diff -rNu3 build.xml build.xml
--- build.xml 2012-08-07 12:29:10.000000000 -0700
+++ build.xml 2012-08-08 12:01:11.000000000 -0700
@@ -453,7 +453,7 @@
stripcommand="${archutil}strip"
objcopycommand="${archutil}objcopy">
- -mwindows
+ -mconsole
-mthreads
@@ -527,7 +527,7 @@
stripcommand="${archutil}strip"
objcopycommand="${archutil}objcopy">
- -mwindows
+ -mconsole
-mthreads
diff -rNu3 configure.ac configure.ac
--- configure.ac 2012-08-07 12:29:10.000000000 -0700
+++ configure.ac 2012-08-08 09:04:00.000000000 -0700
@@ -11,6 +11,7 @@
AC_CANONICAL_HOST
AC_CONFIG_SRCDIR([src/main.cpp])
+AC_CONFIG_MACRO_DIR([m4])
AM_INIT_AUTOMAKE([dist-zip dist-bzip2 tar-pax])
AC_ARG_ENABLE([lsb], AS_HELP_STRING([--enable-lsb], [LSB-compatible build configuration]), [
@@ -69,7 +70,7 @@
AC_MSG_CHECKING([compiler support for -Werror=format-security])
ink_svd_CPPFLAGS="$CPPFLAGS"
CPPFLAGS="-Werror=format-security $CPPFLAGS"
- AC_COMPILE_IFELSE(AC_LANG_PROGRAM([]), [ink_opt_ok=yes], [ink_opt_ok=no])
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([])], [ink_opt_ok=yes], [ink_opt_ok=no])
AC_MSG_RESULT([$ink_opt_ok])
if test "x$ink_opt_ok" != "xyes"; then
CPPFLAGS="$ink_svd_CPPFLAGS"
@@ -83,7 +84,7 @@
AC_MSG_CHECKING([compiler support for -Wno-pointer-sign])
ink_svd_CFLAGS="$CFLAGS"
CFLAGS="-Wno-pointer-sign $CFLAGS"
- AC_COMPILE_IFELSE(AC_LANG_PROGRAM([]), [ink_opt_ok=yes], [ink_opt_ok=no])
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([])], [ink_opt_ok=yes], [ink_opt_ok=no])
AC_MSG_RESULT([$ink_opt_ok])
if test "x$ink_opt_ok" != "xyes"; then
CFLAGS="$ink_svd_CFLAGS"
@@ -96,7 +97,7 @@
AC_MSG_CHECKING([linker tolerates -z relro])
ink_svd_LDFLAGS="$LDFLAGS"
LDFLAGS="-Wl,-z,relro $LDFLAGS"
- AC_LINK_IFELSE(AC_LANG_PROGRAM([]), [ink_opt_ok=yes], [ink_opt_ok=no])
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([])], [ink_opt_ok=yes], [ink_opt_ok=no])
AC_MSG_RESULT([$ink_opt_ok])
if test "x$ink_opt_ok" != "xyes"; then
LDFLAGS="$ink_svd_LDFLAGS"
@@ -137,14 +138,14 @@
# Detect a working version of unordered containers.
AC_MSG_CHECKING([TR1 unordered_set usability])
-AC_COMPILE_IFELSE([
+AC_COMPILE_IFELSE([AC_LANG_SOURCE([
#include
int main() {
std::tr1::unordered_set i, j;
i = j;
return 0;
}
-], [unordered_set_works=yes], [unordered_set_works=no])
+])], [unordered_set_works=yes], [unordered_set_works=no])
if test "x$unordered_set_works" = "xyes"; then
AC_MSG_RESULT([ok])
AC_DEFINE(HAVE_TR1_UNORDERED_SET, 1, [Has working standard TR1 unordered_set])
@@ -161,13 +162,13 @@
ignore_strict_aliasing=no
CXXFLAGS_SAVE=$CXXFLAGS
CXXFLAGS="$CXXFLAGS -Werror=strict-aliasing"
-AC_COMPILE_IFELSE([
+AC_COMPILE_IFELSE([AC_LANG_SOURCE([
#include
boost::optional x;
int func() {
return *x;
}
-], [ignore_strict_aliasing=no], [ignore_strict_aliasing=yes])
+])], [ignore_strict_aliasing=no], [ignore_strict_aliasing=yes])
AC_MSG_RESULT($ignore_strict_aliasing)
CXXFLAGS=$CXXFLAGS_SAVE
if test "x$ignore_strict_aliasing" = "xyes"; then
@@ -609,7 +610,7 @@
AC_MSG_CHECKING(for new color space API in Poppler)
popplercolor="no"
-AC_COMPILE_IFELSE([
+AC_COMPILE_IFELSE([AC_LANG_SOURCE([
#include
int main() {
@@ -618,7 +619,7 @@
p = &GfxColorSpace::parse;
return 0;
}
-], [popplercolor=yes])
+])], [popplercolor=yes])
if test "x$popplercolor" = "xyes"; then
AC_DEFINE(POPPLER_NEW_COLOR_SPACE_API, 1, [Use color space API from Poppler >= 0.12.2])
AC_MSG_RESULT(yes)
@@ -629,7 +630,7 @@
# Poppler's b604a008 commit changes this
AC_MSG_CHECKING([whether Poppler's GfxPatch no longer uses GfxColor])
popplergfxcolor="no"
-AC_COMPILE_IFELSE([
+AC_COMPILE_IFELSE([AC_LANG_SOURCE([
#include
int main() {
@@ -638,7 +639,7 @@
patch.color[[0]][[0]] = color;
return 0;
}
-], [popplergfxcolor=yes])
+])], [popplergfxcolor=yes])
if test "x$popplergfxcolor" = "xyes"; then
AC_DEFINE(POPPLER_NEW_GFXPATCH, 1, [GfxPatch no longer uses GfxColor in >= 0.15.1])
AC_MSG_RESULT(yes)
@@ -843,10 +844,10 @@
# Check for Apple Mac OS X Carbon framework
carbon_ok=no
AC_MSG_CHECKING([for Mac OS X Carbon support])
-AC_COMPILE_IFELSE([
+AC_COMPILE_IFELSE([AC_LANG_SOURCE([
#include
#include
-], [carbon_ok=yes])
+])], [carbon_ok=yes])
AC_MSG_RESULT($carbon_ok)
if test "x$carbon_ok" = "xyes"; then
AC_DEFINE(HAVE_CARBON, 1, [define to 1 if Carbon is available])
@@ -1012,8 +1013,8 @@
ink_svd_CXXFLAGS="$CXXFLAGS"
CXXFLAGS="-Wno-unused-parameter $CXXFLAGS"
# -Wno-unused-parameter isn't accepted by gcc 2.95.
- AC_COMPILE_IFELSE([int dummy;
-], , CXXFLAGS="-Wno-unused $ink_svd_CXXFLAGS",)
+ AC_COMPILE_IFELSE([AC_LANG_SOURCE([int dummy;
+])], , CXXFLAGS="-Wno-unused $ink_svd_CXXFLAGS",)
# Note: At least one bug has been caught from unused parameter warnings,
# so it might be worth trying not to disable it.
# One way of selectively disabling the warnings (i.e. only where the
@@ -1065,6 +1066,7 @@
src/libgdl/makefile
src/libnrtype/makefile
src/libavoid/makefile
+src/libunicode-convert/makefile
src/livarot/makefile
src/live_effects/makefile
src/live_effects/parameter/makefile
diff -rNu3 share/extensions/fontfix.conf share/extensions/fontfix.conf
--- share/extensions/fontfix.conf 1969-12-31 16:00:00.000000000 -0800
+++ share/extensions/fontfix.conf 2012-08-07 13:12:16.000000000 -0700
@@ -0,0 +1,55 @@
+# This file contains correction factors for the PowerPoint compensation method
+# when files are saved to EMF. PowerPoint applies some odd offsets when it ungroups
+# fonts from within an EMF. This file contains compensating factors so that the
+# imported, ungrouped characters end up in the desired location.
+#
+# Format(s)
+#
+# # a comment
+#
+# f1 f2 f3 FontName
+# where
+# f1: vertical (rotating) correction factor (a double)
+# f2: vertical (nonrotating) correction factor (a double)
+# f3: horizontal (nonrotating) correction factor (a double)
+# FontName: Case sensitive, may contain spaces. Example: Times New Roman
+#
+# The first font will listed will be used as the default for any font which
+# is later requested but was not explicitly listed.
+#
+# If f1 specifies a multiplicative correction factor. It is multiplied by the font size
+# and then the character is offset parallel to the (original) vertical direction of the character,
+# that is, along the long part of a capital L.
+#
+# If f2 or f3 is nonzero then for angles <1 degree from 0,90,180,270 degrees
+# the angle is snapped to n*90 and f2 is used for the vertical displacements, f3
+# for the horizontal displacements (that is, for 90 degrees, f3 is used).
+#
+# There is are one special type of fontname: Convert To FontName,
+# for instance "Convert To Symbol". It is used when EMF print converts
+# from unicode to Symbol, Wingdings, or Zapf Dingbats.
+#
+# Positive values lower the letter, negative raise it
+#
+# File history:
+# 1.0.0 03/26/2012, David Mathog, initial values
+#####################################################################
+0.05 -0.055 -0.065 Arial
+0.05 -0.055 -0.065 Times New Roman
+-0.025 -0.055 -0.065 Lucida Sans
+0.05 -0.055 -0.065 Sans
+-0.05 -0.055 -0.065 Microsoft Sans Serif
+0.05 -0.055 -0.065 Serif
+0.05 -0.055 -0.065 Garamond
+0.25 0.025 0.025 Century Schoolbook
+0.025 0.0 0.0 Verdana
+0.045 0.025 0.025 Tahoma
+0.025 0.0 0.0 Symbol
+0.05 0.0 0.0 Wingdings
+0.025 0.0 0.0 Zapf Dingbats
+0.025 0.0 0.0 Convert To Symbol
+0.05 0.0 0.0 Convert To Wingdings
+0.025 0.0 0.0 Convert To Zapf Dingbats
+0.1 0.0 0.0 Sylfaen
+0.175 0.125 0.125 Palatino Linotype
+0.1 0.0 0.0 Segoe UI
diff -rNu3 ../inkscape/share/extensions/Makefile.am share/extensions/Makefile.am
--- ../inkscape/share/extensions/Makefile.am 2012-07-22 10:51:28.473073000 -0700
+++ share/extensions/Makefile.am 2012-08-08 15:59:23.365615640 -0700
@@ -178,6 +178,7 @@
yocto_css.py
otherstuff = \
+ fontfix.conf \
inkweb.js \
jessyInk.js \
jessyInk_core_mouseHandler_noclick.js \
diff -rNu3 src/extension/init.cpp src/extension/init.cpp
--- src/extension/init.cpp 2012-08-07 12:29:10.000000000 -0700
+++ src/extension/init.cpp 2012-08-07 12:43:08.000000000 -0700
@@ -32,10 +32,8 @@
#include "system.h"
#include "db.h"
#include "internal/svgz.h"
-#ifdef WIN32
-# include "internal/emf-win32-inout.h"
-# include "internal/emf-win32-print.h"
-#endif
+# include "internal/emf-inout.h"
+# include "internal/emf-print.h"
#ifdef HAVE_CAIRO_PDF
# include "internal/cairo-renderer-pdf-out.h"
# include "internal/cairo-png-out.h"
@@ -171,10 +169,8 @@
Internal::PdfInputCairo::init();
}
#endif
-#ifdef WIN32
- Internal::PrintEmfWin32::init();
- Internal::EmfWin32::init();
-#endif
+ Internal::PrintEmf::init();
+ Internal::Emf::init();
Internal::PovOutput::init();
Internal::JavaFXOutput::init();
Internal::OdfOutput::init();
@@ -308,7 +304,7 @@
continue;
}
- gchar *pathname = g_build_filename(dirname, filename, NULL);
+ gchar *pathname = g_build_filename(dirname, filename, (char *) NULL);
build_from_file(pathname);
g_free(pathname);
}
diff -rNu3 src/extension/internal/emf-inout.cpp src/extension/internal/emf-inout.cpp
--- src/extension/internal/emf-inout.cpp 1969-12-31 16:00:00.000000000 -0800
+++ src/extension/internal/emf-inout.cpp 2012-08-08 10:58:31.000000000 -0700
@@ -0,0 +1,2696 @@
+/** @file
+ * @brief Windows-only Enhanced Metafile input and output.
+ */
+/* Authors:
+ * Ulf Erikson
+ * Jon A. Cruz
+ * Abhishek Sharma
+ *
+ * Copyright (C) 2006-2008 Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ *
+ * References:
+ * - How to Create & Play Enhanced Metafiles in Win32
+ * http://support.microsoft.com/kb/q145999/
+ * - INFO: Windows Metafile Functions & Aldus Placeable Metafiles
+ * http://support.microsoft.com/kb/q66949/
+ * - Metafile Functions
+ * http://msdn.microsoft.com/library/en-us/gdi/metafile_0whf.asp
+ * - Metafile Structures
+ * http://msdn.microsoft.com/library/en-us/gdi/metafile_5hkj.asp
+ */
+
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#define EMF_DRIVER
+#include "sp-root.h"
+#include "sp-path.h"
+#include "style.h"
+#include "print.h"
+#include "extension/system.h"
+#include "extension/print.h"
+#include "extension/db.h"
+#include "extension/input.h"
+#include "extension/output.h"
+#include "display/drawing.h"
+#include "display/drawing-item.h"
+#include "unit-constants.h"
+#include "clear-n_.h"
+#include "document.h"
+#include "libunicode-convert/unicode-convert.h"
+
+
+#include "emf-print.h"
+#include "emf-inout.h"
+#include "uemf.h"
+
+#define PRINT_EMF "org.inkscape.print.emf"
+
+#ifndef U_PS_JOIN_MASK
+#define U_PS_JOIN_MASK (U_PS_JOIN_BEVEL|U_PS_JOIN_MITER|U_PS_JOIN_ROUND)
+#endif
+
+namespace Inkscape {
+namespace Extension {
+namespace Internal {
+
+
+static float device_scale = DEVICESCALE;
+static U_RECTL rc_old;
+static bool clipset = false;
+static uint32_t ICMmode=0;
+static uint32_t BLTmode=0;
+
+/** Construct a PNG in memory from an RGB from the EMF file
+
+from:
+http://www.lemoda.net/c/write-png/
+
+which was based on:
+http://stackoverflow.com/questions/1821806/how-to-encode-png-to-buffer-using-libpng
+
+gcc -Wall -o testpng testpng.c -lpng
+*/
+
+#include
+#include
+#include
+#include
+
+/* A coloured pixel. */
+
+typedef struct {
+ uint8_t red;
+ uint8_t green;
+ uint8_t blue;
+ uint8_t opacity;
+} pixel_t;
+
+/* A picture. */
+
+typedef struct {
+ pixel_t *pixels;
+ size_t width;
+ size_t height;
+} bitmap_t;
+
+/* structure to store PNG image bytes */
+typedef struct {
+ char *buffer;
+ size_t size;
+} MEMPNG, *PMEMPNG;
+
+/* Given "bitmap", this returns the pixel of bitmap at the point
+ ("x", "y"). */
+
+static pixel_t * pixel_at (bitmap_t * bitmap, int x, int y)
+{
+ return bitmap->pixels + bitmap->width * y + x;
+}
+
+/* Write "bitmap" to a PNG file specified by "path"; returns 0 on
+ success, non-zero on error. */
+
+
+
+void
+my_png_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
+{
+ /* with libpng15 next line causes pointer deference error; use libpng12 */
+ PMEMPNG p=(PMEMPNG)png_ptr->io_ptr;
+ size_t nsize = p->size + length;
+
+ /* allocate or grow buffer */
+ if(p->buffer)
+ p->buffer = (char *) realloc(p->buffer, nsize);
+ else
+ p->buffer = (char *) malloc(nsize);
+
+ if(!p->buffer)
+ png_error(png_ptr, "Write Error");
+
+ /* copy new bytes to end of buffer */
+ memcpy(p->buffer + p->size, data, length);
+ p->size += length;
+}
+
+void toPNG(PMEMPNG accum, int width, int height, char *px, uint32_t cbPx){
+ bitmap_t bmstore;
+ bitmap_t *bitmap=&bmstore;
+ accum->buffer=NULL; // PNG constructed in memory will end up here, caller must free().
+ accum->size=0;
+ bitmap->pixels=(pixel_t *)px;
+ bitmap->width = width;
+ bitmap->height = height;
+
+ png_structp png_ptr = NULL;
+ png_infop info_ptr = NULL;
+ size_t x, y;
+ png_byte ** row_pointers = NULL;
+ /* The following number is set by trial and error only. I cannot
+ see where it it is documented in the libpng manual.
+ */
+ int pixel_size = 3;
+ int depth = 8;
+
+ png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+ if (png_ptr == NULL){
+ accum->buffer=NULL;
+ return;
+ }
+
+ info_ptr = png_create_info_struct (png_ptr);
+ if (info_ptr == NULL){
+ png_destroy_write_struct (&png_ptr, &info_ptr);
+ accum->buffer=NULL;
+ return;
+ }
+
+ /* Set up error handling. */
+
+ if (setjmp (png_jmpbuf (png_ptr))) {
+ png_destroy_write_struct (&png_ptr, &info_ptr);
+ accum->buffer=NULL;
+ return;
+ }
+
+ /* Set image attributes. */
+
+ png_set_IHDR (png_ptr,
+ info_ptr,
+ bitmap->width,
+ bitmap->height,
+ depth,
+ PNG_COLOR_TYPE_RGB,
+ PNG_INTERLACE_NONE,
+ PNG_COMPRESSION_TYPE_DEFAULT,
+ PNG_FILTER_TYPE_DEFAULT);
+
+ /* Initialize rows of PNG. */
+
+ row_pointers = (png_byte **) png_malloc (png_ptr, bitmap->height * sizeof (png_byte *));
+ for (y = 0; y < bitmap->height; ++y) {
+ png_byte *row =
+ (png_byte *) png_malloc (png_ptr, sizeof (uint8_t) * bitmap->width * pixel_size);
+ row_pointers[bitmap->height - y - 1] = row; // Row order in EMF is reversed.
+ for (x = 0; x < bitmap->width; ++x) {
+ pixel_t * pixel = pixel_at (bitmap, x, y);
+ *row++ = pixel->red; // R & B channels were set correctly by DIB_to_RGB
+ *row++ = pixel->green;
+ *row++ = pixel->blue;
+ }
+ }
+
+ /* Write the image data to memory */
+
+ png_set_rows (png_ptr, info_ptr, row_pointers);
+
+ png_set_write_fn(png_ptr, accum, my_png_write_data, NULL);
+
+ png_write_png (png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
+
+ for (y = 0; y < bitmap->height; y++) {
+ png_free (png_ptr, row_pointers[y]);
+ }
+ png_free (png_ptr, row_pointers);
+
+}
+
+/* Given "value" and "max", the maximum value which we expect "value"
+ to take, this returns an integer between 0 and 255 proportional to
+ "value" divided by "max". */
+
+static int pix (int value, int max)
+{
+ if (value < 0)
+ return 0;
+ return (int) (256.0 *((double) (value)/(double) max));
+}
+
+
+
+Emf::Emf (void) // The null constructor
+{
+ return;
+}
+
+
+Emf::~Emf (void) //The destructor
+{
+ return;
+}
+
+
+bool
+Emf::check (Inkscape::Extension::Extension * /*module*/)
+{
+ if (NULL == Inkscape::Extension::db.get(PRINT_EMF))
+ return FALSE;
+ return TRUE;
+}
+
+
+static void
+emf_print_document_to_file(SPDocument *doc, gchar const *filename)
+{
+ Inkscape::Extension::Print *mod;
+ SPPrintContext context;
+ gchar const *oldconst;
+ gchar *oldoutput;
+ unsigned int ret;
+
+ doc->ensureUpToDate();
+
+ mod = Inkscape::Extension::get_print(PRINT_EMF);
+ oldconst = mod->get_param_string("destination");
+ oldoutput = g_strdup(oldconst);
+ mod->set_param_string("destination", filename);
+
+/* Start */
+ context.module = mod;
+ /* fixme: This has to go into module constructor somehow */
+ /* Create new arena */
+ mod->base = doc->getRoot();
+ Inkscape::Drawing drawing;
+ mod->dkey = SPItem::display_key_new(1);
+ mod->root = mod->base->invoke_show(drawing, mod->dkey, SP_ITEM_SHOW_DISPLAY);
+ drawing.setRoot(mod->root);
+ /* Print document */
+ ret = mod->begin(doc);
+ if (ret) {
+ g_free(oldoutput);
+ throw Inkscape::Extension::Output::save_failed();
+ }
+ mod->base->invoke_print(&context);
+ ret = mod->finish();
+ /* Release arena */
+ mod->base->invoke_hide(mod->dkey);
+ mod->base = NULL;
+ mod->root = NULL; // deleted by invoke_hide
+/* end */
+
+ mod->set_param_string("destination", oldoutput);
+ g_free(oldoutput);
+
+ return;
+}
+
+
+void
+Emf::save(Inkscape::Extension::Output *mod, SPDocument *doc, gchar const *filename)
+{
+ Inkscape::Extension::Extension * ext;
+
+ ext = Inkscape::Extension::db.get(PRINT_EMF);
+ if (ext == NULL)
+ return;
+
+ bool new_val = mod->get_param_bool("textToPath");
+ bool new_FixPPT1 = mod->get_param_bool("FixPPT1");
+
+ TableGen( //possibly regenerate the unicode-convert tables
+ mod->get_param_bool("TnrToSymbol"),
+ mod->get_param_bool("TnrToWingdings"),
+ mod->get_param_bool("TnrToZapfDingbats"),
+ mod->get_param_bool("UsePUA")
+ );
+
+ ext->set_param_bool("FixPPT1",new_FixPPT1); // pass FixPPT1 into the extension MATHOG
+ ext->set_param_bool("textToPath", new_val);
+
+ emf_print_document_to_file(doc, filename);
+
+ return;
+}
+
+
+
+typedef struct {
+ int type;
+ int level;
+ char *lpEMFR;
+} EMF_OBJECT, *PEMF_OBJECT;
+
+typedef struct emf_device_context {
+ struct SPStyle style;
+ class SPTextStyle tstyle;
+ bool stroke_set;
+ bool fill_set;
+
+ U_SIZEL sizeWnd;
+ U_SIZEL sizeView;
+ float PixelsInX, PixelsInY;
+ float PixelsOutX, PixelsOutY;
+ U_POINTL winorg;
+ U_POINTL vieworg;
+ double ScaleInX, ScaleInY;
+ double ScaleOutX, ScaleOutY;
+ U_COLORREF textColor;
+ bool textColorSet;
+ uint32_t textAlign;
+ U_XFORM worldTransform;
+ U_POINTL cur;
+} EMF_DEVICE_CONTEXT, *PEMF_DEVICE_CONTEXT;
+
+#define EMF_MAX_DC 128
+
+typedef struct emf_callback_data {
+ Glib::ustring *outsvg;
+ Glib::ustring *path;
+ Glib::ustring *outdef;
+
+ EMF_DEVICE_CONTEXT dc[EMF_MAX_DC+1]; // FIXME: This should be dynamic..
+ int level;
+
+ double xDPI, yDPI;
+ uint32_t mask; // Draw properties
+ int arcdir; //U_AD_COUNTERCLOCKWISE 1 or U_AD_CLOCKWISE 2
+
+ uint32_t dwRop2; // Binary raster operation, 0 if none (use brush/pen unmolested)
+ uint32_t dwRop3; // Ternary raster operation, 0 if none (use brush/pen unmolested)
+
+ float MMX;
+ float MMY;
+ float dwInchesX;
+ float dwInchesY;
+
+ unsigned int id;
+ unsigned int drawtype; // one of 0 or U_EMR_FILLPATH, U_EMR_STROKEPATH, U_EMR_STROKEANDFILLPATH
+ char *pDesc;
+
+ int n_obj;
+ PEMF_OBJECT emf_obj;
+} EMF_CALLBACK_DATA, *PEMF_CALLBACK_DATA;
+
+
+static void
+output_style(PEMF_CALLBACK_DATA d, int iType)
+{
+// SVGOStringStream tmp_id;
+ SVGOStringStream tmp_style;
+ char tmp[1024] = {0};
+
+ float fill_rgb[3];
+ sp_color_get_rgb_floatv( &(d->dc[d->level].style.fill.value.color), fill_rgb );
+ float stroke_rgb[3];
+ sp_color_get_rgb_floatv(&(d->dc[d->level].style.stroke.value.color), stroke_rgb);
+
+ // for U_EMR_BITBLT with no image, try to approximate some of these operations/
+ // Assume src color is "white"
+ if(d->dwRop3){
+ switch(d->dwRop3){
+ case U_PATINVERT: // treat all of these as black
+ case U_SRCINVERT:
+ case U_DSTINVERT:
+ case U_BLACKNESS:
+ case U_SRCERASE:
+ case U_NOTSRCCOPY:
+ fill_rgb[0]=fill_rgb[1]=fill_rgb[2]=0.0;
+ break;
+ case U_SRCCOPY: // treat all of these as white
+ case U_NOTSRCERASE:
+ case U_PATCOPY:
+ case U_WHITENESS:
+ fill_rgb[0]=fill_rgb[1]=fill_rgb[2]=1.0;
+ break;
+ case U_SRCPAINT: // use the existing color
+ case U_SRCAND:
+ case U_MERGECOPY:
+ case U_MERGEPAINT:
+ case U_PATPAINT:
+ default:
+ break;
+ }
+ d->dwRop3 = 0; // might as well reset it here, it must be set for each BITBLT
+ }
+
+ // Implement some of these, the ones where the original screen color does not matter.
+ // The options that merge screen and pen colors cannot be done correctly because we
+ // have no way of knowing what color is already on the screen. For those just pass the
+ // pen color through.
+ switch(d->dwRop2){
+ case U_R2_BLACK:
+ fill_rgb[0] = fill_rgb[1] = fill_rgb[2] = 0.0;
+ stroke_rgb[0]= stroke_rgb[1]= stroke_rgb[2] = 0.0;
+ break;
+ case U_R2_NOTMERGEPEN:
+ case U_R2_MASKNOTPEN:
+ break;
+ case U_R2_NOTCOPYPEN:
+ fill_rgb[0] = 1.0 - fill_rgb[0];
+ fill_rgb[1] = 1.0 - fill_rgb[1];
+ fill_rgb[2] = 1.0 - fill_rgb[2];
+ stroke_rgb[0] = 1.0 - stroke_rgb[0];
+ stroke_rgb[1] = 1.0 - stroke_rgb[1];
+ stroke_rgb[2] = 1.0 - stroke_rgb[2];
+ break;
+ case U_R2_MASKPENNOT:
+ case U_R2_NOT:
+ case U_R2_XORPEN:
+ case U_R2_NOTMASKPEN:
+ case U_R2_NOTXORPEN:
+ case U_R2_NOP:
+ case U_R2_MERGENOTPEN:
+ case U_R2_COPYPEN:
+ case U_R2_MASKPEN:
+ case U_R2_MERGEPENNOT:
+ case U_R2_MERGEPEN:
+ break;
+ case U_R2_WHITE:
+ fill_rgb[0] = fill_rgb[1] = fill_rgb[2] = 1.0;
+ stroke_rgb[0]= stroke_rgb[1]= stroke_rgb[2] = 1.0;
+ break;
+ default:
+ break;
+ }
+
+
+// tmp_id << "\n\tid=\"" << (d->id++) << "\"";
+// *(d->outsvg) += tmp_id.str().c_str();
+ *(d->outsvg) += "\n\tstyle=\"";
+ if (iType == U_EMR_STROKEPATH || !d->dc[d->level].fill_set) {
+ tmp_style << "fill:none;";
+ } else {
+ snprintf(tmp, 1023,
+ "fill:#%02x%02x%02x;",
+ SP_COLOR_F_TO_U(fill_rgb[0]),
+ SP_COLOR_F_TO_U(fill_rgb[1]),
+ SP_COLOR_F_TO_U(fill_rgb[2]));
+ tmp_style << tmp;
+ snprintf(tmp, 1023,
+ "fill-rule:%s;",
+ d->dc[d->level].style.fill_rule.value == 0 ? "evenodd" : "nonzero");
+ tmp_style << tmp;
+ tmp_style << "fill-opacity:1;";
+
+ if (d->dc[d->level].fill_set && d->dc[d->level].stroke_set && d->dc[d->level].style.stroke_width.value == 1 &&
+ fill_rgb[0]==stroke_rgb[0] && fill_rgb[1]==stroke_rgb[1] && fill_rgb[2]==stroke_rgb[2])
+ {
+ d->dc[d->level].stroke_set = false;
+ }
+ }
+
+ if (iType == U_EMR_FILLPATH || !d->dc[d->level].stroke_set) {
+ tmp_style << "stroke:none;";
+ } else {
+ snprintf(tmp, 1023,
+ "stroke:#%02x%02x%02x;",
+ SP_COLOR_F_TO_U(stroke_rgb[0]),
+ SP_COLOR_F_TO_U(stroke_rgb[1]),
+ SP_COLOR_F_TO_U(stroke_rgb[2]));
+ tmp_style << tmp;
+
+ tmp_style << "stroke-width:" <<
+ MAX( 0.001, d->dc[d->level].style.stroke_width.value ) << "px;";
+
+ tmp_style << "stroke-linecap:" <<
+ (d->dc[d->level].style.stroke_linecap.computed == 0 ? "butt" :
+ d->dc[d->level].style.stroke_linecap.computed == 1 ? "round" :
+ d->dc[d->level].style.stroke_linecap.computed == 2 ? "square" :
+ "unknown") << ";";
+
+ tmp_style << "stroke-linejoin:" <<
+ (d->dc[d->level].style.stroke_linejoin.computed == 0 ? "miter" :
+ d->dc[d->level].style.stroke_linejoin.computed == 1 ? "round" :
+ d->dc[d->level].style.stroke_linejoin.computed == 2 ? "bevel" :
+ "unknown") << ";";
+
+ // Set miter limit if known, even if it is not needed immediately (not miter)
+ tmp_style << "stroke-miterlimit:" <<
+ MAX( 2.0, d->dc[d->level].style.stroke_miterlimit.value ) << ";";
+
+ if (d->dc[d->level].style.stroke_dasharray_set &&
+ d->dc[d->level].style.stroke_dash.n_dash && d->dc[d->level].style.stroke_dash.dash)
+ {
+ tmp_style << "stroke-dasharray:";
+ for (int i=0; idc[d->level].style.stroke_dash.n_dash; i++) {
+ if (i)
+ tmp_style << ",";
+ tmp_style << d->dc[d->level].style.stroke_dash.dash[i];
+ }
+ tmp_style << ";";
+ tmp_style << "stroke-dashoffset:0;";
+ } else {
+ tmp_style << "stroke-dasharray:none;";
+ }
+ tmp_style << "stroke-opacity:1;";
+ }
+ tmp_style << "\" ";
+ if (clipset)
+ tmp_style << "\n\tclip-path=\"url(#clipEmfPath" << d->id << ")\" ";
+ clipset = false;
+
+ *(d->outsvg) += tmp_style.str().c_str();
+}
+
+
+static double
+_pix_x_to_point(PEMF_CALLBACK_DATA d, double px)
+{
+ double tmp = px - d->dc[d->level].winorg.x;
+ tmp *= d->dc[d->level].ScaleInX ? d->dc[d->level].ScaleInX : 1.0;
+ tmp += d->dc[d->level].vieworg.x;
+ return tmp;
+}
+
+static double
+_pix_y_to_point(PEMF_CALLBACK_DATA d, double px)
+{
+ double tmp = px - d->dc[d->level].winorg.y;
+ tmp *= d->dc[d->level].ScaleInY ? d->dc[d->level].ScaleInY : 1.0;
+ tmp += d->dc[d->level].vieworg.y;
+ return tmp;
+}
+
+
+static double
+pix_to_x_point(PEMF_CALLBACK_DATA d, double px, double py)
+{
+ double ppx = _pix_x_to_point(d, px);
+ double ppy = _pix_y_to_point(d, py);
+
+ double x = ppx * d->dc[d->level].worldTransform.eM11 + ppy * d->dc[d->level].worldTransform.eM21 + d->dc[d->level].worldTransform.eDx;
+ x *= device_scale;
+
+ return x;
+}
+
+static double
+pix_to_y_point(PEMF_CALLBACK_DATA d, double px, double py)
+{
+ double ppx = _pix_x_to_point(d, px);
+ double ppy = _pix_y_to_point(d, py);
+
+ double y = ppx * d->dc[d->level].worldTransform.eM12 + ppy * d->dc[d->level].worldTransform.eM22 + d->dc[d->level].worldTransform.eDy;
+ y *= device_scale;
+
+ return y;
+}
+
+static double
+pix_to_size_point(PEMF_CALLBACK_DATA d, double px)
+{
+ double ppx = px * (d->dc[d->level].ScaleInX ? d->dc[d->level].ScaleInX : 1.0);
+ double ppy = 0;
+
+ double dx = ppx * d->dc[d->level].worldTransform.eM11 + ppy * d->dc[d->level].worldTransform.eM21;
+ dx *= device_scale;
+ double dy = ppx * d->dc[d->level].worldTransform.eM12 + ppy * d->dc[d->level].worldTransform.eM22;
+ dy *= device_scale;
+
+ double tmp = sqrt(dx * dx + dy * dy);
+ return tmp;
+}
+
+
+static void
+select_pen(PEMF_CALLBACK_DATA d, int index)
+{
+ PU_EMRCREATEPEN pEmr = NULL;
+
+ if (index >= 0 && index < d->n_obj)
+ pEmr = (PU_EMRCREATEPEN) d->emf_obj[index].lpEMFR;
+
+ if (!pEmr)
+ return;
+
+ switch (pEmr->lopn.lopnStyle & U_PS_STYLE_MASK) {
+ case U_PS_DASH:
+ case U_PS_DOT:
+ case U_PS_DASHDOT:
+ case U_PS_DASHDOTDOT:
+ {
+ int i = 0;
+ int penstyle = (pEmr->lopn.lopnStyle & U_PS_STYLE_MASK);
+ d->dc[d->level].style.stroke_dash.n_dash =
+ penstyle == U_PS_DASHDOTDOT ? 6 : penstyle == U_PS_DASHDOT ? 4 : 2;
+ if (d->dc[d->level].style.stroke_dash.dash && (d->level==0 || (d->level>0 && d->dc[d->level].style.stroke_dash.dash!=d->dc[d->level-1].style.stroke_dash.dash)))
+ delete[] d->dc[d->level].style.stroke_dash.dash;
+ d->dc[d->level].style.stroke_dash.dash = new double[d->dc[d->level].style.stroke_dash.n_dash];
+ if (penstyle==U_PS_DASH || penstyle==U_PS_DASHDOT || penstyle==U_PS_DASHDOTDOT) {
+ d->dc[d->level].style.stroke_dash.dash[i++] = 3;
+ d->dc[d->level].style.stroke_dash.dash[i++] = 1;
+ }
+ if (penstyle==U_PS_DOT || penstyle==U_PS_DASHDOT || penstyle==U_PS_DASHDOTDOT) {
+ d->dc[d->level].style.stroke_dash.dash[i++] = 1;
+ d->dc[d->level].style.stroke_dash.dash[i++] = 1;
+ }
+ if (penstyle==U_PS_DASHDOTDOT) {
+ d->dc[d->level].style.stroke_dash.dash[i++] = 1;
+ d->dc[d->level].style.stroke_dash.dash[i++] = 1;
+ }
+
+ d->dc[d->level].style.stroke_dasharray_set = 1;
+ break;
+ }
+
+ case U_PS_SOLID:
+ default:
+ {
+ d->dc[d->level].style.stroke_dasharray_set = 0;
+ break;
+ }
+ }
+
+ switch (pEmr->lopn.lopnStyle & U_PS_ENDCAP_MASK) {
+ case U_PS_ENDCAP_ROUND:
+ {
+ d->dc[d->level].style.stroke_linecap.computed = 1;
+ break;
+ }
+ case U_PS_ENDCAP_SQUARE:
+ {
+ d->dc[d->level].style.stroke_linecap.computed = 2;
+ break;
+ }
+ case U_PS_ENDCAP_FLAT:
+ default:
+ {
+ d->dc[d->level].style.stroke_linecap.computed = 0;
+ break;
+ }
+ }
+
+ switch (pEmr->lopn.lopnStyle & U_PS_JOIN_MASK) {
+ case U_PS_JOIN_BEVEL:
+ {
+ d->dc[d->level].style.stroke_linejoin.computed = 2;
+ break;
+ }
+ case U_PS_JOIN_MITER:
+ {
+ d->dc[d->level].style.stroke_linejoin.computed = 0;
+ break;
+ }
+ case U_PS_JOIN_ROUND:
+ default:
+ {
+ d->dc[d->level].style.stroke_linejoin.computed = 1;
+ break;
+ }
+ }
+
+ d->dc[d->level].stroke_set = true;
+
+ if (pEmr->lopn.lopnStyle == U_PS_NULL) {
+ d->dc[d->level].style.stroke_width.value = 0;
+ d->dc[d->level].stroke_set = false;
+ } else if (pEmr->lopn.lopnWidth.x) {
+ int cur_level = d->level;
+ d->level = d->emf_obj[index].level;
+ double pen_width = pix_to_size_point( d, pEmr->lopn.lopnWidth.x );
+ d->level = cur_level;
+ d->dc[d->level].style.stroke_width.value = pen_width;
+ } else { // this stroke should always be rendered as 1 pixel wide, independent of zoom level (can that be done in SVG?)
+ //d->dc[d->level].style.stroke_width.value = 1.0;
+ int cur_level = d->level;
+ d->level = d->emf_obj[index].level;
+ double pen_width = pix_to_size_point( d, 1 );
+ d->level = cur_level;
+ d->dc[d->level].style.stroke_width.value = pen_width;
+ }
+
+ double r, g, b;
+ r = SP_COLOR_U_TO_F( U_RGBAGetR(pEmr->lopn.lopnColor) );
+ g = SP_COLOR_U_TO_F( U_RGBAGetG(pEmr->lopn.lopnColor) );
+ b = SP_COLOR_U_TO_F( U_RGBAGetB(pEmr->lopn.lopnColor) );
+ d->dc[d->level].style.stroke.value.color.set( r, g, b );
+}
+
+
+static void
+select_extpen(PEMF_CALLBACK_DATA d, int index)
+{
+ PU_EMREXTCREATEPEN pEmr = NULL;
+
+ if (index >= 0 && index < d->n_obj)
+ pEmr = (PU_EMREXTCREATEPEN) d->emf_obj[index].lpEMFR;
+
+ if (!pEmr)
+ return;
+
+ switch (pEmr->elp.elpPenStyle & U_PS_STYLE_MASK) {
+ case U_PS_USERSTYLE:
+ {
+ if (pEmr->elp.elpNumEntries) {
+ d->dc[d->level].style.stroke_dash.n_dash = pEmr->elp.elpNumEntries;
+ if (d->dc[d->level].style.stroke_dash.dash && (d->level==0 || (d->level>0 && d->dc[d->level].style.stroke_dash.dash!=d->dc[d->level-1].style.stroke_dash.dash)))
+ delete[] d->dc[d->level].style.stroke_dash.dash;
+ d->dc[d->level].style.stroke_dash.dash = new double[pEmr->elp.elpNumEntries];
+ for (unsigned int i=0; ielp.elpNumEntries; i++) {
+ int cur_level = d->level;
+ d->level = d->emf_obj[index].level;
+// Doing it this way typically results in a pattern that is tiny, better to assume the array
+// is the same scale as for dot/dash below, that is, no scaling should be applied
+// double dash_length = pix_to_size_point( d, pEmr->elp.elpStyleEntry[i] );
+ double dash_length = pEmr->elp.elpStyleEntry[i];
+ d->level = cur_level;
+ d->dc[d->level].style.stroke_dash.dash[i] = dash_length;
+ }
+ d->dc[d->level].style.stroke_dasharray_set = 1;
+ } else {
+ d->dc[d->level].style.stroke_dasharray_set = 0;
+ }
+ break;
+ }
+
+ case U_PS_DASH:
+ case U_PS_DOT:
+ case U_PS_DASHDOT:
+ case U_PS_DASHDOTDOT:
+ {
+ int i = 0;
+ int penstyle = (pEmr->elp.elpPenStyle & U_PS_STYLE_MASK);
+ d->dc[d->level].style.stroke_dash.n_dash =
+ penstyle == U_PS_DASHDOTDOT ? 6 : penstyle == U_PS_DASHDOT ? 4 : 2;
+ if (d->dc[d->level].style.stroke_dash.dash && (d->level==0 || (d->level>0 && d->dc[d->level].style.stroke_dash.dash!=d->dc[d->level-1].style.stroke_dash.dash)))
+ delete[] d->dc[d->level].style.stroke_dash.dash;
+ d->dc[d->level].style.stroke_dash.dash = new double[d->dc[d->level].style.stroke_dash.n_dash];
+ if (penstyle==U_PS_DASH || penstyle==U_PS_DASHDOT || penstyle==U_PS_DASHDOTDOT) {
+ d->dc[d->level].style.stroke_dash.dash[i++] = 3;
+ d->dc[d->level].style.stroke_dash.dash[i++] = 2;
+ }
+ if (penstyle==U_PS_DOT || penstyle==U_PS_DASHDOT || penstyle==U_PS_DASHDOTDOT) {
+ d->dc[d->level].style.stroke_dash.dash[i++] = 1;
+ d->dc[d->level].style.stroke_dash.dash[i++] = 2;
+ }
+ if (penstyle==U_PS_DASHDOTDOT) {
+ d->dc[d->level].style.stroke_dash.dash[i++] = 1;
+ d->dc[d->level].style.stroke_dash.dash[i++] = 2;
+ }
+
+ d->dc[d->level].style.stroke_dasharray_set = 1;
+ break;
+ }
+
+ case U_PS_SOLID:
+ default:
+ {
+ d->dc[d->level].style.stroke_dasharray_set = 0;
+ break;
+ }
+ }
+
+ switch (pEmr->elp.elpPenStyle & U_PS_ENDCAP_MASK) {
+ case U_PS_ENDCAP_ROUND:
+ {
+ d->dc[d->level].style.stroke_linecap.computed = 1;
+ break;
+ }
+ case U_PS_ENDCAP_SQUARE:
+ {
+ d->dc[d->level].style.stroke_linecap.computed = 2;
+ break;
+ }
+ case U_PS_ENDCAP_FLAT:
+ default:
+ {
+ d->dc[d->level].style.stroke_linecap.computed = 0;
+ break;
+ }
+ }
+
+ switch (pEmr->elp.elpPenStyle & U_PS_JOIN_MASK) {
+ case U_PS_JOIN_BEVEL:
+ {
+ d->dc[d->level].style.stroke_linejoin.computed = 2;
+ break;
+ }
+ case U_PS_JOIN_MITER:
+ {
+ d->dc[d->level].style.stroke_linejoin.computed = 0;
+ break;
+ }
+ case U_PS_JOIN_ROUND:
+ default:
+ {
+ d->dc[d->level].style.stroke_linejoin.computed = 1;
+ break;
+ }
+ }
+
+ d->dc[d->level].stroke_set = true;
+
+ if (pEmr->elp.elpPenStyle == U_PS_NULL) {
+ d->dc[d->level].style.stroke_width.value = 0;
+ d->dc[d->level].stroke_set = false;
+ } else if (pEmr->elp.elpWidth) {
+ int cur_level = d->level;
+ d->level = d->emf_obj[index].level;
+ double pen_width = pix_to_size_point( d, pEmr->elp.elpWidth );
+ d->level = cur_level;
+ d->dc[d->level].style.stroke_width.value = pen_width;
+ } else { // this stroke should always be rendered as 1 pixel wide, independent of zoom level (can that be done in SVG?)
+ //d->dc[d->level].style.stroke_width.value = 1.0;
+ int cur_level = d->level;
+ d->level = d->emf_obj[index].level;
+ double pen_width = pix_to_size_point( d, 1 );
+ d->level = cur_level;
+ d->dc[d->level].style.stroke_width.value = pen_width;
+ }
+
+ double r, g, b;
+ r = SP_COLOR_U_TO_F( U_RGBAGetR(pEmr->elp.elpColor) );
+ g = SP_COLOR_U_TO_F( U_RGBAGetG(pEmr->elp.elpColor) );
+ b = SP_COLOR_U_TO_F( U_RGBAGetB(pEmr->elp.elpColor) );
+
+ d->dc[d->level].style.stroke.value.color.set( r, g, b );
+}
+
+
+static void
+select_brush(PEMF_CALLBACK_DATA d, int index)
+{
+ PU_EMRCREATEBRUSHINDIRECT pEmr = NULL;
+
+ if (index >= 0 && index < d->n_obj)
+ pEmr = (PU_EMRCREATEBRUSHINDIRECT) d->emf_obj[index].lpEMFR;
+
+ if (!pEmr)return;
+
+ if (pEmr->lb.lbStyle == U_BS_SOLID) {
+ double r, g, b;
+ r = SP_COLOR_U_TO_F( U_RGBAGetR(pEmr->lb.lbColor) );
+ g = SP_COLOR_U_TO_F( U_RGBAGetG(pEmr->lb.lbColor) );
+ b = SP_COLOR_U_TO_F( U_RGBAGetB(pEmr->lb.lbColor) );
+ d->dc[d->level].style.fill.value.color.set( r, g, b );
+ }
+
+ d->dc[d->level].fill_set = true;
+}
+
+
+static void
+select_font(PEMF_CALLBACK_DATA d, int index)
+{
+ PU_EMREXTCREATEFONTINDIRECTW pEmr = NULL;
+
+ if (index >= 0 && index < d->n_obj)
+ pEmr = (PU_EMREXTCREATEFONTINDIRECTW) d->emf_obj[index].lpEMFR;
+
+ if (!pEmr)return;
+
+
+ /* The logfont information always starts with a U_LOGFONT structure but the U_EMREXTCREATEFONTINDIRECTW
+ is defined as U_LOGFONT_PANOSE so it can handle one of those if that is actually present. Currently only logfont
+ is supported, and the remainder, it it really is a U_LOGFONT_PANOSE record, is ignored
+ */
+ int cur_level = d->level;
+ d->level = d->emf_obj[index].level;
+ double font_size = pix_to_size_point( d, pEmr->elfw.elfLogFont.lfHeight );
+ d->level = cur_level;
+ d->dc[d->level].style.font_size.computed = font_size;
+ d->dc[d->level].style.font_weight.value =
+ pEmr->elfw.elfLogFont.lfWeight == U_FW_THIN ? SP_CSS_FONT_WEIGHT_100 :
+ pEmr->elfw.elfLogFont.lfWeight == U_FW_EXTRALIGHT ? SP_CSS_FONT_WEIGHT_200 :
+ pEmr->elfw.elfLogFont.lfWeight == U_FW_LIGHT ? SP_CSS_FONT_WEIGHT_300 :
+ pEmr->elfw.elfLogFont.lfWeight == U_FW_NORMAL ? SP_CSS_FONT_WEIGHT_400 :
+ pEmr->elfw.elfLogFont.lfWeight == U_FW_MEDIUM ? SP_CSS_FONT_WEIGHT_500 :
+ pEmr->elfw.elfLogFont.lfWeight == U_FW_SEMIBOLD ? SP_CSS_FONT_WEIGHT_600 :
+ pEmr->elfw.elfLogFont.lfWeight == U_FW_BOLD ? SP_CSS_FONT_WEIGHT_700 :
+ pEmr->elfw.elfLogFont.lfWeight == U_FW_EXTRABOLD ? SP_CSS_FONT_WEIGHT_800 :
+ pEmr->elfw.elfLogFont.lfWeight == U_FW_HEAVY ? SP_CSS_FONT_WEIGHT_900 :
+ pEmr->elfw.elfLogFont.lfWeight == U_FW_NORMAL ? SP_CSS_FONT_WEIGHT_NORMAL :
+ pEmr->elfw.elfLogFont.lfWeight == U_FW_BOLD ? SP_CSS_FONT_WEIGHT_BOLD :
+ pEmr->elfw.elfLogFont.lfWeight == U_FW_EXTRALIGHT ? SP_CSS_FONT_WEIGHT_LIGHTER :
+ pEmr->elfw.elfLogFont.lfWeight == U_FW_EXTRABOLD ? SP_CSS_FONT_WEIGHT_BOLDER :
+ U_FW_NORMAL;
+ d->dc[d->level].style.font_style.value = (pEmr->elfw.elfLogFont.lfItalic ? SP_CSS_FONT_STYLE_ITALIC : SP_CSS_FONT_STYLE_NORMAL);
+ d->dc[d->level].style.text_decoration.underline = pEmr->elfw.elfLogFont.lfUnderline;
+ d->dc[d->level].style.text_decoration.line_through = pEmr->elfw.elfLogFont.lfStrikeOut;
+ if (d->dc[d->level].tstyle.font_family.value){ free(d->dc[d->level].tstyle.font_family.value); }
+ d->dc[d->level].tstyle.font_family.value =
+ U_Utf16leToUtf8((uint16_t *) (pEmr->elfw.elfLogFont.lfFaceName), U_LF_FACESIZE, NULL);
+ d->dc[d->level].style.baseline_shift.value = ((pEmr->elfw.elfLogFont.lfEscapement + 3600) % 3600) / 10; // use baseline_shift instead of text_transform to avoid overflow
+}
+
+static void
+delete_object(PEMF_CALLBACK_DATA d, int index)
+{
+ if (index >= 0 && index < d->n_obj) {
+ d->emf_obj[index].type = 0;
+// We are keeping a copy of the EMR rather than just a structure. Currently that is not necessary as the entire
+// EMF is read in at once and is stored in a big malloc. However, in past versions it was handled
+// reord by record, and we might need to do that again at some point in the future if we start running into EMF
+// files too big to fit into memory.
+ if (d->emf_obj[index].lpEMFR)
+ free(d->emf_obj[index].lpEMFR);
+ d->emf_obj[index].lpEMFR = NULL;
+ }
+}
+
+
+static void
+insert_object(PEMF_CALLBACK_DATA d, int index, int type, PU_ENHMETARECORD pObj)
+{
+ if (index >= 0 && index < d->n_obj) {
+ delete_object(d, index);
+ d->emf_obj[index].type = type;
+ d->emf_obj[index].level = d->level;
+ d->emf_obj[index].lpEMFR = emr_dup((char *) pObj);
+ }
+}
+
+/**
+ \fn myEnhMetaFileProc(char *contents, unsigned int length, PEMF_CALLBACK_DATA lpData)
+ \param contents binary contents of an EMF file
+ \param length length in bytes of contents
+ \param d Inkscape data structures returned by this call
+*/
+//THis was a callback, just build it into a normal function
+int myEnhMetaFileProc(char *contents, unsigned int length, PEMF_CALLBACK_DATA d)
+{
+ uint32_t off=0;
+ uint32_t emr_mask;
+ int OK =1;
+ PU_ENHMETARECORD lpEMFR;
+
+ while(OK){
+ if(off>=length)return(0); //normally should exit from while after EMREOF sets OK to false.
+
+ lpEMFR = (PU_ENHMETARECORD)(contents + off);
+// std::cout << "record type: " << lpEMFR->iType << " length: " << lpEMFR->nSize << "offset: " << off <nSize;
+
+ SVGOStringStream tmp_outsvg;
+ SVGOStringStream tmp_path;
+ SVGOStringStream tmp_str;
+ SVGOStringStream dbg_str;
+
+ emr_mask = emr_properties(lpEMFR->iType);
+
+/*
+std::cout << "BEFORE DRAW logic d->mask: " << std::hex << d->mask << " emr_mask: " << emr_mask << std::dec << std::endl;
+std::cout << "BEFORE DRAW"
+ << " test1 " << ( d->mask & U_DRAW_FORCE)
+ << " test2 " << (emr_mask & U_DRAW_ALTERS)
+ << " test3 " << (emr_mask & U_DRAW_VISIBLE)
+ << " test4 " << !(d->mask & U_DRAW_ONLYTO)
+ << " test5 " << ((d->mask & U_DRAW_ONLYTO) && !(emr_mask & U_DRAW_ONLYTO) )
+ << std::endl;
+*/
+ if ( (emr_mask != 0xFFFFFFFF) && // next record is valid type
+ (d->mask & U_DRAW_VISIBLE) && // This record is drawable
+ ( (d->mask & U_DRAW_FORCE) || // This draw is forced by STROKE/FILL/STROKEANDFILL PATH
+ (emr_mask & U_DRAW_ALTERS) || // Next record would alter the drawing environment in some way
+ ( (emr_mask & U_DRAW_VISIBLE) // Next record is visible...
+ &&
+ (
+ ( !(d->mask & U_DRAW_ONLYTO) ) // Non *TO records cannot be followed by any Visible
+ ||
+ ((d->mask & U_DRAW_ONLYTO) && !(emr_mask & U_DRAW_ONLYTO) ) // *TO records can only be followed by other *TO records
+ )
+ )
+ )
+ ){
+//std::cout << "PATH DRAW at TOP" << std::endl;
+ *(d->outsvg) += " drawtype){ // explicit draw type EMR record
+ output_style(d, d->drawtype);
+ }
+ else if(d->mask & U_DRAW_CLOSED){ // implicit draw type
+ output_style(d, U_EMR_STROKEANDFILLPATH);
+ }
+ else {
+ output_style(d, U_EMR_STROKEPATH);
+ }
+ *(d->outsvg) += "\n\t";
+ *(d->outsvg) += "\n\td=\""; // this is the ONLY place d=" should be used!!!!
+ *(d->outsvg) += *(d->path);
+ *(d->outsvg) += " \" /> \n";
+ *(d->path) = "";
+ // reset the flags
+ d->mask = 0;
+ d->drawtype = 0;
+ }
+//std::cout << "AFTER DRAW logic d->mask: " << std::hex << d->mask << " emr_mask: " << emr_mask << std::dec << std::endl;
+
+ switch (lpEMFR->iType)
+ {
+ case U_EMR_HEADER:
+ {
+ dbg_str << "\n";
+
+ *(d->outdef) += "\n";
+
+ if (d->pDesc) {
+ *(d->outdef) += "\n";
+ }
+
+ PU_EMRHEADER pEmr = (PU_EMRHEADER) lpEMFR;
+ SVGOStringStream tmp_outdef;
+ tmp_outdef << "\n";
+ *(d->outsvg) = *(d->outdef) + *(d->outsvg);
+ OK=0;
+ break;
+ }
+ case U_EMR_SETPIXELV: dbg_str << "\n"; break;
+ case U_EMR_SETMAPPERFLAGS: dbg_str << "\n"; break;
+ case U_EMR_SETMAPMODE: dbg_str << "\n"; break;
+ case U_EMR_SETBKMODE: dbg_str << "\n"; break;
+ case U_EMR_SETPOLYFILLMODE:
+ {
+ dbg_str << "\n";
+
+ PU_EMRSETPOLYFILLMODE pEmr = (PU_EMRSETPOLYFILLMODE) lpEMFR;
+ d->dc[d->level].style.fill_rule.value =
+ (pEmr->iMode == U_ALTERNATE ? 0 :
+ pEmr->iMode == U_WINDING ? 1 : 0);
+ break;
+ }
+ case U_EMR_SETROP2:
+ {
+ dbg_str << "\n";
+ PU_EMRSETROP2 pEmr = (PU_EMRSETROP2) lpEMFR;
+ d->dwRop2 = pEmr->iMode;
+ break;
+ }
+ case U_EMR_SETSTRETCHBLTMODE:
+ {
+ PU_EMRSETSTRETCHBLTMODE pEmr = (PU_EMRSETSTRETCHBLTMODE) lpEMFR; // from wingdi.h
+ BLTmode = pEmr->iMode;
+ dbg_str << "\n";
+ break;
+ }
+ case U_EMR_SETTEXTALIGN:
+ {
+ dbg_str << "\n";
+
+ PU_EMRSETTEXTALIGN pEmr = (PU_EMRSETTEXTALIGN) lpEMFR;
+ d->dc[d->level].textAlign = pEmr->iMode;
+ break;
+ }
+ case U_EMR_SETCOLORADJUSTMENT:
+ dbg_str << "\n";
+ break;
+ case U_EMR_SETTEXTCOLOR:
+ {
+ dbg_str << "\n";
+
+ PU_EMRSETTEXTCOLOR pEmr = (PU_EMRSETTEXTCOLOR) lpEMFR;
+ d->dc[d->level].textColor = pEmr->crColor;
+ d->dc[d->level].textColorSet = true;
+ break;
+ }
+ case U_EMR_SETBKCOLOR: dbg_str << "\n"; break;
+ case U_EMR_OFFSETCLIPRGN: dbg_str << "\n"; break;
+ case U_EMR_MOVETOEX:
+ {
+ dbg_str << "\n";
+
+ PU_EMRMOVETOEX pEmr = (PU_EMRMOVETOEX) lpEMFR;
+
+ d->mask |= emr_mask;
+
+ d->dc[d->level].cur = pEmr->ptl;
+
+ tmp_path <<
+ "\n\tM " <<
+ pix_to_x_point( d, pEmr->ptl.x, pEmr->ptl.y ) << " " <<
+ pix_to_y_point( d, pEmr->ptl.x, pEmr->ptl.y ) << " ";
+ break;
+ }
+ case U_EMR_SETMETARGN: dbg_str << "\n"; break;
+ case U_EMR_EXCLUDECLIPRECT: dbg_str << "\n"; break;
+ case U_EMR_INTERSECTCLIPRECT:
+ {
+ dbg_str << "\n";
+
+ PU_EMRINTERSECTCLIPRECT pEmr = (PU_EMRINTERSECTCLIPRECT) lpEMFR;
+ U_RECTL rc = pEmr->rclClip;
+ clipset = true;
+ if ((rc.left == rc_old.left) && (rc.top == rc_old.top) && (rc.right == rc_old.right) && (rc.bottom == rc_old.bottom))
+ break;
+ rc_old = rc;
+
+ double l = pix_to_x_point( d, rc.left, rc.top );
+ double t = pix_to_y_point( d, rc.left, rc.top );
+ double r = pix_to_x_point( d, rc.right, rc.bottom );
+ double b = pix_to_y_point( d, rc.right, rc.bottom );
+
+ SVGOStringStream tmp_rectangle;
+ tmp_rectangle << "\nid) << "\" >";
+ tmp_rectangle << "\n";
+ tmp_rectangle << "\n";
+
+ *(d->outdef) += tmp_rectangle.str().c_str();
+ *(d->path) = "";
+ break;
+ }
+ case U_EMR_SCALEVIEWPORTEXTEX: dbg_str << "\n"; break;
+ case U_EMR_SCALEWINDOWEXTEX: dbg_str << "\n"; break;
+ case U_EMR_SAVEDC:
+ dbg_str << "\n";
+
+ if (d->level < EMF_MAX_DC) {
+ d->dc[d->level + 1] = d->dc[d->level];
+ d->level = d->level + 1;
+ }
+ break;
+ case U_EMR_RESTOREDC:
+ {
+ dbg_str << "\n";
+
+ PU_EMRRESTOREDC pEmr = (PU_EMRRESTOREDC) lpEMFR;
+ int old_level = d->level;
+ if (pEmr->iRelative >= 0) {
+ if (pEmr->iRelative < d->level)
+ d->level = pEmr->iRelative;
+ }
+ else {
+ if (d->level + pEmr->iRelative >= 0)
+ d->level = d->level + pEmr->iRelative;
+ }
+ while (old_level > d->level) {
+ if (d->dc[old_level].style.stroke_dash.dash && (old_level==0 || (old_level>0 && d->dc[old_level].style.stroke_dash.dash!=d->dc[old_level-1].style.stroke_dash.dash)))
+ delete[] d->dc[old_level].style.stroke_dash.dash;
+ old_level--;
+ }
+ break;
+ }
+ case U_EMR_SETWORLDTRANSFORM:
+ {
+ dbg_str << "\n";
+
+ PU_EMRSETWORLDTRANSFORM pEmr = (PU_EMRSETWORLDTRANSFORM) lpEMFR;
+ d->dc[d->level].worldTransform = pEmr->xform;
+ break;
+ }
+ case U_EMR_MODIFYWORLDTRANSFORM:
+ {
+ dbg_str << "\n";
+
+ PU_EMRMODIFYWORLDTRANSFORM pEmr = (PU_EMRMODIFYWORLDTRANSFORM) lpEMFR;
+ switch (pEmr->iMode)
+ {
+ case U_MWT_IDENTITY:
+ d->dc[d->level].worldTransform.eM11 = 1.0;
+ d->dc[d->level].worldTransform.eM12 = 0.0;
+ d->dc[d->level].worldTransform.eM21 = 0.0;
+ d->dc[d->level].worldTransform.eM22 = 1.0;
+ d->dc[d->level].worldTransform.eDx = 0.0;
+ d->dc[d->level].worldTransform.eDy = 0.0;
+ break;
+ case U_MWT_LEFTMULTIPLY:
+ {
+// d->dc[d->level].worldTransform = pEmr->xform * worldTransform;
+
+ float a11 = pEmr->xform.eM11;
+ float a12 = pEmr->xform.eM12;
+ float a13 = 0.0;
+ float a21 = pEmr->xform.eM21;
+ float a22 = pEmr->xform.eM22;
+ float a23 = 0.0;
+ float a31 = pEmr->xform.eDx;
+ float a32 = pEmr->xform.eDy;
+ float a33 = 1.0;
+
+ float b11 = d->dc[d->level].worldTransform.eM11;
+ float b12 = d->dc[d->level].worldTransform.eM12;
+ //float b13 = 0.0;
+ float b21 = d->dc[d->level].worldTransform.eM21;
+ float b22 = d->dc[d->level].worldTransform.eM22;
+ //float b23 = 0.0;
+ float b31 = d->dc[d->level].worldTransform.eDx;
+ float b32 = d->dc[d->level].worldTransform.eDy;
+ //float b33 = 1.0;
+
+ float c11 = a11*b11 + a12*b21 + a13*b31;;
+ float c12 = a11*b12 + a12*b22 + a13*b32;;
+ //float c13 = a11*b13 + a12*b23 + a13*b33;;
+ float c21 = a21*b11 + a22*b21 + a23*b31;;
+ float c22 = a21*b12 + a22*b22 + a23*b32;;
+ //float c23 = a21*b13 + a22*b23 + a23*b33;;
+ float c31 = a31*b11 + a32*b21 + a33*b31;;
+ float c32 = a31*b12 + a32*b22 + a33*b32;;
+ //float c33 = a31*b13 + a32*b23 + a33*b33;;
+
+ d->dc[d->level].worldTransform.eM11 = c11;;
+ d->dc[d->level].worldTransform.eM12 = c12;;
+ d->dc[d->level].worldTransform.eM21 = c21;;
+ d->dc[d->level].worldTransform.eM22 = c22;;
+ d->dc[d->level].worldTransform.eDx = c31;
+ d->dc[d->level].worldTransform.eDy = c32;
+
+ break;
+ }
+ case U_MWT_RIGHTMULTIPLY:
+ {
+// d->dc[d->level].worldTransform = worldTransform * pEmr->xform;
+
+ float a11 = d->dc[d->level].worldTransform.eM11;
+ float a12 = d->dc[d->level].worldTransform.eM12;
+ float a13 = 0.0;
+ float a21 = d->dc[d->level].worldTransform.eM21;
+ float a22 = d->dc[d->level].worldTransform.eM22;
+ float a23 = 0.0;
+ float a31 = d->dc[d->level].worldTransform.eDx;
+ float a32 = d->dc[d->level].worldTransform.eDy;
+ float a33 = 1.0;
+
+ float b11 = pEmr->xform.eM11;
+ float b12 = pEmr->xform.eM12;
+ //float b13 = 0.0;
+ float b21 = pEmr->xform.eM21;
+ float b22 = pEmr->xform.eM22;
+ //float b23 = 0.0;
+ float b31 = pEmr->xform.eDx;
+ float b32 = pEmr->xform.eDy;
+ //float b33 = 1.0;
+
+ float c11 = a11*b11 + a12*b21 + a13*b31;;
+ float c12 = a11*b12 + a12*b22 + a13*b32;;
+ //float c13 = a11*b13 + a12*b23 + a13*b33;;
+ float c21 = a21*b11 + a22*b21 + a23*b31;;
+ float c22 = a21*b12 + a22*b22 + a23*b32;;
+ //float c23 = a21*b13 + a22*b23 + a23*b33;;
+ float c31 = a31*b11 + a32*b21 + a33*b31;;
+ float c32 = a31*b12 + a32*b22 + a33*b32;;
+ //float c33 = a31*b13 + a32*b23 + a33*b33;;
+
+ d->dc[d->level].worldTransform.eM11 = c11;;
+ d->dc[d->level].worldTransform.eM12 = c12;;
+ d->dc[d->level].worldTransform.eM21 = c21;;
+ d->dc[d->level].worldTransform.eM22 = c22;;
+ d->dc[d->level].worldTransform.eDx = c31;
+ d->dc[d->level].worldTransform.eDy = c32;
+
+ break;
+ }
+// case MWT_SET:
+ default:
+ d->dc[d->level].worldTransform = pEmr->xform;
+ break;
+ }
+ break;
+ }
+ case U_EMR_SELECTOBJECT:
+ {
+ dbg_str << "\n";
+
+ PU_EMRSELECTOBJECT pEmr = (PU_EMRSELECTOBJECT) lpEMFR;
+ unsigned int index = pEmr->ihObject;
+
+ if (index & U_STOCK_OBJECT) {
+ switch (index) {
+ case U_NULL_BRUSH:
+ d->dc[d->level].fill_set = false;
+ break;
+ case U_BLACK_BRUSH:
+ case U_DKGRAY_BRUSH:
+ case U_GRAY_BRUSH:
+ case U_LTGRAY_BRUSH:
+ case U_WHITE_BRUSH:
+ {
+ float val = 0;
+ switch (index) {
+ case U_BLACK_BRUSH:
+ val = 0.0 / 255.0;
+ break;
+ case U_DKGRAY_BRUSH:
+ val = 64.0 / 255.0;
+ break;
+ case U_GRAY_BRUSH:
+ val = 128.0 / 255.0;
+ break;
+ case U_LTGRAY_BRUSH:
+ val = 192.0 / 255.0;
+ break;
+ case U_WHITE_BRUSH:
+ val = 255.0 / 255.0;
+ break;
+ }
+ d->dc[d->level].style.fill.value.color.set( val, val, val );
+
+ d->dc[d->level].fill_set = true;
+ break;
+ }
+ case U_NULL_PEN:
+ d->dc[d->level].stroke_set = false;
+ break;
+ case U_BLACK_PEN:
+ case U_WHITE_PEN:
+ {
+ float val = index == U_BLACK_PEN ? 0 : 1;
+ d->dc[d->level].style.stroke_dasharray_set = 0;
+ d->dc[d->level].style.stroke_width.value = 1.0;
+ d->dc[d->level].style.stroke.value.color.set( val, val, val );
+
+ d->dc[d->level].stroke_set = true;
+
+ break;
+ }
+ }
+ } else {
+ if ( /*index >= 0 &&*/ index < (unsigned int) d->n_obj) {
+ switch (d->emf_obj[index].type)
+ {
+ case U_EMR_CREATEPEN:
+ select_pen(d, index);
+ break;
+ case U_EMR_CREATEBRUSHINDIRECT:
+ select_brush(d, index);
+ break;
+ case U_EMR_EXTCREATEPEN:
+ select_extpen(d, index);
+ break;
+ case U_EMR_EXTCREATEFONTINDIRECTW:
+ select_font(d, index);
+ break;
+ }
+ }
+ }
+ break;
+ }
+ case U_EMR_CREATEPEN:
+ {
+ dbg_str << "\n";
+
+ PU_EMRCREATEPEN pEmr = (PU_EMRCREATEPEN) lpEMFR;
+ insert_object(d, pEmr->ihPen, U_EMR_CREATEPEN, lpEMFR);
+ break;
+ }
+ case U_EMR_CREATEBRUSHINDIRECT:
+ {
+ dbg_str << "\n";
+
+ PU_EMRCREATEBRUSHINDIRECT pEmr = (PU_EMRCREATEBRUSHINDIRECT) lpEMFR;
+ insert_object(d, pEmr->ihBrush, U_EMR_CREATEBRUSHINDIRECT, lpEMFR);
+ break;
+ }
+ case U_EMR_DELETEOBJECT:
+ dbg_str << "\n";
+ break;
+ case U_EMR_ANGLEARC:
+ dbg_str << "\n";
+ break;
+ case U_EMR_ELLIPSE:
+ {
+ dbg_str << "\n";
+
+ PU_EMRELLIPSE pEmr = (PU_EMRELLIPSE) lpEMFR;
+ U_RECTL rclBox = pEmr->rclBox;
+
+ double l = pix_to_x_point( d, rclBox.left, rclBox.top );
+ double t = pix_to_y_point( d, rclBox.left, rclBox.top );
+ double r = pix_to_x_point( d, rclBox.right, rclBox.bottom );
+ double b = pix_to_y_point( d, rclBox.right, rclBox.bottom );
+
+ double cx = (l + r) / 2.0;
+ double cy = (t + b) / 2.0;
+ double rx = fabs(l - r) / 2.0;
+ double ry = fabs(t - b) / 2.0;
+
+ SVGOStringStream tmp_ellipse;
+ tmp_ellipse << "cx=\"" << cx << "\" ";
+ tmp_ellipse << "cy=\"" << cy << "\" ";
+ tmp_ellipse << "rx=\"" << rx << "\" ";
+ tmp_ellipse << "ry=\"" << ry << "\" ";
+
+ d->mask |= emr_mask;
+ *(d->outsvg) += " iType);
+ *(d->outsvg) += "\n\t";
+ *(d->outsvg) += tmp_ellipse.str().c_str();
+ *(d->outsvg) += "/> \n";
+ *(d->path) = "";
+ break;
+ }
+ case U_EMR_RECTANGLE:
+ {
+ dbg_str << "\n";
+
+ PU_EMRRECTANGLE pEmr = (PU_EMRRECTANGLE) lpEMFR;
+ U_RECTL rc = pEmr->rclBox;
+
+ double l = pix_to_x_point( d, rc.left, rc.top );
+ double t = pix_to_y_point( d, rc.left, rc.top );
+ double r = pix_to_x_point( d, rc.right, rc.bottom );
+ double b = pix_to_y_point( d, rc.right, rc.bottom );
+
+ SVGOStringStream tmp_rectangle;
+ tmp_rectangle << "\n\tM " << l << " " << t << " ";
+ tmp_rectangle << "\n\tL " << r << " " << t << " ";
+ tmp_rectangle << "\n\tL " << r << " " << b << " ";
+ tmp_rectangle << "\n\tL " << l << " " << b << " ";
+ tmp_rectangle << "\n\tz";
+
+ d->mask |= emr_mask;
+
+ tmp_path << tmp_rectangle.str().c_str();
+ break;
+ }
+ case U_EMR_ROUNDRECT:
+ {
+ dbg_str << "\n";
+
+ PU_EMRROUNDRECT pEmr = (PU_EMRROUNDRECT) lpEMFR;
+ U_RECTL rc = pEmr->rclBox;
+ U_SIZEL corner = pEmr->szlCorner;
+ double f = 4.*(sqrt(2) - 1)/3;
+
+ double l = pix_to_x_point(d, rc.left, rc.top);
+ double t = pix_to_y_point(d, rc.left, rc.top);
+ double r = pix_to_x_point(d, rc.right, rc.bottom);
+ double b = pix_to_y_point(d, rc.right, rc.bottom);
+ double cnx = pix_to_size_point(d, corner.cx/2);
+ double cny = pix_to_size_point(d, corner.cy/2);
+
+ SVGOStringStream tmp_rectangle;
+ tmp_rectangle << "\n\tM " << l << ", " << t + cny << " ";
+ tmp_rectangle << "\n\tC " << l << ", " << t + (1-f)*cny << " " << l + (1-f)*cnx << ", " << t << " " << l + cnx << ", " << t << " ";
+ tmp_rectangle << "\n\tL " << r - cnx << ", " << t << " ";
+ tmp_rectangle << "\n\tC " << r - (1-f)*cnx << ", " << t << " " << r << ", " << t + (1-f)*cny << " " << r << ", " << t + cny << " ";
+ tmp_rectangle << "\n\tL " << r << ", " << b - cny << " ";
+ tmp_rectangle << "\n\tC " << r << ", " << b - (1-f)*cny << " " << r - (1-f)*cnx << ", " << b << " " << r - cnx << ", " << b << " ";
+ tmp_rectangle << "\n\tL " << l + cnx << ", " << b << " ";
+ tmp_rectangle << "\n\tC " << l + (1-f)*cnx << ", " << b << " " << l << ", " << b - (1-f)*cny << " " << l << ", " << b - cny << " ";
+ tmp_rectangle << "\n\tz";
+
+ d->mask |= emr_mask;
+
+ tmp_path << tmp_rectangle.str().c_str();
+ break;
+ }
+ case U_EMR_ARC:
+ {
+ dbg_str << "\n";
+ U_PAIRF center,start,end,size;
+ int f1;
+ int f2 = (d->arcdir == U_AD_COUNTERCLOCKWISE ? 0 : 1);
+ if(!emr_arc_points( lpEMFR, &f1, f2, ¢er, &start, &end, &size)){
+ tmp_path << "\n\tM " << pix_to_x_point(d, start.x, start.y) << "," << pix_to_y_point(d, start.x, start.y);
+ tmp_path << " A " << pix_to_x_point(d, size.x, size.y)/2.0 << "," << pix_to_y_point(d, size.x, size.y)/2.0 ;
+ tmp_path << " 0 ";
+ tmp_path << " " << f1 << "," << f2 << " ";
+ tmp_path << pix_to_x_point(d, end.x, end.y) << "," << pix_to_y_point(d, end.x, end.y)<< " ";
+
+ d->mask |= emr_mask;
+ }
+ else {
+ dbg_str << "\n";
+ }
+ break;
+ }
+ case U_EMR_CHORD:
+ {
+ dbg_str << "\n";
+ U_PAIRF center,start,end,size;
+ int f1;
+ int f2 = (d->arcdir == U_AD_COUNTERCLOCKWISE ? 0 : 1);
+ if(!emr_arc_points( lpEMFR, &f1, f2, ¢er, &start, &end, &size)){
+ tmp_path << "\n\tM " << pix_to_x_point(d, start.x, start.y) << "," << pix_to_y_point(d, start.x, start.y);
+ tmp_path << " A " << pix_to_x_point(d, size.x, size.y)/2.0 << "," << pix_to_y_point(d, size.x, size.y)/2.0 ;
+ tmp_path << " 0 ";
+ tmp_path << " " << f1 << "," << f2 << " ";
+ tmp_path << pix_to_x_point(d, end.x, end.y) << "," << pix_to_y_point(d, end.x, end.y);
+ tmp_path << " z ";
+ d->mask |= emr_mask;
+ }
+ else {
+ dbg_str << "\n";
+ }
+ break;
+ }
+ case U_EMR_PIE:
+ {
+ dbg_str << "\n";
+ U_PAIRF center,start,end,size;
+ int f1;
+ int f2 = (d->arcdir == U_AD_COUNTERCLOCKWISE ? 0 : 1);
+ if(!emr_arc_points( lpEMFR, &f1, f2, ¢er, &start, &end, &size)){
+ tmp_path << "\n\tM " << pix_to_x_point(d, center.x, center.y) << "," << pix_to_y_point(d, center.x, center.y);
+ tmp_path << "\n\tL " << pix_to_x_point(d, start.x, start.y) << "," << pix_to_y_point(d, start.x, start.y);
+ tmp_path << " A " << pix_to_x_point(d, size.x, size.y)/2.0 << "," << pix_to_y_point(d, size.x, size.y)/2.0;
+ tmp_path << " 0 ";
+ tmp_path << " " << f1 << "," << f2 << " ";
+ tmp_path << pix_to_x_point(d, end.x, end.y) << "," << pix_to_y_point(d, end.x, end.y);
+ tmp_path << " z ";
+ d->mask |= emr_mask;
+ }
+ else {
+ dbg_str << "\n";
+ }
+ break;
+ }
+ case U_EMR_SELECTPALETTE: dbg_str << "\n"; break;
+ case U_EMR_CREATEPALETTE: dbg_str << "\n"; break;
+ case U_EMR_SETPALETTEENTRIES: dbg_str << "\n"; break;
+ case U_EMR_RESIZEPALETTE: dbg_str << "\n"; break;
+ case U_EMR_REALIZEPALETTE: dbg_str << "\n"; break;
+ case U_EMR_EXTFLOODFILL: dbg_str << "\n"; break;
+ case U_EMR_LINETO:
+ {
+ dbg_str << "\n";
+
+ PU_EMRLINETO pEmr = (PU_EMRLINETO) lpEMFR;
+
+ d->mask |= emr_mask;
+
+ tmp_path <<
+ "\n\tL " <<
+ pix_to_x_point( d, pEmr->ptl.x, pEmr->ptl.y ) << " " <<
+ pix_to_y_point( d, pEmr->ptl.x, pEmr->ptl.y ) << " ";
+ break;
+ }
+ case U_EMR_ARCTO:
+ {
+ dbg_str << "\n";
+ U_PAIRF center,start,end,size;
+ int f1;
+ int f2 = (d->arcdir == U_AD_COUNTERCLOCKWISE ? 0 : 1);
+ if(!emr_arc_points( lpEMFR, &f1, f2, ¢er, &start, &end, &size)){
+ // draw a line from current position to start
+ tmp_path << "\n\tL " << pix_to_x_point(d, start.x, start.y) << "," << pix_to_y_point(d, start.x, start.y);
+ tmp_path << "\n\tM " << pix_to_x_point(d, start.x, start.y) << "," << pix_to_y_point(d, start.x, start.y);
+ tmp_path << " A " << pix_to_x_point(d, size.x, size.y)/2.0 << "," << pix_to_y_point(d, size.x, size.y)/2.0 ;
+ tmp_path << " 0 ";
+ tmp_path << " " << f1 << "," << f2 << " ";
+ tmp_path << pix_to_x_point(d, end.x, end.y) << "," << pix_to_y_point(d, end.x, end.y)<< " ";
+
+ d->mask |= emr_mask;
+ }
+ else {
+ dbg_str << "\n";
+ }
+ break;
+ }
+ case U_EMR_POLYDRAW: dbg_str << "\n"; break;
+ case U_EMR_SETARCDIRECTION:
+ {
+ dbg_str << "\n";
+ PU_EMRSETARCDIRECTION pEmr = (PU_EMRSETARCDIRECTION) lpEMFR;
+ if(d->arcdir == U_AD_CLOCKWISE || d->arcdir == U_AD_COUNTERCLOCKWISE){ // EMF file could be corrupt
+ d->arcdir = pEmr->iArcDirection;
+ }
+ break;
+ }
+ case U_EMR_SETMITERLIMIT:
+ {
+ dbg_str << "\n";
+
+ PU_EMRSETMITERLIMIT pEmr = (PU_EMRSETMITERLIMIT) lpEMFR;
+
+ //The function takes a float but saves a 32 bit int in the U_EMR_SETMITERLIMIT record.
+ float miterlimit = *((int32_t *) &(pEmr->eMiterLimit));
+ d->dc[d->level].style.stroke_miterlimit.value = miterlimit; //ratio, not a pt size
+ if (d->dc[d->level].style.stroke_miterlimit.value < 2)
+ d->dc[d->level].style.stroke_miterlimit.value = 2.0;
+ break;
+ }
+ case U_EMR_BEGINPATH:
+ {
+ dbg_str << "\n";
+ // The next line should never be needed, should have been handled before main switch
+ *(d->path) = "";
+ d->mask |= emr_mask;
+ break;
+ }
+ case U_EMR_ENDPATH:
+ {
+ dbg_str << "\n";
+ d->mask &= (0xFFFFFFFF - U_DRAW_ONLYTO); // clear the OnlyTo bit (it might not have been set), prevents any further path extension
+ break;
+ }
+ case U_EMR_CLOSEFIGURE:
+ {
+ dbg_str << "\n";
+ if(!(d->mask & U_DRAW_CLOSED)){ // EMF could be malformed, with multiple closefigures on one path
+ tmp_path << "\n\tz";
+ d->mask |= U_DRAW_CLOSED;
+ }
+ break;
+ }
+ case U_EMR_FILLPATH:
+ {
+ dbg_str << "\n";
+ if(d->mask & U_DRAW_PATH){ // Operation only effects declared paths
+ if(!(d->mask & U_DRAW_CLOSED)){ // EMF could be malformed, with multiple closefigures on one path
+ tmp_path << "\n\tz";
+ d->mask |= U_DRAW_CLOSED;
+ }
+ d->mask |= emr_mask;
+ d->drawtype = U_EMR_FILLPATH;
+ }
+ break;
+ }
+ case U_EMR_STROKEANDFILLPATH:
+ {
+ dbg_str << "\n";
+ if(d->mask & U_DRAW_PATH){ // Operation only effects declared paths
+ if(!(d->mask & U_DRAW_CLOSED)){ // EMF could be malformed, with multiple closefigures on one path
+ tmp_path << "\n\tz";
+ d->mask |= U_DRAW_CLOSED;
+ }
+ d->mask |= emr_mask;
+ d->drawtype = U_EMR_STROKEANDFILLPATH;
+ }
+ break;
+ }
+ case U_EMR_STROKEPATH:
+ {
+ dbg_str << "\n";
+ if(d->mask & U_DRAW_PATH){ // Operation only effects declared paths
+ d->mask |= emr_mask;
+ d->drawtype = U_EMR_STROKEPATH;
+ }
+ break;
+ }
+ case U_EMR_FLATTENPATH: dbg_str << "\n"; break;
+ case U_EMR_WIDENPATH: dbg_str << "\n"; break;
+ case U_EMR_SELECTCLIPPATH: dbg_str << "\n"; break;
+ case U_EMR_ABORTPATH:
+ {
+ dbg_str << "\n";
+ *(d->path) = "";
+ d->drawtype = 0;
+ break;
+ }
+ case U_EMR_UNDEF69: dbg_str << "\n"; break;
+ case U_EMR_COMMENT:
+ {
+ dbg_str << "\n";
+
+ PU_EMRCOMMENT pEmr = (PU_EMRCOMMENT) lpEMFR;
+
+ char *szTxt = (char *) pEmr->Data;
+
+ for (uint32_t i = 0; i < pEmr->cbData; i++) {
+ if ( *szTxt) {
+ if ( *szTxt >= ' ' && *szTxt < 'z' && *szTxt != '<' && *szTxt != '>' ) {
+ tmp_str << *szTxt;
+ }
+ szTxt++;
+ }
+ }
+
+ if (0 && strlen(tmp_str.str().c_str())) {
+ tmp_outsvg << " \n";
+ }
+
+ break;
+ }
+ case U_EMR_FILLRGN: dbg_str << "\n"; break;
+ case U_EMR_FRAMERGN: dbg_str << "\n"; break;
+ case U_EMR_INVERTRGN: dbg_str << "\n"; break;
+ case U_EMR_PAINTRGN: dbg_str << "\n"; break;
+ case U_EMR_EXTSELECTCLIPRGN:
+ {
+ dbg_str << "\n";
+
+ PU_EMREXTSELECTCLIPRGN pEmr = (PU_EMREXTSELECTCLIPRGN) lpEMFR;
+ if (pEmr->iMode == U_RGN_COPY)
+ clipset = false;
+ break;
+ }
+ case U_EMR_BITBLT:
+ {
+ dbg_str << "\n";
+
+ PU_EMRBITBLT pEmr = (PU_EMRBITBLT) lpEMFR;
+ // Treat all nonImage bitblts as a rectangular write. Definitely not correct, but at
+ // least it leaves objects where the operations should have been.
+ if (!pEmr->cbBmiSrc) {
+ // should be an application of a DIBPATTERNBRUSHPT, use a solid color instead
+ double l = pix_to_x_point( d, pEmr->Dest.x, pEmr->Dest.y);
+ double t = pix_to_y_point( d, pEmr->Dest.x, pEmr->Dest.y);
+ double r = pix_to_x_point( d, pEmr->Dest.x + pEmr->cDest.x, pEmr->Dest.y + pEmr->cDest.y);
+ double b = pix_to_y_point( d, pEmr->Dest.x + pEmr->cDest.x, pEmr->Dest.y + pEmr->cDest.y);
+
+ SVGOStringStream tmp_rectangle;
+ tmp_rectangle << "\n\tM " << l << " " << t << " ";
+ tmp_rectangle << "\n\tL " << r << " " << t << " ";
+ tmp_rectangle << "\n\tL " << r << " " << b << " ";
+ tmp_rectangle << "\n\tL " << l << " " << b << " ";
+ tmp_rectangle << "\n\tz";
+
+ d->mask |= emr_mask;
+ d->dwRop3 = pEmr->dwRop; // we will try to approximate SOME of these
+ d->mask |= U_DRAW_CLOSED; // Bitblit is not really open or closed, but we need it to fill, and this is the flag for that
+
+ tmp_path << tmp_rectangle.str().c_str();
+ }
+ break;
+ }
+ case U_EMR_STRETCHBLT: dbg_str << "\n"; break;
+ case U_EMR_MASKBLT: dbg_str << "\n"; break;
+ case U_EMR_PLGBLT: dbg_str << "\n"; break;
+ case U_EMR_SETDIBITSTODEVICE: dbg_str << "\n"; break;
+ case U_EMR_STRETCHDIBITS:
+ {
+ // Some applications use multiple EMF operations, including multiple STRETCHDIBITS to create
+ // images with transparent regions. PowerPoint does this with rotated images, for instance.
+ // Parsing all of that to derive a single resultant image object is left for a later version
+ // of this code. In the meantime, every STRETCHDIBITS goes directly to an image. The Inkscape
+ // user can sort out transparency later using Gimp, if need be.
+
+ PU_EMRSTRETCHDIBITS pEmr = (PU_EMRSTRETCHDIBITS) lpEMFR;
+ double l = pix_to_x_point( d, pEmr->Dest.x, pEmr->Dest.y );
+ double t = pix_to_y_point( d, pEmr->Dest.x, pEmr->Dest.y );
+ double r = pix_to_x_point( d, pEmr->Dest.x + pEmr->cDest.x, pEmr->Dest.y + pEmr->cDest.y );
+ double b = pix_to_y_point( d, pEmr->Dest.x + pEmr->cDest.x, pEmr->Dest.y + pEmr->cDest.y );
+ SVGOStringStream tmp_image;
+ tmp_image << " y=\"" << t << "\"\n x=\"" << l <<"\"\n ";
+
+ // The image ID is filled in much later when tmp_image is converted
+
+ tmp_image << " xlink:href=\"data:image/png;base64,";
+
+ MEMPNG mempng; // PNG in memory comes back in this
+ mempng.buffer = NULL;
+
+ char *rgba_px=NULL; // RGBA pixels
+ char *px=NULL; // DIB pixels
+ uint32_t width, height, colortype, numCt, invert;
+ PU_RGBQUAD ct = NULL;
+ if(!pEmr->cbBitsSrc ||
+ !pEmr->cbBmiSrc ||
+ (pEmr->iUsageSrc != U_DIB_RGB_COLORS) ||
+ !get_DIB_params( // this returns pointers and values, but allocates no memory
+ pEmr,
+ pEmr->offBitsSrc,
+ pEmr->offBmiSrc,
+ &px,
+ &ct,
+ &numCt,
+ &width,
+ &height,
+ &colortype,
+ &invert
+ )){
+
+ if(!DIB_to_RGBA(
+ px, // DIB pixel array
+ ct, // DIB color table
+ numCt, // DIB color table number of entries
+ &rgba_px, // U_RGBA pixel array (32 bits), created by this routine, caller must free.
+ width, // Width of pixel array
+ height, // Height of pixel array
+ colortype, // DIB BitCount Enumeration
+ numCt, // Color table used if not 0
+ invert // If DIB rows are in opposite order from RGBA rows
+ ) &&
+ rgba_px)
+ {
+ toPNG( // Get the image from the RGBA px into mempng
+ &mempng,
+ width, height,
+ rgba_px,
+ 4 * width * height);
+ free(rgba_px);
+ }
+ }
+ if(mempng.buffer){
+ gchar *base64String = g_base64_encode((guchar*) mempng.buffer, mempng.size );
+ free(mempng.buffer);
+ tmp_image << base64String ;
+ g_free(base64String);
+ }
+ else {
+ // insert a random 3x4 blotch otherwise
+ tmp_image << "iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAIAAAA7ljmRAAAAA3NCSVQICAjb4U/gAAAALElEQVQImQXBQQ2AMAAAsUJQMSWI2H8qME1yMshojwrvGB8XcHKvR1XtOTc/8HENumHCsOMAAAAASUVORK5CYII=";
+ }
+
+ tmp_image << "\"\n height=\"" << b-t+1 << "\"\n width=\"" << r-l+1 << "\"\n";
+
+ *(d->outsvg) += "\n\t outsvg) += tmp_image.str().c_str();
+ *(d->outsvg) += "/> \n";
+ *(d->path) = "";
+
+ dbg_str << "\n";
+ break;
+ }
+ case U_EMR_EXTCREATEFONTINDIRECTW:
+ {
+ dbg_str << "\n";
+
+ PU_EMREXTCREATEFONTINDIRECTW pEmr = (PU_EMREXTCREATEFONTINDIRECTW) lpEMFR;
+ insert_object(d, pEmr->ihFont, U_EMR_EXTCREATEFONTINDIRECTW, lpEMFR);
+ break;
+ }
+ case U_EMR_EXTTEXTOUTA:
+ case U_EMR_EXTTEXTOUTW:
+ case U_EMR_SMALLTEXTOUT:
+ {
+ dbg_str << "\n";
+
+ PU_EMREXTTEXTOUTW pEmr = (PU_EMREXTTEXTOUTW) lpEMFR;
+ PU_EMRSMALLTEXTOUT pEmrS = (PU_EMRSMALLTEXTOUT) lpEMFR;
+
+ double x1,y1;
+ int roff = sizeof(U_EMRSMALLTEXTOUT); //offset to the start of the variable fields, only used with U_EMR_SMALLTEXTOUT
+ int cChars;
+ if(lpEMFR->iType==U_EMR_SMALLTEXTOUT){
+ x1 = pEmrS->Dest.x;
+ y1 = pEmrS->Dest.y;
+ cChars = pEmrS->cChars;
+ if(!(pEmrS->fuOptions & U_ETO_NO_RECT)){ roff += sizeof(U_RECTL); }
+ }
+ else {
+ x1 = pEmr->emrtext.ptlReference.x;
+ y1 = pEmr->emrtext.ptlReference.y;
+ cChars = 0;
+ }
+
+ if (d->dc[d->level].textAlign & U_TA_UPDATECP) {
+ x1 = d->dc[d->level].cur.x;
+ y1 = d->dc[d->level].cur.y;
+ }
+
+ double x = pix_to_x_point(d, x1, y1);
+ double y = pix_to_y_point(d, x1, y1);
+
+ double dfact;
+ if (d->dc[d->level].textAlign & U_TA_BASEBIT){ dfact = 0.00; } // alignments 0x10 to U_TA_BASELINE 0x18
+ else if(d->dc[d->level].textAlign & U_TA_BOTTOM){ dfact = -0.35; } // alignments U_TA_BOTTOM 0x08 to 0x0E, factor is approximate
+ else { dfact = 0.85; } // alignments U_TA_TOP 0x00 to 0x07, factor is approximate
+ if (d->dc[d->level].style.baseline_shift.value) {
+ x += dfact * std::sin(d->dc[d->level].style.baseline_shift.value*M_PI/180.0)*fabs(d->dc[d->level].style.font_size.computed);
+ y += dfact * std::cos(d->dc[d->level].style.baseline_shift.value*M_PI/180.0)*fabs(d->dc[d->level].style.font_size.computed);
+ }
+ else {
+ y += dfact * fabs(d->dc[d->level].style.font_size.computed);
+ }
+
+ wchar_t *dup_wt = NULL;
+
+ if(sizeof(wchar_t)==2){ // Windows
+ if( lpEMFR->iType==U_EMR_EXTTEXTOUTA){
+ dup_wt = (wchar_t *) U_Utf8ToUtf16le((char *) pEmr + pEmr->emrtext.offString, pEmr->emrtext.nChars, NULL);
+ }
+ else if( lpEMFR->iType==U_EMR_EXTTEXTOUTW){
+ dup_wt = (wchar_t *) calloc(2*(1 + pEmr->emrtext.nChars),1); // So the string will pick up a terminator
+ memcpy(dup_wt,((char *)pEmr + pEmr->emrtext.offString),2*pEmr->emrtext.nChars);
+ }
+ else { // U_EMR_SMALLTEXTOUT
+ if(pEmrS->fuOptions & U_ETO_SMALL_CHARS){
+ dup_wt = (wchar_t *) U_Utf8ToUtf16le((char *) pEmrS + roff, cChars, NULL);
+ }
+ else {
+ dup_wt = (wchar_t *) calloc(2*(1 + cChars),1); // So the string will pick up a terminator
+ memcpy(dup_wt,(char *) pEmrS + roff, 2 * cChars);
+ }
+ }
+ }
+ else { // Linux or Mac
+ if( lpEMFR->iType==U_EMR_EXTTEXTOUTA){
+ dup_wt = (wchar_t *) U_Utf8ToUtf32le((char *) pEmr + pEmr->emrtext.offString, pEmr->emrtext.nChars, NULL);
+ }
+ else if( lpEMFR->iType==U_EMR_EXTTEXTOUTW){
+ dup_wt = (wchar_t *) U_Utf16leToUtf32le((uint16_t *)((char *) pEmr + pEmr->emrtext.offString), pEmr->emrtext.nChars, NULL);
+ }
+ else { // U_ERM_SMALLTEXTOUT
+ if(pEmrS->fuOptions & U_ETO_SMALL_CHARS){
+ dup_wt = (wchar_t *) U_Utf8ToUtf32le((char *) pEmrS + roff, cChars, NULL);
+ }
+ else {
+ dup_wt = (wchar_t *) U_Utf16leToUtf32le((uint16_t *)((char *) pEmrS + roff), cChars, NULL);
+ }
+ }
+ }
+
+
+ msdepua(dup_wt); //convert everything in Microsoft's private use area. For Symbol, Wingdings, Dingbats
+
+ if(NonToUnicode(dup_wt, d->dc[d->level].tstyle.font_family.value)){
+ g_free(d->dc[d->level].tstyle.font_family.value);
+ d->dc[d->level].tstyle.font_family.value = g_strdup("Times New Roman");
+ }
+
+ char *ansi_text;
+ if(sizeof(wchar_t)==sizeof(uint16_t)){ // Windows
+ ansi_text = (char *) U_Utf16leToUtf8((uint16_t *)dup_wt, 0, NULL);
+ }
+ else { // Linux or Mac
+ ansi_text = (char *) U_Utf32leToUtf8((uint32_t *)dup_wt, 0, NULL);
+ }
+ free(dup_wt);
+
+ if (ansi_text) {
+// gchar *p = ansi_text;
+// while (*p) {
+// if (*p < 32 || *p >= 127) {
+// g_free(ansi_text);
+// ansi_text = g_strdup("");
+// break;
+// }
+// p++;
+// }
+
+ SVGOStringStream ts;
+
+ gchar *escaped_text = g_markup_escape_text(ansi_text, -1);
+
+// float text_rgb[3];
+// sp_color_get_rgb_floatv( &(d->dc[d->level].style.fill.value.color), text_rgb );
+
+// if (!d->dc[d->level].textColorSet) {
+// d->dc[d->level].textColor = RGB(SP_COLOR_F_TO_U(text_rgb[0]),
+// SP_COLOR_F_TO_U(text_rgb[1]),
+// SP_COLOR_F_TO_U(text_rgb[2]));
+// }
+
+ char tmp[128];
+ snprintf(tmp, 127,
+ "fill:#%02x%02x%02x;",
+ U_RGBAGetR(d->dc[d->level].textColor),
+ U_RGBAGetG(d->dc[d->level].textColor),
+ U_RGBAGetB(d->dc[d->level].textColor));
+
+ bool i = (d->dc[d->level].style.font_style.value == SP_CSS_FONT_STYLE_ITALIC);
+ //bool o = (d->dc[d->level].style.font_style.value == SP_CSS_FONT_STYLE_OBLIQUE);
+ bool b = (d->dc[d->level].style.font_weight.value == SP_CSS_FONT_WEIGHT_BOLD) ||
+ (d->dc[d->level].style.font_weight.value >= SP_CSS_FONT_WEIGHT_500 && d->dc[d->level].style.font_weight.value <= SP_CSS_FONT_WEIGHT_900);
+ // EMF textalignment is a bit strange: 0x6 is center, 0x2 is right, 0x0 is left, the value 0x4 is also drawn left
+ int lcr = ((d->dc[d->level].textAlign & U_TA_CENTER) == U_TA_CENTER) ? 2 : ((d->dc[d->level].textAlign & U_TA_CENTER) == U_TA_LEFT) ? 0 : 1;
+
+ ts << " id++) << "\"\n";
+ ts << " xml:space=\"preserve\"\n";
+ ts << " x=\"" << x << "\"\n";
+ ts << " y=\"" << y << "\"\n";
+ if (d->dc[d->level].style.baseline_shift.value) {
+ ts << " transform=\""
+ << "rotate(-" << d->dc[d->level].style.baseline_shift.value
+ << " " << x << " " << y << ")"
+ << "\"\n";
+ }
+ ts << " style=\""
+ << "font-size:" << fabs(d->dc[d->level].style.font_size.computed) << "px;"
+ << tmp
+ << "font-style:" << (i ? "italic" : "normal") << ";"
+ << "font-weight:" << (b ? "bold" : "normal") << ";"
+ << "text-align:" << (lcr==2 ? "center" : lcr==1 ? "end" : "start") << ";"
+ << "text-anchor:" << (lcr==2 ? "middle" : lcr==1 ? "end" : "start") << ";"
+ << "font-family:" << d->dc[d->level].tstyle.font_family.value << ";"
+ << "\"\n";
+ ts << " >";
+ ts << escaped_text;
+ ts << "\n";
+
+ *(d->outsvg) += ts.str().c_str();
+
+ g_free(escaped_text);
+ free(ansi_text);
+ }
+
+ break;
+ }
+ case U_EMR_POLYBEZIER16:
+ {
+ dbg_str << "\n";
+
+ PU_EMRPOLYBEZIER16 pEmr = (PU_EMRPOLYBEZIER16) lpEMFR;
+ PU_POINT16 apts = (PU_POINT16) pEmr->apts; // Bug in MinGW wingdi.h ?
+ uint32_t i,j;
+
+ if (pEmr->cpts<4)
+ break;
+
+ d->mask |= emr_mask;
+
+ tmp_str <<
+ "\n\tM " <<
+ pix_to_x_point( d, apts[0].x, apts[0].y ) << " " <<
+ pix_to_y_point( d, apts[0].x, apts[0].y ) << " ";
+
+ for (i=1; icpts; ) {
+ tmp_str << "\n\tC ";
+ for (j=0; j<3 && icpts; j++,i++) {
+ tmp_str <<
+ pix_to_x_point( d, apts[i].x, apts[i].y ) << " " <<
+ pix_to_y_point( d, apts[i].x, apts[i].y ) << " ";
+ }
+ }
+
+ tmp_path << tmp_str.str().c_str();
+
+ break;
+ }
+ case U_EMR_POLYGON16:
+ {
+ dbg_str << "\n";
+
+ PU_EMRPOLYGON16 pEmr = (PU_EMRPOLYGON16) lpEMFR;
+ PU_POINT16 apts = (PU_POINT16) pEmr->apts; // Bug in MinGW wingdi.h ?
+ SVGOStringStream tmp_poly;
+ unsigned int i;
+ unsigned int first = 0;
+
+ d->mask |= emr_mask;
+
+ // skip the first point?
+ tmp_poly << "\n\tM " <<
+ pix_to_x_point( d, apts[first].x, apts[first].y ) << " " <<
+ pix_to_y_point( d, apts[first].x, apts[first].y ) << " ";
+
+ for (i=first+1; icpts; i++) {
+ tmp_poly << "\n\tL " <<
+ pix_to_x_point( d, apts[i].x, apts[i].y ) << " " <<
+ pix_to_y_point( d, apts[i].x, apts[i].y ) << " ";
+ }
+
+ tmp_path << tmp_poly.str().c_str();
+ tmp_path << "\n\tz";
+ d->mask |= U_DRAW_CLOSED;
+
+ break;
+ }
+ case U_EMR_POLYLINE16:
+ {
+ dbg_str << "\n";
+
+ PU_EMRPOLYLINE16 pEmr = (PU_EMRPOLYLINE16) lpEMFR;
+ PU_POINT16 apts = (PU_POINT16) pEmr->apts; // Bug in MinGW wingdi.h ?
+ uint32_t i;
+
+ if (pEmr->cpts<2)
+ break;
+
+ d->mask |= emr_mask;
+
+ tmp_str <<
+ "\n\tM " <<
+ pix_to_x_point( d, apts[0].x, apts[0].y ) << " " <<
+ pix_to_y_point( d, apts[0].x, apts[0].y ) << " ";
+
+ for (i=1; icpts; i++) {
+ tmp_str <<
+ "\n\tL " <<
+ pix_to_x_point( d, apts[i].x, apts[i].y ) << " " <<
+ pix_to_y_point( d, apts[i].x, apts[i].y ) << " ";
+ }
+
+ tmp_path << tmp_str.str().c_str();
+
+ break;
+ }
+ case U_EMR_POLYBEZIERTO16:
+ {
+ dbg_str << "\n";
+
+ PU_EMRPOLYBEZIERTO16 pEmr = (PU_EMRPOLYBEZIERTO16) lpEMFR;
+ PU_POINT16 apts = (PU_POINT16) pEmr->apts; // Bug in MinGW wingdi.h ?
+ uint32_t i,j;
+
+ d->mask |= emr_mask;
+
+ for (i=0; icpts;) {
+ tmp_path << "\n\tC ";
+ for (j=0; j<3 && icpts; j++,i++) {
+ tmp_path <<
+ pix_to_x_point( d, apts[i].x, apts[i].y ) << " " <<
+ pix_to_y_point( d, apts[i].x, apts[i].y ) << " ";
+ }
+ }
+
+ break;
+ }
+ case U_EMR_POLYLINETO16:
+ {
+ dbg_str << "\n";
+
+ PU_EMRPOLYLINETO16 pEmr = (PU_EMRPOLYLINETO16) lpEMFR;
+ PU_POINT16 apts = (PU_POINT16) pEmr->apts; // Bug in MinGW wingdi.h ?
+ uint32_t i;
+
+ d->mask |= emr_mask;
+
+ for (i=0; icpts;i++) {
+ tmp_path <<
+ "\n\tL " <<
+ pix_to_x_point( d, apts[i].x, apts[i].y ) << " " <<
+ pix_to_y_point( d, apts[i].x, apts[i].y ) << " ";
+ }
+
+ break;
+ }
+ case U_EMR_POLYPOLYLINE16:
+ case U_EMR_POLYPOLYGON16:
+ {
+ if (lpEMFR->iType == U_EMR_POLYPOLYLINE16)
+ dbg_str << "\n";
+ if (lpEMFR->iType == U_EMR_POLYPOLYGON16)
+ dbg_str << "\n";
+
+ PU_EMRPOLYPOLYGON16 pEmr = (PU_EMRPOLYPOLYGON16) lpEMFR;
+ unsigned int n, i, j;
+
+ d->mask |= emr_mask;
+
+ PU_POINT16 apts = (PU_POINT16) &pEmr->aPolyCounts[pEmr->nPolys];
+
+ i = 0;
+ for (n=0; nnPolys && icpts; n++) {
+ SVGOStringStream poly_path;
+
+ poly_path << "\n\tM " <<
+ pix_to_x_point( d, apts[i].x, apts[i].y ) << " " <<
+ pix_to_y_point( d, apts[i].x, apts[i].y ) << " ";
+ i++;
+
+ for (j=1; jaPolyCounts[n] && icpts; j++) {
+ poly_path << "\n\tL " <<
+ pix_to_x_point( d, apts[i].x, apts[i].y ) << " " <<
+ pix_to_y_point( d, apts[i].x, apts[i].y ) << " ";
+ i++;
+ }
+
+ tmp_str << poly_path.str().c_str();
+ if (lpEMFR->iType == U_EMR_POLYPOLYGON16)
+ tmp_str << " z";
+ tmp_str << " \n";
+ }
+
+ tmp_path << tmp_str.str().c_str();
+
+ break;
+ }
+ case U_EMR_POLYDRAW16: dbg_str << "\n"; break;
+ case U_EMR_CREATEMONOBRUSH: dbg_str << "\n"; break;
+ case U_EMR_CREATEDIBPATTERNBRUSHPT:
+ {
+ dbg_str << "\n";
+
+ PU_EMRCREATEDIBPATTERNBRUSHPT pEmr = (PU_EMRCREATEDIBPATTERNBRUSHPT) lpEMFR;
+ insert_object(d, pEmr->ihBrush, U_EMR_CREATEDIBPATTERNBRUSHPT, lpEMFR);
+ break;
+ }
+ case U_EMR_EXTCREATEPEN:
+ {
+ dbg_str << "\n";
+
+ PU_EMREXTCREATEPEN pEmr = (PU_EMREXTCREATEPEN) lpEMFR;
+ insert_object(d, pEmr->ihPen, U_EMR_EXTCREATEPEN, lpEMFR);
+ break;
+ }
+ case U_EMR_POLYTEXTOUTA: dbg_str << "\n"; break;
+ case U_EMR_POLYTEXTOUTW: dbg_str << "\n"; break;
+ case U_EMR_SETICMMODE:
+ {
+ dbg_str << "\n";
+#if 0
+ PU_EMRENABLEICM pEmr = (PU_EMRENABLEICM) lpEMFR;
+ ICMmode= pEmr->iMode;
+#endif //0
+ break;
+ }
+ case U_EMR_CREATECOLORSPACE: dbg_str << "\n"; break;
+ case U_EMR_SETCOLORSPACE: dbg_str << "\n"; break;
+ case U_EMR_DELETECOLORSPACE: dbg_str << "\n"; break;
+ case U_EMR_GLSRECORD: dbg_str << "\n"; break;
+ case U_EMR_GLSBOUNDEDRECORD: dbg_str << "\n"; break;
+ case U_EMR_PIXELFORMAT: dbg_str << "\n"; break;
+ case U_EMR_DRAWESCAPE: dbg_str << "\n"; break;
+ case U_EMR_EXTESCAPE: dbg_str << "\n"; break;
+ case U_EMR_UNDEF107: dbg_str << "\n"; break;
+ // U_EMR_SMALLTEXTOUT is handled with U_EMR_EXTTEXTOUTA/W above
+ case U_EMR_FORCEUFIMAPPING: dbg_str << "\n"; break;
+ case U_EMR_NAMEDESCAPE: dbg_str << "\n"; break;
+ case U_EMR_COLORCORRECTPALETTE: dbg_str << "\n"; break;
+ case U_EMR_SETICMPROFILEA: dbg_str << "\n"; break;
+ case U_EMR_SETICMPROFILEW: dbg_str << "\n"; break;
+ case U_EMR_ALPHABLEND: dbg_str << "\n"; break;
+ case U_EMR_SETLAYOUT: dbg_str << "\n"; break;
+ case U_EMR_TRANSPARENTBLT: dbg_str << "\n"; break;
+ case U_EMR_UNDEF117: dbg_str << "\n"; break;
+ case U_EMR_GRADIENTFILL: dbg_str << "\n"; break;
+ case U_EMR_SETLINKEDUFIS: dbg_str << "\n"; break;
+ case U_EMR_SETTEXTJUSTIFICATION: dbg_str << "\n"; break;
+ case U_EMR_COLORMATCHTOTARGETW: dbg_str << "\n"; break;
+ case U_EMR_CREATECOLORSPACEW: dbg_str << "\n"; break;
+ default:
+ dbg_str << "\n";
+ break;
+ } //end of switch
+// When testing, uncomment the following to place a comment for each processed EMR record in the SVG
+// *(d->outsvg) += dbg_str.str().c_str();
+ *(d->outsvg) += tmp_outsvg.str().c_str();
+ *(d->path) += tmp_path.str().c_str();
+
+ } //end of while
+// When testing, uncomment the following to show the final SVG derived from the EMF
+//std::cout << *(d->outsvg) << std::endl;
+
+ return 1;
+}
+
+
+// Aldus Placeable Header ===================================================
+// Since we are a 32bit app, we have to be sure this structure compiles to
+// be identical to a 16 bit app's version. To do this, we use the #pragma
+// to adjust packing, we use a uint16_t for the hmf handle, and a SMALL_RECT
+// for the bbox rectangle.
+#pragma pack( push )
+#pragma pack( 2 )
+typedef struct _SMALL_RECT {
+ int16_t Left;
+ int16_t Top;
+ int16_t Right;
+ int16_t Bottom;
+} SMALL_RECT, *PSMALL_RECT;
+typedef struct
+{
+ uint32_t dwKey;
+ uint16_t hmf;
+ SMALL_RECT bbox;
+ uint16_t wInch;
+ uint32_t dwReserved;
+ uint16_t wCheckSum;
+} APMHEADER, *PAPMHEADER;
+#pragma pack( pop )
+
+
+SPDocument *
+Emf::open( Inkscape::Extension::Input * /*mod*/, const gchar *uri )
+{
+ EMF_CALLBACK_DATA d;
+
+ memset(&d, 0, sizeof(d));
+
+ d.dc[0].worldTransform.eM11 = 1.0;
+ d.dc[0].worldTransform.eM12 = 0.0;
+ d.dc[0].worldTransform.eM21 = 0.0;
+ d.dc[0].worldTransform.eM22 = 1.0;
+ d.dc[0].worldTransform.eDx = 0.0;
+ d.dc[0].worldTransform.eDy = 0.0;
+
+ if (uri == NULL) {
+ return NULL;
+ }
+
+ d.outsvg = new Glib::ustring("");
+ d.path = new Glib::ustring("");
+ d.outdef = new Glib::ustring("");
+ d.mask = 0;
+ d.drawtype = 0;
+ d.arcdir = U_AD_COUNTERCLOCKWISE;
+ d.dwRop2 = U_R2_COPYPEN;
+ d.dwRop3 = 0;
+
+ size_t length;
+ char *contents;
+ if(emf_readdata(uri, &contents, &length))return(NULL);
+
+ d.pDesc = NULL;
+
+
+ (void) myEnhMetaFileProc(contents,length, &d);
+ free(contents);
+
+
+ if (d.pDesc)
+ free( d.pDesc );
+
+// std::cout << "SVG Output: " << std::endl << *(d.outsvg) << std::endl;
+
+ SPDocument *doc = SPDocument::createNewDocFromMem(d.outsvg->c_str(), strlen(d.outsvg->c_str()), TRUE);
+
+ delete d.outsvg;
+ delete d.path;
+ delete d.outdef;
+
+ if (d.emf_obj) {
+ int i;
+ for (i=0; i\n"
+ "" N_("EMF Input") "\n"
+ "org.inkscape.input.emf\n"
+ "\n"
+ ".emf\n"
+ "image/x-emf\n"
+ "" N_("Enhanced Metafiles (*.emf)") "\n"
+ "" N_("Enhanced Metafiles") "\n"
+ "org.inkscape.output.emf\n"
+ "\n"
+ "", new Emf());
+
+ /* EMF out */
+ Inkscape::Extension::build_from_mem(
+ "\n"
+ "" N_("EMF Output") "\n"
+ "org.inkscape.output.emf\n"
+ "true\n"
+ "true\n"
+ "true\n"
+ "true\n"
+ "false\n"
+ "false\n"
+ "\n"
+ "", new Emf());
+
+ return;
+}
+
+
+} } } /* namespace Inkscape, Extension, Implementation */
+
+/*
+ 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 -rNu3 src/extension/internal/emf-inout.h src/extension/internal/emf-inout.h
--- src/extension/internal/emf-inout.h 1969-12-31 16:00:00.000000000 -0800
+++ src/extension/internal/emf-inout.h 2012-08-07 12:44:25.000000000 -0700
@@ -0,0 +1,55 @@
+/** @file
+ * @brief Enhanced Metafile Input/Output
+ */
+/* Authors:
+ * Ulf Erikson
+ *
+ * Copyright (C) 2006-2008 Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+#ifndef SEEN_EXTENSION_INTERNAL_EMF_H
+#define SEEN_EXTENSION_INTERNAL_EMF_H
+
+#include "extension/implementation/implementation.h"
+
+namespace Inkscape {
+namespace Extension {
+namespace Internal {
+
+class Emf : Inkscape::Extension::Implementation::Implementation { //This is a derived class
+
+public:
+ Emf(); // Empty constructor
+
+ virtual ~Emf();//Destructor
+
+ bool check(Inkscape::Extension::Extension *module); //Can this module load (always yes for now)
+
+ void save(Inkscape::Extension::Output *mod, // Save the given document to the given filename
+ SPDocument *doc,
+ gchar const *filename);
+
+ virtual SPDocument *open( Inkscape::Extension::Input *mod,
+ const gchar *uri );
+
+ static void init(void);//Initialize the class
+
+private:
+};
+
+} } } /* namespace Inkscape, Extension, Implementation */
+
+
+#endif /* EXTENSION_INTERNAL_EMF_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 -rNu3 src/extension/internal/emf-print.cpp src/extension/internal/emf-print.cpp
--- src/extension/internal/emf-print.cpp 1969-12-31 16:00:00.000000000 -0800
+++ src/extension/internal/emf-print.cpp 2012-08-07 12:44:32.000000000 -0700
@@ -0,0 +1,1420 @@
+/** @file
+ * @brief Enhanced Metafile printing
+ */
+/* Authors:
+ * Ulf Erikson
+ * Jon A. Cruz
+ * Abhishek Sharma
+ * David Mathog
+ *
+ * Copyright (C) 2006-2009 Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+/*
+ * References:
+ * - How to Create & Play Enhanced Metafiles in Win32
+ * http://support.microsoft.com/kb/q145999/
+ * - INFO: Windows Metafile Functions & Aldus Placeable Metafiles
+ * http://support.microsoft.com/kb/q66949/
+ * - Metafile Functions
+ * http://msdn.microsoft.com/library/en-us/gdi/metafile_0whf.asp
+ * - Metafile Structures
+ * http://msdn.microsoft.com/library/en-us/gdi/metafile_5hkj.asp
+ */
+
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+
+#include <2geom/pathvector.h>
+#include <2geom/rect.h>
+#include <2geom/bezier-curve.h>
+#include <2geom/hvlinesegment.h>
+#include "helper/geom.h"
+#include "helper/geom-curves.h"
+#include "sp-item.h"
+
+#include "style.h"
+#include "inkscape-version.h"
+#include "sp-root.h"
+
+#include "emf-print.h"
+
+#include "unit-constants.h"
+
+#include "extension/system.h"
+#include "extension/print.h"
+#include "document.h"
+#include "path-prefix.h"
+#include
+extern "C" {
+#include "libunicode-convert/unicode-convert.h"
+}
+
+
+namespace Inkscape {
+namespace Extension {
+namespace Internal {
+
+
+struct FFNEXUS {
+ char *fontname; //Font name
+ FFNEXUS *next; //link to next nexus, NULL if this is the last
+ double f1; //Vertical (rotating) offset factor (* font height)
+ double f2; //Vertical (nonrotating) offset factor (* font height)
+ double f3; //Horizontal (nonrotating) offset factor (* font height)
+ };
+
+
+static float PX2WORLD = 20.0f;
+static U_XFORM worldTransform;
+static bool FixPPT1;
+static FFNEXUS *short_fflist=NULL; //only those fonts so far encountered
+static FFNEXUS *long_fflist=NULL; //all the fonts described in ...\share\extensions\fontfix.conf
+static EMFTRACK* et = NULL;
+static EMFHANDLES* eht = NULL;
+
+void read_system_fflist(void){ //this is not called by any other source files
+FFNEXUS *temp=NULL;
+FFNEXUS *ptr=NULL;
+std::fstream fffile;
+std::string instr;
+char fontname[128];
+double f1,f2,f3;
+std::string path_to_ffconf;
+
+ if(long_fflist)return;
+ path_to_ffconf=INKSCAPE_EXTENSIONDIR;
+#ifdef WIN32
+ path_to_ffconf.append("\\fontfix.conf"); //Windows path syntax
+#else
+ path_to_ffconf.append("/fontfix.conf"); //Unix/linx path syntax
+#endif
+ //open the input
+ fffile.open(path_to_ffconf.c_str(), std::ios::in);
+ if(!fffile.is_open()){
+ g_message("Unable to open file: %s\n", path_to_ffconf.c_str());
+ throw "boom";
+ }
+ while (std::getline(fffile,instr)){
+ if(instr[0]=='#')continue;
+ // not a comment, get the 4 values from the line
+ int elements=sscanf(instr.c_str(),"%lf %lf %lf %[^\n]",&f1,&f2,&f3, &fontname[0]);
+ if(elements!=4){
+ g_message("Expected \"f1 f2 f3 Fontname\" but did not find it in file: %s\n", path_to_ffconf.c_str());
+ throw "boom";
+ }
+ temp=(FFNEXUS *) calloc(1,sizeof(FFNEXUS)); //This will never be freed
+ temp->f1=f1;
+ temp->f2=f2;
+ temp->f3=f3;
+ temp->fontname=strdup(fontname);
+ temp->next=NULL; //just to be explicit, it is already 0
+ if(ptr){
+ ptr->next=temp;
+ ptr=temp;
+ }
+ else {
+ long_fflist=ptr=temp;
+ }
+ }
+ fffile.close();
+}
+
+/* Looks for the fontname in the long list. If it does not find it, it adds the default values
+to the short list with this fontname. If it does find it, then it adds the specified values.
+*/
+void search_long_fflist(const char *fontname, double *f1, double *f2, double *f3){ //this is not called by any other source files
+FFNEXUS *ptr=NULL;
+FFNEXUS *tmp=long_fflist;
+ if(!long_fflist){
+ g_message("Programming error search_long_fflist called before read_system_fflist\n");
+ throw "boom";
+ }
+ ptr=long_fflist;
+ while(ptr){
+ if(!strcmp(ptr->fontname,fontname)){ tmp=ptr; break; }
+ ptr=ptr->next;
+ }
+ //tmp points at either the found name, or the default, the first entry in long_fflist
+ if(!short_fflist){
+ ptr=short_fflist=(FFNEXUS *) malloc(sizeof(FFNEXUS));
+ }
+ else {
+ ptr=short_fflist;
+ while(ptr->next){ ptr=ptr->next; }
+ ptr->next=(FFNEXUS *) malloc(sizeof(FFNEXUS));
+ ptr=ptr->next;
+ }
+ ptr->fontname=strdup(tmp->fontname);
+ *f1 = ptr->f1 = tmp->f1;
+ *f2 = ptr->f2 = tmp->f2;
+ *f3 = ptr->f3 = tmp->f3;
+ ptr->next=NULL;
+}
+
+/* Looks for the fontname in the short list. If it does not find it, it looks in the long_fflist.
+Either way it returns the f1, f2, f3 parameters for the font, even if these are for the default.
+*/
+void search_short_fflist(const char *fontname, double *f1, double *f2, double *f3){ //this is not called by any other source files
+FFNEXUS *ptr=NULL;
+static FFNEXUS *last=NULL;
+ if(!long_fflist){
+ g_message("Programming error search_short_fflist called before read_system_fflist\n");
+ throw "boom";
+ }
+ // This speeds things up a lot - if the same font is called twice in a row, pull it out immediately
+ if(last && !strcmp(last->fontname,fontname)){ ptr=last; }
+ else { ptr=short_fflist; } // short_fflist may still be NULL
+ while(ptr){
+ if(!strcmp(ptr->fontname,fontname)){ *f1=ptr->f1; *f2=ptr->f2; *f3=ptr->f3; last=ptr; return; }
+ ptr=ptr->next;
+ }
+ //reach this point only if there is no match
+ search_long_fflist(fontname, f1, f2, f3);
+}
+
+void smuggle_adx_out(const char *string, uint32_t **adx, int *ndx, float scale){
+ float fdx;
+ int i;
+ uint32_t *ladx;
+ const char *cptr=&string[strlen(string)+1];
+
+ *adx=NULL;
+ sscanf(cptr,"%7d",ndx);
+ if(!*ndx)return; // this could happen with an empty string
+ cptr += 7;
+ ladx = (uint32_t *) malloc(*ndx * sizeof(uint32_t) );
+ *adx=ladx;
+ for(i=0; i<*ndx; i++,cptr+=7, ladx++){
+ sscanf(cptr,"%7f",&fdx);
+ *ladx=(uint32_t) round(fdx * scale);
+ }
+}
+
+/* Translate inkscape weights to EMF weights.
+*/
+uint32_t transweight(const unsigned int inkweight){
+ if(inkweight == SP_CSS_FONT_WEIGHT_400)return(U_FW_NORMAL);
+ if(inkweight == SP_CSS_FONT_WEIGHT_100)return(U_FW_THIN);
+ if(inkweight == SP_CSS_FONT_WEIGHT_200)return(U_FW_EXTRALIGHT);
+ if(inkweight == SP_CSS_FONT_WEIGHT_300)return(U_FW_LIGHT);
+ // 400 is tested first, as it is the most common case
+ if(inkweight == SP_CSS_FONT_WEIGHT_500)return(U_FW_MEDIUM);
+ if(inkweight == SP_CSS_FONT_WEIGHT_600)return(U_FW_SEMIBOLD);
+ if(inkweight == SP_CSS_FONT_WEIGHT_700)return(U_FW_BOLD);
+ if(inkweight == SP_CSS_FONT_WEIGHT_800)return(U_FW_EXTRABOLD);
+ if(inkweight == SP_CSS_FONT_WEIGHT_900)return(U_FW_HEAVY);
+ return(U_FW_NORMAL);
+}
+
+PrintEmf::PrintEmf (void):
+ _width(0),
+ _height(0),
+ hbrush(0),
+ hbrushOld(0),
+ hpen(0),
+ stroke_and_fill(false),
+ fill_only(false),
+ simple_shape(false)
+{
+}
+
+
+PrintEmf::~PrintEmf (void)
+{
+
+ /* restore default signal handling for SIGPIPE */
+#if !defined(_WIN32) && !defined(__WIN32__)
+ (void) signal(SIGPIPE, SIG_DFL);
+#endif
+ return;
+}
+
+
+unsigned int PrintEmf::setup (Inkscape::Extension::Print * /*mod*/)
+{
+ return TRUE;
+}
+
+
+unsigned int PrintEmf::begin (Inkscape::Extension::Print *mod, SPDocument *doc)
+{
+ U_SIZEL szlDev, szlMm;
+ U_RECTL rclBounds, rclFrame;
+ char *rec;
+
+ gchar const *utf8_fn = mod->get_param_string("destination");
+ FixPPT1 = mod->get_param_bool("FixPPT1");
+
+ (void) emf_start(utf8_fn, 1000000, 250000, &et); // Initialize the et structure
+ (void) htable_create(128, 128, &eht); // Initialize the eht structure
+
+ char *ansi_uri = (char *) utf8_fn;
+
+ // width and height in px
+ _width = doc->getWidth();
+ _height = doc->getHeight();
+
+ bool pageBoundingBox;
+ pageBoundingBox = mod->get_param_bool("pageBoundingBox");
+
+ Geom::Rect d;
+ if (pageBoundingBox) {
+ d = Geom::Rect::from_xywh(0, 0, _width, _height);
+ } else {
+ SPItem* doc_item = doc->getRoot();
+ Geom::OptRect bbox = doc_item->desktopVisualBounds();
+ if (bbox) d = *bbox;
+ }
+
+ d *= Geom::Scale(IN_PER_PX);
+
+ float dwInchesX = d.width();
+ float dwInchesY = d.height();
+
+ // dwInchesX x dwInchesY in micrometer units, dpi=90 -> 3543.3 dpm
+ (void) drawing_size((int) ceil(dwInchesX*25.4), (int) ceil(dwInchesY*25.4), 3.543307, &rclBounds, &rclFrame);
+
+ // set up the device as A4 horizontal, 47.244094 dpmm (1200 dpi)
+ int MMX = 216;
+ int MMY = 279;
+ (void) device_size(MMX, MMY, 47.244094, &szlDev, &szlMm); // Drawing: A4 horizontal, 42744 dpm (1200 dpi)
+ int PixelsX = szlDev.cx;
+ int PixelsY = szlDev.cy;
+
+ // set up the description: (version string)0(file)00
+ char buff[1024];
+ memset(buff,0, sizeof(buff));
+ char *p1 = strrchr(ansi_uri, '\\');
+ char *p2 = strrchr(ansi_uri, '/');
+ char *p = MAX(p1, p2);
+ if (p)
+ p++;
+ else
+ p = ansi_uri;
+ snprintf(buff, sizeof(buff)-1, "Inkscape %s (%s)\1%s\1", Inkscape::version_string, __DATE__,p);
+ uint16_t *Description = U_Utf8ToUtf16le(buff, 0, NULL);
+ int cbDesc = 2 + wchar16len(Description); // also count the final terminator
+ (void) U_Utf16leEdit(Description, '\1', '\0'); // swap the temporary \1 characters for nulls
+
+ // construct the EMRHEADER record and append it to the EMF in memory
+ rec = U_EMRHEADER_set( rclBounds, rclFrame, NULL, cbDesc, Description, szlDev, szlMm, 0);
+ free(Description);
+ if(!rec || emf_append((PU_ENHMETARECORD)rec, et, U_REC_FREE)){
+ throw "Fatal programming error in PrintEmf::begin at EMRHEADER";
+ }
+
+
+ // Simplest mapping mode, supply all coordinates in pixels
+ rec = U_EMRSETMAPMODE_set(U_MM_TEXT);
+ if(!rec || emf_append((PU_ENHMETARECORD)rec, et, U_REC_FREE)){
+ throw "Fatal programming error in PrintEmf::begin at EMRSETMAPMODE";
+ }
+
+
+ // Correct for dpi in EMF vs dpi in Inkscape (always 90?)
+ // Also correct for the scaling in PX2WORLD, which is set to 20. Doesn't hurt for high resolution,
+ // helps prevent rounding errors for low resolution EMF. Low resolution EMF is possible if there
+ // are no print devices and the screen resolution is low.
+
+ worldTransform.eM11 = ((float)PixelsX * 25.4f)/((float)MMX*90.0f*PX2WORLD);
+ worldTransform.eM12 = 0.0f;
+ worldTransform.eM21 = 0.0f;
+ worldTransform.eM22 = ((float)PixelsY * 25.4f)/((float)MMY*90.0f*PX2WORLD);
+ worldTransform.eDx = 0;
+ worldTransform.eDy = 0;
+
+ rec = U_EMRMODIFYWORLDTRANSFORM_set(worldTransform, U_MWT_LEFTMULTIPLY);
+ if(!rec || emf_append((PU_ENHMETARECORD)rec, et, U_REC_FREE)){
+ throw "Fatal programming error in PrintEmf::begin at EMRMODIFYWORLDTRANSFORM";
+ }
+
+
+ if (1) {
+ snprintf(buff, sizeof(buff)-1, "Screen=%dx%dpx, %dx%dmm", PixelsX, PixelsY, MMX, MMY);
+ rec = textcomment_set(buff);
+ if(!rec || emf_append((PU_ENHMETARECORD)rec, et, U_REC_FREE)){
+ throw "Fatal programming error in PrintEmf::begin at textcomment_set 1";
+ }
+
+ snprintf(buff, sizeof(buff)-1, "Drawing=%.1lfx%.1lfpx, %.1lfx%.1lfmm", _width, _height, dwInchesX * MM_PER_IN, dwInchesY * MM_PER_IN);
+ rec = textcomment_set(buff);
+ if(!rec || emf_append((PU_ENHMETARECORD)rec, et, U_REC_FREE)){
+ throw "Fatal programming error in PrintEmf::begin at textcomment_set 1";
+ }
+ }
+
+ return 0;
+}
+
+
+unsigned int PrintEmf::finish (Inkscape::Extension::Print * /*mod*/)
+{
+// std::cout << "finish " << std::endl;
+ char *rec;
+ if (!et) return 0;
+
+ flush_fill(); // flush any pending fills
+
+ rec = U_EMREOF_set(0,NULL,et); // generate the EOF record
+ if(!rec || emf_append((PU_ENHMETARECORD)rec, et, U_REC_FREE)){
+ throw "Fatal programming error in PrintEmf::finish";
+ }
+ (void) emf_finish(et, eht); // Finalize and write out the EMF
+ emf_free(&et); // clean up
+ htable_free(&eht); // clean up
+
+// std::cout << "end finish" << std::endl;
+ return 0;
+}
+
+
+unsigned int PrintEmf::comment (Inkscape::Extension::Print * /*module*/,
+ const char * /*comment*/)
+{
+// std::cout << "comment " << std::endl;
+ if (!et) return 0;
+
+ flush_fill(); // flush any pending fills
+
+// std::cout << "end comment" << std::endl;
+ return 0;
+}
+
+
+int PrintEmf::create_brush(SPStyle const *style)
+{
+// std::cout << "create_brush " << std::endl;
+ float rgb[3];
+ char *rec;
+ U_LOGBRUSH lb;
+ uint32_t brush, fmode;
+
+ if (!et) return 0;
+ if (style) {
+ float opacity = SP_SCALE24_TO_FLOAT(style->fill_opacity.value);
+ if (opacity <= 0.0) return 1; // opacity isn't used here beyond this
+
+ sp_color_get_rgb_floatv( &style->fill.value.color, rgb );
+ lb = (U_LOGBRUSH) { U_BS_SOLID, U_RGB(255*rgb[0], 255*rgb[1], 255*rgb[2]), U_HS_HORIZONTAL };
+
+ fmode = style->fill_rule.computed == 0 ? U_WINDING : (style->fill_rule.computed == 2 ? U_ALTERNATE : U_ALTERNATE);
+ } else { // if (!style)
+ lb = (U_LOGBRUSH) { U_BS_SOLID, U_RGB(0, 0, 0), U_HS_HORIZONTAL };
+
+ fmode = U_ALTERNATE;
+ }
+
+ rec = createbrushindirect_set(&brush, eht, lb);
+ if(!rec || emf_append((PU_ENHMETARECORD)rec, et, U_REC_FREE)){
+ throw "Fatal programming error in PrintEmf::create_brush at createbrushindirect_set";
+ }
+ hbrush = brush; // need this later for destroy_brush
+
+ rec = selectobject_set(brush, eht);
+ if(!rec || emf_append((PU_ENHMETARECORD)rec, et, U_REC_FREE)){
+ throw "Fatal programming error in PrintEmf::create_brush at selectobject_set";
+ }
+
+ rec = U_EMRSETPOLYFILLMODE_set(fmode);
+ if(!rec || emf_append((PU_ENHMETARECORD)rec, et, U_REC_FREE)){
+ throw "Fatal programming error in PrintEmf::create_brush at U_EMRSETPOLYFILLMODE_set";
+ }
+// std::cout << "end create_brush " << std::endl;
+ return 0;
+}
+
+
+void PrintEmf::destroy_brush()
+{
+// std::cout << "destroy_brush " << std::endl;
+ char *rec;
+ // before an object may be safely deleted it must no longer be selected
+ // select in a stock object to deselect this one, the stock object should
+ // never be used because we always select in a new one before drawing anythingrestore previous brush, necessary??? Would using a default stock object not work?
+ rec = selectobject_set(U_NULL_BRUSH, eht);
+ if(!rec || emf_append((PU_ENHMETARECORD)rec, et, U_REC_FREE)){
+ throw "Fatal programming error in PrintEmf::destroy_brush at selectobject_set";
+ }
+ if (hbrush){
+ rec = deleteobject_set(&hbrush, eht);
+ if(!rec || emf_append((PU_ENHMETARECORD)rec, et, U_REC_FREE)){
+ throw "Fatal programming error in PrintEmf::destroy_brush";
+ }
+ hbrush = 0;
+ }
+// std::cout << "end destroy_brush" << std::endl;
+}
+
+
+void PrintEmf::create_pen(SPStyle const *style, const Geom::Affine &transform)
+{
+ U_COLORREF cr;
+ U_LOGBRUSH lb;
+ U_EXTLOGPEN *elp;
+ U_NUM_STYLEENTRY n_dash = 0;
+ U_STYLEENTRY *dash = NULL;
+ char *rec = NULL;
+ int linestyle = U_PS_SOLID;
+ int linecap = 0;
+ int linejoin = 0;
+ uint32_t pen;
+// std::cout << "create_pen " << std::endl;
+
+ if (style) {
+ float rgb[3];
+
+ sp_color_get_rgb_floatv(&style->stroke.value.color, rgb);
+
+ lb = logbrush_set(U_BS_SOLID, U_RGB( 255*rgb[0], 255*rgb[1], 255*rgb[2] ), U_HS_SOLIDCLR);
+
+
+ using Geom::X;
+ using Geom::Y;
+
+ Geom::Point zero(0, 0);
+ Geom::Point one(1, 1);
+ Geom::Point p0(zero * transform);
+ Geom::Point p1(one * transform);
+ Geom::Point p(p1 - p0);
+
+ double scale = sqrt( (p[X]*p[X]) + (p[Y]*p[Y]) ) / sqrt(2);
+
+ if(!style->stroke_width.computed){return;} //if width is 0 do not (reset) the pen, it should already be NULL_PEN
+ uint32_t linewidth = MAX( 1, (uint32_t) (scale * style->stroke_width.computed * PX2WORLD) );
+
+ if (style->stroke_linecap.computed == 0) {
+ linecap = U_PS_ENDCAP_FLAT;
+ }
+ else if (style->stroke_linecap.computed == 1) {
+ linecap = U_PS_ENDCAP_ROUND;
+ }
+ else if (style->stroke_linecap.computed == 2) {
+ linecap = U_PS_ENDCAP_SQUARE;
+ }
+
+ if (style->stroke_linejoin.computed == 0) {
+ linejoin = U_PS_JOIN_MITER;
+ }
+ else if (style->stroke_linejoin.computed == 1) {
+ linejoin = U_PS_JOIN_ROUND;
+ }
+ else if (style->stroke_linejoin.computed == 2) {
+ linejoin = U_PS_JOIN_BEVEL;
+ }
+
+ if (style->stroke_dash.n_dash &&
+ style->stroke_dash.dash )
+ {
+ int i = 0;
+ while (linestyle != U_PS_USERSTYLE &&
+ (i < style->stroke_dash.n_dash)) {
+ if (style->stroke_dash.dash[i] > 0.00000001)
+ linestyle = U_PS_USERSTYLE;
+ i++;
+ }
+
+ if (linestyle == U_PS_USERSTYLE) {
+ n_dash = style->stroke_dash.n_dash;
+ dash = new uint32_t[n_dash];
+ for (i = 0; i < style->stroke_dash.n_dash; i++) {
+ dash[i] = (uint32_t) (style->stroke_dash.dash[i] * PX2WORLD);
+ }
+ }
+ }
+
+ cr = colorref_set(255*rgb[0], 255*rgb[1], 255*rgb[2]);
+ elp = extlogpen_set(
+ U_PS_GEOMETRIC | linestyle | linecap | linejoin,
+ linewidth,
+ U_BS_SOLID,
+ cr,
+ U_HS_HORIZONTAL,
+ n_dash,
+ dash);
+
+ }
+ else { // if (!style)
+ linejoin=0;
+ elp = extlogpen_set(
+ linestyle,
+ 1,
+ U_BS_SOLID,
+ U_RGB(0,0,0),
+ U_HS_HORIZONTAL,
+ 0,
+ NULL);
+ }
+
+ rec = extcreatepen_set(&pen, eht, NULL, 0, NULL, elp );
+ if(!rec || emf_append((PU_ENHMETARECORD)rec, et, U_REC_FREE)){
+ throw "Fatal programming error in PrintEmf::create_pen at extcreatepen_set";
+ }
+ free(elp);
+
+ rec = selectobject_set(pen, eht);
+ if(!rec || emf_append((PU_ENHMETARECORD)rec, et, U_REC_FREE)){
+ throw "Fatal programming error in PrintEmf::create_pen at selectobject_set";
+ }
+ hpen = pen; // need this later for destroy_pen
+
+ if (linejoin == U_PS_JOIN_MITER) {
+ float miterlimit = style->stroke_miterlimit.value;
+
+ miterlimit = miterlimit * 10.0 / 4.0;
+ if (miterlimit < 1)
+ miterlimit = 10.0;
+
+ miterlimit = miterlimit * PX2WORLD;
+
+ rec = U_EMRSETMITERLIMIT_set((uint32_t) miterlimit);
+ if(!rec || emf_append((PU_ENHMETARECORD)rec, et, U_REC_FREE)){
+ throw "Fatal programming error in PrintEmf::create_pen at U_EMRSETMITERLIMIT_set";
+ }
+ }
+
+ if (n_dash) {
+ delete[] dash;
+ }
+// std::cout << "end create_pen" << std::endl;
+}
+
+
+void PrintEmf::destroy_pen()
+{
+// std::cout << "destroy_pen hpen: " << hpen<< std::endl;
+ char *rec = NULL;
+ // before an object may be safely deleted it must no longer be selected
+ // select in a stock object to deselect this one, the stock object should
+ // never be used because we always select in a new one before drawing anythingrestore previous brush, necessary??? Would using a default stock object not work?
+ rec = selectobject_set(U_NULL_PEN, eht);
+ if(!rec || emf_append((PU_ENHMETARECORD)rec, et, U_REC_FREE)){
+ throw "Fatal programming error in PrintEmf::destroy_pen at selectobject_set";
+ }
+ if (hpen){
+ rec = deleteobject_set(&hpen, eht);
+ if(!rec || emf_append((PU_ENHMETARECORD)rec, et, U_REC_FREE)){
+ throw "Fatal programming error in PrintEmf::destroy_pen";
+ }
+ hpen = 0;
+ }
+// std::cout << "end destroy_pen " << std::endl;
+}
+
+
+void PrintEmf::flush_fill()
+{
+// std::cout << "flush_fill " << std::endl;
+ char *rec = NULL;
+ if (!fill_pathv.empty()) {
+ stroke_and_fill = false;
+ fill_only = true;
+ print_pathv(fill_pathv, fill_transform);
+ fill_only = false;
+ if (!simple_shape){
+ rec = U_EMRFILLPATH_set(U_RCL_DEF);
+ if(!rec || emf_append((PU_ENHMETARECORD)rec, et, U_REC_FREE)){
+ throw "Fatal programming error in PrintEmf::flush_fill";
+ }
+ }
+ destroy_brush();
+ fill_pathv.clear();
+ }
+// std::cout << "end flush_fill" << std::endl;
+}
+
+unsigned int PrintEmf::bind(Inkscape::Extension::Print * /*mod*/, Geom::Affine const &transform, float /*opacity*/)
+{
+// std::cout << "bind " << std::endl;
+ if (!m_tr_stack.empty()) {
+ Geom::Affine tr_top = m_tr_stack.top();
+ m_tr_stack.push(transform * tr_top);
+ } else {
+ m_tr_stack.push(transform);
+ }
+
+// std::cout << "end bind" << std::endl;
+ return 1;
+}
+
+unsigned int PrintEmf::release(Inkscape::Extension::Print * /*mod*/)
+{
+// std::cout << "release " << std::endl;
+ m_tr_stack.pop();
+// std::cout << "end release" << std::endl;
+ return 1;
+}
+
+unsigned int PrintEmf::fill(Inkscape::Extension::Print * /*mod*/,
+ Geom::PathVector const &pathv, Geom::Affine const & /*transform*/, SPStyle const *style,
+ Geom::OptRect const &/*pbox*/, Geom::OptRect const &/*dbox*/, Geom::OptRect const &/*bbox*/)
+{
+// std::cout << "fill " << std::endl;
+ char *rec = NULL;
+
+ Geom::Affine tf = m_tr_stack.top();
+
+ flush_fill(); // flush any pending fills
+
+//Inkscape is NOT calling create_pen for objects with no border. PPT, and presumably others, pick whatever they want
+//for the border if it is not specified, so no border can become border. To avoid this specify "no pen" here if we can determine
+//that will not be needed after the fill.
+ if (style->stroke.noneSet || style->stroke_width.computed == 0.0){
+ if(hpen)destroy_pen();
+ rec = selectobject_set(U_NULL_PEN, eht);
+ if(!rec || emf_append((PU_ENHMETARECORD)rec, et, U_REC_FREE)){
+ throw "Fatal programming error in PrintEmf::create_pen at selectobject_set";
+ }
+ }
+
+ if (style->fill.isColor()) {
+ if (create_brush(style))
+ return 0;
+ } else {
+ // create_brush(NULL);
+ return 0;
+ }
+
+ fill_pathv.clear();
+ std::copy(pathv.begin(), pathv.end(), std::back_inserter(fill_pathv));
+ fill_transform = tf;
+
+ // postpone fill in case of stroke-and-fill, otherwise do it now
+ if (style->stroke.noneSet || style->stroke_width.computed == 0.0){
+ flush_fill(); // flush any pending fills
+ }
+
+// std::cout << "end fill" << std::endl;
+ return 0;
+}
+
+
+unsigned int PrintEmf::stroke (Inkscape::Extension::Print * /*mod*/,
+ Geom::PathVector const &pathv, const Geom::Affine &/*transform*/, const SPStyle *style,
+ Geom::OptRect const &/*pbox*/, Geom::OptRect const &/*dbox*/, Geom::OptRect const &/*bbox*/)
+{
+// std::cout << "stroke " << std::endl;
+ char *rec = NULL;
+
+ Geom::Affine tf = m_tr_stack.top();
+
+ stroke_and_fill = ( pathv == fill_pathv );
+
+ if (!stroke_and_fill) {
+ flush_fill(); // flush any pending fills
+ }
+
+ if (style->stroke.isColor()) {
+ create_pen(style, tf);
+ } else {
+ // create_pen(NULL, tf);
+ return 0;
+ }
+
+ print_pathv(pathv, tf);
+
+ if (stroke_and_fill) {
+ if (!simple_shape){
+ rec = U_EMRSTROKEANDFILLPATH_set(U_RCL_DEF);
+ if(!rec || emf_append((PU_ENHMETARECORD)rec, et, U_REC_FREE)){
+ throw "Fatal programming error in PrintEmf::stroke at U_EMRSTROKEANDFILLPATH_set";
+ }
+ }
+ destroy_brush();
+ fill_pathv.clear();
+ } else {
+ if (!simple_shape){
+ rec = U_EMRSTROKEPATH_set(U_RCL_DEF);
+ if(!rec || emf_append((PU_ENHMETARECORD)rec, et, U_REC_FREE)){
+ throw "Fatal programming error in PrintEmf::stroke at U_EMRSTROKEANDFILLPATH_set";
+ }
+ }
+ }
+
+ destroy_pen();
+
+// std::cout << "end stroke " << std::endl;
+ return 0;
+}
+
+
+bool PrintEmf::print_simple_shape(Geom::PathVector const &pathv, const Geom::Affine &transform)
+{
+// std::cout << "print_simple_shape " << std::endl <begin(); cit != pit->end_open(); ++cit)
+ {
+ nodes++;
+
+ if ( is_straight_curve(*cit) ) {
+ lines++;
+ }
+ else if (Geom::CubicBezier const *cubic = dynamic_cast(&*cit)) {
+ cubic = cubic;
+ curves++;
+ }
+ }
+ }
+
+ if (!nodes)
+ return false;
+
+ U_POINT *lpPoints = new U_POINT[moves + lines + curves*3];
+ int i = 0;
+
+ /**
+ * For all Subpaths in the
+ */
+ for (Geom::PathVector::const_iterator pit = pv.begin(); pit != pv.end(); ++pit)
+ {
+ using Geom::X;
+ using Geom::Y;
+
+ Geom::Point p0 = pit->initialPoint();
+
+ p0[X] = (p0[X] * PX2WORLD);
+ p0[Y] = (p0[Y] * PX2WORLD);
+
+ int32_t const x0 = (int32_t) round(p0[X]);
+ int32_t const y0 = (int32_t) round(p0[Y]);
+
+ lpPoints[i].x = x0;
+ lpPoints[i].y = y0;
+ i = i + 1;
+
+ /**
+ * For all segments in the subpath
+ */
+ for (Geom::Path::const_iterator cit = pit->begin(); cit != pit->end_open(); ++cit)
+ {
+ if ( is_straight_curve(*cit) )
+ {
+ //Geom::Point p0 = cit->initialPoint();
+ Geom::Point p1 = cit->finalPoint();
+
+ //p0[X] = (p0[X] * PX2WORLD);
+ p1[X] = (p1[X] * PX2WORLD);
+ //p0[Y] = (p0[Y] * PX2WORLD);
+ p1[Y] = (p1[Y] * PX2WORLD);
+
+ //int32_t const x0 = (int32_t) round(p0[X]);
+ //int32_t const y0 = (int32_t) round(p0[Y]);
+ int32_t const x1 = (int32_t) round(p1[X]);
+ int32_t const y1 = (int32_t) round(p1[Y]);
+
+ lpPoints[i].x = x1;
+ lpPoints[i].y = y1;
+ i = i + 1;
+ }
+ else if (Geom::CubicBezier const *cubic = dynamic_cast(&*cit))
+ {
+ std::vector points = cubic->points();
+ //Geom::Point p0 = points[0];
+ Geom::Point p1 = points[1];
+ Geom::Point p2 = points[2];
+ Geom::Point p3 = points[3];
+
+ //p0[X] = (p0[X] * PX2WORLD);
+ p1[X] = (p1[X] * PX2WORLD);
+ p2[X] = (p2[X] * PX2WORLD);
+ p3[X] = (p3[X] * PX2WORLD);
+ //p0[Y] = (p0[Y] * PX2WORLD);
+ p1[Y] = (p1[Y] * PX2WORLD);
+ p2[Y] = (p2[Y] * PX2WORLD);
+ p3[Y] = (p3[Y] * PX2WORLD);
+
+ //int32_t const x0 = (int32_t) round(p0[X]);
+ //int32_t const y0 = (int32_t) round(p0[Y]);
+ int32_t const x1 = (int32_t) round(p1[X]);
+ int32_t const y1 = (int32_t) round(p1[Y]);
+ int32_t const x2 = (int32_t) round(p2[X]);
+ int32_t const y2 = (int32_t) round(p2[Y]);
+ int32_t const x3 = (int32_t) round(p3[X]);
+ int32_t const y3 = (int32_t) round(p3[Y]);
+
+ lpPoints[i].x = x1;
+ lpPoints[i].y = y1;
+ lpPoints[i+1].x = x2;
+ lpPoints[i+1].y = y2;
+ lpPoints[i+2].x = x3;
+ lpPoints[i+2].y = y3;
+ i = i + 3;
+ }
+ }
+ }
+
+ bool done = false;
+ bool closed = (lpPoints[0].x == lpPoints[i-1].x) && (lpPoints[0].y == lpPoints[i-1].y);
+ bool polygon = false;
+ bool rectangle = false;
+ bool ellipse = false;
+
+ if (moves == 1 && moves+lines == nodes && closed) {
+ polygon = true;
+// if (nodes==5) { // disable due to LP Bug 407394
+// if (lpPoints[0].x == lpPoints[3].x && lpPoints[1].x == lpPoints[2].x &&
+// lpPoints[0].y == lpPoints[1].y && lpPoints[2].y == lpPoints[3].y)
+// {
+// rectangle = true;
+// }
+// }
+ }
+ else if (moves == 1 && nodes == 5 && moves+curves == nodes && closed) {
+// if (lpPoints[0].x == lpPoints[1].x && lpPoints[1].x == lpPoints[11].x &&
+// lpPoints[5].x == lpPoints[6].x && lpPoints[6].x == lpPoints[7].x &&
+// lpPoints[2].x == lpPoints[10].x && lpPoints[3].x == lpPoints[9].x && lpPoints[4].x == lpPoints[8].x &&
+// lpPoints[2].y == lpPoints[3].y && lpPoints[3].y == lpPoints[4].y &&
+// lpPoints[8].y == lpPoints[9].y && lpPoints[9].y == lpPoints[10].y &&
+// lpPoints[5].y == lpPoints[1].y && lpPoints[6].y == lpPoints[0].y && lpPoints[7].y == lpPoints[11].y)
+// { // disable due to LP Bug 407394
+// ellipse = true;
+// }
+ }
+
+ if (polygon || ellipse) {
+
+ if (!stroke_and_fill) {
+ if (fill_only) {
+ rec = selectobject_set(U_NULL_PEN, eht);
+ if(!rec || emf_append((PU_ENHMETARECORD)rec, et, U_REC_FREE)){
+ throw "Fatal programming error in PrintEmf::print_simple_shape at selectobject_set pen";
+ }
+ }
+ else { // if (stroke_only)
+ rec = selectobject_set(U_NULL_BRUSH, eht);
+ if(!rec || emf_append((PU_ENHMETARECORD)rec, et, U_REC_FREE)){
+ throw "Fatal programming error in PrintEmf::print_simple_shape at selectobject_set brush";
+ }
+ }
+ }
+
+ if (polygon) {
+ if (rectangle){
+ U_RECTL rcl = rectl_set((U_POINTL) {lpPoints[0].x, lpPoints[0].y}, (U_POINTL) {lpPoints[2].x, lpPoints[2].y});
+ rec = U_EMRRECTANGLE_set(rcl);
+ }
+ else {
+ rec = U_EMRPOLYGON_set(U_RCL_DEF, nodes, lpPoints);
+ }
+ }
+ else if (ellipse) {
+ U_RECTL rcl = rectl_set((U_POINTL) {lpPoints[6].x, lpPoints[3].y}, (U_POINTL) {lpPoints[0].x, lpPoints[9].y});
+ rec = U_EMRELLIPSE_set(rcl);
+ }
+ if(!rec || emf_append((PU_ENHMETARECORD)rec, et, U_REC_FREE)){
+ throw "Fatal programming error in PrintEmf::print_simple_shape at retangle/ellipse/polygon";
+ }
+
+ done = true;
+
+ // replace the handle we moved above, assuming there was something set already
+ if (!stroke_and_fill) {
+ if (fill_only) {
+ if(hpen){
+ rec = selectobject_set(hpen, eht);
+ if(!rec || emf_append((PU_ENHMETARECORD)rec, et, U_REC_FREE)){
+ throw "Fatal programming error in PrintEmf::print_simple_shape at selectobject_set pen";
+ }
+ }
+ }
+ else { // if (stroke_only)
+ if(hbrush){
+ rec = selectobject_set(hbrush, eht);
+ if(!rec || emf_append((PU_ENHMETARECORD)rec, et, U_REC_FREE)){
+ throw "Fatal programming error in PrintEmf::print_simple_shape at selectobject_set brush";
+ }
+ }
+ }
+ }
+
+ }
+
+ delete[] lpPoints;
+
+// std::cout << "end simple_shape " << std::endl;
+ return done;
+}
+
+/** Some parts based on win32.cpp by Lauris Kaplinski . Was a part of Inkscape
+ in the past (or will be in the future?) Not in current trunk. (4/19/2012)
+
+ Limitations of this code:
+ 1. rotated images are mangled. They stay in their original orientation and are stretched
+ along X or Y.
+ 2. Transparency is lost on export. (Apparently a limitation of the EMF format.)
+ 3. Probably messes up if row stride != w*4
+ 4. There is still a small memory leak somewhere, possibly in a pixbuf created in a routine
+ that calls this one and passes px, but never removes the rest of the pixbuf. The first time
+ this is called it leaked 5M (in one test) and each subsequent call leaked around 200K more.
+ If this routine is reduced to
+ if(1)return(0);
+ and called for a single 1280 x 1024 image then the program leaks 11M per call, or roughly the
+ size of two bitmaps.
+*/
+
+unsigned int PrintEmf::image(Inkscape::Extension::Print * /* module */, /** not used */
+ unsigned char *px, /** array of pixel values, Gdk::Pixbuf bitmap format */
+ unsigned int w, /** width of bitmap */
+ unsigned int h, /** height of bitmap */
+ unsigned int rs, /** row stride (normally w*4) */
+ Geom::Affine const &tf_ignore, /** WRONG affine transform, use the one from m_tr_stack */
+ SPStyle const *style) /** provides indirect link to image object */
+{
+// std::cout << "image " << std::endl;
+ double x1,x2,y1,y2;
+ char *rec = NULL;
+ Geom::Affine tf = m_tr_stack.top();
+
+ x1= atof(style->object->getAttribute("x"));
+ y1= atof(style->object->getAttribute("y"));
+ x2=x1 + atof(style->object->getAttribute("width"));
+ y2=y1 + atof(style->object->getAttribute("height"));
+ Geom::Point pLL(x1,y1);
+ Geom::Point pUR(x2,y2);
+ Geom::Point p2LL = pLL * tf;
+ Geom::Point p2UR = pUR * tf;
+
+ U_BITMAPINFO bmInfo = {
+ {
+ sizeof (U_BITMAPINFOHEADER), // bV4Size
+ w, // biWidth
+ h, // biHeight
+ 1, // biPlanes
+ 32, // biBitCount
+ U_BI_RGB, // biCompression
+ 0, // biSizeImage
+ 2835, // biXPelsPerMeter, ignore this???
+ 2835, // biYPelsPerMeter
+ 0, // biClrUsed
+ 0 // biClrImportant
+ },
+ { { 0, 0, 0, 0 } } // bmiColors
+ };
+
+ unsigned int i,j;
+ /** Swap red and blue channels; Pixbuf is RGBA, Win32 GDI is BGRA. */
+ for ( i = 0 ; i < h * w ; i++ ) {
+ unsigned char temp=px[i*4];
+ px[i*4] = px[i*4+2];
+ px[i*4+2] = temp;
+ }
+
+ /** px has the lines reversed, so that when written to the EMF
+ x positions are correct but y are mirrored within the image. Correct
+ that here.
+ */
+ char *tbuf= (char *) malloc(rs);
+ for(i = 0, j = (h-1)*rs ; i < j; i+=rs,j-=rs){
+ memcpy(tbuf, &px[i],rs);
+ memcpy(&px[i],&px[j],rs);
+ memcpy(&px[j],tbuf, rs);
+ }
+ free(tbuf);
+
+ rec = U_EMRSETSTRETCHBLTMODE_set(U_COLORONCOLOR);
+ if(!rec || emf_append((PU_ENHMETARECORD)rec, et, U_REC_FREE)){
+ throw "Fatal programming error in PrintEmf::image at EMRHEADER";
+ }
+
+ U_POINTL Dest = pointl_set(round(p2LL[Geom::X] * PX2WORLD), round(p2LL[Geom::Y] * PX2WORLD));
+ U_POINTL cDest = pointl_set(round((p2UR[Geom::X]-p2LL[Geom::X]) * PX2WORLD), round((p2UR[Geom::Y]-p2LL[Geom::Y]) * PX2WORLD));
+ U_POINTL Src = pointl_set(0,0);
+ U_POINTL cSrc = pointl_set(w,h);
+ rec = U_EMRSTRETCHDIBITS_set(
+ U_RCL_DEF, //! Bounding rectangle in device units
+ Dest, //! Destination UL corner in logical units
+ cDest, //! Destination W & H in logical units
+ Src, //! Source UL corner in logical units
+ cSrc, //! Source W & H in logical units
+ U_DIB_RGB_COLORS, //! DIBColors Enumeration
+ U_SRCCOPY, //! RasterOPeration Enumeration
+ &bmInfo, //! (Optional) bitmapbuffer (U_BITMAPINFO section)
+ h*rs, //! size in bytes of px
+ (char *) px //! (Optional) bitmapbuffer (U_BITMAPINFO section)
+ );
+ if(!rec || emf_append((PU_ENHMETARECORD)rec, et, U_REC_FREE)){
+ throw "Fatal programming error in PrintEmf::image at U_EMRSTRETCHDIBITS_set";
+ }
+
+// std::cout << "end image" << std::endl;
+ return 0;
+}
+
+unsigned int PrintEmf::print_pathv(Geom::PathVector const &pathv, const Geom::Affine &transform)
+{
+// std::cout << "print_pathv " << std::endl << std::flush;
+ char *rec = NULL;
+ simple_shape = print_simple_shape(pathv, transform);
+
+ if (simple_shape)
+ return TRUE;
+
+ Geom::PathVector pv = pathv_to_linear_and_cubic_beziers( pathv * transform );
+
+ rec = U_EMRBEGINPATH_set();
+ if(!rec || emf_append((PU_ENHMETARECORD)rec, et, U_REC_FREE)){
+ throw "Fatal programming error in PrintEmf::print_pathv at U_EMRBEGINPATH_set";
+ }
+
+ /**
+ * For all Subpaths in the
+ */
+ for (Geom::PathVector::const_iterator pit = pv.begin(); pit != pv.end(); ++pit)
+ {
+ using Geom::X;
+ using Geom::Y;
+
+ Geom::Point p0 = pit->initialPoint();
+
+ p0[X] = (p0[X] * PX2WORLD);
+ p0[Y] = (p0[Y] * PX2WORLD);
+
+ U_POINTL ptl = pointl_set((int32_t) round(p0[X]), (int32_t) round(p0[Y]));
+ rec = U_EMRMOVETOEX_set(ptl);
+ if(!rec || emf_append((PU_ENHMETARECORD)rec, et, U_REC_FREE)){
+ throw "Fatal programming error in PrintEmf::print_pathv at U_EMRMOVETOEX_set";
+ }
+
+ /**
+ * For all segments in the subpath
+ */
+ for (Geom::Path::const_iterator cit = pit->begin(); cit != pit->end_open(); ++cit)
+ {
+ if ( is_straight_curve(*cit) )
+ {
+ //Geom::Point p0 = cit->initialPoint();
+ Geom::Point p1 = cit->finalPoint();
+
+ //p0[X] = (p0[X] * PX2WORLD);
+ p1[X] = (p1[X] * PX2WORLD);
+ //p0[Y] = (p0[Y] * PX2WORLD);
+ p1[Y] = (p1[Y] * PX2WORLD);
+
+ //int32_t const x0 = (int32_t) round(p0[X]);
+ //int32_t const y0 = (int32_t) round(p0[Y]);
+
+ ptl = pointl_set((int32_t) round(p1[X]), (int32_t) round(p1[Y]));
+ rec = U_EMRLINETO_set(ptl);
+ if(!rec || emf_append((PU_ENHMETARECORD)rec, et, U_REC_FREE)){
+ throw "Fatal programming error in PrintEmf::print_pathv at U_EMRLINETO_set";
+ }
+ }
+ else if (Geom::CubicBezier const *cubic = dynamic_cast(&*cit))
+ {
+ std::vector points = cubic->points();
+ //Geom::Point p0 = points[0];
+ Geom::Point p1 = points[1];
+ Geom::Point p2 = points[2];
+ Geom::Point p3 = points[3];
+
+ //p0[X] = (p0[X] * PX2WORLD);
+ p1[X] = (p1[X] * PX2WORLD);
+ p2[X] = (p2[X] * PX2WORLD);
+ p3[X] = (p3[X] * PX2WORLD);
+ //p0[Y] = (p0[Y] * PX2WORLD);
+ p1[Y] = (p1[Y] * PX2WORLD);
+ p2[Y] = (p2[Y] * PX2WORLD);
+ p3[Y] = (p3[Y] * PX2WORLD);
+
+ //int32_t const x0 = (int32_t) round(p0[X]);
+ //int32_t const y0 = (int32_t) round(p0[Y]);
+ int32_t const x1 = (int32_t) round(p1[X]);
+ int32_t const y1 = (int32_t) round(p1[Y]);
+ int32_t const x2 = (int32_t) round(p2[X]);
+ int32_t const y2 = (int32_t) round(p2[Y]);
+ int32_t const x3 = (int32_t) round(p3[X]);
+ int32_t const y3 = (int32_t) round(p3[Y]);
+
+ U_POINTL pt[3];
+ pt[0].x = x1;
+ pt[0].y = y1;
+ pt[1].x = x2;
+ pt[1].y = y2;
+ pt[2].x = x3;
+ pt[2].y = y3;
+
+ rec = U_EMRPOLYBEZIERTO_set(U_RCL_DEF, 3, pt);
+ if(!rec || emf_append((PU_ENHMETARECORD)rec, et, U_REC_FREE)){
+ throw "Fatal programming error in PrintEmf::print_pathv at U_EMRPOLYBEZIERTO_set";
+ }
+ }
+ else
+ {
+ g_warning("logical error, because pathv_to_linear_and_cubic_beziers was used");
+ }
+ }
+
+ if (pit->end_default() == pit->end_closed()) {
+ rec = U_EMRCLOSEFIGURE_set();
+ if(!rec || emf_append((PU_ENHMETARECORD)rec, et, U_REC_FREE)){
+ throw "Fatal programming error in PrintEmf::print_pathv at U_EMRCLOSEFIGURE_set";
+ }
+ }
+ }
+
+ rec = U_EMRENDPATH_set();
+ if(!rec || emf_append((PU_ENHMETARECORD)rec, et, U_REC_FREE)){
+ throw "Fatal programming error in PrintEmf::print_pathv at U_EMRENDPATH_set";
+ }
+// std::cout << "end pathv" << std::endl;
+
+ return TRUE;
+}
+
+
+bool PrintEmf::textToPath(Inkscape::Extension::Print * ext)
+{
+ return ext->get_param_bool("textToPath");
+}
+
+unsigned int PrintEmf::text(Inkscape::Extension::Print * /*mod*/, char const *text, Geom::Point const &p,
+ SPStyle const *const style)
+{
+// std::cout << "text " << std::endl;
+ if (!et) return 0;
+
+ char *rec = NULL;
+ int ccount,newfont;
+ int fix90n=0;
+ uint32_t hfont = 0;
+ Geom::Affine tf = m_tr_stack.top();
+ double rot = -1800.0*std::atan2(tf[1], tf[0])/M_PI; // 0.1 degree rotation, - sign for MM_TEXT
+ double rotb = -std::atan2(tf[1], tf[0]); // rotation for baseline offset for superscript/subscript, used below
+ double dx,dy;
+ double f1,f2,f3;
+
+#ifdef USE_PANGO_WIN32
+/*
+ font_instance *tf = (font_factory::Default())->Face(style->text->font_family.value, font_style_to_pos(*style));
+ if (tf) {
+ LOGFONT *lf = pango_win32_font_logfont(tf->pFont);
+ tf->Unref();
+ hfont = CreateFontIndirect(lf);
+ g_free(lf);
+ }
+*/
+#endif
+
+ // the dx array is smuggled in like: textw1 w2 w3 ...wn, where the widths are floats 7 characters wide, including the space
+ int ndx;
+ uint32_t *adx;
+ smuggle_adx_out(text, &adx, &ndx, PX2WORLD * std::min(tf.expansionX(),tf.expansionY())); // side effect: free() adx
+
+ char *text2 = strdup(text); // because U_Utf8ToUtf16le calls iconv which does not like a const char *
+ uint16_t *unicode_text = U_Utf8ToUtf16le( text2, 0, NULL );
+ free(text2);
+ //translates Unicode to NonUnicode, if possible. If any translate, all will, and all to
+ //the same font, because of code in Layout::print
+ if(sizeof(wchar_t) == sizeof(uint16_t)){ // This will be true on Windows
+ UnicodeToNon((wchar_t *)unicode_text, &ccount, &newfont);
+ }
+ else { // assume uint32_t, as on Linux and OS/X
+ wchar_t *wtmp = (wchar_t *) U_Utf16leToUtf32le(unicode_text, 0, NULL);
+ free(unicode_text);
+ UnicodeToNon(wtmp, &ccount, &newfont);
+ unicode_text = U_Utf32leToUtf16le((uint32_t*) wtmp, 0, NULL);
+ free(wtmp);
+ }
+
+ //PPT gets funky with text within +-1 degree of a multiple of 90, but only for SOME fonts.Snap those to the central value
+ //Some funky ones: Arial, Times New Roman
+ //Some not funky ones: Symbol and Verdana.
+ //Without a huge table we cannot catch them all, so just the most common problem ones.
+ if(FixPPT1){
+ switch(newfont){
+ case CVTSYM:
+ search_short_fflist("Convert To Symbol", &f1, &f2, &f3);
+ break;
+ case CVTZDG:
+ search_short_fflist("Convert To Zapf Dingbats", &f1, &f2, &f3);
+ break;
+ case CVTWDG:
+ search_short_fflist("Convert To Wingdings", &f1, &f2, &f3);
+ break;
+ default: //also CVTNON
+ search_short_fflist(style->text->font_family.value, &f1, &f2, &f3);
+ break;
+ }
+ if(f2 || f3){
+ int irem = ((int) round(rot)) % 900 ;
+ if(irem <=9 && irem >= -9){
+ fix90n=1; //assume vertical
+ rot = (double) (((int) round(rot)) - irem);
+ rotb = rot*M_PI/1800.0;
+ if( abs(rot) == 900.0 ){ fix90n = 2; }
+ }
+ }
+ }
+
+ int textheight = -style->font_size.computed * PX2WORLD * std::min(tf.expansionX(),tf.expansionY());
+ if (!hfont) {
+ // Scale the text to the minimum stretch. (It tends to stay within bounding rectangles even if
+ // it was streteched asymmetrically.) Few applications support text from EMF which is scaled
+ // differently by height/width, so leave lfWidth alone.
+ uint16_t *wfacename = U_Utf8ToUtf16le(style->text->font_family.value, 0, NULL);
+ U_LOGFONT lf = logfont_set(
+ textheight,
+ 0,
+ rot,
+ rot,
+ transweight(style->font_weight.computed),
+ (style->font_style.computed == SP_CSS_FONT_STYLE_ITALIC),
+ style->text_decoration.underline,
+ style->text_decoration.line_through,
+ U_DEFAULT_CHARSET,
+ U_OUT_DEFAULT_PRECIS,
+ U_CLIP_DEFAULT_PRECIS,
+ U_DEFAULT_QUALITY,
+ U_DEFAULT_PITCH | U_FF_DONTCARE,
+ wfacename);
+ free(wfacename);
+
+ rec = extcreatefontindirectw_set(&hfont, eht, (char *) &lf, NULL);
+ if(!rec || emf_append((PU_ENHMETARECORD)rec, et, U_REC_FREE)){
+ throw "Fatal programming error in PrintEmf::text at extcreatefontindirectw_set";
+ }
+ }
+
+ rec = selectobject_set(hfont, eht);
+ if(!rec || emf_append((PU_ENHMETARECORD)rec, et, U_REC_FREE)){
+ throw "Fatal programming error in PrintEmf::text at selectobject_set";
+ }
+
+ float rgb[3];
+ sp_color_get_rgb_floatv( &style->fill.value.color, rgb );
+ rec = U_EMRSETTEXTCOLOR_set(U_RGB(255*rgb[0], 255*rgb[1], 255*rgb[2]));
+ if(!rec || emf_append((PU_ENHMETARECORD)rec, et, U_REC_FREE)){
+ throw "Fatal programming error in PrintEmf::text at U_EMRSETTEXTCOLOR_set";
+ }
+
+ // Text alignment:
+ // - (x,y) coordinates received by this filter are those of the point where the text
+ // actually starts, and already takes into account the text object's alignment;
+ // - for this reason, the EMF text alignment must always be TA_BASELINE|TA_LEFT.
+ rec = U_EMRSETTEXTALIGN_set(U_TA_BASELINE | U_TA_LEFT);
+ if(!rec || emf_append((PU_ENHMETARECORD)rec, et, U_REC_FREE)){
+ throw "Fatal programming error in PrintEmf::text at U_EMRSETTEXTALIGN_set";
+ }
+
+ // Transparent text background
+ rec = U_EMRSETBKMODE_set(U_TRANSPARENT);
+ if(!rec || emf_append((PU_ENHMETARECORD)rec, et, U_REC_FREE)){
+ throw "Fatal programming error in PrintEmf::text at U_EMRSETBKMODE_set";
+ }
+
+ Geom::Point p2 = p * tf;
+
+ //Handle super/subscripts. Negative sign because of geometry of MM_TEXT.
+ p2[Geom::X] -= style->baseline_shift.computed * std::sin( rotb );
+ p2[Geom::Y] -= style->baseline_shift.computed * std::cos( rotb );
+
+ //Conditionally handle compensation for PPT EMF import bug (affects PPT 2003-2010, at least)
+ if(FixPPT1){
+ if(fix90n==1){ //vertical
+ dx= 0.0;
+ dy= f3 * style->font_size.computed * std::cos( rotb );
+ }
+ else if(fix90n==2){ //horizontal
+ dx= f2 * style->font_size.computed * std::sin( rotb );
+ dy= 0.0;
+ }
+ else {
+ dx= f1 * style->font_size.computed * std::sin( rotb );
+ dy= f1 * style->font_size.computed * std::cos( rotb );
+ }
+ p2[Geom::X] += dx;
+ p2[Geom::Y] += dy;
+ }
+
+ p2[Geom::X] = (p2[Geom::X] * PX2WORLD);
+ p2[Geom::Y] = (p2[Geom::Y] * PX2WORLD);
+
+ int32_t const xpos = (int32_t) round(p2[Geom::X]);
+ int32_t const ypos = (int32_t) round(p2[Geom::Y]);
+
+ // The number of characters in the string is a bit fuzzy. ndx, the number of entries in adx is
+ // the number of VISIBLE characters, since some may combine from the UTF (8 originally,
+ // now 16) encoding. Conversely strlen() or wchar16len() would give the absolute number of
+ // encoding characters. Unclear if emrtext wants the former or the latter but for now assume the former.
+
+// This is currently being smuggled in from caller as part of text, works
+// MUCH better than the fallback hack below
+// uint32_t *adx = dx_set(textheight, U_FW_NORMAL, slen); // dx is needed, this makes one up
+ char *rec2 = emrtext_set( (U_POINTL) {xpos, ypos}, ndx, 2, unicode_text, U_ETO_NONE, U_RCL_DEF, adx);
+ free(unicode_text);
+ free(adx);
+ rec = U_EMREXTTEXTOUTW_set(U_RCL_DEF,U_GM_COMPATIBLE,1.0,1.0,(PU_EMRTEXT)rec2);
+ free(rec2);
+ if(!rec || emf_append((PU_ENHMETARECORD)rec, et, U_REC_FREE)){
+ throw "Fatal programming error in PrintEmf::text at U_EMREXTTEXTOUTW_set";
+ }
+
+ // Must deselect an object before deleting it. Put the default font (back) in.
+ rec = selectobject_set(U_DEVICE_DEFAULT_FONT, eht);
+ if(!rec || emf_append((PU_ENHMETARECORD)rec, et, U_REC_FREE)){
+ throw "Fatal programming error in PrintEmf::text at selectobject_set";
+ }
+
+ if(hfont){
+ rec = deleteobject_set(&hfont, eht);
+ if(!rec || emf_append((PU_ENHMETARECORD)rec, et, U_REC_FREE)){
+ throw "Fatal programming error in PrintEmf::text at deleteobject_set";
+ }
+ }
+
+// std::cout << "end text" << std::endl;
+ return 0;
+}
+
+void PrintEmf::init (void)
+{
+// std::cout << "init " << std::endl;
+ read_system_fflist();
+
+ /* EMF print */
+ Inkscape::Extension::build_from_mem(
+ "\n"
+ "Enhanced Metafile Print\n"
+ "org.inkscape.print.emf\n"
+ "\n"
+ "true\n"
+ "true\n"
+ "false\n"
+ "\n"
+ "", new PrintEmf());
+
+ return;
+}
+
+} /* namespace Internal */
+} /* namespace Extension */
+} /* namespace Inkscape */
+
+
+/*
+ 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 -rNu3 src/extension/internal/emf-print.h src/extension/internal/emf-print.h
--- src/extension/internal/emf-print.h 1969-12-31 16:00:00.000000000 -0800
+++ src/extension/internal/emf-print.h 2012-08-07 12:44:29.000000000 -0700
@@ -0,0 +1,115 @@
+/** @file
+ * @brief Enhanced Metafile printing - implementation
+ */
+/* Author:
+ * Ulf Erikson
+ *
+ * Copyright (C) 2006-2008 Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+#ifndef __INKSCAPE_EXTENSION_INTERNAL_PRINT_EMF_H__
+#define __INKSCAPE_EXTENSION_INTERNAL_PRINT_EMF_H__
+
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "uemf.h"
+
+#include "extension/implementation/implementation.h"
+//#include "extension/extension.h"
+
+#include <2geom/pathvector.h>
+
+#include
+
+namespace Inkscape {
+namespace Extension {
+namespace Internal {
+
+class PrintEmf : public Inkscape::Extension::Implementation::Implementation
+{
+ double _width;
+ double _height;
+ U_RECTL rc;
+
+ uint32_t hbrush, hbrushOld, hpen, hpenOld;
+
+ std::stack m_tr_stack;
+ Geom::PathVector fill_pathv;
+ Geom::Affine fill_transform;
+ bool stroke_and_fill;
+ bool fill_only;
+ bool simple_shape;
+
+ unsigned int print_pathv (Geom::PathVector const &pathv, const Geom::Affine &transform);
+ bool print_simple_shape (Geom::PathVector const &pathv, const Geom::Affine &transform);
+
+public:
+ PrintEmf (void);
+ virtual ~PrintEmf (void);
+
+ /* Print functions */
+ virtual unsigned int setup (Inkscape::Extension::Print * module);
+
+ virtual unsigned int begin (Inkscape::Extension::Print * module, SPDocument *doc);
+ virtual unsigned int finish (Inkscape::Extension::Print * module);
+
+ /* Rendering methods */
+ virtual unsigned int bind(Inkscape::Extension::Print *module, Geom::Affine const &transform, float opacity);
+ virtual unsigned int release(Inkscape::Extension::Print *module);
+ virtual unsigned int fill (Inkscape::Extension::Print *module,
+ Geom::PathVector const &pathv,
+ Geom::Affine const &ctm, SPStyle const *style,
+ Geom::OptRect const &pbox, Geom::OptRect const &dbox,
+ Geom::OptRect const &bbox);
+ virtual unsigned int stroke (Inkscape::Extension::Print * module,
+ Geom::PathVector const &pathv,
+ Geom::Affine const &ctm, SPStyle const *style,
+ Geom::OptRect const &pbox, Geom::OptRect const &dbox,
+ Geom::OptRect const &bbox);
+ virtual unsigned int image(Inkscape::Extension::Print *module,
+ unsigned char *px,
+ unsigned int w,
+ unsigned int h,
+ unsigned int rs,
+ Geom::Affine const &transform,
+ SPStyle const *style);
+ virtual unsigned int comment(Inkscape::Extension::Print *module, const char * comment);
+ virtual unsigned int text(Inkscape::Extension::Print *module, char const *text,
+ Geom::Point const &p, SPStyle const *style);
+ bool textToPath (Inkscape::Extension::Print * ext);
+
+ static void init (void);
+protected:
+ int create_brush(SPStyle const *style);
+
+ void destroy_brush();
+
+ void create_pen(SPStyle const *style, const Geom::Affine &transform);
+
+ void destroy_pen();
+
+ void flush_fill();
+
+};
+
+} /* namespace Internal */
+} /* namespace Extension */
+} /* namespace Inkscape */
+
+
+#endif /* __INKSCAPE_EXTENSION_INTERNAL_PRINT_EMF_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 -rNu3 src/extension/internal/emf-win32-inout.cpp src/extension/internal/emf-win32-inout.cpp
--- src/extension/internal/emf-win32-inout.cpp 2012-08-07 12:29:10.000000000 -0700
+++ src/extension/internal/emf-win32-inout.cpp 1969-12-31 16:00:00.000000000 -0800
@@ -1,2526 +0,0 @@
-/** @file
- * @brief Windows-only Enhanced Metafile input and output.
- */
-/* Authors:
- * Ulf Erikson
- * Jon A. Cruz
- * Abhishek Sharma
- *
- * Copyright (C) 2006-2008 Authors
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- *
- * References:
- * - How to Create & Play Enhanced Metafiles in Win32
- * http://support.microsoft.com/kb/q145999/
- * - INFO: Windows Metafile Functions & Aldus Placeable Metafiles
- * http://support.microsoft.com/kb/q66949/
- * - Metafile Functions
- * http://msdn.microsoft.com/library/en-us/gdi/metafile_0whf.asp
- * - Metafile Structures
- * http://msdn.microsoft.com/library/en-us/gdi/metafile_5hkj.asp
- */
-
-#ifdef WIN32
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include "sp-root.h"
-#include "sp-path.h"
-#include "style.h"
-#include "print.h"
-#include "extension/system.h"
-#include "extension/print.h"
-#include "extension/db.h"
-#include "extension/output.h"
-#include "display/drawing.h"
-#include "display/drawing-item.h"
-#include "unit-constants.h"
-#include "clear-n_.h"
-#include "document.h"
-
-#define WIN32_LEAN_AND_MEAN
-#include
-
-#include "emf-win32-print.h"
-#include "emf-win32-inout.h"
-
-
-#define PRINT_EMF_WIN32 "org.inkscape.print.emf.win32"
-
-#ifndef PS_JOIN_MASK
-#define PS_JOIN_MASK (PS_JOIN_BEVEL|PS_JOIN_MITER|PS_JOIN_ROUND)
-#endif
-
-#define DPA 0x00A000C9 // TernaryRasterOperation
-
-namespace Inkscape {
-namespace Extension {
-namespace Internal {
-
-static float device_scale = DEVICESCALE;
-static RECTL rc_old;
-static bool clipset = false;
-
-EmfWin32::EmfWin32 (void) // The null constructor
-{
- return;
-}
-
-
-EmfWin32::~EmfWin32 (void) //The destructor
-{
- return;
-}
-
-
-bool
-EmfWin32::check (Inkscape::Extension::Extension * /*module*/)
-{
- if (NULL == Inkscape::Extension::db.get(PRINT_EMF_WIN32))
- return FALSE;
- return TRUE;
-}
-
-
-static void
-emf_print_document_to_file(SPDocument *doc, gchar const *filename)
-{
- Inkscape::Extension::Print *mod;
- SPPrintContext context;
- gchar const *oldconst;
- gchar *oldoutput;
- unsigned int ret;
-
- doc->ensureUpToDate();
-
- mod = Inkscape::Extension::get_print(PRINT_EMF_WIN32);
- oldconst = mod->get_param_string("destination");
- oldoutput = g_strdup(oldconst);
- mod->set_param_string("destination", filename);
-
-/* Start */
- context.module = mod;
- /* fixme: This has to go into module constructor somehow */
- /* Create new arena */
- mod->base = doc->getRoot();
- Inkscape::Drawing drawing;
- mod->dkey = SPItem::display_key_new(1);
- mod->root = mod->base->invoke_show(drawing, mod->dkey, SP_ITEM_SHOW_DISPLAY);
- drawing.setRoot(mod->root);
- /* Print document */
- ret = mod->begin(doc);
- if (ret) {
- g_free(oldoutput);
- throw Inkscape::Extension::Output::save_failed();
- }
- mod->base->invoke_print(&context);
- ret = mod->finish();
- /* Release arena */
- mod->base->invoke_hide(mod->dkey);
- mod->base = NULL;
- mod->root = NULL; // deleted by invoke_hide
-/* end */
-
- mod->set_param_string("destination", oldoutput);
- g_free(oldoutput);
-
- return;
-}
-
-
-void
-EmfWin32::save(Inkscape::Extension::Output *mod, SPDocument *doc, gchar const *filename)
-{
- Inkscape::Extension::Extension * ext;
-
- ext = Inkscape::Extension::db.get(PRINT_EMF_WIN32);
- if (ext == NULL)
- return;
-
- bool old_textToPath = ext->get_param_bool("textToPath");
- bool new_val = mod->get_param_bool("textToPath");
- ext->set_param_bool("textToPath", new_val);
-
- emf_print_document_to_file(doc, filename);
-
- ext->set_param_bool("textToPath", old_textToPath);
-
- return;
-}
-
-
-
-typedef struct {
- int type;
- int level;
- ENHMETARECORD *lpEMFR;
-} EMF_OBJECT, *PEMF_OBJECT;
-
-typedef struct emf_device_context {
- struct SPStyle style;
- class SPTextStyle tstyle;
- bool stroke_set;
- bool fill_set;
-
- SIZEL sizeWnd;
- SIZEL sizeView;
- float PixelsInX, PixelsInY;
- float PixelsOutX, PixelsOutY;
- POINTL winorg;
- POINTL vieworg;
- double ScaleInX, ScaleInY;
- double ScaleOutX, ScaleOutY;
- COLORREF textColor;
- bool textColorSet;
- DWORD textAlign;
- XFORM worldTransform;
- POINTL cur;
-} EMF_DEVICE_CONTEXT, *PEMF_DEVICE_CONTEXT;
-
-#define EMF_MAX_DC 128
-
-typedef struct emf_callback_data {
- Glib::ustring *outsvg;
- Glib::ustring *path;
- Glib::ustring *outdef;
-
- EMF_DEVICE_CONTEXT dc[EMF_MAX_DC+1]; // FIXME: This should be dynamic..
- int level;
-
- double xDPI, yDPI;
- bool pathless_stroke;
- bool inpath;
-
- float MMX;
- float MMY;
- float dwInchesX;
- float dwInchesY;
-
- unsigned int id;
- CHAR *pDesc;
-
- int n_obj;
- PEMF_OBJECT emf_obj;
-} EMF_CALLBACK_DATA, *PEMF_CALLBACK_DATA;
-
-
-static void
-output_style(PEMF_CALLBACK_DATA d, int iType)
-{
-// SVGOStringStream tmp_id;
- SVGOStringStream tmp_style;
- char tmp[1024] = {0};
-
- float fill_rgb[3];
- sp_color_get_rgb_floatv( &(d->dc[d->level].style.fill.value.color), fill_rgb );
-
- float stroke_rgb[3];
- sp_color_get_rgb_floatv(&(d->dc[d->level].style.stroke.value.color), stroke_rgb);
-
-// tmp_id << "\n\tid=\"" << (d->id++) << "\"";
-// *(d->outsvg) += tmp_id.str().c_str();
- *(d->outsvg) += "\n\tstyle=\"";
- if (iType == EMR_STROKEPATH || !d->dc[d->level].fill_set) {
- tmp_style << "fill:none;";
- } else {
- snprintf(tmp, 1023,
- "fill:#%02x%02x%02x;",
- SP_COLOR_F_TO_U(fill_rgb[0]),
- SP_COLOR_F_TO_U(fill_rgb[1]),
- SP_COLOR_F_TO_U(fill_rgb[2]));
- tmp_style << tmp;
- snprintf(tmp, 1023,
- "fill-rule:%s;",
- d->dc[d->level].style.fill_rule.value == 0 ? "evenodd" : "nonzero");
- tmp_style << tmp;
- tmp_style << "fill-opacity:1;";
-
- if (d->dc[d->level].fill_set && d->dc[d->level].stroke_set && d->dc[d->level].style.stroke_width.value == 1 &&
- fill_rgb[0]==stroke_rgb[0] && fill_rgb[1]==stroke_rgb[1] && fill_rgb[2]==stroke_rgb[2])
- {
- d->dc[d->level].stroke_set = false;
- }
- }
-
- if (iType == EMR_FILLPATH || !d->dc[d->level].stroke_set) {
- tmp_style << "stroke:none;";
- } else {
- snprintf(tmp, 1023,
- "stroke:#%02x%02x%02x;",
- SP_COLOR_F_TO_U(stroke_rgb[0]),
- SP_COLOR_F_TO_U(stroke_rgb[1]),
- SP_COLOR_F_TO_U(stroke_rgb[2]));
- tmp_style << tmp;
-
- tmp_style << "stroke-width:" <<
- MAX( 0.001, d->dc[d->level].style.stroke_width.value ) << "px;";
-
- tmp_style << "stroke-linecap:" <<
- (d->dc[d->level].style.stroke_linecap.computed == 0 ? "butt" :
- d->dc[d->level].style.stroke_linecap.computed == 1 ? "round" :
- d->dc[d->level].style.stroke_linecap.computed == 2 ? "square" :
- "unknown") << ";";
-
- tmp_style << "stroke-linejoin:" <<
- (d->dc[d->level].style.stroke_linejoin.computed == 0 ? "miter" :
- d->dc[d->level].style.stroke_linejoin.computed == 1 ? "round" :
- d->dc[d->level].style.stroke_linejoin.computed == 2 ? "bevel" :
- "unknown") << ";";
-
- if (d->dc[d->level].style.stroke_linejoin.computed == 0) {
- tmp_style << "stroke-miterlimit:" <<
- MAX( 0.01, d->dc[d->level].style.stroke_miterlimit.value ) << ";";
- }
-
- if (d->dc[d->level].style.stroke_dasharray_set &&
- d->dc[d->level].style.stroke_dash.n_dash && d->dc[d->level].style.stroke_dash.dash)
- {
- tmp_style << "stroke-dasharray:";
- for (int i=0; idc[d->level].style.stroke_dash.n_dash; i++) {
- if (i)
- tmp_style << ",";
- tmp_style << d->dc[d->level].style.stroke_dash.dash[i];
- }
- tmp_style << ";";
- tmp_style << "stroke-dashoffset:0;";
- } else {
- tmp_style << "stroke-dasharray:none;";
- }
- tmp_style << "stroke-opacity:1;";
- }
- tmp_style << "\" ";
- if (clipset)
- tmp_style << "\n\tclip-path=\"url(#clipEmfPath" << d->id << ")\" ";
- clipset = false;
-
- *(d->outsvg) += tmp_style.str().c_str();
-}
-
-
-static double
-_pix_x_to_point(PEMF_CALLBACK_DATA d, double px)
-{
- double tmp = px - d->dc[d->level].winorg.x;
- tmp *= d->dc[d->level].ScaleInX ? d->dc[d->level].ScaleInX : 1.0;
- tmp += d->dc[d->level].vieworg.x;
- return tmp;
-}
-
-static double
-_pix_y_to_point(PEMF_CALLBACK_DATA d, double px)
-{
- double tmp = px - d->dc[d->level].winorg.y;
- tmp *= d->dc[d->level].ScaleInY ? d->dc[d->level].ScaleInY : 1.0;
- tmp += d->dc[d->level].vieworg.y;
- return tmp;
-}
-
-
-static double
-pix_to_x_point(PEMF_CALLBACK_DATA d, double px, double py)
-{
- double ppx = _pix_x_to_point(d, px);
- double ppy = _pix_y_to_point(d, py);
-
- double x = ppx * d->dc[d->level].worldTransform.eM11 + ppy * d->dc[d->level].worldTransform.eM21 + d->dc[d->level].worldTransform.eDx;
- x *= device_scale;
-
- return x;
-}
-
-static double
-pix_to_y_point(PEMF_CALLBACK_DATA d, double px, double py)
-{
- double ppx = _pix_x_to_point(d, px);
- double ppy = _pix_y_to_point(d, py);
-
- double y = ppx * d->dc[d->level].worldTransform.eM12 + ppy * d->dc[d->level].worldTransform.eM22 + d->dc[d->level].worldTransform.eDy;
- y *= device_scale;
-
- return y;
-}
-
-static double
-pix_to_size_point(PEMF_CALLBACK_DATA d, double px)
-{
- double ppx = px * (d->dc[d->level].ScaleInX ? d->dc[d->level].ScaleInX : 1.0);
- double ppy = 0;
-
- double dx = ppx * d->dc[d->level].worldTransform.eM11 + ppy * d->dc[d->level].worldTransform.eM21;
- dx *= device_scale;
- double dy = ppx * d->dc[d->level].worldTransform.eM12 + ppy * d->dc[d->level].worldTransform.eM22;
- dy *= device_scale;
-
- double tmp = sqrt(dx * dx + dy * dy);
- return tmp;
-}
-
-
-static void
-select_pen(PEMF_CALLBACK_DATA d, int index)
-{
- PEMRCREATEPEN pEmr = NULL;
-
- if (index >= 0 && index < d->n_obj)
- pEmr = (PEMRCREATEPEN) d->emf_obj[index].lpEMFR;
-
- if (!pEmr)
- return;
-
- switch (pEmr->lopn.lopnStyle & PS_STYLE_MASK) {
- case PS_DASH:
- case PS_DOT:
- case PS_DASHDOT:
- case PS_DASHDOTDOT:
- {
- int i = 0;
- int penstyle = (pEmr->lopn.lopnStyle & PS_STYLE_MASK);
- d->dc[d->level].style.stroke_dash.n_dash =
- penstyle == PS_DASHDOTDOT ? 6 : penstyle == PS_DASHDOT ? 4 : 2;
- if (d->dc[d->level].style.stroke_dash.dash && (d->level==0 || (d->level>0 && d->dc[d->level].style.stroke_dash.dash!=d->dc[d->level-1].style.stroke_dash.dash)))
- delete[] d->dc[d->level].style.stroke_dash.dash;
- d->dc[d->level].style.stroke_dash.dash = new double[d->dc[d->level].style.stroke_dash.n_dash];
- if (penstyle==PS_DASH || penstyle==PS_DASHDOT || penstyle==PS_DASHDOTDOT) {
- d->dc[d->level].style.stroke_dash.dash[i++] = 3;
- d->dc[d->level].style.stroke_dash.dash[i++] = 1;
- }
- if (penstyle==PS_DOT || penstyle==PS_DASHDOT || penstyle==PS_DASHDOTDOT) {
- d->dc[d->level].style.stroke_dash.dash[i++] = 1;
- d->dc[d->level].style.stroke_dash.dash[i++] = 1;
- }
- if (penstyle==PS_DASHDOTDOT) {
- d->dc[d->level].style.stroke_dash.dash[i++] = 1;
- d->dc[d->level].style.stroke_dash.dash[i++] = 1;
- }
-
- d->dc[d->level].style.stroke_dasharray_set = 1;
- break;
- }
-
- case PS_SOLID:
- default:
- {
- d->dc[d->level].style.stroke_dasharray_set = 0;
- break;
- }
- }
-
- switch (pEmr->lopn.lopnStyle & PS_ENDCAP_MASK) {
- case PS_ENDCAP_ROUND:
- {
- d->dc[d->level].style.stroke_linecap.computed = 1;
- break;
- }
- case PS_ENDCAP_SQUARE:
- {
- d->dc[d->level].style.stroke_linecap.computed = 2;
- break;
- }
- case PS_ENDCAP_FLAT:
- default:
- {
- d->dc[d->level].style.stroke_linecap.computed = 0;
- break;
- }
- }
-
- switch (pEmr->lopn.lopnStyle & PS_JOIN_MASK) {
- case PS_JOIN_BEVEL:
- {
- d->dc[d->level].style.stroke_linejoin.computed = 2;
- break;
- }
- case PS_JOIN_MITER:
- {
- d->dc[d->level].style.stroke_linejoin.computed = 0;
- break;
- }
- case PS_JOIN_ROUND:
- default:
- {
- d->dc[d->level].style.stroke_linejoin.computed = 1;
- break;
- }
- }
-
- d->dc[d->level].stroke_set = true;
-
- if (pEmr->lopn.lopnStyle == PS_NULL) {
- d->dc[d->level].style.stroke_width.value = 0;
- d->dc[d->level].stroke_set = false;
- } else if (pEmr->lopn.lopnWidth.x) {
- int cur_level = d->level;
- d->level = d->emf_obj[index].level;
- double pen_width = pix_to_size_point( d, pEmr->lopn.lopnWidth.x );
- d->level = cur_level;
- d->dc[d->level].style.stroke_width.value = pen_width;
- } else { // this stroke should always be rendered as 1 pixel wide, independent of zoom level (can that be done in SVG?)
- //d->dc[d->level].style.stroke_width.value = 1.0;
- int cur_level = d->level;
- d->level = d->emf_obj[index].level;
- double pen_width = pix_to_size_point( d, 1 );
- d->level = cur_level;
- d->dc[d->level].style.stroke_width.value = pen_width;
- }
-
- double r, g, b;
- r = SP_COLOR_U_TO_F( GetRValue(pEmr->lopn.lopnColor) );
- g = SP_COLOR_U_TO_F( GetGValue(pEmr->lopn.lopnColor) );
- b = SP_COLOR_U_TO_F( GetBValue(pEmr->lopn.lopnColor) );
- d->dc[d->level].style.stroke.value.color.set( r, g, b );
-}
-
-
-static void
-select_extpen(PEMF_CALLBACK_DATA d, int index)
-{
- PEMREXTCREATEPEN pEmr = NULL;
-
- if (index >= 0 && index < d->n_obj)
- pEmr = (PEMREXTCREATEPEN) d->emf_obj[index].lpEMFR;
-
- if (!pEmr)
- return;
-
- switch (pEmr->elp.elpPenStyle & PS_STYLE_MASK) {
- case PS_USERSTYLE:
- {
- if (pEmr->elp.elpNumEntries) {
- d->dc[d->level].style.stroke_dash.n_dash = pEmr->elp.elpNumEntries;
- if (d->dc[d->level].style.stroke_dash.dash && (d->level==0 || (d->level>0 && d->dc[d->level].style.stroke_dash.dash!=d->dc[d->level-1].style.stroke_dash.dash)))
- delete[] d->dc[d->level].style.stroke_dash.dash;
- d->dc[d->level].style.stroke_dash.dash = new double[pEmr->elp.elpNumEntries];
- for (unsigned int i=0; ielp.elpNumEntries; i++) {
- int cur_level = d->level;
- d->level = d->emf_obj[index].level;
- double dash_length = pix_to_size_point( d, pEmr->elp.elpStyleEntry[i] );
- d->level = cur_level;
- d->dc[d->level].style.stroke_dash.dash[i] = dash_length;
- }
- d->dc[d->level].style.stroke_dasharray_set = 1;
- } else {
- d->dc[d->level].style.stroke_dasharray_set = 0;
- }
- break;
- }
-
- case PS_DASH:
- case PS_DOT:
- case PS_DASHDOT:
- case PS_DASHDOTDOT:
- {
- int i = 0;
- int penstyle = (pEmr->elp.elpPenStyle & PS_STYLE_MASK);
- d->dc[d->level].style.stroke_dash.n_dash =
- penstyle == PS_DASHDOTDOT ? 6 : penstyle == PS_DASHDOT ? 4 : 2;
- if (d->dc[d->level].style.stroke_dash.dash && (d->level==0 || (d->level>0 && d->dc[d->level].style.stroke_dash.dash!=d->dc[d->level-1].style.stroke_dash.dash)))
- delete[] d->dc[d->level].style.stroke_dash.dash;
- d->dc[d->level].style.stroke_dash.dash = new double[d->dc[d->level].style.stroke_dash.n_dash];
- if (penstyle==PS_DASH || penstyle==PS_DASHDOT || penstyle==PS_DASHDOTDOT) {
- d->dc[d->level].style.stroke_dash.dash[i++] = 3;
- d->dc[d->level].style.stroke_dash.dash[i++] = 2;
- }
- if (penstyle==PS_DOT || penstyle==PS_DASHDOT || penstyle==PS_DASHDOTDOT) {
- d->dc[d->level].style.stroke_dash.dash[i++] = 1;
- d->dc[d->level].style.stroke_dash.dash[i++] = 2;
- }
- if (penstyle==PS_DASHDOTDOT) {
- d->dc[d->level].style.stroke_dash.dash[i++] = 1;
- d->dc[d->level].style.stroke_dash.dash[i++] = 2;
- }
-
- d->dc[d->level].style.stroke_dasharray_set = 1;
- break;
- }
-
- case PS_SOLID:
- default:
- {
- d->dc[d->level].style.stroke_dasharray_set = 0;
- break;
- }
- }
-
- switch (pEmr->elp.elpPenStyle & PS_ENDCAP_MASK) {
- case PS_ENDCAP_ROUND:
- {
- d->dc[d->level].style.stroke_linecap.computed = 1;
- break;
- }
- case PS_ENDCAP_SQUARE:
- {
- d->dc[d->level].style.stroke_linecap.computed = 2;
- break;
- }
- case PS_ENDCAP_FLAT:
- default:
- {
- d->dc[d->level].style.stroke_linecap.computed = 0;
- break;
- }
- }
-
- switch (pEmr->elp.elpPenStyle & PS_JOIN_MASK) {
- case PS_JOIN_BEVEL:
- {
- d->dc[d->level].style.stroke_linejoin.computed = 2;
- break;
- }
- case PS_JOIN_MITER:
- {
- d->dc[d->level].style.stroke_linejoin.computed = 0;
- break;
- }
- case PS_JOIN_ROUND:
- default:
- {
- d->dc[d->level].style.stroke_linejoin.computed = 1;
- break;
- }
- }
-
- d->dc[d->level].stroke_set = true;
-
- if (pEmr->elp.elpPenStyle == PS_NULL) {
- d->dc[d->level].style.stroke_width.value = 0;
- d->dc[d->level].stroke_set = false;
- } else if (pEmr->elp.elpWidth) {
- int cur_level = d->level;
- d->level = d->emf_obj[index].level;
- double pen_width = pix_to_size_point( d, pEmr->elp.elpWidth );
- d->level = cur_level;
- d->dc[d->level].style.stroke_width.value = pen_width;
- } else { // this stroke should always be rendered as 1 pixel wide, independent of zoom level (can that be done in SVG?)
- //d->dc[d->level].style.stroke_width.value = 1.0;
- int cur_level = d->level;
- d->level = d->emf_obj[index].level;
- double pen_width = pix_to_size_point( d, 1 );
- d->level = cur_level;
- d->dc[d->level].style.stroke_width.value = pen_width;
- }
-
- double r, g, b;
- r = SP_COLOR_U_TO_F( GetRValue(pEmr->elp.elpColor) );
- g = SP_COLOR_U_TO_F( GetGValue(pEmr->elp.elpColor) );
- b = SP_COLOR_U_TO_F( GetBValue(pEmr->elp.elpColor) );
-
- d->dc[d->level].style.stroke.value.color.set( r, g, b );
-}
-
-
-static void
-select_brush(PEMF_CALLBACK_DATA d, int index)
-{
- PEMRCREATEBRUSHINDIRECT pEmr = NULL;
-
- if (index >= 0 && index < d->n_obj)
- pEmr = (PEMRCREATEBRUSHINDIRECT) d->emf_obj[index].lpEMFR;
-
- if (!pEmr)
- return;
-
- if (pEmr->lb.lbStyle == BS_SOLID) {
- double r, g, b;
- r = SP_COLOR_U_TO_F( GetRValue(pEmr->lb.lbColor) );
- g = SP_COLOR_U_TO_F( GetGValue(pEmr->lb.lbColor) );
- b = SP_COLOR_U_TO_F( GetBValue(pEmr->lb.lbColor) );
- d->dc[d->level].style.fill.value.color.set( r, g, b );
- }
-
- d->dc[d->level].fill_set = true;
-}
-
-
-static void
-select_font(PEMF_CALLBACK_DATA d, int index)
-{
- PEMREXTCREATEFONTINDIRECTW pEmr = NULL;
-
- if (index >= 0 && index < d->n_obj)
- pEmr = (PEMREXTCREATEFONTINDIRECTW) d->emf_obj[index].lpEMFR;
-
- if (!pEmr)
- return;
-
- int cur_level = d->level;
- d->level = d->emf_obj[index].level;
- double font_size = pix_to_size_point( d, pEmr->elfw.elfLogFont.lfHeight );
- d->level = cur_level;
- d->dc[d->level].style.font_size.computed = font_size;
- d->dc[d->level].style.font_weight.value =
- pEmr->elfw.elfLogFont.lfWeight == FW_THIN ? SP_CSS_FONT_WEIGHT_100 :
- pEmr->elfw.elfLogFont.lfWeight == FW_EXTRALIGHT ? SP_CSS_FONT_WEIGHT_200 :
- pEmr->elfw.elfLogFont.lfWeight == FW_LIGHT ? SP_CSS_FONT_WEIGHT_300 :
- pEmr->elfw.elfLogFont.lfWeight == FW_NORMAL ? SP_CSS_FONT_WEIGHT_400 :
- pEmr->elfw.elfLogFont.lfWeight == FW_MEDIUM ? SP_CSS_FONT_WEIGHT_500 :
- pEmr->elfw.elfLogFont.lfWeight == FW_SEMIBOLD ? SP_CSS_FONT_WEIGHT_600 :
- pEmr->elfw.elfLogFont.lfWeight == FW_BOLD ? SP_CSS_FONT_WEIGHT_700 :
- pEmr->elfw.elfLogFont.lfWeight == FW_EXTRABOLD ? SP_CSS_FONT_WEIGHT_800 :
- pEmr->elfw.elfLogFont.lfWeight == FW_HEAVY ? SP_CSS_FONT_WEIGHT_900 :
- pEmr->elfw.elfLogFont.lfWeight == FW_NORMAL ? SP_CSS_FONT_WEIGHT_NORMAL :
- pEmr->elfw.elfLogFont.lfWeight == FW_BOLD ? SP_CSS_FONT_WEIGHT_BOLD :
- pEmr->elfw.elfLogFont.lfWeight == FW_EXTRALIGHT ? SP_CSS_FONT_WEIGHT_LIGHTER :
- pEmr->elfw.elfLogFont.lfWeight == FW_EXTRABOLD ? SP_CSS_FONT_WEIGHT_BOLDER :
- FW_NORMAL;
- d->dc[d->level].style.font_style.value = (pEmr->elfw.elfLogFont.lfItalic ? SP_CSS_FONT_STYLE_ITALIC : SP_CSS_FONT_STYLE_NORMAL);
- d->dc[d->level].style.text_decoration.underline = pEmr->elfw.elfLogFont.lfUnderline;
- d->dc[d->level].style.text_decoration.line_through = pEmr->elfw.elfLogFont.lfStrikeOut;
- if (d->dc[d->level].tstyle.font_family.value)
- g_free(d->dc[d->level].tstyle.font_family.value);
- d->dc[d->level].tstyle.font_family.value =
- (gchar *) g_utf16_to_utf8( (gunichar2*) pEmr->elfw.elfLogFont.lfFaceName, -1, NULL, NULL, NULL );
- d->dc[d->level].style.baseline_shift.value = ((pEmr->elfw.elfLogFont.lfEscapement + 3600) % 3600) / 10; // use baseline_shift instead of text_transform to avoid overflow
-}
-
-static void
-delete_object(PEMF_CALLBACK_DATA d, int index)
-{
- if (index >= 0 && index < d->n_obj) {
- d->emf_obj[index].type = 0;
- if (d->emf_obj[index].lpEMFR)
- free(d->emf_obj[index].lpEMFR);
- d->emf_obj[index].lpEMFR = NULL;
- }
-}
-
-
-static void
-insert_object(PEMF_CALLBACK_DATA d, int index, int type, ENHMETARECORD *pObj)
-{
- if (index >= 0 && index < d->n_obj) {
- delete_object(d, index);
- d->emf_obj[index].type = type;
- d->emf_obj[index].level = d->level;
- d->emf_obj[index].lpEMFR = pObj;
- }
-}
-
-static void
-assert_empty_path(PEMF_CALLBACK_DATA d, const char * /*fun*/)
-{
- if (!d->path->empty()) {
- // g_debug("emf-win32-inout: assert_empty_path failed for %s\n", fun);
-
- *(d->outsvg) += "\n";
-
- *(d->path) = "";
- }
-}
-
-
-static int CALLBACK
-myEnhMetaFileProc(HDC /*hDC*/, HANDLETABLE * /*lpHTable*/, ENHMETARECORD const *lpEMFR, int /*nObj*/, LPARAM lpData)
-{
- PEMF_CALLBACK_DATA d;
- SVGOStringStream tmp_outsvg;
- SVGOStringStream tmp_path;
- SVGOStringStream tmp_str;
- SVGOStringStream dbg_str;
-
- d = (PEMF_CALLBACK_DATA) lpData;
-
- if (d->pathless_stroke) {
- if (lpEMFR->iType!=EMR_POLYBEZIERTO && lpEMFR->iType!=EMR_POLYBEZIERTO16 &&
- lpEMFR->iType!=EMR_POLYLINETO && lpEMFR->iType!=EMR_POLYLINETO16 &&
- lpEMFR->iType!=EMR_LINETO && lpEMFR->iType!=EMR_ARCTO &&
- lpEMFR->iType!=EMR_SETBKCOLOR && lpEMFR->iType!=EMR_SETROP2 &&
- lpEMFR->iType!=EMR_SETBKMODE && lpEMFR->iType!=EMR_SELECTOBJECT &&
- lpEMFR->iType!=EMR_BEGINPATH)
- {
- *(d->outsvg) += " outsvg) += "\n\t";
- *(d->outsvg) += *(d->path);
- *(d->outsvg) += " \" /> \n";
- *(d->path) = "";
- d->pathless_stroke = false;
- }
- }
-
- switch (lpEMFR->iType)
- {
- case EMR_HEADER:
- {
- dbg_str << "\n";
-
- *(d->outdef) += "\n";
-
- if (d->pDesc) {
- *(d->outdef) += "\n";
- }
-
- ENHMETAHEADER *pEmr = (ENHMETAHEADER *) lpEMFR;
- SVGOStringStream tmp_outdef;
- tmp_outdef << "\n";
- *(d->outsvg) = *(d->outdef) + *(d->outsvg);
- break;
- }
- case EMR_SETPIXELV:
- dbg_str << "\n";
- break;
- case EMR_SETMAPPERFLAGS:
- dbg_str << "\n";
- break;
- case EMR_SETMAPMODE:
- dbg_str << "\n";
- break;
- case EMR_SETBKMODE:
- dbg_str << "\n";
- break;
- case EMR_SETPOLYFILLMODE:
- {
- dbg_str << "\n";
-
- PEMRSETPOLYFILLMODE pEmr = (PEMRSETPOLYFILLMODE) lpEMFR;
- d->dc[d->level].style.fill_rule.value =
- (pEmr->iMode == ALTERNATE ? 0 :
- pEmr->iMode == WINDING ? 1 : 0);
- break;
- }
- case EMR_SETROP2:
- dbg_str << "\n";
- break;
- case EMR_SETSTRETCHBLTMODE:
- dbg_str << "\n";
- break;
- case EMR_SETTEXTALIGN:
- {
- dbg_str << "\n";
-
- PEMRSETTEXTALIGN pEmr = (PEMRSETTEXTALIGN) lpEMFR;
- d->dc[d->level].textAlign = pEmr->iMode;
- break;
- }
- case EMR_SETCOLORADJUSTMENT:
- dbg_str << "\n";
- break;
- case EMR_SETTEXTCOLOR:
- {
- dbg_str << "\n";
-
- PEMRSETTEXTCOLOR pEmr = (PEMRSETTEXTCOLOR) lpEMFR;
- d->dc[d->level].textColor = pEmr->crColor;
- d->dc[d->level].textColorSet = true;
- break;
- }
- case EMR_SETBKCOLOR:
- dbg_str << "\n";
- break;
- case EMR_OFFSETCLIPRGN:
- dbg_str << "\n";
- break;
- case EMR_MOVETOEX:
- {
- dbg_str << "\n";
-
- PEMRMOVETOEX pEmr = (PEMRMOVETOEX) lpEMFR;
-
- if (d->path->empty()) {
- d->pathless_stroke = true;
- *(d->path) = "d=\"";
- }
-
- d->dc[d->level].cur = pEmr->ptl;
-
- tmp_path <<
- "\n\tM " <<
- pix_to_x_point( d, pEmr->ptl.x, pEmr->ptl.y ) << " " <<
- pix_to_y_point( d, pEmr->ptl.x, pEmr->ptl.y ) << " ";
- break;
- }
- case EMR_SETMETARGN:
- dbg_str << "\n";
- break;
- case EMR_EXCLUDECLIPRECT:
- dbg_str << "\n";
- break;
- case EMR_INTERSECTCLIPRECT:
- {
- dbg_str << "\n";
-
- PEMRINTERSECTCLIPRECT pEmr = (PEMRINTERSECTCLIPRECT) lpEMFR;
- RECTL rc = pEmr->rclClip;
- clipset = true;
- if ((rc.left == rc_old.left) && (rc.top == rc_old.top) && (rc.right == rc_old.right) && (rc.bottom == rc_old.bottom))
- break;
- rc_old = rc;
-
- double l = pix_to_x_point( d, rc.left, rc.top );
- double t = pix_to_y_point( d, rc.left, rc.top );
- double r = pix_to_x_point( d, rc.right, rc.bottom );
- double b = pix_to_y_point( d, rc.right, rc.bottom );
-
- SVGOStringStream tmp_rectangle;
- tmp_rectangle << "\nid) << "\" >";
- tmp_rectangle << "\n";
- tmp_rectangle << "\n";
-
- assert_empty_path(d, "EMR_RECTANGLE");
-
- *(d->outdef) += tmp_rectangle.str().c_str();
- *(d->path) = "";
- break;
- }
- case EMR_SCALEVIEWPORTEXTEX:
- dbg_str << "\n";
- break;
- case EMR_SCALEWINDOWEXTEX:
- dbg_str << "\n";
- break;
- case EMR_SAVEDC:
- dbg_str << "\n";
-
- if (d->level < EMF_MAX_DC) {
- d->dc[d->level + 1] = d->dc[d->level];
- d->level = d->level + 1;
- }
- break;
- case EMR_RESTOREDC:
- {
- dbg_str << "\n";
-
- PEMRRESTOREDC pEmr = (PEMRRESTOREDC) lpEMFR;
- int old_level = d->level;
- if (pEmr->iRelative >= 0) {
- if (pEmr->iRelative < d->level)
- d->level = pEmr->iRelative;
- }
- else {
- if (d->level + pEmr->iRelative >= 0)
- d->level = d->level + pEmr->iRelative;
- }
- while (old_level > d->level) {
- if (d->dc[old_level].style.stroke_dash.dash && (old_level==0 || (old_level>0 && d->dc[old_level].style.stroke_dash.dash!=d->dc[old_level-1].style.stroke_dash.dash)))
- delete[] d->dc[old_level].style.stroke_dash.dash;
- old_level--;
- }
- break;
- }
- case EMR_SETWORLDTRANSFORM:
- {
- dbg_str << "\n";
-
- PEMRSETWORLDTRANSFORM pEmr = (PEMRSETWORLDTRANSFORM) lpEMFR;
- d->dc[d->level].worldTransform = pEmr->xform;
- break;
- }
- case EMR_MODIFYWORLDTRANSFORM:
- {
- dbg_str << "\n";
-
- PEMRMODIFYWORLDTRANSFORM pEmr = (PEMRMODIFYWORLDTRANSFORM) lpEMFR;
- switch (pEmr->iMode)
- {
- case MWT_IDENTITY:
- d->dc[d->level].worldTransform.eM11 = 1.0;
- d->dc[d->level].worldTransform.eM12 = 0.0;
- d->dc[d->level].worldTransform.eM21 = 0.0;
- d->dc[d->level].worldTransform.eM22 = 1.0;
- d->dc[d->level].worldTransform.eDx = 0.0;
- d->dc[d->level].worldTransform.eDy = 0.0;
- break;
- case MWT_LEFTMULTIPLY:
- {
-// d->dc[d->level].worldTransform = pEmr->xform * worldTransform;
-
- float a11 = pEmr->xform.eM11;
- float a12 = pEmr->xform.eM12;
- float a13 = 0.0;
- float a21 = pEmr->xform.eM21;
- float a22 = pEmr->xform.eM22;
- float a23 = 0.0;
- float a31 = pEmr->xform.eDx;
- float a32 = pEmr->xform.eDy;
- float a33 = 1.0;
-
- float b11 = d->dc[d->level].worldTransform.eM11;
- float b12 = d->dc[d->level].worldTransform.eM12;
- //float b13 = 0.0;
- float b21 = d->dc[d->level].worldTransform.eM21;
- float b22 = d->dc[d->level].worldTransform.eM22;
- //float b23 = 0.0;
- float b31 = d->dc[d->level].worldTransform.eDx;
- float b32 = d->dc[d->level].worldTransform.eDy;
- //float b33 = 1.0;
-
- float c11 = a11*b11 + a12*b21 + a13*b31;;
- float c12 = a11*b12 + a12*b22 + a13*b32;;
- //float c13 = a11*b13 + a12*b23 + a13*b33;;
- float c21 = a21*b11 + a22*b21 + a23*b31;;
- float c22 = a21*b12 + a22*b22 + a23*b32;;
- //float c23 = a21*b13 + a22*b23 + a23*b33;;
- float c31 = a31*b11 + a32*b21 + a33*b31;;
- float c32 = a31*b12 + a32*b22 + a33*b32;;
- //float c33 = a31*b13 + a32*b23 + a33*b33;;
-
- d->dc[d->level].worldTransform.eM11 = c11;;
- d->dc[d->level].worldTransform.eM12 = c12;;
- d->dc[d->level].worldTransform.eM21 = c21;;
- d->dc[d->level].worldTransform.eM22 = c22;;
- d->dc[d->level].worldTransform.eDx = c31;
- d->dc[d->level].worldTransform.eDy = c32;
-
- break;
- }
- case MWT_RIGHTMULTIPLY:
- {
-// d->dc[d->level].worldTransform = worldTransform * pEmr->xform;
-
- float a11 = d->dc[d->level].worldTransform.eM11;
- float a12 = d->dc[d->level].worldTransform.eM12;
- float a13 = 0.0;
- float a21 = d->dc[d->level].worldTransform.eM21;
- float a22 = d->dc[d->level].worldTransform.eM22;
- float a23 = 0.0;
- float a31 = d->dc[d->level].worldTransform.eDx;
- float a32 = d->dc[d->level].worldTransform.eDy;
- float a33 = 1.0;
-
- float b11 = pEmr->xform.eM11;
- float b12 = pEmr->xform.eM12;
- //float b13 = 0.0;
- float b21 = pEmr->xform.eM21;
- float b22 = pEmr->xform.eM22;
- //float b23 = 0.0;
- float b31 = pEmr->xform.eDx;
- float b32 = pEmr->xform.eDy;
- //float b33 = 1.0;
-
- float c11 = a11*b11 + a12*b21 + a13*b31;;
- float c12 = a11*b12 + a12*b22 + a13*b32;;
- //float c13 = a11*b13 + a12*b23 + a13*b33;;
- float c21 = a21*b11 + a22*b21 + a23*b31;;
- float c22 = a21*b12 + a22*b22 + a23*b32;;
- //float c23 = a21*b13 + a22*b23 + a23*b33;;
- float c31 = a31*b11 + a32*b21 + a33*b31;;
- float c32 = a31*b12 + a32*b22 + a33*b32;;
- //float c33 = a31*b13 + a32*b23 + a33*b33;;
-
- d->dc[d->level].worldTransform.eM11 = c11;;
- d->dc[d->level].worldTransform.eM12 = c12;;
- d->dc[d->level].worldTransform.eM21 = c21;;
- d->dc[d->level].worldTransform.eM22 = c22;;
- d->dc[d->level].worldTransform.eDx = c31;
- d->dc[d->level].worldTransform.eDy = c32;
-
- break;
- }
-// case MWT_SET:
- default:
- d->dc[d->level].worldTransform = pEmr->xform;
- break;
- }
- break;
- }
- case EMR_SELECTOBJECT:
- {
- dbg_str << "\n";
-
- PEMRSELECTOBJECT pEmr = (PEMRSELECTOBJECT) lpEMFR;
- unsigned int index = pEmr->ihObject;
-
- if (index >= ENHMETA_STOCK_OBJECT) {
- index -= ENHMETA_STOCK_OBJECT;
- switch (index) {
- case NULL_BRUSH:
- d->dc[d->level].fill_set = false;
- break;
- case BLACK_BRUSH:
- case DKGRAY_BRUSH:
- case GRAY_BRUSH:
- case LTGRAY_BRUSH:
- case WHITE_BRUSH:
- {
- float val = 0;
- switch (index) {
- case BLACK_BRUSH:
- val = 0.0 / 255.0;
- break;
- case DKGRAY_BRUSH:
- val = 64.0 / 255.0;
- break;
- case GRAY_BRUSH:
- val = 128.0 / 255.0;
- break;
- case LTGRAY_BRUSH:
- val = 192.0 / 255.0;
- break;
- case WHITE_BRUSH:
- val = 255.0 / 255.0;
- break;
- }
- d->dc[d->level].style.fill.value.color.set( val, val, val );
-
- d->dc[d->level].fill_set = true;
- break;
- }
- case NULL_PEN:
- d->dc[d->level].stroke_set = false;
- break;
- case BLACK_PEN:
- case WHITE_PEN:
- {
- float val = index == BLACK_PEN ? 0 : 1;
- d->dc[d->level].style.stroke_dasharray_set = 0;
- d->dc[d->level].style.stroke_width.value = 1.0;
- d->dc[d->level].style.stroke.value.color.set( val, val, val );
-
- d->dc[d->level].stroke_set = true;
-
- break;
- }
- }
- } else {
- if ( /*index >= 0 &&*/ index < (unsigned int) d->n_obj) {
- switch (d->emf_obj[index].type)
- {
- case EMR_CREATEPEN:
- select_pen(d, index);
- break;
- case EMR_CREATEBRUSHINDIRECT:
- select_brush(d, index);
- break;
- case EMR_EXTCREATEPEN:
- select_extpen(d, index);
- break;
- case EMR_EXTCREATEFONTINDIRECTW:
- select_font(d, index);
- break;
- }
- }
- }
- break;
- }
- case EMR_CREATEPEN:
- {
- dbg_str << "\n";
-
- PEMRCREATEPEN pEmr = (PEMRCREATEPEN) lpEMFR;
- int index = pEmr->ihPen;
-
- EMRCREATEPEN *pPen =
- (EMRCREATEPEN *) malloc( sizeof(EMRCREATEPEN) );
- pPen->lopn = pEmr->lopn;
- insert_object(d, index, EMR_CREATEPEN, (ENHMETARECORD *) pPen);
-
- break;
- }
- case EMR_CREATEBRUSHINDIRECT:
- {
- dbg_str << "\n";
-
- PEMRCREATEBRUSHINDIRECT pEmr = (PEMRCREATEBRUSHINDIRECT) lpEMFR;
- int index = pEmr->ihBrush;
-
- EMRCREATEBRUSHINDIRECT *pBrush =
- (EMRCREATEBRUSHINDIRECT *) malloc( sizeof(EMRCREATEBRUSHINDIRECT) );
- pBrush->lb = pEmr->lb;
- insert_object(d, index, EMR_CREATEBRUSHINDIRECT, (ENHMETARECORD *) pBrush);
-
- break;
- }
- case EMR_DELETEOBJECT:
- dbg_str << "\n";
- break;
- case EMR_ANGLEARC:
- dbg_str << "\n";
- break;
- case EMR_ELLIPSE:
- {
- dbg_str << "\n";
-
- PEMRELLIPSE pEmr = (PEMRELLIPSE) lpEMFR;
- RECTL rclBox = pEmr->rclBox;
-
- double l = pix_to_x_point( d, pEmr->rclBox.left, pEmr->rclBox.top );
- double t = pix_to_y_point( d, pEmr->rclBox.left, pEmr->rclBox.top );
- double r = pix_to_x_point( d, pEmr->rclBox.right, pEmr->rclBox.bottom );
- double b = pix_to_y_point( d, pEmr->rclBox.right, pEmr->rclBox.bottom );
-
- double cx = (l + r) / 2.0;
- double cy = (t + b) / 2.0;
- double rx = fabs(l - r) / 2.0;
- double ry = fabs(t - b) / 2.0;
-
- SVGOStringStream tmp_ellipse;
- tmp_ellipse << "cx=\"" << cx << "\" ";
- tmp_ellipse << "cy=\"" << cy << "\" ";
- tmp_ellipse << "rx=\"" << rx << "\" ";
- tmp_ellipse << "ry=\"" << ry << "\" ";
-
- assert_empty_path(d, "EMR_ELLIPSE");
-
- *(d->outsvg) += " iType);
- *(d->outsvg) += "\n\t";
- *(d->outsvg) += tmp_ellipse.str().c_str();
- *(d->outsvg) += "/> \n";
- *(d->path) = "";
- break;
- }
- case EMR_RECTANGLE:
- {
- dbg_str << "\n";
-
- PEMRRECTANGLE pEmr = (PEMRRECTANGLE) lpEMFR;
- RECTL rc = pEmr->rclBox;
-
- double l = pix_to_x_point( d, rc.left, rc.top );
- double t = pix_to_y_point( d, rc.left, rc.top );
- double r = pix_to_x_point( d, rc.right, rc.bottom );
- double b = pix_to_y_point( d, rc.right, rc.bottom );
-
- SVGOStringStream tmp_rectangle;
- tmp_rectangle << "d=\"";
- tmp_rectangle << "\n\tM " << l << " " << t << " ";
- tmp_rectangle << "\n\tL " << r << " " << t << " ";
- tmp_rectangle << "\n\tL " << r << " " << b << " ";
- tmp_rectangle << "\n\tL " << l << " " << b << " ";
- tmp_rectangle << "\n\tz";
-
- assert_empty_path(d, "EMR_RECTANGLE");
-
- *(d->outsvg) += " iType);
- *(d->outsvg) += "\n\t";
- *(d->outsvg) += tmp_rectangle.str().c_str();
- *(d->outsvg) += " \" /> \n";
- *(d->path) = "";
- break;
- }
- case EMR_ROUNDRECT:
- {
- dbg_str << "\n";
-
- PEMRROUNDRECT pEmr = (PEMRROUNDRECT) lpEMFR;
- RECTL rc = pEmr->rclBox;
- SIZEL corner = pEmr->szlCorner;
- double f = 4.*(sqrt(2) - 1)/3;
-
- double l = pix_to_x_point(d, rc.left, rc.top);
- double t = pix_to_y_point(d, rc.left, rc.top);
- double r = pix_to_x_point(d, rc.right, rc.bottom);
- double b = pix_to_y_point(d, rc.right, rc.bottom);
- double cnx = pix_to_size_point(d, corner.cx/2);
- double cny = pix_to_size_point(d, corner.cy/2);
-
- SVGOStringStream tmp_rectangle;
- tmp_rectangle << "d=\"";
- tmp_rectangle << "\n\tM " << l << ", " << t + cny << " ";
- tmp_rectangle << "\n\tC " << l << ", " << t + (1-f)*cny << " " << l + (1-f)*cnx << ", " << t << " " << l + cnx << ", " << t << " ";
- tmp_rectangle << "\n\tL " << r - cnx << ", " << t << " ";
- tmp_rectangle << "\n\tC " << r - (1-f)*cnx << ", " << t << " " << r << ", " << t + (1-f)*cny << " " << r << ", " << t + cny << " ";
- tmp_rectangle << "\n\tL " << r << ", " << b - cny << " ";
- tmp_rectangle << "\n\tC " << r << ", " << b - (1-f)*cny << " " << r - (1-f)*cnx << ", " << b << " " << r - cnx << ", " << b << " ";
- tmp_rectangle << "\n\tL " << l + cnx << ", " << b << " ";
- tmp_rectangle << "\n\tC " << l + (1-f)*cnx << ", " << b << " " << l << ", " << b - (1-f)*cny << " " << l << ", " << b - cny << " ";
- tmp_rectangle << "\n\tz";
- assert_empty_path(d, "EMR_ROUNDRECT");
-
- *(d->outsvg) += " iType);
- *(d->outsvg) += "\n\t";
- *(d->outsvg) += tmp_rectangle.str().c_str();
- *(d->outsvg) += " \" /> \n";
- *(d->path) = "";
- break;
- }
- case EMR_ARC:
- dbg_str << "\n";
- break;
- case EMR_CHORD:
- dbg_str << "\n";
- break;
- case EMR_PIE:
- dbg_str << "\n";
- break;
- case EMR_SELECTPALETTE:
- dbg_str << "\n";
- break;
- case EMR_CREATEPALETTE:
- dbg_str << "\n";
- break;
- case EMR_SETPALETTEENTRIES:
- dbg_str << "\n";
- break;
- case EMR_RESIZEPALETTE:
- dbg_str << "\n";
- break;
- case EMR_REALIZEPALETTE:
- dbg_str << "\n";
- break;
- case EMR_EXTFLOODFILL:
- dbg_str << "\n";
- break;
- case EMR_LINETO:
- {
- dbg_str << "\n";
-
- PEMRLINETO pEmr = (PEMRLINETO) lpEMFR;
-
- if (d->path->empty()) {
- d->pathless_stroke = true;
- *(d->path) = "d=\"";
- }
-
- tmp_path <<
- "\n\tL " <<
- pix_to_x_point( d, pEmr->ptl.x, pEmr->ptl.y ) << " " <<
- pix_to_y_point( d, pEmr->ptl.x, pEmr->ptl.y ) << " ";
- break;
- }
- case EMR_ARCTO:
- dbg_str << "\n";
- break;
- case EMR_POLYDRAW:
- dbg_str << "\n";
- break;
- case EMR_SETARCDIRECTION:
- dbg_str << "\n";
- break;
- case EMR_SETMITERLIMIT:
- {
- dbg_str << "\n";
-
- PEMRSETMITERLIMIT pEmr = (PEMRSETMITERLIMIT) lpEMFR;
-
- //BUG in SetMiterLimit() on mingw, possibly in underlying Windows(at least on XP?)
- //The function takes a float but saves a 32 bit int in the EMR_SETMITERLIMIT record.
- float miterlimit = *((int32_t *) &(pEmr->eMiterLimit));
- d->dc[d->level].style.stroke_miterlimit.value = miterlimit; //ratio, not a pt size
- if (d->dc[d->level].style.stroke_miterlimit.value < 1.0)
- d->dc[d->level].style.stroke_miterlimit.value = 1.0;
- break;
- }
- case EMR_BEGINPATH:
- {
- dbg_str << "\n";
-
- if (!d->pathless_stroke) {
- tmp_path << "d=\"";
- *(d->path) = "";
- }
- d->pathless_stroke = false;
- d->inpath = true;
- break;
- }
- case EMR_ENDPATH:
- {
- dbg_str << "\n";
-
- tmp_path << "\"";
- d->inpath = false;
- break;
- }
- case EMR_CLOSEFIGURE:
- {
- dbg_str << "\n";
-
- tmp_path << "\n\tz";
- break;
- }
- case EMR_FILLPATH:
- case EMR_STROKEANDFILLPATH:
- case EMR_STROKEPATH:
- {
- if (lpEMFR->iType == EMR_FILLPATH)
- dbg_str << "\n";
- if (lpEMFR->iType == EMR_STROKEANDFILLPATH)
- dbg_str << "\n";
- if (lpEMFR->iType == EMR_STROKEPATH)
- dbg_str << "\n";
-
- *(d->outsvg) += " iType);
- *(d->outsvg) += "\n\t";
- *(d->outsvg) += *(d->path);
- *(d->outsvg) += " /> \n";
- *(d->path) = "";
- break;
- }
- case EMR_FLATTENPATH:
- dbg_str << "\n";
- break;
- case EMR_WIDENPATH:
- dbg_str << "\n";
- break;
- case EMR_SELECTCLIPPATH:
- dbg_str << "\n";
- break;
- case EMR_ABORTPATH:
- dbg_str << "\n";
- break;
- case EMR_GDICOMMENT:
- {
- dbg_str << "\n";
-
- PEMRGDICOMMENT pEmr = (PEMRGDICOMMENT) lpEMFR;
-
- CHAR *szTxt = (CHAR *) pEmr->Data;
-
- for (DWORD i = 0; i < pEmr->cbData; i++) {
- if ( *szTxt) {
- if ( *szTxt >= ' ' && *szTxt < 'z' && *szTxt != '<' && *szTxt != '>' ) {
- tmp_str << *szTxt;
- }
- szTxt++;
- }
- }
-
- if (0 && strlen(tmp_str.str().c_str())) {
- tmp_outsvg << " \n";
- }
-
- break;
- }
- case EMR_FILLRGN:
- dbg_str << "\n";
- break;
- case EMR_FRAMERGN:
- dbg_str << "\n";
- break;
- case EMR_INVERTRGN:
- dbg_str << "\n";
- break;
- case EMR_PAINTRGN:
- dbg_str << "\n";
- break;
- case EMR_EXTSELECTCLIPRGN:
- {
- dbg_str << "\n";
-
- PEMREXTSELECTCLIPRGN pEmr = (PEMREXTSELECTCLIPRGN) lpEMFR;
- if (pEmr->iMode == RGN_COPY)
- clipset = false;
- break;
- }
- case EMR_BITBLT:
- {
- dbg_str << "\n";
-
- PEMRBITBLT pEmr = (PEMRBITBLT) lpEMFR;
- if (pEmr->dwRop == DPA) {
- // should be an application of a DIBPATTERNBRUSHPT, use a solid color instead
- double l = pix_to_x_point( d, pEmr->xDest, pEmr->yDest);
- double t = pix_to_y_point( d, pEmr->xDest, pEmr->yDest);
- double r = pix_to_x_point( d, pEmr->xDest + pEmr->cxDest, pEmr->yDest + pEmr->cyDest);
- double b = pix_to_y_point( d, pEmr->xDest + pEmr->cxDest, pEmr->yDest + pEmr->cyDest);
-
- SVGOStringStream tmp_rectangle;
- tmp_rectangle << "d=\"";
- tmp_rectangle << "\n\tM " << l << " " << t << " ";
- tmp_rectangle << "\n\tL " << r << " " << t << " ";
- tmp_rectangle << "\n\tL " << r << " " << b << " ";
- tmp_rectangle << "\n\tL " << l << " " << b << " ";
- tmp_rectangle << "\n\tz";
-
- assert_empty_path(d, "EMR_BITBLT");
-
- *(d->outsvg) += " iType);
- *(d->outsvg) += "\n\t";
- *(d->outsvg) += tmp_rectangle.str().c_str();
- *(d->outsvg) += " \" /> \n";
- *(d->path) = "";
- }
- break;
- }
- case EMR_STRETCHBLT:
- dbg_str << "\n";
- break;
- case EMR_MASKBLT:
- dbg_str << "\n";
- break;
- case EMR_PLGBLT:
- dbg_str << "\n";
- break;
- case EMR_SETDIBITSTODEVICE:
- dbg_str << "\n";
- break;
- case EMR_STRETCHDIBITS:
- dbg_str << "\n";
- break;
- case EMR_EXTCREATEFONTINDIRECTW:
- {
- dbg_str << "\n";
-
- PEMREXTCREATEFONTINDIRECTW pEmr = (PEMREXTCREATEFONTINDIRECTW) lpEMFR;
- int index = pEmr->ihFont;
-
- EMREXTCREATEFONTINDIRECTW *pFont =
- (EMREXTCREATEFONTINDIRECTW *) malloc( sizeof(EMREXTCREATEFONTINDIRECTW) );
- pFont->elfw = pEmr->elfw;
- insert_object(d, index, EMR_EXTCREATEFONTINDIRECTW, (ENHMETARECORD *) pFont);
- break;
- }
- case EMR_EXTTEXTOUTA:
- {
- dbg_str << "\n";
- break;
- }
- case EMR_EXTTEXTOUTW:
- {
- dbg_str << "\n";
-
- PEMREXTTEXTOUTW pEmr = (PEMREXTTEXTOUTW) lpEMFR;
-
- double x1 = pEmr->emrtext.ptlReference.x;
- double y1 = pEmr->emrtext.ptlReference.y;
-
- if (d->dc[d->level].textAlign & TA_UPDATECP) {
- x1 = d->dc[d->level].cur.x;
- y1 = d->dc[d->level].cur.y;
- }
-
- double x = pix_to_x_point(d, x1, y1);
- double y = pix_to_y_point(d, x1, y1);
-
- if (!(d->dc[d->level].textAlign & TA_BOTTOM))
- if (d->dc[d->level].style.baseline_shift.value) {
- x += std::sin(d->dc[d->level].style.baseline_shift.value*M_PI/180.0)*fabs(d->dc[d->level].style.font_size.computed);
- y += std::cos(d->dc[d->level].style.baseline_shift.value*M_PI/180.0)*fabs(d->dc[d->level].style.font_size.computed);
- }
- else
- y += fabs(d->dc[d->level].style.font_size.computed);
-
- wchar_t *wide_text = (wchar_t *) ((char *) pEmr + pEmr->emrtext.offString);
-
- gchar *ansi_text =
- (gchar *) g_utf16_to_utf8( (gunichar2 *) wide_text, pEmr->emrtext.nChars, NULL, NULL, NULL );
-
- if (ansi_text) {
-// gchar *p = ansi_text;
-// while (*p) {
-// if (*p < 32 || *p >= 127) {
-// g_free(ansi_text);
-// ansi_text = g_strdup("");
-// break;
-// }
-// p++;
-// }
-
- SVGOStringStream ts;
-
- gchar *escaped_text = g_markup_escape_text(ansi_text, -1);
-
-// float text_rgb[3];
-// sp_color_get_rgb_floatv( &(d->dc[d->level].style.fill.value.color), text_rgb );
-
-// if (!d->dc[d->level].textColorSet) {
-// d->dc[d->level].textColor = RGB(SP_COLOR_F_TO_U(text_rgb[0]),
-// SP_COLOR_F_TO_U(text_rgb[1]),
-// SP_COLOR_F_TO_U(text_rgb[2]));
-// }
-
- char tmp[128];
- snprintf(tmp, 127,
- "fill:#%02x%02x%02x;",
- GetRValue(d->dc[d->level].textColor),
- GetGValue(d->dc[d->level].textColor),
- GetBValue(d->dc[d->level].textColor));
-
- bool i = (d->dc[d->level].style.font_style.value == SP_CSS_FONT_STYLE_ITALIC);
- //bool o = (d->dc[d->level].style.font_style.value == SP_CSS_FONT_STYLE_OBLIQUE);
- bool b = (d->dc[d->level].style.font_weight.value == SP_CSS_FONT_WEIGHT_BOLD) ||
- (d->dc[d->level].style.font_weight.value >= SP_CSS_FONT_WEIGHT_500 && d->dc[d->level].style.font_weight.value <= SP_CSS_FONT_WEIGHT_900);
- int lcr = ((d->dc[d->level].textAlign & TA_CENTER) == TA_CENTER) ? 2 : ((d->dc[d->level].textAlign & TA_RIGHT) == TA_RIGHT) ? 1 : 0;
-
- assert_empty_path(d, "EMR_EXTTEXTOUTW");
-
- ts << " id++) << "\"\n";
- ts << " xml:space=\"preserve\"\n";
- ts << " x=\"" << x << "\"\n";
- ts << " y=\"" << y << "\"\n";
- if (d->dc[d->level].style.baseline_shift.value) {
- ts << " transform=\""
- << "rotate(-" << d->dc[d->level].style.baseline_shift.value
- << " " << x << " " << y << ")"
- << "\"\n";
- }
- ts << " style=\""
- << "font-size:" << fabs(d->dc[d->level].style.font_size.computed) << "px;"
- << tmp
- << "font-style:" << (i ? "italic" : "normal") << ";"
- << "font-weight:" << (b ? "bold" : "normal") << ";"
- << "text-align:" << (lcr==2 ? "center" : lcr==1 ? "end" : "start") << ";"
- << "text-anchor:" << (lcr==2 ? "middle" : lcr==1 ? "end" : "start") << ";"
- << "font-family:" << d->dc[d->level].tstyle.font_family.value << ";"
- << "\"\n";
- ts << " >";
- ts << escaped_text;
- ts << "\n";
-
- *(d->outsvg) += ts.str().c_str();
-
- g_free(escaped_text);
- g_free(ansi_text);
- }
-
- break;
- }
- case EMR_POLYBEZIER16:
- {
- dbg_str << "\n";
-
- PEMRPOLYBEZIER16 pEmr = (PEMRPOLYBEZIER16) lpEMFR;
- POINTS *apts = (POINTS *) pEmr->apts; // Bug in MinGW wingdi.h ?
- DWORD i,j;
-
- if (pEmr->cpts<4)
- break;
-
- if (!d->inpath) {
- assert_empty_path(d, "EMR_POLYBEZIER16");
-
- *(d->outsvg) += " outsvg) += "\n\td=\"";
- }
-
- tmp_str <<
- "\n\tM " <<
- pix_to_x_point( d, apts[0].x, apts[0].y ) << " " <<
- pix_to_y_point( d, apts[0].x, apts[0].y ) << " ";
-
- for (i=1; icpts; ) {
- tmp_str << "\n\tC ";
- for (j=0; j<3 && icpts; j++,i++) {
- tmp_str <<
- pix_to_x_point( d, apts[i].x, apts[i].y ) << " " <<
- pix_to_y_point( d, apts[i].x, apts[i].y ) << " ";
- }
- }
-
- if (d->inpath) {
- tmp_path << tmp_str.str().c_str();
- }
- else {
- *(d->outsvg) += tmp_str.str().c_str();
- *(d->outsvg) += " \" /> \n";
- }
-
- break;
- }
- case EMR_POLYGON16:
- {
- dbg_str << "\n";
-
- PEMRPOLYGON16 pEmr = (PEMRPOLYGON16) lpEMFR;
- POINTS *apts = (POINTS *) pEmr->apts; // Bug in MinGW wingdi.h ?
- SVGOStringStream tmp_poly;
- unsigned int i;
- unsigned int first = 0;
-
- assert_empty_path(d, "EMR_POLYGON16");
-
- *(d->outsvg) += " outsvg) += "\n\td=\"";
-
- // skip the first point?
- tmp_poly << "\n\tM " <<
- pix_to_x_point( d, apts[first].x, apts[first].y ) << " " <<
- pix_to_y_point( d, apts[first].x, apts[first].y ) << " ";
-
- for (i=first+1; icpts; i++) {
- tmp_poly << "\n\tL " <<
- pix_to_x_point( d, apts[i].x, apts[i].y ) << " " <<
- pix_to_y_point( d, apts[i].x, apts[i].y ) << " ";
- }
-
- *(d->outsvg) += tmp_poly.str().c_str();
- *(d->outsvg) += " z \" /> \n";
-
- break;
- }
- case EMR_POLYLINE16:
- {
- dbg_str << "\n";
-
- EMRPOLYLINE16 *pEmr = (EMRPOLYLINE16 *) lpEMFR;
- POINTS *apts = (POINTS *) pEmr->apts; // Bug in MinGW wingdi.h ?
- DWORD i;
-
- if (pEmr->cpts<2)
- break;
-
- if (!d->inpath) {
- assert_empty_path(d, "EMR_POLYLINE16");
-
- *(d->outsvg) += " outsvg) += "\n\td=\"";
- }
-
- tmp_str <<
- "\n\tM " <<
- pix_to_x_point( d, apts[0].x, apts[0].y ) << " " <<
- pix_to_y_point( d, apts[0].x, apts[0].y ) << " ";
-
- for (i=1; icpts; i++) {
- tmp_str <<
- "\n\tL " <<
- pix_to_x_point( d, apts[i].x, apts[i].y ) << " " <<
- pix_to_y_point( d, apts[i].x, apts[i].y ) << " ";
- }
-
- if (d->inpath) {
- tmp_path << tmp_str.str().c_str();
- }
- else {
- *(d->outsvg) += tmp_str.str().c_str();
- *(d->outsvg) += " \" /> \n";
- }
-
- break;
- }
- case EMR_POLYBEZIERTO16:
- {
- dbg_str << "\n";
-
- PEMRPOLYBEZIERTO16 pEmr = (PEMRPOLYBEZIERTO16) lpEMFR;
- POINTS *apts = (POINTS *) pEmr->apts; // Bug in MinGW wingdi.h ?
- DWORD i,j;
-
- if (d->path->empty()) {
- d->pathless_stroke = true;
- *(d->path) = "d=\"";
- }
-
- for (i=0; icpts;) {
- tmp_path << "\n\tC ";
- for (j=0; j<3 && icpts; j++,i++) {
- tmp_path <<
- pix_to_x_point( d, apts[i].x, apts[i].y ) << " " <<
- pix_to_y_point( d, apts[i].x, apts[i].y ) << " ";
- }
- }
-
- break;
- }
- case EMR_POLYLINETO16:
- {
- dbg_str << "\n";
-
- PEMRPOLYLINETO16 pEmr = (PEMRPOLYLINETO16) lpEMFR;
- POINTS *apts = (POINTS *) pEmr->apts; // Bug in MinGW wingdi.h ?
- DWORD i;
-
- if (d->path->empty()) {
- d->pathless_stroke = true;
- *(d->path) = "d=\"";
- }
-
- for (i=0; icpts;i++) {
- tmp_path <<
- "\n\tL " <<
- pix_to_x_point( d, apts[i].x, apts[i].y ) << " " <<
- pix_to_y_point( d, apts[i].x, apts[i].y ) << " ";
- }
-
- break;
- }
- case EMR_POLYPOLYLINE16:
- case EMR_POLYPOLYGON16:
- {
- if (lpEMFR->iType == EMR_POLYPOLYLINE16)
- dbg_str << "\n";
- if (lpEMFR->iType == EMR_POLYPOLYGON16)
- dbg_str << "\n";
-
- PEMRPOLYPOLYGON16 pEmr = (PEMRPOLYPOLYGON16) lpEMFR;
- unsigned int n, i, j;
-
- if (!d->inpath) {
- assert_empty_path(d, lpEMFR->iType == EMR_POLYPOLYGON16 ? "EMR_POLYPOLYGON16" : "EMR_POLYPOLYLINE16");
-
- *(d->outsvg) += " iType==EMR_POLYPOLYGON16 ? EMR_STROKEANDFILLPATH : EMR_STROKEPATH);
- *(d->outsvg) += "\n\td=\"";
- }
-
- POINTS *apts = (POINTS *) &pEmr->aPolyCounts[pEmr->nPolys];
-
- i = 0;
- for (n=0; nnPolys && icpts; n++) {
- SVGOStringStream poly_path;
-
- poly_path << "\n\tM " <<
- pix_to_x_point( d, apts[i].x, apts[i].y ) << " " <<
- pix_to_y_point( d, apts[i].x, apts[i].y ) << " ";
- i++;
-
- for (j=1; jaPolyCounts[n] && icpts; j++) {
- poly_path << "\n\tL " <<
- pix_to_x_point( d, apts[i].x, apts[i].y ) << " " <<
- pix_to_y_point( d, apts[i].x, apts[i].y ) << " ";
- i++;
- }
-
- tmp_str << poly_path.str().c_str();
- if (lpEMFR->iType == EMR_POLYPOLYGON16)
- tmp_str << " z";
- tmp_str << " \n";
- }
-
- if (d->inpath) {
- tmp_path << tmp_str.str().c_str();
- }
- else {
- *(d->outsvg) += tmp_str.str().c_str();
- *(d->outsvg) += " \" /> \n";
- }
-
- break;
- }
- case EMR_POLYDRAW16:
- dbg_str << "\n";
- break;
- case EMR_CREATEMONOBRUSH:
- dbg_str << "\n";
- break;
- case EMR_CREATEDIBPATTERNBRUSHPT:
- {
- dbg_str << "\n";
-
- PEMRCREATEDIBPATTERNBRUSHPT pEmr = (PEMRCREATEDIBPATTERNBRUSHPT) lpEMFR;
- int index = pEmr->ihBrush;
-
- EMRCREATEDIBPATTERNBRUSHPT *pBrush =
- (EMRCREATEDIBPATTERNBRUSHPT *) malloc( sizeof(EMRCREATEDIBPATTERNBRUSHPT) );
- insert_object(d, index, EMR_CREATEDIBPATTERNBRUSHPT, (ENHMETARECORD *) pBrush);
- break;
- }
- case EMR_EXTCREATEPEN:
- {
- dbg_str << "\n";
-
- PEMREXTCREATEPEN pEmr = (PEMREXTCREATEPEN) lpEMFR;
- int index = pEmr->ihPen;
-
- EMREXTCREATEPEN *pPen =
- (EMREXTCREATEPEN *) malloc( sizeof(EMREXTCREATEPEN) +
- sizeof(DWORD) * pEmr->elp.elpNumEntries );
- pPen->ihPen = pEmr->ihPen;
- pPen->offBmi = pEmr->offBmi;
- pPen->cbBmi = pEmr->cbBmi;
- pPen->offBits = pEmr->offBits;
- pPen->cbBits = pEmr->cbBits;
- pPen->elp = pEmr->elp;
- for (unsigned int i=0; ielp.elpNumEntries; i++) {
- pPen->elp.elpStyleEntry[i] = pEmr->elp.elpStyleEntry[i];
- }
- insert_object(d, index, EMR_EXTCREATEPEN, (ENHMETARECORD *) pPen);
-
- break;
- }
- case EMR_POLYTEXTOUTA:
- dbg_str << "\n";
- break;
- case EMR_POLYTEXTOUTW:
- dbg_str << "\n";
- break;
- case EMR_SETICMMODE:
- dbg_str << "\n";
- break;
- case EMR_CREATECOLORSPACE:
- dbg_str << "\n";
- break;
- case EMR_SETCOLORSPACE:
- dbg_str << "\n";
- break;
- case EMR_DELETECOLORSPACE:
- dbg_str << "\n";
- break;
- case EMR_GLSRECORD:
- dbg_str << "\n";
- break;
- case EMR_GLSBOUNDEDRECORD:
- dbg_str << "\n";
- break;
- case EMR_PIXELFORMAT:
- dbg_str << "\n";
- break;
- default:
- dbg_str << "\n";
- break;
- }
-
-// *(d->outsvg) += dbg_str.str().c_str();
- *(d->outsvg) += tmp_outsvg.str().c_str();
- *(d->path) += tmp_path.str().c_str();
-
- return 1;
-}
-
-static int CALLBACK
-myMetaFileProc(HDC /*hDC*/, HANDLETABLE * /*lpHTable*/, METARECORD * /*lpMFR*/, int /*nObj*/, LPARAM /*lpData*/)
-{
- g_warning("Unable to import Windows Meta File.\n");
- return 0;
-}
-
-// Aldus Placeable Header ===================================================
-// Since we are a 32bit app, we have to be sure this structure compiles to
-// be identical to a 16 bit app's version. To do this, we use the #pragma
-// to adjust packing, we use a WORD for the hmf handle, and a SMALL_RECT
-// for the bbox rectangle.
-#pragma pack( push )
-#pragma pack( 2 )
-typedef struct
-{
- DWORD dwKey;
- WORD hmf;
- SMALL_RECT bbox;
- WORD wInch;
- DWORD dwReserved;
- WORD wCheckSum;
-} APMHEADER, *PAPMHEADER;
-#pragma pack( pop )
-
-
-SPDocument *
-EmfWin32::open( Inkscape::Extension::Input * /*mod*/, const gchar *uri )
-{
- EMF_CALLBACK_DATA d;
-
- memset(&d, 0, sizeof(d));
-
- d.dc[0].worldTransform.eM11 = 1.0;
- d.dc[0].worldTransform.eM12 = 0.0;
- d.dc[0].worldTransform.eM21 = 0.0;
- d.dc[0].worldTransform.eM22 = 1.0;
- d.dc[0].worldTransform.eDx = 0.0;
- d.dc[0].worldTransform.eDy = 0.0;
-
- gsize bytesRead = 0;
- gsize bytesWritten = 0;
- GError* error = NULL;
- gchar *local_fn =
- g_filename_from_utf8( uri, -1, &bytesRead, &bytesWritten, &error );
-
- if (local_fn == NULL) {
- return NULL;
- }
-
- d.outsvg = new Glib::ustring("");
- d.path = new Glib::ustring("");
- d.outdef = new Glib::ustring("");
-
- CHAR *ansi_uri = (CHAR *) local_fn;
- gunichar2 *unicode_fn = g_utf8_to_utf16( local_fn, -1, NULL, NULL, NULL );
- WCHAR *unicode_uri = (WCHAR *) unicode_fn;
-
- DWORD filesize = 0;
- HANDLE fp = NULL;
-
- HMETAFILE hmf;
- HENHMETAFILE hemf;
-
- fp = CreateFileW(unicode_uri, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
-
- if ( fp != INVALID_HANDLE_VALUE ) {
- filesize = GetFileSize(fp, NULL);
- CloseHandle(fp);
- }
-
- // Try open as Enhanced Metafile
- hemf = GetEnhMetaFileW(unicode_uri);
-
- if (!hemf) {
- // Try open as Windows Metafile
- hmf = GetMetaFileW(unicode_uri);
-
- METAFILEPICT mp;
- HDC hDC;
-
- if (!hmf) {
- WCHAR szTemp[MAX_PATH];
-
- DWORD dw = GetShortPathNameW( unicode_uri, szTemp, MAX_PATH );
- if (dw) {
- hmf = GetMetaFileW( szTemp );
- }
- }
-
- if (hmf) {
- DWORD nSize = GetMetaFileBitsEx( hmf, 0, NULL );
-
- if (!nSize)
- nSize = filesize;
-
- if (nSize) {
- BYTE *lpvData = new BYTE[nSize];
- if (lpvData) {
- DWORD dw = GetMetaFileBitsEx( hmf, nSize, lpvData );
- if (dw) {
- // Fill out a METAFILEPICT structure
- mp.mm = MM_ANISOTROPIC;
- mp.xExt = 1000;
- mp.yExt = 1000;
- mp.hMF = NULL;
- // Get a reference DC
- hDC = GetDC( NULL );
- // Make an enhanced metafile from the windows metafile
- hemf = SetWinMetaFileBits( nSize, lpvData, hDC, &mp );
- // Clean up
- ReleaseDC( NULL, hDC );
- DeleteMetaFile( hmf );
- hmf = NULL;
- }
- else {
- // EnumMetaFile
- }
- delete[] lpvData;
- }
- else {
- DeleteMetaFile( hmf );
- hmf = NULL;
- }
- }
- else {
- DeleteMetaFile( hmf );
- hmf = NULL;
- }
- }
- else {
- // Try open as Aldus Placeable Metafile
- HANDLE hFile;
- hFile = CreateFileW( unicode_uri, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
-
- if (hFile != INVALID_HANDLE_VALUE) {
- DWORD nSize = GetFileSize( hFile, NULL );
- if (nSize) {
- BYTE *lpvData = new BYTE[nSize];
- if (lpvData) {
- DWORD dw = ReadFile( hFile, lpvData, nSize, &nSize, NULL );
- if (dw) {
- if ( ((PAPMHEADER)lpvData)->dwKey == 0x9ac6cdd7l ) {
- // Fill out a METAFILEPICT structure
- mp.mm = MM_ANISOTROPIC;
- mp.xExt = ((PAPMHEADER)lpvData)->bbox.Right - ((PAPMHEADER)lpvData)->bbox.Left;
- mp.xExt = ( mp.xExt * 2540l ) / (DWORD)(((PAPMHEADER)lpvData)->wInch);
- mp.yExt = ((PAPMHEADER)lpvData)->bbox.Bottom - ((PAPMHEADER)lpvData)->bbox.Top;
- mp.yExt = ( mp.yExt * 2540l ) / (DWORD)(((PAPMHEADER)lpvData)->wInch);
- mp.hMF = NULL;
- // Get a reference DC
- hDC = GetDC( NULL );
- // Create an enhanced metafile from the bits
- hemf = SetWinMetaFileBits( nSize, lpvData+sizeof(APMHEADER), hDC, &mp );
- // Clean up
- ReleaseDC( NULL, hDC );
- }
- }
- delete[] lpvData;
- }
- }
- CloseHandle( hFile );
- }
- }
- }
-
- if ((!hemf && !hmf) || !d.outsvg || !d.path) {
- if (d.outsvg)
- delete d.outsvg;
- if (d.path)
- delete d.path;
- if (d.outdef)
- delete d.outdef;
- if (local_fn)
- g_free(local_fn);
- if (unicode_fn)
- g_free(unicode_fn);
- if (hemf)
- DeleteEnhMetaFile(hemf);
- if (hmf)
- DeleteMetaFile(hmf);
- return NULL;
- }
-
- d.pDesc = NULL;
-
- if (hemf) {
- DWORD dwNeeded = GetEnhMetaFileDescriptionA( hemf, 0, NULL );
- if ( dwNeeded > 0 ) {
- d.pDesc = (CHAR *) malloc( dwNeeded + 1 );
- if ( GetEnhMetaFileDescription( hemf, dwNeeded, d.pDesc ) == 0 )
- lstrcpy( d.pDesc, "" );
- if ( lstrlen( d.pDesc ) > 1 )
- d.pDesc[lstrlen(d.pDesc)] = '#';
- }
-
- // This ugly reinterpret_cast is to prevent old versions of gcc from whining about a mismatch in the const-ness of the arguments
- EnumEnhMetaFile(NULL, hemf, reinterpret_cast(myEnhMetaFileProc), (LPVOID) &d, NULL);
- DeleteEnhMetaFile(hemf);
- }
- else {
- EnumMetaFile(NULL, hmf, myMetaFileProc, (LPARAM) &d);
- DeleteMetaFile(hmf);
- }
-
- if (d.pDesc)
- free( d.pDesc );
-
-// std::cout << "SVG Output: " << std::endl << *(d.outsvg) << std::endl;
-
- SPDocument *doc = SPDocument::createNewDocFromMem(d.outsvg->c_str(), strlen(d.outsvg->c_str()), TRUE);
-
- delete d.outsvg;
- delete d.path;
- delete d.outdef;
-
- if (d.emf_obj) {
- int i;
- for (i=0; i\n"
- "" N_("EMF Input") "\n"
- "org.inkscape.input.emf.win32\n"
- "\n"
- ".emf\n"
- "image/x-emf\n"
- "" N_("Enhanced Metafiles (*.emf)") "\n"
- "" N_("Enhanced Metafiles") "\n"
- "org.inkscape.output.emf.win32\n"
- "\n"
- "", new EmfWin32());
-
- /* WMF in */
- Inkscape::Extension::build_from_mem(
- "\n"
- "" N_("WMF Input") "\n"
- "org.inkscape.input.wmf.win32\n"
- "\n"
- ".wmf\n"
- "image/x-wmf\n"
- "" N_("Windows Metafiles (*.wmf)") "\n"
- "" N_("Windows Metafiles") "\n"
- "org.inkscape.output.emf.win32\n"
- "\n"
- "", new EmfWin32());
-
- /* EMF out */
- Inkscape::Extension::build_from_mem(
- "\n"
- "" N_("EMF Output") "\n"
- "org.inkscape.output.emf.win32\n"
- "true\n"
- "\n"
- "", new EmfWin32());
-
- return;
-}
-
-
-} } } /* namespace Inkscape, Extension, Implementation */
-
-#endif /* WIN32 */
-/*
- 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 -rNu3 src/extension/internal/emf-win32-inout.h src/extension/internal/emf-win32-inout.h
--- src/extension/internal/emf-win32-inout.h 2012-08-07 12:29:10.000000000 -0700
+++ src/extension/internal/emf-win32-inout.h 1969-12-31 16:00:00.000000000 -0800
@@ -1,57 +0,0 @@
-/** @file
- * @brief Enhanced Metafile Input/Output
- */
-/* Authors:
- * Ulf Erikson
- *
- * Copyright (C) 2006-2008 Authors
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-#ifndef SEEN_EXTENSION_INTERNAL_EMF_WIN32_H
-#define SEEN_EXTENSION_INTERNAL_EMF_WIN32_H
-#ifdef WIN32
-
-#include "extension/implementation/implementation.h"
-
-namespace Inkscape {
-namespace Extension {
-namespace Internal {
-
-class EmfWin32 : Inkscape::Extension::Implementation::Implementation { //This is a derived class
-
-public:
- EmfWin32(); // Empty constructor
-
- virtual ~EmfWin32();//Destructor
-
- bool check(Inkscape::Extension::Extension *module); //Can this module load (always yes for now)
-
- void save(Inkscape::Extension::Output *mod, // Save the given document to the given filename
- SPDocument *doc,
- gchar const *filename);
-
- virtual SPDocument *open( Inkscape::Extension::Input *mod,
- const gchar *uri );
-
- static void init(void);//Initialize the class
-
-private:
-};
-
-} } } /* namespace Inkscape, Extension, Implementation */
-
-#endif /* WIN32 */
-
-#endif /* EXTENSION_INTERNAL_EMF_WIN32_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 -rNu3 src/extension/internal/emf-win32-print.cpp src/extension/internal/emf-win32-print.cpp
--- src/extension/internal/emf-win32-print.cpp 2012-08-07 12:29:10.000000000 -0700
+++ src/extension/internal/emf-win32-print.cpp 1969-12-31 16:00:00.000000000 -0800
@@ -1,942 +0,0 @@
-/** @file
- * @brief Enhanced Metafile printing
- */
-/* Authors:
- * Ulf Erikson
- * Jon A. Cruz
- * Abhishek Sharma
- *
- * Copyright (C) 2006-2009 Authors
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-/*
- * References:
- * - How to Create & Play Enhanced Metafiles in Win32
- * http://support.microsoft.com/kb/q145999/
- * - INFO: Windows Metafile Functions & Aldus Placeable Metafiles
- * http://support.microsoft.com/kb/q66949/
- * - Metafile Functions
- * http://msdn.microsoft.com/library/en-us/gdi/metafile_0whf.asp
- * - Metafile Structures
- * http://msdn.microsoft.com/library/en-us/gdi/metafile_5hkj.asp
- */
-
-#ifdef WIN32
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-
-#include <2geom/pathvector.h>
-#include <2geom/rect.h>
-#include <2geom/bezier-curve.h>
-#include <2geom/hvlinesegment.h>
-#include "helper/geom.h"
-#include "helper/geom-curves.h"
-#include "sp-item.h"
-
-#include "style.h"
-#include "inkscape-version.h"
-#include "sp-root.h"
-
-#include "emf-win32-print.h"
-
-#include "unit-constants.h"
-
-#include "extension/system.h"
-#include "extension/print.h"
-#include "document.h"
-
-
-namespace Inkscape {
-namespace Extension {
-namespace Internal {
-
-static float dwDPI = 2540;
-
-
-PrintEmfWin32::PrintEmfWin32 (void):
- _width(0),
- _height(0),
- hdc(NULL),
- hbrush(NULL),
- hbrushOld(NULL),
- hpen(NULL),
- stroke_and_fill(false),
- fill_only(false),
- simple_shape(false)
-{
-}
-
-
-PrintEmfWin32::~PrintEmfWin32 (void)
-{
- if (hdc) {
- HENHMETAFILE metafile = CloseEnhMetaFile( hdc );
- if ( metafile ) {
- DeleteEnhMetaFile( metafile );
- }
- DeleteDC( hdc );
- }
-
- /* restore default signal handling for SIGPIPE */
-#if !defined(_WIN32) && !defined(__WIN32__)
- (void) signal(SIGPIPE, SIG_DFL);
-#endif
- return;
-}
-
-
-unsigned int PrintEmfWin32::setup (Inkscape::Extension::Print * /*mod*/)
-{
- return TRUE;
-}
-
-
-unsigned int PrintEmfWin32::begin (Inkscape::Extension::Print *mod, SPDocument *doc)
-{
- gchar const *utf8_fn = mod->get_param_string("destination");
-
- gsize bytesRead = 0;
- gsize bytesWritten = 0;
- GError* error = NULL;
- gchar *local_fn =
- g_filename_from_utf8( utf8_fn, -1, &bytesRead, &bytesWritten, &error );
-
- if (local_fn == NULL) {
- return 1;
- }
-
- CHAR *ansi_uri = (CHAR *) local_fn;
- gunichar2 *unicode_fn = g_utf8_to_utf16( local_fn, -1, NULL, NULL, NULL );
- WCHAR *unicode_uri = (WCHAR *) unicode_fn;
-
- // width and height in px
- _width = doc->getWidth();
- _height = doc->getHeight();
-
- bool pageBoundingBox;
- pageBoundingBox = mod->get_param_bool("pageBoundingBox");
-
- Geom::Rect d;
- if (pageBoundingBox) {
- d = Geom::Rect::from_xywh(0, 0, _width, _height);
- } else {
- SPItem* doc_item = doc->getRoot();
- Geom::OptRect bbox = doc_item->desktopVisualBounds();
- if (bbox) d = *bbox;
- }
-
- d *= Geom::Scale(IN_PER_PX);
-
- float dwInchesX = d.width();
- float dwInchesY = d.height();
-
- // dwInchesX x dwInchesY in .01mm units
- SetRect( &rc, 0, 0, (int) ceil(dwInchesX*2540), (int) ceil(dwInchesY*2540) );
-
- // Get a Reference DC
- HDC hScreenDC = GetDC( NULL );
-
- // Get the physical characteristics of the reference DC
- int PixelsX = GetDeviceCaps( hScreenDC, HORZRES );
- int PixelsY = GetDeviceCaps( hScreenDC, VERTRES );
- int MMX = GetDeviceCaps( hScreenDC, HORZSIZE );
- int MMY = GetDeviceCaps( hScreenDC, VERTSIZE );
-
- CHAR buff[1024];
- ZeroMemory(buff, sizeof(buff));
- snprintf(buff, sizeof(buff)-1, "Inkscape %s (%s)", Inkscape::version_string, __DATE__);
- INT len = strlen(buff);
- CHAR *p1 = strrchr(ansi_uri, '\\');
- CHAR *p2 = strrchr(ansi_uri, '/');
- CHAR *p = MAX(p1, p2);
- if (p)
- p++;
- else
- p = ansi_uri;
- snprintf(buff+len+1, sizeof(buff)-len-2, "%s", p);
-
- // Create the Metafile
- {
- WCHAR wbuff[1024];
- ZeroMemory(wbuff, sizeof(wbuff));
- MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, buff, sizeof(buff)/sizeof(buff[0]), wbuff, sizeof(wbuff)/sizeof(wbuff[0]));
- hdc = CreateEnhMetaFileW( hScreenDC, unicode_uri, &rc, wbuff );
- }
-
- // Release the reference DC
- ReleaseDC( NULL, hScreenDC );
-
- // Did we get a good metafile?
- if (hdc == NULL)
- {
- g_free(local_fn);
- g_free(unicode_fn);
- return 1;
- }
-
- // Anisotropic mapping mode
- SetMapMode( hdc, MM_ANISOTROPIC );
-
- // Set the Windows extent
- int windowextX = (int) ceil(dwInchesX*dwDPI);
- int windowextY = (int) ceil(dwInchesY*dwDPI);
- SetWindowExtEx( hdc, windowextX, windowextY, NULL );
-
- // Set the viewport extent to reflect
- // dwInchesX" x dwInchesY" in device units
- int viewportextX = (int)((float)dwInchesX*25.4f*(float)PixelsX/(float)MMX);
- int viewportextY = (int)((float)dwInchesY*25.4f*(float)PixelsY/(float)MMY);
- SetViewportExtEx( hdc, viewportextX, viewportextY, NULL );
-
- if (1) {
- snprintf(buff, sizeof(buff)-1, "Screen=%dx%dpx, %dx%dmm", PixelsX, PixelsY, MMX, MMY);
- GdiComment(hdc, strlen(buff), (BYTE*) buff);
-
- snprintf(buff, sizeof(buff)-1, "Drawing=%.1lfx%.1lfpx, %.1lfx%.1lfmm", _width, _height, dwInchesX * MM_PER_IN, dwInchesY * MM_PER_IN);
- GdiComment(hdc, strlen(buff), (BYTE*) buff);
- }
-
- SetRect( &rc, 0, 0, (int) ceil(dwInchesX*dwDPI), (int) ceil(dwInchesY*dwDPI) );
-
- g_free(local_fn);
- g_free(unicode_fn);
-
- m_tr_stack.push( Geom::Scale(1, -1) * Geom::Translate(0, doc->getHeight())); /// @fixme hardcoded doc2dt transform
-
- return 0;
-}
-
-
-unsigned int PrintEmfWin32::finish (Inkscape::Extension::Print * /*mod*/)
-{
- if (!hdc) return 0;
-
- flush_fill(); // flush any pending fills
-
- HENHMETAFILE metafile = CloseEnhMetaFile( hdc );
- if ( metafile ) {
- DeleteEnhMetaFile( metafile );
- }
- DeleteDC( hdc );
-
- hdc = NULL;
-
- return 0;
-}
-
-
-unsigned int PrintEmfWin32::comment (Inkscape::Extension::Print * /*module*/,
- const char * /*comment*/)
-{
- if (!hdc) return 0;
-
- flush_fill(); // flush any pending fills
-
- return 0;
-}
-
-
-int PrintEmfWin32::create_brush(SPStyle const *style)
-{
- float rgb[3];
-
- if (style) {
- float opacity = SP_SCALE24_TO_FLOAT(style->fill_opacity.value);
- if (opacity <= 0.0)
- return 1;
-
- sp_color_get_rgb_floatv( &style->fill.value.color, rgb );
- hbrush = CreateSolidBrush( RGB(255*rgb[0], 255*rgb[1], 255*rgb[2]) );
- hbrushOld = (HBRUSH) SelectObject( hdc, hbrush );
-
- SetPolyFillMode( hdc,
- style->fill_rule.computed == 0 ? WINDING :
- style->fill_rule.computed == 2 ? ALTERNATE : ALTERNATE );
- } else { // if (!style)
- hbrush = CreateSolidBrush( RGB(255, 255, 255) );
- hbrushOld = (HBRUSH) SelectObject( hdc, hbrush );
- SetPolyFillMode( hdc, ALTERNATE );
- }
-
- return 0;
-}
-
-
-void PrintEmfWin32::destroy_brush()
-{
- SelectObject( hdc, hbrushOld );
- if (hbrush)
- DeleteObject( hbrush );
- hbrush = NULL;
- hbrushOld = NULL;
-}
-
-
-void PrintEmfWin32::create_pen(SPStyle const *style, const Geom::Affine &transform)
-{
- if (style) {
- float rgb[3];
-
- sp_color_get_rgb_floatv(&style->stroke.value.color, rgb);
-
- LOGBRUSH lb;
- ZeroMemory(&lb, sizeof(lb));
- lb.lbStyle = BS_SOLID;
- lb.lbColor = RGB( 255*rgb[0], 255*rgb[1], 255*rgb[2] );
-
- int linestyle = PS_SOLID;
- int linecap = 0;
- int linejoin = 0;
- DWORD n_dash = 0;
- DWORD *dash = NULL;
-
- using Geom::X;
- using Geom::Y;
-
- Geom::Point zero(0, 0);
- Geom::Point one(1, 1);
- Geom::Point p0(zero * transform);
- Geom::Point p1(one * transform);
- Geom::Point p(p1 - p0);
-
- double scale = sqrt( (p[X]*p[X]) + (p[Y]*p[Y]) ) / sqrt(2);
-
- DWORD linewidth = MAX( 1, (DWORD) (scale * style->stroke_width.computed * IN_PER_PX * dwDPI) );
-
- if (style->stroke_linecap.computed == 0) {
- linecap = PS_ENDCAP_FLAT;
- }
- else if (style->stroke_linecap.computed == 1) {
- linecap = PS_ENDCAP_ROUND;
- }
- else if (style->stroke_linecap.computed == 2) {
- linecap = PS_ENDCAP_SQUARE;
- }
-
- if (style->stroke_linejoin.computed == 0) {
- linejoin = PS_JOIN_MITER;
- }
- else if (style->stroke_linejoin.computed == 1) {
- linejoin = PS_JOIN_ROUND;
- }
- else if (style->stroke_linejoin.computed == 2) {
- linejoin = PS_JOIN_BEVEL;
- }
-
- if (style->stroke_dash.n_dash &&
- style->stroke_dash.dash )
- {
- int i = 0;
- while (linestyle != PS_USERSTYLE &&
- (i < style->stroke_dash.n_dash)) {
- if (style->stroke_dash.dash[i] > 0.00000001)
- linestyle = PS_USERSTYLE;
- i++;
- }
-
- if (linestyle == PS_USERSTYLE) {
- n_dash = style->stroke_dash.n_dash;
- dash = new DWORD[n_dash];
- for (i = 0; i < style->stroke_dash.n_dash; i++) {
- dash[i] = (DWORD) (style->stroke_dash.dash[i] * IN_PER_PX * dwDPI);
- }
- }
- }
-
- hpen = ExtCreatePen(
- PS_GEOMETRIC | linestyle | linecap | linejoin,
- linewidth,
- &lb,
- n_dash,
- dash );
-
- if ( !hpen && linestyle == PS_USERSTYLE ) {
- hpen = ExtCreatePen(
- PS_GEOMETRIC | PS_SOLID | linecap | linejoin,
- linewidth,
- &lb,
- 0,
- NULL );
- }
-
- if ( !hpen ) {
- hpen = CreatePen(
- PS_SOLID,
- linewidth,
- lb.lbColor );
- }
-
- hpenOld = (HPEN) SelectObject( hdc, hpen );
-
- if (linejoin == PS_JOIN_MITER) {
- float oldmiterlimit;
- float miterlimit = style->stroke_miterlimit.value; //ratio, not a pt size
-
- SetMiterLimit(
- hdc,
- miterlimit,
- &oldmiterlimit );
- }
-
- if (n_dash) {
- delete[] dash;
- }
- }
- else { // if (!style)
- hpen = CreatePen( PS_SOLID, 1, RGB(0, 0, 0) );
- hpenOld = (HPEN) SelectObject( hdc, hpen );
- }
-}
-
-
-void PrintEmfWin32::destroy_pen()
-{
- SelectObject( hdc, hpenOld );
- if (hpen)
- DeleteObject( hpen );
- hpen = NULL;
-}
-
-
-void PrintEmfWin32::flush_fill()
-{
- if (!fill_pathv.empty()) {
- stroke_and_fill = false;
- fill_only = true;
- print_pathv(fill_pathv, fill_transform);
- fill_only = false;
- if (!simple_shape)
- FillPath( hdc );
- destroy_brush();
- fill_pathv.clear();
- }
-}
-
-unsigned int PrintEmfWin32::bind(Inkscape::Extension::Print * /*mod*/, Geom::Affine const &transform, float /*opacity*/)
-{
- if (!m_tr_stack.empty()) {
- Geom::Affine tr_top = m_tr_stack.top();
- m_tr_stack.push(transform * tr_top);
- } else {
- m_tr_stack.push(transform);
- }
-
- return 1;
-}
-
-unsigned int PrintEmfWin32::release(Inkscape::Extension::Print * /*mod*/)
-{
- m_tr_stack.pop();
- return 1;
-}
-
-unsigned int PrintEmfWin32::fill(Inkscape::Extension::Print * /*mod*/,
- Geom::PathVector const &pathv, Geom::Affine const & /*transform*/, SPStyle const *style,
- Geom::OptRect const &/*pbox*/, Geom::OptRect const &/*dbox*/, Geom::OptRect const &/*bbox*/)
-{
- if (!hdc) return 0;
-
- Geom::Affine tf = m_tr_stack.top();
-
- flush_fill(); // flush any pending fills
-
- if (style->fill.isColor()) {
- if (create_brush(style))
- return 0;
- } else {
- // create_brush(NULL);
- return 0;
- }
-
- fill_pathv.clear();
- std::copy(pathv.begin(), pathv.end(), std::back_inserter(fill_pathv));
- fill_transform = tf;
-
- // postpone fill in case of stroke-and-fill
-
- return 0;
-}
-
-
-unsigned int PrintEmfWin32::stroke (Inkscape::Extension::Print * /*mod*/,
- Geom::PathVector const &pathv, const Geom::Affine &/*transform*/, const SPStyle *style,
- Geom::OptRect const &/*pbox*/, Geom::OptRect const &/*dbox*/, Geom::OptRect const &/*bbox*/)
-{
- if (!hdc) return 0;
-
- Geom::Affine tf = m_tr_stack.top();
-
- stroke_and_fill = ( pathv == fill_pathv );
-
- if (!stroke_and_fill) {
- flush_fill(); // flush any pending fills
- }
-
- if (style->stroke.isColor()) {
- create_pen(style, tf);
- } else {
- // create_pen(NULL, tf);
- return 0;
- }
-
- print_pathv(pathv, tf);
-
- if (stroke_and_fill) {
- if (!simple_shape)
- StrokeAndFillPath( hdc );
- destroy_brush();
- fill_pathv.clear();
- } else {
- if (!simple_shape)
- StrokePath( hdc );
- }
-
- destroy_pen();
-
- return 0;
-}
-
-
-bool PrintEmfWin32::print_simple_shape(Geom::PathVector const &pathv, const Geom::Affine &transform)
-{
- Geom::PathVector pv = pathv_to_linear_and_cubic_beziers( pathv * transform );
-
- int nodes = 0;
- int moves = 0;
- int lines = 0;
- int curves = 0;
-
- for (Geom::PathVector::const_iterator pit = pv.begin(); pit != pv.end(); ++pit)
- {
- moves++;
- nodes++;
-
- for (Geom::Path::const_iterator cit = pit->begin(); cit != pit->end_open(); ++cit)
- {
- nodes++;
-
- if ( is_straight_curve(*cit) ) {
- lines++;
- }
- else if (Geom::CubicBezier const *cubic = dynamic_cast(&*cit)) {
- cubic = cubic;
- curves++;
- }
- }
- }
-
- if (!nodes)
- return false;
-
- POINT *lpPoints = new POINT[moves + lines + curves*3];
- int i = 0;
-
- /**
- * For all Subpaths in the
- */
- for (Geom::PathVector::const_iterator pit = pv.begin(); pit != pv.end(); ++pit)
- {
- using Geom::X;
- using Geom::Y;
-
- Geom::Point p0 = pit->initialPoint();
-
- p0[X] = (p0[X] * IN_PER_PX * dwDPI);
- p0[Y] = (p0[Y] * IN_PER_PX * dwDPI);
-
- LONG const x0 = (LONG) round(p0[X]);
- LONG const y0 = (LONG) round(rc.bottom-p0[Y]);
-
- lpPoints[i].x = x0;
- lpPoints[i].y = y0;
- i = i + 1;
-
- /**
- * For all segments in the subpath
- */
- for (Geom::Path::const_iterator cit = pit->begin(); cit != pit->end_open(); ++cit)
- {
- if ( is_straight_curve(*cit) )
- {
- //Geom::Point p0 = cit->initialPoint();
- Geom::Point p1 = cit->finalPoint();
-
- //p0[X] = (p0[X] * IN_PER_PX * dwDPI);
- p1[X] = (p1[X] * IN_PER_PX * dwDPI);
- //p0[Y] = (p0[Y] * IN_PER_PX * dwDPI);
- p1[Y] = (p1[Y] * IN_PER_PX * dwDPI);
-
- //LONG const x0 = (LONG) round(p0[X]);
- //LONG const y0 = (LONG) round(rc.bottom-p0[Y]);
- LONG const x1 = (LONG) round(p1[X]);
- LONG const y1 = (LONG) round(rc.bottom-p1[Y]);
-
- lpPoints[i].x = x1;
- lpPoints[i].y = y1;
- i = i + 1;
- }
- else if (Geom::CubicBezier const *cubic = dynamic_cast(&*cit))
- {
- std::vector points = cubic->points();
- //Geom::Point p0 = points[0];
- Geom::Point p1 = points[1];
- Geom::Point p2 = points[2];
- Geom::Point p3 = points[3];
-
- //p0[X] = (p0[X] * IN_PER_PX * dwDPI);
- p1[X] = (p1[X] * IN_PER_PX * dwDPI);
- p2[X] = (p2[X] * IN_PER_PX * dwDPI);
- p3[X] = (p3[X] * IN_PER_PX * dwDPI);
- //p0[Y] = (p0[Y] * IN_PER_PX * dwDPI);
- p1[Y] = (p1[Y] * IN_PER_PX * dwDPI);
- p2[Y] = (p2[Y] * IN_PER_PX * dwDPI);
- p3[Y] = (p3[Y] * IN_PER_PX * dwDPI);
-
- //LONG const x0 = (LONG) round(p0[X]);
- //LONG const y0 = (LONG) round(rc.bottom-p0[Y]);
- LONG const x1 = (LONG) round(p1[X]);
- LONG const y1 = (LONG) round(rc.bottom-p1[Y]);
- LONG const x2 = (LONG) round(p2[X]);
- LONG const y2 = (LONG) round(rc.bottom-p2[Y]);
- LONG const x3 = (LONG) round(p3[X]);
- LONG const y3 = (LONG) round(rc.bottom-p3[Y]);
-
- POINT pt[3];
- pt[0].x = x1;
- pt[0].y = y1;
- pt[1].x = x2;
- pt[1].y = y2;
- pt[2].x = x3;
- pt[2].y = y3;
-
- lpPoints[i].x = x1;
- lpPoints[i].y = y1;
- lpPoints[i+1].x = x2;
- lpPoints[i+1].y = y2;
- lpPoints[i+2].x = x3;
- lpPoints[i+2].y = y3;
- i = i + 3;
- }
- }
- }
-
- bool done = false;
- bool closed = (lpPoints[0].x == lpPoints[i-1].x) && (lpPoints[0].y == lpPoints[i-1].y);
- bool polygon = false;
- bool rectangle = false;
- bool ellipse = false;
-
- if (moves == 1 && moves+lines == nodes && closed) {
- polygon = true;
-// if (nodes==5) { // disable due to LP Bug 407394
-// if (lpPoints[0].x == lpPoints[3].x && lpPoints[1].x == lpPoints[2].x &&
-// lpPoints[0].y == lpPoints[1].y && lpPoints[2].y == lpPoints[3].y)
-// {
-// rectangle = true;
-// }
-// }
- }
- else if (moves == 1 && nodes == 5 && moves+curves == nodes && closed) {
-// if (lpPoints[0].x == lpPoints[1].x && lpPoints[1].x == lpPoints[11].x &&
-// lpPoints[5].x == lpPoints[6].x && lpPoints[6].x == lpPoints[7].x &&
-// lpPoints[2].x == lpPoints[10].x && lpPoints[3].x == lpPoints[9].x && lpPoints[4].x == lpPoints[8].x &&
-// lpPoints[2].y == lpPoints[3].y && lpPoints[3].y == lpPoints[4].y &&
-// lpPoints[8].y == lpPoints[9].y && lpPoints[9].y == lpPoints[10].y &&
-// lpPoints[5].y == lpPoints[1].y && lpPoints[6].y == lpPoints[0].y && lpPoints[7].y == lpPoints[11].y)
-// { // disable due to LP Bug 407394
-// ellipse = true;
-// }
- }
-
- if (polygon || ellipse) {
- HPEN hpenTmp = NULL;
- HPEN hpenOld = NULL;
- HBRUSH hbrushTmp = NULL;
- HBRUSH hbrushOld = NULL;
-
- if (!stroke_and_fill) {
- if (fill_only) {
- hpenTmp = (HPEN) GetStockObject(NULL_PEN);
- hpenOld = (HPEN) SelectObject( hdc, hpenTmp );
- }
- else { // if (stroke_only)
- hbrushTmp = (HBRUSH) GetStockObject(NULL_BRUSH);
- hbrushOld = (HBRUSH) SelectObject( hdc, hbrushTmp );
- }
- }
-
- if (polygon) {
- if (rectangle)
- Rectangle( hdc, lpPoints[0].x, lpPoints[0].y, lpPoints[2].x, lpPoints[2].y );
- else
- Polygon( hdc, lpPoints, nodes );
- }
- else if (ellipse) {
- Ellipse( hdc, lpPoints[6].x, lpPoints[3].y, lpPoints[0].x, lpPoints[9].y);
- }
-
- done = true;
-
- if (hpenOld)
- SelectObject( hdc, hpenOld );
- if (hpenTmp)
- DeleteObject( hpenTmp );
- if (hbrushOld)
- SelectObject( hdc, hbrushOld );
- if (hbrushTmp)
- DeleteObject( hbrushTmp );
- }
-
- delete[] lpPoints;
-
- return done;
-}
-
-unsigned int PrintEmfWin32::print_pathv(Geom::PathVector const &pathv, const Geom::Affine &transform)
-{
- simple_shape = print_simple_shape(pathv, transform);
-
- if (simple_shape)
- return TRUE;
-
- Geom::PathVector pv = pathv_to_linear_and_cubic_beziers( pathv * transform );
-
- BeginPath( hdc );
-
- /**
- * For all Subpaths in the
- */
- for (Geom::PathVector::const_iterator pit = pv.begin(); pit != pv.end(); ++pit)
- {
- using Geom::X;
- using Geom::Y;
-
- Geom::Point p0 = pit->initialPoint();
-
- p0[X] = (p0[X] * IN_PER_PX * dwDPI);
- p0[Y] = (p0[Y] * IN_PER_PX * dwDPI);
-
- LONG const x0 = (LONG) round(p0[X]);
- LONG const y0 = (LONG) round(rc.bottom-p0[Y]);
-
- MoveToEx( hdc, x0, y0, NULL );
-
- /**
- * For all segments in the subpath
- */
- for (Geom::Path::const_iterator cit = pit->begin(); cit != pit->end_open(); ++cit)
- {
- if ( is_straight_curve(*cit) )
- {
- //Geom::Point p0 = cit->initialPoint();
- Geom::Point p1 = cit->finalPoint();
-
- //p0[X] = (p0[X] * IN_PER_PX * dwDPI);
- p1[X] = (p1[X] * IN_PER_PX * dwDPI);
- //p0[Y] = (p0[Y] * IN_PER_PX * dwDPI);
- p1[Y] = (p1[Y] * IN_PER_PX * dwDPI);
-
- //LONG const x0 = (LONG) round(p0[X]);
- //LONG const y0 = (LONG) round(rc.bottom-p0[Y]);
- LONG const x1 = (LONG) round(p1[X]);
- LONG const y1 = (LONG) round(rc.bottom-p1[Y]);
-
- LineTo( hdc, x1, y1 );
- }
- else if (Geom::CubicBezier const *cubic = dynamic_cast(&*cit))
- {
- std::vector points = cubic->points();
- //Geom::Point p0 = points[0];
- Geom::Point p1 = points[1];
- Geom::Point p2 = points[2];
- Geom::Point p3 = points[3];
-
- //p0[X] = (p0[X] * IN_PER_PX * dwDPI);
- p1[X] = (p1[X] * IN_PER_PX * dwDPI);
- p2[X] = (p2[X] * IN_PER_PX * dwDPI);
- p3[X] = (p3[X] * IN_PER_PX * dwDPI);
- //p0[Y] = (p0[Y] * IN_PER_PX * dwDPI);
- p1[Y] = (p1[Y] * IN_PER_PX * dwDPI);
- p2[Y] = (p2[Y] * IN_PER_PX * dwDPI);
- p3[Y] = (p3[Y] * IN_PER_PX * dwDPI);
-
- //LONG const x0 = (LONG) round(p0[X]);
- //LONG const y0 = (LONG) round(rc.bottom-p0[Y]);
- LONG const x1 = (LONG) round(p1[X]);
- LONG const y1 = (LONG) round(rc.bottom-p1[Y]);
- LONG const x2 = (LONG) round(p2[X]);
- LONG const y2 = (LONG) round(rc.bottom-p2[Y]);
- LONG const x3 = (LONG) round(p3[X]);
- LONG const y3 = (LONG) round(rc.bottom-p3[Y]);
-
- POINT pt[3];
- pt[0].x = x1;
- pt[0].y = y1;
- pt[1].x = x2;
- pt[1].y = y2;
- pt[2].x = x3;
- pt[2].y = y3;
-
- PolyBezierTo( hdc, pt, 3 );
- }
- else
- {
- g_warning("logical error, because pathv_to_linear_and_cubic_beziers was used");
- }
- }
-
- if (pit->end_default() == pit->end_closed()) {
- CloseFigure( hdc );
- }
- }
-
- EndPath( hdc );
-
- return TRUE;
-}
-
-
-bool PrintEmfWin32::textToPath(Inkscape::Extension::Print * ext)
-{
- return ext->get_param_bool("textToPath");
-}
-
-unsigned int PrintEmfWin32::text(Inkscape::Extension::Print * /*mod*/, char const *text, Geom::Point const &p,
- SPStyle const *const style)
-{
- if (!hdc) return 0;
-
- HFONT hfont = NULL;
- Geom::Affine tf = m_tr_stack.top();
- double rot = 1800.0*std::atan2(tf[1], tf[0])/M_PI; // 0.1 degree rotation
-
-#ifdef USE_PANGO_WIN32
-/*
- font_instance *tf = (font_factory::Default())->Face(style->text->font_family.value, font_style_to_pos(*style));
- if (tf) {
- LOGFONT *lf = pango_win32_font_logfont(tf->pFont);
- tf->Unref();
- hfont = CreateFontIndirect(lf);
- g_free(lf);
- }
-*/
-#endif
-
- if (!hfont) {
- LOGFONTW *lf = (LOGFONTW*)g_malloc(sizeof(LOGFONTW));
- g_assert(lf != NULL);
-
- lf->lfHeight = -style->font_size.computed * IN_PER_PX * dwDPI;
- lf->lfWidth = 0;
- lf->lfEscapement = rot;
- lf->lfOrientation = rot;
- lf->lfWeight =
- style->font_weight.computed == SP_CSS_FONT_WEIGHT_100 ? FW_THIN :
- style->font_weight.computed == SP_CSS_FONT_WEIGHT_200 ? FW_EXTRALIGHT :
- style->font_weight.computed == SP_CSS_FONT_WEIGHT_300 ? FW_LIGHT :
- style->font_weight.computed == SP_CSS_FONT_WEIGHT_400 ? FW_NORMAL :
- style->font_weight.computed == SP_CSS_FONT_WEIGHT_500 ? FW_MEDIUM :
- style->font_weight.computed == SP_CSS_FONT_WEIGHT_600 ? FW_SEMIBOLD :
- style->font_weight.computed == SP_CSS_FONT_WEIGHT_700 ? FW_BOLD :
- style->font_weight.computed == SP_CSS_FONT_WEIGHT_800 ? FW_EXTRABOLD :
- style->font_weight.computed == SP_CSS_FONT_WEIGHT_900 ? FW_HEAVY :
- FW_NORMAL;
- lf->lfItalic = (style->font_style.computed == SP_CSS_FONT_STYLE_ITALIC);
- lf->lfUnderline = style->text_decoration.underline;
- lf->lfStrikeOut = style->text_decoration.line_through;
- lf->lfCharSet = DEFAULT_CHARSET;
- lf->lfOutPrecision = OUT_DEFAULT_PRECIS;
- lf->lfClipPrecision = CLIP_DEFAULT_PRECIS;
- lf->lfQuality = DEFAULT_QUALITY;
- lf->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
-
- gunichar2 *unicode_name = g_utf8_to_utf16( style->text->font_family.value, -1, NULL, NULL, NULL );
- wcsncpy(lf->lfFaceName, (wchar_t*) unicode_name, LF_FACESIZE-1);
- g_free(unicode_name);
-
- hfont = CreateFontIndirectW(lf);
-
- g_free(lf);
- }
-
- HFONT hfontOld = (HFONT) SelectObject(hdc, hfont);
-
- float rgb[3];
- sp_color_get_rgb_floatv( &style->fill.value.color, rgb );
- SetTextColor(hdc, RGB(255*rgb[0], 255*rgb[1], 255*rgb[2]));
-
- // Text alignment:
- // - (x,y) coordinates received by this filter are those of the point where the text
- // actually starts, and already takes into account the text object's alignment;
- // - for this reason, the EMF text alignment must always be TA_BASELINE|TA_LEFT.
- SetTextAlign(hdc, TA_BASELINE | TA_LEFT);
-
- // Transparent text background
- SetBkMode(hdc, TRANSPARENT);
-
- Geom::Point p2 = p * tf;
- p2[Geom::X] = (p2[Geom::X] * IN_PER_PX * dwDPI);
- p2[Geom::Y] = (p2[Geom::Y] * IN_PER_PX * dwDPI);
-
- LONG const xpos = (LONG) round(p2[Geom::X]);
- LONG const ypos = (LONG) round(rc.bottom - p2[Geom::Y]);
-
- {
- gunichar2 *unicode_text = g_utf8_to_utf16( text, -1, NULL, NULL, NULL );
- TextOutW(hdc, xpos, ypos, (WCHAR*)unicode_text, wcslen((wchar_t*)unicode_text));
- }
-
- SelectObject(hdc, hfontOld);
- DeleteObject(hfont);
-
- return 0;
-}
-
-void PrintEmfWin32::init (void)
-{
- /* EMF print */
- Inkscape::Extension::build_from_mem(
- "\n"
- "Enhanced Metafile Print\n"
- "org.inkscape.print.emf.win32\n"
- "\n"
- "true\n"
- "true\n"
- "\n"
- "", new PrintEmfWin32());
-
- return;
-}
-
-unsigned int PrintEmfWin32::image(Inkscape::Extension::Print * /* module */, /** not used */
- unsigned char *px, /** array of pixel values, Gdk::Pixbuf bitmap format */
- unsigned int /*w*/, /** width of bitmap */
- unsigned int /*h*/, /** height of bitmap */
- unsigned int /*rs*/, /** row stride (normally w*4) */
- Geom::Affine const & /*tf_ignore*/, /** WRONG affine transform, use the one from m_tr_stack */
- SPStyle const * /*style*/) /** provides indirect link to image object */
-{
- free(px);
- return 0;
-}
-
-} /* namespace Internal */
-} /* namespace Extension */
-} /* namespace Inkscape */
-
-#endif /* WIN32 */
-
-/*
- 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 -rNu3 src/extension/internal/emf-win32-print.h src/extension/internal/emf-win32-print.h
--- src/extension/internal/emf-win32-print.h 2012-08-07 12:29:10.000000000 -0700
+++ src/extension/internal/emf-win32-print.h 1969-12-31 16:00:00.000000000 -0800
@@ -1,120 +0,0 @@
-/** @file
- * @brief Enhanced Metafile printing - implementation
- */
-/* Author:
- * Ulf Erikson
- *
- * Copyright (C) 2006-2008 Authors
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-#ifndef __INKSCAPE_EXTENSION_INTERNAL_PRINT_EMF_WIN32_H__
-#define __INKSCAPE_EXTENSION_INTERNAL_PRINT_EMF_WIN32_H__
-
-#ifdef WIN32
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#define WIN32_LEAN_AND_MEAN
-#include
-
-#include "extension/implementation/implementation.h"
-//#include "extension/extension.h"
-
-#include <2geom/pathvector.h>
-
-#include
-
-namespace Inkscape {
-namespace Extension {
-namespace Internal {
-
-class PrintEmfWin32 : public Inkscape::Extension::Implementation::Implementation
-{
- double _width;
- double _height;
- HDC hdc;
- RECT rc;
-
- HBRUSH hbrush, hbrushOld;
- HPEN hpen, hpenOld;
-
- std::stack m_tr_stack;
- Geom::PathVector fill_pathv;
- Geom::Affine fill_transform;
- bool stroke_and_fill;
- bool fill_only;
- bool simple_shape;
-
- unsigned int print_pathv (Geom::PathVector const &pathv, const Geom::Affine &transform);
- bool print_simple_shape (Geom::PathVector const &pathv, const Geom::Affine &transform);
- unsigned int image(Inkscape::Extension::Print * /* module */, /** not used */
- unsigned char *px, /** array of pixel values, Gdk::Pixbuf bitmap format */
- unsigned int w, /** width of bitmap */
- unsigned int h, /** height of bitmap */
- unsigned int rs, /** row stride (normally w*4) */
- Geom::Affine const &tf_ignore, /** WRONG affine transform, use the one from m_tr_stack */
- SPStyle const *style); /** provides indirect link to image object */
-
-public:
- PrintEmfWin32 (void);
- virtual ~PrintEmfWin32 (void);
-
- /* Print functions */
- virtual unsigned int setup (Inkscape::Extension::Print * module);
-
- virtual unsigned int begin (Inkscape::Extension::Print * module, SPDocument *doc);
- virtual unsigned int finish (Inkscape::Extension::Print * module);
-
- /* Rendering methods */
- virtual unsigned int bind(Inkscape::Extension::Print *module, Geom::Affine const &transform, float opacity);
- virtual unsigned int release(Inkscape::Extension::Print *module);
- virtual unsigned int fill (Inkscape::Extension::Print *module,
- Geom::PathVector const &pathv,
- Geom::Affine const &ctm, SPStyle const *style,
- Geom::OptRect const &pbox, Geom::OptRect const &dbox,
- Geom::OptRect const &bbox);
- virtual unsigned int stroke (Inkscape::Extension::Print * module,
- Geom::PathVector const &pathv,
- Geom::Affine const &ctm, SPStyle const *style,
- Geom::OptRect const &pbox, Geom::OptRect const &dbox,
- Geom::OptRect const &bbox);
- virtual unsigned int comment(Inkscape::Extension::Print *module, const char * comment);
- virtual unsigned int text(Inkscape::Extension::Print *module, char const *text,
- Geom::Point const &p, SPStyle const *style);
- bool textToPath (Inkscape::Extension::Print * ext);
-
- static void init (void);
-protected:
- int create_brush(SPStyle const *style);
-
- void destroy_brush();
-
- void create_pen(SPStyle const *style, const Geom::Affine &transform);
-
- void destroy_pen();
-
- void flush_fill();
-
-};
-
-} /* namespace Internal */
-} /* namespace Extension */
-} /* namespace Inkscape */
-
-#endif /* WIN32 */
-
-#endif /* __INKSCAPE_EXTENSION_INTERNAL_PRINT_EMF_WIN32_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 -rNu3 src/extension/internal/Makefile_insert src/extension/internal/Makefile_insert
--- src/extension/internal/Makefile_insert 2012-08-07 12:29:10.000000000 -0700
+++ src/extension/internal/Makefile_insert 2012-08-08 09:49:58.000000000 -0700
@@ -133,10 +133,14 @@
extension/internal/filter/filter.h \
extension/internal/filter/drop-shadow.h \
extension/internal/filter/snow.h \
- extension/internal/emf-win32-print.h \
- extension/internal/emf-win32-print.cpp \
- extension/internal/emf-win32-inout.h \
- extension/internal/emf-win32-inout.cpp \
+ extension/internal/uemf.c \
+ extension/internal/uemf.h \
+ extension/internal/uemf_endian.c \
+ extension/internal/uemf_endian.h \
+ extension/internal/emf-print.h \
+ extension/internal/emf-print.cpp \
+ extension/internal/emf-inout.h \
+ extension/internal/emf-inout.cpp \
extension/internal/image-resolution.h \
extension/internal/image-resolution.cpp
diff -rNu3 src/extension/internal/uemf.c src/extension/internal/uemf.c
--- src/extension/internal/uemf.c 1969-12-31 16:00:00.000000000 -0800
+++ src/extension/internal/uemf.c 2012-08-08 10:27:38.000000000 -0700
@@ -0,0 +1,5518 @@
+/**
+ @file uemf.c 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.5
+Date: 08-AUG-2012
+Author: David Mathog, Biology Division, Caltech
+email: mathog@caltech.edu
+Copyright: 2012 David Mathog and California Institute of Technology (Caltech)
+*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include // for INT_MAX, INT_MIN
+#include // for U_ROUND()
+#if 0
+#include //Not actually used, looking for collisions
+#include //Not actually used, looking for collisions
+#include //Not actually used, looking for collisions
+#endif
+#include "uemf.h"
+/* one prototype from uemf_endian. Put it here because end user should never need to see it, sno
+not in uemf.h or uemf_endian.h */
+void U_swap2(void *ul, unsigned int count);
+
+/* **********************************************************************************************
+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_BIMAPINFO, 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 * B->bmiHeader.biClrUsed; /* bmiheader + colortable*/ \
+ }\
+ else { 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){ 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;\
+ }
+
+/* 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).
+*/
+#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 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(
+ 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 a UTF8 string. Not for use in production code.
+ \param src string to examine
+*/
+void wchar8show(
+ const char *src
+ ){
+ 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
+ ){
+ 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
+ ){
+ 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;
+ printf("wchar_t show\n");
+ size_t srclen = 0;
+ 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++;
+ }
+}
+
+/**
+ \brief Dump the eht structure. Not for use in production code.
+ \param string Text to output before dumping eht structure
+ \param handle Handle
+ \param eht eht 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 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;
+ 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;
+ 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
+ ){
+ 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
+ ){
+ for(;nchars;nchars--,dst++,src++){
+ *dst = *src;
+ if(!*src)break;
+ }
+ 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;
+ size_t srclen,dstlen,status;
+
+ 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)return(NULL);
+ iconv_t conv = iconv_open("UTF-16LE", "UTF-32LE");
+ status = iconv(conv, ICONV_CAST &src, &srclen, &dst, &dstlen);
+ iconv_close(conv);
+ if(status == (size_t) -1)return(NULL);
+ 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(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)return(NULL);
+ iconv_t conv = iconv_open("UTF-32LE", "UTF-16LE");
+ if ( conv == (iconv_t)-1)return(NULL);
+ status = iconv(conv, ICONV_CAST &src2, &srclen, &dst, &dstlen);
+ iconv_close(conv);
+ if(status == (size_t) -1)return(NULL);
+ 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(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)return(NULL);
+ iconv_t conv = iconv_open("UTF-32LE", "UTF-8");
+ if ( conv == (iconv_t) -1)return(NULL);
+ status = iconv(conv, ICONV_CAST &src2, &srclen, &dst, &dstlen);
+ iconv_close(conv);
+ if(status == (size_t) -1)return(NULL);
+ 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(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)return(NULL);
+ iconv_t conv = iconv_open("UTF-8", "UTF-32LE");
+ if ( conv == (iconv_t)-1)return(NULL);
+ status = iconv(conv, ICONV_CAST &src2, &srclen, &dst, &dstlen);
+ iconv_close(conv);
+ if(status == (size_t) -1)return(NULL);
+ 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;
+ size_t srclen,dstlen,status;
+ iconv_t conv;
+
+ 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)return(NULL);
+ conv = iconv_open("UTF-16LE", "UTF-8");
+ if (conv == (iconv_t) -1)return(NULL);
+ status = iconv(conv, ICONV_CAST &src, &srclen, &dst, &dstlen);
+ iconv_close(conv);
+ if(status == (size_t) -1)return(NULL);
+ 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, *ret;
+ size_t srclen,dstlen,status;
+ if(max){ srclen = 2*max; }
+ else { srclen = 2*(1 +wchar16len(src)); } //include terminator, length in BYTES
+ dstlen = 1 + srclen; // this will always work, but may waste space
+ dst2 = dst = (char *) calloc(dstlen,1);
+ if(!dst)return(NULL);
+ iconv_t conv = iconv_open("UTF-8", "UTF-16LE");
+ status = iconv(conv, ICONV_CAST &src, &srclen, &dst, &dstlen);
+ iconv_close(conv);
+ if(status == (size_t) -1)return(NULL);
+ if(len)*len=strlen(dst2);
+ ret=U_strdup(dst2); // make a string of exactly the right size
+ free(dst2); // free the one which was probably too big
+ return(ret);
+}
+
+/**
+ \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 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);
+
+}
+
+/**
+ \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.
+
+ \return bitmap of EMR record properties, or 0xFFFFFFFF on error
+ \param type EMR record type
+
+*/
+uint32_t emr_properties(uint32_t type){
+ static uint32_t *table=NULL;
+ if(!table){
+ table = (uint32_t *) malloc(sizeof(uint32_t)*(1 + U_EMR_MAX));
+ if(!table)return(0xFFFFFFFF);
+// 0x40 0x20 0x10 0x08 0x04 0x02 0x01
+// Path properties (U_DRAW_*) ALTERS ONLYTO VISIBLE
+// PATH FORCE CLOSED NOTEMPTY
+ table[ 0] = 0x00; //!< Does not map to any EMR record
+ table[ 1] = 0x00; //!< U_EMRHEADER 0 0 0 0 0 0 0
+ table[ 2] = 0x03; //!< U_EMRPOLYBEZIER 0 0 0 0 0 1 1
+ table[ 3] = 0x07; //!< U_EMRPOLYGON 0 0 0 0 1 1 1
+ table[ 4] = 0x03; //!< U_EMRPOLYLINE 0 0 0 0 0 1 1
+ table[ 5] = 0x0B; //!< U_EMRPOLYBEZIERTO 0 0 0 1 0 1 1
+ table[ 6] = 0x0B; //!< U_EMRPOLYLINETO 0 0 0 1 0 1 1
+ table[ 7] = 0x03; //!< U_EMRPOLYPOLYLINE 0 0 0 0 0 1 1
+ table[ 8] = 0x07; //!< U_EMRPOLYPOLYGON 0 0 0 0 1 1 1
+ table[ 9] = 0x20; //!< U_EMRSETWINDOWEXTEX 0 1 0 0 0 0 0
+ table[ 10] = 0x20; //!< U_EMRSETWINDOWORGEX 0 1 0 0 0 0 0
+ table[ 11] = 0x20; //!< U_EMRSETVIEWPORTEXTEX 0 1 0 0 0 0 0
+ table[ 12] = 0x20; //!< U_EMRSETVIEWPORTORGEX 0 1 0 0 0 0 0
+ table[ 13] = 0x20; //!< U_EMRSETBRUSHORGEX 0 1 0 0 0 0 0
+ table[ 14] = 0x02; //!< U_EMREOF 0 1 0 0 0 0 0 Force out any pending draw
+ table[ 15] = 0x02; //!< U_EMRSETPIXELV 0 0 0 0 0 1 0
+ table[ 16] = 0x20; //!< U_EMRSETMAPPERFLAGS 0 1 0 0 0 0 0
+ table[ 17] = 0x20; //!< U_EMRSETMAPMODE 0 1 0 0 0 0 0
+ table[ 18] = 0x20; //!< U_EMRSETBKMODE 0 1 0 0 0 0 0
+ table[ 19] = 0x20; //!< U_EMRSETPOLYFILLMODE 0 1 0 0 0 0 0
+ table[ 20] = 0x20; //!< U_EMRSETROP2 0 1 0 0 0 0 0
+ table[ 21] = 0x20; //!< U_EMRSETSTRETCHBLTMODE 0 1 0 0 0 0 0
+ table[ 22] = 0x20; //!< U_EMRSETTEXTALIGN 0 1 0 0 0 0 0
+ table[ 23] = 0x20; //!< U_EMRSETCOLORADJUSTMENT 0 1 0 0 0 0 0
+ table[ 24] = 0x20; //!< U_EMRSETTEXTCOLOR 0 1 0 0 0 0 0
+ table[ 25] = 0x20; //!< U_EMRSETBKCOLOR 0 1 0 0 0 0 0
+ table[ 26] = 0x20; //!< U_EMROFFSETCLIPRGN 0 1 0 0 0 0 0
+ table[ 27] = 0x09; //!< U_EMRMOVETOEX 0 0 0 1 0 0 1
+ table[ 28] = 0x20; //!< U_EMRSETMETARGN 0 1 0 0 0 0 0
+ table[ 29] = 0x20; //!< U_EMREXCLUDECLIPRECT 0 1 0 0 0 0 0
+ table[ 30] = 0x20; //!< U_EMRINTERSECTCLIPRECT 0 1 0 0 0 0 0
+ table[ 31] = 0x20; //!< U_EMRSCALEVIEWPORTEXTEX 0 1 0 0 0 0 0
+ table[ 32] = 0x20; //!< U_EMRSCALEWINDOWEXTEX 0 1 0 0 0 0 0
+ table[ 33] = 0x20; //!< U_EMRSAVEDC 0 1 0 0 0 0 0
+ table[ 34] = 0x20; //!< U_EMRRESTOREDC 0 1 0 0 0 0 0
+ table[ 35] = 0x20; //!< U_EMRSETWORLDTRANSFORM 0 1 0 0 0 0 0
+ table[ 36] = 0x20; //!< U_EMRMODIFYWORLDTRANSFORM 0 1 0 0 0 0 0
+ table[ 37] = 0x20; //!< U_EMRSELECTOBJECT 0 1 0 0 0 0 0
+ table[ 38] = 0x20; //!< U_EMRCREATEPEN 0 1 0 0 0 0 0
+ table[ 39] = 0x20; //!< U_EMRCREATEBRUSHINDIRECT 0 1 0 0 0 0 0
+ table[ 40] = 0x20; //!< U_EMRDELETEOBJECT 0 1 0 0 0 0 0
+ table[ 41] = 0x03; //!< U_EMRANGLEARC 0 0 0 0 0 1 1
+ table[ 42] = 0x07; //!< U_EMRELLIPSE 0 0 0 0 1 1 1
+ table[ 43] = 0x07; //!< U_EMRRECTANGLE 0 0 0 0 1 1 1
+ table[ 44] = 0x07; //!< U_EMRROUNDRECT 0 0 0 0 1 1 1
+ table[ 45] = 0x03; //!< U_EMRARC 0 0 0 0 0 1 1
+ table[ 46] = 0x07; //!< U_EMRCHORD 0 0 0 0 1 1 1
+ table[ 47] = 0x07; //!< U_EMRPIE 0 0 0 0 1 1 1
+ table[ 48] = 0x20; //!< U_EMRSELECTPALETTE 0 1 0 0 0 0 0
+ table[ 49] = 0x20; //!< U_EMRCREATEPALETTE 0 1 0 0 0 0 0
+ table[ 50] = 0x20; //!< U_EMRSETPALETTEENTRIES 0 1 0 0 0 0 0
+ table[ 51] = 0x20; //!< U_EMRRESIZEPALETTE 0 1 0 0 0 0 0
+ table[ 52] = 0x20; //!< U_EMRREALIZEPALETTE 0 1 0 0 0 0 0
+ table[ 53] = 0x02; //!< U_EMREXTFLOODFILL 0 0 0 0 0 1 0
+ table[ 54] = 0x0B; //!< U_EMRLINETO 0 0 0 1 0 1 1
+ table[ 55] = 0x0B; //!< U_EMRARCTO 0 0 0 1 0 1 1
+ table[ 56] = 0x03; //!< U_EMRPOLYDRAW 0 0 0 0 0 1 1
+ table[ 57] = 0x20; //!< U_EMRSETARCDIRECTION 0 1 0 0 0 0 0
+ table[ 58] = 0x20; //!< U_EMRSETMITERLIMIT 0 1 0 0 0 0 0
+ table[ 59] = 0x60; //!< U_EMRBEGINPATH 1 1 0 0 0 0 0
+ table[ 60] = 0x00; //!< U_EMRENDPATH 0 0 0 0 0 0 0
+ table[ 61] = 0x04; //!< U_EMRCLOSEFIGURE 0 0 0 0 1 0 0
+ table[ 62] = 0x14; //!< U_EMRFILLPATH 0 0 1 0 1 0 0
+ table[ 63] = 0x14; //!< U_EMRSTROKEANDFILLPATH 0 0 1 0 1 0 0
+ table[ 64] = 0x10; //!< U_EMRSTROKEPATH 0 0 1 0 0 0 0
+ table[ 65] = 0x20; //!< U_EMRFLATTENPATH 0 1 0 0 0 0 0
+ table[ 66] = 0x20; //!< U_EMRWIDENPATH 0 1 0 0 0 0 0
+ table[ 67] = 0x20; //!< U_EMRSELECTCLIPPATH 0 1 0 0 0 0 0
+ table[ 68] = 0x20; //!< U_EMRABORTPATH 0 1 0 0 0 0 0
+ table[ 69] = 0x20; //!< U_EMRUNDEF69 0 1 0 0 0 0 0
+ table[ 70] = 0x00; //!< U_EMRCOMMENT 0 0 0 0 0 0 0
+ table[ 71] = 0x02; //!< U_EMRFILLRGN 0 0 0 0 0 1 0
+ table[ 72] = 0x02; //!< U_EMRFRAMERGN 0 0 0 0 0 1 0
+ table[ 73] = 0x02; //!< U_EMRINVERTRGN 0 0 0 0 0 1 0
+ table[ 74] = 0x02; //!< U_EMRPAINTRGN 0 0 0 0 0 1 0
+ table[ 75] = 0x20; //!< U_EMREXTSELECTCLIPRGN 0 1 0 0 0 0 0
+ table[ 76] = 0x02; //!< U_EMRBITBLT 0 0 0 0 0 1 0
+ table[ 77] = 0x02; //!< U_EMRSTRETCHBLT 0 0 0 0 0 1 0
+ table[ 78] = 0x02; //!< U_EMRMASKBLT 0 0 0 0 0 1 0
+ table[ 79] = 0x02; //!< U_EMRPLGBLT 0 0 0 0 0 1 0
+ table[ 80] = 0x20; //!< U_EMRSETDIBITSTODEVICE 0 1 0 0 0 0 0
+ table[ 81] = 0x20; //!< U_EMRSTRETCHDIBITS 0 1 0 0 0 0 0
+ table[ 82] = 0x20; //!< U_EMREXTCREATEFONTINDIRECTW 0 1 0 0 0 0 0
+ table[ 83] = 0x02; //!< U_EMREXTTEXTOUTA 0 0 0 0 0 1 0
+ table[ 84] = 0x02; //!< U_EMREXTTEXTOUTW 0 0 0 0 0 1 0
+ table[ 85] = 0x03; //!< U_EMRPOLYBEZIER16 0 0 0 0 0 1 1
+ table[ 86] = 0x03; //!< U_EMRPOLYGON16 0 0 0 0 0 1 1
+ table[ 87] = 0x03; //!< U_EMRPOLYLINE16 0 0 0 0 0 1 1
+ table[ 88] = 0x0B; //!< U_EMRPOLYBEZIERTO16 0 0 0 1 0 1 1
+ table[ 89] = 0x0B; //!< U_EMRPOLYLINETO16 0 0 0 1 0 1 1
+ table[ 90] = 0x03; //!< U_EMRPOLYPOLYLINE16 0 0 0 0 0 1 1
+ table[ 91] = 0x07; //!< U_EMRPOLYPOLYGON16 0 0 0 0 1 1 1
+ table[ 92] = 0x03; //!< U_EMRPOLYDRAW16 0 0 0 0 0 1 1
+ table[ 93] = 0x00; //!< U_EMRCREATEMONOBRUSH 0 0 0 0 0 0 0 Not selected yet, so no change in drawing conditions
+ table[ 94] = 0x00; //!< U_EMRCREATEDIBPATTERNBRUSHPT 0 0 0 0 0 0 0 "
+ table[ 95] = 0x00; //!< U_EMREXTCREATEPEN 0 0 0 0 0 0 0 "
+ table[ 96] = 0x02; //!< U_EMRPOLYTEXTOUTA 0 0 0 0 0 1 0
+ table[ 97] = 0x02; //!< U_EMRPOLYTEXTOUTW 0 0 0 0 0 1 0
+ table[ 98] = 0x20; //!< U_EMRSETICMMODE 0 1 0 0 0 0 0
+ table[ 99] = 0x20; //!< U_EMRCREATECOLORSPACE 0 1 0 0 0 0 0
+ table[100] = 0x20; //!< U_EMRSETCOLORSPACE 0 1 0 0 0 0 0
+ table[101] = 0x20; //!< U_EMRDELETECOLORSPACE 0 1 0 0 0 0 0
+ table[102] = 0x20; //!< U_EMRGLSRECORD 0 1 0 0 0 0 0
+ table[103] = 0x20; //!< U_EMRGLSBOUNDEDRECORD 0 1 0 0 0 0 0
+ table[104] = 0x20; //!< U_EMRPIXELFORMAT 0 1 0 0 0 0 0
+ table[105] = 0x20; //!< U_EMRDRAWESCAPE 0 1 0 0 0 0 0
+ table[106] = 0x20; //!< U_EMREXTESCAPE 0 1 0 0 0 0 0
+ table[107] = 0x20; //!< U_EMRUNDEF107 0 1 0 0 0 0 0
+ table[108] = 0x02; //!< U_EMRSMALLTEXTOUT 0 0 0 0 0 1 0
+ table[109] = 0x20; //!< U_EMRFORCEUFIMAPPING 0 1 0 0 0 0 0
+ table[110] = 0x20; //!< U_EMRNAMEDESCAPE 0 1 0 0 0 0 0
+ table[111] = 0x20; //!< U_EMRCOLORCORRECTPALETTE 0 1 0 0 0 0 0
+ table[112] = 0x20; //!< U_EMRSETICMPROFILEA 0 1 0 0 0 0 0
+ table[113] = 0x20; //!< U_EMRSETICMPROFILEW 0 1 0 0 0 0 0
+ table[114] = 0x02; //!< U_EMRALPHABLEND 0 0 0 0 0 1 0
+ table[115] = 0x20; //!< U_EMRSETLAYOUT 0 1 0 0 0 0 0
+ table[116] = 0x02; //!< U_EMRTRANSPARENTBLT 0 0 0 0 0 1 0
+ table[117] = 0x20; //!< U_EMRUNDEF117 0 1 0 0 0 0 0
+ table[118] = 0x02; //!< U_EMRGRADIENTFILL 0 0 0 0 0 1 0
+ table[119] = 0x20; //!< U_EMRSETLINKEDUFIS 0 1 0 0 0 0 0
+ table[120] = 0x20; //!< U_EMRSETTEXTJUSTIFICATION 0 1 0 0 0 0 0
+ table[121] = 0x20; //!< U_EMRCOLORMATCHTOTARGETW 0 1 0 0 0 0 0
+ table[122] = 0x20; //!< U_EMRCREATECOLORSPACEW 0 1 0 0 0 0 0
+ }
+ if(type<1 || type >U_EMR_MAX)return(0xFFFFFFFF);
+ return(table[type]);
+}
+
+/**
+ \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
+ ){
+ 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;
+ PU_EMRARC pEmr = (PU_EMRARC) (record);
+ center->x = ((float)(pEmr->rclBox.left + pEmr->rclBox.right ))/2.0;
+ center->y = ((float)(pEmr->rclBox.top + pEmr->rclBox.bottom))/2.0;
+ size->x = (float)(pEmr->rclBox.right - pEmr->rclBox.left );
+ size->y = (float)(pEmr->rclBox.bottom - pEmr->rclBox.top );
+ estart.x = (float)(pEmr->ptlStart.x);
+ estart.y = (float)(pEmr->ptlStart.y);
+ eend.x = (float)(pEmr->ptlEnd.x);
+ eend.y = (float)(pEmr->ptlEnd.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 = start->x * end->y - start->y * end->x;
+ if(!f2){ // counter clockwise rotation
+ if(cross >=0){ *f1 = 0; }
+ else { *f1 = 1; }
+ }
+ else {
+ if(cross >=0){ *f1 = 1; }
+ else { *f1 = 0; }
+ }
+
+
+ return(0);
+}
+
+/**
+ \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,
+ 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;
+ 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){
+ 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 *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 DIB parameters from the BMI of the record for use by DBI_to_RGBA()
+
+ \return 0 on success, other values on errors.
+ \param pEmr 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
+ \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(
+ void *pEmr,
+ uint32_t offBitsSrc,
+ uint32_t offBmiSrc,
+ char **px,
+ PU_RGBQUAD *ct,
+ uint32_t *numCt,
+ uint32_t *width,
+ uint32_t *height,
+ uint32_t *colortype,
+ uint32_t *invert
+ ){
+ PU_BITMAPINFO Bmi = (PU_BITMAPINFO)((char *)pEmr + offBmiSrc);
+ if(Bmi->bmiHeader.biCompression != U_BI_RGB)return(1);
+ *width = Bmi->bmiHeader.biWidth;
+ *colortype = Bmi->bmiHeader.biBitCount;
+ *numCt = Bmi->bmiHeader.biClrUsed;
+ if(Bmi->bmiHeader.biHeight < 0){
+ *height = -Bmi->bmiHeader.biHeight;
+ *invert = 1;
+ }
+ else {
+ *height = Bmi->bmiHeader.biHeight;
+ *invert = 0;
+ }
+ if(numCt){
+ *ct = (PU_RGBQUAD) ((char *)Bmi + sizeof(U_BITMAPINFOHEADER));
+ }
+ *px = (char *)((char *)pEmr + offBitsSrc);
+ return(0);
+}
+
+/**
+ \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
+ \param h Height of pixel array
+ \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(
+ char *px,
+ PU_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;
+ 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){
+ 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> 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; jnSize;
+ 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 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 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);
+ free(ehtl->table);
+ return(5);
+ }
+ memset(ehtl->table , 0, initsize * sizeof(uint32_t)); // zero all slots in the table
+ for(i=1; istack[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 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 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);
+ eht->stack = realloc(eht->stack,newsize * sizeof(uint32_t));
+ if(!eht->stack)return(6);
+ for(i=eht->allocated; istack[i] = i; }
+ 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 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.
+ \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); // because coordinate system is 0,0 in upper left, N,M in lower right
+ rclBounds->bottom = U_ROUND((float) ymm * dpmm);
+ rclFrame->left = 0;
+ rclFrame->top = 0;
+ rclFrame->right = U_ROUND((float) xmm * 100.);
+ rclFrame->bottom = U_ROUND((float) ymm * 100.);
+ return(0);
+}
+
+/**
+ \brief Set a U_COLORREF value from separeate R,G,B values.
+ Or use macro directly: cr = U_RGB(r,g,b).
+ \param red Red component
+ \param green Green component
+ \param blue Blue component
+
+*/
+U_COLORREF colorref_set(
+ uint8_t red,
+ uint8_t green,
+ uint8_t blue
+ ){
+ U_COLORREF cr = (U_COLORREF){red , green, blue, 0};
+ 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 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; ix < 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; ix < 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 axesRatio 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;
+ memset(lcsa.lcsFilename,0,U_MAX_PATH); // zero out the Filename field
+ strncpy(lcsa.lcsFilename,lcsFilename,U_MAX_PATH);
+ 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);
+ 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
+ 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);
+ wchar16strncpy(lfp.elfStyle, elfStyle, U_LF_FACESIZE);
+ 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*BmiHeader.biClrUsed;
+ 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 retangle 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(
+ 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(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(eht->top < ihObject)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(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(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(htable_insert(ihBrush, eht))return(NULL);
+ return(U_EMRCREATEBRUSHINDIRECT_set(*ihBrush, lb));
+}
+
+/**
+ \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(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(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(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(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(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(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(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; iiType = 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(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(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(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(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(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(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(
+ 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(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(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(uint32_t iType, PU_RGNDATA RgnData){
+ char *record;
+ int irecsize;
+ int cbRgns,cbRgns4,off;
+
+ if(!RgnData)return(NULL);
+ cbRgns = ((PU_RGNDATAHEADER) RgnData)->nRgnSize;
+ cbRgns4 = UP4(cbRgns);
+ irecsize = sizeof(U_EMRINVERTRGN) + cbRgns4 - sizeof(U_RGNDATAHEADER); // core + array - overlap
+ 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 = cbRgns;
+ off = irecsize - cbRgns4;
+ memcpy(record + off, RgnData, cbRgns);
+ off += cbRgns;
+ if(cbRgns < cbRgns4){ memset(record + off,0, cbRgns4 - cbRgns); } // 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)
+ ){
+ char *record;
+ int irecsize;
+ int cbImage,cbImage4,cbBmi,off;
+
+ if(Bmi){
+ if(Bmi->bmiHeader.biSizeImage != 0){ cbImage = Bmi->bmiHeader.biSizeImage; }
+ else { cbImage = 0; }
+ cbImage4 = UP4(cbImage); // pixel array might not be a multiples of 4 bytes
+ cbBmi = sizeof(U_BITMAPINFOHEADER) + 4 * Bmi->bmiHeader.biClrUsed; // bmiheader + colortable
+ }
+ else { cbBmi = 0; cbImage4=0; }
+
+ 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;
+ ((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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(U_EMR_OFFSETCLIPRGN, (U_PAIR) 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(U_EMR_MOVETOEX, (U_PAIR) 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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(U_EMR_LINETO, (U_PAIR) 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(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 (also 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(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(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(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(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(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(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(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(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(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(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(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(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,off;
+
+ if(!RgnData)return(NULL);
+ cbRgns = ((PU_RGNDATAHEADER) RgnData)->nRgnSize;
+ cbRgns4 = UP4(cbRgns);
+ irecsize = sizeof(U_EMRFILLRGN) + cbRgns4 - sizeof(U_RGNDATAHEADER); // core + array - overlap
+ record = malloc(irecsize);
+ if(record){
+ ((PU_EMR) record)->iType = U_EMR_FILLRGN;
+ ((PU_EMR) record)->nSize = irecsize;
+ ((PU_EMRFILLRGN) record)->rclBounds = rclBounds; // or ??? ((PU_RGNDATAHEADER) RgnData)->rclBounds;
+ ((PU_EMRFILLRGN) record)->cbRgnData = cbRgns;
+ ((PU_EMRFILLRGN) record)->ihBrush = ihBrush;
+ off = irecsize - cbRgns4;
+ memcpy(record + off, RgnData, cbRgns);
+ off += cbRgns;
+ if(cbRgns4 > cbRgns){ memset(record + off,0,cbRgns4-cbRgns); } // 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,off;
+
+ if(!RgnData)return(NULL);
+ cbRgns = ((PU_RGNDATAHEADER) RgnData)->nRgnSize;
+ cbRgns4 = UP4(cbRgns);
+ irecsize = sizeof(U_EMRFRAMERGN) + cbRgns4 - sizeof(U_RGNDATAHEADER); // core + array - overlap
+ record = malloc(irecsize);
+ if(record){
+ ((PU_EMR) record)->iType = U_EMR_FRAMERGN;
+ ((PU_EMR) record)->nSize = irecsize;
+ ((PU_EMRFRAMERGN) record)->rclBounds = rclBounds; // or ??? ((PU_RGNDATAHEADER) RgnData)->rclBounds;
+ ((PU_EMRFRAMERGN) record)->cbRgnData = cbRgns;
+ ((PU_EMRFRAMERGN) record)->ihBrush = ihBrush;
+ ((PU_EMRFRAMERGN) record)->szlStroke = szlStroke;
+ off = irecsize - cbRgns4;
+ memcpy(record + off, RgnData, cbRgns);
+ off += cbRgns;
+ if(cbRgns4 > cbRgns){ memset(record + off,0,cbRgns4-cbRgns); } // 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(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(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,off;
+
+ if(!RgnData)return(NULL);
+ cbRgns = ((PU_RGNDATAHEADER) RgnData)->nRgnSize;
+ cbRgns4 = UP4(cbRgns);
+ irecsize = sizeof(U_EMREXTSELECTCLIPRGN) + cbRgns4 - sizeof(U_RGNDATAHEADER); // core + array - overlap
+ record = malloc(irecsize);
+ if(record){
+ ((PU_EMR) record)->iType = U_EMR_EXTSELECTCLIPRGN;
+ ((PU_EMR) record)->nSize = irecsize;
+ ((PU_EMREXTSELECTCLIPRGN) record)->cbRgnData = cbRgns;
+ ((PU_EMREXTSELECTCLIPRGN) record)->iMode = iMode;
+ off = irecsize - cbRgns4;
+ memcpy(record + off, RgnData, cbRgns);
+ off += cbRgns;
+ if(cbRgns4 > cbRgns){ memset(record + off,0,cbRgns4-cbRgns); } // 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(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(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(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(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(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(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(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(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(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 (also 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)
+*/
+char *U_EMRCREATEMONOBRUSH_set(
+ const uint32_t ihBrush,
+ const uint32_t iUsage,
+ const PU_BITMAPINFO Bmi
+ ){
+ return(U_EMR_CORE12_set(U_EMR_CREATEMONOBRUSH,ihBrush,iUsage,Bmi));
+}
+
+// U_EMRCREATEDIBPATTERNBRUSHPT_set 94
+/**
+ \brief Allocate and construct a U_EMR_CREATEDIBPATTERNBRUSHPT record.
+ \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)
+*/
+char *U_EMRCREATEDIBPATTERNBRUSHPT_set(
+ const uint32_t ihBrush,
+ const uint32_t iUsage,
+ const PU_BITMAPINFO Bmi
+ ){
+ return(U_EMR_CORE12_set(U_EMR_CREATEDIBPATTERNBRUSHPT,ihBrush,iUsage,Bmi));
+}
+
+
+// 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);
+ off = sizeof(U_EMREXTCREATEPEN) + cbStyleArray - sizeof(U_STYLEENTRY);
+ // 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(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(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(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(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)
+*/
+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;
+ 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); }
+
+ irecsize = sizeof(U_EMRGRADIENTFILL) + cbTriVert + cbGradObj;
+ 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);
+ }
+ 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 -rNu3 src/extension/internal/uemf_endian.c src/extension/internal/uemf_endian.c
--- src/extension/internal/uemf_endian.c 1969-12-31 16:00:00.000000000 -0800
+++ src/extension/internal/uemf_endian.c 2012-08-07 12:44:46.000000000 -0700
@@ -0,0 +1,1745 @@
+/**
+ @file uemf_endian.c Functions for converting EMF records between Big Endian and Little Endian
+
+ 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.
+*/
+
+/*
+File: uemf_endian.h
+Version: 0.0.4
+Date: 25-JUL-2012
+Author: David Mathog, Biology Division, Caltech
+email: mathog@caltech.edu
+Copyright: 2012 David Mathog and California Institute of Technology (Caltech)
+*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include
+#include
+#include
+#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){
+ union i16 {
+ uint16_t i16;
+ uint8_t i8[2];
+ };
+ register union i16 ltmp;
+ register uint8_t ctmp;
+ for(; count; count--,ul+=2){
+ ltmp.i16 = *(uint16_t *)ul;
+ ctmp = ltmp.i8[0];
+ ltmp.i8[0] = ltmp.i8[1];
+ ltmp.i8[1] = ctmp;
+ *(uint16_t *)ul = ltmp.i16;
+ }
+}
+
+void U_swap4(void *ul, unsigned int count){
+ union i32 {
+ uint32_t i32;
+ uint8_t i8[4];
+ };
+ register union i32 ltmp;
+ register uint8_t ctmp;
+ for(;count;count--,ul+=4){
+ ltmp.i32 = *(uint32_t *)ul;
+ ctmp = ltmp.i8[0];
+ ltmp.i8[0] = ltmp.i8[3];
+ ltmp.i8[3] = ctmp;
+ ctmp = ltmp.i8[1];
+ ltmp.i8[1] = ltmp.i8[2];
+ ltmp.i8[2] = ctmp;
+ *(uint32_t *)ul = ltmp.i32;
+ }
+}
+
+/**
+ 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);
+ U_swap2(&(tv->Red),4);
+ }
+}
+
+/**
+ \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,4*count);
+}
+
+/**
+ \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(
+ PU_BITMAPINFO Bmi
+ ){
+ bitmapinfoheader_swap(&(Bmi->bmiHeader)); // bmIHeader
+ // ordered bytes: bmiColors
+}
+
+/**
+ \brief Convert a pointer to a U_EXTLOGPEN object.
+ \param elp PU_EXTLOGPEN object
+*/
+void extlogpen_swap(
+ PU_EXTLOGPEN elp,
+ int torev
+ ){
+ int count;
+ 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;
+ }
+ U_swap4(&(elp->elpStyleEntry),count); // elpStyleEntry[]
+}
+
+/**
+ \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
+}
+
+/**
+ \brief Convert a pointer to a U_RGNDATA object.
+ \param rgd pointer to a U_RGNDATA object.
+*/
+void rgndata_swap(
+ PU_RGNDATA rd
+ ){
+ int count = rd->rdh.nCount;
+ rgndataheader_swap(&(rd->rdh));
+ U_swap4(rd->Buffer,4*count);
+}
+
+/**
+ \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_ERMTEXT
+ \param torev 1 for native to reversed, 0 for reversed to native
+*/
+void emrtext_swap(
+ PU_EMRTEXT pemt,
+ char *record,
+ int torev
+ ){
+ int off;
+ uint32_t count;
+ uint32_t offDx;
+ uint32_t fOptions;
+ 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)){
+ 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
+ U_swap4(((char *)pemt+off),1); // offDx
+ if(!torev){
+ offDx = *(uint32_t *)((char *)pemt +off);
+ }
+ U_swap4((record+offDx),count); // Dx[], offset with respect to the Record, NOT the object
+}
+
+
+
+/* **********************************************************************************************
+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
+void core5_swap(char *record, int torev){
+ torev = torev; // shuts up compiler warnings about unused parameters
+ PU_ENHMETARECORD pEMR = (PU_ENHMETARECORD)(record);
+ U_swap4(pEMR,2); // iType nSize
+}
+
+// Functions with the same form starting with U_EMRPOLYBEZIER_swap
+void core1_swap(char *record, int torev){
+ int count;
+ PU_EMRPOLYLINETO pEmr = (PU_EMRPOLYLINETO) (record);
+ if(torev){
+ count = pEmr->cptl;
+ }
+ core5_swap(record, torev);
+ rectl_swap(&(pEmr->rclBounds),1 ); // rclBounds
+ U_swap4(&(pEmr->cptl),1); // cptl
+ if(!torev){
+ count = pEmr->cptl;
+ }
+ pointl_swap((pEmr->aptl),count); // aptl[]
+}
+
+// Functions with the same form starting with U_EMRPOLYPOLYLINE_swap
+void core2_swap(char *record, int torev){
+ int count, nPolys;
+ PU_EMRPOLYPOLYLINE pEmr = (PU_EMRPOLYPOLYLINE) (record);
+ if(torev){
+ count = pEmr->cptl;
+ nPolys = pEmr->nPolys;
+ }
+ core5_swap(record, torev);
+ rectl_swap(&(pEmr->rclBounds),1); // rclBounds
+ U_swap4(&(pEmr->nPolys),2); // nPolys cptl
+ if(!torev){
+ count = pEmr->cptl;
+ nPolys = pEmr->nPolys;
+ }
+ U_swap4(pEmr->aPolyCounts,nPolys); // aPolyCounts[]
+ pointl_swap((PU_POINT)(record + sizeof(U_EMRPOLYPOLYLINE) - 4 + sizeof(uint32_t)* nPolys), count); // paptl[]
+}
+
+
+// Functions with the same form starting with U_EMRSETMAPMODE_swap
+void core3_swap(char *record, int torev){
+ PU_EMRSETMAPMODE pEmr = (PU_EMRSETMAPMODE)(record);
+ core5_swap(record, torev);
+ U_swap4(&(pEmr->iMode),1); // iMode
+}
+
+// Functions taking a single U_RECT or U_RECTL, starting with U_EMRELLIPSE_swap, also U_EMRFILLPATH_swap,
+void core4_swap(char *record, int torev){
+ PU_EMRELLIPSE pEmr = (PU_EMRELLIPSE)( record);
+ core5_swap(record, torev);
+ rectl_swap(&(pEmr->rclBox),1); // rclBox
+}
+
+// Functions with the same form starting with U_EMRPOLYBEZIER16_swap
+void core6_swap(char *record, int torev){
+ int count;
+ PU_EMRPOLYBEZIER16 pEmr = (PU_EMRPOLYBEZIER16) (record);
+ if(torev){
+ count = pEmr->cpts;
+ }
+ core5_swap(record, torev);
+ rectl_swap(&(pEmr->rclBounds),1); // rclBounds
+ U_swap4(&(pEmr->cpts),1); // cpts
+ if(!torev){
+ count = pEmr->cpts;
+ }
+ point16_swap((pEmr->apts),count); // apts[]
+}
+
+
+// Records with the same form starting with U_EMRSETWINDOWEXTEX_swap, that is, all with two uint32_t values after the emr
+void core7_swap(char *record, int torev){
+ PU_EMRGENERICPAIR pEmr = (PU_EMRGENERICPAIR) (record);
+ core5_swap(record, torev);
+ U_swap4(&(pEmr->pair),2);
+}
+
+// For U_EMREXTTEXTOUTA and U_EMREXTTEXTOUTW, type=0 for the first one
+void core8_swap(char *record, int torev){
+ PU_EMREXTTEXTOUTA pEmr = (PU_EMREXTTEXTOUTA) (record);
+ emrtext_swap(&(pEmr->emrtext),record,torev);
+ core5_swap(record, torev);
+ U_swap4(&(pEmr->iGraphicsMode),1); // iGraphicsMode
+ rectl_swap(&(pEmr->rclBounds),1); // rclBounds
+ U_swap4(&(pEmr->exScale),2); // exScale eyScale
+}
+
+// Functions that take a rect and a pair of points, starting with U_EMRARC_swap
+void core9_swap(char *record, int torev){
+ PU_EMRARC pEmr = (PU_EMRARC) (record);
+ core5_swap(record, torev);
+ rectl_swap(&(pEmr->rclBox),1); // rclBox
+ U_swap4(&(pEmr->ptlStart),4); // ptlStart ptlEnd
+}
+
+// Functions with the same form starting with U_EMRPOLYPOLYLINE16_swap
+void core10_swap(char *record, int torev){
+ int count, nPolys;
+ PU_EMRPOLYPOLYLINE16 pEmr = (PU_EMRPOLYPOLYLINE16) (record);
+ if(torev){
+ count = pEmr->cpts;
+ nPolys = pEmr->nPolys;
+ }
+ core5_swap(record, torev);
+ rectl_swap(&(pEmr->rclBounds),1); // rclBounds
+ U_swap4(&(pEmr->nPolys),2); // nPolys cpts
+ if(!torev){
+ count = pEmr->cpts;
+ nPolys = pEmr->nPolys;
+ }
+ U_swap4(pEmr->aPolyCounts,nPolys); // aPolyCounts[]
+ point16_swap((PU_POINT16)(record + sizeof(U_EMRPOLYPOLYLINE16) - 4 + sizeof(uint32_t)* nPolys), count); // apts[]
+}
+
+// Functions with the same form starting with U_EMRINVERTRGN_swap and U_EMRPAINTRGN_swap,
+void core11_swap(char *record, int torev){
+ int roff,nextroff, limit;
+ PU_EMRINVERTRGN pEmr = (PU_EMRINVERTRGN) (record);
+ roff = 0;
+ if(torev){
+ limit = pEmr->emr.nSize;
+ nextroff = 0;
+ }
+ core5_swap(record, torev);
+ if(!torev){
+ limit = pEmr->emr.nSize;
+ }
+ rectl_swap(&(pEmr->rclBounds),1); // rclBounds
+ U_swap4(&(pEmr->cbRgnData),1); // cbRgnData
+ if(!torev){
+ limit = pEmr->emr.nSize;
+ }
+ // This one is a pain since each RGNDATA may be a different size, so it isn't possible to index through them.
+ char *prd = (char *) &(pEmr->RgnData);
+ while(roff + 28 < limit){ // up to the end of the record
+ if(torev){
+ nextroff += (((PU_RGNDATA)prd)->rdh.dwSize + ((PU_RGNDATA)prd)->rdh.nRgnSize - 16);
+ rgndata_swap((PU_RGNDATA) (prd + roff));
+ roff = nextroff;
+ }
+ else {
+ rgndata_swap((PU_RGNDATA) (prd + roff));
+ roff += (((PU_RGNDATA)prd)->rdh.dwSize + ((PU_RGNDATA)prd)->rdh.nRgnSize - 16);
+ }
+ }
+}
+
+
+// common code for U_EMRCREATEMONOBRUSH_swap and U_EMRCREATEDIBPATTERNBRUSHPT_swap,
+void core12_swap(char *record, int torev){
+ PU_EMRCREATEMONOBRUSH pEmr = (PU_EMRCREATEMONOBRUSH) (record);
+ if(torev && pEmr->cbBmi){
+ bitmapinfo_swap((PU_BITMAPINFO)(record + pEmr->offBmi)); // Bmi
+ }
+ core5_swap(record, torev);
+ U_swap4(&(pEmr->ihBrush),6); // ihBrush iUsage offBmi cbBmi offBits cbBits
+ // ordered bytes: bitmap (including 16 bit 5bit/channel color mode, which is done bytewise).
+ if(!torev && pEmr->cbBmi){
+ bitmapinfo_swap((PU_BITMAPINFO)(record + pEmr->offBmi)); // Bmi
+ }
+}
+
+// common code for U_EMRALPHABLEND_swap and U_EMRTRANSPARENTBLT_swap,
+void core13_swap(char *record, int torev){
+ PU_EMRALPHABLEND pEmr = (PU_EMRALPHABLEND) (record);
+ if(torev && pEmr->cbBmiSrc){
+ bitmapinfo_swap((PU_BITMAPINFO)(record + pEmr->offBmiSrc));
+ }
+ core5_swap(record, torev);
+ 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
+ // ordered bytes: bitmap (including 16 bit 5bit/channel color mode, which is done bytewise).
+ if(!torev && pEmr->cbBmiSrc){
+ bitmapinfo_swap((PU_BITMAPINFO)(record + pEmr->offBmiSrc));
+ }
+}
+
+/* **********************************************************************************************
+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.
+*********************************************************************************************** */
+
+/**
+ 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
+*/
+void U_EMRNOTIMPLEMENTED_swap(char *record, int torev){
+ core5_swap(record, torev);
+ printf("WARNING: could not convert data in record type that has not been implemented!\n");
+}
+
+// U_EMRHEADER 1
+void U_EMRHEADER_swap(char *record, int torev){
+ core5_swap(record, torev);
+
+ PU_EMRHEADER pEmr = (PU_EMRHEADER)(record);
+ 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
+ // UTF16-LE Description
+ sizel_swap(&(pEmr->szlDevice), 2); // szlDevice szlMillimeters
+ if(torev && pEmr->cbPixelFormat){
+ pixelformatdescriptor_swap( (PU_PIXELFORMATDESCRIPTOR) (record + pEmr->offPixelFormat));
+ }
+ U_swap4(&(pEmr->cbPixelFormat), 2); // cbPixelFormat offPixelFormat
+ if(!torev && pEmr->cbPixelFormat){
+ pixelformatdescriptor_swap( (PU_PIXELFORMATDESCRIPTOR) (record + pEmr->offPixelFormat));
+ }
+ U_swap4(&(pEmr->bOpenGL), 1); // bOpenGL
+ sizel_swap(&(pEmr->szlMicrometers), 1); // szlMicrometers
+}
+
+// U_EMRPOLYBEZIER 2
+void U_EMRPOLYBEZIER_swap(char *record, int torev){
+ core1_swap(record, torev);
+}
+
+// U_EMRPOLYGON 3
+void U_EMRPOLYGON_swap(char *record, int torev){
+ core1_swap(record, torev);
+}
+
+
+// U_EMRPOLYLINE 4
+void U_EMRPOLYLINE_swap(char *record, int torev){
+ core1_swap(record, torev);
+}
+
+// U_EMRPOLYBEZIERTO 5
+void U_EMRPOLYBEZIERTO_swap(char *record, int torev){
+ core1_swap(record, torev);
+}
+
+// U_EMRPOLYLINETO 6
+void U_EMRPOLYLINETO_swap(char *record, int torev){
+ core1_swap(record, torev);
+}
+
+// U_EMRPOLYPOLYLINE 7
+void U_EMRPOLYPOLYLINE_swap(char *record, int torev){
+ core2_swap(record, torev);
+}
+
+// U_EMRPOLYPOLYGON 8
+void U_EMRPOLYPOLYGON_swap(char *record, int torev){
+ core2_swap(record, torev);
+}
+
+// U_EMRSETWINDOWEXTEX 9
+void U_EMRSETWINDOWEXTEX_swap(char *record, int torev){
+ core7_swap(record, torev);
+}
+
+// U_EMRSETWINDOWORGEX 10
+void U_EMRSETWINDOWORGEX_swap(char *record, int torev){
+ core7_swap(record, torev);
+}
+
+// U_EMRSETVIEWPORTEXTEX 11
+void U_EMRSETVIEWPORTEXTEX_swap(char *record, int torev){
+ core7_swap(record, torev);
+}
+
+// U_EMRSETVIEWPORTORGEX 12
+void U_EMRSETVIEWPORTORGEX_swap(char *record, int torev){
+ core7_swap(record, torev);
+}
+
+// U_EMRSETBRUSHORGEX 13
+void U_EMRSETBRUSHORGEX_swap(char *record, int torev){
+ core7_swap(record, torev);
+}
+
+// U_EMREOF 14
+void U_EMREOF_swap(char *record, int torev){
+ int off,cbPalEntries;
+ core5_swap(record, torev);
+ PU_EMREOF pEmr = (PU_EMREOF)(record);
+ if(torev){
+ cbPalEntries = pEmr->cbPalEntries;
+ if(cbPalEntries){
+ logpalette_swap( (PU_LOGPALETTE)(record + pEmr->offPalEntries));
+ }
+ }
+ U_swap4(&(pEmr->cbPalEntries),2); // cbPalEntries offPalEntries
+ if(!torev){
+ cbPalEntries = pEmr->cbPalEntries;
+ if(cbPalEntries){
+ logpalette_swap( (PU_LOGPALETTE)(record + pEmr->offPalEntries));
+ }
+ }
+ off = sizeof(U_EMREOF) + 4 * cbPalEntries;
+ U_swap4(record + off,1); // nSizeLast
+}
+
+
+// U_EMRSETPIXELV 15
+void U_EMRSETPIXELV_swap(char *record, int torev){
+ core5_swap(record, torev);
+ PU_EMRSETPIXELV pEmr = (PU_EMRSETPIXELV)(record);
+ pointl_swap(&(pEmr->ptlPixel),1); // ptlPixel
+ // ordered bytes: crColor
+}
+
+
+// U_EMRSETMAPPERFLAGS 16
+void U_EMRSETMAPPERFLAGS_swap(char *record, int torev){
+ core5_swap(record, torev);
+ PU_EMRSETMAPPERFLAGS pEmr = (PU_EMRSETMAPPERFLAGS)(record);
+ U_swap4(&(pEmr->dwFlags),1); // dwFlags
+}
+
+
+// U_EMRSETMAPMODE 17
+void U_EMRSETMAPMODE_swap(char *record, int torev){
+ core3_swap(record, torev);
+}
+
+// U_EMRSETBKMODE 18
+void U_EMRSETBKMODE_swap(char *record, int torev){
+ core3_swap(record, torev);
+}
+
+// U_EMRSETPOLYFILLMODE 19
+void U_EMRSETPOLYFILLMODE_swap(char *record, int torev){
+ core3_swap(record, torev);
+}
+
+// U_EMRSETROP2 20
+void U_EMRSETROP2_swap(char *record, int torev){
+ core3_swap(record, torev);
+}
+
+// U_EMRSETSTRETCHBLTMODE 21
+void U_EMRSETSTRETCHBLTMODE_swap(char *record, int torev){
+ core3_swap(record, torev);
+}
+
+// U_EMRSETTEXTALIGN 22
+void U_EMRSETTEXTALIGN_swap(char *record, int torev){
+ core3_swap(record, torev);
+}
+
+// U_EMRSETCOLORADJUSTMENT 23
+void U_EMRSETCOLORADJUSTMENT_swap(char *record, int torev){
+ core5_swap(record, torev);
+ PU_EMRSETCOLORADJUSTMENT pEmr = (PU_EMRSETCOLORADJUSTMENT)(record);
+ coloradjustment_swap(&(pEmr->ColorAdjustment));
+}
+
+// U_EMRSETTEXTCOLOR 24
+void U_EMRSETTEXTCOLOR_swap(char *record, int torev){
+ core5_swap(record, torev);
+ // ordered bytes: crColor
+}
+
+// U_EMRSETBKCOLOR 25
+void U_EMRSETBKCOLOR_swap(char *record, int torev){
+ core5_swap(record, torev);
+ // ordered bytes: crColor
+}
+
+// U_EMROFFSETCLIPRGN 26
+void U_EMROFFSETCLIPRGN_swap(char *record, int torev){
+ core7_swap(record, torev);
+}
+
+// U_EMRMOVETOEX 27
+void U_EMRMOVETOEX_swap(char *record, int torev){
+ core7_swap(record, torev);
+}
+
+// U_EMRSETMETARGN 28
+void U_EMRSETMETARGN_swap(char *record, int torev){
+ core5_swap(record, torev);
+}
+
+// U_EMREXCLUDECLIPRECT 29
+void U_EMREXCLUDECLIPRECT_swap(char *record, int torev){
+ core4_swap(record, torev);
+}
+
+// U_EMRINTERSECTCLIPRECT 30
+void U_EMRINTERSECTCLIPRECT_swap(char *record, int torev){
+ core4_swap(record, torev);
+}
+
+// U_EMRSCALEVIEWPORTEXTEX 31
+void U_EMRSCALEVIEWPORTEXTEX_swap(char *record, int torev){
+ core4_swap(record, torev);
+}
+
+
+// U_EMRSCALEWINDOWEXTEX 32
+void U_EMRSCALEWINDOWEXTEX_swap(char *record, int torev){
+ core4_swap(record, torev);
+}
+
+// U_EMRSAVEDC 33
+void U_EMRSAVEDC_swap(char *record, int torev){
+ core5_swap(record, torev);
+}
+
+// U_EMRRESTOREDC 34
+void U_EMRRESTOREDC_swap(char *record, int torev){
+ core3_swap(record, torev);
+}
+
+// U_EMRSETWORLDTRANSFORM 35
+void U_EMRSETWORLDTRANSFORM_swap(char *record, int torev){
+ core5_swap(record, torev);
+ PU_EMRSETWORLDTRANSFORM pEmr = (PU_EMRSETWORLDTRANSFORM)(record);
+ xform_swap(&(pEmr->xform));
+}
+
+// U_EMRMODIFYWORLDTRANSFORM 36
+void U_EMRMODIFYWORLDTRANSFORM_swap(char *record, int torev){
+ core5_swap(record, torev);
+ PU_EMRMODIFYWORLDTRANSFORM pEmr = (PU_EMRMODIFYWORLDTRANSFORM)(record);
+ xform_swap(&(pEmr->xform)); // xform
+ U_swap4(&(pEmr->iMode),1); // iMode
+}
+
+// U_EMRSELECTOBJECT 37
+void U_EMRSELECTOBJECT_swap(char *record, int torev){
+ core5_swap(record, torev);
+ PU_EMRSELECTOBJECT pEmr = (PU_EMRSELECTOBJECT)(record);
+ U_swap4(&(pEmr->ihObject),1); // ihObject
+}
+
+// U_EMRCREATEPEN 38
+void U_EMRCREATEPEN_swap(char *record, int torev){
+ core5_swap(record, torev);
+ PU_EMRCREATEPEN pEmr = (PU_EMRCREATEPEN)(record);
+ U_swap4(&(pEmr->ihPen),1); // ihPen
+ logpen_swap(&(pEmr->lopn)); // lopn
+}
+
+// U_EMRCREATEBRUSHINDIRECT 39
+void U_EMRCREATEBRUSHINDIRECT_swap(char *record, int torev){
+ core5_swap(record, torev);
+ PU_EMRCREATEBRUSHINDIRECT pEmr = (PU_EMRCREATEBRUSHINDIRECT)(record);
+ U_swap4(&(pEmr->ihBrush),1); // ihBrush
+ logbrush_swap(&(pEmr->lb)); // lb
+}
+
+// U_EMRDELETEOBJECT 40
+void U_EMRDELETEOBJECT_swap(char *record, int torev){
+ core5_swap(record, torev);
+ PU_EMRDELETEOBJECT pEmr = (PU_EMRDELETEOBJECT)(record);
+ U_swap4(&(pEmr->ihObject),1); // ihObject
+}
+
+// U_EMRANGLEARC 41
+void U_EMRANGLEARC_swap(char *record, int torev){
+ core5_swap(record, torev);
+ PU_EMRANGLEARC pEmr = (PU_EMRANGLEARC)(record);
+ pointl_swap(&(pEmr->ptlCenter),1); // ptlCenter
+ U_swap4(&(pEmr->nRadius),3); // nRadius eStartAngle eSweepAngle
+}
+
+// U_EMRELLIPSE 42
+void U_EMRELLIPSE_swap(char *record, int torev){
+ core4_swap(record, torev);
+}
+
+// U_EMRRECTANGLE 43
+void U_EMRRECTANGLE_swap(char *record, int torev){
+ core4_swap(record, torev);
+}
+
+// U_EMRROUNDRECT 44
+void U_EMRROUNDRECT_swap(char *record, int torev){
+ core5_swap(record, torev);
+ PU_EMRROUNDRECT pEmr = (PU_EMRROUNDRECT)(record);
+ rectl_swap(&(pEmr->rclBox),1); // rclBox
+ sizel_swap(&(pEmr->szlCorner), 1); // szlCorner
+}
+
+// U_EMRARC 45
+void U_EMRARC_swap(char *record, int torev){
+ core9_swap(record, torev);
+}
+
+// U_EMRCHORD 46
+void U_EMRCHORD_swap(char *record, int torev){
+ core9_swap(record, torev);
+}
+
+// U_EMRPIE 47
+void U_EMRPIE_swap(char *record, int torev){
+ core9_swap(record, torev);
+}
+
+// U_EMRSELECTPALETTE 48
+void U_EMRSELECTPALETTE_swap(char *record, int torev){
+ core3_swap(record, torev);
+}
+
+// U_EMRCREATEPALETTE 49
+void U_EMRCREATEPALETTE_swap(char *record, int torev){
+ core5_swap(record, torev);
+ PU_EMRCREATEPALETTE pEmr = (PU_EMRCREATEPALETTE)(record);
+ U_swap4(&(pEmr->ihPal),1); // ihPal
+ logpalette_swap( (PU_LOGPALETTE)&(pEmr->lgpl) ); // lgpl
+}
+
+// U_EMRSETPALETTEENTRIES 50
+void U_EMRSETPALETTEENTRIES_swap(char *record, int torev){
+ core5_swap(record, torev);
+ PU_EMRSETPALETTEENTRIES pEmr = (PU_EMRSETPALETTEENTRIES)(record);
+ U_swap4(&(pEmr->ihPal),3); // ihPal iStart cEntries
+ // ordered bytes: aPalEntries[]
+}
+
+// U_EMRRESIZEPALETTE 51
+void U_EMRRESIZEPALETTE_swap(char *record, int torev){
+ core7_swap(record, torev);
+}
+
+// U_EMRREALIZEPALETTE 52
+void U_EMRREALIZEPALETTE_swap(char *record, int torev){
+ core5_swap(record, torev);
+}
+
+// U_EMREXTFLOODFILL 53
+void U_EMREXTFLOODFILL_swap(char *record, int torev){
+ core5_swap(record, torev);
+ PU_EMREXTFLOODFILL pEmr = (PU_EMREXTFLOODFILL)(record);
+ pointl_swap(&(pEmr->ptlStart),1); // ptlStart
+ // ordered bytes: crColor
+ U_swap4(&(pEmr->iMode),1); // iMode
+}
+
+// U_EMRLINETO 54
+void U_EMRLINETO_swap(char *record, int torev){
+ core7_swap(record, torev);
+}
+
+// U_EMRARCTO 55
+void U_EMRARCTO_swap(char *record, int torev){
+ core9_swap(record, torev);
+}
+
+// U_EMRPOLYDRAW 56
+void U_EMRPOLYDRAW_swap(char *record, int torev){
+ int count;
+ core5_swap(record, torev);
+ PU_EMRPOLYDRAW pEmr = (PU_EMRPOLYDRAW)(record);
+
+ if(torev){
+ count = pEmr->cptl;
+ }
+ rectl_swap(&(pEmr->rclBounds),1); // rclBounds
+ U_swap4(&(pEmr->cptl),1); // cptl
+ if(!torev){
+ count = pEmr->cptl;
+ }
+ pointl_swap(pEmr->aptl,count); // aptl[]
+ U_swap4(pEmr->abTypes,count); // abTypes[]
+}
+
+// U_EMRSETARCDIRECTION 57
+void U_EMRSETARCDIRECTION_swap(char *record, int torev){
+ core3_swap(record, torev);
+}
+
+// U_EMRSETMITERLIMIT 58
+void U_EMRSETMITERLIMIT_swap(char *record, int torev){
+ core3_swap(record, torev);
+}
+
+
+// U_EMRBEGINPATH 59
+void U_EMRBEGINPATH_swap(char *record, int torev){
+ core5_swap(record, torev);
+}
+
+// U_EMRENDPATH 60
+void U_EMRENDPATH_swap(char *record, int torev){
+ core5_swap(record, torev);
+}
+
+// U_EMRCLOSEFIGURE 61
+void U_EMRCLOSEFIGURE_swap(char *record, int torev){
+ core5_swap(record, torev);
+}
+
+// U_EMRFILLPATH 62
+void U_EMRFILLPATH_swap(char *record, int torev){
+ core4_swap(record, torev);
+}
+
+// U_EMRSTROKEANDFILLPATH 63
+void U_EMRSTROKEANDFILLPATH_swap(char *record, int torev){
+ core4_swap(record, torev);
+}
+
+// U_EMRSTROKEPATH 64
+void U_EMRSTROKEPATH_swap(char *record, int torev){
+ core4_swap(record, torev);
+}
+
+// U_EMRFLATTENPATH 65
+void U_EMRFLATTENPATH_swap(char *record, int torev){
+ core5_swap(record, torev);
+}
+
+// U_EMRWIDENPATH 66
+void U_EMRWIDENPATH_swap(char *record, int torev){
+ core5_swap(record, torev);
+}
+
+// U_EMRSELECTCLIPPATH 67
+void U_EMRSELECTCLIPPATH_swap(char *record, int torev){
+ core3_swap(record, torev);
+}
+
+// U_EMRABORTPATH 68
+void U_EMRABORTPATH_swap(char *record, int torev){
+ core5_swap(record, torev);
+}
+
+// U_EMRUNDEF69 69
+#define U_EMRUNDEF69_swap U_EMRNOTIMPLEMENTED_swap
+
+// U_EMRCOMMENT 70 Comment (any binary data, interpretation is program specific)
+void U_EMRCOMMENT_swap(char *record, int torev){
+ core5_swap(record, torev);
+ PU_EMRCOMMENT pEmr = (PU_EMRCOMMENT)(record);
+ U_swap4(&(pEmr->cbData),1); // cbData
+ // program specific data, presumably byte ordered, otherwise, not portable
+}
+
+// U_EMRFILLRGN 71
+void U_EMRFILLRGN_swap(char *record, int torev){
+ int roff, nextroff, limit;
+ roff=0;
+ PU_EMRFILLRGN pEmr = (PU_EMRFILLRGN)(record);
+ if(torev){
+ limit = pEmr->emr.nSize;
+ nextroff = 0;
+ }
+ core5_swap(record, torev);
+ if(!torev){
+ limit = pEmr->emr.nSize;
+ }
+ rectl_swap(&(pEmr->rclBounds),1); // rclBounds
+ U_swap4(&(pEmr->cbRgnData),2); // cbRgnData ihBrush
+ // This one is a pain since each RGNDATA may be a different size, so it isn't possible to index through them.
+ char *prd = (char *) &(pEmr->RgnData);
+ while(roff + 28 < limit){ // up to the end of the record
+ if(torev){
+ nextroff += (((PU_RGNDATA)prd)->rdh.dwSize + ((PU_RGNDATA)prd)->rdh.nRgnSize - 16);
+ rgndata_swap((PU_RGNDATA) (prd + roff));
+ roff = nextroff;
+ }
+ else {
+ rgndata_swap((PU_RGNDATA) (prd + roff));
+ roff += (((PU_RGNDATA)prd)->rdh.dwSize + ((PU_RGNDATA)prd)->rdh.nRgnSize - 16);
+ }
+ }
+}
+
+// U_EMRFRAMERGN 72
+void U_EMRFRAMERGN_swap(char *record, int torev){
+ int roff, nextroff, limit;
+ PU_EMRFRAMERGN pEmr = (PU_EMRFRAMERGN)(record);
+ roff = 0;
+ if(torev){
+ limit = pEmr->emr.nSize;
+ nextroff = 0;
+ }
+ core5_swap(record, torev);
+ if(!torev){
+ limit = pEmr->emr.nSize;
+ }
+ rectl_swap(&(pEmr->rclBounds),1); // rclBounds
+ U_swap4(&(pEmr->cbRgnData),2); // cbRgnData ihBrush
+ sizel_swap(&(pEmr->szlStroke), 2); // szlStroke
+ // This one is a pain since each RGNDATA may be a different size, so it isn't possible to index through them.
+ char *prd = (char *) &(pEmr->RgnData);
+ while(roff + 28 < limit){ // up to the end of the record
+ if(torev){
+ nextroff += (((PU_RGNDATA)prd)->rdh.dwSize + ((PU_RGNDATA)prd)->rdh.nRgnSize - 16);
+ rgndata_swap((PU_RGNDATA) (prd + roff));
+ roff = nextroff;
+ }
+ else {
+ rgndata_swap((PU_RGNDATA) (prd + roff));
+ roff += (((PU_RGNDATA)prd)->rdh.dwSize + ((PU_RGNDATA)prd)->rdh.nRgnSize - 16);
+ }
+ }
+}
+
+// U_EMRINVERTRGN 73
+void U_EMRINVERTRGN_swap(char *record, int torev){
+ core11_swap(record, torev);
+}
+
+// U_EMRPAINTRGN 74
+void U_EMRPAINTRGN_swap(char *record, int torev){
+ core11_swap(record, torev);
+}
+
+// U_EMREXTSELECTCLIPRGN 75
+void U_EMREXTSELECTCLIPRGN_swap(char *record, int torev){
+ int roff, nextroff, limit;
+ PU_EMREXTSELECTCLIPRGN pEmr = (PU_EMREXTSELECTCLIPRGN) (record);
+ roff = 0;
+ if(torev){
+ limit = pEmr->emr.nSize;
+ nextroff = 0;
+ }
+ core5_swap(record, torev);
+ if(!torev){
+ limit = pEmr->emr.nSize;
+ }
+ U_swap4(&(pEmr->cbRgnData),2); // cbRgnData iMode
+ // This one is a pain since each RGNDATA may be a different size, so it isn't possible to index through them.
+ char *prd = (char *) &(pEmr->RgnData);
+ nextroff = roff = 0;
+ while(roff + 16 < limit){ // up to the end of the record
+ if(torev){
+ nextroff += (((PU_RGNDATA)prd)->rdh.dwSize + ((PU_RGNDATA)prd)->rdh.nRgnSize - 16);
+ rgndata_swap((PU_RGNDATA) (prd + roff));
+ roff = nextroff;
+ }
+ else {
+ rgndata_swap((PU_RGNDATA) (prd + roff));
+ roff += (((PU_RGNDATA)prd)->rdh.dwSize + ((PU_RGNDATA)prd)->rdh.nRgnSize - 16);
+ }
+ }
+}
+
+// U_EMRBITBLT 76
+void U_EMRBITBLT_swap(char *record, int torev){
+ core5_swap(record, torev);
+ PU_EMRBITBLT pEmr = (PU_EMRBITBLT) (record);
+ if(torev && pEmr->cbBmiSrc){
+ bitmapinfo_swap((PU_BITMAPINFO)(record + pEmr->offBmiSrc));
+ }
+ 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
+ // ordered bytes: bitmap (including 16 bit 5bit/channel color mode, which is done bytewise).
+ if(!torev && pEmr->cbBmiSrc){
+ bitmapinfo_swap((PU_BITMAPINFO)(record + pEmr->offBmiSrc));
+ }
+}
+
+// U_EMRSTRETCHBLT 77
+void U_EMRSTRETCHBLT_swap(char *record, int torev){
+ PU_EMRSTRETCHBLT pEmr = (PU_EMRSTRETCHBLT) (record);
+ core5_swap(record, torev);
+ 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
+ if(torev && pEmr->cbBmiSrc){
+ bitmapinfo_swap((PU_BITMAPINFO)(record + pEmr->offBmiSrc));
+ }
+ U_swap4(&(pEmr->iUsageSrc),5); // iUsageSrc offBmiSrc cbBmiSrc offBitsSrc cbBitsSrc
+ pointl_swap(&(pEmr->cSrc),1); // cSrc
+ if(!torev && pEmr->cbBmiSrc){
+ bitmapinfo_swap((PU_BITMAPINFO)(record + pEmr->offBmiSrc));
+ }
+}
+
+// U_EMRMASKBLT 78
+void U_EMRMASKBLT_swap(char *record, int torev){
+ PU_EMRMASKBLT pEmr = (PU_EMRMASKBLT) (record);
+ core5_swap(record, torev);
+ if(torev && pEmr->cbBmiSrc){
+ bitmapinfo_swap((PU_BITMAPINFO)(record + pEmr->offBmiSrc));
+ }
+ if(torev && pEmr->cbBmiMask){
+ bitmapinfo_swap((PU_BITMAPINFO)(record + pEmr->offBmiMask));
+ }
+ 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 && pEmr->cbBmiSrc){
+ bitmapinfo_swap((PU_BITMAPINFO)(record + pEmr->offBmiSrc));
+ }
+ if(!torev && pEmr->cbBmiMask){
+ bitmapinfo_swap((PU_BITMAPINFO)(record + pEmr->offBmiMask));
+ }
+}
+
+// U_EMRPLGBLT 79
+void U_EMRPLGBLT_swap(char *record, int torev){
+ PU_EMRPLGBLT pEmr = (PU_EMRPLGBLT) (record);
+ core5_swap(record, torev);
+ if(torev && pEmr->cbBmiSrc){
+ bitmapinfo_swap((PU_BITMAPINFO)(record + pEmr->offBmiSrc));
+ }
+ if(torev && pEmr->cbBmiMask){
+ bitmapinfo_swap((PU_BITMAPINFO)(record + pEmr->offBmiMask));
+ }
+ 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 && pEmr->cbBmiSrc){
+ bitmapinfo_swap((PU_BITMAPINFO)(record + pEmr->offBmiSrc));
+ }
+ if(!torev && pEmr->cbBmiMask){
+ bitmapinfo_swap((PU_BITMAPINFO)(record + pEmr->offBmiMask));
+ }
+}
+
+// U_EMRSETDIBITSTODEVICE 80
+void U_EMRSETDIBITSTODEVICE_swap(char *record, int torev){
+ PU_EMRSETDIBITSTODEVICE pEmr = (PU_EMRSETDIBITSTODEVICE) (record);
+ core5_swap(record, torev);
+ if(torev && pEmr->cbBmiSrc){
+ bitmapinfo_swap((PU_BITMAPINFO)(record + pEmr->offBmiSrc));
+ }
+ 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 && pEmr->cbBmiSrc){
+ bitmapinfo_swap((PU_BITMAPINFO)(record + pEmr->offBmiSrc));
+ }
+}
+
+// U_EMRSTRETCHDIBITS 81
+void U_EMRSTRETCHDIBITS_swap(char *record, int torev){
+ PU_EMRSTRETCHDIBITS pEmr = (PU_EMRSTRETCHDIBITS) (record);
+ core5_swap(record, torev);
+ if(torev && pEmr->cbBmiSrc){
+ bitmapinfo_swap((PU_BITMAPINFO)(record + pEmr->offBmiSrc));
+ }
+ 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 && pEmr->cbBmiSrc){
+ bitmapinfo_swap((PU_BITMAPINFO)(record + pEmr->offBmiSrc));
+ }
+}
+
+// U_EMREXTCREATEFONTINDIRECTW_swap 82
+void U_EMREXTCREATEFONTINDIRECTW_swap(char *record, int torev){
+ PU_EMREXTCREATEFONTINDIRECTW pEmr = (PU_EMREXTCREATEFONTINDIRECTW) (record);
+ if(torev){
+ if(pEmr->emr.nSize == sizeof(U_EMREXTCREATEFONTINDIRECTW)){
+ logfont_panose_swap(&(pEmr->elfw));
+ }
+ else {
+ logfont_swap( (PU_LOGFONT) &(pEmr->elfw));
+ }
+ }
+ core5_swap(record, torev);
+ if(!torev){
+ if(pEmr->emr.nSize == sizeof(U_EMREXTCREATEFONTINDIRECTW)){
+ logfont_panose_swap(&(pEmr->elfw));
+ }
+ else {
+ logfont_swap( (PU_LOGFONT) &(pEmr->elfw));
+ }
+ }
+ U_swap4(&(pEmr->ihFont),1); // ihFont
+}
+
+// U_EMREXTTEXTOUTA 83
+void U_EMREXTTEXTOUTA_swap(char *record, int torev){
+ core8_swap(record, torev);
+}
+
+// U_EMREXTTEXTOUTW 84
+void U_EMREXTTEXTOUTW_swap(char *record, int torev){
+ 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
+*/
+void U_EMRPOLYBEZIER16_swap(char *record, int torev){
+ core6_swap(record, torev);
+}
+
+// U_EMRPOLYGON16 86
+void U_EMRPOLYGON16_swap(char *record, int torev){
+ core6_swap(record, torev);
+}
+
+// U_EMRPOLYLINE16 87
+void U_EMRPOLYLINE16_swap(char *record, int torev){
+ core6_swap(record, torev);
+}
+
+// U_EMRPOLYBEZIERTO16 88
+void U_EMRPOLYBEZIERTO16_swap(char *record, int torev){
+ 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
+*/
+void U_EMRPOLYLINETO16_swap(char *record, int torev){
+ core6_swap(record, torev);
+}
+
+// U_EMRPOLYPOLYLINE16 90
+void U_EMRPOLYPOLYLINE16_swap(char *record, int torev){
+ core10_swap(record, torev);
+}
+
+// U_EMRPOLYPOLYGON16 91
+void U_EMRPOLYPOLYGON16_swap(char *record, int torev){
+ core10_swap(record, torev);
+}
+
+
+// U_EMRPOLYDRAW16 92
+void U_EMRPOLYDRAW16_swap(char *record, int torev){
+ int count;
+ core5_swap(record, torev);
+ PU_EMRPOLYDRAW16 pEmr = (PU_EMRPOLYDRAW16)(record);
+ if(torev){
+ count = pEmr->cpts;
+ }
+ rectl_swap(&(pEmr->rclBounds),1); // rclBounds
+ U_swap4(&(pEmr->cpts),1); // cpts
+ if(!torev){
+ count = pEmr->cpts;
+ }
+ point16_swap(pEmr->apts,count); // apts[]
+ U_swap4(pEmr->abTypes,count); // abTypes[]
+}
+
+// U_EMRCREATEMONOBRUSH 93
+void U_EMRCREATEMONOBRUSH_swap(char *record, int torev){
+ core12_swap(record, torev);
+}
+
+// U_EMRCREATEDIBPATTERNBRUSHPT_swap 94
+void U_EMRCREATEDIBPATTERNBRUSHPT_swap(char *record, int torev){
+ core12_swap(record, torev);
+}
+
+
+// U_EMREXTCREATEPEN 95
+void U_EMREXTCREATEPEN_swap(char *record, int torev){
+ core5_swap(record, torev);
+ PU_EMREXTCREATEPEN pEmr = (PU_EMREXTCREATEPEN)(record);
+ if(torev && pEmr->cbBmi){
+ bitmapinfo_swap((PU_BITMAPINFO)(record + pEmr->offBmi));
+ }
+ U_swap4(&(pEmr->ihPen),5); // ihPen offBmi cbBmi offBits cbBits
+ if(!torev && pEmr->cbBmi){
+ bitmapinfo_swap((PU_BITMAPINFO)(record + pEmr->offBmi));
+ }
+ extlogpen_swap((PU_EXTLOGPEN) &(pEmr->elp), torev);
+}
+
+// U_EMRPOLYTEXTOUTA 96 NOT IMPLEMENTED, denigrated after Windows NT
+#define U_EMRPOLYTEXTOUTA_swap U_EMRNOTIMPLEMENTED_swap
+// U_EMRPOLYTEXTOUTW 97 NOT IMPLEMENTED, denigrated after Windows NT
+#define U_EMRPOLYTEXTOUTW_swap U_EMRNOTIMPLEMENTED_swap
+
+// U_EMRSETICMMODE 98
+void U_EMRSETICMMODE_swap(char *record, int torev){
+ core3_swap(record, torev);
+}
+
+// U_EMRCREATECOLORSPACE 99
+void U_EMRCREATECOLORSPACE_swap(char *record, int torev){
+ core5_swap(record, torev);
+ PU_EMRCREATECOLORSPACE pEmr = (PU_EMRCREATECOLORSPACE)(record);
+ U_swap4(&(pEmr->ihCS),1); // ihCS
+ logcolorspacea_swap(&(pEmr->lcs)); // lcs
+}
+
+// U_EMRSETCOLORSPACE 100
+void U_EMRSETCOLORSPACE_swap(char *record, int torev){
+ core3_swap(record, torev);
+}
+
+// U_EMRDELETECOLORSPACE 101
+void U_EMRDELETECOLORSPACE_swap(char *record, int torev){
+ core3_swap(record, torev);
+}
+
+// U_EMRGLSRECORD 102 Not implemented
+#define U_EMRGLSRECORD_swap U_EMRNOTIMPLEMENTED_swap
+// U_EMRGLSBOUNDEDRECORD 103 Not implemented
+#define U_EMRGLSBOUNDEDRECORD_swap U_EMRNOTIMPLEMENTED_swap
+
+// U_EMRPIXELFORMAT 104
+void U_EMRPIXELFORMAT_swap(char *record, int torev){
+ core5_swap(record, torev);
+ PU_EMRPIXELFORMAT pEmr = (PU_EMRPIXELFORMAT)(record);
+ pixelformatdescriptor_swap(&(pEmr->pfd)); // pfd
+}
+
+// U_EMRDRAWESCAPE 105 Not implemented
+#define U_EMRDRAWESCAPE_swap U_EMRNOTIMPLEMENTED_swap
+// U_EMREXTESCAPE 106 Not implemented
+#define U_EMREXTESCAPE_swap U_EMRNOTIMPLEMENTED_swap
+// U_EMRUNDEF107 107 Not implemented
+#define U_EMRUNDEF107_swap U_EMRNOTIMPLEMENTED_swap
+
+// U_EMRSMALLTEXTOUT 108
+void U_EMRSMALLTEXTOUT_swap(char *record, int torev){
+ int roff,fuOptions;
+ core5_swap(record, torev);
+ PU_EMRSMALLTEXTOUT pEmr = (PU_EMRSMALLTEXTOUT)(record);
+ if(torev){
+ fuOptions = pEmr->fuOptions;
+ }
+ pointl_swap(&(pEmr->Dest),1); // Dest
+ U_swap4(&(pEmr->cChars),5); // cChars fuOptions iGraphicsMode exScale eyScale
+ if(!torev){
+ fuOptions = pEmr->fuOptions;
+ }
+ roff = sizeof(U_EMRSMALLTEXTOUT); // offset to the start of the variable fields
+ if(!(fuOptions & U_ETO_NO_RECT)){
+ rectl_swap( (PU_RECTL) (record + roff),1); // rclBounds
+ }
+ // ordered bytes or UTF16-LE TextString
+}
+
+// U_EMRFORCEUFIMAPPING 109 Not implemented
+#define U_EMRFORCEUFIMAPPING_swap U_EMRNOTIMPLEMENTED_swap
+// U_EMRNAMEDESCAPE 110 Not implemented
+#define U_EMRNAMEDESCAPE_swap U_EMRNOTIMPLEMENTED_swap
+// U_EMRCOLORCORRECTPALETTE 111 Not implemented
+#define U_EMRCOLORCORRECTPALETTE_swap U_EMRNOTIMPLEMENTED_swap
+// U_EMRSETICMPROFILEA 112 Not implemented
+#define U_EMRSETICMPROFILEA_swap U_EMRNOTIMPLEMENTED_swap
+// U_EMRSETICMPROFILEW 113 Not implemented
+#define U_EMRSETICMPROFILEW_swap U_EMRNOTIMPLEMENTED_swap
+
+// U_EMRALPHABLEND 114
+void U_EMRALPHABLEND_swap(char *record, int torev){
+ core13_swap(record, torev);
+}
+
+// U_EMRSETLAYOUT 115
+void U_EMRSETLAYOUT_swap(char *record, int torev){
+ core3_swap(record, torev);
+}
+
+// U_EMRTRANSPARENTBLT 116
+void U_EMRTRANSPARENTBLT_swap(char *record, int torev){
+ core13_swap(record, torev);
+}
+
+
+// U_EMRUNDEF117 117 Not implemented
+#define U_EMRUNDEF117_swap U_EMRNOTIMPLEMENTED_swap
+// U_EMRGRADIENTFILL 118
+void U_EMRGRADIENTFILL_swap(char *record, int torev){
+ int nTriVert,nGradObj,ulMode;
+ core5_swap(record, torev);
+ PU_EMRGRADIENTFILL pEmr = (PU_EMRGRADIENTFILL)(record);
+ if(torev){
+ nTriVert = pEmr->nTriVert;
+ nGradObj = pEmr->nGradObj;
+ ulMode = pEmr->ulMode;
+ }
+ 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;
+ }
+ record += sizeof(U_EMRGRADIENTFILL);
+ if(nTriVert){
+ trivertex_swap((PU_TRIVERTEX)(record),nTriVert); // TriVert[]
+ }
+ if(nGradObj){
+ if( ulMode == U_GRADIENT_FILL_TRIANGLE){
+ gradient3_swap((PU_GRADIENT3)(record), nGradObj); // GradObj[]
+ }
+ else if(ulMode == U_GRADIENT_FILL_RECT_H || ulMode == U_GRADIENT_FILL_RECT_V){
+ gradient4_swap((PU_GRADIENT4)(record), nGradObj); // GradObj[]
+ }
+ }
+}
+
+// U_EMRSETLINKEDUFIS 119 Not implemented
+#define U_EMRSETLINKEDUFIS_swap U_EMRNOTIMPLEMENTED_swap
+// U_EMRSETTEXTJUSTIFICATION120 Not implemented (denigrated)
+#define U_EMRSETTEXTJUSTIFICATION_swap U_EMRNOTIMPLEMENTED_swap
+// U_EMRCOLORMATCHTOTARGETW 121 Not implemented
+#define U_EMRCOLORMATCHTOTARGETW_swap U_EMRNOTIMPLEMENTED_swap
+
+// U_EMRCREATECOLORSPACEW 122
+void U_EMRCREATECOLORSPACEW_swap(char *record, int torev){
+ core5_swap(record, torev);
+ PU_EMRCREATECOLORSPACEW pEmr = (PU_EMRCREATECOLORSPACEW)(record);
+ U_swap4(&(pEmr->ihCS),1); // ihCS
+ logcolorspacew_swap(&(pEmr->lcs)); // lcs
+ U_swap4(&(pEmr->dwFlags),2); // dwFlags cbData
+ // ordered bytes: Data
+}
+
+//! @endcond
+
+
+/**
+ \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){
+ size_t off;
+ uint32_t OK, recnum, iType;
+ char *record;
+ PU_ENHMETARECORD pEmr;
+
+ record = contents;
+ OK = 1;
+ off = 0;
+ recnum = 0;
+ while(OK){
+ if(record > contents + length){ // this is most likely a corrupt EMF
+ return(0);
+ }
+
+ pEmr = (PU_ENHMETARECORD)(record);
+
+ iType = pEmr->iType;
+ off = pEmr->nSize;
+ if(!torev){
+ U_swap4(&iType,1);
+ U_swap4(&off,1);
+ }
+
+ switch (iType)
+ {
+ case U_EMR_HEADER: U_EMRHEADER_swap(record, torev); break;
+ case U_EMR_POLYBEZIER: U_EMRPOLYBEZIER_swap(record, torev); break;
+ case U_EMR_POLYGON: U_EMRPOLYGON_swap(record, torev); break;
+ case U_EMR_POLYLINE: U_EMRPOLYLINE_swap(record, torev); break;
+ case U_EMR_POLYBEZIERTO: U_EMRPOLYBEZIERTO_swap(record, torev); break;
+ case U_EMR_POLYLINETO: U_EMRPOLYLINETO_swap(record, torev); break;
+ case U_EMR_POLYPOLYLINE: U_EMRPOLYPOLYLINE_swap(record, torev); break;
+ case U_EMR_POLYPOLYGON: U_EMRPOLYPOLYGON_swap(record, torev); break;
+ case U_EMR_SETWINDOWEXTEX: U_EMRSETWINDOWEXTEX_swap(record, torev); break;
+ case U_EMR_SETWINDOWORGEX: U_EMRSETWINDOWORGEX_swap(record, torev); break;
+ case U_EMR_SETVIEWPORTEXTEX: U_EMRSETVIEWPORTEXTEX_swap(record, torev); break;
+ case U_EMR_SETVIEWPORTORGEX: U_EMRSETVIEWPORTORGEX_swap(record, torev); break;
+ case U_EMR_SETBRUSHORGEX: U_EMRSETBRUSHORGEX_swap(record, torev); break;
+ case U_EMR_EOF:
+ U_EMREOF_swap(record, torev);
+ OK = 0; /* Exit triggered here */
+ break;
+ case U_EMR_SETPIXELV: U_EMRSETPIXELV_swap(record, torev); break;
+ case U_EMR_SETMAPPERFLAGS: U_EMRSETMAPPERFLAGS_swap(record, torev); break;
+ case U_EMR_SETMAPMODE: U_EMRSETMAPMODE_swap(record, torev); break;
+ case U_EMR_SETBKMODE: U_EMRSETBKMODE_swap(record, torev); break;
+ case U_EMR_SETPOLYFILLMODE: U_EMRSETPOLYFILLMODE_swap(record, torev); break;
+ case U_EMR_SETROP2: U_EMRSETROP2_swap(record, torev); break;
+ case U_EMR_SETSTRETCHBLTMODE: U_EMRSETSTRETCHBLTMODE_swap(record, torev); break;
+ case U_EMR_SETTEXTALIGN: U_EMRSETTEXTALIGN_swap(record, torev); break;
+ case U_EMR_SETCOLORADJUSTMENT: U_EMRSETCOLORADJUSTMENT_swap(record, torev); break;
+ case U_EMR_SETTEXTCOLOR: U_EMRSETTEXTCOLOR_swap(record, torev); break;
+ case U_EMR_SETBKCOLOR: U_EMRSETBKCOLOR_swap(record, torev); break;
+ case U_EMR_OFFSETCLIPRGN: U_EMROFFSETCLIPRGN_swap(record, torev); break;
+ case U_EMR_MOVETOEX: U_EMRMOVETOEX_swap(record, torev); break;
+ case U_EMR_SETMETARGN: U_EMRSETMETARGN_swap(record, torev); break;
+ case U_EMR_EXCLUDECLIPRECT: U_EMREXCLUDECLIPRECT_swap(record, torev); break;
+ case U_EMR_INTERSECTCLIPRECT: U_EMRINTERSECTCLIPRECT_swap(record, torev); break;
+ case U_EMR_SCALEVIEWPORTEXTEX: U_EMRSCALEVIEWPORTEXTEX_swap(record, torev); break;
+ case U_EMR_SCALEWINDOWEXTEX: U_EMRSCALEWINDOWEXTEX_swap(record, torev); break;
+ case U_EMR_SAVEDC: U_EMRSAVEDC_swap(record, torev); break;
+ case U_EMR_RESTOREDC: U_EMRRESTOREDC_swap(record, torev); break;
+ case U_EMR_SETWORLDTRANSFORM: U_EMRSETWORLDTRANSFORM_swap(record, torev); break;
+ case U_EMR_MODIFYWORLDTRANSFORM: U_EMRMODIFYWORLDTRANSFORM_swap(record, torev); break;
+ case U_EMR_SELECTOBJECT: U_EMRSELECTOBJECT_swap(record, torev); break;
+ case U_EMR_CREATEPEN: U_EMRCREATEPEN_swap(record, torev); break;
+ case U_EMR_CREATEBRUSHINDIRECT: U_EMRCREATEBRUSHINDIRECT_swap(record, torev); break;
+ case U_EMR_DELETEOBJECT: U_EMRDELETEOBJECT_swap(record, torev); break;
+ case U_EMR_ANGLEARC: U_EMRANGLEARC_swap(record, torev); break;
+ case U_EMR_ELLIPSE: U_EMRELLIPSE_swap(record, torev); break;
+ case U_EMR_RECTANGLE: U_EMRRECTANGLE_swap(record, torev); break;
+ case U_EMR_ROUNDRECT: U_EMRROUNDRECT_swap(record, torev); break;
+ case U_EMR_ARC: U_EMRARC_swap(record, torev); break;
+ case U_EMR_CHORD: U_EMRCHORD_swap(record, torev); break;
+ case U_EMR_PIE: U_EMRPIE_swap(record, torev); break;
+ case U_EMR_SELECTPALETTE: U_EMRSELECTPALETTE_swap(record, torev); break;
+ case U_EMR_CREATEPALETTE: U_EMRCREATEPALETTE_swap(record, torev); break;
+ case U_EMR_SETPALETTEENTRIES: U_EMRSETPALETTEENTRIES_swap(record, torev); break;
+ case U_EMR_RESIZEPALETTE: U_EMRRESIZEPALETTE_swap(record, torev); break;
+ case U_EMR_REALIZEPALETTE: U_EMRREALIZEPALETTE_swap(record, torev); break;
+ case U_EMR_EXTFLOODFILL: U_EMREXTFLOODFILL_swap(record, torev); break;
+ case U_EMR_LINETO: U_EMRLINETO_swap(record, torev); break;
+ case U_EMR_ARCTO: U_EMRARCTO_swap(record, torev); break;
+ case U_EMR_POLYDRAW: U_EMRPOLYDRAW_swap(record, torev); break;
+ case U_EMR_SETARCDIRECTION: U_EMRSETARCDIRECTION_swap(record, torev); break;
+ case U_EMR_SETMITERLIMIT: U_EMRSETMITERLIMIT_swap(record, torev); break;
+ case U_EMR_BEGINPATH: U_EMRBEGINPATH_swap(record, torev); break;
+ case U_EMR_ENDPATH: U_EMRENDPATH_swap(record, torev); break;
+ case U_EMR_CLOSEFIGURE: U_EMRCLOSEFIGURE_swap(record, torev); break;
+ case U_EMR_FILLPATH: U_EMRFILLPATH_swap(record, torev); break;
+ case U_EMR_STROKEANDFILLPATH: U_EMRSTROKEANDFILLPATH_swap(record, torev); break;
+ case U_EMR_STROKEPATH: U_EMRSTROKEPATH_swap(record, torev); break;
+ case U_EMR_FLATTENPATH: U_EMRFLATTENPATH_swap(record, torev); break;
+ case U_EMR_WIDENPATH: U_EMRWIDENPATH_swap(record, torev); break;
+ case U_EMR_SELECTCLIPPATH: U_EMRSELECTCLIPPATH_swap(record, torev); break;
+ case U_EMR_ABORTPATH: U_EMRABORTPATH_swap(record, torev); break;
+ case U_EMR_UNDEF69: U_EMRUNDEF69_swap(record, torev); break;
+ case U_EMR_COMMENT: U_EMRCOMMENT_swap(record, torev); break;
+ case U_EMR_FILLRGN: U_EMRFILLRGN_swap(record, torev); break;
+ case U_EMR_FRAMERGN: U_EMRFRAMERGN_swap(record, torev); break;
+ case U_EMR_INVERTRGN: U_EMRINVERTRGN_swap(record, torev); break;
+ case U_EMR_PAINTRGN: U_EMRPAINTRGN_swap(record, torev); break;
+ case U_EMR_EXTSELECTCLIPRGN: U_EMREXTSELECTCLIPRGN_swap(record, torev); break;
+ case U_EMR_BITBLT: U_EMRBITBLT_swap(record, torev); break;
+ case U_EMR_STRETCHBLT: U_EMRSTRETCHBLT_swap(record, torev); break;
+ case U_EMR_MASKBLT: U_EMRMASKBLT_swap(record, torev); break;
+ case U_EMR_PLGBLT: U_EMRPLGBLT_swap(record, torev); break;
+ case U_EMR_SETDIBITSTODEVICE: U_EMRSETDIBITSTODEVICE_swap(record, torev); break;
+ case U_EMR_STRETCHDIBITS: U_EMRSTRETCHDIBITS_swap(record, torev); break;
+ case U_EMR_EXTCREATEFONTINDIRECTW: U_EMREXTCREATEFONTINDIRECTW_swap(record, torev); break;
+ case U_EMR_EXTTEXTOUTA: U_EMREXTTEXTOUTA_swap(record, torev); break;
+ case U_EMR_EXTTEXTOUTW: U_EMREXTTEXTOUTW_swap(record, torev); break;
+ case U_EMR_POLYBEZIER16: U_EMRPOLYBEZIER16_swap(record, torev); break;
+ case U_EMR_POLYGON16: U_EMRPOLYGON16_swap(record, torev); break;
+ case U_EMR_POLYLINE16: U_EMRPOLYLINE16_swap(record, torev); break;
+ case U_EMR_POLYBEZIERTO16: U_EMRPOLYBEZIERTO16_swap(record, torev); break;
+ case U_EMR_POLYLINETO16: U_EMRPOLYLINETO16_swap(record, torev); break;
+ case U_EMR_POLYPOLYLINE16: U_EMRPOLYPOLYLINE16_swap(record, torev); break;
+ case U_EMR_POLYPOLYGON16: U_EMRPOLYPOLYGON16_swap(record, torev); break;
+ case U_EMR_POLYDRAW16: U_EMRPOLYDRAW16_swap(record, torev); break;
+ case U_EMR_CREATEMONOBRUSH: U_EMRCREATEMONOBRUSH_swap(record, torev); break;
+ case U_EMR_CREATEDIBPATTERNBRUSHPT: U_EMRCREATEDIBPATTERNBRUSHPT_swap(record, torev); break;
+ case U_EMR_EXTCREATEPEN: U_EMREXTCREATEPEN_swap(record, torev); break;
+ case U_EMR_POLYTEXTOUTA: U_EMRPOLYTEXTOUTA_swap(record, torev); break;
+ case U_EMR_POLYTEXTOUTW: U_EMRPOLYTEXTOUTW_swap(record, torev); break;
+ case U_EMR_SETICMMODE: U_EMRSETICMMODE_swap(record, torev); break;
+ case U_EMR_CREATECOLORSPACE: U_EMRCREATECOLORSPACE_swap(record, torev); break;
+ case U_EMR_SETCOLORSPACE: U_EMRSETCOLORSPACE_swap(record, torev); break;
+ case U_EMR_DELETECOLORSPACE: U_EMRDELETECOLORSPACE_swap(record, torev); break;
+ case U_EMR_GLSRECORD: U_EMRGLSRECORD_swap(record, torev); break;
+ case U_EMR_GLSBOUNDEDRECORD: U_EMRGLSBOUNDEDRECORD_swap(record, torev); break;
+ case U_EMR_PIXELFORMAT: U_EMRPIXELFORMAT_swap(record, torev); break;
+ case U_EMR_DRAWESCAPE: U_EMRDRAWESCAPE_swap(record, torev); break;
+ case U_EMR_EXTESCAPE: U_EMREXTESCAPE_swap(record, torev); break;
+ case U_EMR_UNDEF107: U_EMRUNDEF107_swap(record, torev); break;
+ case U_EMR_SMALLTEXTOUT: U_EMRSMALLTEXTOUT_swap(record, torev); break;
+ case U_EMR_FORCEUFIMAPPING: U_EMRFORCEUFIMAPPING_swap(record, torev); break;
+ case U_EMR_NAMEDESCAPE: U_EMRNAMEDESCAPE_swap(record, torev); break;
+ case U_EMR_COLORCORRECTPALETTE: U_EMRCOLORCORRECTPALETTE_swap(record, torev); break;
+ case U_EMR_SETICMPROFILEA: U_EMRSETICMPROFILEA_swap(record, torev); break;
+ case U_EMR_SETICMPROFILEW: U_EMRSETICMPROFILEW_swap(record, torev); break;
+ case U_EMR_ALPHABLEND: U_EMRALPHABLEND_swap(record, torev); break;
+ case U_EMR_SETLAYOUT: U_EMRSETLAYOUT_swap(record, torev); break;
+ case U_EMR_TRANSPARENTBLT: U_EMRTRANSPARENTBLT_swap(record, torev); break;
+ case U_EMR_UNDEF117: U_EMRUNDEF117_swap(record, torev); break;
+ case U_EMR_GRADIENTFILL: U_EMRGRADIENTFILL_swap(record, torev); break;
+ case U_EMR_SETLINKEDUFIS: U_EMRSETLINKEDUFIS_swap(record, torev); break;
+ case U_EMR_SETTEXTJUSTIFICATION: U_EMRSETTEXTJUSTIFICATION_swap(record, torev); break;
+ case U_EMR_COLORMATCHTOTARGETW: U_EMRCOLORMATCHTOTARGETW_swap(record, torev); break;
+ case U_EMR_CREATECOLORSPACEW: U_EMRCREATECOLORSPACEW_swap(record, torev); break;
+ default: U_EMRNOTIMPLEMENTED_swap(record, torev); break;
+ } //end of switch
+ record += off;
+ recnum++;
+ } //end of while
+
+ return(1);
+}
+
+#ifdef __cplusplus
+}
+#endif
diff -rNu3 src/extension/internal/uemf_endian.h src/extension/internal/uemf_endian.h
--- src/extension/internal/uemf_endian.h 1969-12-31 16:00:00.000000000 -0800
+++ src/extension/internal/uemf_endian.h 2012-08-07 12:44:48.000000000 -0700
@@ -0,0 +1,37 @@
+/**
+ @file uemf_endian.h Prototype for function for converting EMF records between Big Endian and Little Endian
+*/
+
+/*
+File: uemf_endian.h
+Version: 0.0.3
+Date: 24-JUL-2012
+Author: David Mathog, Biology Division, Caltech
+email: mathog@caltech.edu
+Copyright: 2012 David Mathog and California Institute of Technology (Caltech)
+*/
+
+#ifndef _UEMF_ENDIAN_
+#define _UEMF_ENDIAN_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* 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
+#else
+#define U_BYTE_SWAP 0
+#endif
+
+// prototypes
+int U_emf_endian(char *contents, size_t length, int torev);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _UEMF_ENDIAN_ */
diff -rNu3 src/extension/internal/uemf.h src/extension/internal/uemf.h
--- src/extension/internal/uemf.h 1969-12-31 16:00:00.000000000 -0800
+++ src/extension/internal/uemf.h 2012-08-07 12:44:48.000000000 -0700
@@ -0,0 +1,2919 @@
+/**
+ @file uemf.h Structures and functions 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"
+
+*/
+
+/*
+File: uemf.h
+Version: 0.0.4
+Date: 25-JUL-2012
+Author: David Mathog, Biology Division, Caltech
+email: mathog@caltech.edu
+Copyright: 2012 David Mathog and California Institute of Technology (Caltech)
+*/
+
+#ifndef _UEMF_
+#define _UEMF_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include
+#include
+#include "uemf_endian.h"
+
+
+
+// ***********************************************************************************
+// 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
+
+
+// ***********************************************************************************
+// Value enumerations and other predefined constants, alphabetical order by group
+
+
+
+/** \defgroup Font_struct_widths 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_EMR_Qualifiers RecordType Enumeration
+ (RecordType Enumeration)
+ For U_EMR iType field
+ @{
+*/
+#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
+/** @} */
+
+/** \defgroup U_DRAW_PROPERTIES
+ Used in draw_properties(). These are the bit definitions.
+ @{
+*/
+#define U_DRAW_NOTEMPTY 0x01 //!< Path has at least a MOVETO in it
+#define U_DRAW_VISIBLE 0x02 //!< Path has at least a LINE in it
+#define U_DRAW_CLOSED 0x04 //!< Path has been closed
+#define U_DRAW_ONLYTO 0x08 //!< Path so far contains only *TO operations
+#define U_DRAW_FORCE 0x10 //!< Path MUST be drawn
+#define U_DRAW_ALTERS 0x20 //!< Alters draw parameters (pen, brush, coordinates...)
+#define U_DRAW_PATH 0x40 //!< An explicit path is being used (with a BEGIN and END)
+
+/** @} */
+/** \defgroup U_EMRSETARCDIRECTION_Qualifiers ArcDirection Enumeration
+ For U_EMRSETARCDIRECTION iArcDirection field
+ @{
+*/
+#define U_AD_COUNTERCLOCKWISE 1
+#define U_AD_CLOCKWISE 2
+/** @} */
+
+/** \defgroup U_PANOSE_bArmStyle_Qualifiers ArmStyle Enumeration
+ For U_PANOSE bArmStyle field
+ @{
+*/
+#define U_PAN_STRAIGHT_ARMS_HORZ 2
+#define U_PAN_STRAIGHT_ARMS_WEDGE 3
+#define U_PAN_STRAIGHT_ARMS_VERT 4
+#define U_PAN_STRAIGHT_ARMS_SINGLE_SERIF 5
+#define U_PAN_STRAIGHT_ARMS_DOUBLE_SERIF 6
+#define U_PAN_BENT_ARMS_HORZ 7
+#define U_PAN_BENT_ARMS_WEDGE 8
+#define U_PAN_BENT_ARMS_VERT 9
+#define U_PAN_BENT_ARMS_SINGLE_SERIF 10
+#define U_PAN_BENT_ARMS_DOUBLE_SERIF 11
+/** @} */
+
+/** \defgroup U_EMRSETBKMODE_iMode_Qualifiers BackgroundMode enumeration
+ For U_EMRSETBKMODE iMode field
+ @{
+*/
+#define U_TRANSPARENT 1
+#define U_OPAQUE 2
+/** @} */
+
+/** \defgroup U_BITMAPINFOHEADER_biBitCount_Qualifiers BitCount Enumeration
+ For U_BITMAPINFOHEADER biBitCount field.
+ @{
+*/
+#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.
+/** @} */
+
+/** \defgroup U_BITMAPINFOHEADER_biCompression_Qualifiers BI_Compression Enumeration
+ For U_BITMAPINFOHEADER biCompression field
+ @{
+*/
+#define U_BI_RGB 0 //!< This is the only one supported by UEMF at present
+#define U_BI_RLE8 1
+#define U_BI_RLE4 2
+#define U_BI_BITFIELDS 3
+#define U_BI_JPEG 4
+#define U_BI_PNG 5
+/** @} */
+
+/** \defgroup U_COLORADJUSTMENT_caFlags_Qualifiers ColorAdjustment Enumeration
+ For U_COLORADJUSTMENT caFlags field
+ @{
+*/
+#define U_CA_NEGATIVE 0x0001
+#define U_CA_LOG_FILTER 0x0002
+/** @} */
+
+/** \defgroup U_EMRCOLORMATCHTOTARGETW_dwAction_Qualifiers ColorMatchToTarget Enumeration
+ For U_EMRCOLORMATCHTOTARGETW dwFlags field
+ @{
+*/
+#define U_COLORMATCHTOTARGET_NOTEMBEDDED 0
+#define U_COLORMATCHTOTARGET_EMBEDDED 1
+/** @} */
+
+/** \defgroup U_EMRCOLORMATCHTOTARGETW_dwAction_Qualifiers ColorSpace Enumeration
+ For U_EMRCOLORMATCHTOTARGETW dwAction field
+ @{
+*/
+#define U_CS_ENABLE 1
+#define U_CS_DISABLE 2
+#define U_CS_DELETE_TRANSFORM 3
+/** @} */
+
+/** \defgroup U_PANOSE_bContrast_Qualifiers Contrast Enumeration
+ For U_PANOSE bContrast field
+ @{
+*/
+#define U_PAN_CONTRAST_NONE 2
+#define U_PAN_CONTRAST_VERY_LOW 3
+#define U_PAN_CONTRAST_LOW 4
+#define U_PAN_CONTRAST_MEDIUM_LOW 5
+#define U_PAN_CONTRAST_MEDIUM 6
+#define U_PAN_CONTRAST_MEDIUM_HIGH 7
+#define U_PAN_CONTRAST_HIGH 8
+#define U_PAN_CONTRAST_VERY_HIGH 9
+/** @} */
+
+/** \defgroup U_DIBITS_iUsageSrc_Qualifiers DIBColors Enumeration
+ For U_EMRSETDIBITSTODEIVCE and U_EMRSTRETCHDIBITS iUsageSrc fields.
+ @{
+*/
+#define U_DIB_RGB_COLORS 0
+#define U_DIB_PAL_COLORS 1
+/** @} */
+
+/** \defgroup U_EMR_COMMENT_PublicCommentIdentifier_Qualifiers EmrComment Enumeration
+ For U_EMR_COMMENT_* PublicCommentIdentifier fields
+ @{
+*/
+#define U_EMR_COMMENT_IDENTIFIER 0x43494447
+#define U_EMR_COMMENT_WINDOWS_METAFILE 0x80000001
+#define U_EMR_COMMENT_BEGINGROUP 0x00000002
+#define U_EMR_COMMENT_ENDGROUP 0x00000003
+#define U_EMR_COMMENT_MULTIFORMATS 0x40000004
+#define U_EMR_COMMENT_UNICODE_STRING 0x00000040
+#define U_EMR_COMMENT_UNICODE_END 0x00000080
+/** @} */
+
+/** \defgroup U_EMRTEXT_foptions_Qualifiers ExtTextOutOptions Enumeration
+ For U_EMRTEXT foptions field
+ @{
+*/
+#define U_ETO_NONE 0x00000000
+#define U_ETO_GRAYED 0x00000001
+#define U_ETO_OPAQUE 0x00000002
+#define U_ETO_CLIPPED 0x00000004
+#define U_ETO_GLYPH_INDEX 0x00000010
+#define U_ETO_RTLREADING 0x00000080
+#define U_ETO_NO_RECT 0x00000100
+#define U_ETO_SMALL_CHARS 0x00000200 // For EMRSMALLTEXTOUT ONLY, does not affect EMRTEXTOUTA or EMRTEXTOUTW
+#define U_ETO_NUMERICSLOCAL 0x00000400
+#define U_ETO_NUMERICSLATIN 0x00000800
+#define U_ETO_IGNORELANGUAGE 0x00001000
+#define U_ETO_PDY 0x00002000
+#define U_ETO_REVERSE_INDEX_MAP 0x00010000
+/** @} */
+
+/** \defgroup U_PANOSE_bFamilyType_Qualifiers FamilyType Enumeration
+ For U_PANOSE bFamilyType field
+ @{
+*/
+#define U_PAN_FAMILY_TEXT_DISPLAY 2
+#define U_PAN_FAMILY_SCRIPT 3
+#define U_PAN_FAMILY_DECORATIVE 4
+#define U_PAN_FAMILY_PICTORIAL 5
+/** @} */
+
+/** \defgroup U_EMREXTFLOODFILL_iMode_Qualifiers FloodFill Enumeration
+ For U_EMREXTFLOODFILL iMode field
+ @{
+*/
+#define U_FLOODFILLBORDER 0x00000000
+#define U_FLOODFILLSURFACE 0x00000000
+/** @} */
+
+/** \defgroup U_DESIGNVECTOR_Signature_Qualifiers Signature Enumeration
+ For U_DESIGNVECTOR Signature field
+ @{
+*/
+#define U_ENHMETA_SIGNATURE 0x464D4520 //!< also for U_EMRHEADER dSignature field
+#define U_EPS_SIGNATURE 0x46535045
+/** @} */
+
+/** \defgroup U_EMRGRADIENTFILL_ulMode_Qualifiers GradientFill Enumeration
+ For U_EMRGRADIENTFILL ulMode field
+ @{
+*/
+#define U_GRADIENT_FILL_RECT_H 0x00000000
+#define U_GRADIENT_FILL_RECT_V 0x00000001
+#define U_GRADIENT_FILL_TRIANGLE 0x00000002
+/** @} */
+
+/** \defgroup U_EMREXTTEXTOUT_iGraphicsMode_Qualifiers GraphicsMode Enumeration
+ For U_EMREXTTEXTOUTA/U_EMREXTTEXTOUTW and all other iGraphicsMode fields
+ @{
+*/
+#define U_GM_COMPATIBLE 1
+#define U_GM_ADVANCED 2
+#define U_GM_LAST 2
+/** @} */
+
+/** \defgroup U_LOGBRUSH_lbHatch_Qualifiers HatchStyle Enumeration
+ For U_LOGBRUSH lbHatch field
+ @{
+*/
+#define U_HS_HORIZONTAL 0
+#define U_HS_VERTICAL 1
+#define U_HS_FDIAGONAL 2
+#define U_HS_BDIAGONAL 3
+#define U_HS_CROSS 4
+#define U_HS_DIAGCROSS 5
+#define U_HS_SOLIDCLR 6
+#define U_HS_DITHEREDCLR 7
+#define U_HS_SOLIDTEXTCLR 8
+#define U_HS_DITHEREDTEXTCLR 9
+#define U_HS_SOLIDBKCLR 10
+#define U_HS_DITHEREDBKCLR 11
+/** @} */
+
+/** \defgroup U_EMRSETICMMODE_iMode_Qualifiers ICMMode Enumeration
+ For EMF U_EMR_SETICMMODE iMode field
+ @{
+*/
+#define U_ICM_OFF 1
+#define U_ICM_ON 2
+#define U_ICM_QUERY 3
+/** @} */
+
+/** \defgroup U_COLORADJUSTMENT_caIlluminantIndex_Qualifiers Illuminant Enumeration
+ For U_COLORADJUSTMENT caIlluminantIndex field
+ @{
+*/
+#define U_ILLUMINANT_DEVICE_DEFAULT 0
+#define U_ILLUMINANT_A 1
+#define U_ILLUMINANT_B 2
+#define U_ILLUMINANT_C 3
+#define U_ILLUMINANT_D50 4
+#define U_ILLUMINANT_D55 5
+#define U_ILLUMINANT_D65 6
+#define U_ILLUMINANT_D75 7
+#define U_ILLUMINANT_F2 8
+#define U_ILLUMINANT_MAX_INDEX ILLUMINANT_F2
+#define U_ILLUMINANT_TUNGSTEN ILLUMINANT_A
+#define U_ILLUMINANT_DAYLIGHT ILLUMINANT_C
+#define U_ILLUMINANT_FLUORESCENT ILLUMINANT_F2
+#define U_ILLUMINANT_NTSC ILLUMINANT_C
+/** @} */
+
+/** \defgroup U_LOGBRUSH_lbStyle_Qualifiers LB_Style Enumeration
+ For U_LOGBRUSH lbStyle field
+ @{
+*/
+#define U_BS_SOLID 0
+#define U_BS_NULL 1
+#define U_BS_HOLLOW 1
+#define U_BS_HATCHED 2
+#define U_BS_PATTERN 3
+#define U_BS_INDEXED 4
+#define U_BS_DIBPATTERN 5
+#define U_BS_DIBPATTERNPT 6
+#define U_BS_PATTERN8X8 7
+#define U_BS_DIBPATTERN8X8 8
+#define U_BS_MONOPATTERN 9
+/** @} */
+
+/** \defgroup _LOGCOLORSPACE_lcsCSType_Qualifiers LCS_CSType Enumeration
+ For U_LOGCOLORSPACEA/U_LOGCOLORSPACEW lcsCSType field
+ @{
+*/
+#define U_LCS_CALIBRATED_RGB 0x00000000L
+#define U_LCS_DEVICE_RGB 0x00000001L
+#define U_LCS_DEVICE_CMYK 0x00000002L
+/** @} */
+
+/** \defgroup U_LOGCOLORSPACE_lcsIntent_Qualifiers LCS_Intent Enumeration
+ For U_LOGCOLORSPACEA/U_LOGCOLORSPACEW lcsIntent field
+ @{
+*/
+#define U_LCS_GM_BUSINESS 0x00000001L
+#define U_LCS_GM_GRAPHICS 0x00000002L
+#define U_LCS_GM_IMAGES 0x00000004L
+#define U_LCS_GM_ABS_COLORIMETRIC 0x00000008L
+/** @} */
+
+/** \defgroup U_PANOSE_bLetterForm_Qualifiers Letterform Enumeration
+ For U_PANOSE bLetterForm field
+ @{
+*/
+#define U_PAN_LETT_NORMAL_COMPACT 2
+#define U_PAN_LETT_NORMAL_WEIGHTED 3
+#define U_PAN_LETT_NORMAL_BOXED 4
+#define U_PAN_LETT_NORMAL_FLATTENED 5
+#define U_PAN_LETT_NORMAL_ROUNDED 6
+#define U_PAN_LETT_NORMAL_OFF_CENTER 7
+#define U_PAN_LETT_NORMAL_SQUARE 8
+#define U_PAN_LETT_OBLIQUE_COMPACT 9
+#define U_PAN_LETT_OBLIQUE_WEIGHTED 10
+#define U_PAN_LETT_OBLIQUE_BOXED 11
+#define U_PAN_LETT_OBLIQUE_FLATTENED 12
+#define U_PAN_LETT_OBLIQUE_ROUNDED 13
+#define U_PAN_LETT_OBLIQUE_OFF_CENTER 14
+#define U_PAN_LETT_OBLIQUE_SQUARE 15
+/** @} */
+
+/** \defgroup U_LOGFONT_lfWeight_Qualifiers LF_Weight Enumeration
+ For U_LOGFONT lfWeight field
+ @{
+*/
+#define U_FW_DONTCARE 0
+#define U_FW_THIN 100
+#define U_FW_EXTRALIGHT 200
+#define U_FW_ULTRALIGHT 200
+#define U_FW_LIGHT 300
+#define U_FW_NORMAL 400
+#define U_FW_REGULAR 400
+#define U_FW_MEDIUM 500
+#define U_FW_SEMIBOLD 600
+#define U_FW_DEMIBOLD 600
+#define U_FW_BOLD 700
+#define U_FW_EXTRABOLD 800
+#define U_FW_ULTRABOLD 800
+#define U_FW_HEAVY 900
+#define U_FW_BLACK 900
+/** @} */
+
+/** \defgroup U_LOGFONT_lfItalic_Qualifiers LF_Italic Enumeration
+ For U_LOGFONT lfItalic field
+ @{
+*/
+#define U_FW_NOITALIC 0
+#define U_FW_ITALIC 1
+/** @} */
+
+/** \defgroup U_LOGFONT_lfunderline_Qualifiers LF_Underline Enumeration
+ For U_LOGFONT lfunderline field
+ @{
+*/
+#define U_FW_NOUNDERLINE 0
+#define U_FW_UNDERLINE 1
+/** @} */
+
+/** \defgroup U_LOGFONT_lfStrikeOut_Qualifiers LF_StrikeOut Enumeration
+ For U_LOGFONT lfStrikeOut field
+ @{
+*/
+#define U_FW_NOSTRIKEOUT 0
+#define U_FW_STRIKEOUT 1
+/** @} */
+
+/** \defgroup U_LOGFONT_lfCharSet_Qualifiers LF_CharSet Enumeration
+ For U_LOGFONT lfCharSet field
+ @{
+*/
+#define U_ANSI_CHARSET (uint8_t)0 /* CP1252, ansi-0, iso8859-{1,15} */
+#define U_DEFAULT_CHARSET (uint8_t)1
+#define U_SYMBOL_CHARSET (uint8_t)2
+#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
+#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
+#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
+#define U_OEM_CHARSET (uint8_t)255
+/* I don't know if the values of *_CHARSET macros are defined in Windows
+ * or if we can choose them as we want. -- srtxg
+ */
+#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_LOGFONT_lfOutPrecision_Qualifiers LF_OutPrecision Enumeration
+ For U_LOGFONT lfOutPrecision field
+ @{
+*/
+#define U_OUT_DEFAULT_PRECIS 0
+#define U_OUT_STRING_PRECIS 1
+#define U_OUT_CHARACTER_PRECIS 2
+#define U_OUT_STROKE_PRECIS 3
+#define U_OUT_TT_PRECIS 4
+#define U_OUT_DEVICE_PRECIS 5
+#define U_OUT_RASTER_PRECIS 6
+#define U_OUT_TT_ONLY_PRECIS 7
+#define U_OUT_OUTLINE_PRECIS 8
+/** @} */
+
+/** \defgroup U_LOGFONT_lfClipPrecision_Qualifiers LF_ClipPrecision Enumeration
+ For U_LOGFONT lfClipPrecision field
+ @{
+*/
+#define U_CLIP_DEFAULT_PRECIS 0x00
+#define U_CLIP_CHARACTER_PRECIS 0x01
+#define U_CLIP_STROKE_PRECIS 0x02
+#define U_CLIP_MASK 0x0F
+#define U_CLIP_LH_ANGLES 0x10
+#define U_CLIP_TT_ALWAYS 0x20
+#define U_CLIP_EMBEDDED 0x80
+/** @} */
+
+/** \defgroup U_LOGFONT_lfQuality_Qualifiers LF_Quality Enumeration
+ For For U_LOGFONT lfQuality field
+ @{
+*/
+#define U_DEFAULT_QUALITY 0
+#define U_DRAFT_QUALITY 1
+#define U_PROOF_QUALITY 2
+#define U_NONANTIALIASED_QUALITY 3
+#define U_ANTIALIASED_QUALITY 4
+/** @} */
+
+/** \defgroup U_LOGFONT_lfPitchAndFamily_Qualifiers LF_PitchAndFamily Enumeration
+ For U_LOGFONT lfPitchAndFamily field
+ @{
+*/
+#define U_DEFAULT_PITCH 0x00
+#define U_FIXED_PITCH 0x01
+#define U_VARIABLE_PITCH 0x02
+#define U_MONO_FONT 0x08
+#define U_FF_DONTCARE 0x00
+#define U_FF_ROMAN 0x10
+#define U_FF_SWISS 0x20
+#define U_FF_MODERN 0x30
+#define U_FF_SCRIPT 0x40
+#define U_FF_DECORATIVE 0x50
+/** @} */
+
+/** \defgroup U_EMRSETMAPMODE_iMode_Qualifiers MapMode Enumeration
+ For U_EMRSETMAPMODE iMode field
+ @{
+*/
+#define U_MM_TEXT 1
+#define U_MM_LOMETRIC 2
+#define U_MM_HIMETRIC 3
+#define U_MM_LOENGLISH 4
+#define U_MM_HIENGLISH 5
+#define U_MM_TWIPS 6
+#define U_MM_ISOTROPIC 7
+#define U_MM_ANISOTROPIC 8
+#define U_MM_MIN U_MM_TEXT
+#define U_MM_MAX U_MM_ANISOTROPIC
+#define U_MM_MAX_FIXEDSCALE U_MM_TWIPS
+/** @} */
+
+
+/** \defgroup U_PANOSE_bMidline_Qualifiers MidLine Enumeration
+ For U_PANOSE bMidline field
+ @{
+*/
+#define U_PAN_MIDLINE_STANDARD_TRIMMED 2
+#define U_PAN_MIDLINE_STANDARD_POINTED 3
+#define U_PAN_MIDLINE_STANDARD_SERIFED 4
+#define U_PAN_MIDLINE_HIGH_TRIMMED 5
+#define U_PAN_MIDLINE_HIGH_POINTED 6
+#define U_PAN_MIDLINE_HIGH_SERIFED 7
+#define U_PAN_MIDLINE_CONSTANT_TRIMMED 8
+#define U_PAN_MIDLINE_CONSTANT_POINTED 9
+#define U_PAN_MIDLINE_CONSTANT_SERIFED 10
+#define U_PAN_MIDLINE_LOW_TRIMMED 11
+#define U_PAN_MIDLINE_LOW_POINTED 12
+#define U_PAN_MIDLINE_LOW_SERIFED 13
+/** @} */
+
+/** \defgroup U_EMRSETLAYOUT_iMode_Qualifiers Mirroring Enumeration
+ For U_EMRSETLAYOUT iMode field
+ @{
+*/
+#define U_LAYOUT_LTR 0x00000000
+#define U_LAYOUT_RTL 0x00000001
+#define U_LAYOUT_BITMAPORIENTATIONPRESERVED 0x00000008
+#define U_NOMIRRORBITMAP 0x80000000
+/** @} */
+
+/** \defgroup U_EMRMODIFYWORLDTRANSFORM_iMode_Qualifiers ModifyWorldTransformMode Enumeration
+ For U_EMRMODIFYWORLDTRANSFORM iMode
+ @{
+*/
+#define U_MWT_IDENTITY 1
+#define U_MWT_LEFTMULTIPLY 2
+#define U_MWT_RIGHTMULTIPLY 3
+#define U_MWT_MIN U_MWT_IDENTITY
+#define U_MWT_MAX U_MWT_RIGHTMULTIPLY
+/** @} */
+
+/** \defgroup U_PANOSE_common_Qualifiers 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
+#define U_PAN_NO_FIT 1
+/** @} */
+
+/** \defgroup U_PANOSE_index PanoseIndex Enumeration
+ Fositions of each field in U_PANOSE structure.
+ @{
+*/
+#define U_PANOSE_COUNT 10
+#define U_PANOSE_FAMILYTYPE_INDEX 0
+#define U_PAN_SERIFSTYLE_INDEX 1
+#define U_PAN_WEIGHT_INDEX 2
+#define U_PAN_PROPORTION_INDEX 3
+#define U_PAN_CONTRAST_INDEX 4
+#define U_PAN_STROKEVARIATION_INDEX 5
+#define U_PAN_ARMSTYLE_INDEX 6
+#define U_PAN_LETTERFORM_INDEX 7
+#define U_PAN_MIDLINE_INDEX 8
+#define U_PAN_XHEIGHT_INDEX 9
+/** @} */
+
+/** \defgroup U_*LOGPEN_elpPenStyle_Qualifiers PenStyle Enumeration
+ For U_LOGPEN lopnStyle and U_EXTLOGPEN elpPenStyle fields
+ @{
+*/
+#define U_PS_SOLID 0x00000000
+#define U_PS_DASH 0x00000001 //!< 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 //!< 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 //!< 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 //!< 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
+#define U_PS_INSIDEFRAME 0x00000006
+#define U_PS_USERSTYLE 0x00000007
+#define U_PS_ALTERNATE 0x00000008
+#define U_PS_STYLE_MASK 0x0000000f
+
+#define U_PS_ENDCAP_ROUND 0x00000000 //!< These are only with U_PS_GEOMETRIC
+#define U_PS_ENDCAP_SQUARE 0x00000100
+#define U_PS_ENDCAP_FLAT 0x00000200
+#define U_PS_ENDCAP_MASK 0x00000f00
+
+#define U_PS_JOIN_ROUND 0x00000000 //!< These are only with U_PS_GEOMETRIC
+#define U_PS_JOIN_BEVEL 0x00001000
+#define U_PS_JOIN_MITER 0x00002000
+#define U_PS_JOIN_MASK 0x0000f000
+
+#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
+/** @} */
+
+/** \defgroup U_PIXELFORMATDESCRIPTOR_dwFlags_Qualifiers PFD_dwFlags Enumeration
+ For U_PIXELFORMATDESCRIPTOR dwFlags field
+ @{
+*/
+#define U_PFD_DOUBLEBUFFER 0x00000001
+#define U_PFD_STEREO 0x00000002
+#define U_PFD_DRAW_TO_WINDOW 0x00000004
+#define U_PFD_DRAW_TO_BITMAP 0x00000008
+#define U_PFD_SUPPORT_GDI 0x00000010
+#define U_PFD_SUPPORT_OPENGL 0x00000020
+#define U_PFD_GENERIC_FORMAT 0x00000040
+#define U_PFD_NEED_PALETTE 0x00000080
+#define U_PFD_NEED_SYSTEM_PALETTE 0x00000100
+#define U_PFD_SWAP_EXCHANGE 0x00000200
+#define U_PFD_SWAP_COPY 0x00000400
+#define U_PFD_SWAP_LAYER_BUFFERS 0x00000800
+#define U_PFD_GENERIC_ACCELERATED 0x00001000
+/** @} */
+
+/** \defgroup U_PIXELFORMATDESCRIPTOR_iLayerType_Qualifiers PFD_iLayerType Enumeration
+ For U_PIXELFORMATDESCRIPTOR iLayerType field
+ @{
+*/
+#define U_PFD_MAIN_PLANE 0
+#define U_PFD_OVERLAY_PLANE 1
+#define U_PFD_UNDERLAY_PLANE (-1)
+/** @} */
+
+/** \defgroup U_PIXELFORMATDESCRIPTOR_iPixelType_Qualifiers PFD_iPixelType Enumeration
+ For U_PIXELFORMATDESCRIPTOR iPixelType field
+ @{
+*/
+#define U_PFD_TYPE_RGBA 0
+#define U_PFD_TYPE_COLORINDEX 1
+/** @} */
+
+/** \defgroup U_EMRPOLY_iMode_Qualifiers Point Enumeration
+ For U_EMRPOLYDRAW and U_EMRPOLAYDRAW16 abTypes fields.
+ @{
+*/
+#define U_PT_CLOSEFIGURE 0x0001
+#define U_PT_LINETO 0x0002
+#define U_PT_BEZIERTO 0x0004
+#define U_PT_MOVETO 0x0006
+/** @} */
+
+/** \defgroup U_EMRSETPOLYFILLMODE_iMode_Qualifiers PolygonFillMode Enumeration
+ For U_EMRSETPOLYFILLMODE iMode field
+ @{
+*/
+#define U_ALTERNATE 1
+#define U_WINDING 2
+#define U_POLYFILL_LAST 2
+/** @} */
+
+/** \defgroup U_BITMAPV5HEADER_bV5CSType_Qualifiers Profile Enumeration
+ For U_BITMAPV5HEADER bV5CSType field
+ @{
+*/
+#define U_PROFILE_LINKED 'LINK'
+#define U_PROFILE_EMBEDDED 'MBED'
+/** @} */
+
+/** \defgroup U_PANOSE_bProportion_Qualifiers Proportion Enumeration
+ For U_PANOSE bProportion field
+ @{
+*/
+#define U_PAN_PROP_OLD_STYLE 2
+#define U_PAN_PROP_MODERN 3
+#define U_PAN_PROP_EVEN_WIDTH 4
+#define U_PAN_PROP_EXPANDED 5
+#define U_PAN_PROP_CONDENSED 6
+#define U_PAN_PROP_VERY_EXPANDED 7
+#define U_PAN_PROP_VERY_CONDENSED 8
+#define U_PAN_PROP_MONOSPACED 9
+/** @} */
+
+/** \defgroup U_EMR_dwROP_Qualifiers Ternary Raster Operation enumeration
+ For U_EMR* dwROP fields.
+
+ 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 0xcc0020
+#define U_SRCPAINT 0xee0086
+#define U_SRCAND 0x8800c6
+#define U_SRCINVERT 0x660046
+#define U_SRCERASE 0x440328
+#define U_NOTSRCCOPY 0x330008
+#define U_NOTSRCERASE 0x1100a6
+#define U_MERGECOPY 0xc000ca
+#define U_MERGEPAINT 0xbb0226
+#define U_PATCOPY 0xf00021
+#define U_PATPAINT 0xfb0a09
+#define U_PATINVERT 0x5a0049
+#define U_DSTINVERT 0x550009
+#define U_BLACKNESS 0x000042
+#define U_WHITENESS 0xff0062
+/** @} */
+
+/** \defgroup U_EMRSETROP2_iMode_Qualifiers Binary Raster Operation Enumeration
+ For U_EMRSETROP2 iMode field
+
+ 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
+#define U_R2_NOTMERGEPEN 2
+#define U_R2_MASKNOTPEN 3
+#define U_R2_NOTCOPYPEN 4
+#define U_R2_MASKPENNOT 5
+#define U_R2_NOT 6
+#define U_R2_XORPEN 7
+#define U_R2_NOTMASKPEN 8
+#define U_R2_MASKPEN 9
+#define U_R2_NOTXORPEN 10
+#define U_R2_NOP 11
+#define U_R2_MERGENOTPEN 12
+#define U_R2_COPYPEN 13
+#define U_R2_MERGEPENNOT 14
+#define U_R2_MERGEPEN 15
+#define U_R2_WHITE 16
+#define U_R2_LAST 16
+/** @} */
+
+/** \defgroup U_EMRSELECTCLIP_iMode_Qualifiers RegionMode Enumeration
+ For U_EMRSELECTCLIPPATH and U_EMREXTSELECTCLIPRGN iMode field
+ @{
+*/
+#define U_RGN_AND 1
+#define U_RGN_OR 2
+#define U_RGN_XOR 3
+#define U_RGN_DIFF 4
+#define U_RGN_COPY 5
+#define U_RGN_MIN U_RGN_AND
+#define U_RGN_MAX U_RGN_COPY
+/** @} */
+
+/** \defgroup U_PANOSE_bSerifStyle_Qualifiers SerifType Enumeration
+ For U_PANOSE bSerifStyle field
+ @{
+*/
+#define U_PAN_SERIF_COVE 2
+#define U_PAN_SERIF_OBTUSE_COVE 3
+#define U_PAN_SERIF_SQUARE_COVE 4
+#define U_PAN_SERIF_OBTUSE_SQUARE_COVE 5
+#define U_PAN_SERIF_SQUARE 6
+#define U_PAN_SERIF_THIN 7
+#define U_PAN_SERIF_BONE 8
+#define U_PAN_SERIF_EXAGGERATED 9
+#define U_PAN_SERIF_TRIANGLE 10
+#define U_PAN_SERIF_NORMAL_SANS 11
+#define U_PAN_SERIF_OBTUSE_SANS 12
+#define U_PAN_SERIF_PERP_SANS 13
+#define U_PAN_SERIF_FLARED 14
+#define U_PAN_SERIF_ROUNDED 15
+/** @} */
+
+/** \defgroup U_EMRSELECTOBJECT_ihObject_Qualifiers StockObject Enumeration
+ For U_EMRSELECTOBJECT ihObject field.
+ @{
+*/
+#define U_STOCK_OBJECT 0x80000000
+#define U_WHITE_BRUSH 0x80000000
+#define U_LTGRAY_BRUSH 0x80000001
+#define U_GRAY_BRUSH 0x80000002
+#define U_DKGRAY_BRUSH 0x80000003
+#define U_BLACK_BRUSH 0x80000004
+#define U_NULL_BRUSH 0x80000005
+#define U_HOLLOW_BRUSH 0x80000005
+#define U_WHITE_PEN 0x80000006
+#define U_BLACK_PEN 0x80000007
+#define U_NULL_PEN 0x80000008
+#define U_OEM_FIXED_FONT 0x8000000A
+#define U_ANSI_FIXED_FONT 0x8000000B
+#define U_ANSI_VAR_FONT 0x8000000C
+#define U_SYSTEM_FONT 0x8000000D
+#define U_DEVICE_DEFAULT_FONT 0x8000000E
+#define U_DEFAULT_PALETTE 0x8000000F
+#define U_SYSTEM_FIXED_FONT 0x80000010
+#define U_DEFAULT_GUI_FONT 0x80000011
+#define U_STOCK_LAST 0x80000011
+/** @} */
+
+/** \defgroup U_EMRSETSTRETCHBLTMODE_iMode_Qualifiers StretchMode Enumeration
+ For EMF U_EMRSETSTRETCHBLTMODE iMode field
+ @{
+*/
+#define U_BLACKONWHITE 1
+#define U_WHITEONBLACK 2
+#define U_COLORONCOLOR 3
+#define U_HALFTONE 4
+#define U_MAXSTRETCHBLTMODE 4
+#define U_STRETCH_ANDSCANS 1
+#define U_STRETCH_ORSCANS 2
+#define U_STRETCH_DELETESCANS 3
+#define U_STRETCH_HALFTONE 4
+/** @} */
+
+/** \defgroup U_PANOSE_bStrokeVariation_Qualifiers StrokeVariation Enumeration
+ For U_PANOSE bStrokeVariation field
+ @{
+*/
+#define U_PAN_STROKE_GRADUAL_DIAG 2
+#define U_PAN_STROKE_GRADUAL_TRAN 3
+#define U_PAN_STROKE_GRADUAL_VERT 4
+#define U_PAN_STROKE_GRADUAL_HORZ 5
+#define U_PAN_STROKE_RAPID_VERT 6
+#define U_PAN_STROKE_RAPID_HORZ 7
+#define U_PAN_STROKE_INSTANT_VERT 8
+/** @} */
+
+/** \defgroup U_EMRSETTEXTALIGN_iMode_Qualifiers TextAlignment Enumeration
+ For U_EMRSETTEXTALIGN iMode field
+
+ 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
+// Vertical text flags
+#define U_VTA_BASELINE U_TA_BASELINE // for vertical text
+#define U_VTA_LEFT U_TA_BOTTOM
+#define U_VTA_RIGHT U_TA_TOP
+#define U_VTA_CENTER U_TA_CENTER
+#define U_VTA_BOTTOM U_TA_RIGHT
+#define U_VTA_TOP U_TA_LEFT
+/** @} */
+
+/** \defgroup U_PANOSE_bWeight_Qualifiers Weight Enumeration
+ For U_PANOSE bWeight field
+ @{
+*/
+#define U_PAN_WEIGHT_VERY_LIGHT 2
+#define U_PAN_WEIGHT_LIGHT 3
+#define U_PAN_WEIGHT_THIN 4
+#define U_PAN_WEIGHT_BOOK 5
+#define U_PAN_WEIGHT_MEDIUM 6
+#define U_PAN_WEIGHT_DEMI 7
+#define U_PAN_WEIGHT_BOLD 8
+#define U_PAN_WEIGHT_HEAVY 9
+#define U_PAN_WEIGHT_BLACK 10
+#define U_PAN_WEIGHT_NORD 11
+/** @} */
+
+/** \defgroup U_PANOSE_bXHeight_Qualifiers XHeight Enumeration
+ For U_PANOSE bXHeight field
+ @{
+*/
+#define U_PAN_XHEIGHT_CONSTANT_SMALL 2
+#define U_PAN_XHEIGHT_CONSTANT_STANDARD 3
+#define U_PAN_XHEIGHT_CONSTANT_LARGE 4
+#define U_PAN_XHEIGHT_DUCKING_SMALL 5
+#define U_PAN_XHEIGHT_DUCKING_STANDARD 6
+#define U_PAN_XHEIGHT_DUCKING_LARGE 7
+/** @} */
+
+/** \defgroup U_BLEND_Op_Qualifiers Blend Enumeration
+ For U_BLEND Op field
+ @{
+*/
+#define U_AC_SRC_GLOBAL 0
+#define U_AC_SRC_CONST 0
+#define U_AC_SRC_ALPHA 1
+/** @} */
+
+
+// ***************************************************************************
+/** \defgroup Miscellaneous_values Miscellaneous Values
+ @{
+*/
+#define U_NONE 0 //!< Generic for nothing selected for all flag fields
+#define U_PI 3.14159265358979323846 //!< pi
+#define U_READ 1
+#define U_WRITE 0
+#define U_ENHMETA_VERSION 0x00010000 //!< U_EMRHEADER nVersion field
+#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 //!< used with emf_append
+#define U_REC_KEEP 0 //!< used with emf_append
+/** 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) ) )
+
+/** @} */
+
+// ***************************************************************************
+// Macros
+
+/** \defgroup Common_macros Common Macros
+ @{
+*/
+// Color U_BGR(A), byte order lo to hi: {B,G,R,A} corresponding to U_RGBQUAD. Set/Get Macros.
+// 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) (U_RGBQUAD){b,g,r,0} //!< Set any BGR color with an {r,g,b} triplet
+#define U_BGRA(r,g,b,a) (U_RGBQUAD){b,g,r,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) ((U_RGBQUAD)rgb).Red //!< Color BGR Get Red Macro.
+#define U_BGRAGetG(rgb) ((U_RGBQUAD)rgb).Green //!< Color BGR Get Green Macro.
+#define U_BGRAGetB(rgb) ((U_RGBQUAD)rgb).Blue //!< Color BGR Get Blue Macro.
+#define U_BGRAGetA(rgb) ((U_RGBQUAD)rgb).Reserved //!< Color BGR Get A/reserved Macro.
+
+#define U_PALETTERGB(r,g,b) U_RGB(r,g,b,0x02)) //!< Set any Palette RGB color.
+#define U_PALETTEINDEX(i) ((U_COLORREF)(0x01000000 | (uint16_t)(i)))\
+ //!< Get RGB from Palette by index.
+
+// Color U_RGB(A), byte order lo to hi: {R,G,B,A} corresponding to U_COLORREF. Set/Get Macros.
+// 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 U_RGB(r,g,b) (U_COLORREF){r,g,b,0} //!< Set any RGB color with an {r,g,b} triplet
+#define U_RGBA(r,g,b,a) (U_COLORREF){r,g,b,a} //!< Set any RGBA color with an {r,g,b,a} quad
+#define U_RGBAGetR(rgb) ((U_COLORREF)rgb).Red //!< Color RGB Get Red Macro.
+#define U_RGBAGetG(rgb) ((U_COLORREF)rgb).Green //!< Color RGB Get Green Macro.
+#define U_RGBAGetB(rgb) ((U_COLORREF)rgb).Blue //!< Color RGB Get Blue Macro.
+#define U_RGBAGetA(rgb) ((U_COLORREF)rgb).Reserved //!< Color RGBA Get A/reserved Macro.
+
+// 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 macro
+#define UP4(A) (4 * ((A + 3 ) / 4)) //!< Round up to nearest multiple of 4
+/** @} */
+
+typedef float U_FLOAT;
+
+typedef uint32_t U_CBBITS; // Describes byte count of TYPE
+typedef uint32_t U_CBBITSMSK;
+typedef uint32_t U_CBBITSSRC;
+typedef uint32_t U_CBBMI;
+typedef uint32_t U_CBBMIMSK;
+typedef uint32_t U_CBBMISRC;
+typedef uint32_t U_CBDATA;
+typedef uint32_t U_CBNAME;
+typedef uint32_t U_CBPLENTRIES;
+typedef uint32_t U_CBPXLFMT;
+typedef uint32_t U_CBRGNDATA;
+typedef uint32_t U_CBSTR; // bytes in an 8 or 16 bit string
+
+typedef uint32_t U_OFFBITS; // Describes byte offset to TYPE, always measured from the start of the RECORD (not the struct)
+typedef uint32_t U_OFFBITSMSK;
+typedef uint32_t U_OFFBITSSRC;
+typedef uint32_t U_OFFBMI;
+typedef uint32_t U_OFFBMIMSK;
+typedef uint32_t U_OFFBMISRC;
+typedef uint32_t U_OFFDATA;
+typedef uint32_t U_OFFDESC;
+typedef uint32_t U_OFFDX;
+typedef uint32_t U_OFFPLENTRIES;
+typedef uint32_t U_OFFPXLFMT;
+typedef uint32_t U_OFFSTR; // 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)
+
+
+/**
+ \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, *PU_SIZE, *PU_SIZEL;
+
+/**
+ \brief Used for any generic pair of floats
+ Microsoft name: (none)
+*/
+typedef struct {
+ float x; //!< X value
+ float y; //!< Y value
+} U_PAIRF, *PU_PAIRF;
+
+/**
+ \brief Used for any generic pair of uint32_t
+ Microsoft name: POINT Object
+*/
+typedef struct {
+ int32_t x; //!< X value
+ int32_t y; //!< Y value
+} U_PAIR, *PU_PAIR, U_POINT, *PU_POINT, U_POINTL, *PU_POINTL;
+
+/**
+ \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;
+
+/**
+ \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
+*/
+typedef struct {
+ int32_t left; //!< left coordinate
+ int32_t top; //!< top coordinate
+ int32_t right; //!< right coordinate
+ int32_t bottom; //!< bottom coordinate
+} U_RECT, *PU_RECT,
+ U_RECTL, *PU_RECTL;
+
+#define U_RCL_DEF (U_RECTL){0,0,-1,-1} //!< Use this when no bounds are needed.
+
+/* ************************************************************
+ EMF structures OTHER than those corresponding to complete U_EMR_* records
+ ************************************************************ */
+
+/**
+ \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;
+
+/**
+ \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;
+
+/**
+ \brief For U_POINT28_4 x and y fields.
+ 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;
+
+/**
+ \brief For U_LCS_GAMMARGB lcsGamma* fields
+ Microsoft name:(unknown) Object
+*/
+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;
+
+/**
+ \brief For U_LOGCOLORSPACEA and U_LOGCOLORSPACEW lcsGammaRGB field
+ Microsoft name:(unknown) Object
+*/
+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;
+
+/**
+ \brief For U_EMRSETOLORADJUSTMENT ColorAdjustment field
+ Note, range constants are: RGB_GAMMA_[MIN|MAX],REFERENCE_[WHITE|BLACK]_[MIN|MAX],COLOR_ADJ_[MIN|MAX]
+ Microsoft name: ColorAdjustment Object
+*/
+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;
+
+/**
+ \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;
+
+/**
+ \brief For U_EMR_COMMENT_MULTIFORMATS record, where an array of these is used
+ 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;
+
+/**
+ \brief For U_EMR[POLY]EXTTEXTOUT[A|W] emrtext field
+ 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.
+ Microsoft name: EmrText Object
+ 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;
+
+/**
+ \brief For U_EPS_DATA Points field
+ Microsoft name: Point28_4 Object
+*/
+typedef struct {
+ U_BITFIX28_4 x; //!< X coordinate
+ U_BITFIX28_4 y; //!< Y coordinate
+} U_POINT28_4, *PU_POINT28_4;
+
+/**
+ \brief For embedding EPS in EMF via U_EMRFORMAT offData array in U_EMR_COMMENT_MULTIFORMATS
+ 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;
+
+/**
+ \brief For GRADIENT_[TRIANGLE|U_RECT]
+ Microsoft name: TriVertex Object
+*/
+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;
+
+
+/**
+ \brief For U_EMRGRADIENTFILL GradObj field
+
+ 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.
+
+ Microsoft name: GradientTriangle Object
+*/
+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;
+
+/**
+ \brief For U_EMRGRADIENTFILL GradObj field
+ 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;
+
+/**
+ \brief For U_EMRCREATEBRUSHINDIRECT lb field
+ 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, *PU_LOGBRUSH;
+typedef U_LOGBRUSH U_PATTERN, *PU_PATTERN;
+
+/**
+ \brief For U_LOGFONT_PANOSE elfLogFont field
+ 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 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;
+
+#if 0
+// Do EMF files ever use any of these???
+
+// Microsoft name: BITMAPV4HEADER Object
+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, *PU_BITMAPV4HEADER; //!< For ?
+
+// Microsoft name: BITMAPV5HEADER Object
+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, *PU_BITMAPV5HEADER; //!< For ?
+
+// Microsoft name: BITMAPCOREHEADER Object
+typedef struct {
+ uint32_t bcSize; //!< Structure size in bytes
+ uint16_t bcWidth; //!< Bitmap width in pixels
+ uint16_t bcHeight; //!< Bitmap height in pixels
+ uint16_t bcPlanes; //!< Planes (must be 1)
+ uint16_t bcBitCount; //!< BitCount Enumeration
+} U_BITMAPCOREHEADER, *PU_BITMAPCOREHEADER; //!< For U_BITMAPCOREINFO
+
+// Microsoft name: BITMAPCOREINFO Object
+// Description of a simple Device Independent Bitmap (DIB) - no compression or color maps
+typedef struct {
+ U_BITMAPCOREHEADER bmciHeader; //!< Geometry and pixel properties
+ U_RGBTRIPLE bmciColors[1]; //!< Color table
+} U_BITMAPCOREINFO, *PU_BITMAPCOREINFO; //!< For ?
+
+// Microsoft name: RGBTRIPLE Object
+// NOTE that the color order is BGR, even though the name is RGB!
+typedef struct {
+ uint8_t rgbtBlue; //!< Blue color (0-255)
+ uint8_t rgbtGreen; //!< Green color (0-255)
+ uint8_t rgbtRed; //!< Red color (0-255)
+} U_RGBTRIPLE, *PU_RGBTRIPLE; //!< For U_BITMAPCOREINFO bmciColors field
+
+
+#endif // elements possibly never used by an EMF file
+
+/**
+ \brief For U_EMR_* OffBmi* fields
+ Description of a Bitmap which in some cases is a Device Independent Bitmap (DIB)
+ Microsoft name: BITMAPINFO Object
+*/
+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;
+
+/**
+ \brief U_EMRALPHABLEND Blend field
+*/
+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;
+#
+
+/**
+ 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;
+
+/** First two fields of all EMF records
+ 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;
+
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ U_PAIR pair; //!< pair of 32 bit values
+} U_EMRGENERICPAIR, *PU_EMRGENERICPAIR;
+
+
+
+
+// ***********************************************************************************
+// The following have U_EMR_# records
+
+/* Index 1 */
+/**
+ \brief The firstU_ENHMETARECORD record in the metafile.
+
+ 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 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 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
+ //!< Record may include optional Description, UTF-16BE string
+ //!< Record may include optional PxlFmtDescriptor, U_PIXELFORMATDESCRIPTOR
+} U_EMRHEADER, *PU_EMRHEADER;
+
+/* Index 2,3,4,5,6*/
+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, *PU_EMRPOLYBEZIER,
+ U_EMRPOLYGON, *PU_EMRPOLYGON,
+ U_EMRPOLYLINE, *PU_EMRPOLYLINE,
+ U_EMRPOLYBEZIERTO, *PU_EMRPOLYBEZIERTO,
+ U_EMRPOLYLINETO, *PU_EMRPOLYLINETO;
+
+/* Index 7,8 */
+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)
+// This will appear somewhere but is not really part of the core structure.
+// U_POINTL aptl[1]; //!< array of points
+} U_EMRPOLYPOLYLINE, *PU_EMRPOLYPOLYLINE,
+ U_EMRPOLYPOLYGON, *PU_EMRPOLYPOLYGON;
+
+/* Index 9,11 (numbers interleave with next one) */
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ U_SIZEL szlExtent; //!< H & V extent in logical units
+} U_EMRSETWINDOWEXTEX, *PU_EMRSETWINDOWEXTEX,
+ U_EMRSETVIEWPORTEXTEX, *PU_EMRSETVIEWPORTEXTEX;
+
+/* Index 10,12,13 */
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ U_POINTL ptlOrigin; //!< H & V origin in logical units
+} U_EMRSETWINDOWORGEX, *PU_EMRSETWINDOWORGEX,
+ U_EMRSETVIEWPORTORGEX, *PU_EMRSETVIEWPORTORGEX,
+ U_EMRSETBRUSHORGEX, *PU_EMRSETBRUSHORGEX;
+
+/* Index 14
+*/
+/**
+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 appear these fields:
+
+ 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;
+
+/* Index 15 */
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ U_POINTL ptlPixel; //!< Pixel coordinates (logical)
+ U_COLORREF crColor; //!< Pixel color
+} U_EMRSETPIXELV, *PU_EMRSETPIXELV;
+
+/* Index 16 */
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ uint32_t dwFlags; //!< must be 1
+} U_EMRSETMAPPERFLAGS, *PU_EMRSETMAPPERFLAGS;
+
+/* Index 17,18,19,20,21,22,67,98,115 */
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ uint32_t iMode; //!< enumeration varies with type
+} U_EMRSETMAPMODE, *PU_EMRSETMAPMODE, //!< MapMode enumeration
+ U_EMRSETBKMODE, *PU_EMRSETBKMODE, //!< BackgroundMode Enumeration
+ U_EMRSETPOLYFILLMODE, *PU_EMRSETPOLYFILLMODE, //!< PolygonFillMode Enumeration
+ U_EMRSETROP2, *PU_EMRSETROP2, //!< Binary Raster Operation Enumeration
+ U_EMRSETSTRETCHBLTMODE, *PU_EMRSETSTRETCHBLTMODE, //!< StretchMode Enumeration
+ U_EMRSETTEXTALIGN, *PU_EMRSETTEXTALIGN, //!< TextAlignment enumeration
+ U_EMRSELECTCLIPPATH, *PU_EMRSELECTCLIPPATH, //!< RegionMode Enumeration
+ U_EMRSETICMMODE, *PU_ERMSETICMMODE, //!< ICMMode Enumeration
+ U_EMRSETLAYOUT, *PU_EMRSETLAYOUT; //!< Mirroring Enumeration
+
+/* Index 23 */
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ U_COLORADJUSTMENT ColorAdjustment; //!< Color Adjustment
+} U_EMRSETCOLORADJUSTMENT, *PU_EMRSETCOLORADJUSTMENT;
+
+/* Index 24, 25 */
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ U_COLORREF crColor; //!< Color
+} U_EMRSETTEXTCOLOR, *PU_EMRSETTEXTCOLOR,
+ U_EMRSETBKCOLOR, *PU_EMRSETBKCOLOR;
+
+/* Index 26 */
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ U_POINTL ptlOffset; //!< Clipping region
+} U_EMROFFSETCLIPRGN, *PU_EMROFFSETCLIPRGN;
+
+/* Index 27, 54 */
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ U_POINTL ptl; //!< Point coordinates
+} U_EMRMOVETOEX, *PU_EMRMOVETOEX,
+ U_EMRLINETO, *PU_EMRLINETO;
+
+/* Index 28,33,52,59,60,61,65,66,68 */
+typedef struct {
+ U_EMR emr; //!< U_EMR
+}
+ U_EMRSETMETARGN, *PU_EMRSETMETARGN,
+ U_EMRSAVEDC, *PU_EMRSAVEDC,
+ U_EMRREALIZEPALETTE, *PU_EMRREALIZEPALETTE,
+ U_EMRBEGINPATH, *PU_EMRBEGINPATH,
+ U_EMRENDPATH, *PU_EMRENDPATH,
+ U_EMRCLOSEFIGURE, *PU_EMRCLOSEFIGURE,
+ U_EMRFLATTENPATH, *PU_EMRFLATTENPATH,
+ U_EMRWIDENPATH, *PU_EMRWIDENPATH,
+ U_EMRABORTPATH, *PU_EMRABORTPATH;
+
+/* Index 29,30 */
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ U_RECTL rclClip; //!< Clipping Region
+} U_EMREXCLUDECLIPRECT, *PU_EMREXCLUDECLIPRECT,
+ U_EMRINTERSECTCLIPRECT, *PU_EMRINTERSECTCLIPRECT;
+
+/* Index 31,32 */
+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, *PU_EMRSCALEVIEWPORTEXTEX,
+ U_EMRSCALEWINDOWEXTEX, *PU_EMRSCALEWINDOWEXTEX;
+
+/* Index 33 (see 28) */
+
+/* Index 34 */
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ int32_t iRelative; //!< DC to restore. -1 is preceding
+} U_EMRRESTOREDC, *PU_EMRRESTOREDC;
+
+/* Index 35 */
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ U_XFORM xform; //!< Transform
+} U_EMRSETWORLDTRANSFORM, *PU_EMRSETWORLDTRANSFORM;
+
+/* Index 36 */
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ U_XFORM xform; //!< Transform
+ uint32_t iMode; //!< ModifyWorldTransformMode Enumeration
+} U_EMRMODIFYWORLDTRANSFORM, *PU_EMRMODIFYWORLDTRANSFORM;
+
+/* Index 37,40 */
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ uint32_t ihObject; //!< Number of a stock or created object
+} U_EMRDELETEOBJECT, *PU_EMRDELETEOBJECT,
+ U_EMRSELECTOBJECT, *PU_EMRSELECTOBJECT;
+
+/* Index 38 */
+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;
+
+/* Index 39 */
+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;
+
+/* Index 40 see 37 */
+
+/* Index 41 */
+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;
+
+/* Index 42,43 */
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ U_RECTL rclBox; //!< bounding rectangle in logical units
+} U_EMRELLIPSE, *PU_EMRELLIPSE,
+ U_EMRRECTANGLE, *PU_EMRRECTANGLE;
+
+/* Index 44 */
+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;
+
+/* Index 45, 46 ,47, 55 */
+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, *PU_EMRARC,
+ U_EMRCHORD, *PU_EMRCHORD,
+ U_EMRPIE, *PU_EMRPIE,
+ U_EMRARCTO, *PU_EMRARCTO;
+
+/* Index 48 */
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ uint32_t ihPal; //!< Index of a Palette object in the EMF object table
+} U_EMRSELECTPALETTE, *PU_EMRSELECTPALETTE;
+
+/* Index 49 */
+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
+} U_EMRCREATEPALETTE, *PU_EMRCREATEPALETTE;
+
+/* Index 50 */
+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;
+
+/* Index 51 */
+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;
+
+/* Index 52 (see 28) */
+
+/* Index 53 */
+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;
+
+/* Index 54 (see 27) */
+
+/* Index 55 (see 45) */
+
+/* Index 56 */
+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
+ uint8_t abTypes[1]; //!< Array of Point Enumeration
+} U_EMRPOLYDRAW, *PU_EMRPOLYDRAW;
+
+/* Index 57 */
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ uint32_t iArcDirection; //!< ArcDirection Enumeration
+} U_EMRSETARCDIRECTION, *PU_EMRSETARCDIRECTION;
+
+/* Index 58
+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;
+
+/* Index 59,60,61 (see 28) */
+
+/* Index 62,63,64 */
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ U_RECTL rclBounds; //!< Bounding rectangle in device units
+} U_EMRFILLPATH, *PU_EMRFILLPATH,
+ U_EMRSTROKEANDFILLPATH, *PU_EMRSTROKEANDFILLPATH,
+ U_EMRSTROKEPATH, *PU_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 */
+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; //!< AKA GDICOMMENT
+
+/* Index 71 */
+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;
+
+/* Index 72 */
+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;
+
+/* Index 73,74 */
+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, *PU_EMRINVERTRGN,
+ U_EMRPAINTRGN, *PU_EMRPAINTRGN;
+
+/* Index 75 */
+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;
+
+/* Index 76 */
+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;
+
+/* Index 77 */
+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;
+
+/* Index 78 */
+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;
+
+/* Index 79 */
+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;
+
+/* Index 80 */
+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;
+
+/* Index 81 */
+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;
+
+/* Index 82 */
+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;
+
+/* Index 83,84 */
+/**
+Variable and optional fields may follow core structure in record:
+
+ 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_RECTL rcl; 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 from the start of the RECORD
+// Record may include optional Dx, character spacing, array of uint32_t
+} U_EMREXTTEXTOUTA, *PU_EMREXTTEXTOUTA,
+ U_EMREXTTEXTOUTW, *PU_EMREXTTEXTOUTW;
+
+/* Index 85,86,87,88,89 */
+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,*PU_EMRPOLYBEZIER16,
+ U_EMRPOLYGON16,*PU_EMRPOLYGON16,
+ U_EMRPOLYLINE16,*PU_EMRPOLYLINE16,
+ U_EMRPOLYBEZIERTO16,*PU_EMRPOLYBEZIERTO16,
+ U_EMRPOLYLINETO16,*PU_EMRPOLYLINETO16;
+
+/* Index 90,91 */
+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)
+// This will appear somewhere but is not really part of the core structure.
+// U_POINT16 apts[1]; //!< array of point16
+} U_EMRPOLYPOLYLINE16,*PU_EMRPOLYPOLYLINE16,
+ U_EMRPOLYPOLYGON16,*PU_EMRPOLYPOLYGON16;
+
+/* Index 92 */
+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
+ uint8_t abTypes[1]; //!< Array of Point Enumeration
+} U_EMRPOLYDRAW16,*PU_EMRPOLYDRAW16;
+
+/* Index 93 */
+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;
+
+/* Index 94 */
+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;
+
+/* Index 95 */
+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;
+
+/* Index 96.97 */
+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, *PU_EMRPOLYTEXTOUTA,
+ U_EMRPOLYTEXTOUTW, *PU_EMRPOLYTEXTOUTW;
+
+/* Index 98 (see 17) */
+
+/* Index 99 */
+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;
+
+/* Index 100,101 */
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ uint32_t ihCS; //!< Index of object in EMF object table
+} U_EMRDELETECOLORSPACE, *PU_EMRDELETECOLORSPACE,
+ U_EMRSETCOLORSPACE, *PU_EMRSETCOLORSPACE;
+
+/* Index 102 */
+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;
+
+/* Index 103 */
+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;
+
+/* Index 104 */
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ U_PIXELFORMATDESCRIPTOR pfd; //!< PixelFormatDescriptor
+} U_EMRPIXELFORMAT, *PU_EMRPIXELFORMAT;
+
+/* Index 105 */
+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;
+
+/* Index 106 */
+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;
+
+/* Index 107 (not implemented ) */
+
+/* Index 108 */
+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;
+
+/* Index 109 (not implemented ) */
+
+/* Index 110 */
+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
+ uint8_t Data[1]; //!< Data for printer driver
+} U_EMRNAMEDESCAPE, *PU_EMRNAMEDESCAPE;
+
+/* Index 111-113 (not implemented ) */
+
+/* Index 114 */
+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;
+
+/* Index 115 (see 17) */
+
+/* Index 116 */
+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;
+
+/* Index 117 (not a defined U_EMR record type ) */
+
+/* Index 118 */
+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)
+//parts that are required but which are not included in the core structure
+// 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)
+} U_EMRGRADIENTFILL, *PU_EMRGRADIENTFILL;
+
+/* Index 119,120 (not implemented ) */
+
+/* Index 121 */
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ uint32_t dwAction; //!< ColorSpace Enumeration
+ uint32_t dwFlags; //!< ColorMatchToTarget Enumeration
+ U_CBNAME cbName; //!< Number of bytes in 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;
+
+/* Index 122 */
+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;
+
+// ************************************************************************************************
+// Utility function structures
+
+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, which here 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, but 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;
+ double M12;
+ double M21;
+ double M22;
+} U_MAT2X2, *PU_MAT2X2;
+
+// ************************************************************************************************
+// Prototypes
+
+int memprobe(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);
+
+
+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);
+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);
+uint16_t U_Utf16le(const uint16_t src);
+int U_Utf16leEdit(uint16_t *src, uint16_t old, uint16_t sub);
+uint32_t *dx_set(int32_t height, uint32_t weight, uint32_t members);
+char *U_strdup(const char *s);
+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 RGBA_to_DIB( char **px, uint32_t *cbPx, PU_RGBQUAD *ct, int *numCt,
+ char *rgba_px, int w, int h, int stride, uint32_t colortype, int use_ct, int invert);
+int get_DIB_params( void *pEmr, uint32_t offBitsSrc, uint32_t offBmiSrc,
+ char **px, PU_RGBQUAD *ct, uint32_t *numCt,
+ uint32_t *width, uint32_t *height, uint32_t *colortype, uint32_t *invert );
+int DIB_to_RGBA(char *px, PU_RGBQUAD ct, int numCt,
+ char **rgba_px, int w, int h, uint32_t colortype, int use_ct, int invert);
+
+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);
+
+int htable_create(uint32_t initsize, uint32_t chunksize, EMFHANDLES **eht);
+int htable_delete(uint32_t *ih, EMFHANDLES *eht);
+int htable_insert(uint32_t *ih, EMFHANDLES *eht);
+int htable_free(EMFHANDLES **eht);
+
+U_RECTL rectl_set(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 colorref_set(uint8_t red, uint8_t green, uint8_t blue);
+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(char *emr);
+
+char *textcomment_set(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 *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);
+char *U_EMRCREATEDIBPATTERNBRUSHPT_set(const uint32_t ihBrush, const uint32_t iUsage, const PU_BITMAPINFO Bmi);
+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);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _UEMF_ */
diff -rNu3 src/extension/internal/uemf_print.c src/extension/internal/uemf_print.c
--- src/extension/internal/uemf_print.c 1969-12-31 16:00:00.000000000 -0800
+++ src/extension/internal/uemf_print.c 2012-08-07 12:44:46.000000000 -0700
@@ -0,0 +1,2577 @@
+/**
+ @file uemf_print.c Functions for printing EMF records
+*/
+
+/*
+File: uemf_print.c
+Version: 0.0.4
+Date: 25-JUL-2012
+Author: David Mathog, Biology Division, Caltech
+email: mathog@caltech.edu
+Copyright: 2012 David Mathog and California Institute of Technology (Caltech)
+*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include
+#include
+#include
+#include "uemf.h"
+
+/**
+ \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 U_POINT16 object
+ \param pt U_POINT16 object
+*/
+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 tv 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 tv 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 );
+ 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 U_BITMAPINFOHEADER object.
+ \param Bmi U_BITMAPINFOHEADER object
+*/
+void bitmapinfoheader_print(
+ U_BITMAPINFOHEADER Bmi
+ ){
+ printf("biSize:%u " ,Bmi.biSize );
+ printf("biWidth:%d " ,Bmi.biWidth );
+ printf("biHeight:%d " ,Bmi.biHeight );
+ printf("biPlanes:%u " ,Bmi.biPlanes );
+ printf("biBitCount:%u " ,Bmi.biBitCount );
+ printf("biCompression:%u " ,Bmi.biCompression );
+ printf("biSizeImage:%u " ,Bmi.biSizeImage );
+ printf("biXPelsPerMeter:%d " ,Bmi.biXPelsPerMeter);
+ printf("biYPelsPerMeter:%d " ,Bmi.biYPelsPerMeter);
+ printf("biClrUsed:%u " ,Bmi.biClrUsed );
+ printf("biClrImportant:%u " ,Bmi.biClrImportant );
+}
+
+
+/**
+ \brief Print a Pointer to a U_BITMAPINFO object.
+ \param Bmi Pointer to a U_BITMAPINFO object
+*/
+void bitmapinfo_print(
+ PU_BITMAPINFO Bmi
+ ){
+ int i;
+ PU_RGBQUAD BmiColors;
+ PU_BITMAPINFOHEADER BmiHeader = &(Bmi->bmiHeader);
+ printf("BmiHeader: "); bitmapinfoheader_print(*BmiHeader);
+ if(BmiHeader->biClrUsed){
+ BmiColors = (PU_RGBQUAD) ((char *)Bmi + sizeof(U_BITMAPINFOHEADER));
+ for(i=0; ibiClrUsed; i++){
+ printf("%d:",i); rgbquad_print(BmiColors[i]);
+ }
+ }
+}
+
+/**
+ \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
+ ){
+ 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;ielpNumEntries;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:%u " ,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;ipalNumEntries;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 rgd pointer to a U_RGNDATA object.
+*/
+void rgndata_print(
+ PU_RGNDATA rd
+ ){
+ int i;
+ PU_RECTL rects;
+ printf("rdh:"); rgndataheader_print(rd->rdh );
+ if(rd->rdh.nCount){
+ rects = (PU_RECTL) &(rd->Buffer);
+ for(i=0;irdh.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:%u " ,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.
+ \return U_PIXELFORMATDESCRIPTOR object
+ \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
+*/
+void pixelformatdescriptor_print(
+ U_PIXELFORMATDESCRIPTOR pfd
+ ){
+ printf("nSize:%u " ,pfd.nSize );
+ printf("nVersion:%u " ,pfd.nVersion );
+ printf("dwFlags:%u " ,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 type 0 for 8 bit character, anything else for 16
+*/
+void emrtext_print(
+ char *emt,
+ char *record,
+ int type
+ ){
+ 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){
+ printf("string8:<%s> ",record + pemt->offString);
+ }
+ else {
+ string = U_Utf16leToUtf8((uint16_t *)(record + pemt->offString), pemt->nChars, NULL);
+ printf("string16:<%s> ",string);
+ free(string);
+ }
+ }
+ printf("fOptions:%u " ,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; inChars; 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.
+
+ void core5_print(char *name, char *contents, int recnum, size_t off)
+
+ The exceptions:
+ void core3_print(char *name, char *label, char *contents, int recnum, size_t off)
+ void core7_print(char *name, char *field1, char *field2, char *contents, int recnum, size_t off)
+ void core8_print(char *name, char *contents, int recnum, size_t off, int type)
+
+
+*********************************************************************************************** */
+
+// all core*_print call this, U_EMRSETMARGN_print 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
+void core5_print(char *name, char *contents, int recnum, size_t off){
+ PU_ENHMETARECORD lpEMFR = (PU_ENHMETARECORD)(contents + off);
+ printf("%-30srecord:%5d type:%3d offset:%8d size:%8d\n",name,recnum,lpEMFR->iType,(int) off,lpEMFR->nSize);
+}
+
+// Functions with the same form starting with U_EMRPOLYBEZIER_print
+void core1_print(char *name, char *contents, int recnum, size_t off){
+ int i;
+ PU_EMRPOLYLINETO pEmr = (PU_EMRPOLYLINETO) (contents + off);
+ core5_print(name, contents, recnum, off);
+ printf(" rclBounds: "); rectl_print(pEmr->rclBounds); printf("\n");
+ printf(" cptl: %d\n",pEmr->cptl );
+ printf(" Points: ");
+ for(i=0;icptl; i++){
+ printf("[%d]:",i); pointl_print(pEmr->aptl[i]);
+ }
+ printf("\n");
+}
+
+// Functions with the same form starting with U_EMRPOLYPOLYLINE_print
+void core2_print(char *name, char *contents, int recnum, size_t off){
+ int i;
+ PU_EMRPOLYPOLYGON pEmr = (PU_EMRPOLYPOLYGON) (contents + off);
+ core5_print(name, contents, recnum, off);
+ printf(" rclBounds: "); rectl_print(pEmr->rclBounds); printf("\n");
+ printf(" nPolys: %d\n",pEmr->nPolys );
+ printf(" cptl: %d\n",pEmr->cptl );
+ printf(" Counts: ");
+ for(i=0;inPolys; 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: ");
+ for(i=0;icptl; i++){
+ printf(" [%d]:",i); pointl_print(paptl[i]);
+ }
+ printf("\n");
+}
+
+
+// Functions with the same form starting with U_EMRSETMAPMODE_print
+void core3_print(char *name, char *label, char *contents, int recnum, size_t off){
+ PU_EMRSETMAPMODE pEmr = (PU_EMRSETMAPMODE)(contents + off);
+ core5_print(name, contents, recnum, off);
+ 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(char *name, char *contents, int recnum, size_t off){
+ PU_EMRELLIPSE pEmr = (PU_EMRELLIPSE)( contents + off);
+ core5_print(name, contents, recnum, off);
+ printf(" rclBox: "); rectl_print(pEmr->rclBox); printf("\n");
+}
+
+// Functions with the same form starting with U_EMRPOLYBEZIER16_print
+void core6_print(char *name, char *contents, int recnum, size_t off){
+ int i;
+ PU_EMRPOLYBEZIER16 pEmr = (PU_EMRPOLYBEZIER16) (contents + off);
+ core5_print(name, contents, recnum, off);
+ printf(" rclBounds: "); rectl_print(pEmr->rclBounds); printf("\n");
+ printf(" cpts: %d\n",pEmr->cpts );
+ printf(" Points: ");
+ PU_POINT16 papts = (PU_POINT16)(&(pEmr->apts));
+ for(i=0; icpts; 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(char *name, char *field1, char *field2, char *contents, int recnum, size_t off){
+ PU_EMRGENERICPAIR pEmr = (PU_EMRGENERICPAIR) (contents + off);
+ core5_print(name, contents, recnum, off);
+ 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(char *name, char *contents, int recnum, size_t off, int type){
+ PU_EMREXTTEXTOUTA pEmr = (PU_EMREXTTEXTOUTA) (contents + off);
+ core5_print(name, contents, recnum, off);
+ 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 + off + sizeof(U_EMREXTTEXTOUTA) - sizeof(U_EMRTEXT),contents + off,type);
+ printf("\n");
+}
+
+// Functions that take a rect and a pair of points, starting with U_EMRARC_print
+void core9_print(char *name, char *contents, int recnum, size_t off){
+ PU_EMRARC pEmr = (PU_EMRARC) (contents + off);
+ core5_print(name, contents, recnum, off);
+ 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(char *name, char *contents, int recnum, size_t off){
+ int i;
+ PU_EMRPOLYPOLYLINE16 pEmr = (PU_EMRPOLYPOLYLINE16) (contents + off);
+ core5_print(name, contents, recnum, off);
+ printf(" rclBounds: "); rectl_print(pEmr->rclBounds); printf("\n");
+ printf(" nPolys: %d\n",pEmr->nPolys );
+ printf(" cpts: %d\n",pEmr->cpts );
+ printf(" Counts: ");
+ for(i=0;inPolys; i++){
+ printf(" [%d]:%d ",i,pEmr->aPolyCounts[i] );
+ }
+ printf("\n");
+ printf(" Points: ");
+ PU_POINT16 papts = (PU_POINT16)((char *)pEmr->aPolyCounts + sizeof(uint32_t)* pEmr->nPolys);
+ for(i=0; icpts; 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(char *name, char *contents, int recnum, size_t off){
+ int i,roff;
+ PU_EMRINVERTRGN pEmr = (PU_EMRINVERTRGN) (contents + off);
+ core5_print(name, contents, recnum, off);
+ printf(" rclBounds: "); rectl_print(pEmr->rclBounds); printf("\n");
+ printf(" cbRgnData: %d\n",pEmr->cbRgnData);
+ // This one is a pain since each RGNDATA may be a different size, so it isn't possible to index through them.
+ roff=0;
+ i=1;
+ char *prd = (char *) &(pEmr->RgnData);
+ while(roff + 28 < pEmr->emr.nSize){ // up to the end of the record
+ printf(" RegionData:%d",i);
+ rgndata_print((PU_RGNDATA) (prd + roff));
+ roff += (((PU_RGNDATA)prd)->rdh.dwSize + ((PU_RGNDATA)prd)->rdh.nRgnSize - 16);
+ printf("\n");
+ }
+}
+
+
+// common code for U_EMRCREATEMONOBRUSH_print and U_EMRCREATEDIBPATTERNBRUSHPT_print,
+void core12_print(char *name, char *contents, int recnum, size_t off){
+ PU_EMRCREATEMONOBRUSH pEmr = (PU_EMRCREATEMONOBRUSH) (contents + off);
+ core5_print(name, contents, recnum, off);
+ 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((PU_BITMAPINFO)(contents + off + pEmr->offBmi));
+ 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(char *name, char *contents, int recnum, size_t off){
+ PU_EMRALPHABLEND pEmr = (PU_EMRALPHABLEND) (contents + off);
+ core5_print(name, contents, recnum, off);
+ 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((PU_BITMAPINFO)(contents + off + pEmr->offBmiSrc));
+ 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
+ \param recnum number of this record in contents
+ \param off offset to this record in contents
+*/
+void U_EMRNOTIMPLEMENTED_print(char *name, char *contents, int recnum, size_t off){
+ PU_ENHMETARECORD lpEMFR = (PU_ENHMETARECORD)(contents + off);
+ printf("%-30srecord:%5d type:%3d offset:%8d size:%8d\n",name,recnum,lpEMFR->iType,(int) off,lpEMFR->nSize);
+ 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
+ \param recnum number of this record in contents
+ \param off offset to this record in contents
+*/
+void U_EMRHEADER_print(char *contents, int recnum, size_t off){
+ char *string;
+ int p1len;
+ core5_print("U_EMRHEADER", contents, recnum, off);
+
+ PU_EMRHEADER pEmr = (PU_EMRHEADER)(contents+off);
+ 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){
+ 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);
+ printf(" cbPixelFormat: %d\n", pEmr->cbPixelFormat );
+ printf(" offPixelFormat: %d\n", pEmr->offPixelFormat);
+ if(pEmr->cbPixelFormat){
+ printf(" PFD:");
+ pixelformatdescriptor_print( *(PU_PIXELFORMATDESCRIPTOR) (contents + off + pEmr->offPixelFormat));
+ printf("\n");
+ }
+ printf(" bOpenGL: %d\n",pEmr->bOpenGL );
+ 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
+ \param recnum number of this record in contents
+ \param off offset to this record in contents
+*/
+void U_EMRPOLYBEZIER_print(char *contents, int recnum, size_t off){
+ core1_print("U_EMRPOLYBEZIER", contents, recnum, off);
+}
+
+// U_EMRPOLYGON 3
+/**
+ \brief Print a pointer to a U_EMR_POLYGON 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_EMRPOLYGON_print(char *contents, int recnum, size_t off){
+ core1_print("U_EMRPOLYGON", contents, recnum, off);
+}
+
+
+// U_EMRPOLYLINE 4
+/**
+ \brief Print a pointer to a U_EMR_POLYLINE 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_EMRPOLYLINE_print(char *contents, int recnum, size_t off){
+ core1_print("U_EMRPOLYLINE", contents, recnum, off);
+}
+
+// U_EMRPOLYBEZIERTO 5
+/**
+ \brief Print a pointer to a U_EMR_POLYBEZIERTO 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_EMRPOLYBEZIERTO_print(char *contents, int recnum, size_t off){
+ core1_print("U_EMRPOLYBEZIERTO", contents, recnum, off);
+}
+
+// U_EMRPOLYLINETO 6
+/**
+ \brief Print a pointer to a U_EMR_POLYLINETO 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_EMRPOLYLINETO_print(char *contents, int recnum, size_t off){
+ core1_print("U_EMRPOLYLINETO", contents, recnum, off);
+}
+
+// U_EMRPOLYPOLYLINE 7
+/**
+ \brief Print a pointer to a U_EMR_POLYPOLYLINE 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_EMRPOLYPOLYLINE_print(char *contents, int recnum, size_t off){
+ core2_print("U_EMRPOLYPOLYLINE", contents, recnum, off);
+}
+
+// U_EMRPOLYPOLYGON 8
+/**
+ \brief Print a pointer to a U_EMR_POLYPOLYGON 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_EMRPOLYPOLYGON_print(char *contents, int recnum, size_t off){
+ core2_print("U_EMRPOLYPOLYGON", contents, recnum, off);
+}
+
+// U_EMRSETWINDOWEXTEX 9
+/**
+ \brief Print a pointer to a U_EMR_SETWINDOWEXTEX 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_EMRSETWINDOWEXTEX_print(char *contents, int recnum, size_t off){
+ core7_print("U_EMRSETWINDOWEXTEX", "szlExtent:","",contents, recnum, off);
+}
+
+// U_EMRSETWINDOWORGEX 10
+/**
+ \brief Print a pointer to a U_EMR_SETWINDOWORGEX 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_EMRSETWINDOWORGEX_print(char *contents, int recnum, size_t off){
+ core7_print("U_EMRSETWINDOWORGEX", "ptlOrigin:","",contents, recnum, off);
+}
+
+// U_EMRSETVIEWPORTEXTEX 11
+/**
+ \brief Print a pointer to a U_EMR_SETVIEWPORTEXTEX 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_EMRSETVIEWPORTEXTEX_print(char *contents, int recnum, size_t off){
+ core7_print("U_EMRSETVIEWPORTEXTEX", "szlExtent:","",contents, recnum, off);
+}
+
+// U_EMRSETVIEWPORTORGEX 12
+/**
+ \brief Print a pointer to a U_EMR_SETVIEWPORTORGEX 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_EMRSETVIEWPORTORGEX_print(char *contents, int recnum, size_t off){
+ core7_print("U_EMRSETVIEWPORTORGEX", "ptlOrigin:","",contents, recnum, off);
+}
+
+// U_EMRSETBRUSHORGEX 13
+/**
+ \brief Print a pointer to a U_EMR_SETBRUSHORGEX 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_EMRSETBRUSHORGEX_print(char *contents, int recnum, size_t off){
+ core7_print("U_EMRSETBRUSHORGEX", "ptlOrigin:","",contents, recnum, off);
+}
+
+// U_EMREOF 14
+/**
+ \brief Print a pointer to a U_EMR_EOF 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_EMREOF_print(char *contents, int recnum, size_t off){
+ core5_print("U_EMREOF", contents, recnum, off);
+
+ PU_EMREOF pEmr = (PU_EMREOF)(contents+off);
+ printf(" cbPalEntries: %u\n", pEmr->cbPalEntries );
+ printf(" offPalEntries: %u\n", pEmr->offPalEntries);
+ if(pEmr->cbPalEntries){
+ printf(" PE:");
+ logpalette_print( (PU_LOGPALETTE)(contents + off + 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
+ \param recnum number of this record in contents
+ \param off offset to this record in contents
+*/
+void U_EMRSETPIXELV_print(char *contents, int recnum, size_t off){
+ core5_print("U_EMRSETPIXELV", contents, recnum, off);
+ PU_EMRSETPIXELV pEmr = (PU_EMRSETPIXELV)(contents+off);
+ 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
+ \param recnum number of this record in contents
+ \param off offset to this record in contents
+*/
+void U_EMRSETMAPPERFLAGS_print(char *contents, int recnum, size_t off){
+ core5_print("U_EMRSETMAPPERFLAGS", contents, recnum, off);
+ PU_EMRSETMAPPERFLAGS pEmr = (PU_EMRSETMAPPERFLAGS)(contents+off);
+ printf(" dwFlags: %u\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
+ \param recnum number of this record in contents
+ \param off offset to this record in contents
+*/
+void U_EMRSETMAPMODE_print(char *contents, int recnum, size_t off){
+ core3_print("U_EMRSETMAPMODE", "iMode:", contents, recnum, off);
+}
+
+// U_EMRSETBKMODE 18
+/**
+ \brief Print a pointer to a U_EMR_SETBKMODE 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_EMRSETBKMODE_print(char *contents, int recnum, size_t off){
+ core3_print("U_EMRSETBKMODE", "iMode:", contents, recnum, off);
+}
+
+// U_EMRSETPOLYFILLMODE 19
+/**
+ \brief Print a pointer to a U_EMR_SETPOLYFILLMODE 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_EMRSETPOLYFILLMODE_print(char *contents, int recnum, size_t off){
+ core3_print("U_EMRSETPOLYFILLMODE", "iMode:", contents, recnum, off);
+}
+
+// U_EMRSETROP2 20
+/**
+ \brief Print a pointer to a U_EMR_SETROP2 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_EMRSETROP2_print(char *contents, int recnum, size_t off){
+ core3_print("U_EMRSETROP2", "dwRop:", contents, recnum, off);
+}
+
+// U_EMRSETSTRETCHBLTMODE 21
+/**
+ \brief Print a pointer to a U_EMR_SETSTRETCHBLTMODE 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_EMRSETSTRETCHBLTMODE_print(char *contents, int recnum, size_t off){
+ core3_print("U_EMRSETSTRETCHBLTMODE", "iMode:", contents, recnum, off);
+}
+
+// U_EMRSETTEXTALIGN 22
+/**
+ \brief Print a pointer to a U_EMR_SETTEXTALIGN 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_EMRSETTEXTALIGN_print(char *contents, int recnum, size_t off){
+ core3_print("U_EMRSETTEXTALIGN", "iMode:", contents, recnum, off);
+}
+
+// U_EMRSETCOLORADJUSTMENT 23
+/**
+ \brief Print a pointer to a U_EMR_SETCOLORADJUSTMENT 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_EMRSETCOLORADJUSTMENT_print(char *contents, int recnum, size_t off){
+ core5_print("U_EMRSETCOLORADJUSTMENT", contents, recnum, off);
+ PU_EMRSETCOLORADJUSTMENT pEmr = (PU_EMRSETCOLORADJUSTMENT)(contents+off);
+ 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
+ \param recnum number of this record in contents
+ \param off offset to this record in contents
+*/
+void U_EMRSETTEXTCOLOR_print(char *contents, int recnum, size_t off){
+ core3_print("U_EMRSETTEXTCOLOR", "crColor:", contents, recnum, off);
+}
+
+// U_EMRSETBKCOLOR 25
+/**
+ \brief Print a pointer to a U_EMR_SETBKCOLOR 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_EMRSETBKCOLOR_print(char *contents, int recnum, size_t off){
+ core3_print("U_EMRSETBKCOLOR", "crColor:", contents, recnum, off);
+}
+
+// U_EMROFFSETCLIPRGN 26
+/**
+ \brief Print a pointer to a U_EMR_OFFSETCLIPRGN 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_EMROFFSETCLIPRGN_print(char *contents, int recnum, size_t off){
+ core7_print("U_EMROFFSETCLIPRGN", "ptl:","",contents, recnum, off);
+}
+
+// U_EMRMOVETOEX 27
+/**
+ \brief Print a pointer to a U_EMR_MOVETOEX 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_EMRMOVETOEX_print(char *contents, int recnum, size_t off){
+ core7_print("U_EMRMOVETOEX", "ptl:","",contents, recnum, off);
+}
+
+// U_EMRSETMETARGN 28
+/**
+ \brief Print a pointer to a U_EMR_SETMETARGN 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_EMRSETMETARGN_print(char *contents, int recnum, size_t off){
+ core5_print("U_EMRSETMETARGN", contents, recnum, off);
+}
+
+// U_EMREXCLUDECLIPRECT 29
+/**
+ \brief Print a pointer to a U_EMR_EXCLUDECLIPRECT 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_EMREXCLUDECLIPRECT_print(char *contents, int recnum, size_t off){
+ core4_print("U_EMREXCLUDECLIPRECT", contents, recnum, off);
+}
+
+// U_EMRINTERSECTCLIPRECT 30
+/**
+ \brief Print a pointer to a U_EMR_INTERSECTCLIPRECT 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_EMRINTERSECTCLIPRECT_print(char *contents, int recnum, size_t off){
+ core4_print("U_EMRINTERSECTCLIPRECT", contents, recnum, off);
+}
+
+// U_EMRSCALEVIEWPORTEXTEX 31
+/**
+ \brief Print a pointer to a U_EMR_SCALEVIEWPORTEXTEX 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_EMRSCALEVIEWPORTEXTEX_print(char *contents, int recnum, size_t off){
+ core4_print("U_EMRSCALEVIEWPORTEXTEX", contents, recnum, off);
+}
+
+
+// U_EMRSCALEWINDOWEXTEX 32
+/**
+ \brief Print a pointer to a U_EMR_SCALEWINDOWEXTEX 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_EMRSCALEWINDOWEXTEX_print(char *contents, int recnum, size_t off){
+ core4_print("U_EMRSCALEWINDOWEXTEX", contents, recnum, off);
+}
+
+// U_EMRSAVEDC 33
+/**
+ \brief Print a pointer to a U_EMR_SAVEDC 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_EMRSAVEDC_print(char *contents, int recnum, size_t off){
+ core5_print("U_EMRSAVEDC", contents, recnum, off);
+}
+
+// U_EMRRESTOREDC 34
+/**
+ \brief Print a pointer to a U_EMR_RESTOREDC 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_EMRRESTOREDC_print(char *contents, int recnum, size_t off){
+ core3_print("U_EMRRESTOREDC", "iRelative:", contents, recnum, off);
+}
+
+// U_EMRSETWORLDTRANSFORM 35
+/**
+ \brief Print a pointer to a U_EMR_SETWORLDTRANSFORM 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_EMRSETWORLDTRANSFORM_print(char *contents, int recnum, size_t off){
+ core5_print("U_EMRSETWORLDTRANSFORM", contents, recnum, off);
+ PU_EMRSETWORLDTRANSFORM pEmr = (PU_EMRSETWORLDTRANSFORM)(contents+off);
+ 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
+ \param recnum number of this record in contents
+ \param off offset to this record in contents
+*/
+void U_EMRMODIFYWORLDTRANSFORM_print(char *contents, int recnum, size_t off){
+ core5_print("U_EMRMODIFYWORLDTRANSFORM", contents, recnum, off);
+ PU_EMRMODIFYWORLDTRANSFORM pEmr = (PU_EMRMODIFYWORLDTRANSFORM)(contents+off);
+ 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
+ \param recnum number of this record in contents
+ \param off offset to this record in contents
+*/
+void U_EMRSELECTOBJECT_print(char *contents, int recnum, size_t off){
+ core5_print("U_EMRSELECTOBJECT", contents, recnum, off);
+ PU_EMRSELECTOBJECT pEmr = (PU_EMRSELECTOBJECT)(contents+off);
+ 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
+ \param recnum number of this record in contents
+ \param off offset to this record in contents
+*/
+void U_EMRCREATEPEN_print(char *contents, int recnum, size_t off){
+ core5_print("U_EMRCREATEPEN", contents, recnum, off);
+ PU_EMRCREATEPEN pEmr = (PU_EMRCREATEPEN)(contents+off);
+ 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
+ \param recnum number of this record in contents
+ \param off offset to this record in contents
+*/
+void U_EMRCREATEBRUSHINDIRECT_print(char *contents, int recnum, size_t off){
+ core5_print("U_EMRCREATEBRUSHINDIRECT", contents, recnum, off);
+ PU_EMRCREATEBRUSHINDIRECT pEmr = (PU_EMRCREATEBRUSHINDIRECT)(contents+off);
+ 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
+ \param recnum number of this record in contents
+ \param off offset to this record in contents
+*/
+void U_EMRDELETEOBJECT_print(char *contents, int recnum, size_t off){
+ core5_print("U_EMRDELETEOBJECT", contents, recnum, off);
+ PU_EMRDELETEOBJECT pEmr = (PU_EMRDELETEOBJECT)(contents+off);
+ 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
+ \param recnum number of this record in contents
+ \param off offset to this record in contents
+*/
+void U_EMRANGLEARC_print(char *contents, int recnum, size_t off){
+ core5_print("U_EMRANGLEARC", contents, recnum, off);
+ PU_EMRANGLEARC pEmr = (PU_EMRANGLEARC)(contents+off);
+ 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
+ \param recnum number of this record in contents
+ \param off offset to this record in contents
+*/
+void U_EMRELLIPSE_print(char *contents, int recnum, size_t off){
+ core4_print("U_EMRELLIPSE", contents, recnum, off);
+}
+
+// U_EMRRECTANGLE 43
+/**
+ \brief Print a pointer to a U_EMR_RECTANGLE 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_EMRRECTANGLE_print(char *contents, int recnum, size_t off){
+ core4_print("U_EMRRECTANGLE", contents, recnum, off);
+}
+
+// U_EMRROUNDRECT 44
+/**
+ \brief Print a pointer to a U_EMR_ROUNDRECT 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_EMRROUNDRECT_print(char *contents, int recnum, size_t off){
+ core5_print("U_EMRROUNDRECT", contents, recnum, off);
+ PU_EMRROUNDRECT pEmr = (PU_EMRROUNDRECT)(contents+off);
+ 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
+ \param recnum number of this record in contents
+ \param off offset to this record in contents
+*/
+void U_EMRARC_print(char *contents, int recnum, size_t off){
+ core9_print("U_EMRARC", contents, recnum, off);
+}
+
+// U_EMRCHORD 46
+/**
+ \brief Print a pointer to a U_EMR_CHORD 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_EMRCHORD_print(char *contents, int recnum, size_t off){
+ core9_print("U_EMRCHORD", contents, recnum, off);
+}
+
+// U_EMRPIE 47
+/**
+ \brief Print a pointer to a U_EMR_PIE 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_EMRPIE_print(char *contents, int recnum, size_t off){
+ core9_print("U_EMRPIE", contents, recnum, off);
+}
+
+// U_EMRSELECTPALETTE 48
+/**
+ \brief Print a pointer to a U_EMR_SELECTPALETTE 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_EMRSELECTPALETTE_print(char *contents, int recnum, size_t off){
+ core3_print("U_EMRSELECTPALETTE", "ihPal:", contents, recnum, off);
+}
+
+// U_EMRCREATEPALETTE 49
+/**
+ \brief Print a pointer to a U_EMR_CREATEPALETTE 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_EMRCREATEPALETTE_print(char *contents, int recnum, size_t off){
+ core5_print("U_EMRCREATEPALETTE", contents, recnum, off);
+ PU_EMRCREATEPALETTE pEmr = (PU_EMRCREATEPALETTE)(contents+off);
+ 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
+ \param recnum number of this record in contents
+ \param off offset to this record in contents
+*/
+void U_EMRSETPALETTEENTRIES_print(char *contents, int recnum, size_t off){
+ int i;
+ core5_print("U_EMRSETPALETTEENTRIES", contents, recnum, off);
+ PU_EMRSETPALETTEENTRIES pEmr = (PU_EMRSETPALETTEENTRIES)(contents+off);
+ 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);
+ for(i=0; icEntries; 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
+ \param recnum number of this record in contents
+ \param off offset to this record in contents
+*/
+void U_EMRRESIZEPALETTE_print(char *contents, int recnum, size_t off){
+ core7_print("U_EMRRESIZEPALETTE", "ihPal:","cEntries",contents, recnum, off);
+}
+
+// U_EMRREALIZEPALETTE 52
+/**
+ \brief Print a pointer to a U_EMR_REALIZEPALETTE 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_EMRREALIZEPALETTE_print(char *contents, int recnum, size_t off){
+ core5_print("U_EMRREALIZEPALETTE", contents, recnum, off);
+}
+
+// U_EMREXTFLOODFILL 53
+/**
+ \brief Print a pointer to a U_EMR_EXTFLOODFILL 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_EMREXTFLOODFILL_print(char *contents, int recnum, size_t off){
+ core5_print("U_EMREXTFLOODFILL", contents, recnum, off);
+ PU_EMREXTFLOODFILL pEmr = (PU_EMREXTFLOODFILL)(contents+off);
+ 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
+ \param recnum number of this record in contents
+ \param off offset to this record in contents
+*/
+void U_EMRLINETO_print(char *contents, int recnum, size_t off){
+ core7_print("U_EMRLINETO", "ptl:","",contents, recnum, off);
+}
+
+// U_EMRARCTO 55
+/**
+ \brief Print a pointer to a U_EMR_ARCTO 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_EMRARCTO_print(char *contents, int recnum, size_t off){
+ core9_print("U_EMRARCTO", contents, recnum, off);
+}
+
+// U_EMRPOLYDRAW 56
+/**
+ \brief Print a pointer to a U_EMR_POLYDRAW 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_EMRPOLYDRAW_print(char *contents, int recnum, size_t off){
+ int i;
+ core5_print("U_EMRPOLYDRAW", contents, recnum, off);
+ PU_EMRPOLYDRAW pEmr = (PU_EMRPOLYDRAW)(contents+off);
+ printf(" rclBounds: "); rectl_print( pEmr->rclBounds); printf("\n");
+ printf(" cptl: %d\n",pEmr->cptl );
+ printf(" Points: ");
+ for(i=0;icptl; i++){
+ printf(" [%d]:",i);
+ pointl_print(pEmr->aptl[i]);
+ }
+ printf("\n");
+ printf(" Types: ");
+ for(i=0;icptl; i++){
+ printf(" [%d]:%u ",i,pEmr->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
+ \param recnum number of this record in contents
+ \param off offset to this record in contents
+*/
+void U_EMRSETARCDIRECTION_print(char *contents, int recnum, size_t off){
+ core3_print("U_EMRSETARCDIRECTION","arcDirection:", contents, recnum, off);
+}
+
+// U_EMRSETMITERLIMIT 58
+/**
+ \brief Print a pointer to a U_EMR_SETMITERLIMIT 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_EMRSETMITERLIMIT_print(char *contents, int recnum, size_t off){
+ core3_print("U_EMRSETMITERLIMIT", "eMiterLimit:", contents, recnum, off);
+}
+
+
+// U_EMRBEGINPATH 59
+/**
+ \brief Print a pointer to a U_EMR_BEGINPATH 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_EMRBEGINPATH_print(char *contents, int recnum, size_t off){
+ core5_print("U_EMRBEGINPATH", contents, recnum, off);
+}
+
+// U_EMRENDPATH 60
+/**
+ \brief Print a pointer to a U_EMR_ENDPATH 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_EMRENDPATH_print(char *contents, int recnum, size_t off){
+ core5_print("U_EMRENDPATH", contents, recnum, off);
+}
+
+// U_EMRCLOSEFIGURE 61
+/**
+ \brief Print a pointer to a U_EMR_CLOSEFIGURE 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_EMRCLOSEFIGURE_print(char *contents, int recnum, size_t off){
+ core5_print("U_EMRCLOSEFIGURE", contents, recnum, off);
+}
+
+// U_EMRFILLPATH 62
+/**
+ \brief Print a pointer to a U_EMR_FILLPATH 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_EMRFILLPATH_print(char *contents, int recnum, size_t off){
+ core4_print("U_EMRFILLPATH", contents, recnum, off);
+}
+
+// U_EMRSTROKEANDFILLPATH 63
+/**
+ \brief Print a pointer to a U_EMR_STROKEANDFILLPATH 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_EMRSTROKEANDFILLPATH_print(char *contents, int recnum, size_t off){
+ core4_print("U_EMRSTROKEANDFILLPATH", contents, recnum, off);
+}
+
+// U_EMRSTROKEPATH 64
+/**
+ \brief Print a pointer to a U_EMR_STROKEPATH 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_EMRSTROKEPATH_print(char *contents, int recnum, size_t off){
+ core4_print("U_EMRSTROKEPATH", contents, recnum, off);
+}
+
+// U_EMRFLATTENPATH 65
+/**
+ \brief Print a pointer to a U_EMR_FLATTENPATH 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_EMRFLATTENPATH_print(char *contents, int recnum, size_t off){
+ core5_print("U_EMRFLATTENPATH", contents, recnum, off);
+}
+
+// U_EMRWIDENPATH 66
+/**
+ \brief Print a pointer to a U_EMR_WIDENPATH 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_EMRWIDENPATH_print(char *contents, int recnum, size_t off){
+ core5_print("U_EMRWIDENPATH", contents, recnum, off);
+}
+
+// U_EMRSELECTCLIPPATH 67
+/**
+ \brief Print a pointer to a U_EMR_SELECTCLIPPATH 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_EMRSELECTCLIPPATH_print(char *contents, int recnum, size_t off){
+ core3_print("U_EMRSELECTCLIPPATH", "iMode:", contents, recnum, off);
+}
+
+// U_EMRABORTPATH 68
+/**
+ \brief Print a pointer to a U_EMR_ABORTPATH 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_EMRABORTPATH_print(char *contents, int recnum, size_t off){
+ core5_print("U_EMRABORTPATH", contents, recnum, off);
+}
+
+// U_EMRUNDEF69 69
+#define U_EMRUNDEF69_print(A,B,C) U_EMRNOTIMPLEMENTED_print("U_EMRUNDEF69",A,B,C)
+
+// 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 buffer holding all EMR records
+ \param recnum number of this record in contents
+ \param off offset to this record in contents
+*/
+void U_EMRCOMMENT_print(char *contents, int recnum, size_t off){
+ char *string;
+ core5_print("U_EMRCOMMENT", contents, recnum, off);
+ PU_EMRCOMMENT pEmr = (PU_EMRCOMMENT)(contents+off);
+ printf(" cbData: %d\n",pEmr->cbData );
+ if(pEmr->cbData){ // The data may not be printable, but try it just in case
+ string = malloc(pEmr->cbData + 1);
+ (void)strncpy(string, (char *)&(pEmr->Data), pEmr->cbData);
+ string[pEmr->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
+ \param recnum number of this record in contents
+ \param off offset to this record in contents
+*/
+void U_EMRFILLRGN_print(char *contents, int recnum, size_t off){
+ int i,roff;
+ core5_print("U_EMRFILLRGN", contents, recnum, off);
+ PU_EMRFILLRGN pEmr = (PU_EMRFILLRGN)(contents+off);
+ printf(" rclBounds: "); rectl_print(pEmr->rclBounds); printf("\n");
+ printf(" cbRgnData: %u\n",pEmr->cbRgnData);
+ printf(" ihBrush: %u\n",pEmr->ihBrush);
+ // This one is a pain since each RGNDATA may be a different size, so it isn't possible to index through them.
+ roff=0;
+ i=1;
+ char *prd = (char *) &(pEmr->RgnData);
+ while(roff + 28 < pEmr->emr.nSize){ // up to the end of the record
+ printf(" RegionData[%d]: ",i); rgndata_print((PU_RGNDATA) (prd + roff)); printf("\n");
+ roff += (((PU_RGNDATA)prd)->rdh.dwSize + ((PU_RGNDATA)prd)->rdh.nRgnSize - 16);
+ }
+}
+
+// U_EMRFRAMERGN 72
+/**
+ \brief Print a pointer to a U_EMR_FRAMERGN 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_EMRFRAMERGN_print(char *contents, int recnum, size_t off){
+ int i,roff;
+ core5_print("U_EMRFRAMERGN", contents, recnum, off);
+ PU_EMRFRAMERGN pEmr = (PU_EMRFRAMERGN)(contents+off);
+ 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");
+ // This one is a pain since each RGNDATA may be a different size, so it isn't possible to index through them.
+ roff=0;
+ i=1;
+ char *prd = (char *) &(pEmr->RgnData);
+ while(roff + 28 < pEmr->emr.nSize){ // up to the end of the record
+ printf(" RegionData[%d]: ",i); rgndata_print((PU_RGNDATA) (prd + roff)); printf("\n");
+ roff += (((PU_RGNDATA)prd)->rdh.dwSize + ((PU_RGNDATA)prd)->rdh.nRgnSize - 16);
+ }
+}
+
+// U_EMRINVERTRGN 73
+/**
+ \brief Print a pointer to a U_EMR_INVERTRGN 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_EMRINVERTRGN_print(char *contents, int recnum, size_t off){
+ core11_print("U_EMRINVERTRGN", contents, recnum, off);
+}
+
+// U_EMRPAINTRGN 74
+/**
+ \brief Print a pointer to a U_EMR_PAINTRGN 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_EMRPAINTRGN_print(char *contents, int recnum, size_t off){
+ core11_print("U_EMRPAINTRGN", contents, recnum, off);
+}
+
+// U_EMREXTSELECTCLIPRGN 75
+/**
+ \brief Print a pointer to a U_EMR_EXTSELECTCLIPRGN 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_EMREXTSELECTCLIPRGN_print(char *contents, int recnum, size_t off){
+ int i,roff;
+ PU_EMREXTSELECTCLIPRGN pEmr = (PU_EMREXTSELECTCLIPRGN) (contents + off);
+ core5_print("U_EMREXTSELECTCLIPRGN", contents, recnum, off);
+ printf(" cbRgnData: %u\n",pEmr->cbRgnData);
+ printf(" iMode: %u\n",pEmr->iMode);
+ // This one is a pain since each RGNDATA may be a different size, so it isn't possible to index through them.
+ char *prd = (char *) &(pEmr->RgnData);
+ i=roff=0;
+ while(roff + 16 < pEmr->emr.nSize){ // stop at end of the record
+ printf(" RegionData[%d]: ",i++); rgndata_print((PU_RGNDATA) (prd + roff)); printf("\n");
+ roff += (((PU_RGNDATA)prd)->rdh.dwSize + ((PU_RGNDATA)prd)->rdh.nRgnSize - 16);
+ }
+}
+
+// U_EMRBITBLT 76
+/**
+ \brief Print a pointer to a U_EMR_BITBLT 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_EMRBITBLT_print(char *contents, int recnum, size_t off){
+ PU_EMRBITBLT pEmr = (PU_EMRBITBLT) (contents + off);
+ core5_print("U_EMRBITBLT", contents, recnum, off);
+ 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 : %u\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((PU_BITMAPINFO)(contents + off + pEmr->offBmiSrc));
+ 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
+ \param recnum number of this record in contents
+ \param off offset to this record in contents
+*/
+void U_EMRSTRETCHBLT_print(char *contents, int recnum, size_t off){
+ PU_EMRSTRETCHBLT pEmr = (PU_EMRSTRETCHBLT) (contents + off);
+ core5_print("U_EMRSTRETCHBLT", contents, recnum, off);
+ 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 : %u\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((PU_BITMAPINFO)(contents + off + pEmr->offBmiSrc));
+ 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
+ \param recnum number of this record in contents
+ \param off offset to this record in contents
+*/
+void U_EMRMASKBLT_print(char *contents, int recnum, size_t off){
+ PU_EMRMASKBLT pEmr = (PU_EMRMASKBLT) (contents + off);
+ core5_print("U_EMRMASKBLT", contents, recnum, off);
+ 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 : %u\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((PU_BITMAPINFO)(contents + off + pEmr->offBmiSrc));
+ 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((PU_BITMAPINFO)(contents + off + pEmr->offBmiMask));
+ 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
+ \param recnum number of this record in contents
+ \param off offset to this record in contents
+*/
+void U_EMRPLGBLT_print(char *contents, int recnum, size_t off){
+ PU_EMRPLGBLT pEmr = (PU_EMRPLGBLT) (contents + off);
+ core5_print("U_EMRPLGBLT", contents, recnum, off);
+ 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((PU_BITMAPINFO)(contents + off + pEmr->offBmiSrc));
+ 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((PU_BITMAPINFO)(contents + off + pEmr->offBmiMask));
+ 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
+ \param recnum number of this record in contents
+ \param off offset to this record in contents
+*/
+void U_EMRSETDIBITSTODEVICE_print(char *contents, int recnum, size_t off){
+ PU_EMRSETDIBITSTODEVICE pEmr = (PU_EMRSETDIBITSTODEVICE) (contents + off);
+ core5_print("U_EMRSETDIBITSTODEVICE", contents, recnum, off);
+ 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((PU_BITMAPINFO)(contents + off + pEmr->offBmiSrc));
+ 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
+ \param recnum number of this record in contents
+ \param off offset to this record in contents
+*/
+void U_EMRSTRETCHDIBITS_print(char *contents, int recnum, size_t off){
+ PU_EMRSTRETCHDIBITS pEmr = (PU_EMRSTRETCHDIBITS) (contents + off);
+ core5_print("U_EMRSTRETCHDIBITS", contents, recnum, off);
+ 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((PU_BITMAPINFO)(contents + off + pEmr->offBmiSrc));
+ printf("\n");
+ }
+ printf(" offBitsSrc: %u\n", pEmr->offBitsSrc );
+ printf(" cbBitsSrc: %u\n", pEmr->cbBitsSrc );
+ printf(" iUsageSrc: %u\n", pEmr->iUsageSrc );
+ printf(" dwRop : %u\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
+ \param recnum number of this record in contents
+ \param off offset to this record in contents
+*/
+void U_EMREXTCREATEFONTINDIRECTW_print(char *contents, int recnum, size_t off){
+ PU_EMREXTCREATEFONTINDIRECTW pEmr = (PU_EMREXTCREATEFONTINDIRECTW) (contents + off);
+ core5_print("U_EMREXTCREATEFONTINDIRECTW", contents, recnum, off);
+ printf(" ihFont: %u\n",pEmr->ihFont );
+ printf(" Font: ");
+ if(pEmr->emr.nSize == sizeof(U_EMREXTCREATEFONTINDIRECTW)){ // holds logfont_panose
+ logfont_panose_print(pEmr->elfw);
+ }
+ else { // holds logfont
+ 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
+ \param recnum number of this record in contents
+ \param off offset to this record in contents
+*/
+void U_EMREXTTEXTOUTA_print(char *contents, int recnum, size_t off){
+ core8_print("U_EMREXTTEXTOUTA", contents, recnum, off, 0);
+}
+
+// U_EMREXTTEXTOUTW 84
+/**
+ \brief Print a pointer to a U_EMR_EXTTEXTOUTW 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_EMREXTTEXTOUTW_print(char *contents, int recnum, size_t off){
+ core8_print("U_EMREXTTEXTOUTW", contents, recnum, off, 1);
+}
+
+// U_EMRPOLYBEZIER16 85
+/**
+ \brief Print a pointer to a U_EMR_POLYBEZIER16 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_EMRPOLYBEZIER16_print(char *contents, int recnum, size_t off){
+ core6_print("U_EMRPOLYBEZIER16", contents, recnum, off);
+}
+
+// U_EMRPOLYGON16 86
+/**
+ \brief Print a pointer to a U_EMR_POLYGON16 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_EMRPOLYGON16_print(char *contents, int recnum, size_t off){
+ core6_print("U_EMRPOLYGON16", contents, recnum, off);
+}
+
+// U_EMRPOLYLINE16 87
+/**
+ \brief Print a pointer to a U_EMR_POLYLINE16 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_EMRPOLYLINE16_print(char *contents, int recnum, size_t off){
+ core6_print("U_EMRPOLYLINE16", contents, recnum, off);
+}
+
+// U_EMRPOLYBEZIERTO16 88
+/**
+ \brief Print a pointer to a U_EMR_POLYBEZIERTO16 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_EMRPOLYBEZIERTO16_print(char *contents, int recnum, size_t off){
+ core6_print("U_EMRPOLYBEZIERTO16", contents, recnum, off);
+}
+
+// U_EMRPOLYLINETO16 89
+/**
+ \brief Print a pointer to a U_EMR_POLYLINETO16 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_EMRPOLYLINETO16_print(char *contents, int recnum, size_t off){
+ core6_print("U_EMRPOLYLINETO16", contents, recnum, off);
+}
+
+// U_EMRPOLYPOLYLINE16 90
+/**
+ \brief Print a pointer to a U_EMR_POLYPOLYLINE16 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_EMRPOLYPOLYLINE16_print(char *contents, int recnum, size_t off){
+ core10_print("U_EMRPOLYPOLYLINE16", contents, recnum, off);
+}
+
+// U_EMRPOLYPOLYGON16 91
+/**
+ \brief Print a pointer to a U_EMR_POLYPOLYGON16 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_EMRPOLYPOLYGON16_print(char *contents, int recnum, size_t off){
+ core10_print("U_EMRPOLYPOLYGON16", contents, recnum, off);
+}
+
+
+// U_EMRPOLYDRAW16 92
+/**
+ \brief Print a pointer to a U_EMR_POLYDRAW16 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_EMRPOLYDRAW16_print(char *contents, int recnum, size_t off){
+ int i;
+ core5_print("U_EMRPOLYDRAW16", contents, recnum, off);
+ PU_EMRPOLYDRAW16 pEmr = (PU_EMRPOLYDRAW16)(contents+off);
+ printf(" rclBounds: "); rectl_print( pEmr->rclBounds); printf("\n");
+ printf(" cpts: %d\n",pEmr->cpts );
+ printf(" Points: ");
+ for(i=0;icpts; i++){
+ printf(" [%d]:",i);
+ point16_print(pEmr->apts[i]);
+ }
+ printf("\n");
+ printf(" Types: ");
+ for(i=0;icpts; i++){
+ printf(" [%d]:%u ",i,pEmr->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
+ \param recnum number of this record in contents
+ \param off offset to this record in contents
+*/
+void U_EMRCREATEMONOBRUSH_print(char *contents, int recnum, size_t off){
+ core12_print("U_EMRCREATEMONOBRUSH", contents, recnum, off);
+}
+
+// U_EMRCREATEDIBPATTERNBRUSHPT_print 94
+/**
+ \brief Print a pointer to a U_EMR_CREATEDIBPATTERNBRUSHPT 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_EMRCREATEDIBPATTERNBRUSHPT_print(char *contents, int recnum, size_t off){
+ core12_print("U_EMRCREATEDIBPATTERNBRUSHPT", contents, recnum, off);
+}
+
+
+// U_EMREXTCREATEPEN 95
+/**
+ \brief Print a pointer to a U_EMR_EXTCREATEPEN 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_EMREXTCREATEPEN_print(char *contents, int recnum, size_t off){
+ core5_print("U_EMREXTCREATEPEN", contents, recnum, off);
+ PU_EMREXTCREATEPEN pEmr = (PU_EMREXTCREATEPEN)(contents+off);
+ 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((PU_BITMAPINFO)(contents + off + pEmr->offBmi));
+ 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,B,C) U_EMRNOTIMPLEMENTED_print("U_EMRPOLYTEXTOUTA",A,B,C)
+// U_EMRPOLYTEXTOUTW 97 NOT IMPLEMENTED, denigrated after Windows NT
+#define U_EMRPOLYTEXTOUTW_print(A,B,C) U_EMRNOTIMPLEMENTED_print("U_EMRPOLYTEXTOUTW",A,B,C)
+
+// U_EMRSETICMMODE 98
+/**
+ \brief Print a pointer to a U_EMR_SETICMMODE 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_EMRSETICMMODE_print(char *contents, int recnum, size_t off){
+ core3_print("U_EMRSETICMMODE", "iMode:", contents, recnum, off);
+}
+
+// U_EMRCREATECOLORSPACE 99
+/**
+ \brief Print a pointer to a U_EMR_CREATECOLORSPACE 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_EMRCREATECOLORSPACE_print(char *contents, int recnum, size_t off){
+ core5_print("U_EMRCREATECOLORSPACE", contents, recnum, off);
+ PU_EMRCREATECOLORSPACE pEmr = (PU_EMRCREATECOLORSPACE)(contents+off);
+ 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
+ \param recnum number of this record in contents
+ \param off offset to this record in contents
+*/
+void U_EMRSETCOLORSPACE_print(char *contents, int recnum, size_t off){
+ core3_print("U_EMRSETCOLORSPACE", "ihCS:", contents, recnum, off);
+}
+
+// U_EMRDELETECOLORSPACE 101
+/**
+ \brief Print a pointer to a U_EMR_DELETECOLORSPACE 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_EMRDELETECOLORSPACE_print(char *contents, int recnum, size_t off){
+ core3_print("U_EMRDELETECOLORSPACE", "ihCS:", contents, recnum, off);
+}
+
+// U_EMRGLSRECORD 102 Not implemented
+#define U_EMRGLSRECORD_print(A,B,C) U_EMRNOTIMPLEMENTED_print("U_EMRGLSRECORD",A,B,C)
+// U_EMRGLSBOUNDEDRECORD 103 Not implemented
+#define U_EMRGLSBOUNDEDRECORD_print(A,B,C) U_EMRNOTIMPLEMENTED_print("U_EMRGLSBOUNDEDRECORD",A,B,C)
+
+// U_EMRPIXELFORMAT 104
+/**
+ \brief Print a pointer to a U_EMR_PIXELFORMAT 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_EMRPIXELFORMAT_print(char *contents, int recnum, size_t off){
+ core5_print("U_EMRPIXELFORMAT", contents, recnum, off);
+ PU_EMRPIXELFORMAT pEmr = (PU_EMRPIXELFORMAT)(contents+off);
+ printf(" Pfd: "); pixelformatdescriptor_print(pEmr->pfd); printf("\n");
+}
+
+// U_EMRDRAWESCAPE 105 Not implemented
+#define U_EMRDRAWESCAPE_print(A,B,C) U_EMRNOTIMPLEMENTED_print("U_EMRDRAWESCAPE",A,B,C)
+// U_EMREXTESCAPE 106 Not implemented
+#define U_EMREXTESCAPE_print(A,B,C) U_EMRNOTIMPLEMENTED_print("U_EMREXTESCAPE",A,B,C)
+// U_EMRUNDEF107 107 Not implemented
+#define U_EMRUNDEF107_print(A,B,C) U_EMRNOTIMPLEMENTED_print("U_EMRUNDEF107",A,B,C)
+
+// U_EMRSMALLTEXTOUT 108
+/**
+ \brief Print a pointer to a U_EMR_SMALLTEXTOUT 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_EMRSMALLTEXTOUT_print(char *contents, int recnum, size_t off){
+ int roff;
+ char *string;
+ core5_print("U_EMRSMALLTEXTOUT", contents, recnum, off);
+ PU_EMRSMALLTEXTOUT pEmr = (PU_EMRSMALLTEXTOUT)(contents+off);
+ 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)){
+ printf(" rclBounds: "); rectl_print( *(PU_RECTL) (contents + off + roff)); printf("\n");
+ roff += sizeof(U_RECTL);
+ }
+ if(pEmr->fuOptions & U_ETO_SMALL_CHARS){
+ printf(" Text8: <%s>\n",contents+off+roff);
+ }
+ else {
+ string = U_Utf16leToUtf8((uint16_t *)(contents+off+roff), pEmr->cChars, NULL);
+ printf(" Text16: <%s>\n",contents+off+roff);
+ free(string);
+ }
+}
+
+// U_EMRFORCEUFIMAPPING 109 Not implemented
+#define U_EMRFORCEUFIMAPPING_print(A,B,C) U_EMRNOTIMPLEMENTED_print("U_EMRFORCEUFIMAPPING",A,B,C)
+// U_EMRNAMEDESCAPE 110 Not implemented
+#define U_EMRNAMEDESCAPE_print(A,B,C) U_EMRNOTIMPLEMENTED_print("U_EMRNAMEDESCAPE",A,B,C)
+// U_EMRCOLORCORRECTPALETTE 111 Not implemented
+#define U_EMRCOLORCORRECTPALETTE_print(A,B,C) U_EMRNOTIMPLEMENTED_print("U_EMRCOLORCORRECTPALETTE",A,B,C)
+// U_EMRSETICMPROFILEA 112 Not implemented
+#define U_EMRSETICMPROFILEA_print(A,B,C) U_EMRNOTIMPLEMENTED_print("U_EMRSETICMPROFILEA",A,B,C)
+// U_EMRSETICMPROFILEW 113 Not implemented
+#define U_EMRSETICMPROFILEW_print(A,B,C) U_EMRNOTIMPLEMENTED_print("U_EMRSETICMPROFILEW",A,B,C)
+
+// U_EMRALPHABLEND 114
+/**
+ \brief Print a pointer to a U_EMR_ALPHABLEND 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_EMRALPHABLEND_print(char *contents, int recnum, size_t off){
+ core13_print("U_EMRALPHABLEND", contents, recnum, off);
+}
+
+// U_EMRSETLAYOUT 115
+/**
+ \brief Print a pointer to a U_EMR_SETLAYOUT 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_EMRSETLAYOUT_print(char *contents, int recnum, size_t off){
+ core3_print("U_EMRSETLAYOUT", "iMode:", contents, recnum, off);
+}
+
+// U_EMRTRANSPARENTBLT 116
+/**
+ \brief Print a pointer to a U_EMR_TRANSPARENTBLT 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_EMRTRANSPARENTBLT_print(char *contents, int recnum, size_t off){
+ core13_print("U_EMRTRANSPARENTBLT", contents, recnum, off);
+}
+
+// U_EMRUNDEF117 117 Not implemented
+#define U_EMRUNDEF117_print(A,B,C) U_EMRNOTIMPLEMENTED_print("U_EMRUNDEF117",A,B,C)
+// U_EMRGRADIENTFILL 118
+/**
+ \brief Print a pointer to a U_EMR_GRADIENTFILL 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_EMRGRADIENTFILL_print(char *contents, int recnum, size_t off){
+ int i;
+ core5_print("U_EMRGRADIENTFILL", contents, recnum, off);
+ PU_EMRGRADIENTFILL pEmr = (PU_EMRGRADIENTFILL)(contents+off);
+ 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 );
+ off += sizeof(U_EMRGRADIENTFILL);
+ if(pEmr->nTriVert){
+ printf(" TriVert: ");
+ for(i=0; inTriVert; i++, off+=sizeof(U_TRIVERTEX)){
+ trivertex_print(*(PU_TRIVERTEX)(contents + off));
+ }
+ printf("\n");
+ }
+ if(pEmr->nGradObj){
+ printf(" GradObj: ");
+ if( pEmr->ulMode == U_GRADIENT_FILL_TRIANGLE){
+ for(i=0; inGradObj; i++, off+=sizeof(U_GRADIENT3)){
+ gradient3_print(*(PU_GRADIENT3)(contents + off));
+ }
+ }
+ else if(pEmr->ulMode == U_GRADIENT_FILL_RECT_H ||
+ pEmr->ulMode == U_GRADIENT_FILL_RECT_V){
+ for(i=0; inGradObj; i++, off+=sizeof(U_GRADIENT4)){
+ gradient4_print(*(PU_GRADIENT4)(contents + off));
+ }
+ }
+ else { printf("invalid ulMode value!"); }
+ printf("\n");
+ }
+}
+
+// U_EMRSETLINKEDUFIS 119 Not implemented
+#define U_EMRSETLINKEDUFIS_print(A,B,C) U_EMRNOTIMPLEMENTED_print("U_EMRSETLINKEDUFIS",A,B,C)
+// U_EMRSETTEXTJUSTIFICATION120 Not implemented (denigrated)
+#define U_EMRSETTEXTJUSTIFICATION_print(A,B,C) U_EMRNOTIMPLEMENTED_print("U_EMRSETTEXTJUSTIFICATION",A,B,C)
+// U_EMRCOLORMATCHTOTARGETW 121 Not implemented
+#define U_EMRCOLORMATCHTOTARGETW_print(A,B,C) U_EMRNOTIMPLEMENTED_print("U_EMRCOLORMATCHTOTARGETW",A,B,C)
+
+// U_EMRCREATECOLORSPACEW 122
+/**
+ \brief Print a pointer to a U_EMR_CREATECOLORSPACEW 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_EMRCREATECOLORSPACEW_print(char *contents, int recnum, size_t off){
+ int i;
+ core5_print("U_EMRCREATECOLORSPACEW", contents, recnum, off);
+ PU_EMRCREATECOLORSPACEW pEmr = (PU_EMRCREATECOLORSPACEW)(contents+off);
+ printf(" ihCS: %u\n", pEmr->ihCS );
+ printf(" ColorSpace: "); logcolorspacew_print(pEmr->lcs); printf("\n");
+ printf(" dwFlags: %u\n", pEmr->dwFlags );
+ printf(" cbData: %u\n", pEmr->cbData );
+ printf(" Data: ");
+ if(pEmr->dwFlags & 1){
+ for(i=0; icbData; i++){
+ printf("[%d]:%2.2X ",i,pEmr->Data[i]);
+ }
+ }
+ printf("\n");
+}
+
+/**
+ \brief Print any record in an emf
+ \returns 1 for a normal record, 0 for EMREOF
+ \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
+*/
+int U_emf_onerec_print(char *contents, int recnum, size_t off){
+ PU_ENHMETARECORD lpEMFR = (PU_ENHMETARECORD)(contents + off);
+ int regular=1;
+ switch (lpEMFR->iType)
+ {
+ case U_EMR_HEADER: U_EMRHEADER_print(contents, recnum, off); break;
+ case U_EMR_POLYBEZIER: U_EMRPOLYBEZIER_print(contents, recnum, off); break;
+ case U_EMR_POLYGON: U_EMRPOLYGON_print(contents, recnum, off); break;
+ case U_EMR_POLYLINE: U_EMRPOLYLINE_print(contents, recnum, off); break;
+ case U_EMR_POLYBEZIERTO: U_EMRPOLYBEZIERTO_print(contents, recnum, off); break;
+ case U_EMR_POLYLINETO: U_EMRPOLYLINETO_print(contents, recnum, off); break;
+ case U_EMR_POLYPOLYLINE: U_EMRPOLYPOLYLINE_print(contents, recnum, off); break;
+ case U_EMR_POLYPOLYGON: U_EMRPOLYPOLYGON_print(contents, recnum, off); break;
+ case U_EMR_SETWINDOWEXTEX: U_EMRSETWINDOWEXTEX_print(contents, recnum, off); break;
+ case U_EMR_SETWINDOWORGEX: U_EMRSETWINDOWORGEX_print(contents, recnum, off); break;
+ case U_EMR_SETVIEWPORTEXTEX: U_EMRSETVIEWPORTEXTEX_print(contents, recnum, off); break;
+ case U_EMR_SETVIEWPORTORGEX: U_EMRSETVIEWPORTORGEX_print(contents, recnum, off); break;
+ case U_EMR_SETBRUSHORGEX: U_EMRSETBRUSHORGEX_print(contents, recnum, off); break;
+ case U_EMR_EOF: U_EMREOF_print(contents, recnum, off); regular=0; break;
+ case U_EMR_SETPIXELV: U_EMRSETPIXELV_print(contents, recnum, off); break;
+ case U_EMR_SETMAPPERFLAGS: U_EMRSETMAPPERFLAGS_print(contents, recnum, off); break;
+ case U_EMR_SETMAPMODE: U_EMRSETMAPMODE_print(contents, recnum, off); break;
+ case U_EMR_SETBKMODE: U_EMRSETBKMODE_print(contents, recnum, off); break;
+ case U_EMR_SETPOLYFILLMODE: U_EMRSETPOLYFILLMODE_print(contents, recnum, off); break;
+ case U_EMR_SETROP2: U_EMRSETROP2_print(contents, recnum, off); break;
+ case U_EMR_SETSTRETCHBLTMODE: U_EMRSETSTRETCHBLTMODE_print(contents, recnum, off); break;
+ case U_EMR_SETTEXTALIGN: U_EMRSETTEXTALIGN_print(contents, recnum, off); break;
+ case U_EMR_SETCOLORADJUSTMENT: U_EMRSETCOLORADJUSTMENT_print(contents, recnum, off); break;
+ case U_EMR_SETTEXTCOLOR: U_EMRSETTEXTCOLOR_print(contents, recnum, off); break;
+ case U_EMR_SETBKCOLOR: U_EMRSETBKCOLOR_print(contents, recnum, off); break;
+ case U_EMR_OFFSETCLIPRGN: U_EMROFFSETCLIPRGN_print(contents, recnum, off); break;
+ case U_EMR_MOVETOEX: U_EMRMOVETOEX_print(contents, recnum, off); break;
+ case U_EMR_SETMETARGN: U_EMRSETMETARGN_print(contents, recnum, off); break;
+ case U_EMR_EXCLUDECLIPRECT: U_EMREXCLUDECLIPRECT_print(contents, recnum, off); break;
+ case U_EMR_INTERSECTCLIPRECT: U_EMRINTERSECTCLIPRECT_print(contents, recnum, off); break;
+ case U_EMR_SCALEVIEWPORTEXTEX: U_EMRSCALEVIEWPORTEXTEX_print(contents, recnum, off); break;
+ case U_EMR_SCALEWINDOWEXTEX: U_EMRSCALEWINDOWEXTEX_print(contents, recnum, off); break;
+ case U_EMR_SAVEDC: U_EMRSAVEDC_print(contents, recnum, off); break;
+ case U_EMR_RESTOREDC: U_EMRRESTOREDC_print(contents, recnum, off); break;
+ case U_EMR_SETWORLDTRANSFORM: U_EMRSETWORLDTRANSFORM_print(contents, recnum, off); break;
+ case U_EMR_MODIFYWORLDTRANSFORM: U_EMRMODIFYWORLDTRANSFORM_print(contents, recnum, off); break;
+ case U_EMR_SELECTOBJECT: U_EMRSELECTOBJECT_print(contents, recnum, off); break;
+ case U_EMR_CREATEPEN: U_EMRCREATEPEN_print(contents, recnum, off); break;
+ case U_EMR_CREATEBRUSHINDIRECT: U_EMRCREATEBRUSHINDIRECT_print(contents, recnum, off); break;
+ case U_EMR_DELETEOBJECT: U_EMRDELETEOBJECT_print(contents, recnum, off); break;
+ case U_EMR_ANGLEARC: U_EMRANGLEARC_print(contents, recnum, off); break;
+ case U_EMR_ELLIPSE: U_EMRELLIPSE_print(contents, recnum, off); break;
+ case U_EMR_RECTANGLE: U_EMRRECTANGLE_print(contents, recnum, off); break;
+ case U_EMR_ROUNDRECT: U_EMRROUNDRECT_print(contents, recnum, off); break;
+ case U_EMR_ARC: U_EMRARC_print(contents, recnum, off); break;
+ case U_EMR_CHORD: U_EMRCHORD_print(contents, recnum, off); break;
+ case U_EMR_PIE: U_EMRPIE_print(contents, recnum, off); break;
+ case U_EMR_SELECTPALETTE: U_EMRSELECTPALETTE_print(contents, recnum, off); break;
+ case U_EMR_CREATEPALETTE: U_EMRCREATEPALETTE_print(contents, recnum, off); break;
+ case U_EMR_SETPALETTEENTRIES: U_EMRSETPALETTEENTRIES_print(contents, recnum, off); break;
+ case U_EMR_RESIZEPALETTE: U_EMRRESIZEPALETTE_print(contents, recnum, off); break;
+ case U_EMR_REALIZEPALETTE: U_EMRREALIZEPALETTE_print(contents, recnum, off); break;
+ case U_EMR_EXTFLOODFILL: U_EMREXTFLOODFILL_print(contents, recnum, off); break;
+ case U_EMR_LINETO: U_EMRLINETO_print(contents, recnum, off); break;
+ case U_EMR_ARCTO: U_EMRARCTO_print(contents, recnum, off); break;
+ case U_EMR_POLYDRAW: U_EMRPOLYDRAW_print(contents, recnum, off); break;
+ case U_EMR_SETARCDIRECTION: U_EMRSETARCDIRECTION_print(contents, recnum, off); break;
+ case U_EMR_SETMITERLIMIT: U_EMRSETMITERLIMIT_print(contents, recnum, off); break;
+ case U_EMR_BEGINPATH: U_EMRBEGINPATH_print(contents, recnum, off); break;
+ case U_EMR_ENDPATH: U_EMRENDPATH_print(contents, recnum, off); break;
+ case U_EMR_CLOSEFIGURE: U_EMRCLOSEFIGURE_print(contents, recnum, off); break;
+ case U_EMR_FILLPATH: U_EMRFILLPATH_print(contents, recnum, off); break;
+ case U_EMR_STROKEANDFILLPATH: U_EMRSTROKEANDFILLPATH_print(contents, recnum, off); break;
+ case U_EMR_STROKEPATH: U_EMRSTROKEPATH_print(contents, recnum, off); break;
+ case U_EMR_FLATTENPATH: U_EMRFLATTENPATH_print(contents, recnum, off); break;
+ case U_EMR_WIDENPATH: U_EMRWIDENPATH_print(contents, recnum, off); break;
+ case U_EMR_SELECTCLIPPATH: U_EMRSELECTCLIPPATH_print(contents, recnum, off); break;
+ case U_EMR_ABORTPATH: U_EMRABORTPATH_print(contents, recnum, off); break;
+ case U_EMR_UNDEF69: U_EMRUNDEF69_print(contents, recnum, off); break;
+ case U_EMR_COMMENT: U_EMRCOMMENT_print(contents, recnum, off); break;
+ case U_EMR_FILLRGN: U_EMRFILLRGN_print(contents, recnum, off); break;
+ case U_EMR_FRAMERGN: U_EMRFRAMERGN_print(contents, recnum, off); break;
+ case U_EMR_INVERTRGN: U_EMRINVERTRGN_print(contents, recnum, off); break;
+ case U_EMR_PAINTRGN: U_EMRPAINTRGN_print(contents, recnum, off); break;
+ case U_EMR_EXTSELECTCLIPRGN: U_EMREXTSELECTCLIPRGN_print(contents, recnum, off); break;
+ case U_EMR_BITBLT: U_EMRBITBLT_print(contents, recnum, off); break;
+ case U_EMR_STRETCHBLT: U_EMRSTRETCHBLT_print(contents, recnum, off); break;
+ case U_EMR_MASKBLT: U_EMRMASKBLT_print(contents, recnum, off); break;
+ case U_EMR_PLGBLT: U_EMRPLGBLT_print(contents, recnum, off); break;
+ case U_EMR_SETDIBITSTODEVICE: U_EMRSETDIBITSTODEVICE_print(contents, recnum, off); break;
+ case U_EMR_STRETCHDIBITS: U_EMRSTRETCHDIBITS_print(contents, recnum, off); break;
+ case U_EMR_EXTCREATEFONTINDIRECTW: U_EMREXTCREATEFONTINDIRECTW_print(contents, recnum, off); break;
+ case U_EMR_EXTTEXTOUTA: U_EMREXTTEXTOUTA_print(contents, recnum, off); break;
+ case U_EMR_EXTTEXTOUTW: U_EMREXTTEXTOUTW_print(contents, recnum, off); break;
+ case U_EMR_POLYBEZIER16: U_EMRPOLYBEZIER16_print(contents, recnum, off); break;
+ case U_EMR_POLYGON16: U_EMRPOLYGON16_print(contents, recnum, off); break;
+ case U_EMR_POLYLINE16: U_EMRPOLYLINE16_print(contents, recnum, off); break;
+ case U_EMR_POLYBEZIERTO16: U_EMRPOLYBEZIERTO16_print(contents, recnum, off); break;
+ case U_EMR_POLYLINETO16: U_EMRPOLYLINETO16_print(contents, recnum, off); break;
+ case U_EMR_POLYPOLYLINE16: U_EMRPOLYPOLYLINE16_print(contents, recnum, off); break;
+ case U_EMR_POLYPOLYGON16: U_EMRPOLYPOLYGON16_print(contents, recnum, off); break;
+ case U_EMR_POLYDRAW16: U_EMRPOLYDRAW16_print(contents, recnum, off); break;
+ case U_EMR_CREATEMONOBRUSH: U_EMRCREATEMONOBRUSH_print(contents, recnum, off); break;
+ case U_EMR_CREATEDIBPATTERNBRUSHPT: U_EMRCREATEDIBPATTERNBRUSHPT_print(contents, recnum, off); break;
+ case U_EMR_EXTCREATEPEN: U_EMREXTCREATEPEN_print(contents, recnum, off); break;
+ case U_EMR_POLYTEXTOUTA: U_EMRPOLYTEXTOUTA_print(contents, recnum, off); break;
+ case U_EMR_POLYTEXTOUTW: U_EMRPOLYTEXTOUTW_print(contents, recnum, off); break;
+ case U_EMR_SETICMMODE: U_EMRSETICMMODE_print(contents, recnum, off); break;
+ case U_EMR_CREATECOLORSPACE: U_EMRCREATECOLORSPACE_print(contents, recnum, off); break;
+ case U_EMR_SETCOLORSPACE: U_EMRSETCOLORSPACE_print(contents, recnum, off); break;
+ case U_EMR_DELETECOLORSPACE: U_EMRDELETECOLORSPACE_print(contents, recnum, off); break;
+ case U_EMR_GLSRECORD: U_EMRGLSRECORD_print(contents, recnum, off); break;
+ case U_EMR_GLSBOUNDEDRECORD: U_EMRGLSBOUNDEDRECORD_print(contents, recnum, off); break;
+ case U_EMR_PIXELFORMAT: U_EMRPIXELFORMAT_print(contents, recnum, off); break;
+ case U_EMR_DRAWESCAPE: U_EMRDRAWESCAPE_print(contents, recnum, off); break;
+ case U_EMR_EXTESCAPE: U_EMREXTESCAPE_print(contents, recnum, off); break;
+ case U_EMR_UNDEF107: U_EMRUNDEF107_print(contents, recnum, off); break;
+ case U_EMR_SMALLTEXTOUT: U_EMRSMALLTEXTOUT_print(contents, recnum, off); break;
+ case U_EMR_FORCEUFIMAPPING: U_EMRFORCEUFIMAPPING_print(contents, recnum, off); break;
+ case U_EMR_NAMEDESCAPE: U_EMRNAMEDESCAPE_print(contents, recnum, off); break;
+ case U_EMR_COLORCORRECTPALETTE: U_EMRCOLORCORRECTPALETTE_print(contents, recnum, off); break;
+ case U_EMR_SETICMPROFILEA: U_EMRSETICMPROFILEA_print(contents, recnum, off); break;
+ case U_EMR_SETICMPROFILEW: U_EMRSETICMPROFILEW_print(contents, recnum, off); break;
+ case U_EMR_ALPHABLEND: U_EMRALPHABLEND_print(contents, recnum, off); break;
+ case U_EMR_SETLAYOUT: U_EMRSETLAYOUT_print(contents, recnum, off); break;
+ case U_EMR_TRANSPARENTBLT: U_EMRTRANSPARENTBLT_print(contents, recnum, off); break;
+ case U_EMR_UNDEF117: U_EMRUNDEF117_print(contents, recnum, off); break;
+ case U_EMR_GRADIENTFILL: U_EMRGRADIENTFILL_print(contents, recnum, off); break;
+ case U_EMR_SETLINKEDUFIS: U_EMRSETLINKEDUFIS_print(contents, recnum, off); break;
+ case U_EMR_SETTEXTJUSTIFICATION: U_EMRSETTEXTJUSTIFICATION_print(contents, recnum, off); break;
+ case U_EMR_COLORMATCHTOTARGETW: U_EMRCOLORMATCHTOTARGETW_print(contents, recnum, off); break;
+ case U_EMR_CREATECOLORSPACEW: U_EMRCREATECOLORSPACEW_print(contents, recnum, off); break;
+ default: U_EMRNOTIMPLEMENTED_print("?",contents, recnum, off); break;
+ } //end of switch
+ return(regular);
+}
+
+
+#ifdef __cplusplus
+}
+#endif
diff -rNu3 src/extension/internal/uemf_print.h src/extension/internal/uemf_print.h
--- src/extension/internal/uemf_print.h 1969-12-31 16:00:00.000000000 -0800
+++ src/extension/internal/uemf_print.h 2012-08-07 12:44:48.000000000 -0700
@@ -0,0 +1,134 @@
+/**
+ @file uemf_print.h Functions for printing records from EMF files.
+*/
+
+/*
+File: uemf_print.h
+Version: 0.0.3
+Date: 24-JUL-2012
+Author: David Mathog, Biology Division, Caltech
+email: mathog@caltech.edu
+Copyright: 2012 David Mathog and California Institute of Technology (Caltech)
+*/
+
+#ifndef _UEMF_PRINT_
+#define _UEMF_PRINT_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// prototypes
+void U_EMRNOTIMPLEMENTED_print(char *name, char *contents, int recnum, int off);
+void U_EMRHEADER_print(char *contents, int recnum, int off);
+void U_EMRPOLYBEZIER_print(char *contents, int recnum, int off);
+void U_EMRPOLYGON_print(char *contents, int recnum, int off);
+void U_EMRPOLYLINE_print(char *contents, int recnum, int off);
+void U_EMRPOLYBEZIERTO_print(char *contents, int recnum, int off);
+void U_EMRPOLYLINETO_print(char *contents, int recnum, int off);
+void U_EMRPOLYPOLYLINE_print(char *contents, int recnum, int off);
+void U_EMRPOLYPOLYGON_print(char *contents, int recnum, int off);
+void U_EMRSETWINDOWEXTEX_print(char *contents, int recnum, int off);
+void U_EMRSETWINDOWORGEX_print(char *contents, int recnum, int off);
+void U_EMRSETVIEWPORTEXTEX_print(char *contents, int recnum, int off);
+void U_EMRSETVIEWPORTORGEX_print(char *contents, int recnum, int off);
+void U_EMRSETBRUSHORGEX_print(char *contents, int recnum, int off);
+void U_EMREOF_print(char *contents, int recnum, int off);
+void U_EMRSETPIXELV_print(char *contents, int recnum, int off);
+void U_EMRSETMAPPERFLAGS_print(char *contents, int recnum, int off);
+void U_EMRSETMAPMODE_print(char *contents, int recnum, int off);
+void U_EMRSETBKMODE_print(char *contents, int recnum, int off);
+void U_EMRSETPOLYFILLMODE_print(char *contents, int recnum, int off);
+void U_EMRSETROP2_print(char *contents, int recnum, int off);
+void U_EMRSETSTRETCHBLTMODE_print(char *contents, int recnum, int off);
+void U_EMRSETTEXTALIGN_print(char *contents, int recnum, int off);
+void U_EMRSETCOLORADJUSTMENT_print(char *contents, int recnum, int off);
+void U_EMRSETTEXTCOLOR_print(char *contents, int recnum, int off);
+void U_EMRSETBKCOLOR_print(char *contents, int recnum, int off);
+void U_EMROFFSETCLIPRGN_print(char *contents, int recnum, int off);
+void U_EMRMOVETOEX_print(char *contents, int recnum, int off);
+void U_EMRSETMETARGN_print(char *contents, int recnum, int off);
+void U_EMREXCLUDECLIPRECT_print(char *contents, int recnum, int off);
+void U_EMRINTERSECTCLIPRECT_print(char *contents, int recnum, int off);
+void U_EMRSCALEVIEWPORTEXTEX_print(char *contents, int recnum, int off);
+void U_EMRSCALEWINDOWEXTEX_print(char *contents, int recnum, int off);
+void U_EMRSAVEDC_print(char *contents, int recnum, int off);
+void U_EMRRESTOREDC_print(char *contents, int recnum, int off);
+void U_EMRSETWORLDTRANSFORM_print(char *contents, int recnum, int off);
+void U_EMRMODIFYWORLDTRANSFORM_print(char *contents, int recnum, int off);
+void U_EMRSELECTOBJECT_print(char *contents, int recnum, int off);
+void U_EMRCREATEPEN_print(char *contents, int recnum, int off);
+void U_EMRCREATEBRUSHINDIRECT_print(char *contents, int recnum, int off);
+void U_EMRDELETEOBJECT_print(char *contents, int recnum, int off);
+void U_EMRANGLEARC_print(char *contents, int recnum, int off);
+void U_EMRELLIPSE_print(char *contents, int recnum, int off);
+void U_EMRRECTANGLE_print(char *contents, int recnum, int off);
+void U_EMRROUNDRECT_print(char *contents, int recnum, int off);
+void U_EMRARC_print(char *contents, int recnum, int off);
+void U_EMRCHORD_print(char *contents, int recnum, int off);
+void U_EMRPIE_print(char *contents, int recnum, int off);
+void U_EMRSELECTPALETTE_print(char *contents, int recnum, int off);
+void U_EMRCREATEPALETTE_print(char *contents, int recnum, int off);
+void U_EMRSETPALETTEENTRIES_print(char *contents, int recnum, int off);
+void U_EMRRESIZEPALETTE_print(char *contents, int recnum, int off);
+void U_EMRREALIZEPALETTE_print(char *contents, int recnum, int off);
+void U_EMREXTFLOODFILL_print(char *contents, int recnum, int off);
+void U_EMRLINETO_print(char *contents, int recnum, int off);
+void U_EMRARCTO_print(char *contents, int recnum, int off);
+void U_EMRPOLYDRAW_print(char *contents, int recnum, int off);
+void U_EMRSETARCDIRECTION_print(char *contents, int recnum, int off);
+void U_EMRSETMITERLIMIT_print(char *contents, int recnum, int off);
+void U_EMRBEGINPATH_print(char *contents, int recnum, int off);
+void U_EMRENDPATH_print(char *contents, int recnum, int off);
+void U_EMRCLOSEFIGURE_print(char *contents, int recnum, int off);
+void U_EMRFILLPATH_print(char *contents, int recnum, int off);
+void U_EMRSTROKEANDFILLPATH_print(char *contents, int recnum, int off);
+void U_EMRSTROKEPATH_print(char *contents, int recnum, int off);
+void U_EMRFLATTENPATH_print(char *contents, int recnum, int off);
+void U_EMRWIDENPATH_print(char *contents, int recnum, int off);
+void U_EMRSELECTCLIPPATH_print(char *contents, int recnum, int off);
+void U_EMRABORTPATH_print(char *contents, int recnum, int off);
+void U_EMRCOMMENT_print(char *contents, int recnum, int off);
+void U_EMRFILLRGN_print(char *contents, int recnum, int off);
+void U_EMRFRAMERGN_print(char *contents, int recnum, int off);
+void U_EMRINVERTRGN_print(char *contents, int recnum, int off);
+void U_EMRPAINTRGN_print(char *contents, int recnum, int off);
+void U_EMREXTSELECTCLIPRGN_print(char *contents, int recnum, int off);
+void U_EMRBITBLT_print(char *contents, int recnum, int off);
+void U_EMRSTRETCHBLT_print(char *contents, int recnum, int off);
+void U_EMRMASKBLT_print(char *contents, int recnum, int off);
+void U_EMRPLGBLT_print(char *contents, int recnum, int off);
+void U_EMRSETDIBITSTODEVICE_print(char *contents, int recnum, int off);
+void U_EMRSTRETCHDIBITS_print(char *contents, int recnum, int off);
+void U_EMREXTCREATEFONTINDIRECTW_print(char *contents, int recnum, int off);
+void U_EMREXTTEXTOUTA_print(char *contents, int recnum, int off);
+void U_EMREXTTEXTOUTW_print(char *contents, int recnum, int off);
+void U_EMRPOLYBEZIER16_print(char *contents, int recnum, int off);
+void U_EMRPOLYGON16_print(char *contents, int recnum, int off);
+void U_EMRPOLYLINE16_print(char *contents, int recnum, int off);
+void U_EMRPOLYBEZIERTO16_print(char *contents, int recnum, int off);
+void U_EMRPOLYLINETO16_print(char *contents, int recnum, int off);
+void U_EMRPOLYPOLYLINE16_print(char *contents, int recnum, int off);
+void U_EMRPOLYPOLYGON16_print(char *contents, int recnum, int off);
+void U_EMRPOLYDRAW16_print(char *contents, int recnum, int off);
+void U_EMRCREATEMONOBRUSH_print(char *contents, int recnum, int off);
+void U_EMRCREATEDIBPATTERNBRUSHPT_print(char *contents, int recnum, int off);
+void U_EMREXTCREATEPEN_print(char *contents, int recnum, int off);
+void U_EMRSETICMMODE_print(char *contents, int recnum, int off);
+void U_EMRCREATECOLORSPACE_print(char *contents, int recnum, int off);
+void U_EMRSETCOLORSPACE_print(char *contents, int recnum, int off);
+void U_EMRDELETECOLORSPACE_print(char *contents, int recnum, int off);
+void U_EMRPIXELFORMAT_print(char *contents, int recnum, int off);
+void U_EMRSMALLTEXTOUT_print(char *contents, int recnum, int off);
+void U_EMRALPHABLEND_print(char *contents, int recnum, int off);
+void U_EMRSETLAYOUT_print(char *contents, int recnum, int off);
+void U_EMRTRANSPARENTBLT_print(char *contents, int recnum, int off);
+void U_EMRGRADIENTFILL_print(char *contents, int recnum, int off);
+void U_EMRCREATECOLORSPACEW_print(char *contents, int recnum, int off);
+int U_emf_onerec_print(char *contents, int recnum, int off);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _UEMF_PRINT_ */
diff -rNu3 src/libnrtype/Layout-TNG-Output.cpp src/libnrtype/Layout-TNG-Output.cpp
--- src/libnrtype/Layout-TNG-Output.cpp 2012-08-07 12:29:10.000000000 -0700
+++ src/libnrtype/Layout-TNG-Output.cpp 2012-08-08 11:14:07.000000000 -0700
@@ -20,6 +20,7 @@
#include "extension/internal/cairo-render-context.h"
#include "display/curve.h"
#include <2geom/pathvector.h>
+#include "libunicode-convert/unicode-convert.h"
#if !PANGO_VERSION_CHECK(1,24,0)
#define PANGO_WEIGHT_THIN static_cast(100)
@@ -43,6 +44,27 @@
namespace Inkscape {
namespace Text {
+// the dx array is smuggled through to the EMF (ignored by others) as:
+// textN w1 w2 w3 ...wN
+// where the widths are floats 7 characters wide, including the space
+char *smuggle_adx_in(const char *string, int ndx, int size, float *adx){
+ int slen=strlen(string);
+ // holds: string, fake terminator, Number of offsets, series of offsets, real (double) terminator.
+ int newsize=slen + 1 + 7 + 7*ndx + 2;
+ newsize = 8*((7 + newsize)/8); // suppress valgrind messages if it is a multiple of 8 bytes???
+ char *smuggle=(char *)calloc(newsize,1); //initialize all bytes, inluding terminators
+ strcpy(smuggle,string);
+ char *cptr = smuggle + slen + 1; // immediately after the first terminator
+ sprintf(cptr,"%07d",ndx);
+ cptr+=7;
+ for(int i=0; imodule->textToPath();
+ doUTN = CanUTN(); // Unicode to Nonunicode translation enabled if true
for (unsigned glyph_index = 0 ; glyph_index < _glyphs.size() ; ) {
if (_characters[_glyphs[glyph_index].in_character].in_glyph == -1) {
// invisible glyphs
@@ -180,9 +209,15 @@
}
// try to output as many characters as possible in one go by detecting kerning and stopping when we encounter it
+ // also break spans at changes in Unicode->nonunicode translations, so that each span
+ // sent down from here is translated the same way. The translation happens much later
+ // in the emf-win32-print code
+
Glib::ustring span_string;
double char_x = _characters[_glyphs[glyph_index].in_character].x;
unsigned this_span_index = _characters[_glyphs[glyph_index].in_character].in_span;
+ if(doUTN)lasttarget=SingleUnicodeToNon(*span_iter);
+
do {
span_string += *span_iter;
span_iter++;
@@ -190,14 +225,25 @@
unsigned same_character = _glyphs[glyph_index].in_character;
while (glyph_index < _glyphs.size() && _glyphs[glyph_index].in_character == same_character) {
char_x += _glyphs[glyph_index].width;
+ if(ndx < MAX_DX){ hold_dx[ndx++] = _glyphs[glyph_index].width; }
glyph_index++;
}
} while (glyph_index < _glyphs.size()
&& _path_fitted == NULL
&& _characters[_glyphs[glyph_index].in_character].in_span == this_span_index
- && fabs(char_x - _characters[_glyphs[glyph_index].in_character].x) < 1e-4);
+ && fabs(char_x - _characters[_glyphs[glyph_index].in_character].x) < 1e-4
+ && (doUTN ? (lasttarget==SingleUnicodeToNon(*span_iter) ? 1 : 0) : 1 )
+ );
sp_print_bind(ctx, glyph_matrix, 1.0);
- sp_print_text(ctx, span_string.c_str(), g_pos, text_source->style);
+
+ // the dx array is smuggled through to the EMF (ignored by others) as:
+ // textw1 w2 w3 ...wn
+ // where the widths are floats 7 characters wide, including the space
+
+ char *smuggle_string=smuggle_adx_in(span_string.c_str(),ndx,MAX_DX, &hold_dx[0]);
+// sp_print_text(ctx, span_string.c_str(), g_pos, text_source->style);
+ sp_print_text(ctx, smuggle_string, g_pos, text_source->style);
+ free(smuggle_string);
sp_print_release(ctx);
}
}
@@ -342,7 +388,7 @@
Glib::ustring Layout::getFontFamily(unsigned span_index) const
{
- if (span_index < 0 || span_index >= _spans.size())
+ if (span_index >= _spans.size())
return "";
if (_spans[span_index].font) {
diff -rNu3 src/libunicode-convert/makefile.in src/libunicode-convert/makefile.in
--- src/libunicode-convert/makefile.in 1969-12-31 16:00:00.000000000 -0800
+++ src/libunicode-convert/makefile.in 2012-08-07 13:52:37.000000000 -0700
@@ -0,0 +1,17 @@
+# Convenience stub makefile to call the real Makefile.
+
+@SET_MAKE@
+
+OBJEXT = @OBJEXT@
+
+# Explicit so that it's the default rule.
+all:
+ cd .. && $(MAKE) libunicode-convert/all
+
+clean %.a %.$(OBJEXT):
+ cd .. && $(MAKE) libunicode-convert/$@
+
+.PHONY: all clean
+
+.SUFFIXES:
+.SUFFIXES: .a .$(OBJEXT)
diff -rNu3 src/libunicode-convert/Makefile_insert src/libunicode-convert/Makefile_insert
--- src/libunicode-convert/Makefile_insert 1969-12-31 16:00:00.000000000 -0800
+++ src/libunicode-convert/Makefile_insert 2012-08-07 13:52:37.000000000 -0700
@@ -0,0 +1,5 @@
+## Makefile.am fragment sourced by src/Makefile.am.
+
+ink_common_sources += \
+ libunicode-convert/unicode-convert.c \
+ libunicode-convert/unicode-convert.h
diff -rNu3 src/libunicode-convert/README src/libunicode-convert/README
--- src/libunicode-convert/README 1969-12-31 16:00:00.000000000 -0800
+++ src/libunicode-convert/README 2012-08-07 13:52:37.000000000 -0700
@@ -0,0 +1 @@
+Some simple routines for converting between Unicode and nonunicode fonts.
diff -rNu3 src/libunicode-convert/unicode-convert.c src/libunicode-convert/unicode-convert.c
--- src/libunicode-convert/unicode-convert.c 1969-12-31 16:00:00.000000000 -0800
+++ src/libunicode-convert/unicode-convert.c 2012-08-07 13:52:37.000000000 -0700
@@ -0,0 +1,1047 @@
+/** @file
+ * @brief Windows-only Enhanced Metafile input and output.
+ */
+/* Authors:
+ * David mathog
+ *
+ * Copyright (C) 2012 Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ *
+ * References:
+ * see unicode-convert.h
+ *
+ * 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
+ * v1.2 03/26/2012 Introduced bug into SingleUnicodeToNon repaired.
+ * 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.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include
+#include
+#include "unicode-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
+void UC_log_message(char *text){
+FILE *fp;
+ fp=fopen("c:/temp/debug.txt","a");
+ fprintf(fp,"%s",text);
+ fclose(fp);
+}
+
+// wstrdup, might not be available, make a local one. No error checking
+wchar_t *lcl_wstrdup(wchar_t *wtext){
+ if(!wtext)return NULL;
+ wchar_t *wdup = (wchar_t *) calloc((1 + wcslen(wtext)),sizeof(wchar_t));
+ (void) wcscpy(wdup, wtext);
+ return wdup;
+}
+
+// convert 8 bit to 16 bit by copying values, return in a new buffer. (For MS A/W variants of functions)
+wchar_t *AMS2WMS(char *atext){
+int tsize,i;
+wchar_t *wdup;
+ if(!atext)return NULL;
+ tsize = strlen(atext);
+ wdup = (wchar_t *)malloc((1+tsize)* sizeof(wchar_t));
+ for(i=0;i<=tsize;i++){ wdup[i] = ((unsigned char *)atext)[i]; } // This copies the 0 terminator
+ return wdup;
+}
+
+//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 (wchar_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 (wchar_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);
+}
+// Returns the font name (wide), given the classification code, or NULL
+// The returned value must NOT be free'd
+wchar_t *wFontName(int code){
+wchar_t *wptr;
+static wchar_t name_symbol[]=L"Symbol";
+static wchar_t name_wingdings[]=L"Wingdings";
+static wchar_t name_zapfdingbats[]=L"ZapfDingbats";
+ switch(code){
+ case CVTSYM: wptr=&name_symbol[0]; break;
+ case CVTWDG: wptr=&name_wingdings[0]; break;
+ case CVTZDG: wptr=&name_zapfdingbats[0]; break;
+ default: wptr=NULL; break;
+ }
+ return(wptr);
+}
+
+
+// Goes through the wchar converting as needed.
+int NonToUnicode(wchar_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 = (wchar_t) 0xFFFD; } // out of range
+ else { *text = (wchar_t) 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(wchar_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(wchar_t text){
+ if(to_font){return(to_font[text]); }
+ else { return(CVTNON); }
+}
+
+// utility - translates a multibyte utf8 to utf16 and returns it
+wchar_t one_Utf8_to_Utf16(char *text){
+wchar_t retwide;
+ (void) mbstowcs(&retwide, text, 1);
+ return(retwide);
+}
+
+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(char));
+ to_font = (unsigned char *) calloc(0x10000,sizeof(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 -rNu3 src/libunicode-convert/unicode-convert.h src/libunicode-convert/unicode-convert.h
--- src/libunicode-convert/unicode-convert.h 1969-12-31 16:00:00.000000000 -0800
+++ src/libunicode-convert/unicode-convert.h 2012-08-07 13:52:37.000000000 -0700
@@ -0,0 +1,53 @@
+/** @file
+ * @brief Enhanced Metafile Input/Output
+ */
+/* Authors:
+ * David Mathog
+ *
+ * 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
+#include
+ enum cvt_to_font {CVTNON, CVTSYM, CVTZDG, CVTWDG};
+
+ wchar_t *AMS2WMS(char *atext); //copy MS A format text to MS W format text, return in new buffer
+ void msdepua(wchar_t *text); //translate down from Microsoft Private Use Area
+ void msrepua(wchar_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
+ wchar_t *wFontName(int code); //returns the font name (or NULL) wide, given the enum code
+ int NonToUnicode(wchar_t *text, char *font); //nonunicode to Unicode translation
+ int CanUTN(void); // 1 if tables exist for UnicodeToNon translation
+ int SingleUnicodeToNon(wchar_t text); //retuns the enum value for this translation
+ void UnicodeToNon(wchar_t *text, int *ecount, int *edest); //translate Unicode to NonUnicode
+ wchar_t one_Utf8_to_Utf16(char *text); //translates a single character multibye UTF8 to UTF16
+ void TableGen(bool symb, bool wing, bool zdng, bool pua);
+ wchar_t *lcl_wstrdup(wchar_t *wtext);
+
+#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 -rNu3 src/Makefile.am src/Makefile.am
--- src/Makefile.am 2012-08-07 12:29:10.000000000 -0700
+++ src/Makefile.am 2012-08-07 12:45:41.000000000 -0700
@@ -135,6 +135,7 @@
include live_effects/parameter/Makefile_insert
include libvpsc/Makefile_insert
include libcola/Makefile_insert
+include libunicode-convert/Makefile_insert
include svg/Makefile_insert
include widgets/Makefile_insert
include debug/Makefile_insert
@@ -190,10 +191,10 @@
widgets/makefile.in \
xml/makefile.in \
2geom/makefile.in \
- extension/internal/emf-win32-inout.cpp \
- extension/internal/emf-win32-inout.h \
- extension/internal/emf-win32-print.cpp \
- extension/internal/emf-win32-print.h \
+ extension/internal/emf-inout.cpp \
+ extension/internal/emf-inout.h \
+ extension/internal/emf-print.cpp \
+ extension/internal/emf-print.h \
helper/sp-marshal.list \
show-preview.bmp \
winconsole.cpp \
diff -rNu3 src/sp-image.cpp src/sp-image.cpp
--- src/sp-image.cpp 2012-08-07 12:29:10.000000000 -0700
+++ src/sp-image.cpp 2012-08-07 12:54:27.000000000 -0700
@@ -1119,6 +1119,7 @@
t = ti * t;
sp_print_image_R8G8B8A8_N(ctx, px + trimx*pixskip + trimy*rs, trimwidth, trimheight, rs, t, item->style);
}
+ free(px); // else big memory leak on each image print!
}
}
diff -rNu3 src/style.h src/style.h
--- src/style.h 2012-08-07 12:29:10.000000000 -0700
+++ src/style.h 2012-08-07 12:53:57.000000000 -0700
@@ -178,12 +178,17 @@
void read( gchar const *str, SPStyle &tyle, SPDocument *document = 0);
- // Win32 is a temp work-around until the emf extension is fixed:
-#ifndef WIN32
+/* EMF_DRIVER is a temp work-around
+The problem is that SPIPaint is private, but is included in the SPStyle struct, and that is needed in emf-inout.cpp, but the compiler
+won't accept it there. If the two conditional lines are moved out of the "private" they end up generating undefined reference
+errors.
+*/
+
private:
+#ifndef EMF_DRIVER
SPIPaint(SPIPaint const&);
SPIPaint &operator=(SPIPaint const &);
-#endif // WIN32
+#endif // EMF_DRIVER
};
/// Filter type internal to SPStyle
diff -rNu3 src/ui/tool/path-manipulator.cpp src/ui/tool/path-manipulator.cpp
--- src/ui/tool/path-manipulator.cpp 2012-08-07 12:29:10.000000000 -0700
+++ src/ui/tool/path-manipulator.cpp 2012-08-07 12:57:39.000000000 -0700
@@ -949,10 +949,12 @@
* at the given time value */
NodeList::iterator PathManipulator::subdivideSegment(NodeList::iterator first, double t)
{
- if (!first) throw std::invalid_argument("Subdivide after invalid iterator");
+ //throw originally used std::invalid_argument, that caused a link error against static libstdc++,
+ //this form was only used here.
+ if (!first) throw "Subdivide after invalid iterator";
NodeList &list = NodeList::get(first);
NodeList::iterator second = first.next();
- if (!second) throw std::invalid_argument("Subdivide after last node in open path");
+ if (!second) throw "Subdivide after last node in open path";
// We need to insert the segment after 'first'. We can't simply use 'second'
// as the point of insertion, because when 'first' is the last node of closed path,
diff -rNu3 src/widgets/dash-selector.cpp src/widgets/dash-selector.cpp
--- src/widgets/dash-selector.cpp 2012-08-07 12:29:10.000000000 -0700
+++ src/widgets/dash-selector.cpp 2012-08-07 13:01:21.000000000 -0700
@@ -39,6 +39,7 @@
static double dash_1_2[] = {1.0, 2.0, -1.0};
static double dash_1_4[] = {1.0, 4.0, -1.0};
+#define bd_len 7 // must correspond to the number of entries in the next line
static double *builtin_dashes[] = {dash_0, dash_1_1, dash_2_1, dash_4_1, dash_1_2, dash_1_4, NULL};
static double **dashes = NULL;
@@ -79,12 +80,18 @@
this->pack_start(*sb, false, false, 0);
- for (int i = 0; dashes[i]; i++) {
+ int np=0;
+ while (dashes[np]){ np++;}
+ for (int i = 0; iappend());
row[dash_columns.dash] = dashes[i];
row[dash_columns.pixbuf] = Glib::wrap(sp_dash_to_pixbuf(dashes[i]));
}
+ // add the custom one
+ Gtk::TreeModel::Row row = *(dash_store->append());
+ row[dash_columns.dash] = dashes[np-1];
+ row[dash_columns.pixbuf] = Glib::wrap(sp_text_to_pixbuf((char *)"Custom"));
this->set_data("pattern", dashes[0]);
}
@@ -109,10 +116,10 @@
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
std::vector dash_prefs = prefs->getAllDirs(_prefs_path);
+ int pos = 0;
if (!dash_prefs.empty()) {
- int pos = 0;
SPStyle *style = sp_style_new (NULL);
- dashes = g_new (double *, dash_prefs.size() + 1);
+ dashes = g_new (double *, dash_prefs.size() + 2); // +1 for custom slot, +1 for terminator slot
for (std::vector::iterator i = dash_prefs.begin(); i != dash_prefs.end(); ++i) {
sp_style_read_from_prefs(style, *i);
@@ -130,23 +137,36 @@
}
pos += 1;
}
- dashes[pos] = NULL;
- } else {
- dashes = builtin_dashes;
+ } else { // This code may never execute - a new preferences.xml is created for a new user. Maybe if the user deletes dashes from preferences.xml?
+ dashes = g_new (double *, bd_len + 2); // +1 for custom slot, +1 for terminator slot
+ int i;
+ for(i=0;i 0) {
double delta = 0.0;
for (int i = 0; i < ndash; i++)
delta += dash[i];
delta /= 1000.0;
- for (int i = 0; dashes[i]; i++) {
+ for (int i = 0; dashes[i]; i++,count++) {
double *pattern = dashes[i];
int np = 0;
while (pattern[np] >= 0.0)
@@ -154,6 +174,7 @@
if (np == ndash) {
int j;
for (j = 0; j < ndash; j++) {
+
if (!Geom::are_near(dash[j], pattern[j], delta))
break;
}
@@ -164,10 +185,27 @@
}
}
}
+ else if(ndash==0) {
+ pos = 0;
+ }
- this->set_data("pattern", dashes[pos]);
- this->dash_combo.set_active(pos);
- this->offset->set_value(o);
+ if(pos>=0){
+ this->set_data("pattern", dashes[pos]);
+ this->dash_combo.set_active(pos);
+ this->offset->set_value(o);
+ }
+ else { // Hit a custom pattern in the SVG, write it into the combobox.
+ count--; // the one slot for custom patterns
+ double *d = dashes[count];
+ int i=0;
+ for(i=0;i< (ndash > 15 ? 15 : ndash) ;i++) {
+ d[i]=dash[i];
+ } // store the custom pattern
+ d[ndash]=-1.0; //terminate it
+ this->set_data("pattern", dashes[count]);
+ this->dash_combo.set_active(count);
+ this->offset->set_value(o); // what does this do????
+ }
}
void SPDashSelector::get_dash(int *ndash, double **dash, double *off)
@@ -227,6 +265,32 @@
return pixbuf;
}
+/**
+ * Fill a pixbuf with a text label using standard cairo drawing
+ */
+GdkPixbuf* SPDashSelector::sp_text_to_pixbuf(char *text) {
+
+ cairo_surface_t *s = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, preview_width, preview_height);
+ cairo_t *ct = cairo_create(s);
+
+ cairo_select_font_face (ct, "Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
+ cairo_set_font_size (ct, 12.0);
+ cairo_set_source_rgb (ct, 0.0, 0.0, 0.0);
+ cairo_move_to (ct, 16.0, 13.0);
+ cairo_show_text (ct, text);
+
+ cairo_stroke (ct);
+
+ cairo_destroy(ct);
+ cairo_surface_flush(s);
+
+ GdkPixbuf* pixbuf = gdk_pixbuf_new_from_data( cairo_image_surface_get_data(s),
+ GDK_COLORSPACE_RGB, TRUE, 8,
+ preview_width, preview_height, cairo_image_surface_get_stride(s),
+ ink_cairo_pixbuf_cleanup, s);
+ convert_pixbuf_argb32_to_normal(pixbuf);
+ return pixbuf;
+}
void SPDashSelector::on_selection ()
{
diff -rNu3 src/widgets/dash-selector.h src/widgets/dash-selector.h
--- src/widgets/dash-selector.h 2012-08-07 12:29:10.000000000 -0700
+++ src/widgets/dash-selector.h 2012-08-07 12:58:44.000000000 -0700
@@ -46,6 +46,11 @@
GdkPixbuf* sp_dash_to_pixbuf(double *pattern);
/**
+ * Fill a pixbuf with text standard cairo drawing
+ */
+ GdkPixbuf* sp_text_to_pixbuf(char *text);
+
+ /**
* Callback for combobox image renderer
*/
void prepareImageRenderer( Gtk::TreeModel::const_iterator const &row );