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