1 /** @file
2 * @brief Windows-only Enhanced Metafile input and output.
3 */
4 /* Authors:
5 * Ulf Erikson <ulferikson@users.sf.net>
6 * Jon A. Cruz <jon@joncruz.org>
7 * Abhishek Sharma
8 *
9 * Copyright (C) 2006-2008 Authors
10 *
11 * Released under GNU GPL, read the file 'COPYING' for more information
12 *
13 * References:
14 * - How to Create & Play Enhanced Metafiles in Win32
15 * http://support.microsoft.com/kb/q145999/
16 * - INFO: Windows Metafile Functions & Aldus Placeable Metafiles
17 * http://support.microsoft.com/kb/q66949/
18 * - Metafile Functions
19 * http://msdn.microsoft.com/library/en-us/gdi/metafile_0whf.asp
20 * - Metafile Structures
21 * http://msdn.microsoft.com/library/en-us/gdi/metafile_5hkj.asp
22 */
24 #ifdef WIN32
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
30 //#include "inkscape.h"
31 #include "sp-path.h"
32 #include "style.h"
33 //#include "color.h"
34 //#include "display/curve.h"
35 //#include "libnr/nr-point-matrix-ops.h"
36 //#include "gtk/gtk.h"
37 #include "print.h"
38 //#include "glibmm/i18n.h"
39 //#include "extension/extension.h"
40 #include "extension/system.h"
41 #include "extension/print.h"
42 #include "extension/db.h"
43 #include "extension/output.h"
44 //#include "document.h"
45 #include "display/nr-arena.h"
46 #include "display/nr-arena-item.h"
48 //#include "libnr/nr-rect.h"
49 //#include "libnr/nr-matrix.h"
50 //#include "libnr/nr-pixblock.h"
52 //#include <stdio.h>
53 //#include <string.h>
55 //#include <vector>
56 //#include <string>
58 //#include "io/sys.h"
60 #include "unit-constants.h"
62 #include "clear-n_.h"
64 #define WIN32_LEAN_AND_MEAN
65 #include <windows.h>
67 #include "win32.h"
68 #include "emf-win32-print.h"
69 #include "emf-win32-inout.h"
72 #define PRINT_EMF_WIN32 "org.inkscape.print.emf.win32"
74 #ifndef PS_JOIN_MASK
75 #define PS_JOIN_MASK (PS_JOIN_BEVEL|PS_JOIN_MITER|PS_JOIN_ROUND)
76 #endif
79 namespace Inkscape {
80 namespace Extension {
81 namespace Internal {
84 EmfWin32::EmfWin32 (void) // The null constructor
85 {
86 return;
87 }
90 EmfWin32::~EmfWin32 (void) //The destructor
91 {
92 return;
93 }
96 bool
97 EmfWin32::check (Inkscape::Extension::Extension * /*module*/)
98 {
99 if (NULL == Inkscape::Extension::db.get(PRINT_EMF_WIN32))
100 return FALSE;
101 return TRUE;
102 }
105 static void
106 emf_print_document_to_file(SPDocument *doc, gchar const *filename)
107 {
108 Inkscape::Extension::Print *mod;
109 SPPrintContext context;
110 gchar const *oldconst;
111 gchar *oldoutput;
112 unsigned int ret;
114 doc->ensureUpToDate();
116 mod = Inkscape::Extension::get_print(PRINT_EMF_WIN32);
117 oldconst = mod->get_param_string("destination");
118 oldoutput = g_strdup(oldconst);
119 mod->set_param_string("destination", filename);
121 /* Start */
122 context.module = mod;
123 /* fixme: This has to go into module constructor somehow */
124 /* Create new arena */
125 mod->base = SP_ITEM(doc->getRoot());
126 mod->arena = NRArena::create();
127 mod->dkey = sp_item_display_key_new(1);
128 mod->root = mod->base->invoke_show(mod->arena, mod->dkey, SP_ITEM_SHOW_DISPLAY);
129 /* Print document */
130 ret = mod->begin(doc);
131 if (ret) {
132 g_free(oldoutput);
133 throw Inkscape::Extension::Output::save_failed();
134 }
135 mod->base->invoke_print(&context);
136 ret = mod->finish();
137 /* Release arena */
138 mod->base->invoke_hide(mod->dkey);
139 mod->base = NULL;
140 mod->root = NULL;
141 nr_object_unref((NRObject *) mod->arena);
142 mod->arena = NULL;
143 /* end */
145 mod->set_param_string("destination", oldoutput);
146 g_free(oldoutput);
148 return;
149 }
152 void
153 EmfWin32::save(Inkscape::Extension::Output *mod, SPDocument *doc, gchar const *filename)
154 {
155 Inkscape::Extension::Extension * ext;
157 ext = Inkscape::Extension::db.get(PRINT_EMF_WIN32);
158 if (ext == NULL)
159 return;
161 bool old_textToPath = ext->get_param_bool("textToPath");
162 bool new_val = mod->get_param_bool("textToPath");
163 ext->set_param_bool("textToPath", new_val);
165 emf_print_document_to_file(doc, filename);
167 ext->set_param_bool("textToPath", old_textToPath);
169 return;
170 }
174 typedef struct {
175 int type;
176 int level;
177 ENHMETARECORD *lpEMFR;
178 } EMF_OBJECT, *PEMF_OBJECT;
180 typedef struct emf_device_context {
181 struct SPStyle style;
182 class SPTextStyle tstyle;
183 bool stroke_set;
184 bool fill_set;
186 SIZEL sizeWnd;
187 SIZEL sizeView;
188 float PixelsInX, PixelsInY;
189 float PixelsOutX, PixelsOutY;
190 POINTL winorg;
191 POINTL vieworg;
192 double ScaleInX, ScaleInY;
193 double ScaleOutX, ScaleOutY;
194 COLORREF textColor;
195 bool textColorSet;
196 DWORD textAlign;
197 XFORM worldTransform;
198 POINTL cur;
199 } EMF_DEVICE_CONTEXT, *PEMF_DEVICE_CONTEXT;
201 #define EMF_MAX_DC 128
203 typedef struct emf_callback_data {
204 Glib::ustring *outsvg;
205 Glib::ustring *path;
207 EMF_DEVICE_CONTEXT dc[EMF_MAX_DC+1]; // FIXME: This should be dynamic..
208 int level;
210 double xDPI, yDPI;
211 bool pathless_stroke;
212 bool inpath;
214 float MMX;
215 float MMY;
216 float dwInchesX;
217 float dwInchesY;
219 unsigned int id;
220 CHAR *pDesc;
222 int n_obj;
223 PEMF_OBJECT emf_obj;
224 } EMF_CALLBACK_DATA, *PEMF_CALLBACK_DATA;
227 static void
228 output_style(PEMF_CALLBACK_DATA d, int iType)
229 {
230 SVGOStringStream tmp_id;
231 SVGOStringStream tmp_style;
232 char tmp[1024] = {0};
234 float fill_rgb[3];
235 sp_color_get_rgb_floatv( &(d->dc[d->level].style.fill.value.color), fill_rgb );
237 float stroke_rgb[3];
238 sp_color_get_rgb_floatv(&(d->dc[d->level].style.stroke.value.color), stroke_rgb);
240 tmp_id << "\n\tid=\"" << (d->id++) << "\"";
241 *(d->outsvg) += tmp_id.str().c_str();
242 *(d->outsvg) += "\n\tstyle=\"";
243 if (iType == EMR_STROKEPATH || !d->dc[d->level].fill_set) {
244 tmp_style << "fill:none;";
245 } else {
246 snprintf(tmp, 1023,
247 "fill:#%02x%02x%02x;",
248 SP_COLOR_F_TO_U(fill_rgb[0]),
249 SP_COLOR_F_TO_U(fill_rgb[1]),
250 SP_COLOR_F_TO_U(fill_rgb[2]));
251 tmp_style << tmp;
252 snprintf(tmp, 1023,
253 "fill-rule:%s;",
254 d->dc[d->level].style.fill_rule.value == 0 ? "evenodd" : "nonzero");
255 tmp_style << tmp;
256 tmp_style << "fill-opacity:1;";
258 if (d->dc[d->level].fill_set && d->dc[d->level].stroke_set && d->dc[d->level].style.stroke_width.value == 1 &&
259 fill_rgb[0]==stroke_rgb[0] && fill_rgb[1]==stroke_rgb[1] && fill_rgb[2]==stroke_rgb[2])
260 {
261 d->dc[d->level].stroke_set = false;
262 }
263 }
265 if (iType == EMR_FILLPATH || !d->dc[d->level].stroke_set) {
266 tmp_style << "stroke:none;";
267 } else {
268 snprintf(tmp, 1023,
269 "stroke:#%02x%02x%02x;",
270 SP_COLOR_F_TO_U(stroke_rgb[0]),
271 SP_COLOR_F_TO_U(stroke_rgb[1]),
272 SP_COLOR_F_TO_U(stroke_rgb[2]));
273 tmp_style << tmp;
275 tmp_style << "stroke-width:" <<
276 MAX( 0.001, d->dc[d->level].style.stroke_width.value ) << "px;";
278 tmp_style << "stroke-linecap:" <<
279 (d->dc[d->level].style.stroke_linecap.computed == 0 ? "butt" :
280 d->dc[d->level].style.stroke_linecap.computed == 1 ? "round" :
281 d->dc[d->level].style.stroke_linecap.computed == 2 ? "square" :
282 "unknown") << ";";
284 tmp_style << "stroke-linejoin:" <<
285 (d->dc[d->level].style.stroke_linejoin.computed == 0 ? "miter" :
286 d->dc[d->level].style.stroke_linejoin.computed == 1 ? "round" :
287 d->dc[d->level].style.stroke_linejoin.computed == 2 ? "bevel" :
288 "unknown") << ";";
290 if (d->dc[d->level].style.stroke_linejoin.computed == 0) {
291 tmp_style << "stroke-miterlimit:" <<
292 MAX( 0.01, d->dc[d->level].style.stroke_miterlimit.value ) << ";";
293 }
295 if (d->dc[d->level].style.stroke_dasharray_set &&
296 d->dc[d->level].style.stroke_dash.n_dash && d->dc[d->level].style.stroke_dash.dash)
297 {
298 tmp_style << "stroke-dasharray:";
299 for (int i=0; i<d->dc[d->level].style.stroke_dash.n_dash; i++) {
300 if (i)
301 tmp_style << ",";
302 tmp_style << d->dc[d->level].style.stroke_dash.dash[i];
303 }
304 tmp_style << ";";
305 tmp_style << "stroke-dashoffset:0;";
306 } else {
307 tmp_style << "stroke-dasharray:none;";
308 }
309 tmp_style << "stroke-opacity:1;";
310 }
311 tmp_style << "\" ";
313 *(d->outsvg) += tmp_style.str().c_str();
314 }
317 static double
318 _pix_x_to_point(PEMF_CALLBACK_DATA d, double px)
319 {
320 double tmp = px - d->dc[d->level].winorg.x;
321 tmp *= d->dc[d->level].ScaleInX ? d->dc[d->level].ScaleInX : 1.0;
322 tmp += d->dc[d->level].vieworg.x;
323 return tmp;
324 }
326 static double
327 _pix_y_to_point(PEMF_CALLBACK_DATA d, double px)
328 {
329 double tmp = px - d->dc[d->level].winorg.y;
330 tmp *= d->dc[d->level].ScaleInY ? d->dc[d->level].ScaleInY : 1.0;
331 tmp += d->dc[d->level].vieworg.y;
332 return tmp;
333 }
336 static double
337 pix_to_x_point(PEMF_CALLBACK_DATA d, double px, double py)
338 {
339 double ppx = _pix_x_to_point(d, px);
340 double ppy = _pix_y_to_point(d, py);
342 double x = ppx * d->dc[d->level].worldTransform.eM11 + ppy * d->dc[d->level].worldTransform.eM21 + d->dc[d->level].worldTransform.eDx;
343 x *= d->dc[d->level].ScaleOutX ? d->dc[d->level].ScaleOutX : DEVICESCALE;
345 return x;
346 }
348 static double
349 pix_to_y_point(PEMF_CALLBACK_DATA d, double px, double py)
350 {
351 double ppx = _pix_x_to_point(d, px);
352 double ppy = _pix_y_to_point(d, py);
354 double y = ppx * d->dc[d->level].worldTransform.eM12 + ppy * d->dc[d->level].worldTransform.eM22 + d->dc[d->level].worldTransform.eDy;
355 y *= d->dc[d->level].ScaleOutY ? d->dc[d->level].ScaleOutY : DEVICESCALE;
357 return y;
358 }
360 static double
361 pix_to_size_point(PEMF_CALLBACK_DATA d, double px)
362 {
363 double ppx = px * (d->dc[d->level].ScaleInX ? d->dc[d->level].ScaleInX : 1.0);
364 double ppy = 0;
366 double dx = ppx * d->dc[d->level].worldTransform.eM11 + ppy * d->dc[d->level].worldTransform.eM21;
367 dx *= d->dc[d->level].ScaleOutX ? d->dc[d->level].ScaleOutX : DEVICESCALE;
368 double dy = ppx * d->dc[d->level].worldTransform.eM12 + ppy * d->dc[d->level].worldTransform.eM22;
369 dy *= d->dc[d->level].ScaleOutY ? d->dc[d->level].ScaleOutY : DEVICESCALE;
371 double tmp = sqrt(dx * dx + dy * dy);
372 return tmp;
373 }
376 static void
377 select_pen(PEMF_CALLBACK_DATA d, int index)
378 {
379 PEMRCREATEPEN pEmr = NULL;
381 if (index >= 0 && index < d->n_obj)
382 pEmr = (PEMRCREATEPEN) d->emf_obj[index].lpEMFR;
384 if (!pEmr)
385 return;
387 switch (pEmr->lopn.lopnStyle & PS_STYLE_MASK) {
388 case PS_DASH:
389 case PS_DOT:
390 case PS_DASHDOT:
391 case PS_DASHDOTDOT:
392 {
393 int i = 0;
394 int penstyle = (pEmr->lopn.lopnStyle & PS_STYLE_MASK);
395 d->dc[d->level].style.stroke_dash.n_dash =
396 penstyle == PS_DASHDOTDOT ? 6 : penstyle == PS_DASHDOT ? 4 : 2;
397 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)))
398 delete[] d->dc[d->level].style.stroke_dash.dash;
399 d->dc[d->level].style.stroke_dash.dash = new double[d->dc[d->level].style.stroke_dash.n_dash];
400 if (penstyle==PS_DASH || penstyle==PS_DASHDOT || penstyle==PS_DASHDOTDOT) {
401 d->dc[d->level].style.stroke_dash.dash[i++] = 3;
402 d->dc[d->level].style.stroke_dash.dash[i++] = 1;
403 }
404 if (penstyle==PS_DOT || penstyle==PS_DASHDOT || penstyle==PS_DASHDOTDOT) {
405 d->dc[d->level].style.stroke_dash.dash[i++] = 1;
406 d->dc[d->level].style.stroke_dash.dash[i++] = 1;
407 }
408 if (penstyle==PS_DASHDOTDOT) {
409 d->dc[d->level].style.stroke_dash.dash[i++] = 1;
410 d->dc[d->level].style.stroke_dash.dash[i++] = 1;
411 }
413 d->dc[d->level].style.stroke_dasharray_set = 1;
414 break;
415 }
417 case PS_SOLID:
418 default:
419 {
420 d->dc[d->level].style.stroke_dasharray_set = 0;
421 break;
422 }
423 }
425 switch (pEmr->lopn.lopnStyle & PS_ENDCAP_MASK) {
426 case PS_ENDCAP_ROUND:
427 {
428 d->dc[d->level].style.stroke_linecap.computed = 1;
429 break;
430 }
431 case PS_ENDCAP_SQUARE:
432 {
433 d->dc[d->level].style.stroke_linecap.computed = 2;
434 break;
435 }
436 case PS_ENDCAP_FLAT:
437 default:
438 {
439 d->dc[d->level].style.stroke_linecap.computed = 0;
440 break;
441 }
442 }
444 switch (pEmr->lopn.lopnStyle & PS_JOIN_MASK) {
445 case PS_JOIN_BEVEL:
446 {
447 d->dc[d->level].style.stroke_linejoin.computed = 2;
448 break;
449 }
450 case PS_JOIN_MITER:
451 {
452 d->dc[d->level].style.stroke_linejoin.computed = 0;
453 break;
454 }
455 case PS_JOIN_ROUND:
456 default:
457 {
458 d->dc[d->level].style.stroke_linejoin.computed = 1;
459 break;
460 }
461 }
463 d->dc[d->level].stroke_set = true;
465 if (pEmr->lopn.lopnStyle == PS_NULL) {
466 d->dc[d->level].style.stroke_width.value = 0;
467 d->dc[d->level].stroke_set = false;
468 } else if (pEmr->lopn.lopnWidth.x) {
469 int cur_level = d->level;
470 d->level = d->emf_obj[index].level;
471 double pen_width = pix_to_size_point( d, pEmr->lopn.lopnWidth.x );
472 d->level = cur_level;
473 d->dc[d->level].style.stroke_width.value = pen_width;
474 } else { // this stroke should always be rendered as 1 pixel wide, independent of zoom level (can that be done in SVG?)
475 //d->dc[d->level].style.stroke_width.value = 1.0;
476 int cur_level = d->level;
477 d->level = d->emf_obj[index].level;
478 double pen_width = pix_to_size_point( d, 1 );
479 d->level = cur_level;
480 d->dc[d->level].style.stroke_width.value = pen_width;
481 }
483 double r, g, b;
484 r = SP_COLOR_U_TO_F( GetRValue(pEmr->lopn.lopnColor) );
485 g = SP_COLOR_U_TO_F( GetGValue(pEmr->lopn.lopnColor) );
486 b = SP_COLOR_U_TO_F( GetBValue(pEmr->lopn.lopnColor) );
487 d->dc[d->level].style.stroke.value.color.set( r, g, b );
488 }
491 static void
492 select_extpen(PEMF_CALLBACK_DATA d, int index)
493 {
494 PEMREXTCREATEPEN pEmr = NULL;
496 if (index >= 0 && index < d->n_obj)
497 pEmr = (PEMREXTCREATEPEN) d->emf_obj[index].lpEMFR;
499 if (!pEmr)
500 return;
502 switch (pEmr->elp.elpPenStyle & PS_STYLE_MASK) {
503 case PS_USERSTYLE:
504 {
505 if (pEmr->elp.elpNumEntries) {
506 d->dc[d->level].style.stroke_dash.n_dash = pEmr->elp.elpNumEntries;
507 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)))
508 delete[] d->dc[d->level].style.stroke_dash.dash;
509 d->dc[d->level].style.stroke_dash.dash = new double[pEmr->elp.elpNumEntries];
510 for (unsigned int i=0; i<pEmr->elp.elpNumEntries; i++) {
511 int cur_level = d->level;
512 d->level = d->emf_obj[index].level;
513 double dash_length = pix_to_size_point( d, pEmr->elp.elpStyleEntry[i] );
514 d->level = cur_level;
515 d->dc[d->level].style.stroke_dash.dash[i] = dash_length;
516 }
517 d->dc[d->level].style.stroke_dasharray_set = 1;
518 } else {
519 d->dc[d->level].style.stroke_dasharray_set = 0;
520 }
521 break;
522 }
524 case PS_DASH:
525 case PS_DOT:
526 case PS_DASHDOT:
527 case PS_DASHDOTDOT:
528 {
529 int i = 0;
530 int penstyle = (pEmr->elp.elpPenStyle & PS_STYLE_MASK);
531 d->dc[d->level].style.stroke_dash.n_dash =
532 penstyle == PS_DASHDOTDOT ? 6 : penstyle == PS_DASHDOT ? 4 : 2;
533 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)))
534 delete[] d->dc[d->level].style.stroke_dash.dash;
535 d->dc[d->level].style.stroke_dash.dash = new double[d->dc[d->level].style.stroke_dash.n_dash];
536 if (penstyle==PS_DASH || penstyle==PS_DASHDOT || penstyle==PS_DASHDOTDOT) {
537 d->dc[d->level].style.stroke_dash.dash[i++] = 3;
538 d->dc[d->level].style.stroke_dash.dash[i++] = 2;
539 }
540 if (penstyle==PS_DOT || penstyle==PS_DASHDOT || penstyle==PS_DASHDOTDOT) {
541 d->dc[d->level].style.stroke_dash.dash[i++] = 1;
542 d->dc[d->level].style.stroke_dash.dash[i++] = 2;
543 }
544 if (penstyle==PS_DASHDOTDOT) {
545 d->dc[d->level].style.stroke_dash.dash[i++] = 1;
546 d->dc[d->level].style.stroke_dash.dash[i++] = 2;
547 }
549 d->dc[d->level].style.stroke_dasharray_set = 1;
550 break;
551 }
553 case PS_SOLID:
554 default:
555 {
556 d->dc[d->level].style.stroke_dasharray_set = 0;
557 break;
558 }
559 }
561 switch (pEmr->elp.elpPenStyle & PS_ENDCAP_MASK) {
562 case PS_ENDCAP_ROUND:
563 {
564 d->dc[d->level].style.stroke_linecap.computed = 1;
565 break;
566 }
567 case PS_ENDCAP_SQUARE:
568 {
569 d->dc[d->level].style.stroke_linecap.computed = 2;
570 break;
571 }
572 case PS_ENDCAP_FLAT:
573 default:
574 {
575 d->dc[d->level].style.stroke_linecap.computed = 0;
576 break;
577 }
578 }
580 switch (pEmr->elp.elpPenStyle & PS_JOIN_MASK) {
581 case PS_JOIN_BEVEL:
582 {
583 d->dc[d->level].style.stroke_linejoin.computed = 2;
584 break;
585 }
586 case PS_JOIN_MITER:
587 {
588 d->dc[d->level].style.stroke_linejoin.computed = 0;
589 break;
590 }
591 case PS_JOIN_ROUND:
592 default:
593 {
594 d->dc[d->level].style.stroke_linejoin.computed = 1;
595 break;
596 }
597 }
599 d->dc[d->level].stroke_set = true;
601 if (pEmr->elp.elpPenStyle == PS_NULL) {
602 d->dc[d->level].style.stroke_width.value = 0;
603 d->dc[d->level].stroke_set = false;
604 } else if (pEmr->elp.elpWidth) {
605 int cur_level = d->level;
606 d->level = d->emf_obj[index].level;
607 double pen_width = pix_to_size_point( d, pEmr->elp.elpWidth );
608 d->level = cur_level;
609 d->dc[d->level].style.stroke_width.value = pen_width;
610 } else { // this stroke should always be rendered as 1 pixel wide, independent of zoom level (can that be done in SVG?)
611 //d->dc[d->level].style.stroke_width.value = 1.0;
612 int cur_level = d->level;
613 d->level = d->emf_obj[index].level;
614 double pen_width = pix_to_size_point( d, 1 );
615 d->level = cur_level;
616 d->dc[d->level].style.stroke_width.value = pen_width;
617 }
619 double r, g, b;
620 r = SP_COLOR_U_TO_F( GetRValue(pEmr->elp.elpColor) );
621 g = SP_COLOR_U_TO_F( GetGValue(pEmr->elp.elpColor) );
622 b = SP_COLOR_U_TO_F( GetBValue(pEmr->elp.elpColor) );
624 d->dc[d->level].style.stroke.value.color.set( r, g, b );
625 }
628 static void
629 select_brush(PEMF_CALLBACK_DATA d, int index)
630 {
631 PEMRCREATEBRUSHINDIRECT pEmr = NULL;
633 if (index >= 0 && index < d->n_obj)
634 pEmr = (PEMRCREATEBRUSHINDIRECT) d->emf_obj[index].lpEMFR;
636 if (!pEmr)
637 return;
639 if (pEmr->lb.lbStyle == BS_SOLID) {
640 double r, g, b;
641 r = SP_COLOR_U_TO_F( GetRValue(pEmr->lb.lbColor) );
642 g = SP_COLOR_U_TO_F( GetGValue(pEmr->lb.lbColor) );
643 b = SP_COLOR_U_TO_F( GetBValue(pEmr->lb.lbColor) );
644 d->dc[d->level].style.fill.value.color.set( r, g, b );
645 }
647 d->dc[d->level].fill_set = true;
648 }
651 static void
652 select_font(PEMF_CALLBACK_DATA d, int index)
653 {
654 PEMREXTCREATEFONTINDIRECTW pEmr = NULL;
656 if (index >= 0 && index < d->n_obj)
657 pEmr = (PEMREXTCREATEFONTINDIRECTW) d->emf_obj[index].lpEMFR;
659 if (!pEmr)
660 return;
662 int cur_level = d->level;
663 d->level = d->emf_obj[index].level;
664 double font_size = pix_to_size_point( d, pEmr->elfw.elfLogFont.lfHeight );
665 d->level = cur_level;
666 d->dc[d->level].style.font_size.computed = font_size;
667 d->dc[d->level].style.font_weight.value =
668 pEmr->elfw.elfLogFont.lfWeight == FW_THIN ? SP_CSS_FONT_WEIGHT_100 :
669 pEmr->elfw.elfLogFont.lfWeight == FW_EXTRALIGHT ? SP_CSS_FONT_WEIGHT_200 :
670 pEmr->elfw.elfLogFont.lfWeight == FW_LIGHT ? SP_CSS_FONT_WEIGHT_300 :
671 pEmr->elfw.elfLogFont.lfWeight == FW_NORMAL ? SP_CSS_FONT_WEIGHT_400 :
672 pEmr->elfw.elfLogFont.lfWeight == FW_MEDIUM ? SP_CSS_FONT_WEIGHT_500 :
673 pEmr->elfw.elfLogFont.lfWeight == FW_SEMIBOLD ? SP_CSS_FONT_WEIGHT_600 :
674 pEmr->elfw.elfLogFont.lfWeight == FW_BOLD ? SP_CSS_FONT_WEIGHT_700 :
675 pEmr->elfw.elfLogFont.lfWeight == FW_EXTRABOLD ? SP_CSS_FONT_WEIGHT_800 :
676 pEmr->elfw.elfLogFont.lfWeight == FW_HEAVY ? SP_CSS_FONT_WEIGHT_900 :
677 pEmr->elfw.elfLogFont.lfWeight == FW_NORMAL ? SP_CSS_FONT_WEIGHT_NORMAL :
678 pEmr->elfw.elfLogFont.lfWeight == FW_BOLD ? SP_CSS_FONT_WEIGHT_BOLD :
679 pEmr->elfw.elfLogFont.lfWeight == FW_EXTRALIGHT ? SP_CSS_FONT_WEIGHT_LIGHTER :
680 pEmr->elfw.elfLogFont.lfWeight == FW_EXTRABOLD ? SP_CSS_FONT_WEIGHT_BOLDER :
681 FW_NORMAL;
682 d->dc[d->level].style.font_style.value = (pEmr->elfw.elfLogFont.lfItalic ? SP_CSS_FONT_STYLE_ITALIC : SP_CSS_FONT_STYLE_NORMAL);
683 d->dc[d->level].style.text_decoration.underline = pEmr->elfw.elfLogFont.lfUnderline;
684 d->dc[d->level].style.text_decoration.line_through = pEmr->elfw.elfLogFont.lfStrikeOut;
685 if (d->dc[d->level].tstyle.font_family.value)
686 g_free(d->dc[d->level].tstyle.font_family.value);
687 d->dc[d->level].tstyle.font_family.value =
688 (gchar *) g_utf16_to_utf8( (gunichar2*) pEmr->elfw.elfLogFont.lfFaceName, -1, NULL, NULL, NULL );
689 d->dc[d->level].style.text_transform.value = ((pEmr->elfw.elfLogFont.lfEscapement + 3600) % 3600) / 10;
690 }
692 static void
693 delete_object(PEMF_CALLBACK_DATA d, int index)
694 {
695 if (index >= 0 && index < d->n_obj) {
696 d->emf_obj[index].type = 0;
697 if (d->emf_obj[index].lpEMFR)
698 free(d->emf_obj[index].lpEMFR);
699 d->emf_obj[index].lpEMFR = NULL;
700 }
701 }
704 static void
705 insert_object(PEMF_CALLBACK_DATA d, int index, int type, ENHMETARECORD *pObj)
706 {
707 if (index >= 0 && index < d->n_obj) {
708 delete_object(d, index);
709 d->emf_obj[index].type = type;
710 d->emf_obj[index].level = d->level;
711 d->emf_obj[index].lpEMFR = pObj;
712 }
713 }
715 static void
716 assert_empty_path(PEMF_CALLBACK_DATA d, const char * /*fun*/)
717 {
718 if (!d->path->empty()) {
719 // g_debug("emf-win32-inout: assert_empty_path failed for %s\n", fun);
721 *(d->outsvg) += "<!--\n";
722 *(d->outsvg) += " <path \t";
723 output_style(d, EMR_STROKEPATH);
724 if (strstr(d->path->c_str(), "d=\"") == NULL) {
725 *(d->outsvg) += "d=\"";
726 *(d->outsvg) += "\n\t";
727 }
728 *(d->outsvg) += *(d->path);
729 *(d->outsvg) += " \" /> \n";
730 *(d->outsvg) += "-->\n";
732 *(d->path) = "";
733 }
734 }
737 static int CALLBACK
738 myEnhMetaFileProc(HDC /*hDC*/, HANDLETABLE * /*lpHTable*/, ENHMETARECORD const *lpEMFR, int /*nObj*/, LPARAM lpData)
739 {
740 PEMF_CALLBACK_DATA d;
741 SVGOStringStream tmp_outsvg;
742 SVGOStringStream tmp_path;
743 SVGOStringStream tmp_str;
744 SVGOStringStream dbg_str;
746 d = (PEMF_CALLBACK_DATA) lpData;
748 if (d->pathless_stroke) {
749 if (lpEMFR->iType!=EMR_POLYBEZIERTO && lpEMFR->iType!=EMR_POLYBEZIERTO16 &&
750 lpEMFR->iType!=EMR_POLYLINETO && lpEMFR->iType!=EMR_POLYLINETO16 &&
751 lpEMFR->iType!=EMR_LINETO && lpEMFR->iType!=EMR_ARCTO &&
752 lpEMFR->iType!=EMR_SETBKCOLOR && lpEMFR->iType!=EMR_SETROP2 &&
753 lpEMFR->iType!=EMR_SETBKMODE)
754 {
755 *(d->outsvg) += " <path ";
756 output_style(d, EMR_STROKEPATH);
757 *(d->outsvg) += "\n\t";
758 *(d->outsvg) += *(d->path);
759 *(d->outsvg) += " \" /> \n";
760 *(d->path) = "";
761 d->pathless_stroke = false;
762 }
763 }
765 switch (lpEMFR->iType)
766 {
767 case EMR_HEADER:
768 {
769 dbg_str << "<!-- EMR_HEADER -->\n";
771 *(d->outsvg) += "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n";
773 if (d->pDesc) {
774 *(d->outsvg) += "<!-- ";
775 *(d->outsvg) += d->pDesc;
776 *(d->outsvg) += " -->\n";
777 }
779 ENHMETAHEADER *pEmr = (ENHMETAHEADER *) lpEMFR;
780 tmp_outsvg << "<svg\n";
781 tmp_outsvg << " xmlns:svg=\"http://www.w3.org/2000/svg\"\n";
782 tmp_outsvg << " xmlns=\"http://www.w3.org/2000/svg\"\n";
783 tmp_outsvg << " version=\"1.0\"\n";
785 d->xDPI = 2540;
786 d->yDPI = 2540;
788 d->dc[d->level].PixelsInX = pEmr->rclFrame.right - pEmr->rclFrame.left;
789 d->dc[d->level].PixelsInY = pEmr->rclFrame.bottom - pEmr->rclFrame.top;
791 d->MMX = d->dc[d->level].PixelsInX / 100.0;
792 d->MMY = d->dc[d->level].PixelsInY / 100.0;
794 d->dc[d->level].PixelsOutX = d->MMX * PX_PER_MM;
795 d->dc[d->level].PixelsOutY = d->MMY * PX_PER_MM;
797 tmp_outsvg <<
798 " width=\"" << d->MMX << "mm\"\n" <<
799 " height=\"" << d->MMY << "mm\"\n";
800 tmp_outsvg <<
801 " id=\"" << (d->id++) << "\">\n";
803 tmp_outsvg <<
804 "<g\n" <<
805 " id=\"" << (d->id++) << "\">\n";
807 if (pEmr->nHandles) {
808 d->n_obj = pEmr->nHandles;
809 d->emf_obj = new EMF_OBJECT[d->n_obj];
811 // Init the new emf_obj list elements to null, provided the
812 // dynamic allocation succeeded.
813 if ( d->emf_obj != NULL )
814 {
815 for( int i=0; i < d->n_obj; ++i )
816 d->emf_obj[i].lpEMFR = NULL;
817 } //if
819 } else {
820 d->emf_obj = NULL;
821 }
823 break;
824 }
825 case EMR_POLYBEZIER:
826 {
827 dbg_str << "<!-- EMR_POLYBEZIER -->\n";
829 PEMRPOLYBEZIER pEmr = (PEMRPOLYBEZIER) lpEMFR;
830 DWORD i,j;
832 if (pEmr->cptl<4)
833 break;
835 if (!d->inpath) {
836 assert_empty_path(d, "EMR_POLYBEZIER");
838 *(d->outsvg) += " <path ";
839 output_style(d, EMR_STROKEPATH);
840 *(d->outsvg) += "\n\td=\"";
841 }
843 tmp_str <<
844 "\n\tM " <<
845 pix_to_x_point( d, pEmr->aptl[0].x, pEmr->aptl[0].y ) << " " <<
846 pix_to_y_point( d, pEmr->aptl[0].x, pEmr->aptl[0].y) << " ";
848 for (i=1; i<pEmr->cptl; ) {
849 tmp_str << "\n\tC ";
850 for (j=0; j<3 && i<pEmr->cptl; j++,i++) {
851 tmp_str <<
852 pix_to_x_point( d, pEmr->aptl[i].x, pEmr->aptl[i].y ) << " " <<
853 pix_to_y_point( d, pEmr->aptl[i].x, pEmr->aptl[i].y ) << " ";
854 }
855 }
857 if (d->inpath) {
858 tmp_path << tmp_str.str().c_str();
859 }
860 else {
861 *(d->outsvg) += tmp_str.str().c_str();
862 *(d->outsvg) += " \" /> \n";
863 }
865 break;
866 }
867 case EMR_POLYGON:
868 {
869 dbg_str << "<!-- EMR_POLYGON -->\n";
871 EMRPOLYGON *pEmr = (EMRPOLYGON *) lpEMFR;
872 DWORD i;
874 if (pEmr->cptl < 2)
875 break;
877 assert_empty_path(d, "EMR_POLYGON");
879 *(d->outsvg) += " <path ";
880 output_style(d, EMR_STROKEANDFILLPATH);
881 *(d->outsvg) += "\n\td=\"";
883 tmp_str <<
884 "\n\tM " <<
885 pix_to_x_point( d, pEmr->aptl[0].x, pEmr->aptl[0].y ) << " " <<
886 pix_to_y_point( d, pEmr->aptl[0].x, pEmr->aptl[0].y ) << " ";
888 for (i=1; i<pEmr->cptl; i++) {
889 tmp_str <<
890 "\n\tL " <<
891 pix_to_x_point( d, pEmr->aptl[i].x, pEmr->aptl[i].y ) << " " <<
892 pix_to_y_point( d, pEmr->aptl[i].x, pEmr->aptl[i].y ) << " ";
893 }
895 *(d->outsvg) += tmp_str.str().c_str();
896 *(d->outsvg) += " z \" /> \n";
898 break;
899 }
900 case EMR_POLYLINE:
901 {
902 dbg_str << "<!-- EMR_POLYLINE -->\n";
904 EMRPOLYLINE *pEmr = (EMRPOLYLINE *) lpEMFR;
905 DWORD i;
907 if (pEmr->cptl<2)
908 break;
910 if (!d->inpath) {
911 assert_empty_path(d, "EMR_POLYLINE");
913 *(d->outsvg) += " <path ";
914 output_style(d, EMR_STROKEPATH);
915 *(d->outsvg) += "\n\td=\"";
916 }
918 tmp_str <<
919 "\n\tM " <<
920 pix_to_x_point( d, pEmr->aptl[0].x, pEmr->aptl[0].y ) << " " <<
921 pix_to_y_point( d, pEmr->aptl[0].x, pEmr->aptl[0].y ) << " ";
923 for (i=1; i<pEmr->cptl; i++) {
924 tmp_str <<
925 "\n\tL " <<
926 pix_to_x_point( d, pEmr->aptl[i].x, pEmr->aptl[i].y ) << " " <<
927 pix_to_y_point( d, pEmr->aptl[i].x, pEmr->aptl[i].y ) << " ";
928 }
930 if (d->inpath) {
931 tmp_path << tmp_str.str().c_str();
932 }
933 else {
934 *(d->outsvg) += tmp_str.str().c_str();
935 *(d->outsvg) += " \" /> \n";
936 }
938 break;
939 }
940 case EMR_POLYBEZIERTO:
941 {
942 dbg_str << "<!-- EMR_POLYBEZIERTO -->\n";
944 PEMRPOLYBEZIERTO pEmr = (PEMRPOLYBEZIERTO) lpEMFR;
945 DWORD i,j;
947 if (d->path->empty()) {
948 d->pathless_stroke = true;
949 *(d->path) = "d=\"";
950 }
952 for (i=0; i<pEmr->cptl;) {
953 tmp_path << "\n\tC ";
954 for (j=0; j<3 && i<pEmr->cptl; j++,i++) {
955 tmp_path <<
956 pix_to_x_point( d, pEmr->aptl[i].x, pEmr->aptl[i].y ) << " " <<
957 pix_to_y_point( d, pEmr->aptl[i].x, pEmr->aptl[i].y ) << " ";
958 }
959 }
961 break;
962 }
963 case EMR_POLYLINETO:
964 {
965 dbg_str << "<!-- EMR_POLYLINETO -->\n";
967 PEMRPOLYLINETO pEmr = (PEMRPOLYLINETO) lpEMFR;
968 DWORD i;
970 if (d->path->empty()) {
971 d->pathless_stroke = true;
972 *(d->path) = "d=\"";
973 }
975 for (i=0; i<pEmr->cptl;i++) {
976 tmp_path <<
977 "\n\tL " <<
978 pix_to_x_point( d, pEmr->aptl[i].x, pEmr->aptl[i].y ) << " " <<
979 pix_to_y_point( d, pEmr->aptl[i].x, pEmr->aptl[i].y ) << " ";
980 }
982 break;
983 }
984 case EMR_POLYPOLYLINE:
985 case EMR_POLYPOLYGON:
986 {
987 if (lpEMFR->iType == EMR_POLYPOLYLINE)
988 dbg_str << "<!-- EMR_POLYPOLYLINE -->\n";
989 if (lpEMFR->iType == EMR_POLYPOLYGON)
990 dbg_str << "<!-- EMR_POLYPOLYGON -->\n";
992 PEMRPOLYPOLYGON pEmr = (PEMRPOLYPOLYGON) lpEMFR;
993 unsigned int n, i, j;
995 if (!d->inpath) {
996 assert_empty_path(d, lpEMFR->iType == EMR_POLYPOLYGON ? "EMR_POLYPOLYGON" : "EMR_POLYPOLYLINE");
998 *(d->outsvg) += " <path ";
999 output_style(d, lpEMFR->iType==EMR_POLYPOLYGON ? EMR_STROKEANDFILLPATH : EMR_STROKEPATH);
1000 *(d->outsvg) += "\n\td=\"";
1001 }
1003 POINTL *aptl = (POINTL *) &pEmr->aPolyCounts[pEmr->nPolys];
1005 i = 0;
1006 for (n=0; n<pEmr->nPolys && i<pEmr->cptl; n++) {
1007 SVGOStringStream poly_path;
1009 poly_path << "\n\tM " <<
1010 pix_to_x_point( d, aptl[i].x, aptl[i].y ) << " " <<
1011 pix_to_y_point( d, aptl[i].x, aptl[i].y ) << " ";
1012 i++;
1014 for (j=1; j<pEmr->aPolyCounts[n] && i<pEmr->cptl; j++) {
1015 poly_path << "\n\tL " <<
1016 pix_to_x_point( d, aptl[i].x, aptl[i].y ) << " " <<
1017 pix_to_y_point( d, aptl[i].x, aptl[i].y ) << " ";
1018 i++;
1019 }
1021 tmp_str << poly_path.str().c_str();
1022 if (lpEMFR->iType == EMR_POLYPOLYGON)
1023 tmp_str << " z";
1024 tmp_str << " \n";
1025 }
1027 if (d->inpath) {
1028 tmp_path << tmp_str.str().c_str();
1029 }
1030 else {
1031 *(d->outsvg) += tmp_str.str().c_str();
1032 *(d->outsvg) += " \" /> \n";
1033 }
1035 break;
1036 }
1037 case EMR_SETWINDOWEXTEX:
1038 {
1039 dbg_str << "<!-- EMR_SETWINDOWEXTEX -->\n";
1041 PEMRSETWINDOWEXTEX pEmr = (PEMRSETWINDOWEXTEX) lpEMFR;
1043 d->dc[d->level].sizeWnd = pEmr->szlExtent;
1045 if (!d->dc[d->level].sizeWnd.cx || !d->dc[d->level].sizeWnd.cy) {
1046 d->dc[d->level].sizeWnd = d->dc[d->level].sizeView;
1047 if (!d->dc[d->level].sizeWnd.cx || !d->dc[d->level].sizeWnd.cy) {
1048 d->dc[d->level].sizeWnd.cx = d->dc[d->level].PixelsOutX;
1049 d->dc[d->level].sizeWnd.cy = d->dc[d->level].PixelsOutY;
1050 }
1051 }
1053 if (!d->dc[d->level].sizeView.cx || !d->dc[d->level].sizeView.cy) {
1054 d->dc[d->level].sizeView = d->dc[d->level].sizeWnd;
1055 }
1057 d->dc[d->level].PixelsInX = d->dc[d->level].sizeWnd.cx;
1058 d->dc[d->level].PixelsInY = d->dc[d->level].sizeWnd.cy;
1060 if (d->dc[d->level].PixelsInX && d->dc[d->level].PixelsInY) {
1061 d->dc[d->level].ScaleInX = (double) d->dc[d->level].sizeView.cx / (double) d->dc[d->level].PixelsInX;
1062 d->dc[d->level].ScaleInY = (double) d->dc[d->level].sizeView.cy / (double) d->dc[d->level].PixelsInY;
1063 }
1064 else {
1065 d->dc[d->level].ScaleInX = 1;
1066 d->dc[d->level].ScaleInY = 1;
1067 }
1069 if (d->dc[d->level].sizeView.cx && d->dc[d->level].sizeView.cy) {
1070 d->dc[d->level].ScaleOutX = (double) d->dc[d->level].PixelsOutX / (double) d->dc[d->level].sizeView.cx;
1071 d->dc[d->level].ScaleOutY = (double) d->dc[d->level].PixelsOutY / (double) d->dc[d->level].sizeView.cy;
1072 }
1073 else {
1074 d->dc[d->level].ScaleOutX = DEVICESCALE;
1075 d->dc[d->level].ScaleOutY = DEVICESCALE;
1076 }
1078 break;
1079 }
1080 case EMR_SETWINDOWORGEX:
1081 {
1082 dbg_str << "<!-- EMR_SETWINDOWORGEX -->\n";
1084 PEMRSETWINDOWORGEX pEmr = (PEMRSETWINDOWORGEX) lpEMFR;
1085 d->dc[d->level].winorg = pEmr->ptlOrigin;
1086 break;
1087 }
1088 case EMR_SETVIEWPORTEXTEX:
1089 {
1090 dbg_str << "<!-- EMR_SETVIEWPORTEXTEX -->\n";
1092 PEMRSETVIEWPORTEXTEX pEmr = (PEMRSETVIEWPORTEXTEX) lpEMFR;
1094 d->dc[d->level].sizeView = pEmr->szlExtent;
1096 if (!d->dc[d->level].sizeView.cx || !d->dc[d->level].sizeView.cy) {
1097 d->dc[d->level].sizeView = d->dc[d->level].sizeWnd;
1098 if (!d->dc[d->level].sizeView.cx || !d->dc[d->level].sizeView.cy) {
1099 d->dc[d->level].sizeView.cx = d->dc[d->level].PixelsOutX;
1100 d->dc[d->level].sizeView.cy = d->dc[d->level].PixelsOutY;
1101 }
1102 }
1104 if (!d->dc[d->level].sizeWnd.cx || !d->dc[d->level].sizeWnd.cy) {
1105 d->dc[d->level].sizeWnd = d->dc[d->level].sizeView;
1106 }
1108 d->dc[d->level].PixelsInX = d->dc[d->level].sizeWnd.cx;
1109 d->dc[d->level].PixelsInY = d->dc[d->level].sizeWnd.cy;
1111 if (d->dc[d->level].PixelsInX && d->dc[d->level].PixelsInY) {
1112 d->dc[d->level].ScaleInX = (double) d->dc[d->level].sizeView.cx / (double) d->dc[d->level].PixelsInX;
1113 d->dc[d->level].ScaleInY = (double) d->dc[d->level].sizeView.cy / (double) d->dc[d->level].PixelsInY;
1114 }
1115 else {
1116 d->dc[d->level].ScaleInX = 1;
1117 d->dc[d->level].ScaleInY = 1;
1118 }
1120 if (d->dc[d->level].sizeView.cx && d->dc[d->level].sizeView.cy) {
1121 d->dc[d->level].ScaleOutX = (double) d->dc[d->level].PixelsOutX / (double) d->dc[d->level].sizeView.cx;
1122 d->dc[d->level].ScaleOutY = (double) d->dc[d->level].PixelsOutY / (double) d->dc[d->level].sizeView.cy;
1123 }
1124 else {
1125 d->dc[d->level].ScaleOutX = DEVICESCALE;
1126 d->dc[d->level].ScaleOutY = DEVICESCALE;
1127 }
1129 break;
1130 }
1131 case EMR_SETVIEWPORTORGEX:
1132 {
1133 dbg_str << "<!-- EMR_SETVIEWPORTORGEX -->\n";
1135 PEMRSETVIEWPORTORGEX pEmr = (PEMRSETVIEWPORTORGEX) lpEMFR;
1136 d->dc[d->level].vieworg = pEmr->ptlOrigin;
1137 break;
1138 }
1139 case EMR_SETBRUSHORGEX:
1140 dbg_str << "<!-- EMR_SETBRUSHORGEX -->\n";
1141 break;
1142 case EMR_EOF:
1143 {
1144 dbg_str << "<!-- EMR_EOF -->\n";
1146 assert_empty_path(d, "EMR_EOF");
1147 tmp_outsvg << "</g>\n";
1148 tmp_outsvg << "</svg>\n";
1149 break;
1150 }
1151 case EMR_SETPIXELV:
1152 dbg_str << "<!-- EMR_SETPIXELV -->\n";
1153 break;
1154 case EMR_SETMAPPERFLAGS:
1155 dbg_str << "<!-- EMR_SETMAPPERFLAGS -->\n";
1156 break;
1157 case EMR_SETMAPMODE:
1158 dbg_str << "<!-- EMR_SETMAPMODE -->\n";
1159 break;
1160 case EMR_SETBKMODE:
1161 dbg_str << "<!-- EMR_SETBKMODE -->\n";
1162 break;
1163 case EMR_SETPOLYFILLMODE:
1164 {
1165 dbg_str << "<!-- EMR_SETPOLYFILLMODE -->\n";
1167 PEMRSETPOLYFILLMODE pEmr = (PEMRSETPOLYFILLMODE) lpEMFR;
1168 d->dc[d->level].style.fill_rule.value =
1169 (pEmr->iMode == ALTERNATE ? 0 :
1170 pEmr->iMode == WINDING ? 1 : 0);
1171 break;
1172 }
1173 case EMR_SETROP2:
1174 dbg_str << "<!-- EMR_SETROP2 -->\n";
1175 break;
1176 case EMR_SETSTRETCHBLTMODE:
1177 dbg_str << "<!-- EMR_SETSTRETCHBLTMODE -->\n";
1178 break;
1179 case EMR_SETTEXTALIGN:
1180 {
1181 dbg_str << "<!-- EMR_SETTEXTALIGN -->\n";
1183 PEMRSETTEXTALIGN pEmr = (PEMRSETTEXTALIGN) lpEMFR;
1184 d->dc[d->level].textAlign = pEmr->iMode;
1185 break;
1186 }
1187 case EMR_SETCOLORADJUSTMENT:
1188 dbg_str << "<!-- EMR_SETCOLORADJUSTMENT -->\n";
1189 break;
1190 case EMR_SETTEXTCOLOR:
1191 {
1192 dbg_str << "<!-- EMR_SETTEXTCOLOR -->\n";
1194 PEMRSETTEXTCOLOR pEmr = (PEMRSETTEXTCOLOR) lpEMFR;
1195 d->dc[d->level].textColor = pEmr->crColor;
1196 d->dc[d->level].textColorSet = true;
1197 break;
1198 }
1199 case EMR_SETBKCOLOR:
1200 dbg_str << "<!-- EMR_SETBKCOLOR -->\n";
1201 break;
1202 case EMR_OFFSETCLIPRGN:
1203 dbg_str << "<!-- EMR_OFFSETCLIPRGN -->\n";
1204 break;
1205 case EMR_MOVETOEX:
1206 {
1207 dbg_str << "<!-- EMR_MOVETOEX -->\n";
1209 PEMRMOVETOEX pEmr = (PEMRMOVETOEX) lpEMFR;
1211 if (d->path->empty()) {
1212 d->pathless_stroke = true;
1213 *(d->path) = "d=\"";
1214 }
1216 d->dc[d->level].cur = pEmr->ptl;
1218 tmp_path <<
1219 "\n\tM " <<
1220 pix_to_x_point( d, pEmr->ptl.x, pEmr->ptl.y ) << " " <<
1221 pix_to_y_point( d, pEmr->ptl.x, pEmr->ptl.y ) << " ";
1222 break;
1223 }
1224 case EMR_SETMETARGN:
1225 dbg_str << "<!-- EMR_SETMETARGN -->\n";
1226 break;
1227 case EMR_EXCLUDECLIPRECT:
1228 dbg_str << "<!-- EMR_EXCLUDECLIPRECT -->\n";
1229 break;
1230 case EMR_INTERSECTCLIPRECT:
1231 dbg_str << "<!-- EMR_INTERSECTCLIPRECT -->\n";
1232 break;
1233 case EMR_SCALEVIEWPORTEXTEX:
1234 dbg_str << "<!-- EMR_SCALEVIEWPORTEXTEX -->\n";
1235 break;
1236 case EMR_SCALEWINDOWEXTEX:
1237 dbg_str << "<!-- EMR_SCALEWINDOWEXTEX -->\n";
1238 break;
1239 case EMR_SAVEDC:
1240 dbg_str << "<!-- EMR_SAVEDC -->\n";
1242 if (d->level < EMF_MAX_DC) {
1243 d->dc[d->level + 1] = d->dc[d->level];
1244 d->level = d->level + 1;
1245 }
1246 break;
1247 case EMR_RESTOREDC:
1248 {
1249 dbg_str << "<!-- EMR_RESTOREDC -->\n";
1251 PEMRRESTOREDC pEmr = (PEMRRESTOREDC) lpEMFR;
1252 int old_level = d->level;
1253 if (pEmr->iRelative >= 0) {
1254 if (pEmr->iRelative < d->level)
1255 d->level = pEmr->iRelative;
1256 }
1257 else {
1258 if (d->level + pEmr->iRelative >= 0)
1259 d->level = d->level + pEmr->iRelative;
1260 }
1261 while (old_level > d->level) {
1262 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)))
1263 delete[] d->dc[old_level].style.stroke_dash.dash;
1264 old_level--;
1265 }
1266 break;
1267 }
1268 case EMR_SETWORLDTRANSFORM:
1269 {
1270 dbg_str << "<!-- EMR_SETWORLDTRANSFORM -->\n";
1272 PEMRSETWORLDTRANSFORM pEmr = (PEMRSETWORLDTRANSFORM) lpEMFR;
1273 d->dc[d->level].worldTransform = pEmr->xform;
1274 break;
1275 }
1276 case EMR_MODIFYWORLDTRANSFORM:
1277 {
1278 dbg_str << "<!-- EMR_MODIFYWORLDTRANSFORM -->\n";
1280 PEMRMODIFYWORLDTRANSFORM pEmr = (PEMRMODIFYWORLDTRANSFORM) lpEMFR;
1281 switch (pEmr->iMode)
1282 {
1283 case MWT_IDENTITY:
1284 d->dc[d->level].worldTransform.eM11 = 1.0;
1285 d->dc[d->level].worldTransform.eM12 = 0.0;
1286 d->dc[d->level].worldTransform.eM21 = 0.0;
1287 d->dc[d->level].worldTransform.eM22 = 1.0;
1288 d->dc[d->level].worldTransform.eDx = 0.0;
1289 d->dc[d->level].worldTransform.eDy = 0.0;
1290 break;
1291 case MWT_LEFTMULTIPLY:
1292 {
1293 // d->dc[d->level].worldTransform = pEmr->xform * worldTransform;
1295 float a11 = pEmr->xform.eM11;
1296 float a12 = pEmr->xform.eM12;
1297 float a13 = 0.0;
1298 float a21 = pEmr->xform.eM21;
1299 float a22 = pEmr->xform.eM22;
1300 float a23 = 0.0;
1301 float a31 = pEmr->xform.eDx;
1302 float a32 = pEmr->xform.eDy;
1303 float a33 = 1.0;
1305 float b11 = d->dc[d->level].worldTransform.eM11;
1306 float b12 = d->dc[d->level].worldTransform.eM12;
1307 //float b13 = 0.0;
1308 float b21 = d->dc[d->level].worldTransform.eM21;
1309 float b22 = d->dc[d->level].worldTransform.eM22;
1310 //float b23 = 0.0;
1311 float b31 = d->dc[d->level].worldTransform.eDx;
1312 float b32 = d->dc[d->level].worldTransform.eDy;
1313 //float b33 = 1.0;
1315 float c11 = a11*b11 + a12*b21 + a13*b31;;
1316 float c12 = a11*b12 + a12*b22 + a13*b32;;
1317 //float c13 = a11*b13 + a12*b23 + a13*b33;;
1318 float c21 = a21*b11 + a22*b21 + a23*b31;;
1319 float c22 = a21*b12 + a22*b22 + a23*b32;;
1320 //float c23 = a21*b13 + a22*b23 + a23*b33;;
1321 float c31 = a31*b11 + a32*b21 + a33*b31;;
1322 float c32 = a31*b12 + a32*b22 + a33*b32;;
1323 //float c33 = a31*b13 + a32*b23 + a33*b33;;
1325 d->dc[d->level].worldTransform.eM11 = c11;;
1326 d->dc[d->level].worldTransform.eM12 = c12;;
1327 d->dc[d->level].worldTransform.eM21 = c21;;
1328 d->dc[d->level].worldTransform.eM22 = c22;;
1329 d->dc[d->level].worldTransform.eDx = c31;
1330 d->dc[d->level].worldTransform.eDy = c32;
1332 break;
1333 }
1334 case MWT_RIGHTMULTIPLY:
1335 {
1336 // d->dc[d->level].worldTransform = worldTransform * pEmr->xform;
1338 float a11 = d->dc[d->level].worldTransform.eM11;
1339 float a12 = d->dc[d->level].worldTransform.eM12;
1340 float a13 = 0.0;
1341 float a21 = d->dc[d->level].worldTransform.eM21;
1342 float a22 = d->dc[d->level].worldTransform.eM22;
1343 float a23 = 0.0;
1344 float a31 = d->dc[d->level].worldTransform.eDx;
1345 float a32 = d->dc[d->level].worldTransform.eDy;
1346 float a33 = 1.0;
1348 float b11 = pEmr->xform.eM11;
1349 float b12 = pEmr->xform.eM12;
1350 //float b13 = 0.0;
1351 float b21 = pEmr->xform.eM21;
1352 float b22 = pEmr->xform.eM22;
1353 //float b23 = 0.0;
1354 float b31 = pEmr->xform.eDx;
1355 float b32 = pEmr->xform.eDy;
1356 //float b33 = 1.0;
1358 float c11 = a11*b11 + a12*b21 + a13*b31;;
1359 float c12 = a11*b12 + a12*b22 + a13*b32;;
1360 //float c13 = a11*b13 + a12*b23 + a13*b33;;
1361 float c21 = a21*b11 + a22*b21 + a23*b31;;
1362 float c22 = a21*b12 + a22*b22 + a23*b32;;
1363 //float c23 = a21*b13 + a22*b23 + a23*b33;;
1364 float c31 = a31*b11 + a32*b21 + a33*b31;;
1365 float c32 = a31*b12 + a32*b22 + a33*b32;;
1366 //float c33 = a31*b13 + a32*b23 + a33*b33;;
1368 d->dc[d->level].worldTransform.eM11 = c11;;
1369 d->dc[d->level].worldTransform.eM12 = c12;;
1370 d->dc[d->level].worldTransform.eM21 = c21;;
1371 d->dc[d->level].worldTransform.eM22 = c22;;
1372 d->dc[d->level].worldTransform.eDx = c31;
1373 d->dc[d->level].worldTransform.eDy = c32;
1375 break;
1376 }
1377 // case MWT_SET:
1378 default:
1379 d->dc[d->level].worldTransform = pEmr->xform;
1380 break;
1381 }
1382 break;
1383 }
1384 case EMR_SELECTOBJECT:
1385 {
1386 dbg_str << "<!-- EMR_SELECTOBJECT -->\n";
1388 PEMRSELECTOBJECT pEmr = (PEMRSELECTOBJECT) lpEMFR;
1389 unsigned int index = pEmr->ihObject;
1391 if (index >= ENHMETA_STOCK_OBJECT) {
1392 index -= ENHMETA_STOCK_OBJECT;
1393 switch (index) {
1394 case NULL_BRUSH:
1395 d->dc[d->level].fill_set = false;
1396 break;
1397 case BLACK_BRUSH:
1398 case DKGRAY_BRUSH:
1399 case GRAY_BRUSH:
1400 case LTGRAY_BRUSH:
1401 case WHITE_BRUSH:
1402 {
1403 float val = 0;
1404 switch (index) {
1405 case BLACK_BRUSH:
1406 val = 0.0 / 255.0;
1407 break;
1408 case DKGRAY_BRUSH:
1409 val = 64.0 / 255.0;
1410 break;
1411 case GRAY_BRUSH:
1412 val = 128.0 / 255.0;
1413 break;
1414 case LTGRAY_BRUSH:
1415 val = 192.0 / 255.0;
1416 break;
1417 case WHITE_BRUSH:
1418 val = 255.0 / 255.0;
1419 break;
1420 }
1421 d->dc[d->level].style.fill.value.color.set( val, val, val );
1423 d->dc[d->level].fill_set = true;
1424 break;
1425 }
1426 case NULL_PEN:
1427 d->dc[d->level].stroke_set = false;
1428 break;
1429 case BLACK_PEN:
1430 case WHITE_PEN:
1431 {
1432 float val = index == BLACK_PEN ? 0 : 1;
1433 d->dc[d->level].style.stroke_dasharray_set = 0;
1434 d->dc[d->level].style.stroke_width.value = 1.0;
1435 d->dc[d->level].style.stroke.value.color.set( val, val, val );
1437 d->dc[d->level].stroke_set = true;
1439 break;
1440 }
1441 }
1442 } else {
1443 if ( /*index >= 0 &&*/ index < (unsigned int) d->n_obj) {
1444 switch (d->emf_obj[index].type)
1445 {
1446 case EMR_CREATEPEN:
1447 select_pen(d, index);
1448 break;
1449 case EMR_CREATEBRUSHINDIRECT:
1450 select_brush(d, index);
1451 break;
1452 case EMR_EXTCREATEPEN:
1453 select_extpen(d, index);
1454 break;
1455 case EMR_EXTCREATEFONTINDIRECTW:
1456 select_font(d, index);
1457 break;
1458 }
1459 }
1460 }
1461 break;
1462 }
1463 case EMR_CREATEPEN:
1464 {
1465 dbg_str << "<!-- EMR_CREATEPEN -->\n";
1467 PEMRCREATEPEN pEmr = (PEMRCREATEPEN) lpEMFR;
1468 int index = pEmr->ihPen;
1470 EMRCREATEPEN *pPen =
1471 (EMRCREATEPEN *) malloc( sizeof(EMRCREATEPEN) );
1472 pPen->lopn = pEmr->lopn;
1473 insert_object(d, index, EMR_CREATEPEN, (ENHMETARECORD *) pPen);
1475 break;
1476 }
1477 case EMR_CREATEBRUSHINDIRECT:
1478 {
1479 dbg_str << "<!-- EMR_CREATEBRUSHINDIRECT -->\n";
1481 PEMRCREATEBRUSHINDIRECT pEmr = (PEMRCREATEBRUSHINDIRECT) lpEMFR;
1482 int index = pEmr->ihBrush;
1484 EMRCREATEBRUSHINDIRECT *pBrush =
1485 (EMRCREATEBRUSHINDIRECT *) malloc( sizeof(EMRCREATEBRUSHINDIRECT) );
1486 pBrush->lb = pEmr->lb;
1487 insert_object(d, index, EMR_CREATEBRUSHINDIRECT, (ENHMETARECORD *) pBrush);
1489 break;
1490 }
1491 case EMR_DELETEOBJECT:
1492 dbg_str << "<!-- EMR_DELETEOBJECT -->\n";
1493 break;
1494 case EMR_ANGLEARC:
1495 dbg_str << "<!-- EMR_ANGLEARC -->\n";
1496 break;
1497 case EMR_ELLIPSE:
1498 {
1499 dbg_str << "<!-- EMR_ELLIPSE -->\n";
1501 PEMRELLIPSE pEmr = (PEMRELLIPSE) lpEMFR;
1502 RECTL rclBox = pEmr->rclBox;
1504 double l = pix_to_x_point( d, pEmr->rclBox.left, pEmr->rclBox.top );
1505 double t = pix_to_y_point( d, pEmr->rclBox.left, pEmr->rclBox.top );
1506 double r = pix_to_x_point( d, pEmr->rclBox.right, pEmr->rclBox.bottom );
1507 double b = pix_to_y_point( d, pEmr->rclBox.right, pEmr->rclBox.bottom );
1509 double cx = (l + r) / 2.0;
1510 double cy = (t + b) / 2.0;
1511 double rx = fabs(l - r) / 2.0;
1512 double ry = fabs(t - b) / 2.0;
1514 SVGOStringStream tmp_ellipse;
1515 tmp_ellipse << "cx=\"" << cx << "\" ";
1516 tmp_ellipse << "cy=\"" << cy << "\" ";
1517 tmp_ellipse << "rx=\"" << rx << "\" ";
1518 tmp_ellipse << "ry=\"" << ry << "\" ";
1520 assert_empty_path(d, "EMR_ELLIPSE");
1522 *(d->outsvg) += " <ellipse ";
1523 output_style(d, lpEMFR->iType);
1524 *(d->outsvg) += "\n\t";
1525 *(d->outsvg) += tmp_ellipse.str().c_str();
1526 *(d->outsvg) += "/> \n";
1527 *(d->path) = "";
1528 break;
1529 }
1530 case EMR_RECTANGLE:
1531 {
1532 dbg_str << "<!-- EMR_RECTANGLE -->\n";
1534 PEMRRECTANGLE pEmr = (PEMRRECTANGLE) lpEMFR;
1535 RECTL rc = pEmr->rclBox;
1537 double l = pix_to_x_point( d, rc.left, rc.top );
1538 double t = pix_to_y_point( d, rc.left, rc.top );
1539 double r = pix_to_x_point( d, rc.right, rc.bottom );
1540 double b = pix_to_y_point( d, rc.right, rc.bottom );
1542 SVGOStringStream tmp_rectangle;
1543 tmp_rectangle << "d=\"";
1544 tmp_rectangle << "\n\tM " << l << " " << t << " ";
1545 tmp_rectangle << "\n\tL " << r << " " << t << " ";
1546 tmp_rectangle << "\n\tL " << r << " " << b << " ";
1547 tmp_rectangle << "\n\tL " << l << " " << b << " ";
1548 tmp_rectangle << "\n\tz";
1550 assert_empty_path(d, "EMR_RECTANGLE");
1552 *(d->outsvg) += " <path ";
1553 output_style(d, lpEMFR->iType);
1554 *(d->outsvg) += "\n\t";
1555 *(d->outsvg) += tmp_rectangle.str().c_str();
1556 *(d->outsvg) += " \" /> \n";
1557 *(d->path) = "";
1558 break;
1559 }
1560 case EMR_ROUNDRECT:
1561 dbg_str << "<!-- EMR_ROUNDRECT -->\n";
1562 break;
1563 case EMR_ARC:
1564 dbg_str << "<!-- EMR_ARC -->\n";
1565 break;
1566 case EMR_CHORD:
1567 dbg_str << "<!-- EMR_CHORD -->\n";
1568 break;
1569 case EMR_PIE:
1570 dbg_str << "<!-- EMR_PIE -->\n";
1571 break;
1572 case EMR_SELECTPALETTE:
1573 dbg_str << "<!-- EMR_SELECTPALETTE -->\n";
1574 break;
1575 case EMR_CREATEPALETTE:
1576 dbg_str << "<!-- EMR_CREATEPALETTE -->\n";
1577 break;
1578 case EMR_SETPALETTEENTRIES:
1579 dbg_str << "<!-- EMR_SETPALETTEENTRIES -->\n";
1580 break;
1581 case EMR_RESIZEPALETTE:
1582 dbg_str << "<!-- EMR_RESIZEPALETTE -->\n";
1583 break;
1584 case EMR_REALIZEPALETTE:
1585 dbg_str << "<!-- EMR_REALIZEPALETTE -->\n";
1586 break;
1587 case EMR_EXTFLOODFILL:
1588 dbg_str << "<!-- EMR_EXTFLOODFILL -->\n";
1589 break;
1590 case EMR_LINETO:
1591 {
1592 dbg_str << "<!-- EMR_LINETO -->\n";
1594 PEMRLINETO pEmr = (PEMRLINETO) lpEMFR;
1596 if (d->path->empty()) {
1597 d->pathless_stroke = true;
1598 *(d->path) = "d=\"";
1599 }
1601 tmp_path <<
1602 "\n\tL " <<
1603 pix_to_x_point( d, pEmr->ptl.x, pEmr->ptl.y ) << " " <<
1604 pix_to_y_point( d, pEmr->ptl.x, pEmr->ptl.y ) << " ";
1605 break;
1606 }
1607 case EMR_ARCTO:
1608 dbg_str << "<!-- EMR_ARCTO -->\n";
1609 break;
1610 case EMR_POLYDRAW:
1611 dbg_str << "<!-- EMR_POLYDRAW -->\n";
1612 break;
1613 case EMR_SETARCDIRECTION:
1614 dbg_str << "<!-- EMR_SETARCDIRECTION -->\n";
1615 break;
1616 case EMR_SETMITERLIMIT:
1617 {
1618 dbg_str << "<!-- EMR_SETMITERLIMIT -->\n";
1620 PEMRSETMITERLIMIT pEmr = (PEMRSETMITERLIMIT) lpEMFR;
1622 float miterlimit = pEmr->eMiterLimit;
1623 miterlimit = miterlimit * 4.0 / 10.0;
1624 d->dc[d->level].style.stroke_miterlimit.value = pix_to_size_point( d, miterlimit );
1625 if (d->dc[d->level].style.stroke_miterlimit.value < 1)
1626 d->dc[d->level].style.stroke_miterlimit.value = 4.0;
1627 break;
1628 }
1629 case EMR_BEGINPATH:
1630 {
1631 dbg_str << "<!-- EMR_BEGINPATH -->\n";
1633 tmp_path << "d=\"";
1634 *(d->path) = "";
1635 d->inpath = true;
1636 break;
1637 }
1638 case EMR_ENDPATH:
1639 {
1640 dbg_str << "<!-- EMR_ENDPATH -->\n";
1642 tmp_path << "\"";
1643 d->inpath = false;
1644 break;
1645 }
1646 case EMR_CLOSEFIGURE:
1647 {
1648 dbg_str << "<!-- EMR_CLOSEFIGURE -->\n";
1650 tmp_path << "\n\tz";
1651 break;
1652 }
1653 case EMR_FILLPATH:
1654 case EMR_STROKEANDFILLPATH:
1655 case EMR_STROKEPATH:
1656 {
1657 if (lpEMFR->iType == EMR_FILLPATH)
1658 dbg_str << "<!-- EMR_FILLPATH -->\n";
1659 if (lpEMFR->iType == EMR_STROKEANDFILLPATH)
1660 dbg_str << "<!-- EMR_STROKEANDFILLPATH -->\n";
1661 if (lpEMFR->iType == EMR_STROKEPATH)
1662 dbg_str << "<!-- EMR_STROKEPATH -->\n";
1664 *(d->outsvg) += " <path ";
1665 output_style(d, lpEMFR->iType);
1666 *(d->outsvg) += "\n\t";
1667 *(d->outsvg) += *(d->path);
1668 *(d->outsvg) += " /> \n";
1669 *(d->path) = "";
1670 break;
1671 }
1672 case EMR_FLATTENPATH:
1673 dbg_str << "<!-- EMR_FLATTENPATH -->\n";
1674 break;
1675 case EMR_WIDENPATH:
1676 dbg_str << "<!-- EMR_WIDENPATH -->\n";
1677 break;
1678 case EMR_SELECTCLIPPATH:
1679 dbg_str << "<!-- EMR_SELECTCLIPPATH -->\n";
1680 break;
1681 case EMR_ABORTPATH:
1682 dbg_str << "<!-- EMR_ABORTPATH -->\n";
1683 break;
1684 case EMR_GDICOMMENT:
1685 {
1686 dbg_str << "<!-- EMR_GDICOMMENT -->\n";
1688 PEMRGDICOMMENT pEmr = (PEMRGDICOMMENT) lpEMFR;
1690 CHAR *szTxt = (CHAR *) pEmr->Data;
1692 for (DWORD i = 0; i < pEmr->cbData; i++) {
1693 if ( *szTxt) {
1694 if ( *szTxt >= ' ' && *szTxt < 'z' && *szTxt != '<' && *szTxt != '>' ) {
1695 tmp_str << *szTxt;
1696 }
1697 szTxt++;
1698 }
1699 }
1701 if (0 && strlen(tmp_str.str().c_str())) {
1702 tmp_outsvg << " <!-- \"";
1703 tmp_outsvg << tmp_str.str().c_str();
1704 tmp_outsvg << "\" -->\n";
1705 }
1707 break;
1708 }
1709 case EMR_FILLRGN:
1710 dbg_str << "<!-- EMR_FILLRGN -->\n";
1711 break;
1712 case EMR_FRAMERGN:
1713 dbg_str << "<!-- EMR_FRAMERGN -->\n";
1714 break;
1715 case EMR_INVERTRGN:
1716 dbg_str << "<!-- EMR_INVERTRGN -->\n";
1717 break;
1718 case EMR_PAINTRGN:
1719 dbg_str << "<!-- EMR_PAINTRGN -->\n";
1720 break;
1721 case EMR_EXTSELECTCLIPRGN:
1722 dbg_str << "<!-- EMR_EXTSELECTCLIPRGN -->\n";
1723 break;
1724 case EMR_BITBLT:
1725 dbg_str << "<!-- EMR_BITBLT -->\n";
1726 break;
1727 case EMR_STRETCHBLT:
1728 dbg_str << "<!-- EMR_STRETCHBLT -->\n";
1729 break;
1730 case EMR_MASKBLT:
1731 dbg_str << "<!-- EMR_MASKBLT -->\n";
1732 break;
1733 case EMR_PLGBLT:
1734 dbg_str << "<!-- EMR_PLGBLT -->\n";
1735 break;
1736 case EMR_SETDIBITSTODEVICE:
1737 dbg_str << "<!-- EMR_SETDIBITSTODEVICE -->\n";
1738 break;
1739 case EMR_STRETCHDIBITS:
1740 dbg_str << "<!-- EMR_STRETCHDIBITS -->\n";
1741 break;
1742 case EMR_EXTCREATEFONTINDIRECTW:
1743 {
1744 dbg_str << "<!-- EMR_EXTCREATEFONTINDIRECTW -->\n";
1746 PEMREXTCREATEFONTINDIRECTW pEmr = (PEMREXTCREATEFONTINDIRECTW) lpEMFR;
1747 int index = pEmr->ihFont;
1749 EMREXTCREATEFONTINDIRECTW *pFont =
1750 (EMREXTCREATEFONTINDIRECTW *) malloc( sizeof(EMREXTCREATEFONTINDIRECTW) );
1751 pFont->elfw = pEmr->elfw;
1752 insert_object(d, index, EMR_EXTCREATEFONTINDIRECTW, (ENHMETARECORD *) pFont);
1753 break;
1754 }
1755 case EMR_EXTTEXTOUTA:
1756 {
1757 dbg_str << "<!-- EMR_EXTTEXTOUTA -->\n";
1758 break;
1759 }
1760 case EMR_EXTTEXTOUTW:
1761 {
1762 dbg_str << "<!-- EMR_EXTTEXTOUTW -->\n";
1764 PEMREXTTEXTOUTW pEmr = (PEMREXTTEXTOUTW) lpEMFR;
1766 double x1 = pEmr->emrtext.ptlReference.x;
1767 double y1 = pEmr->emrtext.ptlReference.y;
1769 if (d->dc[d->level].textAlign & TA_UPDATECP) {
1770 x1 = d->dc[d->level].cur.x;
1771 y1 = d->dc[d->level].cur.y;
1772 }
1774 if (!(d->dc[d->level].textAlign & TA_BOTTOM))
1775 y1 += fabs(d->dc[d->level].style.font_size.computed);
1777 double x = pix_to_x_point(d, x1, y1);
1778 double y = pix_to_y_point(d, x1, y1);
1780 wchar_t *wide_text = (wchar_t *) ((char *) pEmr + pEmr->emrtext.offString);
1782 gchar *ansi_text =
1783 (gchar *) g_utf16_to_utf8( (gunichar2 *) wide_text, pEmr->emrtext.nChars, NULL, NULL, NULL );
1785 if (ansi_text) {
1786 gchar *p = ansi_text;
1787 while (*p) {
1788 if (*p < 32 || *p >= 127) {
1789 g_free(ansi_text);
1790 ansi_text = g_strdup("");
1791 break;
1792 }
1793 p++;
1794 }
1796 SVGOStringStream ts;
1798 gchar *escaped_text = g_markup_escape_text(ansi_text, -1);
1800 float text_rgb[3];
1801 sp_color_get_rgb_floatv( &(d->dc[d->level].style.fill.value.color), text_rgb );
1803 if (!d->dc[d->level].textColorSet) {
1804 d->dc[d->level].textColor = RGB(SP_COLOR_F_TO_U(text_rgb[0]),
1805 SP_COLOR_F_TO_U(text_rgb[1]),
1806 SP_COLOR_F_TO_U(text_rgb[2]));
1807 }
1809 char tmp[128];
1810 snprintf(tmp, 127,
1811 "fill:#%02x%02x%02x;",
1812 GetRValue(d->dc[d->level].textColor),
1813 GetGValue(d->dc[d->level].textColor),
1814 GetBValue(d->dc[d->level].textColor));
1816 bool i = (d->dc[d->level].style.font_style.value == SP_CSS_FONT_STYLE_ITALIC);
1817 //bool o = (d->dc[d->level].style.font_style.value == SP_CSS_FONT_STYLE_OBLIQUE);
1818 bool b = (d->dc[d->level].style.font_weight.value == SP_CSS_FONT_WEIGHT_BOLD) ||
1819 (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);
1820 int lcr = ((d->dc[d->level].textAlign & TA_CENTER) == TA_CENTER) ? 2 : ((d->dc[d->level].textAlign & TA_RIGHT) == TA_RIGHT) ? 1 : 0;
1822 assert_empty_path(d, "EMR_EXTTEXTOUTW");
1824 ts << " <text\n";
1825 ts << " id=\"" << (d->id++) << "\"\n";
1826 ts << " xml:space=\"preserve\"\n";
1827 ts << " x=\"" << x << "\"\n";
1828 ts << " y=\"" << y << "\"\n";
1829 if (d->dc[d->level].style.text_transform.value) {
1830 ts << " transform=\""
1831 << "rotate(-" << d->dc[d->level].style.text_transform.value
1832 << " " << x << " " << y << ")"
1833 << "\"\n";
1834 }
1835 ts << " style=\""
1836 << "font-size:" << fabs(d->dc[d->level].style.font_size.computed) << "px;"
1837 << tmp
1838 << "font-style:" << (i ? "italic" : "normal") << ";"
1839 << "font-weight:" << (b ? "bold" : "normal") << ";"
1840 << "text-align:" << (lcr==2 ? "center" : lcr==1 ? "end" : "start") << ";"
1841 << "text-anchor:" << (lcr==2 ? "middle" : lcr==1 ? "end" : "start") << ";"
1842 << "font-family:" << d->dc[d->level].tstyle.font_family.value << ";"
1843 << "\"\n";
1844 ts << " >";
1845 ts << escaped_text;
1846 ts << "</text>\n";
1848 *(d->outsvg) += ts.str().c_str();
1850 g_free(escaped_text);
1851 g_free(ansi_text);
1852 }
1854 break;
1855 }
1856 case EMR_POLYBEZIER16:
1857 {
1858 dbg_str << "<!-- EMR_POLYBEZIER16 -->\n";
1860 PEMRPOLYBEZIER16 pEmr = (PEMRPOLYBEZIER16) lpEMFR;
1861 POINTS *apts = (POINTS *) pEmr->apts; // Bug in MinGW wingdi.h ?
1862 DWORD i,j;
1864 if (pEmr->cpts<4)
1865 break;
1867 if (!d->inpath) {
1868 assert_empty_path(d, "EMR_POLYBEZIER16");
1870 *(d->outsvg) += " <path ";
1871 output_style(d, EMR_STROKEPATH);
1872 *(d->outsvg) += "\n\td=\"";
1873 }
1875 tmp_str <<
1876 "\n\tM " <<
1877 pix_to_x_point( d, apts[0].x, apts[0].y ) << " " <<
1878 pix_to_y_point( d, apts[0].x, apts[0].y ) << " ";
1880 for (i=1; i<pEmr->cpts; ) {
1881 tmp_str << "\n\tC ";
1882 for (j=0; j<3 && i<pEmr->cpts; j++,i++) {
1883 tmp_str <<
1884 pix_to_x_point( d, apts[i].x, apts[i].y ) << " " <<
1885 pix_to_y_point( d, apts[i].x, apts[i].y ) << " ";
1886 }
1887 }
1889 if (d->inpath) {
1890 tmp_path << tmp_str.str().c_str();
1891 }
1892 else {
1893 *(d->outsvg) += tmp_str.str().c_str();
1894 *(d->outsvg) += " \" /> \n";
1895 }
1897 break;
1898 }
1899 case EMR_POLYGON16:
1900 {
1901 dbg_str << "<!-- EMR_POLYGON16 -->\n";
1903 PEMRPOLYGON16 pEmr = (PEMRPOLYGON16) lpEMFR;
1904 POINTS *apts = (POINTS *) pEmr->apts; // Bug in MinGW wingdi.h ?
1905 SVGOStringStream tmp_poly;
1906 unsigned int i;
1907 unsigned int first = 0;
1909 assert_empty_path(d, "EMR_POLYGON16");
1911 *(d->outsvg) += " <path ";
1912 output_style(d, EMR_STROKEANDFILLPATH);
1913 *(d->outsvg) += "\n\td=\"";
1915 // skip the first point?
1916 tmp_poly << "\n\tM " <<
1917 pix_to_x_point( d, apts[first].x, apts[first].y ) << " " <<
1918 pix_to_y_point( d, apts[first].x, apts[first].y ) << " ";
1920 for (i=first+1; i<pEmr->cpts; i++) {
1921 tmp_poly << "\n\tL " <<
1922 pix_to_x_point( d, apts[i].x, apts[i].y ) << " " <<
1923 pix_to_y_point( d, apts[i].x, apts[i].y ) << " ";
1924 }
1926 *(d->outsvg) += tmp_poly.str().c_str();
1927 *(d->outsvg) += " z \" /> \n";
1929 break;
1930 }
1931 case EMR_POLYLINE16:
1932 {
1933 dbg_str << "<!-- EMR_POLYLINE16 -->\n";
1935 EMRPOLYLINE16 *pEmr = (EMRPOLYLINE16 *) lpEMFR;
1936 POINTS *apts = (POINTS *) pEmr->apts; // Bug in MinGW wingdi.h ?
1937 DWORD i;
1939 if (pEmr->cpts<2)
1940 break;
1942 if (!d->inpath) {
1943 assert_empty_path(d, "EMR_POLYLINE16");
1945 *(d->outsvg) += " <path ";
1946 output_style(d, EMR_STROKEPATH);
1947 *(d->outsvg) += "\n\td=\"";
1948 }
1950 tmp_str <<
1951 "\n\tM " <<
1952 pix_to_x_point( d, apts[0].x, apts[0].y ) << " " <<
1953 pix_to_y_point( d, apts[0].x, apts[0].y ) << " ";
1955 for (i=1; i<pEmr->cpts; i++) {
1956 tmp_str <<
1957 "\n\tL " <<
1958 pix_to_x_point( d, apts[i].x, apts[i].y ) << " " <<
1959 pix_to_y_point( d, apts[i].x, apts[i].y ) << " ";
1960 }
1962 if (d->inpath) {
1963 tmp_path << tmp_str.str().c_str();
1964 }
1965 else {
1966 *(d->outsvg) += tmp_str.str().c_str();
1967 *(d->outsvg) += " \" /> \n";
1968 }
1970 break;
1971 }
1972 case EMR_POLYBEZIERTO16:
1973 {
1974 dbg_str << "<!-- EMR_POLYBEZIERTO16 -->\n";
1976 PEMRPOLYBEZIERTO16 pEmr = (PEMRPOLYBEZIERTO16) lpEMFR;
1977 POINTS *apts = (POINTS *) pEmr->apts; // Bug in MinGW wingdi.h ?
1978 DWORD i,j;
1980 if (d->path->empty()) {
1981 d->pathless_stroke = true;
1982 *(d->path) = "d=\"";
1983 }
1985 for (i=0; i<pEmr->cpts;) {
1986 tmp_path << "\n\tC ";
1987 for (j=0; j<3 && i<pEmr->cpts; j++,i++) {
1988 tmp_path <<
1989 pix_to_x_point( d, apts[i].x, apts[i].y ) << " " <<
1990 pix_to_y_point( d, apts[i].x, apts[i].y ) << " ";
1991 }
1992 }
1994 break;
1995 }
1996 case EMR_POLYLINETO16:
1997 {
1998 dbg_str << "<!-- EMR_POLYLINETO16 -->\n";
2000 PEMRPOLYLINETO16 pEmr = (PEMRPOLYLINETO16) lpEMFR;
2001 POINTS *apts = (POINTS *) pEmr->apts; // Bug in MinGW wingdi.h ?
2002 DWORD i;
2004 if (d->path->empty()) {
2005 d->pathless_stroke = true;
2006 *(d->path) = "d=\"";
2007 }
2009 for (i=0; i<pEmr->cpts;i++) {
2010 tmp_path <<
2011 "\n\tL " <<
2012 pix_to_x_point( d, apts[i].x, apts[i].y ) << " " <<
2013 pix_to_y_point( d, apts[i].x, apts[i].y ) << " ";
2014 }
2016 break;
2017 }
2018 case EMR_POLYPOLYLINE16:
2019 case EMR_POLYPOLYGON16:
2020 {
2021 if (lpEMFR->iType == EMR_POLYPOLYLINE16)
2022 dbg_str << "<!-- EMR_POLYPOLYLINE16 -->\n";
2023 if (lpEMFR->iType == EMR_POLYPOLYGON16)
2024 dbg_str << "<!-- EMR_POLYPOLYGON16 -->\n";
2026 PEMRPOLYPOLYGON16 pEmr = (PEMRPOLYPOLYGON16) lpEMFR;
2027 unsigned int n, i, j;
2029 if (!d->inpath) {
2030 assert_empty_path(d, lpEMFR->iType == EMR_POLYPOLYGON16 ? "EMR_POLYPOLYGON16" : "EMR_POLYPOLYLINE16");
2032 *(d->outsvg) += " <path ";
2033 output_style(d, lpEMFR->iType==EMR_POLYPOLYGON16 ? EMR_STROKEANDFILLPATH : EMR_STROKEPATH);
2034 *(d->outsvg) += "\n\td=\"";
2035 }
2037 POINTS *apts = (POINTS *) &pEmr->aPolyCounts[pEmr->nPolys];
2039 i = 0;
2040 for (n=0; n<pEmr->nPolys && i<pEmr->cpts; n++) {
2041 SVGOStringStream poly_path;
2043 poly_path << "\n\tM " <<
2044 pix_to_x_point( d, apts[i].x, apts[i].y ) << " " <<
2045 pix_to_y_point( d, apts[i].x, apts[i].y ) << " ";
2046 i++;
2048 for (j=1; j<pEmr->aPolyCounts[n] && i<pEmr->cpts; j++) {
2049 poly_path << "\n\tL " <<
2050 pix_to_x_point( d, apts[i].x, apts[i].y ) << " " <<
2051 pix_to_y_point( d, apts[i].x, apts[i].y ) << " ";
2052 i++;
2053 }
2055 tmp_str << poly_path.str().c_str();
2056 if (lpEMFR->iType == EMR_POLYPOLYGON16)
2057 tmp_str << " z";
2058 tmp_str << " \n";
2059 }
2061 if (d->inpath) {
2062 tmp_path << tmp_str.str().c_str();
2063 }
2064 else {
2065 *(d->outsvg) += tmp_str.str().c_str();
2066 *(d->outsvg) += " \" /> \n";
2067 }
2069 break;
2070 }
2071 case EMR_POLYDRAW16:
2072 dbg_str << "<!-- EMR_POLYDRAW16 -->\n";
2073 break;
2074 case EMR_CREATEMONOBRUSH:
2075 dbg_str << "<!-- EMR_CREATEMONOBRUSH -->\n";
2076 break;
2077 case EMR_CREATEDIBPATTERNBRUSHPT:
2078 dbg_str << "<!-- EMR_CREATEDIBPATTERNBRUSHPT -->\n";
2079 break;
2080 case EMR_EXTCREATEPEN:
2081 {
2082 dbg_str << "<!-- EMR_EXTCREATEPEN -->\n";
2084 PEMREXTCREATEPEN pEmr = (PEMREXTCREATEPEN) lpEMFR;
2085 int index = pEmr->ihPen;
2087 EMREXTCREATEPEN *pPen =
2088 (EMREXTCREATEPEN *) malloc( sizeof(EMREXTCREATEPEN) +
2089 sizeof(DWORD) * pEmr->elp.elpNumEntries );
2090 pPen->ihPen = pEmr->ihPen;
2091 pPen->offBmi = pEmr->offBmi;
2092 pPen->cbBmi = pEmr->cbBmi;
2093 pPen->offBits = pEmr->offBits;
2094 pPen->cbBits = pEmr->cbBits;
2095 pPen->elp = pEmr->elp;
2096 for (unsigned int i=0; i<pEmr->elp.elpNumEntries; i++) {
2097 pPen->elp.elpStyleEntry[i] = pEmr->elp.elpStyleEntry[i];
2098 }
2099 insert_object(d, index, EMR_EXTCREATEPEN, (ENHMETARECORD *) pPen);
2101 break;
2102 }
2103 case EMR_POLYTEXTOUTA:
2104 dbg_str << "<!-- EMR_POLYTEXTOUTA -->\n";
2105 break;
2106 case EMR_POLYTEXTOUTW:
2107 dbg_str << "<!-- EMR_POLYTEXTOUTW -->\n";
2108 break;
2109 case EMR_SETICMMODE:
2110 dbg_str << "<!-- EMR_SETICMMODE -->\n";
2111 break;
2112 case EMR_CREATECOLORSPACE:
2113 dbg_str << "<!-- EMR_CREATECOLORSPACE -->\n";
2114 break;
2115 case EMR_SETCOLORSPACE:
2116 dbg_str << "<!-- EMR_SETCOLORSPACE -->\n";
2117 break;
2118 case EMR_DELETECOLORSPACE:
2119 dbg_str << "<!-- EMR_DELETECOLORSPACE -->\n";
2120 break;
2121 case EMR_GLSRECORD:
2122 dbg_str << "<!-- EMR_GLSRECORD -->\n";
2123 break;
2124 case EMR_GLSBOUNDEDRECORD:
2125 dbg_str << "<!-- EMR_GLSBOUNDEDRECORD -->\n";
2126 break;
2127 case EMR_PIXELFORMAT:
2128 dbg_str << "<!-- EMR_PIXELFORMAT -->\n";
2129 break;
2130 default:
2131 dbg_str << "<!-- EMR_??? -->\n";
2132 break;
2133 }
2135 // *(d->outsvg) += dbg_str.str().c_str();
2136 *(d->outsvg) += tmp_outsvg.str().c_str();
2137 *(d->path) += tmp_path.str().c_str();
2139 return 1;
2140 }
2142 static int CALLBACK
2143 myMetaFileProc(HDC /*hDC*/, HANDLETABLE * /*lpHTable*/, METARECORD * /*lpMFR*/, int /*nObj*/, LPARAM /*lpData*/)
2144 {
2145 g_warning("Unable to import Windows Meta File.\n");
2146 return 0;
2147 }
2149 // Aldus Placeable Header ===================================================
2150 // Since we are a 32bit app, we have to be sure this structure compiles to
2151 // be identical to a 16 bit app's version. To do this, we use the #pragma
2152 // to adjust packing, we use a WORD for the hmf handle, and a SMALL_RECT
2153 // for the bbox rectangle.
2154 #pragma pack( push )
2155 #pragma pack( 2 )
2156 typedef struct
2157 {
2158 DWORD dwKey;
2159 WORD hmf;
2160 SMALL_RECT bbox;
2161 WORD wInch;
2162 DWORD dwReserved;
2163 WORD wCheckSum;
2164 } APMHEADER, *PAPMHEADER;
2165 #pragma pack( pop )
2168 SPDocument *
2169 EmfWin32::open( Inkscape::Extension::Input * /*mod*/, const gchar *uri )
2170 {
2171 EMF_CALLBACK_DATA d;
2173 memset(&d, 0, sizeof(d));
2175 d.dc[0].worldTransform.eM11 = 1.0;
2176 d.dc[0].worldTransform.eM12 = 0.0;
2177 d.dc[0].worldTransform.eM21 = 0.0;
2178 d.dc[0].worldTransform.eM22 = 1.0;
2179 d.dc[0].worldTransform.eDx = 0.0;
2180 d.dc[0].worldTransform.eDy = 0.0;
2182 gsize bytesRead = 0;
2183 gsize bytesWritten = 0;
2184 GError* error = NULL;
2185 gchar *local_fn =
2186 g_filename_from_utf8( uri, -1, &bytesRead, &bytesWritten, &error );
2188 if (local_fn == NULL) {
2189 return NULL;
2190 }
2192 d.outsvg = new Glib::ustring("");
2193 d.path = new Glib::ustring("");
2195 CHAR *ansi_uri = (CHAR *) local_fn;
2196 gunichar2 *unicode_fn = g_utf8_to_utf16( local_fn, -1, NULL, NULL, NULL );
2197 WCHAR *unicode_uri = (WCHAR *) unicode_fn;
2199 DWORD filesize = 0;
2200 HANDLE fp = NULL;
2202 HMETAFILE hmf;
2203 HENHMETAFILE hemf;
2205 if (PrintWin32::is_os_wide()) {
2206 fp = CreateFileW(unicode_uri, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
2207 }
2208 else {
2209 fp = CreateFileA(ansi_uri, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
2210 }
2212 if ( fp != INVALID_HANDLE_VALUE ) {
2213 filesize = GetFileSize(fp, NULL);
2214 CloseHandle(fp);
2215 }
2217 // Try open as Enhanced Metafile
2218 if (PrintWin32::is_os_wide())
2219 hemf = GetEnhMetaFileW(unicode_uri);
2220 else
2221 hemf = GetEnhMetaFileA(ansi_uri);
2223 if (!hemf) {
2224 // Try open as Windows Metafile
2225 if (PrintWin32::is_os_wide())
2226 hmf = GetMetaFileW(unicode_uri);
2227 else
2228 hmf = GetMetaFileA(ansi_uri);
2230 METAFILEPICT mp;
2231 HDC hDC;
2233 if (!hmf) {
2234 if (PrintWin32::is_os_wide()) {
2235 WCHAR szTemp[MAX_PATH];
2237 DWORD dw = GetShortPathNameW( unicode_uri, szTemp, MAX_PATH );
2238 if (dw) {
2239 hmf = GetMetaFileW( szTemp );
2240 }
2241 } else {
2242 CHAR szTemp[MAX_PATH];
2244 DWORD dw = GetShortPathNameA( ansi_uri, szTemp, MAX_PATH );
2245 if (dw) {
2246 hmf = GetMetaFileA( szTemp );
2247 }
2248 }
2249 }
2251 if (hmf) {
2252 DWORD nSize = GetMetaFileBitsEx( hmf, 0, NULL );
2254 if (!nSize)
2255 nSize = filesize;
2257 if (nSize) {
2258 BYTE *lpvData = new BYTE[nSize];
2259 if (lpvData) {
2260 DWORD dw = GetMetaFileBitsEx( hmf, nSize, lpvData );
2261 if (dw) {
2262 // Fill out a METAFILEPICT structure
2263 mp.mm = MM_ANISOTROPIC;
2264 mp.xExt = 1000;
2265 mp.yExt = 1000;
2266 mp.hMF = NULL;
2267 // Get a reference DC
2268 hDC = GetDC( NULL );
2269 // Make an enhanced metafile from the windows metafile
2270 hemf = SetWinMetaFileBits( nSize, lpvData, hDC, &mp );
2271 // Clean up
2272 ReleaseDC( NULL, hDC );
2273 DeleteMetaFile( hmf );
2274 hmf = NULL;
2275 }
2276 else {
2277 // EnumMetaFile
2278 }
2279 delete[] lpvData;
2280 }
2281 else {
2282 DeleteMetaFile( hmf );
2283 hmf = NULL;
2284 }
2285 }
2286 else {
2287 DeleteMetaFile( hmf );
2288 hmf = NULL;
2289 }
2290 }
2291 else {
2292 // Try open as Aldus Placeable Metafile
2293 HANDLE hFile;
2294 if (PrintWin32::is_os_wide())
2295 hFile = CreateFileW( unicode_uri, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
2296 else
2297 hFile = CreateFileA( ansi_uri, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
2299 if (hFile != INVALID_HANDLE_VALUE) {
2300 DWORD nSize = GetFileSize( hFile, NULL );
2301 if (nSize) {
2302 BYTE *lpvData = new BYTE[nSize];
2303 if (lpvData) {
2304 DWORD dw = ReadFile( hFile, lpvData, nSize, &nSize, NULL );
2305 if (dw) {
2306 if ( ((PAPMHEADER)lpvData)->dwKey == 0x9ac6cdd7l ) {
2307 // Fill out a METAFILEPICT structure
2308 mp.mm = MM_ANISOTROPIC;
2309 mp.xExt = ((PAPMHEADER)lpvData)->bbox.Right - ((PAPMHEADER)lpvData)->bbox.Left;
2310 mp.xExt = ( mp.xExt * 2540l ) / (DWORD)(((PAPMHEADER)lpvData)->wInch);
2311 mp.yExt = ((PAPMHEADER)lpvData)->bbox.Bottom - ((PAPMHEADER)lpvData)->bbox.Top;
2312 mp.yExt = ( mp.yExt * 2540l ) / (DWORD)(((PAPMHEADER)lpvData)->wInch);
2313 mp.hMF = NULL;
2314 // Get a reference DC
2315 hDC = GetDC( NULL );
2316 // Create an enhanced metafile from the bits
2317 hemf = SetWinMetaFileBits( nSize, lpvData+sizeof(APMHEADER), hDC, &mp );
2318 // Clean up
2319 ReleaseDC( NULL, hDC );
2320 }
2321 }
2322 delete[] lpvData;
2323 }
2324 }
2325 CloseHandle( hFile );
2326 }
2327 }
2328 }
2330 if ((!hemf && !hmf) || !d.outsvg || !d.path) {
2331 if (d.outsvg)
2332 delete d.outsvg;
2333 if (d.path)
2334 delete d.path;
2335 if (local_fn)
2336 g_free(local_fn);
2337 if (unicode_fn)
2338 g_free(unicode_fn);
2339 if (hemf)
2340 DeleteEnhMetaFile(hemf);
2341 if (hmf)
2342 DeleteMetaFile(hmf);
2343 return NULL;
2344 }
2346 d.pDesc = NULL;
2348 if (hemf) {
2349 DWORD dwNeeded = GetEnhMetaFileDescriptionA( hemf, 0, NULL );
2350 if ( dwNeeded > 0 ) {
2351 d.pDesc = (CHAR *) malloc( dwNeeded + 1 );
2352 if ( GetEnhMetaFileDescription( hemf, dwNeeded, d.pDesc ) == 0 )
2353 lstrcpy( d.pDesc, "" );
2354 if ( lstrlen( d.pDesc ) > 1 )
2355 d.pDesc[lstrlen(d.pDesc)] = '#';
2356 }
2358 // This ugly reinterpret_cast is to prevent old versions of gcc from whining about a mismatch in the const-ness of the arguments
2359 EnumEnhMetaFile(NULL, hemf, reinterpret_cast<ENHMFENUMPROC>(myEnhMetaFileProc), (LPVOID) &d, NULL);
2360 DeleteEnhMetaFile(hemf);
2361 }
2362 else {
2363 EnumMetaFile(NULL, hmf, myMetaFileProc, (LPARAM) &d);
2364 DeleteMetaFile(hmf);
2365 }
2367 if (d.pDesc)
2368 free( d.pDesc );
2370 // std::cout << "SVG Output: " << std::endl << *(d.outsvg) << std::endl;
2372 SPDocument *doc = SPDocument::createNewDocFromMem(d.outsvg->c_str(), d.outsvg->length(), TRUE);
2374 delete d.outsvg;
2375 delete d.path;
2377 if (d.emf_obj) {
2378 int i;
2379 for (i=0; i<d.n_obj; i++)
2380 delete_object(&d, i);
2381 delete[] d.emf_obj;
2382 }
2384 if (d.dc[0].style.stroke_dash.dash)
2385 delete[] d.dc[0].style.stroke_dash.dash;
2387 if (local_fn)
2388 g_free(local_fn);
2389 if (unicode_fn)
2390 g_free(unicode_fn);
2392 return doc;
2393 }
2396 void
2397 EmfWin32::init (void)
2398 {
2399 Inkscape::Extension::Extension * ext;
2401 /* EMF in */
2402 ext = Inkscape::Extension::build_from_mem(
2403 "<inkscape-extension xmlns=\"" INKSCAPE_EXTENSION_URI "\">\n"
2404 "<name>" N_("EMF Input") "</name>\n"
2405 "<id>org.inkscape.input.emf.win32</id>\n"
2406 "<input>\n"
2407 "<extension>.emf</extension>\n"
2408 "<mimetype>image/x-emf</mimetype>\n"
2409 "<filetypename>" N_("Enhanced Metafiles (*.emf)") "</filetypename>\n"
2410 "<filetypetooltip>" N_("Enhanced Metafiles") "</filetypetooltip>\n"
2411 "<output_extension>org.inkscape.output.emf.win32</output_extension>\n"
2412 "</input>\n"
2413 "</inkscape-extension>", new EmfWin32());
2415 /* WMF in */
2416 ext = Inkscape::Extension::build_from_mem(
2417 "<inkscape-extension xmlns=\"" INKSCAPE_EXTENSION_URI "\">\n"
2418 "<name>" N_("WMF Input") "</name>\n"
2419 "<id>org.inkscape.input.wmf.win32</id>\n"
2420 "<input>\n"
2421 "<extension>.wmf</extension>\n"
2422 "<mimetype>image/x-wmf</mimetype>\n"
2423 "<filetypename>" N_("Windows Metafiles (*.wmf)") "</filetypename>\n"
2424 "<filetypetooltip>" N_("Windows Metafiles") "</filetypetooltip>\n"
2425 "<output_extension>org.inkscape.output.emf.win32</output_extension>\n"
2426 "</input>\n"
2427 "</inkscape-extension>", new EmfWin32());
2429 /* EMF out */
2430 ext = Inkscape::Extension::build_from_mem(
2431 "<inkscape-extension xmlns=\"" INKSCAPE_EXTENSION_URI "\">\n"
2432 "<name>" N_("EMF Output") "</name>\n"
2433 "<id>org.inkscape.output.emf.win32</id>\n"
2434 "<param name=\"textToPath\" gui-text=\"" N_("Convert texts to paths") "\" type=\"boolean\">true</param>\n"
2435 "<output>\n"
2436 "<extension>.emf</extension>\n"
2437 "<mimetype>image/x-emf</mimetype>\n"
2438 "<filetypename>" N_("Enhanced Metafile (*.emf)") "</filetypename>\n"
2439 "<filetypetooltip>" N_("Enhanced Metafile") "</filetypetooltip>\n"
2440 "</output>\n"
2441 "</inkscape-extension>", new EmfWin32());
2443 return;
2444 }
2447 } } } /* namespace Inkscape, Extension, Implementation */
2449 #endif /* WIN32 */
2450 /*
2451 Local Variables:
2452 mode:c++
2453 c-file-style:"stroustrup"
2454 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
2455 indent-tabs-mode:nil
2456 fill-column:99
2457 End:
2458 */
2459 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :