summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 8519552)
raw | patch | inline | side by side (parent: 8519552)
author | buliabyak <buliabyak@users.sourceforge.net> | |
Mon, 13 Nov 2006 22:05:28 +0000 (22:05 +0000) | ||
committer | buliabyak <buliabyak@users.sourceforge.net> | |
Mon, 13 Nov 2006 22:05:28 +0000 (22:05 +0000) |
src/extension/init.cpp | patch | blob | history | |
src/extension/internal/Makefile_insert | patch | blob | history | |
src/extension/internal/emf-win32-inout.cpp | [new file with mode: 0644] | patch | blob |
src/extension/internal/emf-win32-inout.h | [new file with mode: 0644] | patch | blob |
src/extension/internal/emf-win32-print.cpp | [new file with mode: 0644] | patch | blob |
src/extension/internal/emf-win32-print.h | [new file with mode: 0644] | patch | blob |
diff --git a/src/extension/init.cpp b/src/extension/init.cpp
index a10f21913dbe561a58b952106da95c11a498f5e5..ddbf308eecef18290b2a95b59d10d9fefa570eef 100644 (file)
--- a/src/extension/init.cpp
+++ b/src/extension/init.cpp
#endif
#ifdef WIN32
# include "internal/win32.h"
+# include "internal/emf-win32-inout.h"
+# include "internal/emf-win32-print.h"
#endif
#include "internal/ps-out.h"
#ifdef HAVE_CAIRO_PDF
#endif
#ifdef WIN32
Internal::PrintWin32::init();
+ Internal::PrintEmfWin32::init();
+ Internal::EmfWin32::init();
#endif
Internal::PovOutput::init();
Internal::OdfOutput::init();
index eff097c95abd6bf65180979526e01896811699ef..c89c1e77f2a156e3522fbf3a2e0797df95443d17 100644 (file)
extension/internal/gnome.h
endif
+if WIN32
+extension_internal_win32_sources = \
+ extension/internal/win32.cpp \
+ extension/internal/win32.h \
+ extension/internal/emf-win32-inout.cpp \
+ extension/internal/emf-win32-inout.h \
+ extension/internal/emf-win32-print.cpp \
+ extension/internal/emf-win32-print.h
+endif
+
extension_internal_libinternal_a_SOURCES = \
extension/internal/bluredge.h \
extension/internal/bluredge.cpp \
extension/internal/latex-pstricks-out.h \
extension/internal/wpg-input.cpp \
extension/internal/wpg-input.h \
- $(extension_internal_gnome_print_sources)
-
+ $(extension_internal_gnome_print_sources) \
+ $(extension_internal_win32_sources)
diff --git a/src/extension/internal/emf-win32-inout.cpp b/src/extension/internal/emf-win32-inout.cpp
--- /dev/null
@@ -0,0 +1,1430 @@
+/** \file\r
+ * Enhanced Metafile Input and Output.\r
+ */\r
+/*\r
+ * Authors:\r
+ * Ulf Erikson <ulferikson@users.sf.net>\r
+ *\r
+ * Copyright (C) 2006 Authors\r
+ *\r
+ * Released under GNU GPL, read the file 'COPYING' for more information\r
+ */\r
+/*\r
+ * References:\r
+ * - How to Create & Play Enhanced Metafiles in Win32\r
+ * http://support.microsoft.com/kb/q145999/\r
+ * - INFO: Windows Metafile Functions & Aldus Placeable Metafiles\r
+ * http://support.microsoft.com/kb/q66949/\r
+ * - Metafile Functions\r
+ * http://msdn.microsoft.com/library/en-us/gdi/metafile_0whf.asp\r
+ * - Metafile Structures\r
+ * http://msdn.microsoft.com/library/en-us/gdi/metafile_5hkj.asp\r
+ */\r
+\r
+#ifdef WIN32\r
+\r
+#ifdef HAVE_CONFIG_H\r
+# include "config.h"\r
+#endif\r
+\r
+#include "win32.h"\r
+#include "emf-win32-print.h"\r
+#include "emf-win32-inout.h"\r
+#include "inkscape.h"\r
+#include "sp-path.h"\r
+#include "style.h"\r
+#include "color.h"\r
+#include "display/curve.h"\r
+#include "libnr/n-art-bpath.h"\r
+#include "libnr/nr-point-matrix-ops.h"\r
+#include "gtk/gtk.h"\r
+#include "print.h"\r
+#include "glibmm/i18n.h"\r
+#include "extension/extension.h"\r
+#include "extension/system.h"\r
+#include "extension/print.h"\r
+#include "extension/db.h"\r
+#include "extension/output.h"\r
+#include "document.h"\r
+#include "display/nr-arena.h"\r
+#include "display/nr-arena-item.h"\r
+\r
+#include "libnr/nr-rect.h"\r
+#include "libnr/nr-matrix.h"\r
+#include "libnr/nr-pixblock.h"\r
+\r
+#include <stdio.h>\r
+#include <string.h>\r
+\r
+#include <vector>\r
+#include <string>\r
+\r
+#include "io/sys.h"\r
+\r
+#include "unit-constants.h"\r
+\r
+#include "clear-n_.h"\r
+\r
+\r
+#define PRINT_EMF_WIN32 "org.inkscape.print.emf.win32"\r
+\r
+#ifndef PS_JOIN_MASK\r
+#define PS_JOIN_MASK (PS_JOIN_BEVEL|PS_JOIN_MITER|PS_JOIN_ROUND)\r
+#endif\r
+\r
+\r
+namespace Inkscape {\r
+namespace Extension {\r
+namespace Internal {\r
+\r
+\r
+EmfWin32::EmfWin32 (void) // The null constructor\r
+{\r
+ return;\r
+}\r
+\r
+\r
+EmfWin32::~EmfWin32 (void) //The destructor\r
+{\r
+ return;\r
+}\r
+\r
+\r
+bool\r
+EmfWin32::check (Inkscape::Extension::Extension * module)\r
+{\r
+ if (NULL == Inkscape::Extension::db.get(PRINT_EMF_WIN32))\r
+ return FALSE;\r
+ return TRUE;\r
+}\r
+\r
+\r
+static void\r
+emf_print_document_to_file(SPDocument *doc, gchar const *filename)\r
+{\r
+ Inkscape::Extension::Print *mod;\r
+ SPPrintContext context;\r
+ gchar const *oldconst;\r
+ gchar *oldoutput;\r
+ unsigned int ret;\r
+\r
+ sp_document_ensure_up_to_date(doc);\r
+\r
+ mod = Inkscape::Extension::get_print(PRINT_EMF_WIN32);\r
+ oldconst = mod->get_param_string("destination");\r
+ oldoutput = g_strdup(oldconst);\r
+ mod->set_param_string("destination", (gchar *)filename);\r
+\r
+/* Start */\r
+ context.module = mod;\r
+ /* fixme: This has to go into module constructor somehow */\r
+ /* Create new arena */\r
+ mod->base = SP_ITEM(sp_document_root(doc));\r
+ mod->arena = NRArena::create();\r
+ mod->dkey = sp_item_display_key_new(1);\r
+ mod->root = sp_item_invoke_show(mod->base, mod->arena, mod->dkey, SP_ITEM_SHOW_DISPLAY);\r
+ /* Print document */\r
+ ret = mod->begin(doc);\r
+ if (ret) {\r
+ throw Inkscape::Extension::Output::save_failed();\r
+ }\r
+ sp_item_invoke_print(mod->base, &context);\r
+ ret = mod->finish();\r
+ /* Release arena */\r
+ sp_item_invoke_hide(mod->base, mod->dkey);\r
+ mod->base = NULL;\r
+ nr_arena_item_unref(mod->root);\r
+ mod->root = NULL;\r
+ nr_object_unref((NRObject *) mod->arena);\r
+ mod->arena = NULL;\r
+/* end */\r
+\r
+ mod->set_param_string("destination", oldoutput);\r
+ g_free(oldoutput);\r
+\r
+ return;\r
+}\r
+\r
+\r
+void\r
+EmfWin32::save (Inkscape::Extension::Output *mod, SPDocument *doc, const gchar *uri)\r
+{\r
+ Inkscape::Extension::Extension * ext;\r
+\r
+ ext = Inkscape::Extension::db.get(PRINT_EMF_WIN32);\r
+ if (ext == NULL)\r
+ return;\r
+\r
+// bool old_textToPath = ext->get_param_bool("textToPath");\r
+// bool new_val = mod->get_param_bool("textToPath");\r
+// ext->set_param_bool("textToPath", new_val);\r
+\r
+ gchar * final_name;\r
+ final_name = g_strdup_printf("%s", uri);\r
+ emf_print_document_to_file(doc, final_name);\r
+ g_free(final_name);\r
+\r
+// ext->set_param_bool("textToPath", old_textToPath);\r
+\r
+ return;\r
+}\r
+\r
+\r
+\r
+typedef struct {\r
+ int type;\r
+ ENHMETARECORD *lpEMFR;\r
+} EMF_OBJECT, *PEMF_OBJECT;\r
+\r
+typedef struct emf_callback_data {\r
+ Glib::ustring *outsvg;\r
+ Glib::ustring *path;\r
+ struct SPStyle style;\r
+ bool stroke_set;\r
+ bool fill_set;\r
+ double xDPI, yDPI;\r
+\r
+ SIZEL sizeWnd;\r
+ SIZEL sizeView;\r
+ float PixelsX;\r
+ float PixelsY;\r
+ float MMX;\r
+ float MMY;\r
+ float dwInchesX;\r
+ float dwInchesY;\r
+ POINTL winorg;\r
+ POINTL vieworg;\r
+ double ScaleX, ScaleY;\r
+\r
+ int n_obj;\r
+ PEMF_OBJECT emf_obj;\r
+} EMF_CALLBACK_DATA, *PEMF_CALLBACK_DATA;\r
+\r
+\r
+static void\r
+output_style(PEMF_CALLBACK_DATA d, int iType)\r
+{\r
+ SVGOStringStream tmp_style;\r
+ char tmp[1024] = {0};\r
+\r
+ *(d->outsvg) += "\n\tstyle=\"";\r
+ if (iType == EMR_STROKEPATH || !d->fill_set) {\r
+ tmp_style << "fill:none;";\r
+ } else {\r
+ float rgb[3];\r
+ sp_color_get_rgb_floatv( &(d->style.fill.value.color), rgb );\r
+ snprintf(tmp, 1023,\r
+ "fill:#%02x%02x%02x;",\r
+ SP_COLOR_F_TO_U(rgb[0]),\r
+ SP_COLOR_F_TO_U(rgb[1]),\r
+ SP_COLOR_F_TO_U(rgb[2]));\r
+ tmp_style << tmp;\r
+ snprintf(tmp, 1023,\r
+ "fill-rule:%s;",\r
+ d->style.fill_rule.value != 0 ? "evenodd" : "nonzero");\r
+ tmp_style << tmp;\r
+ tmp_style << "fill-opacity:1;";\r
+ }\r
+\r
+ if (iType == EMR_FILLPATH || !d->stroke_set) {\r
+ tmp_style << "stroke:none;";\r
+ } else {\r
+ float rgb[3];\r
+ sp_color_get_rgb_floatv(&(d->style.stroke.value.color), rgb);\r
+ snprintf(tmp, 1023,\r
+ "stroke:#%02x%02x%02x;",\r
+ SP_COLOR_F_TO_U(rgb[0]),\r
+ SP_COLOR_F_TO_U(rgb[1]),\r
+ SP_COLOR_F_TO_U(rgb[2]));\r
+ tmp_style << tmp;\r
+\r
+ tmp_style << "stroke-width:" <<\r
+ MAX( 0.001, d->style.stroke_width.value ) << "px;";\r
+\r
+ tmp_style << "stroke-linejoin:" <<\r
+ (d->style.stroke_linejoin.computed == 0 ? "miter" :\r
+ d->style.stroke_linejoin.computed == 1 ? "round" :\r
+ d->style.stroke_linejoin.computed == 2 ? "bevel" :\r
+ "unknown") << ";";\r
+\r
+ if (d->style.stroke_linejoin.computed == 0) {\r
+ tmp_style << "stroke-miterlimit:" <<\r
+ MAX( 0.01, d->style.stroke_miterlimit.value ) << ";";\r
+ }\r
+\r
+ if (d->style.stroke_dasharray_set &&\r
+ d->style.stroke_dash.n_dash && d->style.stroke_dash.dash)\r
+ {\r
+ tmp_style << "stroke-dasharray:";\r
+ for (int i=0; i<d->style.stroke_dash.n_dash; i++) {\r
+ if (i)\r
+ tmp_style << ",";\r
+ tmp_style << d->style.stroke_dash.dash[i];\r
+ }\r
+ tmp_style << ";";\r
+ tmp_style << "stroke-dashoffset:0;";\r
+ } else {\r
+ tmp_style << "stroke-dasharray:none;";\r
+ }\r
+ tmp_style << "stroke-opacity:1;";\r
+ }\r
+ tmp_style << "\" ";\r
+\r
+ *(d->outsvg) += tmp_style.str().c_str();\r
+}\r
+\r
+\r
+static double\r
+pix_x_to_point(PEMF_CALLBACK_DATA d, double px)\r
+{\r
+ double tmp = px - d->winorg.x;\r
+ tmp *= (double) PX_PER_IN / d->ScaleX;\r
+ tmp += d->vieworg.x;\r
+ return tmp;\r
+}\r
+\r
+\r
+static double\r
+pix_y_to_point(PEMF_CALLBACK_DATA d, double px)\r
+{\r
+ double tmp = px - d->winorg.y;\r
+ tmp *= (double) PX_PER_IN / d->ScaleY;\r
+ tmp += d->vieworg.y;\r
+ return tmp;\r
+}\r
+\r
+\r
+static double\r
+pix_size_to_point(PEMF_CALLBACK_DATA d, double px)\r
+{\r
+ double tmp = px;\r
+ tmp *= (double) PX_PER_IN / d->ScaleX;\r
+ return tmp;\r
+}\r
+\r
+\r
+static void\r
+select_pen(PEMF_CALLBACK_DATA d, int index)\r
+{\r
+ PEMRCREATEPEN pEmr = NULL;\r
+\r
+ if (index >= 0 && index < d->n_obj)\r
+ pEmr = (PEMRCREATEPEN) d->emf_obj[index].lpEMFR;\r
+\r
+ if (!pEmr)\r
+ return;\r
+\r
+ switch (pEmr->lopn.lopnStyle) {\r
+ default:\r
+ {\r
+ d->style.stroke_dasharray_set = 0;\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (pEmr->lopn.lopnWidth.x) {\r
+ d->style.stroke_width.value = pix_size_to_point( d, pEmr->lopn.lopnWidth.x );\r
+ } else { // this stroke should always be rendered as 1 pixel wide, independent of zoom level (can that be done in SVG?)\r
+ d->style.stroke_width.value = 1.0;\r
+ }\r
+\r
+ double r, g, b;\r
+ r = SP_COLOR_U_TO_F( GetRValue(pEmr->lopn.lopnColor) );\r
+ g = SP_COLOR_U_TO_F( GetGValue(pEmr->lopn.lopnColor) );\r
+ b = SP_COLOR_U_TO_F( GetBValue(pEmr->lopn.lopnColor) );\r
+ sp_color_set_rgb_float( &(d->style.stroke.value.color), r,g,b );\r
+\r
+ d->style.stroke_linejoin.computed = 1;\r
+\r
+ d->stroke_set = true;\r
+}\r
+\r
+\r
+static void\r
+select_extpen(PEMF_CALLBACK_DATA d, int index)\r
+{\r
+ PEMREXTCREATEPEN pEmr = NULL;\r
+\r
+ if (index >= 0 && index < d->n_obj)\r
+ pEmr = (PEMREXTCREATEPEN) d->emf_obj[index].lpEMFR;\r
+\r
+ if (!pEmr)\r
+ return;\r
+\r
+ switch (pEmr->elp.elpPenStyle & PS_STYLE_MASK) {\r
+ case PS_USERSTYLE:\r
+ {\r
+ if (pEmr->elp.elpNumEntries) {\r
+ d->style.stroke_dash.n_dash = pEmr->elp.elpNumEntries;\r
+ if (d->style.stroke_dash.dash)\r
+ delete[] d->style.stroke_dash.dash;\r
+ d->style.stroke_dash.dash = new double[pEmr->elp.elpNumEntries];\r
+ for (unsigned int i=0; i<pEmr->elp.elpNumEntries; i++) {\r
+ d->style.stroke_dash.dash[i] = pix_size_to_point( d, pEmr->elp.elpStyleEntry[i] );\r
+ }\r
+ d->style.stroke_dasharray_set = 1;\r
+ } else {\r
+ d->style.stroke_dasharray_set = 0;\r
+ }\r
+ break;\r
+ }\r
+ default:\r
+ {\r
+ d->style.stroke_dasharray_set = 0;\r
+ break;\r
+ }\r
+ }\r
+\r
+ switch (pEmr->elp.elpPenStyle & PS_ENDCAP_MASK) {\r
+ case PS_ENDCAP_ROUND:\r
+ {\r
+ d->style.stroke_linecap.computed = 1;\r
+ break;\r
+ }\r
+ case PS_ENDCAP_SQUARE:\r
+ {\r
+ d->style.stroke_linecap.computed = 2;\r
+ break;\r
+ }\r
+ case PS_ENDCAP_FLAT:\r
+ default:\r
+ {\r
+ d->style.stroke_linecap.computed = 0;\r
+ break;\r
+ }\r
+ }\r
+\r
+ switch (pEmr->elp.elpPenStyle & PS_JOIN_MASK) {\r
+ case PS_JOIN_BEVEL:\r
+ {\r
+ d->style.stroke_linejoin.computed = 2;\r
+ break;\r
+ }\r
+ case PS_JOIN_MITER:\r
+ {\r
+ d->style.stroke_linejoin.computed = 0;\r
+ break;\r
+ }\r
+ case PS_JOIN_ROUND:\r
+ default:\r
+ {\r
+ d->style.stroke_linejoin.computed = 1;\r
+ break;\r
+ }\r
+ }\r
+\r
+ d->style.stroke_width.value = pix_size_to_point( d, pEmr->elp.elpWidth );\r
+\r
+ double r, g, b;\r
+ r = SP_COLOR_U_TO_F( GetRValue(pEmr->elp.elpColor) );\r
+ g = SP_COLOR_U_TO_F( GetGValue(pEmr->elp.elpColor) );\r
+ b = SP_COLOR_U_TO_F( GetBValue(pEmr->elp.elpColor) );\r
+\r
+ sp_color_set_rgb_float( &(d->style.stroke.value.color), r,g,b );\r
+\r
+ d->stroke_set = true;\r
+}\r
+\r
+\r
+static void\r
+select_brush(PEMF_CALLBACK_DATA d, int index)\r
+{\r
+ PEMRCREATEBRUSHINDIRECT pEmr = NULL;\r
+\r
+ if (index >= 0 && index < d->n_obj)\r
+ pEmr = (PEMRCREATEBRUSHINDIRECT) d->emf_obj[index].lpEMFR;\r
+\r
+ if (!pEmr)\r
+ return;\r
+\r
+ if (pEmr->lb.lbStyle == BS_SOLID) {\r
+ double r, g, b;\r
+ r = SP_COLOR_U_TO_F( GetRValue(pEmr->lb.lbColor) );\r
+ g = SP_COLOR_U_TO_F( GetGValue(pEmr->lb.lbColor) );\r
+ b = SP_COLOR_U_TO_F( GetBValue(pEmr->lb.lbColor) );\r
+ sp_color_set_rgb_float( &(d->style.fill.value.color), r,g,b );\r
+ }\r
+\r
+ d->fill_set = true;\r
+}\r
+\r
+\r
+static void\r
+delete_object(PEMF_CALLBACK_DATA d, int index)\r
+{\r
+ if (index >= 0 && index < d->n_obj) {\r
+ d->emf_obj[index].type = 0;\r
+ if (d->emf_obj[index].lpEMFR)\r
+ free(d->emf_obj[index].lpEMFR);\r
+ d->emf_obj[index].lpEMFR = NULL;\r
+ }\r
+}\r
+\r
+\r
+static void\r
+insert_object(PEMF_CALLBACK_DATA d, int index, int type, ENHMETARECORD *pObj)\r
+{\r
+ if (index >= 0 && index < d->n_obj) {\r
+ delete_object(d, index);\r
+ d->emf_obj[index].type = type;\r
+ d->emf_obj[index].lpEMFR = pObj;\r
+ }\r
+}\r
+\r
+\r
+static int CALLBACK\r
+myEnhMetaFileProc(HDC hDC, HANDLETABLE *lpHTable, ENHMETARECORD *lpEMFR, int nObj, LPARAM lpData)\r
+{\r
+ PEMF_CALLBACK_DATA d;\r
+ SVGOStringStream tmp_outsvg;\r
+ SVGOStringStream tmp_path;\r
+ SVGOStringStream tmp_str;\r
+\r
+ d = (PEMF_CALLBACK_DATA) lpData;\r
+\r
+ switch (lpEMFR->iType)\r
+ {\r
+ case EMR_HEADER:\r
+ {\r
+ ENHMETAHEADER *pEmr = (ENHMETAHEADER *) lpEMFR;\r
+ tmp_outsvg << "<svg\n";\r
+\r
+ d->xDPI = 2540;\r
+ d->yDPI = 2540;\r
+\r
+ d->PixelsX = pEmr->rclFrame.right - pEmr->rclFrame.left;\r
+ d->PixelsY = pEmr->rclFrame.bottom - pEmr->rclFrame.top;\r
+\r
+ d->MMX = d->PixelsX / 100.0;\r
+ d->MMY = d->PixelsY / 100.0;\r
+\r
+ tmp_outsvg <<\r
+ " width=\"" << d->MMX << "mm\"\n" <<\r
+ " height=\"" << d->MMY << "mm\">\n";\r
+\r
+ if (pEmr->nHandles) {\r
+ d->n_obj = pEmr->nHandles;\r
+ d->emf_obj = new EMF_OBJECT[d->n_obj];\r
+ } else {\r
+ d->emf_obj = NULL;\r
+ }\r
+\r
+ break;\r
+ }\r
+ case EMR_POLYBEZIER:\r
+ {\r
+ PEMRPOLYBEZIER pEmr = (PEMRPOLYBEZIER) lpEMFR;\r
+ DWORD i,j;\r
+\r
+ if (pEmr->cptl<4)\r
+ break;\r
+\r
+ *(d->outsvg) += " <path ";\r
+ output_style(d, EMR_STROKEPATH);\r
+ *(d->outsvg) += "\n\td=\"";\r
+\r
+ tmp_str <<\r
+ "\n\tM " <<\r
+ pix_x_to_point( d, pEmr->aptl[0].x ) << " " <<\r
+ pix_x_to_point( d, pEmr->aptl[0].y) << " ";\r
+\r
+ for (i=1; i<pEmr->cptl; ) {\r
+ tmp_str << "\n\tC ";\r
+ for (j=0; j<3 && i<pEmr->cptl; j++,i++) {\r
+ tmp_str <<\r
+ pix_x_to_point( d, pEmr->aptl[i].x ) << " " <<\r
+ pix_y_to_point( d, pEmr->aptl[i].y ) << " ";\r
+ }\r
+ }\r
+\r
+ *(d->outsvg) += tmp_str.str().c_str();\r
+ *(d->outsvg) += " \" /> \n";\r
+\r
+ break;\r
+ }\r
+ case EMR_POLYGON:\r
+ {\r
+ EMRPOLYGON *pEmr = (EMRPOLYGON *) lpEMFR;\r
+ DWORD i;\r
+\r
+ if (pEmr->cptl < 2)\r
+ break;\r
+\r
+ *(d->outsvg) += " <path ";\r
+ output_style(d, EMR_STROKEANDFILLPATH);\r
+ *(d->outsvg) += "\n\td=\"";\r
+\r
+ tmp_str <<\r
+ "\n\tM " <<\r
+ pix_x_to_point( d, pEmr->aptl[0].x ) << " " <<\r
+ pix_y_to_point( d, pEmr->aptl[0].y ) << " ";\r
+\r
+ for (i=1; i<pEmr->cptl; i++) {\r
+ tmp_str <<\r
+ "\n\tL " <<\r
+ pix_x_to_point( d, pEmr->aptl[i].x ) << " " <<\r
+ pix_y_to_point( d, pEmr->aptl[i].y ) << " ";\r
+ }\r
+\r
+ *(d->outsvg) += tmp_str.str().c_str();\r
+ *(d->outsvg) += " z \" /> \n";\r
+\r
+ break;\r
+ }\r
+ case EMR_POLYLINE:\r
+ {\r
+ EMRPOLYLINE *pEmr = (EMRPOLYLINE *) lpEMFR;\r
+ DWORD i;\r
+\r
+ if (pEmr->cptl<2)\r
+ break;\r
+\r
+ *(d->outsvg) += " <path ";\r
+ output_style(d, EMR_STROKEPATH);\r
+ *(d->outsvg) += "\n\td=\"";\r
+\r
+ tmp_str <<\r
+ "\n\tM " <<\r
+ pix_x_to_point( d, pEmr->aptl[0].x ) << " " <<\r
+ pix_y_to_point( d, pEmr->aptl[0].y ) << " ";\r
+\r
+ for (i=1; i<pEmr->cptl; i++) {\r
+ tmp_str <<\r
+ "\n\tL " <<\r
+ pix_x_to_point( d, pEmr->aptl[i].x ) << " " <<\r
+ pix_y_to_point( d, pEmr->aptl[i].y ) << " ";\r
+ }\r
+\r
+ *(d->outsvg) += tmp_str.str().c_str();\r
+ *(d->outsvg) += " \" /> \n";\r
+\r
+ break;\r
+ }\r
+ case EMR_POLYBEZIERTO:\r
+ {\r
+ PEMRPOLYBEZIERTO pEmr = (PEMRPOLYBEZIERTO) lpEMFR;\r
+ DWORD i,j;\r
+\r
+ for (i=0; i<pEmr->cptl;) {\r
+ tmp_path << "\n\tC ";\r
+ for (j=0; j<3 && i<pEmr->cptl; j++,i++) {\r
+ tmp_path <<\r
+ pix_x_to_point( d, pEmr->aptl[i].x ) << " " <<\r
+ pix_y_to_point( d, pEmr->aptl[i].y ) << " ";\r
+ }\r
+ }\r
+\r
+ break;\r
+ }\r
+ case EMR_POLYLINETO:\r
+ {\r
+ PEMRPOLYLINETO pEmr = (PEMRPOLYLINETO) lpEMFR;\r
+ DWORD i;\r
+\r
+ for (i=0; i<pEmr->cptl;i++) {\r
+ tmp_path <<\r
+ "\n\tL " <<\r
+ pix_x_to_point( d, pEmr->aptl[i].x ) << " " <<\r
+ pix_y_to_point( d, pEmr->aptl[i].y ) << " ";\r
+ }\r
+\r
+ break;\r
+ }\r
+ case EMR_POLYPOLYLINE:\r
+ break;\r
+ case EMR_POLYPOLYGON:\r
+ break;\r
+ case EMR_SETWINDOWEXTEX:\r
+ {\r
+ PEMRSETWINDOWEXTEX pEmr = (PEMRSETWINDOWEXTEX) lpEMFR;\r
+\r
+ d->sizeWnd = pEmr->szlExtent;\r
+ d->PixelsX = d->sizeWnd.cx;\r
+ d->PixelsY = d->sizeWnd.cy;\r
+\r
+ d->ScaleX = d->xDPI / (100*d->MMX / d->PixelsX);\r
+ d->ScaleY = d->yDPI / (100*d->MMY / d->PixelsY);\r
+\r
+ break;\r
+ }\r
+ case EMR_SETWINDOWORGEX:\r
+ {\r
+ PEMRSETWINDOWORGEX pEmr = (PEMRSETWINDOWORGEX) lpEMFR;\r
+ d->winorg = pEmr->ptlOrigin;\r
+ break;\r
+ }\r
+ case EMR_SETVIEWPORTEXTEX:\r
+ {\r
+ PEMRSETVIEWPORTEXTEX pEmr = (PEMRSETVIEWPORTEXTEX) lpEMFR;\r
+\r
+ d->sizeView = pEmr->szlExtent;\r
+\r
+ if (d->sizeWnd.cx && d->sizeWnd.cy) {\r
+ HDC hScreenDC = GetDC( NULL );\r
+\r
+ float scrPixelsX = (float)GetDeviceCaps( hScreenDC, HORZRES );\r
+ float scrPixelsY = (float)GetDeviceCaps( hScreenDC, VERTRES );\r
+ float scrMMX = (float)GetDeviceCaps( hScreenDC, HORZSIZE );\r
+ float scrMMY = (float)GetDeviceCaps( hScreenDC, VERTSIZE );\r
+\r
+ ReleaseDC( NULL, hScreenDC );\r
+\r
+ d->dwInchesX = d->sizeView.cx / (25.4f*scrPixelsX/scrMMX);\r
+ d->dwInchesY = d->sizeView.cy / (25.4f*scrPixelsY/scrMMY);\r
+ d->xDPI = d->sizeWnd.cx / d->dwInchesX;\r
+ d->yDPI = d->sizeWnd.cy / d->dwInchesY;\r
+\r
+ if (1) {\r
+ d->xDPI = 2540;\r
+ d->yDPI = 2540;\r
+ d->dwInchesX = d->PixelsX / d->xDPI;\r
+ d->dwInchesY = d->PixelsY / d->yDPI;\r
+ d->ScaleX = d->xDPI;\r
+ d->ScaleY = d->yDPI;\r
+ }\r
+\r
+ d->MMX = d->dwInchesX * MM_PER_IN;\r
+ d->MMY = d->dwInchesY * MM_PER_IN;\r
+ }\r
+\r
+ break;\r
+ }\r
+ case EMR_SETVIEWPORTORGEX:\r
+ {\r
+ PEMRSETVIEWPORTORGEX pEmr = (PEMRSETVIEWPORTORGEX) lpEMFR;\r
+ d->vieworg = pEmr->ptlOrigin;\r
+ break;\r
+ }\r
+ case EMR_SETBRUSHORGEX:\r
+ break;\r
+ case EMR_EOF:\r
+ {\r
+ tmp_outsvg << "</svg>\n";\r
+ break;\r
+ }\r
+ case EMR_SETPIXELV:\r
+ break;\r
+ case EMR_SETMAPPERFLAGS:\r
+ break;\r
+ case EMR_SETMAPMODE:\r
+ break;\r
+ case EMR_SETBKMODE:\r
+ break;\r
+ case EMR_SETPOLYFILLMODE:\r
+ {\r
+ PEMRSETPOLYFILLMODE pEmr = (PEMRSETPOLYFILLMODE) lpEMFR;\r
+ d->style.fill_rule.value =\r
+ (pEmr->iMode == WINDING ? 0 :\r
+ pEmr->iMode == ALTERNATE ? 1 : 0);\r
+ break;\r
+ }\r
+ case EMR_SETROP2:\r
+ break;\r
+ case EMR_SETSTRETCHBLTMODE:\r
+ break;\r
+ case EMR_SETTEXTALIGN:\r
+ break;\r
+ case EMR_SETCOLORADJUSTMENT:\r
+ break;\r
+ case EMR_SETTEXTCOLOR:\r
+ break;\r
+ case EMR_SETBKCOLOR:\r
+ break;\r
+ case EMR_OFFSETCLIPRGN:\r
+ break;\r
+ case EMR_MOVETOEX:\r
+ {\r
+ PEMRMOVETOEX pEmr = (PEMRMOVETOEX) lpEMFR;\r
+ tmp_path <<\r
+ "\n\tM " <<\r
+ pix_x_to_point( d, pEmr->ptl.x ) << " " <<\r
+ pix_y_to_point( d, pEmr->ptl.y ) << " ";\r
+ break;\r
+ }\r
+ case EMR_SETMETARGN:\r
+ break;\r
+ case EMR_EXCLUDECLIPRECT:\r
+ break;\r
+ case EMR_INTERSECTCLIPRECT:\r
+ break;\r
+ case EMR_SCALEVIEWPORTEXTEX:\r
+ break;\r
+ case EMR_SCALEWINDOWEXTEX:\r
+ break;\r
+ case EMR_SAVEDC:\r
+ break;\r
+ case EMR_RESTOREDC:\r
+ break;\r
+ case EMR_SETWORLDTRANSFORM:\r
+ break;\r
+ case EMR_MODIFYWORLDTRANSFORM:\r
+ break;\r
+ case EMR_SELECTOBJECT:\r
+ {\r
+ PEMRSELECTOBJECT pEmr = (PEMRSELECTOBJECT) lpEMFR;\r
+ unsigned int index = pEmr->ihObject;\r
+\r
+ if (index >= ENHMETA_STOCK_OBJECT) {\r
+ index -= ENHMETA_STOCK_OBJECT;\r
+ switch (index) {\r
+ case NULL_BRUSH:\r
+ d->fill_set = false;\r
+ break;\r
+ case BLACK_BRUSH:\r
+ case DKGRAY_BRUSH:\r
+ case GRAY_BRUSH:\r
+ case LTGRAY_BRUSH:\r
+ case WHITE_BRUSH:\r
+ {\r
+ float val = 0;\r
+ switch (index) {\r
+ case BLACK_BRUSH:\r
+ val = 0.0 / 255.0;\r
+ break;\r
+ case DKGRAY_BRUSH:\r
+ val = 64.0 / 255.0;\r
+ break;\r
+ case GRAY_BRUSH:\r
+ val = 128.0 / 255.0;\r
+ break;\r
+ case LTGRAY_BRUSH:\r
+ val = 192.0 / 255.0;\r
+ break;\r
+ case WHITE_BRUSH:\r
+ val = 255.0 / 255.0;\r
+ break;\r
+ }\r
+ sp_color_set_rgb_float( &(d->style.fill.value.color), val,val,val );\r
+\r
+ d->fill_set = true;\r
+ break;\r
+ }\r
+ case NULL_PEN:\r
+ d->stroke_set = false;\r
+ break;\r
+ case BLACK_PEN:\r
+ case WHITE_PEN:\r
+ {\r
+ float val = index == BLACK_PEN ? 0 : 1;\r
+ d->style.stroke_dasharray_set = 0;\r
+ d->style.stroke_width.value = 1.0;\r
+ sp_color_set_rgb_float( &(d->style.stroke.value.color), val,val,val );\r
+\r
+ d->stroke_set = true;\r
+\r
+ break;\r
+ }\r
+ }\r
+ } else {\r
+ if (index >= 0 && index < d->n_obj) {\r
+ switch (d->emf_obj[index].type)\r
+ {\r
+ case EMR_CREATEPEN:\r
+ select_pen(d, index);\r
+ break;\r
+ case EMR_CREATEBRUSHINDIRECT:\r
+ select_brush(d, index);\r
+ break;\r
+ case EMR_EXTCREATEPEN:\r
+ select_extpen(d, index);\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ break;\r
+ }\r
+ case EMR_CREATEPEN:\r
+ {\r
+ PEMRCREATEPEN pEmr = (PEMRCREATEPEN) lpEMFR;\r
+ int index = pEmr->ihPen;\r
+\r
+ EMRCREATEPEN *pPen =\r
+ (EMRCREATEPEN *) malloc( sizeof(EMREXTCREATEPEN) );\r
+ pPen->lopn = pEmr->lopn;\r
+ insert_object(d, index, EMR_CREATEPEN, (ENHMETARECORD *) pPen);\r
+\r
+ break;\r
+ }\r
+ case EMR_CREATEBRUSHINDIRECT:\r
+ {\r
+ PEMRCREATEBRUSHINDIRECT pEmr = (PEMRCREATEBRUSHINDIRECT) lpEMFR;\r
+ int index = pEmr->ihBrush;\r
+\r
+ EMRCREATEBRUSHINDIRECT *pBrush =\r
+ (EMRCREATEBRUSHINDIRECT *) malloc( sizeof(EMRCREATEBRUSHINDIRECT) );\r
+ pBrush->lb = pEmr->lb;\r
+ insert_object(d, index, EMR_CREATEBRUSHINDIRECT, (ENHMETARECORD *) pBrush);\r
+\r
+ break;\r
+ }\r
+ case EMR_DELETEOBJECT:\r
+ break;\r
+ case EMR_ANGLEARC:\r
+ break;\r
+ case EMR_ELLIPSE:\r
+ break;\r
+ case EMR_RECTANGLE:\r
+ break;\r
+ case EMR_ROUNDRECT:\r
+ break;\r
+ case EMR_ARC:\r
+ break;\r
+ case EMR_CHORD:\r
+ break;\r
+ case EMR_PIE:\r
+ break;\r
+ case EMR_SELECTPALETTE:\r
+ break;\r
+ case EMR_CREATEPALETTE:\r
+ break;\r
+ case EMR_SETPALETTEENTRIES:\r
+ break;\r
+ case EMR_RESIZEPALETTE:\r
+ break;\r
+ case EMR_REALIZEPALETTE:\r
+ break;\r
+ case EMR_EXTFLOODFILL:\r
+ break;\r
+ case EMR_LINETO:\r
+ {\r
+ PEMRLINETO pEmr = (PEMRLINETO) lpEMFR;\r
+ tmp_path <<\r
+ "\n\tL " <<\r
+ pix_x_to_point( d, pEmr->ptl.x ) << " " <<\r
+ pix_y_to_point( d, pEmr->ptl.y ) << " ";\r
+ break;\r
+ }\r
+ case EMR_ARCTO:\r
+ break;\r
+ case EMR_POLYDRAW:\r
+ break;\r
+ case EMR_SETARCDIRECTION:\r
+ break;\r
+ case EMR_SETMITERLIMIT:\r
+ {\r
+ PEMRSETMITERLIMIT pEmr = (PEMRSETMITERLIMIT) lpEMFR;\r
+ d->style.stroke_miterlimit.value = pix_size_to_point( d, pEmr->eMiterLimit );\r
+\r
+ if (d->style.stroke_miterlimit.value < 1)\r
+ d->style.stroke_miterlimit.value = 1.0;\r
+\r
+ break;\r
+ }\r
+ case EMR_BEGINPATH:\r
+ {\r
+ tmp_path << " d=\"";\r
+ *(d->path) = "";\r
+ break;\r
+ }\r
+ case EMR_ENDPATH:\r
+ {\r
+ tmp_path << "\"";\r
+ break;\r
+ }\r
+ case EMR_CLOSEFIGURE:\r
+ {\r
+ tmp_path << "\n\tz";\r
+ break;\r
+ }\r
+ case EMR_FILLPATH:\r
+ case EMR_STROKEANDFILLPATH:\r
+ case EMR_STROKEPATH:\r
+ {\r
+ *(d->outsvg) += " <path ";\r
+ output_style(d, lpEMFR->iType);\r
+ *(d->outsvg) += "\n\t";\r
+ *(d->outsvg) += *(d->path);\r
+ *(d->outsvg) += " /> \n";\r
+ break;\r
+ }\r
+ case EMR_FLATTENPATH:\r
+ break;\r
+ case EMR_WIDENPATH:\r
+ break;\r
+ case EMR_SELECTCLIPPATH:\r
+ break;\r
+ case EMR_ABORTPATH:\r
+ break;\r
+ case EMR_GDICOMMENT:\r
+ break;\r
+ case EMR_FILLRGN:\r
+ break;\r
+ case EMR_FRAMERGN:\r
+ break;\r
+ case EMR_INVERTRGN:\r
+ break;\r
+ case EMR_PAINTRGN:\r
+ break;\r
+ case EMR_EXTSELECTCLIPRGN:\r
+ break;\r
+ case EMR_BITBLT:\r
+ break;\r
+ case EMR_STRETCHBLT:\r
+ break;\r
+ case EMR_MASKBLT:\r
+ break;\r
+ case EMR_PLGBLT:\r
+ break;\r
+ case EMR_SETDIBITSTODEVICE:\r
+ break;\r
+ case EMR_STRETCHDIBITS:\r
+ break;\r
+ case EMR_EXTCREATEFONTINDIRECTW:\r
+ break;\r
+ case EMR_EXTTEXTOUTA:\r
+ break;\r
+ case EMR_EXTTEXTOUTW:\r
+ break;\r
+ case EMR_POLYBEZIER16:\r
+ {\r
+ PEMRPOLYBEZIER16 pEmr = (PEMRPOLYBEZIER16) lpEMFR;\r
+ POINTS *apts = (POINTS *) pEmr->apts; // Bug in MinGW wingdi.h ?\r
+ DWORD i,j;\r
+\r
+ if (pEmr->cpts<4)\r
+ break;\r
+\r
+ *(d->outsvg) += " <path ";\r
+ output_style(d, EMR_STROKEPATH);\r
+ *(d->outsvg) += "\n\td=\"";\r
+\r
+ tmp_str <<\r
+ "\n\tM " <<\r
+ pix_x_to_point( d, apts[0].x ) << " " <<\r
+ pix_y_to_point( d, apts[0].y ) << " ";\r
+\r
+ for (i=1; i<pEmr->cpts; ) {\r
+ tmp_str << "\n\tC ";\r
+ for (j=0; j<3 && i<pEmr->cpts; j++,i++) {\r
+ tmp_str <<\r
+ pix_x_to_point( d, apts[i].x ) << " " <<\r
+ pix_y_to_point( d, apts[i].y ) << " ";\r
+ }\r
+ }\r
+\r
+ *(d->outsvg) += tmp_str.str().c_str();\r
+ *(d->outsvg) += " \" /> \n";\r
+\r
+ break;\r
+ }\r
+ case EMR_POLYGON16:\r
+ {\r
+ PEMRPOLYGON16 pEmr = (PEMRPOLYGON16) lpEMFR;\r
+ POINTS *apts = (POINTS *) pEmr->apts; // Bug in MinGW wingdi.h ?\r
+ unsigned int i;\r
+\r
+ *(d->outsvg) += "<path ";\r
+ output_style(d, EMR_STROKEANDFILLPATH);\r
+ *(d->outsvg) += "\n\td=\"";\r
+\r
+ // skip the first point?\r
+ tmp_path << "\n\tM " <<\r
+ pix_x_to_point( d, apts[1].x ) << " " <<\r
+ pix_y_to_point( d, apts[1].y ) << " ";\r
+\r
+ for (i=2; i<pEmr->cpts; i++) {\r
+ tmp_path << "\n\tL " <<\r
+ pix_x_to_point( d, apts[i].x ) << " " <<\r
+ pix_y_to_point( d, apts[i].y ) << " ";\r
+ }\r
+\r
+ *(d->outsvg) += tmp_path.str().c_str();\r
+ *(d->outsvg) += " z \" /> \n";\r
+\r
+ break;\r
+ }\r
+ case EMR_POLYLINE16:\r
+ {\r
+ EMRPOLYLINE16 *pEmr = (EMRPOLYLINE16 *) lpEMFR;\r
+ POINTS *apts = (POINTS *) pEmr->apts; // Bug in MinGW wingdi.h ?\r
+ DWORD i;\r
+\r
+ if (pEmr->cpts<2)\r
+ break;\r
+\r
+ *(d->outsvg) += " <path ";\r
+ output_style(d, EMR_STROKEPATH);\r
+ *(d->outsvg) += "\n\td=\"";\r
+\r
+ tmp_str <<\r
+ "\n\tM " <<\r
+ pix_x_to_point( d, apts[0].x ) << " " <<\r
+ pix_y_to_point( d, apts[0].y ) << " ";\r
+\r
+ for (i=1; i<pEmr->cpts; i++) {\r
+ tmp_str <<\r
+ "\n\tL " <<\r
+ pix_x_to_point( d, apts[i].x ) << " " <<\r
+ pix_y_to_point( d, apts[i].y ) << " ";\r
+ }\r
+\r
+ *(d->outsvg) += tmp_str.str().c_str();\r
+ *(d->outsvg) += " \" /> \n";\r
+\r
+ break;\r
+ }\r
+ case EMR_POLYBEZIERTO16:\r
+ {\r
+ PEMRPOLYBEZIERTO16 pEmr = (PEMRPOLYBEZIERTO16) lpEMFR;\r
+ POINTS *apts = (POINTS *) pEmr->apts; // Bug in MinGW wingdi.h ?\r
+ DWORD i,j;\r
+\r
+ for (i=0; i<pEmr->cpts;) {\r
+ tmp_path << "\n\tC ";\r
+ for (j=0; j<3 && i<pEmr->cpts; j++,i++) {\r
+ tmp_path <<\r
+ pix_x_to_point( d, apts[i].x ) << " " <<\r
+ pix_y_to_point( d, apts[i].y ) << " ";\r
+ }\r
+ }\r
+\r
+ break;\r
+ }\r
+ case EMR_POLYLINETO16:\r
+ {\r
+ PEMRPOLYLINETO16 pEmr = (PEMRPOLYLINETO16) lpEMFR;\r
+ POINTS *apts = (POINTS *) pEmr->apts; // Bug in MinGW wingdi.h ?\r
+ DWORD i;\r
+\r
+ for (i=0; i<pEmr->cpts;i++) {\r
+ tmp_path <<\r
+ "\n\tL " <<\r
+ pix_x_to_point( d, apts[i].x ) << " " <<\r
+ pix_y_to_point( d, apts[i].y ) << " ";\r
+ }\r
+\r
+ break;\r
+ }\r
+ case EMR_POLYPOLYLINE16:\r
+ break;\r
+ case EMR_POLYPOLYGON16:\r
+ {\r
+ PEMRPOLYPOLYGON16 pEmr = (PEMRPOLYPOLYGON16) lpEMFR;\r
+ unsigned int n, i, j;\r
+\r
+ *(d->outsvg) += "<path ";\r
+ output_style(d, EMR_STROKEANDFILLPATH);\r
+ *(d->outsvg) += "\n\td=\"";\r
+\r
+ i = pEmr->nPolys-1; // ???\r
+ for (n=0; n<pEmr->nPolys /*&& i<pEmr->cpts*/; n++) {\r
+ SVGOStringStream poly_path;\r
+\r
+ poly_path << "\n\tM " <<\r
+ pix_x_to_point( d, pEmr->apts[i].x ) << " " <<\r
+ pix_y_to_point( d, pEmr->apts[i].y ) << " ";\r
+ i++;\r
+\r
+ for (j=1; j<pEmr->aPolyCounts[n] /*&& i<pEmr->cpts*/; j++) {\r
+ poly_path << "\n\tL " <<\r
+ pix_x_to_point( d, pEmr->apts[i].x ) << " " <<\r
+ pix_y_to_point( d, pEmr->apts[i].y ) << " ";\r
+ i++;\r
+ }\r
+\r
+ *(d->outsvg) += poly_path.str().c_str();\r
+ *(d->outsvg) += " z \n";\r
+ }\r
+\r
+ *(d->outsvg) += " \" /> \n";\r
+ break;\r
+ }\r
+ case EMR_POLYDRAW16:\r
+ break;\r
+ case EMR_CREATEMONOBRUSH:\r
+ break;\r
+ case EMR_CREATEDIBPATTERNBRUSHPT:\r
+ break;\r
+ case EMR_EXTCREATEPEN:\r
+ {\r
+ PEMREXTCREATEPEN pEmr = (PEMREXTCREATEPEN) lpEMFR;\r
+ int index = pEmr->ihPen;\r
+\r
+ EMREXTCREATEPEN *pPen =\r
+ (EMREXTCREATEPEN *) malloc( sizeof(EMREXTCREATEPEN) +\r
+ sizeof(DWORD) * pEmr->elp.elpNumEntries );\r
+ pPen->ihPen = pEmr->ihPen;\r
+ pPen->offBmi = pEmr->offBmi;\r
+ pPen->cbBmi = pEmr->cbBmi;\r
+ pPen->offBits = pEmr->offBits;\r
+ pPen->cbBits = pEmr->cbBits;\r
+ pPen->elp = pEmr->elp;\r
+ for (unsigned int i=0; i<pEmr->elp.elpNumEntries; i++) {\r
+ pPen->elp.elpStyleEntry[i] = pEmr->elp.elpStyleEntry[i];\r
+ }\r
+ insert_object(d, index, EMR_EXTCREATEPEN, (ENHMETARECORD *) pPen);\r
+\r
+ break;\r
+ }\r
+ case EMR_POLYTEXTOUTA:\r
+ break;\r
+ case EMR_POLYTEXTOUTW:\r
+ break;\r
+ case EMR_SETICMMODE:\r
+ break;\r
+ case EMR_CREATECOLORSPACE:\r
+ break;\r
+ case EMR_SETCOLORSPACE:\r
+ break;\r
+ case EMR_DELETECOLORSPACE:\r
+ break;\r
+ case EMR_GLSRECORD:\r
+ break;\r
+ case EMR_GLSBOUNDEDRECORD:\r
+ break;\r
+ case EMR_PIXELFORMAT:\r
+ break;\r
+ }\r
+\r
+ *(d->outsvg) += tmp_outsvg.str().c_str();\r
+ *(d->path) += tmp_path.str().c_str();\r
+\r
+ return 1;\r
+}\r
+\r
+\r
+// Aldus Placeable Header ===================================================\r
+// Since we are a 32bit app, we have to be sure this structure compiles to\r
+// be identical to a 16 bit app's version. To do this, we use the #pragma\r
+// to adjust packing, we use a WORD for the hmf handle, and a SMALL_RECT\r
+// for the bbox rectangle.\r
+#pragma pack( push )\r
+#pragma pack( 2 )\r
+typedef struct\r
+{\r
+ DWORD dwKey;\r
+ WORD hmf;\r
+ SMALL_RECT bbox;\r
+ WORD wInch;\r
+ DWORD dwReserved;\r
+ WORD wCheckSum;\r
+} APMHEADER, *PAPMHEADER;\r
+#pragma pack( pop )\r
+\r
+\r
+SPDocument *\r
+EmfWin32::open( Inkscape::Extension::Input *mod, const gchar *uri )\r
+{\r
+ EMF_CALLBACK_DATA d = {0};\r
+\r
+ gsize bytesRead = 0;\r
+ gsize bytesWritten = 0;\r
+ GError* error = NULL;\r
+ gchar *local_fn =\r
+ g_filename_from_utf8( uri, -1, &bytesRead, &bytesWritten, &error );\r
+\r
+ if (local_fn == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ d.outsvg = new Glib::ustring("");\r
+ d.path = new Glib::ustring("");\r
+\r
+ CHAR *ansi_uri = (CHAR *) local_fn;\r
+ gunichar2 *unicode_fn = g_utf8_to_utf16( local_fn, -1, NULL, NULL, NULL );\r
+ WCHAR *unicode_uri = (WCHAR *) unicode_fn;\r
+\r
+ // Try open as Enhanced Metafile\r
+ HENHMETAFILE hemf;\r
+ if (PrintWin32::is_os_wide())\r
+ hemf = GetEnhMetaFileW(unicode_uri);\r
+ else\r
+ hemf = GetEnhMetaFileA(ansi_uri);\r
+\r
+ if (!hemf) {\r
+ // Try open as Windows Metafile\r
+ HMETAFILE hmf;\r
+ if (PrintWin32::is_os_wide())\r
+ hmf = GetMetaFileW(unicode_uri);\r
+ else\r
+ hmf = GetMetaFileA(ansi_uri);\r
+\r
+ METAFILEPICT mp;\r
+ HDC hDC;\r
+\r
+ if (!hmf) {\r
+ if (PrintWin32::is_os_wide()) {\r
+ WCHAR szTemp[MAX_PATH];\r
+\r
+ DWORD dw = GetShortPathNameW( unicode_uri, szTemp, MAX_PATH );\r
+ if (dw) {\r
+ hmf = GetMetaFileW( szTemp );\r
+ }\r
+ } else {\r
+ CHAR szTemp[MAX_PATH];\r
+\r
+ DWORD dw = GetShortPathNameA( ansi_uri, szTemp, MAX_PATH );\r
+ if (dw) {\r
+ hmf = GetMetaFileA( szTemp );\r
+ }\r
+ }\r
+ }\r
+\r
+ if (hmf) {\r
+ DWORD nSize = GetMetaFileBitsEx( hmf, 0, NULL );\r
+ if (nSize) {\r
+ BYTE *lpvData = new BYTE[nSize];\r
+ if (lpvData) {\r
+ DWORD dw = GetMetaFileBitsEx( hmf, nSize, lpvData );\r
+ if (dw) {\r
+ // Fill out a METAFILEPICT structure\r
+ mp.mm = MM_ANISOTROPIC;\r
+ mp.xExt = 1000;\r
+ mp.yExt = 1000;\r
+ mp.hMF = NULL;\r
+ // Get a reference DC\r
+ hDC = GetDC( NULL );\r
+ // Make an enhanced metafile from the windows metafile\r
+ hemf = SetWinMetaFileBits( nSize, lpvData, hDC, &mp );\r
+ // Clean up\r
+ ReleaseDC( NULL, hDC );\r
+ }\r
+ delete[] lpvData;\r
+ }\r
+ DeleteMetaFile( hmf );\r
+ }\r
+ } else {\r
+ // Try open as Aldus Placeable Metafile\r
+ HANDLE hFile;\r
+ if (PrintWin32::is_os_wide())\r
+ hFile = CreateFileW( unicode_uri, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );\r
+ else\r
+ hFile = CreateFileA( ansi_uri, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );\r
+ if (hFile != INVALID_HANDLE_VALUE) {\r
+ DWORD nSize = GetFileSize( hFile, NULL );\r
+ if (nSize) {\r
+ BYTE *lpvData = new BYTE[nSize];\r
+ if (lpvData) {\r
+ DWORD dw = ReadFile( hFile, lpvData, nSize, &nSize, NULL );\r
+ if (dw) {\r
+ if ( ((PAPMHEADER)lpvData)->dwKey == 0x9ac6cdd7l ) {\r
+ // Fill out a METAFILEPICT structure\r
+ mp.mm = MM_ANISOTROPIC;\r
+ mp.xExt = ((PAPMHEADER)lpvData)->bbox.Right - ((PAPMHEADER)lpvData)->bbox.Left;\r
+ mp.xExt = ( mp.xExt * 2540l ) / (DWORD)(((PAPMHEADER)lpvData)->wInch);\r
+ mp.yExt = ((PAPMHEADER)lpvData)->bbox.Bottom - ((PAPMHEADER)lpvData)->bbox.Top;\r
+ mp.yExt = ( mp.yExt * 2540l ) / (DWORD)(((PAPMHEADER)lpvData)->wInch);\r
+ mp.hMF = NULL;\r
+ // Get a reference DC\r
+ hDC = GetDC( NULL );\r
+ // Create an enhanced metafile from the bits\r
+ hemf = SetWinMetaFileBits( nSize, lpvData+sizeof(APMHEADER), hDC, &mp );\r
+ // Clean up\r
+ ReleaseDC( NULL, hDC );\r
+ }\r
+ }\r
+ delete[] lpvData;\r
+ }\r
+ }\r
+ CloseHandle( hFile );\r
+ }\r
+ }\r
+ }\r
+\r
+ if (!hemf || !d.outsvg || !d.path) {\r
+ if (d.outsvg)\r
+ delete d.outsvg;\r
+ if (d.path)\r
+ delete d.path;\r
+ if (local_fn)\r
+ g_free(local_fn);\r
+ if (unicode_fn)\r
+ g_free(unicode_fn);\r
+ return NULL;\r
+ }\r
+\r
+ EnumEnhMetaFile(NULL, hemf, myEnhMetaFileProc, (LPVOID) &d, NULL);\r
+ DeleteEnhMetaFile(hemf);\r
+\r
+// std::cout << "SVG Output: " << std::endl << *(d.outsvg) << std::endl;\r
+\r
+ SPDocument *doc = sp_document_new_from_mem(d.outsvg->c_str(), d.outsvg->length(), TRUE);\r
+\r
+ delete d.outsvg;\r
+ delete d.path;\r
+\r
+ if (d.emf_obj) {\r
+ int i;\r
+ for (i=0; i<d.n_obj; i++)\r
+ delete_object(&d, i);\r
+ delete[] d.emf_obj;\r
+ }\r
+ \r
+ if (d.style.stroke_dash.dash)\r
+ delete[] d.style.stroke_dash.dash;\r
+\r
+ if (local_fn)\r
+ g_free(local_fn);\r
+ if (unicode_fn)\r
+ g_free(unicode_fn);\r
+\r
+ return doc;\r
+}\r
+\r
+\r
+void\r
+EmfWin32::init (void)\r
+{\r
+ Inkscape::Extension::Extension * ext;\r
+\r
+ /* EMF in */\r
+ ext = Inkscape::Extension::build_from_mem(\r
+ "<inkscape-extension>\n"\r
+ "<name>" N_("EMF Input") "</name>\n"\r
+ "<id>org.inkscape.input.emf.win32</id>\n"\r
+ "<input>\n"\r
+ "<extension>.emf</extension>\n"\r
+ "<mimetype>image/x-emf</mimetype>\n"\r
+ "<filetypename>" N_("Enhanced Metafiles (*.emf)") "</filetypename>\n"\r
+ "<filetypetooltip>" N_("Enhanced Metafiles") "</filetypetooltip>\n"\r
+ "<output_extension>org.inkscape.output.emf.win32</output_extension>\n"\r
+ "</input>\n"\r
+ "</inkscape-extension>", new EmfWin32());\r
+\r
+ /* WMF in */\r
+ ext = Inkscape::Extension::build_from_mem(\r
+ "<inkscape-extension>\n"\r
+ "<name>" N_("WMF Input") "</name>\n"\r
+ "<id>org.inkscape.input.wmf.win32</id>\n"\r
+ "<input>\n"\r
+ "<extension>.wmf</extension>\n"\r
+ "<mimetype>image/x-wmf</mimetype>\n"\r
+ "<filetypename>" N_("Windows Metafiles (*.wmf)") "</filetypename>\n"\r
+ "<filetypetooltip>" N_("Windows Metafiles") "</filetypetooltip>\n"\r
+ "<output_extension>org.inkscape.output.emf.win32</output_extension>\n"\r
+ "</input>\n"\r
+ "</inkscape-extension>", new EmfWin32());\r
+\r
+ /* EMF out */\r
+ ext = Inkscape::Extension::build_from_mem(\r
+ "<inkscape-extension>\n"\r
+ "<name>" N_("EMF Output") "</name>\n"\r
+ "<id>org.inkscape.output.emf.win32</id>\n"\r
+ "<output>\n"\r
+ "<extension>.emf</extension>\n"\r
+ "<mimetype>image/x-emf</mimetype>\n"\r
+ "<filetypename>" N_("Enhanced Metafile (*.emf)") "</filetypename>\n"\r
+ "<filetypetooltip>" N_("Enhanced Metafile") "</filetypetooltip>\n"\r
+ "</output>\n"\r
+ "</inkscape-extension>", new EmfWin32());\r
+\r
+ return;\r
+}\r
+\r
+\r
+} } } /* namespace Inkscape, Extension, Implementation */\r
+\r
+\r
+#endif /* WIN32 */\r
+\r
+\r
+/*\r
+ Local Variables:\r
+ mode:cpp\r
+ c-file-style:"stroustrup"\r
+ c-file-offsets:((innamespace . 0)(inline-open . 0))\r
+ indent-tabs-mode:nil\r
+ fill-column:99\r
+ End:\r
+*/\r
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :\r
diff --git a/src/extension/internal/emf-win32-inout.h b/src/extension/internal/emf-win32-inout.h
--- /dev/null
@@ -0,0 +1,60 @@
+/*\r
+ * Enhanced Metafile Input/Output.\r
+ *\r
+ * Authors:\r
+ * Ulf Erikson <ulferikson@users.sf.net>\r
+ *\r
+ * Copyright (C) 2006 Authors\r
+ *\r
+ * Released under GNU GPL, read the file 'COPYING' for more information\r
+ */\r
+\r
+#ifndef EXTENSION_INTERNAL_EMF_WIN32_H\r
+#define EXTENSION_INTERNAL_EMF_WIN32_H\r
+\r
+#ifdef WIN32\r
+\r
+#include "extension/implementation/implementation.h"\r
+#include "style.h"\r
+\r
+namespace Inkscape {\r
+namespace Extension {\r
+namespace Internal {\r
+\r
+class EmfWin32 : Inkscape::Extension::Implementation::Implementation { //This is a derived class\r
+\r
+public:\r
+ EmfWin32(); // Empty constructor\r
+\r
+ virtual ~EmfWin32();//Destructor\r
+\r
+ bool check(Inkscape::Extension::Extension *module); //Can this module load (always yes for now)\r
+\r
+ void save(Inkscape::Extension::Output *mod, // Save the given document to the given filename\r
+ SPDocument *doc,\r
+ gchar const *uri);\r
+\r
+ virtual SPDocument *open( Inkscape::Extension::Input *mod,\r
+ const gchar *uri );\r
+\r
+ static void init(void);//Initialize the class\r
+\r
+private:\r
+};\r
+\r
+} } } /* namespace Inkscape, Extension, Implementation */\r
+\r
+#endif /* WIN32 */\r
+\r
+#endif /* EXTENSION_INTERNAL_EMF_WIN32_H */\r
+\r
+/*\r
+ Local Variables:\r
+ mode:c++\r
+ c-file-style:"stroustrup"\r
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))\r
+ indent-tabs-mode:nil\r
+ fill-column:99\r
+ End:\r
+*/\r
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :\r
diff --git a/src/extension/internal/emf-win32-print.cpp b/src/extension/internal/emf-win32-print.cpp
--- /dev/null
@@ -0,0 +1,629 @@
+/** \file\r
+ * Enhanced Metafile Printing.\r
+ */\r
+/*\r
+ * Authors:\r
+ * Ulf Erikson <ulferikson@users.sf.net>\r
+ *\r
+ * Copyright (C) 2006 Authors\r
+ *\r
+ * Released under GNU GPL, read the file 'COPYING' for more information\r
+ */\r
+/*\r
+ * References:\r
+ * - How to Create & Play Enhanced Metafiles in Win32\r
+ * http://support.microsoft.com/kb/q145999/\r
+ * - INFO: Windows Metafile Functions & Aldus Placeable Metafiles\r
+ * http://support.microsoft.com/kb/q66949/\r
+ * - Metafile Functions\r
+ * http://msdn.microsoft.com/library/en-us/gdi/metafile_0whf.asp\r
+ * - Metafile Structures\r
+ * http://msdn.microsoft.com/library/en-us/gdi/metafile_5hkj.asp\r
+ */\r
+\r
+#ifdef WIN32\r
+\r
+#ifdef HAVE_CONFIG_H\r
+# include "config.h"\r
+#endif\r
+\r
+#include <string.h>\r
+#include <signal.h>\r
+#include <errno.h>\r
+\r
+#include "libnr/n-art-bpath.h"\r
+#include "libnr/nr-point-matrix-ops.h"\r
+#include "libnr/nr-rect.h"\r
+#include "libnr/nr-matrix.h"\r
+#include "libnr/nr-matrix-fns.h"\r
+#include "libnr/nr-path.h"\r
+#include "libnr/nr-pixblock.h"\r
+#include "display/canvas-bpath.h"\r
+#include "sp-item.h"\r
+\r
+#include "glib.h"\r
+#include "gtk/gtkdialog.h"\r
+#include "gtk/gtkbox.h"\r
+#include "gtk/gtkstock.h"\r
+\r
+#include "glibmm/i18n.h"\r
+#include "enums.h"\r
+#include "document.h"\r
+#include "style.h"\r
+#include "sp-paint-server.h"\r
+#include "inkscape_version.h"\r
+\r
+#include "win32.h"\r
+#include "emf-win32-print.h"\r
+\r
+#include "unit-constants.h"\r
+\r
+#include "extension/extension.h"\r
+#include "extension/system.h"\r
+#include "extension/print.h"\r
+\r
+#include "io/sys.h"\r
+\r
+#include "macros.h"\r
+\r
+#define WIN32_LEAN_AND_MEAN\r
+#include <windows.h>\r
+\r
+namespace Inkscape {\r
+namespace Extension {\r
+namespace Internal {\r
+\r
+static float dwDPI = 2540;\r
+\r
+\r
+PrintEmfWin32::PrintEmfWin32 (void):\r
+ hdc(NULL),\r
+ hbrush(NULL),\r
+ hpen(NULL),\r
+ fill_path(NULL)\r
+{\r
+}\r
+\r
+\r
+PrintEmfWin32::~PrintEmfWin32 (void)\r
+{\r
+ if (hdc) {\r
+ HENHMETAFILE metafile = CloseEnhMetaFile( hdc );\r
+ if ( metafile ) {\r
+ DeleteEnhMetaFile( metafile );\r
+ }\r
+ DeleteDC( hdc );\r
+ }\r
+\r
+ /* restore default signal handling for SIGPIPE */\r
+#if !defined(_WIN32) && !defined(__WIN32__)\r
+ (void) signal(SIGPIPE, SIG_DFL);\r
+#endif\r
+ return;\r
+}\r
+\r
+\r
+unsigned int\r
+PrintEmfWin32::setup (Inkscape::Extension::Print *mod)\r
+{\r
+ return TRUE;\r
+}\r
+\r
+\r
+unsigned int\r
+PrintEmfWin32::begin (Inkscape::Extension::Print *mod, SPDocument *doc)\r
+{\r
+ gchar const *utf8_fn = mod->get_param_string("destination");\r
+\r
+ gsize bytesRead = 0;\r
+ gsize bytesWritten = 0;\r
+ GError* error = NULL;\r
+ gchar *local_fn =\r
+ g_filename_from_utf8( utf8_fn, -1, &bytesRead, &bytesWritten, &error );\r
+\r
+ if (local_fn == NULL) {\r
+ return 1;\r
+ }\r
+\r
+ CHAR *ansi_uri = (CHAR *) local_fn;\r
+ gunichar2 *unicode_fn = g_utf8_to_utf16( local_fn, -1, NULL, NULL, NULL );\r
+ WCHAR *unicode_uri = (WCHAR *) unicode_fn;\r
+\r
+ // width and height in px\r
+ _width = sp_document_width(doc);\r
+ _height = sp_document_height(doc);\r
+\r
+ NRRect d;\r
+ bool pageBoundingBox;\r
+ pageBoundingBox = mod->get_param_bool("pageBoundingBox");\r
+ if (pageBoundingBox) {\r
+ d.x0 = d.y0 = 0;\r
+ d.x1 = _width;\r
+ d.y1 = _height;\r
+ } else {\r
+ SPItem* doc_item = SP_ITEM(sp_document_root(doc));\r
+ sp_item_invoke_bbox(doc_item, &d, sp_item_i2r_affine(doc_item), TRUE);\r
+ }\r
+\r
+ d.x0 *= IN_PER_PX;\r
+ d.y0 *= IN_PER_PX;\r
+ d.x1 *= IN_PER_PX;\r
+ d.y1 *= IN_PER_PX;\r
+\r
+ float dwInchesX = (d.x1 - d.x0);\r
+ float dwInchesY = (d.y1 - d.y0);\r
+\r
+ // dwInchesX x dwInchesY in .01mm units\r
+ SetRect( &rc, 0, 0, (int) ceil(dwInchesX*2540), (int) ceil(dwInchesY*2540) );\r
+\r
+ // Get a Reference DC\r
+ HDC hScreenDC = GetDC( NULL );\r
+\r
+ // Get the physical characteristics of the reference DC\r
+ float PixelsX = (float) GetDeviceCaps( hScreenDC, HORZRES );\r
+ float PixelsY = (float) GetDeviceCaps( hScreenDC, VERTRES );\r
+ float MMX = (float) GetDeviceCaps( hScreenDC, HORZSIZE );\r
+ float MMY = (float) GetDeviceCaps( hScreenDC, VERTSIZE );\r
+\r
+ // Create the Metafile\r
+ if (PrintWin32::is_os_wide())\r
+ hdc = CreateEnhMetaFileW( hScreenDC, unicode_uri, &rc, NULL );\r
+ else\r
+ hdc = CreateEnhMetaFileA( hScreenDC, ansi_uri, &rc, NULL );\r
+\r
+ // Release the reference DC\r
+ ReleaseDC( NULL, hScreenDC );\r
+\r
+ // Did we get a good metafile?\r
+ if (hdc == NULL)\r
+ {\r
+ g_free(local_fn);\r
+ g_free(unicode_fn);\r
+ return 1;\r
+ }\r
+\r
+ // Anisotropic mapping mode\r
+ SetMapMode( hdc, MM_ANISOTROPIC );\r
+\r
+ // Set the Windows extent\r
+ SetWindowExtEx( hdc, (int) (dwInchesX*dwDPI), (int) (dwInchesY*dwDPI), NULL );\r
+\r
+ // Set the viewport extent to reflect\r
+ // dwInchesX" x dwInchesY" in device units\r
+ SetViewportExtEx( hdc,\r
+ (int) ((float) dwInchesX*25.4f*PixelsX/MMX),\r
+ (int) ((float) dwInchesY*25.4f*PixelsY/MMY),\r
+ NULL );\r
+\r
+ SetRect( &rc, 0, 0, (int) ceil(dwInchesX*dwDPI), (int) ceil(dwInchesY*dwDPI) );\r
+\r
+ g_free(local_fn);\r
+ g_free(unicode_fn);\r
+\r
+ return 0;\r
+}\r
+\r
+\r
+unsigned int\r
+PrintEmfWin32::finish (Inkscape::Extension::Print *mod)\r
+{\r
+ if (!hdc) return 0;\r
+\r
+ flush_fill(); // flush any pending fills\r
+\r
+ HENHMETAFILE metafile = CloseEnhMetaFile( hdc );\r
+ if ( metafile ) {\r
+ DeleteEnhMetaFile( metafile );\r
+ }\r
+ DeleteDC( hdc );\r
+\r
+ hdc = NULL;\r
+\r
+ return 0;\r
+}\r
+\r
+\r
+unsigned int\r
+PrintEmfWin32::comment (Inkscape::Extension::Print * module,\r
+ const char *comment)\r
+{\r
+ if (!hdc) return 0;\r
+\r
+ flush_fill(); // flush any pending fills\r
+\r
+ return 0;\r
+}\r
+\r
+\r
+void\r
+PrintEmfWin32::create_brush(SPStyle const *style)\r
+{\r
+ float rgb[3];\r
+\r
+ if (style) {\r
+ sp_color_get_rgb_floatv( &style->fill.value.color, rgb );\r
+ hbrush = CreateSolidBrush( RGB(255*rgb[0], 255*rgb[1], 255*rgb[2]) );\r
+ hbrushOld = (HBRUSH) SelectObject( hdc, hbrush );\r
+\r
+ SetPolyFillMode( hdc,\r
+ style->fill_rule.computed == 0 ? WINDING :\r
+ style->fill_rule.computed == 2 ? ALTERNATE : ALTERNATE );\r
+ } else { // if (!style)\r
+ hbrush = CreateSolidBrush( RGB(255, 255, 255) );\r
+ hbrushOld = (HBRUSH) SelectObject( hdc, hbrush );\r
+ SetPolyFillMode( hdc, ALTERNATE );\r
+ }\r
+}\r
+\r
+\r
+void\r
+PrintEmfWin32::destroy_brush()\r
+{\r
+ SelectObject( hdc, hbrushOld );\r
+ if (hbrush)\r
+ DeleteObject( hbrush );\r
+ hbrush = NULL;\r
+}\r
+\r
+\r
+void\r
+PrintEmfWin32::create_pen(SPStyle const *style)\r
+{\r
+ if (style) {\r
+ float rgb[3];\r
+\r
+ sp_color_get_rgb_floatv(&style->stroke.value.color, rgb);\r
+\r
+ LOGBRUSH lb = {0};\r
+ lb.lbStyle = BS_SOLID;\r
+ lb.lbColor = RGB( 255*rgb[0], 255*rgb[1], 255*rgb[2] );\r
+\r
+ int linestyle = PS_SOLID;\r
+ int linecap = 0;\r
+ int linejoin = 0;\r
+ DWORD n_dash = 0;\r
+ DWORD *dash = NULL;\r
+ float oldmiterlimit;\r
+\r
+ DWORD linewidth = MAX( 1, (DWORD) (style->stroke_width.computed * IN_PER_PX * dwDPI) );\r
+\r
+ if (style->stroke_linecap.computed == 0) {\r
+ linecap = PS_ENDCAP_FLAT;\r
+ }\r
+ else if (style->stroke_linecap.computed == 1) {\r
+ linecap = PS_ENDCAP_ROUND;\r
+ }\r
+ else if (style->stroke_linecap.computed == 2) {\r
+ linecap = PS_ENDCAP_SQUARE;\r
+ }\r
+\r
+ if (style->stroke_linejoin.computed == 0) {\r
+ linejoin = PS_JOIN_MITER;\r
+ }\r
+ else if (style->stroke_linejoin.computed == 1) {\r
+ linejoin = PS_JOIN_ROUND;\r
+ }\r
+ else if (style->stroke_linejoin.computed == 2) {\r
+ linejoin = PS_JOIN_BEVEL;\r
+ }\r
+\r
+ if (style->stroke_dash.n_dash &&\r
+ style->stroke_dash.dash )\r
+ {\r
+ int i = 0;\r
+ while (linestyle != PS_USERSTYLE &&\r
+ (i < style->stroke_dash.n_dash)) {\r
+ if (style->stroke_dash.dash[i] > 0.00000001)\r
+ linestyle = PS_USERSTYLE;\r
+ i++;\r
+ }\r
+\r
+ if (linestyle == PS_USERSTYLE) {\r
+ n_dash = style->stroke_dash.n_dash;\r
+ dash = new DWORD[n_dash];\r
+ for (i = 0; i < style->stroke_dash.n_dash; i++) {\r
+ dash[i] = (DWORD) (style->stroke_dash.dash[i] * IN_PER_PX * dwDPI);\r
+ }\r
+ }\r
+ }\r
+\r
+ hpen = ExtCreatePen(\r
+ PS_GEOMETRIC | linestyle | linecap | linejoin,\r
+ linewidth,\r
+ &lb,\r
+ n_dash,\r
+ dash );\r
+\r
+ if ( !hpen && linestyle == PS_USERSTYLE ) {\r
+ hpen = ExtCreatePen(\r
+ PS_GEOMETRIC | PS_SOLID | linecap | linejoin,\r
+ linewidth,\r
+ &lb,\r
+ 0,\r
+ NULL );\r
+ }\r
+\r
+ if ( !hpen ) {\r
+ hpen = CreatePen(\r
+ PS_SOLID,\r
+ linewidth,\r
+ lb.lbColor );\r
+ }\r
+\r
+ hpenOld = (HPEN) SelectObject( hdc, hpen );\r
+\r
+ if (linejoin == PS_JOIN_MITER) {\r
+ float miterlimit = style->stroke_miterlimit.value;\r
+ if (miterlimit < 1)\r
+ miterlimit = 4.0;\r
+ SetMiterLimit(\r
+ hdc,\r
+ miterlimit * IN_PER_PX * dwDPI,\r
+ &oldmiterlimit );\r
+ }\r
+\r
+ if (n_dash) {\r
+ delete[] dash;\r
+ }\r
+ }\r
+ else { // if (!style)\r
+ hpen = CreatePen( PS_SOLID, 1, RGB(0, 0, 0) );\r
+ hpenOld = (HPEN) SelectObject( hdc, hpen );\r
+ }\r
+}\r
+\r
+\r
+void\r
+PrintEmfWin32::destroy_pen()\r
+{\r
+ SelectObject( hdc, hpenOld );\r
+ if (hpen)\r
+ DeleteObject( hpen );\r
+ hpen = NULL;\r
+}\r
+\r
+\r
+void\r
+PrintEmfWin32::flush_fill()\r
+{\r
+ if (fill_path) {\r
+ print_bpath(fill_path, &fill_transform, &fill_pbox);\r
+ FillPath( hdc );\r
+ destroy_brush();\r
+ delete[] fill_path;\r
+ fill_path = NULL;\r
+ }\r
+}\r
+\r
+\r
+NArtBpath *\r
+PrintEmfWin32::copy_bpath(const NArtBpath *bp)\r
+{\r
+ NArtBpath *tmp = (NArtBpath *) bp;\r
+ int num = 1;\r
+ \r
+ while (tmp->code != NR_END) {\r
+ num++;\r
+ tmp += 1;\r
+ }\r
+\r
+ tmp = new NArtBpath[num];\r
+ while (num--) {\r
+ tmp[num] = bp[num];\r
+ }\r
+\r
+ return tmp;\r
+}\r
+\r
+\r
+int\r
+PrintEmfWin32::cmp_bpath(const NArtBpath *bp1, const NArtBpath *bp2)\r
+{\r
+ if (!bp1 || !bp2) {\r
+ return 1;\r
+ }\r
+ \r
+ while (bp1->code != NR_END && bp2->code != NR_END) {\r
+ if (bp1->code != bp2->code) {\r
+ return 1;\r
+ }\r
+\r
+ if ( fabs(bp1->x1 - bp2->x1) > 0.00000001 ||\r
+ fabs(bp1->y1 - bp2->y1) > 0.00000001 ||\r
+ fabs(bp1->x2 - bp2->x2) > 0.00000001 ||\r
+ fabs(bp1->y2 - bp2->y2) > 0.00000001 ||\r
+ fabs(bp1->x3 - bp2->x3) > 0.00000001 ||\r
+ fabs(bp1->y3 - bp2->y3) > 0.00000001 )\r
+ {\r
+ return 1;\r
+ }\r
+ \r
+ bp1 += 1;\r
+ bp2 += 1;\r
+ }\r
+ \r
+ return bp1->code != NR_END || bp2->code != NR_END;\r
+}\r
+\r
+\r
+unsigned int\r
+PrintEmfWin32::fill(Inkscape::Extension::Print *mod,\r
+ NRBPath const *bpath, NRMatrix const *transform, SPStyle const *style,\r
+ NRRect const *pbox, NRRect const *dbox, NRRect const *bbox)\r
+{\r
+ if (!hdc) return 0;\r
+\r
+ flush_fill(); // flush any pending fills\r
+\r
+ if (style->fill.type == SP_PAINT_TYPE_COLOR) {\r
+ create_brush(style);\r
+ } else {\r
+ // create_brush(NULL);\r
+ return 0;\r
+ }\r
+\r
+ fill_path = copy_bpath( bpath->path );\r
+ fill_transform = *transform;\r
+ fill_pbox = *pbox;\r
+\r
+ // postpone fill in case of stroke-and-fill\r
+\r
+ return 0;\r
+}\r
+\r
+\r
+unsigned int\r
+PrintEmfWin32::stroke (Inkscape::Extension::Print *mod,\r
+ const NRBPath *bpath, const NRMatrix *transform, const SPStyle *style,\r
+ const NRRect *pbox, const NRRect *dbox, const NRRect *bbox)\r
+{\r
+ if (!hdc) return 0;\r
+\r
+ bool stroke_and_fill = ( cmp_bpath( bpath->path, fill_path ) == 0 );\r
+\r
+ if (!stroke_and_fill) {\r
+ flush_fill(); // flush any pending fills\r
+ }\r
+\r
+ if (style->stroke.type == SP_PAINT_TYPE_COLOR) {\r
+ create_pen(style);\r
+ } else {\r
+ // create_pen(NULL);\r
+ return 0;\r
+ }\r
+\r
+ print_bpath(bpath->path, transform, pbox);\r
+\r
+ if (stroke_and_fill) {\r
+ StrokeAndFillPath( hdc );\r
+ destroy_brush();\r
+ delete[] fill_path;\r
+ fill_path = NULL;\r
+ } else {\r
+ StrokePath( hdc );\r
+ }\r
+\r
+ destroy_pen();\r
+\r
+ return 0;\r
+}\r
+\r
+\r
+unsigned int\r
+PrintEmfWin32::print_bpath(const NArtBpath *bp, const NRMatrix *transform, NRRect const *pbox)\r
+{\r
+ unsigned int closed;\r
+ NR::Matrix tf = *transform;\r
+\r
+ BeginPath( hdc );\r
+ closed = FALSE;\r
+ while (bp->code != NR_END) {\r
+ using NR::X;\r
+ using NR::Y;\r
+\r
+ NR::Point p1(bp->c(1) * tf);\r
+ NR::Point p2(bp->c(2) * tf);\r
+ NR::Point p3(bp->c(3) * tf);\r
+\r
+ p1[X] = (p1[X] * IN_PER_PX * dwDPI);\r
+ p2[X] = (p2[X] * IN_PER_PX * dwDPI);\r
+ p3[X] = (p3[X] * IN_PER_PX * dwDPI);\r
+ p1[Y] = (p1[Y] * IN_PER_PX * dwDPI);\r
+ p2[Y] = (p2[Y] * IN_PER_PX * dwDPI);\r
+ p3[Y] = (p3[Y] * IN_PER_PX * dwDPI);\r
+\r
+ LONG const x1 = (LONG) round(p1[X]);\r
+ LONG const y1 = (LONG) round(rc.bottom-p1[Y]);\r
+ LONG const x2 = (LONG) round(p2[X]);\r
+ LONG const y2 = (LONG) round(rc.bottom-p2[Y]);\r
+ LONG const x3 = (LONG) round(p3[X]);\r
+ LONG const y3 = (LONG) round(rc.bottom-p3[Y]);\r
+\r
+ switch (bp->code) {\r
+ case NR_MOVETO:\r
+ if (closed) {\r
+ CloseFigure( hdc );\r
+ }\r
+ closed = TRUE;\r
+ MoveToEx( hdc, x3, y3, NULL );\r
+ break;\r
+ case NR_MOVETO_OPEN:\r
+ if (closed) {\r
+ CloseFigure( hdc );\r
+ }\r
+ closed = FALSE;\r
+ MoveToEx( hdc, x3, y3, NULL );\r
+ break;\r
+ case NR_LINETO:\r
+ LineTo( hdc, x3, y3 );\r
+ break;\r
+ case NR_CURVETO:\r
+ {\r
+ POINT pt[3];\r
+ pt[0].x = x1;\r
+ pt[0].y = y1;\r
+ pt[1].x = x2;\r
+ pt[1].y = y2;\r
+ pt[2].x = x3;\r
+ pt[2].y = y3;\r
+\r
+ PolyBezierTo( hdc, pt, 3 );\r
+ break;\r
+ }\r
+ default:\r
+ break;\r
+ }\r
+ bp += 1;\r
+ }\r
+ if (closed) {\r
+ CloseFigure( hdc );\r
+ }\r
+ EndPath( hdc );\r
+\r
+ return closed;\r
+}\r
+\r
+\r
+bool\r
+PrintEmfWin32::textToPath(Inkscape::Extension::Print * ext)\r
+{\r
+ return ext->get_param_bool("textToPath");\r
+}\r
+\r
+\r
+void\r
+PrintEmfWin32::init (void)\r
+{\r
+ Inkscape::Extension::Extension * ext;\r
+\r
+ /* EMF print */\r
+ ext = Inkscape::Extension::build_from_mem(\r
+ "<inkscape-extension>\n"\r
+ "<name>Enhanced Metafile Print</name>\n"\r
+ "<id>org.inkscape.print.emf.win32</id>\n"\r
+ "<param name=\"destination\" type=\"string\"></param>\n"\r
+ "<param name=\"textToPath\" type=\"boolean\">TRUE</param>\n"\r
+ "<param name=\"pageBoundingBox\" type=\"boolean\">TRUE</param>\n"\r
+ "<print/>\n"\r
+ "</inkscape-extension>", new PrintEmfWin32());\r
+\r
+ return;\r
+}\r
+\r
+\r
+} /* namespace Internal */\r
+} /* namespace Extension */\r
+} /* namespace Inkscape */\r
+\r
+#endif /* WIN32 */\r
+\r
+/*\r
+ Local Variables:\r
+ mode:c++\r
+ c-file-style:"stroustrup"\r
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))\r
+ indent-tabs-mode:nil\r
+ fill-column:99\r
+ End:\r
+*/\r
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :\r
diff --git a/src/extension/internal/emf-win32-print.h b/src/extension/internal/emf-win32-print.h
--- /dev/null
@@ -0,0 +1,107 @@
+#ifndef __INKSCAPE_EXTENSION_INTERNAL_PRINT_EMF_WIN32_H__\r
+#define __INKSCAPE_EXTENSION_INTERNAL_PRINT_EMF_WIN32_H__\r
+\r
+/*\r
+ * Enhanced Metafile Printing.\r
+ *\r
+ * Author:\r
+ * Ulf Erikson <ulferikson@users.sf.net>\r
+ *\r
+ * Copyright (C) 2006 Authors\r
+ *\r
+ * Released under GNU GPL, read the file 'COPYING' for more information\r
+ */\r
+\r
+#ifdef WIN32\r
+\r
+#ifdef HAVE_CONFIG_H\r
+# include "config.h"\r
+#endif\r
+\r
+#include "extension/implementation/implementation.h"\r
+#include "extension/extension.h"\r
+\r
+#include "svg/stringstream.h"\r
+#include "libnr/nr-matrix.h"\r
+#include "libnr/nr-rect.h"\r
+\r
+#define WIN32_LEAN_AND_MEAN\r
+#include <windows.h>\r
+\r
+namespace Inkscape {\r
+namespace Extension {\r
+namespace Internal {\r
+\r
+class PrintEmfWin32 : public Inkscape::Extension::Implementation::Implementation\r
+{\r
+ double _width;\r
+ double _height;\r
+ HDC hdc;\r
+ RECT rc;\r
+\r
+ HBRUSH hbrush, hbrushOld;\r
+ HPEN hpen, hpenOld;\r
+\r
+ NArtBpath *fill_path;\r
+ NArtBpath *fill_path_copy;\r
+ NRMatrix fill_transform;\r
+ NRRect fill_pbox;\r
+\r
+ unsigned int print_bpath (const NArtBpath *bp, const NRMatrix *transform, NRRect const *pbox);\r
+\r
+public:\r
+ PrintEmfWin32 (void);\r
+ virtual ~PrintEmfWin32 (void);\r
+\r
+ /* Print functions */\r
+ virtual unsigned int setup (Inkscape::Extension::Print * module);\r
+\r
+ virtual unsigned int begin (Inkscape::Extension::Print * module, SPDocument *doc);\r
+ virtual unsigned int finish (Inkscape::Extension::Print * module);\r
+\r
+ /* Rendering methods */\r
+ virtual unsigned int fill (Inkscape::Extension::Print * module,\r
+ const NRBPath *bpath, const NRMatrix *ctm, const SPStyle *style,\r
+ const NRRect *pbox, const NRRect *dbox, const NRRect *bbox);\r
+ virtual unsigned int stroke (Inkscape::Extension::Print * module,\r
+ const NRBPath *bpath, const NRMatrix *transform, const SPStyle *style,\r
+ const NRRect *pbox, const NRRect *dbox, const NRRect *bbox);\r
+ virtual unsigned int comment(Inkscape::Extension::Print *module, const char * comment);\r
+ bool textToPath (Inkscape::Extension::Print * ext);\r
+\r
+ static void init (void);\r
+\r
+protected:\r
+ void create_brush(SPStyle const *style);\r
+\r
+ void destroy_brush();\r
+\r
+ void create_pen(SPStyle const *style);\r
+\r
+ void destroy_pen();\r
+\r
+ void flush_fill();\r
+\r
+ NArtBpath *copy_bpath(const NArtBpath *bp);\r
+ int cmp_bpath(const NArtBpath *bp1, const NArtBpath *bp2);\r
+\r
+};\r
+\r
+} /* namespace Internal */\r
+} /* namespace Extension */\r
+} /* namespace Inkscape */\r
+\r
+#endif /* WIN32 */\r
+\r
+#endif /* __INKSCAPE_EXTENSION_INTERNAL_PRINT_EMF_WIN32_H__ */\r
+\r
+/*\r
+ Local Variables:\r
+ mode:cpp\r
+ c-file-style:"stroustrup"\r
+ c-file-offsets:((innamespace . 0)(inline-open . 0))\r
+ indent-tabs-mode:nil\r
+ fill-column:99\r
+ End:\r
+*/\r
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :\r