diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:24:48 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:24:48 +0000 |
commit | cca66b9ec4e494c1d919bff0f71a820d8afab1fa (patch) | |
tree | 146f39ded1c938019e1ed42d30923c2ac9e86789 /src/3rdparty/libuemf | |
parent | Initial commit. (diff) | |
download | inkscape-cca66b9ec4e494c1d919bff0f71a820d8afab1fa.tar.xz inkscape-cca66b9ec4e494c1d919bff0f71a820d8afab1fa.zip |
Adding upstream version 1.2.2.upstream/1.2.2upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/3rdparty/libuemf')
24 files changed, 46767 insertions, 0 deletions
diff --git a/src/3rdparty/libuemf/CMakeLists.txt b/src/3rdparty/libuemf/CMakeLists.txt new file mode 100644 index 0000000..9e6b689 --- /dev/null +++ b/src/3rdparty/libuemf/CMakeLists.txt @@ -0,0 +1,30 @@ + +set(libuemf_SRC + symbol_convert.c + uemf.c + uemf_endian.c + uemf_print.c + uemf_safe.c + uemf_utf.c + uwmf.c + uwmf_endian.c + uwmf_print.c + upmf.c + upmf_print.c + + # ------- + # Headers + symbol_convert.h + uemf.h + uemf_endian.h + uemf_print.h + uemf_safe.h + uemf_utf.h + uwmf.h + uwmf_endian.h + uwmf_print.h + upmf.h + upmf_print.h +) + +add_inkscape_lib(uemf_LIB "${libuemf_SRC}") diff --git a/src/3rdparty/libuemf/README b/src/3rdparty/libuemf/README new file mode 100644 index 0000000..4d66bbe --- /dev/null +++ b/src/3rdparty/libuemf/README @@ -0,0 +1,567 @@ +Overview: + +libUEMF is a portable C99 implementation for reading/writing Enhanced Metafile (EMF), +Enhanced Metafile Format Plus (PMF), and Windows Metafile (WMF) files. libUEMF +avoids collisions with Microsoft defined functions and values, so portable programs +which use it and have a Windows version, do not require any conditional logic to +separate the native GDI support from the WMF/EMF/PMF support proviced by libUEMF. To +accomplish this libUEMF does not implement GDI calls. Instead, for each WMR/EMR/PMR +record type, and each object type incorporated into such a record, it provides +corresponding *_set, *_print, and *_swap functions. For PMF and WMF there are also +*_get functions, see below. For example, for the U_EMRBITBLT record there are +corresponding functions: U_EMRBITBLT_set, U_EMRBITBLT_print, and U_EMRBITBLT_swap. A +few additional functions are provided for assembling the EMF in memory, debugging, and +converting the EMF file to/from Little Endian representation. (EMF files' internal +data representation is always Little Endian.) + +This code has been tested on 32 bit Ubuntu (LE), 32 bit Mingw, 64 bit CentOS, and 64 +bit Solaris (BE). + +libUEMF is released under the GPL 2 license, read the file 'COPYING' for more information + +Version 0.2.8, released May 13, 2020. + +To report bugs or provide feedback send email to David Mathog, mathog@caltech.edu. + +-------------------------------------------------------------------------------------------- +Sources: + +EMF file Record structure information has been derived from Mingw, Wine, and libEMF +header files, and from Microsoft's EMF Information pdf, release date March 28,2012, +link from here: + + http://msdn2.microsoft.com/en-us/library/cc230514.aspx + +If the direct link fails the document may be found +by searching the web for: "[MS-EMF]: Enhanced Metafile Format". + +WMF file Record structure information is from some of the same sources, as well as: + http://msdn2.microsoft.com/en-us/library/250370.aspx + +If the direct link fails the document may be found +by searching the web for: "[MS-WMF]: Windows Metafile Format" + +EMF+ file Record structure is from many helpful responses from Microsoft documentation support +and from: + http://msdn.microsoft.com/en-us/library/cc230724.aspx + +If the direct link fails the document may be found +by searching the web for: "[MS-EMFPLUS]: Enhanced Metafile Format Plus Extensions" + + +Files: + +README This file. + +CMakeLists.txt Build instructions for cmake on linux. Not tested on OS X or + Windows. + +COPYING GPL V2 license file. + +DOXYFILE Doxygen configuration file, for generating documentation from the source files. + +testbuild.sh Small bash script to build all programs. Modify as needed for target platform. + +testit.sh Small bash script that generates all test files and compares + them with referencess supplied. This script should be edited + to match your test system before it is run! + +uemf.c Contains the *_set functions needed to construct an EMF file. + Also contains auxilliary functions for debugging and constructing + EMF files in memory. + +uemf.h Definitions and structures for EMF records and objects. + Prototypes for *_set and construction functions. + +uemf_print.c Contains the *_print functions needed to print the contents of EMF records and objects. + +uemf_print.h Prototypes for *_print functions. + +uemf_endian.c Contains the *_swap functions needed to rearrange bytes between Big and Little Endian. + U_emf_endian() is the only function here that user could should call. + +uemf_endian.h Prototype for U_emf_endian() and definitions for Endian type of the local machine. + +uemf_safe.c Contains the *_safe functions for EMF records, which verify that all + offsets and counts stay within the declared size of a record. Also checks that + core record sizes are sane. U_emf_record_safe() is the only _safe function which + user code should call directly, and then ONLY after a previous call to + U_emf_record_sizeok(), which is in the endian file. + +uemf_safe.h Prototype for U_emf_record_safe(). + . +upmf.c Contains the *_set and *_get functions needed to construct or read an EMF+ file. + Also contains auxilliary functions for debugging and constructing + EMF+ files in memory. + +upmf.h Definitions and structures for EMF+ records and objects. + Prototypes for *_set, *_get and construction functions. + +upmf_print.c Contains the *_print functions needed to print the contents of EMF+ records and objects. + +upmf_print.h Prototypes for *_print functions. + + +uwmf.c Contains the *_set and *_get functions needed to construct or read a WMF file. + Also contains auxilliary functions for debugging and constructing + WMF files in memory. + +uwmf.h Definitions and structures for WMF records and objects. + Prototypes for *_set, *_get and construction functions. + +uwmf_print.c Contains the *_print functions needed to print the contents of WMF records and objects. + +uwmf_print.h Prototypes for *_print functions. + +uwmf_endian.c Contains the *_swap functions needed to rearrange bytes between Big and Little Endian. + U_wmf_endian() is the only function here that user could should call. + +uwmf_endian.h Prototype for U_wmf_endian() and definitions for Endian type of the local machine. + + +testbed_emf.c Program used for testing emf functions in libUEMF. Run it like: testbed_emf flags. + Run with no argument to see what the bit flag values are. + It creates a test file "test_libuemf.emf" which should be identical to + test_libuemf_ref.emf. (This file cannot be imported from EMF into PowerPoint + because it contains dotted lines. Use "testbed_emf 1" to generate a file without + any dotted lines. ) + +testbed_pmf.c Program used for testing EMF+ functions in libUEMF. Similar to testbed_emf. + +testbed_wmf.c Program used for testing wmf functions in libUEMF. Similar to testbed_emf. + +test_mapmodes_emf.c + Program used for testing emf functions in libUEMF. Generates one test file + in each MAPMODE, MM_TEXT through MM_ANISOTROPIC, optionally with offsets to the + bounds and with particular Viewport origin. (Bounds offset + Viewport Origin + sets the Window origin.) + +test_mapmodes_wmf.c + Program used for testing wmf functions in libUEMF. Similar to test_mapmodes_emf. + +reademf.c Utility that that reads an EMF file and emits its contents in text form. + Also processes EMF+ files. + Run it like: reademf target_file.emf + +readwmf.c Utility that that reads an WMF file and emits its contents in text form. + Run it like: reademf target_file.wmf + +cutemf.c Utility for removing specific records from an EMF file. + Run it like: cutemf '2,10,12...13' src_file.emf dst_file.emf + +pmfdual2single.c Utility for reducing dual-mode EMF+ file to single mode. Removes all + nonessential EMF records. + Run it like: pmfdual2single dual_mode.emf single_mode.emf + + +test_libuemf_ref.emf + Example output from: testbed_emf 0 +test_libuemf_p_ref.emf + Example output from: testbed_pmf 0 +test_libuemf_ref30.emf + Example output from: testbed_emf 4 +test_libuemf_ref.wmf + Example output from: testbed_wmf 0 + +test_libuemf_ref_emf.txt + Example output from: reademf test_libuemf_ref.emf +test_libuemf_ref_wmf.txt + Example output from: readwmf test_libuemf_ref.wmf + +test_mm_<modes>_ref.emf + Example output from: test_mapmodes_emf -vX 2000 -vY 1000 + +emf-inout.cpp,example +emf-inout.h.example +emf-print.cpp.example +emf-print.h.example + Example code from Inkscape, demonstrates how to integrate libUEMF with another program. + +-------------------------------------------------------------------------------------------- +How to Build: + +In Linux/Unix like environments build and install a shared library and the test and tool +programs: + cd <TOP_DIRECTORY> + #modify the destination in CMakeLists.txt if /usr/local is not acceptable + mkdir build + cd build + make + make install + cd .. + ./testit.sh + rm -rf build + + For simple development work use testbuild.sh to make debug versions without the shared + library. + + (Sparc)[ Solaris 8 and 9 are Big Endian, and to work around some minor incompatibilities with more recent systems, + assuming gcc is installed in /opt/csw and PATH is set correctly to use it] + export CLIBS="-lm -L/opt/csw/lib -liconv" + export CFLAGS="-DSOL8 -DWORDS_BIGENDIAN -std=c99 -pedantic -Wall -g" + + (win32) [This uses _wfopen() instead of fopen(), with filename translation from UTF-8 to + UTF-16LE. This will allow file opens to utilize unicode names. If WIN32 is omitted on Windows + file names must be all ASCII. This works in mingw.] Then compile with: + + export CLIBS="-lm -liconv" + export CFLAGS="-DWIN32 -std=c99 -pedantic -Wall -g" + + gcc $CFLAGS -o cutemf cutemf.c uemf.c uemf_endian.c uemf_utf.c $CLIBS + gcc $CFLAGS -o pmfdual2single pmfdual2single.c uemf.c uemf_endian.c uemf_utf.c upmf.c $CLIBS + gcc $CFLAGS -o reademf reademf.c uemf.c uemf_endian.c uemf_safe.c uemf_print.c uemf_utf.c upmf.c upmf_print.c $CLIBS + gcc $CFLAGS -o readwmf readwmf.c uemf.c uemf_endian.c uemf_safe.c uemf_print.c uemf_utf.c upmf.c upmf_print.c uwmf.c uwmf_endian.c uwmf_print.c $CLIBS + gcc $CFLAGS -o testbed_emf testbed_emf.c uemf.c uemf_endian.c uemf_safe.c uemf_print.c uemf_utf.c upmf.c upmf_print.c $CLIBS + gcc $CFLAGS -o testbed_pmf testbed_pmf.c uemf.c uemf_endian.c uemf_safe.c uemf_utf.c upmf.c $CLIBS + gcc $CFLAGS -o testbed_wmf testbed_wmf.c uemf.c uemf_endian.c uemf_safe.c uemf_print.c uemf_utf.c upmf.c upmf_print.c uwmf.c uwmf_endian.c $CLIBS + gcc $CFLAGS -o test_mapmodes_emf test_mapmodes_emf.c uemf.c uemf_endian.c uemf_safe.c uemf_print.c uemf_utf.c upmf.c upmf_print.c $CLIBS + +Extra debugging on linux may be enabled in testbed for use under Valgrind. To build that way do instead: + + 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 + + +and then compile as above for linux. + + +Dependencies: + libiconv (if not built into your compiler) + libpng (in the Inkscape examples) + +-------------------------------------------------------------------------------------------- +Testing + +All modules must also compile without warning under the more restrictive: + + ls -1 *.c \ + | extract -fmt 'gcc -Werror=format-security -Wall -Wformat -Wformat-security -W -Wno-pointer-sign -O2 -c -o deleteme.o [1,]' \ + | execinput + +-------------------------------------------------------------------------------------------- +Using libUEMF: + +To write an EMF file the code first runs two initialization functions: emf_start() and htable_create(). +Then a U_EMRHEADER record is created. This and all subsequent records are appended to the EMF file in +memory with emf_append(). Whichever other EMR records are desired are also added. The last EMR record +added must be the single instance of U_EMREOF. Then the code calls emf_finish(), emf_free(), and +htable_free(). Conversion of byte order on Big Endian machines to Little Endian is carried out +automatically in emf_finish(), if it is required. + +To input an EMF file it is is opened and the data read into a buffer in memory with emf_readdata(). On a +Big Endian machine this will also swap machine dependent byte orders as needed. At that point end user code +generally has to do something with the data in each record. The simplest case is to just print it, as shown +in reademf.c. More typically it must map the operations into its own graphics model, as shown in the +emf32*.*.example files from Inkscape. Basically the processing program needs to enter a loop, processing +one record at a time, pulling the record size and type from the first two uint32_t values present in each +record. It then enters a switch statement with one case for each EMR record type. Each case: statement +will generally define a pointer to that type of data object. Accessing the data from that pointer is +illustrated in the code for the corresponding *_print function. + +While libUEMF implements _print and _swap functions for all supported EMR records, end user code would +never call any of these directly. Instead it should either pass a single EMR record +to U_emf_onerec_print() (see reademf.c) or the entire completed EMF file in memory buffer to U_emf_endian() +(see testbed.c). + +WMF support is similar, except the functions are wmf_start(), wmf_readdata(), and so forth. It is a good +idea to separate end user WMF and EMF generating code into different modules, in order to avoid accidentally +writing EMR records to a WMF file and vice versa. WHile EMF objects are aligned in memory and so may be +accessed using the supplied structs, the ones for WMF files are not usually aligned and so must be accessed +using the supplied *_get functions. (The difference may not be evident on an x86 platform, but on RISC directly +trying to access objects in memory will result in access violations.) + +Things to be aware of in EMF files: + +The usual idea when employing a graphics file type like EMF is to copy a description of the objects in a +drawing from one program to another. Many of the record types in an EMF file can be thought of as objects, +they are lines or shapes or bitmaps or text. However, Microsoft's GDI implements binary and ternary raster +operations (see the descriptions in uemf.h) and most of these operations are not object like, instead they +combine things on the drawing surface. (There is in each case a copy operation which is object like.) +Consequently, EMF files which use these other raster operations are not particularly easy to import as +graphic objects. For instance, when PowerPoint rotates an image and saves it in an EMF the result is not +a single rotated image object. Instead there is an image containing the rotated image, which is followed by +masking operations to make the regions outside of the image transparent. There appears to be no standard +for when and where these subsequent operations will be applied. That is, there is no equivalent of +"begin path" and "end path" to delineate the start and end of such a compound operation. So a program +reading such a file has no easy way of figuring out which previous object is being modified by a subsequent +raster operation. The testbed program provided in this package generates a region which applies all +binary raster operations in vertical slices to two images. The expected result appears in Windows "Preview", +but if that region is imported into PowerPoint and converted to objects within that program the result looks +nothing like what Preview shows. + +Support for U_EMREXTTEXTOUTW is much more common than for U_EMRSMALLTEXT. The latter is easier to use, +since it does not require a Dx array for each text string, but the objects will not import into PowerPoint, +for instance. + +There are two types of dotted/dashed lines. The first uses a set of predefined flags to set the pattern +and the latter is end user user defined. Both are restricted to lines of width 1. These built in types are +problematic as key applications cannot handle them properly. PowerPoint cannot convert either type to its +internal object format. The first form loses the pattern and comes through as solid lines. The second type +is toxic - even a single dotted line of the second type will prevent the entire EMF from being converted. +The safest choice is to avoid these patterned line styles entirely. Convert all dots and dashes to separate +line draws before writing those into the EMF file. libUEMF has no problem reading these records, so code +should accept them for input. + +As with most graphics file formats there is no single object representation of a complex text string (varying +font size, super/sub script, bold, italic,.etc.). Such text must be decomposed into multiple text strings, +each with its own formatting. It is unlikely that a subsequent program reading these records from the EMF +will be able to reassemble them back into a single complex text string. + +If a font used in an EMF file is not present on both the sending and receiving systems text will not look the +same on both. Font substitution is usually silent in most programs, so it may not be evident why the text looks +a little odd. However, if text is simple, that is, consists of just one line of text without size, color, +or other changes, then it will look approximately correct after font substitution. + +Things to be aware of in WMF files: + +WMF graphics are quite limited when compared to EMF graphics. When reading a WMF file it is essential that +end user code always create a specified object, even if that object is just a placeholder with no real +function. If any "create" operation presented by the WMF file is not handled then the object indices used +further along in the WMF file will be off, with very bad results! WMF "regions" are not supported by libUEMF, +however, if an operation creates regions, this type of placeholder must still be created. + +In theory WMF supports mapmodes other than Anisotropic. However, since many programs do not handle +these other modes it is strongly suggested that any WMF files generated use Anisotropic. For this +reason there is no test_mapmodes_wmf program - windows XP preview did not show anything when WMF +files in the other modes were produced. With no positive control there was no way to verify that they +were valid. + +Things to be aware of in EMF+ files: + +EMF+ files are usually stored in files with an ".emf" file extension. In this package EMF+ programs, +functions, and definitions use PMF or PMR to distinguish them from the EMF and WMF material. ("EMF+" +is not an allowed variable or function name in C.) Dual mode EMF+ files contain both EMF and +EMF+ records. HOWEVER, those generated by PowerPoint are defective in that they drop all text +information from the drawing in the EMF+ representation. There is no simple way to line up the +EMF and EMF+ records in their representations to determine which ones correspond to which drawing +object. So it is generally not possible to see which elements are represented in both +representations, or which are missing in one representation. The example file generated by this library +has only EMF+ records plus the few EMF records needed to wrap them. + +Text in EMF+ is placed not from the baseline, as in EMF, but from the upper left corner of the Em square. +Use the utility function U_PMR_drawstring() to draw text onto a baseline. Font +substitutions result in badly placed text because even fonts that look similar on the screen may have +different font metrics. Specifically, font substitutions look worse in EMF+ files than they do +in EMF files. There is no way to embed fonts, or their font information in the EMF+ file. +Consequently the text representation within an EMF+ file is not very portable between systems - it will +only render correctly if the second system has all of the fonts used in the document. The testbed_pmf.c +program contains some metrics for common fonts which may be used with U_PMR_drawstring() +to accurately place text. + + + +-------------------------------------------------------------------------------------------- +History + + (Note, version numbers in files represent the libUEMF release where it was last modified, so not + all files will show the same version numbers in each release.) + +0.2.8 2020-05-13 + Fixed warnings from newer compilers. + Fixed truncation of one string in testbed outputs files, + from 32 to 31 bytes (seen on CentOS 8 with gcc 8.3.1 + but not CentOS 7 with gcc 4.8.5) +0.2.7 2019-10-10 + Added CMakeLists.txt for linux. + Added cmake instructions in README. + Fixed typo in README build instructions. + Error checking added to testit.sh. + Increased max records in cutemf from 10K to 10M. +0.2.6 2019-03-21 + Fixed typo in upmf.c discovered by David Binderman. +0.2.5 2017-01-03 + Fixed a misplaced paren in uemf.h (thanks to Tavmjong Bah for noticing it) + Added more U_SIZE_* definitions in uemf.h for "cores" of record types with final + variable length arrays, such as U_SIZE_EMRNAMEDESCAPE + Removed redundant U_SIZE_BITMAPINFOHEADER definition from uwmf.h +0.2.4 2016-01-26 + Record EXTSELECTCLIPRGN is supposed to be valid when the RgnDataSize is 0 if the RegionMode + is "COPY". Modified safe and print routines so that they would handle this situation. + U_PMR_DrawDriverstring seen for the first time and it crashed reademf. Reason, there was a spurious + "Tension" value in the structure, which offset values in the record. +0.2.3 2015-05-28 + Fixed an assortment of warnings and a couple of bugs flagged by clang static analysis. +0.2.2 2015-04-28 + Added lu_crc32 sums to record information in print statements. Affects only reademf and readwmf. + The point of this exercise is to enable the detection of differences in binary fields + which are not expanded by the print functions. This (re)uses code from Alexander Peslyak. + lu_ in name because crc32 conflicts with other libraries, like png. + Minor changes to some wmf function parameter types. + Minor changes to upmf.c so that it compiles cleanly with clang. + Restrict IS_MEM_UNSAFE 2nd parameter to be int or larger and test for negative values. + Updated the examples from Inkscape. + +0.2.1 2015-04-23 + Bug in safety check on EMREXTCREATEFONTINDIRECTW because it had alternative "standard" record sizes. + Changed warnings on unimplemented EMF record types encounterd in swap or safe from stdout to stderr. + Added memory checking for WMF polyline and polygon records, for the variable part and some others. + Note: U_WMRCREATEREGION_get does not check that the variable part stays within the record. Current + implementation seems to be broken since it does not show up in XP preview. +0.2.0 2015-03-20 + Added UEMF _safe functions to better handle corrupt records, where variable sizes fields might + have been specified to read past the end of memory. These are records with offsets, arrays + with counts, and bitmaps. Also any record which specifies a size smaller than the minimum + for that record type. + Added similar code for EMF+. + These changed the API so the minor version number was bumped by 1. + +0.1.18 2015-01-15 + Pierre-Francois Carpentier sent some EMF examples which used U_EMR_EXTSELECTCLIPRGN, which had + not previously been encountered and showed that the handling of regions was broken. + Added tests for U_EMRFILLRGN, U_EMRFRAMERGN, U_EMRFRAMERGN, U_EMREXTSELECTCLIPRGN to testbed_emf. + +0.1.18 2014-04-28 + Fixed typo in testbed_wmf.c. "include,include" in one place should have been + "exclude,exclude". + +0.1.17 2014-04-25 + Added text clipping tests to testbed_emf.c, testbed_wmf.c, and testbed_pmf.c. + Added option to omit clipping tests in testbed's. + +0.1.16 2014-04-14 + Fixed bug in U_WMRRESTOREDC_set. + Added clipping tests to testbed_wmf.c. + +0.1.15 2014-04-04 + Changed record flags for U_EMRSELECTCLIPPATH record, it consumes a path but does not ALTER (which + forced a premature draw.) + Added U_EMROFFSETCLIPRGN test to testbed_emf.c. + Changed location on dist drawing where clipping appears. + +0.1.14 2014-03-27 + Fixed bug, in U_PMF_RECTN_set() in upmf.c. Never tested. + Fixed a few potential bugs in upmf.c if a null pointer was passed for + certain function arguments. (Previously unhandled cases.) + Fixed bug, operations setting variables that are never read along those + execution paths: upmf_print.c, uemf.c, uwmf.c, uemf_endian.cm upmf.c. + Fixed potential (but very unlikely) memory leaks in upmf.c and uemf_utf.c. + Added test of U_PMF_RECTN_set to testbed_pmf.c. + Changed U_wmr_names() and U_wmr_escnames() to const char* (from char*). + Changed method for suppressing unused parameter warnings. + + +0.1.13 2014-03-21 + Fixed bug, cutemf was messing up the object count (pens, brushes, etc.). + Added cutemf can now take ranges of lines. + Added testbed_emf generates clipping records for rect and path (but not region). + +0.1.12 2014-02-14 + Documentation change, U_WMRCREATEPATTERNBRUSH is obsolete. + Changed wmf_finish() so that it accurately reflects the largest number of objects used, + previously it showed the number of appends, which was much larger. + +0.1.11 2014-01-29 + Fixed bug in uwmf.c (wrong minimum record size on U_WMRTEXTOUT) + Fixed bug in uwmf.c (U_WMRCREATEPATTERNBRUSH not right) + Fixed bug in uwmf_print.c (U_WMRTEXTOUT_print, x,y were reversed) + Added error handling to uemf_utf.c for cases where src is a null pointer. + Added a test of createpatternbrush to testlib_wmf + +0.1.10 2014-01-14 + Slight changes in documentation for uemf.h. + Fixed typo in uemf_endian.c. + Fixed a tiny bug in uemf.c (if memory allocation failed a struct would have + been deleted before the struct itself. + +0.1.9 2013-12-02 + Added U_PMF_DASHEDLINEDATA_set3 (dot/dash pattern from bits in a uint32_t). + Finally was able to make linear gradient gradientfill records work. Updated + testbed_emf.c to include that. + +0.1.8 2013-11-28 + Fixed a bug in U_PMF_REGIONNODEPATH_print(), returned size was 4 too small. + Changed formatting of U_PMF_REGIONNODECHILDNODES_print() output to improve readability + of nested region structures in reademf. + +0.1.7 2013-11-20 + Added EMF+ support. + Converted U_RGA and similar from defines to functions, because the method being used + in the define (from C99) was not exactly compatible with C++ compilation. + Fixed error in test_mapmodes_emf.c where truncation float to integer was used where round + have been, resulting in an off by 1 error on some platforms. + Eliminated PU_W* pointers. + Cleaned up Doxygen comments. + +0.1.6. 2013-04-18 + Added tests which vary background mode, background color, and text color. + Slight modification to testit.sh. + Updated example files. + +0.1.5. 2013-02-13 + Added missing parameter for WMF RESTOREDC_set/get. + Replaced all sizeof() in uwmf.c that referred to UWMF structures with their + U_SIZE_* equivalents. + Added DIB related WMF _get functions. (Which were missing). These are U_BITMAPCOREHEADER_get, + U_BITMAPINFOHEADER_get, wget_dib_params + Added const where appropriate to wmf _get functions. + Added comprehensive cap,join,miter tests to testbeds. + Fixed bug in gradient4_swap(). + Fixed bug in emr_arc_points_common(), used vector where unit vectors were + needed, sometimes flipped direction for arcs/chords. + Fixed bug in U_WMFTEXTOUT_get(). + Changed all dst->Dst and src->Src as call variables in WMF code. + Denigrated htable_*() for emf, these become emf_htable_*(), to match naming convention + used for wmf_table_*(). +0.1.4 2013-02-04 + Added code to handle DIB formats that use clrUsed=0 to mean "maximum number of color entries", + this showed up in several places, including uemf.c and uemf_print.c. + Added some labels to test drawings, slightly rearranged image section, added + PNG and JPG image tests and clrUsed=0 images. + Modified uemf_endian.c to suppress some compiler warnings. + Changed get_DIB_params to return the Compression enumeration. + Fixed a typo in uwmf_print.c. +0.1.3 2013-01-29 Add modes to EMF test programs that changes worldtransform, so + that the resulting test files will exercise rotation transforms. + Added flags indication for testbed programs. + Added test for ROUNDRECT records. Swapped argument orders for those _get/_set operations. +0.1.2 2013-01-25 Fixed bug revealed by newer gcc on Solaris, assignment of aligned 32 bit to unaligned + 16 bit segfaulted. +0.1.1 2013-01-24 Fixed a few compiler warnings under g++, mostly having to do + with signed unsigned comparisons. Eliminated + an unused variable from wmf_finish and two stray lines from U_WMRHEADER_set. + Cleaned up doxygen comments. +0.1.0 2013-01-09 Added WMF functions. + Simplified print functions. Changed output format of reademf slightly, + from U_EMRXXX to U_EMR_XXX - easier to read the new way. +0.0.11 2012-12-04 Moved UTF and related functions out of uemf.c uemf.h and into uemf_utf.c uemf_utf.h. +0.0.10 2012-11-28 Discovered that not enough space was being allocated for some UTF conversions. To be + safe need 4 bytes per glyph + 1 for UTF-8. +0.0.9 2012-09-26 Some "uninitialized variable warnings" for certain versions of + gcc. These were, as far as I could tell, all spurious, but to quiet them + the variables in question were all initialized to 0. + Fixed header related print/swap functions - depending on what type of header there + could be an access violation. + Fixed U_Utf16leToUtf8, could leak memory if the conversion failed. + Fixed sections which were not testing for all types of EMF headers. + Added RGBA_to_RGBA() so that extractions of subsets of bitmaps (offset, different size) + can be handled. + Added cutemf. Utility to remove records from an EMF file. + Added test_mapmodes. Program to generate test files in each MAPMODE. + Added test_mm_(mode)_ref.emf files. These are reference for: + test_mapmodes -vX 2000 -vY 1000 + +0.0.8 2012-09-10 Fixed bug in htable_insert, failed to celear newly added table + slots. Fixed test for EMR_GRADIENTFILL triangle mode (rectangle still produces toxic EMF files.) + Fixed bug in gradientfill_swap on Solaris. + +0.0.7 2012-08-30 Added/fixed tests for hatched, DIB, and mono strokes. + Corrected error in U_EMREXTCREATEPEN_set. + +0.0.6 2012-08-21 Added/fixed tests for hatched, DIB, and mono fills. + +0.0.5 2012-08-08 Minor changes to uemf.c to suppress compiler warnings. Fixed + one bug in SET_CB_FROM_PXBMI macro (which was not triggered in testbed + because all images were the same size). + +0.0.4 2012-07-25 More tests in testbed.c. Found and fixed bugs in + U_POLYPOLYLINE and U_POLYPOLYGON related code. + +0.0.3 2012-07-24 Warnings related to printing size_t on 64 bit Linux. Correct + fix is to use "zd", but gcc -std=c99 does not support that on Solaris 9, + the only available big endian system. So use cast or the size_t to (int) + and stick with %d format specifier. This should be OK as the sizes involved + should not be all that large. + + Bug in core9 affecting U_EMRARC_swap(), and related, on Big Endian. + +0.0.2 2012-07-12 first release + diff --git a/src/3rdparty/libuemf/symbol_convert.c b/src/3rdparty/libuemf/symbol_convert.c new file mode 100644 index 0000000..6a919fc --- /dev/null +++ b/src/3rdparty/libuemf/symbol_convert.c @@ -0,0 +1,1008 @@ +/** @file + * @brief Windows-only Enhanced Metafile input and output. + */ +/* Authors: + * David mathog <mathog@caltech.edu> + * + * Copyright (C) 2012 Authors + * + * Released under GNU GPL, read the file 'COPYING' for more information + * + * References: + * see unicode-convert.h + * + * v1.4 08/21/2012 Changed this so that the incoming routines use uint32_t and the outgoing use uint16_t. This gets rid + * of wchar_t, which was different sizes on windows/linux, and required lots of ifdef's elsewhere in the code. + * v1.3 04/03/2012 Bullets were a problem. Symbol bullet -> Times New Roman Bullet looks OK, but + * it looked bad going the other way. Changed mapping Symbol bullet to 2219 (Bullet operator, math + * symbol.) That way Symbol bullet can map in and out, while other font bullet an remain in that + * font's bullet glyph. + * v1.2 03/26/2012 Introduced bug into SingleUnicodeToNon repaired. + * v1.1 03/25/2012 Changed ampersand mapping on Wingdings (to avoid normal Ampersand mapping + * to Wingdings ampersand when not intended. Fixed access bugs for when no conversion is + * mapped in UnicodeToNon and SingleUnicodeToNon + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <string.h> +#include "symbol_convert.h" + + +static bool hold_symb=0; // if any of these change, (re)generate the map table +static bool hold_wing=0; +static bool hold_zdng=0; +static bool hold_pua=0; +static unsigned char *from_unicode=NULL; +static unsigned char *to_font=NULL; + +/* The following tables were created from the files + adobe-dingbats.enc.gz + adobe-symbol.enc.gz + adobe-standard.enc.gz + + which came as part of the X11-font-encodings rpm on Mandriva 2010. + The original source for the data must have been Adobe. + Some also from: + ftp://ftp.unicode.org/Public/MAPPINGS/VENDORS/ADOBE/symbol.txt + http://www.csn.ul.ie/~caolan/wingdings/proposal/ + www.renderx.com/Tests/zapf-dingbats.pdf + + The intent is as follows: + + on conversion from ASCII/extended -> Unicode use the appropriate table for + the font and change font + code (symbol, zapf dingbats, wingdings). + Going the other way, set up two transfer tables, + the first is unicode -> 0-FF values, and the seond is unicode -> cvt_to_font. + These tables are filled dingbats, wingdings, then symbols, so with the rightmost one getting + precedence if both contain the symbol. + + Whereever possible do NOT map two input characters to the same output character, use a slightly + off character if it is somewhat close and disambiguates. + +v 1.0.0 14-MAR-2012, David Mathog + +*/ + +static unsigned int wingdings_convert[256]={ + 0xFFFD, // 0x00 no replacement + 0xFFFD, // 0x01 no replacement + 0xFFFD, // 0x02 no replacement + 0xFFFD, // 0x03 no replacement + 0xFFFD, // 0x04 no replacement + 0xFFFD, // 0x05 no replacement + 0xFFFD, // 0x06 no replacement + 0xFFFD, // 0x07 no replacement + 0xFFFD, // 0x08 no replacement + 0xFFFD, // 0x09 no replacement + 0xFFFD, // 0x0A no replacement + 0xFFFD, // 0x0B no replacement + 0xFFFD, // 0x0C no replacement + 0xFFFD, // 0x0D no replacement + 0xFFFD, // 0x0E no replacement + 0xFFFD, // 0x0F no replacement + 0xFFFD, // 0x10 no replacement + 0xFFFD, // 0x11 no replacement + 0xFFFD, // 0x12 no replacement + 0xFFFD, // 0x13 no replacement + 0xFFFD, // 0x14 no replacement + 0xFFFD, // 0x15 no replacement + 0xFFFD, // 0x16 no replacement + 0xFFFD, // 0x17 no replacement + 0xFFFD, // 0x18 no replacement + 0xFFFD, // 0x19 no replacement + 0xFFFD, // 0x1A no replacement + 0xFFFD, // 0x1B no replacement + 0xFFFD, // 0x1C no replacement + 0xFFFD, // 0x1D no replacement + 0xFFFD, // 0x1E no replacement + 0xFFFD, // 0x1F no replacement + 0x0020, // 0x20 SPACE + 0x270E, // 0x21 LOWER RIGHT PENCIL (close, but not exact) + 0x2702, // 0x22 BLACK SCISSORS + 0x2701, // 0x23 UPPER BLADE SCISSORS + 0xFFFD, // 0x24 no replacement + 0xFFFD, // 0x25 no replacement + 0xFFFD, // 0x26 no replacement + 0xFFFD, // 0x27 no replacement + 0x260E, // 0x28 BLACK TELEPHONE + 0x2706, // 0x29 TELEPHONE LOCATION SIGN (close, but not exact) + 0x2709, // 0x2A ENVELOPE + 0x2709, // 0x2B ENVELOPE (close, but not exact) + 0xFFFD, // 0x2C no replacement + 0xFFFD, // 0x2D no replacement + 0xFFFD, // 0x2E no replacement + 0xFFFD, // 0x2F no replacement + 0xFFFD, // 0x30 no replacement + 0xFFFD, // 0x31 no replacement + 0xFFFD, // 0x32 no replacement + 0xFFFD, // 0x33 no replacement + 0xFFFD, // 0x34 no replacement + 0xFFFD, // 0x35 no replacement + 0x231B, // 0x36 HOURGLASS + 0x2328, // 0x37 KEYBOARD + 0xFFFD, // 0x38 no replacement + 0xFFFD, // 0x39 no replacement + 0xFFFD, // 0x3A no replacement + 0xFFFD, // 0x3B no replacement + 0xFFFD, // 0x3C no replacement + 0xFFFD, // 0x3D no replacement + 0x2707, // 0x3E TAPE DRIVE + 0x270D, // 0x3F WRITING HAND + 0x270D, // 0x40 WRITING HAND (close, but not exact) + 0x270C, // 0x41 VICTORY HAND + 0xFFFD, // 0x42 3 FINGER UP HAND (no replacement) + 0xFFFD, // 0x43 THUMBS UP HAND (no replacement) + 0xFFFD, // 0x44 THUMBS DOWN HAND (no replacement) + 0x261C, // 0x45 WHITE LEFT POINTING INDEX + 0x261E, // 0x46 WHITE RIGHT POINTING INDEX + 0x261D, // 0x47 WHITE UP POINTING INDEX + 0x261F, // 0x48 WHITE DOWN POINTING INDEX + 0xFFFD, // 0x49 OPEN HAND (no replacement) + 0x263A, // 0x4A WHITE SMILING FACE + 0x263A, // 0x4B WHITE SMILING FACE (close, but not exact) + 0x2639, // 0x4C WHITE FROWNING FACE + 0xFFFD, // 0x4D BOMB (no replacement. 1F4A3) + 0x2620, // 0x4E SKULL AND CROSSBONES + 0x2690, // 0x4F WHITE FLAG (not exact) + 0x2691, // 0x50 WHITE PENANT (use BLACK FLAG) + 0x2708, // 0x51 AIRPLANE + 0x263C, // 0x52 WHITE SUN WITH RAYS (close, but not exact) + 0x2602, // 0x53 RAINDROP (use UMBRELLA) + 0x2744, // 0x54 SNOWFLAKE + 0x271D, // 0x55 WHITE LATIN CROSS (use BLACK CROSS) + 0x271E, // 0x56 SHADOWED WHITE LATIN CROSS + 0x271F, // 0x57 CELTIC CROSS (use OUTLINED LATIN CROSS) + 0x2720, // 0x58 MALTESE CROSS + 0x2721, // 0x59 STAR OF DAVID + 0x262A, // 0x5A STAR AND CRESCENT + 0x262F, // 0x5B YIN YANG + 0x0950, // 0x5C DEVANGARI OM CORRECT|CLOSE: Perhaps PROPOSE SACRED OM ? + 0x2638, // 0x5D WHEEL OF DHARMA + 0x2648, // 0x5E ARIES + 0x2649, // 0x5F TAURUS + 0x264A, // 0x60 GEMINI + 0x264B, // 0x61 CANCER + 0x264C, // 0x62 LEO + 0x264D, // 0x63 VIRGO + 0x264E, // 0x64 LIBRA + 0x264F, // 0x65 SCORPIUS + 0x2650, // 0x66 SAGITTARIUS + 0x2651, // 0x67 CAPRICORN + 0x2652, // 0x68 AQUARIUS + 0x2653, // 0x69 PISCES + 0xFFFD, // 0x6A LOWER CASE AMPERSAND)?) (no replacement) + 0xFF06, // 0x6B AMPERSAND (use FULL WIDTH AMPERSAND, close, but not exact. Do NOT use 0026, or it maps normal Ampersands to Wingdings Ampersand) + 0x25CF, // 0x6C BLACK CIRCLE + 0x274D, // 0x6D SHADOWED WHITE CIRCLE (close, but not exact) + 0x25A0, // 0x6E BLACK SQUARE + 0x25A3, // 0x6F WHITE SQUARE IN BLACK RECTANGLE (use BLACK SQUSRE in WHITE SQUARE) + 0x25A1, // 0x70 WHITE SQUARE (close, but not exact) + 0x2751, // 0x71 LOWER RIGHT SHADOWED WHITE SQUARE + 0x2752, // 0x72 UPPER RIGHT SHADOWED WHITE SQUARE + 0x25CA, // 0x73 LOZENGE (close, but not exact) + 0x25CA, // 0x74 LOZENGE (close, but not exact) + 0x25C6, // 0x75 BLACK DIAMOND + 0x2756, // 0x76 BLACK DIAMOND MINUS WHITE X + 0x25C6, // 0x77 BLACK DIAMOND (close, but not exact) + 0x2327, // 0x78 X IN A RECTANGLE BOX + 0x2353, // 0x79 APL FUNCTIONAL SYMBOL QUAD UP CARET(close, but not exact) + 0x2318, // 0x7A PLACE OF INTEREST SIGN + 0x2740, // 0x7B WHITE FLORETTE (close, but not exact) + 0x273F, // 0x7C BLACK FLORETTE (close, but not exact) + 0x275D, // 0x7D HEAVY DOUBLE TURNED COMMA QUOTATION MARK ORNAMENT + 0x275E, // 0x7E HEAVY DOUBLE COMMA QUOTATION MARK ORNAMENT + 0xFFFD, // 0x7F unused + 0x24EA, // 0x80 CIRCLED DIGIT ZERO + 0x2460, // 0x81 CIRCLED DIGIT ONE + 0x2461, // 0x82 CIRCLED DIGIT TWO + 0x2462, // 0x83 CIRCLED DIGIT THREE + 0x2463, // 0x84 CIRCLED DIGIT FOUR + 0x2464, // 0x85 CIRCLED DIGIT FIVE + 0x2465, // 0x86 CIRCLED DIGIT SIX + 0x2466, // 0x87 CIRCLED DIGIT SEVEN + 0x2467, // 0x88 CIRCLED DIGIT EIGHT + 0x2468, // 0x89 CIRCLED DIGIT NINE + 0x2469, // 0x8A CIRCLED NUMBER TEN + 0xFFFD, // 0x8B no replacement + 0x2776, // 0x8C DINGBAT NEGATIVE CIRCLED DIGIT ONE + 0x2777, // 0x8D DINGBAT NEGATIVE CIRCLED DIGIT TWO + 0x2778, // 0x8E DINGBAT NEGATIVE CIRCLED DIGIT THREE + 0x2779, // 0x8F DINGBAT NEGATIVE CIRCLED DIGIT FOUR + 0x277A, // 0x90 DINGBAT NEGATIVE CIRCLED DIGIT FIVE + 0x277B, // 0x91 DINGBAT NEGATIVE CIRCLED DIGIT SIX + 0x277C, // 0x92 DINGBAT NEGATIVE CIRCLED DIGIT SEVEN + 0x277D, // 0x93 DINGBAT NEGATIVE CIRCLED DIGIT EIGHT + 0x277E, // 0x94 DINGBAT NEGATIVE CIRCLED DIGIT NINE + 0x277F, // 0x95 DINGBAT NEGATIVE CIRCLED NUMBER TEN + 0xFFFD, // 0x96 ROTATED FLORAL HEART BULLET (no good replacement) + 0xFFFD, // 0x97 REVERSED ROTATED FLORAL HEART BULLET (no good replacement) + 0xFFFD, // 0x98 REVERSED ROTATED FLORAL HEART BULLET (no good replacement) + 0xFFFD, // 0x99 ROTATED FLORAL HEART BULLET (no good replacement) + 0xFFFD, // 0x9A ROTATED FLORAL HEART BULLET (no good replacement) + 0xFFFD, // 0x9B REVERSED ROTATED FLORAL HEART BULLET (no good replacement) + 0xFFFD, // 0x9C REVERSED ROTATED FLORAL HEART BULLET (no good replacement) + 0xFFFD, // 0x9D ROTATED FLORAL HEART BULLET (no good replacement) + 0x2219, // 0x9E BULLET (use BULLET operator, so normal font BULLET will not convert to Symbol BULLET) + 0x25CF, // 0x9F BLACK CIRCLE (close, but not exact) + 0x25AA, // 0xA0 BLACK VERY SMALL SQUARE + 0x26AA, // 0xA1 WHITE CIRCLE (use MEDIUM WHITE CIRCLE) + 0x25CB, // 0xA2 HEAVY WHITE CIRCLE (use WHITE CIRCLE) + 0x25CD, // 0xA3 HEAVIEST CIRCLE (use CIRCLE WITH VERTICAL FILL) + 0x25C9, // 0xA4 CIRCLE WITH A CENTRAL DOT (close, dot much bigger) + 0x25CE, // 0xA5 BULLSEYE + 0x274D, // 0xA6 SHADOWED WHITE CIRCLE (close, but not exact) + 0xFFED, // 0xA7 BLACK SMALL SQUARE + 0x2610, // 0xA8 WHITE SQUARE (close, but not exact, different fro 25A1) + 0xFFFD, // 0xA9 no replacement + 0x2726, // 0xAA BLACK FOUR POINTED STAR MAYBE + 0x2605, // 0xAB BLACK STAR + 0x2736, // 0xAC SIX POINTED BLACK STAR + 0x2737, // 0xAD EIGHT POINTED RECTILINEAR BLACK STAR + 0x2738, // 0xAE TWELVE POINTED BLACK STAR + 0x2735, // 0xAF EIGHT POINTED PINWHEEL STAR + 0xFFFD, // 0xB0 no replacement + 0xFFFD, // 0xB1 no replacement + 0x2727, // 0xB2 WHITE FOUR POINTED STAR + 0x2726, // 0xB3 ROTATED WHITE FOUR POINTED STAR (use BLACK FOUR POINTED STAR) + 0xFFFD, // 0xB4 REPLACEMENT CHARACTER (close, but not exact) + 0x272A, // 0xB5 CIRCLED WHITE STAR + 0x2730, // 0xB6 SHADOWED WHITE STAR + 0xFFFD, // 0xB7 ANALOG CLOCK 1 (no replacement) + 0xFFFD, // 0xB8 ANALOG CLOCK 2 (no replacement) + 0xFFFD, // 0xB9 ANALOG CLOCK 3 (no replacement) + 0xFFFD, // 0xBA ANALOG CLOCK 4 (no replacement) + 0xFFFD, // 0xBB ANALOG CLOCK 5 (no replacement) + 0xFFFD, // 0xBC ANALOG CLOCK 6 (no replacement) + 0xFFFD, // 0xBD ANALOG CLOCK 7 (no replacement) + 0xFFFD, // 0xBE ANALOG CLOCK 8 (no replacement) + 0xFFFD, // 0xBF ANALOG CLOCK 9 (no replacement) + 0xFFFD, // 0xC0 ANALOG CLOCK 10 (no replacement) + 0xFFFD, // 0xC1 ANALOG CLOCK 11 (no replacement) + 0xFFFD, // 0xC2 ANALOG CLOCK 12 (no replacement) + 0x21B2, // 0xC3 TURN ARROW DOWN AND LEFT (Meaning close, shape differs) + 0x21B3, // 0xC4 TURN ARROW DOWN AND RIGHT (Meaning close, shape differs) + 0x21B0, // 0xC5 TURN ARROW UP AND LEFT (Meaning close, shape differs) + 0x21B1, // 0xC6 TURN ARROW UP AND RIGHT (Meaning close, shape differs) + 0x2B11, // 0xC7 TURN ARROW LEFT AND UP (Meaning close, shape differs) + 0x2B0F, // 0xC8 TURN ARROW RIGHT AND UP (Meaning close, shape differs) + 0x2B10, // 0xC9 TURN ARROW LEFT AND DOWN (Meaning close, shape differs) + 0x2B0E, // 0xCA TURN ARROW RIGHT AND DOWN (Meaning close, shape differs) + 0xFFFD, // 0xCB no replacement + 0xFFFD, // 0xCC no replacement + 0xFFFD, // 0xCD no replacement + 0xFFFD, // 0xCE no replacement + 0xFFFD, // 0xCF no replacement + 0xFFFD, // 0xD0 no replacement + 0xFFFD, // 0xD1 no replacement + 0xFFFD, // 0xD2 no replacement + 0xFFFD, // 0xD3 no replacement + 0xFFFD, // 0xD4 no replacement + 0x232B, // 0xD5 ERASE TO THE LEFT + 0x2326, // 0xD6 ERASE TO THE RIGHT + 0x25C0, // 0xD7 THREE-D LIGHTED LEFT ARROWHEAD (Use BLACK LEFT TRIANGLE) + 0x25B6, // 0xD8 THREE-D LIGHTED RIGHT ARROWHEAD (Use BLACK RIGHT TRIANGLE, 27A2 is exact but has no other directions) + 0x25B2, // 0xD9 THREE-D LIGHTED UP ARROWHEAD (Use BLACK UP TRIANGLE) + 0x25BC, // 0xDA THREE-D LIGHTED DOWN ARROWHEAD (Use BLACK DOWN TRIANGLE) + 0xFFFD, // 0xDB no replacement + 0x27B2, // 0xDC CIRCLED HEAVY WHITE RIGHTWARDS ARROW + 0xFFFD, // 0xDD no replacement + 0xFFFD, // 0xDE no replacement + 0x2190, // 0xDF LEFT ARROW + 0x2192, // 0xE0 RIGHT ARROW + 0x2191, // 0xE1 UP ARROW + 0x2193, // 0xE2 DOWN ARROW + 0x2196, // 0xE3 UPPER LEFT ARROW + 0x2197, // 0xE4 UPPER RIGHT ARROW + 0x2199, // 0xE5 LOWER LEFT ARROW + 0x2198, // 0xE6 LOWER RIGHT ARROW + 0x2B05, // 0xE7 HEAVY LEFT BLACK ARROW (same as regular BLACK ARROW) + 0x2B08, // 0xE8 HEAVY RIGHT BLACK ARROW (same as regular BLACK ARROW) + 0x2B06, // 0xE9 HEAVY UP BLACK ARROW (no equiv BLACK ARROW) + 0x2B07, // 0xEA HEAVY DOWN BLACK ARROW (same as regular BLACK ARROW) + 0x2B09, // 0xEB HEAVY UPPER LEFT BLACK ARROW same as regular BLACK ARROW) + 0x2B08, // 0xEC HEAVY UPPER RIGHT BLACK ARROW same as regular BLACK ARROW) + 0x2B0B, // 0xED HEAVY LOWER LEFT BLACK ARROW (same as regular BLACK ARROW) + 0x2B0A, // 0xEE HEAVY LOWER RIGHT BLACK ARROW (same as regular BLACK ARROW) + 0x21E6, // 0xEF LEFTWARDS WHITE ARROW + 0x21E8, // 0xF0 RIGHTWARDS WHITE ARROW + 0x21E7, // 0xF1 UPWARDS WHITE ARROW + 0x21E9, // 0xF2 DOWNWARDS WHITE ARROW + 0x21D4, // 0xF3 LEFT RIGHT DOUBLE ARROW + 0x21D5, // 0xF4 UP DOWN DOUBLE ARROW + 0x21D6, // 0xF5 NORTH WEST DOUBLE ARROW (close, but not exact) + 0x21D7, // 0xF6 NORTH EAST DOUBLE ARROW (close, but not exact) + 0x21D9, // 0xF7 SOUTH WEST DOUBLE ARROW (close, but not exact) + 0x21D8, // 0xF8 SOUTH EAST DOUBLE ARROW (close, but not exact) + 0xFFFD, // 0xF9 no replacement + 0xFFFD, // 0xFA no replacement + 0x2717, // 0xFB BALLOT X + 0x2713, // 0xFC CHECK MARK + 0x2612, // 0xFD BALLOT BOX WITH X + 0x2611, // 0xFE BALLOT BOX WITH CHECK + 0xFFFD // 0xFF no replacement +}; + +/* characters from zapf dingbat font, conversion to a unicode font. Change both the + code and the font on conversion. These are untested as the development machine did + not have the font installed. */ +static unsigned int dingbats_convert[256]={ + 0xFFFD, // 0x00 no replacement + 0xFFFD, // 0x01 no replacement + 0xFFFD, // 0x02 no replacement + 0xFFFD, // 0x03 no replacement + 0xFFFD, // 0x04 no replacement + 0xFFFD, // 0x05 no replacement + 0xFFFD, // 0x06 no replacement + 0xFFFD, // 0x07 no replacement + 0xFFFD, // 0x08 no replacement + 0xFFFD, // 0x09 no replacement + 0xFFFD, // 0x0A no replacement + 0xFFFD, // 0x0B no replacement + 0xFFFD, // 0x0C no replacement + 0xFFFD, // 0x0D no replacement + 0xFFFD, // 0x0E no replacement + 0xFFFD, // 0x0F no replacement + 0xFFFD, // 0x10 no replacement + 0xFFFD, // 0x11 no replacement + 0xFFFD, // 0x12 no replacement + 0xFFFD, // 0x13 no replacement + 0xFFFD, // 0x14 no replacement + 0xFFFD, // 0x15 no replacement + 0xFFFD, // 0x16 no replacement + 0xFFFD, // 0x17 no replacement + 0xFFFD, // 0x18 no replacement + 0xFFFD, // 0x19 no replacement + 0xFFFD, // 0x1A no replacement + 0xFFFD, // 0x1B no replacement + 0xFFFD, // 0x1C no replacement + 0xFFFD, // 0x1D no replacement + 0xFFFD, // 0x1E no replacement + 0xFFFD, // 0x1F no replacement + 0x0020, // 0x20 SPACE + 0x2701, // 0x21 UPPER BLADE SCISSORS + 0x2702, // 0x22 BLACK SCISSORS + 0x2703, // 0x23 LOWER BLADE SCISSORS + 0x2704, // 0x24 WHITE SCISSORS + 0x260E, // 0x25 BLACK TELEPHONE + 0x2706, // 0x26 TELEPHONE LOCATION SIGN + 0x2707, // 0x27 TAPE DRIVE + 0x2708, // 0x28 AIRPLANE + 0x2709, // 0x29 ENVELOPE + 0x261B, // 0x2A BLACK RIGHT POINTING INDEX + 0x261E, // 0x2B WHITE RIGHT POINTING INDEX + 0x270C, // 0x2C VICTORY HAND + 0x270D, // 0x2D WRITING HAND + 0x270E, // 0x2E LOWER RIGHT PENCIL + 0x270F, // 0x2F PENCIL + 0x2710, // 0x30 UPPER RIGHT PENCIL + 0x2711, // 0x31 WHITE NIB + 0x2712, // 0x32 BLACK NIB + 0x2713, // 0x33 CHECK MARK + 0x2714, // 0x34 HEAVY CHECK MARK + 0x2715, // 0x35 MULTIPLICATION X + 0x2716, // 0x36 HEAVY MULTIPLICATION X + 0x2717, // 0x37 BALLOT X + 0x2718, // 0x38 HEAVY BALLOT X + 0x2719, // 0x39 OUTLINED GREEK CROSS + 0x271A, // 0x3A HEAVY GREEK CROSS + 0x271B, // 0x3B OPEN CENTRE CROSS + 0x271C, // 0x3C HEAVY OPEN CENTRE CROSS + 0x271D, // 0x3D LATIN CROSS + 0x271E, // 0x3E SHADOWED WHITE LATIN CROSS + 0x271F, // 0x3F OUTLINED LATIN CROSS + 0x2720, // 0x40 MALTESE CROSS + 0x2721, // 0x41 STAR OF DAVID + 0x2722, // 0x42 FOUR TEARDROP-SPOKED ASTERISK + 0x2723, // 0x43 FOUR BALLOON-SPOKED ASTERISK + 0x2724, // 0x44 HEAVY FOUR BALLOON-SPOKED ASTERISK + 0x2725, // 0x45 FOUR CLUB-SPOKED ASTERISK + 0x2726, // 0x46 BLACK FOUR POINTED STAR + 0x2727, // 0x47 WHITE FOUR POINTED STAR + 0x2605, // 0x48 BLACK STAR + 0x2729, // 0x49 STRESS OUTLINED WHITE STAR + 0x272A, // 0x4A CIRCLED WHITE STAR + 0x272B, // 0x4B OPEN CENTRE BLACK STAR + 0x272C, // 0x4C BLACK CENTRE WHITE STAR + 0x272D, // 0x4D OUTLINED BLACK STAR + 0x272E, // 0x4E HEAVY OUTLINED BLACK STAR + 0x272F, // 0x4F PINWHEEL STAR + 0x2730, // 0x50 SHADOWED WHITE STAR + 0x2731, // 0x51 HEAVY ASTERISK + 0x2732, // 0x52 OPEN CENTRE ASTERISK + 0x2733, // 0x53 EIGHT SPOKED ASTERISK + 0x2734, // 0x54 EIGHT POINTED BLACK STAR + 0x2735, // 0x55 EIGHT POINTED PINWHEEL STAR + 0x2736, // 0x56 SIX POINTED BLACK STAR + 0x2737, // 0x57 EIGHT POINTED RECTILINEAR BLACK STAR + 0x2738, // 0x58 HEAVY EIGHT POINTED RECTILINEAR BLACK STAR + 0x2739, // 0x59 TWELVE POINTED BLACK STAR + 0x273A, // 0x5A SIXTEEN POINTED ASTERISK + 0x273B, // 0x5B TEARDROP-SPOKED ASTERISK + 0x273C, // 0x5C OPEN CENTRE TEARDROP-SPOKED ASTERISK + 0x273D, // 0x5D HEAVY TEARDROP-SPOKED ASTERISK + 0x273E, // 0x5E SIX PETALLED BLACK AND WHITE FLORETTE + 0x273F, // 0x5F BLACK FLORETTE + 0x2740, // 0x60 WHITE FLORETTE + 0x2741, // 0x61 EIGHT PETALLED OUTLINED BLACK FLORETTE + 0x2742, // 0x62 CIRCLED OPEN CENTRE EIGHT POINTED STAR + 0x2743, // 0x63 HEAVY TEARDROP-SPOKED PINWHEEL ASTERISK + 0x2744, // 0x64 SNOWFLAKE + 0x2745, // 0x65 TIGHT TRIFOLIATE SNOWFLAKE + 0x2746, // 0x66 HEAVY CHEVRON SNOWFLAKE + 0x2747, // 0x67 SPARKLE + 0x2748, // 0x68 HEAVY SPARKLE + 0x2749, // 0x69 BALLOON-SPOKED ASTERISK + 0x274A, // 0x6A EIGHT TEARDROP-SPOKED PROPELLER ASTERISK + 0x274B, // 0x6B HEAVY EIGHT TEARDROP-SPOKED PROPELLER ASTERISK + 0x25CF, // 0x6C BLACK CIRCLE + 0x274D, // 0x6D SHADOWED WHITE CIRCLE + 0x25A0, // 0x6E BLACK SQUARE + 0x274F, // 0x6F LOWER RIGHT DROP-SHADOWED WHITE SQUARE + 0x2750, // 0x70 UPPER RIGHT DROP-SHADOWED WHITE SQUARE + 0x2751, // 0x71 LOWER RIGHT SHADOWED WHITE SQUARE + 0x2752, // 0x72 UPPER RIGHT SHADOWED WHITE SQUARE + 0x25B2, // 0x73 BLACK UP-POINTING TRIANGLE + 0x25BC, // 0x74 BLACK DOWN-POINTING TRIANGLE + 0x25C6, // 0x75 BLACK DIAMOND + 0x2756, // 0x76 BLACK DIAMOND MINUS WHITE X + 0x25D7, // 0x77 RIGHT HALF BLACK CIRCLE + 0x2758, // 0x78 LIGHT VERTICAL BAR + 0x2759, // 0x79 MEDIUM VERTICAL BAR + 0x275A, // 0x7A HEAVY VERTICAL BAR + 0x275B, // 0x7B HEAVY SINGLE TURNED COMMA QUOTATION MARK ORNAMENT + 0x275C, // 0x7C HEAVY SINGLE COMMA QUOTATION MARK ORNAMENT + 0x275D, // 0x7D HEAVY DOUBLE TURNED COMMA QUOTATION MARK ORNAMENT + 0x275E, // 0x7E HEAVY DOUBLE COMMA QUOTATION MARK ORNAMENT + 0xFFFD, // 0x7F no replacement + 0xF8D7, // 0x80 MEDIUM LEFT PARENTHESIS ORNAMENT + 0xF8D8, // 0x81 MEDIUM RIGHT PARENTHESIS ORNAMENT + 0xF8D9, // 0x82 MEDIUM FLATTENED LEFT PARENTHESIS ORNAMENT + 0xF8DA, // 0x83 MEDIUM FLATTENED RIGHT PARENTHESIS ORNAMENT + 0xF8DB, // 0x84 MEDIUM LEFT-POINTING ANGLE BRACKET ORNAMENT + 0xF8DC, // 0x85 MEDIUM RIGHT-POINTING ANGLE BRACKET ORNAMENT + 0xF8DD, // 0x86 HEAVY LEFT-POINTING ANGLE QUOTATION MARK ORNAMENT + 0xF8DE, // 0x87 HEAVY RIGHT-POINTING ANGLE QUOTATION MARK ORNAMENT + 0xF8DF, // 0x88 HEAVY LEFT-POINTING ANGLE BRACKET ORNAMENT + 0xF8E0, // 0x89 HEAVY RIGHT-POINTING ANGLE BRACKET ORNAMENT + 0xF8E1, // 0x8A LIGHT LEFT TORTOISE SHELL BRACKET ORNAMENT + 0xF8E2, // 0x8B LIGHT RIGHT TORTOISE SHELL BRACKET ORNAMENT + 0xF8E3, // 0x8C MEDIUM LEFT CURLY BRACKET ORNAMENT + 0xF8E4, // 0x8D MEDIUM RIGHT CURLY BRACKET ORNAMENT + 0xFFFD, // 0x8E no replacement + 0xFFFD, // 0x8F no replacement + 0xFFFD, // 0x90 no replacement + 0xFFFD, // 0x91 no replacement + 0xFFFD, // 0x92 no replacement + 0xFFFD, // 0x93 no replacement + 0xFFFD, // 0x94 no replacement + 0xFFFD, // 0x95 no replacement + 0xFFFD, // 0x96 no replacement + 0xFFFD, // 0x97 no replacement + 0xFFFD, // 0x98 no replacement + 0xFFFD, // 0x99 no replacement + 0xFFFD, // 0x9A no replacement + 0xFFFD, // 0x9B no replacement + 0xFFFD, // 0x9C no replacement + 0xFFFD, // 0x9D no replacement + 0xFFFD, // 0x9E no replacement + 0xFFFD, // 0x9F no replacement + 0xFFFD, // 0xA0 no replacement + 0x2761, // 0xA1 CURVED STEM PARAGRAPH SIGN ORNAMENT + 0x2762, // 0xA2 HEAVY EXCLAMATION MARK ORNAMENT + 0x2763, // 0xA3 HEAVY HEART EXCLAMATION MARK ORNAMENT + 0x2764, // 0xA4 HEAVY BLACK HEART + 0x2765, // 0xA5 ROTATED HEAVY BLACK HEART BULLET + 0x2766, // 0xA6 FLORAL HEART + 0x2767, // 0xA7 ROTATED FLORAL HEART BULLET + 0x2663, // 0xA8 BLACK CLUB SUIT + 0x2666, // 0xA9 BLACK DIAMOND SUIT + 0x2665, // 0xAA BLACK HEART SUIT + 0x2660, // 0xAB BLACK SPADE SUIT + 0x2460, // 0xAC CIRCLED DIGIT ONE + 0x2461, // 0xAD CIRCLED DIGIT TWO + 0x2462, // 0xAE CIRCLED DIGIT THREE + 0x2463, // 0xAF CIRCLED DIGIT FOUR + 0x2464, // 0xB0 CIRCLED DIGIT FIVE + 0x2465, // 0xB1 CIRCLED DIGIT SIX + 0x2466, // 0xB2 CIRCLED DIGIT SEVEN + 0x2467, // 0xB3 CIRCLED DIGIT EIGHT + 0x2468, // 0xB4 CIRCLED DIGIT NINE + 0x2469, // 0xB5 CIRCLED NUMBER TEN + 0x2776, // 0xB6 DINGBAT NEGATIVE CIRCLED DIGIT ONE + 0x2777, // 0xB7 DINGBAT NEGATIVE CIRCLED DIGIT TWO + 0x2778, // 0xB8 DINGBAT NEGATIVE CIRCLED DIGIT THREE + 0x2779, // 0xB9 DINGBAT NEGATIVE CIRCLED DIGIT FOUR + 0x277A, // 0xBA DINGBAT NEGATIVE CIRCLED DIGIT FIVE + 0x277B, // 0xBB DINGBAT NEGATIVE CIRCLED DIGIT SIX + 0x277C, // 0xBC DINGBAT NEGATIVE CIRCLED DIGIT SEVEN + 0x277D, // 0xBD DINGBAT NEGATIVE CIRCLED DIGIT EIGHT + 0x277E, // 0xBE DINGBAT NEGATIVE CIRCLED DIGIT NINE + 0x277F, // 0xBF DINGBAT NEGATIVE CIRCLED NUMBER TEN + 0x2780, // 0xC0 DINGBAT CIRCLED SANS-SERIF DIGIT ONE + 0x2781, // 0xC1 DINGBAT CIRCLED SANS-SERIF DIGIT TWO + 0x2782, // 0xC2 DINGBAT CIRCLED SANS-SERIF DIGIT THREE + 0x2783, // 0xC3 DINGBAT CIRCLED SANS-SERIF DIGIT FOUR + 0x2784, // 0xC4 DINGBAT CIRCLED SANS-SERIF DIGIT FIVE + 0x2785, // 0xC5 DINGBAT CIRCLED SANS-SERIF DIGIT SIX + 0x2786, // 0xC6 DINGBAT CIRCLED SANS-SERIF DIGIT SEVEN + 0x2787, // 0xC7 DINGBAT CIRCLED SANS-SERIF DIGIT EIGHT + 0x2788, // 0xC8 DINGBAT CIRCLED SANS-SERIF DIGIT NINE + 0x2789, // 0xC9 DINGBAT CIRCLED SANS-SERIF NUMBER TEN + 0x278A, // 0xCA DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT ONE + 0x278B, // 0xCB DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT TWO + 0x278C, // 0xCC DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT THREE + 0x278D, // 0xCD DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT FOUR + 0x278E, // 0xCE DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT FIVE + 0x278F, // 0xCF DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT SIX + 0x2790, // 0xD0 DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT SEVEN + 0x2791, // 0xD1 DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT EIGHT + 0x2792, // 0xD2 DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT NINE + 0x2793, // 0xD3 DINGBAT NEGATIVE CIRCLED SANS-SERIF NUMBER TEN + 0x2794, // 0xD4 HEAVY WIDE-HEADED RIGHTWARDS ARROW + 0x2192, // 0xD5 RIGHTWARDS ARROW + 0x2194, // 0xD6 LEFT RIGHT ARROW + 0x2195, // 0xD7 UP DOWN ARROW + 0x2798, // 0xD8 HEAVY SOUTH EAST ARROW + 0x2799, // 0xD9 HEAVY RIGHTWARDS ARROW + 0x279A, // 0xDA HEAVY NORTH EAST ARROW + 0x279B, // 0xDB DRAFTING POINT RIGHTWARDS ARROW + 0x279C, // 0xDC HEAVY ROUND-TIPPED RIGHTWARDS ARROW + 0x279D, // 0xDD TRIANGLE-HEADED RIGHTWARDS ARROW + 0x279E, // 0xDE HEAVY TRIANGLE-HEADED RIGHTWARDS ARROW + 0x279F, // 0xDF DASHED TRIANGLE-HEADED RIGHTWARDS ARROW + 0x27A0, // 0xE0 HEAVY DASHED TRIANGLE-HEADED RIGHTWARDS ARROW + 0x27A1, // 0xE1 BLACK RIGHTWARDS ARROW + 0x27A2, // 0xE2 THREE-D TOP-LIGHTED RIGHTWARDS ARROWHEAD + 0x27A3, // 0xE3 THREE-D BOTTOM-LIGHTED RIGHTWARDS ARROWHEAD + 0x27A4, // 0xE4 BLACK RIGHTWARDS ARROWHEAD + 0x27A5, // 0xE5 HEAVY BLACK CURVED DOWNWARDS AND RIGHTWARDS ARROW + 0x27A6, // 0xE6 HEAVY BLACK CURVED UPWARDS AND RIGHTWARDS ARROW + 0x27A7, // 0xE7 SQUAT BLACK RIGHTWARDS ARROW + 0x27A8, // 0xE8 HEAVY CONCAVE-POINTED BLACK RIGHTWARDS ARROW + 0x27A9, // 0xE9 RIGHT-SHADED WHITE RIGHTWARDS ARROW + 0x27AA, // 0xEA LEFT-SHADED WHITE RIGHTWARDS ARROW + 0x27AB, // 0xEB BACK-TILTED SHADOWED WHITE RIGHTWARDS ARROW + 0x27AC, // 0xEC FRONT-TILTED SHADOWED WHITE RIGHTWARDS ARROW + 0x27AD, // 0xED HEAVY LOWER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW + 0x27AE, // 0xEE HEAVY UPPER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW + 0x27AF, // 0xEF NOTCHED LOWER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW + 0xFFFD, // 0xF0 no replacement + 0x27B1, // 0xF1 NOTCHED UPPER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW + 0x27B2, // 0xF2 CIRCLED HEAVY WHITE RIGHTWARDS ARROW + 0x27B3, // 0xF3 WHITE-FEATHERED RIGHTWARDS ARROW + 0x27B4, // 0xF4 BLACK-FEATHERED SOUTH EAST ARROW + 0x27B5, // 0xF5 BLACK-FEATHERED RIGHTWARDS ARROW + 0x27B6, // 0xF6 BLACK-FEATHERED NORTH EAST ARROW + 0x27B7, // 0xF7 HEAVY BLACK-FEATHERED SOUTH EAST ARROW + 0x27B8, // 0xF8 HEAVY BLACK-FEATHERED RIGHTWARDS ARROW + 0x27B9, // 0xF9 HEAVY BLACK-FEATHERED NORTH EAST ARROW + 0x27BA, // 0xFA TEARDROP-BARBED RIGHTWARDS ARROW + 0x27BB, // 0xFB HEAVY TEARDROP-SHANKED RIGHTWARDS ARROW + 0x27BC, // 0xFC WEDGE-TAILED RIGHTWARDS ARROW + 0x27BD, // 0xFD HEAVY WEDGE-TAILED RIGHTWARDS ARROW + 0x27BE, // 0xFE OPEN-OUTLINED RIGHTWARDS ARROW + 0xFFFD // 0xFF no replacement +}; + +/* characters from symbol font, conversion to a unicode font. Change both the + code and the font on conversion. */ +static unsigned int symbol_convert[256]={ + 0xFFFD, // 0x00 no replacement + 0xFFFD, // 0x01 no replacement + 0xFFFD, // 0x02 no replacement + 0xFFFD, // 0x03 no replacement + 0xFFFD, // 0x04 no replacement + 0xFFFD, // 0x05 no replacement + 0xFFFD, // 0x06 no replacement + 0xFFFD, // 0x07 no replacement + 0xFFFD, // 0x08 no replacement + 0xFFFD, // 0x09 no replacement + 0xFFFD, // 0x0A no replacement + 0xFFFD, // 0x0B no replacement + 0xFFFD, // 0x0C no replacement + 0xFFFD, // 0x0D no replacement + 0xFFFD, // 0x0E no replacement + 0xFFFD, // 0x0F no replacement + 0xFFFD, // 0x10 no replacement + 0xFFFD, // 0x11 no replacement + 0xFFFD, // 0x12 no replacement + 0xFFFD, // 0x13 no replacement + 0xFFFD, // 0x14 no replacement + 0xFFFD, // 0x15 no replacement + 0xFFFD, // 0x16 no replacement + 0xFFFD, // 0x17 no replacement + 0xFFFD, // 0x18 no replacement + 0xFFFD, // 0x19 no replacement + 0xFFFD, // 0x1A no replacement + 0xFFFD, // 0x1B no replacement + 0xFFFD, // 0x1C no replacement + 0xFFFD, // 0x1D no replacement + 0xFFFD, // 0x1E no replacement + 0xFFFD, // 0x1F no replacement + 0x0020, // 0x20 SPACE + 0x0021, // 0x21 EXCLAMATION MARK + 0x2200, // 0x22 FOR ALL + 0x0023, // 0x23 NUMBER SIGN + 0x2203, // 0x24 THERE EXISTS + 0x0025, // 0x25 PERCENT SIGN + 0x0026, // 0x26 AMPERSAND + 0x220B, // 0x27 CONTAINS AS MEMBER + 0x0028, // 0x28 OPENING PARENTHESIS + 0x0029, // 0x29 CLOSING PARENTHESIS + 0x2217, // 0x2A ASTERISK OPERATOR + 0x002B, // 0x2B PLUS SIGN + 0x002C, // 0x2C COMMA + 0x2212, // 0x2D MINUS SIGN + 0x002E, // 0x2E PERIOD + 0x002F, // 0x2F SLASH + 0x0030, // 0x30 DIGIT ZERO + 0x0031, // 0x31 DIGIT ONE + 0x0032, // 0x32 DIGIT TWO + 0x0033, // 0x33 DIGIT THREE + 0x0034, // 0x34 DIGIT FOUR + 0x0035, // 0x35 DIGIT FIVE + 0x0036, // 0x36 DIGIT SIX + 0x0037, // 0x37 DIGIT SEVEN + 0x0038, // 0x38 DIGIT EIGHT + 0x0039, // 0x39 DIGIT NINE + 0x003A, // 0x3A COLON + 0x003B, // 0x3B SEMICOLON + 0x003C, // 0x3C LESS-THAN SIGN + 0x003D, // 0x3D EQUALS SIGN + 0x003E, // 0x3E GREATER-THAN SIGN + 0x003F, // 0x3F QUESTION MARK + 0x2245, // 0x40 APPROXIMATELY EQUAL TO + 0x0391, // 0x41 GREEK CAPITAL LETTER ALPHA + 0x0392, // 0x42 GREEK CAPITAL LETTER BETA + 0x03A7, // 0x43 GREEK CAPITAL LETTER CHI + 0x0394, // 0x44 GREEK CAPITAL LETTER DELTA + 0x0395, // 0x45 GREEK CAPITAL LETTER EPSILON + 0x03A6, // 0x46 GREEK CAPITAL LETTER PHI + 0x0393, // 0x47 GREEK CAPITAL LETTER GAMMA + 0x0397, // 0x48 GREEK CAPITAL LETTER ETA + 0x0399, // 0x49 GREEK CAPITAL LETTER IOTA + 0x03D1, // 0x4A GREEK SMALL LETTER SCRIPT THETA + 0x039A, // 0x4B GREEK CAPITAL LETTER KAPPA + 0x039B, // 0x4C GREEK CAPITAL LETTER LAMBDA + 0x039C, // 0x4D GREEK CAPITAL LETTER MU + 0x039D, // 0x4E GREEK CAPITAL LETTER NU + 0x039F, // 0x4F GREEK CAPITAL LETTER OMICRON + 0x03A0, // 0x50 GREEK CAPITAL LETTER PI + 0x0398, // 0x51 GREEK CAPITAL LETTER THETA + 0x03A1, // 0x52 GREEK CAPITAL LETTER RHO + 0x03A3, // 0x53 GREEK CAPITAL LETTER SIGMA + 0x03A4, // 0x54 GREEK CAPITAL LETTER TAU + 0x03A5, // 0x55 GREEK CAPITAL LETTER UPSILON + 0x03C2, // 0x56 GREEK SMALL LETTER FINAL SIGMA + 0x03A9, // 0x57 GREEK CAPITAL LETTER OMEGA + 0x039E, // 0x58 GREEK CAPITAL LETTER XI + 0x03A8, // 0x59 GREEK CAPITAL LETTER PSI + 0x0396, // 0x5A GREEK CAPITAL LETTER ZETA + 0x005B, // 0x5B OPENING SQUARE BRACKET + 0x2234, // 0x5C THEREFORE + 0x005D, // 0x5D CLOSING SQUARE BRACKET + 0x22A5, // 0x5E UP TACK + 0x005F, // 0x5F SPACING UNDERSCORE + 0x203E, // 0x60 SPACING OVERSCORE + 0x03B1, // 0x61 GREEK SMALL LETTER ALPHA + 0x03B2, // 0x62 GREEK SMALL LETTER BETA + 0x03C7, // 0x63 GREEK SMALL LETTER CHI + 0x03B4, // 0x64 GREEK SMALL LETTER DELTA + 0x03B5, // 0x65 GREEK SMALL LETTER EPSILON + 0x03C6, // 0x66 GREEK SMALL LETTER PHI + 0x03B3, // 0x67 GREEK SMALL LETTER GAMMA + 0x03B7, // 0x68 GREEK SMALL LETTER ETA + 0x03B9, // 0x69 GREEK SMALL LETTER IOTA + 0x03D5, // 0x6A GREEK SMALL LETTER SCRIPT PHI + 0x03BA, // 0x6B GREEK SMALL LETTER KAPPA + 0x03BB, // 0x6C GREEK SMALL LETTER LAMBDA + 0x03BC, // 0x6D GREEK SMALL LETTER MU + 0x03BD, // 0x6E GREEK SMALL LETTER NU + 0x03BF, // 0x6F GREEK SMALL LETTER OMICRON + 0x03C0, // 0x70 GREEK SMALL LETTER PI + 0x03B8, // 0x71 GREEK SMALL LETTER THETA + 0x03C1, // 0x72 GREEK SMALL LETTER RHO + 0x03C3, // 0x73 GREEK SMALL LETTER SIGMA + 0x03C4, // 0x74 GREEK SMALL LETTER TAU + 0x03C5, // 0x75 GREEK SMALL LETTER UPSILON + 0x03D6, // 0x76 GREEK SMALL LETTER OMEGA PI + 0x03C9, // 0x77 GREEK SMALL LETTER OMEGA + 0x03BE, // 0x78 GREEK SMALL LETTER XI + 0x03C8, // 0x79 GREEK SMALL LETTER PSI + 0x03B6, // 0x7A GREEK SMALL LETTER ZETA + 0x007B, // 0x7B OPENING CURLY BRACKET + 0x007C, // 0x7C VERTICAL BAR + 0x007D, // 0x7D CLOSING CURLY BRACKET + 0x223C, // 0x7E TILDE OPERATOR + 0xFFFD, // 0x7F no replacement + 0xFFFD, // 0x80 no replacement + 0xFFFD, // 0x81 no replacement + 0xFFFD, // 0x82 no replacement + 0xFFFD, // 0x83 no replacement + 0xFFFD, // 0x84 no replacement + 0xFFFD, // 0x85 no replacement + 0xFFFD, // 0x86 no replacement + 0xFFFD, // 0x87 no replacement + 0xFFFD, // 0x88 no replacement + 0xFFFD, // 0x89 no replacement + 0xFFFD, // 0x8A no replacement + 0xFFFD, // 0x8B no replacement + 0xFFFD, // 0x8C no replacement + 0xFFFD, // 0x8D no replacement + 0xFFFD, // 0x8E no replacement + 0xFFFD, // 0x8F no replacement + 0xFFFD, // 0x90 no replacement + 0xFFFD, // 0x91 no replacement + 0xFFFD, // 0x92 no replacement + 0xFFFD, // 0x93 no replacement + 0xFFFD, // 0x94 no replacement + 0xFFFD, // 0x95 no replacement + 0xFFFD, // 0x96 no replacement + 0xFFFD, // 0x97 no replacement + 0xFFFD, // 0x98 no replacement + 0xFFFD, // 0x99 no replacement + 0xFFFD, // 0x9A no replacement + 0xFFFD, // 0x9B no replacement + 0xFFFD, // 0x9C no replacement + 0xFFFD, // 0x9D no replacement + 0xFFFD, // 0x9E no replacement + 0xFFFD, // 0x9F no replacement + 0x20AC, // 0xA0 EURO SIGN + 0x03D2, // 0xA1 GREEK CAPITAL LETTER UPSILON HOOK + 0x2032, // 0xA2 PRIME + 0x2264, // 0xA3 LESS THAN OR EQUAL TO + 0x2044, // 0xA4 FRACTION SLASH + 0x221E, // 0xA5 INFINITY + 0x0192, // 0xA6 LATIN SMALL LETTER SCRIPT F + 0x2663, // 0xA7 BLACK CLUB SUIT + 0x2666, // 0xA8 BLACK DIAMOND SUIT + 0x2665, // 0xA9 BLACK HEART SUIT + 0x2660, // 0xAA BLACK SPADE SUIT + 0x2194, // 0xAB LEFT RIGHT ARROW + 0x2190, // 0xAC LEFT ARROW + 0x2191, // 0xAD UP ARROW + 0x2192, // 0xAE RIGHT ARROW + 0x2193, // 0xAF DOWN ARROW + 0x00B0, // 0xB0 DEGREE SIGN + 0x00B1, // 0xB1 PLUS-OR-MINUS SIGN + 0x2033, // 0xB2 DOUBLE PRIME + 0x2265, // 0xB3 GREATER THAN OR EQUAL TO + 0x00D7, // 0xB4 MULTIPLICATION SIGN + 0x221D, // 0xB5 PROPORTIONAL TO + 0x2202, // 0xB6 PARTIAL DIFFERENTIAL + 0x2219, // 0xB7 BULLET (use BULLET operator, so normal font BULLET will not convert to Symbol BULLET) + 0x00F7, // 0xB8 DIVISION SIGN + 0x2260, // 0xB9 NOT EQUAL TO + 0x2261, // 0xBA IDENTICAL TO + 0x2248, // 0xBB ALMOST EQUAL TO + 0x2026, // 0xBC HORIZONTAL ELLIPSIS + 0xF8E6, // 0xBD VERTICAL ARROW EXTENDER + 0xF8E7, // 0xBE HORIZONTAL ARROW EXTENDER + 0x21B5, // 0xBF DOWN ARROW WITH CORNER LEFT + 0x2135, // 0xC0 FIRST TRANSFINITE CARDINAL + 0x2111, // 0xC1 BLACK-LETTER I + 0x211C, // 0xC2 BLACK-LETTER R + 0x2118, // 0xC3 SCRIPT P + 0x2297, // 0xC4 CIRCLED TIMES + 0x2295, // 0xC5 CIRCLED PLUS + 0x2205, // 0xC6 EMPTY SET + 0x2229, // 0xC7 INTERSECTION + 0x222A, // 0xC8 UNION + 0x2283, // 0xC9 SUPERSET OF + 0x2287, // 0xCA SUPERSET OF OR EQUAL TO + 0x2284, // 0xCB NOT A SUBSET OF + 0x2282, // 0xCC SUBSET OF + 0x2286, // 0xCD SUBSET OF OR EQUAL TO + 0x2208, // 0xCE ELEMENT OF + 0x2209, // 0xCF NOT AN ELEMENT OF + 0x2220, // 0xD0 ANGLE + 0x2207, // 0xD1 NABLA + 0x00AE, // 0xD2 REGISTERED TRADE MARK SIGN + 0x00A9, // 0xD3 COPYRIGHT SIGN + 0x2122, // 0xD4 TRADEMARK + 0x220F, // 0xD5 N-ARY PRODUCT + 0x221A, // 0xD6 SQUARE ROOT + 0x22C5, // 0xD7 DOT OPERATOR + 0x00AC, // 0xD8 NOT SIGN + 0x2227, // 0xD9 LOGICAL AND + 0x2228, // 0xDA LOGICAL OR + 0x21D4, // 0xDB LEFT RIGHT DOUBLE ARROW + 0x21D0, // 0xDC LEFT DOUBLE ARROW + 0x21D1, // 0xDD UP DOUBLE ARROW + 0x21D2, // 0xDE RIGHT DOUBLE ARROW + 0x21D3, // 0xDF DOWN DOUBLE ARROW + 0x25CA, // 0xE0 LOZENGE + 0x2329, // 0xE1 BRA + 0x00AE, // 0xE2 REGISTERED TRADE MARK SIGN + 0x00A9, // 0xE3 COPYRIGHT SIGN + 0x2122, // 0xE4 TRADEMARK + 0x2211, // 0xE5 N-ARY SUMMATION + 0x239B, // 0xE6 LEFT PAREN TOP + 0x239C, // 0xE7 LEFT PAREN EXTENDER + 0x239D, // 0xE8 LEFT PAREN BOTTOM + 0x23A1, // 0xE9 LEFT SQUARE BRACKET TOP + 0x23A2, // 0xEA LEFT SQUARE BRACKET EXTENDER + 0x23A3, // 0xEB LEFT SQUARE BRACKET BOTTOM + 0x23A7, // 0xEC LEFT CURLY BRACKET TOP + 0x23A8, // 0xED LEFT CURLY BRACKET MID + 0x23A9, // 0xEE LEFT CURLY BRACKET BOTTOM + 0x23AA, // 0xEF CURLY BRACKET EXTENDER + 0xFFFD, // 0xF0 no replacement + 0x232A, // 0xF1 KET + 0x222B, // 0xF2 INTEGRAL + 0x2320, // 0xF3 TOP HALF INTEGRAL + 0x23AE, // 0xF4 INTEGRAL EXTENDER + 0x2321, // 0xF5 BOTTOM HALF INTEGRAL + 0x239E, // 0xF6 RIGHT PAREN TOP + 0x239F, // 0xF7 RIGHT PAREN EXTENDER + 0x23A0, // 0xF8 RIGHT PAREN BOTTOM + 0x23A4, // 0xF9 RIGHT SQUARE BRACKET TOP + 0x23A5, // 0xFA RIGHT SQUARE BRACKET EXTENDER + 0x23A6, // 0xFB RIGHT SQUARE BRACKET BOTTOM + 0x23AB, // 0xFC RIGHT CURLY BRACKET TOP + 0x23AC, // 0xFD RIGHT CURLY BRACKET MID + 0x23AD, // 0xFE RIGHT CURLY BRACKET BOTTOM + 0xFFFD // 0xFF no replacement +}; + +/* Use this for debugging */ +#include <stdio.h> +void UC_log_message(char *text){ +FILE *fp; + fp=fopen("c:/temp/debug.txt","a"); + fprintf(fp,"%s",text); + fclose(fp); +} + + +//if any character is in the MS private use area (F020 through F0FF) subtract F000, for use with Symbol and Wingdings* from older software +void msdepua (uint32_t *text) +{ + while(*text){ + if(*text >= 0xF020 && *text <= 0xF0FF){ *text -= 0xF000; } + text++; + } +} + +//move characters up to MS private use area (F020 through F0FF) +void msrepua (uint16_t *text) +{ + while(*text){ + if(*text >= 0x20 && *text <= 0xFF){ *text += 0xF000; } + text++; + } +} + +// Returns the font classification code +int isNon(char *font){ +int retval; + if(!strcmp(font,"Symbol")){ + retval=CVTSYM; + } + else if(!strcmp(font,"Wingdings")){ + retval=CVTWDG; + } + else if(!strcmp(font,"ZapfDingbats")){ + retval=CVTZDG; + } + else { + retval=CVTNON; + } + return retval; +} + +// Returns the font name, given the classification code, or NULL +// The returned value must NOT be free'd +char *FontName(int code){ +char *cptr; +static char name_symbol[]="Symbol"; +static char name_wingdings[]="Wingdings"; +static char name_zapfdingbats[]="ZapfDingbats"; + switch(code){ + case CVTSYM: cptr=&name_symbol[0]; break; + case CVTWDG: cptr=&name_wingdings[0]; break; + case CVTZDG: cptr=&name_zapfdingbats[0]; break; + default: cptr=NULL; break; + } + return(cptr); +} + + +// Goes through the uint32_t string converting as needed. +int NonToUnicode(uint32_t *text, char *font){ +int retval; +unsigned int *convert_from=NULL; + retval=isNon(font); + switch(retval){ + case CVTSYM: convert_from=symbol_convert; break; + case CVTWDG: convert_from=wingdings_convert; break; + case CVTZDG: convert_from=dingbats_convert; break; + default: return(retval); //no conversion + } + while(*text){ + if(*text > 0xFF){ *text = 0xFFFD; } // out of range + else { *text = convert_from[*text]; } + text++; + } + return(retval); +} + +//returns 1 if tables are defines for UnicodeToNon translation +int CanUTN(void){ + if(from_unicode)return(1); + return(0); +} + +//translates from Unicode to some non unicode font until the target font changes. +//A target font change is like symbol -> wingdings, or symbol -> no translation +//returns the number of characters changed in ecount +//returns the enum value for the destination value in edest +void UnicodeToNon(uint16_t *text, int *ecount, int *edest){ +int count=0; +unsigned char target=0; + if(to_font){ + if(text && (target=to_font[*text])){ //There is actually something here to convert + while(*text && target==to_font[*text]){ + *text=from_unicode[*text] + (hold_pua ? 0xF000 : 0 ); + text++; + count++; + } + } + *ecount=count; + *edest=target; + } + else { // no translation tables, so change nothing and return + *ecount=0; + *edest=CVTNON; + } +} + +//Indicates the type of translation for a single character, Unicode to some non unicode +//returns the enum value for the destination value. +//If no translation tables are defined returns CVTNON (no conversions) +int SingleUnicodeToNon(uint16_t text){ + if(to_font){return(to_font[text]); } + else { return(CVTNON); } +} + +void table_filler(unsigned int *src, int code){ +unsigned int i; + for(i=0;i<0x100;i++){ + if(src[i] == 0xFFFD)continue; /* no mapping Unicode -> nonUnicode */ + if(src[i] == i)continue; /* no remapping of spaces back to spaces, for instance */ + from_unicode[src[i]] = i; + to_font[src[i]] = code; + } +} + +//possibly (re)generate the tables +void TableGen(bool new_symb,bool new_wing, bool new_zdng, bool new_pua){ +int i; + if(hold_symb != new_symb || hold_wing != new_wing + || hold_zdng != new_zdng || hold_pua != new_pua ){ // must (re)generate tables + if(!from_unicode){ // create arrays + from_unicode = (unsigned char *) calloc(0x10000,sizeof(unsigned char)); + to_font = (unsigned char *) calloc(0x10000,sizeof(unsigned char)); + // should check here for malloc error + } + hold_symb = new_symb; + hold_wing = new_wing; + hold_zdng = new_zdng; + hold_pua = new_pua; + for(i=0;i<0x10000;i++){ from_unicode[i] = to_font[i] = 0; } + if(hold_zdng)table_filler(&dingbats_convert[0],CVTZDG); + if(hold_wing)table_filler(&wingdings_convert[0],CVTWDG); + if(hold_symb)table_filler(&symbol_convert[0],CVTSYM); + } +} + +#ifdef __cplusplus +} +#endif diff --git a/src/3rdparty/libuemf/symbol_convert.h b/src/3rdparty/libuemf/symbol_convert.h new file mode 100644 index 0000000..ac17950 --- /dev/null +++ b/src/3rdparty/libuemf/symbol_convert.h @@ -0,0 +1,51 @@ +/** @file + * @brief Enhanced Metafile Input/Output + */ +/* Authors: + * David Mathog <mathog@caltech.edu> + * + * Copyright (C) 2012 Authors + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef SEEN_UNICODE_CONVERT_H +#define SEEN_UNICODE_CONVERT_H +#include <stdlib.h> +#include <stdbool.h> +#include <stdint.h> + + enum cvt_to_font {CVTNON, CVTSYM, CVTZDG, CVTWDG}; + + void msdepua(uint32_t *text); //translate down from Microsoft Private Use Area + void msrepua(uint16_t *text); //translate up to Microsoft Private Use Area + int isNon(char *font); //returns one of the cvt_to_font enum values + char *FontName(int code); //returns the font name (or NULL) given the enum code + int NonToUnicode(uint32_t *text, char *font); //nonunicode to Unicode translation + int CanUTN(void); // 1 if tables exist for UnicodeToNon translation + int SingleUnicodeToNon(uint16_t text); //retuns the enum value for this translation + void UnicodeToNon(uint16_t *text, int *ecount, int *edest); //translate Unicode to NonUnicode + void TableGen(bool symb, bool wing, bool zdng, bool pua); + +#ifdef __cplusplus +} +#endif + +#endif /* SEEN_UNICODE_CONVERT_H */ + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : + + diff --git a/src/3rdparty/libuemf/uemf.c b/src/3rdparty/libuemf/uemf.c new file mode 100644 index 0000000..fa7689b --- /dev/null +++ b/src/3rdparty/libuemf/uemf.c @@ -0,0 +1,5606 @@ +/** + @file uemf.c + + @brief Functions for manipulating EMF files and structures. + + [U_EMR]_set all take data and return a pointer to memory holding the constructed record. + The size of that record is also returned in recsize. + It is also in the second int32 in the record, but may have been byte swapped and so not usable. + If something goes wrong a NULL pointer is returned and recsize is set to 0. + + Compile with "U_VALGRIND" defined defined to enable code which lets valgrind check each record for + uninitialized data. + + Compile with "SOL8" defined for Solaris 8 or 9 (Sparc). +*/ + +/* +File: uemf.c +Version: 0.0.31 +Date: 26-JAN-2016 +Author: David Mathog, Biology Division, Caltech +email: mathog@caltech.edu +Copyright: 2016 David Mathog and California Institute of Technology (Caltech) +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <iconv.h> +#include <wchar.h> +#include <errno.h> +#include <string.h> +#include <limits.h> // for INT_MAX, INT_MIN +#include <math.h> // for U_ROUND() +#include <stddef.h> /* for offsetof() macro */ +#if 0 +#include <windef.h> //Not actually used, looking for collisions +#include <winnt.h> //Not actually used, looking for collisions +#include <wingdi.h> //Not actually used, looking for collisions +#endif +#include "uemf.h" + +//! \cond +/* one prototype from uemf_endian. Put it here because end user should never need to see it, so +not in uemf.h or uemf_endian.h */ +void U_swap2(void *ul, unsigned int count); +//! \endcond + +/** + \brief Look up the name of the EMR record by type. Returns U_EMR_INVALID if out of range. + + \return name of the EMR record, "U_EMR_INVALID" if out of range. + \param idx EMR record type. + +*/ +char *U_emr_names(unsigned int idx){ + if(idx<U_EMR_MIN || idx > U_EMR_MAX){ idx = 0; } + static char *U_EMR_NAMES[U_EMR_MAX+1]={ + "U_EMR_INVALID", + "U_EMR_HEADER", + "U_EMR_POLYBEZIER", + "U_EMR_POLYGON", + "U_EMR_POLYLINE", + "U_EMR_POLYBEZIERTO", + "U_EMR_POLYLINETO", + "U_EMR_POLYPOLYLINE", + "U_EMR_POLYPOLYGON", + "U_EMR_SETWINDOWEXTEX", + "U_EMR_SETWINDOWORGEX", + "U_EMR_SETVIEWPORTEXTEX", + "U_EMR_SETVIEWPORTORGEX", + "U_EMR_SETBRUSHORGEX", + "U_EMR_EOF", + "U_EMR_SETPIXELV", + "U_EMR_SETMAPPERFLAGS", + "U_EMR_SETMAPMODE", + "U_EMR_SETBKMODE", + "U_EMR_SETPOLYFILLMODE", + "U_EMR_SETROP2", + "U_EMR_SETSTRETCHBLTMODE", + "U_EMR_SETTEXTALIGN", + "U_EMR_SETCOLORADJUSTMENT", + "U_EMR_SETTEXTCOLOR", + "U_EMR_SETBKCOLOR", + "U_EMR_OFFSETCLIPRGN", + "U_EMR_MOVETOEX", + "U_EMR_SETMETARGN", + "U_EMR_EXCLUDECLIPRECT", + "U_EMR_INTERSECTCLIPRECT", + "U_EMR_SCALEVIEWPORTEXTEX", + "U_EMR_SCALEWINDOWEXTEX", + "U_EMR_SAVEDC", + "U_EMR_RESTOREDC", + "U_EMR_SETWORLDTRANSFORM", + "U_EMR_MODIFYWORLDTRANSFORM", + "U_EMR_SELECTOBJECT", + "U_EMR_CREATEPEN", + "U_EMR_CREATEBRUSHINDIRECT", + "U_EMR_DELETEOBJECT", + "U_EMR_ANGLEARC", + "U_EMR_ELLIPSE", + "U_EMR_RECTANGLE", + "U_EMR_ROUNDRECT", + "U_EMR_ARC", + "U_EMR_CHORD", + "U_EMR_PIE", + "U_EMR_SELECTPALETTE", + "U_EMR_CREATEPALETTE", + "U_EMR_SETPALETTEENTRIES", + "U_EMR_RESIZEPALETTE", + "U_EMR_REALIZEPALETTE", + "U_EMR_EXTFLOODFILL", + "U_EMR_LINETO", + "U_EMR_ARCTO", + "U_EMR_POLYDRAW", + "U_EMR_SETARCDIRECTION", + "U_EMR_SETMITERLIMIT", + "U_EMR_BEGINPATH", + "U_EMR_ENDPATH", + "U_EMR_CLOSEFIGURE", + "U_EMR_FILLPATH", + "U_EMR_STROKEANDFILLPATH", + "U_EMR_STROKEPATH", + "U_EMR_FLATTENPATH", + "U_EMR_WIDENPATH", + "U_EMR_SELECTCLIPPATH", + "U_EMR_ABORTPATH", + "U_EMR_UNDEF69", + "U_EMR_COMMENT", + "U_EMR_FILLRGN", + "U_EMR_FRAMERGN", + "U_EMR_INVERTRGN", + "U_EMR_PAINTRGN", + "U_EMR_EXTSELECTCLIPRGN", + "U_EMR_BITBLT", + "U_EMR_STRETCHBLT", + "U_EMR_MASKBLT", + "U_EMR_PLGBLT", + "U_EMR_SETDIBITSTODEVICE", + "U_EMR_STRETCHDIBITS", + "U_EMR_EXTCREATEFONTINDIRECTW", + "U_EMR_EXTTEXTOUTA", + "U_EMR_EXTTEXTOUTW", + "U_EMR_POLYBEZIER16", + "U_EMR_POLYGON16", + "U_EMR_POLYLINE16", + "U_EMR_POLYBEZIERTO16", + "U_EMR_POLYLINETO16", + "U_EMR_POLYPOLYLINE16", + "U_EMR_POLYPOLYGON16", + "U_EMR_POLYDRAW16", + "U_EMR_CREATEMONOBRUSH", + "U_EMR_CREATEDIBPATTERNBRUSHPT", + "U_EMR_EXTCREATEPEN", + "U_EMR_POLYTEXTOUTA", + "U_EMR_POLYTEXTOUTW", + "U_EMR_SETICMMODE", + "U_EMR_CREATECOLORSPACE", + "U_EMR_SETCOLORSPACE", + "U_EMR_DELETECOLORSPACE", + "U_EMR_GLSRECORD", + "U_EMR_GLSBOUNDEDRECORD", + "U_EMR_PIXELFORMAT", + "U_EMR_DRAWESCAPE", + "U_EMR_EXTESCAPE", + "U_EMR_UNDEF107", + "U_EMR_SMALLTEXTOUT", + "U_EMR_FORCEUFIMAPPING", + "U_EMR_NAMEDESCAPE", + "U_EMR_COLORCORRECTPALETTE", + "U_EMR_SETICMPROFILEA", + "U_EMR_SETICMPROFILEW", + "U_EMR_ALPHABLEND", + "U_EMR_SETLAYOUT", + "U_EMR_TRANSPARENTBLT", + "U_EMR_UNDEF117", + "U_EMR_GRADIENTFILL", + "U_EMR_SETLINKEDUFIS", + "U_EMR_SETTEXTJUSTIFICATION", + "U_EMR_COLORMATCHTOTARGETW", + "U_EMR_CREATECOLORSPACEW" + }; + return(U_EMR_NAMES[idx]); +} + + + +/* ********************************************************************************************** +These definitions are for code pieces that are used many times in the following implementation. These +definitions are not needed in end user code, so they are here rather than in uemf.h. +*********************************************************************************************** */ + +//! @cond + +// this one may also be used A=Msk,B=MskBmi and F=cbMsk +#define SET_CB_FROM_PXBMI(A,B,C,D,E,F) /* A=Px, B=Bmi, C=cbImage, D=cbImage4, E=cbBmi, F=cbPx */ \ + if(A){\ + if(!B)return(NULL); /* size is derived from U_BITMAPINFO, but NOT from its size field, go figure*/ \ + C = F;\ + D = UP4(C); /* pixel array might not be a multiples of 4 bytes*/ \ + E = sizeof(U_BITMAPINFOHEADER) + 4 * get_real_color_count((const char *) &(B->bmiHeader)); /* bmiheader + colortable*/ \ + }\ + else { C = 0; D = 0; E=0; } + +// variable "off" must be declared in the function + +#define APPEND_PXBMISRC(A,B,C,D,E,F,G) /* A=record, B=U_EMR,C=cbBmi, D=Bmi, E=Px, F=cbImage, G=cbImage4 */ \ + if(C){\ + memcpy(A + off, D, C);\ + ((B *) A)->offBmiSrc = off;\ + ((B *) A)->cbBmiSrc = C;\ + off += C;\ + memcpy(A + off, E, F);\ + ((B *) A)->offBitsSrc = off;\ + ((B *) A)->cbBitsSrc = F;\ + if(G - F){ \ + off += F;\ + memset(A + off, 0, G - F); \ + }\ + }\ + else {\ + ((B *) A)->offBmiSrc = 0;\ + ((B *) A)->cbBmiSrc = 0;\ + ((B *) A)->offBitsSrc = 0;\ + ((B *) A)->cbBitsSrc = 0;\ + } + +// variable "off" must be declared in the function + +#define APPEND_MSKBMISRC(A,B,C,D,E,F,G) /* A=record, B=U_EMR*,C=cbMskBmi, D=MskBmi, E=Msk, F=cbMskImage, G=cbMskImage4 */ \ + if(C){\ + memcpy(A + off, D, C);\ + ((B *) A)->offBmiMask = off;\ + ((B *) A)->cbBmiMask = C;\ + off += C;\ + memcpy(A + off, Msk, F);\ + ((B *) A)->offBitsMask = off;\ + ((B *) A)->cbBitsMask = F;\ + if(G - F){ memset(A + off, 0, G - F); }\ + }\ + else {\ + ((B *) A)->offBmiMask = 0;\ + ((B *) A)->cbBmiMask = 0;\ + ((B *) A)->offBitsMask = 0;\ + ((B *) A)->cbBitsMask = 0;\ + } + +//! @endcond + +/* ********************************************************************************************** +These functions are used for development and debugging and should be be includied in production code. +*********************************************************************************************** */ + +/** + \brief Debugging utility, used with valgrind to find uninitialized values. Not for use in production code. + \param buf memory area to examine ! + \param size length in bytes of buf! +*/ +int memprobe( + const void *buf, + size_t size + ){ + int sum=0; + char *ptr=(char *)buf; + for(;size;size--,ptr++){ sum += *ptr; } // read all bytes, trigger valgrind warning if any uninitialized + return(sum); +} + +/** + \brief Dump an EMFHANDLES structure. Not for use in production code. + \param string Text to output before dumping eht structure + \param handle Handle + \param eht EMFHANDLES structure to dump +*/ +void dumpeht( + char *string, + unsigned int *handle, + EMFHANDLES *eht + ){ + uint32_t i; + printf("%s\n",string); + printf("sptr: %d peak: %d top: %d\n",eht->sptr,eht->peak,eht->top); + if(handle){ + printf("handle: %d \n",*handle); + } + for(i=0;i<=5;i++){ + printf("table[%d]: %d\n",i,eht->table[i]); + } + for(i=1;i<=5;i++){ + printf("stack[%d]: %d\n",i,eht->stack[i]); + } +} + +/* ********************************************************************************************** +These functions are used for Image conversions and other +utility operations. Character type conversions are in uemf_utf.c +*********************************************************************************************** */ + +/** + \brief Make up an approximate dx array to pass to emrtext_set(), based on character height and weight. + + Take abs. value of character height, get width by multiplying by 0.6, and correct weight + approximately, with formula (measured on screen for one text line of Arial). + Caller is responsible for free() on the returned pointer. + + \return pointer to dx array + \param height character height (absolute value will be used) + \param weight LF_Weight Enumeration (character weight) + \param members Number of entries to put into dx + +*/ +uint32_t *dx_set( + int32_t height, + uint32_t weight, + uint32_t members + ){ + uint32_t i, width, *dx; + dx = (uint32_t *) malloc(members * sizeof(uint32_t)); + if(dx){ + if(U_FW_DONTCARE == weight)weight=U_FW_NORMAL; + width = (uint32_t) U_ROUND(((float) (height > 0 ? height : -height)) * 0.6 * (0.00024*(float) weight + 0.904)); + for ( i = 0; i < members; i++ ){ dx[i] = width; } + } + return(dx); +} + +/** + \brief Look up the properties (a bit map) of a type of EMR record. + Bits that may be set are defined in "Draw Properties" in uemf.h, they are U_DRAW_NOTEMPTY, etc.. + + \return bitmap of EMR record properties, or U_EMR_INVALID on error or release of all memory + \param type EMR record type. If U_EMR_INVALID release memory. (There is no U_EMR_INVALID EMR record type) + +*/ +uint32_t emr_properties(uint32_t type){ + static uint32_t *table=NULL; + uint32_t result = U_EMR_INVALID; // initialized to indicate an error (on a lookup) or nothing (on a memory release) + if(type == U_EMR_INVALID){ + if(table)free(table); + table=NULL; + } + else if(type>=1 && type<U_EMR_MAX){ + if(!table){ + table = (uint32_t *) malloc(sizeof(uint32_t)*(1 + U_EMR_MAX)); + if(!table)return(result); + // 0x80 0x40 0x20 0x10 0x08 0x04 0x02 0x01 + // Path properties (U_DRAW_*) TEXT ALTERS ONLYTO VISIBLE + // PATH FORCE CLOSED NOTEMPTY + table[ 0] = 0x00; // Does not map to any EMR record + table[ 1] = 0x80; // U_EMRHEADER 1 0 0 0 0 0 0 0 + table[ 2] = 0x83; // U_EMRPOLYBEZIER 1 0 0 0 0 0 1 1 + table[ 3] = 0x87; // U_EMRPOLYGON 1 0 0 0 0 1 1 1 + table[ 4] = 0x83; // U_EMRPOLYLINE 1 0 0 0 0 0 1 1 + table[ 5] = 0x8B; // U_EMRPOLYBEZIERTO 1 0 0 0 1 0 1 1 + table[ 6] = 0x8B; // U_EMRPOLYLINETO 1 0 0 0 1 0 1 1 + table[ 7] = 0x83; // U_EMRPOLYPOLYLINE 1 0 0 0 0 0 1 1 + table[ 8] = 0x87; // U_EMRPOLYPOLYGON 1 0 0 0 0 1 1 1 + table[ 9] = 0xA0; // U_EMRSETWINDOWEXTEX 1 0 1 0 0 0 0 0 + table[ 10] = 0xA0; // U_EMRSETWINDOWORGEX 1 0 1 0 0 0 0 0 + table[ 11] = 0xA0; // U_EMRSETVIEWPORTEXTEX 1 0 1 0 0 0 0 0 + table[ 12] = 0xA0; // U_EMRSETVIEWPORTORGEX 1 0 1 0 0 0 0 0 + table[ 13] = 0xA0; // U_EMRSETBRUSHORGEX 1 0 1 0 0 0 0 0 + table[ 14] = 0x82; // U_EMREOF 1 0 1 0 0 0 0 0 Force out any pending draw + table[ 15] = 0x82; // U_EMRSETPIXELV 1 0 0 0 0 0 1 0 + table[ 16] = 0xA0; // U_EMRSETMAPPERFLAGS 1 0 1 0 0 0 0 0 + table[ 17] = 0xA0; // U_EMRSETMAPMODE 1 0 1 0 0 0 0 0 + table[ 18] = 0x20; // U_EMRSETBKMODE 0 0 1 0 0 0 0 0 + table[ 19] = 0xA0; // U_EMRSETPOLYFILLMODE 1 0 1 0 0 0 0 0 + table[ 20] = 0xA0; // U_EMRSETROP2 1 0 1 0 0 0 0 0 + table[ 21] = 0xA0; // U_EMRSETSTRETCHBLTMODE 1 0 1 0 0 0 0 0 + table[ 22] = 0x20; // U_EMRSETTEXTALIGN 0 0 1 0 0 0 0 0 + table[ 23] = 0xA0; // U_EMRSETCOLORADJUSTMENT 1 0 1 0 0 0 0 0 + table[ 24] = 0x20; // U_EMRSETTEXTCOLOR 0 0 1 0 0 0 0 0 + table[ 25] = 0x20; // U_EMRSETBKCOLOR 0 0 1 0 0 0 0 0 + table[ 26] = 0xA0; // U_EMROFFSETCLIPRGN 1 0 1 0 0 0 0 0 + table[ 27] = 0x89; // U_EMRMOVETOEX 1 0 0 0 1 0 0 1 + table[ 28] = 0xA0; // U_EMRSETMETARGN 1 0 1 0 0 0 0 0 + table[ 29] = 0xA0; // U_EMREXCLUDECLIPRECT 1 0 1 0 0 0 0 0 + table[ 30] = 0xA0; // U_EMRINTERSECTCLIPRECT 1 0 1 0 0 0 0 0 + table[ 31] = 0xA0; // U_EMRSCALEVIEWPORTEXTEX 1 0 1 0 0 0 0 0 + table[ 32] = 0xA0; // U_EMRSCALEWINDOWEXTEX 1 0 1 0 0 0 0 0 + table[ 33] = 0xA0; // U_EMRSAVEDC 1 0 1 0 0 0 0 0 + table[ 34] = 0xA0; // U_EMRRESTOREDC 1 0 1 0 0 0 0 0 + table[ 35] = 0xA0; // U_EMRSETWORLDTRANSFORM 1 0 1 0 0 0 0 0 + table[ 36] = 0xA0; // U_EMRMODIFYWORLDTRANSFORM 1 0 1 0 0 0 0 0 + table[ 37] = 0x20; // U_EMRSELECTOBJECT 0 0 1 0 0 0 0 0 + table[ 38] = 0x20; // U_EMRCREATEPEN 0 0 1 0 0 0 0 0 + table[ 39] = 0x20; // U_EMRCREATEBRUSHINDIRECT 0 0 1 0 0 0 0 0 + table[ 40] = 0x20; // U_EMRDELETEOBJECT 0 0 1 0 0 0 0 0 + table[ 41] = 0x83; // U_EMRANGLEARC 1 0 0 0 0 0 1 1 + table[ 42] = 0x87; // U_EMRELLIPSE 1 0 0 0 0 1 1 1 + table[ 43] = 0x87; // U_EMRRECTANGLE 1 0 0 0 0 1 1 1 + table[ 44] = 0x87; // U_EMRROUNDRECT 1 0 0 0 0 1 1 1 + table[ 45] = 0x83; // U_EMRARC 1 0 0 0 0 0 1 1 + table[ 46] = 0x87; // U_EMRCHORD 1 0 0 0 0 1 1 1 + table[ 47] = 0x87; // U_EMRPIE 1 0 0 0 0 1 1 1 + table[ 48] = 0xA0; // U_EMRSELECTPALETTE 1 0 1 0 0 0 0 0 + table[ 49] = 0xA0; // U_EMRCREATEPALETTE 1 0 1 0 0 0 0 0 + table[ 50] = 0xA0; // U_EMRSETPALETTEENTRIES 1 0 1 0 0 0 0 0 + table[ 51] = 0xA0; // U_EMRRESIZEPALETTE 1 0 1 0 0 0 0 0 + table[ 52] = 0xA0; // U_EMRREALIZEPALETTE 1 0 1 0 0 0 0 0 + table[ 53] = 0x82; // U_EMREXTFLOODFILL 1 0 0 0 0 0 1 0 + table[ 54] = 0x8B; // U_EMRLINETO 1 0 0 0 1 0 1 1 + table[ 55] = 0x8B; // U_EMRARCTO 1 0 0 0 1 0 1 1 + table[ 56] = 0x83; // U_EMRPOLYDRAW 1 0 0 0 0 0 1 1 + table[ 57] = 0xA0; // U_EMRSETARCDIRECTION 1 0 1 0 0 0 0 0 + table[ 58] = 0xA0; // U_EMRSETMITERLIMIT 1 0 1 0 0 0 0 0 + table[ 59] = 0xE0; // U_EMRBEGINPATH 1 1 1 0 0 0 0 0 + table[ 60] = 0x80; // U_EMRENDPATH 1 0 0 0 0 0 0 0 + table[ 61] = 0x84; // U_EMRCLOSEFIGURE 1 0 0 0 0 1 0 0 + table[ 62] = 0x94; // U_EMRFILLPATH 1 0 0 1 0 1 0 0 + table[ 63] = 0x94; // U_EMRSTROKEANDFILLPATH 1 0 0 1 0 1 0 0 + table[ 64] = 0x90; // U_EMRSTROKEPATH 1 0 0 1 0 0 0 0 + table[ 65] = 0xA0; // U_EMRFLATTENPATH 1 0 1 0 0 0 0 0 + table[ 66] = 0xA0; // U_EMRWIDENPATH 1 0 1 0 0 0 0 0 + table[ 67] = 0x80; // U_EMRSELECTCLIPPATH 1 0 0 0 0 0 0 0 consumes the path, draws nothing + table[ 68] = 0xA0; // U_EMRABORTPATH 1 0 1 0 0 0 0 0 + table[ 69] = 0xA0; // U_EMRUNDEF69 1 0 1 0 0 0 0 0 + table[ 70] = 0x00; // U_EMRCOMMENT 0 0 0 0 0 0 0 0 + table[ 71] = 0x82; // U_EMRFILLRGN 1 0 0 0 0 0 1 0 + table[ 72] = 0x82; // U_EMRFRAMERGN 1 0 0 0 0 0 1 0 + table[ 73] = 0x82; // U_EMRINVERTRGN 1 0 0 0 0 0 1 0 + table[ 74] = 0x82; // U_EMRPAINTRGN 1 0 0 0 0 0 1 0 + table[ 75] = 0xA0; // U_EMREXTSELECTCLIPRGN 1 0 1 0 0 0 0 0 + table[ 76] = 0x82; // U_EMRBITBLT 1 0 0 0 0 0 1 0 + table[ 77] = 0x82; // U_EMRSTRETCHBLT 1 0 0 0 0 0 1 0 + table[ 78] = 0x82; // U_EMRMASKBLT 1 0 0 0 0 0 1 0 + table[ 79] = 0x82; // U_EMRPLGBLT 1 0 0 0 0 0 1 0 + table[ 80] = 0xA0; // U_EMRSETDIBITSTODEVICE 1 0 1 0 0 0 0 0 + table[ 81] = 0xA0; // U_EMRSTRETCHDIBITS 1 0 1 0 0 0 0 0 + table[ 82] = 0x20; // U_EMREXTCREATEFONTINDIRECTW 0 0 1 0 0 0 0 0 + table[ 83] = 0x02; // U_EMREXTTEXTOUTA 0 0 0 0 0 0 1 0 + table[ 84] = 0x02; // U_EMREXTTEXTOUTW 0 0 0 0 0 0 1 0 + table[ 85] = 0x83; // U_EMRPOLYBEZIER16 1 0 0 0 0 0 1 1 + table[ 86] = 0x83; // U_EMRPOLYGON16 1 0 0 0 0 0 1 1 + table[ 87] = 0x83; // U_EMRPOLYLINE16 1 0 0 0 0 0 1 1 + table[ 88] = 0x8B; // U_EMRPOLYBEZIERTO16 1 0 0 0 1 0 1 1 + table[ 89] = 0x8B; // U_EMRPOLYLINETO16 1 0 0 0 1 0 1 1 + table[ 90] = 0x83; // U_EMRPOLYPOLYLINE16 1 0 0 0 0 0 1 1 + table[ 91] = 0x87; // U_EMRPOLYPOLYGON16 1 0 0 0 0 1 1 1 + table[ 92] = 0x83; // U_EMRPOLYDRAW16 1 0 0 0 0 0 1 1 + table[ 93] = 0x80; // U_EMRCREATEMONOBRUSH 1 0 0 0 0 0 0 0 Not selected yet, so no change in drawing conditions + table[ 94] = 0x80; // U_EMRCREATEDIBPATTERNBRUSHPT 1 0 0 0 0 0 0 0 " + table[ 95] = 0x00; // U_EMREXTCREATEPEN 0 0 0 0 0 0 0 0 " + table[ 96] = 0x02; // U_EMRPOLYTEXTOUTA 0 0 0 0 0 0 1 0 + table[ 97] = 0x02; // U_EMRPOLYTEXTOUTW 0 0 0 0 0 0 1 0 + table[ 98] = 0xA0; // U_EMRSETICMMODE 1 0 1 0 0 0 0 0 + table[ 99] = 0xA0; // U_EMRCREATECOLORSPACE 1 0 1 0 0 0 0 0 + table[100] = 0xA0; // U_EMRSETCOLORSPACE 1 0 1 0 0 0 0 0 + table[101] = 0xA0; // U_EMRDELETECOLORSPACE 1 0 1 0 0 0 0 0 + table[102] = 0xA0; // U_EMRGLSRECORD 1 0 1 0 0 0 0 0 + table[103] = 0xA0; // U_EMRGLSBOUNDEDRECORD 1 0 1 0 0 0 0 0 + table[104] = 0xA0; // U_EMRPIXELFORMAT 1 0 1 0 0 0 0 0 + table[105] = 0xA0; // U_EMRDRAWESCAPE 1 0 1 0 0 0 0 0 + table[106] = 0xA0; // U_EMREXTESCAPE 1 0 1 0 0 0 0 0 + table[107] = 0xA0; // U_EMRUNDEF107 1 0 1 0 0 0 0 0 + table[108] = 0x02; // U_EMRSMALLTEXTOUT 0 0 0 0 0 0 1 0 + table[109] = 0xA0; // U_EMRFORCEUFIMAPPING 1 0 1 0 0 0 0 0 + table[110] = 0xA0; // U_EMRNAMEDESCAPE 1 0 1 0 0 0 0 0 + table[111] = 0xA0; // U_EMRCOLORCORRECTPALETTE 1 0 1 0 0 0 0 0 + table[112] = 0xA0; // U_EMRSETICMPROFILEA 1 0 1 0 0 0 0 0 + table[113] = 0xA0; // U_EMRSETICMPROFILEW 1 0 1 0 0 0 0 0 + table[114] = 0x82; // U_EMRALPHABLEND 1 0 0 0 0 0 1 0 + table[115] = 0xA0; // U_EMRSETLAYOUT 1 0 1 0 0 0 0 0 + table[116] = 0x82; // U_EMRTRANSPARENTBLT 1 0 0 0 0 0 1 0 + table[117] = 0xA0; // U_EMRUNDEF117 1 0 1 0 0 0 0 0 + table[118] = 0x82; // U_EMRGRADIENTFILL 1 0 1 0 0 0 1 0 + table[119] = 0xA0; // U_EMRSETLINKEDUFIS 1 0 1 0 0 0 0 0 + table[120] = 0x20; // U_EMRSETTEXTJUSTIFICATION 0 0 1 0 0 0 0 0 + table[121] = 0xA0; // U_EMRCOLORMATCHTOTARGETW 1 0 1 0 0 0 0 0 + table[122] = 0xA0; // U_EMRCREATECOLORSPACEW 1 0 1 0 0 0 0 0 + } + result = table[type]; + } + return(result); +} + +/** + \brief Derive from bounding rect, start and end radials, for arc, chord, or pie, the center, start, and end points, and the bounding rectangle. + + \return 0 on success, other values on errors. + \param rclBox bounding rectangle + \param ArcStart start of arc + \param ArcEnd end of arc + \param f1 1 if rotation angle >= 180, else 0 + \param f2 Rotation direction, 1 if counter clockwise, else 0 + \param center Center coordinates + \param start Start coordinates (point on the ellipse defined by rect) + \param end End coordinates (point on the ellipse defined by rect) + \param size W,H of the x,y axes of the bounding rectangle. +*/ +int emr_arc_points_common( + PU_RECTL rclBox, + PU_POINTL ArcStart, + PU_POINTL ArcEnd, + int *f1, + int f2, + PU_PAIRF center, + PU_PAIRF start, + PU_PAIRF end, + PU_PAIRF size + ){ + U_PAIRF estart; // EMF start position, defines a radial + U_PAIRF eend; // EMF end position, defines a radial + U_PAIRF vec_estart; // define a unit vector from the center to estart + U_PAIRF vec_eend; // define a unit vector from the center to eend + U_PAIRF radii; // x,y radii of ellipse + U_PAIRF ratio; // intermediate value + float scale, cross; + center->x = ((float)(rclBox->left + rclBox->right ))/2.0; + center->y = ((float)(rclBox->top + rclBox->bottom))/2.0; + size->x = (float)(rclBox->right - rclBox->left ); + size->y = (float)(rclBox->bottom - rclBox->top ); + estart.x = (float)(ArcStart->x); + estart.y = (float)(ArcStart->y); + eend.x = (float)(ArcEnd->x); + eend.y = (float)(ArcEnd->y); + radii.x = size->x/2.0; + radii.y = size->y/2.0; + + vec_estart.x = (estart.x - center->x); // initial vector, not unit length + vec_estart.y = (estart.y - center->y); + scale = sqrt(vec_estart.x*vec_estart.x + vec_estart.y*vec_estart.y); + if(!scale)return(1); // bogus record, has start at center + vec_estart.x /= scale; // now a unit vector + vec_estart.y /= scale; + + vec_eend.x = (eend.x - center->x); // initial vector, not unit length + vec_eend.y = (eend.y - center->y); + scale = sqrt(vec_eend.x*vec_eend.x + vec_eend.y*vec_eend.y); + if(!scale)return(2); // bogus record, has end at center + vec_eend.x /= scale; // now a unit vector + vec_eend.y /= scale; + + + // Find the intersection of the vectors with the ellipse. With no loss of generality + // we can translate the ellipse to the origin, then we just need to find tu (t a factor, u the unit vector) + // that also satisfies (x/Rx)^2 + (y/Ry)^2 = 1. x is t*(ux), y is t*(uy), where ux,uy are the x,y components + // of the unit vector. Substituting gives: + // (t*(ux)/Rx)^2 + (t*(uy)/Ry)^2 = 1 + // t^2 = 1/( (ux/Rx)^2 + (uy/Ry)^2 ) + // t = sqrt(1/( (ux/Rx)^2 + (uy/Ry)^2 )) + + ratio.x = vec_estart.x/radii.x; + ratio.y = vec_estart.y/radii.y; + ratio.x *= ratio.x; // we only use the square + ratio.y *= ratio.y; + scale = 1.0/sqrt(ratio.x + ratio.y); + start->x = center->x + scale * vec_estart.x; + start->y = center->y + scale * vec_estart.y; + + ratio.x = vec_eend.x/radii.x; + ratio.y = vec_eend.y/radii.y; + ratio.x *= ratio.x; // we only use the square + ratio.y *= ratio.y; + scale = 1.0/sqrt(ratio.x + ratio.y); + end->x = center->x + scale * vec_eend.x; + end->y = center->y + scale * vec_eend.y; + + //lastly figure out if the swept angle is >180 degrees or not, based on the direction of rotation + //and the two unit vectors. + + cross = vec_estart.x * vec_eend.y - vec_estart.y * vec_eend.x; + if(!f2){ // counter clockwise rotation + if(cross >=0){ *f1 = 1; } + else { *f1 = 0; } + } + else { + if(cross >=0){ *f1 = 0; } + else { *f1 = 1; } + } + + + return(0); +} + +/** + \brief Derive from an EMF arc, chord, or pie the center, start, and end points, and the bounding rectangle. + + \return 0 on success, other values on errors. + \param record U_EMRPIE, U_EMRCHORD, or _EMRARC record + \param f1 1 if rotation angle >= 180, else 0 + \param f2 Rotation direction, 1 if counter clockwise, else 0 + \param center Center coordinates + \param start Start coordinates (point on the ellipse defined by rect) + \param end End coordinates (point on the ellipse defined by rect) + \param size W,H of the x,y axes of the bounding rectangle. +*/ +int emr_arc_points( + PU_ENHMETARECORD record, + int *f1, + int f2, + PU_PAIRF center, + PU_PAIRF start, + PU_PAIRF end, + PU_PAIRF size + ){ + PU_EMRARC pEmr = (PU_EMRARC) (record); + return emr_arc_points_common(&(pEmr->rclBox), &(pEmr->ptlStart), &(pEmr->ptlEnd), f1, f2, center, start, end, size ); +} + +/** + \brief Convert a U_RGBA 32 bit pixmap to one of many different types of DIB pixmaps. + + Conversions to formats using color tables assume that the color table can hold every color + in the input image. If that assumption is false then the conversion will fail. Conversion + from 8 bit color to N bit colors (N<8) do so by shifting the appropriate number of bits. + + \return 0 on success, other values on errors. + \param px DIB pixel array + \param cbPx DIB pixel array size in bytes + \param ct DIB color table + \param numCt DIB color table number of entries + \param rgba_px U_RGBA pixel array (32 bits) + \param w Width of pixel array + \param h Height of pixel array + \param stride Row stride of input pixel array in bytes + \param colortype DIB BitCount Enumeration + \param use_ct If true use color table (only for 1-16 bit DIBs). + \param invert If DIB rows are in opposite order from RGBA rows +*/ +int RGBA_to_DIB( + char **px, + uint32_t *cbPx, + PU_RGBQUAD *ct, + int *numCt, + const char *rgba_px, + int w, + int h, + int stride, + uint32_t colortype, + int use_ct, + int invert + ){ + int bs; + int pad; + int i,j,k; + int istart, iend, iinc; + uint8_t r,g,b,a,tmp8; + char *pxptr; + const char *rptr; + int found; + int usedbytes; + U_RGBQUAD color; + PU_RGBQUAD lct; + int32_t index; + + *px=NULL; + *ct=NULL; + *numCt=0; + *cbPx=0; + // sanity checking + if(!w || !h || !stride || !colortype || !rgba_px)return(1); + if(use_ct && colortype >= U_BCBM_COLOR16)return(2); //color tables not used above 16 bit pixels + if(!use_ct && colortype < U_BCBM_COLOR16)return(3); //color tables mandatory for < 16 bit + + bs = colortype/8; + if(bs<1){ + usedbytes = (w*colortype + 7)/8; // width of line in fully and partially occupied bytes + } + else { + usedbytes = w*bs; + } + pad = UP4(usedbytes) - usedbytes; // DIB rows must be aligned on 4 byte boundaries, they are padded at the end to accomplish this.; + *cbPx = h * (usedbytes + pad); // Rows must start on a 4 byte boundary! + *px = (char *) malloc(*cbPx); + if(!px)return(4); + if(use_ct){ + *numCt = 1<< colortype; + if(*numCt >w*h)*numCt=w*h; + lct = (PU_RGBQUAD) malloc(*numCt * sizeof(U_RGBQUAD)); + if(!lct)return(5); + *ct = lct; + } + + if(invert){ + istart = h-1; + iend = -1; + iinc = -1; + } + else { + istart = 0; + iend = h; + iinc = 1; + } + + found = 0; + tmp8 = 0; + pxptr = *px; + for(i=istart; i!=iend; i+=iinc){ + rptr= rgba_px + i*stride; + for(j=0; j<w; j++){ + r = *rptr++; + g = *rptr++; + b = *rptr++; + a = *rptr++; + if(use_ct){ + color = U_BGRA(r,g,b,a); // color has order in memory: b,g,r,a, same as EMF+ ARGB + index = -1; + for(lct = *ct, k=0; k<found; k++,lct++){ // Is this color in the table (VERY inefficient if there are a lot of colors!!!) + if(*(uint32_t *)lct != *(uint32_t *) &color)continue; + index =k; + break; + } + if(index==-1){ // add a color + found++; + if(found > *numCt){ // More colors found than are supported by the color table + free(*ct); + free(*px); + *numCt=0; + *cbPx=0; + return(6); + } + index = found - 1; + *lct = color; + } + switch(colortype){ + case U_BCBM_MONOCHROME: // 2 colors. bmiColors array has two entries + tmp8 = tmp8 >> 1; // This seems wrong, as it fills from the top of each byte. But it works. + tmp8 |= index << 7; + if(!((j+1) % 8)){ + *pxptr++ = tmp8; + tmp8 = 0; + } + break; + case U_BCBM_COLOR4: // 2^4 colors. bmiColors array has 16 entries + tmp8 = tmp8 << 4; + tmp8 |= index; + if(!((j+1) % 2)){ + *pxptr++ = tmp8; + tmp8 = 0; + } + break; + case U_BCBM_COLOR8: // 2^8 colors. bmiColors array has 256 entries + tmp8 = index; + *pxptr++ = tmp8; + break; + case U_BCBM_COLOR16: // 2^16 colors. (Several different color methods)) + case U_BCBM_COLOR24: // 2^24 colors. bmiColors is not used. Pixels are U_RGBTRIPLE. + case U_BCBM_COLOR32: // 2^32 colors. bmiColors is not used. Pixels are U_RGBQUAD. + case U_BCBM_EXPLICIT: // Derinved from JPG or PNG compressed image or ? + default: + return(7); // This should not be possible, but might happen with memory corruption + } + } + else { + switch(colortype){ + case U_BCBM_COLOR16: // 2^16 colors. (Several different color methods)) + b /= 8; g /= 8; r /= 8; + // Do it in this way so that the bytes are always stored Little Endian + tmp8 = b; + tmp8 |= g<<5; // least significant 3 bits of green + *pxptr++ = tmp8; + tmp8 = g>>3; // most significant 2 bits of green (there are only 5 bits of data) + tmp8 |= r<<2; + *pxptr++ = tmp8; + break; + case U_BCBM_COLOR24: // 2^24 colors. bmiColors is not used. Pixels are U_RGBTRIPLE. + *pxptr++ = b; + *pxptr++ = g; + *pxptr++ = r; + break; + case U_BCBM_COLOR32: // 2^32 colors. bmiColors is not used. Pixels are U_RGBQUAD. + *pxptr++ = b; + *pxptr++ = g; + *pxptr++ = r; + *pxptr++ = a; + break; + case U_BCBM_MONOCHROME: // 2 colors. bmiColors array has two entries + case U_BCBM_COLOR4: // 2^4 colors. bmiColors array has 16 entries + case U_BCBM_COLOR8: // 2^8 colors. bmiColors array has 256 entries + case U_BCBM_EXPLICIT: // Derinved from JPG or PNG compressed image or ? + default: + return(7); // This should not be possible, but might happen with memory corruption + } + } + } + if( use_ct && colortype == U_BCBM_MONOCHROME && (j % 8) ){ + *pxptr++ = tmp8; // Write last few indices + tmp8 = 0; + } + if( use_ct && colortype == U_BCBM_COLOR4 && (j % 2) ){ + *pxptr++ = tmp8; // Write last few indices + tmp8 = 0; + } + if(pad){ + memset(pxptr,0,pad); // not strictly necessary, but set all bytes so that we can find important unset ones with valgrind + pxptr += pad; + } + } + return(0); +} + +/** + \brief Get the actual number of colors in the color table from the BitMapInfoHeader. + \return Number of entries in the color table. + \param Bmih char * pointer to the U_BITMAPINFOHEADER + + BitmapInfoHeader may list 0 for some types which implies the maximum value. + If the image is big enough, that is set by the bit count, as in 256 for an 8 + bit image. + If the image is smaller it is set by width * height. + Note, this may be called by WMF code, so it is not safe to assume the data is aligned. +*/ +int get_real_color_count( + const char *Bmih + ){ + int Colors, BitCount, Width, Height; + uint32_t utmp4; + uint16_t utmp2; + int32_t tmp4; + char *cBmih = (char *) Bmih; + memcpy(&utmp4, cBmih + offsetof(U_BITMAPINFOHEADER,biClrUsed), 4); Colors = utmp4; + memcpy(&utmp2, cBmih + offsetof(U_BITMAPINFOHEADER,biBitCount), 2); BitCount = utmp2; + memcpy(&tmp4, cBmih + offsetof(U_BITMAPINFOHEADER,biWidth), 4); Width = tmp4; + memcpy(&tmp4, cBmih + offsetof(U_BITMAPINFOHEADER,biHeight), 4); Height = tmp4; + return(get_real_color_icount(Colors, BitCount, Width, Height)); +} + +/** + \brief Get the actual number of colors in the color table from the ClrUsed, BitCount, Width, and Height. + \return Number of entries in the color table. + \param Colors Number of colors in the table. + \param BitCount BitCount Enumeration + \param Width bitmap width + \param Height bitmap height +*/ +int get_real_color_icount( + int Colors, + int BitCount, + int Width, + int Height + ){ + int area = Width * Height; + if(area < 0){ area = -area; } /* Height might be negative */ + if(Colors == 0){ + if( BitCount == U_BCBM_MONOCHROME){ Colors = 2; } + else if(BitCount == U_BCBM_COLOR4 ){ Colors = 16; } + else if(BitCount == U_BCBM_COLOR8 ){ Colors = 256; } + if(Colors > area){ Colors = area; } + } + return(Colors); +} + + +/** + \brief Get the DIB parameters from the BMI of the record for use by DBI_to_RGBA() + + \return BI_Compression Enumeration. For anything other than U_BI_RGB values other than px may not be valid. + \param record pointer to EMR record that has a U_BITMAPINFO and bitmap + \param offBitsSrc Offset to the bitmap + \param offBmiSrc Offset to the U_BITMAPINFO + \param px pointer to DIB pixel array in pEmr + \param ct pointer to DIB color table in pEmr + \param numCt DIB color table number of entries, for PNG or JPG returns the number of bytes in the image + \param width Width of pixel array + \param height Height of pixel array (always returned as a positive number) + \param colortype DIB BitCount Enumeration + \param invert If DIB rows are in opposite order from RGBA rows +*/ +int get_DIB_params( + const char *record, + uint32_t offBitsSrc, + uint32_t offBmiSrc, + const char **px, + const U_RGBQUAD **ct, + uint32_t *numCt, + uint32_t *width, + uint32_t *height, + uint32_t *colortype, + uint32_t *invert + ){ + uint32_t bic; + PU_BITMAPINFO Bmi = (PU_BITMAPINFO)(record + offBmiSrc); + PU_BITMAPINFOHEADER Bmih = &(Bmi->bmiHeader); + /* if biCompression is not U_BI_RGB some or all of the following might not hold real values */ + bic = Bmih->biCompression; + *width = Bmih->biWidth; + *colortype = Bmih->biBitCount; + if(Bmih->biHeight < 0){ + *height = -Bmih->biHeight; + *invert = 1; + } + else { + *height = Bmih->biHeight; + *invert = 0; + } + if(bic == U_BI_RGB){ + *numCt = get_real_color_count((const char *) Bmih); + if( numCt){ *ct = (PU_RGBQUAD) ((char *)Bmi + sizeof(U_BITMAPINFOHEADER)); } + else { *ct = NULL; } + } + else if(bic == U_BI_BITFIELDS){ /* to date only encountered once, for 32 bit, from PPT*/ + *numCt = 0; + *ct = NULL; + bic = U_BI_RGB; /* there seems to be no difference, at least for the 32 bit images */ + } + else { + *numCt = Bmih->biSizeImage; + *ct = NULL; + } + *px = record + offBitsSrc; + return(bic); +} + +/** + \brief Convert one of many different types of DIB pixmaps to an RGBA 32 bit pixmap. + + \return 0 on success, other values on errors. + \param px DIB pixel array + \param ct DIB color table + \param numCt DIB color table number of entries + \param rgba_px U_RGBA pixel array (32 bits), created by this routine, caller must free. + \param w Width of pixel array in the record + \param h Height of pixel array in the record + \param colortype DIB BitCount Enumeration + \param use_ct Kept for symmetry with RGBA_to_DIB, should be set to numCt + \param invert If DIB rows are in opposite order from RGBA rows +*/ +int DIB_to_RGBA( + const char *px, + const U_RGBQUAD *ct, + int numCt, + char **rgba_px, + int w, + int h, + uint32_t colortype, + int use_ct, + int invert + ){ + uint32_t cbRgba_px; + int stride; + int bs; + int pad; + int i,j; + int istart, iend, iinc; + uint8_t r,g,b,a,tmp8; + const char *pxptr; + char *rptr; + int usedbytes; + U_RGBQUAD color; + int32_t index; + + // sanity checking + if(!w || !h || !colortype || !px)return(1); + if(use_ct && colortype >= U_BCBM_COLOR16)return(2); //color tables not used above 16 bit pixels + if(!use_ct && colortype < U_BCBM_COLOR16)return(3); //color tables mandatory for < 16 bit + if(use_ct && !numCt)return(4); //color table not adequately described + + stride = w * 4; + cbRgba_px = stride * h; + bs = colortype/8; + if(bs<1){ + usedbytes = (w*colortype + 7)/8; // width of line in fully and partially occupied bytes + } + else { + usedbytes = w*bs; + } + pad = UP4(usedbytes) - usedbytes; // DIB rows must be aligned on 4 byte boundaries, they are padded at the end to accomplish this.; + *rgba_px = (char *) malloc(cbRgba_px); + if(!rgba_px)return(4); + + if(invert){ + istart = h-1; + iend = -1; + iinc = -1; + } + else { + istart = 0; + iend = h; + iinc = 1; + } + + pxptr = px; + tmp8 = 0; // silences a compiler warning, tmp8 always sets when j=0, so never used uninitialized + for(i=istart; i!=iend; i+=iinc){ + rptr= *rgba_px + i*stride; + for(j=0; j<w; j++){ + if(use_ct){ + switch(colortype){ + case U_BCBM_MONOCHROME: // 2 colors. bmiColors array has two entries + if(!(j % 8)){ tmp8 = *pxptr++; } + index = 0x80 & tmp8; // This seems wrong, as lowest position is top bit, but it works. + index = index >> 7; + tmp8 = tmp8 << 1; + break; + case U_BCBM_COLOR4: // 2^4 colors. bmiColors array has 16 entries + if(!(j % 2)){ tmp8 = *pxptr++; } + index = 0xF0 & tmp8; + index = index >> 4; + tmp8 = tmp8 << 4; + break; + case U_BCBM_COLOR8: // 2^8 colors. bmiColors array has 256 entries + index = (uint8_t) *pxptr++;; + break; + case U_BCBM_COLOR16: // 2^16 colors. (Several different color methods)) + case U_BCBM_COLOR24: // 2^24 colors. bmiColors is not used. Pixels are U_RGBTRIPLE. + case U_BCBM_COLOR32: // 2^32 colors. bmiColors is not used. Pixels are U_RGBQUAD. + case U_BCBM_EXPLICIT: // Derinved from JPG or PNG compressed image or ? + default: + return(7); // This should not be possible, but might happen with memory corruption + } + color = ct[index]; + b = U_BGRAGetB(color); + g = U_BGRAGetG(color); + r = U_BGRAGetR(color); + a = U_BGRAGetA(color); + } + else { + switch(colortype){ + case U_BCBM_COLOR16: // 2^16 colors. (Several different color methods)) + // Do it in this way because the bytes are always stored Little Endian + tmp8 = *pxptr++; + b = (0x1F & tmp8) <<3; // 5 bits of b into the top 5 of 8 + g = tmp8 >> 5; // least significant 3 bits of green + tmp8 = *pxptr++; + r = (0x7C & tmp8) << 1; // 5 bits of r into the top 5 of 8 + g |= (0x3 & tmp8) << 3; // most significant 2 bits of green (there are only 5 bits of data) + g = g << 3; // restore intensity (have lost 3 bits of accuracy) + a = 0; + break; + case U_BCBM_COLOR24: // 2^24 colors. bmiColors is not used. Pixels are U_RGBTRIPLE. + b = *pxptr++; + g = *pxptr++; + r = *pxptr++; + a = 0; + break; + case U_BCBM_COLOR32: // 2^32 colors. bmiColors is not used. Pixels are U_RGBQUAD. + b = *pxptr++; + g = *pxptr++; + r = *pxptr++; + a = *pxptr++; + break; + case U_BCBM_MONOCHROME: // 2 colors. bmiColors array has two entries + case U_BCBM_COLOR4: // 2^4 colors. bmiColors array has 16 entries + case U_BCBM_COLOR8: // 2^8 colors. bmiColors array has 256 entries + case U_BCBM_EXPLICIT: // Derinved from JPG or PNG compressed image or ? + default: + return(7); // This should not be possible, but might happen with memory corruption + } + } + *rptr++ = r; + *rptr++ = g; + *rptr++ = b; + *rptr++ = a; + } + for(j=0; j<pad; j++){ pxptr++; } // DIB rows are all 4 byte aligned + } + return(0); +} + +/** + \brief Extract a subset of an RGBA bitmap array. + Frees the incoming bitmap array IF a subset is extracted, otherwise it is left alone. + If the entire array is extracted it just returns the incoming pointer. + If the subset requested is partially outside of the bitmap the region is clipped to the + bitmap boundaries and extracted. This seems to be a (very) grey area in EMF files, and + even different Microsoft applications do not always do the same thing. For instance, + XP Preview gives some different images for EMR_BITBLT records than does the "import image" + (but not unpacked) view in PowerPoint. Since all of these states are probably best viewed + as undefined or errors we can only try to do something reasonable and not blow up when + encountering one. + + \return Pointer to the sub array on success, NULL otherwise. + \param rgba_px U_RGBA pixel array (32 bits), created by this routine, caller must free. + \param w Width of pixel array in the record + \param h Height of pixel array in the record + \param sl start left position in the pixel array in the record to start extracting + \param st start top position in the pixel array in the record to start extracting + \param eew Width of pixel array to extract + \param eeh Height of pixel array to extract +*/ +char *RGBA_to_RGBA( + char *rgba_px, + int w, + int h, + int sl, + int st, + int *eew, + int *eeh + ){ + int i; + char *sub; + char *sptr; + int ew = *eew; + int eh = *eeh; + + // sanity checking + if(w<=0 || h<=0 || ew<=0 || eh<=0 || !rgba_px)return(NULL); + + if(sl>w || st >h)return(NULL); // This is hopeless, the start point is outside of the array. + if(sl<0){ + if(sl+ew<=0)return(NULL); // This is hopeless, the start point is outside of the array. + ew += sl; + sl = 0; + } + if(st<0){ + if(st+eh<=0)return(NULL); // This is hopeless, the start point is outside of the array. + eh += st; + st = 0; + } + if(sl+ew > w)ew=w-sl; + if(st+eh > h)eh=h-st; + if(!sl && !st && (ew == w) && (eh == h)){ + sub = rgba_px; + } + else { + sptr = sub = malloc(ew*eh*4); + if(!sub)return(NULL); + for(i=st; i<st+eh; i++){ + memcpy(sptr,rgba_px + i*w*4 + sl*4,4*ew); + sptr += 4*ew; + } + free(rgba_px); + } + *eeh = eh; + *eew = ew; + return(sub); + } + + +/* ********************************************************************************************** +These functions are for setting up, appending to, and then tearing down an EMF structure, including +writing the final data structure out to a file. +*********************************************************************************************** */ + +/** + \brief Duplicate an EMR record. + \param emr record to duplicate +*/ +char *emr_dup( + const char *emr + ){ + char *dup; + int irecsize; + + if(!emr)return(NULL); + irecsize = ((PU_EMR)emr)->nSize; + dup=malloc(irecsize); + if(dup){ memcpy(dup,emr,irecsize); } + return(dup); +} + + +/** + \brief Start constructing an emf in memory. Supply the file name and initial size. + \return 0 for success, >=0 for failure. + \param name EMF filename (will be opened) + \param initsize Initialize EMF in memory to hold this many bytes + \param chunksize When needed increase EMF in memory by this number of bytes + \param et EMF in memory + + +*/ +int emf_start( + const char *name, + const uint32_t initsize, + const uint32_t chunksize, + EMFTRACK **et + ){ + FILE *fp; + EMFTRACK *etl=NULL; + + if(initsize < 1)return(1); + if(chunksize < 1)return(2); + if(!name)return(3); + etl = (EMFTRACK *) malloc(sizeof(EMFTRACK)); + if(!etl)return(4); + etl->buf = malloc(initsize); // no need to zero the memory + if(!etl->buf){ + free(etl); + return(5); + } + fp=emf_fopen(name,U_WRITE); + if(!fp){ + free(etl->buf); + free(etl); + return(6); + } + etl->fp = fp; + etl->allocated = initsize; + etl->used = 0; + etl->records = 0; + etl->PalEntries = 0; + etl->chunk = chunksize; + *et=etl; + return(0); +} + +/** + \brief Finalize the emf in memory and write it to the file. + \return 0 on success, >=1 on failure + \param et EMF in memory + \param eht EMF handle table (peak handle number needed) +*/ +int emf_finish( + EMFTRACK *et, + EMFHANDLES *eht + ){ + U_EMRHEADER *record; + + if(!et->fp)return(1); // This could happen if something stomps on memory, otherwise should be caught in emf_start + + // Set the header fields which were unknown up until this point + + record = (U_EMRHEADER *)et->buf; + record->nBytes = et->used; + record->nRecords = et->records; + record->nHandles = eht->peak + 1; + record->nPalEntries = et->PalEntries; + +#if U_BYTE_SWAP + //This is a Big Endian machine, EMF data must be Little Endian + U_emf_endian(et->buf,et->used,1); +#endif + + if(1 != fwrite(et->buf,et->used,1,et->fp))return(2); + (void) fclose(et->fp); + et->fp=NULL; + return(0); +} + +/** + \brief Release memory for an emf structure in memory. Call this after emf_finish(). + \return 0 on success, >=1 on failure + \param et EMF in memory +*/ +int emf_free( + EMFTRACK **et + ){ + EMFTRACK *etl; + if(!et)return(1); + etl=*et; + if(!etl)return(2); + free(etl->buf); + free(etl); + *et=NULL; + return(0); +} + +/** + \brief wrapper for fopen, works on any platform + \return 0 on success, >=1 on failure + \param filename file to open (either ASCII or UTF-8) + \param mode U_READ or U_WRITE (these map to "rb" and "wb") +*/ +FILE *emf_fopen( + const char *filename, + const int mode + ){ + FILE *fp = NULL; +#ifdef WIN32 + uint16_t *fn16; + uint16_t *md16; + if(mode == U_READ){ md16 = U_Utf8ToUtf16le("rb", 0, NULL); } + else { md16 = U_Utf8ToUtf16le("wb", 0, NULL); } + fn16 = U_Utf8ToUtf16le(filename, 0, NULL); + fp = _wfopen(fn16,md16); + free(fn16); + free(md16); +#else + if(mode == U_READ){ fp = fopen(filename,"rb"); } + else { fp = fopen(filename,"wb"); } +#endif + return(fp); +} + +/** + \brief Retrieve contents of an EMF file by name. + \return 0 on success, >=1 on failure + \param filename Name of file to open, including the path + \param contents Contents of the file. Buffer must be free()'d by caller. + \param length Number of bytes in Contents +*/ +int emf_readdata( + const char *filename, + char **contents, + size_t *length + ){ + FILE *fp; + int status=0; + + *contents=NULL; + fp=emf_fopen(filename,U_READ); + if(!fp){ status = 1; } + else { + // read the entire file into memory + fseek(fp, 0, SEEK_END); // move to end + *length = ftell(fp); + rewind(fp); + *contents = (char *) malloc(*length); + if(!*contents){ + status = 2; + } + else { + size_t inbytes = fread(*contents,*length,1,fp); + if(inbytes != 1){ + free(*contents); + status = 3; + } + else { +#if U_BYTE_SWAP + //This is a Big Endian machine, EMF data is Little Endian + U_emf_endian(*contents,*length,0); // LE to BE +#endif + } + } + fclose(fp); + } + return(status); +} + + +/** + \brief Append an EMF record to an emf in memory. This may reallocate buf memory. + \return 0 for success, >=1 for failure. + \param rec Record to append to EMF in memory + \param et EMF in memory + \param freerec If true, free rec after append +*/ +int emf_append( + U_ENHMETARECORD *rec, + EMFTRACK *et, + int freerec + ){ + size_t deficit; + +#ifdef U_VALGRIND + printf("\nbefore \n"); + printf(" probe %d\n",memprobe(rec, U_EMRSIZE(rec))); + printf("after \n"); +#endif + if(!rec)return(1); + if(!et)return(2); + if(rec->nSize + et->used > et->allocated){ + deficit = rec->nSize + et->used - et->allocated; + if(deficit < et->chunk)deficit = et->chunk; + et->allocated += deficit; + et->buf = realloc(et->buf,et->allocated); + if(!et->buf)return(3); + } + memcpy(et->buf + et->used, rec, rec->nSize); + et->used += rec->nSize; + et->records++; + if(rec->iType == U_EMR_EOF){ et->PalEntries = ((U_EMREOF *)rec)->cbPalEntries; } + if(freerec){ free(rec); } + return(0); +} + +/** + \brief Create a handle table. Entries filled with 0 are empty, entries >0 hold a handle. + \return 0 for success, >=1 for failure. + \param initsize Initialize with space for this number of handles + \param chunksize When needed increase space by this number of handles + \param eht EMF handle table +*/ +int emf_htable_create( + uint32_t initsize, + uint32_t chunksize, + EMFHANDLES **eht + ){ + EMFHANDLES *ehtl; + unsigned int i; + + if(initsize<1)return(1); + if(chunksize<1)return(2); + ehtl = (EMFHANDLES *) malloc(sizeof(EMFHANDLES)); + if(!ehtl)return(3); + ehtl->table = malloc(initsize * sizeof(uint32_t)); + if(!ehtl->table){ + free(ehtl); + return(4); + } + ehtl->stack = malloc(initsize * sizeof(uint32_t)); + if(!ehtl->stack){ + free(ehtl->table); + free(ehtl); + return(5); + } + memset(ehtl->table , 0, initsize * sizeof(uint32_t)); // zero all slots in the table + for(i=1; i<initsize; i++){ehtl->stack[i]=i;} // preset the stack + ehtl->allocated = initsize; + ehtl->chunk = chunksize; + ehtl->table[0] = 0; // This slot isn't actually ever used + ehtl->stack[0] = 0; // This stack position isn't actually ever used + ehtl->peak = 1; + ehtl->sptr = 1; + ehtl->top = 0; + *eht = ehtl; + return(0); +} + +/** + \brief Delete an entry from the handle table. Move it back onto the stack. The specified slot is filled with a 0. + \return 0 for success, >=1 for failure. + \param ih handle + \param eht EMF handle table + +*/ +int emf_htable_delete( + uint32_t *ih, + EMFHANDLES *eht + ){ + if(!eht)return(1); + if(!eht->table)return(2); + if(!eht->stack)return(3); + if(*ih < 1)return(4); // invalid handle + if(!eht->table[*ih])return(5); // requested table position was not in use + eht->table[*ih]=0; // remove handle from table + while(eht->top>0 && !eht->table[eht->top]){ // adjust top + eht->top--; + } + eht->sptr--; // adjust stack + eht->stack[eht->sptr]=*ih; // place handle on stack + *ih=0; // invalidate handle variable, so a second delete will of it is not possible + return(0); +} + +/** + \brief Returns the index of the first free slot. + Call realloc() if needed. The slot is set to handle (indicates occupied) and the peak value is adjusted. + \return 0 for success, >=1 for failure. + \param ih handle + \param eht EMF handle table +*/ +int emf_htable_insert( + uint32_t *ih, + EMFHANDLES *eht + ){ + unsigned int i; + size_t newsize; + + if(!eht)return(1); + if(!eht->table)return(2); + if(!eht->stack)return(3); + if(!ih)return(4); + if(eht->sptr >= eht->allocated - 1){ // need to reallocate + newsize=eht->allocated + eht->chunk; + eht->table = realloc(eht->table,newsize * sizeof(uint32_t)); + if(!eht->table)return(5); + memset(&eht->table[eht->allocated] , 0, eht->chunk * sizeof(uint32_t)); // zero all NEW slots in the table + + eht->stack = realloc(eht->stack,newsize * sizeof(uint32_t)); + if(!eht->stack)return(6); + for(i=eht->allocated; i<newsize;i++){ eht->stack[i] = i; } // init all NEW slots in the stack + eht->allocated = newsize; + } + *ih = eht->stack[eht->sptr]; // handle that is inserted + if(eht->table[*ih])return(7); + eht->table[*ih] = *ih; // handle goes into preexisting (but zero) slot in table + eht->stack[eht->sptr] = 0; + if(*ih > eht->top){ eht->top = *ih; } + if(eht->sptr > eht->peak){ eht->peak = eht->sptr; } + eht->sptr++; // next available handle + return(0); +} + +/** + \brief Free all memory in an htable. Sets the pointer to NULL. + \return 0 for success, >=1 for failure. + \param eht EMF handle table +*/ +int emf_htable_free( + EMFHANDLES **eht + ){ + EMFHANDLES *ehtl; + if(!eht)return(1); + ehtl = *eht; + if(!ehtl)return(2); + if(!ehtl->table)return(3); + if(!ehtl->stack)return(4); + free(ehtl->table); + free(ehtl->stack); + free(ehtl); + *eht=NULL; + return(0); +} + +/* ********************************************************************************************** +These functions create standard structures used in the EMR records. +*********************************************************************************************** */ + + +/** + \brief Set up fields for an EMR_HEADER from the physical device's width and height in mm and dots per millimeter. + Typically this is something like 216,279,47.244 (Letter paper, 1200 DPI = 47.244 DPmm) + \return 0 for success, >=1 for failure. + \param xmm Device width in millimeters + \param ymm Device height in millimeters + \param dpmm Dots per millimeter + \param szlDev Device size structure in pixels + \param szlMm Device size structure in mm +*/ +int device_size( + const int xmm, + const int ymm, + const float dpmm, + U_SIZEL *szlDev, + U_SIZEL *szlMm + ){ + if(xmm < 0 || ymm < 0 || dpmm < 0)return(1); + szlDev->cx = U_ROUND((float) xmm * dpmm); + szlDev->cy = U_ROUND((float) ymm * dpmm);; + szlMm->cx = xmm; + szlMm->cy = ymm; + return(0); +} + +/** + \brief Set up fields for an EMR_HEADER for drawing by physical size in mm and dots per millimeter. + Technically rclBounds is supposed to be the extent of the drawing within the EMF, but libUEMF has no way + of knowing this since it never actually draws anything. Instead this is set to the full drawing size. + Coordinates are inclusive inclusive, so 297 -> 0,29699. + \return 0 for success, >=1 for failure. + \param xmm Drawing width in millimeters + \param ymm Drawing height in millimeters + \param dpmm Dots per millimeter + \param rclBounds Drawing size structure in pixels + \param rclFrame Drawing size structure in mm +*/ +int drawing_size( + const int xmm, + const int ymm, + const float dpmm, + U_RECTL *rclBounds, + U_RECTL *rclFrame + ){ + if(xmm < 0 || ymm < 0 || dpmm < 0)return(1); + rclBounds->left = 0; + rclBounds->top = 0; + rclBounds->right = U_ROUND((float) xmm * dpmm) - 1; // because coordinate system is 0,0 in upper left, N,M in lower right + rclBounds->bottom = U_ROUND((float) ymm * dpmm) - 1; + rclFrame->left = 0; + rclFrame->top = 0; + rclFrame->right = U_ROUND((float) xmm * 100.) - 1; + rclFrame->bottom = U_ROUND((float) ymm * 100.) - 1; + return(0); +} + +/** + \brief Set a U_COLORREF value from separate R,G,B values. + \param red Red component + \param green Green component + \param blue Blue component + +*/ +U_COLORREF colorref3_set( + uint8_t red, + uint8_t green, + uint8_t blue + ){ + U_COLORREF cr = (U_COLORREF){red , green, blue, 0}; + return(cr); +} + +/** + \brief Set a U_COLORREF value from separate R,G,B, and Reserved values. + \param red Red component + \param green Green component + \param blue Blue component + \param Reserved Reserved component + +*/ +U_COLORREF colorref4_set( + uint8_t red, + uint8_t green, + uint8_t blue, + uint8_t Reserved + ){ + U_COLORREF cr = (U_COLORREF){red , green, blue, Reserved}; + return(cr); +} + +/** + \brief Set a U_RGBQUAD value from separate R,G,B, Reserved values. + \param red Red component + \param green Green component + \param blue Blue component + \param reserved Reserved component + +*/ +U_RGBQUAD rgbquad_set( + uint8_t red, + uint8_t green, + uint8_t blue, + uint8_t reserved + ){ + U_RGBQUAD cr = (U_RGBQUAD){blue , green, red, reserved}; + return(cr); +} + +/** + \brief Set rect and rectl objects from Upper Left and Lower Right corner points. + \param ul upper left corner of rectangle + \param lr lower right corner of rectangle +*/ +U_RECTL rectl_set( + U_POINTL ul, + U_POINTL lr + ){ + U_RECTL rct; + rct.left = ul.x; + rct.top = ul.y; + rct.right = lr.x; + rct.bottom = lr.y; + return(rct); +} + +/** + \brief Set rect and rectl objects from Upper Left and Lower Right corner points. + \param array array of rectangles + \param index array entry to fill, numbered from 0 + \param ul upper left corner of rectangle + \param lr lower right corner of rectangle +*/ +void rectli_set( + PU_RECTL array, + int index, + U_POINTL ul, + U_POINTL lr + ){ + PU_RECTL rct = &(array[index]); + rct->left = ul.x; + rct->top = ul.y; + rct->right = lr.x; + rct->bottom = lr.y; +} + +/** + \brief Set sizel objects with X,Y values. + \param x X coordinate + \param y Y coordinate +*/ +U_SIZEL sizel_set( + int32_t x, + int32_t y + ){ + U_SIZEL sz; + sz.cx = x; + sz.cy = y; + return(sz); +} + +/** + \brief Set pointl objects with X,Y values. + \param x X coordinate + \param y Y coordinate +*/ +U_POINTL point32_set( + int32_t x, + int32_t y + ){ + U_POINTL pt; + pt.x = x; + pt.y = y; + return(pt); +} + +/** + \brief Set point16 objects with 16 bit X,Y values. + \param x X coordinate + \param y Y coordinate +*/ +U_POINT16 point16_set( + int16_t x, + int16_t y + ){ + U_POINT16 pt; + pt.x = x; + pt.y = y; + return(pt); +} + +/** + \brief Find the bounding rectangle from a polyline of a given width. + \param count number of points in the polyline + \param pts the polyline + \param width width of drawn line + +*/ +U_RECT findbounds( + uint32_t count, + PU_POINT pts, + uint32_t width + ){ + U_RECT rect={INT32_MAX, INT32_MAX, INT32_MIN, INT32_MIN }; + unsigned int i; + + for(i=0; i<count;i++,pts++){ + if ( pts->x < rect.left ) rect.left = pts->x; + if ( pts->x > rect.right ) rect.right = pts->x; + if ( pts->y < rect.top ) rect.top = pts->y; + if ( pts->y > rect.bottom ) rect.bottom = pts->y; + } + if(width > 0){ + rect.left -= width; + rect.right += width; + rect.top += width; + rect.bottom -= width; + } + return(rect); +} + +/** + \brief Find the bounding rectangle from a polyline of a given width. + \param count number of points in the polyline + \param pts the polyline + \param width width of drawn line + +*/ +U_RECT findbounds16( + uint32_t count, + PU_POINT16 pts, + uint32_t width + ){ + U_RECT rect={INT16_MAX, INT16_MAX, INT16_MIN, INT16_MIN }; + unsigned int i; + + for(i=0; i<count;i++,pts++){ + if ( pts->x < rect.left ) rect.left = pts->x; + if ( pts->x > rect.right ) rect.right = pts->x; + if ( pts->y < rect.top ) rect.top = pts->y; + if ( pts->y > rect.bottom ) rect.bottom = pts->y; + } + if(width > 0){ + rect.left -= width; + rect.right += width; + rect.top += width; + rect.bottom -= width; + } + return(rect); +} +/** + \brief Construct a U_LOGBRUSH structure. + \return U_LOGBRUSH structure + \param lbStyle LB_Style Enumeration + \param lbColor Brush color + \param lbHatch HatchStyle Enumertaion +*/ +U_LOGBRUSH logbrush_set( + uint32_t lbStyle, + U_COLORREF lbColor, + int32_t lbHatch + ){ + U_LOGBRUSH lb; + lb.lbStyle = lbStyle; + lb.lbColor = lbColor; + lb.lbHatch = lbHatch; + return(lb); +} + +/** + \brief Construct a U_XFORM structure. + \return U_XFORM structure + \param eM11 Rotation Matrix element + \param eM12 Rotation Matrix element + \param eM21 Rotation Matrix element + \param eM22 Rotation Matrix element + \param eDx Translation element + \param eDy Translation element +*/ +U_XFORM xform_set( + U_FLOAT eM11, + U_FLOAT eM12, + U_FLOAT eM21, + U_FLOAT eM22, + U_FLOAT eDx, + U_FLOAT eDy + ){ + U_XFORM xform; + xform.eM11 = eM11; + xform.eM12 = eM12; + xform.eM21 = eM21; + xform.eM22 = eM22; + xform.eDx = eDx; + xform.eDy = eDy; + return(xform); +} + +/** + \brief Construct a U_XFORM structure. + \return U_XFORM structure + \param scale Scale factor + \param ratio Ratio of minor axis/major axis + \param rot Rotation angle in degrees, positive is counter clockwise from the x axis. + \param axisrot Angle in degrees defining the major axis before rotation, positive is counter clockwise from the x axis. + \param eDx Translation element + \param eDy Translation element + + Operation is: + 1 Conformal map of points based on scale, axis rotation, and axis ratio, + 2. Apply rotation + 3. Apply offset +*/ +U_XFORM xform_alt_set( + U_FLOAT scale, + U_FLOAT ratio, + U_FLOAT rot, + U_FLOAT axisrot, + U_FLOAT eDx, + U_FLOAT eDy + ){ + U_XFORM xform; + U_MAT2X2 mat1, mat2; + // angles are in degrees, must be in radians + rot *= (2.0 * U_PI)/360.0; + axisrot *= -(2.0 * U_PI)/360.0; + mat1.M11 = cos(rot); // set up the rotation matrix + mat1.M12 = -sin(rot); + mat1.M21 = sin(rot); + mat1.M22 = cos(rot); + if(ratio!=1.0){ // set scale/ellipticity matrix + mat2.M11 = scale*( cos(axisrot)*cos(axisrot) + ratio*sin(axisrot)*sin(axisrot) ); + mat2.M12 = mat2.M21 = scale*( sin(axisrot)*cos(axisrot) * (1.0 - ratio) ); + mat2.M22 = scale*( sin(axisrot)*sin(axisrot) + ratio*cos(axisrot)*cos(axisrot) ); + } + else { // when the ratio is 1.0 then the major axis angle is ignored and only scale matters + mat2.M11 = scale; + mat2.M12 = 0.0; + mat2.M21 = 0.0; + mat2.M22 = scale; + } + xform.eM11 = mat2.M11 * mat1.M11 + mat2.M12 * mat1.M21; + xform.eM12 = mat2.M11 * mat1.M12 + mat2.M12 * mat1.M22;; + xform.eM21 = mat2.M21 * mat1.M11 + mat2.M22 * mat1.M21; + xform.eM22 = mat2.M21 * mat1.M12 + mat2.M22 * mat1.M22; + xform.eDx = eDx; + xform.eDy = eDy; + return(xform); +} + + +/** + \brief Construct a U_LOGCOLORSPACEA structure. + \return U_LOGCOLORSPACEA structure + \param lcsCSType LCS_CSType Enumeration + \param lcsIntent LCS_Intent Enumeration + \param lcsEndpoints CIE XYZ color space endpoints + \param lcsGammaRGB Gamma For RGB + \param lcsFilename Could name an external color profile file, otherwise empty string +*/ +U_LOGCOLORSPACEA logcolorspacea_set( + int32_t lcsCSType, + int32_t lcsIntent, + U_CIEXYZTRIPLE lcsEndpoints, + U_LCS_GAMMARGB lcsGammaRGB, + char *lcsFilename + ){ + U_LOGCOLORSPACEA lcsa; + lcsa.lcsSignature = U_LCS_SIGNATURE; + lcsa.lcsVersion = U_LCS_SIGNATURE; + lcsa.lcsSize = sizeof(U_LOGCOLORSPACEA); + lcsa.lcsCSType = lcsCSType; + lcsa.lcsIntent = lcsIntent; + lcsa.lcsEndpoints = lcsEndpoints; + lcsa.lcsGammaRGB = lcsGammaRGB; + strncpy(lcsa.lcsFilename,lcsFilename,U_MAX_PATH); + lcsa.lcsFilename[U_MAX_PATH-1] = '\0'; + return(lcsa); +} + +/** + + \brief Construct a U_LOGCOLORSPACEW structure. + \return U_LOGCOLORSPACEW structure + \param lcsCSType LCS_CSType Enumeration + \param lcsIntent LCS_Intent Enumeration + \param lcsEndpoints CIE XYZ color space endpoints + \param lcsGammaRGB Gamma For RGB + \param lcsFilename Could name an external color profile file, otherwise empty string +*/ +U_LOGCOLORSPACEW logcolorspacew_set( + int32_t lcsCSType, + int32_t lcsIntent, + U_CIEXYZTRIPLE lcsEndpoints, + U_LCS_GAMMARGB lcsGammaRGB, + uint16_t *lcsFilename + ){ + U_LOGCOLORSPACEW lcsa; + lcsa.lcsSignature = U_LCS_SIGNATURE; + lcsa.lcsVersion = U_LCS_SIGNATURE; + lcsa.lcsSize = sizeof(U_LOGCOLORSPACEW); + lcsa.lcsCSType = lcsCSType; + lcsa.lcsIntent = lcsIntent; + lcsa.lcsEndpoints = lcsEndpoints; + lcsa.lcsGammaRGB = lcsGammaRGB; + wchar16strncpypad(lcsa.lcsFilename,lcsFilename,U_MAX_PATH); + lcsa.lcsFilename[U_MAX_PATH-1] = '\0'; + return(lcsa); +} + +/** + + \brief Construct a U_PANOSE structure. + \return U_PANOSE structure + \param bFamilyType FamilyType Enumeration + \param bSerifStyle SerifType Enumeration + \param bWeight Weight Enumeration + \param bProportion Proportion Enumeration + \param bContrast Contrast Enumeration + \param bStrokeVariation StrokeVariation Enumeration + \param bArmStyle ArmStyle Enumeration + \param bLetterform Letterform Enumeration + \param bMidline Midline Enumeration + \param bXHeight XHeight Enumeration +*/ +U_PANOSE panose_set( + uint8_t bFamilyType, + uint8_t bSerifStyle, + uint8_t bWeight, + uint8_t bProportion, + uint8_t bContrast, + uint8_t bStrokeVariation, + uint8_t bArmStyle, + uint8_t bLetterform, + uint8_t bMidline, + uint8_t bXHeight + ){ + U_PANOSE panose; + panose.bFamilyType = bFamilyType; + panose.bSerifStyle = bSerifStyle; + panose.bWeight = bWeight; + panose.bProportion = bProportion; + panose.bContrast = bContrast; + panose.bStrokeVariation = bStrokeVariation; + panose.bArmStyle = bArmStyle; + panose.bLetterform = bLetterform; + panose.bMidline = bMidline; + panose.bXHeight = bXHeight; + return(panose); +} + +/** + \brief Construct a U_LOGFONT structure. + \return U_LOGFONT structure + \param lfHeight Height in Logical units + \param lfWidth Average Width in Logical units + \param lfEscapement Angle in 0.1 degrees betweem escapement vector and X axis + \param lfOrientation Angle in 0.1 degrees between baseline and X axis + \param lfWeight LF_Weight Enumeration + \param lfItalic Italics: 0 or 1 + \param lfUnderline Underline: 0 or 1 + \param lfStrikeOut Strikeout: 0 or 1 + \param lfCharSet LF_CharSet Enumeration + \param lfOutPrecision LF_OutPrecision Enumeration + \param lfClipPrecision LF_ClipPrecision Enumeration + \param lfQuality LF_Quality Enumeration + \param lfPitchAndFamily LF_PitchAndFamily Enumeration + \param lfFaceName Name of font. truncates at U_LF_FACESIZE, smaller must be null terminated + +*/ +U_LOGFONT logfont_set( + int32_t lfHeight, + int32_t lfWidth, + int32_t lfEscapement, + int32_t lfOrientation, + int32_t lfWeight, + uint8_t lfItalic, + uint8_t lfUnderline, + uint8_t lfStrikeOut, + uint8_t lfCharSet, + uint8_t lfOutPrecision, + uint8_t lfClipPrecision, + uint8_t lfQuality, + uint8_t lfPitchAndFamily, + uint16_t *lfFaceName + ){ + U_LOGFONT lf; + lf.lfHeight = lfHeight; + lf.lfWidth = lfWidth; + lf.lfEscapement = lfEscapement; + lf.lfOrientation = lfOrientation; + lf.lfWeight = lfWeight; + lf.lfItalic = lfItalic; + lf.lfUnderline = lfUnderline; + lf.lfStrikeOut = lfStrikeOut; + lf.lfCharSet = lfCharSet; + lf.lfOutPrecision = lfOutPrecision; + lf.lfClipPrecision = lfClipPrecision; + lf.lfQuality = lfQuality; + lf.lfPitchAndFamily = lfPitchAndFamily; + wchar16strncpypad(lf.lfFaceName, lfFaceName, U_LF_FACESIZE); // pad this one as the intial structure was not set to zero + lf.lfFaceName[U_LF_FACESIZE-1] = '\0'; + return(lf); +} + + +/** + \brief Construct a U_LOGFONT_PANOSE structure. + \return U_LOGFONT_PANOSE structure + \param elfLogFont Basic font attributes + \param elfFullName Font full name, truncates at U_LF_FULLFACESIZE, smaller must be null terminated + \param elfStyle Font style, truncates at U_LF_FULLFACESIZE, smaller must be null terminated + \param elfStyleSize Font hinting starting at this point size, if 0, starts at Height + \param elfPanose Panose Object. If all zero, it is ignored. +*/ +U_LOGFONT_PANOSE logfont_panose_set( + U_LOGFONT elfLogFont, + uint16_t *elfFullName, + uint16_t *elfStyle, + uint32_t elfStyleSize, + U_PANOSE elfPanose + ){ + U_LOGFONT_PANOSE lfp; + memset(&lfp,0,sizeof(U_LOGFONT_PANOSE)); // all fields zero unless needed. Many should be ignored or must be 0. + wchar16strncpy(lfp.elfFullName, elfFullName, U_LF_FULLFACESIZE); + lfp.elfFullName[U_LF_FULLFACESIZE-1] = '\0'; + wchar16strncpy(lfp.elfStyle, elfStyle, U_LF_FACESIZE); + lfp.elfStyle[U_LF_FACESIZE-1] = '\0'; + lfp.elfLogFont = elfLogFont; + lfp.elfStyleSize = elfStyleSize; + lfp.elfPanose = elfPanose; + return(lfp); +} + +/** + \brief Construct a U_BITMAPINFOHEADER structure. + \return U_BITMAPINFOHEADER structure + \param biWidth Bitmap width in pixels + \param biHeight Bitmap height in pixels + \param biPlanes Planes (must be 1) + \param biBitCount BitCount Enumeration + \param biCompression BI_Compression Enumeration + \param biSizeImage Size in bytes of image + \param biXPelsPerMeter X Resolution in pixels/meter + \param biYPelsPerMeter Y Resolution in pixels/meter + \param biClrUsed Number of bmciColors in U_BITMAPCOREINFO + \param biClrImportant Number of bmciColors needed (0 means all). +*/ +U_BITMAPINFOHEADER bitmapinfoheader_set( + int32_t biWidth, + int32_t biHeight, + uint16_t biPlanes, + uint16_t biBitCount, + uint32_t biCompression, + uint32_t biSizeImage, + int32_t biXPelsPerMeter, + int32_t biYPelsPerMeter, + U_NUM_RGBQUAD biClrUsed, + uint32_t biClrImportant + ){ + U_BITMAPINFOHEADER Bmi; + Bmi.biSize = sizeof(U_BITMAPINFOHEADER); + Bmi.biWidth = biWidth; + Bmi.biHeight = biHeight; + Bmi.biPlanes = biPlanes; + Bmi.biBitCount = biBitCount; + Bmi.biCompression = biCompression; + Bmi.biSizeImage = biSizeImage; + Bmi.biXPelsPerMeter = biXPelsPerMeter; + Bmi.biYPelsPerMeter = biYPelsPerMeter; + Bmi.biClrUsed = biClrUsed; + Bmi.biClrImportant = biClrImportant; + return(Bmi); +} + + +/** + \brief Allocate and construct a U_BITMAPINFO structure. + \return Pointer to a U_BITMAPINFO structure + \param BmiHeader Geometry and pixel properties + \param BmiColors Color table (must be NULL for some values of BmiHeader->biBitCount) +*/ +PU_BITMAPINFO bitmapinfo_set( + U_BITMAPINFOHEADER BmiHeader, + PU_RGBQUAD BmiColors + ){ + char *record; + int irecsize; + int cbColors, cbColors4, off; + + cbColors = 4*get_real_color_count((char *) &BmiHeader); + cbColors4 = UP4(cbColors); + irecsize = sizeof(U_BITMAPINFOHEADER) + cbColors4; + record = malloc(irecsize); + if(record){ + memcpy(record, &BmiHeader, sizeof(U_BITMAPINFOHEADER)); + if(cbColors){ + off = sizeof(U_BITMAPINFOHEADER); + memcpy(record + off, BmiColors, cbColors); + off += cbColors; + if(cbColors4 - cbColors){ memset(record + off, 0, cbColors4 - cbColors); } + } + } + return((PU_BITMAPINFO) record); +} + +/** + \brief Allocate and construct a U_EXTLOGPEN structure. + \return pointer to U_EXTLOGPEN structure, or NULL on error + \param elpPenStyle PenStyle Enumeration + \param elpWidth Width in logical units (elpPenStyle & U_PS_GEOMETRIC) or 1 (pixel) + \param elpBrushStyle LB_Style Enumeration + \param elpColor Pen color + \param elpHatch HatchStyle Enumeration + \param elpNumEntries Count of StyleEntry array + \param elpStyleEntry Array of StyleEntry (For user specified dot/dash patterns) +*/ +PU_EXTLOGPEN extlogpen_set( + uint32_t elpPenStyle, + uint32_t elpWidth, + uint32_t elpBrushStyle, + U_COLORREF elpColor, + int32_t elpHatch, + U_NUM_STYLEENTRY elpNumEntries, + U_STYLEENTRY *elpStyleEntry + ){ + int irecsize,szSyleArray; + char *record; + + if(elpNumEntries){ + if(!elpStyleEntry)return(NULL); + szSyleArray = elpNumEntries * sizeof(U_STYLEENTRY); + irecsize = sizeof(U_EXTLOGPEN) + szSyleArray - sizeof(U_STYLEENTRY); // first one is in the record + } + else { + szSyleArray = 0; + irecsize = sizeof(U_EXTLOGPEN); + } + record = malloc(irecsize); + if(record){ + ((PU_EXTLOGPEN) record)->elpPenStyle = elpPenStyle; + ((PU_EXTLOGPEN) record)->elpWidth = elpWidth; + ((PU_EXTLOGPEN) record)->elpBrushStyle = elpBrushStyle; + ((PU_EXTLOGPEN) record)->elpColor = elpColor; + ((PU_EXTLOGPEN) record)->elpHatch = elpHatch; + ((PU_EXTLOGPEN) record)->elpNumEntries = elpNumEntries; + if(elpNumEntries){ memcpy(((PU_EXTLOGPEN) record)->elpStyleEntry,elpStyleEntry,szSyleArray); } + else { memset(((PU_EXTLOGPEN) record)->elpStyleEntry,0,sizeof(U_STYLEENTRY)); } // not used, but this stops valgrind warnings + } + return((PU_EXTLOGPEN) record); +} + +/** + \brief Construct a U_LOGPEN structure. + \return U_LOGPEN structure + \param lopnStyle PenStyle Enumeration + \param lopnWidth Width of pen set by X, Y is ignored + \param lopnColor Pen color value + +*/ +U_LOGPEN logpen_set( + uint32_t lopnStyle, + U_POINT lopnWidth, + U_COLORREF lopnColor + ){ + U_LOGPEN lp; + lp.lopnStyle = lopnStyle; + lp.lopnWidth = lopnWidth; + lp.lopnColor = lopnColor; + return(lp); +} + +/** + \brief Construct a U_LOGPLTNTRY structure. + \return U_LOGPLTNTRY structure + \param peReserved Ignore + \param peRed Palette entry Red Intensity + \param peGreen Palette entry Green Intensity + \param peBlue Palette entry Blue Intensity +*/ +U_LOGPLTNTRY logpltntry_set( + uint8_t peReserved, + uint8_t peRed, + uint8_t peGreen, + uint8_t peBlue + ){ + U_LOGPLTNTRY lpny; + lpny.peReserved = peReserved; + lpny.peRed = peRed; + lpny.peGreen = peGreen; + lpny.peBlue = peBlue; + return(lpny); +} + +/** + \brief Allocate and construct a U_LOGPALETTE structure. + \return pointer to U_LOGPALETTE structure, or NULL on error. + \param palNumEntries Number of U_LOGPLTNTRY objects + \param palPalEntry array, PC_Entry Enumeration +*/ +PU_LOGPALETTE logpalette_set( + U_NUM_LOGPLTNTRY palNumEntries, + PU_LOGPLTNTRY *palPalEntry + ){ + PU_LOGPALETTE record; + int cbPalArray,irecsize; + + if(palNumEntries == 0 || !palPalEntry)return(NULL); + cbPalArray = palNumEntries * sizeof(U_LOGPLTNTRY); + irecsize = sizeof(U_LOGPALETTE) + cbPalArray - sizeof(U_LOGPLTNTRY); + record = (PU_LOGPALETTE) malloc(irecsize); + if(irecsize){ + record->palVersion = U_LP_VERSION; + record->palNumEntries = palNumEntries; + memcpy(record->palPalEntry,palPalEntry,cbPalArray); + } + return(record); +} + +/** + \brief Construct a U_RGNDATAHEADER structure. + \return U_RGNDATAHEADER structure + \param nCount Number of rectangles in region + \param rclBounds Region bounds +*/ +U_RGNDATAHEADER rgndataheader_set( + U_NUM_RECTL nCount, + U_RECTL rclBounds + ){ + U_RGNDATAHEADER rdh; + rdh.dwSize = U_RDH_OBJSIZE; + rdh.iType = U_RDH_RECTANGLES; + rdh.nCount = nCount; + rdh.nRgnSize = nCount * sizeof(U_RECTL); // Size in bytes of rectangle array + rdh.rclBounds = rclBounds; + return(rdh); +} + +/** + \brief Allocate and construct a U_RGNDATA structure. + \return pointer to U_RGNDATA structure, or NULL on error. + \param rdh Data description + \param Buffer Array of U_RECTL elements +*/ +PU_RGNDATA rgndata_set( + U_RGNDATAHEADER rdh, + PU_RECTL Buffer + ){ + char *record; + int irecsize; + int szRgnArray,off; + + if(!Buffer || !rdh.nCount || !rdh.nRgnSize)return(NULL); + szRgnArray = rdh.nRgnSize; // size of the U_RECTL array + irecsize = sizeof(U_RGNDATA) + szRgnArray - sizeof(U_RECTL); // core + array - overlap + record = malloc(irecsize); + if(record){ + memcpy(record, &rdh, sizeof(U_RGNDATAHEADER)); + off = sizeof(U_RGNDATAHEADER); + memcpy(record + off, Buffer, szRgnArray); + } + return((PU_RGNDATA) record); +} + +/** + \brief Construct a U_COLORADJUSTMENT structure. + \return U_COLORADJUSTMENT structure + \param Size Size of this structure in bytes + \param Flags ColorAdjustment Enumeration + \param IlluminantIndex Illuminant Enumeration + \param RedGamma Red Gamma correction (range:2500:65000, 10000 is no correction) + \param GreenGamma Green Gamma correction (range:2500:65000, 10000 is no correction) + \param BlueGamma Blue Gamma correction (range:2500:65000, 10000 is no correction) + \param ReferenceBlack Values less than this are black (range:0:4000) + \param ReferenceWhite Values more than this are white (range:6000:10000) + \param Contrast Contrast adjustment (range:-100:100, 0 is no correction) + \param Brightness Brightness adjustment (range:-100:100, 0 is no correction) + \param Colorfulness Colorfulness adjustment (range:-100:100, 0 is no correction) + \param RedGreenTint Tine adjustment (range:-100:100, 0 is no correction) +*/ +U_COLORADJUSTMENT coloradjustment_set( + uint16_t Size, + uint16_t Flags, + uint16_t IlluminantIndex, + uint16_t RedGamma, + uint16_t GreenGamma, + uint16_t BlueGamma, + uint16_t ReferenceBlack, + uint16_t ReferenceWhite, + int16_t Contrast, + int16_t Brightness, + int16_t Colorfulness, + int16_t RedGreenTint + ){ + U_COLORADJUSTMENT ca; + ca.caSize = Size; + ca.caFlags = Flags; + ca.caIlluminantIndex = IlluminantIndex; + ca.caRedGamma = U_MNMX(RedGamma, U_RGB_GAMMA_MIN, U_RGB_GAMMA_MAX); + ca.caGreenGamma = U_MNMX(GreenGamma, U_RGB_GAMMA_MIN, U_RGB_GAMMA_MAX); + ca.caBlueGamma = U_MNMX(BlueGamma, U_RGB_GAMMA_MIN, U_RGB_GAMMA_MAX); + // Next one is different to eliminate compiler warning - U_R_B_MIN is 0 and unsigned + ca.caReferenceBlack = U_MAX( ReferenceBlack, U_REFERENCE_BLACK_MAX); + ca.caReferenceWhite = U_MNMX(ReferenceWhite, U_REFERENCE_WHITE_MIN, U_REFERENCE_WHITE_MAX); + ca.caContrast = U_MNMX(Contrast, U_COLOR_ADJ_MIN, U_COLOR_ADJ_MAX); + ca.caBrightness = U_MNMX(Brightness, U_COLOR_ADJ_MIN, U_COLOR_ADJ_MAX); + ca.caColorfulness = U_MNMX(Colorfulness, U_COLOR_ADJ_MIN, U_COLOR_ADJ_MAX); + ca.caRedGreenTint = U_MNMX(RedGreenTint, U_COLOR_ADJ_MIN, U_COLOR_ADJ_MAX); + return(ca); +} + +/** + \brief Construct a U_PIXELFORMATDESCRIPTOR structure. + \return U_PIXELFORMATDESCRIPTOR structure + \param dwFlags PFD_dwFlags Enumeration + \param iPixelType PFD_iPixelType Enumeration + \param cColorBits RGBA: total bits per pixel + \param cRedBits Red bits per pixel + \param cRedShift Red shift to data bits + \param cGreenBits Green bits per pixel + \param cGreenShift Green shift to data bits + \param cBlueBits Blue bits per pixel + \param cBlueShift Blue shift to data bits + \param cAlphaBits Alpha bits per pixel + \param cAlphaShift Alpha shift to data bits + \param cAccumBits Accumulator buffer, total bitplanes + \param cAccumRedBits Red accumulator buffer bitplanes + \param cAccumGreenBits Green accumulator buffer bitplanes + \param cAccumBlueBits Blue accumulator buffer bitplanes + \param cAccumAlphaBits Alpha accumulator buffer bitplanes + \param cDepthBits Depth of Z-buffer + \param cStencilBits Depth of stencil buffer + \param cAuxBuffers Depth of auxilliary buffers (not supported) + \param iLayerType PFD_iLayerType Enumeration, may be ignored + \param bReserved Bits 0:3/4:7 are number of Overlay/Underlay planes + \param dwLayerMask may be ignored + \param dwVisibleMask color or index of underlay plane + \param dwDamageMask may be ignored +*/ +U_PIXELFORMATDESCRIPTOR pixelformatdescriptor_set( + uint32_t dwFlags, + uint8_t iPixelType, + uint8_t cColorBits, + uint8_t cRedBits, + uint8_t cRedShift, + uint8_t cGreenBits, + uint8_t cGreenShift, + uint8_t cBlueBits, + uint8_t cBlueShift, + uint8_t cAlphaBits, + uint8_t cAlphaShift, + uint8_t cAccumBits, + uint8_t cAccumRedBits, + uint8_t cAccumGreenBits, + uint8_t cAccumBlueBits, + uint8_t cAccumAlphaBits, + uint8_t cDepthBits, + uint8_t cStencilBits, + uint8_t cAuxBuffers, + uint8_t iLayerType, + uint8_t bReserved, + uint32_t dwLayerMask, + uint32_t dwVisibleMask, + uint32_t dwDamageMask + ){ + U_PIXELFORMATDESCRIPTOR pfd; + pfd.nSize = sizeof(U_PIXELFORMATDESCRIPTOR); + pfd.nVersion = 1; + pfd.dwFlags = dwFlags; + pfd.iPixelType = iPixelType; + pfd.cColorBits = cColorBits; + pfd.cRedBits = cRedBits; + pfd.cRedShift = cRedShift; + pfd.cGreenBits = cGreenBits; + pfd.cGreenShift = cGreenShift; + pfd.cBlueBits = cBlueBits; + pfd.cBlueShift = cBlueShift; + pfd.cAlphaBits = cAlphaBits; + pfd.cAlphaShift = cAlphaShift; + pfd.cAccumBits = cAccumBits; + pfd.cAccumRedBits = cAccumRedBits; + pfd.cAccumGreenBits = cAccumGreenBits; + pfd.cAccumBlueBits = cAccumBlueBits; + pfd.cAccumAlphaBits = cAccumAlphaBits; + pfd.cDepthBits = cDepthBits; + pfd.cStencilBits = cStencilBits; + pfd.cAuxBuffers = cAuxBuffers; + pfd.iLayerType = iLayerType; + pfd.bReserved = bReserved; + pfd.dwLayerMask = dwLayerMask; + pfd.dwVisibleMask = dwVisibleMask; + pfd.dwDamageMask = dwDamageMask; + return(pfd); +} + +/** + \brief Allocate and create a U_EMRTEXT structure followed by its variable pieces via a char* pointer. + Dx cannot be NULL, if the calling program has no appropriate values call dx_set() first. + \return char* pointer to U_EMRTEXT structure followed by its variable pieces, or NULL on error + \param ptlReference String start coordinates + \param NumString Number of characters in string, does NOT include a terminator + \param cbChar Number of bytes per character + \param String String to write + \param fOptions ExtTextOutOptions Enumeration + \param rcl (Optional, when fOptions & 7) grayed/clipping/opaque rectangle + \param Dx Character spacing array from the start of the RECORD +*/ +char *emrtext_set( + U_POINTL ptlReference, + U_NUM_STR NumString, + uint32_t cbChar, + void *String, + uint32_t fOptions, + U_RECTL rcl, + uint32_t *Dx + ){ + int irecsize,cbDxArray,cbString4,cbString,off; + char *record; + uint32_t *loffDx; + + if(!String)return(NULL); + if(!Dx)return(NULL); + cbString = cbChar * NumString; // size of the string in bytes + cbString4 = UP4(cbString); // size of the string buffer + cbDxArray = sizeof(uint32_t)*NumString; // size of Dx array storage + if(fOptions & U_ETO_PDY)cbDxArray += cbDxArray; // of the Dx buffer, here do both X and Y coordinates + irecsize = sizeof(U_EMRTEXT) + sizeof(uint32_t) + cbString4 + cbDxArray; // core structure + offDx + string buf + dx buf + if(!(fOptions & U_ETO_NO_RECT)){ irecsize += sizeof(U_RECTL); } // plus variable U_RECTL, when it is present + record = malloc(irecsize); + if(record){ + ((PU_EMRTEXT)record)->ptlReference = ptlReference; + ((PU_EMRTEXT)record)->nChars = NumString; + // pick up ((PU_EMRTEXT)record)->offString later + ((PU_EMRTEXT)record)->fOptions = fOptions; + off = sizeof(U_EMRTEXT); // location where variable pieces will start to be written + if(!(fOptions & U_ETO_NO_RECT)){ // variable field, may or may not be present + memcpy(record + off,&rcl, sizeof(U_RECTL)); + off += sizeof(U_RECTL); + } + loffDx = (uint32_t *)(record + off); // offDx will go here, but we do not know with what value yet + off += sizeof(uint32_t); + memcpy(record + off,String,cbString); // copy the string data to its buffer + ((PU_EMRTEXT)record)->offString = off; // now save offset in the structure + off += cbString; + if(cbString < cbString4){ + memset(record+off,0,cbString4-cbString); // keeps valgrind happy (initialize padding after string) + off += cbString4-cbString; + } + memcpy(record + off, Dx, cbDxArray); // copy the Dx data to its buffer + *loffDx = off; // now save offDx to the structure + } + return(record); +} + + + +/* ********************************************************************************************** +These functions are simpler or more convenient ways to generate the specified types of EMR records. +Each should be called in preference to the underlying "base" EMR function. +*********************************************************************************************** */ + + +/** + \brief Allocate and construct a U_EMRCOMMENT structure with a UTF8 string. + A U_EMRCOMMENT contains application specific data, and that may include contain null characters. This function may be used when the + comment only incluces UT8 text. + \return pointer to U_EMRCOMMENT structure, or NULL on error. + \param string UTF8 string to store in the comment + + +*/ +char *textcomment_set( + const char *string + ){ + if(!string)return(NULL); + return(U_EMRCOMMENT_set(1 + strlen(string),string)); +} + +/** + \brief Allocate and construct a U_EMRDELETEOBJECT structure and also delete the requested object from the table. + Use this function instead of calling U_EMRDELETEOBJECT_set() directly. + \return pointer to U_EMRDELETEOBJECT structure, or NULL on error. + \param ihObject Pointer to handle to delete. This value is set to 0 if the function succeeds. + \param eht EMF handle table + + Note that calling this function should always be conditional on the specifed object being defined. It is easy to + write a program where deleteobject_set() is called in a sequence where, at the time, we know that ihObject is defined. + Then a later modification, possibly quite far away in the code, causes it to be undefined. That distant change will + result in a failure when this function reutrns. That problem cannot be handled here because the only values which + may be returned are a valid U_EMRDELETEOBJECT record or a NULL, and other errors could result in the NULL. + So the object must be checked before the call. +*/ +char *deleteobject_set( + uint32_t *ihObject, + EMFHANDLES *eht + ){ + uint32_t saveObject=*ihObject; + if(emf_htable_delete(ihObject,eht))return(NULL); // invalid handle or other problem, cannot be deleted + return(U_EMRDELETEOBJECT_set(saveObject)); +} + +/** + \brief Allocate and construct a U_EMRSELECTOBJECT structure, checks that the handle specified is one that can actually be selected. + Use this function instead of calling U_EMRSELECTOBJECT_set() directly. + \return pointer to U_EMRSELECTOBJECT structure, or NULL on error. + \param ihObject handle to select + \param eht EMF handle table +*/ +char *selectobject_set( + uint32_t ihObject, + EMFHANDLES *eht + ){ + if(!(U_STOCK_OBJECT & ihObject)){ // not a stock object, those go straight through + if(ihObject > eht->top)return(NULL); // handle this high is not in the table + if(!eht->table[ihObject])return(NULL); // handle is not in the table, so not active, so cannot be selected + } + return(U_EMRSELECTOBJECT_set(ihObject)); +} + +/** + \brief Allocate and construct a U_EMREXTCREATEPEN structure, create a handle and return it. + Use this function instead of calling U_EMREXTCREATEPEN_set() directly. + \return pointer to U_EMREXTCREATEPEN structure, or NULL on error. + \param ihPen handle to be used by new object + \param eht EMF handle table + \param Bmi bitmapbuffer + \param cbPx Size in bytes of pixel array (row stride * height, there may be some padding at the end of each row) + \param Px pixel array (NULL if cbPx == 0) + \param elp Pen parameters (Size is Variable!!!!) +*/ +char *extcreatepen_set( + uint32_t *ihPen, + EMFHANDLES *eht, + PU_BITMAPINFO Bmi, + const uint32_t cbPx, + char *Px, + PU_EXTLOGPEN elp + ){ + if(emf_htable_insert(ihPen, eht))return(NULL); + return(U_EMREXTCREATEPEN_set(*ihPen, Bmi, cbPx, Px, elp )); +} + +/** + \brief Allocate and construct a U_EMRCREATEPEN structure, create a handle and returns it + Use this function instead of calling U_EMRCREATEPEN_set() directly. + \return pointer to U_EMRCREATEPEN structure, or NULL on error. + \param ihPen handle to be used by new object + \param eht EMF handle table + \param lopn Pen parameters +*/ +char *createpen_set( + uint32_t *ihPen, + EMFHANDLES *eht, + U_LOGPEN lopn + ){ + if(emf_htable_insert(ihPen, eht))return(NULL); + return(U_EMRCREATEPEN_set(*ihPen, lopn)); +} + +/** + \brief Allocate and construct a U_EMRCREATEBRUSHINDIRECT structure, create a handle and returns it + Use this function instead of calling U_EMRCREATEBRUSHINDIRECT_set() directly. + \return pointer to U_EMRCREATEBRUSHINDIRECT structure, or NULL on error. + \param ihBrush handle to be used by new object + \param eht EMF handle table + \param lb Brush parameters +*/ +char *createbrushindirect_set( + uint32_t *ihBrush, + EMFHANDLES *eht, + U_LOGBRUSH lb + ){ + if(emf_htable_insert(ihBrush, eht))return(NULL); + return(U_EMRCREATEBRUSHINDIRECT_set(*ihBrush, lb)); +} + +/** + \brief Allocate and construct a U_EMRCREATEDIBPATTERNBRUSHPT_set structure, create a handle and returns it + Use this function instead of calling U_EMRCREATEDIBPATTERNBRUSHPT_set() directly. + \return pointer to U_EMRCREATEDIBPATTERNBRUSHPT_set structure, or NULL on error. + \param ihBrush handle to be used by new object + \param eht EMF handle table + \param iUsage DIBColors enumeration + \param Bmi Bitmap info + \param cbPx Size in bytes of pixel array (row stride * height, there may be some padding at the end of each row) + \param Px (Optional) bitmapbuffer (pixel array section ) +*/ +char *createdibpatternbrushpt_set( + uint32_t *ihBrush, + EMFHANDLES *eht, + const uint32_t iUsage, + PU_BITMAPINFO Bmi, + const uint32_t cbPx, + const char *Px + + ){ + if(emf_htable_insert(ihBrush, eht))return(NULL); + return(U_EMRCREATEDIBPATTERNBRUSHPT_set(*ihBrush, iUsage, Bmi, cbPx, Px)); +} + +/** + \brief Allocate and construct a U_EMRCREATEMONOBRUSH_set structure, create a handle and returns it + Use this function instead of calling U_EMRCREATEMONOBRUSH_set() directly. + \return pointer to U_EMRCREATEMONOBRUSH_set structure, or NULL on error. + \param ihBrush handle to be used by new object + \param eht EMF handle table + \param iUsage DIBColors enumeration + \param Bmi Bitmap info + \param cbPx Size in bytes of pixel array (row stride * height, there may be some padding at the end of each row) + \param Px (Optional) bitmapbuffer (pixel array section ) +*/ +char *createmonobrush_set( + uint32_t *ihBrush, + EMFHANDLES *eht, + const uint32_t iUsage, + PU_BITMAPINFO Bmi, + const uint32_t cbPx, + const char *Px + + ){ + if(emf_htable_insert(ihBrush, eht))return(NULL); + return(U_EMRCREATEMONOBRUSH_set(*ihBrush, iUsage, Bmi, cbPx, Px)); +} + + +/** + \brief Allocate and construct a U_EMRCREATECOLORSPACE structure, create a handle and returns it + Use this function instead of calling U_EMRCREATECOLORSPACE_set() directly. + \return pointer to U_EMRCREATECOLORSPACE structure, or NULL on error. + \param ihCS ColorSpace handle, will be created and returned + \param eht Pointer to structure holding all EMF handles + \param lcs ColorSpace parameters +*/ +char *createcolorspace_set( + uint32_t *ihCS, + EMFHANDLES *eht, + U_LOGCOLORSPACEA lcs + ){ + if(emf_htable_insert(ihCS, eht))return(NULL); + return(U_EMRCREATECOLORSPACE_set(*ihCS,lcs)); +} + +/** + \brief Allocate and construct a U_EMRCREATECOLORSPACEW structure, create a handle and returns it + Use this function instead of calling U_EMRCREATECOLORSPACEW_set() directly. + \return pointer to U_EMRCREATECOLORSPACEW structure, or NULL on error. + \param ihCS ColorSpace handle, will be created and returned + \param eht Pointer to structure holding all EMF handles + \param lcs ColorSpace parameters + \param dwFlags If low bit set Data is present + \param cbData Number of bytes of theData field. + \param Data (Optional, dwFlags & 1) color profile data +*/ +char *createcolorspacew_set( + uint32_t *ihCS, + EMFHANDLES *eht, + U_LOGCOLORSPACEW lcs, + uint32_t dwFlags, + U_CBDATA cbData, + uint8_t *Data + ){ + if(emf_htable_insert(ihCS, eht))return(NULL); + return(U_EMRCREATECOLORSPACEW_set(*ihCS, lcs, dwFlags, cbData, Data)); +} + +/** + \brief Allocate and construct a U_EMREXTCREATEFONTINDIRECTW structure, create a handle and returns it + Use this function instead of calling U_EMREXTCREATEFONTINDIRECTW_set() directly. + \return pointer to U_EMREXTCREATEFONTINDIRECTW structure, or NULL on error. + \param ihFont Font handle, will be created and returned + \param eht Pointer to structure holding all EMF handles + \param elf Pointer to Font parameters asPU_LOGFONT + \param elfw Pointer to Font parameters as U_LOGFONT_PANOSE +*/ +char *extcreatefontindirectw_set( + uint32_t *ihFont, + EMFHANDLES *eht, + const char *elf, + const char *elfw + ){ + if(emf_htable_insert(ihFont, eht))return(NULL); + return(U_EMREXTCREATEFONTINDIRECTW_set(*ihFont, elf, elfw)); +} + +/** + \brief Allocate and construct a U_EMRCREATEPALETTE structure, create a handle and returns it + Use this function instead of calling U_EMRCREATEPALETTE_set() directly. + \return pointer to U_EMRCREATEPALETTE structure, or NULL on error. + \param ihPal Palette handle, will be created and returned + \param eht Pointer to structure holding all EMF handles + \param lgpl PaletteFont parameters +*/ +char *createpalette_set( + uint32_t *ihPal, + EMFHANDLES *eht, + U_LOGPALETTE lgpl + ){ + if(emf_htable_insert(ihPal, eht))return(NULL); + return(U_EMRCREATEPALETTE_set(*ihPal, lgpl)); +} + +/** + \brief Allocate and construct a U_EMRSETPALETTEENTRIES structure, create a handle and returns it + Use this function instead of calling U_EMRSETPALETTEENTRIES_set() directly. + \return pointer to U_EMRSETPALETTEENTRIES structure, or NULL on error. + \param ihPal Palette handle, will be created and returned + \param eht Pointer to structure holding all EMF handles + \param iStart First Palette entry in selected object to set + \param cEntries Number of Palette entries in selected object to set + \param aPalEntries Values to set with +*/ +char *setpaletteentries_set( + uint32_t *ihPal, + EMFHANDLES *eht, + const uint32_t iStart, + const U_NUM_LOGPLTNTRY cEntries, + const PU_LOGPLTNTRY aPalEntries + ){ + if(emf_htable_insert(ihPal, eht))return(NULL); + return(U_EMRSETPALETTEENTRIES_set(*ihPal, iStart, cEntries, aPalEntries)); +} + +/** + \brief Allocate and construct a U_EMRFILLRGN structure, create a handle and returns it + Use this function instead of calling U_EMRFILLRGN_set() directly. + \return pointer to U_EMRFILLRGN structure, or NULL on error. + \param ihBrush Brush handle, will be created and returned + \param eht Pointer to structure holding all EMF handles + \param rclBounds Bounding rectangle in device units + \param RgnData Pointer to a U_RGNDATA structure +*/ +char *fillrgn_set( + uint32_t *ihBrush, + EMFHANDLES *eht, + const U_RECTL rclBounds, + const PU_RGNDATA RgnData + ){ + if(emf_htable_insert(ihBrush, eht))return(NULL); + return(U_EMRFILLRGN_set(rclBounds, *ihBrush, RgnData)); +} + +/** + \brief Allocate and construct a U_EMRFRAMERGN structure, create a handle and returns it + Use this function instead of calling U_EMRFRAMERGN_set() directly. + \return pointer to U_EMRFRAMERGN structure, or NULL on error. + \param ihBrush Brush handle, will be created and returned + \param eht Pointer to structure holding all EMF handles + \param rclBounds Bounding rectangle in device units + \param szlStroke W & H of Brush stroke + \param RgnData Pointer to a U_RGNDATA structure +*/ +char *framergn_set( + uint32_t *ihBrush, + EMFHANDLES *eht, + const U_RECTL rclBounds, + const U_SIZEL szlStroke, + const PU_RGNDATA RgnData + ){ + if(emf_htable_insert(ihBrush, eht))return(NULL); + return(U_EMRFRAMERGN_set(rclBounds, *ihBrush, szlStroke, RgnData)); +} + +/** + \brief Allocate and construct an array of U_POINT objects which has been subjected to a U_XFORM + \returns pointer to an array of U_POINT structures. + \param points pointer to the source U_POINT structures + \param count number of members in points + \param xform U_XFORM to apply + + May also be used to modify U_RECT by doubling the count and casting the pointer. +*/ +PU_POINT points_transform(PU_POINT points, int count, U_XFORM xform){ + PU_POINT newpts; + int i; + float x,y; + newpts = (PU_POINT) malloc(count * sizeof(U_POINT)); + for(i=0; i<count; i++){ + x = (float) points[i].x; + y = (float) points[i].y; + newpts[i].x = U_ROUND(x * xform.eM11 + y * xform.eM21 + xform.eDx); + newpts[i].y = U_ROUND(x * xform.eM12 + y * xform.eM22 + xform.eDy); + } + return(newpts); +} + +/** + \brief Allocate and construct an array of U_POINT16 objects which has been subjected to a U_XFORM + \returns pointer to an array of U_POINT16 structures. + \param points pointer to the source U_POINT16 structures + \param count number of members in points + \param xform U_XFORM to apply + + Transformed src points {x0,y0} appear at {x0*xscale + x, y0*yscale + y} +*/ +PU_POINT16 point16_transform(PU_POINT16 points, int count, U_XFORM xform){ + PU_POINT16 newpts; + int i; + float x,y; + newpts = (PU_POINT16) malloc(count * sizeof(U_POINT16)); + for(i=0; i<count; i++){ + x = (float) points[i].x; + y = (float) points[i].y; + newpts[i].x = U_ROUND(x * xform.eM11 + y * xform.eM21 + xform.eDx); + newpts[i].y = U_ROUND(x * xform.eM12 + y * xform.eM22 + xform.eDy); + } + return(newpts); +} + +/** + \brief Allocate and construct an array of U_TRIVERTEX objects which has been subjected to a U_XFORM + \returns pointer to an array of U_TRIVERTEX structures. + \param tv pointer to the source U_TRIVERTEX structures + \param count number of members in points + \param xform U_XFORM to apply + + Transformed Trivertex points {x0,y0} appear at {x0*xscale + x, y0*yscale + y} +*/ +PU_TRIVERTEX trivertex_transform(PU_TRIVERTEX tv, int count, U_XFORM xform){ + PU_TRIVERTEX newtvs; + int i; + float x,y; + newtvs = (PU_TRIVERTEX) malloc(count * sizeof(U_TRIVERTEX)); + for(i=0; i<count; i++){ + x = (float) tv[i].x; + y = (float) tv[i].y; + newtvs[i] = tv[i]; + newtvs[i].x = U_ROUND(x * xform.eM11 + y * xform.eM21 + xform.eDx); + newtvs[i].y = U_ROUND(x * xform.eM12 + y * xform.eM22 + xform.eDy); + } + return(newtvs); +} + +/** + \brief Allocate and construct an array of U_POINT objects from a set of U_POINT16 objects + \returns pointer to an array of U_POINT structures. + \param points pointer to the source U_POINT16 structures + \param count number of members in points + +*/ +PU_POINT point16_to_point(PU_POINT16 points, int count){ + PU_POINT newpts; + int i; + newpts = (PU_POINT) malloc(count * sizeof(U_POINT)); + for(i=0; i<count; i++){ + newpts[i].x = points[i].x; + newpts[i].y = points[i].y; + } + return(newpts); +} + +/** + \brief Allocate and construct an array of U_POINT16 objects from a set of U_POINT objects + \returns pointer to an array of U_POINT16 structures. + \param points pointer to the source U_POINT structures + \param count number of members in points + + If a coordinate is out of range it saturates at boundary. +*/ +PU_POINT16 point_to_point16(PU_POINT points, int count){ + PU_POINT16 newpts; + int i; + newpts = (PU_POINT16) malloc(count * sizeof(U_POINT16)); + for(i=0; i<count; i++){ + newpts[i].x = U_MNMX(points[i].x, INT16_MIN, INT16_MAX); + newpts[i].y = U_MNMX(points[i].y, INT16_MIN, INT16_MAX); + } + return(newpts); +} + +// hide these from Doxygen +//! @cond +/* ********************************************************************************************** +These functions contain shared code used by various U_EMR*_set functions. These should NEVER be called +by end user code and to further that end prototypes are NOT provided and they are hidden from Doxygen. + + + These are (mostly) ordered by U_EMR_* index number. + For all _set functions the caller must eventually call free() on the returned pointer. + + CORE1(uint32_t iType, U_RECTL rclBounds, const uint32_t cptl, const U_POINTL *points){ + CORE2(uint32_t iType, U_RECTL rclBounds, const uint32_t nPolys, const uint32_t *aPolyCounts,const uint32_t cptl, const U_POINTL *points){ + CORE3(uint32_t iType, uint32_t iMode){ (generic 1 uint) + CORE4(uint32_t iType, U_RECTL rclBox){ + CORE5(uint32_t iType){ (generic noargs) + CORE6(uint32_t iType, U_RECTL rclBounds, const uint32_t cpts, const U_POINT16 *points){ (16bit form of CORE1) + CORE7(uint32_t iType, U_PAIR pair){ + CORE8(uint32_t iType, U_RECTL rclBounds, uint32_t iGraphicsMode, U_FLOAT exScale, U_FLOAT eyScale, PU_EMRTEXT emrtext){ + CORE9(uint32_t iType, U_RECTL rclBox, U_POINTL ptlStart, U_POINTL ptlEnd){ + CORE10(uint32_t iType, U_RECTL rclBounds, const uint32_t nPolys, const uint32_t *aPolyCounts,const uint32_t cpts, const U_POINT16 *points){ (16bit form of CORE2) + CORE11(uint32_t iType, PU_RGNDATA RgnData){ + CORE12(uint32_t iType, uint32_t ihBrush, uint32_t iUsage, PU_BITMAPINFO Bmi){ + CORE13(uint32_t iType, U_RECTL rclBounds, U_POINTL Dest, U_POINTL cDest, + U_POINTL Src, U_POINTL cSrc, U_XFORM xformSrc, U_COLORREF crBkColorSrc, uint32_t iUsageSrc, + uint32_t Data, PU_BITMAPINFO Bmi); +*********************************************************************************************** */ + + +// Functions with the same form starting with U_EMRPOLYBEZIER_set +char *U_EMR_CORE1_set(uint32_t iType, U_RECTL rclBounds, const uint32_t cptl, const U_POINTL *points){ + char *record; + int cbPoints; + int irecsize; + + cbPoints = sizeof(U_POINTL)*cptl; + irecsize = sizeof(U_EMRPOLYBEZIER) + cbPoints - sizeof(U_POINTL); // First instance is in struct + record = malloc(irecsize); + if(record){ + ((PU_EMR) record)->iType = iType; + ((PU_EMR) record)->nSize = irecsize; + ((PU_EMRPOLYBEZIER) record)->rclBounds = rclBounds; + ((PU_EMRPOLYBEZIER) record)->cptl = cptl; + memcpy(((PU_EMRPOLYBEZIER) record)->aptl,points,cbPoints); + } + return(record); +} + +// Functions with the same form starting with U_EMR_POLYPOLYLINE +char *U_EMR_CORE2_set(uint32_t iType, U_RECTL rclBounds, const uint32_t nPolys, const uint32_t *aPolyCounts,const uint32_t cptl, const U_POINTL *points){ + char *record; + int cbPolys,cbPoints,off; + int irecsize; + + cbPoints = sizeof(U_POINTL)*cptl; + cbPolys = sizeof(uint32_t)*nPolys; + irecsize = sizeof(U_EMRPOLYPOLYLINE) + cbPoints + cbPolys - sizeof(uint32_t); // First instance of each is in struct + record = malloc(irecsize); + if(record){ + ((PU_EMR) record)->iType = iType; + ((PU_EMR) record)->nSize = irecsize; + ((PU_EMRPOLYPOLYLINE) record)->rclBounds = rclBounds; + ((PU_EMRPOLYPOLYLINE) record)->nPolys = nPolys; + ((PU_EMRPOLYPOLYLINE) record)->cptl = cptl; + memcpy(((PU_EMRPOLYPOLYLINE) record)->aPolyCounts,aPolyCounts,cbPolys); + off = sizeof(U_EMRPOLYPOLYLINE) - 4 + cbPolys; + memcpy(record + off,points,cbPoints); + } + return(record); +} + +// Functions with the same form starting with U_EMR_SETMAPMODE_set +char *U_EMR_CORE3_set(uint32_t iType, uint32_t iMode){ + char *record; + int irecsize; + + irecsize = sizeof(U_EMRSETMAPMODE); + record = malloc(irecsize); + if(record){ + ((PU_EMR) record)->iType = iType; + ((PU_EMR) record)->nSize = irecsize; + ((PU_EMRSETMAPMODE)record)->iMode = iMode; + } + return(record); +} + +// Functions taking a single U_RECT or U_RECTL, starting with U_EMRELLIPSE_set, also U_EMRFILLPATH, +char *U_EMR_CORE4_set(uint32_t iType, U_RECTL rclBox){ + char *record; + int irecsize; + + irecsize = sizeof(U_EMRELLIPSE); + record = malloc(irecsize); + memset(record,0,irecsize); + if(record){ + ((PU_EMR) record)->iType = iType; + ((PU_EMR) record)->nSize = irecsize; + ((PU_EMRELLIPSE)record)->rclBox = rclBox; // bounding rectangle in logical units + } + return(record); +} + +// Functions with the same form starting with U_EMRSETMETARGN_set +char *U_EMR_CORE5_set(uint32_t iType){ + char *record; + int irecsize = 8; + + record = malloc(irecsize); + if(record){ + ((PU_EMR) record)->iType = iType; + ((PU_EMR) record)->nSize = irecsize; + } + return(record); +} + +// Functions with the same form starting with U_EMRPOLYBEZIER16_set +char *U_EMR_CORE6_set(uint32_t iType, U_RECTL rclBounds, const uint32_t cpts, const U_POINT16 *points){ + char *record; + int cbPoints,cbPoints4,off; + int irecsize; + + cbPoints = sizeof(U_POINT16)*cpts; + cbPoints4 = UP4(cbPoints); + off = sizeof(U_EMR) + sizeof(U_RECTL) + sizeof(U_NUM_POINT16); // offset to the start of the variable region + irecsize = off + cbPoints4; // First instance is in struct + record = malloc(irecsize); + if(record){ + ((PU_EMR) record)->iType = iType; + ((PU_EMR) record)->nSize = irecsize; + ((PU_EMRPOLYBEZIER16) record)->rclBounds = rclBounds; + ((PU_EMRPOLYBEZIER16) record)->cpts = cpts; + memcpy(record + off, points, cbPoints); + if(cbPoints < cbPoints4){ + off += cbPoints; + memset(record + off, 0, cbPoints4 - cbPoints); + } + } + return(record); +} + + +// Functions that take a single struct argument which contains two uint32_t, starting with U_EMRSETWINDOWEXTEX_set +// these all pass two 32 bit ints and are cast by the caller to U_PAIR +char *U_EMR_CORE7_set(uint32_t iType, U_PAIR pair){ + char *record; + int irecsize = sizeof(U_EMRGENERICPAIR); + + record = malloc(irecsize); + if(record){ + ((PU_EMR) record)->iType = iType; + ((PU_EMR) record)->nSize = irecsize; + ((PU_EMRGENERICPAIR)record)->pair = pair; + } + return(record); +} + +// For U_EMREXTTEXTOUTA and U_EMREXTTEXTOUTW +char *U_EMR_CORE8_set( + uint32_t iType, + U_RECTL rclBounds, // Bounding rectangle in device units + uint32_t iGraphicsMode, // Graphics mode Enumeration + U_FLOAT exScale, // scale to 0.01 mm units ( only if iGraphicsMode & GM_COMPATIBLE) + U_FLOAT eyScale, // scale to 0.01 mm units ( only if iGraphicsMode & GM_COMPATIBLE) + PU_EMRTEXT emrtext // Text parameters + ){ + char *record; + int irecsize,cbString,cbString4,cbDx,cbEmrtext,cbEmrtextAll; + uint32_t *loffDx; + int csize; + + if( iType == U_EMR_EXTTEXTOUTA){ csize = 1; } // how many bytes per character + else if(iType == U_EMR_EXTTEXTOUTW){ csize = 2; } + else { return(NULL); } + + cbString = csize * emrtext->nChars; + cbString4 = UP4(cbString); // size of the string buffer + cbEmrtext = sizeof(U_EMRTEXT); // size of the constant part of the U_EMRTEXT structure + if(!(emrtext->fOptions & U_ETO_NO_RECT)){ cbEmrtext += sizeof(U_RECTL); } // plus the variable U_RECTL, when it is present + cbDx = emrtext->nChars * sizeof(int32_t); // size of Dx buffer + if(emrtext->fOptions & U_ETO_PDY)cbDx += cbDx; // size of Dx buffer when both x and y offsets are used + cbEmrtextAll = cbEmrtext + sizeof(uint32_t) + cbString4 + cbDx; // structure (+- rect) + offDx + string buf + dx buf + offDx + + /* adjust offset fields in emrtext to match the EMRTEXTOUT* field, currently they match EMRTEXT. + This works because the variable pieces have all been moved outside of the U_EMRTEXT and U_EMRTEXTOUTA strutures. + */ + ((PU_EMRTEXT)emrtext)->offString += sizeof(U_EMREXTTEXTOUTA) - sizeof(U_EMRTEXT); // adjust offString + loffDx = (uint32_t *)((char *)emrtext + cbEmrtext); + *loffDx += sizeof(U_EMREXTTEXTOUTA) - sizeof(U_EMRTEXT); + + // final record size is: U_EMREXTTEXTOUTA (includes constant part of U_EMRTEXT) + U_RECTL (if present) + offDx + dx buffer + string buffer + irecsize = sizeof(U_EMREXTTEXTOUTA) + cbEmrtextAll - sizeof(U_EMRTEXT); // do not count core emrtext strcture twice + record = malloc(irecsize); + if(record){ + ((PU_EMR) record)->iType = iType; + ((PU_EMR) record)->nSize = irecsize; + ((PU_EMREXTTEXTOUTA) record)->iGraphicsMode = iGraphicsMode; + ((PU_EMREXTTEXTOUTA) record)->rclBounds = rclBounds; + ((PU_EMREXTTEXTOUTA) record)->exScale = exScale; + ((PU_EMREXTTEXTOUTA) record)->eyScale = eyScale; + // copy the adjusted U_EMRTEXT into the emrtext part of the full record.. + memcpy(&(((PU_EMREXTTEXTOUTA) record)->emrtext), emrtext, cbEmrtextAll); + } + return(record); +} + +// Functions that take a rect and a pair of points, starting with U_EMRARC_set +char *U_EMR_CORE9_set(uint32_t iType, U_RECTL rclBox, U_POINTL ptlStart, U_POINTL ptlEnd){ + char *record; + int irecsize = sizeof(U_EMRARC); + + record = malloc(irecsize); + if(record){ + ((PU_EMR) record)->iType = iType; + ((PU_EMR) record)->nSize = irecsize; + ((PU_EMRARC) record)->rclBox = rclBox; + ((PU_EMRARC) record)->ptlStart = ptlStart; + ((PU_EMRARC) record)->ptlEnd = ptlEnd; + } + return(record); +} + +// Functions with the same form starting with U_EMR_POLYPOLYLINE16 +char *U_EMR_CORE10_set(uint32_t iType, U_RECTL rclBounds, const uint32_t nPolys, const uint32_t *aPolyCounts,const uint32_t cpts, const U_POINT16 *points){ + char *record; + int cbPoints,cbPolys,off; + int irecsize; + + cbPolys = sizeof(uint32_t)*nPolys; + cbPoints = sizeof(U_POINT16)*cpts; + irecsize = sizeof(U_EMRPOLYPOLYLINE16) + cbPoints + cbPolys - sizeof(uint32_t); // First instance of each is in struct + record = malloc(irecsize); + if(record){ + ((PU_EMR) record)->iType = iType; + ((PU_EMR) record)->nSize = irecsize; + ((PU_EMRPOLYPOLYLINE16) record)->rclBounds = rclBounds; + ((PU_EMRPOLYPOLYLINE16) record)->nPolys = nPolys; + ((PU_EMRPOLYPOLYLINE16) record)->cpts = cpts; + memcpy(((PU_EMRPOLYPOLYLINE16) record)->aPolyCounts,aPolyCounts,cbPolys); + off = sizeof(U_EMRPOLYPOLYLINE16) - 4 + cbPolys; + memcpy(record + off,points,cbPoints); + } + return(record); +} + +// common code for U_EMRINVERTRGN and U_EMRPAINTRGN, +char *U_EMR_CORE11_set(uint32_t iType, PU_RGNDATA RgnData){ + char *record; + int irecsize; + int cbRgns,cbRgns4,rds,rds4,off; + + if(!RgnData)return(NULL); + cbRgns = ((PU_RGNDATAHEADER) RgnData)->nRgnSize; + cbRgns4 = UP4(cbRgns); + rds = sizeof(U_RGNDATAHEADER) + cbRgns; + rds4 = UP4(rds); + irecsize = sizeof(U_EMRINVERTRGN) - sizeof(U_RECTL) + cbRgns4; // core + array - overlap of one rectL + record = malloc(irecsize); + if(record){ + ((PU_EMR) record)->iType = iType; + ((PU_EMR) record)->nSize = irecsize; + ((PU_EMRINVERTRGN) record)->rclBounds = ((PU_RGNDATAHEADER) RgnData)->rclBounds; + ((PU_EMRINVERTRGN) record)->cbRgnData = rds; + off = sizeof(U_EMRINVERTRGN) - sizeof(U_RGNDATA); + memcpy(record + off, RgnData, rds); + off += rds; + if(rds < rds4){ memset(record + off,0, rds4 - rds); } // clear any unused bytes + } + return(record); +} + + +// common code for U_EMRCREATEMONOBRUSH_set and U_EMRCREATEDIBPATTERNBRUSHPT_set, +char *U_EMR_CORE12_set( + uint32_t iType, + uint32_t ihBrush, // Index to place object in EMF object table (this entry must not yet exist) + uint32_t iUsage, // DIBcolors Enumeration + PU_BITMAPINFO Bmi, // (Optional) bitmapbuffer (U_BITMAPINFO + pixel array) + const uint32_t cbPx, // Size in bytes of pixel array (row stride * height, there may be some padding at the end of each row) + const char *Px // (Optional) bitmapbuffer (pixel array section ) + ){ + char *record; + int irecsize; + int cbImage,cbImage4,cbBmi,off; + + SET_CB_FROM_PXBMI(Px,Bmi,cbImage,cbImage4,cbBmi,cbPx); + + irecsize = sizeof(U_EMRCREATEMONOBRUSH) + cbBmi + cbImage4; + record = malloc(irecsize); + if(record){ + ((PU_EMR) record)->iType = iType; + ((PU_EMR) record)->nSize = irecsize; + ((PU_EMRCREATEMONOBRUSH) record)->ihBrush = ihBrush; + ((PU_EMRCREATEMONOBRUSH) record)->iUsage = iUsage; + if(cbBmi){ + off = sizeof(U_EMRCREATEMONOBRUSH); + memcpy(record + off, Bmi, cbBmi); + ((PU_EMRCREATEMONOBRUSH) record)->offBmi = off; + ((PU_EMRCREATEMONOBRUSH) record)->cbBmi = cbBmi; + off += cbBmi; + memcpy(record + off, Px, cbPx); + ((PU_EMRCREATEMONOBRUSH) record)->offBits = off; + ((PU_EMRCREATEMONOBRUSH) record)->cbBits = cbImage; + } + else { + ((PU_EMRCREATEMONOBRUSH) record)->offBmi = 0; + ((PU_EMRCREATEMONOBRUSH) record)->cbBmi = 0; + ((PU_EMRCREATEMONOBRUSH) record)->offBits = 0; + ((PU_EMRCREATEMONOBRUSH) record)->cbBits = 0; + } + } + return(record); +} + +// common code for U_EMRBLEND_set and U_EMRTRANSPARENTBLT_set, +char *U_EMR_CORE13_set( + uint32_t iType, + U_RECTL rclBounds, // Bounding rectangle in device units + U_POINTL Dest, // Destination UL corner in logical units + U_POINTL cDest, // Destination width in logical units + U_POINTL Src, // Source UL corner in logical units + U_POINTL cSrc, // Src W & H in logical units + U_XFORM xformSrc, // Transform to apply to source + U_COLORREF crBkColorSrc, // Background color + uint32_t iUsageSrc, // DIBcolors Enumeration + uint32_t Data, // The meaning and type of this field varies, but it is always 4 bytes + const PU_BITMAPINFO Bmi, // (Optional) bitmapbuffer (U_BITMAPINFO section) + const uint32_t cbPx, // Size in bytes of pixel array (row stride * height, there may be some padding at the end of each row) + char *Px // (Optional) bitmapbuffer (pixel array section ) + ){ + char *record; + int irecsize; + int cbImage,cbImage4,cbBmi,off; + + SET_CB_FROM_PXBMI(Px,Bmi,cbImage,cbImage4,cbBmi,cbPx); + + irecsize = sizeof(U_EMRALPHABLEND) + cbBmi + cbImage4; + record = malloc(irecsize); + if(record){ + ((PU_EMR) record)->iType = iType; + ((PU_EMR) record)->nSize = irecsize; + ((PU_EMRALPHABLEND) record)->rclBounds = rclBounds; + ((PU_EMRALPHABLEND) record)->Dest = Dest; + ((PU_EMRALPHABLEND) record)->cDest = cDest; + ((PU_EMRALPHABLEND) record)->Blend = *((PU_BLEND)&Data); + ((PU_EMRALPHABLEND) record)->Src = Src; + ((PU_EMRALPHABLEND) record)->xformSrc = xformSrc; + ((PU_EMRALPHABLEND) record)->crBkColorSrc = crBkColorSrc; + ((PU_EMRALPHABLEND) record)->iUsageSrc = iUsageSrc; + off = sizeof(U_EMRALPHABLEND); + APPEND_PXBMISRC(record, U_EMRALPHABLEND, cbBmi, Bmi, Px, cbImage, cbImage4); + ((PU_EMRALPHABLEND) record)->cSrc = cSrc; + } + return(record); +} +//! @endcond + +/* ********************************************************************************************** +These are the core EMR functions, each creates a particular type of record. +All return these records via a char* pointer, which is NULL if the call failed. +They are listed in order by the corresponding U_EMR_* index number. +*********************************************************************************************** */ + +// U_EMRHEADER_set 1 + +/** + \brief Allocate and construct a U_EMRHEADER record. + \return pointer to U_EMRHEADER record, or NULL on error. + \param rclBounds Bounding rectangle in device units + \param rclFrame Bounding rectangle in 0.01 mm units + \param pfmtDesc Pointer to a PixelFormatDescriptor + \param nDesc number of characters in Description, will include first three '\0' + \param Description Description, formatted like: text1\0text2\0\0 + \param szlDevice Reference device size in pixels + \param szlMillimeters Reference device size in 0.01 mm + \param bOpenGL nonZero if OpenGL commands are included +*/ +char *U_EMRHEADER_set( + const U_RECTL rclBounds, + const U_RECTL rclFrame, + U_PIXELFORMATDESCRIPTOR* const pfmtDesc, + U_CBSTR nDesc, + uint16_t* const Description, + const U_SIZEL szlDevice, + const U_SIZEL szlMillimeters, + const uint32_t bOpenGL + ){ + + char *record; + int cbPFD,cbDesc,cbDesc4; + uint32_t off; + int irecsize; + + if(pfmtDesc){ cbPFD = sizeof(U_PIXELFORMATDESCRIPTOR); } + else { cbPFD = 0; } + if(Description){ cbDesc = 2*nDesc; } // also copy the terminator. Size is in bytes + else { cbDesc = 0; } + cbDesc4 = UP4(cbDesc); + irecsize = sizeof(U_EMRHEADER) + cbPFD + cbDesc4; + record = malloc(irecsize); + if(record){ + off = sizeof(U_EMRHEADER); + ((PU_EMR) record)->iType = U_EMR_HEADER; + ((PU_EMR) record)->nSize = irecsize; + ((PU_EMRHEADER) record)->rclBounds = rclBounds; + ((PU_EMRHEADER) record)->rclFrame = rclFrame; + ((PU_EMRHEADER) record)->dSignature = U_ENHMETA_SIGNATURE; + ((PU_EMRHEADER) record)->nVersion = U_ENHMETA_VERSION; + ((PU_EMRHEADER) record)->nBytes = 0; // Not known yet + ((PU_EMRHEADER) record)->nRecords = 0; // Not known yet + ((PU_EMRHEADER) record)->nHandles = 0; // Not known yet + ((PU_EMRHEADER) record)->sReserved = 0; // Must be 0 + ((PU_EMRHEADER) record)->nDescription = nDesc; + ((PU_EMRHEADER) record)->offDescription = 0; // may change below + ((PU_EMRHEADER) record)->nPalEntries = 0; // Not known yet + ((PU_EMRHEADER) record)->szlDevice = szlDevice; + ((PU_EMRHEADER) record)->szlMillimeters = szlMillimeters; + ((PU_EMRHEADER) record)->cbPixelFormat = cbPFD; + ((PU_EMRHEADER) record)->offPixelFormat = 0; // may change below + ((PU_EMRHEADER) record)->bOpenGL = bOpenGL; + ((PU_EMRHEADER) record)->szlMicrometers.cx = szlMillimeters.cx*1000; + ((PU_EMRHEADER) record)->szlMicrometers.cy = szlMillimeters.cy*1000; + if(cbDesc4){ + ((PU_EMRHEADER) record)->offDescription = off; + memcpy(record + off, Description, cbDesc); + off += cbDesc; + if(cbDesc < cbDesc4)memset(record + off,0,cbDesc4-cbDesc); // clear any unused bytes + off += cbDesc4 - cbDesc; + } + if(cbPFD){ + ((PU_EMRHEADER) record)->offPixelFormat = off; + memcpy(record+off,pfmtDesc,cbPFD); + } + } + return(record); +} + +// U_EMRPOLYBEZIER_set 2 +/** + \brief Allocate and construct a U_EMR_POLYBEZIER record. + \return pointer to U_EMR_POLYBEZIER record, or NULL on error. + \param rclBounds bounding rectangle in device units + \param cptl Number of points to draw + \param points array of points +*/ +char *U_EMRPOLYBEZIER_set( + const U_RECTL rclBounds, + const uint32_t cptl, + const U_POINTL *points + ){ + return(U_EMR_CORE1_set(U_EMR_POLYBEZIER, rclBounds, cptl, points)); +} + +// U_EMRPOLYGON_set 3 +/** + \brief Allocate and construct a U_EMR_POLYGON record. + \return pointer to U_EMR_POLYGON record, or NULL on error. + \param rclBounds bounding rectangle in device units + \param cptl Number of points to draw + \param points array of points +*/ +char *U_EMRPOLYGON_set( + const U_RECTL rclBounds, + const uint32_t cptl, + const U_POINTL *points + ){ + return(U_EMR_CORE1_set(U_EMR_POLYGON, rclBounds, cptl, points)); +} + +// U_EMRPOLYLINE_set 4 +/** + \brief Allocate and construct a U_EMR_POLYLINE record. + \return pointer to U_EMR_POLYLINE record, or NULL on error. + \param rclBounds bounding rectangle in device units + \param cptl Number of points to draw + \param points array of points +*/ +char *U_EMRPOLYLINE_set( + const U_RECTL rclBounds, + const uint32_t cptl, + const U_POINTL *points + ){ + return(U_EMR_CORE1_set(U_EMR_POLYLINE, rclBounds, cptl, points)); +} + +// U_EMRPOLYBEZIERTO_set 5 +/** + \brief Allocate and construct a U_EMR_POLYBEZIERTO record. + \return pointer to U_EMR_POLYBEZIERTO record, or NULL on error. + \param rclBounds bounding rectangle in device units + \param cptl Number of points to draw + \param points array of points +*/ +char *U_EMRPOLYBEZIERTO_set( + const U_RECTL rclBounds, + const uint32_t cptl, + const U_POINTL *points + ){ + return(U_EMR_CORE1_set(U_EMR_POLYBEZIERTO, rclBounds, cptl, points)); +} + +// U_EMRPOLYLINETO_set 6 +/** + \brief Allocate and construct a U_EMR_POLYLINETO record. + \return pointer to U_EMR_POLYLINETO record, or NULL on error. + \param rclBounds bounding rectangle in device units + \param cptl Number of points to draw + \param points array of points +*/ +char *U_EMRPOLYLINETO_set( + const U_RECTL rclBounds, + const uint32_t cptl, + const U_POINTL *points + ){ + return(U_EMR_CORE1_set(U_EMR_POLYLINETO, rclBounds, cptl, points)); +} + +// U_EMRPOLYPOLYLINE_set 7 +/** + \brief Allocate and construct a U_EMR_POLYPOLYLINE record. + \return pointer to U_EMR_POLYPOLYLINE record, or NULL on error. + \param rclBounds bounding rectangle in device units + \param nPolys Number of elements in aPolyCounts + \param aPolyCounts Number of points in each poly (sequential) + \param cptl Total number of points (over all poly) + \param points array of points +*/ +char *U_EMRPOLYPOLYLINE_set( + const U_RECTL rclBounds, + const uint32_t nPolys, + const uint32_t *aPolyCounts, + const uint32_t cptl, + const U_POINTL *points + ){ + return(U_EMR_CORE2_set(U_EMR_POLYPOLYLINE, rclBounds, nPolys, aPolyCounts,cptl, points)); +} + +// U_EMRPOLYPOLYGON_set 8 +/** + \brief Allocate and construct a U_EMR_POLYPOLYGON record. + \return pointer to U_EMR_POLYPOLYGON record, or NULL on error. + \param rclBounds bounding rectangle in device units + \param nPolys Number of elements in aPolyCounts + \param aPolyCounts Number of points in each poly (sequential) + \param cptl Total number of points (over all poly) + \param points array of points +*/ +char *U_EMRPOLYPOLYGON_set( + const U_RECTL rclBounds, + const uint32_t nPolys, + const uint32_t *aPolyCounts, + const uint32_t cptl, + const U_POINTL *points + ){ + return(U_EMR_CORE2_set(U_EMR_POLYPOLYGON, rclBounds, nPolys, aPolyCounts,cptl, points)); +} + +// U_EMRSETWINDOWEXTEX_set 9 +/** + \brief Allocate and construct a U_EMR_SETWINDOWEXTEX record. + \return pointer to U_EMR_SETWINDOWEXTEX record, or NULL on error. + \param szlExtent H & V extent in logical units +*/ +char *U_EMRSETWINDOWEXTEX_set( + const U_SIZEL szlExtent + ){ + U_PAIR temp; + temp.x = szlExtent.cx; + temp.y = szlExtent.cy; + return(U_EMR_CORE7_set(U_EMR_SETWINDOWEXTEX, temp)); +} + +// U_EMRSETWINDOWORGEX_set 10 +/** + \brief Allocate and construct a U_EMR_SETWINDOWORGEX record. + \return pointer to U_EMR_SETWINDOWORGEX record, or NULL on error. + \param ptlOrigin H & V origin in logical units +*/ +char *U_EMRSETWINDOWORGEX_set( + const U_POINTL ptlOrigin + ){ + return(U_EMR_CORE7_set(U_EMR_SETWINDOWORGEX, ptlOrigin)); // U_PAIR and U_POINTL are the same thing +} + +// U_EMRSETVIEWPORTEXTEX_set 11 +/** + \brief Allocate and construct a U_EMR_SETVIEWPORTEXTEX record. + \return pointer to U_EMR_SETVIEWPORTEXTEX record, or NULL on error. + \param szlExtent H & V extent in logical units +*/ +char *U_EMRSETVIEWPORTEXTEX_set( + const U_SIZEL szlExtent + ){ + U_PAIR temp; + temp.x = szlExtent.cx; + temp.y = szlExtent.cy; + return(U_EMR_CORE7_set(U_EMR_SETVIEWPORTEXTEX, temp)); +} + +// U_EMRSETVIEWPORTORGEX_set 12 +/** + \brief Allocate and construct a U_EMR_SETVIEWPORTORGEX record. + \return pointer to U_EMR_SETVIEWPORTORGEX record, or NULL on error. + \param ptlOrigin H & V origin in logical units +*/ +char *U_EMRSETVIEWPORTORGEX_set( + const U_POINTL ptlOrigin + ){ + return(U_EMR_CORE7_set(U_EMR_SETVIEWPORTORGEX, ptlOrigin)); // U_PAIR and U_POINTL are the same thing +} + +// U_EMRSETBRUSHORGEX_set 13 +/** + \brief Allocate and construct a U_EMR_SETBRUSHORGEX record. + \return pointer to U_EMR_SETBRUSHORGEX record, or NULL on error. + \param ptlOrigin H & V origin in logical units +*/ +char *U_EMRSETBRUSHORGEX_set( + const U_POINTL ptlOrigin + ){ + return(U_EMR_CORE7_set(U_EMR_SETBRUSHORGEX, *((PU_PAIR) & ptlOrigin))); +} + +// U_EMREOF_set 14 +/** + \brief Allocate and construct a U_EMR_EOF record. + \return pointer to U_EMR_EOF record, or NULL on error. + \param cbPalEntries Number of palette entries + \param PalEntries (optional) array of PalEntries + \param et tracking information, needed for nSizeLast calculation +*/ +char *U_EMREOF_set( + const U_CBPLENTRIES cbPalEntries, + const PU_LOGPLTNTRY PalEntries, + EMFTRACK *et + ){ + char *record; + char *ptr; + int irecsize; + int cbPals; // space allocated for Palette Entries + uint32_t off; + + if(cbPalEntries && !PalEntries)return(NULL); + if(!et)return(NULL); + cbPals = cbPalEntries * sizeof(U_LOGPLTNTRY); + irecsize = sizeof(U_EMREOF) + cbPals + sizeof(uint32_t); //invariant core, variable palette, palette byte count + record = malloc(irecsize); + if(record){ + ((PU_EMR) record)->iType = U_EMR_EOF; + ((PU_EMR) record)->nSize = irecsize; + ((PU_EMREOF) record)->cbPalEntries = cbPalEntries; + ((PU_EMREOF) record)->offPalEntries = 0; // May be changed below + off = sizeof(U_EMREOF); //start of the variable region + if(cbPals){ + ((PU_EMREOF) record)->offPalEntries = off; + memcpy(record+off,PalEntries,cbPals); + off += cbPals; + } + ptr = record + off; + *(uint32_t *)ptr = irecsize + et->used; // EMREOF nSizeLast field, not at a fixed position, cannot be accessed by field name + } + et->PalEntries = cbPalEntries; + return(record); +} + + +// U_EMRSETPIXELV_set 15 +/** + \brief Allocate and construct a U_EMR_SETPIXELV record. + \return pointer to U_EMR_SETPIXELV record, or NULL on error. + \param ptlPixel Pixel coordinates (logical) + \param crColor Pixel color +*/ +char *U_EMRSETPIXELV_set( + const U_POINTL ptlPixel, + const U_COLORREF crColor + ){ + char *record; + int irecsize; + + irecsize = sizeof(U_EMRSETPIXELV); + record = malloc(irecsize); + if(record){ + ((PU_EMR) record)->iType = U_EMR_SETPIXELV; + ((PU_EMR) record)->nSize = irecsize; + ((PU_EMRSETPIXELV)record)->ptlPixel = ptlPixel; + ((PU_EMRSETPIXELV)record)->crColor = crColor; + } + return(record); +} + + +// U_EMRSETMAPPERFLAGS_set 16 +/** + \brief Allocate and construct a U_EMR_SETMAPPERFLAGS record. + \return pointer to U_EMR_SETMAPPERFLAGS record, or NULL on error. +*/ +char *U_EMRSETMAPPERFLAGS_set(void){ + char *record; + int irecsize; + + irecsize = sizeof(U_EMRSETMAPPERFLAGS); + record = malloc(irecsize); + if(record){ + ((PU_EMR) record)->iType = U_EMR_SETMAPPERFLAGS; + ((PU_EMR) record)->nSize = irecsize; + ((PU_EMRSETMAPPERFLAGS)record)->dwFlags = 1; + } + return(record); +} + +// U_EMRSETMAPMODE_set 17 +/** + \brief Allocate and construct a U_EMR_SETMAPMODE record. + \return pointer to U_EMR_SETMAPMODE record, or NULL on error. + \param iMode MapMode Enumeration +*/ +char *U_EMRSETMAPMODE_set( + const uint32_t iMode + ){ + return(U_EMR_CORE3_set(U_EMR_SETMAPMODE, iMode)); +} + +// U_EMRSETBKMODE_set 18 +/** + \brief Allocate and construct a U_EMR_SETBKMODE record. + \return pointer to U_EMR_SETBKMODE record, or NULL on error. + \param iMode BackgroundMode Enumeration +*/ +char *U_EMRSETBKMODE_set( + const uint32_t iMode + ){ + return(U_EMR_CORE3_set(U_EMR_SETBKMODE, iMode)); +} + +// U_EMRSETPOLYFILLMODE_set 19 +/** + \brief Allocate and construct a U_EMR_SETPOLYFILLMODE record. + \return pointer to U_EMR_SETPOLYFILLMODE record, or NULL on error. + \param iMode PolygonFillMode Enumeration +*/ +char *U_EMRSETPOLYFILLMODE_set( + const uint32_t iMode + ){ + return(U_EMR_CORE3_set(U_EMR_SETPOLYFILLMODE, iMode)); +} + +// U_EMRSETROP2_set 20 +/** + \brief Allocate and construct a U_EMR_SETROP2 record. + \return pointer to U_EMR_SETROP2 record, or NULL on error. + \param iMode RasterOperation2 Enumeration +*/ +char *U_EMRSETROP2_set( + const uint32_t iMode + ){ + return(U_EMR_CORE3_set(U_EMR_SETROP2, iMode)); +} + +// U_EMRSETSTRETCHBLTMODE_set 21 +/** + \brief Allocate and construct a U_EMR_SETSTRETCHBLTMODE record. + \return pointer to U_EMR_SETSTRETCHBLTMODE record, or NULL on error. + \param iMode StretchMode Enumeration +*/ +char *U_EMRSETSTRETCHBLTMODE_set( + const uint32_t iMode + ){ + return(U_EMR_CORE3_set(U_EMR_SETSTRETCHBLTMODE, iMode)); +} + +// U_EMRSETTEXTALIGN_set 22 +/** + \brief Allocate and construct a U_EMR_SETTEXTALIGN record. + \return pointer to U_EMR_SETTEXTALIGN record, or NULL on error. + \param iMode TextAlignment Enumeration +*/ +char *U_EMRSETTEXTALIGN_set( + const uint32_t iMode + ){ + return(U_EMR_CORE3_set(U_EMR_SETTEXTALIGN, iMode)); +} + +// U_EMRSETCOLORADJUSTMENT_set 23 +/** + \brief Allocate and construct a U_EMR_SETCOLORADJUSTMENT record. + \return pointer to U_EMR_SETCOLORADJUSTMENT record, or NULL on error. + \param ColorAdjustment Color Adjustment +*/ +char *U_EMRSETCOLORADJUSTMENT_set( + const U_COLORADJUSTMENT ColorAdjustment + ){ + char *record; + int irecsize; + + irecsize = sizeof(U_EMRSETCOLORADJUSTMENT); + record = malloc(irecsize); + if(record){ + ((PU_EMR) record)->iType = U_EMR_SETCOLORADJUSTMENT; + ((PU_EMR) record)->nSize = irecsize; + ((PU_EMRSETCOLORADJUSTMENT) record)->ColorAdjustment = ColorAdjustment; + } + return(record); +} + +// U_EMRSETTEXTCOLOR_set 24 +/** + \brief Allocate and construct a U_EMR_SETTEXTCOLOR record. + \return pointer to U_EMR_SETTEXTCOLOR record, or NULL on error. + \param crColor Text Color +*/ +char *U_EMRSETTEXTCOLOR_set( + const U_COLORREF crColor + ){ + return(U_EMR_CORE3_set(U_EMR_SETTEXTCOLOR, *(uint32_t *) &crColor)); +} + +// U_EMRSETBKCOLOR_set 25 +/** + \brief Allocate and construct a U_EMR_SETBKCOLOR record. + \return pointer to U_EMR_SETBKCOLOR record, or NULL on error. + \param crColor Background Color +*/ +char *U_EMRSETBKCOLOR_set( + const U_COLORREF crColor + ){ + return(U_EMR_CORE3_set(U_EMR_SETBKCOLOR, *(uint32_t *) &crColor)); +} + +// U_EMROFFSETCLIPRGN_set 26 +/** + \brief Allocate and construct a U_EMR_OFFSETCLIPRGN record. + \return pointer to U_EMR_OFFSETCLIPRGN record, or NULL on error. + \param ptl Clipping region +*/ +char *U_EMROFFSETCLIPRGN_set( + const U_POINTL ptl + ){ + return(U_EMR_CORE7_set(U_EMR_OFFSETCLIPRGN, ptl)); +} + +// U_EMRMOVETOEX_set 27 +/** + \brief Allocate and construct a U_EMR_MOVETOEX record. + \return pointer to U_EMR_MOVETOEX record, or NULL on error. + \param ptl Point coordinates +*/ +char *U_EMRMOVETOEX_set( + const U_POINTL ptl + ){ + return(U_EMR_CORE7_set(U_EMR_MOVETOEX, ptl)); +} + +// U_EMRSETMETARGN_set 28 +/** + \brief Allocate and construct a U_EMR_SETMETARGN record. + \return pointer to U_EMR_SETMETARGN record, or NULL on error. +*/ +char *U_EMRSETMETARGN_set(void){ + return(U_EMR_CORE5_set(U_EMR_SETMETARGN)); +} + +// U_EMREXCLUDECLIPRECT_set 29 +/** + \brief Allocate and construct a U_EMR_EXCLUDECLIPRECT record. + \return pointer to U_EMR_EXCLUDECLIPRECT record, or NULL on error. + \param rclClip Clipping Region +*/ +char *U_EMREXCLUDECLIPRECT_set( + const U_RECTL rclClip + ){ + return(U_EMR_CORE4_set(U_EMR_EXCLUDECLIPRECT,rclClip)); +} + +// U_EMRINTERSECTCLIPRECT_set 30 +/** + \brief Allocate and construct a U_EMR_INTERSECTCLIPRECT record. + \return pointer to U_EMR_INTERSECTCLIPRECT record, or NULL on error. + \param rclClip Clipping Region +*/ +char *U_EMRINTERSECTCLIPRECT_set( + const U_RECTL rclClip + ){ + return(U_EMR_CORE4_set(U_EMR_INTERSECTCLIPRECT,rclClip)); +} + +// U_EMRSCALEVIEWPORTEXTEX_set 31 +/** + \brief Allocate and construct a U_EMR_SCALEVIEWPORTEXTEX record. + \return pointer to U_EMR_SCALEVIEWPORTEXTEX record, or NULL on error. + \param xNum Horizontal multiplier (!=0) + \param xDenom Horizontal divisor (!=0) + \param yNum Vertical multiplier (!=0) + \param yDenom Vertical divisor (!=0) +*/ +char *U_EMRSCALEVIEWPORTEXTEX_set( + const int32_t xNum, + const int32_t xDenom, + const int32_t yNum, + const int32_t yDenom + ){ + return(U_EMR_CORE4_set(U_EMR_SCALEVIEWPORTEXTEX,(U_RECTL){xNum,xDenom,yNum,yDenom})); +} + + +// U_EMRSCALEWINDOWEXTEX_set 32 +/** + \brief Allocate and construct a U_EMR_SCALEWINDOWEXTEX record. + \return pointer to U_EMR_SCALEWINDOWEXTEX record, or NULL on error. + \param xNum Horizontal multiplier (!=0) + \param xDenom Horizontal divisor (!=0) + \param yNum Vertical multiplier (!=0) + \param yDenom Vertical divisor (!=0) +*/ +char *U_EMRSCALEWINDOWEXTEX_set( + const int32_t xNum, + const int32_t xDenom, + const int32_t yNum, + const int32_t yDenom + ){ + return(U_EMR_CORE4_set(U_EMR_SCALEWINDOWEXTEX,(U_RECTL){xNum,xDenom,yNum,yDenom})); +} + +// U_EMRSAVEDC_set 33 +/** + \brief Allocate and construct a U_EMR_SAVEDC record. + \return pointer to U_EMR_SAVEDC record, or NULL on error. +*/ +char *U_EMRSAVEDC_set(void){ + return(U_EMR_CORE5_set(U_EMR_SAVEDC)); +} + +// U_EMRRESTOREDC_set 34 +/** + \brief Allocate and construct a U_EMR_RESTOREDC record. + \return pointer to U_EMR_RESTOREDC record, or NULL on error. + \param iRelative DC to restore. -1 is preceding +*/ +char *U_EMRRESTOREDC_set( + const int32_t iRelative + ){ + return(U_EMR_CORE3_set(U_EMR_RESTOREDC, (uint32_t) iRelative)); +} + +// U_EMRSETWORLDTRANSFORM_set 35 +/** + \brief Allocate and construct a U_EMR_SETWORLDTRANSFORM record. + \return pointer to U_EMR_SETWORLDTRANSFORM record, or NULL on error. + \param xform Transform to use +*/ +char *U_EMRSETWORLDTRANSFORM_set( + const U_XFORM xform + ){ + char *record; + int irecsize; + + irecsize = sizeof(U_EMRSETWORLDTRANSFORM); + record = malloc(irecsize); + if(record){ + ((PU_EMR) record)->iType = U_EMR_SETWORLDTRANSFORM; + ((PU_EMR) record)->nSize = irecsize; + ((PU_EMRSETWORLDTRANSFORM) record)->xform = xform; + } + return(record); +} + +// U_EMRMODIFYWORLDTRANSFORM_set 36 +/** + \brief Allocate and construct a U_EMR_MODIFYWORLDTRANSFORM record. + \return pointer to U_EMR_MODIFYWORLDTRANSFORM record, or NULL on error. + \param xform Transform to use + \param iMode ModifyWorldTransformMode Enumeration +*/ +char *U_EMRMODIFYWORLDTRANSFORM_set( + const U_XFORM xform, + const uint32_t iMode + ){ + char *record; + int irecsize; + + irecsize = sizeof(U_EMRMODIFYWORLDTRANSFORM); + record = malloc(irecsize); + if(record){ + ((PU_EMR) record)->iType = U_EMR_MODIFYWORLDTRANSFORM; + ((PU_EMR) record)->nSize = irecsize; + ((PU_EMRMODIFYWORLDTRANSFORM) record)->xform = xform; + ((PU_EMRMODIFYWORLDTRANSFORM) record)->iMode = iMode; + } + return(record); +} + +// U_EMRSELECTOBJECT_set 37 +/** + \brief Allocate and construct a U_EMR_SELECTOBJECT record. + Use selectobject_set() instead of calling this function directly. + \return pointer to U_EMR_SELECTOBJECT record, or NULL on error. + \param ihObject Number of a stock or created object +*/ +char *U_EMRSELECTOBJECT_set( + const uint32_t ihObject + ){ + char *record; + int irecsize; + + irecsize = sizeof(U_EMRSELECTOBJECT); + record = malloc(irecsize); + if(record){ + ((PU_EMR) record)->iType = U_EMR_SELECTOBJECT; + ((PU_EMR) record)->nSize = irecsize; + ((PU_EMRSELECTOBJECT) record)->ihObject = ihObject; // Index of object to SELECT + } + return(record); +} + +// U_EMRCREATEPEN_set 38 +/** + \brief Allocate and construct a U_EMR_CREATEPEN record. + Use createpen_set() instead of calling this function directly. + \return pointer to U_EMR_CREATEPEN record, or NULL on error. + \param ihPen Handle of created pen + \param lopn U_LOGPEN structure describing this pen +*/ +char *U_EMRCREATEPEN_set( + const uint32_t ihPen, + const U_LOGPEN lopn + ){ + char *record; + int irecsize=sizeof(U_EMRCREATEPEN); + + record = malloc(irecsize); + if(record){ + ((PU_EMR) record)->iType = U_EMR_CREATEPEN; + ((PU_EMR) record)->nSize = irecsize; + ((PU_EMRCREATEPEN) record)->ihPen = ihPen; + ((PU_EMRCREATEPEN) record)->lopn = lopn; + } + return(record); +} + +// U_EMRCREATEBRUSHINDIRECT_set 39 +/** + \brief Allocate and construct a U_EMR_CREATEBRUSHINDIRECT record. + Use createbrushindirect_set() instead of calling this function directly. + \return pointer to U_EMR_CREATEBRUSHINDIRECT record, or NULL on error. + \param ihBrush Index to place object in EMF object table (this entry must not yet exist) + \param lb Brush properties +*/ +char *U_EMRCREATEBRUSHINDIRECT_set( + const uint32_t ihBrush, + const U_LOGBRUSH lb + ){ + char *record; + int irecsize; + + irecsize = sizeof(U_EMRCREATEBRUSHINDIRECT); + record = malloc(irecsize); + if(record){ + ((PU_EMR) record)->iType = U_EMR_CREATEBRUSHINDIRECT; + ((PU_EMR) record)->nSize = irecsize; + ((PU_EMRCREATEBRUSHINDIRECT) record)->ihBrush = ihBrush; // Index to place object in EMF object table (this entry must not yet exist) + ((PU_EMRCREATEBRUSHINDIRECT) record)->lb = lb; + } + return(record); +} + +// U_EMRDELETEOBJECT_set 40 +/** + \brief Allocate and construct a U_EMR_DELETEOBJECT record. + Use deleteobject_set() instead of calling this function directly. + \return pointer to U_EMR_DELETEOBJECT record, or NULL on error. + \param ihObject Number of a stock or created object +*/ +char *U_EMRDELETEOBJECT_set( + const uint32_t ihObject + ){ + char *record; + int irecsize; + + irecsize = sizeof(U_EMRDELETEOBJECT); + record = malloc(irecsize); + if(record){ + ((PU_EMR) record)->iType = U_EMR_DELETEOBJECT; + ((PU_EMR) record)->nSize = irecsize; + ((PU_EMRDELETEOBJECT) record)->ihObject = ihObject; // Index of object to DELETE + } + return(record); +} + +// U_EMRANGLEARC_set 41 +/** + \brief Allocate and construct a U_EMR_ANGLEARC record. + \return pointer to U_EMR_ANGLEARC record, or NULL on error. + \param ptlCenter Center in logical units + \param nRadius Radius in logical units + \param eStartAngle Starting angle in degrees (counter clockwise from x axis) + \param eSweepAngle Sweep angle in degrees +*/ +char *U_EMRANGLEARC_set( + const U_POINTL ptlCenter, + const uint32_t nRadius, + const U_FLOAT eStartAngle, + const U_FLOAT eSweepAngle + ){ + char *record; + int irecsize; + + irecsize = sizeof(U_EMRANGLEARC); + record = malloc(irecsize); + if(record){ + ((PU_EMR) record)->iType = U_EMR_ANGLEARC; + ((PU_EMR) record)->nSize = irecsize; + ((PU_EMRANGLEARC) record)->ptlCenter = ptlCenter; + ((PU_EMRANGLEARC) record)->nRadius = nRadius; + ((PU_EMRANGLEARC) record)->eStartAngle = eStartAngle; + ((PU_EMRANGLEARC) record)->eSweepAngle = eSweepAngle; + } + return(record); +} + +// U_EMRELLIPSE_set 42 +/** + \brief Allocate and construct a U_EMR_ELLIPSE record. + \return pointer to U_EMR_ELLIPSE record, or NULL on error. + \param rclBox bounding rectangle in logical units +*/ +char *U_EMRELLIPSE_set( + const U_RECTL rclBox + ){ + return(U_EMR_CORE4_set(U_EMR_ELLIPSE,rclBox)); +} + +// U_EMRRECTANGLE_set 43 +/** + \brief Allocate and construct a U_EMR_RECTANGLE record. + \return pointer to U_EMR_RECTANGLE record, or NULL on error. + \param rclBox bounding rectangle in logical units +*/ +char *U_EMRRECTANGLE_set( + const U_RECTL rclBox + ){ + return(U_EMR_CORE4_set(U_EMR_RECTANGLE,rclBox)); +} + +// U_EMRROUNDRECT_set 44 +/** + \brief Allocate and construct a U_EMR_ROUNDRECT record. + \return pointer to U_EMR_ROUNDRECT record, or NULL on error. + \param rclBox bounding rectangle in logical units + \param szlCorner W & H in logical units of ellipse used to round corner +*/ +char *U_EMRROUNDRECT_set( + const U_RECTL rclBox, + const U_SIZEL szlCorner + ){ + char *record; + int irecsize; + + irecsize = sizeof(U_EMRROUNDRECT); + record = malloc(irecsize); + if(record){ + ((PU_EMR) record)->iType = U_EMR_ROUNDRECT; + ((PU_EMR) record)->nSize = irecsize; + ((PU_EMRROUNDRECT) record)->rclBox = rclBox; + ((PU_EMRROUNDRECT) record)->szlCorner = szlCorner; + } + return(record); +} + +// U_EMRARC_set 45 +/** + \brief Allocate and construct a U_EMR_ARC record. + \return pointer to U_EMR_ARC record, or NULL on error. + \param rclBox bounding rectangle in logical units + \param ptlStart Start point in logical units + \param ptlEnd End point in logical units +*/ +char *U_EMRARC_set( + const U_RECTL rclBox, + const U_POINTL ptlStart, + const U_POINTL ptlEnd + ){ + return(U_EMR_CORE9_set(U_EMR_ARC,rclBox, ptlStart, ptlEnd)); +} + +// U_EMRCHORD_set 46 +/** + \brief Allocate and construct a U_EMR_CHORD record. + \return pointer to U_EMR_CHORD record, or NULL on error. + \param rclBox bounding rectangle in logical units + \param ptlStart Start point in logical units + \param ptlEnd End point in logical units +*/ +char *U_EMRCHORD_set( + const U_RECTL rclBox, + const U_POINTL ptlStart, + const U_POINTL ptlEnd + ){ + return(U_EMR_CORE9_set(U_EMR_CHORD,rclBox, ptlStart, ptlEnd)); +} + +// U_EMRPIE_set 47 +/** + \brief Allocate and construct a U_EMR_PIE record. + \return pointer to U_EMR_PIE record, or NULL on error. + \param rclBox bounding rectangle in logical units + \param ptlStart Start point in logical units + \param ptlEnd End point in logical units +*/ +char *U_EMRPIE_set( + const U_RECTL rclBox, + const U_POINTL ptlStart, + const U_POINTL ptlEnd + ){ + return(U_EMR_CORE9_set(U_EMR_PIE,rclBox, ptlStart, ptlEnd)); +} + +// U_EMRSELECTPALETTE_set 48 +/** + \brief Allocate and construct a U_EMR_SELECTPALETTE record. + \return pointer to U_EMR_SELECTPALETTE record, or NULL on error. + \param ihPal Index of a Palette object in the EMF object table +*/ +char *U_EMRSELECTPALETTE_set( + const uint32_t ihPal + ){ + return(U_EMR_CORE3_set(U_EMR_SELECTPALETTE, ihPal)); +} + +// U_EMRCREATEPALETTE_set 49 +/** + \brief Allocate and construct a U_EMR_CREATEPALETTE record. + Use createpalette_set() instead of calling this function directly. + \return pointer to U_EMR_CREATEPALETTE record, or NULL on error. + \param ihPal Index to place object in EMF object table (this entry must not yet exist) + \param lgpl Palette properties +*/ +char *U_EMRCREATEPALETTE_set( + const uint32_t ihPal, + const U_LOGPALETTE lgpl + ){ + char *record; + int irecsize; + + irecsize = sizeof(U_EMRCREATEPALETTE); + record = malloc(irecsize); + if(record){ + ((PU_EMR) record)->iType = U_EMR_CREATEPALETTE; + ((PU_EMR) record)->nSize = irecsize; + ((PU_EMRCREATEPALETTE) record)->ihPal = ihPal; + ((PU_EMRCREATEPALETTE) record)->lgpl = lgpl; + } + return(record); +} + +// U_EMRSETPALETTEENTRIES_set 50 +/** + \brief Allocate and construct a U_EMR_SETPALETTEENTRIES record. + Use setpaletteentries_set() instead of calling this function directly. + \return pointer to U_EMR_SETPALETTEENTRIES record, or NULL on error. + \param ihPal Index of a Palette object in the EMF object table + \param iStart First Palette entry in selected object to set + \param cEntries Number of Palette entries in selected object to set + \param aPalEntries Values to set with +*/ +char *U_EMRSETPALETTEENTRIES_set( + const uint32_t ihPal, + const uint32_t iStart, + const U_NUM_LOGPLTNTRY cEntries, + const PU_LOGPLTNTRY aPalEntries + ){ + char *record; + int irecsize; + int cbPals; + + if(!aPalEntries)return(NULL); + cbPals = cEntries * sizeof(U_LOGPLTNTRY); + irecsize = sizeof(U_EMRSETPALETTEENTRIES) + cbPals - sizeof(U_LOGPLTNTRY); + record = malloc(irecsize); + if(record){ + ((PU_EMR) record)->iType = U_EMR_SETPALETTEENTRIES; + ((PU_EMR) record)->nSize = irecsize; + ((PU_EMRSETPALETTEENTRIES) record)->ihPal = ihPal; + ((PU_EMRSETPALETTEENTRIES) record)->iStart = iStart; + ((PU_EMRSETPALETTEENTRIES) record)->cEntries = cEntries; + memcpy(((PU_EMRSETPALETTEENTRIES) record)->aPalEntries, aPalEntries,cbPals); + } + return(record); +} + +// U_EMRRESIZEPALETTE_set 51 +/** + \brief Allocate and construct a U_EMR_RESIZEPALETTE record. + \return pointer to U_EMR_RESIZEPALETTE record, or NULL on error. + \param ihPal Index of a Palette object in the EMF object table + \param cEntries Number to expand or truncate the Palette entry list to +*/ +char *U_EMRRESIZEPALETTE_set( + const uint32_t ihPal, + const uint32_t cEntries + ){ + return(U_EMR_CORE7_set(U_EMR_RESIZEPALETTE, (U_PAIR){ihPal,cEntries})); +} + +// U_EMRREALIZEPALETTE_set 52 +/** + \brief Allocate and construct a U_EMR_REALIZEPALETTE record. + \return pointer to U_EMR_REALIZEPALETTE record, or NULL on error. +*/ +char *U_EMRREALIZEPALETTE_set(void){ + return(U_EMR_CORE5_set(U_EMR_REALIZEPALETTE)); +} + +// U_EMREXTFLOODFILL_set 53 +/** + \brief Allocate and construct a U_EMR_EXTFLOODFILL record. + \return pointer to U_EMR_EXTFLOODFILL record, or NULL on error. + \param ptlStart Start point in logical units + \param crColor Color to fill with + \param iMode FloodFill Enumeration +*/ +char *U_EMREXTFLOODFILL_set( + const U_POINTL ptlStart, + const U_COLORREF crColor, + const uint32_t iMode + ){ + char *record; + int irecsize; + + irecsize = sizeof(U_EMREXTFLOODFILL); + record = malloc(irecsize); + if(record){ + ((PU_EMR) record)->iType = U_EMR_EXTFLOODFILL; + ((PU_EMR) record)->nSize = irecsize; + ((PU_EMREXTFLOODFILL) record)->ptlStart = ptlStart; + ((PU_EMREXTFLOODFILL) record)->crColor = crColor; + ((PU_EMREXTFLOODFILL) record)->iMode = iMode; + } + return(record); +} + +// U_EMRLINETO_set 54 +/** + \brief Allocate and construct a U_EMR_LINETO record. + \return pointer to U_EMR_LINETO record, or NULL on error. + \param ptl Point coordinates +*/ +char *U_EMRLINETO_set( + const U_POINTL ptl + ){ + return(U_EMR_CORE7_set(U_EMR_LINETO, ptl)); +} + +// U_EMRARCTO_set 55 +/** + \brief Allocate and construct a U_EMR_ARCTO record. + \return pointer to U_EMR_ARCTO record, or NULL on error. + \param rclBox bounding rectangle in logical units + \param ptlStart Start point in logical units + \param ptlEnd End point in logical units + + Note that the draw begins with a line from the current point to ptlStart, which is + not indicated in the Microsoft EMF documentation for this record. +*/ +char *U_EMRARCTO_set( + U_RECTL rclBox, + U_POINTL ptlStart, + U_POINTL ptlEnd + ){ + return(U_EMR_CORE9_set(U_EMR_ARCTO,rclBox, ptlStart, ptlEnd)); +} + +// U_EMRPOLYDRAW_set 56 +/** + \brief Allocate and construct a U_EMR_POLYDRAW record. + \return pointer to U_EMR_POLYDRAW record, or NULL on error. + \param rclBounds Bounding rectangle in device units + \param cptl Number of U_POINTL objects + \param aptl Array of U_POINTL objects + \param abTypes Array of Point Enumeration +*/ +char *U_EMRPOLYDRAW_set( + const U_RECTL rclBounds, + const U_NUM_POINTL cptl, + const U_POINTL *aptl, + const uint8_t *abTypes + ){ + char *record; + int irecsize; + int cbPoints, cbAbTypes, cbAbTypes4, off; + + if(!cptl || !aptl || !abTypes)return(NULL); + cbPoints = cptl * sizeof(U_POINTL); // space for aptl + cbAbTypes = cptl; // number of abTypes (same array size, 1 byte each) + cbAbTypes4 = UP4(cbAbTypes); // space for abTypes + irecsize = sizeof(U_EMRPOLYDRAW) + cbPoints + cbAbTypes4 - sizeof(U_POINTL) - 1; + record = malloc(irecsize); + if(record){ + ((PU_EMR) record)->iType = U_EMR_POLYDRAW; + ((PU_EMR) record)->nSize = irecsize; + ((PU_EMRPOLYDRAW) record)->rclBounds = rclBounds; + ((PU_EMRPOLYDRAW) record)->cptl = cptl; + off = sizeof(U_EMR) + sizeof(U_RECTL) + sizeof(uint32_t); // offset to first variable part + memcpy(record+off,aptl,cbPoints); + off += cbPoints; + memcpy(record+off,abTypes,cbAbTypes); + off += cbAbTypes; + if(cbAbTypes4 > cbAbTypes){ memset(record+off,0,cbAbTypes4-cbAbTypes); } // keeps valgrind happy (initialize padding after byte array) + } + return(record); +} + +// U_EMRSETARCDIRECTION_set 57 +/** + \brief Allocate and construct a U_EMR_SETARCDIRECTION record. + \return pointer to U_EMR_SETARCDIRECTION record, or NULL on error. + \param iArcDirection ArcDirection Enumeration +*/ +char *U_EMRSETARCDIRECTION_set( + const uint32_t iArcDirection + ){ + return(U_EMR_CORE3_set(U_EMR_SETARCDIRECTION, iArcDirection)); +} + +// U_EMRSETMITERLIMIT_set 58 +/** + \brief Allocate and construct a U_EMR_SETMITERLIMIT record. + \return pointer to U_EMR_SETMITERLIMIT record, or NULL on error. + \param eMiterLimit MapMode Enumeration +*/ +char *U_EMRSETMITERLIMIT_set( + const uint32_t eMiterLimit + ){ + return(U_EMR_CORE3_set(U_EMR_SETMITERLIMIT, eMiterLimit)); +} + + +// U_EMRBEGINPATH_set 59 +/** + \brief Allocate and construct a U_EMR_BEGINPATH record. + \return pointer to U_EMR_BEGINPATH record, or NULL on error. +*/ +char *U_EMRBEGINPATH_set(void){ + return(U_EMR_CORE5_set(U_EMR_BEGINPATH)); +} + +// U_EMRENDPATH_set 60 +/** + \brief Allocate and construct a U_EMR_ENDPATH record. + \return pointer to U_EMR_ENDPATH record, or NULL on error. +*/ +char *U_EMRENDPATH_set(void){ + return(U_EMR_CORE5_set(U_EMR_ENDPATH)); +} + +// U_EMRCLOSEFIGURE_set 61 +/** + \brief Allocate and construct a U_EMR_CLOSEFIGURE record. + \return pointer to U_EMR_CLOSEFIGURE record, or NULL on error. +*/ +char *U_EMRCLOSEFIGURE_set(void){ + return(U_EMR_CORE5_set(U_EMR_CLOSEFIGURE)); +} + +// U_EMRFILLPATH_set 62 +/** + \brief Allocate and construct a U_EMR_FILLPATH record. + \return pointer to U_EMR_FILLPATH record, or NULL on error. + \param rclBox Bounding rectangle in device units + + U_EMR_FILLPATH closes the open figure before filling. +*/ +char *U_EMRFILLPATH_set( + const U_RECTL rclBox + ){ + return(U_EMR_CORE4_set(U_EMR_FILLPATH,rclBox)); +} + +// U_EMRSTROKEANDFILLPATH_set 63 +/** + \brief Allocate and construct a U_EMR_STROKEANDFILLPATH record. + \return pointer to U_EMR_STROKEANDFILLPATH record, or NULL on error. + \param rclBox Bounding rectangle in device units + + U_EMR_STROKEANDFILLPATH closes the open figure before filling and stroking. + There appears to be no way to fill an open path while stroking it, as any one + of U_EMRFILLPATH, U_EMRSTROKEPATH, or U_EMRSTROKEANDFILEPATH will "use up" the path, +*/ +char *U_EMRSTROKEANDFILLPATH_set( + const U_RECTL rclBox + ){ + return(U_EMR_CORE4_set(U_EMR_STROKEANDFILLPATH,rclBox)); +} + +// U_EMRSTROKEPATH_set 64 +/** + \brief Allocate and construct a U_EMR_STROKEPATH record. + \return pointer to U_EMR_STROKEPATH record, or NULL on error. + \param rclBox Bounding rectangle in device units + + U_EMR_STROKEPATH does NOT close the open figure before stroking it. +*/ +char *U_EMRSTROKEPATH_set( + const U_RECTL rclBox + ){ + return(U_EMR_CORE4_set(U_EMR_STROKEPATH,rclBox)); +} + +// U_EMRFLATTENPATH_set 65 +/** + \brief Allocate and construct a U_EMR_FLATTENPATH record. + \return pointer to U_EMR_FLATTENPATH record, or NULL on error. +*/ +char *U_EMRFLATTENPATH_set(void){ + return(U_EMR_CORE5_set(U_EMR_FLATTENPATH)); +} + +// U_EMRWIDENPATH_set 66 +/** + \brief Allocate and construct a U_EMR_WIDENPATH record. + \return pointer to U_EMR_WIDENPATH record, or NULL on error. +*/ +char *U_EMRWIDENPATH_set(void){ + return(U_EMR_CORE5_set(U_EMR_WIDENPATH)); +} + +// U_EMRSELECTCLIPPATH_set 67 +/** + \brief Allocate and construct a U_EMR_SELECTCLIPPATH record. + \return pointer to U_EMR_SELECTCLIPPATH record, or NULL on error. + \param iMode RegionMode Enumeration +*/ +char *U_EMRSELECTCLIPPATH_set( + const uint32_t iMode + ){ + return(U_EMR_CORE3_set(U_EMR_SELECTCLIPPATH, iMode)); +} + +// U_EMRABORTPATH_set 68 +/** + \brief Allocate and construct a U_EMR_ABORTPATH record. + \return pointer to U_EMR_ABORTPATH record, or NULL on error. +*/ +char *U_EMRABORTPATH_set(void){ + return(U_EMR_CORE5_set(U_EMR_ABORTPATH)); +} + +// U_EMRUNDEF69 69 + +// U_EMRCOMMENT_set 70 Comment (any binary data, interpretation is program specific) +/** + \brief Allocate and construct a U_EMR_COMMENT record. + \return pointer to U_EMR_COMMENT record, or NULL on error. + \param cbData Number of bytes in comment + \param Data Comment (any binary data, interpretation is program specific) +*/ +char *U_EMRCOMMENT_set( + const U_CBDATA cbData, + const char *Data + ){ + char *record; + unsigned int cbData4; + int irecsize; + + cbData4 = UP4(cbData); + irecsize = sizeof(U_EMR) + sizeof(U_CBDATA) + cbData4; + record = malloc(irecsize); + if(record){ + ((PU_EMR) record)->iType = U_EMR_COMMENT; + ((PU_EMR) record)->nSize = irecsize; + ((PU_EMRCOMMENT) record)->cbData = cbData; + memcpy(record + irecsize - cbData4,Data,cbData); + if(cbData4 > cbData)memset(record + irecsize - cbData4 + cbData,0,cbData4-cbData); // clear any unused bytes + } + return(record); +} + +// U_EMRFILLRGN_set 71 +/** + \brief Allocate and construct a U_EMR_FILLRGN record. + Use fillrgn_set() instead of calling this function directly. + \return pointer to U_EMR_FILLRGN record, or NULL on error. + \param rclBounds Bounding rectangle in device units + \param ihBrush Index of a Brush object in the EMF object table + \param RgnData Pointer to a U_RGNDATA structure +*/ +char *U_EMRFILLRGN_set( + const U_RECTL rclBounds, + const uint32_t ihBrush, + const PU_RGNDATA RgnData + ){ + char *record; + int irecsize; + int cbRgns,cbRgns4,rds,rds4,off; + + if(!RgnData)return(NULL); + cbRgns = ((PU_RGNDATAHEADER) RgnData)->nRgnSize; + cbRgns4 = UP4(cbRgns); + rds = sizeof(U_RGNDATAHEADER) + cbRgns; + rds4 = UP4(rds); + irecsize = sizeof(U_EMRFILLRGN) - sizeof(U_RECTL) + cbRgns4; // core + array - overlap of one rectL + record = malloc(irecsize); + if(record){ + ((PU_EMR) record)->iType = U_EMR_FILLRGN; + ((PU_EMR) record)->nSize = irecsize; + ((PU_EMRFILLRGN) record)->rclBounds = rclBounds; + ((PU_EMRFILLRGN) record)->cbRgnData = rds; + ((PU_EMRFILLRGN) record)->ihBrush = ihBrush; + off = sizeof(U_EMRFILLRGN) - sizeof(U_RGNDATA); + memcpy(record + off, RgnData, rds); + off += rds; + if(rds < rds4){ memset(record + off,0, rds4 - rds); } // clear any unused bytes + } + return(record); +} + +// U_EMRFRAMERGN_set 72 +/** + \brief Allocate and construct a U_EMR_FRAMERGN record. + Use framegrn_set() instead of calling this function directly. + \return pointer to U_EMR_FRAMERGN record, or NULL on error. + \param rclBounds Bounding rectangle in device units + \param ihBrush Index of a Brush object in the EMF object table + \param szlStroke W & H of Brush stroke + \param RgnData Pointer to a U_RGNDATA structure +*/ +char *U_EMRFRAMERGN_set( + const U_RECTL rclBounds, + const uint32_t ihBrush, + const U_SIZEL szlStroke, + const PU_RGNDATA RgnData + ){ + char *record; + int irecsize; + int cbRgns,cbRgns4,rds,rds4,off; + + if(!RgnData)return(NULL); + cbRgns = ((PU_RGNDATAHEADER) RgnData)->nRgnSize; + cbRgns4 = UP4(cbRgns); + rds = sizeof(U_RGNDATAHEADER) + cbRgns; + rds4 = UP4(rds); + irecsize = sizeof(U_EMRFRAMERGN) - sizeof(U_RECTL) + cbRgns4; // core + array - overlap of one rectL + record = malloc(irecsize); + if(record){ + ((PU_EMR) record)->iType = U_EMR_FRAMERGN; + ((PU_EMR) record)->nSize = irecsize; + ((PU_EMRFRAMERGN) record)->rclBounds = rclBounds; + ((PU_EMRFRAMERGN) record)->cbRgnData = rds; + ((PU_EMRFRAMERGN) record)->ihBrush = ihBrush; + ((PU_EMRFRAMERGN) record)->szlStroke = szlStroke; + off = sizeof(U_EMRFRAMERGN) - sizeof(U_RGNDATA); + memcpy(record + off, RgnData, rds); + off += rds; + if(rds < rds4){ memset(record + off,0, rds4 - rds); } // clear any unused bytes + } + return(record); +} + +// U_EMRINVERTRGN_set 73 +/** + \brief Allocate and construct a U_EMR_INVERTRGN record. + \return pointer to U_EMR_INVERTRGN record, or NULL on error. + \param RgnData Variable size U_RGNDATA structure +*/ +char *U_EMRINVERTRGN_set( + const PU_RGNDATA RgnData + ){ + return(U_EMR_CORE11_set(U_EMR_INVERTRGN, RgnData)); +} + +// U_EMRPAINTRGN_set 74 +/** + \brief Allocate and construct a U_EMR_PAINTRGN record. + \return pointer to U_EMR_PAINTRGN record, or NULL on error. + \param RgnData Variable size U_RGNDATA structure +*/ +char *U_EMRPAINTRGN_set( + const PU_RGNDATA RgnData + ){ + return(U_EMR_CORE11_set(U_EMR_PAINTRGN, RgnData)); +} + +// U_EMREXTSELECTCLIPRGN_set 75 +/** + \brief Allocate and construct a U_EMR_EXTSELECTCLIPRGN record. + \return pointer to U_EMR_EXTSELECTCLIPRGN or NULL on error. + \param iMode RegionMode Enumeration + \param RgnData Variable size U_RGNDATA structure +*/ +char *U_EMREXTSELECTCLIPRGN_set( + const uint32_t iMode, + const PU_RGNDATA RgnData + ){ + char *record; + int irecsize; + int cbRgns,cbRgns4,rds,rds4,off; + + if(!RgnData)return(NULL); + cbRgns = ((PU_RGNDATAHEADER) RgnData)->nRgnSize; + cbRgns4 = UP4(cbRgns); + rds = sizeof(U_RGNDATAHEADER) + cbRgns; + rds4 = UP4(rds); + irecsize = sizeof(U_EMREXTSELECTCLIPRGN) - sizeof(U_RECTL) + cbRgns4; // core + array - overlap of one rectL + record = malloc(irecsize); + if(record){ + ((PU_EMR) record)->iType = U_EMR_EXTSELECTCLIPRGN; + ((PU_EMR) record)->nSize = irecsize; + ((PU_EMREXTSELECTCLIPRGN) record)->cbRgnData = rds; + ((PU_EMREXTSELECTCLIPRGN) record)->iMode = iMode; + off = sizeof(U_EMREXTSELECTCLIPRGN) - sizeof(U_RGNDATA); + memcpy(record + off, RgnData, rds); + off += rds; + if(rds < rds4){ memset(record + off,0, rds4 - rds); } // clear any unused bytes + } + return(record); +} + +// U_EMRBITBLT_set 76 +/** + \brief Allocate and construct a U_EMR_BITBLT record. + \return pointer to U_EMR_BITBLT record, or NULL on error. + \param rclBounds Bounding rectangle in device units + \param Dest Destination UL corner in logical units + \param cDest Destination width in logical units + \param Src Source rectangle UL corner in logical units + \param xformSrc Source bitmap transform (world to page coordinates) + \param crBkColorSrc Source bitmap background color + \param iUsageSrc DIBcolors Enumeration + \param dwRop Ternary Raster Operation enumeration + \param Bmi (Optional) bitmapbuffer (U_BITMAPINFO section) + \param cbPx Size in bytes of pixel array (row stride * height, there may be some padding at the end of each row) + \param Px (Optional) bitmapbuffer (pixel array section ) +*/ +char *U_EMRBITBLT_set( + const U_RECTL rclBounds, + const U_POINTL Dest, + const U_POINTL cDest, + const U_POINTL Src, + const U_XFORM xformSrc, + const U_COLORREF crBkColorSrc, + const uint32_t iUsageSrc, + const uint32_t dwRop, + const PU_BITMAPINFO Bmi, + const uint32_t cbPx, + char *Px + ){ + char *record; + int irecsize; + int cbImage,cbImage4,cbBmi,off; + + SET_CB_FROM_PXBMI(Px,Bmi,cbImage,cbImage4,cbBmi,cbPx); + irecsize = sizeof(U_EMRBITBLT) + cbBmi + cbImage4; + record = malloc(irecsize); + if(record){ + ((PU_EMR) record)->iType = U_EMR_BITBLT; + ((PU_EMR) record)->nSize = irecsize; + ((PU_EMRBITBLT) record)->rclBounds = rclBounds; + ((PU_EMRBITBLT) record)->Dest = Dest; + ((PU_EMRBITBLT) record)->cDest = cDest; + ((PU_EMRBITBLT) record)->dwRop = dwRop; + ((PU_EMRBITBLT) record)->Src = Src; + ((PU_EMRBITBLT) record)->xformSrc = xformSrc; + ((PU_EMRBITBLT) record)->crBkColorSrc = crBkColorSrc; + ((PU_EMRBITBLT) record)->iUsageSrc = iUsageSrc; + off = sizeof(U_EMRBITBLT); + APPEND_PXBMISRC(record, U_EMRBITBLT, cbBmi, Bmi, Px, cbImage, cbImage4); + } + return(record); +} + +// U_EMRSTRETCHBLT_set 77 +/** + \brief Allocate and construct a U_EMR_STRETCHBLT record. + \return pointer to U_EMR_STRETCHBLT record, or NULL on error. + \param rclBounds Bounding rectangle in device units + \param Dest Destination UL corner in logical units + \param cDest Destination width in logical units + \param Src Source UL corner in logical units + \param cSrc Src W & H in logical units + \param xformSrc Transform to apply to source + \param crBkColorSrc Background color + \param iUsageSrc DIBcolors Enumeration + \param dwRop Ternary Raster Operation enumeration + \param Bmi (Optional) bitmapbuffer (U_BITMAPINFO section) + \param cbPx Size in bytes of pixel array (row stride * height, there may be some padding at the end of each row) + \param Px (Optional) bitmapbuffer (pixel array section ) +*/ +char *U_EMRSTRETCHBLT_set( + const U_RECTL rclBounds, + const U_POINTL Dest, + const U_POINTL cDest, + const U_POINTL Src, + const U_POINTL cSrc, + const U_XFORM xformSrc, + const U_COLORREF crBkColorSrc, + const uint32_t iUsageSrc, + const uint32_t dwRop, + const PU_BITMAPINFO Bmi, + const uint32_t cbPx, + char *Px + ){ + char *record; + int irecsize; + int cbImage,cbImage4,cbBmi,off; + + SET_CB_FROM_PXBMI(Px,Bmi,cbImage,cbImage4,cbBmi,cbPx); + + irecsize = sizeof(U_EMRSTRETCHBLT) + cbBmi + cbImage4; + record = malloc(irecsize); + if(record){ + ((PU_EMR) record)->iType = U_EMR_STRETCHBLT; + ((PU_EMR) record)->nSize = irecsize; + ((PU_EMRSTRETCHBLT) record)->rclBounds = rclBounds; + ((PU_EMRSTRETCHBLT) record)->Dest = Dest; + ((PU_EMRSTRETCHBLT) record)->cDest = cDest; + ((PU_EMRSTRETCHBLT) record)->dwRop = dwRop; + ((PU_EMRSTRETCHBLT) record)->Src = Src; + ((PU_EMRSTRETCHBLT) record)->xformSrc = xformSrc; + ((PU_EMRSTRETCHBLT) record)->crBkColorSrc = crBkColorSrc; + ((PU_EMRSTRETCHBLT) record)->iUsageSrc = iUsageSrc; + off = sizeof(U_EMRSTRETCHBLT); + APPEND_PXBMISRC(record, U_EMRSTRETCHBLT, cbBmi, Bmi, Px, cbImage, cbImage4); + ((PU_EMRSTRETCHBLT) record)->cSrc = cSrc; + } + return(record); +} + +// U_EMRMASKBLT_set 78 +/** + \brief Allocate and construct a U_EMR_MASKBLT record. + \return pointer to U_EMR_MASKBLT record, or NULL on error. + \param rclBounds Bounding rectangle in device units + \param Dest Destination UL corner in logical units + \param cDest Destination width in logical units + \param Src Source UL corner in logical units + \param xformSrc Transform to apply to source + \param crBkColorSrc Background color + \param iUsageSrc DIBcolors Enumeration + \param Mask Mask UL corner in logical units + \param iUsageMask DIBcolors Enumeration + \param dwRop Ternary Raster Operation enumeration + \param Bmi (Optional) bitmapbuffer (U_BITMAPINFO section) + \param cbPx Size in bytes of pixel array (row stride * height, there may be some padding at the end of each row) + \param Px (Optional) bitmapbuffer (pixel array section ) + \param MskBmi (Optional) bitmapbuffer (U_BITMAPINFO section) + \param cbMsk Size in bytes of mask array (row stride * height, there may be some padding at the end of each row) + \param Msk (Optional) bitmapbuffer (mask section ) +*/ +char *U_EMRMASKBLT_set( + const U_RECTL rclBounds, + const U_POINTL Dest, + const U_POINTL cDest, + const U_POINTL Src, + const U_XFORM xformSrc, + const U_COLORREF crBkColorSrc, + const uint32_t iUsageSrc, + const U_POINTL Mask, + const uint32_t iUsageMask, + const uint32_t dwRop, + const PU_BITMAPINFO Bmi, + const uint32_t cbPx, + char *Px, + const PU_BITMAPINFO MskBmi, + const uint32_t cbMsk, + char *Msk + ){ + char *record; + int irecsize; + int cbImage,cbImage4,cbBmi,cbMskImage,cbMskImage4,cbMskBmi,off; + + SET_CB_FROM_PXBMI(Px,Bmi,cbImage,cbImage4,cbBmi,cbPx); + SET_CB_FROM_PXBMI(Msk,MskBmi,cbMskImage,cbMskImage4,cbMskBmi,cbMsk); + + irecsize = sizeof(U_EMRMASKBLT) + cbBmi + cbImage4 + cbMskBmi + cbMskImage4; + record = malloc(irecsize); + if(record){ + ((PU_EMR) record)->iType = U_EMR_MASKBLT; + ((PU_EMR) record)->nSize = irecsize; + ((PU_EMRMASKBLT) record)->rclBounds = rclBounds; + ((PU_EMRMASKBLT) record)->Dest = Dest; + ((PU_EMRMASKBLT) record)->cDest = cDest; + ((PU_EMRMASKBLT) record)->dwRop = dwRop; + ((PU_EMRMASKBLT) record)->Src = Src; + ((PU_EMRMASKBLT) record)->xformSrc = xformSrc; + ((PU_EMRMASKBLT) record)->crBkColorSrc = crBkColorSrc; + ((PU_EMRMASKBLT) record)->iUsageSrc = iUsageSrc; + ((PU_EMRMASKBLT) record)->Mask = Mask; + ((PU_EMRMASKBLT) record)->iUsageMask = iUsageMask; + off = sizeof(U_EMRMASKBLT); + APPEND_PXBMISRC(record, U_EMRMASKBLT, cbBmi, Bmi, Px, cbImage, cbImage4); + APPEND_MSKBMISRC(record, U_EMRMASKBLT, cbMskBmi, MskBmi, Msk, cbMskImage, cbMskImage4); + } + return(record); +} + +// U_EMRPLGBLT_set 79 + +/** + \brief Allocate and construct a U_EMRPLGBLT record. + \return U_EMRPLGBLT record. + \param rclBounds Bounding rectangle in device units + \param aptlDst Defines parallelogram, UL, UR, LL corners, LR is derived (3 points) + \param Src Source UL corner in logical units + \param cSrc Source width in logical units + \param xformSrc Transform to apply to source + \param crBkColorSrc Background color + \param iUsageSrc DIBcolors Enumeration + \param Mask Mask UL corner in logical units + \param iUsageMask DIBcolors Enumeration + \param Bmi (Optional) bitmapbuffer (U_BITMAPINFO section) + \param cbPx Size in bytes of pixel array (row stride * height, there may be some padding at the end of each row) + \param Px (Optional) bitmapbuffer (pixel array section ) + \param MskBmi (Optional) bitmapbuffer (U_BITMAPINFO section) + \param cbMsk Size in bytes of mask array (row stride * height, there may be some padding at the end of each row) + \param Msk (Optional) bitmapbuffer (mask section ) +*/ +char *U_EMRPLGBLT_set( + const U_RECTL rclBounds, + const PU_POINTL aptlDst, + const U_POINTL Src, + const U_POINTL cSrc, + const U_XFORM xformSrc, + const U_COLORREF crBkColorSrc, + const uint32_t iUsageSrc, + const U_POINTL Mask, + const uint32_t iUsageMask, + const PU_BITMAPINFO Bmi, + const uint32_t cbPx, + char *Px, + const PU_BITMAPINFO MskBmi, + const uint32_t cbMsk, + char *Msk + ){ + char *record; + int irecsize; + int cbImage,cbImage4,cbBmi,cbMskImage,cbMskImage4,cbMskBmi,off; + + SET_CB_FROM_PXBMI(Px,Bmi,cbImage,cbImage4,cbBmi,cbPx); + SET_CB_FROM_PXBMI(Msk,MskBmi,cbMskImage,cbMskImage4,cbMskBmi,cbMsk); + + irecsize = sizeof(U_EMRPLGBLT) + cbBmi + cbImage4 + cbMskBmi + cbMskImage4; + record = malloc(irecsize); + if(record){ + ((PU_EMR) record)->iType = U_EMR_PLGBLT; + ((PU_EMR) record)->nSize = irecsize; + ((PU_EMRPLGBLT) record)->rclBounds = rclBounds; + memcpy(((PU_EMRPLGBLT) record)->aptlDst,aptlDst,3*sizeof(U_POINTL)); + ((PU_EMRPLGBLT) record)->Src = Src; + ((PU_EMRPLGBLT) record)->cSrc = cSrc; + ((PU_EMRPLGBLT) record)->xformSrc = xformSrc; + ((PU_EMRPLGBLT) record)->crBkColorSrc = crBkColorSrc; + ((PU_EMRPLGBLT) record)->iUsageSrc = iUsageSrc; + ((PU_EMRPLGBLT) record)->Mask = Mask; + ((PU_EMRPLGBLT) record)->iUsageMask = iUsageMask; + off = sizeof(U_EMRPLGBLT); + APPEND_PXBMISRC(record, U_EMRPLGBLT, cbBmi, Bmi, Px, cbImage, cbImage4); + APPEND_MSKBMISRC(record, U_EMRPLGBLT, cbMskBmi, MskBmi, Msk, cbMskImage, cbMskImage4); + } + return(record); +} + +// U_EMRSETDIBITSTODEVICE_set 80 +/** + \brief Allocate and construct a U_EMR_SETDIBITSTODEVICE record. + \return pointer to U_EMR_SETDIBITSTODEVICE record, or NULL on error. + \param rclBounds Bounding rectangle in device units + \param Dest Destination UL corner in logical units + \param Src Source UL corner in logical units + \param cSrc Source W & H in logical units + \param iUsageSrc DIBColors Enumeration + \param iStartScan First scan line + \param cScans Number of scan lines + \param Bmi (Optional) bitmapbuffer (U_BITMAPINFO section) + \param cbPx Size in bytes of pixel array (row stride * height, there may be some padding at the end of each row) + \param Px (Optional) bitmapbuffer (pixel array section ) +*/ +char *U_EMRSETDIBITSTODEVICE_set( + const U_RECTL rclBounds, + const U_POINTL Dest, + const U_POINTL Src, + const U_POINTL cSrc, + const uint32_t iUsageSrc, + const uint32_t iStartScan, + const uint32_t cScans, + const PU_BITMAPINFO Bmi, + const uint32_t cbPx, + char *Px + ){ + char *record; + int irecsize; + int cbImage,cbImage4,cbBmi,off; + + SET_CB_FROM_PXBMI(Px,Bmi,cbImage,cbImage4,cbBmi,cbPx); + + irecsize = sizeof(U_EMRSETDIBITSTODEVICE) + cbBmi + cbImage4; + record = malloc(irecsize); + if(record){ + ((PU_EMR) record)->iType = U_EMR_SETDIBITSTODEVICE; + ((PU_EMR) record)->nSize = irecsize; + ((PU_EMRSETDIBITSTODEVICE) record)->rclBounds = rclBounds; + ((PU_EMRSETDIBITSTODEVICE) record)->Dest = Dest; + ((PU_EMRSETDIBITSTODEVICE) record)->Src = Src; + ((PU_EMRSETDIBITSTODEVICE) record)->cSrc = cSrc; + ((PU_EMRSETDIBITSTODEVICE) record)->iUsageSrc = iUsageSrc; + ((PU_EMRSETDIBITSTODEVICE) record)->iStartScan = iStartScan; + ((PU_EMRSETDIBITSTODEVICE) record)->cScans = cScans; + off = sizeof(U_EMRSETDIBITSTODEVICE); + APPEND_PXBMISRC(record, U_EMRSETDIBITSTODEVICE, cbBmi, Bmi, Px, cbImage, cbImage4); + } + return(record); +} + +// U_EMRSTRETCHDIBITS_set 81 +/** + \brief Allocate and construct a U_EMR_EMRSTRETCHDIBITS record. + \return pointer to U_EMR_EMRSTRETCHDIBITS record, or NULL on error. + \param rclBounds Bounding rectangle in device units + \param Dest Destination UL corner in logical units + \param cDest Destination W & H in logical units + \param Src Source UL corner in logical units + \param cSrc Source W & H in logical units + \param iUsageSrc DIBColors Enumeration + \param dwRop RasterOPeration Enumeration + \param Bmi (Optional) bitmapbuffer (U_BITMAPINFO section) + \param cbPx Size in bytes of pixel array (row STRIDE * height, there may be some padding at the end of each row) + \param Px (Optional) bitmapbuffer (pixel array section ) +*/ +char *U_EMRSTRETCHDIBITS_set( + const U_RECTL rclBounds, + const U_POINTL Dest, + const U_POINTL cDest, + const U_POINTL Src, + const U_POINTL cSrc, + const uint32_t iUsageSrc, + const uint32_t dwRop, + const PU_BITMAPINFO Bmi, + const uint32_t cbPx, + char *Px + ){ + char *record; + int irecsize; + int cbImage,cbImage4,cbBmi,off; + + SET_CB_FROM_PXBMI(Px,Bmi,cbImage,cbImage4,cbBmi,cbPx); + + irecsize = sizeof(U_EMRSTRETCHDIBITS) + cbBmi + cbImage4; + record = malloc(irecsize); + if(record){ + ((PU_EMR) record)->iType = U_EMR_STRETCHDIBITS; + ((PU_EMR) record)->nSize = irecsize; + ((PU_EMRSTRETCHDIBITS) record)->rclBounds = rclBounds; + ((PU_EMRSTRETCHDIBITS) record)->Dest = Dest; + ((PU_EMRSTRETCHDIBITS) record)->Src = Src; + ((PU_EMRSTRETCHDIBITS) record)->cSrc = cSrc; + ((PU_EMRSTRETCHDIBITS) record)->iUsageSrc = iUsageSrc; + ((PU_EMRSTRETCHDIBITS) record)->dwRop = dwRop; + ((PU_EMRSTRETCHDIBITS) record)->cDest = cDest; + off = sizeof(U_EMRSTRETCHDIBITS); + APPEND_PXBMISRC(record, U_EMRSTRETCHDIBITS, cbBmi, Bmi, Px, cbImage, cbImage4); + } + return(record); +} + +// U_EMREXTCREATEFONTINDIRECTW_set 82 +/** + \brief Allocate and construct a U_EMR_EXTCREATEFONTINDIRECTW record. + Use extcreatefontindirectw_set() instead of calling this function directly. + \return pointer to U_EMR_EXTCREATEFONTINDIRECTW record, or NULL on error. + \param ihFont Index of the font in the EMF object table + \param elf Font parameters as U_LOGFONT + \param elfw Font parameters as U_LOGFONT_PANOSE +*/ +char *U_EMREXTCREATEFONTINDIRECTW_set( + const uint32_t ihFont, + const char * elf, + const char * elfw + ){ + char *record; + const char *cptr; + int irecsize; + int cbLf,off; + + if((elf && elfw) || (!elf && !elfw))return(NULL); // ONE only must be passed + if(elf){ cbLf = sizeof(U_LOGFONT); cptr = elf; } + else { cbLf = sizeof(U_LOGFONT_PANOSE); cptr = elfw; } + + irecsize = sizeof(U_EMR) + sizeof(uint32_t) + cbLf; + record = malloc(irecsize); + if(record){ + ((PU_EMR) record)->iType = U_EMR_EXTCREATEFONTINDIRECTW; + ((PU_EMR) record)->nSize = irecsize; + ((PU_EMREXTCREATEFONTINDIRECTW) record)->ihFont = ihFont; + off = sizeof(U_EMR) + sizeof(uint32_t); + memcpy(record + off, cptr, cbLf); // No need to add padding for either structure + } + return(record); +} + +// U_EMREXTTEXTOUTA_set 83 +/** + \brief Allocate and construct a U_EMR_EXTTEXTOUTA record. + \return pointer to U_EMR_EXTTEXTOUTA record, or NULL on error. + \param rclBounds Bounding rectangle in device units + \param iGraphicsMode Graphics mode Enumeration + \param exScale scale to 0.01 mm units ( only if iGraphicsMode & GM_COMPATIBLE) + \param eyScale scale to 0.01 mm units ( only if iGraphicsMode & GM_COMPATIBLE) + \param emrtext Text parameters +*/ +char *U_EMREXTTEXTOUTA_set( + const U_RECTL rclBounds, + const uint32_t iGraphicsMode, + const U_FLOAT exScale, + const U_FLOAT eyScale, + const PU_EMRTEXT emrtext + ){ + return(U_EMR_CORE8_set(U_EMR_EXTTEXTOUTA,rclBounds, iGraphicsMode, exScale, eyScale,emrtext)); +} + +// U_EMREXTTEXTOUTW_set 84 +/** + \brief Allocate and construct a U_EMR_EXTTEXTOUTW record. + \return pointer to U_EMR_EXTTEXTOUTW record, or NULL on error. + \param rclBounds Bounding rectangle in device units + \param iGraphicsMode Graphics mode Enumeration + \param exScale scale to 0.01 mm units ( only if iGraphicsMode & GM_COMPATIBLE) + \param eyScale scale to 0.01 mm units ( only if iGraphicsMode & GM_COMPATIBLE) + \param emrtext Text parameters +*/ +char *U_EMREXTTEXTOUTW_set( + const U_RECTL rclBounds, + const uint32_t iGraphicsMode, + const U_FLOAT exScale, + const U_FLOAT eyScale, + const PU_EMRTEXT emrtext + ){ + return(U_EMR_CORE8_set(U_EMR_EXTTEXTOUTW,rclBounds, iGraphicsMode, exScale, eyScale,emrtext)); +} + +// U_EMRPOLYBEZIER16_set 85 +/** + \brief Allocate and construct a U_EMR_POLYBEZIER16 record. + \return pointer to U_EMR_POLYBEZIER16 record, or NULL on error. + \param rclBounds Bounding rectangle in device units + \param cpts Number of POINT16 in array + \param points Array of POINT16 +*/ +char *U_EMRPOLYBEZIER16_set( + const U_RECTL rclBounds, + const uint32_t cpts, + const U_POINT16 *points + ){ + return(U_EMR_CORE6_set(U_EMR_POLYBEZIER16, rclBounds, cpts, points)); +} + +// U_EMRPOLYGON16_set 86 +/** + \brief Allocate and construct a U_EMR_POLYGON16 record. + \return pointer to U_EMR_POLYGON16 record, or NULL on error. + \param rclBounds Bounding rectangle in device units + \param cpts Number of POINT16 in array + \param points Array of POINT16 +*/ +char *U_EMRPOLYGON16_set( + const U_RECTL rclBounds, + const uint32_t cpts, + const U_POINT16 *points + ){ + return(U_EMR_CORE6_set(U_EMR_POLYGON16, rclBounds, cpts, points)); +} + +// U_EMRPOLYLINE16_set 87 +/** + \brief Allocate and construct a U_EMR_POLYLINE16 record. + \return pointer to U_EMR_POLYLINE16 record, or NULL on error. + \param rclBounds Bounding rectangle in device units + \param cpts Number of POINT16 in array + \param points Array of POINT16 +*/ +char *U_EMRPOLYLINE16_set( + const U_RECTL rclBounds, + const uint32_t cpts, + const U_POINT16 *points + ){ + return(U_EMR_CORE6_set(U_EMR_POLYLINE16, rclBounds, cpts, points)); +} + +// U_EMRPOLYBEZIERTO16_set 88 +/** + \brief Allocate and construct a U_EMR_POLYBEZIERTO record. + \return pointer to U_EMR_POLYBEZIERTO record, or NULL on error. + \param rclBounds Bounding rectangle in device units + \param cpts Number of POINT16 in array + \param points Array of POINT16 +*/ +char *U_EMRPOLYBEZIERTO16_set( + const U_RECTL rclBounds, + const uint32_t cpts, + const U_POINT16 *points + ){ + return(U_EMR_CORE6_set(U_EMR_POLYBEZIERTO16, rclBounds, cpts, points)); +} + +// U_EMRPOLYLINETO16_set 89 +/** + \brief Allocate and construct a U_EMR_POLYLINETO record. + \return pointer to U_EMR_POLYLINETO record, or NULL on error. + \param rclBounds Bounding rectangle in device units + \param cpts Number of POINT16 in array + \param points Array of POINT16 +*/ +char *U_EMRPOLYLINETO16_set( + const U_RECTL rclBounds, + const uint32_t cpts, + const U_POINT16 *points + ){ + return(U_EMR_CORE6_set(U_EMR_POLYLINETO16, rclBounds, cpts, points)); +} + +// U_EMRPOLYPOLYLINE16_set 90 +/** + \brief Allocate and construct a U_EMR_POLYPOLYLINE16 record. + \return pointer to U_EMR_POLYPOLYLINE16 record, or NULL on error. + \param rclBounds Bounding rectangle in device units + \param nPolys Number of elements in aPolyCounts + \param aPolyCounts Number of points in each poly (sequential) + \param cpts Number of POINT16 in array + \param points Array of POINT16 +*/ +char *U_EMRPOLYPOLYLINE16_set( + const U_RECTL rclBounds, + const uint32_t nPolys, + const uint32_t *aPolyCounts, + const uint32_t cpts, + const U_POINT16 *points + ){ + return(U_EMR_CORE10_set(U_EMR_POLYPOLYLINE16, rclBounds, nPolys, aPolyCounts,cpts, points)); +} + +// U_EMRPOLYPOLYGON16_set 91 +/** + \brief Allocate and construct a U_EMR_POLYPOLYGON16 record. + \return pointer to U_EMR_POLYPOLYGON16 record, or NULL on error. + \param rclBounds Bounding rectangle in device units + \param nPolys Number of elements in aPolyCounts + \param aPolyCounts Number of points in each poly (sequential) + \param cpts Number of POINT16 in array + \param points Array of POINT16 +*/ +char *U_EMRPOLYPOLYGON16_set( + const U_RECTL rclBounds, + const uint32_t nPolys, + const uint32_t *aPolyCounts, + const uint32_t cpts, + const U_POINT16 *points + ){ + return(U_EMR_CORE10_set(U_EMR_POLYPOLYGON16, rclBounds, nPolys, aPolyCounts,cpts, points)); +} + + +// U_EMRPOLYDRAW16_set 92 +/** + \brief Allocate and construct a U_EMR_POLYDRAW16 record. + \return pointer to U_EMR_POLYDRAW16 record, or NULL on error. + \param rclBounds Bounding rectangle in device units + \param cpts Number of U_POINTL objects + \param aptl Array of U_POINTL objects + \param abTypes Array of Point Enumeration +*/ +char *U_EMRPOLYDRAW16_set( + const U_RECTL rclBounds, + const U_NUM_POINT16 cpts, + const U_POINT16 *aptl, + const uint8_t *abTypes + ){ + char *record; + int irecsize; + int cbPoints, cbAbTypes, cbAbTypes4, off; + + if(!cpts || !aptl || !abTypes)return(NULL); + cbPoints = cpts * sizeof(U_POINT16); // space for aptl + cbAbTypes = cpts; // number of abTypes (same array size, 1 byte each) + cbAbTypes4 = UP4(cbAbTypes); // space for abTypes + irecsize = sizeof(U_EMRPOLYDRAW16) + cbPoints + cbAbTypes4 - sizeof(U_POINT16) - 1; + record = malloc(irecsize); + if(record){ + ((PU_EMR) record)->iType = U_EMR_POLYDRAW16; + ((PU_EMR) record)->nSize = irecsize; + ((PU_EMRPOLYDRAW16) record)->rclBounds = rclBounds; + ((PU_EMRPOLYDRAW16) record)->cpts = cpts; + off = sizeof(U_EMR) + sizeof(U_RECTL) + sizeof(uint32_t); // offset to first variable part + memcpy(record+off,aptl,cbPoints); + off += cbPoints; + memcpy(record+off,abTypes,cbAbTypes); + off += cbAbTypes; + if(cbAbTypes4 > cbAbTypes){ memset(record+off,0,cbAbTypes4-cbAbTypes); } // keeps valgrind happy (initialize padding after byte array) + } + return(record); +} + +// U_EMRCREATEMONOBRUSH_set 93 +/** + \brief Allocate and construct a U_EMR_CREATEMONOBRUSH record. + \return pointer to U_EMR_CREATEMONOBRUSH record, or NULL on error. + \param ihBrush Index to place object in EMF object table (this entry must not yet exist) + \param iUsage DIBcolors Enumeration + \param Bmi (Optional) bitmapbuffer (U_BITMAPINFO + pixel array) + \param cbPx Size in bytes of pixel array (row stride * height, there may be some padding at the end of each row) + \param Px (Optional) bitmapbuffer (pixel array section ) +*/ +char *U_EMRCREATEMONOBRUSH_set( + const uint32_t ihBrush, + const uint32_t iUsage, + const PU_BITMAPINFO Bmi, + const uint32_t cbPx, + const char *Px + ){ + return(U_EMR_CORE12_set(U_EMR_CREATEMONOBRUSH,ihBrush,iUsage,Bmi,cbPx,Px)); +} + +// U_EMRCREATEDIBPATTERNBRUSHPT_set 94 +/** + \brief Allocate and construct a U_EMR_CREATEDIBPATTERNBRUSHPT record. + Use createdibpatternbrushpt_set() instead of calling this function directly. + \return pointer to U_EMR_CREATEDIBPATTERNBRUSHPT record, or NULL on error. + \param ihBrush Index to place object in EMF object table (this entry must not yet exist) + \param iUsage DIBcolors Enumeration + \param Bmi (Optional) bitmapbuffer (U_BITMAPINFO + pixel array) + \param cbPx Size in bytes of pixel array (row stride * height, there may be some padding at the end of each row) + \param Px (Optional) bitmapbuffer (pixel array section ) +*/ +char *U_EMRCREATEDIBPATTERNBRUSHPT_set( + const uint32_t ihBrush, + const uint32_t iUsage, + const PU_BITMAPINFO Bmi, + const uint32_t cbPx, + const char *Px + ){ + return(U_EMR_CORE12_set(U_EMR_CREATEDIBPATTERNBRUSHPT,ihBrush,iUsage,Bmi,cbPx,Px)); +} + + +// U_EMREXTCREATEPEN_set 95 +/** + \brief Allocate and construct a U_EMR_EXTCREATEPEN record. + Use extcreatepen_set() instead of calling this function directly. + \return pointer to U_EMR_EXTCREATEPEN record, or NULL on error. + \param ihPen ihPen Index to place object in EMF object table (this entry must not yet exist) + \param Bmi Bmi bitmapbuffer + \param cbPx cbPx Size in bytes of pixel array (row stride * height, there may be some padding at the end of each row) + \param Px Px pixel array (NULL if cbPx == 0) + \param elp elp Pen parameters (Size is Variable!!!!) +*/ +char *U_EMREXTCREATEPEN_set( + const uint32_t ihPen, + const PU_BITMAPINFO Bmi, + const uint32_t cbPx, + char *Px, + const PU_EXTLOGPEN elp + ){ + char *record; + int cbImage,cbImage4,cbBmi,off; + int irecsize,cbStyleArray,cbElp; + + if(!elp)return(NULL); + + SET_CB_FROM_PXBMI(Px,Bmi,cbImage,cbImage4,cbBmi,cbPx); + + cbStyleArray = elp->elpNumEntries * sizeof(U_STYLEENTRY); // space actually used by penstyle entries + // EXTLOGPEN is already included in EMREXTCREATEPEN, including the possibly unused first penstyle entry + if(cbStyleArray){ + cbElp = sizeof(U_EXTLOGPEN) + cbStyleArray - sizeof(U_STYLEENTRY); // space actually used by elp + irecsize = sizeof(U_EMREXTCREATEPEN) + cbBmi + cbImage4 + cbStyleArray - sizeof(U_STYLEENTRY); + } + else { + cbElp = sizeof(U_EXTLOGPEN); // first U_STYLEENTRY is present but unused + irecsize = sizeof(U_EMREXTCREATEPEN) + cbBmi + cbImage4; + } + record = malloc(irecsize); + + if(record){ + ((PU_EMR) record)->iType = U_EMR_EXTCREATEPEN; + ((PU_EMR) record)->nSize = irecsize; + ((PU_EMREXTCREATEPEN) record)->ihPen = ihPen; + memcpy(&(((PU_EMREXTCREATEPEN) record)->elp),elp,cbElp); + if(cbStyleArray){ + off = sizeof(U_EMREXTCREATEPEN) + cbStyleArray - sizeof(U_STYLEENTRY); + } + else { + off = sizeof(U_EMREXTCREATEPEN); + } + // Cannot use APPEND_PXBMISRC here because there is no "Src" in the field names + if(cbBmi){ + memcpy(record + off, Bmi, cbBmi); + ((PU_EMREXTCREATEPEN) record)->offBmi = off; + ((PU_EMREXTCREATEPEN) record)->cbBmi = cbBmi; + off += cbBmi; + memcpy(record + off, Px, cbImage); + ((PU_EMREXTCREATEPEN) record)->offBits = off; + ((PU_EMREXTCREATEPEN) record)->cbBits = cbImage; + off += cbImage; + if(cbImage4 - cbImage){ memset(record + off, 0, cbImage4 - cbImage); } + } + else { + ((PU_EMREXTCREATEPEN) record)->cbBmi = 0; + ((PU_EMREXTCREATEPEN) record)->offBmi = 0; + ((PU_EMREXTCREATEPEN) record)->cbBits = 0; + ((PU_EMREXTCREATEPEN) record)->offBits = 0; + } + } + return(record); +} + +// U_EMRPOLYTEXTOUTA_set 96 NOT IMPLEMENTED, denigrated after Windows NT +// U_EMRPOLYTEXTOUTW_set 97 NOT IMPLEMENTED, denigrated after Windows NT + +// U_EMRSETICMMODE_set 98 +/** + \brief Allocate and construct a U_EMR_SETICMMODE record. + \return pointer to U_EMR_SETICMMODE record, or NULL on error. + \param iMode ICMMode Enumeration +*/ +char *U_EMRSETICMMODE_set( + const uint32_t iMode + ){ + return(U_EMR_CORE3_set(U_EMR_SETICMMODE, iMode)); +} + +// U_EMRCREATECOLORSPACE_set 99 +/** + \brief Allocate and construct a U_EMR_CREATECOLORSPACE record. + Use createcolorspace_set() instead of calling this function directly. + \return pointer to U_EMR_CREATECOLORSPACE record, or NULL on error. + \param ihCS Index to place object in EMF object table (this entry must not yet exist) + \param lcs ColorSpace parameters +*/ +char *U_EMRCREATECOLORSPACE_set( + const uint32_t ihCS, + const U_LOGCOLORSPACEA lcs + ){ + char *record; + int irecsize; + + irecsize = sizeof(U_EMRCREATECOLORSPACE); + record = malloc(irecsize); + if(record){ + ((PU_EMR) record)->iType = U_EMR_CREATECOLORSPACE; + ((PU_EMR) record)->nSize = irecsize; + ((PU_EMRCREATECOLORSPACE) record)->ihCS = ihCS; + ((PU_EMRCREATECOLORSPACE) record)->lcs = lcs; + } + return(record); +} + +// U_EMRSETCOLORSPACE_set 100 +/** + \brief Allocate and construct a U_EMR_SETCOLORSPACE record. + \return pointer to U_EMR_SETCOLORSPACE record, or NULL on error. + \param ihCS Index of object in EMF object table +*/ +char *U_EMRSETCOLORSPACE_set( + const uint32_t ihCS + ){ + return(U_EMR_CORE3_set(U_EMR_SETCOLORSPACE, ihCS)); +} + +// U_EMRDELETECOLORSPACE_set 101 +/** + \brief Allocate and construct a U_EMR_DELETECOLORSPACE record. + \return pointer to U_EMR_DELETECOLORSPACE record, or NULL on error. + \param ihCS Index of object in EMF object table +*/ +char *U_EMRDELETECOLORSPACE_set( + const uint32_t ihCS + ){ + return(U_EMR_CORE3_set(U_EMR_DELETECOLORSPACE, ihCS)); +} + +// U_EMRGLSRECORD_set 102 Not implemented +// U_EMRGLSBOUNDEDRECORD_set 103 Not implemented +// U_EMRPIXELFORMAT_set 104 +/** + \brief Allocate and construct a U_EMR_PIXELFORMAT record. + \return pointer to U_EMR_PIXELFORMAT record, or NULL on error. + \param pfd PixelFormatDescriptor +*/ +char *U_EMRPIXELFORMAT_set( + const U_PIXELFORMATDESCRIPTOR pfd + ){ + char *record; + int irecsize; + + irecsize = sizeof(U_EMRPIXELFORMAT); + record = malloc(irecsize); + if(record){ + ((PU_EMR) record)->iType = U_EMR_PIXELFORMAT; + ((PU_EMR) record)->nSize = irecsize; + ((PU_EMRPIXELFORMAT) record)->pfd = pfd; + } + return(record); +} +// U_EMRDRAWESCAPE_set 105 Not implemented +// U_EMREXTESCAPE_set 106 Not implemented +// U_EMRUNDEF107_set 107 Not implemented + +// U_EMRSMALLTEXTOUT_set 108 +/** + \brief Allocate and construct a U_EMR_SMALLTEXTOUT record. + \return pointer to U_EMR_SMALLTEXTOUT record, or NULL on error. + \param Dest Where to draw the text + \param cChars Characters in TextString (not null terminated) + \param fuOptions ExtTextOutOptions Enumeration + \param iGraphicsMode GraphicsMode Enumeration + \param exScale scale on X axis + \param eyScale scale on Y axis + \param rclBounds OPTIONAL Bounding rectangle (absent when: fuOPtions & ETO_NO_U_RECT) + \param TextString text to output (fuOptions & ETO_SMALL_CHARS ? 8 bit : 16 bit) +*/ +char *U_EMRSMALLTEXTOUT_set( + const U_POINTL Dest, + const U_NUM_STR cChars, + const uint32_t fuOptions, + const uint32_t iGraphicsMode, + const U_FLOAT exScale, + const U_FLOAT eyScale, + const U_RECTL rclBounds, + const char *TextString + ){ + char *record; + int irecsize,cbString,cbString4,cbRectl,off; + int csize; + + if( fuOptions & U_ETO_SMALL_CHARS ){ csize = 1; } // how many bytes per character + else { csize = 2; } + cbString = csize * cChars; // filled contents of the string buffer + cbString4 = UP4(cbString); // size of the variable string buffer + if(fuOptions & U_ETO_NO_RECT){ cbRectl = 0; } // size of the optional U_RECTL field + else { cbRectl = sizeof(U_RECTL); } + + irecsize = sizeof(U_EMRSMALLTEXTOUT) + cbString4 + cbRectl; + record = malloc(irecsize); + if(record){ + ((PU_EMR) record)->iType = U_EMR_SMALLTEXTOUT; + ((PU_EMR) record)->nSize = irecsize; + ((PU_EMRSMALLTEXTOUT) record)->Dest = Dest; + ((PU_EMRSMALLTEXTOUT) record)->cChars = cChars; + ((PU_EMRSMALLTEXTOUT) record)->fuOptions = fuOptions; + ((PU_EMRSMALLTEXTOUT) record)->iGraphicsMode = iGraphicsMode; + ((PU_EMRSMALLTEXTOUT) record)->exScale = exScale; + ((PU_EMRSMALLTEXTOUT) record)->eyScale = eyScale; + off = sizeof(U_EMRSMALLTEXTOUT); //offset to the start of the variable fields + if(cbRectl){ + memcpy(record + off, &rclBounds, cbRectl); + off += cbRectl; + } + memcpy(record + off, TextString, cbString); + if(cbString < cbString4){ + off += cbString; + memset(record + off, 0, cbString4 - cbString); + } + } + return(record); +} + +// U_EMRFORCEUFIMAPPING_set 109 Not implemented +// U_EMRNAMEDESCAPE_set 110 Not implemented +// U_EMRCOLORCORRECTPALETTE_set 111 Not implemented +// U_EMRSETICMPROFILEA_set 112 Not implemented +// U_EMRSETICMPROFILEW_set 113 Not implemented + +// U_EMRALPHABLEND_set 114 +/** + \brief Allocate and construct a U_EMR_ALPHABLEND record. + \return pointer to U_EMR_ALPHABLEND record, or NULL on error. + \param rclBounds Bounding rectangle in device units + \param Dest Destination UL corner in logical units + \param cDest Destination width in logical units + \param Src Source UL corner in logical units + \param cSrc Src W & H in logical units + \param xformSrc Transform to apply to source + \param crBkColorSrc Background color + \param iUsageSrc DIBcolors Enumeration + \param Blend Blend function + \param Bmi (Optional) bitmapbuffer (U_BITMAPINFO section) + \param cbPx Size in bytes of pixel array (row stride * height, there may be some padding at the end of each row) + \param Px (Optional) bitmapbuffer (pixel array section ) +*/ +char *U_EMRALPHABLEND_set( + const U_RECTL rclBounds, + const U_POINTL Dest, + const U_POINTL cDest, + const U_POINTL Src, + const U_POINTL cSrc, + const U_XFORM xformSrc, + const U_COLORREF crBkColorSrc, + const uint32_t iUsageSrc, + const U_BLEND Blend, + const PU_BITMAPINFO Bmi, + const uint32_t cbPx, + char *Px + ){ + return(U_EMR_CORE13_set(U_EMR_ALPHABLEND,rclBounds,Dest,cDest,Src,cSrc,xformSrc,crBkColorSrc,iUsageSrc,*((uint32_t *) &Blend),Bmi,cbPx,Px)); +} + +// U_EMRSETLAYOUT_set 115 +/** + \brief Allocate and construct a U_EMR_SETLAYOUT record. + \return pointer to U_EMR_SETLAYOUT record, or NULL on error. + \param iMode Mirroring Enumeration +*/ +char *U_EMRSETLAYOUT_set(uint32_t iMode){ + return(U_EMR_CORE3_set(U_EMR_SETLAYOUT, iMode)); +} + +// U_EMRTRANSPARENTBLT_set 116 +/** + \brief Allocate and construct a U_EMR_TRANSPARENTBLT record. + \return pointer to U_EMR_TRANSPARENTBLT record, or NULL on error. + \param rclBounds Bounding rectangle in device units + \param Dest Destination UL corner in logical units + \param cDest Destination width in logical units + \param Src Source UL corner in logical units + \param cSrc Src W & H in logical units + \param xformSrc Transform to apply to source + \param crBkColorSrc Background color + \param iUsageSrc DIBcolors Enumeration + \param TColor Bitmap color to be treated as transparent + \param Bmi (Optional) bitmapbuffer (U_BITMAPINFO section) + \param cbPx Size in bytes of pixel array (row stride * height, there may be some padding at the end of each row) + \param Px (Optional) bitmapbuffer (pixel array section ) +*/ +char *U_EMRTRANSPARENTBLT_set( + const U_RECTL rclBounds, + const U_POINTL Dest, + const U_POINTL cDest, + const U_POINTL Src, + const U_POINTL cSrc, + const U_XFORM xformSrc, + const U_COLORREF crBkColorSrc, + const uint32_t iUsageSrc, + const uint32_t TColor, + const PU_BITMAPINFO Bmi, + const uint32_t cbPx, + char *Px + ){ + return(U_EMR_CORE13_set(U_EMR_TRANSPARENTBLT,rclBounds,Dest,cDest,Src,cSrc,xformSrc,crBkColorSrc,iUsageSrc,TColor,Bmi,cbPx,Px)); +} +// U_EMRUNDEF117_set 117 Not implemented +// U_EMRGRADIENTFILL_set 118 +/** + \brief Allocate and construct a U_EMR_TRANSPARENTBLT record. + \return pointer to U_EMR_TRANSPARENTBLT record, or NULL on error. + \param rclBounds Bounding rectangle in device units + \param nTriVert Number of TriVertex objects in TriVert + \param nGradObj Number of gradient triangle/rectangle objects + \param ulMode Gradientfill Enumeration (determines Triangle/Rectangle) + \param TriVert Array of TriVertex objects + \param GradObj Array of gradient objects (each has 2 [rect] or 3 [triangle] indices into TriVert array) + +There is an MS documentation or library problem for this record, as the size of the GradObj must always be set +as if it was an array of U_GRADIENT3 objects for both rect and triangle. For horizontal and vertical gradients +this means that there will be unused bytes at the end of the record. This is not what the documentation says, +but it is how MS's libraries work. + +*/ +char *U_EMRGRADIENTFILL_set( + const U_RECTL rclBounds, + const U_NUM_TRIVERTEX nTriVert, + const U_NUM_GRADOBJ nGradObj, + const uint32_t ulMode, + const PU_TRIVERTEX TriVert, + const uint32_t *GradObj + ){ + char *record; + unsigned int cbTriVert,cbGradObj,off; + unsigned int cbGradObjAlloc; /* larger than cbGradObj, because of problem described above */ + int irecsize; + + cbTriVert = sizeof(U_TRIVERTEX) * nTriVert; // all of the cb's will be a multiple of 4 bytes + if( ulMode == U_GRADIENT_FILL_TRIANGLE){ cbGradObj = sizeof(U_GRADIENT3) * nGradObj; } + else if(ulMode == U_GRADIENT_FILL_RECT_H || + ulMode == U_GRADIENT_FILL_RECT_V){ cbGradObj = sizeof(U_GRADIENT4) * nGradObj; } + else { return(NULL); } + cbGradObjAlloc = sizeof(U_GRADIENT3) * nGradObj; + + irecsize = sizeof(U_EMRGRADIENTFILL) + cbTriVert + cbGradObjAlloc; + record = malloc(irecsize); + if(record){ + ((PU_EMR) record)->iType = U_EMR_GRADIENTFILL; + ((PU_EMR) record)->nSize = irecsize; + ((PU_EMRGRADIENTFILL) record)->rclBounds = rclBounds; + ((PU_EMRGRADIENTFILL) record)->nTriVert = nTriVert; + ((PU_EMRGRADIENTFILL) record)->nGradObj = nGradObj; + ((PU_EMRGRADIENTFILL) record)->ulMode = ulMode; + off = sizeof(U_EMRGRADIENTFILL); // offset to TriVert field + memcpy(record + off, TriVert, cbTriVert); + off += cbTriVert; + memcpy(record + off, GradObj, cbGradObj); + off += cbGradObj; + if(cbGradObjAlloc > cbGradObj){ + memset(record+off,0,cbGradObjAlloc - cbGradObj); + } + } + return(record); +} + +// U_EMRSETLINKEDUFIS_set 119 Not implemented +// U_EMRSETTEXTJUSTIFICATION_set 120 Not implemented (denigrated) +// U_EMRCOLORMATCHTOTARGETW_set 121 Not implemented + +// U_EMRCREATECOLORSPACEW_set 122 +/** + \brief Allocate and construct a U_EMR_CREATECOLORSPACEW record. + Use createcolorspacew_set() instead of calling this function directly. + \return pointer to U_EMR_CREATECOLORSPACEW record, or NULL on error. + \param ihCS Index to place object in EMF object table (this entry must not yet exist) + \param lcs ColorSpace parameters + \param dwFlags If low bit set Data is present + \param cbData Number of bytes of theData field. + \param Data (Optional, dwFlags & 1) color profile data +*/ +char *U_EMRCREATECOLORSPACEW_set( + const uint32_t ihCS, + const U_LOGCOLORSPACEW lcs, + const uint32_t dwFlags, + const U_CBDATA cbData, + const uint8_t *Data + ){ + char *record; + unsigned int cbData4,off; + int irecsize; + + cbData4 = UP4(cbData); // buffer to hold Data + irecsize = sizeof(U_EMRCREATECOLORSPACEW) + cbData4; + record = malloc(irecsize); + if(record){ + ((PU_EMR) record)->iType = U_EMR_CREATECOLORSPACEW; + ((PU_EMR) record)->nSize = irecsize; + ((PU_EMRCREATECOLORSPACEW) record)->ihCS = ihCS; + ((PU_EMRCREATECOLORSPACEW) record)->lcs = lcs; + ((PU_EMRCREATECOLORSPACEW) record)->dwFlags = dwFlags; + ((PU_EMRCREATECOLORSPACEW) record)->cbData = cbData; + off = sizeof(U_EMR) + sizeof(uint32_t) + sizeof(U_LOGCOLORSPACEW) + sizeof(uint32_t) + sizeof(U_CBDATA); // offset to Data field + memcpy(record + off, Data, cbData); + if(cbData < cbData4){ + off += cbData; + memset(record + off,0,cbData4-cbData); + } + } + return(record); +} + + +#ifdef __cplusplus +} +#endif diff --git a/src/3rdparty/libuemf/uemf.h b/src/3rdparty/libuemf/uemf.h new file mode 100644 index 0000000..3a51e39 --- /dev/null +++ b/src/3rdparty/libuemf/uemf.h @@ -0,0 +1,3653 @@ +/** + @file uemf.h + + @brief Structures, definitions, and function prototypes for EMF files. + + EMF file Record structure information has been derived from Mingw, Wine, and libEMF header files, and from + Microsoft's EMF Information pdf, release date March 28,2012, link from here: + + http://msdn2.microsoft.com/en-us/library/cc230514.aspx + + If the direct link fails the document may be found + by searching for: "[MS-EMF]: Enhanced Metafile Format" + +*/ + +/** \mainpage libUEMF overview +\section ov Overview +Microsoft's WMF, EMF, and EMF+ metafile types are supported. In each case functions are provided for reading, constructing, writing, and printing +metafile records. The methods used to do that differ somewhat between metafiles, and the simplest +way to get started is to have a look at the example programs provided. The WMF, EMF, and EMF+ structs and functions are +marked with U_WMF, U_EMF, U_PMF and U_WMR, U_EMR, and U_PMR prefixes. (PMF because "+" is a reserved character +in many contexts, so U_EMF+NAME would be a problem.) Please be aware that normally both EMF and EMF+ files have the ".emf" +file extension, and that it is very common for such files to contain both an EMF and an EMF+ representation of the +drawing. + +\section example_sec Example Programs +testbed_emf.c Creates an EMF file test_libuemf.emf.\n +testbed_wmf.c Creates a WMF file test_libuemf.wmf.\n +testbed_pmf.c Creates an EMF+ file test_libuemf_p.emf.\n +reademf.c Reads an EMF or EMF+ file and emits a text summary of its records.\n +readwmf.c Reads a WMF file and emits a text summary of its records.\n +emf-inout.cpp.example Example code from Inkscape to convert graphics from EMF to SVG.\n +emf-print.cpp.example Example code from Inkscape to print a drawing to EMF.\n +wmf-inout.cpp.example Example code from Inkscape to convert graphics from WMF to SVG.\n +wmf-print.cpp.example Example code from Inkscape to print a drawing to WMF. + +\section doxy_limits Documentation issues +There are currently some unresolved issues with Doxygen that result in some structs +not being "defined". This comes up when several different types of structs have the same +layout. When this occurs the first one listed on the "typedef struct" is defined but all the +others will only be shown under "typedef struct" referring to the first one. This is why +clicking on U_RECTL in a function parameter jumps to a typedef struct page, why U_RECTL is shown +as plain text here, but U_RECT is shown as a link here, and clicking on it jumps directly +to its structure definition. + +An additional issue is that the Enumeration names used in WMF are different from those +used in EMF, even when the values are either identical or differ only slightly, and no method +has been found yet to link one to the other in Doxygen. At present the only way to look up +these WMF enumerations is by referencing the following table: + + EMF WMF WMF Manual + EMF Binary Raster Operation Enumeration BinaryRasterOperation Enumeration 2.1.1.2 + EMF Bitcount Enumeration BitCount Enumeration 2.1.1.3 + EMF LB_Style Enumeration BrushStyle Enumeration 2.1.1.4 + EMF LF_CharSet Enumeration CharacterSet Enumeration 2.1.1.5 + EMF DIBColors Enumeration ColorUsage Enumeration [has 1 extra value] 2.1.1.6 + EMF BI_Compression Enumeration Compression Enumeration [has 3 extra values] 2.1.1.7 + - FamilyFont Enumeration 2.1.1.8 + EMF FloodFill Enumeration FloodFill Enumeration 2.1.1.9 + EMF LF_Quality Enumeration FontQuality Enumeration 2.1.1.10 + EMF LCS_Intent Enumeration GamutMappingIntent Enumeration 2.1.1.11 + EMF HatchStyle Enumeration HatchStyle Enumeration 2.1.1.12 + EMF Mirroring Enumeration LayoutEnumeration 2.1.1.13 + - LogicalColorSpace Enumeration 2.1.1.14 + EMF Profile Enumeration LogicalColorSpaceV5 Enumeration 2.1.1.15 + EMF MapMode Enumeration MapModeEnumeration 2.1.1.16 + - MetaFilesEscape Enumeration 2.1.1.17 + - MetafileType Enumeration 2.1.1.18 + - MetafileVersion Enumeration 2.1.1.19 + EMF BackgroundMode Enumeration MixModeEnumeration 2.1.1.20 + EMF LF_OutPrecision Enumeration OutPrecision Enumeration 2.1.1.21 + - PaletteEntryFlag Enumeration 2.1.1.22 + EMF PenStyle Enumeration PenStyle Enumeration [not values >0xFFFF] 2.1.1.23 + - PitchFont Enumeration 2.1.1.24 + EMF PolygonFillMode Enumeration PolyFillMode Enumeration [first 2 only] 2.1.1.25 + - PostScriptCap Enumeration 2.1.1.26 + - PostScriptClipping Enumeration 2.1.1.27 + - PostFeatureSetting Enumeration 2.1.1.28 + - PostScrioptJoin Enumeration 2.1.1.29 + EMF StretchMode Enumeration StretchMode Enumeration 2.1.1.30 + EMF Ternary Raster Operation Enumeration TernaryRasterOperation Enumeration 2.1.1.31 + EMF LF_ClipPrecision Enumeration ClipPrecision Flags 2.1.2.1 + EMF ExtTextOutOptions Enumeration ExtTextOutOptions Flags [subset] 2.1.2.2 + EMF TextAlignment Enumeration TextAlignment Enumeration 2.1.2.3 + EMF TextAlignment Enumeration VertialTextAlignment Enumeration 2.1.2.4 + EMF LF_PitchAndFamily Enumeration PitchAndFamily Enumerations 2.2.2.14 + +\section refs Reference documentation + + Manual Date Link + EMF 3/28/2012 http://msdn2.microsoft.com/en-us/library/cc230514.aspx + EMF+ 7/5/2012 http://msdn.microsoft.com/en-us/library/cc230724.aspx + WMF 7/5/2012 http://msdn2.microsoft.com/en-us/library/cc250370.aspx +*/ + +/* +File: uemf.h +Version: 0.0.34 +Date: 03-JAN-2017 +Author: David Mathog, Biology Division, Caltech +email: mathog@caltech.edu +Copyright: 2017 David Mathog and California Institute of Technology (Caltech) +*/ + +#ifndef _UEMF_ +#define _UEMF_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdlib.h> +#include <stdio.h> +#include <stdint.h> +#include <string.h> +#include <stdbool.h> +#include "uemf_utf.h" +#include "uemf_endian.h" + + +/** \cond */ +// *********************************************************************************** +// defines not placed yet + +#define U_PAN_CULTURE_LATIN 0 + +#define U_SYSPAL_ERROR 0 +#define U_SYSPAL_STATIC 1 +#define U_SYSPAL_NOSTATIC 2 + +#define U_ELF_VENDOR_SIZE 4 + +#define UNUSED_PARAMETER(x) (void)(x) +/** \endcond */ + +// *************************************************************************** +/** \defgroup U_EMF_Miscellaneous_values EMF Miscellaneous Values + @{ +*/ +#define U_NONE 0 //!< Generic for nothing selected for all flag fields +#define U_PI 3.14159265358979323846 //!< pi +#define U_READ 1 //!< open file as "rb" +#define U_WRITE 0 //!< open file as "wb" +#define U_DV_SGNTR 0x08007664 //!< For U_DESIGNVECTOR Signature field +#define U_LP_VERSION 0x0300 //!< For U_LOGPALETTE palVersion field +#define U_RDH_RECTANGLES 1 //!< For U_RGNDATAHEADER iType field +#define U_RDH_OBJSIZE 0x20 //!< For U_RGNDATAHEADER dwSIze field +#define U_RGB_GAMMA_MIN (uint16_t)02500 //!< For U_COLORADJUSTMENT ca[Red|Green|Blue]Gamma fields +#define U_RGB_GAMMA_MAX (uint16_t)65000 //!< For U_COLORADJUSTMENT ca[Red|Green|Blue]Gamma fields +#define U_REFERENCE_WHITE_MIN (uint16_t)6000 //!< For U_COLORADJUSTMENT caReferenceWhite field +#define U_REFERENCE_WHITE_MAX (uint16_t)10000 //!< For U_COLORADJUSTMENT caReferenceWhite field +#define U_REFERENCE_BLACK_MIN (uint16_t)0 //!< For U_COLORADJUSTMENT caReferenceBlack field +#define U_REFERENCE_BLACK_MAX (uint16_t)4000 //!< For U_COLORADJUSTMENT caReferenceBlack field +#define U_COLOR_ADJ_MIN ((int16_t)-100) //!< For U_COLORADJUSTMENT ca[Contrast|Brightness|Colorfulness|RedGreenTint] fields +#define U_COLOR_ADJ_MAX (int16_t) 100 //!< For U_COLORADJUSTMENT ca[Contrast|Brightness|Colorfulness|RedGreenTint] fields +#define U_MAX_PATH 1024 //!< longest path name for a file +#define U_LCS_SIGNATURE 0x50534F43 //!< logColorSpace Signature +#define U_LCS_VERSION 0x400 //!< logColorSpace Version +#define U_REC_FREE 1 //!< use with emf_append +#define U_REC_KEEP 0 //!< use with emf_append +#define U_ROW_ORDER_INVERT 1 //!< For RGBA_to_DIB, invert row order in DIB relative to pixel array +#define U_ROW_ORDER_SAME 0 //!< For RGBA_to_DIB, same row order in DIB as in pixel array +#define U_CT_NO 0 //!< For RGBA_to_DIB, do not use color table +#define U_CT_BGRA 1 //!< For RGBA_to_DIB, use color table (16 bits or less only) BGRA colors, compatible with EMF+ ARGB +#define U_CT_ARGB 1 //!< For RGBA_to_DIB, use color table (16 bits or less only) BGRA colors, compatible with EMF+ ARGB +#define U_EMR_COMMENT_SPOOLFONTDEF 0x544F4E46 //!< For U_EMRCOMMENT record that is U_EMR_COMMENT_SPOOL, comment holds font definition informtion. +/** Solaris 8 has problems with round/roundf, just use this everywhere */ +#define U_ROUND(A) ( (A) > 0 ? floor((A)+0.5) : ( (A) < 0 ? -floor(-(A)+0.5) : (A) ) ) + +#define MAKE_MIN_PTR(A,B) ( A < B ? A : B) +/* IS_MEM_UNSAFE takes 3 parameters: + A start address of a block of allocated memory + B offset into this block starting at A + C address of final byte of a block of allocated memory. + Returns + 1 if B cannot be an int or size_t + 1 if C > A + 1 if A+B is not in the range A to C, inclusive + 0 otherwise. + B may be an int, an unsigned int, or a size_t. An int can be negative, + which is obviously wrong, but testing for that means that the size + of B cannot be more than INT_MAX/2. Accept that limitation since + no reasonable EMF record or file should ever be that large. + If B is a uint16_t gcc complains about the first test. + This Macro must not be used where B needs more than 32 bits! +*/ +#define IS_MEM_UNSAFE(A,B,C) ( (sizeof(B) < sizeof(int) || (int)(B) < 0) ? 1 : ((int8_t *)(A) > (int8_t *)(C) ? 1 : ((int8_t *)(C) - (int8_t *)(A) >= (int)(B) ? 0 : 1 ))) //!< Return 1 when a region of memory starting at A of B bytes extends beyond pointer C + +/** @} */ + + +typedef float U_FLOAT; //!< 32 bit float + +typedef uint32_t U_CBBITS; //!< Count of Bytes in object at corresponding U_OFF* +typedef uint32_t U_CBBITSMSK; //!< Count of Bytes in object at corresponding U_OFF* +typedef uint32_t U_CBBITSSRC; //!< Count of Bytes in object at corresponding U_OFF* +typedef uint32_t U_CBBMI; //!< Count of Bytes in object at corresponding U_OFF* +typedef uint32_t U_CBBMIMSK; //!< Count of Bytes in object at corresponding U_OFF* +typedef uint32_t U_CBBMISRC; //!< Count of Bytes in object at corresponding U_OFF* +typedef uint32_t U_CBDATA; //!< Count of Bytes in object at corresponding U_OFF* +typedef uint32_t U_CBNAME; //!< Count of Bytes in object at corresponding U_OFF* +typedef uint32_t U_CBPLENTRIES; //!< Count of Bytes in object at corresponding U_OFF* +typedef uint32_t U_CBPXLFMT; //!< Count of Bytes in object at corresponding U_OFF* +typedef uint32_t U_CBRGNDATA; //!< Count of Bytes in object at corresponding U_OFF* +typedef uint32_t U_CBSTR; //!< Count of Bytes in an 8 or 16 bit string + +typedef uint32_t U_OFFBITS; //!< Byte offset to TYPE, always measured from the start of the RECORD (not the struct) +typedef uint32_t U_OFFBITSMSK; //!< Byte offset to TYPE, always measured from the start of the RECORD (not the struct) +typedef uint32_t U_OFFBITSSRC; //!< Byte offset to TYPE, always measured from the start of the RECORD (not the struct) +typedef uint32_t U_OFFBMI; //!< Byte offset to TYPE, always measured from the start of the RECORD (not the struct) +typedef uint32_t U_OFFBMIMSK; //!< Byte offset to TYPE, always measured from the start of the RECORD (not the struct) +typedef uint32_t U_OFFBMISRC; //!< Byte offset to TYPE, always measured from the start of the RECORD (not the struct) +typedef uint32_t U_OFFDATA; //!< Byte offset to TYPE, always measured from the start of the RECORD (not the struct) +typedef uint32_t U_OFFDESC; //!< Byte offset to TYPE, always measured from the start of the RECORD (not the struct) +typedef uint32_t U_OFFDX; //!< Byte offset to TYPE, always measured from the start of the RECORD (not the struct) +typedef uint32_t U_OFFPLENTRIES; //!< Byte offset to TYPE, always measured from the start of the RECORD (not the struct) +typedef uint32_t U_OFFPXLFMT; //!< Byte offset to TYPE, always measured from the start of the RECORD (not the struct) +typedef uint32_t U_OFFSTR; //!< Byte offset to string of either 8 or 16 bit characters +typedef uint8_t U_DATA; //!< any binary sort of data, not otherwise classified. + +// "Types" For array components in structures, where not otherwise defined as a structure +typedef uint32_t U_FNTAXES; //!< Font Axes For U_DESIGNVECTOR +typedef uint32_t U_STYLEENTRY; //!< StyleEntry For U_EXTLOGPEN +typedef uint32_t U_POLYCOUNTS; //!< aPolyCounts For U_EMRPOLYPOLYLINE etc. + +// "Counts" for array components in structures +typedef uint32_t U_NUM_FNTAXES; //!< Number of U_FNTAXES +typedef uint32_t U_NUM_LOGPLTNTRY; //!< Number of U_LOGPLTENTRY +typedef uint32_t U_NUM_RECTL; //!< Number of U_RECTL +typedef uint32_t U_NUM_POINTL; //!< Number of U_POINTL +typedef uint32_t U_NUM_POINT16; //!< Number of U_POINT16 +typedef uint32_t U_NUM_STYLEENTRY; //!< Number of U_STYLEENTRY +typedef uint32_t U_NUM_POLYCOUNTS; //!< Number of U_POLYCOUNTS +typedef uint32_t U_NUM_EMRTEXT; //!< Number of U_EMRTEXT +typedef uint32_t U_NUM_STR; //!< Number of 8 or 16 bit characters in string +typedef uint32_t U_NUM_TRIVERTEX; //!< Number of U_TRIVERTEX +typedef uint32_t U_NUM_GRADOBJ; //!< Number of U_GRADIENT4 OR U_GRADIENT3 (determined at run time) +typedef uint32_t U_NUM_RGBQUAD; //!< Number of U_RGBQUAD (in bmciColors in U_BITMAPCOREINFO) + + + +/* ************************ WMF pieces used in EMF or EMF+ ****************************** */ + +/** \defgroup U_EMF_EMRSETROP2_iMode_Qualifiers EMF Binary Raster Operation Enumeration + + For U_EMRSETROP2 iMode field + Microsoft name: Binary Raster Operation Enumeration + WMF manual 2.1.1.2 + + These codes specify: + 1. an order of operands (composed of various orders and combinations of: Dest, Pen) + (There are 2, hence "Binary Raster Operation") + 2. an order of operators to apply to the operands (composed of Not, Xor, Or, And) + Only a few of the more common operations are provided here. + + The default is U_R2_COPYPEN. If this value is changed to something else all subsequenty + draw operations will use the altered logic. For instance, if it is set to U_R2_BLACK and + a red rectangle is drawn it will appear as a black rectangle. + + @{ +*/ +#define U_R2_BLACK 1 //!< BLACK +#define U_R2_NOTMERGEPEN 2 //!< NOTMERGEPEN +#define U_R2_MASKNOTPEN 3 //!< MASKNOTPEN +#define U_R2_NOTCOPYPEN 4 //!< NOTCOPYPEN +#define U_R2_MASKPENNOT 5 //!< MASKPENNOT +#define U_R2_NOT 6 //!< NOT +#define U_R2_XORPEN 7 //!< XORPEN +#define U_R2_NOTMASKPEN 8 //!< NOTMASKPEN +#define U_R2_MASKPEN 9 //!< MASKPEN +#define U_R2_NOTXORPEN 10 //!< NOTXORPEN +#define U_R2_NOP 11 //!< NOP +#define U_R2_MERGENOTPEN 12 //!< MERGENOTPEN +#define U_R2_COPYPEN 13 //!< COPYPEN +#define U_R2_MERGEPENNOT 14 //!< MERGEPENNOT +#define U_R2_MERGEPEN 15 //!< MERGEPEN +#define U_R2_WHITE 16 //!< WHITE +#define U_R2_LAST 16 //!< LAST +/** @} */ + +/** \defgroup U_EMF_BITMAPINFOHEADER_biBitCount_Qualifiers EMF BitCount Enumeration + For U_BITMAPINFOHEADER biBitCount field. + Microsoft name: Bitcount Enumeration + WMF manual 2.1.1.3 + @{ +*/ +#define U_BCBM_EXPLICIT 0 //!< Derived from JPG or PNG compressed image or ? +#define U_BCBM_MONOCHROME 1 //!< 2 colors. bmiColors array has two entries +#define U_BCBM_COLOR4 4 //!< 2^4 colors. bmiColors array has 16 entries +#define U_BCBM_COLOR8 8 //!< 2^8 colors. bmiColors array has 256 entries +#define U_BCBM_COLOR16 16 //!< 2^16 colors. bmiColors is not used. Pixels are 5 bits B,G,R with 1 unused bit +#define U_BCBM_COLOR24 24 //!< 2^24 colors. bmiColors is not used. Pixels are U_RGBTRIPLE. +#define U_BCBM_COLOR32 32 //!< 2^32 colors. bmiColors is not used. Pixels are U_RGBQUAD. Also use for EMF+ ARGB +/** @} */ + +/** \defgroup U_EMF_BITMAPINFOHEADER_biCompression_Qualifiers EMF BI_Compression Enumeration + For U_BITMAPINFOHEADER biCompression field + Microsoft name: Compression Enumeration + WMF manual 2.1.1.7 + @{ +*/ +#define U_BI_UNKNOWN -1 //!< not defined in EMF standard, not to be used in EMF files +#define U_BI_RGB 0 //!< Supported by libUEMF +#define U_BI_RLE8 1 //!< NOT supported by libUEMF +#define U_BI_RLE4 2 //!< NOT supported by libUEMF +#define U_BI_BITFIELDS 3 //!< Supported by libUEMF +#define U_BI_JPEG 4 //!< Supported by libUEMF +#define U_BI_PNG 5 //!< Supported by libUEMF +/** @} */ + +/** \defgroup U_EMF_LOGCOLORSPACE_lcsIntent_Qualifiers EMF LCS_Intent Enumeration + For U_LOGCOLORSPACEA/U_LOGCOLORSPACEW lcsIntent field + Microsoft name: LCS_Intent Enumeration + WMF manual 2.1.1.11 + @{ +*/ +#define U_LCS_GM_BUSINESS 0x00000001L //!< BUSINESS +#define U_LCS_GM_GRAPHICS 0x00000002L //!< GRAPHICS +#define U_LCS_GM_IMAGES 0x00000004L //!< IMAGES +#define U_LCS_GM_ABS_COLORIMETRIC 0x00000008L //!< ABS_COLORIMETRIC +/** @} */ + +/** \defgroup U_EMF_LOGCOLORSPACE_lcsCSType_Qualifiers EMF LCS_CSType Enumeration + For U_LOGCOLORSPACEA/U_LOGCOLORSPACEW lcsCSType field + Microsoft name: LCS_CSType Enumeration + WMF manual 2.1.1.14 + @{ +*/ +#define U_LCS_CALIBRATED_RGB 0x00000000L //!< CALIBRATED_RGB +#define U_LCS_DEVICE_RGB 0x00000001L //!< DEVICE_RGB +#define U_LCS_DEVICE_CMYK 0x00000002L //!< DEVICE_CMYK +/** @} */ + +/** \defgroup U_EMF_EMR_dwROP_Qualifiers EMF Ternary Raster Operation enumeration + + For U_EMR* dwROP fields. + Microsoft name: Ternary Raster Operation enumeration + WMF manual 2.1.1.31 + + These codes specify: + 1. an order of operands (composed of various orders and combinations of: Dest, Src, Pen) + (There are 3, hence "Ternary Raster Operation") + 2. an order of operators to apply to the operands (composed of Not, Xor, Or, And) + Only a few of the more common operations are provided here. + When the Operation does not use a Src operand the corresponding source bitmap may be + omitted from the record. + + For more details see: + http://wiki.winehq.org/TernaryRasterOps + + + @{ +*/ +#define U_SRCCOPY 0x00cc0020 //!< SRCCOPY +#define U_SRCPAINT 0x00ee0086 //!< SRCPAINT +#define U_SRCAND 0x008800c6 //!< SRCAND +#define U_SRCINVERT 0x00660046 //!< SRCINVERT +#define U_SRCERASE 0x00440328 //!< SRCERASE +#define U_NOTSRCCOPY 0x00330008 //!< NOTSRCCOPY +#define U_NOTSRCERASE 0x001100a6 //!< NOTSRCERASE +#define U_MERGECOPY 0x00c000ca //!< MERGECOPY +#define U_MERGEPAINT 0x00bb0226 //!< MERGEPAINT +#define U_PATCOPY 0x00f00021 //!< PATCOPY +#define U_PATPAINT 0x00fb0a09 //!< PATPAINT +#define U_PATINVERT 0x005a0049 //!< PATINVERT +#define U_DSTINVERT 0x00550009 //!< DSTINVERT +#define U_BLACKNESS 0x00000042 //!< BLACKNESS +#define U_WHITENESS 0x00ff0062 //!< WHITENESS +#define U_NOOP 0x00aa0029 //!< Many GDI programs end with a bitblt with this ROP == "D". Seems to work like flush() +#define U_NOMIRRORBITMAP 0x80000000 //!< If bit set, disable horizontal reflection of bitmap. +/** @} */ + +/** \defgroup U_EMF_EMRSETTEXTALIGN_iMode_Qualifiers EMF TextAlignment Enumeration + For U_EMRSETTEXTALIGN iMode field + Microsoft name: TextAlignment Enumeration + WMF Manual 2.1.2.3 + WMF Manual 2.1.2.4 + + Recall that EMF coordinates have UL closest to {0,0}, LR is below and to the right of UL and so has LARGER + {x,y} coordinates. In the following "TOP" is on the horizontal line defined by LR, as it has larger y coordinates, + which when viewing the EMF file, would actually be on the BOTTOM of the bounding rectangle. Similarly, left and right + are reversed. + + Microsoft documentation (WMF manual, section 2.1.2.3) says that the text starts on certain edges of the bounding rectangle. + That is apparently not true, whether the bounding rectangle is {0,0,-1,-1}, which is effectively no bounding rectangle, + or if a valid bounding rectangle is specified. In all cases the text (in Windows XP Preview) starts, has center at, or ends + at the center point. Vertical offsets seem to be defined analogously, but with respect to the height of the font. The bounding + rectangle defined for the U_EMRTEXT record appears to be ignored. + + Microsoft documentation (EMF manual,section 2.2.5) says that the same rectangle is used for "clipping or opaquing" by ExtTextOutA/W. + That does not seem to occur either. + + @{ +*/ +// Horizontal text flags +#define U_TA_DEFAULT 0x00 //!< default alignment +#define U_TA_NOUPDATECP 0x00 //!< Reference point does not move +#define U_TA_UPDATECP 0x01 //!< Reference point moves to end of next text drawn. +#define U_TA_LEFT 0x00 //!< Reference point is on left edge of bounding rectangle +#define U_TA_RIGHT 0x02 //!< Reference point is on right edge of bounding rectangle +#define U_TA_CENTER 0x06 //!< Reference point is on center vertical line of bounding rectangle +#define U_TA_TOP 0x00 //!< Reference point is on top edge of bounding rectangle +#define U_TA_BOTTOM 0x08 //!< Reference point is on bottom edge of bounding rectangle +#define U_TA_BASEBIT 0x10 //!< Reference point is on baseline of text if this bit is set, for 0x10 <-> 0x18 +#define U_TA_BASELINE 0x18 //!< Reference point is on baseline of text +#define U_TA_RTLREADING 0x100 //!< Set for Right to Left languages like Hebrew and Arabic +#define U_TA_MASK U_TA_BASELINE+U_TA_CENTER+U_TA_UPDATECP+U_TA_RTLREADING //!< Mask for these bits +// Vertical text flags +#define U_VTA_BASELINE U_TA_BASELINE //!< same meaning, but for vertical text +#define U_VTA_LEFT U_TA_BOTTOM //!< same meaning, but for vertical text +#define U_VTA_RIGHT U_TA_TOP //!< same meaning, but for vertical text +#define U_VTA_CENTER U_TA_CENTER //!< same meaning, but for vertical text +#define U_VTA_BOTTOM U_TA_RIGHT //!< same meaning, but for vertical text +#define U_VTA_TOP U_TA_LEFT //!< same meaning, but for vertical text +/** @} */ + +/** WMF manual 2.2.2.3 + \brief For U_BITMAPINFO bmiHeader field + + Microsoft name: BITMAPINFOHEADER Object +*/ +typedef struct { + uint32_t biSize; //!< Structure size in bytes + int32_t biWidth; //!< Bitmap width in pixels + int32_t biHeight; //!< Bitmap height in pixels, may be negative. + //!< abs(biHeight) is bitmap height + //!< bitmap may appear in two orientations: + //!< biHeight > 0 origin is LL corner, may be compressed, this is height after decompression. + //!< biHeight < 0 origin is UL corner, may not be compressed + uint16_t biPlanes; //!< Planes (must be 1) + uint16_t biBitCount; //!< BitCount Enumeration (determines number of RBG colors) + uint32_t biCompression; //!< BI_Compression Enumeration + uint32_t biSizeImage; //!< Image size in bytes or 0 = "default size (calculated from geometry?)" + int32_t biXPelsPerMeter; //!< X Resolution in pixels/meter + int32_t biYPelsPerMeter; //!< Y Resolution in pixels/meter + U_NUM_RGBQUAD biClrUsed; //!< Number of bmciColors in U_BITMAPINFO/U_BITMAPCOREINFO that are used by the bitmap + uint32_t biClrImportant; //!< Number of bmciColors needed (0 means all). +} U_BITMAPINFOHEADER, + *PU_BITMAPINFOHEADER; //!< WMF manual 2.2.2.3 +#define U_SIZE_BITMAPINFOHEADER (sizeof(U_BITMAPINFOHEADER)) + +/** WMF manual 2.2.2.6 + \brief For U_CIEXYZTRIPLE (all) fields + + Microsoft name: CIEXYZ Object +*/ +typedef struct { + int32_t ciexyzX; //!< CIE color space X component + int32_t ciexyzY; //!< CIE color space Y component + int32_t ciexyzZ; //!< CIE color space Z component +} U_CIEXYZ, + *PU_CIEXYZ; //!< WMF manual 2.2.2.6 + +/** WMF manual 2.2.2.7 + \brief For U_LOGCOLORSPACEA and U_LOGCOLORSPACEW lcsEndpints field + + defines a CIE colorspace. + Microsoft name: CIEXYZTRIPLE Object + +*/ +typedef struct { + U_CIEXYZ ciexyzRed; //!< CIE XYZ coord of red endpoint of colorspace + U_CIEXYZ ciexyzGreen; //!< CIE XYZ coord of green endpoint of colorspace + U_CIEXYZ ciexyzBlue; //!< CIE XYZ coord of blue endpoint of colorspace +} U_CIEXYZTRIPLE, + *PU_CIEXYZTRIPLE; //!< WMF manual 2.2.2.7 + +/** WMF manual 2.2.2.8 + \brief For U_BITMAPINFO crColor field + + NOTE that the color order is RGB reserved, flipped around from the preceding. + Microsoft name: COLORREF Object +*/ +typedef struct { + uint8_t Red; //!< Red color (0-255) + uint8_t Green; //!< Green color (0-255) + uint8_t Blue; //!< Blue color (0-255) + uint8_t Reserved; //!< Not used +} U_COLORREF, + *PU_COLORREF; //!< WMF manual 2.2.2.8 + +/** WMF manual 2.2.2.11 + \brief For U_LCS_GAMMARGB lcsGamma* fields + + Microsoft name:(unknown) +*/ +typedef struct { + unsigned ignoreHi :8; //!< not used + unsigned intPart :8; //!< integer part + unsigned fracPart :8; //!< fraction part + unsigned ignoreLo :8; //!< not used +} U_LCS_GAMMA, + *PU_LCS_GAMMA; //!< WMF manual 2.2.2.11 + +/** WMF manual 2.2.2.11 + \brief For U_LOGCOLORSPACEA and U_LOGCOLORSPACEW lcsGammaRGB field + + Microsoft name:(unknown) +*/ +typedef struct { + U_LCS_GAMMA lcsGammaRed; //!< Red Gamma + U_LCS_GAMMA lcsGammaGreen; //!< Green Gamma + U_LCS_GAMMA lcsGammaBlue; //!< Blue Gamma +} U_LCS_GAMMARGB, + *PU_LCS_GAMMARGB; //!< WMF manual 2.2.2.11 + +/** WMF manual 2.2.2.11 + \brief For U_EMRCREATECOLORSPACE lcs field + + Microsoft name: LOGCOLORSPACEA Object +*/ +typedef struct { + uint32_t lcsSignature; //!< must be U_LCS_SIGNATURE + uint32_t lcsVersion; //!< must be U_LCS_VERSION + uint32_t lcsSize; //!< Size in bytes of this structure + int32_t lcsCSType; //!< LCS_CSType Enumeration + int32_t lcsIntent; //!< LCS_Intent Enumeration + U_CIEXYZTRIPLE lcsEndpoints; //!< CIE XYZ color space endpoints + U_LCS_GAMMARGB lcsGammaRGB; //!< Gamma For RGB + char lcsFilename[U_MAX_PATH]; //!< Names an external color profile file, otherwise empty string +} U_LOGCOLORSPACEA, + *PU_LOGCOLORSPACEA; //!< WMF manual 2.2.2.11 + +/** WMF manual 2.2.2.12 + \brief For U_EMRCREATECOLORSPACEW lcs field + + Microsoft name: LOGCOLORSPACEW Object +*/ +typedef struct { + uint32_t lcsSignature; //!< must be U_LCS_SIGNATURE + uint32_t lcsVersion; //!< must be U_LCS_VERSION + uint32_t lcsSize; //!< Size in bytes of this structure + int32_t lcsCSType; //!< lcsCSType Enumeration + int32_t lcsIntent; //!< lcsIntent Enumeration + U_CIEXYZTRIPLE lcsEndpoints; //!< CIE XYZ color space endpoints + U_LCS_GAMMARGB lcsGammaRGB; //!< Gamma For RGB + uint16_t lcsFilename[U_MAX_PATH]; //!< Could name an external color profile file, otherwise empty string +} U_LOGCOLORSPACEW, + *PU_LOGCOLORSPACEW; //!< WMF manual 2.2.2.12 + +/** WMF manual 2.2.2.15 + \brief Used for any generic pair of uint32_t + + Microsoft name: POINTL Object +*/ +typedef struct { + int32_t x; //!< X value + int32_t y; //!< Y value +} U_PAIR, + U_POINT, //!< WMF manual 2.2.2.15 + U_POINTL, //!< WMF manual 2.2.2.15 + *PU_PAIR, //!< WMF manual 2.2.2.15 + *PU_POINT, //!< WMF manual 2.2.2.15 + *PU_POINTL; //!< WMF manual 2.2.2.15 + + +/** WMF manual 2.2.2.16 + \brief Point type for 16 bit EMR drawing functions. + + Microsoft name: POINTS Object. + Microsoft name: POINTS16 Object. +*/ +typedef struct { + int16_t x; //!< X size (16 bit) + int16_t y; //!< Y size (16 bit) +} U_POINT16, + *PU_POINT16; //!< WMF manual 2.2.2.16 + +/** WMF manual 2.2.2.19 + \brief Coordinates of the upper left, lower right corner. + + Note that the coordinate system is 0,0 in the upper left corner + of the screen an N,M in the lower right corner. + Microsoft name: RECTL Object +*/ +typedef struct { + int32_t left; //!< left coordinate + int32_t top; //!< top coordinate + int32_t right; //!< right coordinate + int32_t bottom; //!< bottom coordinate +} U_RECT, + U_RECTL, //!< WMF manual 2.2.2.19 + *PU_RECT, //!< WMF manual 2.2.2.19 + *PU_RECTL; //!< WMF manual 2.2.2.19 + +/** WMF manual 2.2.2.20 + \brief For U_BITMAPINFO bmiColors field + + NOTE that the color order is BGR, even though the name is RGB! + Microsoft name: RGBQUAD Object +*/ +typedef struct { + uint8_t Blue; //!< Blue color (0-255) + uint8_t Green; //!< Green color (0-255) + uint8_t Red; //!< Red color (0-255) + uint8_t Reserved; //!< Not used +} U_RGBQUAD, + *PU_RGBQUAD; //!< WMF manual 2.2.2.20 + +#define U_RCL_DEF (U_RECTL){0,0,-1,-1} //!< Use this when no bounds are needed. + +/** WMF manual 2.2.2.22 + \brief Pair of values indicating x and y sizes. + + Microsoft name: SIZE Object + Microsoft name: SIZEL Object +*/ +typedef struct { + int32_t cx; //!< X size + int32_t cy; //!< Y size +} U_SIZE, + U_SIZEL, //!< WMF manual 2.2.2.22 + *PU_SIZE, //!< WMF manual 2.2.2.22 + *PU_SIZEL; //!< WMF manual 2.2.2.22 + + + +/* ************************ EMF or common to EMF and EMF+ ****************************** */ + +// *********************************************************************************** +// Value enumerations and other predefined constants, alphabetical order by group + + +/** \defgroup U_EMF_FONT_STRUCT_WIDTHS EMF Font name and style widths in characters + For U_LOGFONT and U_LOGFONT_PANOSE, + @{ +*/ +#define U_LF_FACESIZE 32 //!< U_LOGFONT lfFaceName and U_LOGFONT_PANOSE elfStyle fields maximum width +#define U_LF_FULLFACESIZE 64 //!< U_LOGFONT_PANOSE elfFullName field maximum width +/** @} */ + +/** \defgroup U_EMF_EMR_Qualifiers EMF RecordType Enumeration + (RecordType Enumeration, EMF manual 2.1.1 ) + For U_EMR iType field + EMF manual 2.1.1 + @{ +*/ +#define U_EMR_HEADER 1 //!< U_EMRHEADER record +#define U_EMR_POLYBEZIER 2 //!< U_EMRPOLYBEZIER record +#define U_EMR_POLYGON 3 //!< U_EMRPOLYGON record +#define U_EMR_POLYLINE 4 //!< U_EMRPOLYLINE record +#define U_EMR_POLYBEZIERTO 5 //!< U_EMRPOLYBEZIERTO record +#define U_EMR_POLYLINETO 6 //!< U_EMRPOLYLINETO record +#define U_EMR_POLYPOLYLINE 7 //!< U_EMRPOLYPOLYLINE record +#define U_EMR_POLYPOLYGON 8 //!< U_EMRPOLYPOLYGON record +#define U_EMR_SETWINDOWEXTEX 9 //!< U_EMRSETWINDOWEXTEX record +#define U_EMR_SETWINDOWORGEX 10 //!< U_EMRSETWINDOWORGEX record +#define U_EMR_SETVIEWPORTEXTEX 11 //!< U_EMRSETVIEWPORTEXTEX record +#define U_EMR_SETVIEWPORTORGEX 12 //!< U_EMRSETVIEWPORTORGEX record +#define U_EMR_SETBRUSHORGEX 13 //!< U_EMRSETBRUSHORGEX record +#define U_EMR_EOF 14 //!< U_EMREOF record +#define U_EMR_SETPIXELV 15 //!< U_EMRSETPIXELV record +#define U_EMR_SETMAPPERFLAGS 16 //!< U_EMRSETMAPPERFLAGS record +#define U_EMR_SETMAPMODE 17 //!< U_EMRSETMAPMODE record +#define U_EMR_SETBKMODE 18 //!< U_EMRSETBKMODE record +#define U_EMR_SETPOLYFILLMODE 19 //!< U_EMRSETPOLYFILLMODE record +#define U_EMR_SETROP2 20 //!< U_EMRSETROP2 record +#define U_EMR_SETSTRETCHBLTMODE 21 //!< U_EMRSETSTRETCHBLTMODE record +#define U_EMR_SETTEXTALIGN 22 //!< U_EMRSETTEXTALIGN record +#define U_EMR_SETCOLORADJUSTMENT 23 //!< U_EMRSETCOLORADJUSTMENT record +#define U_EMR_SETTEXTCOLOR 24 //!< U_EMRSETTEXTCOLOR record +#define U_EMR_SETBKCOLOR 25 //!< U_EMRSETBKCOLOR record +#define U_EMR_OFFSETCLIPRGN 26 //!< U_EMROFFSETCLIPRGN record +#define U_EMR_MOVETOEX 27 //!< U_EMRMOVETOEX record +#define U_EMR_SETMETARGN 28 //!< U_EMRSETMETARGN record +#define U_EMR_EXCLUDECLIPRECT 29 //!< U_EMREXCLUDECLIPRECT record +#define U_EMR_INTERSECTCLIPRECT 30 //!< U_EMRINTERSECTCLIPRECT record +#define U_EMR_SCALEVIEWPORTEXTEX 31 //!< U_EMRSCALEVIEWPORTEXTEX record +#define U_EMR_SCALEWINDOWEXTEX 32 //!< U_EMRSCALEWINDOWEXTEX record +#define U_EMR_SAVEDC 33 //!< U_EMRSAVEDC record +#define U_EMR_RESTOREDC 34 //!< U_EMRRESTOREDC record +#define U_EMR_SETWORLDTRANSFORM 35 //!< U_EMRSETWORLDTRANSFORM record +#define U_EMR_MODIFYWORLDTRANSFORM 36 //!< U_EMRMODIFYWORLDTRANSFORM record +#define U_EMR_SELECTOBJECT 37 //!< U_EMRSELECTOBJECT record +#define U_EMR_CREATEPEN 38 //!< U_EMRCREATEPEN record +#define U_EMR_CREATEBRUSHINDIRECT 39 //!< U_EMRCREATEBRUSHINDIRECT record +#define U_EMR_DELETEOBJECT 40 //!< U_EMRDELETEOBJECT record +#define U_EMR_ANGLEARC 41 //!< U_EMRANGLEARC record +#define U_EMR_ELLIPSE 42 //!< U_EMRELLIPSE record +#define U_EMR_RECTANGLE 43 //!< U_EMRRECTANGLE record +#define U_EMR_ROUNDRECT 44 //!< U_EMRROUNDRECT record +#define U_EMR_ARC 45 //!< U_EMRARC record +#define U_EMR_CHORD 46 //!< U_EMRCHORD record +#define U_EMR_PIE 47 //!< U_EMRPIE record +#define U_EMR_SELECTPALETTE 48 //!< U_EMRSELECTPALETTE record +#define U_EMR_CREATEPALETTE 49 //!< U_EMRCREATEPALETTE record +#define U_EMR_SETPALETTEENTRIES 50 //!< U_EMRSETPALETTEENTRIES record +#define U_EMR_RESIZEPALETTE 51 //!< U_EMRRESIZEPALETTE record +#define U_EMR_REALIZEPALETTE 52 //!< U_EMRREALIZEPALETTE record +#define U_EMR_EXTFLOODFILL 53 //!< U_EMREXTFLOODFILL record +#define U_EMR_LINETO 54 //!< U_EMRLINETO record +#define U_EMR_ARCTO 55 //!< U_EMRARCTO record +#define U_EMR_POLYDRAW 56 //!< U_EMRPOLYDRAW record +#define U_EMR_SETARCDIRECTION 57 //!< U_EMRSETARCDIRECTION record +#define U_EMR_SETMITERLIMIT 58 //!< U_EMRSETMITERLIMIT record +#define U_EMR_BEGINPATH 59 //!< U_EMRBEGINPATH record +#define U_EMR_ENDPATH 60 //!< U_EMRENDPATH record +#define U_EMR_CLOSEFIGURE 61 //!< U_EMRCLOSEFIGURE record +#define U_EMR_FILLPATH 62 //!< U_EMRFILLPATH record +#define U_EMR_STROKEANDFILLPATH 63 //!< U_EMRSTROKEANDFILLPATH record +#define U_EMR_STROKEPATH 64 //!< U_EMRSTROKEPATH record +#define U_EMR_FLATTENPATH 65 //!< U_EMRFLATTENPATH record +#define U_EMR_WIDENPATH 66 //!< U_EMRWIDENPATH record +#define U_EMR_SELECTCLIPPATH 67 //!< U_EMRSELECTCLIPPATH record +#define U_EMR_ABORTPATH 68 //!< U_EMRABORTPATH record +#define U_EMR_UNDEF69 69 //!< U_EMRUNDEF69 record +#define U_EMR_COMMENT 70 //!< U_EMRCOMMENT record +#define U_EMR_FILLRGN 71 //!< U_EMRFILLRGN record +#define U_EMR_FRAMERGN 72 //!< U_EMRFRAMERGN record +#define U_EMR_INVERTRGN 73 //!< U_EMRINVERTRGN record +#define U_EMR_PAINTRGN 74 //!< U_EMRPAINTRGN record +#define U_EMR_EXTSELECTCLIPRGN 75 //!< U_EMREXTSELECTCLIPRGN record +#define U_EMR_BITBLT 76 //!< U_EMRBITBLT record +#define U_EMR_STRETCHBLT 77 //!< U_EMRSTRETCHBLT record +#define U_EMR_MASKBLT 78 //!< U_EMRMASKBLT record +#define U_EMR_PLGBLT 79 //!< U_EMRPLGBLT record +#define U_EMR_SETDIBITSTODEVICE 80 //!< U_EMRSETDIBITSTODEVICE record +#define U_EMR_STRETCHDIBITS 81 //!< U_EMRSTRETCHDIBITS record +#define U_EMR_EXTCREATEFONTINDIRECTW 82 //!< U_EMREXTCREATEFONTINDIRECTW record +#define U_EMR_EXTTEXTOUTA 83 //!< U_EMREXTTEXTOUTA record +#define U_EMR_EXTTEXTOUTW 84 //!< U_EMREXTTEXTOUTW record +#define U_EMR_POLYBEZIER16 85 //!< U_EMRPOLYBEZIER16 record +#define U_EMR_POLYGON16 86 //!< U_EMRPOLYGON16 record +#define U_EMR_POLYLINE16 87 //!< U_EMRPOLYLINE16 record +#define U_EMR_POLYBEZIERTO16 88 //!< U_EMRPOLYBEZIERTO16 record +#define U_EMR_POLYLINETO16 89 //!< U_EMRPOLYLINETO16 record +#define U_EMR_POLYPOLYLINE16 90 //!< U_EMRPOLYPOLYLINE16 record +#define U_EMR_POLYPOLYGON16 91 //!< U_EMRPOLYPOLYGON16 record +#define U_EMR_POLYDRAW16 92 //!< U_EMRPOLYDRAW16 record +#define U_EMR_CREATEMONOBRUSH 93 //!< U_EMRCREATEMONOBRUSH record +#define U_EMR_CREATEDIBPATTERNBRUSHPT 94 //!< U_EMRCREATEDIBPATTERNBRUSHPT record +#define U_EMR_EXTCREATEPEN 95 //!< U_EMREXTCREATEPEN record +#define U_EMR_POLYTEXTOUTA 96 //!< U_EMRPOLYTEXTOUTA record +#define U_EMR_POLYTEXTOUTW 97 //!< U_EMRPOLYTEXTOUTW record +#define U_EMR_SETICMMODE 98 //!< U_EMRSETICMMODE record +#define U_EMR_CREATECOLORSPACE 99 //!< U_EMRCREATECOLORSPACE record +#define U_EMR_SETCOLORSPACE 100 //!< U_EMRSETCOLORSPACE record +#define U_EMR_DELETECOLORSPACE 101 //!< U_EMRDELETECOLORSPACE record +#define U_EMR_GLSRECORD 102 //!< U_EMRGLSRECORD record +#define U_EMR_GLSBOUNDEDRECORD 103 //!< U_EMRGLSBOUNDEDRECORD record +#define U_EMR_PIXELFORMAT 104 //!< U_EMRPIXELFORMAT record +#define U_EMR_DRAWESCAPE 105 //!< U_EMRDRAWESCAPE record +#define U_EMR_EXTESCAPE 106 //!< U_EMREXTESCAPE record +#define U_EMR_UNDEF107 107 //!< U_EMRUNDEF107 record +#define U_EMR_SMALLTEXTOUT 108 //!< U_EMRSMALLTEXTOUT record +#define U_EMR_FORCEUFIMAPPING 109 //!< U_EMRFORCEUFIMAPPING record +#define U_EMR_NAMEDESCAPE 110 //!< U_EMRNAMEDESCAPE record +#define U_EMR_COLORCORRECTPALETTE 111 //!< U_EMRCOLORCORRECTPALETTE record +#define U_EMR_SETICMPROFILEA 112 //!< U_EMRSETICMPROFILEA record +#define U_EMR_SETICMPROFILEW 113 //!< U_EMRSETICMPROFILEW record +#define U_EMR_ALPHABLEND 114 //!< U_EMRALPHABLEND record +#define U_EMR_SETLAYOUT 115 //!< U_EMRSETLAYOUT record +#define U_EMR_TRANSPARENTBLT 116 //!< U_EMRTRANSPARENTBLT record +#define U_EMR_UNDEF117 117 //!< U_EMRUNDEF117 record +#define U_EMR_GRADIENTFILL 118 //!< U_EMRGRADIENTFILL record +#define U_EMR_SETLINKEDUFIS 119 //!< U_EMRSETLINKEDUFIS record +#define U_EMR_SETTEXTJUSTIFICATION 120 //!< U_EMRSETTEXTJUSTIFICATION record +#define U_EMR_COLORMATCHTOTARGETW 121 //!< U_EMRCOLORMATCHTOTARGETW record +#define U_EMR_CREATECOLORSPACEW 122 //!< U_EMRCREATECOLORSPACEW record + +#define U_EMR_MIN 1 //!< Minimum U_EMR_ value. +#define U_EMR_MAX 122 //!< Maximum U_EMR_ value. Not much beyond 104 is implemented + +#define U_EMR_INVALID 0xFFFFFFFF //!< Not any valid U_EMF_ value +/** @} */ + + +/** \defgroup U_EMF_DRAW_PROPERTIES EMF draw properties + Used in emr_properties() and wmr_properties. These are the bit definitions. + @{ +*/ +#define U_DRAW_NOTEMPTY 0x001 //!< Path has at least a MOVETO in it +#define U_DRAW_VISIBLE 0x002 //!< Path has at least a LINE in it +#define U_DRAW_CLOSED 0x004 //!< Path has been closed +#define U_DRAW_ONLYTO 0x008 //!< Path so far contains only *TO operations +#define U_DRAW_FORCE 0x010 //!< Path MUST be drawn +#define U_DRAW_ALTERS 0x020 //!< Alters draw parameters (pen, brush, coordinates...) +#define U_DRAW_PATH 0x040 //!< An explicit path is being used (with a BEGIN and END) +#define U_DRAW_TEXT 0x080 //!< Current record forces all pending text to be drawn first. +#define U_DRAW_OBJECT 0x100 //!< Creates an Object (only used in WMF) +#define U_DRAW_NOFILL 0x200 //!< Object is not fillable (lines and arc, only used in WMF) + +/** @} */ +/** \defgroup U_EMF_EMRSETARCDIRECTION_Qualifiers EMF ArcDirection Enumeration + For U_EMRSETARCDIRECTION iArcDirection field + Microsoft name: ArcDirection Enumeration + EMF manual 2.1.2 + @{ +*/ +#define U_AD_COUNTERCLOCKWISE 1 //!< Draw arc counterclockwise. +#define U_AD_CLOCKWISE 2 //!< Draw arc clockwise. +/** @} */ + +/** \defgroup U_EMF_PANOSE_bArmStyle_Qualifiers EMF ArmStyle Enumeration + For U_PANOSE bArmStyle field + Microsoft name: ArmStyle Enumeration + EMF manual 2.1.3 + @{ +*/ +#define U_PAN_STRAIGHT_ARMS_HORZ 2 //!< straight arms horizontal +#define U_PAN_STRAIGHT_ARMS_WEDGE 3 //!< straight arms wedge +#define U_PAN_STRAIGHT_ARMS_VERT 4 //!< straight arms vertical +#define U_PAN_STRAIGHT_ARMS_SINGLE_SERIF 5 //!< straight arms singleserif +#define U_PAN_STRAIGHT_ARMS_DOUBLE_SERIF 6 //!< straight arms doubleserif +#define U_PAN_BENT_ARMS_HORZ 7 //!< bent arms horizontal +#define U_PAN_BENT_ARMS_WEDGE 8 //!< bent arms wedge +#define U_PAN_BENT_ARMS_VERT 9 //!< bent arms vertical +#define U_PAN_BENT_ARMS_SINGLE_SERIF 10 //!< bent arms singleserif +#define U_PAN_BENT_ARMS_DOUBLE_SERIF 11 //!< bent arms doubleserif +/** @} */ + +/** \defgroup U_EMF_EMRSETBKMODE_iMode_Qualifiers EMF BackgroundMode enumeration + For U_EMRSETBKMODE iMode field + Microsoft name: BackgroundMode enumeration + EMF manual 2.1.4 + @{ +*/ +#define U_TRANSPARENT 1 //!< Transparent background mode +#define U_OPAQUE 2 //!< Opaque background mode +/** @} */ + +/** \defgroup U_EMF_COLORADJUSTMENT_caFlags_Qualifiers EMF ColorAdjustment Enumeration + For U_COLORADJUSTMENT caFlags field + Microsoft name: ColorAdjustment Enumeration + EMF manual 2.1.5 + @{ +*/ +#define U_CA_NEGATIVE 0x0001 //!< display Negative of image +#define U_CA_LOG_FILTER 0x0002 //!< display Logarithmi filter of image +/** @} */ + +/** \defgroup U_EMF_EMRCOLORMATCHTOTARGETW_dwFlags_Qualifiers EMF ColorMatchToTarget Enumeration + For U_EMRCOLORMATCHTOTARGETW dwFlags field + Microsoft name: ColorMatchToTarget Enumeration + EMF manual 2.1.6 + @{ +*/ +#define U_COLORMATCHTOTARGET_NOTEMBEDDED 0 //!< Color match profile is not embedded in metafile +#define U_COLORMATCHTOTARGET_EMBEDDED 1 //!< Color match profile is embedded in metafile +/** @} */ + +/** \defgroup U_EMF_EMRCOLORMATCHTOTARGETW_dwAction_Qualifiers EMF ColorSpace Enumeration + For U_EMRCOLORMATCHTOTARGETW dwAction field + Microsoft name: ColorSpace Enumeration + EMF manual 2.1.7 + @{ +*/ +#define U_CS_ENABLE 1 //!< Enable color proofing. +#define U_CS_DISABLE 2 //!< Disable color proofing. +#define U_CS_DELETE_TRANSFORM 3 //!< Disable proofing and delete color transform. +/** @} */ + +/** \defgroup U_EMF_PANOSE_common_Qualifiers EMF PanoseCommon Enumeration + Used by all PAN_* enumerations, but only defined once here. + See also U_PAN_ALL1 after the U_PANOSE structure + @{ +*/ +#define U_PAN_ANY 0 //!< Any (for any type of Panose enumeration) +#define U_PAN_NO_FIT 1 //!< No fit (for any type of Panose enumeration) +/** @} */ + +/** \defgroup U_EMF_PANOSE_bContrast_Qualifiers EMF Contrast Enumeration + For U_PANOSE bContrast field + Microsoft name: Contrast Enumeration + EMF manual 2.1.8 + @{ +*/ +#define U_PAN_CONTRAST_NONE 2 //!< None +#define U_PAN_CONTRAST_VERY_LOW 3 //!< Very low +#define U_PAN_CONTRAST_LOW 4 //!< Low +#define U_PAN_CONTRAST_MEDIUM_LOW 5 //!< Medium low +#define U_PAN_CONTRAST_MEDIUM 6 //!< Medium +#define U_PAN_CONTRAST_MEDIUM_HIGH 7 //!< Medium high +#define U_PAN_CONTRAST_HIGH 8 //!< High +#define U_PAN_CONTRAST_VERY_HIGH 9 //!< Very high +/** @} */ + +/** \defgroup U_EMF_DIBITS_iUsageSrc_Qualifiers EMF DIBColors Enumeration + For U_EMRSETDIBITSTODEIVCE and U_EMRSTRETCHDIBITS iUsageSrc fields. + Microsoft name: DIBColors Enumeration + EMF manual 2.1.9 + @{ +*/ +#define U_DIB_RGB_COLORS 0 //!< color table contains colors +#define U_DIB_PAL_COLORS 1 //!< color table contains 16 bit indices into logical palette +#define U_DIB_PAL_INDICES 2 //!< no color table, pixel values are indices into logical palette +/** @} */ + +/** \defgroup U_EMF_EMR_COMMENT_PUBLIC EMF EMRComment Enumeration + For U_EMRCOMMENT_PUBLIC pcIdent fields + Microsoft name: EMRComment Enumeration + EMF manual 2.1.10 + @{ +*/ +#define U_EMR_COMMENT_WINDOWS_METAFILE 0x80000001 //!< Comment contains WMF +#define U_EMR_COMMENT_BEGINGROUP 0x00000002 //!< Comment begins group of EMF records +#define U_EMR_COMMENT_ENDGROUP 0x00000003 //!< Comment ends group of EMF records +#define U_EMR_COMMENT_MULTIFORMATS 0x40000004 //!< Comment contains some other representation of drawing +#define U_EMR_COMMENT_UNICODE_STRING 0x00000040 //!< Reserved +#define U_EMR_COMMENT_UNICODE_END 0x00000080 //!< Reserved +/** @} */ + +/** \defgroup U_EMF_EMRTEXT_foptions_Qualifiers EMF ExtTextOutOptions Enumeration + For U_EMRTEXT foptions field + Microsoft name: ExtTextOutOptions Enumeration + EMF manual 2.1.11 + @{ +*/ +#define U_ETO_NONE 0x00000000 //!< None +#define U_ETO_GRAYED 0x00000001 //!< Grayed +#define U_ETO_OPAQUE 0x00000002 //!< Fill rectangle with background color. +#define U_ETO_CLIPPED 0x00000004 //!< Clip text to rectangle. +#define U_ETO_GLYPH_INDEX 0x00000010 //!< Characters are glyph indices for the font. +#define U_ETO_RTLREADING 0x00000080 //!< Right to left text. +#define U_ETO_NO_RECT 0x00000100 //!< No bounding rectangle is specified. +#define U_ETO_SMALL_CHARS 0x00000200 //!< 8 bit characters instead of 16 bit. For EMRSMALLTEXTOUT ONLY, does not affect EMRTEXTOUTA or EMRTEXTOUTW +#define U_ETO_NUMERICSLOCAL 0x00000400 //!< Show numbers for the current locale. +#define U_ETO_NUMERICSLATIN 0x00000800 //!< Show numbers using European digits. +#define U_ETO_IGNORELANGUAGE 0x00001000 //!< Process Right to Left languages exactly as specified in the metafile. +#define U_ETO_PDY 0x00002000 //!< Both horizontal and vertical displacements are provided. +#define U_ETO_REVERSE_INDEX_MAP 0x00010000 //!< Reverse_index_map +/** @} */ + +/** \defgroup U_EMF_PANOSE_bFamilyType_Qualifiers EMF FamilyType Enumeration + For U_PANOSE bFamilyType field + Microsoft name: FamilyType Enumeration + EMF manual 2.1.12 + @{ +*/ +#define U_PAN_FAMILY_TEXT_DISPLAY 2 //!< Text display +#define U_PAN_FAMILY_SCRIPT 3 //!< Script +#define U_PAN_FAMILY_DECORATIVE 4 //!< Decorative +#define U_PAN_FAMILY_PICTORIAL 5 //!< Pictorial +/** @} */ + +/** \defgroup U_EMF_EMREXTFLOODFILL_iMode_Qualifiers EMF FloodFill Enumeration + For U_EMREXTFLOODFILL iMode field + Microsoft name: FloodFill Enumeration + EMF manual 2.1.13 + @{ +*/ +#define U_FLOODFILLBORDER 0x00000000 //!< Color specified must be the same as the border - brush fill stops at this color +#define U_FLOODFILLSURFACE 0x00000001 //!< Color specified must be different from the border - brush fills only this color +/** @} */ + +/** \defgroup U_EMF_DESIGNVECTOR_Signature_Qualifiers EMF Signature Enumeration + For U_DESIGNVECTOR Signature field + Microsoft name: Signature Enumeration + EMF manual 2.1.14 + @{ +*/ +#define U_ENHMETA_SIGNATURE 0x464D4520 //!< "EMF" signature also for U_EMRHEADER dSignature field. +#define U_EPS_SIGNATURE 0x46535045 //!< "FSPE" signature, indicates encapsulated postscript. +/** @} */ + +/** \defgroup U_EMF_EMRGRADIENTFILL_ulMode_Qualifiers EMF GradientFill Enumeration + For U_EMRGRADIENTFILL ulMode field + Microsoft name: GradientFill Enumeration + EMF manual 2.1.15 + @{ +*/ +#define U_GRADIENT_FILL_RECT_H 0x00000000 //!< Gradient is left to right. +#define U_GRADIENT_FILL_RECT_V 0x00000001 //!< Grident is top to bottom. +#define U_GRADIENT_FILL_TRIANGLE 0x00000002 //!< Gradient is between 3 vertices of a triangle. +/** @} */ + +/** \defgroup U_EMF_EMREXTTEXTOUT_iGraphicsMode_Qualifiers EMF GraphicsMode Enumeration + For U_EMREXTTEXTOUTA/U_EMREXTTEXTOUTW and all other iGraphicsMode fields + Microsoft name: GraphicsMode Enumeration + EMF manual 2.1.16 + @{ +*/ +#define U_GM_COMPATIBLE 1 //!< TrueType text ignores world to device transform except for Scale. Arcs ignore transform +#define U_GM_ADVANCED 2 //!< TrueType text and Arcs must conform to all of world to device transform. +#define U_GM_LAST 2 //!< Number of GraphicsMode Enumeration entries. +/** @} */ + +/** \defgroup U_EMF_LOGBRUSH_lbHatch_Qualifiers EMF HatchStyle Enumeration + For U_LOGBRUSH lbHatch field + Microsoft name: HatchStyle Enumeration + EMF manual 2.1.17 + @{ +*/ +#define U_HS_HORIZONTAL 0 //!< Horizontal. +#define U_HS_VERTICAL 1 //!< Vertical. +#define U_HS_FDIAGONAL 2 //!< Forward diagonal. +#define U_HS_BDIAGONAL 3 //!< Back diagonal. +#define U_HS_CROSS 4 //!< Cross. +#define U_HS_DIAGCROSS 5 //!< Diagonal cross. +#define U_HS_SOLIDCLR 6 //!< Solid color. +#define U_HS_DITHEREDCLR 7 //!< Dithered color. +#define U_HS_SOLIDTEXTCLR 8 //!< Solid text color. +#define U_HS_DITHEREDTEXTCLR 9 //!< Dithered text color. +#define U_HS_SOLIDBKCLR 10 //!< Solid background color. +#define U_HS_DITHEREDBKCLR 11 //!< Dithered background color. +/** @} */ + +/** \defgroup U_EMF_EMRSETICMMODE_iMode_Qualifiers EMF ICMMode Enumeration + For EMF U_EMR_SETICMMODE iMode field + Microsoft name: ICMMode Enumeration + EMF manual 2.1.18 + @{ +*/ +#define U_ICM_OFF 1 //!< Off +#define U_ICM_ON 2 //!< On +#define U_ICM_QUERY 3 //!< Query +/** @} */ + +/** \defgroup U_EMF_COLORADJUSTMENT_caIlluminantIndex_Qualifiers EMF Illuminant Enumeration + For U_COLORADJUSTMENT caIlluminantIndex field + Microsoft name: Illuminant Enumeration + EMF manual 2.1.19 + @{ +*/ +#define U_ILLUMINANT_DEVICE_DEFAULT 0 //!< Device default +#define U_ILLUMINANT_A 1 //!< A +#define U_ILLUMINANT_B 2 //!< B +#define U_ILLUMINANT_C 3 //!< C +#define U_ILLUMINANT_D50 4 //!< D50 +#define U_ILLUMINANT_D55 5 //!< D55 +#define U_ILLUMINANT_D65 6 //!< D65 +#define U_ILLUMINANT_D75 7 //!< D75 +#define U_ILLUMINANT_F2 8 //!< F2 +#define U_ILLUMINANT_MAX_INDEX ILLUMINANT_F2 //!< Max index +#define U_ILLUMINANT_TUNGSTEN ILLUMINANT_A //!< Tungsten +#define U_ILLUMINANT_DAYLIGHT ILLUMINANT_C //!< Daylight +#define U_ILLUMINANT_FLUORESCENT ILLUMINANT_F2 //!< Fluorescent +#define U_ILLUMINANT_NTSC ILLUMINANT_C //!< NTSC +/** @} */ + +/** \defgroup U_EMF_PANOSE_bLetterForm_Qualifiers EMF Letterform Enumeration + For U_PANOSE bLetterForm field + Microsoft name: Letterform Enumeration + EMF manual 2.1.20 + @{ +*/ +#define U_PAN_LETT_NORMAL_COMPACT 2 //!< Normal compact +#define U_PAN_LETT_NORMAL_WEIGHTED 3 //!< Normal weighted +#define U_PAN_LETT_NORMAL_BOXED 4 //!< Normal boxed +#define U_PAN_LETT_NORMAL_FLATTENED 5 //!< Normal flattened +#define U_PAN_LETT_NORMAL_ROUNDED 6 //!< Normal rounded +#define U_PAN_LETT_NORMAL_OFF_CENTER 7 //!< Normal off center +#define U_PAN_LETT_NORMAL_SQUARE 8 //!< Normal square +#define U_PAN_LETT_OBLIQUE_COMPACT 9 //!< Oblique compact +#define U_PAN_LETT_OBLIQUE_WEIGHTED 10 //!< Oblique weighted +#define U_PAN_LETT_OBLIQUE_BOXED 11 //!< Oblique boxed +#define U_PAN_LETT_OBLIQUE_FLATTENED 12 //!< Oblique flattened +#define U_PAN_LETT_OBLIQUE_ROUNDED 13 //!< Oblique rounded +#define U_PAN_LETT_OBLIQUE_OFF_CENTER 14 //!< Oblique off center +#define U_PAN_LETT_OBLIQUE_SQUARE 15 //!< Oblique square +/** @} */ + +/** \defgroup U_EMF_EMRSETMAPMODE_iMode_Qualifiers EMF MapMode Enumeration + For U_EMRSETMAPMODE iMode field + Microsoft name: MapMode Enumeration + EMF manual 2.1.21 + @{ +*/ +#define U_MM_TEXT 1 //!< Text +#define U_MM_LOMETRIC 2 //!< Low metric +#define U_MM_HIMETRIC 3 //!< Hig hmetric +#define U_MM_LOENGLISH 4 //!< Low English +#define U_MM_HIENGLISH 5 //!< High English +#define U_MM_TWIPS 6 //!< Twips +#define U_MM_ISOTROPIC 7 //!< Isotropic +#define U_MM_ANISOTROPIC 8 //!< Anisotropic +#define U_MM_MIN U_MM_TEXT //!< smallest enumeration +#define U_MM_MAX U_MM_ANISOTROPIC //!< largest enumeration +#define U_MM_MAX_FIXEDSCALE U_MM_TWIPS //!< alternate definition +/** @} */ + +/** \defgroup U_EMF_MF_version EMF MetafileVersion Enumeration + For U_EMR_COMMENTS_METAFILE version field + Microsoft name: MetafileVersion Enumeration + EMF manual 2.1.22 + @{ +*/ +#define U_ENHMETA_VERSION 0x00010000 //!< U_EMRHEADER nVersion field +/** @} */ + +/** \defgroup U_EMF_PANOSE_bMidline_Qualifiers EMF MidLine Enumeration + For U_PANOSE bMidline field + Microsoft name: MidLine Enumeration + EMF manual 2.1.23 + @{ +*/ +#define U_PAN_MIDLINE_STANDARD_TRIMMED 2 //!< Midline standard trimmed +#define U_PAN_MIDLINE_STANDARD_POINTED 3 //!< Midline standard pointed +#define U_PAN_MIDLINE_STANDARD_SERIFED 4 //!< Midline standard serifed +#define U_PAN_MIDLINE_HIGH_TRIMMED 5 //!< Midline high trimmed +#define U_PAN_MIDLINE_HIGH_POINTED 6 //!< Midline high pointed +#define U_PAN_MIDLINE_HIGH_SERIFED 7 //!< Midline high serifed +#define U_PAN_MIDLINE_CONSTANT_TRIMMED 8 //!< Midline constant trimmed +#define U_PAN_MIDLINE_CONSTANT_POINTED 9 //!< Midline constant pointed +#define U_PAN_MIDLINE_CONSTANT_SERIFED 10 //!< Midline constant serifed +#define U_PAN_MIDLINE_LOW_TRIMMED 11 //!< Midline low trimmed +#define U_PAN_MIDLINE_LOW_POINTED 12 //!< Midline low pointed +#define U_PAN_MIDLINE_LOW_SERIFED 13 //!< Midline low serifed +/** @} */ + +/** \defgroup U_EMF_EMRMODIFYWORLDTRANSFORM_iMode_Qualifiers EMF ModifyWorldTransformMode Enumeration + For U_EMRMODIFYWORLDTRANSFORM iMode + Microsoft name: ModifyWorldTransformMode Enumeration + EMF manual 2.1.24 + @{ +*/ +#define U_MWT_IDENTITY 1 //!< Transform is identity. +#define U_MWT_LEFTMULTIPLY 2 //!< Left multiply transform. +#define U_MWT_RIGHTMULTIPLY 3 //!< Right multiply transform. +#define U_MWT_MIN U_MWT_IDENTITY //!< smallest enumeration. +#define U_MWT_MAX U_MWT_RIGHTMULTIPLY //!< largest enumeration. +/** @} */ + +/** \defgroup U_EMF_LOGPEN_elpPenStyle_Qualifiers EMF PenStyle Enumeration + For U_LOGPEN lopnStyle and U_EXTLOGPEN elpPenStyle fields + Microsoft name: PenStyle Enumeration + EMF manual 2.1.25 + @{ +*/ +#define U_PS_SOLID 0x00000000 //!< Solid line. +#define U_PS_DASH 0x00000001 //!< Dashed line. This only works when NO other U_PS is set. Line width is minimum no matter what pen is set to. +#define U_PS_DOT 0x00000002 //!< Dotted line. This only works when NO other U_PS is set. Line width is minimum no matter what pen is set to. +#define U_PS_DASHDOT 0x00000003 //!< Dash-Dot line. This only works when NO other U_PS is set. Line width is minimum no matter what pen is set to. +#define U_PS_DASHDOTDOT 0x00000004 //!< Dash-Dot-Dot line. This only works when NO other U_PS is set. Line width is minimum no matter what pen is set to. +#define U_PS_NULL 0x00000005 //!< Invisible line. +#define U_PS_INSIDEFRAME 0x00000006 //!< Draw line around drawing, then shrink drawing to fit within line taking its width into account. +#define U_PS_USERSTYLE 0x00000007 //!< User defined. +#define U_PS_ALTERNATE 0x00000008 //!< Every other pixel is drawn. +#define U_PS_STYLE_MASK 0x0000000f //!< Mask to select just the preceding line type fields. + +#define U_PS_ENDCAP_ROUND 0x00000000 //!< Round end cap. Only with U_PS_GEOMETRIC +#define U_PS_ENDCAP_SQUARE 0x00000100 //!< Square end cap. Only with U_PS_GEOMETRIC +#define U_PS_ENDCAP_FLAT 0x00000200 //!< Flat end cap. Only with U_PS_GEOMETRIC +#define U_PS_ENDCAP_MASK 0x00000f00 //!< Mask to select just the preceding ENDCAP fields. + +#define U_PS_JOIN_ROUND 0x00000000 //!< Rounded join. Only with U_PS_GEOMETRIC +#define U_PS_JOIN_BEVEL 0x00001000 //!< Beveled join. Only with U_PS_GEOMETRIC +#define U_PS_JOIN_MITER 0x00002000 //!< Mitered join. Only with U_PS_GEOMETRIC +#define U_PS_JOIN_MASK 0x0000f000 //!< Mask to select just the preceding JOIN fields. + +#define U_PS_COSMETIC 0x00000000 //!< width may only be 1 pixel. (If set higher it is still drawn as 1). +#define U_PS_GEOMETRIC 0x00010000 //!< width may be >1 pixel, but style may only be U_PS_SOLID or U_PS_NULL. +#define U_PS_TYPE_MASK 0x000f0000 //!< Mask to select just the preceding TYPE fields. +/** @} */ +/** \defgroup U_EMF_EMRPOLY_iMode_Qualifiers EMF Point Enumeration + For U_EMRPOLYDRAW and U_EMRPOLAYDRAW16 abTypes fields. + Microsoft name: Point Enumeration + EMF manual 2.1.26 + @{ +*/ +#define U_PT_CLOSEFIGURE 0x0001 //!< Close figure +#define U_PT_LINETO 0x0002 //!< Line to +#define U_PT_BEZIERTO 0x0004 //!< Bezier to +#define U_PT_MOVETO 0x0006 //!< Move to +/** @} */ + +/** \defgroup U_EMF_EMRSETPOLYFILLMODE_iMode_Qualifiers EMF PolygonFillMode Enumeration + For U_EMRSETPOLYFILLMODE iMode field + Microsoft name: PolygonFillMode Enumeration + EMF manual 2.1.27 + @{ +*/ +#define U_ALTERNATE 1 //!< Alternate +#define U_WINDING 2 //!< Winding +#define U_POLYFILL_LAST 2 //!< Polyfill last +/** @} */ + +/** \defgroup U_EMF_PANOSE_bProportion_Qualifiers EMF Proportion Enumeration + For U_PANOSE bProportion field + Microsoft name: Proportion Enumeration + EMF manual 2.1.28 + @{ +*/ +#define U_PAN_PROP_OLD_STYLE 2 //!< Old style +#define U_PAN_PROP_MODERN 3 //!< Modern +#define U_PAN_PROP_EVEN_WIDTH 4 //!< Even width +#define U_PAN_PROP_EXPANDED 5 //!< Expanded +#define U_PAN_PROP_CONDENSED 6 //!< Condensed +#define U_PAN_PROP_VERY_EXPANDED 7 //!< Very expanded +#define U_PAN_PROP_VERY_CONDENSED 8 //!< Very condensed +#define U_PAN_PROP_MONOSPACED 9 //!< Monospaced +/** @} */ + +/** \defgroup U_EMF_EMRSELECTCLIP_iMode_Qualifiers EMF RegionMode Enumeration + For U_EMRSELECTCLIPPATH and U_EMREXTSELECTCLIPRGN iMode field + Microsoft name: RegionMode Enumeration + EMF manual 2.1.29 + @{ +*/ +#define U_RGN_NONE 0 //!< not part of EMF standard, may be used by others +#define U_RGN_AND 1 //!< Region becomes intersection of existing region and new region. +#define U_RGN_OR 2 //!< Region becomes union of existing region and new region. +#define U_RGN_XOR 3 //!< Region becomes XOR of existing and new regions. +#define U_RGN_DIFF 4 //!< Region becomes part of existing region not in new region. +#define U_RGN_COPY 5 //!< Region becomes new region. +#define U_RGN_MIN U_RGN_AND //!< smallest enumeration. +#define U_RGN_MAX U_RGN_COPY //!< largest enumeration. +/** @} */ + +/** \defgroup U_EMF_PANOSE_bSerifStyle_Qualifiers EMF SerifType Enumeration + For U_PANOSE bSerifStyle field + Microsoft name: SerifType Enumeration + EMF manual 2.1.30 + @{ +*/ +#define U_PAN_SERIF_COVE 2 //!< Serif cove +#define U_PAN_SERIF_OBTUSE_COVE 3 //!< Serif obtuse cove +#define U_PAN_SERIF_SQUARE_COVE 4 //!< Serif square cove +#define U_PAN_SERIF_OBTUSE_SQUARE_COVE 5 //!< Serif obtuse square cove +#define U_PAN_SERIF_SQUARE 6 //!< Serif square +#define U_PAN_SERIF_THIN 7 //!< Serif thin +#define U_PAN_SERIF_BONE 8 //!< Serif bone +#define U_PAN_SERIF_EXAGGERATED 9 //!< Serif exaggerated +#define U_PAN_SERIF_TRIANGLE 10 //!< Serif triangle +#define U_PAN_SERIF_NORMAL_SANS 11 //!< Serif normal sans +#define U_PAN_SERIF_OBTUSE_SANS 12 //!< Serif obtuse sans +#define U_PAN_SERIF_PERP_SANS 13 //!< Serif perp sans +#define U_PAN_SERIF_FLARED 14 //!< Serif flared +#define U_PAN_SERIF_ROUNDED 15 //!< Serif rounded +/** @} */ + +/** \defgroup U_EMF_EMRSELECTOBJECT_ihObject_Qualifiers EMF StockObject Enumeration + For U_EMRSELECTOBJECT ihObject field. + Microsoft name: StockObject Enumeration + EMF manual 2.1.31 + @{ +*/ +#define U_STOCK_OBJECT 0x80000000 //!< Stock object +#define U_WHITE_BRUSH 0x80000000 //!< White brush +#define U_LTGRAY_BRUSH 0x80000001 //!< Ltgray brush +#define U_GRAY_BRUSH 0x80000002 //!< Gray brush +#define U_DKGRAY_BRUSH 0x80000003 //!< Dkgray brush +#define U_BLACK_BRUSH 0x80000004 //!< Black brush +#define U_NULL_BRUSH 0x80000005 //!< Null brush +#define U_HOLLOW_BRUSH 0x80000005 //!< Hollow brush +#define U_WHITE_PEN 0x80000006 //!< White pen +#define U_BLACK_PEN 0x80000007 //!< Black pen +#define U_NULL_PEN 0x80000008 //!< Null pen +#define U_OEM_FIXED_FONT 0x8000000A //!< Oem fixed font +#define U_ANSI_FIXED_FONT 0x8000000B //!< Ansi fixed font +#define U_ANSI_VAR_FONT 0x8000000C //!< Ansi var font +#define U_SYSTEM_FONT 0x8000000D //!< System font +#define U_DEVICE_DEFAULT_FONT 0x8000000E //!< Device default font +#define U_DEFAULT_PALETTE 0x8000000F //!< Default palette +#define U_SYSTEM_FIXED_FONT 0x80000010 //!< System fixed font +#define U_DEFAULT_GUI_FONT 0x80000011 //!< Default GUI font +#define U_STOCK_LAST 0x80000011 //!< Stock last +/** @} */ + +/** \defgroup U_EMF_EMRSETSTRETCHBLTMODE_iMode_Qualifiers EMF StretchMode Enumeration + For EMF U_EMRSETSTRETCHBLTMODE iMode field + Microsoft name: StretchMode Enumeration + EMF manual 2.1.32 and footnote 52 on page 297 + @{ +*/ +#define U_BLACKONWHITE 1 //!< AND the destination and source pixels. +#define U_WHITEONBLACK 2 //!< OR the destination and source pixels. +#define U_COLORONCOLOR 3 //!< Replace the destination pixels with the source pixels. +#define U_HALFTONE 4 //!< Replace a block of destination pixels with a half-tone representation of the source pixel. +#define U_MAXSTRETCHBLTMODE 4 //!< largest enumeration. +#define U_STRETCH_ANDSCANS 1 //!< AND the destination and source pixels. +#define U_STRETCH_ORSCANS 2 //!< OR the destination and source pixels. +#define U_STRETCH_DELETESCANS 3 //!< Replace the destination pixels with the source pixels. +#define U_STRETCH_HALFTONE 4 //!< Replace a block of destination pixels with a half-tone representation of the source pixel. +/** @} */ + +/** \defgroup U_EMF_PANOSE_bStrokeVariation_Qualifiers EMF StrokeVariation Enumeration + For U_PANOSE bStrokeVariation field + Microsoft name: StrokeVariation Enumeration + EMF manual 2.1.33 + @{ +*/ +#define U_PAN_STROKE_GRADUAL_DIAG 2 //!< Gradual diagonal. +#define U_PAN_STROKE_GRADUAL_TRAN 3 //!< Gradual transitional. +#define U_PAN_STROKE_GRADUAL_VERT 4 //!< Gradual vertical. +#define U_PAN_STROKE_GRADUAL_HORZ 5 //!< Gradual horizontal. +#define U_PAN_STROKE_RAPID_VERT 6 //!< Rapid vertical. +#define U_PAN_STROKE_RAPID_HORZ 7 //!< Rapid horizontal. +#define U_PAN_STROKE_INSTANT_VERT 8 //!< Instant vertical. +/** @} */ + +/** \defgroup U_EMF_PANOSE_bWeight_Qualifiers EMF Weight Enumeration + For U_PANOSE bWeight field + EMF manual 2.1.34 + @{ +*/ +#define U_PAN_WEIGHT_VERY_LIGHT 2 //!< Very light +#define U_PAN_WEIGHT_LIGHT 3 //!< Light +#define U_PAN_WEIGHT_THIN 4 //!< Thin +#define U_PAN_WEIGHT_BOOK 5 //!< Book +#define U_PAN_WEIGHT_MEDIUM 6 //!< Medium +#define U_PAN_WEIGHT_DEMI 7 //!< Demi +#define U_PAN_WEIGHT_BOLD 8 //!< Bold +#define U_PAN_WEIGHT_HEAVY 9 //!< Heavy +#define U_PAN_WEIGHT_BLACK 10 //!< Black +#define U_PAN_WEIGHT_NORD 11 //!< Nord +/** @} */ + +/** \defgroup U_EMF_PANOSE_bXHeight_Qualifiers EMF XHeight Enumeration + For U_PANOSE bXHeight field + EMF manual 2.1.35 + @{ +*/ +#define U_PAN_XHEIGHT_CONSTANT_SMALL 2 //!< Constant small +#define U_PAN_XHEIGHT_CONSTANT_STANDARD 3 //!< Constant standard +#define U_PAN_XHEIGHT_CONSTANT_LARGE 4 //!< Constant large +#define U_PAN_XHEIGHT_DUCKING_SMALL 5 //!< Ducking small +#define U_PAN_XHEIGHT_DUCKING_STANDARD 6 //!< Ducking standard +#define U_PAN_XHEIGHT_DUCKING_LARGE 7 //!< Ducking large +/** @} */ + +/** \defgroup U_EMF_LOGFONT_lfWeight_Qualifiers EMF LF_Weight Enumeration + For U_LOGFONT lfWeight field + EMF manual 2.2.13, footnote 61 (on page 297) + @{ +*/ +#define U_FW_DONTCARE 0 //!< Don't care +#define U_FW_THIN 100 //!< Thin +#define U_FW_EXTRALIGHT 200 //!< Extra light +#define U_FW_ULTRALIGHT 200 //!< Ultra light +#define U_FW_LIGHT 300 //!< Light +#define U_FW_NORMAL 400 //!< Normal +#define U_FW_REGULAR 400 //!< Regular +#define U_FW_MEDIUM 500 //!< Medium +#define U_FW_SEMIBOLD 600 //!< Semibold +#define U_FW_DEMIBOLD 600 //!< Demibold +#define U_FW_BOLD 700 //!< Bold +#define U_FW_EXTRABOLD 800 //!< Extrabold +#define U_FW_ULTRABOLD 800 //!< Ultrabold +#define U_FW_HEAVY 900 //!< Heavy +#define U_FW_BLACK 900 //!< Black +/** @} */ + +/** \defgroup U_EMF_LOGFONT_lfItalic_Qualifiers EMF LF_Italic Enumeration + For U_LOGFONT lfItalic field + Microsoft name: LF_Italic Enumeration + EMF manual 2.2.13 + @{ +*/ +#define U_FW_NOITALIC 0 //!< Do not use italics. +#define U_FW_ITALIC 1 //!< Use italics. +/** @} */ + +/** \defgroup U_EMF_LOGFONT_lfunderline_Qualifiers EMF LF_Underline Enumeration + For U_LOGFONT lfunderline field + Microsoft name: LF_Underline Enumeration + EMF manual 2.2.13 + @{ +*/ +#define U_FW_NOUNDERLINE 0 //!< Do not use underline. +#define U_FW_UNDERLINE 1 //!< Use underline. +/** @} */ + +/** \defgroup U_EMF_LOGFONT_lfStrikeOut_Qualifiers EMF LF_StrikeOut Enumeration + For U_LOGFONT lfStrikeOut field + EMF manual 2.2.13 + @{ +*/ +#define U_FW_NOSTRIKEOUT 0 //!< Do not use strikeout. +#define U_FW_STRIKEOUT 1 //!< Use strikeout. +/** @} */ + +/** \defgroup U_EMF_LOGFONT_lfCharSet_Qualifiers EMF LF_CharSet Enumeration + For U_LOGFONT lfCharSet field + EMF manual 2.2.13 & WMF manual 2.1.15 + @{ +*/ +#define U_ANSI_CHARSET (uint8_t)0 //!< CP1252, ansi-0, iso8859-{1,15} +#define U_DEFAULT_CHARSET (uint8_t)1 //!< Default character set. +#define U_SYMBOL_CHARSET (uint8_t)2 //!< Symbol character set. +#define U_SHIFTJIS_CHARSET (uint8_t)128 //!< CP932 +#define U_HANGEUL_CHARSET (uint8_t)129 //!< CP949, ksc5601.1987-0 +#define U_HANGUL_CHARSET U_HANGEUL_CHARSET //!< CP949, ksc5601.1987-0 +#define U_GB2312_CHARSET (uint8_t)134 //!< CP936, gb2312.1980-0 +#define U_CHINESEBIG5_CHARSET (uint8_t)136 //!< CP950, big5.et-0 +#define U_GREEK_CHARSET (uint8_t)161 //!< CP1253 +#define U_TURKISH_CHARSET (uint8_t)162 //!< CP1254, -iso8859-9 +#define U_HEBREW_CHARSET (uint8_t)177 //!< CP1255, -iso8859-8 +#define U_ARABIC_CHARSET (uint8_t)178 //!< CP1256, -iso8859-6 +#define U_BALTIC_CHARSET (uint8_t)186 //!< CP1257, -iso8859-13 +#define U_RUSSIAN_CHARSET (uint8_t)204 //!< CP1251, -iso8859-5 +#define U_EE_CHARSET (uint8_t)238 //!< CP1250, -iso8859-2 +#define U_EASTEUROPE_CHARSET U_EE_CHARSET //!< CP1250, -iso8859-2 +#define U_THAI_CHARSET (uint8_t)222 //!< CP874, iso8859-11, tis620 +#define U_JOHAB_CHARSET (uint8_t)130 //!< korean (johab) CP1361 +#define U_MAC_CHARSET (uint8_t)77 //!< Macintosh character set. +#define U_OEM_CHARSET (uint8_t)255 //!< OEM character set. +#define U_VISCII_CHARSET (uint8_t)240 //!< viscii1.1-1 +#define U_TCVN_CHARSET (uint8_t)241 //!< tcvn-0 +#define U_KOI8_CHARSET (uint8_t)242 //!< koi8-{r,u,ru} +#define U_ISO3_CHARSET (uint8_t)243 //!< iso8859-3 +#define U_ISO4_CHARSET (uint8_t)244 //!< iso8859-4 +#define U_ISO10_CHARSET (uint8_t)245 //!< iso8859-10 +#define U_CELTIC_CHARSET (uint8_t)246 //!< iso8859-14 +/** @} */ + +/** \defgroup U_EMF_LOGFONT_lfOutPrecision_Qualifiers EMF LF_OutPrecision Enumeration + For U_LOGFONT lfOutPrecision field + EMF manual 2.2.13 & WMF manual 2.1.1.21 + @{ +*/ +#define U_OUT_DEFAULT_PRECIS 0 //!< Default precision +#define U_OUT_STRING_PRECIS 1 //!< String precision +#define U_OUT_CHARACTER_PRECIS 2 //!< Character precision +#define U_OUT_STROKE_PRECIS 3 //!< Stroke precision +#define U_OUT_TT_PRECIS 4 //!< Tt precision +#define U_OUT_DEVICE_PRECIS 5 //!< Device precision +#define U_OUT_RASTER_PRECIS 6 //!< Raster precision +#define U_OUT_TT_ONLY_PRECIS 7 //!< Tt_only precision +#define U_OUT_OUTLINE_PRECIS 8 //!< Outline precision +/** @} */ + +/** \defgroup U_EMF_LOGFONT_lfClipPrecision_Qualifiers EMF LF_ClipPrecision Enumeration + For U_LOGFONT lfClipPrecision field + EMF manual 2.2.13 & WMF manual 2.1.2.1 + @{ +*/ +#define U_CLIP_DEFAULT_PRECIS 0x00 //!< Use default clipping precision. +#define U_CLIP_CHARACTER_PRECIS 0x01 //!< Use character clipping precision +#define U_CLIP_STROKE_PRECIS 0x02 //!< (Source documentation is vague about what this means.) +#define U_CLIP_MASK 0x0F //!< MASK for bits in preceding. +#define U_CLIP_LH_ANGLES 0x10 //!< Set: font rotation by coordinate system, Clear: device fonts (only) rotate counterclockwise. +#define U_CLIP_TT_ALWAYS 0x20 //!< Reserved. +#define U_CLIP_EMBEDDED 0x80 //!< Font embedding is required. (Method for doing so is not documented in EMF or WMF.) +/** @} */ + +/** \defgroup U_EMF_LOGFONT_lfQuality_Qualifiers EMF LF_Quality Enumeration + For For U_LOGFONT lfQuality field + EMF manual 2.2.13 & WMF manual 2.1.1.10 + @{ +*/ +#define U_DEFAULT_QUALITY 0 //!< Default quality +#define U_DRAFT_QUALITY 1 //!< Draft quality +#define U_PROOF_QUALITY 2 //!< Proof quality +#define U_NONANTIALIASED_QUALITY 3 //!< Nonantialiased quality +#define U_ANTIALIASED_QUALITY 4 //!< Antialiased quality +/** @} */ + +/** \defgroup U_EMF_LOGFONT_lfPitchAndFamily_Qualifiers EMF LF_PitchAndFamily Enumeration + For U_LOGFONT lfPitchAndFamily field + EMF manual 2.2.13 & WMF manual 2.2.2.14 + @{ +*/ +#define U_DEFAULT_PITCH 0x00 //!< Default pitch +#define U_FIXED_PITCH 0x01 //!< Fixed pitch +#define U_VARIABLE_PITCH 0x02 //!< Variable pitch +#define U_MONO_FONT 0x08 //!< Mono font +#define U_FF_DONTCARE 0x00 //!< Font family don't care +#define U_FF_ROMAN 0x10 //!< Font family Roman +#define U_FF_SWISS 0x20 //!< Font family Swiss +#define U_FF_MODERN 0x30 //!< Font family Modern +#define U_FF_SCRIPT 0x40 //!< Font family Script +#define U_FF_DECORATIVE 0x50 //!< Font family Decorative +/** @} */ + +/** \defgroup U_EMF_LOGBRUSH_lbStyle_Qualifiers EMF LB_Style Enumeration + For U_LOGBRUSH lbStyle field + EMF manual 2.2.20 + @{ +*/ +#define U_BS_SOLID 0 //!< Solid brush. +#define U_BS_NULL 1 //!< Null brush. +#define U_BS_HOLLOW 1 //!< Hollow brush. +#define U_BS_HATCHED 2 //!< Hatched brush. +#define U_BS_PATTERN 3 //!< Pattern brush. +#define U_BS_INDEXED 4 //!< Indexed brush. +#define U_BS_DIBPATTERN 5 //!< Dibpattern brush. +#define U_BS_DIBPATTERNPT 6 //!< Dibpatternpt brush. +#define U_BS_PATTERN8X8 7 //!< Pattern 8x8 brush. +#define U_BS_DIBPATTERN8X8 8 //!< Dibpattern 8x8 brush. +#define U_BS_MONOPATTERN 9 //!< Monopattern brush. +/** @} */ + +/** \defgroup U_EMF_PANOSE_index EMF PanoseIndex Enumeration + Fositions of each field in U_PANOSE structure. + Microsoft name: (none) + EMF manual 2.2.21 + @{ +*/ +#define U_PAN_FAMILYTYPE_INDEX 0 //!< Familytype index +#define U_PAN_SERIFSTYLE_INDEX 1 //!< Serifstyle index +#define U_PAN_WEIGHT_INDEX 2 //!< Weight index +#define U_PAN_PROPORTION_INDEX 3 //!< Proportion index +#define U_PAN_CONTRAST_INDEX 4 //!< Contrast index +#define U_PAN_STROKEVARIATION_INDEX 5 //!< Strokevariation index +#define U_PAN_ARMSTYLE_INDEX 6 //!< Armstyle index +#define U_PAN_LETTERFORM_INDEX 7 //!< Letterform index +#define U_PAN_MIDLINE_INDEX 8 //!< Midline index +#define U_PAN_XHEIGHT_INDEX 9 //!< Xheight index +#define U_PAN_COUNT 10 //!< Count +/** @} */ + + +/** \defgroup U_EMF_PIXELFORMATDESCRIPTOR_iLayerType_Qualifiers EMF PFD_iLayerType Enumeration + For U_PIXELFORMATDESCRIPTOR iLayerType field + Microsoft name: (none) + EMF manual 2.2.22 + @{ +*/ +#define U_PFD_MAIN_PLANE 0 //!< Main plane +#define U_PFD_OVERLAY_PLANE 1 //!< Overlay plane +#define U_PFD_UNDERLAY_PLANE (-1) //!< Underlay plane +/** @} */ + +/** \defgroup U_EMF_PIXELFORMATDESCRIPTOR_iPixelType_Qualifiers EMF PFD_iPixelType Enumeration + For U_PIXELFORMATDESCRIPTOR iPixelType field + Microsoft name: (none) + EMF manual 2.2.22 + @{ +*/ +#define U_PFD_TYPE_RGBA 0 //!< Pixel contains an RGBA value. +#define U_PFD_TYPE_COLORINDEX 1 //!< Pixel contains an index into the color table. +/** @} */ + +/** \defgroup U_EMF_PIXELFORMATDESCRIPTOR_dwFlags_Qualifiers EMF PFD_dwFlags Enumeration + For U_PIXELFORMATDESCRIPTOR dwFlags field + EMF manual 2.2.22 + @{ +*/ +#define U_PFD_DOUBLEBUFFER 0x00000001 //!< Doublebuffer +#define U_PFD_STEREO 0x00000002 //!< Stereo +#define U_PFD_DRAW_TO_WINDOW 0x00000004 //!< Draw to window +#define U_PFD_DRAW_TO_BITMAP 0x00000008 //!< Draw to bitmap +#define U_PFD_SUPPORT_GDI 0x00000010 //!< Support gdi +#define U_PFD_SUPPORT_OPENGL 0x00000020 //!< Support opengl +#define U_PFD_GENERIC_FORMAT 0x00000040 //!< Generic format +#define U_PFD_NEED_PALETTE 0x00000080 //!< Need palette +#define U_PFD_NEED_SYSTEM_PALETTE 0x00000100 //!< Need system palette +#define U_PFD_SWAP_EXCHANGE 0x00000200 //!< Swap exchange +#define U_PFD_SWAP_COPY 0x00000400 //!< Swap copy +#define U_PFD_SWAP_LAYER_BUFFERS 0x00000800 //!< Swap layer buffers +#define U_PFD_GENERIC_ACCELERATED 0x00001000 //!< Generic accelerated +/** @} */ + +/** \defgroup U_EMF_EMRCOMMENT_TYPES EMF Comment record types + For U_EMRCOMMENT_* cIdent fields + EMF manual 2.3.3 + @{ +*/ +#define U_EMR_COMMENT_PUBLIC 0x43494447 //!< Public comment. +#define U_EMR_COMMENT_SPOOL 0x00000000 //!< Spool comment. +#define U_EMR_COMMENT_EMFPLUSRECORD 0x2B464D45 //!< EMF+ record comment. +/** @} */ + +/** \defgroup U_EMF_EMRSETLAYOUT_iMode_Qualifiers EMF Mirroring Enumeration + For U_EMRSETLAYOUT iMode field + EMF manual 2.3.11.17 + @{ +*/ +#define U_LAYOUT_LTR 0x00000000 //!< Left to right lsyout. +#define U_LAYOUT_RTL 0x00000001 //!< Right to left layout. +#define U_LAYOUT_BITMAPORIENTATIONPRESERVED 0x00000008 //!< Do not flip bitmaps if layout is right to left. +/** @} */ + + +/** \defgroup U_EMF_BLEND_Op_Qualifiers EMF Blend Enumeration + For U_BLEND Op field + @{ +*/ +#define U_AC_SRC_GLOBAL 0 //!< Global +#define U_AC_SRC_CONST 0 //!< Const +#define U_AC_SRC_ALPHA 1 //!< Alpha +/** @} */ + + +// *************************************************************************** +// Macros + +/** \defgroup U_EMF_Common_macros EMF Common Macros + @{ +*/ +// Note, many of these were originally defined using C99 (type){val,val,val} format, but that turned out to +// have incompatibilities with C++, so use functions as the basis to avoid this. + +// Set/Get for U_RGBQUAD Colors, which are stored in byte order: {B,G,R,A}. +// These are used in EMF structures and the byte order must be the same in memory or on disk. +#define U_BGR(r,g,b) rgbquad_set(r, g, b, 0) //!< Set any BGR color with an {r,g,b} triplet +#define U_BGRA(r,g,b,a) rgbquad_set(r, g, b, a) //!< Set any BGRA color with an {r,g,b,a} quad +#define U_WHITE U_BGR(255,255,255) //!< Set BGR white. +#define U_BLACK U_BGR(0,0,0) //!< Set BGR black. +#define U_BGRAGetR(rgb) (rgb.Red ) //!< Color BGR Red. +#define U_BGRAGetG(rgb) (rgb.Green ) //!< Color BGR Green. +#define U_BGRAGetB(rgb) (rgb.Blue ) //!< Color BGR Blue. +#define U_BGRAGetA(rgb) (rgb.Reserved) //!< Color BGRA A/reserved + + +// Set/Get for U_COLORREF Color, which are stored in byte order:: {R,G,B,A}. +// These are used in EMF structures and the byte order must be the same in memory or on disk. +// These MAY be used in PNG and other libraries if these enforce byte order in memory, otherwise +// U_swap4 may need to also be employed. +// + +#define colorref_set colorref3_set //!< Most frequent usage is 3 colors, so set the unqualified one to that +#define U_RGB(r,g,b) colorref3_set(r, g, b) //!< Set any RGB color with an {r,g,b} triplet +#define U_RGBA(r,g,b,a) colorref4_set(r, g, b, a) //!< Set any RGBA color with an {r,g,b,a} quad +#define U_RGBAGetR(rgb) (rgb.Red ) //!< Color RGB Red. +#define U_RGBAGetG(rgb) (rgb.Green ) //!< Color RGB Green +#define U_RGBAGetB(rgb) (rgb.Blue ) //!< Color RGB Blue +#define U_RGBAGetA(rgb) (rgb.Reserved) //!< Color RGBA A/reserved + +// color type conversions +#define U_RGB2BGR(rgb) U_BGR(U_RGBAGetR(rgb),U_RGBAGetG(rgb),U_RGBAGetB(rgb)) //!< Set any BGR color from an RGB color +#define U_BGR2RGB(rgb) U_RGB(U_BGRAGetR(rgb),U_BGRAGetG(rgb),U_BGRAGetB(rgb)) //!< Set any RGB color from an BGR color +#define U_RGBA2BGRA(rgb) U_BGRA(U_RGBAGetR(rgb),U_RGBAGetG(rgb),U_RGBAGetB(rgb),U_RGBAGetA(rgb)} //!< Set any BGRA color from an RGBA color +#define U_BGRA2RGBA(rgb) U_RGBA(U_BGRAGetR(rgb),U_BGRAGetG(rgb),U_BGRAGetB(rgb),U_BGRAGetA(rgb)} //!< Set any RGBA color from an BGRA color + +// Color CMYK Get/Set Macros +#define U_CMYK(c,m,y,k)\ + ((COLOREF)((((uint8_t)(k)|((uint16_t)((uint8_t)(y))<<8))|(((uint32_t)(uint8_t)(m))<<16))|(((uint32_t)(uint8_t)(c))<<24))) \ + //!< Color CMYK Set Macro. +#define U_GetKValue(cmyk) ((uint8_t) (cmyk) ) //!< Color CMYK Get K Macro. +#define U_GetYValue(cmyk) ((uint8_t) ((cymk) >> 8)) //!< Color CMYK Get Y Macro. +#define U_GetMValue(cmyk) ((uint8_t) ((cymk) >> 16)) //!< Color CMYK Get M Macro. +#define U_GetCValue(cmyk) ((uint8_t) ((cymk) >> 24)) //!< Color CMYK Get C Macro. + +// Other macros +#define U_Gamma(A) (A < U_RGB_GAMMA_MIN ? U_RGB_GAMMA_MIN : (A > U_RGB_GAMMA_MAX ? U_RGB_GAMMA_MAX: A)) \ + //!< Gamma set Macro (enforce range). +#define U_PM(A,B) ((A)<-(B)?-(B):((A)>(B)?(B):(A))) //!< Plus/Minus Range Macro (B must be postitive!). +#define U_MNMX(A,B,C) ((A)<(B)?(B):((A)>(C)?(C):(A))) //!< Min/Max Range Macro (B <= A <= C). +#define U_MIN(A,B) ((A)>(B)?(B):(A)) //!< Minimum of A,B +#define U_MAX(A,B) ((A)>(B)?(A):(B)) //!< Maximum of A,B + +// basic EMR macros. +#define U_EMRTYPE(A) (((PU_EMR)A)->iType) //!< Get iType from U_EMR* record +#define U_EMRSIZE(A) (((PU_EMR)A)->nSize) //!< Get nSize from U_EMR* record + +// Utility macros +#define UP4(A) (4 * ((A + 3 ) / 4)) //!< Round up to nearest multiple of 4 + +/** @} */ + +/** Any generic pair of floats. + + Microsoft name: (none) +*/ +typedef struct { + float x; //!< X value + float y; //!< Y value +} U_PAIRF, + *PU_PAIRF; //!< Any generic pair of floats. Microsoft name: (none) + + +/* ************************************************************ + EMF structures OTHER than those corresponding to complete U_EMR_* records + ************************************************************ */ + +/** + \brief For U_POINT28_4 x and y fields. + + EMF manual 2.2.1, Microsoft name: BitFIX28_4 Object. +*/ +typedef struct { + signed IntValue :28; //!< Signed integral bit field + unsigned FracValue :4; //!< Unsigned integral bit field +} U_BITFIX28_4, + *PU_BITFIX28_4; //!< EMF manual 2.2.1 + +/** + \brief For U_EMRSETOLORADJUSTMENT ColorAdjustment field + + EMF manual 2.2.2, Microsoft name: ColorAdjustment Object + + Note, range constants are: RGB_GAMMA_[MIN|MAX],REFERENCE_[WHITE|BLACK]_[MIN|MAX],COLOR_ADJ_[MIN|MAX] +*/ +typedef struct { + uint16_t caSize; //!< Size of this structure in bytes + uint16_t caFlags; //!< ColorAdjustment Enumeration + uint16_t caIlluminantIndex; //!< Illuminant Enumeration + uint16_t caRedGamma; //!< Red Gamma correction (range:2500:65000, 10000 is no correction) + uint16_t caGreenGamma; //!< Green Gamma correction (range:2500:65000, 10000 is no correction) + uint16_t caBlueGamma; //!< Blue Gamma correction (range:2500:65000, 10000 is no correction) + uint16_t caReferenceBlack; //!< Values less than this are black (range:0:4000) + uint16_t caReferenceWhite; //!< Values more than this are white (range:6000:10000) + int16_t caContrast; //!< Contrast adjustment (range:-100:100, 0 is no correction) + int16_t caBrightness; //!< Brightness adjustment (range:-100:100, 0 is no correction) + int16_t caColorfulness; //!< Colorfulness adjustment (range:-100:100, 0 is no correction) + int16_t caRedGreenTint; //!< Tine adjustment (range:-100:100, 0 is no correction) +} U_COLORADJUSTMENT, + *PU_COLORADJUSTMENT; //!< EMF manual 2.2.2 + +/** EMF manual 2.2.3 + \brief For ? (not implemented yet) + + Microsoft name: DesignVector Object +*/ +typedef struct { + uint32_t Signature; //!< Must be 0x08007664 (AKA: DV_SGNTR) + U_NUM_FNTAXES NumAxes; //!< Number of elements in Values, 0-16 + U_FNTAXES Values[1]; //!< Optional. Array of font axes for opentype font +} U_DESIGNVECTOR, + *PU_DESIGNVECTOR; //!< EMF manual 2.2.3 +#define U_SIZE_DESIGNVECTOR (sizeof(uint32_t) + sizeof(U_NUM_FNTAXES)) + +/** + \brief For U_EMR_COMMENT_MULTIFORMATS record, where an array of these is used + + EMF manual 2.2.4, Microsoft name: EmrFormat Object +*/ +typedef struct { + uint32_t signature; //!< FormatSignature Enumeration + uint32_t nVersion; //!< Must be 1 if signature is EPS, else ignored + U_CBDATA cbData; //!< Data size in bytes + U_OFFDATA offData; //!< Offset in bytes to the Data from the start of the RECORD +} U_EMRFORMAT, + *PU_EMRFORMAT; //!< EMF manual 2.2.4 + +/** + + \brief For U_EMR[POLY]EXTTEXTOUT[A|W] emrtext field + + EMF manual 2.2.5, Microsoft name: EmrText Object + + Differs from implementation in Mingw and Wine in that the core struct has a fixed size. + Optional and movable components must be handled with offsets. + Following invariant core there may/must be: + + U_RECTL rcl; (Optional, absent when fOptions & U_ETO_NO_RECT) grayed/clipping/opaque rectangle + + U_OFFDX offDx; (required) but position isn't static. Offset in bytes to the character spacing array measured + from the start of the RECORD, NOT from the start of this structure. + + The order of the next two may be reversed, they are found from their offsets. + + char string (required) String buffer holding nChars (padded to a multiple of 4 bytes in length). + + uint32_t Dx[1] (required) character spacing, array with one entry per glyph. +*/ +typedef struct { + U_POINTL ptlReference; //!< String start coordinates + U_NUM_STR nChars; //!< Number of characters in the string + U_OFFSTR offString; //!< Offset in bytes to the string from the start of the RECORD + uint32_t fOptions; //!< ExtTextOutOptions Enumeration +} U_EMRTEXT, + *PU_EMRTEXT; //!< EMF manual 2.2.5 + +/** + \brief For U_EPS_DATA Points field + + EMF manual 2.2.23, Microsoft name: Point28_4 Object, out of order, needed for 2.2.6 +*/ +typedef struct { + U_BITFIX28_4 x; //!< X coordinate + U_BITFIX28_4 y; //!< Y coordinate +} U_POINT28_4, + *PU_POINT28_4; //!< EMF manual 2.2.23 + +/** + \brief For embedding EPS in EMF via U_EMRFORMAT offData array in U_EMR_COMMENT_MULTIFORMATS + + EMF manual 2.2.6, Microsoft name: EpsData Object +*/ +typedef struct { + uint32_t sizeData; //!< Size in bytes of this object + uint32_t version; //!< Must be 1 + U_POINT28_4 Points[3]; //!< Defines parallelogram, UL, UR, LL corners, LR is derived. + U_RECTL PostScriptData; //!< Record may include optional clipping/opaque rectangle +} U_EPS_DATA, + *PU_EPS_DATA; //!< EMF manual 2.2.6 + +/** + \brief For GRADIENT_[TRIANGLE|U_RECT] + + EMF manual 2.2.26, Microsoft name: TriVertex Object, out of order, needed for 2.2.7 +*/ +typedef struct { + int32_t x; //!< X coord + int32_t y; //!< Y coord + uint16_t Red; //!< Red component + uint16_t Green; //!< Green component + uint16_t Blue; //!< Bule component + uint16_t Alpha; //!< Alpha Transparency +} U_TRIVERTEX, + *PU_TRIVERTEX; //!< EMF manual 2.2.26 + +/** + \brief For U_EMRGRADIENTFILL GradObj field + + EMF manual 2.2.7, Microsoft name: GradientRectangle Object +*/ +typedef struct { + uint32_t UpperLeft; //!< Index of UL corner in an array of U_TRIVERTEX objects + uint32_t LowerRight; //!< Index of LR corner in an array of U_TRIVERTEX objects +} U_GRADIENT4, + *PU_GRADIENT4; //!< EMF manual 2.2.7 + +/** + \brief For U_EMRGRADIENTFILL GradObj field + + EMF manual 2.2.8, Microsoft name: GradientTriangle Object + + Gradient object notes. The next two structures are used to define the shape with reference to an existing array + of points stored in an array of TriVertex objects in the U_EMRGRADIENTFILL record. The tricky part + is that these two structures are different sizes. In some implementations (MingW) the array is cast to uint32_t + and basically the cast is then ignored. For libUEMF we leave this out of the structure entirely and get to it with offsets. +*/ +typedef struct { + uint32_t Vertex1; //!< Index of Vertex1 in an array of U_TRIVERTEX objects + uint32_t Vertex2; //!< Index of Vertex2 in an array of U_TRIVERTEX objects + uint32_t Vertex3; //!< Index of Vertex3 in an array of U_TRIVERTEX objects +} U_GRADIENT3, + *PU_GRADIENT3; //!< EMF manual 2.2.8 + +//Microsoft name: Header object, EMF manual 2.2.9 defined below with record structs +//Microsoft name: HeaderExtension1 object, EMF manual 2.2.10 defined below with record structs +//Microsoft name: HeaderExtension1 object, EMF manual 2.2.11 defined below with record structs + +/** + \brief For U_EMRCREATEBRUSHINDIRECT lb field + + EMF manual 2.2.12, Microsoft name: LogBrushEx Object +*/ +typedef struct { //!< In MS documentation this is LogBrushEx Object + uint32_t lbStyle; //!< LB_Style Enumeration + U_COLORREF lbColor; //!< Brush color + uint32_t lbHatch; //!< HatchStyle Enumeration +} U_LOGBRUSH, + U_PATTERN, //!< EMF manual 2.2.12 + *PU_LOGBRUSH, //!< EMF manual 2.2.12 + *PU_PATTERN; //!< EMF manual 2.2.12 + +/** + \brief For U_LOGFONT elfLogFont field + + EMF manual 2.2.13, Microsoft name: LogFont Object +*/ +typedef struct { + int32_t lfHeight; //!< Height in Logical units + int32_t lfWidth; //!< Average Width in Logical units + int32_t lfEscapement; //!< Angle in 0.1 degrees betweem escapement vector and X axis + int32_t lfOrientation; //!< Angle in 0.1 degrees between baseline and X axis + int32_t lfWeight; //!< LF_Weight Enumeration + uint8_t lfItalic; //!< LF_Italic Enumeration + uint8_t lfUnderline; //!< LF_Underline Enumeration + uint8_t lfStrikeOut; //!< LF_StrikeOut Enumeration + uint8_t lfCharSet; //!< LF_CharSet Enumeration + uint8_t lfOutPrecision; //!< LF_OutPrecision Enumeration + uint8_t lfClipPrecision; //!< LF_ClipPrecision Enumeration + uint8_t lfQuality; //!< LF_Quality Enumeration + uint8_t lfPitchAndFamily; //!< LF_PitchAndFamily Enumeration + uint16_t lfFaceName[U_LF_FACESIZE]; //!< Name of font. If <U_LF_FACESIZE chars must be null terminated +} U_LOGFONT, + *PU_LOGFONT; //!< EMF manual 2.2.13 + +// Microsoft name: LogFontEx Object (not implemented) EMF manual 2.2.14 +// Microsoft name: LogFontExDv Object (not implemented) EMF manual 2.2.15 + +/** + \brief For U_LOGFONT_PANOSE elfPanose field + + EMF manual 2.2.21, Microsoft name: Panose Object +*/ +// out of order, needed for 2.2.16 +typedef struct { + uint8_t bFamilyType; //!< FamilyType Enumeration + uint8_t bSerifStyle; //!< SerifType Enumeration + uint8_t bWeight; //!< Weight Enumeration + uint8_t bProportion; //!< Proportion Enumeration + uint8_t bContrast; //!< Contrast Enumeration + uint8_t bStrokeVariation; //!< StrokeVariation Enumeration + uint8_t bArmStyle; //!< ArmStyle Enumeration + uint8_t bLetterform; //!< Letterform Enumeration + uint8_t bMidline; //!< Midline Enumeration + uint8_t bXHeight; //!< XHeight Enumeration +} U_PANOSE, + *PU_PANOSE; //!< EMF manual 2.2.21 + +#define U_PAN_ALL0 (U_PANOSE){0,0,0,0,0,0,0,0,0,0} //!< all U_PAN_ANY, have not seen this in an EMF file +#define U_PAN_ALL1 (U_PANOSE){1,1,1,1,1,1,1,1,1,1} //!< all U_PAN_NO_FIT, this is what createfont() would have made + +/** + \brief For U_EMREXTCREATEFONTINDIRECTW elfw field + + EMF manual 2.2.16, Microsoft name: LogFontPanose Object +*/ +typedef struct { + U_LOGFONT elfLogFont; //!< Basic font attributes + uint16_t elfFullName[U_LF_FULLFACESIZE]; //!< Font full name + uint16_t elfStyle[U_LF_FACESIZE]; //!< Font style (if <U_LF_FACESIZE characters, null terminate string) + uint32_t elfVersion; //!< Ignore + uint32_t elfStyleSize; //!< Font hinting starting at this point size, if 0, starts at Height + uint32_t elfMatch; //!< Ignore + uint32_t elfReserved; //!< Must be 0, Ignore + uint8_t elfVendorId[U_ELF_VENDOR_SIZE]; //!< Ignore + uint32_t elfCulture; //!< Must be 0, Ignore + U_PANOSE elfPanose; //!< Panose Object. If all zero, it is ignored. + uint16_t elfPadding; //!< Ignore +} U_LOGFONT_PANOSE, + *PU_LOGFONT_PANOSE; //!< EMF manual 2.2.16 + +/** + \brief For U_LOGPALETTE palPalEntry field(s) + + EMF manual 2.2.18, Microsoft name: LogPaletteEntry Object +*/ +// out of order, needed for 2.2.17 +typedef struct { + uint8_t peReserved; //!< Ignore + uint8_t peRed; //!< Palette entry Red Intensity + uint8_t peGreen; //!< Palette entry Green Intensity + uint8_t peBlue; //!< Palette entry Blue Intensity +} U_LOGPLTNTRY, + *PU_LOGPLTNTRY; //!< EMF manual 2.2.18 + +/** + \brief For U_EMRCREATEPALETTE lgpl field + + EMF manual 2.2.17, Microsoft name: LogPalette Object + +*/ +typedef struct { + uint16_t palVersion; //!< Must be 0x0300 (AKA: U_LP_VERSION) + uint16_t palNumEntries; //!< Number of U_LOGPLTNTRY objects + U_LOGPLTNTRY palPalEntry[1]; //!< PC_Entry Enumeration +} U_LOGPALETTE, + *PU_LOGPALETTE; //!< EMF manual 2.2.17 +#define U_SIZE_LOGPALETTE (2*sizeof(uint16_t)) + +// Microsoft name: LogPaletteEntry Object, EMF manual 2.2.18, defined above, before 2.2.17 + +/** + \brief For U_EMRCREATEPEN lopn field + + EMF manual 2.2.19, Microsoft name: LogPen Object +*/ +typedef struct { + uint32_t lopnStyle; //!< PenStyle Enumeration + U_POINT lopnWidth; //!< Width of pen set by X, Y is ignored + U_COLORREF lopnColor; //!< Pen color value +} U_LOGPEN, + *PU_LOGPEN; //!< EMF manual 2.2.19 + +// Microsoft name: LogPenEx Object (not implemented) EMF manual 2.2.20 +// Microsoft name: Panose Object, EMF manual 2.2.21, defined above, before 2.2.16 + +/** + \brief For U_EMRPIXELFORMAT pfd field + + EMF manual 2.2.22, Microsoft name: PixelFormatDescriptor Object +*/ +typedef struct { + uint16_t nSize; //!< Structure size in bytes + uint16_t nVersion; //!< must be 1 + uint32_t dwFlags; //!< PFD_dwFlags Enumeration + uint8_t iPixelType; //!< PFD_iPixelType Enumeration + uint8_t cColorBits; //!< RGBA: total bits per pixel + uint8_t cRedBits; //!< Red bits per pixel + uint8_t cRedShift; //!< Red shift to data bits + uint8_t cGreenBits; //!< Green bits per pixel + uint8_t cGreenShift; //!< Green shift to data bits + uint8_t cBlueBits; //!< Blue bits per pixel + uint8_t cBlueShift; //!< Blue shift to data bits + uint8_t cAlphaBits; //!< Alpha bits per pixel + uint8_t cAlphaShift; //!< Alpha shift to data bits + uint8_t cAccumBits; //!< Accumulator buffer, total bitplanes + uint8_t cAccumRedBits; //!< Red accumulator buffer bitplanes + uint8_t cAccumGreenBits; //!< Green accumulator buffer bitplanes + uint8_t cAccumBlueBits; //!< Blue accumulator buffer bitplanes + uint8_t cAccumAlphaBits; //!< Alpha accumulator buffer bitplanes + uint8_t cDepthBits; //!< Depth of Z-buffer + uint8_t cStencilBits; //!< Depth of stencil buffer + uint8_t cAuxBuffers; //!< Depth of auxilliary buffers (not supported) + uint8_t iLayerType; //!< PFD_iLayerType Enumeration, may be ignored + uint8_t bReserved; //!< Bits 0:3/4:7 are number of Overlay/Underlay planes + uint32_t dwLayerMask; //!< may be ignored + uint32_t dwVisibleMask; //!< color or index of underlay plane + uint32_t dwDamageMask; //!< may be ignored +} U_PIXELFORMATDESCRIPTOR, + *PU_PIXELFORMATDESCRIPTOR; //!< EMF manual 2.2.22 + +// Microsoft name: Point28_4 Object. EMF manual 2.2.23, defined above, before 2.2.6 + +/** + \brief For U_RGNDATA rdb field + + EMF manual 2.2.25, Microsoft name: RegionDataHeader Object (RGNDATAHEADER) +*/ +// out of order, needed for 2.2.24 +typedef struct { + uint32_t dwSize; //!< Size in bytes, must be 0x20 (AKA: U_RDH_OBJSIZE) + uint32_t iType; //!< Must be 1 (AKA: U_RDH_RECTANGLES) + U_NUM_RECTL nCount; //!< Number of rectangles in region + uint32_t nRgnSize; //!< Size in bytes of rectangle buffer + U_RECTL rclBounds; //!< Region bounds +} U_RGNDATAHEADER, + *PU_RGNDATAHEADER; //!< EMF manual 2.2.25 +#define U_SIZE_RGNDATAHEADER (sizeof(U_RGNDATAHEADER)) + +/** + \brief For U_EMRFILLRGN RgnData field(s) + + EMF manual 2.2.24, Microsoft name: RegionData Object + +*/ +typedef struct { + U_RGNDATAHEADER rdh; //!< Data description + U_RECTL Buffer[1]; //!< Array of U_RECTL elements +} U_RGNDATA, + *PU_RGNDATA; //!< EMF manual 2.2.24 +#define U_SIZE_RGNDATA U_SIZE_RGNDATAHEADER + +// Microsoft name: RegionDataHeader Object. EMF manual 2.2.25, defined above, before 2.2.24 +// Microsoft name: TriVertex Object. EMF manual 2.2.26, defined above, before 2.2.7 +// Microsoft name: UniversalFontId Object. EMF manual 2.2.27 (not implemented) + +/** + \brief For U_EMR[FILLRGN|STRETCHBLT|MASKBLT|PLGBLT] xformSrc field + + EMF manual 2.2.28, Microsoft name: Xform Object +*/ +typedef struct { + U_FLOAT eM11; //!< Matrix element M11 + U_FLOAT eM12; //!< Matrix element M12 + U_FLOAT eM21; //!< Matrix element M21 + U_FLOAT eM22; //!< Matrix element M22 + U_FLOAT eDx; //!< X offset in logical units + U_FLOAT eDy; //!< Y offset in logical units +} U_XFORM , + *PU_XFORM; //!< EMF manual 2.2.28 + +/** + \brief For U_EMREXTCREATEPEN lopn field + + EMF manual 2.2.20, Microsoft name: LogPenEx Object +*/ +typedef struct { + uint32_t elpPenStyle; //!< PenStyle Enumeration + uint32_t elpWidth; //!< Width in logical units (elpPenStyle & U_PS_GEOMETRIC) or 1 (pixel) + uint32_t elpBrushStyle; //!< LB_Style Enumeration + U_COLORREF elpColor; //!< Pen color + uint32_t elpHatch; //!< HatchStyle Enumeration + U_NUM_STYLEENTRY elpNumEntries; //!< Count of StyleEntry array + U_STYLEENTRY elpStyleEntry[1]; //!< Array of StyleEntry (For user specified dot/dash patterns) +} U_EXTLOGPEN, + *PU_EXTLOGPEN; //!< EMF manual 2.2.20 +#define U_SIZE_EXTLOGPEN (sizeof(U_EXTLOGPEN) - sizeof(U_STYLEENTRY)) // there may not be any style entries + +/** + \brief For U_EMR_* OffBmi* fields + + WMF Manual 2.2.2.9, Microsoft name: (none). + + Description of a Bitmap which in some cases is a Device Independent Bitmap (DIB) +*/ +typedef struct { + U_BITMAPINFOHEADER bmiHeader; //!< Geometry and pixel properties + U_RGBQUAD bmiColors[1]; //!< Color table. 24 bit images do not use color table values. +} U_BITMAPINFO, + *PU_BITMAPINFO; //!< WMF Manual 2.2.2.9 +#define U_SIZE_BITMAPINFO U_SIZE_BITMAPINFOHEADER + +/** + \brief U_EMRALPHABLEND Blend field + + EMF Manual 2.3.1.1, Microsoft name: BLENDFUNCTION field of EMR_ALPHABLEND record. +*/ +typedef struct { + uint8_t Operation; //!< Must be 0 + uint8_t Flags; //!< Must be 0 + uint8_t Global; //!< Alpha for whole thing if Op is U_AC_SRC_GLOBAL (AKA U_AC_SRC_GLOBAL) + uint8_t Op; //!< Blend Enumeration +} U_BLEND, + *PU_BLEND; //!< EMF Manual 2.3.1.1 +# + +/** + General form of an EMF record. + Microsoft name: ENHMETARECORD Object + For generic cast of other U_EMR_* records +*/ +typedef struct { + uint32_t iType; //!< Type of EMR record + uint32_t nSize; //!< Size of entire record in bytes (multiple of 4). + uint32_t dParm[1]; //!< Data in record +} U_ENHMETARECORD, + *PU_ENHMETARECORD; //!< General form of an EMF record. +#define U_SIZE_ENHMETARECORD (2*sizeof(uint32_t)) + +/** First two fields of all EMF records, + First two fields of all EMF+ records (1 or more within an EMF comment) + For accessing iType and nSize files in all U_EMR* records + Microsoft name: EMR Object +*/ +typedef struct { + uint32_t iType; //!< Type of EMR record + uint32_t nSize; //!< Size of entire record in bytes (multiple of 4). +} U_EMR, + *PU_EMR; //!< First two fields of all EMF records, + +/** Generic EMR record with two 32 bit values. + Microsoft name: (none) +*/ +typedef struct { + U_EMR emr; //!< U_EMR + U_PAIR pair; //!< pair of 32 bit values +} U_EMRGENERICPAIR, + *PU_EMRGENERICPAIR; //!< Generic EMR record with two 32 bit values. Microsoft name: (none) + + + + +// *********************************************************************************** +// The following have U_EMR_# records. They are ordered by their record index, not by EMF manual position. + +// records which are documented but not implemented +#define U_SIZE_EMRNOTIMPLEMENTED 2048 + +/* Index 1 */ +/** + \brief The first U_ENHMETARECORD record in the metafile. + + EMF manual 2.2.9, Microsoft name: Header object, HeaderExtension1 object, HeaderExtension2 object + + Microsoft names instead: Header, HeaderExtension1, and HeaderExtension2 objects. These are + used nowhere else, so they are combined here, along with the first two fields which were not listed in the Header. + + Note also that three fields in this file (nBytes, nRecords, nHandles) must be (re)set after the entire EMF + is constructed, since typically they are not known until then. bOpenGL may or may not be knowable when this + header is written. + + Note also that rclBounds and rclFrame are supposed to be the region bounding the drawn content within the + EMF. This is generally smaller than the size from szlDevice. However, since libUEMF does not actually draw + anything it has no way of knowing what these values are. Instead when it creates a header it sets these to + match the szl* fields. + +*/ +typedef struct { + U_EMR emr; //!< U_EMR + U_RECTL rclBounds; //!< Bounding rectangle in device units + U_RECTL rclFrame; //!< Bounding rectangle in 0.01 mm units + uint32_t dSignature; //!< FormatSignature Enumeration (must be U_ENHMETA_SIGNATURE) + uint32_t nVersion; //!< Must be U_ENHMETA_VERSION (0x00010000) + uint32_t nBytes; //!< Length in bytes of the Metafile + uint32_t nRecords; //!< Records in the Metafile + uint16_t nHandles; //!< Number of graphics objects used in the Metafile + uint16_t sReserved; //!< Must be 0 + uint32_t nDescription; //!< Characters in the Description field, 0 if no description + uint32_t offDescription; //!< Offset in bytes to optional UTF-16BE string Description field + uint32_t nPalEntries; //!< Number of Palette entries (in U_EMR_EOF record). + U_SIZEL szlDevice; //!< Reference device size in pixels + U_SIZEL szlMillimeters; //!< Reference device size in 0.01 mm + /** Fields for winver >= win95 */ + U_CBPXLFMT cbPixelFormat; //!< Size in bytes of PixelFormatDescriptor, 0 if no PFD + U_OFFPXLFMT offPixelFormat; //!< Offset in bytes to optional PixelFormatDescriptor from the start of the RECORD, 0 if no PFD + uint32_t bOpenGL; //!< nonZero if OpenGL commands are included + /** Fields for winver >= win98 */ + U_SIZEL szlMicrometers; //!< Size of the display device in micrometer +} U_EMRHEADER, + *PU_EMRHEADER; //!< EMF manual 2.2.9 +#define U_SIZE_EMRHEADER sizeof(U_EMRHEADER) // modern EMF files, for _really_ old ones the _MIN size applies +#define U_SIZE_EMRHEADER_MIN (U_SIZE_EMRHEADER - sizeof(U_CBPXLFMT) - sizeof(U_OFFPXLFMT) - sizeof(uint32_t) - sizeof(U_SIZEL)) + +/* Index 2,3,4,5,6 */ +/** EMF manual 2.3.5.16 +*/ +typedef struct { + U_EMR emr; //!< U_EMR + U_RECTL rclBounds; //!< bounding rectangle in device units + U_NUM_POINTL cptl; //!< Number of points to draw + U_POINTL aptl[1]; //!< array of points +} U_EMRPOLYBEZIER, + U_EMRPOLYGON, //!< EMF manual 2.3.5.22 + U_EMRPOLYLINE, //!< EMF manual 2.3.5.24 + U_EMRPOLYBEZIERTO, //!< EMF manual 2.3.5.18 + U_EMRPOLYLINETO, //!< EMF manual 2.3.5.26 + *PU_EMRPOLYBEZIER, //!< EMF manual 2.3.5.16 + *PU_EMRPOLYGON, //!< EMF manual 2.3.5.22 + *PU_EMRPOLYLINE, //!< EMF manual 2.3.5.24 + *PU_EMRPOLYBEZIERTO, //!< EMF manual 2.3.5.18 + *PU_EMRPOLYLINETO; //!< EMF manual 2.3.5.26 + +#define U_SIZE_EMRPOLYBEZIER (sizeof(U_EMR) + sizeof(U_RECTL) + sizeof(U_NUM_POINTL) ) +#define U_SIZE_EMRPOLYGON U_SIZE_EMRPOLYBEZIER +#define U_SIZE_EMRPOLYLINE U_SIZE_EMRPOLYBEZIER +#define U_SIZE_EMRPOLYBEZIERTO U_SIZE_EMRPOLYBEZIER +#define U_SIZE_EMRPOLYLINETO U_SIZE_EMRPOLYBEZIER +/* Index 7,8 */ +/** EMF manual 2.3.5.30 + + After this struct the record also contains an array of points:\n + U_POINTL aptl[1]; +*/ +typedef struct { + U_EMR emr; //!< U_EMR + U_RECTL rclBounds; //!< bounding rectangle in device units + U_NUM_POLYCOUNTS nPolys; //!< Number of elements in aPolyCounts + U_NUM_POINTL cptl; //!< Total number of points (over all poly) + U_POLYCOUNTS aPolyCounts[1]; //!< Number of points in each poly (sequential) +} U_EMRPOLYPOLYLINE, + U_EMRPOLYPOLYGON, //!< EMF manual 2.3.5.28 + *PU_EMRPOLYPOLYLINE, //!< EMF manual 2.3.5.30 + *PU_EMRPOLYPOLYGON; //!< EMF manual 2.3.5.28 +#define U_SIZE_EMRPOLYPOLYLINE (sizeof(U_EMR) + sizeof(U_RECTL) + sizeof(U_NUM_POLYCOUNTS) + sizeof(U_NUM_POINTL)) +#define U_SIZE_EMRPOLYPOLYGON U_SIZE_EMRPOLYPOLYLINE + +/* Index 9,11 (numbers interleave with next one) */ +/** EMF manual 2.3.11.30 +*/ +typedef struct { + U_EMR emr; //!< U_EMR + U_SIZEL szlExtent; //!< H & V extent in logical units +} U_EMRSETWINDOWEXTEX, + U_EMRSETVIEWPORTEXTEX, //!< EMF manual manual 2.3.11.28 + *PU_EMRSETWINDOWEXTEX, //!< EMF manual manual 2.3.11.30 + *PU_EMRSETVIEWPORTEXTEX; //!< EMF manual manual 2.3.11.28 +#define U_SIZE_EMRSETWINDOWEXTEX (sizeof(U_EMRSETWINDOWEXTEX )) +#define U_SIZE_EMRSETVIEWPORTEXTEX (sizeof(U_EMRSETVIEWPORTEXTEX)) + +/* Index 10,12,13 */ +/** EMF manual 2.3.11.31 +*/ +typedef struct { + U_EMR emr; //!< U_EMR + U_POINTL ptlOrigin; //!< H & V origin in logical units +} U_EMRSETWINDOWORGEX, + U_EMRSETVIEWPORTORGEX, //!< EMF manual 2.3.11.29 + U_EMRSETBRUSHORGEX, //!< EMF manual 2.3.11.12 + *PU_EMRSETWINDOWORGEX, //!< EMF manual 2.3.11.31 + *PU_EMRSETVIEWPORTORGEX, //!< EMF manual 2.3.11.29 + *PU_EMRSETBRUSHORGEX; //!< EMF manual 2.3.11.12 +#define U_SIZE_EMRSETWINDOWORGEX (sizeof(U_EMRSETWINDOWORGEX )) +#define U_SIZE_EMRSETVIEWPORTORGEX (sizeof(U_EMRSETVIEWPORTORGEX)) +#define U_SIZE_EMRSETBRUSHORGEX (sizeof(U_EMRSETBRUSHORGEX )) + +/* Index 14 */ +/** EMF manual 3.2.4.1 + +This is a very odd structure because the nSizeLast follows an optional variable size field. Consequently +even though nSizeLast has a name it cannot actually be accessed by it! Following the core structure +appear these fields:\n + + U_LOGPLTNTRY PalEntries[1]; Record may include optional array of PalEntries + + uint32_t nSizeLast; Mandatory, but position isn't fixed. Must have same value as emr.nSize in header record + +*/ +typedef struct { + U_EMR emr; //!< U_EMR + U_CBPLENTRIES cbPalEntries; //!< Number of palette entries + U_OFFPLENTRIES offPalEntries; //!< Offset in bytes to array of palette entries +} U_EMREOF, + *PU_EMREOF; //!< EMF manual 3.2.4.1 +#define U_SIZE_EMREOF (sizeof(U_EMREOF)) + +/* Index 15 */ +/** EMF manual 2.3.5.36 +*/ +typedef struct { + U_EMR emr; //!< U_EMR + U_POINTL ptlPixel; //!< Pixel coordinates (logical) + U_COLORREF crColor; //!< Pixel color +} U_EMRSETPIXELV, + *PU_EMRSETPIXELV; //!< EMF manual 2.3.5.36 +#define U_SIZE_EMRSETPIXELV (sizeof(U_EMRSETPIXELV)) + +/* Index 16 */ +/** EMF manual 2.3.11.20 +*/ +typedef struct { + U_EMR emr; //!< U_EMR + uint32_t dwFlags; //!< must be 1 +} U_EMRSETMAPPERFLAGS, + *PU_EMRSETMAPPERFLAGS; //!< EMF manual 2.3.11.20 +#define U_SIZE_EMRSETMAPPERFLAGS (sizeof(U_EMRSETMAPPERFLAGS)) + +/* Index 17,18,19,20,21,22,67,98,115 +*/ +/** EMF manual 2.3.11.19 MapMode enumeration +*/ +typedef struct { + U_EMR emr; //!< U_EMR + uint32_t iMode; //!< enumeration varies with type +} U_EMRSETMAPMODE, + U_EMRSETBKMODE, //!< EMF manual 2.3.11.11 BackgroundMode Enumeration + U_EMRSETPOLYFILLMODE, //!< EMF manual 2.3.11.22 PolygonFillMode Enumeration + U_EMRSETROP2, //!< EMF manual 2.3.11.23 Binary Raster Operation Enumeration + U_EMRSETSTRETCHBLTMODE, //!< EMF manual 2.3.11.24 StretchMode Enumeration + U_EMRSETTEXTALIGN, //!< EMF manual 2.3.11.25 TextAlignment enumeration + U_EMRSELECTCLIPPATH, //!< EMF manual 2.3.2.5 RegionMode Enumeration + U_EMRSETICMMODE, //!< EMF manual 2.3.11.14 ICMMode Enumeration + U_EMRSETLAYOUT, //!< EMF manual 2.3.11.17 Mirroring Enumeration + *PU_EMRSETMAPMODE, //!< EMF manual 2.3.11.19 MapMode enumeration + *PU_EMRSETBKMODE, //!< EMF manual 2.3.11.11 BackgroundMode Enumeration + *PU_EMRSETPOLYFILLMODE, //!< EMF manual 2.3.11.22 PolygonFillMode Enumeration + *PU_EMRSETROP2, //!< EMF manual 2.3.11.23 Binary Raster Operation Enumeration + *PU_EMRSETSTRETCHBLTMODE, //!< EMF manual 2.3.11.24 StretchMode Enumeration + *PU_EMRSETTEXTALIGN, //!< EMF manual 2.3.11.25 TextAlignment enumeration + *PU_EMRSELECTCLIPPATH, //!< EMF manual 2.3.2.5 RegionMode Enumeration + *PU_EMRSETICMMODE, //!< EMF manual 2.3.11.14 ICMMode Enumeration + *PU_EMRSETLAYOUT; //!< EMF manual 2.3.11.17 Mirroring Enumeration + +#define U_SIZE_EMRSETMAPMODE (sizeof(U_EMRSETMAPMODE )) +#define U_SIZE_EMRSETBKMODE (sizeof(U_EMRSETBKMODE )) +#define U_SIZE_EMRSETPOLYFILLMODE (sizeof(U_EMRSETPOLYFILLMODE )) +#define U_SIZE_EMRSETROP2 (sizeof(U_EMRSETROP2 )) +#define U_SIZE_EMRSETSTRETCHBLTMODE (sizeof(U_EMRSETSTRETCHBLTMODE)) +#define U_SIZE_EMRSETTEXTALIGN (sizeof(U_EMRSETTEXTALIGN )) +#define U_SIZE_EMRSELECTCLIPPATH (sizeof(U_EMRSELECTCLIPPATH )) +#define U_SIZE_EMRSETICMMODE (sizeof(U_EMRSETICMMODE )) +#define U_SIZE_EMRSETLAYOUT (sizeof(U_EMRSETLAYOUT )) + +/* Index 23 */ +/** EMF manual 2.3.11.13 +*/ +typedef struct { + U_EMR emr; //!< U_EMR + U_COLORADJUSTMENT ColorAdjustment; //!< Color Adjustment +} U_EMRSETCOLORADJUSTMENT, + *PU_EMRSETCOLORADJUSTMENT; //!< EMF manual 2.3.11.13 +#define U_SIZE_EMRSETCOLORADJUSTMENT (sizeof(U_EMRSETCOLORADJUSTMENT)) + +/* Index 24, 25 */ +/** EMF manual 2.3.11.26 +*/ +typedef struct { + U_EMR emr; //!< U_EMR + U_COLORREF crColor; //!< Color +} U_EMRSETTEXTCOLOR, + U_EMRSETBKCOLOR, //!< EMF manual 2.3.11.10 + *PU_EMRSETTEXTCOLOR, //!< EMF manual 2.3.11.26 + *PU_EMRSETBKCOLOR; //!< EMF manual 2.3.11.10 +#define U_SIZE_EMRSETTEXTCOLOR (sizeof(U_EMRSETTEXTCOLOR)) +#define U_SIZE_EMRSETBKCOLOR (sizeof(U_EMRSETBKCOLOR )) + +/* Index 26 */ +/** EMF manual 2.3.2.4 +*/ +typedef struct { + U_EMR emr; //!< U_EMR + U_POINTL ptlOffset; //!< Clipping region +} U_EMROFFSETCLIPRGN, + *PU_EMROFFSETCLIPRGN; //!< EMF manual 2.3.2.4 +#define U_SIZE_EMROFFSETCLIPRGN (sizeof(U_EMROFFSETCLIPRGN)) + +/* Index 27, 54 */ +/** +EMF manual 2.3.11.4 +EMF manual 2.3.5.13 +*/ +typedef struct { + U_EMR emr; //!< U_EMR + U_POINTL ptl; //!< Point coordinates +} U_EMRMOVETOEX, + U_EMRLINETO, //!< EMF manual 2.3.5.13 + *PU_EMRMOVETOEX, //!< EMF manual 2.3.11.4 + *PU_EMRLINETO; //!< EMF manual 2.3.5.13 +#define U_SIZE_EMRMOVETOEX (sizeof(U_EMRMOVETOEX)) +#define U_SIZE_EMRLINETO (sizeof(U_EMRLINETO )) + +/* Index 28,33,52,59,60,61,65,66,68 */ +/** EMF manual 2.3.2 +*/ +typedef struct { + U_EMR emr; //!< U_EMR +} + U_EMRSETMETARGN, + U_EMRSAVEDC, //!< EMF manual 2.3.11 + U_EMRREALIZEPALETTE, //!< EMF manual 2.3.10 + U_EMRBEGINPATH, //!< EMF manual 2.3.10 + U_EMRENDPATH, //!< EMF manual 2.3.10 + U_EMRCLOSEFIGURE, //!< EMF manual 2.3.10 + U_EMRFLATTENPATH, //!< EMF manual 2.3.10 + U_EMRWIDENPATH, //!< EMF manual 2.3.10 + U_EMRABORTPATH, //!< EMF manual 2.3.10 + *PU_EMRSETMETARGN, //!< EMF manual 2.3.2 + *PU_EMRSAVEDC, //!< EMF manual 2.3.11 + *PU_EMRREALIZEPALETTE, //!< EMF manual 2.3.10 + *PU_EMRBEGINPATH, //!< EMF manual 2.3.10 + *PU_EMRENDPATH, //!< EMF manual 2.3.10 + *PU_EMRCLOSEFIGURE, //!< EMF manual 2.3.10 + *PU_EMRFLATTENPATH, //!< EMF manual 2.3.10 + *PU_EMRWIDENPATH, //!< EMF manual 2.3.10 + *PU_EMRABORTPATH; //!< EMF manual 2.3.10 +#define U_SIZE_EMRSETMETARGN (sizeof(U_EMRSETMETARGN )) +#define U_SIZE_EMRSAVEDC (sizeof(U_EMRSAVEDC )) +#define U_SIZE_EMRREALIZEPALETTE (sizeof(U_EMRREALIZEPALETTE)) +#define U_SIZE_EMRBEGINPATH (sizeof(U_EMRBEGINPATH )) +#define U_SIZE_EMRENDPATH (sizeof(U_EMRENDPATH )) +#define U_SIZE_EMRCLOSEFIGURE (sizeof(U_EMRCLOSEFIGURE )) +#define U_SIZE_EMRFLATTENPATH (sizeof(U_EMRFLATTENPATH )) +#define U_SIZE_EMRWIDENPATH (sizeof(U_EMRWIDENPATH )) +#define U_SIZE_EMRABORTPATH (sizeof(U_EMRABORTPATH )) + +/* Index 29,30 */ +/** EMF manual 2.3.2.1 +*/ +typedef struct { + U_EMR emr; //!< U_EMR + U_RECTL rclClip; //!< Clipping Region +} U_EMREXCLUDECLIPRECT, + U_EMRINTERSECTCLIPRECT, //!< EMF manual 2.3.2.3 + *PU_EMREXCLUDECLIPRECT, //!< EMF manual 2.3.2.1 + *PU_EMRINTERSECTCLIPRECT; //!< EMF manual 2.3.2.3 +#define U_SIZE_EMREXCLUDECLIPRECT (sizeof(U_EMREXCLUDECLIPRECT )) +#define U_SIZE_EMRINTERSECTCLIPRECT (sizeof(U_EMRINTERSECTCLIPRECT )) + +/* Index 31,32 */ +/** EMF manual 2.3.11.7 +*/ +typedef struct { + U_EMR emr; //!< U_EMR + int32_t xNum; //!< Horizontal multiplier (!=0) + int32_t xDenom; //!< Horizontal divisor (!=0) + int32_t yNum; //!< Vertical multiplier (!=0) + int32_t yDenom; //!< Vertical divisor (!=0) +} U_EMRSCALEVIEWPORTEXTEX, + U_EMRSCALEWINDOWEXTEX, //!< EMF manual 2.3.11.8 + *PU_EMRSCALEVIEWPORTEXTEX, //!< EMF manual 2.3.11.7 + *PU_EMRSCALEWINDOWEXTEX; //!< EMF manual 2.3.11.8 +#define U_SIZE_EMRSCALEVIEWPORTEXTEX (sizeof(U_EMRSCALEVIEWPORTEXTEX)) +#define U_SIZE_EMRSCALEWINDOWEXTEX (sizeof(U_EMRSCALEWINDOWEXTEX )) + +/* Index 33 (see 28) */ + +/* Index 34 */ +/** EMF manual 2.3.11.6 +*/ +typedef struct { + U_EMR emr; //!< U_EMR + int32_t iRelative; //!< DC to restore. -1 is preceding +} U_EMRRESTOREDC, + *PU_EMRRESTOREDC; //!< EMF manual 2.3.11.6 +#define U_SIZE_EMRRESTOREDC (sizeof(U_EMRRESTOREDC)) + +/* Index 35 */ +/** EMF manual 2.3.12.2 +*/ +typedef struct { + U_EMR emr; //!< U_EMR + U_XFORM xform; //!< Transform +} U_EMRSETWORLDTRANSFORM, + *PU_EMRSETWORLDTRANSFORM; //!< EMF manual 2.3.12.2 +#define U_SIZE_EMRSETWORLDTRANSFORM (sizeof(U_EMRSETWORLDTRANSFORM)) + +/* Index 36 */ +/** EMF manual 2.3.12.1 +*/ +typedef struct { + U_EMR emr; //!< U_EMR + U_XFORM xform; //!< Transform + uint32_t iMode; //!< ModifyWorldTransformMode Enumeration +} U_EMRMODIFYWORLDTRANSFORM, + *PU_EMRMODIFYWORLDTRANSFORM; //!< EMF manual 2.3.12.1 +#define U_SIZE_EMRMODIFYWORLDTRANSFORM (sizeof(U_EMRMODIFYWORLDTRANSFORM)) + +/* Index 37,40 */ +/** EMF manual 2.3.8.3 +*/ +typedef struct { + U_EMR emr; //!< U_EMR + uint32_t ihObject; //!< Number of a stock or created object +} U_EMRDELETEOBJECT, + U_EMRSELECTOBJECT, //!< EMF manual 2.3.8.5 + *PU_EMRDELETEOBJECT, //!< EMF manual 2.3.8.3 + *PU_EMRSELECTOBJECT; //!< EMF manual 2.3.8.5 +#define U_SIZE_EMRDELETEOBJECT (sizeof(U_EMRDELETEOBJECT)) +#define U_SIZE_EMRSELECTOBJECT (sizeof(U_EMRSELECTOBJECT)) + +/* Index 38 */ +/** EMF manual 2.3.7.7 +*/ +typedef struct { + U_EMR emr; //!< U_EMR + uint32_t ihPen; //!< Index to place object in EMF object table (this entry must not yet exist) + U_LOGPEN lopn; //!< Pen properties +} U_EMRCREATEPEN, + *PU_EMRCREATEPEN; //!< EMF manual 2.3.7.7 +#define U_SIZE_EMRCREATEPEN (sizeof(U_EMRCREATEPEN)) + +/* Index 39 */ +/** EMF manual 2.3.7.1 +*/ +typedef struct { + U_EMR emr; //!< U_EMR + uint32_t ihBrush; //!< Index to place object in EMF object table (this entry must not yet exist) + U_LOGBRUSH lb; //!< Brush properties +} U_EMRCREATEBRUSHINDIRECT, + *PU_EMRCREATEBRUSHINDIRECT; //!< EMF manual 2.3.7.1 +#define U_SIZE_EMRCREATEBRUSHINDIRECT (sizeof(U_EMRCREATEBRUSHINDIRECT)) + +/* Index 40 see 37 */ + +/* Index 41 */ +/** EMF manual 2.3.5.1 +*/ +typedef struct { + U_EMR emr; //!< U_EMR + U_POINTL ptlCenter; //!< Center in logical units + uint32_t nRadius; //!< Radius in logical units + U_FLOAT eStartAngle; //!< Starting angle in degrees (counter clockwise from x axis) + U_FLOAT eSweepAngle; //!< Sweep angle in degrees +} U_EMRANGLEARC, + *PU_EMRANGLEARC; //!< EMF manual 2.3.5.1 +#define U_SIZE_EMRANGLEARC (sizeof(U_EMRANGLEARC)) + +/* Index 42,43 */ +/** EMF manual 2.3.5.5 +*/ +typedef struct { + U_EMR emr; //!< U_EMR + U_RECTL rclBox; //!< bounding rectangle in logical units +} U_EMRELLIPSE, + U_EMRRECTANGLE, //!< EMF manual 2.3.5.5 + *PU_EMRELLIPSE, //!< EMF manual 2.3.5.5 + *PU_EMRRECTANGLE; //!< EMF manual 2.3.5.34 +#define U_SIZE_EMRELLIPSE (sizeof(U_EMRELLIPSE )) +#define U_SIZE_EMRRECTANGLE (sizeof(U_EMRRECTANGLE)) + +/* Index 44 */ +/** EMF manual 2.3.5.35 +*/ +typedef struct { + U_EMR emr; //!< U_EMR + U_RECTL rclBox; //!< bounding rectangle in logical units + U_SIZEL szlCorner; //!< W & H in logical units of ellipse used to round corner +} U_EMRROUNDRECT, + *PU_EMRROUNDRECT; //!< EMF manual 2.3.5.35 +#define U_SIZE_EMRROUNDRECT (sizeof(U_EMRROUNDRECT)) + +/* Index 45, 46 ,47, 55 */ +/** EMF manual 2.3.5.2 +*/ +typedef struct { + U_EMR emr; //!< U_EMR + U_RECTL rclBox; //!< bounding rectangle in logical units + U_POINTL ptlStart; //!< Start point in logical units + U_POINTL ptlEnd; //!< End point in logical units +} U_EMRARC, + U_EMRCHORD, //!< EMF manual 2.3.5.4 + U_EMRPIE, //!< EMF manual 2.3.5.15 + U_EMRARCTO, //!< EMF manual 2.3.5.3 + *PU_EMRARC, //!< EMF manual 2.3.5.2 + *PU_EMRCHORD, //!< EMF manual 2.3.5.4 + *PU_EMRPIE, //!< EMF manual 2.3.5.15 + *PU_EMRARCTO; //!< EMF manual 2.3.5.3 +#define U_SIZE_EMRARC (sizeof(U_EMRARC )) +#define U_SIZE_EMRCHORD (sizeof(U_EMRCHORD)) +#define U_SIZE_EMRPIE (sizeof(U_EMRPIE )) +#define U_SIZE_EMRARCTO (sizeof(U_EMRARCTO)) + +/* Index 48 */ +/** EMF manual 2.3.8.6 +*/ +typedef struct { + U_EMR emr; //!< U_EMR + uint32_t ihPal; //!< Index of a Palette object in the EMF object table +} U_EMRSELECTPALETTE, + *PU_EMRSELECTPALETTE; //!< EMF manual 2.3.8.6 +#define U_SIZE_EMRSELECTPALETTE (sizeof(U_EMRSELECTPALETTE)) + +/* Index 49 */ +/** EMF manual 2.3.7.6 +*/ +typedef struct { + U_EMR emr; //!< U_EMR + uint32_t ihPal; //!< Index to place object in EMF object table (this entry must not yet exist) + U_LOGPALETTE lgpl; //!< Palette properties (variable size) +} U_EMRCREATEPALETTE, + *PU_EMRCREATEPALETTE; //!< EMF manual 2.3.7.6 +#define U_SIZE_EMRCREATEPALETTE (sizeof(U_EMR) + sizeof(uint32_t) + U_SIZE_LOGPALETTE) + +/* Index 50 */ +/** EMF manual 2.3.8.8 +*/ +typedef struct { + U_EMR emr; //!< U_EMR + uint32_t ihPal; //!< Index of a Palette object in the EMF object table + uint32_t iStart; //!< First Palette entry in selected object to set + U_NUM_LOGPLTNTRY cEntries; //!< Number of Palette entries in selected object to set + U_LOGPLTNTRY aPalEntries[1]; //!< Values to set with +} U_EMRSETPALETTEENTRIES, + *PU_EMRSETPALETTEENTRIES; //!< EMF manual 2.3.8.8 +#define U_SIZE_EMRSETPALETTEENTRIES (sizeof(U_EMR) + 2*sizeof(uint32_t) + sizeof(U_NUM_LOGPLTNTRY)) + +/* Index 51 */ +/** EMF manual 2.3.8.4 +*/ +typedef struct { + U_EMR emr; //!< U_EMR + uint32_t ihPal; //!< Index of a Palette object in the EMF object table + uint32_t cEntries; //!< Number to expand or truncate the Palette entry list to. +} U_EMRRESIZEPALETTE, + *PU_EMRRESIZEPALETTE; //!< EMF manual 2.3.8.4 +#define U_SIZE_EMRRESIZEPALETTE (sizeof(U_EMRRESIZEPALETTE)) + +/* Index 52 (see 28) */ + +/* Index 53 */ +/** EMF manual 2.3.5.6 +*/ +typedef struct { + U_EMR emr; //!< U_EMR + U_POINTL ptlStart; //!< Start point in logical units + U_COLORREF crColor; //!< Color to fill with + uint32_t iMode; //!< FloodFill Enumeration +} U_EMREXTFLOODFILL, + *PU_EMREXTFLOODFILL; //!< EMF manual 2.3.5.6 +#define U_SIZE_EMREXTFLOODFILL (sizeof(U_EMREXTFLOODFILL)) + +/* Index 54 (see 27) */ + +/* Index 55 (see 45) */ + +/* Index 56 */ +/** EMF manual 2.3.5.20 + + followed by + uint8_t abTypes[1]; //!< Array of Point Enumeration +*/ +typedef struct { + U_EMR emr; //!< U_EMR + U_RECTL rclBounds; //!< Bounding rectangle in device units + U_NUM_POINTL cptl; //!< Number of U_POINTL objects + U_POINTL aptl[1]; //!< Array of U_POINTL objects +} U_EMRPOLYDRAW, + *PU_EMRPOLYDRAW; //!< EMF manual 2.3.5.20 +#define U_SIZE_EMRPOLYDRAW (sizeof(U_EMR) + sizeof(U_RECTL) + sizeof(U_NUM_POINTL)) + +/* Index 57 */ +/** EMF manual 2.3.11.9 +*/ +typedef struct { + U_EMR emr; //!< U_EMR + uint32_t iArcDirection; //!< ArcDirection Enumeration +} U_EMRSETARCDIRECTION, + *PU_EMRSETARCDIRECTION; //!< EMF manual 2.3.11.9 +#define U_SIZE_EMRSETARCDIRECTION (sizeof(U_EMRSETARCDIRECTION)) + +/* Index 58 */ +/** EMF manual 2.3.11.21 + +IMPORTANT!!!! The Microsoft structure uses a float for the miterlimit but the EMF file record +uses an unsigned int. The latter form is used in this structure. +*/ +typedef struct { + U_EMR emr; //!< U_EMR + uint32_t eMiterLimit; //!< Miter limit (max value of mitered length / line width) +} U_EMRSETMITERLIMIT, + *PU_EMRSETMITERLIMIT; //!< EMF manual 2.3.11.21 +#define U_SIZE_EMRSETMITERLIMIT (sizeof(U_EMRSETMITERLIMIT)) + +/* Index 59,60,61 (see 28) */ + +/* Index 62,63,64 */ +/** EMF manual 2.3.5.9 +*/ +typedef struct { + U_EMR emr; //!< U_EMR + U_RECTL rclBounds; //!< Bounding rectangle in device units +} U_EMRFILLPATH, + U_EMRSTROKEANDFILLPATH, //!< EMF manual 2.3.5.38 + U_EMRSTROKEPATH, //!< EMF manual 2.3.5.39 + *PU_EMRFILLPATH, //!< EMF manual 2.3.5.9 + *PU_EMRSTROKEANDFILLPATH, //!< EMF manual 2.3.5.38 + *PU_EMRSTROKEPATH; //!< EMF manual 2.3.5.39 +#define U_SIZE_EMRFILLPATH (sizeof(U_EMRFILLPATH )) +#define U_SIZE_EMRSTROKEANDFILLPATH (sizeof(U_EMRSTROKEANDFILLPATH)) +#define U_SIZE_EMRSTROKEPATH (sizeof(U_EMRSTROKEPATH )) + +/* Index 65,66 (see 28) */ +/* Index 67 (see 17) */ +/* Index 68 (see 28) */ +/* Index 69 (not a defined U_EMR record type ) */ + + +/* Index 70 */ +/** EMF manual 2.3.3.1 +*/ +typedef struct { + U_EMR emr; //!< U_EMR + U_CBDATA cbData; //!< Number of bytes in comment + uint8_t Data[1]; //!< Comment (any binary data, interpretation is program specific) +} U_EMRCOMMENT, + *PU_EMRCOMMENT; //!< EMF manual 2.3.3.1, AKA GDICOMMENT +#define U_SIZE_EMRCOMMENT (sizeof(U_EMR) + sizeof(U_CBDATA)) + +/* variant comment types */ +/** EMF manual 2.3.3.2 +*/ +typedef struct { + U_EMR emr; //!< U_EMR + U_CBDATA cbData; //!< Number of bytes in comment + uint32_t cIdent; //!< Comment identifier, must be U_EMR_COMMENT_EMFPLUSRECORD + uint8_t Data[1]; //!< EMF Plus record +} U_EMRCOMMENT_EMFPLUS, + *PU_EMRCOMMENT_EMFPLUS; //!< EMF manual 2.3.3.2, EMF Plus comment +#define U_SIZE_EMRCOMMENT_EMFPLUS (sizeof(U_EMR) + sizeof(U_CBDATA) + sizeof(uint32_t)) + +/** EMF manual 2.3.3.3 +*/ +typedef struct { + U_EMR emr; //!< U_EMR + U_CBDATA cbData; //!< Number of bytes in comment + uint32_t cIdent; //!< Comment identifier, must be U_EMR_COMMENT_SPOOL + uint32_t esrIdent; //!< EMFSpoolRecordIdentifier, may be U_EMR_COMMENT_SPOOLFONTDEF + uint8_t Data[1]; //!< EMF Spool records +} U_EMRCOMMENT_SPOOL, + *PU_EMRCOMMENT_SPOOL; //!< EMF manual 2.3.3.3, EMF Spool comment +#define U_SIZE_EMRCOMMENT_SPOOL (sizeof(U_EMR) + sizeof(U_CBDATA) + 2*sizeof(uint32_t)) + +/** EMF manual 2.3.3.4 +*/ +typedef struct { + U_EMR emr; //!< U_EMR + U_CBDATA cbData; //!< Number of bytes in comment + uint32_t cIdent; //!< Comment identifier, must be U_EMR_COMMENT_PUBLIC + uint32_t pcIdent; //!< Public Comment Identifier, from EMRComment Enumeration + uint8_t Data[1]; //!< Public comment data +} U_EMRCOMMENT_PUBLIC, + *PU_EMRCOMMENT_PUBLIC; //!< EMF manual 2.3.3.4, EMF Public comment +#define U_SIZE_EMRCOMMENT_PUBLIC (sizeof(U_EMR) + sizeof(U_CBDATA) + 2*sizeof(uint32_t)) + +/* Index 71 */ +/** EMF manual 2.3.5.10 + followed by a variable number of U_RECTLs +*/ +typedef struct { + U_EMR emr; //!< U_EMR + U_RECTL rclBounds; //!< Bounding rectangle in device units + U_CBRGNDATA cbRgnData; //!< Size in bytes of Region data + uint32_t ihBrush; //!< Index of a Brush object in the EMF object table + U_RGNDATA RgnData[1]; //!< Variable size U_RGNDATA structure +} U_EMRFILLRGN, + *PU_EMRFILLRGN; //!< EMF manual 2.3.5.10 +#define U_SIZE_EMRFILLRGN (sizeof(U_EMR) + sizeof(U_RECTL) + sizeof(U_CBRGNDATA) + sizeof(uint32_t)) + +/* Index 72 */ +/** EMF manual 2.3.5.11 +*/ +typedef struct { + U_EMR emr; //!< U_EMR + U_RECTL rclBounds; //!< Bounding rectangle in device units + U_CBRGNDATA cbRgnData; //!< Size in bytes of Region data + uint32_t ihBrush; //!< Index of a Brush object in the EMF object table + U_SIZEL szlStroke; //!< W & H of Brush stroke + U_RGNDATA RgnData[1]; //!< Variable size U_RGNDATA structure +} U_EMRFRAMERGN, + *PU_EMRFRAMERGN; //!< EMF manual 2.3.5.11 +#define U_SIZE_EMRFRAMERGN (sizeof(U_EMR) + sizeof(U_RECTL) + sizeof(U_CBRGNDATA) + sizeof(uint32_t) + sizeof(U_SIZEL)) + +/* Index 73,74 */ +/** EMF manual 2.3.11.3 +*/ +typedef struct { + U_EMR emr; //!< U_EMR + U_RECTL rclBounds; //!< Bounding rectangle in device units + U_CBRGNDATA cbRgnData; //!< Size in bytes of Region data + U_RGNDATA RgnData[1]; //!< Variable size U_RGNDATA structure +} U_EMRINVERTRGN, + U_EMRPAINTRGN, //!< EMF manual 2.3.5.14 + *PU_EMRINVERTRGN, //!< EMF manual 2.3.11.3 + *PU_EMRPAINTRGN; //!< EMF manual 2.3.5.14 +#define U_SIZE_EMRINVERTRGN (sizeof(U_EMR) + sizeof(U_RECTL) + sizeof(U_CBRGNDATA)) +#define U_SIZE_EMRPAINTRGN U_SIZE_EMRINVERTRGN + +/* Index 75 */ +/** EMF manual 2.3.2.2 +*/ +typedef struct { + U_EMR emr; //!< U_EMR + U_CBRGNDATA cbRgnData; //!< Size in bytes of Region data + uint32_t iMode; //!< RegionMode Enumeration + U_RGNDATA RgnData[1]; //!< Variable size U_RGNDATA structure +} U_EMREXTSELECTCLIPRGN, + *PU_EMREXTSELECTCLIPRGN; //!< EMF manual 2.3.2.2 +#define U_SIZE_EMREXTSELECTCLIPRGN (sizeof(U_EMR) + sizeof(U_CBRGNDATA) + sizeof(uint32_t)) + +/* Index 76 */ +/** EMF manual 2.3.1.2 +*/ +typedef struct { + U_EMR emr; //!< U_EMR + U_RECTL rclBounds; //!< Bounding rectangle in device units + U_POINTL Dest; //!< Destination UL corner in logical units + U_POINTL cDest; //!< Destination width in logical units + uint32_t dwRop; //!< Ternary Raster Operation enumeration + U_POINTL Src; //!< Source retangle UL corner in logical units + U_XFORM xformSrc; //!< Source bitmap transform (world to page coordinates) + U_COLORREF crBkColorSrc; //!< Source bitmap background color + uint32_t iUsageSrc; //!< DIBcolors Enumeration + U_OFFBMISRC offBmiSrc; //!< Offset in bytes to U_BITMAPINFO (within bitmapbuffer) + U_CBBMISRC cbBmiSrc; //!< Size in bytes of U_BITMAPINFO + U_OFFBITSSRC offBitsSrc; //!< Offset in bytes to the bitmap (within bitmapbuffer) + U_CBBITS cbBitsSrc; //!< Size in bytes of bitmap + //!< Record may include optional bitmapbuffer +} U_EMRBITBLT, + *PU_EMRBITBLT; //!< EMF manual 2.3.1.2 +#define U_SIZE_EMRBITBLT (sizeof(U_EMRBITBLT)) + +/* Index 77 */ +/** EMF manual 2.3.1.6 +*/ +typedef struct { + U_EMR emr; //!< U_EMR + U_RECTL rclBounds; //!< Bounding rectangle in device units + U_POINTL Dest; //!< Destination UL corner in logical units + U_POINTL cDest; //!< Destination width in logical units + uint32_t dwRop; //!< Ternary Raster Operation enumeration + U_POINTL Src; //!< Source UL corner in logical units + U_XFORM xformSrc; //!< Transform to apply to source + U_COLORREF crBkColorSrc; //!< Background color + uint32_t iUsageSrc; //!< DIBcolors Enumeration + U_OFFBMISRC offBmiSrc; //!< Offset in bytes to U_BITMAPINFO (within bitmapbuffer) + U_CBBMISRC cbBmiSrc; //!< Size in bytes of U_BITMAPINFO + U_OFFBITSSRC offBitsSrc; //!< Offset in bytes to the bitmap (within bitmapbuffer) + U_CBBITS cbBitsSrc; //!< Size in bytes of bitmap + U_POINTL cSrc; //!< Src W & H in logical units + //!< Record may include optional bitmapbuffer +} U_EMRSTRETCHBLT, + *PU_EMRSTRETCHBLT; //!< EMF manual 2.3.1.6 +#define U_SIZE_EMRSTRETCHBLT (sizeof(U_EMRSTRETCHBLT)) + +/* Index 78 */ +/** EMF manual 2.3.1.3 +*/ +typedef struct { + U_EMR emr; //!< U_EMR + U_RECTL rclBounds; //!< Bounding rectangle in device units + U_POINTL Dest; //!< Destination UL corner in logical units + U_POINTL cDest; //!< Destination width in logical units + uint32_t dwRop; //!< Ternary Raster Operation enumeration + U_POINTL Src; //!< Source UL corner in logical units + U_XFORM xformSrc; //!< Transform to apply to source + U_COLORREF crBkColorSrc; //!< Background color + uint32_t iUsageSrc; //!< DIBcolors Enumeration + U_OFFBMISRC offBmiSrc; //!< Offset in bytes to U_BITMAPINFO (within srcbitmapbuffer) + U_CBBMISRC cbBmiSrc; //!< Size in bytes of U_BITMAPINFO + U_OFFBITSSRC offBitsSrc; //!< Offset in bytes to the src bitmap (within srcbitmapbuffer) + U_CBBITS cbBitsSrc; //!< Size in bytes of src bitmap + U_POINTL Mask; //!< Mask UL corner in logical units + uint32_t iUsageMask; //!< DIBcolors Enumeration + U_OFFBMIMSK offBmiMask; //!< Offset in bytes to U_BITMAPINFO (within maskbitmapbuffer) + U_CBBMIMSK cbBmiMask; //!< Size in bytes of U_BITMAPINFO + U_OFFBITSMSK offBitsMask; //!< Offset in bytes to the mask bitmap (within maskbitmapbuffer) + U_CBBITSMSK cbBitsMask; //!< Size in bytes of bitmap + //!< Record may include optional Source and mask bitmapbuffers +} U_EMRMASKBLT, + *PU_EMRMASKBLT; //!< EMF manual 2.3.1.3 +#define U_SIZE_EMRMASKBLT (sizeof(U_EMRMASKBLT)) + +/* Index 79 */ +/** EMF manual 2.3.1.4 +*/ +typedef struct { + U_EMR emr; //!< U_EMR + U_RECTL rclBounds; //!< Bounding rectangle in device units + U_POINTL aptlDst[3]; //!< Defines parallelogram, UL, UR, LL corners, LR is derived. + U_POINTL Src; //!< Source UL corner in logical units + U_POINTL cSrc; //!< Src W & H in logical units + U_XFORM xformSrc; //!< Transform to apply to source + U_COLORREF crBkColorSrc; //!< Background color + uint32_t iUsageSrc; //!< DIBcolors Enumeration + U_OFFBMISRC offBmiSrc; //!< Offset in bytes to U_BITMAPINFO (within srcbitmapbuffer) + U_CBBMISRC cbBmiSrc; //!< Size in bytes of U_BITMAPINFO + U_OFFBITSSRC offBitsSrc; //!< Offset in bytes to the src bitmap (within srcbitmapbuffer) + U_CBBITS cbBitsSrc; //!< Size in bytes of src bitmap + U_POINTL Mask; //!< Mask UL corner in logical units + uint32_t iUsageMask; //!< DIBcolors Enumeration + U_OFFBMIMSK offBmiMask; //!< Offset in bytes to U_BITMAPINFO (within maskbitmapbuffer) + U_CBBMIMSK cbBmiMask; //!< Size in bytes of U_BITMAPINFO + U_OFFBITSMSK offBitsMask; //!< Offset in bytes to the mask bitmap (within maskbitmapbuffer) + U_CBBITSMSK cbBitsMask; //!< Size in bytes of bitmap + //!< Record may include optional Source and mask bitmapbuffers +} U_EMRPLGBLT, + *PU_EMRPLGBLT; //!< EMF manual 2.3.1.4 +#define U_SIZE_EMRPLGBLT (sizeof(U_EMRPLGBLT)) + +/* Index 80 */ +/** EMF manual 2.3.1.5 +*/ +typedef struct { + U_EMR emr; //!< U_EMR + U_RECTL rclBounds; //!< Bounding rectangle in device units + U_POINTL Dest; //!< Destination UL corner in logical units + U_POINTL Src; //!< Source LL corner in logical units + U_POINTL cSrc; //!< Src W & H in logical units + U_OFFBMISRC offBmiSrc; //!< Offset in bytes to U_BITMAPINFO (within bitmapbuffer) + U_CBBMISRC cbBmiSrc; //!< Size in bytes of U_BITMAPINFO + U_OFFBITSSRC offBitsSrc; //!< Offset in bytes to bitmap + U_CBBITS cbBitsSrc; //!< Size in bytes of bitmap + uint32_t iUsageSrc; //!< DIBColors Enumeration + uint32_t iStartScan; //!< First scan line + uint32_t cScans; //!< Number of scan lines + //!< Record may includes optional bitmapbuffer +} U_EMRSETDIBITSTODEVICE, + *PU_EMRSETDIBITSTODEVICE; //!< EMF manual 2.3.1.5 +#define U_SIZE_EMRSETDIBITSTODEVICE (sizeof(U_EMRSETDIBITSTODEVICE)) + +/* Index 81 */ +/** EMF manual 2.3.1.7 +*/ +typedef struct { + U_EMR emr; //!< U_EMR + U_RECTL rclBounds; //!< Bounding rectangle in device units + U_POINTL Dest; //!< Destination UL corner in logical units + U_POINTL Src; //!< Source UL corner in logical units + U_POINTL cSrc; //!< Source W & H in logical units + U_OFFBMISRC offBmiSrc; //!< Offset in bytes to U_BITMAPINFO (within bitmapbuffer) + U_CBBMISRC cbBmiSrc; //!< Size in bytes of U_BITMAPINFO + U_OFFBITSSRC offBitsSrc; //!< Offset in bytes to bitmap + U_CBBITS cbBitsSrc; //!< Size in bytes of bitmap + uint32_t iUsageSrc; //!< DIBColors Enumeration + uint32_t dwRop; //!< Ternary Raster Operation enumeration + U_POINTL cDest; //!< Destination W & H in logical units + //!< Record may includes optional bitmapbuffer +} U_EMRSTRETCHDIBITS, + *PU_EMRSTRETCHDIBITS; //!< EMF manual 2.3.1.7 +#define U_SIZE_EMRSTRETCHDIBITS (sizeof(U_EMRSTRETCHDIBITS)) + +/* Index 82 */ +/** EMF manual 2.3.7.8 +*/ +typedef struct { + U_EMR emr; //!< U_EMR + uint32_t ihFont; //!< Index of the font in the EMF object table + U_LOGFONT_PANOSE elfw; //!< Font parameters, either U_LOGFONT or U_LOGFONT_PANOSE, the latter is bigger so use that type here +} U_EMREXTCREATEFONTINDIRECTW, + *PU_EMREXTCREATEFONTINDIRECTW; //!< EMF manual 2.3.7.8 +#define U_SIZE_EMREXTCREATEFONTINDIRECTW_LOGFONT_PANOSE (sizeof(U_EMR) + 4 + sizeof(U_LOGFONT_PANOSE)) +#define U_SIZE_EMREXTCREATEFONTINDIRECTW_LOGFONT (sizeof(U_EMR) + 4 + sizeof(U_LOGFONT)) + +/* Index 83,84 */ +/** EMF manual 2.3.5.7 + +Variable and optional fields may follow core structure in record:\n + + U_RECTL rcl; absent when fOptions & U_ETO_NO_RECT) grayed/clipping/opaque rectangle + + U_OFFDX offDx; (required) Offset in bytes to the character spacing array from the start of the RECORD + + uint32_t Dx (optional) character spacing array (Required, but position is not static.) +*/ +typedef struct { + U_EMR emr; //!< U_EMR + U_RECTL rclBounds; //!< Bounding rectangle in device units + uint32_t iGraphicsMode; //!< GraphicsMode Enumeration + U_FLOAT exScale; //!< scale to 0.01 mm units ( only if iGraphicsMode & U_GM_COMPATIBLE) + U_FLOAT eyScale; //!< scale to 0.01 mm units ( only if iGraphicsMode & U_GM_COMPATIBLE) + U_EMRTEXT emrtext; //!< Text parameters +} U_EMREXTTEXTOUTA, + U_EMREXTTEXTOUTW, //!< EMF manual 2.3.5.8 + *PU_EMREXTTEXTOUTA, //!< EMF manual 2.3.5.7 + *PU_EMREXTTEXTOUTW; //!< EMF manual 2.3.5.8 +#define U_SIZE_EMREXTTEXTOUTA (sizeof(U_EMREXTTEXTOUTA)) +#define U_SIZE_EMREXTTEXTOUTW (sizeof(U_EMREXTTEXTOUTW)) + +/* Index 85,86,87,88,89 */ +/** EMF manual 2.3.5.17 +*/ +typedef struct { + U_EMR emr; //!< U_EMR + U_RECTL rclBounds; //!< Bounding rectangle in device units + U_NUM_POINT16 cpts; //!< Number of POINT16 in array + U_POINT16 apts[1]; //!< Array of POINT16 +} U_EMRPOLYBEZIER16, + U_EMRPOLYGON16, //!< EMF manual 2.3.5.23 + U_EMRPOLYLINE16, //!< EMF manual 2.3.5.25 + U_EMRPOLYBEZIERTO16, //!< EMF manual 2.3.5.19 + U_EMRPOLYLINETO16, //!< EMF manual 2.3.5.27 + *PU_EMRPOLYBEZIER16, //!< EMF manual 2.3.5.17 + *PU_EMRPOLYGON16, //!< EMF manual 2.3.5.23 + *PU_EMRPOLYLINE16, //!< EMF manual 2.3.5.25 + *PU_EMRPOLYBEZIERTO16, //!< EMF manual 2.3.5.19 + *PU_EMRPOLYLINETO16; //!< EMF manual 2.3.5.27 +#define U_SIZE_EMRPOLYBEZIER16 (sizeof(U_EMR) + sizeof(U_RECTL) + sizeof(U_NUM_POINT16)) +#define U_SIZE_EMRPOLYGON16 U_SIZE_EMRPOLYBEZIER16 +#define U_SIZE_EMRPOLYLINE16 U_SIZE_EMRPOLYBEZIER16 +#define U_SIZE_EMRPOLYBEZIERTO16 U_SIZE_EMRPOLYBEZIER16 +#define U_SIZE_EMRPOLYLINETO16 U_SIZE_EMRPOLYBEZIER16 +/* Index 90,91 */ +/** EMF manual 2.3.5.31 + + followed by + U_POINT16 apts[1]; //!< array of point16 +*/ +typedef struct { + U_EMR emr; //!< U_EMR + U_RECTL rclBounds; //!< Bounding rectangle in device units + U_NUM_POLYCOUNTS nPolys; //!< Number of elements in aPolyCounts + U_NUM_POINT16 cpts; //!< Total number of points (over all poly) + U_POLYCOUNTS aPolyCounts[1]; //!< Number of points in each poly (sequential) +} U_EMRPOLYPOLYLINE16, + U_EMRPOLYPOLYGON16, //!< EMF manual 2.3.5.29 + *PU_EMRPOLYPOLYLINE16, //!< EMF manual 2.3.5.31 + *PU_EMRPOLYPOLYGON16; //!< EMF manual 2.3.5.29 +#define U_SIZE_EMRPOLYPOLYLINE16 (sizeof(U_EMR) + sizeof(U_RECTL) + sizeof(U_NUM_POLYCOUNTS) + sizeof(U_NUM_POINT16)) +#define U_SIZE_EMRPOLYPOLYGON16 U_SIZE_EMRPOLYPOLYLINE16 + +/* Index 92 */ +/** EMF manual 2.3.5.21 + + followed by + uint8_t abTypes[1]; //!< Array of Point Enumeration + +*/ +typedef struct { + U_EMR emr; //!< U_EMR + U_RECTL rclBounds; //!< Bounding rectangle in device units + U_NUM_POINT16 cpts; //!< Total number of points (over all poly) + U_POINT16 apts[1]; //!< array of points +} U_EMRPOLYDRAW16, + *PU_EMRPOLYDRAW16; //!< EMF manual 2.3.5.21 +#define U_SIZE_EMRPOLYDRAW16 (sizeof(U_EMR) + sizeof(U_RECTL) + sizeof(U_NUM_POINT16)) + +/* Index 93 */ +/** EMF manual 2.3.7.5 +*/ +typedef struct { + U_EMR emr; //!< U_EMR + uint32_t ihBrush; //!< Index to place object in EMF object table (this entry must not yet exist) + uint32_t iUsage; //!< DIBcolors Enumeration + U_OFFBMI offBmi; //!< Offset in bytes to U_BITMAPINFO (within DIBbitmapbuffer) + U_CBBMI cbBmi; //!< Size in bytes of U_BITMAPINFO + U_OFFBITS offBits; //!< Offset in bytes to the DIB bitmap data (within DIBbitmapbuffer + U_CBBITS cbBits; //!< Size in bytes of DIB bitmap + //!< Record may include optional DIB bitmapbuffer +} U_EMRCREATEMONOBRUSH, + *PU_EMRCREATEMONOBRUSH; //!< EMF manual 2.3.7.5 +#define U_SIZE_EMRCREATEMONOBRUSH (sizeof(U_EMRCREATEMONOBRUSH)) + +/* Index 94 */ +/** EMF manual 2.3.7.4 +*/ +typedef struct { + U_EMR emr; //!< U_EMR + uint32_t ihBrush; //!< Index to place object in EMF object table (this entry must not yet exist) + uint32_t iUsage; //!< DIBcolors Enumeration + U_OFFBMI offBmi; //!< Offset in bytes to U_BITMAPINFO (within DIB bitmapbuffer) + U_CBBMI cbBmi; //!< Size in bytes of U_BITMAPINFO + U_OFFBITS offBits; //!< Offset in bytes to the DIB bitmap data (within DIB bitmapbuffer + U_CBBITS cbBits; //!< Size in bytes of DIB bitmap + //!< Record may include optional DIB bitmapbuffer +} U_EMRCREATEDIBPATTERNBRUSHPT, + *PU_EMRCREATEDIBPATTERNBRUSHPT; //!< EMF manual 2.3.7.4 +#define U_SIZE_EMRCREATEDIBPATTERNBRUSHPT (sizeof(U_EMRCREATEDIBPATTERNBRUSHPT)) + +/* Index 95 */ +/** EMF manual 2.3.7.9 +*/ +typedef struct { + U_EMR emr; //!< U_EMR + uint32_t ihPen; //!< Index to place object in EMF object table (this entry must not yet exist) + U_OFFBMI offBmi; //!< Offset in bytes to U_BITMAPINFO (within DIB bitmapbuffer) + U_CBBMI cbBmi; //!< Size in bytes of U_BITMAPINFO + U_OFFBITS offBits; //!< Offset in bytes to the DIB bitmap data (within DIB bitmapbuffer + U_CBBITS cbBits; //!< Size in bytes of DIB bitmap + U_EXTLOGPEN elp; //!< Pen parameters (Size is Variable!!!!) + //!< Record may include optional DIB bitmap +} U_EMREXTCREATEPEN, + *PU_EMREXTCREATEPEN; //!< EMF manual 2.3.7.9 +#define U_SIZE_EMREXTCREATEPEN (sizeof(U_EMREXTCREATEPEN) - sizeof(U_EXTLOGPEN) + U_SIZE_EXTLOGPEN) + +/* Index 96.97 */ +/** EMF manual 2.3.5.32 +*/ +typedef struct { + U_EMR emr; //!< U_EMR + U_RECTL rclBounds; //!< Bounding rectangle in device units + uint32_t iGraphicsMode; //!< GraphicsMode Enumeration + U_FLOAT exScale; //!< scale to 0.01 mm units ( only if iGraphicsMode & U_GM_COMPATIBLE) + U_FLOAT eyScale; //!< scale to 0.01 mm units ( only if iGraphicsMode & U_GM_COMPATIBLE) + U_NUM_EMRTEXT cStrings; //!< Number of U_EMRTEXT in array + U_EMRTEXT emrtext[1]; //!< Text parameters +} U_EMRPOLYTEXTOUTA, + U_EMRPOLYTEXTOUTW, //!< EMF manual 2.3.5.33 + *PU_EMRPOLYTEXTOUTA, //!< EMF manual 2.3.5.32 + *PU_EMRPOLYTEXTOUTW; //!< EMF manual 2.3.5.33 +#define U_SIZE_EMRPOLYTEXTOUTA (sizeof(U_EMR) + sizeof(U_RECTL) + sizeof(uint32_t) + 2*sizeof(U_FLOAT) + sizeof(U_NUM_EMRTEXT)) +#define U_SIZE_EMRPOLYTEXTOUTW U_SIZE_EMRPOLYTEXTOUTA + +/* Index 98 (see 17) */ + +/* Index 99 */ +/** EMF manual 2.3.7.2 +*/ +typedef struct { + U_EMR emr; //!< U_EMR + uint32_t ihCS; //!< Index to place object in EMF object table (this entry must not yet exist) + U_LOGCOLORSPACEA lcs; //!< ColorSpace parameters +} U_EMRCREATECOLORSPACE, + *PU_EMRCREATECOLORSPACE; //!< EMF manual 2.3.7.2 +#define U_SIZE_EMRCREATECOLORSPACE (sizeof(U_EMRCREATECOLORSPACE)) + +/* Index 100,101 */ +/** EMF manual 2.3.8.2 +*/ +typedef struct { + U_EMR emr; //!< U_EMR + uint32_t ihCS; //!< Index of object in EMF object table +} U_EMRDELETECOLORSPACE, + U_EMRSETCOLORSPACE, //!< EMF manual 2.3.8.7 + *PU_EMRDELETECOLORSPACE, //!< EMF manual 2.3.8.2 + *PU_EMRSETCOLORSPACE; //!< EMF manual 2.3.8.7 +#define U_SIZE_EMRDELETECOLORSPACE (sizeof(U_EMRDELETECOLORSPACE)) +#define U_SIZE_EMRSETCOLORSPACE (sizeof(U_EMRSETCOLORSPACE )) + +/* Index 102 */ +/** EMF manual 2.3.9.2 +*/ +typedef struct { + U_EMR emr; //!< U_EMR + U_CBDATA cbData; //!< Size of OpenGL data in bytes + U_DATA Data[1]; //!< OpenGL data +} U_EMRGLSRECORD, + *PU_EMRGLSRECORD; //!< EMF manual 2.3.9.2 +#define U_SIZE_EMRGLSRECORD (sizeof(U_EMR) + sizeof(U_CBDATA)) + +/* Index 103 */ +/** EMF manual 2.3.9.1 +*/ +typedef struct { + U_EMR emr; //!< U_EMR + U_RECTL rclBounds; //!< Bounding rectangle in device units + U_CBDATA cbData; //!< Size of OpenGL data in bytes + U_DATA Data[1]; //!< OpenGL data +} U_EMRGLSBOUNDEDRECORD, + *PU_EMRGLSBOUNDEDRECORD; //!< EMF manual 2.3.9.1 +#define U_SIZE_EMRGLSBOUNDEDRECORD (sizeof(U_EMR) + sizeof(U_RECTL) + sizeof(U_CBDATA)) + +/* Index 104 */ +/** EMF manual 2.3.11.5 +*/ +typedef struct { + U_EMR emr; //!< U_EMR + U_PIXELFORMATDESCRIPTOR pfd; //!< PixelFormatDescriptor +} U_EMRPIXELFORMAT, + *PU_EMRPIXELFORMAT; //!< EMF manual 2.3.11.5 +#define U_SIZE_EMRPIXELFORMAT (sizeof(U_EMRPIXELFORMAT)) + +/* Index 105 */ +/** EMF manual 2.3.6.1 +*/ +typedef struct { + U_EMR emr; //!< U_EMR + U_CBDATA cjIn; //!< Number of bytes to send to printer driver + U_DATA Data[1]; //!< Data to send +} U_EMRDRAWESCAPE, + *PU_EMRDRAWESCAPE; //!< EMF manual 2.3.6.1 +#define U_SIZE_EMRDRAWESCAPE (sizeof(U_EMR) + sizeof(U_CBDATA)) + +/* Index 106 */ +/** EMF manual 2.3.6.2 +*/ +typedef struct { + U_EMR emr; //!< U_EMR + U_CBDATA cjIn; //!< Number of bytes to send to printer driver + U_DATA Data[1]; //!< Data to send +} U_EMREXTESCAPE, + *PU_EMREXTESCAPE; //!< EMF manual 2.3.6.2 +#define U_SIZE_EMREXTESCAPE (sizeof(U_EMR) + sizeof(U_CBDATA)) + +/* Index 107 (not implemented ) */ + +/* Index 108 */ +/** EMF manual 2.3.5.37 +*/ +typedef struct { + U_EMR emr; //!< U_EMR + U_POINTL Dest; //!< Where to draw the text + U_NUM_STR cChars; //!< Characters in TextString (not null terminated) + uint32_t fuOptions; //!< ExtTextOutOptions Enumeration + uint32_t iGraphicsMode; //!< GraphicsMode Enumeration + U_FLOAT exScale; //!< scale on X axis + U_FLOAT eyScale; //!< scale on Y axis +//!< the tail end of this record is variable. +//!< U_RECTL rclBounds; Record may include optional Bounding rectangle (absent when: fuOPtions & ETO_NO_U_RECT) +//!< uint32_t TextString; text to output (fuOptions & ETO_SMALL_CHARS ? 8 bit : 16 bit) +} U_EMRSMALLTEXTOUT, + *PU_EMRSMALLTEXTOUT; //!< EMF manual 2.3.5.37 +#define U_SIZE_EMRSMALLTEXTOUT (sizeof(U_EMRSMALLTEXTOUT)) + +/* Index 109 (not implemented ) +EMF manual 2.3.11.2 +*/ + +/* Index 110 */ +/** EMF manual 2.3.6.3 + + followed by + uint8_t Data[1]; //!< Data for printer driver +*/ +typedef struct { + U_EMR emr; //!< U_EMR + U_CBDATA cbDriver; //!< Number of bytes in driver name (note, BYTES, not CHARACTERS) + U_CBDATA cbData; //!< Number of bytes in data + uint16_t Driver[1]; //!< Driver name in uint16_t characters, null terminated +} U_EMRNAMEDESCAPE, + *PU_EMRNAMEDESCAPE; //!< EMF manual 2.3.6.3 +#define U_SIZE_EMRNAMEDESCAPE (sizeof(U_EMR) + 2*sizeof(U_CBDATA)) + +/* Index 111-113 (not implemented ) + EMF manual 2.3.8.1 + EMF manual 2.3.11.15 + EMF manual 2.3.11.16 +*/ + +/* Index 114 */ +/** EMF manual 2.3.1.1 +*/ +typedef struct { + U_EMR emr; //!< U_EMR + U_RECTL rclBounds; //!< Bounding rectangle in device units + U_POINTL Dest; //!< Destination UL corner in logical units + U_POINTL cDest; //!< Destination W & H in logical units + U_BLEND Blend; //!< Blend Function + U_POINTL Src; //!< Source UL corner in logical units + U_XFORM xformSrc; //!< Transform to apply to source + U_COLORREF crBkColorSrc; //!< Background color + uint32_t iUsageSrc; //!< DIBcolors Enumeration + U_OFFBMISRC offBmiSrc; //!< Offset in bytes to U_BITMAPINFO (within bitmapbuffer) + U_CBBMISRC cbBmiSrc; //!< Size in bytes of U_BITMAPINFO + U_OFFBITSSRC offBitsSrc; //!< Offset in bytes to the bitmap (within bitmapbuffer) + U_CBBITS cbBitsSrc; //!< Size in bytes of bitmap + U_POINTL cSrc; //!< Source W & H in logical units + //!< Record may include optional DIB bitmap +} U_EMRALPHABLEND, + *PU_EMRALPHABLEND; //!< EMF manual 2.3.1.1 +#define U_SIZE_EMRALPHABLEND (sizeof(U_EMRALPHABLEND)) + +/* Index 115 (see 17) */ + +/* Index 116 */ +/** EMF manual 2.3.1.8 +*/ +typedef struct { + U_EMR emr; //!< U_EMR + U_RECTL rclBounds; //!< Bounding rectangle in device units + U_POINTL Dest; //!< Destination UL corner in logical units + U_POINTL cDest; //!< Destination W & H in logical units + uint32_t TColor; //!< Bitmap color to be treated as transparent + U_POINTL Src; //!< Source UL corner in logical units + U_XFORM xformSrc; //!< Transform to apply to source + U_COLORREF crBkColorSrc; //!< Background color + uint32_t iUsageSrc; //!< DIBcolors Enumeration + U_OFFBMISRC offBmiSrc; //!< Offset in bytes to U_BITMAPINFO (within bitmapbuffer) + U_CBBMISRC cbBmiSrc; //!< Size in bytes of U_BITMAPINFO + U_OFFBITSSRC offBitsSrc; //!< Offset in bytes to the bitmap (within bitmapbuffer) + U_CBBITS cbBitsSrc; //!< Size in bytes of bitmap + U_POINTL cSrc; //!< Source W & H in logical units + //!< Record may includes optional bitmapbuffer +} U_EMRTRANSPARENTBLT, + *PU_EMRTRANSPARENTBLT; //!< EMF manual 2.3.1.8 +#define U_SIZE_EMRTRANSPARENTBLT (sizeof(U_EMRTRANSPARENTBLT)) + +/* Index 117 (not a defined U_EMR record type ) */ + +/* Index 118 */ +/** EMF manual 2.3.5.12 + + followed by + U_TRIVERTEX TriVert[1]; Array of TriVertex objects + uint32_t GradObj[1]; Array of gradient objects (each has 2 or 3 indices into TriVert array) +*/ +typedef struct { + U_EMR emr; //!< U_EMR + U_RECTL rclBounds; //!< Bounding rectangle in device units + U_NUM_TRIVERTEX nTriVert; //!< Number of TriVertex objects + U_NUM_GRADOBJ nGradObj; //!< Number of gradient triangle/rectangle objects + uint32_t ulMode; //!< Gradientfill Enumeration (determines Triangle/Rectangle) +} U_EMRGRADIENTFILL, + *PU_EMRGRADIENTFILL; //!< EMF manual 2.3.5.12 +#define U_SIZE_EMRGRADIENTFILL (sizeof(U_EMRGRADIENTFILL)) + +/* Index 119,120 (not implemented ) +EMF manual 2.3.11.18 +EMF manual 2.3.11.27 +*/ + +/* Index 121 */ +/** EMF manual 2.3.11.1 +*/ +typedef struct { + U_EMR emr; //!< U_EMR + uint32_t dwAction; //!< ColorSpace Enumeration + uint32_t dwFlags; //!< ColorMatchToTarget Enumeration + U_CBNAME cbName; //!< Number of bytes in UTF16 name of the color profile + U_CBDATA cbData; //!< Number of bytes of the target profile + uint8_t Data[1]; //!< Data of size cbName+cbData: Name in UTF16 then color profile data +} U_EMRCOLORMATCHTOTARGETW, + *PU_EMRCOLORMATCHTOTARGETW; //!< EMF manual 2.3.11.1 +#define U_SIZE_EMRCOLORMATCHTOTARGETW (sizeof(U_EMR) + 2*sizeof(uint32_t) + sizeof(U_CBNAME) + sizeof(U_CBDATA)) + +/* Index 122 */ +/** EMF manual 2.3.7.3 +*/ +typedef struct { + U_EMR emr; //!< U_EMR + uint32_t ihCS; //!< Index of the logical color space object in the EMF object table + U_LOGCOLORSPACEW lcs; //!< Description of the color profile + uint32_t dwFlags; //!< If low bit set Data is present + U_CBDATA cbData; //!< Number of bytes of theData field. + uint8_t Data[1]; //!< (Optional, dwFlags & 1) color profile data +} U_EMRCREATECOLORSPACEW, + *PU_EMRCREATECOLORSPACEW; //!< EMF manual 2.3.7.3 +#define U_SIZE_EMRCREATECOLORSPACEW (sizeof(U_EMR) + 2*sizeof(uint32_t) + sizeof(U_LOGCOLORSPACEW) + sizeof(U_CBDATA)) + +// records which are not documented, so we have no idea what to do with them +#define U_SIZE_EMRUNDEFINED 2048 + +// ************************************************************************************************ +// Utility function structures + +/** + Storage for keeping track of properties of the growing EMF file as records are added. +*/ +typedef struct { + FILE *fp; //!< Open file + size_t allocated; //!< Size of the buffer + size_t used; //!< Amount consumed + uint32_t records; //!< Number of records already contained + uint16_t ignore; //!< size padding,not used + uint32_t PalEntries; //!< Number of PalEntries (set from U_EMREOF) + uint32_t chunk; //!< Number of bytes to add when more space is needed + char *buf; //!< Buffer for constructing the EMF in memory +} EMFTRACK; + +/** + The various create functions need a place to put their handles, these are stored in the table below. + We don't actually do anything much with these handles, that is up to whatever program finally plays back the EMF, but + we do need to keep track of the numbers so that they are not accidentally reused. This structure is used for that, + and all *_set functions that touch a handle reference it. + + Stock objects are not used in this limited model, so libUEMF cannot detect if a handle is still in use. Nor can it + tell when a handle has been deselected (by selecting another handle for the same type of graphic object, and thus + made deleteable). End user code must keep track of this for itself. +*/ +typedef struct { + uint32_t *table; //!< Array Buffer for constructing the EMF in memory + uint32_t *stack; //!< handles are either on the stack or in the table + size_t allocated; //!< Slots in the buffer + size_t chunk; //!< Number to add if a realloc is required + uint32_t sptr; //!< Pointer to next available handle in the stack + uint32_t top; //!< Highest slot occupied (currently) + uint32_t peak; //!< Highest slot occupied (ever) +} EMFHANDLES; + +/** + 2 x 2 matrix, used by xform_alt_set() function. +*/ +typedef struct { + double M11; //!< Matrix element 1,1 + double M12; //!< Matrix element 1,2 + double M21; //!< Matrix element 2,1 + double M22; //!< Matrix element 2,2 +} U_MAT2X2, + *PU_MAT2X2; //!< 2 x 2 matrix, used by xform_alt_set() function. + +// ************************************************************************************************ +// Prototypes + +//! \cond +int memprobe(const void *buf, size_t size); +void wchar8show(const char *src); +void wchar16show(const uint16_t *src); +void wchar32show(const uint32_t *src); +void wchartshow(const wchar_t *src); +void dumpeht(char *string, unsigned int *handle, EMFHANDLES *eht); + + +char *U_emr_names(unsigned int idx); +uint32_t *dx_set(int32_t height, uint32_t weight, uint32_t members); +uint32_t emr_properties(uint32_t type); +int emr_arc_points(PU_ENHMETARECORD record, int *f1, int f2, PU_PAIRF center, PU_PAIRF start, PU_PAIRF end, PU_PAIRF size); +int emr_arc_points_common(PU_RECTL rclBox, PU_POINTL ArcStart, PU_POINTL ArcEnd, + int *f1, int f2, PU_PAIRF center, PU_PAIRF start, PU_PAIRF end, PU_PAIRF size); +int get_real_color_count(const char *Bmih); +int get_real_color_icount(int Colors, int BitCount, int Width, int Height); +int RGBA_to_DIB(char **px, uint32_t *cbPx, PU_RGBQUAD *ct, int *numCt, + const char *rgba_px, int w, int h, int stride, uint32_t colortype, int use_ct, int invert); +int get_DIB_params( const char *record, uint32_t offBitsSrc, uint32_t offBmiSrc, + const char **px, const U_RGBQUAD **ct, uint32_t *numCt, + uint32_t *width, uint32_t *height, uint32_t *colortype, uint32_t *invert ); +int DIB_to_RGBA(const char *px, const U_RGBQUAD *ct, int numCt, + char **rgba_px, int w, int h, uint32_t colortype, int use_ct, int invert); +char *RGBA_to_RGBA(char *rgba_px, int w, int h, int sl, int st, int *ew, int *eh); + +int device_size(const int xmm, const int ymm, const float dpmm, U_SIZEL *szlDev, U_SIZEL *szlMm); +int drawing_size(const int xmm, const int yum, const float dpmm, U_RECTL *rclBounds, U_RECTL *rclFrame); + +int emf_start(const char *name, const uint32_t initsize, const uint32_t chunksize, EMFTRACK **et); +int emf_finish(EMFTRACK *et, EMFHANDLES *eht); +int emf_free(EMFTRACK **et); +int emf_append(U_ENHMETARECORD *rec, EMFTRACK *et, int freerec); +int emf_readdata(const char *filename, char **contents, size_t *length); +FILE *emf_fopen(const char *filename, const int mode); + + +/* use these instead*/ +int emf_htable_create(uint32_t initsize, uint32_t chunksize, EMFHANDLES **eht); +int emf_htable_delete(uint32_t *ih, EMFHANDLES *eht); +int emf_htable_insert(uint32_t *ih, EMFHANDLES *eht); +int emf_htable_free(EMFHANDLES **eht); +/* Deprecated forms */ +#define htable_create emf_htable_create +#define htable_delete emf_htable_delete +#define htable_insert emf_htable_insert +#define htable_free emf_htable_free + +U_RECTL rectl_set(U_POINTL ul, U_POINTL lr); +void rectli_set(PU_RECTL array, int index, U_POINTL ul, U_POINTL lr); +U_SIZEL sizel_set(int32_t x, int32_t y); +U_POINTL point32_set(int32_t x, int32_t y); +#define point_set point32_set +#define pointl_set point32_set +U_POINT16 point16_set(int16_t x, int16_t y); +U_PANOSE panose_set(uint8_t bFamilyType, uint8_t bSerifStyle, uint8_t bWeight, uint8_t bProportion, + uint8_t bContrast, uint8_t bStrokeVariation, uint8_t bArmStyle, uint8_t bLetterform, + uint8_t bMidline, uint8_t bXHeight ); +U_COLORREF colorref3_set(uint8_t red, uint8_t green, uint8_t blue); +U_COLORREF colorref4_set(uint8_t red, uint8_t green, uint8_t blue, uint8_t reserved); +U_RGBQUAD rgbquad_set(uint8_t red,uint8_t green, uint8_t blue, uint8_t reserved); +U_LOGBRUSH logbrush_set(uint32_t lbStyle, U_COLORREF lbColor, int32_t lbHatch); +U_XFORM xform_set(U_FLOAT eM11, U_FLOAT eM12, U_FLOAT eM21, U_FLOAT eM22, U_FLOAT eDx, U_FLOAT eDy); +U_XFORM xform_alt_set(U_FLOAT scale, U_FLOAT ratio, U_FLOAT rot, U_FLOAT axisrot, U_FLOAT eDx, U_FLOAT eDy); +U_LOGPEN logpen_set( uint32_t lopnStyle, U_POINT lopnWidth, U_COLORREF lopnColor ); +PU_EXTLOGPEN extlogpen_set(uint32_t elpPenStyle, uint32_t elpWidth, uint32_t elpBrushStyle, + U_COLORREF elpColor, int32_t elpHatch, U_NUM_STYLEENTRY elpNumEntries, U_STYLEENTRY *elpStyleEntry ); +U_LOGFONT_PANOSE logfont_panose_set(U_LOGFONT elfLogFont, uint16_t *elfFullName, + uint16_t *elfStyle, uint32_t elfStyleSize, U_PANOSE elfPanose); +U_LOGFONT logfont_set( int32_t lfHeight, int32_t lfWidth, int32_t lfEscapement, int32_t lfOrientation, + int32_t lfWeight, uint8_t lfItalic, uint8_t lfUnderline, uint8_t lfStrikeOut, + uint8_t lfCharSet, uint8_t lfOutPrecision, uint8_t lfClipPrecision, + uint8_t lfQuality, uint8_t lfPitchAndFamily, uint16_t *lfFaceName); +char *emrtext_set(U_POINTL ptlReference, U_NUM_STR NumString, uint32_t cbChar, void *String, uint32_t fOptions, U_RECTL rcl, uint32_t *Dx); +U_LOGPLTNTRY logpltntry_set(uint8_t peReserved,uint8_t peRed,uint8_t peGreen,uint8_t peBlue); +PU_LOGPALETTE logpalette_set(U_NUM_LOGPLTNTRY palNumEntries,PU_LOGPLTNTRY *palPalEntry); +U_RGNDATAHEADER rgndataheader_set( U_NUM_RECTL nCount, U_RECTL rcBound); +PU_RGNDATA rgndata_set( U_RGNDATAHEADER rdh, PU_RECTL Buffer); +U_BITMAPINFOHEADER bitmapinfoheader_set(int32_t biWidth, int32_t biHeight, + uint16_t biPlanes, uint16_t biBitCount, uint32_t biCompression, + uint32_t biSizeImage, int32_t biXPelsPerMeter, + int32_t biYPelsPerMeter, U_NUM_RGBQUAD biClrUsed, uint32_t biClrImportant); +PU_BITMAPINFO bitmapinfo_set(U_BITMAPINFOHEADER BmiHeader, PU_RGBQUAD BmiColors); +U_LOGCOLORSPACEA logcolorspacea_set(int32_t lcsCSType, int32_t lcsIntent, + U_CIEXYZTRIPLE lcsEndpoints, U_LCS_GAMMARGB lcsGammaRGB, char *lcsFilename); +U_LOGCOLORSPACEW logcolorspacew_set(int32_t lcsCSType, int32_t lcsIntent, + U_CIEXYZTRIPLE lcsEndpoints, U_LCS_GAMMARGB lcsGammaRGB, uint16_t *lcsFilename); +U_COLORADJUSTMENT coloradjustment_set(uint16_t Size, uint16_t Flags, uint16_t IlluminantIndex, + uint16_t RedGamma, uint16_t GreenGamma, uint16_t BlueGamma, + uint16_t ReferenceBlack, uint16_t ReferenceWhite, + int16_t Contrast, int16_t Brightness, int16_t Colorfulness, int16_t RedGreenTint); +U_PIXELFORMATDESCRIPTOR pixelformatdescriptor_set( uint32_t dwFlags, uint8_t iPixelType, uint8_t cColorBits, + uint8_t cRedBits, uint8_t cRedShift, + uint8_t cGreenBits, uint8_t cGreenShift, + uint8_t cBlueBits, uint8_t cBlueShift, + uint8_t cAlphaBits, uint8_t cAlphaShift, + uint8_t cAccumBits, uint8_t cAccumRedBits, uint8_t cAccumGreenBits, uint8_t cAccumBlueBits, + uint8_t cAccumAlphaBits, uint8_t cDepthBits, uint8_t cStencilBits, + uint8_t cAuxBuffers, uint8_t iLayerType, uint8_t bReserved, uint32_t dwLayerMask, + uint32_t dwVisibleMask, uint32_t dwDamageMask); + +PU_POINT points_transform(PU_POINT points, int count, U_XFORM xform); +PU_POINT16 point16_transform(PU_POINT16 points, int count, U_XFORM xform); +PU_TRIVERTEX trivertex_transform(PU_TRIVERTEX tv, int count, U_XFORM xform); +PU_POINT point16_to_point(PU_POINT16 points, int count); +PU_POINT16 point_to_point16(PU_POINT points, int count); + +U_RECT findbounds(uint32_t count, PU_POINT pts, uint32_t width); +U_RECT findbounds16(uint32_t count, PU_POINT16 pts, uint32_t width); +char *emr_dup(const char *emr); + +char *textcomment_set(const char *string); + +// These generate the handle and then call the underlying function +char *deleteobject_set(uint32_t *ihObject, EMFHANDLES *eht); +char *selectobject_set(uint32_t ihObject, EMFHANDLES *eht); +char *createpen_set(uint32_t *ihPen, EMFHANDLES *eht, U_LOGPEN lopn ); +char *extcreatepen_set(uint32_t *ihPen, EMFHANDLES *eht, + PU_BITMAPINFO Bmi, const uint32_t cbPx, char *Px, PU_EXTLOGPEN elp); +char *createbrushindirect_set(uint32_t *ihBrush, EMFHANDLES *eht, U_LOGBRUSH lb ); +char *createdibpatternbrushpt_set(uint32_t *ihBrush, EMFHANDLES *eht, uint32_t iUsage, + PU_BITMAPINFO Bmi, const uint32_t cbPx, const char *Px); +char *createmonobrush_set(uint32_t *ihBrush, EMFHANDLES *eht, uint32_t iUsage, + PU_BITMAPINFO Bmi, const uint32_t cbPx, const char *Px); +char *extcreatefontindirectw_set(uint32_t *ihFont, EMFHANDLES *eht, const char *elf, const char *elfw); +char *createpalette_set(uint32_t *ihPal, EMFHANDLES *eht, U_LOGPALETTE lgpl); +char *setpaletteentries_set(uint32_t *ihPal, EMFHANDLES *eht, uint32_t iStart, U_NUM_LOGPLTNTRY cEntries, PU_LOGPLTNTRY aPalEntries); +char *fillrgn_set(uint32_t *ihBrush, EMFHANDLES *eht, U_RECTL rclBounds,PU_RGNDATA RgnData); +char *framergn_set(uint32_t *ihBrush, EMFHANDLES *eht, U_RECTL rclBounds, U_SIZEL szlStroke, PU_RGNDATA RgnData); +char *createcolorspace_set(uint32_t *ihCS, EMFHANDLES *eht, U_LOGCOLORSPACEA lcs); +char *createcolorspacew_set(uint32_t *ihCS, EMFHANDLES *eht, U_LOGCOLORSPACEW lcs, uint32_t dwFlags, U_CBDATA cbData, uint8_t *Data); + +char *U_EMRHEADER_set( const U_RECTL rclBounds, const U_RECTL rclFrame, U_PIXELFORMATDESCRIPTOR* const pfmtDesc, + U_CBSTR nDesc, uint16_t* const Description, const U_SIZEL szlDevice, const U_SIZEL szlMillimeters, + const uint32_t bOpenGL); +char *U_EMRPOLYBEZIER_set( const U_RECTL rclBounds, const uint32_t count, const U_POINTL *points); +char *U_EMRPOLYGON_set( const U_RECTL rclBounds, const uint32_t count, const U_POINTL *points); +char *U_EMRPOLYLINE_set( const U_RECTL rclBounds, const uint32_t count, const U_POINTL *points); +char *U_EMRPOLYBEZIERTO_set(const U_RECTL rclBounds, const uint32_t count, const U_POINTL *points); +char *U_EMRPOLYLINETO_set( const U_RECTL rclBounds, const uint32_t count, const U_POINTL *points); + +char *U_EMRPOLYPOLYLINE_set(const U_RECTL rclBounds, const uint32_t nPolys, const uint32_t *aPolyCounts, + const uint32_t cptl, const U_POINTL *points); +char *U_EMRPOLYPOLYGON_set(const U_RECTL rclBounds, const uint32_t nPolys, const uint32_t *aPolyCounts, + const uint32_t cptl, const U_POINTL *points); +char *U_EMRSETWINDOWEXTEX_set(const U_SIZEL szlExtent); +char *U_EMRSETWINDOWORGEX_set(const U_POINTL ptlOrigin); +char *U_EMRSETVIEWPORTEXTEX_set(const U_SIZEL szlExtent); +char *U_EMRSETVIEWPORTORGEX_set(const U_POINTL ptlOrigin); +char *U_EMRSETBRUSHORGEX_set(const U_POINTL ptlOrigin); +char *U_EMREOF_set(const U_CBPLENTRIES cbPalEntries, const PU_LOGPLTNTRY PalEntries, EMFTRACK *et); +char *U_EMRSETPIXELV_set(const U_POINTL ptlPixel, const U_COLORREF crColor); +char *U_EMRSETMAPPERFLAGS_set(void); +char *U_EMRSETMAPMODE_set(const uint32_t iMode); +char *U_EMRSETBKMODE_set(const uint32_t iMode); +char *U_EMRSETPOLYFILLMODE_set(const uint32_t iMode); +char *U_EMRSETROP2_set(const uint32_t iMode); +char *U_EMRSETSTRETCHBLTMODE_set(const uint32_t iMode); +char *U_EMRSETTEXTALIGN_set(const uint32_t iMode); +char *U_EMRSETCOLORADJUSTMENT_set(const U_COLORADJUSTMENT ColorAdjustment); +char *U_EMRSETTEXTCOLOR_set(const U_COLORREF crColor); +char *U_EMRSETBKCOLOR_set(const U_COLORREF crColor); +char *U_EMROFFSETCLIPRGN_set(const U_POINTL ptl); +char *U_EMRMOVETOEX_set(const U_POINTL ptl); +char *U_EMRSETMETARGN_set(void); +char *U_EMREXCLUDECLIPRECT_set(const U_RECTL rclClip); +char *U_EMRINTERSECTCLIPRECT_set(const U_RECTL rclClip); +char *U_EMRSCALEVIEWPORTEXTEX_set(const int32_t xNum, const int32_t xDenom, const int32_t yNum, const int32_t yDenom); +char *U_EMRSCALEWINDOWEXTEX_set(const int32_t xNum, const int32_t xDenom, const int32_t yNum, const int32_t yDenom); +char *U_EMRSAVEDC_set(void); +char *U_EMRRESTOREDC_set(const int32_t iRelative); +char *U_EMRSETWORLDTRANSFORM_set(const U_XFORM xform); +char *U_EMRMODIFYWORLDTRANSFORM_set(const U_XFORM xform, const uint32_t iMode); +char *U_EMRSELECTOBJECT_set(const uint32_t ihObject); // better to call selectobject_set() +char *U_EMRCREATEPEN_set(const uint32_t ihPen, const U_LOGPEN lopn ); +char *U_EMRCREATEBRUSHINDIRECT_set(const uint32_t ihBrush, const U_LOGBRUSH lb); +char *U_EMRDELETEOBJECT_set(const uint32_t ihObject); // better to call deleteobject_set() +char *U_EMRANGLEARC_set(const U_POINTL ptlCenter, const uint32_t nRadius, const U_FLOAT eStartAngle, const U_FLOAT eSweepAngle); +char *U_EMRELLIPSE_set(const U_RECTL rclBox); +char *U_EMRRECTANGLE_set(const U_RECTL rclBox); +char *U_EMRROUNDRECT_set(const U_RECTL rclBox, const U_SIZEL szlCorner); +char *U_EMRARC_set(const U_RECTL rclBox, const U_POINTL ptlStart, const U_POINTL ptlEnd); +char *U_EMRCHORD_set(const U_RECTL rclBox, const U_POINTL ptlStart, const U_POINTL ptlEnd); +char *U_EMRPIE_set(const U_RECTL rclBox, const U_POINTL ptlStart, const U_POINTL ptlEnd); +char *U_EMRSELECTPALETTE_set(const uint32_t ihPal); +char *U_EMRCREATEPALETTE_set(const uint32_t ihPal, const U_LOGPALETTE lgpl); +char *U_EMRSETPALETTEENTRIES_set(const uint32_t ihPal, const uint32_t iStart, const U_NUM_LOGPLTNTRY cEntries, const PU_LOGPLTNTRY aPalEntries); +char *U_EMRRESIZEPALETTE_set(const uint32_t ihPal, const uint32_t cEntries); +char *U_EMRREALIZEPALETTE_set(void); +char *U_EMREXTFLOODFILL_set(const U_POINTL ptlStart, const U_COLORREF crColor, const uint32_t iMode); +char *U_EMRLINETO_set(const U_POINTL ptl); +char *U_EMRARCTO_set(const U_RECTL rclBox, const U_POINTL ptlStart, const U_POINTL ptlEnd); +char *U_EMRPOLYDRAW_set(const U_RECTL rclBounds,const U_NUM_POINTL cptl,const U_POINTL *aptl,const uint8_t *abTypes); +char *U_EMRSETARCDIRECTION_set(const uint32_t iArcDirection); +char *U_EMRSETMITERLIMIT_set(const uint32_t eMiterLimit); +char *U_EMRBEGINPATH_set(void); +char *U_EMRENDPATH_set(void); +char *U_EMRCLOSEFIGURE_set(void); +char *U_EMRFILLPATH_set(const U_RECTL rclBox); +char *U_EMRSTROKEANDFILLPATH_set(const U_RECTL rclBox); +char *U_EMRSTROKEPATH_set(const U_RECTL rclBox); +char *U_EMRFLATTENPATH_set(void); +char *U_EMRWIDENPATH_set(void); +char *U_EMRSELECTCLIPPATH_set(const uint32_t iMode); +char *U_EMRABORTPATH_set(void); +// EMR_ENDEF69 +char *U_EMRCOMMENT_set(const U_CBDATA cbData, const char *Data); +char *U_EMRFILLRGN_set(const U_RECTL rclBounds, const uint32_t ihBrush, const PU_RGNDATA RgnData); +char *U_EMRFRAMERGN_set(const U_RECTL rclBounds, const uint32_t ihBrush, const U_SIZEL szlStroke, const PU_RGNDATA RgnData); +char *U_EMRINVERTRGN_set(const PU_RGNDATA RgnData); +char *U_EMRPAINTRGN_set(const PU_RGNDATA RgnData); +char *U_EMREXTSELECTCLIPRGN_set(const uint32_t iMode, const PU_RGNDATA RgnData); +char *U_EMRBITBLT_set(const U_RECTL rclBounds, const U_POINTL Dest, const U_POINTL cDest, + const U_POINTL Src, const U_XFORM xformSrc, const U_COLORREF crBkColorSrc, + const uint32_t iUsageSrc, const uint32_t dwRop, + const PU_BITMAPINFO Bmi, const uint32_t cbPx, char *Px); +char *U_EMRSTRETCHBLT_set(U_RECTL rclBounds, U_POINTL Dest, U_POINTL cDest, + const U_POINTL Src, const U_POINTL cSrc, const U_XFORM xformSrc, const U_COLORREF crBkColorSrc, const uint32_t iUsageSrc, + const uint32_t dwRop, + const PU_BITMAPINFO Bmi, const uint32_t cbPx, char *Px); +char *U_EMRMASKBLT_set(U_RECTL rclBounds, U_POINTL Dest, U_POINTL cDest, + const U_POINTL Src, const U_XFORM xformSrc, const U_COLORREF crBkColorSrc, const uint32_t iUsageSrc, + const U_POINTL Mask, const uint32_t iUsageMask, + const uint32_t dwRop, + const PU_BITMAPINFO Bmi, const uint32_t cbPx, char *Px, + const PU_BITMAPINFO BmiMsk, const uint32_t cbMsk, char *Msk); +char *U_EMRPLGBLT_set(const U_RECTL rclBounds, const PU_POINTL aptlDst, + const U_POINTL Src, const U_POINTL cSrc, const U_XFORM xformSrc, const U_COLORREF crBkColorSrc, const uint32_t iUsageSrc, + const U_POINTL Mask, const uint32_t iUsageMask, + const PU_BITMAPINFO Bmi, const uint32_t cbPx, char *Px, + const PU_BITMAPINFO BmiMsk, const uint32_t cbMsk, char *Msk); +char *U_EMRSETDIBITSTODEVICE_set(const U_RECTL rclBounds, const U_POINTL Dest, + const U_POINTL Src, const U_POINTL cSrc, const uint32_t iUsageSrc, + const uint32_t iStartScan, const uint32_t cScans, + const PU_BITMAPINFO Bmi, const uint32_t cbPx, char *Px); +char *U_EMRSTRETCHDIBITS_set(const U_RECTL rclBounds, const U_POINTL Dest, const U_POINTL cDest, + const U_POINTL Src, const U_POINTL cSrc, const uint32_t iUsageSrc, + const uint32_t dwRop, + const PU_BITMAPINFO Bmi, const uint32_t cbPx, char *Px); +char *U_EMREXTCREATEFONTINDIRECTW_set( uint32_t ihFont, const char *elf, const char *elfw); +char *U_EMREXTTEXTOUTA_set(U_RECTL rclBounds, uint32_t iGraphicsMode, U_FLOAT exScale, U_FLOAT eyScale, PU_EMRTEXT emrtext); +char *U_EMREXTTEXTOUTW_set(U_RECTL rclBounds, uint32_t iGraphicsMode, U_FLOAT exScale, U_FLOAT eyScale, PU_EMRTEXT emrtext); +char *U_EMRPOLYBEZIER16_set(const U_RECTL rclBounds, const uint32_t cpts, const U_POINT16 *points); +char *U_EMRPOLYGON16_set(const U_RECTL rclBounds, const uint32_t cpts, const U_POINT16 *points); +char *U_EMRPOLYLINE16_set(const U_RECTL rclBounds, const uint32_t cpts, const U_POINT16 *points); +char *U_EMRPOLYBEZIERTO16_set(const U_RECTL rclBounds, const uint32_t cpts, const U_POINT16 *points); +char *U_EMRPOLYLINETO16_set(const U_RECTL rclBounds, const uint32_t cpts, const U_POINT16 *points); +char *U_EMRPOLYPOLYLINE16_set(const U_RECTL rclBounds, const uint32_t nPolys, const uint32_t *aPolyCounts,const uint32_t cpts, const U_POINT16 *points); +char *U_EMRPOLYPOLYGON16_set(const U_RECTL rclBounds, const uint32_t nPolys, const uint32_t *aPolyCounts,const uint32_t cpts, const U_POINT16 *points); +char *U_EMRPOLYDRAW16_set(const U_RECTL rclBounds,const U_NUM_POINT16 cpts, const U_POINT16 *aptl, const uint8_t *abTypes); +char *U_EMRCREATEMONOBRUSH_set(const uint32_t ihBrush, const uint32_t iUsage, + const PU_BITMAPINFO Bmi, const uint32_t cbPx, const char *Px); +char *U_EMRCREATEDIBPATTERNBRUSHPT_set(const uint32_t ihBrush, const uint32_t iUsage, + const PU_BITMAPINFO Bmi, const uint32_t cbPx, const char *Px); +char *U_EMREXTCREATEPEN_set(const uint32_t ihPen, const PU_BITMAPINFO Bmi, const uint32_t cbPx, char *Px, const PU_EXTLOGPEN elp ); +// U_EMRPOLYTEXTOUTA_set 96 NOT IMPLEMENTED, denigrated after Windows NT +// U_EMRPOLYTEXTOUTW_set 97 NOT IMPLEMENTED, denigrated after Windows NT +char *U_EMRSETICMMODE_set(const uint32_t iMode); +char *U_EMRCREATECOLORSPACE_set(const uint32_t ihCS, const U_LOGCOLORSPACEA lcs); +char *U_EMRSETCOLORSPACE_set(const uint32_t ihCS ); +char *U_EMRDELETECOLORSPACE_set(const uint32_t ihCS); +// U_EMRGLSRECORD_set 102 Not implemented +// U_EMRGLSBOUNDEDRECORD_set 103 Not implemented +char *U_EMRPIXELFORMAT_set(const U_PIXELFORMATDESCRIPTOR pfd); +char *U_EMRSMALLTEXTOUT_set(const U_POINTL Dest, const U_NUM_STR cChars, const uint32_t fuOptions, const uint32_t iGraphicsMode, + const U_FLOAT exScale, const U_FLOAT eyScale, const U_RECTL rclBounds, const char *TextString); +// U_EMRDRAWESCAPE_set 105 Not implemented +// U_EMREXTESCAPE_set 106 Not implemented +// U_EMRUNDEF107_set 107 Not implemented +// U_EMRSMALLTEXTOUT_set 108 +// U_EMRFORCEUFIMAPPING_set 109 Not implemented +// U_EMRNAMEDESCAPE_set 110 Not implemented +// U_EMRCOLORCORRECTPALETTE_set 111 Not implemented +// U_EMRSETICMPROFILEA_set 112 Not implemented +// U_EMRSETICMPROFILEW_set 113 Not implemented + + +char *U_EMRALPHABLEND_set(const U_RECTL rclBounds, const U_POINTL Dest, const U_POINTL cDest, + const U_POINTL Src, const U_POINTL cSrc, const U_XFORM xformSrc, + const U_COLORREF crBkColorSrc, const uint32_t iUsageSrc, + const U_BLEND Blend, + const PU_BITMAPINFO Bmi, const uint32_t cbPx, char *Px); +char *U_EMRSETLAYOUT_set(const uint32_t iMode); +char *U_EMRTRANSPARENTBLT_set(const U_RECTL rclBounds, const U_POINTL Dest, const U_POINTL cDest, + const U_POINTL Src, const U_POINTL cSrc, const U_XFORM xformSrc, + const U_COLORREF crBkColorSrc, const uint32_t iUsageSrc, const uint32_t TColor, + const PU_BITMAPINFO Bmi, const uint32_t cbPx, char *Px); +// U_EMRUNDEF117_set 117 Not implemented +char *U_EMRGRADIENTFILL_set(const U_RECTL rclBounds, const U_NUM_TRIVERTEX nTriVert, const U_NUM_GRADOBJ nGradObj, + const uint32_t ulMode, const PU_TRIVERTEX TriVert, const uint32_t *GradObj ); +// U_EMRSETLINKEDUFIS_set 119 Not implemented +// U_EMRSETTEXTJUSTIFICATION_set 120 Not implemented (denigrated) +// U_EMRCOLORMATCHTOTARGETW_set 121 Not implemented +char *U_EMRCREATECOLORSPACEW_set(const uint32_t ihCS, const U_LOGCOLORSPACEW lcs, const uint32_t dwFlags, + const U_CBDATA cbData, const uint8_t *Data); + +//! \endcond + +#ifdef __cplusplus +} +#endif + +#endif /* _UEMF_ */ diff --git a/src/3rdparty/libuemf/uemf_endian.c b/src/3rdparty/libuemf/uemf_endian.c new file mode 100644 index 0000000..f746553 --- /dev/null +++ b/src/3rdparty/libuemf/uemf_endian.c @@ -0,0 +1,2270 @@ +/** + @file uemf_endian.c + + @brief Functions for converting EMF records between Big Endian and Little Endian byte orders. + + EMF files use Little Endian order. + On a Big Endian machine the data must be converted to/from Little Endian when it is writen to/read from a file. + On a Little Endian machine no conversion is required, but it is good to be able to test the routines on either platform. + When "torev" is true these routines convert from the native byte order to the reverse. + When "torev" is false these routines convert from the reverse byte order to the native. + Routines that do not use that variable swap byte order, and the way in which they do so does not depend + on the native byte order. + + The only function here which should be called directly is U_emf_endian(), and then,except for testing purposes, only on a BE machine. + + Many variables are initialized to zero even though they will always be set because + some versions of gcc give spurious "may be used uninitialized" warnings otherwise. +*/ + +/* +File: uemf_endian.c +Version: 0.0.21 +Date: 23-APR-2015 +Author: David Mathog, Biology Division, Caltech +email: mathog@caltech.edu +Copyright: 2015 David Mathog and California Institute of Technology (Caltech) +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include "uemf.h" +#include "uemf_endian.h" + +// hide almost everuything in here from Doxygen +//! \cond + +/* ********************************************************************************************** + These functions convert standard objects used in the EMR records. +*********************************************************************************************** */ + +void U_swap2(void *ul, unsigned int count){ + uint8_t ctmp; + uint8_t *cl = (uint8_t *) ul; + for(; count; count--,cl+=2){ + ctmp = *cl; + *cl = *(cl+1); + *(cl+1) = ctmp; + } +} + +/* Note: U_swap4 is also used by uwmf_endian.c, in cases where the 32 bit data is not aligned on a 4 byte boundary */ +void U_swap4(void *ul, unsigned int count){ + uint8_t ctmp; + uint8_t *cl = (uint8_t *) ul; + for(; count; count--,cl+=4){ + ctmp = *(cl+0); + *(cl+0) = *(cl+3); + *(cl+3) = ctmp; + ctmp = *(cl+1); + *(cl+1) = *(cl+2); + *(cl+2) = ctmp; + } +} + +/** + U_COLORREF and U_RGBQUAD do NOT need to be swapped, they are always stored in memory in the proper order. +*/ + +/** + \brief Convert rect and rectl objects from Upper Left and Lower Right corner points. + \param rect U_RECTL object + \param count number to convert +*/ +void rectl_swap( + PU_RECTL rect, + unsigned int count + ){ + U_swap4(rect,4*count); +} + +/** + \brief Convert a U_SIZEL object. + \param sz U_SizeL object + \param count number to convert +*/ +void sizel_swap( + PU_SIZEL sz, + unsigned int count + ){ + U_swap4(sz,2*count); +} + +/** + \brief Convert a U_POINTL object + \param pt U_POINTL object + \param count number to convert +*/ +void pointl_swap( + PU_POINTL pt, + unsigned int count + ){ + U_swap4(pt,2*count); +} + +/** + \brief Convert a U_POINT16 object + \param pt U_POINT16 object + \param count number to convert +*/ +void point16_swap( + PU_POINT16 pt, + unsigned int count + ){ + U_swap2(pt,2*count); +} + + + +/** + \brief Convert a U_TRIVERTEX object. + \param tv U_TRIVERTEX object. + \param count number to convert +*/ +void trivertex_swap( + PU_TRIVERTEX tv, + unsigned int count + ){ + for(;count; count--, tv++){ + U_swap4(tv,2); /* x,y */ + U_swap2(&(tv->Red),4); /* Red, Green, Blue, Alpha */ + } +} + +/** + \brief Convert a U_GRADIENT3 object. + \param tv U_GRADIENT3 object. + \param count number to convert +*/ +void gradient3_swap( + PU_GRADIENT3 g3, + unsigned int count + ){ + U_swap4(g3,3*count); +} + +/** + \brief Convert a U_GRADIENT4 object. + \param tv U_GRADIENT4 object. + \param count number to convert +*/ +void gradient4_swap( + PU_GRADIENT4 g4, + unsigned int count + ){ + U_swap4(g4,2*count); //a gradient4 object has 2 int4's, NOT 4! +} + +/** + \brief Convert a U_LOGBRUSH object. + \param lb U_LOGBRUSH object. +*/ +void logbrush_swap( + PU_LOGBRUSH lb + ){ + U_swap4(&(lb->lbStyle),1); // lbStyle + // ordered bytes: lbColor + U_swap4(&(lb->lbHatch),1); // lbHatch +} + +/** + \brief Convert a U_XFORM object. + \param xform U_XFORM object +*/ +void xform_swap( + PU_XFORM xform + ){ + U_swap4(xform,6); +} + + +/** + \brief Convert a U_CIEXYZTRIPLE object + \param cie3 U_CIEXYZTRIPLE object +*/ +void ciexyztriple_swap( + PU_CIEXYZTRIPLE cie3 + ){ + U_swap4(cie3,9); +} +/** + \brief Convert a U_LOGCOLORSPACEA object. + \param lcsa U_LOGCOLORSPACEA object +*/ +void logcolorspacea_swap( + PU_LOGCOLORSPACEA lcsa + ){ + U_swap4(lcsa,5); // lcsSignature lcsVersion lcsSize lcsCSType lcsIntent + ciexyztriple_swap(&(lcsa->lcsEndpoints)); + // ordered bytes: lcsGammaRGB + // ordered bytes: lcsFilename +} + +/** + + \brief Convert a U_LOGCOLORSPACEW object. + \param lcsa U_LOGCOLORSPACEW object +*/ +void logcolorspacew_swap( + PU_LOGCOLORSPACEW lcsa + ){ + U_swap4(lcsa,5); // lcsSignature lcsVersion lcsSize lcsCSType lcsIntent + ciexyztriple_swap(&(lcsa->lcsEndpoints)); + // ordered bytes: lcsGammaRGB + // UTF-16LE, already in order: lcsFilename +} + + +/** + \brief Convert a U_LOGFONT object. + \param lf U_LOGFONT object +*/ +void logfont_swap( + PU_LOGFONT lf + ){ + U_swap4(lf,5); // lfHeight lfWidth lfEscapement lfOrientation lfWeight + // ordered bytes: lfItalic lfUnderline lfStrikeOut lfCharSet lfOutPrecision lfClipPrecision lfQuality lfPitchAndFamily + // UTF16-LE, already in order +} + +/** + \brief Convert a U_LOGFONT_PANOSE object. + \return U_LOGFONT_PANOSE object +*/ +void logfont_panose_swap( + PU_LOGFONT_PANOSE lfp + ){ + logfont_swap(&(lfp->elfLogFont)); // elfLogFont + // UTF-16LE, already in order: elfFullName + // UTF-16LE, already in order: elfStyle + U_swap4(&(lfp->elfVersion),4); // elfVersion elfStyleSize elfMatch elfReserved + // ordered bytes: elfVendorId + U_swap4(&(lfp->elfCulture),1); // elfCulture + // ordered bytes: elfPanose +} + +/** + \brief Convert a U_BITMAPINFOHEADER object. + \param Bmi U_BITMAPINFOHEADER object +*/ +void bitmapinfoheader_swap( + PU_BITMAPINFOHEADER Bmi + ){ + U_swap4(Bmi,3); // biSize biWidth biHeight + U_swap2(&(Bmi->biPlanes),2); // biPlanes biBitCount + U_swap4(&(Bmi->biCompression),6); // biCompression biSizeImage biXPelsPerMeter biYPelsPerMeter biClrUsed biClrImportant +} + + +/** + \brief Convert a Pointer to a U_BITMAPINFO object. + \param Bmi Pointer to a U_BITMAPINFO object +*/ +void bitmapinfo_swap( + const char *Bmi + ){ + PU_BITMAPINFO pBmi = (PU_BITMAPINFO)Bmi; + bitmapinfoheader_swap(&(pBmi->bmiHeader)); // bmIHeader + // ordered bytes: bmiColors +} + +/** + \brief Swap the ordered bytes in a DIB and verify that the sizes are OK + + \return 1 on success, 0 on failure + \param record EMF record that contains a DIB pixel array + \param iUsage DIBcolors Enumeration + \param offBmi offset from the start of the record to the start of the bitmapinfo structure + \param cbBmi declared space for the bitmapinfo structure in the record + \param offBits offset from the start of the record to the start of the bitmap + \param cbBits declared space for the bitmap in the record (amount used may be less than this) + \param blimit one byte past the end of the record. + \param torev 1 for native to reversed, 0 for reversed to native + + This method can only test DIBs that hold Microsoft's various bitmap types. PNG or JPG is just a bag + of bytes, and there is no possible way to derive from the known width and height how big it should be. +*/ +int DIB_swap( + const char *record, + uint32_t iUsage, + uint32_t offBmi, + uint32_t cbBmi, + uint32_t offBits, + uint32_t cbBits, + const char *blimit, + int torev + ){ + int dibparams = U_BI_UNKNOWN; // type of image not yet determined + const char *px = NULL; // DIB pixels + const U_RGBQUAD *ct = NULL; // DIB color table + int bs; + int usedbytes; + + if(!cbBmi)return(1); // No DIB in a record where it is optional + if(IS_MEM_UNSAFE(record, offBmi + cbBmi, blimit))return(0); + if(cbBits && IS_MEM_UNSAFE(record, offBits + cbBits, blimit))return(0); + if(iUsage == U_DIB_RGB_COLORS){ + uint32_t width, height, colortype, numCt, invert; // these values will be set in get_DIB_params + // next call returns pointers and values, but allocates no memory + if(torev){ + dibparams = get_DIB_params(record, offBits, offBmi, &px, (const U_RGBQUAD **) &ct, + &numCt, &width, &height, &colortype, &invert); + } + bitmapinfo_swap(record + offBmi); // byte ordered fields in bitmapinfo + if(!torev){ + dibparams = get_DIB_params(record, offBits, offBmi, &px, (const U_RGBQUAD **) &ct, + &numCt, &width, &height, &colortype, &invert); + } + + // sanity checking + if(numCt && colortype >= U_BCBM_COLOR16)return(0); //color tables not used above 16 bit pixels + if(!numCt && colortype < U_BCBM_COLOR16)return(0); //color tables mandatory for < 16 bit + + if(dibparams ==U_BI_RGB){ + // this is the only DIB type where we can calculate how big it should be when stored in the EMF file + bs = colortype/8; + if(bs<1){ + usedbytes = (width*colortype + 7)/8; // width of line in fully and partially occupied bytes + } + else { + usedbytes = width*bs; + } + if(IS_MEM_UNSAFE(record+offBits, usedbytes, blimit))return(0); + } + } + else { + bitmapinfo_swap(record + offBmi); + } + return(1); +} + +/** + \brief Convert a pointer to a U_EXTLOGPEN object. + \param elp PU_EXTLOGPEN object + \param blimit one byte past the end of the record +*/ +int extlogpen_swap( + PU_EXTLOGPEN elp, + const char *blimit, + int torev + ){ + int count=0; + U_swap4(elp,3); // elpPenStyle elpWidth elpBrushStyle + // ordered bytes: elpColor + if(torev){ + count = elp->elpNumEntries; + } + U_swap4(&(elp->elpHatch),2); // elpHatch elpNumEntries + if(!torev){ + count = elp->elpNumEntries; + } + if(IS_MEM_UNSAFE(&(elp->elpStyleEntry), count*4, blimit))return(0); + U_swap4(&(elp->elpStyleEntry),count); // elpStyleEntry[] + return(1); +} + +/** + \brief Convert a U_LOGPEN object. + \param lp U_LOGPEN object + +*/ +void logpen_swap( + PU_LOGPEN lp + ){ + U_swap4(lp,1); // lopnStyle + pointl_swap(&(lp->lopnWidth),1); // lopnWidth + // ordered bytes: lopnColor +} + + +/** + \brief Convert a pointer to a U_LOGPALETTE object. + \param lp Pointer to a U_LOGPALETTE object. +*/ +void logpalette_swap( + PU_LOGPALETTE lp + ){ + U_swap2(lp,2); // palVersion palNumEntries + // ordered bytes: palPalEntry[] +} + +/** + \brief Convert a U_RGNDATAHEADER object. + \param rdh U_RGNDATAHEADER object +*/ +void rgndataheader_swap( + PU_RGNDATAHEADER rdh + ){ + U_swap4(rdh,4); // dwSize iType nCount nRgnSize + rectl_swap(&(rdh->rclBounds),1); // rclBounds +} + +/** + \return 1 on success, 0 on failure + \brief Convert a pointer to a U_RGNDATA object. + \param rd pointer to a U_RGNDATA object. + \param cbRgnData size of the U_RGNDATA object. +*/ +int rgndata_swap( + PU_RGNDATA rd, + int cbRgnData, + int torev + ){ + int count = 0; + if(torev){ + count = rd->rdh.nCount; + } + rgndataheader_swap(&(rd->rdh)); + if(!torev){ + count = rd->rdh.nCount; + } + if(4*count + (int)sizeof(U_RGNDATAHEADER) > cbRgnData)return(0); + U_swap4(rd->Buffer,4*count); + return(1); +} + +/** + \brief Convert a U_COLORADJUSTMENT object. + \param ca U_COLORADJUSTMENT object. +*/ +void coloradjustment_swap( + PU_COLORADJUSTMENT ca + ){ + U_swap2(ca,12); // caSize caFlags caIlluminantIndex caRedGamma caGreenGamma caBlueGamma caReferenceBlack caReferenceWhite caContrast caBrightness caColorfulness caRedGreenTint +} + +/** + \brief Convert a pointer to a U_PIXELFORMATDESCRIPTOR object. + \param pfd pointer to a U_PIXELFORMATDESCRIPTOR object. +*/ +void pixelformatdescriptor_swap( + PU_PIXELFORMATDESCRIPTOR pfd + ){ + U_swap2(pfd,2); // nSize nVersion + U_swap4(&(pfd->dwFlags),1); // dwFlags + // ordered bytes: iPixelType cColorBits cRedBits cRedShift cGreenBits cGreenShift cBlueBits cBlueShift cAlphaBits cAlphaShift cAccumBits cAccumRedBits cAccumGreenBits cAccumBlueBits cAccumAlphaBits cDepthBits cStencilBits cAuxBuffers iLayerType bReserved + U_swap4(&(pfd->dwLayerMask),3); // dwLayerMask dwVisibleMask dwDamageMask +} + +/** + \brief Convert a Pointer to a U_EMRTEXT record + \param pemt Pointer to a U_EMRTEXT record + \param record Pointer to the start of the record which contains this U_EMRTEXT + \param blimit one byte past the end of the record. + \param torev 1 for native to reversed, 0 for reversed to native +*/ +int emrtext_swap( + PU_EMRTEXT pemt, + char *record, + const char *blimit, + int torev + ){ + int off; + uint32_t count=0; + uint32_t offDx=0; + uint32_t fOptions=0; + pointl_swap(&(pemt->ptlReference),1); // ptlReference + if(torev){ + count = pemt->nChars; + fOptions = pemt->fOptions; + } + U_swap4(&(pemt->nChars),3); // nChars offString fOptions + if(!torev){ + count = pemt->nChars; + fOptions = pemt->fOptions; + } + off = sizeof(U_EMRTEXT); + if(!(fOptions & U_ETO_NO_RECT)){ + if(IS_MEM_UNSAFE(pemt, sizeof(U_RECTL), blimit))return(0); + rectl_swap((PU_RECTL)((char *)pemt + off),1); // optional rectangle + off+=sizeof(U_RECTL); + } + if(torev){ + offDx = *(uint32_t *)((char *)pemt +off); + } + // ordered bytes OR UTF16-LE: the string at offString + if(IS_MEM_UNSAFE(pemt, off + 4, blimit))return(0); + U_swap4(((char *)pemt+off),1); // offDx + if(!torev){ + offDx = *(uint32_t *)((char *)pemt +off); + } + if(IS_MEM_UNSAFE(record, count*4, blimit))return(0); + U_swap4((record + offDx),count); // Dx[], offset with respect to the Record, NOT the object + return(1); +} + + + +/* ********************************************************************************************** +These functions contain shared code used by various U_EMR*_swap functions. These should NEVER be called +by end user code and to further that end prototypes are NOT provided and they are hidden from Doxygen. + + + These all have this form: + + void core1_swap(char *record, int torev){ + + but some do not actually use torev. + + + +*********************************************************************************************** */ + +// all core*_swap call this, U_EMRSETMARGN_swap and some others all it directly +// numbered as core5 to be consistent with uemf.c, but must appear before the others as there is no prototype +int core5_swap(char *record, int torev){ + UNUSED_PARAMETER(torev); + if(!record)return(0); + PU_EMR pEmr = (PU_EMR)(record); + U_swap4(pEmr,2); // iType nSize + return(1); +} + +// Functions with the same form starting with U_EMRPOLYBEZIER_swap +int core1_swap(char *record, int torev){ + int count=0; + const char *blimit = NULL; + PU_EMRPOLYLINETO pEmr = (PU_EMRPOLYLINETO) (record); + if(torev){ + count = pEmr->cptl; + blimit = record + pEmr->emr.nSize; + } + if(!core5_swap(record, torev))return(0); + rectl_swap(&(pEmr->rclBounds),1 ); // rclBounds + U_swap4(&(pEmr->cptl),1); // cptl + if(!torev){ + count = pEmr->cptl; + blimit = record + pEmr->emr.nSize; + } + if(IS_MEM_UNSAFE((pEmr->aptl), count*sizeof(U_POINTL), blimit))return(0); + pointl_swap((pEmr->aptl),count); // aptl[] + return(1); +} + +// Functions with the same form starting with U_EMRPOLYPOLYLINE_swap +int core2_swap(char *record, int torev){ + int count=0; + int nPolys=0; + const char *blimit = NULL; + PU_EMRPOLYPOLYLINE pEmr = (PU_EMRPOLYPOLYLINE) (record); + if(torev){ + count = pEmr->cptl; + nPolys = pEmr->nPolys; + blimit = record + pEmr->emr.nSize; + } + if(!core5_swap(record, torev))return(0); + rectl_swap(&(pEmr->rclBounds),1); // rclBounds + U_swap4(&(pEmr->nPolys),2); // nPolys cptl + if(!torev){ + count = pEmr->cptl; + nPolys = pEmr->nPolys; + blimit = record + pEmr->emr.nSize; + } + if(IS_MEM_UNSAFE((pEmr->aPolyCounts), nPolys*4, blimit))return(0); + U_swap4(pEmr->aPolyCounts,nPolys); // aPolyCounts[] + record += sizeof(U_EMRPOLYPOLYLINE) - 4 + sizeof(uint32_t)* nPolys; + if(IS_MEM_UNSAFE(record, count*sizeof(U_POINTL), blimit))return(0); + pointl_swap((PU_POINT)(record), count); // paptl[] + return(1); +} + + +// Functions with the same form starting with U_EMRSETMAPMODE_swap +int core3_swap(char *record, int torev){ + PU_EMRSETMAPMODE pEmr = (PU_EMRSETMAPMODE)(record); + if(!core5_swap(record, torev))return(0); + U_swap4(&(pEmr->iMode),1); // iMode + return(1); +} + +// Functions taking a single U_RECT or U_RECTL, starting with U_EMRELLIPSE_swap, also U_EMRFILLPATH_swap, +int core4_swap(char *record, int torev){ + PU_EMRELLIPSE pEmr = (PU_EMRELLIPSE)( record); + if(!core5_swap(record, torev))return(0); + rectl_swap(&(pEmr->rclBox),1); // rclBox + return(1); +} + +// Functions with the same form starting with U_EMRPOLYBEZIER16_swap +int core6_swap(char *record, int torev){ + int count=0; + const char *blimit = NULL; + PU_EMRPOLYBEZIER16 pEmr = (PU_EMRPOLYBEZIER16) (record); + if(torev){ + count = pEmr->cpts; + blimit = record + pEmr->emr.nSize; + } + if(!core5_swap(record, torev))return(0); + rectl_swap(&(pEmr->rclBounds),1); // rclBounds + U_swap4(&(pEmr->cpts),1); // cpts + if(!torev){ + count = pEmr->cpts; + blimit = record + pEmr->emr.nSize; + } + if(IS_MEM_UNSAFE((pEmr->apts), count*sizeof(U_POINT16), blimit))return(0); + point16_swap((pEmr->apts),count); // apts[] + return(1); +} + + +// Records with the same form starting with U_EMRSETWINDOWEXTEX_swap, that is, all with two uint32_t values after the emr +int core7_swap(char *record, int torev){ + PU_EMRGENERICPAIR pEmr = (PU_EMRGENERICPAIR) (record); + if(!core5_swap(record, torev))return(0); + U_swap4(&(pEmr->pair),2); + return(1); +} + +// For U_EMREXTTEXTOUTA and U_EMREXTTEXTOUTW, type=0 for the first one +int core8_swap(char *record, int torev){ + const char *blimit = NULL; + PU_EMREXTTEXTOUTA pEmr = (PU_EMREXTTEXTOUTA) (record); + if(torev){ + blimit = record + pEmr->emr.nSize; + } + if(!core5_swap(record, torev))return(0); + U_swap4(&(pEmr->iGraphicsMode),1); // iGraphicsMode + rectl_swap(&(pEmr->rclBounds),1); // rclBounds + U_swap4(&(pEmr->exScale),2); // exScale eyScale + if(!torev){ + blimit = record + pEmr->emr.nSize; + } + if(!emrtext_swap(&(pEmr->emrtext),record,blimit,torev))return(0); + return(1); +} + +// Functions that take a rect and a pair of points, starting with U_EMRARC_swap +int core9_swap(char *record, int torev){ + PU_EMRARC pEmr = (PU_EMRARC) (record); + if(!core5_swap(record, torev))return(0); + rectl_swap(&(pEmr->rclBox),1); // rclBox + U_swap4(&(pEmr->ptlStart),4); // ptlStart ptlEnd + return(1); +} + +// Functions with the same form starting with U_EMRPOLYPOLYLINE16_swap +int core10_swap(char *record, int torev){ + int count=0; + int nPolys=0; + const char *blimit = NULL; + PU_EMRPOLYPOLYLINE16 pEmr = (PU_EMRPOLYPOLYLINE16) (record); + if(torev){ + count = pEmr->cpts; + nPolys = pEmr->nPolys; + blimit = record + pEmr->emr.nSize; + } + if(!core5_swap(record, torev))return(0); + rectl_swap(&(pEmr->rclBounds),1); // rclBounds + U_swap4(&(pEmr->nPolys),2); // nPolys cpts + if(!torev){ + count = pEmr->cpts; + nPolys = pEmr->nPolys; + blimit = record + pEmr->emr.nSize; + } + if(IS_MEM_UNSAFE((pEmr->aPolyCounts), nPolys*4, blimit))return(0); + U_swap4(pEmr->aPolyCounts,nPolys); // aPolyCounts[] + record += sizeof(U_EMRPOLYPOLYLINE16) - 4 + sizeof(uint32_t)* nPolys; + if(IS_MEM_UNSAFE(record, count*sizeof(U_POINT16), blimit))return(0); + point16_swap((PU_POINT16)(record), count); // apts[] + return(1); +} + +// Functions with the same form starting with U_EMRINVERTRGN_swap and U_EMRPAINTRGN_swap, +int core11_swap(char *record, int torev){ + int cbRgnData=0; + const char *blimit = NULL; + PU_EMRINVERTRGN pEmr = (PU_EMRINVERTRGN)(record); + if(torev){ + cbRgnData= pEmr->cbRgnData; + blimit = record + pEmr->emr.nSize; + } + if(!core5_swap(record, torev))return(0); + rectl_swap(&(pEmr->rclBounds),1); // rclBounds + U_swap4(&(pEmr->cbRgnData),1); // cbRgnData + if(!torev){ + cbRgnData= pEmr->cbRgnData; + blimit = record + pEmr->emr.nSize; + } + if(IS_MEM_UNSAFE(pEmr->RgnData, cbRgnData, blimit))return(0); + return(rgndata_swap(pEmr->RgnData, cbRgnData, torev)); +} + + +// common code for U_EMRCREATEMONOBRUSH_swap and U_EMRCREATEDIBPATTERNBRUSHPT_swap, +int core12_swap(char *record, int torev){ + const char *blimit = NULL; + U_OFFBMI offBmi = 0; + U_CBBMI cbBmi = 0; + U_OFFBITS offBits = 0; + U_CBBITS cbBits = 0; + uint32_t iUsage = 0; + PU_EMRCREATEMONOBRUSH pEmr = (PU_EMRCREATEMONOBRUSH) (record); + if(torev){ + offBmi = pEmr->offBmi; + cbBmi = pEmr->cbBmi; + offBits = pEmr->offBits; + cbBits = pEmr->cbBits; + iUsage = pEmr->iUsage; + blimit = record + pEmr->emr.nSize; + if(!DIB_swap(record, iUsage, offBmi, cbBmi, offBits, cbBits, blimit, torev))return(0); + } + if(!core5_swap(record, torev))return(0); + U_swap4(&(pEmr->ihBrush),6); // ihBrush iUsage offBmi cbBmi offBits cbBits + if(!torev){ + offBmi = pEmr->offBmi; + cbBmi = pEmr->cbBmi; + offBits = pEmr->offBits; + cbBits = pEmr->cbBits; + iUsage = pEmr->iUsage; + blimit = record + pEmr->emr.nSize; + if(!DIB_swap(record, iUsage, offBmi, cbBmi, offBits, cbBits, blimit, torev))return(0); + } + // ordered bytes: bitmap (including 16 bit 5bit/channel color mode, which is done bytewise). + return(1); +} + +// common code for U_EMRALPHABLEND_swap and U_EMRTRANSPARENTBLT_swap, +int core13_swap(char *record, int torev){ + const char *blimit = NULL; + U_OFFBMISRC offBmiSrc = 0; + U_CBBMISRC cbBmiSrc = 0; + U_OFFBITSSRC offBitsSrc = 0; + U_CBBITSSRC cbBitsSrc = 0; + uint32_t iUsageSrc = 0; + PU_EMRALPHABLEND pEmr = (PU_EMRALPHABLEND) (record); + if(torev){ + offBmiSrc = pEmr->offBmiSrc; + cbBmiSrc = pEmr->cbBmiSrc; + offBitsSrc = pEmr->offBitsSrc; + cbBitsSrc = pEmr->cbBitsSrc; + iUsageSrc = pEmr->iUsageSrc; + blimit = record + pEmr->emr.nSize; + if(!DIB_swap(record, iUsageSrc, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc, blimit, torev))return(0); + } + if(!core5_swap(record, torev))return(0); + rectl_swap(&(pEmr->rclBounds),1); // rclBounds + pointl_swap(&(pEmr->Dest),2); // Dest cDest + pointl_swap(&(pEmr->Dest),2); // Dest cDest + // ordered bytes: Blend + pointl_swap(&(pEmr->Src),2); // Src + xform_swap( &(pEmr->xformSrc)); // xformSrc + // ordered bytes: crBkColorSrc + U_swap4(&(pEmr->iUsageSrc),5); // iUsageSrc offBmiSrc cbBmiSrc offBitsSrc cbBitsSrc + if(!torev){ + offBmiSrc = pEmr->offBmiSrc; + cbBmiSrc = pEmr->cbBmiSrc; + offBitsSrc = pEmr->offBitsSrc; + cbBitsSrc = pEmr->cbBitsSrc; + iUsageSrc = pEmr->iUsageSrc; + blimit = record + pEmr->emr.nSize; + if(!DIB_swap(record, iUsageSrc, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc, blimit, torev))return(0); + } + // ordered bytes: bitmap (including 16 bit 5bit/channel color mode, which is done bytewise). + return(1); +} + +/* ********************************************************************************************** +These are the core EMR_swap functions, each converts a particular type of record. +All operate in place on the chunk of memory holding that record. +Some of these have offsets or counts which, if corrupt or evil would result in access outside + the record. These cases return a status value of 0 if that happens, 1 on success. Other + records which do not have these issues do not return a status value. +They are listed in order by the corresponding U_EMR_* index number. +*********************************************************************************************** */ + +/** + All of the record level (hidden) functions have this form: + \brief Convert a pointer to a U_EMR_whatever record which has not been implemented. + \param record pointer to a buffer holding the EMR record + \param torev 1 for native to reversed, 0 for reversed to native +*/ +int U_EMRNOTIMPLEMENTED_swap(char *record, int torev){ + fprintf(stderr,"EMF WARNING: could not swap data bytes on record because that type has not been implemented!\n"); + return(core5_swap(record, torev)); +} + +// U_EMRHEADER 1 +int U_EMRHEADER_swap(char *record, int torev){ + int nDesc,offDesc,nSize,cbPix,offPix; + nDesc = offDesc = nSize = cbPix = offPix = 0; + PU_EMRHEADER pEmr = (PU_EMRHEADER)(record); + if(torev){ + nSize = pEmr->emr.nSize; + nDesc = pEmr->nDescription; + offDesc = pEmr->offDescription; + } + if(!core5_swap(record, torev))return(0); + rectl_swap(&(pEmr->rclBounds),2); // rclBounds rclFrame + U_swap4(&(pEmr->dSignature), 4); // dSignature nVersion nBytes nRecords + U_swap2(&(pEmr->nHandles), 2); // nHandlessReserved + U_swap4(&(pEmr->nDescription), 3); // nDescription offDescription nPalEntries + if(!torev){ + nSize = pEmr->emr.nSize; + nDesc = pEmr->nDescription; + offDesc = pEmr->offDescription; + } + // UTF16-LE Description + sizel_swap(&(pEmr->szlDevice), 2); // szlDevice szlMillimeters + if((nDesc && (offDesc >= 100)) || + (!offDesc && nSize >= 100) + ){ + if(torev){ + cbPix = pEmr->cbPixelFormat; + offPix = pEmr->offPixelFormat; + } + U_swap4(&(pEmr->cbPixelFormat), 2); // cbPixelFormat offPixelFormat + U_swap4(&(pEmr->bOpenGL), 1); // bOpenGL + if(!torev){ + cbPix = pEmr->cbPixelFormat; + offPix = pEmr->offPixelFormat; + } + if(cbPix)pixelformatdescriptor_swap( (PU_PIXELFORMATDESCRIPTOR) (record + pEmr->offPixelFormat)); + if((nDesc && (offDesc >= 108)) || + (cbPix && (offPix >=108)) || + (!offDesc && !cbPix && nSize >= 108) + ){ + sizel_swap(&(pEmr->szlMicrometers), 1); // szlMicrometers + } + } + return(1); +} + +// U_EMRPOLYBEZIER 2 +int U_EMRPOLYBEZIER_swap(char *record, int torev){ + return(core1_swap(record, torev)); +} + +// U_EMRPOLYGON 3 +int U_EMRPOLYGON_swap(char *record, int torev){ + return(core1_swap(record, torev)); +} + + +// U_EMRPOLYLINE 4 +int U_EMRPOLYLINE_swap(char *record, int torev){ + return(core1_swap(record, torev)); +} + +// U_EMRPOLYBEZIERTO 5 +int U_EMRPOLYBEZIERTO_swap(char *record, int torev){ + return(core1_swap(record, torev)); +} + +// U_EMRPOLYLINETO 6 +int U_EMRPOLYLINETO_swap(char *record, int torev){ + return(core1_swap(record, torev)); +} + +// U_EMRPOLYPOLYLINE 7 +int U_EMRPOLYPOLYLINE_swap(char *record, int torev){ + return(core2_swap(record, torev)); +} + +// U_EMRPOLYPOLYGON 8 +int U_EMRPOLYPOLYGON_swap(char *record, int torev){ + return(core2_swap(record, torev)); +} + +// U_EMRSETWINDOWEXTEX 9 +int U_EMRSETWINDOWEXTEX_swap(char *record, int torev){ + return(core7_swap(record, torev)); +} + +// U_EMRSETWINDOWORGEX 10 +int U_EMRSETWINDOWORGEX_swap(char *record, int torev){ + return(core7_swap(record, torev)); +} + +// U_EMRSETVIEWPORTEXTEX 11 +int U_EMRSETVIEWPORTEXTEX_swap(char *record, int torev){ + return(core7_swap(record, torev)); +} + +// U_EMRSETVIEWPORTORGEX 12 +int U_EMRSETVIEWPORTORGEX_swap(char *record, int torev){ + return(core7_swap(record, torev)); +} + +// U_EMRSETBRUSHORGEX 13 +int U_EMRSETBRUSHORGEX_swap(char *record, int torev){ + return(core7_swap(record, torev)); +} + +// U_EMREOF 14 +int U_EMREOF_swap(char *record, int torev){ + int off=0; + int cbPalEntries=0; + const char *blimit = NULL; + PU_EMREOF pEmr = (PU_EMREOF)(record); + if(torev){ + blimit = record + pEmr->emr.nSize; + cbPalEntries = pEmr->cbPalEntries; + } + if(!core5_swap(record, torev))return(0); + U_swap4(&(pEmr->cbPalEntries),2); // cbPalEntries offPalEntries + if(!torev){ + blimit = record + pEmr->emr.nSize; + cbPalEntries = pEmr->cbPalEntries; + } + if(cbPalEntries){ + if(IS_MEM_UNSAFE(record, pEmr->offPalEntries + 2*2, blimit))return(0); // 2 16 bit values in U_LOGPALLETE + logpalette_swap( (PU_LOGPALETTE)(record + pEmr->offPalEntries)); + // U_LOGPLTNTRY values in pallette are ordered data + } + off = sizeof(U_EMREOF) + 4 * cbPalEntries; + if(IS_MEM_UNSAFE(record, off + 4, blimit))return(0); + U_swap4(record + off,1); // nSizeLast + return(1); +} + + +// U_EMRSETPIXELV 15 +int U_EMRSETPIXELV_swap(char *record, int torev){ + if(!core5_swap(record, torev))return(0); + PU_EMRSETPIXELV pEmr = (PU_EMRSETPIXELV)(record); + pointl_swap(&(pEmr->ptlPixel),1); // ptlPixel + // ordered bytes: crColor + return(1); +} + + +// U_EMRSETMAPPERFLAGS 16 +int U_EMRSETMAPPERFLAGS_swap(char *record, int torev){ + if(!core5_swap(record, torev))return(0); + PU_EMRSETMAPPERFLAGS pEmr = (PU_EMRSETMAPPERFLAGS)(record); + U_swap4(&(pEmr->dwFlags),1); // dwFlags + return(1); +} + + +// U_EMRSETMAPMODE 17 +int U_EMRSETMAPMODE_swap(char *record, int torev){ + return(core3_swap(record, torev)); +} + +// U_EMRSETBKMODE 18 +int U_EMRSETBKMODE_swap(char *record, int torev){ + return(core3_swap(record, torev)); +} + +// U_EMRSETPOLYFILLMODE 19 +int U_EMRSETPOLYFILLMODE_swap(char *record, int torev){ + return(core3_swap(record, torev)); +} + +// U_EMRSETROP2 20 +int U_EMRSETROP2_swap(char *record, int torev){ + return(core3_swap(record, torev)); +} + +// U_EMRSETSTRETCHBLTMODE 21 +int U_EMRSETSTRETCHBLTMODE_swap(char *record, int torev){ + return(core3_swap(record, torev)); +} + +// U_EMRSETTEXTALIGN 22 +int U_EMRSETTEXTALIGN_swap(char *record, int torev){ + return(core3_swap(record, torev)); +} + +// U_EMRSETCOLORADJUSTMENT 23 +int U_EMRSETCOLORADJUSTMENT_swap(char *record, int torev){ + if(!core5_swap(record, torev))return(0); + PU_EMRSETCOLORADJUSTMENT pEmr = (PU_EMRSETCOLORADJUSTMENT)(record); + coloradjustment_swap(&(pEmr->ColorAdjustment)); + return(1); +} + +// U_EMRSETTEXTCOLOR 24 +int U_EMRSETTEXTCOLOR_swap(char *record, int torev){ + if(!core5_swap(record, torev))return(0); + // ordered bytes: crColor + return(1); +} + +// U_EMRSETBKCOLOR 25 +int U_EMRSETBKCOLOR_swap(char *record, int torev){ + if(!core5_swap(record, torev))return(0); + // ordered bytes: crColor + return(1); +} + +// U_EMROFFSETCLIPRGN 26 +int U_EMROFFSETCLIPRGN_swap(char *record, int torev){ + return(core7_swap(record, torev)); +} + +// U_EMRMOVETOEX 27 +int U_EMRMOVETOEX_swap(char *record, int torev){ + return(core7_swap(record, torev)); +} + +// U_EMRSETMETARGN 28 +int U_EMRSETMETARGN_swap(char *record, int torev){ + return(core5_swap(record, torev)); +} + +// U_EMREXCLUDECLIPRECT 29 +int U_EMREXCLUDECLIPRECT_swap(char *record, int torev){ + return(core4_swap(record, torev)); +} + +// U_EMRINTERSECTCLIPRECT 30 +int U_EMRINTERSECTCLIPRECT_swap(char *record, int torev){ + return(core4_swap(record, torev)); +} + +// U_EMRSCALEVIEWPORTEXTEX 31 +int U_EMRSCALEVIEWPORTEXTEX_swap(char *record, int torev){ + return(core4_swap(record, torev)); +} + +// U_EMRSCALEWINDOWEXTEX 32 +int U_EMRSCALEWINDOWEXTEX_swap(char *record, int torev){ + return(core4_swap(record, torev)); +} + +// U_EMRSAVEDC 33 +int U_EMRSAVEDC_swap(char *record, int torev){ + return(core5_swap(record, torev)); +} + +// U_EMRRESTOREDC 34 +int U_EMRRESTOREDC_swap(char *record, int torev){ + return(core3_swap(record, torev)); +} + +// U_EMRSETWORLDTRANSFORM 35 +int U_EMRSETWORLDTRANSFORM_swap(char *record, int torev){ + if(!core5_swap(record, torev))return(0); + PU_EMRSETWORLDTRANSFORM pEmr = (PU_EMRSETWORLDTRANSFORM)(record); + xform_swap(&(pEmr->xform)); + return(1); +} + +// U_EMRMODIFYWORLDTRANSFORM 36 +int U_EMRMODIFYWORLDTRANSFORM_swap(char *record, int torev){ + if(!core5_swap(record, torev))return(0); + PU_EMRMODIFYWORLDTRANSFORM pEmr = (PU_EMRMODIFYWORLDTRANSFORM)(record); + xform_swap(&(pEmr->xform)); // xform + U_swap4(&(pEmr->iMode),1); // iMode + return(1); +} + +// U_EMRSELECTOBJECT 37 +int U_EMRSELECTOBJECT_swap(char *record, int torev){ + if(!core5_swap(record, torev))return(0); + PU_EMRSELECTOBJECT pEmr = (PU_EMRSELECTOBJECT)(record); + U_swap4(&(pEmr->ihObject),1); // ihObject + return(1); +} + +// U_EMRCREATEPEN 38 +int U_EMRCREATEPEN_swap(char *record, int torev){ + if(!core5_swap(record, torev))return(0); + PU_EMRCREATEPEN pEmr = (PU_EMRCREATEPEN)(record); + U_swap4(&(pEmr->ihPen),1); // ihPen + logpen_swap(&(pEmr->lopn)); // lopn + return(1); +} + +// U_EMRCREATEBRUSHINDIRECT 39 +int U_EMRCREATEBRUSHINDIRECT_swap(char *record, int torev){ + if(!core5_swap(record, torev))return(0); + PU_EMRCREATEBRUSHINDIRECT pEmr = (PU_EMRCREATEBRUSHINDIRECT)(record); + U_swap4(&(pEmr->ihBrush),1); // ihBrush + logbrush_swap(&(pEmr->lb)); // lb + return(1); +} + +// U_EMRDELETEOBJECT 40 +int U_EMRDELETEOBJECT_swap(char *record, int torev){ + if(!core5_swap(record, torev))return(0); + PU_EMRDELETEOBJECT pEmr = (PU_EMRDELETEOBJECT)(record); + U_swap4(&(pEmr->ihObject),1); // ihObject + return(1); +} + +// U_EMRANGLEARC 41 +int U_EMRANGLEARC_swap(char *record, int torev){ + if(!core5_swap(record, torev))return(0); + PU_EMRANGLEARC pEmr = (PU_EMRANGLEARC)(record); + pointl_swap(&(pEmr->ptlCenter),1); // ptlCenter + U_swap4(&(pEmr->nRadius),3); // nRadius eStartAngle eSweepAngle + return(1); +} + +// U_EMRELLIPSE 42 +int U_EMRELLIPSE_swap(char *record, int torev){ + return(core4_swap(record, torev)); +} + +// U_EMRRECTANGLE 43 +int U_EMRRECTANGLE_swap(char *record, int torev){ + return(core4_swap(record, torev)); +} + +// U_EMRROUNDRECT 44 +int U_EMRROUNDRECT_swap(char *record, int torev){ + if(!core5_swap(record, torev))return(0); + PU_EMRROUNDRECT pEmr = (PU_EMRROUNDRECT)(record); + rectl_swap(&(pEmr->rclBox),1); // rclBox + sizel_swap(&(pEmr->szlCorner), 1); // szlCorner + return(1); +} + +// U_EMRARC 45 +int U_EMRARC_swap(char *record, int torev){ + return(core9_swap(record, torev)); +} + +// U_EMRCHORD 46 +int U_EMRCHORD_swap(char *record, int torev){ + return(core9_swap(record, torev)); +} + +// U_EMRPIE 47 +int U_EMRPIE_swap(char *record, int torev){ + return(core9_swap(record, torev)); +} + +// U_EMRSELECTPALETTE 48 +int U_EMRSELECTPALETTE_swap(char *record, int torev){ + return(core3_swap(record, torev)); +} + +// U_EMRCREATEPALETTE 49 +int U_EMRCREATEPALETTE_swap(char *record, int torev){ + if(!core5_swap(record, torev))return(0); + PU_EMRCREATEPALETTE pEmr = (PU_EMRCREATEPALETTE)(record); + U_swap4(&(pEmr->ihPal),1); // ihPal + logpalette_swap( (PU_LOGPALETTE)&(pEmr->lgpl) ); // lgpl + return(1); +} + +// U_EMRSETPALETTEENTRIES 50 +int U_EMRSETPALETTEENTRIES_swap(char *record, int torev){ + if(!core5_swap(record, torev))return(0); + PU_EMRSETPALETTEENTRIES pEmr = (PU_EMRSETPALETTEENTRIES)(record); + U_swap4(&(pEmr->ihPal),3); // ihPal iStart cEntries + // ordered bytes: aPalEntries[] + return(1); +} + +// U_EMRRESIZEPALETTE 51 +int U_EMRRESIZEPALETTE_swap(char *record, int torev){ + return(core7_swap(record, torev)); +} + +// U_EMRREALIZEPALETTE 52 +int U_EMRREALIZEPALETTE_swap(char *record, int torev){ + return(core5_swap(record, torev)); +} + +// U_EMREXTFLOODFILL 53 +int U_EMREXTFLOODFILL_swap(char *record, int torev){ + if(!core5_swap(record, torev))return(0); + PU_EMREXTFLOODFILL pEmr = (PU_EMREXTFLOODFILL)(record); + pointl_swap(&(pEmr->ptlStart),1); // ptlStart + // ordered bytes: crColor + U_swap4(&(pEmr->iMode),1); // iMode + return(1); +} + +// U_EMRLINETO 54 +int U_EMRLINETO_swap(char *record, int torev){ + return(core7_swap(record, torev)); +} + +// U_EMRARCTO 55 +int U_EMRARCTO_swap(char *record, int torev){ + return(core9_swap(record, torev)); +} + +// U_EMRPOLYDRAW 56 +int U_EMRPOLYDRAW_swap(char *record, int torev){ + int count=0; + const char *blimit = NULL; + PU_EMRPOLYDRAW pEmr = (PU_EMRPOLYDRAW)(record); + + if(torev){ + count = pEmr->cptl; + blimit = record + pEmr->emr.nSize; + } + if(!core5_swap(record, torev))return(0); + rectl_swap(&(pEmr->rclBounds),1); // rclBounds + U_swap4(&(pEmr->cptl),1); // cptl + if(!torev){ + count = pEmr->cptl; + blimit = record + pEmr->emr.nSize; + } + if(IS_MEM_UNSAFE((pEmr->aptl), count*sizeof(U_POINTL), blimit))return(0); + pointl_swap(pEmr->aptl,count); // aptl[] + // single byte data abTypes + return(1); +} + +// U_EMRSETARCDIRECTION 57 +int U_EMRSETARCDIRECTION_swap(char *record, int torev){ + return(core3_swap(record, torev)); +} + +// U_EMRSETMITERLIMIT 58 +int U_EMRSETMITERLIMIT_swap(char *record, int torev){ + return(core3_swap(record, torev)); +} + + +// U_EMRBEGINPATH 59 +int U_EMRBEGINPATH_swap(char *record, int torev){ + return(core5_swap(record, torev)); +} + +// U_EMRENDPATH 60 +int U_EMRENDPATH_swap(char *record, int torev){ + return(core5_swap(record, torev)); +} + +// U_EMRCLOSEFIGURE 61 +int U_EMRCLOSEFIGURE_swap(char *record, int torev){ + return(core5_swap(record, torev)); +} + +// U_EMRFILLPATH 62 +int U_EMRFILLPATH_swap(char *record, int torev){ + return(core4_swap(record, torev)); +} + +// U_EMRSTROKEANDFILLPATH 63 +int U_EMRSTROKEANDFILLPATH_swap(char *record, int torev){ + return(core4_swap(record, torev)); +} + +// U_EMRSTROKEPATH 64 +int U_EMRSTROKEPATH_swap(char *record, int torev){ + return(core4_swap(record, torev)); +} + +// U_EMRFLATTENPATH 65 +int U_EMRFLATTENPATH_swap(char *record, int torev){ + return(core5_swap(record, torev)); +} + +// U_EMRWIDENPATH 66 +int U_EMRWIDENPATH_swap(char *record, int torev){ + return(core5_swap(record, torev)); +} + +// U_EMRSELECTCLIPPATH 67 +int U_EMRSELECTCLIPPATH_swap(char *record, int torev){ + return(core3_swap(record, torev)); +} + +// U_EMRABORTPATH 68 +int U_EMRABORTPATH_swap(char *record, int torev){ + return(core5_swap(record, torev)); +} + +// U_EMRUNDEF69 69 +#define U_EMRUNDEF69_swap(A,B) U_EMRNOTIMPLEMENTED_swap(A,B) //!< Not implemented. + +// U_EMRCOMMENT 70 Comment (any binary data, interpretation is program specific) +int U_EMRCOMMENT_swap(char *record, int torev){ + int cbData = 0; + const char *blimit = NULL; + PU_EMRCOMMENT pEmr = (PU_EMRCOMMENT)(record); + if(torev){ + cbData = pEmr->cbData; + blimit = record + pEmr->emr.nSize; + } + if(!core5_swap(record, torev))return(0); + U_swap4(&(pEmr->cbData),1); // cbData + if(!torev){ + cbData = pEmr->cbData; + blimit = record + pEmr->emr.nSize; + } + if(IS_MEM_UNSAFE(record, cbData + sizeof(U_SIZE_EMRCOMMENT), blimit))return(0); + // program specific data, presumably byte ordered, otherwise, not portable + return(1); +} + +// U_EMRFILLRGN 71 +int U_EMRFILLRGN_swap(char *record, int torev){ + int cbRgnData=0; + const char *blimit = NULL; + PU_EMRFILLRGN pEmr = (PU_EMRFILLRGN)(record); + if(torev){ + cbRgnData= pEmr->cbRgnData; + blimit = record + pEmr->emr.nSize; + } + if(!core5_swap(record, torev))return(0); + rectl_swap(&(pEmr->rclBounds),1); // rclBounds + U_swap4(&(pEmr->cbRgnData),2); // cbRgnData ihBrush + if(!torev){ + cbRgnData= pEmr->cbRgnData; + blimit = record + pEmr->emr.nSize; + } + if(IS_MEM_UNSAFE(pEmr->RgnData, cbRgnData, blimit))return(0); + return(rgndata_swap(pEmr->RgnData, cbRgnData, torev)); +} + +// U_EMRFRAMERGN 72 +int U_EMRFRAMERGN_swap(char *record, int torev){ + int cbRgnData=0; + const char *blimit = NULL; + PU_EMRFRAMERGN pEmr = (PU_EMRFRAMERGN)(record); + if(torev){ + cbRgnData= pEmr->cbRgnData; + blimit = record + pEmr->emr.nSize; + } + if(!core5_swap(record, torev))return(0); + rectl_swap(&(pEmr->rclBounds),1); // rclBounds + U_swap4(&(pEmr->cbRgnData),2); // cbRgnData ihBrush + sizel_swap(&(pEmr->szlStroke), 1); // szlStroke + if(!torev){ + cbRgnData= pEmr->cbRgnData; + blimit = record + pEmr->emr.nSize; + } + if(IS_MEM_UNSAFE(pEmr->RgnData, cbRgnData, blimit))return(0); + return(rgndata_swap(pEmr->RgnData, cbRgnData, torev)); +} + +// U_EMRINVERTRGN 73 +int U_EMRINVERTRGN_swap(char *record, int torev){ + return(core11_swap(record, torev)); +} + +// U_EMRPAINTRGN 74 +int U_EMRPAINTRGN_swap(char *record, int torev){ + return(core11_swap(record, torev)); +} + +// U_EMREXTSELECTCLIPRGN 75 +int U_EMREXTSELECTCLIPRGN_swap(char *record, int torev){ + int cbRgnData=0; + const char *blimit = NULL; + PU_EMREXTSELECTCLIPRGN pEmr = (PU_EMREXTSELECTCLIPRGN)(record); + if(torev){ + cbRgnData= pEmr->cbRgnData; + blimit = record + pEmr->emr.nSize; + } + if(!core5_swap(record, torev))return(0); + U_swap4(&(pEmr->cbRgnData),2); // cbRgnData iMode + if(!torev){ + cbRgnData= pEmr->cbRgnData; + blimit = record + pEmr->emr.nSize; + } + if(IS_MEM_UNSAFE(pEmr->RgnData, cbRgnData, blimit))return(0); + return(rgndata_swap(pEmr->RgnData, cbRgnData, torev)); +} + +// U_EMRBITBLT 76 +int U_EMRBITBLT_swap(char *record, int torev){ + const char *blimit = NULL; + U_OFFBMISRC offBmiSrc = 0; + U_CBBMISRC cbBmiSrc = 0; + U_OFFBITSSRC offBitsSrc = 0; + U_CBBITSSRC cbBitsSrc = 0; + uint32_t iUsageSrc = 0; + PU_EMRBITBLT pEmr = (PU_EMRBITBLT) (record); + if(torev){ + offBmiSrc = pEmr->offBmiSrc; + cbBmiSrc = pEmr->cbBmiSrc; + offBitsSrc = pEmr->offBitsSrc; + cbBitsSrc = pEmr->cbBitsSrc; + iUsageSrc = pEmr->iUsageSrc; + blimit = record + pEmr->emr.nSize; + if(!DIB_swap(record, iUsageSrc, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc, blimit, torev))return(0); + } + if(!core5_swap(record, torev))return(0); + rectl_swap(&(pEmr->rclBounds),1); // rclBounds + pointl_swap(&(pEmr->Dest),2); // Dest cDest + U_swap4(&(pEmr->dwRop),1); // dwRop + pointl_swap(&(pEmr->Src),1); // Src + xform_swap(&(pEmr->xformSrc)); // xformSrc + // ordered bytes: crBkColorSrc + U_swap4(&(pEmr->iUsageSrc),5); // iUsageSrc offBmiSrc cbBmiSrc offBitsSrc cbBitsSrc + if(!torev){ + offBmiSrc = pEmr->offBmiSrc; + cbBmiSrc = pEmr->cbBmiSrc; + offBitsSrc = pEmr->offBitsSrc; + cbBitsSrc = pEmr->cbBitsSrc; + iUsageSrc = pEmr->iUsageSrc; + blimit = record + pEmr->emr.nSize; + if(!DIB_swap(record, iUsageSrc, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc, blimit, torev))return(0); + } + // ordered bytes: bitmap (including 16 bit 5bit/channel color mode, which is done bytewise). + return(1); +} + +// U_EMRSTRETCHBLT 77 +int U_EMRSTRETCHBLT_swap(char *record, int torev){ + const char *blimit = NULL; + U_OFFBMISRC offBmiSrc = 0; + U_CBBMISRC cbBmiSrc = 0; + U_OFFBITSSRC offBitsSrc = 0; + U_CBBITSSRC cbBitsSrc = 0; + uint32_t iUsageSrc = 0; + PU_EMRSTRETCHBLT pEmr = (PU_EMRSTRETCHBLT) (record); + if(torev){ + offBmiSrc = pEmr->offBmiSrc; + cbBmiSrc = pEmr->cbBmiSrc; + offBitsSrc = pEmr->offBitsSrc; + cbBitsSrc = pEmr->cbBitsSrc; + iUsageSrc = pEmr->iUsageSrc; + blimit = record + pEmr->emr.nSize; + if(!DIB_swap(record, iUsageSrc, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc, blimit, torev))return(0); + } + if(!core5_swap(record, torev))return(0); + rectl_swap(&(pEmr->rclBounds),1); // rclBounds + pointl_swap(&(pEmr->Dest),2); // Dest cDest + U_swap4(&(pEmr->dwRop),1); // dwRop + pointl_swap(&(pEmr->Src),1); // Src + xform_swap(&(pEmr->xformSrc)); // xformSrc + // ordered bytes: crBkColorSrc + U_swap4(&(pEmr->iUsageSrc),5); // iUsageSrc offBmiSrc cbBmiSrc offBitsSrc cbBitsSrc + pointl_swap(&(pEmr->cSrc),1); // cSrc + if(!torev){ + offBmiSrc = pEmr->offBmiSrc; + cbBmiSrc = pEmr->cbBmiSrc; + offBitsSrc = pEmr->offBitsSrc; + cbBitsSrc = pEmr->cbBitsSrc; + iUsageSrc = pEmr->iUsageSrc; + blimit = record + pEmr->emr.nSize; + if(!DIB_swap(record, iUsageSrc, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc, blimit, torev))return(0); + } + // ordered bytes: bitmap (including 16 bit 5bit/channel color mode, which is done bytewise). + return(1); +} + +// U_EMRMASKBLT 78 +int U_EMRMASKBLT_swap(char *record, int torev){ + const char *blimit = NULL; + U_OFFBMISRC offBmiSrc = 0; + U_CBBMISRC cbBmiSrc = 0; + U_OFFBITSSRC offBitsSrc = 0; + U_CBBITSSRC cbBitsSrc = 0; + uint32_t iUsageSrc = 0; + U_OFFBMIMSK offBmiMask = 0; + U_CBBMIMSK cbBmiMask = 0; + U_OFFBITSMSK offBitsMask = 0; + U_CBBITSMSK cbBitsMask = 0; + uint32_t iUsageMask = 0; + PU_EMRMASKBLT pEmr = (PU_EMRMASKBLT) (record); + if(torev){ + offBmiSrc = pEmr->offBmiSrc; + cbBmiSrc = pEmr->cbBmiSrc; + offBitsSrc = pEmr->offBitsSrc; + cbBitsSrc = pEmr->cbBitsSrc; + iUsageSrc = pEmr->iUsageSrc; + offBmiMask = pEmr->offBmiMask; + cbBmiMask = pEmr->cbBmiMask; + offBitsMask = pEmr->offBitsMask; + cbBitsMask = pEmr->cbBitsMask; + iUsageMask = pEmr->iUsageMask; + blimit = record + pEmr->emr.nSize; + if(!DIB_swap(record, iUsageSrc, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc, blimit, torev))return(0); + if(!DIB_swap(record, iUsageMask, offBmiMask, cbBmiMask, offBitsMask, cbBitsMask, blimit, torev))return(0); + } + if(!core5_swap(record, torev))return(0); + rectl_swap(&(pEmr->rclBounds),1); // rclBounds + pointl_swap(&(pEmr->Dest),2); // Dest cDest + U_swap4(&(pEmr->dwRop),1); // dwRop + pointl_swap(&(pEmr->Src),1); // Src + xform_swap(&(pEmr->xformSrc)); // xformSrc + // ordered bytes: crBkColorSrc + U_swap4(&(pEmr->iUsageSrc),5); // iUsageSrc offBmiSrc cbBmiSrc offBitsSrc cbBitsSrc + pointl_swap(&(pEmr->Mask),1); // Mask + U_swap4(&(pEmr->iUsageMask),5); // iUsageMask offBmiMask cbBmiMask offBitsMask cbBitsMask + if(!torev){ + offBmiSrc = pEmr->offBmiSrc; + cbBmiSrc = pEmr->cbBmiSrc; + offBitsSrc = pEmr->offBitsSrc; + cbBitsSrc = pEmr->cbBitsSrc; + iUsageSrc = pEmr->iUsageSrc; + offBmiMask = pEmr->offBmiMask; + cbBmiMask = pEmr->cbBmiMask; + offBitsMask = pEmr->offBitsMask; + cbBitsMask = pEmr->cbBitsMask; + iUsageMask = pEmr->iUsageMask; + blimit = record + pEmr->emr.nSize; + if(!DIB_swap(record, iUsageSrc, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc, blimit, torev))return(0); + if(!DIB_swap(record, iUsageMask, offBmiMask, cbBmiMask, offBitsMask, cbBitsMask, blimit, torev))return(0); + } + return(1); +} + +// U_EMRPLGBLT 79 +int U_EMRPLGBLT_swap(char *record, int torev){ + const char *blimit = NULL; + U_OFFBMISRC offBmiSrc = 0; + U_CBBMISRC cbBmiSrc = 0; + U_OFFBITSSRC offBitsSrc = 0; + U_CBBITSSRC cbBitsSrc = 0; + uint32_t iUsageSrc = 0; + U_OFFBMIMSK offBmiMask = 0; + U_CBBMIMSK cbBmiMask = 0; + U_OFFBITSMSK offBitsMask = 0; + U_CBBITSMSK cbBitsMask = 0; + uint32_t iUsageMask = 0; + PU_EMRPLGBLT pEmr = (PU_EMRPLGBLT) (record); + if(torev){ + offBmiSrc = pEmr->offBmiSrc; + cbBmiSrc = pEmr->cbBmiSrc; + offBitsSrc = pEmr->offBitsSrc; + cbBitsSrc = pEmr->cbBitsSrc; + iUsageSrc = pEmr->iUsageSrc; + offBmiMask = pEmr->offBmiMask; + cbBmiMask = pEmr->cbBmiMask; + offBitsMask = pEmr->offBitsMask; + cbBitsMask = pEmr->cbBitsMask; + iUsageMask = pEmr->iUsageMask; + blimit = record + pEmr->emr.nSize; + if(!DIB_swap(record, iUsageSrc, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc, blimit, torev))return(0); + if(!DIB_swap(record, iUsageMask, offBmiMask, cbBmiMask, offBitsMask, cbBitsMask, blimit, torev))return(0); + } + if(!core5_swap(record, torev))return(0); + rectl_swap(&(pEmr->rclBounds),1); // rclBounds + pointl_swap(pEmr->aptlDst,3); // aptlDst[] + pointl_swap(&(pEmr->Src),2); // Src cSrc + xform_swap(&(pEmr->xformSrc)); // xformSrc + // ordered bytes: crBkColorSrc + U_swap4(&(pEmr->iUsageSrc),5); // iUsageSrc offBmiSrc cbBmiSrc offBitsSrc cbBitsSrc + pointl_swap(&(pEmr->Mask),1); // Mask + U_swap4(&(pEmr->iUsageMask),5); // iUsageMask offBmiMask cbBmiMask offBitsMask cbBitsMask + if(!torev){ + offBmiSrc = pEmr->offBmiSrc; + cbBmiSrc = pEmr->cbBmiSrc; + offBitsSrc = pEmr->offBitsSrc; + cbBitsSrc = pEmr->cbBitsSrc; + iUsageSrc = pEmr->iUsageSrc; + offBmiMask = pEmr->offBmiMask; + cbBmiMask = pEmr->cbBmiMask; + offBitsMask = pEmr->offBitsMask; + cbBitsMask = pEmr->cbBitsMask; + iUsageMask = pEmr->iUsageMask; + blimit = record + pEmr->emr.nSize; + if(!DIB_swap(record, iUsageSrc, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc, blimit, torev))return(0); + if(!DIB_swap(record, iUsageMask, offBmiMask, cbBmiMask, offBitsMask, cbBitsMask, blimit, torev))return(0); + } + return(1); +} + +// U_EMRSETDIBITSTODEVICE 80 +int U_EMRSETDIBITSTODEVICE_swap(char *record, int torev){ + const char *blimit = NULL; + U_OFFBMISRC offBmiSrc = 0; + U_CBBMISRC cbBmiSrc = 0; + U_OFFBITSSRC offBitsSrc = 0; + U_CBBITSSRC cbBitsSrc = 0; + uint32_t iUsageSrc = 0; + PU_EMRSETDIBITSTODEVICE pEmr = (PU_EMRSETDIBITSTODEVICE) (record); + if(torev){ + offBmiSrc = pEmr->offBmiSrc; + cbBmiSrc = pEmr->cbBmiSrc; + offBitsSrc = pEmr->offBitsSrc; + cbBitsSrc = pEmr->cbBitsSrc; + iUsageSrc = pEmr->iUsageSrc; + blimit = record + pEmr->emr.nSize; + if(!DIB_swap(record, iUsageSrc, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc, blimit, torev))return(0); + } + if(!core5_swap(record, torev))return(0); + rectl_swap(&(pEmr->rclBounds),1); // rclBounds + pointl_swap(&(pEmr->Dest),1); // Dest + pointl_swap(&(pEmr->Src),2); // Src cSrc + U_swap4(&(pEmr->offBmiSrc),7); // offBmiSrc cbBmiSrc offBitsSrc cbBitsSrc iUsageSrc iStartScan cScans + if(!torev){ + offBmiSrc = pEmr->offBmiSrc; + cbBmiSrc = pEmr->cbBmiSrc; + offBitsSrc = pEmr->offBitsSrc; + cbBitsSrc = pEmr->cbBitsSrc; + iUsageSrc = pEmr->iUsageSrc; + blimit = record + pEmr->emr.nSize; + if(!DIB_swap(record, iUsageSrc, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc, blimit, torev))return(0); + } + return(1); +} + +// U_EMRSTRETCHDIBITS 81 +int U_EMRSTRETCHDIBITS_swap(char *record, int torev){ + const char *blimit = NULL; + U_OFFBMISRC offBmiSrc = 0; + U_CBBMISRC cbBmiSrc = 0; + U_OFFBITSSRC offBitsSrc = 0; + U_CBBITSSRC cbBitsSrc = 0; + uint32_t iUsageSrc = 0; + PU_EMRSTRETCHDIBITS pEmr = (PU_EMRSTRETCHDIBITS) (record); + if(torev){ + offBmiSrc = pEmr->offBmiSrc; + cbBmiSrc = pEmr->cbBmiSrc; + offBitsSrc = pEmr->offBitsSrc; + cbBitsSrc = pEmr->cbBitsSrc; + iUsageSrc = pEmr->iUsageSrc; + blimit = record + pEmr->emr.nSize; + if(!DIB_swap(record, iUsageSrc, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc, blimit, torev))return(0); + } + if(!core5_swap(record, torev))return(0); + rectl_swap(&(pEmr->rclBounds),1); // rclBounds + pointl_swap(&(pEmr->Dest),1); // Dest + pointl_swap(&(pEmr->Src),2); // Src cSrc + U_swap4(&(pEmr->offBmiSrc),6); // offBmiSrc cbBmiSrc offBitsSrc cbBitsSrc iUsageSrc dwRop + pointl_swap(&(pEmr->cDest),1); // cDest + if(!torev){ + offBmiSrc = pEmr->offBmiSrc; + cbBmiSrc = pEmr->cbBmiSrc; + offBitsSrc = pEmr->offBitsSrc; + cbBitsSrc = pEmr->cbBitsSrc; + iUsageSrc = pEmr->iUsageSrc; + blimit = record + pEmr->emr.nSize; + if(!DIB_swap(record, iUsageSrc, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc, blimit, torev))return(0); + } + return(1); +} + +// U_EMREXTCREATEFONTINDIRECTW 82 +int U_EMREXTCREATEFONTINDIRECTW_swap(char *record, int torev){ + int nSize = 0; + PU_EMREXTCREATEFONTINDIRECTW pEmr = (PU_EMREXTCREATEFONTINDIRECTW) (record); + if(torev){ + nSize = pEmr->emr.nSize; + } + if(!core5_swap(record, torev))return(0); + U_swap4(&(pEmr->ihFont),1); // ihFont + if(!torev){ + nSize = pEmr->emr.nSize; + } + if(nSize == U_SIZE_EMREXTCREATEFONTINDIRECTW_LOGFONT_PANOSE){ + logfont_panose_swap(&(pEmr->elfw)); + } + else { // logfont or logfontExDv (which starts with logfont, which can be swapped, and the rest is already in byte order + logfont_swap( (PU_LOGFONT) &(pEmr->elfw)); + } + return(1); +} + +// U_EMREXTTEXTOUTA 83 +int U_EMREXTTEXTOUTA_swap(char *record, int torev){ + return(core8_swap(record, torev)); +} + +// U_EMREXTTEXTOUTW 84 +int U_EMREXTTEXTOUTW_swap(char *record, int torev){ + return(core8_swap(record, torev)); +} + +// U_EMRPOLYBEZIER16 85 +/** + \brief Convert a pointer to a U_EMR_POLYBEZIER16 record. + \param record pointer to a buffer holding the EMR record +*/ +int U_EMRPOLYBEZIER16_swap(char *record, int torev){ + return(core6_swap(record, torev)); +} + +// U_EMRPOLYGON16 86 +int U_EMRPOLYGON16_swap(char *record, int torev){ + return(core6_swap(record, torev)); +} + +// U_EMRPOLYLINE16 87 +int U_EMRPOLYLINE16_swap(char *record, int torev){ + return(core6_swap(record, torev)); +} + +// U_EMRPOLYBEZIERTO16 88 +int U_EMRPOLYBEZIERTO16_swap(char *record, int torev){ + return(core6_swap(record, torev)); +} + +// U_EMRPOLYLINETO16 89 +/** + \brief Convert a pointer to a U_EMR_POLYLINETO16 record. + \param record pointer to a buffer holding the EMR record +*/ +int U_EMRPOLYLINETO16_swap(char *record, int torev){ + return(core6_swap(record, torev)); +} + +// U_EMRPOLYPOLYLINE16 90 +int U_EMRPOLYPOLYLINE16_swap(char *record, int torev){ + return(core10_swap(record, torev)); +} + +// U_EMRPOLYPOLYGON16 91 +int U_EMRPOLYPOLYGON16_swap(char *record, int torev){ + return(core10_swap(record, torev)); +} + + +// U_EMRPOLYDRAW16 92 +int U_EMRPOLYDRAW16_swap(char *record, int torev){ + int count=0; + const char *blimit = NULL; + PU_EMRPOLYDRAW16 pEmr = (PU_EMRPOLYDRAW16)(record); + if(torev){ + count = pEmr->cpts; + blimit = record + pEmr->emr.nSize; + } + if(!core5_swap(record, torev))return(0); + rectl_swap(&(pEmr->rclBounds),1); // rclBounds + U_swap4(&(pEmr->cpts),1); // cpts + if(!torev){ + count = pEmr->cpts; + blimit = record + pEmr->emr.nSize; + } + if(IS_MEM_UNSAFE((pEmr->apts), count*sizeof(U_POINT16), blimit))return(0); + point16_swap(pEmr->apts,count); // apts[] + // single byte data abTypes + return(1); +} + +// U_EMRCREATEMONOBRUSH 93 +int U_EMRCREATEMONOBRUSH_swap(char *record, int torev){ + return(core12_swap(record, torev)); +} + +// U_EMRCREATEDIBPATTERNBRUSHPT_swap 94 +int U_EMRCREATEDIBPATTERNBRUSHPT_swap(char *record, int torev){ + return(core12_swap(record, torev)); +} + + +// U_EMREXTCREATEPEN 95 +int U_EMREXTCREATEPEN_swap(char *record, int torev){ + const char *blimit = NULL; + U_OFFBMI offBmi = 0; + U_CBBMI cbBmi = 0; + U_OFFBITS offBits = 0; + U_CBBITS cbBits = 0; + PU_EMREXTCREATEPEN pEmr = (PU_EMREXTCREATEPEN)(record); + if(torev){ + offBmi = pEmr->offBmi; + cbBmi = pEmr->cbBmi; + offBits = pEmr->offBits; + cbBits = pEmr->cbBits; + blimit = record + pEmr->emr.nSize; + if(!DIB_swap(record, U_DIB_RGB_COLORS, offBmi, cbBmi, offBits, cbBits, blimit, torev))return(0); + } + if(!core5_swap(record, torev))return(0); + U_swap4(&(pEmr->ihPen),5); // ihPen offBmi cbBmi offBits cbBits + if(!torev){ + offBmi = pEmr->offBmi; + cbBmi = pEmr->cbBmi; + offBits = pEmr->offBits; + cbBits = pEmr->cbBits; + blimit = record + pEmr->emr.nSize; + if(!DIB_swap(record, U_DIB_RGB_COLORS, offBmi, cbBmi, offBits, cbBits, blimit, torev))return(0); + } + return(extlogpen_swap((PU_EXTLOGPEN) &(pEmr->elp), blimit, torev)); +} + +// U_EMRPOLYTEXTOUTA 96 NOT IMPLEMENTED, denigrated after Windows NT +#define U_EMRPOLYTEXTOUTA_swap(A,B) U_EMRNOTIMPLEMENTED_swap(A,B) //!< Not implemented. +// U_EMRPOLYTEXTOUTW 97 NOT IMPLEMENTED, denigrated after Windows NT +#define U_EMRPOLYTEXTOUTW_swap(A,B) U_EMRNOTIMPLEMENTED_swap(A,B) //!< Not implemented. + +// U_EMRSETICMMODE 98 +int U_EMRSETICMMODE_swap(char *record, int torev){ + return(core3_swap(record, torev)); +} + +// U_EMRCREATECOLORSPACE 99 +int U_EMRCREATECOLORSPACE_swap(char *record, int torev){ + if(!core5_swap(record, torev))return(0); + PU_EMRCREATECOLORSPACE pEmr = (PU_EMRCREATECOLORSPACE)(record); + U_swap4(&(pEmr->ihCS),1); // ihCS + logcolorspacea_swap(&(pEmr->lcs)); // lcs + return(1); +} + +// U_EMRSETCOLORSPACE 100 +int U_EMRSETCOLORSPACE_swap(char *record, int torev){ + return(core3_swap(record, torev)); +} + +// U_EMRDELETECOLORSPACE 101 +int U_EMRDELETECOLORSPACE_swap(char *record, int torev){ + return(core3_swap(record, torev)); +} + +// U_EMRGLSRECORD 102 Not implemented +#define U_EMRGLSRECORD_swap(A,B) U_EMRNOTIMPLEMENTED_swap(A,B) //!< Not implemented. +// U_EMRGLSBOUNDEDRECORD 103 Not implemented +#define U_EMRGLSBOUNDEDRECORD_swap(A,B) U_EMRNOTIMPLEMENTED_swap(A,B) //!< Not implemented. + +// U_EMRPIXELFORMAT 104 +int U_EMRPIXELFORMAT_swap(char *record, int torev){ + if(!core5_swap(record, torev))return(0); + PU_EMRPIXELFORMAT pEmr = (PU_EMRPIXELFORMAT)(record); + pixelformatdescriptor_swap(&(pEmr->pfd)); // pfd + return(1); +} + +// U_EMRDRAWESCAPE 105 Not implemented +#define U_EMRDRAWESCAPE_swap(A,B) U_EMRNOTIMPLEMENTED_swap(A,B) //!< Not implemented. +// U_EMREXTESCAPE 106 Not implemented +#define U_EMREXTESCAPE_swap(A,B) U_EMRNOTIMPLEMENTED_swap(A,B) //!< Not implemented. +// U_EMRUNDEF107 107 Not implemented +#define U_EMRUNDEF107_swap(A,B) U_EMRNOTIMPLEMENTED_swap(A,B) //!< Not implemented. + +// U_EMRSMALLTEXTOUT 108 +int U_EMRSMALLTEXTOUT_swap(char *record, int torev){ + int roff=sizeof(U_EMRSMALLTEXTOUT); // offset to the start of the variable fields + int fuOptions = 0; + int cChars = 0; + const char *blimit = NULL; + PU_EMRSMALLTEXTOUT pEmr = (PU_EMRSMALLTEXTOUT)(record); + if(torev){ + fuOptions = pEmr->fuOptions; + cChars = pEmr->cChars; + blimit = record + pEmr->emr.nSize; + } + if(!core5_swap(record, torev))return(0); + pointl_swap(&(pEmr->Dest),1); // Dest + U_swap4(&(pEmr->cChars),5); // cChars fuOptions iGraphicsMode exScale eyScale + if(!torev){ + fuOptions = pEmr->fuOptions; + cChars = pEmr->cChars; + blimit = record + pEmr->emr.nSize; + } + if(!(fuOptions & U_ETO_NO_RECT)){ + if(IS_MEM_UNSAFE(record, roff + sizeof(U_RECTL), blimit))return(0); + rectl_swap( (PU_RECTL) (record + roff),1); // rclBounds + } + if(IS_MEM_UNSAFE(record, roff + sizeof(U_RECTL) + cChars, blimit))return(0); + // ordered bytes or UTF16-LE TextString + return(1); +} + +// U_EMRFORCEUFIMAPPING 109 Not implemented +#define U_EMRFORCEUFIMAPPING_swap(A,B) U_EMRNOTIMPLEMENTED_swap(A,B) //!< Not implemented. +// U_EMRNAMEDESCAPE 110 Not implemented +#define U_EMRNAMEDESCAPE_swap(A,B) U_EMRNOTIMPLEMENTED_swap(A,B) //!< Not implemented. +// U_EMRCOLORCORRECTPALETTE 111 Not implemented +#define U_EMRCOLORCORRECTPALETTE_swap(A,B) U_EMRNOTIMPLEMENTED_swap(A,B) //!< Not implemented. +// U_EMRSETICMPROFILEA 112 Not implemented +#define U_EMRSETICMPROFILEA_swap(A,B) U_EMRNOTIMPLEMENTED_swap(A,B) //!< Not implemented. +// U_EMRSETICMPROFILEW 113 Not implemented +#define U_EMRSETICMPROFILEW_swap(A,B) U_EMRNOTIMPLEMENTED_swap(A,B) //!< Not implemented. + +// U_EMRALPHABLEND 114 +int U_EMRALPHABLEND_swap(char *record, int torev){ + return(core13_swap(record, torev)); +} + +// U_EMRSETLAYOUT 115 +int U_EMRSETLAYOUT_swap(char *record, int torev){ + return(core3_swap(record, torev)); +} + +// U_EMRTRANSPARENTBLT 116 +int U_EMRTRANSPARENTBLT_swap(char *record, int torev){ + return(core13_swap(record, torev)); +} + + +// U_EMRUNDEF117 117 Not implemented +#define U_EMRUNDEF117_swap(A,B) U_EMRNOTIMPLEMENTED_swap(A,B) //!< Not implemented. +// U_EMRGRADIENTFILL 118 +int U_EMRGRADIENTFILL_swap(char *record, int torev){ + int nTriVert=0; + int nGradObj=0; + int ulMode=0; + const char *blimit = NULL; + PU_EMRGRADIENTFILL pEmr = (PU_EMRGRADIENTFILL)(record); + if(torev){ + nTriVert = pEmr->nTriVert; + nGradObj = pEmr->nGradObj; + ulMode = pEmr->ulMode; + blimit = record + pEmr->emr.nSize; + } + if(!core5_swap(record, torev))return(0); + rectl_swap(&(pEmr->rclBounds),1); // rclBounds + U_swap4(&(pEmr->nTriVert),3); // nTriVert nGradObj ulMode + if(!torev){ + nTriVert = pEmr->nTriVert; + nGradObj = pEmr->nGradObj; + ulMode = pEmr->ulMode; + blimit = record + pEmr->emr.nSize; + } + record += sizeof(U_EMRGRADIENTFILL); + if(IS_MEM_UNSAFE(record, nTriVert*sizeof(U_TRIVERTEX), blimit))return(0); + if(nTriVert){ + trivertex_swap((PU_TRIVERTEX)(record),nTriVert); // TriVert[] + } + record += nTriVert * sizeof(U_TRIVERTEX); + if(nGradObj){ + if( ulMode == U_GRADIENT_FILL_TRIANGLE){ + if(IS_MEM_UNSAFE(record, nGradObj*sizeof(U_GRADIENT3), blimit))return(0); + gradient3_swap((PU_GRADIENT3)(record), nGradObj); // GradObj[] + } + else if(ulMode == U_GRADIENT_FILL_RECT_H || ulMode == U_GRADIENT_FILL_RECT_V){ + if(IS_MEM_UNSAFE(record, nGradObj*sizeof(U_GRADIENT4), blimit))return(0); + gradient4_swap((PU_GRADIENT4)(record), nGradObj); // GradObj[] + } + } + return(1); +} + +// U_EMRSETLINKEDUFIS 119 Not implemented +#define U_EMRSETLINKEDUFIS_swap(A,B) U_EMRNOTIMPLEMENTED_swap(A,B) //!< Not implemented. +// U_EMRSETTEXTJUSTIFICATION120 Not implemented (denigrated) +#define U_EMRSETTEXTJUSTIFICATION_swap(A,B) U_EMRNOTIMPLEMENTED_swap(A,B) //!< Not implemented. +// U_EMRCOLORMATCHTOTARGETW 121 Not implemented +#define U_EMRCOLORMATCHTOTARGETW_swap(A,B) U_EMRNOTIMPLEMENTED_swap(A,B) //!< Not implemented. + +// U_EMRCREATECOLORSPACEW 122 +int U_EMRCREATECOLORSPACEW_swap(char *record, int torev){ + PU_EMRCREATECOLORSPACEW pEmr = (PU_EMRCREATECOLORSPACEW)(record); + if(!core5_swap(record, torev))return(0); + U_swap4(&(pEmr->ihCS),1); // ihCS + logcolorspacew_swap(&(pEmr->lcs)); // lcs + U_swap4(&(pEmr->dwFlags),2); // dwFlags cbData + // ordered bytes: Data + return(1); +} + +//! \endcond + +/** + \brief Checks the declared size of a record for consistency + \return 0 on failure, 1 on success + \param record pointer to the start of the EMF record in memory + \param blimit pointer to one byte after the EMF record in memory + \param nSize number of bytes in the record, read from the record + \param iType type of the record, read from the record + \param torev 1 for native to reversed, 0 for reversed to native + + Normally this would be called immediately after reading the data from a file. + Verifies that the declared size is consistent with this type of record. +*/ +int U_emf_record_sizeok(const char *record, const char *blimit, uint32_t *nSize, uint32_t *iType, int torev){ + uint32_t rsize=0; + if(!nSize || !iType)return(0); // programming error + + /* Check that COMMON data in record can be touched without an access violation. If it cannot be + this is either a corrupt EMF or one engineered to cause a buffer overflow. Pointer math + could wrap so check both sides of the range, and fail any indications of such a wrap. + */ + if(IS_MEM_UNSAFE(record, sizeof(U_EMR), blimit))return(0); + + PU_ENHMETARECORD pEmr = (PU_ENHMETARECORD)(record); + *iType = pEmr->iType; + *nSize = pEmr->nSize; + if(!torev){ + U_swap4(iType,1); + U_swap4(nSize,1); + } + + /* Check that the FULL record size is OK, abort if not. */ + if(IS_MEM_UNSAFE(record, *nSize, blimit))return(0); + + switch (*iType) + { + // next line, ancient EMF files used a smaller header, to be safe, test for that + case U_EMR_HEADER: rsize = U_SIZE_EMRHEADER_MIN; break; + case U_EMR_POLYBEZIER: rsize = U_SIZE_EMRPOLYBEZIER; break; + case U_EMR_POLYGON: rsize = U_SIZE_EMRPOLYGON; break; + case U_EMR_POLYLINE: rsize = U_SIZE_EMRPOLYLINE; break; + case U_EMR_POLYBEZIERTO: rsize = U_SIZE_EMRPOLYBEZIERTO; break; + case U_EMR_POLYLINETO: rsize = U_SIZE_EMRPOLYLINETO; break; + case U_EMR_POLYPOLYLINE: rsize = U_SIZE_EMRPOLYPOLYLINE; break; + case U_EMR_POLYPOLYGON: rsize = U_SIZE_EMRPOLYPOLYGON; break; + case U_EMR_SETWINDOWEXTEX: rsize = U_SIZE_EMRSETWINDOWEXTEX; break; + case U_EMR_SETWINDOWORGEX: rsize = U_SIZE_EMRSETWINDOWORGEX; break; + case U_EMR_SETVIEWPORTEXTEX: rsize = U_SIZE_EMRSETVIEWPORTEXTEX; break; + case U_EMR_SETVIEWPORTORGEX: rsize = U_SIZE_EMRSETVIEWPORTORGEX; break; + case U_EMR_SETBRUSHORGEX: rsize = U_SIZE_EMRSETBRUSHORGEX; break; + case U_EMR_EOF: rsize = U_SIZE_EMREOF; break; + case U_EMR_SETPIXELV: rsize = U_SIZE_EMRSETPIXELV; break; + case U_EMR_SETMAPPERFLAGS: rsize = U_SIZE_EMRSETMAPPERFLAGS; break; + case U_EMR_SETMAPMODE: rsize = U_SIZE_EMRSETMAPMODE; break; + case U_EMR_SETBKMODE: rsize = U_SIZE_EMRSETBKMODE; break; + case U_EMR_SETPOLYFILLMODE: rsize = U_SIZE_EMRSETPOLYFILLMODE; break; + case U_EMR_SETROP2: rsize = U_SIZE_EMRSETROP2; break; + case U_EMR_SETSTRETCHBLTMODE: rsize = U_SIZE_EMRSETSTRETCHBLTMODE; break; + case U_EMR_SETTEXTALIGN: rsize = U_SIZE_EMRSETTEXTALIGN; break; + case U_EMR_SETCOLORADJUSTMENT: rsize = U_SIZE_EMRSETCOLORADJUSTMENT; break; + case U_EMR_SETTEXTCOLOR: rsize = U_SIZE_EMRSETTEXTCOLOR; break; + case U_EMR_SETBKCOLOR: rsize = U_SIZE_EMRSETBKCOLOR; break; + case U_EMR_OFFSETCLIPRGN: rsize = U_SIZE_EMROFFSETCLIPRGN; break; + case U_EMR_MOVETOEX: rsize = U_SIZE_EMRMOVETOEX; break; + case U_EMR_SETMETARGN: rsize = U_SIZE_EMRSETMETARGN; break; + case U_EMR_EXCLUDECLIPRECT: rsize = U_SIZE_EMREXCLUDECLIPRECT; break; + case U_EMR_INTERSECTCLIPRECT: rsize = U_SIZE_EMRINTERSECTCLIPRECT; break; + case U_EMR_SCALEVIEWPORTEXTEX: rsize = U_SIZE_EMRSCALEVIEWPORTEXTEX; break; + case U_EMR_SCALEWINDOWEXTEX: rsize = U_SIZE_EMRSCALEWINDOWEXTEX; break; + case U_EMR_SAVEDC: rsize = U_SIZE_EMRSAVEDC; break; + case U_EMR_RESTOREDC: rsize = U_SIZE_EMRRESTOREDC; break; + case U_EMR_SETWORLDTRANSFORM: rsize = U_SIZE_EMRSETWORLDTRANSFORM; break; + case U_EMR_MODIFYWORLDTRANSFORM: rsize = U_SIZE_EMRMODIFYWORLDTRANSFORM; break; + case U_EMR_SELECTOBJECT: rsize = U_SIZE_EMRSELECTOBJECT; break; + case U_EMR_CREATEPEN: rsize = U_SIZE_EMRCREATEPEN; break; + case U_EMR_CREATEBRUSHINDIRECT: rsize = U_SIZE_EMRCREATEBRUSHINDIRECT; break; + case U_EMR_DELETEOBJECT: rsize = U_SIZE_EMRDELETEOBJECT; break; + case U_EMR_ANGLEARC: rsize = U_SIZE_EMRANGLEARC; break; + case U_EMR_ELLIPSE: rsize = U_SIZE_EMRELLIPSE; break; + case U_EMR_RECTANGLE: rsize = U_SIZE_EMRRECTANGLE; break; + case U_EMR_ROUNDRECT: rsize = U_SIZE_EMRROUNDRECT; break; + case U_EMR_ARC: rsize = U_SIZE_EMRARC; break; + case U_EMR_CHORD: rsize = U_SIZE_EMRCHORD; break; + case U_EMR_PIE: rsize = U_SIZE_EMRPIE; break; + case U_EMR_SELECTPALETTE: rsize = U_SIZE_EMRSELECTPALETTE; break; + case U_EMR_CREATEPALETTE: rsize = U_SIZE_EMRCREATEPALETTE; break; + case U_EMR_SETPALETTEENTRIES: rsize = U_SIZE_EMRSETPALETTEENTRIES; break; + case U_EMR_RESIZEPALETTE: rsize = U_SIZE_EMRRESIZEPALETTE; break; + case U_EMR_REALIZEPALETTE: rsize = U_SIZE_EMRREALIZEPALETTE; break; + case U_EMR_EXTFLOODFILL: rsize = U_SIZE_EMREXTFLOODFILL; break; + case U_EMR_LINETO: rsize = U_SIZE_EMRLINETO; break; + case U_EMR_ARCTO: rsize = U_SIZE_EMRARCTO; break; + case U_EMR_POLYDRAW: rsize = U_SIZE_EMRPOLYDRAW; break; + case U_EMR_SETARCDIRECTION: rsize = U_SIZE_EMRSETARCDIRECTION; break; + case U_EMR_SETMITERLIMIT: rsize = U_SIZE_EMRSETMITERLIMIT; break; + case U_EMR_BEGINPATH: rsize = U_SIZE_EMRBEGINPATH; break; + case U_EMR_ENDPATH: rsize = U_SIZE_EMRENDPATH; break; + case U_EMR_CLOSEFIGURE: rsize = U_SIZE_EMRCLOSEFIGURE; break; + case U_EMR_FILLPATH: rsize = U_SIZE_EMRFILLPATH; break; + case U_EMR_STROKEANDFILLPATH: rsize = U_SIZE_EMRSTROKEANDFILLPATH; break; + case U_EMR_STROKEPATH: rsize = U_SIZE_EMRSTROKEPATH; break; + case U_EMR_FLATTENPATH: rsize = U_SIZE_EMRFLATTENPATH; break; + case U_EMR_WIDENPATH: rsize = U_SIZE_EMRWIDENPATH; break; + case U_EMR_SELECTCLIPPATH: rsize = U_SIZE_EMRSELECTCLIPPATH; break; + case U_EMR_ABORTPATH: rsize = U_SIZE_EMRABORTPATH; break; + case U_EMR_UNDEF69: rsize = U_SIZE_EMRUNDEFINED; break; + case U_EMR_COMMENT: rsize = U_SIZE_EMRCOMMENT; break; + case U_EMR_FILLRGN: rsize = U_SIZE_EMRFILLRGN; break; + case U_EMR_FRAMERGN: rsize = U_SIZE_EMRFRAMERGN; break; + case U_EMR_INVERTRGN: rsize = U_SIZE_EMRINVERTRGN; break; + case U_EMR_PAINTRGN: rsize = U_SIZE_EMRPAINTRGN; break; + case U_EMR_EXTSELECTCLIPRGN: rsize = U_SIZE_EMREXTSELECTCLIPRGN; break; + case U_EMR_BITBLT: rsize = U_SIZE_EMRBITBLT; break; + case U_EMR_STRETCHBLT: rsize = U_SIZE_EMRSTRETCHBLT; break; + case U_EMR_MASKBLT: rsize = U_SIZE_EMRMASKBLT; break; + case U_EMR_PLGBLT: rsize = U_SIZE_EMRPLGBLT; break; + case U_EMR_SETDIBITSTODEVICE: rsize = U_SIZE_EMRSETDIBITSTODEVICE; break; + case U_EMR_STRETCHDIBITS: rsize = U_SIZE_EMRSTRETCHDIBITS; break; + case U_EMR_EXTCREATEFONTINDIRECTW: rsize = U_SIZE_EMREXTCREATEFONTINDIRECTW_LOGFONT; break; + case U_EMR_EXTTEXTOUTA: rsize = U_SIZE_EMREXTTEXTOUTA; break; + case U_EMR_EXTTEXTOUTW: rsize = U_SIZE_EMREXTTEXTOUTW; break; + case U_EMR_POLYBEZIER16: rsize = U_SIZE_EMRPOLYBEZIER16; break; + case U_EMR_POLYGON16: rsize = U_SIZE_EMRPOLYGON16; break; + case U_EMR_POLYLINE16: rsize = U_SIZE_EMRPOLYLINE16; break; + case U_EMR_POLYBEZIERTO16: rsize = U_SIZE_EMRPOLYBEZIERTO16; break; + case U_EMR_POLYLINETO16: rsize = U_SIZE_EMRPOLYLINETO16; break; + case U_EMR_POLYPOLYLINE16: rsize = U_SIZE_EMRPOLYPOLYLINE16; break; + case U_EMR_POLYPOLYGON16: rsize = U_SIZE_EMRPOLYPOLYGON16; break; + case U_EMR_POLYDRAW16: rsize = U_SIZE_EMRPOLYDRAW16; break; + case U_EMR_CREATEMONOBRUSH: rsize = U_SIZE_EMRCREATEMONOBRUSH; break; + case U_EMR_CREATEDIBPATTERNBRUSHPT: rsize = U_SIZE_EMRCREATEDIBPATTERNBRUSHPT; break; + case U_EMR_EXTCREATEPEN: rsize = U_SIZE_EMREXTCREATEPEN; break; + case U_EMR_POLYTEXTOUTA: rsize = U_SIZE_EMRPOLYTEXTOUTA; break; + case U_EMR_POLYTEXTOUTW: rsize = U_SIZE_EMRPOLYTEXTOUTW; break; + case U_EMR_SETICMMODE: rsize = U_SIZE_EMRSETICMMODE; break; + case U_EMR_CREATECOLORSPACE: rsize = U_SIZE_EMRCREATECOLORSPACE; break; + case U_EMR_SETCOLORSPACE: rsize = U_SIZE_EMRSETCOLORSPACE; break; + case U_EMR_DELETECOLORSPACE: rsize = U_SIZE_EMRDELETECOLORSPACE; break; + case U_EMR_GLSRECORD: rsize = U_SIZE_EMRGLSRECORD; break; + case U_EMR_GLSBOUNDEDRECORD: rsize = U_SIZE_EMRGLSBOUNDEDRECORD; break; + case U_EMR_PIXELFORMAT: rsize = U_SIZE_EMRPIXELFORMAT; break; + case U_EMR_DRAWESCAPE: rsize = U_SIZE_EMRDRAWESCAPE; break; + case U_EMR_EXTESCAPE: rsize = U_SIZE_EMREXTESCAPE; break; + case U_EMR_UNDEF107: rsize = U_SIZE_EMRUNDEFINED; break; + case U_EMR_SMALLTEXTOUT: rsize = U_SIZE_EMRSMALLTEXTOUT; break; +// case U_EMR_FORCEUFIMAPPING: rsize = U_SIZE_EMRFORCEUFIMAPPING; break; + case U_EMR_NAMEDESCAPE: rsize = U_SIZE_EMRNAMEDESCAPE; break; +// case U_EMR_COLORCORRECTPALETTE: rsize = U_SIZE_EMRCOLORCORRECTPALETTE; break; +// case U_EMR_SETICMPROFILEA: rsize = U_SIZE_EMRSETICMPROFILEA; break; +// case U_EMR_SETICMPROFILEW: rsize = U_SIZE_EMRSETICMPROFILEW; break; + case U_EMR_ALPHABLEND: rsize = U_SIZE_EMRALPHABLEND; break; + case U_EMR_SETLAYOUT: rsize = U_SIZE_EMRSETLAYOUT; break; + case U_EMR_TRANSPARENTBLT: rsize = U_SIZE_EMRTRANSPARENTBLT; break; + case U_EMR_UNDEF117: rsize = U_SIZE_EMRUNDEFINED; break; + case U_EMR_GRADIENTFILL: rsize = U_SIZE_EMRGRADIENTFILL; break; +// case U_EMR_SETLINKEDUFIS: rsize = U_SIZE_EMRSETLINKEDUFIS; break; +// case U_EMR_SETTEXTJUSTIFICATION: rsize = U_SIZE_EMRSETTEXTJUSTIFICATION; break; + case U_EMR_COLORMATCHTOTARGETW: rsize = U_SIZE_EMRCOLORMATCHTOTARGETW; break; + case U_EMR_CREATECOLORSPACEW: rsize = U_SIZE_EMRCREATECOLORSPACEW; break; + default: rsize = U_SIZE_EMRNOTIMPLEMENTED; break; + } //end of switch + // record's declared size must be more than the minimum size for this type of record + if(*nSize < rsize){ + return(0); + } + return(1); +} + + +/** + \brief Convert an entire EMF in memory from Big Endian to Little Endian. + \return 0 on failure, 1 on success + \param contents pointer to the buffer holding the entire EMF in memory + \param length number of bytes in the buffer + \param torev 1 for native to reversed, 0 for reversed to native + + Normally this would be called immediately before writing the data to a file + or immediately after reading the data from a file. +*/ +int U_emf_endian(char *contents, size_t length, int torev){ + uint32_t off; + uint32_t OK, recnum, iType; + char *record; + const char *blimit = contents + length; /* should never wrap since it describes a structure in memory */ + int rstatus=1; + + record = contents; + OK = 1; + off = 0; + recnum = 0; + while(OK){ + + if(!U_emf_record_sizeok(record, blimit, &off, &iType, torev)){ + return(0); + } + + switch (iType) + { + case U_EMR_HEADER: rstatus=U_EMRHEADER_swap(record, torev); break; + case U_EMR_POLYBEZIER: rstatus=U_EMRPOLYBEZIER_swap(record, torev); break; + case U_EMR_POLYGON: rstatus=U_EMRPOLYGON_swap(record, torev); break; + case U_EMR_POLYLINE: rstatus=U_EMRPOLYLINE_swap(record, torev); break; + case U_EMR_POLYBEZIERTO: rstatus=U_EMRPOLYBEZIERTO_swap(record, torev); break; + case U_EMR_POLYLINETO: rstatus=U_EMRPOLYLINETO_swap(record, torev); break; + case U_EMR_POLYPOLYLINE: rstatus=U_EMRPOLYPOLYLINE_swap(record, torev); break; + case U_EMR_POLYPOLYGON: rstatus=U_EMRPOLYPOLYGON_swap(record, torev); break; + case U_EMR_SETWINDOWEXTEX: rstatus=U_EMRSETWINDOWEXTEX_swap(record, torev); break; + case U_EMR_SETWINDOWORGEX: rstatus=U_EMRSETWINDOWORGEX_swap(record, torev); break; + case U_EMR_SETVIEWPORTEXTEX: rstatus=U_EMRSETVIEWPORTEXTEX_swap(record, torev); break; + case U_EMR_SETVIEWPORTORGEX: rstatus=U_EMRSETVIEWPORTORGEX_swap(record, torev); break; + case U_EMR_SETBRUSHORGEX: rstatus=U_EMRSETBRUSHORGEX_swap(record, torev); break; + case U_EMR_EOF: + rstatus=U_EMREOF_swap(record, torev); + OK = 0; /* Exit triggered here */ + break; + case U_EMR_SETPIXELV: rstatus=U_EMRSETPIXELV_swap(record, torev); break; + case U_EMR_SETMAPPERFLAGS: rstatus=U_EMRSETMAPPERFLAGS_swap(record, torev); break; + case U_EMR_SETMAPMODE: rstatus=U_EMRSETMAPMODE_swap(record, torev); break; + case U_EMR_SETBKMODE: rstatus=U_EMRSETBKMODE_swap(record, torev); break; + case U_EMR_SETPOLYFILLMODE: rstatus=U_EMRSETPOLYFILLMODE_swap(record, torev); break; + case U_EMR_SETROP2: rstatus=U_EMRSETROP2_swap(record, torev); break; + case U_EMR_SETSTRETCHBLTMODE: rstatus=U_EMRSETSTRETCHBLTMODE_swap(record, torev); break; + case U_EMR_SETTEXTALIGN: rstatus=U_EMRSETTEXTALIGN_swap(record, torev); break; + case U_EMR_SETCOLORADJUSTMENT: rstatus=U_EMRSETCOLORADJUSTMENT_swap(record, torev); break; + case U_EMR_SETTEXTCOLOR: rstatus=U_EMRSETTEXTCOLOR_swap(record, torev); break; + case U_EMR_SETBKCOLOR: rstatus=U_EMRSETBKCOLOR_swap(record, torev); break; + case U_EMR_OFFSETCLIPRGN: rstatus=U_EMROFFSETCLIPRGN_swap(record, torev); break; + case U_EMR_MOVETOEX: rstatus=U_EMRMOVETOEX_swap(record, torev); break; + case U_EMR_SETMETARGN: rstatus=U_EMRSETMETARGN_swap(record, torev); break; + case U_EMR_EXCLUDECLIPRECT: rstatus=U_EMREXCLUDECLIPRECT_swap(record, torev); break; + case U_EMR_INTERSECTCLIPRECT: rstatus=U_EMRINTERSECTCLIPRECT_swap(record, torev); break; + case U_EMR_SCALEVIEWPORTEXTEX: rstatus=U_EMRSCALEVIEWPORTEXTEX_swap(record, torev); break; + case U_EMR_SCALEWINDOWEXTEX: rstatus=U_EMRSCALEWINDOWEXTEX_swap(record, torev); break; + case U_EMR_SAVEDC: rstatus=U_EMRSAVEDC_swap(record, torev); break; + case U_EMR_RESTOREDC: rstatus=U_EMRRESTOREDC_swap(record, torev); break; + case U_EMR_SETWORLDTRANSFORM: rstatus=U_EMRSETWORLDTRANSFORM_swap(record, torev); break; + case U_EMR_MODIFYWORLDTRANSFORM: rstatus=U_EMRMODIFYWORLDTRANSFORM_swap(record, torev); break; + case U_EMR_SELECTOBJECT: rstatus=U_EMRSELECTOBJECT_swap(record, torev); break; + case U_EMR_CREATEPEN: rstatus=U_EMRCREATEPEN_swap(record, torev); break; + case U_EMR_CREATEBRUSHINDIRECT: rstatus=U_EMRCREATEBRUSHINDIRECT_swap(record, torev); break; + case U_EMR_DELETEOBJECT: rstatus=U_EMRDELETEOBJECT_swap(record, torev); break; + case U_EMR_ANGLEARC: rstatus=U_EMRANGLEARC_swap(record, torev); break; + case U_EMR_ELLIPSE: rstatus=U_EMRELLIPSE_swap(record, torev); break; + case U_EMR_RECTANGLE: rstatus=U_EMRRECTANGLE_swap(record, torev); break; + case U_EMR_ROUNDRECT: rstatus=U_EMRROUNDRECT_swap(record, torev); break; + case U_EMR_ARC: rstatus=U_EMRARC_swap(record, torev); break; + case U_EMR_CHORD: rstatus=U_EMRCHORD_swap(record, torev); break; + case U_EMR_PIE: rstatus=U_EMRPIE_swap(record, torev); break; + case U_EMR_SELECTPALETTE: rstatus=U_EMRSELECTPALETTE_swap(record, torev); break; + case U_EMR_CREATEPALETTE: rstatus=U_EMRCREATEPALETTE_swap(record, torev); break; + case U_EMR_SETPALETTEENTRIES: rstatus=U_EMRSETPALETTEENTRIES_swap(record, torev); break; + case U_EMR_RESIZEPALETTE: rstatus=U_EMRRESIZEPALETTE_swap(record, torev); break; + case U_EMR_REALIZEPALETTE: rstatus=U_EMRREALIZEPALETTE_swap(record, torev); break; + case U_EMR_EXTFLOODFILL: rstatus=U_EMREXTFLOODFILL_swap(record, torev); break; + case U_EMR_LINETO: rstatus=U_EMRLINETO_swap(record, torev); break; + case U_EMR_ARCTO: rstatus=U_EMRARCTO_swap(record, torev); break; + case U_EMR_POLYDRAW: rstatus=U_EMRPOLYDRAW_swap(record, torev); break; + case U_EMR_SETARCDIRECTION: rstatus=U_EMRSETARCDIRECTION_swap(record, torev); break; + case U_EMR_SETMITERLIMIT: rstatus=U_EMRSETMITERLIMIT_swap(record, torev); break; + case U_EMR_BEGINPATH: rstatus=U_EMRBEGINPATH_swap(record, torev); break; + case U_EMR_ENDPATH: rstatus=U_EMRENDPATH_swap(record, torev); break; + case U_EMR_CLOSEFIGURE: rstatus=U_EMRCLOSEFIGURE_swap(record, torev); break; + case U_EMR_FILLPATH: rstatus=U_EMRFILLPATH_swap(record, torev); break; + case U_EMR_STROKEANDFILLPATH: rstatus=U_EMRSTROKEANDFILLPATH_swap(record, torev); break; + case U_EMR_STROKEPATH: rstatus=U_EMRSTROKEPATH_swap(record, torev); break; + case U_EMR_FLATTENPATH: rstatus=U_EMRFLATTENPATH_swap(record, torev); break; + case U_EMR_WIDENPATH: rstatus=U_EMRWIDENPATH_swap(record, torev); break; + case U_EMR_SELECTCLIPPATH: rstatus=U_EMRSELECTCLIPPATH_swap(record, torev); break; + case U_EMR_ABORTPATH: rstatus=U_EMRABORTPATH_swap(record, torev); break; + case U_EMR_UNDEF69: rstatus=U_EMRUNDEF69_swap(record, torev); break; + case U_EMR_COMMENT: rstatus=U_EMRCOMMENT_swap(record, torev); break; + case U_EMR_FILLRGN: rstatus=U_EMRFILLRGN_swap(record, torev); break; + case U_EMR_FRAMERGN: rstatus=U_EMRFRAMERGN_swap(record, torev); break; + case U_EMR_INVERTRGN: rstatus=U_EMRINVERTRGN_swap(record, torev); break; + case U_EMR_PAINTRGN: rstatus=U_EMRPAINTRGN_swap(record, torev); break; + case U_EMR_EXTSELECTCLIPRGN: rstatus=U_EMREXTSELECTCLIPRGN_swap(record, torev);break; + case U_EMR_BITBLT: rstatus=U_EMRBITBLT_swap(record, torev); break; + case U_EMR_STRETCHBLT: rstatus=U_EMRSTRETCHBLT_swap(record, torev); break; + case U_EMR_MASKBLT: rstatus=U_EMRMASKBLT_swap(record, torev); break; + case U_EMR_PLGBLT: rstatus=U_EMRPLGBLT_swap(record, torev); break; + case U_EMR_SETDIBITSTODEVICE: rstatus=U_EMRSETDIBITSTODEVICE_swap(record, torev); break; + case U_EMR_STRETCHDIBITS: rstatus=U_EMRSTRETCHDIBITS_swap(record, torev); break; + case U_EMR_EXTCREATEFONTINDIRECTW: rstatus=U_EMREXTCREATEFONTINDIRECTW_swap(record, torev); break; + case U_EMR_EXTTEXTOUTA: rstatus=U_EMREXTTEXTOUTA_swap(record, torev); break; + case U_EMR_EXTTEXTOUTW: rstatus=U_EMREXTTEXTOUTW_swap(record, torev); break; + case U_EMR_POLYBEZIER16: rstatus=U_EMRPOLYBEZIER16_swap(record, torev); break; + case U_EMR_POLYGON16: rstatus=U_EMRPOLYGON16_swap(record, torev); break; + case U_EMR_POLYLINE16: rstatus=U_EMRPOLYLINE16_swap(record, torev); break; + case U_EMR_POLYBEZIERTO16: rstatus=U_EMRPOLYBEZIERTO16_swap(record, torev); break; + case U_EMR_POLYLINETO16: rstatus=U_EMRPOLYLINETO16_swap(record, torev); break; + case U_EMR_POLYPOLYLINE16: rstatus=U_EMRPOLYPOLYLINE16_swap(record, torev); break; + case U_EMR_POLYPOLYGON16: rstatus=U_EMRPOLYPOLYGON16_swap(record, torev); break; + case U_EMR_POLYDRAW16: rstatus=U_EMRPOLYDRAW16_swap(record, torev); break; + case U_EMR_CREATEMONOBRUSH: rstatus=U_EMRCREATEMONOBRUSH_swap(record, torev); break; + case U_EMR_CREATEDIBPATTERNBRUSHPT: rstatus=U_EMRCREATEDIBPATTERNBRUSHPT_swap(record, torev); break; + case U_EMR_EXTCREATEPEN: rstatus=U_EMREXTCREATEPEN_swap(record, torev); break; + case U_EMR_POLYTEXTOUTA: rstatus=U_EMRPOLYTEXTOUTA_swap(record, torev); break; + case U_EMR_POLYTEXTOUTW: rstatus=U_EMRPOLYTEXTOUTW_swap(record, torev); break; + case U_EMR_SETICMMODE: rstatus=U_EMRSETICMMODE_swap(record, torev); break; + case U_EMR_CREATECOLORSPACE: rstatus=U_EMRCREATECOLORSPACE_swap(record, torev); break; + case U_EMR_SETCOLORSPACE: rstatus=U_EMRSETCOLORSPACE_swap(record, torev); break; + case U_EMR_DELETECOLORSPACE: rstatus=U_EMRDELETECOLORSPACE_swap(record, torev); break; + case U_EMR_GLSRECORD: rstatus=U_EMRGLSRECORD_swap(record, torev); break; + case U_EMR_GLSBOUNDEDRECORD: rstatus=U_EMRGLSBOUNDEDRECORD_swap(record, torev); break; + case U_EMR_PIXELFORMAT: rstatus=U_EMRPIXELFORMAT_swap(record, torev); break; + case U_EMR_DRAWESCAPE: rstatus=U_EMRDRAWESCAPE_swap(record, torev); break; + case U_EMR_EXTESCAPE: rstatus=U_EMREXTESCAPE_swap(record, torev); break; + case U_EMR_UNDEF107: rstatus=U_EMRUNDEF107_swap(record, torev); break; + case U_EMR_SMALLTEXTOUT: rstatus=U_EMRSMALLTEXTOUT_swap(record, torev); break; + case U_EMR_FORCEUFIMAPPING: rstatus=U_EMRFORCEUFIMAPPING_swap(record, torev); break; + case U_EMR_NAMEDESCAPE: rstatus=U_EMRNAMEDESCAPE_swap(record, torev); break; + case U_EMR_COLORCORRECTPALETTE: rstatus=U_EMRCOLORCORRECTPALETTE_swap(record, torev); break; + case U_EMR_SETICMPROFILEA: rstatus=U_EMRSETICMPROFILEA_swap(record, torev); break; + case U_EMR_SETICMPROFILEW: rstatus=U_EMRSETICMPROFILEW_swap(record, torev); break; + case U_EMR_ALPHABLEND: rstatus=U_EMRALPHABLEND_swap(record, torev); break; + case U_EMR_SETLAYOUT: rstatus=U_EMRSETLAYOUT_swap(record, torev); break; + case U_EMR_TRANSPARENTBLT: rstatus=U_EMRTRANSPARENTBLT_swap(record, torev); break; + case U_EMR_UNDEF117: rstatus=U_EMRUNDEF117_swap(record, torev); break; + case U_EMR_GRADIENTFILL: rstatus=U_EMRGRADIENTFILL_swap(record, torev); break; + case U_EMR_SETLINKEDUFIS: rstatus=U_EMRSETLINKEDUFIS_swap(record, torev); break; + case U_EMR_SETTEXTJUSTIFICATION: rstatus=U_EMRSETTEXTJUSTIFICATION_swap(record, torev); break; + case U_EMR_COLORMATCHTOTARGETW: rstatus=U_EMRCOLORMATCHTOTARGETW_swap(record, torev); break; + case U_EMR_CREATECOLORSPACEW: rstatus=U_EMRCREATECOLORSPACEW_swap(record, torev); break; + default: rstatus=U_EMRNOTIMPLEMENTED_swap(record, torev); break; + } //end of switch + if(!rstatus){ + return(rstatus); + } + record += off; + recnum++; + } //end of while + + return(1); +} + +#ifdef __cplusplus +} +#endif diff --git a/src/3rdparty/libuemf/uemf_endian.h b/src/3rdparty/libuemf/uemf_endian.h new file mode 100644 index 0000000..9dbcec4 --- /dev/null +++ b/src/3rdparty/libuemf/uemf_endian.h @@ -0,0 +1,59 @@ +/** + @file uemf_endian.h + + @brief Defintions and prototype for function for converting EMF records between Big Endian and Little Endian byte orders. +*/ + +/* +File: uemf_endian.h +Version: 0.0.4 +Date: 24-MAR-2015 +Author: David Mathog, Biology Division, Caltech +email: mathog@caltech.edu +Copyright: 2015 David Mathog and California Institute of Technology (Caltech) +*/ + +#ifndef _UEMF_ENDIAN_ +#define _UEMF_ENDIAN_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** \defgroup U_Endian Byte order identification + + There is no way for the preprocessor, in general, to figure out endianness. So the command line must define + WORDS_BIGENDIAN for a big endian machine. Otherwise we assume is is little endian. If it is something + else this code won't work in any case. + + @{ +*/ + +#ifdef WORDS_BIGENDIAN +#define U_BYTE_SWAP 1 //!< byte swapping into metafile is required +#define U_IS_BE 1 //!< this machine is big endian +#define U_IS_LE 0 //!< this machine is not little endian +#else +#define U_BYTE_SWAP 0 //!< byte swapping into metafile is not required +#define U_IS_BE 0 //!< this machine is not big endian +#define U_IS_LE 1 //!< this machine is little endian +#endif + +#define U_XE 0 //!< do not rearrange endian for target +#define U_LE 1 //!< target is Little Endian +#define U_BE 2 //!< target is Big Endian +#define U_RP 4 //!< replicate first instance +#define U_XX 0xFF //!< may be used to terminate a list of these target entries +/** @} */ + +//! \cond +// prototypes +int U_emf_endian(char *contents, size_t length, int torev); +int U_emf_record_sizeok(const char *record, const char *blimit, uint32_t *nSize, uint32_t *iType, int torev); +//! \endcond + +#ifdef __cplusplus +} +#endif + +#endif /* _UEMF_ENDIAN_ */ diff --git a/src/3rdparty/libuemf/uemf_print.c b/src/3rdparty/libuemf/uemf_print.c new file mode 100644 index 0000000..74fa5ae --- /dev/null +++ b/src/3rdparty/libuemf/uemf_print.c @@ -0,0 +1,2704 @@ +/** + @file uemf_print.c + + @brief Functions for printing EMF records +*/ + +/* +File: uemf_print.c +Version: 0.0.22 +Date: 12-MAY-2020 +Author: David Mathog, Biology Division, Caltech +email: mathog@caltech.edu +Copyright: 2020 David Mathog and California Institute of Technology (Caltech) +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdlib.h> +#include <stdio.h> +#include <stddef.h> /* for offsetof() macro */ +#include <string.h> +#include "uemf.h" +#include "upmf_print.h" +#include "uemf_safe.h" + +//! \cond +#define UNUSED(x) (void)(x) +/* This bit of code is used all over the place, so reduce it to a DEFINITION */ +#define IF_MEM_UNSAFE_PRINT_AND_RETURN(A,B,C) if(IS_MEM_UNSAFE(A,B,C)){printf(" record corruption HERE\n"); return; } + +/* one needed prototype */ +void U_swap4(void *ul, unsigned int count); +//! \endcond + +/** + \brief calculate a CRC32 value for record + \returns CRC32 value calculated for record + \param record pointer to the first byte + \param Size number of bytes in the record + +Code based on example crc32b here: + http://www.hackersdelight.org/hdcodetxt/crc.c.txt +*/ +uint32_t lu_crc32(const char *record, uint32_t Size){ + const unsigned char *message = (const unsigned char *)record; + uint32_t i, j; + uint32_t crc, mask; + + crc = 0xFFFFFFFF; + for(i=0;i<Size;i++){ // over all bytes + crc = crc ^ *message++; + for (j = 0; j < 8; j++) { // over all bits + mask = -(crc & 1); + crc = (crc >> 1) ^ (0xEDB88320 & mask); + } + } + return ~crc; +} + +/** + \brief Print some number of hex bytes + \param buf pointer to the first byte + \param num number of bytes +*/ +void hexbytes_print(uint8_t *buf,unsigned int num){ + for(; num; num--,buf++){ + printf("%2.2X",*buf); + } +} + + +/* ********************************************************************************************** + These functions print standard objects used in the EMR records. + The low level ones do not append EOL. +*********************************************************************************************** */ + + + +/** + \brief Print a U_COLORREF object. + \param color U_COLORREF object +*/ +void colorref_print( + U_COLORREF color + ){ + printf("{%u,%u,%u} ",color.Red,color.Green,color.Blue); +} + + +/** + \brief Print a U_RGBQUAD object. + \param color U_RGBQUAD object +*/ +void rgbquad_print( + U_RGBQUAD color + ){ + printf("{%u,%u,%u,%u} ",color.Blue,color.Green,color.Red,color.Reserved); +} + +/** + \brief Print rect and rectl objects from Upper Left and Lower Right corner points. + \param rect U_RECTL object +*/ +void rectl_print( + U_RECTL rect + ){ + printf("{%d,%d,%d,%d} ",rect.left,rect.top,rect.right,rect.bottom); +} + +/** + \brief Print a U_SIZEL object. + \param sz U_SizeL object +*/ +void sizel_print( + U_SIZEL sz + ){ + printf("{%d,%d} ",sz.cx ,sz.cy); +} + +/** + \brief Print a U_POINTL object + \param pt U_POINTL object +*/ +void pointl_print( + U_POINTL pt + ){ + printf("{%d,%d} ",pt.x ,pt.y); +} + +/** + \brief Print a pointer to a U_POINT16 object + \param pt pointer to a U_POINT16 object + Warning - WMF data may contain unaligned U_POINT16, do not call + this routine with a pointer to such data! +*/ +void point16_print( + U_POINT16 pt + ){ + printf("{%d,%d} ",pt.x ,pt.y); +} + +/** + \brief Print a U_LCS_GAMMA object + \param lg U_LCS_GAMMA object +*/ +void lcs_gamma_print( + U_LCS_GAMMA lg + ){ + uint8_t tmp; + tmp = lg.ignoreHi; printf("ignoreHi:%u ",tmp); + tmp = lg.intPart ; printf("intPart :%u ",tmp); + tmp = lg.fracPart; printf("fracPart:%u ",tmp); + tmp = lg.ignoreLo; printf("ignoreLo:%u ",tmp); +} + +/** + \brief Print a U_LCS_GAMMARGB object + \param lgr U_LCS_GAMMARGB object +*/ +void lcs_gammargb_print( + U_LCS_GAMMARGB lgr + ){ + printf("lcsGammaRed:"); lcs_gamma_print(lgr.lcsGammaRed ); + printf("lcsGammaGreen:"); lcs_gamma_print(lgr.lcsGammaGreen); + printf("lcsGammaBlue:"); lcs_gamma_print(lgr.lcsGammaBlue ); +} + +/** + \brief Print a U_TRIVERTEX object. + \param tv U_TRIVERTEX object. +*/ +void trivertex_print( + U_TRIVERTEX tv + ){ + printf("{{%d,%d},{%u,%u,%u,%u}} ",tv.x,tv.y,tv.Red,tv.Green,tv.Blue,tv.Alpha); +} + +/** + \brief Print a U_GRADIENT3 object. + \param g3 U_GRADIENT3 object. +*/ +void gradient3_print( + U_GRADIENT3 g3 + ){ + printf("{%u,%u,%u} ",g3.Vertex1,g3.Vertex2,g3.Vertex3); +} + +/** + \brief Print a U_GRADIENT4 object. + \param g4 U_GRADIENT4 object. +*/ +void gradient4_print( + U_GRADIENT4 g4 + ){ + printf("{%u,%u} ",g4.UpperLeft,g4.LowerRight); +} + +/** + \brief Print a U_LOGBRUSH object. + \param lb U_LOGBRUSH object. +*/ +void logbrush_print( + U_LOGBRUSH lb + ){ + printf("lbStyle:0x%8.8X ", lb.lbStyle); + printf("lbColor:"); colorref_print(lb.lbColor); + printf("lbHatch:0x%8.8X ", lb.lbHatch); +} + +/** + \brief Print a U_XFORM object. + \param xform U_XFORM object +*/ +void xform_print( + U_XFORM xform + ){ + printf("{%f,%f.%f,%f,%f,%f} ",xform.eM11,xform.eM12,xform.eM21,xform.eM22,xform.eDx,xform.eDy); +} + +/** + \brief Print a U_CIEXYZ object + \param ciexyz U_CIEXYZ object +*/ +void ciexyz_print( + U_CIEXYZ ciexyz + ){ + printf("{%d,%d.%d} ",ciexyz.ciexyzX,ciexyz.ciexyzY,ciexyz.ciexyzZ); + +} + +/** + \brief Print a U_CIEXYZTRIPLE object + \param cie3 U_CIEXYZTRIPLE object +*/ +void ciexyztriple_print( + U_CIEXYZTRIPLE cie3 + ){ + printf("{Red:"); ciexyz_print(cie3.ciexyzRed ); + printf(", Green:"); ciexyz_print(cie3.ciexyzGreen); + printf(", Blue:"); ciexyz_print(cie3.ciexyzBlue ); + printf("} "); +} +/** + \brief Print a U_LOGCOLORSPACEA object. + \param lcsa U_LOGCOLORSPACEA object +*/ +void logcolorspacea_print( + U_LOGCOLORSPACEA lcsa + ){ + printf("lcsSignature:%u ",lcsa.lcsSignature); + printf("lcsVersion:%u ", lcsa.lcsVersion ); + printf("lcsSize:%u ", lcsa.lcsSize ); + printf("lcsCSType:%d ", lcsa.lcsCSType ); + printf("lcsIntent:%d ", lcsa.lcsIntent ); + printf("lcsEndpoints:"); ciexyztriple_print(lcsa.lcsEndpoints); + printf("lcsGammaRGB: "); lcs_gammargb_print(lcsa.lcsGammaRGB ); + printf("filename:%s ", lcsa.lcsFilename ); +} + +/** + + \brief Print a U_LOGCOLORSPACEW object. + \param lcsa U_LOGCOLORSPACEW object +*/ +void logcolorspacew_print( + U_LOGCOLORSPACEW lcsa + ){ + char *string; + printf("lcsSignature:%d ",lcsa.lcsSignature); + printf("lcsVersion:%d ", lcsa.lcsVersion ); + printf("lcsSize:%d ", lcsa.lcsSize ); + printf("lcsCSType:%d ", lcsa.lcsCSType ); + printf("lcsIntent:%d ", lcsa.lcsIntent ); + printf("lcsEndpoints:"); ciexyztriple_print(lcsa.lcsEndpoints); + printf("lcsGammaRGB: "); lcs_gammargb_print(lcsa.lcsGammaRGB ); + string = U_Utf16leToUtf8(lcsa.lcsFilename, U_MAX_PATH, NULL); + printf("filename:%s ", string ); + free(string); +} + +/** + \brief Print a U_PANOSE object. + \param panose U_PANOSE object +*/ +void panose_print( + U_PANOSE panose + ){ + printf("bFamilyType:%u ", panose.bFamilyType ); + printf("bSerifStyle:%u ", panose.bSerifStyle ); + printf("bWeight:%u ", panose.bWeight ); + printf("bProportion:%u ", panose.bProportion ); + printf("bContrast:%u ", panose.bContrast ); + printf("bStrokeVariation:%u ",panose.bStrokeVariation); + printf("bArmStyle:%u ", panose.bArmStyle ); + printf("bLetterform:%u ", panose.bLetterform ); + printf("bMidline:%u ", panose.bMidline ); + printf("bXHeight:%u ", panose.bXHeight ); +} + +/** + \brief Print a U_LOGFONT object. + \param lf U_LOGFONT object +*/ +void logfont_print( + U_LOGFONT lf + ){ + char *string; + printf("lfHeight:%d ", lf.lfHeight ); + printf("lfWidth:%d ", lf.lfWidth ); + printf("lfEscapement:%d ", lf.lfEscapement ); + printf("lfOrientation:%d ", lf.lfOrientation ); + printf("lfWeight:%d ", lf.lfWeight ); + printf("lfItalic:0x%2.2X ", lf.lfItalic ); + printf("lfUnderline:0x%2.2X ", lf.lfUnderline ); + printf("lfStrikeOut:0x%2.2X ", lf.lfStrikeOut ); + printf("lfCharSet:0x%2.2X ", lf.lfCharSet ); + printf("lfOutPrecision:0x%2.2X ", lf.lfOutPrecision ); + printf("lfClipPrecision:0x%2.2X ", lf.lfClipPrecision ); + printf("lfQuality:0x%2.2X ", lf.lfQuality ); + printf("lfPitchAndFamily:0x%2.2X ", lf.lfPitchAndFamily); + string = U_Utf16leToUtf8(lf.lfFaceName, U_LF_FACESIZE, NULL); + printf("lfFaceName:%s ", string ); + free(string); +} + +/** + \brief Print a U_LOGFONT_PANOSE object. + \return U_LOGFONT_PANOSE object +*/ +void logfont_panose_print( + U_LOGFONT_PANOSE lfp + ){ + char *string; + printf("elfLogFont:"); logfont_print(lfp.elfLogFont); + string = U_Utf16leToUtf8(lfp.elfFullName, U_LF_FULLFACESIZE, NULL); + printf("elfFullName:%s ", string ); + free(string); + string = U_Utf16leToUtf8(lfp.elfStyle, U_LF_FACESIZE, NULL); + printf("elfStyle:%s ", string ); + free(string); + printf("elfVersion:%u " ,lfp.elfVersion ); + printf("elfStyleSize:%u " ,lfp.elfStyleSize); + printf("elfMatch:%u " ,lfp.elfMatch ); + printf("elfReserved:%u " ,lfp.elfReserved ); + printf("elfVendorId:"); hexbytes_print((uint8_t *)lfp.elfVendorId,U_ELF_VENDOR_SIZE); printf(" "); + printf("elfCulture:%u " ,lfp.elfCulture ); + printf("elfPanose:"); panose_print(lfp.elfPanose); +} + +/** + \brief Print a pointer to U_BITMAPINFOHEADER object. + + This may be called indirectly from WMF _print routines, where problems could occur + if the data was passed as the struct or a pointer to the struct, as the struct may not + be aligned in memory. + + \returns Actual number of color table entries. + \param Bmih pointer to a U_BITMAPINFOHEADER object +*/ +int bitmapinfoheader_print( + const char *Bmih + ){ + uint32_t utmp4; + int32_t tmp4; + int16_t tmp2; + int Colors, BitCount, Width, Height, RealColors; + + /* DIB from a WMF may not be properly aligned on a 4 byte boundary, will be aligned on a 2 byte boundary */ + + memcpy(&utmp4, Bmih + offsetof(U_BITMAPINFOHEADER,biSize), 4); printf("biSize:%u " ,utmp4 ); + memcpy(&tmp4, Bmih + offsetof(U_BITMAPINFOHEADER,biWidth), 4); printf("biWidth:%d " ,tmp4 ); + Width = tmp4; + memcpy(&tmp4, Bmih + offsetof(U_BITMAPINFOHEADER,biHeight), 4); printf("biHeight:%d " ,tmp4 ); + Height = tmp4; + memcpy(&tmp2, Bmih + offsetof(U_BITMAPINFOHEADER,biPlanes), 2); printf("biPlanes:%u " ,tmp2 ); + memcpy(&tmp2, Bmih + offsetof(U_BITMAPINFOHEADER,biBitCount), 2); printf("biBitCount:%u " ,tmp2 ); + BitCount = tmp2; + memcpy(&utmp4, Bmih + offsetof(U_BITMAPINFOHEADER,biCompression), 4); printf("biCompression:%u " ,utmp4 ); + memcpy(&utmp4, Bmih + offsetof(U_BITMAPINFOHEADER,biSizeImage), 4); printf("biSizeImage:%u " ,utmp4 ); + memcpy(&tmp4, Bmih + offsetof(U_BITMAPINFOHEADER,biXPelsPerMeter), 4); printf("biXPelsPerMeter:%d " ,tmp4 ); + memcpy(&tmp4, Bmih + offsetof(U_BITMAPINFOHEADER,biYPelsPerMeter), 4); printf("biYPelsPerMeter:%d " ,tmp4 ); + memcpy(&utmp4, Bmih + offsetof(U_BITMAPINFOHEADER,biClrUsed), 4); printf("biClrUsed:%u " ,utmp4 ); + Colors = utmp4; + memcpy(&utmp4, Bmih + offsetof(U_BITMAPINFOHEADER,biClrImportant), 4); printf("biClrImportant:%u " ,utmp4 ); + RealColors = get_real_color_icount(Colors, BitCount, Width, Height); + printf("ColorEntries:%d ",RealColors); + return(RealColors); +} + + +/** + \brief Print a Pointer to a U_BITMAPINFO object. + \param Bmi Pointer to a U_BITMAPINFO object + \param blimit Pointer to the first byte after after this record + This may be called from WMF _print routines, where problems could occur + if the data was passed as the struct or a pointer to the struct, as the struct may not + be aligned in memory. +*/ +void bitmapinfo_print( + const char *Bmi, + const char *blimit + ){ + int i,k; + int ClrUsed; + U_RGBQUAD BmiColor; + printf("BmiHeader: "); + IF_MEM_UNSAFE_PRINT_AND_RETURN(Bmi, offsetof(U_BITMAPINFO,bmiHeader) + sizeof(U_BITMAPINFOHEADER), blimit); + ClrUsed = bitmapinfoheader_print(Bmi + offsetof(U_BITMAPINFO,bmiHeader)); + if(ClrUsed){ + k= offsetof(U_BITMAPINFO,bmiColors); + IF_MEM_UNSAFE_PRINT_AND_RETURN(Bmi, offsetof(U_BITMAPINFO,bmiColors) + ClrUsed*sizeof(U_RGBQUAD), blimit); + for(i=0; i<ClrUsed; i++, k+= sizeof(U_RGBQUAD)){ + memcpy(&BmiColor, Bmi+k, sizeof(U_RGBQUAD)); + printf("%d:",i); rgbquad_print(BmiColor); + } + } +} + +/** + \brief Print a U_BLEND object. + \param blend a U_BLEND object +*/ +void blend_print( + U_BLEND blend + ){ + printf("Operation:%u " ,blend.Operation); + printf("Flags:%u " ,blend.Flags ); + printf("Global:%u " ,blend.Global ); + printf("Op:%u " ,blend.Op ); +} + +/** + \brief Print a pointer to a U_EXTLOGPEN object. + \param elp PU_EXTLOGPEN object +*/ +void extlogpen_print( + PU_EXTLOGPEN elp + ){ + unsigned int i; + U_STYLEENTRY *elpStyleEntry; + printf("elpPenStyle:0x%8.8X " ,elp->elpPenStyle ); + printf("elpWidth:%u " ,elp->elpWidth ); + printf("elpBrushStyle:0x%8.8X " ,elp->elpBrushStyle); + printf("elpColor"); colorref_print(elp->elpColor); + printf("elpHatch:%d " ,elp->elpHatch ); + printf("elpNumEntries:%u " ,elp->elpNumEntries); + if(elp->elpNumEntries){ + printf("elpStyleEntry:"); + elpStyleEntry = (uint32_t *) elp->elpStyleEntry; + for(i=0;i<elp->elpNumEntries;i++){ + printf("%d:%u ",i,elpStyleEntry[i]); + } + } +} + +/** + \brief Print a U_LOGPEN object. + \param lp U_LOGPEN object + +*/ +void logpen_print( + U_LOGPEN lp + ){ + printf("lopnStyle:0x%8.8X " ,lp.lopnStyle ); + printf("lopnWidth:"); pointl_print( lp.lopnWidth ); + printf("lopnColor:"); colorref_print(lp.lopnColor ); +} + +/** + \brief Print a U_LOGPLTNTRY object. + \param lpny Ignore U_LOGPLTNTRY object. +*/ +void logpltntry_print( + U_LOGPLTNTRY lpny + ){ + printf("peReserved:%u " ,lpny.peReserved ); + printf("peRed:%u " ,lpny.peRed ); + printf("peGreen:%u " ,lpny.peGreen ); + printf("peBlue:%u " ,lpny.peBlue ); +} + +/** + \brief Print a pointer to a U_LOGPALETTE object. + \param lp Pointer to a U_LOGPALETTE object. +*/ +void logpalette_print( + PU_LOGPALETTE lp + ){ + int i; + PU_LOGPLTNTRY palPalEntry; + printf("palVersion:%u ", lp->palVersion ); + printf("palNumEntries:%u ", lp->palNumEntries ); + if(lp->palNumEntries){ + palPalEntry = (PU_LOGPLTNTRY) &(lp->palPalEntry); + for(i=0;i<lp->palNumEntries;i++){ + printf("%d:",i); logpltntry_print(palPalEntry[i]); + } + } +} + +/** + \brief Print a U_RGNDATAHEADER object. + \param rdh U_RGNDATAHEADER object +*/ +void rgndataheader_print( + U_RGNDATAHEADER rdh + ){ + printf("dwSize:%u ", rdh.dwSize ); + printf("iType:%u ", rdh.iType ); + printf("nCount:%u ", rdh.nCount ); + printf("nRgnSize:%u ", rdh.nRgnSize ); + printf("rclBounds:"); rectl_print(rdh.rclBounds ); +} + +/** + \brief Print a pointer to a U_RGNDATA object. + \param rd pointer to a U_RGNDATA object. + \param limit pointer that sets upper limit for data examination +*/ +void rgndata_print( + PU_RGNDATA rd, + const char *blimit + ){ + unsigned int i; + PU_RECTL rects; + IF_MEM_UNSAFE_PRINT_AND_RETURN(rd, sizeof(U_RGNDATAHEADER), blimit); + printf("rdh: "); rgndataheader_print(rd->rdh ); printf(" rects: "); + if(rd->rdh.nCount){ + rects = (PU_RECTL) &(rd->Buffer); + IF_MEM_UNSAFE_PRINT_AND_RETURN(rects, rd->rdh.nCount * sizeof(U_RECTL), blimit); + for(i=0;i<rd->rdh.nCount;i++){ + printf("%d:",i); rectl_print(rects[i]); + } + } +} + +/** + \brief Print a U_COLORADJUSTMENT object. + \param ca U_COLORADJUSTMENT object. +*/ +void coloradjustment_print( + U_COLORADJUSTMENT ca + ){ + printf("caSize:%u " ,ca.caSize ); + printf("caFlags:0x%4.4X " ,ca.caFlags ); + printf("caIlluminantIndex:%u " ,ca.caIlluminantIndex); + printf("caRedGamma:%u " ,ca.caRedGamma ); + printf("caGreenGamma:%u " ,ca.caGreenGamma ); + printf("caBlueGamma:%u " ,ca.caBlueGamma ); + printf("caReferenceBlack:%u " ,ca.caReferenceBlack ); + printf("caReferenceWhite:%u " ,ca.caReferenceWhite ); + printf("caContrast:%d " ,ca.caContrast ); + printf("caBrightness:%d " ,ca.caBrightness ); + printf("caColorfulness:%d " ,ca.caColorfulness ); + printf("caRedGreenTint:%d " ,ca.caRedGreenTint ); +} + +/** + \brief Print a U_PIXELFORMATDESCRIPTOR object. + \param pfd U_PIXELFORMATDESCRIPTOR object +*/ +void pixelformatdescriptor_print( + U_PIXELFORMATDESCRIPTOR pfd + ){ + printf("nSize:%u " ,pfd.nSize ); + printf("nVersion:%u " ,pfd.nVersion ); + printf("dwFlags:0x%8.8X " ,pfd.dwFlags ); + printf("iPixelType:%u " ,pfd.iPixelType ); + printf("cColorBits:%u " ,pfd.cColorBits ); + printf("cRedBits:%u " ,pfd.cRedBits ); + printf("cRedShift:%u " ,pfd.cRedShift ); + printf("cGreenBits:%u " ,pfd.cGreenBits ); + printf("cGreenShift:%u " ,pfd.cGreenShift ); + printf("cBlueBits:%u " ,pfd.cBlueBits ); + printf("cBlueShift:%u " ,pfd.cBlueShift ); + printf("cAlphaBits:%u " ,pfd.cAlphaBits ); + printf("cAlphaShift:%u " ,pfd.cAlphaShift ); + printf("cAccumBits:%u " ,pfd.cAccumBits ); + printf("cAccumRedBits:%u " ,pfd.cAccumRedBits ); + printf("cAccumGreenBits:%u " ,pfd.cAccumGreenBits ); + printf("cAccumBlueBits:%u " ,pfd.cAccumBlueBits ); + printf("cAccumAlphaBits:%u " ,pfd.cAccumAlphaBits ); + printf("cDepthBits:%u " ,pfd.cDepthBits ); + printf("cStencilBits:%u " ,pfd.cStencilBits ); + printf("cAuxBuffers:%u " ,pfd.cAuxBuffers ); + printf("iLayerType:%u " ,pfd.iLayerType ); + printf("bReserved:%u " ,pfd.bReserved ); + printf("dwLayerMask:%u " ,pfd.dwLayerMask ); + printf("dwVisibleMask:%u " ,pfd.dwVisibleMask ); + printf("dwDamageMask:%u " ,pfd.dwDamageMask ); +} + +/** + \brief Print a Pointer to a U_EMRTEXT record + \param emt Pointer to a U_EMRTEXT record + \param record Pointer to the start of the record which contains this U_ERMTEXT + \param blimit Pointer to the first byte after after this record + \param type 0 for 8 bit character, anything else for 16 +*/ +void emrtext_print( + const char *emt, + const char *record, + const char *blimit, + int type + ){ + unsigned int i,off; + char *string; + PU_EMRTEXT pemt = (PU_EMRTEXT) emt; + // constant part + printf("ptlReference:"); pointl_print(pemt->ptlReference); + printf("nChars:%u " ,pemt->nChars ); + printf("offString:%u " ,pemt->offString ); + if(pemt->offString){ + if(!type){ + IF_MEM_UNSAFE_PRINT_AND_RETURN(record, pemt->offString + pemt->nChars*sizeof(char), blimit); + printf("string8:<%s> ",record + pemt->offString); + } + else { + IF_MEM_UNSAFE_PRINT_AND_RETURN(record, pemt->offString + pemt->nChars*2*sizeof(char), blimit); + string = U_Utf16leToUtf8((uint16_t *)(record + pemt->offString), pemt->nChars, NULL); + printf("string16:<%s> ",string); + free(string); + } + } + printf("fOptions:0x%8.8X " ,pemt->fOptions ); + off = sizeof(U_EMRTEXT); + if(!(pemt->fOptions & U_ETO_NO_RECT)){ + printf("rcl"); rectl_print( *((U_RECTL *)(emt+off)) ); + off += sizeof(U_RECTL); + } + printf("offDx:%u " , *((U_OFFDX *)(emt+off)) ); off = *(U_OFFDX *)(emt+off); + printf("Dx:"); + for(i=0; i<pemt->nChars; i++, off+=sizeof(uint32_t)){ + printf("%d:", *((uint32_t *)(record+off)) ); + } +} + + + + +// hide these from Doxygen +//! @cond +/* ********************************************************************************************** +These functions contain shared code used by various U_EMR*_print functions. These should NEVER be called +by end user code and to further that end prototypes are NOT provided and they are hidden from Doxygen. + + + These are (mostly) ordered by U_EMR_* index number. + + The exceptions: + void core3_print(const char *name, const char *label, const char *contents) + void core7_print(const char *name, const char *field1, const char *field2, const char *contents) + void core8_print(const char *name, const char *contents, int type) + + +*********************************************************************************************** */ + + +// Functions with the same form starting with U_EMRPOLYBEZIER_print +void core1_print(const char *name, const char *contents){ + unsigned int i; + UNUSED(name); + PU_EMRPOLYLINETO pEmr = (PU_EMRPOLYLINETO) (contents); + if(pEmr->emr.nSize < sizeof(U_EMRPOLYBEZIER)){ + printf(" record corruption HERE\n"); + return; + } + const char *blimit = contents + pEmr->emr.nSize; + printf(" rclBounds: "); rectl_print(pEmr->rclBounds); printf("\n"); + printf(" cptl: %d\n",pEmr->cptl ); + printf(" Points: "); + IF_MEM_UNSAFE_PRINT_AND_RETURN(pEmr->aptl, pEmr->cptl*sizeof(U_POINTL), blimit); + for(i=0;i<pEmr->cptl; i++){ + printf("[%d]:",i); pointl_print(pEmr->aptl[i]); + } + printf("\n"); +} + +// Functions with the same form starting with U_EMRPOLYPOLYLINE_print +void core2_print(const char *name, const char *contents){ + unsigned int i; + UNUSED(name); + PU_EMRPOLYPOLYGON pEmr = (PU_EMRPOLYPOLYGON) (contents); + if(pEmr->emr.nSize < sizeof(U_EMRPOLYPOLYGON)){ + printf(" record corruption HERE\n"); + return; + } + const char *blimit = contents + pEmr->emr.nSize; + printf(" rclBounds: "); rectl_print(pEmr->rclBounds); printf("\n"); + printf(" nPolys: %d\n",pEmr->nPolys ); + printf(" cptl: %d\n",pEmr->cptl ); + printf(" Counts: "); + IF_MEM_UNSAFE_PRINT_AND_RETURN(pEmr->aPolyCounts, pEmr->nPolys*sizeof(U_POLYCOUNTS), blimit); + for(i=0;i<pEmr->nPolys; i++){ + printf(" [%d]:%d ",i,pEmr->aPolyCounts[i] ); + } + printf("\n"); + PU_POINTL paptl = (PU_POINTL)((char *)pEmr->aPolyCounts + sizeof(uint32_t)* pEmr->nPolys); + printf(" Points: "); + IF_MEM_UNSAFE_PRINT_AND_RETURN(paptl, pEmr->cptl*sizeof(U_POINTL), blimit); + for(i=0;i<pEmr->cptl; i++){ + printf(" [%d]:",i); pointl_print(paptl[i]); + } + printf("\n"); +} + + +// Functions with the same form starting with U_EMRSETMAPMODE_print +void core3_print(const char *name, const char *label, const char *contents){ + UNUSED(name); + /* access violation is impossible for these because there are no counts or offsets */ + PU_EMRSETMAPMODE pEmr = (PU_EMRSETMAPMODE)(contents); + if(pEmr->emr.nSize < sizeof(U_EMRSETMAPMODE)){ + printf(" record corruption HERE\n"); + return; + } + if(!strcmp(label,"crColor:")){ + printf(" %-15s ",label); colorref_print(*(U_COLORREF *)&(pEmr->iMode)); printf("\n"); + } + else if(!strcmp(label,"iMode:")){ + printf(" %-15s 0x%8.8X\n",label,pEmr->iMode ); + } + else { + printf(" %-15s %d\n",label,pEmr->iMode ); + } +} + +// Functions taking a single U_RECT or U_RECTL, starting with U_EMRELLIPSE_print, also U_EMRFILLPATH_print, +void core4_print(const char *name, const char *contents){ + UNUSED(name); + PU_EMRELLIPSE pEmr = (PU_EMRELLIPSE)( contents); + if(pEmr->emr.nSize < sizeof(U_EMRELLIPSE)){ + printf(" record corruption HERE\n"); + return; + } + printf(" rclBox: "); rectl_print(pEmr->rclBox); printf("\n"); +} + +// Functions with the same form starting with U_EMRPOLYBEZIER16_print +void core6_print(const char *name, const char *contents){ + UNUSED(name); + unsigned int i; + PU_EMRPOLYBEZIER16 pEmr = (PU_EMRPOLYBEZIER16) (contents); + if(pEmr->emr.nSize < sizeof(U_EMRPOLYBEZIER16)){ + printf(" record corruption HERE\n"); + return; + } + const char *blimit = contents + pEmr->emr.nSize; + printf(" rclBounds: "); rectl_print(pEmr->rclBounds); printf("\n"); + printf(" cpts: %d\n",pEmr->cpts ); + printf(" Points: "); + PU_POINT16 papts = (PU_POINT16)(&(pEmr->apts)); + IF_MEM_UNSAFE_PRINT_AND_RETURN(papts, pEmr->cpts*sizeof(U_POINT16), blimit); + for(i=0; i<pEmr->cpts; i++){ + printf(" [%d]:",i); point16_print(papts[i]); + } + printf("\n"); +} + + +// Records with the same form starting with U_EMRSETWINDOWEXTEX_print +// CAREFUL, in the _set equivalents all functions with two uint32_t values are mapped here, and member names differ, consequently +// print routines must supply the names of the two arguments. These cannot be null. If the second one is +// empty the values are printed as a pair {x,y}, otherwise each is printed with its own label on a separate line. +void core7_print(const char *name, const char *field1, const char *field2, const char *contents){ + UNUSED(name); + PU_EMRGENERICPAIR pEmr = (PU_EMRGENERICPAIR) (contents); + if(pEmr->emr.nSize < sizeof(U_EMRGENERICPAIR)){ + printf(" record corruption HERE\n"); + return; + } + if(*field2){ + printf(" %-15s %d\n",field1,pEmr->pair.x); + printf(" %-15s %d\n",field2,pEmr->pair.y); + } + else { + printf(" %-15s {%d,%d}\n",field1,pEmr->pair.x,pEmr->pair.y); + } +} + +// For U_EMREXTTEXTOUTA and U_EMREXTTEXTOUTW, type=0 for the first one +void core8_print(const char *name, const char *contents, int type){ + UNUSED(name); + PU_EMREXTTEXTOUTA pEmr = (PU_EMREXTTEXTOUTA) (contents); + const char *blimit = contents + pEmr->emr.nSize; + printf(" iGraphicsMode: %u\n",pEmr->iGraphicsMode ); + printf(" rclBounds: "); rectl_print(pEmr->rclBounds); printf("\n"); + printf(" exScale: %f\n",pEmr->exScale ); + printf(" eyScale: %f\n",pEmr->eyScale ); + printf(" emrtext: "); + emrtext_print(contents + sizeof(U_EMREXTTEXTOUTA) - sizeof(U_EMRTEXT),contents,blimit,type); + printf("\n"); +} + +// Functions that take a rect and a pair of points, starting with U_EMRARC_print +void core9_print(const char *name, const char *contents){ + UNUSED(name); + PU_EMRARC pEmr = (PU_EMRARC) (contents); + if(pEmr->emr.nSize < sizeof(U_EMRARC)){ + printf(" record corruption HERE\n"); + return; + } + printf(" rclBox: "); rectl_print(pEmr->rclBox); printf("\n"); + printf(" ptlStart: "); pointl_print(pEmr->ptlStart); printf("\n"); + printf(" ptlEnd: "); pointl_print(pEmr->ptlEnd); printf("\n"); +} + +// Functions with the same form starting with U_EMRPOLYPOLYLINE16_print +void core10_print(const char *name, const char *contents){ + UNUSED(name); + unsigned int i; + PU_EMRPOLYPOLYLINE16 pEmr = (PU_EMRPOLYPOLYLINE16) (contents); + if(pEmr->emr.nSize < sizeof(U_EMRPOLYPOLYLINE16)){ + printf(" record corruption HERE\n"); + return; + } + const char *blimit = contents + pEmr->emr.nSize; + printf(" rclBounds: "); rectl_print(pEmr->rclBounds); printf("\n"); + printf(" nPolys: %d\n",pEmr->nPolys ); + printf(" cpts: %d\n",pEmr->cpts ); + printf(" Counts: "); + IF_MEM_UNSAFE_PRINT_AND_RETURN(&(pEmr->aPolyCounts), pEmr->nPolys*sizeof(U_POLYCOUNTS), blimit); + for(i=0;i<pEmr->nPolys; i++){ + printf(" [%d]:%d ",i,pEmr->aPolyCounts[i] ); + } + printf("\n"); + printf(" Points: "); + PU_POINT16 papts = (PU_POINT16)((char *)pEmr->aPolyCounts + pEmr->nPolys*sizeof(U_POLYCOUNTS) ); + IF_MEM_UNSAFE_PRINT_AND_RETURN(papts, pEmr->cpts*sizeof(U_POINT16), blimit); + for(i=0; i<pEmr->cpts; i++){ + printf(" [%d]:",i); point16_print(papts[i]); + } + printf("\n"); + +} + +// Functions with the same form starting with U_EMRINVERTRGN_print and U_EMRPAINTRGN_print, +void core11_print(const char *name, const char *contents){ + UNUSED(name); + PU_EMRINVERTRGN pEmr = (PU_EMRINVERTRGN) (contents); + if(pEmr->emr.nSize < sizeof(U_EMRINVERTRGN)){ + printf(" record corruption HERE\n"); + return; + } + const char *blimit = contents + pEmr->emr.nSize; + printf(" rclBounds: "); rectl_print(pEmr->rclBounds); printf("\n"); + printf(" cbRgnData: %d\n",pEmr->cbRgnData); + printf(" RegionData:"); + const char *minptr = MAKE_MIN_PTR(((const char *) &pEmr->RgnData + pEmr->cbRgnData),blimit); + rgndata_print(pEmr->RgnData, minptr); + printf("\n"); +} + + +// common code for U_EMRCREATEMONOBRUSH_print and U_EMRCREATEDIBPATTERNBRUSHPT_print, +void core12_print(const char *name, const char *contents){ + UNUSED(name); + PU_EMRCREATEMONOBRUSH pEmr = (PU_EMRCREATEMONOBRUSH) (contents); + if(pEmr->emr.nSize < sizeof(U_EMRCREATEMONOBRUSH)){ + printf(" record corruption HERE\n"); + return; + } + const char *blimit = contents + pEmr->emr.nSize; + printf(" ihBrush: %u\n",pEmr->ihBrush ); + printf(" iUsage : %u\n",pEmr->iUsage ); + printf(" offBmi : %u\n",pEmr->offBmi ); + printf(" cbBmi : %u\n",pEmr->cbBmi ); + if(pEmr->cbBmi){ + printf(" bitmap:"); + bitmapinfo_print(contents + pEmr->offBmi, blimit); + printf("\n"); + } + printf(" offBits: %u\n",pEmr->offBits ); + printf(" cbBits : %u\n",pEmr->cbBits ); +} + +// common code for U_EMRALPHABLEND_print and U_EMRTRANSPARENTBLT_print, +void core13_print(const char *name, const char *contents){ + UNUSED(name); + PU_EMRALPHABLEND pEmr = (PU_EMRALPHABLEND) (contents); + if(pEmr->emr.nSize < sizeof(U_EMRALPHABLEND)){ + printf(" record corruption HERE\n"); + return; + } + const char *blimit = contents + pEmr->emr.nSize; + printf(" rclBounds: "); rectl_print( pEmr->rclBounds); printf("\n"); + printf(" Dest: "); pointl_print(pEmr->Dest); printf("\n"); + printf(" cDest: "); pointl_print(pEmr->cDest); printf("\n"); + printf(" Blend: "); blend_print(pEmr->Blend); printf("\n"); + printf(" Src: "); pointl_print(pEmr->Src); printf("\n"); + printf(" xformSrc: "); xform_print( pEmr->xformSrc); printf("\n"); + printf(" crBkColorSrc: "); colorref_print( pEmr->crBkColorSrc); printf("\n"); + printf(" iUsageSrc: %u\n",pEmr->iUsageSrc ); + printf(" offBmiSrc: %u\n",pEmr->offBmiSrc ); + printf(" cbBmiSrc: %u\n",pEmr->cbBmiSrc ); + if(pEmr->cbBmiSrc){ + printf(" bitmap:"); + bitmapinfo_print(contents + pEmr->offBmiSrc, blimit); + printf("\n"); + } + printf(" offBitsSrc: %u\n",pEmr->offBitsSrc ); + printf(" cbBitsSrc: %u\n",pEmr->cbBitsSrc ); +} +//! @endcond + +/* ********************************************************************************************** +These are the core EMR functions, each creates a particular type of record. +All return these records via a char* pointer, which is NULL if the call failed. +They are listed in order by the corresponding U_EMR_* index number. +*********************************************************************************************** */ + +/** + \brief Print a pointer to a U_EMR_whatever record which has not been implemented. + \param name name of this type of record + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRNOTIMPLEMENTED_print(const char *name, const char *contents){ + UNUSED(name); + UNUSED(contents); + printf(" Not Implemented!\n"); +} + +// U_EMRHEADER 1 +/** + \brief Print a pointer to a U_EMR_HEADER record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRHEADER_print(const char *contents){ + char *string; + int p1len; + + PU_EMRHEADER pEmr = (PU_EMRHEADER)(contents); + if(pEmr->emr.nSize < sizeof(U_EMRHEADER)){ + printf(" record corruption HERE\n"); + return; + } + const char *blimit = contents + pEmr->emr.nSize; + printf(" rclBounds: "); rectl_print( pEmr->rclBounds); printf("\n"); + printf(" rclFrame: "); rectl_print( pEmr->rclFrame); printf("\n"); + printf(" dSignature: 0x%8.8X\n", pEmr->dSignature ); + printf(" nVersion: 0x%8.8X\n", pEmr->nVersion ); + printf(" nBytes: %d\n", pEmr->nBytes ); + printf(" nRecords: %d\n", pEmr->nRecords ); + printf(" nHandles: %d\n", pEmr->nHandles ); + printf(" sReserved: %d\n", pEmr->sReserved ); + printf(" nDescription: %d\n", pEmr->nDescription ); + printf(" offDescription: %d\n", pEmr->offDescription); + if(pEmr->offDescription){ + IF_MEM_UNSAFE_PRINT_AND_RETURN(contents, pEmr->offDescription + pEmr->nDescription*2*sizeof(char), blimit); + string = U_Utf16leToUtf8((uint16_t *)((char *) pEmr + pEmr->offDescription), pEmr->nDescription, NULL); + printf(" Desc. A: %s\n",string); + free(string); + p1len = 2 + 2*wchar16len((uint16_t *)((char *) pEmr + pEmr->offDescription)); + string = U_Utf16leToUtf8((uint16_t *)((char *) pEmr + pEmr->offDescription + p1len), pEmr->nDescription, NULL); + printf(" Desc. B: %s\n",string); + free(string); + } + printf(" nPalEntries: %d\n", pEmr->nPalEntries ); + printf(" szlDevice: {%d,%d} \n", pEmr->szlDevice.cx,pEmr->szlDevice.cy); + printf(" szlMillimeters: {%d,%d} \n", pEmr->szlMillimeters.cx,pEmr->szlMillimeters.cy); + if((pEmr->nDescription && (pEmr->offDescription >= 100)) || + (!pEmr->offDescription && pEmr->emr.nSize >= 100) + ){ + printf(" cbPixelFormat: %d\n", pEmr->cbPixelFormat ); + printf(" offPixelFormat: %d\n", pEmr->offPixelFormat); + if(pEmr->cbPixelFormat){ + printf(" PFD:"); + IF_MEM_UNSAFE_PRINT_AND_RETURN(contents, pEmr->offPixelFormat + sizeof(U_PIXELFORMATDESCRIPTOR), blimit); + pixelformatdescriptor_print( *(PU_PIXELFORMATDESCRIPTOR) (contents + pEmr->offPixelFormat)); + printf("\n"); + } + printf(" bOpenGL: %d\n",pEmr->bOpenGL ); + if((pEmr->nDescription && (pEmr->offDescription >= 108)) || + (pEmr->cbPixelFormat && (pEmr->offPixelFormat >=108)) || + (!pEmr->offDescription && !pEmr->cbPixelFormat && pEmr->emr.nSize >= 108) + ){ + printf(" szlMicrometers: {%d,%d} \n", pEmr->szlMicrometers.cx,pEmr->szlMicrometers.cy); + } + } +} + +// U_EMRPOLYBEZIER 2 +/** + \brief Print a pointer to a U_EMR_POLYBEZIER record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRPOLYBEZIER_print(const char *contents){ + core1_print("U_EMRPOLYBEZIER", contents); +} + +// U_EMRPOLYGON 3 +/** + \brief Print a pointer to a U_EMR_POLYGON record. + \param contents pointer to a buffer holding all EMR records + */ +void U_EMRPOLYGON_print(const char *contents){ + core1_print("U_EMRPOLYGON", contents); +} + + +// U_EMRPOLYLINE 4 +/** + \brief Print a pointer to a U_EMR_POLYLINE record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRPOLYLINE_print(const char *contents){ + core1_print("U_EMRPOLYLINE", contents); +} + +// U_EMRPOLYBEZIERTO 5 +/** + \brief Print a pointer to a U_EMR_POLYBEZIERTO record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRPOLYBEZIERTO_print(const char *contents){ + core1_print("U_EMRPOLYBEZIERTO", contents); +} + +// U_EMRPOLYLINETO 6 +/** + \brief Print a pointer to a U_EMR_POLYLINETO record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRPOLYLINETO_print(const char *contents){ + core1_print("U_EMRPOLYLINETO", contents); +} + +// U_EMRPOLYPOLYLINE 7 +/** + \brief Print a pointer to a U_EMR_POLYPOLYLINE record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRPOLYPOLYLINE_print(const char *contents){ + core2_print("U_EMRPOLYPOLYLINE", contents); +} + +// U_EMRPOLYPOLYGON 8 +/** + \brief Print a pointer to a U_EMR_POLYPOLYGON record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRPOLYPOLYGON_print(const char *contents){ + core2_print("U_EMRPOLYPOLYGON", contents); +} + +// U_EMRSETWINDOWEXTEX 9 +/** + \brief Print a pointer to a U_EMR_SETWINDOWEXTEX record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRSETWINDOWEXTEX_print(const char *contents){ + core7_print("U_EMRSETWINDOWEXTEX", "szlExtent:","",contents); +} + +// U_EMRSETWINDOWORGEX 10 +/** + \brief Print a pointer to a U_EMR_SETWINDOWORGEX record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRSETWINDOWORGEX_print(const char *contents){ + core7_print("U_EMRSETWINDOWORGEX", "ptlOrigin:","",contents); +} + +// U_EMRSETVIEWPORTEXTEX 11 +/** + \brief Print a pointer to a U_EMR_SETVIEWPORTEXTEX record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRSETVIEWPORTEXTEX_print(const char *contents){ + core7_print("U_EMRSETVIEWPORTEXTEX", "szlExtent:","",contents); +} + +// U_EMRSETVIEWPORTORGEX 12 +/** + \brief Print a pointer to a U_EMR_SETVIEWPORTORGEX record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRSETVIEWPORTORGEX_print(const char *contents){ + core7_print("U_EMRSETVIEWPORTORGEX", "ptlOrigin:","",contents); +} + +// U_EMRSETBRUSHORGEX 13 +/** + \brief Print a pointer to a U_EMR_SETBRUSHORGEX record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRSETBRUSHORGEX_print(const char *contents){ + core7_print("U_EMRSETBRUSHORGEX", "ptlOrigin:","",contents); +} + +// U_EMREOF 14 +/** + \brief Print a pointer to a U_EMR_EOF record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMREOF_print(const char *contents){ + PU_EMREOF pEmr = (PU_EMREOF)(contents); + if(pEmr->emr.nSize < sizeof(U_EMREOF)){ + printf(" record corruption HERE\n"); + return; + } + printf(" cbPalEntries: %u\n", pEmr->cbPalEntries ); + printf(" offPalEntries: %u\n", pEmr->offPalEntries); + if(pEmr->cbPalEntries){ + printf(" PE:"); + logpalette_print( (PU_LOGPALETTE)(contents + pEmr->offPalEntries)); + printf("\n"); + } +} + + +// U_EMRSETPIXELV 15 +/** + \brief Print a pointer to a U_EMR_SETPIXELV record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRSETPIXELV_print(const char *contents){ + PU_EMRSETPIXELV pEmr = (PU_EMRSETPIXELV)(contents); + if(pEmr->emr.nSize < sizeof(U_EMRSETPIXELV)){ + printf(" record corruption HERE\n"); + return; + } + printf(" ptlPixel: "); pointl_print( pEmr->ptlPixel); printf("\n"); + printf(" crColor: "); colorref_print(pEmr->crColor); printf("\n"); +} + + +// U_EMRSETMAPPERFLAGS 16 +/** + \brief Print a pointer to a U_EMR_SETMAPPERFLAGS record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRSETMAPPERFLAGS_print(const char *contents){ + PU_EMRSETMAPPERFLAGS pEmr = (PU_EMRSETMAPPERFLAGS)(contents); + if(pEmr->emr.nSize < sizeof(U_EMRSETMAPPERFLAGS)){ + printf(" record corruption HERE\n"); + return; + } + printf(" dwFlags: 0x%8.8X\n",pEmr->dwFlags); +} + + +// U_EMRSETMAPMODE 17 +/** + \brief Print a pointer to a U_EMR_SETMAPMODE record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRSETMAPMODE_print(const char *contents){ + core3_print("U_EMRSETMAPMODE", "iMode:", contents); +} + +// U_EMRSETBKMODE 18 +/** + \brief Print a pointer to a U_EMR_SETBKMODE record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRSETBKMODE_print(const char *contents){ + core3_print("U_EMRSETBKMODE", "iMode:", contents); +} + +// U_EMRSETPOLYFILLMODE 19 +/** + \brief Print a pointer to a U_EMR_SETPOLYFILLMODE record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRSETPOLYFILLMODE_print(const char *contents){ + core3_print("U_EMRSETPOLYFILLMODE", "iMode:", contents); +} + +// U_EMRSETROP2 20 +/** + \brief Print a pointer to a U_EMR_SETROP2 record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRSETROP2_print(const char *contents){ + core3_print("U_EMRSETROP2", "dwRop:", contents); +} + +// U_EMRSETSTRETCHBLTMODE 21 +/** + \brief Print a pointer to a U_EMR_SETSTRETCHBLTMODE record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRSETSTRETCHBLTMODE_print(const char *contents){ + core3_print("U_EMRSETSTRETCHBLTMODE", "iMode:", contents); +} + +// U_EMRSETTEXTALIGN 22 +/** + \brief Print a pointer to a U_EMR_SETTEXTALIGN record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRSETTEXTALIGN_print(const char *contents){ + core3_print("U_EMRSETTEXTALIGN", "iMode:", contents); +} + +// U_EMRSETCOLORADJUSTMENT 23 +/** + \brief Print a pointer to a U_EMR_SETCOLORADJUSTMENT record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRSETCOLORADJUSTMENT_print(const char *contents){ + PU_EMRSETCOLORADJUSTMENT pEmr = (PU_EMRSETCOLORADJUSTMENT)(contents); + if(pEmr->emr.nSize < sizeof(U_EMRSETCOLORADJUSTMENT)){ + printf(" record corruption HERE\n"); + return; + } + printf(" ColorAdjustment:"); + coloradjustment_print(pEmr->ColorAdjustment); + printf("\n"); +} + +// U_EMRSETTEXTCOLOR 24 +/** + \brief Print a pointer to a U_EMR_SETTEXTCOLOR record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRSETTEXTCOLOR_print(const char *contents){ + core3_print("U_EMRSETTEXTCOLOR", "crColor:", contents); +} + +// U_EMRSETBKCOLOR 25 +/** + \brief Print a pointer to a U_EMR_SETBKCOLOR record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRSETBKCOLOR_print(const char *contents){ + core3_print("U_EMRSETBKCOLOR", "crColor:", contents); +} + +// U_EMROFFSETCLIPRGN 26 +/** + \brief Print a pointer to a U_EMR_OFFSETCLIPRGN record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMROFFSETCLIPRGN_print(const char *contents){ + core7_print("U_EMROFFSETCLIPRGN", "ptl:","",contents); +} + +// U_EMRMOVETOEX 27 +/** + \brief Print a pointer to a U_EMR_MOVETOEX record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRMOVETOEX_print(const char *contents){ + core7_print("U_EMRMOVETOEX", "ptl:","",contents); +} + +// U_EMRSETMETARGN 28 +/** + \brief Print a pointer to a U_EMR_SETMETARGN record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRSETMETARGN_print(const char *contents){ + UNUSED(contents); +} + +// U_EMREXCLUDECLIPRECT 29 +/** + \brief Print a pointer to a U_EMR_EXCLUDECLIPRECT record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMREXCLUDECLIPRECT_print(const char *contents){ + core4_print("U_EMREXCLUDECLIPRECT", contents); +} + +// U_EMRINTERSECTCLIPRECT 30 +/** + \brief Print a pointer to a U_EMR_INTERSECTCLIPRECT record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRINTERSECTCLIPRECT_print(const char *contents){ + core4_print("U_EMRINTERSECTCLIPRECT", contents); +} + +// U_EMRSCALEVIEWPORTEXTEX 31 +/** + \brief Print a pointer to a U_EMR_SCALEVIEWPORTEXTEX record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRSCALEVIEWPORTEXTEX_print(const char *contents){ + core4_print("U_EMRSCALEVIEWPORTEXTEX", contents); +} + + +// U_EMRSCALEWINDOWEXTEX 32 +/** + \brief Print a pointer to a U_EMR_SCALEWINDOWEXTEX record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRSCALEWINDOWEXTEX_print(const char *contents){ + core4_print("U_EMRSCALEWINDOWEXTEX", contents); +} + +// U_EMRSAVEDC 33 +/** + \brief Print a pointer to a U_EMR_SAVEDC record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRSAVEDC_print(const char *contents){ + UNUSED(contents); +} + +// U_EMRRESTOREDC 34 +/** + \brief Print a pointer to a U_EMR_RESTOREDC record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRRESTOREDC_print(const char *contents){ + core3_print("U_EMRRESTOREDC", "iRelative:", contents); +} + +// U_EMRSETWORLDTRANSFORM 35 +/** + \brief Print a pointer to a U_EMR_SETWORLDTRANSFORM record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRSETWORLDTRANSFORM_print(const char *contents){ + PU_EMRSETWORLDTRANSFORM pEmr = (PU_EMRSETWORLDTRANSFORM)(contents); + if(pEmr->emr.nSize < sizeof(U_EMRSETWORLDTRANSFORM)){ + printf(" record corruption HERE\n"); + return; + } + printf(" xform:"); + xform_print(pEmr->xform); + printf("\n"); +} + +// U_EMRMODIFYWORLDTRANSFORM 36 +/** + \brief Print a pointer to a U_EMR_MODIFYWORLDTRANSFORM record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRMODIFYWORLDTRANSFORM_print(const char *contents){ + PU_EMRMODIFYWORLDTRANSFORM pEmr = (PU_EMRMODIFYWORLDTRANSFORM)(contents); + if(pEmr->emr.nSize < sizeof(U_EMRMODIFYWORLDTRANSFORM)){ + printf(" record corruption HERE\n"); + return; + } + printf(" xform:"); + xform_print(pEmr->xform); + printf("\n"); + printf(" iMode: %u\n", pEmr->iMode ); +} + +// U_EMRSELECTOBJECT 37 +/** + \brief Print a pointer to a U_EMR_SELECTOBJECT record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRSELECTOBJECT_print(const char *contents){ + PU_EMRSELECTOBJECT pEmr = (PU_EMRSELECTOBJECT)(contents); + if(pEmr->emr.nSize < sizeof(U_EMRSELECTOBJECT)){ + printf(" record corruption HERE\n"); + return; + } + if(pEmr->ihObject & U_STOCK_OBJECT){ + printf(" StockObject: 0x%8.8X\n", pEmr->ihObject ); + } + else { + printf(" ihObject: %u\n", pEmr->ihObject ); + } +} + +// U_EMRCREATEPEN 38 +/** + \brief Print a pointer to a U_EMR_CREATEPEN record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRCREATEPEN_print(const char *contents){ + PU_EMRCREATEPEN pEmr = (PU_EMRCREATEPEN)(contents); + if(pEmr->emr.nSize < sizeof(U_EMRCREATEPEN)){ + printf(" record corruption HERE\n"); + return; + } + printf(" ihPen: %u\n", pEmr->ihPen ); + printf(" lopn: "); logpen_print(pEmr->lopn); printf("\n"); +} + +// U_EMRCREATEBRUSHINDIRECT 39 +/** + \brief Print a pointer to a U_EMR_CREATEBRUSHINDIRECT record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRCREATEBRUSHINDIRECT_print(const char *contents){ + PU_EMRCREATEBRUSHINDIRECT pEmr = (PU_EMRCREATEBRUSHINDIRECT)(contents); + if(pEmr->emr.nSize < sizeof(U_EMRCREATEBRUSHINDIRECT)){ + printf(" record corruption HERE\n"); + return; + } + printf(" ihBrush: %u\n", pEmr->ihBrush ); + printf(" lb: "); logbrush_print(pEmr->lb); printf("\n"); +} + +// U_EMRDELETEOBJECT 40 +/** + \brief Print a pointer to a U_EMR_DELETEOBJECT record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRDELETEOBJECT_print(const char *contents){ + PU_EMRDELETEOBJECT pEmr = (PU_EMRDELETEOBJECT)(contents); + if(pEmr->emr.nSize < sizeof(U_EMRDELETEOBJECT)){ + printf(" record corruption HERE\n"); + return; + } + printf(" ihObject: %u\n", pEmr->ihObject ); +} + +// U_EMRANGLEARC 41 +/** + \brief Print a pointer to a U_EMR_ANGLEARC record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRANGLEARC_print(const char *contents){ + PU_EMRANGLEARC pEmr = (PU_EMRANGLEARC)(contents); + if(pEmr->emr.nSize < sizeof(U_EMRANGLEARC)){ + printf(" record corruption HERE\n"); + return; + } + printf(" ptlCenter: "), pointl_print(pEmr->ptlCenter ); printf("\n"); + printf(" nRadius: %u\n", pEmr->nRadius ); + printf(" eStartAngle: %f\n", pEmr->eStartAngle ); + printf(" eSweepAngle: %f\n", pEmr->eSweepAngle ); +} + +// U_EMRELLIPSE 42 +/** + \brief Print a pointer to a U_EMR_ELLIPSE record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRELLIPSE_print(const char *contents){ + core4_print("U_EMRELLIPSE", contents); +} + +// U_EMRRECTANGLE 43 +/** + \brief Print a pointer to a U_EMR_RECTANGLE record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRRECTANGLE_print(const char *contents){ + core4_print("U_EMRRECTANGLE", contents); +} + +// U_EMRROUNDRECT 44 +/** + \brief Print a pointer to a U_EMR_ROUNDRECT record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRROUNDRECT_print(const char *contents){ + PU_EMRROUNDRECT pEmr = (PU_EMRROUNDRECT)(contents); + if(pEmr->emr.nSize < sizeof(U_EMRROUNDRECT)){ + printf(" record corruption HERE\n"); + return; + } + printf(" rclBox: "), rectl_print(pEmr->rclBox ); printf("\n"); + printf(" szlCorner: "), sizel_print(pEmr->szlCorner ); printf("\n"); +} + +// U_EMRARC 45 +/** + \brief Print a pointer to a U_EMR_ARC record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRARC_print(const char *contents){ + core9_print("U_EMRARC", contents); +} + +// U_EMRCHORD 46 +/** + \brief Print a pointer to a U_EMR_CHORD record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRCHORD_print(const char *contents){ + core9_print("U_EMRCHORD", contents); +} + +// U_EMRPIE 47 +/** + \brief Print a pointer to a U_EMR_PIE record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRPIE_print(const char *contents){ + core9_print("U_EMRPIE", contents); +} + +// U_EMRSELECTPALETTE 48 +/** + \brief Print a pointer to a U_EMR_SELECTPALETTE record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRSELECTPALETTE_print(const char *contents){ + core3_print("U_EMRSELECTPALETTE", "ihPal:", contents); +} + +// U_EMRCREATEPALETTE 49 +/** + \brief Print a pointer to a U_EMR_CREATEPALETTE record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRCREATEPALETTE_print(const char *contents){ + PU_EMRCREATEPALETTE pEmr = (PU_EMRCREATEPALETTE)(contents); + if(pEmr->emr.nSize < sizeof(U_EMRCREATEPALETTE)){ + printf(" record corruption HERE\n"); + return; + } + printf(" ihPal: %u\n",pEmr->ihPal); + printf(" lgpl: "), logpalette_print( (PU_LOGPALETTE)&(pEmr->lgpl) ); printf("\n"); +} + +// U_EMRSETPALETTEENTRIES 50 +/** + \brief Print a pointer to a U_EMR_SETPALETTEENTRIES record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRSETPALETTEENTRIES_print(const char *contents){ + unsigned int i; + PU_EMRSETPALETTEENTRIES pEmr = (PU_EMRSETPALETTEENTRIES)(contents); + if(pEmr->emr.nSize < sizeof(U_EMRSETPALETTEENTRIES)){ + printf(" record corruption HERE\n"); + return; + } + const char *blimit = contents + pEmr->emr.nSize; + printf(" ihPal: %u\n",pEmr->ihPal); + printf(" iStart: %u\n",pEmr->iStart); + printf(" cEntries: %u\n",pEmr->cEntries); + if(pEmr->cEntries){ + printf(" PLTEntries:"); + PU_LOGPLTNTRY aPalEntries = (PU_LOGPLTNTRY) &(pEmr->aPalEntries); + IF_MEM_UNSAFE_PRINT_AND_RETURN(aPalEntries, pEmr->cEntries*sizeof(U_LOGPLTNTRY), blimit); + for(i=0; i<pEmr->cEntries; i++){ + printf("%d:",i); logpltntry_print(aPalEntries[i]); + } + printf("\n"); + } +} + +// U_EMRRESIZEPALETTE 51 +/** + \brief Print a pointer to a U_EMR_RESIZEPALETTE record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRRESIZEPALETTE_print(const char *contents){ + core7_print("U_EMRRESIZEPALETTE", "ihPal:","cEntries",contents); +} + +// U_EMRREALIZEPALETTE 52 +/** + \brief Print a pointer to a U_EMR_REALIZEPALETTE record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRREALIZEPALETTE_print(const char *contents){ + UNUSED(contents); +} + +// U_EMREXTFLOODFILL 53 +/** + \brief Print a pointer to a U_EMR_EXTFLOODFILL record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMREXTFLOODFILL_print(const char *contents){ + PU_EMREXTFLOODFILL pEmr = (PU_EMREXTFLOODFILL)(contents); + if(pEmr->emr.nSize < sizeof(U_EMREXTFLOODFILL)){ + printf(" record corruption HERE\n"); + return; + } + printf(" ptlStart: "); pointl_print(pEmr->ptlStart); printf("\n"); + printf(" crColor: "); colorref_print(pEmr->crColor); printf("\n"); + printf(" iMode: %u\n",pEmr->iMode); +} + +// U_EMRLINETO 54 +/** + \brief Print a pointer to a U_EMR_LINETO record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRLINETO_print(const char *contents){ + core7_print("U_EMRLINETO", "ptl:","",contents); +} + +// U_EMRARCTO 55 +/** + \brief Print a pointer to a U_EMR_ARCTO record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRARCTO_print(const char *contents){ + core9_print("U_EMRARCTO", contents); +} + +// U_EMRPOLYDRAW 56 +/** + \brief Print a pointer to a U_EMR_POLYDRAW record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRPOLYDRAW_print(const char *contents){ + unsigned int i; + PU_EMRPOLYDRAW pEmr = (PU_EMRPOLYDRAW)(contents); + if(pEmr->emr.nSize < sizeof(U_EMRPOLYDRAW)){ + printf(" record corruption HERE\n"); + return; + } + const char *blimit = contents + pEmr->emr.nSize; + printf(" rclBounds: "); rectl_print( pEmr->rclBounds); printf("\n"); + printf(" cptl: %d\n",pEmr->cptl ); + printf(" Points: "); + IF_MEM_UNSAFE_PRINT_AND_RETURN(pEmr->aptl, pEmr->cptl*sizeof(U_POINTL), blimit); + for(i=0;i<pEmr->cptl; i++){ + printf(" [%d]:",i); + pointl_print(pEmr->aptl[i]); + } + printf("\n"); + printf(" Types: "); + const char *abTypes = (const char *) pEmr->aptl + pEmr->cptl*sizeof(U_POINTL); + IF_MEM_UNSAFE_PRINT_AND_RETURN(abTypes, pEmr->cptl, blimit); + for(i=0;i<pEmr->cptl; i++){ + printf(" [%d]:%u ",i,((uint8_t *)abTypes)[i]); + } + printf("\n"); +} + +// U_EMRSETARCDIRECTION 57 +/** + \brief Print a pointer to a U_EMR_SETARCDIRECTION record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRSETARCDIRECTION_print(const char *contents){ + core3_print("U_EMRSETARCDIRECTION","arcDirection:", contents); +} + +// U_EMRSETMITERLIMIT 58 +/** + \brief Print a pointer to a U_EMR_SETMITERLIMIT record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRSETMITERLIMIT_print(const char *contents){ + core3_print("U_EMRSETMITERLIMIT", "eMiterLimit:", contents); +} + + +// U_EMRBEGINPATH 59 +/** + \brief Print a pointer to a U_EMR_BEGINPATH record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRBEGINPATH_print(const char *contents){ + UNUSED(contents); +} + +// U_EMRENDPATH 60 +/** + \brief Print a pointer to a U_EMR_ENDPATH record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRENDPATH_print(const char *contents){ + UNUSED(contents); +} + +// U_EMRCLOSEFIGURE 61 +/** + \brief Print a pointer to a U_EMR_CLOSEFIGURE record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRCLOSEFIGURE_print(const char *contents){ + UNUSED(contents); +} + +// U_EMRFILLPATH 62 +/** + \brief Print a pointer to a U_EMR_FILLPATH record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRFILLPATH_print(const char *contents){ + core4_print("U_EMRFILLPATH", contents); +} + +// U_EMRSTROKEANDFILLPATH 63 +/** + \brief Print a pointer to a U_EMR_STROKEANDFILLPATH record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRSTROKEANDFILLPATH_print(const char *contents){ + core4_print("U_EMRSTROKEANDFILLPATH", contents); +} + +// U_EMRSTROKEPATH 64 +/** + \brief Print a pointer to a U_EMR_STROKEPATH record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRSTROKEPATH_print(const char *contents){ + core4_print("U_EMRSTROKEPATH", contents); +} + +// U_EMRFLATTENPATH 65 +/** + \brief Print a pointer to a U_EMR_FLATTENPATH record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRFLATTENPATH_print(const char *contents){ + UNUSED(contents); +} + +// U_EMRWIDENPATH 66 +/** + \brief Print a pointer to a U_EMR_WIDENPATH record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRWIDENPATH_print(const char *contents){ + UNUSED(contents); +} + +// U_EMRSELECTCLIPPATH 67 +/** + \brief Print a pointer to a U_EMR_SELECTCLIPPATH record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRSELECTCLIPPATH_print(const char *contents){ + core3_print("U_EMRSELECTCLIPPATH", "iMode:", contents); +} + +// U_EMRABORTPATH 68 +/** + \brief Print a pointer to a U_EMR_ABORTPATH record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRABORTPATH_print(const char *contents){ + UNUSED(contents); +} + +// U_EMRUNDEF69 69 +#define U_EMRUNDEF69_print(A) U_EMRNOTIMPLEMENTED_print("U_EMRUNDEF69",A) //!< Not implemented. + +// U_EMRCOMMENT 70 Comment (any binary data, interpretation is program specific) +/** + \brief Print a pointer to a U_EMR_COMMENT record. + \param contents pointer to a location in memory holding the comment record + \param off offset in bytes to the first byte in this record (needed for EMF+ record printing) + + EMF+ records, if any, are stored in EMF comment records. +*/ +void U_EMRCOMMENT_print(const char *contents, size_t off){ + char *string; + char *src; + uint32_t cIdent,cIdent2,cbData; + size_t loff; + int recsize; + static int recnum=0; + + PU_EMRCOMMENT pEmr = (PU_EMRCOMMENT)(contents); + if(pEmr->emr.nSize < sizeof(U_EMRCOMMENT)){ + printf(" record corruption HERE\n"); + return; + } + const char *blimit = contents + pEmr->emr.nSize; + + /* There are several different types of comments */ + + IF_MEM_UNSAFE_PRINT_AND_RETURN(contents, sizeof(U_EMRCOMMENT), blimit); + cbData = pEmr->cbData; + printf(" cbData: %d\n",cbData ); + IF_MEM_UNSAFE_PRINT_AND_RETURN(contents, sizeof(U_EMR) + sizeof(U_CBDATA) + cbData, blimit); + src = (char *)&(pEmr->Data); // default + if(cbData >= 4){ + /* Since the comment is just a big bag of bytes the emf endian code cannot safely touch + any of its payload. This is the only record type with that limitation. So the record + may appear at this stage with the wrong endianness. Try to determine + what the contents are even if more byte swapping is required. */ + cIdent = *(uint32_t *)(src); + if(U_BYTE_SWAP){ U_swap4(&(cIdent),1); } + if( cIdent == U_EMR_COMMENT_PUBLIC ){ + printf(" cIdent: Public\n"); + PU_EMRCOMMENT_PUBLIC pEmrp = (PU_EMRCOMMENT_PUBLIC) pEmr; + IF_MEM_UNSAFE_PRINT_AND_RETURN(contents, sizeof(U_EMRCOMMENT_PUBLIC), blimit); + cIdent2 = pEmrp->pcIdent; + if(U_BYTE_SWAP){ U_swap4(&(cIdent2),1); } + printf(" pcIdent: 0x%8.8x\n",cIdent2); + src = (char *)&(pEmrp->Data); + cbData -= 8; + } + else if(cIdent == U_EMR_COMMENT_SPOOL ){ + printf(" cIdent: Spool\n"); + PU_EMRCOMMENT_SPOOL pEmrs = (PU_EMRCOMMENT_SPOOL) pEmr; + IF_MEM_UNSAFE_PRINT_AND_RETURN(contents, sizeof(U_EMRCOMMENT_SPOOL), blimit); + cIdent2 = pEmrs->esrIdent; + if(U_BYTE_SWAP){ U_swap4(&(cIdent2),1); } + printf(" esrIdent: 0x%8.8x\n",cIdent2); + src = (char *)&(pEmrs->Data); + cbData -= 8; + } + else if(cIdent == U_EMR_COMMENT_EMFPLUSRECORD){ + printf(" cIdent: EMF+\n"); + PU_EMRCOMMENT_EMFPLUS pEmrpl = (PU_EMRCOMMENT_EMFPLUS) pEmr; + IF_MEM_UNSAFE_PRINT_AND_RETURN(contents, sizeof(U_EMRCOMMENT_EMFPLUS), blimit); + src = (char *)&(pEmrpl->Data); + loff = 16; /* Header size of the header part of an EMF+ comment record */ + while(loff < cbData + 12){ // EMF+ records may not fill the entire comment, cbData value includes cIdent, but not U_EMR or cbData + recsize = U_pmf_onerec_print(src, blimit, recnum, loff + off); + if(recsize==0){ break; } + else if(recsize<0){ + printf(" record corruption HERE\n"); + return; + } + loff += recsize; + src += recsize; + recnum++; + } + return; + } + else { + printf(" cIdent: not (Public or Spool or EMF+)\n"); + } + } + if(cbData){ // The data may not be printable, but try it just in case + string = malloc(cbData + 1); + (void)strncpy(string, src, cbData); + string[cbData] = '\0'; // it might not be terminated - it might not even be text! + printf(" Data: <%s>\n",string); + free(string); + } +} + +// U_EMRFILLRGN 71 +/** + \brief Print a pointer to a U_EMR_FILLRGN record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRFILLRGN_print(const char *contents){ + PU_EMRFILLRGN pEmr = (PU_EMRFILLRGN)(contents); + if(pEmr->emr.nSize < sizeof(U_EMRFILLRGN)){ + printf(" record corruption HERE\n"); + return; + } + const char *blimit = contents + pEmr->emr.nSize; + printf(" rclBounds: "); rectl_print(pEmr->rclBounds); printf("\n"); + printf(" cbRgnData: %u\n",pEmr->cbRgnData); + printf(" ihBrush: %u\n",pEmr->ihBrush); + const char *minptr = MAKE_MIN_PTR(((const char *) &pEmr->RgnData + pEmr->cbRgnData + sizeof(U_RGNDATAHEADER)),blimit); + printf(" RegionData: "); rgndata_print(pEmr->RgnData, minptr); printf("\n"); +} + +// U_EMRFRAMERGN 72 +/** + \brief Print a pointer to a U_EMR_FRAMERGN record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRFRAMERGN_print(const char *contents){ + PU_EMRFRAMERGN pEmr = (PU_EMRFRAMERGN)(contents); + if(pEmr->emr.nSize < sizeof(U_EMRFRAMERGN)){ + printf(" record corruption HERE\n"); + return; + } + const char *blimit = contents + pEmr->emr.nSize; + printf(" rclBounds: "); rectl_print(pEmr->rclBounds); printf("\n"); + printf(" cbRgnData: %u\n",pEmr->cbRgnData); + printf(" ihBrush: %u\n",pEmr->ihBrush); + printf(" szlStroke: "), sizel_print(pEmr->szlStroke ); printf("\n"); + const char *minptr = MAKE_MIN_PTR(((const char *) &pEmr->RgnData + pEmr->cbRgnData),blimit); + printf(" RegionData: "); rgndata_print(pEmr->RgnData, minptr); printf("\n"); +} + +// U_EMRINVERTRGN 73 +/** + \brief Print a pointer to a U_EMR_INVERTRGN record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRINVERTRGN_print(const char *contents){ + core11_print("U_EMRINVERTRGN", contents); +} + +// U_EMRPAINTRGN 74 +/** + \brief Print a pointer to a U_EMR_PAINTRGN record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRPAINTRGN_print(const char *contents){ + core11_print("U_EMRPAINTRGN", contents); +} + +// U_EMREXTSELECTCLIPRGN 75 +/** + \brief Print a pointer to a U_EMR_EXTSELECTCLIPRGN record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMREXTSELECTCLIPRGN_print(const char *contents){ + PU_EMREXTSELECTCLIPRGN pEmr = (PU_EMREXTSELECTCLIPRGN) (contents); + if(pEmr->emr.nSize < U_SIZE_EMREXTSELECTCLIPRGN){ + printf(" record corruption HERE\n"); + return; + } + const char *blimit = contents + pEmr->emr.nSize; + printf(" cbRgnData: %u\n",pEmr->cbRgnData); + printf(" iMode: %u\n",pEmr->iMode); + if(pEmr->iMode == U_RGN_COPY && !pEmr->cbRgnData){ + printf(" RegionData: none (Clip region becomes NULL)\n"); + } + else { + const char *minptr = MAKE_MIN_PTR(((const char *) &pEmr->RgnData + pEmr->cbRgnData),blimit); + printf(" RegionData: "); rgndata_print(pEmr->RgnData, minptr); printf("\n"); + } + +} + +// U_EMRBITBLT 76 +/** + \brief Print a pointer to a U_EMR_BITBLT record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRBITBLT_print(const char *contents){ + PU_EMRBITBLT pEmr = (PU_EMRBITBLT) (contents); + if(pEmr->emr.nSize < sizeof(U_EMRBITBLT)){ + printf(" record corruption HERE\n"); + return; + } + const char *blimit = contents + pEmr->emr.nSize; + printf(" rclBounds: "); rectl_print( pEmr->rclBounds); printf("\n"); + printf(" Dest: "); pointl_print(pEmr->Dest); printf("\n"); + printf(" cDest: "); pointl_print(pEmr->cDest); printf("\n"); + printf(" dwRop : 0x%8.8X\n", pEmr->dwRop ); + printf(" Src: "); pointl_print(pEmr->Src); printf("\n"); + printf(" xformSrc: "); xform_print( pEmr->xformSrc); printf("\n"); + printf(" crBkColorSrc: "); colorref_print( pEmr->crBkColorSrc); printf("\n"); + printf(" iUsageSrc: %u\n", pEmr->iUsageSrc ); + printf(" offBmiSrc: %u\n", pEmr->offBmiSrc ); + printf(" cbBmiSrc: %u\n", pEmr->cbBmiSrc ); + if(pEmr->cbBmiSrc){ + printf(" bitmap: "); + bitmapinfo_print(contents + pEmr->offBmiSrc, blimit); + printf("\n"); + } + printf(" offBitsSrc: %u\n", pEmr->offBitsSrc ); + printf(" cbBitsSrc: %u\n", pEmr->cbBitsSrc ); +} + +// U_EMRSTRETCHBLT 77 +/** + \brief Print a pointer to a U_EMR_STRETCHBLT record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRSTRETCHBLT_print(const char *contents){ + PU_EMRSTRETCHBLT pEmr = (PU_EMRSTRETCHBLT) (contents); + if(pEmr->emr.nSize < sizeof(U_EMRSTRETCHBLT)){ + printf(" record corruption HERE\n"); + return; + } + const char *blimit = contents + pEmr->emr.nSize; + printf(" rclBounds: "); rectl_print( pEmr->rclBounds); printf("\n"); + printf(" Dest: "); pointl_print(pEmr->Dest); printf("\n"); + printf(" cDest: "); pointl_print(pEmr->cDest); printf("\n"); + printf(" dwRop : 0x%8.8X\n", pEmr->dwRop ); + printf(" Src: "); pointl_print(pEmr->Src); printf("\n"); + printf(" xformSrc: "); xform_print( pEmr->xformSrc); printf("\n"); + printf(" crBkColorSrc: "); colorref_print( pEmr->crBkColorSrc); printf("\n"); + printf(" iUsageSrc: %u\n", pEmr->iUsageSrc ); + printf(" offBmiSrc: %u\n", pEmr->offBmiSrc ); + printf(" cbBmiSrc: %u\n", pEmr->cbBmiSrc ); + if(pEmr->cbBmiSrc){ + printf(" bitmap: "); + bitmapinfo_print(contents + pEmr->offBmiSrc, blimit); + printf("\n"); + } + printf(" offBitsSrc: %u\n", pEmr->offBitsSrc ); + printf(" cbBitsSrc: %u\n", pEmr->cbBitsSrc ); + printf(" cSrc: "); pointl_print(pEmr->cSrc); printf("\n"); +} + +// U_EMRMASKBLT 78 +/** + \brief Print a pointer to a U_EMR_MASKBLT record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRMASKBLT_print(const char *contents){ + PU_EMRMASKBLT pEmr = (PU_EMRMASKBLT) (contents); + if(pEmr->emr.nSize < sizeof(U_EMRMASKBLT)){ + printf(" record corruption HERE\n"); + return; + } + const char *blimit = contents + pEmr->emr.nSize; + printf(" rclBounds: "); rectl_print( pEmr->rclBounds); printf("\n"); + printf(" Dest: "); pointl_print(pEmr->Dest); printf("\n"); + printf(" cDest: "); pointl_print(pEmr->cDest); printf("\n"); + printf(" dwRop : 0x%8.8X\n", pEmr->dwRop ); + printf(" Src: "); pointl_print(pEmr->Src); printf("\n"); + printf(" xformSrc: "); xform_print( pEmr->xformSrc); printf("\n"); + printf(" crBkColorSrc: "); colorref_print( pEmr->crBkColorSrc); printf("\n"); + printf(" iUsageSrc: %u\n", pEmr->iUsageSrc ); + printf(" offBmiSrc: %u\n", pEmr->offBmiSrc ); + printf(" cbBmiSrc: %u\n", pEmr->cbBmiSrc ); + if(pEmr->cbBmiSrc){ + printf(" Src bitmap: "); + bitmapinfo_print(contents + pEmr->offBmiSrc, blimit); + printf("\n"); + } + printf(" offBitsSrc: %u\n", pEmr->offBitsSrc ); + printf(" cbBitsSrc: %u\n", pEmr->cbBitsSrc ); + printf(" Mask: "); pointl_print(pEmr->Mask); printf("\n"); + printf(" iUsageMask: %u\n", pEmr->iUsageMask ); + printf(" offBmiMask: %u\n", pEmr->offBmiMask ); + printf(" cbBmiMask: %u\n", pEmr->cbBmiMask ); + if(pEmr->cbBmiMask){ + printf(" Mask bitmap: "); + bitmapinfo_print(contents + pEmr->offBmiMask, blimit); + printf("\n"); + } + printf(" offBitsMask: %u\n", pEmr->offBitsMask ); + printf(" cbBitsMask: %u\n", pEmr->cbBitsMask ); +} + +// U_EMRPLGBLT 79 +/** + \brief Print a pointer to a U_EMR_PLGBLT record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRPLGBLT_print(const char *contents){ + PU_EMRPLGBLT pEmr = (PU_EMRPLGBLT) (contents); + if(pEmr->emr.nSize < sizeof(U_EMRPLGBLT)){ + printf(" record corruption HERE\n"); + return; + } + const char *blimit = contents + pEmr->emr.nSize; + printf(" rclBounds: "); rectl_print( pEmr->rclBounds); printf("\n"); + printf(" aptlDst(UL): "); pointl_print(pEmr->aptlDst[0]); printf("\n"); + printf(" aptlDst(UR): "); pointl_print(pEmr->aptlDst[1]); printf("\n"); + printf(" aptlDst(LL): "); pointl_print(pEmr->aptlDst[2]); printf("\n"); + printf(" Src: "); pointl_print(pEmr->Src); printf("\n"); + printf(" cSrc: "); pointl_print(pEmr->cSrc); printf("\n"); + printf(" xformSrc: "); xform_print( pEmr->xformSrc); printf("\n"); + printf(" crBkColorSrc: "); colorref_print( pEmr->crBkColorSrc); printf("\n"); + printf(" iUsageSrc: %u\n", pEmr->iUsageSrc ); + printf(" offBmiSrc: %u\n", pEmr->offBmiSrc ); + printf(" cbBmiSrc: %u\n", pEmr->cbBmiSrc ); + if(pEmr->cbBmiSrc){ + printf(" Src bitmap: "); + bitmapinfo_print(contents + pEmr->offBmiSrc, blimit); + printf("\n"); + } + printf(" offBitsSrc: %u\n", pEmr->offBitsSrc ); + printf(" cbBitsSrc: %u\n", pEmr->cbBitsSrc ); + printf(" Mask: "); pointl_print(pEmr->Mask); printf("\n"); + printf(" iUsageMsk: %u\n", pEmr->iUsageMask ); + printf(" offBmiMask: %u\n", pEmr->offBmiMask ); + printf(" cbBmiMask: %u\n", pEmr->cbBmiMask ); + if(pEmr->cbBmiMask){ + printf(" Mask bitmap: "); + bitmapinfo_print(contents + pEmr->offBmiMask, blimit); + printf("\n"); + } + printf(" offBitsMask: %u\n", pEmr->offBitsMask ); + printf(" cbBitsMask: %u\n", pEmr->cbBitsMask ); +} + +// U_EMRSETDIBITSTODEVICE 80 +/** + \brief Print a pointer to a U_EMRSETDIBITSTODEVICE record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRSETDIBITSTODEVICE_print(const char *contents){ + PU_EMRSETDIBITSTODEVICE pEmr = (PU_EMRSETDIBITSTODEVICE) (contents); + if(pEmr->emr.nSize < sizeof(U_EMRSETDIBITSTODEVICE)){ + printf(" record corruption HERE\n"); + return; + } + const char *blimit = contents + pEmr->emr.nSize; + printf(" rclBounds: "); rectl_print( pEmr->rclBounds); printf("\n"); + printf(" Dest: "); pointl_print(pEmr->Dest); printf("\n"); + printf(" Src: "); pointl_print(pEmr->Src); printf("\n"); + printf(" cSrc: "); pointl_print(pEmr->cSrc); printf("\n"); + printf(" offBmiSrc: %u\n", pEmr->offBmiSrc ); + printf(" cbBmiSrc: %u\n", pEmr->cbBmiSrc ); + if(pEmr->cbBmiSrc){ + printf(" Src bitmap: "); + bitmapinfo_print(contents + pEmr->offBmiSrc, blimit); + printf("\n"); + } + printf(" offBitsSrc: %u\n", pEmr->offBitsSrc ); + printf(" cbBitsSrc: %u\n", pEmr->cbBitsSrc ); + printf(" iUsageSrc: %u\n", pEmr->iUsageSrc ); + printf(" iStartScan: %u\n", pEmr->iStartScan ); + printf(" cScans : %u\n", pEmr->cScans ); +} + +// U_EMRSTRETCHDIBITS 81 +/** + \brief Print a pointer to a U_EMR_STRETCHDIBITS record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRSTRETCHDIBITS_print(const char *contents){ + PU_EMRSTRETCHDIBITS pEmr = (PU_EMRSTRETCHDIBITS) (contents); + if(pEmr->emr.nSize < sizeof(U_EMRSTRETCHDIBITS)){ + printf(" record corruption HERE\n"); + return; + } + const char *blimit = contents + pEmr->emr.nSize; + printf(" rclBounds: "); rectl_print( pEmr->rclBounds); printf("\n"); + printf(" Dest: "); pointl_print(pEmr->Dest); printf("\n"); + printf(" Src: "); pointl_print(pEmr->Src); printf("\n"); + printf(" cSrc: "); pointl_print(pEmr->cSrc); printf("\n"); + printf(" offBmiSrc: %u\n", pEmr->offBmiSrc ); + printf(" cbBmiSrc: %u\n", pEmr->cbBmiSrc ); + if(pEmr->cbBmiSrc){ + printf(" Src bitmap: "); + bitmapinfo_print(contents + pEmr->offBmiSrc, blimit); + printf("\n"); + } + printf(" offBitsSrc: %u\n", pEmr->offBitsSrc ); + printf(" cbBitsSrc: %u\n", pEmr->cbBitsSrc ); + printf(" iUsageSrc: %u\n", pEmr->iUsageSrc ); + printf(" dwRop : 0x%8.8X\n", pEmr->dwRop ); + printf(" cDest: "); pointl_print(pEmr->cDest); printf("\n"); +} + +// U_EMREXTCREATEFONTINDIRECTW_print 82 +/** + \brief Print a pointer to a U_EMR_EXTCREATEFONTINDIRECTW record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMREXTCREATEFONTINDIRECTW_print(const char *contents){ + PU_EMREXTCREATEFONTINDIRECTW pEmr = (PU_EMREXTCREATEFONTINDIRECTW) (contents); + if(pEmr->emr.nSize < U_SIZE_EMREXTCREATEFONTINDIRECTW_LOGFONT){ // smallest variant + printf(" record corruption HERE\n"); + return; + } + const char *blimit = contents + pEmr->emr.nSize; + printf(" ihFont: %u\n",pEmr->ihFont ); + printf(" Font: "); + if(pEmr->emr.nSize == U_SIZE_EMREXTCREATEFONTINDIRECTW_LOGFONT_PANOSE){ // holds logfont_panose + IF_MEM_UNSAFE_PRINT_AND_RETURN(&(pEmr->elfw), sizeof(U_PANOSE), blimit); + logfont_panose_print(pEmr->elfw); + } + else { // holds logfont or logfontExDv. The latter isn't supported but it starts with logfont, so use that + IF_MEM_UNSAFE_PRINT_AND_RETURN(&(pEmr->elfw), sizeof(U_LOGFONT), blimit); + logfont_print( *(PU_LOGFONT) &(pEmr->elfw)); + } + printf("\n"); +} + +// U_EMREXTTEXTOUTA 83 +/** + \brief Print a pointer to a U_EMR_EXTTEXTOUTA record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMREXTTEXTOUTA_print(const char *contents){ + core8_print("U_EMREXTTEXTOUTA", contents, 0); +} + +// U_EMREXTTEXTOUTW 84 +/** + \brief Print a pointer to a U_EMR_EXTTEXTOUTW record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMREXTTEXTOUTW_print(const char *contents){ + core8_print("U_EMREXTTEXTOUTW", contents, 1); +} + +// U_EMRPOLYBEZIER16 85 +/** + \brief Print a pointer to a U_EMR_POLYBEZIER16 record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRPOLYBEZIER16_print(const char *contents){ + core6_print("U_EMRPOLYBEZIER16", contents); +} + +// U_EMRPOLYGON16 86 +/** + \brief Print a pointer to a U_EMR_POLYGON16 record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRPOLYGON16_print(const char *contents){ + core6_print("U_EMRPOLYGON16", contents); +} + +// U_EMRPOLYLINE16 87 +/** + \brief Print a pointer to a U_EMR_POLYLINE16 record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRPOLYLINE16_print(const char *contents){ + core6_print("U_EMRPOLYLINE16", contents); +} + +// U_EMRPOLYBEZIERTO16 88 +/** + \brief Print a pointer to a U_EMR_POLYBEZIERTO16 record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRPOLYBEZIERTO16_print(const char *contents){ + core6_print("U_EMRPOLYBEZIERTO16", contents); +} + +// U_EMRPOLYLINETO16 89 +/** + \brief Print a pointer to a U_EMR_POLYLINETO16 record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRPOLYLINETO16_print(const char *contents){ + core6_print("U_EMRPOLYLINETO16", contents); +} + +// U_EMRPOLYPOLYLINE16 90 +/** + \brief Print a pointer to a U_EMR_POLYPOLYLINE16 record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRPOLYPOLYLINE16_print(const char *contents){ + core10_print("U_EMRPOLYPOLYLINE16", contents); +} + +// U_EMRPOLYPOLYGON16 91 +/** + \brief Print a pointer to a U_EMR_POLYPOLYGON16 record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRPOLYPOLYGON16_print(const char *contents){ + core10_print("U_EMRPOLYPOLYGON16", contents); +} + + +// U_EMRPOLYDRAW16 92 +/** + \brief Print a pointer to a U_EMR_POLYDRAW16 record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRPOLYDRAW16_print(const char *contents){ + unsigned int i; + PU_EMRPOLYDRAW16 pEmr = (PU_EMRPOLYDRAW16)(contents); + if(pEmr->emr.nSize < sizeof(U_EMRPOLYDRAW16)){ + printf(" record corruption HERE\n"); + return; + } + const char *blimit = contents + pEmr->emr.nSize; + printf(" rclBounds: "); rectl_print( pEmr->rclBounds); printf("\n"); + printf(" cpts: %d\n",pEmr->cpts ); + printf(" Points: "); + IF_MEM_UNSAFE_PRINT_AND_RETURN(pEmr->apts, pEmr->cpts*sizeof(U_POINT16), blimit); + for(i=0;i<pEmr->cpts; i++){ + printf(" [%d]:",i); + point16_print(pEmr->apts[i]); + } + printf("\n"); + printf(" Types: "); + const char *abTypes = (const char *) pEmr->apts + pEmr->cpts*sizeof(U_POINT16); + IF_MEM_UNSAFE_PRINT_AND_RETURN(abTypes, pEmr->cpts, blimit); + for(i=0;i<pEmr->cpts; i++){ + printf(" [%d]:%u ",i,((uint8_t *)abTypes)[i]); + } + printf("\n"); +} + +// U_EMRCREATEMONOBRUSH 93 +/** + \brief Print a pointer to a U_EMR_CREATEMONOBRUSH record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRCREATEMONOBRUSH_print(const char *contents){ + core12_print("U_EMRCREATEMONOBRUSH", contents); +} + +// U_EMRCREATEDIBPATTERNBRUSHPT_print 94 +/** + \brief Print a pointer to a U_EMR_CREATEDIBPATTERNBRUSHPT record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRCREATEDIBPATTERNBRUSHPT_print(const char *contents){ + core12_print("U_EMRCREATEDIBPATTERNBRUSHPT", contents); +} + + +// U_EMREXTCREATEPEN 95 +/** + \brief Print a pointer to a U_EMR_EXTCREATEPEN record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMREXTCREATEPEN_print(const char *contents){ + PU_EMREXTCREATEPEN pEmr = (PU_EMREXTCREATEPEN)(contents); + if(pEmr->emr.nSize < sizeof(U_EMREXTCREATEPEN)){ + printf(" record corruption HERE\n"); + return; + } + const char *blimit = contents + pEmr->emr.nSize; + printf(" ihPen: %u\n", pEmr->ihPen ); + printf(" offBmi: %u\n", pEmr->offBmi ); + printf(" cbBmi: %u\n", pEmr->cbBmi ); + if(pEmr->cbBmi){ + printf(" bitmap: "); + bitmapinfo_print(contents + pEmr->offBmi, blimit); + printf("\n"); + } + printf(" offBits: %u\n", pEmr->offBits ); + printf(" cbBits: %u\n", pEmr->cbBits ); + printf(" elp: "); extlogpen_print((PU_EXTLOGPEN) &(pEmr->elp)); printf("\n"); +} + +// U_EMRPOLYTEXTOUTA 96 NOT IMPLEMENTED, denigrated after Windows NT +#define U_EMRPOLYTEXTOUTA_print(A) U_EMRNOTIMPLEMENTED_print("U_EMRPOLYTEXTOUTA",A) //!< Not implemented. +// U_EMRPOLYTEXTOUTW 97 NOT IMPLEMENTED, denigrated after Windows NT +#define U_EMRPOLYTEXTOUTW_print(A) U_EMRNOTIMPLEMENTED_print("U_EMRPOLYTEXTOUTW",A) //!< Not implemented. + +// U_EMRSETICMMODE 98 +/** + \brief Print a pointer to a U_EMR_SETICMMODE record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRSETICMMODE_print(const char *contents){ + core3_print("U_EMRSETICMMODE", "iMode:", contents); +} + +// U_EMRCREATECOLORSPACE 99 +/** + \brief Print a pointer to a U_EMR_CREATECOLORSPACE record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRCREATECOLORSPACE_print(const char *contents){ + PU_EMRCREATECOLORSPACE pEmr = (PU_EMRCREATECOLORSPACE)(contents); + if(pEmr->emr.nSize < sizeof(U_EMRCREATECOLORSPACE)){ + printf(" record corruption HERE\n"); + return; + } + printf(" ihCS: %u\n", pEmr->ihCS ); + printf(" ColorSpace: "); logcolorspacea_print(pEmr->lcs); printf("\n"); +} + +// U_EMRSETCOLORSPACE 100 +/** + \brief Print a pointer to a U_EMR_SETCOLORSPACE record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRSETCOLORSPACE_print(const char *contents){ + core3_print("U_EMRSETCOLORSPACE", "ihCS:", contents); +} + +// U_EMRDELETECOLORSPACE 101 +/** + \brief Print a pointer to a U_EMR_DELETECOLORSPACE record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRDELETECOLORSPACE_print(const char *contents){ + core3_print("U_EMRDELETECOLORSPACE", "ihCS:", contents); +} + +// U_EMRGLSRECORD 102 Not implemented +#define U_EMRGLSRECORD_print(A) U_EMRNOTIMPLEMENTED_print("U_EMRGLSRECORD",A) //!< Not implemented. +// U_EMRGLSBOUNDEDRECORD 103 Not implemented +#define U_EMRGLSBOUNDEDRECORD_print(A) U_EMRNOTIMPLEMENTED_print("U_EMRGLSBOUNDEDRECORD",A) //!< Not implemented. + +// U_EMRPIXELFORMAT 104 +/** + \brief Print a pointer to a U_EMR_PIXELFORMAT record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRPIXELFORMAT_print(const char *contents){ + PU_EMRPIXELFORMAT pEmr = (PU_EMRPIXELFORMAT)(contents); + if(pEmr->emr.nSize < sizeof(U_EMRPIXELFORMAT)){ + printf(" record corruption HERE\n"); + return; + } + const char *blimit = contents + pEmr->emr.nSize; + IF_MEM_UNSAFE_PRINT_AND_RETURN(&(pEmr->pfd), sizeof(U_PIXELFORMATDESCRIPTOR), blimit); + printf(" Pfd: "); pixelformatdescriptor_print(pEmr->pfd); printf("\n"); +} + +// U_EMRDRAWESCAPE 105 Not implemented +#define U_EMRDRAWESCAPE_print(A) U_EMRNOTIMPLEMENTED_print("U_EMRDRAWESCAPE",A) //!< Not implemented. +// U_EMREXTESCAPE 106 Not implemented +#define U_EMREXTESCAPE_print(A) U_EMRNOTIMPLEMENTED_print("U_EMREXTESCAPE",A) //!< Not implemented. +// U_EMRUNDEF107 107 Not implemented +#define U_EMRUNDEF107_print(A) U_EMRNOTIMPLEMENTED_print("U_EMRUNDEF107",A) //!< Not implemented. + +// U_EMRSMALLTEXTOUT 108 +/** + \brief Print a pointer to a U_EMR_SMALLTEXTOUT record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRSMALLTEXTOUT_print(const char *contents){ + int roff; + char *string; + PU_EMRSMALLTEXTOUT pEmr = (PU_EMRSMALLTEXTOUT)(contents); + if(pEmr->emr.nSize < sizeof(U_EMRSMALLTEXTOUT)){ + printf(" record corruption HERE\n"); + return; + } + const char *blimit = contents + pEmr->emr.nSize; + printf(" Dest: "); pointl_print(pEmr->Dest); printf("\n"); + printf(" cChars: %u\n", pEmr->cChars ); + printf(" fuOptions: 0x%8.8X\n", pEmr->fuOptions ); + printf(" iGraphicsMode: 0x%8.8X\n", pEmr->iGraphicsMode ); + printf(" exScale: %f\n", pEmr->exScale ); + printf(" eyScale: %f\n", pEmr->eyScale ); + roff = sizeof(U_EMRSMALLTEXTOUT); //offset to the start of the variable fields + if(!(pEmr->fuOptions & U_ETO_NO_RECT)){ + IF_MEM_UNSAFE_PRINT_AND_RETURN(contents, roff, blimit); + printf(" rclBounds: "); rectl_print( *(PU_RECTL) (contents + roff)); printf("\n"); + roff += sizeof(U_RECTL); + } + if(pEmr->fuOptions & U_ETO_SMALL_CHARS){ + IF_MEM_UNSAFE_PRINT_AND_RETURN(contents, roff + pEmr->cChars*sizeof(char), blimit); + printf(" Text8: <%.*s>\n",pEmr->cChars,contents+roff); /* May not be null terminated */ + } + else { + string = U_Utf16leToUtf8((uint16_t *)(contents+roff), pEmr->cChars, NULL); + IF_MEM_UNSAFE_PRINT_AND_RETURN(contents, roff + pEmr->cChars*2*sizeof(char), blimit); + printf(" Text16: <%s>\n",contents+roff); + free(string); + } +} + +// U_EMRFORCEUFIMAPPING 109 Not implemented +#define U_EMRFORCEUFIMAPPING_print(A) U_EMRNOTIMPLEMENTED_print("U_EMRFORCEUFIMAPPING",A) //!< Not implemented. +// U_EMRNAMEDESCAPE 110 Not implemented +#define U_EMRNAMEDESCAPE_print(A) U_EMRNOTIMPLEMENTED_print("U_EMRNAMEDESCAPE",A) //!< Not implemented. +// U_EMRCOLORCORRECTPALETTE 111 Not implemented +#define U_EMRCOLORCORRECTPALETTE_print(A) U_EMRNOTIMPLEMENTED_print("U_EMRCOLORCORRECTPALETTE",A) //!< Not implemented. +// U_EMRSETICMPROFILEA 112 Not implemented +#define U_EMRSETICMPROFILEA_print(A) U_EMRNOTIMPLEMENTED_print("U_EMRSETICMPROFILEA",A) //!< Not implemented. +// U_EMRSETICMPROFILEW 113 Not implemented +#define U_EMRSETICMPROFILEW_print(A) U_EMRNOTIMPLEMENTED_print("U_EMRSETICMPROFILEW",A) //!< Not implemented. + +// U_EMRALPHABLEND 114 +/** + \brief Print a pointer to a U_EMR_ALPHABLEND record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRALPHABLEND_print(const char *contents){ + core13_print("U_EMRALPHABLEND", contents); +} + +// U_EMRSETLAYOUT 115 +/** + \brief Print a pointer to a U_EMR_SETLAYOUT record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRSETLAYOUT_print(const char *contents){ + core3_print("U_EMRSETLAYOUT", "iMode:", contents); +} + +// U_EMRTRANSPARENTBLT 116 +/** + \brief Print a pointer to a U_EMR_TRANSPARENTBLT record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRTRANSPARENTBLT_print(const char *contents){ + core13_print("U_EMRTRANSPARENTBLT", contents); +} + +// U_EMRUNDEF117 117 Not implemented +#define U_EMRUNDEF117_print(A) U_EMRNOTIMPLEMENTED_print("U_EMRUNDEF117",A) //!< Not implemented. +// U_EMRGRADIENTFILL 118 +/** + \brief Print a pointer to a U_EMR_GRADIENTFILL record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRGRADIENTFILL_print(const char *contents){ + unsigned int i; + PU_EMRGRADIENTFILL pEmr = (PU_EMRGRADIENTFILL)(contents); + if(pEmr->emr.nSize < sizeof(U_EMRGRADIENTFILL)){ + printf(" record corruption HERE\n"); + return; + } + const char *blimit = contents + pEmr->emr.nSize; + printf(" rclBounds: "); rectl_print( pEmr->rclBounds); printf("\n"); + printf(" nTriVert: %u\n", pEmr->nTriVert ); + printf(" nGradObj: %u\n", pEmr->nGradObj ); + printf(" ulMode: %u\n", pEmr->ulMode ); + contents += sizeof(U_EMRGRADIENTFILL); + if(pEmr->nTriVert){ + IF_MEM_UNSAFE_PRINT_AND_RETURN(contents, pEmr->nTriVert*sizeof(U_TRIVERTEX), blimit); + printf(" TriVert: "); + for(i=0; i<pEmr->nTriVert; i++, contents+=sizeof(U_TRIVERTEX)){ + trivertex_print(*(PU_TRIVERTEX)(contents)); + } + printf("\n"); + } + if(pEmr->nGradObj){ + printf(" GradObj: "); + if( pEmr->ulMode == U_GRADIENT_FILL_TRIANGLE){ + IF_MEM_UNSAFE_PRINT_AND_RETURN(contents, pEmr->nGradObj*sizeof(U_GRADIENT3), blimit); + for(i=0; i<pEmr->nGradObj; i++, contents+=sizeof(U_GRADIENT3)){ + gradient3_print(*(PU_GRADIENT3)(contents)); + } + } + else if(pEmr->ulMode == U_GRADIENT_FILL_RECT_H || + pEmr->ulMode == U_GRADIENT_FILL_RECT_V){ + IF_MEM_UNSAFE_PRINT_AND_RETURN(contents, pEmr->nGradObj*sizeof(U_GRADIENT4), blimit); + for(i=0; i<pEmr->nGradObj; i++, contents+=sizeof(U_GRADIENT4)){ + gradient4_print(*(PU_GRADIENT4)(contents)); + } + } + else { printf("invalid ulMode value!"); } + printf("\n"); + } +} + +// U_EMRSETLINKEDUFIS 119 Not implemented +#define U_EMRSETLINKEDUFIS_print(A) U_EMRNOTIMPLEMENTED_print("U_EMR_SETLINKEDUFIS",A) //!< Not implemented. +// U_EMRSETTEXTJUSTIFICATION120 Not implemented (denigrated) +#define U_EMRSETTEXTJUSTIFICATION_print(A) U_EMRNOTIMPLEMENTED_print("U_EMR_SETTEXTJUSTIFICATION",A) //!< Not implemented. +// U_EMRCOLORMATCHTOTARGETW 121 Not implemented +#define U_EMRCOLORMATCHTOTARGETW_print(A) U_EMRNOTIMPLEMENTED_print("U_EMR_COLORMATCHTOTARGETW",A) //!< Not implemented. + +// U_EMRCREATECOLORSPACEW 122 +/** + \brief Print a pointer to a U_EMR_CREATECOLORSPACEW record. + \param contents pointer to a buffer holding all EMR records +*/ +void U_EMRCREATECOLORSPACEW_print(const char *contents){ + unsigned int i; + PU_EMRCREATECOLORSPACEW pEmr = (PU_EMRCREATECOLORSPACEW)(contents); + if(pEmr->emr.nSize < sizeof(U_EMRCREATECOLORSPACEW)){ + printf(" record corruption HERE\n"); + return; + } + const char *blimit = contents + pEmr->emr.nSize; + printf(" ihCS: %u\n", pEmr->ihCS ); + printf(" ColorSpace: "); logcolorspacew_print(pEmr->lcs); printf("\n"); + printf(" dwFlags: 0x%8.8X\n", pEmr->dwFlags ); + printf(" cbData: %u\n", pEmr->cbData ); + printf(" Data(hexvalues):"); + if(pEmr->dwFlags & 1){ + IF_MEM_UNSAFE_PRINT_AND_RETURN(contents, pEmr->cbData, blimit); + for(i=0; i<pEmr->cbData; i++){ + printf("[%d]:%2.2X ",i,pEmr->Data[i]); + } + } + printf("\n"); +} + +/** + \brief Print any record in an emf + \returns record length for a normal record, 0 for EMREOF, -1 for a bad record + \param contents pointer to a buffer holding all EMR records + \param blimit pointer to the byte after the last byte in the buffer holding all EMR records + \param recnum number of this record in contents + \param off offset to this record in contents +*/ +int U_emf_onerec_print(const char *contents, const char *blimit, int recnum, size_t off){ + PU_ENHMETARECORD lpEMFR = (PU_ENHMETARECORD)(contents + off); + uint32_t nSize; + uint32_t iType; + const char *record = contents + off; + + if(record < contents)return(-1); // offset wrapped + + /* Check that COMMON data in record can be touched without an access violation. If it cannot be + this is either a corrupt EMF or one engineered to cause a buffer overflow. Pointer math + could wrap so check both sides of the range. + */ + if(!U_emf_record_sizeok(record, blimit, &nSize, &iType, 1))return(-1); + + uint32_t crc; +#if U_BYTE_SWAP + //This is a Big Endian machine, EMF crc values must be calculated on Little Endian form + char *swapbuf=malloc(nSize); + if(!swapbuf)return(-1); + memcpy(swapbuf,record,nSize); + U_emf_endian(swapbuf,nSize,1); // BE to LE + crc=lu_crc32(swapbuf,nSize); + free(swapbuf); +#else + crc=lu_crc32(record,nSize); +#endif + printf("%-30srecord:%5d type:%-4d offset:%8d rsize:%8d crc32:%8.8X\n", + U_emr_names(iType),recnum,iType,(int) off,nSize,crc); + + fflush(stdout); + + /* print the record header before checking further. + Note if this is a corrupt record, but continue anyway. + The _print routines will stop at the actual problem and print another corrupt message. + */ + if(!U_emf_record_safe(record)){printf("WARNING: Corrupt record. Emitting fields above the problem.\n");} + + switch (lpEMFR->iType) + { + case U_EMR_HEADER: U_EMRHEADER_print(record); break; + case U_EMR_POLYBEZIER: U_EMRPOLYBEZIER_print(record); break; + case U_EMR_POLYGON: U_EMRPOLYGON_print(record); break; + case U_EMR_POLYLINE: U_EMRPOLYLINE_print(record); break; + case U_EMR_POLYBEZIERTO: U_EMRPOLYBEZIERTO_print(record); break; + case U_EMR_POLYLINETO: U_EMRPOLYLINETO_print(record); break; + case U_EMR_POLYPOLYLINE: U_EMRPOLYPOLYLINE_print(record); break; + case U_EMR_POLYPOLYGON: U_EMRPOLYPOLYGON_print(record); break; + case U_EMR_SETWINDOWEXTEX: U_EMRSETWINDOWEXTEX_print(record); break; + case U_EMR_SETWINDOWORGEX: U_EMRSETWINDOWORGEX_print(record); break; + case U_EMR_SETVIEWPORTEXTEX: U_EMRSETVIEWPORTEXTEX_print(record); break; + case U_EMR_SETVIEWPORTORGEX: U_EMRSETVIEWPORTORGEX_print(record); break; + case U_EMR_SETBRUSHORGEX: U_EMRSETBRUSHORGEX_print(record); break; + case U_EMR_EOF: U_EMREOF_print(record); nSize=0; break; + case U_EMR_SETPIXELV: U_EMRSETPIXELV_print(record); break; + case U_EMR_SETMAPPERFLAGS: U_EMRSETMAPPERFLAGS_print(record); break; + case U_EMR_SETMAPMODE: U_EMRSETMAPMODE_print(record); break; + case U_EMR_SETBKMODE: U_EMRSETBKMODE_print(record); break; + case U_EMR_SETPOLYFILLMODE: U_EMRSETPOLYFILLMODE_print(record); break; + case U_EMR_SETROP2: U_EMRSETROP2_print(record); break; + case U_EMR_SETSTRETCHBLTMODE: U_EMRSETSTRETCHBLTMODE_print(record); break; + case U_EMR_SETTEXTALIGN: U_EMRSETTEXTALIGN_print(record); break; + case U_EMR_SETCOLORADJUSTMENT: U_EMRSETCOLORADJUSTMENT_print(record); break; + case U_EMR_SETTEXTCOLOR: U_EMRSETTEXTCOLOR_print(record); break; + case U_EMR_SETBKCOLOR: U_EMRSETBKCOLOR_print(record); break; + case U_EMR_OFFSETCLIPRGN: U_EMROFFSETCLIPRGN_print(record); break; + case U_EMR_MOVETOEX: U_EMRMOVETOEX_print(record); break; + case U_EMR_SETMETARGN: U_EMRSETMETARGN_print(record); break; + case U_EMR_EXCLUDECLIPRECT: U_EMREXCLUDECLIPRECT_print(record); break; + case U_EMR_INTERSECTCLIPRECT: U_EMRINTERSECTCLIPRECT_print(record); break; + case U_EMR_SCALEVIEWPORTEXTEX: U_EMRSCALEVIEWPORTEXTEX_print(record); break; + case U_EMR_SCALEWINDOWEXTEX: U_EMRSCALEWINDOWEXTEX_print(record); break; + case U_EMR_SAVEDC: U_EMRSAVEDC_print(record); break; + case U_EMR_RESTOREDC: U_EMRRESTOREDC_print(record); break; + case U_EMR_SETWORLDTRANSFORM: U_EMRSETWORLDTRANSFORM_print(record); break; + case U_EMR_MODIFYWORLDTRANSFORM: U_EMRMODIFYWORLDTRANSFORM_print(record); break; + case U_EMR_SELECTOBJECT: U_EMRSELECTOBJECT_print(record); break; + case U_EMR_CREATEPEN: U_EMRCREATEPEN_print(record); break; + case U_EMR_CREATEBRUSHINDIRECT: U_EMRCREATEBRUSHINDIRECT_print(record); break; + case U_EMR_DELETEOBJECT: U_EMRDELETEOBJECT_print(record); break; + case U_EMR_ANGLEARC: U_EMRANGLEARC_print(record); break; + case U_EMR_ELLIPSE: U_EMRELLIPSE_print(record); break; + case U_EMR_RECTANGLE: U_EMRRECTANGLE_print(record); break; + case U_EMR_ROUNDRECT: U_EMRROUNDRECT_print(record); break; + case U_EMR_ARC: U_EMRARC_print(record); break; + case U_EMR_CHORD: U_EMRCHORD_print(record); break; + case U_EMR_PIE: U_EMRPIE_print(record); break; + case U_EMR_SELECTPALETTE: U_EMRSELECTPALETTE_print(record); break; + case U_EMR_CREATEPALETTE: U_EMRCREATEPALETTE_print(record); break; + case U_EMR_SETPALETTEENTRIES: U_EMRSETPALETTEENTRIES_print(record); break; + case U_EMR_RESIZEPALETTE: U_EMRRESIZEPALETTE_print(record); break; + case U_EMR_REALIZEPALETTE: U_EMRREALIZEPALETTE_print(record); break; + case U_EMR_EXTFLOODFILL: U_EMREXTFLOODFILL_print(record); break; + case U_EMR_LINETO: U_EMRLINETO_print(record); break; + case U_EMR_ARCTO: U_EMRARCTO_print(record); break; + case U_EMR_POLYDRAW: U_EMRPOLYDRAW_print(record); break; + case U_EMR_SETARCDIRECTION: U_EMRSETARCDIRECTION_print(record); break; + case U_EMR_SETMITERLIMIT: U_EMRSETMITERLIMIT_print(record); break; + case U_EMR_BEGINPATH: U_EMRBEGINPATH_print(record); break; + case U_EMR_ENDPATH: U_EMRENDPATH_print(record); break; + case U_EMR_CLOSEFIGURE: U_EMRCLOSEFIGURE_print(record); break; + case U_EMR_FILLPATH: U_EMRFILLPATH_print(record); break; + case U_EMR_STROKEANDFILLPATH: U_EMRSTROKEANDFILLPATH_print(record); break; + case U_EMR_STROKEPATH: U_EMRSTROKEPATH_print(record); break; + case U_EMR_FLATTENPATH: U_EMRFLATTENPATH_print(record); break; + case U_EMR_WIDENPATH: U_EMRWIDENPATH_print(record); break; + case U_EMR_SELECTCLIPPATH: U_EMRSELECTCLIPPATH_print(record); break; + case U_EMR_ABORTPATH: U_EMRABORTPATH_print(record); break; + case U_EMR_UNDEF69: U_EMRUNDEF69_print(record); break; + case U_EMR_COMMENT: U_EMRCOMMENT_print(record, off); break; + case U_EMR_FILLRGN: U_EMRFILLRGN_print(record); break; + case U_EMR_FRAMERGN: U_EMRFRAMERGN_print(record); break; + case U_EMR_INVERTRGN: U_EMRINVERTRGN_print(record); break; + case U_EMR_PAINTRGN: U_EMRPAINTRGN_print(record); break; + case U_EMR_EXTSELECTCLIPRGN: U_EMREXTSELECTCLIPRGN_print(record); break; + case U_EMR_BITBLT: U_EMRBITBLT_print(record); break; + case U_EMR_STRETCHBLT: U_EMRSTRETCHBLT_print(record); break; + case U_EMR_MASKBLT: U_EMRMASKBLT_print(record); break; + case U_EMR_PLGBLT: U_EMRPLGBLT_print(record); break; + case U_EMR_SETDIBITSTODEVICE: U_EMRSETDIBITSTODEVICE_print(record); break; + case U_EMR_STRETCHDIBITS: U_EMRSTRETCHDIBITS_print(record); break; + case U_EMR_EXTCREATEFONTINDIRECTW: U_EMREXTCREATEFONTINDIRECTW_print(record); break; + case U_EMR_EXTTEXTOUTA: U_EMREXTTEXTOUTA_print(record); break; + case U_EMR_EXTTEXTOUTW: U_EMREXTTEXTOUTW_print(record); break; + case U_EMR_POLYBEZIER16: U_EMRPOLYBEZIER16_print(record); break; + case U_EMR_POLYGON16: U_EMRPOLYGON16_print(record); break; + case U_EMR_POLYLINE16: U_EMRPOLYLINE16_print(record); break; + case U_EMR_POLYBEZIERTO16: U_EMRPOLYBEZIERTO16_print(record); break; + case U_EMR_POLYLINETO16: U_EMRPOLYLINETO16_print(record); break; + case U_EMR_POLYPOLYLINE16: U_EMRPOLYPOLYLINE16_print(record); break; + case U_EMR_POLYPOLYGON16: U_EMRPOLYPOLYGON16_print(record); break; + case U_EMR_POLYDRAW16: U_EMRPOLYDRAW16_print(record); break; + case U_EMR_CREATEMONOBRUSH: U_EMRCREATEMONOBRUSH_print(record); break; + case U_EMR_CREATEDIBPATTERNBRUSHPT: U_EMRCREATEDIBPATTERNBRUSHPT_print(record); break; + case U_EMR_EXTCREATEPEN: U_EMREXTCREATEPEN_print(record); break; + case U_EMR_POLYTEXTOUTA: U_EMRPOLYTEXTOUTA_print(record); break; + case U_EMR_POLYTEXTOUTW: U_EMRPOLYTEXTOUTW_print(record); break; + case U_EMR_SETICMMODE: U_EMRSETICMMODE_print(record); break; + case U_EMR_CREATECOLORSPACE: U_EMRCREATECOLORSPACE_print(record); break; + case U_EMR_SETCOLORSPACE: U_EMRSETCOLORSPACE_print(record); break; + case U_EMR_DELETECOLORSPACE: U_EMRDELETECOLORSPACE_print(record); break; + case U_EMR_GLSRECORD: U_EMRGLSRECORD_print(record); break; + case U_EMR_GLSBOUNDEDRECORD: U_EMRGLSBOUNDEDRECORD_print(record); break; + case U_EMR_PIXELFORMAT: U_EMRPIXELFORMAT_print(record); break; + case U_EMR_DRAWESCAPE: U_EMRDRAWESCAPE_print(record); break; + case U_EMR_EXTESCAPE: U_EMREXTESCAPE_print(record); break; + case U_EMR_UNDEF107: U_EMRUNDEF107_print(record); break; + case U_EMR_SMALLTEXTOUT: U_EMRSMALLTEXTOUT_print(record); break; + case U_EMR_FORCEUFIMAPPING: U_EMRFORCEUFIMAPPING_print(record); break; + case U_EMR_NAMEDESCAPE: U_EMRNAMEDESCAPE_print(record); break; + case U_EMR_COLORCORRECTPALETTE: U_EMRCOLORCORRECTPALETTE_print(record); break; + case U_EMR_SETICMPROFILEA: U_EMRSETICMPROFILEA_print(record); break; + case U_EMR_SETICMPROFILEW: U_EMRSETICMPROFILEW_print(record); break; + case U_EMR_ALPHABLEND: U_EMRALPHABLEND_print(record); break; + case U_EMR_SETLAYOUT: U_EMRSETLAYOUT_print(record); break; + case U_EMR_TRANSPARENTBLT: U_EMRTRANSPARENTBLT_print(record); break; + case U_EMR_UNDEF117: U_EMRUNDEF117_print(record); break; + case U_EMR_GRADIENTFILL: U_EMRGRADIENTFILL_print(record); break; + case U_EMR_SETLINKEDUFIS: U_EMRSETLINKEDUFIS_print(record); break; + case U_EMR_SETTEXTJUSTIFICATION: U_EMRSETTEXTJUSTIFICATION_print(record); break; + case U_EMR_COLORMATCHTOTARGETW: U_EMRCOLORMATCHTOTARGETW_print(record); break; + case U_EMR_CREATECOLORSPACEW: U_EMRCREATECOLORSPACEW_print(record); break; + default: U_EMRNOTIMPLEMENTED_print("?",record); break; + } //end of switch + return(nSize); +} + + +#ifdef __cplusplus +} +#endif diff --git a/src/3rdparty/libuemf/uemf_print.h b/src/3rdparty/libuemf/uemf_print.h new file mode 100644 index 0000000..088a8a3 --- /dev/null +++ b/src/3rdparty/libuemf/uemf_print.h @@ -0,0 +1,177 @@ +/** + @file uemf_print.h + + @brief Prototypes for functions for printing records from EMF files. +*/ + +/* +File: uemf_print.h +Version: 0.0.9 +Date: 21-MAY-2015 +Author: David Mathog, Biology Division, Caltech +email: mathog@caltech.edu +Copyright: 2015 David Mathog and California Institute of Technology (Caltech) +*/ + +#ifndef _UEMF_PRINT_ +#define _UEMF_PRINT_ + +#ifdef __cplusplus +extern "C" { +#endif + +//! \cond +/* prototypes for miscellaneous */ +uint32_t lu_crc32(const char *record, uint32_t Size); + +/* prototypes for objects used in EMR records */ +void hexbytes_print(uint8_t *buf,unsigned int num); +void colorref_print(U_COLORREF color); +void rgbquad_print(U_RGBQUAD color); +void rectl_print(U_RECTL rect); +void sizel_print(U_SIZEL sz); +void pointl_print(U_POINTL pt); +void point16_print(U_POINT16 pt); +void lcs_gamma_print(U_LCS_GAMMA lg); +void lcs_gammargb_print(U_LCS_GAMMARGB lgr); +void trivertex_print(U_TRIVERTEX tv); +void gradient3_print(U_GRADIENT3 g3); +void gradient4_print(U_GRADIENT4 g4); +void logbrush_print(U_LOGBRUSH lb); +void xform_print(U_XFORM xform); +void ciexyz_print(U_CIEXYZ ciexyz); +void ciexyztriple_print(U_CIEXYZTRIPLE cie3); +void logcolorspacea_print(U_LOGCOLORSPACEA lcsa); +void logcolorspacew_print(U_LOGCOLORSPACEW lcsa); +void panose_print(U_PANOSE panose); +void logfont_print(U_LOGFONT lf); +void logfont_panose_print(U_LOGFONT_PANOSE lfp); +void bitmapinfoheader_print(const char *Bmih); +void bitmapinfo_print(const char *Bmi, const char *blimit); +void blend_print(U_BLEND blend); +void extlogpen_print(const PU_EXTLOGPEN elp); +void logpen_print(U_LOGPEN lp); +void logpltntry_print(U_LOGPLTNTRY lpny); +void logpalette_print(const PU_LOGPALETTE lp); +void rgndataheader_print(U_RGNDATAHEADER rdh); +void rgndata_print(const PU_RGNDATA rd, const char *blimit); +void coloradjustment_print(U_COLORADJUSTMENT ca); +void pixelformatdescriptor_print(U_PIXELFORMATDESCRIPTOR pfd); +void emrtext_print(const char *emt, const char *record, const char *blimit, int type); + +/* prototypes for EMR records */ +void U_EMRNOTIMPLEMENTED_print(const char *name, const char *contents, int recnum, int off); +void U_EMRHEADER_print(const char *contents); +void U_EMRPOLYBEZIER_print(const char *contents); +void U_EMRPOLYGON_print(const char *contents); +void U_EMRPOLYLINE_print(const char *contents); +void U_EMRPOLYBEZIERTO_print(const char *contents); +void U_EMRPOLYLINETO_print(const char *contents); +void U_EMRPOLYPOLYLINE_print(const char *contents); +void U_EMRPOLYPOLYGON_print(const char *contents); +void U_EMRSETWINDOWEXTEX_print(const char *contents); +void U_EMRSETWINDOWORGEX_print(const char *contents); +void U_EMRSETVIEWPORTEXTEX_print(const char *contents); +void U_EMRSETVIEWPORTORGEX_print(const char *contents); +void U_EMRSETBRUSHORGEX_print(const char *contents); +void U_EMREOF_print(const char *contents); +void U_EMRSETPIXELV_print(const char *contents); +void U_EMRSETMAPPERFLAGS_print(const char *contents); +void U_EMRSETMAPMODE_print(const char *contents); +void U_EMRSETBKMODE_print(const char *contents); +void U_EMRSETPOLYFILLMODE_print(const char *contents); +void U_EMRSETROP2_print(const char *contents); +void U_EMRSETSTRETCHBLTMODE_print(const char *contents); +void U_EMRSETTEXTALIGN_print(const char *contents); +void U_EMRSETCOLORADJUSTMENT_print(const char *contents); +void U_EMRSETTEXTCOLOR_print(const char *contents); +void U_EMRSETBKCOLOR_print(const char *contents); +void U_EMROFFSETCLIPRGN_print(const char *contents); +void U_EMRMOVETOEX_print(const char *contents); +void U_EMRSETMETARGN_print(const char *contents); +void U_EMREXCLUDECLIPRECT_print(const char *contents); +void U_EMRINTERSECTCLIPRECT_print(const char *contents); +void U_EMRSCALEVIEWPORTEXTEX_print(const char *contents); +void U_EMRSCALEWINDOWEXTEX_print(const char *contents); +void U_EMRSAVEDC_print(const char *contents); +void U_EMRRESTOREDC_print(const char *contents); +void U_EMRSETWORLDTRANSFORM_print(const char *contents); +void U_EMRMODIFYWORLDTRANSFORM_print(const char *contents); +void U_EMRSELECTOBJECT_print(const char *contents); +void U_EMRCREATEPEN_print(const char *contents); +void U_EMRCREATEBRUSHINDIRECT_print(const char *contents); +void U_EMRDELETEOBJECT_print(const char *contents); +void U_EMRANGLEARC_print(const char *contents); +void U_EMRELLIPSE_print(const char *contents); +void U_EMRRECTANGLE_print(const char *contents); +void U_EMRROUNDRECT_print(const char *contents); +void U_EMRARC_print(const char *contents); +void U_EMRCHORD_print(const char *contents); +void U_EMRPIE_print(const char *contents); +void U_EMRSELECTPALETTE_print(const char *contents); +void U_EMRCREATEPALETTE_print(const char *contents); +void U_EMRSETPALETTEENTRIES_print(const char *contents); +void U_EMRRESIZEPALETTE_print(const char *contents); +void U_EMRREALIZEPALETTE_print(const char *contents); +void U_EMREXTFLOODFILL_print(const char *contents); +void U_EMRLINETO_print(const char *contents); +void U_EMRARCTO_print(const char *contents); +void U_EMRPOLYDRAW_print(const char *contents); +void U_EMRSETARCDIRECTION_print(const char *contents); +void U_EMRSETMITERLIMIT_print(const char *contents); +void U_EMRBEGINPATH_print(const char *contents); +void U_EMRENDPATH_print(const char *contents); +void U_EMRCLOSEFIGURE_print(const char *contents); +void U_EMRFILLPATH_print(const char *contents); +void U_EMRSTROKEANDFILLPATH_print(const char *contents); +void U_EMRSTROKEPATH_print(const char *contents); +void U_EMRFLATTENPATH_print(const char *contents); +void U_EMRWIDENPATH_print(const char *contents); +void U_EMRSELECTCLIPPATH_print(const char *contents); +void U_EMRABORTPATH_print(const char *contents); +void U_EMRCOMMENT_print(const char *contents, size_t off); +void U_EMRFILLRGN_print(const char *contents); +void U_EMRFRAMERGN_print(const char *contents); +void U_EMRINVERTRGN_print(const char *contents); +void U_EMRPAINTRGN_print(const char *contents); +void U_EMREXTSELECTCLIPRGN_print(const char *contents); +void U_EMRBITBLT_print(const char *contents); +void U_EMRSTRETCHBLT_print(const char *contents); +void U_EMRMASKBLT_print(const char *contents); +void U_EMRPLGBLT_print(const char *contents); +void U_EMRSETDIBITSTODEVICE_print(const char *contents); +void U_EMRSTRETCHDIBITS_print(const char *contents); +void U_EMREXTCREATEFONTINDIRECTW_print(const char *contents); +void U_EMREXTTEXTOUTA_print(const char *contents); +void U_EMREXTTEXTOUTW_print(const char *contents); +void U_EMRPOLYBEZIER16_print(const char *contents); +void U_EMRPOLYGON16_print(const char *contents); +void U_EMRPOLYLINE16_print(const char *contents); +void U_EMRPOLYBEZIERTO16_print(const char *contents); +void U_EMRPOLYLINETO16_print(const char *contents); +void U_EMRPOLYPOLYLINE16_print(const char *contents); +void U_EMRPOLYPOLYGON16_print(const char *contents); +void U_EMRPOLYDRAW16_print(const char *contents); +void U_EMRCREATEMONOBRUSH_print(const char *contents); +void U_EMRCREATEDIBPATTERNBRUSHPT_print(const char *contents); +void U_EMREXTCREATEPEN_print(const char *contents); +void U_EMRSETICMMODE_print(const char *contents); +void U_EMRCREATECOLORSPACE_print(const char *contents); +void U_EMRSETCOLORSPACE_print(const char *contents); +void U_EMRDELETECOLORSPACE_print(const char *contents); +void U_EMRPIXELFORMAT_print(const char *contents); +void U_EMRSMALLTEXTOUT_print(const char *contents); +void U_EMRALPHABLEND_print(const char *contents); +void U_EMRSETLAYOUT_print(const char *contents); +void U_EMRTRANSPARENTBLT_print(const char *contents); +void U_EMRGRADIENTFILL_print(const char *contents); +void U_EMRCREATECOLORSPACEW_print(const char *contents); +int U_emf_onerec_print(const char *contents, char *blimit, int recnum, int off); +//! \endcond + + +#ifdef __cplusplus +} +#endif + +#endif /* _UEMF_PRINT_ */ diff --git a/src/3rdparty/libuemf/uemf_safe.c b/src/3rdparty/libuemf/uemf_safe.c new file mode 100644 index 0000000..a3e0502 --- /dev/null +++ b/src/3rdparty/libuemf/uemf_safe.c @@ -0,0 +1,1204 @@ +/** + @file uemf_safe.c + + @brief Functions for checking EMF records for memory issues. + + EMF records come in a variety of sizes, and some types have variable sizes. + These functions check the record types and report if there are any issues + that could cause a memory access problem. All counts and offsets are examined + and the data structure checked so that no referenced byte is outside of the + declared size of the record. + + Many variables are initialized to zero even though they will always be set because + some versions of gcc give spurious "may be used uninitialized" warnings otherwise. +*/ + +/* +File: uemf_safe.c +Version: 0.0.5 +Date: 26-JAN-2016 +Author: David Mathog, Biology Division, Caltech +email: mathog@caltech.edu +Copyright: 2016 David Mathog and California Institute of Technology (Caltech) +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <stddef.h> /* for offsetof() macro */ +#include "uemf.h" +#include "uemf_endian.h" // for u_emf_record_sizeok + +// hide almost everuything in here from Doxygen +//! \cond + +/** + \brief Test a U_EXTLOGPEN object. + \param elp PU_EXTLOGPEN object + \param blimit one byte past the end of the record +*/ +int extlogpen_safe( + PU_EXTLOGPEN elp, + const char *blimit + ){ + int count=elp->elpNumEntries; + if(IS_MEM_UNSAFE(&(elp->elpStyleEntry), count*4, blimit))return(0); + return(1); +} + +/** + \brief Test a U_EMRTEXT record + \param pemt Pointer to a U_EMRTEXT record + \param record Pointer to the start of the record which contains this U_EMRTEXT + \param blimit one byte past the end of the record. +*/ +int emrtext_safe( + PU_EMRTEXT pemt, + const char *record, + const char *blimit + ){ + int off; + uint32_t count = pemt->nChars; + uint32_t fOptions = pemt->fOptions; + uint32_t offDx = 0; + off = sizeof(U_EMRTEXT); + if(!(fOptions & U_ETO_NO_RECT)){ + if(IS_MEM_UNSAFE(pemt, sizeof(U_RECTL), blimit))return(0); + off+=sizeof(U_RECTL); + } + offDx = *(uint32_t *)((char *)pemt +off); + if(IS_MEM_UNSAFE(pemt, off + 4, blimit))return(0); + if(IS_MEM_UNSAFE(record, offDx + count*4, blimit))return(0); + return(1); +} + +/** + \return 1 on success, 0 on failure + \brief Test a U_RGNDATA object. + \param rd pointer to a U_RGNDATA object. + \param cbRgnData size of the U_RGNDATA object. +*/ +int rgndata_safe( + PU_RGNDATA rd, + int cbRgnData + ){ + int count = rd->rdh.nCount; + if(4*count + (int)sizeof(U_RGNDATAHEADER) > cbRgnData)return(0); + return(1); +} + + +/** + \return 1 on success, 0 on failure + \brief Test a U_BITMAPINFO object. + \param Bmi pointer to a U_BITMAPINFO object. + \param blimit one byte past the end of the record. +*/ +int bitmapinfo_safe( + const char *Bmi, + const char *blimit + ){ + int ClrUsed; + if(IS_MEM_UNSAFE(Bmi, offsetof(U_BITMAPINFO,bmiHeader) + sizeof(U_BITMAPINFOHEADER), blimit))return(0); + ClrUsed = get_real_color_count(Bmi + offsetof(U_BITMAPINFO,bmiHeader)); + if(ClrUsed && IS_MEM_UNSAFE(Bmi, offsetof(U_BITMAPINFO,bmiColors) + ClrUsed*sizeof(U_RGBQUAD), blimit))return(0); + return(1); +} + +/** + \brief Check that the bitmap in the specified DIB is compatible with the record size + + \return 1 on success, 0 on failure + \param record EMF record that contains a DIB pixel array + \param iUsage DIBcolors Enumeration + \param offBmi offset from the start of the record to the start of the bitmapinfo structure + \param cbBmi declared space for the bitmapinfo structure in the record + \param offBits offset from the start of the record to the start of the bitmap + \param cbBits declared space for the bitmap in the record (amount used may be less than this) + \param blimit one byte past the end of the record. + + This method can only test DIBs that hold Microsoft's various bitmap types. PNG or JPG is just a bag + of bytes, and there is no possible way to derive from the known width and height how big it should be. +*/ +int DIB_safe( + const char *record, + uint32_t iUsage, + uint32_t offBmi, + uint32_t cbBmi, + uint32_t offBits, + uint32_t cbBits, + const char *blimit + ){ + int dibparams = U_BI_UNKNOWN; // type of image not yet determined + const char *px = NULL; // DIB pixels + const U_RGBQUAD *ct = NULL; // DIB color table + int bs; + int usedbytes; + + if(!cbBmi)return(1); // No DIB in a record where it is optional + if(IS_MEM_UNSAFE(record, offBmi + cbBmi, blimit))return(0); + if(!bitmapinfo_safe(record + offBmi, blimit))return(0); // checks the number of colors + if(cbBits && IS_MEM_UNSAFE(record, offBits + cbBits, blimit))return(0); + if(iUsage == U_DIB_RGB_COLORS){ + uint32_t width, height, colortype, numCt, invert; // these values will be set in get_DIB_params + // next call returns pointers and values, but allocates no memory + dibparams = get_DIB_params(record, offBits, offBmi, &px, (const U_RGBQUAD **) &ct, + &numCt, &width, &height, &colortype, &invert); + + // sanity checking + if(numCt && colortype >= U_BCBM_COLOR16)return(0); //color tables not used above 16 bit pixels + if(!numCt && colortype < U_BCBM_COLOR16)return(0); //color tables mandatory for < 16 bit + + if(dibparams ==U_BI_RGB){ + // this is the only DIB type where we can calculate how big it should be when stored in the EMF file + bs = colortype/8; + if(bs<1){ + usedbytes = (width*colortype + 7)/8; // width of line in fully and partially occupied bytes + } + else { + usedbytes = width*bs; + } + if(IS_MEM_UNSAFE(record+offBits, usedbytes, blimit))return(0); + } + } + return(1); +} + + +/* ********************************************************************************************** +These functions contain shared code used by various U_EMR*_safe functions. These should NEVER be called +by end user code and to further that end prototypes are NOT provided and they are hidden from Doxygen. + + + These all have this form: + + void core1_safe(const char *record){ + + but some do not actually use torev. + + + +*********************************************************************************************** */ + +// all core*_safe call this, U_EMRSETMARGN_safe and some others all it directly +// numbered as core5 to be consistent with uemf.c, but must appear before the others as there is no prototype +// sizeof(U_ENHMETARECORD) bytes in the record +int core5_safe(const char *record, int minSize){ + PU_EMR pEmr = (PU_EMR)(record); + if((int) pEmr->nSize < minSize)return(0); + return(1); +} + +// Functions with the same form starting with U_EMRPOLYBEZIER_safe +int core1_safe(const char *record){ + if(!core5_safe(record, U_SIZE_EMRPOLYLINETO))return(0); + PU_EMRPOLYLINETO pEmr = (PU_EMRPOLYLINETO) (record); + int count=pEmr->cptl; + const char *blimit = record + pEmr->emr.nSize; + if(IS_MEM_UNSAFE(pEmr->aptl, count*sizeof(U_POINTL), blimit))return(0); + return(1); +} + +// Functions with the same form starting with U_EMRPOLYPOLYLINE_safe +int core2_safe(const char *record){ + if(!core5_safe(record, U_SIZE_EMRPOLYPOLYLINE))return(0); + PU_EMRPOLYPOLYLINE pEmr = (PU_EMRPOLYPOLYLINE) (record); + int count = pEmr->cptl; + int nPolys = pEmr->nPolys; + const char * blimit = record + pEmr->emr.nSize; + if(IS_MEM_UNSAFE(pEmr->aPolyCounts, nPolys*4, blimit))return(0); + record += sizeof(U_EMRPOLYPOLYLINE) - 4 + sizeof(uint32_t)* nPolys; + if(IS_MEM_UNSAFE(record, count*sizeof(U_POINTL), blimit))return(0); + return(1); +} + + +// Functions with the same form starting with U_EMRSETMAPMODE_safe +int core3_safe(const char *record){ + if(!core5_safe(record, U_SIZE_EMRSETMAPMODE))return(0); + return(1); +} + +// Functions taking a single U_RECT or U_RECTL, starting with U_EMRELLIPSE_safe, also U_EMRFILLPATH_safe, +int core4_safe(const char *record){ + if(!core5_safe(record, U_SIZE_EMRELLIPSE))return(0); + return(1); +} + +// Functions with the same form starting with U_EMRPOLYBEZIER16_safe +int core6_safe(const char *record){ + if(!core5_safe(record, U_SIZE_EMRPOLYBEZIER16))return(0); + PU_EMRPOLYBEZIER16 pEmr = (PU_EMRPOLYBEZIER16) (record); + int count=pEmr->cpts; + const char *blimit = record + pEmr->emr.nSize; + if(IS_MEM_UNSAFE(pEmr->apts, count*sizeof(U_POINT16), blimit))return(0); + return(1); +} + + +// Records with the same form starting with U_EMRSETWINDOWEXTEX_safe, that is, all with two uint32_t values after the emr +int core7_safe(const char *record){ + if(!core5_safe(record, U_SIZE_EMRSETWINDOWEXTEX))return(0); + return(1); +} + +// For U_EMREXTTEXTOUTA and U_EMREXTTEXTOUTW, type=0 for the first one +int core8_safe(const char *record){ + if(!core5_safe(record, U_SIZE_EMREXTTEXTOUTA))return(0); + PU_EMREXTTEXTOUTA pEmr = (PU_EMREXTTEXTOUTA) (record); + const char *blimit = record + pEmr->emr.nSize; + if(!emrtext_safe(&(pEmr->emrtext),record,blimit))return(0); + return(1); +} + +// Functions that take a rect and a pair of points, starting with U_EMRARC_safe +int core9_safe(const char *record){ + if(!core5_safe(record, U_SIZE_EMRARC))return(0); + return(1); +} + +// Functions with the same form starting with U_EMRPOLYPOLYLINE16_safe +int core10_safe(const char *record){ + if(!core5_safe(record, U_SIZE_EMRPOLYPOLYLINE16))return(0); + PU_EMRPOLYPOLYLINE16 pEmr = (PU_EMRPOLYPOLYLINE16) (record); + int count = pEmr->cpts; + int nPolys = pEmr->nPolys; + const char *blimit = record + pEmr->emr.nSize; + if(IS_MEM_UNSAFE(pEmr->aPolyCounts, nPolys*4, blimit))return(0); + record += sizeof(U_EMRPOLYPOLYLINE16) - 4 + sizeof(uint32_t)* nPolys; + if(IS_MEM_UNSAFE(record, count*sizeof(U_POINT16), blimit))return(0); + return(1); +} + +// Functions with the same form starting with U_EMRINVERTRGN_safe and U_EMRPAINTRGN_safe, +int core11_safe(const char *record){ + if(!core5_safe(record, U_SIZE_EMRINVERTRGN))return(0); + PU_EMRINVERTRGN pEmr = (PU_EMRINVERTRGN)(record); + int cbRgnData = pEmr->cbRgnData; + const char *blimit = record + pEmr->emr.nSize; + if(IS_MEM_UNSAFE(pEmr->RgnData, cbRgnData, blimit))return(0); + return(rgndata_safe(pEmr->RgnData, cbRgnData)); +} + + +// common code for U_EMRCREATEMONOBRUSH_safe and U_EMRCREATEDIBPATTERNBRUSHPT_safe, +int core12_safe(const char *record){ + if(!core5_safe(record, U_SIZE_EMRCREATEMONOBRUSH))return(0); + PU_EMRCREATEMONOBRUSH pEmr = (PU_EMRCREATEMONOBRUSH) (record); + const char *blimit = record + pEmr->emr.nSize; + U_OFFBMI offBmi = pEmr->offBmi; + U_CBBMI cbBmi = pEmr->cbBmi; + U_OFFBITS offBits = pEmr->offBits; + U_CBBITS cbBits = pEmr->cbBits; + uint32_t iUsage = pEmr->iUsage; + return(DIB_safe(record, iUsage, offBmi, cbBmi, offBits, cbBits, blimit)); +} + +// common code for U_EMRALPHABLEND_safe and U_EMRTRANSPARENTBLT_safe, +int core13_safe(const char *record){ + if(!core5_safe(record, U_SIZE_EMRALPHABLEND))return(0); + PU_EMRALPHABLEND pEmr = (PU_EMRALPHABLEND) (record); + const char *blimit = record + pEmr->emr.nSize; + U_OFFBMISRC offBmiSrc = pEmr->offBmiSrc; + U_CBBMISRC cbBmiSrc = pEmr->cbBmiSrc; + U_OFFBITSSRC offBitsSrc = pEmr->offBitsSrc; + U_CBBITS cbBitsSrc = pEmr->cbBitsSrc; + uint32_t iUsageSrc = pEmr->iUsageSrc; + return(DIB_safe(record, iUsageSrc, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc, blimit)); +} + +/* ********************************************************************************************** +These are the core EMR_safe functions, each converts a particular type of record. +All operate in place on the chunk of memory holding that record. +Some of these have offsets or counts which, if corrupt or evil would result in access outside + the record. These cases return a status value of 0 if that happens, 1 on success. Other + records which do not have these issues do not return a status value. +They are listed in order by the corresponding U_EMR_* index number. +*********************************************************************************************** */ + +/** + All of the record level (hidden) functions have this form: + \brief Convert a pointer to a U_EMR_whatever record which has not been implemented. + \param record pointer to a buffer holding the EMR record + \param torev 1 for native to reversed, 0 for reversed to native +*/ +int U_EMRNOTIMPLEMENTED_safe(const char *record){ + fprintf(stderr,"EMF WARNING: could not safety check record because that type has not been implemented!\n"); + return(core5_safe(record, sizeof(U_EMR))); +} + +// U_EMRHEADER 1 +int U_EMRHEADER_safe(const char *record){ + // use _MIN form so that it accepts very old EMF files + return(core5_safe(record, U_SIZE_EMRHEADER_MIN)); +} + +// U_EMRPOLYBEZIER 2 +int U_EMRPOLYBEZIER_safe(const char *record){ + return(core1_safe(record)); +} + +// U_EMRPOLYGON 3 +int U_EMRPOLYGON_safe(const char *record){ + return(core1_safe(record)); +} + +// U_EMRPOLYLINE 4 +int U_EMRPOLYLINE_safe(const char *record){ + return(core1_safe(record)); +} + +// U_EMRPOLYBEZIERTO 5 +int U_EMRPOLYBEZIERTO_safe(const char *record){ + return(core1_safe(record)); +} + +// U_EMRPOLYLINETO 6 +int U_EMRPOLYLINETO_safe(const char *record){ + return(core1_safe(record)); +} + +// U_EMRPOLYPOLYLINE 7 +int U_EMRPOLYPOLYLINE_safe(const char *record){ + return(core2_safe(record)); +} + +// U_EMRPOLYPOLYGON 8 +int U_EMRPOLYPOLYGON_safe(const char *record){ + return(core2_safe(record)); +} + +// U_EMRSETWINDOWEXTEX 9 +int U_EMRSETWINDOWEXTEX_safe(const char *record){ + return(core7_safe(record)); +} + +// U_EMRSETWINDOWORGEX 10 +int U_EMRSETWINDOWORGEX_safe(const char *record){ + return(core7_safe(record)); +} + +// U_EMRSETVIEWPORTEXTEX 11 +int U_EMRSETVIEWPORTEXTEX_safe(const char *record){ + return(core7_safe(record)); +} + +// U_EMRSETVIEWPORTORGEX 12 +int U_EMRSETVIEWPORTORGEX_safe(const char *record){ + return(core7_safe(record)); +} + +// U_EMRSETBRUSHORGEX 13 +int U_EMRSETBRUSHORGEX_safe(const char *record){ + return(core7_safe(record)); +} + +// U_EMREOF 14 +int U_EMREOF_safe(const char *record){ + if(!core5_safe(record, U_SIZE_EMREOF))return(0); + PU_EMREOF pEmr = (PU_EMREOF)(record); + const char *blimit = record + pEmr->emr.nSize; + int cbPalEntries=pEmr->cbPalEntries; + if(cbPalEntries){ + if(IS_MEM_UNSAFE(record, pEmr->offPalEntries + 2*2, blimit))return(0);// 2 16 bit values in U_LOGPALLETE + } + int off = sizeof(U_EMREOF) + 4 * cbPalEntries; + if(IS_MEM_UNSAFE(record, off + 4, blimit))return(0); + return(1); +} + + +// U_EMRSETPIXELV 15 +int U_EMRSETPIXELV_safe(const char *record){ + return(core5_safe(record, U_SIZE_EMRSETPIXELV)); + +} + + +// U_EMRSETMAPPERFLAGS 16 +int U_EMRSETMAPPERFLAGS_safe(const char *record){ + return(core5_safe(record, U_SIZE_EMRSETMAPPERFLAGS)); +} + + +// U_EMRSETMAPMODE 17 +int U_EMRSETMAPMODE_safe(const char *record){ + return(core3_safe(record)); +} + +// U_EMRSETBKMODE 18 +int U_EMRSETBKMODE_safe(const char *record){ + return(core3_safe(record)); +} + +// U_EMRSETPOLYFILLMODE 19 +int U_EMRSETPOLYFILLMODE_safe(const char *record){ + return(core3_safe(record)); +} + +// U_EMRSETROP2 20 +int U_EMRSETROP2_safe(const char *record){ + return(core3_safe(record)); +} + +// U_EMRSETSTRETCHBLTMODE 21 +int U_EMRSETSTRETCHBLTMODE_safe(const char *record){ + return(core3_safe(record)); +} + +// U_EMRSETTEXTALIGN 22 +int U_EMRSETTEXTALIGN_safe(const char *record){ + return(core3_safe(record)); +} + +// U_EMRSETCOLORADJUSTMENT 23 +int U_EMRSETCOLORADJUSTMENT_safe(const char *record){ + return(core5_safe(record, U_SIZE_EMRSETCOLORADJUSTMENT)); +} + +// U_EMRSETTEXTCOLOR 24 +int U_EMRSETTEXTCOLOR_safe(const char *record){ + return(core5_safe(record, U_SIZE_EMRSETTEXTCOLOR)); +} + +// U_EMRSETBKCOLOR 25 +int U_EMRSETBKCOLOR_safe(const char *record){ + return(core5_safe(record, U_SIZE_EMRSETBKCOLOR)); +} + +// U_EMROFFSETCLIPRGN 26 +int U_EMROFFSETCLIPRGN_safe(const char *record){ + return(core7_safe(record)); +} + +// U_EMRMOVETOEX 27 +int U_EMRMOVETOEX_safe(const char *record){ + return(core7_safe(record)); +} + +// U_EMRSETMETARGN 28 +int U_EMRSETMETARGN_safe(const char *record){ + return(core5_safe(record, U_SIZE_EMRSETMETARGN)); +} + +// U_EMREXCLUDECLIPRECT 29 +int U_EMREXCLUDECLIPRECT_safe(const char *record){ + return(core4_safe(record)); +} + +// U_EMRINTERSECTCLIPRECT 30 +int U_EMRINTERSECTCLIPRECT_safe(const char *record){ + return(core4_safe(record)); +} + +// U_EMRSCALEVIEWPORTEXTEX 31 +int U_EMRSCALEVIEWPORTEXTEX_safe(const char *record){ + return(core4_safe(record)); +} + +// U_EMRSCALEWINDOWEXTEX 32 +int U_EMRSCALEWINDOWEXTEX_safe(const char *record){ + return(core4_safe(record)); +} + +// U_EMRSAVEDC 33 +int U_EMRSAVEDC_safe(const char *record){ + return(core5_safe(record, U_SIZE_EMRSAVEDC)); +} + +// U_EMRRESTOREDC 34 +int U_EMRRESTOREDC_safe(const char *record){ + return(core3_safe(record)); +} + +// U_EMRSETWORLDTRANSFORM 35 +int U_EMRSETWORLDTRANSFORM_safe(const char *record){ + return(core5_safe(record, U_SIZE_EMRSETWORLDTRANSFORM)); +} + +// U_EMRMODIFYWORLDTRANSFORM 36 +int U_EMRMODIFYWORLDTRANSFORM_safe(const char *record){ + return(core5_safe(record, U_SIZE_EMRMODIFYWORLDTRANSFORM)); +} + +// U_EMRSELECTOBJECT 37 +int U_EMRSELECTOBJECT_safe(const char *record){ + return(core5_safe(record, U_SIZE_EMRSELECTOBJECT)); +} + +// U_EMRCREATEPEN 38 +int U_EMRCREATEPEN_safe(const char *record){ + return(core5_safe(record, U_SIZE_EMRCREATEPEN)); +} + +// U_EMRCREATEBRUSHINDIRECT 39 +int U_EMRCREATEBRUSHINDIRECT_safe(const char *record){ + return(core5_safe(record, U_SIZE_EMRCREATEBRUSHINDIRECT)); +} + +// U_EMRDELETEOBJECT 40 +int U_EMRDELETEOBJECT_safe(const char *record){ + return(core5_safe(record, U_SIZE_EMRDELETEOBJECT)); + +} + +// U_EMRANGLEARC 41 +int U_EMRANGLEARC_safe(const char *record){ + return(core5_safe(record, U_SIZE_EMRANGLEARC)); +} + +// U_EMRELLIPSE 42 +int U_EMRELLIPSE_safe(const char *record){ + return(core4_safe(record)); +} + +// U_EMRRECTANGLE 43 +int U_EMRRECTANGLE_safe(const char *record){ + return(core4_safe(record)); +} + +// U_EMRROUNDRECT 44 +int U_EMRROUNDRECT_safe(const char *record){ + return(core5_safe(record, U_SIZE_EMRROUNDRECT)); +} + +// U_EMRARC 45 +int U_EMRARC_safe(const char *record){ + return(core9_safe(record)); +} + +// U_EMRCHORD 46 +int U_EMRCHORD_safe(const char *record){ + return(core9_safe(record)); +} + +// U_EMRPIE 47 +int U_EMRPIE_safe(const char *record){ + return(core9_safe(record)); +} + +// U_EMRSELECTPALETTE 48 +int U_EMRSELECTPALETTE_safe(const char *record){ + return(core3_safe(record)); +} + +// U_EMRCREATEPALETTE 49 +int U_EMRCREATEPALETTE_safe(const char *record){ + return(core5_safe(record, U_SIZE_EMRCREATEPALETTE)); +} + +// U_EMRSETPALETTEENTRIES 50 +int U_EMRSETPALETTEENTRIES_safe(const char *record){ + return(core5_safe(record, U_SIZE_EMRSETPALETTEENTRIES)); +} + +// U_EMRRESIZEPALETTE 51 +int U_EMRRESIZEPALETTE_safe(const char *record){ + return(core7_safe(record)); +} + +// U_EMRREALIZEPALETTE 52 +int U_EMRREALIZEPALETTE_safe(const char *record){ + return(core5_safe(record, U_SIZE_EMRREALIZEPALETTE)); +} + +// U_EMREXTFLOODFILL 53 +int U_EMREXTFLOODFILL_safe(const char *record){ + return(core5_safe(record, U_SIZE_EMREXTFLOODFILL)); +} + +// U_EMRLINETO 54 +int U_EMRLINETO_safe(const char *record){ + return(core7_safe(record)); +} + +// U_EMRARCTO 55 +int U_EMRARCTO_safe(const char *record){ + return(core9_safe(record)); +} + +// U_EMRPOLYDRAW 56 +int U_EMRPOLYDRAW_safe(const char *record){ + if(!core5_safe(record, U_SIZE_EMRPOLYDRAW))return(0); + PU_EMRPOLYDRAW pEmr = (PU_EMRPOLYDRAW)(record); + int count = pEmr->cptl; + const char *blimit = record + pEmr->emr.nSize; + if(IS_MEM_UNSAFE(pEmr->aptl, count*sizeof(U_POINTL), blimit))return(0); + return(1); +} + +// U_EMRSETARCDIRECTION 57 +int U_EMRSETARCDIRECTION_safe(const char *record){ + return(core3_safe(record)); +} + +// U_EMRSETMITERLIMIT 58 +int U_EMRSETMITERLIMIT_safe(const char *record){ + return(core3_safe(record)); +} + + +// U_EMRBEGINPATH 59 +int U_EMRBEGINPATH_safe(const char *record){ + return(core5_safe(record, U_SIZE_EMRBEGINPATH)); +} + +// U_EMRENDPATH 60 +int U_EMRENDPATH_safe(const char *record){ + return(core5_safe(record, U_SIZE_EMRENDPATH)); +} + +// U_EMRCLOSEFIGURE 61 +int U_EMRCLOSEFIGURE_safe(const char *record){ + return(core5_safe(record, U_SIZE_EMRCLOSEFIGURE)); +} + +// U_EMRFILLPATH 62 +int U_EMRFILLPATH_safe(const char *record){ + return(core4_safe(record)); +} + +// U_EMRSTROKEANDFILLPATH 63 +int U_EMRSTROKEANDFILLPATH_safe(const char *record){ + return(core4_safe(record)); +} + +// U_EMRSTROKEPATH 64 +int U_EMRSTROKEPATH_safe(const char *record){ + return(core4_safe(record)); +} + +// U_EMRFLATTENPATH 65 +int U_EMRFLATTENPATH_safe(const char *record){ + return(core5_safe(record, U_SIZE_EMRFLATTENPATH)); +} + +// U_EMRWIDENPATH 66 +int U_EMRWIDENPATH_safe(const char *record){ + return(core5_safe(record, U_SIZE_EMRWIDENPATH)); +} + +// U_EMRSELECTCLIPPATH 67 +int U_EMRSELECTCLIPPATH_safe(const char *record){ + return(core3_safe(record)); +} + +// U_EMRABORTPATH 68 +int U_EMRABORTPATH_safe(const char *record){ + return(core5_safe(record, U_SIZE_EMRABORTPATH)); +} + +// U_EMRUNDEF69 69 +#define U_EMRUNDEF69_safe(A) U_EMRNOTIMPLEMENTED_safe(A) //!< Not implemented. + +// U_EMRCOMMENT 70 Comment (any binary data, interpretation is program specific) +int U_EMRCOMMENT_safe(const char *record){ + if(!core5_safe(record, U_SIZE_EMRCOMMENT))return(0); + PU_EMRCOMMENT pEmr = (PU_EMRCOMMENT)(record); + int cbData = pEmr->cbData; + const char *blimit =record + pEmr->emr.nSize; + if(IS_MEM_UNSAFE(record, cbData + sizeof(U_SIZE_EMRCOMMENT), blimit))return(0); + return(1); +} + +// U_EMRFILLRGN 71 +int U_EMRFILLRGN_safe(const char *record){ + if(!core5_safe(record, U_SIZE_EMRFILLRGN))return(0); + PU_EMRFILLRGN pEmr = (PU_EMRFILLRGN)(record); + int cbRgnData = pEmr->cbRgnData; + const char *blimit = record + pEmr->emr.nSize; + if(IS_MEM_UNSAFE(pEmr->RgnData, cbRgnData, blimit))return(0); + return(rgndata_safe(pEmr->RgnData, cbRgnData)); +} + +// U_EMRFRAMERGN 72 +int U_EMRFRAMERGN_safe(const char *record){ + if(!core5_safe(record, U_SIZE_EMRFRAMERGN))return(0); + PU_EMRFRAMERGN pEmr = (PU_EMRFRAMERGN)(record); + int cbRgnData = pEmr->cbRgnData; + const char *blimit = record + pEmr->emr.nSize; + if(IS_MEM_UNSAFE(pEmr->RgnData, cbRgnData, blimit))return(0); + return(rgndata_safe(pEmr->RgnData, cbRgnData)); +} + +// U_EMRINVERTRGN 73 +int U_EMRINVERTRGN_safe(const char *record){ + return(core11_safe(record)); +} + +// U_EMRPAINTRGN 74 +int U_EMRPAINTRGN_safe(const char *record){ + return(core11_safe(record)); +} + +// U_EMREXTSELECTCLIPRGN 75 +int U_EMREXTSELECTCLIPRGN_safe(const char *record){ + if(!core5_safe(record, U_SIZE_EMREXTSELECTCLIPRGN))return(0); + PU_EMREXTSELECTCLIPRGN pEmr = (PU_EMREXTSELECTCLIPRGN)(record); + int cbRgnData = pEmr->cbRgnData; + /* data size can be 0 with COPY mode, it means clear the clip region. */ + if(pEmr->iMode == U_RGN_COPY && !cbRgnData)return(1); + const char *blimit = record + pEmr->emr.nSize; + if(IS_MEM_UNSAFE(pEmr->RgnData, cbRgnData, blimit))return(0); + return(rgndata_safe(pEmr->RgnData, cbRgnData)); +} + +// U_EMRBITBLT 76 +int U_EMRBITBLT_safe(const char *record){ + if(!core5_safe(record, U_SIZE_EMRBITBLT))return(0); + PU_EMRBITBLT pEmr = (PU_EMRBITBLT) (record); + const char *blimit = record + pEmr->emr.nSize; + U_OFFBMISRC offBmiSrc = pEmr->offBmiSrc; + U_CBBMISRC cbBmiSrc = pEmr->cbBmiSrc; + U_OFFBITSSRC offBitsSrc = pEmr->offBitsSrc; + U_CBBITS cbBitsSrc = pEmr->cbBitsSrc; + uint32_t iUsageSrc = pEmr->iUsageSrc; + return(DIB_safe(record, iUsageSrc, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc, blimit)); +} + +// U_EMRSTRETCHBLT 77 +int U_EMRSTRETCHBLT_safe(const char *record){ + if(!core5_safe(record, U_SIZE_EMRSTRETCHBLT))return(0); + PU_EMRBITBLT pEmr = (PU_EMRBITBLT) (record); + const char *blimit = record + pEmr->emr.nSize; + U_OFFBMISRC offBmiSrc = pEmr->offBmiSrc; + U_CBBMISRC cbBmiSrc = pEmr->cbBmiSrc; + U_OFFBITSSRC offBitsSrc = pEmr->offBitsSrc; + U_CBBITS cbBitsSrc = pEmr->cbBitsSrc; + uint32_t iUsageSrc = pEmr->iUsageSrc; + return(DIB_safe(record, iUsageSrc, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc, blimit)); +} + +// U_EMRMASKBLT 78 +int U_EMRMASKBLT_safe(const char *record){ + if(!core5_safe(record, U_SIZE_EMRMASKBLT))return(0); + PU_EMRMASKBLT pEmr = (PU_EMRMASKBLT) (record); + const char *blimit = record + pEmr->emr.nSize; + U_OFFBMISRC offBmiSrc = pEmr->offBmiSrc; + U_CBBMISRC cbBmiSrc = pEmr->cbBmiSrc; + U_OFFBMIMSK offBmiMask = pEmr->offBmiMask; + U_CBBMIMSK cbBmiMask = pEmr->cbBmiMask; + U_OFFBITSSRC offBitsSrc = pEmr->offBitsSrc; + U_CBBITSSRC cbBitsSrc = pEmr->cbBitsSrc; + U_OFFBITSMSK offBitsMask = pEmr->offBitsMask; + U_CBBITSMSK cbBitsMask = pEmr->cbBitsMask; + uint32_t iUsageSrc = pEmr->iUsageSrc; + uint32_t iUsageMask = pEmr->iUsageMask; + if(!DIB_safe(record, iUsageSrc, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc, blimit))return(0); + return(DIB_safe(record, iUsageMask, offBmiMask, cbBmiMask, offBitsMask, cbBitsMask, blimit)); +} + +// U_EMRPLGBLT 79 +int U_EMRPLGBLT_safe(const char *record){ + if(!core5_safe(record, U_SIZE_EMRPLGBLT))return(0); + PU_EMRPLGBLT pEmr = (PU_EMRPLGBLT) (record); + const char *blimit = record + pEmr->emr.nSize; + U_OFFBMISRC offBmiSrc = pEmr->offBmiSrc; + U_CBBMISRC cbBmiSrc = pEmr->cbBmiSrc; + U_OFFBMIMSK offBmiMask = pEmr->offBmiMask; + U_CBBMIMSK cbBmiMask = pEmr->cbBmiMask; + U_OFFBITSSRC offBitsSrc = pEmr->offBitsSrc; + U_CBBITSSRC cbBitsSrc = pEmr->cbBitsSrc; + U_OFFBITSMSK offBitsMask = pEmr->offBitsMask; + U_CBBITSMSK cbBitsMask = pEmr->cbBitsMask; + uint32_t iUsageSrc = pEmr->iUsageSrc; + uint32_t iUsageMask = pEmr->iUsageMask; + if(!DIB_safe(record, iUsageSrc, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc, blimit))return(0); + return(DIB_safe(record, iUsageMask, offBmiMask, cbBmiMask, offBitsMask, cbBitsMask, blimit)); +} + +// U_EMRSETDIBITSTODEVICE 80 +int U_EMRSETDIBITSTODEVICE_safe(const char *record){ + if(!core5_safe(record, U_SIZE_EMRSETDIBITSTODEVICE))return(0); + PU_EMRSETDIBITSTODEVICE pEmr = (PU_EMRSETDIBITSTODEVICE) (record); + const char *blimit = record + pEmr->emr.nSize; + U_OFFBMISRC offBmiSrc = pEmr->offBmiSrc; + U_CBBMISRC cbBmiSrc = pEmr->cbBmiSrc; + U_OFFBITSSRC offBitsSrc = pEmr->offBitsSrc; + U_CBBITSSRC cbBitsSrc = pEmr->cbBitsSrc; + uint32_t iUsageSrc = pEmr->iUsageSrc; + return(DIB_safe(record, iUsageSrc, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc, blimit)); +} + +// U_EMRSTRETCHDIBITS 81 +int U_EMRSTRETCHDIBITS_safe(const char *record){ + if(!core5_safe(record, U_SIZE_EMRSTRETCHDIBITS))return(0); + PU_EMRSTRETCHDIBITS pEmr = (PU_EMRSTRETCHDIBITS) (record); + const char *blimit = record + pEmr->emr.nSize; + U_OFFBMISRC offBmiSrc = pEmr->offBmiSrc; + U_CBBMISRC cbBmiSrc = pEmr->cbBmiSrc; + U_OFFBITSSRC offBitsSrc = pEmr->offBitsSrc; + U_CBBITSSRC cbBitsSrc = pEmr->cbBitsSrc; + uint32_t iUsageSrc = pEmr->iUsageSrc; + return(DIB_safe(record, iUsageSrc, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc, blimit)); +} + +// U_EMREXTCREATEFONTINDIRECTW 82 +int U_EMREXTCREATEFONTINDIRECTW_safe(const char *record){ + /* Panose or logfont, LogFontExDv is not supported. Test smallest to largest */ + if(core5_safe(record, U_SIZE_EMREXTCREATEFONTINDIRECTW_LOGFONT))return(1); + return(core5_safe(record, U_SIZE_EMREXTCREATEFONTINDIRECTW_LOGFONT_PANOSE)); +} + +// U_EMREXTTEXTOUTA 83 +int U_EMREXTTEXTOUTA_safe(const char *record){ + return(core8_safe(record)); +} + +// U_EMREXTTEXTOUTW 84 +int U_EMREXTTEXTOUTW_safe(const char *record){ + return(core8_safe(record)); +} + +// U_EMRPOLYBEZIER16 85 +/** + \brief Convert a pointer to a U_EMR_POLYBEZIER16 record. + \param record pointer to a buffer holding the EMR record +*/ +int U_EMRPOLYBEZIER16_safe(const char *record){ + return(core6_safe(record)); +} + +// U_EMRPOLYGON16 86 +int U_EMRPOLYGON16_safe(const char *record){ + return(core6_safe(record)); +} + +// U_EMRPOLYLINE16 87 +int U_EMRPOLYLINE16_safe(const char *record){ + return(core6_safe(record)); +} + +// U_EMRPOLYBEZIERTO16 88 +int U_EMRPOLYBEZIERTO16_safe(const char *record){ + return(core6_safe(record)); +} + +// U_EMRPOLYLINETO16 89 +/** + \brief Convert a pointer to a U_EMR_POLYLINETO16 record. + \param record pointer to a buffer holding the EMR record +*/ +int U_EMRPOLYLINETO16_safe(const char *record){ + return(core6_safe(record)); +} + +// U_EMRPOLYPOLYLINE16 90 +int U_EMRPOLYPOLYLINE16_safe(const char *record){ + return(core10_safe(record)); +} + +// U_EMRPOLYPOLYGON16 91 +int U_EMRPOLYPOLYGON16_safe(const char *record){ + return(core10_safe(record)); +} + + +// U_EMRPOLYDRAW16 92 +int U_EMRPOLYDRAW16_safe(const char *record){ + if(!core5_safe(record, U_SIZE_EMRPOLYDRAW16))return(0); + PU_EMRPOLYDRAW16 pEmr = (PU_EMRPOLYDRAW16)(record); + int count = pEmr->cpts; + const char *blimit = record + pEmr->emr.nSize; + if(IS_MEM_UNSAFE(pEmr->apts, count*sizeof(U_POINT16), blimit))return(0); + return(1); +} + +// U_EMRCREATEMONOBRUSH 93 +int U_EMRCREATEMONOBRUSH_safe(const char *record){ + return(core12_safe(record)); +} + +// U_EMRCREATEDIBPATTERNBRUSHPT_safe 94 +int U_EMRCREATEDIBPATTERNBRUSHPT_safe(const char *record){ + return(core12_safe(record)); +} + + +// U_EMREXTCREATEPEN 95 +int U_EMREXTCREATEPEN_safe(const char *record){ + if(!core5_safe(record, U_SIZE_EMREXTCREATEPEN))return(0); + PU_EMREXTCREATEPEN pEmr = (PU_EMREXTCREATEPEN)(record); + const char *blimit = record + pEmr->emr.nSize; + U_OFFBMI offBmi = pEmr->offBmi; + U_CBBMI cbBmi = pEmr->cbBmi; + U_OFFBITS offBits = pEmr->offBits; + U_CBBITS cbBits = pEmr->cbBits; + if(!DIB_safe(record, U_DIB_RGB_COLORS, offBmi, cbBmi, offBits, cbBits, blimit))return(0); + return(extlogpen_safe((PU_EXTLOGPEN) &(pEmr->elp), blimit)); +} + +// U_EMRPOLYTEXTOUTA 96 NOT IMPLEMENTED, denigrated after Windows NT +#define U_EMRPOLYTEXTOUTA_safe(A) U_EMRNOTIMPLEMENTED_safe(A) //!< Not implemented. +// U_EMRPOLYTEXTOUTW 97 NOT IMPLEMENTED, denigrated after Windows NT +#define U_EMRPOLYTEXTOUTW_safe(A) U_EMRNOTIMPLEMENTED_safe(A) //!< Not implemented. + +// U_EMRSETICMMODE 98 +int U_EMRSETICMMODE_safe(const char *record){ + return(core3_safe(record)); +} + +// U_EMRCREATECOLORSPACE 99 +int U_EMRCREATECOLORSPACE_safe(const char *record){ + return(core5_safe(record, U_SIZE_EMRCREATECOLORSPACE)); +} + +// U_EMRSETCOLORSPACE 100 +int U_EMRSETCOLORSPACE_safe(const char *record){ + return(core3_safe(record)); +} + +// U_EMRDELETECOLORSPACE 101 +int U_EMRDELETECOLORSPACE_safe(const char *record){ + return(core3_safe(record)); +} + +// U_EMRGLSRECORD 102 Not implemented +#define U_EMRGLSRECORD_safe(A) U_EMRNOTIMPLEMENTED_safe(A) //!< Not implemented. +// U_EMRGLSBOUNDEDRECORD 103 Not implemented +#define U_EMRGLSBOUNDEDRECORD_safe(A) U_EMRNOTIMPLEMENTED_safe(A) //!< Not implemented. + +// U_EMRPIXELFORMAT 104 +int U_EMRPIXELFORMAT_safe(const char *record){ + return(core5_safe(record, U_SIZE_EMRPIXELFORMAT)); +} + +// U_EMRDRAWESCAPE 105 Not implemented +#define U_EMRDRAWESCAPE_safe(A) U_EMRNOTIMPLEMENTED_safe(A) //!< Not implemented. +// U_EMREXTESCAPE 106 Not implemented +#define U_EMREXTESCAPE_safe(A) U_EMRNOTIMPLEMENTED_safe(A) //!< Not implemented. +// U_EMRUNDEF107 107 Not implemented +#define U_EMRUNDEF107_safe(A) U_EMRNOTIMPLEMENTED_safe(A) //!< Not implemented. + +// U_EMRSMALLTEXTOUT 108 +int U_EMRSMALLTEXTOUT_safe(const char *record){ + if(!core5_safe(record, U_SIZE_EMRSMALLTEXTOUT))return(0); + PU_EMRSMALLTEXTOUT pEmr = (PU_EMRSMALLTEXTOUT)(record); + int roff=sizeof(U_EMRSMALLTEXTOUT); // offset to the start of the variable fields + int fuOptions = pEmr->fuOptions; + int cChars = pEmr->cChars; + const char *blimit = record + pEmr->emr.nSize; + if(!(fuOptions & U_ETO_NO_RECT)){ + if(IS_MEM_UNSAFE(record, roff + sizeof(U_RECTL), blimit))return(0); + } + if(IS_MEM_UNSAFE(record, roff + sizeof(U_RECTL) + cChars, blimit))return(0); + return(1); +} + +// U_EMRFORCEUFIMAPPING 109 Not implemented +#define U_EMRFORCEUFIMAPPING_safe(A) U_EMRNOTIMPLEMENTED_safe(A) //!< Not implemented. +// U_EMRNAMEDESCAPE 110 Not implemented +#define U_EMRNAMEDESCAPE_safe(A) U_EMRNOTIMPLEMENTED_safe(A) //!< Not implemented. +// U_EMRCOLORCORRECTPALETTE 111 Not implemented +#define U_EMRCOLORCORRECTPALETTE_safe(A) U_EMRNOTIMPLEMENTED_safe(A) //!< Not implemented. +// U_EMRSETICMPROFILEA 112 Not implemented +#define U_EMRSETICMPROFILEA_safe(A) U_EMRNOTIMPLEMENTED_safe(A) //!< Not implemented. +// U_EMRSETICMPROFILEW 113 Not implemented +#define U_EMRSETICMPROFILEW_safe(A) U_EMRNOTIMPLEMENTED_safe(A) //!< Not implemented. + +// U_EMRALPHABLEND 114 +int U_EMRALPHABLEND_safe(const char *record){ + return(core13_safe(record)); +} + +// U_EMRSETLAYOUT 115 +int U_EMRSETLAYOUT_safe(const char *record){ + return(core3_safe(record)); +} + +// U_EMRTRANSPARENTBLT 116 +int U_EMRTRANSPARENTBLT_safe(const char *record){ + return(core13_safe(record)); +} + + +// U_EMRUNDEF117 117 Not implemented +#define U_EMRUNDEF117_safe(A) U_EMRNOTIMPLEMENTED_safe(A) //!< Not implemented. +// U_EMRGRADIENTFILL 118 +int U_EMRGRADIENTFILL_safe(const char *record){ + if(!core5_safe(record, U_SIZE_EMRGRADIENTFILL))return(0); + PU_EMRGRADIENTFILL pEmr = (PU_EMRGRADIENTFILL)(record); + int nTriVert = pEmr->nTriVert; + int nGradObj = pEmr->nGradObj; + int ulMode = pEmr->ulMode; + const char *blimit = record + pEmr->emr.nSize; + if(IS_MEM_UNSAFE(record, nTriVert*sizeof(U_TRIVERTEX), blimit))return(0); + record += nTriVert * sizeof(U_TRIVERTEX); + if(nGradObj){ + if( ulMode == U_GRADIENT_FILL_TRIANGLE){ + if(IS_MEM_UNSAFE(record, nGradObj*sizeof(U_GRADIENT3), blimit))return(0); + } + else if(ulMode == U_GRADIENT_FILL_RECT_H || ulMode == U_GRADIENT_FILL_RECT_V){ + if(IS_MEM_UNSAFE(record, nGradObj*sizeof(U_GRADIENT4), blimit))return(0); + } + } + return(1); +} + +// U_EMRSETLINKEDUFIS 119 Not implemented +#define U_EMRSETLINKEDUFIS_safe(A) U_EMRNOTIMPLEMENTED_safe(A) //!< Not implemented. +// U_EMRSETTEXTJUSTIFICATION120 Not implemented (denigrated) +#define U_EMRSETTEXTJUSTIFICATION_safe(A) U_EMRNOTIMPLEMENTED_safe(A) //!< Not implemented. +// U_EMRCOLORMATCHTOTARGETW 121 Not implemented +#define U_EMRCOLORMATCHTOTARGETW_safe(A) U_EMRNOTIMPLEMENTED_safe(A) //!< Not implemented. + +// U_EMRCREATECOLORSPACEW 122 +int U_EMRCREATECOLORSPACEW_safe(const char *record){ + return(core5_safe(record, U_SIZE_EMRCREATECOLORSPACEW)); +} + +//! \endcond + +/** + \brief Test an EMF record in memory from Big Endian to Little Endian. + \return 0 on failure, 1 on success + \param record pointer to the EMF record in memory + + Normally this would be called immediately after reading a record from a file + and having called U_emf_record_sizeok(). + It is NOT safe to call this routine without first calling U_emf_record_sizeok)()! + If the file has been converted from one endian to another calling this routine is + not necessary, because those routines also perform these checks. +*/ +int U_emf_record_safe(const char *record){ + int rstatus=1; + + if(!record)return(0); // programming error + + switch (U_EMRTYPE(record)) + { + case U_EMR_HEADER: rstatus=U_EMRHEADER_safe(record); break; + case U_EMR_POLYBEZIER: rstatus=U_EMRPOLYBEZIER_safe(record); break; + case U_EMR_POLYGON: rstatus=U_EMRPOLYGON_safe(record); break; + case U_EMR_POLYLINE: rstatus=U_EMRPOLYLINE_safe(record); break; + case U_EMR_POLYBEZIERTO: rstatus=U_EMRPOLYBEZIERTO_safe(record); break; + case U_EMR_POLYLINETO: rstatus=U_EMRPOLYLINETO_safe(record); break; + case U_EMR_POLYPOLYLINE: rstatus=U_EMRPOLYPOLYLINE_safe(record); break; + case U_EMR_POLYPOLYGON: rstatus=U_EMRPOLYPOLYGON_safe(record); break; + case U_EMR_SETWINDOWEXTEX: rstatus=U_EMRSETWINDOWEXTEX_safe(record); break; + case U_EMR_SETWINDOWORGEX: rstatus=U_EMRSETWINDOWORGEX_safe(record); break; + case U_EMR_SETVIEWPORTEXTEX: rstatus=U_EMRSETVIEWPORTEXTEX_safe(record); break; + case U_EMR_SETVIEWPORTORGEX: rstatus=U_EMRSETVIEWPORTORGEX_safe(record); break; + case U_EMR_SETBRUSHORGEX: rstatus=U_EMRSETBRUSHORGEX_safe(record); break; + case U_EMR_EOF: rstatus=U_EMREOF_safe(record); break; + case U_EMR_SETPIXELV: rstatus=U_EMRSETPIXELV_safe(record); break; + case U_EMR_SETMAPPERFLAGS: rstatus=U_EMRSETMAPPERFLAGS_safe(record); break; + case U_EMR_SETMAPMODE: rstatus=U_EMRSETMAPMODE_safe(record); break; + case U_EMR_SETBKMODE: rstatus=U_EMRSETBKMODE_safe(record); break; + case U_EMR_SETPOLYFILLMODE: rstatus=U_EMRSETPOLYFILLMODE_safe(record); break; + case U_EMR_SETROP2: rstatus=U_EMRSETROP2_safe(record); break; + case U_EMR_SETSTRETCHBLTMODE: rstatus=U_EMRSETSTRETCHBLTMODE_safe(record); break; + case U_EMR_SETTEXTALIGN: rstatus=U_EMRSETTEXTALIGN_safe(record); break; + case U_EMR_SETCOLORADJUSTMENT: rstatus=U_EMRSETCOLORADJUSTMENT_safe(record); break; + case U_EMR_SETTEXTCOLOR: rstatus=U_EMRSETTEXTCOLOR_safe(record); break; + case U_EMR_SETBKCOLOR: rstatus=U_EMRSETBKCOLOR_safe(record); break; + case U_EMR_OFFSETCLIPRGN: rstatus=U_EMROFFSETCLIPRGN_safe(record); break; + case U_EMR_MOVETOEX: rstatus=U_EMRMOVETOEX_safe(record); break; + case U_EMR_SETMETARGN: rstatus=U_EMRSETMETARGN_safe(record); break; + case U_EMR_EXCLUDECLIPRECT: rstatus=U_EMREXCLUDECLIPRECT_safe(record); break; + case U_EMR_INTERSECTCLIPRECT: rstatus=U_EMRINTERSECTCLIPRECT_safe(record); break; + case U_EMR_SCALEVIEWPORTEXTEX: rstatus=U_EMRSCALEVIEWPORTEXTEX_safe(record); break; + case U_EMR_SCALEWINDOWEXTEX: rstatus=U_EMRSCALEWINDOWEXTEX_safe(record); break; + case U_EMR_SAVEDC: rstatus=U_EMRSAVEDC_safe(record); break; + case U_EMR_RESTOREDC: rstatus=U_EMRRESTOREDC_safe(record); break; + case U_EMR_SETWORLDTRANSFORM: rstatus=U_EMRSETWORLDTRANSFORM_safe(record); break; + case U_EMR_MODIFYWORLDTRANSFORM: rstatus=U_EMRMODIFYWORLDTRANSFORM_safe(record); break; + case U_EMR_SELECTOBJECT: rstatus=U_EMRSELECTOBJECT_safe(record); break; + case U_EMR_CREATEPEN: rstatus=U_EMRCREATEPEN_safe(record); break; + case U_EMR_CREATEBRUSHINDIRECT: rstatus=U_EMRCREATEBRUSHINDIRECT_safe(record); break; + case U_EMR_DELETEOBJECT: rstatus=U_EMRDELETEOBJECT_safe(record); break; + case U_EMR_ANGLEARC: rstatus=U_EMRANGLEARC_safe(record); break; + case U_EMR_ELLIPSE: rstatus=U_EMRELLIPSE_safe(record); break; + case U_EMR_RECTANGLE: rstatus=U_EMRRECTANGLE_safe(record); break; + case U_EMR_ROUNDRECT: rstatus=U_EMRROUNDRECT_safe(record); break; + case U_EMR_ARC: rstatus=U_EMRARC_safe(record); break; + case U_EMR_CHORD: rstatus=U_EMRCHORD_safe(record); break; + case U_EMR_PIE: rstatus=U_EMRPIE_safe(record); break; + case U_EMR_SELECTPALETTE: rstatus=U_EMRSELECTPALETTE_safe(record); break; + case U_EMR_CREATEPALETTE: rstatus=U_EMRCREATEPALETTE_safe(record); break; + case U_EMR_SETPALETTEENTRIES: rstatus=U_EMRSETPALETTEENTRIES_safe(record); break; + case U_EMR_RESIZEPALETTE: rstatus=U_EMRRESIZEPALETTE_safe(record); break; + case U_EMR_REALIZEPALETTE: rstatus=U_EMRREALIZEPALETTE_safe(record); break; + case U_EMR_EXTFLOODFILL: rstatus=U_EMREXTFLOODFILL_safe(record); break; + case U_EMR_LINETO: rstatus=U_EMRLINETO_safe(record); break; + case U_EMR_ARCTO: rstatus=U_EMRARCTO_safe(record); break; + case U_EMR_POLYDRAW: rstatus=U_EMRPOLYDRAW_safe(record); break; + case U_EMR_SETARCDIRECTION: rstatus=U_EMRSETARCDIRECTION_safe(record); break; + case U_EMR_SETMITERLIMIT: rstatus=U_EMRSETMITERLIMIT_safe(record); break; + case U_EMR_BEGINPATH: rstatus=U_EMRBEGINPATH_safe(record); break; + case U_EMR_ENDPATH: rstatus=U_EMRENDPATH_safe(record); break; + case U_EMR_CLOSEFIGURE: rstatus=U_EMRCLOSEFIGURE_safe(record); break; + case U_EMR_FILLPATH: rstatus=U_EMRFILLPATH_safe(record); break; + case U_EMR_STROKEANDFILLPATH: rstatus=U_EMRSTROKEANDFILLPATH_safe(record); break; + case U_EMR_STROKEPATH: rstatus=U_EMRSTROKEPATH_safe(record); break; + case U_EMR_FLATTENPATH: rstatus=U_EMRFLATTENPATH_safe(record); break; + case U_EMR_WIDENPATH: rstatus=U_EMRWIDENPATH_safe(record); break; + case U_EMR_SELECTCLIPPATH: rstatus=U_EMRSELECTCLIPPATH_safe(record); break; + case U_EMR_ABORTPATH: rstatus=U_EMRABORTPATH_safe(record); break; + case U_EMR_UNDEF69: rstatus=U_EMRUNDEF69_safe(record); break; + case U_EMR_COMMENT: rstatus=U_EMRCOMMENT_safe(record); break; + case U_EMR_FILLRGN: rstatus=U_EMRFILLRGN_safe(record); break; + case U_EMR_FRAMERGN: rstatus=U_EMRFRAMERGN_safe(record); break; + case U_EMR_INVERTRGN: rstatus=U_EMRINVERTRGN_safe(record); break; + case U_EMR_PAINTRGN: rstatus=U_EMRPAINTRGN_safe(record); break; + case U_EMR_EXTSELECTCLIPRGN: rstatus=U_EMREXTSELECTCLIPRGN_safe(record); break; + case U_EMR_BITBLT: rstatus=U_EMRBITBLT_safe(record); break; + case U_EMR_STRETCHBLT: rstatus=U_EMRSTRETCHBLT_safe(record); break; + case U_EMR_MASKBLT: rstatus=U_EMRMASKBLT_safe(record); break; + case U_EMR_PLGBLT: rstatus=U_EMRPLGBLT_safe(record); break; + case U_EMR_SETDIBITSTODEVICE: rstatus=U_EMRSETDIBITSTODEVICE_safe(record); break; + case U_EMR_STRETCHDIBITS: rstatus=U_EMRSTRETCHDIBITS_safe(record); break; + case U_EMR_EXTCREATEFONTINDIRECTW: rstatus=U_EMREXTCREATEFONTINDIRECTW_safe(record); break; + case U_EMR_EXTTEXTOUTA: rstatus=U_EMREXTTEXTOUTA_safe(record); break; + case U_EMR_EXTTEXTOUTW: rstatus=U_EMREXTTEXTOUTW_safe(record); break; + case U_EMR_POLYBEZIER16: rstatus=U_EMRPOLYBEZIER16_safe(record); break; + case U_EMR_POLYGON16: rstatus=U_EMRPOLYGON16_safe(record); break; + case U_EMR_POLYLINE16: rstatus=U_EMRPOLYLINE16_safe(record); break; + case U_EMR_POLYBEZIERTO16: rstatus=U_EMRPOLYBEZIERTO16_safe(record); break; + case U_EMR_POLYLINETO16: rstatus=U_EMRPOLYLINETO16_safe(record); break; + case U_EMR_POLYPOLYLINE16: rstatus=U_EMRPOLYPOLYLINE16_safe(record); break; + case U_EMR_POLYPOLYGON16: rstatus=U_EMRPOLYPOLYGON16_safe(record); break; + case U_EMR_POLYDRAW16: rstatus=U_EMRPOLYDRAW16_safe(record); break; + case U_EMR_CREATEMONOBRUSH: rstatus=U_EMRCREATEMONOBRUSH_safe(record); break; + case U_EMR_CREATEDIBPATTERNBRUSHPT: rstatus=U_EMRCREATEDIBPATTERNBRUSHPT_safe(record); break; + case U_EMR_EXTCREATEPEN: rstatus=U_EMREXTCREATEPEN_safe(record); break; + case U_EMR_POLYTEXTOUTA: rstatus=U_EMRPOLYTEXTOUTA_safe(record); break; + case U_EMR_POLYTEXTOUTW: rstatus=U_EMRPOLYTEXTOUTW_safe(record); break; + case U_EMR_SETICMMODE: rstatus=U_EMRSETICMMODE_safe(record); break; + case U_EMR_CREATECOLORSPACE: rstatus=U_EMRCREATECOLORSPACE_safe(record); break; + case U_EMR_SETCOLORSPACE: rstatus=U_EMRSETCOLORSPACE_safe(record); break; + case U_EMR_DELETECOLORSPACE: rstatus=U_EMRDELETECOLORSPACE_safe(record); break; + case U_EMR_GLSRECORD: rstatus=U_EMRGLSRECORD_safe(record); break; + case U_EMR_GLSBOUNDEDRECORD: rstatus=U_EMRGLSBOUNDEDRECORD_safe(record); break; + case U_EMR_PIXELFORMAT: rstatus=U_EMRPIXELFORMAT_safe(record); break; + case U_EMR_DRAWESCAPE: rstatus=U_EMRDRAWESCAPE_safe(record); break; + case U_EMR_EXTESCAPE: rstatus=U_EMREXTESCAPE_safe(record); break; + case U_EMR_UNDEF107: rstatus=U_EMRUNDEF107_safe(record); break; + case U_EMR_SMALLTEXTOUT: rstatus=U_EMRSMALLTEXTOUT_safe(record); break; + case U_EMR_FORCEUFIMAPPING: rstatus=U_EMRFORCEUFIMAPPING_safe(record); break; + case U_EMR_NAMEDESCAPE: rstatus=U_EMRNAMEDESCAPE_safe(record); break; + case U_EMR_COLORCORRECTPALETTE: rstatus=U_EMRCOLORCORRECTPALETTE_safe(record); break; + case U_EMR_SETICMPROFILEA: rstatus=U_EMRSETICMPROFILEA_safe(record); break; + case U_EMR_SETICMPROFILEW: rstatus=U_EMRSETICMPROFILEW_safe(record); break; + case U_EMR_ALPHABLEND: rstatus=U_EMRALPHABLEND_safe(record); break; + case U_EMR_SETLAYOUT: rstatus=U_EMRSETLAYOUT_safe(record); break; + case U_EMR_TRANSPARENTBLT: rstatus=U_EMRTRANSPARENTBLT_safe(record); break; + case U_EMR_UNDEF117: rstatus=U_EMRUNDEF117_safe(record); break; + case U_EMR_GRADIENTFILL: rstatus=U_EMRGRADIENTFILL_safe(record); break; + case U_EMR_SETLINKEDUFIS: rstatus=U_EMRSETLINKEDUFIS_safe(record); break; + case U_EMR_SETTEXTJUSTIFICATION: rstatus=U_EMRSETTEXTJUSTIFICATION_safe(record); break; + case U_EMR_COLORMATCHTOTARGETW: rstatus=U_EMRCOLORMATCHTOTARGETW_safe(record); break; + case U_EMR_CREATECOLORSPACEW: rstatus=U_EMRCREATECOLORSPACEW_safe(record); break; + default: rstatus=U_EMRNOTIMPLEMENTED_safe(record); break; + } //end of switch + return(rstatus); +} + + +#ifdef __cplusplus +} +#endif diff --git a/src/3rdparty/libuemf/uemf_safe.h b/src/3rdparty/libuemf/uemf_safe.h new file mode 100644 index 0000000..0c9e3cc --- /dev/null +++ b/src/3rdparty/libuemf/uemf_safe.h @@ -0,0 +1,32 @@ +/** + @file uemf_safe.h + + @brief Defintions and prototype for function for converting EMF records between Big Endian and Little Endian byte orders. +*/ + +/* +File: uemf_endian.h +Version: 0.0.2 +Date: 26-MAR-2015 +Author: David Mathog, Biology Division, Caltech +email: mathog@caltech.edu +Copyright: 2015 David Mathog and California Institute of Technology (Caltech) +*/ + +#ifndef _UEMF_SAFE_ +#define _UEMF_SAFE_ + +#ifdef __cplusplus +extern "C" { +#endif + +// prototypes +int U_emf_record_safe(const char *record); +int bitmapinfo_safe(const char *Bmi, const char *blimit); +//! \endcond + +#ifdef __cplusplus +} +#endif + +#endif /* _UEMF_SAFE_ */ diff --git a/src/3rdparty/libuemf/uemf_utf.c b/src/3rdparty/libuemf/uemf_utf.c new file mode 100644 index 0000000..5c65078 --- /dev/null +++ b/src/3rdparty/libuemf/uemf_utf.c @@ -0,0 +1,720 @@ +/** + @file uemf_utf.c + + @brief Functions for manipulating UTF and various types of text. + + + Compile with "U_VALGRIND" defined defined to enable code which lets valgrind check each record for + uninitialized data. + + Compile with "SOL8" defined for Solaris 8 or 9 (Sparc). +*/ + +/* +File: uemf_utf.c +Version: 0.0.5 +Date: 29-JAN-2014 +Author: David Mathog, Biology Division, Caltech +email: mathog@caltech.edu +Copyright: 2014 David Mathog and California Institute of Technology (Caltech) +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <iconv.h> +#include <wchar.h> +#include <errno.h> +#include <string.h> +#include <limits.h> // for INT_MAX, INT_MIN +#include <math.h> // for U_ROUND() +#include "uemf_utf.h" + +//! \cond +/* Prototypes for functions used here and defined in uemf_endian.c, but which are not supposed +to be used in end user code. */ + +void U_swap2(void *ul, unsigned int count); +//! \endcond + +/* ******************************************************************************************** */ + +/** \cond */ +/* iconv() has a funny cast on some older systems, on most recent ones + it is just char **. This tries to work around the issue. If you build this + on another funky system this code may need to be modified, or define ICONV_CAST + on the compile line(but it may be tricky). +*/ +#if _LIBICONV_VERSION == 0x0109 +# define ICONV_CAST (const char **) +#endif // _LIBICONV_VERSION 0x0109 +#ifdef SOL8 +# define ICONV_CAST (const char **) +#endif //SOL8 +#if !defined(ICONV_CAST) +# define ICONV_CAST (char **) +#endif //ICONV_CAST +/** \endcond */ + +/* ********************************************************************************************** +These functions are used for development and debugging and should be be includied in production code. +*********************************************************************************************** */ + +/** + \brief Dump a UTF8 string. Not for use in production code. + \param src string to examine +*/ +void wchar8show( + const char *src + ){ + if(!src){ + printf("char show <NULL>\n"); + } + else { + printf("char show\n"); + size_t srclen = 0; + while(*src){ printf("%d %d %x\n",(int) srclen,*src,*src); srclen++; src++; } + } +} + +/** + \brief Dump a UTF16 string. Not for use in production code. + \param src string to examine +*/ +void wchar16show( + const uint16_t *src + ){ + if(!src){ + printf("uint16_t show <NULL>\n"); + } + else { + printf("uint16_t show\n"); + size_t srclen = 0; + while(*src){ printf("%d %d %x\n",(int) srclen,*src,*src); srclen++; src++; } + } +} + +/** + \brief Dump a UTF32 string. Not for use in production code. +*/ +void wchar32show( + const uint32_t *src + ){ + if(!src){ + printf("uint32_t show <NULL>\n"); + } + else { + printf("uint32_t show\n"); + size_t srclen = 0; + while(*src){ printf("%d %d %x\n",(int) srclen,*src,*src); srclen++; src++; } + } +} + +/** + \brief Dump a wchar_t string. Not for use in production code. + \param src string to examine +*/ +void wchartshow( + const wchar_t *src + ){ + uint32_t val; + if(!src){ + printf("wchar_t show <NULL>\n"); + } + else { + printf("wchar_t show\n"); + size_t srclen = 0; + if(!src)return; + while(*src){ + val = *src; // because *src is wchar_t is not strictly an integer type, can cause warnings on next line + printf("%d %d %x\n",(int) srclen,val,val); + srclen++; + src++; + } + } +} + +/* ********************************************************************************************** +These functions are used for character type conversions, Image conversions, and other +utility operations +*********************************************************************************************** */ + +/** + \brief Find the number of (storage) characters in a 16 bit character string, not including terminator. + \param src string to examine +*/ +size_t wchar16len( + const uint16_t *src + ){ + size_t srclen = 0; + if(src){ + while(*src){ srclen++; src++; } + } + return(srclen); +} + +/** + \brief Find the number of (storage) characters in a 32 bit character string, not including terminator. + \param src string to examine +*/ +size_t wchar32len( + const uint32_t *src + ){ + size_t srclen = 0; + if(src){ + while(*src){ srclen++; src++; } + } + return(srclen); +} + +/** + \brief Strncpy for wchar16 (UTF16). + \param dst destination (already allocated) + \param src source + \param nchars number of characters to copy +*/ +void wchar16strncpy( + uint16_t *dst, + const uint16_t *src, + size_t nchars + ){ + if(src){ + for(;nchars;nchars--,dst++,src++){ + *dst = *src; + if(!*src)break; + } + } +} + +/** + \brief Fill the output string with N characters, if the input string is shorter than N, pad with nulls. + \param dst destination (already allocated) + \param src source + \param nchars number of characters to copy + +*/ +void wchar16strncpypad( + uint16_t *dst, + const uint16_t *src, + size_t nchars + ){ + if(src){ + for(;*src && nchars;nchars--,dst++,src++){ *dst = *src; } + for(;nchars;nchars--,dst++){ *dst = 0; } // Pad the remainder + } +} + +/* For the following converstion functions, remember that iconv() modifies ALL of its parameters, + so save a pointer to the destination buffer!!!! + It isn't clear that terminators are being + copied properly, so be sure allocated space is a bit larger and cleared. +*/ + +/** + \brief Convert a UTF32LE string to a UTF16LE string. + \returns pointer to new string or NULL if it fails + \param src wchar_t string to convert + \param max number of characters to convert, if 0, until terminator + \param len number of characters in new string, NOT including terminator +*/ +uint16_t *U_Utf32leToUtf16le( + const uint32_t *src, + size_t max, + size_t *len + ){ + char *dst,*dst2; + char *src2 = (char *) src; + size_t srclen,dstlen,status; + + if(!src)return(NULL); + if(max){ srclen = 4*max; } + else { srclen = 4 + 4*wchar32len(src); } //include terminator, length in BYTES + + dstlen = 2 + srclen; // this will always work, but may waste space + dst2 = dst = calloc(dstlen,1); // so there will be at least one terminator + if(dst){ + iconv_t conv = iconv_open("UTF-16LE", "UTF-32LE"); + if ( conv == (iconv_t) -1){ + free(dst2); + dst2=NULL; + } + else { + status = iconv(conv, ICONV_CAST &src2, &srclen, &dst, &dstlen); + iconv_close(conv); + if(status == (size_t) -1){ + free(dst2); + dst2 = NULL; + } + else if(len){ + *len=wchar16len((uint16_t *)dst2); + } + } + } + return((uint16_t *)dst2); +} + +/** + \brief Convert a UTF16LE string to a UTF32LE string. + \return pointer to new string or NULL if it fails + \param src UTF16LE string to convert + \param max number of characters to convert, if 0, until terminator + \param len number of characters in new string, NOT including terminator +*/ +uint32_t *U_Utf16leToUtf32le( + const uint16_t *src, + size_t max, + size_t *len + ){ + char *dst,*dst2; + char *src2 = (char *) src; + size_t srclen,dstlen,status; + + if(!src)return(NULL); + if(max){ srclen = 2*max; } + else { srclen = 2*wchar16len(src)+2; } // include terminator, length in BYTES + dstlen = 2*(2 + srclen); // This should always work + dst2 = dst = calloc(dstlen,1); + if(dst){ + iconv_t conv = iconv_open("UTF-32LE", "UTF-16LE"); + if ( conv == (iconv_t) -1){ + free(dst2); + dst2=NULL; + } + else { + status = iconv(conv, ICONV_CAST &src2, &srclen, &dst, &dstlen); + iconv_close(conv); + if(status == (size_t) -1){ + free(dst2); + dst2 = NULL; + } + else if(len){ + *len=wchar32len((uint32_t *)dst2); + } + } + } + return((uint32_t *) dst2); +} + +/** + \brief Convert a Latin1 string to a UTF32LE string. + \return pointer to new string or NULL if it fails + \param src Latin1 string to convert + \param max number of characters to convert, if 0, until terminator + \param len number of characters in new string, NOT including terminator + + + U_EMR_EXTTEXTOUTA records are "8 bit ASCII". In theory that is ASCII in an 8 + bit character, but numerous applications store Latin1 in them, and some + _may_ store UTF-8 in them. Since very vew Latin1 strings are valid UTF-8 strings, + call U_Utf8ToUtf32le first, and if it fails, then call this function. +*/ +uint32_t *U_Latin1ToUtf32le( + const char *src, + size_t max, + size_t *len + ){ + char *dst,*dst2; + char *src2 = (char *) src; + size_t srclen,dstlen,status; + + if(!src)return(NULL); + if(max){ srclen = max; } + else { srclen = strlen(src)+1; } // include terminator, length in BYTES + dstlen = sizeof(uint32_t)*(1 + srclen); // This should always work but might waste some space + dst2 = dst = calloc(dstlen,1); + if(dst){ + iconv_t conv = iconv_open("UTF-32LE", "LATIN1"); + if ( conv == (iconv_t) -1){ + free(dst2); + dst2=NULL; + } + else { + status = iconv(conv, ICONV_CAST &src2, &srclen, &dst, &dstlen); + iconv_close(conv); + if(status == (size_t) -1){ + free(dst2); + dst2 = NULL; + } + else if(len){ + *len=wchar32len((uint32_t *)dst2); + } + } + } + return((uint32_t *) dst2); +} + +/** + \brief Convert a UTF8 string to a UTF32LE string. + \return pointer to new string or NULL if it fails + \param src UTF8 string to convert + \param max number of characters to convert, if 0, until terminator + \param len number of characters in new string, NOT including terminator +*/ +uint32_t *U_Utf8ToUtf32le( + const char *src, + size_t max, + size_t *len + ){ + char *dst,*dst2; + char *src2 = (char *) src; + size_t srclen,dstlen,status; + + if(!src)return(NULL); + if(max){ srclen = max; } + else { srclen = strlen(src)+1; } // include terminator, length in BYTES + dstlen = sizeof(uint32_t)*(1 + srclen); // This should always work but might waste some space + dst2 = dst = calloc(dstlen,1); + if(dst){ + iconv_t conv = iconv_open("UTF-32LE", "UTF-8"); + if ( conv == (iconv_t) -1){ + free(dst2); + dst2=NULL; + } + else { + status = iconv(conv, ICONV_CAST &src2, &srclen, &dst, &dstlen); + iconv_close(conv); + if(status == (size_t) -1){ + free(dst2); + dst2 = NULL; + } + else if(len){ + *len=wchar32len((uint32_t *)dst2); + } + } + } + return((uint32_t *) dst2); +} + +/** + \brief Convert a UTF32LE string to a UTF8 string. + \return pointer to new string or NULL if it fails + \param src wchar_t string to convert + \param max number of characters to convert, if 0, until terminator + \param len number of characters in new string, NOT including terminator +*/ +char *U_Utf32leToUtf8( + const uint32_t *src, + size_t max, + size_t *len + ){ + char *dst,*dst2; + char *src2 = (char *) src; + size_t srclen,dstlen,status; + + if(!src)return(NULL); + if(max){ srclen = 4*max; } + else { srclen = 4*(1 + wchar32len(src)); } //include terminator, length in BYTES + dstlen = 1 + srclen; // This should always work but might waste some space + dst2 = dst = calloc(dstlen,1); + if(dst){ + iconv_t conv = iconv_open("UTF-8", "UTF-32LE"); + if ( conv == (iconv_t) -1){ + free(dst2); + dst2=NULL; + } + else { + status = iconv(conv, ICONV_CAST &src2, &srclen, &dst, &dstlen); + iconv_close(conv); + if(status == (size_t) -1){ + free(dst2); + dst2 = NULL; + } + else if(len){ + *len=strlen(dst2); + } + } + } + return(dst2); +} + +/** + \brief Convert a UTF-8 string to a UTF16-LE string. + \return pointer to new string or NULL if it fails + \param src UTF8 string to convert + \param max number of characters to convert, if 0, until terminator + \param len number of characters in new string, NOT including terminator +*/ +uint16_t *U_Utf8ToUtf16le( + const char *src, + size_t max, + size_t *len + ){ + char *dst,*dst2; + char *src2 = (char *) src; + size_t srclen,dstlen,status; + + if(!src)return(NULL); + if(max){ srclen = max; } + else { srclen = strlen(src)+1; } // include terminator, length in BYTES + dstlen = 2 * (1 + srclen); // this will always work, but may waste space + dst2 = dst =calloc(dstlen,1); // so there will always be a terminator + if(dst){ + iconv_t conv = iconv_open("UTF-16LE", "UTF-8"); + if ( conv == (iconv_t) -1){ + free(dst2); + dst2=NULL; + } + else { + status = iconv(conv, ICONV_CAST &src2, &srclen, &dst, &dstlen); + iconv_close(conv); + if(status == (size_t) -1){ + free(dst2); + dst2 = NULL; + } + else if(len){ + *len=wchar16len((uint16_t *)dst2); + } + } + } + return((uint16_t *)dst2); +} + +/** + \brief Convert a UTF16LE string to a UTF8 string. + \return pointer to new UTF8 string or NULL if it fails + \param src UTF16LE string to convert + \param max number of characters to convert, if 0, until terminator + \param len number of characters in new string, NOT including terminator +*/ +char *U_Utf16leToUtf8( + const uint16_t *src, + size_t max, + size_t *len + ){ + char *dst, *dst2; + char *src2 = (char *) src; + size_t srclen,dstlen,status; + + if(!src)return(NULL); + if(max){ srclen = 2*max; } + else { srclen = 2*(1 +wchar16len(src)); } //include terminator, length in BYTES + dstlen = 1 + 2*srclen; // this will always work, but may waste space + // worst case is all glyphs (==max) need 4 UTF-8 encoded bytes + terminator. + dst2 = dst = (char *) calloc(dstlen,1); + if(dst){ + iconv_t conv = iconv_open("UTF-8", "UTF-16LE"); + if ( conv == (iconv_t) -1){ + free(dst2); + dst2=NULL; + } + else { + status = iconv(conv, ICONV_CAST &src2, &srclen, &dst, &dstlen); + iconv_close(conv); + if(status == (size_t) -1){ + free(dst2); + dst2 = NULL; + } + else if(len){ + *len=strlen(dst2); + dst = dst2; + dst2 = U_strdup(dst); // make a string of exactly the right size + free(dst); // free the one which was probably too big + } + } + } + return(dst2); +} + +/** + \brief Convert a UTF16LE string to a LATIN1 string. + \return pointer to new UTF8 string or NULL if it fails + \param src UTF16LE string to convert + \param max number of characters to convert, if 0, until terminator + \param len number of characters in new string, NOT including terminator +*/ +char *U_Utf16leToLatin1( + const uint16_t *src, + size_t max, + size_t *len + ){ + char *dst, *dst2; + char *src2 = (char *) src; + size_t srclen,dstlen,status; + + if(!src)return(NULL); + if(max){ srclen = 2*max; } + else { srclen = 2*(1 +wchar16len(src)); } //include terminator, length in BYTES + dstlen = 1 + srclen; // this will always work as latin1 is always 1 byte/character + dst2 = dst = (char *) calloc(dstlen,1); + if(dst){ + iconv_t conv = iconv_open("LATIN1//TRANSLIT", "UTF-16LE"); + if ( conv == (iconv_t) -1){ + free(dst2); + dst2=NULL; + } + else { + status = iconv(conv, ICONV_CAST &src2, &srclen, &dst, &dstlen); + iconv_close(conv); + if(status == (size_t) -1){ + free(dst2); + dst2 = NULL; + } + else if(len){ + *len=strlen(dst2); + dst = dst2; + dst2 = U_strdup(dst); // make a string of exactly the right size + free(dst); // free the one which was probably too big + } + } + } + return(dst2); +} +/** + \brief Put a single 16 bit character into UTF-16LE form. + + Used in conjunction with U_Utf16leEdit(), because the character + representation would otherwise be dependent on machine Endianness. + + \return UTF16LE representation of the character. + \param src 16 bit character + +*/ +uint16_t U_Utf16le(const uint16_t src){ + uint16_t dst=src; +#if U_BYTE_SWAP + U_swap2(&dst,1); +#endif + return(dst); +} + +/** + \brief Convert a UTF8 string to a Latin1 string. + \return pointer to new string or NULL if it fails + \param src Latin1 string to convert + \param max number of characters to convert, if 0, until terminator + \param len number of characters in new string, NOT including terminator + + + WMF uses latin1, others UTF-8, only some utf-8 can be converted to latin1. + +*/ +char *U_Utf8ToLatin1( + const char *src, + size_t max, + size_t *len + ){ + char *dst,*dst2; + char *src2 = (char *) src; + size_t srclen,dstlen,status; + if(max){ srclen = max; } + else { srclen = strlen(src)+1; } // include terminator, length in BYTES + dstlen = (1 + srclen); // This should always work but might waste some space + dst2 = dst = calloc(dstlen,1); + if(dst){ + iconv_t conv = iconv_open("LATIN1//TRANSLIT", "UTF-8"); // translate what can be, fill in with something close for the rest + if ( conv == (iconv_t) -1){ + free(dst2); + dst2=NULL; + } + else { + status = iconv(conv, ICONV_CAST &src2, &srclen, &dst, &dstlen); + iconv_close(conv); + if(status == (size_t) -1){ + free(dst2); + dst2 = NULL; + } + else if(len){ + *len=strlen(dst2); + } + } + } + return((char *) dst2); +} + +/** + \brief Convert a Latin1 string to a UTF8 string. + \return pointer to new string or NULL if it fails + \param src Latin1 string to convert + \param max number of characters to convert, if 0, until terminator + \param len number of characters in new string, NOT including terminator + + + WMF uses latin1, others UTF-8, all Latin1 should be able to convert to utf-8. + +*/ +char *U_Latin1ToUtf8( + const char *src, + size_t max, + size_t *len + ){ + char *dst,*dst2; + char *src2 = (char *) src; + size_t srclen,dstlen,status; + if(max){ srclen = max; } + else { srclen = strlen(src)+1; } // include terminator, will waste some space + dstlen = (1 + 2*srclen); // This should always work because all latin1 convert to 1 or 2 byte UTF8, it might waste some space + dst2 = dst = calloc(dstlen,1); + if(dst){ + iconv_t conv = iconv_open("UTF-8", "LATIN1"); // everything should translate + if ( conv == (iconv_t) -1){ + free(dst2); + dst2=NULL; + } + else { + status = iconv(conv, ICONV_CAST &src2, &srclen, &dst, &dstlen); + iconv_close(conv); + if(status == (size_t) -1){ + free(dst2); + dst2 = NULL; + } + else if(len){ + *len=strlen(dst2); + } + } + } + return((char *) dst2); +} + +/** + \brief Single character replacement in a UTF-16LE string. + + Used solely for the Description field which contains + embedded nulls, which makes it difficult to manipulate. Use some other character and then swap it. + + \return number of substitutions, or -1 if src is not defined + \param src UTF16LE string to edit + \param find character to replace + \param replace replacestitute character + +*/ +int U_Utf16leEdit( + uint16_t *src, + uint16_t find, + uint16_t replace + ){ + int count=0; + if(!src)return(-1); + while(*src){ + if(*src == find){ *src = replace; count++; } + src++; + } + return(count); +} + +/** + \brief strdup for when strict C99 compliance is enforced + \returns duplicate string or NULL on error + \param s string to duplicate +*/ +char *U_strdup(const char *s){ + char *news=NULL; + size_t slen; + if(s){ + slen = strlen(s) + 1; //include the terminator! + news = malloc(slen); + if(news){ + memcpy(news,s,slen); + } + } + return(news); + +} + + +#ifdef __cplusplus +} +#endif diff --git a/src/3rdparty/libuemf/uemf_utf.h b/src/3rdparty/libuemf/uemf_utf.h new file mode 100644 index 0000000..68452b6 --- /dev/null +++ b/src/3rdparty/libuemf/uemf_utf.h @@ -0,0 +1,55 @@ +/** + @file uemf_utf.h + + @brief Prototypes for functions that manipulate UTF and various types of text. + +*/ + +/* +File: uemf_utf.h +Version: 0.0.1 +Date: 04-DEC-2012 +Author: David Mathog, Biology Division, Caltech +email: mathog@caltech.edu +Copyright: 2012 David Mathog and California Institute of Technology (Caltech) +*/ + +#ifndef _UEMF_UTF_ +#define _UEMF_UTF_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdint.h> +#include <stdbool.h> +#include "uemf_endian.h" + +void wchar8show(const char *src); +void wchar16show(const uint16_t *src); +void wchar32show(const uint32_t *src); +void wchartshow(const wchar_t *src); + +size_t wchar16len(const uint16_t *src); +size_t wchar32len(const uint32_t *src); +void wchar16strncpy(uint16_t *dst, const uint16_t *src, size_t nchars); +void wchar16strncpypad(uint16_t *dst, const uint16_t *src, size_t nchars); +uint16_t *U_Utf8ToUtf16le( const char *src, size_t max, size_t *len ); +uint32_t *U_Utf8ToUtf32le( const char *src, size_t max, size_t *len ); +uint32_t *U_Latin1ToUtf32le( const char *src, size_t max, size_t *len ); +uint16_t *U_Utf32leToUtf16le( const uint32_t *src, size_t max, size_t *len ); +char *U_Utf32leToUtf8( const uint32_t *src, size_t max, size_t *len ); +uint32_t *U_Utf16leToUtf32le( const uint16_t *src, size_t max, size_t *len ); +char *U_Utf16leToUtf8( const uint16_t *src, size_t max, size_t *len ); +char *U_Utf16leToLatin1( const uint16_t *src, size_t max, size_t *len ); +char *U_Utf8ToLatin1( const char *src, size_t max, size_t *len ); +char *U_Latin1ToUtf8( const char *src, size_t max, size_t *len ); +uint16_t U_Utf16le(const uint16_t src); +int U_Utf16leEdit( uint16_t *src, uint16_t find, uint16_t replace ); +char *U_strdup(const char *s); + +#ifdef __cplusplus +} +#endif + +#endif /* _UEMF_UTF_ */ diff --git a/src/3rdparty/libuemf/upmf.c b/src/3rdparty/libuemf/upmf.c new file mode 100644 index 0000000..20a87ae --- /dev/null +++ b/src/3rdparty/libuemf/upmf.c @@ -0,0 +1,8661 @@ +/** + @file upmf.c + + @brief Functions for manipulating EMF+ files and structures. + + EMF+ is much more object based than is EMF or WMF, so the U_PMR_*_set and most U_PMF_*_set functions + return a pointer to a PseudoObject. PseudoObjects are structs that contain a data field to hold the + object in EMF+ file byte order, size information, and some type information. This is sufficient to allow + complex records to be built up from the various sorts of nested objects which they normally contain. + If something goes wrong a NULL pointer is returned and recsize is set to 0. + + EMF+ does not use a separate set of endian functions, _get and _set routines convert from/to + the EMF+ file byte order on the fly. + + WARNING: Microsoft's EMF+ documentation is little-endian for everything EXCEPT + bitfields, which are big-endian. See EMF+ manual section 1.3.2 + That documentation also uses 0 as the MOST significant bit, N-1 as the least. + This code is little-endian throughout, and 0 is the LEAST significant bit + +*/ + +/* +File: upmf.c +Version: 0.0.13 +Date: 21-MAR-2019 +Author: David Mathog, Biology Division, Caltech +email: mathog@caltech.edu +Copyright: 2019 David Mathog and California Institute of Technology (Caltech) +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <iconv.h> +#include <wchar.h> +#include <errno.h> +#include <string.h> +#include <limits.h> // for INT_MAX, INT_MIN +#include <math.h> // for sin, cos, tan2, use U_ROUND() instead of roundf() +#include <stddef.h> /* for offsetof() macro */ +#if 0 +#include <windef.h> //Not actually used, looking for collisions +#include <winnt.h> //Not actually used, looking for collisions +#include <wingdi.h> //Not actually used, looking for collisions +#endif +#include "upmf.h" // includes uemf.h +#include "uemf_endian.h" // for U_swap* functions + +//! \cond + +/// things Doxygen should not process +/* remove this after debugging is completed */ +void dumphex(uint8_t *buf,unsigned int num){ + for(; num; num--,buf++){ + printf("%2.2X",*buf); + } +} + + +/* Prototypes for functions used here and defined in uemf_endian.c, but which are not supposed +to be used in end user code. */ + +void U_swap2(void *ul, unsigned int count); +void U_swap4(void *ul, unsigned int count); +//! \endcond + +/** + \brief Utility function for writing one or more EMF+ records in a PseudoObject to the EMF output file + \return 1 on success, 0 on error. + \param po U_PSEUDO_OBJ to write, it is deleted after it is written + \param sum U_PSEUDO_OBJ to use for scratch space + \param et EMFTRACK used to write records to EMF file +*/ +int U_PMR_write(U_PSEUDO_OBJ *po, U_PSEUDO_OBJ *sum, EMFTRACK *et){ + char *rec; + int status = 0; + sum->Used = 0; /* clean it out, retaining allocated memory */ + sum = U_PO_append(sum, "EMF+", 4); /* indicates that this comment holds an EMF+ record */ + if(!sum)goto end; + sum = U_PO_append(sum, po->Data, po->Used); /* the EMF+ record itself */ + if(!sum)goto end; + U_PO_free(&po); /* delete the PseudoObject */ + rec = U_EMRCOMMENT_set(sum->Used, sum->Data); /* stuff it into the EMF comment */ + if(!emf_append((PU_ENHMETARECORD)rec, et, 1))goto end; /* write it to the EMF file, delete the record, check status */ + status = 1; +end: + return(status); +} + +/** + \brief Utility function to draw a line. + \return 1 on success, 0 on error. + \param PenID Index of U_PMF_PEN object to use in the EMF+ object table (0-63, inclusive) + \param PathID Index of U_PMF_PATH object to use in the EMF+ object table (0-63, inclusive) + \param Start U_PMF_POINTF coordinates of start of line. + \param End U_PMF_POINTF coordinates of end of line. + \param Dashed Set if the line is dashed, clear if it is not. + \param sum PseudoObject used for scratch space + \param et EMFTRACK used to write records to EMF file + +*/ +int U_PMR_drawline(uint32_t PenID, uint32_t PathID, U_PMF_POINTF Start, U_PMF_POINTF End, int Dashed, U_PSEUDO_OBJ *sum, EMFTRACK *et){ + U_DPSEUDO_OBJ *dpath; + U_PSEUDO_OBJ *poPath; + U_PSEUDO_OBJ *po; + int status=0; + int PTP_value = ( Dashed ? U_PTP_DashMode : U_PTP_None); + dpath = U_PATH_create(0, NULL, 0, 0); /* create an empty path*/ + if(dpath){ + if(U_PATH_moveto(dpath, Start, PTP_value) && U_PATH_lineto(dpath, End, PTP_value)){ + poPath = U_PMF_PATH_set2(U_PMF_GRAPHICSVERSIONOBJ_set(2), dpath); + if(poPath){ + po = U_PMR_OBJECT_PO_set(PathID, poPath); + U_PO_free(&poPath); + if(po){ + U_PMR_write(po, sum, et); + po = U_PMR_DRAWPATH_set(PathID, PenID); + if(po){ + U_PMR_write(po, sum, et); + status = 1; + } + } + } + } + U_DPO_free(&dpath); + } + return(status); +} + +/** + \brief Utility function for drawing strings onto the baseline in one call. + \return 1 on success, 0 on error. + \param string Text to draw in UTF-8 format + \param Vpos StringAlignment Enumeration. Always drawn on baseline, but using one of these three modes. + \param FontID Index of U_PMF_FONT object to use in the EMF+ object table (0-63, inclusive) + \param BrushID U_PSEUDO_OBJ containing a U_PMF_ARGB or a U_PMF_4NUM. Color or U_PMF_BRUSH object in the EMF+ object table (0-63, inclusive) + \param FormatID index of U_PMF_STRINGFORMAT object to use in the EMF+ Object Table. + \param Sfs StringFormat structure. Ignored values: StringAlignment, LineAlign, Flags + \param FontName Name of font to draw with + \param Height Height of font in pixels (positive) + \param fip U_FontInfoParams (ascent, descent, and so forth) + \param FontFlags FontStyle Flags + \param x X position in pixels of left side of EM box of first character + \param y Y position in pixels of baseline of first character + \param sum PseudoObject used for scratch space + \param et EMFTRACK used to write records to EMF file + + EMF+ manual 2.3.4.14, Microsoft name: EmfPlusDrawString Record, Index 0x1C + + For most fonts Ascent and Descent are used to adjust the bounding box to properly position the + baseline. Some fonts, like Verdana, are strange and they position the baseline on the bottom of + the bounding box if that box has the same height as the font. For those fonts specify 0.0 for + both Ascent and Descent. +*/ +int U_PMR_drawstring( const char *string, int Vpos, uint32_t FontID, const U_PSEUDO_OBJ *BrushID, uint32_t FormatID, + U_PMF_STRINGFORMAT Sfs, const char *FontName, U_FLOAT Height, U_FontInfoParams *fip, uint32_t FontFlags, + U_FLOAT x, U_FLOAT y, U_PSEUDO_OBJ *sum, EMFTRACK *et){ + U_PSEUDO_OBJ *po; + U_PSEUDO_OBJ *poSF; + U_PSEUDO_OBJ *poFont; + U_PSEUDO_OBJ *poRect; + U_FLOAT rx,ry,rw,rh,rd; + uint16_t *UFontName; + uint16_t *Text16; + int slen; + int status = 0; + double aval, dval; + + Sfs.Flags = U_SF_NoFitBlackBox + U_SF_NoClip; + + if(Vpos < U_SA_Near || Vpos > U_SA_Far)return(0); + Sfs.StringAlignment = U_SA_Near; // Horizontal + Sfs.LineAlign = Vpos; // Vertical + + UFontName = U_Utf8ToUtf16le(FontName, 0, NULL); + slen = strlen(FontName); + poFont = U_PMF_FONT_set(U_PMF_GRAPHICSVERSIONOBJ_set(2), Height, U_UT_World, FontFlags, slen, UFontName); + if(poFont){ + po = U_PMR_OBJECT_PO_set(FontID, poFont); /* font to use */ + if(po){ + U_PMR_write(po, sum, et); + + poSF = U_PMF_STRINGFORMAT_set(&Sfs, NULL); + if(poSF){ + po = U_PMR_OBJECT_PO_set(FormatID, poSF); + U_PO_free(&poSF); + if(po){ + U_PMR_write(po, sum, et); + + rw = 4*Height*slen; /* This could probably be any value */ + rh = Height; + rx = x; + if(fip->LineGap > -fip->Descent){ aval = fip->yMax; } // sylfaen, palatino + else { aval = fip->Ascent; } // others + if(fip->LineGap && (fip->LineGap < -fip->Descent)){ dval = ((double) (fip->Descent - fip->LineGap)) / ((double) fip->EmSize); } //shruti and some others + else { dval = ((double) fip->Descent ) / ((double) fip->EmSize); } + switch(Vpos){ + case U_SA_Near: + rd = Height * aval / ((double) fip->EmSize); + break; + case U_SA_Center: + rd = 0.5 * ( Height * aval / ((double) fip->EmSize) + Height * ( 1.0 + dval)); + break; + case U_SA_Far: + rd = Height * ( 1.0 + dval); + break; + } + ry = y - rd; /* draw from upper left corner, which is shifted to put baseline on y */ + poRect = U_PMF_RECTF4_set(rx, ry, rw, rh); +#if 0 +(void) U_PMR_drawline(OBJ_PEN_BLACK_1,OBJ_PATH_1, (U_PMF_POINTF){x-100, ry}, (U_PMF_POINTF){x+100, ry}, 0, sum, et); +(void) U_PMR_drawline(OBJ_PEN_BLACK_1,OBJ_PATH_1, (U_PMF_POINTF){x-100, ry+rh}, (U_PMF_POINTF){x+100, ry+rh}, 0, sum, et); +(void) U_PMR_drawline(OBJ_PEN_BLACK_1,OBJ_PATH_1, (U_PMF_POINTF){x-100, ry}, (U_PMF_POINTF){x-100, ry + Height * (double) fip->Ascent / ((double) fip->EmSize)}, 0, sum, et); +(void) U_PMR_drawline(OBJ_PEN_BLACK_1,OBJ_PATH_1, (U_PMF_POINTF){x- 90, ry}, (U_PMF_POINTF){x- 90, ry - Height * (double) fip->Descent / ((double) fip->EmSize)}, 0, sum, et); +(void) U_PMR_drawline(OBJ_PEN_BLACK_1,OBJ_PATH_1, (U_PMF_POINTF){x- 80, ry}, (U_PMF_POINTF){x- 80, ry + Height * (double) fip->yMax / ((double) fip->EmSize)}, 0, sum, et); +(void) U_PMR_drawline(OBJ_PEN_BLACK_1,OBJ_PATH_1, (U_PMF_POINTF){x- 70, ry}, (U_PMF_POINTF){x- 70, ry - Height * (double) fip->yMin / ((double) fip->EmSize)}, 0, sum, et); +(void) U_PMR_drawline(OBJ_PEN_BLACK_1,OBJ_PATH_1, (U_PMF_POINTF){x- 60, ry}, (U_PMF_POINTF){x- 60, ry + Height * (double) fip->LineGap / ((double) fip->EmSize)}, 0, sum, et); +(void) U_PMR_drawline(OBJ_PEN_BLACK_1,OBJ_PATH_1, (U_PMF_POINTF){x- 50, ry}, (U_PMF_POINTF){x- 50, ry + Height * ( 1.0 - (((double) (fip->LineGap - fip->Descent)) / ((double) fip->EmSize)) )}, 0, sum, et); +#endif + + Text16 = U_Utf8ToUtf16le(string, 0, NULL); + slen = strlen(string); + po = U_PMR_DRAWSTRING_set(FontID, BrushID, FormatID, slen, poRect, Text16); + if(po){ + U_PMR_write(po, sum, et); + status = 1; /* Success!!! */ + } + U_PO_free(&poRect); + free(Text16); + } + } + } + U_PO_free(&poFont); + } + free(UFontName); + return(status); +} + +/** + \brief Allocate and construct an array of U_POINT16 objects from a set of U_PMF_POINTF objects, endianness in and out is LE + \returns pointer to an array of U_POINT16 structures. + \param points pointer to the source U_POINT structures + \param count number of members in points + + If a coordinate is out of range it saturates at boundary. +*/ +U_PMF_POINT *POINTF_To_POINT16_LE(U_PMF_POINTF *points, int count){ + U_PMF_POINT *newpts; + U_PMF_POINTF ptfl; + int i; + newpts = (U_PMF_POINT *) malloc(count * sizeof(U_PMF_POINT)); + + for(i=0; i<count; i++){ + memcpy(&ptfl, &(points[i]), 8); + if(U_BYTE_SWAP){ U_swap4(&ptfl,2); } /* on BE platforms swap going in and coming out */ + newpts[i].X = U_MNMX(ptfl.X, INT16_MIN, INT16_MAX); + newpts[i].Y = U_MNMX(ptfl.Y, INT16_MIN, INT16_MAX); + if(U_BYTE_SWAP){ U_swap2(&(newpts[i]),2); } + } + return(newpts); +} + +/** + \brief Look up the name of the EMR+ record by type. Returns U_EMR_INVALID if out of range. + + \return name of the PMR record, "U_EMR_INVALID" if out of range. + \param idx PMR record type WITHOUT the U_PMR_RECFLAG bit. + +*/ +char *U_pmr_names(unsigned int idx){ + if(idx<U_PMR_MIN || idx > U_PMR_MAX){ idx = 0; } + static char *U_PMR_NAMES[U_PMR_MAX+1]={ + "U_PMR_INVALID", + "U_PMR_Header", + "U_PMR_EndOfFile", + "U_PMR_Comment", + "U_PMR_GetDC", + "U_PMR_MultiFormatStart", + "U_PMR_MultiFormatSection", + "U_PMR_MultiFormatEnd", + "U_PMR_Object", + "U_PMR_Clear", + "U_PMR_FillRects", + "U_PMR_DrawRects", + "U_PMR_FillPolygon", + "U_PMR_DrawLines", + "U_PMR_FillEllipse", + "U_PMR_DrawEllipse", + "U_PMR_FillPie", + "U_PMR_DrawPie", + "U_PMR_DrawArc", + "U_PMR_FillRegion", + "U_PMR_FillPath", + "U_PMR_DrawPath", + "U_PMR_FillClosedCurve", + "U_PMR_DrawClosedCurve", + "U_PMR_DrawCurve", + "U_PMR_DrawBeziers", + "U_PMR_DrawImage", + "U_PMR_DrawImagePoints", + "U_PMR_DrawString", + "U_PMR_SetRenderingOrigin", + "U_PMR_SetAntiAliasMode", + "U_PMR_SetTextRenderingHint", + "U_PMR_SetTextContrast", + "U_PMR_SetInterpolationMode", + "U_PMR_SetPixelOffsetMode", + "U_PMR_SetCompositingMode", + "U_PMR_SetCompositingQuality", + "U_PMR_Save", + "U_PMR_Restore", + "U_PMR_BeginContainer", + "U_PMR_BeginContainerNoParams", + "U_PMR_EndContainer", + "U_PMR_SetWorldTransform", + "U_PMR_ResetWorldTransform", + "U_PMR_MultiplyWorldTransform", + "U_PMR_TranslateWorldTransform", + "U_PMR_ScaleWorldTransform", + "U_PMR_RotateWorldTransform", + "U_PMR_SetPageTransform", + "U_PMR_ResetClip", + "U_PMR_SetClipRect", + "U_PMR_SetClipPath", + "U_PMR_SetClipRegion", + "U_PMR_OffsetClip", + "U_PMR_DrawDriverstring", + "U_PMR_StrokeFillPath", + "U_PMR_SerializableObject", + "U_PMR_SetTSGraphics", + "U_PMR_SetTSClip" + }; + return(U_PMR_NAMES[idx]); +} + +/** + \brief Convert from PseudoObject OID to ObjectType enumeration. + \returns OT value on success, 0 if no match + \param OID PseudoObject OID (based on EMF+ manual chapter number. ) + + Only OTs that may be stored in the EMF+ object table are supported. +*/ + +int U_OID_To_OT(uint32_t OID){ + int otype; + if( OID==U_PMF_BRUSH_OID ){ otype = U_OT_Brush; } + else if(OID==U_PMF_PEN_OID ){ otype = U_OT_Pen; } + else if(OID==U_PMF_PATH_OID ){ otype = U_OT_Path; } + else if(OID==U_PMF_REGION_OID ){ otype = U_OT_Region; } + else if(OID==U_PMF_IMAGE_OID ){ otype = U_OT_Image; } + else if(OID==U_PMF_FONT_OID ){ otype = U_OT_Font; } + else if(OID==U_PMF_STRINGFORMAT_OID ){ otype = U_OT_StringFormat; } + else if(OID==U_PMF_IMAGEATTRIBUTES_OID){ otype = U_OT_ImageAttributes; } + else if(OID==U_PMF_CUSTOMLINECAP_OID ){ otype = U_OT_CustomLineCap; } + else { otype = U_OT_Invalid; } + return(otype); +} + +/** + \brief Convert from PseudoObject OID to BrushType enumeration. + \returns BT value on success, -1 if no match + \param OID PseudoObject OID (based on EMF+ manual chapter number. ) + + Only OIDs that map to BT's are supported. +*/ + +int U_OID_To_BT(uint32_t OID){ + int otype; + if( OID==U_PMF_HATCHBRUSHDATA_OID ){ otype = U_BT_HatchFill; } + else if(OID==U_PMF_LINEARGRADIENTBRUSHDATA_OID ){ otype = U_BT_LinearGradient; } + else if(OID==U_PMF_PATHGRADIENTBRUSHDATA_OID ){ otype = U_BT_PathGradient; } + else if(OID==U_PMF_SOLIDBRUSHDATA_OID ){ otype = U_BT_SolidColor; } + else if(OID==U_PMF_TEXTUREBRUSHDATA_OID ){ otype = U_BT_TextureFill; } + else { otype = -1; } + return(otype); +} + +/** + \brief Convert from PseudoObject OID to CustomLineCapDataType Enumeration. + \returns BT value on success, -1 if no match + \param OID PseudoObject OID (based on EMF+ manual chapter number. ) + + Only OIDs that map to CLCDT's are supported. +*/ + +int U_OID_To_CLCDT(uint32_t OID){ + int otype; + if( OID==U_PMF_CUSTOMLINECAPDATA_OID ){ otype = U_CLCDT_Default; } + else if(OID==U_PMF_CUSTOMLINECAPARROWDATA_OID ){ otype = U_CLCDT_AdjustableArrow; } + else { otype = -1; } + return(otype); +} + +/** + \brief Convert from PseudoObject OID to ImageDataType Enumeration. + \returns BT value on success, -1 if no match + \param OID PseudoObject OID (based on EMF+ manual chapter number. ) + + Only OIDs that map to IDT's are supported. +*/ + +int U_OID_To_IDT(uint32_t OID){ + int otype; + if( OID==U_PMF_BITMAP_OID ){ otype = U_IDT_Bitmap; } + else if(OID==U_PMF_METAFILE_OID ){ otype = U_IDT_Metafile; } + else { otype = -1; } + return(otype); +} + +/** + \brief Convert from PseudoObject OID to RegionNodeDataType Enumeration. + \returns BT value on success, -1 if no match + \param OID PseudoObject OID (based on EMF+ manual chapter number. ) + + Only OIDs that map to RNDT's are supported. +*/ + +int U_OID_To_RNDT(uint32_t OID){ + int otype; + if( OID==U_PMF_REGIONNODECHILDNODES_OID ){ otype = U_RNDT_Kids; } /* there are 5 types, which must be specified separately */ + else if(OID==U_PMF_RECTF_OID ){ otype = U_RNDT_Rect; } + else if(OID==U_PMF_REGIONNODEPATH_OID ){ otype = U_RNDT_Path; } + else { otype = -1; } + return(otype); +} + +/** + \brief Append data to an U_OBJ_ACCUM structure. + \param oa pointer to the U_OBJ_ACCUM structure + \param data data to add + \param size bytes in data + \param Type object type + \param Id Object ID + \returns 0 on success, !0 on error. -1 on Type change, -2 on Id change + + Safe to test for Id, Type changes by calling with size=0. +*/ +int U_OA_append(U_OBJ_ACCUM *oa, const char *data, int size, int Type, int Id){ + int tail; + if(!oa)return(2); + if(oa->used){ + if(oa->Type != Type)return(-1); + if(oa->Id != Id)return(-2); + } + tail = oa->used; + if(oa->used + size >= oa->space){ + oa->space += size; + char *newaccum = (char *) realloc(oa->accum, oa->space); + if(!newaccum){ + oa->space -= size; /* put it back the way it was */ + return(1); + } + oa->accum = newaccum; + } + memcpy(oa->accum + tail,data,size); + oa->used += size; + oa->Type = Type; + oa->Id = Id; + return(0); +} + + +/** + \brief Clear an U_OBJ_ACCUM structure. Accumulated storage is retained. + \param oa pointer to the U_OBJ_ACCUM structure + \returns 0 on success, !0 on error. +*/ +int U_OA_clear(U_OBJ_ACCUM *oa){ + if(!oa)return(2); + oa->used=0; + /* Type and Id may be ignored as they are reset on the first append */ + return(0); +} + +/** + \brief Release an U_OBJ_ACCUM structure. Accumulated storage is free'd. + \param oa pointer to the U_OBJ_ACCUM structure + \returns 0 on success, !0 on error. +*/ +int U_OA_release(U_OBJ_ACCUM *oa){ + if(!oa)return(2); + oa->used=0; + oa->space = 0; + if(oa->accum)free(oa->accum); + oa->accum=NULL; + return(0); +} + +/** + \brief Create and set an U_PSEUDO_OBJ + \returns pointer to the U_PSEUDO_OBJ, NULL on error + \param Data Data to copy into the PseudoObject's data. If NULL, space is allocated, but is cleared instead of filled. + \param Size Number of bytes to allocate for Data (may be >Use if padding is present) + \param Use Number of data bytes in Data (whether or not Data is actually copied) + \param Type Type numbers are from manual section: 1.2.3.47 -> 0x01020347 + + If Data is NULL and Size is 0 an empty PseudoObject is created. One byte of storage + is allocated for Data, Size is set to 1, and Used to 0. + + If Data is NULL and Size is !0 a zero filled PseudoObject is created. + + If Data is !Null and Size is !0 a data filled PseudoObject is created. +*/ +U_PSEUDO_OBJ *U_PO_create(char *Data, size_t Size, size_t Use, uint32_t Type){ + if(Use>Size)return(NULL); + size_t tSize = (Size ? Size : 1); + U_PSEUDO_OBJ *po = (U_PSEUDO_OBJ *)malloc(sizeof(U_PSEUDO_OBJ)); + if(po){ + po->Data = malloc(tSize); + if(po->Data){ + po->Size = tSize; + po->Used = Use; + po->Type = Type; + if(Data){ memcpy(po->Data, Data, Use); } /* if Use < Size uninitialized bytes will be present! */ + else { memset(po->Data, 0, tSize); } + } + else { + free(po); + po=NULL; + } + } + return(po); +} + +/** + \brief Append data to a U_PSEUDO_OBJ object and return it + \returns pointer to the U_PSEUDO_OBJ object, NULL on error + \param po PseudoObject to append to. Cannot be NULL. + \param Data Data to copy into the PseudoObject's data. If NULL, space is allocated (if necessary) and cleared instead of filled. + \param Size Number of data bytes in Data +*/ +U_PSEUDO_OBJ *U_PO_append(U_PSEUDO_OBJ *po, const char *Data, size_t Size){ + /* po cannot be NULL,as in U_PO_po_append(), because there would be no way to determine the TYPE of the resulting PO */ + if(po){ + if(!po->Data || po->Used + Size > po->Size){ + po->Size = po->Used + Size; + char *newData = realloc(po->Data, po->Size); + if(!newData){ + po->Size -= Size; /* put it back the way it was*/ + po=NULL; /* skip the rest of the actions, does not affect po in caller */ + } + else { + po->Data = newData; + } + } + if(po){ /* po->Data ready to append new data */ + if(Data){ memcpy(po->Data + po->Used, Data, Size); } + else { memset(po->Data + po->Used, 0, Size); } + po->Used += Size; + } + } + return(po); +} + +/** + \brief Append data to a U_PSEUDO_OBJ object and return it + \returns pointer to the U_PSEUDO_OBJ object, NULL on error + \param po PseudoObject to append to. May be NULL. + \param Src PseudoObject to append. + \param StripE Set: leading Elements in Src->Data is not copied, Clear: it is copied. +*/ +U_PSEUDO_OBJ *U_PO_po_append(U_PSEUDO_OBJ *po, U_PSEUDO_OBJ *Src, int StripE){ + if(!Src){ return(NULL); } + if((StripE && (Src->Used == 4)) || !Src->Used){ return(po); } /* appending nothing is not an error */ + char *Data = Src->Data; + size_t Size = Src->Used; /* append only what is used */ + U_PSEUDO_OBJ *ipo = po; + if(StripE){ Size -= 4; } + if(!ipo){ + ipo = U_PO_create(NULL, 0, 0, Src->Type); /* create an empty pseudoobject */ + } + if(ipo){ + if(!ipo->Data || ipo->Used + Size > ipo->Size){ + ipo->Size = ipo->Used + Size; + char *newData = realloc(ipo->Data, ipo->Size); + if(!newData){ + if(ipo != po)U_PO_free(&ipo); + } + else { + ipo->Data = newData; + } + } + if(ipo){ + if(Data){ + if(StripE){ memcpy(ipo->Data + ipo->Used, Data + 4, Size); } /* Size is already 4 less, skip the leading Elements value */ + else { memcpy(ipo->Data + ipo->Used, Data, Size); } /* copy everything */ + } + else { memset(ipo->Data + ipo->Used, 0, Size); } /* set everything */ + ipo->Used += Size; + } + } + return(ipo); +} + +/** + \brief Free an U_PSEUDO_OBJ structure. All associated memory is released. + \param po Address of a pointer to the U_PSEUDO_OBJ structure, Pointer is set to NULL. + \returns 1 on success, 0 on error. +*/ +int U_PO_free(U_PSEUDO_OBJ **po){ + if(!po)return(0); + if(!*po)return(1); + if((*po)->Data)free((*po)->Data); + free(*po); + *po=NULL; + return(1); +} + +/** \brief create a PseudoObject with data in the correct byte order for an EMF+ file. + \returns The PseudoObject on success, NULL on error. + + \param Type the type of the PseudoObject that is created. Allowed values are in U_PID_Values. + \param List an array of U_SERIAL_DESC structures containing the data to store. + + The U_PMF_SERIAL_set() function should not ever be called directly by end user code. + + Each U_SERIAL_DESC element in List consists of Data fields and a description of that data. List is terminated + by the first U_SERIAL_DESC element having a TE value of U_XX. + + Data fields: an array of a basic type of Units bytes repeated Reps times with the target byte order + described in TE. + + Ptrs: Address of the first byte of the data fields. + + Units: Number of bytes of in each data field unit + + Reps: Number of repeats of the unit in data fields. + If a Ptr is NULL, and Units*Reps is not zero, then Units*Reps 0x00 bytes are stored. + If a Ptr is NULL, and Units*Reps is zero, this U_SERIAL_DESC is ignored. + if a Ptr is NOT NULL, and Units * Reps is not zero, then the data is stored in the indicated byte order. + If a Ptr is NOT NULL, and Units or Reps is zero an error is signaled. + + TE: (Target Endian) the byte order in which to store each unit of a data field as defined in U_Endian. + Byte swapping is only enabled when Units is 2 or 4. In addition to the byte order values U_XE, U_LE, + and U_BE, and the array terminator U_XX, the value may also be U_RP. U_RP means there is only a + single unit in the data fields, but it is to be copied to the target Reps times. That is, the data + was passed in with a form of run length encoding. + + Creates an empty PseudoObject if all pointers are NULL and all sizes are zero. + */ +U_PSEUDO_OBJ *U_PMF_SERIAL_set(uint32_t Type, const U_SERIAL_DESC *List){ + U_PSEUDO_OBJ *po=NULL; + size_t Total=0; + size_t FSize; + char *cptr; + char *hptr; + const U_SERIAL_DESC *lptr; + if(!List)return(NULL); + for(lptr=List; lptr->TE != U_XX; lptr++){ + FSize = lptr->Units * lptr->Reps; + if(!FSize && lptr->Ptr)return(po); + Total += FSize; + } + po = U_PO_create(NULL, Total, Total, Type); + if(po){ + cptr = po->Data; + for(lptr=List; lptr->TE != U_XX; lptr++){ + FSize = lptr->Units * lptr->Reps; + if(FSize){ /* Ptr is not NULL, that would have been detected already */ + hptr = cptr; + if(lptr->TE & U_RP){ U_PMF_REPCPY_DSTSHIFT(&cptr, lptr->Ptr, lptr->Units, lptr->Reps); } + else { U_PMF_MEMCPY_DSTSHIFT(&cptr, lptr->Ptr, FSize); } + if(((lptr->TE & U_LE) && U_IS_BE) || ((lptr->TE & U_BE) && U_IS_LE)){ + if(lptr->Units==2){ U_swap2(hptr,lptr->Reps); } + else if(lptr->Units==4){ U_swap4(hptr,lptr->Reps); } + } + } + } + } + return(po); +} + +/** + \brief Create U_DPSEUDO_OBJ's for the Points and Types of a path + \param Elements Number of elements in Points. May be zero, which creates an empty path. + \param Points Array of U_PMF_POINTF values. + \param First Apply to first point, unsigned byte, lower 4 bits hold the PathPointType flag upper 4 bits hold the PathPointType enumeration. Must have U_PPT_Start set. + \param Others Apply to all other points, unsigned byte, lower 4 bits hold the PathPointType flag upper 4 bits hold the PathPointType enumeration. Must have U_PPT_Line or U_PPT_Bezier set. + \returns pointer to the DU_PSEUDO_OBJ object, NULL on error +*/ +U_DPSEUDO_OBJ *U_PATH_create(int Elements, const U_PMF_POINTF *Points, uint8_t First, uint8_t Others){ + if(Elements){ + if(!Points){ return(NULL); } + if( (First & U_PPT_MASK) != U_PPT_Start ){ return(NULL); } + if(!(Others & U_PPT_Bezier)){ return(NULL); } /* will pass if either line or bezier is set */ + } + + U_DPSEUDO_OBJ *Path = (U_DPSEUDO_OBJ *)calloc(sizeof(U_DPSEUDO_OBJ),1); /* make poTypes and poPoints NULL */ + const U_SERIAL_DESC List[] = { {NULL,0,0,U_XX} }; + if(Path){ + Path->Elements = Elements; + Path->poPoints = U_PMF_SERIAL_set(U_PMF_RAW_OID, List); /* Empty PO to hold points as raw data */ + if(!Elements){ + Path->poTypes = U_PMF_SERIAL_set(U_PMF_RAW_OID, List); /* Empty PO to hold types as raw data */ + } + else { + Path->poPoints = U_PO_append(Path->poPoints, (char *)Points, Elements*sizeof(U_PMF_POINTF)); + if(Path->poPoints){ + U_PSEUDO_OBJ *tpo = U_PMF_PATHPOINTTYPE_set2(Elements, First | U_PPT_Start, Others); /* PO holding types, has leading Elements value */ + Path->poTypes = U_PO_po_append(NULL, tpo, U_PMF_DROP_ELEMENTS); /* remove the leading Elements value*/ + U_PO_free(&tpo); + if(!Path->poTypes){ U_PO_free(&Path->poPoints); } + } + if(!Path->poPoints){ U_DPO_free(&Path); } + } + } + return(Path); +} + +/** + \brief Free U_DPSEUDO_OBJ's + \returns 1 on success, 0 on error. +*/ +int U_DPO_free(U_DPSEUDO_OBJ **dpo){ + if(!dpo){ return(0); } + if(!*dpo){ return(1); } + U_DPSEUDO_OBJ *kpo = *dpo; + if(kpo->poPoints){ U_PO_free(&kpo->poPoints); } + if(kpo->poTypes){ U_PO_free(&kpo->poTypes); } + free(*dpo); + *dpo=NULL; + return(1); +} + +/** + \brief Clear U_DPSEUDO_OBJ's. Memory is retained, Elements and Used values are set to 0. + \returns 1 on success, 0 on error. + + It is much more efficient to clear a DPO and reuse it than to free that DPO and create another. +*/ +int U_DPO_clear(U_DPSEUDO_OBJ *dpo){ + if(!dpo){ return(0); } + if(dpo->poPoints){ dpo->poPoints->Used = 0; } + if(dpo->poTypes){ dpo->poTypes->Used = 0; } + dpo->Elements = 0; + return(1); +} + +/** + \brief Append a "moveto" point to a path + \param Path Address of a DoublePseudoObject holding the path to append to. + \param Point Point to move to. + \param Flags Flags may be (U_PTP_None, U_PTP_DashMode, U_PTP_PathMarker, U_PTP_NoBit, U_PTP_CloseSubpath) + \returns 1 on success, 0 on error. +*/ +int U_PATH_moveto(U_DPSEUDO_OBJ *Path, U_PMF_POINTF Point, uint8_t Flags){ + if(!Path){ return(0); } + U_PSEUDO_OBJ *tpo; + U_PSEUDO_OBJ *tpo2; + uint8_t Type = (Flags & U_PTP_NotClose) | U_PPT_Start; + + tpo = U_PMF_POINTF_set(1, &Point); + if(!tpo){ return(0); } + tpo2 = U_PO_po_append(Path->poPoints, tpo, U_PMF_DROP_ELEMENTS); + U_PO_free(&tpo); + if(!tpo2)return(0); + Path->poPoints = tpo2; + + + tpo = U_PMF_PATHPOINTTYPE_set(1, &Type); + if(!tpo){ return(0); } + tpo2= U_PO_po_append(Path->poTypes, tpo, U_PMF_DROP_ELEMENTS); + U_PO_free(&tpo); + if(!tpo2)return(0); + Path->poTypes = tpo2; + + Path->Elements++; + return(1); +} + +/** + \brief Append a "lineto" point to a path + \param Path Address of a DoublePseudoObject holding the path to append to. + \param Point U_PMF_POINTF point to draw to. + \param Flags Flags may be (U_PTP_None, U_PTP_DashMode, U_PTP_PathMarker, U_PTP_NoBit, U_PTP_CloseSubpath) + \returns 1 on success, 0 on error. +*/ +int U_PATH_lineto(U_DPSEUDO_OBJ *Path, U_PMF_POINTF Point, uint8_t Flags){ + if(!Path || !Path->Elements){ return(0); } /* must be at least one point to extend from */ + if(Path->poTypes->Data[Path->Elements - 1] & U_PTP_CloseSubpath){ return(0); } /* cannot extend a closed subpath */ + U_PSEUDO_OBJ *tpo; + U_PSEUDO_OBJ *tpo2; + uint8_t Type = (Flags & U_PTP_NotClose) | U_PPT_Line; + tpo = U_PMF_POINTF_set(1, &Point); + if(!tpo){ return(0); } + tpo2 = U_PO_po_append(Path->poPoints, tpo, U_PMF_DROP_ELEMENTS); + U_PO_free(&tpo); + if(!tpo2)return(0); + Path->poPoints = tpo2; + + + tpo = U_PMF_PATHPOINTTYPE_set(1, &Type); + if(!tpo){ return(0); } + tpo2 = U_PO_po_append(Path->poTypes, tpo, U_PMF_DROP_ELEMENTS); + U_PO_free(&tpo); + if(!tpo2)return(0); + Path->poTypes = tpo2; + + Path->Elements++; + return(1); +} + +/** + \brief Set the closepath bit in the last point + \param Path Address of a DoublePseudoObject holding the path to act upon. + \returns 1 on success, 0 on error. +*/ +int U_PATH_closepath(U_DPSEUDO_OBJ *Path){ + if(!Path || !Path->poTypes){ return(0); } + uint32_t Elements = Path->Elements; + uint8_t *Type = (uint8_t *)(Path->poTypes->Data) + Elements - 1; + if(*Type & U_PPT_Start){ return(0); } /* single point closed path makes no sense */ + *Type = *Type | U_PTP_CloseSubpath; + return(1); +} + +/** + \brief Append a "polylineto" set of point to a path + \param Path Address of a DoublePseudoObject holding the path to append to. + \param Elements number of Points and Flags + \param Points Line points. + \param Flags Flags (U_PTP_None, U_PTP_DashMode, U_PTP_PathMarker, U_PTP_NoBit, but NOT U_PTP_CloseSubpath) + \param StartSeg If set, use U_PPT_Start PathPointType enumeration for first point, otherwise use U_PPT_Line. + \returns 1 on success, 0 on error. +*/ +int U_PATH_polylineto(U_DPSEUDO_OBJ *Path, uint32_t Elements, const U_PMF_POINTF *Points, uint8_t Flags, uint8_t StartSeg){ + if(!Path || !Points){ return(0); } + if(!Elements){ return(1); } /* harmless - do nothing */ + U_PSEUDO_OBJ *tpo; + U_PSEUDO_OBJ *tpo2; + uint8_t First, Others; + + tpo = U_PMF_POINTF_set(Elements, Points); + tpo2 = U_PO_po_append(Path->poPoints, tpo, U_PMF_DROP_ELEMENTS); + U_PO_free(&tpo); + if(!tpo2)return(0); + Path->poPoints = tpo2; + + if(StartSeg){ First = (Flags & U_PTP_NotClose) | U_PPT_Start; } + else { First = (Flags & U_PTP_NotClose) | U_PPT_Line; } + Others = (Flags & U_PTP_NotClose) | U_PPT_Line; + tpo = U_PMF_PATHPOINTTYPE_set2(Elements, First, Others); + if(!tpo){ return(0); } + tpo2 = U_PO_po_append(Path->poTypes, tpo, U_PMF_DROP_ELEMENTS); + U_PO_free(&tpo); + if(!tpo2)return(0); + Path->poTypes = tpo2; + + Path->Elements += Elements; + return(1); +} + + +/** + \brief Append a "polybezierto" set of point to a path + \param Path Address of a DoublePseudoObject holding the path to append to. + \param Elements number of Points + \param Points Bezier points. Optional starting point, then N sets of 3, example: [P1] (Q12A Q12B P2) (Q23A Q23B P3). + \param Flags Flags (U_PTP_None, U_PTP_DashMode, U_PTP_PathMarker, U_PTP_NoBit, but NOT U_PTP_CloseSubpath) + \param StartSeg If set, use U_PPT_Start PathPointType enumeration for first point, otherwise use U_PPT_Bezier. + \returns 1 on success, 0 on error. + + If Start is set Elements must be 1 + multiple of 3. Ie, P1 Q12A Q12B P2 Q23A Q23B P3 + + If Start is clear Elements must be a multiple of 3. Ie, (P1, already in path) Q12A Q12B P2 Q23A Q23B P3 +*/ +int U_PATH_polybezierto(U_DPSEUDO_OBJ *Path, uint32_t Elements, const U_PMF_POINTF *Points, uint8_t Flags, uint8_t StartSeg){ + if(!Path || !Points){ return(0); } + if(!Elements){ + if(StartSeg){ return(0); } /* cannot have both a NEW segment and ZERO points */ + else{ return(1); } /* harmless - do nothing */ + } + if(StartSeg && ((Elements - 1) % 3)){ return(0); } /* new segment must be 1 + N*3 points */ + if(!StartSeg && (Elements % 3)){ return(0); } /* extend segment must be N*3 points */ + U_PSEUDO_OBJ *tpo; + U_PSEUDO_OBJ *tpo2; + uint8_t First, Others; + + tpo = U_PMF_POINTF_set(Elements, Points); + tpo2 = U_PO_po_append(Path->poPoints, tpo, U_PMF_DROP_ELEMENTS); + U_PO_free(&tpo); + if(!tpo2)return(0); + Path->poPoints = tpo2; + + if(StartSeg){ First = (Flags & U_PTP_NotClose) | U_PPT_Start; } + else { First = (Flags & U_PTP_NotClose) | U_PPT_Bezier; } + Others = (Flags & U_PTP_NotClose) | U_PPT_Bezier; + tpo = U_PMF_PATHPOINTTYPE_set2(Elements, First, Others); + if(!tpo){ return(0); } + tpo2 = U_PO_po_append(Path->poTypes, tpo, U_PMF_DROP_ELEMENTS); + U_PO_free(&tpo); + if(!tpo2)return(0); + Path->poTypes = tpo2; + + Path->Elements += Elements; + return(1); +} + +/** + \brief Append a "polygon" set of points to a path. + \param Path Address of a DoublePseudoObject holding the path to append to. + \param Elements number of Points and Flags + \param Points Line points. + \param Flags Flags (U_PTP_None, U_PTP_DashMode, U_PTP_PathMarker, U_PTP_NoBit, but NOT U_PTP_CloseSubpath) + \returns 1 on success, 0 on error. +*/ +int U_PATH_polygon(U_DPSEUDO_OBJ *Path, uint32_t Elements, const U_PMF_POINTF *Points, uint8_t Flags){ + int status = U_PATH_polylineto(Path, Elements, Points, Flags, U_SEG_NEW); + if(status){ + status = U_PATH_closepath(Path); + } + return(status); +} + +//! \cond +// These are not exposed in the API +/* Parameterized Ellipse coordinates */ +U_PMF_POINTF U_eparam(U_FLOAT a, U_FLOAT b, U_PMF_POINTF *center, double Ang, double Theta){ + U_PMF_POINTF point; + point.X = center->X + a*cos(Theta)*cos(Ang) - b*sin(Theta)*sin(Ang); + point.Y = center->Y + a*sin(Theta)*cos(Ang) + b*cos(Theta)*sin(Ang); + return(point); +} + +/* Parameterized Ellipse derivative */ +U_PMF_POINTF U_eparam2(U_FLOAT a, U_FLOAT b, double Ang, double Theta){ + U_PMF_POINTF point; + point.X = -a*cos(Theta)*sin(Ang) - b*sin(Theta)*cos(Ang); + point.Y = -a*sin(Theta)*sin(Ang) + b*cos(Theta)*cos(Ang); + return(point); +} + +double U_aparam(double Ang1, double Ang2){ + double Alpha; + double t2; + t2 = tan((Ang2 - Ang1)/2.0); + t2 *= t2; + Alpha = sin(Ang2 - Ang1) * (sqrt(4 + 3*t2) -1.0)/3.0; + return(Alpha); +} + +/* Parameterized Bezier point Q1 or Q2 derivative */ +U_PMF_POINTF U_qparam(double Alpha, double a, double b, U_PMF_POINTF *Point, double Ang, double Theta, int mode){ + U_PMF_POINTF Q, Prime; + Prime = U_eparam2(a,b,Ang,Theta); + if(mode==1){ /* Q1, anything else is Q2*/ + Q.X = Point->X + Alpha * Prime.X; + Q.Y = Point->Y + Alpha * Prime.Y; + } + else { + Q.X = Point->X - Alpha * Prime.X; + Q.Y = Point->Y - Alpha * Prime.Y; + } + return(Q); +} +//! \endcond + +/** + \brief Append an "arcto" set of points to a path (Bezier points are calculated, and these are appended + \param Path Address of a pointer to the U_PSEUDO_OBJ that holds points + \param Start Start angle, >=0.0, degrees clockwise from 3:00 + \param Sweep Sweep angle, -360<= angle <=360, degrees clockwise from Start + \param Rot Rotation angle to apply to coordinate system (Start and Rect), positive is degrees clockwise + \param Rect U_PMF_RECTF that defines the bounding rectangle. + \param Flags Flags (U_PTP_None, U_PTP_DashMode, U_PTP_PathMarker, U_PTP_NoBit, but NOT U_PTP_CloseSubpath) + \param StartSeg If set, the arc starts a new segment, if clear, continue the existing segment. Starting a new segment does not automatically apply U_PATH_closepath to the existing path. + \returns 1 on success, 0 on error. + + Based on Luc Maisonobe's work, http://www.spaceroots.org/documents/ellipse/ +*/ +int U_PATH_arcto(U_DPSEUDO_OBJ *Path, U_FLOAT Start, U_FLOAT Sweep, U_FLOAT Rot, U_PMF_RECTF *Rect, uint8_t Flags, int StartSeg){ + U_PMF_POINTF Bz[3]; + U_PMF_POINTF Center; + U_PMF_POINTF P1,P2; + double a, b; + int done = 0; + int fpoint = 0; + double L1, L2; /* These are degrees CounterClockwise from 3:00 */ + double Ang1, Ang2; /* These are parametric angles, derived from L1, L2*/ + double Alpha; /* Dimensionless number used for Q1, Q2 */ + double Theta; /* Rot in radians */ + double Slop; /* do not let rounding errors cause spurious end points */ + if(!Path){ return(0); } + if((Sweep > 360.0) || (Sweep < -360.0)){ return(0); } + /* Start should be between 0 and 360 degrees, but it does not really matter because sin, and cos will accept anything */ + /* the sign on Sweep and Start is correct bacause LM's derivation has y positive up, but GDI+ has y positive down. */ + a = Rect->Width/2.0; + b = Rect->Height/2.0; + if(!a || !b){ return(0); } + Center.X = Rect->X + a; + Center.Y = Rect->Y + b; + /* convert to radians */ + Start = (2.0 * U_PI * Start)/360.0; + Sweep = (2.0 * U_PI * Sweep)/360.0; + Theta = (2.0 * U_PI * Rot )/360.0; + Slop = Sweep/100000.0; + L1 = Start; + + while(!done){ + if(Sweep < 0){ + L2 = L1 - U_PI/2.0; + if(L2 <= Sweep + Start - Slop){ L2 = Sweep + Start; done = 1; } + else {done = 0; } + } + else { + L2 = L1 + U_PI/2.0; + if(L2 >= Sweep + Start + Slop){ L2 = Sweep + Start; done = 1; } + else {done = 0; } + } + Ang1 = atan2(sin(L1)/b, cos(L1)/a); + Ang2 = atan2(sin(L2)/b, cos(L2)/a); + Alpha = U_aparam(Ang1, Ang2); + P1 = U_eparam(a, b, &Center, Ang1, Theta); /* P1 */ + P2 = U_eparam(a, b, &Center, Ang2, Theta); /* P2 */ + Bz[0] = U_qparam(Alpha, a, b, &P1, Ang1, Theta, 1); /* Q1 */ + Bz[1] = U_qparam(Alpha, a, b, &P2, Ang2, Theta, 2); /* Q2 */ + Bz[2] = P2; + if(!fpoint){ + if(StartSeg){ U_PATH_moveto(Path, P1, Flags); } + else { U_PATH_lineto(Path, P1, Flags); } + fpoint = 1; + } + U_PATH_polybezierto(Path, 3, Bz, Flags, U_SEG_OLD ); + L1 = L2; + } + return(1); +} + +/** + \brief Allocate and construct an array of U_PMF_POINTF objects which have been subjected to a U_XFORM + \returns pointer to an array of U_PMF_POINTF structures. + \param points pointer to the source U_PMF_POINTF structures + \param count number of members in points + \param xform U_XFORM to apply + +*/ +U_PMF_POINTF *pointfs_transform(U_PMF_POINTF *points, int count, U_XFORM xform){ + U_PMF_POINTF *newpts=NULL;; + int i; + float X,Y; + newpts = (U_PMF_POINTF *) malloc(count * sizeof(U_PMF_POINTF)); + if(newpts){ + for(i=0; i<count; i++){ + X = points[i].X; + Y = points[i].Y; + newpts[i].X = U_ROUND(X * xform.eM11 + Y * xform.eM21 + xform.eDx); + newpts[i].Y = U_ROUND(X * xform.eM12 + Y * xform.eM22 + xform.eDy); + } + } + return(newpts); +} + +/** + \brief Allocate and construct an array of U_PMF_RECTF objects which have been subjected to a U_XFORM + \returns pointer to an array of U_PMF_RECTF structures. + \param Rects pointer to the source U_PMF_RECTF structures + \param Count number of members in Rects + \param Xform U_XFORM to apply. Rotation is ignored, only translation is applied. + +*/ +U_PMF_RECTF *rectfs_transform(U_PMF_RECTF *Rects, int Count, U_XFORM Xform){ + U_PMF_RECTF *newRects; + int i; + newRects = (U_PMF_RECTF *) malloc(Count * sizeof(U_PMF_RECTF)); + if(newRects){ + for(i=0; i<Count; i++){ + newRects[i].X = U_ROUND(Rects[i].X + Xform.eDx); + newRects[i].Y = U_ROUND(Rects[i].Y + Xform.eDy); + newRects[i].Width = U_ROUND(Rects[i].Width); + newRects[i].Height = U_ROUND(Rects[i].Height); + } + } + return(newRects); +} + +/** + \brief Utility function calculate the transformation matrix needed to make a gradient run precisely corner to corner of a rectangle + \param Angle Rotation in degrees clockwise of the gradient. 0 is horizontal gradient. + \param w Width of the rectangle + \param h Height of the rectangle + \param x X coordinate of upper left corner of rectangle + \param y Y coordinate of upper left corner of rectangle + \param Periods Periods of gradient corner to corner. 1.0 is one, corner to corner. + \return Transformation matrix. All values are zero if Periods, w, or h are less than or equal to zero. +*/ +U_PMF_TRANSFORMMATRIX tm_for_gradrect(U_FLOAT Angle, U_FLOAT w, U_FLOAT h, U_FLOAT x, U_FLOAT y, U_FLOAT Periods){ +//! \cond +#define CLOSE_TO_IS_REALLY_ZERO(A) ((A) > 1.0e-10 || (A) < -1.0e-10 ? (A) : 0.0) //! \hideinitializer +//! \endcond + U_PMF_TRANSFORMMATRIX tm; + double dang = Angle * 2*U_PI /360.0; + double scale; + double cd,sd; + if((Periods <=0.0) || (w <= 0.0) || (h <= 0.0)){ + tm.m11 = tm.m12 = tm.m21 = tm.m22 = tm.dX = tm.dY = 0.0; + } + else { + /* + scale is gradient period divided by w + The scale value sets the gradient period to match exactly with the inscribed (w,h) rectangle + in the direction specified by the angle. + The numberator of scale is the max of the four dot product values of the rotated X basis unit vector with (w,h), + with each of the vectors {w,h}, {-w,h}, {-w,-h}, {w,h}. Those vectors run from each corner in turn + to the opposite corner. The one most parallel to the rotated unit vector will have both terms positive. + + Trig results like cos(pi/2) are not stable between platforms due to minor differences in the + implementation. Detect these and make them zero, which then allows binary comparison of output files. + Otherwise the binary comparisons between platforms would fail because of a bunch of insignificant digits. + */ + cd = CLOSE_TO_IS_REALLY_ZERO(cos(dang)); + sd = CLOSE_TO_IS_REALLY_ZERO(sin(dang)); + scale = (w*fabs(cd) + h*fabs(sd))/(w*Periods); + tm.m11 = scale * cd; + tm.m12 = -scale * sd; + tm.m21 = scale * sd; + tm.m22 = scale * cd; + /* offset is to one corner of the square, depending on which quadrant the rotation selects. */ + if(cos(dang)>=0){ + tm.dX = x; + if(sin(dang)>=0){tm.dY = y + h; } // LL corner + else { tm.dY = y; } // UL corner + } + else { + tm.dX = x + w; + if(sin(dang)>=0){ tm.dY = y + h; } // LR corner + else { tm.dY = y; } // UR corner + } + } + return tm; +#undef CLOSE_TO_IS_REALLY_ZERO +} +/** + \brief Create a U_PSEUDO_OBJ containing a U_PMR_FILLPATH and U_PMR_DRAWPATH records. + \returns pointer to U_PSEUDO_OBJ or NULL on error. + \param PathID U_PMF_PATH object in the EMF+ object table (0-63, inclusive) + \param PenID U_PMF_PEN object in the EMF+ object table (0-63, inclusive) + \param BrushID U_PSEUDO_OBJ containing a U_PMF_ARGB or a U_PMF_4NUM. Color or U_PMF_BRUSH object in the EMF+ object table (0-63, inclusive) +*/ +U_PSEUDO_OBJ *U_PMR_drawfill(uint32_t PathID, uint32_t PenID, const U_PSEUDO_OBJ *BrushID){ + U_PSEUDO_OBJ *po = U_PMR_FILLPATH_set(PathID, BrushID); + if(po){ + U_PSEUDO_OBJ *tpo = U_PMR_DRAWPATH_set(PathID, PenID); + po = U_PO_po_append(po, tpo, U_PMF_KEEP_ELEMENTS); + U_PO_free(&tpo); + } + return(po); +} + + + +/** + \brief Extract a single data field from a source. + \returns 1 on success, 0 on error. + \param Src where the data is coming from. It is incremented by the number of bytes retrieved. + \param Dst where the data will be stored. This must either be NULL (in which case the Src + is advanced and nothing is stored, or it must be allocated to Reps * Units bytes!!!! + \param Units number of bytes in each unit of the data field + \param Reps number of repeats of units in the data field. + If a Ptr is NULL, then Units*Reps 0 bytes are stored. + If a Ptr is NOT NULL, and Units or Reps, is zero an error is signaled. + If a Ptr is NULL and Units*Reps is 0, nothing happens. + \param SE logical (Source Endian). Only relevant for Sizes of 2 or 4 + Indicates when Bytes may need to be rearranged when they are retrieved. + U_XE no change (this is used when the data has already been set to the proper orientation or it is not known) + U_LE source is Little Endian + U_BE source is Big Endian. + U_XX error + +*/ +int U_PMF_SERIAL_get(const char **Src, void *Dst, size_t Units, size_t Reps, int SE){ + if(!Src || !*Src || SE == U_XX){ return(0); } + U_PMF_MEMCPY_SRCSHIFT(Dst, Src, Units * Reps); + if(!Dst){ return(1); } /* "fake" get, no data was retrieved, so we are done */ + if(SE == U_XE){ return(1); } + if(SE == U_LE && U_IS_LE){ return(1); } + if(SE == U_BE && U_IS_BE){ return(1); } + /* need to swap */ + if( Units==2){ U_swap2(Dst,Reps); } + else if(Units==4){ U_swap4(Dst,Reps); } + return(1); +} + +/** + \brief Conditionally extract an array of data from a source, allocating space to hold it. + \returns 1 on success, 0 on error. + \param Src where the data is coming from. It is incremented by the number of bytes retrieved. + \param Dst Caller must free. Where the pointer to the data will be stored. Reps * Units bytes will be allocated, + \param Units number of bytes in each unit of the data field + \param Reps number of repeats of units in the data field. + If a Ptr is NULL, then Units*Reps 0 bytes are stored. + If a Ptr is NOT NULL, and Units or Reps, is zero an error is signaled. + If a Ptr is NULL and Units*Reps is 0, nothing happens. + \param SE logical (Source Endian). Only relevant for Sizes of 2 or 4 + Indicates when Bytes may need to be rearranged when they are retrieved. + U_XE no change (this is used when the data has already been set to the proper orientation or it is not known) + U_LE source is Little Endian + U_BE source is Big Endian. + U_XX error + \param Cond Store the data into *Dst if true, set *Dst to NULL otherwise. + +*/ +int U_PMF_SERIAL_array_copy_get(const char **Src, void **Dst, size_t Units, size_t Reps, int SE, int Cond){ + if(!Src || !*Src || !Dst || SE == U_XX){ return(0); } + if(!Cond){ + *Src += Units * Reps; + *Dst = NULL; + return(1); + } + *Dst = malloc(Units * Reps); + if(!*Dst){ return(1); } /* "fake" get, no data was retrieved, so we are done */ + U_PMF_MEMCPY_SRCSHIFT(*Dst, Src, Units * Reps); + if(SE == U_XE){ return(1); } + if(SE == U_LE && U_IS_LE){ return(1); } + if(SE == U_BE && U_IS_BE){ return(1); } + /* need to swap */ + if( Units==2){ U_swap2(*Dst,Reps); } + else if(Units==4){ U_swap4(*Dst,Reps); } + return(1); +} + + + +/** + \brief Calculate the length in bytes of a relative path object composed of U_PMF_INTEGER7 and U_PMF_INTER15 values + \return >=0 length == success, <0 error + \param contents Start of a relative path consisting of int7 and int15 X,Y pairs. + \param Elements number of relative X,Y pairs in the object +*/ +int U_PMF_LEN_REL715(const char *contents, int Elements){ + int length=0; + Elements *= 2; /* N pairs = 2N values */ + for( ; Elements; Elements--){ + /* X or Y value */ + if(*contents & U_TEST_INT7){ contents +=2; length +=2; } //int15 + else { contents +=1; length +=1; } //int7 + } + return(length); +} + +/** + \brief Calculate the length in bytes of objects which are a 4 byte Count followed by Count * float bytes + \return >=0 length == success, <0 error + Object types whose size may be derived with this function are: + U_PMF_COMPOUNDLINEDATA + U_PMF_DASHEDLINEDATA +*/ +int U_PMF_LEN_FLOATDATA(const char *contents){ + int Size; + U_PMF_SERIAL_get(&contents, &Size, 4, 1, U_LE); + Size = 4*Size + 4; + return(Size); +} + +/** + \brief Calculate the length in bytes of objects which are a 4 byte count followed by count bytes + \return >=0 length == success, <0 error + Object types whose size may be derived with this function are: + U_PMF_BOUNDARYPATHDATA + U_PMF_BOUNDARYPOINTDATA + U_PMF_CUSTOMSTARTCAPDATA + U_PMF_PATH + U_PMF_LINEPATH + U_PMF_REGIONNODEPATH +*/ +int U_PMF_LEN_BYTEDATA(const char *contents){ + int Size; + U_PMF_SERIAL_get(&contents, &Size, 4, 1, U_LE); + Size += 4; + return(Size); +} + +/** + \brief Create a string containing the curly bracket form of the 16 byte GUID value + \return number of bytes in record, 0 on error + \param GUID pointer to the 16 unsigned bytes + \return string in curly bracket form. + http://msdn.microsoft.com/en-us/library/cc230316.aspx + + Text form is Data1-Data2-Data3-Data4, the first 3 are stored as little endian integers, the last as a string (big endian). +*/ +char *U_PMF_CURLYGUID_set(uint8_t *GUID){ + char *string=malloc(64); + if(string){ + sprintf(string,"{%2.2X%2.2X%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X}", + GUID[3],GUID[2],GUID[1],GUID[0], + GUID[5],GUID[4], + GUID[7],GUID[6], + GUID[8],GUID[9], + GUID[10],GUID[11],GUID[12],GUID[13],GUID[14],GUID[15] + ); + } + return(string); +} + +/** + \brief Identify a known curly GUID + \param string Curly GUID form. + \return EmageEffects Enumerator + + EMF+ manual 2.1.3.1, Microsoft name: ImageEffects Identifier +*/ +int U_PMF_KNOWNCURLYGUID_set(const char *string){ + int status; + if( !strcmp(string,"{633C80A4-1843-482B-9EF2-BE2834C5FDD4}")){ status = U_IEE_BlurEffectGuid; } + else if(!strcmp(string,"{D3A1DBE1-8EC4-4C17-9F4C-EA97AD1C343D}")){ status = U_IEE_BrightnessContrastEffectGuid; } + else if(!strcmp(string,"{537E597D-251E-48DA-9664-29CA496B70F8}")){ status = U_IEE_ColorBalanceEffectGuid; } + else if(!strcmp(string,"{DD6A0022-58E4-4A67-9D9B-D48EB881A53D}")){ status = U_IEE_ColorCurveEffectGuid; } + else if(!strcmp(string,"{A7CE72A9-0F7F-40D7-B3CC-D0C02D5C3212}")){ status = U_IEE_ColorLookupTableEffectGuid; } + else if(!strcmp(string,"{718F2615-7933-40E3-A511-5F68FE14DD74}")){ status = U_IEE_ColorMatrixEffectGuid; } + else if(!strcmp(string,"{8B2DD6C3-EB07-4D87-A5F0-7108E26A9C5F}")){ status = U_IEE_HueSaturationLightnessEffectGuid;} + else if(!strcmp(string,"{99C354EC-2A31-4F3A-8C34-17A803B33A25}")){ status = U_IEE_LevelsEffectGuid; } + else if(!strcmp(string,"{74D29D05-69A4-4266-9549-3CC52836B632}")){ status = U_IEE_RedEyeCorrectionEffectGuid; } + else if(!strcmp(string,"{63CBF3EE-C526-402C-8F71-62C540BF5142}")){ status = U_IEE_SharpenEffectGuid; } + else if(!strcmp(string,"{1077AF00-2848-4441-9489-44AD4C2D7A2C}")){ status = U_IEE_TintEffectGuid; } + else { status = U_IEE_Unknown; } + return(status); +} + +/** \brief Load a GUID from text format into EMF+ file binary format. + \param string Curly GUID as text, minus the barckets and dashes. + \return GUID in EMF+ file binary format. + + +This accepts a string that is 16 bytes long = 32 characters hex (no dash spaces or brackets) as text. +Text form is; Data1|Data2|Data3|Data4, first three are stored as little endian integers of 4,2,2 bytes, respectively, +last is stored like a string (big endian), after conversion from text hex to binary. + +This function is not normally called by end user code. +*/ +uint8_t *U_LOAD_GUID(char *string){ + uint32_t Data1,tData2,tData3,tByte; + uint16_t Data2,Data3; + char *Data4 = string + 16; + uint8_t *hold = malloc(16); + char *lf = (char *) hold; + int i; + if(hold){ + Data1=tData2=tData3=0; + if(3 != sscanf(string + 0,"%8X",&Data1) + + sscanf(string + 8,"%4X",&tData2) + + sscanf(string + 12,"%4X",&tData3)){ + free(hold); + hold = NULL; + goto bye; + } + Data2=tData2; + Data3=tData3; + U_PMF_MEMCPY_DSTSHIFT(&lf, &Data1, 4); + U_PMF_MEMCPY_DSTSHIFT(&lf, &Data2, 2); + U_PMF_MEMCPY_DSTSHIFT(&lf, &Data3, 2); + if(U_IS_BE){ /* these fields are stored little endian */ + U_swap4(hold,1); + U_swap2(hold+4,2); + } + /* remainder is converted byte by byte and stored in that order */ + for(i=0;i<8;i++,Data4+=2,lf++){ + if(1 != sscanf(Data4,"%2X",&tByte)){ + free(hold); + hold = NULL; + goto bye; + } + *lf=tByte; + } + } +bye: + return(hold); +} + +/** + \brief Generate the 16 byte form from OID of the ImageEffects Identifier + \param OID OID of the ImageEffects Identifier + \return pointer to 16 byte buffer holding the long GUID binary form, or NULL on error. + + EMF+ manual 2.1.3.1, Microsoft name: ImageEffects Identifier +*/ +uint8_t *U_OID_To_GUID(uint32_t OID){ + uint8_t *lf = NULL; + if( OID == U_PMF_IE_BLUR_OID ){ lf = U_LOAD_GUID("633C80A41843482B9EF2BE2834C5FDD4"); } + else if(OID == U_PMF_IE_BRIGHTNESSCONTRAST_OID ){ lf = U_LOAD_GUID("D3A1DBE18EC44C179F4CEA97AD1C343D"); } + else if(OID == U_PMF_IE_COLORBALANCE_OID ){ lf = U_LOAD_GUID("537E597D251E48DA966429CA496B70F8"); } + else if(OID == U_PMF_IE_COLORCURVE_OID ){ lf = U_LOAD_GUID("DD6A002258E44A679D9BD48EB881A53D"); } + else if(OID == U_PMF_IE_COLORLOOKUPTABLE_OID ){ lf = U_LOAD_GUID("A7CE72A90F7F40D7B3CCD0C02D5C3212"); } + else if(OID == U_PMF_IE_COLORMATRIX_OID ){ lf = U_LOAD_GUID("718F2615793340E3A5115F68FE14DD74"); } + else if(OID == U_PMF_IE_HUESATURATIONLIGHTNESS_OID){ lf = U_LOAD_GUID("8B2DD6C3EB074D87A5F07108E26A9C5F"); } + else if(OID == U_PMF_IE_LEVELS_OID ){ lf = U_LOAD_GUID("99C354EC2A314F3A8C3417A803B33A25"); } + else if(OID == U_PMF_IE_REDEYECORRECTION_OID ){ lf = U_LOAD_GUID("74D29D0569A4426695493CC52836B632"); } + else if(OID == U_PMF_IE_SHARPEN_OID ){ lf = U_LOAD_GUID("63CBF3EEC526402C8F7162C540BF5142"); } + else if(OID == U_PMF_IE_TINT_OID ){ lf = U_LOAD_GUID("1077AF0028484441948944AD4C2D7A2C"); } + return(lf); +} + +/** + \brief copy data and shift source pointer by the amount of data moved + \param Dst Destination in memory + \param Src Source in memory + \param Size Number of bytes to move +*/ +void U_PMF_MEMCPY_SRCSHIFT(void *Dst, const char **Src, size_t Size){ + if(Dst)memcpy(Dst, *Src, Size); + *Src += Size; +} + +/** + \brief copy data and shift destination pointer by the amount of data moved + \param Dst Destination in memory (this must not be NULL) + \param Src Source in memory (if this is NULL, fill with that many zero bytes instead) + \param Size Number of bytes to move +*/ +void U_PMF_MEMCPY_DSTSHIFT(char **Dst, const void *Src, size_t Size){ + if(Src){ memcpy(*Dst, Src, Size); } + else { memset(*Dst, 0, Size); } + *Dst += Size; +} + +/** + \brief Copy the single instance at Src repeatedly to Dst. + \param Dst Destination in memory + \param Src Source in memory (if this is NULL, fill with that many zero bytes instead) + \param Size number of bytes in single instance that is template. + \param Reps Number of instances of the template to opy +*/ +void U_PMF_REPCPY_DSTSHIFT(char **Dst, const void *Src, size_t Size, size_t Reps){ + for(;Reps;Reps--){ + if(Src){ memcpy(*Dst, Src, Size); } + else { memset(*Dst, 0, Size); } + *Dst += Size; + } +} + +/** + \brief save pointer to data and shift source pointer by the amount of data moved + \param Dst Destination in memory + \param Src Source in memory or NULL. If NULL Dst is set to NULL. + \param Size Number of bytes to move +*/ +void U_PMF_PTRSAV_SHIFT(const char **Dst, const char **Src, size_t Size){ + if(*Src){ + if(Dst)*Dst = *Src; + *Src += Size; + } + else { + if(Dst)*Dst = NULL; + } +} + +/** + \brief save pointer to data and shift source pointer by the amount of data moved + \return 1 on sucess, 0 on error + \param Dst Destination in memory + \param Src Source in memory or NULL. If NULL Dst is set to NULL. + \param Doit Assign if true, otherwise, set to NULL +*/ +int U_PMF_PTRSAV_COND(const char **Dst, const char *Src, int Doit){ + if(!Dst){ return(0); } + if(Src && Doit){ *Dst = Src; } + else { *Dst = NULL; } + return(1); +} +/* + + ===================================================================================== + start of U_PMF_*_get() functions + +*/ + +/** + \brief Get the 16 bit unsigned Flags field from a header. + \param contents Record from which to extract data, will be incremented by header size. + \return Flags field + + In many records the only value needed from the header is Flags. Rather than mapping + the entire Header and returning it, in these instances this function may be called to + just get this one value. +*/ +uint16_t U_PMF_HEADERFLAGS_get(const char *contents){ + uint16_t Flags; + const char *cptr = contents + offsetof(U_PMF_CMN_HDR,Flags); + U_PMF_SERIAL_get(&cptr, &Flags, 2, 1, U_LE); /* EMF+ manual documents it as BE, but this code implements it as LE*/ + return(Flags); +} + +/** + \brief Retrieve whichever header fields are requested. NULL pointers do not retrieve. + \param contents Record from which to extract data, will be incremented by header size. + \param Type Record type + \param Flags Record flags + \param Size Records size + \param Datasize Data size + \return 1 on success, 0 on failure. +*/ +int U_PMF_HEADERFIELDS_get(const char *contents, + uint16_t *Type, uint16_t *Flags, uint32_t *Size, uint32_t *Datasize){ + if(!contents){ return(0); } + U_PMF_SERIAL_get(&contents, Type, 2, 1, U_LE); + U_PMF_SERIAL_get(&contents, Flags, 2, 1, U_LE); /* EMF+ manual documents it as BE, but this code implements it as LE*/ + U_PMF_SERIAL_get(&contents, Size, 4, 1, U_LE); + U_PMF_SERIAL_get(&contents, Datasize, 4, 1, U_LE); + return(1); +} + +/** + \brief Get the entire EMF+ record header. + \param contents Record from which to extract data, will be offset by header size. + \param Header Location to store data (may be NULL) + \returns 1 + If Header is Null, nothing is stored but contents is still offset. +*/ +int U_PMF_CMN_HDR_get(const char **contents, U_PMF_CMN_HDR *Header){ + if(!contents || !*contents){ return(0); } + if(Header){ + U_PMF_SERIAL_get(contents, &(Header->Type), 2, 1, U_LE); + U_PMF_SERIAL_get(contents, &(Header->Flags), 2, 1, U_LE); /* EMF+ manual documents it as BE, but this code implements it as LE*/ + U_PMF_SERIAL_get(contents, &(Header->Size), 4, 1, U_LE); + U_PMF_SERIAL_get(contents, &(Header->DataSize), 4, 1, U_LE); + } + else { + *contents += sizeof(U_PMF_CMN_HDR); + } + return(1); +} + +/** + \brief return the size in bytes of the EMF+ record + \param contents Record from which to extract data, will not be modified. + \returns size, or 0 if contents is Null +*/ +int U_PMF_RECORD_SIZE_get(const char *contents){ + if(!contents){ return(0); } + int Size; + const char *from = contents + 4; + U_PMF_SERIAL_get(&from, &Size, 4, 1, U_LE); + return(Size); +} + +/** + \brief Return the size of a PenData object from an EMF+ record. + \param PenData Address in memory where the PenData object starts. + \returns size of the object in bytes +*/ +int U_PMF_LEN_PENDATA(const char *PenData){ + uint32_t Flags; + int length=12; /* Flags, Unit, Width */ + U_PMF_SERIAL_get(&PenData, &Flags, 4, 1, U_LE); + PenData += 8; /* skip Unit and Width */ + length += U_PMF_LEN_OPTPENDATA(PenData, Flags); + return(length); +} + +/** + \brief Return the size of an OptPenData object from an EMF+ record. + \param PenData Address in memory where the PenData object starts. + \param Flags PenData Flags that indicate which fields are present. + \returns size of the object in bytes +*/ +int U_PMF_LEN_OPTPENDATA(const char *PenData, uint32_t Flags){ + int length=0; + if(Flags & U_PD_Transform){ length += sizeof(U_PMF_TRANSFORMMATRIX); } + if(Flags & U_PD_StartCap){ length += sizeof(int32_t); } + if(Flags & U_PD_EndCap){ length += sizeof(int32_t); } + if(Flags & U_PD_Join){ length += sizeof(uint32_t); } + if(Flags & U_PD_MiterLimit){ length += sizeof(U_FLOAT); } + if(Flags & U_PD_LineStyle){ length += sizeof(int32_t); } + if(Flags & U_PD_DLCap){ length += sizeof(int32_t); } + if(Flags & U_PD_DLOffset){ length += sizeof(int32_t); } + if(Flags & U_PD_DLData){ length += U_PMF_LEN_FLOATDATA(PenData + length); } + if(Flags & U_PD_NonCenter){ length += sizeof(int32_t); } + if(Flags & U_PD_CLData){ length += U_PMF_LEN_FLOATDATA(PenData + length); } + if(Flags & U_PD_CustomStartCap){ length += U_PMF_LEN_BYTEDATA(PenData + length); } + if(Flags & U_PD_CustomEndCap){ length += U_PMF_LEN_BYTEDATA(PenData + length); } + return(length); +} + +/** + \brief Create and set a U_PMF_BRUSH PseudoObject + \return Pointer to PseudoObject, NULL on error + \param Version EmfPlusGraphicsVersion object + \param Bd U_PSEUDO_OBJ containing one of the 5 types of Brush data + + EMF+ manual 2.2.1.1, Microsoft name: EmfPlusBrush Object +*/ +U_PSEUDO_OBJ *U_PMF_BRUSH_set(uint32_t Version, const U_PSEUDO_OBJ *Bd){ + if(!Bd){ return(NULL); } + int32_t Type = U_OID_To_BT(Bd->Type); + if(Type < 0){ return(NULL); } + const U_SERIAL_DESC List[] = { + {&Version, 4, 1, U_LE}, + {&Type, 4, 1, U_LE}, + {Bd->Data, Bd->Used, 1, U_XE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_BRUSH_OID, List); + return(po); +} + +/** + \brief Create and set a U_PMF_CUSTOMLINECAP PseudoObject + \return Pointer to PseudoObject, NULL on error + \param Version EmfPlusGraphicsVersion object + \param Ld U_PSEUDO_OBJ containing one of the 2 types of Linecap data + + EMF+ manual 2.2.1.2, Microsoft name: EmfPlusCustomLineCap Object +*/ +U_PSEUDO_OBJ *U_PMF_CUSTOMLINECAP_set(uint32_t Version, const U_PSEUDO_OBJ *Ld){ + if(!Ld){ return(NULL); } + int32_t Type = U_OID_To_CLCDT(Ld->Type); + if(Type<0){ return(NULL); } + const U_SERIAL_DESC List[] = { + {&Version, 4, 1, U_LE}, + {&Type, 4, 1, U_LE}, + {Ld->Data, Ld->Used, 1, U_XE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_CUSTOMLINECAP_OID, List); + return(po); +} + +/** + \brief Create and set a U_PMF_FONT PseudoObject + \return Pointer to PseudoObject, NULL on error + \param Version EmfPlusGraphicsVersion object + \param EmSize em size in units of SizeUnit + \param SizeUnit UnitType enumeration + \param FSFlags FontStyle flags + \param Length Number of Unicode Characters in FamilyName + \param Font Unicode (UTF-16LE) fontname + + EMF+ manual 2.2.1.3, Microsoft name: EmfPlusFont Object +*/ +U_PSEUDO_OBJ *U_PMF_FONT_set(uint32_t Version, U_FLOAT EmSize, uint32_t SizeUnit, + int32_t FSFlags, uint32_t Length, const uint16_t *Font){ + uint32_t cbFont = 2 * wchar16len(Font); /* this need not be 2*Length parameter */ + uint32_t pad = (0x3 & cbFont ? 2 : 0); + const U_SERIAL_DESC List[] = { + {&Version, 4, 1, U_LE}, + {&EmSize, 4, 1, U_LE}, + {&SizeUnit,4, 1, U_LE}, + {&FSFlags, 4, 1, U_LE}, + {NULL, 4, 1, U_LE}, /* NULL is for Reserved field */ + {&Length, 4, 1, U_LE}, + {Font, cbFont, 1, U_LE}, + {NULL, pad, (pad ? 1 : 0), (pad ? U_XE : U_XX)}, /* Entire record must be a multiple of 4 */ + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_FONT_OID, List); + return(po); +} + +/** + \brief Create and set a U_PMF_IMAGE PseudoObject + \return Pointer to PseudoObject, NULL on error + \param Version EmfPlusGraphicsVersion object + \param Id U_PSEUDO_OBJ containing one of the 2 types of image data + + EMF+ manual 2.2.1.4, Microsoft name: EmfPlusImage Object +*/ +U_PSEUDO_OBJ *U_PMF_IMAGE_set(uint32_t Version, const U_PSEUDO_OBJ *Id){ + if(!Id){ return(NULL); } + int32_t Type = U_OID_To_IDT(Id->Type); + if(Type<0){ return(NULL);} + const U_SERIAL_DESC List[] = { + {&Version, 4, 1, U_LE}, + {&Type, 4, 1, U_LE}, + {Id->Data, Id->Used, 1, U_XE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_IMAGE_OID, List); + return(po); +} + +/** + \brief Create and set a U_PMF_IMAGEATTRIBUTES PseudoObject + \return Pointer to PseudoObject, NULL on error + \param Version EmfPlusGraphicsVersion object + \param WrapMode WrapMode object + \param ClampColor EmfPlusARGB object + \param ObjectClamp ObjectClamp Identifiers + + EMF+ manual 2.2.1.5, Microsoft name: EmfPlusImageAttributes Object +*/ +U_PSEUDO_OBJ *U_PMF_IMAGEATTRIBUTES_set(uint32_t Version, uint32_t WrapMode, uint32_t ClampColor, uint32_t ObjectClamp){ + uint32_t Reserved=0; + const U_SERIAL_DESC List[] = { + {&Version, 4, 1, U_LE}, + {&Reserved, 4, 1, U_LE}, + {&WrapMode, 4, 1, U_LE}, + {&ClampColor, 4, 1, U_LE}, + {&ObjectClamp, 4, 1, U_LE}, + {&Reserved, 4, 1, U_LE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_IMAGEATTRIBUTES_OID, List); + return(po); +} + +/** + \brief Create and set a U_PMF_PATH PseudoObject + \return Pointer to PseudoObject, NULL on error + \param Version EmfPlusGraphicsVersion object + \param Points U_PSEUDO_OBJ containing array of points (of type PMFPointR, PMFPoint, or PMFPointF, determined by U_PPF_P and U_PPF_C bits in Flags) + \param Types U_PSEUDO_OBJ containing array of types (U_PMF_PATHPOINTTYPE or U_PMF_PATHPOINTTYPERLE, determined by U_PPF_R big in Flags) + + EMF+ manual 2.2.1.6, Microsoft name: EmfPlusPath Object +*/ +U_PSEUDO_OBJ *U_PMF_PATH_set(uint32_t Version, const U_PSEUDO_OBJ *Points, const U_PSEUDO_OBJ *Types){ + int ctype, RelAbs, rtype; + int pad; + if(Points){ + if( Points->Type == U_PMF_POINTR_OID){ RelAbs = 1; ctype = 0; } + else if(Points->Type == (U_PMF_POINT_OID | U_PMF_ARRAY_OID)){ RelAbs = 0; ctype = 1; } + else if(Points->Type == (U_PMF_POINTF_OID | U_PMF_ARRAY_OID)){ RelAbs = 0; ctype = 0; } + else { return(NULL); } + } + else { return(NULL); } + if(Types){ + if( Types->Type == (U_PMF_PATHPOINTTYPERLE_OID | U_PMF_ARRAY_OID)){ rtype = 1; } + else if(Types->Type == (U_PMF_PATHPOINTTYPE_OID | U_PMF_ARRAY_OID)){ rtype = 0; } + else { return(NULL); } + } + else { return(NULL); } + uint16_t Flags = (rtype ? U_PPF_R : 0) | (ctype ? U_PPF_C : 0)| (RelAbs ? U_PPF_P : 0); + pad = (0x3 & (Points->Used + Types->Used)); + if(pad){ pad = 4 - pad; } + const U_SERIAL_DESC List[] = { + {&Version, 4, 1, U_LE }, + {Points->Data, 4, 1, U_XE }, /* Elements from Points */ + {&Flags, 2, 1, U_LE }, + {NULL, 2, 1, U_LE }, /* Reserved field */ + {Points->Data + 4, Points->Used - 4, 1, U_XE }, /* omit Points Elements */ + {Types->Data +4, Types->Used - 4, 1, U_XE }, /* omit Types Elements */ + {NULL, pad, (pad ? 1 : 0), (pad ? U_XE : U_XX)}, /* if no padding is needed the Units will be zero and nothing will happen */ + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_PATH_OID, List); + return(po); +} + + +/** + \brief Create and set a U_PMF_PATH PseudoObject that uses U_PMF_POINTF coordinates + \return Pointer to PseudoObject, NULL on error + \param Version EmfPlusGraphicsVersion object + \param Path U_DPSEUDO_OBJ containing a path. + + EMF+ manual 2.2.1.6, Microsoft name: EmfPlusPath Object +*/ +U_PSEUDO_OBJ *U_PMF_PATH_set2(uint32_t Version, const U_DPSEUDO_OBJ *Path){ + if(!Path || !Path->Elements){ return(NULL); } + uint16_t Flags = 0; + int pad = (0x3 & Path->Elements); + if(pad){ pad = 4 - pad; } + const U_SERIAL_DESC List[] = { + {&Version, 4, 1, U_LE }, + {&Path->Elements, 4, 1, U_LE }, + {&Flags, 2, 1, U_LE }, + {NULL, 2, 1, U_LE }, /* Reserved field */ + {Path->poPoints->Data, 4, 2*Path->Elements,U_XE }, /* raw OID, so no leading Elements to omit */ + {Path->poTypes->Data, 1, Path->Elements, U_XE }, /* raw OID, so no leading Elements to omit */ + {NULL, pad, (pad ? 1 : 0), (pad ? U_XE : U_XX)}, /* if no padding is needed the Units will be zero and nothing will happen */ + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_PATH_OID, List); + return(po); +} + +/** + \brief Create and set a U_PMF_PATH PseudoObject that uses U_PMF_POINT (int 16) coordinates + \return Pointer to PseudoObject, NULL on error + \param Version EmfPlusGraphicsVersion object + \param Path U_DPSEUDO_OBJ containing a path. + + EMF+ manual 2.2.1.6, Microsoft name: EmfPlusPath Object +*/ +U_PSEUDO_OBJ *U_PMF_PATH_set3(uint32_t Version, const U_DPSEUDO_OBJ *Path){ + if(!Path || !Path->Elements){return(NULL); } + uint16_t Flags = U_PPF_C; + int pad = (0x3 & Path->Elements); + if(pad){ pad = 4 - pad; } + U_PMF_POINT *Points16 = POINTF_To_POINT16_LE((U_PMF_POINTF *)Path->poPoints->Data, Path->Elements); + if(!Points16){ return(NULL); } + const U_SERIAL_DESC List[] = { + {&Version, 4, 1, U_LE }, + {&Path->Elements, 4, 1, U_LE }, + {&Flags, 2, 1, U_LE }, + {NULL, 2, 1, U_LE }, /* Reserved field */ + {Points16, 2, 2*Path->Elements,U_XE }, /* raw data, so no leading Elements to omit */ + {Path->poTypes->Data, 1, Path->Elements, U_XE }, /* raw data, so no leading Elements to omit */ + {NULL, pad, (pad ? 1 : 0), (pad ? U_XE : U_XX)}, /* if no padding is needed the Units will be zero and nothing will happen */ + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_PATH_OID, List); + free(Points16); + return(po); +} + +/** + \brief Create and set a U_PMF_PEN PseudoObject + \return Pointer to PseudoObject, NULL on error + \param Version EmfPlusGraphicsVersion object + \param PenData U_PSEUDO_OBJ containing U_PMF_PENDATA object + \param Brush U_PSEUDO_OBJ containing U_PMF_BRUSH object + + EMF+ manual 2.2.1.7, Microsoft name: EmfPlusPen Object +*/ +U_PSEUDO_OBJ *U_PMF_PEN_set(uint32_t Version, const U_PSEUDO_OBJ *PenData, const U_PSEUDO_OBJ *Brush){ + if(!PenData || (PenData->Type != U_PMF_PENDATA_OID)){ return(NULL); } + if(!Brush || (Brush->Type != U_PMF_BRUSH_OID) ){ return(NULL); } + const U_SERIAL_DESC List[] = { + {&Version, 4, 1, U_LE}, + {NULL, 4, 1, U_LE}, + {PenData->Data, PenData->Used, 1, U_XE}, + {Brush->Data, Brush->Used, 1, U_XE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_PEN_OID, List); + return(po); +} + + +/** + \brief Create and set a U_PMF_REGION PseudoObject + \return Pointer to PseudoObject, NULL on error + \param Version EmfPlusGraphicsVersion object + \param Count Number of CHILD nodes. This is one less than the total number of U_PMF_REGIONNODE objects in Nodes. + \param Nodes U_PSEUDO_OBJ containing U_PMF_REGIONNODE object (Nodes defining region, may be a single element or a binary tree) + + EMF+ manual 2.2.1.8, Microsoft name: EmfPlusRegion Object +*/ +U_PSEUDO_OBJ *U_PMF_REGION_set(uint32_t Version, uint32_t Count, const U_PSEUDO_OBJ *Nodes){ + if(!Nodes || Nodes->Type != U_PMF_REGIONNODE_OID)return(NULL); + const U_SERIAL_DESC List[] = { + {&Version, 4, 1, U_LE}, + {&Count, 4, 1, U_LE}, + {Nodes->Data, Nodes->Used, 1, U_XE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_REGION_OID, List); + return(po); +} + +/** + \brief Create and set a U_PMF_STRINGFORMAT PseudoObject + \return Pointer to PseudoObject, NULL on error + \param Sfs pointer to U_PMF_STRINGFORMAT structure, with no variable part + \param Sfd (optional) U_PSEUDO_OBJ containing U_PMF_STRINGFORMATDATA object + + EMF+ manual 2.2.1.9, Microsoft name: EmfPlusStringFormat Object +*/ +U_PSEUDO_OBJ *U_PMF_STRINGFORMAT_set(U_PMF_STRINGFORMAT *Sfs, const U_PSEUDO_OBJ *Sfd){ + if(!Sfs){ return(NULL); } + if(Sfd){ + if((!Sfs->TabStopCount && !Sfs->RangeCount) || (Sfd->Type != U_PMF_STRINGFORMATDATA_OID))return(NULL); + } + else { + if(Sfs->TabStopCount || Sfs->RangeCount)return(NULL); + } + const U_SERIAL_DESC List[] = { + {&Sfs->Version, 4, 1, U_LE}, + {&Sfs->Flags, 4, 1, U_LE}, + {&Sfs->Language, 4, 1, U_LE}, + {&Sfs->StringAlignment, 4, 1, U_LE}, + {&Sfs->LineAlign, 4, 1, U_LE}, + {&Sfs->DigitSubstitution, 4, 1, U_LE}, + {&Sfs->DigitLanguage, 4, 1, U_LE}, + {&Sfs->FirstTabOffset, 4, 1, U_LE}, + {&Sfs->HotkeyPrefix, 4, 1, U_LE}, + {&Sfs->LeadingMargin, 4, 1, U_LE}, + {&Sfs->TrailingMargin, 4, 1, U_LE}, + {&Sfs->Tracking, 4, 1, U_LE}, + {&Sfs->Trimming, 4, 1, U_LE}, + {&Sfs->TabStopCount, 4, 1, U_LE}, + {&Sfs->RangeCount, 4, 1, U_LE}, + {(Sfd ? Sfd->Data : NULL), (Sfd ? Sfd->Used : 0), 1, U_XE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_STRINGFORMAT_OID, List); + return(po); +} + +/** + \brief Create and set a PMF_4NUM PseudoObject (used for BrushID's) + \return Pointer to PseudoObject, NULL on error + \param BrushID U_PMF_BRUSH object in the EMF+ object table (0-63, inclusive) + +*/ +U_PSEUDO_OBJ *U_PMF_4NUM_set(uint32_t BrushID){ + if(BrushID>63){ return(NULL); } + const U_SERIAL_DESC List[] = { + {&BrushID, 4, 1, U_LE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_4NUM_OID, List); + return(po); +} + +/** + \brief Create and set a U_PMF_ARGB PseudoObject + \return Pointer to PseudoObject, NULL on error + \param Alpha Alpha (0-255) + \param Red Red color (0-255) + \param Green Green color (0-255) + \param Blue Blue color (0-255) + + EMF+ manual 2.2.2.1, Microsoft name: EmfPlusARGB Object +*/ +U_PSEUDO_OBJ *U_PMF_ARGB_set(uint8_t Alpha, uint8_t Red, uint8_t Green, uint8_t Blue){ + const U_SERIAL_DESC List[] = { + {&Blue, 1, 1, U_XE}, + {&Green, 1, 1, U_XE}, + {&Red, 1, 1, U_XE}, + {&Alpha, 1, 1, U_XE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_ARGB_OID, List); + return(po); +} + +/** + \brief Create and set an Array of U_PMF_ARGB valus in a PseudoObject + \return Pointer to PseudoObject containing the count, followed by the array of colors, NULL on error + \param Count Number of entries in Colors + \param Colors Array of ARGB values + + EMF+ manual 2.2.2.1, Microsoft name: EmfPlusARGB Object +*/ +U_PSEUDO_OBJ *U_PMF_ARGBN_set(uint32_t Count, U_PMF_ARGB *Colors){ + const U_SERIAL_DESC List[] = { + {&Count, 4, 1, U_LE}, + {Colors, 4, Count, U_XE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_ARGB_OID | U_PMF_ARRAY_OID, List); + return(po); +} + +/** + \brief Set a U_PMF_ARGB object + \return Object + \param Alpha Alpha (0-255) + \param Red Red color (0-255) + \param Green Green color (0-255) + \param Blue Blue color (0-255) + + EMF+ manual 2.2.2.1, Microsoft name: EmfPlusARGB Object +*/ +U_PMF_ARGB U_PMF_ARGBOBJ_set(uint8_t Alpha, uint8_t Red, uint8_t Green, uint8_t Blue){ + U_PMF_ARGB argb; + char *ptr = (char *) &argb; + U_PMF_MEMCPY_DSTSHIFT(&ptr, &Blue, 1); + U_PMF_MEMCPY_DSTSHIFT(&ptr, &Green, 1); + U_PMF_MEMCPY_DSTSHIFT(&ptr, &Red, 1); + U_PMF_MEMCPY_DSTSHIFT(&ptr, &Alpha, 1); + return(argb); +} + +/** + \brief Create and set a U_PMF_BITMAP PseudoObject + \return Pointer to PseudoObject, NULL on error + \param Bs pointer to U_PMF_BITMAP structure, with no variable part + \param Bm U_PSEUDO_OBJ containing an U_PMF_BITMAPDATA or U_PMF_COMPRESSEDIMAGE object + + EMF+ manual 2.2.2.2, Microsoft name: EmfPlusBitmap Object +*/ +U_PSEUDO_OBJ *U_PMF_BITMAP_set(const U_PMF_BITMAP *Bs, const U_PSEUDO_OBJ *Bm){ + if(!Bs)return(NULL); + if(Bm->Type != U_PMF_BITMAPDATA_OID && + Bm->Type != U_PMF_COMPRESSEDIMAGE_OID )return(NULL); + uint32_t Pad = UP4(Bm->Used) - Bm->Used; /* undocumented padding, must be present for at least PNG */ + const U_SERIAL_DESC List[] = { + {Bs, 4, 5, U_LE}, + {Bm->Data, Bm->Used, 1, U_XE}, + {NULL, (Pad ? Pad : 0), (Pad ? 1 : 0), U_XE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_BITMAP_OID, List); + return(po); +} + +/** + \brief Create and set a U_PMF_BITMAPDATA PseudoObject + \return Pointer to PseudoObject, NULL on error + \param Ps (optional) U_PSEUDO_OBJ containing a U_PMF_PALETTE structure + \param cbBm Bytes in Bm + \param Bm An array of bytes, meaning depends on fields in U_PMF_BITMAP object and the PixelFormat enumeration. + + EMF+ manual 2.2.2.3, Microsoft name: EmfPlusBitmapData Object +*/ +U_PSEUDO_OBJ *U_PMF_BITMAPDATA_set( const U_PSEUDO_OBJ *Ps, int cbBm, const char *Bm){ + if(Ps && (Ps->Type != U_PMF_PALETTE_OID))return(NULL); + if(!Bm && cbBm)return(NULL); + const U_SERIAL_DESC List[] = { + {(Ps ? Ps->Data : NULL), (Ps ? Ps->Used : 0), (Ps ? 1 : 0), U_LE}, + {Bm, cbBm, 1, U_XE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_BITMAPDATA_OID, List); + return(po); +} + +/** + \brief Create and set a U_PMF_BLENDCOLORS PseudoObject + \return Pointer to PseudoObject, NULL on Positions and Colors + \param Elements number of elements in Positions, must agree with the number of Colors. + \param Positions positions along gradient line. The first position MUST be 0.0 and the last MUST be 1.0. + \param Colors U_PSEUDO_OBJ containing an array of U_PMF_ARGB objects: object colors at positions on gradient line + + EMF+ manual 2.2.2.4, Microsoft name: EmfPlusBlendColors Object +*/ +U_PSEUDO_OBJ *U_PMF_BLENDCOLORS_set(uint32_t Elements, const U_FLOAT *Positions, const U_PSEUDO_OBJ *Colors){ + if(!Colors || !Positions || Colors->Type != (U_PMF_ARGB_OID | U_PMF_ARRAY_OID)){ return(NULL); } + uint32_t CElements = (Colors->Used - 4)/4; + if(CElements != Elements){ return(NULL); } + const U_SERIAL_DESC List[] = { + {&CElements, 4, 1, U_LE}, + {Positions, 4, CElements, U_LE}, + {Colors->Data + 4, Colors->Used - 4, 1, U_XE}, /* omit Elements part of this PseudoObject */ + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_BLENDCOLORS_OID, List); + return(po); +} + +/** + \brief Create and set a U_PMF_BLENDCOLORS PseudoObject + \return Pointer to PseudoObject, NULL on error + \param Elements members in osition, inluding Start and End (0.0 - 1.0) + \param StartColor Start Color (U_PMF_ARGB) + \param EndColor End Color (U_PMF_ARGB) + + EMF+ manual 2.2.2.5, Microsoft name: EmfPlusBlendFactors Object + + + Positions always start at 0.0 and always end at 1.0. It is not well documented but other + start and end values generally do not work. +*/ +U_PSEUDO_OBJ *U_PMF_BLENDCOLORS_linear_set(uint32_t Elements, U_PMF_ARGB StartColor, U_PMF_ARGB EndColor){ + double dP,dR,dG,dB,dA,P,R,G,B,A; + U_FLOAT StartPos = 0.0; + U_FLOAT EndPos = 1.0; + U_FLOAT *Positions; + U_FLOAT *pP; + U_PMF_ARGB *Colors; + U_PMF_ARGB *pC; + unsigned int i; + if(Elements <= 2 ){ return(NULL); } + pP = Positions = (U_FLOAT *)malloc(Elements *sizeof(U_FLOAT)); + if(!Positions){ return(NULL); } + pC = Colors = (U_PMF_ARGB *)malloc(Elements *sizeof(U_PMF_ARGB)); + if(!Colors){ + free(Positions); + return(NULL); + } + dP = (EndPos - StartPos )/(float)(Elements - 1); + dB = ((double)EndColor.Blue - (double)StartColor.Blue )/(double)(Elements - 1); + dG = ((double)EndColor.Green - (double)StartColor.Green)/(double)(Elements - 1); + dR = ((double)EndColor.Red - (double)StartColor.Red )/(double)(Elements - 1); + dA = ((double)EndColor.Alpha - (double)StartColor.Alpha)/(double)(Elements - 1); + P = StartPos; + B = StartColor.Blue; + G = StartColor.Green; + R = StartColor.Red; + A = StartColor.Alpha; + for(i=0;i<Elements;i++,pC++,pP++){ /* hopefully the rounding errors are not a problem, used doubles to minimize that */ + *pP = P; + P += dP; + *pC = (U_PMF_ARGB){B,G,R,A}; + B += dB; + G += dG; + R += dR; + A += dA; + } + U_PSEUDO_OBJ *poColors = U_PMF_ARGBN_set(Elements, Colors); + U_PSEUDO_OBJ *po = U_PMF_BLENDCOLORS_set(Elements, Positions, poColors); + U_PO_free(&poColors); + free(Positions); + free(Colors); + return(po); +} + + +/** + \brief Create and set a U_PMF_BLENDFACTORS PseudoObject + \return Pointer to PseudoObject, NULL on error + \param Elements members in each array + \param Positions positions along gradient line. The first position MUST be 0.0 and the last MUST be 1.0. + \param Factors blending factors, 0.0->1.0 values, inclusive + + EMF+ manual 2.2.2.5, Microsoft name: EmfPlusBlendFactors Object +*/ +U_PSEUDO_OBJ *U_PMF_BLENDFACTORS_set(uint32_t Elements, const U_FLOAT *Positions, const U_FLOAT *Factors){ + if(!Positions || !Factors)return(NULL); + const U_SERIAL_DESC List[] = { + {&Elements, 4, 1, U_LE}, + {Positions, 4, Elements, U_LE}, + {Factors, 4, Elements, U_LE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_BLENDFACTORS_OID, List); + return(po); +} + +/** + \brief Create and set a U_PMF_BLENDFACTORS PseudoObject + \return Pointer to PseudoObject, NULL on error + \param Elements members in osition, inluding Start and End (0.0 - 1.0) + \param StartFactor Start Factor (0.0 - 1.0) + \param EndFactor End Factor (0.0 - 1.0) + + EMF+ manual 2.2.2.5, Microsoft name: EmfPlusBlendFactors Object + + + Positions always start at 0.0 and always end at 1.0. It is not well documented but other + start and end values generally do not work. +*/ +U_PSEUDO_OBJ *U_PMF_BLENDFACTORS_linear_set(uint32_t Elements, U_FLOAT StartFactor, U_FLOAT EndFactor){ + double dP,dF,P,F; + U_FLOAT StartPos = 0.0; + U_FLOAT EndPos = 1.0; + U_FLOAT *Positions; + U_FLOAT *Factors; + U_FLOAT *pP; + U_FLOAT *pF; + unsigned int i; + if(Elements <= 2 ){ return(NULL); } + pP = Positions = (U_FLOAT *)malloc(Elements *sizeof(U_FLOAT)); + if(!Positions){ return(NULL); } + pF = Factors = (U_FLOAT *)malloc(Elements *sizeof(U_FLOAT)); + if(!Factors){ + free(Positions); + return(NULL); + } + dP = (EndPos - StartPos )/(float)(Elements - 1); + dF = (EndFactor - StartFactor)/(float)(Elements - 1); + P = StartPos; + F = StartFactor; + for(i=0;i<Elements;i++){ /* hopefully the rounding errors are not a problem, used doubles to minimize that */ + *pP++ = P; P += dP; + *pF++ = F; F += dF; + } + U_PSEUDO_OBJ *po = U_PMF_BLENDFACTORS_set(Elements, Positions, Factors); + free(Positions); + free(Factors); + return(po); +} + +/** + \brief Create and set a U_PMF_BOUNDARYPATHDATA PseudoObject + \return Pointer to PseudoObject, NULL on error + \param Path U_PSEUDO_OBJ containing U_PMF_PATH object + + EMF+ manual 2.2.2.6, Microsoft name: EmfPlusBoundaryPathData Object +*/ +U_PSEUDO_OBJ *U_PMF_BOUNDARYPATHDATA_set(const U_PSEUDO_OBJ *Path){ + if(!Path || Path->Type != U_PMF_PATH_OID)return(NULL); + /* PO Used is size_t, might be 8 bytes, value in record must be 4 bytes */ + uint32_t Used = Path->Used; + const U_SERIAL_DESC List[] = { + {&Used, 4, 1, U_LE}, + {Path->Data, Path->Used, 1, U_XE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_BOUNDARYPATHDATA_OID, List); + return(po); +} + + +/** + \brief Create and set a U_PMF_BOUNDARYPOINTDATA PseudoObject + \return Pointer to PseudoObject, NULL on error + \param Elements members in each array + \param Points array of U_PMF_POINTF + + EMF+ manual 2.2.2.7, Microsoft name: EmfPlusBoundaryPointData Object +*/ +U_PSEUDO_OBJ *U_PMF_BOUNDARYPOINTDATA_set(uint32_t Elements, const U_PMF_POINTF *Points){ + if(!Points)return(NULL); + const U_SERIAL_DESC List[] = { + {&Elements, 4, 1, U_LE}, + {Points, 4, 2*Elements,U_LE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_BOUNDARYPOINTDATA_OID, List); + return(po); +} + +/** + \brief Create and set a U_PMF_CHARACTERRANGE PseudoObject + \return Pointer to PseudoObject, NULL on error + \param First First position in range + \param Length Range length + + EMF+ manual 2.2.2.8, Microsoft name: EmfPlusCharacterRange Object +*/ +U_PSEUDO_OBJ *U_PMF_CHARACTERRANGE_set(int32_t First, int32_t Length){ + const U_SERIAL_DESC List[] = { + {&First, 4, 1, U_LE}, + {&Length, 4, 1, U_LE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_CHARACTERRANGE_OID, List); + return(po); +} + +/** + \brief Create and set a U_PMF_COMPOUNDLINEDATA PseudoObject + \return Pointer to PseudoObject, NULL on error + \param Elements Members in Widths + \param Widths Array of U_FLOAT Line or gap widths (0.0 <-> 1.0, fraction of total line width ) + + EMF+ manual 2.2.2.9, Microsoft name: EmfPlusCompoundLineData Object +*/ +U_PSEUDO_OBJ *U_PMF_COMPOUNDLINEDATA_set(int32_t Elements, const char *Widths){ + if(!Widths)return(NULL); + const U_SERIAL_DESC List[] = { + {&Elements ,4, 1, U_LE}, + {Widths, 4, Elements,U_LE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_COMPOUNDLINEDATA_OID, List); + return(po); +} + +/** + \brief Create and set a U_PMF_COMPRESSEDIMAGE PseudoObject + \return Pointer to PseudoObject, NULL on error + \param cbImage Bytes in Image + \param Image Stored image in one of the supported formats (GIF, PNG, etc.). + + EMF+ manual 2.2.2.10, Microsoft name: EmfPlusCompressedImage Object +*/ +U_PSEUDO_OBJ *U_PMF_COMPRESSEDIMAGE_set(int32_t cbImage, const char *Image){ + if(!cbImage || !Image)return(NULL); + const U_SERIAL_DESC List[] = { + {Image, cbImage, 1, U_XE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_COMPRESSEDIMAGE_OID, List); + return(po); +} + +/** + \brief Create and set a U_PMF_CUSTOMENDCAPDATA PseudoObject + \return Pointer to PseudoObject, NULL on error + \param Clc U_PSEUDO_OBJ containing a U_PMF_CUSTOMLINECAP object + + EMF+ manual 2.2.2.11, Microsoft name: EmfPlusCustomEndCapData Object +*/ +U_PSEUDO_OBJ *U_PMF_CUSTOMENDCAPDATA_set(const U_PSEUDO_OBJ *Clc){ + if(!Clc || Clc->Type != U_PMF_CUSTOMLINECAP_OID)return(NULL); + /* PO Used is size_t, might be 8 bytes, value in record must be 4 bytes */ + uint32_t Used = Clc->Used; + const U_SERIAL_DESC List[] = { + {&Used, 4, 1, U_LE}, + {Clc->Data, Clc->Used, 1, U_XE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_CUSTOMENDCAPDATA_OID, List); + return(po); +} + +/** + \brief Create and set a U_PMF_CUSTOMLINECAPARROWDATA PseudoObject + \return Pointer to PseudoObject, NULL on error + \param Width Arrow cap width (is multiplied by line width before draw) + \param Height Arrow cap length (is multiplied by line width before draw) + \param MiddleInset Pixels between outer edge and filled region + \param FillState If set, fill, otherwise, only border + \param StartCap LineCap enumeration (type of cap) + \param EndCap LineCap enumeration + \param Join LineJoin enumeration + \param MiterLimit Maximum (miter length / line width) + \param WidthScale Scale for U_PMF_CUSTOMLINECAP object + + EMF+ manual 2.2.2.12, Microsoft name: EmfPlusCustomLineCapArrowData Object +*/ +U_PSEUDO_OBJ *U_PMF_CUSTOMLINECAPARROWDATA_set(U_FLOAT Width, U_FLOAT Height, + U_FLOAT MiddleInset, uint32_t FillState, uint32_t StartCap, uint32_t EndCap, uint32_t Join, + U_FLOAT MiterLimit, U_FLOAT WidthScale + ){ + const U_SERIAL_DESC List[] = { + {&Width, 4, 1, U_LE}, + {&Height ,4, 1, U_LE}, + {&MiddleInset, 4, 1, U_LE}, + {&FillState, 4, 1, U_LE}, + {&StartCap, 4, 1, U_LE}, + {&EndCap, 4, 1, U_LE}, + {&Join, 4, 1, U_LE}, + {&MiterLimit, 4, 1, U_LE}, + {&WidthScale, 4, 1, U_LE}, + {NULL, 8, 2, U_LE}, /* FillHotSpots and LineHotSpots */ + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_CUSTOMLINECAPARROWDATA_OID, List); + return(po); +} + + +/** + \brief Create and set a U_PMF_CUSTOMLINECAPDATA PseudoObject + \return Pointer to PseudoObject, NULL on error + \param Flags CustomLineCapData flags + \param Cap LineCap enumeration (type of cap) + \param Inset Distance line cap start -> line end + \param StartCap LineCap enumeration + \param EndCap LineCap enumeration + \param Join LineJoin enumeration + \param MiterLimit Maximum (miter length / line width) + \param WidthScale Scale for U_PMF_CUSTOMLINECAP object + \param Clcod U_PSEUDO_OBJ containing a U_PMF_CUSTOMLINECAPOPTIONALDATA object + + EMF+ manual 2.2.2.13, Microsoft name: EmfPlusCustomLineCapData Object +*/ +U_PSEUDO_OBJ *U_PMF_CUSTOMLINECAPDATA_set(uint32_t Flags, uint32_t Cap, + U_FLOAT Inset, uint32_t StartCap, uint32_t EndCap, + uint32_t Join, U_FLOAT MiterLimit, U_FLOAT WidthScale, + const U_PSEUDO_OBJ *Clcod + ){ + if(!Clcod || Clcod->Type != U_PMF_CUSTOMLINECAPOPTIONALDATA_OID)return(NULL); + const U_SERIAL_DESC List[] = { + {&Flags, 4, 1, U_LE}, + {&Cap, 4, 1, U_LE}, + {&Inset, 4, 1, U_LE}, + {&StartCap, 4, 1, U_LE}, + {&EndCap, 4, 1, U_LE}, + {&Join, 4, 1, U_LE}, + {&MiterLimit, 4, 1, U_LE}, + {&WidthScale, 4, 1, U_LE}, + {NULL, 8, 2, U_LE}, /* FillHotSpots and LineHotSpots */ + {Clcod->Data, Clcod->Used, 1, U_XE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_CUSTOMLINECAPDATA_OID, List); + return(po); +} + +/** + \brief Create and set a U_PMF_CUSTOMLINECAPOPTIONALDATA PseudoObject + \return Pointer to PseudoObject, NULL on error + \param Fill U_PSEUDO_OBJ containing a U_PMF_FILLPATHOBJ object (optional) + \param Line U_PSEUDO_OBJ containing a U_PMF_LINEPATH object (optional) + + EMF+ manual 2.2.2.14, Microsoft name: EmfPlusCustomLineCapOptionalData Object +*/ +U_PSEUDO_OBJ *U_PMF_CUSTOMLINECAPOPTIONALDATA_set(const U_PSEUDO_OBJ *Fill, const U_PSEUDO_OBJ *Line){ + if(Fill && (Fill->Type != U_PMF_FILLPATHOBJ_OID))return(NULL); + if(Line && (Line->Type != U_PMF_LINEPATH_OID))return(NULL); + const U_SERIAL_DESC List[] = { + {(Fill ? Fill->Data : NULL), (Fill ? Fill->Used : 0), 1, U_XE}, + {(Line ? Line->Data : NULL), (Line ? Line->Used : 0), 1, U_XE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_CUSTOMLINECAPOPTIONALDATA_OID, List); + return(po); +} + +/** + \brief Create and set a U_PMF_CUSTOMSTARTCAPDATA PseudoObject + \return Pointer to PseudoObject, NULL on error + \param Clc U_PSEUDO_OBJ containing a U_PMF_CUSTOMLINECAPDATA object + + EMF+ manual 2.2.2.15, Microsoft name: EmfPlusCustomStartCapData Object +*/ +U_PSEUDO_OBJ *U_PMF_CUSTOMSTARTCAPDATA_set(const U_PSEUDO_OBJ *Clc){ + if(!Clc || Clc->Type != U_PMF_CUSTOMLINECAP_OID)return(NULL); + const U_SERIAL_DESC List[] = { + {Clc->Data, Clc->Used, 1, U_XE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_CUSTOMSTARTCAPDATA_OID, List); + return(po); +} + +/** + \brief Create and set a U_PMF_DASHEDLINEDATA PseudoObject + \return Pointer to PseudoObject, NULL on error + \param Elements Members in Lengths + \param Lengths Array of U_FLOAT holding lengths of dashes and spaces. + + EMF+ manual 2.2.2.16, Microsoft name: EmfPlusDashedLineData Object +*/ +U_PSEUDO_OBJ *U_PMF_DASHEDLINEDATA_set(int32_t Elements, const U_FLOAT *Lengths){ + if(!Lengths)return(NULL); + const U_SERIAL_DESC List[] = { + {&Elements, 4, 1, U_LE}, + {Lengths, 4, Elements, U_LE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_DASHEDLINEDATA_OID, List); + return(po); +} + +/** + \brief Utility function to create and set a U_PMF_DASHEDLINEDATA PseudoObject from one of a predefined set of patterns + \return Pointer to PseudoObject, NULL on error + \param Unit Length of the repeat unit + \param StdPat Members in Lengths + + EMF+ manual 2.2.2.16, Microsoft name: EmfPlusDashedLineData Object +*/ +U_PSEUDO_OBJ *U_PMF_DASHEDLINEDATA_set2(U_FLOAT Unit, int StdPat){ + uint32_t Elements; + uint8_t *p; + U_FLOAT SubUnit; + U_FLOAT Lengths[8]; /* This is the most dash/spaces that will be needed*/ + int i; + /* Dot = 1, Dash = 2; Long = 3, 0 = terminate pattern */ + uint8_t SB[U_DD_Types][5] = + { + {0,0,0,0,0}, // Solid + {2,0,0,0,0}, // Dash + {2,2,0,0,0}, // DashDash + {2,2,2,0,0}, // DashDashDash + {2,2,2,2,0}, // DashDashDashDash + {1,0,0,0,0}, // Dot + {1,1,0,0,0}, // DotDot + {1,1,1,0,0}, // DotDotDot + {1,1,1,1,0}, // DotDotDotDot + {2,1,0,0,0}, // DashDot + {2,2,1,0,0}, // DashDashDot + {2,2,1,1,0}, // DashDashDotDot + {2,2,2,1,0}, // DashDashDashDot + {2,1,1,0,0}, // DashDotDot + {2,1,1,1,0}, // DashDotDotDot + {2,1,2,1,0}, // DashDotDashDot + {3,0,0,0,0}, // Long + {3,3,0,0,0}, // LongLong + {3,3,3,0,0}, // LongLongLong + {3,3,3,3,0}, // LongLongLongLong + {3,1,0,0,0}, // LongDot + {3,3,1,0,0}, // LongLongDot + {3,3,1,1,0}, // LongLongDotDot + {3,3,3,1,0}, // LongLongLongDot + {3,1,1,0,0}, // LongDotDot + {3,1,1,1,0}, // LongDotDotDot + {3,1,3,1,0} // LongDotLongDot + }; + if(Unit <= 0 ){ return(NULL); } + if((StdPat <= 0) || (StdPat > U_DD_LongDotLongDot)){ return(NULL); } + p = &(SB[StdPat][0]); + for(Elements = 0; *p; p++, Elements++){} + SubUnit = Unit/((U_FLOAT) Elements); + Elements *= 2; + p = &(SB[StdPat][0]); + for(i=0; *p; p++){ + switch(*p){ + case 0: break; + case 1: /* dot */ + Lengths[i++] = SubUnit * 0.125; + Lengths[i++] = SubUnit * 0.875; + break; + case 2: /* dash */ + Lengths[i++] = SubUnit * 0.5; + Lengths[i++] = SubUnit * 0.5; + break; + case 3: /* long */ + Lengths[i++] = SubUnit * 0.75; + Lengths[i++] = SubUnit * 0.25; + break; + } + } + + U_PSEUDO_OBJ *po = U_PMF_DASHEDLINEDATA_set(Elements, Lengths); + return(po); +} + +/** + \brief Utility function to create and set a U_PMF_DASHEDLINEDATA PseudoObject from the bits that are set in a uint32_t + \return Pointer to PseudoObject, NULL on error + \param Unit Length of the repeat unit + \param BitPat uint32_t holding the bit pattern, the lowest order bit MUST be set and the highest order MUST be clear. + + Make a line with a dot/dash pattern defined by the bits in the BitPat value. If a bit is set it is drawn, + if clear it is not. Every bit drawn has length Unit/32, and consecutive drawn bits are merged together. + The lowest order bit is the first bit that may be drawn, the highest the last. + + Example: if the integer has value 0x13 the pattern produced will be: + 0 -> 2*unit/32 drawn + 2*unit/32 -> 5*unit/32 not drawn + 5*unit/32 -> 6*unit/32 drawn + 6*unit/32 -> unit not drawn + + EMF+ manual 2.2.2.16, Microsoft name: EmfPlusDashedLineData Object +*/ +U_PSEUDO_OBJ *U_PMF_DASHEDLINEDATA_set3(U_FLOAT Unit, uint32_t BitPat){ + uint32_t Elements=0; + U_FLOAT SubUnit = Unit/32.0; + U_FLOAT Lengths[32]; /* This is the most dash/spaces that will be needed*/ + if(!(0x00000001 & BitPat))return(NULL); /* Pattern must start with a drawn segment, this bit must be set */ + if( 0x80000000 & BitPat )return(NULL); /* Pattern must end with an undrawn segment, this bit must be clear */ + int i=0; + int k; + int lastType=1; + int newType=0; + uint32_t j=1; + Lengths[0]=0; + for(k=0; k<32; k++, j=j<<1){ + if(j & BitPat){ + if(!lastType){ + newType=1; + } + } + else { + if(lastType){ + newType=1; + } + } + if(newType){ + i++; + Lengths[i]=0; + Elements++; + lastType = !lastType; + newType = 0; + } + Lengths[i] += SubUnit; + } + Elements = i+1; + + U_PSEUDO_OBJ *po = U_PMF_DASHEDLINEDATA_set(Elements, Lengths); + return(po); +} + +/** + \brief Create and set a U_PMF_FILLPATHOBJ PseudoObject + \return Pointer to PseudoObject, NULL on error + \param Path U_PSEUDO_OBJ containing a U_PMF_PATH object + + EMF+ manual 2.2.2.17, Microsoft name: EmfPlusFillPath Object +*/ +U_PSEUDO_OBJ *U_PMF_FILLPATHOBJ_set(const U_PSEUDO_OBJ *Path){ + if(!Path || (Path->Type != U_PMF_PATH_OID))return(NULL); + const U_SERIAL_DESC List[] = { + {Path->Data, Path->Used, 1, U_XE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_FILLPATHOBJ_OID, List); + return(po); +} + +/** + \brief Create and set a U_PMF_FOCUSSCALEDATA PseudoObject + \return Pointer to PseudoObject, NULL on error + \param ScaleX value 0.0 <-> 1.0 + \param ScaleY value 0.0 <-> 1.0 + + EMF+ manual 2.2.2.18, Microsoft name: EmfPlusFocusScaleData Object +*/ +U_PSEUDO_OBJ *U_PMF_FOCUSSCALEDATA_set(U_FLOAT ScaleX, U_FLOAT ScaleY){ + uint32_t tmp = 2; + const U_SERIAL_DESC List[] = { + {&tmp, 4, 1, U_LE}, + {&ScaleX, 4, 1, U_LE}, + {&ScaleY, 4, 1, U_LE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_FOCUSSCALEDATA_OID, List); + return(po); +} + +/** + \brief Create and set a U_PMF_GRAPHICSVERSION object (Signature always set to 0xDBC01) + \return Pointer to PseudoObject, NULL on error + \param GrfVersion GraphicsVersion enumeration + + EMF+ manual 2.2.2.19, Microsoft name: EmfPlusGraphicsVersion Object +*/ +U_PSEUDO_OBJ *U_PMF_GRAPHICSVERSION_set(int GrfVersion){ + uint32_t tmp; + tmp = U_GFVR_PMF << 12; /* signature, can only have this value */ + tmp |= (GrfVersion & U_GFVR_MASKLO); + const U_SERIAL_DESC List[] = { + {&tmp, 4, 1, U_LE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_GRAPHICSVERSION_OID, List); + return(po); +} + +/** + \brief Create and set a U_PMF_GRAPHICSVERSION object Structure (Signature always set to 0xDBC01) + \return U_PMF_GRAPHICSVERSION + \param GrfVersion GraphicsVersion enumeration + + EMF+ manual 2.2.2.19, Microsoft name: EmfPlusGraphicsVersion Object +*/ +U_PMF_GRAPHICSVERSION U_PMF_GRAPHICSVERSIONOBJ_set(int GrfVersion){ + uint32_t tmp; + tmp = U_GFVR_PMF << 12; /* signature, can only have this value */ + tmp |= (GrfVersion & U_GFVR_MASKLO); + return(tmp); +} + + +/** + \brief Create and set a U_PMF_HATCHBRUSHDATA PseudoObject + \return Pointer to PseudoObject, NULL on error + \param Style HatchStyle enumeration + \param Fg U_PSEUDO_OBJ containing a U_ARGB object, Foreground hatch pattern line color + \param Bg U_PSEUDO_OBJ containing a U_ARGB object, Background hatch pattern line color + + EMF+ manual 2.2.2.20, Microsoft name: EmfPlusHatchBrushData Object +*/ +U_PSEUDO_OBJ *U_PMF_HATCHBRUSHDATA_set(uint32_t Style, const U_PSEUDO_OBJ *Fg, const U_PSEUDO_OBJ *Bg){ + if(!Fg ||(Fg->Type != U_PMF_ARGB_OID))return(NULL); + if(!Bg ||(Bg->Type != U_PMF_ARGB_OID))return(NULL); + const U_SERIAL_DESC List[] = { + {&Style, 4, 1, U_LE}, + {Fg->Data, Fg->Used, 1, U_XE}, + {Bg->Data, Bg->Used, 1, U_XE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_HATCHBRUSHDATA_OID, List); + return(po); +} + +/** + \brief Create and set a U_PMF_INTEGER7 PseudoObject + \return Pointer to PseudoObject, NULL on error + \param Value 7 bit signed integer (stored in an integer, range 63 <-> -64, inclusive) + + EMF+ manual 2.2.2.21, Microsoft name: EmfPlusInteger7 Object +*/ +U_PSEUDO_OBJ *U_PMF_INTEGER7_set(int Value){ + uint8_t utmp; + if(Value < -64 || Value > 63)return(NULL); + utmp = U_MASK_INT7 & *(unsigned int *)&Value; + U_PSEUDO_OBJ *po = U_PO_create((char *)&utmp, 1, 1, U_PMF_INTEGER7_OID); /* simple method is OK, no possibility of Endian issues */ + return(po); +} + +/** + \brief Create and set a U_PMF_INTEGER15 PseudoObject + \return Pointer to PseudoObject, NULL on error + \param Value 15 bit signed integer (stored in an integer, range 32677 <-> -32678, inclusive) + + EMF+ manual 2.2.2.22, Microsoft name: EmfPlusInteger15 Object +*/ +U_PSEUDO_OBJ *U_PMF_INTEGER15_set(int Value){ + uint16_t utmp; + if(Value < -32678 || Value > 32677)return(NULL); + utmp = U_TEST_INT15 | (U_MASK_INT15 & *(unsigned int *)&Value); + const U_SERIAL_DESC List[] = { + {&utmp, 2, 1, U_BE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_INTEGER15_OID, List); + return(po); +} + +/** + \brief Create and set a U_PMF_LANGUAGEIDENTIFIER value in 4 byte unsigned int, in NATIVE byte order + \return LID value in least significant two bytes and 0 in most significant two bytes. + \param SubLId Example: code for USA + \param PriLId Example: code for English + + EMF+ manual 2.2.2.23, Microsoft name: EmfPlusLanguageIdentifier Object +*/ +U_PMF_LANGUAGEIDENTIFIER U_PMF_LANGUAGEIDENTIFIEROBJ_set(int SubLId, int PriLId){ + U_PMF_LANGUAGEIDENTIFIER utmp32; + utmp32 = ((SubLId & U_FF_MASK_SUBLID) << U_FF_SHFT_SUBLID) | ((PriLId & U_FF_MASK_PRILID) << U_FF_SHFT_PRILID); + return(utmp32); +} + +/** + \brief Create and set a U_PMF_LANGUAGEIDENTIFIER PseudoObject + \return Pointer to PseudoObject, NULL on error + \param LId Language Identifier as produced by U_PMF_LANGUAGEIDENTIFIEROBJ_set(). + + EMF+ manual 2.2.2.23, Microsoft name: EmfPlusLanguageIdentifier Object +*/ +U_PSEUDO_OBJ *U_PMF_LANGUAGEIDENTIFIER_set(U_PMF_LANGUAGEIDENTIFIER LId){ + uint16_t utmp16; + utmp16 = (LId & U_FF_MASK_LID) << U_FF_SHFT_LID; + const U_SERIAL_DESC List[] = { + {&utmp16, 2, 1, U_LE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_LANGUAGEIDENTIFIER_OID, List); + return(po); +} + +/** + \brief Create and set a U_PMF_LINEARGRADIENTBRUSHDATA PseudoObject + \return Pointer to PseudoObject, NULL on error + \param Lgbd U_PMF_LINEARGRADIENTBRUSHDATA object (constant part) + \param Lgbod U_PSEUDO_OBJ containing a U_PMF_LINEARGRADIENTBRUSHOPTIONALDATA object (variable part of a U_PMF_LINEARGRADIENTBRUSHDATA object) + + + EMF+ manual 2.2.2.24, Microsoft name: EmfPlusLinearGradientBrushData Object +*/ +U_PSEUDO_OBJ *U_PMF_LINEARGRADIENTBRUSHDATA_set(const U_PMF_LINEARGRADIENTBRUSHDATA *Lgbd, const U_PSEUDO_OBJ *Lgbod){ + if(!Lgbd || !Lgbod || (Lgbod->Type != U_PMF_LINEARGRADIENTBRUSHOPTIONALDATA_OID))return(NULL); + const U_SERIAL_DESC List[] = { + {Lgbd, 4, 6, U_LE}, + {&(Lgbd->StartColor), 4, 2, U_XE}, + {&(Lgbd->StartColor), 4, 2, U_XE}, /* repeat the start/end colors. Supposedly reserved. */ +// {NULL, 4, 2, U_LE}, /* zero fill the two Reserved fields, no matter what is passed in */ + {(Lgbod->Used ? Lgbod->Data : NULL), Lgbod->Used, 1, U_XE}, /* optional Data can exist and Used can be zero, SERIAL_set would throw an error on that */ + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_LINEARGRADIENTBRUSHDATA_OID, List); + return(po); +} + +/** + \brief Create and set a U_PMF_LINEARGRADIENTBRUSHOPTIONALDATA PseudoObject + \return Pointer to PseudoObject, NULL on error + \param Flags Bits are set that indicate which of the following were included. The caller must clear before passing it in. + \param Tm (optional) U_PSEUDO_OBJ containing a U_PMF_TRANSFORMMATRIX object + \param Bc (optional) U_PSEUDO_OBJ containing a U_PMF_BLENDCOLORS object or NULL + \param BfH (optional) U_PSEUDO_OBJ containing a U_PMF_BLENDFACTORS (H) object or NULL + \param BfV (optional) U_PSEUDO_OBJ containing a U_PMF_BLENDFACTORS (V) object or NULL (WARNING, GDI+ defines this field but does not render it. DO NOT USE.) + + + EMF+ manual 2.2.2.25, Microsoft name: EmfPlusLinearGradientBrushOptionalData Object + + + The rectangular gradients repeat in a tiled pattern. Tm can rotate and offset the gradient within each tile. + The gradient wraps when it is offset. + +*/ +U_PSEUDO_OBJ *U_PMF_LINEARGRADIENTBRUSHOPTIONALDATA_set(uint32_t *Flags, const U_PSEUDO_OBJ *Tm, + const U_PSEUDO_OBJ *Bc, const U_PSEUDO_OBJ *BfH, const U_PSEUDO_OBJ *BfV){ + if(!Flags )return(NULL); + if(Tm && (Tm->Type != U_PMF_TRANSFORMMATRIX_OID))return(NULL); + if(Bc && (Bc->Type != U_PMF_BLENDCOLORS_OID) )return(NULL); + if(BfH && (BfH->Type != U_PMF_BLENDFACTORS_OID) )return(NULL); + if(BfV && (BfV->Type != U_PMF_BLENDFACTORS_OID) )return(NULL); + if(Bc && (BfH || BfV) )return(NULL); + const U_SERIAL_DESC List[] = { + {(Tm ? Tm->Data : NULL), (Tm ? Tm->Used : 0), 1, U_XE}, + {(Bc ? Bc->Data : NULL), (Bc ? Bc->Used : 0), 1, U_XE}, + {(BfH ? BfH->Data : NULL), (BfH ? BfH->Used : 0), 1, U_XE}, + {(BfV ? BfV->Data : NULL), (BfV ? BfV->Used : 0), 1, U_XE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_LINEARGRADIENTBRUSHOPTIONALDATA_OID, List); + if(Tm ){ *Flags |= U_BD_Transform; } + if(Bc ){ *Flags |= U_BD_PresetColors; } + if(BfH){ *Flags |= U_BD_BlendFactorsH; } + if(BfV){ *Flags |= U_BD_BlendFactorsV; } + return(po); +} + +/** + \brief Create and set a U_PMF_LINEPATH PseudoObject + \return Pointer to PseudoObject, NULL on error + \param Path U_PSEUDO_OBJ containing a U_PMF_PATH object + + + EMF+ manual 2.2.2.26, Microsoft name: EmfPlusLinePath Object +*/ +U_PSEUDO_OBJ *U_PMF_LINEPATH_set(const U_PSEUDO_OBJ *Path){ + if(!Path || (Path->Type != U_PMF_PATH_OID))return(NULL); + const U_SERIAL_DESC List[] = { + {&Path->Data, Path->Used, 1, U_XE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_LINEPATH_OID, List); + return(po); +} + +/** + \brief Create and set a U_PMF_METAFILE object (NOT SUPPORTED!) + \return Null + + + EMF+ manual 2.2.2.27, Microsoft name: EmfPlusMetafile Object +*/ +U_PSEUDO_OBJ *U_PMF_METAFILE_set(void){ + return(NULL); +} + +/** + \brief Create and set a U_PMF_PALETTE PseudoObject + \return Pointer to PseudoObject, NULL on error + \param Flags PaletteStyle flags + \param Elements Members in Lengths + \param Pd Array of U_PMF_ARGB holding colors of palettes. (Palette Data) + + EMF+ manual 2.2.2.28, Microsoft name: EmfPlusPalette Object +*/ +U_PSEUDO_OBJ *U_PMF_PALETTE_set(uint32_t Flags, uint32_t Elements, const U_PMF_ARGB *Pd){ + if(!Pd)return(NULL); + const U_SERIAL_DESC List[] = { + {&Flags, 4, 1, U_LE}, + {&Elements, 4, 1, U_LE}, + {Pd, 4, Elements, U_XE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_PALETTE_OID, List); + return(po); +} + +/** + \brief Create and set a U_PMF_PATHGRADIENTBRUSHDATA PseudoObject + \return Pointer to PseudoObject, NULL on error + \param Flags PaletteStyle flags + \param WrapMode WrapMode enumeration + \param CenterColor U_PMF_ARGB Center color + \param Center Center coordinates + \param Gradient U_PSEUDO_OBJ containing an Array of U_PMF_ARGB holding colors of Gradient + \param Boundary U_PSEUDO_OBJ containing a U_PMF_BOUNDARYPATHDATA or U_PMF_BOUNDARYPOINTDATA object. (Boundary Data) + \param Data variable part of U_PMF_LINEARGRADIENTBRUSHDATA, exact composition depends on Flags + + EMF+ manual 2.2.2.29, Microsoft name: EmfPlusPathGradientBrushData Object +*/ +U_PSEUDO_OBJ *U_PMF_PATHGRADIENTBRUSHDATA_set(uint32_t Flags, int32_t WrapMode, U_PMF_ARGB CenterColor, + U_PMF_POINTF Center, + const U_PSEUDO_OBJ *Gradient, const U_PSEUDO_OBJ *Boundary, const U_PSEUDO_OBJ *Data){ + if( (Flags & U_BD_Path) && (!Boundary || (Boundary->Type != U_PMF_BOUNDARYPATHDATA_OID)))return(NULL); + if(!(Flags & U_BD_Path) && (!Boundary || (Boundary->Type != U_PMF_BOUNDARYPOINTDATA_OID)))return(NULL); + if(!Gradient || (Gradient->Type != (U_PMF_ARGB_OID | U_PMF_ARRAY_OID)))return(NULL); + if(!(Flags & U_BD_Transform) && + !(Flags & U_BD_PresetColors) && + !(Flags & U_BD_BlendFactorsH) && + !(Flags & U_BD_FocusScales) && + (!Data || (Data->Type != U_PMF_PATHGRADIENTBRUSHOPTIONALDATA_OID)))return(NULL); + + const U_SERIAL_DESC List[] = { + {&Flags, 4, 1, U_LE}, + {&WrapMode, 4, 1, U_LE}, + {&CenterColor, 4, 1, U_XE}, + {&Center.X, 4, 2, U_LE}, + {Gradient->Data, Gradient->Used, 1, U_XE}, /* includes Elements */ + {Boundary->Data, Boundary->Used, 1, U_XE}, + {(Data ? Data->Data : NULL), (Data ? Data->Used : 0), 1, U_XE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_PATHGRADIENTBRUSHDATA_OID, List); + return(po); +} + +/** + \brief Create and set a U_PMF_PATHGRADIENTBRUSHOPTIONALDATA PseudoObject + \return Pointer to PseudoObject, NULL on error + \param Flags PaletteStyle flags + \param Tm U_PSEUDO_OBJ containing a U_PMF_TRANSFORMMATRIX. (Transformation matrix) + \param Pd U_PSEUDO_OBJ containing a U_PMF_BLENDCOLORS or U_PMF_BLENDFACTORS object. (Pattern Data) + \param Fsd U_PSEUDO_OBJ containing a U_PMF_FOCUSSSCALEDATA object. (Focus Scale Data) + + EMF+ manual 2.2.2.30, Microsoft name: EmfPlusPathGradientBrushOptionalData Object +*/ +U_PSEUDO_OBJ *U_PMF_PATHGRADIENTBRUSHOPTIONALDATA_set(uint32_t Flags, + const U_PSEUDO_OBJ *Tm, const U_PSEUDO_OBJ *Pd, const U_PSEUDO_OBJ *Fsd){ + if(Tm && (Tm->Type != U_PMF_TRANSFORMMATRIX_OID))return(NULL); + if(Pd && !(Flags & (U_BD_PresetColors | U_BD_BlendFactorsH)))return(NULL); + if( (Flags & U_BD_PresetColors) && ((Flags & U_BD_BlendFactorsH) || !Pd || (Pd->Type != U_PMF_BLENDCOLORS_OID) ))return(NULL); + if( (Flags & U_BD_BlendFactorsH) && ((Flags & U_BD_PresetColors) || !Pd || (Pd->Type != U_PMF_BLENDFACTORS_OID)))return(NULL); + if(Fsd && !(Flags & U_BD_FocusScales))return(NULL); + if( (Flags & U_BD_FocusScales) && (!Fsd || (Fsd->Type != U_PMF_BLENDCOLORS_OID) ))return(NULL); + const U_SERIAL_DESC List[] = { + {(Tm ? Tm->Data : NULL), (Tm ? Tm->Used : 0), 1, U_XE}, + {(Pd ? Pd->Data : NULL), (Pd ? Pd->Used : 0), 1, U_XE}, + {(Fsd ? Fsd->Data : NULL), (Fsd ? Fsd->Used : 0), 1, U_XE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_PATHGRADIENTBRUSHOPTIONALDATA_OID, List); + return(po); +} + +/** + \brief Create and set an ARRAY of U_PMF_PATHPOINTTYPE objects + \return Pointer to PseudoObject, NULL on error + \param Elements Number of entries in Flags and Enumerations + \param Ppt Array of unsigned bytes, lower 4 bits hold the PathPointType flag upper 4 bits hold the PathPointType enumeration. + + EMF+ manual 2.2.2.31, Microsoft name: EmfPlusPathPointType Object +*/ +U_PSEUDO_OBJ *U_PMF_PATHPOINTTYPE_set(uint32_t Elements, const uint8_t *Ppt){ + if(!Elements || !Ppt)return(NULL); + const U_SERIAL_DESC List[] = { + {&Elements, 4, 1, U_LE}, + {Ppt, 1, Elements, U_XE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_PATHPOINTTYPE_OID | U_PMF_ARRAY_OID, List); + return(po); +} + +/** + \brief Create and set an ARRAY of U_PMF_PATHPOINTTYPE objects, with a preceding Elements count + \return Pointer to PseudoObject, NULL on error + \param Elements Number of elements to add. First is added once and Others Elements-1 times. + \param First Apply to first point, unsigned byte, lower 4 bits hold the PathPointType flag upper 4 bits hold the PathPointType enumeration. + \param Others Apply to all other points, unsigned byte, lower 4 bits hold the PathPointType flag upper 4 bits hold the PathPointType enumeration. + + EMF+ manual 2.2.2.31, Microsoft name: EmfPlusPathPointType Object +*/ +U_PSEUDO_OBJ *U_PMF_PATHPOINTTYPE_set2(uint32_t Elements, uint8_t First, uint8_t Others){ + if(!Elements)return(NULL); + const U_SERIAL_DESC List[] = { + {&Elements, 4, 1, U_XE}, + {&First, 1, 1, U_XE}, + {&Others, 1, Elements-1, U_RP}, /* replicate the one value N-1 times */ + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_PATHPOINTTYPE_OID | U_PMF_ARRAY_OID, List); + return(po); +} + +/** + \brief Create and set an ARRAY of U_PMF_PATHPOINTTYPERLE objects + \return Pointer to PseudoObject containing first the number of elements, then an array of U_PMF_PATHPOINTTYPERLE, NULL on error + \param Elements Number of entries in the arrays + \param Bz Array of unsigned bytes, if not zero, element has Bezier bit set + \param RL Array of unsigned bytes, Run lengths. + \param Ppte Array of unsigned bytes, PathPointType enumerations. + + EMF+ manual 2.2.2.32, Microsoft name: EmfPlusPathPointTypeRLE Object +*/ +U_PSEUDO_OBJ *U_PMF_PATHPOINTTYPERLE_set(uint32_t Elements, const uint8_t *Bz, const uint8_t *RL, const uint8_t *Ppte){ + uint8_t utmp; + if(!Bz || !RL || !Ppte)return(NULL); + /* allocate space in the structure but put no data in */ + U_PSEUDO_OBJ *po = U_PO_create(NULL, 4 + 2*Elements, 0, U_PMF_PATHPOINTTYPERLE_OID | U_PMF_ARRAY_OID); + U_PSEUDO_OBJ *holdpo = po; + if(po){ + U_PSEUDO_OBJ *poi = U_PMF_4NUM_set(Elements); + if(!poi)goto end; + po = U_PO_append(po, poi->Data, poi->Used); + U_PO_free(&poi); + if(!po)goto end; + + for( ;Elements; Elements--, Bz++, RL++, Ppte++){ + po = U_PO_append(po, (char *)Ppte, 1); + if(!po)goto end; + + if(*RL > 0x3F) goto end; /* run length too big for field */ + + utmp = (*Bz ? 1 : 0) | ((*RL & 0x3F)<<2); /* bit 1 is not used and is set to 0 */ + po = U_PO_append(po, (char *)&utmp, 1); + if(!po)goto end; + } + } +end: + if(!po)U_PO_free(&holdpo); + return(holdpo); +} + +/** + \brief Create and set a U_PMF_PENDATA PseudoObject + \return Pointer to PseudoObject, NULL on error + \param Unit UnitType enumeration + \param Width Width in units set by Unit + \param Pod U_PSEUDO_OBJ containing first the PenData flags then a U_PMF_PENOPTIONALDATA object (the second part + may be an empty if Flags is 0) + + + EMF+ manual 2.2.2.33, Microsoft name: EmfPlusPenData Object +*/ +U_PSEUDO_OBJ *U_PMF_PENDATA_set(uint32_t Unit, U_FLOAT Width, const U_PSEUDO_OBJ *Pod){ + if(Pod && ((Pod->Type != U_PMF_PENOPTIONALDATA_OID) || Pod->Used < 4))return(NULL); + const U_SERIAL_DESC List[] = { + {(Pod ? Pod->Data : NULL), 4, 1, U_XE}, /* the Flags field, clear if no optional data */ + {&Unit, 4, 1, U_LE}, + {&Width, 4, 1, U_LE}, + /* next is the (optional) U_PMF_PENOPTIONALDATA part or a terminator */ + {(Pod ? Pod->Data + 4 : NULL), (Pod ? Pod->Used - 4 : 0), (Pod ? 1 : 0), (Pod ? U_XE : U_XX)}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_PENDATA_OID, List); + return(po); +} + +/** + \brief Create and set a U_PMF_PENOPTIONALDATA PseudoObject + \return Pointer to PseudoObject, NULL on error. Returned PO contains first the Flags, then the PO proper. + \param Flags Determines which of the values are stored. + \param Tm U_PSEUDO_OBJ containing a U_PMF_TRANSFORMMATRIX object (Transformation matrix) + \param StartCap LineCapType enumeration + \param EndCap LineCapType enumeration + \param Join LineJoinType enumeration + \param MiterLimit Maximum (miter length / line width) + \param Style LineStyle enumeration + \param DLCap DashedLineCapType enumeration + \param DLOffset Distance line start to first dash start + \param DLData U_PSEUDO_OBJ containing a U_PMF_DASHEDLINEDATA object Dash and space widths + \param PenAlignment PenAlignment enumeration + \param CmpndLineData U_PSEUDO_OBJ containing a U_PMF_COMPOUNDLINEDATA object Compount Line (parallel lines drawn instead of one) + \param CSCapData U_PSEUDO_OBJ containing a U_PMF_CUSTOMSTARTCAPDATA object Custom start cap + \param CECapData U_PSEUDO_OBJ containing a U_PMF_CUSTOMENDCAPDATA object Custom end cap + + + EMF+ manual 2.2.2.34, Microsoft name: EmfPlusPenOptionalData Object +*/ +U_PSEUDO_OBJ *U_PMF_PENOPTIONALDATA_set(uint32_t Flags, U_PSEUDO_OBJ *Tm, int32_t StartCap, int32_t EndCap, uint32_t Join, + U_FLOAT MiterLimit, int32_t Style, int32_t DLCap, U_FLOAT DLOffset, + U_PSEUDO_OBJ *DLData, int32_t PenAlignment, U_PSEUDO_OBJ *CmpndLineData, U_PSEUDO_OBJ *CSCapData, + U_PSEUDO_OBJ *CECapData + ){ + + if((Flags & U_PD_Transform) && (!Tm || (Tm->Type != U_PMF_TRANSFORMMATRIX_OID)) )return(NULL); + if((Flags & U_PD_DLData) && (!DLData || (DLData->Type != U_PMF_DASHEDLINEDATA_OID)) )return(NULL); + if((Flags & U_PD_CLData) && (!CmpndLineData || (CmpndLineData->Type != U_PMF_COMPOUNDLINEDATA_OID)) )return(NULL); + if((Flags & U_PD_CustomStartCap) && (!CSCapData || (CSCapData->Type != U_PMF_CUSTOMSTARTCAPDATA_OID)))return(NULL); + if((Flags & U_PD_CustomEndCap) && (!CECapData || (CECapData->Type != U_PMF_CUSTOMENDCAPDATA_OID)) )return(NULL); + + /* prepend the Flags field to the PseudoObject proper */ + const U_SERIAL_DESC List[] = { + {&Flags, 4, 1, U_LE}, + {((Flags & U_PD_Transform) ? Tm->Data : NULL), ((Flags & U_PD_Transform) ? Tm->Used : 0), 1, U_XE}, + {((Flags & U_PD_StartCap ) ? (char *)&StartCap : NULL), ((Flags & U_PD_StartCap ) ? 4 : 0), 1, U_LE}, + {((Flags & U_PD_EndCap ) ? (char *)&EndCap : NULL), ((Flags & U_PD_EndCap ) ? 4 : 0), 1, U_LE}, + {((Flags & U_PD_Join ) ? (char *)&Join : NULL), ((Flags & U_PD_Join ) ? 4 : 0), 1, U_LE}, + {((Flags & U_PD_MiterLimit ) ? (char *)&MiterLimit : NULL), ((Flags & U_PD_MiterLimit ) ? 4 : 0), 1, U_LE}, + {((Flags & U_PD_LineStyle ) ? (char *)&Style : NULL), ((Flags & U_PD_LineStyle ) ? 4 : 0), 1, U_LE}, + {((Flags & U_PD_DLCap ) ? (char *)&DLCap : NULL), ((Flags & U_PD_DLCap ) ? 4 : 0), 1, U_LE}, + {((Flags & U_PD_DLOffset ) ? (char *)&DLOffset : NULL), ((Flags & U_PD_DLOffset ) ? 4 : 0), 1, U_LE}, + {((Flags & U_PD_DLData ) ? DLData->Data : NULL), ((Flags & U_PD_DLData ) ? DLData->Used : 0), 1, U_XE}, + {((Flags & U_PD_NonCenter ) ? (char *)&PenAlignment : NULL), ((Flags & U_PD_NonCenter ) ? 4 : 0), 1, U_LE}, + {((Flags & U_PD_CLData ) ? CmpndLineData->Data : NULL), ((Flags & U_PD_CLData ) ? CmpndLineData->Used : 0), 1, U_XE}, + {((Flags & U_PD_CustomStartCap) ? CSCapData->Data : NULL), ((Flags & U_PD_CustomStartCap) ? CSCapData->Used : 0), 1, U_XE}, + {((Flags & U_PD_CustomEndCap ) ? CECapData->Data : NULL), ((Flags & U_PD_CustomEndCap ) ? CECapData->Used : 0), 1, U_XE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_PENOPTIONALDATA_OID, List); + return(po); +} + +/** + \brief Create and set an ARRAY of U_PMF_POINT objects + \return Pointer to PseudoObject, NULL on error + \param Elements Number of pairs of points in Coords + \param Coords Array of X,Y pairs. + + EMF+ manual 2.2.2.35, Microsoft name: EmfPlusPoint Object +*/ +U_PSEUDO_OBJ *U_PMF_POINT_set(uint32_t Elements, const U_PMF_POINT *Coords){ + if(!Elements || !Coords)return(NULL); + const U_SERIAL_DESC List[] = { + {&Elements, 4, 1, U_LE}, + { Coords, 2, 2*Elements, U_LE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_POINT_OID | U_PMF_ARRAY_OID, List); + return(po); +} + +/** + \brief Create and set an ARRAY of U_PMF_POINTF objects, with a leading Elements value + \return Pointer to PseudoObject, NULL on error + \param Elements Number of pairs of points in Coords + \param Coords Array of X,Y pairs. + + EMF+ manual 2.2.2.36, Microsoft name: EmfPlusPointF Object +*/ +U_PSEUDO_OBJ *U_PMF_POINTF_set(uint32_t Elements, const U_PMF_POINTF *Coords){ + if(!Elements || !Coords)return(NULL); + const U_SERIAL_DESC List[] = { + {&Elements, 4, 1, U_LE}, + {Coords, 4, 2*Elements, U_LE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_POINTF_OID | U_PMF_ARRAY_OID, List); + return(po); +} + +/** + \brief Create and set an ARRAY of U_PMF_POINTR objects + \return Pointer to PseudoObject, NULL on error + \param Elements Number of pairs of points in Coords + \param Coords Array of X,Y pairs. These are absolute coordinates, they are converted to Relative here. + + EMF+ manual 2.2.2.37, Microsoft name: EmfPlusPointR Object +*/ +U_PSEUDO_OBJ *U_PMF_POINTR_set(uint32_t Elements, const U_PMF_POINTF *Coords){ + int X,Y; + U_FLOAT Xf,Yf; + U_PSEUDO_OBJ *poi; + /* Worst case scenario it is 4 bytes per coord, plus the count */ + U_PSEUDO_OBJ *po = U_PO_create(NULL, 4 + 4*Elements, 0, U_PMF_POINTR_OID); /* not exactly an array, so no U_PMF_ARRAY_OID */ + U_PSEUDO_OBJ *holdpo = po; + if(!po)goto end; + + poi = U_PMF_4NUM_set(Elements); + po = U_PO_append(po, poi->Data, poi->Used); + U_PO_free(&poi); + if(!po)goto end; + + for(Xf = Yf = 0.0 ;Elements; Elements--, Coords++){ + Xf = U_ROUND(Coords->X) - Xf; + Yf = U_ROUND(Coords->Y) - Yf; + X = ( Xf >= UINT16_MAX ? UINT16_MAX : ( Xf <= INT16_MIN ? INT16_MIN : Xf)); + Y = ( Yf >= UINT16_MAX ? UINT16_MAX : ( Yf <= INT16_MIN ? INT16_MIN : Yf)); + Xf = U_ROUND(Coords->X); + Yf = U_ROUND(Coords->Y); + + /* this is not a very efficient method, too much mucking around with memory */ + + poi = U_PMF_INTEGER7_set(X); + if(!poi)poi = U_PMF_INTEGER15_set(X); /* This one must work because of the range checking, above */ + po = U_PO_append(po, poi->Data, poi->Used); + U_PO_free(&poi); + if(!po)goto end; + + poi = U_PMF_INTEGER7_set(Y); + if(!poi)poi = U_PMF_INTEGER15_set(Y); /* This one must work because of the range checking, above */ + po = U_PO_append(po, poi->Data, poi->Used); + U_PO_free(&poi); + if(!po)goto end; + } + /* Because the values stored were some unpredictable combination of 1 and 2 bytes, the last byte may not end + on a 4 byte boundary. Make it do so by padding with up to 3 zero bytes. */ + + int residual; + residual = 3 & po->Used; + if(residual){ + po = U_PO_append(po, NULL, (4 - residual)); + if(!po)goto end; + } + +end: + if(!po)U_PO_free(&holdpo); + return(holdpo); +} + +/** + \brief Create and set a U_PMF_RECT object + \return Pointer to PseudoObject, NULL on error + \param X UL X value + \param Y UL Y value + \param Width Width + \param Height Height + + EMF+ manual 2.2.2.38, Microsoft name: EmfPlusRect Object +*/ +U_PSEUDO_OBJ *U_PMF_RECT4_set(int16_t X, int16_t Y, int16_t Width, int16_t Height){ + const U_SERIAL_DESC List[] = { + {&X, 2, 1, U_LE}, + {&Y, 2, 1, U_LE}, + {&Width, 2, 1, U_LE}, + {&Height, 2, 1, U_LE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_RECT_OID, List); + return(po); +} + +/** + \brief Create and set a U_PMF_RECT object + \return Pointer to PseudoObject, NULL on error + \param Rect U_PMF_RECT structures + + EMF+ manual 2.2.2.38, Microsoft name: EmfPlusRect Object +*/ +U_PSEUDO_OBJ *U_PMF_RECT_set(U_PMF_RECT *Rect){ + const U_SERIAL_DESC List[] = { + {Rect, 2, 4, U_LE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_RECT_OID, List); + return(po); +} + +/** + \brief Create and set an array of U_PMF_RECT objects in a PseudoObject + \return Pointer to PseudoObject, NULL on error. PseudoObject contains Elements followed by the array of U_PMF_RECT objects. + \param Elements Number of elements in Rects + \param Rects Array of U_PMF_RECT structures + + EMF+ manual 2.2.2.38, Microsoft name: EmfPlusRect Object +*/ +U_PSEUDO_OBJ *U_PMF_RECTN_set(uint32_t Elements, U_PMF_RECT *Rects){ + if(!Rects){ return(NULL); } + uint32_t count = Elements; + U_SERIAL_DESC *List = (U_SERIAL_DESC *) malloc((Elements + 2) * sizeof(U_SERIAL_DESC)); + U_SERIAL_DESC *Lptr = List; + if(!List){ return(NULL); } + *Lptr++ = (U_SERIAL_DESC){&Elements, 4, 1, U_LE}; + for(; count; count--, Lptr++, Rects++){ + *Lptr = (U_SERIAL_DESC){Rects, 2, 4, U_LE}; + } + *Lptr = (U_SERIAL_DESC){NULL,0,0,U_XX}; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_RECT_OID | U_PMF_ARRAY_OID, List); + free(List); + return(po); +} + +/** + \brief Create and set a U_PMF_RECTF object in a PseudoObject + \return Pointer to PseudoObject, NULL on error + \param X UL X value + \param Y UL Y value + \param Width Width + \param Height Height + + EMF+ manual 2.2.2.39, Microsoft name: EmfPlusRectF Object +*/ +U_PSEUDO_OBJ *U_PMF_RECTF4_set(U_FLOAT X, U_FLOAT Y, U_FLOAT Width, U_FLOAT Height){ + const U_SERIAL_DESC List[] = { + {&X, 4, 1, U_LE}, + {&Y, 4, 1, U_LE}, + {&Width, 4, 1, U_LE}, + {&Height, 4, 1, U_LE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_RECTF_OID, List); + return(po); +} + +/** + \brief Create and set a U_PMF_RECTF object in a PseudoObject + \return Pointer to PseudoObject, NULL on error + \param Rect U_PMF_RECTF structure + + EMF+ manual 2.2.2.39, Microsoft name: EmfPlusRectF Object +*/ +U_PSEUDO_OBJ *U_PMF_RECTF_set(U_PMF_RECTF *Rect){ + const U_SERIAL_DESC List[] = { + {Rect, 4, 4, U_LE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_RECTF_OID, List); + return(po); +} + +/** + \brief Create and set an array of U_PMF_RECTF objects in a PseudoObject + \return Pointer to PseudoObject, NULL on error. PseudoObject contains Elements followed by the array of U_PMF_RECTF objects. + \param Elements Number of elements in Rects + \param Rects Array of U_PMF_RECTF structures + + EMF+ manual 2.2.2.39, Microsoft name: EmfPlusRectF Object +*/ +U_PSEUDO_OBJ *U_PMF_RECTFN_set(uint32_t Elements, U_PMF_RECTF *Rects){ + if(!Rects){ return(NULL); } + uint32_t count = Elements; + U_SERIAL_DESC *List = (U_SERIAL_DESC *) malloc((Elements + 2) * sizeof(U_SERIAL_DESC)); + U_SERIAL_DESC *Lptr = List; + if(!List){ return(NULL); } + *Lptr++ = (U_SERIAL_DESC){&Elements, 4, 1, U_LE}; + for(; count; count--, Lptr++, Rects++){ + *Lptr = (U_SERIAL_DESC){Rects, 4, 4, U_LE}; + } + *Lptr = (U_SERIAL_DESC){NULL,0,0,U_XX}; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_RECTF_OID | U_PMF_ARRAY_OID, List); + free(List); + return(po); +} + +/** + \brief Create and set a U_PMF_REGIONNODE PseudoObject + \return Pointer to PseudoObject, NULL on error + \param Type RegionNodeDataType Enumeration + \param Rnd (optional) U_PSEUDO_OBJ containing a U_PMF_REGIONNODEPATH, U_PMF_RECTF, or U_PMF_REGIONNODECHILDNODES object (Region Node Data) + + + EMF+ manual 2.2.2.40, Microsoft name: EmfPlusRegionNode Object +*/ +U_PSEUDO_OBJ *U_PMF_REGIONNODE_set(int32_t Type, const U_PSEUDO_OBJ *Rnd){ + int32_t pType; + /* make sure that the type of Rnd agrees with Type */ + if(Rnd){ + pType = U_OID_To_RNDT(Rnd->Type); + if( pType < 0){ return(NULL); } + if((pType > 0) && (pType != Type)){ return(NULL); } + if((pType == 0) && + ( + (Type < U_RNDT_And) || + (Type > U_RNDT_Complement) + ) + ){ return(NULL); } + if((Type == U_RNDT_Rect) && (Rnd->Type != U_PMF_RECTF_OID)){ return(NULL); } + if((Type == U_RNDT_Path) && (Rnd->Type != U_PMF_REGIONNODEPATH_OID)){ return(NULL); } + + } + else { /* only U_RNDT_Empty and U_RNDT_Infinite do not have data */ + if((Type != U_RNDT_Empty) || + (Type != U_RNDT_Infinite) ){ return(NULL); } + } + + + const U_SERIAL_DESC List[] = { + {&Type, 4, 1, U_LE}, + {(Rnd ? Rnd->Data : NULL), (Rnd ? Rnd->Used : 0), 1, U_XE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_REGIONNODE_OID, List); + return(po); +} + +/** + \brief Create and set a U_PMF_REGIONNODECHILDNODES PseudoObject + \return Pointer to PseudoObject containing a U_PMF_REGIONNODECHILDNODES_OID object, NULL on error + \param Left U_PSEUDO_OBJ containing a U_PMF_REGIONNODE object + \param Right U_PSEUDO_OBJ containing a U_PMF_REGIONNODE object + + + EMF+ manual 2.2.2.41, Microsoft name: EmfPlusRegionNodeChildNodes Object +*/ +U_PSEUDO_OBJ *U_PMF_REGIONNODECHILDNODES_set(const U_PSEUDO_OBJ *Left, const U_PSEUDO_OBJ *Right){ + if(!Left || (Left->Type != U_PMF_REGIONNODE_OID)){ return(NULL); } + if(!Right || (Right->Type != U_PMF_REGIONNODE_OID)){ return(NULL); } + + const U_SERIAL_DESC List[] = { + {Left->Data, Left->Used, 1, U_XE}, + {Right->Data, Right->Used, 1, U_XE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_REGIONNODECHILDNODES_OID, List); + return(po); +} + +/** + \brief Create and set a U_PMF_REGIONNODEPATH PseudoObject + \return Pointer to PseudoObject, NULL on error + \param Path U_PSEUDO_OBJ containing a U_PMF_PATH object + + + EMF+ manual 2.2.2.42, Microsoft name: EmfPlusRegionNodePath Object +*/ +U_PSEUDO_OBJ *U_PMF_REGIONNODEPATH_set(const U_PSEUDO_OBJ *Path){ + if(!Path || (Path->Type != U_PMF_PATH_OID)){ return(NULL); } + /* PO Used is size_t, might be 8 bytes, value in record must be 4 bytes */ + uint32_t Used = Path->Used; + + const U_SERIAL_DESC List[] = { + {&Used, 4, 1, U_LE}, + {Path->Data, Path->Used, 1, U_XE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_REGIONNODEPATH_OID, List); + return(po); +} + +/** + \brief Create and set a U_PMF_SOLIDBRUSHDATA PseudoObject + \return Pointer to PseudoObject, NULL on error + \param Color U_PSEUDO_OBJ containing a U_PMF_ARGB object + + + EMF+ manual 2.2.2.43, Microsoft name: EmfPlusSolidBrushData Object +*/ +U_PSEUDO_OBJ *U_PMF_SOLIDBRUSHDATA_set(const U_PSEUDO_OBJ *Color){ + if(!Color || (Color->Type != U_PMF_ARGB_OID)){ return(NULL); } + + const U_SERIAL_DESC List[] = { + {Color->Data, Color->Used, 1, U_XE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_SOLIDBRUSHDATA_OID, List); + return(po); +} + +/** + \brief Create and set a U_PMF_STRINGFORMATDATA PseudoObject + \return Pointer to PseudoObject, NULL on error + \param TabStopCount Entries in TabStop array + \param TabStops (optional) Array of tabstop locations + \param Ranges (optional) U_PSEUDO_OBJ containing an array of U_PMF_CHARACTERRANGE objects + + + EMF+ manual 2.2.2.44, Microsoft name: EmfPlusStringFormatData Object +*/ +U_PSEUDO_OBJ *U_PMF_STRINGFORMATDATA_set(uint32_t TabStopCount, U_FLOAT *TabStops, const U_PSEUDO_OBJ *Ranges){ + if(Ranges && (Ranges->Type != (U_PMF_CHARACTERRANGE_OID | U_PMF_ARRAY_OID))){ return(NULL); } + + const U_SERIAL_DESC List[] = { + {TabStops, TabStopCount*4, 1, U_LE}, + {(Ranges ? Ranges->Data : NULL), (Ranges ? Ranges->Used : 0), 1, U_XE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_STRINGFORMATDATA_OID, List); + return(po); +} + +/** + \brief Create and set a U_PMF_TEXTUREBRUSHDATA PseudoObject + \return Pointer to PseudoObject, NULL on error + \param Flags BrushData flags + \param WrapMode WrapMode enumeration + \param Tbod U_PSEUDO_OBJ containing an U_PMF_TEXTUREBRUSHOPTIONALDATA object + + + EMF+ manual 2.2.2.45, Microsoft name: EmfPlusTextureBrushData Object +*/ +U_PSEUDO_OBJ *U_PMF_TEXTUREBRUSHDATA_set(uint32_t Flags, uint32_t WrapMode, const U_PSEUDO_OBJ *Tbod){ + if(Flags & ~U_BD_MASKB){ return(NULL); } /* a bit was set that is not supported for this record */ + if(WrapMode > U_WM_Clamp){ return(NULL); } + if(!Tbod || (Tbod->Type != (U_PMF_TEXTUREBRUSHOPTIONALDATA_OID))){ return(NULL); } + + const U_SERIAL_DESC List[] = { + {&Flags, 4, 1, U_LE}, + {&WrapMode, 4, 1, U_LE}, + {Tbod->Data, Tbod->Used, 1, U_XE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_TEXTUREBRUSHDATA_OID, List); + return(po); +} + +/** + \brief Create and set a U_PMF_TEXTUREBRUSHOPTIONALDATA PseudoObject + \return Pointer to PseudoObject, NULL on error + \param Tm (optional) U_PSEUDO_OBJ containing an U_PMF_TRANSFORMMATRIX object + \param Image (optional) U_PSEUDO_OBJ containing an U_PMF_IMAGE object + + + EMF+ manual 2.2.2.46, Microsoft name: EmfPlusTextureBrushOptionalData Object +*/ +U_PSEUDO_OBJ *U_PMF_TEXTUREBRUSHOPTIONALDATA_set(const U_PSEUDO_OBJ *Tm, const U_PSEUDO_OBJ *Image){ + if(Tm && (Tm->Type != (U_PMF_TRANSFORMMATRIX_OID))){ return(NULL); } + if(Image && (Image->Type != (U_PMF_IMAGE_OID))){ return(NULL); } + + const U_SERIAL_DESC List[] = { + {(Tm ? Tm->Data : NULL), (Tm ? Tm->Used : 0), 1, U_XE}, + {(Image ? Image->Data : NULL), (Image ? Image->Used : 0), 1, U_XE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_TEXTUREBRUSHOPTIONALDATA_OID, List); + return(po); +} + +/** + \brief Create and set a U_PMF_TRANSFORMMATRIX PseudoObject + \return Pointer to PseudoObject, NULL on error + \param Tm U_PMF_TRANSFORMMATRIX_ object + + + EMF+ manual 2.2.2.47, Microsoft name: EmfPlusTransformMatrix Object +*/ +U_PSEUDO_OBJ *U_PMF_TRANSFORMMATRIX_set(U_PMF_TRANSFORMMATRIX *Tm){ + if(!Tm){ return(NULL); } + + const U_SERIAL_DESC List[] = { + {Tm, 4, 6, U_LE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_TRANSFORMMATRIX_OID, List); + return(po); +} + +/** + \brief Create and set a U_PMF_IE_BLUR PseudoObject + \return Pointer to PseudoObject, NULL on error + \param Radius Blur radius in pixels + \param ExpandEdge 1: expand bitmap by Radius; 0: bitmap size unchanged + + + EMF+ manual 2.2.3.1, Microsoft name: BlurEffect Object +*/ +U_PSEUDO_OBJ *U_PMF_IE_BLUR_set(U_FLOAT Radius, uint32_t ExpandEdge){ + + const U_SERIAL_DESC List[] = { + {&Radius, 4, 1, U_LE}, + {&ExpandEdge, 4, 1, U_LE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_IE_BLUR_OID, List); + return(po); +} + +/** + \brief Create and set a U_PMF_IE_BRIGHTNESSCONTRAST PseudoObject + \return Pointer to PseudoObject, NULL on error + \param Brightness -255 to 255, 0 is unchanged, positive increases, negative decreases + \param Contrast -100 to 100, 0 is unchanged, positive increases, negative decreases + + + EMF+ manual 2.2.3.2, Microsoft name: BrightnessContrastEffect Object +*/ +U_PSEUDO_OBJ *U_PMF_IE_BRIGHTNESSCONTRAST_set(int32_t Brightness, int32_t Contrast){ + + const U_SERIAL_DESC List[] = { + {&Brightness, 4, 1, U_LE}, + {&Contrast, 4, 1, U_LE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_IE_BRIGHTNESSCONTRAST_OID, List); + return(po); +} + +/** + \brief Create and set a U_PMF_IE_COLORBALANCE PseudoObject + \return Pointer to PseudoObject, NULL on error + \param CyanRed -100 to 100, 0 is unchanged, positive increases Red & decreases Cyan, negative is opposite + \param MagentaGreen -100 to 100, 0 is unchanged, positive increases Green & decreases Magenta, negative is opposite + \param YellowBlue -100 to 100, 0 is unchanged, positive increases Blue & decreases Yellow, negative is opposite + + + EMF+ manual 2.2.3.3, Microsoft name: ColorBalanceEffect Object +*/ +U_PSEUDO_OBJ *U_PMF_IE_COLORBALANCE_set(int32_t CyanRed, int32_t MagentaGreen, int32_t YellowBlue){ + + const U_SERIAL_DESC List[] = { + {&CyanRed, 4, 1, U_LE}, + {&MagentaGreen, 4, 1, U_LE}, + {&YellowBlue, 4, 1, U_LE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_IE_COLORBALANCE_OID, List); + return(po); +} + +/** + \brief Create and set a U_PMF_IE_COLORCURVE PseudoObject + \return Pointer to PseudoObject, NULL on error + \param Adjust CurveAdjustment enumeration + \param Channel CurveChannel enumeration + \param Intensity adjustment to apply. "Adjust" determines what field this is and range values. + + + EMF+ manual 2.2.3.4, Microsoft name: ColorCurveEffect Object +*/ +U_PSEUDO_OBJ *U_PMF_IE_COLORCURVE_set(uint32_t Adjust, uint32_t Channel, int32_t Intensity){ + + const U_SERIAL_DESC List[] = { + {&Adjust, 4, 1, U_LE}, + {&Channel, 4, 1, U_LE}, + {&Intensity, 4, 1, U_LE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_IE_COLORCURVE_OID, List); + return(po); +} + +/** + \brief Create and set a U_PMF_IE_COLORLOOKUPTABLE PseudoObject + \return Pointer to PseudoObject, NULL on error + \param BLUT Blue color lookup table + \param GLUT Green color lookup table + \param RLUT Red color lookup table + \param ALUT Alpha color lookup table + + + + EMF+ manual 2.2.3.5, Microsoft name: ColorLookupTableEffect Object. + All tables have 256 entries. +*/ +U_PSEUDO_OBJ *U_PMF_IE_COLORLOOKUPTABLE_set(const uint8_t *BLUT, const uint8_t *GLUT, const uint8_t *RLUT, const uint8_t *ALUT){ + if(!BLUT || !GLUT || !RLUT || !ALUT)return(NULL); + + const U_SERIAL_DESC List[] = { + {BLUT, 1, 256, U_XE}, + {GLUT, 1, 256, U_XE}, + {RLUT, 1, 256, U_XE}, + {ALUT, 1, 256, U_XE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_IE_COLORLOOKUPTABLE_OID, List); + return(po); +} + +/** + \brief Create and set a U_PMF_IE_COLORMATRIX PseudoObject + \return Pointer to PseudoObject, NULL on error + \param Matrix 5 x 5 color transformation matrix, First 4 rows are [{4 multiplier values},0.0] for R,G,B,A, last Row is [{4 color translation valuess}, 1.0] + + + EMF+ manual 2.2.3.6, Microsoft name: ColorMatrixEffect Object +*/ +U_PSEUDO_OBJ *U_PMF_IE_COLORMATRIX_set(const U_FLOAT *Matrix){ + if(!Matrix)return(NULL); + + const U_SERIAL_DESC List[] = { + {Matrix, 4, 25, U_LE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_IE_COLORMATRIX_OID, List); + return(po); +} + +/** + \brief Create and set a U_PMF_IE_HUESATURATIONLIGHTNESS PseudoObject + \return Pointer to PseudoObject, NULL on error + \param Hue -180 to 180, 0 is unchanged + \param Saturation -100 to 100, 0 is unchanged + \param Lightness -100 to 100, 0 is unchanged + + + EMF+ manual 2.2.3.7, Microsoft name: HueSaturationLightnessEffect Object +*/ +U_PSEUDO_OBJ *U_PMF_IE_HUESATURATIONLIGHTNESS_set(int32_t Hue, int32_t Saturation, int32_t Lightness){ + + const U_SERIAL_DESC List[] = { + {&Hue, 4, 1, U_LE}, + {&Saturation, 4, 1, U_LE}, + {&Lightness, 4, 1, U_LE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_IE_HUESATURATIONLIGHTNESS_OID, List); + return(po); +} + +/** + \brief Create and set a U_PMF_IE_LEVELS PseudoObject + \return Pointer to PseudoObject, NULL on error + \param Highlight 0 to 100, 100 is unchanged + \param Midtone -100 to 0, 0 is unchanged + \param Shadow 0 to 100, 0 is unchanged + + + EMF+ manual 2.2.3.8, Microsoft name: LevelsEffect Object +*/ +U_PSEUDO_OBJ *U_PMF_IE_LEVELS_set(int32_t Highlight, int32_t Midtone, int32_t Shadow){ + + const U_SERIAL_DESC List[] = { + {&Highlight, 4, 1, U_LE}, + {&Midtone, 4, 1, U_LE}, + {&Shadow, 4, 1, U_LE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_IE_LEVELS_OID, List); + return(po); +} + +/** + \brief Create and set a U_PMF_IE_REDEYECORRECTION PseudoObject + \return Pointer to PseudoObject, NULL on error + \param Elements Number of members in Rects + \param Rects Array of U_RECTL rectangular area(s) to apply red eye correction + + + EMF+ manual 2.2.3.9, Microsoft name: RedEyeCorrectionEffect Object +*/ +U_PSEUDO_OBJ *U_PMF_IE_REDEYECORRECTION_set(uint32_t Elements, const U_RECTL *Rects){ + if(!Elements || !Rects){return(NULL);} + + const U_SERIAL_DESC List[] = { + {&Elements, 4, 1, U_LE}, + {Rects, 4*4, Elements,U_LE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_IE_REDEYECORRECTION_OID, List); + return(po); +} + +/** + \brief Create and set a U_PMF_IE_SHARPEN PseudoObject + \return Pointer to PseudoObject, NULL on error + \param Radius Sharpening radius in pixels + \param Sharpen 0 to 100, 0 is unchanged + + + EMF+ manual 2.2.3.10, Microsoft name: SharpenEffect Object +*/ +U_PSEUDO_OBJ *U_PMF_IE_SHARPEN_set(U_FLOAT Radius, int32_t Sharpen){ + + const U_SERIAL_DESC List[] = { + {&Radius, 4, 1, U_LE}, + {&Sharpen, 4, 1, U_LE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_IE_SHARPEN_OID, List); + return(po); +} + +/** + \brief Create and set a U_PMF_IE_TINT PseudoObject + \return Pointer to PseudoObject, NULL on error + \param Hue -180 to 180, [positive==clockwise] rotation in degrees starting from blue + \param Amount -100 [add black] to 100[add white], 0 is unchanged. Change in hue on specified axis + + + EMF+ manual 2.2.3.11, Microsoft name: TintEffect Object +*/ +U_PSEUDO_OBJ *U_PMF_IE_TINT_set(const int32_t Hue, const int32_t Amount){ + + const U_SERIAL_DESC List[] = { + {&Hue, 4, 1, U_LE}, + {&Amount, 4, 1, U_LE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_IE_TINT_OID, List); + return(po); +} + +//! \cond +/* internal routine, not part of the API. + Returns a PseudoObject containing a U_PMR_CMN_HDR_OID object. + The type is something like U_PMR_OFFSETCLIP (the record type, NOT the U_PMR_OFFSETCLIP_OID PseudoObject Type!). + The U_PMR_RECFLAG bit is added both in the data and in the Type of the PseudoObject. + If that bit is already set no harm, no foul. +*/ + +U_PSEUDO_OBJ *U_PMR_CMN_HDR_set(uint32_t Type, uint16_t Flags, uint32_t DataSize){ + + uint32_t Size = 12 + UP4(DataSize); /* The header itself is always 12, PMR records must be a multiple of 4 */ + Type |= U_PMR_RECFLAG; + uint16_t utmp16 = Type; + const U_SERIAL_DESC List[] = { + {&utmp16, 2, 1, U_LE}, + {&Flags, 2, 1, U_LE}, /* Microsoft EMF+ manual is BE, but this field in this implementation is LE */ + {&Size, 4, 1, U_LE}, + {&DataSize, 4, 1, U_LE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_CMN_HDR_OID, List); + return(po); +} +//! \endcond + + +/** + \brief Create and set a U_PMR_STROKEFILLPATH PseudoObject + \return Pointer to PseudoObject, NULL on error + + + EMF+ manual mentioned in 2.1.1.1, not otherwise documented, Microsoft name: EmfPlusStrokeFillPath Record, Index 0x37 + + "This record closes any open figures in a path, strokes the outline of + the path by using the current pen, and fills its interior by using the current brush." + +*/ +U_PSEUDO_OBJ *U_PMR_STROKEFILLPATH_set(void){ + int Size = 0; + uint16_t utmp16 = 0; + U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_STROKEFILLPATH,utmp16,Size); + const U_SERIAL_DESC List[] = { + {ph->Data, ph->Used, 1, U_XE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_STROKEFILLPATH_OID, List); + U_PO_free(&ph); + return(po); +} + +/** + \brief Create and set a U_PMR_OFFSETCLIP PseudoObject + \return Pointer to PseudoObject, NULL on error + \param dX horizontal translation offset to apply to clipping region + \param dY vertical translation offset to apply to clipping region + + + EMF+ manual 2.3.1.1, Microsoft name: EmfPlusOffsetClip Record, Index 0x35 +*/ +U_PSEUDO_OBJ *U_PMR_OFFSETCLIP_set(U_FLOAT dX, U_FLOAT dY){ + int Size = 2*4; + U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_OFFSETCLIP,0,Size); + const U_SERIAL_DESC List[] = { + {ph->Data, ph->Used, 1, U_XE}, + {&dX, 4, 1, U_LE}, + {&dY, 4, 1, U_LE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_OFFSETCLIP_OID, List); + U_PO_free(&ph); + return(po); +} + +/** + \brief Create and set a U_PMR_RESETCLIP PseudoObject + \return Pointer to PseudoObject, NULL on error + + + EMF+ manual 2.3.1.2, Microsoft name: EmfPlusResetClip Record, Index 0x31 +*/ +U_PSEUDO_OBJ *U_PMR_RESETCLIP_set(void){ + int Size = 0; + U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_RESETCLIP,0,Size); + const U_SERIAL_DESC List[] = { + {ph->Data, ph->Used, 1, U_XE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_RESETCLIP_OID, List); + U_PO_free(&ph); + return(po); +} + +/** + \brief Create and set a U_PMR_SETCLIPPATH PseudoObject + \return Pointer to PseudoObject, NULL on error + \param CMenum CombineMode enumeration.. + \param PathID U_PMF_PATH object in the EMF+ object table (0-63, inclusive) + + + EMF+ manual 2.3.1.3, Microsoft name: EmfPlusSetClipPath Record, Index 0x33 +*/ +U_PSEUDO_OBJ *U_PMR_SETCLIPPATH_set(uint32_t PathID, uint32_t CMenum){ + if(PathID>63)return(NULL); + int Size=0; + uint16_t utmp16 = ((PathID & U_FF_MASK_OID8) << U_FF_SHFT_OID8) | ((CMenum & U_FF_MASK_CM4) << U_FF_SHFT_CM4); + U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_SETCLIPPATH,utmp16,Size); + const U_SERIAL_DESC List[] = { + {ph->Data, ph->Used, 1, U_XE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_SETCLIPPATH_OID, List); + U_PO_free(&ph); + return(po); +} + +/** + \brief Create and set a U_PMR_SETCLIPRECT PseudoObject + \return Pointer to PseudoObject, NULL on error + \param CMenum CombineMode enumeration.. + \param Rect U_PSEUDO_OBJ containing an U_PMF_RECTF object or an array of U_PMF_RECTF objects (the first is used) + + + EMF+ manual 2.3.1.4, Microsoft name: EmfPlusSetClipRect Record, Index 0x32 +*/ +U_PSEUDO_OBJ *U_PMR_SETCLIPRECT_set(uint32_t CMenum, const U_PSEUDO_OBJ *Rect){ + int Size=4*4; + const char *start; + uint16_t utmp16 = ((CMenum & U_FF_MASK_CM4) << U_FF_SHFT_CM4); + if(Rect){ + if( Rect->Type == U_PMF_RECTF_OID){ + start = Rect->Data; + } + else if(Rect->Type == (U_PMF_RECTF_OID | U_PMF_ARRAY_OID)){ + start = Rect->Data + 4; + } + else { return(0); } + } + else { return(0); } + + U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_SETCLIPRECT,utmp16,Size); + const U_SERIAL_DESC List[] = { + {ph->Data, ph->Used, 1, U_XE}, + {start, 4, 4, U_XE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_SETCLIPRECT_OID, List); + U_PO_free(&ph); + return(po); +} + +/** + \brief Create and set a U_PMR_SETCLIPREGION PseudoObject + \return Pointer to PseudoObject, NULL on error + \param PathID U_PMF_PATH object in the EMF+ object table (0-63, inclusive) + \param CMenum CombineMode enumeration.. + + + EMF+ manual 2.3.1.5, Microsoft name: EmfPlusSetClipRegion Record, Index 0x34 +*/ +U_PSEUDO_OBJ *U_PMR_SETCLIPREGION_set(uint32_t PathID, uint32_t CMenum){ + if(PathID>63)return(NULL); + int Size=0; + uint16_t utmp16 = ((PathID & U_FF_MASK_OID8) << U_FF_SHFT_OID8) | ((CMenum & U_FF_MASK_CM4) << U_FF_SHFT_CM4); + + U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_SETCLIPREGION,utmp16,Size); + const U_SERIAL_DESC List[] = { + {ph->Data, ph->Used, 1, U_XE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_SETCLIPREGION_OID, List); + U_PO_free(&ph); + return(po); +} + +/** + \brief Create and set a U_PMR_COMMENT PseudoObject + \return Pointer to PseudoObject, NULL on error + \param cbData Number of bytes in Data, must be a multiple of 4 + \param Data Private data, may be anything. Stored in PseudoObject without adjusting byte order. + + + EMF+ manual 2.3.2.1, Microsoft name: EmfPlusComment Record, Index 0x03 +*/ +U_PSEUDO_OBJ *U_PMR_COMMENT_set(size_t cbData, const void *Data){ + if(UP4(cbData) != cbData){ return(NULL); } + if(cbData && !Data){ return(NULL); } + int Size=cbData; + + U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_COMMENT,0,Size); + const U_SERIAL_DESC List[] = { + {ph->Data, ph->Used, 1, U_XE}, + {Data, cbData, 1, U_XE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_COMMENT_OID, List); + U_PO_free(&ph); + return(po); +} + +/** + \brief Create and set a U_PMR_ENDOFFILE PseudoObject + \return Pointer to PseudoObject, NULL on error + + + EMF+ manual 2.3.3.1, Microsoft name: EmfPlusEndOfFile Record, Index 0x02 +*/ +U_PSEUDO_OBJ *U_PMR_ENDOFFILE_set(void){ + int Size=0; + U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_ENDOFFILE,0,Size); + const U_SERIAL_DESC List[] = { + {ph->Data, ph->Used, 1, U_XE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_ENDOFFILE_OID, List); + U_PO_free(&ph); + return(po); +} + +/** + \brief Create and set a U_PMR_GETDC PseudoObject + \return Pointer to PseudoObject, NULL on error + + + EMF+ manual 2.3.3.2, Microsoft name: EmfPlusGetDC Record, Index 0x04 +*/ +U_PSEUDO_OBJ *U_PMR_GETDC_set(void){ + int Size=0; + U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_GETDC,0,Size); + const U_SERIAL_DESC List[] = { + {ph->Data, ph->Used, 1, U_XE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_GETDC_OID, List); + U_PO_free(&ph); + return(po); +} + +/** + \brief Create and set a U_PMR_HEADER PseudoObject + \return Pointer to PseudoObject, NULL on error + \param IsDual set = Dual-mode file, clear= EMF+ only file. + \param IsVideo set = video device, clear= printer. Ignore all other bits. + \param Version U_PSEUDO_OBJ containing a U_PMF_GRAPHICSVERSION object + \param LogicalDpiX Horizontal resolution reference device in DPI + \param LogicalDpiY Vertical resolution reference device in DPI + + + EMF+ manual 2.3.3.3, Microsoft name: EmfPlusHeader Record, Index 0x01 +*/ +U_PSEUDO_OBJ *U_PMR_HEADER_set(int IsDual, int IsVideo, const U_PSEUDO_OBJ *Version, + uint32_t LogicalDpiX, uint32_t LogicalDpiY){ + if(!Version || (Version->Type != U_PMF_GRAPHICSVERSION_OID)){ return(NULL); } + int Size=Version->Used + 3*4; + uint16_t utmp16 = (IsDual ? U_PPF_DM : 0); + uint32_t Flags = (IsVideo ? U_PPF_VIDEO : 0); + U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_HEADER,utmp16,Size); + const U_SERIAL_DESC List[] = { + {ph->Data, ph->Used, 1, U_XE}, + {Version->Data, Version->Used, 1, U_XE}, + {&Flags, 4, 1, U_LE}, + {&LogicalDpiX, 4, 1, U_LE}, + {&LogicalDpiY, 4, 1, U_LE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_HEADER_OID, List); + U_PO_free(&ph); + return(po); +} + +/** + \brief Create and set a U_PMR_CLEAR PseudoObject + \return Pointer to PseudoObject, NULL on error + \param Color U_PSEUDO_OBJ containing a U_PMF_ARGB object. + + + + EMF+ manual 2.3.4.1, Microsoft name: EmfPlusClear Record, Index 0x09 + + Erase everything preceding, set background ARGB to Color. +*/ +U_PSEUDO_OBJ *U_PMR_CLEAR_set(const U_PSEUDO_OBJ *Color){ + if(!Color || (Color->Type != U_PMF_ARGB_OID)){ return(NULL); } + int Size=Color->Used; + U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_CLEAR,0,Size); + const U_SERIAL_DESC List[] = { + {ph->Data, ph->Used, 1, U_XE}, + {Color->Data, Color->Used, 1, U_XE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_CLEAR_OID, List); + U_PO_free(&ph); + return(po); +} + +/** + \brief Create and set a U_PMR_DRAWARC PseudoObject + \return Pointer to PseudoObject, NULL on error + \param PenID U_PMF_PEN object in the EMF+ object table (0-63, inclusive) + \param Start Start angle, >=0.0, degrees clockwise from 3:00 + \param Sweep Sweep angle, -360<= angle <=360, degrees clockwise from Start + \param Rect U_PSEUDO_OBJ containing a U_PMF_RECT or U_PMF_RECTF object + + + EMF+ manual 2.3.4.2, Microsoft name: EmfPlusDrawArc Record, Index 0x12 +*/ +U_PSEUDO_OBJ *U_PMR_DRAWARC_set(uint32_t PenID, U_FLOAT Start, U_FLOAT Sweep, const U_PSEUDO_OBJ *Rect){ + int ctype; + if(PenID>63)return(NULL); + if(!Rect){ return(NULL); } + else { + if( Rect->Type == U_PMF_RECT_OID ){ ctype = 1; } + else if(Rect->Type == U_PMF_RECTF_OID){ ctype = 0; } + else { return(NULL); } + } + int Size = 2*4 + Rect->Used; + uint16_t utmp16 = (ctype ? U_PPF_C : 0) | (PenID & U_FF_MASK_OID8) << U_FF_SHFT_OID8; + U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_DRAWARC,utmp16,Size); + const U_SERIAL_DESC List[] = { + {ph->Data, ph->Used, 1, U_XE}, + {&Start, 4, 1, U_LE}, + {&Sweep, 4, 1, U_LE}, + {Rect->Data, Rect->Used, 1, U_XE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_DRAWARC_OID, List); + U_PO_free(&ph); + return(po); +} + +/** + \brief Create and set a U_PMR_DRAWBEZIERS PseudoObject + \return Pointer to PseudoObject, NULL on error + \param PenID U_PMF_PEN object in the EMF+ object table (0-63, inclusive) + \param Points U_PSEUDO_OBJ containing first Elements, then a U_PMF_POINT, U_PMF_POINTR or U_PMF_POINTF object + + + EMF+ manual 2.3.4.3, Microsoft name: EmfPlusDrawBeziers Record, Index 0x19 +*/ +U_PSEUDO_OBJ *U_PMR_DRAWBEZIERS_set(uint32_t PenID, const U_PSEUDO_OBJ *Points){ + int ctype, RelAbs; + if(PenID>63)return(NULL); + if(Points){ + if( Points->Type == U_PMF_POINTR_OID){ RelAbs = 1; ctype = 0; } + else if(Points->Type == (U_PMF_POINT_OID | U_PMF_ARRAY_OID)){ RelAbs = 0; ctype = 1; } + else if(Points->Type == (U_PMF_POINTF_OID | U_PMF_ARRAY_OID)){ RelAbs = 0; ctype = 0; } + else { return(NULL); } + } + else { return(NULL); } + int Size = Points->Used; + uint16_t utmp16 = (ctype ? U_PPF_C : 0) | (RelAbs ? U_PPF_P : 0) |(PenID & U_FF_MASK_OID8) << U_FF_SHFT_OID8; + U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_DRAWBEZIERS,utmp16,Size); + const U_SERIAL_DESC List[] = { + {ph->Data, ph->Used, 1, U_XE}, + {Points->Data, Points->Used, 1, U_XE}, /* Includes Elements */ + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_DRAWBEZIERS_OID, List); + U_PO_free(&ph); + return(po); +} + +/** + \brief Create and set a U_PMR_DRAWCLOSEDCURVE PseudoObject + \return Pointer to PseudoObject, NULL on error + \param PenID U_PMF_PEN object in the EMF+ object table (0-63, inclusive) + \param Tension Controls splines, 0 is straight line, >0 is curved + \param Points U_PSEUDO_OBJ containing a U_PMF_POINT, U_PMF_POINTR or U_PMF_POINTF object + + + EMF+ manual 2.3.4.4, Microsoft name: EmfPlusDrawClosedCurve Record, Index 0x17 + + Curve is a cardinal spline. + + References sent by MS support: + + http://alvyray.com/Memos/CG/Pixar/spline77.pdf + + http://msdn.microsoft.com/en-us/library/4cf6we5y(v=vs.110).aspx + + +*/ +U_PSEUDO_OBJ *U_PMR_DRAWCLOSEDCURVE_set(uint32_t PenID, U_FLOAT Tension, const U_PSEUDO_OBJ *Points){ + int ctype, RelAbs; + if(PenID>63)return(NULL); + if(Points){ + if( Points->Type == U_PMF_POINTR_OID){ RelAbs = 1; ctype = 0; } + else if(Points->Type == (U_PMF_POINT_OID | U_PMF_ARRAY_OID)){ RelAbs = 0; ctype = 1; } + else if(Points->Type == (U_PMF_POINTF_OID | U_PMF_ARRAY_OID)){ RelAbs = 0; ctype = 0; } + else { return(NULL); } + } + else { return(NULL); } + int Size = 4 + Points->Used; + uint16_t utmp16 = (ctype ? U_PPF_C : 0) | (RelAbs ? U_PPF_P : 0) |(PenID & U_FF_MASK_OID8) << U_FF_SHFT_OID8; + U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_DRAWCLOSEDCURVE,utmp16,Size); + const U_SERIAL_DESC List[] = { + {ph->Data, ph->Used, 1, U_XE}, + {&Tension, 4, 1, U_LE}, + {Points->Data, Points->Used, 1, U_XE}, /* includes Elements*/ + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_DRAWCLOSEDCURVE_OID, List); + U_PO_free(&ph); + return(po); +} + +/** + \brief Create and set a U_PMR_DRAWCURVE PseudoObject + \return Pointer to PseudoObject, NULL on error + \param PenID U_PMF_PEN object in the EMF+ object table (0-63, inclusive) + \param Tension Controls splines, 0 is straight line, >0 is curved + \param Offset The starting point in the list of points, 0 is first. + \param NSegs Number of segments to draw. Starting at Offset go NSegs straight lines, must not run out of points.. + \param Points U_PSEUDO_OBJ containing an element count then a series of U_PMF_POINT or U_PMF_POINTF object + + + EMF+ manual 2.3.4.5, Microsoft name: EmfPlusDrawCurve Record, Index 0x18 + + Curve is a cardinal spline, using doubled terminator points to generate curves for the terminal segments. + + References sent by MS support: + + http://alvyray.com/Memos/CG/Pixar/spline77.pdf + + http://msdn.microsoft.com/en-us/library/4cf6we5y(v=vs.110).aspx + +*/ +U_PSEUDO_OBJ *U_PMR_DRAWCURVE_set(uint32_t PenID, U_FLOAT Tension, uint32_t Offset, uint32_t NSegs, const U_PSEUDO_OBJ *Points){ + int ctype; + if(PenID>63)return(NULL); + if(!Points){ return(NULL); } + if(!NSegs){ return(NULL); } + else { + if( Points->Type == (U_PMF_POINT_OID | U_PMF_ARRAY_OID)){ ctype = 1; } + else if(Points->Type == (U_PMF_POINTF_OID | U_PMF_ARRAY_OID)){ ctype = 0; } + else { return(NULL); } + } + uint32_t Elements = (Points->Used - 4)/(ctype ? 4 : 8); /* This way do not need to worry about byte order */ + if(Offset + NSegs + 1 > Elements){ return(NULL); } + int Size = 3*4 + Points->Used; + uint16_t utmp16 = (ctype ? U_PPF_C : 0) |(PenID & U_FF_MASK_OID8) << U_FF_SHFT_OID8; + U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_DRAWCURVE,utmp16,Size); + const U_SERIAL_DESC List[] = { + {ph->Data, ph->Used, 1, U_XE}, + {&Tension, 4, 1, U_LE}, + {&Offset, 4, 1, U_LE}, + {&NSegs, 4, 1, U_LE}, + {Points->Data, Points->Used, 1, U_XE}, /* Elements, points */ + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_DRAWCURVE_OID, List); + U_PO_free(&ph); + return(po); +} + +/** + \brief Create and set a U_PMR_DRAWDRIVERSTRING PseudoObject + \return Pointer to PseudoObject, NULL on error + \param FontID U_PMF_FONT object in the EMF+ object table (0-63, inclusive) + \param BrushID U_PSEUDO_OBJ containing a U_PMF_ARGB or a U_PMF_4NUM. Color or U_PMF_BRUSH object in the EMF+ object table (0-63, inclusive) + \param DSOFlags DriverStringOptions flags + \param HasMatrix If 1 record contains a TransformMatrix field, if 0 it does not. + \param GlyphCount The number of Elements in Glyphs, must agree with the number of elements in Points. + \param Glyphs If U_DSO_CmapLookup is set in DSOFlags this is an array of UTF16LE characters, otherwise, it is an array of indices into the U_PMF_FONT object indexed by Object_ID in flags. + \param Points U_PSEUDO_OBJ containing a U_PMF_POINTF object + \param Tm U_PSEUDO_OBJ containing a U_PMF_TRANSFORMMATRIX object. Apply to Glyphs & Positions. Present if HasMatrix is 1 + + + EMF+ manual 2.3.4.6, Microsoft name: EmfPlusDrawDriverString Record, Index 0x36 +*/ +U_PSEUDO_OBJ *U_PMR_DRAWDRIVERSTRING_set(uint32_t FontID, const U_PSEUDO_OBJ *BrushID, + uint32_t DSOFlags, uint32_t HasMatrix, uint32_t GlyphCount, + const uint16_t *Glyphs, const U_PSEUDO_OBJ *Points, const U_PSEUDO_OBJ *Tm){ + int btype; + if(FontID>63){ return(NULL); } + if(!Glyphs){ return(NULL); } + if(!Points || (Points->Type != (U_PMF_POINTF_OID | U_PMF_ARRAY_OID))){ return(NULL); } + uint32_t Elements = (Points->Used -4)/4; + if(GlyphCount != Elements){ return(NULL); } + if(BrushID){ + if( BrushID->Used != 4){ return(NULL); } + else if( BrushID->Type == U_PMF_ARGB_OID){ btype = 1; } + else if( BrushID->Type == U_PMF_4NUM_OID){ btype = 0; } + else { return(NULL); } + } + else { return(NULL); } + int Size = 4 + BrushID->Used + 3*4 + Elements*2 + (Points->Used - 4); + if(HasMatrix){ + if(!Tm){ return(NULL); } + else if(Tm->Type != (U_PMF_TRANSFORMMATRIX_OID)){ return(NULL); } + Size += Tm->Used; + } + uint16_t utmp16 = (btype ? U_PPF_B : 0) |(FontID & U_FF_MASK_OID8) << U_FF_SHFT_OID8; + U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_DRAWDRIVERSTRING,utmp16,Size); + const U_SERIAL_DESC List[] = { + {ph->Data,ph->Used, 1, U_XE}, + {BrushID->Data, BrushID->Used, 1, U_XE}, + {&DSOFlags, 4, 1, U_LE}, + {&HasMatrix, 4, 1, U_LE}, + {&Elements, 4, 1, U_LE}, + {Glyphs, 2, Elements, U_LE}, + {Points->Data + 4, Points->Used - 4, 1, U_XE}, /* omit Elements */ + {(HasMatrix ? Tm->Data : NULL), (HasMatrix ? Tm->Used : 0), 1, U_XE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_DRAWDRIVERSTRING_OID, List); + U_PO_free(&ph); + return(po); +} + +/** + \brief Create and set a U_PMR_DRAWELLIPSE PseudoObject + \return Pointer to PseudoObject, NULL on error + \param PenID U_PMF_PEN object in the EMF+ object table (0-63, inclusive) + \param Rect U_PSEUDO_OBJ containing a U_PMF_RECT or U_PMF_RECTF object + + + EMF+ manual 2.3.4.7, Microsoft name: EmfPlusDrawEllipse Record, Index 0x0F +*/ +U_PSEUDO_OBJ *U_PMR_DRAWELLIPSE_set(uint32_t PenID, const U_PSEUDO_OBJ *Rect){ + if(PenID>63)return(NULL); + int ctype; + if(!Rect){ return(NULL); } + else { + if( Rect->Type == U_PMF_RECT_OID ){ ctype = 1; } + else if(Rect->Type == U_PMF_RECTF_OID){ ctype = 0; } + else { return(NULL); } + } + int Size = Rect->Used; + uint16_t utmp16 = (ctype ? U_PPF_C : 0) | (PenID & U_FF_MASK_OID8) << U_FF_SHFT_OID8; + U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_DRAWELLIPSE,utmp16,Size); + const U_SERIAL_DESC List[] = { + {ph->Data, ph->Used, 1, U_XE}, + {Rect->Data, Rect->Used, 1, U_XE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_DRAWELLIPSE_OID, List); + U_PO_free(&ph); + return(po); +} + +/** + \brief Create and set a U_PMR_DRAWIMAGE PseudoObject + \return Pointer to PseudoObject, NULL on error + \param ImgID U_PMF_IMAGE object in the EMF+ object table (0-63, inclusive) + \param ImgAttrID index of a U_PMF_IMAGEATTRIBUTES object in the object table + \param SrcUnit UnitType enumeration + \param SrcRect U_PSEUDO_OBJ containing a U_PMF_RECTF object, Source region of image + \param DstRect U_PSEUDO_OBJ containing a U_PMF_RECT or U_PMF_RECTF object + + + EMF+ manual 2.3.4.8, Microsoft name: EmfPlusDrawImage Record, Index 0x1A +*/ +U_PSEUDO_OBJ *U_PMR_DRAWIMAGE_set(uint32_t ImgID, + int32_t ImgAttrID, int32_t SrcUnit, const U_PSEUDO_OBJ *SrcRect, const U_PSEUDO_OBJ *DstRect){ + int ctype; + if(ImgID>63)return(NULL); + if(!SrcRect || (SrcRect->Type != U_PMF_RECTF_OID)){ return(NULL); } + if(!DstRect){ return(NULL); } + else { + if( DstRect->Type == U_PMF_RECT_OID ){ ctype = 1; } + else if(DstRect->Type == U_PMF_RECTF_OID){ ctype = 0; } + else { return(NULL); } + } + int Size = 2*4 + SrcRect->Used + DstRect->Used; + uint16_t utmp16 = (ctype ? U_PPF_C : 0) | (ImgID & U_FF_MASK_OID8) << U_FF_SHFT_OID8; + U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_DRAWIMAGE,utmp16,Size); + const U_SERIAL_DESC List[] = { + {ph->Data, ph->Used, 1, U_XE}, + {&ImgAttrID, 4, 1, U_LE}, + {&SrcUnit, 4, 1, U_LE}, + {SrcRect->Data, SrcRect->Used, 1, U_XE}, + {DstRect->Data, DstRect->Used, 1, U_XE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_DRAWIMAGE_OID, List); + U_PO_free(&ph); + return(po); +} + +/** + \brief Create and set a U_PMR_DRAWIMAGEPOINTS PseudoObject + \return Pointer to PseudoObject, NULL on error + \param ImgID U_PMF_IMAGE object in the EMF+ object table (0-63, inclusive) + \param etype Set: effect from previous U_PMR_SERIALIZABLEOBJECT record will be applied; Clear: no effect applied + \param ImgAttrID index of a U_PMF_IMAGEATTRIBUTES object in the object table + \param SrcUnit UnitType enumeration + \param SrcRect U_PSEUDO_OBJ containing a U_PMF_RECTF object, Source region of image + \param Points U_PSEUDO_OBJ containing an array of 3 (U_PMF_POINT, U_PMF_POINTF, or U_PMF_POINTF) objects. These points are the UL, UR, and LL vertices of a parallelogram. + + + EMF+ manual 2.3.4.9, Microsoft name: EmfPlusDrawImagePoints Record, Index 0x1B + + + WARNING! Windows XP Preview does not show filter effects, whether or not U_PPF_E is set. They are visible if the EMF+ + file is inserted as an image into PowerPoint. +*/ +U_PSEUDO_OBJ *U_PMR_DRAWIMAGEPOINTS_set(uint32_t ImgID, int etype, + int32_t ImgAttrID, int32_t SrcUnit, const U_PSEUDO_OBJ *SrcRect, + const U_PSEUDO_OBJ *Points){ + int ctype, RelAbs; + if(ImgID>63){ return(NULL); } + if(!SrcRect || (SrcRect->Type != U_PMF_RECTF_OID)){ return(NULL); } + if(Points){ + if( Points->Type == U_PMF_POINTR_OID){ RelAbs = 1; ctype = 0; } + else if(Points->Type == (U_PMF_POINT_OID | U_PMF_ARRAY_OID)){ RelAbs = 0; ctype = 1; } + else if(Points->Type == (U_PMF_POINTF_OID | U_PMF_ARRAY_OID)){ RelAbs = 0; ctype = 0; } + else { return(NULL); } + } + else { return(NULL); } + int Size = 2*4 + SrcRect->Used + Points->Used; + uint16_t utmp16 = (ctype ? U_PPF_C : 0) | (etype ? U_PPF_E : 0) | (RelAbs ? U_PPF_P : 0) | (ImgID & U_FF_MASK_OID8) << U_FF_SHFT_OID8; + U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_DRAWIMAGEPOINTS,utmp16,Size); + const U_SERIAL_DESC List[] = { + {ph->Data, ph->Used, 1, U_XE}, + {&ImgAttrID, 4, 1, U_LE}, + {&SrcUnit, 4, 1, U_LE}, + {SrcRect->Data, SrcRect->Used, 1, U_XE}, + {Points->Data, Points->Used, 1, U_XE}, /* includes Elements*/ + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_DRAWIMAGEPOINTS_OID, List); + U_PO_free(&ph); + return(po); +} + +/** + \brief Create and set a U_PMR_DRAWLINES PseudoObject + \return Pointer to PseudoObject, NULL on error + \param PenID U_PMF_PEN object in the EMF+ object table (0-63, inclusive) + \param dtype Set: path must be closed, Clear: path is open + \param Points U_PSEUDO_OBJ containing an array of 3 U_PMF_POINT, U_PMF_POINTR, or U_PMF_POINTF objects + + + EMF+ manual 2.3.4.10, Microsoft name: EmfPlusDrawLines Record, Index 0x0D +*/ +U_PSEUDO_OBJ *U_PMR_DRAWLINES_set(uint32_t PenID, int dtype, const U_PSEUDO_OBJ *Points){ + int ctype, RelAbs; + if(PenID>63){ return(NULL); } + if(Points){ + if( Points->Type == U_PMF_POINTR_OID){ RelAbs = 1; ctype = 0; } + else if(Points->Type == (U_PMF_POINT_OID | U_PMF_ARRAY_OID)){ RelAbs = 0; ctype = 1; } + else if(Points->Type == (U_PMF_POINTF_OID | U_PMF_ARRAY_OID)){ RelAbs = 0; ctype = 0; } + else { return(NULL); } + } + else { return(NULL); } + int Size = Points->Used; + uint16_t utmp16 = (ctype ? U_PPF_C : 0) | (dtype ? U_PPF_D : 0) | (RelAbs ? U_PPF_P : 0) | (PenID & U_FF_MASK_OID8) << U_FF_SHFT_OID8; + U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_DRAWLINES,utmp16,Size); + const U_SERIAL_DESC List[] = { + {ph->Data, ph->Used, 1, U_XE}, + {Points->Data, Points->Used, 1, U_XE}, /* includes Elements */ + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_DRAWLINES_OID, List); + U_PO_free(&ph); + return(po); +} + +/** + \brief Create and set a U_PMR_DRAWPATH PseudoObject + \return Pointer to PseudoObject, NULL on error + \param PathID U_PMF_PATH object in the EMF+ object table (0-63, inclusive) + \param PenID U_PMF_PEN object in the EMF+ object table (0-63, inclusive) + + + EMF+ manual 2.3.4.11, Microsoft name: EmfPlusDrawPath Record, Index 0x15 +*/ +U_PSEUDO_OBJ *U_PMR_DRAWPATH_set(uint32_t PathID, uint32_t PenID){ + if(PathID>63)return(NULL); + if(PenID>63)return(NULL); + int Size = 4; + uint16_t utmp16 = (PathID & U_FF_MASK_OID8) << U_FF_SHFT_OID8; + U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_DRAWPATH,utmp16,Size); + const U_SERIAL_DESC List[] = { + {ph->Data, ph->Used, 1, U_XE}, + {&PenID, 4, 1, U_LE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_DRAWPATH_OID, List); + U_PO_free(&ph); + return(po); +} + +/** + \brief Create and set a U_PMR_DRAWPIE PseudoObject + \return Pointer to PseudoObject, NULL on error + \param PenID U_PMF_PEN object in the EMF+ object table (0-63, inclusive) + \param Start Start angle, >=0.0, degrees clockwise from 3:00 + \param Sweep Sweep angle, -360<= angle <=360, degrees clockwise from Start + \param Rect U_PSEUDO_OBJ containing a U_PMF_RECT or U_PMF_RECTF object + + + EMF+ manual 2.3.4.12, Microsoft name: EmfPlusDrawPie Record, Index 0x0D +*/ +U_PSEUDO_OBJ *U_PMR_DRAWPIE_set(uint32_t PenID, + U_FLOAT Start, U_FLOAT Sweep, const U_PSEUDO_OBJ *Rect){ + int ctype; + if(PenID>63)return(NULL); + if(!Rect){ return(NULL); } + else { + if( Rect->Type == U_PMF_RECT_OID ){ ctype = 1; } + else if(Rect->Type == U_PMF_RECTF_OID){ ctype = 0; } + else { return(NULL); } + } + int Size = 2*4 + Rect->Used; + uint16_t utmp16 = (ctype ? U_PPF_C : 0) | (PenID & U_FF_MASK_OID8) << U_FF_SHFT_OID8; + U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_DRAWPIE,utmp16,Size); + const U_SERIAL_DESC List[] = { + {ph->Data, ph->Used, 1, U_XE}, + {&Start, 4, 1, U_LE}, + {&Sweep, 4, 1, U_LE}, + {Rect->Data, Rect->Used, 1, U_XE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_DRAWPIE_OID, List); + U_PO_free(&ph); + return(po); +} + +/** + \brief Create and set a U_PMR_DRAWRECTS PseudoObject + \return Pointer to PseudoObject, NULL on error + \param PenID U_PMF_PEN object in the EMF+ object table (0-63, inclusive) + \param Rects U_PSEUDO_OBJ containing 1 rect OR a count N follwed by N rects. Rects may be either U_PMF_RECT or U_PMF_RECTF + + + EMF+ manual 2.3.4.13, Microsoft name: EmfPlusDrawRects Record, Index 0x0B +*/ +U_PSEUDO_OBJ *U_PMR_DRAWRECTS_set(uint32_t PenID, const U_PSEUDO_OBJ *Rects){ + int ctype; + int just1; + uint32_t Elements=1; /* only used when a single rect is passed in, not an array, not even an array with one member*/ + if(PenID>63){ return(NULL); } + if(Rects){ + if( (Rects->Type & U_PMF_MASK_OID) == U_PMF_RECT_OID ){ ctype = 1; } + else if( (Rects->Type & U_PMF_MASK_OID) == U_PMF_RECTF_OID){ ctype = 0; } + else { return(NULL); } + } + else { return(NULL); } + just1 = (Rects->Type & U_PMF_ARRAY_OID ? 0 : 1); + int Size = Rects->Used + (just1 ? 4 : 0); /* Elements in Rects for array, not for single */ + uint16_t utmp16 = (ctype ? U_PPF_C : 0)| (PenID & U_FF_MASK_OID8) << U_FF_SHFT_OID8; + U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_DRAWRECTS,utmp16,Size); + const U_SERIAL_DESC List[] = { + {ph->Data, ph->Used, 1, U_XE}, + {(just1 ? (char *)&Elements : NULL), (just1 ? 4: 0), 1, U_LE}, /* element count if a single Rect was passed in, empty otherwise */ + {Rects->Data, Rects->Used, 1, U_XE}, /* Elements + Array, already stored in Rects, if an array was passed in, just rect if a single */ + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_DRAWRECTS_OID, List); + U_PO_free(&ph); + return(po); +} + +/** + \brief Create and set a U_PMR_DRAWSTRING PseudoObject + \return Pointer to PseudoObject, NULL on error + \param FontID U_PMF_FONT object in the EMF+ object table (0-63, inclusive) + \param BrushID U_PSEUDO_OBJ containing a U_PMF_ARGB or a U_PMF_4NUM. Color or U_PMF_BRUSH object in the EMF+ object table (0-63, inclusive) + \param FormatID U_PMF_STRINGFORMAT object in EMF+ Object Table. + \param Length Number of characters in the string. + \param Rect U_PSEUDO_OBJ containing a U_PMF_RECTF object, string's bounding box + \param Text Array of UFT-16LE unicode characters. + + + EMF+ manual 2.3.4.14, Microsoft name: EmfPlusDrawString Record, Index 0x1C +*/ +U_PSEUDO_OBJ *U_PMR_DRAWSTRING_set(uint32_t FontID, const U_PSEUDO_OBJ *BrushID, + uint32_t FormatID, uint32_t Length, const U_PSEUDO_OBJ *Rect, const uint16_t *Text){ + int btype; + if(FontID>63){ return(NULL); } + if(!Length){ return(NULL); } + else if (!Text){ return(NULL); } + if(!Rect || Rect->Type != U_PMF_RECTF_OID){ return(NULL); } + if(BrushID){ + if( BrushID->Used != 4){ return(NULL); } + else if( BrushID->Type == U_PMF_ARGB_OID){ btype = 1; } + else if( BrushID->Type == U_PMF_4NUM_OID){ btype = 0; } + else { return(NULL); } + } + else { return(NULL); } + int Size = BrushID->Used + 2*4 + Rect->Used +2*Length; + uint16_t utmp16 = (btype ? U_PPF_B : 0)| (FontID & U_FF_MASK_OID8) << U_FF_SHFT_OID8; + uint32_t pad = (0x1 & Length ? 2 : 0); + Size+=pad; + U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_DRAWSTRING,utmp16,Size); + const U_SERIAL_DESC List[] = { + {ph->Data, ph->Used, 1, U_XE}, + {BrushID->Data, BrushID->Used, 1, U_XE}, + {&FormatID, 4, 1, U_LE}, + {&Length, 4, 1, U_LE}, + {Rect->Data, Rect->Used, 1, U_XE}, + {Text, 2*Length, 1, U_XE}, + {NULL, pad, (pad ? 1 : 0), (pad ? U_XE : U_XX)}, /* Entire record must be a multiple of 4 */ + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_DRAWSTRING_OID, List); + U_PO_free(&ph); + return(po); +} + +/** + \brief Create and set a U_PMR_FILLCLOSEDCURVE PseudoObject + \return Pointer to PseudoObject, NULL on error + \param ftype If U_WINDING use winding fill, else use fill + \param BrushID U_PSEUDO_OBJ containing a U_PMF_ARGB or a U_PMF_4NUM. Color or U_PMF_BRUSH object in the EMF+ object table (0-63, inclusive) + \param Tension Controls splines, 0 is straight line, >0 is curved + \param Points U_PSEUDO_OBJ containing a U_PMF_POINT, U_PMF_POINTR or U_PMF_POINTF object + + + EMF+ manual 2.3.4.15, Microsoft name: EmfPlusFillClosedCurve Record, Index 0x16 +*/ +U_PSEUDO_OBJ *U_PMR_FILLCLOSEDCURVE_set(int ftype, U_FLOAT Tension, const U_PSEUDO_OBJ *BrushID, const U_PSEUDO_OBJ *Points){ + int btype, ctype, RelAbs; + int Size=0; + if(BrushID){ + if( BrushID->Used != 4){ return(NULL); } + else if( BrushID->Type == U_PMF_ARGB_OID){ btype = 1; } + else if( BrushID->Type == U_PMF_4NUM_OID){ btype = 0; } + else { return(NULL); } + } + else { return(NULL); } + if(Points){ + if( Points->Type == U_PMF_POINTR_OID){ RelAbs = 1; ctype = 0; } + else if(Points->Type == (U_PMF_POINT_OID | U_PMF_ARRAY_OID)){ RelAbs = 0; ctype = 1; } + else if(Points->Type == (U_PMF_POINTF_OID | U_PMF_ARRAY_OID)){ RelAbs = 0; ctype = 0; } + else { return(NULL); } + } + else { return(NULL); } + Size = BrushID->Used + 4 + Points->Used; + uint16_t utmp16 = (btype ? U_PPF_B : 0) | (ctype ? U_PPF_C : 0) |((ftype == U_WINDING) ? U_PPF_F : 0) |(RelAbs ? U_PPF_P : 0); + U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_FILLCLOSEDCURVE,utmp16,Size); + const U_SERIAL_DESC List[] = { + {ph->Data, ph->Used, 1, U_XE}, + {BrushID->Data, BrushID->Used, 1, U_XE}, + {&Tension, 4, 1, U_LE}, + {Points->Data, Points->Used, 1, U_XE}, /* includes Elements */ + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_FILLCLOSEDCURVE_OID, List); + U_PO_free(&ph); + return(po); +} + +/** + \brief Create and set a U_PMR_FILLELLIPSE PseudoObject + \return Pointer to PseudoObject, NULL on error + \param BrushID U_PSEUDO_OBJ containing a U_PMF_ARGB or a U_PMF_4NUM. Color or U_PMF_BRUSH object in the EMF+ object table (0-63, inclusive) + \param Rect U_PSEUDO_OBJ containing a U_PMF_RECT or U_PMF_RECTF object + + + EMF+ manual 2.3.4.16, Microsoft name: EmfPlusFillEllipse Record, Index 0x0E +*/ +U_PSEUDO_OBJ *U_PMR_FILLELLIPSE_set(const U_PSEUDO_OBJ *BrushID, const U_PSEUDO_OBJ *Rect){ + int btype, ctype; + if(BrushID){ + if( BrushID->Used != 4){ return(NULL); } + else if( BrushID->Type == U_PMF_ARGB_OID){ btype = 1; } + else if( BrushID->Type == U_PMF_4NUM_OID){ btype = 0; } + else { return(NULL); } + } + else { return(NULL); } + if(Rect){ + if( Rect->Type == U_PMF_RECT_OID ){ ctype = 1; } + else if(Rect->Type == U_PMF_RECTF_OID){ ctype = 0; } + else { return(NULL); } + } + else { return(NULL); } + int Size = BrushID->Used + Rect->Used; + uint16_t utmp16 = (btype ? U_PPF_B : 0) | (ctype ? U_PPF_C : 0); + U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_FILLELLIPSE,utmp16,Size); + const U_SERIAL_DESC List[] = { + {ph->Data, ph->Used, 1, U_XE}, + {BrushID->Data, BrushID->Used, 1, U_XE}, + {Rect->Data, Rect->Used, 1, U_XE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_FILLELLIPSE_OID, List); + U_PO_free(&ph); + return(po); +} + +/** + \brief Create and set a U_PMR_FILLPATH PseudoObject + \return Pointer to PseudoObject, NULL on error + \param PathID U_PMF_PATH object in the EMF+ object table (0-63, inclusive) + \param BrushID U_PSEUDO_OBJ containing a U_PMF_ARGB or a U_PMF_4NUM. Color or U_PMF_BRUSH object in the EMF+ object table (0-63, inclusive) + + + EMF+ manual 2.3.4.17, Microsoft name: EmfPlusFillPath Record, Index 0x14 +*/ +U_PSEUDO_OBJ *U_PMR_FILLPATH_set(uint32_t PathID, const U_PSEUDO_OBJ *BrushID){ + int btype; + int Size=0; + if(PathID>63)return(NULL); + if(BrushID){ + if( BrushID->Used != 4){ return(NULL); } + else if( BrushID->Type == U_PMF_ARGB_OID){ btype = 1; } + else if( BrushID->Type == U_PMF_4NUM_OID){ btype = 0; } + else { return(NULL); } + } + else { return(NULL); } + Size = BrushID->Used; + uint16_t utmp16 = (btype ? U_PPF_B : 0) | (PathID & U_FF_MASK_OID8) << U_FF_SHFT_OID8 ; + U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_FILLPATH,utmp16,Size); + const U_SERIAL_DESC List[] = { + {ph->Data, ph->Used, 1, U_XE}, + {BrushID->Data, BrushID->Used, 1, U_XE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_FILLPATH_OID, List); + U_PO_free(&ph); + return(po); +} + +/** + \brief Create and set a U_PMR_FILLPIE PseudoObject + \return Pointer to PseudoObject, NULL on error + \param Start Start angle, >=0.0, degrees clockwise from 3:00 + \param Sweep Sweep angle, -360<= angle <=360, degrees clockwise from Start + \param BrushID U_PSEUDO_OBJ containing a U_PMF_ARGB or a U_PMF_4NUM. Color or U_PMF_BRUSH object in the EMF+ object table (0-63, inclusive) + \param Rect U_PSEUDO_OBJ containing a U_PMF_RECT or U_PMF_RECTF object + + + EMF+ manual 2.3.4.18, Microsoft name: EmfPlusFillPie Record, Index 0x10 +*/ +U_PSEUDO_OBJ *U_PMR_FILLPIE_set(U_FLOAT Start, U_FLOAT Sweep, const U_PSEUDO_OBJ *BrushID, const U_PSEUDO_OBJ *Rect){ + int btype, ctype; + if(BrushID){ + if( BrushID->Used != 4){ return(NULL); } + else if( BrushID->Type == U_PMF_ARGB_OID){ btype = 1; } + else if( BrushID->Type == U_PMF_4NUM_OID){ btype = 0; } + else { return(NULL); } + } + else { return(NULL); } + if(!Rect){ return(NULL); } + else { + if( Rect->Type == U_PMF_RECT_OID ){ ctype = 1; } + else if(Rect->Type == U_PMF_RECTF_OID){ ctype = 0; } + else { return(NULL); } + } + int Size = BrushID->Used + 2*4 + Rect->Used; + uint16_t utmp16 = (btype ? U_PPF_B : 0) | (ctype ? U_PPF_C : 0); + U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_FILLPIE,utmp16,Size); + const U_SERIAL_DESC List[] = { + {ph->Data, ph->Used, 1, U_XE}, + {BrushID->Data, BrushID->Used, 1, U_XE}, + {&Start, 4, 1, U_LE}, + {&Sweep, 4, 1, U_LE}, + {Rect->Data, Rect->Used, 1, U_XE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_FILLPIE_OID, List); + U_PO_free(&ph); + return(po); +} + +/** + \brief Create and set a U_PMR_FILLPOLYGON PseudoObject + \return Pointer to PseudoObject, NULL on error + \param BrushID U_PSEUDO_OBJ containing a U_PMF_ARGB or a U_PMF_4NUM. Color or U_PMF_BRUSH object in the EMF+ object table (0-63, inclusive) + \param Points U_PSEUDO_OBJ containing an array of 3 U_PMF_POINT, U_PMF_POINTR, or U_PMF_POINTF objects + + + EMF+ manual 2.3.4.19, Microsoft name: EmfPlusFillPolygon Record, Index 0x0C +*/ +U_PSEUDO_OBJ *U_PMR_FILLPOLYGON_set(const U_PSEUDO_OBJ *BrushID, const U_PSEUDO_OBJ *Points){ + int btype, ctype, RelAbs; + if(BrushID){ + if( BrushID->Used != 4){ return(NULL); } + else if( BrushID->Type == U_PMF_ARGB_OID){ btype = 1; } + else if( BrushID->Type == U_PMF_4NUM_OID){ btype = 0; } + else { return(NULL); } + } + else { return(NULL); } + if(Points){ + if( Points->Type == U_PMF_POINTR_OID){ RelAbs = 1; ctype = 0; } + else if(Points->Type == (U_PMF_POINT_OID | U_PMF_ARRAY_OID)){ RelAbs = 0; ctype = 1; } + else if(Points->Type == (U_PMF_POINTF_OID | U_PMF_ARRAY_OID)){ RelAbs = 0; ctype = 0; } + else { return(NULL); } + } + else { return(NULL); } + int Size = BrushID->Used + Points->Used; + uint16_t utmp16 = (btype ? U_PPF_B : 0) | (ctype ? U_PPF_C : 0) |(RelAbs ? U_PPF_P : 0); + U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_FILLPOLYGON,utmp16,Size); + const U_SERIAL_DESC List[] = { + {ph->Data, ph->Used, 1, U_XE}, + {BrushID->Data, BrushID->Used, 1, U_XE}, + {Points->Data, Points->Used, 1, U_XE}, /* includes Elements */ + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_FILLPOLYGON_OID, List); + U_PO_free(&ph); + return(po); +} + +/** + \brief Create and set a U_PMR_FILLRECTS PseudoObject + \return Pointer to PseudoObject, NULL on error + \param BrushID U_PSEUDO_OBJ containing a U_PMF_ARGB or a U_PMF_4NUM. Color or U_PMF_BRUSH object in the EMF+ object table (0-63, inclusive) + \param Rects U_PSEUDO_OBJ containing 1 rect OR a count N followed by N rects. Rects may be either U_PMF_RECT or U_PMF_RECTF + + + EMF+ manual 2.3.4.20, Microsoft name: EmfPlusFillRects Record, Index 0x0A +*/ +U_PSEUDO_OBJ *U_PMR_FILLRECTS_set(const U_PSEUDO_OBJ *BrushID, const U_PSEUDO_OBJ *Rects){ + int btype, ctype; + int just1; + uint32_t Elements=1; /* only used when a single rect is passed in, not an array, not even an array with one member*/ + if(BrushID){ + if( BrushID->Used != 4){ return(NULL); } + else if( BrushID->Type == U_PMF_ARGB_OID){ btype = 1; } + else if( BrushID->Type == U_PMF_4NUM_OID){ btype = 0; } + else { return(NULL); } + } + else { return(NULL); } + if(Rects){ + if( (Rects->Type & U_PMF_MASK_OID) == U_PMF_RECT_OID ){ ctype = 1; } + else if( (Rects->Type & U_PMF_MASK_OID) == U_PMF_RECTF_OID){ ctype = 0; } + else { return(NULL); } + } + else { return(NULL); } + just1 = (Rects->Type & U_PMF_ARRAY_OID ? 0 : 1); + int Size = BrushID->Used + Rects->Used + (just1 ? 4 : 0); /* Elements in Rects for array, not for single */ + uint16_t utmp16 = (btype ? U_PPF_B : 0)|(ctype ? U_PPF_C : 0); + U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_FILLRECTS,utmp16,Size); + const U_SERIAL_DESC List[] = { + {ph->Data, ph->Used, 1, U_XE}, + {BrushID->Data, BrushID->Used, 1, U_XE}, + {(just1 ? (char *)&Elements : NULL), (just1 ? 4: 0), 1, U_LE}, /* element count if a single Rect was passed in, empty otherwise */ + {Rects->Data, Rects->Used, 1, U_XE}, /* Elements + Array, already stored in Rects, if an array was passed in, just rect if a single */ + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_FILLRECTS_OID, List); + U_PO_free(&ph); + return(po); +} + +/** + \brief Create and set a U_PMR_FILLREGION PseudoObject + \return Pointer to PseudoObject, NULL on error + \param RgnID U_PMF_REGION object in the EMF+ object table (0-63, inclusive) + \param BrushID U_PSEUDO_OBJ containing a U_PMF_ARGB or a U_PMF_4NUM. Color or U_PMF_BRUSH object in the EMF+ object table (0-63, inclusive) + + + EMF+ manual 2.3.4.21, Microsoft name: EmfPlusFillRegion Record, Index 0x13 +*/ +U_PSEUDO_OBJ *U_PMR_FILLREGION_set(uint32_t RgnID, const U_PSEUDO_OBJ *BrushID){ + int btype; + if(BrushID){ + if( BrushID->Used != 4){ return(NULL); } + else if( BrushID->Type == U_PMF_ARGB_OID){ btype = 1; } + else if( BrushID->Type == U_PMF_4NUM_OID){ btype = 0; } + else { return(NULL); } + } + else { return(NULL); } + int Size = BrushID->Used; + uint16_t utmp16 = (btype ? U_PPF_B : 0) | (RgnID & U_FF_MASK_OID8) << U_FF_SHFT_OID8; + U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_FILLREGION,utmp16,Size); + const U_SERIAL_DESC List[] = { + {ph->Data, ph->Used, 1, U_XE}, + {BrushID->Data, BrushID->Used, 1, U_XE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_FILLREGION_OID, List); + U_PO_free(&ph); + return(po); +} + +/** + \brief Create and set a U_PMR_OBJECT PseudoObject from another PseudoObject + \return Pointer to PseudoObject, NULL on error + \param ObjID Index for this object in the EMF+ object table (0-63, inclusive) + \param Po U_PSEUDO_OBJ containing an object type that may be stored in the EMF+ object table +*/ +U_PSEUDO_OBJ *U_PMR_OBJECT_PO_set(uint32_t ObjID, U_PSEUDO_OBJ *Po){ + if(!Po){ return(NULL); } + int otype = U_OID_To_OT(Po->Type); /* This will return 0 if the type is not valid for an object */ + if(!otype){ return(NULL); } + U_PSEUDO_OBJ *po = U_PMR_OBJECT_set(ObjID, otype, 0, 0, Po->Used, Po->Data); /* 0,0 = rec. not continued, TSize value (ignored) */ + return(po); +} + +/** + \brief Create and set a U_PMR_OBJECT PseudoObject + \return Pointer to PseudoObject, NULL on error + \param ObjID Index for this object in the EMF+ object table (0-63, inclusive) + \param otype ObjectType enumeration for this Object + \param ntype Set: object definition continues in next record; Clear: this is the sole object definition record + \param TSize If ntype is set the total number of data bytes split across multiple records. If ntype is clear, it is ignored. + \param cbData Object's data size, in bytes. + \param Data Object's data. Type from otype. + + + EMF+ manual 2.3.5.1, Microsoft name: EmfPlusObject Record, Index 0x13 + + Normally this is only called by U_PMR_OBJECT_PO_set(). + + U_PMR_OBJECT records can only hold a maximum of 65020 bytes of data. If the object is larger than that + then multiple U_PMR_OBJECT records are created, one after the other. If this + happens each record has cbData following ph, and the ntype flag is set. If all of the data is less than 65020 + then cbData is NOT entered following ph, and the ntype flag is clear. + + Call initially in all cases with ntype clear and TSize = 0. If the record needs to be fragmented + the function will call itself recursively to do so. + +*/ +U_PSEUDO_OBJ *U_PMR_OBJECT_set(uint32_t ObjID, int otype, int ntype, uint32_t TSize, size_t cbData, const char *Data){ + uint32_t CSize; + int Pad = UP4(TSize) - TSize; + if((otype < U_OT_Brush) || (otype > U_OT_CustomLineCap)){ return(NULL); } + if(ntype && (cbData > U_OBJRECLIM)){ return(NULL); } + if(!Data || !cbData){ return(NULL); } + U_PSEUDO_OBJ *po; + + if(!ntype && !TSize && (cbData > U_OBJRECLIM)){ + ntype = 1; + TSize = cbData; + po = U_PO_create(NULL, TSize + 16 * (1 + (TSize/cbData)), 0, U_PMR_OBJECT_OID); + if(po){ + while(cbData){ + CSize = (cbData > U_OBJRECLIM ? U_OBJRECLIM : cbData); + U_PSEUDO_OBJ *pot = U_PMR_OBJECT_set(ObjID, otype, ntype, TSize, CSize, Data); + if(!pot)break; + U_PSEUDO_OBJ *newpo = U_PO_po_append(po, pot, U_PMF_KEEP_ELEMENTS); + U_PO_free(&pot); + if(!newpo)break; + po = newpo; + Data += U_OBJRECLIM; + cbData -= CSize; + } + if(cbData){ /* some error */ + U_PO_free(&po); + } + } + } + else { + /* Send in DataSize, U_PMR_CMN_HDR_set will adjust Header Size with 1-3 pad bytes if needed */ + uint16_t utmp16 = otype << 8 | (ntype ? U_PPF_N : 0) | (ObjID & U_FF_MASK_OID8) << U_FF_SHFT_OID8; + U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_OBJECT,utmp16,cbData + (ntype ? 4 : 0)); + const U_SERIAL_DESC List[] = { + {ph->Data, ph->Used, 1, U_XE }, + {(ntype ? &TSize : NULL), (ntype ? 4 : 0), (ntype ? 1 : 0), U_LE }, + {Data, cbData, 1, U_XE }, + {NULL, (Pad ? Pad : 0), (Pad ? 1 : 0), (Pad ? U_XE : U_XX)}, /* Either 1-3 pad bytes or a terminator */ + {NULL,0,0,U_XX} /* terminator, possibly a second in the list, which is harmless */ + }; + po = U_PMF_SERIAL_set(U_PMR_OBJECT_OID, List); + U_PO_free(&ph); + } + return(po); +} + +/** + \brief Create and set a U_PMR_SERIALIZABLEOBJECT PseudoObject + \return Pointer to PseudoObject, NULL on error + \param Siepb U_PSEUDO_OBJ containing a "Serialized image effects parameter block". One of the ImageEffects objects. + + EMF+ manual 2.3.5.2, Microsoft name: EmfPlusSerializableObject Record, Index 0x38 + + + This sets an ImageEffect in the renderer, which will be applied to the next EmfPlusDrawImagePoints + record that is encountered. The image effect is "consumed" by that EmfPlusDrawImagePoints record, resetting + the renderer to its original state.\n + + WARNING! Windows XP Preview does not show filter effects, whether or not U_PPF_E is set. They are visible if the EMF+ + file is inserted as an image into PowerPoint. + +*/ +U_PSEUDO_OBJ *U_PMR_SERIALIZABLEOBJECT_set(const U_PSEUDO_OBJ *Siepb){ + if(!Siepb){ return(NULL); } + uint8_t *GUID = U_OID_To_GUID(Siepb->Type); + if(!GUID){ return(NULL); } + /* PO Used is size_t, might be 8 bytes, value in record must be 4 bytes */ + uint32_t Used = Siepb->Used; + int Size = 16 + 4 + Siepb->Used; + U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_SERIALIZABLEOBJECT,0,Size); + const U_SERIAL_DESC List[] = { + {ph->Data, ph->Used, 1, U_XE}, + {GUID, 16, 1, U_XE}, + {&Used, 4, 1, U_LE}, + {Siepb->Data, Siepb->Used, 1, U_XE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_SERIALIZABLEOBJECT_OID, List); + U_PO_free(&ph); + free(GUID); + return(po); +} + +/** + \brief Create and set a U_PMR_SETANTIALIASMODE PseudoObject + \return Pointer to PseudoObject, NULL on error + \param SMenum SmoothingMode enumeration + \param aatype Set: anti-aliasing on; Clear: anti-aliasing off + + + EMF+ manual 2.3.6.1, Microsoft name: EmfPlusSetAntiAliasMode Record, Index 0x1E +*/ +U_PSEUDO_OBJ *U_PMR_SETANTIALIASMODE_set(int SMenum, int aatype){ + int Size = 0; + uint16_t utmp16 = (aatype ? U_PPF_AA : 0) | (SMenum & U_FF_MASK_AA)<<U_FF_SHFT_AA; + U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_SETANTIALIASMODE,utmp16,Size); + const U_SERIAL_DESC List[] = { + {ph->Data, ph->Used, 1, U_XE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_SETANTIALIASMODE_OID, List); + U_PO_free(&ph); + return(po); +} + +/** + \brief Create and set a U_PMR_SETCOMPOSITINGMODE PseudoObject + \return Pointer to PseudoObject, NULL on error + \param CMenum CompositingMode enumeration + + + EMF+ manual 2.3.6.2, Microsoft name: EmfPlusSetCompositingMode Record, Index 0x23 +*/ +U_PSEUDO_OBJ *U_PMR_SETCOMPOSITINGMODE_set(int CMenum){ + int Size = 0; + uint16_t utmp16 = (CMenum & U_FF_MASK_CM)<<U_FF_SHFT_CM; + U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_SETCOMPOSITINGMODE,utmp16,Size); + const U_SERIAL_DESC List[] = { + {ph->Data, ph->Used, 1, U_XE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_SETCOMPOSITINGMODE_OID, List); + U_PO_free(&ph); + return(po); +} + +/** + \brief Create and set a U_PMR_SETCOMPOSITINGQUALITY PseudoObject + \return Pointer to PseudoObject, NULL on error + \param CQenum CompositingQuality enumeration + + + EMF+ manual 2.3.6.3, Microsoft name: EmfPlusSetCompositingQuality Record, Index 0x24 +*/ +U_PSEUDO_OBJ *U_PMR_SETCOMPOSITINGQUALITY_set(int CQenum){ + int Size = 0; + uint16_t utmp16 = (CQenum & U_FF_MASK_CQ)<<U_FF_SHFT_CQ; + U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_SETCOMPOSITINGQUALITY,utmp16,Size); + const U_SERIAL_DESC List[] = { + {ph->Data, ph->Used, 1, U_XE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_SETCOMPOSITINGQUALITY_OID, List); + U_PO_free(&ph); + return(po); +} + +/** + \brief Create and set a U_PMR_SETINTERPOLATIONMODE PseudoObject + \return Pointer to PseudoObject, NULL on error + \param IMenum InterpolationMode enumeration + + + EMF+ manual 2.3.6.4, Microsoft name: EmfPlusSetInterpolationMode Record, Index 0x21 +*/ +U_PSEUDO_OBJ *U_PMR_SETINTERPOLATIONMODE_set(int IMenum){ + int Size = 0; + uint16_t utmp16 = (IMenum & U_FF_MASK_IM)<<U_FF_SHFT_IM; + U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_SETINTERPOLATIONMODE,utmp16,Size); + const U_SERIAL_DESC List[] = { + {ph->Data, ph->Used, 1, U_XE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_SETINTERPOLATIONMODE_OID, List); + U_PO_free(&ph); + return(po); +} + +/** + \brief Create and set a U_PMR_SETPIXELOFFSETMODE PseudoObject + \return Pointer to PseudoObject, NULL on error + \param POMenum PixelOffsetMode enumeration + + + EMF+ manual 2.3.6.5, Microsoft name: EmfPlusSetPixelOffsetMode Record, Index 0x22 +*/ +U_PSEUDO_OBJ *U_PMR_SETPIXELOFFSETMODE_set(int POMenum){ + int Size = 0; + uint16_t utmp16 = (POMenum & U_FF_MASK_PxOffM) << U_FF_SHFT_PxOffM; + U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_SETPIXELOFFSETMODE,utmp16,Size); + const U_SERIAL_DESC List[] = { + {ph->Data, ph->Used, 1, U_XE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_SETPIXELOFFSETMODE_OID, List); + U_PO_free(&ph); + return(po); +} + +/** + \brief Create and set a U_PMR_SETRENDERINGORIGIN PseudoObject + \return Pointer to PseudoObject, NULL on error + \param X X coordinate of rendering origin. + \param Y Y coordinate of rendering origin. + + + EMF+ manual 2.3.6.6, Microsoft name: EmfPlusSetRenderingOrigin Record, Index 0x1D +*/ +U_PSEUDO_OBJ *U_PMR_SETRENDERINGORIGIN_set(int32_t X, int32_t Y){ + int Size = 2*4; + uint16_t utmp16 = 0; + U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_SETRENDERINGORIGIN,utmp16,Size); + const U_SERIAL_DESC List[] = { + {ph->Data, ph->Used, 1, U_XE}, + {&X, 4, 1, U_LE}, + {&Y, 4, 1, U_LE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_SETRENDERINGORIGIN_OID, List); + U_PO_free(&ph); + return(po); +} + +/** + \brief Create and set a U_PMR_SETTEXTCONTRAST PseudoObject + \return Pointer to PseudoObject, NULL on error + \param TGC Text Gamma correction value (x 1000). + + + EMF+ manual 2.3.6.7, Microsoft name: EmfPlusSetTextContrast Record, Index 0x20 +*/ +U_PSEUDO_OBJ *U_PMR_SETTEXTCONTRAST_set(int TGC){ + int Size = 0; + uint16_t utmp16 = (TGC & U_FF_MASK_TGC) << U_FF_SHFT_TGC; + U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_SETTEXTCONTRAST,utmp16,Size); + const U_SERIAL_DESC List[] = { + {ph->Data, ph->Used, 1, U_XE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_SETTEXTCONTRAST_OID, List); + U_PO_free(&ph); + return(po); +} + +/** + \brief Create and set a U_PMR_SETTEXTRENDERINGHINT PseudoObject + \return Pointer to PseudoObject, NULL on error + \param TRHenum TextRenderingHint enumeration + + + EMF+ manual 2.3.6.8, Microsoft name: EmfPlusSetTextRenderingHint Record, Index 0x1F +*/ +U_PSEUDO_OBJ *U_PMR_SETTEXTRENDERINGHINT_set(int TRHenum){ + int Size = 0; + uint16_t utmp16 = (TRHenum & U_FF_MASK_TRH) << U_FF_SHFT_TRH; + U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_SETTEXTRENDERINGHINT,utmp16,Size); + const U_SERIAL_DESC List[] = { + {ph->Data, ph->Used, 1, U_XE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_SETTEXTRENDERINGHINT_OID, List); + U_PO_free(&ph); + return(po); +} + +/** + \brief Create and set a U_PMR_BEGINCONTAINER PseudoObject + \return Pointer to PseudoObject, NULL on error + \param UTenum UnitType enumeration + \param DstRect a U_PSEUDO_OBJ containing a U_PMF_RECTF object. with SrcRect specifies a transformation + \param SrcRect a U_PSEUDO_OBJ containing a U_PMF_RECTF object. with DstRect specifies a transformation + \param StackID EMF+ Object Stack Index to use for this graphics container + + + EMF+ manual 2.3.7.1, Microsoft name: EmfPlusBeginContainer Record, Index 0x27 +*/ +U_PSEUDO_OBJ *U_PMR_BEGINCONTAINER_set(int UTenum, U_PSEUDO_OBJ *DstRect, U_PSEUDO_OBJ *SrcRect, uint32_t StackID){ + if(UTenum < U_UT_World || UTenum > U_UT_Millimeter){ return(NULL); } + if(!DstRect || (DstRect->Type != U_PMF_RECTF_OID)){ return(NULL); } + if(!SrcRect || (SrcRect->Type != U_PMF_RECTF_OID)){ return(NULL); } + int Size = DstRect->Used + SrcRect->Used + 4; + uint16_t utmp16 = (UTenum & U_FF_MASK_UT) << U_FF_SHFT_UT; + U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_BEGINCONTAINER,utmp16,Size); + const U_SERIAL_DESC List[] = { + {ph->Data, ph->Used, 1, U_XE}, + {DstRect->Data, DstRect->Used, 1, U_XE}, + {SrcRect->Data, SrcRect->Used, 1, U_XE}, + {&StackID, 4, 1, U_LE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_BEGINCONTAINER_OID, List); + U_PO_free(&ph); + return(po); +} + +/** + \brief Create and set a U_PMR_BEGINCONTAINERNOPARAMS PseudoObject + \return Pointer to PseudoObject, NULL on error + \param StackID EMF+ Object Stack Index to use for this graphics container + + + EMF+ manual 2.3.7.2, Microsoft name: EmfPlusBeginContainerNoParams Record, Index 0x28 +*/ +U_PSEUDO_OBJ *U_PMR_BEGINCONTAINERNOPARAMS_set(int StackID){ + int Size = 4; + uint16_t utmp16 = 0; + U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_BEGINCONTAINERNOPARAMS,utmp16,Size); + const U_SERIAL_DESC List[] = { + {ph->Data, ph->Used, 1, U_XE}, + {&StackID, 4, 1, U_LE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_BEGINCONTAINERNOPARAMS_OID, List); + U_PO_free(&ph); + return(po); +} + +/** + \brief Create and set a U_PMR_ENDCONTAINER PseudoObject + \return Pointer to PseudoObject, NULL on error + \param StackID EMF+ Object Stack Index to use for this graphics container + + + EMF+ manual 2.3.7.3, Microsoft name: EmfPlusEndContainer Record, Index 0x29 +*/ +U_PSEUDO_OBJ *U_PMR_ENDCONTAINER_set(int StackID){ + int Size = 4; + uint16_t utmp16 = 0; + U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_ENDCONTAINER,utmp16,Size); + const U_SERIAL_DESC List[] = { + {ph->Data, ph->Used, 1, U_XE}, + {&StackID, 4, 1, U_LE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_ENDCONTAINER_OID, List); + U_PO_free(&ph); + return(po); +} + +/** + \brief Create and set a U_PMR_RESTORE PseudoObject + \return Pointer to PseudoObject, NULL on error + \param StackID EMF+ Graphics State Stack to restore from. Must have been put on the GSS with a U_PMR_SAVE. + + + EMF+ manual 2.3.7.4, Microsoft name: EmfPlusRestore Record, Index 0x26 +*/ +U_PSEUDO_OBJ *U_PMR_RESTORE_set(int StackID){ + int Size = 4; + uint16_t utmp16 = 0; + U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_RESTORE,utmp16,Size); + const U_SERIAL_DESC List[] = { + {ph->Data, ph->Used, 1, U_XE}, + {&StackID, 4, 1, U_LE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_RESTORE_OID, List); + U_PO_free(&ph); + return(po); +} + +/** + \brief Create and set a U_PMR_SAVE PseudoObject + \return Pointer to PseudoObject, NULL on error + \param StackID EMF+ Graphics State Stack to restore from. Must have been put on the GSS with a U_PMR_SAVE. + + + EMF+ manual 2.3.7.5, Microsoft name: EmfPlusSave Record, Index 0x25 +*/ +U_PSEUDO_OBJ *U_PMR_SAVE_set(int StackID){ + int Size = 4; + uint16_t utmp16 = 0; + U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_SAVE,utmp16,Size); + const U_SERIAL_DESC List[] = { + {ph->Data, ph->Used, 1, U_XE}, + {&StackID, 4, 1, U_LE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_SAVE_OID, List); + U_PO_free(&ph); + return(po); +} + +/** + \brief Create and set a U_PMR_SETTSCLIP PseudoObject + \return Pointer to PseudoObject, NULL on error + \param Rects a U_PSEUDO_OBJ containing an array of U_PMF_RECT or U_PMF_RECTF objects. + + + EMF+ manual 2.3.8.1, Microsoft name: EmfPlusSetTSClip Record, Index 0x3A +*/ +U_PSEUDO_OBJ *U_PMR_SETTSCLIP_set(U_PSEUDO_OBJ *Rects){ + int ctype; + uint32_t Elements; + if(Rects){ + if( Rects->Type == (U_PMF_RECT_OID | U_PMF_ARRAY_OID)){ ctype = 1; Elements = (Rects->Used - 4)/8; } + else if(Rects->Type == (U_PMF_RECTF_OID | U_PMF_ARRAY_OID)){ ctype = 0; Elements = (Rects->Used - 4)/16; } + else { return(NULL); } + } + else { return(NULL); } + int Size = Rects->Used; /* Rects includes Elements */ + uint16_t utmp16 = (ctype ? U_PPF_K : 0) | (Elements & U_FF_MASK_TSC) << U_FF_SHFT_TSC; + U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_SETTSCLIP,utmp16,Size); + const U_SERIAL_DESC List[] = { + {ph->Data, ph->Used, 1, U_XE}, + {Rects->Data, Rects->Used, 1, U_XE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_SETTSCLIP_OID, List); + U_PO_free(&ph); + return(po); +} + +/** + \brief Create and set a U_PMR_SETTSGRAPHICS PseudoObject + \return Pointer to PseudoObject, NULL on error + \param vgatype Set: Palette is VGA basic colors; Clear: Palette is ??? + \param Tsg A U_PMF_SETTSGRAPHICS object + \param Palette (optional) a U_PSEUDO_OBJ containing a U_PMF_PALETTE object. + + + EMF+ manual 2.3.8.2, Microsoft name: EmfPlusSetTSGraphics Record, Index 0x39 +*/ +U_PSEUDO_OBJ *U_PMR_SETTSGRAPHICS_set(int vgatype, U_PMF_SETTSGRAPHICS *Tsg, U_PSEUDO_OBJ *Palette){ + if(!Tsg){ return(NULL); } + int Size = sizeof(U_PMF_SETTSGRAPHICS) + (Palette ? Palette->Used : 0); + uint16_t utmp16 = (vgatype ? U_PPF_VGA : 0) | (Palette ? U_PPF_PP : 0) ; + U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_SETTSGRAPHICS,utmp16,Size); + const U_SERIAL_DESC List[] = { + {ph->Data, ph->Used, 1, U_XE}, + {&(Tsg->AntiAliasMode), 1, 1, U_XE}, + {&(Tsg->TextRenderHint), 1, 1, U_XE}, + {&(Tsg->CompositingMode), 1, 1, U_XE}, + {&(Tsg->CompositingQuality), 1, 1, U_XE}, + {&(Tsg->RenderOriginX), 2, 1, U_LE}, + {&(Tsg->RenderOriginY), 2, 1, U_LE}, + {&(Tsg->TextContrast), 2, 1, U_LE}, + {&(Tsg->FilterType), 1, 1, U_XE}, + {&(Tsg->PixelOffset), 1, 1, U_XE}, + {&(Tsg->WorldToDevice), 4, 6, U_LE}, + {(Palette ? Palette->Data : NULL), (Palette ? Palette->Used: 0), 1, U_XE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_SETTSGRAPHICS_OID, List); + U_PO_free(&ph); + return(po); +} + +/** + \brief Create and set a U_PMR_MULTIPLYWORLDTRANSFORM PseudoObject + \return Pointer to PseudoObject, NULL on error + \param xmtype Set: Post multiply; Clear: Pre multiply + \param Tm a U_PSEUDO_OBJ containing a U_PMF_TRANSFORMMATRIX. (Transformation matrix) + + + EMF+ manual 2.3.9.1, Microsoft name: EmfPlusMultiplyWorldTransform Record, Index 0x2C +*/ +U_PSEUDO_OBJ *U_PMR_MULTIPLYWORLDTRANSFORM_set(int xmtype, U_PSEUDO_OBJ *Tm){ + if(!Tm || (Tm->Type != U_PMF_TRANSFORMMATRIX_OID)){ return(NULL); } + int Size = Tm->Used; + uint16_t utmp16 = (xmtype ? U_PPF_XM : 0); + U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_MULTIPLYWORLDTRANSFORM,utmp16,Size); + const U_SERIAL_DESC List[] = { + {ph->Data, ph->Used, 1, U_XE}, + {Tm->Data, Tm->Used, 1, U_XE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_MULTIPLYWORLDTRANSFORM_OID, List); + U_PO_free(&ph); + return(po); +} + +/** + \brief Create and set a U_PMR_RESETWORLDTRANSFORM PseudoObject + \return Pointer to PseudoObject, NULL on error + + + EMF+ manual 2.3.9.2, Microsoft name: EmfPlusResetWorldTransform Record, Index 0x2B +*/ +U_PSEUDO_OBJ *U_PMR_RESETWORLDTRANSFORM_set(void){ + int Size = 0; + uint16_t utmp16 = 0; + U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_RESETWORLDTRANSFORM,utmp16,Size); + const U_SERIAL_DESC List[] = { + {ph->Data, ph->Used, 1, U_XE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_RESETWORLDTRANSFORM_OID, List); + U_PO_free(&ph); + return(po); +} + +/** + \brief Create and set a U_PMR_ROTATEWORLDTRANSFORM PseudoObject + \return Pointer to PseudoObject, NULL on error + \param xmtype Set: Post multiply; Clear: Pre multiply + \param Angle Rotation angle, in degrees + + + EMF+ manual 2.3.9.3, Microsoft name: EmfPlusRotateWorldTransform Record, Index 0x2F +*/ +U_PSEUDO_OBJ *U_PMR_ROTATEWORLDTRANSFORM_set(int xmtype, U_FLOAT Angle){ + int Size = 4; + uint16_t utmp16 = (xmtype ? U_PPF_XM : 0); + U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_ROTATEWORLDTRANSFORM,utmp16,Size); + const U_SERIAL_DESC List[] = { + {ph->Data, ph->Used, 1, U_XE}, + {&Angle, 4, 1, U_LE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_ROTATEWORLDTRANSFORM_OID, List); + U_PO_free(&ph); + return(po); +} + +/** + \brief Create and set a U_PMR_SCALEWORLDTRANSFORM PseudoObject + \return Pointer to PseudoObject, NULL on error + \param xmtype Set: Post multiply; Clear: Pre multiply + \param X Scale in X + \param Y Scale in Y + + EMF+ manual 2.3.9.4, Microsoft name: EmfPlusScaleWorldTransform Record, Index 0x2E +*/ +U_PSEUDO_OBJ *U_PMR_SCALEWORLDTRANSFORM_set(int xmtype, U_FLOAT X, U_FLOAT Y){ + int Size = 2*4; + uint16_t utmp16 = (xmtype ? U_PPF_XM : 0); + U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_SCALEWORLDTRANSFORM,utmp16,Size); + const U_SERIAL_DESC List[] = { + {ph->Data, ph->Used, 1, U_XE}, + {&X, 4, 1, U_LE}, + {&Y, 4, 1, U_LE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_SCALEWORLDTRANSFORM_OID, List); + U_PO_free(&ph); + return(po); +} + +/** + \brief Create and set a U_PMR_SETPAGETRANSFORM PseudoObject + \return Pointer to PseudoObject, NULL on error + \param PUenum Page Unit, in UnitType enumeration + \param Scale Scale factor to convert page space to device space + + + + EMF+ manual 2.3.9.5, Microsoft name: EmfPlusSetPageTransform Record, Index 0x30 + + Defines Page Space -> Device Space transformation +*/ +U_PSEUDO_OBJ *U_PMR_SETPAGETRANSFORM_set(int PUenum, U_FLOAT Scale){ + int Size = 4; + uint16_t utmp16 = (PUenum & U_FF_MASK_PU) << U_FF_SHFT_PU; + U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_SETPAGETRANSFORM,utmp16,Size); + const U_SERIAL_DESC List[] = { + {ph->Data, ph->Used, 1, U_XE}, + {&Scale, 4, 1, U_LE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_SETPAGETRANSFORM_OID, List); + U_PO_free(&ph); + return(po); +} + +/** + \brief Create and set a U_PMR_SETWORLDTRANSFORM PseudoObject + \return Pointer to PseudoObject, NULL on error + \param Tm a U_PSEUDO_OBJ containing a U_PMF_TRANSFORMMATRIX. (Transformation matrix) + + + + EMF+ manual 2.3.9.6, Microsoft name: EmfPlusSetWorldTransform Record, Index 0x2A + + Defines World Space -> Page Space transformation +*/ +U_PSEUDO_OBJ *U_PMR_SETWORLDTRANSFORM_set(U_PSEUDO_OBJ *Tm){ + if(!Tm || (Tm->Type != U_PMF_TRANSFORMMATRIX_OID)){ return(NULL); } + int Size = Tm->Used; + uint16_t utmp16 = 0; + U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_SETWORLDTRANSFORM,utmp16,Size); + const U_SERIAL_DESC List[] = { + {ph->Data, ph->Used, 1, U_XE}, + {Tm->Data, Tm->Used, 1, U_XE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_SETWORLDTRANSFORM_OID, List); + U_PO_free(&ph); + return(po); +} + +/** + \brief Create and set a U_PMR_TRANSLATEWORLDTRANSFORM PseudoObject + \return Pointer to PseudoObject, NULL on error + \param xmtype Set: Post multiply; Clear: Pre multiply + \param Dx X offset + \param Dy Y offset + + + EMF+ manual 2.3.9.7, Microsoft name: EmfPlusTranslateWorldTransform Record, Index 0x2D +*/ +U_PSEUDO_OBJ *U_PMR_TRANSLATEWORLDTRANSFORM_set(int xmtype, U_FLOAT Dx, U_FLOAT Dy){ + int Size = 2*4; + uint16_t utmp16 = (xmtype ? U_PPF_XM : 0); + U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_TRANSLATEWORLDTRANSFORM,utmp16,Size); + const U_SERIAL_DESC List[] = { + {ph->Data, ph->Used, 1, U_XE}, + {&Dx, 4, 1, U_LE}, + {&Dy, 4, 1, U_LE}, + {NULL,0,0,U_XX} + }; + U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_TRANSLATEWORLDTRANSFORM_OID, List); + U_PO_free(&ph); + return(po); +} + +/* + + end of U_PMF_*_set() functions + ===================================================================================== + start of U_PMF_*_get() functions + + These functions all take a blimit value so that they can check if the data description in the fields + they process extend beyond the end of the record. + +*/ + + +//! \cond +/* core _get functions, not accessed outside of this routine */ + +/* get copies of up to 0-6 consecutive 4 byte values and a pointer to the rest */ +int U_PMF_CORE1_get(const char *contents, void *v1, void *v2, void *v3, void *v4, void *v5, void *v6, const char **vR){ + if(v1){ U_PMF_MEMCPY_SRCSHIFT(v1, &contents, 4); + if(v2){ U_PMF_MEMCPY_SRCSHIFT(v2, &contents, 4); + if(v3){ U_PMF_MEMCPY_SRCSHIFT(v3, &contents, 4); + if(v4){ U_PMF_MEMCPY_SRCSHIFT(v4, &contents, 4); + if(v5){ U_PMF_MEMCPY_SRCSHIFT(v5, &contents, 4); + if(v6){ U_PMF_MEMCPY_SRCSHIFT(v6, &contents, 4); }}}}}} + if(vR){ *vR = contents; } + return(1); +} +//! \endcond + + +/** + \brief Get data from a U_PMF_BRUSH object + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Version EmfPlusGraphicsVersion object + \param Type BrushType Enumeration + \param Data one of the 5 types of Brush data + \param blimit one byte past the end of data + + EMF+ manual 2.2.1.1, Microsoft name: EmfPlusBrush Object + + Caller must check Data for possible memory access violations. +*/ +int U_PMF_BRUSH_get(const char *contents, uint32_t *Version, uint32_t *Type, const char **Data, const char *blimit){ + if(!contents || !Version || !Type || !Data || !blimit){ return(0); } + if(IS_MEM_UNSAFE(contents,sizeof(U_PMF_BRUSH), blimit))return(0); + U_PMF_SERIAL_get(&contents, Version, 4, 1, U_LE); + U_PMF_SERIAL_get(&contents, Type, 4, 1, U_LE); + U_PMF_PTRSAV_SHIFT(Data, &contents, 0); + return(1); +} + +/** + \brief Get data from a U_PMF_CUSTOMLINECAP object + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Version EmfPlusGraphicsVersion object + \param Type CustomLineCapData Enumeration + \param Data one of the 2 types of Linecap data + \param blimit one byte past the end of data + + EMF+ manual 2.2.1.2, Microsoft name: EmfPlusCustomLineCap Object + + Caller must check Data for possible memory access violations. +*/ +int U_PMF_CUSTOMLINECAP_get(const char *contents, uint32_t *Version, uint32_t *Type, const char **Data, const char *blimit){ + if(!contents || !Version || !Type || !Data || !blimit){ return(0); } + if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_CUSTOMLINECAP), blimit))return(0); + U_PMF_SERIAL_get(&contents, Version, 4, 1, U_LE); + U_PMF_SERIAL_get(&contents, Type, 4, 1, U_LE); + U_PMF_PTRSAV_SHIFT(Data, &contents, 0); + return(1); +} + +/** + \brief Get data from a U_PMF_FONT object + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Version EmfPlusGraphicsVersion object + \param EmSize em size in units of SizeUnit + \param SizeUnit UnitType enumeration + \param FSFlags FontStyle flags + \param Length Number of Unicode Characters in FamilyName + \param Data Unicode (UTF-16LE) name of font family + + EMF+ manual 2.2.1.3, Microsoft name: EmfPlusFont Object + + Caller must check Data for possible memory access violations. +*/ +int U_PMF_FONT_get(const char *contents, uint32_t *Version, U_FLOAT *EmSize, uint32_t *SizeUnit, + int32_t *FSFlags, uint32_t *Length, const char **Data, const char *blimit){ + if(!contents || !Version || !EmSize || !SizeUnit || !FSFlags || !Length || !Data || !blimit){ return(0); } + if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_FONT), blimit))return(0); + U_PMF_SERIAL_get(&contents, Version, 4, 1, U_LE); + U_PMF_SERIAL_get(&contents, EmSize, 4, 1, U_LE); + U_PMF_SERIAL_get(&contents, SizeUnit, 4, 1, U_LE); + U_PMF_SERIAL_get(&contents, FSFlags, 4, 1, U_LE); + contents += 4; /* Reserved field, which is ignored */ + U_PMF_SERIAL_get(&contents, Length, 4, 1, U_LE); + U_PMF_PTRSAV_SHIFT(Data, &contents, 0); + return(1); +} + + +/** + \brief Get data from a U_PMF_IMAGE object + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Version EmfPlusGraphicsVersion object + \param Type ImageDataType Enumeration + \param Data one of the 2 types of image data + + EMF+ manual 2.2.1.4, Microsoft name: EmfPlusImage Object + + Caller must check Data for possible memory access violations. +*/ +int U_PMF_IMAGE_get(const char *contents, uint32_t *Version, uint32_t *Type, const char **Data, const char *blimit){ + if(!contents || !Version || !Type || !blimit){ return(0); } + if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_IMAGE), blimit))return(0); + U_PMF_SERIAL_get(&contents, Version, 4, 1, U_LE); + U_PMF_SERIAL_get(&contents, Type, 4, 1, U_LE); + U_PMF_PTRSAV_SHIFT(Data, &contents, 0); + return(1); +} + +/** + \brief Get data from a U_PMF_IMAGEATTRIBUTES object + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Version EmfPlusGraphicsVersion object + \param WrapMode WrapMode object + \param ClampColor EmfPlusARGB object + \param ObjectClamp ObjectClamp Identifiers + + EMF+ manual 2.2.1.5, Microsoft name: EmfPlusImageAttributes Object +*/ +int U_PMF_IMAGEATTRIBUTES_get(const char *contents, uint32_t *Version, uint32_t *WrapMode, uint32_t *ClampColor, + uint32_t *ObjectClamp, const char *blimit){ + if(!contents || !Version || !WrapMode || !ClampColor || !ObjectClamp || !blimit){ return(0); } + if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_IMAGEATTRIBUTES), blimit))return(0); + U_PMF_SERIAL_get(&contents, Version, 4, 1, U_LE); + contents += 4; /* Skip Reserved 1*/ + U_PMF_SERIAL_get(&contents, WrapMode, 4, 1, U_LE); + U_PMF_SERIAL_get(&contents, ClampColor, 4, 1, U_LE); + U_PMF_SERIAL_get(&contents, ObjectClamp,4, 1, U_LE); + /* Skip Reserved 2*/ + return(1); +} + +/** + \brief Get data from a U_PMF_PATH object + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Version EmfPlusGraphicsVersion object + \param Count Number of points and point types in this object + \param Flags PathPoint Flags + \param Points array of points type PMFPointR, PMFPoint, or PMFPointF + \param Types array of U_PMF_PATHPOINTTYPERLE and/or U_PMF_PATHPOINTTYPE + + EMF+ manual 2.2.1.6, Microsoft name: EmfPlusPath Object + + Caller must check Types for possible memory access violations if type can be U_PMF_PATHPOINTTYPERLE. +*/ +int U_PMF_PATH_get(const char *contents, uint32_t *Version, uint32_t *Count, uint16_t *Flags, + const char **Points, const char **Types, const char *blimit){ + if(!contents || !Version || !Count || !Flags || !Points || !Types || !blimit){ return(0); } + if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_PATH), blimit))return(0); + U_PMF_SERIAL_get(&contents, Version, 4, 1, U_LE); + U_PMF_SERIAL_get(&contents, Count, 4, 1, U_LE); + U_PMF_SERIAL_get(&contents, Flags, 2, 1, U_LE); + contents+=2; /* reserved */ + uint32_t sizeP, sizeT; + if(*Flags & U_PPF_P){ + sizeP = U_PMF_LEN_REL715(contents,*Count); //DEBUG + printf("DEBUG U_PMF_PATH_get count:%d LENREL715:%d\n",*Count,sizeP);fflush(stdout); + } + else if(*Flags & U_PPF_C){ sizeP = *Count * sizeof(U_PMF_POINT); } + else { sizeP = *Count * sizeof(U_PMF_POINTF); } + if(IS_MEM_UNSAFE(contents, sizeP, blimit))return(0); + U_PMF_PTRSAV_SHIFT(Points, &contents, 0); + contents += sizeP; + /* this limit is correct if there are only U_PMF_PATHPOINTTYPE PointTypes, it is a lower bound if + there can also be U_PMF_PATHPOINTTYPERLE */ + sizeT = *Count * sizeof(U_PMF_PATHPOINTTYPE); + if(IS_MEM_UNSAFE(contents, sizeT, blimit))return(0); + U_PMF_PTRSAV_SHIFT(Types, &contents, 0); + return(1); +} + +/** + \brief Get data from a U_PMF_PEN object + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Version EmfPlusGraphicsVersion object + \param Type must be zero + \param PenData Pen description + \param Brush Brush Description + + EMF+ manual 2.2.1.7, Microsoft name: EmfPlusPen Object + + Caller must check Brush and PenData for possible memory access violations. +*/ +int U_PMF_PEN_get(const char *contents, uint32_t *Version, uint32_t *Type, const char **PenData, const char **Brush, const char *blimit){ + if(!contents || !Type || !PenData || !Brush || !blimit){ return(0); } + if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_PEN), blimit))return(0); + U_PMF_SERIAL_get(&contents, Version, 4, 1, U_LE); + U_PMF_SERIAL_get(&contents, Type, 4, 1, U_LE); + U_PMF_PTRSAV_SHIFT(PenData, &contents, 0); + *Brush = *PenData + U_PMF_LEN_PENDATA(*PenData); + return(1); +} + +/** + \brief Get data from a U_PMF_REGION object + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Version EmfPlusGraphicsVersion object + \param Count Number of CHILD nodes. This is one less than the total number of U_PMF_REGIONNODE objects in Nodes. + \param Nodes Nodes defining region + + EMF+ manual 2.2.1.8, Microsoft name: EmfPlusRegion Object +*/ +int U_PMF_REGION_get(const char *contents, uint32_t *Version, uint32_t *Count, const char **Nodes, const char *blimit){ + if(!contents || !Version || !Count || !Nodes || !blimit){ return(0); } + if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_REGION), blimit))return(0); + U_PMF_SERIAL_get(&contents, Version, 4, 1, U_LE); + U_PMF_SERIAL_get(&contents, Count, 4, 1, U_LE); + U_PMF_PTRSAV_SHIFT(Nodes, &contents, 0); + return(1); +} + +/** + \brief Get data from a U_PMF_STRINGFORMAT object + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Sfs pointer to U_PMF_STRINGFORMAT structure, with no variable part + \param Data pointer to variable part + + EMF+ manual 2.2.1.9, Microsoft name: EmfPlusStringFormat Object +*/ +int U_PMF_STRINGFORMAT_get(const char *contents, U_PMF_STRINGFORMAT *Sfs, const char **Data, const char *blimit){ + if(!contents || !Sfs || !Data || !blimit){ return(0); } + if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_STRINGFORMAT), blimit))return(0); + U_PMF_SERIAL_get(&contents, Sfs, 4, 15, U_LE); + *Data = contents; + return(1); +} + +/** + \brief Get data from a U_PMF_ARGB object + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Blue Blue color (0-255) + \param Green Green color (0-255) + \param Red Red color (0-255) + \param Alpha Alpha (0-255) + + EMF+ manual 2.2.2.1, Microsoft name: EmfPlusARGB Object +*/ +int U_PMF_ARGB_get(const char *contents, uint8_t *Blue, uint8_t *Green, uint8_t *Red, uint8_t *Alpha, const char *blimit){ + if(!contents || !Blue || !Green || !Red || !Alpha || !blimit){ return(0); } + if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_ARGB), blimit))return(0); + U_PMF_SERIAL_get(&contents, Blue, 1, 1, U_XE); + U_PMF_SERIAL_get(&contents, Green, 1, 1, U_XE); + U_PMF_SERIAL_get(&contents, Red, 1, 1, U_XE); + U_PMF_SERIAL_get(&contents, Alpha, 1, 1, U_XE); + return(1); +} + +/** + \brief Get data from a U_PMF_BITMAP object + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Bs pointer to U_PMF_BITMAP structure, with no variable part + \param Data pointer to variable part + + EMF+ manual 2.2.2.2, Microsoft name: EmfPlusBitmap Object + + Caller must check Data for possible memory access violations. +*/ +int U_PMF_BITMAP_get(const char *contents, U_PMF_BITMAP *Bs, const char **Data, const char *blimit){ + if(!contents || !Bs || !Data || !blimit){ return(0); } + if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_BITMAP), blimit))return(0); + U_PMF_SERIAL_get(&contents, Bs, 4, 5, U_LE); // width, height, stride, pixelformat, type + U_PMF_PTRSAV_SHIFT(Data, &contents, 0); // bitmapdata + return(1); +} + +/** + \brief Get data from a U_PMF_BITMAPDATA object + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Ps pointer to U_PMF_PALETTE structure, with no variable part + \param Colors Color part of U_PMF_PALETTE object + \param Data An array of bytes, meaning depends on fields in U_PMF_BITMAP object and the PixelFormat enumeration. + + EMF+ manual 2.2.2.3, Microsoft name: EmfPlusBitmapData Object + + Caller must check Data for possible memory access violations. +*/ +int U_PMF_BITMAPDATA_get(const char *contents, U_PMF_PALETTE *Ps, const char **Colors, const char **Data, const char *blimit){ + if(!contents || !Ps || !Colors || !Data || !blimit){ return(0); } + /* this structure is entirely optional */ + if(IS_MEM_UNSAFE(contents, 4*2, blimit))return(0); + U_PMF_SERIAL_get(&contents, Ps, 4, 2, U_LE); + U_PMF_PTRSAV_SHIFT(Colors, &contents, Ps->Elements * sizeof(U_PMF_ARGB)); + /* difficult to know how big the actual bitmap will be, just return the pointer to it untested */ + U_PMF_PTRSAV_SHIFT(Data, &contents, 0); + return(1); +} + +/** + \brief Get data from a U_PMF_BLENDCOLORS object + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Elements Number of members in Positions and Colors + \param Positions Caller must free. Pointer to memory holding positions along gradient line. + \param Colors Caller must NOT free memory, Pointer to memory holding colors at positions on gradient line. + + EMF+ manual 2.2.2.4, Microsoft name: EmfPlusBlendColors Object +*/ +int U_PMF_BLENDCOLORS_get(const char *contents, uint32_t *Elements, U_FLOAT **Positions, const char **Colors, const char *blimit){ + if(!contents || !Positions || !Colors || !blimit){ return(0); } + if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_BLENDCOLORS), blimit))return(0); + U_PMF_SERIAL_get(&contents, Elements, 4, 1, U_LE); + if(IS_MEM_UNSAFE(contents, *Elements * 4, blimit))return(0); + if(!U_PMF_SERIAL_array_copy_get(&contents, (void **)Positions, 4, *Elements, U_LE,1)){ return(0); } + U_PMF_PTRSAV_SHIFT(Colors, &contents, 0); + return(1); +} + +/** + \brief Get data from a U_PMF_BLENDFACTORS object + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Elements members in each array + \param Positions Caller must free. Pointer to memory holding positions along gradient line. + \param Factors Caller must free. Pointer to memory holding blending factors, 0.0->1.0 values, inclusive along gradient line. + + EMF+ manual 2.2.2.5, Microsoft name: EmfPlusBlendFactors Object +*/ +int U_PMF_BLENDFACTORS_get(const char *contents, uint32_t *Elements, U_FLOAT **Positions, U_FLOAT **Factors, const char *blimit){ + if(!contents || !Elements || !Positions || !Factors || !blimit){ return(0); } + if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_BLENDFACTORS), blimit))return(0); + U_PMF_SERIAL_get(&contents, Elements, 4, 1, U_LE); + if(IS_MEM_UNSAFE(contents, *Elements * 4 * 2, blimit))return(0); + if(!U_PMF_SERIAL_array_copy_get(&contents, (void **)Positions, 4, *Elements, U_LE, 1)){ return(0); } + if(!U_PMF_SERIAL_array_copy_get(&contents, (void **)Factors, 4, *Elements, U_LE, 1)){ + free(*Positions); + return(0); + } + return(1); +} + +/** + \brief Get data from a U_PMF_BOUNDARYPATHDATA object + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Size bytes in Data + \param Data boundary of the brush + + EMF+ manual 2.2.2.6, Microsoft name: EmfPlusBoundaryPathData Object + + Caller must check Data for possible memory access violations. +*/ +int U_PMF_BOUNDARYPATHDATA_get(const char *contents, int32_t *Size, const char **Data, const char *blimit){ + if(!contents || !Size || !Data || !blimit){ return(0); } + if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_BOUNDARYPATHDATA), blimit))return(0); + U_PMF_SERIAL_get(&contents, Size, 4, 1, U_LE); + U_PMF_PTRSAV_SHIFT(Data, &contents, 0); + return(1); +} + +/** + \brief Get data from a U_PMF_BOUNDARYPOINTDATA object + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Elements Members in Points + \param Points Caller must free. Pointer to memory holding points along gradient line. Boundary of the brush. + + EMF+ manual 2.2.2.7, Microsoft name: EmfPlusBoundaryPointData Object +*/ +int U_PMF_BOUNDARYPOINTDATA_get(const char *contents, int32_t *Elements, U_PMF_POINTF **Points, const char *blimit){ + if(!contents || !Elements || !Points || !blimit){ return(0); } + if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_BOUNDARYPOINTDATA), blimit))return(0); + U_PMF_SERIAL_get(&contents, Elements, 4, 1, U_LE); + if(IS_MEM_UNSAFE(contents, *Elements * 2, blimit))return(0); + if(!U_PMF_SERIAL_array_copy_get(&contents, (void **)Points, 4, *Elements * 2, U_LE, 1)){ return(0); } + return(1); +} + +/** + \brief Get data from a U_PMF_CHARACTERRANGE object + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param First First position in range + \param Length Range length + + EMF+ manual 2.2.2.8, Microsoft name: EmfPlusCharacterRange Object +*/ +int U_PMF_CHARACTERRANGE_get(const char *contents, int32_t *First, int32_t *Length, const char *blimit){ + if(!contents || !First || !Length || !blimit){ return(0); } + if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_CHARACTERRANGE), blimit))return(0); + U_PMF_SERIAL_get(&contents, First, 4, 1, U_LE); + U_PMF_SERIAL_get(&contents, Length, 4, 1, U_LE); + return(1); +} + +/** + \brief Get data from a U_PMF_COMPOUNDLINEDATA object + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Elements Members in the array + \param Widths Caller must free. Pointer to memory holding Line or gap widths (0.0 <-> 1.0, fraction of total line width ). + + EMF+ manual 2.2.2.9, Microsoft name: EmfPlusCompoundLineData Object +*/ +int U_PMF_COMPOUNDLINEDATA_get(const char *contents, int32_t *Elements, U_FLOAT **Widths, const char *blimit){ + if(!contents || !Elements || !Widths || !blimit){ return(0); } + if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_COMPOUNDLINEDATA), blimit))return(0); + U_PMF_SERIAL_get(&contents, Elements, 4, 1, U_LE); + if(IS_MEM_UNSAFE(contents, *Elements * sizeof(U_FLOAT), blimit))return(0); + *Widths = (U_FLOAT *)malloc(*Elements * sizeof(U_FLOAT)); + if(!*Widths){ return(0); } + U_PMF_SERIAL_get(&contents, *Widths, 4, *Elements, U_LE); + return(1); +} + +/** + \brief Get data from a U_PMF_COMPRESSEDIMAGE object + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Data Stored image in one of the supported formats. + + EMF+ manual 2.2.2.10, Microsoft name: EmfPlusCompressedImage Object + + + This function does not do anything useful, but it is included so that all objects have a corresponding _get(). + + Caller must check Data for possible memory access violations. +*/ +int U_PMF_COMPRESSEDIMAGE_get(const char *contents, const char **Data, const char *blimit){ + if(!contents || !Data || !blimit){ return(0); } + if(contents >= blimit)return(0); + U_PMF_PTRSAV_SHIFT(Data, &contents, 0); + return(1); +} + +/** + \brief Get data from a U_PMF_CUSTOMENDCAPDATA object + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Size Bytes in Data + \param Data Description of linecap + + EMF+ manual 2.2.2.11, Microsoft name: EmfPlusCustomEndCapData Object + + Caller must check Data for possible memory access violations. +*/ +int U_PMF_CUSTOMENDCAPDATA_get(const char *contents, int32_t *Size, const char **Data, const char *blimit){ + if(!contents || !Size || !Data || !blimit){ return(0); } + if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_CUSTOMENDCAPDATA), blimit))return(0); + U_PMF_SERIAL_get(&contents, Size, 4, 1, U_LE); + U_PMF_PTRSAV_SHIFT(Data, &contents, 0); + return(1); +} + +/** + \brief Get data from a U_PMF_CUSTOMLINECAPARROWDATA object + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Ccad pointer to U_PMF_CUSTOMLINECAPARROWDATA structure + + EMF+ manual 2.2.2.12, Microsoft name: EmfPlusCustomLineCapArrowData Object +*/ +int U_PMF_CUSTOMLINECAPARROWDATA_get(const char *contents, U_PMF_CUSTOMLINECAPARROWDATA *Ccad, const char *blimit){ + if(!contents || !Ccad || !blimit){ return(0); } + if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_CUSTOMLINECAPARROWDATA), blimit))return(0); + U_PMF_SERIAL_get(&contents, Ccad, 4, 13, U_LE); + return(1); +} + +/** + \brief Get data from a U_PMF_CUSTOMLINECAPDATA object + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Clcd pointer to U_PMF_CUSTOMLINECAPDATA structure, with no variable part + \param Data variable part of U_PMF_CUSTOMLINECAPDATA + + EMF+ manual 2.2.2.13, Microsoft name: EmfPlusCustomLineCapData Object + + Caller must check Data for possible memory access violations. +*/ +int U_PMF_CUSTOMLINECAPDATA_get(const char *contents, U_PMF_CUSTOMLINECAPDATA *Clcd, const char **Data, const char *blimit){ + if(!contents || !Clcd || !blimit){ return(0); } + if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_CUSTOMLINECAPDATA), blimit))return(0); + U_PMF_SERIAL_get(&contents, Clcd, 4, 12, U_LE); + U_PMF_PTRSAV_SHIFT(Data, &contents, 0); + return(1); +} + +/** + \brief Get data from a U_PMF_CUSTOMLINECAPOPTIONALDATA object + \return on success 3,5, or 7 (for varying combinations of data present) or 1 (no data is present), 0 on error + \param contents Record from which to extract data + \param Flags bits set to indicate the presence of FillData and/or LineData + \param FillData Path to fill (optional) + \param LineData Path to stroke (optional) + + EMF+ manual 2.2.2.14, Microsoft name: EmfPlusCustomLineCapOptionalData Object + + Caller must check LineData for possible memory access violations. +*/ +int U_PMF_CUSTOMLINECAPOPTIONALDATA_get(const char *contents, uint32_t Flags, const char **FillData, const char **LineData, const char *blimit){ + uint32_t length; + int status = 1; + if(!contents || !*FillData || !*LineData || !blimit){ return(0); } + /* this structure is entirely optional */ + if(Flags & U_CLCD_FillPath){ + if(!FillData){ return(0); } + if(IS_MEM_UNSAFE(contents, 4, blimit))return(0); + U_PMF_SERIAL_get(&contents, &length, 4, 1, U_LE); + if(IS_MEM_UNSAFE(contents, length, blimit))return(0); + contents -= 4; /* undo the unneeded shift from preceding */ + U_PMF_PTRSAV_SHIFT(FillData, &contents, 4 + length); + status += 2; + } + else { *FillData = NULL; } + + if(Flags & U_CLCD_LinePath){ + if(!LineData){ return(0); } + if(IS_MEM_UNSAFE(contents, 4, blimit))return(0); + U_PMF_SERIAL_get(&contents, &length, 4, 1, U_LE); + if(IS_MEM_UNSAFE(contents, length, blimit))return(0); + contents -= 4; /* undo the unneeded shift from preceding */ + U_PMF_PTRSAV_SHIFT(LineData, &contents, 0); + status += 4; + } + else { *LineData = NULL; } + return(status); +} + +/** + \brief Get data from a U_PMF_CUSTOMSTARTCAPDATA object + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Size Bytes in Data + \param Data Description of linecap + + EMF+ manual 2.2.2.15, Microsoft name: EmfPlusCustomStartCapData Object + + Caller must check Data for possible memory access violations. +*/ +int U_PMF_CUSTOMSTARTCAPDATA_get(const char *contents, int32_t *Size, const char **Data, const char *blimit){ + if(!contents || !Size || !Data || !blimit){ return(0); } + if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_CUSTOMSTARTCAPDATA), blimit))return(0); + U_PMF_SERIAL_get(&contents, Size, 4, 1, U_LE); + U_PMF_PTRSAV_SHIFT(Data, &contents, 0); + return(1); +} + +/** + \brief Get data from a U_PMF_DASHEDLINEDATA object + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Elements Members in the array + \param Lengths Caller must free. Pointer to memory holding lengths of dashes and spaces. + + EMF+ manual 2.2.2.16, Microsoft name: EmfPlusDashedLineData Object +*/ +int U_PMF_DASHEDLINEDATA_get(const char *contents, int32_t *Elements, U_FLOAT **Lengths, const char *blimit){ + if(!contents || !Elements || !Lengths || !blimit){ return(0); } + if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_DASHEDLINEDATA), blimit))return(0); + U_PMF_SERIAL_get(&contents, Elements, 4, 1, U_LE); + if(IS_MEM_UNSAFE(contents, *Elements * sizeof(U_FLOAT), blimit))return(0); + *Lengths = (U_FLOAT *)malloc(*Elements * sizeof(U_FLOAT)); + if(!*Lengths){ return(0); } + U_PMF_SERIAL_get(&contents, *Lengths, 4, *Elements, U_LE); + return(1); +} + +/** + \brief Get data from a U_PMF_FILLPATHOBJ object + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Size Bytes in Data + \param Data Path specification + + EMF+ manual 2.2.2.17, Microsoft name: EmfPlusFillPath Object + + Caller must check Data for possible memory access violations. +*/ +int U_PMF_FILLPATHOBJ_get(const char *contents, int32_t *Size, const char **Data, const char *blimit){ + if(!contents || !Size || !Data || !blimit){ return(0); } + if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_FILLPATHO), blimit))return(0); + U_PMF_SERIAL_get(&contents, Size, 4, 1, U_LE); + U_PMF_PTRSAV_SHIFT(Data, &contents, 0); + return(1); +} + +/** + \brief Get data from a U_PMF_FOCUSSCALEDATA object + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Count must be 2 + \param ScaleX value 0.0 <-> 1.0 + \param ScaleY value 0.0 <-> 1.0 + + EMF+ manual 2.2.2.18, Microsoft name: EmfPlusFocusScaleData Object +*/ +int U_PMF_FOCUSSCALEDATA_get(const char *contents, uint32_t *Count, U_FLOAT *ScaleX, U_FLOAT *ScaleY, const char *blimit){ + if(!contents || !Count || !ScaleX || !ScaleY || !blimit){ return(0); } + if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_FOCUSSCALEDATA), blimit))return(0); + U_PMF_SERIAL_get(&contents, Count, 4, 1, U_LE); + if(*Count != 2){ return(0); } + U_PMF_SERIAL_get(&contents, ScaleX, 4, 1, U_LE); + U_PMF_SERIAL_get(&contents, ScaleY, 4, 1, U_LE); + return(1); +} + +/** + \brief Get data from a U_PMF_GRAPHICSVERSION object + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Signature Must be U_GFVR_PMF (0xDBC01) + \param GrfVersion GraphicsVersion enumeration + + EMF+ manual 2.2.2.19, Microsoft name: EmfPlusGraphicsVersion Object +*/ +int U_PMF_GRAPHICSVERSION_get(const char *contents, int *Signature, int *GrfVersion, const char *blimit){ + uint32_t tmp; + if(!contents || !Signature || !GrfVersion || !blimit){ return(0); } + if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_GRAPHICSVERSION), blimit))return(0); + memcpy(&tmp, contents, 4); + *Signature = tmp >> 12; + *GrfVersion = tmp & U_GFVR_MASKLO; + return(1); +} + +/** + \brief Get data from a U_PMF_HATCHBRUSHDATA object + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Style HatchStyle enumeration + \param Foreground Hatch pattern line color + \param Background Hatch pattern bkground color + + EMF+ manual 2.2.2.20, Microsoft name: EmfPlusHatchBrushData Object +*/ +int U_PMF_HATCHBRUSHDATA_get(const char *contents, uint32_t *Style, U_PMF_ARGB *Foreground, U_PMF_ARGB *Background, const char *blimit){ + if(!contents || !Style || !Foreground || !Background || !blimit){ return(0); } + if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_HATCHBRUSHDATA), blimit))return(0); + U_PMF_SERIAL_get(&contents, Style, 4, 1, U_LE); + U_PMF_SERIAL_get(&contents, Foreground, 4, 1, U_XE); + U_PMF_SERIAL_get(&contents, Background, 4, 1, U_XE); + return(1); +} + +/** + \brief Get data from a U_PMF_INTEGER7 object + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Value 7 bit signed integer (stored in an integer) + \param blimit one byte past the end of data + + EMF+ manual 2.2.2.21, Microsoft name: EmfPlusInteger7 Object +*/ +int U_PMF_INTEGER7_get(const char **contents, U_FLOAT *Value, const char *blimit){ + uint8_t tmp; + if(!contents || !*contents || !Value || !blimit){ return(0); } + if(IS_MEM_UNSAFE(*contents, 1, blimit))return(0); /* past end of buffer */ + if(**contents & U_TEST_INT7)return(0); /* this bit must be 0 in this object type */ + U_PMF_SERIAL_get(contents, &tmp, 1, 1, U_XE); + if(tmp & U_SIGN_INT7){ + tmp |= U_TEST_INT7; /* now it has the bit pattern of a signed int8_t */ + *Value = *(int8_t *)&tmp; + } + else { + *Value = tmp; + } + return(1); +} + +/** + \brief Get data from a U_PMF_INTEGER15 object + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Value 15 bit signed integer (stored in an integer) + \param blimit one byte past the end of data + + EMF+ manual 2.2.2.22, Microsoft name: EmfPlusInteger15 Object +*/ +int U_PMF_INTEGER15_get(const char **contents, U_FLOAT *Value, const char *blimit){ + if(!contents || !*contents || !Value || !blimit){ return(0); } + uint16_t tmp; + if(IS_MEM_UNSAFE(*contents, 2, blimit))return(0); /* past end of buffer */ + if(!(**contents & U_TEST_INT7))return(0); /* this bit must be 1 in this object type */ + U_PMF_SERIAL_get(contents, &tmp, 2, 1, U_BE); + tmp &= U_MASK_INT15; /* drop the 7/15 flag from the most significant bit */ + if(tmp & U_SIGN_INT15){ + tmp |= U_TEST_INT15; /* now it has the bit pattern of a signed int16_t */ + *Value = *(int16_t *)&tmp; + } + else { + *Value = tmp; + } + return(1); +} + +/** + \brief Get data from a U_PMF_LANGUAGEIDENTIFIER object + \return 1 on success, 0 on error + \param LId U_PMF_LANGUAGEIDENTIFIER from which to extract data + \param SubLId Example: code for USA + \param PriLId Example: code for English + + + + EMF+ manual 2.2.2.23, Microsoft name: EmfPlusLanguageIdentifier Object + + This type is defined as 16 bits in the manual section, but it is only ever used as part of a 32 bit field! +*/ +int U_PMF_LANGUAGEIDENTIFIER_get(U_PMF_LANGUAGEIDENTIFIER LId, int *SubLId, int *PriLId){ + if(!SubLId || !PriLId){ return(0); } + *SubLId = (LId >> U_FF_SHFT_SUBLID ) & U_FF_MASK_SUBLID; + *PriLId = (LId >> U_FF_SHFT_PRILID ) & U_FF_MASK_PRILID; + /* 16 bits above that are not used */ + return(1); +} + +/** + \brief Get data from a U_PMF_LINEARGRADIENTBRUSHDATA object + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Lgbd U_PMF_LINEARGRADIENTBRUSHDATA structure, with no variable part + \param Data variable part of U_PMF_LINEARGRADIENTBRUSHDATA + \param blimit one byte past the end of data + + EMF+ manual 2.2.2.24, Microsoft name: EmfPlusLinearGradientBrushData Object + + Caller must check Data for possible memory access violations. +*/ +int U_PMF_LINEARGRADIENTBRUSHDATA_get(const char *contents, U_PMF_LINEARGRADIENTBRUSHDATA *Lgbd, const char **Data, const char *blimit){ + if(!contents || !Lgbd || !Data || !blimit){ return(0); } + if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_LINEARGRADIENTBRUSHDATA), blimit))return(0); + U_PMF_SERIAL_get(&contents, Lgbd, 4, 6, U_LE); /* Flags, WrapMode, RectF*/ + U_PMF_SERIAL_get(&contents, &(Lgbd->StartColor), 4, 4, U_XE); /* StartColor, EndColor, Reserved1 & 2 */ + U_PMF_PTRSAV_SHIFT(Data, &contents, 0); + return(1); +} + +/** + \brief Get data from a U_PMF_LINEARGRADIENTBRUSHOPTIONALDATA object + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Flags BrushData flags - indicates which of the following date fields are present. + \param Tm Transformation matrix + \param Bc U_PMF_BLENDCOLORS object or NULL + \param BfH U_PMF_BLENDFACTORS (H) object or NULL + \param BfV U_PMF_BLENDFACTORS (V) object or NULL (WARNING, GDI+ defines this field but does not render it. DO NOT USE.) + \param blimit one byte past the end of data + + EMF+ manual 2.2.2.25, Microsoft name: EmfPlusLinearGradientBrushOptionalData Object + +*/ +int U_PMF_LINEARGRADIENTBRUSHOPTIONALDATA_get(const char *contents, uint32_t Flags, U_PMF_TRANSFORMMATRIX *Tm, + const char **Bc, const char **BfH, const char **BfV, const char *blimit){ + uint32_t Elements; + if(!contents || !Tm|| !Bc || !BfH || !BfV || !blimit){ return(0); } + /* all of the fields are optional! */ + *Bc = *BfH = *BfV = NULL; + if(Flags & U_BD_Transform){ + if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_ROTMATRIX), blimit))return(0); + U_PMF_SERIAL_get(&contents, Tm, 4, 6, U_LE); + } + if(Flags & U_BD_PresetColors){ + if(IS_MEM_UNSAFE(contents, 4, blimit))return(0); + U_PMF_SERIAL_get(&contents, &Elements, 4, 1, U_LE); /* starts with a 4 byte count*/ + if(IS_MEM_UNSAFE(contents, Elements * ( sizeof(U_FLOAT) + sizeof(U_PMF_ARGB)), blimit))return(0); + contents-=4; /* back up to the front of the count, as it is part of the data field */ + U_PMF_PTRSAV_SHIFT(Bc, &contents, 0); + } + else if(Flags & U_BD_BlendFactorsH){ + U_PMF_SERIAL_get(&contents, &Elements, 4, 1, U_LE); /* starts with a 4 byte count*/ + if(IS_MEM_UNSAFE(contents, Elements * 2 * sizeof(U_FLOAT), blimit))return(0); + contents-=4; /* back up to the front of the count, as it is part of the data field */ + U_PMF_PTRSAV_SHIFT(BfH, &contents, 4 + (Elements * 2 * sizeof(U_FLOAT))); /* 4 byte count + 2 * 4bytes * Elements */ + if(Flags & U_BD_BlendFactorsV){ + if(IS_MEM_UNSAFE(contents, Elements * 2 * sizeof(U_FLOAT), blimit))return(0); + U_PMF_PTRSAV_SHIFT(BfV, &contents, 0); + } + } + else if(Flags & U_BD_BlendFactorsV){ + U_PMF_SERIAL_get(&contents, &Elements, 4, 1, U_LE); /* starts with a 4 byte count*/ + if(IS_MEM_UNSAFE(contents, Elements * 2 * sizeof(U_FLOAT), blimit))return(0); + contents-=4; /* back up to the front of the count, as it is part of the data field */ + U_PMF_PTRSAV_SHIFT(BfV, &contents, 0); + } + return(1); +} + +/** + \brief Get data from a U_PMF_LINEPATH object + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Size Bytes in Data + \param Data Outline path + \param blimit one byte past the end of data + + EMF+ manual 2.2.2.26, Microsoft name: EmfPlusLinePath Object + + Caller must check Data for possible memory access violations. +*/ +int U_PMF_LINEPATH_get(const char *contents, int32_t *Size, const char **Data, const char *blimit){ + if(!contents || !Size || !Data || !blimit){ return(0); } + if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_LINEPATH), blimit))return(0); + U_PMF_SERIAL_get(&contents, Size, 4, 1, U_LE); + U_PMF_PTRSAV_SHIFT(Data, &contents, 0); + return(1); +} + +/** + \brief Get data from a U_PMF_METAFILE object + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Type + \param Size Bytes in Data + \param Data Various types of data, like an EMF metafile, WMF metafile, another EMF+ metafile + \param blimit one byte past the end of data + + EMF+ manual 2.2.2.27, Microsoft name: EmfPlusMetafile Object + + Caller must check Data for possible memory access violations. +*/ +int U_PMF_METAFILE_get(const char *contents, uint32_t *Type, uint32_t *Size, const char **Data, const char *blimit){ + if(!contents || !Type || !Size || !Data || !blimit){ return(0); } + if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_METAFILE), blimit))return(0); + U_PMF_SERIAL_get(&contents, &Type, 4, 1, U_LE); + U_PMF_SERIAL_get(&contents, &Size, 4, 1, U_LE); + U_PMF_PTRSAV_SHIFT(Data, &contents, 0); + return(1); +} + +/** + \brief Get data from a U_PMF_PALETTE object + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Flags PaletteStyle flags + \param Elements Members in the array + \param Colors Palette data (array of colors) + \param blimit one byte past the end of data + + EMF+ manual 2.2.2.28, Microsoft name: EmfPlusPalette Object +*/ +int U_PMF_PALETTE_get(const char *contents, uint32_t *Flags, uint32_t *Elements, const char **Colors, const char *blimit){ + if(!contents || !Flags || !Elements || !Colors || !blimit){ return(0); } + if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_PALETTE), blimit))return(0); + U_PMF_SERIAL_get(&contents, &Flags, 4, 1, U_LE); + U_PMF_SERIAL_get(&contents, &Elements, 4, 1, U_LE); + if(IS_MEM_UNSAFE(contents, *Elements*sizeof(U_RGBQUAD), blimit))return(0); + U_PMF_PTRSAV_SHIFT(Colors, &contents, 0); + return(1); + +} + +/** + \brief Get data from a U_PMF_PATHGRADIENTBRUSHDATA object + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Pgbd constant part of U_PMF_PATHGRADIENTBRUSHDATA object + \param Gradient variable part of U_PMF_LINEARGRADIENTBRUSHDATA, Color Gradient with Elements members + \param Boundary variable part of U_PMF_LINEARGRADIENTBRUSHDATA, U_PMF_BOUNDARYPATHDATA object if BrushDataPath bit set in Flag, else U_PMF_BOUNDARYPOINTDATA object + \param Data variable part of U_PMF_LINEARGRADIENTBRUSHDATA, exact composition depends on Flags + \param blimit one byte past the end of data + + EMF+ manual 2.2.2.29, Microsoft name: EmfPlusPathGradientBrushData Object + + Caller must check Data for possible memory access violations. + +*/ +int U_PMF_PATHGRADIENTBRUSHDATA_get(const char *contents, U_PMF_PATHGRADIENTBRUSHDATA *Pgbd, const char **Gradient, + const char **Boundary, const char **Data, const char *blimit){ + if(!contents || !Pgbd || !Gradient || !Boundary || !Data || !blimit){ return(0); } + if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_PATHGRADIENTBRUSHDATA), blimit))return(0); + uint32_t Size; + U_PMF_SERIAL_get(&contents, Pgbd, 4, 2, U_LE); /* Flags and WrapMode*/ + U_PMF_SERIAL_get(&contents, &(Pgbd->CenterColor), 4, 1, U_XE); + U_PMF_SERIAL_get(&contents, &(Pgbd->Center), 4, 3, U_LE); /* Center and Elements */ + if(IS_MEM_UNSAFE(contents, Pgbd->Elements * sizeof(U_PMF_ARGB), blimit))return(0); + U_PMF_PTRSAV_SHIFT(Gradient, &contents, Pgbd->Elements * sizeof(U_PMF_ARGB)); + U_PMF_PTRSAV_SHIFT(Boundary, &contents, 0); + U_PMF_SERIAL_get(&contents, &Size, 4, 1, U_LE); /* The first 4 bytes of the Boundary are always a size */ + if(Pgbd->Flags & U_BD_Path){ contents += Size; } // U_PMF_BOUNDARYPATHDATA + else { contents += Size*2*sizeof(U_FLOAT); } // U_PMF_BOUNDARYPOINTDATA + if(Pgbd->Flags & (U_BD_Transform |U_BD_PresetColors | U_BD_BlendFactorsH| U_BD_FocusScales)){ // optional data present + if(contents >= blimit)return(0); // the size is variable but this must still hold + U_PMF_PTRSAV_SHIFT(Data, &contents, 0); + } + else { *Data = NULL; } // no optional data present + return(1); +} + +/** + \brief Get data from a U_PMF_PATHGRADIENTBRUSHOPTIONALDATA object + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Flags bits set to indicate the presence of FillData and/or LineData + \param Matrix Transformation matrix + \param Pattern Blend Pattern + \param Data Focus scales for the brush + \param blimit one byte past the end of data + + EMF+ manual 2.2.2.30, Microsoft name: EmfPlusPathGradientBrushOptionalData Object +*/ +int U_PMF_PATHGRADIENTBRUSHOPTIONALDATA_get(const char *contents, uint32_t Flags, U_PMF_TRANSFORMMATRIX *Matrix, + const char **Pattern, const char **Data, const char *blimit){ + int varsize; + if(!contents || !Flags || !Matrix || !Pattern || !Data || !blimit){ return(0); } + /* this structure is entirely optional */ + if(Flags & U_BD_Transform){ + if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_TRANSFORMMATRIX), blimit))return(0); + U_PMF_SERIAL_get(&contents, Matrix, 4, 6, U_LE); + } + if(Flags & (U_BD_PresetColors | U_BD_BlendFactorsH)){ + if(IS_MEM_UNSAFE(contents, 4, blimit))return(0); + uint32_t Elements; + U_PMF_SERIAL_get(&contents, &Elements, 4, 1, U_LE); + contents -= 4; + varsize=(Elements * 4 * (Flags & U_BD_BlendFactorsH ? 2 :1)); + if(IS_MEM_UNSAFE(contents, varsize, blimit))return(0); + U_PMF_PTRSAV_SHIFT(Pattern, &contents, varsize); + } + else { *Pattern=NULL; } + if(Flags & U_BD_FocusScales){ + if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_FOCUSSCALEDATA), blimit))return(0); + U_PMF_PTRSAV_SHIFT(Data, &contents, sizeof(U_PMF_FOCUSSCALEDATA)); + } + else { *Data=NULL; } + return(1); +} + +/** + \brief Get data from a U_PMF_PATHPOINTTYPE object + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Flags PathPointType flags + \param Type PathPointType enumeration + \param blimit one byte past the end of data + + EMF+ manual 2.2.2.31, Microsoft name: EmfPlusPathPointType Object + + Note: order of 4bit fields appears to be shown in the LE column, not as + documented in the BE column. +*/ +int U_PMF_PATHPOINTTYPE_get(const char *contents, int *Flags, int *Type, const char *blimit){ + if(!contents || !Flags || !Type || !blimit){ return(0); } + if(IS_MEM_UNSAFE(contents, 1, blimit))return(0); + uint8_t tmp; + memcpy(&tmp, contents, 1); + *Flags =(tmp & U_PTP_MASK) >> U_PTP_SHIFT; + *Type = (tmp & U_PPT_MASK); + return(1); +} + +/** + \brief Get data from a U_PMF_PATHPOINTTYPERLE object + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Bezier Set: Bezier curve, Clear: straight line + \param RL Run Length + \param Ppt PathPointType enumeration + \param blimit one byte past the end of data + + EMF+ manual 2.2.2.32, Microsoft name: EmfPlusPathPointTypeRLE Object +*/ +int U_PMF_PATHPOINTTYPERLE_get(const char *contents, int *Bezier, int *RL, int *Ppt, const char *blimit){ + if(!contents || !Bezier || !RL || !Ppt || !blimit){ return(0); } + uint16_t tmp; + if(IS_MEM_UNSAFE(contents, 2, blimit))return(0); + U_PMF_SERIAL_get(&contents, &tmp, 2, 1, U_LE); + *Bezier = tmp & U_PPF_BZ; + *RL = (tmp >> U_FF_SHFT_RL) & U_FF_MASK_RL; + *Ppt = (tmp >> U_FF_SHFT_PPT) & U_FF_MASK_PPT; + return(1); +} + +/** + \brief Get data from a U_PMF_PENDATA object + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Flags PenData flags + \param Unit UnitType enumeration + \param Width Width in units set by Unit + \param Data Optional pen data, exact composition depends on Flags + \param blimit one byte past the end of data + + EMF+ manual 2.2.2.33, Microsoft name: EmfPlusPenData Object +*/ +int U_PMF_PENDATA_get(const char *contents, uint32_t *Flags, uint32_t *Unit, U_FLOAT *Width, const char **Data, const char *blimit){ + if(!contents || !Flags || !Unit || !Width || !Data || !blimit){ return(0); } + if(IS_MEM_UNSAFE(contents, 3*4, blimit))return(0); + U_PMF_SERIAL_get(&contents, Flags, 4, 1, U_LE); + U_PMF_SERIAL_get(&contents, Unit, 4, 1, U_LE); + U_PMF_SERIAL_get(&contents, Width, 4, 1, U_LE); + if(contents >= blimit)return(0); // variable data will extend farther, but this much at least must be true + U_PMF_PTRSAV_SHIFT(Data, &contents, 0); + return(1); +} + +/** + \brief Get data from a U_PMF_PENOPTIONALDATA object + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Flags; PenData Flags - indicated which of the many fields are present. + \param Matrix; Transformation matrix + \param StartCap LineCapType enumeration + \param EndCap LineCapType enumeration + \param Join LineJoinType enumeration + \param MiterLimit Maximum (miter length / line width) + \param Style LineStyle enumeration + \param DLCap DashedLineCapType enumeration + \param DLOffset Distance line start to first dash start + \param DLData Dash and space widths + \param Alignment PenAlignment enumeration + \param CmpndLineData Compount Line (parallel lines drawn instead of one) + \param CSCapData Custom start cap + \param CECapData Custom end cap + \param blimit one byte past the end of data + + EMF+ manual 2.2.2.34, Microsoft name: EmfPlusPenOptionalData Object + + This object consists of a large number of optional and or variable values, which + are returned, or not, depending on bits in Flags. +*/ +int U_PMF_PENOPTIONALDATA_get( + const char *contents, + uint32_t Flags, // determines which fields are filled + U_PMF_TRANSFORMMATRIX *Matrix, + int32_t *StartCap, + int32_t *EndCap, + uint32_t *Join, + U_FLOAT *MiterLimit, + int32_t *Style, + int32_t *DLCap, + U_FLOAT *DLOffset, + const char **DLData, + int32_t *Alignment, + const char **CmpndLineData, + const char **CSCapData, + const char **CECapData, + const char *blimit){ + if(!contents || + !Flags || !Matrix || !StartCap || !EndCap || + !Join || !MiterLimit || !Style || !DLCap || + !DLOffset || !DLData || !Alignment || !CmpndLineData || + !CSCapData || !CECapData || !blimit){ return(0); } + + if(Flags & U_PD_Transform){ if(IS_MEM_UNSAFE(contents, 4*6, blimit))return(0); + U_PMF_SERIAL_get(&contents, Matrix, 4, 6, U_LE); + } + if(Flags & U_PD_StartCap){ if(IS_MEM_UNSAFE(contents, 4, blimit))return(0); + U_PMF_SERIAL_get(&contents, StartCap, 4, 1, U_LE); + } + if(Flags & U_PD_EndCap){ if(IS_MEM_UNSAFE(contents, 4, blimit))return(0); + U_PMF_SERIAL_get(&contents, EndCap, 4, 1, U_LE); + } + if(Flags & U_PD_Join){ if(IS_MEM_UNSAFE(contents, 4, blimit))return(0); + U_PMF_SERIAL_get(&contents, Join, 4, 1, U_LE); + } + if(Flags & U_PD_MiterLimit){ if(IS_MEM_UNSAFE(contents, 4, blimit))return(0); + U_PMF_SERIAL_get(&contents, MiterLimit, 4, 1, U_LE); + } + if(Flags & U_PD_LineStyle){ if(IS_MEM_UNSAFE(contents, 4, blimit))return(0); + U_PMF_SERIAL_get(&contents, Style, 4, 1, U_LE); + } + if(Flags & U_PD_DLCap){ if(IS_MEM_UNSAFE(contents, 4, blimit))return(0); + U_PMF_SERIAL_get(&contents, DLCap, 4, 1, U_LE); + } + if(Flags & U_PD_DLOffset){ if(IS_MEM_UNSAFE(contents, 4, blimit))return(0); + U_PMF_SERIAL_get(&contents, DLOffset, 4, 1, U_LE); + } + if(Flags & U_PD_DLData){ if(IS_MEM_UNSAFE(contents, 4, blimit))return(0); + if(IS_MEM_UNSAFE(contents, U_PMF_LEN_FLOATDATA(contents), blimit))return(0); + U_PMF_PTRSAV_SHIFT( DLData, &contents, U_PMF_LEN_FLOATDATA(contents)); + } + if(Flags & U_PD_NonCenter){ if(IS_MEM_UNSAFE(contents, 4, blimit))return(0); + U_PMF_SERIAL_get(&contents, Alignment, 4, 1, U_LE); } + if(Flags & U_PD_CLData){ if(IS_MEM_UNSAFE(contents, 4, blimit))return(0); + if(IS_MEM_UNSAFE(contents, U_PMF_LEN_FLOATDATA(contents), blimit))return(0); + U_PMF_PTRSAV_SHIFT( CmpndLineData, &contents, U_PMF_LEN_FLOATDATA(contents)); + } + if(Flags & U_PD_CustomStartCap){ if(IS_MEM_UNSAFE(contents, 4, blimit))return(0); + if(IS_MEM_UNSAFE(contents, U_PMF_LEN_BYTEDATA(contents), blimit))return(0); + U_PMF_PTRSAV_SHIFT( CSCapData, &contents, U_PMF_LEN_BYTEDATA(contents)); + } + if(Flags & U_PD_CustomEndCap){ if(IS_MEM_UNSAFE(contents, 4, blimit))return(0); + if(IS_MEM_UNSAFE(contents, U_PMF_LEN_BYTEDATA(contents), blimit))return(0); + U_PMF_PTRSAV_SHIFT( CECapData, &contents, U_PMF_LEN_BYTEDATA(contents)); + } + return(1); +} + +/** + \brief Get data from a U_PMF_POINT object + \return 1 on success, 0 on error + \param contents Record from which to extract data. On return position is offset by sizeof(U_PMF_POINT). + \param X X coordinate + \param Y Y coordinate + \param blimit one byte past the end of data + + EMF+ manual 2.2.2.35, Microsoft name: EmfPlusPoint Object +*/ +int U_PMF_POINT_get(const char **contents, U_FLOAT *X, U_FLOAT *Y, const char *blimit){ + if(!contents || !X || !Y || !blimit){ return(0); } + int16_t tmp; + if(IS_MEM_UNSAFE(*contents, 2*2, blimit))return(0); + U_PMF_SERIAL_get(contents, &tmp, 2, 1, U_LE); *X = tmp; + U_PMF_SERIAL_get(contents, &tmp, 2, 1, U_LE); *Y = tmp; + return(1); +} + +/** + \brief Get data from a U_PMF_POINTF object + \return 1 on success, 0 on error + \param contents Record from which to extract data. On return position is offset by sizeof(U_PMF_POINTF). + \param X X coordinate + \param Y Y coordinate + \param blimit one byte past the end of data + + EMF+ manual 2.2.2.36, Microsoft name: EmfPlusPointF Object +*/ +int U_PMF_POINTF_get(const char **contents, U_FLOAT *X, U_FLOAT *Y, const char *blimit){ + if(!contents || !X || !Y || !blimit){ return(0); } + if(IS_MEM_UNSAFE(*contents, 4*2, blimit))return(0); + U_PMF_SERIAL_get(contents, X, 4, 1, U_LE); + U_PMF_SERIAL_get(contents, Y, 4, 1, U_LE); + return(1); +} + +/** + \brief Get data from a U_PMF_POINTR object + \return size in bytes traversed on success, 0 on error + \param contents Record from which to extract data. On return position is offset by returned size. + \param X X coordinate + \param Y Y coordinate + \param blimit one byte past the end of data + + EMF+ manual 2.2.2.37, Microsoft name: EmfPlusPointR Object +*/ +int U_PMF_POINTR_get(const char **contents, U_FLOAT *X, U_FLOAT *Y, const char *blimit){ + if(!contents || !*contents || !X || !Y || !blimit){ return(0); } + int size=0; + + if( U_PMF_INTEGER7_get( contents, X, blimit)){ size +=1; } + else if(U_PMF_INTEGER15_get(contents, X, blimit)){ size +=2; } + else { return(0); } + + if( U_PMF_INTEGER7_get( contents, Y, blimit)){ size +=1; } + else if(U_PMF_INTEGER15_get(contents, Y, blimit)){ size +=2; } + else { return(0); } + + return(size); +} + +/** + \brief Get data from a variable POINTS object, which may be U_PMF_POINTS, U_PMF_POINTF, or U_PMF_POINTR. + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Flags Record flags (bits U_PPF_C and U_PPF_P are referenced) + \param Elements Number of points to retrieve. + \param Points Caller must free. Array of U_PMF_POINTF coordinates. + \param blimit one byte past the end of data + + This function should never be called directly by end user code. +*/ +int U_PMF_VARPOINTS_get(const char *contents, uint16_t Flags, int Elements, U_PMF_POINTF **Points, const char *blimit){ + int status = 0; + if(!contents || !Points || !Elements || !blimit){ return(status); } + U_PMF_POINTF *pts = (U_PMF_POINTF *)malloc(Elements * sizeof(U_PMF_POINTF)); + if(!pts){ return(status); } + *Points = pts; + U_FLOAT XF, YF; + U_FLOAT XFS, YFS; + + if(Flags & U_PPF_P){ + for(XFS = YFS = 0.0; Elements; Elements--, pts++){ + if(!U_PMF_POINTR_get(&contents, &XF, &YF, blimit))return(0); /* this should never happen */ + XFS += XF; /* position relative to previous point, first point is always 0,0 */ + YFS += YF; + pts->X = XFS; + pts->Y = YFS; + } + } + else if(Flags & U_PPF_C){ + for(XF = YF = 0.0; Elements; Elements--, pts++){ + if(!U_PMF_POINT_get(&contents, &XF, &XF, blimit))break; /* this should never happen */ + pts->X = XF; + pts->Y = YF; + } + } + else { + for(XF = YF = 0.0; Elements; Elements--, pts++){ + (void) U_PMF_POINTF_get(&contents, &XF, &YF, blimit); + pts->X = XF; + pts->Y = YF; + } + } + if(Elements){ /* some error in the preceding */ + free(*Points); + *Points = NULL; + } + else { + status = 1; + } + return(status); +} + +/** + \brief Get data from a U_PMF_RECT object + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param X UL X value + \param Y UL Y value + \param Width Width + \param Height Height + \param blimit one byte past the end of data + + EMF+ manual 2.2.2.38, Microsoft name: EmfPlusRect Object +*/ +int U_PMF_RECT_get(const char **contents, int16_t *X, int16_t *Y, int16_t *Width, int16_t *Height, const char *blimit){ + if(!contents || !X || !Y|| !Width || !Height){ return(0); } + if(IS_MEM_UNSAFE(*contents, 2*4, blimit))return(0); + U_PMF_SERIAL_get(contents, X, 2, 1, U_LE); + U_PMF_SERIAL_get(contents, Y, 2, 1, U_LE); + U_PMF_SERIAL_get(contents, Width, 2, 1, U_LE); + U_PMF_SERIAL_get(contents, Height, 2, 1, U_LE); + return(1); +} + +/** + \brief Get data from a U_PMF_RECTF object + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param X UL X value + \param Y UL Y value + \param Width Width + \param Height Height + \param blimit one byte past the end of data + + EMF+ manual 2.2.2.39, Microsoft name: EmfPlusRectF Object +*/ +int U_PMF_RECTF_get(const char **contents, U_FLOAT *X, U_FLOAT *Y, U_FLOAT *Width, U_FLOAT *Height, const char *blimit){ + if(!contents || !X || !Y|| !Width || !Height){ return(0); } + if(IS_MEM_UNSAFE(*contents, 4*4, blimit))return(0); + U_PMF_SERIAL_get(contents, X, 4, 1, U_LE); + U_PMF_SERIAL_get(contents, Y, 4, 1, U_LE); + U_PMF_SERIAL_get(contents, Width, 4, 1, U_LE); + U_PMF_SERIAL_get(contents, Height, 4, 1, U_LE); + return(1); +} + +/** + \brief Get data from a variable RECTS object, which may be U_PMF_RECT or U_PMF_RECTF + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Flags Record flags (bit U_PPF_C is referenced) + \param Elements Number of rects to retrieve. + \param Rects Caller must free. Array of U_PMF_RECTF coordinates. + \param blimit one byte past the end of data + + Rects in record may be either U_PMF_RECT or U_PMF_RECTF, but this function always + returns U_PMF_RECTF +*/ +int U_PMF_VARRECTS_get(const char **contents, uint16_t Flags, int Elements, U_PMF_RECTF **Rects, const char *blimit){ + int16_t X16, Y16, Width, Height; + if(!contents || !*contents || !Rects || !blimit){ return(0); } + U_PMF_RECTF *rts = (U_PMF_RECTF *)malloc(Elements * sizeof(U_PMF_RECTF)); + if(!rts){ + *Rects = NULL; + return(0); + } + + *Rects = rts; + if(Flags & U_PPF_C){ + if(IS_MEM_UNSAFE(*contents, Elements*sizeof(U_PMF_RECT), blimit)){ + free(rts); + return(0); + } + } + else { + if(IS_MEM_UNSAFE(*contents, Elements*sizeof(U_PMF_RECT), blimit)){ + free(rts); + return(0); + } + } + for(; Elements; Elements--, rts++){ + if(Flags & U_PPF_C){ + (void) U_PMF_RECT_get(contents, &X16, &Y16, &Width, &Height, blimit); + rts->X = X16; + rts->Y = Y16; + rts->Width = Width; + rts->Height = Height; + } + else { + (void) U_PMF_RECTF_get(contents, &(rts->X), &(rts->Y), &(rts->Width), &(rts->Height), blimit); + } + } + return(1); +} + +/** + \brief Get data from a U_PMF_REGIONNODE object + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Type RegionNodeDataType + \param Data Depending on Type: U_PMF_REGIONNODEPATH, U_PMF_RECTF, or U_PMF_REGIONNODECHILDNODES + \param blimit one byte past the end of data + + EMF+ manual 2.2.2.40, Microsoft name: EmfPlusRegionNode Object + + Caller must check Data for possible memory access violations. +*/ +int U_PMF_REGIONNODE_get(const char *contents, uint32_t *Type, const char **Data, const char *blimit){ + if(!contents || !Type || !Data || !blimit){ return(0); } + /* Important! This only checks the constant part, the caller must check that returned data doesn't exceed blimit */ + if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_REGIONNODE), blimit))return(0); + U_PMF_SERIAL_get(&contents, Type, 4, 1, U_LE); + if(contents >= blimit)return(0); // returned Data is variable size, this much at least must be true + U_PMF_PTRSAV_COND(Data, contents, !(*Type == U_RNDT_Empty || *Type == U_RNDT_Infinite )); + return(1); +} + +/** + There is no U_PMF_REGIONNODECHILDNODES_get! + + The Region object is recursive allowing U_PMF_REGIONNODECHILDNODES -> + U_PMF_REGIONNODE -> U_PMF_REGIONNODECHILDNODES etc. + So the data stored in each node must be handled as the tree is followed recursively. + + See U_PMF_REGIONNODECHILDNODES_print() and U_PMF_REGIONNODE_print() for an example. + + + EMF+ manual 2.2.2.41, Microsoft name: EmfPlusRegionNodeChildNodes Object +*/ + +/** + \brief Get data from a U_PMF_REGIONNODEPATH object + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Size Bytes in Data + \param Data Boundary of region node + \param blimit one byte past the end of data + + EMF+ manual 2.2.2.42, Microsoft name: EmfPlusRegionNodePath Object +*/ +int U_PMF_REGIONNODEPATH_get(const char *contents, int32_t *Size, const char **Data, const char *blimit){ + if(!contents || !Size || !Data || !blimit){ return(0); } + /* Important! This only checks the constant part, the caller must check that returned data doesn't exceed blimit */ + if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_REGIONNODEPATH), blimit))return(0); + U_PMF_SERIAL_get(&contents, Size, 4, 1, U_LE); + if(contents >= blimit)return(0); // returned Data is variable size, this much at least must be true + U_PMF_PTRSAV_SHIFT(Data, &contents, 0); + return(1); +} + +/** + \brief Get data from a U_PMF_SOLIDBRUSHDATA object + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Color Color of brush + \param blimit one byte past the end of data + + EMF+ manual 2.2.2.43, Microsoft name: EmfPlusSolidBrushData Object +*/ +int U_PMF_SOLIDBRUSHDATA_get(const char *contents, U_PMF_ARGB *Color, const char *blimit){ + if(!contents || !Color || !blimit){ return(0); } + if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_SOLIDBRUSHDATA), blimit))return(0); + U_PMF_SERIAL_get(&contents, Color, 4, 1, U_XE); + return(1); +} + +/** + \brief Get data from a U_PMF_STRINGFORMATDATA object + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param TabStopCount Entries in TabStop array + \param RangeCount Entries in CharRange array + \param TabStops Array of tabstop locations + \param CharRange Array of character ranges in the text + \param blimit one byte past the end of data + + EMF+ manual 2.2.2.44, Microsoft name: EmfPlusStringFormatData Object +*/ +int U_PMF_STRINGFORMATDATA_get(const char *contents, uint32_t TabStopCount, uint32_t RangeCount, + const U_FLOAT **TabStops, const U_PMF_CHARACTERRANGE **CharRange, const char *blimit){ + if(!contents || !TabStops|| !CharRange || !blimit){ return(0); } + if(IS_MEM_UNSAFE(contents, (TabStopCount + 2*RangeCount)*4, blimit))return(0); + *TabStops = NULL; + if(TabStopCount > 0){ U_PMF_SERIAL_get(&contents, TabStops, 4, TabStopCount, U_LE); } + *CharRange = NULL; + if(RangeCount > 0){ U_PMF_SERIAL_get(&contents, CharRange, 4, 2*RangeCount, U_LE); } + return(1); +} + +/** + \brief Get data from a U_PMF_TEXTUREBRUSHDATA object + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Flags BrushData flags + \param WrapMode WrapMode enumeration + \param Data Optional texture data + \param blimit one byte past the end of data + + EMF+ manual 2.2.2.45, Microsoft name: EmfPlusTextureBrushData Object + + Caller must check Data for possible memory access violations. +*/ +int U_PMF_TEXTUREBRUSHDATA_get(const char *contents, uint32_t *Flags, int32_t *WrapMode, const char **Data, const char *blimit){ + if(!contents || !Flags || !WrapMode || !Data || !blimit){ return(0); } + /* Important! This only checks the constant part, the caller must check that returned data doesn't exceed blimit */ + if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_TEXTUREBRUSHDATA), blimit))return(0); + U_PMF_SERIAL_get(&contents, Flags, 4, 1, U_LE); + U_PMF_SERIAL_get(&contents, WrapMode, 4, 1, U_LE); + if(contents >= blimit)return(0); // returned Data is variable size, this much at least must be true + U_PMF_PTRSAV_SHIFT(Data, &contents, 0); + return(1); +} + +/** + \brief Get data from a U_PMF_TEXTUREBRUSHOPTIONALDATA object + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param HasImage True if this object has an Image + \param Matrix Transformation matrix, NULL if Flag BrushDataTransform is not set. + \param Image Image that contains the texture. + \param blimit one byte past the end of data + + EMF+ manual 2.2.2.46, Microsoft name: EmfPlusTextureBrushOptionalData Object + + Caller must check Image for possible memory access violations. +*/ +int U_PMF_TEXTUREBRUSHOPTIONALDATA_get(const char *contents, int HasImage, U_PMF_TRANSFORMMATRIX *Matrix, + const char **Image, const char *blimit){ + if(!contents || !Image || !blimit){ return(0); } + if(Matrix){ + if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_TRANSFORMMATRIX), blimit))return(0); + U_PMF_SERIAL_get(&contents, Matrix, 4, 6, U_LE); + } + if(HasImage){ + if(contents >= blimit)return(0); // returned Data is variable size, this much at least must be true + U_PMF_PTRSAV_COND(Image, contents, HasImage); + } + return(1); +} + +/** + \brief Get data from a U_PMF_TRANSFORMMATRIX object + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Matrix Transformation matrix, present if Flag BrushDataTransform is set. + \param blimit one byte past the end of data + + EMF+ manual 2.2.2.47, Microsoft name: EmfPlusTransformMatrix Object +*/ +int U_PMF_TRANSFORMMATRIX_get(const char *contents, U_PMF_TRANSFORMMATRIX *Matrix, const char *blimit){ + if(!contents || !Matrix || !blimit){ return(0); } + if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_TRANSFORMMATRIX), blimit))return(0); + U_PMF_SERIAL_get(&contents, Matrix, 4, 6, U_LE); + return(1); +} + +/** + \brief Get data from a U_PMF_IE_BLUR object + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Radius Blur radius in pixels + \param ExpandEdge 1: expand bitmap by Radius; 0: bitmap size unchanged + \param blimit one byte past the end of data + + EMF+ manual 2.2.3.1, Microsoft name: BlurEffect Object +*/ +int U_PMF_IE_BLUR_get(const char *contents, U_FLOAT *Radius, uint32_t *ExpandEdge, const char *blimit){ + if(!contents || !Radius || !ExpandEdge || !blimit){ return(0); } + if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_IE_BLUR), blimit))return(0); + U_PMF_SERIAL_get(&contents, Radius, 4, 1, U_LE); + U_PMF_SERIAL_get(&contents, ExpandEdge, 4, 1, U_LE); + return(1); +} + +/** + \brief Get data from a U_PMF_IE_BRIGHTNESSCONTRAST object + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Brightness -255 to 255, 0 is unchanged, positive increases, negative decreases + \param Contrast -100 to 100, 0 is unchanged, positive increases, negative decreases + \param blimit one byte past the end of data + + EMF+ manual 2.2.3.2, Microsoft name: BrightnessContrastEffect Object +*/ +int U_PMF_IE_BRIGHTNESSCONTRAST_get(const char *contents, int32_t *Brightness, int32_t *Contrast, const char *blimit){ + if(!contents || !Brightness || !Contrast || !blimit){ return(0); } + if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_IE_BRIGHTNESSCONTRAST), blimit))return(0); + U_PMF_SERIAL_get(&contents, Brightness, 4, 1, U_LE); + U_PMF_SERIAL_get(&contents, Contrast, 4, 1, U_LE); + return(1); +} + +/** + \brief Get data from a U_PMF_IE_COLORBALANCE object + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param CyanRed -100 to 100, 0 is unchanged, positive increases Red & decreases Cyan, negative is opposite + \param MagentaGreen -100 to 100, 0 is unchanged, positive increases Green & decreases Magenta, negative is opposite + \param YellowBlue -100 to 100, 0 is unchanged, positive increases Blue & decreases Yellow, negative is opposite + \param blimit one byte past the end of data + + EMF+ manual 2.2.3.3, Microsoft name: ColorBalanceEffect Object +*/ +int U_PMF_IE_COLORBALANCE_get(const char *contents, int32_t *CyanRed, int32_t *MagentaGreen, int32_t *YellowBlue, const char *blimit){ + if(!contents || !CyanRed || !MagentaGreen || !YellowBlue || !blimit){ return(0); } + if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_IE_COLORBALANCE), blimit))return(0); + U_PMF_SERIAL_get(&contents, CyanRed, 4, 1, U_LE); + U_PMF_SERIAL_get(&contents, MagentaGreen, 4, 1, U_LE); + U_PMF_SERIAL_get(&contents, YellowBlue, 4, 1, U_LE); + return(1); +} + + +/** + \brief Get data from a U_PMF_IE_COLORCURVE object + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Adjust CurveAdjustment enumeration + \param Channel CurveChannel enumeration + \param Intensity adjustment to apply. "Adjust" determines what field this is and range values. + \param blimit one byte past the end of data + + EMF+ manual 2.2.3.4, Microsoft name: ColorCurveEffect Object +*/ +int U_PMF_IE_COLORCURVE_get(const char *contents, uint32_t *Adjust, uint32_t *Channel, int32_t *Intensity, const char *blimit){ + if(!contents || !Adjust || !Channel || !Intensity || !blimit){ return(0); } + if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_IE_COLORCURVE), blimit))return(0); + U_PMF_SERIAL_get(&contents, Adjust, 4, 1, U_LE); + U_PMF_SERIAL_get(&contents, Channel, 4, 1, U_LE); + U_PMF_SERIAL_get(&contents, Intensity, 4, 1, U_LE); + return(1); +} + +/** + \brief Get data from a U_PMF_IE_COLORLOOKUPTABLE object + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param BLUT Blue color lookup table + \param GLUT Green color lookup table + \param RLUT Red color lookup table + \param ALUT Alpha color lookup table + \param blimit one byte past the end of data + + EMF+ manual 2.2.3.5, Microsoft name: ColorLookupTableEffect Object +*/ +int U_PMF_IE_COLORLOOKUPTABLE_get(const char *contents, + const uint8_t **BLUT, const uint8_t **GLUT, const uint8_t **RLUT, const uint8_t **ALUT, const char *blimit){ + if(!contents || !BLUT || !GLUT || !RLUT || !ALUT || !blimit){ return(0); } + if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_IE_COLORLOOKUPTABLE) + 4 * 256, blimit))return(0); + U_PMF_PTRSAV_SHIFT((const char **)BLUT, &contents, 256); + U_PMF_PTRSAV_SHIFT((const char **)GLUT, &contents, 256); + U_PMF_PTRSAV_SHIFT((const char **)RLUT, &contents, 256); + U_PMF_PTRSAV_SHIFT((const char **)ALUT, &contents, 256); + return(1); +} + +/** + \brief Get data from a U_PMF_IE_COLORMATRIX object + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Matrix 5 x 5 color transformation matrix, First 4 rows are [{4 multiplier values},0.0] for R,G,B,A, last Row is [{4 color translation valuess}, 1.0] + \param blimit one byte past the end of data + + EMF+ manual 2.2.3.6, Microsoft name: ColorMatrixEffect Object +*/ +int U_PMF_IE_COLORMATRIX_get(const char *contents, U_PMF_IE_COLORMATRIX *Matrix, const char *blimit){ + if(!contents || !Matrix || !blimit){ return(0); } + /* Important! This only checks the constant part, the caller must check that returned data doesn't exceed blimit */ + if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_IE_COLORMATRIX), blimit))return(0); + U_PMF_SERIAL_get(&contents, Matrix, 4, 5*5, U_LE); + return(1); +} + +/** + \brief Get data from a U_PMF_IE_HUESATURATIONLIGHTNESS object + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Hue -180 to 180, 0 is unchanged + \param Saturation -100 to 100, 0 is unchanged + \param Lightness -100 to 100, 0 is unchanged + \param blimit one byte past the end of data + + EMF+ manual 2.2.3.7, Microsoft name: HueSaturationLightnessEffect Object +*/ +int U_PMF_IE_HUESATURATIONLIGHTNESS_get(const char *contents, int32_t *Hue, int32_t *Saturation, int32_t *Lightness, const char *blimit){ + if(!contents || !Hue || !Saturation || !Lightness || !blimit){ return(0); } + if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_IE_HUESATURATIONLIGHTNESS), blimit))return(0); + U_PMF_SERIAL_get(&contents, Hue, 4, 1, U_LE); + U_PMF_SERIAL_get(&contents, Saturation, 4, 1, U_LE); + U_PMF_SERIAL_get(&contents, Lightness, 4, 1, U_LE); + return(1); +} + +/** + \brief Get data from a U_PMF_IE_LEVELS object + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Highlight 0 to 100, 100 is unchanged + \param Midtone -100 to 100, 0 is unchanged + \param Shadow 0 to 100, 0 is unchanged + \param blimit one byte past the end of data + + EMF+ manual 2.2.3.8, Microsoft name: LevelsEffect Object +*/ +int U_PMF_IE_LEVELS_get(const char *contents, int32_t *Highlight, int32_t *Midtone, int32_t *Shadow, const char *blimit){ + if(!contents || !Highlight || !Midtone || !Shadow || !blimit){ return(0); } + if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_IE_LEVELS), blimit))return(0); + U_PMF_SERIAL_get(&contents, Highlight, 4, 1, U_LE); + U_PMF_SERIAL_get(&contents, Midtone, 4, 1, U_LE); + U_PMF_SERIAL_get(&contents, Shadow, 4, 1, U_LE); + return(1); +} + +/** + \brief Get data from a U_PMF_IE_REDEYECORRECTION object + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Elements Number of members in Rects + \param Rects Caller must free. Pointer to memory holding an array of U_RECTL. + \param blimit one byte past the end of data + + EMF+ manual 2.2.3.9, Microsoft name: RedEyeCorrectionEffect Object +*/ +int U_PMF_IE_REDEYECORRECTION_get(const char *contents, int32_t *Elements, U_RECTL **Rects, const char *blimit){ + if(!contents || !Elements || !Rects || !blimit){ return(0); } + if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_IE_REDEYECORRECTION), blimit))return(0); + U_PMF_SERIAL_get(&contents, Elements, 4, 1, U_LE); + if(IS_MEM_UNSAFE(contents, *Elements * 4, blimit))return(0); + *Rects = (U_RECTL *) malloc(*Elements * sizeof(U_RECTL)); + if(!*Rects){ return(0); } + U_PMF_SERIAL_get(&contents, *Rects, 4, *Elements * 4, U_LE); + return(1); +} + +/** + \brief Get data from a U_PMF_IE_SHARPEN object + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Radius Sharpening radius in pixels + \param Sharpen 0 to 100, 0 is unchanged + \param blimit one byte past the end of data + + EMF+ manual 2.2.3.10, Microsoft name: SharpenEffect Object +*/ +int U_PMF_IE_SHARPEN_get(const char *contents, U_FLOAT *Radius, int32_t *Sharpen, const char *blimit){ + if(!contents || !Radius || !Sharpen || !blimit){ return(0); } + if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_IE_SHARPEN), blimit))return(0); + U_PMF_SERIAL_get(&contents, Radius, 4, 1, U_LE); + U_PMF_SERIAL_get(&contents, Sharpen, 4, 1, U_LE); + return(1); +} + +/** + \brief Get data from a U_PMF_IE_TINT object + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Hue -180 to 180, [positive==clockwise] rotation in degrees starting from blue + \param Amount -100 [add black] to 100[add white], 0 is unchanged. Change in hue on specified axis + \param blimit one byte past the end of data + + EMF+ manual 2.2.3.11, Microsoft name: TintEffect Object +*/ +int U_PMF_IE_TINT_get(const char *contents, int32_t *Hue, int32_t *Amount, const char *blimit){ + if(!contents || !Hue || !Amount || !blimit){ return(0); } + if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_IE_TINT), blimit))return(0); + U_PMF_SERIAL_get(&contents, Hue, 4, 1, U_LE); + U_PMF_SERIAL_get(&contents, Amount, 4, 1, U_LE); + return(1); +} + +/* + + end of U_PMF_*_get() functions + ===================================================================================== + start of U_PMR_*_get() functions + + These functions all assume that the size field in the common EMF+ header has already + been checked, so that the extent the record claims exists in the data read in for the file. + Consequently none of them takes a blimit parameter. They generate a new one from the + header size field and contents if needed. + +*/ + +int U_PMR_common_stack_get(const char *contents, U_PMF_CMN_HDR *Header, uint32_t *StackID){ + if(!contents || !StackID){ return(0); } + + U_PMF_CMN_HDR lclHeader; + U_PMF_CMN_HDR_get(&contents, &lclHeader); + if(lclHeader.Size < sizeof(U_PMF_RESTORE))return(0); + if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); } + + U_PMF_SERIAL_get(&contents, StackID, 4, 1, U_LE); + return(1); +} + +/* for records that have a type but no associated flag bits or data */ +int U_PMR_common_header_get(const char *contents, U_PMF_CMN_HDR *Header){ + /* memory access safe, only uses the common header */ + if(!contents){ return(0); } + U_PMF_CMN_HDR_get(&contents, Header); + return(1); +} + +/** + \brief Get data from a U_PMR_OFFSETCLIP record + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Header Common header (ignore flags) + \param dX horizontal translation offset to apply to clipping region + \param dY vertical translation offset to apply to clipping region + + EMF+ manual 2.3.1.1, Microsoft name: EmfPlusOffsetClip Record, Index 0x35 +*/ +int U_PMR_OFFSETCLIP_get(const char *contents, U_PMF_CMN_HDR *Header, + U_FLOAT *dX, U_FLOAT *dY){ + if(!contents){ return(0); } + + U_PMF_CMN_HDR lclHeader; + U_PMF_CMN_HDR_get(&contents, &lclHeader); + if(lclHeader.Size < sizeof(U_PMF_OFFSETCLIP))return(0); + if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); } + + U_PMF_SERIAL_get(&contents, dX, 4, 1, U_LE); + U_PMF_SERIAL_get(&contents, dY, 4, 1, U_LE); + return(1); +} + +/** + \brief Get data from a U_PMR_RESETCLIP record + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Header Common header (ignore flags) + + EMF+ manual 2.3.1.2, Microsoft name: EmfPlusResetClip Record, Index 0x31 +*/ +int U_PMR_RESETCLIP_get(const char *contents, U_PMF_CMN_HDR *Header){ + if(!contents){ return(0); } + U_PMF_CMN_HDR_get(&contents, Header); + return(1); +} + +/** + \brief Get data from a U_PMR_SETCLIPPATH record + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Header Common header + \param CMenum CombineMode enumeration.. + \param PathID U_PMF_PATH object in the EMF+ object table (0-63, inclusive) + + EMF+ manual 2.3.1.3, Microsoft name: EmfPlusSetClipPath Record, Index 0x33 +*/ +int U_PMR_SETCLIPPATH_get(const char *contents, U_PMF_CMN_HDR *Header, + uint32_t *PathID, int *CMenum){ + if(!contents || !PathID || !CMenum){ return(0); } + + U_PMF_CMN_HDR lclHeader; + U_PMF_CMN_HDR_get(&contents, &lclHeader); + if(lclHeader.Size < sizeof(U_PMF_SETCLIPPATH))return(0); + if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); } + + *CMenum = (lclHeader.Flags >> U_FF_SHFT_CM4) & U_FF_MASK_CM4; + *PathID = (lclHeader.Flags >> U_FF_SHFT_OID8) & U_FF_MASK_OID8; + return(1); +} + +/** + \brief Get data from a U_PMR_SETCLIPRECT record + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Header Common header (ignore flags) + \param CMenum Combine mode enumeration. + \param Rect Rectangle used with CombineMode enumeration from Header.Flags + + EMF+ manual 2.3.1.4, Microsoft name: EmfPlusSetClipRect Record, Index 0x32 +*/ +int U_PMR_SETCLIPRECT_get(const char *contents, U_PMF_CMN_HDR *Header, + int *CMenum, + U_PMF_RECTF *Rect){ + if(!contents || !CMenum || !Rect ){ return(0); } + + U_PMF_CMN_HDR lclHeader; + U_PMF_CMN_HDR_get(&contents, &lclHeader); + if(lclHeader.Size < sizeof(U_PMF_SETCLIPRECT))return(0); + if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); } + + *CMenum = (lclHeader.Flags >> U_FF_SHFT_CM4) & U_FF_MASK_CM4; + U_PMF_SERIAL_get(&contents, Rect, 4, 4, U_LE); + return(1); +} + +/** + \brief Get data from a U_PMR_SETCLIPREGION record + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Header Common header + \param CMenum CombineMode enumeration.. + \param PathID U_PMF_PATH object in the EMF+ object table (0-63, inclusive) + + EMF+ manual 2.3.1.5, Microsoft name: EmfPlusSetClipRegion Record, Index 0x34 +*/ +int U_PMR_SETCLIPREGION_get(const char *contents, U_PMF_CMN_HDR *Header, + uint32_t *PathID, int *CMenum){ + if(!contents || !PathID || !CMenum){ return(0); } + + U_PMF_CMN_HDR lclHeader; + U_PMF_CMN_HDR_get(&contents, &lclHeader); + if(lclHeader.Size < sizeof(U_PMF_SETCLIPREGION))return(0); + if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); } + + *CMenum = (lclHeader.Flags >> U_FF_SHFT_CM4) & U_FF_MASK_CM4; + *PathID = (lclHeader.Flags >> U_FF_SHFT_OID8) & U_FF_MASK_OID8; + return(1); +} + +/** + \brief Get data from a U_PMR_COMMENT record + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Header Common header (ignore flags) + \param Data Private data, may be anything + + EMF+ manual 2.3.2.1, Microsoft name: EmfPlusComment Record, Index 0x03 + + Caller must check Data for possible memory access violations. +*/ +int U_PMR_COMMENT_get(const char *contents, U_PMF_CMN_HDR *Header, + const char **Data){ + if(!contents || !Data){ return(0); } + + U_PMF_CMN_HDR lclHeader; + U_PMF_CMN_HDR_get(&contents, &lclHeader); + if(lclHeader.Size < sizeof(U_PMF_COMMENT))return(0); + if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); } + + U_PMF_PTRSAV_SHIFT(Data, &contents, 0); + return(1); +} + +/** + \brief Get data from a U_PMR_ENDOFFILE record + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Header Common header (ignore flags) + + EMF+ manual 2.3.3.1, Microsoft name: EmfPlusEndOfFile Record, Index 0x02 +*/ +int U_PMR_ENDOFFILE_get(const char *contents, U_PMF_CMN_HDR *Header){ + if(!contents){ return(0); } + U_PMF_CMN_HDR_get(&contents, Header); + return(1); +} + +/** + \brief Get data from a U_PMR_GETDC record + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Header Common header (ignore flags) + + EMF+ manual 2.3.3.2, Microsoft name: EmfPlusGetDC Record, Index 0x04 +*/ +int U_PMR_GETDC_get(const char *contents, U_PMF_CMN_HDR *Header){ + if(!contents){ return(0); } + U_PMF_CMN_HDR_get(&contents, Header); + return(1); +} + +/** + \brief Get data from a U_PMR_HEADER record + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Header Common header (ignore flags) + \param Version EmfPlusGraphicsVersion object + \param IsDual set = Dual-mode file, clear= EMF+ only file. + \param IsVideo set = video device, clear= printer. Ignore all other bits. + \param LogicalDpiX Horizontal resolution reference device in DPI + \param LogicalDpiY Vertical resolution reference device in DPI + + EMF+ manual 2.3.3.3, Microsoft name: EmfPlusHeader Record, Index 0x01 +*/ +int U_PMR_HEADER_get(const char *contents, U_PMF_CMN_HDR *Header, + U_PMF_GRAPHICSVERSION *Version, int *IsDual, int *IsVideo, uint32_t *LogicalDpiX, uint32_t *LogicalDpiY){ + if(!contents || !Version || !IsDual || !IsVideo || !LogicalDpiX || !LogicalDpiY){ return(0); } + uint32_t tmp; + + U_PMF_CMN_HDR lclHeader; + U_PMF_CMN_HDR_get(&contents, &lclHeader); + if(lclHeader.Size < sizeof(U_PMF_HEADER))return(0); + if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); } + + *IsDual = (lclHeader.Flags & U_PPF_DM ? 1 : 0 ); + U_PMF_SERIAL_get(&contents, Version, 4, 1, U_LE); + U_PMF_SERIAL_get(&contents, &tmp, 4, 1, U_LE); + U_PMF_SERIAL_get(&contents, LogicalDpiX, 4, 1, U_LE); + U_PMF_SERIAL_get(&contents, LogicalDpiY, 4, 1, U_LE); + *IsVideo = (tmp & U_PPF_VIDEO ? 1 : 0 ); + return(1); +} + +/** + \brief Get data from a U_PMR_CLEAR record + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Header Common header (ignore flags) + \param Color Erase everything preceding, set background ARGB color. + + EMF+ manual 2.3.4.1, Microsoft name: EmfPlusClear Record, Index 0x09 +*/ +int U_PMR_CLEAR_get(const char *contents, U_PMF_CMN_HDR *Header, + U_PMF_ARGB *Color){ + if(!contents || !Color){ return(0); } + + U_PMF_CMN_HDR lclHeader; + U_PMF_CMN_HDR_get(&contents, &lclHeader); + if(lclHeader.Size < sizeof(U_PMF_CLEAR))return(0); + if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); } + + U_PMF_SERIAL_get(&contents, Color, 4, 1, U_LE); + return(1); +} + +/** + \brief Get data from a U_PMR_DRAWARC record + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Header Common header + \param PenID U_PMF_PEN object in the EMF+ object table (0-63, inclusive) + \param ctype Set: int16_t coordinates; Clear: U_FLOAT coordinates + \param Start Start angle, >=0.0, degrees clockwise from 3:00 + \param Sweep Sweep angle, -360<= angle <=360, degrees clockwise from Start + \param Rect Caller must free. Bounding rectangle. Coordinate type set by ctype. + + EMF+ manual 2.3.4.2, Microsoft name: EmfPlusDrawArc Record, Index 0x12 +*/ +int U_PMR_DRAWARC_get(const char *contents, U_PMF_CMN_HDR *Header, + uint32_t *PenID, int *ctype, + U_FLOAT *Start, U_FLOAT *Sweep, + U_PMF_RECTF *Rect){ + if(!contents || !PenID || !ctype || !Start || !Sweep || !Rect){ return(0); } + + const char *blimit = contents; + U_PMF_CMN_HDR lclHeader; + U_PMF_CMN_HDR_get(&contents, &lclHeader); + if(lclHeader.Size < sizeof(U_PMF_DRAWARC))return(0); + if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); } + blimit += lclHeader.Size; + + *ctype = (lclHeader.Flags & U_PPF_C ? 1 : 0 ); + *PenID = (lclHeader.Flags >> U_FF_SHFT_OID8) & U_FF_MASK_OID8; + U_PMF_SERIAL_get(&contents, Start, 4, 1, U_LE); + U_PMF_SERIAL_get(&contents, Sweep, 4, 1, U_LE); + U_PMF_RECTF *Rects = NULL; + if(!U_PMF_VARRECTS_get(&contents, lclHeader.Flags, 1, &Rects, blimit))return(0); + memcpy(Rect,Rects,sizeof(U_PMF_RECTF)); + free(Rects); + return(1); +} + + +/** + \brief Get data from a U_PMR_DRAWBEZIERS record + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Header Common header + \param PenID U_PMF_PEN object in the EMF+ object table (0-63, inclusive) + \param ctype Set: int16_t coordinates; Clear: U_FLOAT coordinates + \param RelAbs Set: Coordinates are relative; Clear: Coordinates are absolute and their type is set by ctype + \param Elements Number of members in the Data array + \param Points Caller must free. Array of U_POINT_F = Sequence of points to connect. Coordinate type set by ctype and RelAbs. + + EMF+ manual 2.3.4.3, Microsoft name: EmfPlusDrawBeziers Record, Index 0x19 +*/ +int U_PMR_DRAWBEZIERS_get(const char *contents, U_PMF_CMN_HDR *Header, + uint32_t *PenID, int *ctype, int *RelAbs, + uint32_t *Elements, + U_PMF_POINTF **Points){ + if(!contents || !PenID || !ctype || !RelAbs || !Elements || !Points){ return(0); } + + const char *blimit = contents; + U_PMF_CMN_HDR lclHeader; + U_PMF_CMN_HDR_get(&contents, &lclHeader); + if(lclHeader.Size < sizeof(U_PMF_DRAWBEZIERS))return(0); + if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); } + blimit += lclHeader.Size; + + *ctype = (lclHeader.Flags & U_PPF_C ? 1 : 0 ); + *RelAbs = (lclHeader.Flags & U_PPF_P ? 1 : 0 ); + *PenID = (lclHeader.Flags >> U_FF_SHFT_OID8) & U_FF_MASK_OID8; + U_PMF_SERIAL_get(&contents, Elements, 4, 1, U_LE); + int status = U_PMF_VARPOINTS_get(contents, lclHeader.Flags, *Elements, Points, blimit ); + return(status); +} + +/** + \brief Get data from a U_PMR_DRAWCLOSEDCURVE record + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Header Common header + \param PenID U_PMF_PEN object in the EMF+ object table (0-63, inclusive) + \param ctype Set: int16_t coordinates; Clear: U_FLOAT coordinates + \param RelAbs Set: Coordinates are relative; Clear: Coordinates are absolute and their type is set by ctype + \param Tension Controls splines, 0 is straight line, >0 is curved + \param Elements Number of members in the Data array + \param Points Caller must free. Array of U_POINT_F = Sequence of points to connect. Coordinate type set by ctype and RelAbs. + + EMF+ manual 2.3.4.4, Microsoft name: EmfPlusDrawClosedCurve Record, Index 0x17 +*/ +int U_PMR_DRAWCLOSEDCURVE_get(const char *contents, U_PMF_CMN_HDR *Header, + uint32_t *PenID, int *ctype, int *RelAbs, + U_FLOAT *Tension, uint32_t *Elements, + U_PMF_POINTF **Points){ + if(!contents || !PenID || !ctype || !RelAbs || !Tension || !Elements || !Points){ return(0); } + + const char *blimit = contents; + U_PMF_CMN_HDR lclHeader; + U_PMF_CMN_HDR_get(&contents, &lclHeader); + if(lclHeader.Size < sizeof(U_PMF_DRAWCLOSEDCURVE))return(0); + if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); } + blimit += lclHeader.Size; + + *ctype = (lclHeader.Flags & U_PPF_C ? 1 : 0 ); + *RelAbs = (lclHeader.Flags & U_PPF_P ? 1 : 0 ); + *PenID = (lclHeader.Flags >> U_FF_SHFT_OID8) & U_FF_MASK_OID8; + U_PMF_SERIAL_get(&contents, Tension, 4, 1, U_LE); + U_PMF_SERIAL_get(&contents, Elements, 4, 1, U_LE); + U_PMF_VARPOINTS_get(contents, lclHeader.Flags, *Elements, Points, blimit); + return(1); +} + +/** + \brief Get data from a U_PMR_DRAWCURVE record + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Header Common header + \param PenID U_PMF_PEN object in the EMF+ object table (0-63, inclusive) + \param ctype Set: int16_t coordinates; Clear: U_FLOAT coordinates + \param Tension Controls splines, 0 is straight line, >0 is curved + \param Offset Element in Points that is the spline's starting point + \param NSegs Number of segments + \param Elements Number of members in Data array + \param Points Caller must free. Array of U_POINT_F = Sequence of points to connect. Coordinate type set by ctype and RelAbs. + + EMF+ manual 2.3.4.5, Microsoft name: EmfPlusDrawCurve Record, Index 0x18 +*/ +int U_PMR_DRAWCURVE_get(const char *contents, U_PMF_CMN_HDR *Header, + uint32_t *PenID, int *ctype, + U_FLOAT *Tension, uint32_t *Offset, uint32_t *NSegs, uint32_t *Elements, + U_PMF_POINTF **Points){ + if(!contents || !PenID || !ctype || !Tension || !Offset || !NSegs || !Elements || !Points){ return(0); } + + const char *blimit = contents; + U_PMF_CMN_HDR lclHeader; + U_PMF_CMN_HDR_get(&contents, &lclHeader); + if(lclHeader.Size < sizeof(U_PMF_DRAWCURVE))return(0); + if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); } + blimit += lclHeader.Size; + + *ctype = (lclHeader.Flags & U_PPF_C ? 1 : 0 ); + *PenID = (lclHeader.Flags >> U_FF_SHFT_OID8) & U_FF_MASK_OID8; + U_PMF_SERIAL_get(&contents, Tension, 4, 1, U_LE); + U_PMF_SERIAL_get(&contents, Offset, 4, 1, U_LE); + U_PMF_SERIAL_get(&contents, NSegs, 4, 1, U_LE); + U_PMF_SERIAL_get(&contents, Elements, 4, 1, U_LE); + U_PMF_VARPOINTS_get(contents, lclHeader.Flags, *Elements, Points, blimit); + return(1); +} + +/** + \brief Get data from a U_PMR_DRAWDRIVERSTRING record + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Header Common header + \param FontID U_PMF_FONT object in the EMF+ object table (0-63, inclusive) + \param btype Set: BrushID is an U_PFM_ARGB; Clear: index of U_PMF_BRUSH object in EMF+ object table. + \param BrushID Color or index of U_PMF_BRUSH object in the EMF+ object table, depends on Flags bit0 + \param DSOFlags DriverStringOptions flags + \param HasMatrix If 1 record contains a TransformMatrix field, if 0 it does not. + \param Elements Number of members in Glyphs and Positions array + \param Glyphs Caller must free. If U_DSO_CmapLookup is set in DSOFlags this is an array of UTF16LE characters, otherwise, it is an array of indices into the U_PMF_FONT object indexed by Object_ID in flags. + \param Points Caller must free. Coordinates of each member of Glyphs. U_DSO_RealizedAdvance set in DSOFlags Relative then positions are calculated relative to the first glyph which is stored in Positions, otherwise, all glyph positions are stored in Positions. + \param Matrix Caller must free. Transformation to apply to Glyphs & Positions. Present if HasMatrix is 1 + + EMF+ manual 2.3.4.6, Microsoft name: EmfPlusDrawDriverString Record, Index 0x36 +*/ +int U_PMR_DRAWDRIVERSTRING_get(const char *contents, U_PMF_CMN_HDR *Header, + uint32_t *FontID, int *btype, + uint32_t *BrushID, uint32_t *DSOFlags, uint32_t *HasMatrix, uint32_t *Elements, + uint16_t **Glyphs, U_PMF_POINTF **Points, U_PMF_TRANSFORMMATRIX **Matrix){ + if(!contents || !FontID || !btype || !BrushID || + !DSOFlags || !HasMatrix || !Elements || !Glyphs || !Points || !Matrix){ return(0); } + + const char *blimit = contents; + U_PMF_CMN_HDR lclHeader; + U_PMF_CMN_HDR_get(&contents, &lclHeader); + if(lclHeader.Size < sizeof(U_PMF_DRAWDRIVERSTRING))return(0); + if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); } + blimit += lclHeader.Size; + + *btype = (lclHeader.Flags & U_PPF_B ? 1 : 0 ); + *FontID = (lclHeader.Flags >> U_FF_SHFT_OID8) & U_FF_MASK_OID8; + U_PMF_SERIAL_get(&contents, BrushID, 4, 1, (*btype ? U_XE : U_LE)); /* color is not byte swapped, ID integer is */ + U_PMF_SERIAL_get(&contents, DSOFlags, 4, 1, U_LE); + U_PMF_SERIAL_get(&contents, HasMatrix, 4, 1, U_LE); + U_PMF_SERIAL_get(&contents, Elements, 4, 1, U_LE); + if(IS_MEM_UNSAFE(contents, *Elements*2 + *Elements*2*4 + 24, blimit))return(0); + if(!U_PMF_SERIAL_array_copy_get(&contents, (void **)Glyphs, 2, *Elements, U_LE, (*DSOFlags & U_DSO_CmapLookup))){ return(0); } + if(!U_PMF_SERIAL_array_copy_get(&contents, (void **)Points, 4, *Elements *2, U_LE, (*DSOFlags & U_DSO_RealizedAdvance))){ return(0); } + if(!U_PMF_SERIAL_array_copy_get(&contents, (void **)Matrix, 4, 6, U_LE, (*HasMatrix))){ return(0); } + return(1); +} + +/** + \brief Get data from a U_PMR_DRAWELLIPSE record + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Header Common header + \param PenID U_PMF_PEN object in the EMF+ object table (0-63, inclusive) + \param ctype Set: int16_t coordinates; Clear: U_FLOAT coordinates + \param Rect Caller must free. Bounding rectangle. Coordinate type set by ctype. + + EMF+ manual 2.3.4.7, Microsoft name: EmfPlusDrawEllipse Record, Index 0x0F +*/ +int U_PMR_DRAWELLIPSE_get(const char *contents, U_PMF_CMN_HDR *Header, + uint32_t *PenID, int *ctype, + U_PMF_RECTF *Rect){ + if(!contents || !PenID || !ctype || !Rect){ return(0); } + + U_PMF_CMN_HDR lclHeader; + U_PMF_CMN_HDR_get(&contents, &lclHeader); + if(lclHeader.Size < sizeof(U_PMF_DRAWELLIPSE))return(0); + if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); } + + *ctype = (lclHeader.Flags & U_PPF_C ? 1 : 0 ); + *PenID = (lclHeader.Flags >> U_FF_SHFT_OID8) & U_FF_MASK_OID8; + U_PMF_SERIAL_get(&contents, Rect, 4, 4, U_LE); + return(1); +} + +/** + \brief Get data from a U_PMR_DRAWIMAGE record + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Header Common header + \param ImgID U_PMF_IMAGE object in the EMF+ object table (0-63, inclusive) + \param ctype Set: int16_t coordinates; Clear: U_FLOAT coordinates + \param ImgAttrID index of a U_PMF_IMAGEATTRIBUTES object in the object table + \param SrcUnit UnitType enumeration + \param SrcRect Region of image + \param DstRect Destination rectangle for image. Coordinate type set by ctype. + + EMF+ manual 2.3.4.8, Microsoft name: EmfPlusDrawImage Record, Index 0x1A +*/ +int U_PMR_DRAWIMAGE_get(const char *contents, U_PMF_CMN_HDR *Header, + uint32_t *ImgID, int *ctype, + uint32_t *ImgAttrID, int32_t *SrcUnit, U_PMF_RECTF *SrcRect, + U_PMF_RECTF *DstRect){ + if(!contents || !ImgID || !ctype || !ImgAttrID || !SrcUnit || !SrcRect || !DstRect){ return(0); } + + U_PMF_CMN_HDR lclHeader; + U_PMF_CMN_HDR_get(&contents, &lclHeader); + if(lclHeader.Size < sizeof(U_PMF_DRAWIMAGE))return(0); + if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); } + + *ctype = (lclHeader.Flags & U_PPF_C ? 1 : 0 ); + *ImgID = (lclHeader.Flags >> U_FF_SHFT_OID8) & U_FF_MASK_OID8; + U_PMF_SERIAL_get(&contents, ImgAttrID, 4, 1, U_LE); + U_PMF_SERIAL_get(&contents, SrcUnit, 4, 1, U_LE); + U_PMF_SERIAL_get(&contents, SrcRect, 4, 4, U_LE); + U_PMF_SERIAL_get(&contents, DstRect, 4, 4, U_LE); + return(1); +} + +/** + \brief Get data from a U_PMR_DRAWIMAGEPOINTS record + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Header Common header + \param ImgID U_PMF_IMAGE object in the EMF+ object table (0-63, inclusive) + \param ctype Set: int16_t coordinates; Clear: U_FLOAT coordinates + \param etype Set: effect from previous U_PMR_SERIALIZABLEOBJECT record will be applied; Clear: no effect applied + \param RelAbs Set: Data is relative, Clear: if it is absolute + \param ImgAttrID EmfPlusImageAttributes object + \param SrcUnit UnitType enumeration + \param SrcRect Region of image + \param Elements Number of members in Points, must be 3 + \param Points Caller must free. 3 points of a parallelogram.. Coordinate type set by ctype and RelAbs. + + EMF+ manual 2.3.4.9, Microsoft name: EmfPlusDrawImagePoints Record, Index 0x1B +*/ +int U_PMR_DRAWIMAGEPOINTS_get(const char *contents, U_PMF_CMN_HDR *Header, + uint32_t *ImgID, int *ctype, int *etype, int *RelAbs, + uint32_t *ImgAttrID, int32_t *SrcUnit, U_PMF_RECTF *SrcRect, uint32_t *Elements, + U_PMF_POINTF **Points){ + if(!contents || !ImgID || !ctype || !etype || !RelAbs || !ImgAttrID || !SrcUnit || !Elements || !Points){ return(0); } + + const char *blimit = contents; + U_PMF_CMN_HDR lclHeader; + U_PMF_CMN_HDR_get(&contents, &lclHeader); + if(lclHeader.Size < sizeof(U_PMF_DRAWIMAGEPOINTS))return(0); + if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); } + blimit += lclHeader.Size; + + *ctype = (lclHeader.Flags & U_PPF_C ? 1 : 0 ); + *etype = (lclHeader.Flags & U_PPF_E ? 1 : 0 ); + *RelAbs = (lclHeader.Flags & U_PPF_P ? 1 : 0 ); + *ImgID = (lclHeader.Flags >> U_FF_SHFT_OID8) & U_FF_MASK_OID8; + U_PMF_SERIAL_get(&contents, ImgAttrID, 4, 1, U_LE); + U_PMF_SERIAL_get(&contents, SrcUnit, 4, 1, U_LE); + U_PMF_SERIAL_get(&contents, SrcRect, 4, 4, U_LE); + U_PMF_SERIAL_get(&contents, Elements, 4, 1, U_LE); + U_PMF_VARPOINTS_get(contents, lclHeader.Flags, *Elements, Points, blimit); + return(1); +} + +/** + \brief Get data from a U_PMR_DRAWLINES record + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Header Common header + \param PenID U_PMF_PEN object in the EMF+ object table (0-63, inclusive) + \param ctype Set: int16_t coordinates; Clear: U_FLOAT coordinates + \param dtype Set: path must be closed, Clear: path is open + \param RelAbs Set: Coordinates are relative; Clear: Coordinates are absolute and their type is set by ctype + \param Elements Number of members in Points + \param Points Caller must free. Array of U_POINT_F = Sequence of points to connect. Coordinate type set by ctype and RelAbs. + + EMF+ manual 2.3.4.10, Microsoft name: EmfPlusDrawLines Record, Index 0x0D +*/ +int U_PMR_DRAWLINES_get(const char *contents, U_PMF_CMN_HDR *Header, + uint32_t *PenID, int *ctype, int *dtype, int *RelAbs, + uint32_t *Elements, + U_PMF_POINTF **Points){ + if(!contents || !PenID || !ctype || !dtype || !RelAbs || !Elements || !Points){ return(0); } + + const char *blimit = contents; + U_PMF_CMN_HDR lclHeader; + U_PMF_CMN_HDR_get(&contents, &lclHeader); + if(lclHeader.Size < sizeof(U_PMF_DRAWLINES))return(0); + if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); } + blimit += lclHeader.Size; + + *ctype = (lclHeader.Flags & U_PPF_C ? 1 : 0 ); + *dtype = (lclHeader.Flags & U_PPF_D ? 1 : 0 ); + *RelAbs = (lclHeader.Flags & U_PPF_P ? 1 : 0 ); + *PenID = (lclHeader.Flags >> U_FF_SHFT_OID8) & U_FF_MASK_OID8; + U_PMF_SERIAL_get(&contents, Elements, 4, 1, U_LE); + U_PMF_VARPOINTS_get(contents, lclHeader.Flags, *Elements, Points, blimit); + return(1); +} + +/** + \brief Get data from a U_PMR_DRAWPATH record + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Header Common header + \param PathID U_PMF_PATH object in the EMF+ object table (0-63, inclusive) + \param PenID U_PMF_PEN object in the EMF+ object table (0-63, inclusive) + + EMF+ manual 2.3.4.11, Microsoft name: EmfPlusDrawPath Record, Index 0x15 +*/ +int U_PMR_DRAWPATH_get(const char *contents, U_PMF_CMN_HDR *Header, + uint32_t *PathID, uint32_t *PenID){ + if(!contents || !PathID || !PenID){ return(0); } + + U_PMF_CMN_HDR lclHeader; + U_PMF_CMN_HDR_get(&contents, &lclHeader); + if(lclHeader.Size < sizeof(U_PMF_DRAWPATH))return(0); + if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); } + + *PathID = (lclHeader.Flags >> U_FF_SHFT_OID8) & U_FF_MASK_OID8; + U_PMF_SERIAL_get(&contents, PenID, 4, 1, U_LE); + return(1); +} + +/** + \brief Get data from a U_PMR_DRAWPIE record + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Header Common header + \param PenID U_PMF_PEN object in the EMF+ object table (0-63, inclusive) + \param ctype Set: int16_t coordinates; Clear: U_FLOAT coordinates + \param Start Start angle, >=0.0, degrees clockwise from 3:00 + \param Sweep Sweep angle, -360<= angle <=360, degrees clockwise from Start + \param Rect Caller must free. Bounding rectangle. Coordinate type set by ctype. + + EMF+ manual 2.3.4.12, Microsoft name: EmfPlusDrawPie Record, Index 0x0D +*/ +int U_PMR_DRAWPIE_get(const char *contents, U_PMF_CMN_HDR *Header, + uint32_t *PenID, int *ctype, + U_FLOAT *Start, U_FLOAT *Sweep, + U_PMF_RECTF *Rect){ + if(!contents || !PenID || !ctype || !Start || !Sweep || !Rect){ return(0); } + + const char *blimit = contents; + U_PMF_CMN_HDR lclHeader; + U_PMF_CMN_HDR_get(&contents, &lclHeader); + if(lclHeader.Size < sizeof(U_PMF_DRAWPIE))return(0); + if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); } + blimit += lclHeader.Size; + + *ctype = (lclHeader.Flags & U_PPF_C ? 1 : 0 ); + *PenID = (lclHeader.Flags >> U_FF_SHFT_OID8) & U_FF_MASK_OID8; + U_PMF_SERIAL_get(&contents, Start, 4, 1, U_LE); + U_PMF_SERIAL_get(&contents, Sweep, 4, 1, U_LE); + U_PMF_RECTF *Rects = NULL; + if(!U_PMF_VARRECTS_get(&contents, lclHeader.Flags, 1, &Rects, blimit))return(0); + memcpy(Rect,Rects,sizeof(U_PMF_RECTF)); + free(Rects); + return(1); +} + +/** + \brief Get data from a U_PMR_DRAWRECTS record + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Header Common header + \param PenID U_PMF_PEN object in the EMF+ object table (0-63, inclusive) + \param ctype Set: int16_t coordinates; Clear: U_FLOAT coordinates + \param Elements Number of members in Rects + \param Rects Caller must free. Array of U_PMF_RECTF rectangles to draw. + + EMF+ manual 2.3.4.13, Microsoft name: EmfPlusDrawRects Record, Index 0x0B + + Rects in record may be either U_PMF_RECT or U_PMF_RECTF, but this function always + returns U_PMF_RECTF +*/ +int U_PMR_DRAWRECTS_get(const char *contents, U_PMF_CMN_HDR *Header, + uint32_t *PenID, int *ctype, + uint32_t *Elements, + U_PMF_RECTF **Rects){ + if(!contents || !PenID || !Elements || !Rects){ return(0); } + + const char *blimit = contents; + U_PMF_CMN_HDR lclHeader; + U_PMF_CMN_HDR_get(&contents, &lclHeader); + if(lclHeader.Size < sizeof(U_PMF_DRAWPIE))return(0); + if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); } + blimit += lclHeader.Size; + + *PenID = (lclHeader.Flags >> U_FF_SHFT_OID8) & U_FF_MASK_OID8; + *ctype = (lclHeader.Flags & U_PPF_C ? 1 : 0 ); + U_PMF_SERIAL_get(&contents, Elements, 4, 1, U_LE); + U_PMF_VARRECTS_get(&contents, lclHeader.Flags, *Elements, Rects, blimit); + return(1); +} + +/** + \brief Get data from a U_PMR_DRAWSTRING record + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Header Common header + \param FontID U_PMF_FONT object in the EMF+ object table (0-63, inclusive) + \param btype Set: BrushID is an U_PFM_ARGB; Clear: index of U_PMF_BRUSH object in EMF+ object table. + \param BrushID Color or index of U_PMF_BRUSH object in the EMF+ object table, depending on btype. + \param FormatID U_PMF_STRINGFORMAT object in EMF+ Object Table. + \param Elements Number of characters in the string. + \param Rect String's bounding box. + \param String Caller must free. Array of UFT-16LE unicode characters. + + EMF+ manual 2.3.4.14, Microsoft name: EmfPlusDrawString Record, Index 0x1C +*/ +int U_PMR_DRAWSTRING_get(const char *contents, U_PMF_CMN_HDR *Header, + uint32_t *FontID, int *btype, + uint32_t *BrushID, uint32_t *FormatID, uint32_t *Elements, U_PMF_RECTF *Rect, + uint16_t **String){ + if(!contents || !FontID || !btype || !BrushID || !FormatID || !Elements || !String){ return(0); } + + const char *blimit = contents; + U_PMF_CMN_HDR lclHeader; + U_PMF_CMN_HDR_get(&contents, &lclHeader); + if(lclHeader.Size < sizeof(U_PMF_DRAWPIE))return(0); + if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); } + blimit += lclHeader.Size; + + *btype = (lclHeader.Flags & U_PPF_B ? 1 : 0 ); + *FontID = (lclHeader.Flags >> U_FF_SHFT_OID8) & U_FF_MASK_OID8; + U_PMF_SERIAL_get(&contents, BrushID, 4, 1, (*btype ? U_XE : U_LE)); /* color is not byte swapped, ID integer is */ + U_PMF_SERIAL_get(&contents, FormatID, 4, 1, U_LE); + U_PMF_SERIAL_get(&contents, Elements, 4, 1, U_LE); + U_PMF_SERIAL_get(&contents, Rect, 4, 4, U_LE); + if(IS_MEM_UNSAFE(contents, *Elements * 2, blimit))return(0); + if(!U_PMF_SERIAL_array_copy_get(&contents, (void **)String, 2, *Elements, U_XE, 1)){ return(0); } + return(1); +} + +/** + \brief Get data from a U_PMR_FILLCLOSEDCURVE record + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Header Common header + \param btype Set: BrushID is an U_PFM_ARGB; Clear: is index of U_PMF_BRUSH object in EMF+ object table. + \param ctype Set: int16_t coordinates; Clear: U_FLOAT coordinates + \param ftype Set: winding fill; Clear: alternate fill + \param RelAbs Set: Coordinates are relative; Clear: Coordinates are absolute and their type is set by ctype + \param BrushID Color or index of U_PMF_BRUSH object in the EMF+ object table, depending on btype. + \param Tension Controls splines, 0 is straight line, >0 is curved + \param Elements Number of members in Points + \param Points Caller must free. Array of U_POINT_F = Sequence of points to connect. Coordinate type set by ctype and RelAbs. + + EMF+ manual 2.3.4.15, Microsoft name: EmfPlusFillClosedCurve Record, Index 0x16 +*/ +int U_PMR_FILLCLOSEDCURVE_get(const char *contents, U_PMF_CMN_HDR *Header, + int *btype, int *ctype, int *ftype, int *RelAbs, + uint32_t *BrushID, U_FLOAT *Tension, uint32_t *Elements, + U_PMF_POINTF **Points){ + if(!contents || !btype || !ctype || !ftype || !RelAbs || !BrushID || !Tension || !Elements || !Points){ return(0); } + + const char *blimit = contents; + U_PMF_CMN_HDR lclHeader; + U_PMF_CMN_HDR_get(&contents, &lclHeader); + if(lclHeader.Size < sizeof(U_PMF_DRAWLINES))return(0); + if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); } + blimit += lclHeader.Size; + + *btype = (lclHeader.Flags & U_PPF_B ? 1 : 0 ); + *ctype = (lclHeader.Flags & U_PPF_C ? 1 : 0 ); + *ftype = (lclHeader.Flags & U_PPF_F ? 1 : 0 ); + *RelAbs = (lclHeader.Flags & U_PPF_P ? 1 : 0 ); + U_PMF_SERIAL_get(&contents, BrushID, 4, 1, (*btype ? U_XE : U_LE)); /* color is not byte swapped, ID integer is */ + U_PMF_SERIAL_get(&contents, Tension, 4, 1, U_LE); + U_PMF_SERIAL_get(&contents, Elements, 4, 1, U_LE); + U_PMF_VARPOINTS_get(contents, lclHeader.Flags, *Elements, Points, blimit); + return(1); +} + +/** + \brief Get data from a U_PMR_FILLELLIPSE record + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Header Common header + \param btype Set: BrushID is an U_PFM_ARGB; Clear: is index of U_PMF_BRUSH object in EMF+ object table. + \param ctype Set: int16_t coordinates; Clear: U_FLOAT coordinates + \param BrushID Color or index of U_PMF_BRUSH object in the EMF+ object table, depending on btype. + \param Rect Caller must free. Bounding box for elliptical pie segment being drawn. Coordinate type set by ctype. + + EMF+ manual 2.3.4.16, Microsoft name: EmfPlusFillEllipse Record, Index 0x0E +*/ +int U_PMR_FILLELLIPSE_get(const char *contents, U_PMF_CMN_HDR *Header, + int *btype, int *ctype, + uint32_t *BrushID, + U_PMF_RECTF *Rect){ + if(!contents || !btype || !ctype || !BrushID || !Rect){ return(0); } + + U_PMF_CMN_HDR lclHeader; + U_PMF_CMN_HDR_get(&contents, &lclHeader); + if(lclHeader.Size < sizeof(U_PMF_FILLELLIPSE))return(0); + if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); } + + *btype = (lclHeader.Flags & U_PPF_B ? 1 : 0 ); + *ctype = (lclHeader.Flags & U_PPF_C ? 1 : 0 ); + U_PMF_SERIAL_get(&contents, BrushID, 4, 1, (*btype ? U_XE : U_LE)); /* color is not byte swapped, ID integer is */ + U_PMF_SERIAL_get(&contents, Rect, 4, 4, U_LE); + return(1); +} + +/** + \brief Get data from a U_PMR_FILLPATH record + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Header Common header + \param btype Set: BrushID is an U_PFM_ARGB; Clear: is index of U_PMF_BRUSH object in EMF+ object table. + \param PathID U_PMF_PATH object in the EMF+ object table (0-63, inclusive) + \param BrushID Color or index of U_PMF_BRUSH object in the EMF+ object table, depending on btype. + + EMF+ manual 2.3.4.17, Microsoft name: EmfPlusFillPath Record, Index 0x14 + + Note: U_PMF_FILLPATHOBJ is the object, U_PMF_FILLPATH is the file record +*/ +int U_PMR_FILLPATH_get(const char *contents, U_PMF_CMN_HDR *Header, + uint32_t *PathID, int *btype, + uint32_t *BrushID){ + if(!contents || !PathID || !btype || !BrushID){ return(0); } + + U_PMF_CMN_HDR lclHeader; + U_PMF_CMN_HDR_get(&contents, &lclHeader); + if(lclHeader.Size < sizeof(U_PMF_FILLPATH))return(0); + if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); } + + *btype = (lclHeader.Flags & U_PPF_B ? 1 : 0 ); + *PathID = (lclHeader.Flags >> U_FF_SHFT_OID8) & U_FF_MASK_OID8; + U_PMF_SERIAL_get(&contents, BrushID, 4, 1, (*btype ? U_XE : U_LE)); /* color is not byte swapped, ID integer is */ + return(1); +} + +/** + \brief Get data from a U_PMR_FILLPIE record + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Header Common header + \param btype Set: BrushID is an U_PFM_ARGB; Clear: is index of U_PMF_BRUSH object in EMF+ object table. + \param ctype Set: int16_t coordinates; Clear: U_FLOAT coordinates + \param BrushID Color or index of U_PMF_BRUSH object in the EMF+ object table, depending on btype. + \param Start Start angle, >=0.0, degrees clockwise from 3:00 + \param Sweep Sweep angle, -360<= angle <=360, degrees clockwise from Start + \param Rect Bounding box for elliptical pie segment being filled. Coordinate type set by ctype. + + EMF+ manual 2.3.4.18, Microsoft name: EmfPlusFillPie Record, Index 0x10 +*/ +int U_PMR_FILLPIE_get(const char *contents, U_PMF_CMN_HDR *Header, + int *btype, int *ctype, + uint32_t *BrushID, U_FLOAT *Start, U_FLOAT *Sweep, + U_PMF_RECTF *Rect){ + if(!contents || !btype || !ctype || !BrushID || !Start || !Sweep || !Rect){ return(0); } + + const char *blimit = contents; + U_PMF_CMN_HDR lclHeader; + U_PMF_CMN_HDR_get(&contents, &lclHeader); + if(lclHeader.Size < sizeof(U_PMF_FILLPIE))return(0); + if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); } + blimit += lclHeader.Size; + + *btype = (lclHeader.Flags & U_PPF_B ? 1 : 0 ); + *ctype = (lclHeader.Flags & U_PPF_C ? 1 : 0 ); + U_PMF_SERIAL_get(&contents, BrushID, 4, 1, (*btype ? U_XE : U_LE)); /* color is not byte swapped, ID integer is */ + U_PMF_SERIAL_get(&contents, Start, 4, 1, U_LE); + U_PMF_SERIAL_get(&contents, Sweep, 4, 1, U_LE); + U_PMF_RECTF *Rects = NULL; + if(!U_PMF_VARRECTS_get(&contents, lclHeader.Flags, 1, &Rects, blimit))return(0); + memcpy(Rect,Rects,sizeof(U_PMF_RECTF)); + free(Rects); + return(1); +} + +/** + \brief Get data from a U_PMR_FILLPOLYGON record + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Header Common header + \param btype Set: BrushID is an U_PFM_ARGB; Clear: is index of U_PMF_BRUSH object in EMF+ object table. + \param ctype Set: int16_t coordinates; Clear: U_FLOAT coordinates + \param RelAbs Set: U_PMF_PathPointTypeRLE and/or U_PMF_PathPointType objects; Clear: only U_PMF_PathPointType + \param BrushID Color or index of U_PMF_BRUSH object in the EMF+ object table, depending on btype. + \param Elements Number of members in Data. + \param Points Sequence of points to connect with line segments. Coordinate type set by ctype and RelAbs. + + EMF+ manual 2.3.4.19, Microsoft name: EmfPlusFillPolygon Record, Index 0x0C +*/ +int U_PMR_FILLPOLYGON_get(const char *contents, U_PMF_CMN_HDR *Header, + int *btype, int *ctype, int *RelAbs, + uint32_t *BrushID, uint32_t *Elements, + U_PMF_POINTF **Points){ + if(!contents || !btype || !ctype || !RelAbs || !BrushID || !Elements || !Points){ return(0); } + + const char *blimit = contents; + U_PMF_CMN_HDR lclHeader; + U_PMF_CMN_HDR_get(&contents, &lclHeader); + if(lclHeader.Size < sizeof(U_PMF_DRAWLINES))return(0); + if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); } + blimit += lclHeader.Size; + + *btype = (lclHeader.Flags & U_PPF_B ? 1 : 0 ); + *ctype = (lclHeader.Flags & U_PPF_C ? 1 : 0 ); + *RelAbs = (lclHeader.Flags & U_PPF_R ? 1 : 0 ); + U_PMF_SERIAL_get(&contents, BrushID, 4, 1, (*btype ? U_XE : U_LE)); /* color is not byte swapped, ID integer is */ + U_PMF_SERIAL_get(&contents, Elements, 4, 1, U_LE); + U_PMF_VARPOINTS_get(contents, lclHeader.Flags, *Elements, Points, blimit); + return(1); +} + +/** + \brief Get data from a U_PMR_FILLRECTS record + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Header Common header + \param btype Set: BrushID is an U_PFM_ARGB; Clear: is index of U_PMF_BRUSH object in EMF+ object table. + \param ctype Set: int16_t coordinates; Clear: U_FLOAT coordinates + \param BrushID Color or index of U_PMF_BRUSH object in the EMF+ object table, depending on btype. + \param Elements Number of members in Data. + \param Rects Caller must free. Array of U_PMF_RECTF rectangles to draw. + + EMF+ manual 2.3.4.20, Microsoft name: EmfPlusFillRects Record, Index 0x0A + + EMF+ files have been encountered where BrushID must be a color, because it has a value like FFFF0000 but + the flags are set wrong, so that U_PPF_B is not set. Detect these by BrushID >63 for btype=0 and correct. + If the opposite problem occurs it cannot be reliably detected, so it cannot be corrected. + + Rects in record may be either U_PMF_RECT or U_PMF_RECTF, but this function always + returns U_PMF_RECTF +*/ +int U_PMR_FILLRECTS_get(const char *contents, U_PMF_CMN_HDR *Header, + int *btype, int *ctype, + uint32_t *BrushID, uint32_t *Elements, + U_PMF_RECTF **Rects){ + if(!contents || !btype || !ctype || !BrushID || !Elements || !Rects){ return(0); } + + const char *blimit = contents; + U_PMF_CMN_HDR lclHeader; + U_PMF_CMN_HDR_get(&contents, &lclHeader); + if(lclHeader.Size < sizeof(U_PMF_FILLRECTS))return(0); + if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); } + blimit += lclHeader.Size; + + *btype = (lclHeader.Flags & U_PPF_B ? 1 : 0 ); + *ctype = (lclHeader.Flags & U_PPF_C ? 1 : 0 ); + U_PMF_SERIAL_get(&contents, BrushID, 4, 1, (*btype ? U_XE : U_LE)); /* color is not byte swapped, ID integer is */ + U_PMF_SERIAL_get(&contents, Elements, 4, 1, U_LE); + U_PMF_VARRECTS_get(&contents, lclHeader.Flags, *Elements, Rects, blimit); + /* correct btype, if necessary, for invalid EMF+ input */ + if((*BrushID > 63) & !*btype)*btype=1; + return(1); +} + + +/** + \brief Get data from a U_PMR_FILLREGION record + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Header Common header + \param RgnID U_PMF_REGION object in the EMF+ object table (0-63, inclusive) + \param btype Set: BrushID is an U_PFM_ARGB; Clear: is index of U_PMF_BRUSH object in EMF+ object table. + \param ctype Set: int16_t coordinates; Clear: U_FLOAT coordinates + \param BrushID Color or index of U_PMF_BRUSH object in the EMF+ object table, depending on btype. + + EMF+ manual 2.3.4.21, Microsoft name: EmfPlusFillRegion Record, Index 0x13 +*/ +int U_PMR_FILLREGION_get(const char *contents, U_PMF_CMN_HDR *Header, + uint32_t *RgnID, int *btype, int *ctype, + uint32_t *BrushID){ + if(!contents || !RgnID || !btype || !ctype || !BrushID){ return(0); } + + U_PMF_CMN_HDR lclHeader; + U_PMF_CMN_HDR_get(&contents, &lclHeader); + if(lclHeader.Size < sizeof(U_PMF_FILLREGION))return(0); + if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); } + + *btype = (lclHeader.Flags & U_PPF_B ? 1 : 0 ); + *ctype = (lclHeader.Flags & U_PPF_C ? 1 : 0 ); + *RgnID = (lclHeader.Flags >> U_FF_SHFT_OID8) & U_FF_MASK_OID8; + U_PMF_SERIAL_get(&contents, BrushID, 4, 1, (*btype ? U_XE : U_LE)); /* color is not byte swapped, ID integer is */ + return(1); +} + +/** + \brief Get data from a U_PMR_OBJECT record + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Header Common header + \param ObjID Index for this object in the EMF+ object table (0-63, inclusive) + \param otype ObjectType enumeration + \param ntype Set: object definition continue bit is set + \param TSize If ntype is set, holds the total number of data bytes split across multiple records. If ntype is clear, has no meaning. + \param Data Object's data. Type from otype. + + EMF+ manual 2.3.5.1, Microsoft name: EmfPlusObject Record, Index 0x13 + + Caller must check Data for possible memory access violations. + + OTHER NOTES: + All objects are to be stored in the same table and retrieved by index. + Documentation indicates that this table contains only 64 slots, although the index + field which references it can code for values 0-127. + If a new object has the same index as an existing object the old one is deleted and + the new one goes into its storage slot. + The continuation bit (U_PPF_N) is documented as indicating that the object is continued into + the next record. Examination of emf+ records in emf files produced by PowerPoint 2003 + show that changing the ObjID also serves as a continued record terminator, and that it apparently + overrides the value for the continue bit. That is, even though the preceding records said + that it was continued, the change of ObjID terminates that preceding record without adding + any more data to it. In one example the sequential emf+ records were: + ObjID type size continue + 0 5 65008 Y + 0 5 65008 Y + 0 5 63104 Y + 1 8 24 N + A DrawImagePoints record followed that referenced ObjID 0. + Examination of the records with continue set showed that data in each + was preceded by a uint32_t size value equivalent to the size of the + data that had been split across multiple records, in this case + 0x0002F254 = 193108. It is not clear at present if this size value + will also be present at the end of a continued series that terminates + by not using the continue bit, rather than changing the ObjID. +*/ +int U_PMR_OBJECT_get(const char *contents, U_PMF_CMN_HDR *Header, + uint32_t *ObjID, int *otype, int *ntype, uint32_t *TSize, + const char **Data){ + if(!contents || !ObjID || !otype || !ntype || !Data){ return(0); } + + U_PMF_CMN_HDR lclHeader; + U_PMF_CMN_HDR_get(&contents, &lclHeader); + if(lclHeader.Size < sizeof(U_PMF_OBJECT))return(0); + if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); } + + *ntype = (lclHeader.Flags & U_PPF_N ? 1 : 0 ); + *ObjID = (lclHeader.Flags >> U_FF_SHFT_OID8) & U_FF_MASK_OID8; + *otype = (lclHeader.Flags >> U_FF_SHFT_OT) & U_FF_MASK_OT; + if(*ntype){ U_PMF_SERIAL_get(&contents, TSize, 4, 1, U_LE); } + else { *TSize = 0; } + U_PMF_PTRSAV_SHIFT(Data, &contents, 0); + return(1); +} + +/** + \brief Get data from a U_PMR_SERIALIZABLEOBJECT record + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Header Common header + \param GUID ImageEffects identifier. + \param Size Bytes in Data. + \param Data "Serialized image effects parameter block". One of the ImageEffects objects. + + EMF+ manual 2.3.5.2, Microsoft name: EmfPlusSerializableObject Record, Index 0x38 + + Caller must check Data for possible memory access violations. +*/ +int U_PMR_SERIALIZABLEOBJECT_get(const char *contents, U_PMF_CMN_HDR *Header, + uint8_t *GUID, uint32_t *Size, + const char **Data){ + if(!contents || !GUID || !Size || !Data){ return(0); } + + U_PMF_CMN_HDR lclHeader; + U_PMF_CMN_HDR_get(&contents, &lclHeader); + if(lclHeader.Size < sizeof(U_PMF_SERIALIZABLEOBJECT))return(0); + if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); } + + U_PMF_SERIAL_get(&contents, GUID, 1, 16, U_XE); + U_PMF_SERIAL_get(&contents, Size, 4, 1, U_LE); + U_PMF_PTRSAV_SHIFT(Data, &contents, 0); + return(1); +} + +/** + \brief Get data from a U_PMR_SETANTIALIASMODE record + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Header Common header + \param SMenum SmoothingMode enumeration + \param aatype Set: anti-aliasing on; Clear: anti-aliasing off + + EMF+ manual 2.3.6.1, Microsoft name: EmfPlusSetAntiAliasMode Record, Index 0x1E +*/ +int U_PMR_SETANTIALIASMODE_get(const char *contents, U_PMF_CMN_HDR *Header, + int *SMenum, int *aatype){ + if(!contents || !SMenum || !aatype){ return(0); } + + U_PMF_CMN_HDR lclHeader; + U_PMF_CMN_HDR_get(&contents, &lclHeader); + if(lclHeader.Size < sizeof(U_PMF_SETANTIALIASMODE))return(0); + if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); } + + *aatype = (lclHeader.Flags & U_PPF_AA ? 1 : 0 ); + *SMenum = (lclHeader.Flags >> U_FF_SHFT_AA) & U_FF_MASK_AA; + return(1); +} + +/** + \brief Get data from a U_PMR_SETCOMPOSITINGMODE record + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Header Common header + \param CMenum CompositingMode enumeration + + EMF+ manual 2.3.6.2, Microsoft name: EmfPlusSetCompositingMode Record, Index 0x23 +*/ +int U_PMR_SETCOMPOSITINGMODE_get(const char *contents, U_PMF_CMN_HDR *Header, + int *CMenum){ + /* memory access safe, only uses the common header */ + if(!contents || !CMenum){ return(0); } + uint16_t Flags = U_PMF_HEADERFLAGS_get(contents); + *CMenum = (Flags >> U_FF_SHFT_CM) & U_FF_MASK_CM; + U_PMF_CMN_HDR_get(&contents, Header); + return(1); +} + +/** + \brief Get data from a U_PMR_SETCOMPOSITINGQUALITY record + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Header Common header + \param CQenum CompositingQuality enumeration + + EMF+ manual 2.3.6.3, Microsoft name: EmfPlusSetCompositingQuality Record, Index 0x24 +*/ +int U_PMR_SETCOMPOSITINGQUALITY_get(const char *contents, U_PMF_CMN_HDR *Header, + int *CQenum){ + /* memory access safe, only uses the common header */ + if(!contents || !CQenum){ return(0); } + uint16_t Flags = U_PMF_HEADERFLAGS_get(contents); + *CQenum = (Flags >> U_FF_SHFT_CQ) & U_FF_MASK_CQ; + U_PMF_CMN_HDR_get(&contents, Header); + return(1); +} + +/** + \brief Get data from a U_PMR_SETINTERPOLATIONMODE record + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Header Common header + \param IMenum InterpolationMode enumeration + + EMF+ manual 2.3.6.4, Microsoft name: EmfPlusSetInterpolationMode Record, Index 0x21 +*/ +int U_PMR_SETINTERPOLATIONMODE_get(const char *contents, U_PMF_CMN_HDR *Header, + int *IMenum){ + /* memory access safe, only uses the common header */ + if(!contents || !IMenum){ return(0); } + uint16_t Flags = U_PMF_HEADERFLAGS_get(contents); + *IMenum = (Flags >> U_FF_SHFT_IM) & U_FF_MASK_IM; + U_PMF_CMN_HDR_get(&contents, Header); + return(1); +} + +/** + \brief Get data from a U_PMR_SETPIXELOFFSETMODE record + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Header Common header + \param POMenum PixelOffsetMode enumeration. + + EMF+ manual 2.3.6.5, Microsoft name: EmfPlusSetPixelOffsetMode Record, Index 0x22 +*/ +int U_PMR_SETPIXELOFFSETMODE_get(const char *contents, U_PMF_CMN_HDR *Header, + int *POMenum){ + /* memory access safe, only uses the common header */ + if(!contents || !POMenum){ return(0); } + uint16_t Flags = U_PMF_HEADERFLAGS_get(contents); + *POMenum = (Flags >> U_FF_SHFT_PxOffM) & U_FF_MASK_PxOffM; + U_PMF_CMN_HDR_get(&contents, Header); + return(1); +} + +/** + \brief Get data from a U_PMR_SETRENDERINGORIGIN record + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Header Common header. + \param X X coordinate of rendering origin. + \param Y Y coordinate of rendering origin. + + EMF+ manual 2.3.6.6, Microsoft name: EmfPlusSetRenderingOrigin Record, Index 0x1D +*/ +int U_PMR_SETRENDERINGORIGIN_get(const char *contents, U_PMF_CMN_HDR *Header, + int32_t *X, int32_t *Y){ + if(!contents || !X || !Y){ return(0); } + + U_PMF_CMN_HDR lclHeader; + if(!U_PMF_CMN_HDR_get(&contents, &lclHeader))return(0); + if(lclHeader.Size < sizeof(U_PMF_SETRENDERINGORIGIN))return(0); + if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); } + + U_PMF_SERIAL_get(&contents, X, 4, 1, U_LE); + U_PMF_SERIAL_get(&contents, Y, 4, 1, U_LE); + return(1); +} + +/** + \brief Get data from a U_PMR_SETTEXTCONTRAST record + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Header Common header. + \param TGC Text Gamma correction value (x 1000). + + EMF+ manual 2.3.6.7, Microsoft name: EmfPlusSetTextContrast Record, Index 0x20 +*/ +int U_PMR_SETTEXTCONTRAST_get(const char *contents, U_PMF_CMN_HDR *Header, + int *TGC){ + /* memory access safe, only uses the common header */ + if(!contents || !TGC){ return(0); } + uint16_t Flags = U_PMF_HEADERFLAGS_get(contents); + *TGC = (Flags >> U_FF_SHFT_TGC) & U_FF_MASK_TGC; + U_PMF_CMN_HDR_get(&contents, Header); + return(1); +} + +/** + \brief Get data from a U_PMR_SETTEXTRENDERINGHINT record + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Header Common header. + \param TRHenum TextRenderingHint enumeration + + EMF+ manual 2.3.6.8, Microsoft name: EmfPlusSetTextRenderingHint Record, Index 0x1F +*/ +int U_PMR_SETTEXTRENDERINGHINT_get(const char *contents, U_PMF_CMN_HDR *Header, + int *TRHenum){ + /* memory access safe, only uses the common header */ + if(!contents || !TRHenum){ return(0); } + uint16_t Flags = U_PMF_HEADERFLAGS_get(contents); + *TRHenum = (Flags >> U_FF_SHFT_TRH) & U_FF_MASK_TRH; + U_PMF_CMN_HDR_get(&contents, Header); + return(1); +} + +/** + \brief Get data from a U_PMR_BEGINCONTAINER record + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Header Common header + \param UTenum UnitType enumeration + \param DstRect with SrcRect specifies a transformation + \param SrcRect with DstRect specifies a transformation + \param StackID EMF+ Object Stack Index to use for this graphics container + + EMF+ manual 2.3.7.1, Microsoft name: EmfPlusBeginContainer Record, Index 0x27 +*/ +int U_PMR_BEGINCONTAINER_get(const char *contents, U_PMF_CMN_HDR *Header, + int *UTenum, + U_PMF_RECTF *DstRect, U_PMF_RECTF *SrcRect, uint32_t *StackID){ + if(!contents || !UTenum || !DstRect || !SrcRect || !StackID){ return(0); } + + U_PMF_CMN_HDR lclHeader; + U_PMF_CMN_HDR_get(&contents, &lclHeader); + if(lclHeader.Size < sizeof(U_PMF_SETCLIPREGION))return(0); + if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); } + + *UTenum = (lclHeader.Flags >> U_FF_SHFT_UT) & U_FF_MASK_UT; + U_PMF_SERIAL_get(&contents, DstRect, 4, 4, U_LE); + U_PMF_SERIAL_get(&contents, SrcRect, 4, 4, U_LE); + U_PMF_SERIAL_get(&contents, StackID, 4, 1, U_LE); + return(1); +} + +/** + \brief Get data from a U_PMR_BEGINCONTAINERNOPARAMS record + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Header Common header + \param StackID EMF+ Object Stack Index to use for this graphics container + + EMF+ manual 2.3.7.2, Microsoft name: EmfPlusBeginContainerNoParams Record, Index 0x28 +*/ +int U_PMR_BEGINCONTAINERNOPARAMS_get(const char *contents, U_PMF_CMN_HDR *Header, uint32_t *StackID){ + return(U_PMR_common_stack_get(contents, Header, StackID)); +} + +/** + \brief Get data from a U_PMR_ENDCONTAINER record + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Header Common header + \param StackID EMF+ Object Stack Index of this graphics container + + EMF+ manual 2.3.7.3, Microsoft name: EmfPlusEndContainer Record, Index 0x29 +*/ +int U_PMR_ENDCONTAINER_get(const char *contents, U_PMF_CMN_HDR *Header, uint32_t *StackID){ + return(U_PMR_common_stack_get(contents, Header, StackID)); +} + +/** + \brief Get data from a U_PMR_RESTORE record + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Header Common header + \param StackID State (level) to restore from the EMF+ Graphics Stack. Must have been put on the GS with a U_PMR_SAVE. + + EMF+ manual 2.3.7.4, Microsoft name: EmfPlusRestore Record, Index 0x26 +*/ +int U_PMR_RESTORE_get(const char *contents, U_PMF_CMN_HDR *Header, uint32_t *StackID){ + return(U_PMR_common_stack_get(contents, Header, StackID)); +} + +/** + \brief Get data from a U_PMR_SAVE record + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Header Common header + \param StackID State (level) to save.on the EMF+ Graphics Stack + + EMF+ manual 2.3.7.5, Microsoft name: EmfPlusSave Record, Index 0x25 +*/ +int U_PMR_SAVE_get(const char *contents, U_PMF_CMN_HDR *Header, uint32_t *StackID){ + return(U_PMR_common_stack_get(contents, Header, StackID)); +} + +/** + \brief Get data from a U_PMR_SETTSCLIP record + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Header Common header + \param ctype Set: int16_t coordinates; Clear: U_FLOAT coordinates + \param Elements Number of members in Data. + \param Rects Caller must free. Array of rectangles to draw. Coordinate type set by ctype. + + EMF+ manual 2.3.8.1, Microsoft name: EmfPlusSetTSClip Record, Index 0x3A +*/ +int U_PMR_SETTSCLIP_get(const char *contents, U_PMF_CMN_HDR *Header, + int *ctype, uint32_t *Elements, + U_PMF_RECTF **Rects){ + if(!contents || !ctype || !Elements || !Rects){ return(0); } + + const char *blimit = contents; + U_PMF_CMN_HDR lclHeader; + U_PMF_CMN_HDR_get(&contents, &lclHeader); + if(lclHeader.Size < sizeof(U_PMF_SETTSCLIP))return(0); + if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); } + blimit += lclHeader.Size; + + *ctype = (lclHeader.Flags & U_PPF_K ? 1 : 0 ); + *Elements = (lclHeader.Flags >> U_FF_SHFT_TSC) & U_FF_MASK_TSC; + U_PMF_VARRECTS_get(&contents, lclHeader.Flags, *Elements, Rects, blimit); + return(1); +} + +/** + \brief Get data from a U_PMR_SETTSGRAPHICS record + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Header Common header + \param vgatype Set: Palette is VGA basic colors; Clear: Palette is ??? + \param pptype Set: Palette is present; Clear: Palette is absent. + \param AntiAliasMode SmoothingMode enumeration + \param TextRenderHint TextRenderingHint enumeration + \param CompositingMode CompositingMode enumeration + \param CompositingQuality CompositingQuality enumeration + \param RenderOriginX Origin X for halftoning and dithering + \param RenderOriginY Origin Y for halftoning and dithering + \param TextContrast Gamma correction, range 0 to 12 + \param FilterType FilterType enumeraton + \param PixelOffset PixelOffsetMode enumeration + \param WorldToDevice world to device transform + \param Data Palette (optional) + + EMF+ manual 2.3.8.2, Microsoft name: EmfPlusSetTSGraphics Record, Index 0x39 + + Caller must check Data for possible memory access violations. +*/ +int U_PMR_SETTSGRAPHICS_get(const char *contents, U_PMF_CMN_HDR *Header, + int *vgatype, int *pptype, + uint8_t *AntiAliasMode, uint8_t *TextRenderHint, uint8_t *CompositingMode, uint8_t *CompositingQuality, + int16_t *RenderOriginX, int16_t *RenderOriginY, uint16_t *TextContrast, uint8_t *FilterType, + uint8_t *PixelOffset, U_PMF_TRANSFORMMATRIX *WorldToDevice, + const char **Data){ + if(!contents || !vgatype || !pptype || + !AntiAliasMode || !TextRenderHint || !CompositingMode || !CompositingQuality || + !RenderOriginX || !RenderOriginY || !TextContrast || !FilterType || + !PixelOffset || !WorldToDevice || !Data){ return(0); } + + U_PMF_CMN_HDR lclHeader; + U_PMF_CMN_HDR_get(&contents, &lclHeader); + if(lclHeader.Size < sizeof(U_PMF_SETTSGRAPHICS))return(0); + if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); } + + *vgatype = (lclHeader.Flags & U_PPF_VGA ? 1 : 0 ); + *pptype = (lclHeader.Flags & U_PPF_PP ? 1 : 0 ); + U_PMF_SERIAL_get(&contents, AntiAliasMode, 1, 1, U_XE); + U_PMF_SERIAL_get(&contents, TextRenderHint, 1, 1, U_XE); + U_PMF_SERIAL_get(&contents, CompositingMode, 1, 1, U_XE); + U_PMF_SERIAL_get(&contents, CompositingQuality, 1, 1, U_XE); + U_PMF_SERIAL_get(&contents, RenderOriginX, 2, 1, U_LE); + U_PMF_SERIAL_get(&contents, RenderOriginY, 2, 1, U_LE); + U_PMF_SERIAL_get(&contents, TextContrast, 2, 1, U_LE); + U_PMF_SERIAL_get(&contents, FilterType, 1, 1, U_XE); + U_PMF_SERIAL_get(&contents, WorldToDevice, 4, 6, U_LE); + U_PMF_PTRSAV_COND(Data, contents, *pptype); + return(1); +} + +/** + \brief Get data from a U_PMR_MULTIPLYWORLDTRANSFORM record + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Header Common header + \param xmtype Set: Post multiply; Clear: Pre multiply + \param Matrix Transformation matrix + + EMF+ manual 2.3.9.1, Microsoft name: EmfPlusMultiplyWorldTransform Record, Index 0x2C +*/ +int U_PMR_MULTIPLYWORLDTRANSFORM_get(const char *contents, U_PMF_CMN_HDR *Header, + int *xmtype, + U_PMF_TRANSFORMMATRIX *Matrix){ + if(!contents || !xmtype || !Matrix){ return(0); } + + U_PMF_CMN_HDR lclHeader; + U_PMF_CMN_HDR_get(&contents, &lclHeader); + if(lclHeader.Size < sizeof(U_PMF_MULTIPLYWORLDTRANSFORM))return(0); + if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); } + + *xmtype = (lclHeader.Flags & U_PPF_XM ? 1 : 0 ); + U_PMF_SERIAL_get(&contents, Matrix, 4, 6, U_LE); + return(1); +} + +/** + \brief Get data from a U_PMR_RESETWORLDTRANSFORM record + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Header Common header + + EMF+ manual 2.3.9.2, Microsoft name: EmfPlusResetWorldTransform Record, Index 0x2B +*/ +int U_PMR_RESETWORLDTRANSFORM_get(const char *contents, U_PMF_CMN_HDR *Header){ + return( U_PMR_common_header_get(contents,Header)); +} + +/** + \brief Get data from a U_PMR_ROTATEWORLDTRANSFORM record + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Header Common header + \param xmtype Set: Post multiply; Clear: Pre multiply + \param Angle Rotation angle, in degrees + + EMF+ manual 2.3.9.3, Microsoft name: EmfPlusRotateWorldTransform Record, Index 0x2F +*/ +int U_PMR_ROTATEWORLDTRANSFORM_get(const char *contents, U_PMF_CMN_HDR *Header, + int *xmtype, + U_FLOAT *Angle){ + if(!contents || !xmtype || !Angle){ return(0); } + + U_PMF_CMN_HDR lclHeader; + U_PMF_CMN_HDR_get(&contents, &lclHeader); + if(lclHeader.Size < sizeof(U_PMF_ROTATEWORLDTRANSFORM))return(0); + if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); } + + *xmtype = (lclHeader.Flags & U_PPF_XM ? 1 : 0 ); + U_PMF_SERIAL_get(&contents, Angle, 4, 1, U_LE); + return(1); +} + +/** + \brief Get data from a U_PMR_SCALEWORLDTRANSFORM record + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Header Common header + \param xmtype Set: Post multiply; Clear: Pre multiply. + \param Sx X scale factor. + \param Sy Y scale factor. + + EMF+ manual 2.3.9.4, Microsoft name: EmfPlusScaleWorldTransform Record, Index 0x2E +*/ +int U_PMR_SCALEWORLDTRANSFORM_get(const char *contents, U_PMF_CMN_HDR *Header, + int *xmtype, + U_FLOAT *Sx, U_FLOAT *Sy){ + if(!contents || !xmtype || !Sx || !Sy){ return(0); } + + U_PMF_CMN_HDR lclHeader; + U_PMF_CMN_HDR_get(&contents, &lclHeader); + if(lclHeader.Size < sizeof(U_PMF_SCALEWORLDTRANSFORM))return(0); + if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); } + + *xmtype = (lclHeader.Flags & U_PPF_XM ? 1 : 0 ); + U_PMF_SERIAL_get(&contents, Sx, 4, 1, U_LE); + U_PMF_SERIAL_get(&contents, Sy, 4, 1, U_LE); + return(1); +} + +/** + \brief Get data from a U_PMR_SETPAGETRANSFORM record + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Header Common header + \param PUenum Page Unit, UnitType enumeration + \param Scale Scale factor to convert page space to device space + + EMF+ manual 2.3.9.5, Microsoft name: EmfPlusSetPageTransform Record, Index 0x30 +*/ +int U_PMR_SETPAGETRANSFORM_get(const char *contents, U_PMF_CMN_HDR *Header, + int *PUenum, + U_FLOAT *Scale){ + if(!contents || !PUenum || !Scale){ return(0); } + + U_PMF_CMN_HDR lclHeader; + U_PMF_CMN_HDR_get(&contents, &lclHeader); + if(lclHeader.Size < sizeof(U_PMF_SETPAGETRANSFORM))return(0); + if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); } + + *PUenum = (lclHeader.Flags >> U_FF_SHFT_PU) & U_FF_MASK_PU; + U_PMF_SERIAL_get(&contents, Scale, 4, 1, U_LE); + return(1); +} + +/** + \brief Get data from a U_PMR_SETWORLDTRANSFORM record + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Header Common header + \param Matrix Transformation matrix + + EMF+ manual 2.3.9.6, Microsoft name: EmfPlusSetWorldTransform Record, Index 0x2A +*/ +int U_PMR_SETWORLDTRANSFORM_get(const char *contents, U_PMF_CMN_HDR *Header, + U_PMF_TRANSFORMMATRIX *Matrix){ + if(!contents || !Matrix){ return(0); } + + U_PMF_CMN_HDR lclHeader; + U_PMF_CMN_HDR_get(&contents, &lclHeader); + if(lclHeader.Size < sizeof(U_PMF_SETWORLDTRANSFORM))return(0); + if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); } + + U_PMF_SERIAL_get(&contents, Matrix, 4, 6, U_LE); + return(1); +} + +/** + \brief Get data from a U_PMR_TRANSLATEWORLDTRANSFORM record + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Header Common header + \param xmtype Set: Post multiply; Clear: Pre multiply + \param Dx X offset + \param Dy Y offset + + EMF+ manual 2.3.9.7, Microsoft name: EmfPlusTranslateWorldTransform Record, Index 0x2D +*/ +int U_PMR_TRANSLATEWORLDTRANSFORM_get(const char *contents, U_PMF_CMN_HDR *Header, + int *xmtype, + U_FLOAT *Dx, U_FLOAT *Dy){ + if(!contents || !xmtype || !Dx || !Dy){ return(0); } + + U_PMF_CMN_HDR lclHeader; + U_PMF_CMN_HDR_get(&contents, &lclHeader); + if(lclHeader.Size < sizeof(U_PMF_TRANSLATEWORLDTRANSFORM))return(0); + if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); } + + *xmtype = (lclHeader.Flags & U_PPF_XM ? 1 : 0 ); + U_PMF_SERIAL_get(&contents, Dx, 4, 1, U_LE); + U_PMF_SERIAL_get(&contents, Dy, 4, 1, U_LE); + return(1); +} + +/** + \brief Get data from a U_PMR_STROKEFILLPATH record + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Header Common header (ignore flags) + + + EMF+ manual mentioned in 2.1.1.1, not otherwise documented, Microsoft name: EmfPlusStrokeFillPath Record, Index 0x37 + + "This record closes any open figures in a path, strokes the outline of + the path by using the current pen, and fills its interior by using the current brush." +*/ +int U_PMR_STROKEFILLPATH_get(const char *contents, U_PMF_CMN_HDR *Header){ + return( U_PMR_common_header_get(contents,Header)); +} + +/** + \brief Get data from a U_PMR_MULTIFORMATSTART record + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Header Common header (ignore flags) + + EMF+ manual mentioned in 2.1.1.1, reserved, not otherwise documented, Microsoft name: EmfPlusMultiFormatStart Record, Index 0x05 +*/ +int U_PMR_MULTIFORMATSTART_get(const char *contents, U_PMF_CMN_HDR *Header){ + return( U_PMR_common_header_get(contents,Header)); +} + +/** + \brief Get data from a U_PMR_MULTIFORMATSECTION record + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Header Common header (ignore flags) + + EMF+ manual mentioned in 2.1.1.1, reserved, not otherwise documented, Microsoft name: EmfPlusMultiFormatSection Record, Index 0x06 +*/ +int U_PMR_MULTIFORMATSECTION_get(const char *contents, U_PMF_CMN_HDR *Header){ + return( U_PMR_common_header_get(contents,Header)); +} + +/** + \brief Get data from a U_PMR_MULTIFORMATEND record + \return 1 on success, 0 on error + \param contents Record from which to extract data + \param Header Common header (ignore flags) + + EMF+ manual mentioned in 2.1.1.1, reserved, not otherwise documented, Microsoft name: EmfPlusMultiFormatEnd Record, Index 0x06 +*/ +int U_PMR_MULTIFORMATEND_get(const char *contents, U_PMF_CMN_HDR *Header){ + return( U_PMR_common_header_get(contents,Header)); +} + + +#ifdef __cplusplus +} +#endif diff --git a/src/3rdparty/libuemf/upmf.h b/src/3rdparty/libuemf/upmf.h new file mode 100644 index 0000000..c793746 --- /dev/null +++ b/src/3rdparty/libuemf/upmf.h @@ -0,0 +1,3178 @@ +/** + @file upmf.h + + @brief Structures, definitions, and function prototypes for EMF+ files. + + EMF+ file Record structure derived from Microsoft's EMF+ Information pdf, releade date July 5,2012, link from + here: + + http://msdn.microsoft.com/en-us/library/cc230724.aspx + + If the direct link fails the document may be found + by searching for: "[MS-EMFPLUS]: Enhanced Metafile Format Plus Extensions " + + EMR records and structures are EMF or common with EMF+ + PMR records and structures are specific to EMF+ + + Using PMF instead of EMF+ because "+" is a problem in symbol names. + + ***************************************************************************************** + * WARNING: Microsoft's EMF+ documentation is little-endian for everything EXCEPT * + * bitfields, which are big-endian. See section 1.3.2 * + * That documentation also uses 0 as the MOST significant bit, N-1 as the least. * + * This code is little-endian throughout, and 0 is the LEAST significant bit * + ***************************************************************************************** + +*/ + +/* +File: upmf.h +Version: 0.0.6 +Date: 13-MAY-2020 +Author: David Mathog, Biology Division, Caltech +email: mathog@caltech.edu +Copyright: 2020 David Mathog and California Institute of Technology (Caltech) +*/ + +#ifndef _UPMF_ +#define _UPMF_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdint.h> +#include <stdbool.h> +#include "uemf.h" + + +/** \defgroup U_PMF_PMF_Misc PMF Miscellaneous defines + @{ +*/ +#define U_PMF_DROP_ELEMENTS 1 //!< Remove leading Elements value from data. +#define U_PMF_KEEP_ELEMENTS 0 //!< Retain leading Elements value from data. + +#define U_SEG_NEW 1 //!< start a new segment in the path +#define U_SEG_OLD 0 //!< continue the old (current) segment in the path + +#define U_FILTER_APPLY 1 //!< With U_PMR_DRAWIMAGEPOINTS_set, use whatever filter has been set up up. +#define U_FILTER_IGNORE 0 //!< With U_PMR_DRAWIMAGEPOINTS_set, ignore whatever filter has been set up up. +#define U_OBJRECLIM 65020 //!< Longest U_PMR_OBJECT that GDI+ will process + // used 9728 to test fragmenting of emitted object records + +/** @} */ + +/** \defgroup U_PMF_DD_ PMF "standard" custom Dash Dot patterns for lines. + + U_DD_DASH, U_DD_DOT, U_DD_DASHDOT, and U_DD_DASHDOTDOT are the only ones with corresponding + standard EMF and EMF+ dash/dot patterns. + + These values are used to tell U_PMF_DASHEDLINEDATA_set2() to create one of 27 custom line patterns. + Other custom line patterns may be created using U_PMF_DASHEDLINEDATA_set(), but this provides an easier + way to get the same result if one of these patterns is acceptable. + + The length is divided by 2X the number of elements, so dashdash has twice as many + dashes of half the length as just dash. + + Dot is 1/8 of (sub)unit length + Dash is 1/2 of (sub)unit length + Long is 3/4 of (sub)unit length + Example: DotDot has (sub)unit length 1/2, so each dot will be 1/16 of unit length. + + @{ +*/ +#define U_DD_Solid 0 //!< Solid line. +#define U_DD_Dash 1 //!< Dash line. +#define U_DD_DashDash 2 //!< Dash Dash line. +#define U_DD_DashDashDash 3 //!< Dash Dash Dash line. +#define U_DD_DashDashDashDash 4 //!< Dash Dash Dash Dash line. +#define U_DD_Dot 5 //!< Dot line. +#define U_DD_DotDot 6 //!< Dot Dot line. +#define U_DD_DotDotDot 7 //!< Dot Dot Dot line. +#define U_DD_DotDotDotDot 8 //!< Dot Dot Dot Dot line. +#define U_DD_DashDot 9 //!< Dash Dot line. +#define U_DD_DashDashDot 10 //!< Dash Dash Dot line. +#define U_DD_DashDashDotDot 11 //!< Dash Dash Dot Dot line. +#define U_DD_DashDashDashDot 12 //!< Dash Dash Das hDot line. +#define U_DD_DashDotDot 13 //!< Dash Dot Dot line. +#define U_DD_DashDotDotDot 14 //!< Dash Dot Dot Dot line. +#define U_DD_DashDotDashDot 15 //!< Dash Dot Dash Dot line. +#define U_DD_Long 16 //!< Long line. +#define U_DD_LongLong 17 //!< Long Long line. +#define U_DD_LongLongLong 18 //!< Long Long Long line. +#define U_DD_LongLongLongLong 19 //!< Long Long Long Long line. +#define U_DD_LongDot 20 //!< Long Dot line. +#define U_DD_LongLongDot 21 //!< Long Long Dot line. +#define U_DD_LongLongDotDot 22 //!< Long Long Dot Dot line. +#define U_DD_LongLongLongDot 23 //!< Long Long Long Dot line. +#define U_DD_LongDotDot 24 //!< Long Dot Dot line. +#define U_DD_LongDotDotDot 25 //!< Long Dot Dot Dot line. +#define U_DD_LongDotLongDot 26 //!< Long Dot Long Dot line. +#define U_DD_Types 27 //!< Types + +/** @} */ + + +/** \defgroup U_PMF_PMR_Qualifiers PMF RecordType Enumeration + EMF+ manual 2.1.1.1, Microsoft name: RecordType Enumeration + @{ +*/ +#define U_PMR_HEADER 0x0001 //!< U_PMRHeader record +#define U_PMR_ENDOFFILE 0x0002 //!< U_PMREndOfFile record +#define U_PMR_COMMENT 0x0003 //!< U_PMRComment record +#define U_PMR_GETDC 0x0004 //!< U_PMRGetDC record +#define U_PMR_MULTIFORMATSTART 0x0005 //!< U_PMRMultiFormatStart record +#define U_PMR_MULTIFORMATSECTION 0x0006 //!< U_PMRMultiFormatSection record +#define U_PMR_MULTIFORMATEND 0x0007 //!< U_PMRMultiFormatEnd record +#define U_PMR_OBJECT 0x0008 //!< U_PMRObject record +#define U_PMR_CLEAR 0x0009 //!< U_PMRClear record +#define U_PMR_FILLRECTS 0x000A //!< U_PMRFillRects record +#define U_PMR_DRAWRECTS 0x000B //!< U_PMRDrawRects record +#define U_PMR_FILLPOLYGON 0x000C //!< U_PMRFillPolygon record +#define U_PMR_DRAWLINES 0x000D //!< U_PMRDrawLines record +#define U_PMR_FILLELLIPSE 0x000E //!< U_PMRFillEllipse record +#define U_PMR_DRAWELLIPSE 0x000F //!< U_PMRDrawEllipse record +#define U_PMR_FILLPIE 0x0010 //!< U_PMRFillPie record +#define U_PMR_DRAWPIE 0x0011 //!< U_PMRDrawPie record +#define U_PMR_DRAWARC 0x0012 //!< U_PMRDrawArc record +#define U_PMR_FILLREGION 0x0013 //!< U_PMRFillRegion record +#define U_PMR_FILLPATH 0x0014 //!< U_PMRFillPath record +#define U_PMR_DRAWPATH 0x0015 //!< U_PMRDrawPath record +#define U_PMR_FILLCLOSEDCURVE 0x0016 //!< U_PMRFillClosedCurve record +#define U_PMR_DRAWCLOSEDCURVE 0x0017 //!< U_PMRDrawClosedCurve record +#define U_PMR_DRAWCURVE 0x0018 //!< U_PMRDrawCurve record +#define U_PMR_DRAWBEZIERS 0x0019 //!< U_PMRDrawBeziers record +#define U_PMR_DRAWIMAGE 0x001A //!< U_PMRDrawImage record +#define U_PMR_DRAWIMAGEPOINTS 0x001B //!< U_PMRDrawImagePoints record +#define U_PMR_DRAWSTRING 0x001C //!< U_PMRDrawString record +#define U_PMR_SETRENDERINGORIGIN 0x001D //!< U_PMRSetRenderingOrigin record +#define U_PMR_SETANTIALIASMODE 0x001E //!< U_PMRSetAntiAliasMode record +#define U_PMR_SETTEXTRENDERINGHINT 0x001F //!< U_PMRSetTextRenderingHint record +#define U_PMR_SETTEXTCONTRAST 0x0020 //!< U_PMRSetTextContrast record +#define U_PMR_SETINTERPOLATIONMODE 0x0021 //!< U_PMRSetInterpolationMode record +#define U_PMR_SETPIXELOFFSETMODE 0x0022 //!< U_PMRSetPixelOffsetMode record +#define U_PMR_SETCOMPOSITINGMODE 0x0023 //!< U_PMRSetCompositingMode record +#define U_PMR_SETCOMPOSITINGQUALITY 0x0024 //!< U_PMRSetCompositingQuality record +#define U_PMR_SAVE 0x0025 //!< U_PMRSave record +#define U_PMR_RESTORE 0x0026 //!< U_PMRRestore record +#define U_PMR_BEGINCONTAINER 0x0027 //!< U_PMRBeginContainer record +#define U_PMR_BEGINCONTAINERNOPARAMS 0x0028 //!< U_PMRBeginContainerNoParams record +#define U_PMR_ENDCONTAINER 0x0029 //!< U_PMREndContainer record +#define U_PMR_SETWORLDTRANSFORM 0x002A //!< U_PMRSetWorldTransform record +#define U_PMR_RESETWORLDTRANSFORM 0x002B //!< U_PMRResetWorldTransform record +#define U_PMR_MULTIPLYWORLDTRANSFORM 0x002C //!< U_PMRMultiplyWorldTransform record +#define U_PMR_TRANSLATEWORLDTRANSFORM 0x002D //!< U_PMRTranslateWorldTransform record +#define U_PMR_SCALEWORLDTRANSFORM 0x002E //!< U_PMRScaleWorldTransform record +#define U_PMR_ROTATEWORLDTRANSFORM 0x002F //!< U_PMRRotateWorldTransform record +#define U_PMR_SETPAGETRANSFORM 0x0030 //!< U_PMRSetPageTransform record +#define U_PMR_RESETCLIP 0x0031 //!< U_PMRResetClip record +#define U_PMR_SETCLIPRECT 0x0032 //!< U_PMRSetClipRect record +#define U_PMR_SETCLIPPATH 0x0033 //!< U_PMRSetClipPath record +#define U_PMR_SETCLIPREGION 0x0034 //!< U_PMRSetClipRegion record +#define U_PMR_OFFSETCLIP 0x0035 //!< U_PMROffsetClip record +#define U_PMR_DRAWDRIVERSTRING 0x0036 //!< U_PMRDrawDriverstring record +#define U_PMR_STROKEFILLPATH 0x0037 //!< U_PMRStrokeFillPath record +#define U_PMR_SERIALIZABLEOBJECT 0x0038 //!< U_PMRSerializableObject record +#define U_PMR_SETTSGRAPHICS 0x0039 //!< U_PMRSetTSGraphics record +#define U_PMR_SETTSCLIP 0x003A //!< U_PMRSetTSClip record +#define U_PMR_RECFLAG 0x4000 //!< In EMF+ files the type is one of the above + this flag +#define U_PMR_TYPE_MASK 0x003F //!< mask for EMF+ types +#define U_PMR_MIN 1 //!< Minimum U_PMR_ value. +#define U_PMR_MAX 58 //!< Maximum U_PMR_ value. + +/** @} */ + +/** \defgroup U_PMF_PID_Values PMF Identifiers for PseudoObjects + These are used by the *_set routines to identify types of PseudoObject. + Note that records are U_PMR_*_OID and other objects are U_PMF_*_OID + The numbers are derived from the EMF+ manual sections, as in 2.2.1.3 become + 02020103. Numbers 40000000 and up are not derived from manual setions. + @{ +*/ +#define U_UNDEFINED_OID 0x00000000 //!< Undefined PseudoObject +#define U_PMF_BRUSH_OID 0x02020101 //!< PMF_BRUSH PseudoObject type. +#define U_PMF_CUSTOMLINECAP_OID 0x02020102 //!< PMF_CUSTOMLINECAP PseudoObject type. +#define U_PMF_FONT_OID 0x02020103 //!< PMF_FONT PseudoObject type. +#define U_PMF_IMAGE_OID 0x02020104 //!< PMF_IMAGE PseudoObject type. +#define U_PMF_IMAGEATTRIBUTES_OID 0x02020105 //!< PMF_IMAGEATTRIBUTES PseudoObject type. +#define U_PMF_PATH_OID 0x02020106 //!< PMF_PATH PseudoObject type. +#define U_PMF_PEN_OID 0x02020107 //!< PMF_PEN PseudoObject type. +#define U_PMF_REGION_OID 0x02020108 //!< PMF_REGION PseudoObject type. +#define U_PMF_STRINGFORMAT_OID 0x02020109 //!< PMF_STRINGFORMAT PseudoObject type. +#define U_PMF_ARGB_OID 0x02020201 //!< PMF_ARGB PseudoObject type. +#define U_PMF_BITMAP_OID 0x02020202 //!< PMF_BITMAP PseudoObject type. +#define U_PMF_BITMAPDATA_OID 0x02020203 //!< PMF_BITMAPDATA PseudoObject type. +#define U_PMF_BLENDCOLORS_OID 0x02020204 //!< PMF_BLENDCOLORS PseudoObject type. +#define U_PMF_BLENDFACTORS_OID 0x02020205 //!< PMF_BLENDFACTORS PseudoObject type. +#define U_PMF_BOUNDARYPATHDATA_OID 0x02020206 //!< PMF_BOUNDARYPATHDATA PseudoObject type. +#define U_PMF_BOUNDARYPOINTDATA_OID 0x02020207 //!< PMF_BOUNDARYPOINTDATA PseudoObject type. +#define U_PMF_CHARACTERRANGE_OID 0x02020208 //!< PMF_CHARACTERRANGE PseudoObject type. +#define U_PMF_COMPOUNDLINEDATA_OID 0x02020209 //!< PMF_COMPOUNDLINEDATA PseudoObject type. +#define U_PMF_COMPRESSEDIMAGE_OID 0x02020210 //!< PMF_COMPRESSEDIMAGE PseudoObject type. +#define U_PMF_CUSTOMENDCAPDATA_OID 0x02020211 //!< PMF_CUSTOMENDCAPDATA PseudoObject type. +#define U_PMF_CUSTOMLINECAPARROWDATA_OID 0x02020212 //!< PMF_CUSTOMLINECAPARROWDATA PseudoObject type. +#define U_PMF_CUSTOMLINECAPDATA_OID 0x02020213 //!< PMF_CUSTOMLINECAPDATA PseudoObject type. +#define U_PMF_CUSTOMLINECAPOPTIONALDATA_OID 0x02020214 //!< PMF_CUSTOMLINECAPOPTIONALDATA PseudoObject type. +#define U_PMF_CUSTOMSTARTCAPDATA_OID 0x02020215 //!< PMF_CUSTOMSTARTCAPDATA PseudoObject type. +#define U_PMF_DASHEDLINEDATA_OID 0x02020216 //!< PMF_DASHEDLINEDATA PseudoObject type. +#define U_PMF_FILLPATHOBJ_OID 0x02020217 //!< PMF_FILLPATHOBJ PseudoObject type. +#define U_PMF_FOCUSSCALEDATA_OID 0x02020218 //!< PMF_FOCUSSCALEDATA PseudoObject type. +#define U_PMF_GRAPHICSVERSION_OID 0x02020219 //!< PMF_GRAPHICSVERSION PseudoObject type. +#define U_PMF_HATCHBRUSHDATA_OID 0x02020220 //!< PMF_HATCHBRUSHDATA PseudoObject type. +#define U_PMF_INTEGER7_OID 0x02020221 //!< PMF_INTEGER7 PseudoObject type. +#define U_PMF_INTEGER15_OID 0x02020222 //!< PMF_INTEGER15 PseudoObject type. +#define U_PMF_LANGUAGEIDENTIFIER_OID 0x02020223 //!< PMF_LANGUAGEIDENTIFIER PseudoObject type. +#define U_PMF_LINEARGRADIENTBRUSHDATA_OID 0x02020224 //!< PMF_LINEARGRADIENTBRUSHDATA PseudoObject type. +#define U_PMF_LINEARGRADIENTBRUSHOPTIONALDATA_OID 0x02020225 //!< PMF_LINEARGRADIENTBRUSHOPTIONALDATA PseudoObject type. +#define U_PMF_LINEPATH_OID 0x02020226 //!< PMF_LINEPATH PseudoObject type. +#define U_PMF_METAFILE_OID 0x02020227 //!< PMF_METAFILE PseudoObject type. +#define U_PMF_PALETTE_OID 0x02020228 //!< PMF_PALETTE PseudoObject type. +#define U_PMF_PATHGRADIENTBRUSHDATA_OID 0x02020229 //!< PMF_PATHGRADIENTBRUSHDATA PseudoObject type. +#define U_PMF_PATHGRADIENTBRUSHOPTIONALDATA_OID 0x02020230 //!< PMF_PATHGRADIENTBRUSHOPTIONALDATA PseudoObject type. +#define U_PMF_PATHPOINTTYPE_OID 0x02020231 //!< PMF_PATHPOINTTYPE PseudoObject type. +#define U_PMF_PATHPOINTTYPERLE_OID 0x02020232 //!< PMF_PATHPOINTTYPERLE PseudoObject type. +#define U_PMF_PENDATA_OID 0x02020233 //!< PMF_PENDATA PseudoObject type. +#define U_PMF_PENOPTIONALDATA_OID 0x02020234 //!< PMF_PENOPTIONALDATA PseudoObject type. +#define U_PMF_POINT_OID 0x02020235 //!< PMF_POINT PseudoObject type. +#define U_PMF_POINTF_OID 0x02020236 //!< PMF_POINTF PseudoObject type. +#define U_PMF_POINTR_OID 0x02020237 //!< PMF_POINTR PseudoObject type. +#define U_PMF_RECT_OID 0x02020238 //!< PMF_RECT PseudoObject type. +#define U_PMF_RECTF_OID 0x02020239 //!< PMF_RECTF PseudoObject type. +#define U_PMF_REGIONNODE_OID 0x02020240 //!< PMF_REGIONNODE PseudoObject type. +#define U_PMF_REGIONNODECHILDNODES_OID 0x02020241 //!< PMF_REGIONNODECHILDNODES PseudoObject type. +#define U_PMF_REGIONNODEPATH_OID 0x02020242 //!< PMF_REGIONNODEPATH PseudoObject type. +#define U_PMF_SOLIDBRUSHDATA_OID 0x02020243 //!< PMF_SOLIDBRUSHDATA PseudoObject type. +#define U_PMF_STRINGFORMATDATA_OID 0x02020244 //!< PMF_STRINGFORMATDATA PseudoObject type. +#define U_PMF_TEXTUREBRUSHDATA_OID 0x02020245 //!< PMF_TEXTUREBRUSHDATA PseudoObject type. +#define U_PMF_TEXTUREBRUSHOPTIONALDATA_OID 0x02020246 //!< PMF_TEXTUREBRUSHOPTIONALDATA PseudoObject type. +#define U_PMF_TRANSFORMMATRIX_OID 0x02020247 //!< PMF_TRANSFORMMATRIX PseudoObject type. +#define U_PMF_IE_BLUR_OID 0x02020301 //!< PMF_IE_BLUR PseudoObject type. +#define U_PMF_IE_BRIGHTNESSCONTRAST_OID 0x02020302 //!< PMF_IE_BRIGHTNESSCONTRAST PseudoObject type. +#define U_PMF_IE_COLORBALANCE_OID 0x02020303 //!< PMF_IE_COLORBALANCE PseudoObject type. +#define U_PMF_IE_COLORCURVE_OID 0x02020304 //!< PMF_IE_COLORCURVE PseudoObject type. +#define U_PMF_IE_COLORLOOKUPTABLE_OID 0x02020305 //!< PMF_IE_COLORLOOKUPTABLE PseudoObject type. +#define U_PMF_IE_COLORMATRIX_OID 0x02020306 //!< PMF_IE_COLORMATRIX PseudoObject type. +#define U_PMF_IE_HUESATURATIONLIGHTNESS_OID 0x02020307 //!< PMF_IE_HUESATURATIONLIGHTNESS PseudoObject type. +#define U_PMF_IE_LEVELS_OID 0x02020308 //!< PMF_IE_LEVELS PseudoObject type. +#define U_PMF_IE_REDEYECORRECTION_OID 0x02020309 //!< PMF_IE_REDEYECORRECTION PseudoObject type. +#define U_PMF_IE_SHARPEN_OID 0x02020310 //!< PMF_IE_SHARPEN PseudoObject type. +#define U_PMF_IE_TINT_OID 0x02020311 //!< PMF_IE_TINT PseudoObject type. +#define U_PMR_STROKEFILLPATH_OID 0x02010101 //!< PMR_STROKEFILLPATH PseudoObject type. (Mentioned in passing here). +#define U_PMR_OFFSETCLIP_OID 0x02030101 //!< PMR_OFFSETCLIP PseudoObject type. +#define U_PMR_RESETCLIP_OID 0x02030102 //!< PMR_RESETCLIP PseudoObject type. +#define U_PMR_SETCLIPPATH_OID 0x02030103 //!< PMR_SETCLIPPATH PseudoObject type. +#define U_PMR_SETCLIPRECT_OID 0x02030104 //!< PMR_SETCLIPRECT PseudoObject type. +#define U_PMR_SETCLIPREGION_OID 0x02030105 //!< PMR_SETCLIPREGION PseudoObject type. +#define U_PMR_COMMENT_OID 0x02030201 //!< PMR_COMMENT PseudoObject type. +#define U_PMR_ENDOFFILE_OID 0x02030301 //!< PMR_ENDOFFILE PseudoObject type. +#define U_PMR_GETDC_OID 0x02030302 //!< PMR_GETDC PseudoObject type. +#define U_PMR_HEADER_OID 0x02030303 //!< PMR_HEADER PseudoObject type. +#define U_PMR_CLEAR_OID 0x02030401 //!< PMR_CLEAR PseudoObject type. +#define U_PMR_DRAWARC_OID 0x02030402 //!< PMR_DRAWARC PseudoObject type. +#define U_PMR_DRAWBEZIERS_OID 0x02030403 //!< PMR_DRAWBEZIERS PseudoObject type. +#define U_PMR_DRAWCLOSEDCURVE_OID 0x02030404 //!< PMR_DRAWCLOSEDCURVE PseudoObject type. +#define U_PMR_DRAWCURVE_OID 0x02030405 //!< PMR_DRAWCURVE PseudoObject type. +#define U_PMR_DRAWDRIVERSTRING_OID 0x02030406 //!< PMR_DRAWDRIVERSTRING PseudoObject type. +#define U_PMR_DRAWELLIPSE_OID 0x02030407 //!< PMR_DRAWELLIPSE PseudoObject type. +#define U_PMR_DRAWIMAGE_OID 0x02030408 //!< PMR_DRAWIMAGE PseudoObject type. +#define U_PMR_DRAWIMAGEPOINTS_OID 0x02030409 //!< PMR_DRAWIMAGEPOINTS PseudoObject type. +#define U_PMR_DRAWLINES_OID 0x02030410 //!< PMR_DRAWLINES PseudoObject type. +#define U_PMR_DRAWPATH_OID 0x02030411 //!< PMR_DRAWPATH PseudoObject type. +#define U_PMR_DRAWPIE_OID 0x02030412 //!< PMR_DRAWPIE PseudoObject type. +#define U_PMR_DRAWRECTS_OID 0x02030413 //!< PMR_DRAWRECTS PseudoObject type. +#define U_PMR_DRAWSTRING_OID 0x02030414 //!< PMR_DRAWSTRING PseudoObject type. +#define U_PMR_FILLCLOSEDCURVE_OID 0x02030415 //!< PMR_FILLCLOSEDCURVE PseudoObject type. +#define U_PMR_FILLELLIPSE_OID 0x02030416 //!< PMR_FILLELLIPSE PseudoObject type. +#define U_PMR_FILLPATH_OID 0x02030417 //!< PMR_FILLPATH PseudoObject type. +#define U_PMR_FILLPIE_OID 0x02030418 //!< PMR_FILLPIE PseudoObject type. +#define U_PMR_FILLPOLYGON_OID 0x02030419 //!< PMR_FILLPOLYGON PseudoObject type. +#define U_PMR_FILLRECTS_OID 0x02030420 //!< PMR_FILLRECTS PseudoObject type. +#define U_PMR_FILLREGION_OID 0x02030421 //!< PMR_FILLREGION PseudoObject type. +#define U_PMR_OBJECT_OID 0x02030501 //!< PMR_OBJECT PseudoObject type. +#define U_PMR_SERIALIZABLEOBJECT_OID 0x02030502 //!< PMR_SERIALIZABLEOBJECT PseudoObject type. +#define U_PMR_SETANTIALIASMODE_OID 0x02030601 //!< PMR_SETANTIALIASMODE PseudoObject type. +#define U_PMR_SETCOMPOSITINGMODE_OID 0x02030602 //!< PMR_SETCOMPOSITINGMODE PseudoObject type. +#define U_PMR_SETCOMPOSITINGQUALITY_OID 0x02030603 //!< PMR_SETCOMPOSITINGQUALITY PseudoObject type. +#define U_PMR_SETINTERPOLATIONMODE_OID 0x02030604 //!< PMR_SETINTERPOLATIONMODE PseudoObject type. +#define U_PMR_SETPIXELOFFSETMODE_OID 0x02030605 //!< PMR_SETPIXELOFFSETMODE PseudoObject type. +#define U_PMR_SETRENDERINGORIGIN_OID 0x02030606 //!< PMR_SETRENDERINGORIGIN PseudoObject type. +#define U_PMR_SETTEXTCONTRAST_OID 0x02030607 //!< PMR_SETTEXTCONTRAST PseudoObject type. +#define U_PMR_SETTEXTRENDERINGHINT_OID 0x02030608 //!< PMR_SETTEXTRENDERINGHINT PseudoObject type. +#define U_PMR_BEGINCONTAINER_OID 0x02030701 //!< PMR_BEGINCONTAINER PseudoObject type. +#define U_PMR_BEGINCONTAINERNOPARAMS_OID 0x02030702 //!< PMR_BEGINCONTAINERNOPARAMS PseudoObject type. +#define U_PMR_ENDCONTAINER_OID 0x02030703 //!< PMR_ENDCONTAINER PseudoObject type. +#define U_PMR_RESTORE_OID 0x02030704 //!< PMR_RESTORE PseudoObject type. +#define U_PMR_SAVE_OID 0x02030705 //!< PMR_SAVE PseudoObject type. +#define U_PMR_SETTSCLIP_OID 0x02030801 //!< PMR_SETTSCLIP PseudoObject type. +#define U_PMR_SETTSGRAPHICS_OID 0x02030802 //!< PMR_SETTSGRAPHICS PseudoObject type. +#define U_PMR_MULTIPLYWORLDTRANSFORM_OID 0x02030901 //!< PMR_MULTIPLYWORLDTRANSFORM PseudoObject type. +#define U_PMR_RESETWORLDTRANSFORM_OID 0x02030902 //!< PMR_RESETWORLDTRANSFORM PseudoObject type. +#define U_PMR_ROTATEWORLDTRANSFORM_OID 0x02030903 //!< PMR_ROTATEWORLDTRANSFORM PseudoObject type. +#define U_PMR_SCALEWORLDTRANSFORM_OID 0x02030904 //!< PMR_SCALEWORLDTRANSFORM PseudoObject type. +#define U_PMR_SETPAGETRANSFORM_OID 0x02030905 //!< PMR_SETPAGETRANSFORM PseudoObject type. +#define U_PMR_SETWORLDTRANSFORM_OID 0x02030906 //!< PMR_SETWORLDTRANSFORM PseudoObject type. +#define U_PMR_TRANSLATEWORLDTRANSFORM_OID 0x02030907 //!< PMR_TRANSLATEWORLDTRANSFORM PseudoObject type. +#define U_PMR_TRANSLATEWORLDTRANSFORM_OID 0x02030907 //!< PMR_TRANSLATEWORLDTRANSFORM PseudoObject type. +#define U_PMR_CMN_HDR_OID 0x40000000 //!< PMR_CMN_HDR PseudoObject type. +#define U_PMF_4NUM_OID 0x40000001 //!< PMF_4NUM PseudoObject type. PseudoObject contains a 4 unsigned int in EMF+ file byte order, used in some contexts to indicate an object index number.. +#define U_PMF_RAW_OID 0x40000002 //!< PMF_RAW PseudoObject type. Raw data: no preceding elements, data has native endianness. +#define U_PMF_ARRAY_OID 0x80000000 //!< PMF_ARRAY PseudoObject type modifier. PseudoObject contains an array of the data type revealed when this bit is cleared. +#define U_PMF_MASK_OID 0x7FFFFFFF //!< PMF_MASK. Select PseudoObject data type without regard to PMF_ARRAY. + +/** @} */ + + +/** \defgroup U_PMF_BDT_ PMF BitmapDataType Enumeration + For + EMF+ manual 2.1.1.2, Microsoft name: BitmapDataType Enumeration (U_BDT_*) + @{ +*/ +#define U_BDT_Pixel 0x00 //!< Data is a bitmap. +#define U_BDT_Compressed 0x01 //!< Data is a compressed bitmap (like a PNG). +/** @} */ + +/** \defgroup U_PMF_BT_ PMF BrushType Enumeration + For + EMF+ manual 2.1.1.3, Microsoft name: BrushType Enumeration (U_BT_*) + @{ +*/ +#define U_BT_SolidColor 0x00 //!< Solid Color brush. +#define U_BT_HatchFill 0x01 //!< Hatch Fill brush. +#define U_BT_TextureFill 0x02 //!< Texture Fill brush. +#define U_BT_PathGradient 0x03 //!< Path Gradient brush. +#define U_BT_LinearGradient 0x04 //!< Linear Gradient brush. +/** @} */ + +/** \defgroup U_PMF_CM_ PMF CombineMode Enumeration + For + EMF+ manual 2.1.1.4, Microsoft name: CombineMode Enumeration (U_CM_*) + @{ +*/ +#define U_CM_Replace 0x00 //!< Region becomes new region. +#define U_CM_Intersect 0x01 //!< Region becomes intersection of existing region and new region. +#define U_CM_Union 0x02 //!< Region becomes union of existing and new regions. +#define U_CM_XOR 0x03 //!< Region becomes XOR of existing and new regions. +#define U_CM_Exclude 0x04 //!< Region becomes part of existing region not in new region. +#define U_CM_Complement 0x05 //!< Region becomes part of new region not in existing region. +/** @} */ + +/** \defgroup U_PMF_CMS_ PMF CompositingMode Enumeration + For + EMF+ manual 2.1.1.5, Microsoft name: CompositingMode Enumeration (U_CMS_* [S==Source]) + @{ +*/ +#define U_CMS_Over 0x00 //!< Source is alpha blends with destination. +#define U_CMS_Copy 0x01 //!< Source over writes destination. +/** @} */ + +/** \defgroup U_PMF_CQ_ PMF CompositingQuality Enumeration + For + EMF+ manual 2.1.1.6, Microsoft name: CompositingQuality Enumeration (U_CQ_*) + @{ +*/ +#define U_CQ_Default 0x01 //!< Default compositing quality +#define U_CQ_HighSpeed 0x02 //!< High Speed compositing quality +#define U_CQ_HighQuality 0x03 //!< High Quality compositing quality +#define U_CQ_GammaCorrected 0x04 //!< Gamma Corrected compositing quality +#define U_CQ_AssumeLinear 0x05 //!< Assume Linear compositing quality +/** @} */ + +/** \defgroup U_PMF_CA_ PMF CurveAdjustments Enumeration + For + EMF+ manual 2.1.1.7, Microsoft name: CurveAdjustments Enumeration (U_CA_*) + @{ +*/ +#define U_CA_Exposure 0x00 //!< Exposure color curve adjustment +#define U_CA_Density 0x01 //!< Density color curve adjustment +#define U_CA_Contrast 0x02 //!< Contrast color curve adjustment +#define U_CA_Highlight 0x03 //!< Highlight color curve adjustment +#define U_CA_Shadow 0x04 //!< Shadow color curve adjustment +#define U_CA_Midtone 0x05 //!< Midtone color curve adjustment +#define U_CA_WhiteSaturation 0x06 //!< White Saturation color curve adjustment +#define U_CA_BlackSaturation 0x07 //!< Black Saturation color curve adjustment +/** @} */ + +/** \defgroup U_PMF_CC_ PMF CurveChannel Enumeration + For + EMF+ manual 2.1.1.8, Microsoft name: CurveChannel Enumeration (U_CC_*) + @{ +*/ +#define U_CC_All 0x00 //!< All color channels +#define U_CC_Red 0x01 //!< Red color channel +#define U_CC_Green 0x02 //!< Green color channel +#define U_CC_Blue 0x03 //!< Blue color channel +/** @} */ + +/** \defgroup U_PMF_CLCDT_ PMF CustomLineCapDataType Enumeration + For + EMF+ manual 2.1.1.9, Microsoft name: CustomLineCapDataType Enumeration (U_CLCDT_*) + @{ +*/ +#define U_CLCDT_Default 0x00 //!< Default custom line cap +#define U_CLCDT_AdjustableArrow 0x01 //!< Adjustable Arrow custom line cap +/** @} */ + +/** \defgroup U_PMF_DLCT_ PMF DashedLineCapType Enumeration + For + EMF+ manual 2.1.1.10, Microsoft name: DashedLineCapType Enumeration (U_DLCT_*) + @{ +*/ +#define U_DLCT_Flat 0x00 //!< Flat dashed line cap +#define U_DLCT_Round 0x02 //!< Round dashed line cap +#define U_DLCT_Triangle 0x03 //!< Triangle dashed line cap +/** @} */ + +/** \defgroup U_PMF_FT_ PMF FilterType Enumeration + For + EMF+ manual 2.1.1.11, Microsoft name: FilterType Enumeration (U_FT_*) + @{ +*/ +#define U_FT_None 0x00 //!< No filtering +#define U_FT_Point 0x01 //!< Point filtering +#define U_FT_Linear 0x02 //!< Linear filtering +#define U_FT_Triangle 0x03 //!< Triangle filtering +#define U_FT_Box 0x04 //!< Box filtering +#define U_FT_PyramidalQuad 0x06 //!< Pyramidal Quad filtering +#define U_FT_GaussianQuad 0x07 //!< Gaussian Quad filtering +/** @} */ + +/** \defgroup U_PMF_GV_ PMF GraphicsVersion Enumeration + For + EMF+ manual 2.1.1.12, Microsoft name: GraphicsVersion Enumeration (U_GV_*) + @{ +*/ +#define U_GV_1 0x01 //!< 1 graphics version +#define U_GV_1_1 0x02 //!< 1.1 graphics version +/** @} */ + +/** \defgroup U_PMF_HSP_ PMF HatchStyle Enumeration + For + EMF+ manual 2.1.1.13, Microsoft name: HatchStyle Enumeration (U_HSP_* [U_HS_ already used for EMF]) + @{ +*/ +#define U_HSP_Horizontal 0x00000000 //!< Horizontal +#define U_HSP_Vertical 0x00000001 //!< Vertical +#define U_HSP_ForwardDiagonal 0x00000002 //!< Forward Diagonal +#define U_HSP_BackwardDiagonal 0x00000003 //!< Backward Diagonal +#define U_HSP_LargeGrid 0x00000004 //!< Large Grid +#define U_HSP_DiagonalCross 0x00000005 //!< Diagonal Cross +#define U_HSP_05Percent 0x00000006 //!< 05 Percent +#define U_HSP_10Percent 0x00000007 //!< 10 Percent +#define U_HSP_20Percent 0x00000008 //!< 20 Percent +#define U_HSP_25Percent 0x00000009 //!< 25 Percent +#define U_HSP_30Percent 0x0000000A //!< 30 Percent +#define U_HSP_40Percent 0x0000000B //!< 40 Percent +#define U_HSP_50Percent 0x0000000C //!< 50 Percent +#define U_HSP_60Percent 0x0000000D //!< 60 Percent +#define U_HSP_70Percent 0x0000000E //!< 70 Percent +#define U_HSP_75Percent 0x0000000F //!< 75 Percent +#define U_HSP_80Percent 0x00000010 //!< 80 Percent +#define U_HSP_90Percent 0x00000011 //!< 90 Percent +#define U_HSP_LightDownwardDiagonal 0x00000012 //!< Light Downward Diagonal +#define U_HSP_LightUpwardDiagonal 0x00000013 //!< Light Upward Diagonal +#define U_HSP_DarkDownwardDiagonal 0x00000014 //!< Dark Downward Diagonal +#define U_HSP_DarkUpwardDiagonal 0x00000015 //!< Dark Upward Diagonal +#define U_HSP_WideDownwardDiagonal 0x00000016 //!< Wide Downward Diagonal +#define U_HSP_WideUpwardDiagonal 0x00000017 //!< Wide Upward Diagonal +#define U_HSP_LightVertical 0x00000018 //!< Light Vertical +#define U_HSP_LightHorizontal 0x00000019 //!< Light Horizontal +#define U_HSP_NarrowVertical 0x0000001A //!< Narrow Vertical +#define U_HSP_NarrowHorizontal 0x0000001B //!< Narrow Horizontal +#define U_HSP_DarkVertical 0x0000001C //!< Dark Vertical +#define U_HSP_DarkHorizontal 0x0000001D //!< Dark Horizontal +#define U_HSP_DashedDownwardDiagonal 0x0000001E //!< Dashed Downward Diagonal +#define U_HSP_DashedUpwardDiagonal 0x0000001F //!< Dashed Upward Diagonal +#define U_HSP_DashedHorizontal 0x00000020 //!< Dashed Horizontal +#define U_HSP_DashedVertical 0x00000021 //!< Dashed Vertical +#define U_HSP_SmallConfetti 0x00000022 //!< Small Confetti +#define U_HSP_LargeConfetti 0x00000023 //!< LargeC onfetti +#define U_HSP_ZigZag 0x00000024 //!< Zig Zag +#define U_HSP_Wave 0x00000025 //!< Wave +#define U_HSP_DiagonalBrick 0x00000026 //!< Diagonal Brick +#define U_HSP_HorizontalBrick 0x00000027 //!< Horizontal Brick +#define U_HSP_Weave 0x00000028 //!< Weave +#define U_HSP_Plaid 0x00000029 //!< Plaid +#define U_HSP_Divot 0x0000002A //!< Divot +#define U_HSP_DottedGrid 0x0000002B //!< DottedGrid +#define U_HSP_DottedDiamond 0x0000002C //!< DottedDiamond +#define U_HSP_Shingle 0x0000002D //!< Shingle +#define U_HSP_Trellis 0x0000002E //!< Trellis +#define U_HSP_Sphere 0x0000002F //!< Sphere +#define U_HSP_SmallGrid 0x00000030 //!< Small Grid +#define U_HSP_SmallCheckerBoard 0x00000031 //!< Small Checker Board +#define U_HSP_LargeCheckerBoard 0x00000032 //!< Large Checker Board +#define U_HSP_OutlinedDiamond 0x00000033 //!< Outlined Diamond +#define U_HSP_SolidDiamond 0x00000034 //!< Solid Diamond +/** @} */ + +/** \defgroup U_PMF_HKP_ PMF HotkeyPrefix Enumeration + For + EMF+ manual 2.1.1.14, Microsoft name: HotkeyPrefix Enumeration (U_HKP_*) + @{ +*/ +#define U_HKP_None 0x00 //!< No hot key prefix +#define U_HKP_Show 0x01 //!< Show hot key prefix +#define U_HKP_Hide 0x02 //!< Hide hot key prefix +/** @} */ + +/** \defgroup U_PMF_IDT_ PMF ImageDataType Enumeration + For + EMF+ manual 2.1.1.15, Microsoft name: ImageDataType Enumeration (U_IDT_*) + @{ +*/ +#define U_IDT_Unknown 0x00 //!< Unknown image data type +#define U_IDT_Bitmap 0x01 //!< Bitmap image data type +#define U_IDT_Metafile 0x02 //!< Metafile image data type +/** @} */ + +/** \defgroup U_PMF_IM_ PMF InterpolationMode Enumeration + For + EMF+ manual 2.1.1.16, Microsoft name: InterpolationMode Enumeration (U_IM_*) + @{ +*/ +#define U_IM_Default 0x00 //!< Default interpolation mode +#define U_IM_LowQuality 0x01 //!< Low Quality interpolation mode +#define U_IM_HighQuality 0x02 //!< High Quality interpolation mode +#define U_IM_Bilinear 0x03 //!< Bilinear interpolation mode +#define U_IM_Bicubic 0x04 //!< Bicubic interpolation mode +#define U_IM_NearestNeighbor 0x05 //!< Nearest Neighbor interpolation mode +#define U_IM_HighQualityBilinear 0x06 //!< High Quality Bilinear interpolation mode +#define U_IM_HighQualityBicubic 0x07 //!< High Quality Bicubic interpolation mode +/** @} */ + +/** \defgroup U_PMF_LID_ PMF LanguageIdentifier Enumeration + For + EMF+ manual 2.1.1.17, Microsoft name: LanguageIdentifier Enumeration (U_LID_*) + @{ +*/ +#define U_LID_LANG_NEUTRAL 0x0000 //!< LANG_NEUTRAL +#define U_LID_zh_CHS 0x0004 //!< zh_CHS +#define U_LID_LANG_INVARIANT 0x007F //!< LANG_INVARIANT +#define U_LID_LANG_NEUTRAL_USER_DEFAULT 0x0400 //!< LANG_NEUTRAL_USER_DEFAULT +#define U_LID_ar_SA 0x0401 //!< ar_SA +#define U_LID_bg_BG 0x0402 //!< bg_BG +#define U_LID_ca_ES 0x0403 //!< ca_ES +#define U_LID_zh_CHT 0x0404 //!< zh_CHT +#define U_LID_cs_CZ 0x0405 //!< cs_CZ +#define U_LID_da_DK 0x0406 //!< da_DK +#define U_LID_de_DE 0x0407 //!< de_DE +#define U_LID_el_GR 0x0408 //!< el_GR +#define U_LID_en_US 0x0409 //!< en_US +#define U_LID_es_Tradnl_ES 0x040A //!< es_Tradnl_ES +#define U_LID_fi_FI 0x040B //!< fi_FI +#define U_LID_fr_FR 0x040C //!< fr_FR +#define U_LID_he_IL 0x040D //!< he_IL +#define U_LID_hu_HU 0x040E //!< hu_HU +#define U_LID_is_IS 0x040F //!< is_IS +#define U_LID_it_IT 0x0410 //!< it_IT +#define U_LID_ja_JA 0x0411 //!< ja_JA +#define U_LID_ko_KR 0x0412 //!< ko_KR +#define U_LID_nl_NL 0x0413 //!< nl_NL +#define U_LID_nb_NO 0x0414 //!< nb_NO +#define U_LID_pl_PL 0x0415 //!< pl_PL +#define U_LID_pt_BR 0x0416 //!< pt_BR +#define U_LID_rm_CH 0x0417 //!< rm_CH +#define U_LID_ro_RO 0x0418 //!< ro_RO +#define U_LID_ru_RU 0x0419 //!< ru_RU +#define U_LID_hr_HR 0x041A //!< hr_HR +#define U_LID_sk_SK 0x041B //!< sk_SK +#define U_LID_sq_AL 0x041C //!< sq_AL +#define U_LID_sv_SE 0x041D //!< sv_SE +#define U_LID_th_TH 0x041E //!< th_TH +#define U_LID_tr_TR 0x041F //!< tr_TR +#define U_LID_ur_PK 0x0420 //!< ur_PK +#define U_LID_id_ID 0x0421 //!< id_ID +#define U_LID_uk_UA 0x0422 //!< uk_UA +#define U_LID_be_BY 0x0423 //!< be_BY +#define U_LID_sl_SI 0x0424 //!< sl_SI +#define U_LID_et_EE 0x0425 //!< et_EE +#define U_LID_lv_LV 0x0426 //!< lv_LV +#define U_LID_lt_LT 0x0427 //!< lt_LT +#define U_LID_tg_TJ 0x0428 //!< tg_TJ +#define U_LID_fa_IR 0x0429 //!< fa_IR +#define U_LID_vi_VN 0x042A //!< vi_VN +#define U_LID_hy_AM 0x042B //!< hy_AM +#define U_LID_az_Latn_AZ 0x042C //!< az_Latn_AZ +#define U_LID_eu_ES 0x042D //!< eu_ES +#define U_LID_wen_DE 0x042E //!< wen_DE +#define U_LID_mk_MK 0x042F //!< mk_MK +#define U_LID_st_ZA 0x0430 //!< st_ZA +#define U_LID_tn_ZA 0x0432 //!< tn_ZA +#define U_LID_xh_ZA 0x0434 //!< xh_ZA +#define U_LID_zu_ZA 0x0435 //!< zu_ZA +#define U_LID_af_ZA 0x0436 //!< af_ZA +#define U_LID_ka_GE 0x0437 //!< ka_GE +#define U_LID_fa_FA 0x0438 //!< fa_FA +#define U_LID_hi_IN 0x0439 //!< hi_IN +#define U_LID_mt_MT 0x043A //!< mt_MT +#define U_LID_se_NO 0x043B //!< se_NO +#define U_LID_ga_GB 0x043C //!< ga_GB +#define U_LID_ms_MY 0x043E //!< ms_MY +#define U_LID_kk_KZ 0x043F //!< kk_KZ +#define U_LID_ky_KG 0x0440 //!< ky_KG +#define U_LID_sw_KE 0x0441 //!< sw_KE +#define U_LID_tk_TM 0x0442 //!< tk_TM +#define U_LID_uz_Latn_UZ 0x0443 //!< uz_Latn_UZ +#define U_LID_tt_Ru 0x0444 //!< tt_Ru +#define U_LID_bn_IN 0x0445 //!< bn_IN +#define U_LID_pa_IN 0x0446 //!< pa_IN +#define U_LID_gu_IN 0x0447 //!< gu_IN +#define U_LID_or_IN 0x0448 //!< or_IN +#define U_LID_ta_IN 0x0449 //!< ta_IN +#define U_LID_te_IN 0x044A //!< te_IN +#define U_LID_kn_IN 0x044B //!< kn_IN +#define U_LID_ml_IN 0x044C //!< ml_IN +#define U_LID_as_IN 0x044D //!< as_IN +#define U_LID_mr_IN 0x044E //!< mr_IN +#define U_LID_sa_IN 0x044F //!< sa_IN +#define U_LID_mn_MN 0x0450 //!< mn_MN +#define U_LID_bo_CN 0x0451 //!< bo_CN +#define U_LID_cy_GB 0x0452 //!< cy_GB +#define U_LID_km_KH 0x0453 //!< km_KH +#define U_LID_lo_LA 0x0454 //!< lo_LA +#define U_LID_gl_ES 0x0456 //!< gl_ES +#define U_LID_kok_IN 0x0457 //!< kok_IN +#define U_LID_sd_IN 0x0459 //!< sd_IN +#define U_LID_syr_SY 0x045A //!< syr_SY +#define U_LID_si_LK 0x045B //!< si_LK +#define U_LID_iu_Cans_CA 0x045D //!< iu_Cans_CA +#define U_LID_am_ET 0x045E //!< am_ET +#define U_LID_ne_NP 0x0461 //!< ne_NP +#define U_LID_fy_NL 0x0462 //!< fy_NL +#define U_LID_ps_AF 0x0463 //!< ps_AF +#define U_LID_fil_PH 0x0464 //!< fil_PH +#define U_LID_div_MV 0x0465 //!< div_MV +#define U_LID_ha_Latn_NG 0x0468 //!< ha_Latn_NG +#define U_LID_yo_NG 0x046A //!< yo_NG +#define U_LID_quz_BO 0x046B //!< quz_BO +#define U_LID_nzo_ZA 0x046C //!< nzo_ZA +#define U_LID_ba_RU 0x046D //!< ba_RU +#define U_LID_lb_LU 0x046E //!< lb_LU +#define U_LID_kl_GL 0x046F //!< kl_GL +#define U_LID_ig_NG 0x0470 //!< ig_NG +#define U_LID_so_SO 0x0477 //!< so_SO +#define U_LID_ii_CN 0x0478 //!< ii_CN +#define U_LID_arn_CL 0x047A //!< arn_CL +#define U_LID_moh_CA 0x047C //!< moh_CA +#define U_LID_br_FR 0x047E //!< br_FR +#define U_LID_ug_CN 0x0480 //!< ug_CN +#define U_LID_ mi_NZ 0x0481 //!< mi_NZ +#define U_LID_oc_FR 0x0482 //!< oc_FR +#define U_LID_co_FR 0x0483 //!< co_FR +#define U_LID_gsw_FR 0x0484 //!< gsw_FR +#define U_LID_sah_RU 0x0485 //!< sah_RU +#define U_LID_qut_GT 0x0486 //!< qut_GT +#define U_LID_rw_RW 0x0487 //!< rw_RW +#define U_LID_wo_SN 0x0488 //!< wo_SN +#define U_LID_gbz_AF 0x048C //!< gbz_AF +#define U_LID_LANG_NEUTRAL_SYS_DEFAULT 0x0800 //!< LANG_NEUTRAL_SYS_DEFAULT +#define U_LID_ar_IQ 0x0801 //!< ar_IQ +#define U_LID_zh_CN 0x0804 //!< zh_CN +#define U_LID_de_CH 0x0807 //!< de_CH +#define U_LID_en_GB 0x0809 //!< en_GB +#define U_LID_es_MX 0x080A //!< es_MX +#define U_LID_fr_BE 0x080C //!< fr_BE +#define U_LID_it_CH 0x0810 //!< it_CH +#define U_LID_ko_Johab_KR 0x0812 //!< ko_Johab_KR +#define U_LID_nl_BE 0x0813 //!< nl_BE +#define U_LID_nn_NO 0x0814 //!< nn_NO +#define U_LID_pt_PT 0x0816 //!< pt_PT +#define U_LID_sr_Latn_SP 0x081A //!< sr_Latn_SP +#define U_LID_sv_FI 0x081D //!< sv_FI +#define U_LID_ur_IN 0x0820 //!< ur_IN +#define U_LID_lt_C_LT 0x0827 //!< lt_C_LT +#define U_LID_az_Cyrl_AZ 0x082C //!< az_Cyrl_AZ +#define U_LID_wee_DE 0x082E //!< wee_DE +#define U_LID_se_SE 0x083B //!< se_SE +#define U_LID_ga_IE 0x083C //!< ga_IE +#define U_LID_ms_BN 0x083E //!< ms_BN +#define U_LID_uz_Cyrl_UZ 0x0843 //!< uz_Cyrl_UZ +#define U_LID_bn_BD 0x0845 //!< bn_BD +#define U_LID_mn_Mong_CN 0x0850 //!< mn_Mong_CN +#define U_LID_sd_PK 0x0859 //!< sd_PK +#define U_LID_iu_Latn_CA 0x085D //!< iu_Latn_CA +#define U_LID_tzm_Latn_DZ 0x085F //!< tzm_Latn_DZ +#define U_LID_quz_EC 0x086B //!< quz_EC +#define U_LID_LANG_NEUTRAL_CUSTOM_DEFAULT 0x0C00 //!< LANG_NEUTRAL_CUSTOM_DEFAULT +#define U_LID_ar_EG 0x0C01 //!< ar_EG +#define U_LID_zh_HK 0x0C04 //!< zh_HK +#define U_LID_de_AT 0x0C07 //!< de_AT +#define U_LID_en_AU 0x0C09 //!< en_AU +#define U_LID_es_ES 0x0C0A //!< es_ES +#define U_LID_fr_CA 0x0C0C //!< fr_CA +#define U_LID_sr_Cyrl_CS 0x0C1A //!< sr_Cyrl_CS +#define U_LID_se_FI 0x0C3B //!< se_FI +#define U_LID_quz_PE 0x0C6B //!< quz_PE +#define U_LID_LANG_NEUTRAL_CUSTOM 0x1000 //!< LANG_NEUTRAL_CUSTOM +#define U_LID_ar_LY 0x1001 //!< ar_LY +#define U_LID_zh_SG 0x1004 //!< zh_SG +#define U_LID_de_LU 0x1007 //!< de_LU +#define U_LID_en_CA 0x1009 //!< en_CA +#define U_LID_es_GT 0x100A //!< es_GT +#define U_LID_fr_CH 0x100C //!< fr_CH +#define U_LID_hr_BA 0x101A //!< hr_BA +#define U_LID_smj_NO 0x103B //!< smj_NO +#define U_LID_LANG_NEUTRAL_CUSTOM_DEFAULT_MUI 0x1400 //!< LANG_NEUTRAL_CUSTOM_DEFAULT_MUI +#define U_LID_ar_DZ 0x1401 //!< ar_DZ +#define U_LID_zh_MO 0x1404 //!< zh_MO +#define U_LID_de_LI 0x1407 //!< de_LI +#define U_LID_en_NZ 0x1409 //!< en_NZ +#define U_LID_es_CR 0x140A //!< es_CR +#define U_LID_fr_LU 0x140C //!< fr_LU +#define U_LID_bs_Latn_BA 0x141A //!< bs_Latn_BA +#define U_LID_smj_SE 0x143B //!< smj_SE +#define U_LID_ar_MA 0x1801 //!< ar_MA +#define U_LID_en_IE 0x1809 //!< en_IE +#define U_LID_es_PA 0x180A //!< es_PA +#define U_LID_ar_MC 0x180C //!< ar_MC +#define U_LID_sr_Latn_BA 0x181A //!< sr_Latn_BA +#define U_LID_sma_NO 0x183B //!< sma_NO +#define U_LID_ar_TN 0x1C01 //!< ar_TN +#define U_LID_en_ZA 0x1C09 //!< en_ZA +#define U_LID_es_DO 0x1C0A //!< es_DO +#define U_LID_sr_Cyrl_BA 0x1C1A //!< sr_Cyrl_BA +#define U_LID_sma_SE 0x1C3B //!< sma_SE +#define U_LID_ar_OM 0x2001 //!< ar_OM +#define U_LID_el_2_GR 0x2008 //!< el_2_GR +#define U_LID_en_JM 0x2009 //!< en_JM +#define U_LID_es_VE 0x200A //!< es_VE +#define U_LID_bs_Cyrl_BA 0x201A //!< bs_Cyrl_BA +#define U_LID_sms_FI 0x203B //!< sms_FI +#define U_LID_ar_YE 0x2401 //!< ar_YE +#define U_LID_ar_029 0x2409 //!< ar_029 +#define U_LID_es_CO 0x240A //!< es_CO +#define U_LID_smn_FI 0x243B //!< smn_FI +#define U_LID_ar_SY 0x2801 //!< ar_SY +#define U_LID_en_BZ 0x2809 //!< en_BZ +#define U_LID_es_PE 0x280A //!< es_PE +#define U_LID_ar_JO 0x2C01 //!< ar_JO +#define U_LID_en_TT 0x2C09 //!< en_TT +#define U_LID_es_AR 0x2C0A //!< es_AR +#define U_LID_ar_LB 0x3001 //!< ar_LB +#define U_LID_en_ZW 0x3009 //!< en_ZW +#define U_LID_es_EC 0x300A //!< es_EC +#define U_LID_ar_KW 0x3401 //!< ar_KW +#define U_LID_en_PH 0x3409 //!< en_PH +#define U_LID_es_CL 0x340A //!< es_CL +#define U_LID_ar_AE 0x3801 //!< ar_AE +#define U_LID_es_UY 0x380A //!< es_UY +#define U_LID_ar_BH 0x3C01 //!< ar_BH +#define U_LID_es_PY 0x3C0A //!< es_PY +#define U_LID_ar_QA 0x4001 //!< ar_QA +#define U_LID_en_IN 0x4009 //!< en_IN +#define U_LID_es_BO 0x400A //!< es_BO +#define U_LID_en_MY 0x4409 //!< en_MY +#define U_LID_es_SV 0x440A //!< es_SV +#define U_LID_en_SG 0x4809 //!< en_SG +#define U_LID_es_HN 0x480A //!< es_HN +#define U_LID_es_NI 0x4C0A //!< es_NI +#define U_LID_es_PR 0x500A //!< es_PR +#define U_LID_es_US 0x540A //!< es_US +#define U_LID_zh_Hant 0x7C04 //!< zh_Hant +#define U_LID_SEC_MASK 0xFB00 //!< Mask for region part of LID +#define U_LID_PRI_MASK 0x03FF //!< MASK for languagepart of LID +/** @} */ + +/** \defgroup U_PMF_LCT_ PMF LineCapType Enumeration + For + EMF+ manual 2.1.1.18, Microsoft name: LineCapType Enumeration (U_LCT_*) + @{ +*/ +#define U_LCT_Flat 0x00 //!< Flat line cap +#define U_LCT_Square 0x01 //!< Square line cap +#define U_LCT_Round 0x02 //!< Round line cap +#define U_LCT_Triangle 0x03 //!< Triangle line cap +#define U_LCT_NoAnchor 0x10 //!< No Anchor line cap +#define U_LCT_SquareAnchor 0x11 //!< Square Anchor line cap +#define U_LCT_RoundAnchor 0x12 //!< Round Anchor line cap +#define U_LCT_DiamondAnchor 0x13 //!< Diamond Anchor line cap +#define U_LCT_ArrowAnchor 0x14 //!< Arrow Anchor line cap +#define U_LCT_AnchorMask 0xF0 //!< Ancho rMask line cap +#define U_LCT_Custom 0xFF //!< Custom line cap +/** @} */ + +/** \defgroup U_PMF_LJT_ PMF LineJoinType Enumeration + For + EMF+ manual 2.1.1.19, Microsoft name: LineJoinType Enumeration (U_LJT_*) + @{ +*/ +#define U_LJT_Miter 0x00 //!< Miter line join +#define U_LJT_Bevel 0x01 //!< Bevel line join +#define U_LJT_Round 0x02 //!< Round line join +#define U_LJT_MiterClipped 0x03 //!< Miter Clipped line join +/** @} */ + +/** \defgroup U_PMF_LS_ PMF LineStyle Enumeration + For + EMF+ manual 2.1.1.20, Microsoft name: LineStyle Enumeration (U_LS_*) + @{ +*/ +#define U_LS_Solid 0x00 //!< Solid line +#define U_LS_Dash 0x01 //!< Dashed line +#define U_LS_Dot 0x02 //!< Dotted line +#define U_LS_DashDot 0x03 //!< Dash Dot line +#define U_LS_DashDotDot 0x04 //!< Dash Dot Dot line +#define U_LS_Custom 0x05 //!< Custom line +/** @} */ + +/** \defgroup U_PMF_MDT_ PMF MetafileDataType Enumeration + For + EMF+ manual 2.1.1.21, Microsoft name: MetafileDataType Enumeration (U_MDT_*) + @{ +*/ +#define U_MDT_Wmf 0x01 //!< WMF metafile +#define U_MDT_WmfPlaceable 0x02 //!< WMF placeable metafile +#define U_MDT_Emf 0x03 //!< EMF metafile +#define U_MDT_EmfPlusOnly 0x04 //!< EMF+ single mode metafile +#define U_MDT_EmfPlusDual 0x05 //!< EMF+ dual mode metafile +/** @} */ + +/** \defgroup U_PMF_OT_ PMF ObjectType Enumeration + For + EMF+ manual 2.1.1.22, Microsoft name: ObjectType Enumeration (U_OT_*) + @{ +*/ +#define U_OT_Invalid 0x00 //!< Invalid object +#define U_OT_Brush 0x01 //!< Brush object +#define U_OT_Pen 0x02 //!< Pen object +#define U_OT_Path 0x03 //!< Path object +#define U_OT_Region 0x04 //!< Region object +#define U_OT_Image 0x05 //!< Image object +#define U_OT_Font 0x06 //!< Font object +#define U_OT_StringFormat 0x07 //!< StringFormat object +#define U_OT_ImageAttributes 0x08 //!< ImageAttributes object +#define U_OT_CustomLineCap 0x09 //!< CustomLineCap object +/** @} */ + +/** \defgroup U_PMF_PPT_ PMF PathPointType Enumeration + For + EMF+ manual 2.1.1.23, Microsoft name: PathPointType Enumeration (U_PPT_*) + @{ +*/ +#define U_PPT_Start 0x00 //!< Start of path +#define U_PPT_Line 0x01 //!< Line path +#define U_PPT_Bezier 0x03 //!< Bezier path +#define U_PPT_MASK 0x0F //!< MASK for bits in flag +/** @} */ + +/** \defgroup U_PMF_PA_ PMF PenAlignment Enumeration + For + EMF+ manual 2.1.1.24, Microsoft name: PenAlignment Enumeration (U_PA_*) + @{ +*/ +#define U_PA_Center 0x00 //!< Center pen alignment +#define U_PA_Inset 0x01 //!< Inset pen alignment +#define U_PA_Left 0x02 //!< Left pen alignment +#define U_PA_Outset 0x03 //!< Outset pen alignment +#define U_PA_Right 0x04 //!< Right pen alignment +/** @} */ + +/** \defgroup U_PMF_PF_ PMF PixelFormat Enumeration + For U_PMF_BITMAP PxFormat field + EMF+ manual 2.1.1.25, Microsoft name: PixelFormat Enumeration (U_PF_*) + + Bitmap for this 32 bit value is: + 0-9 ignored + 10 Set: 32 bit ARGB; Clear: !32 bit ARGB + 11 Set: 16 bits/channel; Clear: !16 bits + 12 Set: colors premultiplied by alpha; Clear: !premultiplied + 13 Set: has Alpha; Clear: !has Alpha + 14 Set: Windows GDI supports; Clear: !Windows GDI supports + 15 Set: uses LUT; Clear !uses LUT + 16-23 = total number of BITS per pixel + 24-31 = pixel format enumeration index (0->15) + @{ +*/ +#define U_PF_Undefined 0x00000000 //!< undefined Pixel Format +#define U_PF_1bppIndexed 0x00030101 //!< monochrome with LUT +#define U_PF_4bppIndexed 0x00030402 //!< 4 bit with LUT +#define U_PF_8bppIndexed 0x00030803 //!< 8 bit with LUT +#define U_PF_16bppGrayScale 0x00101004 //!< 16 bits grey values +#define U_PF_16bppRGB555 0x00021005 //!< 16 bit RGB values (5,5,5,(1 ignored)) +#define U_PF_16bppRGB565 0x00021006 //!< 16 bit RGB values (5,6,5) +#define U_PF_16bppARGB1555 0x00061007 //!< 16 bit ARGB values (1 alpha, 5,5,5 colors) +#define U_PF_24bppRGB 0x00021808 //!< 24 bit RGB values (8,8.8) +#define U_PF_32bppRGB 0x00022009 //!< 32 bit RGB value (8,8,8,(8 ignored)) +#define U_PF_32bppARGB 0x0026200A //!< 32 bit ARGB values (8 alpha,8,8,8) +#define U_PF_32bppPARGB 0x000E200B //!< 32 bit PARGB values (8,8,8,8, but RGB already multiplied by A) +#define U_PF_48bppRGB 0x0010300C //!< 48 bit RGB (16,16,16) +#define U_PF_64bppARGB 0x0034400D //!< 64 bit ARGB (16 alpha, 16,16,16) +#define U_PF_64bppPARGB 0x001A400E //!< 64 bit PARGB (16,16,16,16, but RGB already multiplied by A) +/** @} */ + +/** \defgroup U_PMF_POM_ PMF PixelOffsetMode Enumeration + For + EMF+ manual 2.1.1.26, Microsoft name: PixelOffsetMode Enumeration (U_POM_*) + @{ +*/ +#define U_POM_Default 0x00 //!< center at {0.0,0.0} +#define U_POM_HighSpeed 0x01 //!< center at {0.0,0.0} +#define U_POM_HighQuality 0x02 //!< center at {0.5,0.5} +#define U_POM_None 0x03 //!< center at {0.0,0.0} +#define U_POM_Half 0x04 //!< center at {0.5,0.5} +/** @} */ + +/** \defgroup U_PMF_RNDT_ PMF RegionNodeDataType Enumeration + For + EMF+ manual 2.1.1.27, Microsoft name: RegionNodeDataType Enumeration (U_RNDT_*) + @{ +*/ +#define U_RNDT_Kids 0x00000000 //!< One of the next 5 is to be applied +#define U_RNDT_And 0x00000001 //!< AND the child nodes +#define U_RNDT_Or 0x00000002 //!< OR the child nodes +#define U_RNDT_Xor 0x00000003 //!< XOR the child nodes +#define U_RNDT_Exclude 0x00000004 //!< Part of 1st child node not in 2nd child node +#define U_RNDT_Complement 0x00000005 //!< Part of 2nd child node not in 1st child node +#define U_RNDT_Rect 0x10000000 //!< Child node is a rectangle +#define U_RNDT_Path 0x10000001 //!< Child node is a path +#define U_RNDT_Empty 0x10000002 //!< Child node is empty +#define U_RNDT_Infinite 0x10000003 //!< Child node has infinite extent (?) +/** @} */ + +/** \defgroup U_PMF_SM_ PMF SmoothingMode Enumeration + For + EMF+ manual 2.1.1.28, Microsoft name: SmoothingMode Enumeration (U_SM_*) + @{ +*/ +#define U_SM_Default 0x00 //!< Default smoothing +#define U_SM_HighSpeed 0x01 //!< High Speed smoothing +#define U_SM_HighQuality 0x02 //!< High Quality smoothing +#define U_SM_None 0x03 //!< No smoothing +#define U_SM_AntiAlias8x4 0x04 //!< Anti Alias 8x4 smoothing +#define U_SM_AntiAlias8x8 0x05 //!< Anti Alias 8x8 smoothing +/** @} */ + +/** \defgroup U_PMF_SA_ PMF StringAlignment Enumeration + For + EMF+ manual 2.1.1.29, Microsoft name: StringAlignment Enumeration (U_SA_*) + + Note, that unlike EMF these are with respect to the bounding rectangle, not to a single point. So + to draw centered text, for instance, U_SA_Center must be used, and the bounding rectangle must also be + centered. + + For horizontal positioning of L->R text Near is all the way left in the box, Far is all the way right, + and Center puts the center of the text in the center of the box. + + For vertical positioning things are a little strange. Near is a certain distance down from the top, Far is a + certain distance up from the bottom, and center puts the center of the text in the center of the box. The + "certain distance" is not specified in the EMF+ documentation. See the function U_PMR_drawstring() for an + implementation that places text on the baseline. + @{ +*/ +#define U_SA_Near 0x00 //!< Position near +#define U_SA_Center 0x01 //!< Position center +#define U_SA_Far 0x02 //!< Position far +/** @} */ + +/** \defgroup U_PMF_SDS_ PMF StringDigitSubstitution Enumeration + For + EMF+ manual 2.1.1.30, Microsoft name: StringDigitSubstitution Enumeration (U_SDS_*) + @{ +*/ +#define U_SDS_User 0x00 //!< Digit substitution is set by implementation +#define U_SDS_None 0x01 //!< No Digit substitution +#define U_SDS_National 0x02 //!< Digit substitution by official locale +#define U_SDS_Traditional 0x03 //!< Digit substitution by traditional locale +/** @} */ + +/** \defgroup U_PMF_ST_ PMF StringTrimming Enumeration + For + EMF+ manual 2.1.1.31, Microsoft name: StringTrimming Enumeration (U_ST_*) + @{ +*/ +#define U_ST_None 0x00 //!< no string trimming +#define U_ST_Character 0x01 //!< Trim at Character +#define U_ST_Word 0x02 //!< Trim at Word +#define U_ST_EllipsisCharacter 0x03 //!< Trim at Ellipsis Character +#define U_ST_EllipsisWord 0x04 //!< Trim at Ellipsis Word +#define U_ST_EllipsisPath 0x05 //!< Trim at Ellipsis Path +/** @} */ + +/** \defgroup U_PMF_TRH_ PMF TextRenderingHint Enumeration + For + EMF+ manual 2.1.1.32, Microsoft name: TextRenderingHint Enumeration (U_TRH_*) + @{ +*/ +#define U_TRH_SystemDefault 0x00 //!< System Default +#define U_TRH_SingleBitPerPixelGridFit 0x01 //!< Single Bit Per Pixel Grid Fit +#define U_TRH_SingleBitPerPixel 0x02 //!< Single Bit Per Pixel +#define U_TRH_AntialiasGridFit 0x03 //!< Antialias Grid Fit +#define U_TRH_Antialias 0x04 //!< Antialias +#define U_TRH_ClearTypeGridFit 0x05 //!< ClearType Grid Fit +/** @} */ + +/** \defgroup U_PMF_UT_ PMF UnitType Enumeration + For + EMF+ manual 2.1.1.33, Microsoft name: UnitType Enumeration (U_UT_*) + @{ +*/ +#define U_UT_World 0x00 //!< World units +#define U_UT_Display 0x01 //!< Display units +#define U_UT_Pixel 0x02 //!< Pixel units +#define U_UT_Point 0x03 //!< Point units +#define U_UT_Inch 0x04 //!< Inch units +#define U_UT_Document 0x05 //!< Document units +#define U_UT_Millimeter 0x06 //!< Millimeter units +/** @} */ + +/** \defgroup U_PMF_WM_ PMF WrapMode Enumeration + For + EMF+ manual 2.1.1.34, Microsoft name: WrapMode Enumeration (U_WM_*) + @{ +*/ +#define U_WM_Tile 0x00000000 //!< Tile +#define U_WM_TileFlipX 0x00000001 //!< Reverse horizontally then tile +#define U_WM_TileFlipY 0x00000002 //!< Reverse vertically then tile +#define U_WM_TileFlipXY 0x00000003 //!< Reverse horizontally and vertically then tile +#define U_WM_Clamp 0x00000004 //!< Clamp pattern to the object boundary +/** @} */ + +/** \defgroup U_PMF_BD_ PMF BrushData Flags + For + EMF+ manual 2.1.2.1, Microsoft name: BrushData Flags (U_BD_*) + + Bit flags allowed in brush object types. Each bit indicates a type of object which is included. + There are 5 brush types abbreviated A through E, and each uses a subset of the + BrushData Flags, as summarized in the following table: + + Bits Brush____Type EMF+ Manual + used Abbrev. Name + 5 A U_PMF_LINEARGRADIENTBRUSHDATA 2.2.2.24 + 6 B U_PMF_PATHGRADIENTBRUSHDATA 2.2.2.29 + 3 C U_PMF_TEXTUREBRUSHDATA 2.2.2.45 + 0 D U_PMF_HATCHBRUSHDATA 2.2.2.20 + 0 E U_PMF_SOLIDBRUSHDATA 2.2.2.45 + @{ +*/ +#define U_BD_None 0x0000 //!< no bits set +#define U_BD_Path 0x0001 //!< Path, in {B} +#define U_BD_Transform 0x0002 //!< Transform in {ABC} +#define U_BD_PresetColors 0x0004 //!< PresetColors in {AB} +#define U_BD_BlendFactorsH 0x0008 //!< BlendFactorsH in {AB} +#define U_BD_BlendFactorsV 0x0010 //!< BlendFactorsV in {A} - Note, not actually implemented in GDI+. +#define U_BD_NoBit 0x0020 //!< unused bit +#define U_BD_FocusScales 0x0040 //!< Focus Scales in {B} +#define U_BD_IsGammaCorrected 0x0080 //!< GammaCorrected in {ABC} +#define U_BD_DoNotTransform 0x0100 //!< Ignore world to device transform in {C} +#define U_BD_MASKA 0x009E //!< all bits that MAY be set in A +#define U_BD_MASKB 0x00CF //!< all bits that MAY be set in B +#define U_BD_MASKC 0x0182 //!< all bits that MAY be set in C +/** @} */ + +/** \defgroup U_PMF_CLCD_ PMF CustomLineCapData Flags + For + EMF+ manual 2.1.2.2, Microsoft name: CustomLineCapData Flags (U_CLCD_*) + @{ +*/ +#define U_CLCD_None 0x00 //!< no bits set +#define U_CLCD_FillPath 0x01 //!< Fill Path +#define U_CLCD_LinePath 0x02 //!< Line Path +/** @} */ + +/** \defgroup U_PMF_DSO_ PMF DriverStringOptions Flags + For + EMF+ manual 2.1.2.3, Microsoft name: DriverStringOptions Flags (U_DSO_*) + @{ +*/ +#define U_DSO_None 0x00 //!< no bits set +#define U_DSO_CmapLookup 0x01 //!< Set: value is a Unicode character; Clear: value is an index into Glyph table in a font +#define U_DSO_Vertical 0x02 //!< Set: draw string verically; Clear: draw horizontally +#define U_DSO_RealizedAdvance 0x04 /**< Set: U_PMF_DRAWDRIVERSTRING Positions field specifies only position of first of Glyphs field, + with the rest calculated from font information; Clear: Positions specifies coordinates for each Glyphs member.*/ +#define U_DSO_LimitSubpixel 0x08 //!< Set: use less memory to cache anti-aliased glyphs; Clear: use more +/** @} */ + +/** \defgroup U_PMF_FS_ PMF FontStyle Flags + For + EMF+ manual 2.1.2.4, Microsoft name: FontStyle Flags (U_FS_*) +# @{ +*/ +#define U_FS_None 0x00 //!< no bits set +#define U_FS_Bold 0x01 //!< Bold +#define U_FS_Italic 0x02 //!< Italic +#define U_FS_Underline 0x04 //!< Underline +#define U_FS_Strikeout 0x08 //!< Strikeout +/** @} */ + +/** \defgroup U_PMF_PLTS_ PMF PaletteStyle Flags + For + EMF+ manual 2.1.2.5, Microsoft name: PaletteStyle Flags (U_PLTS_*) + @{ +*/ +#define U_PLTS_None 0x00 //!< no bits set +#define U_PLTS_HasAlpha 0x01 //!< Has Alpha +#define U_PLTS_GrayScale 0x02 //!< Gray Scale +#define U_PLTS_Halftone 0x04 //!< Halftone +/** @} */ + +/** \defgroup U_PMF_PTP_ PMF PathPointType Flags + For + EMF+ manual 2.1.2.6, Microsoft name: PathPointType Flags (U_PTP_*) + @{ +*/ +#define U_PTP_None 0x00 //!< no bits set +#define U_PTP_DashMode 0x10 //!< Dash Mode +#define U_PTP_PathMarker 0x20 //!< Path Marker +#define U_PTP_NoBit 0x40 //!< unused bit +#define U_PTP_CloseSubpath 0x80 //!< CloseSubpath +#define U_PTP_NotClose 0x70 //!< Everything but close +#define U_PTP_MASK 0xF0 //!< Everything +#define U_PTP_SHIFT 4 //!< offset to this bitfield +/** @} */ + +/** \defgroup U_PMF_PD_ PMF PenData Flags + For + EMF+ manual 2.1.2.7, Microsoft name: PenData Flags (U_PD_*) + +If bit is set the corresponding object must be specfied in the OptionalData field + + @{ +*/ +#define U_PD_None 0x0000 //!< no bits set +#define U_PD_Transform 0x0001 //!< Transform +#define U_PD_StartCap 0x0002 //!< Start Cap +#define U_PD_EndCap 0x0004 //!< End Cap +#define U_PD_Join 0x0008 //!< Join +#define U_PD_MiterLimit 0x0010 //!< Miter Limit +#define U_PD_LineStyle 0x0020 //!< Line Style +#define U_PD_DLCap 0x0040 //!< Dashed Line Cap +#define U_PD_DLOffset 0x0080 //!< Dashed Line Offset +#define U_PD_DLData 0x0100 //!< Dashed Line Data +#define U_PD_NonCenter 0x0200 //!< Alignment must be specified with optinal data +#define U_PD_CLData 0x0400 //!< Compound Line Data +#define U_PD_CustomStartCap 0x0800 //!< Custom Start Cap +#define U_PD_CustomEndCap 0x1000 //!< Custom End Cap +/** @} */ + +/** \defgroup U_PMF_SF_ PMF StringFormat Flags + For EmfPlusStringFormat + EMF+ manual 2.1.2.8, Microsoft name: StringFormat Flags (U_SF_*) + @{ +*/ +#define U_SF_None 0x00000000 //!< no bits set +#define U_SF_DirectionRightToLeft 0x00000001 //!< text Right to Left +#define U_SF_DirectionVertical 0x00000002 //!< text Left to Right +#define U_SF_NoFitBlackBox 0x00000004 //!< text not restricted to layout bbox +#define U_SF_NoBit4 0x00000008 //!< unused bit +#define U_SF_NoBit5 0x00000010 //!< unused bit +#define U_SF_DisplayFormatControl 0x00000020 //!< control codes display as "representative" glyphs +#define U_SF_NoBit7 0x00000040 //!< unused bit +#define U_SF_NoBit8 0x00000080 //!< unused bit +#define U_SF_NoBit9 0x00000100 //!< unused bit +#define U_SF_NoBit10 0x00000200 //!< unused bit +#define U_SF_NoFontFallback 0x00000400 //!< show as missing glyph if not in font +#define U_SF_MeasureTrailingSpaces 0x00000800 //!< trailing spaces included in line length +#define U_SF_NoWrap 0x00001000 //!< text does not wrap +#define U_SF_LineLimit 0x00002000 //!< emit whole lines if not clipped +#define U_SF_NoClip 0x00004000 //!< text is not clipped +#define U_SF_BypassGDI 0x80000000 //!< use implementation specific text rendering instead of GDI +/** @} */ + +/** \defgroup U_PMF_IE_ PMF ImageEffects Identifiers + For + EMF+ manual 2.1.3.1, Microsoft name: ImageEffects Identifiers (U_IE_*) + @{ +*/ +#define U_IE_BlurEffectGuid "{633C80A4-1843-482B-9EF2-BE2834C5FDD4}" //!< Blur Effect +#define U_IE_BrightnessContrastEffectGuid "{D3A1DBE1-8EC4-4C17-9F4C-EA97AD1C343D}" //!< Brightness Contrast Effect +#define U_IE_ColorBalanceEffectGuid "{537E597D-251E-48DA-9664-29CA496B70F8}" //!< Color Balance Effect +#define U_IE_ColorCurveEffectGuid "{DD6A0022-58E4-4A67-9D9B-D48EB881A53D}" //!< Color Curve Effect +#define U_IE_ColorLookupTableEffectGuid "{A7CE72A9-0F7F-40D7-B3CC-D0C02D5C3212}" //!< Color Lookup Table Effect +#define U_IE_ColorMatrixEffectGuid "{718F2615-7933-40E3-A511-5F68FE14DD74}" //!< Color Matrix Effect +#define U_IE_HueSaturationLightnessEffectGuid "{8B2DD6C3-EB07-4D87-A5F0-7108E26A9C5F}" //!< Hue Saturation Lightness Effect +#define U_IE_LevelsEffectGuid "{99C354EC-2A31-4F3A-8C34-17A803B33A25}" //!< Levels Effect +#define U_IE_RedEyeCorrectionEffectGuid "{74D29D05-69A4-4266-9549-3CC52836B632}" //!< Red Eye Correction Effect +#define U_IE_SharpenEffectGuid "{63CBF3EE-C526-402C-8F71-62C540BF5142}" //!< Sharpen Effect +#define U_IE_TintEffectGuid "{1077AF00-2848-4441-9489-44AD4C2D7A2C}" //!< Tint Effect +/** @} */ + +/** \defgroup U_PMF_IEE_ PMF ImageEffects Enumerators + based on U_IE_ + These may be used by a parser to set up for a switch() statement. + @{ +*/ +#define U_IEE_Unknown 0 //!< none of the following +#define U_IEE_BlurEffectGuid 1 //!< Blur Effect +#define U_IEE_BrightnessContrastEffectGuid 2 //!< Brightness Contrast Effect +#define U_IEE_ColorBalanceEffectGuid 3 //!< Color Balance Effect +#define U_IEE_ColorCurveEffectGuid 4 //!< Color Curve Effect +#define U_IEE_ColorLookupTableEffectGuid 5 //!< Color Lookup Table Effect +#define U_IEE_ColorMatrixEffectGuid 6 //!< Color Matrix Effect +#define U_IEE_HueSaturationLightnessEffectGuid 7 //!< Hue Saturation Lightness Effect +#define U_IEE_LevelsEffectGuid 8 //!< Levels Effect +#define U_IEE_RedEyeCorrectionEffectGuid 9 //!< Red Eye Correction Effect +#define U_IEE_SharpenEffectGuid 10 //!< Sharpen Effect +#define U_IEE_TintEffectGuid 11 //!< Tint Effect +/** @} */ + +/** \defgroup U_PMF_OC_ PMF ObjectClamp Identifiers + For U_PMF_IMAGEATTRIBUTES ObjectClamp field + EMF+ manual 2.2.1.5, Microsoft name: ImageEffects Identifiers (U_OC_*) + @{ +*/ +#define U_OC_Rect 0x00 //!< Clamp object to rectangle. +#define U_OC_Bitmap 0x01 //!< Clamp object to bitmap. +/** @} */ + +/** \defgroup U_PMF_PPF_ PMF PathPoint Flags + For U_PMF_PATH Flags field + For U_PMF_CMN_HDR Flags field + EMF+ manual 2.2.1.6, Microsoft name: PathPoint Flags (U_PPF_*) + For U_PMF_CMN_HDR Flags the bits are scattered all over the EMF+ manual. + NOTE: bitfields in manual are BIG endian and MSB 0. + This code reads the 16 bit flag field as LITTLE endian and uses LSB 0. + The values shown are AFTER the data has been read into a uint16_t and the byte order set + appropriately. + All of these come out of a 16 bit field. + @{ +*/ +#define U_PPF_B 0x8000 //!< 15 Set: BrushID is an U_PFM_ARGB; Clear: is index of U_PMF_BRUSH object in EMF+ object table. +#define U_PPF_BZ 0x8000 //!< 15 Set: Points are on a Bezier curve; Clear: Points are on a line +#define U_PPF_N 0x8000 //!< 15 Set: object definition continues in next record; Clear: this is the final object definition record +#define U_PPF_K 0x8000 //!< 15 Set: int16_t coordinates; Clear: use U_FLOAT coordinates +#define U_PPF_C 0x4000 //!< 14 Set: int16_t coordinates; Clear: use U_FLOAT coordinates +#define U_PPF_XM 0x2000 //!< 13 Set: Post multiply matrix; Clear: Pre multiply matrix +#define U_PPF_F 0x2000 //!< 13 Set: winding fill; Clear: alternate fill +#define U_PPF_E 0x2000 //!< 13 Set: effect from previous U_PMF_SERIALIZABLEOBJECT record will be applied,; Clear: no effect applied +#define U_PPF_R 0x1000 //!< 12 Set: U_PMF_PathPointTypeRLE and/or U_PMF_PathPointType objects; Clear: only U_PMF_PathPointType +#define U_PPF_P 0x0800 //!< 11 Set: relative coordinates; Clear absolute coordinates +#define U_PPF_D 0x0400 //!< 10 Set: draw path closed; Clear: draw path open +#define U_PPF_VGA 0x0002 //!< 1 Set: Palette is VGA basic colors; Clear: Palette is ??? +#define U_PPF_PP 0x0001 //!< 0 Set: Palette field is present; Clear: Palette field is absent +#define U_PPF_DM 0x0001 //!< 0 Set: Dual-mode file; Clear: EMF+ only file +#define U_PPF_AA 0x0001 //!< 0 Set: anti-aliasing on; Clear: anti-aliasing off +#define U_PPF_VIDEO 0x0001 //!< 0 Set: reference device is video display; Clear: reference devis is printer +/** @} */ + +/** \defgroup U_PMF_FF_ PMF Masks and offsets for 16 bit flag fields + Documenting the OBSERVED positions of fields in 16 bit flag integers + after they have been read in Little Ended from files. + + Note, some of these are used in more than one record type, only a single reference is provided + @{ +*/ + +#define U_FF_MASK_SUBLID 0x003F //!< EMF+ manual 2.2.2.23, Microsoft name: EmfPlusLanguageIdentifier +#define U_FF_SHFT_SUBLID 0x000A //!< EMF+ manual 2.2.2.23, Microsoft name: EmfPlusLanguageIdentifier +#define U_FF_MASK_PRILID 0x03FF //!< EMF+ manual 2.2.2.23, Microsoft name: EmfPlusLanguageIdentifier +#define U_FF_SHFT_PRILID 0x0000 //!< EMF+ manual 2.2.2.23, Microsoft name: EmfPlusLanguageIdentifier +#define U_FF_MASK_LID 0xFFFF //!< EMF+ manual 2.2.2.23, Microsoft name: EmfPlusLanguageIdentifier +#define U_FF_SHFT_LID 0x0000 //!< EMF+ manual 2.2.2.23, Microsoft name: EmfPlusLanguageIdentifier +#define U_FF_MASK_RL 0x003F //!< EMF+ manual 2.2.2.32, Microsoft name: EmfPlusPathPointTypeRLE +#define U_FF_SHFT_RL 0x0008 //!< EMF+ manual 2.2.2.32, Microsoft name: EmfPlusPathPointTypeRLE +#define U_FF_MASK_PPT 0x00FF //!< EMF+ manual 2.2.2.32, Microsoft name: EmfPlusPathPointTypeRLE +#define U_FF_SHFT_PPT 0x0000 //!< EMF+ manual 2.2.2.32, Microsoft name: EmfPlusPathPointTypeRLE +/* the next one is used most places an object ID is specified */ +#define U_FF_MASK_OID8 0x00FF //!< EMF+ manual 2.3.1.3, Microsoft name: EmfPlusSetClipPath +#define U_FF_SHFT_OID8 0x0000 //!< EMF+ manual 2.3.1.3, Microsoft name: EmfPlusSetClipPath +#define U_FF_MASK_CM4 0x000F //!< EMF+ manual 2.3.1.3, Microsoft name: EmfPlusSetClipPath +#define U_FF_SHFT_CM4 0x0008 //!< EMF+ manual 2.3.1.3, Microsoft name: EmfPlusSetClipPath +#define U_FF_MASK_OT 0x003F //!< EMF+ manual 2.3.5.1, Microsoft name: EmfPlusObject +#define U_FF_SHFT_OT 0x0008 //!< EMF+ manual 2.3.5.1, Microsoft name: EmfPlusObject +#define U_FF_MASK_AA 0x007F //!< EMF+ manual 2.3.6.1, Microsoft name: EmfPlusSetAntiAliasMode +#define U_FF_SHFT_AA 0x0001 //!< EMF+ manual 2.3.6.1, Microsoft name: EmfPlusSetAntiAliasMode +#define U_FF_MASK_CM 0x00FF //!< EMF+ manual 2.3.6.2, Microsoft name: EmfPlusSetCompositingMode +#define U_FF_SHFT_CM 0x0000 //!< EMF+ manual 2.3.6.2, Microsoft name: EmfPlusSetCompositingMode +#define U_FF_MASK_CQ 0x00FF //!< EMF+ manual 2.3.6.3, Microsoft name: EmfPlusSetCompositingQuality +#define U_FF_SHFT_CQ 0x0000 //!< EMF+ manual 2.3.6.3, Microsoft name: EmfPlusSetCompositingQuality +#define U_FF_MASK_IM 0x00FF //!< EMF+ manual 2.3.6.4, Microsoft name: EmfPlusSetInterpolationMode +#define U_FF_SHFT_IM 0x0000 //!< EMF+ manual 2.3.6.4, Microsoft name: EmfPlusSetInterpolationMode +#define U_FF_MASK_PxOffM 0x00FF //!< EMF+ manual 2.3.6.5, Microsoft name: EmfPlusSetPixelOffsetMode +#define U_FF_SHFT_PxOffM 0x0000 //!< EMF+ manual 2.3.6.5, Microsoft name: EmfPlusSetPixelOffsetMode +#define U_FF_MASK_TGC 0x0FFF //!< EMF+ manual 2.3.6.7, Microsoft name: EmfPlusSetTextContrast +#define U_FF_SHFT_TGC 0x0000 //!< EMF+ manual 2.3.6.7, Microsoft name: EmfPlusSetTextContrast +#define U_FF_MASK_TRH 0x00FF //!< EMF+ manual 2.3.6.8, Microsoft name: EmfPlusSetTextRenderingHint +#define U_FF_SHFT_TRH 0x0000 //!< EMF+ manual 2.3.6.8, Microsoft name: EmfPlusSetTextRenderingHint +#define U_FF_MASK_UT 0x00FF //!< EMF+ manual 2.3.7.1, Microsoft name: EmfPlusBeginContainer +#define U_FF_SHFT_UT 0x0008 //!< EMF+ manual 2.3.7.1, Microsoft name: EmfPlusBeginContainer +#define U_FF_MASK_TSC 0x7FFF //!< EMF+ manual 2.3.8.1, Microsoft name: EmfPlusSetTSClip +#define U_FF_SHFT_TSC 0x0000 //!< EMF+ manual 2.3.8.1, Microsoft name: EmfPlusSetTSClip +#define U_FF_MASK_PU 0x00FF //!< EMF+ manual 2.3.9.5, Microsoft name: EmfPlusSetPageTransform +#define U_FF_SHFT_PU 0x0000 //!< EMF+ manual 2.3.9.5, Microsoft name: EmfPlusSetPageTransform +/** @} */ + + +/** \defgroup U_PMF_GFVR_ PMF MetafileSignature + For U_PMF_GRAPHICSVERSION Signature field + EMF+ manual 2.2.2.19, Microsoft name: (none) (U_GFVR_*) + @{ +*/ +#define U_GFVR_PMF 0x000DBC01 //!< indicates an EMF+ metafile +#define U_GFVR_MASKHI 0xFFFFF000 //!< mask for the signature bit field (20 bits) +#define U_GFVR_MASKLO 0x00000FFF //!< mask for the version bit field (12 bits) +/** @} */ + +/** \defgroup U_PMF_XM_ PMF Matrix Multiplication Enumerator + For U_PMF_RotateWorldTransform and others + EMF+ manual 2.3.9.3, Microsoft name: (none) (U_XM_*) + @{ +*/ +#define U_XM_PostX 1 //!< Post Multiply change to current Transformation Matrix +#define U_XM_PreX 0 //!< Pre Multiply change to current Transformation Matrix +/** @} */ + + +/* Utility objects, not defined in EMF+ spec */ + +/** @brief Used to accumulate data for objects continued over multiple records. + see EMF+ manual 2.3.5.1 +*/ +typedef struct { + char *accum; /**< data accumulates here */ + uint32_t space; /**< bytes allocated */ + uint32_t used; /**< bytes in use */ + int Type; /**< ObjectType enumeration */ + int Id; /**< Object ID */ +} U_OBJ_ACCUM; + +/** @brief Holds EMF+ objects and records in EMF+ file format byte order. +*/ +typedef struct { + char *Data; /**< Buffer that hold's the PseudoObject's data */ + size_t Size; /**< Number of bytes allocated in Data (may be >Used if padding is present) */ + size_t Used; /**< Number of data bytes that are stored in Data */ + uint32_t Type; /**< Type numbers are from manual section: 1.2.3.4 -> 10203040 */ +} U_PSEUDO_OBJ; + +/** @brief DoublePseudoObject holds pairs of PseudoObjects. Used for constructing paths along with their types. + The data stored in the PsuedoObjects maintains LittleEndian-ness, as expected in the final file. + The type is U_RAW_OID, and there is no elements count at the beginning of Data +*/ +typedef struct { + uint32_t Elements; /**< Element count, applies to both PseudoObjects */ + U_PSEUDO_OBJ *poPoints; /**< Points in path */ + U_PSEUDO_OBJ *poTypes; /**< Types of points in path */ +} U_DPSEUDO_OBJ; + +/** @brief Serializer description records. + +An array of these are passed to U_PMF_SERIAL_set() to construct EMF+ objects from their component parts. +The U_PMF_SERIAL_set() function should not ever be called directly by end user code. +*/ +typedef struct { + const void *Ptr; /**< Pointer to the first byte of the data field. + Each data field is an array of a basic type of Units + bytes repeated Reps times */ + size_t Units; /**< Number of bytes in each unit of each data field. */ + size_t Reps; /**< Number of repeats of Units in each data field. */ + int TE; /**< (Target Endian). Only relevant for Units of 2 or 4*/ +} U_SERIAL_DESC; + +/** @brief FontInfoParams hold font information that is needed by U_PMR_drawstring so that it can + place text on the baseline. This must be extracted from the font file using + an appropriate utility. (See testbed_pmf.c for a table of these values for some + common fonts.) +*/ +typedef struct { + char *name; /**< Font name (like "Arial") */ + int Ascent; /**< in Font units (positive) */ + int Descent; /**< in Font units (negative) */ + int LineGap; /**< in Font units (positive) */ + int EmSize; /**< Y extent of Em square, usually 2048 */ + int yMax; /**< in Font units (positive) */ + int yMin; /**< in Font units (negative) */ +} U_FontInfoParams; + + + +/* EMF+ objects */ + +/** @brief EMF+ manual 2.2.1.1, Microsoft name: EmfPlusBrush Object + +variable part of object follows structure: + uint32_t Data[]; // one of the 5 types of Brush data (2.2.2 20, 24, 29, 43, or 45) +*/ +typedef struct { + uint32_t Version; //!< EmfPlusGraphicsVersion object + uint32_t Type; //!< BrushType Enumeration +} U_PMF_BRUSH; + +/** @brief EMF+ manual 2.2.1.2, Microsoft name: EmfPlusCustomLineCap Object */ +typedef struct { +/*@{*/ + uint32_t Version; //!< EmfPlusGraphicsVersion object + uint32_t Type; //!< BrushType Enumeration +/* variable part of object, not part of structure + uint32_t Data[]; //!< one of the 2 types of Linecap data (2.2.2 12, 13) +*/ +/*@}*/ +} U_PMF_CUSTOMLINECAP; + +/** @brief EMF+ manual 2.2.1.3, Microsoft name: EmfPlusFont Object */ +typedef struct { +/*@{*/ + uint32_t Version; //!< EmfPlusGraphicsVersion object + U_FLOAT EmSize; //!< em size in units of SizeUnit + uint32_t SizeUnit; //!< UnitType enumeration + int32_t FSFlags; //!< FontStyle flags + uint32_t Reserved; //!< ignored + uint32_t Length; //!< Number of Unicode Characters in FamilyName +/* variable part of object, not part of structure + uint16_t FamilyName[]; //!< Unicode (UTF-16LE) name of font family +*/ +/*@}*/ +} U_PMF_FONT; + +/** @brief EMF+ manual 2.2.1.4, Microsoft name: EmfPlusImage Object */ +typedef struct { +/*@{*/ + uint32_t Version; //!< EmfPlusGraphicsVersion object + uint32_t Type; //!< ImageDataType Enumeration +/* variable part of object, not part of structure + uint32_t Data[]; //!< one of the 2 types of image data (2.2.2 2 or 27) +*/ +/*@}*/ +} U_PMF_IMAGE; + +/** @brief EMF+ manual 2.2.2.1, Microsoft name: EmfPlusARGB Object, out of order, needed for 2.2.1.5 */ +typedef struct { +/*@{*/ + uint8_t Blue; //!< Blue color (0-255) + uint8_t Green; //!< Green color (0-255) + uint8_t Red; //!< Red color (0-255) + uint8_t Alpha; //!< Alpha (0-255) +/*@}*/ +} U_PMF_ARGB; + +/** @brief EMF+ manual 2.2.1.5, Microsoft name: EmfPlusImageAttributes Object */ +typedef struct { + /*@{*/ + uint32_t Version; //!< EmfPlusGraphicsVersion object + uint32_t Reserved1; //!< ignored + uint32_t WrapMode; //!< WrapMode object + U_PMF_ARGB ClampColor; //!< EmfPlusARGB object + int32_t ObjectClamp; //!< ObjectClamp Identifiers + uint32_t Reserved2; //!< ignored +/*@}*/ +} U_PMF_IMAGEATTRIBUTES; + +/** @brief EMF+ manual 2.2.1.6, Microsoft name: EmfPlusPath Object */ +typedef struct { +/*@{*/ + uint32_t Version; //!< EmfPlusGraphicsVersion object + uint32_t Count; //!< points and point types in this object + uint16_t Flags; //!< PathPoint Flags +/* variable part of object, not part of structure + points array of points like: + U_PPF_P U_PPF_C Type + 1 x U_PMF_POINTR + 0 1 U_PMF_POINT + 0 0 U_PMF_POINTF + types array of:. + U_PPF_R Type + 1 U_PMF_PATHPOINTTYPERLE and/or U_PMF_PATHPOINTTYPE + 0 U_PMF_PathPointType (only) + alignment padding up to 3 bytes +*/ +/*@}*/ +} U_PMF_PATH; + +/** @brief EMF+ manual 2.2.1.7, Microsoft name: EmfPlusPen Object */ + +typedef struct { + uint32_t Version; //!< EmfPlusGraphicsVersion object + uint32_t type; //!< must be zero +/* variable part of object, not part of structure + U_PMF_PENDATA pen + U_PMF_BRUSH brush +*/ +} U_PMF_PEN; + +/** @brief EMF+ manual 2.2.2.40, Microsoft name: EmfPlusRegionNode Object, out of order, needed for 2.2.1.8 */ +typedef struct { + uint32_t Type; //!< RegionNodeDataType +/* variable part of object, not part of structure, will be absent in object for some types + data data is a tree made up of some combination of these objects + U_PMF_REGIONNODEPATH 2.2.2.42 terminal node + U_PMF_RECTF 2.2.2.39 terminal node + U_PMF_REGIONNODECHILDNODES 2.2.2.41 non-terminal node +*/ +} U_PMF_REGIONNODE; + +/** @brief EMF+ manual 2.2.1.8, Microsoft name: EmfPlusRegion Object */ +typedef struct { + uint32_t Version; //!< EmfPlusGraphicsVersion object + uint32_t Elements; //!< Number of members in Nodes array +/* variable part of object, not part of structure, will be absent in object for some types + U_PMF_REGIONNODE Nodes[1]; //!< Nodes defining region +*/ +} U_PMF_REGION; + +/** @brief EMF+ manual 2.2.2.23, Microsoft name: EmfPlusLanguageIdentifier Object, out of order, needed for 2.2.1.9 + +Bit fields are not used in structs in this implementation, these are serialized/deserialized in +the corresponding routines. Bitfields in the FILE (LITTLE endian here, manual uses BIG endian) are: + int SubLId : 6; Example: code for USA + int PriLId : 10; Example: code for English + +This type is defined as 16 bits in the manual section, but it is only ever used as part of a 32 bit field! +*/ +typedef uint32_t U_PMF_LANGUAGEIDENTIFIER; + +/** @brief EMF+ manual 2.2.1.9, Microsoft name: EmfPlusStringFormat Object */ +typedef struct { + uint32_t Version; //!< EmfPlusGraphicsVersion object + uint32_t Flags; //!< StringFormat flags + U_PMF_LANGUAGEIDENTIFIER + Language; //!< String's Language + uint32_t StringAlignment; //!< StringAlignment enumeration. + uint32_t LineAlign; //!< StringAlignment enumeration. + uint32_t DigitSubstitution; //!< StringDigitSubstitution enumeration + U_PMF_LANGUAGEIDENTIFIER + DigitLanguage; //!< Digit's Language (overrides Language, above) + U_FLOAT FirstTabOffset; //!< the number of spaces to the first tab stop. + int32_t HotkeyPrefix; //!< HotkeyPrefix enumeration + U_FLOAT LeadingMargin; //!< space before starting position (text) of a string + U_FLOAT TrailingMargin; //!< space after last position (text) of a string + U_FLOAT Tracking; //!< horizontal space alotted per character/font specification per character + uint32_t Trimming; //!< StringTrimming enumeration + uint32_t TabStopCount; //!< Number of tab stops in data field. + uint32_t RangeCount; //!< Number of U_PMF_CHARACTERRANGE objects in data field. +/* variable part of object, not part of structure. + U_PMF_STRINGFORMATDATA data + + Note that U_PMF_STRINGFORMATDATA has no struct as it is entirely variable + and the size of the two fields in it are specified by the two preceding fields in this object type. +*/ +} U_PMF_STRINGFORMAT; + +/** U_PMF_ARGB EMF+ manual 2.2.2.1, Microsoft name: EmfPlusARGB Object, defined above, before 2.2.1.6*/ + +/** @brief EMF+ manual 2.2.2.2, Microsoft name: EmfPlusBitmap Object */ +typedef struct { + int32_t Width; //!< Width in pixels + int32_t Height; //!< Height in pixels + int32_t Stride; //!< length in bytes of 1 scan line (multiple of 4) + uint32_t PxFormat; //!< PixelFormat enumeration + uint32_t Type; //!< BitmapDataType enumeration (section 2.1.1.2). +/* variable part of object, not part of structure. + (various types) BitmapData //!< is either an U_PMF_BITMAPDATA or U_PMF_COMPRESSEDIMAGE object +*/ +} U_PMF_BITMAP; + +/** U_PMF_BITMAPDATA EMF+ manual 2.2.2.3, Microsoft name: EmfPlusBitmapData Object +U_PMF_BITMAPDATA is an entirely variable object, there is no corresponding struct. It consists of + + Colors U_PMF_PALETTE object + PixelData An array of bytes, meaning depends on fields in U_PMF_BITMAP object and the PixelFormat enumeration. + +*/ + +/** @brief EMF+ manual 2.2.2.4, Microsoft name: EmfPlusBlendColors Object + For Pattern field of U_PMF_LINEARGRADIENTBRUSHOPTIONALDATA +*/ +typedef struct { + uint32_t Elements; //!< members in each array +/* variable part of object, not part of structure. + U_FLOAT Positions //!< positions along gradient line. The first position MUST be 0.0 and the last MUST be 1.0. + U_PMF_ARGB Colors //!< colors at positions on gradient line +*/ +} U_PMF_BLENDCOLORS; + +/** @brief EMF+ manual 2.2.2.5, Microsoft name: EmfPlusBlendFactors Object */ +typedef struct { + uint32_t Elements; //!< Members in each array +/* variable part of object, not part of structure. + U_FLOAT Positions //!< positions along gradient line. The first position MUST be 0.0 and the last MUST be 1.0. + U_FLOAT Factors //!< blending factors, 0.0->1.0 values, inclusive +*/ +} U_PMF_BLENDFACTORS; + +/** @brief EMF+ manual 2.2.2.6, Microsoft name: EmfPlusBoundaryPathData Object */ +typedef struct { + int32_t Size; //!< Bytes in Data +/* variable part of object, not part of structure. + U_PMF_PATH Data //!< Boundary of the brush +*/ +} U_PMF_BOUNDARYPATHDATA; + +/** @brief EMF+ manual 2.2.2.7, Microsoft name: EmfPlusBoundaryPointData Object */ +typedef struct { + int32_t Elements; //!< Members in the array +/* variable part of object, not part of structure. + U_PMF_POINTF Points //!< Boundary of the brush +*/ +} U_PMF_BOUNDARYPOINTDATA; + +/** @brief EMF+ manual 2.2.2.8, Microsoft name: EmfPlusCharacterRange Object */ +typedef struct { + int32_t First; //!< First position in range + int32_t Length; //!< Range length +} U_PMF_CHARACTERRANGE; + +/** @brief EMF+ manual 2.2.2.9, Microsoft name: EmfPlusCompoundLineData Object +Compound lines are pens that draw several parallel lines at once. The data here +alternates (sub)line width (as fraction of total width and gaps (also as fraction +of total width). +*/ +typedef struct { + int32_t Elements; //!< Members in the array +/* variable part of object, not part of structure. + U_FLOAT Data //!< Line or gap width (0.0 <-> 1.0, fraction of total line width ) +*/ +} U_PMF_COMPOUNDLINEDATA; + +/** @brief EMF+ manual 2.2.2.10, Microsoft name: EmfPlusCompressedImage Object +Holds an EXIF, GIF, JFIF, PNG, or TIFF image. + For U_PMF_BITMAP BitmapData field + + object has no assocated struct! + U_PMF_COMPRESSEDIMAGE +*/ + +/** @brief EMF+ manual 2.2.2.11, Microsoft name: EmfPlusCustomEndCapData Object */ +typedef struct { + int32_t Size; //!< Bytes in Data +/* variable part of object, not part of structure. + U_PMF_CUSTOMLINECAP Data //!< Description of linecap +*/ +} U_PMF_CUSTOMENDCAPDATA; + +/** @brief EMF+ manual 2.2.2.12, Microsoft name: EmfPlusCustomLineCapArrowData Object */ +typedef struct { + U_FLOAT Width; //!< Arrow cap width (is multiplied by line width before draw) + U_FLOAT Height; //!< Arrow cap length (is multiplied by line width before draw) + U_FLOAT MiddleInset; //!< Pixels between outer edge and filled region + uint32_t FillState; //!< If set, fill, otherwise, only border + uint32_t StartCap; //!< LineCap enumeration (type of cap) + uint32_t EndCap; //!< LineCap enumeration + uint32_t Join; //!< LineJoin enumeration + U_FLOAT MiterLimit; //!< Maximum (miter length / line width) + U_FLOAT WidthScale; //!< Scale for U_PMF_CUSTOMLINECAP object + U_FLOAT FillHotSpot[2]; //!< must be 0.0, 0.0 + U_FLOAT LineHotSpot[2]; //!< must be 0.0, 0.0 +} U_PMF_CUSTOMLINECAPARROWDATA; + +/** @brief EMF+ manual 2.2.2.13, Microsoft name: EmfPlusCustomLineCapData Object */ +typedef struct { + uint32_t Flags; //!< CustomLineCapData flags + uint32_t Cap; //!< LineCap enumeration (type of cap) + U_FLOAT Inset; //!< Distance line cap start -> line end + uint32_t StartCap; //!< LineCap enumeration + uint32_t EndCap; //!< LineCap enumeration + uint32_t Join; //!< LineJoin enumeration + U_FLOAT MiterLimit; //!< Maximum (miter length / line width) + U_FLOAT WidthScale; //!< Scale for U_PMF_CUSTOMLINECAP object + U_FLOAT FillHotSpot[2]; //!< must be 0.0, 0.0 + U_FLOAT LineHotSpot[2]; //!< must be 0.0, 0.0 +/* variable part of object, not part of structure. + U_PMF_CUSTOMLINECAPOPTIONALDATA Data //!< meaning determined by Flags +*/ +} U_PMF_CUSTOMLINECAPDATA; + +/** U_PMF_CUSTOMLINECAPOPTIONALDATA EMF+ manual 2.2.2.14, Microsoft name: EmfPlusCustomLineCapOptionalData Object + + object has no assocated struct! + + U_PMF_FILLPATHO FillData; //!< path to fill (optional) + U_PMF_LINEPATH LineData; //!< path to stroke (optional) +*/ + +/** @brief EMF+ manual 2.2.2.15, Microsoft name: EmfPlusCustomStartCapData Object */ +typedef struct { + int32_t Size; //!< Bytes in Data +/* variable part of object, not part of structure. + U_PMF_CUSTOMLINECAP Data //!< Description of linecap +*/ +} U_PMF_CUSTOMSTARTCAPDATA; + +/** @brief EMF+ manual 2.2.2.16, Microsoft name: EmfPlusDashedLineData Object */ +typedef struct { + int32_t Elements; //!< Elements in Data +/* variable part of object, not part of structure. + U_FLOAT Data; //!< Array of lengths of dashes and spaces +*/ +} U_PMF_DASHEDLINEDATA; + +/** @brief EMF+ manual 2.2.2.17, Microsoft name: EmfPlusFillPath Object +Note: U_PMF_FILLPATHOBJ is the object, U_PMF_FILLPATH is the file record +*/ + +typedef struct { + int32_t Size; //!< Bytes in Data +/* variable part of object, not part of structure. + U_PMF_PATH Data; //!< Path specification +*/ +} U_PMF_FILLPATHO; + +/** @brief EMF+ manual 2.2.2.18, Microsoft name: EmfPlusFocusScaleData Object + for U_PMF_PATHGRADIENTBRUSHOPTIONALDATA data field + +Used with path gradient brushes. May be used to expand the center color +of a gradient, which would otherwise only be found at the center point. +The expanded area is the width, height X scale factor, but in no case +less than 1 pixel. + +*/ +typedef struct { + uint32_t Count; //!< must be 2 + U_FLOAT ScaleX; //!< value 0.0 <-> 1.0 + U_FLOAT ScaleY; //!< value 0.0 <-> 1.0 +} U_PMF_FOCUSSCALEDATA; + +/** @brief EMF+ manual 2.2.2.19, Microsoft name: EmfPlusGraphicsVersion Object + +Bit fields are not used in structs in this implementation, these are serialized/deserialized in +the corresponding routines. Bitfields in the FILE (LITTLE endian here, manual uses BIG endian) are: + unsigned int GrfVersion : 12; GraphicsVersion enumeration + unsigned int Signature : 20; Must be U_GFVR_PMF (0xDBC01) + @{ +*/ +typedef uint32_t U_PMF_GRAPHICSVERSION; //!< EMF+ manual 2.2.2.19, Microsoft name: EmfPlusGraphicsVersion Object +/** @} */ + +/** @brief EMF+ manual 2.2.2.20, Microsoft name: EmfPlusHatchBrushData Object */ +typedef struct { + uint32_t Style; //!< HatchStyle enumeration + U_PMF_ARGB Foreground; //!< Hatch pattern line color + U_PMF_ARGB Background; //!< Hatch pattern bkground color +} U_PMF_HATCHBRUSHDATA; + +/** \defgroup U_PMF_Int7 PMF 7 bit signed integer + @brief EMF+ manual 2.2.2.21, Microsoft name: EmfPlusInteger7 Object + + bit 7 U_INT7 Clear in Integer7 objects + bits 0-6 7 bit signed integer value + @{ +*/ +#define U_TEST_INT7 0x80 //!< This bit is clear in Integer7 objects. +#define U_SIGN_INT7 0x40 //!< Sign bit on an Integer7 object. +#define U_MASK_INT7 0x7F //!< xMask to retrieve integer7 bits. +/** @} */ + +/** \defgroup U_PMF_Int15 PMF 15 bit signed integer + @brief EMF+ manual 2.2.2.22, Microsoft name: EmfPlusInteger15 Object + + bit 15 U_INT15 Set in Integer15 objects + bits 0-15 15 bit signed integer value + + This is the one data type that really does seem to be stored into the file in Big Endian order. + It has to be this way because the bit that determines if data is int7 or int15 must be in the first byte + the parser sees, and that byte is the high order byte. + @{ +*/ +#define U_TEST_INT15 0x8000 //!< This bit is set in Integer15 objects. +#define U_SIGN_INT15 0x4000 //!< Sign bit on an Integer15 object. +#define U_MASK_INT15 0x7FFF //!< Mask to retrieve integer15 bits. +/** @} */ + +/* EMF+ manual 2.2.2.23, Microsoft name: EmfPlusLanguageIdentifier Object, defined above, before 2.2.1.9 */ + +/** @brief EMF+ manual 2.2.2.39, Microsoft name: EmfPlusRectF Object, out of order, needed for 2.2.2.24 */ +typedef struct { + U_FLOAT X; //!< UL X value + U_FLOAT Y; //!< UL Y value + U_FLOAT Width; //!< Width + U_FLOAT Height; //!< Height +} U_PMF_RECTF; + +/** @brief EMF+ manual 2.2.2.24, Microsoft name: EmfPlusLinearGradientBrushData Object +Manual says that Reserved1 and Reserved2 must be ignored. In practice if Reserved1 is not set to StartColor +and Reserved2 is not set to EndColor, then XP Preview will not display the gradient. +*/ +typedef struct { + uint32_t Flags; //!< BrushData flags + int32_t WrapMode; //!< WrapMode enumeration + U_PMF_RECTF RectF; //!< UL=start, LR=end of gradient + U_PMF_ARGB StartColor; //!< Gradient start color + U_PMF_ARGB EndColor; //!< Gradient end color + uint32_t Reserved1; //!< ignore + uint32_t Reserved2; //!< ignore +/* variable part of object, not part of structure. + U_PMF_LINEARGRADIENTBRUSHOPTIONALDATA data; //!< presence and meaning depend on Flags field +*/ +} U_PMF_LINEARGRADIENTBRUSHDATA; + +/** @brief EMF+ manual 2.2.2.47, Microsoft name: EmfPlusTransformMatrix Object, out of order, needed for 2.2.2.25 */ +typedef struct { + U_FLOAT m11; //!< Rotation matrix m11 element + U_FLOAT m12; //!< Rotation matrix m12 element + U_FLOAT m21; //!< Rotation matrix m21 element + U_FLOAT m22; //!< Rotation matrix m22 element + U_FLOAT dX; //!< Translation in X + U_FLOAT dY; //!< Translation in Y +} U_PMF_TRANSFORMMATRIX; + +/** NOT DOCUMENTED. Encountered in actual EmfPlusLinearGradientBrushOptionalData Object made by PowerPoint 2003. This + structure is needed for the next. */ +typedef struct { + U_FLOAT m11; //!< Rotation matrix m11 element + U_FLOAT m12; //!< Rotation matrix m12 element + U_FLOAT m21; //!< Rotation matrix m21 element + U_FLOAT m22; //!< Rotation matrix m22 element +} U_PMF_ROTMATRIX; + +/** @brief EMF+ manual 2.2.2.25, Microsoft name: EmfPlusLinearGradientBrushOptionalData Object + For U_PMF_LINEARGRADIENTBRUSHDATA data field +*/ +/* Entire object is variable and not part of a structure! U_PMF_LINEARGRADIENTBRUSHOPTIONALDATA + U_PMF_ROTMATRIX Matrix; //!< Rotation matrix, Manuals says that this should be Transformation matrix, but last two values are missing + (various) pattern; //!< Presence and meaning depend on Flags field, see below + + Flag values + U_BD_PresetColors U_BD_BlendFactorsH U_BD_BlendFactorsV pattern(s) present? + 0 0 0 none + 1 0 0 U_PMF_BLENDCOLORS + 0 1 0 U_PMF_BLENDFACTORS + 0 0 1 U_PMF_BLENDFACTORS + 0 1 1 U_PMF_BLENDFACTORS, U_PMF_BLENDFACTORS +*/ + +/** @brief EMF+ manual 2.2.2.26, Microsoft name: EmfPlusLinePath Object */ +typedef struct { + int32_t Size; //!< Bytes in Data +/* variable part of object, not part of structure. + U_PMF_PATH Data; //!< Outline path +*/ +} U_PMF_LINEPATH; + +/** @brief EMF+ manual 2.2.2.27, Microsoft name: EmfPlusMetafile Object */ +typedef struct { + uint32_t Type; //!< MetaFileDatatype enumeration + uint32_t Size; //!< Bytes in Data +/* variable part of object, not part of structure. + U_PMF_IMAGE Data; //!< Various types of data, like an EMF metafile, WMF metafile, another EMF+ metafile +*/ +} U_PMF_METAFILE; + +/** @brief EMF+ manual 2.2.2.28, Microsoft name: EmfPlusPalette Object */ +typedef struct { + uint32_t Flags; //!< PaletteStyle flags + uint32_t Elements; //!< elements in Data +/* variable part of object, not part of structure. + U_PMF_ARGB Data; //!< Palette data (array of colors) +*/ +} U_PMF_PALETTE; + +/** @brief EMF+ manual 2.2.2.36, Microsoft name: EmfPlusPointF Object, out of order, needed for 2.2.2.29 */ +typedef struct { + U_FLOAT X; //!< UL X value + U_FLOAT Y; //!< UL Y value +} U_PMF_POINTF; + +/** @brief EMF+ manual 2.2.2.29, Microsoft name: EmfPlusPathGradientBrushData Object */ +typedef struct { + uint32_t Flags; //!< BrushData flags + int32_t WrapMode; //!< WrapMode enumeration + U_PMF_ARGB CenterColor; //!< Gradient center color + U_PMF_POINTF Center; //!< Center coordinates + uint32_t Elements; //!< Number of elements in gradient (not counting center) +/* variable part of object, not part of structure. + U_PMF_ARGB Gradient; //!< Color Gradient with Elements members + (varies) Boundary; //!< U_PMF_BOUNDARYPATHDATA object if BrushDataPath bit set in Flag, else U_PMF_BOUNDARYPOINTDATA object + U_PMF_GRADIENTBRUSHOPTIONALDATA data; //!< exact composition depends on Flags +*/ +} U_PMF_PATHGRADIENTBRUSHDATA; + +/** EMF+ manual 2.2.2.30, Microsoft name: EmfPlusPathGradientBrushOptionalData Object + for U_PMF_PATHGRADIENTNBRUSHDATA data field +*/ +/* Entire thing is variable or optional. +typedef struct { + U_PMF_TRANSFORMMATRIX Matrix; //!< Optional Transformation matrix + U_PMF_BLENDCOLORS Pattern; //!< presence and meaning depend on Flags field + Flag values + U_BD_PresetColors U_BD_BlendFactorsH pattern? + 0 0 none + 1 0 U_PMF_BLENDCOLORS + 0 1 U_PMF_BLENDFACTORS + U_PMF_FOCUSSSCALEDATA data //!< Present if U_BD_FocusScales bit set in Flags in U_PMF_PATHGRADIENTNBRUSHDATA object +} U_PMF_PATHGRADIENTBRUSHOPTIONALDATA; +*/ + +/** \defgroup U_PMF_PPTYPE PMF Path Point Types + @brief EMF+ manual 2.2.2.31, Microsoft name: EmfPlusPathPointType Object + +Bitfields in the FILE (LITTLE endian here, manual uses BIG endian) are: + bits 4-7 PathPointType flags + bits 0-3 PathPointType enumeration + @{ +*/ +typedef uint8_t U_PMF_PATHPOINTTYPE; //!< EMF+ manual 2.2.2.31, Microsoft name: EmfPlusPathPointType Object +/** @} */ + +/** \defgroup U_PMF_PPTYPERLE PMF Run Length Encoded Path Point Types + @brief EMF+ manual 2.2.2.32, Microsoft name: EmfPlusPathPointTypeRLE Object + +U_PMF_PATHPOINTTYPERLE fields specify point types in a path where the path is Run Length Encoded. +Bit fields are not used in structs in this implementation, these are serialized/deserialized in +the corresponding routines. Bitfields in the FILE (LITTLE endian here, manual uses BIG endian) are: + bit 15 Set: Bezier curve; Clear: straight line + bit 14 ignored + bits 8-13 Run count + bits 0-7 PathPointType enumeration + @{ +*/ +typedef uint16_t U_PMF_PATHPOINTTYPERLE; //!< EMF+ manual 2.2.2.32, Microsoft name: EmfPlusPathPointTypeRLE Object +/** @} */ + +/** @brief EMF+ manual 2.2.2.33, Microsoft name: EmfPlusPenData Object + +Variable part of object follows structure: + U_PMF_PENOPTIONALDATA data; Optional pen data, exact composition depends on Flags +*/ +typedef struct { + uint32_t Flags; //!< PenData flags + uint32_t Unit; //!< UnitType enumeration + U_FLOAT Width; //!< Width in units set by Unit +} U_PMF_PENDATA; + +/** @brief EMF+ manual 2.2.2.34, Microsoft name: EmfPlusPenOptionalData Object + +Every part of this object is variable or optional, there is no corresponding struct + + Present if Flag What is it + U_PMF_TRANSFORMMATRIX Matrix //!< U_PD_Transform Transformation matrix + int32_t StartCap //!< U_PD_StartCap LineCapType enumeration + int32_t EndCap //!< U_PD_EndCap LineCapType enumeration + uint32_t Join //!< U_PD_Join LineJoinType enumeration + U_FLOAT MiterLimit //!< U_PD_MiterLimit Maximum (miter length / line width) + int32_t Style //!< U_PD_LineStyle LineStyle enumeration + int32_t DLCap //!< U_PD_DLCap DashedLineCapType enumeration + U_FLOAT DLOffset //!< U_PD_DLOffset Distance line start to first dash start + U_PMF_DASHEDLINEDATA DLData //!< U_PD_DLData Dash and space widths + int32_t PenAlignment //!< U_PD_NonCenter PenAlignment enumeration + U_PMF_COMPOUNDLINEDATA CLData //!< U_PD_CompoundLineData Compount Line (parallel lines drawn instead of one) + U_PMF_CUSTOMSTARTCAPDATA CSCapData //!< U_PD_CustomStartCap Custom start cap + U_PMF_CUSTOMENDCAPDATA CECapData //!< U_PD_CustomEndCap Custom end cap + */ + +/** @brief EMF+ manual 2.2.2.35, Microsoft name: EmfPlusPoint Object */ +typedef struct { + int16_t X; //!< X coordinate + int16_t Y; //!< Y coordinate +} U_PMF_POINT; + +/** U_PMF_POINTF EMF+ manual 2.2.2.36, Microsoft name: EmfPlusPointF Object, defined above, before 2.2.2.29 */ + +/** U_PMF_POINTR EMF+ manual 2.2.2.37, Microsoft name: EmfPlusPointR Object + For U_PMF_DRAWBEZIERS data field (optionally). + Both parts of this object are variable, there is no corresponding struct. + Any combination of the two allowed types of integer is valid. + + (varies) X; //!< U_PMF_INTEGER7 or U_PMF_INTEGER15 + (varies) Y; //!< U_PMF_INTEGER7 or U_PMF_INTEGER15 + +*/ + +/** @brief EMF+ manual 2.2.2.38, Microsoft name: EmfPlusRect Object */ +typedef struct { + int16_t X; //!< UL X value + int16_t Y; //!< UL Y value + int16_t Width; //!< Width + int16_t Height; //!< Height +} U_PMF_RECT; + +/** U_PMF_RECTF EMF+ manual 2.2.2.39, Microsoft name: EmfPlusRectF Object, defined above, before 2.2.2.24 */ + +/** U_PMF_REGIONNODE EMF+ manual 2.2.2.40, Microsoft name: EmfPlusRegionNode Object, defined above, before 2.2.1.8 */ + +/** U_PMF_REGIONNODECHILDNODES EMF+ manual 2.2.2.41, Microsoft name: EmfPlusRegionNodeChildNodes Object + For U_PMF_REGIONNODE data field (optionally). + Both parts of this object are variable, there is no corresponding struct. + U_PMF_REGIONNODE Left; //!< Left child + U_PMF_REGIONNODE Right; //!< Right child +*/ + +/** @brief EMF+ manual 2.2.2.42, Microsoft name: EmfPlusRegionNodePath Object */ +typedef struct { + int32_t Size; //!< Bytes in Data +/* variable part of object, not part of structure. + U_PMF_PATH Data; //!< Boundary of region node +*/ +} U_PMF_REGIONNODEPATH; + +/** @brief EMF+ manual 2.2.2.43, Microsoft name: EmfPlusSolidBrushData Object + For U_PMF_BRUSH data field (one type of brush) +*/ +typedef struct { + U_PMF_ARGB Color; //!< Color of brush +} U_PMF_SOLIDBRUSHDATA; + +/** U_PMF_STRINGFORMATDATA EMF+ manual 2.2.2.44, Microsoft name: EmfPlusStringFormatData Object + Both parts of this object are variable and optional, there is no corresponding struct + U_FLOAT TabStops[]; //!< Array of tabstop locations + U_PMF_CHARACTERRANGE CharRange[]; //!< Array of character ranges in the text +*/ + +/** @brief EMF+ manual 2.2.2.45, Microsoft name: EmfPlusTextureBrushData Object */ +typedef struct { + uint32_t Flags; //!< BrushData flags + int32_t WrapMode; //!< WrapMode enumeration +/* variable part of object, not part of structure. + U_PMF_TEXTUREBRUSHOPTIONALDATA data; //!< Optional texture data +*/ +} U_PMF_TEXTUREBRUSHDATA; + +/** U_PMF_TEXTUREBRUSHOPTIONALDATA EMF+ manual 2.2.2.46, Microsoft name: EmfPlusTextureBrushOptionalData Object + +Every part of this object is variable or optional, there is no corresponding struct + + U_PMF_TRANSFORMMATRIX Matrix; Transformation matrix, present if Flag BrushDataTransform is set. + U_PMF_IMAGE Image Image that contains the texture. Present if the PMR record that includes this object still has space + for an U_PMF_IMAGE after all the other variable and optional data + within it has been accounted for. +*/ + +/** U_PMF_TRANSFORMMATRIX EMF+ manual 2.2.2.47, Microsoft name: EmfPlusTransformMatrix Object, defined above, before 2.2.2.25 */ + +/** common structure present at the beginning of all(*) EMF+ records */ +typedef struct { + uint16_t Type; //!< Recordtype enumeration (what this record is) + uint16_t Flags; //!< Flags (meaning varies by record type) + uint32_t Size; //!< Bytes in record, including this struct (will be a multiple of 4) + uint32_t DataSize; //!< Bytes of data that follow, may not be a multiple of 4. +} U_PMF_CMN_HDR; + +/** These are the Image Effect Objects 2.2.3.* They specify parameters for "filters" that may be applied to bitmaps. */ + +/** @brief EMF+ manual 2.2.3.1, Microsoft name: BlurEffect Object */ +typedef struct { + U_FLOAT Radius; //!< Blur radius in pixels + uint32_t ExpandEdge; //!< 1: expand bitmap by Radius; 0: bitmap size unchanged +} U_PMF_IE_BLUR; + + +/** @brief EMF+ manual 2.2.3.2, Microsoft name: BrightnessContrastEffect Object */ +typedef struct { + int32_t Brightness; //!< -255 to 255, 0 is unchanged, positive increases, negative decreases + int32_t Contrast; //!< -100 to 100, 0 is unchanged, positive increases, negative decreases +} U_PMF_IE_BRIGHTNESSCONTRAST; + +/** @brief EMF+ manual 2.2.3.3, Microsoft name: ColorBalanceEffect Object */ +typedef struct { + int32_t CyanRed; //!< -100 to 100, 0 is unchanged, positive increases Red & decreases Cyan, negative is opposite + int32_t MagentaGreen; //!< -100 to 100, 0 is unchanged, positive increases Green & decreases Magenta, negative is opposite + int32_t YellowBlue; //!< -100 to 100, 0 is unchanged, positive increases Blue & decreases Yellow, negative is opposite +} U_PMF_IE_COLORBALANCE; + +/** @brief EMF+ manual 2.2.3.4, Microsoft name: ColorCurveEffect Object + Adjust Range + Exposure -255 to 255, 0 is unchanged + Density -255 to 255, 0 is unchanged + Contrast -100 to 100, 0 is unchanged + Highlight -100 to 100, 0 is unchanged + Shadow -100 to 100, 0 is unchanged + WhiteSaturation 0 to 255 + BlackSaturation 0 to 255 +*/ +typedef struct { + uint32_t Adjust; //!< CurveAdjustment enumeration + uint32_t Channel; //!< CurveChannel enumeration + int32_t Intensity; //!< adjustment to apply. "Adjust" determines what field this is and range values. +} U_PMF_IE_COLORCURVE; + +/** @brief EMF+ manual 2.2.3.5, Microsoft name: ColorLookupTableEffect Object */ +typedef struct { + uint8_t BLUT[256]; //!< Blue color lookup table + uint8_t GLUT[256]; //!< Green color lookup table + uint8_t RLUT[256]; //!< Red color lookup table + uint8_t ALUT[256]; //!< Alpha color lookup table +} U_PMF_IE_COLORLOOKUPTABLE; + +/** @brief EMF+ manual 2.2.3.6, Microsoft name: ColorMatrixEffect Object */ +typedef struct { + U_FLOAT M[5][5]; //!< 5 x 5 color transformation matrix, First 4 rows are [{4 multiplier values},0.0] for R,G,B,A, last Row is [{4 color translation valuess}, 1.0] +} U_PMF_IE_COLORMATRIX; + +/** @brief EMF+ manual 2.2.3.7, Microsoft name: HueSaturationLightnessEffect Object */ +typedef struct { + int32_t Hue; //!< -180 to 180, 0 is unchanged + int32_t Saturation; //!< -100 to 100, 0 is unchanged + int32_t Lightness; //!< -100 to 100, 0 is unchanged +} U_PMF_IE_HUESATURATIONLIGHTNESS; + +/** @brief EMF+ manual 2.2.3.8, Microsoft name: LevelsEffect Object */ +typedef struct { + int32_t Highlight; //!< 0 to 100, 100 is unchanged + int32_t Midtone; //!< -100 to 100, 0 is unchanged + int32_t Shadow; //!< 0 to 100, 0 is unchanged +} U_PMF_IE_LEVELS; + +/** @brief EMF+ manual 2.2.3.9, Microsoft name: RedEyeCorrectionEffect Object */ +typedef struct { + int32_t Elements; //!< Number of members in Rects +/* variable part of object, not included in structure + U_RECTL Rects[]; //!< Array of rectangular area(s) to apply red eye correction +*/ +} U_PMF_IE_REDEYECORRECTION; + +/** @brief EMF+ manual 2.2.3.10, Microsoft name: SharpenEffect Object */ +typedef struct { + U_FLOAT Radius; //!< Sharpening radius in pixels + int32_t Sharpen; //!< 0 to 100, 0 is unchanged +} U_PMF_IE_SHARPEN; + +/** @brief EMF+ manual 2.2.3.11, Microsoft name: TintEffect Object */ +typedef struct { + int32_t Hue; //!< -180 to 180, [positive==clockwise] rotation in degrees starting from blue + int32_t Amount; //!< -100 [add black] to 100[add white], 0 is unchanged. Change in hue on specified axis +} U_PMF_IE_TINT; + +/* ************************** EMF+ Records ******************************** */ + +/** @brief EMF+ manual 2.3.1.1, Microsoft name: EmfPlusOffsetClip Record, Index 0x35 */ +typedef struct { + U_PMF_CMN_HDR Header; //!< Common header (ignore flags) + U_FLOAT dX; //!< horizontal translation offset to apply to clipping region + U_FLOAT dY; //!< vertical translation offset to apply to clipping region +} U_PMF_OFFSETCLIP; + +/** @brief U_PMF_RESETCLIP EMF+ manual 2.3.1.2, Microsoft name: EmfPlusResetClip Record, Index 0x31 */ +typedef struct { + U_PMF_CMN_HDR Header; //!< Common header (ignore flags) +} U_PMF_RESETCLIP; + +/** @brief EMF+ manual 2.3.1.3, Microsoft name: EmfPlusSetClipPath Record, Index 0x33 + +flags (LITTLE endian here, manual uses BIG endian) + bits 8-11 CombineMode enumeration + bits 0-7 Index of an U_PMF_PATH object in the EMF+ object table (0-63, inclusive) +*/ +typedef struct { + U_PMF_CMN_HDR Header; //!< Common header +} U_PMF_SETCLIPPATH; + +/** @brief EMF+ manual 2.3.1.4, Microsoft name: EmfPlusSetClipRect Record, Index 0x32 + +flags (LITTLE endian here, manual uses BIG endian) + bits 8-11 CombineMode enumeration +*/ +typedef struct { + U_PMF_CMN_HDR Header; //!< Common header + U_PMF_RECTF Rect; //!< Rectangle used with CombineMode enumeration from Header.Flags +} U_PMF_SETCLIPRECT; + +/** @brief EMF+ manual 2.3.1.5, Microsoft name: EmfPlusSetClipRegion Record, Index 0x34 + + flags (LITTLE endian here, manual uses BIG endian) + bits 12-15 CombineMode enumeration + bits 0-7 Index of an U_PMF_REGION object in the EMF+ object table (0-63, inclusive) +*/ +typedef struct { + U_PMF_CMN_HDR Header; //!< Common header +} U_PMF_SETCLIPREGION; + +/** @brief EMF+ manual 2.3.2.1, Microsoft name: EmfPlusComment Record, Index 0x03 + + variable part of record, not included in structure + char data[]; //!< Private data, may be anything +*/ +typedef struct { + U_PMF_CMN_HDR Header; //!< Common header (ignore flags and set to zero) +} U_PMF_COMMENT; + +/** @brief EMF+ manual 2.3.3.1, Microsoft name: EmfPlusEndOfFile Record, Index 0x02 */ +typedef struct { + U_PMF_CMN_HDR Header; //!< Common header (ignore flags and set to zero) +} U_PMF_ENDOFFILE; + +/** @brief EMF+ manual 2.3.3.2, Microsoft name: EmfPlusGetDC Record, Index 0x04 */ +typedef struct { + U_PMF_CMN_HDR Header; //!< Common header (ignore flags and set to zero) +} U_PMF_GETDC; + +/** @brief EMF+ manual 2.3.3.3, Microsoft name: EmfPlusHeader Record, Index 0x01 + + flags (LITTLE endian here, manual uses BIG endian) + bit 0 Set indicates "dual mode" EMF+ +*/ +typedef struct { + U_PMF_CMN_HDR Header; //!< Common header (ignore flags and set to zero) + U_PMF_GRAPHICSVERSION Version; //!< EmfPlusGraphicsVersion object + uint32_t EmfPlusFlags; //!< Reference device 0 bit: set = video device, clear= printer. Ignore all other bits. + uint32_t LogicalDpiX; //!< Horizontal resolution reference device in DPI + uint32_t LogicalDpiY; //!< Vertical resolution reference device in DPI +} U_PMF_HEADER; + +/** @brief EMF+ manual 2.3.4.1, Microsoft name: EmfPlusClear Record, Index 0x09 */ +typedef struct { + U_PMF_CMN_HDR Header; //!< Common header (ignore flags and set to zero) + U_PMF_ARGB Color; //!< Erase everything preceding, set background ARGB color. +} U_PMF_CLEAR; + +/** @brief EMF+ manual 2.3.4.2, Microsoft name: EmfPlusDrawArc Record, Index 0x12 + + flags (LITTLE endian here, manual uses BIG endian) + bit 9 U_PPF_C Set: Rect is U_PMF_RECT; Clear: Rect is U_PMF_RECTF + bits 0-7 Index of an U_PMF_PEN object in the EMF+ object table (0-63, inclusive) +*/ +typedef struct { + U_PMF_CMN_HDR Header; //!< Common header + U_FLOAT Start; //!< Start angle, >=0.0, degrees clockwise from 3:00 + U_FLOAT Sweep; //!< Sweep angle, -360<= angle <=360, degrees clockwise from Start +/* variable part of record, not included in structure + U_RECT or U_RECTF Rect; //!< Bounding box for elliptical arc being drawn. +*/ +} U_PMF_DRAWARC; + +/** @brief EMF+ manual 2.3.4.3, Microsoft name: EmfPlusDrawBeziers Record, Index 0x19 + flags (LITTLE endian here, manual uses BIG endian) + bit 9 U_PPF_C Set: int16_t coordinates; Clear: U_FLOAT coordinates (IGNORE if bit 4 is set) + bit 12 U_PPF_P Set: Coordinates are relative; Clear: they are absolute + bits 0-7 Index of an U_PMF_PEN object in the EMF+ object table (0-63, inclusive) + + bit1 bit4 Type of Data + 1 0 U_EMF_POINT + 0 0 U_EMF_POINTF + 0 1 U_EMF_POINTR +*/ +typedef struct { + U_PMF_CMN_HDR Header; //!< Common header + uint32_t Elements; //!< Number of members in the Points array +/* + variable part of record, not included in structure + (varies) Points; //!< Points, for type see table above +*/ +} U_PMF_DRAWBEZIERS; + +/** @brief EMF+ manual 2.3.4.4, Microsoft name: EmfPlusDrawClosedCurve Record, Index 0x17 + + flags (LITTLE endian here, manual uses BIG endian) + bit 9 U_PPF_C Set: int16_t coordinates; Clear: U_FLOAT coordinates (IGNORE if bit 4 is set) + bit 12 U_PPF_P Set: Coordinates are relative; Clear: they are absolute + bits 0-7 Index of an U_PMF_PEN object in the EMF+ object table (0-63, inclusive) + + bit1 bit4 Type of Data + 1 0 U_EMF_POINT + 0 0 U_EMF_POINTF + 0 1 U_EMF_POINTR + +Curve is a cardinal spline. +References sent by MS support: + +http://alvyray.com/Memos/CG/Pixar/spline77.pdf +http://msdn.microsoft.com/en-us/library/4cf6we5y(v=vs.110).aspx + +*/ +typedef struct { + U_PMF_CMN_HDR Header; //!< Common header + U_FLOAT Tension; //!< Controls splines, 0 is straight line, >0 is curved +/* + variable part of record, not included in structure + (varies) Points; //!< Points, for type see table above +*/ +} U_PMF_DRAWCLOSEDCURVE; + +/** @brief EMF+ manual 2.3.4.5, Microsoft name: EmfPlusDrawCurve Record, Index 0x18 + flags (LITTLE endian here, manual uses BIG endian) + bit 9 U_PPF_C Set: int16_t coordinates; Clear: U_FLOAT coordinates (IGNORE if bit 4 is set) + bits 0-7 Index of an U_PMF_PEN object in the EMF+ object table (0-63, inclusive) + + bit1 Type of Data + 1 U_EMF_POINT + 0 U_EMF_POINTF + +Curve is a cardinal spline, using doubled terminator points to generate curves for the terminal segments. +References sent by MS support: + +http://alvyray.com/Memos/CG/Pixar/spline77.pdf +http://msdn.microsoft.com/en-us/library/4cf6we5y(v=vs.110).aspx +*/ +typedef struct { + U_PMF_CMN_HDR Header; //!< Common header + U_FLOAT Tension; //!< Controls splines, 0 is straight line, >0 is curved + uint32_t Offset; //!< Element in Points that is the spline's starting point + uint32_t NSegs; //!< Number of segments + uint32_t Elements; //!< Number of members in Points array +/* + variable part of record, not included in structure + (varies) Points; //!< Points, for type see table above +*/ +} U_PMF_DRAWCURVE; + +/** @brief EMF+ manual 2.3.4.6, Microsoft name: EmfPlusDrawDriverString Record, Index 0x36 + + flags (LITTLE endian here, manual uses BIG endian) +. bit 15 U_PPF_B Set: BrushID is an U_PFM_ARGB; Clear: is index of U_PMF_BRUSH object in EMF+ object table + bits 0-7 Index of an U_PMF_FONT object in the EMF+ object table (0-63, inclusive) +*/ +typedef struct { + U_PMF_CMN_HDR Header; //!< Common header + uint32_t BrushID; //!< Color or index to Brush object, depends on Flags bit0 + uint32_t DSOFlags; //!< DriverStringOptions flags + uint32_t HasMatrix; //!< If 1 record contains a TransformMatrix field, if 0 it does not. + uint32_t Elements; //!< Number of members in Glyphs and Positions array +/* + variable part of record, not included in structure + uint16_t Glyphs; //!< If U_DSO_CmapLookup is set in DSOFlags this is an array + of UTF16LE characters, otherwise, it is an array of indices into the U_PMF_FONT + object indexed by Object_ID in flags. + U_PMF_POINTF Positions; //!< Coordinates of each member of Glyphs. U_DSO_RealizedAdvance set in DSOFlags + Relative then positions are calculated relative to the first glyph which is stored + in Positions, otherwise, all glyph positions are stored in Positions. + U_PMF_TRANSFORMMATRIX Matrix; //!< Transformation to apply to Glyphs & Positions. Present if HasMatrix is 1 +*/ +} U_PMF_DRAWDRIVERSTRING; + +/** @brief EMF+ manual 2.3.4.7, Microsoft name: EmfPlusDrawEllipse Record, Index 0x0F + + flags (LITTLE endian here, manual uses BIG endian) + bit 9 U_PPF_C Set: Rect is U_PMF_RECT; Clear: Rect is U_PMF_RECTF + bits 0-7 Index of an U_PMF_PEN object in the EMF+ object table (0-63, inclusive) +*/ +typedef struct { + U_PMF_CMN_HDR Header; //!< Common header +/* + variable part of record, not included in structure + (varies) Rect; //!< Bounding rectangle, data type set by bit1 of Header.Flags +*/ +} U_PMF_DRAWELLIPSE; + +/** @brief EMF+ manual 2.3.4.8, Microsoft name: EmfPlusDrawImage Record, Index 0x1A + + flags (LITTLE endian here, manual uses BIG endian) + bit 9 U_PPF_C Set: DstRect is U_PMF_RECT; Clear: DstRect is U_PMF_RECTF + bits 0-7 Index of an U_PMF_Image object in the EMF+ object table (0-63, inclusive) +*/ +typedef struct { + U_PMF_CMN_HDR Header; //!< Common header + uint32_t ImgAttrID; //!< EmfPlusImageAttributes object + int32_t SrcUnit; //!< UnitType enumeration + U_PMF_RECTF SrcRect; //!< Region of image +/* + variable part of record, not included in structure + (varies) DstRect; //!< Destination rectangle for image. Type controlled by bit1 of Header.Flags +*/ +} U_PMF_DRAWIMAGE; + +/** @brief EMF+ manual 2.3.4.9, Microsoft name: EmfPlusDrawImagePoints Record, Index 0x1B + + flags (LITTLE endian here, manual uses BIG endian) + bit 14 U_PPF_C Set: Points is U_PMF_POINT; Clear: Points is U_PMF_POINTF + bit 13 U_PPF_E Set: effect from previous U_PMF_SERIALIZABLEOBJECT record will be applied; Clear: no effect applied + bit 11 U_PPF_P Set: Points has relative coordinates; Clear: Points has absolute coordinates + bits 0-7 Index of an U_PMF_Image object in the EMF+ object table (0-63, inclusive) + + bit1 bit4 Type of Data + 1 0 U_EMF_POINT + 0 0 U_EMF_POINTF + 0 1 U_EMF_POINTR + + WARNING! Windows XP Preview does not show filter effects, whether or not U_PPF_E is set. They are visible if the EMF+ + file is inserted as an image into PowerPoint. +*/ +typedef struct { + U_PMF_CMN_HDR Header; //!< Common header + uint32_t ImgAttrID; //!< EmfPlusImageAttributes object + int32_t SrcUnit; //!< UnitType enumeration + U_PMF_RECTF SrcRect; //!< Region of image + uint32_t Elements; //!< Number of members in Points, must be 3 +/* + variable part of record, not included in structure + (varies) Points; //!< 3 points of a parallelogram. Type from bit1 and bit4 of Header.Flags, see table above +*/ +} U_PMF_DRAWIMAGEPOINTS; + +/** @brief EMF+ manual 2.3.4.10, Microsoft name: EmfPlusDrawLines Record, Index 0x0D + + flags (LITTLE endian here, manual uses BIG endian) + bit 9 U_PPF_C Set: Points is U_PMF_POINT; Clear: Points is U_PMF_POINTF + bit 10 U_PPF_D Set: close shape by connecting last point to first; Clear: leave path open + bit 12 U_PPF_P Set: Points has relative coordinates; Clear: Points has absolute coordinates + bits 0-7 Index of an U_PMF_Image object in the EMF+ object table (0-63, inclusive) + + bit1 bit4 Type of Data + 1 0 U_EMF_POINT + 0 0 U_EMF_POINTF + 0 1 U_EMF_POINTR +*/ +typedef struct { + U_PMF_CMN_HDR Header; //!< Common header + uint32_t Elements; //!< Number of members in Points +/* + variable part of record, not included in structure + (varies) Points; //!< Sequence of points to connect with line segments. Type from bit1 and bit4 of Header.Flags, see table above +*/ +} U_PMF_DRAWLINES; + +/** @brief EMF+ manual 2.3.4.11, Microsoft name: EmfPlusDrawPath Record, Index 0x15 + + flags (LITTLE endian here, manual uses BIG endian) + bits 0-7 Index of an U_PMF_PATH object in the EMF+ object table (0-63, inclusive) +*/ +typedef struct { + U_PMF_CMN_HDR Header; //!< Common header + uint32_t PenID; //!< U_PMF_PEN object in the EMF+ object table (0-63, inclusive) +} U_PMF_DRAWPATH; + +/** @brief EMF+ manual 2.3.4.12, Microsoft name: EmfPlusDrawPie Record, Index 0x0D + + flags (LITTLE endian here, manual uses BIG endian) + bit 9 U_PPF_C Set: Rect is U_PMF_RECT; Clear: Rect is U_PMF_RECTF + bits 0-7 Index of an U_PMF_Pen object in the EMF+ object table (0-63, inclusive) +*/ +typedef struct { + U_PMF_CMN_HDR Header; //!< Common header + U_FLOAT Start; //!< Start angle, >=0.0, degrees clockwise from 3:00 + U_FLOAT Sweep; //!< Sweep angle, -360<= angle <=360, degrees clockwise from Start +/* + variable part of record, not included in structure + U_RECT or U_RECTF Rect; //!< Bounding box for elliptical pie segment being drawn. Type from bit1 of Header.Flags, see above +*/ +} U_PMF_DRAWPIE; + +/** @brief EMF+ manual 2.3.4.13, Microsoft name: EmfPlusDrawRects Record, Index 0x0B + + flags (LITTLE endian here, manual uses BIG endian) + bit 9 U_PPF_C Set: Rect is U_PMF_RECT; Clear: Rect is U_PMF_RECTF + bits 0-7 Index of an U_PMF_Pen object in the EMF+ object table (0-63, inclusive) +*/ +typedef struct { + U_PMF_CMN_HDR Header; //!< Common header + uint32_t Elements; //!< Number of members in Rects +/* + variable part of record, not included in structure + U_RECT or U_RECTF Rects; //!< Array of rectangles to draw. Type from bit1 of Header.Flags, see above +*/ +} U_PMF_DRAWRECTS; + +/** @brief EMF+ manual 2.3.4.14, Microsoft name: EmfPlusDrawString Record, Index 0x1C + + flags (LITTLE endian here, manual uses BIG endian) + bit 15 U_PPF_B Set: BrushID is an U_PFM_ARGB; Clear: is index of U_PMF_BRUSH object in EMF+ object table. + bits 0-7 Index of an U_PMF_FONT object in the EMF+ object table (0-63, inclusive) +*/ +typedef struct { + U_PMF_CMN_HDR Header; //!< Common header + uint32_t BrushID; //!< Color or index to Brush object, depends on Flags bit0 + uint32_t FormatID; //!< U_PMF_STRINGFORMAT object in EMF+ Object Table. + uint32_t Length; //!< Number of characters in the string. + U_PMF_RECTF Rect; //!< String's bounding box. +/* + variable part of record, not included in structure + uint16_t String; //!< Array of UFT-16LE unicode characters. +*/ +} U_PMF_DRAWSTRING; + +/** @brief EMF+ manual 2.3.4.15, Microsoft name: EmfPlusFillClosedCurve Record, Index 0x16 + + flags (LITTLE endian here, manual uses BIG endian) + bit 15 U_PPF_B Set: BrushID is an U_PFM_ARGB; Clear: is index of U_PMF_BRUSH object in EMF+ object table. + bit 9 U_PPF_C Set: Points is U_PMF_POINT; Clear: Points is U_PMF_POINTF + bit 10 U_PPF_F Set: winding fill; Clear: alternate fill + bit 12 U_PPF_P Set: Points has relative coordinates; Clear: Points has absolute coordinates + + bit1 bit4 Type of Data + 1 0 U_EMF_POINT + 0 0 U_EMF_POINTF + 0 1 U_EMF_POINTR +*/ +typedef struct { + U_PMF_CMN_HDR Header; //!< Common header + uint32_t BrushID; //!< Color or index to Brush object, depends on Header.Flags bit0 + U_FLOAT Tension; //!< Controls splines, 0 is straight line, >0 is curved + uint32_t Elements; //!< Number of members in Points +/* + variable part of record, not included in structure + (varies) Points; //!< Sequence of points to connect. Type from bit1 and bit4 of Header.Flags, see table above +*/ +} U_PMF_FILLCLOSEDCURVE; + +/** @brief EMF+ manual 2.3.4.16, Microsoft name: EmfPlusFillEllipse Record, Index 0x0E + + flags (LITTLE endian here, manual uses BIG endian) + bit 15 U_PPF_B Set: BrushID is an U_PFM_ARGB; Clear: is index of U_PMF_BRUSH object in EMF+ object table. + bit 9 U_PPF_C Set: Rect is U_PMF_RECT; Clear: Rect is U_PMF_RECTF +*/ +typedef struct { + U_PMF_CMN_HDR Header; //!< Common header + uint32_t BrushID; //!< Color or index to Brush object, depends on Header.Flags bit0 +/* + variable part of record, not included in structure + U_RECT or U_RECTF Rect; //!< Bounding box for elliptical pie segment being drawn. Type from bit1 of Header.Flags, see above +*/ +} U_PMF_FILLELLIPSE; + +/** @brief EMF+ manual 2.3.4.17, Microsoft name: EmfPlusFillPath Record, Index 0x14 +Note: U_PMF_FILLPATHOBJ is the object, U_PMF_FILLPATH is the file record + + flags (LITTLE endian here, manual uses BIG endian) + bit 15 U_PPF_B Set: BrushID is an U_PFM_ARGB; Clear: is index of U_PMF_BRUSH object in EMF+ object table. + bits 0-7 Index of an U_PMF_PATH object in the EMF+ object table (0-63, inclusive) +*/ +typedef struct { + U_PMF_CMN_HDR Header; //!< Common header + uint32_t BrushID; //!< Color or index to Brush object, depends on Header.Flags bit0 +} U_PMF_FILLPATH; + +/** @brief EMF+ manual 2.3.4.18, Microsoft name: EmfPlusFillPie Record, Index 0x10 + + flags (LITTLE endian here, manual uses BIG endian) + bit 15 U_PPF_B Set: BrushID is an U_PFM_ARGB; Clear: is index of U_PMF_BRUSH object in EMF+ object table. + bit 9 U_PPF_C Set: Rect is U_PMF_RECT; Clear: Rect is U_PMF_RECTF +*/ +typedef struct { + U_PMF_CMN_HDR Header; //!< Common header + uint32_t BrushID; //!< Color or index to Brush object, depends on Header.Flags bit0 + U_FLOAT Start; //!< Start angle, >=0.0, degrees clockwise from 3:00 + U_FLOAT Sweep; //!< Sweep angle, -360<= angle <=360, degrees clockwise from Start +/* + variable part of record, not included in structure + U_RECT or U_RECTF Rect; //!< Bounding box for elliptical pie segment being filled. Type from bit1 of Header.Flags, see above +*/ +} U_PMF_FILLPIE; + +/** @brief EMF+ manual 2.3.4.19, Microsoft name: EmfPlusFillPolygon Record, Index 0x0C + + flags (LITTLE endian here, manual uses BIG endian) + bit 15 U_PPF_B Set: BrushID is an U_PFM_ARGB; Clear: is index of U_PMF_BRUSH object in EMF+ object table. + bit 9 U_PPF_C Set: Points is U_PMF_POINT; Clear: Points is U_PMF_POINTF + bit 12 U_PPF_P Set: Points has relative coordinates; Clear: Points has absolute coordinates + + bit1 bit4 Type of Data + 1 0 U_EMF_POINT + 0 0 U_EMF_POINTF + 0 1 U_EMF_POINTR +*/ +typedef struct { + U_PMF_CMN_HDR Header; //!< Common header + uint32_t BrushID; //!< Color or index to Brush object, depends on Header.Flags bit0 + uint32_t Elements; //!< Number of members in Points +/* + variable part of record, not included in structure + (varies) Points; //!< Sequence of points to connect with line segments. Type from bit1 and bit4 of Header.Flags, see table above +*/ +} U_PMF_FILLPOLYGON; + +/** @brief EMF+ manual 2.3.4.20, Microsoft name: EmfPlusFillRects Record, Index 0x0A + + flags (LITTLE endian here, manual uses BIG endian) + bit 15 U_PPF_B Set: BrushID is an U_PFM_ARGB; Clear: is index of U_PMF_BRUSH object in EMF+ object table. + bit 9 U_PPF_C Set: Rect is U_PMF_RECT; Clear: Rect is U_PMF_RECTF +*/ +typedef struct { + U_PMF_CMN_HDR Header; //!< Common header + uint32_t BrushID; //!< Color or index to Brush object, depends on Header.Flags bit0 + uint32_t Elements; //!< Number of members in Rects +/* + variable part of record, not included in structure + U_RECT or U_RECTF Rects; //!< Array of rectangles to draw. Type from bit1 of Header.Flags, see above +*/ +} U_PMF_FILLRECTS; + +/** @brief EMF+ manual 2.3.4.21, Microsoft name: EmfPlusFillRegion Record, Index 0x13 + + flags (LITTLE endian here, manual uses BIG endian) + bit 15 U_PPF_B Set: BrushID is an U_PFM_ARGB; Clear: is index of U_PMF_BRUSH object in EMF+ object table. + bits 0-7 Index of an U_PMF_REGION object in the EMF+ object table (0-63, inclusive) +*/ +typedef struct { + U_PMF_CMN_HDR Header; //!< Common header + uint32_t BrushID; //!< Color or index to Brush object, depends on Header.Flags bit0 +} U_PMF_FILLREGION; + +/** @brief EMF+ manual 2.3.5.1, Microsoft name: EmfPlusObject Record, Index 0x13 + + flags (LITTLE endian here, manual uses BIG endian) + bit 15 U_PPF_N Set: object definition continues in next record; Clear: this is the final object definition record + bits 8-14 Type of object being created, ObjectType enumeration + bits 0-7 Index of an U_PMF_REGION object in the EMF+ object table (0-63, inclusive) +*/ +typedef struct { + U_PMF_CMN_HDR Header; //!< Common header +/* + variable part of record, not included in structure + uint8_t Data; //!< Object's data. Type from bits1-7 and bits8-15 of Header.Flags, see above +*/ +} U_PMF_OBJECT; + +/** @brief EMF+ manual 2.3.5.2, Microsoft name: EmfPlusSerializableObject Record, Index 0x38 + + WARNING! Windows XP Preview does not show filter effects, whether or not U_PPF_E is set. They are visible if the EMF+ + file is inserted as an image into PowerPoint. + +*/ +typedef struct { + U_PMF_CMN_HDR Header; //!< Common header (ignore flags and set to zero) + uint8_t GUID[16]; //!< ImageEffects identifier. Composed of Data1[4]-Data2[2]-Data3[2]-Data4[8] + //!< Data1-Data3 are stored as little endian integers. Data4 is stored big endian (like a string) + uint32_t Size; //!< Bytes in Data. +/* + variable part of record, not included in structure + uint8_t Data; //!< "Serialized image effects parameter block". One of the ImageEffects objects. +*/ +} U_PMF_SERIALIZABLEOBJECT; + +/** @brief EMF+ manual 2.3.6.1, Microsoft name: EmfPlusSetAntiAliasMode Record, Index 0x1E + + flags (LITTLE endian here, manual uses BIG endian) + bits 7-1 SmoothingMode enumeration + bit 0 U_PPF_AA Set: anti-aliasing on; Clear: anti-aliasing off +*/ +typedef struct { + U_PMF_CMN_HDR Header; //!< Common header +} U_PMF_SETANTIALIASMODE; + +/** @brief EMF+ manual 2.3.6.2, Microsoft name: EmfPlusSetCompositingMode Record, Index 0x23 + + flags (LITTLE endian here, manual uses BIG endian) + bits 0-7 CompositingMode enumeration +*/ +typedef struct { + U_PMF_CMN_HDR Header; //!< Common header +} U_PMF_SETCOMPOSITINGMODE; + +/** @brief EMF+ manual 2.3.6.3, Microsoft name: EmfPlusSetCompositingQuality Record, Index 0x24 + + flags (LITTLE endian here, manual uses BIG endian) + bits 0-7 CompositingQuality enumeration +*/ +typedef struct { + U_PMF_CMN_HDR Header; //!< Common header +} U_PMF_SETCOMPOSITINGQUALITY; + +/** @brief EMF+ manual 2.3.6.4, Microsoft name: EmfPlusSetInterpolationMode Record, Index 0x21 + + flags (LITTLE endian here, manual uses BIG endian) + bits 0-7 InterpolationMode enumeration +*/ +typedef struct { + U_PMF_CMN_HDR Header; //!< Common header +} U_PMF_SETINTERPOLATIONMODE; + +/** @brief EMF+ manual 2.3.6.5, Microsoft name: EmfPlusSetPixelOffsetMode Record, Index 0x22 + + flags (LITTLE endian here, manual uses BIG endian) + bits 0-7 PixelOffsetMode enumeration +*/ +typedef struct { + U_PMF_CMN_HDR Header; //!< Common header +} U_PMF_SETPIXELOFFSETMODE; + +/** @brief EMF+ manual 2.3.6.6, Microsoft name: EmfPlusSetRenderingOrigin Record, Index 0x1D */ +typedef struct { + U_PMF_CMN_HDR Header; //!< Common header (ignore flags and set to zero) + int32_t X; //!< X coordinate of rendering origin + int32_t Y; //!< Y coordinate of rendering origin +} U_PMF_SETRENDERINGORIGIN; + +/** @brief EMF+ manual 2.3.6.7, Microsoft name: EmfPlusSetTextContrast Record, Index 0x20 + + flags (LITTLE endian here, manual uses BIG endian) + bits 12-0 1000 x Gamma correction value. Range 1000-2200 = gamma 1.0-2.2 +*/ +typedef struct { + U_PMF_CMN_HDR Header; //!< Common header +} U_PMF_SETTEXTCONTRAST; + +/** @brief EMF+ manual 2.3.6.8, Microsoft name: EmfPlusSetTextRenderingHint Record, Index 0x1F + + flags (LITTLE endian here, manual uses BIG endian) + bits 0-7 TextRenderingHint enumeration +*/ +typedef struct { + U_PMF_CMN_HDR Header; //!< Common header +} U_PMF_SETTEXTRENDERINGHINT; + +/** @brief EMF+ manual 2.3.7.1, Microsoft name: EmfPlusBeginContainer Record, Index 0x27 + + flags (LITTLE endian here, manual uses BIG endian) + bits 8-15 UnitType enumeration + bits 0-7 (all zero) +*/ +typedef struct { + U_PMF_CMN_HDR Header; //!< Common header + U_PMF_RECTF DstRect; //!< with SrcRect specifies a transformation + U_PMF_RECTF SrcRect; //!< with DstRect specifies a transformation + uint32_t Index; //!< Index to apply to this graphics container +} U_PMF_BEGINCONTAINER; + +/** @brief EMF+ manual 2.3.7.2, Microsoft name: EmfPlusBeginContainerNoParams Record, Index 0x28 */ +typedef struct { + U_PMF_CMN_HDR Header; //!< Common header (ignore flags and set to zero) + uint32_t Index; //!< Index to apply to this graphics container +} U_PMF_BEGINCONTAINERNOPARAMS; + +/** @brief EMF+ manual 2.3.7.3, Microsoft name: EmfPlusEndContainer Record, Index 0x29 */ +typedef struct { + U_PMF_CMN_HDR Header; //!< Common header (ignore flags and set to zero) + uint32_t Index; //!< Index of container being closed, from U_PMF_BEGINCONTAINERNOPARAMS or U_PMF_BEGINCONTAINER +} U_PMF_ENDCONTAINER; + +/** @brief EMF+ manual 2.3.7.4, Microsoft name: EmfPlusRestore Record, Index 0x26 */ +typedef struct { + U_PMF_CMN_HDR Header; //!< Common header (ignore flags and set to zero) + uint32_t Index; //!< Index of Graphics State being restored, from U_PMF_SAVE +} U_PMF_RESTORE; + +/** @brief EMF+ manual 2.3.7.5, Microsoft name: EmfPlusSave Record, Index 0x25 */ +typedef struct { + U_PMF_CMN_HDR Header; //!< Common header (ignore flags and set to zero) + uint32_t Index; //!< Index of Graphics State being saved +} U_PMF_SAVE; + +/** @brief EMF+ manual 2.3.8.1, Microsoft name: EmfPlusSetTSClip Record, Index 0x3A + + flags (LITTLE endian here, manual uses BIG endian) + bit 15 U_PPF_K Set: Rect is U_PMF_RECT; Clear: Rect is U_PMF_RECTF + bits 14-0 Number of rectangles in Rects field +*/ +typedef struct { + U_PMF_CMN_HDR Header; //!< Common header +/* + variable part of record, not included in structure + U_RECT or U_RECTF Rects; //!< Array of rectangles to draw. Type from bit0 of Header.Flags, see above +*/ +} U_PMF_SETTSCLIP; + +/** @brief EMF+ manual 2.3.8.2, Microsoft name: EmfPlusSetTSGraphics Record, Index 0x39 + + flags (LITTLE endian here, manual uses BIG endian) + bit 1 U_PPF_VGA Set: Palette is VGA basic colors; Clear: Palette is a U_PMF_PALETTE object. + bit 0 U_PPF_PP Set: Palette field is present; Clear: Palette field is absent +*/ +typedef struct { + U_PMF_CMN_HDR Header; //!< Common header + uint8_t AntiAliasMode; //!< SmoothingMode enumeration + uint8_t TextRenderHint; //!< TextRenderingHint enumeration + uint8_t CompositingMode; //!< CompositingMode enumeration + uint8_t CompositingQuality; //!< CompositingQuality enumeration + int16_t RenderOriginX; //!< Origin X for halftoning and dithering + int16_t RenderOriginY; //!< Origin Y for halftoning and dithering + uint16_t TextContrast; //!< Gamma correction, range 0 to 12 + uint8_t FilterType; //!< FilterType enumeraton + uint8_t PixelOffset; //!< PixelOffsetMode enumeration + U_PMF_TRANSFORMMATRIX WorldToDevice; //!< world to device transform +/* + optional part of record, not included in structure + U_PMF_PALETTE Palette; //!< Present if bit15 of Header.Flags is set +*/ +} U_PMF_SETTSGRAPHICS; + +/** @brief EMF+ manual 2.3.9.1, Microsoft name: EmfPlusMultiplyWorldTransform Record, Index 0x2C + + flags (LITTLE endian here, manual uses BIG endian) + bit 13 U_PPF_XM Set: Post multiply; Clear: Pre multiply +*/ +typedef struct { + U_PMF_CMN_HDR Header; //!< Common header + U_PMF_TRANSFORMMATRIX Matrix; //!< Transformation matrix +} U_PMF_MULTIPLYWORLDTRANSFORM; + +/** @brief EMF+ manual 2.3.9.2, Microsoft name: EmfPlusResetWorldTransform Record, Index 0x2B +Sets transformation matrix to identity matrix. +*/ +typedef struct { + U_PMF_CMN_HDR Header; //!< Common header (ignore flags and set to zero) +} U_PMF_RESETWORLDTRANSFORM; + +/** @brief EMF+ manual 2.3.9.3, Microsoft name: EmfPlusRotateWorldTransform Record, Index 0x2F + Construct transformation matrix from Angle: + sin(Angle) cos(Angle) 0 + cos(Angle) -sin(Angle) 0 + Multiply this against current world space transform, result becomes new world space transform. + + flags (LITTLE endian here, manual uses BIG endian) + bit 13 U_PPF_XM Set: Post multiply; Clear: Pre multiply +*/ +typedef struct { + U_PMF_CMN_HDR Header; //!< Common header + U_FLOAT Angle; //!< Rotation angle, in degrees +} U_PMF_ROTATEWORLDTRANSFORM; + +/** @brief EMF+ manual 2.3.9.4, Microsoft name: EmfPlusScaleWorldTransform Record, Index 0x2E + Construct transformation matrix: + Sx 0 0 + 0 Sy 0 + Multiply this against current world space transform, result becomes new world space transform. + + flags (LITTLE endian here, manual uses BIG endian) + bit 13 U_PPF_XM Set: Post multiply; Clear: Pre multiply +*/ +typedef struct { + U_PMF_CMN_HDR Header; //!< Common header + U_FLOAT Sx; //!< X scale factor + U_FLOAT Sy; //!< Y scale factor +} U_PMF_SCALEWORLDTRANSFORM; + +/** @brief EMF+ manual 2.3.9.5, Microsoft name: EmfPlusSetPageTransform Record, Index 0x30 + flags (LITTLE endian here, manual uses BIG endian) + bits 0-7 UnitType enumeration +*/ +typedef struct { + U_PMF_CMN_HDR Header; //!< Common header + U_FLOAT Scale; //!< Scale factor to convert page space to device space +} U_PMF_SETPAGETRANSFORM; + + +/** @brief EMF+ manual 2.3.9.6, Microsoft name: EmfPlusSetWorldTransform Record, Index 0x2A */ +typedef struct { + U_PMF_CMN_HDR Header; //!< Common header (ignore flags and set to zero) + U_PMF_TRANSFORMMATRIX Matrix; //!< Transformation matrix +} U_PMF_SETWORLDTRANSFORM; + +/** @brief EMF+ manual 2.3.9.7, Microsoft name: EmfPlusTranslateWorldTransform Record, Index 0x2D + Construct transformation matrix: + 1 0 Dx + 0 1 Dy + Multiply this against current world space transform, result becomes new world space transform. + + flags (LITTLE endian here, manual uses BIG endian) + bit 13 U_PPF_XM Set: Post multiply; Clear: Pre multiply +*/ +typedef struct { + U_PMF_CMN_HDR Header; //!< Common header + U_FLOAT Dx; //!< X offset + U_FLOAT Dy; //!< Y offset +} U_PMF_TRANSLATEWORLDTRANSFORM; + +//! \cond + +/* EMF+ prototypes (helper functions) */ +int U_PMR_write(U_PSEUDO_OBJ *po, U_PSEUDO_OBJ *sum, EMFTRACK *et); +int U_PMR_drawline(uint32_t PenID, uint32_t PathID, U_PMF_POINTF Start, U_PMF_POINTF End, int Dashed, U_PSEUDO_OBJ *sum, EMFTRACK *et); +int U_PMR_drawstring( const char *string, int Vpos, uint32_t FontID, const U_PSEUDO_OBJ *BrushID, uint32_t FormatID, + U_PMF_STRINGFORMAT Sfs, const char *FontName, U_FLOAT Height, U_FontInfoParams *fip, uint32_t FontFlags, + U_FLOAT x, U_FLOAT y, U_PSEUDO_OBJ *sum, EMFTRACK *et); +U_PMF_POINT *POINTF_To_POINT16_LE(U_PMF_POINTF *points, int count); +int U_PMF_LEN_REL715(const char *contents, int Elements); +int U_PMF_LEN_FLOATDATA(const char *contents); +int U_PMF_LEN_BYTEDATA(const char *contents); +int U_PMF_LEN_PENDATA(const char *PenData); +int U_PMF_LEN_OPTPENDATA(const char *PenData, uint32_t Flags); +char *U_PMF_CURLYGUID_set(uint8_t *GUID); +int U_PMF_KNOWNCURLYGUID_set(const char *string); +void U_PMF_MEMCPY_SRCSHIFT(void *Dst, const char **Src, size_t Size); +void U_PMF_MEMCPY_DSTSHIFT(char **Dst, const void *Src, size_t Size); +void U_PMF_REPCPY_DSTSHIFT(char **Dst, const void *Src, size_t Size, size_t Reps); +void U_PMF_PTRSAV_SHIFT(const char **Dst, const char **Src, size_t Size); +uint16_t U_PMF_HEADERFLAGS_get(const char *contents); +int U_PMF_RECORD_SIZE_get(const char *contents); +int U_PMF_CMN_HDR_get(const char **contents, U_PMF_CMN_HDR *Header); +int U_OID_To_OT(uint32_t OID); +int U_OID_To_BT(uint32_t OID); +int U_OID_To_CLCDT(uint32_t OID); +int U_OID_To_IDT(uint32_t OID); +int U_OID_To_RNDT(uint32_t OID); +uint8_t *U_OID_To_GUID(uint32_t OID); +int U_OA_append(U_OBJ_ACCUM *oa, const char *data, int size, int Type, int Id); +int U_OA_clear(U_OBJ_ACCUM *oa); +int U_OA_release(U_OBJ_ACCUM *oa); +U_PSEUDO_OBJ *U_PO_create(char *Data, size_t Size, size_t Use, uint32_t Type); +U_PSEUDO_OBJ *U_PO_append(U_PSEUDO_OBJ *po, const char *Data, size_t Size); +U_PSEUDO_OBJ *U_PO_po_append(U_PSEUDO_OBJ *po, U_PSEUDO_OBJ *src, int StripE); +int U_PO_free(U_PSEUDO_OBJ **po); +U_DPSEUDO_OBJ *U_PATH_create(int Elements, const U_PMF_POINTF *Points, uint8_t First, uint8_t Others); +int U_DPO_free(U_DPSEUDO_OBJ **dpo); +int U_DPO_clear(U_DPSEUDO_OBJ *dpo); +int U_PATH_moveto(U_DPSEUDO_OBJ *path, U_PMF_POINTF Point, uint8_t Flags); +int U_PATH_lineto(U_DPSEUDO_OBJ *path, U_PMF_POINTF Point, uint8_t Flags); +int U_PATH_closepath(U_DPSEUDO_OBJ *path); +int U_PATH_polylineto(U_DPSEUDO_OBJ *path, uint32_t Elements, const U_PMF_POINTF *Points, uint8_t Flags, uint8_t StartSeg); +int U_PATH_polybezierto(U_DPSEUDO_OBJ *path, uint32_t Elements, const U_PMF_POINTF *Points, uint8_t Flags, uint8_t StartSeg); +int U_PATH_polygon(U_DPSEUDO_OBJ *Path, uint32_t Elements, const U_PMF_POINTF *Points, uint8_t Flags); +int U_PATH_arcto(U_DPSEUDO_OBJ *Path, U_FLOAT Start, U_FLOAT Sweep, U_FLOAT Rot, U_PMF_RECTF *Rect, uint8_t Flags, int StartSeg); +U_PMF_POINTF *pointfs_transform(U_PMF_POINTF *points, int count, U_XFORM xform); +U_PMF_RECTF *rectfs_transform(U_PMF_RECTF *rects, int count, U_XFORM xform); +U_PMF_TRANSFORMMATRIX tm_for_gradrect(U_FLOAT Angle, U_FLOAT w, U_FLOAT h, U_FLOAT x, U_FLOAT y, U_FLOAT Periods); +U_PSEUDO_OBJ *U_PMR_drawfill(uint32_t PathID, uint32_t PenID, const U_PSEUDO_OBJ *BrushID); + + +char *U_pmr_names(unsigned int idx); + +/* EMF+ prototypes (objects_set) */ + +U_PSEUDO_OBJ *U_PMF_BRUSH_set(uint32_t Version, const U_PSEUDO_OBJ *po); +U_PSEUDO_OBJ *U_PMF_CUSTOMLINECAP_set(uint32_t Version, const U_PSEUDO_OBJ *po); +U_PSEUDO_OBJ *U_PMF_FONT_set(uint32_t Version, U_FLOAT EmSize, uint32_t SizeUnit, + int32_t FSFlags, uint32_t Length, const uint16_t *Font); +U_PSEUDO_OBJ *U_PMF_IMAGE_set(uint32_t Version, const U_PSEUDO_OBJ *po); +U_PSEUDO_OBJ *U_PMF_IMAGEATTRIBUTES_set(uint32_t Version, uint32_t WrapMode, uint32_t ClampColor, uint32_t ObjectClamp); +U_PSEUDO_OBJ *U_PMF_PATH_set(uint32_t Version, const U_PSEUDO_OBJ *Points, const U_PSEUDO_OBJ *Types); +U_PSEUDO_OBJ *U_PMF_PATH_set2(uint32_t Version, const U_DPSEUDO_OBJ *Path); +U_PSEUDO_OBJ *U_PMF_PATH_set3(uint32_t Version, const U_DPSEUDO_OBJ *Path); +U_PSEUDO_OBJ *U_PMF_PEN_set(uint32_t Version, const U_PSEUDO_OBJ *PenData, const U_PSEUDO_OBJ *Brush); +U_PSEUDO_OBJ *U_PMF_REGION_set(uint32_t Version, uint32_t Count, const U_PSEUDO_OBJ *Nodes); +U_PSEUDO_OBJ *U_PMF_STRINGFORMAT_set(U_PMF_STRINGFORMAT *Sfs, const U_PSEUDO_OBJ *Sfd); +U_PSEUDO_OBJ *U_PMF_4NUM_set(uint32_t BrushID); +U_PSEUDO_OBJ *U_PMF_ARGB_set(uint8_t Alpha, uint8_t Red, uint8_t Green, uint8_t Blue); +U_PSEUDO_OBJ *U_PMF_ARGBN_set(uint32_t Count, U_PMF_ARGB *Colors); +U_PMF_ARGB U_PMF_ARGBOBJ_set(uint8_t Alpha, uint8_t Red, uint8_t Green, uint8_t Blue); +U_PSEUDO_OBJ *U_PMF_BITMAP_set(const U_PMF_BITMAP *Bs, const U_PSEUDO_OBJ *Bm); +U_PSEUDO_OBJ *U_PMF_BITMAPDATA_set( const U_PSEUDO_OBJ *Ps, int cbBm, const char *Bm); +U_PSEUDO_OBJ *U_PMF_BLENDCOLORS_set(uint32_t Elements, const U_FLOAT *Positions, const U_PSEUDO_OBJ *Colors); +U_PSEUDO_OBJ *U_PMF_BLENDCOLORS_linear_set(uint32_t Elements,U_PMF_ARGB StartColor, U_PMF_ARGB EndColor); +U_PSEUDO_OBJ *U_PMF_BLENDFACTORS_set(uint32_t Elements, const U_FLOAT *Positions, const U_FLOAT *Factors); +U_PSEUDO_OBJ *U_PMF_BLENDFACTORS_linear_set(uint32_t Elements, U_FLOAT StartFactor, U_FLOAT EndFactor); +U_PSEUDO_OBJ *U_PMF_BOUNDARYPATHDATA_set(const U_PSEUDO_OBJ *Path); +U_PSEUDO_OBJ *U_PMF_BOUNDARYPOINTDATA_set(uint32_t Elements, const U_PMF_POINTF *Points); +U_PSEUDO_OBJ *U_PMF_CHARACTERRANGE_set(int32_t First, int32_t Length); +U_PSEUDO_OBJ *U_PMF_COMPOUNDLINEDATA_set(int32_t Elements, const char *Widths); +U_PSEUDO_OBJ *U_PMF_COMPRESSEDIMAGE_set(int32_t cbImage, const char *Image); +U_PSEUDO_OBJ *U_PMF_CUSTOMENDCAPDATA_set(const U_PSEUDO_OBJ *Clc); +U_PSEUDO_OBJ *U_PMF_CUSTOMLINECAPARROWDATA_set(U_FLOAT Width, U_FLOAT Height, + U_FLOAT MiddleInset, uint32_t FillState, uint32_t StartCap, uint32_t EndCap, uint32_t Join, + U_FLOAT MiterLimit, U_FLOAT WidthScale); +U_PSEUDO_OBJ *U_PMF_CUSTOMLINECAPDATA_set(uint32_t Flags, uint32_t Cap, + U_FLOAT Inset, uint32_t StartCap, uint32_t EndCap, + uint32_t Join, U_FLOAT MiterLimit, U_FLOAT WidthScale, + const U_PSEUDO_OBJ *Clcod); +U_PSEUDO_OBJ *U_PMF_CUSTOMLINECAPOPTIONALDATA_set(const U_PSEUDO_OBJ *Fill, const U_PSEUDO_OBJ *Line); +U_PSEUDO_OBJ *U_PMF_CUSTOMSTARTCAPDATA_set(const U_PSEUDO_OBJ *Clc); +U_PSEUDO_OBJ *U_PMF_DASHEDLINEDATA_set(int32_t Elements, const U_FLOAT *Lengths); +U_PSEUDO_OBJ *U_PMF_DASHEDLINEDATA_set2(U_FLOAT Unit, int StdPat); +U_PSEUDO_OBJ *U_PMF_DASHEDLINEDATA_set3(U_FLOAT Unit, uint32_t BitPat); +U_PSEUDO_OBJ *U_PMF_FILLPATHOBJ_set(const U_PSEUDO_OBJ *Path); +U_PSEUDO_OBJ *U_PMF_FOCUSSCALEDATA_set(U_FLOAT ScaleX, U_FLOAT ScaleY); +U_PSEUDO_OBJ *U_PMF_GRAPHICSVERSION_set(int GrfVersion); +U_PMF_GRAPHICSVERSION U_PMF_GRAPHICSVERSIONOBJ_set(int GrfVersion); +U_PSEUDO_OBJ *U_PMF_HATCHBRUSHDATA_set(uint32_t Style, const U_PSEUDO_OBJ *Fg, const U_PSEUDO_OBJ *Bg); +U_PSEUDO_OBJ *U_PMF_INTEGER7_set(int value); +U_PSEUDO_OBJ *U_PMF_INTEGER15_set(int value); +U_PMF_LANGUAGEIDENTIFIER U_PMF_LANGUAGEIDENTIFIEROBJ_set(int SubLId, int PriLId); +U_PSEUDO_OBJ *U_PMF_LANGUAGEIDENTIFIER_set(U_PMF_LANGUAGEIDENTIFIER LId); +U_PSEUDO_OBJ *U_PMF_LINEARGRADIENTBRUSHDATA_set(const U_PMF_LINEARGRADIENTBRUSHDATA *Lgbd, const U_PSEUDO_OBJ *Lgbod); +U_PSEUDO_OBJ *U_PMF_LINEARGRADIENTBRUSHOPTIONALDATA_set(uint32_t *Flags, const U_PSEUDO_OBJ *Tm, const U_PSEUDO_OBJ *Bc, const U_PSEUDO_OBJ *BfH, const U_PSEUDO_OBJ *BfV); +U_PSEUDO_OBJ *U_PMF_LINEPATH_set(const U_PSEUDO_OBJ *Path); +U_PSEUDO_OBJ *U_PMF_METAFILE_set(void); +U_PSEUDO_OBJ *U_PMF_PALETTE_set(uint32_t Flags, uint32_t Elements, const U_PMF_ARGB *Pd); +U_PSEUDO_OBJ *U_PMF_PATHGRADIENTBRUSHDATA_set(uint32_t Flags, int32_t WrapMode, U_PMF_ARGB CenterColor, + U_PMF_POINTF Center, const U_PSEUDO_OBJ *Gradient, const U_PSEUDO_OBJ *Boundary, const U_PSEUDO_OBJ *Data); +U_PSEUDO_OBJ *U_PMF_PATHGRADIENTBRUSHOPTIONALDATA_set(uint32_t Flags, + const U_PSEUDO_OBJ *Tm, const U_PSEUDO_OBJ *Pd, const U_PSEUDO_OBJ *Fsd); +U_PSEUDO_OBJ *U_PMF_PATHPOINTTYPE_set(uint32_t Elements, const uint8_t *Ppt); +U_PSEUDO_OBJ *U_PMF_PATHPOINTTYPE_set2(uint32_t Elements, uint8_t Start, uint8_t Others); +U_PSEUDO_OBJ *U_PMF_PATHPOINTTYPERLE_set(uint32_t Elements, const uint8_t *Bz, const uint8_t *RL, const uint8_t *Ppte); +U_PSEUDO_OBJ *U_PMF_PENDATA_set(uint32_t Unit, U_FLOAT Width, const U_PSEUDO_OBJ *Pod); +U_PSEUDO_OBJ *U_PMF_PENOPTIONALDATA_set(uint32_t Flags, U_PSEUDO_OBJ *Tm, int32_t StartCap, int32_t EndCap, uint32_t Join, + U_FLOAT MiterLimit, int32_t Style, int32_t DLCap, U_FLOAT DLOffset, + U_PSEUDO_OBJ *DLData, int32_t PenAlignment, U_PSEUDO_OBJ *CmpndLineData, U_PSEUDO_OBJ *CSCapData, + U_PSEUDO_OBJ *CECapData); +U_PSEUDO_OBJ *U_PMF_POINT_set(uint32_t Elements, const U_PMF_POINT *Coords); +U_PSEUDO_OBJ *U_PMF_POINTF_set(uint32_t Elements, const U_PMF_POINTF *Coords); +U_PSEUDO_OBJ *U_PMF_POINTR_set(uint32_t Elements, const U_PMF_POINTF *Coords); +U_PSEUDO_OBJ *U_PMF_RECT4_set(int16_t X, int16_t Y, int16_t Width, int16_t Height); +U_PSEUDO_OBJ *U_PMF_RECT_set(U_PMF_RECT *Rect); +U_PSEUDO_OBJ *U_PMF_RECTN_set(uint32_t Elements, U_PMF_RECT *Rects); +U_PSEUDO_OBJ *U_PMF_RECTF4_set(U_FLOAT X, U_FLOAT Y, U_FLOAT Width, U_FLOAT Height); +U_PSEUDO_OBJ *U_PMF_RECTF_set(U_PMF_RECTF *Rect); +U_PSEUDO_OBJ *U_PMF_RECTFN_set(uint32_t Elements, U_PMF_RECTF *Rects); +U_PSEUDO_OBJ *U_PMF_REGIONNODE_set(int32_t Type, const U_PSEUDO_OBJ *Rnd); +U_PSEUDO_OBJ *U_PMF_REGIONNODECHILDNODES_set(const U_PSEUDO_OBJ *Left, const U_PSEUDO_OBJ *Right); +U_PSEUDO_OBJ *U_PMF_REGIONNODEPATH_set(const U_PSEUDO_OBJ *Path); +U_PSEUDO_OBJ *U_PMF_SOLIDBRUSHDATA_set(const U_PSEUDO_OBJ *Color); +U_PSEUDO_OBJ *U_PMF_STRINGFORMATDATA_set(uint32_t TabStopCount, U_FLOAT *TabStops, const U_PSEUDO_OBJ *Ranges); +U_PSEUDO_OBJ *U_PMF_TEXTUREBRUSHDATA_set(uint32_t Flags, uint32_t WrapMode, const U_PSEUDO_OBJ *Tbod); +U_PSEUDO_OBJ *U_PMF_TEXTUREBRUSHOPTIONALDATA_set(const U_PSEUDO_OBJ *Tm, const U_PSEUDO_OBJ *Image); +U_PSEUDO_OBJ *U_PMF_TRANSFORMMATRIX_set(U_PMF_TRANSFORMMATRIX *Tm); +U_PSEUDO_OBJ *U_PMF_IE_BLUR_set(U_FLOAT Radius, uint32_t ExpandEdge); +U_PSEUDO_OBJ *U_PMF_IE_BRIGHTNESSCONTRAST_set(int32_t Brightness, int32_t Contrast); +U_PSEUDO_OBJ *U_PMF_IE_COLORBALANCE_set(int32_t CyanRed, int32_t MagentaGreen, int32_t YellowBlue); +U_PSEUDO_OBJ *U_PMF_IE_COLORCURVE_set(uint32_t Adjust, uint32_t Channel, int32_t Intensity); +U_PSEUDO_OBJ *U_PMF_IE_COLORLOOKUPTABLE_set(const uint8_t *BLUT, const uint8_t *GLUT, const uint8_t *RLUT, const uint8_t *ALUT); +U_PSEUDO_OBJ *U_PMF_IE_COLORMATRIX_set(const U_FLOAT *Matrix); +U_PSEUDO_OBJ *U_PMF_IE_HUESATURATIONLIGHTNESS_set(int32_t Hue, int32_t Saturation, int32_t Lightness); +U_PSEUDO_OBJ *U_PMF_IE_LEVELS_set(int32_t Highlight, int32_t Midtone, int32_t Shadow); +U_PSEUDO_OBJ *U_PMF_IE_REDEYECORRECTION_set(uint32_t Elements, const U_RECTL *rects); +U_PSEUDO_OBJ *U_PMF_IE_SHARPEN_set(U_FLOAT Radius, int32_t Sharpen); +U_PSEUDO_OBJ *U_PMF_IE_TINT_set(int32_t Hue, int32_t Amount); +U_PSEUDO_OBJ *U_PMR_SERIALIZABLEOBJECT_set(const U_PSEUDO_OBJ *Siepb); + +/* EMF+ prototypes (records_set) */ + +U_PSEUDO_OBJ *U_PMR_OFFSETCLIP_set(U_FLOAT dX, U_FLOAT dY); +U_PSEUDO_OBJ *U_PMR_RESETCLIP_set(void); +U_PSEUDO_OBJ *U_PMR_SETCLIPPATH_set(uint32_t PathID, uint32_t CMenum); +U_PSEUDO_OBJ *U_PMR_SETCLIPRECT_set(uint32_t CMenum, const U_PSEUDO_OBJ *Rect); +U_PSEUDO_OBJ *U_PMR_SETCLIPREGION_set(uint32_t PathID, uint32_t CMenum); +U_PSEUDO_OBJ *U_PMR_COMMENT_set(size_t cbData, const void *Data); +U_PSEUDO_OBJ *U_PMR_ENDOFFILE_set(void); +U_PSEUDO_OBJ *U_PMR_GETDC_set(void); +U_PSEUDO_OBJ *U_PMR_HEADER_set(int IsDual, int IsVideo, const U_PSEUDO_OBJ *Version, + uint32_t LogicalDpiX, uint32_t LogicalDpiY); +U_PSEUDO_OBJ *U_PMR_CLEAR_set(const U_PSEUDO_OBJ *Color); +U_PSEUDO_OBJ *U_PMR_DRAWARC_set(uint32_t PenID, U_FLOAT Start, U_FLOAT Sweep, const U_PSEUDO_OBJ *Rect); +U_PSEUDO_OBJ *U_PMR_DRAWBEZIERS_set(uint32_t PenID, const U_PSEUDO_OBJ *Points); +U_PSEUDO_OBJ *U_PMR_DRAWCLOSEDCURVE_set(uint32_t PenID, U_FLOAT Tension, const U_PSEUDO_OBJ *Points); +U_PSEUDO_OBJ *U_PMR_DRAWCURVE_set(uint32_t PenID, U_FLOAT Tension,uint32_t Offset, uint32_t NSegs, const U_PSEUDO_OBJ *Points); +U_PSEUDO_OBJ *U_PMR_DRAWDRIVERSTRING_set(uint32_t FontID, const U_PSEUDO_OBJ *BrushID, + uint32_t DSOFlags, uint32_t HasMatrix, uint32_t GlyphCount, + const uint16_t *Glyphs, const U_PSEUDO_OBJ *Points, const U_PSEUDO_OBJ *Tm); +U_PSEUDO_OBJ *U_PMR_DRAWELLIPSE_set(uint32_t PenID, const U_PSEUDO_OBJ *Rect); +U_PSEUDO_OBJ *U_PMR_DRAWIMAGE_set(uint32_t ImgID, int32_t ImgAttrID, int32_t SrcUnit, const U_PSEUDO_OBJ *SrcRect, const U_PSEUDO_OBJ *DstRect); +U_PSEUDO_OBJ *U_PMR_DRAWIMAGEPOINTS_set(uint32_t ImgID, int etype, int32_t ImgAttrID, int32_t SrcUnit, const U_PSEUDO_OBJ *SrcRect, const U_PSEUDO_OBJ *Points); +U_PSEUDO_OBJ *U_PMR_DRAWLINES_set(uint32_t PenID, int dtype, const U_PSEUDO_OBJ *Points); +U_PSEUDO_OBJ *U_PMR_DRAWPATH_set(uint32_t PathID, uint32_t PenID); +U_PSEUDO_OBJ *U_PMR_DRAWPIE_set(uint32_t PenID, U_FLOAT Start, U_FLOAT Sweep, const U_PSEUDO_OBJ *Rect); +U_PSEUDO_OBJ *U_PMR_DRAWRECTS_set(uint32_t PenID, const U_PSEUDO_OBJ *Rects); +U_PSEUDO_OBJ *U_PMR_DRAWSTRING_set(uint32_t FontID, const U_PSEUDO_OBJ *BrushID, + uint32_t FormatID, uint32_t Length, const U_PSEUDO_OBJ *Rect, const uint16_t *Text); +U_PSEUDO_OBJ *U_PMR_FILLCLOSEDCURVE_set(int ftype, U_FLOAT Tension, const U_PSEUDO_OBJ * BrushID, const U_PSEUDO_OBJ *Points); +U_PSEUDO_OBJ *U_PMR_FILLELLIPSE_set(const U_PSEUDO_OBJ * BrushID, const U_PSEUDO_OBJ *Rect); +U_PSEUDO_OBJ *U_PMR_FILLPATH_set(uint32_t PathID, const U_PSEUDO_OBJ * BrushID); +U_PSEUDO_OBJ *U_PMR_FILLPIE_set(U_FLOAT Start, U_FLOAT Sweep, const U_PSEUDO_OBJ *BrushID, const U_PSEUDO_OBJ *Rect); +U_PSEUDO_OBJ *U_PMR_FILLPOLYGON_set(const U_PSEUDO_OBJ *BrushID, const U_PSEUDO_OBJ *Points); +U_PSEUDO_OBJ *U_PMR_FILLRECTS_set(const U_PSEUDO_OBJ *BrushID, const U_PSEUDO_OBJ *Rects); +U_PSEUDO_OBJ *U_PMR_FILLREGION_set(uint32_t RgnID, const U_PSEUDO_OBJ *BrushID); +U_PSEUDO_OBJ *U_PMR_OBJECT_PO_set(uint32_t ObjID, U_PSEUDO_OBJ *Po); +U_PSEUDO_OBJ *U_PMR_OBJECT_set(uint32_t ObjID, int otype, int ntype, uint32_t TSize, size_t cbData, const char *Data); +U_PSEUDO_OBJ *U_PMR_SETANTIALIASMODE_set(int SMenum, int aatype); +U_PSEUDO_OBJ *U_PMR_SETCOMPOSITINGMODE_set(int CMenum); +U_PSEUDO_OBJ *U_PMR_SETCOMPOSITINGQUALITY_set(int CQenum); +U_PSEUDO_OBJ *U_PMR_SETINTERPOLATIONMODE_set(int IMenum); +U_PSEUDO_OBJ *U_PMR_SETPIXELOFFSETMODE_set(int POMenum); +U_PSEUDO_OBJ *U_PMR_SETRENDERINGORIGIN_set(int32_t X, int32_t Y); +U_PSEUDO_OBJ *U_PMR_SETTEXTCONTRAST_set(int GC); +U_PSEUDO_OBJ *U_PMR_SETTEXTRENDERINGHINT_set(int TRHenum); +U_PSEUDO_OBJ *U_PMR_BEGINCONTAINER_set(int UTenum, U_PSEUDO_OBJ *DstRect, U_PSEUDO_OBJ *SrcRect, uint32_t StackID); +U_PSEUDO_OBJ *U_PMR_BEGINCONTAINERNOPARAMS_set(int StackID); +U_PSEUDO_OBJ *U_PMR_ENDCONTAINER_set(int StackID); +U_PSEUDO_OBJ *U_PMR_RESTORE_set(int StackID); +U_PSEUDO_OBJ *U_PMR_SAVE_set(int StackID); +U_PSEUDO_OBJ *U_PMR_SETTSCLIP_set(U_PSEUDO_OBJ *Rects); +U_PSEUDO_OBJ *U_PMR_SETTSGRAPHICS_set(int vgatype, U_PMF_SETTSGRAPHICS *Tsg, U_PSEUDO_OBJ *Palette); +U_PSEUDO_OBJ *U_PMR_MULTIPLYWORLDTRANSFORM_set(int xmtype, U_PSEUDO_OBJ *Tm); +U_PSEUDO_OBJ *U_PMR_RESETWORLDTRANSFORM_set(void); +U_PSEUDO_OBJ *U_PMR_ROTATEWORLDTRANSFORM_set(int xmtype, U_FLOAT Angle); +U_PSEUDO_OBJ *U_PMR_SCALEWORLDTRANSFORM_set(int xmtype, U_FLOAT X, U_FLOAT Y); +U_PSEUDO_OBJ *U_PMR_SETPAGETRANSFORM_set(int PUenum, U_FLOAT Sale); +U_PSEUDO_OBJ *U_PMR_SETWORLDTRANSFORM_set(U_PSEUDO_OBJ *Tm); +U_PSEUDO_OBJ *U_PMR_TRANSLATEWORLDTRANSFORM_set(int xmtype, U_FLOAT Dx, U_FLOAT Dy); +U_PSEUDO_OBJ *U_PMR_STROKEFILLPATH_set(void); + + + + +/* EMF+ prototypes (objects_get) */ + +int U_PMF_BRUSH_get(const char *contents, uint32_t *Version, uint32_t *Type, const char **Data, const char *blimit); +int U_PMF_CUSTOMLINECAP_get(const char *contents, uint32_t *Version, uint32_t *Type, const char **Data, const char *blimit); +int U_PMF_FONT_get(const char *contents, uint32_t *Version, U_FLOAT *EmSize, uint32_t *SizeUnit, int32_t *FSFlags, uint32_t *Length, const char **Data, const char *blimit); +int U_PMF_IMAGE_get(const char *contents, uint32_t *Version, uint32_t *Type, const char **Data, const char *blimit); +int U_PMF_IMAGEATTRIBUTES_get(const char *contents, uint32_t *Version, uint32_t *WrapMode, uint32_t *ClampColor, uint32_t *ObjectClamp, const char *blimit); +int U_PMF_PATH_get(const char *contents, uint32_t *Version, uint32_t *Count, uint16_t *Flags, const char **Points, const char **Types, const char *blimit); +int U_PMF_PEN_get(const char *contents, uint32_t *Version, uint32_t *Type, const char **PenData, const char **Brush, const char *blimit); +int U_PMF_REGION_get(const char *contents, uint32_t *Version, uint32_t *Count, const char **Nodes, const char *blimit); +int U_PMF_STRINGFORMAT_get(const char *contents, U_PMF_STRINGFORMAT *Sfs, const char **Data, const char *blimit); +int U_PMF_ARGB_get(const char *contents, uint8_t *Blue, uint8_t *Green, uint8_t *Red, uint8_t *Alpha, const char *blimit); +int U_PMF_BITMAP_get(const char *contents, U_PMF_BITMAP *Bs, const char **Data, const char *blimit); +int U_PMF_BITMAPDATA_get(const char *contents, U_PMF_PALETTE *Ps, const char **Colors, const char **Data, const char *blimit); +int U_PMF_BLENDCOLORS_get(const char *contents, uint32_t *Elements, U_FLOAT **Positions, const char **Colors, const char *blimit); +int U_PMF_BLENDFACTORS_get(const char *contents, uint32_t *Elements, U_FLOAT **Positions, U_FLOAT **Factors, const char *blimit); +int U_PMF_BOUNDARYPATHDATA_get(const char *contents, int32_t *Size, const char **Data, const char *blimit); +int U_PMF_BOUNDARYPOINTDATA_get(const char *contents, int32_t *Elements, U_PMF_POINTF **Points, const char *blimit); +int U_PMF_CHARACTERRANGE_get(const char *contents, int32_t *First, int32_t *Length, const char *blimit); +int U_PMF_COMPOUNDLINEDATA_get(const char *contents, int32_t *Elements, U_FLOAT **Widths, const char *blimit); +int U_PMF_COMPRESSEDIMAGE_get(const char *contents, const char **Data, const char *blimit); +int U_PMF_CUSTOMENDCAPDATA_get(const char *contents, int32_t *Size, const char **Data, const char *blimit); +int U_PMF_CUSTOMLINECAPARROWDATA_get(const char *contents, U_PMF_CUSTOMLINECAPARROWDATA *Ccad, const char *blimit); +int U_PMF_CUSTOMLINECAPDATA_get(const char *contents, U_PMF_CUSTOMLINECAPDATA *Clcd, const char **Data, const char *blimit); +int U_PMF_CUSTOMLINECAPOPTIONALDATA_get(const char *contents, uint32_t Flags, const char **FillData, const char **LineData, const char *blimit); +int U_PMF_CUSTOMSTARTCAPDATA_get(const char *contents, int32_t *Size, const char **Data, const char *blimit); +int U_PMF_DASHEDLINEDATA_get(const char *contents, int32_t *Elements, U_FLOAT **Lengths, const char *blimit); +int U_PMF_FILLPATHOBJ_get(const char *contents, int32_t *Size, const char **Data, const char *blimit); +int U_PMF_FOCUSSCALEDATA_get(const char *contents, uint32_t *Count, U_FLOAT *ScaleX, U_FLOAT *ScaleY, const char *blimit); +int U_PMF_GRAPHICSVERSION_get(const char *contents, int *Signature, int *GrfVersion, const char *blimit); +int U_PMF_HATCHBRUSHDATA_get(const char *contents, uint32_t *Style, U_PMF_ARGB *Foreground, U_PMF_ARGB *Background, const char *blimit); +int U_PMF_INTEGER7_get(const char **contents, U_FLOAT *Value, const char *blimit); +int U_PMF_INTEGER15_get(const char **contents, U_FLOAT *Value, const char *blimit); +int U_PMF_LANGUAGEIDENTIFIER_get(U_PMF_LANGUAGEIDENTIFIER LId, int *SubLId, int *PriLId); +int U_PMF_LINEARGRADIENTBRUSHDATA_get(const char *contents, U_PMF_LINEARGRADIENTBRUSHDATA *Lgbd, const char **Data, const char *blimit); +int U_PMF_LINEARGRADIENTBRUSHOPTIONALDATA_get(const char *contents, uint32_t Flags, U_PMF_TRANSFORMMATRIX *Tm, const char **Bc, const char **BfH, const char **BfV, const char *blimit); +int U_PMF_LINEPATH_get(const char *contents, int32_t *Size, const char **Data, const char *blimit); +int U_PMF_METAFILE_get(const char *contents, uint32_t *Type, uint32_t *Size, const char **Data, const char *blimit); +int U_PMF_PALETTE_get(const char *contents, uint32_t *Flags, uint32_t *Elements, const char **Data, const char *blimit); +int U_PMF_PATHGRADIENTBRUSHDATA_get(const char *contents, U_PMF_PATHGRADIENTBRUSHDATA *Pgbd, const char **Gradient, const char **Boundary, const char **Data, const char *blimit); +int U_PMF_PATHGRADIENTBRUSHOPTIONALDATA_get(const char *contents, uint32_t Flags, U_PMF_TRANSFORMMATRIX *Matrix, const char **Pattern, const char **Data, const char *blimit); +int U_PMF_PATHPOINTTYPE_get(const char *contents, int *Flags, int *Type, const char *blimit); +int U_PMF_PATHPOINTTYPERLE_get(const char *contents, int *Bezier, int *RL, int *Ppt, const char *blimit); +int U_PMF_PENDATA_get(const char *contents, uint32_t *Flags, uint32_t *Unit, U_FLOAT *Width, const char **Data, const char *blimit); +int U_PMF_PENOPTIONALDATA_get(const char *contents, uint32_t Flags, U_PMF_TRANSFORMMATRIX *Matrix, + int32_t *StartCap, int32_t *EndCap, uint32_t *Join, U_FLOAT *MiterLimit, int32_t *Style, int32_t *DLCap, U_FLOAT *DLOffset, + const char **DLData, int32_t *Alignment, const char **CmpndLineData, const char **CSCapData, const char **CECapData, const char *blimit); +int U_PMF_POINT_get(const char **contents, U_FLOAT *X, U_FLOAT *Y, const char *blimit); +int U_PMF_POINTF_get(const char **contents, U_FLOAT *X, U_FLOAT *Y, const char *blimit); +int U_PMF_POINTR_get(const char **contents, U_FLOAT *X, U_FLOAT *Y, const char *blimit); +int U_PMF_RECT_get(const char **contents, int16_t *X, int16_t *Y, int16_t *Width, int16_t *Height, const char *blimit); +int U_PMF_RECTF_get(const char **contents, U_FLOAT *X, U_FLOAT *Y, U_FLOAT *Width, U_FLOAT *Height, const char *blimit); +int U_PMF_REGIONNODE_get(const char *contents, uint32_t *Type, const char **Data, const char *blimit); +/* There is no U_PMF_REGIONNODECHILDNODES_get, see the note in upmf.c */ +int U_PMF_REGIONNODEPATH_get(const char *contents, int32_t *Size, const char **Data, const char *blimit); +int U_PMF_SOLIDBRUSHDATA_get(const char *contents, U_PMF_ARGB *Color, const char *blimit); +int U_PMF_STRINGFORMATDATA_get(const char *contents, uint32_t TabStopCount, uint32_t RangeCount, + const U_FLOAT **TabStops, const U_PMF_CHARACTERRANGE **CharRange, const char *blimit); +int U_PMF_TEXTUREBRUSHDATA_get(const char *contents, uint32_t *Flags, int32_t *WrapMode, const char **Data, const char *blimit); +int U_PMF_TEXTUREBRUSHOPTIONALDATA_get(const char *contents, int HasImage, U_PMF_TRANSFORMMATRIX *Matrix, const char **Image, const char *blimit); +int U_PMF_TRANSFORMMATRIX_get(const char *contents, U_PMF_TRANSFORMMATRIX *Matrix, const char *blimit); +int U_PMF_IE_BLUR_get(const char *contents, U_FLOAT *Radius, uint32_t *ExpandEdge, const char *blimit); +int U_PMF_IE_BRIGHTNESSCONTRAST_get(const char *contents, int32_t *Brightness, int32_t *Contrast, const char *blimit); +int U_PMF_IE_COLORBALANCE_get(const char *contents, int32_t *CyanRed, int32_t *MagentaGreen, int32_t *YellowBlue, const char *blimit); +int U_PMF_IE_COLORCURVE_get(const char *contents, uint32_t *Adjust, uint32_t *Channel, int32_t *Intensity, const char *blimit); +int U_PMF_IE_COLORLOOKUPTABLE_get(const char *contents, + const uint8_t **BLUT, const uint8_t **GLUT, const uint8_t **RLUT, const uint8_t **ALUT, const char *blimit); +int U_PMF_IE_COLORMATRIX_get(const char *contents, U_PMF_IE_COLORMATRIX *Matrix, const char *blimit); +int U_PMF_IE_HUESATURATIONLIGHTNESS_get(const char *contents, int32_t *Hue, int32_t *Saturation, int32_t *Lightness, const char *blimit); +int U_PMF_IE_LEVELS_get(const char *contents, int32_t *Highlight, int32_t *Midtone, int32_t *Shadow, const char *blimit); +int U_PMF_IE_REDEYECORRECTION_get(const char *contents, int32_t *Elements, U_RECTL **Rects, const char *blimit); +int U_PMF_IE_SHARPEN_get(const char *contents, U_FLOAT *Radius, int32_t *Sharpen, const char *blimit); +int U_PMF_IE_TINT_get(const char *contents, int32_t *Hue, int32_t *Amount, const char *blimit); + +/* EMF+ prototypes (records_get) */ + +int U_PMR_OFFSETCLIP_get(const char *contents, U_PMF_CMN_HDR *Header, U_FLOAT *dX, U_FLOAT *dY); +int U_PMR_RESETCLIP_get(const char *contents, U_PMF_CMN_HDR *Header); +int U_PMR_SETCLIPPATH_get(const char *contents, U_PMF_CMN_HDR *Header, uint32_t *PathID, int *CMenum); +int U_PMR_SETCLIPRECT_get(const char *contents, U_PMF_CMN_HDR *Header, int *CMenum, U_PMF_RECTF *Rect); +int U_PMR_SETCLIPREGION_get(const char *contents, U_PMF_CMN_HDR *Header, uint32_t *PathID, int *CMenum); +int U_PMR_COMMENT_get(const char *contents, U_PMF_CMN_HDR *Header, const char **Data); +int U_PMR_ENDOFFILE_get(const char *contents, U_PMF_CMN_HDR *Header); +int U_PMR_GETDC_get(const char *contents, U_PMF_CMN_HDR *Header); +int U_PMR_HEADER_get(const char *contents, U_PMF_CMN_HDR *Header, U_PMF_GRAPHICSVERSION *Version, int *IsDual, int *IsVideo, uint32_t *LogicalDpiX, uint32_t *LogicalDpiY); +int U_PMR_CLEAR_get(const char *contents, U_PMF_CMN_HDR *Header, U_PMF_ARGB *Color); +int U_PMR_DRAWARC_get(const char *contents, U_PMF_CMN_HDR *Header, uint32_t *PenID, int *ctype, U_FLOAT *Start, U_FLOAT *Sweep, U_PMF_RECTF *Rect); +int U_PMR_DRAWBEZIERS_get(const char *contents, U_PMF_CMN_HDR *Header, uint32_t *PenID, int *ctype, int *RelAbs, uint32_t *Elements, U_PMF_POINTF **Points); +int U_PMR_DRAWCLOSEDCURVE_get(const char *contents, U_PMF_CMN_HDR *Header, uint32_t *PenID, int *ctype, int *RelAbs, U_FLOAT *Tension, uint32_t *Elements, U_PMF_POINTF **Points); +int U_PMR_DRAWCURVE_get(const char *contents, U_PMF_CMN_HDR *Header, uint32_t *PenID, int *ctype, U_FLOAT *Tension, uint32_t *Offset, uint32_t *NSegs, uint32_t *Elements, U_PMF_POINTF **Points); +int U_PMR_DRAWDRIVERSTRING_get(const char *contents, U_PMF_CMN_HDR *Header, uint32_t *FontID, int *btype, uint32_t *BrushID, uint32_t *DSOFlags, uint32_t *HasMatrix, uint32_t *Elements, uint16_t **Glyphs, U_PMF_POINTF **Points, U_PMF_TRANSFORMMATRIX **Matrix); +int U_PMR_DRAWELLIPSE_get(const char *contents, U_PMF_CMN_HDR *Header, uint32_t *PenID, int *ctype, U_PMF_RECTF *Rect); +int U_PMR_DRAWIMAGE_get(const char *contents, U_PMF_CMN_HDR *Header, uint32_t *ImgID, int *ctype, uint32_t *ImgAttrID, int32_t *SrcUnit, U_PMF_RECTF *SrcRect, U_PMF_RECTF *DstRect); +int U_PMR_DRAWIMAGEPOINTS_get(const char *contents, U_PMF_CMN_HDR *Header, uint32_t *ImgID, int *ctype, int *etype, int *RelAbs, uint32_t *ImgAttrID, int32_t *SrcUnit, U_PMF_RECTF *SrcRect, uint32_t *Elements, U_PMF_POINTF **Points); +int U_PMR_DRAWLINES_get(const char *contents, U_PMF_CMN_HDR *Header, uint32_t *PenID, int *ctype, int *dtype, int *RelAbs, uint32_t *Elements, U_PMF_POINTF **Points); +int U_PMR_DRAWPATH_get(const char *contents, U_PMF_CMN_HDR *Header, uint32_t *PathID, uint32_t *PenID); +int U_PMR_DRAWPIE_get(const char *contents, U_PMF_CMN_HDR *Header, uint32_t *PenID, int *ctype, U_FLOAT *Start, U_FLOAT *Sweep, U_PMF_RECTF *Rect); +int U_PMR_DRAWRECTS_get(const char *contents, U_PMF_CMN_HDR *Header, uint32_t *PenID, int *ctype, uint32_t *Elements, U_PMF_RECTF **Rects); +int U_PMR_DRAWSTRING_get(const char *contents, U_PMF_CMN_HDR *Header, uint32_t *FontID, int *btype, uint32_t *BrushID, uint32_t *FormatID, uint32_t *Elements, U_PMF_RECTF *Rect, uint16_t **String); +int U_PMR_FILLCLOSEDCURVE_get(const char *contents, U_PMF_CMN_HDR *Header, int *btype, int *ctype, int *ftype, int *RelAbs, uint32_t *BrushID, U_FLOAT *Tension, uint32_t *Elements, U_PMF_POINTF **Points); +int U_PMR_FILLELLIPSE_get(const char *contents, U_PMF_CMN_HDR *Header, int *btype, int *ctype, uint32_t *BrushID, U_PMF_RECTF *Rect); +int U_PMR_FILLPATH_get(const char *contents, U_PMF_CMN_HDR *Header, uint32_t *PathID, int *btype, uint32_t *BrushID); +int U_PMR_FILLPIE_get(const char *contents, U_PMF_CMN_HDR *Header, int *btype, int *ctype, uint32_t *BrushID, U_FLOAT *Start, U_FLOAT *Sweep, U_PMF_RECTF *Rect); +int U_PMR_FILLPOLYGON_get(const char *contents, U_PMF_CMN_HDR *Header, int *btype, int *ctype, int *RelAbs, uint32_t *BrushID, uint32_t *Elements, U_PMF_POINTF **Points); +int U_PMR_FILLRECTS_get(const char *contents, U_PMF_CMN_HDR *Header, int *btype, int *ctype, uint32_t *BrushID, uint32_t *Elements, U_PMF_RECTF **Rects); +int U_PMR_FILLREGION_get(const char *contents, U_PMF_CMN_HDR *Header, uint32_t *RgnID, int *btype, int *ctype, uint32_t *BrushID); +int U_PMR_OBJECT_get(const char *contents, U_PMF_CMN_HDR *Header, uint32_t *ObjID, int *otype, int *ntype, uint32_t *TSize, const char **Data); +int U_PMR_SERIALIZABLEOBJECT_get(const char *contents, U_PMF_CMN_HDR *Header, uint8_t *GUID, uint32_t *Size, const char **Data); +int U_PMR_SETANTIALIASMODE_get(const char *contents, U_PMF_CMN_HDR *Header, int *SMenum, int *aatype); +int U_PMR_SETCOMPOSITINGMODE_get(const char *contents, U_PMF_CMN_HDR *Header, int *CMenum); +int U_PMR_SETCOMPOSITINGQUALITY_get(const char *contents, U_PMF_CMN_HDR *Header, int *CQenum); +int U_PMR_SETINTERPOLATIONMODE_get(const char *contents, U_PMF_CMN_HDR *Header, int *IMenum); +int U_PMR_SETPIXELOFFSETMODE_get(const char *contents, U_PMF_CMN_HDR *Header, int *POMenum); +int U_PMR_SETRENDERINGORIGIN_get(const char *contents, U_PMF_CMN_HDR *Header, int32_t *X, int32_t *Y); +int U_PMR_SETTEXTCONTRAST_get(const char *contents, U_PMF_CMN_HDR *Header, int *TGC); +int U_PMR_SETTEXTRENDERINGHINT_get(const char *contents, U_PMF_CMN_HDR *Header, int *TRHenum); +int U_PMR_BEGINCONTAINER_get(const char *contents, U_PMF_CMN_HDR *Header, int *UTenum, U_PMF_RECTF *DstRect, U_PMF_RECTF *SrcRect, uint32_t *StackID); +int U_PMR_BEGINCONTAINERNOPARAMS_get(const char *contents, U_PMF_CMN_HDR *Header, uint32_t *StackID); +int U_PMR_ENDCONTAINER_get(const char *contents, U_PMF_CMN_HDR *Header, uint32_t *StackID); +int U_PMR_RESTORE_get(const char *contents, U_PMF_CMN_HDR *Header, uint32_t *StackID); +int U_PMR_SAVE_get(const char *contents, U_PMF_CMN_HDR *Header, uint32_t *StackID); +int U_PMR_SETTSCLIP_get(const char *contents, U_PMF_CMN_HDR *Header, int *ctype, uint32_t *Elements, U_PMF_RECTF **Rects); +int U_PMR_SETTSGRAPHICS_get(const char *contents, U_PMF_CMN_HDR *Header, int *vgatype, int *pptype, uint8_t *AntiAliasMode, uint8_t *TextRenderHint, uint8_t *CompositingMode, uint8_t *CompositingQuality, int16_t *RenderOriginX, int16_t *RenderOriginY, uint16_t *TextContrast, uint8_t *FilterType, uint8_t *PixelOffset, U_PMF_TRANSFORMMATRIX *WorldToDevice, const char **Data); +int U_PMR_MULTIPLYWORLDTRANSFORM_get(const char *contents, U_PMF_CMN_HDR *Header, int *xmtype, U_PMF_TRANSFORMMATRIX *Matrix); +int U_PMR_RESETWORLDTRANSFORM_get(const char *contents, U_PMF_CMN_HDR *Header); +int U_PMR_ROTATEWORLDTRANSFORM_get(const char *contents, U_PMF_CMN_HDR *Header, int *xmtype, U_FLOAT *Angle); +int U_PMR_SCALEWORLDTRANSFORM_get(const char *contents, U_PMF_CMN_HDR *Header, int *xmtype, U_FLOAT *Sx, U_FLOAT *Sy); +int U_PMR_SETPAGETRANSFORM_get(const char *contents, U_PMF_CMN_HDR *Header, int *PUenum, U_FLOAT *Scale); +int U_PMR_SETWORLDTRANSFORM_get(const char *contents, U_PMF_CMN_HDR *Header, U_PMF_TRANSFORMMATRIX *Matrix); +int U_PMR_TRANSLATEWORLDTRANSFORM_get(const char *contents, U_PMF_CMN_HDR *Header, int *xmtype, U_FLOAT *Dx, U_FLOAT *Dy); +int U_PMR_STROKEFILLPATH_get(const char *contents, U_PMF_CMN_HDR *Header); +int U_PMR_MULTIFORMATSTART_get(const char *contents, U_PMF_CMN_HDR *Header); +int U_PMR_MULTIFORMATSECTION_get(const char *contents, U_PMF_CMN_HDR *Header); +int U_PMR_MULTIFORMATEND_get(const char *contents, U_PMF_CMN_HDR *Header); +//! \endcond + + +#ifdef __cplusplus +} +#endif + +#endif /* _UPMF_ */ diff --git a/src/3rdparty/libuemf/upmf_print.c b/src/3rdparty/libuemf/upmf_print.c new file mode 100644 index 0000000..69fad36 --- /dev/null +++ b/src/3rdparty/libuemf/upmf_print.c @@ -0,0 +1,3400 @@ +/** + @file upmf_print.c + + @brief Functions for printing EMF records +*/ + +/* +File: upmf_print.c +Version: 0.0.8 +Date: 26-JAN-2016 +Author: David Mathog, Biology Division, Caltech +email: mathog@caltech.edu +Copyright: 2016 David Mathog and California Institute of Technology (Caltech) +*/ + +/* compiler options: + +-DNOBRUSH causes brush objects to be treated as pen objects. PowerPoint 2003 and 2010 define pen objects +as brush objects, and this is one way to see their structure even though they are misidentified. +This option should only be used for tiny test files, consisting of just line objects. +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdlib.h> +#include <stdio.h> +#include <stddef.h> /* for offsetof() macro */ +#include <string.h> +#include "upmf_print.h" +#include "uemf_print.h" +#include "uemf_safe.h" + + +//! \cond + +#define UNUSED(x) (void)(x) //! Please ignore - Doxygen simply insisted on including this + +/* + this function is not visible in the API. Print "data" for one of the many records that has none. +*/ +int U_PMR_NODATAREC_print(const char *contents){ + U_PMF_CMN_HDR Header; + int status = U_PMR_RESETCLIP_get(contents,&Header); /* One of many possibilities */ + if(status)status = Header.Size; + return(status); +} + +/* + this function is not visible in the API. Common routine used by many functions that draw points. +*/ +void U_PMF_VARPOINTS_print(const char **contents, int Flags, uint32_t Elements, const char *blimit){ + unsigned int i; + U_FLOAT Xpos, Ypos; + + if( Flags & U_PPF_P){ printf(" + Points(Relative):"); } + else if(Flags & U_PPF_C){ printf(" + Points(Int16):"); } + else { printf(" + Points(Float):"); } + for(Xpos = Ypos = i = 0; i<Elements; i++){ + printf(" %d:",i); + if( Flags & U_PPF_P){ (void) U_PMF_POINTR_print(contents, &Xpos, &Ypos, blimit); } + else if(Flags & U_PPF_C){ (void) U_PMF_POINT_print(contents, blimit); } + else { (void) U_PMF_POINTF_print(contents, blimit); } + } +#if 0 +int residual; +uintptr_t holdptr = (uintptr_t) *contents; + residual = holdptr & 0x3; + if(residual){ *contents += (4-residual); } +printf("DEBUG U_PMF_VARPOINTS_print residual:%d *contents:%p\n",residual,*contents);fflush(stdout); +#endif + printf("\n"); +} + +/* + this function is not visible in the API. Common routine used by many functions that draw points. +*/ +void U_PMF_VARPOINTF_S_print(U_PMF_POINTF *Points, uint32_t Elements){ + unsigned int i; + printf(" + Points:"); + for(i=0; i<Elements; i++, Points++){ + printf(" %d:",i); + (void) U_PMF_POINTF_S_print(Points); + } + printf("\n"); +} + +/* + this function is not visible in the API. Common routine used by many functions that draw rectangles. +*/ +int U_PMF_VARRECTF_S_print(U_PMF_RECTF *Rects, uint32_t Elements){ + if(!Elements)return(0); + if(Elements == 1){ printf(" Rect(Float):"); } + else { printf(" Rects(Float):"); } + while(1){ + U_PMF_RECTF_S_print(Rects++); + Elements--; + if(!Elements)break; + printf(" "); + } + return(1); +} + +/* + this function is not visible in the API. Common routine used by many functions. +*/ +int U_PMF_VARBRUSHID_print(int btype, uint32_t BrushID){ + if(btype){ + printf(" Color:"); + (void) U_PMF_ARGB_print((char *)&(BrushID)); + } + else { + printf(" BrushID:%u",BrushID); + } + return(1); +} +//! \endcond + +/** + \brief Print any EMF+ record + \returns record length for a normal record, 0 for EMREOF or , -1 for a bad record + \param contents pointer to a buffer holding this EMF+ record + \param blimit one byte after this EMF+ record + \param recnum EMF number of this record in contents + \param off Offset from the beginning of the EMF+ file to the start of this record. +*/ +int U_pmf_onerec_print(const char *contents, const char *blimit, int recnum, int off){ + int status; + int rstatus; + static U_OBJ_ACCUM ObjCont={NULL,0,0,0,0}; /* for keeping track of object continuation. These may + be split across multiple EMF Comment records */ + U_PMF_CMN_HDR Header; + const char *contemp = contents; + + /* Check that COMMON header data in record can be touched without an access violation. If it cannot be + this is either a corrupt EMF or one engineered to cause a buffer overflow. Pointer math + could wrap so check both sides of the range. + */ + if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_CMN_HDR), blimit))return(-1); + if(!U_PMF_CMN_HDR_get(&contemp, &Header)){return(-1);} + + int type = Header.Type & U_PMR_TYPE_MASK; /* strip the U_PMR_RECFLAG bit, leaving the indexable part */ + if(type < U_PMR_MIN || type > U_PMR_MAX)return(-1); /* unknown EMF+ record type */ + status = U_PMF_CMN_HDR_print(contents, Header, recnum, off); /* EMF+ part */ + + /* Buggy EMF+ can set the continue bit and then do something else. In that case, force out the pending + Object. Side effect - clears the pending object. */ + if((type != U_PMR_OBJECT) && (ObjCont.used > 0)){ + U_PMR_OBJECT_print(contents, blimit, &ObjCont, 1); + } + + /* Check that the record size is OK, abort if not. */ + if(Header.Size < sizeof(U_PMF_CMN_HDR) || + IS_MEM_UNSAFE(contents, Header.Size, blimit))return(-1); + + switch(type){ + case (U_PMR_HEADER): rstatus = U_PMR_HEADER_print(contents); break; + case (U_PMR_ENDOFFILE): rstatus = U_PMR_ENDOFFILE_print(contents); + U_OA_release(&ObjCont); break; + case (U_PMR_COMMENT): rstatus = U_PMR_COMMENT_print(contents); break; + case (U_PMR_GETDC): rstatus = U_PMR_GETDC_print(contents); break; + case (U_PMR_MULTIFORMATSTART): rstatus = U_PMR_MULTIFORMATSTART_print(contents); break; + case (U_PMR_MULTIFORMATSECTION): rstatus = U_PMR_MULTIFORMATSECTION_print(contents); break; + case (U_PMR_MULTIFORMATEND): rstatus = U_PMR_MULTIFORMATEND_print(contents); break; + case (U_PMR_OBJECT): rstatus = U_PMR_OBJECT_print(contents,blimit,&ObjCont,0); break; + case (U_PMR_CLEAR): rstatus = U_PMR_CLEAR_print(contents); break; + case (U_PMR_FILLRECTS): rstatus = U_PMR_FILLRECTS_print(contents); break; + case (U_PMR_DRAWRECTS): rstatus = U_PMR_DRAWRECTS_print(contents); break; + case (U_PMR_FILLPOLYGON): rstatus = U_PMR_FILLPOLYGON_print(contents); break; + case (U_PMR_DRAWLINES): rstatus = U_PMR_DRAWLINES_print(contents); break; + case (U_PMR_FILLELLIPSE): rstatus = U_PMR_FILLELLIPSE_print(contents); break; + case (U_PMR_DRAWELLIPSE): rstatus = U_PMR_DRAWELLIPSE_print(contents); break; + case (U_PMR_FILLPIE): rstatus = U_PMR_FILLPIE_print(contents); break; + case (U_PMR_DRAWPIE): rstatus = U_PMR_DRAWPIE_print(contents); break; + case (U_PMR_DRAWARC): rstatus = U_PMR_DRAWARC_print(contents); break; + case (U_PMR_FILLREGION): rstatus = U_PMR_FILLREGION_print(contents); break; + case (U_PMR_FILLPATH): rstatus = U_PMR_FILLPATH_print(contents); break; + case (U_PMR_DRAWPATH): rstatus = U_PMR_DRAWPATH_print(contents); break; + case (U_PMR_FILLCLOSEDCURVE): rstatus = U_PMR_FILLCLOSEDCURVE_print(contents); break; + case (U_PMR_DRAWCLOSEDCURVE): rstatus = U_PMR_DRAWCLOSEDCURVE_print(contents); break; + case (U_PMR_DRAWCURVE): rstatus = U_PMR_DRAWCURVE_print(contents); break; + case (U_PMR_DRAWBEZIERS): rstatus = U_PMR_DRAWBEZIERS_print(contents); break; + case (U_PMR_DRAWIMAGE): rstatus = U_PMR_DRAWIMAGE_print(contents); break; + case (U_PMR_DRAWIMAGEPOINTS): rstatus = U_PMR_DRAWIMAGEPOINTS_print(contents); break; + case (U_PMR_DRAWSTRING): rstatus = U_PMR_DRAWSTRING_print(contents); break; + case (U_PMR_SETRENDERINGORIGIN): rstatus = U_PMR_SETRENDERINGORIGIN_print(contents); break; + case (U_PMR_SETANTIALIASMODE): rstatus = U_PMR_SETANTIALIASMODE_print(contents); break; + case (U_PMR_SETTEXTRENDERINGHINT): rstatus = U_PMR_SETTEXTRENDERINGHINT_print(contents); break; + case (U_PMR_SETTEXTCONTRAST): rstatus = U_PMR_SETTEXTCONTRAST_print(contents); break; + case (U_PMR_SETINTERPOLATIONMODE): rstatus = U_PMR_SETINTERPOLATIONMODE_print(contents); break; + case (U_PMR_SETPIXELOFFSETMODE): rstatus = U_PMR_SETPIXELOFFSETMODE_print(contents); break; + case (U_PMR_SETCOMPOSITINGMODE): rstatus = U_PMR_SETCOMPOSITINGMODE_print(contents); break; + case (U_PMR_SETCOMPOSITINGQUALITY): rstatus = U_PMR_SETCOMPOSITINGQUALITY_print(contents); break; + case (U_PMR_SAVE): rstatus = U_PMR_SAVE_print(contents); break; + case (U_PMR_RESTORE): rstatus = U_PMR_RESTORE_print(contents); break; + case (U_PMR_BEGINCONTAINER): rstatus = U_PMR_BEGINCONTAINER_print(contents); break; + case (U_PMR_BEGINCONTAINERNOPARAMS): rstatus = U_PMR_BEGINCONTAINERNOPARAMS_print(contents); break; + case (U_PMR_ENDCONTAINER): rstatus = U_PMR_ENDCONTAINER_print(contents); break; + case (U_PMR_SETWORLDTRANSFORM): rstatus = U_PMR_SETWORLDTRANSFORM_print(contents); break; + case (U_PMR_RESETWORLDTRANSFORM): rstatus = U_PMR_RESETWORLDTRANSFORM_print(contents); break; + case (U_PMR_MULTIPLYWORLDTRANSFORM): rstatus = U_PMR_MULTIPLYWORLDTRANSFORM_print(contents); break; + case (U_PMR_TRANSLATEWORLDTRANSFORM): rstatus = U_PMR_TRANSLATEWORLDTRANSFORM_print(contents); break; + case (U_PMR_SCALEWORLDTRANSFORM): rstatus = U_PMR_SCALEWORLDTRANSFORM_print(contents); break; + case (U_PMR_ROTATEWORLDTRANSFORM): rstatus = U_PMR_ROTATEWORLDTRANSFORM_print(contents); break; + case (U_PMR_SETPAGETRANSFORM): rstatus = U_PMR_SETPAGETRANSFORM_print(contents); break; + case (U_PMR_RESETCLIP): rstatus = U_PMR_RESETCLIP_print(contents); break; + case (U_PMR_SETCLIPRECT): rstatus = U_PMR_SETCLIPRECT_print(contents); break; + case (U_PMR_SETCLIPPATH): rstatus = U_PMR_SETCLIPPATH_print(contents); break; + case (U_PMR_SETCLIPREGION): rstatus = U_PMR_SETCLIPREGION_print(contents); break; + case (U_PMR_OFFSETCLIP): rstatus = U_PMR_OFFSETCLIP_print(contents); break; + case (U_PMR_DRAWDRIVERSTRING): rstatus = U_PMR_DRAWDRIVERSTRING_print(contents); break; + case (U_PMR_STROKEFILLPATH): rstatus = U_PMR_STROKEFILLPATH_print(contents); break; + case (U_PMR_SERIALIZABLEOBJECT): rstatus = U_PMR_SERIALIZABLEOBJECT_print(contents); break; + case (U_PMR_SETTSGRAPHICS): rstatus = U_PMR_SETTSGRAPHICS_print(contents); break; + case (U_PMR_SETTSCLIP): rstatus = U_PMR_SETTSCLIP_print(contents); break; + } + if(!rstatus)status=-1; + return(status); +} + +/** + \brief Print data from a U_PMF_CMN_HDR object + \return number of bytes in record, 0 on error + \param contents pointer to a buffer holding this EMF+ record + \param Header Header of the record + \param precnum EMF+ record number in file. + \param off Offset in file to the start of this EMF+ record. + common structure present at the beginning of all(*) EMF+ records +*/ +int U_PMF_CMN_HDR_print(const char *contents, U_PMF_CMN_HDR Header, int precnum, int off){ + printf(" %-29srec+:%5d type:%X offset:%8d rsize:%8u dsize:%8u flags:%4.4X crc32:%8.8X\n", + U_pmr_names(Header.Type &U_PMR_TYPE_MASK),precnum, Header.Type,off,Header.Size,Header.DataSize,Header.Flags, + lu_crc32(contents,Header.Size)); + return((int) Header.Size); +} + +/** + \brief Print data from a an array of uint8_t values + \return 1 + \param Start Text to lead array data + \param Array uint8_t array of data passed as char * + \param Elements Number of elements in Array + \param End Text to follow array data +*/ +int U_PMF_UINT8_ARRAY_print(const char *Start, const uint8_t *Array, int Elements, char *End){ + if(Start)printf("%s",Start); + for(; Elements--; Array++){ printf(" %u", *Array); } + if(End)printf("%s",End); + return(1); +} + +/** + \brief Print value of an BrushType Enumeration + \returns record 1 on sucess, 0 on error + \param otype Value to print. + EMF+ manual 2.1.1.3, Microsoft name: BrushType Enumeration +*/ +int U_PMF_BRUSHTYPEENUMERATION_print(int otype){ + int status=1; + switch(otype){ + case U_BT_SolidColor: printf("SolidColor"); break; + case U_BT_HatchFill: printf("HatchFill"); break; + case U_BT_TextureFill: printf("TextureFill"); break; + case U_BT_PathGradient: printf("PathGradient"); break; + case U_BT_LinearGradient: printf("LinearGradient"); break; + default: status=0; printf("INVALID(%d)",otype); break; + } + return(status); +} + +/** + \brief Print value of an BrushType Enumeration + \returns record 1 on sucess, 0 on error + \param otype Value to print. + EMF+ manual 2.1.1.4, Microsoft name: BrushType Enumeration +*/ +int U_PMF_COMBINEMODEENUMERATION_print(int otype){ + int status=1; + switch(otype){ + case U_CM_Replace: printf("Replace" ); break; + case U_CM_Intersect: printf("Intersect" ); break; + case U_CM_Union: printf("Union" ); break; + case U_CM_XOR: printf("XOR" ); break; + case U_CM_Exclude: printf("Exclude" ); break; + case U_CM_Complement: printf("Complement"); break; + default: status=0; printf("INVALID(%d)",otype); break; + } + return(status); +} + +/** + \brief Print value of a HatchStyle Enumeration + \returns record 1 on sucess, 0 on error + \param hstype Value to print. + EMF+ manual 2.1.1.13, Microsoft name: HatchStyle Enumeration +*/ +int U_PMF_HATCHSTYLEENUMERATION_print(int hstype){ + int status=1; + switch(hstype){ + case U_HSP_Horizontal: printf("Horizontal"); break; + case U_HSP_Vertical: printf("Vertical"); break; + case U_HSP_ForwardDiagonal: printf("ForwardDiagonal"); break; + case U_HSP_BackwardDiagonal: printf("BackwardDiagonal"); break; + case U_HSP_LargeGrid: printf("LargeGrid"); break; + case U_HSP_DiagonalCross: printf("DiagonalCross"); break; + case U_HSP_05Percent: printf("05Percent"); break; + case U_HSP_10Percent: printf("10Percent"); break; + case U_HSP_20Percent: printf("20Percent"); break; + case U_HSP_25Percent: printf("25Percent"); break; + case U_HSP_30Percent: printf("30Percent"); break; + case U_HSP_40Percent: printf("40Percent"); break; + case U_HSP_50Percent: printf("50Percent"); break; + case U_HSP_60Percent: printf("60Percent"); break; + case U_HSP_70Percent: printf("70Percent"); break; + case U_HSP_75Percent: printf("75Percent"); break; + case U_HSP_80Percent: printf("80Percent"); break; + case U_HSP_90Percent: printf("90Percent"); break; + case U_HSP_LightDownwardDiagonal: printf("LightDownwardDiagonal"); break; + case U_HSP_LightUpwardDiagonal: printf("LightUpwardDiagonal"); break; + case U_HSP_DarkDownwardDiagonal: printf("DarkDownwardDiagonal"); break; + case U_HSP_DarkUpwardDiagonal: printf("DarkUpwardDiagonal"); break; + case U_HSP_WideDownwardDiagonal: printf("WideDownwardDiagonal"); break; + case U_HSP_WideUpwardDiagonal: printf("WideUpwardDiagonal"); break; + case U_HSP_LightVertical: printf("LightVertical"); break; + case U_HSP_LightHorizontal: printf("LightHorizontal"); break; + case U_HSP_NarrowVertical: printf("NarrowVertical"); break; + case U_HSP_NarrowHorizontal: printf("NarrowHorizontal"); break; + case U_HSP_DarkVertical: printf("DarkVertical"); break; + case U_HSP_DarkHorizontal: printf("DarkHorizontal"); break; + case U_HSP_DashedDownwardDiagonal: printf("DashedDownwardDiagonal"); break; + case U_HSP_DashedUpwardDiagonal: printf("DashedUpwardDiagonal"); break; + case U_HSP_DashedHorizontal: printf("DashedHorizontal"); break; + case U_HSP_DashedVertical: printf("DashedVertical"); break; + case U_HSP_SmallConfetti: printf("SmallConfetti"); break; + case U_HSP_LargeConfetti: printf("LargeConfetti"); break; + case U_HSP_ZigZag: printf("ZigZag"); break; + case U_HSP_Wave: printf("Wave"); break; + case U_HSP_DiagonalBrick: printf("DiagonalBrick"); break; + case U_HSP_HorizontalBrick: printf("HorizontalBrick"); break; + case U_HSP_Weave: printf("Weave"); break; + case U_HSP_Plaid: printf("Plaid"); break; + case U_HSP_Divot: printf("Divot"); break; + case U_HSP_DottedGrid: printf("DottedGrid"); break; + case U_HSP_DottedDiamond: printf("DottedDiamond"); break; + case U_HSP_Shingle: printf("Shingle"); break; + case U_HSP_Trellis: printf("Trellis"); break; + case U_HSP_Sphere: printf("Sphere"); break; + case U_HSP_SmallGrid: printf("SmallGrid"); break; + case U_HSP_SmallCheckerBoard: printf("SmallCheckerBoard"); break; + case U_HSP_LargeCheckerBoard: printf("LargeCheckerBoard"); break; + case U_HSP_OutlinedDiamond: printf("OutlinedDiamond"); break; + case U_HSP_SolidDiamond: printf("SolidDiamond"); break; + default: status=0; printf("INVALID(%d)",hstype); break; + } + return(status); +} + +/** + \brief Print value of an ObjectType Enumeration + \returns record 1 on sucess, 0 on error + \param otype Value to print. + EMF+ manual 2.1.1.22, Microsoft name: ObjectType Enumeration +*/ +int U_PMF_OBJECTTYPEENUMERATION_print(int otype){ + int status=1; + switch(otype){ + case U_OT_Invalid: printf("Invalid"); break; + case U_OT_Brush: printf("Brush"); break; + case U_OT_Pen: printf("Pen"); break; + case U_OT_Path: printf("Path"); break; + case U_OT_Region: printf("Region"); break; + case U_OT_Image: printf("Image"); break; + case U_OT_Font: printf("Font"); break; + case U_OT_StringFormat: printf("StringFormat"); break; + case U_OT_ImageAttributes: printf("ImageAttributes"); break; + case U_OT_CustomLineCap: printf("CustomLineCap"); break; + default: + status=0; printf("INVALID(%d)",otype); break; + } + return(status); +} + +/** + \brief Print value of a U_PMF_PATHPOINTTYPE_ENUM object + \return 1 + \param Type Value to print + EMF+ manual 2.1.1.23, Microsoft name: PathPointType Enumeration +*/ +int U_PMF_PATHPOINTTYPE_ENUM_print(int Type){ + switch(Type & U_PPT_MASK){ + case U_PPT_Start : printf("Start"); break; + case U_PPT_Line : printf("Line"); break; + case U_PPT_Bezier: printf("Bezier"); break; + default: printf("INVALID(%d)",Type); break; + } + return(1); +} + +/** + \brief Print data from a PixelFormat Enumeration value + \return 1 always + \param pfe A PixelFormat Enumeration value + EMF+ manual 2.1.1.25, Microsoft name: PixelFormat Enumeration (U_PF_*) +*/ +int U_PMF_PX_FMT_ENUM_print(int pfe){ + uint8_t idx; + printf(" + PxFmtEnum: "); + printf(" 32Bit:%c", (pfe & 1<< 9 ? 'Y' : 'N')); + printf(" 16Bit:%c", (pfe & 1<<10 ? 'Y' : 'N')); + printf(" PreAlpha:%c", (pfe & 1<<11 ? 'Y' : 'N')); + printf(" Alpha:%c", (pfe & 1<<12 ? 'Y' : 'N')); + printf(" GDI:%c", (pfe & 1<<13 ? 'Y' : 'N')); + printf(" LUT:%c", (pfe & 1<<14 ? 'Y' : 'N')); + printf(" BitsPerPx:%u", (pfe >> 16) & 0xFF); + idx = pfe >> 24; + printf(" Type:%u(",idx); + switch(idx){ + case 0: printf("undefined"); break; + case 1: printf("monochrome with LUT"); break; + case 2: printf("4 bit with LUT"); break; + case 3: printf("8 bit with LUT"); break; + case 4: printf("16 bits grey values"); break; + case 5: printf("16 bit RGB values (5,5,5,(1 ignored))"); break; + case 6: printf("16 bit RGB values (5,6,5)"); break; + case 7: printf("16 bit ARGB values (1 alpha, 5,5,5 colors)"); break; + case 8: printf("24 bit RGB values (8,8.8)"); break; + case 9: printf("32 bit RGB value (8,8,8,(8 ignored))"); break; + case 10: printf("32 bit ARGB values (8 alpha,8,8,8)"); break; + case 11: printf("32 bit PARGB values (8,8,8,8, but RGB already multiplied by A)"); break; + case 12: printf("48 bit RGB (16,16,16)"); break; + case 13: printf("64 bit ARGB (16 alpha, 16,16,16)"); break; + case 14: printf("64 bit PARGB (16,16,16,16, but RGB already multiplied by A)"); break; + default: printf("INVALID(%d)",idx); break; + } + printf(")"); + return(1); +} + +/** + \brief Print as text a RegionNodeDataType Enumeration + \return 1 + \param Type RegionNodeDataType Enumeration + EMF+ manual 2.1.1.27, Microsoft name: RegionNodeDataType Enumeration (U_RNDT_*) +*/ +int U_PMF_NODETYPE_print(int Type){ + if( Type == U_RNDT_And ){ printf("And" ); } + else if(Type == U_RNDT_Or ){ printf("Or" ); } + else if(Type == U_RNDT_Xor ){ printf("Xor" ); } + else if(Type == U_RNDT_Exclude ){ printf("Exclude" ); } + else if(Type == U_RNDT_Complement){ printf("Complement"); } + else if(Type == U_RNDT_Rect ){ printf("Rect" ); } + else if(Type == U_RNDT_Path ){ printf("Path" ); } + else if(Type == U_RNDT_Empty ){ printf("Empty" ); } + else if(Type == U_RNDT_Infinite ){ printf("Infinite" ); } + else { printf("Undefined" ); return(0); } + return(1); +} + +/** + \brief Print data from a U_PMF_BRUSH object + \return 1 on success, 0 on error + \param contents Record from which to print data + \param blimit one byte past the end of data + EMF+ manual 2.2.1.1, Microsoft name: EmfPlusBrush Object +*/ +int U_PMF_BRUSH_print(const char *contents, const char *blimit){ + uint32_t Version, Type; + const char *Data; + int status = U_PMF_BRUSH_get(contents, &Version, &Type, &Data, blimit); + if(status){ + printf(" + Brush:"); + (void) U_PMF_GRAPHICSVERSION_memsafe_print((char *)&Version);; + printf(" Type:%X(",Type); + (void) U_PMF_BRUSHTYPEENUMERATION_print(Type); + printf(")"); + switch(Type){ + case U_BT_SolidColor: + status = U_PMF_ARGB_print(Data); + break; + case U_BT_HatchFill: + printf("\n"); + status = U_PMF_HATCHBRUSHDATA_print(Data, blimit); + break; + case U_BT_TextureFill: + printf("\n"); + status = U_PMF_TEXTUREBRUSHDATA_print(Data, blimit); + break; + case U_BT_PathGradient: + printf("\n"); + status = U_PMF_PATHGRADIENTBRUSHDATA_print(Data, blimit); + break; + case U_BT_LinearGradient: + printf("\n"); + status = U_PMF_LINEARGRADIENTBRUSHDATA_print(Data, blimit); + break; + default: + status = 0; + } + printf("\n"); + } + return(status); +} + +/** + \brief Print data from a U_PMF_CUSTOMLINECAP object + \return 1 on success, 0 on error + \param contents Record from which to print data + \param Which A string which is either "Start" or "End". + \param blimit one byte past the end of data + EMF+ manual 2.2.1.2, Microsoft name: EmfPlusCustomLineCap Object +*/ +int U_PMF_CUSTOMLINECAP_print(const char *contents, const char *Which, const char *blimit){ + uint32_t Version, Type; + const char *Data; + int status = U_PMF_CUSTOMLINECAP_get(contents, &Version, &Type, &Data, blimit); + + if(status){ + printf(" + %sLineCap:",Which); + (void) U_PMF_GRAPHICSVERSION_memsafe_print((char *)&Version);; + printf(", Type %X\n",Type); + switch(Type){ + case U_CLCDT_Default: + status = U_PMF_CUSTOMLINECAPDATA_print(Data, blimit); + break; + case U_CLCDT_AdjustableArrow: + status = U_PMF_CUSTOMLINECAPARROWDATA_print(Data, blimit); + break; + default: + status = 0; + } + } + return(status); +} + +/** + \brief Print data from a U_PMF_FONT object + \return 1 on success, 0 on error + \param contents Record from which to print data + \param blimit one byte past the end of data + EMF+ manual 2.2.1.3, Microsoft name: EmfPlusFont Object +*/ +int U_PMF_FONT_print(const char *contents, const char *blimit){ + uint32_t Version, SizeUnit, Length; + U_FLOAT EmSize; + int32_t FSFlags; + const char *Data; + char *string; + int status = U_PMF_FONT_get(contents, &Version, &EmSize, &SizeUnit, &FSFlags, &Length, &Data, blimit); + if(status){ + printf(" + Font:"); + (void) U_PMF_GRAPHICSVERSION_memsafe_print((char *)&Version);; + printf(" EmSize:%f ", EmSize ); + printf(" SizeUnit:%d ",SizeUnit); + printf(" FSFlags:%d ", FSFlags ); + printf(" Length:%d", Length ); + string = U_Utf16leToUtf8((uint16_t *)Data, Length, NULL); + if(string){ + printf(" Family:<%s>\n",string); + free(string); + } + else { + printf(" Family:<>\n"); + } + } + return(status); +} + + +/** + \brief Print data from a U_PMF_IMAGE object + \return 1 on success, 0 on error + \param contents Record from which to print data + \param blimit one byte past the end of data + + EMF+ manual 2.2.1.4, Microsoft name: EmfPlusImage Object +*/ +int U_PMF_IMAGE_print(const char *contents, const char *blimit){ + uint32_t Version, Type; + const char *Data; + int status = U_PMF_IMAGE_get(contents, &Version, &Type, &Data, blimit); + if(status){ + printf(" + Image:"); + (void) U_PMF_GRAPHICSVERSION_memsafe_print((char *)&Version);; + printf(" Type:%X\n",Type); + switch(Type){ + case U_IDT_Unknown: + printf(" + Unknown Image Type\n"); + break; + case U_IDT_Bitmap: + status = U_PMF_BITMAP_print(Data, blimit); + break; + case U_IDT_Metafile: + status = U_PMF_METAFILE_print(Data, blimit); + break; + default: + status = 0; + } + } + return(status); +} + + +/** + \brief Print data from a U_PMF_IMAGEATTRIBUTES object + \return 1 on success, 0 on error + \param contents Record from which to print data + \param blimit one byte past the end of data + EMF+ manual 2.2.1.5, Microsoft name: EmfPlusImageAttributes Object +*/ +int U_PMF_IMAGEATTRIBUTES_print(const char *contents, const char *blimit){ + uint32_t Version, WrapMode, ClampColor, ObjectClamp; + int status = U_PMF_IMAGEATTRIBUTES_get(contents, &Version, &WrapMode, &ClampColor, &ObjectClamp, blimit); + + if(status){ + printf(" + Image Attributes: "); + (void) U_PMF_GRAPHICSVERSION_memsafe_print((char *)&Version);; + printf(" WrapMode:%X", WrapMode); + printf(" ClampColor:%X", ClampColor); + printf(" ObjectClamp:%X\n", ObjectClamp); + } + return(status); +} + + + +/** + \brief Print data from a U_PMF_PATH object + \return 1 on success, 0 on error + \param contents Record from which to print data + \param blimit one byte past the end of data + EMF+ manual 2.2.1.6, Microsoft name: EmfPlusPath Object +*/ +int U_PMF_PATH_print(const char *contents, const char *blimit){ + unsigned int i, pos; + uint32_t Version, Count; + uint16_t Flags; + const char *Points; + const char *Types; + int status = U_PMF_PATH_get(contents, &Version, &Count, &Flags, &Points, &Types, blimit); + if(status){ + printf(" + Path: Version:%X Count:%d Flags:%X\n",Version, Count, Flags); + + /* Points part */ + U_PMF_VARPOINTS_print(&Points, Flags, Count, blimit); + + /* Types part */ + printf(" + Types:"); + pos = 0; + for(i=0; i<Count; i++){ + /* EMF+ manual says that the first of these two cases can actually contain either type + of PATHPOINT, but it does not say how the program is supposed to figure out which record + is which type. */ + if(Flags & U_PPF_R){ + printf(" %u:",pos); + pos += U_PMF_PATHPOINTTYPERLE_print(Types, blimit); + Types+=2; + } + else { + printf(" %d:",i); + (void) U_PMF_PATHPOINTTYPE_print(Types, blimit); + Types++; + } + } + printf("\n"); + } + return(status); +} + +/** + \brief Print data from a U_PMF_PEN object + \return 1 on success, 0 on error + \param contents Record from which to print data + EMF+ manual 2.2.1.7, Microsoft name: EmfPlusPen Object +*/ +int U_PMF_PEN_print(const char *contents, const char *blimit){ + uint32_t Version, Type; + const char *PenData; + const char *Brush; + int status = U_PMF_PEN_get(contents, &Version, &Type, &PenData, &Brush, blimit); + if(status){ + printf(" + Pen: Version:%X Type:%d\n",Version,Type); + (void) U_PMF_PENDATA_print(PenData, blimit); + (void) U_PMF_BRUSH_print(Brush, blimit); + } + return(status); +} + +/** + \brief Print data from a U_PMF_REGION object + \return 1 on success, 0 on error + \param contents Record from which to print data + \param blimit one byte past the end of data + + EMF+ manual 2.2.1.8, Microsoft name: EmfPlusRegion Object +*/ +int U_PMF_REGION_print(const char *contents, const char *blimit){ + uint32_t Version, Count; + const char *Nodes; + int status = U_PMF_REGION_get(contents, &Version, &Count, &Nodes, blimit); + if(status){ + printf(" + "); + (void) U_PMF_GRAPHICSVERSION_memsafe_print((char *)&Version);; + printf(" ChildNodes:%d",Count); + (void) U_PMF_REGIONNODE_print(Nodes, 1, blimit); /* 1 == top level*/ + } + return(status); +} + +/** + \brief Print data from a U_PMF_STRINGFORMAT object + \return 1 on success, 0 on error + \param contents Record from which to print data + \param blimit one byte past the end of data + EMF+ manual 2.2.1.9, Microsoft name: EmfPlusStringFormat Object +*/ +int U_PMF_STRINGFORMAT_print(const char *contents, const char *blimit){ + U_PMF_STRINGFORMAT Sfs; + const char *Data; + int status = U_PMF_STRINGFORMAT_get(contents, &Sfs, &Data, blimit); + if(status){ + printf(" + StringFormat: "); + printf(" Version:%X", Sfs.Version ); + printf(" Flags:%X", Sfs.Flags ); + printf(" Language"); (void) U_PMF_LANGUAGEIDENTIFIER_print(Sfs.Language); + printf(" StringAlignment:%X", Sfs.StringAlignment ); + printf(" LineAlign:%X", Sfs.LineAlign ); + printf(" DigitSubstitution:%X",Sfs.DigitSubstitution); + printf(" DigitLanguage"); (void) U_PMF_LANGUAGEIDENTIFIER_print(Sfs.DigitLanguage); + printf(" FirstTabOffset:%f", Sfs.FirstTabOffset ); + printf(" HotkeyPrefix:%d", Sfs.HotkeyPrefix ); + printf(" LeadingMargin:%f", Sfs.LeadingMargin ); + printf(" TrailingMargin:%f", Sfs.TrailingMargin ); + printf(" Tracking:%f", Sfs.Tracking ); + printf(" Trimming:%X", Sfs.Trimming ); + printf(" TabStopCount:%u", Sfs.TabStopCount ); + printf(" RangeCount:%u", Sfs.RangeCount ); + (void) U_PMF_STRINGFORMATDATA_print(Data, Sfs.TabStopCount, Sfs.RangeCount, blimit); + } + return(status); +} + +/** + \brief Print data from a U_PMF_ARGB object + \return 1 on success, 0 on error + \param contents Record from which to print data + + Does not accept a blimit value. + EMF+ manual 2.2.2.1, Microsoft name: EmfPlusARGB Object +*/ +int U_PMF_ARGB_print(const char *contents){ + uint8_t Blue, Green, Red, Alpha; + int status = U_PMF_ARGB_get(contents, &Blue, &Green, &Red, &Alpha, contents + sizeof(U_RGBQUAD)); + if(status){ + printf(" RGBA{%2.2X,%2.2X,%2.2X,%2.2X}", Red, Green, Blue, Alpha); + } + return(status); +} + + +/** + \brief Print data from a U_PMF_BITMAP object + \return 1 on success, 0 on error + \param contents Record from which to print data + \param blimit one byte past the end of data + EMF+ manual 2.2.2.2, Microsoft name: EmfPlusBitmap Object +*/ +int U_PMF_BITMAP_print(const char *contents, const char *blimit){ + U_PMF_BITMAP Bs; + const char *Data; + int status = U_PMF_BITMAP_get(contents, &Bs, &Data, blimit); + if(status){ + printf(" + Bitmap: Width:%d Height:%d Stride:%d\n",Bs.Width, Bs.Height, Bs.Stride); + U_PMF_PX_FMT_ENUM_print(Bs.PxFormat); + switch(Bs.Type){ + case 0: printf(" Type:MSBitmap\n"); break; + case 1: printf(" Type:(PNG|JPG|GIF|EXIF|TIFF)\n"); break; + default: printf(" Type:INVALID(%d)\n",Bs.Type); break; + } + /* Pixel data is never shown - it could easily swamp the output for even a smallish picture */ + } + return(status); +} + + +/** + \brief Print data from a U_PMF_BITMAPDATA object + \return 1 on success, 0 on error + \param contents Record from which to print data + \param blimit one byte past the end of data + EMF+ manual 2.2.2.3, Microsoft name: EmfPlusBitmapData Object +*/ +int U_PMF_BITMAPDATA_print(const char *contents, const char *blimit){ + unsigned int i; + U_PMF_PALETTE Ps; + const char *Colors; + const char *Data; + int status = U_PMF_BITMAPDATA_get(contents, &Ps, &Colors, &Data, blimit); + if(status){ + status = 0; + printf(" BMData: Flags:%X, Elements:%u Colors:", Ps.Flags, Ps.Elements); + for(i=0; i<Ps.Elements; i++, Colors+=sizeof(U_PMF_ARGB)){ + (void) U_PMF_ARGB_print(Colors); + } + } + return(status); +} + +/** + \brief Print data from a U_PMF_BLENDCOLORS object + \return size in bytes on success, 0 on error + \param contents Record from which to print data + \param blimit one byte past the end of data + EMF+ manual 2.2.2.4, Microsoft name: EmfPlusBlendColors Object +*/ +int U_PMF_BLENDCOLORS_print(const char *contents, const char *blimit){ + unsigned int i; + uint32_t Elements; + U_FLOAT *Positions; + const char *Colors; + int status = U_PMF_BLENDCOLORS_get(contents, &Elements, &Positions, &Colors, blimit); + if(status){ + printf(" + BlendColors: Entries:%d (entry,pos,color): ", Elements); + for(i=0; i<Elements; i++){ + printf(" (%d,%f,", i, Positions[i]); + (void) U_PMF_ARGB_print(Colors); + Colors += sizeof(U_PMF_ARGB); + printf(")"); + } + status = sizeof(uint32_t) + Elements*sizeof(U_FLOAT) + Elements*sizeof(U_PMF_ARGB); + free(Positions); + } + return(status); +} + +/** + \brief Print data from a U_PMF_BLENDFACTORS object + \return size on success, 0 on error + \param type Type of BlendFactors, usually H or V + \param contents Record from which to print data + \param blimit one byte past the end of data + EMF+ manual 2.2.2.5, Microsoft name: EmfPlusBlendFactors Object +*/ +int U_PMF_BLENDFACTORS_print(const char *contents, const char *type, const char *blimit){ + unsigned int i; + uint32_t Elements; + U_FLOAT *Positions; + U_FLOAT *Factors; + int status = U_PMF_BLENDFACTORS_get(contents, &Elements, &Positions, &Factors, blimit); + if(status){ + printf(" + BlendFactors%s: Entries:%d (entry,pos,factor): ",type, Elements); + for(i=0; i<Elements; i++){ + printf(" (%d,%f,%f)", i, Positions[i],Factors[i]); + } + status = sizeof(uint32_t) + Elements*2*sizeof(U_FLOAT); + free(Positions); + free(Factors); + } + return(status); +} + +/** + \brief Print data from a U_PMF_BOUNDARYPATHDATA object + \return size on success, 0 on error + \param contents Record from which to print data + \param blimit one byte past the end of data + EMF+ manual 2.2.2.6, Microsoft name: EmfPlusBoundaryPathData Object +*/ +int U_PMF_BOUNDARYPATHDATA_print(const char *contents, const char * blimit){ + int32_t Size; + const char *Data; + int status = U_PMF_BOUNDARYPATHDATA_get(contents, &Size, &Data, blimit); + if(status){ + printf(" + BoundaryPathData: Size:%d\n",Size); + (void) U_PMF_PATH_print(Data, blimit); + } + return(status); +} + + +/** + \brief Print data from a U_PMF_BOUNDARYPOINTDATA object + \return size on success, 0 on error + \param contents Record from which to print data + \param blimit one byte past the end of data + EMF+ manual 2.2.2.7, Microsoft name: EmfPlusBoundaryPointData Object +*/ +int U_PMF_BOUNDARYPOINTDATA_print(const char *contents, const char *blimit){ + int32_t Elements; + U_PMF_POINTF *Points; + int status = U_PMF_BOUNDARYPOINTDATA_get(contents, &Elements, &Points, blimit); + if(status){ + printf(" + BoundaryPointData: Elements:%u\n",Elements); + U_PMF_VARPOINTF_S_print(Points, Elements); + free(Points); + } + return(status); +} + +/** + \brief Print data from a U_PMF_CHARACTERRANGE object + \return 1 on success, 0 on error + \param contents Record from which to print data + \param blimit one byte past the end of data + EMF+ manual 2.2.2.8, Microsoft name: EmfPlusCharacterRange Object +*/ +int U_PMF_CHARACTERRANGE_print(const char *contents, const char *blimit){ + int32_t First, Length; + int status = U_PMF_CHARACTERRANGE_get(contents, &First, &Length, blimit); + if(status){ + printf(" {%d,%d}",First,Length); + } + return(status); +} + +/** + \brief Print data from a U_PMF_DASHEDLINEDATA object + \return 1 on success, 0 on error + \param blimit one byte past the end of data + \param contents Record from which to print data + EMF+ manual 2.2.2.9, Microsoft name: EmfPlusCompoundLineData Object +*/ +int U_PMF_COMPOUNDLINEDATA_print(const char *contents, const char *blimit){ + int32_t Elements; + U_FLOAT *Widths; + U_FLOAT *hold; + int status = U_PMF_COMPOUNDLINEDATA_get(contents, &Elements, &Widths, blimit); + if(status){ + printf(" + CompoundLineData: Elements:%u {",Elements); + Elements--; + for(hold=Widths; Elements; Elements--,Widths++){ printf("%f, ",*Widths); } + printf("%f}",*Widths); + free(hold); + printf("\n"); + } + return(status); +} + +/** + \brief Print data from a U_PMF_COMPRESSEDIMAGE object + \return 1 on success, 0 on error + \param contents Record from which to print data + \param blimit one byte past the end of data + EMF+ manual 2.2.2.10, Microsoft name: EmfPlusCompressedImage Object + + This function does not do anything useful, but it is included so that all objects have a corresponding _get(). +*/ +int U_PMF_COMPRESSEDIMAGE_print(const char *contents, const char *blimit){ + const char *Data; + int status = U_PMF_COMPRESSEDIMAGE_get(contents, &Data, blimit); + if(status){ + printf("CompressedImage:\n"); + } + return(status); +} + +/** + \brief Print data from a U_PMF_CUSTOMENDCAPDATA object + \return 1 on success, 0 on error + \param contents Record from which to print data + \param blimit one byte past the end of data + EMF+ manual 2.2.2.11, Microsoft name: EmfPlusCustomEndCapData Object +*/ +int U_PMF_CUSTOMENDCAPDATA_print(const char *contents, const char *blimit){ + int32_t Size; + const char *Data; + int status = U_PMF_CUSTOMENDCAPDATA_get(contents, &Size, &Data, blimit); + if(status){ + printf(" + CustomEndCap: Size:%d\n",Size); + (void) U_PMF_CUSTOMLINECAP_print(Data, "End", blimit); + } + return(status); +} + +/** + \brief Print data from a U_PMF_CUSTOMLINECAPARROWDATA object + \return 1 on success, 0 on error + \param contents Record from which to print data + \param blimit one byte past the end of data + EMF+ manual 2.2.2.12, Microsoft name: EmfPlusCustomLineCapArrowData Object +*/ +int U_PMF_CUSTOMLINECAPARROWDATA_print(const char *contents, const char *blimit){ + U_PMF_CUSTOMLINECAPARROWDATA Ccad; + int status = U_PMF_CUSTOMLINECAPARROWDATA_get(contents, &Ccad, blimit); + if(status){ + printf("CustomLineCapArrowData: "); + printf(" Width:%f", Ccad.Width ); + printf(" Height:%f", Ccad.Height ); + printf(" MiddleInset:%f", Ccad.MiddleInset ); + printf(" FillState:%u", Ccad.FillState ); + printf(" StartCap:%X", Ccad.StartCap ); + printf(" EndCap:%X", Ccad.EndCap ); + printf(" Join:%X", Ccad.Join ); + printf(" MiterLimit:%f", Ccad.MiterLimit ); + printf(" WidthScale:%f", Ccad.WidthScale ); + printf(" FillHotSpot:{%f,%f}",Ccad.FillHotSpot[0],Ccad.FillHotSpot[1]); + printf(" LineHotSpot:{%f,%f}",Ccad.LineHotSpot[0],Ccad.LineHotSpot[1]); + printf("\n"); + } + return(status); +} + +/** + \brief Print data from a U_PMF_CUSTOMLINECAPDATA object + \return 1 on success, 0 on error + \param contents Record from which to print data + \param blimit one byte past the end of data + EMF+ manual 2.2.2.13, Microsoft name: EmfPlusCustomLineCapData Object +*/ +int U_PMF_CUSTOMLINECAPDATA_print(const char *contents, const char *blimit){ + U_PMF_CUSTOMLINECAPDATA Clcd; + const char *Data; + int status = U_PMF_CUSTOMLINECAPDATA_get(contents, &Clcd, &Data, blimit); + if(status){ + printf(" + CustomLineCapData: "); + printf(" Flags:%X", Clcd.Flags ); + printf(" Cap:%X", Clcd.Cap ); + printf(" Inset:%f", Clcd.Inset ); + printf(" StartCap:%X", Clcd.StartCap ); + printf(" EndCap:%X", Clcd.EndCap ); + printf(" Join:%X", Clcd.Join ); + printf(" MiterLimit:%f", Clcd.MiterLimit ); + printf(" WidthScale:%f", Clcd.WidthScale ); + printf(" FillHotSpot:{%f,%f}",Clcd.FillHotSpot[0],Clcd.FillHotSpot[1]); + printf(" LineHotSpot:{%f,%f}\n",Clcd.LineHotSpot[0],Clcd.LineHotSpot[1]); + (void) U_PMF_CUSTOMLINECAPOPTIONALDATA_print(Data, Clcd.Flags, blimit); + /* preceding line always emits an EOL */ + } + return(status); +} + + +/** + \brief Print data from a U_PMF_CUSTOMLINECAPOPTIONALDATA object + \return 1 on success, 0 on error + \param contents Record from which to print data + \param Flags CustomLineCapData Flags + \param blimit one byte past the end of data + + EMF+ manual 2.2.2.14, Microsoft name: EmfPlusCustomLineCapOptionalData Object +*/ +int U_PMF_CUSTOMLINECAPOPTIONALDATA_print(const char *contents, uint32_t Flags, const char *blimit){ + const char *FillData; + const char *LineData; + int status = U_PMF_CUSTOMLINECAPOPTIONALDATA_get(contents, Flags, &FillData, &LineData, blimit); + if(status){ /* True even if there is nothing in it! */ + printf(" + CustomLineCapOptionalData:"); + if(FillData || LineData){ + if(FillData){ (void) U_PMF_FILLPATHOBJ_print(FillData, blimit); } + if(LineData){ (void) U_PMF_LINEPATH_print(LineData, blimit); } + } + else { + printf("None"); + } + } + if(status<=1){ printf("\n"); } + return(status); +} + +/** + \brief Print data from a U_PMF_CUSTOMSTARTCAPDATA object + \return 1 on success, 0 on error + \param contents Record from which to print data + \param blimit one byte past the end of data + EMF+ manual 2.2.2.15, Microsoft name: EmfPlusCustomStartCapData Object +*/ +int U_PMF_CUSTOMSTARTCAPDATA_print(const char *contents, const char *blimit){ + int32_t Size; + const char *Data; + int status = U_PMF_CUSTOMSTARTCAPDATA_get(contents, &Size, &Data, blimit); + if(status){ + printf(" + CustomStartCap: Size:%d ",Size); + (void) U_PMF_CUSTOMLINECAP_print(Data, "Start", blimit); + } + return(status); +} + +/** + \brief Print data from a U_PMF_DASHEDLINEDATA object + \return 1 on success, 0 on error + \param contents Record from which to print data + \param blimit one byte past the end of data + EMF+ manual 2.2.2.16, Microsoft name: EmfPlusDashedLineData Object +*/ +int U_PMF_DASHEDLINEDATA_print(const char *contents, const char *blimit){ + int32_t Elements; + U_FLOAT *Lengths; + U_FLOAT *hold; + int status = U_PMF_DASHEDLINEDATA_get(contents, &Elements, &Lengths, blimit); + if(status){ + printf(" DashedLineData: Elements:%u {",Elements); + Elements--; + for(hold=Lengths; Elements; Elements--, Lengths++){ printf("%f, ", *Lengths); } + printf("%f}", *Lengths); + free(hold); + } + return(status); +} + +/** + \brief Print data from a U_PMF_FILLPATHOBJ object + \return 1 on success, 0 on error + \param contents Record from which to print data + \param blimit one byte past the end of data + EMF+ manual 2.2.2.17, Microsoft name: EmfPlusFillPath Object +*/ +int U_PMF_FILLPATHOBJ_print(const char *contents, const char * blimit){ + int32_t Size; + const char *Data; + int status = U_PMF_FILLPATHOBJ_get(contents, &Size, &Data, blimit); + if(status){ + printf(" FillPathObj: Size:%d\n",Size); + if(Size){ (void) U_PMF_PATH_print(Data, blimit); } + } + return(status); +} + +/** + \brief Print data from a U_PMF_FOCUSSCALEDATA object + \return 1 on success, 0 on error + \param contents Record from which to print data + \param blimit one byte past the end of data + EMF+ manual 2.2.2.18, Microsoft name: EmfPlusFocusScaleData Object +*/ +int U_PMF_FOCUSSCALEDATA_print(const char *contents, const char *blimit){ + uint32_t Count; + U_FLOAT ScaleX, ScaleY; + int status = U_PMF_FOCUSSCALEDATA_get(contents, &Count, &ScaleX, &ScaleY, blimit); + if(status){ + printf(" FocusScaleData: Count:%d ScaleX:%f ScaleY:%f ",Count,ScaleX,ScaleY); + } + return(status); +} + +/** + \brief Print data from a U_PMF_GRAPHICSVERSION object already known to be memory safe + \return 1 on success, 0 on error + \param contents Record from which to print data + EMF+ manual 2.2.2.19, Microsoft name: EmfPlusGraphicsVersion Object + + In this module the only time a U_PMF_GRAPHICSVERSION is printed is after it + has already been copied into a safe memory structure. This routine fakes up + a blimit for the general routine. + +*/ +int U_PMF_GRAPHICSVERSION_memsafe_print(const char *contents){ + const char *blimit = contents + sizeof(U_PMF_GRAPHICSVERSION); + return(U_PMF_GRAPHICSVERSION_print(contents, blimit)); +} + +/** + \brief Print data from a U_PMF_GRAPHICSVERSION object + \return 1 on success, 0 on error + \param contents Record from which to print data + \param blimit one byte past the end of data + EMF+ manual 2.2.2.19, Microsoft name: EmfPlusGraphicsVersion Object +*/ +int U_PMF_GRAPHICSVERSION_print(const char *contents, const char *blimit){ + int Signature,GrfVersion; + int status = U_PMF_GRAPHICSVERSION_get(contents, &Signature, &GrfVersion, blimit); + if(status){ + printf(" MetaFileSig:%X",Signature ); + printf(" GraphicsVersion:%X", GrfVersion); + } + return(status); +} + + +/** + \brief Print data from a U_PMF_HATCHBRUSHDATA object + \return 1 on success, 0 on error + \param contents Record from which to print data + \param blimit One byte past the last record in memory. + EMF+ manual 2.2.2.20, Microsoft name: EmfPlusHatchBrushData Object +*/ +int U_PMF_HATCHBRUSHDATA_print(const char *contents, const char *blimit){ + uint32_t Style; + U_PMF_ARGB Foreground, Background; + int status = U_PMF_HATCHBRUSHDATA_get(contents, &Style, &Foreground, &Background, blimit); + if(status){ + printf(" + HBdata: Style:%u(",Style); + U_PMF_HATCHSTYLEENUMERATION_print(Style); + printf(") FG:{"); + (void) U_PMF_ARGB_print((char *)&Foreground); + printf("} BG:{"); + (void) U_PMF_ARGB_print((char *)&Background); + printf("}"); + } + return(status); +} + +/** + \brief Print data from a U_PMF_LANGUAGEIDENTIFIER object + \return 1 on success, 0 on error + \param LId Record from which to print data + EMF+ manual 2.2.2.23, Microsoft name: EmfPlusLanguageIdentifier Object +*/ +int U_PMF_LANGUAGEIDENTIFIER_print(U_PMF_LANGUAGEIDENTIFIER LId){ + int SubLId, PriLId; + int status = U_PMF_LANGUAGEIDENTIFIER_get(LId, &SubLId, &PriLId); + if(status){ /* do it the hard way just to verify that the preceding call works, OK to just print LId directly */ + printf("{%4.4X}",U_PMF_LANGUAGEIDENTIFIEROBJ_set(SubLId, PriLId)); + } + return(status); +} + + + +/** + \brief Print data from a U_PMF_LINEARGRADIENTBRUSHDATA object + \return 1 on success, 0 on error + \param contents Record from which to print data + \param blimit One byte past the last record in memory. + EMF+ manual 2.2.2.24, Microsoft name: EmfPlusLinearGradientBrushData Object +*/ +int U_PMF_LINEARGRADIENTBRUSHDATA_print(const char *contents, const char *blimit){ + U_PMF_LINEARGRADIENTBRUSHDATA Lgbd; + const char *Data; + int status = U_PMF_LINEARGRADIENTBRUSHDATA_get(contents, &Lgbd, &Data, blimit); + if(status){ + printf(" + LinearGradientBrushData: Flags:%X WrapMode:%d Rect:",Lgbd.Flags, Lgbd.WrapMode); + (void) U_PMF_RECTF_S_print(&(Lgbd.RectF)); + printf(" StartColor:"); + (void) U_PMF_ARGB_print((char *)&(Lgbd.StartColor)); + printf(" EndColor:"); + (void) U_PMF_ARGB_print((char *)&(Lgbd.EndColor)); + /* Technically these are to be ignored, in practice they must be colors with the same value as the preceding 2*/ + printf(" Reserved1:"); + (void) U_PMF_ARGB_print((char *)&(Lgbd.Reserved1)); + printf(" Reserved2:"); + (void) U_PMF_ARGB_print((char *)&(Lgbd.Reserved2)); + printf("\n"); + (void) U_PMF_LINEARGRADIENTBRUSHOPTIONALDATA_print(Data, Lgbd.Flags, blimit); + } + return(status); +} + + + +/** + \brief Print data from a U_PMF_LINEARGRADIENTBRUSHOPTIONALDATA object + \return 1 on success, 0 on error + \param contents Record from which to print data + \param BDFlag Describes optional values in contents + \param blimit One byte past the last record in memory. + EMF+ manual 2.2.2.25, Microsoft name: EmfPlusLinearGradientBrushOptionalData Object +*/ +int U_PMF_LINEARGRADIENTBRUSHOPTIONALDATA_print(const char *contents, int BDFlag, const char *blimit){ + U_PMF_TRANSFORMMATRIX Tm; + const char *Bc; + const char *BfH; + const char *BfV; + int None=1; + printf(" + LinearGradientBrushOptionalData: "); + int status = U_PMF_LINEARGRADIENTBRUSHOPTIONALDATA_get(contents, BDFlag, &Tm, &Bc, &BfH, &BfV, blimit); + if(status){ + if(BDFlag & U_BD_Transform){ + U_PMF_TRANSFORMMATRIX2_print(&Tm); + None=0; + } + if(Bc){ + printf("\n"); + (void) U_PMF_BLENDCOLORS_print(Bc, blimit); + None=0; + } + if(BfH){ + printf("\n"); + (void) U_PMF_BLENDFACTORS_print(BfH,"H", blimit); + None=0; + } + if(BfV){ + printf("\n"); + (void) U_PMF_BLENDFACTORS_print(BfV,"V", blimit); + None=0; + } + if(None){ + printf("(none)"); + } + } + return(status); +} + +/** + \brief Print data from a U_PMF_LINEPATH object + \return 1 on success, 0 on error + \param contents Record from which to print data + \param blimit one byte past the end of data + EMF+ manual 2.2.2.26, Microsoft name: EmfPlusLinePath Object +*/ +int U_PMF_LINEPATH_print(const char *contents, const char * blimit){ + int32_t Size; + const char *Data; + int status = U_PMF_LINEPATH_get(contents, &Size, &Data, blimit); + if(status){ + printf(" LinePath: Size:%d\n", Size); + (void) U_PMF_PATH_print(Data, blimit); + } + return(status); +} + +/** + \brief Print data from a U_PMF_METAFILE object + \return 1 on success, 0 on error + \param contents Record from which to print data + \param blimit one byte past the end of data + EMF+ manual 2.2.2.27, Microsoft name: EmfPlusMetafile Object +*/ +int U_PMF_METAFILE_print(const char *contents, const char * blimit){ + uint32_t Type; + uint32_t Size; + const char *Data; + int status = U_PMF_METAFILE_get(contents, &Type, &Size, &Data, blimit); + if(status){ + printf(" MetaFile: Type:%X Size:%d",Type, Size); + /* embedded metafiles are not handled beyond this*/ + } + return(status); +} + +/** + \brief Print data from a U_PMF_PALETTE object + \return 1 on success, 0 on error + \param contents Record from which to print data + \param blimit one byte past the end of data + EMF+ manual 2.2.2.28, Microsoft name: EmfPlusPalette Object +*/ +int U_PMF_PALETTE_print(const char *contents, const char *blimit){ + unsigned int i; + uint32_t Flags; + uint32_t Elements; + const char *Data; + int status = U_PMF_PALETTE_get(contents, &Flags, &Elements, &Data, blimit); + if(status){ + printf(" Palette: Flags:%X Elements:%u Colors:",Flags, Elements); + for(i=0; i<Elements; i++){ + (void) U_PMF_ARGB_print(Data); + Data += sizeof(U_PMF_ARGB); + } + printf("\n"); + } + return(status); +} + +/** + \brief Print data from a U_PMF_PATHGRADIENTBRUSHDATA object + \return 1 on success, 0 on error + \param contents Record from which to print data + \param blimit one byte past the end of data + EMF+ manual 2.2.2.29, Microsoft name: EmfPlusPathGradientBrushData Object +*/ +int U_PMF_PATHGRADIENTBRUSHDATA_print(const char *contents, const char *blimit){ + U_PMF_PATHGRADIENTBRUSHDATA Pgbd; + const char *Gradient; + const char *Boundary; + const char *Data=NULL; + unsigned int i; + int status = U_PMF_PATHGRADIENTBRUSHDATA_get(contents, &Pgbd, &Gradient, &Boundary, &Data, blimit); + if(status){ + printf(" + PathGradientBrushData: Flags:%X WrapMode:%d, CenterColor:",Pgbd.Flags, Pgbd.WrapMode); + (void) U_PMF_ARGB_print((char *)&(Pgbd.CenterColor)); + printf(" Center:"); + (void) U_PMF_POINTF_S_print(&(Pgbd.Center)); + printf(" Elements:%u\n",Pgbd.Elements); + if(Pgbd.Elements){ + printf(" + SurroundingColor: "); + for(i=Pgbd.Elements; i; i--, Gradient+=4){ + (void) U_PMF_ARGB_print(Gradient); + } + printf("\n"); + } + if(Pgbd.Flags & U_BD_Path){ + (void) U_PMF_BOUNDARYPATHDATA_print(Boundary, blimit); + } + else { + (void) U_PMF_BOUNDARYPOINTDATA_print(Boundary, blimit); + } + (void) U_PMF_PATHGRADIENTBRUSHOPTIONALDATA_print(Data, Pgbd.Flags, blimit); + } + return(status); +} + +/** + \brief Print data from a U_PMF_PATHGRADIENTBRUSHOPTIONALDATA object + \return 1 on success, 0 on error + \param contents Record from which to print data + \param BDFlag Describes optional values in contents + \param blimit one byte past the end of data + EMF+ manual 2.2.2.30, Microsoft name: EmfPlusPathGradientBrushOptionalData Object +*/ +int U_PMF_PATHGRADIENTBRUSHOPTIONALDATA_print(const char *contents, int BDFlag, const char *blimit){ + if(BDFlag & (U_BD_Transform | U_BD_PresetColors | U_BD_BlendFactorsH | U_BD_FocusScales)){ + printf(" + PathGradientBrushOptionalData: "); + } + if(BDFlag & U_BD_Transform){ + U_PMF_TRANSFORMMATRIX_print(contents, blimit); + contents += sizeof(U_PMF_TRANSFORMMATRIX); + } + if(BDFlag & U_BD_PresetColors){ /* If this is present, BlendFactorsH will not be */ + contents += U_PMF_BLENDCOLORS_print(contents, blimit); + } + if(BDFlag & U_BD_BlendFactorsH){/* If this is present, U_BD_PresetColors will not be */ + contents += U_PMF_BLENDFACTORS_print(contents,"", blimit); + } + if(BDFlag & U_BD_FocusScales){ + contents += U_PMF_BLENDFACTORS_print(contents,"", blimit); + U_PMF_FOCUSSCALEDATA_print(contents, blimit); + } + return(1); +} + +/** + \brief Print data from a U_PMF_PATHPOINTTYPE object + \return 1 on success, 0 on error + \param contents Record from which to print data + \param blimit one byte past the end of data + EMF+ manual 2.2.2.31, Microsoft name: EmfPlusPathPointType Object +*/ +int U_PMF_PATHPOINTTYPE_print(const char *contents, const char *blimit){ + int Flags, Type; + int status = U_PMF_PATHPOINTTYPE_get(contents, &Flags, &Type, blimit); + if(status){ + printf("{Flags:%X Type:",Flags); + (void) U_PMF_PATHPOINTTYPE_ENUM_print(Type); + printf("}"); + } + return(status); +} + +/** + \brief Print data from a U_PMF_PATHPOINTTYPERLE object + \return Number of elements in the run, 0 on error + \param contents Record from which to print data + \param blimit one byte past the end of data + EMF+ manual 2.2.2.32, Microsoft name: EmfPlusPathPointTypeRLE Object +*/ +int U_PMF_PATHPOINTTYPERLE_print(const char *contents, const char *blimit){ + int Bezier, Elements, Type; + int status = U_PMF_PATHPOINTTYPERLE_get(contents, &Bezier, &Elements, &Type, blimit); + if(status){ + status = Elements; + printf(" PathPointTypeRLE: Bezier:%c Elements:%u, Type: ",(Bezier ? 'Y' : 'N'), Elements); + (void) U_PMF_PATHPOINTTYPE_ENUM_print(Type); + printf("\n"); + } + return(status); +} + +/** + \brief Print data from a U_PMF_PATHPOINTTYPERLE object + \return 1 on success, 0 on error + \param contents Record from which to print data + \param blimit one byte past the end of data + EMF+ manual 2.2.2.33, Microsoft name: EmfPlusPenData Object +*/ +int U_PMF_PENDATA_print(const char *contents, const char *blimit){ + uint32_t Flags, Unit; + U_FLOAT Width; + const char *Data; + int status = U_PMF_PENDATA_get(contents, &Flags, &Unit, &Width, &Data, blimit); + if(status){ + printf(" + Pendata: Flags:%X Unit:%X Width:%f",Flags, Unit, Width); + (void) U_PMF_PENOPTIONALDATA_print(Data, Flags, blimit); /* prints a new line at end */ + } + return(status); +} + + + +/** + \brief Print data from a U_PMF_PENOPTIONALDATA object + \return 1 on success, 0 on error + \param contents Record from which to print data + \param blimit one byte past the end of data + \param Flags PenData Flags that determine which optionaldata fields are present in the record. + + EMF+ manual 2.2.2.34, Microsoft name: EmfPlusPenOptionalData Object +*/ +int U_PMF_PENOPTIONALDATA_print(const char *contents, int Flags, const char *blimit){ + U_PMF_TRANSFORMMATRIX Matrix; + int32_t StartCap; + int32_t EndCap; + uint32_t Join; + U_FLOAT MiterLimit; + int32_t Style; + int32_t DLCap; + U_FLOAT DLOffset; + const char *DLData; + int32_t Alignment; + const char *CmpndLineData; + const char *CSCapData; + const char *CECapData; + int status = U_PMF_PENOPTIONALDATA_get( + contents, + Flags, // determines which fields are filled + &Matrix, + &StartCap, + &EndCap, + &Join, + &MiterLimit, + &Style, + &DLCap, + &DLOffset, + &DLData, + &Alignment, + &CmpndLineData, + &CSCapData, + &CECapData, + blimit); + if(status){ + if(Flags & U_PD_Transform){ (void) U_PMF_TRANSFORMMATRIX2_print(&Matrix);} + if(Flags & U_PD_StartCap){ printf(" StartCap:%d", StartCap );} + if(Flags & U_PD_EndCap){ printf(" EndCap:%d", EndCap );} + if(Flags & U_PD_Join){ printf(" Join:%X", Join );} + if(Flags & U_PD_MiterLimit){ printf(" MiterLimit:%f", MiterLimit );} + if(Flags & U_PD_LineStyle){ printf(" Style:%X", Style );} + if(Flags & U_PD_DLCap){ printf(" DLCap:%X", DLCap );} + if(Flags & U_PD_DLOffset){ printf(" DLOffset:%f", DLOffset );} + if(Flags & U_PD_DLData){ (void) U_PMF_DASHEDLINEDATA_print(DLData, blimit );} + if(Flags & U_PD_NonCenter){ printf(" Alignment:%d", Alignment );} + if(Flags & (U_PD_Transform | U_PD_StartCap | U_PD_EndCap | + U_PD_Join | U_PD_MiterLimit | U_PD_LineStyle | + U_PD_DLCap | U_PD_DLOffset |U_PD_DLData |U_PD_NonCenter)){ printf("\n"); } + if(Flags & U_PD_CLData){ (void) U_PMF_COMPOUNDLINEDATA_print(CmpndLineData, blimit); } + if(Flags & U_PD_CustomStartCap){ (void) U_PMF_CUSTOMSTARTCAPDATA_print(CSCapData, blimit); } + if(Flags & U_PD_CustomEndCap){ (void) U_PMF_CUSTOMENDCAPDATA_print(CECapData, blimit); } + } + return(status); +} +/** + \brief Print data from a U_PMF_POINT object + \return 1 on success, 0 on error + \param contents Record from which to print data + \param blimit one byte past the end of data + EMF+ manual 2.2.2.35, Microsoft name: EmfPlusPoint Object +*/ +int U_PMF_POINT_print(const char **contents, const char *blimit){ + U_FLOAT X, Y; + int status = U_PMF_POINT_get(contents, &X, &Y, blimit); + if(status){ + printf("{%f,%f}", X, Y); + } + return(status); +} + +/** + \brief Print data from a U_PMF_POINT Structure + \return 1 on success, 0 on error + \param Point U_PMF_POINT Structure to print + EMF+ manual 2.2.2.35, Microsoft name: EmfPlusPoint Object +*/ +int U_PMF_POINT_S_print(U_PMF_POINT *Point){\ + if(!Point){ return(0); } + printf("{%d,%d}", Point->X, Point->Y); + return(1); +} + +/** + \brief Print data from a U_PMF_POINTF object + \return 1 on success, 0 on error + \param contents Record from which to print data + \param blimit one byte past the end of data + EMF+ manual 2.2.2.36, Microsoft name: EmfPlusPointF Object +*/ +int U_PMF_POINTF_print(const char **contents, const char *blimit){ + U_FLOAT X, Y; + int status = U_PMF_POINTF_get(contents, &X, &Y, blimit); + if(status){ + printf("{%f,%f}", X, Y); + } + return(status); +} + +/** + \brief Print data from a U_PMF_POINTF Structure + \return 1 on success, 0 on error + \param Point U_PMF_POINTF Structure to print + EMF+ manual 2.2.2.36, Microsoft name: EmfPlusPointF Object +*/ +int U_PMF_POINTF_S_print(U_PMF_POINTF *Point){ + if(!Point){ return(0); } + printf("{%f,%f}", Point->X, Point->Y); + return(1); +} + +/** + \brief Print data from a U_PMF_POINTR object + \return bytes traversed on success, 0 on error + \param contents Pointer to next data to print + \param Xpos X coordinate for current point + \param Ypos Y coordinate for current point + \param blimit one byte past the end of data + + On each call the next relative offset is extracted, the current + coordinates are modified with that offset, and the pointer is + advanced to the next data point. + + EMF+ manual 2.2.2.37, Microsoft name: EmfPlusPointR Object +*/ +int U_PMF_POINTR_print(const char **contents, U_FLOAT *Xpos, U_FLOAT *Ypos, const char *blimit){ + U_FLOAT X, Y; + int status = U_PMF_POINTR_get(contents, &X, &Y, blimit); + *Xpos += X; + *Ypos += Y; + if(status){ + printf("{%f,%f(%f,%f)}", *Xpos, *Ypos, X, Y); + } + return(status); +} + +/** + \brief Print data from a U_PMF_RECT object + \return 1 on success, 0 on error + \param contents Record from which to print data + \param blimit one byte past the end of data + EMF+ manual 2.2.2.38, Microsoft name: EmfPlusRect Object +*/ +int U_PMF_RECT_print(const char **contents, const char *blimit){ + int16_t X, Y, Width, Height; + int status = U_PMF_RECT_get(contents, &X, &Y, &Width, &Height, blimit); + if(status){ + printf("{UL{%d,%d},WH{%d,%d}}", X, Y, Width, Height); + } + return(status); +} + +/** + \brief Print data from a U_PMF_RECT Structure + \return 1 on success, 0 on error + \param Rect U_PMF_RECT structure + EMF+ manual 2.2.2.39, Microsoft name: EmfPlusRectF Object +*/ +int U_PMF_RECT_S_print(U_PMF_RECT *Rect){ + printf("{UL{%d,%d},WH{%d,%d}}", Rect->X, Rect->Y, Rect->Width, Rect->Height); + return(1); +} + +/** + \brief Print data from a U_PMF_RECTF object + \return 1 on success, 0 on error + \param contents Record from which to print data + \param blimit one byte past the end of data + EMF+ manual 2.2.2.39, Microsoft name: EmfPlusRectF Object +*/ +int U_PMF_RECTF_print(const char **contents, const char *blimit){ + U_FLOAT X, Y, Width, Height; + int status = U_PMF_RECTF_get(contents, &X, &Y, &Width, &Height, blimit); + if(status){ + printf("{UL{%f,%f},WH{%f,%f}}", X, Y, Width, Height); + } + return(status); +} + +/** + \brief Print data from a U_PMF_RECTF Structure + \return 1 on success, 0 on error + \param Rect U_PMF_RECTF Structure + EMF+ manual 2.2.2.39, Microsoft name: EmfPlusRectF Object +*/ +int U_PMF_RECTF_S_print(U_PMF_RECTF *Rect){ + printf("{UL{%f,%f},WH{%f,%f}}", Rect->X, Rect->Y, Rect->Width, Rect->Height); + return(1); +} + +/** + \brief Print data from a U_PMF_REGIONNODE object + \return size on success, 0 on error + \param contents Record from which to print data + \param Level Tree level. This routine is recursive and could go down many levels. 1 is the top, >1 are child nodes. + \param blimit one byte past the end of data + EMF+ manual 2.2.2.40, Microsoft name: EmfPlusRegionNode Object +*/ +int U_PMF_REGIONNODE_print(const char *contents, int Level, const char *blimit){ + int len=4; /* Type will always be present */ + uint32_t Type; + const char *Data; + int status = U_PMF_REGIONNODE_get(contents, &Type, &Data, blimit); + if(status){ + printf("\n + RegionNode(Level:%d) { Type:%X(",Level,Type); + U_PMF_NODETYPE_print(Type); + printf(")"); + if(Type >= U_RNDT_And && Type <= U_RNDT_Complement){ + len += U_PMF_REGIONNODECHILDNODES_print(Data, Level+1, blimit); + } + else if(Type == U_RNDT_Rect){ + len += sizeof(U_PMF_RECTF); + (void) U_PMF_RECTF_print(&Data, blimit); + printf("\n"); + } + else if(Type == U_RNDT_Path){ + len += U_PMF_REGIONNODEPATH_print(Data, blimit); + } + /* U_RNDT_Empty and U_RNDT_Infinite do not change the length */ + else if(Type == U_RNDT_Empty ){ printf(" Empty" ); } + else if(Type == U_RNDT_Infinite ){ printf(" Infinite" ); } + printf(" + RegionNode(Level:%d) }",Level); + status = len; /* length of data + length of type */ + } + printf("\n"); + return(status); +} + +/** + \brief Print data from a U_PMF_REGIONNODECHILDNODES object + \return size on success, 0 on error + \param contents Record from which to print data + \param Level Tree level. This routine is recursive and could go down many levels. 1 is the top, >1 are child nodes. + \param blimit one byte past the end of data + EMF+ manual 2.2.2.41, Microsoft name: EmfPlusRegionNodeChildNodes Object +*/ +int U_PMF_REGIONNODECHILDNODES_print(const char *contents, int Level, const char *blimit){ + uint32_t size,rsize; + printf(" RegionNodeChildNodes:\n"); + printf(" + RNCN__Left(Level:%d) {", Level); + size = U_PMF_REGIONNODE_print(contents, Level, blimit); + printf(" + RNCN__Left(Level:%d) },\n", Level); + if(size){ + contents += size; + printf(" + RNCN_Right(Level:%d) {", Level); + rsize = U_PMF_REGIONNODE_print(contents, Level, blimit); + size += rsize; + printf(" + RNCN_Right(Level:%d) },\n",Level); + } + return(size); +} + +/** + \brief Print data from a U_PMF_REGIONNODEPATH object + \return Size of data on success, 0 on error + \param contents Record from which to print data + \param blimit one byte past the end of data + EMF+ manual 2.2.2.42, Microsoft name: EmfPlusRegionNodePath Object +*/ +int U_PMF_REGIONNODEPATH_print(const char *contents, const char * blimit){ + int32_t Size; + const char *Data; + int status = U_PMF_REGIONNODEPATH_get(contents, &Size, &Data, blimit); + if(status){ + printf(" RegionNodePath: \n"); + (void) U_PMF_PATH_print(Data, blimit); + status = Size + 4; /* data sizee + the 4 bytes encoding the size */ + } + return(status); +} + + +/** + \brief Print data from a U_PMF_SOLIDBRUSHDATA object + \return 1 on success, 0 on error + \param contents Record from which to print data + \param blimit one byte past the end of data + EMF+ manual 2.2.2.43, Microsoft name: EmfPlusSolidBrushData Object +*/ +int U_PMF_SOLIDBRUSHDATA_print(const char *contents, const char *blimit){ + U_PMF_ARGB Color; + int status = U_PMF_SOLIDBRUSHDATA_get(contents, &Color, blimit); + if(status){ + printf(" SolidBrushData: "); + (void) U_PMF_ARGB_print((char *) &Color); + } + return(status); +} + +/** + \brief Print data from a U_PMF_STRINGFORMATDATA object + \return 1 on success, 0 on error + \param contents Record from which to print data + \param TabStopCount Entries in TabStop array + \param RangeCount Entries in CharRange array + \param blimit one byte past the end of data + EMF+ manual 2.2.2.44, Microsoft name: EmfPlusStringFormatData Object +*/ +int U_PMF_STRINGFORMATDATA_print(const char *contents, uint32_t TabStopCount, uint32_t RangeCount, const char *blimit){ + const U_FLOAT *TabStops; + const U_PMF_CHARACTERRANGE *CharRange; + int status = U_PMF_STRINGFORMATDATA_get(contents, TabStopCount, RangeCount, &TabStops, &CharRange, blimit); + if(status){ + printf(" SFdata: TabStopCount:%u RangeCount:%u\n", TabStopCount, RangeCount); + + printf(" Tabstops:"); + for(; TabStopCount; TabStopCount--,TabStops++){ printf(" %f",*TabStops); } + printf("\n"); + + printf(" CharRange:"); + for(; RangeCount; RangeCount--,CharRange++){ printf(" {%d,%d}",CharRange->First,CharRange->Length); } + printf("\n"); + + } + return(status); +} + +/** + \brief Print data from a U_PMF_TEXTUREBRUSHDATA object + \return 1 on success, 0 on error + \param contents Record from which to print data + \param blimit one byte past the end of data + EMF+ manual 2.2.2.45, Microsoft name: EmfPlusTextureBrushData Object +*/ +int U_PMF_TEXTUREBRUSHDATA_print(const char *contents, const char *blimit){ + uint32_t Flags; + int32_t WrapMode; + const char *Data; + int status = U_PMF_TEXTUREBRUSHDATA_get(contents, &Flags, &WrapMode, &Data, blimit); + if(status){ + printf(" + TBdata: Flags:%X WrapMode:%d", Flags, WrapMode); + } + return(status); +} + +/** + \brief Print data from a U_PMF_TEXTUREBRUSHOPTIONALDATA object + \return 1 on success, 0 on error + \param contents Record from which to print data + \param HasMatrix True if the record contains a matrix. + \param HasImage True if the record contains an image. + \param blimit one byte past the end of data + + EMF+ manual 2.2.2.46, Microsoft name: EmfPlusTextureBrushOptionalData Object +*/ +int U_PMF_TEXTUREBRUSHOPTIONALDATA_print(const char *contents, int HasMatrix, int HasImage, const char *blimit){ + U_PMF_TRANSFORMMATRIX Matrix; + U_PMF_TRANSFORMMATRIX *pMatrix; + const char *Image; + if(HasMatrix){ pMatrix = &Matrix; } + else { pMatrix = NULL; } + int status = U_PMF_TEXTUREBRUSHOPTIONALDATA_get(contents, HasImage, pMatrix, &Image, blimit); + if(status){ + printf(" + TBOptdata: Image:%c", (HasImage ? 'Y' : 'N')); + (void) U_PMF_TRANSFORMMATRIX2_print(&Matrix); + (void) U_PMF_IMAGE_print(Image, blimit); + } + return(status); +} + +/** + \brief Print data from a U_PMF_TRANSFORMMATRIX object stored in file byte order. + \return 1 on success, 0 on error + \param contents Record from which to print data + \param blimit one byte past the end of data + EMF+ manual 2.2.2.47, Microsoft name: EmfPlusTransformMatrix Object +*/ +int U_PMF_TRANSFORMMATRIX_print(const char *contents, const char *blimit){ + U_PMF_TRANSFORMMATRIX Tm; + int status = U_PMF_TRANSFORMMATRIX_get(contents, &Tm, blimit); + if(status){ + U_PMF_TRANSFORMMATRIX2_print(&Tm); + } + return(status); +} + +/** + \brief Print data from a U_PMF_TRANSFORMMATRIX structure + \return 1 on success, 0 on error + \param Tm U_PMF_TRANSFORMMATRIX structure + EMF+ manual 2.2.2.47, Microsoft name: EmfPlusTransformMatrix Object +*/ +int U_PMF_TRANSFORMMATRIX2_print(U_PMF_TRANSFORMMATRIX *Tm){ + if(Tm){ + printf(" Matrix:{%f,%f,%f,%f,%f,%f}", Tm->m11, Tm->m12, Tm->m21, Tm->m22, Tm->dX, Tm->dY); + } + else { + printf(" Matrix:(None)"); + } + return(1); +} + +/** + \brief Print data from a U_PMF_ROTMATRIX object + \return 1 on success, 0 on error + \param Rm U_PMF_ROTMATRIX object + NOT DOCUMENTED, like EMF+ manual 2.2.2.47, Microsoft name: EmfPlusTransformMatrix Object, but missing offset values +*/ +int U_PMF_ROTMATRIX2_print(U_PMF_ROTMATRIX *Rm){ + printf(" Matrix:{%f,%f,%f,%f}", Rm->m11, Rm->m12, Rm->m21, Rm->m22); + return(1); +} + +/** + \brief Print data from a U_PMF_IE_BLUR object + \return 1 on success, 0 on error + \param contents Record from which to print data + \param blimit one byte past the end of data + EMF+ manual 2.2.3.1, Microsoft name: BlurEffect Object +*/ +int U_PMF_IE_BLUR_print(const char *contents, const char *blimit){ + U_FLOAT Radius; + uint32_t ExpandEdge; + int status = U_PMF_IE_BLUR_get(contents, &Radius, &ExpandEdge, blimit); + if(status){ + printf("BlurEffect Radius:%f ExpandEdge:%u\n", Radius, ExpandEdge); + } + return(status); +} + +/** + \brief Print data from a U_PMF_IE_BRIGHTNESSCONTRAST object + \return 1 on success, 0 on error + \param contents Record from which to print data + \param blimit one byte past the end of data + EMF+ manual 2.2.3.2, Microsoft name: BrightnessContrastEffect Object +*/ +int U_PMF_IE_BRIGHTNESSCONTRAST_print(const char *contents, const char *blimit){ + int32_t Brightness, Contrast; + int status = U_PMF_IE_BRIGHTNESSCONTRAST_get(contents, &Brightness, &Contrast, blimit); + if(status){ + printf("BrightnessContrastEffect Brightness:%d Contrast:%d\n", Brightness, Contrast); + } + return(status); +} + +/** + \brief Print data from a U_PMF_IE_COLORBALANCE object + \return 1 on success, 0 on error + \param contents Record from which to print data + \param blimit one byte past the end of data + EMF+ manual 2.2.3.3, Microsoft name: ColorBalanceEffect Object +*/ +int U_PMF_IE_COLORBALANCE_print(const char *contents, const char *blimit){ + int32_t CyanRed, MagentaGreen, YellowBlue; + int status = U_PMF_IE_COLORBALANCE_get(contents, &CyanRed, &MagentaGreen, &YellowBlue, blimit); + if(status){ + printf("ColorBalanceEffect CyanRed:%d MagentaGreen:%d YellowBlue:%d\n", CyanRed, MagentaGreen, YellowBlue); + } + return(status); +} + +/** + \brief Print data from a U_PMF_IE_COLORCURVE object + \return 1 on success, 0 on error + \param contents Record from which to print data + \param blimit one byte past the end of data + EMF+ manual 2.2.3.4, Microsoft name: ColorCurveEffect Object +*/ +int U_PMF_IE_COLORCURVE_print(const char *contents, const char *blimit){ + uint32_t Adjust, Channel; + int32_t Intensity; + int status = U_PMF_IE_COLORCURVE_get(contents, &Adjust, &Channel, &Intensity, blimit); + if(status){ + printf("ColorBalanceEffect Adjust:%u Channel:%u Intensity:%d\n", Adjust, Channel, Intensity); + } + return(status); +} + +/** + \brief Print data from a U_PMF_IE_COLORLOOKUPTABLE object + \return 1 on success, 0 on error + \param contents Record from which to print data + \param blimit one byte past the end of data + EMF+ manual 2.2.3.5, Microsoft name: ColorLookupTableEffect Object +*/ +int U_PMF_IE_COLORLOOKUPTABLE_print(const char *contents, const char *blimit){ + const uint8_t *BLUT, *GLUT, *RLUT, *ALUT; + int status = U_PMF_IE_COLORLOOKUPTABLE_get(contents, &BLUT, &GLUT, &RLUT, &ALUT, blimit); + if(status){ + printf("ColorLookupTableEffect \n"); + U_PMF_UINT8_ARRAY_print(" BLUT:", BLUT, 256, "\n"); + U_PMF_UINT8_ARRAY_print(" GLUT:", GLUT, 256, "\n"); + U_PMF_UINT8_ARRAY_print(" RLUT:", RLUT, 256, "\n"); + U_PMF_UINT8_ARRAY_print(" ALUT:", ALUT, 256, "\n"); + } + return(status); +} + +/** + \brief Print data from a U_PMF_IE_COLORMATRIX object + \return 1 on success, 0 on error + \param contents Record from which to print data + \param blimit one byte past the end of data + EMF+ manual 2.2.3.6, Microsoft name: ColorMatrixEffect Object +*/ +int U_PMF_IE_COLORMATRIX_print(const char *contents, const char *blimit){ + U_PMF_IE_COLORMATRIX Matrix; + int i,j; + int status = U_PMF_IE_COLORMATRIX_get(contents, &Matrix, blimit); + if(status){ + printf("ColorMatrixEffect\n"); + for(i=0;i<5;i++){ + printf(" {"); + for(j=0;j<4;i++){ printf("%f,",Matrix.M[i][j]); } + printf("%f}",Matrix.M[i][j]); + } + printf("\n"); + } + return(status); +} + +/** + \brief Print data from a U_PMF_IE_HUESATURATIONLIGHTNESS object + \return 1 on success, 0 on error + \param contents Record from which to print data + \param blimit one byte past the end of data + EMF+ manual 2.2.3.7, Microsoft name: HueSaturationLightnessEffect Object +*/ +int U_PMF_IE_HUESATURATIONLIGHTNESS_print(const char *contents, const char *blimit){ + int32_t Hue, Saturation, Lightness; + int status = U_PMF_IE_HUESATURATIONLIGHTNESS_get(contents, &Hue, &Saturation, &Lightness, blimit); + if(status){ + printf("HueSaturationLightnessEffect Hue:%d Saturation:%d Lightness:%d\n", Hue, Saturation, Lightness); + } + return(status); +} + +/** + \brief Print data from a U_PMF_IE_LEVELS object + \return 1 on success, 0 on error + \param contents Record from which to print data + \param blimit one byte past the end of data + EMF+ manual 2.2.3.8, Microsoft name: LevelsEffect Object +*/ +int U_PMF_IE_LEVELS_print(const char *contents, const char *blimit){ + int32_t Highlight, Midtone, Shadow; + int status = U_PMF_IE_LEVELS_get(contents, &Highlight, &Midtone, &Shadow, blimit); + if(status){ + printf("LevelEffect Highlight:%d Midtone:%d Shadow:%d\n", Highlight, Midtone, Shadow); + } + return(status); +} + +/** + \brief Print data from a U_PMF_IE_REDEYECORRECTION object + \return 1 on success, 0 on error + \param contents Record from which to print data + \param blimit one byte past the end of data + EMF+ manual 2.2.3.9, Microsoft name: RedEyeCorrectionEffect Object +*/ +int U_PMF_IE_REDEYECORRECTION_print(const char *contents, const char *blimit){ + int32_t Elements; + U_RECTL *Rects; + int status = U_PMF_IE_REDEYECORRECTION_get(contents, &Elements, &Rects, blimit); + if(status){ + printf("RedEyeCorrectionEffect Elements:%u", Elements); + for(; Elements; Elements--, Rects++){ + printf(" "); + rectl_print(*Rects); + } + printf("\n"); + } + return(status); +} + +/** + \brief Print data from a U_PMF_IE_SHARPEN object + \return 1 on success, 0 on error + \param blimit one byte past the end of data + \param contents Record from which to print data + EMF+ manual 2.2.3.10, Microsoft name: SharpenEffect Object +*/ +int U_PMF_IE_SHARPEN_print(const char *contents, const char *blimit){ + U_FLOAT Radius; + int32_t Sharpen; + int status = U_PMF_IE_SHARPEN_get(contents, &Radius, &Sharpen, blimit); + if(status){ + printf("SharpenEffect Radius:%f Sharpen:%u\n", Radius, Sharpen); + } + return(status); +} + +/** + \brief Print data from a U_PMF_IE_TINT object + \return 1 on success, 0 on error + \param contents Record from which to print data + \param blimit one byte past the end of data + EMF+ manual 2.2.3.11, Microsoft name: TintEffect Object +*/ +int U_PMF_IE_TINT_print(const char *contents, const char *blimit){ + int32_t Hue, Amount; + int status = U_PMF_IE_TINT_get(contents, &Hue, &Amount, blimit); + if(status){ + printf("TintEffect Hue:%d Amount:%d\n", Hue, Amount); + } + return(status); +} + +/* ***************************************************************************************** */ +/* EMF+ records, the EMF+ record header is printed separately, these print the contents only */ +/* ***************************************************************************************** */ + + +/** + \brief Print data from a U_PMR_OFFSETCLIP record + \return size of record in bytes on success, 0 on error + \param contents Record from which to print data + EMF+ manual 2.3.1.1, Microsoft name: EmfPlusOffsetClip Record, Index 0x35 +*/ +int U_PMR_OFFSETCLIP_print(const char *contents){ + U_PMF_CMN_HDR Header; + U_FLOAT dX,dY; + int status = U_PMR_OFFSETCLIP_get(contents, &Header, &dX, &dY); + if(status){ + printf(" + dx:%f dy:%f\n",dX,dY); + } + else { + printf(" corrupt record\n"); + } + return(status); +} + +/** + \brief Print data from a U_PMR_OFFSETCLIP record + \return size of record in bytes on success, 0 on error + \param contents Record from which to print data + EMF+ manual 2.3.1.2, Microsoft name: EmfPlusResetClip Record, Index 0x31 +*/ +int U_PMR_RESETCLIP_print(const char *contents){ + return(U_PMR_NODATAREC_print(contents)); +} + +/** + \brief Print data from a U_PMR_SETCLIPPATH record + \return size of record in bytes on success, 0 on error + \param contents Record from which to print data + EMF+ manual 2.3.1.3, Microsoft name: EmfPlusSetClipPath Record, Index 0x33 +*/ +int U_PMR_SETCLIPPATH_print(const char *contents){ + int CMenum; + uint32_t PathID; + int status = U_PMR_SETCLIPPATH_get(contents, NULL, &PathID, &CMenum); + if(status){ + printf(" + PathID:%u CMenum:%d\n",PathID,CMenum); + } + else { + printf(" corrupt record\n"); + } + return(status); +} + +/** + \brief Print data from a U_PMR_SETCLIPRECT record + \return size of record in bytes on success, 0 on error + \param contents Record from which to print data + EMF+ manual 2.3.1.4, Microsoft name: EmfPlusSetClipRect Record, Index 0x32 +*/ +int U_PMR_SETCLIPRECT_print(const char *contents){ + int CMenum; + U_PMF_RECTF Rect; + int status = U_PMR_SETCLIPRECT_get(contents, NULL, &CMenum, &Rect); + if(status){ + printf(" + CMenum:%d(", CMenum); + U_PMF_COMBINEMODEENUMERATION_print(CMenum); + printf(") Rect:"); + U_PMF_RECTF_S_print(&Rect); + printf("\n"); + } + else { + printf(" corrupt record\n"); + } + return(status); +} + +/** + \brief Print data from a U_PMR_SETCLIPREGION record + \return size of record in bytes on success, 0 on error + \param contents Record from which to print data + EMF+ manual 2.3.1.5, Microsoft name: EmfPlusSetClipRegion Record, Index 0x34 +*/ +int U_PMR_SETCLIPREGION_print(const char *contents){ + int CMenum; + uint32_t PathID; + int status = U_PMR_SETCLIPREGION_get(contents, NULL, &PathID, &CMenum); + if(status){ + printf(" + PathID:%u CMenum:%d(",PathID, CMenum); + U_PMF_COMBINEMODEENUMERATION_print(CMenum); + printf(")\n"); + } + else { + printf(" corrupt record\n"); + } + return(status); +} + + +/** + \brief Print data from a U_PMR_COMMENT record + \return size of record in bytes on success, 0 on error + \param contents Record from which to print data + EMF+ manual 2.3.2.1, Microsoft name: EmfPlusComment Record, Index 0x03 +*/ +int U_PMR_COMMENT_print(const char *contents){ + U_PMF_CMN_HDR Header; + const char *Data; + unsigned int i=0; + int status = U_PMR_COMMENT_get(contents, &Header, &Data); + if(status){ + const char *blimit = contents + Header.Size; + if(IS_MEM_UNSAFE(Data, Header.DataSize, blimit)){ + printf(" corrupt record\n"); + return(0); + } + /* try to print it, but only ASCII, bail on anything that is not ASCII */ + printf(" + Data:"); + for(i=0; i< Header.DataSize; i++,Data++){ + if(!*Data)break; + if(*(unsigned const char *)Data <128){ printf("%c",*Data); } + else { break; } + } + printf("\n"); + } + else { + printf(" corrupt record\n"); + } + return(status); +} + +/** + \brief Print data from a U_PMR_ENDOFFILE record + \return size of record in bytes on success, 0 on error + \param contents Record from which to print data + EMF+ manual 2.3.3.1, Microsoft name: EmfPlusEndOfFile Record, Index 0x02 +*/ +int U_PMR_ENDOFFILE_print(const char *contents){ + return(U_PMR_NODATAREC_print(contents)); +} + +/** + \brief Print data from a U_PMR_ENDOFFILE record + \return size of record in bytes on success, 0 on error + \param contents Record from which to print data + EMF+ manual 2.3.3.2, Microsoft name: EmfPlusGetDC Record, Index 0x04 +*/ +int U_PMR_GETDC_print(const char *contents){ + return(U_PMR_NODATAREC_print(contents)); +} + +/** + \brief Print data from a U_PMR_HEADER record + \return size of record in bytes on success, 0 on error + \param contents Record from which to print data + EMF+ manual 2.3.3.3, Microsoft name: EmfPlusHeader Record, Index 0x01 +*/ +int U_PMR_HEADER_print(const char *contents){ + U_PMF_GRAPHICSVERSION Version; + int IsDual, IsVideo; + uint32_t LogicalDpiX, LogicalDpiY; + int status = U_PMR_HEADER_get(contents, NULL, &Version, &IsDual, &IsVideo, &LogicalDpiX, &LogicalDpiY); + if(status){ + /* try to print it, but only ASCII, bail on anything that is not ASCII */ + printf(" + "); + (void) U_PMF_GRAPHICSVERSION_memsafe_print((char *)&Version);; + printf(" IsDual:%c IsVideo:%d LogicalDpiX,y:{%u,%u}\n",(IsDual ? 'Y' : 'N'),IsVideo,LogicalDpiX, LogicalDpiY); + } + else { + printf(" corrupt record\n"); + } + return(status); +} + +/** + \brief Print data from a U_PMR_CLEAR record + \return size of record in bytes on success, 0 on error + \param contents Record from which to print data + EMF+ manual 2.3.4.1, Microsoft name: EmfPlusClear Record, Index 0x09 +*/ +int U_PMR_CLEAR_print(const char *contents){ + U_PMF_ARGB Color; + int status = U_PMR_CLEAR_get(contents, NULL, &Color); + if(status){ + /* try to print it, but only ASCII, bail on anything that is not ASCII */ + printf(" + Color:"); + (void) U_PMF_ARGB_print((char *) &Color); + } + else { + printf(" corrupt record\n"); + } + return(status); +} + +/** + \brief Print data from a U_PMR_DRAWARC record + \return size of record in bytes on success, 0 on error + \param contents Record from which to print data + EMF+ manual 2.3.4.2, Microsoft name: EmfPlusDrawArc Record, Index 0x12 +*/ +int U_PMR_DRAWARC_print(const char *contents){ + uint32_t PenID; + int ctype; + U_FLOAT Start, Sweep; + U_PMF_RECTF Rect; + int status = U_PMR_DRAWARC_get(contents, NULL, &PenID, &ctype, &Start, &Sweep, &Rect); + if(status){ + printf(" + PenID:%u ctype:%d Start:%f Sweep:%f Rect:", PenID,ctype,Start,Sweep); + (void) U_PMF_VARRECTF_S_print(&Rect, 1); + printf("\n"); + } + else { + printf(" corrupt record\n"); + } + return(status); +} + +/** + \brief Print data from a U_PMR_DRAWBEZIERS record + \return size of record in bytes on success, 0 on error + \param contents Record from which to print data + EMF+ manual 2.3.4.3, Microsoft name: EmfPlusDrawBeziers Record, Index 0x19 +*/ +int U_PMR_DRAWBEZIERS_print(const char *contents){ + uint32_t PenID; + int ctype, RelAbs; + uint32_t Elements; + U_PMF_POINTF *Points; + int status = U_PMR_DRAWBEZIERS_get(contents, NULL, &PenID, &ctype, &RelAbs, &Elements, &Points); + if(status){ + printf(" + PenIdx:%u ctype:%d RelAbs:%d Elements:%u\n", PenID, ctype, RelAbs, Elements); + U_PMF_VARPOINTF_S_print(Points, Elements); + free(Points); + } + else { + printf(" corrupt record\n"); + } + return(status); +} + +/** + \brief Print data from a U_PMR_DRAWCLOSEDCURVE record + \return size of record in bytes on success, 0 on error + \param contents Record from which to print data + + Curve is a cardinal spline. + References sent by MS support: + http://alvyray.com/Memos/CG/Pixar/spline77.pdf + http://msdn.microsoft.com/en-us/library/4cf6we5y(v=vs.110).aspx + + EMF+ manual 2.3.4.4, Microsoft name: EmfPlusDrawClosedCurve Record, Index 0x17 +*/ +int U_PMR_DRAWCLOSEDCURVE_print(const char *contents){ + uint32_t PenID; + int ctype, RelAbs; + U_FLOAT Tension; + uint32_t Elements; + U_PMF_POINTF *Points; + int status = U_PMR_DRAWCLOSEDCURVE_get(contents, NULL, &PenID, &ctype, &RelAbs, &Tension, &Elements, &Points); + if(status){ + printf(" + PenID:%u ctype:%d RelAbs:%d Tension:%f\n", PenID, ctype, RelAbs, Tension); + U_PMF_VARPOINTF_S_print(Points, Elements); + free(Points); + } + else { + printf(" corrupt record\n"); + } + return(status); +} + +/** + \brief Print data from a U_PMR_DRAWCURVE record + \return size of record in bytes on success, 0 on error + \param contents Record from which to print data + + Curve is a cardinal spline, using doubled terminator points to generate curves for the terminal segments. + References sent by MS support: + http://alvyray.com/Memos/CG/Pixar/spline77.pdf + http://msdn.microsoft.com/en-us/library/4cf6we5y(v=vs.110).aspx + + EMF+ manual 2.3.4.5, Microsoft name: EmfPlusDrawCurve Record, Index 0x18 +*/ +int U_PMR_DRAWCURVE_print(const char *contents){ + uint32_t PenID; + int ctype; + U_FLOAT Tension; + uint32_t Offset, NSegs, Elements; + U_PMF_POINTF *Points; + int status = U_PMR_DRAWCURVE_get(contents, NULL, &PenID, &ctype, &Tension, &Offset, &NSegs, &Elements, &Points); + if(status){ + printf(" + PenID:%u ctype:%d Tension:%f Offset:%u NSegs:%u Elements:%u\n", PenID, ctype, Tension, Offset, NSegs, Elements); + U_PMF_VARPOINTF_S_print(Points, Elements); + free(Points); + } + else { + printf(" corrupt record\n"); + } + return(status); +} + +/** + \brief Print data from a U_PMR_DRAWDRIVERSTRING record + \return size of record in bytes on success, 0 on error + \param contents Record from which to print data + EMF+ manual 2.3.4.6, Microsoft name: EmfPlusDrawDriverString Record, Index 0x36 +*/ +int U_PMR_DRAWDRIVERSTRING_print(const char *contents){ + unsigned int i; + uint32_t FontID; + int btype; + uint32_t BrushID, DSOFlags, HasMatrix, Elements; + uint16_t *Glyphs; + uint16_t *GlyphsIter; + U_PMF_POINTF *Points; + U_PMF_TRANSFORMMATRIX *Matrix; + int status = U_PMR_DRAWDRIVERSTRING_get(contents, NULL, &FontID, &btype, + &BrushID, &DSOFlags, &HasMatrix, &Elements,&Glyphs, &Points, &Matrix); + if(status){ + printf(" + FontID:%u btype:%d BrushID:%u DSOFlags:%X Elements:%u\n", FontID,btype, BrushID, DSOFlags, Elements); + + printf(" + Glyphs:"); + if(*Glyphs){ + for(GlyphsIter=Glyphs, i=0; i<Elements;i++, GlyphsIter++){ printf(" %u",*GlyphsIter); } + free(Glyphs); + } + else { + printf("(none)"); + } + printf("\n"); + + printf(" + Positions:\n"); + if(Points){ + U_PMF_VARPOINTF_S_print(Points, Elements); + free(Points); + } + else { + printf("(none)\n"); + } + + if(Matrix){ + printf(" + "); + U_PMF_TRANSFORMMATRIX2_print(Matrix); + free(Matrix); + printf("\n"); + } + } + else { + printf(" corrupt record\n"); + } + return(status); +} + +/** + \brief Print data from a U_PMR_DRAWELLIPSE record + \return size of record in bytes on success, 0 on error + \param contents Record from which to print data + EMF+ manual 2.3.4.7, Microsoft name: EmfPlusDrawEllipse Record, Index 0x0F +*/ +int U_PMR_DRAWELLIPSE_print(const char *contents){ + uint32_t PenID; + int ctype; + U_PMF_RECTF Rect; + int status = U_PMR_DRAWELLIPSE_get(contents, NULL, &PenID, &ctype, &Rect); + if(status){ + printf(" + PenID:%u ctype:%d", PenID,ctype); + (void) U_PMF_VARRECTF_S_print(&Rect, 1); + printf("\n"); + } + else { + printf(" corrupt record\n"); + } + return(status); +} + +/** + \brief Print data from a U_PMR_DRAWIMAGE record + \return size of record in bytes on success, 0 on error + \param contents Record from which to print data + EMF+ manual 2.3.4.8, Microsoft name: EmfPlusDrawImage Record, Index 0x1A +*/ +int U_PMR_DRAWIMAGE_print(const char *contents){ + uint32_t ImgID, ImgAttrID; + int ctype; + int32_t SrcUnit; + U_PMF_RECTF SrcRect; + U_PMF_RECTF DstRect; + int status = U_PMR_DRAWIMAGE_get(contents, NULL, &ImgID, &ctype, &ImgAttrID, &SrcUnit, &SrcRect, &DstRect); + if(status){ + printf(" + ImgID:%u ctype:%d ImgAttrID:%u SrcUnit:%d SrcRect:", ImgID, ctype, ImgAttrID, SrcUnit); + (void) U_PMF_RECTF_S_print(&SrcRect); + printf(" DstRect:"); + (void) U_PMF_RECTF_S_print(&DstRect); + printf("\n"); + } + else { + printf(" corrupt record\n"); + } + return(status); +} + +/** + \brief Print data from a U_PMR_DRAWIMAGEPOINTS record + \return size of record in bytes on success, 0 on error + \param contents Record from which to print data + EMF+ manual 2.3.4.9, Microsoft name: EmfPlusDrawImagePoints Record, Index 0x1B +*/ +int U_PMR_DRAWIMAGEPOINTS_print(const char *contents){ + uint32_t ImgID, ImgAttrID; + int ctype, etype, RelAbs; + int32_t SrcUnit; + U_PMF_RECTF SrcRect; + uint32_t Elements; + U_PMF_POINTF *Points; + int status = U_PMR_DRAWIMAGEPOINTS_get(contents, NULL, &ImgID, &ctype, &etype, &RelAbs, + &ImgAttrID, &SrcUnit, &SrcRect, &Elements, &Points); + if(status){ + printf(" + ImgID:%u ctype:%d etype:%d ImgAttrID:%u SrcUnit:%d Elements:%u SrcRect:", + ImgID, ctype, etype, ImgAttrID, SrcUnit, Elements); + (void) U_PMF_RECTF_S_print(&SrcRect); + printf("\n"); + U_PMF_VARPOINTF_S_print(Points, Elements); + free(Points); + } + else { + printf(" corrupt record\n"); + } + return(status); +} + + +/** + \brief Print data from a U_PMR_DRAWLINES record + \return size of record in bytes on success, 0 on error + \param contents Record from which to print data + EMF+ manual 2.3.4.10, Microsoft name: EmfPlusDrawLines Record, Index 0x0D +*/ +int U_PMR_DRAWLINES_print(const char *contents){ + uint32_t PenIdx; + int ctype, dtype, RelAbs; + uint32_t Elements; + U_PMF_POINTF *Points; + int status = U_PMR_DRAWLINES_get(contents, NULL, &PenIdx, &ctype, &dtype, &RelAbs, &Elements, &Points); + if(status){ + printf(" + PenIdx:%d ctype:%d dtype:%d RelAbs:%d\n", PenIdx,ctype,dtype,RelAbs); + U_PMF_VARPOINTF_S_print(Points, Elements); + free(Points); + } + else { + printf(" corrupt record\n"); + } + return(status); +} + +/** + \brief Print data from a U_PMR_DRAWPATH record + \return size of record in bytes on success, 0 on error + \param contents Record from which to print data + EMF+ manual 2.3.4.11, Microsoft name: EmfPlusDrawPath Record, Index 0x15 +*/ +int U_PMR_DRAWPATH_print(const char *contents){ + uint32_t PathIdx, PenIdx; + int status = U_PMR_DRAWPATH_get(contents, NULL, &PathIdx, &PenIdx); + if(status){ + printf(" + PathIdx:%d PenIdx:%d\n", PathIdx, PenIdx); + } + else { + printf(" corrupt record\n"); + } + return(status); +} + +/** + \brief Print data from a U_PMR_DRAWPIE record + \return size of record in bytes on success, 0 on error + \param contents Record from which to print data + EMF+ manual 2.3.4.12, Microsoft name: EmfPlusDrawPie Record, Index 0x0D +*/ +int U_PMR_DRAWPIE_print(const char *contents){ + uint32_t PenID; + int ctype; + U_FLOAT Start, Sweep; + U_PMF_RECTF Rect; + int status = U_PMR_DRAWPIE_get(contents, NULL, &PenID, &ctype, &Start, &Sweep, &Rect); + if(status){ + printf(" + PenID:%u ctype:%d Start:%f Sweep:%f Rect:", PenID,ctype,Start,Sweep); + (void) U_PMF_VARRECTF_S_print(&Rect, 1); + printf("\n"); + } + else { + printf(" corrupt record\n"); + } + return(status); +} + +/** + \brief Print data from a U_PMR_DRAWRECTS record + \return size of record in bytes on success, 0 on error + \param contents Record from which to print data + EMF+ manual 2.3.4.13, Microsoft name: EmfPlusDrawRects Record, Index 0x0B +*/ +int U_PMR_DRAWRECTS_print(const char *contents){ + uint32_t PenID; + int ctype; + uint32_t Elements; + U_PMF_RECTF *Rects=NULL; + U_PMF_CMN_HDR hdr; + int status = U_PMR_DRAWRECTS_get(contents, &hdr, &PenID, &ctype, &Elements, &Rects); + if(status){ + printf(" + PenID:%u ctype:%d Elements:%u Rect:", PenID,ctype,Elements); + (void) U_PMF_VARRECTF_S_print(Rects, Elements); + printf("\n"); + } + else { + printf(" corrupt record\n"); + } + if(Rects)free(Rects); + return(status); +} + +/** + \brief Print data from a U_PMR_DRAWSTRING record + \return size of record in bytes on success, 0 on error + \param contents Record from which to print data + EMF+ manual 2.3.4.14, Microsoft name: EmfPlusDrawString Record, Index 0x1C +*/ +int U_PMR_DRAWSTRING_print(const char *contents){ + char *String8=NULL; + uint32_t FontID, BrushID, FormatID, Length; + int btype; + U_PMF_RECTF Rect; + uint16_t *String16; + int status = U_PMR_DRAWSTRING_get(contents, NULL, &FontID, &btype, + &BrushID, &FormatID, &Length, &Rect, &String16); + if(status){ + printf(" + FontID:%u StringFormatID:%u btype:%d Length:%u Rect:", FontID, FormatID, btype, Length); + (void) U_PMF_RECTF_S_print(&Rect); + (void) U_PMF_VARBRUSHID_print(btype, BrushID); + if(String16){ + String8 = U_Utf16leToUtf8(String16, Length, NULL); + free(String16); + if(String8){ + printf(" String(as_UTF8):<%s>\n",String8); + free(String8); + } + } + else { + printf(" String(as_UTF8):(none)\n"); + } + } + else { + printf(" corrupt record\n"); + } + return(status); +} + +/** + \brief Print data from a U_PMR_FILLCLOSEDCURVE record + \return size of record in bytes on success, 0 on error + \param contents Record from which to print data + EMF+ manual 2.3.4.15, Microsoft name: EmfPlusFillClosedCurve Record, Index 0x16 +*/ +int U_PMR_FILLCLOSEDCURVE_print(const char *contents){ + uint32_t BrushID; + int btype, ctype, ftype, RelAbs; + U_FLOAT Tension; + uint32_t Elements; + U_PMF_POINTF *Points; + int status = U_PMR_FILLCLOSEDCURVE_get(contents, NULL, &btype, &ctype, &ftype, &RelAbs, + &BrushID, &Tension, &Elements, &Points); + if(status){ + printf(" + btype:%d ctype:%d ftype:%d RelAbs:%d Elements:%u", + btype, ctype, ftype, RelAbs, Elements); + (void) U_PMF_VARBRUSHID_print(btype, BrushID); + printf("\n"); + U_PMF_VARPOINTF_S_print(Points, Elements); + free(Points); + } + else { + printf(" corrupt record\n"); + } + return(status); +} + + +/** + \brief Print data from a U_PMR_FILLELLIPSE record + \return size of record in bytes on success, 0 on error + \param contents Record from which to print data + EMF+ manual 2.3.4.16, Microsoft name: EmfPlusFillEllipse Record, Index 0x0E +*/ +int U_PMR_FILLELLIPSE_print(const char *contents){ + int btype, ctype; + uint32_t BrushID; + U_PMF_RECTF Rect; + int status = U_PMR_FILLELLIPSE_get(contents, NULL, &btype, &ctype, &BrushID, &Rect); + if(status){ + printf(" + btype:%d ctype:%d",btype,ctype); + (void) U_PMF_VARBRUSHID_print(btype, BrushID); + (void) U_PMF_VARRECTF_S_print(&Rect, 1); + printf("\n"); + } + else { + printf(" corrupt record\n"); + } + return(status); +} + +/** + \brief Print data from a U_PMR_FILLPATH record + \return size of record in bytes on success, 0 on error + \param contents Record from which to print data + EMF+ manual 2.3.4.17, Microsoft name: EmfPlusFillPath Record, Index 0x14 +*/ +int U_PMR_FILLPATH_print(const char *contents){ + int btype; + uint32_t PathID, BrushID; + int status = U_PMR_FILLPATH_get(contents, NULL, &PathID, &btype, &BrushID); + if(status){ + printf(" + PathID:%u btype:%d",PathID, btype); + (void) U_PMF_VARBRUSHID_print(btype, BrushID); + printf("\n"); + } + else { + printf(" corrupt record\n"); + } + return(status); +} + +/** + \brief Print data from a U_PMR_FILLPIE record + \return size of record in bytes on success, 0 on error + \param contents Record from which to print data + EMF+ manual 2.3.4.18, Microsoft name: EmfPlusFillPie Record, Index 0x10 +*/ +int U_PMR_FILLPIE_print(const char *contents){ + int btype, ctype; + U_FLOAT Start, Sweep; + uint32_t BrushID; + U_PMF_RECTF Rect; + int status = U_PMR_FILLPIE_get(contents, NULL, &btype, &ctype, &BrushID, &Start, &Sweep, &Rect); + if(status){ + printf(" + btype:%d ctype:%d",btype,ctype); + (void) U_PMF_VARBRUSHID_print(btype, BrushID); + (void) U_PMF_VARRECTF_S_print(&Rect, 1); + printf("\n"); + } + else { + printf(" corrupt record\n"); + } + return(status); +} + +/** + \brief Print data from a U_PMR_FILLPOLYGON record + \return size of record in bytes on success, 0 on error + \param contents Record from which to print data + EMF+ manual 2.3.4.19, Microsoft name: EmfPlusFillPolygon Record, Index 0x0C +*/ +int U_PMR_FILLPOLYGON_print(const char *contents){ + int btype, ctype, RelAbs; + uint32_t BrushID, Elements; + U_PMF_POINTF *Points; + int status = U_PMR_FILLPOLYGON_get(contents, NULL, &btype, &ctype, &RelAbs, &BrushID, &Elements, &Points); + if(status){ + printf(" + btype:%d ctype:%d RelAbs:%d Elements:%u",btype,ctype,RelAbs,Elements); + (void) U_PMF_VARBRUSHID_print(btype, BrushID); + printf("\n"); + U_PMF_VARPOINTF_S_print(Points, Elements); + free(Points); + } + else { + printf(" corrupt record\n"); + } + return(status); +} + +/** + \brief Print data from a U_PMR_FILLRECTS record + \return size of record in bytes on success, 0 on error + \param contents Record from which to print data + EMF+ manual 2.3.4.20, Microsoft name: EmfPlusFillRects Record, Index 0x0A +*/ +int U_PMR_FILLRECTS_print(const char *contents){ + int btype, ctype; + uint32_t BrushID, Elements; + U_PMF_RECTF *Rects; + U_PMF_CMN_HDR hdr; + int status = U_PMR_FILLRECTS_get(contents, &hdr, &btype,&ctype, &BrushID, &Elements, &Rects); + if(status){ + printf(" + btype:%d ctype:%d Elements:%u",btype,ctype,Elements); + (void) U_PMF_VARBRUSHID_print(btype, BrushID); + (void) U_PMF_VARRECTF_S_print(Rects, Elements); + free(Rects); + printf("\n"); + } + else { + printf(" corrupt record\n"); + } + return(status); +} + +/** + \brief Print data from a U_PMR_FILLREGION record + \return size of record in bytes on success, 0 on error + \param contents Record from which to print data + EMF+ manual 2.3.4.21, Microsoft name: EmfPlusFillRegion Record, Index 0x13 +*/ +int U_PMR_FILLREGION_print(const char *contents){ + uint32_t RgnID, BrushID; + int btype, ctype; + int status = U_PMR_FILLREGION_get(contents, NULL, &RgnID, &btype, &ctype, &BrushID); + if(status){ + printf(" + RgnID:%u btype:%d ctype:%d", RgnID, btype, ctype); + (void) U_PMF_VARBRUSHID_print(btype, BrushID); + printf("\n"); + } + else { + printf(" corrupt record\n"); + } + return(status); +} + +/** + \brief Print data from a U_PMR_OBJECT record + \return size of record in bytes on success, 0 on error + \param contents Record from which to print data + \param blimit One byte past the last record in memory. + \param ObjCont Structure that holds accumulated object. + \param term Flag used when an abnormal termination of a series of continuation records is encountered. + EMF+ manual 2.3.5.1, Microsoft name: EmfPlusObject Record, Index 0x13 + + This is the ONLY EMF+ record type which needs an explicit blimit passed in. Since it glues + together multiple records, and calls itself recursively, the initial caller cannot determine + that all of the sizes will be OK from the first record's header. +*/ +int U_PMR_OBJECT_print(const char *contents, const char *blimit, U_OBJ_ACCUM *ObjCont, int term){ + U_PMF_CMN_HDR Header; + uint32_t ObjID; + int otype, ntype; + uint32_t TSize; + const char *Data; + int ttype,status; + +//int k; const char *cptr; for(cptr=contents, k=0; k<608;k++,cptr++){ printf("%3.3d %2.2X\n",k,*(uint8_t*)cptr); }; fflush(stdout); + + /* Continued records are a pain. Each contains the total size of the continued object in the first 4 bytes + of data. When the total hits that then then the record is complete, even though the continuation bit will + still be set on that last record. Check for this and then print the terminated continued series. + */ + + if(term){ /* mode for handling unexpected end of accumulated object */ + if(ObjCont->used == 0)return(0); /* no continued object pending */ + printf(" + START Forced Termination of Accumulating object Bytes:%u ObjID:%u DeclaredType:%d(", + ObjCont->used, ObjCont->Id, ObjCont->Type); + U_PMF_OBJECTTYPEENUMERATION_print(ObjCont->Type); + ttype = ObjCont->Type & 0x3F; + printf(")\n"); + status = 1; + } + else { + status = U_PMR_OBJECT_get(contents, &Header, &ObjID, &otype, &ntype, &TSize, &Data); + /* In a corrupt EMF+ file we might hit a new type of record before all the continuation records + expected have been found. If that happens terminate whatever we have accumulated so far, and then go on + to emit the new (unexpected) record. */ + if(IS_MEM_UNSAFE(contents, Header.Size, blimit))return(0); + if(!status){ + printf(" corrupt record\n"); + return(status); + } + if((ObjCont->used > 0) && (U_OA_append(ObjCont, NULL, 0, otype, ObjID) < 0)){ + U_PMR_OBJECT_print(contents, blimit, ObjCont, 1); + } + printf(" + ObjID:%u ObjType:%d(", ObjID, otype); + U_PMF_OBJECTTYPEENUMERATION_print(otype); + printf(") ntype:%d", ntype); + printf(" ContinueD:%c",( ObjCont->used ? 'Y' : 'N')); + printf(" ContinueB:%c",( ntype ? 'Y' : 'N')); + if(ntype){ + U_OA_append(ObjCont, Data, Header.DataSize - 4, otype, ObjID); // The total byte count is not added to the object + printf(" TotalSize:%u",TSize); + printf(" Accumulated:%u",ObjCont->used); + } + else { + U_OA_append(ObjCont, Data, Header.DataSize, otype, ObjID); // The total byte count is not added to the object + } + printf("\n"); + if(ntype && ObjCont->used < TSize)return(status); + /* preceding terminates any continued series for >= accumulated bytes */ + ttype = otype; + } + if(status){ + blimit = ObjCont->accum + ObjCont->used; /* more restrictive blimit, just to end of object */ + switch(ttype){ + case U_OT_Brush: (void) U_PMF_BRUSH_print(ObjCont->accum, blimit); break; + case U_OT_Pen: (void) U_PMF_PEN_print(ObjCont->accum, blimit); break; + case U_OT_Path: (void) U_PMF_PATH_print(ObjCont->accum, blimit); break; + case U_OT_Region: (void) U_PMF_REGION_print(ObjCont->accum, blimit); break; + case U_OT_Image: (void) U_PMF_IMAGE_print(ObjCont->accum, blimit); break; + case U_OT_Font: (void) U_PMF_FONT_print(ObjCont->accum, blimit); break; + case U_OT_StringFormat: (void) U_PMF_STRINGFORMAT_print(ObjCont->accum, blimit); break; + case U_OT_ImageAttributes: (void) U_PMF_IMAGEATTRIBUTES_print(ObjCont->accum, blimit); break; + case U_OT_CustomLineCap: (void) U_PMF_CUSTOMLINECAP_print(ObjCont->accum,"", blimit); break; + case U_OT_Invalid: + default: + printf("INVALID OBJECT TYPE!!!!\n"); + break; + } + U_OA_clear(ObjCont); + } + if(term)printf(" + END Forced Termination of Accumulating object\n"); + return(status); +} + +/** + \brief Print data from a U_PMR_SERIALIZABLEOBJECT record + \return size of record in bytes on success, 0 on error + \param contents Record from which to print data + EMF+ manual 2.3.5.2, Microsoft name: EmfPlusSerializableObject Record, Index 0x38 +*/ +int U_PMR_SERIALIZABLEOBJECT_print(const char *contents){ + uint8_t GUID[16]; + uint32_t Size; + const char *Data; + char *string=NULL; + int iee; + int status = U_PMR_SERIALIZABLEOBJECT_get(contents, NULL, &GUID[0], &Size, &Data); + if(status){ + string = U_PMF_CURLYGUID_set(&GUID[0]); + if(string){ + printf(" + GUID:%s Size:%u",string,Size); + iee = U_PMF_KNOWNCURLYGUID_set(string); /* overwrites string with short text form */ + printf("\n + Effect:"); + free(string); + switch(iee){ + case U_IEE_Unknown: printf("(undefined)\n"); break; + case U_IEE_BlurEffectGuid: U_PMF_IE_BLUR_print(Data, Data + sizeof(U_PMF_IE_BLUR)); break; + case U_IEE_BrightnessContrastEffectGuid: U_PMF_IE_BRIGHTNESSCONTRAST_print(Data, Data + sizeof(U_PMF_IE_BRIGHTNESSCONTRAST)); break; + case U_IEE_ColorBalanceEffectGuid: U_PMF_IE_COLORBALANCE_print(Data, Data + sizeof(U_PMF_IE_COLORBALANCE)); break; + case U_IEE_ColorCurveEffectGuid: U_PMF_IE_COLORCURVE_print(Data, Data + sizeof(U_PMF_IE_COLORCURVE)); break; + case U_IEE_ColorLookupTableEffectGuid: U_PMF_IE_COLORLOOKUPTABLE_print(Data, Data + sizeof(U_PMF_IE_COLORLOOKUPTABLE)); break; + case U_IEE_ColorMatrixEffectGuid: U_PMF_IE_COLORMATRIX_print(Data, Data + sizeof(U_PMF_IE_COLORMATRIX)); break; + case U_IEE_HueSaturationLightnessEffectGuid: U_PMF_IE_HUESATURATIONLIGHTNESS_print(Data, Data + sizeof(U_PMF_IE_HUESATURATIONLIGHTNESS)); break; + case U_IEE_LevelsEffectGuid: U_PMF_IE_LEVELS_print(Data, Data + sizeof(U_PMF_IE_LEVELS)); break; + case U_IEE_RedEyeCorrectionEffectGuid: U_PMF_IE_REDEYECORRECTION_print(Data, Data + sizeof(U_PMF_IE_REDEYECORRECTION)); break; + case U_IEE_SharpenEffectGuid: U_PMF_IE_SHARPEN_print(Data, Data + sizeof(U_PMF_IE_SHARPEN)); break; + case U_IEE_TintEffectGuid: U_PMF_IE_TINT_print(Data, Data + sizeof(U_PMF_IE_TINT)); break; + } + } + else { + printf(" + GUID:ERROR Size:%u\n",Size); + } + } + else { + printf(" corrupt record\n"); + } + return(status); +} + +/** + \brief Print data from a U_PMR_SETANTIALIASMODE record + \return size of record in bytes on success, 0 on error + \param contents Record from which to print data + EMF+ manual 2.3.6.1, Microsoft name: EmfPlusSetAntiAliasMode Record, Index 0x1E +*/ +int U_PMR_SETANTIALIASMODE_print(const char *contents){ + int SMenum, aatype; + int status = U_PMR_SETANTIALIASMODE_get(contents, NULL, &SMenum, &aatype); + if(status){ + printf(" + SMenum:%d AntiAlias:%c\n",SMenum,(aatype ? 'Y' : 'N')); + } + else { + printf(" corrupt record\n"); + } + return(status); +} + +/** + \brief Print data from a U_PMR_SETCOMPOSITINGMODE record + \return size of record in bytes on success, 0 on error + \param contents Record from which to print data + EMF+ manual 2.3.6.2, Microsoft name: EmfPlusSetCompositingMode Record, Index 0x23 +*/ +int U_PMR_SETCOMPOSITINGMODE_print(const char *contents){ + int CMenum; + int status = U_PMR_SETCOMPOSITINGMODE_get(contents, NULL, &CMenum); + if(status){ + printf(" + CMenum:%d\n",CMenum); + } + else { + printf(" corrupt record\n"); + } + return(status); +} + +/** + \brief Print data from a U_PMR_SETCOMPOSITINGQUALITY record + \return size of record in bytes on success, 0 on error + \param contents Record from which to print data + EMF+ manual 2.3.6.3, Microsoft name: EmfPlusSetCompositingQuality Record, Index 0x24 +*/ +int U_PMR_SETCOMPOSITINGQUALITY_print(const char *contents){ + int CQenum; + int status = U_PMR_SETCOMPOSITINGQUALITY_get(contents, NULL, &CQenum); + if(status){ + printf(" + CQenum:%d\n",CQenum); + } + else { + printf(" corrupt record\n"); + } + return(status); +} + +/** + \brief Print data from a U_PMR_SETINTERPOLATIONMODE record + \return size of record in bytes on success, 0 on error + \param contents Record from which to print data + EMF+ manual 2.3.6.4, Microsoft name: EmfPlusSetInterpolationMode Record, Index 0x21 +*/ +int U_PMR_SETINTERPOLATIONMODE_print(const char *contents){ + int IMenum; + int status = U_PMR_SETINTERPOLATIONMODE_get(contents, NULL, &IMenum); + if(status){ + printf(" + IMenum:%d\n",IMenum); + } + else { + printf(" corrupt record\n"); + } + return(status); +} + +/** + \brief Print data from a U_PMR_SETPIXELOFFSETMODE record + \return size of record in bytes on success, 0 on error + \param contents Record from which to print data + EMF+ manual 2.3.6.5, Microsoft name: EmfPlusSetPixelOffsetMode Record, Index 0x22 +*/ +int U_PMR_SETPIXELOFFSETMODE_print(const char *contents){ + int POMenum; + int status = U_PMR_SETPIXELOFFSETMODE_get(contents, NULL, &POMenum); + if(status){ + printf(" + POMenum:%d\n",POMenum); + } + else { + printf(" corrupt record\n"); + } + return(status); +} + +/** + \brief Print data from a U_PMR_SETRENDERINGORIGIN record + \return size of record in bytes on success, 0 on error + \param contents Record from which to print data + EMF+ manual 2.3.6.6, Microsoft name: EmfPlusSetRenderingOrigin Record, Index 0x1D +*/ +int U_PMR_SETRENDERINGORIGIN_print(const char *contents){ + int32_t X, Y; + int status = U_PMR_SETRENDERINGORIGIN_get(contents, NULL, &X, &Y); + if(status){ + printf(" + X:%d Y:%d\n", X, Y); + } + else { + printf(" corrupt record\n"); + } + return(status); +} + +/** + \brief Print data from a U_PMR_SETTEXTCONTRAST record + \return size of record in bytes on success, 0 on error + \param contents Record from which to print data + EMF+ manual 2.3.6.7, Microsoft name: EmfPlusSetTextContrast Record, Index 0x20 +*/ +int U_PMR_SETTEXTCONTRAST_print(const char *contents){ + int GC; + int status = U_PMR_SETTEXTCONTRAST_get(contents, NULL, &GC); + if(status){ + printf(" + GC:%d\n", GC); + } + else { + printf(" corrupt record\n"); + } + return(status); +} + +/** + \brief Print data from a U_PMR_SETTEXTRENDERINGHINT record + \return size of record in bytes on success, 0 on error + \param contents Record from which to print data + EMF+ manual 2.3.6.8, Microsoft name: EmfPlusSetTextRenderingHint Record, Index 0x1F +*/ +int U_PMR_SETTEXTRENDERINGHINT_print(const char *contents){ + int TRHenum; + int status = U_PMR_SETTEXTRENDERINGHINT_get(contents, NULL, &TRHenum); + if(status){ + printf(" + TRHenum:%d\n",TRHenum); + } + else { + printf(" corrupt record\n"); + } + return(status); +} + +/** + \brief Print data from a U_PMR_BEGINCONTAINER record + \return size of record in bytes on success, 0 on error + \param contents Record from which to print data + EMF+ manual 2.3.7.1, Microsoft name: EmfPlusBeginContainer Record, Index 0x27 +*/ +int U_PMR_BEGINCONTAINER_print(const char *contents){ + int UTenum; + U_PMF_RECTF DstRect, SrcRect; + uint32_t StackID; + int status = U_PMR_BEGINCONTAINER_get(contents, NULL, &UTenum, &DstRect, &SrcRect, &StackID); + if(status){ + printf(" + UTenum:%d",UTenum); + printf(" DstRect:"); (void) U_PMF_RECTF_S_print(&DstRect); + printf(" SrcRect:"); (void) U_PMF_RECTF_S_print(&SrcRect); + printf(" StackID:%u\n", StackID); + } + else { + printf(" corrupt record\n"); + } + return(status); +} + +/** + \brief Print data from a U_PMR_BEGINCONTAINERNOPARAMS record + \return size of record in bytes on success, 0 on error + \param contents Record from which to print data + EMF+ manual 2.3.7.2, Microsoft name: EmfPlusBeginContainerNoParams Record, Index 0x28 +*/ +int U_PMR_BEGINCONTAINERNOPARAMS_print(const char *contents){ + uint32_t StackID; + int status = U_PMR_BEGINCONTAINERNOPARAMS_get(contents, NULL, &StackID); + if(status){ + printf(" + StackID:%u\n", StackID); + } + else { + printf(" corrupt record\n"); + } + return(status); +} + +/** + \brief Print data from a U_PMR_ENDCONTAINER record + \return size of record in bytes on success, 0 on error + \param contents Record from which to print data + EMF+ manual 2.3.7.3, Microsoft name: EmfPlusEndContainer Record, Index 0x29 +*/ +int U_PMR_ENDCONTAINER_print(const char *contents){ + uint32_t StackID; + int status = U_PMR_ENDCONTAINER_get(contents, NULL, &StackID); + if(status){ + printf(" + StackID:%u\n", StackID); + } + else { + printf(" corrupt record\n"); + } + return(status); +} + +/** + \brief Print data from a U_PMR_RESTORE record + \return size of record in bytes on success, 0 on error + \param contents Record from which to print data + EMF+ manual 2.3.7.4, Microsoft name: EmfPlusRestore Record, Index 0x26 +*/ +int U_PMR_RESTORE_print(const char *contents){ + uint32_t StackID; + int status = U_PMR_RESTORE_get(contents, NULL, &StackID); + if(status){ + printf(" + StackID:%u\n", StackID); + } + else { + printf(" corrupt record\n"); + } + return(status); +} + +/** + \brief Print data from a U_PMR_SAVE record + \return size of record in bytes on success, 0 on error + \param contents Record from which to print data + EMF+ manual 2.3.7.5, Microsoft name: EmfPlusSave Record, Index 0x25 +*/ +int U_PMR_SAVE_print(const char *contents){ + uint32_t StackID; + int status = U_PMR_SAVE_get(contents, NULL, &StackID); + if(status){ + printf(" + StackID:%u\n", StackID); + } + else { + printf(" corrupt record\n"); + } + return(status); +} + +/** + \brief Print data from a U_PMR_SETTSCLIP record + \return size of record in bytes on success, 0 on error + \param contents Record from which to print data + EMF+ manual 2.3.8.1, Microsoft name: EmfPlusSetTSClip Record, Index 0x3A +*/ +int U_PMR_SETTSCLIP_print(const char *contents){ + int ctype; + uint32_t Elements; + U_PMF_RECTF *Rects; + int status = U_PMR_SETTSCLIP_get(contents, NULL, &ctype, &Elements, &Rects); + if(status){ + printf(" + ctype:%d Elements:%u",ctype,Elements); + (void) U_PMF_VARRECTF_S_print(Rects, Elements); + free(Rects); + printf("\n"); + } + else { + printf(" corrupt record\n"); + } + return(status); +} + +/** + \brief Print data from a U_PMR_SETTSGRAPHICS record + \return size of record in bytes on success, 0 on error + \param contents Record from which to print data + EMF+ manual 2.3.8.2, Microsoft name: EmfPlusSetTSGraphics Record, Index 0x39 +*/ +int U_PMR_SETTSGRAPHICS_print(const char *contents){ + int vgatype, pptype; + uint8_t AntiAliasMode, TextRenderHint, CompositingMode, CompositingQuality, FilterType, PixelOffset; + int16_t RenderOriginX, RenderOriginY; + uint16_t TextContrast; + U_PMF_TRANSFORMMATRIX WorldToDevice; + const char *Data; + int status = U_PMR_SETTSGRAPHICS_get(contents, NULL, + &vgatype, &pptype, + &AntiAliasMode, &TextRenderHint, &CompositingMode, &CompositingQuality, + &RenderOriginX, &RenderOriginY, &TextContrast, &FilterType, + &PixelOffset, &WorldToDevice, &Data); + if(status){ + const char *blimit = contents + status; + printf(" + vgatype:%d pptype:%u",vgatype,pptype); + printf(" AntiAliasMode:%u TextRenderHint:%u CompositingMode:%u CompositingQuality:%u", + AntiAliasMode, TextRenderHint, CompositingMode, CompositingQuality); + printf(" RenderOriginX:%d RenderOriginY:%d",RenderOriginX, RenderOriginY); + printf(" TextContrast:%u",TextContrast); + printf(" WorldToDevice:"); + U_PMF_TRANSFORMMATRIX2_print(&WorldToDevice); + if(pptype && !U_PMF_PALETTE_print(Data, blimit))return(0); + printf("\n"); + } + else { + printf(" corrupt record\n"); + } + return(status); +} + + +/** + \brief Print data from a U_PMR_MULTIPLYWORLDTRANSFORM record + \return size of record in bytes on success, 0 on error + \param contents Record from which to print data + EMF+ manual 2.3.9.1, Microsoft name: EmfPlusMultiplyWorldTransform Record, Index 0x2C +*/ +int U_PMR_MULTIPLYWORLDTRANSFORM_print(const char *contents){ + int xmtype; + U_PMF_TRANSFORMMATRIX Matrix; + int status = U_PMR_MULTIPLYWORLDTRANSFORM_get(contents, NULL, &xmtype, &Matrix); + if(status){ + printf(" + xmtype:%d Multiply:%s",xmtype,(xmtype ? "Post" : "Pre")); + U_PMF_TRANSFORMMATRIX2_print(&Matrix); + printf("\n"); + } + else { + printf(" corrupt record\n"); + } + return(status); +} + +/** + \brief Print data from a U_PMR_RESETWORLDTRANSFORM record + \return size of record in bytes on success, 0 on error + \param contents Record from which to print data + EMF+ manual 2.3.9.2, Microsoft name: EmfPlusResetWorldTransform Record, Index 0x2B +*/ +int U_PMR_RESETWORLDTRANSFORM_print(const char *contents){ + return(U_PMR_NODATAREC_print(contents)); +} + +/** + \brief Print data from a U_PMR_ROTATEWORLDTRANSFORM record + \return size of record in bytes on success, 0 on error + \param contents Record from which to print data + EMF+ manual 2.3.9.3, Microsoft name: EmfPlusRotateWorldTransform Record, Index 0x2F +*/ +int U_PMR_ROTATEWORLDTRANSFORM_print(const char *contents){ + int xmtype; + U_FLOAT Angle; + int status = U_PMR_ROTATEWORLDTRANSFORM_get(contents, NULL, &xmtype, &Angle); + if(status){ + printf(" + xmtype:%d Multiply:%s Angle:%f\n",xmtype,(xmtype ? "Post" : "Pre"), Angle); + } + else { + printf(" corrupt record\n"); + } + return(status); +} + +/** + \brief Print data from a U_PMR_SCALEWORLDTRANSFORM record + \return size of record in bytes on success, 0 on error + \param contents Record from which to print data + EMF+ manual 2.3.9.4, Microsoft name: EmfPlusScaleWorldTransform Record, Index 0x2E +*/ +int U_PMR_SCALEWORLDTRANSFORM_print(const char *contents){ + int xmtype; + U_FLOAT Sx, Sy; + int status = U_PMR_SCALEWORLDTRANSFORM_get(contents, NULL, &xmtype, &Sx, &Sy); + if(status){ + printf(" + xmtype:%d Multiply:%s ScaleX:%f ScaleY:%f\n",xmtype,(xmtype ? "Post" : "Pre"), Sx, Sy); + } + else { + printf(" corrupt record\n"); + } + return(status); +} + +/** + \brief Print data from a U_PMR_SETPAGETRANSFORM record + \return size of record in bytes on success, 0 on error + \param contents Record from which to print data + EMF+ manual 2.3.9.5, Microsoft name: EmfPlusSetPageTransform Record, Index 0x30 +*/ +int U_PMR_SETPAGETRANSFORM_print(const char *contents){ + int UTenum; + U_FLOAT Scale; + int status = U_PMR_SETPAGETRANSFORM_get(contents, NULL, &UTenum, &Scale); + if(status){ + printf(" + UTenum:%d Scale:%f\n",UTenum, Scale); + } + else { + printf(" corrupt record\n"); + } + return(status); +} + +/** + \brief Print data from a U_PMR_SETWORLDTRANSFORM record + \return size of record in bytes on success, 0 on error + \param contents Record from which to print data + EMF+ manual 2.3.9.6, Microsoft name: EmfPlusSetWorldTransform Record, Index 0x2A +*/ +int U_PMR_SETWORLDTRANSFORM_print(const char *contents){ + U_PMF_TRANSFORMMATRIX Matrix; + int status = U_PMR_SETWORLDTRANSFORM_get(contents, NULL, &Matrix); + if(status){ + printf(" + "); + U_PMF_TRANSFORMMATRIX2_print(&Matrix); + printf("\n"); + } + else { + printf(" corrupt record\n"); + } + return(status); +} + +/** + \brief Print data from a U_PMR_TRANSLATEWORLDTRANSFORM record + \return size of record in bytes on success, 0 on error + \param contents Record from which to print data + EMF+ manual 2.3.9.7, Microsoft name: EmfPlusTranslateWorldTransform Record, Index 0x2D +*/ +int U_PMR_TRANSLATEWORLDTRANSFORM_print(const char *contents){ + int xmtype; + U_FLOAT Dx, Dy; + int status = U_PMR_TRANSLATEWORLDTRANSFORM_get(contents, NULL, &xmtype, &Dx, &Dy); + if(status){ + printf(" + xmtype:%d Multiply:%s TranslateX:%f TranlateY:%f\n",xmtype,(xmtype ? "Post" : "Pre"), Dx, Dy); + } + else { + printf(" corrupt record\n"); + } + return(status); +} + + +/** + \brief Print data from a U_PMR_STROKEFILLPATH record + \return 1 on success, 0 on error + \param contents Record from which to print data +*/ +int U_PMR_STROKEFILLPATH_print(const char *contents){ + return(U_PMR_NODATAREC_print(contents)); +} + +/** + \brief Print data from a U_PMR_MULTIFORMATSTART record + \return 1 on success, 0 on error + \param contents Record from which to print data + EMF+ manual mentioned in 2.1.1.1, reserved, not otherwise documented, Microsoft name: EmfPlusMultiFormatStart Record, Index 0x05 +*/ +int U_PMR_MULTIFORMATSTART_print(const char *contents){ + return(U_PMR_NODATAREC_print(contents)); +} + +/** + \brief Print data from a U_PMR_MULTIFORMATSECTION record + \return 1 on success, 0 on error + \param contents Record from which to print data + EMF+ manual mentioned in 2.1.1.1, reserved, not otherwise documented, Microsoft name: EmfPlusMultiFormatSection Record, Index 0x06 +*/ +int U_PMR_MULTIFORMATSECTION_print(const char *contents){ + return(U_PMR_NODATAREC_print(contents)); +} + +/** + \brief Print data from a U_PMR_MULTIFORMATEND record + \return 1 on success, 0 on error + \param contents Record from which to print data + EMF+ manual mentioned in 2.1.1.1, reserved, not otherwise documented, Microsoft name: EmfPlusMultiFormatEnd Record, Index 0x06 +*/ +int U_PMR_MULTIFORMATEND_print(const char *contents){ + return(U_PMR_NODATAREC_print(contents)); +} + + + +#ifdef __cplusplus +} +#endif diff --git a/src/3rdparty/libuemf/upmf_print.h b/src/3rdparty/libuemf/upmf_print.h new file mode 100644 index 0000000..a253744 --- /dev/null +++ b/src/3rdparty/libuemf/upmf_print.h @@ -0,0 +1,181 @@ +/** + @file upmf_print.h + + @brief Prototypes for functions for printing records from EMF files. +*/ + +/* +File: upmf_print.h +Version: 0.0.5 +Date: 28-APR-2015 +Author: David Mathog, Biology Division, Caltech +email: mathog@caltech.edu +Copyright: 2015 David Mathog and California Institute of Technology (Caltech) +*/ + +#ifndef _UPMF_PRINT_ +#define _UPMF_PRINT_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "upmf.h" /* includes uemf.h */ + +/* prototypes for simple types and enums used in PMR records */ +int U_PMF_CMN_HDR_print(const char *contents, U_PMF_CMN_HDR Header, int precnum, int off); +int U_PMF_UINT8_ARRAY_print(const char *Start, const uint8_t *Array, int Elements, char *End); +int U_PMF_BRUSHTYPEENUMERATION_print(int otype); +int U_PMF_HATCHSTYLEENUMERATION_print(int hstype); +int U_PMF_OBJECTTYPEENUMERATION_print(int otype); +int U_PMF_PATHPOINTTYPE_ENUM_print(int Type); +int U_PMF_PX_FMT_ENUM_print(int pfe); +int U_PMF_NODETYPE_print(int Type); + +/* prototypes for objects used in PMR records */ +int U_PMF_BRUSH_print(const char *contents, const char *blimit); +int U_PMF_CUSTOMLINECAP_print(const char *contents, const char *Which, const char *blimit); +int U_PMF_FONT_print(const char *contents, const char *blimit); +int U_PMF_IMAGE_print(const char *contents, const char *blimit); +int U_PMF_IMAGEATTRIBUTES_print(const char *contents, const char *blimit); +int U_PMF_PATH_print(const char *contents, const char *blimit); +int U_PMF_PEN_print(const char *contents, const char *blimit); +int U_PMF_REGION_print(const char *contents, const char *blimit); +int U_PMF_STRINGFORMAT_print(const char *contents, const char *blimit); +int U_PMF_ARGB_print(const char *contents); +int U_PMF_BITMAP_print(const char *contents, const char *blimit); +int U_PMF_BITMAPDATA_print(const char *contents, const char *blimit); +int U_PMF_BLENDCOLORS_print(const char *contents, const char *blimit); +int U_PMF_BLENDFACTORS_print(const char *contents, const char *type, const char *blimit); +int U_PMF_BOUNDARYPATHDATA_print(const char *contents, const char *blimit); +int U_PMF_BOUNDARYPOINTDATA_print(const char *contents, const char *blimit); +int U_PMF_CHARACTERRANGE_print(const char *contents, const char *blimit); +int U_PMF_COMPOUNDLINEDATA_print(const char *contents, const char *blimit); +int U_PMF_COMPRESSEDIMAGE_print(const char *contents, const char *blimit); +int U_PMF_CUSTOMENDCAPDATA_print(const char *contents, const char *blimit); +int U_PMF_CUSTOMLINECAPARROWDATA_print(const char *contents, const char *blimit); +int U_PMF_CUSTOMLINECAPDATA_print(const char *contents, const char *blimit); +int U_PMF_CUSTOMLINECAPOPTIONALDATA_print(const char *contents, uint32_t Flags, const char *blimit); +int U_PMF_CUSTOMSTARTCAPDATA_print(const char *contents, const char *blimit); +int U_PMF_DASHEDLINEDATA_print(const char *contents, const char *blimit); +int U_PMF_FILLPATHOBJ_print(const char *contents, const char *blimit); +int U_PMF_FOCUSSCALEDATA_print(const char *contents, const char *blimit); +int U_PMF_GRAPHICSVERSION_memsafe_print(const char *contents); +int U_PMF_GRAPHICSVERSION_print(const char *contents, const char *blimit); +int U_PMF_HATCHBRUSHDATA_print(const char *contents, const char *blimit); +int U_PMF_LANGUAGEIDENTIFIER_print(U_PMF_LANGUAGEIDENTIFIER LId); +int U_PMF_LINEARGRADIENTBRUSHDATA_print(const char *contents, const char *blimit); +int U_PMF_LINEARGRADIENTBRUSHOPTIONALDATA_print(const char *contents, int BDFlag, const char *blimit); +int U_PMF_LINEPATH_print(const char *contents, const char *blimit); +int U_PMF_METAFILE_print(const char *contents, const char *blimit); +int U_PMF_PALETTE_print(const char *contents, const char *blimit); +int U_PMF_PATHGRADIENTBRUSHDATA_print(const char *contents, const char *blimit); +int U_PMF_PATHGRADIENTBRUSHOPTIONALDATA_print(const char *contents, int BDFlag, const char *blimit); +int U_PMF_PATHPOINTTYPE_print(const char *contents, const char *blimit); +int U_PMF_PATHPOINTTYPERLE_print(const char *contents, const char *blimit); +int U_PMF_PENDATA_print(const char *contents, const char *blimit); +int U_PMF_PENOPTIONALDATA_print(const char *contents, int Flags, const char *blimit); +int U_PMF_POINT_print(const char **contents, const char *blimit); +int U_PMF_POINTF_print(const char **contents, const char *blimit); +int U_PMF_POINTR_print(const char **contents, U_FLOAT *Xpos, U_FLOAT *Ypos, const char *blimit); +int U_PMF_POINT_S_print(U_PMF_POINT *Point); +int U_PMF_POINTF_S_print(U_PMF_POINTF *Point); +int U_PMF_RECT_print(const char **contents, const char *blimit); +int U_PMF_RECTF_print(const char **contents, const char *blimit); +int U_PMF_RECT_S_print(U_PMF_RECT *Rect); +int U_PMF_RECTF_S_print(U_PMF_RECTF *Rect); +int U_PMF_REGIONNODE_print(const char *contents, int Level, const char *blimit); +int U_PMF_REGIONNODECHILDNODES_print(const char *contents, int Level, const char *blimit); +int U_PMF_REGIONNODEPATH_print(const char *contents, const char *blimit); +int U_PMF_SOLIDBRUSHDATA_print(const char *contents, const char *blimit); +int U_PMF_STRINGFORMATDATA_print(const char *contents, uint32_t TabStopCount, uint32_t RangeCount, const char *blimit); +int U_PMF_TEXTUREBRUSHDATA_print(const char *contents, const char *blimit); +int U_PMF_TEXTUREBRUSHOPTIONALDATA_print(const char *contents, int HasMatrix, int HasImage, const char *blimit); +int U_PMF_TRANSFORMMATRIX_print(const char *contents, const char *blimit); +int U_PMF_TRANSFORMMATRIX2_print(U_PMF_TRANSFORMMATRIX *Matrix); +int U_PMF_ROTMATRIX2_print(U_PMF_ROTMATRIX *Matrix); +int U_PMF_IE_BLUR_print(const char *contents, const char *blimit); +int U_PMF_IE_BRIGHTNESSCONTRAST_print(const char *contents, const char *blimit); +int U_PMF_IE_COLORBALANCE_print(const char *contents, const char *blimit); +int U_PMF_IE_COLORCURVE_print(const char *contents, const char *blimit); +int U_PMF_IE_COLORLOOKUPTABLE_print(const char *contents, const char *blimit); +int U_PMF_IE_COLORMATRIX_print(const char *contents, const char *blimit); +int U_PMF_IE_HUESATURATIONLIGHTNESS_print(const char *contents, const char *blimit); +int U_PMF_IE_LEVELS_print(const char *contents, const char *blimit); +int U_PMF_IE_REDEYECORRECTION_print(const char *contents, const char *blimit); +int U_PMF_IE_SHARPEN_print(const char *contents, const char *blimit); +int U_PMF_IE_TINT_print(const char *contents, const char *blimit); + +/* prototypes for PMR records */ +int U_PMR_OFFSETCLIP_print(const char *contents); +int U_PMR_RESETCLIP_print(const char *contents); +int U_PMR_SETCLIPPATH_print(const char *contents); +int U_PMR_SETCLIPRECT_print(const char *contents); +int U_PMR_SETCLIPREGION_print(const char *contents); +int U_PMR_COMMENT_print(const char *contents); +int U_PMR_ENDOFFILE_print(const char *contents); +int U_PMR_GETDC_print(const char *contents); +int U_PMR_HEADER_print(const char *contents); +int U_PMR_CLEAR_print(const char *contents); +int U_PMR_DRAWARC_print(const char *contents); +int U_PMR_DRAWBEZIERS_print(const char *contents); +int U_PMR_DRAWCLOSEDCURVE_print(const char *contents); +int U_PMR_DRAWCURVE_print(const char *contents); +int U_PMR_DRAWDRIVERSTRING_print(const char *contents); +int U_PMR_DRAWELLIPSE_print(const char *contents); +int U_PMR_DRAWIMAGE_print(const char *contents); +int U_PMR_DRAWIMAGEPOINTS_print(const char *contents); +int U_PMR_DRAWLINES_print(const char *contents); +int U_PMR_DRAWPATH_print(const char *contents); +int U_PMR_DRAWPIE_print(const char *contents); +int U_PMR_DRAWRECTS_print(const char *contents); +int U_PMR_DRAWSTRING_print(const char *contents); +int U_PMR_FILLCLOSEDCURVE_print(const char *contents); +int U_PMR_FILLELLIPSE_print(const char *contents); +int U_PMR_FILLPATH_print(const char *contents); +int U_PMR_FILLPIE_print(const char *contents); +int U_PMR_FILLPOLYGON_print(const char *contents); +int U_PMR_FILLRECTS_print(const char *contents); +int U_PMR_FILLREGION_print(const char *contents); +int U_PMR_OBJECT_print(const char *contents, const char *blimit, U_OBJ_ACCUM *ObjCont, int term); +int U_PMR_SERIALIZABLEOBJECT_print(const char *contents); +int U_PMR_SETANTIALIASMODE_print(const char *contents); +int U_PMR_SETCOMPOSITINGMODE_print(const char *contents); +int U_PMR_SETCOMPOSITINGQUALITY_print(const char *contents); +int U_PMR_SETINTERPOLATIONMODE_print(const char *contents); +int U_PMR_SETPIXELOFFSETMODE_print(const char *contents); +int U_PMR_SETRENDERINGORIGIN_print(const char *contents); +int U_PMR_SETTEXTCONTRAST_print(const char *contents); +int U_PMR_SETTEXTRENDERINGHINT_print(const char *contents); +int U_PMR_BEGINCONTAINER_print(const char *contents); +int U_PMR_BEGINCONTAINERNOPARAMS_print(const char *contents); +int U_PMR_ENDCONTAINER_print(const char *contents); +int U_PMR_RESTORE_print(const char *contents); +int U_PMR_SAVE_print(const char *contents); +int U_PMR_SETTSCLIP_print(const char *contents); +int U_PMR_SETTSGRAPHICS_print(const char *contents); +int U_PMR_MULTIPLYWORLDTRANSFORM_print(const char *contents); +int U_PMR_RESETWORLDTRANSFORM_print(const char *contents); +int U_PMR_ROTATEWORLDTRANSFORM_print(const char *contents); +int U_PMR_SCALEWORLDTRANSFORM_print(const char *contents); +int U_PMR_SETPAGETRANSFORM_print(const char *contents); +int U_PMR_SETWORLDTRANSFORM_print(const char *contents); +int U_PMR_TRANSLATEWORLDTRANSFORM_print(const char *contents); +int U_PMR_STROKEFILLPATH_print(const char *contents); /* not documented */ +int U_PMR_MULTIFORMATSTART_print(const char *contents); /* last of reserved but not used */ +int U_PMR_MULTIFORMATSECTION_print(const char *contents); /* last of reserved but not used */ +int U_PMR_MULTIFORMATEND_print(const char *contents); /* last of reserved but not used */ + +int U_pmf_onerec_print(const char *contents, const char *blimit, int recnum, int off); + + + + + + + +#ifdef __cplusplus +} +#endif + +#endif /* _UPMF_PRINT_ */ diff --git a/src/3rdparty/libuemf/uwmf.c b/src/3rdparty/libuemf/uwmf.c new file mode 100644 index 0000000..50e4075 --- /dev/null +++ b/src/3rdparty/libuemf/uwmf.c @@ -0,0 +1,7039 @@ +/** + @file uwmf.c + + @brief Functions for manipulating WMF files and structures. + + [U_WMR*]_set all take data and return a pointer to memory holding the constructed record. + If something goes wrong a NULL pointer is returned. + [U_WMR*]_get takes a pointer to memory and returns the length of that record as well + as the values from it (in the provided fields, passed by reference.) + If something goes wrong, a size of 0 is returned. + + The _set material comes first, then all of the _get material. + + Compile with "U_VALGRIND" defined defined to enable code which lets valgrind check each record for + uninitialized data. + + Compile with "SOL8" defined for Solaris 8 or 9 (Sparc). +*/ + +/* +File: uwmf.c +Version: 0.0.17 +Date: 28-MAR-2015 +Author: David Mathog, Biology Division, Caltech +email: mathog@caltech.edu +Copyright: 2014 David Mathog and California Institute of Technology (Caltech) +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdlib.h> +#include <stdio.h> +#include <stddef.h> /* for offsetof() */ +#include <string.h> +#include <iconv.h> +#include <wchar.h> +#include <errno.h> +#include <string.h> +#include <limits.h> // for INT_MAX, INT_MIN +#include <math.h> // for U_ROUND() +#if 0 +#include <windef.h> //Not actually used, looking for collisions +#include <winnt.h> //Not actually used, looking for collisions +#include <wingdi.h> //Not actually used, looking for collisions +#endif +#include "uwmf.h" +#include "uwmf_endian.h" +#include "uemf_safe.h" + +/** + \brief Look up the full numeric type of a WMR record by type. + + \return Full numeric value for this type of WMR record, Returns 0xFFFFFFFF if out of range. + \param idx WMR record type. + +*/ +uint32_t U_wmr_values(int idx){ + int ret; + int U_WMR_VALUES[256]={ + 0x0000, //!< U_WMR_EOF + 0x0201, //!< U_WMR_SETBKCOLOR + 0x0102, //!< U_WMR_SETBKMODE + 0x0103, //!< U_WMR_SETMAPMODE + 0x0104, //!< U_WMR_SETROP2 + 0x0105, //!< U_WMR_SETRELABS + 0x0106, //!< U_WMR_SETPOLYFILLMODE + 0x0107, //!< U_WMR_SETSTRETCHBLTMODE + 0x0108, //!< U_WMR_SETTEXTCHAREXTRA + 0x0209, //!< U_WMR_SETTEXTCOLOR + 0x020A, //!< U_WMR_SETTEXTJUSTIFICATION + 0x020B, //!< U_WMR_SETWINDOWORG + 0x020C, //!< U_WMR_SETWINDOWEXT + 0x020D, //!< U_WMR_SETVIEWPORTORG + 0x020E, //!< U_WMR_SETVIEWPORTEXT + 0x020F, //!< U_WMR_OFFSETWINDOWORG + 0x0410, //!< U_WMR_SCALEWINDOWEXT + 0x0211, //!< U_WMR_OFFSETVIEWPORTORG + 0x0412, //!< U_WMR_SCALEVIEWPORTEXT + 0x0213, //!< U_WMR_LINETO + 0x0214, //!< U_WMR_MOVETO + 0x0415, //!< U_WMR_EXCLUDECLIPRECT + 0x0416, //!< U_WMR_INTERSECTCLIPRECT + 0x0817, //!< U_WMR_ARC + 0x0418, //!< U_WMR_ELLIPSE + 0x0419, //!< U_WMR_FLOODFILL + 0x081A, //!< U_WMR_PIE + 0x041B, //!< U_WMR_RECTANGLE + 0x061C, //!< U_WMR_ROUNDRECT + 0x061D, //!< U_WMR_PATBLT + 0x001E, //!< U_WMR_SAVEDC + 0x041F, //!< U_WMR_SETPIXEL + 0x0220, //!< U_WMR_OFFSETCLIPRGN + 0x0521, //!< U_WMR_TEXTOUT + 0x0922, //!< U_WMR_BITBLT + 0x0B23, //!< U_WMR_STRETCHBLT + 0x0324, //!< U_WMR_POLYGON + 0x0325, //!< U_WMR_POLYLINE + 0x0626, //!< U_WMR_ESCAPE + 0x0127, //!< U_WMR_RESTOREDC + 0x0228, //!< U_WMR_FILLREGION + 0x0429, //!< U_WMR_FRAMEREGION + 0x012A, //!< U_WMR_INVERTREGION + 0x012B, //!< U_WMR_PAINTREGION + 0x012C, //!< U_WMR_SELECTCLIPREGION + 0x012D, //!< U_WMR_SELECTOBJECT + 0x012E, //!< U_WMR_SETTEXTALIGN + 0x062F, //!< U_WMR_DRAWTEXT + 0x0830, //!< U_WMR_CHORD + 0x0231, //!< U_WMR_SETMAPPERFLAGS + 0x0A32, //!< U_WMR_EXTTEXTOUT + 0x0D33, //!< U_WMR_SETDIBTODEV + 0x0234, //!< U_WMR_SELECTPALETTE + 0x0035, //!< U_WMR_REALIZEPALETTE + 0x0436, //!< U_WMR_ANIMATEPALETTE + 0x0037, //!< U_WMR_SETPALENTRIES + 0x0538, //!< U_WMR_POLYPOLYGON + 0x0139, //!< U_WMR_RESIZEPALETTE + 0x003A, //!< U_WMR_3A + 0x003B, //!< U_WMR_3B + 0x003C, //!< U_WMR_3C + 0x003D, //!< U_WMR_3D + 0x003E, //!< U_WMR_3E + 0x003F, //!< U_WMR_3F + 0x0940, //!< U_WMR_DIBBITBLT + 0x0B41, //!< U_WMR_DIBSTRETCHBLT + 0x0142, //!< U_WMR_DIBCREATEPATTERNBRUSH + 0x0F43, //!< U_WMR_STRETCHDIB + 0x0044, //!< U_WMR_44 + 0x0045, //!< U_WMR_45 + 0x0046, //!< U_WMR_46 + 0x0047, //!< U_WMR_47 + 0x0548, //!< U_WMR_EXTFLOODFILL + 0x0049, //!< U_WMR_49 + 0x004A, //!< U_WMR_4A + 0x004B, //!< U_WMR_4B + 0x014C, //!< U_WMR_4C + 0x014D, //!< U_WMR_4D + 0x004E, //!< U_WMR_4E + 0x004F, //!< U_WMR_4F + 0x0050, //!< U_WMR_50 + 0x0051, //!< U_WMR_51 + 0x0052, //!< U_WMR_52 + 0x0053, //!< U_WMR_53 + 0x0054, //!< U_WMR_54 + 0x0055, //!< U_WMR_55 + 0x0056, //!< U_WMR_56 + 0x0057, //!< U_WMR_57 + 0x0058, //!< U_WMR_58 + 0x0059, //!< U_WMR_59 + 0x005A, //!< U_WMR_5A + 0x005B, //!< U_WMR_5B + 0x005C, //!< U_WMR_5C + 0x005D, //!< U_WMR_5D + 0x005E, //!< U_WMR_5E + 0x005F, //!< U_WMR_5F + 0x0060, //!< U_WMR_60 + 0x0061, //!< U_WMR_61 + 0x0062, //!< U_WMR_62 + 0x0063, //!< U_WMR_63 + 0x0064, //!< U_WMR_64 + 0x0065, //!< U_WMR_65 + 0x0066, //!< U_WMR_66 + 0x0067, //!< U_WMR_67 + 0x0068, //!< U_WMR_68 + 0x0069, //!< U_WMR_69 + 0x006A, //!< U_WMR_6A + 0x006B, //!< U_WMR_6B + 0x006C, //!< U_WMR_6C + 0x006D, //!< U_WMR_6D + 0x006E, //!< U_WMR_6E + 0x006F, //!< U_WMR_6F + 0x0070, //!< U_WMR_70 + 0x0071, //!< U_WMR_71 + 0x0072, //!< U_WMR_72 + 0x0073, //!< U_WMR_73 + 0x0074, //!< U_WMR_74 + 0x0075, //!< U_WMR_75 + 0x0076, //!< U_WMR_76 + 0x0077, //!< U_WMR_77 + 0x0078, //!< U_WMR_78 + 0x0079, //!< U_WMR_79 + 0x007A, //!< U_WMR_7A + 0x007B, //!< U_WMR_7B + 0x007C, //!< U_WMR_7C + 0x007D, //!< U_WMR_7D + 0x007E, //!< U_WMR_7E + 0x007F, //!< U_WMR_7F + 0x0080, //!< U_WMR_80 + 0x0081, //!< U_WMR_81 + 0x0082, //!< U_WMR_82 + 0x0083, //!< U_WMR_83 + 0x0084, //!< U_WMR_84 + 0x0085, //!< U_WMR_85 + 0x0086, //!< U_WMR_86 + 0x0087, //!< U_WMR_87 + 0x0088, //!< U_WMR_88 + 0x0089, //!< U_WMR_89 + 0x008A, //!< U_WMR_8A + 0x008B, //!< U_WMR_8B + 0x008C, //!< U_WMR_8C + 0x008D, //!< U_WMR_8D + 0x008E, //!< U_WMR_8E + 0x008F, //!< U_WMR_8F + 0x0090, //!< U_WMR_90 + 0x0091, //!< U_WMR_91 + 0x0092, //!< U_WMR_92 + 0x0093, //!< U_WMR_93 + 0x0094, //!< U_WMR_94 + 0x0095, //!< U_WMR_95 + 0x0096, //!< U_WMR_96 + 0x0097, //!< U_WMR_97 + 0x0098, //!< U_WMR_98 + 0x0099, //!< U_WMR_99 + 0x009A, //!< U_WMR_9A + 0x009B, //!< U_WMR_9B + 0x009C, //!< U_WMR_9C + 0x009D, //!< U_WMR_9D + 0x009E, //!< U_WMR_9E + 0x009F, //!< U_WMR_9F + 0x00A0, //!< U_WMR_A0 + 0x00A1, //!< U_WMR_A1 + 0x00A2, //!< U_WMR_A2 + 0x00A3, //!< U_WMR_A3 + 0x00A4, //!< U_WMR_A4 + 0x00A5, //!< U_WMR_A5 + 0x00A6, //!< U_WMR_A6 + 0x00A7, //!< U_WMR_A7 + 0x00A8, //!< U_WMR_A8 + 0x00A9, //!< U_WMR_A9 + 0x00AA, //!< U_WMR_AA + 0x00AB, //!< U_WMR_AB + 0x00AC, //!< U_WMR_AC + 0x00AD, //!< U_WMR_AD + 0x00AE, //!< U_WMR_AE + 0x00AF, //!< U_WMR_AF + 0x00B0, //!< U_WMR_B0 + 0x00B1, //!< U_WMR_B1 + 0x00B2, //!< U_WMR_B2 + 0x00B3, //!< U_WMR_B3 + 0x00B4, //!< U_WMR_B4 + 0x00B5, //!< U_WMR_B5 + 0x00B6, //!< U_WMR_B6 + 0x00B7, //!< U_WMR_B7 + 0x00B8, //!< U_WMR_B8 + 0x00B9, //!< U_WMR_B9 + 0x00BA, //!< U_WMR_BA + 0x00BB, //!< U_WMR_BB + 0x00BC, //!< U_WMR_BC + 0x00BD, //!< U_WMR_BD + 0x00BE, //!< U_WMR_BE + 0x00BF, //!< U_WMR_BF + 0x00C0, //!< U_WMR_C0 + 0x00C1, //!< U_WMR_C1 + 0x00C2, //!< U_WMR_C2 + 0x00C3, //!< U_WMR_C3 + 0x00C4, //!< U_WMR_C4 + 0x00C5, //!< U_WMR_C5 + 0x00C6, //!< U_WMR_C6 + 0x00C7, //!< U_WMR_C7 + 0x00C8, //!< U_WMR_C8 + 0x00C9, //!< U_WMR_C9 + 0x00CA, //!< U_WMR_CA + 0x00CB, //!< U_WMR_CB + 0x00CC, //!< U_WMR_CC + 0x00CD, //!< U_WMR_CD + 0x00CE, //!< U_WMR_CE + 0x00CF, //!< U_WMR_CF + 0x00D0, //!< U_WMR_D0 + 0x00D1, //!< U_WMR_D1 + 0x00D2, //!< U_WMR_D2 + 0x00D3, //!< U_WMR_D3 + 0x00D4, //!< U_WMR_D4 + 0x00D5, //!< U_WMR_D5 + 0x00D6, //!< U_WMR_D6 + 0x00D7, //!< U_WMR_D7 + 0x00D8, //!< U_WMR_D8 + 0x00D9, //!< U_WMR_D9 + 0x00DA, //!< U_WMR_DA + 0x00DB, //!< U_WMR_DB + 0x00DC, //!< U_WMR_DC + 0x00DD, //!< U_WMR_DD + 0x00DE, //!< U_WMR_DE + 0x00DF, //!< U_WMR_DF + 0x00E0, //!< U_WMR_E0 + 0x00E1, //!< U_WMR_E1 + 0x00E2, //!< U_WMR_E2 + 0x00E3, //!< U_WMR_E3 + 0x00E4, //!< U_WMR_E4 + 0x00E5, //!< U_WMR_E5 + 0x00E6, //!< U_WMR_E6 + 0x00E7, //!< U_WMR_E7 + 0x00E8, //!< U_WMR_E8 + 0x00E9, //!< U_WMR_E9 + 0x00EA, //!< U_WMR_EA + 0x00EB, //!< U_WMR_EB + 0x00EC, //!< U_WMR_EC + 0x00ED, //!< U_WMR_ED + 0x00EE, //!< U_WMR_EE + 0x00EF, //!< U_WMR_EF + 0x01F0, //!< U_WMR_DELETEOBJECT + 0x00F1, //!< U_WMR_F1 + 0x00F2, //!< U_WMR_F2 + 0x00F3, //!< U_WMR_F3 + 0x00F4, //!< U_WMR_F4 + 0x00F5, //!< U_WMR_F5 + 0x00F6, //!< U_WMR_F6 + 0x00F7, //!< U_WMR_CREATEPALETTE + 0x00F8, //!< U_WMR_CREATEBRUSH + 0x01F9, //!< U_WMR_CREATEPATTERNBRUSH + 0x02FA, //!< U_WMR_CREATEPENINDIRECT + 0x02FB, //!< U_WMR_CREATEFONTINDIRECT + 0x02FC, //!< U_WMR_CREATEBRUSHINDIRECT + 0x02FD, //!< U_WMR_CREATEBITMAPINDIRECT + 0x06FE, //!< U_WMR_CREATEBITMAP + 0x06FF //!< U_WMR_CREATEREGION + }; + if(idx<U_WMR_MIN || idx > U_WMR_MAX){ ret = 0xFFFFFFFF; } + else { ret = U_WMR_VALUES[idx]; } + return(ret); +} + +/** + \brief Look up the name of the WMR record by type. Returns U_WMR_INVALID if out of range. + + \return name of the WMR record, "U_WMR_INVALID" if out of range. + \param idx WMR record type. + +*/ +const char *U_wmr_names(int idx){ + int ret; + static const char *U_WMR_NAMES[257]={ + "U_WMR_EOF", + "U_WMR_SETBKCOLOR", + "U_WMR_SETBKMODE", + "U_WMR_SETMAPMODE", + "U_WMR_SETROP2", + "U_WMR_SETRELABS", + "U_WMR_SETPOLYFILLMODE", + "U_WMR_SETSTRETCHBLTMODE", + "U_WMR_SETTEXTCHAREXTRA", + "U_WMR_SETTEXTCOLOR", + "U_WMR_SETTEXTJUSTIFICATION", + "U_WMR_SETWINDOWORG", + "U_WMR_SETWINDOWEXT", + "U_WMR_SETVIEWPORTORG", + "U_WMR_SETVIEWPORTEXT", + "U_WMR_OFFSETWINDOWORG", + "U_WMR_SCALEWINDOWEXT", + "U_WMR_OFFSETVIEWPORTORG", + "U_WMR_SCALEVIEWPORTEXT", + "U_WMR_LINETO", + "U_WMR_MOVETO", + "U_WMR_EXCLUDECLIPRECT", + "U_WMR_INTERSECTCLIPRECT", + "U_WMR_ARC", + "U_WMR_ELLIPSE", + "U_WMR_FLOODFILL", + "U_WMR_PIE", + "U_WMR_RECTANGLE", + "U_WMR_ROUNDRECT", + "U_WMR_PATBLT", + "U_WMR_SAVEDC", + "U_WMR_SETPIXEL", + "U_WMR_OFFSETCLIPRGN", + "U_WMR_TEXTOUT", + "U_WMR_BITBLT", + "U_WMR_STRETCHBLT", + "U_WMR_POLYGON", + "U_WMR_POLYLINE", + "U_WMR_ESCAPE", + "U_WMR_RESTOREDC", + "U_WMR_FILLREGION", + "U_WMR_FRAMEREGION", + "U_WMR_INVERTREGION", + "U_WMR_PAINTREGION", + "U_WMR_SELECTCLIPREGION", + "U_WMR_SELECTOBJECT", + "U_WMR_SETTEXTALIGN", + "U_WMR_DRAWTEXT", + "U_WMR_CHORD", + "U_WMR_SETMAPPERFLAGS", + "U_WMR_EXTTEXTOUT", + "U_WMR_SETDIBTODEV", + "U_WMR_SELECTPALETTE", + "U_WMR_REALIZEPALETTE", + "U_WMR_ANIMATEPALETTE", + "U_WMR_SETPALENTRIES", + "U_WMR_POLYPOLYGON", + "U_WMR_RESIZEPALETTE", + "U_WMR_3A", + "U_WMR_3B", + "U_WMR_3C", + "U_WMR_3D", + "U_WMR_3E", + "U_WMR_3F", + "U_WMR_DIBBITBLT", + "U_WMR_DIBSTRETCHBLT", + "U_WMR_DIBCREATEPATTERNBRUSH", + "U_WMR_STRETCHDIB", + "U_WMR_44", + "U_WMR_45", + "U_WMR_46", + "U_WMR_47", + "U_WMR_EXTFLOODFILL", + "U_WMR_49", + "U_WMR_4A", + "U_WMR_4B", + "U_WMR_4C", + "U_WMR_4D", + "U_WMR_4E", + "U_WMR_4F", + "U_WMR_50", + "U_WMR_51", + "U_WMR_52", + "U_WMR_53", + "U_WMR_54", + "U_WMR_55", + "U_WMR_56", + "U_WMR_57", + "U_WMR_58", + "U_WMR_59", + "U_WMR_5A", + "U_WMR_5B", + "U_WMR_5C", + "U_WMR_5D", + "U_WMR_5E", + "U_WMR_5F", + "U_WMR_60", + "U_WMR_61", + "U_WMR_62", + "U_WMR_63", + "U_WMR_64", + "U_WMR_65", + "U_WMR_66", + "U_WMR_67", + "U_WMR_68", + "U_WMR_69", + "U_WMR_6A", + "U_WMR_6B", + "U_WMR_6C", + "U_WMR_6D", + "U_WMR_6E", + "U_WMR_6F", + "U_WMR_70", + "U_WMR_71", + "U_WMR_72", + "U_WMR_73", + "U_WMR_74", + "U_WMR_75", + "U_WMR_76", + "U_WMR_77", + "U_WMR_78", + "U_WMR_79", + "U_WMR_7A", + "U_WMR_7B", + "U_WMR_7C", + "U_WMR_7D", + "U_WMR_7E", + "U_WMR_7F", + "U_WMR_80", + "U_WMR_81", + "U_WMR_82", + "U_WMR_83", + "U_WMR_84", + "U_WMR_85", + "U_WMR_86", + "U_WMR_87", + "U_WMR_88", + "U_WMR_89", + "U_WMR_8A", + "U_WMR_8B", + "U_WMR_8C", + "U_WMR_8D", + "U_WMR_8E", + "U_WMR_8F", + "U_WMR_90", + "U_WMR_91", + "U_WMR_92", + "U_WMR_93", + "U_WMR_94", + "U_WMR_95", + "U_WMR_96", + "U_WMR_97", + "U_WMR_98", + "U_WMR_99", + "U_WMR_9A", + "U_WMR_9B", + "U_WMR_9C", + "U_WMR_9D", + "U_WMR_9E", + "U_WMR_9F", + "U_WMR_A0", + "U_WMR_A1", + "U_WMR_A2", + "U_WMR_A3", + "U_WMR_A4", + "U_WMR_A5", + "U_WMR_A6", + "U_WMR_A7", + "U_WMR_A8", + "U_WMR_A9", + "U_WMR_AA", + "U_WMR_AB", + "U_WMR_AC", + "U_WMR_AD", + "U_WMR_AE", + "U_WMR_AF", + "U_WMR_B0", + "U_WMR_B1", + "U_WMR_B2", + "U_WMR_B3", + "U_WMR_B4", + "U_WMR_B5", + "U_WMR_B6", + "U_WMR_B7", + "U_WMR_B8", + "U_WMR_B9", + "U_WMR_BA", + "U_WMR_BB", + "U_WMR_BC", + "U_WMR_BD", + "U_WMR_BE", + "U_WMR_BF", + "U_WMR_C0", + "U_WMR_C1", + "U_WMR_C2", + "U_WMR_C3", + "U_WMR_C4", + "U_WMR_C5", + "U_WMR_C6", + "U_WMR_C7", + "U_WMR_C8", + "U_WMR_C9", + "U_WMR_CA", + "U_WMR_CB", + "U_WMR_CC", + "U_WMR_CD", + "U_WMR_CE", + "U_WMR_CF", + "U_WMR_D0", + "U_WMR_D1", + "U_WMR_D2", + "U_WMR_D3", + "U_WMR_D4", + "U_WMR_D5", + "U_WMR_D6", + "U_WMR_D7", + "U_WMR_D8", + "U_WMR_D9", + "U_WMR_DA", + "U_WMR_DB", + "U_WMR_DC", + "U_WMR_DD", + "U_WMR_DE", + "U_WMR_DF", + "U_WMR_E0", + "U_WMR_E1", + "U_WMR_E2", + "U_WMR_E3", + "U_WMR_E4", + "U_WMR_E5", + "U_WMR_E6", + "U_WMR_E7", + "U_WMR_E8", + "U_WMR_E9", + "U_WMR_EA", + "U_WMR_EB", + "U_WMR_EC", + "U_WMR_ED", + "U_WMR_EE", + "U_WMR_EF", + "U_WMR_DELETEOBJECT", + "U_WMR_F1", + "U_WMR_F2", + "U_WMR_F3", + "U_WMR_F4", + "U_WMR_F5", + "U_WMR_F6", + "U_WMR_CREATEPALETTE", + "U_WMR_CREATEBRUSH", + "U_WMR_CREATEPATTERNBRUSH", + "U_WMR_CREATEPENINDIRECT", + "U_WMR_CREATEFONTINDIRECT", + "U_WMR_CREATEBRUSHINDIRECT", + "U_WMR_CREATEBITMAPINDIRECT", + "U_WMR_CREATEBITMAP", + "U_WMR_CREATEREGION" + }; + if(idx<U_WMR_MIN || idx > U_WMR_MAX){ ret = 256; } + else { ret = idx; } + return(U_WMR_NAMES[ret]); +} + +/** + \brief Text description of Escape record type. + \return name of the WMR record, "UNKNOWN_ESCAPE" if out of range. + \param idx Escape record type. +*/ +const char *U_wmr_escnames(int idx){ + const char *name; + if(idx>=1 && idx <= 0x0023){ + switch(idx){ + case 0x0001: name = "NEWFRAME"; break; + case 0x0002: name = "ABORTDOC"; break; + case 0x0003: name = "NEXTBAND"; break; + case 0x0004: name = "SETCOLORTABLE"; break; + case 0x0005: name = "GETCOLORTABLE"; break; + case 0x0006: name = "FLUSHOUT"; break; + case 0x0007: name = "DRAFTMODE"; break; + case 0x0008: name = "QUERYESCSUPPORT"; break; + case 0x0009: name = "SETABORTPROC"; break; + case 0x000A: name = "STARTDOC"; break; + case 0x000B: name = "ENDDOC"; break; + case 0x000C: name = "GETPHYSPAGESIZE"; break; + case 0x000D: name = "GETPRINTINGOFFSET"; break; + case 0x000E: name = "GETSCALINGFACTOR"; break; + case 0x000F: name = "META_ESCAPE_ENHANCED_METAFILE"; break; + case 0x0010: name = "SETPENWIDTH"; break; + case 0x0011: name = "SETCOPYCOUNT"; break; + case 0x0012: name = "SETPAPERSOURCE"; break; + case 0x0013: name = "PASSTHROUGH"; break; + case 0x0014: name = "GETTECHNOLOGY"; break; + case 0x0015: name = "SETLINECAP"; break; + case 0x0016: name = "SETLINEJOIN"; break; + case 0x0017: name = "SETMITERLIMIT"; break; + case 0x0018: name = "BANDINFO"; break; + case 0x0019: name = "DRAWPATTERNRECT"; break; + case 0x001A: name = "GETVECTORPENSIZE"; break; + case 0x001B: name = "GETVECTORBRUSHSIZE"; break; + case 0x001C: name = "ENABLEDUPLEX"; break; + case 0x001D: name = "GETSETPAPERBINS"; break; + case 0x001E: name = "GETSETPRINTORIENT"; break; + case 0x001F: name = "ENUMPAPERBINS"; break; + case 0x0020: name = "SETDIBSCALING"; break; + case 0x0021: name = "EPSPRINTING"; break; + case 0x0022: name = "ENUMPAPERMETRICS"; break; + case 0x0023: name = "GETSETPAPERMETRICS"; break; + } + } + else if(idx == 0x0025){ name = "POSTSCRIPT_DATA"; } + else if(idx == 0x0026){ name = "POSTSCRIPT_IGNORE"; } + else if(idx == 0x002A){ name = "GETDEVICEUNITS"; } + else if(idx == 0x0100){ name = "GETEXTENDEDTEXTMETRICS"; } + else if(idx == 0x0102){ name = "GETPAIRKERNTABLE"; } + else if(idx == 0x0200){ name = "EXTTEXTOUT"; } + else if(idx == 0x0201){ name = "GETFACENAME"; } + else if(idx == 0x0202){ name = "DOWNLOADFACE"; } + else if(idx == 0x0801){ name = "METAFILE_DRIVER"; } + else if(idx == 0x0C01){ name = "QUERYDIBSUPPORT"; } + else if(idx == 0x1000){ name = "BEGIN_PATH"; } + else if(idx == 0x1001){ name = "CLIP_TO_PATH"; } + else if(idx == 0x1002){ name = "END_PATH"; } + else if(idx == 0x100E){ name = "OPEN_CHANNEL"; } + else if(idx == 0x100F){ name = "DOWNLOADHEADER"; } + else if(idx == 0x1010){ name = "CLOSE_CHANNEL"; } + else if(idx == 0x1013){ name = "POSTSCRIPT_PASSTHROUGH"; } + else if(idx == 0x1014){ name = "ENCAPSULATED_POSTSCRIPT";} + else if(idx == 0x1015){ name = "POSTSCRIPT_IDENTIFY"; } + else if(idx == 0x1016){ name = "POSTSCRIPT_INJECTION"; } + else if(idx == 0x1017){ name = "CHECKJPEGFORMAT"; } + else if(idx == 0x1018){ name = "CHECKPNGFORMAT"; } + else if(idx == 0x1019){ name = "GET_PS_FEATURESETTING"; } + else if(idx == 0x101A){ name = "MXDC_ESCAPE"; } + else if(idx == 0x11D8){ name = "SPCLPASSTHROUGH2"; } + else { name = "UNKNOWN_ESCAPE"; } + return(name); +} + +//! \cond +/* one prototype from uwmf_endian. Put it here because end user should never need to see it, so +not in uemf.h or uwmf_endian.h */ +void U_swap2(void *ul, unsigned int count); + +/** + \brief Check that the bitmap in the specified packed DIB is compatible with the record size + + \return 1 on success, 0 on failure + \param record EMF record that contains a DIB pixel array + \param blimit one byte past the end of the record. + + This method can only test DIBs that hold Microsoft's various bitmap types. PNG or JPG is just a bag + of bytes, and there is no possible way to derive from the known width and height how big it should be. + + This should not be called directly by end user code. +*/ +int packed_DIB_safe( + const char *record, + const char *blimit + ){ + int dibparams = U_BI_UNKNOWN; // type of image not yet determined + const char *px = NULL; // DIB pixels + const U_RGBQUAD *ct = NULL; // DIB color table + int bs; + int usedbytes; + + if(!bitmapinfo_safe(record, blimit))return(0); // this DIB has issues with colors fitting into the record + uint32_t numCt; // these values will be set in get_DIB_params + int32_t width, height, colortype, invert; // these values will be set in get_DIB_params + // next call returns pointers and values, but allocates no memory + dibparams = wget_DIB_params(record, &px, (const U_RGBQUAD **) &ct, &numCt, &width, &height, &colortype, &invert); + // sanity checking + if(numCt && colortype >= U_BCBM_COLOR16)return(0); //color tables not used above 16 bit pixels + if(!numCt && colortype < U_BCBM_COLOR16)return(0); //color tables mandatory for < 16 bit + + if(dibparams ==U_BI_RGB){ + // this is the only DIB type where we can calculate how big it should be when stored in the WMF file + bs = colortype/8; + if(bs<1){ + usedbytes = (width*colortype + 7)/8; // width of line in fully and partially occupied bytes + } + else { + usedbytes = width*bs; + } + if(IS_MEM_UNSAFE(px, usedbytes, blimit))return(0); + } + return(1); +} + +//! \endcond + +/** + \brief Derive from bounding box and start and end arc, for WMF arc, chord, or pie records, the center, start, and end points, and the bounding rectangle. + + \return 0 on success, other values on errors. + \param rclBox16 Bounding box of Arc + \param ArcStart16 Coordinates for Start of Arc + \param ArcEnd16 Coordinates for End of Arc + \param f1 1 if rotation angle >= 180, else 0 + \param f2 Rotation direction, 1 if counter clockwise, else 0 + \param center Center coordinates + \param start Start coordinates (point on the ellipse defined by rect) + \param end End coordinates (point on the ellipse defined by rect) + \param size W,H of the x,y axes of the bounding rectangle. +*/ +int wmr_arc_points( + U_RECT16 rclBox16, + U_POINT16 ArcStart16, + U_POINT16 ArcEnd16, + int *f1, + int f2, + U_PAIRF *center, + U_PAIRF *start, + U_PAIRF *end, + U_PAIRF *size + ){ + U_RECTL rclBox; + U_POINTL ArcStart,ArcEnd; + rclBox.left = rclBox16.left; + rclBox.top = rclBox16.top; + rclBox.right = rclBox16.right; + rclBox.bottom = rclBox16.bottom; + ArcStart.x = ArcStart16.x; + ArcStart.y = ArcStart16.y; + ArcEnd.x = ArcEnd16.x; + ArcEnd.y = ArcEnd16.y; + return emr_arc_points_common(&rclBox, &ArcStart, &ArcEnd, f1, f2, center, start, end, size); +} + +/** + \brief A U_RECT16 may have its values swapped, L<->R and T<->B, this extracts the leftmost as left, and so forth. + \param rc U_RECT156 binary contents of an WMF file + \param left the leftmost of rc.left and rc.right + \param top the topmost of rc.top and rc.bottom + \param right the rightmost of rc.left and rc.right + \param bottom the bottommost of rc.top and rc.bottom +*/ +void U_sanerect16(U_RECT16 rc, double *left, double *top, double *right, double *bottom){ + if(rc.left < rc.right) { *left = rc.left; *right = rc.right; } + else { *left = rc.right; *right = rc.left; } + if(rc.top < rc.bottom){ *top = rc.top; *bottom = rc.bottom; } + else{ *top = rc.bottom; *bottom = rc.top; } +} + +/* ********************************************************************************************** +These definitions are for code pieces that are used many times in the following implementation. These +definitions are not needed in end user code, so they are here rather than in uwmf.h. +*********************************************************************************************** */ + +/** + \brief Get record size in bytes from U_WMR* record, which may not be aligned + \return number of bytes in record. +*/ +uint32_t U_wmr_size(const U_METARECORD *record){ + uint32_t Size16; + memcpy(&Size16,record, 4); + return(2*Size16); +} + +//! \cond should never be called directly +#define SET_CB_FROM_PXBMI(A,B,C,D,E,F) /* A=Px, B=Bmi, C=cbImage, D=cbImage4, E=cbBmi, F=cbPx */ \ + if(A){\ + if(!B)return(NULL); /* size is derived from U_BITMAPINFO, but NOT from its size field, go figure*/ \ + C = F;\ + D = UP4(C); /* pixel array might not be a multiples of 4 bytes*/ \ + E = U_SIZE_BITMAPINFOHEADER + 4 * get_real_color_count((char *)&(B->bmiHeader)); /* bmiheader + colortable*/ \ + }\ + else { C = 0; D = 0; E=0; } +//! \endcond + +/** + \brief Create and return a U_FONT structure. + \return pointer to the created U_FONT structure. + \param Height Height in Logical units + \param Width Average Width in Logical units + \param Escapement Angle in 0.1 degrees betweem escapement vector and X axis + \param Orientation Angle in 0.1 degrees between baseline and X axis + \param Weight LF_Weight Enumeration + \param Italic LF_Italic Enumeration + \param Underline LF_Underline Enumeration + \param StrikeOut LF_StrikeOut Enumeration + \param CharSet LF_CharSet Enumeration + \param OutPrecision LF_OutPrecision Enumeration + \param ClipPrecision LF_ClipPrecision Enumeration + \param Quality LF_Quality Enumeration + \param PitchAndFamily LF_PitchAndFamily Enumeration + \param FaceName Name of font. ANSI Latin1, null terminated. +*/ +U_FONT *U_FONT_set( + int16_t Height, //!< Height in Logical units + int16_t Width, //!< Average Width in Logical units + int16_t Escapement, //!< Angle in 0.1 degrees betweem escapement vector and X axis + int16_t Orientation, //!< Angle in 0.1 degrees between baseline and X axis + int16_t Weight, //!< LF_Weight Enumeration + uint8_t Italic, //!< LF_Italic Enumeration + uint8_t Underline, //!< LF_Underline Enumeration + uint8_t StrikeOut, //!< LF_StrikeOut Enumeration + uint8_t CharSet, //!< LF_CharSet Enumeration + uint8_t OutPrecision, //!< LF_OutPrecision Enumeration + uint8_t ClipPrecision, //!< LF_ClipPrecision Enumeration + uint8_t Quality, //!< LF_Quality Enumeration + uint8_t PitchAndFamily, //!< LF_PitchAndFamily Enumeration + char *FaceName //!< Name of font. ANSI Latin1, null terminated. + ){ + U_FONT *font; + int slen = 1 + strlen(FaceName); /* include terminator */ + if(slen & 1)slen++; /* storage length even */ + font = (U_FONT *) calloc(1,slen + U_SIZE_FONT_CORE); /* use calloc to auto fill in terminating '\0'*/ + if(font){ + font->Height = Height; + font->Width = Width; + font->Escapement = Escapement; + font->Orientation = Orientation; + font->Weight = Weight; + font->Italic = Italic; + font->Underline = Underline; + font->StrikeOut = StrikeOut; + font->CharSet = CharSet; + font->OutPrecision = OutPrecision; + font->ClipPrecision = ClipPrecision; + font->Quality = Quality; + font->PitchAndFamily = PitchAndFamily; + strcpy((char *)&font->FaceName, FaceName); + } + return(font); +} + +/** + \brief Create and return a U_PLTENTRY structure. + \return the created U_PLTENTRY structure. + \param Color Color for the U_PLTENTRY +*/ +U_PLTNTRY U_PLTNTRY_set(U_COLORREF Color){ + U_PLTNTRY pe; + pe.Value = Color.Reserved; + pe.Blue = Color.Blue; + pe.Green = Color.Green; + pe.Red = Color.Red; + return(pe); +} + +/** + \brief Create and return a U_PALETTE structure. + \return pointer to the created U_PALETTE structure. + \param Start Either 0x0300 or an offset into the Palette table + \param NumEntries Number of U_LOGPLTNTRY objects + \param PalEntries Pointer to array of PaletteEntry Objects +*/ +U_PALETTE *U_PLTENTRY_set( + uint16_t Start, //!< Either 0x0300 or an offset into the Palette table + uint16_t NumEntries, //!< Number of U_LOGPLTNTRY objects + U_PLTNTRY *PalEntries //!< Pointer to array of PaletteEntry Objects + ){ + U_PALETTE *Palette = NULL; + if(NumEntries){ + Palette = malloc(4 + 4*NumEntries); + if(Palette){ + Palette->Start = Start; + Palette->NumEntries = NumEntries; + memcpy(&Palette->PalEntries, PalEntries, NumEntries*4); + } + } + return(Palette); +} + +/** + \brief Create and return a U_PEN structure. + \return the created U_PEN structure. + \param Style PenStyle Enumeration + \param Width Width of Pen + \param Color Pen Color. +*/ +U_PEN U_PEN_set( + uint16_t Style, //!< PenStyle Enumeration + uint16_t Width, //!< Width of Pen + U_COLORREF Color //!< Pen Color. + ){ + U_PEN p; + p.Style = Style; + p.Widthw[0] = Width; + p.Widthw[1] = 0; /* ignored */ + p.Color.Red = Color.Red; + p.Color.Green = Color.Green; + p.Color.Blue = Color.Blue; + p.Color.Reserved = Color.Reserved; + return(p); +} + +/** + \brief Create and return a U_RECT16 structure from Upper Left and Lower Right corner points. + \param ul upper left corner of rectangle + \param lr lower right corner of rectangle +*/ +U_RECT16 U_RECT16_set( + U_POINT16 ul, + U_POINT16 lr + ){ + U_RECT16 rect; + rect.left = ul.x; + rect.top = ul.y; + rect.right = lr.x; + rect.bottom = lr.y; + return(rect); +} + +/** + \brief Create and return a U_BITMAP16 structure + \return pointer to the U_BITMAP16 structure, or NULL on failure + \param Type bitmap Type (not described at all in the WMF PDF) + \param Width bitmap width in pixels. + \param Height bitmap height in scan lines. + \param LineN each array line in Bits is a multiple of this (4 for a DIB) + \param BitsPixel number of adjacent color bits on each plane (R bits + G bits + B bits ????) + \param Bits bitmap pixel data. Bytes contained = (((Width * BitsPixel + 15) >> 4) << 1) * Height +*/ +U_BITMAP16 *U_BITMAP16_set( + const int16_t Type, + const int16_t Width, + const int16_t Height, + const int16_t LineN, + const uint8_t BitsPixel, + const char *Bits + ){ + U_BITMAP16 *bm16; + uint32_t irecsize; + int cbBits,iHeight; + int usedbytes; + int16_t WidthBytes; // total bytes per scan line (used and padding). + + usedbytes = (Width * BitsPixel + 7)/8; // width of line in fully and partially occupied bytes + WidthBytes = (LineN * ((usedbytes + (LineN - 1) ) / LineN)); // Account for padding required by line alignment in the pixel array + + iHeight = (Height < 0 ? -Height : Height); /* DIB can use a negative height, but it does not look like a Bitmap16 object can */ + cbBits = WidthBytes * iHeight; + if(!Bits || cbBits<=0)return(NULL); + irecsize = U_SIZE_BITMAP16 + cbBits; + bm16 = (U_BITMAP16 *) malloc(irecsize); + if(bm16){ + bm16->Type = Type; + bm16->Width = Width; + bm16->Height = iHeight; + bm16->WidthBytes = WidthBytes; + bm16->Planes = 1; + bm16->BitsPixel = BitsPixel; + memcpy((char *)bm16 + U_SIZE_BITMAP16,Bits,cbBits); + } + return(bm16); +} + +/** + \brief Create and return a U_SCAN structure + \return U_SCAN structure + \param count Number of entries in the ScanLines array + \param top Y coordinate of the top scanline + \param bottom Y coordinate of the bottom scanline + \param ScanLines Array of 16 bit left/right pairs, array has 2*count entries +*/ +U_SCAN *U_SCAN_set( + uint16_t count, //!< Number of entries in the ScanLines array + uint16_t top, //!< Y coordinate of the top scanline + uint16_t bottom, //!< Y coordinate of the bottom scanline + uint16_t *ScanLines //!< Array of 16 bit left/right pairs, array has 2*count entries + ){ + U_SCAN *scan=NULL; + int size = 6 + count*4; + scan = malloc(size); + if(scan){ + scan->count = count; + scan->top = top; + scan->bottom = bottom; + memcpy(&scan->ScanLines,ScanLines,4*count); + } + return(scan); +} + +/** + \brief Create and return a U_REGION structure + \return pointer to created U_REGION structure or NULL on error + \param Size aScans in bytes + regions size in bytes (size of this header plus all U_SCAN objects?) + \param sCount number of scan objects in region (docs say scanlines, but then no way to add sizes) + \param sMax largest number of points in any scan + \param sRect bounding rectangle + \param aScans series of U_SCAN objects to append. This is also an array of uint16_t, but should be handled as a bunch of U_SCAN objects tightly packed into the buffer. +*/ +U_REGION *U_REGION_set( + int16_t Size, //!< aScans in bytes + regions size in bytes (size of this header plus all U_SCAN objects?) + int16_t sCount, //!< number of scan objects in region (docs say scanlines, but then no way to add sizes) + int16_t sMax, //!< largest number of points in any scan + U_RECT16 sRect, //!< bounding rectangle + uint16_t *aScans //!< series of U_SCAN objects to append. This is also an array of uint16_t, but should be handled as a bunch of U_SCAN objects tightly packed into the buffer. + ){ + U_REGION *region=NULL; + char *psc; + int scansize,i,off; + psc = (char *)aScans; + for(scansize=i=0; i<sCount; i++){ + off = 6 + 4*(((U_SCAN *)psc)->count); + scansize += off; + psc += off; + } + region = malloc(U_SIZE_REGION + scansize); + if(region){ + region->ignore1 = 0; + region->Type = 0x0006; + region->ignore2 = 0; + region->Size = Size; + region->sCount = sCount; + region->sMax = sMax; + region->sRect = sRect; + memcpy(®ion->aScans,aScans,scansize); + } + return(region); +} + + +/** + \brief Create and return a U_WLOGBRUSH structure. + \return the created U_WLOGBRUSH structure. + \param Style BrushStyle Enumeration + \param Color Brush Color value + \param Hatch HatchStyle Enumeration +*/ +U_WLOGBRUSH U_WLOGBRUSH_set( + uint16_t Style, //!< BrushStyle Enumeration + U_COLORREF Color, //!< Brush Color value + uint16_t Hatch //!< HatchStyle Enumeration + ){ + U_WLOGBRUSH lb; + lb.Style = Style; + lb.Color.Red = Color.Red; + lb.Color.Green = Color.Green; + lb.Color.Blue = Color.Blue; + lb.Color.Reserved = Color.Reserved; + lb.Hatch = Hatch; + return(lb); +} + + +/** + \brief Create and return a U_PAIRF structure. + \return pointer to the created U_PAIRF structure. + \param x x value + \param y y value +*/ +U_PAIRF *U_PAIRF_set( + float x, //!< x value + float y //!< y value + ){ + U_PAIRF *pf=malloc(U_SIZE_PAIRF); + if(pf){ + pf->x = x; + pf->y = y; + } + return(pf); +} + +/* ********************************************************************************************** +These functions are used for Image conversions and other +utility operations. Character type conversions are in uwmf_utf.c +*********************************************************************************************** */ + +/** + \brief Calculate the int16_t checksum of the buffer for the number of positions specified. This is XOR of all values. + \return checksum + \param buf array of uint16_t values + \param count number of members in buf + +*/ +int16_t U_16_checksum(int16_t *buf, int count){ + int16_t result=0; + for(;count;count--){ + result ^= *buf++; + } + return(result); +} + +/** + \brief Dump a WMFHANDLES structure. Not for use in production code. + \param string Text to output before dumping eht structure + \param handle Handle + \param wht WMFHANDLES structure to dump +*/ +void dumpwht( + char *string, + unsigned int *handle, + WMFHANDLES *wht + ){ + uint32_t i; + printf("%s\n",string); + printf("lo: %d hi: %d peak: %d\n", wht->lolimit, wht->hilimit, wht->peak); + if(handle){ + printf("handle: %d \n",*handle); + } + for(i=0;i<=5;i++){ + printf("table[%d]: %d\n",i,wht->table[i]); + } +} + +/** + \brief Make up an approximate dx array to pass to U_WMREXTTEXTOUT_set(), based on character height and weight. + + Take abs. value of character height, get width by multiplying by 0.6, and correct weight + approximately, with formula (measured on screen for one text line of Arial). + Caller is responsible for free() on the returned pointer. + + \return pointer to dx array + \param height character height (absolute value will be used) + \param weight LF_Weight Enumeration (character weight) + \param members Number of entries to put into dx + +*/ +int16_t *dx16_set( + int32_t height, + uint32_t weight, + uint32_t members + ){ + uint32_t i, width; + int16_t *dx; + dx = (int16_t *) malloc(members * sizeof(int16_t)); + if(dx){ + if(U_FW_DONTCARE == weight)weight=U_FW_NORMAL; + width = (uint32_t) U_ROUND(((float) (height > 0 ? height : -height)) * 0.6 * (0.00024*(float) weight + 0.904)); + for ( i = 0; i < members; i++ ){ dx[i] = (width > INT16_MAX ? INT16_MAX : width); } + } + return(dx); +} +/** + \brief Look up the properties (a bit map) of a type of WMR record. + Bits that may be set are defined in "Draw Properties" in uemf.h, they are U_DRAW_NOTEMPTY, etc.. + \return bitmap of WMR record properties, or U_WMR_INVALID on error or release of all memory. + \param type WMR record type. If U_WMR_INVALID release memory. (There is no U_WMR_INVALID WMR record type) + +*/ +uint32_t U_wmr_properties(uint32_t type){ + static uint32_t *table=NULL; + uint32_t result = U_WMR_INVALID; // initialized to indicate an error (on a lookup) or nothing (on a memory release) + if(type == U_WMR_INVALID){ + if(table)free(table); + table=NULL; + } + else if(type<=U_WMR_MAX){ // type is uint so always >=0, no need to test U_WMR_MIN, which is 0. + if(!table){ + table = (uint32_t *) malloc(sizeof(uint32_t)*(1 + U_WMR_MAX)); + if(!table)return(result); + // 0x200 0x100 0x80 0x40 0x20 0x10 0x08 0x04 0x02 0x01 + // properties (U_DRAW_*) TEXT ALTERS ONLYTO VISIBLE + // NOFILL OBJECT PATH FORCE CLOSED NOTEMPTY + // Record Type + table[0x00] = 0x0A0; // U_WMREOF 0 0 1 0 1 0 0 0 0 0 Force out any pending draw + table[0x01] = 0x020; // U_WMRSETBKCOLOR 0 0 0 0 1 0 0 0 0 0 + table[0x02] = 0x020; // U_WMRSETBKMODE 0 0 0 0 1 0 0 0 0 0 + table[0x03] = 0x0A0; // U_WMRSETMAPMODE 0 0 1 0 1 0 0 0 0 0 + table[0x04] = 0x0A0; // U_WMRSETROP2 0 0 1 0 1 0 0 0 0 0 + table[0x05] = 0x000; // U_WMRSETRELABS 0 0 0 0 0 0 0 0 0 0 No idea what this is supposed to do + table[0x06] = 0x0A0; // U_WMRSETPOLYFILLMODE 0 0 1 0 1 0 0 0 0 0 + table[0x07] = 0x0A0; // U_WMRSETSTRETCHBLTMODE 0 0 1 0 1 0 0 0 0 0 + table[0x08] = 0x000; // U_WMRSETTEXTCHAREXTRA 0 0 0 0 0 0 0 0 0 0 + table[0x09] = 0x020; // U_WMRSETTEXTCOLOR 0 0 0 0 1 0 0 0 0 0 + table[0x0A] = 0x020; // U_WMRSETTEXTJUSTIFICATION 0 0 0 0 1 0 0 0 0 0 + table[0x0B] = 0x0A0; // U_WMRSETWINDOWORG 0 0 1 0 1 0 0 0 0 0 + table[0x0C] = 0x0A0; // U_WMRSETWINDOWEXT 0 0 1 0 1 0 0 0 0 0 + table[0x0D] = 0x0A0; // U_WMRSETVIEWPORTORG 0 0 1 0 1 0 0 0 0 0 + table[0x0E] = 0x0A0; // U_WMRSETVIEWPORTEXT 0 0 1 0 1 0 0 0 0 0 + table[0x0F] = 0x000; // U_WMROFFSETWINDOWORG 0 0 0 0 0 0 0 0 0 0 + table[0x10] = 0x000; // U_WMRSCALEWINDOWEXT 0 0 0 0 0 0 0 0 0 0 + table[0x11] = 0x0A0; // U_WMROFFSETVIEWPORTORG 0 0 1 0 1 0 0 0 0 0 + table[0x12] = 0x0A0; // U_WMRSCALEVIEWPORTEXT 0 0 1 0 1 0 0 0 0 0 + table[0x13] = 0x28B; // U_WMRLINETO 1 0 1 0 0 0 1 0 1 1 + table[0x14] = 0x289; // U_WMRMOVETO 1 0 1 0 0 0 1 0 0 1 + table[0x15] = 0x0A0; // U_WMREXCLUDECLIPRECT 0 0 1 0 1 0 0 0 0 0 + table[0x16] = 0x0A0; // U_WMRINTERSECTCLIPRECT 0 0 1 0 1 0 0 0 0 0 + table[0x17] = 0x283; // U_WMRARC 1 0 1 0 0 0 0 0 1 1 + table[0x18] = 0x087; // U_WMRELLIPSE 0 0 1 0 0 0 0 1 1 1 + table[0x19] = 0x082; // U_WMRFLOODFILL 0 0 1 0 0 0 0 0 1 0 + table[0x1A] = 0x087; // U_WMRPIE 0 0 1 0 0 0 0 1 1 1 + table[0x1B] = 0x087; // U_WMRRECTANGLE 0 0 1 0 0 0 0 1 1 1 + table[0x1C] = 0x087; // U_WMRROUNDRECT 0 0 1 0 0 0 0 1 1 1 + table[0x1D] = 0x000; // U_WMRPATBLT 0 0 1 0 0 0 0 1 1 1 + table[0x1E] = 0x0A0; // U_WMRSAVEDC 0 0 1 0 1 0 0 0 0 0 + table[0x1F] = 0x082; // U_WMRSETPIXEL 0 0 1 0 0 0 0 0 1 0 + table[0x20] = 0x0A0; // U_WMROFFSETCLIPRGN 0 0 1 0 1 0 0 0 0 0 + table[0x21] = 0x002; // U_WMRTEXTOUT 0 0 0 0 0 0 0 0 1 0 + table[0x22] = 0x082; // U_WMRBITBLT 0 0 1 0 0 0 0 0 1 0 + table[0x23] = 0x082; // U_WMRSTRETCHBLT 0 0 1 0 0 0 0 0 1 0 + table[0x24] = 0x083; // U_WMRPOLYGON 0 0 1 0 0 0 0 0 1 1 + table[0x25] = 0x283; // U_WMRPOLYLINE 1 0 1 0 0 0 0 0 1 1 + table[0x26] = 0x0A0; // U_WMRESCAPE 0 0 1 0 1 0 0 0 0 0 + table[0x27] = 0x0A0; // U_WMRRESTOREDC 0 0 1 0 1 0 0 0 0 0 + table[0x28] = 0x082; // U_WMRFILLREGION 0 0 1 0 0 0 0 0 1 0 + table[0x29] = 0x082; // U_WMRFRAMEREGION 0 0 1 0 0 0 0 0 1 0 + table[0x2A] = 0x082; // U_WMRINVERTREGION 0 0 1 0 0 0 0 0 1 0 + table[0x2B] = 0x082; // U_WMRPAINTREGION 0 0 1 0 0 0 0 0 1 0 + table[0x2C] = 0x0A0; // U_WMRSELECTCLIPREGION 0 0 1 0 1 0 0 0 0 0 + table[0x2D] = 0x020; // U_WMRSELECTOBJECT 0 0 0 0 1 0 0 0 0 0 + table[0x2E] = 0x020; // U_WMRSETTEXTALIGN 0 0 0 0 1 0 0 0 0 0 + table[0x2F] = 0x002; // U_WMRDRAWTEXT 0 0 0 0 0 0 0 0 1 0 no idea what this is supposed to do + table[0x30] = 0x087; // U_WMRCHORD 0 0 1 0 0 0 0 1 1 1 + table[0x31] = 0x0A0; // U_WMRSETMAPPERFLAGS 0 0 1 0 1 0 0 0 0 0 + table[0x32] = 0x002; // U_WMREXTTEXTOUT 0 0 0 0 0 0 0 0 1 0 + table[0x33] = 0x000; // U_WMRSETDIBTODEV 0 0 0 0 0 0 0 0 0 0 + table[0x34] = 0x0A0; // U_WMRSELECTPALETTE 0 0 1 0 1 0 0 0 0 0 + table[0x35] = 0x0A0; // U_WMRREALIZEPALETTE 0 0 1 0 1 0 0 0 0 0 + table[0x36] = 0x0A0; // U_WMRANIMATEPALETTE 0 0 1 0 1 0 0 0 0 0 + table[0x37] = 0x0A0; // U_WMRSETPALENTRIES 0 0 1 0 1 0 0 0 0 0 + table[0x38] = 0x087; // U_WMRPOLYPOLYGON 0 0 1 0 0 0 0 1 1 1 + table[0x39] = 0x0A0; // U_WMRRESIZEPALETTE 0 0 1 0 1 0 0 0 0 0 + table[0x3A] = 0x000; // U_WMR3A 0 0 0 0 0 0 0 0 0 0 + table[0x3B] = 0x000; // U_WMR3B 0 0 0 0 0 0 0 0 0 0 + table[0x3C] = 0x000; // U_WMR3C 0 0 0 0 0 0 0 0 0 0 + table[0x3D] = 0x000; // U_WMR3D 0 0 0 0 0 0 0 0 0 0 + table[0x3E] = 0x000; // U_WMR3E 0 0 0 0 0 0 0 0 0 0 + table[0x3F] = 0x000; // U_WMR3F 0 0 0 0 0 0 0 0 0 0 + table[0x40] = 0x0A0; // U_WMRDIBBITBLT 0 0 1 0 1 0 0 0 0 0 + table[0x41] = 0x0A0; // U_WMRDIBSTRETCHBLT 0 0 1 0 1 0 0 0 0 0 + table[0x42] = 0x080; // U_WMRDIBCREATEPATTERNBRUSH 0 0 1 0 0 0 0 0 0 0 Not selected yet, so no change in drawing conditions + table[0x43] = 0x0A0; // U_WMRSTRETCHDIB 0 0 1 0 1 0 0 0 0 0 + table[0x44] = 0x000; // U_WMR44 0 0 0 0 0 0 0 0 0 0 + table[0x45] = 0x000; // U_WMR45 0 0 0 0 0 0 0 0 0 0 + table[0x46] = 0x000; // U_WMR46 0 0 0 0 0 0 0 0 0 0 + table[0x47] = 0x000; // U_WMR47 0 0 0 0 0 0 0 0 0 0 + table[0x48] = 0x082; // U_WMREXTFLOODFILL 0 0 1 0 0 0 0 0 1 0 + table[0x49] = 0x000; // U_WMR49 0 0 0 0 0 0 0 0 0 0 + table[0x4A] = 0x000; // U_WMR4A 0 0 0 0 0 0 0 0 0 0 + table[0x4B] = 0x000; // U_WMR4B 0 0 0 0 0 0 0 0 0 0 + table[0x4C] = 0x000; // U_WMR4C 0 0 0 0 0 0 0 0 0 0 + table[0x4D] = 0x000; // U_WMR4D 0 0 0 0 0 0 0 0 0 0 + table[0x4E] = 0x000; // U_WMR4E 0 0 0 0 0 0 0 0 0 0 + table[0x4F] = 0x000; // U_WMR4F 0 0 0 0 0 0 0 0 0 0 + table[0x50] = 0x000; // U_WMR50 0 0 0 0 0 0 0 0 0 0 + table[0x51] = 0x000; // U_WMR51 0 0 0 0 0 0 0 0 0 0 + table[0x52] = 0x000; // U_WMR52 0 0 0 0 0 0 0 0 0 0 + table[0x53] = 0x000; // U_WMR53 0 0 0 0 0 0 0 0 0 0 + table[0x54] = 0x000; // U_WMR54 0 0 0 0 0 0 0 0 0 0 + table[0x55] = 0x000; // U_WMR55 0 0 0 0 0 0 0 0 0 0 + table[0x56] = 0x000; // U_WMR56 0 0 0 0 0 0 0 0 0 0 + table[0x57] = 0x000; // U_WMR57 0 0 0 0 0 0 0 0 0 0 + table[0x58] = 0x000; // U_WMR58 0 0 0 0 0 0 0 0 0 0 + table[0x59] = 0x000; // U_WMR59 0 0 0 0 0 0 0 0 0 0 + table[0x5A] = 0x000; // U_WMR5A 0 0 0 0 0 0 0 0 0 0 + table[0x5B] = 0x000; // U_WMR5B 0 0 0 0 0 0 0 0 0 0 + table[0x5C] = 0x000; // U_WMR5C 0 0 0 0 0 0 0 0 0 0 + table[0x5D] = 0x000; // U_WMR5D 0 0 0 0 0 0 0 0 0 0 + table[0x5E] = 0x000; // U_WMR5E 0 0 0 0 0 0 0 0 0 0 + table[0x5F] = 0x000; // U_WMR5F 0 0 0 0 0 0 0 0 0 0 + table[0x60] = 0x000; // U_WMR60 0 0 0 0 0 0 0 0 0 0 + table[0x61] = 0x000; // U_WMR61 0 0 0 0 0 0 0 0 0 0 + table[0x62] = 0x000; // U_WMR62 0 0 0 0 0 0 0 0 0 0 + table[0x63] = 0x000; // U_WMR63 0 0 0 0 0 0 0 0 0 0 + table[0x64] = 0x000; // U_WMR64 0 0 0 0 0 0 0 0 0 0 + table[0x65] = 0x000; // U_WMR65 0 0 0 0 0 0 0 0 0 0 + table[0x66] = 0x000; // U_WMR66 0 0 0 0 0 0 0 0 0 0 + table[0x67] = 0x000; // U_WMR67 0 0 0 0 0 0 0 0 0 0 + table[0x68] = 0x000; // U_WMR68 0 0 0 0 0 0 0 0 0 0 + table[0x69] = 0x000; // U_WMR69 0 0 0 0 0 0 0 0 0 0 + table[0x6A] = 0x000; // U_WMR6A 0 0 0 0 0 0 0 0 0 0 + table[0x6B] = 0x000; // U_WMR6B 0 0 0 0 0 0 0 0 0 0 + table[0x6C] = 0x000; // U_WMR6C 0 0 0 0 0 0 0 0 0 0 + table[0x6D] = 0x000; // U_WMR6D 0 0 0 0 0 0 0 0 0 0 + table[0x6E] = 0x000; // U_WMR6E 0 0 0 0 0 0 0 0 0 0 + table[0x6F] = 0x000; // U_WMR6F 0 0 0 0 0 0 0 0 0 0 + table[0x70] = 0x000; // U_WMR70 0 0 0 0 0 0 0 0 0 0 + table[0x71] = 0x000; // U_WMR71 0 0 0 0 0 0 0 0 0 0 + table[0x72] = 0x000; // U_WMR72 0 0 0 0 0 0 0 0 0 0 + table[0x73] = 0x000; // U_WMR73 0 0 0 0 0 0 0 0 0 0 + table[0x74] = 0x000; // U_WMR74 0 0 0 0 0 0 0 0 0 0 + table[0x75] = 0x000; // U_WMR75 0 0 0 0 0 0 0 0 0 0 + table[0x76] = 0x000; // U_WMR76 0 0 0 0 0 0 0 0 0 0 + table[0x77] = 0x000; // U_WMR77 0 0 0 0 0 0 0 0 0 0 + table[0x78] = 0x000; // U_WMR78 0 0 0 0 0 0 0 0 0 0 + table[0x79] = 0x000; // U_WMR79 0 0 0 0 0 0 0 0 0 0 + table[0x7A] = 0x000; // U_WMR7A 0 0 0 0 0 0 0 0 0 0 + table[0x7B] = 0x000; // U_WMR7B 0 0 0 0 0 0 0 0 0 0 + table[0x7C] = 0x000; // U_WMR7C 0 0 0 0 0 0 0 0 0 0 + table[0x7D] = 0x000; // U_WMR7D 0 0 0 0 0 0 0 0 0 0 + table[0x7E] = 0x000; // U_WMR7E 0 0 0 0 0 0 0 0 0 0 + table[0x7F] = 0x000; // U_WMR7F 0 0 0 0 0 0 0 0 0 0 + table[0x80] = 0x000; // U_WMR80 0 0 0 0 0 0 0 0 0 0 + table[0x81] = 0x000; // U_WMR81 0 0 0 0 0 0 0 0 0 0 + table[0x82] = 0x000; // U_WMR82 0 0 0 0 0 0 0 0 0 0 + table[0x83] = 0x000; // U_WMR83 0 0 0 0 0 0 0 0 0 0 + table[0x84] = 0x000; // U_WMR84 0 0 0 0 0 0 0 0 0 0 + table[0x85] = 0x000; // U_WMR85 0 0 0 0 0 0 0 0 0 0 + table[0x86] = 0x000; // U_WMR86 0 0 0 0 0 0 0 0 0 0 + table[0x87] = 0x000; // U_WMR87 0 0 0 0 0 0 0 0 0 0 + table[0x88] = 0x000; // U_WMR88 0 0 0 0 0 0 0 0 0 0 + table[0x89] = 0x000; // U_WMR89 0 0 0 0 0 0 0 0 0 0 + table[0x8A] = 0x000; // U_WMR8A 0 0 0 0 0 0 0 0 0 0 + table[0x8B] = 0x000; // U_WMR8B 0 0 0 0 0 0 0 0 0 0 + table[0x8C] = 0x000; // U_WMR8C 0 0 0 0 0 0 0 0 0 0 + table[0x8D] = 0x000; // U_WMR8D 0 0 0 0 0 0 0 0 0 0 + table[0x8E] = 0x000; // U_WMR8E 0 0 0 0 0 0 0 0 0 0 + table[0x8F] = 0x000; // U_WMR8F 0 0 0 0 0 0 0 0 0 0 + table[0x90] = 0x000; // U_WMR90 0 0 0 0 0 0 0 0 0 0 + table[0x91] = 0x000; // U_WMR91 0 0 0 0 0 0 0 0 0 0 + table[0x92] = 0x000; // U_WMR92 0 0 0 0 0 0 0 0 0 0 + table[0x93] = 0x000; // U_WMR93 0 0 0 0 0 0 0 0 0 0 + table[0x94] = 0x000; // U_WMR94 0 0 0 0 0 0 0 0 0 0 + table[0x95] = 0x000; // U_WMR95 0 0 0 0 0 0 0 0 0 0 + table[0x96] = 0x000; // U_WMR96 0 0 0 0 0 0 0 0 0 0 + table[0x97] = 0x000; // U_WMR97 0 0 0 0 0 0 0 0 0 0 + table[0x98] = 0x000; // U_WMR98 0 0 0 0 0 0 0 0 0 0 + table[0x99] = 0x000; // U_WMR99 0 0 0 0 0 0 0 0 0 0 + table[0x9A] = 0x000; // U_WMR9A 0 0 0 0 0 0 0 0 0 0 + table[0x9B] = 0x000; // U_WMR9B 0 0 0 0 0 0 0 0 0 0 + table[0x9C] = 0x000; // U_WMR9C 0 0 0 0 0 0 0 0 0 0 + table[0x9D] = 0x000; // U_WMR9D 0 0 0 0 0 0 0 0 0 0 + table[0x9E] = 0x000; // U_WMR9E 0 0 0 0 0 0 0 0 0 0 + table[0x9F] = 0x000; // U_WMR9F 0 0 0 0 0 0 0 0 0 0 + table[0xA0] = 0x000; // U_WMRA0 0 0 0 0 0 0 0 0 0 0 + table[0xA1] = 0x000; // U_WMRA1 0 0 0 0 0 0 0 0 0 0 + table[0xA2] = 0x000; // U_WMRA2 0 0 0 0 0 0 0 0 0 0 + table[0xA3] = 0x000; // U_WMRA3 0 0 0 0 0 0 0 0 0 0 + table[0xA4] = 0x000; // U_WMRA4 0 0 0 0 0 0 0 0 0 0 + table[0xA5] = 0x000; // U_WMRA5 0 0 0 0 0 0 0 0 0 0 + table[0xA6] = 0x000; // U_WMRA6 0 0 0 0 0 0 0 0 0 0 + table[0xA7] = 0x000; // U_WMRA7 0 0 0 0 0 0 0 0 0 0 + table[0xA8] = 0x000; // U_WMRA8 0 0 0 0 0 0 0 0 0 0 + table[0xA9] = 0x000; // U_WMRA9 0 0 0 0 0 0 0 0 0 0 + table[0xAA] = 0x000; // U_WMRAA 0 0 0 0 0 0 0 0 0 0 + table[0xAB] = 0x000; // U_WMRAB 0 0 0 0 0 0 0 0 0 0 + table[0xAC] = 0x000; // U_WMRAC 0 0 0 0 0 0 0 0 0 0 + table[0xAD] = 0x000; // U_WMRAD 0 0 0 0 0 0 0 0 0 0 + table[0xAE] = 0x000; // U_WMRAE 0 0 0 0 0 0 0 0 0 0 + table[0xAF] = 0x000; // U_WMRAF 0 0 0 0 0 0 0 0 0 0 + table[0xB0] = 0x000; // U_WMRB0 0 0 0 0 0 0 0 0 0 0 + table[0xB1] = 0x000; // U_WMRB1 0 0 0 0 0 0 0 0 0 0 + table[0xB2] = 0x000; // U_WMRB2 0 0 0 0 0 0 0 0 0 0 + table[0xB3] = 0x000; // U_WMRB3 0 0 0 0 0 0 0 0 0 0 + table[0xB4] = 0x000; // U_WMRB4 0 0 0 0 0 0 0 0 0 0 + table[0xB5] = 0x000; // U_WMRB5 0 0 0 0 0 0 0 0 0 0 + table[0xB6] = 0x000; // U_WMRB6 0 0 0 0 0 0 0 0 0 0 + table[0xB7] = 0x000; // U_WMRB7 0 0 0 0 0 0 0 0 0 0 + table[0xB8] = 0x000; // U_WMRB8 0 0 0 0 0 0 0 0 0 0 + table[0xB9] = 0x000; // U_WMRB9 0 0 0 0 0 0 0 0 0 0 + table[0xBA] = 0x000; // U_WMRBA 0 0 0 0 0 0 0 0 0 0 + table[0xBB] = 0x000; // U_WMRBB 0 0 0 0 0 0 0 0 0 0 + table[0xBC] = 0x000; // U_WMRBC 0 0 0 0 0 0 0 0 0 0 + table[0xBD] = 0x000; // U_WMRBD 0 0 0 0 0 0 0 0 0 0 + table[0xBE] = 0x000; // U_WMRBE 0 0 0 0 0 0 0 0 0 0 + table[0xBF] = 0x000; // U_WMRBF 0 0 0 0 0 0 0 0 0 0 + table[0xC0] = 0x000; // U_WMRC0 0 0 0 0 0 0 0 0 0 0 + table[0xC1] = 0x000; // U_WMRC1 0 0 0 0 0 0 0 0 0 0 + table[0xC2] = 0x000; // U_WMRC2 0 0 0 0 0 0 0 0 0 0 + table[0xC3] = 0x000; // U_WMRC3 0 0 0 0 0 0 0 0 0 0 + table[0xC4] = 0x000; // U_WMRC4 0 0 0 0 0 0 0 0 0 0 + table[0xC5] = 0x000; // U_WMRC5 0 0 0 0 0 0 0 0 0 0 + table[0xC6] = 0x000; // U_WMRC6 0 0 0 0 0 0 0 0 0 0 + table[0xC7] = 0x000; // U_WMRC7 0 0 0 0 0 0 0 0 0 0 + table[0xC8] = 0x000; // U_WMRC8 0 0 0 0 0 0 0 0 0 0 + table[0xC9] = 0x000; // U_WMRC9 0 0 0 0 0 0 0 0 0 0 + table[0xCA] = 0x000; // U_WMRCA 0 0 0 0 0 0 0 0 0 0 + table[0xCB] = 0x000; // U_WMRCB 0 0 0 0 0 0 0 0 0 0 + table[0xCC] = 0x000; // U_WMRCC 0 0 0 0 0 0 0 0 0 0 + table[0xCD] = 0x000; // U_WMRCD 0 0 0 0 0 0 0 0 0 0 + table[0xCE] = 0x000; // U_WMRCE 0 0 0 0 0 0 0 0 0 0 + table[0xCF] = 0x000; // U_WMRCF 0 0 0 0 0 0 0 0 0 0 + table[0xD0] = 0x000; // U_WMRD0 0 0 0 0 0 0 0 0 0 0 + table[0xD1] = 0x000; // U_WMRD1 0 0 0 0 0 0 0 0 0 0 + table[0xD2] = 0x000; // U_WMRD2 0 0 0 0 0 0 0 0 0 0 + table[0xD3] = 0x000; // U_WMRD3 0 0 0 0 0 0 0 0 0 0 + table[0xD4] = 0x000; // U_WMRD4 0 0 0 0 0 0 0 0 0 0 + table[0xD5] = 0x000; // U_WMRD5 0 0 0 0 0 0 0 0 0 0 + table[0xD6] = 0x000; // U_WMRD6 0 0 0 0 0 0 0 0 0 0 + table[0xD7] = 0x000; // U_WMRD7 0 0 0 0 0 0 0 0 0 0 + table[0xD8] = 0x000; // U_WMRD8 0 0 0 0 0 0 0 0 0 0 + table[0xD9] = 0x000; // U_WMRD9 0 0 0 0 0 0 0 0 0 0 + table[0xDA] = 0x000; // U_WMRDA 0 0 0 0 0 0 0 0 0 0 + table[0xDB] = 0x000; // U_WMRDB 0 0 0 0 0 0 0 0 0 0 + table[0xDC] = 0x000; // U_WMRDC 0 0 0 0 0 0 0 0 0 0 + table[0xDD] = 0x000; // U_WMRDD 0 0 0 0 0 0 0 0 0 0 + table[0xDE] = 0x000; // U_WMRDE 0 0 0 0 0 0 0 0 0 0 + table[0xDF] = 0x000; // U_WMRDF 0 0 0 0 0 0 0 0 0 0 + table[0xE0] = 0x000; // U_WMRE0 0 0 0 0 0 0 0 0 0 0 + table[0xE1] = 0x000; // U_WMRE1 0 0 0 0 0 0 0 0 0 0 + table[0xE2] = 0x000; // U_WMRE2 0 0 0 0 0 0 0 0 0 0 + table[0xE3] = 0x000; // U_WMRE3 0 0 0 0 0 0 0 0 0 0 + table[0xE4] = 0x000; // U_WMRE4 0 0 0 0 0 0 0 0 0 0 + table[0xE5] = 0x000; // U_WMRE5 0 0 0 0 0 0 0 0 0 0 + table[0xE6] = 0x000; // U_WMRE6 0 0 0 0 0 0 0 0 0 0 + table[0xE7] = 0x000; // U_WMRE7 0 0 0 0 0 0 0 0 0 0 + table[0xE8] = 0x000; // U_WMRE8 0 0 0 0 0 0 0 0 0 0 + table[0xE9] = 0x000; // U_WMRE9 0 0 0 0 0 0 0 0 0 0 + table[0xEA] = 0x000; // U_WMREA 0 0 0 0 0 0 0 0 0 0 + table[0xEB] = 0x000; // U_WMREB 0 0 0 0 0 0 0 0 0 0 + table[0xEC] = 0x000; // U_WMREC 0 0 0 0 0 0 0 0 0 0 + table[0xED] = 0x000; // U_WMRED 0 0 0 0 0 0 0 0 0 0 + table[0xEE] = 0x000; // U_WMREE 0 0 0 0 0 0 0 0 0 0 + table[0xEF] = 0x000; // U_WMREF 0 0 0 0 0 0 0 0 0 0 + table[0xF0] = 0x020; // U_WMRDELETEOBJECT 0 0 0 0 1 0 0 0 0 0 + table[0xF1] = 0x000; // U_WMRF1 0 0 0 0 0 0 0 0 0 0 + table[0xF2] = 0x000; // U_WMRF2 0 0 0 0 0 0 0 0 0 0 + table[0xF3] = 0x000; // U_WMRF3 0 0 0 0 0 0 0 0 0 0 + table[0xF4] = 0x000; // U_WMRF4 0 0 0 0 0 0 0 0 0 0 + table[0xF5] = 0x000; // U_WMRF5 0 0 0 0 0 0 0 0 0 0 + table[0xF6] = 0x000; // U_WMRF6 0 0 0 0 0 0 0 0 0 0 + table[0xF7] = 0x120; // U_WMRCREATEPALETTE 0 1 0 0 1 0 0 0 0 0 Not selected yet, so no change in drawing conditions + table[0xF8] = 0x120; // U_WMRCREATEBRUSH 0 1 0 0 1 0 0 0 0 0 " + table[0xF9] = 0x120; // U_WMRCREATEPATTERNBRUSH 0 1 0 0 1 0 0 0 0 0 " + table[0xFA] = 0x120; // U_WMRCREATEPENINDIRECT 0 1 0 0 1 0 0 0 0 0 " + table[0xFB] = 0x120; // U_WMRCREATEFONTINDIRECT 0 1 0 0 1 0 0 0 0 0 " + table[0xFC] = 0x120; // U_WMRCREATEBRUSHINDIRECT 0 1 0 0 1 0 0 0 0 0 " + table[0xFD] = 0x020; // U_WMRCREATEBITMAPINDIRECT 0 0 0 0 1 0 0 0 0 0 " + table[0xFE] = 0x020; // U_WMRCREATEBITMAP 0 0 0 0 1 0 0 0 0 0 " + table[0xFF] = 0x120; // U_WMRCREATEREGION 0 1 0 0 1 0 0 0 0 0 " + } + result = table[type]; + } + return(result); +} + +/* ********************************************************************************************** +These functions are for setting up, appending to, and then tearing down an WMF structure, including +writing the final data structure out to a file. +*********************************************************************************************** */ + +/** + \brief Duplicate an WMR record. + \param wmr record to duplicate +*/ +char *wmr_dup( + const char *wmr + ){ + char *dup; + uint32_t irecsize; + + if(!wmr)return(NULL); + memcpy(&irecsize,wmr,4); /* Size16_4 field is at offset 0 */ + irecsize *= 2; + dup=malloc(irecsize); + if(dup){ memcpy(dup,wmr,irecsize); } + return(dup); +} + + +/* some of these functions are identical to the emf ones, handled by defines in uemf.h,use the emf versions */ + +/** + \brief Start constructing an wmf in memory. Supply the file name and initial size. + \return 0 for success, >=0 for failure. + \param name WMF filename (will be opened) + \param initsize Initialize WMF in memory to hold this many bytes + \param chunksize When needed increase WMF in memory by this number of bytes + \param wt WMF in memory + + +*/ +int wmf_start( + const char *name, + const uint32_t initsize, + const uint32_t chunksize, + WMFTRACK **wt + ){ + FILE *fp; + WMFTRACK *wtl=NULL; + + if(initsize < 1)return(1); + if(chunksize < 1)return(2); + if(!name)return(3); + wtl = (WMFTRACK *) malloc(sizeof(WMFTRACK)); + if(!wtl)return(4); + wtl->buf = malloc(initsize); // no need to zero the memory + if(!wtl->buf){ + free(wtl); + return(5); + } + fp=wmf_fopen(name,U_WRITE); + if(!fp){ + free(wtl->buf); + free(wtl); + return(6); + } + wtl->fp = fp; + wtl->allocated = initsize; + wtl->used = 0; + wtl->records = 0; + wtl->PalEntries = 0; + wtl->chunk = chunksize; + wtl->largest = 0; /* only used by WMF */ + wtl->sumObjects = 0; /* only used by WMF */ + (void) wmf_highwater(U_HIGHWATER_CLEAR); + *wt=wtl; + return(0); +} + +/** + \brief Release memory for an wmf structure in memory. Call this after wmf_finish(). + \return 0 on success, >=1 on failure + \param wt WMF in memory + Renamed to uwmf_free to avoid conflict with libwmf +*/ +int uwmf_free( + WMFTRACK **wt + ){ + WMFTRACK *wtl; + if(!wt)return(1); + wtl=*wt; + if(!wtl)return(2); + free(wtl->buf); + free(wtl); + *wt=NULL; + (void)wmf_highwater(U_HIGHWATER_CLEAR); + return(0); +} + +/** + \brief Finalize the emf in memory and write it to the file. + \return 0 on success, >=1 on failure + \param wt WMF in memory +*/ +int wmf_finish( + WMFTRACK *wt + ){ + char *record; + int off; + uint32_t tmp; + uint16_t tmp16; + + if(!wt->fp)return(1); // This could happen if something stomps on memory, otherwise should be caught in wmf_start + + // Set the header fields which were unknown up until this point + + + if(((U_WMRPLACEABLE *) wt->buf)->Key == 0x9AC6CDD7){ off = U_SIZE_WMRPLACEABLE; } + else { off = 0; } + + record = (wt->buf + off); + tmp = (wt->used)/2; + memcpy(record + offsetof(U_WMRHEADER,Sizew), &tmp, 4); /* 16 bit words in file. not aligned */ + tmp = (wt->largest)/2; + memcpy(record + offsetof(U_WMRHEADER,maxSize), &tmp, 4); /* 16 bit words in largest record, not aligned */ + uint32_t maxobj = wmf_highwater(U_HIGHWATER_READ); + if(maxobj > UINT16_MAX)return(3); + tmp16 = maxobj; + memcpy(record + offsetof(U_WMRHEADER,nObjects), &tmp16, 2); /* Total number of brushes, pens, and other graphics objects defined in this file */ + +#if U_BYTE_SWAP + //This is a Big Endian machine, WMF data must be Little Endian + U_wmf_endian(wt->buf,wt->used,1,0); // BE to LE, entire file +#endif + + (void) U_wmr_properties(U_WMR_INVALID); /* force the release of the lookup table memory, returned value is irrelevant */ + if(1 != fwrite(wt->buf,wt->used,1,wt->fp))return(2); + (void) fclose(wt->fp); + wt->fp=NULL; + return(0); +} + +/** + \brief Retrieve contents of an WMF file by name. + \return 0 on success, >=1 on failure + \param filename Name of file to open, including the path + \param contents Contents of the file. Buffer must be free()'d by caller. + \param length Number of bytes in Contents +*/ +int wmf_readdata( + const char *filename, + char **contents, + size_t *length + ){ + FILE *fp; + int status=0; + + *contents=NULL; + fp=wmf_fopen(filename,U_READ); + if(!fp){ status = 1; } + else { + // read the entire file into memory + fseek(fp, 0, SEEK_END); // move to end + *length = ftell(fp); + rewind(fp); + *contents = (char *) malloc(*length); + if(!*contents){ + status = 2; + } + else { + size_t inbytes = fread(*contents,*length,1,fp); + if(inbytes != 1){ + free(*contents); + status = 3; + } + else { +#if U_BYTE_SWAP + //This is a Big Endian machine, WMF data is Little Endian + U_wmf_endian(*contents,*length,0,0); // LE to BE, entire file +#endif + } + } + fclose(fp); + } + return(status); +} + +/** + \brief Append an WMF record to a wmf in memory. This may reallocate buf memory. + \return 0 for success, >=1 for failure. + \param rec Record to append to WMF in memory + \param wt WMF in memory + \param freerec If true, free rec after append +*/ +int wmf_append( + U_METARECORD *rec, + WMFTRACK *wt, + int freerec + ){ + size_t deficit; + uint32_t wp; + uint32_t size; + + size = U_wmr_size(rec); +#ifdef U_VALGRIND + printf("\nbefore \n"); + printf(" probe %d\n",memprobe(rec, size)); + printf("after \n"); +#endif + if(!rec)return(1); + if(!wt)return(2); + if(size + wt->used > wt->allocated){ + deficit = size + wt->used - wt->allocated; + if(deficit < wt->chunk)deficit = wt->chunk; + wt->allocated += deficit; + wt->buf = realloc(wt->buf,wt->allocated); + if(!wt->buf)return(3); + } + memcpy(wt->buf + wt->used, rec, size); + wt->used += size; + wt->records++; + if(wt->largest < size)wt->largest=size; + /* does the record create an object: brush, font, palette, pen, or region ? + Following EOF properties comes back as U_WMR_INVALID */ + wp = U_wmr_properties(U_WMRTYPE(rec)); + if((wp != U_WMR_INVALID) && (U_DRAW_OBJECT & wp))wt->sumObjects++; + if(freerec){ free(rec); } + return(0); +} + +/** + \brief Append an WMF header to a wmf in memory. This may reallocate buf memory. + WMF header is not a normal record, method used to figure out its size is different. + \return 0 for success, >=1 for failure. + \param rec header to append to WMF in memory + \param wt WMF in memory + \param freerec If true, free rec after append +*/ +int wmf_header_append( + U_METARECORD *rec, + WMFTRACK *wt, + int freerec + ){ + size_t deficit; + unsigned int hsize; + + hsize = (((U_WMRPLACEABLE *) rec)->Key == 0x9AC6CDD7 ? U_SIZE_WMRHEADER + U_SIZE_WMRPLACEABLE: U_SIZE_WMRHEADER); + +#ifdef U_VALGRIND + printf("\nbefore \n"); + printf(" probe %d\n",memprobe(rec, hsize)); + printf("after \n"); +#endif + if(!rec)return(1); + if(!wt)return(2); + if(U_wmr_size(rec) + wt->used > wt->allocated){ + deficit = hsize + wt->used - wt->allocated; + if(deficit < wt->chunk)deficit = wt->chunk; + wt->allocated += deficit; + wt->buf = realloc(wt->buf,wt->allocated); + if(!wt->buf)return(3); + } + memcpy(wt->buf + wt->used, rec, hsize); + wt->used += hsize; + /* do NOT increment records count, this is not strictly a record */ + if(wt->largest < hsize)wt->largest=hsize; + if(freerec){ free(rec); } + return(0); +} + +/** + \brief Keep track of the largest number used. + \return The largest object number used. + \param setval U_HIGHWATER_READ only return value, U_HIGHWATER_CLEAR also set value to 0, anything else, set to this if higher than stored. +*/ +int wmf_highwater(uint32_t setval){ + static uint32_t value=0; + uint32_t retval; + if(setval == U_HIGHWATER_READ){ + retval = value; + } + else if(setval == U_HIGHWATER_CLEAR){ + retval = value; + value = 0; + } + else { + if(setval > value)value = setval; + retval = value; + } + return(retval); +} + +/** + \brief Create a handle table. Entries filled with 0 are empty, entries >0 hold a handle. + \return 0 for success, >=1 for failure. + \param initsize Initialize with space for this number of handles + \param chunksize When needed increase space by this number of handles + \param wht WMF handle table +*/ +int wmf_htable_create( + uint32_t initsize, + uint32_t chunksize, + WMFHANDLES **wht + ){ + WMFHANDLES *whtl; + + if(initsize<1)return(1); + if(chunksize<1)return(2); + whtl = (WMFHANDLES *) malloc(sizeof(WMFHANDLES)); + if(!whtl)return(3); + whtl->table = malloc(initsize * sizeof(uint32_t)); + if(!whtl->table){ + free(whtl); + return(4); + } + memset(whtl->table , 0, initsize * sizeof(uint32_t)); // zero all slots in the table + whtl->allocated = initsize; + whtl->chunk = chunksize; + whtl->table[0] = 0; // This slot isn't actually ever used + whtl->lolimit = 1; // first available table entry + whtl->hilimit = 0; // no entries in the table yet. + whtl->peak = 0; // no entries in the table ever + *wht = whtl; + return(0); +} + +/** + \brief Delete an entry from the handle table. Move it back onto the stack. The specified slot is filled with a 0. + \return 0 for success, >=1 for failure. + \param ih handle + \param wht WMF handle table + +*/ +int wmf_htable_delete( + uint32_t *ih, + WMFHANDLES *wht + ){ + if(!wht)return(1); + if(!wht->table)return(2); + if(*ih < 1)return(4); // invalid handle + if(!wht->table[*ih])return(5); // requested table position was not in use + wht->table[*ih]=0; // remove handle from table + while(wht->hilimit>0 && !wht->table[wht->hilimit]){ // adjust hilimit + wht->hilimit--; + } + if(*ih < wht->lolimit)wht->lolimit = *ih; // adjust lolimit + *ih=0; // invalidate handle variable, so a second delete will of it is not possible + return(0); +} + +/** + \brief Returns the index of the first free slot. + Call realloc() if needed. The slot is set to handle (indicates occupied) and the peak value is adjusted. + \return 0 for success, >=1 for failure. + \param ih handle + \param wht WMF handle table +*/ +int wmf_htable_insert( + uint32_t *ih, + WMFHANDLES *wht + ){ + size_t newsize; + + if(!wht)return(1); + if(!wht->table)return(2); + if(!ih)return(4); + if(wht->lolimit >= wht->allocated - 1){ // need to reallocate + newsize=wht->allocated + wht->chunk; + wht->table = realloc(wht->table,newsize * sizeof(uint32_t)); + if(!wht->table)return(5); + memset(&wht->table[wht->allocated] , 0, wht->chunk * sizeof(uint32_t)); // zero all NEW slots in the table + wht->allocated = newsize; + } + *ih = wht->lolimit; // handle that is inserted in first available slot + wht->table[*ih] = *ih; // handle goes into preexisting (but zero) slot in table, handle number is the same as the slot number + if(*ih > wht->hilimit){ + wht->hilimit = *ih; + (void) wmf_highwater(wht->hilimit); + } + if(*ih > wht->peak){ + wht->peak = *ih; + } + /* Find the next available slot, it will be at least one higher than the present position, and will have a zero in it. */ + wht->lolimit++; + while(wht->lolimit<= wht->hilimit && wht->table[wht->lolimit]){ wht->lolimit++; } + return(0); +} + +/** + \brief Free all memory in an htable. Sets the pointer to NULL. + \return 0 for success, >=1 for failure. + \param wht WMF handle table +*/ +int wmf_htable_free( + WMFHANDLES **wht + ){ + WMFHANDLES *whtl; + if(!wht)return(1); + whtl = *wht; + if(!whtl)return(2); + if(!whtl->table)return(3); + free(whtl->table); + free(whtl); + *wht=NULL; + return(0); +} + + +/* ********************************************************************************************** +These functions create standard structures used in the WMR records. +*********************************************************************************************** */ + +// hide these from Doxygen +//! \cond +/* ********************************************************************************************** +These functions contain shared code used by various U_WMR*_print functions. These should NEVER be called +by end user code and to further that end prototypes are NOT provided and they are hidden from Doxygen. +*********************************************************************************************** */ + +/* These definitons only used here */ +#define U_SIZE_WMR_NOARGS 6 +#define U_SIZE_WMR_1ARG16 8 +#define U_SIZE_WMR_2ARG16 10 +#define U_SIZE_WMR_3ARG16 12 +#define U_SIZE_WMR_4ARG16 14 +#define U_SIZE_WMR_5ARG16 16 +#define U_SIZE_WMR_6ARG16 18 +#define U_SIZE_WMR_8ARG16 22 + +char *U_WMRCORENONE_set(char *string){ + printf("unimplemented creator for:%s\n",string); + return(NULL); +} + +void U_WMRCORE_SETRECHEAD(char *record, uint32_t irecsize, int iType){ + uint32_t Size16; + Size16 = irecsize/2; + memcpy(record,&Size16,4); /*Size16_4 is at offset 0 in the record */ + ((U_METARECORD *) record)->iType = iType; + ((U_METARECORD *) record)->xb = U_WMR_XB_FROM_TYPE(iType); +} + +/* records that have no arguments */ +char *U_WMRCORE_NOARGS_set( + int iType +){ + char *record=NULL; + uint32_t irecsize; + irecsize = U_SIZE_METARECORD; + record = malloc(irecsize); + if(record)U_WMRCORE_SETRECHEAD(record,irecsize,iType); + return(record); +} + + +/* records like U_WMRFLOODFILL and others. all args are optional, Color is not */ +char *U_WMRCORE_1U16_CRF_2U16_set( + int iType, + uint16_t *arg1, + U_COLORREF Color, + uint16_t *arg2, + uint16_t *arg3 +){ + char *record=NULL; + uint32_t irecsize,off; + irecsize = U_SIZE_METARECORD + U_SIZE_COLORREF; + if(arg1)irecsize+=2; + if(arg2)irecsize+=2; + if(arg3)irecsize+=2; + record = malloc(irecsize); + if(record){ + U_WMRCORE_SETRECHEAD(record,irecsize,iType); + off = U_SIZE_METARECORD; + if(arg1){ memcpy(record + off, arg1, 2); off+=2; } + memcpy(record + off, &Color, 4); off+=4; + if(arg2){ memcpy(record + off, arg2, 2); off+=2; } + if(arg3){ memcpy(record + off, arg3, 2); } + } + return(record); +} + +/* records that have a single uint16_t argument like U_WMRSETMAPMODE + May also be used with int16_t with appropriate casts */ +char *U_WMRCORE_1U16_set( + int iType, + uint16_t arg1 +){ + char *record=NULL; + uint32_t irecsize,off; + irecsize = U_SIZE_WMR_1ARG16; + record = malloc(irecsize); + if(record){ + U_WMRCORE_SETRECHEAD(record,irecsize,iType); + off = U_SIZE_METARECORD; + memcpy(record+off,&arg1,2); + } + return(record); +} + +/* records that have two uint16_t arguments like U_WMRSETBKMODE + May also be used with int16_t with appropriate casts */ +char *U_WMRCORE_2U16_set( + int iType, + uint16_t arg1, + uint16_t arg2 +){ + char *record=NULL; + uint32_t irecsize,off; + irecsize = U_SIZE_WMR_2ARG16; + record = malloc(irecsize); + if(record){ + U_WMRCORE_SETRECHEAD(record,irecsize,iType); + off = U_SIZE_METARECORD; + memcpy(record+off,&arg1,2); off+=2; + memcpy(record+off,&arg2,2); + } + return(record); +} + +/* records that have four uint16_t arguments like U_WMRSCALEWINDOWEXT + May also be used with int16_t with appropriate casts */ +char *U_WMRCORE_4U16_set( + int iType, + uint16_t arg1, + uint16_t arg2, + uint16_t arg3, + uint16_t arg4 +){ + char *record=NULL; + uint32_t irecsize, off; + irecsize = U_SIZE_WMR_4ARG16; + record = malloc(irecsize); + if(record){ + U_WMRCORE_SETRECHEAD(record,irecsize,iType); + off = U_SIZE_METARECORD; + memcpy(record+off,&arg1,2); off+=2; + memcpy(record+off,&arg2,2); off+=2; + memcpy(record+off,&arg3,2); off+=2; + memcpy(record+off,&arg4,2); + } + return(record); +} + +/* records that have five uint16_t arguments like U_WMRCREATEPENINDIRECT + May also be used with int16_t with appropriate casts */ +char *U_WMRCORE_5U16_set( + int iType, + uint16_t arg1, + uint16_t arg2, + uint16_t arg3, + uint16_t arg4, + uint16_t arg5 +){ + char *record=NULL; + uint32_t irecsize, off; + irecsize = U_SIZE_WMR_5ARG16; + record = malloc(irecsize); + if(record){ + U_WMRCORE_SETRECHEAD(record,irecsize,iType); + off = U_SIZE_METARECORD; + memcpy(record+off,&arg1,2); off+=2; + memcpy(record+off,&arg2,2); off+=2; + memcpy(record+off,&arg3,2); off+=2; + memcpy(record+off,&arg4,2); off+=2; + memcpy(record+off,&arg5,2); + } + return(record); +} + +/* records that have size uint16_t arguments like U_ROUNDREC + May also be used with int16_t with appropriate casts */ +char *U_WMRCORE_6U16_set( + int iType, + uint16_t arg1, + uint16_t arg2, + uint16_t arg3, + uint16_t arg4, + uint16_t arg5, + uint16_t arg6 +){ + char *record=NULL; + uint32_t irecsize, off; + irecsize = U_SIZE_WMR_6ARG16; + record = malloc(irecsize); + if(record){ + U_WMRCORE_SETRECHEAD(record,irecsize,iType); + off = U_SIZE_METARECORD; + memcpy(record+off,&arg1,2); off+=2; + memcpy(record+off,&arg2,2); off+=2; + memcpy(record+off,&arg3,2); off+=2; + memcpy(record+off,&arg4,2); off+=2; + memcpy(record+off,&arg5,2); off+=2; + memcpy(record+off,&arg6,2); + } + return(record); +} + +/* records that have eight uint16_t arguments like U_WMRARC + May also be used with int16_t with appropriate casts */ +char *U_WMRCORE_8U16_set( + int iType, + uint16_t arg1, + uint16_t arg2, + uint16_t arg3, + uint16_t arg4, + uint16_t arg5, + uint16_t arg6, + uint16_t arg7, + uint16_t arg8 +){ + char *record=NULL; + uint32_t irecsize, off; + irecsize = U_SIZE_WMR_8ARG16; + record = malloc(irecsize); + if(record){ + U_WMRCORE_SETRECHEAD(record,irecsize,iType); + off = U_SIZE_METARECORD; + memcpy(record+off,&arg1,2); off+=2; + memcpy(record+off,&arg2,2); off+=2; + memcpy(record+off,&arg3,2); off+=2; + memcpy(record+off,&arg4,2); off+=2; + memcpy(record+off,&arg5,2); off+=2; + memcpy(record+off,&arg6,2); off+=2; + memcpy(record+off,&arg7,2); off+=2; + memcpy(record+off,&arg8,2); + } + return(record); +} + +/* records that have + arg1 an (optional) (u)int16 + arg2 an (optional( (u)int16 + N16 number of (u)int16_t cells in array. may be zero + array of N16 (u)int16_t cells (or any structure that is 2N bytes in size), should be NULL if N16 is 0. + like U_WMRCREATEBRUSHINDIRECT with arg1=arg2=NULL +*/ +char *U_WMRCORE_2U16_N16_set( + int iType, + const uint16_t *arg1, + const uint16_t *arg2, + const uint16_t N16, + const void *array + ){ + char *record=NULL; + uint32_t irecsize, off; + irecsize = U_SIZE_METARECORD + N16*2; + if(arg1)irecsize += 2; + if(arg2)irecsize += 2; + record = malloc(irecsize); + if(record){ + U_WMRCORE_SETRECHEAD(record,irecsize,iType); + off = U_SIZE_METARECORD; + if(arg1){ memcpy(record+off,arg1,2); off+=2; } + if(arg2){ memcpy(record+off,arg2,2); off+=2; } + if(N16){ memcpy(record+off,array,2*N16); } + } + return(record); +} + + + +/* records that set a U_PALETTE , then a count and then a uint16_t list like U_WMRANIMATEPALETTE + May also be used with int16_t with appropriate casts */ +char *U_WMRCORE_PALETTE_set( + int iType, + const U_PALETTE *Palette +){ + char *record=NULL; + uint32_t irecsize, off, nPE; + nPE = 4*Palette->NumEntries; + if(!nPE)return(NULL); /* What would it mean to load an empty palette??? */ + irecsize = U_SIZE_METARECORD + 2 + 2 + nPE; + record = malloc(irecsize); + if(record){ + U_WMRCORE_SETRECHEAD(record,irecsize,iType); + off = U_SIZE_METARECORD; + memcpy(record+off, &Palette->Start, 2); off+=2; + memcpy(record+off, &Palette->NumEntries, 2); off+=2; + memcpy(record+off, &Palette->PalEntries, nPE); + } + return(record); +} + +//! \endcond + +/* ********************************************************************************************** +These functions are simpler or more convenient ways to generate the specified types of WMR records. +Each should be called in preference to the underlying "base" WMR function. +*********************************************************************************************** */ + + +/** + \brief Allocate and construct a U_WMRDELETEOBJECT record and also delete the requested object from the table. + Use this function instead of calling U_WMRDELETEOBJECT_set() directly. + Object Pointer in WMF (caller) is 0->N, but in htable it is 1->N+1, make that correction here. + \return pointer to the U_WMRDELETEOBJECT record, or NULL on error. + \param ihObject Pointer to handle to delete. This value is set to 0xFFFFFFFF if the function succeeds. + \param wht WMF handle table + + Note that calling this function should always be conditional on the specifed object being defined. It is easy to + write a program where deleteobject_set() is called in a sequence where, at the time, we know that ihObject is defined. + Then a later modification, possibly quite far away in the code, causes it to be undefined. That distant change will + result in a failure when this function reutrns. That problem cannot be handled here because the only values which + may be returned are a valid U_WMRDELETEOBJECT record or a NULL, and other errors could result in the NULL. + So the object must be checked before the call. +*/ +char *wdeleteobject_set( + uint32_t *ihObject, + WMFHANDLES *wht + ){ + uint32_t saveObject=*ihObject; /* caller 0->N */ + *ihObject += 1; /* caller 0->N --> 1->N+1 table*/ + if(wmf_htable_delete(ihObject,wht))return(NULL); /* invalid handle or other problem, cannot be deleted */ + *ihObject = 0xFFFFFFFF; /* EMF would have set to 0, but 0 is an allowed index in WMF */ + return(U_WMRDELETEOBJECT_set(saveObject)); /* caller 0->N */ +} + +/** + \brief Allocate and construct a U_WMRSELECTOBJECT record, checks that the handle specified is one that can actually be selected. + Use this function instead of calling U_WMRSELECTOBJECT_set() directly. + Object Pointer in WMF (caller) is 0->N, so is record, so no correction to 1->N+1 needed here. + \return pointer to the U_WMRSELECTOBJECT record, or NULL on error. + \param ihObject handle to select + \param wht WMF handle table +*/ +char *wselectobject_set( + uint32_t ihObject, + WMFHANDLES *wht + ){ + /* WMF has no stock objects! */ + if(ihObject > wht->hilimit)return(NULL); // handle this high is not in the table + /* caller uses 0->N, table uses 1->N+1 */ + if(!wht->table[ihObject+1])return(NULL); // handle is not in the table, so cannot be selected + /* file uses 0->N */ + return(U_WMRSELECTOBJECT_set(ihObject)); +} + +/** + \brief Allocate and construct a U_WMRCREATEPENINDIRECT record, create a handle and returns it + Use this function instead of calling U_WMRCREATEPENINDIRECT_set() directly. + Object Pointer in WMF (caller) is 0->N, but in htable it is 1->N+1, make that correction here. + \return pointer to the U_WMRCREATEPENINDIRECT record, or NULL on error. + \param ihPen handle to be used by new object + \param wht WMF handle table + \param pen Pen parameters (U_PEN) +*/ +char *wcreatepenindirect_set( + uint32_t *ihPen, + WMFHANDLES *wht, + U_PEN pen + ){ + if(wmf_htable_insert(ihPen, wht))return(NULL); + *ihPen -= 1; /* 1->N+1 --> 0->N */ + return(U_WMRCREATEPENINDIRECT_set(pen)); +} + +/** + \brief Allocate and construct a U_WMRCREATEBRUSHINDIRECT record, create a handle and returns it + Use this function instead of calling U_WMRCREATEBRUSHINDIRECT_set() directly. + Object Pointer in WMF (caller) is 0->N, but in htable it is 1->N+1, make that correction here. + \return pointer to the U_WMRCREATEBRUSHINDIRECT record, or NULL on error. + \param ihBrush handle to be used by new object + \param wht WMF handle table + \param lb Brush parameters +*/ +char *wcreatebrushindirect_set( + uint32_t *ihBrush, + WMFHANDLES *wht, + U_WLOGBRUSH lb + ){ + if(wmf_htable_insert(ihBrush, wht))return(NULL); + *ihBrush -= 1; /* 1->N+1 --> 0->N */ + return(U_WMRCREATEBRUSHINDIRECT_set(lb)); +} + +/** + \brief Allocate and construct a U_WMRDIBCREATEPATTERNBRUSH record from a DIB. + Use this function instead of calling U_WMRDIBCREATEPATTERNBRUSH_set() directly. + \return pointer to the U_WMRDIBCREATEPATTERNBRUSH record, or NULL on error. + \param ihBrush handle to be used by new object + \param wht WMF handle table + \param iUsage DIBColors enumeration + \param Bmi Bitmap info + \param cbPx Size in bytes of pixel array (row stride * height, there may be some padding at the end of each row) + \param Px (Optional) bitmapbuffer (pixel array section ) +*/ +char *wcreatedibpatternbrush_srcdib_set( + uint32_t *ihBrush, + WMFHANDLES *wht, + const uint32_t iUsage, + const U_BITMAPINFO *Bmi, + const uint32_t cbPx, + const char *Px + + ){ + if(wmf_htable_insert(ihBrush, wht))return(NULL); + *ihBrush -= 1; /* 1->N+1 --> 0->N */ + return(U_WMRDIBCREATEPATTERNBRUSH_set(U_BS_DIBPATTERNPT, iUsage, Bmi, cbPx, Px,NULL)); +} + +/** + \brief Allocate and construct a U_WMRDIBCREATEPATTERNBRUSH record from a U_BITMAP16 object. + Use this function instead of calling U_WMRDIBCREATEPATTERNBRUSH_set() directly. + \return pointer to the U_WMRDIBCREATEPATTERNBRUSH record, or NULL on error. + \param ihBrush handle to be used by new object + \param wht WMF handle table + \param iUsage DIBColors enumeration + \param Bm16 Pointer to a Bitmap16 object +*/ +char *wcreatedibpatternbrush_srcbm16_set( + uint32_t *ihBrush, + WMFHANDLES *wht, + const uint32_t iUsage, + const U_BITMAP16 *Bm16 + ){ + if(wmf_htable_insert(ihBrush, wht))return(NULL); + *ihBrush -= 1; /* 1->N+1 --> 0->N */ + return(U_WMRDIBCREATEPATTERNBRUSH_set(U_BS_PATTERN, iUsage, NULL, 0, NULL, Bm16)); +} + +/** + \brief Allocate and construct a U_WMRCREATEPATTERNBRUSH record, create a handle and returns it + Use this function instead of calling U_WMRCREATEPATTERNBRUSH_set() directly. + WARNING - U_WMRCREATEPATTERNBRUSH has been declared obsolete and application support is spotty - + use U_WMRDIBCREATEPATTERNBRUSH instead. + \return pointer to the U_WMRCREATEPATTERNBRUSH record, or NULL on error. + \param ihBrush handle to be used by new object + \param wht WMF handle table + \param Bm16 Pointer to a Bitmap16 structure (only first 10 bytes are used). + \param Pattern Pointer to a byte array described by Bm16. (Pattern may be a pointer to the BM16 Bits field.) +*/ +char *wcreatepatternbrush_set( + uint32_t *ihBrush, + WMFHANDLES *wht, + U_BITMAP16 *Bm16, + char *Pattern + ){ + if(wmf_htable_insert(ihBrush, wht))return(NULL); + *ihBrush -= 1; /* 1->N+1 --> 0->N */ + return(U_WMRCREATEPATTERNBRUSH_set(Bm16, Pattern)); +} + +/** + \brief Allocate and construct a U_WMRCREATEFONTINDIRECT record, create a handle and returns it + Use this function instead of calling U_WMRCREATEFONTINDIRECT_set() directly. + Object Pointer in WMF (caller) is 0->N, but in htable it is 1->N+1, make that correction here. + \return pointer to the U_WMRCREATEFONTINDIRECT record, or NULL on error. + \param ihFont Font handle, will be created and returned + \param wht Pointer to structure holding all WMF handles + \param uf Pointer to Font parameters as U_FONT * +*/ +char *wcreatefontindirect_set( + uint32_t *ihFont, + WMFHANDLES *wht, + U_FONT *uf + ){ + if(wmf_htable_insert(ihFont, wht))return(NULL); + *ihFont -= 1; /* 1->N+1 --> 0->N */ + return(U_WMRCREATEFONTINDIRECT_set(uf)); +} + +/** + \brief Allocate and construct a U_WMRCREATEPALETTE record, create a handle and returns it + Use this function instead of calling U_WMRCREATEPALETTE_set() directly. + Object Pointer in WMF (caller) is 0->N, but in htable it is 1->N+1, make that correction here. + \return pointer to the U_WMRCREATEPALETTE record, or NULL on error. + \param ihPal Palette handle, will be created and returned + \param wht Pointer to structure holding all WMF handles + \param up Palette parameters +*/ +char *wcreatepalette_set( + uint32_t *ihPal, + WMFHANDLES *wht, + U_PALETTE *up + ){ + if(wmf_htable_insert(ihPal, wht))return(NULL); + *ihPal -= 1; /* 1->N+1 --> 0->N */ + return(U_WMRCREATEPALETTE_set(up)); +} + +/** + \brief Allocate and construct a U_WMRSETPALENTRIES record, create a handle and returns it + Use this function instead of calling U_WMRSETPALENTRIES_set() directly. + Object Pointer in WMF (caller) is 0->N, but in htable it is 1->N+1, make that correction here. + \return pointer to the U_WMRSETPALENTRIES record, or NULL on error. + \param ihPal Palette handle, will be created and returned + \param wht Pointer to structure holding all WMF handles + \param Palettes Values to set with +*/ +char *wsetpaletteentries_set( + uint32_t *ihPal, + WMFHANDLES *wht, + const U_PALETTE *Palettes + ){ + if(wmf_htable_insert(ihPal, wht))return(NULL); + *ihPal -= 1; /* 1->N+1 --> 0->N */ + return(U_WMRSETPALENTRIES_set(Palettes)); +} + +/** + \brief Allocate and construct a U_WMRCREATEREGION record, create a handle and returns it + Use this function instead of calling U_WMRCREATEREGION() directly. + Object Pointer in WMF (caller) is 0->N, but in htable it is 1->N+1, make that correction here. + \return pointer to the U_REGIONS record, or NULL on error. + \param ihReg Region handle, will be created and returned + \param wht Pointer to structure holding all WMF handles + \param Region Values to set with +*/ +char *wcreateregion_set( + uint32_t *ihReg, + WMFHANDLES *wht, + const U_REGION *Region + ){ + if(wmf_htable_insert(ihReg, wht))return(NULL); + *ihReg -= 1; /* 1->N+1 --> 0->N */ + return(U_WMRCREATEREGION_set(Region)); +} +/* A few escape functions are implemented, just those that set a state or a single value */ + +/** + \brief Allocate and construct the specified U_WMRESCAPE structure, create a handle and returns it + Use this function instead of calling U_WMRESCAPE_set() directly. + \return pointer to the U_WMRESCAPE structure, or NULL on error. +*/ +char *wbegin_path_set(void){ + return(U_WMRESCAPE_set(U_MFE_BEGIN_PATH,0,NULL)); +} + +/** + \brief Allocate and construct the specified U_WMRESCAPE structure, create a handle and returns it + Use this function instead of calling U_WMRESCAPE_set() directly. + \return pointer to the U_WMRESCAPE structure, or NULL on error. +*/ +char *wend_path_set(void){ + return(U_WMRESCAPE_set(U_MFE_END_PATH,0,NULL)); +} + +/** + \brief Allocate and construct the specified U_WMRESCAPE structure, create a handle and returns it + Use this function instead of calling U_WMRESCAPE_set() directly. + \return pointer to the U_WMRESCAPE structure, or NULL on error. + \param Type PostScriptCap Enumeration, anything else is an error +*/ +char *wlinecap_set( + int32_t Type + ){ + char *record =NULL; + if(Type == U_WPS_CAP_NOTSET || + Type == U_WPS_CAP_FLAT || + Type == U_WPS_CAP_ROUND || + Type == U_WPS_CAP_SQUARE){ record = U_WMRESCAPE_set(U_MFE_SETLINECAP,4,&Type); } + return(record); +} + +/** + \brief Allocate and construct the specified U_WMRESCAPE structure, create a handle and returns it + Use this function instead of calling U_WMRESCAPE_set() directly. + \return pointer to the U_WMRESCAPE structure, or NULL on error. + \param Type PostScriptCap Enumeration, anything else is an error +*/ +char *wlinejoin_set( + int32_t Type + ){ + char *record =NULL; + if(Type == U_WPS_JOIN_NOTSET || + Type == U_WPS_JOIN_MITER || + Type == U_WPS_JOIN_ROUND || + Type == U_WPS_JOIN_BEVEL){ record = U_WMRESCAPE_set(U_MFE_SETLINEJOIN,4,&Type); } + return(record); +} + +/** + \brief Allocate and construct the specified U_WMRESCAPE structure, create a handle and returns it + Use this function instead of calling U_WMRESCAPE_set() directly. + \return pointer to the U_WMRESCAPE structure, or NULL on error. + \param limit PostScriptCap Enumeration, anything else is an error +*/ +char *wmiterlimit_set( + int32_t limit + ){ + return(U_WMRESCAPE_set(U_MFE_SETMITERLIMIT,4,&limit)); +} + +/* ********************************************************************************************** +These are the core WMR functions, each creates a particular type of record. +All return these records via a char* pointer, which is NULL if the call failed. +They are listed in order by the corresponding U_WMR_* index number. +*********************************************************************************************** */ + +/** + \brief Set up fields for a (placeable) WMR_HEADER. Most of the fields are blank and are not set until all is written. + Typically values are something like (8.5,11.0), 1440 (Letter paper, 1440 DPI). + The scaled paper size must fit in the range 0<->32767 inclusive, because it must be represented by a signed 16bit number. + If the size + dpi result in out of range values a failure will result. + \return pointer to the WMF header record, or NULL on failure + \param size Pointer to page size (if NULL, not a placeable header) in inches. Values must be positive and scaled + \param dpi Logical units/inch. If 0 defaults to 1440. +*/ +char *U_WMRHEADER_set( + U_PAIRF *size, + unsigned int dpi + ){ + char *record=NULL; + uint32_t irecsize,off; + double xmax,ymax; + int16_t xm16,ym16; + irecsize = (size ? U_SIZE_WMRHEADER + U_SIZE_WMRPLACEABLE : U_SIZE_WMRHEADER); + record = calloc(1,irecsize); /* most will be zero*/ + off = 0; + if(record){ + if(size){ /* placeable */ + if(!dpi)dpi=1440; + xmax = U_ROUND((double) size->x * (double) dpi); + ymax = U_ROUND((double) size->y * (double) dpi); + if(xmax < 0 || ymax < 0 || xmax > 32767 || ymax > 32767){ + free(record); + return(NULL); + } + xm16 = xmax; + ym16 = ymax; + ((U_WMRPLACEABLE *) record)->Key = 0x9AC6CDD7; + ((U_WMRPLACEABLE *) record)->HWmf = 0; /* Manual says number of 16 bit words in record, but all WMF examples had it as 0 */ + ((U_WMRPLACEABLE *) record)->Dst.left = 0; + ((U_WMRPLACEABLE *) record)->Dst.top = 0; + ((U_WMRPLACEABLE *) record)->Dst.right = xm16; + ((U_WMRPLACEABLE *) record)->Dst.bottom = ym16; + ((U_WMRPLACEABLE *) record)->Inch = dpi; + ((U_WMRPLACEABLE *) record)->Reserved = 0; + ((U_WMRPLACEABLE *) record)->Checksum = U_16_checksum((int16_t *)record,10); + off = U_SIZE_WMRPLACEABLE; + } + ((U_WMRHEADER *) (record + off))->iType = 1; + ((U_WMRHEADER *) (record + off))->version = U_METAVERSION300; + ((U_WMRHEADER *) (record + off))->Size16w = U_SIZE_WMRHEADER/2; + } + return(record); +} + + +/** + \brief Allocate and construct a U_WMREOF record + \return pointer to the U_WMREOF record, or NULL on error. +*/ +char *U_WMREOF_set(void){ + return U_WMRCORE_NOARGS_set(U_WMR_EOF); +} + +/** + \brief Create and return a U_WMRSETBKCOLOR record + \return pointer to the U_WMRSETBKCOLOR record, or NULL on error + \param Color Background Color. +*/ +char *U_WMRSETBKCOLOR_set(U_COLORREF Color){ + return U_WMRCORE_1U16_CRF_2U16_set(U_WMR_SETBKCOLOR,NULL,Color,NULL,NULL); +} + +/** + \brief Create and return a U_WMRSETBKMODE record + \return pointer to the U_WMRSETBKMODE record, or NULL on error + \param Mode MixMode Enumeration +*/ +char *U_WMRSETBKMODE_set(uint16_t Mode){ + return U_WMRCORE_2U16_set(U_WMR_SETBKMODE, Mode, 0); +} + +/** + \brief Create and return a U_WMRSETMAPMODE record + \return pointer to the U_WMRSETMAPMODE record, or NULL on error + \param Mode MapMode Enumeration +*/ +char *U_WMRSETMAPMODE_set(uint16_t Mode){ + return U_WMRCORE_1U16_set(U_WMR_SETMAPMODE, Mode); +} + +/** + \brief Create and return a U_WMRSETROP2 record + \return pointer to the U_WMRSETROP2 record, or NULL on error + \param Mode Binary Raster Operation Enumeration +*/ +char *U_WMRSETROP2_set(uint16_t Mode){ + return U_WMRCORE_2U16_set(U_WMR_SETROP2, Mode, 0); +} + +/** + \brief Allocate and construct a U_WMRSETRELABS record + \return pointer to the U_WMRSETRELABS record, or NULL on error. +*/ +char *U_WMRSETRELABS_set(void){ + return U_WMRCORE_NOARGS_set(U_WMR_SETRELABS); +} + +/** + \brief Create and return a U_WMRSETPOLYFILLMODE record + \return pointer to the U_WMRSETPOLYFILLMODE record, or NULL on error + \param Mode PolyFillMode Enumeration +*/ +char *U_WMRSETPOLYFILLMODE_set(uint16_t Mode){ + return U_WMRCORE_2U16_set(U_WMR_SETPOLYFILLMODE, Mode, 0); +} + +/** + \brief Create and return a U_WMRSETSTRETCHBLTMODE record + \return pointer to the U_WMRSETSTRETCHBLTMODE record, or NULL on error + \param Mode StretchMode Enumeration +*/ +char *U_WMRSETSTRETCHBLTMODE_set(uint16_t Mode){ + return U_WMRCORE_2U16_set(U_WMR_SETSTRETCHBLTMODE, Mode, 0); +} + +/** + \brief Create and return a U_WMRSETTEXTCHAREXTRA record + \return pointer to the U_WMRSETTEXTCHAREXTRA record, or NULL on error + \param Mode Extra space in logical units to add to each character +*/ +char *U_WMRSETTEXTCHAREXTRA_set(uint16_t Mode){ + return U_WMRCORE_1U16_set(U_WMR_SETTEXTCHAREXTRA, Mode); +} + +/** + \brief Create and return a U_WMRSETTEXTCOLOR record + \return pointer to the U_WMRSETTEXTCOLOR record, or NULL on error + \param Color Text Color. +*/ +char *U_WMRSETTEXTCOLOR_set(U_COLORREF Color){ + return U_WMRCORE_1U16_CRF_2U16_set(U_WMR_SETTEXTCOLOR,NULL,Color,NULL,NULL); +} + +/** + \brief Create and return a U_WMRSETTEXTJUSTIFICATION record + \return pointer to the U_WMRSETTEXTJUSTIFICATION record, or NULL on error + \param Count Number of space characters in the line. + \param Extra Number of extra space characters to add to the line. +*/ +char *U_WMRSETTEXTJUSTIFICATION_set(uint16_t Count, uint16_t Extra){ + return U_WMRCORE_2U16_set(U_WMR_SETBKMODE, Count, Extra); +} + +/** + \brief Create and return a U_WMRSETWINDOWORG record + \return pointer to the U_WMRSETWINDOWORG record, or NULL on error + \param coord Window Origin. +*/ +char *U_WMRSETWINDOWORG_set(U_POINT16 coord){ + return U_WMRCORE_2U16_set(U_WMR_SETWINDOWORG, U_U16(coord.y), U_U16(coord.x)); +} + +/** + \brief Create and return a U_WMRSETWINDOWEXT record + \return pointer to the U_WMRSETWINDOWEXT record, or NULL on error + \param extent Window Extent. +*/ +char *U_WMRSETWINDOWEXT_set(U_POINT16 extent){ + return U_WMRCORE_2U16_set(U_WMR_SETWINDOWEXT, U_U16(extent.y), U_U16(extent.x)); +} + +/** + \brief Create and return a U_WMRSETVIEWPORTORG record + \return pointer to the U_WMRSETVIEWPORTORG record, or NULL on error + \param coord Viewport Origin. +*/ +char *U_WMRSETVIEWPORTORG_set(U_POINT16 coord){ + return U_WMRCORE_2U16_set(U_WMR_SETVIEWPORTORG, U_U16(coord.y), U_U16(coord.x)); +} + +/** + \brief Create and return a U_WMRSETVIEWPORTEXT record + \return pointer to the U_WMRSETVIEWPORTEXT record, or NULL on error + \param extent Viewport Extent. +*/ +char *U_WMRSETVIEWPORTEXT_set(U_POINT16 extent){ + return U_WMRCORE_2U16_set(U_WMR_SETWINDOWEXT, U_U16(extent.y), U_U16(extent.x)); +} + +/** + \brief Create and return a U_WMROFFSETWINDOWORG record + \return pointer to the U_WMROFFSETWINDOWORG record, or NULL on error + \param offset Window offset in device units. +*/ +char *U_WMROFFSETWINDOWORG_set(U_POINT16 offset){ + return U_WMRCORE_2U16_set(U_WMR_OFFSETWINDOWORG, U_U16(offset.y), U_U16(offset.x)); +} + +/** + \brief Create and return a U_WMRSCALEWINDOWEXT record + \return pointer to the U_WMRSCALEWINDOWEXT record, or NULL on error + \param Denom {X,Y} denominators. + \param Num {X,Y} numerators. +*/ +char *U_WMRSCALEWINDOWEXT_set(U_POINT16 Denom, U_POINT16 Num){ + return U_WMRCORE_4U16_set(U_WMR_SCALEWINDOWEXT, U_U16(Denom.y), U_U16(Num.y), U_U16(Denom.x), U_U16(Num.x)); +} + +/** + \brief Create and return a U_WMROFFSETVIEWPORTORG record + \return pointer to the U_WMROFFSETVIEWPORTORG record, or NULL on error + \param offset Viewport offset in device units. +*/ +char *U_WMROFFSETVIEWPORTORG_set(U_POINT16 offset){ + return U_WMRCORE_2U16_set(U_WMR_OFFSETVIEWPORTORG, U_U16(offset.y), U_U16(offset.x)); +} + +/** + \brief Create and return a U_WMRSCALEVIEWPORTEXT record + \return pointer to the U_WMRSCALEVIEWPORTEXT record, or NULL on error + \param Denom {X,Y} denominators. + \param Num {X,Y} numerators. +*/ +char *U_WMRSCALEVIEWPORTEXT_set(U_POINT16 Denom, U_POINT16 Num){ + return U_WMRCORE_4U16_set(U_WMR_SCALEVIEWPORTEXT, U_U16(Denom.y), U_U16(Num.y), U_U16(Denom.x), U_U16(Num.x)); +} + +/** + \brief Create and return a U_WMRLINETO record + \return pointer to the U_WMRLINETO record, or NULL on error + \param coord Draw line to {X,Y}. +*/ +char *U_WMRLINETO_set(U_POINT16 coord){ + return U_WMRCORE_2U16_set(U_WMR_LINETO, U_U16(coord.y), U_U16(coord.x)); +} + +/** + \brief Create and return a U_WMRMOVETO record + \return pointer to the U_WMRMOVETO record, or NULL on error + \param coord Move to {X,Y}. +*/ +char *U_WMRMOVETO_set(U_POINT16 coord){ + return U_WMRCORE_2U16_set(U_WMR_MOVETO, U_U16(coord.y), U_U16(coord.x)); +} + +/** + \brief Create and return a U_WMREXCLUDECLIPRECT record + \return pointer to the U_WMREXCLUDECLIPRECT record, or NULL on error + \param rect Exclude rect from clipping region. +*/ +char *U_WMREXCLUDECLIPRECT_set(U_RECT16 rect){ + return U_WMRCORE_4U16_set( + U_WMR_EXCLUDECLIPRECT, + U_U16(rect.bottom), + U_U16(rect.right), + U_U16(rect.top), + U_U16(rect.left) + ); +} + +/** + \brief Create and return a U_WMRINTERSECTCLIPRECT record + \return pointer to the U_WMRINTERSECTCLIPRECT record, or NULL on error + \param rect Clipping region is intersection of existing clipping region with rect. +*/ +char *U_WMRINTERSECTCLIPRECT_set(U_RECT16 rect){ + return U_WMRCORE_4U16_set( + U_WMR_INTERSECTCLIPRECT, + U_U16(rect.bottom), + U_U16(rect.right), + U_U16(rect.top), + U_U16(rect.left) + ); +} + +/** + \brief Create and return a U_WMRARC record + \return pointer to the U_WMRARC record, or NULL on error + \param StartArc Start of Arc + \param EndArc End of Arc + \param rect Bounding rectangle. +*/ +char *U_WMRARC_set(U_POINT16 StartArc, U_POINT16 EndArc, U_RECT16 rect){ + return U_WMRCORE_8U16_set( + U_WMR_ARC, + U_U16(EndArc.y), + U_U16(EndArc.x), + U_U16(StartArc.y), + U_U16(StartArc.x), + U_U16(rect.bottom), + U_U16(rect.right), + U_U16(rect.top), + U_U16(rect.left) + ); +} + +/** + \brief Create and return a U_WMRELLIPSE record + \return pointer to the U_WMRELLIPSE record, or NULL on error + \param rect Bounding rectangle for Ellipse. +*/ +char *U_WMRELLIPSE_set(U_RECT16 rect){ + return U_WMRCORE_4U16_set( + U_WMR_ELLIPSE, + U_U16(rect.bottom), + U_U16(rect.right), + U_U16(rect.top), + U_U16(rect.left) + ); +} + +/** + \brief Create and return a U_WMRFLOODFILL record + \return pointer to the U_WMRFLOODFILL record, or NULL on error + \param Mode FloodFill Enumeration. + \param Color Color to Fill with. + \param coord Location to start fill. +*/ +char *U_WMRFLOODFILL_set(uint16_t Mode, U_COLORREF Color, U_POINT16 coord){ + return U_WMRCORE_1U16_CRF_2U16_set( + U_WMR_FLOODFILL, + &Mode, + Color, + U_P16(coord.y), + U_P16(coord.x) + ); +} + +/** + \brief Create and return a U_WMRPIE record + \return pointer to the U_WMRPIE record, or NULL on error + \param Radial1 Start of Pie + \param Radial2 End of Pie + \param rect Bounding rectangle. +*/ +char *U_WMRPIE_set(U_POINT16 Radial1, U_POINT16 Radial2, U_RECT16 rect){ + return U_WMRCORE_8U16_set( + U_WMR_PIE, + U_U16(Radial2.y), + U_U16(Radial2.x), + U_U16(Radial1.y), + U_U16(Radial1.x), + U_U16(rect.bottom), + U_U16(rect.right), + U_U16(rect.top), + U_U16(rect.left) + ); +} + +/** + \brief Create and return a U_WMRRECTANGLE record + \return pointer to the U_WMRRECTANGLE record, or NULL on error + \param rect Boundaries. +*/ +char *U_WMRRECTANGLE_set(U_RECT16 rect){ + return U_WMRCORE_4U16_set( + U_WMR_RECTANGLE, + U_U16(rect.bottom), + U_U16(rect.right), + U_U16(rect.top), + U_U16(rect.left) + ); +} + +/** + \brief Create and return a U_WMRROUNDRECT record + \return pointer to the U_WMRROUNDRECT record, or NULL on error + \param Width Horizontal rounding length. + \param Height Vertical rounding length. + \param rect Boundaries. +*/ +char *U_WMRROUNDRECT_set(int16_t Width, int16_t Height, U_RECT16 rect){ + return U_WMRCORE_6U16_set( + U_WMR_ROUNDRECT, + U_U16(Height), + U_U16(Width), + U_U16(rect.bottom), + U_U16(rect.right), + U_U16(rect.top), + U_U16(rect.left) + ); +} + +/** + \brief Allocate and construct a U_WMRPATBLT record. + \return pointer to the U_WMRPATBLT record, or NULL on error. + \param Dst Destination UL corner in logical units + \param cwh W & H for Dst and Src in logical units + \param dwRop3 RasterOPeration Enumeration +*/ +char *U_WMRPATBLT_set( + U_POINT16 Dst, + U_POINT16 cwh, + uint32_t dwRop3 + ){ + char *record=NULL; + uint32_t irecsize; + U_WMRPATBLT *pmr; + + irecsize = U_SIZE_WMRPATBLT; + record = malloc(irecsize); + if(record){ + U_WMRCORE_SETRECHEAD(record,irecsize,U_WMR_PATBLT); + pmr = (U_WMRPATBLT *) record; + memcpy(pmr->rop3w, &dwRop3, 4); + pmr->Height = cwh.y; + pmr->Width = cwh.x; + pmr->yDst = Dst.y; + pmr->xDst = Dst.x; + } + return(record); +} + +/** + \brief Allocate and construct a U_WMRSAVEDC record + \return pointer to the U_WMRSAVEDC record, or NULL on error. +*/ +char *U_WMRSAVEDC_set(void){ + return U_WMRCORE_NOARGS_set(U_WMR_SAVEDC); +} + +/** + \brief Allocate and construct a U_WMRSETPIXEL record + \return pointer to the U_WMRSETPIXEL record, or NULL on error. + \param Color U_COLORREF color of the pixel + \param Coord U_POINT16 coordinates of the pixel +*/ +char *U_WMRSETPIXEL_set(U_COLORREF Color, U_POINT16 Coord){ + return U_WMRCORE_1U16_CRF_2U16_set( + U_WMR_SETPIXEL, + NULL, + Color, + U_P16(Coord.y), + U_P16(Coord.x) + ); +} + +/** + \brief Allocate and construct a U_WMROFFSETCLIPRGN record + \return pointer to the U_WMROFFSETCLIPRGN record, or NULL on error. + \param offset U_POINT16 x,y offset to apply to the clipping region. +*/ +char *U_WMROFFSETCLIPRGN_set(U_POINT16 offset){ + return U_WMRCORE_2U16_set(U_WMR_OFFSETCLIPRGN, U_U16(offset.y), U_U16(offset.x)); +} + +/** + \brief Allocate and construct a U_WMRTEXTOUT record. + \return pointer to the U_WMRTEXTOUT record, or NULL on error. + \param Dst Destinationin logical units + \param string Null terminated string to write. The terminator is NOT placed in the record! +*/ +char *U_WMRTEXTOUT_set(U_POINT16 Dst, char *string){ + char *record=NULL; + uint32_t irecsize,off; + int L2; + int16_t Length; + irecsize = 2 + U_SIZE_METARECORD + 4; /* core + length + Dst */ + Length = strlen(string); + L2 = ( Length & 1 ? Length + 1 : Length); + irecsize += L2; + record = malloc(irecsize); + if(record){ + U_WMRCORE_SETRECHEAD(record,irecsize,U_WMR_TEXTOUT); + off = U_SIZE_METARECORD; + memcpy(record+off,&Length,2); off+=2; + memcpy(record+off,string,Length); off+=Length; + if(Length!=L2){ + memset(record+off,0,1); off+=1; + } + memcpy(record+off,&Dst.y,2); off+=2; + memcpy(record+off,&Dst.x,2); + } + return(record); +} + +/** + \brief Allocate and construct a U_WMRBITBLT record. + Note that unlike U_EMRBITBLT there is no scaling available - the Src and Dst + rectangles must be the same size. + \return pointer to the U_WMRBITBLT record, or NULL on error. + \param Dst Destination UL corner in logical units + \param cwh W & H for Dst and Src in logical units + \param Src Source UL corner in logical units + \param dwRop3 RasterOPeration Enumeration + \param Bm16 (Optional) bitmap16 object +*/ +char *U_WMRBITBLT_set( + U_POINT16 Dst, + U_POINT16 cwh, + U_POINT16 Src, + uint32_t dwRop3, + const U_BITMAP16 *Bm16 + ){ + char *record=NULL; + uint32_t irecsize; + int cbBm16,cbBm164,off; + U_WMRBITBLT_PX *pmr_px; + U_WMRBITBLT_NOPX *pmr_nopx; + + if(Bm16){ + cbBm16 = U_SIZE_BITMAP16 + (((Bm16->Width * Bm16->BitsPixel + 15) >> 4) << 1) * Bm16->Height; + cbBm164 = UP4(cbBm16); + irecsize = U_SIZE_WMRBITBLT_PX + cbBm164; + record = malloc(irecsize); + if(record){ + U_WMRCORE_SETRECHEAD(record,irecsize,U_WMR_BITBLT); + pmr_px = (U_WMRBITBLT_PX *) record; + memcpy(pmr_px->rop3w, &dwRop3, 4); + pmr_px->ySrc = Src.y; + pmr_px->xSrc = Src.x; + pmr_px->Height = cwh.y; + pmr_px->Width = cwh.x; + pmr_px->yDst = Dst.y; + pmr_px->xDst = Dst.x; + off = U_SIZE_WMRBITBLT_PX; + memcpy(record + off, Bm16, cbBm16); off += cbBm16; + if(cbBm164 - cbBm16)memset(record+off,0,cbBm164 - cbBm16); + } + } + else { + irecsize = U_SIZE_WMRBITBLT_NOPX; + record = malloc(irecsize); + if(record){ + U_WMRCORE_SETRECHEAD(record,irecsize,U_WMR_BITBLT); + pmr_nopx = (U_WMRBITBLT_NOPX *) record; + memcpy(pmr_nopx->rop3w, &dwRop3, 4); + pmr_nopx->ySrc = Src.y; + pmr_nopx->xSrc = Src.x; + pmr_nopx->Height = cwh.y; + pmr_nopx->Width = cwh.x; + pmr_nopx->ignore = 0; + pmr_nopx->yDst = Dst.y; + pmr_nopx->xDst = Dst.x; + } + } + return(record); +} + +/** + \brief Allocate and construct a U_WMRSTRETCHBLT record. + \return pointer to the U_WMRSTRETCHBLT record, or NULL on error. + \param Dst Destination UL corner in logical units + \param cDst Destination W & H in logical units + \param Src Source UL corner in logical units + \param cSrc Source W & H in logical units + \param dwRop3 RasterOPeration Enumeration + \param Bm16 (Optional) bitmap16 object +*/ +char *U_WMRSTRETCHBLT_set( + U_POINT16 Dst, + U_POINT16 cDst, + U_POINT16 Src, + U_POINT16 cSrc, + uint32_t dwRop3, + const U_BITMAP16 *Bm16 + ){ + char *record=NULL; + uint32_t irecsize; + int cbBm16,cbBm164,off; + U_WMRSTRETCHBLT_PX *pmr_px; + U_WMRSTRETCHBLT_NOPX *pmr_nopx; + + if(Bm16){ + cbBm16 = U_SIZE_BITMAP16 + (((Bm16->Width * Bm16->BitsPixel + 15) >> 4) << 1) * Bm16->Height; + cbBm164 = UP4(cbBm16); + irecsize = U_SIZE_WMRSTRETCHBLT_PX + cbBm164; + record = malloc(irecsize); + if(record){ + U_WMRCORE_SETRECHEAD(record,irecsize,U_WMR_STRETCHBLT); + pmr_px = (U_WMRSTRETCHBLT_PX *) record; + memcpy(pmr_px->rop3w, &dwRop3, 4); + pmr_px->hSrc = cSrc.y; + pmr_px->wSrc = cSrc.x; + pmr_px->ySrc = Src.y; + pmr_px->xSrc = Src.x; + pmr_px->hDst = cDst.y; + pmr_px->wDst = cDst.x; + pmr_px->yDst = Dst.y; + pmr_px->xDst = Dst.x; + off = U_SIZE_WMRSTRETCHBLT_PX; + memcpy(record + off, Bm16, cbBm16); off += cbBm16; + if(cbBm164 - cbBm16)memset(record+off,0,cbBm164 - cbBm16); + } + } + else { + irecsize = U_SIZE_WMRSTRETCHBLT_NOPX; + record = malloc(irecsize); + if(record){ + U_WMRCORE_SETRECHEAD(record,irecsize,U_WMR_STRETCHBLT); + pmr_nopx = (U_WMRSTRETCHBLT_NOPX *) record; + memcpy(pmr_nopx->rop3w, &dwRop3, 4); + pmr_nopx->hSrc = cSrc.y; + pmr_nopx->wSrc = cSrc.x; + pmr_nopx->ySrc = Src.y; + pmr_nopx->xSrc = Src.x; + pmr_nopx->ignore = 0; + pmr_nopx->hDst = cDst.y; + pmr_nopx->wDst = cDst.x; + pmr_nopx->yDst = Dst.y; + pmr_nopx->xDst = Dst.x; + } + } + return(record); +} + +/** + \brief Allocate and construct a U_WMRPOLYGON record. + \return pointer to the U_WMRPOLYGON record, or NULL on error. + \param Length Number of points in the Polygon + \param Data Array of Length points +*/ +char *U_WMRPOLYGON_set(uint16_t Length, const U_POINT16 *Data){ + return U_WMRCORE_2U16_N16_set(U_WMR_POLYGON, NULL, &Length, 2*Length, Data); +} + +/** + \brief Allocate and construct a U_WMRPOLYLINE record. + \return pointer to the U_WMRPOLYLINE record, or NULL on error. + \param Length Number of points in the Polyline + \param Data Array of Length points +*/ +char *U_WMRPOLYLINE_set(uint16_t Length, const U_POINT16 *Data){ + return U_WMRCORE_2U16_N16_set(U_WMR_POLYLINE, NULL, &Length, 2*Length, Data); +} + +/** + \brief Allocate and construct a U_WMRESCAPE record. + WARNING! Only three Escape record types are fully supported: SETLINECAP, SETLINEJOIN, SETMITERLIMIT. + Even these should not be set here directly, instead use the wsetlinecap_set(), wsetlinejoin_set(), + or wsetmiterlimit_set() functions. + Escape records created with this function, with the exception of the three named above, will not have + the byte orders in Data adjusted automatically. The user code must set Data to be little endian no + matter what the endianness of the current platform where the user code is running. + \return pointer to the U_WMRESCAPE record, or NULL on error. + \param Escape Escape function + \param Length Bytes in the Data + \param Data Array of Length bytes +*/ +char *U_WMRESCAPE_set(uint16_t Escape, uint16_t Length, const void *Data){ + return U_WMRCORE_2U16_N16_set(U_WMR_ESCAPE, &Escape, &Length, Length/2, Data); +} + +/** + \brief Allocate and construct a U_WMRRESTOREDC record + \return pointer to the U_WMRRESTOREDC record, or NULL on error. + \param DC Drawing Context to restore. (negative is relative to current, positive is absolute) +*/ +char *U_WMRRESTOREDC_set(int16_t DC){ + return U_WMRCORE_1U16_set(U_WMR_RESTOREDC, DC); +} + +/** + \brief Allocate and construct a U_WMRFILLREGION record. + \return pointer to the U_WMRFILLREGION record, or NULL on error. + \param Region Region to fill + \param Brush Brush to fill with +*/ +char *U_WMRFILLREGION_set(uint16_t Region, uint16_t Brush){ + return U_WMRCORE_2U16_set(U_WMR_FILLREGION, Region, Brush); +} + +/** + \brief Allocate and construct a U_WMRFRAMEREGION record. + \return pointer to the U_WMRFRAMEREGION record, or NULL on error. + \param Region Index of region to frame in object table + \param Brush Index of brush to use in frame in object table + \param Height in logical units (of frame) + \param Width in logical units (of frame) +*/ +char *U_WMRFRAMEREGION_set(uint16_t Region, uint16_t Brush, int16_t Height, int16_t Width){ + return U_WMRCORE_4U16_set(U_WMR_FRAMEREGION, Region, Brush, U_U16(Height), U_U16(Width)); +} + +/** + \brief Allocate and construct a U_WMRINVERTREGION record. + \return pointer to the U_WMRINVERTREGION record, or NULL on error. + \param Region Index of region to invert. +*/ +char *U_WMRINVERTREGION_set(uint16_t Region){ + return U_WMRCORE_1U16_set(U_WMR_INVERTREGION, Region); +} + +/** + \brief Allocate and construct a U_WMRPAINTREGION record. + \return pointer to the U_WMRPAINTREGION record, or NULL on error. + \param Region Index of region to paint with the current Brush. +*/ +char *U_WMRPAINTREGION_set(uint16_t Region){ + return U_WMRCORE_1U16_set(U_WMR_PAINTREGION, Region); +} + +/** + \brief Allocate and construct a U_WMRSELECTCLIPREGION record. + \return pointer to the U_WMRSELECTCLIPREGION record, or NULL on error. + \param Region Index of region to become clipping region.. +*/ +char *U_WMRSELECTCLIPREGION_set(uint16_t Region){ + return U_WMRCORE_1U16_set(U_WMR_SELECTCLIPREGION, Region); +} + +/** + \brief Allocate and construct a U_WMRSELECTOBJECT record. + \return pointer to the U_WMRSELECTOBJECT record, or NULL on error. + \param object Index of object which is made active. +*/ +char *U_WMRSELECTOBJECT_set(uint16_t object){ + return U_WMRCORE_1U16_set(U_WMR_SELECTOBJECT, object); +} + +/** + \brief Allocate and construct a U_WMRSETTEXTALIGN record. + \return pointer to the U_WMRSETTEXTALIGN record, or NULL on error. + \param Mode TextAlignment Enumeration. +*/ +char *U_WMRSETTEXTALIGN_set(uint16_t Mode){ + return U_WMRCORE_2U16_set(U_WMR_SETTEXTALIGN, Mode, 0); +} + +/** in GDI and Wine, not in WMF manual.. +*/ + char *U_WMRDRAWTEXT_set(void){ + return U_WMRCORENONE_set("U_WMRDRAWTEXT"); +} + +/** + \brief Create and return a U_WMRCHORD record + \return pointer to the U_WMRCHORD record, or NULL on error + \param Radial1 Start of Chord + \param Radial2 End of Chord + \param rect Bounding rectangle. +*/ +char *U_WMRCHORD_set(U_POINT16 Radial1, U_POINT16 Radial2, U_RECT16 rect){ + return U_WMRCORE_8U16_set( + U_WMR_CHORD, + U_U16(Radial2.y), + U_U16(Radial2.x), + U_U16(Radial1.y), + U_U16(Radial1.x), + U_U16(rect.bottom), + U_U16(rect.right), + U_U16(rect.top), + U_U16(rect.left) + ); +} + +/** + \brief Allocate and construct a U_WMRSETMAPPERFLAGS record. + \return pointer to the U_WMRSETMAPPERFLAGS record, or NULL on error. + \param Mode If 1 bit set font mapper selects only matching aspect fonts. +*/ +char *U_WMRSETMAPPERFLAGS_set(uint32_t Mode){ + return U_WMRCORE_2U16_set(U_WMR_SETMAPPERFLAGS, 0xFFFF & Mode, Mode>>16); +} + +/** + \brief Allocate and construct a U_WMREXTTEXTOUT record. + \return pointer to the U_WMREXTTEXTOUT record, or NULL on error. + \param Dst {X,Y} coordinates where the string is to be written. + \param Length Stringlength in bytes + \param Opts ExtTextOutOptions Flags + \param string String to write (Latin1 encoding) + \param dx Kerning information. Must have same number of entries as Length. + \param rect Used when when U_ETO_OPAQUE or U_ETO_CLIPPED bits are set in Opts +*/ +char *U_WMREXTTEXTOUT_set(U_POINT16 Dst, int16_t Length, uint16_t Opts, + const char *string, int16_t *dx, U_RECT16 rect){ + + char *record=NULL; + uint32_t irecsize,off; + int slen; + irecsize = U_SIZE_METARECORD + 8; /* 8 = y,x,Length,Opts*/ + slen = ( Length & 1 ? Length + 1 : Length); + irecsize += slen; + if(dx)irecsize += 2*Length; + if(Opts & (U_ETO_OPAQUE | U_ETO_CLIPPED)){ + irecsize += U_SIZE_RECT16; + } + record = malloc(irecsize); + if(record){ + U_WMRCORE_SETRECHEAD(record,irecsize,U_WMR_EXTTEXTOUT); + off = U_SIZE_METARECORD; + memcpy(record+off,&Dst.y,2); off+=2; + memcpy(record+off,&Dst.x,2); off+=2; + memcpy(record+off,&Length,2); off+=2; + memcpy(record+off,&Opts,2); off+=2; + if(Opts & (U_ETO_OPAQUE | U_ETO_CLIPPED)){ + memcpy(record+off,&rect.bottom,2); off+=2; + memcpy(record+off,&rect.right, 2); off+=2; + memcpy(record+off,&rect.top, 2); off+=2; + memcpy(record+off,&rect.left, 2); off+=2; + } + memcpy(record+off,string,strlen(string)); off+=Length; + if(Length!=slen){ + memset(record+off,0,1); off+=1; + } + if(dx){ + memcpy(record+off,dx,2*Length); + } + } + return(record); +} + +/** + \brief Allocate and construct a U_WMRSETDIBTODEV record + \return pointer to the U_WMRSETDIBTODEV record, or NULL on error. +*/ +char *U_WMRSETDIBTODEV_set(void){ + return U_WMRCORENONE_set("U_WMRSETDIBTODEV"); +} + +/** + \brief Allocate and construct a U_WMRSELECTPALETTE record + \return pointer to the U_WMRSELECTPALETTE record, or NULL on error. + \param Palette Index of Palette to make active. +*/ +char *U_WMRSELECTPALETTE_set(uint16_t Palette){ + return U_WMRCORE_1U16_set(U_WMR_SELECTPALETTE, Palette); +} + +/** + \brief Allocate and construct a U_WMRREALIZEPALETTE record + \return pointer to the U_WMRREALIZEPALETTE record, or NULL on error. +*/ +char *U_WMRREALIZEPALETTE_set(void){ + return U_WMRCORE_NOARGS_set(U_WMR_REALIZEPALETTE); +} + +/** + \brief Allocate and construct a U_WMRSETPALENTRIES record + \return pointer to the U_WMRSETPALENTRIES record, or NULL on error. + \param Palette Redefines a set of RGB values for the current active Palette. +*/ +char *U_WMRANIMATEPALETTE_set(U_PALETTE *Palette){ + return U_WMRCORE_PALETTE_set(U_WMR_ANIMATEPALETTE, Palette); +} + +/** + \brief Allocate and construct a U_WMRSETPALENTRIES record + \return pointer to the U_WMRSETPALENTRIES record, or NULL on error. + \param Palette Defines a set of RGB values for the current active Palette. +*/ +char *U_WMRSETPALENTRIES_set(const U_PALETTE *Palette){ + return U_WMRCORE_PALETTE_set(U_WMR_SETPALENTRIES, Palette); +} + +/** + \brief Allocate and construct a U_WMR_POLYPOLYGON record. + \return pointer to the U_WMR_POLYPOLYGON record, or NULL on error. + \param nPolys Number of elements in aPolyCounts + \param aPolyCounts Number of points in each poly (sequential) + \param Points array of points +*/ +char *U_WMRPOLYPOLYGON_set( + const uint16_t nPolys, + const uint16_t *aPolyCounts, + const U_POINT16 *Points + ){ + char *record; + uint32_t irecsize; + int i,cbPolys,cbPoints,off; + + cbPolys = sizeof(uint16_t)*nPolys; + for(i=cbPoints=0; i<nPolys; i++){ cbPoints += U_SIZE_POINT16*aPolyCounts[i]; } + + if(nPolys==0 || cbPoints==0)return(NULL); + + irecsize = U_SIZE_METARECORD + 2 + cbPolys + cbPoints; /* core WMR + nPolys + two array sizes in bytes */ + record = malloc(irecsize); + if(record){ + U_WMRCORE_SETRECHEAD(record,irecsize,U_WMR_POLYPOLYGON); + off = U_SIZE_METARECORD; + memcpy(record + off, &nPolys, 2); off+=2; + memcpy(record + off, aPolyCounts, cbPolys); off+=cbPolys; + memcpy(record + off, Points, cbPoints); + } + return(record); +} + +/** + \brief Allocate and construct a U_WMRRESIZEPALETTE record + \return pointer to the U_WMRRESIZEPALETTE record, or NULL on error. + \param Palette Changes the size of the currently active Palette. +*/ +char *U_WMRRESIZEPALETTE_set(uint16_t Palette){ + return U_WMRCORE_1U16_set(U_WMR_RESIZEPALETTE, Palette); +} + +//! \cond +char *U_WMR3A_set(void){ + return U_WMRCORENONE_set("U_WMR3A"); +} + +char *U_WMR3B_set(void){ + return U_WMRCORENONE_set("U_WMR3B"); +} + +char *U_WMR3C_set(void){ + return U_WMRCORENONE_set("U_WMR3C"); +} + +char *U_WMR3D_set(void){ + return U_WMRCORENONE_set("U_WMR3D"); +} + +char *U_WMR3E_set(void){ + return U_WMRCORENONE_set("U_WMR3E"); +} + +char *U_WMR3F_set(void){ + return U_WMRCORENONE_set("U_WMR3F"); +} +//! \endcond + +// U_WMRDIBBITBLT_set +/** + \brief Allocate and construct a U_WMRDIBITBLT record. + \return pointer to the U_WMRDIBITBLT record, or NULL on error. + \param Dst Destination UL corner in logical units + \param Src Source UL corner in logical units + \param cwh W & H in logical units of Src and Dst + \param dwRop3 RasterOPeration Enumeration + \param Bmi (Optional) bitmapbuffer (U_BITMAPINFO section) + \param cbPx Size in bytes of pixel array (row STRIDE * height, there may be some padding at the end of each row) + \param Px (Optional) bitmapbuffer (pixel array section ) +*/ +char *U_WMRDIBBITBLT_set( + U_POINT16 Dst, + U_POINT16 cwh, + U_POINT16 Src, + uint32_t dwRop3, + const U_BITMAPINFO *Bmi, + uint32_t cbPx, + const char *Px + ){ + char *record=NULL; + uint32_t irecsize; + int cbImage,cbImage4,cbBmi,off; + U_WMRDIBBITBLT_PX *pmr_px; + U_WMRDIBBITBLT_NOPX *pmr_nopx; + + + if(Px && Bmi){ + SET_CB_FROM_PXBMI(Px,Bmi,cbImage,cbImage4,cbBmi,cbPx); + irecsize = U_SIZE_WMRDIBBITBLT_PX + cbBmi + cbImage4; + record = malloc(irecsize); + if(record){ + U_WMRCORE_SETRECHEAD(record,irecsize,U_WMR_DIBBITBLT); + pmr_px = (U_WMRDIBBITBLT_PX *) record; + memcpy(pmr_px->rop3w, &dwRop3, 4); + pmr_px->ySrc = Src.y; + pmr_px->xSrc = Src.x; + pmr_px->Height = cwh.y; + pmr_px->Width = cwh.x; + pmr_px->yDst = Dst.y; + pmr_px->xDst = Dst.x; + off = U_SIZE_WMRDIBBITBLT_PX; + memcpy(record + off, Bmi, cbBmi); off += cbBmi; + memcpy(record + off, Px, cbPx); off += cbPx; + if(cbImage4 - cbImage)memset(record+off,0,cbImage4 - cbImage); + } + } + else if(!Px && !Bmi){ + irecsize = U_SIZE_WMRDIBBITBLT_NOPX; + record = malloc(irecsize); + if(record){ + U_WMRCORE_SETRECHEAD(record,irecsize,U_WMR_DIBBITBLT); + pmr_nopx = (U_WMRDIBBITBLT_NOPX *) record; + memcpy(pmr_nopx->rop3w, &dwRop3, 4); + pmr_nopx->ySrc = Src.y; + pmr_nopx->xSrc = Src.x; + pmr_nopx->ignore = 0; + pmr_nopx->Height = cwh.y; + pmr_nopx->Width = cwh.x; + pmr_nopx->yDst = Dst.y; + pmr_nopx->xDst = Dst.x; + } + } + return(record); +} + +/** + \brief Allocate and construct a U_WMRSTRETCHDIB record. + \return pointer to the U_WMRSTRETCHDIB record, or NULL on error. + \param Dst Destination UL corner in logical units + \param cDst Destination W & H in logical units + \param Src Source UL corner in logical units + \param cSrc Source W & H in logical units + \param dwRop3 RasterOPeration Enumeration + \param Bmi (Optional) bitmapbuffer (U_BITMAPINFO section) + \param cbPx Size in bytes of pixel array (row STRIDE * height, there may be some padding at the end of each row) + \param Px (Optional) bitmapbuffer (pixel array section ) +*/ +char *U_WMRDIBSTRETCHBLT_set( + U_POINT16 Dst, + U_POINT16 cDst, + U_POINT16 Src, + U_POINT16 cSrc, + uint32_t dwRop3, + const U_BITMAPINFO *Bmi, + uint32_t cbPx, + const char *Px + ){ + char *record=NULL; + uint32_t irecsize; + int cbImage,cbImage4,cbBmi,off; + U_WMRDIBSTRETCHBLT_PX *pmr_px; + U_WMRDIBSTRETCHBLT_NOPX *pmr_nopx; + if(Px && Bmi){ + SET_CB_FROM_PXBMI(Px,Bmi,cbImage,cbImage4,cbBmi,cbPx); + irecsize = U_SIZE_WMRDIBSTRETCHBLT_PX + cbBmi + cbImage4; + record = malloc(irecsize); + if(record){ + U_WMRCORE_SETRECHEAD(record,irecsize,U_WMR_DIBSTRETCHBLT); + pmr_px = (U_WMRDIBSTRETCHBLT_PX *) record; + memcpy(pmr_px->rop3w, &dwRop3, 4); + pmr_px->hSrc = cSrc.y; + pmr_px->wSrc = cSrc.x; + pmr_px->ySrc = Src.y; + pmr_px->xSrc = Src.x; + pmr_px->hDst = cDst.y; + pmr_px->wDst = cDst.x; + pmr_px->yDst = Dst.y; + pmr_px->xDst = Dst.x; + off = U_SIZE_WMRDIBSTRETCHBLT_PX; + memcpy(record + off, Bmi, cbBmi); off += cbBmi; + memcpy(record + off, Px, cbPx); off += cbPx; + if(cbImage4 - cbImage)memset(record+off,0,cbImage4 - cbImage); + } + } + else if(!Px && !Bmi){ + irecsize = U_SIZE_WMRDIBSTRETCHBLT_NOPX; + record = malloc(irecsize); + if(record){ + U_WMRCORE_SETRECHEAD(record,irecsize,U_WMR_DIBSTRETCHBLT); + pmr_nopx = (U_WMRDIBSTRETCHBLT_NOPX *) record; + memcpy(pmr_nopx->rop3w, &dwRop3, 4); + pmr_nopx->hSrc = cSrc.y; + pmr_nopx->wSrc = cSrc.x; + pmr_nopx->ySrc = Src.y; + pmr_nopx->xSrc = Src.x; + pmr_nopx->ignore = 0; + pmr_nopx->hDst = cDst.y; + pmr_nopx->wDst = cDst.x; + pmr_nopx->yDst = Dst.y; + pmr_nopx->xDst = Dst.x; + } + } + return(record); +} + +/** + \brief Allocate and construct a U_WMRDIBCREATEPATTERNBRUSH record. + Accepts an image as either a DIB (Bmi/CbPx/Px defined) or a Bitmap16 (Bm16 defined). + \return pointer to the U_WMRDIBCREATEPATTERNBRUSH record, or NULL on error. + \param Style BrushStyle Enumeration + \param iUsage DIBcolors Enumeration + \param Bm16 pointer to U_BITMAP16 object for Style U_BS_PATTERN only + \param cbPx Size in bytes of pixel array (row stride * height, there may be some padding at the end of each row), for use with Bmi + \param Px bitmap buffer, for use with Bmi + \param Bmi pointer to U_BITMAPINFO for all Style OTHER than U_BS_PATTERN +*/ +char *U_WMRDIBCREATEPATTERNBRUSH_set( + const uint16_t Style, + const uint16_t iUsage, + const U_BITMAPINFO *Bmi, + const uint32_t cbPx, + const char *Px, + const U_BITMAP16 *Bm16 + ){ + char *record=NULL; + uint32_t irecsize; + int cbImage,cbImage4,cbBmi,cbBm16,cbBm164,off; + + if(Style==U_BS_PATTERN && Bm16){ + cbBm16 = U_SIZE_BITMAP16 + (((Bm16->Width * Bm16->BitsPixel + 15) >> 4) << 1) * Bm16->Height; + cbBm164 = UP4(cbBm16); + irecsize = U_SIZE_WMRDIBCREATEPATTERNBRUSH + cbBm164; + record = malloc(irecsize); + if(record){ + U_WMRCORE_SETRECHEAD(record,irecsize,U_WMR_DIBCREATEPATTERNBRUSH); + off = U_SIZE_METARECORD; + memcpy(record + off, &Style, 2); off+=2; + memcpy(record + off, &iUsage, 2); off+=2; + memcpy(record + off, Bm16, cbBm16); off += cbBm16; + if(cbBm164 - cbBm16)memset(record+off,0,cbBm164 - cbBm16); + } + } + else if(Bmi && Px){ + SET_CB_FROM_PXBMI(Px,Bmi,cbImage,cbImage4,cbBmi,cbPx); + irecsize = U_SIZE_WMRDIBCREATEPATTERNBRUSH + cbBmi + cbImage4; + record = malloc(irecsize); + if(record){ + U_WMRCORE_SETRECHEAD(record,irecsize,U_WMR_DIBCREATEPATTERNBRUSH); + off = U_SIZE_METARECORD; + memcpy(record + off, &Style, 2); off+=2; + memcpy(record + off, &iUsage, 2); off+=2; + memcpy(record + off, Bmi, cbBmi); off += cbBmi; + memcpy(record + off, Px, cbImage); off += cbImage; + if(cbImage4 - cbImage)memset(record + off, 0, cbImage4 - cbImage); + } + } + return(record); +} + +/** + \brief Allocate and construct a U_WMRSTRETCHDIB record. + \return pointer to the U_WMRSTRETCHDIB record, or NULL on error. + \param Dst Destination UL corner in logical units + \param cDst Destination W & H in logical units + \param Src Source UL corner in logical units + \param cSrc Source W & H in logical units + \param cUsage DIBColors Enumeration + \param dwRop3 RasterOPeration Enumeration + \param Bmi (Optional) bitmapbuffer (U_BITMAPINFO section) + \param cbPx Size in bytes of pixel array (row STRIDE * height, there may be some padding at the end of each row) + \param Px (Optional) bitmapbuffer (pixel array section ) +*/ +char *U_WMRSTRETCHDIB_set( + U_POINT16 Dst, + U_POINT16 cDst, + U_POINT16 Src, + U_POINT16 cSrc, + uint16_t cUsage, + uint32_t dwRop3, + const U_BITMAPINFO *Bmi, + uint32_t cbPx, + const char *Px + ){ + char *record; + uint32_t irecsize; + int cbImage,cbImage4,cbBmi,off; + U_WMRSTRETCHDIB *pmr; + + SET_CB_FROM_PXBMI(Px,Bmi,cbImage,cbImage4,cbBmi,cbPx); + + irecsize = U_SIZE_WMRSTRETCHDIB + cbBmi + cbImage4; + record = malloc(irecsize); + if(record){ + U_WMRCORE_SETRECHEAD(record,irecsize,U_WMR_STRETCHDIB); + pmr = (U_WMRSTRETCHDIB *) record; + memcpy(pmr->rop3w, &dwRop3, 4); + pmr->cUsage = cUsage; + pmr->hSrc = cSrc.y; + pmr->wSrc = cSrc.x; + pmr->ySrc = Src.y; + pmr->xSrc = Src.x; + pmr->hDst = cDst.y; + pmr->wDst = cDst.x; + pmr->yDst = Dst.y; + pmr->xDst = Dst.x; + off = U_SIZE_WMRSTRETCHDIB; + if(cbBmi){ + memcpy(record + off, Bmi, cbBmi); off += cbBmi; + memcpy(record + off, Px, cbPx); off += cbPx; + if(cbImage4 - cbImage)memset(record+off,0,cbImage4 - cbImage); + } + } + return(record); +} + +//! \cond +char *U_WMR44_set(void){ + return U_WMRCORENONE_set("U_WMR44"); +} + +char *U_WMR45_set(void){ + return U_WMRCORENONE_set("U_WMR45"); +} + +char *U_WMR46_set(void){ + return U_WMRCORENONE_set("U_WMR46"); +} + +char *U_WMR47_set(void){ + return U_WMRCORENONE_set("U_WMR47"); +} +//! \endcond + +/** + \brief Create and return a U_WMREXTFLOODFILL record + \return pointer to the U_WMREXTFLOODFILL record, or NULL on error + \param Mode FloodFill Enumeration. + \param Color Color to Fill with. + \param coord Location to start fill. +*/ +char *U_WMREXTFLOODFILL_set(uint16_t Mode, U_COLORREF Color, U_POINT16 coord){ + return U_WMRCORE_1U16_CRF_2U16_set( + U_WMR_EXTFLOODFILL, + &Mode, + Color, + U_P16(coord.y), + U_P16(coord.x) + ); +} + +//! \cond +char *U_WMR49_set(void){ + return U_WMRCORENONE_set("U_WMR49"); +} + +char *U_WMR4A_set(void){ + return U_WMRCORENONE_set("U_WMR4A"); +} + +char *U_WMR4B_set(void){ + return U_WMRCORENONE_set("U_WMR4B"); +} + +char *U_WMR4C_set(void){ + return U_WMRCORENONE_set("U_WMRRESETDOC"); +} + +char *U_WMR4D_set(void){ + return U_WMRCORENONE_set("U_WMRSTARTDOC"); +} + +char *U_WMR4E_set(void){ + return U_WMRCORENONE_set("U_WMR4E"); +} + +char *U_WMR4F_set(void){ + return U_WMRCORENONE_set("U_WMRSTARTPAGE"); +} + +char *U_WMR50_set(void){ + return U_WMRCORENONE_set("U_WMRENDPAGE"); +} + +char *U_WMR51_set(void){ + return U_WMRCORENONE_set("U_WMR51"); +} + +char *U_WMRABORTDOC_set(void){ + return U_WMRCORENONE_set("U_WMRABORTDOC"); +} + +char *U_WMR53_set(void){ + return U_WMRCORENONE_set("U_WMR53"); +} + +char *U_WMR54_set(void){ + return U_WMRCORENONE_set("U_WMR54"); +} + +char *U_WMR55_set(void){ + return U_WMRCORENONE_set("U_WMR55"); +} + +char *U_WMR56_set(void){ + return U_WMRCORENONE_set("U_WMR56"); +} + +char *U_WMR57_set(void){ + return U_WMRCORENONE_set("U_WMR57"); +} + +char *U_WMR58_set(void){ + return U_WMRCORENONE_set("U_WMR58"); +} + +char *U_WMR59_set(void){ + return U_WMRCORENONE_set("U_WMR59"); +} + +char *U_WMR5A_set(void){ + return U_WMRCORENONE_set("U_WMR5A"); +} + +char *U_WMR5B_set(void){ + return U_WMRCORENONE_set("U_WMR5B"); +} + +char *U_WMR5C_set(void){ + return U_WMRCORENONE_set("U_WMR5C"); +} + +char *U_WMR5D_set(void){ + return U_WMRCORENONE_set("U_WMR5D"); +} + +char *U_WMR5E_set(void){ + return U_WMRCORENONE_set("U_WMRENDDOC"); +} + +char *U_WMR5F_set(void){ + return U_WMRCORENONE_set("U_WMR5F"); +} + +char *U_WMR60_set(void){ + return U_WMRCORENONE_set("U_WMR60"); +} + +char *U_WMR61_set(void){ + return U_WMRCORENONE_set("U_WMR61"); +} + +char *U_WMR62_set(void){ + return U_WMRCORENONE_set("U_WMR62"); +} + +char *U_WMR63_set(void){ + return U_WMRCORENONE_set("U_WMR63"); +} + +char *U_WMR64_set(void){ + return U_WMRCORENONE_set("U_WMR64"); +} + +char *U_WMR65_set(void){ + return U_WMRCORENONE_set("U_WMR65"); +} + +char *U_WMR66_set(void){ + return U_WMRCORENONE_set("U_WMR66"); +} + +char *U_WMR67_set(void){ + return U_WMRCORENONE_set("U_WMR67"); +} + +char *U_WMR68_set(void){ + return U_WMRCORENONE_set("U_WMR68"); +} + +char *U_WMR69_set(void){ + return U_WMRCORENONE_set("U_WMR69"); +} + +char *U_WMR6A_set(void){ + return U_WMRCORENONE_set("U_WMR6A"); +} + +char *U_WMR6B_set(void){ + return U_WMRCORENONE_set("U_WMR6B"); +} + +char *U_WMR6C_set(void){ + return U_WMRCORENONE_set("U_WMR6C"); +} + +char *U_WMR6D_set(void){ + return U_WMRCORENONE_set("U_WMR6D"); +} + +char *U_WMR6E_set(void){ + return U_WMRCORENONE_set("U_WMR6E"); +} + +char *U_WMR6F_set(void){ + return U_WMRCORENONE_set("U_WMR6F"); +} + +char *U_WMR70_set(void){ + return U_WMRCORENONE_set("U_WMR70"); +} + +char *U_WMR71_set(void){ + return U_WMRCORENONE_set("U_WMR71"); +} + +char *U_WMR72_set(void){ + return U_WMRCORENONE_set("U_WMR72"); +} + +char *U_WMR73_set(void){ + return U_WMRCORENONE_set("U_WMR73"); +} + +char *U_WMR74_set(void){ + return U_WMRCORENONE_set("U_WMR74"); +} + +char *U_WMR75_set(void){ + return U_WMRCORENONE_set("U_WMR75"); +} + +char *U_WMR76_set(void){ + return U_WMRCORENONE_set("U_WMR76"); +} + +char *U_WMR77_set(void){ + return U_WMRCORENONE_set("U_WMR77"); +} + +char *U_WMR78_set(void){ + return U_WMRCORENONE_set("U_WMR78"); +} + +char *U_WMR79_set(void){ + return U_WMRCORENONE_set("U_WMR79"); +} + +char *U_WMR7A_set(void){ + return U_WMRCORENONE_set("U_WMR7A"); +} + +char *U_WMR7B_set(void){ + return U_WMRCORENONE_set("U_WMR7B"); +} + +char *U_WMR7C_set(void){ + return U_WMRCORENONE_set("U_WMR7C"); +} + +char *U_WMR7D_set(void){ + return U_WMRCORENONE_set("U_WMR7D"); +} + +char *U_WMR7E_set(void){ + return U_WMRCORENONE_set("U_WMR7E"); +} + +char *U_WMR7F_set(void){ + return U_WMRCORENONE_set("U_WMR7F"); +} + +char *U_WMR80_set(void){ + return U_WMRCORENONE_set("U_WMR80"); +} + +char *U_WMR81_set(void){ + return U_WMRCORENONE_set("U_WMR81"); +} + +char *U_WMR82_set(void){ + return U_WMRCORENONE_set("U_WMR82"); +} + +char *U_WMR83_set(void){ + return U_WMRCORENONE_set("U_WMR83"); +} + +char *U_WMR84_set(void){ + return U_WMRCORENONE_set("U_WMR84"); +} + +char *U_WMR85_set(void){ + return U_WMRCORENONE_set("U_WMR85"); +} + +char *U_WMR86_set(void){ + return U_WMRCORENONE_set("U_WMR86"); +} + +char *U_WMR87_set(void){ + return U_WMRCORENONE_set("U_WMR87"); +} + +char *U_WMR88_set(void){ + return U_WMRCORENONE_set("U_WMR88"); +} + +char *U_WMR89_set(void){ + return U_WMRCORENONE_set("U_WMR89"); +} + +char *U_WMR8A_set(void){ + return U_WMRCORENONE_set("U_WMR8A"); +} + +char *U_WMR8B_set(void){ + return U_WMRCORENONE_set("U_WMR8B"); +} + +char *U_WMR8C_set(void){ + return U_WMRCORENONE_set("U_WMR8C"); +} + +char *U_WMR8D_set(void){ + return U_WMRCORENONE_set("U_WMR8D"); +} + +char *U_WMR8E_set(void){ + return U_WMRCORENONE_set("U_WMR8E"); +} + +char *U_WMR8F_set(void){ + return U_WMRCORENONE_set("U_WMR8F"); +} + +char *U_WMR90_set(void){ + return U_WMRCORENONE_set("U_WMR90"); +} + +char *U_WMR91_set(void){ + return U_WMRCORENONE_set("U_WMR91"); +} + +char *U_WMR92_set(void){ + return U_WMRCORENONE_set("U_WMR92"); +} + +char *U_WMR93_set(void){ + return U_WMRCORENONE_set("U_WMR93"); +} + +char *U_WMR94_set(void){ + return U_WMRCORENONE_set("U_WMR94"); +} + +char *U_WMR95_set(void){ + return U_WMRCORENONE_set("U_WMR95"); +} + +char *U_WMR96_set(void){ + return U_WMRCORENONE_set("U_WMR96"); +} + +char *U_WMR97_set(void){ + return U_WMRCORENONE_set("U_WMR97"); +} + +char *U_WMR98_set(void){ + return U_WMRCORENONE_set("U_WMR98"); +} + +char *U_WMR99_set(void){ + return U_WMRCORENONE_set("U_WMR99"); +} + +char *U_WMR9A_set(void){ + return U_WMRCORENONE_set("U_WMR9A"); +} + +char *U_WMR9B_set(void){ + return U_WMRCORENONE_set("U_WMR9B"); +} + +char *U_WMR9C_set(void){ + return U_WMRCORENONE_set("U_WMR9C"); +} + +char *U_WMR9D_set(void){ + return U_WMRCORENONE_set("U_WMR9D"); +} + +char *U_WMR9E_set(void){ + return U_WMRCORENONE_set("U_WMR9E"); +} + +char *U_WMR9F_set(void){ + return U_WMRCORENONE_set("U_WMR9F"); +} + +char *U_WMRA0_set(void){ + return U_WMRCORENONE_set("U_WMRA0"); +} + +char *U_WMRA1_set(void){ + return U_WMRCORENONE_set("U_WMRA1"); +} + +char *U_WMRA2_set(void){ + return U_WMRCORENONE_set("U_WMRA2"); +} + +char *U_WMRA3_set(void){ + return U_WMRCORENONE_set("U_WMRA3"); +} + +char *U_WMRA4_set(void){ + return U_WMRCORENONE_set("U_WMRA4"); +} + +char *U_WMRA5_set(void){ + return U_WMRCORENONE_set("U_WMRA5"); +} + +char *U_WMRA6_set(void){ + return U_WMRCORENONE_set("U_WMRA6"); +} + +char *U_WMRA7_set(void){ + return U_WMRCORENONE_set("U_WMRA7"); +} + +char *U_WMRA8_set(void){ + return U_WMRCORENONE_set("U_WMRA8"); +} + +char *U_WMRA9_set(void){ + return U_WMRCORENONE_set("U_WMRA9"); +} + +char *U_WMRAA_set(void){ + return U_WMRCORENONE_set("U_WMRAA"); +} + +char *U_WMRAB_set(void){ + return U_WMRCORENONE_set("U_WMRAB"); +} + +char *U_WMRAC_set(void){ + return U_WMRCORENONE_set("U_WMRAC"); +} + +char *U_WMRAD_set(void){ + return U_WMRCORENONE_set("U_WMRAD"); +} + +char *U_WMRAE_set(void){ + return U_WMRCORENONE_set("U_WMRAE"); +} + +char *U_WMRAF_set(void){ + return U_WMRCORENONE_set("U_WMRAF"); +} + +char *U_WMRB0_set(void){ + return U_WMRCORENONE_set("U_WMRB0"); +} + +char *U_WMRB1_set(void){ + return U_WMRCORENONE_set("U_WMRB1"); +} + +char *U_WMRB2_set(void){ + return U_WMRCORENONE_set("U_WMRB2"); +} + +char *U_WMRB3_set(void){ + return U_WMRCORENONE_set("U_WMRB3"); +} + +char *U_WMRB4_set(void){ + return U_WMRCORENONE_set("U_WMRB4"); +} + +char *U_WMRB5_set(void){ + return U_WMRCORENONE_set("U_WMRB5"); +} + +char *U_WMRB6_set(void){ + return U_WMRCORENONE_set("U_WMRB6"); +} + +char *U_WMRB7_set(void){ + return U_WMRCORENONE_set("U_WMRB7"); +} + +char *U_WMRB8_set(void){ + return U_WMRCORENONE_set("U_WMRB8"); +} + +char *U_WMRB9_set(void){ + return U_WMRCORENONE_set("U_WMRB9"); +} + +char *U_WMRBA_set(void){ + return U_WMRCORENONE_set("U_WMRBA"); +} + +char *U_WMRBB_set(void){ + return U_WMRCORENONE_set("U_WMRBB"); +} + +char *U_WMRBC_set(void){ + return U_WMRCORENONE_set("U_WMRBC"); +} + +char *U_WMRBD_set(void){ + return U_WMRCORENONE_set("U_WMRBD"); +} + +char *U_WMRBE_set(void){ + return U_WMRCORENONE_set("U_WMRBE"); +} + +char *U_WMRBF_set(void){ + return U_WMRCORENONE_set("U_WMRBF"); +} + +char *U_WMRC0_set(void){ + return U_WMRCORENONE_set("U_WMRC0"); +} + +char *U_WMRC1_set(void){ + return U_WMRCORENONE_set("U_WMRC1"); +} + +char *U_WMRC2_set(void){ + return U_WMRCORENONE_set("U_WMRC2"); +} + +char *U_WMRC3_set(void){ + return U_WMRCORENONE_set("U_WMRC3"); +} + +char *U_WMRC4_set(void){ + return U_WMRCORENONE_set("U_WMRC4"); +} + +char *U_WMRC5_set(void){ + return U_WMRCORENONE_set("U_WMRC5"); +} + +char *U_WMRC6_set(void){ + return U_WMRCORENONE_set("U_WMRC6"); +} + +char *U_WMRC7_set(void){ + return U_WMRCORENONE_set("U_WMRC7"); +} + +char *U_WMRC8_set(void){ + return U_WMRCORENONE_set("U_WMRC8"); +} + +char *U_WMRC9_set(void){ + return U_WMRCORENONE_set("U_WMRC9"); +} + +char *U_WMRCA_set(void){ + return U_WMRCORENONE_set("U_WMRCA"); +} + +char *U_WMRCB_set(void){ + return U_WMRCORENONE_set("U_WMRCB"); +} + +char *U_WMRCC_set(void){ + return U_WMRCORENONE_set("U_WMRCC"); +} + +char *U_WMRCD_set(void){ + return U_WMRCORENONE_set("U_WMRCD"); +} + +char *U_WMRCE_set(void){ + return U_WMRCORENONE_set("U_WMRCE"); +} + +char *U_WMRCF_set(void){ + return U_WMRCORENONE_set("U_WMRCF"); +} + +char *U_WMRD0_set(void){ + return U_WMRCORENONE_set("U_WMRD0"); +} + +char *U_WMRD1_set(void){ + return U_WMRCORENONE_set("U_WMRD1"); +} + +char *U_WMRD2_set(void){ + return U_WMRCORENONE_set("U_WMRD2"); +} + +char *U_WMRD3_set(void){ + return U_WMRCORENONE_set("U_WMRD3"); +} + +char *U_WMRD4_set(void){ + return U_WMRCORENONE_set("U_WMRD4"); +} + +char *U_WMRD5_set(void){ + return U_WMRCORENONE_set("U_WMRD5"); +} + +char *U_WMRD6_set(void){ + return U_WMRCORENONE_set("U_WMRD6"); +} + +char *U_WMRD7_set(void){ + return U_WMRCORENONE_set("U_WMRD7"); +} + +char *U_WMRD8_set(void){ + return U_WMRCORENONE_set("U_WMRD8"); +} + +char *U_WMRD9_set(void){ + return U_WMRCORENONE_set("U_WMRD9"); +} + +char *U_WMRDA_set(void){ + return U_WMRCORENONE_set("U_WMRDA"); +} + +char *U_WMRDB_set(void){ + return U_WMRCORENONE_set("U_WMRDB"); +} + +char *U_WMRDC_set(void){ + return U_WMRCORENONE_set("U_WMRDC"); +} + +char *U_WMRDD_set(void){ + return U_WMRCORENONE_set("U_WMRDD"); +} + +char *U_WMRDE_set(void){ + return U_WMRCORENONE_set("U_WMRDE"); +} + +char *U_WMRDF_set(void){ + return U_WMRCORENONE_set("U_WMRDF"); +} + +char *U_WMRE0_set(void){ + return U_WMRCORENONE_set("U_WMRE0"); +} + +char *U_WMRE1_set(void){ + return U_WMRCORENONE_set("U_WMRE1"); +} + +char *U_WMRE2_set(void){ + return U_WMRCORENONE_set("U_WMRE2"); +} + +char *U_WMRE3_set(void){ + return U_WMRCORENONE_set("U_WMRE3"); +} + +char *U_WMRE4_set(void){ + return U_WMRCORENONE_set("U_WMRE4"); +} + +char *U_WMRE5_set(void){ + return U_WMRCORENONE_set("U_WMRE5"); +} + +char *U_WMRE6_set(void){ + return U_WMRCORENONE_set("U_WMRE6"); +} + +char *U_WMRE7_set(void){ + return U_WMRCORENONE_set("U_WMRE7"); +} + +char *U_WMRE8_set(void){ + return U_WMRCORENONE_set("U_WMRE8"); +} + +char *U_WMRE9_set(void){ + return U_WMRCORENONE_set("U_WMRE9"); +} + +char *U_WMREA_set(void){ + return U_WMRCORENONE_set("U_WMREA"); +} + +char *U_WMREB_set(void){ + return U_WMRCORENONE_set("U_WMREB"); +} + +char *U_WMREC_set(void){ + return U_WMRCORENONE_set("U_WMREC"); +} + +char *U_WMRED_set(void){ + return U_WMRCORENONE_set("U_WMRED"); +} + +char *U_WMREE_set(void){ + return U_WMRCORENONE_set("U_WMREE"); +} + +char *U_WMREF_set(void){ + return U_WMRCORENONE_set("U_WMREF"); +} +//! \endcond + +/** + \brief Create and return a U_WMRDELETEOBJECT record + \return pointer to the U_WMRDELETEOBJECT record, or NULL on error + \param object Index of object to delete. +*/ +char *U_WMRDELETEOBJECT_set(uint16_t object){ + return U_WMRCORE_1U16_set(U_WMR_DELETEOBJECT, object); +} + +//! \cond +char *U_WMRF1_set(void){ + return U_WMRCORENONE_set("U_WMRF1"); +} + +char *U_WMRF2_set(void){ + return U_WMRCORENONE_set("U_WMRF2"); +} + +char *U_WMRF3_set(void){ + return U_WMRCORENONE_set("U_WMRF3"); +} + +char *U_WMRF4_set(void){ + return U_WMRCORENONE_set("U_WMRF4"); +} + +char *U_WMRF5_set(void){ + return U_WMRCORENONE_set("U_WMRF5"); +} + +char *U_WMRF6_set(void){ + return U_WMRCORENONE_set("U_WMRF6"); +} +//! \endcond + +/** + \brief Create and return a U_WMRCREATEPALETTE record + \return pointer to the U_WMRCREATEPALETTE record, or NULL on error + \param Palette Create a Palette object. +*/ +char *U_WMRCREATEPALETTE_set(U_PALETTE *Palette){ + return U_WMRCORE_PALETTE_set(U_WMR_CREATEPALETTE, Palette); +} + +//! \cond +char *U_WMRF8_set(void){ + return U_WMRCORENONE_set("U_WMRF8"); +} +//! \endcond + +/** + \brief Allocate and construct a U_WMRCREATEPATTERNBRUSH record. + WARNING - U_WMRCREATEPATTERNBRUSH has been declared obsolete and application support is spotty - + use U_WMRDIBCREATEPATTERNBRUSH instead. + \return pointer to the U_WMRCREATEPATTERNBRUSH record, or NULL on error. + \param Bm16 Pointer to a Bitmap16 Object, only the first 10 bytes are used. + \param Pattern byte array pattern, described by Bm16, for brush +*/ +char *U_WMRCREATEPATTERNBRUSH_set( + U_BITMAP16 *Bm16, + char *Pattern + ){ + char *record; + uint32_t irecsize,off,cbPat; + if(!Bm16 || !Pattern)return(NULL); + + cbPat = (((Bm16->Width * Bm16->BitsPixel + 15) >> 4) << 1) * Bm16->Height; + irecsize = U_SIZE_METARECORD + 14 + 18 + cbPat; /* core WMR + truncated Bm16 + 18 spaces bytes + pattern */ + record = malloc(irecsize); + if(record){ + U_WMRCORE_SETRECHEAD(record,irecsize,U_WMR_CREATEPATTERNBRUSH); + off = U_SIZE_METARECORD; + memcpy(record + off, Bm16, 14); off+=14; /* Truncated bitmap16 object, last 4 bytes are to be ignored*/ + memset(record + off, 0, 18); off+=18; /* 18 bytes of zero, which are ignored */ + memcpy(record + off, Pattern, cbPat); /* The pattern array */ + } + return(record); +} + +/** + \brief Allocate and construct a U_WMRCREATEPENINDIRECT record. + \return pointer to the U_WMRCREATEPENINDIRECT record, or NULL on error. + \param pen Parameters of the pen object to create. +*/ +char *U_WMRCREATEPENINDIRECT_set(U_PEN pen){ + return U_WMRCORE_2U16_N16_set(U_WMR_CREATEPENINDIRECT, NULL, NULL, U_SIZE_PEN/2, &pen); +} + +/** + \brief Allocate and construct a U_WMRCREATEFONTINDIRECT record. + \return pointer to the U_WMRCREATEFONTINDIRECT record, or NULL on error. + \param font Parameters of the font object to create. +*/ +char *U_WMRCREATEFONTINDIRECT_set(U_FONT *font){ + char *record=NULL; + uint32_t irecsize,off,flen; + flen = 1 + strlen((char *)font->FaceName); /* include the null terminator in the count */ + if(flen & 1) flen++; /* make the allocation end line up at an even byte */ + irecsize = U_SIZE_METARECORD + U_SIZE_FONT_CORE + flen; + record = calloc(1,irecsize); + if(record){ + U_WMRCORE_SETRECHEAD(record,irecsize,U_WMR_CREATEFONTINDIRECT); + off = U_SIZE_METARECORD; + memcpy(record+off,font,U_SIZE_FONT_CORE + flen); + } + return(record); +} + +/** + \brief Allocate and construct a U_WMRCREATEBRUSHINDIRECT record. + \return pointer to the U_WMRCREATEBRUSHINDIRECT record, or NULL on error. + \param brush Parameters of the brush object to create. +*/ +char *U_WMRCREATEBRUSHINDIRECT_set(U_WLOGBRUSH brush){ + return U_WMRCORE_2U16_N16_set(U_WMR_CREATEBRUSHINDIRECT, NULL, NULL, U_SIZE_WLOGBRUSH/2, &brush); +} + +/** in GDI and Wine, not in WMF manual. +*/ +char *U_WMRCREATEBITMAPINDIRECT_set(void){ + return U_WMRCORENONE_set("U_WMRCREATEBITMAPINDIRECT"); +} + +/** in GDI and Wine, not in WMF manual. +*/ + char *U_WMRCREATEBITMAP_set(void){ + return U_WMRCORENONE_set("U_WMRCREATEBITMAP"); +} + +/** + \brief Allocate and construct a U_WMRCREATEREGION record. + \return pointer to the U_WMRCREATEREGION record, or NULL on error. + \param region Parameters of the region object to create. +*/ +char *U_WMRCREATEREGION_set(const U_REGION *region){ + char *record=NULL; + uint32_t irecsize,off; + irecsize = U_SIZE_METARECORD + region->Size; + record = malloc(irecsize); + if(record){ + U_WMRCORE_SETRECHEAD(record,irecsize,U_WMR_CREATEREGION); + off = U_SIZE_METARECORD; + memcpy(record+off,region,region->Size); + } + return(record); +} + + +/* all of the *_set are above, all of the *_get are below */ + +/* ********************************************************************************************** +These functions are used for Image conversions and other +utility operations. Character type conversions are in uwmf_utf.c +*********************************************************************************************** */ + + +/** + \brief Make up an approximate dx array to pass to U_WMREXTTEXTOUT_get(), based on character height and weight. + + Take abs. value of character height, get width by multiplying by 0.6, and correct weight + approximately, with formula (measured on screen for one text line of Arial). + Caller is responsible for free() on the returned pointer. + + \return pointer to dx array + \param height character height (absolute value will be used) + \param weight LF_Weight Enumeration (character weight) + \param members Number of entries to put into dx + +*/ +int16_t *dx16_get( + int32_t height, + uint32_t weight, + uint32_t members + ){ + uint32_t i, width; + int16_t *dx; + dx = (int16_t *) malloc(members * sizeof(int16_t)); + if(dx){ + if(U_FW_DONTCARE == weight)weight=U_FW_NORMAL; + width = (uint32_t) U_ROUND(((float) (height > 0 ? height : -height)) * 0.6 * (0.00024*(float) weight + 0.904)); + for ( i = 0; i < members; i++ ){ dx[i] = (width > INT16_MAX ? INT16_MAX : width); } + } + return(dx); +} + +/** + \brief Return the size of a WMF record, or 0 if it is found to be invalid. + A valid record will have a size that does not cause it to extend + beyond the end of data in memory. + A valid record will not be smaller than the smallest possible WMF record. + \return size of the record in bytes, 0 on failure + \param contents record to extract data from + \param blimit one byte past the last WMF record in memory. +*/ +size_t U_WMRRECSAFE_get( + const char *contents, + const char *blimit + ){ + size_t size=0; + uint32_t Size16; + memcpy(&Size16, contents + offsetof(U_METARECORD,Size16_4), 4); + size = 2*Size16; + /* Record is not self consistent - described size past the end of WMF in memory */ + if(size < U_SIZE_METARECORD || IS_MEM_UNSAFE(contents, size, blimit))size=0; + return(size); +} + + +/* ********************************************************************************************** +These functions create standard structures used in the WMR records. +*********************************************************************************************** */ + +// hide these from Doxygen +//! \cond +/* ********************************************************************************************** +These functions contain shared code used by various U_WMR*_get functions. These should NEVER be called +by end user code and to further that end prototypes are NOT provided and they are hidden from Doxygen. +*********************************************************************************************** */ + +int U_WMRCORENONE_get(char *string){ + printf("unimplemented creator for:%s\n",string); + return(0); +} + +/* Returns the record size in bytes for a valid record, or 0 for an invalid record. + A valid record's size is at least as large as the minimum size passed in through minsize. + Use U_WMRRECSAFE_get() to check if the record extends too far in memory. +*/ +int U_WMRCORE_RECSAFE_get( + const char *contents, + int minsize +){ + int size=0; + uint32_t Size16; + memcpy(&Size16, contents + offsetof(U_METARECORD,Size16_4),4); + size = 2*Size16; + if(size < minsize)size=0; + return(size); +} + + +/* records like U_WMRFLOODFILL and others. all args are optional, Color is not */ +int U_WMRCORE_1U16_CRF_2U16_get( + const char *contents, + uint16_t *arg1, + U_COLORREF *Color, + uint16_t *arg2, + uint16_t *arg3 + ){ + int size = 0; + int off = U_SIZE_METARECORD; + if(arg1){ memcpy(arg1, contents + off, 2); off+=2; size+=2;} + memcpy(Color, contents + off, 4); off+=4; size+=4; + if(arg2){ memcpy(arg2, contents + off, 2); off+=2; size+=2;} + if(arg3){ memcpy(arg3, contents + off, 2); size+=2;} + return(size); +} + +/* records that have a single uint16_t argument like U_WMRSETMAPMODE + May also be used with int16_t with appropriate casts */ +int U_WMRCORE_1U16_get( + const char *contents, + int minsize, + uint16_t *arg1 + ){ + int size = U_WMRCORE_RECSAFE_get(contents, minsize); + int off = U_SIZE_METARECORD; + if(!size)return(0); + memcpy(arg1, contents + off, 2); + return(size); +} + +/* records that have two uint16_t arguments like U_WMRSETBKMODE + May also be used with int16_t with appropriate casts */ +int U_WMRCORE_2U16_get( + const char *contents, + int minsize, + uint16_t *arg1, + uint16_t *arg2 + ){ + int size = U_WMRCORE_RECSAFE_get(contents, minsize); + int off = U_SIZE_METARECORD; + memcpy(arg1, contents + off, 2); off+=2; + memcpy(arg2, contents + off, 2); + return(size); +} + +/* records that have four uint16_t arguments like U_WMRSCALEWINDOWEXT + May also be used with int16_t with appropriate casts */ +int U_WMRCORE_4U16_get( + const char *contents, + int minsize, + uint16_t *arg1, + uint16_t *arg2, + uint16_t *arg3, + uint16_t *arg4 + ){ + int size = U_WMRCORE_RECSAFE_get(contents, minsize); + int off = U_SIZE_METARECORD; + if(!size)return(0); + memcpy(arg1, contents + off, 2); off+=2; + memcpy(arg2, contents + off, 2); off+=2; + memcpy(arg3, contents + off, 2); off+=2; + memcpy(arg4, contents + off, 2); + return(size); +} + +/* records that have five uint16_t arguments like U_WMRCREATEPENINDIRECT + May also be used with int16_t with appropriate casts */ +int U_WMRCORE_5U16_get( + const char *contents, + int minsize, + uint16_t *arg1, + uint16_t *arg2, + uint16_t *arg3, + uint16_t *arg4, + uint16_t *arg5 + ){ + int size = U_WMRCORE_RECSAFE_get(contents, minsize); + int off = U_SIZE_METARECORD; + if(!size)return(0); + memcpy(arg1, contents + off, 2); off+=2; + memcpy(arg2, contents + off, 2); off+=2; + memcpy(arg3, contents + off, 2); off+=2; + memcpy(arg4, contents + off, 2); off+=2; + memcpy(arg5, contents + off, 2); + return(size); +} + +/* records that have six uint16_t arguments like U_ROUNDREC + May also be used with int16_t with appropriate casts */ +int U_WMRCORE_6U16_get( + const char *contents, + int minsize, + uint16_t *arg1, + uint16_t *arg2, + uint16_t *arg3, + uint16_t *arg4, + uint16_t *arg5, + uint16_t *arg6 + ){ + int size = U_WMRCORE_RECSAFE_get(contents, minsize); + int off = U_SIZE_METARECORD; + if(!size)return(0); + memcpy(arg1, contents + off, 2); off+=2; + memcpy(arg2, contents + off, 2); off+=2; + memcpy(arg3, contents + off, 2); off+=2; + memcpy(arg4, contents + off, 2); off+=2; + memcpy(arg5, contents + off, 2); off+=2; + memcpy(arg6, contents + off, 2); + return(size); +} + +/* records that have eight uint16_t arguments like U_WMRARC + May also be used with int16_t with appropriate casts */ +int U_WMRCORE_8U16_get( + const char *contents, + int minsize, + uint16_t *arg1, + uint16_t *arg2, + uint16_t *arg3, + uint16_t *arg4, + uint16_t *arg5, + uint16_t *arg6, + uint16_t *arg7, + uint16_t *arg8 + ){ + int size = U_WMRCORE_RECSAFE_get(contents, minsize); + int off = U_SIZE_METARECORD; + if(!size)return(0); + memcpy(arg1, contents + off, 2); off+=2; + memcpy(arg2, contents + off, 2); off+=2; + memcpy(arg3, contents + off, 2); off+=2; + memcpy(arg4, contents + off, 2); off+=2; + memcpy(arg5, contents + off, 2); off+=2; + memcpy(arg6, contents + off, 2); off+=2; + memcpy(arg7, contents + off, 2); off+=2; + memcpy(arg8, contents + off, 2); + return(size); +} + +/* records that have + arg1 an (optional) (u)int16 + arg2 an (optional( (u)int16 + array of data cells or just a bunch of data. Passed as a char because the structures in the WMF in memory may + not be aligned properly for those structures. Caller has to take them apart - carefully. + like U_WMRCREATEBRUSHINDIRECT with arg1=arg2=NULL +*/ +int U_WMRCORE_2U16_N16_get( + const char *contents, + int minsize, + uint16_t *arg1, + uint16_t *arg2, + const char **array + ){ + int size = U_WMRCORE_RECSAFE_get(contents, minsize); + int off = U_SIZE_METARECORD; + if(!size)return(0); + if(arg1){ memcpy(arg1, contents + off, 2); off+=2; } + if(arg2){ memcpy(arg2, contents + off, 2); off+=2; } + *array = (contents + off); + return(size); +} + + + +/* records that get a U_PALETTE like U_WMRANIMATEPALETTE. Fills in the first two fields of U_PALETTE only, and returns + returns a separateepointer to the PalEntries[] array. This pointer is most likely not aligned with the data. + */ +int U_WMRCORE_PALETTE_get( + const char *contents, + int minsize, + U_PALETTE *Palette, + const char **PalEntries + ){ + int size = U_WMRCORE_RECSAFE_get(contents, minsize); + if(!size)return(0); + contents += offsetof(U_WMRANIMATEPALETTE, Palette); + memset(Palette, 0, (U_SIZE_PALETTE)); + memcpy(Palette, contents, (U_SIZE_PALETTE)); + *PalEntries = (contents + offsetof(U_PALETTE, PalEntries)); + return(size); +} + +//! \endcond + +/** + \brief Return parameters from a bitmapcoreheader. + All are returned as 32 bit integers, regardless of their internal representation. + + \param BmiCh char * pointer to a U_BITMAPCOREHEADER. Note, data may not be properly aligned. + \param Size size of the coreheader in bytes + \param Width; Width of pixel array + \param Height; Height of pixel array + \param BitCount Pixel Format (BitCount Enumeration) +*/ +void U_BITMAPCOREHEADER_get( + const char *BmiCh, + uint32_t *Size, + int32_t *Width, + int32_t *Height, + int32_t *BitCount + ){ + uint32_t utmp4; + uint16_t utmp2; + memcpy(&utmp4, BmiCh + offsetof(U_BITMAPCOREHEADER,Size_4), 4); *Size = utmp4; + memcpy(&utmp2, BmiCh + offsetof(U_BITMAPCOREHEADER,Width), 2); *Width = utmp2; + memcpy(&utmp2, BmiCh + offsetof(U_BITMAPCOREHEADER,Height), 2); *Height = utmp2; + memcpy(&utmp2, BmiCh + offsetof(U_BITMAPCOREHEADER,BitCount), 2); *BitCount = utmp2; +} + +/** + \brief Return parameters from a bitinfoheader. + All are returned as 32 bit integers, regardless of their internal representation. + + \param Bmih char * pointer to a U_BITMAPINFOHEADER. Note, data may not be properly aligned. + \param Size Structure size in bytes + \param Width Bitmap width in pixels + \param Height Bitmap height in pixels, may be negative. + \param Planes Planes (must be 1) + \param BitCount BitCount Enumeration (determines number of RBG colors) + \param Compression BI_Compression Enumeration + \param SizeImage Image size in bytes or 0 = "default size (calculated from geometry?)" + \param XPelsPerMeter X Resolution in pixels/meter + \param YPelsPerMeter Y Resolution in pixels/meter + \param ClrUsed Number of bmciColors in U_BITMAPINFO/U_BITMAPCOREINFO that are used by the bitmap + \param ClrImportant Number of bmciColors needed (0 means all). + + +*/ +void U_BITMAPINFOHEADER_get( + const char *Bmih, + uint32_t *Size, + int32_t *Width, + int32_t *Height, + uint32_t *Planes, + uint32_t *BitCount, + uint32_t *Compression, + uint32_t *SizeImage, + int32_t *XPelsPerMeter, + int32_t *YPelsPerMeter, + uint32_t *ClrUsed, + uint32_t *ClrImportant + ){ + int32_t tmp4; + uint32_t utmp4; + uint16_t utmp2; + + memcpy(&utmp4, Bmih + offsetof(U_BITMAPINFOHEADER,biSize ), 4); *Size = utmp4; + memcpy( &tmp4, Bmih + offsetof(U_BITMAPINFOHEADER,biWidth ), 4); *Width = tmp4; + memcpy( &tmp4, Bmih + offsetof(U_BITMAPINFOHEADER,biHeight ), 4); *Height = tmp4; + memcpy(&utmp2, Bmih + offsetof(U_BITMAPINFOHEADER,biPlanes ), 2); *Planes = utmp2; + memcpy(&utmp2, Bmih + offsetof(U_BITMAPINFOHEADER,biBitCount ), 2); *BitCount = utmp2; + memcpy(&utmp4, Bmih + offsetof(U_BITMAPINFOHEADER,biCompression ), 4); *Compression = utmp4; + memcpy(&utmp4, Bmih + offsetof(U_BITMAPINFOHEADER,biSizeImage ), 4); *SizeImage = utmp4; + memcpy( &tmp4, Bmih + offsetof(U_BITMAPINFOHEADER,biXPelsPerMeter), 4); *XPelsPerMeter = tmp4; + memcpy( &tmp4, Bmih + offsetof(U_BITMAPINFOHEADER,biYPelsPerMeter), 4); *YPelsPerMeter = tmp4; + memcpy(&utmp4, Bmih + offsetof(U_BITMAPINFOHEADER,biClrUsed ), 4); *ClrUsed = utmp4; + memcpy(&utmp4, Bmih + offsetof(U_BITMAPINFOHEADER,biClrImportant ), 4); *ClrImportant = utmp4; +} + +/** + \brief Assume a packed DIB and get the parameters from it, use by DBI_to_RGBA() + + \return BI_Compression Enumeration. For anything other than U_BI_RGB values other than px may not be valid. + \param dib pointer to the start of the DIB in the record + \param px pointer to DIB pixel array + \param ct pointer to DIB color table + \param numCt DIB color table number of entries, for PNG or JPG returns the number of bytes in the image + \param width Width of pixel array + \param height Height of pixel array (always returned as a positive number) + \param colortype DIB BitCount Enumeration + \param invert If DIB rows are in opposite order from RGBA rows +*/ +int wget_DIB_params( + const char *dib, + const char **px, + const U_RGBQUAD **ct, + uint32_t *numCt, + int32_t *width, + int32_t *height, + int32_t *colortype, + int32_t *invert + ){ + uint32_t bic; + uint32_t Size; + bic = U_BI_RGB; // this information is not in the coreheader; + U_BITMAPCOREHEADER_get(dib, &Size, width, height, colortype); + if(Size != 0xC ){ //BitmapCoreHeader + /* if biCompression is not U_BI_RGB some or all of the following might not hold real values. + Ignore most of the information returned from the bitmapinfoheader. + */ + uint32_t uig4; + int32_t ig4; + U_BITMAPINFOHEADER_get(dib, &uig4, width, height,&uig4, (uint32_t *) colortype, &bic, &uig4, &ig4, &ig4, &uig4, &uig4); + } + if(*height < 0){ + *height = -*height; + *invert = 1; + } + else { + *invert = 0; + } + *px = dib + U_SIZE_BITMAPINFOHEADER; + if(bic == U_BI_RGB){ + *numCt = get_real_color_count(dib); + if(*numCt){ + *ct = (U_RGBQUAD *) (dib + U_SIZE_BITMAPINFOHEADER); + *px += U_SIZE_COLORREF * (*numCt); + } + else { *ct = NULL; } + } + else { + memcpy(numCt, dib + offsetof(U_BITMAPINFOHEADER,biSizeImage), 4); + *ct = NULL; + } + return(bic); +} + + + +/* ********************************************************************************************** +These are the core WMR functions, each extracts data from a particular type of record. +In general routines fill in structures which have been passed in by the caller, and zero them +if that (optional) structure is not present. +Because the WMF records may not be aligned they are generally copied into the supplied + aligned structs, so that the caller may retrieve fields with the usual sorts of + structure operations: Struct.field or (*Struct)->field. +A few routines return pointers to data regions in the record. +They are listed in order by the corresponding U_WMR_* index number. +*********************************************************************************************** */ + +/** + \brief Get data from a (placeable) WMR_HEADER. + \return size of the record in bytes, 0 on failure + \param contents record to extract data from + \param blimit one byte past the last WMF record in memory. + \param Placeable U_WMRPLACEABLE data, if any + \param Header U_WMRHEADER data, if any +*/ +int wmfheader_get( + const char *contents, + const char *blimit, + U_WMRPLACEABLE *Placeable, + U_WMRHEADER *Header + ){ + uint32_t Key; + int size=0; + if(!contents || !Placeable || !Header || !blimit)return(0); + if(IS_MEM_UNSAFE(contents, 4, blimit))return(0); + memcpy(&Key, contents + offsetof(U_WMRPLACEABLE,Key), 4); + if(Key == 0x9AC6CDD7){ + size += U_SIZE_WMRPLACEABLE; + if(IS_MEM_UNSAFE(contents, size, blimit))return(0); + memcpy(Placeable, contents, U_SIZE_WMRPLACEABLE); + contents += U_SIZE_WMRPLACEABLE; + } + else { + memset(Placeable, 0, U_SIZE_WMRPLACEABLE); + } + if(IS_MEM_UNSAFE(contents, size + U_SIZE_WMRHEADER, blimit))return(0); + size += 2* (*(uint16_t *)(contents + offsetof(U_WMRHEADER,Size16w))); + if(IS_MEM_UNSAFE(contents, size, blimit))return(0); + memcpy(Header, contents, U_SIZE_WMRHEADER); + return(size); +} + + +/** + \brief Get data from a U_WMREOF record + \return size of record in bytes, or 0 on error + \param contents record to extract data from +*/ +int U_WMREOF_get( + const char *contents + ){ + return(U_WMRCORE_RECSAFE_get(contents, (U_SIZE_WMREOF))); +} + +/** + \brief Retrieve values from a U_WMRSETBKCOLOR record + \return length of the U_WMRSETBKCOLOR record, or NULL on error + \param contents record to extract data from + \param Color Background Color. +*/ +int U_WMRSETBKCOLOR_get( + const char *contents, + U_COLORREF *Color + ){ + int size = U_WMRCORE_RECSAFE_get(contents, (U_SIZE_WMRSETBKCOLOR)); + if(!size)return(0); + memcpy(Color,contents + offsetof(U_WMRSETBKCOLOR,Color),U_SIZE_COLORREF); + return(size); +} + +/** + \brief Retrieve values from a U_WMRSETBKMODE record + \return length of the U_WMRSETBKMODE record, or NULL on error + \param contents record to extract data from + \param Mode MixMode Enumeration +*/ +int U_WMRSETBKMODE_get( + const char *contents, + uint16_t *Mode + ){ + return(U_WMRCORE_1U16_get(contents, (U_SIZE_WMRSETBKMODE), Mode)); +} + +/** + \brief Retrieve values from a U_WMRSETMAPMODE record + \return length of the U_WMRSETMAPMODE record, or NULL on error + \param contents record to extract data from + \param Mode MapMode Enumeration +*/ +int U_WMRSETMAPMODE_get( + const char *contents, + uint16_t *Mode + ){ + return(U_WMRCORE_1U16_get(contents, (U_SIZE_WMRSETMAPMODE), Mode)); +} + +/** + \brief Retrieve values from a U_WMRSETROP2 record + \return length of the U_WMRSETROP2 record, or NULL on error + \param contents record to extract data from + \param Mode Binary Raster Operation Enumeration +*/ +int U_WMRSETROP2_get( + const char *contents, + uint16_t *Mode + ){ + return(U_WMRCORE_1U16_get(contents, (U_SIZE_WMRSETROP2), Mode)); +} + +/** + \brief Get data from a U_WMRSETRELABS record + \return length of the U_WMRSETRELABS record in bytes, or 0 on error + \param contents record to extract data from +*/ +int U_WMRSETRELABS_get( + const char *contents + ){ + return(U_WMRCORE_RECSAFE_get(contents, (U_SIZE_WMRSETRELABS))); +} + +/** + \brief Retrieve values from a U_WMRSETPOLYFILLMODE record + \return length of the U_WMRSETPOLYFILLMODE record, or NULL on error + \param contents record to extract data from + \param Mode PolyFillMode Enumeration +*/ +int U_WMRSETPOLYFILLMODE_get( + const char *contents, + uint16_t *Mode + ){ + return(U_WMRCORE_1U16_get(contents, (U_SIZE_WMRSETPOLYFILLMODE), Mode)); +} + +/** + \brief Retrieve values from a U_WMRSETSTRETCHBLTMODE record + \return length of the U_WMRSETSTRETCHBLTMODE record, or NULL on error + \param contents record to extract data from + \param Mode StretchMode Enumeration +*/ +int U_WMRSETSTRETCHBLTMODE_get( + const char *contents, + uint16_t *Mode + ){ + return(U_WMRCORE_1U16_get(contents, (U_SIZE_WMRSETSTRETCHBLTMODE), Mode)); +} + +/** + \brief Retrieve values from a U_WMRSETTEXTCHAREXTRA record + \return length of the U_WMRSETTEXTCHAREXTRA record, or NULL on error + \param contents record to extract data from + \param Mode Extra space in logical units to add to each character +*/ +int U_WMRSETTEXTCHAREXTRA_get( + const char *contents, + uint16_t *Mode + ){ + return(U_WMRCORE_1U16_get(contents, (U_SIZE_WMRSETTEXTCHAREXTRA), Mode)); +} + +/** + \brief Retrieve values from a U_WMRSETTEXTCOLOR record + \return length of the U_WMRSETTEXTCOLOR record, or NULL on error + \param contents record to extract data from + \param Color Text Color. +*/ +int U_WMRSETTEXTCOLOR_get( + const char *contents, + U_COLORREF *Color + ){ + int size = U_WMRCORE_RECSAFE_get(contents, (U_SIZE_WMRSETTEXTCOLOR)); + if(!size)return(0); + memcpy(Color,contents + offsetof(U_WMRSETTEXTCOLOR,Color),U_SIZE_COLORREF); + return(size); +} + +/** + \brief Retrieve values from a U_WMRSETTEXTJUSTIFICATION record + \return length of the U_WMRSETTEXTJUSTIFICATION record, or NULL on error + \param contents record to extract data from + \param Count Number of space characters in the line. + \param Extra Number of extra space characters to add to the line. +*/ +int U_WMRSETTEXTJUSTIFICATION_get( + const char *contents, + uint16_t *Count, + uint16_t *Extra + ){ + return(U_WMRCORE_2U16_get(contents, (U_SIZE_WMRSETTEXTJUSTIFICATION), Count, Extra)); +} + +/** + \brief Retrieve values from a U_WMRSETWINDOWORG record + \return length of the U_WMRSETWINDOWORG record, or NULL on error + \param contents record to extract data from + \param coord Window Origin. +*/ +int U_WMRSETWINDOWORG_get( + const char *contents, + U_POINT16 * coord + ){ + return(U_WMRCORE_2U16_get(contents, (U_SIZE_WMRSETWINDOWORG), U_P16(coord->y), U_P16(coord->x))); +} + +/** + \brief Retrieve values from a U_WMRSETWINDOWEXT record + \return length of the U_WMRSETWINDOWEXT record, or NULL on error + \param contents record to extract data from + \param extent Window Extent. +*/ +int U_WMRSETWINDOWEXT_get( + const char *contents, + U_POINT16 * extent + ){ + return(U_WMRCORE_2U16_get(contents, (U_SIZE_WMRSETWINDOWEXT), U_P16(extent->y), U_P16(extent->x))); +} + +/** + \brief Retrieve values from a U_WMRSETVIEWPORTORG record + \return length of the U_WMRSETVIEWPORTORG record, or NULL on error + \param contents record to extract data from + \param coord Viewport Origin. +*/ +int U_WMRSETVIEWPORTORG_get( + const char *contents, + U_POINT16 * coord + ){ + return(U_WMRCORE_2U16_get(contents, (U_SIZE_WMRSETVIEWPORTORG), U_P16(coord->y), U_P16(coord->x))); + +} + +/** + \brief Retrieve values from a U_WMRSETVIEWPORTEXT record + \return length of the U_WMRSETVIEWPORTEXT record, or NULL on error + \param contents record to extract data from + \param extent Viewport Extent. +*/ +int U_WMRSETVIEWPORTEXT_get( + const char *contents, + U_POINT16 * extent + ){ + return(U_WMRCORE_2U16_get(contents, (U_SIZE_WMRSETVIEWPORTEXT), U_P16(extent->y), U_P16(extent->x))); +} + +/** + \brief Retrieve values from a U_WMROFFSETWINDOWORG record + \return length of the U_WMROFFSETWINDOWORG record, or NULL on error + \param contents record to extract data from + \param offset Window offset in device units. +*/ +int U_WMROFFSETWINDOWORG_get( + const char *contents, + U_POINT16 * offset + ){ + return(U_WMRCORE_2U16_get(contents, (U_SIZE_WMROFFSETWINDOWORG), U_P16(offset->y), U_P16(offset->x))); +} + +/** + \brief Retrieve values from a U_WMRSCALEWINDOWEXT record + \return length of the U_WMRSCALEWINDOWEXT record, or NULL on error + \param contents record to extract data from + \param Denom {X,Y} denominators. + \param Num {X,Y} numerators. +*/ +int U_WMRSCALEWINDOWEXT_get( + const char *contents, + U_POINT16 * Denom, + U_POINT16 * Num + ){ + return(U_WMRCORE_4U16_get(contents, (U_SIZE_WMRSCALEWINDOWEXT), U_P16(Denom->y), U_P16(Denom->x), U_P16(Num->y), U_P16(Num->x))); +} + +/** + \brief Retrieve values from a U_WMROFFSETVIEWPORTORG record + \return length of the U_WMROFFSETVIEWPORTORG record, or NULL on error + \param contents record to extract data from + \param offset Viewport offset in device units. +*/ +int U_WMROFFSETVIEWPORTORG_get( + const char *contents, + U_POINT16 * offset + ){ + return(U_WMRCORE_2U16_get(contents, (U_SIZE_WMROFFSETVIEWPORTORG), U_P16(offset->y), U_P16(offset->x))); +} + +/** + \brief Retrieve values from a U_WMRSCALEVIEWPORTEXT record + \return length of the U_WMRSCALEVIEWPORTEXT record, or NULL on error + \param contents record to extract data from + \param Denom {X,Y} denominators. + \param Num {X,Y} numerators. +*/ +int U_WMRSCALEVIEWPORTEXT_get( + const char *contents, + U_POINT16 * Denom, + U_POINT16 * Num + ){ + return(U_WMRCORE_4U16_get(contents, (U_SIZE_WMRSCALEVIEWPORTEXT), U_P16(Denom->y), U_P16(Denom->x), U_P16(Num->y), U_P16(Num->x))); +} + +/** + \brief Retrieve values from a U_WMRLINETO record + \return length of the U_WMRLINETO record, or NULL on error + \param contents record to extract data from + \param coord Draw line to {X,Y}. +*/ +int U_WMRLINETO_get( + const char *contents, + U_POINT16 * coord + ){ + return(U_WMRCORE_2U16_get(contents, (U_SIZE_WMRLINETO), U_P16(coord->y), U_P16(coord->x))); +} + +/** + \brief Retrieve values from a U_WMRMOVETO record + \return length of the U_WMRMOVETO record, or NULL on error + \param contents record to extract data from + \param coord Move to {X,Y}. +*/ +int U_WMRMOVETO_get( + const char *contents, + U_POINT16 * coord + ){ + return(U_WMRCORE_2U16_get(contents, (U_SIZE_WMRMOVETO), U_P16(coord->y), U_P16(coord->x))); +} + +/** + \brief Retrieve values from a U_WMREXCLUDECLIPRECT record + \return length of the U_WMREXCLUDECLIPRECT record, or NULL on error + \param contents record to extract data from + \param rect Exclude rect from clipping region. +*/ +int U_WMREXCLUDECLIPRECT_get( + const char *contents, + U_RECT16 *rect + ){ + return(U_WMRCORE_4U16_get(contents, (U_SIZE_WMREXCLUDECLIPRECT), U_P16(rect->bottom), U_P16(rect->right), U_P16(rect->top), U_P16(rect->left))); +} + +/** + \brief Retrieve values from a U_WMRINTERSECTCLIPRECT record + \return length of the U_WMRINTERSECTCLIPRECT record, or NULL on error + \param contents record to extract data from + \param rect Clipping region is intersection of existing clipping region with rect. +*/ +int U_WMRINTERSECTCLIPRECT_get( + const char *contents, + U_RECT16 *rect + ){ + return(U_WMRCORE_4U16_get(contents, (U_SIZE_WMRINTERSECTCLIPRECT), U_P16(rect->bottom), U_P16(rect->right), U_P16(rect->top), U_P16(rect->left))); +} + +/** + \brief Retrieve values from a U_WMRARC record + \return length of the U_WMRARC record, or NULL on error + \param contents record to extract data from + \param StartArc Start of Arc + \param EndArc End of Arc + \param rect Bounding rectangle. +*/ +int U_WMRARC_get( + const char *contents, + U_POINT16 *StartArc, + U_POINT16 *EndArc, + U_RECT16 *rect + ){ + return U_WMRCORE_8U16_get( + contents, + (U_SIZE_WMRARC), + U_P16(EndArc->y), + U_P16(EndArc->x), + U_P16(StartArc->y), + U_P16(StartArc->x), + U_P16(rect->bottom), + U_P16(rect->right), + U_P16(rect->top), + U_P16(rect->left) + ); +} + +/** + \brief Retrieve values from a U_WMRELLIPSE record + \return length of the U_WMRELLIPSE record, or NULL on error + \param contents record to extract data from + \param rect Bounding rectangle for Ellipse. +*/ +int U_WMRELLIPSE_get( + const char *contents, + U_RECT16 *rect + ){ + return U_WMRCORE_4U16_get( + contents, + (U_SIZE_WMRELLIPSE), + U_P16(rect->bottom), + U_P16(rect->right), + U_P16(rect->top), + U_P16(rect->left) + ); +} + +/** + \brief Retrieve values from a U_WMRFLOODFILL record + \return length of the U_WMRFLOODFILL record, or NULL on error + \param contents record to extract data from + \param Mode FloodFill Enumeration. + \param Color Color to Fill with. + \param coord Location to start fill. +*/ +int U_WMRFLOODFILL_get( + const char *contents, + uint16_t *Mode, + U_COLORREF *Color, + U_POINT16 *coord + ){ + return U_WMRCORE_1U16_CRF_2U16_get( + contents, + Mode, + Color, + U_P16(coord->y), + U_P16(coord->x) + ); +} + +/** + \brief Retrieve values from a U_WMRPIE record + \return length of the U_WMRPIE record, or NULL on error + \param contents record to extract data from + \param Radial1 Start of Pie + \param Radial2 End of Pie + \param rect Bounding rectangle. +*/ +int U_WMRPIE_get( + const char *contents, + U_POINT16 *Radial1, + U_POINT16 *Radial2, + U_RECT16 *rect + ){ + return U_WMRCORE_8U16_get( + contents, + (U_SIZE_WMRPIE), + U_P16(Radial2->y), + U_P16(Radial2->x), + U_P16(Radial1->y), + U_P16(Radial1->x), + U_P16(rect->bottom), + U_P16(rect->right), + U_P16(rect->top), + U_P16(rect->left) + ); +} + +/** + \brief Retrieve values from a U_WMRRECTANGLE record + \return length of the U_WMRRECTANGLE record, or NULL on error + \param contents record to extract data from + \param rect Boundaries. +*/ +int U_WMRRECTANGLE_get( + const char *contents, + U_RECT16 *rect + ){ + return U_WMRCORE_4U16_get( + contents, + (U_SIZE_WMRRECTANGLE), + U_P16(rect->bottom), + U_P16(rect->right), + U_P16(rect->top), + U_P16(rect->left) + ); +} + +/** + \brief Retrieve values from a U_WMRROUNDRECT record + \return length of the U_WMRROUNDRECT record, or NULL on error + \param contents record to extract data from + \param Width Horizontal rounding length. + \param Height Vertical rounding length. + \param rect Boundaries. +*/ +int U_WMRROUNDRECT_get( + const char *contents, + int16_t *Width, + int16_t *Height, + U_RECT16 *rect + ){ + return U_WMRCORE_6U16_get( + contents, + (U_SIZE_WMRROUNDRECT), + U_PP16(Height), + U_PP16(Width), + U_P16(rect->bottom), + U_P16(rect->right), + U_P16(rect->top), + U_P16(rect->left) + ); +} + +/** + \brief Get data from a U_WMRPATBLT record. + \return length of the U_WMRPATBLT record in bytes, or 0 on error + \param contents record to extract data from + \param Dst Destination UL corner in logical units + \param cwh W & H for Dst and Src in logical units + \param dwRop3 RasterOPeration Enumeration +*/ +int U_WMRPATBLT_get( + const char *contents, + U_POINT16 * Dst, + U_POINT16 * cwh, + uint32_t *dwRop3 + ){ + int size = U_WMRCORE_RECSAFE_get(contents, (U_SIZE_WMRPATBLT)); + if(!size)return(0); + memcpy(dwRop3, ( contents + offsetof(U_WMRPATBLT, rop3w)), 4); + cwh->y = *(int16_t *)( contents + offsetof(U_WMRPATBLT, Height )); + cwh->x = *(int16_t *)( contents + offsetof(U_WMRPATBLT, Width )); + Dst->y = *(int16_t *)( contents + offsetof(U_WMRPATBLT, yDst )); + Dst->x = *(int16_t *)( contents + offsetof(U_WMRPATBLT, xDst )); + return(size); +} + +/** + \brief Get data from a U_WMRSAVEDC record + \return length of the U_WMRSAVEDC record in bytes, or 0 on error + \param contents record to extract data from +*/ +int U_WMRSAVEDC_get( + const char *contents + ){ + return(U_WMRCORE_RECSAFE_get(contents, (U_SIZE_WMRSAVEDC))); +} + +/** + \brief Get data from a U_WMRSETPIXEL record + \return length of the U_WMRSETPIXEL record in bytes, or 0 on error + \param contents record to extract data from + \param Color pointer to a U_COLORREF variable where the color will be stored. + \param Coord pointer to a U_POINT16 variable where the coordinates will be stored. +*/ +int U_WMRSETPIXEL_get( + const char *contents, + U_COLORREF *Color, + U_POINT16 *Coord){ + return U_WMRCORE_1U16_CRF_2U16_get( + contents, + NULL, + Color, + U_P16(Coord->y), + U_P16(Coord->x) + ); +} + +/** + \brief Get data from a U_WMROFFSETCLIPRGN record + \return length of the U_WMROFFSETCLIPRGN record in bytes, or 0 on error + \param contents record to extract data from + \param offset pointer to a U_POINT16 variable where the x,y offsets will be stored. +*/ +int U_WMROFFSETCLIPRGN_get( + const char *contents, + U_POINT16 *offset + ){ + return U_WMRCORE_2U16_get(contents, (U_SIZE_WMROFFSETCLIPRGN), U_P16(offset->y), U_P16(offset->x)); +} + +/** + \brief Get data from a U_WMRTEXTOUT record + \return length of the U_WMRTEXTOUT record in bytes, or 0 on error + \param contents record to extract data from + \param Dst coordinates where text will be written + \param Length Number of characters in string. + \param string Pointer to string in WMF buffer in memory. This text is generally NOT null terminated!!! +*/ +int U_WMRTEXTOUT_get( + const char *contents, + U_POINT16 * Dst, + int16_t *Length, + const char **string + ){ + int16_t L2; + int off; + int size = U_WMRCORE_RECSAFE_get(contents, (U_SIZE_WMRTEXTOUT)); + if(!size)return(0); + *Length = *(int16_t *)(contents + offsetof(U_WMRTEXTOUT, Length)); + *string = contents + offsetof(U_WMRTEXTOUT, String); /* May not be null terminated!!! */ + L2 = *Length; + if(L2 & 1)L2++; + off = U_SIZE_METARECORD + 2 + L2; + memcpy(&Dst->y, contents + off, 2); off+=2; + memcpy(&Dst->x, contents + off, 2); + return(size); +} + +/** + \brief Get data from a U_WMRBITBLT record. + Note that unlike U_EMRBITBLT there is no scaling available - the Src and Dst + rectangles must be the same size. + \return length of the U_WMRBITBLT record in bytes, or 0 on error + \param contents record to extract data from + \param Dst Destination UL corner in logical units + \param cwh W & H for Dst and Src in logical units + \param Src Source UL corner in logical units + \param dwRop3 RasterOPeration Enumeration + \param Bm16 bitmap16 object (fields in it are all 0 if no bitmap is used) + \param px pointer to bitmap in memory, or NULL if not used +*/ +int U_WMRBITBLT_get( + const char *contents, + U_POINT16 * Dst, + U_POINT16 * cwh, + U_POINT16 * Src, + uint32_t *dwRop3, + U_BITMAP16 *Bm16, + const char **px + ){ + uint8_t xb; + uint32_t size = U_WMRCORE_RECSAFE_get(contents, (U_SIZE_WMRBITBLT_NOPX)); + if(!size)return(0); + xb = *(uint8_t *)( contents + offsetof(U_METARECORD, xb)); + if(U_TEST_NOPXB(size,xb)){ /* no bitmap */ + memcpy(dwRop3, ( contents + offsetof(U_WMRBITBLT_NOPX, rop3w)), 4); + Src->y = *(int16_t *)( contents + offsetof(U_WMRBITBLT_NOPX, ySrc )); + Src->x = *(int16_t *)( contents + offsetof(U_WMRBITBLT_NOPX, xSrc )); + cwh->y = *(int16_t *)( contents + offsetof(U_WMRBITBLT_NOPX, Height )); + cwh->x = *(int16_t *)( contents + offsetof(U_WMRBITBLT_NOPX, Width )); + Dst->y = *(int16_t *)( contents + offsetof(U_WMRBITBLT_NOPX, yDst )); + Dst->x = *(int16_t *)( contents + offsetof(U_WMRBITBLT_NOPX, xDst )); + memset(Bm16, 0, U_SIZE_BITMAP16); + *px = NULL; + } + else { /* yes bitmap */ + memcpy(dwRop3, ( contents + offsetof(U_WMRBITBLT_PX, rop3w)), 4); + Src->y = *(int16_t *)( contents + offsetof(U_WMRBITBLT_PX, ySrc )); + Src->x = *(int16_t *)( contents + offsetof(U_WMRBITBLT_PX, xSrc )); + cwh->y = *(int16_t *)( contents + offsetof(U_WMRBITBLT_PX, Height )); + cwh->x = *(int16_t *)( contents + offsetof(U_WMRBITBLT_PX, Width )); + Dst->y = *(int16_t *)( contents + offsetof(U_WMRBITBLT_PX, yDst )); + Dst->x = *(int16_t *)( contents + offsetof(U_WMRBITBLT_PX, xDst )); + memcpy(Bm16, ( contents + offsetof(U_WMRBITBLT_PX, bitmap)), U_SIZE_BITMAP16); + *px = ( contents + offsetof(U_WMRBITBLT_PX, bitmap) + U_SIZE_BITMAP16); + } + return(size); +} + +/** + \brief Get data from a U_WMRSTRETCHBLT record. + \return length of the U_WMRSTRETCHBLT record in bytes, or 0 on error + \param contents record to extract data from + \param Dst Destination UL corner in logical units + \param cDst Destination W & H in logical units + \param Src Source UL corner in logical units + \param cSrc Source W & H in logical units + \param dwRop3 RasterOPeration Enumeration + \param Bm16 bitmap16 object (fields in it are all 0 if no bitmap is used) + \param px pointer to bitmap in memory, or NULL if not used +*/ +int U_WMRSTRETCHBLT_get( + const char *contents, + U_POINT16 * Dst, + U_POINT16 * cDst, + U_POINT16 * Src, + U_POINT16 * cSrc, + uint32_t *dwRop3, + U_BITMAP16 *Bm16, + const char **px + ){ + uint8_t xb; + uint32_t size = U_WMRCORE_RECSAFE_get(contents, (U_SIZE_WMRSTRETCHBLT_NOPX)); + if(!size)return(0); + xb = *(uint8_t *)( contents + offsetof(U_METARECORD, xb)); + if(U_TEST_NOPXB(size,xb)){ /* no bitmap */ + memcpy(dwRop3, ( contents + offsetof(U_WMRSTRETCHBLT_NOPX, rop3w)), 4); + cSrc->y = *(int16_t *)( contents + offsetof(U_WMRSTRETCHBLT_NOPX, hSrc )); + cSrc->x = *(int16_t *)( contents + offsetof(U_WMRSTRETCHBLT_NOPX, wSrc )); + Src->y = *(int16_t *)( contents + offsetof(U_WMRSTRETCHBLT_NOPX, ySrc )); + Src->x = *(int16_t *)( contents + offsetof(U_WMRSTRETCHBLT_NOPX, xSrc )); + cDst->y = *(int16_t *)( contents + offsetof(U_WMRSTRETCHBLT_NOPX, hDst )); + cDst->x = *(int16_t *)( contents + offsetof(U_WMRSTRETCHBLT_NOPX, wDst )); + Dst->y = *(int16_t *)( contents + offsetof(U_WMRSTRETCHBLT_NOPX, yDst )); + Dst->x = *(int16_t *)( contents + offsetof(U_WMRSTRETCHBLT_NOPX, xDst )); + memset(Bm16, 0, U_SIZE_BITMAP16); + *px = NULL; + } + else { /* yes bitmap */ + memcpy(dwRop3, ( contents + offsetof(U_WMRSTRETCHBLT_PX, rop3w)), 4); + cSrc->y = *(int16_t *)( contents + offsetof(U_WMRSTRETCHBLT_PX, hSrc )); + cSrc->x = *(int16_t *)( contents + offsetof(U_WMRSTRETCHBLT_PX, wSrc )); + Src->y = *(int16_t *)( contents + offsetof(U_WMRSTRETCHBLT_PX, ySrc )); + Src->x = *(int16_t *)( contents + offsetof(U_WMRSTRETCHBLT_PX, xSrc )); + cDst->y = *(int16_t *)( contents + offsetof(U_WMRSTRETCHBLT_PX, hDst )); + cDst->x = *(int16_t *)( contents + offsetof(U_WMRSTRETCHBLT_PX, wDst )); + Dst->y = *(int16_t *)( contents + offsetof(U_WMRSTRETCHBLT_PX, yDst )); + Dst->x = *(int16_t *)( contents + offsetof(U_WMRSTRETCHBLT_PX, xDst )); + memcpy(Bm16, ( contents + offsetof(U_WMRSTRETCHBLT_PX, bitmap)), U_SIZE_BITMAP16); + *px = ( contents + offsetof(U_WMRSTRETCHBLT_PX, bitmap) + U_SIZE_BITMAP16); + } + return(size); +} + +/** + \brief Get data from a U_WMRPOLYGON record. + \return length of the U_WMRPOLYGON record in bytes, or 0 on error + \param contents record to extract data from + \param Length Number of points in the Polygon + \param Data pointer to array of U_POINT16 in memory. Pointer may not be aligned properly for structures. +*/ +int U_WMRPOLYGON_get( + const char *contents, + uint16_t *Length, + const char **Data + ){ + int size = U_WMRCORE_2U16_N16_get(contents, (U_SIZE_WMRPOLYGON), NULL, Length, Data); + if(size){ + int iLength = (*Length)*sizeof(U_POINT16); + if(IS_MEM_UNSAFE(*Data, iLength, contents+size))return(0); + } + return size; +} + +/** + \brief Get data from a U_WMRPOLYLINE record. + \return length of the U_WMRPOLYLINE record in bytes, or 0 on error + \param contents record to extract data from + \param Length Number of points in the Polyline + \param Data pointer to array of U_POINT16 in memory. Pointer may not be aligned properly for structures. +*/ +int U_WMRPOLYLINE_get( + const char *contents, + uint16_t *Length, + const char **Data + ){ + int size = U_WMRCORE_2U16_N16_get(contents, (U_SIZE_WMRPOLYGON), NULL, Length, Data); + if(size){ + int iLength = (*Length)*sizeof(U_POINT16); + if(IS_MEM_UNSAFE(*Data, iLength, contents+size))return(0); + } + return size; +} + +/** + \brief Get data from a U_WMRESCAPE record. + WARNING! Only three Escape record types are fully supported: SETLINECAP, SETLINEJOIN, SETMITERLIMIT. + Even these should not be set here directly, instead use the wsetlinecap_get(), wsetlinejoin_get(), + or wsetmiterlimit_get() functions. + Escape records created with this function, with the exception of the three named above, will not have + the byte orders in Data adjusted automatically. The user code must set Data to be little endian no + matter what the endianness of the current platform where the user code is running. + \return length of the U_WMRESCAPE record in bytes, or 0 on error + \param contents record to extract data from + \param Escape Escape function + \param Length Bytes in the Data + \param Data Array of Length bytes +*/ +int U_WMRESCAPE_get( + const char *contents, + uint16_t *Escape, + uint16_t *Length, + const char **Data + ){ + int size = U_WMRCORE_2U16_N16_get(contents, (U_SIZE_WMRESCAPE), Escape, Length, Data); + if(size){ + int iLength=*Length; + if(IS_MEM_UNSAFE(*Data, iLength, contents+size))return(0); + } + return size; +} + +/** + \brief Get data from a U_WMRRESTOREDC record + \return length of the U_WMRRESTOREDC record in bytes, or 0 on error + \param contents record to extract data from + \param DC DC to restore (relative if negative, absolute if positive) +*/ +int U_WMRRESTOREDC_get( + const char *contents, + int16_t *DC + ){ + return U_WMRCORE_1U16_get(contents, (U_SIZE_WMRRESTOREDC), (uint16_t *)DC); // signed, but it is just a memcpy, so this works +} + +/** + \brief Get data from a U_WMRFILLREGION record. + \return length of the U_WMRFILLREGION record in bytes, or 0 on error + \param contents record to extract data from + \param Region Region to fill + \param Brush Brush to fill with +*/ +int U_WMRFILLREGION_get( + const char *contents, + uint16_t *Region, + uint16_t *Brush + ){ + return U_WMRCORE_2U16_get(contents, (U_SIZE_WMRFILLREGION), Region, Brush); +} + +/** + \brief Get data from a U_WMRFRAMEREGION record. + \return length of the U_WMRFRAMEREGION record in bytes, or 0 on error + \param contents record to extract data from + \param Region Index of region to frame in object table + \param Brush Index of brush to use in frame in object table + \param Height in logical units (of frame) + \param Width in logical units (of frame) +*/ +int U_WMRFRAMEREGION_get( + const char *contents, + uint16_t *Region, + uint16_t *Brush, + int16_t *Height, + int16_t *Width + ){ + return U_WMRCORE_4U16_get(contents, (U_SIZE_WMRFRAMEREGION), Region, Brush, U_PP16(Height), U_PP16(Width)); +} + +/** + \brief Get data from a U_WMRINVERTREGION record. + \return length of the U_WMRINVERTREGION record in bytes, or 0 on error + \param contents record to extract data from + \param Region Index of region to invert. +*/ +int U_WMRINVERTREGION_get( + const char *contents, + uint16_t *Region + ){ + return U_WMRCORE_1U16_get(contents, (U_SIZE_WMRINVERTREGION), Region); +} + +/** + \brief Get data from a U_WMRPAINTREGION record. + \return length of the U_WMRPAINTREGION record in bytes, or 0 on error + \param contents record to extract data from + \param Region Index of region to paint with the current Brush. +*/ +int U_WMRPAINTREGION_get( + const char *contents, + uint16_t *Region + ){ + return U_WMRCORE_1U16_get(contents, (U_SIZE_WMRPAINTREGION), Region); +} + +/** + \brief Get data from a U_WMRSELECTCLIPREGION record. + \return length of the U_WMRSELECTCLIPREGION record in bytes, or 0 on error + \param contents record to extract data from + \param Region Index of region to become clipping region.. +*/ +int U_WMRSELECTCLIPREGION_get( + const char *contents, + uint16_t *Region + ){ + return U_WMRCORE_1U16_get(contents, (U_SIZE_WMRSELECTCLIPREGION), Region); + +} + +/** + \brief Get data from a U_WMRSELECTOBJECT record. + \return length of the U_WMRSELECTOBJECT record in bytes, or 0 on error + \param contents record to extract data from + \param Object Index of object which is made active. +*/ +int U_WMRSELECTOBJECT_get( + const char *contents, + uint16_t *Object + ){ + return U_WMRCORE_1U16_get(contents, (U_SIZE_WMRSELECTOBJECT), Object); +} + +/** + \brief Get data from a U_WMRSETTEXTALIGN record. + \return length of the U_WMRSETTEXTALIGN record in bytes, or 0 on error + \param contents record to extract data from + \param Mode TextAlignment Enumeration. +*/ +int U_WMRSETTEXTALIGN_get( + const char *contents, + uint16_t *Mode + ){ + return U_WMRCORE_1U16_get(contents, (U_SIZE_WMRSETTEXTALIGN), Mode); +} + +/** in GDI and Wine, not in WMF manual. +*/ +int U_WMRDRAWTEXT_get(void){ /* in Wine, not in WMF PDF. */ + return U_WMRCORENONE_get("U_WMRDRAWTEXT"); +} + +/** + \brief Retrieve values from a U_WMRCHORD record + \return length of the U_WMRCHORD record, or NULL on error + \param contents record to extract data from + \param Radial1 Start of Chord + \param Radial2 End of Chord + \param rect Bounding rectangle. +*/ +int U_WMRCHORD_get( + const char *contents, + U_POINT16 *Radial1, + U_POINT16 *Radial2, + U_RECT16 *rect + ){ + return U_WMRCORE_8U16_get( + contents, + (U_SIZE_WMRCHORD), + U_P16(Radial2->y), + U_P16(Radial2->x), + U_P16(Radial1->y), + U_P16(Radial1->x), + U_P16(rect->bottom), + U_P16(rect->right), + U_P16(rect->top), + U_P16(rect->left) + ); +} + +/** + \brief Get data from a U_WMRSETMAPPERFLAGS record. + \return length of the U_WMRSETMAPPERFLAGS record in bytes, or 0 on error + \param contents record to extract data from + \param Mode If 1 bit set font mapper selects only matching aspect fonts. +*/ +int U_WMRSETMAPPERFLAGS_get( + const char *contents, + uint32_t *Mode + ){ + int size = U_WMRCORE_RECSAFE_get(contents, (U_SIZE_WMRSETMAPPERFLAGS)); + if(!size)return(0); + memcpy(Mode, contents + U_SIZE_METARECORD, 4); + return(size); +} + +/** + \brief Get data from a U_WMREXTTEXTOUT record. + \return length of the U_WMREXTTEXTOUT record in bytes, or 0 on error + \param contents record to extract data from + \param Dst {X,Y} coordinates where the string is to be written. + \param Length Stringlength in bytes + \param Opts ExtTextOutOptions Flags + \param string String to write (Latin1 encoding) + \param dx Kerning information. Must have same number of entries as Length. + \param rect Used when when U_ETO_OPAQUE or U_ETO_CLIPPED bits are set in Opts +*/ +int U_WMREXTTEXTOUT_get( + const char *contents, + U_POINT16 * Dst, + int16_t *Length, + uint16_t *Opts, + const char **string, + const int16_t **dx, + U_RECT16 *rect + ){ + int size = U_WMRCORE_RECSAFE_get(contents, (U_SIZE_WMREXTTEXTOUT)); + int off = U_SIZE_METARECORD; + if(!size)return(0); + Dst->y = *(int16_t *)( contents + offsetof(U_WMREXTTEXTOUT, y )); + Dst->x = *(int16_t *)( contents + offsetof(U_WMREXTTEXTOUT, x )); + *Length = *(int16_t *)( contents + offsetof(U_WMREXTTEXTOUT, Length )); + *Opts = *(uint16_t *)(contents + offsetof(U_WMREXTTEXTOUT, Opts )); + off = U_SIZE_WMREXTTEXTOUT; + if(*Opts & (U_ETO_OPAQUE | U_ETO_CLIPPED)){ memcpy(rect, (contents + off), U_SIZE_RECT16); off += U_SIZE_RECT16; } + else { memset(rect, 0, U_SIZE_RECT16); } + *string = (contents + off); + off += 2*((*Length +1)/2); + if(*Length){ *dx = (int16_t *)(contents + off); } + else { *dx = NULL; } + return(size); +} + +/** + \brief Get data from a U_WMRSETDIBTODEV record + \return length of the U_WMRSETDIBTODEV record in bytes, or 0 on error + \param contents record to extract data from + \param Dst UL corner of Dst rect in logical units + \param cwh Width and Height in logical units + \param Src UL corner of Src rect in logical units + \param cUsage ColorUsage enumeration + \param ScanCount Number of scan lines in Src + \param StartScan First Scan line in Src + \param dib DeviceIndependentBitmap object +*/ +int U_WMRSETDIBTODEV_get( + const char *contents, + U_POINT16 * Dst, + U_POINT16 * cwh, + U_POINT16 * Src, + uint16_t *cUsage, + uint16_t *ScanCount, + uint16_t *StartScan, + const char **dib + ){ + int size = U_WMRCORE_RECSAFE_get(contents, (U_SIZE_WMRSETDIBTODEV)); + if(!size)return(0); + *cUsage = *(uint16_t *)(contents + offsetof(U_WMRSETDIBTODEV, cUsage )); + *ScanCount = *(uint16_t *)(contents + offsetof(U_WMRSETDIBTODEV, ScanCount )); + *StartScan = *(uint16_t *)(contents + offsetof(U_WMRSETDIBTODEV, StartScan )); + Src->y = *(int16_t *)( contents + offsetof(U_WMRSETDIBTODEV, ySrc )); + Src->x = *(int16_t *)( contents + offsetof(U_WMRSETDIBTODEV, xSrc )); + cwh->y = *(int16_t *)( contents + offsetof(U_WMRSETDIBTODEV, Height )); + cwh->x = *(int16_t *)( contents + offsetof(U_WMRSETDIBTODEV, Width )); + Dst->y = *(int16_t *)( contents + offsetof(U_WMRSETDIBTODEV, yDst )); + Dst->x = *(int16_t *)( contents + offsetof(U_WMRSETDIBTODEV, xDst )); + *dib = ( contents + offsetof(U_WMRSETDIBTODEV, dib )); + if(!packed_DIB_safe(*dib, *dib+size))return(0); + return(size); +} + +/** + \brief Get data from a U_WMRSELECTPALETTE record + \return length of the U_WMRSELECTPALETTE record in bytes, or 0 on error + \param contents record to extract data from + \param Palette Index of Palette to make active. +*/ +int U_WMRSELECTPALETTE_get( + const char *contents, + uint16_t *Palette + ){ + return U_WMRCORE_1U16_get(contents, (U_SIZE_WMRSELECTPALETTE), Palette); +} + +/** + \brief Get data from a U_WMRREALIZEPALETTE record + \return length of the U_WMRREALIZEPALETTE record in bytes, or 0 on error + \param contents record to extract data from +*/ +int U_WMRREALIZEPALETTE_get( + const char *contents + ){ + return U_WMRCORE_RECSAFE_get(contents, (U_SIZE_WMRREALIZEPALETTE)); +} + +/** + \brief Get data from a U_WMRSETPALENTRIES record + \return length of the U_WMRSETPALENTRIES record in bytes, or 0 on error + \param contents record to extract data from + \param Palette Redefines a set of RGB values for the current active Palette. + \param PalEntries Array of Palette Entries +*/ +int U_WMRANIMATEPALETTE_get( + const char *contents, + U_PALETTE *Palette, + const char **PalEntries + ){ + return U_WMRCORE_PALETTE_get(contents, (U_SIZE_WMRANIMATEPALETTE), Palette, PalEntries); +} + +/** + \brief Get data from a U_WMRSETPALENTRIES record + \return length of the U_WMRSETPALENTRIES record in bytes, or 0 on error + \param contents record to extract data from + \param Palette Defines a set of RGB values for the current active Palette. + \param PalEntries Array of Palette Entries +*/ +int U_WMRSETPALENTRIES_get( + const char *contents, + U_PALETTE *Palette, + const char **PalEntries + ){ + return U_WMRCORE_PALETTE_get(contents, (U_SIZE_WMRSETPALENTRIES), Palette, PalEntries); +} + +/** + \brief Get data from a U_WMR_POLYPOLYGON record. + \return length of the U_WMR_POLYPOLYGON record in bytes, or 0 on error + \param contents record to extract data from + \param nPolys Number of elements in aPolyCounts + \param aPolyCounts Number of points in each poly (sequential) + \param Points pointer to array of U_POINT16 in memory. Probably not aligned. +*/ +int U_WMRPOLYPOLYGON_get( + const char *contents, + uint16_t *nPolys, + const uint16_t **aPolyCounts, + const char **Points + ){ + int size = U_WMRCORE_RECSAFE_get(contents, (U_SIZE_WMRPOLYPOLYGON)); + if(!size)return(0); + contents += offsetof(U_WMRPOLYPOLYGON, PPolygon); + memcpy(nPolys, contents + offsetof(U_POLYPOLYGON, nPolys), 2); + *aPolyCounts = (uint16_t *)(contents + offsetof(U_POLYPOLYGON, aPolyCounts)); + *Points = (contents + offsetof(U_POLYPOLYGON, aPolyCounts) + *nPolys*2); + return(size); +} + +/** + \brief Get data from a U_WMRRESIZEPALETTE record + \return length of the U_WMRRESIZEPALETTE record in bytes, or 0 on error + \param contents record to extract data from + \param Palette Changes the size of the currently active Palette. +*/ +int U_WMRRESIZEPALETTE_get( + const char *contents, + uint16_t *Palette + ){ + return U_WMRCORE_1U16_get(contents, (U_SIZE_WMRRESIZEPALETTE), Palette); +} + +//! \cond +int U_WMR3A_get(void){ + return U_WMRCORENONE_get("U_WMR3A"); +} + +int U_WMR3B_get(void){ + return U_WMRCORENONE_get("U_WMR3B"); +} + +int U_WMR3C_get(void){ + return U_WMRCORENONE_get("U_WMR3C"); +} + +int U_WMR3D_get(void){ + return U_WMRCORENONE_get("U_WMR3D"); +} + +int U_WMR3E_get(void){ + return U_WMRCORENONE_get("U_WMR3E"); +} + +int U_WMR3F_get(void){ + return U_WMRCORENONE_get("U_WMR3F"); +} +//! \endcond + +// U_WMRDIBBITBLT_get +/** + \brief Get data from a U_WMRDIBITBLT record. + \return length of the U_WMRDIBITBLT record in bytes, or 0 on error + \param contents record to extract data from + \param Dst Destination UL corner in logical units + \param Src Source UL corner in logical units + \param cwh W & H in logical units of Src and Dst + \param dwRop3 RasterOPeration Enumeration + \param dib pointer to dib in WMF in memory. Most likely not aligned. +*/ +int U_WMRDIBBITBLT_get( + const char *contents, + U_POINT16 * Dst, + U_POINT16 * cwh, + U_POINT16 * Src, + uint32_t *dwRop3, + const char **dib + ){ + uint8_t xb; + uint32_t size = U_WMRCORE_RECSAFE_get(contents, (U_SIZE_WMRDIBBITBLT_NOPX)); + if(!size)return(0); + xb = *(uint8_t *)( contents + offsetof(U_METARECORD, xb)); + if(U_TEST_NOPXB(size,xb)){ /* no bitmap */ + memcpy(dwRop3, ( contents + offsetof(U_WMRDIBBITBLT_NOPX, rop3w)), 4); + Src->y = *(int16_t *)( contents + offsetof(U_WMRDIBBITBLT_NOPX, ySrc )); + Src->x = *(int16_t *)( contents + offsetof(U_WMRDIBBITBLT_NOPX, xSrc )); + cwh->y = *(int16_t *)( contents + offsetof(U_WMRDIBBITBLT_NOPX, Height )); + cwh->x = *(int16_t *)( contents + offsetof(U_WMRDIBBITBLT_NOPX, Width )); + Dst->y = *(int16_t *)( contents + offsetof(U_WMRDIBBITBLT_NOPX, yDst )); + Dst->x = *(int16_t *)( contents + offsetof(U_WMRDIBBITBLT_NOPX, xDst )); + *dib = NULL; + } + else { /* yes bitmap */ + memcpy(dwRop3, ( contents + offsetof(U_WMRDIBBITBLT_PX, rop3w)), 4); + Src->y = *(int16_t *)( contents + offsetof(U_WMRDIBBITBLT_PX, ySrc )); + Src->x = *(int16_t *)( contents + offsetof(U_WMRDIBBITBLT_PX, xSrc )); + cwh->y = *(int16_t *)( contents + offsetof(U_WMRDIBBITBLT_PX, Height )); + cwh->x = *(int16_t *)( contents + offsetof(U_WMRDIBBITBLT_PX, Width )); + Dst->y = *(int16_t *)( contents + offsetof(U_WMRDIBBITBLT_PX, yDst )); + Dst->x = *(int16_t *)( contents + offsetof(U_WMRDIBBITBLT_PX, xDst )); + *dib = ( contents + offsetof(U_WMRDIBBITBLT_PX, dib )); + if(!packed_DIB_safe(*dib, *dib+size))return(0); + } + return(size); +} + +/** + \brief Get data from a U_WMRSTRETCHDIB record. + \return length of the U_WMRSTRETCHDIB record in bytes, or 0 on error + \param contents record to extract data from + \param Dst Destination UL corner in logical units + \param cDst Destination W & H in logical units + \param Src Source UL corner in logical units + \param cSrc Source W & H in logical units + \param dwRop3 RasterOPeration Enumeration + \param dib pointer to dib in WMF in memory. Most likely not aligned. +*/ +int U_WMRDIBSTRETCHBLT_get( + const char *contents, + U_POINT16 * Dst, + U_POINT16 * cDst, + U_POINT16 * Src, + U_POINT16 * cSrc, + uint32_t *dwRop3, + const char **dib + ){ + uint8_t xb; + uint32_t size = U_WMRCORE_RECSAFE_get(contents, (U_SIZE_WMRDIBSTRETCHBLT_NOPX)); + if(!size)return(0); + xb = *(uint8_t *)( contents + offsetof(U_METARECORD, xb)); + if(U_TEST_NOPXB(size,xb)){ /* no bitmap */ + memcpy(dwRop3 , ( contents + offsetof(U_WMRDIBSTRETCHBLT_NOPX, rop3w)), 4); + Src->y = *(int16_t *)( contents + offsetof(U_WMRDIBSTRETCHBLT_NOPX, ySrc )); + Src->x = *(int16_t *)( contents + offsetof(U_WMRDIBSTRETCHBLT_NOPX, xSrc )); + cSrc->y = *(int16_t *)( contents + offsetof(U_WMRDIBSTRETCHBLT_NOPX, hSrc )); + cSrc->x = *(int16_t *)( contents + offsetof(U_WMRDIBSTRETCHBLT_NOPX, wSrc )); + Dst->y = *(int16_t *)( contents + offsetof(U_WMRDIBSTRETCHBLT_NOPX, yDst )); + Dst->x = *(int16_t *)( contents + offsetof(U_WMRDIBSTRETCHBLT_NOPX, xDst )); + cDst->y = *(int16_t *)( contents + offsetof(U_WMRDIBSTRETCHBLT_NOPX, hDst )); + cDst->x = *(int16_t *)( contents + offsetof(U_WMRDIBSTRETCHBLT_NOPX, wDst )); + *dib = NULL; + } + else { /* yes bitmap */ + memcpy(dwRop3 , ( contents + offsetof(U_WMRDIBSTRETCHBLT_PX, rop3w)), 4); + Src->y = *(int16_t *)( contents + offsetof(U_WMRDIBSTRETCHBLT_PX, ySrc )); + Src->x = *(int16_t *)( contents + offsetof(U_WMRDIBSTRETCHBLT_PX, xSrc )); + cSrc->y = *(int16_t *)( contents + offsetof(U_WMRDIBSTRETCHBLT_PX, hSrc )); + cSrc->x = *(int16_t *)( contents + offsetof(U_WMRDIBSTRETCHBLT_PX, wSrc )); + Dst->y = *(int16_t *)( contents + offsetof(U_WMRDIBSTRETCHBLT_PX, yDst )); + Dst->x = *(int16_t *)( contents + offsetof(U_WMRDIBSTRETCHBLT_PX, xDst )); + cDst->y = *(int16_t *)( contents + offsetof(U_WMRDIBSTRETCHBLT_PX, hDst )); + cDst->x = *(int16_t *)( contents + offsetof(U_WMRDIBSTRETCHBLT_PX, wDst )); + *dib = ( contents + offsetof(U_WMRDIBSTRETCHBLT_PX, dib )); + if(!packed_DIB_safe(*dib, *dib+size))return(0); + } + return(size); +} + +/** + \brief Get data from a U_WMRDIBCREATEPATTERNBRUSH record. + Returns an image as either a DIB (Bmi/CbPx/Px defined) or a Bitmap16 (Bm16 defined). + WARNING - U_WMRCREATEPATTERNBRUSH has been declared obsolete and application support is spotty - + this function is still valid though, for those instances where old WMF input files are encountered. + \return length of the U_WMRDIBCREATEPATTERNBRUSH record in bytes, or 0 on error + \param contents record to extract data from + \param Style BrushStyle Enumeration + \param cUsage DIBcolors Enumeration + \param Bm16 pointer to a U_BITMAP16 in WMF in memory. Most likely not aligned. NULL if dib is used instead. + \param dib pointer to a dib in WMF in memory. Most likely not aligned. NULL if Bm16 is used instead. + */ +int U_WMRDIBCREATEPATTERNBRUSH_get( + const char *contents, + uint16_t *Style, + uint16_t *cUsage, + const char **Bm16, + const char **dib + ){ + int size = U_WMRCORE_RECSAFE_get(contents, (U_SIZE_WMRDIBCREATEPATTERNBRUSH)); + if(!size)return(0); + + *Style = *(uint16_t *)(contents + offsetof(U_WMRDIBCREATEPATTERNBRUSH, Style )); + *cUsage = *(uint16_t *)(contents + offsetof(U_WMRDIBCREATEPATTERNBRUSH, cUsage )); + if(*Style == U_BS_PATTERN){ + *Bm16 = (contents + offsetof(U_WMRDIBCREATEPATTERNBRUSH, Src)); + *dib = NULL; + /* The WMF spec says that Style == U_BS_PATTERN _SHOULD_ be a bitmap16. + However there are instances when it is actually a DIB. U_WMRDIBCREATEPATTERNBRUSH_get + tries to detect this by looking for bogus values when the BM16 is interpreted as such, + and if it finds them, then it returns a dib instead. + */ + U_BITMAP16 TmpBm16; + memcpy(&TmpBm16, *Bm16, U_SIZE_BITMAP16); + if(TmpBm16.Width <= 0 || TmpBm16.Height <= 0 || TmpBm16.Planes != 1 || TmpBm16.BitsPixel == 0){ + *Bm16 = NULL; + *dib = (contents + offsetof(U_WMRDIBCREATEPATTERNBRUSH, Src)); + if(!packed_DIB_safe(*dib, *dib+size))return(0); + } + } + else { /* from DIB */ + *Bm16 = NULL; + *dib = (contents + offsetof(U_WMRDIBCREATEPATTERNBRUSH, Src)); + if(!packed_DIB_safe(*dib, *dib+size))return(0); + } + return(size); +} + +/** + \brief Get data from a U_WMRSTRETCHDIB record. + \return length of the U_WMRSTRETCHDIB record in bytes, or 0 on error + \param contents record to extract data from + \param Dst Destination UL corner in logical units + \param cDst Destination W & H in logical units + \param Src Source UL corner in logical units + \param cSrc Source W & H in logical units + \param cUsage DIBColors Enumeration + \param dwRop3 RasterOPeration Enumeration + \param dib (Optional) device independent bitmap +*/ +int U_WMRSTRETCHDIB_get( + const char *contents, + U_POINT16 * Dst, + U_POINT16 * cDst, + U_POINT16 * Src, + U_POINT16 * cSrc, + uint16_t *cUsage, + uint32_t *dwRop3, + const char **dib + ){ + int size = U_WMRCORE_RECSAFE_get(contents, (U_SIZE_WMRSTRETCHDIB)); + if(!size)return(0); + + memcpy(dwRop3, ( contents + offsetof(U_WMRSTRETCHDIB, rop3w)), 4); + *cUsage = *(uint16_t *)( contents + offsetof(U_WMRSTRETCHDIB, cUsage )); + cSrc->y = *(int16_t *)( contents + offsetof(U_WMRSTRETCHDIB, hSrc )); + cSrc->x = *(int16_t *)( contents + offsetof(U_WMRSTRETCHDIB, wSrc )); + Src->y = *(int16_t *)( contents + offsetof(U_WMRSTRETCHDIB, ySrc )); + Src->x = *(int16_t *)( contents + offsetof(U_WMRSTRETCHDIB, xSrc )); + cDst->y = *(int16_t *)( contents + offsetof(U_WMRSTRETCHDIB, hDst )); + cDst->x = *(int16_t *)( contents + offsetof(U_WMRSTRETCHDIB, wDst )); + Dst->y = *(int16_t *)( contents + offsetof(U_WMRSTRETCHDIB, yDst )); + Dst->x = *(int16_t *)( contents + offsetof(U_WMRSTRETCHDIB, xDst )); + *dib = ( contents + offsetof(U_WMRSTRETCHDIB, dib )); + if(!packed_DIB_safe(*dib, *dib+size))return(0); + return(size); +} + +//! \cond +int U_WMR44_get(void){ + return U_WMRCORENONE_get("U_WMR44"); +} + +int U_WMR45_get(void){ + return U_WMRCORENONE_get("U_WMR45"); +} + +int U_WMR46_get(void){ + return U_WMRCORENONE_get("U_WMR46"); +} + +int U_WMR47_get(void){ + return U_WMRCORENONE_get("U_WMR47"); +} +//! \endcond + +/** + \brief Retrieve values from a U_WMREXTFLOODFILL record + \return length of the U_WMREXTFLOODFILL record, or NULL on error + \param contents record to extract data from + \param Mode FloodFill Enumeration. + \param Color Color to Fill with. + \param coord Location to start fill. +*/ +int U_WMREXTFLOODFILL_get( + const char *contents, + uint16_t *Mode, + U_COLORREF *Color, + U_POINT16 * coord + ){ + return U_WMRCORE_1U16_CRF_2U16_get( + contents, + Mode, + Color, + U_P16(coord->y), + U_P16(coord->x) + ); +} + +//! \cond +int U_WMR49_get(void){ + return U_WMRCORENONE_get("U_WMR49"); +} + +int U_WMR4A_get(void){ + return U_WMRCORENONE_get("U_WMR4A"); +} + +int U_WMR4B_get(void){ + return U_WMRCORENONE_get("U_WMR4B"); +} + +int U_WMR4C_get(void){ + return U_WMRCORENONE_get("U_WMRRESETDOC"); +} + +int U_WMR4D_get(void){ + return U_WMRCORENONE_get("U_WMRSTARTDOC"); +} + +int U_WMR4E_get(void){ + return U_WMRCORENONE_get("U_WMR4E"); +} + +int U_WMR4F_get(void){ + return U_WMRCORENONE_get("U_WMRSTARTPAGE"); +} + +int U_WMR50_get(void){ + return U_WMRCORENONE_get("U_WMRENDPAGE"); +} + +int U_WMR51_get(void){ + return U_WMRCORENONE_get("U_WMR51"); +} + +int U_WMRABORTDOC_get(void){ + return U_WMRCORENONE_get("U_WMRABORTDOC"); +} + +int U_WMR53_get(void){ + return U_WMRCORENONE_get("U_WMR53"); +} + +int U_WMR54_get(void){ + return U_WMRCORENONE_get("U_WMR54"); +} + +int U_WMR55_get(void){ + return U_WMRCORENONE_get("U_WMR55"); +} + +int U_WMR56_get(void){ + return U_WMRCORENONE_get("U_WMR56"); +} + +int U_WMR57_get(void){ + return U_WMRCORENONE_get("U_WMR57"); +} + +int U_WMR58_get(void){ + return U_WMRCORENONE_get("U_WMR58"); +} + +int U_WMR59_get(void){ + return U_WMRCORENONE_get("U_WMR59"); +} + +int U_WMR5A_get(void){ + return U_WMRCORENONE_get("U_WMR5A"); +} + +int U_WMR5B_get(void){ + return U_WMRCORENONE_get("U_WMR5B"); +} + +int U_WMR5C_get(void){ + return U_WMRCORENONE_get("U_WMR5C"); +} + +int U_WMR5D_get(void){ + return U_WMRCORENONE_get("U_WMR5D"); +} + +int U_WMR5E_get(void){ + return U_WMRCORENONE_get("U_WMRENDDOC"); +} + +int U_WMR5F_get(void){ + return U_WMRCORENONE_get("U_WMR5F"); +} + +int U_WMR60_get(void){ + return U_WMRCORENONE_get("U_WMR60"); +} + +int U_WMR61_get(void){ + return U_WMRCORENONE_get("U_WMR61"); +} + +int U_WMR62_get(void){ + return U_WMRCORENONE_get("U_WMR62"); +} + +int U_WMR63_get(void){ + return U_WMRCORENONE_get("U_WMR63"); +} + +int U_WMR64_get(void){ + return U_WMRCORENONE_get("U_WMR64"); +} + +int U_WMR65_get(void){ + return U_WMRCORENONE_get("U_WMR65"); +} + +int U_WMR66_get(void){ + return U_WMRCORENONE_get("U_WMR66"); +} + +int U_WMR67_get(void){ + return U_WMRCORENONE_get("U_WMR67"); +} + +int U_WMR68_get(void){ + return U_WMRCORENONE_get("U_WMR68"); +} + +int U_WMR69_get(void){ + return U_WMRCORENONE_get("U_WMR69"); +} + +int U_WMR6A_get(void){ + return U_WMRCORENONE_get("U_WMR6A"); +} + +int U_WMR6B_get(void){ + return U_WMRCORENONE_get("U_WMR6B"); +} + +int U_WMR6C_get(void){ + return U_WMRCORENONE_get("U_WMR6C"); +} + +int U_WMR6D_get(void){ + return U_WMRCORENONE_get("U_WMR6D"); +} + +int U_WMR6E_get(void){ + return U_WMRCORENONE_get("U_WMR6E"); +} + +int U_WMR6F_get(void){ + return U_WMRCORENONE_get("U_WMR6F"); +} + +int U_WMR70_get(void){ + return U_WMRCORENONE_get("U_WMR70"); +} + +int U_WMR71_get(void){ + return U_WMRCORENONE_get("U_WMR71"); +} + +int U_WMR72_get(void){ + return U_WMRCORENONE_get("U_WMR72"); +} + +int U_WMR73_get(void){ + return U_WMRCORENONE_get("U_WMR73"); +} + +int U_WMR74_get(void){ + return U_WMRCORENONE_get("U_WMR74"); +} + +int U_WMR75_get(void){ + return U_WMRCORENONE_get("U_WMR75"); +} + +int U_WMR76_get(void){ + return U_WMRCORENONE_get("U_WMR76"); +} + +int U_WMR77_get(void){ + return U_WMRCORENONE_get("U_WMR77"); +} + +int U_WMR78_get(void){ + return U_WMRCORENONE_get("U_WMR78"); +} + +int U_WMR79_get(void){ + return U_WMRCORENONE_get("U_WMR79"); +} + +int U_WMR7A_get(void){ + return U_WMRCORENONE_get("U_WMR7A"); +} + +int U_WMR7B_get(void){ + return U_WMRCORENONE_get("U_WMR7B"); +} + +int U_WMR7C_get(void){ + return U_WMRCORENONE_get("U_WMR7C"); +} + +int U_WMR7D_get(void){ + return U_WMRCORENONE_get("U_WMR7D"); +} + +int U_WMR7E_get(void){ + return U_WMRCORENONE_get("U_WMR7E"); +} + +int U_WMR7F_get(void){ + return U_WMRCORENONE_get("U_WMR7F"); +} + +int U_WMR80_get(void){ + return U_WMRCORENONE_get("U_WMR80"); +} + +int U_WMR81_get(void){ + return U_WMRCORENONE_get("U_WMR81"); +} + +int U_WMR82_get(void){ + return U_WMRCORENONE_get("U_WMR82"); +} + +int U_WMR83_get(void){ + return U_WMRCORENONE_get("U_WMR83"); +} + +int U_WMR84_get(void){ + return U_WMRCORENONE_get("U_WMR84"); +} + +int U_WMR85_get(void){ + return U_WMRCORENONE_get("U_WMR85"); +} + +int U_WMR86_get(void){ + return U_WMRCORENONE_get("U_WMR86"); +} + +int U_WMR87_get(void){ + return U_WMRCORENONE_get("U_WMR87"); +} + +int U_WMR88_get(void){ + return U_WMRCORENONE_get("U_WMR88"); +} + +int U_WMR89_get(void){ + return U_WMRCORENONE_get("U_WMR89"); +} + +int U_WMR8A_get(void){ + return U_WMRCORENONE_get("U_WMR8A"); +} + +int U_WMR8B_get(void){ + return U_WMRCORENONE_get("U_WMR8B"); +} + +int U_WMR8C_get(void){ + return U_WMRCORENONE_get("U_WMR8C"); +} + +int U_WMR8D_get(void){ + return U_WMRCORENONE_get("U_WMR8D"); +} + +int U_WMR8E_get(void){ + return U_WMRCORENONE_get("U_WMR8E"); +} + +int U_WMR8F_get(void){ + return U_WMRCORENONE_get("U_WMR8F"); +} + +int U_WMR90_get(void){ + return U_WMRCORENONE_get("U_WMR90"); +} + +int U_WMR91_get(void){ + return U_WMRCORENONE_get("U_WMR91"); +} + +int U_WMR92_get(void){ + return U_WMRCORENONE_get("U_WMR92"); +} + +int U_WMR93_get(void){ + return U_WMRCORENONE_get("U_WMR93"); +} + +int U_WMR94_get(void){ + return U_WMRCORENONE_get("U_WMR94"); +} + +int U_WMR95_get(void){ + return U_WMRCORENONE_get("U_WMR95"); +} + +int U_WMR96_get(void){ + return U_WMRCORENONE_get("U_WMR96"); +} + +int U_WMR97_get(void){ + return U_WMRCORENONE_get("U_WMR97"); +} + +int U_WMR98_get(void){ + return U_WMRCORENONE_get("U_WMR98"); +} + +int U_WMR99_get(void){ + return U_WMRCORENONE_get("U_WMR99"); +} + +int U_WMR9A_get(void){ + return U_WMRCORENONE_get("U_WMR9A"); +} + +int U_WMR9B_get(void){ + return U_WMRCORENONE_get("U_WMR9B"); +} + +int U_WMR9C_get(void){ + return U_WMRCORENONE_get("U_WMR9C"); +} + +int U_WMR9D_get(void){ + return U_WMRCORENONE_get("U_WMR9D"); +} + +int U_WMR9E_get(void){ + return U_WMRCORENONE_get("U_WMR9E"); +} + +int U_WMR9F_get(void){ + return U_WMRCORENONE_get("U_WMR9F"); +} + +int U_WMRA0_get(void){ + return U_WMRCORENONE_get("U_WMRA0"); +} + +int U_WMRA1_get(void){ + return U_WMRCORENONE_get("U_WMRA1"); +} + +int U_WMRA2_get(void){ + return U_WMRCORENONE_get("U_WMRA2"); +} + +int U_WMRA3_get(void){ + return U_WMRCORENONE_get("U_WMRA3"); +} + +int U_WMRA4_get(void){ + return U_WMRCORENONE_get("U_WMRA4"); +} + +int U_WMRA5_get(void){ + return U_WMRCORENONE_get("U_WMRA5"); +} + +int U_WMRA6_get(void){ + return U_WMRCORENONE_get("U_WMRA6"); +} + +int U_WMRA7_get(void){ + return U_WMRCORENONE_get("U_WMRA7"); +} + +int U_WMRA8_get(void){ + return U_WMRCORENONE_get("U_WMRA8"); +} + +int U_WMRA9_get(void){ + return U_WMRCORENONE_get("U_WMRA9"); +} + +int U_WMRAA_get(void){ + return U_WMRCORENONE_get("U_WMRAA"); +} + +int U_WMRAB_get(void){ + return U_WMRCORENONE_get("U_WMRAB"); +} + +int U_WMRAC_get(void){ + return U_WMRCORENONE_get("U_WMRAC"); +} + +int U_WMRAD_get(void){ + return U_WMRCORENONE_get("U_WMRAD"); +} + +int U_WMRAE_get(void){ + return U_WMRCORENONE_get("U_WMRAE"); +} + +int U_WMRAF_get(void){ + return U_WMRCORENONE_get("U_WMRAF"); +} + +int U_WMRB0_get(void){ + return U_WMRCORENONE_get("U_WMRB0"); +} + +int U_WMRB1_get(void){ + return U_WMRCORENONE_get("U_WMRB1"); +} + +int U_WMRB2_get(void){ + return U_WMRCORENONE_get("U_WMRB2"); +} + +int U_WMRB3_get(void){ + return U_WMRCORENONE_get("U_WMRB3"); +} + +int U_WMRB4_get(void){ + return U_WMRCORENONE_get("U_WMRB4"); +} + +int U_WMRB5_get(void){ + return U_WMRCORENONE_get("U_WMRB5"); +} + +int U_WMRB6_get(void){ + return U_WMRCORENONE_get("U_WMRB6"); +} + +int U_WMRB7_get(void){ + return U_WMRCORENONE_get("U_WMRB7"); +} + +int U_WMRB8_get(void){ + return U_WMRCORENONE_get("U_WMRB8"); +} + +int U_WMRB9_get(void){ + return U_WMRCORENONE_get("U_WMRB9"); +} + +int U_WMRBA_get(void){ + return U_WMRCORENONE_get("U_WMRBA"); +} + +int U_WMRBB_get(void){ + return U_WMRCORENONE_get("U_WMRBB"); +} + +int U_WMRBC_get(void){ + return U_WMRCORENONE_get("U_WMRBC"); +} + +int U_WMRBD_get(void){ + return U_WMRCORENONE_get("U_WMRBD"); +} + +int U_WMRBE_get(void){ + return U_WMRCORENONE_get("U_WMRBE"); +} + +int U_WMRBF_get(void){ + return U_WMRCORENONE_get("U_WMRBF"); +} + +int U_WMRC0_get(void){ + return U_WMRCORENONE_get("U_WMRC0"); +} + +int U_WMRC1_get(void){ + return U_WMRCORENONE_get("U_WMRC1"); +} + +int U_WMRC2_get(void){ + return U_WMRCORENONE_get("U_WMRC2"); +} + +int U_WMRC3_get(void){ + return U_WMRCORENONE_get("U_WMRC3"); +} + +int U_WMRC4_get(void){ + return U_WMRCORENONE_get("U_WMRC4"); +} + +int U_WMRC5_get(void){ + return U_WMRCORENONE_get("U_WMRC5"); +} + +int U_WMRC6_get(void){ + return U_WMRCORENONE_get("U_WMRC6"); +} + +int U_WMRC7_get(void){ + return U_WMRCORENONE_get("U_WMRC7"); +} + +int U_WMRC8_get(void){ + return U_WMRCORENONE_get("U_WMRC8"); +} + +int U_WMRC9_get(void){ + return U_WMRCORENONE_get("U_WMRC9"); +} + +int U_WMRCA_get(void){ + return U_WMRCORENONE_get("U_WMRCA"); +} + +int U_WMRCB_get(void){ + return U_WMRCORENONE_get("U_WMRCB"); +} + +int U_WMRCC_get(void){ + return U_WMRCORENONE_get("U_WMRCC"); +} + +int U_WMRCD_get(void){ + return U_WMRCORENONE_get("U_WMRCD"); +} + +int U_WMRCE_get(void){ + return U_WMRCORENONE_get("U_WMRCE"); +} + +int U_WMRCF_get(void){ + return U_WMRCORENONE_get("U_WMRCF"); +} + +int U_WMRD0_get(void){ + return U_WMRCORENONE_get("U_WMRD0"); +} + +int U_WMRD1_get(void){ + return U_WMRCORENONE_get("U_WMRD1"); +} + +int U_WMRD2_get(void){ + return U_WMRCORENONE_get("U_WMRD2"); +} + +int U_WMRD3_get(void){ + return U_WMRCORENONE_get("U_WMRD3"); +} + +int U_WMRD4_get(void){ + return U_WMRCORENONE_get("U_WMRD4"); +} + +int U_WMRD5_get(void){ + return U_WMRCORENONE_get("U_WMRD5"); +} + +int U_WMRD6_get(void){ + return U_WMRCORENONE_get("U_WMRD6"); +} + +int U_WMRD7_get(void){ + return U_WMRCORENONE_get("U_WMRD7"); +} + +int U_WMRD8_get(void){ + return U_WMRCORENONE_get("U_WMRD8"); +} + +int U_WMRD9_get(void){ + return U_WMRCORENONE_get("U_WMRD9"); +} + +int U_WMRDA_get(void){ + return U_WMRCORENONE_get("U_WMRDA"); +} + +int U_WMRDB_get(void){ + return U_WMRCORENONE_get("U_WMRDB"); +} + +int U_WMRDC_get(void){ + return U_WMRCORENONE_get("U_WMRDC"); +} + +int U_WMRDD_get(void){ + return U_WMRCORENONE_get("U_WMRDD"); +} + +int U_WMRDE_get(void){ + return U_WMRCORENONE_get("U_WMRDE"); +} + +int U_WMRDF_get(void){ + return U_WMRCORENONE_get("U_WMRDF"); +} + +int U_WMRE0_get(void){ + return U_WMRCORENONE_get("U_WMRE0"); +} + +int U_WMRE1_get(void){ + return U_WMRCORENONE_get("U_WMRE1"); +} + +int U_WMRE2_get(void){ + return U_WMRCORENONE_get("U_WMRE2"); +} + +int U_WMRE3_get(void){ + return U_WMRCORENONE_get("U_WMRE3"); +} + +int U_WMRE4_get(void){ + return U_WMRCORENONE_get("U_WMRE4"); +} + +int U_WMRE5_get(void){ + return U_WMRCORENONE_get("U_WMRE5"); +} + +int U_WMRE6_get(void){ + return U_WMRCORENONE_get("U_WMRE6"); +} + +int U_WMRE7_get(void){ + return U_WMRCORENONE_get("U_WMRE7"); +} + +int U_WMRE8_get(void){ + return U_WMRCORENONE_get("U_WMRE8"); +} + +int U_WMRE9_get(void){ + return U_WMRCORENONE_get("U_WMRE9"); +} + +int U_WMREA_get(void){ + return U_WMRCORENONE_get("U_WMREA"); +} + +int U_WMREB_get(void){ + return U_WMRCORENONE_get("U_WMREB"); +} + +int U_WMREC_get(void){ + return U_WMRCORENONE_get("U_WMREC"); +} + +int U_WMRED_get(void){ + return U_WMRCORENONE_get("U_WMRED"); +} + +int U_WMREE_get(void){ + return U_WMRCORENONE_get("U_WMREE"); +} + +int U_WMREF_get(void){ + return U_WMRCORENONE_get("U_WMREF"); +} +//! \endcond + +/** + \brief Get data from a U_WMRDELETEOBJECT record. + \return length of the U_WMRDELETEOBJECT record in bytes, or 0 on error + \param contents record to extract data from + \param Object Index of object which is made active. +*/ +int U_WMRDELETEOBJECT_get( + const char *contents, + uint16_t *Object + ){ + return U_WMRCORE_1U16_get(contents, (U_SIZE_WMRDELETEOBJECT), Object); +} + +//! \cond +int U_WMRF1_get(void){ + return U_WMRCORENONE_get("U_WMRF1"); +} + +int U_WMRF2_get(void){ + return U_WMRCORENONE_get("U_WMRF2"); +} + +int U_WMRF3_get(void){ + return U_WMRCORENONE_get("U_WMRF3"); +} + +int U_WMRF4_get(void){ + return U_WMRCORENONE_get("U_WMRF4"); +} + +int U_WMRF5_get(void){ + return U_WMRCORENONE_get("U_WMRF5"); +} + +int U_WMRF6_get(void){ + return U_WMRCORENONE_get("U_WMRF6"); +} +//! \endcond + +/** + \brief Retrieve values from a U_WMRCREATEPALETTE record + \return length of the U_WMRCREATEPALETTE record, or NULL on error + \param contents record to extract data from + \param Palette Create a Palette object. + \param PalEntries Array of Palette Entries +*/ +int U_WMRCREATEPALETTE_get( + const char *contents, + U_PALETTE *Palette, + const char **PalEntries + ){ + return U_WMRCORE_PALETTE_get(contents, (U_SIZE_WMRCREATEPALETTE), Palette, PalEntries); +} + +//! \cond +int U_WMRF8_get(void){ + return U_WMRCORENONE_get("U_WMRF8"); +} +//! \endcond + +/** + \brief Get data from a U_WMRCREATEPATTERNBRUSH record. + Warning - application support for U_WMRCREATEPATTERNBRUSH is spotty, better to use U_WMRDIBCREATEPATTERNBRUSH. + \return length of the U_WMRCREATEPATTERNBRUSH record in bytes, or 0 on error + \param contents record to extract data from + \param Bm16 truncated Bitmap16 structure from record, only tge first 14 bytes hold data. + \param pasize Number of bytes in Pattern + \param Pattern byte array pattern, described by Bm16, for brush +*/ +int U_WMRCREATEPATTERNBRUSH_get( + const char *contents, + U_BITMAP16 *Bm16, + int *pasize, + const char **Pattern + ){ + int off = U_SIZE_METARECORD; + /* size in next one is + 6 (core header) + 14 (truncated bitmap16) + 18 bytes reserved + 2 bytes (at least) for data */ + int size = U_WMRCORE_RECSAFE_get(contents, (U_SIZE_METARECORD + 14 + 18 + 2)); + if(!size)return(0); + memset(Bm16, 0, U_SIZE_BITMAP16); + /* BM16 is truncated in this record type to 14 bytes, last 4 bytes must be ignored, so they are not even copied */ + memcpy(Bm16, contents + off, 10); + *pasize = (((Bm16->Width * Bm16->BitsPixel + 15) >> 4) << 1) * Bm16->Height; + off += 32; /* skip [14 bytes of truncated bitmap16 object and 18 bytes of reserved */ + *Pattern = (contents + off); + return(size); +} + +/** + \brief Get data from a U_WMRCREATEPENINDIRECT record. + \return length of the U_WMRCREATEPENINDIRECT record in bytes, or 0 on error + \param contents record to extract data from + \param pen pointer to a U_PEN object to fill. +*/ +int U_WMRCREATEPENINDIRECT_get( + const char *contents, + U_PEN *pen + ){ + int size = U_WMRCORE_RECSAFE_get(contents, (U_SIZE_WMRCREATEPENINDIRECT)); + if(!size)return(0); + memcpy(pen, contents + offsetof(U_WMRCREATEPENINDIRECT, pen), U_SIZE_PEN); + return(size); +} + +/** + \brief Get data from a U_WMRCREATEFONTINDIRECT record. + \return length of the U_WMRCREATEFONTINDIRECT record in bytes, or 0 on error + \param contents record to extract data from + \param font pointer to array of U_FONT structure in memory. Pointer may not be aligned properly for structure. +*/ +int U_WMRCREATEFONTINDIRECT_get( + const char *contents, + const char **font + ){ + int size = U_WMRCORE_2U16_N16_get(contents, (U_SIZE_WMRCREATEFONTINDIRECT), NULL, NULL, font); + if(size){ + if(IS_MEM_UNSAFE(*font, U_SIZE_FONT_CORE, contents+size))return(0); + if(contents + size - *font > U_SIZE_FONT_CORE + 32)return(0); // font name must fit in a 32 bit field + } + return size; +} + +/** + \brief Get data from a U_WMRCREATEBRUSHINDIRECT record. + \return length of the U_WMRCREATEBRUSHINDIRECT record in bytes, or 0 on error + \param contents record to extract data from + \param brush pointer to U_WLOGBRUSH structure in memory. Pointer may not be aligned properly for structure. +*/ +int U_WMRCREATEBRUSHINDIRECT_get( + const char *contents, + const char **brush + ){ + // U_SIZE_WMRCREATEBRUSHINDIRECT is everything, no variable part, so the test below is sufficient + return U_WMRCORE_2U16_N16_get(contents, (U_SIZE_WMRCREATEBRUSHINDIRECT), NULL, NULL, brush); +} + +/** in GDI and Wine, not in WMF manual. +*/ +int U_WMRCREATEBITMAPINDIRECT_get(void){ + return U_WMRCORENONE_get("U_WMRCREATEBITMAPINDIRECT"); +} + +/** in GDI and Wine, not in WMF manual. +*/ +int U_WMRCREATEBITMAP_get(void){ + return U_WMRCORENONE_get("U_WMRCREATEBITMAP"); +} + +/** + \brief Get data from a U_WMRCREATEREGION record. + \return length of the U_WMRCREATEREGION record in bytes, or 0 on error + \param contents record to extract data from + \param Region pointer to U_REGION structure in memory. Pointer may not be aligned properly for structure. + + Caller must check at the returned Region does not extend outside of the record! +*/ +int U_WMRCREATEREGION_get( + const char *contents, + const char **Region + ){ + return U_WMRCORE_2U16_N16_get(contents, (U_SIZE_WMRCREATEREGION), NULL, NULL, Region); +} + + + + +#ifdef __cplusplus +} +#endif diff --git a/src/3rdparty/libuemf/uwmf.h b/src/3rdparty/libuemf/uwmf.h new file mode 100644 index 0000000..529232c --- /dev/null +++ b/src/3rdparty/libuemf/uwmf.h @@ -0,0 +1,2677 @@ +/** + @file uwmf.h + + @brief Structures, definitions, and function prototypes for WMF files. + + WMF file Record structure information has been derived from Mingw and Wine header files, and from + Microsoft's WMF Information pdf, release date July 5,2012, link from here: + + http://msdn2.microsoft.com/en-us/library/cc250370.aspx + + If the direct link fails the document may be found + by searching for: "[MS-WMF]: Windows Metafile Format" + + *********************************** IMPORTANT!!! ********************************************** + WMF is a 16 bit file type that has some 32 bit integers embedded in it. In + a few cases these 32 bit fields are not aligned in the structures defined in uwmf.h, but + in most cases they are. So when creating the individual WMF records the functions in + uwmf.c can usually use a regular assignment operation for the 32 bit fields. However, once the + records are part of a WMF file in memory there is no guaranty that any 32 bit type will be correctly + aligned. Similarly, many WMF structures contain embedded other structures which would "naturally" + be passed by pointer, but since their alignment may not be what malloc() would have created for that + type, the outcome of that operation is not defined by the C standard. (Per Eric Sosman, section + 6.3.2.3p7 of the standard.) + + For this reason, the _print, _swap and any read operations must pass structures with unknown alignment + as a (char *), and pull out the data using memcpy() or some equivalent + that will not segfault when it tries to read a 32 bit value that is not aligned + on a 4 byte boundary. Failure to do so will result in nonportable code. You have been warned! + + Problem areas: + The Size16_4 field of all WMF records may NOT be assumed to 4 byte aligned. + DIB's U_BITMAPINFOHEADER 32 bit fields may not be aligned. + *********************************** IMPORTANT!!! ********************************************** + +*/ + +/* +File: uwmf.h +Version: 0.0.13 +Date: 26-JAN-2016 +Author: David Mathog, Biology Division, Caltech +email: mathog@caltech.edu +Copyright: 2016 David Mathog and California Institute of Technology (Caltech) +*/ + +#ifndef _UWMF_ +#define _UWMF_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdlib.h> +#include <stdio.h> +#include <stdint.h> +#include <stdbool.h> +#include <string.h> +#include "uemf.h" /* many structures/defs in common, pull in the EMF ones as a basis */ +#include "uemf_utf.h" +#include "uwmf_endian.h" + + +/** HighWater Enumeration not in WMF manual + @{ +*/ +#define U_HIGHWATER_READ 0x00000000 //!< nondestructive read of highwater value +#define U_HIGHWATER_CLEAR 0xFFFFFFFF //!< destructive read, value is reset to 0 +/** @} */ + + + + +// *********************************************************************************** +// Value Enumerations and other predefined constants, alphabetical order by group + +/* RecordType Enumeration WMF manual 2.1.1.1 */ +/** WMF manual 2.1.1.1 + \brief WMR Record types +*/ +enum U_WMR_TYPES{ + U_WMR_EOF, //!< 0x0000 U_WMREOF record + U_WMR_SETBKCOLOR, //!< 0x0201 U_WMRSETBKCOLOR record + U_WMR_SETBKMODE, //!< 0x0102 U_WMRSETBKMODE record + U_WMR_SETMAPMODE, //!< 0x0103 U_WMRSETMAPMODE record + U_WMR_SETROP2, //!< 0x0104 U_WMRSETROP2 record + U_WMR_SETRELABS, //!< 0x0105 U_WMRSETRELABS record + U_WMR_SETPOLYFILLMODE, //!< 0x0106 U_WMRSETPOLYFILLMODE record + U_WMR_SETSTRETCHBLTMODE, //!< 0x0107 U_WMRSETSTRETCHBLTMODE record + U_WMR_SETTEXTCHAREXTRA, //!< 0x0108 U_WMRSETTEXTCHAREXTRA record + U_WMR_SETTEXTCOLOR, //!< 0x0209 U_WMRSETTEXTCOLOR record + U_WMR_SETTEXTJUSTIFICATION, //!< 0x020A U_WMRSETTEXTJUSTIFICATION record + U_WMR_SETWINDOWORG, //!< 0x020B U_WMRSETWINDOWORG record + U_WMR_SETWINDOWEXT, //!< 0x020C U_WMRSETWINDOWEXT record + U_WMR_SETVIEWPORTORG, //!< 0x020D U_WMRSETVIEWPORTORG record + U_WMR_SETVIEWPORTEXT, //!< 0x020E U_WMRSETVIEWPORTEXT record + U_WMR_OFFSETWINDOWORG, //!< 0x020F U_WMROFFSETWINDOWORG record + U_WMR_SCALEWINDOWEXT, //!< 0x0410 U_WMRSCALEWINDOWEXT record + U_WMR_OFFSETVIEWPORTORG, //!< 0x0211 U_WMROFFSETVIEWPORTORG record + U_WMR_SCALEVIEWPORTEXT, //!< 0x0412 U_WMRSCALEVIEWPORTEXT record + U_WMR_LINETO, //!< 0x0213 U_WMRLINETO record + U_WMR_MOVETO, //!< 0x0214 U_WMRMOVETO record + U_WMR_EXCLUDECLIPRECT, //!< 0x0415 U_WMREXCLUDECLIPRECT record + U_WMR_INTERSECTCLIPRECT, //!< 0x0416 U_WMRINTERSECTCLIPRECT record + U_WMR_ARC, //!< 0x0817 U_WMRARC record + U_WMR_ELLIPSE, //!< 0x0418 U_WMRELLIPSE record + U_WMR_FLOODFILL, //!< 0x0419 U_WMRFLOODFILL record + U_WMR_PIE, //!< 0x081A U_WMRPIE record + U_WMR_RECTANGLE, //!< 0x041B U_WMRRECTANGLE record + U_WMR_ROUNDRECT, //!< 0x061C U_WMRROUNDRECT record + U_WMR_PATBLT, //!< 0x061D U_WMRPATBLT record + U_WMR_SAVEDC, //!< 0x001E U_WMRSAVEDC record + U_WMR_SETPIXEL, //!< 0x041F U_WMRSETPIXEL record + U_WMR_OFFSETCLIPRGN, //!< 0x0220 U_WMROFFSETCLIPRGN record + U_WMR_TEXTOUT, //!< 0x0521 U_WMRTEXTOUT record + U_WMR_BITBLT, //!< 0x0922 U_WMRBITBLT record + U_WMR_STRETCHBLT, //!< 0x0B23 U_WMRSTRETCHBLT record + U_WMR_POLYGON, //!< 0x0324 U_WMRPOLYGON record + U_WMR_POLYLINE, //!< 0x0325 U_WMRPOLYLINE record + U_WMR_ESCAPE, //!< 0x0626 U_WMRESCAPE record + U_WMR_RESTOREDC, //!< 0x0127 U_WMRRESTOREDC record + U_WMR_FILLREGION, //!< 0x0228 U_WMRFILLREGION record + U_WMR_FRAMEREGION, //!< 0x0429 U_WMRFRAMEREGION record + U_WMR_INVERTREGION, //!< 0x012A U_WMRINVERTREGION record + U_WMR_PAINTREGION, //!< 0x012B U_WMRPAINTREGION record + U_WMR_SELECTCLIPREGION, //!< 0x012C U_WMRSELECTCLIPREGION record + U_WMR_SELECTOBJECT, //!< 0x012D U_WMRSELECTOBJECT record + U_WMR_SETTEXTALIGN, //!< 0x012E U_WMRSETTEXTALIGN record + U_WMR_DRAWTEXT, //!< 0x062F U_WMRDRAWTEXT record + U_WMR_CHORD, //!< 0x0830 U_WMRCHORD record + U_WMR_SETMAPPERFLAGS, //!< 0x0231 U_WMRSETMAPPERFLAGS record + U_WMR_EXTTEXTOUT, //!< 0x0A32 U_WMREXTTEXTOUT record + U_WMR_SETDIBTODEV, //!< 0x0D33 U_WMRSETDIBTODEV record + U_WMR_SELECTPALETTE, //!< 0x0234 U_WMRSELECTPALETTE record + U_WMR_REALIZEPALETTE, //!< 0x0035 U_WMRREALIZEPALETTE record + U_WMR_ANIMATEPALETTE, //!< 0x0436 U_WMRANIMATEPALETTE record + U_WMR_SETPALENTRIES, //!< 0x0037 U_WMRSETPALENTRIES record + U_WMR_POLYPOLYGON, //!< 0x0538 U_WMRPOLYPOLYGON record + U_WMR_RESIZEPALETTE, //!< 0x0139 U_WMRRESIZEPALETTE record + U_WMR_3A, //!< 0x003A U_WMR3A record + U_WMR_3B, //!< 0x003B U_WMR3B record + U_WMR_3C, //!< 0x003C U_WMR3C record + U_WMR_3D, //!< 0x003D U_WMR3D record + U_WMR_3E, //!< 0x003E U_WMR3E record + U_WMR_3F, //!< 0x003F U_WMR3F record + U_WMR_DIBBITBLT, //!< 0x0940 U_WMRDIBBITBLT record + U_WMR_DIBSTRETCHBLT, //!< 0x0B41 U_WMRDIBSTRETCHBLT record + U_WMR_DIBCREATEPATTERNBRUSH, //!< 0x0142 U_WMRDIBCREATEPATTERNBRUSH record + U_WMR_STRETCHDIB, //!< 0x0F43 U_WMRSTRETCHDIB record + U_WMR_44, //!< 0x0044 U_WMR44 record + U_WMR_45, //!< 0x0045 U_WMR45 record + U_WMR_46, //!< 0x0046 U_WMR46 record + U_WMR_47, //!< 0x0047 U_WMR47 record + U_WMR_EXTFLOODFILL, //!< 0x0548 U_WMREXTFLOODFILL record + U_WMR_49, //!< 0x0049 U_WMR49 record + U_WMR_4A, //!< 0x004A U_WMR4A record + U_WMR_4B, //!< 0x004B U_WMR4B record + U_WMR_4C, //!< 0x014C U_WMR4C record + U_WMR_4D, //!< 0x014D U_WMR4D record + U_WMR_4E, //!< 0x004E U_WMR4E record + U_WMR_4F, //!< 0x004F U_WMR4F record + U_WMR_50, //!< 0x0050 U_WMR50 record + U_WMR_51, //!< 0x0051 U_WMR51 record + U_WMR_52, //!< 0x0052 U_WMR52 record + U_WMR_53, //!< 0x0053 U_WMR53 record + U_WMR_54, //!< 0x0054 U_WMR54 record + U_WMR_55, //!< 0x0055 U_WMR55 record + U_WMR_56, //!< 0x0056 U_WMR56 record + U_WMR_57, //!< 0x0057 U_WMR57 record + U_WMR_58, //!< 0x0058 U_WMR58 record + U_WMR_59, //!< 0x0059 U_WMR59 record + U_WMR_5A, //!< 0x005A U_WMR5A record + U_WMR_5B, //!< 0x005B U_WMR5B record + U_WMR_5C, //!< 0x005C U_WMR5C record + U_WMR_5D, //!< 0x005D U_WMR5D record + U_WMR_5E, //!< 0x005E U_WMR5E record + U_WMR_5F, //!< 0x005F U_WMR5F record + U_WMR_60, //!< 0x0060 U_WMR60 record + U_WMR_61, //!< 0x0061 U_WMR61 record + U_WMR_62, //!< 0x0062 U_WMR62 record + U_WMR_63, //!< 0x0063 U_WMR63 record + U_WMR_64, //!< 0x0064 U_WMR64 record + U_WMR_65, //!< 0x0065 U_WMR65 record + U_WMR_66, //!< 0x0066 U_WMR66 record + U_WMR_67, //!< 0x0067 U_WMR67 record + U_WMR_68, //!< 0x0068 U_WMR68 record + U_WMR_69, //!< 0x0069 U_WMR69 record + U_WMR_6A, //!< 0x006A U_WMR6A record + U_WMR_6B, //!< 0x006B U_WMR6B record + U_WMR_6C, //!< 0x006C U_WMR6C record + U_WMR_6D, //!< 0x006D U_WMR6D record + U_WMR_6E, //!< 0x006E U_WMR6E record + U_WMR_6F, //!< 0x006F U_WMR6F record + U_WMR_70, //!< 0x0070 U_WMR70 record + U_WMR_71, //!< 0x0071 U_WMR71 record + U_WMR_72, //!< 0x0072 U_WMR72 record + U_WMR_73, //!< 0x0073 U_WMR73 record + U_WMR_74, //!< 0x0074 U_WMR74 record + U_WMR_75, //!< 0x0075 U_WMR75 record + U_WMR_76, //!< 0x0076 U_WMR76 record + U_WMR_77, //!< 0x0077 U_WMR77 record + U_WMR_78, //!< 0x0078 U_WMR78 record + U_WMR_79, //!< 0x0079 U_WMR79 record + U_WMR_7A, //!< 0x007A U_WMR7A record + U_WMR_7B, //!< 0x007B U_WMR7B record + U_WMR_7C, //!< 0x007C U_WMR7C record + U_WMR_7D, //!< 0x007D U_WMR7D record + U_WMR_7E, //!< 0x007E U_WMR7E record + U_WMR_7F, //!< 0x007F U_WMR7F record + U_WMR_80, //!< 0x0080 U_WMR80 record + U_WMR_81, //!< 0x0081 U_WMR81 record + U_WMR_82, //!< 0x0082 U_WMR82 record + U_WMR_83, //!< 0x0083 U_WMR83 record + U_WMR_84, //!< 0x0084 U_WMR84 record + U_WMR_85, //!< 0x0085 U_WMR85 record + U_WMR_86, //!< 0x0086 U_WMR86 record + U_WMR_87, //!< 0x0087 U_WMR87 record + U_WMR_88, //!< 0x0088 U_WMR88 record + U_WMR_89, //!< 0x0089 U_WMR89 record + U_WMR_8A, //!< 0x008A U_WMR8A record + U_WMR_8B, //!< 0x008B U_WMR8B record + U_WMR_8C, //!< 0x008C U_WMR8C record + U_WMR_8D, //!< 0x008D U_WMR8D record + U_WMR_8E, //!< 0x008E U_WMR8E record + U_WMR_8F, //!< 0x008F U_WMR8F record + U_WMR_90, //!< 0x0090 U_WMR90 record + U_WMR_91, //!< 0x0091 U_WMR91 record + U_WMR_92, //!< 0x0092 U_WMR92 record + U_WMR_93, //!< 0x0093 U_WMR93 record + U_WMR_94, //!< 0x0094 U_WMR94 record + U_WMR_95, //!< 0x0095 U_WMR95 record + U_WMR_96, //!< 0x0096 U_WMR96 record + U_WMR_97, //!< 0x0097 U_WMR97 record + U_WMR_98, //!< 0x0098 U_WMR98 record + U_WMR_99, //!< 0x0099 U_WMR99 record + U_WMR_9A, //!< 0x009A U_WMR9A record + U_WMR_9B, //!< 0x009B U_WMR9B record + U_WMR_9C, //!< 0x009C U_WMR9C record + U_WMR_9D, //!< 0x009D U_WMR9D record + U_WMR_9E, //!< 0x009E U_WMR9E record + U_WMR_9F, //!< 0x009F U_WMR9F record + U_WMR_A0, //!< 0x00A0 U_WMRA0 record + U_WMR_A1, //!< 0x00A1 U_WMRA1 record + U_WMR_A2, //!< 0x00A2 U_WMRA2 record + U_WMR_A3, //!< 0x00A3 U_WMRA3 record + U_WMR_A4, //!< 0x00A4 U_WMRA4 record + U_WMR_A5, //!< 0x00A5 U_WMRA5 record + U_WMR_A6, //!< 0x00A6 U_WMRA6 record + U_WMR_A7, //!< 0x00A7 U_WMRA7 record + U_WMR_A8, //!< 0x00A8 U_WMRA8 record + U_WMR_A9, //!< 0x00A9 U_WMRA9 record + U_WMR_AA, //!< 0x00AA U_WMRAA record + U_WMR_AB, //!< 0x00AB U_WMRAB record + U_WMR_AC, //!< 0x00AC U_WMRAC record + U_WMR_AD, //!< 0x00AD U_WMRAD record + U_WMR_AE, //!< 0x00AE U_WMRAE record + U_WMR_AF, //!< 0x00AF U_WMRAF record + U_WMR_B0, //!< 0x00B0 U_WMRB0 record + U_WMR_B1, //!< 0x00B1 U_WMRB1 record + U_WMR_B2, //!< 0x00B2 U_WMRB2 record + U_WMR_B3, //!< 0x00B3 U_WMRB3 record + U_WMR_B4, //!< 0x00B4 U_WMRB4 record + U_WMR_B5, //!< 0x00B5 U_WMRB5 record + U_WMR_B6, //!< 0x00B6 U_WMRB6 record + U_WMR_B7, //!< 0x00B7 U_WMRB7 record + U_WMR_B8, //!< 0x00B8 U_WMRB8 record + U_WMR_B9, //!< 0x00B9 U_WMRB9 record + U_WMR_BA, //!< 0x00BA U_WMRBA record + U_WMR_BB, //!< 0x00BB U_WMRBB record + U_WMR_BC, //!< 0x00BC U_WMRBC record + U_WMR_BD, //!< 0x00BD U_WMRBD record + U_WMR_BE, //!< 0x00BE U_WMRBE record + U_WMR_BF, //!< 0x00BF U_WMRBF record + U_WMR_C0, //!< 0x00C0 U_WMRC0 record + U_WMR_C1, //!< 0x00C1 U_WMRC1 record + U_WMR_C2, //!< 0x00C2 U_WMRC2 record + U_WMR_C3, //!< 0x00C3 U_WMRC3 record + U_WMR_C4, //!< 0x00C4 U_WMRC4 record + U_WMR_C5, //!< 0x00C5 U_WMRC5 record + U_WMR_C6, //!< 0x00C6 U_WMRC6 record + U_WMR_C7, //!< 0x00C7 U_WMRC7 record + U_WMR_C8, //!< 0x00C8 U_WMRC8 record + U_WMR_C9, //!< 0x00C9 U_WMRC9 record + U_WMR_CA, //!< 0x00CA U_WMRCA record + U_WMR_CB, //!< 0x00CB U_WMRCB record + U_WMR_CC, //!< 0x00CC U_WMRCC record + U_WMR_CD, //!< 0x00CD U_WMRCD record + U_WMR_CE, //!< 0x00CE U_WMRCE record + U_WMR_CF, //!< 0x00CF U_WMRCF record + U_WMR_D0, //!< 0x00D0 U_WMRD0 record + U_WMR_D1, //!< 0x00D1 U_WMRD1 record + U_WMR_D2, //!< 0x00D2 U_WMRD2 record + U_WMR_D3, //!< 0x00D3 U_WMRD3 record + U_WMR_D4, //!< 0x00D4 U_WMRD4 record + U_WMR_D5, //!< 0x00D5 U_WMRD5 record + U_WMR_D6, //!< 0x00D6 U_WMRD6 record + U_WMR_D7, //!< 0x00D7 U_WMRD7 record + U_WMR_D8, //!< 0x00D8 U_WMRD8 record + U_WMR_D9, //!< 0x00D9 U_WMRD9 record + U_WMR_DA, //!< 0x00DA U_WMRDA record + U_WMR_DB, //!< 0x00DB U_WMRDB record + U_WMR_DC, //!< 0x00DC U_WMRDC record + U_WMR_DD, //!< 0x00DD U_WMRDD record + U_WMR_DE, //!< 0x00DE U_WMRDE record + U_WMR_DF, //!< 0x00DF U_WMRDF record + U_WMR_E0, //!< 0x00E0 U_WMRE0 record + U_WMR_E1, //!< 0x00E1 U_WMRE1 record + U_WMR_E2, //!< 0x00E2 U_WMRE2 record + U_WMR_E3, //!< 0x00E3 U_WMRE3 record + U_WMR_E4, //!< 0x00E4 U_WMRE4 record + U_WMR_E5, //!< 0x00E5 U_WMRE5 record + U_WMR_E6, //!< 0x00E6 U_WMRE6 record + U_WMR_E7, //!< 0x00E7 U_WMRE7 record + U_WMR_E8, //!< 0x00E8 U_WMRE8 record + U_WMR_E9, //!< 0x00E9 U_WMRE9 record + U_WMR_EA, //!< 0x00EA U_WMREA record + U_WMR_EB, //!< 0x00EB U_WMREB record + U_WMR_EC, //!< 0x00EC U_WMREC record + U_WMR_ED, //!< 0x00ED U_WMRED record + U_WMR_EE, //!< 0x00EE U_WMREE record + U_WMR_EF, //!< 0x00EF U_WMREF record + U_WMR_DELETEOBJECT, //!< 0x01F0 U_WMRDELETEOBJECT record + U_WMR_F1, //!< 0x00F1 U_WMRF1 record + U_WMR_F2, //!< 0x00F2 U_WMRF2 record + U_WMR_F3, //!< 0x00F3 U_WMRF3 record + U_WMR_F4, //!< 0x00F4 U_WMRF4 record + U_WMR_F5, //!< 0x00F5 U_WMRF5 record + U_WMR_F6, //!< 0x00F6 U_WMRF6 record + U_WMR_CREATEPALETTE, //!< 0x00F7 U_WMRCREATEPALETTE record + U_WMR_F8 , //!< 0x00F8 U_WMRF8 record + U_WMR_CREATEPATTERNBRUSH, //!< 0x01F9 U_WMRCREATEPATTERNBRUSH record + U_WMR_CREATEPENINDIRECT, //!< 0x02FA U_WMRCREATEPENINDIRECT record + U_WMR_CREATEFONTINDIRECT, //!< 0x02FB U_WMRCREATEFONTINDIRECT record + U_WMR_CREATEBRUSHINDIRECT, //!< 0x02FC U_WMRCREATEBRUSHINDIRECT record + U_WMR_CREATEBITMAPINDIRECT, //!< 0x02FD U_WMRCREATEBITMAPINDIRECT record + U_WMR_CREATEBITMAP, //!< 0x06FE U_WMRCREATEBITMAP record + U_WMR_CREATEREGION, //!< 0x06FF U_WMRCREATEREGION record +}; +#define U_WMR_MIN 0 //!< Minimum U_WMR_ value. +#define U_WMR_MAX 255 //!< Maximum U_WMR_ value. +#define U_WMR_MASK 0xFF //!< Mask for enumerator (lower) byte +#define U_WMR_INVALID 0xFFFFFFFF //!< Indicates "Not a valid U_WMR_* value" + + +/** BinaryRasterOperation Enumeration WMF manual 2.1.1.2 + + Same as U_EMF_EMRSETROP2 in uemf.h +*/ + +/** BitCount Enumeration WMF manual 2.1.1.3 + \defgroup U_WMF_AltBitCount_Qualifiers WMF Alternate names for the values under EMF Bitcount Enumeration in uemf.h + @{ +*/ +#define BI_BITCOUNT_0 U_BCBM_EXPLICIT //!< Derived from JPG or PNG compressed image or ? +#define BI_BITCOUNT_1 U_BCBM_MONOCHROME //!< 2 colors. bmiColors array has two entries +#define BI_BITCOUNT_2 U_BCBM_COLOR4 //!< 2^4 colors. bmiColors array has 16 entries +#define BI_BITCOUNT_3 U_BCBM_COLOR8 //!< 2^8 colors. bmiColors array has 256 entries +#define BI_BITCOUNT_4 U_BCBM_COLOR16 //!< 2^16 colors. bmiColors is not used. Pixels are 5 bits B,G,R with 1 unused bit +#define BI_BITCOUNT_5 U_BCBM_COLOR24 //!< 2^24 colors. bmiColors is not used. Pixels are U_RGBTRIPLE. +#define BI_BITCOUNT_6 U_BCBM_COLOR32 //!< 2^32 colors. bmiColors is not used. Pixels are U_RGBQUAD. +/** @} */ + +/* BrushStyle Enumeration WMF manual 2.1.1.4 + Same as "EMF LB_Style Enumeration" in uemf.h +*/ + +/* CharacterSet Enumeration WMF manual 2.1.1.5 + Same as "EMF LF_CharSet Enumeration" in uemf.h +*/ + +/** ColorUsage Enumeration WMF manual 2.1.1.6 + For cUsage fields in various DIB related records. + \defgroup U_WMF_Extra_iUsageSrc_Qualifiers WMF Extra DIBColors Enumeration + WMF is the same as "EMF DIBColors Enumeration" in uemf.h, except it also supports + this one extra value. + @{ +*/ +#define U_DIB_PAL_INDICES 2 //!< No color table, pixels are logical palette indices. +/** @} */ + +/** Compression Enumeration WMF manual 2.1.1.7 + Same as "EMF BI_Compression Enumeration" in uemf.h with these additions + \defgroup U_WMF_EXTRA_BITMAPINFOHEADER_biCompression_Qualifiers WMF Extra BI_Compression Enumerations, none are implemented + @{ +*/ +#define U_BI_CMYK 0x000B //!< CMYK uncompressed +#define U_BI_CMYKRLE8 0x000C //!< CMYK RLE8 compression +#define U_BI_CMYKRLE4 = 0x000D //!< CMYK RLE4 compression +/** @} */ + +/* FamilyFont Enumeration WMF manual 2.1.1.8 + Only used in a PitchAndFamily object, defined there +*/ + +/* FloodFill Enumeration WMF manual 2.1.1.9 + Same as "EMF FloodFill Enumeration" in uemf.h +*/ + +/* FontQuality Enumeration WMF manual 2.1.1.10 + Same as "EMF LF_Quality Enumeration" in uemf.h +*/ + +/* GamutMappingIntent Enumeration WMF manual 2.1.1.11 + Same as "EMF LCS_Intent Enumeration" in uemf.h +*/ + +/* HatchStyle Enumeration WMF manual 2.1.1.12 + Same as "EMF HatchStyle Enumeration" in uemf.h +*/ + +/* Layout Enumeration WMF manual 2.1.1.13 + Same as "EMF Mirroring Enumeration" in uemf.h +*/ + +/** LogicalColorSpace Enumeration WMF manual 2.1.1.14 + Not used presently, applies in BitmapV4Header + @{ +*/ +/* U_LCS_CALIBRATED_RGB is defined in uemf.h under LCS_CSType Enumeration, WMF manual also defines it, but do not replicate define. +#define U_LCS_CALIBRATED_RGB 0x00000000 //!< calibrated RGB +*/ +#define U_LCS_sRGB 0x73524742 //!< ASCII for "sRGB" +#define U_LCS_WINDOWS_COLOR_SPACE 0x57696E20 //!< ASCII for "Win " +/** @} */ + +/* LogicalColorSpaceV5 Enumeration WMF manual 2.1.1.15 + Same as "EMF Profile Enumeration" in uemf.h +*/ + +/* MapMode Enumeration WMF manual 2.1.1.16 + Same as "EMF MapMode Enumeration" in uemf.h +*/ + +/** MetaFilesEscape Enumeration WMF manual 2.1.1.17 + \defgroup U_WMF_MFEscape_Qualifiers WMF Metafile Escape record types + For U_WMRESCAPE eFunc field + @{ +*/ +#define U_MFE_NEWFRAME 0x0001 //!< NEWFRAME escape type +#define U_MFE_ABORTDOC 0x0002 //!< ABORTDOC escape type +#define U_MFE_NEXTBAND 0x0003 //!< NEXTBAND escape type +#define U_MFE_SETCOLORTABLE 0x0004 //!< SETCOLORTABLE escape type +#define U_MFE_GETCOLORTABLE 0x0005 //!< GETCOLORTABLE escape type +#define U_MFE_FLUSHOUT 0x0006 //!< FLUSHOUT escape type +#define U_MFE_DRAFTMODE 0x0007 //!< DRAFTMODE escape type +#define U_MFE_QUERYESCSUPPORT 0x0008 //!< QUERYESCSUPPORT escape type +#define U_MFE_SETABORTPROC 0x0009 //!< SETABORTPROC escape type +#define U_MFE_STARTDOC 0x000A //!< STARTDOC escape type +#define U_MFE_ENDDOC 0x000B //!< ENDDOC escape type +#define U_MFE_GETPHYSPAGESIZE 0x000C //!< GETPHYSPAGESIZE escape type +#define U_MFE_GETPRINTINGOFFSET 0x000D //!< GETPRINTINGOFFSET escape type +#define U_MFE_GETSCALINGFACTOR 0x000E //!< GETSCALINGFACTOR escape type +#define U_MFE_META_ESCAPE_ENHANCED_METAFILE 0x000F //!< META_ESCAPE_ENHANCED_METAFILE escape type +#define U_MFE_SETPENWIDTH 0x0010 //!< SETPENWIDTH escape type +#define U_MFE_SETCOPYCOUNT 0x0011 //!< SETCOPYCOUNT escape type +#define U_MFE_SETPAPERSOURCE 0x0012 //!< SETPAPERSOURCE escape type +#define U_MFE_PASSTHROUGH 0x0013 //!< PASSTHROUGH escape type +#define U_MFE_GETTECHNOLOGY 0x0014 //!< GETTECHNOLOGY escape type +#define U_MFE_SETLINECAP 0x0015 //!< SETLINECAP escape type +#define U_MFE_SETLINEJOIN 0x0016 //!< SETLINEJOIN escape type +#define U_MFE_SETMITERLIMIT 0x0017 //!< SETMITERLIMIT escape type +#define U_MFE_BANDINFO 0x0018 //!< BANDINFO escape type +#define U_MFE_DRAWPATTERNRECT 0x0019 //!< DRAWPATTERNRECT escape type +#define U_MFE_GETVECTORPENSIZE 0x001A //!< GETVECTORPENSIZE escape type +#define U_MFE_GETVECTORBRUSHSIZE 0x001B //!< GETVECTORBRUSHSIZE escape type +#define U_MFE_ENABLEDUPLEX 0x001C //!< ENABLEDUPLEX escape type +#define U_MFE_GETSETPAPERBINS 0x001D //!< GETSETPAPERBINS escape type +#define U_MFE_GETSETPRINTORIENT 0x001E //!< GETSETPRINTORIENT escape type +#define U_MFE_ENUMPAPERBINS 0x001F //!< ENUMPAPERBINS escape type +#define U_MFE_SETDIBSCALING 0x0020 //!< SETDIBSCALING escape type +#define U_MFE_EPSPRINTING 0x0021 //!< EPSPRINTING escape type +#define U_MFE_ENUMPAPERMETRICS 0x0022 //!< ENUMPAPERMETRICS escape type +#define U_MFE_GETSETPAPERMETRICS 0x0023 //!< GETSETPAPERMETRICS escape type +#define U_MFE_POSTSCRIPT_DATA 0x0025 //!< POSTSCRIPT_DATA escape type +#define U_MFE_POSTSCRIPT_IGNORE 0x0026 //!< POSTSCRIPT_IGNORE escape type +#define U_MFE_GETDEVICEUNITS 0x002A //!< GETDEVICEUNITS escape type +#define U_MFE_GETEXTENDEDTEXTMETRICS 0x0100 //!< GETEXTENDEDTEXTMETRICS escape type +#define U_MFE_GETPAIRKERNTABLE 0x0102 //!< GETPAIRKERNTABLE escape type +#define U_MFE_EXTTEXTOUT 0x0200 //!< EXTTEXTOUT escape type +#define U_MFE_GETFACENAME 0x0201 //!< GETFACENAME escape type +#define U_MFE_DOWNLOADFACE 0x0202 //!< DOWNLOADFACE escape type +#define U_MFE_METAFILE_DRIVER 0x0801 //!< METAFILE_DRIVER escape type +#define U_MFE_QUERYDIBSUPPORT 0x0C01 //!< QUERYDIBSUPPORT escape type +#define U_MFE_BEGIN_PATH 0x1000 //!< BEGIN_PATH escape type +#define U_MFE_CLIP_TO_PATH 0x1001 //!< CLIP_TO_PATH escape type +#define U_MFE_END_PATH 0x1002 //!< END_PATH escape type +#define U_MFE_OPEN_CHANNEL 0x100E //!< OPEN_CHANNEL escape type +#define U_MFE_DOWNLOADHEADER 0x100F //!< DOWNLOADHEADER escape type +#define U_MFE_CLOSE_CHANNEL 0x1010 //!< CLOSE_CHANNEL escape type +#define U_MFE_POSTSCRIPT_PASSTHROUGH 0x1013 //!< POSTSCRIPT_PASSTHROUGH escape type +#define U_MFE_ENCAPSULATED_POSTSCRIPT 0x1014 //!< ENCAPSULATED_POSTSCRIPT escape type +#define U_MFE_POSTSCRIPT_IDENTIFY 0x1015 //!< POSTSCRIPT_IDENTIFY escape type +#define U_MFE_POSTSCRIPT_INJECTION 0x1016 //!< POSTSCRIPT_INJECTION escape type +#define U_MFE_CHECKJPEGFORMAT 0x1017 //!< CHECKJPEGFORMAT escape type +#define U_MFE_CHECKPNGFORMAT 0x1018 //!< CHECKPNGFORMAT escape type +#define U_MFE_GET_PS_FEATURESETTING 0x1019 //!< GET_PS_FEATURESETTING escape type +#define U_MFE_MXDC_ESCAPE 0x101A //!< MXDC_ESCAPE escape type +#define U_MFE_SPCLPASSTHROUGH2 0x11D8 //!< SPCLPASSTHROUGH2 escape type +/** @} */ + +/** MetafileType Enumeration WMF manual 2.1.1.18 + @{ +*/ +#define U_MEMORYMETAFILE 0x0001 //!< memory metafile (never used by libUWMF) +#define U_DISKMETAFILE 0x0002 //!< disk metafile (always used by libUWMF) +/** @} */ + +/** MetafileVersion Enumeration WMF manual 2.1.1.19 + @{ +*/ + +#define U_METAVERSION100 0x0100 //!< DIBs not allowed +#define U_METAVERSION300 0x0300 //!< DIBs allowed +/** @} */ + +/* MixMode Enumeration WMF manual 2.1.1.20 + Same as "EMF BackgroundMode Enumeration" in uemf.h +*/ + +/* OutPrecision Enumeration WMF manual 2.1.1.21 + Same as "EMF LF_OutPrecision Enumeration" in uemf.h +*/ + +/** PaletteEntryFlag Enumeration WMF manual 2.1.1.22 + @{ +*/ +#define U_PC_RESERVED 0x01 //!< used for animation +#define U_PC_EXPLICIT 0x02 //!< low order word is palette index +#define U_PC_NOCOLLAPSE 0x04 //!< store as new color in palette, do not match to existing color +/** @} */ + +/** PenStyle Enumeration WMF manual 2.1.1.23 + Same as "EMF PenStyle Enumeration" in uemf.h, + EXCEPT no values >0xFFFF are used, in particular there is no U_PS_GEOMETRIC (ie, all are U_PS_COSMETIC). + Apparently because there is no U_PS_GEOMETRIC, U_PS_JOIN* and U_PS_ENDCAP* are also ignored by XP SP3 Preview + (which defaults to a rounded cap) and PowerPoint 2003 (which defaults to square cap). The behavior + was the same when escape records for JOIN and ENDCAP are used. Bottom line, WMF line formatting seems + to be very hit and miss from application to application. +*/ + +/* PitchFont Enumeration WMF manual 2.1.1.24 + These are only used in PitchAndFamily object, defined there. +*/ + +/* PolyFillMode Enumeration WMF manual 2.1.1.25 + These are the first two emtries in "EMF PolygonFillMode Enumeration" in uemf.h + +*/ + +/** PostScriptCap Enumeration WMF manual 2.1.1.26 + These are used in Escape Cap + @{ +*/ +#define U_WPS_CAP_NOTSET -2 +#define U_WPS_CAP_FLAT 0 +#define U_WPS_CAP_ROUND 1 +#define U_WPS_CAP_SQUARE 2 +/** @} */ + +/* PostScriptClipping Enumeration WMF manual 2.1.1.27 + PostFeatureSetting Enumeration WMF manual 2.1.1.28 + + These are used by postscript drivers, not supported by libUWEMF. +*/ + +/** PostScrioptJoin Enumeration WMF manual 2.1.1.29 + These are used in Escape Cap + @{ +*/ +#define U_WPS_JOIN_NOTSET -2 +#define U_WPS_JOIN_MITER 0 +#define U_WPS_JOIN_ROUND 1 +#define U_WPS_JOIN_BEVEL 2 +/** @} */ + +/* StretchMode Enumeration WMF manual 2.1.1.30 + Same as "EMF StretchMode Enumeration" in uemf.h + +*/ + +/* TernaryRasterOperation Enumeration WMF manual 2.1.1.31 + Same as "EMF Ternary Raster Operation Enumeration" in uemf.h + Only partially supported in libUWMF.h +*/ + +/* ClipPrecision Flags WMF manual 2.1.2.1 + Same as "EMF LF_ClipPrecision Enumeration" in uemf.h +*/ + +/* ExtTextOutOptions Flags WMF manual 2.1.2.2 + These are a subset of "EMF ExtTextOutOptions Enumeration" in uemf.h + + Not defined for WMF: U_ETO_NONE, U_ETO_GRAYED, U_ETO_NORECT, + U_ETO_SMALL_CHARS,U_ETO_IGNORELANGUAGE,U_ETO_REVERSE_INDEX_MAP + + Defined for WMF: U_ETO_OPAQUE, U_ETO_CLIPPED, U_ETO_GLYPH_INDEX, + U_ETO_RTLREADING,_ETO_NUMERICSLOCAL,U_ETO_NUMERICSLATIN, + U_ETO_PDY +*/ + +/* TextAlignment Enumeration WMF manual 2.1.2.3 + VertialTextAlignment Enumeration WMF manual 2.1.2.4 + These are both in "EMF TextAlignment Enumeration" in uemf.h +*/ + + + +// *************************************************************************** +// Miscellaneous Values +/* TextAlignmentMode Flags WMF manual 2.1.2.3 + VerticalTextAlignmentMode Flags WMF manual 2.1.2.4 + Same as "EMF TextAlignment Enumeration" in uemf.h +*/ + +/** \defgroup U_WMF_MinimumRecord_sizes WMF Size in bytes of core record types. + + The size of the object/record is USUALLY not the same + as the sizeof() of the corresponding struct, so in general it is unsafe to use sizeof() with this code. + + Always use the U_SIZE_x instead!!!! + + Note that some records may actually be much, much longer than their minimum size as they include strings, + bitmaps, and such. + + Documentation for each value is: + + = same as struct size + or + X = different from struct size + followed by + Number (sizeof(struct) == size of the struct in bytes.) + + @{ +*/ +#define U_SIZE_PAIRF 8 /**< + 8 this might be different on 64 bit platform */ +#define U_SIZE_COLORREF 4 /**< + 4 */ +#define U_SIZE_BRUSH 8 /**< + 8 */ +#define U_SIZE_FONT 19 /**< X 20 */ +#define U_SIZE_FONT_CORE 18 /**< X 20 Like U_FONT, but minus the FaceName part */ +#define U_SIZE_PLTNTRY 4 /**< + 4 */ +#define U_SIZE_PALETTE 8 /**< + 8 */ +#define U_SIZE_PEN 10 /**< + 10 */ +#define U_SIZE_POINT16 4 /**< + 4 */ +#define U_SIZE_RECT16 8 /**< + 8 */ +#define U_SIZE_REGION 20 /**< X 22 20 is minums the variable part */ +#define U_SIZE_BITMAP16 10 /**< + 10 */ +#define U_SIZE_BITMAPCOREHEADER 12 /**< + 12 */ +// also defined in uemf.h, avoid redefining. Same value in both places, of course. +// # define U_SIZE_BITMAPINFOHEADER 40 /**< + 40 */ +#define U_SIZE_BITMAPV4HEADER 108 /**< ? 108 not tested */ +#define U_SIZE_BITMAPV5HEADER 124 /**< ? 124 not tested */ +#define U_SIZE_WLOGBRUSH 8 /**< + 8 */ +#define U_SIZE_POLYPOLYGON 4 /**< + 4 */ +#define U_SIZE_SCAN 8 /**< + 8 */ +#define U_SIZE_METARECORD 6 /**< X 8 */ +#define U_SIZE_WMRPLACEABLE 22 /**< X 24 */ +#define U_SIZE_WMRHEADER 18 /**< X 20 */ +#define U_SIZE_WMREOF 6 /**< X 8 */ +#define U_SIZE_WMRSETRELABS 6 /**< X 8 */ +#define U_SIZE_WMRSAVEDC 6 /**< X 8 */ +#define U_SIZE_WMRRESTOREDC 8 /**< * 8 */ +#define U_SIZE_WMRREALIZEPALETTE 6 /**< X 8 */ +#define U_SIZE_WMRSETBKCOLOR 10 /**< X 12 */ +#define U_SIZE_WMRSETTEXTCOLOR 10 /**< X 12 */ +#define U_SIZE_WMRSETBKMODE 8 /**< X 12 last 2 bytes are optional */ +#define U_SIZE_WMRSETROP2 8 /**< X 12 last 2 bytes are optional */ +#define U_SIZE_WMRSETPOLYFILLMODE 8 /**< X 12 last 2 bytes are optional */ +#define U_SIZE_WMRSETSTRETCHBLTMODE 8 /**< X 12 last 2 bytes are optional */ +#define U_SIZE_WMRSETTEXTALIGN 8 /**< X 12 last 2 bytes are optional */ +#define U_SIZE_WMRSETMAPMODE 8 /**< + 8 */ +#define U_SIZE_WMRSETTEXTCHAREXTRA 8 /**< + 8 */ +#define U_SIZE_WMRSETTEXTJUSTIFICATION 10 /**< X 12 */ +#define U_SIZE_WMRSETWINDOWORG 10 /**< X 12 */ +#define U_SIZE_WMRSETWINDOWEXT 10 /**< X 12 */ +#define U_SIZE_WMRSETVIEWPORTORG 10 /**< X 12 */ +#define U_SIZE_WMRSETVIEWPORTEXT 10 /**< X 12 */ +#define U_SIZE_WMROFFSETWINDOWORG 10 /**< X 12 */ +#define U_SIZE_WMROFFSETVIEWPORTORG 10 /**< X 12 */ +#define U_SIZE_WMRLINETO 10 /**< X 12 */ +#define U_SIZE_WMRMOVETO 10 /**< X 12 */ +#define U_SIZE_WMROFFSETCLIPRGN 10 /**< X 12 */ +#define U_SIZE_WMRSCALEWINDOWEXT 14 /**< X 16 */ +#define U_SIZE_WMRSCALEVIEWPORTEXT 14 /**< X 16 */ +#define U_SIZE_WMREXCLUDECLIPRECT 14 /**< X 16 */ +#define U_SIZE_WMRINTERSECTCLIPRECT 14 /**< X 16 */ +#define U_SIZE_WMRARC 22 /**< X 24 */ +#define U_SIZE_WMRELLIPSE 14 /**< X 16 */ +#define U_SIZE_WMRRECTANGLE 14 /**< X 16 */ +#define U_SIZE_WMRFLOODFILL 16 /**< + 16 */ +#define U_SIZE_WMREXTFLOODFILL 16 /**< + 16 */ +#define U_SIZE_WMRSETPIXEL 14 /**< X 16 */ +#define U_SIZE_WMRPIE 22 /**< X 24 */ +#define U_SIZE_WMRCHORD 22 /**< X 24 */ +#define U_SIZE_WMRROUNDRECT 18 /**< X 20 */ +#define U_SIZE_WMRPATBLT 18 /**< X 20 */ +#define U_SIZE_WMRTEXTOUT 8 /**< X 12 (not including String,y,x) */ +#define U_SIZE_WMRBITBLT_NOPX 24 /**< + 24 */ +#define U_SIZE_WMRBITBLT_PX 22 /**< X 32 */ +#define U_SIZE_WMRSTRETCHBLT_NOPX 28 /**< + 28 */ +#define U_SIZE_WMRSTRETCHBLT_PX 26 /**< X 36 */ +#define U_SIZE_WMRPOLYGON 10 /**< X 12 */ +#define U_SIZE_WMRPOLYLINE 10 /**< X 12 */ +#define U_SIZE_WMRESCAPE 10 /**< X 12 Data field could be completely absent */ +#define U_SIZE_WMRFILLREGION 10 /**< X 12 */ +#define U_SIZE_WMRFRAMEREGION 14 /**< X 16 */ +#define U_SIZE_WMRINVERTREGION 8 /**< + 8 */ +#define U_SIZE_WMRPAINTREGION 8 /**< + 8 */ +#define U_SIZE_WMRSELECTCLIPREGION 8 /**< + 8 */ +#define U_SIZE_WMRSELECTOBJECT 8 /**< + 8 */ +#define U_SIZE_WMRSELECTPALETTE 8 /**< + 8 */ +#define U_SIZE_WMRRESIZEPALETTE 8 /**< + 8 */ +#define U_SIZE_WMRDELETEOBJECT 8 /**< + 8 */ +#define U_SIZE_WMRDRAWTEXT 6 /**< X 8 */ +#define U_SIZE_WMRCREATEBITMAPINDIRECT 6 /**< X 8 */ +#define U_SIZE_WMRCREATEBITMAP 6 /**< X 8 */ +#define U_SIZE_WMRSETMAPPERFLAGS 10 /**< X 12 */ +#define U_SIZE_WMREXTTEXTOUT 14 /**< X 16 */ +#define U_SIZE_WMRSETDIBTODEV 22 /**< X 28 */ +#define U_SIZE_WMRANIMATEPALETTE 14 /**< X 16 */ +#define U_SIZE_WMRSETPALENTRIES 14 /**< X 16 */ +#define U_SIZE_WMRCREATEPALETTE 14 /**< X 16 */ +#define U_SIZE_WMRPOLYPOLYGON 10 /**< X 12 */ +#define U_SIZE_WMRDIBBITBLT_NOPX 24 /**< + 24 */ +#define U_SIZE_WMRDIBBITBLT_PX 22 /**< X 24 */ +#define U_SIZE_WMRDIBSTRETCHBLT_NOPX 28 /**< + 28 */ +#define U_SIZE_WMRDIBSTRETCHBLT_PX 26 /**< X 28 */ +#define U_SIZE_WMRDIBCREATEPATTERNBRUSH 10 /**< X 12 */ +#define U_SIZE_WMRSTRETCHDIB 28 /**< X 32 */ +#define U_SIZE_WMRCREATEPATTERNBRUSH 6 /**< X 8 */ +#define U_SIZE_WMRCREATEPENINDIRECT 16 /**< + 16 */ +#define U_SIZE_WMRCREATEFONTINDIRECT 26 /**< X 28 */ +#define U_SIZE_WMRCREATEBRUSHINDIRECT 14 /**< X 16 */ +#define U_SIZE_WMRCREATEREGION 26 /**< X 28 */ +#define U_SIZE_WMRCREATEREGION_CORE 24 /**< X 28 Like U_SIZE_WMRCREATEREGION minus the variable part */ +/** @} */ + + +// *************************************************************************** +// Macros + +/** \defgroup U_WMF_Common_macros WMF Common Macros +Because Size16_4 may not be aligned no tests should dereference it directly from a pointer. +in NOPX tests cast causes uint8_t to promote to uint32_t, without it c++ compiler complains about +comparison of int with unsigned int + @{ +*/ +#define U_TEST_NOPX2(A,B) (A == (uint32_t) (B + 3)) //!< A is Size16_4 (extracted and aligned), B = xb true if no bitmap associated with the structure, used with some BLT records. +#define U_TEST_NOPXB(A,B) (A/2 == (uint32_t) (B + 3)) //!< A is Size16_4 (extracted and aligned)*2, B = xb, true if no bitmap associated with the structure, used with some BLT records. +#define U_WMRTYPE(A) (((U_METARECORD *)A)->iType) //!< Get iType from U_WMR* record. +#define U_WMRXB(A) (((U_METARECORD *)A)->xb) //!< Get xb from U_WMR* record. +#define U_WMR_XB_FROM_TYPE(A) ((uint8_t) (U_wmr_values(A)>>8)) //!< Get xb from type value. +#define U_U16(A) (*(uint16_t *)&A) //!< interpret a 16 bit type as uint16_t. +#define U_P16(A) ( (uint16_t *)&A) //!< pass any 16 bit type as a pointer to a uint16_t. +#define U_PP16(A) ( (uint16_t *) A) //!< pass any pointer to a 16 bit type as a pointer to a uint16_t. + +/** @} */ + +/* ************************************************************ + WMF structures OTHER than those corresponding to complete U_WMR_* records + ************************************************************ */ + +/** Brush Object WMF manual 2.2.1.1 + + Documentation is muddy, bColor and bHatch fields have different meanings depending on + the value of bStyle. Unclear if bHatch bytes are present in some cases from the + documentation. + + style Color Data + U_BS_SOLID ColorRef Object Not used (bytes present???) + U_BS_NULL ignored ignored (bytes present???). + U_BS_PATTERN ignored Bitmap16 object holding patern + U_BS_DIBPATTERNPT ColorUsage Enum DIB object + U_BS_HATCHED ColorRef Object HatchStyle Enumeration +*/ +typedef struct { + uint16_t Style; //!< BrushStyle Enumeration + U_COLORREF Color; //!< Brush Color value, 32 bit value is not aligned. + uint8_t Data[1]; //!< Brush pattern information, variable size and format +} U_BRUSH; + + +/** Font Object WMF manual 2.2.1.2 + Warning, only pass by pointer, passing by value will will truncate in Facename! +*/ +typedef struct { + int16_t Height; //!< Height in Logical units + int16_t Width; //!< Average Width in Logical units + int16_t Escapement; //!< Angle in 0.1 degrees betweem escapement vector and X axis + int16_t Orientation; //!< Angle in 0.1 degrees between baseline and X axis + int16_t Weight; //!< LF_Weight Enumeration + uint8_t Italic; //!< LF_Italic Enumeration + uint8_t Underline; //!< LF_Underline Enumeration + uint8_t StrikeOut; //!< LF_StrikeOut Enumeration + uint8_t CharSet; //!< LF_CharSet Enumeration + uint8_t OutPrecision; //!< LF_OutPrecision Enumeration + uint8_t ClipPrecision; //!< LF_ClipPrecision Enumeration + uint8_t Quality; //!< LF_Quality Enumeration + uint8_t PitchAndFamily; //!< LF_PitchAndFamily Enumeration + uint8_t FaceName[1]; //!< Name of font. ANSI Latin1, null terminated. +} U_FONT; + +/** PaletteEntry Object WMF manual 2.2.2.13 + Note, NOT compatiable with U_LOGPLTNTRY + Out of PDF order because needed for next struture. +*/ +typedef struct { + uint8_t Value; //!< 0 or PaletteEntryFlag Enumeration + uint8_t Blue; //!< Palette entry Blue Intensity + uint8_t Green; //!< Palette entry Green Intensity + uint8_t Red; //!< Palette entry Red Intensity +} U_PLTNTRY; + +/** Palette Object WMF manual 2.2.1.3 + NOT Same as "EMF LogPalette Object" in uemf.h because Palette Entries have reversed colors. + Values for palVersion are expanded + + Start must be 0x0300 (as for EMF) with U_WMRCREATEPALETTE but is an offset + for U_WMRSETPALENTRIES and U_ANIMATEPALETTE +*/ +typedef struct { + uint16_t Start; //!< Either 0x0300 or an offset into the Palette table + uint16_t NumEntries; //!< Number of U_LOGPLTNTRY objects + U_PLTNTRY PalEntries[1]; //!< Array of PaletteEntry Objects +} U_PALETTE; + +/** Pen Object WMF manual 2.2.1.4 +*/ +typedef struct { + uint16_t Style; //!< PenStyle Enumeration + uint16_t Widthw[2]; //!< reassemble/store the Pen Width in object dimensions using Widthw, the 32 bit value is not aligned + U_COLORREF Color; //!< Pen Color, the 32 bit value is not aligned. +} U_PEN; + +/** Rect Object WMF manual 2.2.2.18 + \brief Coordinates of the upper left, lower right corner. + Note that the coordinate system is 0,0 in the upper left corner + of the screen an N,M in the lower right corner. + Microsoft name: RECT Object COLLIDES with EMF Rect Object. + + This one is out of order because it is needed early. +*/ +typedef struct { + int16_t left; //!< left coordinate + int16_t top; //!< top coordinate + int16_t right; //!< right coordinate + int16_t bottom; //!< bottom coordinate +} U_RECT16; + +#define U_RCL16_DEF (U_RECT16){0,0,-1,-1} //!< Use this when no bounds are needed. + +/** Region Object WMF manual 2.2.1.5 +*/ +typedef struct { + uint16_t ignore1; //!< unused value + uint16_t Type; //!< must be 0x0006. + uint16_t ignore2; //!< unused value + int16_t Size; //!< aScans in bytes + regions size in bytes (size of this header plus all U_SCAN objects?) + int16_t sCount; //!< number of scanlines in region + int16_t sMax; //!< largest number of points in any scan + U_RECT16 sRect; //!< bounding rectangle + uint16_t aScans[1]; //!< series of appended U_SCAN objects +} U_REGION; + +/** Bitmap16 Object WMF manual 2.2.2.1 + + The U_BITMAP16 core is always followed by + uint8_t Bits[1]; //!< bitmap pixel data. Bytes contained = (((Width * BitsPixel + 15) >> 4) << 1) * Height + Note that in U_WMRCREATEPATTERNBRUSH Bits is always [4]. + +*/ +typedef struct { + int16_t Type; //!< "bitmap type" MS PDF does not define this field beyond this. + int16_t Width; //!< bitmap width in pixels. + int16_t Height; //!< bitmap height in scan lines. + int16_t WidthBytes; //!< bytes per scan line. + uint8_t Planes; //!< must be 1. + uint8_t BitsPixel; //!< number of adjacent color bits on each plane (R bits + G bits + B bits ????) +} U_BITMAP16; + +/** BitmapCoreHeader Object WMF manual 2.2.2.2 +*/ +typedef struct { + uint16_t Size_4[2]; //!< size of U_BITMAPCOREHEADER in bytes. + uint16_t Width; //!< DIB width in pixels. + uint16_t Height; //!< DIB height in pixels. + uint16_t Planes; //!< must be 1 + uint16_t BitCount; //!< Pixel Format (BitCount Enumeration) +} U_BITMAPCOREHEADER; + + +/** BitmapInfoHeader Object WMF manual 2.2.2.3 + Same as "EMF BITMAPINFOHEADER Object" in uemf.h + use U_BITMAPINFOHEADER +*/ + +//! \cond +/** BitmapV4Header Object WMF manual 2.2.2.4 +*/ +typedef struct { + uint32_t bV4Size; + int32_t bV4Width; + int32_t bV4Height; + uint16_t bV4Planes; + uint16_t bV4BitCount; + uint32_t bV4Compression; + uint32_t bV4SizeImage; + int32_t bV4XPelsPerMeter; + int32_t bV4YPelsPerMeter; + uint32_t bV4ClrUsed; + uint32_t bV4ClrImportant; + uint32_t bV4RedMask; + uint32_t bV4GreenMask; + uint32_t bV4BlueMask; + uint32_t bV4AlphaMask; + uint32_t bV4CSType; + U_CIEXYZTRIPLE bV4EndPoints; + uint32_t bV4GammaRed; + uint32_t bV4GammaGreen; + uint32_t bV4GammaBlue; +} U_BITMAPV4HEADER; //!< For ? + + +/** BitmapV5Header Object WMF manual 2.2.2.5 +*/ +typedef struct { + uint32_t bV5Size; + int32_t bV5Width; + int32_t bV5Height; + uint16_t bV5Planes; + uint16_t bV5BitCount; + uint32_t bV5Compression; + uint32_t bV5SizeImage; + int32_t bV5XPelsPerMeter; + int32_t bV5YPelsPerMeter; + uint32_t bV5ClrUsed; + uint32_t bV5ClrImportant; + uint32_t bV5RedMask; + uint32_t bV5GreenMask; + uint32_t bV5BlueMask; + uint32_t bV5AlphaMask; + uint32_t bV5CSType; + U_CIEXYZTRIPLE bV5Endpoints; + uint32_t bV5GammaRed; + uint32_t bV5GammaGreen; + uint32_t bV5GammaBlue; + uint32_t bV5Intent; + uint32_t bV5ProfileData; + uint32_t bV5ProfileSize; + uint32_t bV5Reserved; +} U_BITMAPV5HEADER; //!< For ? +//! \endcond + + + +/** CIEXYZ Object WMF manual 2.2.2.6 + Same as "EMF CIEXYZ Object" in uemf.h +*/ + +/** CIEXYZTriple Object WMF manual 2.2.2.7 + Same as "EMF CIEXYZTRIPLE Object" in uemf.h +*/ + +/** ColorRef Object WMF manual 2.2.2.8 + Same as "EMF COLORREF Object" in uemf.h +*/ + +/** DeviceIndependentBitmap Object WMF manual 2.2.2.9 +This "object" has an organization, but not one that can be easily expressed with a C struct. It consists of +three parts, all of which have variable size: + + DIBHeaderInfo BitmapCoreHeader or BitmapInfoHeader Object + Colors Array of RGBQuad Objects or uint16_t that make a color table, as determined from the DIBHeaderInfo field. + BitMapBuffer Array of bytes containing the image. + +*/ + +/** WLogBrush Object WMF manual 2.2.2.10 + Not compatible with EMF LogBrush object! + + style Color Hatch + U_BS_SOLID ColorRef Object Not used (bytes present???) + U_BS_NULL ignored ignored (bytes present???). + U_BS_PATTERN ignored not used (Action is not strictly defined) + U_BS_DIBPATTERN ignored not used (Action is not strictly defined) + U_BS_DIBPATTERNPT ignored not used (Action is not strictly defined) + U_BS_HATCHED ColorRef Object HatchStyle Enumeration +*/ +typedef struct { + uint16_t Style; //!< BrushStyle Enumeration + U_COLORREF Color; //!< Brush Color value, 32 bit value is not aligned. + uint16_t Hatch; //!< HatchStyle Enumeration +} U_WLOGBRUSH; + +/* LogColorSpace Object WMF manual 2.2.2.11 + Same as "EMF LOGCOLORSPACEA Object" in uemf.h + use U_LOGCOLORSPACEA +*/ + +/* LogColorSpaceW Object WMF manual 2.2.2.12 + Same as "EMF LOGCOLORSPACEW Object" in uemf.h + use U_LOGCOLORSPACEW +*/ + + +/* PaletteEntry Object WMF manual 2.2.2.13 + moved up before Palette Object */ + +/* PitchAndFamily Enumerations WMF manual 2.2.2.14 + Same as "EMF LF_PitchAndFamily Enumeration" in uemf.h +*/ + +/* PointL Object WMF manual 2.2.2.15 + Same as "EMF Point Object" in uemf.h +*/ + +/* PointS Object WMF manual 2.2.2.16 + Same as "EMF POINTS Object" in uemf.h +*/ + +/* PolyPolygon Object WMF manual 2.2.2.17 */ +/** WMF manual 2.2.2.17 + + There is an array "aPoints" of uint16_t after aPolyCounts that holds the coordinates. + + Presumably it is in order [x1,y1],[x2,y2],etc. The documentation does not say, it might have + y then x. + + aPoints starts at aPolyCounts[nPolys] +*/ +typedef struct { + uint16_t nPolys; //!< Number of polygons + uint16_t aPolyCounts[1]; //!< Number of points in each polygon (sequential) +} U_POLYPOLYGON; + +/* Rect Object WMF manual 2.2.2.18 + This one is out of order, had to be created much earlier than this +*/ + +/* RectL Object WMF manual 2.2.2.19 + Same as "EMF RECT Object" in uemf.h +*/ + +/* RGBQuad Object WMF manual 2.2.2.20 + Same as "EMF RGBQUAD Object" in uemf.h +*/ + +/** Scan Object WMF manual 2.2.2.21 */ +/** WMF manual 2.2.2.21 + + Mandatory field "count2" must follow ScanLines, but it cannot be placed into the struct because + ScanLines has variable size. "count2" is + an uint16_t value which must have the same value as count. +*/ +typedef struct { + uint16_t count; //!< Number of entries in the ScanLines array + uint16_t top; //!< Y coordinate of the top scanline + uint16_t bottom; //!< Y coordinate of the bottom scanline + uint16_t ScanLines[1]; //!< Array of 16 bit left/right pairs +} U_SCAN; + +/** SizeL Object WMF manual 2.2.2.22 + Same as "EMF SIZEL Object" in uemf.h +*/ + + +/** First three fields of MOST WMF records (not WMR_HEADER and WMR_PLACEABLE!) + + This Sshould only used for accessing size and type fields. + It is NOT used as a prefix like U_EMR in uemf.h because it may cause alignment issues. + Microsoft name: WMF Object +*/ +typedef struct { + uint16_t Size16_4[2]; //!< Total number of 16bit words in record + uint8_t iType; //!< RecordType Enumeration + uint8_t xb; //!< Extra high order byte associated with record type +} U_METARECORD; + +/** WMF manual 2.3.2.3 META_PLACEABLE + If present this must immediately precede the header. + It is not enumerated as an WMR record type. + This only ever occurs at the start of a WMF file, so the two uint32_t values will always be aligned. +*/ +typedef struct { + uint32_t Key; //!< MUST be 0x9AC6CDD7 + uint16_t HWmf; //!< 0. (Always. Manual says total number of 16bit words in record, but no examples found like that) + U_RECT16 Dst; //!< Destination bounding box in logical units + uint16_t Inch; //!< Logical units/inch (convention if not specified: 1440 logical units/inch) + uint32_t Reserved; //!< must be 0 + uint16_t Checksum; //!< Checksum of preceding 10 16 bit values +} U_WMRPLACEABLE; + +/** WMF manual 2.3.2.2 META_HEADER +*/ +typedef struct { + uint8_t iType; //!< RecordType Enumeration, must be 1 + uint8_t xb; //!< Extra high order byte associated with record type + uint16_t Size16w; //!< Total number of 16bit words in record + uint16_t version; //!< Metafile version Enumeration + uint16_t Sizew[2]; //!< reassemble/store the Size (16 bit words in entire file) using Sizew, the 32 bit value is not aligned + uint16_t nObjects; //!< Total number of brushes, pens, and other graphics objects defined in this file + uint32_t maxSize; //!< Largest record in file, in number of 16bit words (This uint32_t is aligned) + uint16_t nMembers; //!< Unused, should be 0 +} U_WMRHEADER; + + +// *********************************************************************************** +// The following structures correspond to U_WMR_# records + +/* Index 00 U_WMREOF WMF manual 2.3.2.1 META_EOF */ +/** WMF manual 2.3.2.1 META_EOF +*/ +typedef struct { + uint16_t Size16_4[2]; //!< Total number of 16bit words in record + uint8_t iType; //!< RecordType Enumeration + uint8_t xb; //!< Extra high order byte associated with record type +} U_WMREOF, + U_WMRSETRELABS, //!< WMF manual 2.3.5.21 + U_WMRSAVEDC, //!< WMF manual 2.3.5.11 + U_WMRREALIZEPALETTE; //!< WMF manual 2.3.5.8 + +/* Index 01 U_WMRSETBKCOLOR WMF manual 2.3.5.14 */ +/** WMF manual 2.3.5.14 +*/ +typedef struct { + uint16_t Size16_4[2]; //!< Total number of 16bit words in record + uint8_t iType; //!< RecordType Enumeration + uint8_t xb; //!< Extra high order byte associated with record type + U_COLORREF Color; //!< Color value, the 32 bit value is not aligned. +} U_WMRSETBKCOLOR, + U_WMRSETTEXTCOLOR; //!< WMF manual 2.3.5.26 + +/* Index 02 U_WMRSETBKMODE WMF manual 2.3.5.15 */ +/** WMF manual 2.3.5.15 +mode = MixMode Enumeration. +*/ +typedef struct { + uint16_t Size16_4[2]; //!< Total number of 16bit words in record + uint8_t iType; //!< RecordType Enumeration + uint8_t xb; //!< Extra high order byte associated with record type + uint16_t Mode; //!< Various Enumeraton. + uint16_t Reserved; //!< Ignore (ALSO OPTIONAL - FIELD MAY NOT BE PRESENT!!!!) +} U_WMRSETBKMODE, + U_WMRSETPOLYFILLMODE, //!< WMF manual 2.3.5.20 Mode = PolyFillMode Enumeration. + U_WMRSETROP2, //!< WMF manual 2.3.5.22 Binary Raster Operation Enumeration. + U_WMRSETSTRETCHBLTMODE, //!< WMF manual 2.3.5.23 Mode = StretchMode Enumeration + U_WMRSETTEXTALIGN; //!< WMF manual 2.3.5.24 Mode = TextAlignment Enumeration. + +/* Index 03 U_WMRSETMAPMODE WMF manual 2.3.5.17 */ +/** WMF manual 2.3.5.17 +Mode = MapMode Enumeration. +*/ +typedef struct { + uint16_t Size16_4[2]; //!< Total number of 16bit words in record + uint8_t iType; //!< RecordType Enumeration + uint8_t xb; //!< Extra high order byte associated with record type + uint16_t Mode; //!< Various Enumeraton and other +} U_WMRSETMAPMODE, + U_WMRSETTEXTCHAREXTRA; //!< WMF manual 2.3.5.25, Mode = Extra space in logical units to add to each character + +/* Index 04 U_WMRSETROP2 WMF manual 2.3.5.22 See Index 02 */ + +/* Index 05 U_WMRSETRELABS WMF manual 2.3.5.21 See Index 00*/ + +/* Index 06 U_WMRSETPOLYFILLMODE WMF manual 2.3.5.20 See Index 02 + Index 07 U_WMRSETSTRETCHBLTMODE WMF manual 2.3.5.23 */ + +/* Index 08 U_WMRSETTEXTCHAREXTRA WMF manual 2.3.5.25 See Index 03*/ + +/* Index 09 U_WMRSETTEXTCOLOR WMF manual 2.3.5.26 see Index 01 */ + +/* Index 0A U_WMRSETTEXTJUSTIFICATION WMF manual 2.3.5.27 */ +/** WMF manual 2.3.5.27 +*/ +typedef struct { + uint16_t Size16_4[2]; //!< Total number of 16bit words in record + uint8_t iType; //!< RecordType Enumeration + uint8_t xb; //!< Extra high order byte associated with record type + uint16_t Count; //!< Number of space characters in the line + uint16_t Extra; //!< Number of extra space characters to add to the line +} U_WMRSETTEXTJUSTIFICATION; + +/* Index 0B U_WMRSETWINDOWORG WMF manual 2.3.5.31 + Index 0C U_WMRSETWINDOWEXT WMF manual 2.3.5.30 + Index 0D U_WMRSETVIEWPORTORG WMF manual 2.3.5.29 + Index 0E U_WMRSETVIEWPORTEXT WMF manual 2.3.5.28 + Index 0F U_WMROFFSETWINDOWORG WMF manual 2.3.5.7 + Index 0F U_WMROFFSETVIEWPORTORG WMF manual 2.3.5.6 + Index 13 U_WMRLINETO WMF manual 2.3.3.10 + Index 14 U_WMRMOVETO WMF manual 2.3.3.4 + Index 20 U_WMROFFSETCLIPRGN WMF manual 2.3.5.5 +*/ +/** WMF manual 2.3.5.31 +Window X,Y origin +*/ +typedef struct { + uint16_t Size16_4[2]; //!< Total number of 16bit words in record + uint8_t iType; //!< RecordType Enumeration + uint8_t xb; //!< Extra high order byte associated with record type + int16_t y; //!< Y value (note order!) + int16_t x; //!< X value +} U_WMRSETWINDOWORG, + U_WMRSETWINDOWEXT, //!< WMF manual 2.3.5.30, Window X,Y extent + U_WMRSETVIEWPORTORG, //!< WMF manual 2.3.5.29, Viewport X,Y origin + U_WMRSETVIEWPORTEXT, //!< WMF manual 2.3.5.28, Viewport X,Y extent + U_WMROFFSETWINDOWORG, //!< WMF manual 2.3.5.7, Window X,Y offset in device units + U_WMROFFSETVIEWPORTORG, //!< WMF manual 2.3.5.6, Viewport X,Y offset in device units + U_WMRLINETO, //!< WMF manual 2.3.3.10, Endpoint X,Y in logical units + U_WMRMOVETO, //!< WMF manual 2.3.3.4, Destination X,Y in logical units + U_WMROFFSETCLIPRGN; //!< WMF manual 2.3.5.5, Y offset in logical units + +/* Index 10 U_WMRSCALEWINDOWEXT WMF manual 2.3.5.13 + Index 12 U_WMRSCALEVIEWPORTEXT WMF manual 2.3.5.12 +*/ +/** WMF manual 2.3.5.13 +*/ +typedef struct { + uint16_t Size16_4[2]; //!< Total number of 16bit words in record + uint8_t iType; //!< RecordType Enumeration + uint8_t xb; //!< Extra high order byte associated with record type + int16_t yDenom; //!< Y denominator + int16_t yNum; //!< Y numerator + int16_t xDenom; //!< X denominator + int16_t xNum; //!< X numerator +} U_WMRSCALEWINDOWEXT, + U_WMRSCALEVIEWPORTEXT; //!< WMF manual 2.3.5.12 + +/* Index 11 U_WMROFFSETVIEWPORTORG WMF manual 2.3.5.6 see Index 0B */ + +/* Index 12 U_WMRSCALEVIEWPORTEXT WMF manual 2.3.5.12 see Index 10 */ + +/* Index 13 U_WMRLINETO WMF manual 2.3.3.10 see index 0B + Index 14 U_WMRMOVETO WMF manual 2.3.5.4 */ + +/* Index 15 U_WMREXCLUDECLIPRECT WMF manual 2.3.5.2 + Index 16 U_WMRINTERSECTCLIPRECT WMF manual 2.3.5.3 +*/ +/** WMF manual 2.3.5.2 +*/ +typedef struct { + uint16_t Size16_4[2]; //!< Total number of 16bit words in record + uint8_t iType; //!< RecordType Enumeration + uint8_t xb; //!< Extra high order byte associated with record type + int16_t Bottom; //!< Coordinates in logical units + int16_t Right; //!< Coordinates in logical units + int16_t Top; //!< Coordinates in logical units + int16_t Left; //!< Coordinates in logical units +} U_WMREXCLUDECLIPRECT, + U_WMRINTERSECTCLIPRECT; //!< WMF manual 2.3.5.3 + +/* Index 17 U_WMRARC WMF manual 2.3.3.1 */ +/** WMF manual 2.3.3.1 +*/ +typedef struct { + uint16_t Size16_4[2]; //!< Total number of 16bit words in record + uint8_t iType; //!< RecordType Enumeration + uint8_t xb; //!< Extra high order byte associated with record type + int16_t yEndArc; //!< Coordinates in logical units + int16_t xEndArc; //!< Coordinates in logical units + int16_t yStartArc; //!< Coordinates in logical units + int16_t xStartArc; //!< Coordinates in logical units + int16_t Bottom; //!< Coordinates in logical units + int16_t Right; //!< Coordinates in logical units + int16_t Top; //!< Coordinates in logical units + int16_t Left; //!< Coordinates in logical units +} U_WMRARC; + +/* Index 18 U_WMRELLIPSE WMF manual 2.3.3.3 + Index 1B U_WMRRECTANGLE WMF manual 2.3.3.17 +*/ +/** WMF manual 2.3.3.3 +*/ +typedef struct { + uint16_t Size16_4[2]; //!< Total number of 16bit words in record + uint8_t iType; //!< RecordType Enumeration + uint8_t xb; //!< Extra high order byte associated with record type + int16_t Bottom; //!< Coordinates in logical units + int16_t Right; //!< Coordinates in logical units + int16_t Top; //!< Coordinates in logical units + int16_t Left; //!< Coordinates in logical units +} U_WMRELLIPSE, + U_WMRRECTANGLE; //!< WMF manual 2.3.3.17 + +/* Index 19 U_WMRFLOODFILL WMF manual 2.3.3.7 + Index 48 U_WMREXTFLOODFILL WMF manual 2.3.3.4 +*/ +/** WMF manual 2.3.3.7 +*/ +typedef struct { + uint16_t Size16_4[2]; //!< Total number of 16bit words in record + uint8_t iType; //!< RecordType Enumeration + uint8_t xb; //!< Extra high order byte associated with record type + int16_t Mode; //!< FloodFill Enumeration + U_COLORREF Color; //!< Color + int16_t y; //!< Y + int16_t x; //!< X +} U_WMRFLOODFILL, + U_WMREXTFLOODFILL; //!< WMF manual 2.3.3.7 + +/* Index 1A U_WMRPIE WMF manual 2.3.3.13 + Index 30 U_WMRCHORD WMF manual 2.3.3.2 +*/ +/** WMF manual 2.3.3.13 +*/ +typedef struct { + uint16_t Size16_4[2]; //!< Total number of 16bit words in record + uint8_t iType; //!< RecordType Enumeration + uint8_t xb; //!< Extra high order byte associated with record type + int16_t yRadial2; //!< in logical units + int16_t xRadial2; //!< in logical units + int16_t yRadial1; //!< in logical units + int16_t xRadial1; //!< in logical units + int16_t Bottom; //!< in logical units + int16_t Right; //!< in logical units + int16_t Top; //!< in logical units + int16_t Left; //!< in logical units +} U_WMRPIE, + U_WMRCHORD; //!< WMF manual 2.3.3.2 + +/* Index 1B U_WMRRECTANGLE WMF manual 2.3.3.17 See Index 18 */ + +/* Index 1C U_WMRROUNDRECT WMF manual 2.3.3.18 */ +/** WMF manual 2.3.3.18 +*/ +typedef struct { + uint16_t Size16_4[2]; //!< Total number of 16bit words in record + uint8_t iType; //!< RecordType Enumeration + uint8_t xb; //!< Extra high order byte associated with record type + int16_t Height; //!< in logical units (rounded corner) + int16_t Width; //!< in logical units (rounded corner) + int16_t Bottom; //!< in logical units + int16_t Right; //!< in logical units + int16_t Top; //!< in logical units + int16_t Left; //!< in logical units +} U_WMRROUNDRECT; + +/* Index 1D U_WMRPATBLT WMF manual 2.3.3.12 +*/ +/** WMF manual 2.3.3.12 +*/ +typedef struct { + uint16_t Size16_4[2]; //!< Total number of 16bit words in record + uint8_t iType; //!< RecordType Enumeration + uint8_t xb; //!< Extra high order byte associated with record type + uint16_t rop3w[2]; //!< reassemble/store the rop3 Ternary raster operation using rop3w, as the 32 bit value is not aligned + int16_t Height; //!< in logical units (of Rect to Fill) + int16_t Width; //!< in logical units (of Rect to Fill) + int16_t yDst; //!< in logical units (UL corner to fill) + int16_t xDst; //!< in logical units (UL corner to fill) +} U_WMRPATBLT; + +/* Index 1E U_WMRSAVEDC WMF manual 2.3.5.11 See Index 00*/ + +/* Index 1F U_WMRSETPIXEL WMF manual 2.3.3.19 */ +/** WMF manual 2.3.3.19 +*/ +typedef struct { + uint16_t Size16_4[2]; //!< Total number of 16bit words in record + uint8_t iType; //!< RecordType Enumeration + uint8_t xb; //!< Extra high order byte associated with record type + U_COLORREF Color; //!< Color + int16_t y; //!< Y + int16_t x; //!< X +} U_WMRSETPIXEL; + +/* Index 20 U_WMROFFSETCLIPRGN WMF manual 2.3.5.5 See Index 0B*/ + +/* Index 21 U_WMRTEXTOUT WMF manual 2.3.3.20 +*/ +/** WMF manual 2.3.3.20 +Also part of the record, following String, and so at variable positions: + +int16_t y; start position + +int16_t x; start position +*/ +typedef struct { + uint16_t Size16_4[2]; //!< Total number of 16bit words in record + uint8_t iType; //!< RecordType Enumeration + uint8_t xb; //!< Extra high order byte associated with record type + int16_t Length; //!< Stringlength in bytes + uint8_t String; //!< String to write, storage area must be 2n bytes. +} U_WMRTEXTOUT; + +/* Index 22 U_WMRBITBLT WMF manual 2.3.1.1 +*/ +/** WMF manual 2.3.1.1 + + This is a variable structure the core/invariant part extends to xSrc. + + if RecordSize == ((xb) + 3) then there is no bitmap and use the _NOPX form, otherwise use the _PX form + Use Macro U_TEST_NOPX2 + +*/ +typedef struct { + uint16_t Size16_4[2]; //!< Total number of 16bit words in record + uint8_t iType; //!< RecordType Enumeration + uint8_t xb; //!< Extra high order byte associated with record type + uint16_t rop3w[2]; //!< reassemble/store the Ternary raster operation rop3 value using rop3w, the 32 bit value is not aligned. + int16_t ySrc; //!< in logical units (UL corner of Src rect) + int16_t xSrc; //!< in logical units (UL corner of Src rect) + int16_t ignore; //!< ignore + int16_t Height; //!< in logical units (of Src and Dst rects) + int16_t Width; //!< in logical units (of Src and Dst rects) + int16_t yDst; //!< in logical units (UL corner of Dst rect) + int16_t xDst; //!< in logical units (UL corner of Dst rect) +} U_WMRBITBLT_NOPX; + +/** WMF manual 2.3.1.1 + + This is a variable structure the core/invariant part extends to xSrc. + + if RecordSize == ((xb) + 3) then there is no bitmap and use the _NOPX form, otherwise use the _PX form + Use Macro U_TEST_NOPX2 + +*/ +typedef struct { + uint16_t Size16_4[2]; //!< Total number of 16bit words in record + uint8_t iType; //!< RecordType Enumeration + uint8_t xb; //!< Extra high order byte associated with record type + uint16_t rop3w[2]; //!< reassemble/store the Ternary raster operation rop3 value using rop3w, the 32 bit value is not aligned. + int16_t ySrc; //!< in logical units (UL corner of Src rect) + int16_t xSrc; //!< in logical units (UL corner of Src rect) + int16_t Height; //!< in logical units (of Src and Dst rects) + int16_t Width; //!< in logical units (of Src and Dst rects) + int16_t yDst; //!< in logical units (UL corner of Dst rect) + int16_t xDst; //!< in logical units (UL corner of Dst rect) + U_BITMAP16 bitmap; //!< Src bitmap +} U_WMRBITBLT_PX; + + +/* Index 23 U_WMRSTRETCHBLT WMF manual 2.3.1.5 */ +/** WMF manual 2.3.1.5 + + This is a variable structure the core/invariant part extends to xSrc. + + if RecordSize == ((xb) + 3) then there is no bitmap and use the _NOPX form, otherwise use the _PX form + Use Macro U_TEST_NOPX2. +*/ + +typedef struct { + uint16_t Size16_4[2]; //!< Total number of 16bit words in record + uint8_t iType; //!< RecordType Enumeration + uint8_t xb; //!< Extra high order byte associated with record type + uint16_t rop3w[2]; //!< reassemble/store the Ternary raster operation rop3 value using rop3w, the 32 bit value is not aligned. + int16_t hSrc; //!< Height in logical units of Src rect + int16_t wSrc; //!< Wdith in logical units of Dst rect + int16_t ySrc; //!< in logical units (UL corner of Src rect) + int16_t xSrc; //!< in logical units (UL corner of Src rect) + int16_t ignore; //!< ignored + int16_t hDst; //!< Height in logical units of Dst rect + int16_t wDst; //!< Wdith in logical units of Dst rect + int16_t yDst; //!< in logical units (UL corner of Dst rect) + int16_t xDst; //!< in logical units (UL corner of Dst rect) +} U_WMRSTRETCHBLT_NOPX; + + +/* Index 23 U_WMRSTRETCHBLT WMF manual 2.3.1.5 */ +/** WMF manual 2.3.1.5 + + This is a variable structure the core/invariant part extends to xSrc. + + if RecordSize == ((xb) + 3) then there is no bitmap and use the _NOPX form, otherwise use the _PX form + Use Macro U_TEST_NOPX2. +*/ +typedef struct { + uint16_t Size16_4[2]; //!< Total number of 16bit words in record + uint8_t iType; //!< RecordType Enumeration + uint8_t xb; //!< Extra high order byte associated with record type + uint16_t rop3w[2]; //!< reassemble/store the Ternary raster operation rop3 value using rop3w, the 32 bit value is not aligned. + int16_t hSrc; //!< Height in logical units of Src rect + int16_t wSrc; //!< Wdith in logical units of Dst rect + int16_t ySrc; //!< in logical units (UL corner of Src rect) + int16_t xSrc; //!< in logical units (UL corner of Src rect) + int16_t hDst; //!< Height in logical units of Dst rect + int16_t wDst; //!< Wdith in logical units of Dst rect + int16_t yDst; //!< in logical units (UL corner of Dst rect) + int16_t xDst; //!< in logical units (UL corner of Dst rect) + U_BITMAP16 bitmap; //!< Src bitmap +} U_WMRSTRETCHBLT_PX; + +/* Index 24 U_WMRPOLYGON WMF manual 2.3.3.15 + Index 25 U_WMRPOLYLINE WMF manual 2.3.3.14 +*/ +/** WMF manual 2.3.3.15 +*/ +typedef struct { + uint16_t Size16_4[2]; //!< Total number of 16bit words in record + uint8_t iType; //!< RecordType Enumeration + uint8_t xb; //!< Extra high order byte associated with record type + int16_t nPoints; //!< Number of points in aPoints + U_POINT16 aPoints[1]; //!< Array of points +} U_WMRPOLYGON, + U_WMRPOLYLINE; //!< WMF manual 2.3.3.14 + +/* Index 26 U_WMRESCAPE WMF manual 2.3.6.1 */ +/** WMF manual 2.3.6.1 +*/ +typedef struct { + uint16_t Size16_4[2]; //!< Total number of 16bit words in record + uint8_t iType; //!< RecordType Enumeration + uint8_t xb; //!< Extra high order byte associated with record type + uint16_t eFunc; //!< Escape function + uint16_t nBytes; //!< bytes in the data array + uint8_t Data[1]; //!< data array +} U_WMRESCAPE; + +/* Index 27 U_WMRRESTOREDC WMF manual 2.3.5.10 */ +/** WMF manual 2.3.5.10 +*/ +typedef struct { + uint16_t Size16_4[2]; //!< Total number of 16bit words in record + uint8_t iType; //!< RecordType Enumeration + uint8_t xb; //!< Extra high order byte associated with record type + int16_t DC; //!< DC to restore (negative is relative to current, positive is absolute) +} U_WMRRESTOREDC; + +/* Index 28 U_WMRFILLREGION WMF manual 2.3.3.6 */ +/** WMF manual 2.3.3.6 +*/ +typedef struct { + uint16_t Size16_4[2]; //!< Total number of 16bit words in record + uint8_t iType; //!< RecordType Enumeration + uint8_t xb; //!< Extra high order byte associated with record type + uint16_t Region; //!< Index of region to fill in object table + uint16_t Brush; //!< Index of brush to use in object table +} U_WMRFILLREGION; + +/* Index 29 U_WMRFRAMEREGION WMF manual 2.3.3.8 */ +/** WMF manual 2.3.3.8 +*/ +typedef struct { + uint16_t Size16_4[2]; //!< Total number of 16bit words in record + uint8_t iType; //!< RecordType Enumeration + uint8_t xb; //!< Extra high order byte associated with record type + uint16_t Region; //!< Index of region to frame in object table + uint16_t Brush; //!< Index of brush to use in frame in object table + int16_t Height; //!< in logical units (of frame) + int16_t Width; //!< in logical units (of frame) +} U_WMRFRAMEREGION; + +/* Index 2A U_WMRINVERTREGION WMF manual 2.3.3.9 + Index 2B U_WMRPAINTREGION WMF manual 2.3.3.11 + Index 2C U_WMRSELECTCLIPREGION WMF manual 2.3.4.9 + Index 2D U_WMRSELECTOBJECT WMF manual 2.3.4.10 + Index 34 U_WMRSELECTPALETTE WMF manual 2.3.4.11 + Index 39 U_WMRRESIZEPALETTE WMF manual 2.3.5.9 + Index F0 U_WMRDELETEOBJECT WMF manual 2.3.4.7 +*/ +/** WMF manual 2.3.3.9 +invert region +*/ +typedef struct { + uint16_t Size16_4[2]; //!< Total number of 16bit words in record + uint8_t iType; //!< RecordType Enumeration + uint8_t xb; //!< Extra high order byte associated with record type + uint16_t index; //!< (usually) index of region/object in object table +} U_WMRINVERTREGION, + U_WMRPAINTREGION, //!< WMF manual 2.3.3.11, paint region + U_WMRSELECTCLIPREGION, //!< WMF manual 2.3.4.9, select as clip region + U_WMRSELECTOBJECT, //!< WMF manual 2.3.4.10, select object + U_WMRSELECTPALETTE, //!< WMF manual 2.3.4.11, select palette object + U_WMRRESIZEPALETTE, //!< WMF manual 2.3.5.9, resize the system palette to "index" + U_WMRDELETEOBJECT; //!< WMF manual 2.3.4.7, delete object + +/* Index 2E U_WMRSETTEXTALIGN WMF manual 2.3.5.24 See Index 02 */ + +/* Index 2F U_WMRDRAWTEXT in GDI and Wine, not documented in WMF manual. + Index FE U_WMRCREATEBITMAP in GDI and Wine, not documented in WMF manual. + Index FD U_WMRCREATEBITMAPINDIRECT in GDI and Wine, not documented in WMF manual. + + no documentation found, this part of these records, at least, must be correct */ +/** in GDI and Wine, not documented in WMF manual. +*/ +typedef struct { + uint16_t Size16_4[2]; //!< Total number of 16bit words in record + uint8_t iType; //!< RecordType Enumeration + uint8_t xb; //!< Extra high order byte associated with record type +} U_WMRDRAWTEXT, + U_WMRCREATEBITMAPINDIRECT, //!< in GDI and Wine, not documented in WMF manual. + U_WMRCREATEBITMAP; //!< in GDI and Wine, not documented in WMF manual. + +/* Index 30 U_WMRCHORD WMF manual 2.3.3.2 See Index 1A */ + +/* Index 31 U_WMRSETMAPPERFLAGS WMF manual 2.3.5.18 */ +/** WMF manual 2.3.5.18 +*/ +typedef struct { + uint16_t Size16_4[2]; //!< Total number of 16bit words in record + uint8_t iType; //!< RecordType Enumeration + uint8_t xb; //!< Extra high order byte associated with record type + uint16_t valuew[2]; //!< if 1 bit set font mapper selects only matching aspect fonts. reassemble/store the value using valuew, the 32 bit value is not aligned. +} U_WMRSETMAPPERFLAGS; + +/* Index 32 U_WMREXTTEXTOUT WMF manual 2.3.3.5 +*/ +/** WMF manual 2.3.3.5 + + Variable size record. Optional fields which follow the struct fields are: + + U_RECT16 Rect; Only present when U_ETO_OPAQUE or U_ETO_CLIPPED bits are set in Opts + uint8_t String; String to write, storage area must be 2n bytes. + int16_t Dx; Kerning information. Must have same number of entries as Length. + Dx is present when + 2*Size16_4[2] -14 - 2*((Length + 1)/2)) - 8*(Opts & (U_ETO_OPAQUE | U_ETO_CLIPPED)) == 2*Length +*/ +typedef struct { + uint16_t Size16_4[2]; //!< Total number of 16bit words in record + uint8_t iType; //!< RecordType Enumeration + uint8_t xb; //!< Extra high order byte associated with record type + int16_t y; //!< in logical units (draw point) + int16_t x; //!< in logical units (draw point) + int16_t Length; //!< Stringlength in bytes + uint16_t Opts; //!< ExtTextOutOptions Flags +} U_WMREXTTEXTOUT; + +/* Index 33 U_WMRSETDIBTODEV WMF manual 2.3.1.4 */ +/** WMF manual 2.3.1.4 + + Constant part of record is shown. It is followed by a DeviceIndependentBitmap Object +*/ +typedef struct { + uint16_t Size16_4[2]; //!< Total number of 16bit words in record + uint8_t iType; //!< RecordType Enumeration + uint8_t xb; //!< Extra high order byte associated with record type + uint16_t cUsage; //!< ColorUsage Enumeration + uint16_t ScanCount; //!< Number of scan lines in Src + uint16_t StartScan; //!< First Scan line in Src + int16_t ySrc; //!< in logical units (UL corner of Src rect) + int16_t xSrc; //!< in logical units (UL corner of Src rect) + int16_t Height; //!< in logical units (of Src and Dst) + int16_t Width; //!< in logical units (of Src and Dst) + int16_t yDst; //!< in logical units (UL corner of Dst rect) + int16_t xDst; //!< in logical units (UL corner of Dst rect) + uint8_t dib[1]; //!< DeviceIndependentBitmap object +} U_WMRSETDIBTODEV; + +/* Index 34 U_WMRSELECTPALETTE WMF manual 2.3.4.11 See Index 2A */ + +/* Index 35 U_WMRREALIZEPALETTE WMF manual 2.3.5.8 See Index 00 */ + +/* Index 36 U_WMRANIMATEPALETTE WMF manual 2.3.5.1 + Index 37 U_WMRSETPALENTRIES WMF manual 2.3.5.19 + Index F7 U_WMRCREATEPALETTE WMF manual 2.3.4.3 +*/ +/** WMF manual 2.3.5.1 +*/ +typedef struct { + uint16_t Size16_4[2]; //!< Total number of 16bit words in record + uint8_t iType; //!< RecordType Enumeration + uint8_t xb; //!< Extra high order byte associated with record type + U_PALETTE Palette; //!< Palette object +} U_WMRANIMATEPALETTE, + U_WMRSETPALENTRIES, //!< WMF manual 2.3.5.19 + U_WMRCREATEPALETTE; //!< WMF manual 2.3.4.3 + +/* Index 38 U_WMRPOLYPOLYGON WMF manual 2.3.3.16 */ +/** WMF manual 2.3.3.16 +*/ +typedef struct { + uint16_t Size16_4[2]; //!< Total number of 16bit words in record + uint8_t iType; //!< RecordType Enumeration + uint8_t xb; //!< Extra high order byte associated with record type + U_POLYPOLYGON PPolygon; //!< PolyPolygon object (size is variable!) +} U_WMRPOLYPOLYGON; + +/* Index 39 U_WMRRESIZEPALETTE WMF manual 2.3.5.9 See Index 2A */ + +/* Index 40 U_WMRDIBBITBLT WMF manual 2.3.1.2 +*/ +/** WMF manual 2.3.1.2 + + The PX form is a variable structure the core/invariant part extends to xDst, and that is + followed by a DeviceInvariantBitmap object which starts at "dib". + The NOPX form is a constant structure. + + if RecordSize == ((xb) + 3) then there is no bitmap and use the _NOPX form, otherwise use the _PX form + Use Macro U_TEST_NOPX2. +*/ +typedef struct { + uint16_t Size16_4[2]; //!< Total number of 16bit words in record + uint8_t iType; //!< RecordType Enumeration + uint8_t xb; //!< Extra high order byte associated with record type + uint16_t rop3w[2]; //!< reassemble/store the Ternary raster operation rop3 value using rop3w, the 32 bit value is not aligned. + int16_t ySrc; //!< in logical units (UL corner of Src rect) + int16_t xSrc; //!< in logical units (UL corner of Src rect) + uint16_t ignore; //!< ignore + int16_t Height; //!< in logical units (of Src and Dst) + int16_t Width; //!< in logical units (of Src and Dst) + int16_t yDst; //!< in logical units (UL corner of Dst rect) + int16_t xDst; //!< in logical units (UL corner of Dst rect) +} U_WMRDIBBITBLT_NOPX; + +/** WMF manual 2.3.1.2 + + The PX form is a variable structure the core/invariant part extends to xDst, and that is + followed by a DeviceInvariantBitmap object which starts at "dib". + The NOPX form is a constant structure. + + if RecordSize == ((xb) + 3) then there is no bitmap and use the _NOPX form, otherwise use the _PX form + Use Macro U_TEST_NOPX2. +*/ +typedef struct { + uint16_t Size16_4[2]; //!< Total number of 16bit words in record + uint8_t iType; //!< RecordType Enumeration + uint8_t xb; //!< Extra high order byte associated with record type + uint16_t rop3w[2]; //!< reassemble/store the Ternary raster operation rop3 value using rop3w, the 32 bit value is not aligned. + int16_t ySrc; //!< in logical units (UL corner of Src rect) + int16_t xSrc; //!< in logical units (UL corner of Src rect) + int16_t Height; //!< in logical units (of Src and Dst) + int16_t Width; //!< in logical units (of Src and Dst) + int16_t yDst; //!< in logical units (UL corner of Dst rect) + int16_t xDst; //!< in logical units (UL corner of Dst rect) + uint8_t dib[1]; //!< DeviceIndependentBitmap object +} U_WMRDIBBITBLT_PX; + +/* Index 41 U_WMRDIBSTRETCHBLT WMF manual 2.3.1.3 */ +/** WMF manual 2.3.1.3 + + The PX form is a variable structure the core/invariant part extends to xDst, and that is + followed by a DeviceInvariantBitmap object which starts at "dib". + The NOPX form is a constant structure. + + if RecordSize == ((xb) + 3) then there is no bitmap and use the _NOPX form, otherwise use the _PX form + Use Macro U_TEST_NOPX2. +*/ +typedef struct { + uint16_t Size16_4[2]; //!< Total number of 16bit words in record + uint8_t iType; //!< RecordType Enumeration + uint8_t xb; //!< Extra high order byte associated with record type + uint16_t rop3w[2]; //!< reassemble/store the Ternary raster operation rop3 value using rop3w, the 32 bit value is not aligned. + int16_t hSrc; //!< in logical units (of Src) + int16_t wSrc; //!< in logical units (of Src) + int16_t ySrc; //!< in logical units (UL corner of Src rect) + int16_t xSrc; //!< in logical units (UL corner of Src rect) + uint16_t ignore; //!< ignore + int16_t hDst; //!< in logical units (of Dst) + int16_t wDst; //!< in logical units (of Dst) + int16_t yDst; //!< in logical units (UL corner of Dst rect) + int16_t xDst; //!< in logical units (UL corner of Dst rect) +} U_WMRDIBSTRETCHBLT_NOPX; + +/** WMF manual 2.3.1.3 + + The PX form is a variable structure the core/invariant part extends to xDst, and that is + followed by a DeviceInvariantBitmap object which starts at "dib". + The NOPX form is a constant structure. + + if RecordSize == ((xb) + 3) then there is no bitmap and use the _NOPX form, otherwise use the _PX form + Use Macro U_TEST_NOPX2. +*/ +typedef struct { + uint16_t Size16_4[2]; //!< Total number of 16bit words in record + uint8_t iType; //!< RecordType Enumeration + uint8_t xb; //!< Extra high order byte associated with record type + uint16_t rop3w[2]; //!< reassemble/store the Ternary raster operation rop3 value using rop3w, the 32 bit value is not aligned. + int16_t hSrc; //!< in logical units (of Src) + int16_t wSrc; //!< in logical units (of Src) + int16_t ySrc; //!< in logical units (UL corner of Src rect) + int16_t xSrc; //!< in logical units (UL corner of Src rect) + int16_t hDst; //!< in logical units (of Dst) + int16_t wDst; //!< in logical units (of Dst) + int16_t yDst; //!< in logical units (UL corner of Dst rect) + int16_t xDst; //!< in logical units (UL corner of Dst rect) + uint8_t dib[1]; //!< DeviceIndependentBitmap object +} U_WMRDIBSTRETCHBLT_PX; + + +/* Index 42 U_WMRDIBCREATEPATTERNBRUSH WMF manual 2.3.4.8 +*/ +/** WMF manual 2.3.4.8 + + style cUsage Brush created + U_BS_SOLID like U_BS_DIBPATTERNPT + U_BS_NULL like U_BS_DIBPATTERNPT + U_BS_HATCHED like U_BS_DIBPATTERNPT + U_BS_DIBPATTERNPT ColorUsage enumer. U_BS_DIBPATTERNPT brush from DIB in Src + U_BS_PATTERN ColorUsage enumer. U_BS_PATTERN brush from Bitmap16 object in Src +*/ +typedef struct { + uint16_t Size16_4[2]; //!< Total number of 16bit words in record + uint8_t iType; //!< RecordType Enumeration + uint8_t xb; //!< Extra high order byte associated with record type + uint16_t Style; //!< BrushStyle Enumeration + uint16_t cUsage; //!< See table above + uint8_t Src[1]; //!< DeviceIndependentBitmap or Bitmap16 object +} U_WMRDIBCREATEPATTERNBRUSH; + +/* Index 43 U_WMRSTRETCHDIB WMF manual 2.3.1.6 */ +/** WMF manual 2.3.1.6 +*/ +typedef struct { + uint16_t Size16_4[2]; //!< Total number of 16bit words in record + uint8_t iType; //!< RecordType Enumeration + uint8_t xb; //!< Extra high order byte associated with record type + uint16_t rop3w[2]; //!< reassemble/store the Ternary raster operation rop3 value using rop3w, the 32 bit value is not aligned. + uint16_t cUsage; //!< ColorUsage Enumeration + int16_t hSrc; //!< in logical units (of Src) + int16_t wSrc; //!< in logical units (of Src) + int16_t ySrc; //!< in logical units (UL corner of Src rect) + int16_t xSrc; //!< in logical units (UL corner of Src rect) + int16_t hDst; //!< in logical units (of Dst) + int16_t wDst; //!< in logical units (of Dst) + int16_t yDst; //!< in logical units (UL corner of Dst rect) + int16_t xDst; //!< in logical units (UL corner of Dst rect) + uint8_t dib[1]; //!< DeviceIndependentBitmap object +} U_WMRSTRETCHDIB; + +/* Index 48 U_WMREXTFLOODFILL WMF manual 2.3.3.4 See Index 19*/ +/* Index 4C U_WMR4C */ +/* Index 4D U_WMR4D */ +/* Index 4F U_WMR4F */ +/* Index 50 U_WMR50 */ +/* Index 52 U_WMR52 */ +/* Index 5E U_WMR5E */ +/* Index 5F U_WMR5F */ +/* Index 60 U_WMR60 */ +/* Index 61 U_WMR61 */ +/* Index 62 U_WMR62 */ +/* Index 63 U_WMR63 */ +/* Index 64 U_WMR64 */ +/* Index 65 U_WMR65 */ +/* Index 66 U_WMR66 */ +/* Index 67 U_WMR67 */ +/* Index 68 U_WMR68 */ +/* Index 69 U_WMR69 */ +/* Index 6A U_WMR6A */ +/* Index 6B U_WMR6B */ +/* Index 6C U_WMR6C */ +/* Index 6D U_WMR6D */ +/* Index 6E U_WMR6E */ +/* Index 6F U_WMR6F */ +/* Index 70 U_WMR70 */ +/* Index 71 U_WMR71 */ +/* Index 72 U_WMR72 */ +/* Index 73 U_WMR73 */ +/* Index 74 U_WMR74 */ +/* Index 75 U_WMR75 */ +/* Index 76 U_WMR76 */ +/* Index 77 U_WMR77 */ +/* Index 78 U_WMR78 */ +/* Index 79 U_WMR79 */ +/* Index 7A U_WMR7A */ +/* Index 7B U_WMR7B */ +/* Index 7C U_WMR7C */ +/* Index 7D U_WMR7D */ +/* Index 7E U_WMR7E */ +/* Index 7F U_WMR7F */ +/* Index 80 U_WMR80 */ +/* Index 81 U_WMR81 */ +/* Index 82 U_WMR82 */ +/* Index 83 U_WMR83 */ +/* Index 84 U_WMR84 */ +/* Index 85 U_WMR85 */ +/* Index 86 U_WMR86 */ +/* Index 87 U_WMR87 */ +/* Index 88 U_WMR88 */ +/* Index 89 U_WMR89 */ +/* Index 8A U_WMR8A */ +/* Index 8B U_WMR8B */ +/* Index 8C U_WMR8C */ +/* Index 8D U_WMR8D */ +/* Index 8E U_WMR8E */ +/* Index 8F U_WMR8F */ +/* Index 90 U_WMR90 */ +/* Index 91 U_WMR91 */ +/* Index 92 U_WMR92 */ +/* Index 93 U_WMR93 */ +/* Index 94 U_WMR94 */ +/* Index 95 U_WMR95 */ +/* Index 96 U_WMR96 */ +/* Index 97 U_WMR97 */ +/* Index 98 U_WMR98 */ +/* Index 99 U_WMR99 */ +/* Index 9A U_WMR9A */ +/* Index 9B U_WMR9B */ +/* Index 9C U_WMR9C */ +/* Index 9D U_WMR9D */ +/* Index 9E U_WMR9E */ +/* Index 9F U_WMR9F */ +/* Index A0 U_WMRA0 */ +/* Index A1 U_WMRA1 */ +/* Index A2 U_WMRA2 */ +/* Index A3 U_WMRA3 */ +/* Index A4 U_WMRA4 */ +/* Index A5 U_WMRA5 */ +/* Index A6 U_WMRA6 */ +/* Index A7 U_WMRA7 */ +/* Index A8 U_WMRA8 */ +/* Index A9 U_WMRA9 */ +/* Index AA U_WMRAA */ +/* Index AB U_WMRAB */ +/* Index AC U_WMRAC */ +/* Index AD U_WMRAD */ +/* Index AE U_WMRAE */ +/* Index AF U_WMRAF */ +/* Index B0 U_WMRB0 */ +/* Index B1 U_WMRB1 */ +/* Index B2 U_WMRB2 */ +/* Index B3 U_WMRB3 */ +/* Index B4 U_WMRB4 */ +/* Index B5 U_WMRB5 */ +/* Index B6 U_WMRB6 */ +/* Index B7 U_WMRB7 */ +/* Index B8 U_WMRB8 */ +/* Index B9 U_WMRB9 */ +/* Index BA U_WMRBA */ +/* Index BB U_WMRBB */ +/* Index BC U_WMRBC */ +/* Index BD U_WMRBD */ +/* Index BE U_WMRBE */ +/* Index BF U_WMRBF */ +/* Index C0 U_WMRC0 */ +/* Index C1 U_WMRC1 */ +/* Index C2 U_WMRC2 */ +/* Index C3 U_WMRC3 */ +/* Index C4 U_WMRC4 */ +/* Index C5 U_WMRC5 */ +/* Index C6 U_WMRC6 */ +/* Index C7 U_WMRC7 */ +/* Index C8 U_WMRC8 */ +/* Index C9 U_WMRC9 */ +/* Index CA U_WMRCA */ +/* Index CB U_WMRCB */ +/* Index CC U_WMRCC */ +/* Index CD U_WMRCD */ +/* Index CE U_WMRCE */ +/* Index CF U_WMRCF */ +/* Index D0 U_WMRD0 */ +/* Index D1 U_WMRD1 */ +/* Index D2 U_WMRD2 */ +/* Index D3 U_WMRD3 */ +/* Index D4 U_WMRD4 */ +/* Index D5 U_WMRD5 */ +/* Index D6 U_WMRD6 */ +/* Index D7 U_WMRD7 */ +/* Index D8 U_WMRD8 */ +/* Index D9 U_WMRD9 */ +/* Index DA U_WMRDA */ +/* Index DB U_WMRDB */ +/* Index DC U_WMRDC */ +/* Index DD U_WMRDD */ +/* Index DE U_WMRDE */ +/* Index DF U_WMRDF */ +/* Index E0 U_WMRE0 */ +/* Index E1 U_WMRE1 */ +/* Index E2 U_WMRE2 */ +/* Index E3 U_WMRE3 */ +/* Index E4 U_WMRE4 */ +/* Index E5 U_WMRE5 */ +/* Index E6 U_WMRE6 */ +/* Index E7 U_WMRE7 */ +/* Index E8 U_WMRE8 */ +/* Index E9 U_WMRE9 */ +/* Index EA U_WMREA */ +/* Index EB U_WMREB */ +/* Index EC U_WMREC */ +/* Index ED U_WMRED */ +/* Index EE U_WMREE */ +/* Index EF U_WMREF */ +/* Index F0 U_WMRDELETEOBJECT WMF manual 2.3.4.7 See Index 2A */ +/* Index F1 U_WMRF1 */ +/* Index F2 U_WMRF2 */ +/* Index F3 U_WMRF3 */ +/* Index F4 U_WMRF4 */ +/* Index F5 U_WMRF5 */ + +/* Index F7 U_WMRCREATEPALETTE WMF manual 2.3.4.3 See Index 36*/ + +/* Index F8 U_WMRF8 */ +/* Index F9 U_WMRCREATEPATTERNBRUSH WMF manual 2.3.4.4 */ +/** WMF manual 2.3.4.4 + + WARNING - U_WMRCREATEPATTERNBRUSH has been declared obsolete and application support is spotty - + use U_WMRDIBCREATEPATTERNBRUSH instead. + + This record is peculiar... + + After the core structure there is: + + A truncated U_BITMAP16. Only the first 14 bytes are present, and the last 4 bytes (bits section) are ignored. + 18 zero bytes (reserved) + A pattern. The pattern is a byte array whose size is set by the fields in the U_BITMAP16 structure as follows: + + (((Width * BitsPixel + 15) >> 4) << 1) * Height + + brush created has style U_BS_PATTERN. + +*/ +typedef struct { + uint16_t Size16_4[2]; //!< Total number of 16bit words in record + uint8_t iType; //!< RecordType Enumeration + uint8_t xb; //!< Extra high order byte associated with record type +} U_WMRCREATEPATTERNBRUSH; + +/* Index FA U_WMRCREATEPENINDIRECT WMF manual 2.3.4.5 */ +/** WMF manual 2.3.4.5 +*/ +typedef struct { + uint16_t Size16_4[2]; //!< Total number of 16bit words in record + uint8_t iType; //!< RecordType Enumeration + uint8_t xb; //!< Extra high order byte associated with record type + U_PEN pen; //!< Pen Object +} U_WMRCREATEPENINDIRECT; + +/* Index FB U_WMRCREATEFONTINDIRECT WMF manual 2.3.4.2 */ +/** WMF manual 2.3.4.2 +*/ +typedef struct { + uint16_t Size16_4[2]; //!< Total number of 16bit words in record + uint8_t iType; //!< RecordType Enumeration + uint8_t xb; //!< Extra high order byte associated with record type + U_FONT font; //!< Font Object +} U_WMRCREATEFONTINDIRECT; + +/* Index FC U_WMRCREATEBRUSHINDIRECT WMF manual 2.3.4.1 */ +/** WMF manual 2.3.4.1 +*/ +typedef struct { + uint16_t Size16_4[2]; //!< Total number of 16bit words in record + uint8_t iType; //!< RecordType Enumeration + uint8_t xb; //!< Extra high order byte associated with record type + U_WLOGBRUSH brush; //!< WLogBrush Object +} U_WMRCREATEBRUSHINDIRECT; + +/* Index FD U_WMRCREATEBITMAPINDIRECT in GDI and Wine, not in WMF manual, see index 2F */ + +/* Index FE U_WMRCREATEBITMAP in GDI and Wine, not in WMF manual, see index 2F */ + +/* Index FF U_WMRCREATEREGION WMF manual 2.3.4.6 */ +/** WMF manual 2.3.4.6 +*/ +typedef struct { + uint16_t Size16_4[2]; //!< Total number of 16bit words in record + uint8_t iType; //!< RecordType Enumeration + uint8_t xb; //!< Extra high order byte associated with record type + U_REGION region; //!< Region Object +} U_WMRCREATEREGION; + + + +// ************************************************************************************************ +// Utility function structures + +/** + Storage for keeping track of properties of the growing WMF file as records are added. +*/ +typedef struct { + FILE *fp; //!< Open file + size_t allocated; //!< Size of the buffer + size_t used; //!< Amount consumed + uint32_t records; //!< Number of records already contained + uint16_t ignore; //!< size padding,not used + uint32_t PalEntries; //!< Number of PalEntries (set from U_EMREOF) + uint32_t chunk; //!< Number of bytes to add when more space is needed + char *buf; //!< Buffer for constructing the EMF in memory + uint32_t largest; //!< Largest record size, in bytes (used by WMF, not by EMF) + uint32_t sumObjects; //!< Number of objects appended (used by WMF, not by EMF) [ also see wmf_highwater() ] +} WMFTRACK; + +/** + The various create functions need a place to put their handles, these are stored in the table below. + We don't actually do anything much with these handles, that is up to whatever program finally plays back the WMF, but + we do need to keep track of the numbers so that they are not accidentally reused. (Also WMF files have rules + about how object handles must be numbered, for instance, the lowest possible number must always be used. These + are different from EMF object handles.) This structure is used for staying in conformance with these rules. + + There are no stock objects in WMF files. +*/ +typedef struct { + uint32_t *table; //!< Array Buffer for constructing the WMF in memory + size_t allocated; //!< Slots in the buffer + size_t chunk; //!< Number to add if a realloc is required + uint32_t lolimit; //!< Lowest unoccupied table slot, may be a hole created by a deleteobject. + uint32_t hilimit; //!< Highest table slot occupied (currently) + uint32_t peak; //!< Highest table slot occupied (ever) +} WMFHANDLES; + +//! \cond +// ************************************************************************************************ +// Prototypes (_set first, then _get) +char *wmr_dup(const char *wmr); +int wmf_start(const char *name, uint32_t initsize, uint32_t chunksize, WMFTRACK **wt); +int uwmf_free(WMFTRACK **wt); +int wmf_finish(WMFTRACK *wt); +int wmf_append(U_METARECORD *rec, WMFTRACK *wt, int freerec); +int wmf_header_append(U_METARECORD *rec,WMFTRACK *et, int freerec); +int wmf_readdata(const char *filename, char **contents, size_t*length); +#define wmf_fopen emf_fopen +int wmf_highwater(uint32_t setval); +int wmf_htable_create(uint32_t initsize, uint32_t chunksize, WMFHANDLES **wht); +int wmf_htable_delete(uint32_t *ih, WMFHANDLES *wht); +int wmf_htable_insert(uint32_t *ih, WMFHANDLES *wht); +int wmf_htable_free(WMFHANDLES **wht); +int16_t U_16_checksum(int16_t *buf, int count); +int16_t *dx16_set( int32_t height, uint32_t weight, uint32_t members); +uint32_t U_wmr_properties(uint32_t type); + +uint32_t U_wmr_size(const U_METARECORD *record); +uint32_t U_wmr_values(int idx); +const char *U_wmr_names(int idx); +const char *U_wmr_escnames(int idx); + +void U_sanerect16(U_RECT16 rc, double *left, double *top, double *right, double *bottom); + + +U_FONT *U_FONT_set(int16_t Height, int16_t Width, int16_t Escapement, int16_t Orientation, + int16_t Weight, uint8_t Italic, uint8_t Underline, uint8_t StrikeOut, + uint8_t CharSet, uint8_t OutPrecision, uint8_t ClipPrecision, + uint8_t Quality, uint8_t PitchAndFamily, char *FaceName); +U_PLTNTRY U_PLTNTRY_set(U_COLORREF Color); +U_PALETTE *U_PLTENTRY_set(uint16_t Start, uint16_t NumEntries, U_PLTNTRY *Entries); +U_PEN U_PEN_set(uint16_t Style, uint16_t Width, U_COLORREF Color); +U_RECT16 U_RECT16_set(U_POINT16 ul,U_POINT16 lr); +U_BITMAP16 *U_BITMAP16_set(const int16_t Type, const int16_t Width, const int16_t Height, + const int16_t LineN, const uint8_t BitsPixel, const char *Bits); +U_SCAN *U_SCAN_set(uint16_t count, uint16_t top, uint16_t bottom, uint16_t *ScanLines); +U_REGION *U_REGION_set(int16_t Size, int16_t sCount, int16_t sMax, U_RECT16 sRect, uint16_t *aScans); +U_WLOGBRUSH U_WLOGBRUSH_set(uint16_t Style, U_COLORREF Color, uint16_t Hatch); +U_PAIRF *U_PAIRF_set(float x, float y); + +char *wdeleteobject_set(uint32_t *ihObject, WMFHANDLES *wht); +char *wselectobject_set(uint32_t ihObject, WMFHANDLES *wht ); +char *wcreatepenindirect_set(uint32_t *ihPen, WMFHANDLES *wht, U_PEN pen); +char *wcreatebrushindirect_set(uint32_t *ihBrush, WMFHANDLES *wht, U_WLOGBRUSH lb); +char *wcreatedibpatternbrush_srcdib_set(uint32_t *ihBrush, WMFHANDLES *wht, + uint32_t iUsage, const U_BITMAPINFO *Bmi, uint32_t cbPx, const char *Px); +char *wcreatedibpatternbrush_srcbm16_set(uint32_t *ihBrush, WMFHANDLES *wht, + uint32_t iUsage, const U_BITMAP16 *Bm16); +char *wcreatepatternbrush_set(uint32_t *ihBrush, WMFHANDLES *wht, U_BITMAP16 *Bm16, char *Pattern); +char *wcreatefontindirect_set(uint32_t *ihFont, WMFHANDLES *wht, U_FONT *uf); +char *wcreatepalette_set(uint32_t *ihPal, WMFHANDLES *wht, U_PALETTE *up); +char *wsetpaletteentries_set(uint32_t *ihPal, WMFHANDLES *wht, const U_PALETTE *Palletes); +char *wcreateregion_set(uint32_t *ihReg, WMFHANDLES *wht, const U_REGION *Region); +char *wbegin_path_set(void); +char *wend_path_set(void); +char *wlinecap_set(int32_t Type); +char *wlinejoin_set(int32_t Type); +char *wmiterlimit_set(int32_t limit); + + +char *U_WMRHEADER_set(U_PAIRF *size,unsigned int dpi); +char *U_WMREOF_set(void); +char *U_WMRSETBKCOLOR_set(U_COLORREF Color); +char *U_WMRSETBKMODE_set(uint16_t Mode); +char *U_WMRSETMAPMODE_set(uint16_t Mode); +char *U_WMRSETROP2_set(uint16_t Mode); +char *U_WMRSETRELABS_set(void); +char *U_WMRSETPOLYFILLMODE_set(uint16_t Mode); +char *U_WMRSETSTRETCHBLTMODE_set(uint16_t Mode); +char *U_WMRSETTEXTCHAREXTRA_set(uint16_t Mode); +char *U_WMRSETTEXTCOLOR_set(U_COLORREF Color); +char *U_WMRSETTEXTJUSTIFICATION_set(uint16_t Count, uint16_t Extra); +char *U_WMRSETWINDOWORG_set(U_POINT16 coord); +char *U_WMRSETWINDOWEXT_set(U_POINT16 extent); +char *U_WMRSETVIEWPORTORG_set(U_POINT16 coord); +char *U_WMRSETVIEWPORTEXT_set(U_POINT16 extent); +char *U_WMROFFSETWINDOWORG_set(U_POINT16 offset); +char *U_WMRSCALEWINDOWEXT_set(U_POINT16 Denom, U_POINT16 Num); +char *U_WMROFFSETVIEWPORTORG_set(U_POINT16 offset); +char *U_WMRSCALEVIEWPORTEXT_set(U_POINT16 Denom, U_POINT16 Num); +char *U_WMRLINETO_set(U_POINT16 coord); +char *U_WMRMOVETO_set(U_POINT16 coord); +char *U_WMREXCLUDECLIPRECT_set(U_RECT16 rect); +char *U_WMRINTERSECTCLIPRECT_set(U_RECT16 rect); +char *U_WMRARC_set(U_POINT16 StartArc, U_POINT16 EndArc, U_RECT16 rect); +char *U_WMRELLIPSE_set(U_RECT16 rect); +char *U_WMRFLOODFILL_set(uint16_t Mode, U_COLORREF Color, U_POINT16 coord); +char *U_WMRPIE_set(U_POINT16 Radial1, U_POINT16 Radial2, U_RECT16 rect); +char *U_WMRRECTANGLE_set(U_RECT16 rect); +char *U_WMRROUNDRECT_set(int16_t Width, int16_t Height, U_RECT16 rect); +char *U_WMRPATBLT_set(U_POINT16 Dst, U_POINT16 cwh, uint32_t dwRop3); +char *U_WMRSAVEDC_set(void); +char *U_WMRSETPIXEL_set(U_COLORREF Color, U_POINT16 coord); +char *U_WMROFFSETCLIPRGN_set(U_POINT16 offset); +char *U_WMRTEXTOUT_set(U_POINT16 Dst, char *string); +char *U_WMRBITBLT_set(U_POINT16 Dst, U_POINT16 cwh, U_POINT16 Src, + uint32_t dwRop3, const U_BITMAP16 *Bm16); +char *U_WMRSTRETCHBLT_set(U_POINT16 Dst, U_POINT16 cDst, U_POINT16 Src, + U_POINT16 cSrc, uint32_t dwRop3, const U_BITMAP16 *Bm16); +char *U_WMRPOLYGON_set(uint16_t Length, const U_POINT16 * Data); +char *U_WMRPOLYLINE_set(uint16_t Length, const U_POINT16 * Data); +char *U_WMRESCAPE_set(uint16_t Escape, uint16_t Length, const void *Data); +char *U_WMRRESTOREDC_set(int16_t DC); +char *U_WMRFILLREGION_set(uint16_t Region, uint16_t Brush); +char *U_WMRFRAMEREGION_set(uint16_t Region, uint16_t Brush, int16_t Height, int16_t Width); +char *U_WMRINVERTREGION_set(uint16_t Region); +char *U_WMRPAINTREGION_set(uint16_t Region); +char *U_WMRSELECTCLIPREGION_set(uint16_t Region); +char *U_WMRSELECTOBJECT_set(uint16_t object); +char *U_WMRSETTEXTALIGN_set(uint16_t Mode); +char *U_WMRDRAWTEXT_set(void); /* in GDI and Wine, not in WMF manual. */ +char *U_WMRCHORD_set(U_POINT16 Radial1, U_POINT16 Radial2, U_RECT16 rect); +char *U_WMRSETMAPPERFLAGS_set(uint32_t Mode); +char *U_WMREXTTEXTOUT_set(U_POINT16 Dst, int16_t Length, uint16_t Opts, const char *string, int16_t *dx, U_RECT16 rect); +char *U_WMRSETDIBTODEV_set(void); +char *U_WMRSELECTPALETTE_set(uint16_t Palette); +char *U_WMRREALIZEPALETTE_set(void); +char *U_WMRANIMATEPALETTE_set(U_PALETTE *Palette); +char *U_WMRSETPALENTRIES_set(const U_PALETTE *Palette); +char *U_WMRPOLYPOLYGON_set(const uint16_t, const uint16_t *aPolyCounts, const U_POINT16 * points); +char *U_WMRRESIZEPALETTE_set(uint16_t Palette); +char *U_WMR3A_set(void); +char *U_WMR3B_set(void); +char *U_WMR3C_set(void); +char *U_WMR3D_set(void); +char *U_WMR3E_set(void); +char *U_WMR3F_set(void); +char *U_WMRDIBBITBLT_set(U_POINT16 Dst, U_POINT16 cwh, U_POINT16 Src, + uint32_t dwRop3, const U_BITMAPINFO * Bmi, uint32_t cbPx, const char *Px); +char *U_WMRDIBSTRETCHBLT_set(U_POINT16 Dst, U_POINT16 cDst, U_POINT16 Src, + U_POINT16 cSrc, uint32_t dwRop3, const U_BITMAPINFO *Bmi, uint32_t cbPx, const char *Px); +char *U_WMRDIBCREATEPATTERNBRUSH_set(const uint16_t Style, const uint16_t iUsage, + const U_BITMAPINFO *Bmi, uint32_t cbPx, const char *Px, const U_BITMAP16 *Bm16); +char *U_WMRSTRETCHDIB_set(U_POINT16 Dest, U_POINT16 cDest, U_POINT16 Src, U_POINT16 cSrc, + const uint16_t cUsage, uint32_t dwRop3, const U_BITMAPINFO *Bmi, uint32_t cbPx, const char *Px); +char *U_WMR44_set(void); +char *U_WMR45_set(void); +char *U_WMR46_set(void); +char *U_WMR47_set(void); +char *U_WMREXTFLOODFILL_set(uint16_t Mode, U_COLORREF Color, U_POINT16 coord); +char *U_WMR49_set(void); +char *U_WMR4A_set(void); +char *U_WMR4B_set(void); +char *U_WMR4C_set(void); +char *U_WMR4D_set(void); +char *U_WMR4E_set(void); +char *U_WMR4F_set(void); +char *U_WMR50_set(void); +char *U_WMR51_set(void); +char *U_WMRABORTDOC_set(void); +char *U_WMR53_set(void); +char *U_WMR54_set(void); +char *U_WMR55_set(void); +char *U_WMR56_set(void); +char *U_WMR57_set(void); +char *U_WMR58_set(void); +char *U_WMR59_set(void); +char *U_WMR5A_set(void); +char *U_WMR5B_set(void); +char *U_WMR5C_set(void); +char *U_WMR5D_set(void); +char *U_WMR5E_set(void); +char *U_WMR5F_set(void); +char *U_WMR60_set(void); +char *U_WMR61_set(void); +char *U_WMR62_set(void); +char *U_WMR63_set(void); +char *U_WMR64_set(void); +char *U_WMR65_set(void); +char *U_WMR66_set(void); +char *U_WMR67_set(void); +char *U_WMR68_set(void); +char *U_WMR69_set(void); +char *U_WMR6A_set(void); +char *U_WMR6B_set(void); +char *U_WMR6C_set(void); +char *U_WMR6D_set(void); +char *U_WMR6E_set(void); +char *U_WMR6F_set(void); +char *U_WMR70_set(void); +char *U_WMR71_set(void); +char *U_WMR72_set(void); +char *U_WMR73_set(void); +char *U_WMR74_set(void); +char *U_WMR75_set(void); +char *U_WMR76_set(void); +char *U_WMR77_set(void); +char *U_WMR78_set(void); +char *U_WMR79_set(void); +char *U_WMR7A_set(void); +char *U_WMR7B_set(void); +char *U_WMR7C_set(void); +char *U_WMR7D_set(void); +char *U_WMR7E_set(void); +char *U_WMR7F_set(void); +char *U_WMR80_set(void); +char *U_WMR81_set(void); +char *U_WMR82_set(void); +char *U_WMR83_set(void); +char *U_WMR84_set(void); +char *U_WMR85_set(void); +char *U_WMR86_set(void); +char *U_WMR87_set(void); +char *U_WMR88_set(void); +char *U_WMR89_set(void); +char *U_WMR8A_set(void); +char *U_WMR8B_set(void); +char *U_WMR8C_set(void); +char *U_WMR8D_set(void); +char *U_WMR8E_set(void); +char *U_WMR8F_set(void); +char *U_WMR90_set(void); +char *U_WMR91_set(void); +char *U_WMR92_set(void); +char *U_WMR93_set(void); +char *U_WMR94_set(void); +char *U_WMR95_set(void); +char *U_WMR96_set(void); +char *U_WMR97_set(void); +char *U_WMR98_set(void); +char *U_WMR99_set(void); +char *U_WMR9A_set(void); +char *U_WMR9B_set(void); +char *U_WMR9C_set(void); +char *U_WMR9D_set(void); +char *U_WMR9E_set(void); +char *U_WMR9F_set(void); +char *U_WMRA0_set(void); +char *U_WMRA1_set(void); +char *U_WMRA2_set(void); +char *U_WMRA3_set(void); +char *U_WMRA4_set(void); +char *U_WMRA5_set(void); +char *U_WMRA6_set(void); +char *U_WMRA7_set(void); +char *U_WMRA8_set(void); +char *U_WMRA9_set(void); +char *U_WMRAA_set(void); +char *U_WMRAB_set(void); +char *U_WMRAC_set(void); +char *U_WMRAD_set(void); +char *U_WMRAE_set(void); +char *U_WMRAF_set(void); +char *U_WMRB0_set(void); +char *U_WMRB1_set(void); +char *U_WMRB2_set(void); +char *U_WMRB3_set(void); +char *U_WMRB4_set(void); +char *U_WMRB5_set(void); +char *U_WMRB6_set(void); +char *U_WMRB7_set(void); +char *U_WMRB8_set(void); +char *U_WMRB9_set(void); +char *U_WMRBA_set(void); +char *U_WMRBB_set(void); +char *U_WMRBC_set(void); +char *U_WMRBD_set(void); +char *U_WMRBE_set(void); +char *U_WMRBF_set(void); +char *U_WMRC0_set(void); +char *U_WMRC1_set(void); +char *U_WMRC2_set(void); +char *U_WMRC3_set(void); +char *U_WMRC4_set(void); +char *U_WMRC5_set(void); +char *U_WMRC6_set(void); +char *U_WMRC7_set(void); +char *U_WMRC8_set(void); +char *U_WMRC9_set(void); +char *U_WMRCA_set(void); +char *U_WMRCB_set(void); +char *U_WMRCC_set(void); +char *U_WMRCD_set(void); +char *U_WMRCE_set(void); +char *U_WMRCF_set(void); +char *U_WMRD0_set(void); +char *U_WMRD1_set(void); +char *U_WMRD2_set(void); +char *U_WMRD3_set(void); +char *U_WMRD4_set(void); +char *U_WMRD5_set(void); +char *U_WMRD6_set(void); +char *U_WMRD7_set(void); +char *U_WMRD8_set(void); +char *U_WMRD9_set(void); +char *U_WMRDA_set(void); +char *U_WMRDB_set(void); +char *U_WMRDC_set(void); +char *U_WMRDD_set(void); +char *U_WMRDE_set(void); +char *U_WMRDF_set(void); +char *U_WMRE0_set(void); +char *U_WMRE1_set(void); +char *U_WMRE2_set(void); +char *U_WMRE3_set(void); +char *U_WMRE4_set(void); +char *U_WMRE5_set(void); +char *U_WMRE6_set(void); +char *U_WMRE7_set(void); +char *U_WMRE8_set(void); +char *U_WMRE9_set(void); +char *U_WMREA_set(void); +char *U_WMREB_set(void); +char *U_WMREC_set(void); +char *U_WMRED_set(void); +char *U_WMREE_set(void); +char *U_WMREF_set(void); +char *U_WMRDELETEOBJECT_set(uint16_t object); +char *U_WMRF1_set(void); +char *U_WMRF2_set(void); +char *U_WMRF3_set(void); +char *U_WMRF4_set(void); +char *U_WMRF5_set(void); +char *U_WMRF6_set(void); +char *U_WMRCREATEPALETTE_set(U_PALETTE *Palette); +char *U_WMRF8_set(void); +char *U_WMRCREATEPATTERNBRUSH_set(U_BITMAP16 *Bm16, char *Pattern); +char *U_WMRCREATEPENINDIRECT_set(U_PEN pen); +char *U_WMRCREATEFONTINDIRECT_set(U_FONT *font); +char *U_WMRCREATEBRUSHINDIRECT_set(U_WLOGBRUSH brush); +char *U_WMRCREATEBITMAPINDIRECT_set(void); /* in GDI and Wine, not in WMF manual. */ +char *U_WMRCREATEBITMAP_set(void); /* in GDI and Wine, not in WMF manual. */ +char *U_WMRCREATEREGION_set(const U_REGION *region); + +int16_t *dx16_get( int32_t height, uint32_t weight, uint32_t members); +size_t U_WMRRECSAFE_get(const char *contents, const char *blimit); +int wmfheader_get(const char *contents, const char *blimit, U_WMRPLACEABLE *Placeable, U_WMRHEADER *Header); +int wmr_arc_points(U_RECT16 rclBox, U_POINT16 ArcStart, U_POINT16 ArcEnd, + int *f1, int f2, U_PAIRF *center, U_PAIRF *start, U_PAIRF *end, U_PAIRF *size ); +void U_BITMAPINFOHEADER_get(const char *Bmih, uint32_t *Size, int32_t *Width, int32_t *Height, + uint32_t *Planes, uint32_t *BitCount, uint32_t *Compression, uint32_t *SizeImage, + int32_t *XPelsPerMeter, int32_t *YPelsPerMeter, uint32_t *ClrUsed, uint32_t *ClrImportant); +void U_BITMAPCOREHEADER_get(const char *BmiCh, uint32_t *Size, int32_t *Width, int32_t *Height, int32_t *BitCount); +int wget_DIB_params(const char *dib, const char **px, const U_RGBQUAD **ct, uint32_t *numCt, + int32_t *width, int32_t *height, int32_t *colortype, int32_t *invert); +int U_WMREOF_get(const char *contents); +int U_WMRSETBKCOLOR_get(const char *contents, U_COLORREF *Color); +int U_WMRSETBKMODE_get(const char *contents, uint16_t *Mode); +int U_WMRSETMAPMODE_get(const char *contents, uint16_t *Mode); +int U_WMRSETROP2_get(const char *contents, uint16_t *Mode); +int U_WMRSETRELABS_get(const char *contents); +int U_WMRSETPOLYFILLMODE_get(const char *contents, uint16_t *Mode); +int U_WMRSETSTRETCHBLTMODE_get(const char *contents, uint16_t *Mode); +int U_WMRSETTEXTCHAREXTRA_get(const char *contents, uint16_t *Mode); +int U_WMRSETTEXTCOLOR_get(const char *contents, U_COLORREF *Color); +int U_WMRSETTEXTJUSTIFICATION_get(const char *contents, uint16_t *Count, uint16_t *Extra); +int U_WMRSETWINDOWORG_get(const char *contents, U_POINT16 * coord); +int U_WMRSETWINDOWEXT_get(const char *contents, U_POINT16 * extent); +int U_WMRSETVIEWPORTORG_get(const char *contents, U_POINT16 * coord); +int U_WMRSETVIEWPORTEXT_get(const char *contents, U_POINT16 * extent); +int U_WMROFFSETWINDOWORG_get(const char *contents, U_POINT16 * offset); +int U_WMRSCALEWINDOWEXT_get(const char *contents, U_POINT16 * Denom, U_POINT16 * Num); +int U_WMROFFSETVIEWPORTORG_get(const char *contents, U_POINT16 * offset); +int U_WMRSCALEVIEWPORTEXT_get(const char *contents, U_POINT16 * Denom, U_POINT16 * Num); +int U_WMRLINETO_get(const char *contents, U_POINT16 * coord); +int U_WMRMOVETO_get(const char *contents, U_POINT16 * coord); +int U_WMREXCLUDECLIPRECT_get(const char *contents, U_RECT16 * rect); +int U_WMRINTERSECTCLIPRECT_get(const char *contents, U_RECT16 * rect); +int U_WMRARC_get(const char *contents, U_POINT16 * StartArc, U_POINT16 * EndArc, U_RECT16 * rect); +int U_WMRELLIPSE_get(const char *contents, U_RECT16 * rect); +int U_WMRFLOODFILL_get(const char *contents, uint16_t *Mode, U_COLORREF *Color, U_POINT16 * coord); +int U_WMRPIE_get(const char *contents, U_POINT16 * Radial1, U_POINT16 * Radial2, U_RECT16 * rect); +int U_WMRRECTANGLE_get(const char *contents, U_RECT16 * rect); +int U_WMRROUNDRECT_get(const char *contents, int16_t *Width, int16_t *Height, U_RECT16 * rect); +int U_WMRPATBLT_get(const char *contents, U_POINT16 * Dst, U_POINT16 * cwh, uint32_t *dwRop3); +int U_WMRSAVEDC_get(const char *contents); +int U_WMRSETPIXEL_get(const char *contents, U_COLORREF *Color, U_POINT16 * coord); +int U_WMROFFSETCLIPRGN_get(const char *contents, U_POINT16 * offset); +int U_WMRTEXTOUT_get(const char *contents, U_POINT16 * Dst, int16_t *Length, const char **string); +int U_WMRBITBLT_get(const char *contents, U_POINT16 * Dst, U_POINT16 * cwh, U_POINT16 * Src, uint32_t *dwRop3, U_BITMAP16 *Bm16, const char **px); +int U_WMRSTRETCHBLT_get(const char *contents, U_POINT16 * Dst, U_POINT16 * cDst, U_POINT16 * Src, U_POINT16 * cSrc, uint32_t *dwRop3, U_BITMAP16 *Bm16, const char **px); +int U_WMRPOLYGON_get(const char *contents, uint16_t *Length, const char **Data); +int U_WMRPOLYLINE_get(const char *contents, uint16_t *Length, const char **Data); +int U_WMRESCAPE_get(const char *contents, uint16_t *Escape, uint16_t *Length, const char **Data); +int U_WMRRESTOREDC_get(const char *contents, int16_t *DC); +int U_WMRFILLREGION_get(const char *contents, uint16_t *Region, uint16_t *Brush); +int U_WMRFRAMEREGION_get(const char *contents, uint16_t *Region, uint16_t *Brush, int16_t *Height, int16_t *Width); +int U_WMRINVERTREGION_get(const char *contents, uint16_t *Region); +int U_WMRPAINTREGION_get(const char *contents, uint16_t *Region); +int U_WMRSELECTCLIPREGION_get(const char *contents, uint16_t *Region); +int U_WMRSELECTOBJECT_get(const char *contents, uint16_t *Object); +int U_WMRSETTEXTALIGN_get(const char *contents, uint16_t *Mode); +int U_WMRDRAWTEXT_get(void); /* in GDI and Wine, not in WMF manual. */ +int U_WMRCHORD_get(const char *contents, U_POINT16 * Radial1, U_POINT16 * Radial2, U_RECT16 * rect); +int U_WMRSETMAPPERFLAGS_get(const char *contents, uint32_t *Mode); +int U_WMREXTTEXTOUT_get(const char *contents, U_POINT16 * Dst, int16_t *Length, uint16_t *Opts, const char **string, const int16_t **dx, U_RECT16 * rect); +int U_WMRSETDIBTODEV_get(const char *contents, U_POINT16 * Dst, U_POINT16 * cwh, U_POINT16 * Src, uint16_t *cUsage, uint16_t *ScanCount, uint16_t *StartScan, const char **dib); +int U_WMRSELECTPALETTE_get(const char *contents, uint16_t *Palette); +int U_WMRREALIZEPALETTE_get(const char *contents); +int U_WMRANIMATEPALETTE_get(const char *contents, U_PALETTE *Palette, const char **PalEntries); +int U_WMRSETPALENTRIES_get(const char *contents, U_PALETTE *Palette, const char **PalEntries); +int U_WMRPOLYPOLYGON_get(const char *contents, uint16_t *nPolys, const uint16_t **aPolyCounts, const char **Points); +int U_WMRRESIZEPALETTE_get(const char *contents, uint16_t *Palette); +int U_WMR3A_get(void); +int U_WMR3B_get(void); +int U_WMR3C_get(void); +int U_WMR3D_get(void); +int U_WMR3E_get(void); +int U_WMR3F_get(void); +int U_WMRDIBBITBLT_get(const char *contents, U_POINT16 * Dst, U_POINT16 * cwh, U_POINT16 * Src, uint32_t *dwRop3, const char **dib); +int U_WMRDIBSTRETCHBLT_get(const char *contents, U_POINT16 * Dst, U_POINT16 * cDst, U_POINT16 * Src, U_POINT16 * cSrc, uint32_t *dwRop3, const char **dib); +int U_WMRDIBCREATEPATTERNBRUSH_get(const char *contents, uint16_t *Style, uint16_t *cUsage, const char **Bm16, const char **dib); +int U_WMRSTRETCHDIB_get(const char *contents, U_POINT16 * Dst, U_POINT16 * cDst, U_POINT16 * Src, U_POINT16 * cSrc, uint16_t *cUsage, uint32_t *dwRop3, const char **dib); +int U_WMR44_get(void); +int U_WMR45_get(void); +int U_WMR46_get(void); +int U_WMR47_get(void); +int U_WMREXTFLOODFILL_get(const char *contents, uint16_t *Mode, U_COLORREF *Color, U_POINT16 * coord); +int U_WMR49_get(void); +int U_WMR4A_get(void); +int U_WMR4B_get(void); +int U_WMR4C_get(void); +int U_WMR4D_get(void); +int U_WMR4E_get(void); +int U_WMR4F_get(void); +int U_WMR50_get(void); +int U_WMR51_get(void); +int U_WMRABORTDOC_get(void); +int U_WMR53_get(void); +int U_WMR54_get(void); +int U_WMR55_get(void); +int U_WMR56_get(void); +int U_WMR57_get(void); +int U_WMR58_get(void); +int U_WMR59_get(void); +int U_WMR5A_get(void); +int U_WMR5B_get(void); +int U_WMR5C_get(void); +int U_WMR5D_get(void); +int U_WMR5E_get(void); +int U_WMR5F_get(void); +int U_WMR60_get(void); +int U_WMR61_get(void); +int U_WMR62_get(void); +int U_WMR63_get(void); +int U_WMR64_get(void); +int U_WMR65_get(void); +int U_WMR66_get(void); +int U_WMR67_get(void); +int U_WMR68_get(void); +int U_WMR69_get(void); +int U_WMR6A_get(void); +int U_WMR6B_get(void); +int U_WMR6C_get(void); +int U_WMR6D_get(void); +int U_WMR6E_get(void); +int U_WMR6F_get(void); +int U_WMR70_get(void); +int U_WMR71_get(void); +int U_WMR72_get(void); +int U_WMR73_get(void); +int U_WMR74_get(void); +int U_WMR75_get(void); +int U_WMR76_get(void); +int U_WMR77_get(void); +int U_WMR78_get(void); +int U_WMR79_get(void); +int U_WMR7A_get(void); +int U_WMR7B_get(void); +int U_WMR7C_get(void); +int U_WMR7D_get(void); +int U_WMR7E_get(void); +int U_WMR7F_get(void); +int U_WMR80_get(void); +int U_WMR81_get(void); +int U_WMR82_get(void); +int U_WMR83_get(void); +int U_WMR84_get(void); +int U_WMR85_get(void); +int U_WMR86_get(void); +int U_WMR87_get(void); +int U_WMR88_get(void); +int U_WMR89_get(void); +int U_WMR8A_get(void); +int U_WMR8B_get(void); +int U_WMR8C_get(void); +int U_WMR8D_get(void); +int U_WMR8E_get(void); +int U_WMR8F_get(void); +int U_WMR90_get(void); +int U_WMR91_get(void); +int U_WMR92_get(void); +int U_WMR93_get(void); +int U_WMR94_get(void); +int U_WMR95_get(void); +int U_WMR96_get(void); +int U_WMR97_get(void); +int U_WMR98_get(void); +int U_WMR99_get(void); +int U_WMR9A_get(void); +int U_WMR9B_get(void); +int U_WMR9C_get(void); +int U_WMR9D_get(void); +int U_WMR9E_get(void); +int U_WMR9F_get(void); +int U_WMRA0_get(void); +int U_WMRA1_get(void); +int U_WMRA2_get(void); +int U_WMRA3_get(void); +int U_WMRA4_get(void); +int U_WMRA5_get(void); +int U_WMRA6_get(void); +int U_WMRA7_get(void); +int U_WMRA8_get(void); +int U_WMRA9_get(void); +int U_WMRAA_get(void); +int U_WMRAB_get(void); +int U_WMRAC_get(void); +int U_WMRAD_get(void); +int U_WMRAE_get(void); +int U_WMRAF_get(void); +int U_WMRB0_get(void); +int U_WMRB1_get(void); +int U_WMRB2_get(void); +int U_WMRB3_get(void); +int U_WMRB4_get(void); +int U_WMRB5_get(void); +int U_WMRB6_get(void); +int U_WMRB7_get(void); +int U_WMRB8_get(void); +int U_WMRB9_get(void); +int U_WMRBA_get(void); +int U_WMRBB_get(void); +int U_WMRBC_get(void); +int U_WMRBD_get(void); +int U_WMRBE_get(void); +int U_WMRBF_get(void); +int U_WMRC0_get(void); +int U_WMRC1_get(void); +int U_WMRC2_get(void); +int U_WMRC3_get(void); +int U_WMRC4_get(void); +int U_WMRC5_get(void); +int U_WMRC6_get(void); +int U_WMRC7_get(void); +int U_WMRC8_get(void); +int U_WMRC9_get(void); +int U_WMRCA_get(void); +int U_WMRCB_get(void); +int U_WMRCC_get(void); +int U_WMRCD_get(void); +int U_WMRCE_get(void); +int U_WMRCF_get(void); +int U_WMRD0_get(void); +int U_WMRD1_get(void); +int U_WMRD2_get(void); +int U_WMRD3_get(void); +int U_WMRD4_get(void); +int U_WMRD5_get(void); +int U_WMRD6_get(void); +int U_WMRD7_get(void); +int U_WMRD8_get(void); +int U_WMRD9_get(void); +int U_WMRDA_get(void); +int U_WMRDB_get(void); +int U_WMRDC_get(void); +int U_WMRDD_get(void); +int U_WMRDE_get(void); +int U_WMRDF_get(void); +int U_WMRE0_get(void); +int U_WMRE1_get(void); +int U_WMRE2_get(void); +int U_WMRE3_get(void); +int U_WMRE4_get(void); +int U_WMRE5_get(void); +int U_WMRE6_get(void); +int U_WMRE7_get(void); +int U_WMRE8_get(void); +int U_WMRE9_get(void); +int U_WMREA_get(void); +int U_WMREB_get(void); +int U_WMREC_get(void); +int U_WMRED_get(void); +int U_WMREE_get(void); +int U_WMREF_get(void); +int U_WMRDELETEOBJECT_get(const char *contents, uint16_t *Object); +int U_WMRF1_get(void); +int U_WMRF2_get(void); +int U_WMRF3_get(void); +int U_WMRF4_get(void); +int U_WMRF5_get(void); +int U_WMRF6_get(void); +int U_WMRCREATEPALETTE_get(const char *contents, U_PALETTE *Palette, const char **PalEntries); +int U_WMRF8_get(void); +int U_WMRCREATEPATTERNBRUSH_get(const char *contents, U_BITMAP16 *Bm16, int *pasize, const char **Pattern); +int U_WMRCREATEPENINDIRECT_get(const char *contents, U_PEN *pen); +int U_WMRCREATEFONTINDIRECT_get(const char *contents, const char **font); +int U_WMRCREATEBRUSHINDIRECT_get(const char *contents, const char **brush); +int U_WMRCREATEBITMAPINDIRECT_get(void); +int U_WMRCREATEBITMAP_get(void); +int U_WMRCREATEREGION_get(const char *contents, const char **Region); +//! \endcond + + +#ifdef __cplusplus +} +#endif + +#endif /* _UWMF_ */ diff --git a/src/3rdparty/libuemf/uwmf_endian.c b/src/3rdparty/libuemf/uwmf_endian.c new file mode 100644 index 0000000..7a047c2 --- /dev/null +++ b/src/3rdparty/libuemf/uwmf_endian.c @@ -0,0 +1,1774 @@ +/** + @file uwmf_endian.c + + @brief Functions for converting WMF records between Big Endian and Little Endian byte orders. +*/ + +/* +File: uwmf_endian.c +Version: 0.1.5 +Date: 28-MAY-2015 +Author: David Mathog, Biology Division, Caltech +email: mathog@caltech.edu +Copyright: 2015 David Mathog and California Institute of Technology (Caltech) +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdlib.h> +#include <stdio.h> +#include <stddef.h> /* for offsetof() */ +#include <string.h> +#include "uwmf.h" +#include "uwmf_endian.h" + +// hide almost everything in this file from Doxygen +//! \cond +/* Prototypes for functions used here and defined in uemf_endian.c, but which are not supposed +to be used in end user code. */ + +void U_swap2(void *ul, unsigned int count); +void U_swap4(void *ul, unsigned int count); +void bitmapinfo_swap(char *Bmi); + +/* ********************************************************************************************** + These functions Swap standard objects used in the WMR records. + The low level ones do not append EOL. +*********************************************************************************************** */ + +/** + \brief Swap U_BITMAP16 object + \param b U_BITMAP16 object +*/ +void bitmap16_swap( + char *b + ){ + U_swap2(b,4); /* Type, Width, Height, WidthBytes */ + /* Planes and BitsPixel are bytes, so no swap needed */ + /* Bits[] pixel data should already be in order */ +} + +/** + \brief Swap a U_BRUSH object. + \param b U_BRUSH object. + style bColor bHatch + U_BS_SOLID ColorRef Object Not used (bytes present???) + U_BS_NULL ignored ignored (bytes present???). + U_BS_PATTERN ignored Bitmap16 object holding patern + U_BS_DIBPATTERNPT ColorUsage Enum DIB object + U_BS_HATCHED ColorRef Object HatchStyle Enumeration +*/ +void brush_swap( + char *b, + int torev + ){ + int Style; + if(torev){ Style = *(uint16_t *)(b + offsetof(U_BRUSH,Style)); } + U_swap2(b + offsetof(U_BRUSH,Style),1); + if(!torev){ Style = *(uint16_t *)(b + offsetof(U_BRUSH,Style)); } + /* Color is already in the right order */ + switch(Style){ + case U_BS_SOLID: + /* no/ignored data field */ + break; + case U_BS_NULL: + /* no/ignored data field */ + break; + case U_BS_PATTERN: + bitmap16_swap(b + offsetof(U_BRUSH,Data)); + break; + case U_BS_DIBPATTERNPT: + bitmapinfo_swap(b + offsetof(U_BRUSH,Data)); + break; + case U_BS_HATCHED: + /* no/ignored data field */ + break; + } +} + +/** + \brief Swap a U_FONT object from pointer. + \param lf U_FONT object +*/ +void font_swap( + char *f + ){ + U_swap2(f + offsetof(U_FONT,Height),5); /*Height, Width, Escapement, Orientation, Weight */ + /* Other fields are single bytes */ +} + +/** + \brief Swap a pointer to a U_PALETTE object. + \param lp Pointer to a U_PALETTE object. +*/ +void palette_swap( + char *p + ){ + U_swap2(p + offsetof(U_PALETTE,Start),2); /* Start, NumEntries*/ + /* PalEntries[1] is byte ordered, so no need to swap */ +} + +/** + \brief Swap a U_PEN object. + \param p U_PEN object +*/ +void pen_swap( + char *p + ){ + U_swap2(p + offsetof(U_PEN,Style),3); /* Style,Widthw[0],Widthw[1] */ + /* Color already in order */ +} + +/* there are no + void rect16_ltrb_swap() + void rect16_brtl_swap() +because rectangles are swapped using U_swap2 as an array of 4 int16 values. +*/ + + +/** + \brief Swap U_REGION object + \param rect U_REGION object + \param torev + PARTIAL IMPLEMENTATION +*/ +void region_swap( + char *reg, + int torev + ){ + int Size; + if(torev){ Size = *(int16_t *)(reg + offsetof(U_REGION,Size)); } + U_swap2(reg,10); /* ignore1 through sRrect*/ + if(!torev){ Size = *(int16_t *)(reg + offsetof(U_REGION,Size)); } + U_swap2(reg + U_SIZE_REGION, (Size - U_SIZE_REGION)/2); /* aScans */ +} + + +/** + \brief Swap U_BITMAPCOREHEADER object + \param ch U_BITMAPCOREHEADER object +*/ +void bitmapcoreheader_swap( + char *ch + ){ + U_swap4(ch + offsetof(U_BITMAPCOREHEADER,Size_4), 1); /* Size_4, may not be aligned */ + U_swap2(ch + offsetof(U_BITMAPCOREHEADER,Width),4); /* Width, Height, Planes, BitCount, */ +} + +/** LogBrushW Object WMF PDF 2.2.2.10 + \brief Swap a U_WLOGBRUSH object. + \param lb U_WLOGBRUSH object. + + style Color Hatch + U_BS_SOLID ColorRef Object Not used (bytes present???) + U_BS_NULL ignored ignored (bytes present???). + U_BS_PATTERN ignored not used (Action is not strictly defined) + U_BS_DIBPATTERN ignored not used (Action is not strictly defined) + U_BS_DIBPATTERNPT ignored not used (Action is not strictly defined) + U_BS_HATCHED ColorRef Object HatchStyle Enumeration +*/ +void wlogbrush_swap( + char *lb + ){ + U_swap2(lb + offsetof(U_WLOGBRUSH,Style),1); + /* Color is already in order */ + U_swap2(lb + offsetof(U_WLOGBRUSH,Hatch),1); +} + +/** + \brief Swap U_POLYPOLY object from pointer + \param pp PU_POLYPOLY object +*/ +void polypolygon_swap( + char *pp, + int torev + ){ + int i,totPoints; + uint16_t nPolys; + uint16_t *aPolyCounts; + if(torev){ nPolys = *(uint16_t *)(pp + offsetof(U_POLYPOLYGON, nPolys)); } + U_swap2(pp + offsetof(U_POLYPOLYGON, nPolys),1); + if(!torev){ nPolys = *(uint16_t *)(pp + offsetof(U_POLYPOLYGON, nPolys)); } + aPolyCounts = (uint16_t *)(pp + offsetof(U_POLYPOLYGON, aPolyCounts)); + if(torev){ + for(totPoints=0,i=0;i<nPolys; i++){ totPoints += aPolyCounts[i]; } + } + U_swap2(aPolyCounts,nPolys); + if(!torev){ + for(totPoints=0,i=0;i<nPolys; i++){ totPoints += aPolyCounts[i]; } + } + U_swap2(&(aPolyCounts[nPolys]),2*totPoints); /* 2 coords/ point */ +} + +/** + \brief Swap U_SCAN object + \param pp U_SCAN object +*/ +void scan_swap( + char *sc, + int torev + ){ + int count; + if(torev){ count = *(uint16_t *)sc; } + U_swap2(sc,3); /*count, top, bottom */ + if(!torev){ count = *(uint16_t *)sc; } + U_swap2(sc + offsetof(U_SCAN,ScanLines),count); +} + +/** + \brief Swap a summary of a DIB header + A DIB header in an WMF may be either a BitmapCoreHeader or BitmapInfoHeader. + \param dh void pointer to DIB header +*/ +void dibheader_swap( + char *dh, + int torev + ){ + int Size; + memcpy(&Size, dh, 4); /* may not be aligned */ + if(!torev)U_swap4(&Size,1); + if(Size == 0xC){ + bitmapcoreheader_swap(dh); + } + else { + bitmapinfo_swap(dh); + } +} + +/** + \brief Swap WMF header object + \param head uint8_t pointer to header + \returns size of entire header structure + + If the header is preceded by a placeable struture, Swap that as well. +*/ +int wmfheader_swap( + char *contents, + int torev + ){ + uint32_t Key,Size16w; + int size=0; + Key=*(uint32_t *)(contents + offsetof(U_WMRPLACEABLE,Key)); + if(!torev)U_swap4(&Key,1); + if(Key == 0x9AC6CDD7){ + U_swap4(contents + offsetof(U_WMRPLACEABLE,Key ),1); + U_swap2(contents + offsetof(U_WMRPLACEABLE,HWmf ),1); + U_swap2(contents + offsetof(U_WMRPLACEABLE,Dst ),4); + U_swap2(contents + offsetof(U_WMRPLACEABLE,Inch ),1); + U_swap4(contents + offsetof(U_WMRPLACEABLE,Reserved),1); + U_swap2(contents + offsetof(U_WMRPLACEABLE,Checksum),1); + contents += U_SIZE_WMRPLACEABLE; + size += U_SIZE_WMRPLACEABLE; + } + if(torev){ Size16w = *(uint16_t *)(contents + offsetof(U_WMRHEADER,Size16w)); } + U_swap2(contents + offsetof(U_WMRHEADER,Size16w),2);/* Size16w, Version */ + if(!torev){ Size16w = *(uint16_t *)(contents + offsetof(U_WMRHEADER,Size16w)); } + U_swap4(contents + offsetof(U_WMRHEADER,Sizew ),1);/* Sizew */ + U_swap2(contents + offsetof(U_WMRHEADER,nObjects),1);/* nObjects */ + U_swap4(contents + offsetof(U_WMRHEADER,maxSize ),1);/* maxSize */ + U_swap2(contents + offsetof(U_WMRHEADER,nMembers),1);/* nMembers */ + size += 2*Size16w; + return(size); +} + + + +/* ********************************************************************************************** +These functions contain shared code used by various U_WMR*_Swap functions. These should NEVER be called +by end user code and to further that end prototypes are NOT provided and they are hidden from Doxygen. +*********************************************************************************************** */ + +/* Size16 EVERY record type should call this, directly or indirectly*/ +void U_WMRCORE_SIZE16_swap(char *record, int torev){ + UNUSED_PARAMETER(torev); + U_swap4(record, 1); /* Size16_4 is at offset 0 in U_METARECORD */ +} + + +/* Size16, move to data, Single 32bit followed by array of N16 U_POINT16 */ +void U_WMRCORE_U32_N16_swap(char *record, int N16, int torev){ + int off=U_SIZE_METARECORD; + U_WMRCORE_SIZE16_swap(record, torev); + U_swap4(record + off, 1); off+=4; + U_swap2(record + off, N16); +} + +/* Single 16bit nPoints followed by array of nPoints U_POINT16 */ +void U_WMRCORE_U16_N16_swap(char *record, int torev){ + int nPoints; + U_WMRCORE_SIZE16_swap(record, torev); + if(torev){ nPoints = *(uint16_t *)(record + offsetof(U_WMRPOLYGON,nPoints)); } + U_swap2(record + offsetof(U_WMRPOLYGON,nPoints), 1); + if(!torev){ nPoints = *(uint16_t *)(record + offsetof(U_WMRPOLYGON,nPoints)); } + U_swap2(record + offsetof(U_WMRPOLYGON,aPoints), 2*nPoints); +} + +/* all records that specify palette objects */ +void U_WMRCORE_PALETTE_swap(char *record, int torev){ + UNUSED_PARAMETER(torev); + U_WMRCORE_SIZE16_swap(record, torev); + palette_swap(record + offsetof(U_WMRANIMATEPALETTE,Palette)); +} + +/* all records that have N int16 values, unconditionally swapped */ +void U_WMRCORE_N16_swap(char *record, int N16, int torev){ + U_WMRCORE_SIZE16_swap(record, torev); + U_swap2(record+U_SIZE_METARECORD, N16); +} + + +/* like floodfill */ +void U_WMRCORE_U16_CR_2U16_swap(char *record, int torev){ + int off = U_SIZE_METARECORD; + U_WMRCORE_SIZE16_swap(record, torev); + U_swap2(record+off, 1); off += 2 + sizeof(U_COLORREF); + U_swap2(record+off, 2); +} + +/* ********************************************************************************************** +These are the core WMR functions, each creates a particular type of record. +All return these records via a char* pointer, which is NULL if the call failed. +They are listed in order by the corresponding U_EMR_* index number. +*********************************************************************************************** */ + +/** + \brief Swap a pointer to a U_WMR_whatever record which has not been implemented. + \param name name of this type of record + \param contents pointer to a buffer holding all EMR records + \param recnum number of this record in contents + \param off offset to this record in contents +*/ +void U_WMRNOTIMPLEMENTED_swap(char *record, int torev){ + U_WMRCORE_SIZE16_swap(record, torev); +} + +void U_WMREOF_swap(char *record, int torev){ + U_WMRCORE_SIZE16_swap(record, torev); +} + +void U_WMRSETBKCOLOR_swap(char *record, int torev){ + U_WMRCORE_SIZE16_swap(record, torev); +} + +void U_WMRSETBKMODE_swap(char *record, int torev){ + U_WMRCORE_N16_swap(record,1,torev); +} + +void U_WMRSETMAPMODE_swap(char *record, int torev){ + U_WMRCORE_N16_swap(record,1,torev); +} + +void U_WMRSETROP2_swap(char *record, int torev){ + U_WMRCORE_N16_swap(record,1,torev); +} + +void U_WMRSETRELABS_swap(char *record, int torev){ + U_WMRCORE_SIZE16_swap(record, torev); +} + +void U_WMRSETPOLYFILLMODE_swap(char *record, int torev){ + U_WMRCORE_N16_swap(record,1,torev); +} + +void U_WMRSETSTRETCHBLTMODE_swap(char *record, int torev){ + U_WMRCORE_N16_swap(record,1,torev); +} + +void U_WMRSETTEXTCHAREXTRA_swap(char *record, int torev){ + U_WMRCORE_N16_swap(record,1,torev); +} + +void U_WMRSETTEXTCOLOR_swap(char *record, int torev){ + U_WMRCORE_SIZE16_swap(record, torev); +} + +void U_WMRSETTEXTJUSTIFICATION_swap(char *record, int torev){ + U_WMRCORE_N16_swap(record,2,torev); +} + +void U_WMRSETWINDOWORG_swap(char *record, int torev){ + U_WMRCORE_N16_swap(record,2,torev); +} + +void U_WMRSETWINDOWEXT_swap(char *record, int torev){ + U_WMRCORE_N16_swap(record,2,torev); +} + +void U_WMRSETVIEWPORTORG_swap(char *record, int torev){ + U_WMRCORE_N16_swap(record,2,torev); +} + +void U_WMRSETVIEWPORTEXT_swap(char *record, int torev){ + U_WMRCORE_N16_swap(record,2,torev); +} + +void U_WMROFFSETWINDOWORG_swap(char *record, int torev){ + U_WMRCORE_N16_swap(record,2,torev); +} + +void U_WMRSCALEWINDOWEXT_swap(char *record, int torev){ + U_WMRCORE_N16_swap(record,4,torev); +} + +void U_WMROFFSETVIEWPORTORG_swap(char *record, int torev){ + U_WMRCORE_N16_swap(record,2,torev); +} + +void U_WMRSCALEVIEWPORTEXT_swap(char *record, int torev){ + U_WMRCORE_N16_swap(record,4,torev); +} + +void U_WMRLINETO_swap(char *record, int torev){ + U_WMRCORE_N16_swap(record,2,torev); +} + +void U_WMRMOVETO_swap(char *record, int torev){ + U_WMRCORE_N16_swap(record,2,torev); +} + +void U_WMREXCLUDECLIPRECT_swap(char *record, int torev){ + U_WMRCORE_N16_swap(record,4,torev); +} + +void U_WMRINTERSECTCLIPRECT_swap(char *record, int torev){ + U_WMRCORE_N16_swap(record,4,torev); +} + +void U_WMRARC_swap(char *record, int torev){ + U_WMRCORE_N16_swap(record, 8, torev); +} + +void U_WMRELLIPSE_swap(char *record, int torev){ + U_WMRCORE_N16_swap(record,4,torev); +} + +void U_WMRFLOODFILL_swap(char *record, int torev){ + U_WMRCORE_U16_CR_2U16_swap(record, torev); +} + +void U_WMRPIE_swap(char *record, int torev){ + U_WMRCORE_N16_swap(record, 8, torev); +} + +void U_WMRRECTANGLE_swap(char *record, int torev){ + U_WMRCORE_N16_swap(record,4,torev); +} + +void U_WMRROUNDRECT_swap(char *record, int torev){ + U_WMRCORE_N16_swap(record,6,torev); +} + +void U_WMRPATBLT_swap(char *record, int torev){ + U_WMRCORE_U32_N16_swap(record,4,torev); +} + +void U_WMRSAVEDC_swap(char *record, int torev){ + U_WMRCORE_SIZE16_swap(record, torev); +} + +void U_WMRSETPIXEL_swap(char *record, int torev){ + int off = U_SIZE_METARECORD + sizeof(U_COLORREF); + U_WMRCORE_SIZE16_swap(record, torev); + U_swap2(record+off, 2); +} + +void U_WMROFFSETCLIPRGN_swap(char *record, int torev){ + U_WMRCORE_N16_swap(record,2,torev); +} + +void U_WMRTEXTOUT_swap(char *record, int torev){ + int L2; + if(torev){ L2 = *(int16_t *)(record + U_SIZE_METARECORD); } /* Length field */ + U_WMRCORE_N16_swap(record,1,torev); /* Length */ + if(!torev){ L2 = *(int16_t *)(record + U_SIZE_METARECORD); } /* Length field */ + /* string is in bytes, do not swap that */ + U_swap2(record + U_SIZE_WMRTEXTOUT + L2, 2); /* y,x */ +} + +void U_WMRBITBLT_swap(char *record, int torev){ + uint32_t Size16; + uint8_t xb; + memcpy(&Size16, record + offsetof(U_METARECORD,Size16_4), 4); + if(!torev)U_swap4(&Size16,1); + xb = *(uint8_t *)(record + offsetof(U_METARECORD,xb)); + if(U_TEST_NOPX2(Size16,xb)){ /* no bitmap */ + U_WMRCORE_U32_N16_swap(record,7,torev); + } + else { /* yes bitmap */ + U_WMRCORE_U32_N16_swap(record,6,torev); + bitmap16_swap(record + offsetof(U_WMRBITBLT_PX,bitmap)); + } +} + +void U_WMRSTRETCHBLT_swap(char *record, int torev){ + uint32_t Size16; + uint8_t xb; + memcpy(&Size16, record + offsetof(U_METARECORD,Size16_4), 4); + if(!torev)U_swap4(&Size16,1); + xb = *(uint8_t *)(record + offsetof(U_METARECORD,xb)); + if(U_TEST_NOPX2(Size16,xb)){ /* no bitmap */ + U_WMRCORE_U32_N16_swap(record,9,torev); + } + else { /* yes bitmap */ + U_WMRCORE_U32_N16_swap(record,8,torev); + bitmap16_swap(record + offsetof(U_WMRSTRETCHBLT_PX,bitmap)); + } +} + +void U_WMRPOLYGON_swap(char *record, int torev){ + U_WMRCORE_U16_N16_swap(record, torev); +} + +void U_WMRPOLYLINE_swap(char *record, int torev){ + U_WMRCORE_U16_N16_swap(record, torev); +} + +void U_WMRESCAPE_swap(char *record, int torev){ + uint16_t eFunc; + + if(torev){ eFunc = *(uint16_t *)(record + offsetof(U_WMRESCAPE,eFunc)); } + U_WMRCORE_N16_swap(record,2,torev); + if(!torev){ eFunc = *(uint16_t *)(record + offsetof(U_WMRESCAPE,eFunc)); } + /* Handle data swapping for three types only, anything else end user code must handle */ + if((eFunc == U_MFE_SETLINECAP) || (eFunc == U_MFE_SETLINEJOIN) || (eFunc == U_MFE_SETMITERLIMIT)){ + U_swap4(record + offsetof(U_WMRESCAPE, Data),1); + } +} + +void U_WMRRESTOREDC_swap(char *record, int torev){ + U_WMRCORE_SIZE16_swap(record, torev); +} + +void U_WMRFILLREGION_swap(char *record, int torev){ + U_WMRCORE_N16_swap(record,2,torev); +} + +void U_WMRFRAMEREGION_swap(char *record, int torev){ + U_WMRCORE_N16_swap(record,4,torev); +} + +void U_WMRINVERTREGION_swap(char *record, int torev){ + U_WMRCORE_N16_swap(record,1,torev); +} + +void U_WMRPAINTREGION_swap(char *record, int torev){ + U_WMRCORE_N16_swap(record,1,torev); +} + +void U_WMRSELECTCLIPREGION_swap(char *record, int torev){ + U_WMRCORE_N16_swap(record,1,torev); +} + +void U_WMRSELECTOBJECT_swap(char *record, int torev){ + U_WMRCORE_N16_swap(record,1,torev); +} + +void U_WMRSETTEXTALIGN_swap(char *record, int torev){ + U_WMRCORE_N16_swap(record,1,torev); +} + +void U_WMRDRAWTEXT_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRCHORD_swap(char *record, int torev){ + U_WMRCORE_N16_swap(record, 8, torev); +} + +void U_WMRSETMAPPERFLAGS_swap(char *record, int torev){ + U_WMRCORE_N16_swap(record,1,torev); +} + +void U_WMREXTTEXTOUT_swap(char *record, int torev){ + int off,Length,Len2,Opts; + U_swap4(record + offsetof(U_WMREXTTEXTOUT,Size16_4),1); + if(torev){ + Length = *(int16_t *)( record + offsetof(U_WMREXTTEXTOUT,Length)); + Opts = *(uint16_t *)(record + offsetof(U_WMREXTTEXTOUT,Opts)); + } + U_swap2(record + offsetof(U_WMREXTTEXTOUT,y), 4); /* y,x,Length,Opts*/ + if(!torev){ + Length = *(int16_t *)( record + offsetof(U_WMREXTTEXTOUT,Length)); + Opts = *(uint16_t *)(record + offsetof(U_WMREXTTEXTOUT,Opts)); + } + off = U_SIZE_WMREXTTEXTOUT; + if(Opts & (U_ETO_OPAQUE | U_ETO_CLIPPED)){ + U_swap2(record + off,4); off += 8; + } + Len2 = (Length & 1 ? Length + 1 : Length); + off += Len2; /* no need to swap string, it is a byte array */ + U_swap2(record+off,Length); /* swap the dx array */ +} + +void U_WMRSETDIBTODEV_swap(char *record, int torev){ + U_WMRCORE_N16_swap(record, 9, torev); + dibheader_swap(record + offsetof(U_WMRSETDIBTODEV,dib), torev); +} + +void U_WMRSELECTPALETTE_swap(char *record, int torev){ + U_WMRCORE_N16_swap(record,1,torev); +} + +void U_WMRREALIZEPALETTE_swap(char *record, int torev){ + U_WMRCORE_SIZE16_swap(record, torev); +} + +void U_WMRANIMATEPALETTE_swap(char *record, int torev){ + U_WMRCORE_PALETTE_swap(record, torev); +} + +void U_WMRSETPALENTRIES_swap(char *record, int torev){ + U_WMRCORE_PALETTE_swap(record, torev); +} + +void U_WMRPOLYPOLYGON_swap(char *record, int torev){ + U_WMRCORE_SIZE16_swap(record, torev); + polypolygon_swap(record + offsetof(U_WMRPOLYPOLYGON,PPolygon), torev); +} + +void U_WMRRESIZEPALETTE_swap(char *record, int torev){ + U_WMRCORE_N16_swap(record,1,torev); +} + +void U_WMR3A_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR3B_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR3C_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR3D_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR3E_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR3F_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRDIBBITBLT_swap(char *record, int torev){ + uint32_t Size16; + uint8_t xb; + memcpy(&Size16, record + offsetof(U_METARECORD,Size16_4), 4); + if(!torev)U_swap4(&Size16,1); + xb = *(uint8_t *)(record + offsetof(U_METARECORD,xb)); + if(U_TEST_NOPX2(Size16,xb)){ /* no bitmap */ + U_WMRCORE_U32_N16_swap(record,7,torev); + } + else { /* yes bitmap */ + U_WMRCORE_U32_N16_swap(record,6,torev); + dibheader_swap(record + offsetof(U_WMRDIBBITBLT_PX,dib), torev); + } +} + +void U_WMRDIBSTRETCHBLT_swap(char *record, int torev){ + uint32_t Size16; + uint8_t xb; + memcpy(&Size16, record + offsetof(U_METARECORD,Size16_4), 4); + if(!torev)U_swap4(&Size16,1); + xb = *(uint8_t *)(record + offsetof(U_METARECORD,xb)); + if(U_TEST_NOPX2(Size16,xb)){ /* no bitmap */ + U_WMRCORE_U32_N16_swap(record,9,torev); + } + else { /* yes bitmap */ + U_WMRCORE_U32_N16_swap(record,8,torev); + dibheader_swap(record + offsetof(U_WMRDIBSTRETCHBLT_PX,dib), torev); + } +} + +void U_WMRDIBCREATEPATTERNBRUSH_swap(char *record, int torev){ + int Style; + if(torev){ Style = *(uint16_t *)(record + offsetof(U_WMRDIBCREATEPATTERNBRUSH,Style)); } + U_WMRCORE_N16_swap(record,2,torev); /* Style and cUsage */ + if(!torev){ Style = *(uint16_t *)(record + offsetof(U_WMRDIBCREATEPATTERNBRUSH,Style)); } + if(Style == U_BS_PATTERN){ + bitmap16_swap(record + offsetof(U_WMRDIBCREATEPATTERNBRUSH,Src)); + } + else { + dibheader_swap(record + offsetof(U_WMRDIBCREATEPATTERNBRUSH,Src), torev); + } +} + +void U_WMRSTRETCHDIB_swap(char *record, int torev){ + UNUSED_PARAMETER(torev); + U_WMRCORE_U32_N16_swap(record,9,torev); + dibheader_swap(record + offsetof(U_WMRSTRETCHDIB,dib), torev); +} + +void U_WMR44_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR45_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR46_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR47_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMREXTFLOODFILL_swap(char *record, int torev){ + U_WMRCORE_U16_CR_2U16_swap(record, torev); +} + +void U_WMR49_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR4A_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR4B_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR4C_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR4D_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR4E_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR4F_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR50_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR51_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR52_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR53_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR54_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR55_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR56_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR57_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR58_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR59_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR5A_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR5B_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR5C_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR5D_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR5E_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR5F_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR60_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR61_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR62_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR63_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR64_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR65_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR66_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR67_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR68_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR69_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR6A_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR6B_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR6C_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR6D_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR6E_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR6F_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR70_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR71_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR72_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR73_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR74_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR75_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR76_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR77_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR78_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR79_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR7A_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR7B_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR7C_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR7D_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR7E_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR7F_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR80_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR81_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR82_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR83_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR84_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR85_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR86_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR87_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR88_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR89_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR8A_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR8B_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR8C_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR8D_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR8E_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR8F_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR90_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR91_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR92_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR93_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR94_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR95_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR96_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR97_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR98_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR99_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR9A_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR9B_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR9C_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR9D_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR9E_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMR9F_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRA0_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRA1_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRA2_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRA3_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRA4_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRA5_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRA6_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRA7_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRA8_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRA9_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRAA_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRAB_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRAC_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRAD_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRAE_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRAF_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRB0_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRB1_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRB2_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRB3_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRB4_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRB5_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRB6_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRB7_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRB8_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRB9_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRBA_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRBB_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRBC_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRBD_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRBE_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRBF_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRC0_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRC1_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRC2_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRC3_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRC4_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRC5_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRC6_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRC7_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRC8_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRC9_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRCA_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRCB_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRCC_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRCD_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRCE_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRCF_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRD0_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRD1_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRD2_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRD3_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRD4_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRD5_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRD6_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRD7_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRD8_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRD9_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRDA_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRDB_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRDC_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRDD_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRDE_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRDF_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRE0_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRE1_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRE2_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRE3_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRE4_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRE5_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRE6_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRE7_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRE8_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRE9_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMREA_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMREB_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMREC_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRED_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMREE_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMREF_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRDELETEOBJECT_swap(char *record, int torev){ + U_WMRCORE_N16_swap(record,1,torev); +} + +void U_WMRF1_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRF2_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRF3_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRF4_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRF5_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRF6_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRCREATEPALETTE_swap(char *record, int torev){ + U_WMRCORE_PALETTE_swap(record, torev); +} + +void U_WMRF8_swap(char *record, int torev){ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRCREATEPATTERNBRUSH_swap(char *record, int torev){ + U_WMRCORE_SIZE16_swap(record, torev); + bitmap16_swap(record + U_SIZE_METARECORD); + /* pattern array byte order already correct? */ +} + +void U_WMRCREATEPENINDIRECT_swap(char *record, int torev){ + U_WMRCORE_SIZE16_swap(record, torev); + pen_swap(record + offsetof(U_WMRCREATEPENINDIRECT,pen)); +} + +void U_WMRCREATEFONTINDIRECT_swap(char *record, int torev){ + U_WMRCORE_SIZE16_swap(record, torev); + font_swap(record + offsetof(U_WMRCREATEFONTINDIRECT,font)); +} + +void U_WMRCREATEBRUSHINDIRECT_swap(char *record, int torev){ + U_WMRCORE_SIZE16_swap(record, torev); + wlogbrush_swap(record + offsetof(U_WMRCREATEBRUSHINDIRECT,brush)); +} + +void U_WMRCREATEBITMAPINDIRECT_swap(char *record, int torev){ /* in Wine, not in WMF PDF */ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRCREATEBITMAP_swap(char *record, int torev){ /* in Wine, not in WMF PDF */ + U_WMRNOTIMPLEMENTED_swap(record, torev); +} + +void U_WMRCREATEREGION_swap(char *record, int torev){ + U_WMRCORE_SIZE16_swap(record, torev); + region_swap(record + offsetof(U_WMRCREATEREGION,region), torev); +} +//! \endcond + +/** + \brief Convert an entire WMF in memory from Big Endian to Little Endian (or vice versa). + \return 0 on failure, 1 on success + \param contents pointer to the buffer holding the entire EMF in memory + \param length number of bytes in the buffer + \param torev 1 for native to reversed, 0 for reversed to native + \param onerec 1 if this is operating on a single record instead of an entire file + + Normally this would be called immediately before writing the data to a file + or immediately after reading the data from a file. +*/ +int U_wmf_endian(char *contents, size_t length, int torev, int onerec){ + size_t off=0; + uint32_t OK, Size16; + uint8_t iType; + char *record; + int recnum; + int offset=0; + + record = contents; + if(!onerec){ + off = wmfheader_swap(record,torev); fflush(stdout); /* WMF header is not a normal record, handle it separately */ + record += off; + offset = off; + } + OK = 1; + recnum = 1; /* used when debugging */ + + while(OK){ + if(record > contents + length){ return(0); } // this is most likely a corrupt WMF + + memcpy(&Size16, record + offsetof(U_METARECORD,Size16_4), 4); /* This may not be aligned */ + if(!torev){ U_swap4(&Size16,1); } + iType = *(uint8_t *)(record + offsetof(U_METARECORD,iType)); + +//printf("DEBUG U_wmf_endian before switch record:%d offset:%d type:%d name:%s Size16:%d\n",recnum,offset,iType,U_wmr_names(iType),Size16);fflush(stdout); + switch (iType) + { + case U_WMR_EOF: U_WMREOF_swap(record, torev); OK=0; break; + case U_WMR_SETBKCOLOR: U_WMRSETBKCOLOR_swap(record, torev); break; + case U_WMR_SETBKMODE: U_WMRSETBKMODE_swap(record, torev); break; + case U_WMR_SETMAPMODE: U_WMRSETMAPMODE_swap(record, torev); break; + case U_WMR_SETROP2: U_WMRSETROP2_swap(record, torev); break; + case U_WMR_SETRELABS: U_WMRSETRELABS_swap(record, torev); break; + case U_WMR_SETPOLYFILLMODE: U_WMRSETPOLYFILLMODE_swap(record, torev); break; + case U_WMR_SETSTRETCHBLTMODE: U_WMRSETSTRETCHBLTMODE_swap(record, torev); break; + case U_WMR_SETTEXTCHAREXTRA: U_WMRSETTEXTCHAREXTRA_swap(record, torev); break; + case U_WMR_SETTEXTCOLOR: U_WMRSETTEXTCOLOR_swap(record, torev); break; + case U_WMR_SETTEXTJUSTIFICATION: U_WMRSETTEXTJUSTIFICATION_swap(record, torev); break; + case U_WMR_SETWINDOWORG: U_WMRSETWINDOWORG_swap(record, torev); break; + case U_WMR_SETWINDOWEXT: U_WMRSETWINDOWEXT_swap(record, torev); break; + case U_WMR_SETVIEWPORTORG: U_WMRSETVIEWPORTORG_swap(record, torev); break; + case U_WMR_SETVIEWPORTEXT: U_WMRSETVIEWPORTEXT_swap(record, torev); break; + case U_WMR_OFFSETWINDOWORG: U_WMROFFSETWINDOWORG_swap(record, torev); break; + case U_WMR_SCALEWINDOWEXT: U_WMRSCALEWINDOWEXT_swap(record, torev); break; + case U_WMR_OFFSETVIEWPORTORG: U_WMROFFSETVIEWPORTORG_swap(record, torev); break; + case U_WMR_SCALEVIEWPORTEXT: U_WMRSCALEVIEWPORTEXT_swap(record, torev); break; + case U_WMR_LINETO: U_WMRLINETO_swap(record, torev); break; + case U_WMR_MOVETO: U_WMRMOVETO_swap(record, torev); break; + case U_WMR_EXCLUDECLIPRECT: U_WMREXCLUDECLIPRECT_swap(record, torev); break; + case U_WMR_INTERSECTCLIPRECT: U_WMRINTERSECTCLIPRECT_swap(record, torev); break; + case U_WMR_ARC: U_WMRARC_swap(record, torev); break; + case U_WMR_ELLIPSE: U_WMRELLIPSE_swap(record, torev); break; + case U_WMR_FLOODFILL: U_WMRFLOODFILL_swap(record, torev); break; + case U_WMR_PIE: U_WMRPIE_swap(record, torev); break; + case U_WMR_RECTANGLE: U_WMRRECTANGLE_swap(record, torev); break; + case U_WMR_ROUNDRECT: U_WMRROUNDRECT_swap(record, torev); break; + case U_WMR_PATBLT: U_WMRPATBLT_swap(record, torev); break; + case U_WMR_SAVEDC: U_WMRSAVEDC_swap(record, torev); break; + case U_WMR_SETPIXEL: U_WMRSETPIXEL_swap(record, torev); break; + case U_WMR_OFFSETCLIPRGN: U_WMROFFSETCLIPRGN_swap(record, torev); break; + case U_WMR_TEXTOUT: U_WMRTEXTOUT_swap(record, torev); break; + case U_WMR_BITBLT: U_WMRBITBLT_swap(record, torev); break; + case U_WMR_STRETCHBLT: U_WMRSTRETCHBLT_swap(record, torev); break; + case U_WMR_POLYGON: U_WMRPOLYGON_swap(record, torev); break; + case U_WMR_POLYLINE: U_WMRPOLYLINE_swap(record, torev); break; + case U_WMR_ESCAPE: U_WMRESCAPE_swap(record, torev); break; + case U_WMR_RESTOREDC: U_WMRRESTOREDC_swap(record, torev); break; + case U_WMR_FILLREGION: U_WMRFILLREGION_swap(record, torev); break; + case U_WMR_FRAMEREGION: U_WMRFRAMEREGION_swap(record, torev); break; + case U_WMR_INVERTREGION: U_WMRINVERTREGION_swap(record, torev); break; + case U_WMR_PAINTREGION: U_WMRPAINTREGION_swap(record, torev); break; + case U_WMR_SELECTCLIPREGION: U_WMRSELECTCLIPREGION_swap(record, torev); break; + case U_WMR_SELECTOBJECT: U_WMRSELECTOBJECT_swap(record, torev); break; + case U_WMR_SETTEXTALIGN: U_WMRSETTEXTALIGN_swap(record, torev); break; + case U_WMR_DRAWTEXT: U_WMRDRAWTEXT_swap(record, torev); break; + case U_WMR_CHORD: U_WMRCHORD_swap(record, torev); break; + case U_WMR_SETMAPPERFLAGS: U_WMRSETMAPPERFLAGS_swap(record, torev); break; + case U_WMR_EXTTEXTOUT: U_WMREXTTEXTOUT_swap(record, torev); break; + case U_WMR_SETDIBTODEV: U_WMRSETDIBTODEV_swap(record, torev); break; + case U_WMR_SELECTPALETTE: U_WMRSELECTPALETTE_swap(record, torev); break; + case U_WMR_REALIZEPALETTE: U_WMRREALIZEPALETTE_swap(record, torev); break; + case U_WMR_ANIMATEPALETTE: U_WMRANIMATEPALETTE_swap(record, torev); break; + case U_WMR_SETPALENTRIES: U_WMRSETPALENTRIES_swap(record, torev); break; + case U_WMR_POLYPOLYGON: U_WMRPOLYPOLYGON_swap(record, torev); break; + case U_WMR_RESIZEPALETTE: U_WMRRESIZEPALETTE_swap(record, torev); break; + case U_WMR_3A: U_WMR3A_swap(record, torev); break; + case U_WMR_3B: U_WMR3B_swap(record, torev); break; + case U_WMR_3C: U_WMR3C_swap(record, torev); break; + case U_WMR_3D: U_WMR3D_swap(record, torev); break; + case U_WMR_3E: U_WMR3E_swap(record, torev); break; + case U_WMR_3F: U_WMR3F_swap(record, torev); break; + case U_WMR_DIBBITBLT: U_WMRDIBBITBLT_swap(record, torev); break; + case U_WMR_DIBSTRETCHBLT: U_WMRDIBSTRETCHBLT_swap(record, torev); break; + case U_WMR_DIBCREATEPATTERNBRUSH: U_WMRDIBCREATEPATTERNBRUSH_swap(record, torev); break; + case U_WMR_STRETCHDIB: U_WMRSTRETCHDIB_swap(record, torev); break; + case U_WMR_44: U_WMR44_swap(record, torev); break; + case U_WMR_45: U_WMR45_swap(record, torev); break; + case U_WMR_46: U_WMR46_swap(record, torev); break; + case U_WMR_47: U_WMR47_swap(record, torev); break; + case U_WMR_EXTFLOODFILL: U_WMREXTFLOODFILL_swap(record, torev); break; + case U_WMR_49: U_WMR49_swap(record, torev); break; + case U_WMR_4A: U_WMR4A_swap(record, torev); break; + case U_WMR_4B: U_WMR4B_swap(record, torev); break; + case U_WMR_4C: U_WMR4C_swap(record, torev); break; + case U_WMR_4D: U_WMR4D_swap(record, torev); break; + case U_WMR_4E: U_WMR4E_swap(record, torev); break; + case U_WMR_4F: U_WMR4F_swap(record, torev); break; + case U_WMR_50: U_WMR50_swap(record, torev); break; + case U_WMR_51: U_WMR51_swap(record, torev); break; + case U_WMR_52: U_WMR52_swap(record, torev); break; + case U_WMR_53: U_WMR53_swap(record, torev); break; + case U_WMR_54: U_WMR54_swap(record, torev); break; + case U_WMR_55: U_WMR55_swap(record, torev); break; + case U_WMR_56: U_WMR56_swap(record, torev); break; + case U_WMR_57: U_WMR57_swap(record, torev); break; + case U_WMR_58: U_WMR58_swap(record, torev); break; + case U_WMR_59: U_WMR59_swap(record, torev); break; + case U_WMR_5A: U_WMR5A_swap(record, torev); break; + case U_WMR_5B: U_WMR5B_swap(record, torev); break; + case U_WMR_5C: U_WMR5C_swap(record, torev); break; + case U_WMR_5D: U_WMR5D_swap(record, torev); break; + case U_WMR_5E: U_WMR5E_swap(record, torev); break; + case U_WMR_5F: U_WMR5F_swap(record, torev); break; + case U_WMR_60: U_WMR60_swap(record, torev); break; + case U_WMR_61: U_WMR61_swap(record, torev); break; + case U_WMR_62: U_WMR62_swap(record, torev); break; + case U_WMR_63: U_WMR63_swap(record, torev); break; + case U_WMR_64: U_WMR64_swap(record, torev); break; + case U_WMR_65: U_WMR65_swap(record, torev); break; + case U_WMR_66: U_WMR66_swap(record, torev); break; + case U_WMR_67: U_WMR67_swap(record, torev); break; + case U_WMR_68: U_WMR68_swap(record, torev); break; + case U_WMR_69: U_WMR69_swap(record, torev); break; + case U_WMR_6A: U_WMR6A_swap(record, torev); break; + case U_WMR_6B: U_WMR6B_swap(record, torev); break; + case U_WMR_6C: U_WMR6C_swap(record, torev); break; + case U_WMR_6D: U_WMR6D_swap(record, torev); break; + case U_WMR_6E: U_WMR6E_swap(record, torev); break; + case U_WMR_6F: U_WMR6F_swap(record, torev); break; + case U_WMR_70: U_WMR70_swap(record, torev); break; + case U_WMR_71: U_WMR71_swap(record, torev); break; + case U_WMR_72: U_WMR72_swap(record, torev); break; + case U_WMR_73: U_WMR73_swap(record, torev); break; + case U_WMR_74: U_WMR74_swap(record, torev); break; + case U_WMR_75: U_WMR75_swap(record, torev); break; + case U_WMR_76: U_WMR76_swap(record, torev); break; + case U_WMR_77: U_WMR77_swap(record, torev); break; + case U_WMR_78: U_WMR78_swap(record, torev); break; + case U_WMR_79: U_WMR79_swap(record, torev); break; + case U_WMR_7A: U_WMR7A_swap(record, torev); break; + case U_WMR_7B: U_WMR7B_swap(record, torev); break; + case U_WMR_7C: U_WMR7C_swap(record, torev); break; + case U_WMR_7D: U_WMR7D_swap(record, torev); break; + case U_WMR_7E: U_WMR7E_swap(record, torev); break; + case U_WMR_7F: U_WMR7F_swap(record, torev); break; + case U_WMR_80: U_WMR80_swap(record, torev); break; + case U_WMR_81: U_WMR81_swap(record, torev); break; + case U_WMR_82: U_WMR82_swap(record, torev); break; + case U_WMR_83: U_WMR83_swap(record, torev); break; + case U_WMR_84: U_WMR84_swap(record, torev); break; + case U_WMR_85: U_WMR85_swap(record, torev); break; + case U_WMR_86: U_WMR86_swap(record, torev); break; + case U_WMR_87: U_WMR87_swap(record, torev); break; + case U_WMR_88: U_WMR88_swap(record, torev); break; + case U_WMR_89: U_WMR89_swap(record, torev); break; + case U_WMR_8A: U_WMR8A_swap(record, torev); break; + case U_WMR_8B: U_WMR8B_swap(record, torev); break; + case U_WMR_8C: U_WMR8C_swap(record, torev); break; + case U_WMR_8D: U_WMR8D_swap(record, torev); break; + case U_WMR_8E: U_WMR8E_swap(record, torev); break; + case U_WMR_8F: U_WMR8F_swap(record, torev); break; + case U_WMR_90: U_WMR90_swap(record, torev); break; + case U_WMR_91: U_WMR91_swap(record, torev); break; + case U_WMR_92: U_WMR92_swap(record, torev); break; + case U_WMR_93: U_WMR93_swap(record, torev); break; + case U_WMR_94: U_WMR94_swap(record, torev); break; + case U_WMR_95: U_WMR95_swap(record, torev); break; + case U_WMR_96: U_WMR96_swap(record, torev); break; + case U_WMR_97: U_WMR97_swap(record, torev); break; + case U_WMR_98: U_WMR98_swap(record, torev); break; + case U_WMR_99: U_WMR99_swap(record, torev); break; + case U_WMR_9A: U_WMR9A_swap(record, torev); break; + case U_WMR_9B: U_WMR9B_swap(record, torev); break; + case U_WMR_9C: U_WMR9C_swap(record, torev); break; + case U_WMR_9D: U_WMR9D_swap(record, torev); break; + case U_WMR_9E: U_WMR9E_swap(record, torev); break; + case U_WMR_9F: U_WMR9F_swap(record, torev); break; + case U_WMR_A0: U_WMRA0_swap(record, torev); break; + case U_WMR_A1: U_WMRA1_swap(record, torev); break; + case U_WMR_A2: U_WMRA2_swap(record, torev); break; + case U_WMR_A3: U_WMRA3_swap(record, torev); break; + case U_WMR_A4: U_WMRA4_swap(record, torev); break; + case U_WMR_A5: U_WMRA5_swap(record, torev); break; + case U_WMR_A6: U_WMRA6_swap(record, torev); break; + case U_WMR_A7: U_WMRA7_swap(record, torev); break; + case U_WMR_A8: U_WMRA8_swap(record, torev); break; + case U_WMR_A9: U_WMRA9_swap(record, torev); break; + case U_WMR_AA: U_WMRAA_swap(record, torev); break; + case U_WMR_AB: U_WMRAB_swap(record, torev); break; + case U_WMR_AC: U_WMRAC_swap(record, torev); break; + case U_WMR_AD: U_WMRAD_swap(record, torev); break; + case U_WMR_AE: U_WMRAE_swap(record, torev); break; + case U_WMR_AF: U_WMRAF_swap(record, torev); break; + case U_WMR_B0: U_WMRB0_swap(record, torev); break; + case U_WMR_B1: U_WMRB1_swap(record, torev); break; + case U_WMR_B2: U_WMRB2_swap(record, torev); break; + case U_WMR_B3: U_WMRB3_swap(record, torev); break; + case U_WMR_B4: U_WMRB4_swap(record, torev); break; + case U_WMR_B5: U_WMRB5_swap(record, torev); break; + case U_WMR_B6: U_WMRB6_swap(record, torev); break; + case U_WMR_B7: U_WMRB7_swap(record, torev); break; + case U_WMR_B8: U_WMRB8_swap(record, torev); break; + case U_WMR_B9: U_WMRB9_swap(record, torev); break; + case U_WMR_BA: U_WMRBA_swap(record, torev); break; + case U_WMR_BB: U_WMRBB_swap(record, torev); break; + case U_WMR_BC: U_WMRBC_swap(record, torev); break; + case U_WMR_BD: U_WMRBD_swap(record, torev); break; + case U_WMR_BE: U_WMRBE_swap(record, torev); break; + case U_WMR_BF: U_WMRBF_swap(record, torev); break; + case U_WMR_C0: U_WMRC0_swap(record, torev); break; + case U_WMR_C1: U_WMRC1_swap(record, torev); break; + case U_WMR_C2: U_WMRC2_swap(record, torev); break; + case U_WMR_C3: U_WMRC3_swap(record, torev); break; + case U_WMR_C4: U_WMRC4_swap(record, torev); break; + case U_WMR_C5: U_WMRC5_swap(record, torev); break; + case U_WMR_C6: U_WMRC6_swap(record, torev); break; + case U_WMR_C7: U_WMRC7_swap(record, torev); break; + case U_WMR_C8: U_WMRC8_swap(record, torev); break; + case U_WMR_C9: U_WMRC9_swap(record, torev); break; + case U_WMR_CA: U_WMRCA_swap(record, torev); break; + case U_WMR_CB: U_WMRCB_swap(record, torev); break; + case U_WMR_CC: U_WMRCC_swap(record, torev); break; + case U_WMR_CD: U_WMRCD_swap(record, torev); break; + case U_WMR_CE: U_WMRCE_swap(record, torev); break; + case U_WMR_CF: U_WMRCF_swap(record, torev); break; + case U_WMR_D0: U_WMRD0_swap(record, torev); break; + case U_WMR_D1: U_WMRD1_swap(record, torev); break; + case U_WMR_D2: U_WMRD2_swap(record, torev); break; + case U_WMR_D3: U_WMRD3_swap(record, torev); break; + case U_WMR_D4: U_WMRD4_swap(record, torev); break; + case U_WMR_D5: U_WMRD5_swap(record, torev); break; + case U_WMR_D6: U_WMRD6_swap(record, torev); break; + case U_WMR_D7: U_WMRD7_swap(record, torev); break; + case U_WMR_D8: U_WMRD8_swap(record, torev); break; + case U_WMR_D9: U_WMRD9_swap(record, torev); break; + case U_WMR_DA: U_WMRDA_swap(record, torev); break; + case U_WMR_DB: U_WMRDB_swap(record, torev); break; + case U_WMR_DC: U_WMRDC_swap(record, torev); break; + case U_WMR_DD: U_WMRDD_swap(record, torev); break; + case U_WMR_DE: U_WMRDE_swap(record, torev); break; + case U_WMR_DF: U_WMRDF_swap(record, torev); break; + case U_WMR_E0: U_WMRE0_swap(record, torev); break; + case U_WMR_E1: U_WMRE1_swap(record, torev); break; + case U_WMR_E2: U_WMRE2_swap(record, torev); break; + case U_WMR_E3: U_WMRE3_swap(record, torev); break; + case U_WMR_E4: U_WMRE4_swap(record, torev); break; + case U_WMR_E5: U_WMRE5_swap(record, torev); break; + case U_WMR_E6: U_WMRE6_swap(record, torev); break; + case U_WMR_E7: U_WMRE7_swap(record, torev); break; + case U_WMR_E8: U_WMRE8_swap(record, torev); break; + case U_WMR_E9: U_WMRE9_swap(record, torev); break; + case U_WMR_EA: U_WMREA_swap(record, torev); break; + case U_WMR_EB: U_WMREB_swap(record, torev); break; + case U_WMR_EC: U_WMREC_swap(record, torev); break; + case U_WMR_ED: U_WMRED_swap(record, torev); break; + case U_WMR_EE: U_WMREE_swap(record, torev); break; + case U_WMR_EF: U_WMREF_swap(record, torev); break; + case U_WMR_DELETEOBJECT: U_WMRDELETEOBJECT_swap(record, torev); break; + case U_WMR_F1: U_WMRF1_swap(record, torev); break; + case U_WMR_F2: U_WMRF2_swap(record, torev); break; + case U_WMR_F3: U_WMRF3_swap(record, torev); break; + case U_WMR_F4: U_WMRF4_swap(record, torev); break; + case U_WMR_F5: U_WMRF5_swap(record, torev); break; + case U_WMR_F6: U_WMRF6_swap(record, torev); break; + case U_WMR_CREATEPALETTE: U_WMRCREATEPALETTE_swap(record, torev); break; + case U_WMR_F8: U_WMRF8_swap(record, torev); break; + case U_WMR_CREATEPATTERNBRUSH: U_WMRCREATEPATTERNBRUSH_swap(record, torev); break; + case U_WMR_CREATEPENINDIRECT: U_WMRCREATEPENINDIRECT_swap(record, torev); break; + case U_WMR_CREATEFONTINDIRECT: U_WMRCREATEFONTINDIRECT_swap(record, torev); break; + case U_WMR_CREATEBRUSHINDIRECT: U_WMRCREATEBRUSHINDIRECT_swap(record, torev); break; + case U_WMR_CREATEBITMAPINDIRECT: U_WMRCREATEBITMAPINDIRECT_swap(record, torev); break; + case U_WMR_CREATEBITMAP: U_WMRCREATEBITMAP_swap(record, torev); break; + case U_WMR_CREATEREGION: U_WMRCREATEREGION_swap(record, torev); break; + default: U_WMRNOTIMPLEMENTED_swap(record, torev); break; + } //end of switch + if(onerec)break; + record += 2*Size16; + offset += 2*Size16; + recnum++; + } //end of while + return(1); +} + + +#ifdef __cplusplus +} +#endif diff --git a/src/3rdparty/libuemf/uwmf_endian.h b/src/3rdparty/libuemf/uwmf_endian.h new file mode 100644 index 0000000..6ce7f19 --- /dev/null +++ b/src/3rdparty/libuemf/uwmf_endian.h @@ -0,0 +1,34 @@ +/** + @file uwmf_endian.h + + @brief Prototypes for functions for converting WMF records between Big Endian and Little Endian +*/ + +/* +File: uwmf_endian.h +Version: 0.0.3 +Date: 28-APR-2015 +Author: David Mathog, Biology Division, Caltech +email: mathog@caltech.edu +Copyright: 2015 David Mathog and California Institute of Technology (Caltech) +*/ + +#ifndef _UWMF_ENDIAN_ +#define _UWMF_ENDIAN_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "uemf_endian.h" + +//! \cond +// prototypes +int U_wmf_endian(char *contents, size_t length, int torev, int onerec); +//! \endcond + +#ifdef __cplusplus +} +#endif + +#endif /* _UWMF_ENDIAN_ */ diff --git a/src/3rdparty/libuemf/uwmf_print.c b/src/3rdparty/libuemf/uwmf_print.c new file mode 100644 index 0000000..d6d1b58 --- /dev/null +++ b/src/3rdparty/libuemf/uwmf_print.c @@ -0,0 +1,1635 @@ +/** + @file uwmf_print.c + + @brief Functions for printing WMF records +*/ + +/* +File: uwmf_print.c +Version: 0.0.6 +Date: 21-MAY-2015 +Author: David Mathog, Biology Division, Caltech +email: mathog@caltech.edu +Copyright: 2015 David Mathog and California Institute of Technology (Caltech) +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdlib.h> +#include <stdio.h> +#include <stddef.h> /* for offsetof() macro */ +#include <string.h> +#include "uwmf_print.h" + +//! \cond + +#define UNUSED(x) (void)(x) + +/* ********************************************************************************************** + These functions print standard objects used in the WMR records. + The low level ones do not append EOL. +*********************************************************************************************** */ + +/* many of these are implemented in uemf_print.c and not replicated here */ + + + +/** + \brief Print a U_BRUSH object. + \param b U_BRUSH object. + style bColor bHatch + U_BS_SOLID ColorRef Object Not used (bytes present???) + U_BS_NULL ignored ignored (bytes present???). + U_BS_PATTERN ignored Bitmap16 object holding patern + U_BS_DIBPATTERNPT ColorUsage Enum DIB object + U_BS_HATCHED ColorRef Object HatchStyle Enumeration +*/ +void brush_print( + U_BRUSH b + ){ + uint16_t hatch; + U_COLORREF Color; + switch(b.Style){ + case U_BS_SOLID: + memcpy(&Color, &b.Color, sizeof(U_COLORREF)); + printf("Color:"); colorref_print(Color); + break; + case U_BS_NULL: + printf("Null"); + break; + case U_BS_PATTERN: + printf("Pattern:(not shown)"); + break; + case U_BS_DIBPATTERNPT: + printf("DIBPattern:(not shown)"); + break; + case U_BS_HATCHED: + memcpy(&hatch, b.Data, 2); + printf("Hatch:0x%4.4X ", hatch); + break; + } +} + +/** + \brief Print a U_FONT object from a char *pointer. + The U_FONT struct object may not be properly aligned, but all of the fields within it will + OK for alignment. + \param font U_FONT object (as a char * pointer) +*/ +void font_print( + const char *font + ){ + printf("Height:%d ", *(int16_t *)(font + offsetof(U_FONT,Height ))); + printf("Width:%d ", *(int16_t *)(font + offsetof(U_FONT,Width ))); + printf("Escapement:%d ", *(int16_t *)(font + offsetof(U_FONT,Escapement ))); + printf("Orientation:%d ", *(int16_t *)(font + offsetof(U_FONT,Orientation ))); + printf("Weight:%d ", *(int16_t *)(font + offsetof(U_FONT,Weight ))); + printf("Italic:0x%2.2X ", *(uint8_t *)(font + offsetof(U_FONT,Italic ))); + printf("Underline:0x%2.2X ", *(uint8_t *)(font + offsetof(U_FONT,Underline ))); + printf("StrikeOut:0x%2.2X ", *(uint8_t *)(font + offsetof(U_FONT,StrikeOut ))); + printf("CharSet:0x%2.2X ", *(uint8_t *)(font + offsetof(U_FONT,CharSet ))); + printf("OutPrecision:0x%2.2X ", *(uint8_t *)(font + offsetof(U_FONT,OutPrecision ))); + printf("ClipPrecision:0x%2.2X ", *(uint8_t *)(font + offsetof(U_FONT,ClipPrecision ))); + printf("Quality:0x%2.2X ", *(uint8_t *)(font + offsetof(U_FONT,Quality ))); + printf("PitchAndFamily:0x%2.2X ", *(uint8_t *)(font + offsetof(U_FONT,PitchAndFamily))); + printf("FaceName:%s ", (font + offsetof(U_FONT,FaceName ))); +} + + +/** + \brief Print a U_PLTNTRY object. + \param pny U_PLTNTRY object. +*/ +void pltntry_print( + U_PLTNTRY pny + ){ + printf("Value:%u ", pny.Value); + printf("Red:%u ", pny.Red ); + printf("Green:%u ", pny.Green); + printf("Blue:%u ", pny.Blue ); +} + + +/** + \brief Print a pointer to a U_PALETTE object. + \param p Pointer to a U_PALETTE object + \param PalEntries Array of Palette Entries +*/ +void palette_print( + const U_PALETTE *p, + const char *PalEntries + ){ + int i; + U_PLTNTRY pny; + + printf("Start:%X ", p->Start ); + printf("NumEntries:%u ",p->NumEntries ); + if(p->NumEntries && PalEntries){ + for(i=0; i < p->NumEntries; i++, PalEntries += sizeof(U_PLTNTRY)){ + memcpy(&pny, PalEntries, sizeof(U_PLTNTRY)); + printf("%d:",i); pltntry_print(pny); + } + } +} + +/** + \brief Print a U_PEN object. + \param p U_PEN object + uint16_t Style; //!< PenStyle Enumeration + uint16_t Width; //!< Pen Width in object dimensions + uint16_t unused; //!< unused + union { + U_COLORREF Color; //!< Pen color (NOT aligned on 4n byte boundary!) + uint16_t Colorw[2]; //!< reassemble/store the Color value using these, NOT Color. + }; +*/ +void pen_print( + U_PEN p + ){ + U_COLORREF Color; + printf("Style:0x%8.8X " ,p.Style ); + printf("Width:%u " ,p.Widthw[0] ); + memcpy(&Color, &p.Color, sizeof(U_COLORREF)); + printf("Color"); colorref_print(Color); +} + +/** + \brief Print U_RECT16 object + Prints in order left, top, right, bottom + \param rect U_RECT16 object +*/ +void rect16_ltrb_print( + U_RECT16 rect + ){ + printf("LTRB{%d,%d,%d,%d} ",rect.left,rect.top,rect.right,rect.bottom); +} + +/** + \brief Print U_RECT16 object + Some WMF rects use the order bottom, right, top, left. These are passed in using + the same structure as for a normal U_RECT16 so: + position holds + left bottom + top right + right top + bottom left + This is used by WMR_RECTANGLE and many others. + \param rect U_RECT16 object +*/ +void rect16_brtl_print( + U_RECT16 rect + ){ + printf("BRTL{%d,%d,%d,%d} ",rect.bottom,rect.right,rect.top,rect.left); +} + + + +/** + \brief Print U_REGION object from a char * pointer. + \param region U_REGION object +*/ +void region_print( + const char *region + ){ + U_RECT16 rect16; + printf("Type:%d ", *(uint16_t *)(region + offsetof(U_REGION,Type ))); + printf("Size:%d ", *( int16_t *)(region + offsetof(U_REGION,Size ))); + printf("sCount:%d ",*( int16_t *)(region + offsetof(U_REGION,sCount))); + printf("sMax:%d ", *( int16_t *)(region + offsetof(U_REGION,sMax ))); + memcpy(&rect16, (region + offsetof(U_REGION,sRect )), sizeof(U_RECT16)); + printf("sRect: "); rect16_ltrb_print(rect16); +} + + +/** + \brief Print U_BITMAP16 object + \param b U_BITMAP16 object +*/ +void bitmap16_print( + U_BITMAP16 b + ){ + printf("Type:%d ", b.Type ); + printf("Width:%d ", b.Width ); + printf("Height:%d ", b.Height ); + printf("WidthBytes:%d ", b.WidthBytes); + printf("Planes:%d ", b.Planes ); + printf("BitsPixel:%d ", b.BitsPixel ); + printf("BitsBytes:%d ", (((b.Width * b.BitsPixel + 15) >> 4) << 1) * b.Height ); +} + +/** + \brief Print U_BITMAPCOREHEADER object + \param ch U_BITMAPCOREHEADER object +*/ +void bitmapcoreheader_print( + U_BITMAPCOREHEADER ch + ){ + uint32_t Size; + memcpy(&Size, &(ch.Size_4), 4); /* will be aligned, but is in two pieces */ + printf("Size:%d ", Size); + printf("Width:%d ", ch.Width); + printf("Height:%d ", ch.Height); + printf("Planes:%d ", ch.Planes); + printf("BitCount:%d ", ch.BitCount); +} + +/** LogBrushW Object WMF PDF 2.2.2.10 + \brief Print a U_LOGBRUSHW object. + \param lb U_LOGBRUSHW object. + + style Color Hatch + U_BS_SOLID ColorRef Object Not used (bytes present???) + U_BS_NULL ignored ignored (bytes present???). + U_BS_PATTERN ignored not used (Action is not strictly defined) + U_BS_DIBPATTERN ignored not used (Action is not strictly defined) + U_BS_DIBPATTERNPT ignored not used (Action is not strictly defined) + U_BS_HATCHED ColorRef Object HatchStyle Enumeration +*/ +void wlogbrush_print( + const char *lb + ){ + U_COLORREF Color; + uint16_t Style = *(uint16_t *)(lb + offsetof(U_WLOGBRUSH,Style)); + uint16_t Hatch = *(uint16_t *)(lb + offsetof(U_WLOGBRUSH,Hatch)); + memcpy(&Color, lb + offsetof(U_WLOGBRUSH,Color), sizeof(U_COLORREF)); + printf("Style:0x%4.4X ",Style); + switch(Style){ + case U_BS_SOLID: + printf("Color:"); colorref_print(Color); + break; + case U_BS_NULL: + printf("Null"); + break; + case U_BS_PATTERN: + printf("Pattern:(not implemented)"); + break; + case U_BS_DIBPATTERN: + printf("DIBPattern:(not implemented)"); + break; + case U_BS_DIBPATTERNPT: + printf("DIBPatternPt:(not implemented)"); + break; + case U_BS_HATCHED: + printf("Color:"); colorref_print(Color); + printf("Hatch:0x%4.4X ", Hatch); + break; + } +} + + +/** + \brief Print U_POLYPOLY object from pointer + \param nPolys Number of elements in aPolyCounts + \param aPolyCounts Number of points in each poly (sequential) + \param Points pointer to array of U_POINT16 in memory. Probably not aligned. +*/ +void polypolygon_print( + uint16_t nPolys, + const uint16_t *aPolyCounts, + const char *Points + ){ + int i,j; + U_POINT16 pt; + for(i=0; i<nPolys; i++, aPolyCounts++){ + printf(" Polygon[%d]: ",i); + for(j=0; j < *aPolyCounts; j++, Points += sizeof(U_POINT16)){ + memcpy(&pt, Points, sizeof(U_POINT16)); /* may not be aligned */ + point16_print(pt); + } + } +} + +/** + \brief Print U_SCAN object + \param sc U_SCAN object +*/ +void scan_print( + U_SCAN sc + ){ + printf("Count:%d ", sc.count); + printf("Top:%d ", sc.top); + printf("Bottom:%d ", sc.bottom); + printf("data:(not shown)"); +} + +/** + \brief Print a summary of a DIB header + \param dh void pointer to DIB header + A DIB header in an WMF may be either a BitmapCoreHeader or BitmapInfoHeader. +*/ +void dibheader_print(const char *dh, const char *blimit){ + uint32_t Size; + memcpy(&Size, dh, 4); /* may not be aligned */ + if(Size == 0xC ){ + printf("(BitmapCoreHeader) "); + U_BITMAPCOREHEADER bmch; + memcpy(&bmch, dh, sizeof(U_BITMAPCOREHEADER)); /* may not be aligned */ + bitmapcoreheader_print(bmch); + } + else { + printf(" (BitmapInfoHeader) "); + bitmapinfo_print(dh, blimit); /* may not be aligned, called routine must handle it */ + } +} + +/** + \brief Print WMF header object + \returns size of entire header structure + \param contents pointer to the first byte in the buffer holding the entire WMF file in memory + \param blimit pointer to the byte after the last byte in contents + + If the header is preceded by a placeable struture, print that as well. +*/ +int wmfheader_print( + const char *contents, + const char *blimit + ){ + U_WMRPLACEABLE Placeable; + U_WMRHEADER Header; + int size = wmfheader_get(contents, blimit, &Placeable, &Header); + uint32_t utmp4; + U_RECT16 rect16; + uint32_t Key; + memcpy(&Key, contents + offsetof(U_WMRPLACEABLE,Key), 4); + if(Placeable.Key == 0x9AC6CDD7){ + printf("WMF, Placeable: "); + printf("HWmf:%u ", Placeable.HWmf); + memcpy(&rect16, &(Placeable.Dst), sizeof(U_RECT16)); + printf("Box:"); rect16_ltrb_print(rect16); + printf("Inch:%u ", Placeable.Inch); + printf("Checksum:%d ", Placeable.Checksum); + printf("Calculated_Checksum:%d\n",U_16_checksum((int16_t *)contents,10)); + } + else { + printf("WMF, Not Placeable\n"); + } + printf(" RecType:%d\n", Header.iType); + printf(" 16bit words in record:%d\n", Header.Size16w); + printf(" Version:%d\n", Header.version); + memcpy(&utmp4, &(Header.Sizew),4); + printf(" 16bit words in file:%d\n",utmp4); + printf(" Objects:%d\n", Header.nObjects); + memcpy(&utmp4, &(Header.maxSize),4); + printf(" Largest Record:%d\n", utmp4); + printf(" nMembers:%d\n", Header.nMembers); + + return(size); +} + + + +/* ********************************************************************************************** +These functions contain shared code used by various U_WMR*_print functions. These should NEVER be called +by end user code and to further that end prototypes are NOT provided and they are hidden from Doxygen. +*********************************************************************************************** */ + + +void wcore_points_print(uint16_t nPoints, const char *aPoints){ + int i; + U_POINT16 pt; + printf(" Points: "); + for(i=0;i<nPoints; i++){ + memcpy(&pt, aPoints + i*4, sizeof(U_POINT16)); /* aPoints U_POINT16 structure may not be aligned, so copy it out */ + printf("[%d]:",i); point16_print(pt); + } + printf("\n"); +} + + + +/* ********************************************************************************************** +These are the core WMR functions, each creates a particular type of record. +All return these records via a char* pointer, which is NULL if the call failed. +They are listed in order by the corresponding U_WMR_* index number. +*********************************************************************************************** */ + +/** + \brief Print a pointer to a U_WMR_whatever record which has not been implemented. + \param contents pointer to a buffer holding a WMR record +*/ +void U_WMRNOTIMPLEMENTED_print(const char *contents){ + UNUSED(contents); + printf(" Not Implemented!\n"); +} + +void U_WMREOF_print(const char *contents){ + UNUSED(contents); +} + +void U_WMRSETBKCOLOR_print(const char *contents){ + U_COLORREF Color; + int size = U_WMRSETBKCOLOR_get(contents, &Color); + if(size>0){ + printf(" %-15s ","Color:"); colorref_print(Color); printf("\n"); + } +} + +void U_WMRSETBKMODE_print(const char *contents){ + uint16_t iMode; + int size = U_WMRSETBKMODE_get(contents, &iMode); + if(size>0){ + printf(" %-15s 0x%4.4X\n","iMode:", iMode); + } +} + +void U_WMRSETMAPMODE_print(const char *contents){ + uint16_t iMode; + int size = U_WMRSETMAPMODE_get(contents, &iMode); + if(size>0){ + printf(" %-15s 0x%4.4X\n","iMode:", iMode); + } +} + +void U_WMRSETROP2_print(const char *contents){ + uint16_t iMode; + int size = U_WMRSETROP2_get(contents, &iMode); + if(size>0){ + printf(" %-15s 0x%4.4X\n","iMode:", iMode); + } +} + +void U_WMRSETRELABS_print(const char *contents){ + UNUSED(contents); + /* This record type has only the common 6 bytes, so nothing (else) to print */ +} + +void U_WMRSETPOLYFILLMODE_print(const char *contents){ + uint16_t iMode; + int size = U_WMRSETPOLYFILLMODE_get(contents, &iMode); + if(size>0){ + printf(" %-15s 0x%4.4X\n","iMode:", iMode); + } +} + +void U_WMRSETSTRETCHBLTMODE_print(const char *contents){ + uint16_t iMode; + int size = U_WMRSETSTRETCHBLTMODE_get(contents, &iMode); + if(size>0){ + printf(" %-15s 0x%4.4X\n","iMode:", iMode); + } +} + +void U_WMRSETTEXTCHAREXTRA_print(const char *contents){ + uint16_t iMode; + int size = U_WMRSETTEXTCHAREXTRA_get(contents, &iMode); + if(size>0){ + printf(" %-15s 0x%4.4X\n","iMode:", iMode); + } +} + +void U_WMRSETTEXTCOLOR_print(const char *contents){ + U_COLORREF Color; + int size = U_WMRSETTEXTCOLOR_get(contents, &Color); + if(size>0){ + printf(" %-15s ","Color:"); colorref_print(Color); printf("\n"); + } +} + +void U_WMRSETTEXTJUSTIFICATION_print(const char *contents){ + uint16_t Count; + uint16_t Extra; + int size = U_WMRSETTEXTJUSTIFICATION_get(contents, &Count, &Extra); + if(size){ + printf(" %-15s %d\n","Count", Count); + printf(" %-15s %d\n","Extra", Extra); + } +} + +void U_WMRSETWINDOWORG_print(const char *contents){ + U_POINT16 coord; + int size = U_WMRSETWINDOWORG_get(contents, &coord); + if(size){ + printf(" %-15s {%d,%d}\n","X,Y",coord.x, coord.y); + } +} + +void U_WMRSETWINDOWEXT_print(const char *contents){ + U_POINT16 coord; + int size = U_WMRSETWINDOWEXT_get(contents, &coord); + if(size){ + printf(" %-15s {%d,%d}\n","W,H",coord.x, coord.y); + } +} + +void U_WMRSETVIEWPORTORG_print(const char *contents){ + U_POINT16 coord; + int size = U_WMRSETVIEWPORTORG_get(contents, &coord); + if(size){ + printf(" %-15s {%d,%d}\n","X,Y",coord.x, coord.y); + } +} + +void U_WMRSETVIEWPORTEXT_print(const char *contents){ + U_POINT16 coord; + int size = U_WMRSETVIEWPORTEXT_get(contents, &coord); + if(size){ + printf(" %-15s {%d,%d}\n","W,H",coord.x, coord.y); + } +} + +void U_WMROFFSETWINDOWORG_print(const char *contents){ + U_POINT16 coord; + int size = U_WMROFFSETWINDOWORG_get(contents, &coord); + if(size){ + printf(" %-15s {%d,%d}\n","X,Y",coord.x, coord.y); + } +} + +void U_WMRSCALEWINDOWEXT_print(const char *contents){ + U_POINT16 Denom, Num; + int size = U_WMRSCALEWINDOWEXT_get(contents, &Denom, &Num); + if(size > 0){ + printf(" yDenom:%d\n", Denom.y); + printf(" yNum:%d\n", Num.y ); + printf(" xDenom:%d\n", Denom.x); + printf(" xNum:%d\n", Num.x ); + } +} + +void U_WMROFFSETVIEWPORTORG_print(const char *contents){ + U_POINT16 coord; + int size = U_WMROFFSETVIEWPORTORG_get(contents, &coord); + if(size){ + printf(" %-15s {%d,%d}\n","X,Y",coord.x, coord.y); + } +} + +void U_WMRSCALEVIEWPORTEXT_print(const char *contents){ + U_POINT16 Denom, Num; + int size = U_WMRSCALEVIEWPORTEXT_get(contents, &Denom, &Num); + if(size > 0){ + printf(" yDenom:%d\n", Denom.y); + printf(" yNum:%d\n", Num.y ); + printf(" xDenom:%d\n", Denom.x); + printf(" xNum:%d\n", Num.x ); + } +} + +void U_WMRLINETO_print(const char *contents){ + U_POINT16 coord; + int size = U_WMRLINETO_get(contents, &coord); + if(size){ + printf(" %-15s {%d,%d}\n","X,Y",coord.x, coord.y); + } +} + +void U_WMRMOVETO_print(const char *contents){ + U_POINT16 coord; + int size = U_WMRMOVETO_get(contents, &coord); + if(size > 0){ + printf(" %-15s {%d,%d}\n","X,Y",coord.x, coord.y); + } +} + +void U_WMREXCLUDECLIPRECT_print(const char *contents){ + U_RECT16 rect16; + int size = U_WMREXCLUDECLIPRECT_get(contents, &rect16); + if(size > 0){ + printf(" Rect:"); + rect16_ltrb_print(rect16); + printf("\n"); + } +} + +void U_WMRINTERSECTCLIPRECT_print(const char *contents){ + U_RECT16 rect16; + int size = U_WMRINTERSECTCLIPRECT_get(contents, &rect16); + if(size > 0){ + printf(" Rect:"); + rect16_ltrb_print(rect16); + printf("\n"); + } +} + +void U_WMRARC_print(const char *contents){ + U_POINT16 StartArc, EndArc; + U_RECT16 rect16; + int size = U_WMRARC_get(contents, &StartArc, &EndArc, &rect16); + if(size > 0){ + printf(" yRadial2:%d\n", EndArc.y); + printf(" xRadial2:%d\n", EndArc.x); + printf(" yRadial1:%d\n", StartArc.y); + printf(" xRadial1:%d\n", StartArc.x); + printf(" Rect:"); rect16_ltrb_print(rect16); printf("\n"); + } +} + +void U_WMRELLIPSE_print(const char *contents){ + U_RECT16 rect16; + int size = U_WMRELLIPSE_get(contents, &rect16); + if(size > 0){ + printf(" Rect:"); + rect16_ltrb_print(rect16); + printf("\n"); + } +} + +void U_WMRFLOODFILL_print(const char *contents){ + uint16_t Mode; + U_COLORREF Color; + U_POINT16 coord; + int size = U_WMRFLOODFILL_get(contents, &Mode, &Color, &coord); + if(size > 0){ + printf(" Mode 0x%4.4X\n", Mode); + printf(" Color:"); colorref_print(Color); printf("\n"); + printf(" X,Y {%d,%d}\n", coord.x, coord.y); + } +} + +void U_WMRPIE_print(const char *contents){ + U_POINT16 StartArc, EndArc; + U_RECT16 rect16; + int size = U_WMRPIE_get(contents, &StartArc, &EndArc, &rect16); + if(size > 0){ + printf(" yRadial2:%d\n", EndArc.y); + printf(" xRadial2:%d\n", EndArc.x); + printf(" yRadial1:%d\n", StartArc.y); + printf(" xRadial1:%d\n", StartArc.x); + printf(" Rect:"); rect16_ltrb_print(rect16); printf("\n"); + } +} + +void U_WMRRECTANGLE_print(const char *contents){ + U_RECT16 rect16; + int size = U_WMRRECTANGLE_get(contents, &rect16); + if(size > 0){ + printf(" Rect:"); + rect16_ltrb_print(rect16); + printf("\n"); + } +} + +void U_WMRROUNDRECT_print(const char *contents){ + int16_t Height, Width; + U_RECT16 rect16; + int size = U_WMRROUNDRECT_get(contents, &Width, &Height, &rect16); + if(size > 0){ + printf(" Width:%d\n", Width); + printf(" Height:%d\n", Height); + printf(" Rect:"); + rect16_ltrb_print(rect16); + printf("\n"); + } +} + +void U_WMRPATBLT_print(const char *contents){ + uint32_t dwRop3; + U_POINT16 Dst; + U_POINT16 cwh; + int size = U_WMRPATBLT_get(contents, &Dst, &cwh, &dwRop3); + if(size > 0){ + printf(" Rop3:%8.8X\n", dwRop3 ); + printf(" W,H:%d,%d\n", cwh.x, cwh.y ); + printf(" Dst X,Y:{%d,%d}\n", Dst.x, Dst.y ); + } +} + +void U_WMRSAVEDC_print(const char *contents){ + UNUSED(contents); + /* This record type has only the common 6 bytes, so nothing (else) to print */ +} + +void U_WMRSETPIXEL_print(const char *contents){ + U_COLORREF Color; + U_POINT16 coord; + int size = U_WMRSETPIXEL_get(contents, &Color, &coord); + if(size > 0){ + printf(" Color:"); colorref_print(Color); printf("\n"); + printf(" X,Y {%d,%d}\n", coord.x, coord.y); + } +} + +void U_WMROFFSETCLIPRGN_print(const char *contents){ + U_POINT16 coord; + int size = U_WMROFFSETCLIPRGN_get(contents, &coord); + if(size > 0){ + printf(" %-15s {%d,%d}\n","X,Y",coord.x, coord.y); + } +} + +void U_WMRTEXTOUT_print(const char *contents){ + int16_t Length; + const char *string; + U_POINT16 Dst; + int size = U_WMRTEXTOUT_get(contents, &Dst, &Length, &string); + if(size > 0){ + printf(" X,Y:{%d,%d}\n", Dst.x,Dst.y); + printf(" Length:%d\n", Length); + printf(" String:<%.*s>\n", Length, string); /* May not be null terminated */ + } +} + +void U_WMRBITBLT_print(const char *contents){ + uint32_t dwRop3; + U_POINT16 Dst, Src, cwh; + U_BITMAP16 Bm16; + const char *px; + int size = U_WMRBITBLT_get(contents, &Dst, &cwh, &Src, &dwRop3, &Bm16, &px); + if(size > 0){ + printf(" Rop3:%8.8X\n", dwRop3 ); + printf(" Src X,Y:{%d,%d}\n", Src.x, Src.y); + printf(" W,H:%d,%d\n", cwh.x, cwh.y); + printf(" Dst X,Y:{%d,%d}\n", Dst.x, Dst.y); + if(px){ printf(" Bitmap16:"); bitmap16_print(Bm16); printf("\n"); } + else { printf(" Bitmap16: none\n"); } + } +} + +void U_WMRSTRETCHBLT_print(const char *contents){ + uint32_t dwRop3; + U_POINT16 Dst, Src, cDst, cSrc; + U_BITMAP16 Bm16; + const char *px; + int size = U_WMRSTRETCHBLT_get(contents, &Dst, &cDst, &Src, &cSrc, &dwRop3, &Bm16, &px); + if(size > 0){ + printf(" Rop3:%8.8X\n", dwRop3 ); + printf(" Src W,H:%d,%d\n", cSrc.x, cSrc.y); + printf(" Src X,Y:{%d,%d}\n", Src.x, Src.y ); + printf(" Dst W,H:%d,%d\n", cDst.x, cDst.y); + printf(" Dst X,Y:{%d,%d}\n", Dst.x, Dst.y ); + if(px){ printf(" Bitmap16:"); bitmap16_print(Bm16); printf("\n"); } + else { printf(" Bitmap16: none\n"); } + } +} + +void U_WMRPOLYGON_print(const char *contents){ + uint16_t Length; + const char *Data; + int size = U_WMRPOLYGON_get(contents, &Length, &Data); + if(size > 0){ + wcore_points_print(Length, Data); + } +} + +void U_WMRPOLYLINE_print(const char *contents){ + uint16_t Length; + const char *Data; + int size = U_WMRPOLYLINE_get(contents, &Length, &Data); + if(size > 0){ + wcore_points_print(Length, Data); + } +} + +void U_WMRESCAPE_print(const char *contents){ + uint32_t utmp4; + uint16_t Escape; + uint16_t Length; + const char *Data; + int size = U_WMRESCAPE_get(contents, &Escape, &Length, &Data); + if(size > 0){ + printf(" EscType:%s\n",U_wmr_escnames(Escape)); + printf(" nBytes:%d\n",Length); + if((Escape == U_MFE_SETLINECAP) || (Escape == U_MFE_SETLINEJOIN) || (Escape == U_MFE_SETMITERLIMIT)){ + memcpy(&utmp4, Data ,4); + printf(" Data:%d\n", utmp4); + } + else { + printf(" Data: (not shown)\n"); + } + } +} + +void U_WMRRESTOREDC_print(const char *contents){ + UNUSED(contents); + /* This record type has only the common 6 bytes, so nothing (else) to print */ +} + +void U_WMRFILLREGION_print(const char *contents){ + uint16_t Region; + uint16_t Brush; + int size = U_WMRFILLREGION_get(contents, &Region, &Brush); + if(size > 0){ + printf(" %-15s %d\n","Region", Region); + printf(" %-15s %d\n","Brush", Brush); + } +} + +void U_WMRFRAMEREGION_print(const char *contents){ + uint16_t Region; + uint16_t Brush; + int16_t Height; + int16_t Width; + int size = U_WMRFRAMEREGION_get(contents, &Region, &Brush, &Height, &Width); + if(size > 0){ + printf(" Region:%d\n",Region); + printf(" Brush:%d\n", Brush ); + printf(" Height:%d\n",Height); + printf(" Width:%d\n", Width ); + } +} + +void U_WMRINVERTREGION_print(const char *contents){ + uint16_t Region; + int size = U_WMRSETTEXTALIGN_get(contents, &Region); + if(size > 0){ + printf(" %-15s %d\n","Region:", Region); + } +} + +void U_WMRPAINTREGION_print(const char *contents){ + uint16_t Region; + int size = U_WMRPAINTREGION_get(contents, &Region); + if(size>0){ + printf(" %-15s %d\n","Region:", Region); + } +} + +void U_WMRSELECTCLIPREGION_print(const char *contents){ + uint16_t Region; + int size = U_WMRSELECTCLIPREGION_get(contents, &Region); + if(size>0){ + printf(" %-15s %d\n","Region:", Region); + } +} + +void U_WMRSELECTOBJECT_print(const char *contents){ + uint16_t Object; + int size = U_WMRSELECTOBJECT_get(contents, &Object); + if(size>0){ + printf(" %-15s %d\n","Object:", Object); + } +} + +void U_WMRSETTEXTALIGN_print(const char *contents){ + uint16_t iMode; + int size = U_WMRSETTEXTALIGN_get(contents, &iMode); + if(size>0){ + printf(" %-15s 0x%4.4X\n","iMode:", iMode); + } +} + +#define U_WMRDRAWTEXT_print U_WMRNOTIMPLEMENTED_print + +void U_WMRCHORD_print(const char *contents){ + U_POINT16 StartArc, EndArc; + U_RECT16 rect16; + int size = U_WMRCHORD_get(contents, &StartArc, &EndArc, &rect16); + if(size > 0){ + printf(" yRadial2:%d\n", EndArc.y); + printf(" xRadial2:%d\n", EndArc.x); + printf(" yRadial1:%d\n", StartArc.y); + printf(" xRadial1:%d\n", StartArc.x); + printf(" Rect:"); rect16_ltrb_print(rect16); printf("\n"); + } +} + +void U_WMRSETMAPPERFLAGS_print(const char *contents){ + uint32_t Flags4; + int size = U_WMRSETMAPPERFLAGS_get(contents, &Flags4); + if(size > 0){ + printf(" %-15s 0x%8.8X\n","Flags4:", Flags4); + } +} + +void U_WMREXTTEXTOUT_print(const char *contents){ + U_RECT16 rect16; + U_POINT16 Dst; + int16_t Length; + uint16_t Opts; + const int16_t *dx; + const char *string; + int i; + int size = U_WMREXTTEXTOUT_get(contents, &Dst, &Length, &Opts, &string, &dx, &rect16); + if(size > 0){ + printf(" X,Y:{%d,%d}\n", Dst.x, Dst.y); + printf(" Length:%d\n", Length ); + printf(" Opts:%4.4X\n", Opts ); + if(Opts & (U_ETO_OPAQUE | U_ETO_CLIPPED)){ + printf(" Rect:"); rect16_ltrb_print(rect16); printf("\n"); + } + printf(" String:<%.*s>\n",Length, string); + printf(" Dx:"); + for(i=0; i<Length; i++,dx++){ printf("%d:", *dx ); } + printf("\n"); + } +} + +void U_WMRSETDIBTODEV_print(const char *contents){ + uint16_t cUsage; + uint16_t ScanCount; + uint16_t StartScan; + U_POINT16 Dst; + U_POINT16 cwh; + U_POINT16 Src; + const char *dib; + int size = U_WMRSETDIBTODEV_get(contents, &Dst, &cwh, &Src, &cUsage, &ScanCount, &StartScan, &dib); + if(size > 0){ + printf(" cUsage:%d\n", cUsage ); + printf(" ScanCount:%d\n", ScanCount ); + printf(" StartScan:%d\n", StartScan ); + printf(" Src X,Y:{%d,%d}\n", Src.x, Src.y ); + printf(" W,H:%d,%d\n", cwh.x, cwh.y ); + printf(" Dst X,Y:{%d,%d}\n", Dst.x, Dst.y ); + printf(" DIB:"); dibheader_print(dib, dib+size); printf("\n"); + } +} + +void U_WMRSELECTPALETTE_print(const char *contents){ + uint16_t Palette; + int size = U_WMRSELECTPALETTE_get(contents, &Palette); + if(size > 0){ + printf(" %-15s %d\n","Palette:", Palette); + } +} + +void U_WMRREALIZEPALETTE_print(const char *contents){ + UNUSED(contents); + /* This record type has only the common 6 bytes, so nothing (else) to print */ +} + +void U_WMRANIMATEPALETTE_print(const char *contents){ + U_PALETTE Palette; + const char *PalEntries; + int size = U_WMRANIMATEPALETTE_get(contents, &Palette, &PalEntries); + if(size > 0){ + printf(" Palette:"); palette_print(&Palette, PalEntries); printf("\n"); + + } +} + +void U_WMRSETPALENTRIES_print(const char *contents){ + U_PALETTE Palette; + const char *PalEntries; + int size = U_WMRSETPALENTRIES_get(contents, &Palette, &PalEntries); + if(size > 0){ + printf(" Palette:"); palette_print(&Palette, PalEntries); printf("\n"); + } +} + +void U_WMRPOLYPOLYGON_print(const char *contents){ + uint16_t nPolys; + const uint16_t *aPolyCounts; + const char *Points; + int size = U_WMRPOLYPOLYGON_get(contents, &nPolys, &aPolyCounts, &Points); + if(size > 0){ + printf(" Polygons:"); polypolygon_print(nPolys, aPolyCounts, Points); printf("\n"); + } +} + +void U_WMRRESIZEPALETTE_print(const char *contents){ + uint16_t Palette; + int size = U_WMRSELECTCLIPREGION_get(contents, &Palette); + if(size>0){ + printf(" %-15s %d\n","Palette:", Palette); + } +} + +#define U_WMR3A_print U_WMRNOTIMPLEMENTED_print +#define U_WMR3B_print U_WMRNOTIMPLEMENTED_print +#define U_WMR3C_print U_WMRNOTIMPLEMENTED_print +#define U_WMR3D_print U_WMRNOTIMPLEMENTED_print +#define U_WMR3E_print U_WMRNOTIMPLEMENTED_print +#define U_WMR3F_print U_WMRNOTIMPLEMENTED_print + +void U_WMRDIBBITBLT_print(const char *contents){ + U_POINT16 Dst, cwh, Src; + uint32_t dwRop3; + const char *dib; + int size = U_WMRDIBBITBLT_get(contents, &Dst, &cwh, &Src, &dwRop3, &dib); + if(size > 0){ + printf(" Rop3:%8.8X\n", dwRop3 ); + printf(" Src X,Y:{%d,%d}\n", Src.x, Src.x ); + printf(" W,H:%d,%d\n", cwh.x, cwh.y ); + printf(" Dst X,Y:{%d,%d}\n", Dst.x, Dst.y ); + if(dib){ printf(" DIB:"); dibheader_print(dib, dib+size); printf("\n"); } + else { printf(" DIB: none\n"); } + } +} + +void U_WMRDIBSTRETCHBLT_print(const char *contents){ + U_POINT16 Dst, cDst, Src, cSrc; + uint32_t dwRop3; + const char *dib; + int size = U_WMRDIBSTRETCHBLT_get(contents, &Dst, &cDst, &Src, &cSrc, &dwRop3, &dib); + if(size > 0){ + printf(" Rop3:%8.8X\n", dwRop3 ); + printf(" Src W,H:%d,%d\n", cSrc.x, cSrc.y ); + printf(" Src X,Y:{%d,%d}\n", Src.x, Src.x ); + printf(" Dst W,H:%d,%d\n", cDst.x, cDst.y ); + printf(" Dst X,Y:{%d,%d}\n", Dst.x, Dst.y ); + if(dib){ printf(" DIB:"); dibheader_print(dib, dib+size); printf("\n"); } + else { printf(" DIB: none\n"); } + } +} + +void U_WMRDIBCREATEPATTERNBRUSH_print(const char *contents){ + uint16_t Style, cUsage; + const char *TBm16; + const char *dib; + int size = U_WMRDIBCREATEPATTERNBRUSH_get(contents, &Style, &cUsage, &TBm16, &dib); + if(size > 0){ + U_BITMAP16 Bm16; + printf(" Style:%d\n", Style ); + printf(" cUsage:%d\n", cUsage); + if(TBm16){ + memcpy(&Bm16, TBm16, U_SIZE_BITMAP16); + printf(" Src:Bitmap16:"); bitmap16_print(Bm16); printf("\n"); + } + else { /* from DIB */ + printf(" Src:DIB:"); dibheader_print(dib, dib+size); printf("\n"); + } + } +} + +void U_WMRSTRETCHDIB_print(const char *contents){ + U_POINT16 Dst, cDst, Src, cSrc; + uint32_t dwRop3; + uint16_t cUsage; + const char *dib; + int size = U_WMRSTRETCHDIB_get(contents, &Dst, &cDst, &Src, &cSrc, &cUsage, &dwRop3, &dib); + if(size > 0){ + printf(" Rop3:%8.8X\n", dwRop3 ); + printf(" cUsage:%d\n", cUsage ); + printf(" Src W,H:%d,%d\n", cSrc.x, cSrc.y ); + printf(" Src X,Y:{%d,%d}\n", Src.x, Src.x ); + printf(" Dst W,H:%d,%d\n", cDst.x, cDst.y ); + printf(" Dst X,Y:{%d,%d}\n", Dst.x, Dst.y ); + if(dib){ printf(" DIB:"); dibheader_print(dib, dib+size); printf("\n"); } + else { printf(" DIB: none\n"); } + } +} + +#define U_WMR44_print U_WMRNOTIMPLEMENTED_print +#define U_WMR45_print U_WMRNOTIMPLEMENTED_print +#define U_WMR46_print U_WMRNOTIMPLEMENTED_print +#define U_WMR47_print U_WMRNOTIMPLEMENTED_print + +void U_WMREXTFLOODFILL_print(const char *contents){ + uint16_t Mode; + U_COLORREF Color; + U_POINT16 coord; + int size = U_WMREXTFLOODFILL_get(contents, &Mode, &Color, &coord); + if(size > 0){ + printf(" Mode 0x%4.4X\n", Mode); + printf(" Color:"); colorref_print(Color); printf("\n"); + printf(" X,Y {%d,%d}\n", coord.x, coord.y); + } +} + +#define U_WMR49_print U_WMRNOTIMPLEMENTED_print +#define U_WMR4A_print U_WMRNOTIMPLEMENTED_print +#define U_WMR4B_print U_WMRNOTIMPLEMENTED_print +#define U_WMR4C_print U_WMRNOTIMPLEMENTED_print +#define U_WMR4D_print U_WMRNOTIMPLEMENTED_print +#define U_WMR4E_print U_WMRNOTIMPLEMENTED_print +#define U_WMR4F_print U_WMRNOTIMPLEMENTED_print +#define U_WMR50_print U_WMRNOTIMPLEMENTED_print +#define U_WMR51_print U_WMRNOTIMPLEMENTED_print +#define U_WMR52_print U_WMRNOTIMPLEMENTED_print +#define U_WMR53_print U_WMRNOTIMPLEMENTED_print +#define U_WMR54_print U_WMRNOTIMPLEMENTED_print +#define U_WMR55_print U_WMRNOTIMPLEMENTED_print +#define U_WMR56_print U_WMRNOTIMPLEMENTED_print +#define U_WMR57_print U_WMRNOTIMPLEMENTED_print +#define U_WMR58_print U_WMRNOTIMPLEMENTED_print +#define U_WMR59_print U_WMRNOTIMPLEMENTED_print +#define U_WMR5A_print U_WMRNOTIMPLEMENTED_print +#define U_WMR5B_print U_WMRNOTIMPLEMENTED_print +#define U_WMR5C_print U_WMRNOTIMPLEMENTED_print +#define U_WMR5D_print U_WMRNOTIMPLEMENTED_print +#define U_WMR5E_print U_WMRNOTIMPLEMENTED_print +#define U_WMR5F_print U_WMRNOTIMPLEMENTED_print +#define U_WMR60_print U_WMRNOTIMPLEMENTED_print +#define U_WMR61_print U_WMRNOTIMPLEMENTED_print +#define U_WMR62_print U_WMRNOTIMPLEMENTED_print +#define U_WMR63_print U_WMRNOTIMPLEMENTED_print +#define U_WMR64_print U_WMRNOTIMPLEMENTED_print +#define U_WMR65_print U_WMRNOTIMPLEMENTED_print +#define U_WMR66_print U_WMRNOTIMPLEMENTED_print +#define U_WMR67_print U_WMRNOTIMPLEMENTED_print +#define U_WMR68_print U_WMRNOTIMPLEMENTED_print +#define U_WMR69_print U_WMRNOTIMPLEMENTED_print +#define U_WMR6A_print U_WMRNOTIMPLEMENTED_print +#define U_WMR6B_print U_WMRNOTIMPLEMENTED_print +#define U_WMR6C_print U_WMRNOTIMPLEMENTED_print +#define U_WMR6D_print U_WMRNOTIMPLEMENTED_print +#define U_WMR6E_print U_WMRNOTIMPLEMENTED_print +#define U_WMR6F_print U_WMRNOTIMPLEMENTED_print +#define U_WMR70_print U_WMRNOTIMPLEMENTED_print +#define U_WMR71_print U_WMRNOTIMPLEMENTED_print +#define U_WMR72_print U_WMRNOTIMPLEMENTED_print +#define U_WMR73_print U_WMRNOTIMPLEMENTED_print +#define U_WMR74_print U_WMRNOTIMPLEMENTED_print +#define U_WMR75_print U_WMRNOTIMPLEMENTED_print +#define U_WMR76_print U_WMRNOTIMPLEMENTED_print +#define U_WMR77_print U_WMRNOTIMPLEMENTED_print +#define U_WMR78_print U_WMRNOTIMPLEMENTED_print +#define U_WMR79_print U_WMRNOTIMPLEMENTED_print +#define U_WMR7A_print U_WMRNOTIMPLEMENTED_print +#define U_WMR7B_print U_WMRNOTIMPLEMENTED_print +#define U_WMR7C_print U_WMRNOTIMPLEMENTED_print +#define U_WMR7D_print U_WMRNOTIMPLEMENTED_print +#define U_WMR7E_print U_WMRNOTIMPLEMENTED_print +#define U_WMR7F_print U_WMRNOTIMPLEMENTED_print +#define U_WMR80_print U_WMRNOTIMPLEMENTED_print +#define U_WMR81_print U_WMRNOTIMPLEMENTED_print +#define U_WMR82_print U_WMRNOTIMPLEMENTED_print +#define U_WMR83_print U_WMRNOTIMPLEMENTED_print +#define U_WMR84_print U_WMRNOTIMPLEMENTED_print +#define U_WMR85_print U_WMRNOTIMPLEMENTED_print +#define U_WMR86_print U_WMRNOTIMPLEMENTED_print +#define U_WMR87_print U_WMRNOTIMPLEMENTED_print +#define U_WMR88_print U_WMRNOTIMPLEMENTED_print +#define U_WMR89_print U_WMRNOTIMPLEMENTED_print +#define U_WMR8A_print U_WMRNOTIMPLEMENTED_print +#define U_WMR8B_print U_WMRNOTIMPLEMENTED_print +#define U_WMR8C_print U_WMRNOTIMPLEMENTED_print +#define U_WMR8D_print U_WMRNOTIMPLEMENTED_print +#define U_WMR8E_print U_WMRNOTIMPLEMENTED_print +#define U_WMR8F_print U_WMRNOTIMPLEMENTED_print +#define U_WMR90_print U_WMRNOTIMPLEMENTED_print +#define U_WMR91_print U_WMRNOTIMPLEMENTED_print +#define U_WMR92_print U_WMRNOTIMPLEMENTED_print +#define U_WMR93_print U_WMRNOTIMPLEMENTED_print +#define U_WMR94_print U_WMRNOTIMPLEMENTED_print +#define U_WMR95_print U_WMRNOTIMPLEMENTED_print +#define U_WMR96_print U_WMRNOTIMPLEMENTED_print +#define U_WMR97_print U_WMRNOTIMPLEMENTED_print +#define U_WMR98_print U_WMRNOTIMPLEMENTED_print +#define U_WMR99_print U_WMRNOTIMPLEMENTED_print +#define U_WMR9A_print U_WMRNOTIMPLEMENTED_print +#define U_WMR9B_print U_WMRNOTIMPLEMENTED_print +#define U_WMR9C_print U_WMRNOTIMPLEMENTED_print +#define U_WMR9D_print U_WMRNOTIMPLEMENTED_print +#define U_WMR9E_print U_WMRNOTIMPLEMENTED_print +#define U_WMR9F_print U_WMRNOTIMPLEMENTED_print +#define U_WMRA0_print U_WMRNOTIMPLEMENTED_print +#define U_WMRA1_print U_WMRNOTIMPLEMENTED_print +#define U_WMRA2_print U_WMRNOTIMPLEMENTED_print +#define U_WMRA3_print U_WMRNOTIMPLEMENTED_print +#define U_WMRA4_print U_WMRNOTIMPLEMENTED_print +#define U_WMRA5_print U_WMRNOTIMPLEMENTED_print +#define U_WMRA6_print U_WMRNOTIMPLEMENTED_print +#define U_WMRA7_print U_WMRNOTIMPLEMENTED_print +#define U_WMRA8_print U_WMRNOTIMPLEMENTED_print +#define U_WMRA9_print U_WMRNOTIMPLEMENTED_print +#define U_WMRAA_print U_WMRNOTIMPLEMENTED_print +#define U_WMRAB_print U_WMRNOTIMPLEMENTED_print +#define U_WMRAC_print U_WMRNOTIMPLEMENTED_print +#define U_WMRAD_print U_WMRNOTIMPLEMENTED_print +#define U_WMRAE_print U_WMRNOTIMPLEMENTED_print +#define U_WMRAF_print U_WMRNOTIMPLEMENTED_print +#define U_WMRB0_print U_WMRNOTIMPLEMENTED_print +#define U_WMRB1_print U_WMRNOTIMPLEMENTED_print +#define U_WMRB2_print U_WMRNOTIMPLEMENTED_print +#define U_WMRB3_print U_WMRNOTIMPLEMENTED_print +#define U_WMRB4_print U_WMRNOTIMPLEMENTED_print +#define U_WMRB5_print U_WMRNOTIMPLEMENTED_print +#define U_WMRB6_print U_WMRNOTIMPLEMENTED_print +#define U_WMRB7_print U_WMRNOTIMPLEMENTED_print +#define U_WMRB8_print U_WMRNOTIMPLEMENTED_print +#define U_WMRB9_print U_WMRNOTIMPLEMENTED_print +#define U_WMRBA_print U_WMRNOTIMPLEMENTED_print +#define U_WMRBB_print U_WMRNOTIMPLEMENTED_print +#define U_WMRBC_print U_WMRNOTIMPLEMENTED_print +#define U_WMRBD_print U_WMRNOTIMPLEMENTED_print +#define U_WMRBE_print U_WMRNOTIMPLEMENTED_print +#define U_WMRBF_print U_WMRNOTIMPLEMENTED_print +#define U_WMRC0_print U_WMRNOTIMPLEMENTED_print +#define U_WMRC1_print U_WMRNOTIMPLEMENTED_print +#define U_WMRC2_print U_WMRNOTIMPLEMENTED_print +#define U_WMRC3_print U_WMRNOTIMPLEMENTED_print +#define U_WMRC4_print U_WMRNOTIMPLEMENTED_print +#define U_WMRC5_print U_WMRNOTIMPLEMENTED_print +#define U_WMRC6_print U_WMRNOTIMPLEMENTED_print +#define U_WMRC7_print U_WMRNOTIMPLEMENTED_print +#define U_WMRC8_print U_WMRNOTIMPLEMENTED_print +#define U_WMRC9_print U_WMRNOTIMPLEMENTED_print +#define U_WMRCA_print U_WMRNOTIMPLEMENTED_print +#define U_WMRCB_print U_WMRNOTIMPLEMENTED_print +#define U_WMRCC_print U_WMRNOTIMPLEMENTED_print +#define U_WMRCD_print U_WMRNOTIMPLEMENTED_print +#define U_WMRCE_print U_WMRNOTIMPLEMENTED_print +#define U_WMRCF_print U_WMRNOTIMPLEMENTED_print +#define U_WMRD0_print U_WMRNOTIMPLEMENTED_print +#define U_WMRD1_print U_WMRNOTIMPLEMENTED_print +#define U_WMRD2_print U_WMRNOTIMPLEMENTED_print +#define U_WMRD3_print U_WMRNOTIMPLEMENTED_print +#define U_WMRD4_print U_WMRNOTIMPLEMENTED_print +#define U_WMRD5_print U_WMRNOTIMPLEMENTED_print +#define U_WMRD6_print U_WMRNOTIMPLEMENTED_print +#define U_WMRD7_print U_WMRNOTIMPLEMENTED_print +#define U_WMRD8_print U_WMRNOTIMPLEMENTED_print +#define U_WMRD9_print U_WMRNOTIMPLEMENTED_print +#define U_WMRDA_print U_WMRNOTIMPLEMENTED_print +#define U_WMRDB_print U_WMRNOTIMPLEMENTED_print +#define U_WMRDC_print U_WMRNOTIMPLEMENTED_print +#define U_WMRDD_print U_WMRNOTIMPLEMENTED_print +#define U_WMRDE_print U_WMRNOTIMPLEMENTED_print +#define U_WMRDF_print U_WMRNOTIMPLEMENTED_print +#define U_WMRE0_print U_WMRNOTIMPLEMENTED_print +#define U_WMRE1_print U_WMRNOTIMPLEMENTED_print +#define U_WMRE2_print U_WMRNOTIMPLEMENTED_print +#define U_WMRE3_print U_WMRNOTIMPLEMENTED_print +#define U_WMRE4_print U_WMRNOTIMPLEMENTED_print +#define U_WMRE5_print U_WMRNOTIMPLEMENTED_print +#define U_WMRE6_print U_WMRNOTIMPLEMENTED_print +#define U_WMRE7_print U_WMRNOTIMPLEMENTED_print +#define U_WMRE8_print U_WMRNOTIMPLEMENTED_print +#define U_WMRE9_print U_WMRNOTIMPLEMENTED_print +#define U_WMREA_print U_WMRNOTIMPLEMENTED_print +#define U_WMREB_print U_WMRNOTIMPLEMENTED_print +#define U_WMREC_print U_WMRNOTIMPLEMENTED_print +#define U_WMRED_print U_WMRNOTIMPLEMENTED_print +#define U_WMREE_print U_WMRNOTIMPLEMENTED_print +#define U_WMREF_print U_WMRNOTIMPLEMENTED_print + +void U_WMRDELETEOBJECT_print(const char *contents){ + uint16_t Object; + int size = U_WMRDELETEOBJECT_get(contents, &Object); + if(size>0){ + printf(" %-15s %d\n","Object:", Object); + } +} + +#define U_WMRF1_print U_WMRNOTIMPLEMENTED_print +#define U_WMRF2_print U_WMRNOTIMPLEMENTED_print +#define U_WMRF3_print U_WMRNOTIMPLEMENTED_print +#define U_WMRF4_print U_WMRNOTIMPLEMENTED_print +#define U_WMRF5_print U_WMRNOTIMPLEMENTED_print +#define U_WMRF6_print U_WMRNOTIMPLEMENTED_print + +void U_WMRCREATEPALETTE_print(const char *contents){ + U_PALETTE Palette; + const char *PalEntries; + int size = U_WMRCREATEPALETTE_get(contents, &Palette, &PalEntries); + if(size > 0){ + printf(" Palette:"); palette_print(&Palette, PalEntries); printf("\n"); + + } +} + +#define U_WMRF8_print U_WMRNOTIMPLEMENTED_print + +void U_WMRCREATEPATTERNBRUSH_print(const char *contents){ + U_BITMAP16 Bm16; + int pasize; + int i; + const char *Pattern; + + int size = U_WMRCREATEPATTERNBRUSH_get(contents, &Bm16, &pasize, &Pattern); + if(size > 0){ + /* BM16 is truncated, but bitmap16_print does not get into the part that was omitted */ + printf(" BitMap16: "); bitmap16_print(Bm16); printf("\n"); + printf(" Pattern: "); + for(i=0;i<pasize;i++){ + printf("%2.2X ",Pattern[i]); + } + printf("\n"); + } +} + +void U_WMRCREATEPENINDIRECT_print(const char *contents){ + U_PEN pen; + int size = U_WMRCREATEPENINDIRECT_get(contents, &pen); + if(size > 0){ + printf(" Pen:"); pen_print(pen); printf("\n"); + } +} + +void U_WMRCREATEFONTINDIRECT_print(const char *contents){ + const char *font; /* Note, because of possible struct alignment issue have to use char * to reference the data */ + int size = U_WMRCREATEFONTINDIRECT_get(contents, &font); + if(size > 0){ + printf(" Font:"); + font_print(font); + printf("\n"); + } +} + +void U_WMRCREATEBRUSHINDIRECT_print(const char *contents){ + const char *brush; /* Note, because of possible struct alignment issue have to use char * to reference the data */ + int size = U_WMRCREATEBRUSHINDIRECT_get(contents, &brush); + if(size > 0){ + printf(" Brush:"); + wlogbrush_print(brush); + printf("\n"); + } +} + +void U_WMRCREATEBITMAPINDIRECT_print(const char *contents){ /* in Wine, not in WMF PDF */ + U_WMRNOTIMPLEMENTED_print(contents); +} + +void U_WMRCREATEBITMAP_print(const char *contents){ /* in Wine, not in WMF PDF */ + U_WMRNOTIMPLEMENTED_print(contents); +} + +void U_WMRCREATEREGION_print(const char *contents){ + const char *region; /* Note, because of possible struct alignment issue have to use char * to reference the data */ + int size = U_WMRCREATEBRUSHINDIRECT_get(contents, ®ion); + if(size > 0){ + printf(" Brush:"); + printf(" Region: "); region_print(region); printf("\n"); + } +} + +//! \endcond + +/** + \brief Print any record in a wmf + \returns record length for a normal record, 0 for WMREOF, -1 for a bad record + \param contents pointer to a buffer holding all WMR records + \param blimit one byte past the last WMF record in memory. + \param recnum number of this record in contents + \param off offset to this record in contents +*/ +int U_wmf_onerec_print(const char *contents, const char *blimit, int recnum, size_t off){ + + + uint8_t iType; + size_t size; + + contents += off; + + /* Check that the record size is OK, abort if not. + Pointer math might wrap, so check both sides of the range */ + size = U_WMRRECSAFE_get(contents, blimit); + if(!size)return(-1); + + iType = *(uint8_t *)(contents + offsetof(U_METARECORD, iType ) ); + + uint32_t crc; +#if U_BYTE_SWAP + //This is a Big Endian machine, WMF crc values must be calculated on Little Endian form + char *swapbuf=malloc(size); + if(!swapbuf)return(-1); + memcpy(swapbuf,contents,size); + U_wmf_endian(swapbuf,size,1,1); // BE to LE + crc=lu_crc32(swapbuf,size); + free(swapbuf); +#else + crc=lu_crc32(contents,size); +#endif + printf("%-30srecord:%5d type:%-4u offset:%8d rsize:%8u crc32:%8.8X\n", + U_wmr_names(iType), recnum, iType, (int) off, (int) size, crc); + + switch (iType) + { + case U_WMR_EOF: U_WMREOF_print(contents); size=0; break; + case U_WMR_SETBKCOLOR: U_WMRSETBKCOLOR_print(contents); break; + case U_WMR_SETBKMODE: U_WMRSETBKMODE_print(contents); break; + case U_WMR_SETMAPMODE: U_WMRSETMAPMODE_print(contents); break; + case U_WMR_SETROP2: U_WMRSETROP2_print(contents); break; + case U_WMR_SETRELABS: U_WMRSETRELABS_print(contents); break; + case U_WMR_SETPOLYFILLMODE: U_WMRSETPOLYFILLMODE_print(contents); break; + case U_WMR_SETSTRETCHBLTMODE: U_WMRSETSTRETCHBLTMODE_print(contents); break; + case U_WMR_SETTEXTCHAREXTRA: U_WMRSETTEXTCHAREXTRA_print(contents); break; + case U_WMR_SETTEXTCOLOR: U_WMRSETTEXTCOLOR_print(contents); break; + case U_WMR_SETTEXTJUSTIFICATION: U_WMRSETTEXTJUSTIFICATION_print(contents); break; + case U_WMR_SETWINDOWORG: U_WMRSETWINDOWORG_print(contents); break; + case U_WMR_SETWINDOWEXT: U_WMRSETWINDOWEXT_print(contents); break; + case U_WMR_SETVIEWPORTORG: U_WMRSETVIEWPORTORG_print(contents); break; + case U_WMR_SETVIEWPORTEXT: U_WMRSETVIEWPORTEXT_print(contents); break; + case U_WMR_OFFSETWINDOWORG: U_WMROFFSETWINDOWORG_print(contents); break; + case U_WMR_SCALEWINDOWEXT: U_WMRSCALEWINDOWEXT_print(contents); break; + case U_WMR_OFFSETVIEWPORTORG: U_WMROFFSETVIEWPORTORG_print(contents); break; + case U_WMR_SCALEVIEWPORTEXT: U_WMRSCALEVIEWPORTEXT_print(contents); break; + case U_WMR_LINETO: U_WMRLINETO_print(contents); break; + case U_WMR_MOVETO: U_WMRMOVETO_print(contents); break; + case U_WMR_EXCLUDECLIPRECT: U_WMREXCLUDECLIPRECT_print(contents); break; + case U_WMR_INTERSECTCLIPRECT: U_WMRINTERSECTCLIPRECT_print(contents); break; + case U_WMR_ARC: U_WMRARC_print(contents); break; + case U_WMR_ELLIPSE: U_WMRELLIPSE_print(contents); break; + case U_WMR_FLOODFILL: U_WMRFLOODFILL_print(contents); break; + case U_WMR_PIE: U_WMRPIE_print(contents); break; + case U_WMR_RECTANGLE: U_WMRRECTANGLE_print(contents); break; + case U_WMR_ROUNDRECT: U_WMRROUNDRECT_print(contents); break; + case U_WMR_PATBLT: U_WMRPATBLT_print(contents); break; + case U_WMR_SAVEDC: U_WMRSAVEDC_print(contents); break; + case U_WMR_SETPIXEL: U_WMRSETPIXEL_print(contents); break; + case U_WMR_OFFSETCLIPRGN: U_WMROFFSETCLIPRGN_print(contents); break; + case U_WMR_TEXTOUT: U_WMRTEXTOUT_print(contents); break; + case U_WMR_BITBLT: U_WMRBITBLT_print(contents); break; + case U_WMR_STRETCHBLT: U_WMRSTRETCHBLT_print(contents); break; + case U_WMR_POLYGON: U_WMRPOLYGON_print(contents); break; + case U_WMR_POLYLINE: U_WMRPOLYLINE_print(contents); break; + case U_WMR_ESCAPE: U_WMRESCAPE_print(contents); break; + case U_WMR_RESTOREDC: U_WMRRESTOREDC_print(contents); break; + case U_WMR_FILLREGION: U_WMRFILLREGION_print(contents); break; + case U_WMR_FRAMEREGION: U_WMRFRAMEREGION_print(contents); break; + case U_WMR_INVERTREGION: U_WMRINVERTREGION_print(contents); break; + case U_WMR_PAINTREGION: U_WMRPAINTREGION_print(contents); break; + case U_WMR_SELECTCLIPREGION: U_WMRSELECTCLIPREGION_print(contents); break; + case U_WMR_SELECTOBJECT: U_WMRSELECTOBJECT_print(contents); break; + case U_WMR_SETTEXTALIGN: U_WMRSETTEXTALIGN_print(contents); break; + case U_WMR_DRAWTEXT: U_WMRDRAWTEXT_print(contents); break; + case U_WMR_CHORD: U_WMRCHORD_print(contents); break; + case U_WMR_SETMAPPERFLAGS: U_WMRSETMAPPERFLAGS_print(contents); break; + case U_WMR_EXTTEXTOUT: U_WMREXTTEXTOUT_print(contents); break; + case U_WMR_SETDIBTODEV: U_WMRSETDIBTODEV_print(contents); break; + case U_WMR_SELECTPALETTE: U_WMRSELECTPALETTE_print(contents); break; + case U_WMR_REALIZEPALETTE: U_WMRREALIZEPALETTE_print(contents); break; + case U_WMR_ANIMATEPALETTE: U_WMRANIMATEPALETTE_print(contents); break; + case U_WMR_SETPALENTRIES: U_WMRSETPALENTRIES_print(contents); break; + case U_WMR_POLYPOLYGON: U_WMRPOLYPOLYGON_print(contents); break; + case U_WMR_RESIZEPALETTE: U_WMRRESIZEPALETTE_print(contents); break; + case U_WMR_3A: U_WMR3A_print(contents); break; + case U_WMR_3B: U_WMR3B_print(contents); break; + case U_WMR_3C: U_WMR3C_print(contents); break; + case U_WMR_3D: U_WMR3D_print(contents); break; + case U_WMR_3E: U_WMR3E_print(contents); break; + case U_WMR_3F: U_WMR3F_print(contents); break; + case U_WMR_DIBBITBLT: U_WMRDIBBITBLT_print(contents); break; + case U_WMR_DIBSTRETCHBLT: U_WMRDIBSTRETCHBLT_print(contents); break; + case U_WMR_DIBCREATEPATTERNBRUSH: U_WMRDIBCREATEPATTERNBRUSH_print(contents); break; + case U_WMR_STRETCHDIB: U_WMRSTRETCHDIB_print(contents); break; + case U_WMR_44: U_WMR44_print(contents); break; + case U_WMR_45: U_WMR45_print(contents); break; + case U_WMR_46: U_WMR46_print(contents); break; + case U_WMR_47: U_WMR47_print(contents); break; + case U_WMR_EXTFLOODFILL: U_WMREXTFLOODFILL_print(contents); break; + case U_WMR_49: U_WMR49_print(contents); break; + case U_WMR_4A: U_WMR4A_print(contents); break; + case U_WMR_4B: U_WMR4B_print(contents); break; + case U_WMR_4C: U_WMR4C_print(contents); break; + case U_WMR_4D: U_WMR4D_print(contents); break; + case U_WMR_4E: U_WMR4E_print(contents); break; + case U_WMR_4F: U_WMR4F_print(contents); break; + case U_WMR_50: U_WMR50_print(contents); break; + case U_WMR_51: U_WMR51_print(contents); break; + case U_WMR_52: U_WMR52_print(contents); break; + case U_WMR_53: U_WMR53_print(contents); break; + case U_WMR_54: U_WMR54_print(contents); break; + case U_WMR_55: U_WMR55_print(contents); break; + case U_WMR_56: U_WMR56_print(contents); break; + case U_WMR_57: U_WMR57_print(contents); break; + case U_WMR_58: U_WMR58_print(contents); break; + case U_WMR_59: U_WMR59_print(contents); break; + case U_WMR_5A: U_WMR5A_print(contents); break; + case U_WMR_5B: U_WMR5B_print(contents); break; + case U_WMR_5C: U_WMR5C_print(contents); break; + case U_WMR_5D: U_WMR5D_print(contents); break; + case U_WMR_5E: U_WMR5E_print(contents); break; + case U_WMR_5F: U_WMR5F_print(contents); break; + case U_WMR_60: U_WMR60_print(contents); break; + case U_WMR_61: U_WMR61_print(contents); break; + case U_WMR_62: U_WMR62_print(contents); break; + case U_WMR_63: U_WMR63_print(contents); break; + case U_WMR_64: U_WMR64_print(contents); break; + case U_WMR_65: U_WMR65_print(contents); break; + case U_WMR_66: U_WMR66_print(contents); break; + case U_WMR_67: U_WMR67_print(contents); break; + case U_WMR_68: U_WMR68_print(contents); break; + case U_WMR_69: U_WMR69_print(contents); break; + case U_WMR_6A: U_WMR6A_print(contents); break; + case U_WMR_6B: U_WMR6B_print(contents); break; + case U_WMR_6C: U_WMR6C_print(contents); break; + case U_WMR_6D: U_WMR6D_print(contents); break; + case U_WMR_6E: U_WMR6E_print(contents); break; + case U_WMR_6F: U_WMR6F_print(contents); break; + case U_WMR_70: U_WMR70_print(contents); break; + case U_WMR_71: U_WMR71_print(contents); break; + case U_WMR_72: U_WMR72_print(contents); break; + case U_WMR_73: U_WMR73_print(contents); break; + case U_WMR_74: U_WMR74_print(contents); break; + case U_WMR_75: U_WMR75_print(contents); break; + case U_WMR_76: U_WMR76_print(contents); break; + case U_WMR_77: U_WMR77_print(contents); break; + case U_WMR_78: U_WMR78_print(contents); break; + case U_WMR_79: U_WMR79_print(contents); break; + case U_WMR_7A: U_WMR7A_print(contents); break; + case U_WMR_7B: U_WMR7B_print(contents); break; + case U_WMR_7C: U_WMR7C_print(contents); break; + case U_WMR_7D: U_WMR7D_print(contents); break; + case U_WMR_7E: U_WMR7E_print(contents); break; + case U_WMR_7F: U_WMR7F_print(contents); break; + case U_WMR_80: U_WMR80_print(contents); break; + case U_WMR_81: U_WMR81_print(contents); break; + case U_WMR_82: U_WMR82_print(contents); break; + case U_WMR_83: U_WMR83_print(contents); break; + case U_WMR_84: U_WMR84_print(contents); break; + case U_WMR_85: U_WMR85_print(contents); break; + case U_WMR_86: U_WMR86_print(contents); break; + case U_WMR_87: U_WMR87_print(contents); break; + case U_WMR_88: U_WMR88_print(contents); break; + case U_WMR_89: U_WMR89_print(contents); break; + case U_WMR_8A: U_WMR8A_print(contents); break; + case U_WMR_8B: U_WMR8B_print(contents); break; + case U_WMR_8C: U_WMR8C_print(contents); break; + case U_WMR_8D: U_WMR8D_print(contents); break; + case U_WMR_8E: U_WMR8E_print(contents); break; + case U_WMR_8F: U_WMR8F_print(contents); break; + case U_WMR_90: U_WMR90_print(contents); break; + case U_WMR_91: U_WMR91_print(contents); break; + case U_WMR_92: U_WMR92_print(contents); break; + case U_WMR_93: U_WMR93_print(contents); break; + case U_WMR_94: U_WMR94_print(contents); break; + case U_WMR_95: U_WMR95_print(contents); break; + case U_WMR_96: U_WMR96_print(contents); break; + case U_WMR_97: U_WMR97_print(contents); break; + case U_WMR_98: U_WMR98_print(contents); break; + case U_WMR_99: U_WMR99_print(contents); break; + case U_WMR_9A: U_WMR9A_print(contents); break; + case U_WMR_9B: U_WMR9B_print(contents); break; + case U_WMR_9C: U_WMR9C_print(contents); break; + case U_WMR_9D: U_WMR9D_print(contents); break; + case U_WMR_9E: U_WMR9E_print(contents); break; + case U_WMR_9F: U_WMR9F_print(contents); break; + case U_WMR_A0: U_WMRA0_print(contents); break; + case U_WMR_A1: U_WMRA1_print(contents); break; + case U_WMR_A2: U_WMRA2_print(contents); break; + case U_WMR_A3: U_WMRA3_print(contents); break; + case U_WMR_A4: U_WMRA4_print(contents); break; + case U_WMR_A5: U_WMRA5_print(contents); break; + case U_WMR_A6: U_WMRA6_print(contents); break; + case U_WMR_A7: U_WMRA7_print(contents); break; + case U_WMR_A8: U_WMRA8_print(contents); break; + case U_WMR_A9: U_WMRA9_print(contents); break; + case U_WMR_AA: U_WMRAA_print(contents); break; + case U_WMR_AB: U_WMRAB_print(contents); break; + case U_WMR_AC: U_WMRAC_print(contents); break; + case U_WMR_AD: U_WMRAD_print(contents); break; + case U_WMR_AE: U_WMRAE_print(contents); break; + case U_WMR_AF: U_WMRAF_print(contents); break; + case U_WMR_B0: U_WMRB0_print(contents); break; + case U_WMR_B1: U_WMRB1_print(contents); break; + case U_WMR_B2: U_WMRB2_print(contents); break; + case U_WMR_B3: U_WMRB3_print(contents); break; + case U_WMR_B4: U_WMRB4_print(contents); break; + case U_WMR_B5: U_WMRB5_print(contents); break; + case U_WMR_B6: U_WMRB6_print(contents); break; + case U_WMR_B7: U_WMRB7_print(contents); break; + case U_WMR_B8: U_WMRB8_print(contents); break; + case U_WMR_B9: U_WMRB9_print(contents); break; + case U_WMR_BA: U_WMRBA_print(contents); break; + case U_WMR_BB: U_WMRBB_print(contents); break; + case U_WMR_BC: U_WMRBC_print(contents); break; + case U_WMR_BD: U_WMRBD_print(contents); break; + case U_WMR_BE: U_WMRBE_print(contents); break; + case U_WMR_BF: U_WMRBF_print(contents); break; + case U_WMR_C0: U_WMRC0_print(contents); break; + case U_WMR_C1: U_WMRC1_print(contents); break; + case U_WMR_C2: U_WMRC2_print(contents); break; + case U_WMR_C3: U_WMRC3_print(contents); break; + case U_WMR_C4: U_WMRC4_print(contents); break; + case U_WMR_C5: U_WMRC5_print(contents); break; + case U_WMR_C6: U_WMRC6_print(contents); break; + case U_WMR_C7: U_WMRC7_print(contents); break; + case U_WMR_C8: U_WMRC8_print(contents); break; + case U_WMR_C9: U_WMRC9_print(contents); break; + case U_WMR_CA: U_WMRCA_print(contents); break; + case U_WMR_CB: U_WMRCB_print(contents); break; + case U_WMR_CC: U_WMRCC_print(contents); break; + case U_WMR_CD: U_WMRCD_print(contents); break; + case U_WMR_CE: U_WMRCE_print(contents); break; + case U_WMR_CF: U_WMRCF_print(contents); break; + case U_WMR_D0: U_WMRD0_print(contents); break; + case U_WMR_D1: U_WMRD1_print(contents); break; + case U_WMR_D2: U_WMRD2_print(contents); break; + case U_WMR_D3: U_WMRD3_print(contents); break; + case U_WMR_D4: U_WMRD4_print(contents); break; + case U_WMR_D5: U_WMRD5_print(contents); break; + case U_WMR_D6: U_WMRD6_print(contents); break; + case U_WMR_D7: U_WMRD7_print(contents); break; + case U_WMR_D8: U_WMRD8_print(contents); break; + case U_WMR_D9: U_WMRD9_print(contents); break; + case U_WMR_DA: U_WMRDA_print(contents); break; + case U_WMR_DB: U_WMRDB_print(contents); break; + case U_WMR_DC: U_WMRDC_print(contents); break; + case U_WMR_DD: U_WMRDD_print(contents); break; + case U_WMR_DE: U_WMRDE_print(contents); break; + case U_WMR_DF: U_WMRDF_print(contents); break; + case U_WMR_E0: U_WMRE0_print(contents); break; + case U_WMR_E1: U_WMRE1_print(contents); break; + case U_WMR_E2: U_WMRE2_print(contents); break; + case U_WMR_E3: U_WMRE3_print(contents); break; + case U_WMR_E4: U_WMRE4_print(contents); break; + case U_WMR_E5: U_WMRE5_print(contents); break; + case U_WMR_E6: U_WMRE6_print(contents); break; + case U_WMR_E7: U_WMRE7_print(contents); break; + case U_WMR_E8: U_WMRE8_print(contents); break; + case U_WMR_E9: U_WMRE9_print(contents); break; + case U_WMR_EA: U_WMREA_print(contents); break; + case U_WMR_EB: U_WMREB_print(contents); break; + case U_WMR_EC: U_WMREC_print(contents); break; + case U_WMR_ED: U_WMRED_print(contents); break; + case U_WMR_EE: U_WMREE_print(contents); break; + case U_WMR_EF: U_WMREF_print(contents); break; + case U_WMR_DELETEOBJECT: U_WMRDELETEOBJECT_print(contents); break; + case U_WMR_F1: U_WMRF1_print(contents); break; + case U_WMR_F2: U_WMRF2_print(contents); break; + case U_WMR_F3: U_WMRF3_print(contents); break; + case U_WMR_F4: U_WMRF4_print(contents); break; + case U_WMR_F5: U_WMRF5_print(contents); break; + case U_WMR_F6: U_WMRF6_print(contents); break; + case U_WMR_CREATEPALETTE: U_WMRCREATEPALETTE_print(contents); break; + case U_WMR_F8: U_WMRF8_print(contents); break; + case U_WMR_CREATEPATTERNBRUSH: U_WMRCREATEPATTERNBRUSH_print(contents); break; + case U_WMR_CREATEPENINDIRECT: U_WMRCREATEPENINDIRECT_print(contents); break; + case U_WMR_CREATEFONTINDIRECT: U_WMRCREATEFONTINDIRECT_print(contents); break; + case U_WMR_CREATEBRUSHINDIRECT: U_WMRCREATEBRUSHINDIRECT_print(contents); break; + case U_WMR_CREATEBITMAPINDIRECT: U_WMRCREATEBITMAPINDIRECT_print(contents); break; + case U_WMR_CREATEBITMAP: U_WMRCREATEBITMAP_print(contents); break; + case U_WMR_CREATEREGION: U_WMRCREATEREGION_print(contents); break; + default: U_WMRNOTIMPLEMENTED_print(contents); break; + } //end of switch + return(size); +} + + +#ifdef __cplusplus +} +#endif diff --git a/src/3rdparty/libuemf/uwmf_print.h b/src/3rdparty/libuemf/uwmf_print.h new file mode 100644 index 0000000..54dfe9c --- /dev/null +++ b/src/3rdparty/libuemf/uwmf_print.h @@ -0,0 +1,52 @@ +/** + @file uwmf_print.h + + @brief Prototypes for functions for printing records from WMF files. +*/ + +/* +File: uwmf_print.h +Version: 0.0.2 +Date: 14-FEB-2013 +Author: David Mathog, Biology Division, Caltech +email: mathog@caltech.edu +Copyright: 2012 David Mathog and California Institute of Technology (Caltech) +*/ + +#ifndef _UWMF_PRINT_ +#define _UWMF_PRINT_ + +#ifdef __cplusplus +extern "C" { +#endif +#include "uwmf.h" +#include "uemf_print.h" + +//! \cond +/* prototypes for objects used in WMR records (other than those defined in uemf_print.h) */ +void brush_print(U_BRUSH b); +void font_print(const char *font); +void pltntry_print(U_PLTNTRY pny); +void palette_print(const U_PALETTE *p, const char *PalEntries); +void pen_print(U_PEN p); +void rect16_ltrb_print(U_RECT16 rect); +void rect16_brtl_print(U_RECT16 rect); +void region_print(const char *region); +void bitmap16_print(U_BITMAP16 b); +void bitmapcoreheader_print(U_BITMAPCOREHEADER ch); +void logbrushw_print(U_WLOGBRUSH lb); +void polypolygon_print(uint16_t nPolys, const uint16_t *aPolyCounts, const char *Points); +void scan_print(U_SCAN sc); +void dibheader_print(const char *dh, const char *blimit); + +/* prototypes for WMF records */ +int wmfheader_print(const char *contents, const char *blimit); +void U_WMRNOTIMPLEMENTED_print(const char *contents); +int U_wmf_onerec_print(const char *contents, const char *blimit, int recnum, size_t off); +//! \endcond + +#ifdef __cplusplus +} +#endif + +#endif /* _UWMF_PRINT_ */ |