diff -rNu3 build.xml build.xml
--- build.xml 2012-09-13 10:24:25.000000000 -0700
+++ build.xml 2012-09-13 13:15:09.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-09-13 10:24:25.000000000 -0700
+++ configure.ac 2012-09-13 13:15:09.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])
@@ -1013,8 +1014,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
@@ -1066,6 +1067,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-09-13 13:15:09.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 share/extensions/Makefile.am share/extensions/Makefile.am
--- share/extensions/Makefile.am 2012-09-13 10:24:25.000000000 -0700
+++ share/extensions/Makefile.am 2012-09-13 13:15:09.000000000 -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-09-13 10:24:25.000000000 -0700
+++ src/extension/init.cpp 2012-09-13 13:15:09.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-09-14 14:31:52.000000000 -0700
@@ -0,0 +1,3140 @@
+/** @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);
+ png_destroy_write_struct(&png_ptr, &info_ptr);
+
+}
+
+/* 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));
+}
+
+/* convert an EMF RGB(A) color to 0RGB
+inverse of gethexcolor() in emf-print.cpp
+*/
+uint32_t sethexcolor(U_COLORREF color){
+
+ uint32_t out;
+ out = (U_RGBAGetR(color) << 16) +
+ (U_RGBAGetG(color) << 8 ) +
+ (U_RGBAGetB(color) );
+ return(out);
+}
+
+
+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_FixPPTCharPos = mod->get_param_bool("FixPPTCharPos"); // character position bug
+ // reserve FixPPT2 for opacity bug. Currently EMF does not export opacity values
+ bool new_FixPPTDashLine = mod->get_param_bool("FixPPTDashLine"); // dashed line bug
+ bool new_FixPPTGrad2Polys = mod->get_param_bool("FixPPTGrad2Polys"); // gradient bug
+ bool new_FixPPTPatternAsHatch = mod->get_param_bool("FixPPTPatternAsHatch"); // force all patterns as standard EMF hatch
+
+ 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("FixPPTCharPos",new_FixPPTCharPos); // Remember to add any new ones to PrintEmf::init or a mysterious failure will result!
+ ext->set_param_bool("FixPPTDashLine",new_FixPPTDashLine);
+ ext->set_param_bool("FixPPTGrad2Polys",new_FixPPTGrad2Polys);
+ ext->set_param_bool("FixPPTPatternAsHatch",new_FixPPTPatternAsHatch);
+ ext->set_param_bool("textToPath", new_val);
+
+ emf_print_document_to_file(doc, filename);
+
+ return;
+}
+
+
+enum drawmode {DRAW_PAINT, DRAW_PATTERN, DRAW_IMAGE}; // apply to either fill or stroke
+
+typedef struct {
+ int type;
+ int level;
+ char *lpEMFR;
+} EMF_OBJECT, *PEMF_OBJECT;
+
+typedef struct {
+ int size; // number of slots allocated in strings
+ int count; // number of slots used in strings
+ char **strings; // place to store strings
+} EMF_STRINGS, *PEMF_STRINGS;
+
+typedef struct emf_device_context {
+ struct SPStyle style;
+ class SPTextStyle tstyle;
+ bool stroke_set;
+ int stroke_mode; // enumeration from drawmode, not used if fill_set is not True
+ int stroke_idx; // used with DRAW_PATTERN and DRAW_IMAGE to return the appropriate fill
+ bool fill_set;
+ int fill_mode; // enumeration from drawmode, not used if fill_set is not True
+ int fill_idx; // used with DRAW_PATTERN and DRAW_IMAGE to return the appropriate fill
+
+ 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;
+ U_COLORREF bkColor;
+ bool bkColorSet;
+ 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;
+ Glib::ustring *defs;
+
+ 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;
+ // both of these end up in under the names shown here. These structures allow duplicates to be avoided.
+ EMF_STRINGS hatches; // hold pattern names, all like EMFhatch#_$$$$$$ where # is the EMF hatch code and $$$$$$ is the color
+ EMF_STRINGS images; // hold images, all like Image#, where # is the slot the image lives.
+
+
+ int n_obj;
+ PEMF_OBJECT emf_obj;
+} EMF_CALLBACK_DATA, *PEMF_CALLBACK_DATA;
+
+/* Add another 100 blank slots to the hatches array.
+*/
+void enlarge_hatches(PEMF_CALLBACK_DATA d){
+ d->hatches.size += 100;
+ d->hatches.strings = (char **) realloc(d->hatches.strings,d->hatches.size + sizeof(char *));
+}
+
+/* See if the pattern name is already in the list. If it is return its position (1->n, not 1-n-1)
+*/
+int in_hatches(PEMF_CALLBACK_DATA d, char *test){
+ int i;
+ for(i=0; ihatches.count; i++){
+ if(strcmp(test,d->hatches.strings[i])==0)return(i+1);
+ }
+ return(0);
+}
+
+/* (Conditionally) add a hatch. If a matching hatch already exists nothing happens. If one
+ does not exist it is added to the hatches list and also entered into .
+*/
+uint32_t add_hatch(PEMF_CALLBACK_DATA d, uint32_t hatchType, U_COLORREF hatchColor){
+ char hatchname[64]; // big enough
+ char tmpcolor[8];
+ uint32_t idx;
+
+ if(hatchType==U_HS_DIAGCROSS){ // This is the only one with dependencies on others
+ (void) add_hatch(d,U_HS_FDIAGONAL,hatchColor);
+ (void) add_hatch(d,U_HS_BDIAGONAL,hatchColor);
+ }
+
+ sprintf(tmpcolor,"%6.6X",sethexcolor(hatchColor));
+ switch(hatchType){
+ case U_HS_SOLIDTEXTCLR:
+ case U_HS_DITHEREDTEXTCLR:
+ if(d->dc[d->level].textColorSet){
+ sprintf(tmpcolor,"%6.6X",sethexcolor(d->dc[d->level].textColor));
+ }
+ break;
+ case U_HS_SOLIDBKCLR:
+ case U_HS_DITHEREDBKCLR:
+ if(d->dc[d->level].bkColorSet){
+ sprintf(tmpcolor,"%6.6X",sethexcolor(d->dc[d->level].bkColor));
+ }
+ break;
+ default:
+ break;
+ }
+
+ // EMF can take solid colors from background or the default text color but on conversion to inkscape
+ // these need to go to a defined color. Consequently the hatchType also has to go to a solid color, otherwise
+ // on export the background/text might not match at the time this is written, and the colors will shift.
+ if(hatchType > U_HS_SOLIDCLR)hatchType = U_HS_SOLIDCLR;
+
+ sprintf(hatchname,"EMFhatch%d_%s",hatchType,tmpcolor);
+ idx = in_hatches(d,hatchname);
+ if(!idx){ // add it if not already present
+ if(d->hatches.count == d->hatches.size){ enlarge_hatches(d); }
+ d->hatches.strings[d->hatches.count++]=strdup(hatchname);
+
+ *(d->defs) += "\n";
+ *(d->defs) += " defs) += hatchname;
+ *(d->defs) += "\"\n";
+ switch(hatchType){
+ case U_HS_HORIZONTAL:
+ *(d->defs) += " patternUnits=\"userSpaceOnUse\" width=\"6\" height=\"6\" x=\"0\" y=\"0\" >\n";
+ *(d->defs) += " defs) += tmpcolor;
+ *(d->defs) += "\" />\n";
+ *(d->defs) += " \n";
+ break;
+ case U_HS_VERTICAL:
+ *(d->defs) += " patternUnits=\"userSpaceOnUse\" width=\"6\" height=\"6\" x=\"0\" y=\"0\" >\n";
+ *(d->defs) += " defs) += tmpcolor;
+ *(d->defs) += "\" />\n";
+ *(d->defs) += " \n";
+ break;
+ case U_HS_FDIAGONAL:
+ *(d->defs) += " patternUnits=\"userSpaceOnUse\" width=\"6\" height=\"6\" x=\"0\" y=\"0\" viewBox=\"0 0 6 6\" preserveAspectRatio=\"none\" >\n";
+ *(d->defs) += " defs) += tmpcolor;
+ *(d->defs) += "\" id=\"sub";
+ *(d->defs) += hatchname;
+ *(d->defs) += "\"/>\n";
+ *(d->defs) += "