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 throw Inkscape::Extension::Output::save_failed();
131 }
132 sp_item_invoke_print(mod->base, &context);
133 ret = mod->finish();
134 /* Release arena */
135 sp_item_invoke_hide(mod->base, mod->dkey);
136 mod->base = NULL;
137 mod->root = NULL;
138 nr_object_unref((NRObject *) mod->arena);
139 mod->arena = NULL;
140 /* end */
142 mod->set_param_string("destination", oldoutput);
143 g_free(oldoutput);
145 return;
146 }
149 void
150 EmfWin32::save(Inkscape::Extension::Output *mod, SPDocument *doc, gchar const *filename)
151 {
152 Inkscape::Extension::Extension * ext;
154 ext = Inkscape::Extension::db.get(PRINT_EMF_WIN32);
155 if (ext == NULL)
156 return;
158 bool old_textToPath = ext->get_param_bool("textToPath");
159 bool new_val = mod->get_param_bool("textToPath");
160 ext->set_param_bool("textToPath", new_val);
162 emf_print_document_to_file(doc, filename);
164 ext->set_param_bool("textToPath", old_textToPath);
166 return;
167 }
171 typedef struct {
172 int type;
173 int level;
174 ENHMETARECORD *lpEMFR;
175 } EMF_OBJECT, *PEMF_OBJECT;
177 typedef struct emf_device_context {
178 struct SPStyle style;
179 class SPTextStyle tstyle;
180 bool stroke_set;
181 bool fill_set;
183 SIZEL sizeWnd;
184 SIZEL sizeView;
185 float PixelsInX, PixelsInY;
186 float PixelsOutX, PixelsOutY;
187 POINTL winorg;
188 POINTL vieworg;
189 double ScaleInX, ScaleInY;
190 double ScaleOutX, ScaleOutY;
191 COLORREF textColor;
192 bool textColorSet;
193 DWORD textAlign;
194 XFORM worldTransform;
195 POINTL cur;
196 } EMF_DEVICE_CONTEXT, *PEMF_DEVICE_CONTEXT;
198 #define EMF_MAX_DC 128
200 typedef struct emf_callback_data {
201 Glib::ustring *outsvg;
202 Glib::ustring *path;
204 EMF_DEVICE_CONTEXT dc[EMF_MAX_DC+1]; // FIXME: This should be dynamic..
205 int level;
207 double xDPI, yDPI;
208 bool pathless_stroke;
209 bool inpath;
211 float MMX;
212 float MMY;
213 float dwInchesX;
214 float dwInchesY;
216 unsigned int id;
217 CHAR *pDesc;
219 int n_obj;
220 PEMF_OBJECT emf_obj;
221 } EMF_CALLBACK_DATA, *PEMF_CALLBACK_DATA;
224 static void
225 output_style(PEMF_CALLBACK_DATA d, int iType)
226 {
227 SVGOStringStream tmp_id;
228 SVGOStringStream tmp_style;
229 char tmp[1024] = {0};
231 float fill_rgb[3];
232 sp_color_get_rgb_floatv( &(d->dc[d->level].style.fill.value.color), fill_rgb );
234 float stroke_rgb[3];
235 sp_color_get_rgb_floatv(&(d->dc[d->level].style.stroke.value.color), stroke_rgb);
237 tmp_id << "\n\tid=\"" << (d->id++) << "\"";
238 *(d->outsvg) += tmp_id.str().c_str();
239 *(d->outsvg) += "\n\tstyle=\"";
240 if (iType == EMR_STROKEPATH || !d->dc[d->level].fill_set) {
241 tmp_style << "fill:none;";
242 } else {
243 snprintf(tmp, 1023,
244 "fill:#%02x%02x%02x;",
245 SP_COLOR_F_TO_U(fill_rgb[0]),
246 SP_COLOR_F_TO_U(fill_rgb[1]),
247 SP_COLOR_F_TO_U(fill_rgb[2]));
248 tmp_style << tmp;
249 snprintf(tmp, 1023,
250 "fill-rule:%s;",
251 d->dc[d->level].style.fill_rule.value == 0 ? "evenodd" : "nonzero");
252 tmp_style << tmp;
253 tmp_style << "fill-opacity:1;";
255 if (d->dc[d->level].fill_set && d->dc[d->level].stroke_set && d->dc[d->level].style.stroke_width.value == 1 &&
256 fill_rgb[0]==stroke_rgb[0] && fill_rgb[1]==stroke_rgb[1] && fill_rgb[2]==stroke_rgb[2])
257 {
258 d->dc[d->level].stroke_set = false;
259 }
260 }
262 if (iType == EMR_FILLPATH || !d->dc[d->level].stroke_set) {
263 tmp_style << "stroke:none;";
264 } else {
265 snprintf(tmp, 1023,
266 "stroke:#%02x%02x%02x;",
267 SP_COLOR_F_TO_U(stroke_rgb[0]),
268 SP_COLOR_F_TO_U(stroke_rgb[1]),
269 SP_COLOR_F_TO_U(stroke_rgb[2]));
270 tmp_style << tmp;
272 tmp_style << "stroke-width:" <<
273 MAX( 0.001, d->dc[d->level].style.stroke_width.value ) << "px;";
275 tmp_style << "stroke-linecap:" <<
276 (d->dc[d->level].style.stroke_linecap.computed == 0 ? "butt" :
277 d->dc[d->level].style.stroke_linecap.computed == 1 ? "round" :
278 d->dc[d->level].style.stroke_linecap.computed == 2 ? "square" :
279 "unknown") << ";";
281 tmp_style << "stroke-linejoin:" <<
282 (d->dc[d->level].style.stroke_linejoin.computed == 0 ? "miter" :
283 d->dc[d->level].style.stroke_linejoin.computed == 1 ? "round" :
284 d->dc[d->level].style.stroke_linejoin.computed == 2 ? "bevel" :
285 "unknown") << ";";
287 if (d->dc[d->level].style.stroke_linejoin.computed == 0) {
288 tmp_style << "stroke-miterlimit:" <<
289 MAX( 0.01, d->dc[d->level].style.stroke_miterlimit.value ) << ";";
290 }
292 if (d->dc[d->level].style.stroke_dasharray_set &&
293 d->dc[d->level].style.stroke_dash.n_dash && d->dc[d->level].style.stroke_dash.dash)
294 {
295 tmp_style << "stroke-dasharray:";
296 for (int i=0; i<d->dc[d->level].style.stroke_dash.n_dash; i++) {
297 if (i)
298 tmp_style << ",";
299 tmp_style << d->dc[d->level].style.stroke_dash.dash[i];
300 }
301 tmp_style << ";";
302 tmp_style << "stroke-dashoffset:0;";
303 } else {
304 tmp_style << "stroke-dasharray:none;";
305 }
306 tmp_style << "stroke-opacity:1;";
307 }
308 tmp_style << "\" ";
310 *(d->outsvg) += tmp_style.str().c_str();
311 }
314 static double
315 _pix_x_to_point(PEMF_CALLBACK_DATA d, double px)
316 {
317 double tmp = px - d->dc[d->level].winorg.x;
318 tmp *= d->dc[d->level].ScaleInX ? d->dc[d->level].ScaleInX : 1.0;
319 tmp += d->dc[d->level].vieworg.x;
320 return tmp;
321 }
323 static double
324 _pix_y_to_point(PEMF_CALLBACK_DATA d, double px)
325 {
326 double tmp = px - d->dc[d->level].winorg.y;
327 tmp *= d->dc[d->level].ScaleInY ? d->dc[d->level].ScaleInY : 1.0;
328 tmp += d->dc[d->level].vieworg.y;
329 return tmp;
330 }
333 static double
334 pix_to_x_point(PEMF_CALLBACK_DATA d, double px, double py)
335 {
336 double ppx = _pix_x_to_point(d, px);
337 double ppy = _pix_y_to_point(d, py);
339 double x = ppx * d->dc[d->level].worldTransform.eM11 + ppy * d->dc[d->level].worldTransform.eM21 + d->dc[d->level].worldTransform.eDx;
340 x *= d->dc[d->level].ScaleOutX ? d->dc[d->level].ScaleOutX : DEVICESCALE;
342 return x;
343 }
345 static double
346 pix_to_y_point(PEMF_CALLBACK_DATA d, double px, double py)
347 {
348 double ppx = _pix_x_to_point(d, px);
349 double ppy = _pix_y_to_point(d, py);
351 double y = ppx * d->dc[d->level].worldTransform.eM12 + ppy * d->dc[d->level].worldTransform.eM22 + d->dc[d->level].worldTransform.eDy;
352 y *= d->dc[d->level].ScaleOutY ? d->dc[d->level].ScaleOutY : DEVICESCALE;
354 return y;
355 }
357 static double
358 pix_to_size_point(PEMF_CALLBACK_DATA d, double px)
359 {
360 double ppx = px * (d->dc[d->level].ScaleInX ? d->dc[d->level].ScaleInX : 1.0);
361 double ppy = 0;
363 double dx = ppx * d->dc[d->level].worldTransform.eM11 + ppy * d->dc[d->level].worldTransform.eM21;
364 dx *= d->dc[d->level].ScaleOutX ? d->dc[d->level].ScaleOutX : DEVICESCALE;
365 double dy = ppx * d->dc[d->level].worldTransform.eM12 + ppy * d->dc[d->level].worldTransform.eM22;
366 dy *= d->dc[d->level].ScaleOutY ? d->dc[d->level].ScaleOutY : DEVICESCALE;
368 double tmp = sqrt(dx * dx + dy * dy);
369 return tmp;
370 }
373 static void
374 select_pen(PEMF_CALLBACK_DATA d, int index)
375 {
376 PEMRCREATEPEN pEmr = NULL;
378 if (index >= 0 && index < d->n_obj)
379 pEmr = (PEMRCREATEPEN) d->emf_obj[index].lpEMFR;
381 if (!pEmr)
382 return;
384 switch (pEmr->lopn.lopnStyle & PS_STYLE_MASK) {
385 case PS_DASH:
386 case PS_DOT:
387 case PS_DASHDOT:
388 case PS_DASHDOTDOT:
389 {
390 int i = 0;
391 int penstyle = (pEmr->lopn.lopnStyle & PS_STYLE_MASK);
392 d->dc[d->level].style.stroke_dash.n_dash =
393 penstyle == PS_DASHDOTDOT ? 6 : penstyle == PS_DASHDOT ? 4 : 2;
394 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)))
395 delete[] d->dc[d->level].style.stroke_dash.dash;
396 d->dc[d->level].style.stroke_dash.dash = new double[d->dc[d->level].style.stroke_dash.n_dash];
397 if (penstyle==PS_DASH || penstyle==PS_DASHDOT || penstyle==PS_DASHDOTDOT) {
398 d->dc[d->level].style.stroke_dash.dash[i++] = 3;
399 d->dc[d->level].style.stroke_dash.dash[i++] = 1;
400 }
401 if (penstyle==PS_DOT || penstyle==PS_DASHDOT || penstyle==PS_DASHDOTDOT) {
402 d->dc[d->level].style.stroke_dash.dash[i++] = 1;
403 d->dc[d->level].style.stroke_dash.dash[i++] = 1;
404 }
405 if (penstyle==PS_DASHDOTDOT) {
406 d->dc[d->level].style.stroke_dash.dash[i++] = 1;
407 d->dc[d->level].style.stroke_dash.dash[i++] = 1;
408 }
410 d->dc[d->level].style.stroke_dasharray_set = 1;
411 break;
412 }
414 case PS_SOLID:
415 default:
416 {
417 d->dc[d->level].style.stroke_dasharray_set = 0;
418 break;
419 }
420 }
422 switch (pEmr->lopn.lopnStyle & PS_ENDCAP_MASK) {
423 case PS_ENDCAP_ROUND:
424 {
425 d->dc[d->level].style.stroke_linecap.computed = 1;
426 break;
427 }
428 case PS_ENDCAP_SQUARE:
429 {
430 d->dc[d->level].style.stroke_linecap.computed = 2;
431 break;
432 }
433 case PS_ENDCAP_FLAT:
434 default:
435 {
436 d->dc[d->level].style.stroke_linecap.computed = 0;
437 break;
438 }
439 }
441 switch (pEmr->lopn.lopnStyle & PS_JOIN_MASK) {
442 case PS_JOIN_BEVEL:
443 {
444 d->dc[d->level].style.stroke_linejoin.computed = 2;
445 break;
446 }
447 case PS_JOIN_MITER:
448 {
449 d->dc[d->level].style.stroke_linejoin.computed = 0;
450 break;
451 }
452 case PS_JOIN_ROUND:
453 default:
454 {
455 d->dc[d->level].style.stroke_linejoin.computed = 1;
456 break;
457 }
458 }
460 d->dc[d->level].stroke_set = true;
462 if (pEmr->lopn.lopnStyle == PS_NULL) {
463 d->dc[d->level].style.stroke_width.value = 0;
464 d->dc[d->level].stroke_set = false;
465 } else if (pEmr->lopn.lopnWidth.x) {
466 int cur_level = d->level;
467 d->level = d->emf_obj[index].level;
468 double pen_width = pix_to_size_point( d, pEmr->lopn.lopnWidth.x );
469 d->level = cur_level;
470 d->dc[d->level].style.stroke_width.value = pen_width;
471 } else { // this stroke should always be rendered as 1 pixel wide, independent of zoom level (can that be done in SVG?)
472 //d->dc[d->level].style.stroke_width.value = 1.0;
473 int cur_level = d->level;
474 d->level = d->emf_obj[index].level;
475 double pen_width = pix_to_size_point( d, 1 );
476 d->level = cur_level;
477 d->dc[d->level].style.stroke_width.value = pen_width;
478 }
480 double r, g, b;
481 r = SP_COLOR_U_TO_F( GetRValue(pEmr->lopn.lopnColor) );
482 g = SP_COLOR_U_TO_F( GetGValue(pEmr->lopn.lopnColor) );
483 b = SP_COLOR_U_TO_F( GetBValue(pEmr->lopn.lopnColor) );
484 d->dc[d->level].style.stroke.value.color.set( r, g, b );
485 }
488 static void
489 select_extpen(PEMF_CALLBACK_DATA d, int index)
490 {
491 PEMREXTCREATEPEN pEmr = NULL;
493 if (index >= 0 && index < d->n_obj)
494 pEmr = (PEMREXTCREATEPEN) d->emf_obj[index].lpEMFR;
496 if (!pEmr)
497 return;
499 switch (pEmr->elp.elpPenStyle & PS_STYLE_MASK) {
500 case PS_USERSTYLE:
501 {
502 if (pEmr->elp.elpNumEntries) {
503 d->dc[d->level].style.stroke_dash.n_dash = pEmr->elp.elpNumEntries;
504 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)))
505 delete[] d->dc[d->level].style.stroke_dash.dash;
506 d->dc[d->level].style.stroke_dash.dash = new double[pEmr->elp.elpNumEntries];
507 for (unsigned int i=0; i<pEmr->elp.elpNumEntries; i++) {
508 int cur_level = d->level;
509 d->level = d->emf_obj[index].level;
510 double dash_length = pix_to_size_point( d, pEmr->elp.elpStyleEntry[i] );
511 d->level = cur_level;
512 d->dc[d->level].style.stroke_dash.dash[i] = dash_length;
513 }
514 d->dc[d->level].style.stroke_dasharray_set = 1;
515 } else {
516 d->dc[d->level].style.stroke_dasharray_set = 0;
517 }
518 break;
519 }
521 case PS_DASH:
522 case PS_DOT:
523 case PS_DASHDOT:
524 case PS_DASHDOTDOT:
525 {
526 int i = 0;
527 int penstyle = (pEmr->elp.elpPenStyle & PS_STYLE_MASK);
528 d->dc[d->level].style.stroke_dash.n_dash =
529 penstyle == PS_DASHDOTDOT ? 6 : penstyle == PS_DASHDOT ? 4 : 2;
530 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)))
531 delete[] d->dc[d->level].style.stroke_dash.dash;
532 d->dc[d->level].style.stroke_dash.dash = new double[d->dc[d->level].style.stroke_dash.n_dash];
533 if (penstyle==PS_DASH || penstyle==PS_DASHDOT || penstyle==PS_DASHDOTDOT) {
534 d->dc[d->level].style.stroke_dash.dash[i++] = 3;
535 d->dc[d->level].style.stroke_dash.dash[i++] = 2;
536 }
537 if (penstyle==PS_DOT || penstyle==PS_DASHDOT || penstyle==PS_DASHDOTDOT) {
538 d->dc[d->level].style.stroke_dash.dash[i++] = 1;
539 d->dc[d->level].style.stroke_dash.dash[i++] = 2;
540 }
541 if (penstyle==PS_DASHDOTDOT) {
542 d->dc[d->level].style.stroke_dash.dash[i++] = 1;
543 d->dc[d->level].style.stroke_dash.dash[i++] = 2;
544 }
546 d->dc[d->level].style.stroke_dasharray_set = 1;
547 break;
548 }
550 case PS_SOLID:
551 default:
552 {
553 d->dc[d->level].style.stroke_dasharray_set = 0;
554 break;
555 }
556 }
558 switch (pEmr->elp.elpPenStyle & PS_ENDCAP_MASK) {
559 case PS_ENDCAP_ROUND:
560 {
561 d->dc[d->level].style.stroke_linecap.computed = 1;
562 break;
563 }
564 case PS_ENDCAP_SQUARE:
565 {
566 d->dc[d->level].style.stroke_linecap.computed = 2;
567 break;
568 }
569 case PS_ENDCAP_FLAT:
570 default:
571 {
572 d->dc[d->level].style.stroke_linecap.computed = 0;
573 break;
574 }
575 }
577 switch (pEmr->elp.elpPenStyle & PS_JOIN_MASK) {
578 case PS_JOIN_BEVEL:
579 {
580 d->dc[d->level].style.stroke_linejoin.computed = 2;
581 break;
582 }
583 case PS_JOIN_MITER:
584 {
585 d->dc[d->level].style.stroke_linejoin.computed = 0;
586 break;
587 }
588 case PS_JOIN_ROUND:
589 default:
590 {
591 d->dc[d->level].style.stroke_linejoin.computed = 1;
592 break;
593 }
594 }
596 d->dc[d->level].stroke_set = true;
598 if (pEmr->elp.elpPenStyle == PS_NULL) {
599 d->dc[d->level].style.stroke_width.value = 0;
600 d->dc[d->level].stroke_set = false;
601 } else if (pEmr->elp.elpWidth) {
602 int cur_level = d->level;
603 d->level = d->emf_obj[index].level;
604 double pen_width = pix_to_size_point( d, pEmr->elp.elpWidth );
605 d->level = cur_level;
606 d->dc[d->level].style.stroke_width.value = pen_width;
607 } else { // this stroke should always be rendered as 1 pixel wide, independent of zoom level (can that be done in SVG?)
608 //d->dc[d->level].style.stroke_width.value = 1.0;
609 int cur_level = d->level;
610 d->level = d->emf_obj[index].level;
611 double pen_width = pix_to_size_point( d, 1 );
612 d->level = cur_level;
613 d->dc[d->level].style.stroke_width.value = pen_width;
614 }
616 double r, g, b;
617 r = SP_COLOR_U_TO_F( GetRValue(pEmr->elp.elpColor) );
618 g = SP_COLOR_U_TO_F( GetGValue(pEmr->elp.elpColor) );
619 b = SP_COLOR_U_TO_F( GetBValue(pEmr->elp.elpColor) );
621 d->dc[d->level].style.stroke.value.color.set( r, g, b );
622 }
625 static void
626 select_brush(PEMF_CALLBACK_DATA d, int index)
627 {
628 PEMRCREATEBRUSHINDIRECT pEmr = NULL;
630 if (index >= 0 && index < d->n_obj)
631 pEmr = (PEMRCREATEBRUSHINDIRECT) d->emf_obj[index].lpEMFR;
633 if (!pEmr)
634 return;
636 if (pEmr->lb.lbStyle == BS_SOLID) {
637 double r, g, b;
638 r = SP_COLOR_U_TO_F( GetRValue(pEmr->lb.lbColor) );
639 g = SP_COLOR_U_TO_F( GetGValue(pEmr->lb.lbColor) );
640 b = SP_COLOR_U_TO_F( GetBValue(pEmr->lb.lbColor) );
641 d->dc[d->level].style.fill.value.color.set( r, g, b );
642 }
644 d->dc[d->level].fill_set = true;
645 }
648 static void
649 select_font(PEMF_CALLBACK_DATA d, int index)
650 {
651 PEMREXTCREATEFONTINDIRECTW pEmr = NULL;
653 if (index >= 0 && index < d->n_obj)
654 pEmr = (PEMREXTCREATEFONTINDIRECTW) d->emf_obj[index].lpEMFR;
656 if (!pEmr)
657 return;
659 int cur_level = d->level;
660 d->level = d->emf_obj[index].level;
661 double font_size = pix_to_size_point( d, pEmr->elfw.elfLogFont.lfHeight );
662 d->level = cur_level;
663 d->dc[d->level].style.font_size.computed = font_size;
664 d->dc[d->level].style.font_weight.value =
665 pEmr->elfw.elfLogFont.lfWeight == FW_THIN ? SP_CSS_FONT_WEIGHT_100 :
666 pEmr->elfw.elfLogFont.lfWeight == FW_EXTRALIGHT ? SP_CSS_FONT_WEIGHT_200 :
667 pEmr->elfw.elfLogFont.lfWeight == FW_LIGHT ? SP_CSS_FONT_WEIGHT_300 :
668 pEmr->elfw.elfLogFont.lfWeight == FW_NORMAL ? SP_CSS_FONT_WEIGHT_400 :
669 pEmr->elfw.elfLogFont.lfWeight == FW_MEDIUM ? SP_CSS_FONT_WEIGHT_500 :
670 pEmr->elfw.elfLogFont.lfWeight == FW_SEMIBOLD ? SP_CSS_FONT_WEIGHT_600 :
671 pEmr->elfw.elfLogFont.lfWeight == FW_BOLD ? SP_CSS_FONT_WEIGHT_700 :
672 pEmr->elfw.elfLogFont.lfWeight == FW_EXTRABOLD ? SP_CSS_FONT_WEIGHT_800 :
673 pEmr->elfw.elfLogFont.lfWeight == FW_HEAVY ? SP_CSS_FONT_WEIGHT_900 :
674 pEmr->elfw.elfLogFont.lfWeight == FW_NORMAL ? SP_CSS_FONT_WEIGHT_NORMAL :
675 pEmr->elfw.elfLogFont.lfWeight == FW_BOLD ? SP_CSS_FONT_WEIGHT_BOLD :
676 pEmr->elfw.elfLogFont.lfWeight == FW_EXTRALIGHT ? SP_CSS_FONT_WEIGHT_LIGHTER :
677 pEmr->elfw.elfLogFont.lfWeight == FW_EXTRABOLD ? SP_CSS_FONT_WEIGHT_BOLDER :
678 FW_NORMAL;
679 d->dc[d->level].style.font_style.value = (pEmr->elfw.elfLogFont.lfItalic ? SP_CSS_FONT_STYLE_ITALIC : SP_CSS_FONT_STYLE_NORMAL);
680 d->dc[d->level].style.text_decoration.underline = pEmr->elfw.elfLogFont.lfUnderline;
681 d->dc[d->level].style.text_decoration.line_through = pEmr->elfw.elfLogFont.lfStrikeOut;
682 if (d->dc[d->level].tstyle.font_family.value)
683 g_free(d->dc[d->level].tstyle.font_family.value);
684 d->dc[d->level].tstyle.font_family.value =
685 (gchar *) g_utf16_to_utf8( (gunichar2*) pEmr->elfw.elfLogFont.lfFaceName, -1, NULL, NULL, NULL );
686 d->dc[d->level].style.text_transform.value = ((pEmr->elfw.elfLogFont.lfEscapement + 3600) % 3600) / 10;
687 }
689 static void
690 delete_object(PEMF_CALLBACK_DATA d, int index)
691 {
692 if (index >= 0 && index < d->n_obj) {
693 d->emf_obj[index].type = 0;
694 if (d->emf_obj[index].lpEMFR)
695 free(d->emf_obj[index].lpEMFR);
696 d->emf_obj[index].lpEMFR = NULL;
697 }
698 }
701 static void
702 insert_object(PEMF_CALLBACK_DATA d, int index, int type, ENHMETARECORD *pObj)
703 {
704 if (index >= 0 && index < d->n_obj) {
705 delete_object(d, index);
706 d->emf_obj[index].type = type;
707 d->emf_obj[index].level = d->level;
708 d->emf_obj[index].lpEMFR = pObj;
709 }
710 }
712 static void
713 assert_empty_path(PEMF_CALLBACK_DATA d, const char * /*fun*/)
714 {
715 if (!d->path->empty()) {
716 // g_debug("emf-win32-inout: assert_empty_path failed for %s\n", fun);
718 *(d->outsvg) += "<!--\n";
719 *(d->outsvg) += " <path \t";
720 output_style(d, EMR_STROKEPATH);
721 if (strstr(d->path->c_str(), "d=\"") == NULL) {
722 *(d->outsvg) += "d=\"";
723 *(d->outsvg) += "\n\t";
724 }
725 *(d->outsvg) += *(d->path);
726 *(d->outsvg) += " \" /> \n";
727 *(d->outsvg) += "-->\n";
729 *(d->path) = "";
730 }
731 }
734 static int CALLBACK
735 myEnhMetaFileProc(HDC /*hDC*/, HANDLETABLE * /*lpHTable*/, ENHMETARECORD *lpEMFR, int /*nObj*/, LPARAM lpData)
736 {
737 PEMF_CALLBACK_DATA d;
738 SVGOStringStream tmp_outsvg;
739 SVGOStringStream tmp_path;
740 SVGOStringStream tmp_str;
741 SVGOStringStream dbg_str;
743 d = (PEMF_CALLBACK_DATA) lpData;
745 if (d->pathless_stroke) {
746 if (lpEMFR->iType!=EMR_POLYBEZIERTO && lpEMFR->iType!=EMR_POLYBEZIERTO16 &&
747 lpEMFR->iType!=EMR_POLYLINETO && lpEMFR->iType!=EMR_POLYLINETO16 &&
748 lpEMFR->iType!=EMR_LINETO && lpEMFR->iType!=EMR_ARCTO &&
749 lpEMFR->iType!=EMR_SETBKCOLOR && lpEMFR->iType!=EMR_SETROP2 &&
750 lpEMFR->iType!=EMR_SETBKMODE)
751 {
752 *(d->outsvg) += " <path ";
753 output_style(d, EMR_STROKEPATH);
754 *(d->outsvg) += "\n\t";
755 *(d->outsvg) += *(d->path);
756 *(d->outsvg) += " \" /> \n";
757 *(d->path) = "";
758 d->pathless_stroke = false;
759 }
760 }
762 switch (lpEMFR->iType)
763 {
764 case EMR_HEADER:
765 {
766 dbg_str << "<!-- EMR_HEADER -->\n";
768 *(d->outsvg) += "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n";
770 if (d->pDesc) {
771 *(d->outsvg) += "<!-- ";
772 *(d->outsvg) += d->pDesc;
773 *(d->outsvg) += " -->\n";
774 }
776 ENHMETAHEADER *pEmr = (ENHMETAHEADER *) lpEMFR;
777 tmp_outsvg << "<svg\n";
778 tmp_outsvg << " xmlns:svg=\"http://www.w3.org/2000/svg\"\n";
779 tmp_outsvg << " xmlns=\"http://www.w3.org/2000/svg\"\n";
780 tmp_outsvg << " version=\"1.0\"\n";
782 d->xDPI = 2540;
783 d->yDPI = 2540;
785 d->dc[d->level].PixelsInX = pEmr->rclFrame.right - pEmr->rclFrame.left;
786 d->dc[d->level].PixelsInY = pEmr->rclFrame.bottom - pEmr->rclFrame.top;
788 d->MMX = d->dc[d->level].PixelsInX / 100.0;
789 d->MMY = d->dc[d->level].PixelsInY / 100.0;
791 d->dc[d->level].PixelsOutX = d->MMX * PX_PER_MM;
792 d->dc[d->level].PixelsOutY = d->MMY * PX_PER_MM;
794 tmp_outsvg <<
795 " width=\"" << d->MMX << "mm\"\n" <<
796 " height=\"" << d->MMY << "mm\"\n";
797 tmp_outsvg <<
798 " id=\"" << (d->id++) << "\">\n";
800 tmp_outsvg <<
801 "<g\n" <<
802 " id=\"" << (d->id++) << "\">\n";
804 if (pEmr->nHandles) {
805 d->n_obj = pEmr->nHandles;
806 d->emf_obj = new EMF_OBJECT[d->n_obj];
808 // Init the new emf_obj list elements to null, provided the
809 // dynamic allocation succeeded.
810 if ( d->emf_obj != NULL )
811 {
812 for( int i=0; i < d->n_obj; ++i )
813 d->emf_obj[i].lpEMFR = NULL;
814 } //if
816 } else {
817 d->emf_obj = NULL;
818 }
820 break;
821 }
822 case EMR_POLYBEZIER:
823 {
824 dbg_str << "<!-- EMR_POLYBEZIER -->\n";
826 PEMRPOLYBEZIER pEmr = (PEMRPOLYBEZIER) lpEMFR;
827 DWORD i,j;
829 if (pEmr->cptl<4)
830 break;
832 if (!d->inpath) {
833 assert_empty_path(d, "EMR_POLYBEZIER");
835 *(d->outsvg) += " <path ";
836 output_style(d, EMR_STROKEPATH);
837 *(d->outsvg) += "\n\td=\"";
838 }
840 tmp_str <<
841 "\n\tM " <<
842 pix_to_x_point( d, pEmr->aptl[0].x, pEmr->aptl[0].y ) << " " <<
843 pix_to_y_point( d, pEmr->aptl[0].x, pEmr->aptl[0].y) << " ";
845 for (i=1; i<pEmr->cptl; ) {
846 tmp_str << "\n\tC ";
847 for (j=0; j<3 && i<pEmr->cptl; j++,i++) {
848 tmp_str <<
849 pix_to_x_point( d, pEmr->aptl[i].x, pEmr->aptl[i].y ) << " " <<
850 pix_to_y_point( d, pEmr->aptl[i].x, pEmr->aptl[i].y ) << " ";
851 }
852 }
854 if (d->inpath) {
855 tmp_path << tmp_str.str().c_str();
856 }
857 else {
858 *(d->outsvg) += tmp_str.str().c_str();
859 *(d->outsvg) += " \" /> \n";
860 }
862 break;
863 }
864 case EMR_POLYGON:
865 {
866 dbg_str << "<!-- EMR_POLYGON -->\n";
868 EMRPOLYGON *pEmr = (EMRPOLYGON *) lpEMFR;
869 DWORD i;
871 if (pEmr->cptl < 2)
872 break;
874 assert_empty_path(d, "EMR_POLYGON");
876 *(d->outsvg) += " <path ";
877 output_style(d, EMR_STROKEANDFILLPATH);
878 *(d->outsvg) += "\n\td=\"";
880 tmp_str <<
881 "\n\tM " <<
882 pix_to_x_point( d, pEmr->aptl[0].x, pEmr->aptl[0].y ) << " " <<
883 pix_to_y_point( d, pEmr->aptl[0].x, pEmr->aptl[0].y ) << " ";
885 for (i=1; i<pEmr->cptl; i++) {
886 tmp_str <<
887 "\n\tL " <<
888 pix_to_x_point( d, pEmr->aptl[i].x, pEmr->aptl[i].y ) << " " <<
889 pix_to_y_point( d, pEmr->aptl[i].x, pEmr->aptl[i].y ) << " ";
890 }
892 *(d->outsvg) += tmp_str.str().c_str();
893 *(d->outsvg) += " z \" /> \n";
895 break;
896 }
897 case EMR_POLYLINE:
898 {
899 dbg_str << "<!-- EMR_POLYLINE -->\n";
901 EMRPOLYLINE *pEmr = (EMRPOLYLINE *) lpEMFR;
902 DWORD i;
904 if (pEmr->cptl<2)
905 break;
907 if (!d->inpath) {
908 assert_empty_path(d, "EMR_POLYLINE");
910 *(d->outsvg) += " <path ";
911 output_style(d, EMR_STROKEPATH);
912 *(d->outsvg) += "\n\td=\"";
913 }
915 tmp_str <<
916 "\n\tM " <<
917 pix_to_x_point( d, pEmr->aptl[0].x, pEmr->aptl[0].y ) << " " <<
918 pix_to_y_point( d, pEmr->aptl[0].x, pEmr->aptl[0].y ) << " ";
920 for (i=1; i<pEmr->cptl; i++) {
921 tmp_str <<
922 "\n\tL " <<
923 pix_to_x_point( d, pEmr->aptl[i].x, pEmr->aptl[i].y ) << " " <<
924 pix_to_y_point( d, pEmr->aptl[i].x, pEmr->aptl[i].y ) << " ";
925 }
927 if (d->inpath) {
928 tmp_path << tmp_str.str().c_str();
929 }
930 else {
931 *(d->outsvg) += tmp_str.str().c_str();
932 *(d->outsvg) += " \" /> \n";
933 }
935 break;
936 }
937 case EMR_POLYBEZIERTO:
938 {
939 dbg_str << "<!-- EMR_POLYBEZIERTO -->\n";
941 PEMRPOLYBEZIERTO pEmr = (PEMRPOLYBEZIERTO) lpEMFR;
942 DWORD i,j;
944 if (d->path->empty()) {
945 d->pathless_stroke = true;
946 *(d->path) = "d=\"";
947 }
949 for (i=0; i<pEmr->cptl;) {
950 tmp_path << "\n\tC ";
951 for (j=0; j<3 && i<pEmr->cptl; j++,i++) {
952 tmp_path <<
953 pix_to_x_point( d, pEmr->aptl[i].x, pEmr->aptl[i].y ) << " " <<
954 pix_to_y_point( d, pEmr->aptl[i].x, pEmr->aptl[i].y ) << " ";
955 }
956 }
958 break;
959 }
960 case EMR_POLYLINETO:
961 {
962 dbg_str << "<!-- EMR_POLYLINETO -->\n";
964 PEMRPOLYLINETO pEmr = (PEMRPOLYLINETO) lpEMFR;
965 DWORD i;
967 if (d->path->empty()) {
968 d->pathless_stroke = true;
969 *(d->path) = "d=\"";
970 }
972 for (i=0; i<pEmr->cptl;i++) {
973 tmp_path <<
974 "\n\tL " <<
975 pix_to_x_point( d, pEmr->aptl[i].x, pEmr->aptl[i].y ) << " " <<
976 pix_to_y_point( d, pEmr->aptl[i].x, pEmr->aptl[i].y ) << " ";
977 }
979 break;
980 }
981 case EMR_POLYPOLYLINE:
982 case EMR_POLYPOLYGON:
983 {
984 if (lpEMFR->iType == EMR_POLYPOLYLINE)
985 dbg_str << "<!-- EMR_POLYPOLYLINE -->\n";
986 if (lpEMFR->iType == EMR_POLYPOLYGON)
987 dbg_str << "<!-- EMR_POLYPOLYGON -->\n";
989 PEMRPOLYPOLYGON pEmr = (PEMRPOLYPOLYGON) lpEMFR;
990 unsigned int n, i, j;
992 if (!d->inpath) {
993 assert_empty_path(d, lpEMFR->iType == EMR_POLYPOLYGON ? "EMR_POLYPOLYGON" : "EMR_POLYPOLYLINE");
995 *(d->outsvg) += " <path ";
996 output_style(d, lpEMFR->iType==EMR_POLYPOLYGON ? EMR_STROKEANDFILLPATH : EMR_STROKEPATH);
997 *(d->outsvg) += "\n\td=\"";
998 }
1000 POINTL *aptl = (POINTL *) &pEmr->aPolyCounts[pEmr->nPolys];
1002 i = 0;
1003 for (n=0; n<pEmr->nPolys && i<pEmr->cptl; n++) {
1004 SVGOStringStream poly_path;
1006 poly_path << "\n\tM " <<
1007 pix_to_x_point( d, aptl[i].x, aptl[i].y ) << " " <<
1008 pix_to_y_point( d, aptl[i].x, aptl[i].y ) << " ";
1009 i++;
1011 for (j=1; j<pEmr->aPolyCounts[n] && i<pEmr->cptl; j++) {
1012 poly_path << "\n\tL " <<
1013 pix_to_x_point( d, aptl[i].x, aptl[i].y ) << " " <<
1014 pix_to_y_point( d, aptl[i].x, aptl[i].y ) << " ";
1015 i++;
1016 }
1018 tmp_str << poly_path.str().c_str();
1019 if (lpEMFR->iType == EMR_POLYPOLYGON)
1020 tmp_str << " z";
1021 tmp_str << " \n";
1022 }
1024 if (d->inpath) {
1025 tmp_path << tmp_str.str().c_str();
1026 }
1027 else {
1028 *(d->outsvg) += tmp_str.str().c_str();
1029 *(d->outsvg) += " \" /> \n";
1030 }
1032 break;
1033 }
1034 case EMR_SETWINDOWEXTEX:
1035 {
1036 dbg_str << "<!-- EMR_SETWINDOWEXTEX -->\n";
1038 PEMRSETWINDOWEXTEX pEmr = (PEMRSETWINDOWEXTEX) lpEMFR;
1040 d->dc[d->level].sizeWnd = pEmr->szlExtent;
1042 if (!d->dc[d->level].sizeWnd.cx || !d->dc[d->level].sizeWnd.cy) {
1043 d->dc[d->level].sizeWnd = d->dc[d->level].sizeView;
1044 if (!d->dc[d->level].sizeWnd.cx || !d->dc[d->level].sizeWnd.cy) {
1045 d->dc[d->level].sizeWnd.cx = d->dc[d->level].PixelsOutX;
1046 d->dc[d->level].sizeWnd.cy = d->dc[d->level].PixelsOutY;
1047 }
1048 }
1050 if (!d->dc[d->level].sizeView.cx || !d->dc[d->level].sizeView.cy) {
1051 d->dc[d->level].sizeView = d->dc[d->level].sizeWnd;
1052 }
1054 d->dc[d->level].PixelsInX = d->dc[d->level].sizeWnd.cx;
1055 d->dc[d->level].PixelsInY = d->dc[d->level].sizeWnd.cy;
1057 if (d->dc[d->level].PixelsInX && d->dc[d->level].PixelsInY) {
1058 d->dc[d->level].ScaleInX = (double) d->dc[d->level].sizeView.cx / (double) d->dc[d->level].PixelsInX;
1059 d->dc[d->level].ScaleInY = (double) d->dc[d->level].sizeView.cy / (double) d->dc[d->level].PixelsInY;
1060 }
1061 else {
1062 d->dc[d->level].ScaleInX = 1;
1063 d->dc[d->level].ScaleInY = 1;
1064 }
1066 if (d->dc[d->level].sizeView.cx && d->dc[d->level].sizeView.cy) {
1067 d->dc[d->level].ScaleOutX = (double) d->dc[d->level].PixelsOutX / (double) d->dc[d->level].sizeView.cx;
1068 d->dc[d->level].ScaleOutY = (double) d->dc[d->level].PixelsOutY / (double) d->dc[d->level].sizeView.cy;
1069 }
1070 else {
1071 d->dc[d->level].ScaleOutX = DEVICESCALE;
1072 d->dc[d->level].ScaleOutY = DEVICESCALE;
1073 }
1075 break;
1076 }
1077 case EMR_SETWINDOWORGEX:
1078 {
1079 dbg_str << "<!-- EMR_SETWINDOWORGEX -->\n";
1081 PEMRSETWINDOWORGEX pEmr = (PEMRSETWINDOWORGEX) lpEMFR;
1082 d->dc[d->level].winorg = pEmr->ptlOrigin;
1083 break;
1084 }
1085 case EMR_SETVIEWPORTEXTEX:
1086 {
1087 dbg_str << "<!-- EMR_SETVIEWPORTEXTEX -->\n";
1089 PEMRSETVIEWPORTEXTEX pEmr = (PEMRSETVIEWPORTEXTEX) lpEMFR;
1091 d->dc[d->level].sizeView = pEmr->szlExtent;
1093 if (!d->dc[d->level].sizeView.cx || !d->dc[d->level].sizeView.cy) {
1094 d->dc[d->level].sizeView = d->dc[d->level].sizeWnd;
1095 if (!d->dc[d->level].sizeView.cx || !d->dc[d->level].sizeView.cy) {
1096 d->dc[d->level].sizeView.cx = d->dc[d->level].PixelsOutX;
1097 d->dc[d->level].sizeView.cy = d->dc[d->level].PixelsOutY;
1098 }
1099 }
1101 if (!d->dc[d->level].sizeWnd.cx || !d->dc[d->level].sizeWnd.cy) {
1102 d->dc[d->level].sizeWnd = d->dc[d->level].sizeView;
1103 }
1105 d->dc[d->level].PixelsInX = d->dc[d->level].sizeWnd.cx;
1106 d->dc[d->level].PixelsInY = d->dc[d->level].sizeWnd.cy;
1108 if (d->dc[d->level].PixelsInX && d->dc[d->level].PixelsInY) {
1109 d->dc[d->level].ScaleInX = (double) d->dc[d->level].sizeView.cx / (double) d->dc[d->level].PixelsInX;
1110 d->dc[d->level].ScaleInY = (double) d->dc[d->level].sizeView.cy / (double) d->dc[d->level].PixelsInY;
1111 }
1112 else {
1113 d->dc[d->level].ScaleInX = 1;
1114 d->dc[d->level].ScaleInY = 1;
1115 }
1117 if (d->dc[d->level].sizeView.cx && d->dc[d->level].sizeView.cy) {
1118 d->dc[d->level].ScaleOutX = (double) d->dc[d->level].PixelsOutX / (double) d->dc[d->level].sizeView.cx;
1119 d->dc[d->level].ScaleOutY = (double) d->dc[d->level].PixelsOutY / (double) d->dc[d->level].sizeView.cy;
1120 }
1121 else {
1122 d->dc[d->level].ScaleOutX = DEVICESCALE;
1123 d->dc[d->level].ScaleOutY = DEVICESCALE;
1124 }
1126 break;
1127 }
1128 case EMR_SETVIEWPORTORGEX:
1129 {
1130 dbg_str << "<!-- EMR_SETVIEWPORTORGEX -->\n";
1132 PEMRSETVIEWPORTORGEX pEmr = (PEMRSETVIEWPORTORGEX) lpEMFR;
1133 d->dc[d->level].vieworg = pEmr->ptlOrigin;
1134 break;
1135 }
1136 case EMR_SETBRUSHORGEX:
1137 dbg_str << "<!-- EMR_SETBRUSHORGEX -->\n";
1138 break;
1139 case EMR_EOF:
1140 {
1141 dbg_str << "<!-- EMR_EOF -->\n";
1143 assert_empty_path(d, "EMR_EOF");
1144 tmp_outsvg << "</g>\n";
1145 tmp_outsvg << "</svg>\n";
1146 break;
1147 }
1148 case EMR_SETPIXELV:
1149 dbg_str << "<!-- EMR_SETPIXELV -->\n";
1150 break;
1151 case EMR_SETMAPPERFLAGS:
1152 dbg_str << "<!-- EMR_SETMAPPERFLAGS -->\n";
1153 break;
1154 case EMR_SETMAPMODE:
1155 dbg_str << "<!-- EMR_SETMAPMODE -->\n";
1156 break;
1157 case EMR_SETBKMODE:
1158 dbg_str << "<!-- EMR_SETBKMODE -->\n";
1159 break;
1160 case EMR_SETPOLYFILLMODE:
1161 {
1162 dbg_str << "<!-- EMR_SETPOLYFILLMODE -->\n";
1164 PEMRSETPOLYFILLMODE pEmr = (PEMRSETPOLYFILLMODE) lpEMFR;
1165 d->dc[d->level].style.fill_rule.value =
1166 (pEmr->iMode == ALTERNATE ? 0 :
1167 pEmr->iMode == WINDING ? 1 : 0);
1168 break;
1169 }
1170 case EMR_SETROP2:
1171 dbg_str << "<!-- EMR_SETROP2 -->\n";
1172 break;
1173 case EMR_SETSTRETCHBLTMODE:
1174 dbg_str << "<!-- EMR_SETSTRETCHBLTMODE -->\n";
1175 break;
1176 case EMR_SETTEXTALIGN:
1177 {
1178 dbg_str << "<!-- EMR_SETTEXTALIGN -->\n";
1180 PEMRSETTEXTALIGN pEmr = (PEMRSETTEXTALIGN) lpEMFR;
1181 d->dc[d->level].textAlign = pEmr->iMode;
1182 break;
1183 }
1184 case EMR_SETCOLORADJUSTMENT:
1185 dbg_str << "<!-- EMR_SETCOLORADJUSTMENT -->\n";
1186 break;
1187 case EMR_SETTEXTCOLOR:
1188 {
1189 dbg_str << "<!-- EMR_SETTEXTCOLOR -->\n";
1191 PEMRSETTEXTCOLOR pEmr = (PEMRSETTEXTCOLOR) lpEMFR;
1192 d->dc[d->level].textColor = pEmr->crColor;
1193 d->dc[d->level].textColorSet = true;
1194 break;
1195 }
1196 case EMR_SETBKCOLOR:
1197 dbg_str << "<!-- EMR_SETBKCOLOR -->\n";
1198 break;
1199 case EMR_OFFSETCLIPRGN:
1200 dbg_str << "<!-- EMR_OFFSETCLIPRGN -->\n";
1201 break;
1202 case EMR_MOVETOEX:
1203 {
1204 dbg_str << "<!-- EMR_MOVETOEX -->\n";
1206 PEMRMOVETOEX pEmr = (PEMRMOVETOEX) lpEMFR;
1208 if (d->path->empty()) {
1209 d->pathless_stroke = true;
1210 *(d->path) = "d=\"";
1211 }
1213 d->dc[d->level].cur = pEmr->ptl;
1215 tmp_path <<
1216 "\n\tM " <<
1217 pix_to_x_point( d, pEmr->ptl.x, pEmr->ptl.y ) << " " <<
1218 pix_to_y_point( d, pEmr->ptl.x, pEmr->ptl.y ) << " ";
1219 break;
1220 }
1221 case EMR_SETMETARGN:
1222 dbg_str << "<!-- EMR_SETMETARGN -->\n";
1223 break;
1224 case EMR_EXCLUDECLIPRECT:
1225 dbg_str << "<!-- EMR_EXCLUDECLIPRECT -->\n";
1226 break;
1227 case EMR_INTERSECTCLIPRECT:
1228 dbg_str << "<!-- EMR_INTERSECTCLIPRECT -->\n";
1229 break;
1230 case EMR_SCALEVIEWPORTEXTEX:
1231 dbg_str << "<!-- EMR_SCALEVIEWPORTEXTEX -->\n";
1232 break;
1233 case EMR_SCALEWINDOWEXTEX:
1234 dbg_str << "<!-- EMR_SCALEWINDOWEXTEX -->\n";
1235 break;
1236 case EMR_SAVEDC:
1237 dbg_str << "<!-- EMR_SAVEDC -->\n";
1239 if (d->level < EMF_MAX_DC) {
1240 d->dc[d->level + 1] = d->dc[d->level];
1241 d->level = d->level + 1;
1242 }
1243 break;
1244 case EMR_RESTOREDC:
1245 {
1246 dbg_str << "<!-- EMR_RESTOREDC -->\n";
1248 PEMRRESTOREDC pEmr = (PEMRRESTOREDC) lpEMFR;
1249 int old_level = d->level;
1250 if (pEmr->iRelative >= 0) {
1251 if (pEmr->iRelative < d->level)
1252 d->level = pEmr->iRelative;
1253 }
1254 else {
1255 if (d->level + pEmr->iRelative >= 0)
1256 d->level = d->level + pEmr->iRelative;
1257 }
1258 while (old_level > d->level) {
1259 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)))
1260 delete[] d->dc[old_level].style.stroke_dash.dash;
1261 old_level--;
1262 }
1263 break;
1264 }
1265 case EMR_SETWORLDTRANSFORM:
1266 {
1267 dbg_str << "<!-- EMR_SETWORLDTRANSFORM -->\n";
1269 PEMRSETWORLDTRANSFORM pEmr = (PEMRSETWORLDTRANSFORM) lpEMFR;
1270 d->dc[d->level].worldTransform = pEmr->xform;
1271 break;
1272 }
1273 case EMR_MODIFYWORLDTRANSFORM:
1274 {
1275 dbg_str << "<!-- EMR_MODIFYWORLDTRANSFORM -->\n";
1277 PEMRMODIFYWORLDTRANSFORM pEmr = (PEMRMODIFYWORLDTRANSFORM) lpEMFR;
1278 switch (pEmr->iMode)
1279 {
1280 case MWT_IDENTITY:
1281 d->dc[d->level].worldTransform.eM11 = 1.0;
1282 d->dc[d->level].worldTransform.eM12 = 0.0;
1283 d->dc[d->level].worldTransform.eM21 = 0.0;
1284 d->dc[d->level].worldTransform.eM22 = 1.0;
1285 d->dc[d->level].worldTransform.eDx = 0.0;
1286 d->dc[d->level].worldTransform.eDy = 0.0;
1287 break;
1288 case MWT_LEFTMULTIPLY:
1289 {
1290 // d->dc[d->level].worldTransform = pEmr->xform * worldTransform;
1292 float a11 = pEmr->xform.eM11;
1293 float a12 = pEmr->xform.eM12;
1294 float a13 = 0.0;
1295 float a21 = pEmr->xform.eM21;
1296 float a22 = pEmr->xform.eM22;
1297 float a23 = 0.0;
1298 float a31 = pEmr->xform.eDx;
1299 float a32 = pEmr->xform.eDy;
1300 float a33 = 1.0;
1302 float b11 = d->dc[d->level].worldTransform.eM11;
1303 float b12 = d->dc[d->level].worldTransform.eM12;
1304 //float b13 = 0.0;
1305 float b21 = d->dc[d->level].worldTransform.eM21;
1306 float b22 = d->dc[d->level].worldTransform.eM22;
1307 //float b23 = 0.0;
1308 float b31 = d->dc[d->level].worldTransform.eDx;
1309 float b32 = d->dc[d->level].worldTransform.eDy;
1310 //float b33 = 1.0;
1312 float c11 = a11*b11 + a12*b21 + a13*b31;;
1313 float c12 = a11*b12 + a12*b22 + a13*b32;;
1314 //float c13 = a11*b13 + a12*b23 + a13*b33;;
1315 float c21 = a21*b11 + a22*b21 + a23*b31;;
1316 float c22 = a21*b12 + a22*b22 + a23*b32;;
1317 //float c23 = a21*b13 + a22*b23 + a23*b33;;
1318 float c31 = a31*b11 + a32*b21 + a33*b31;;
1319 float c32 = a31*b12 + a32*b22 + a33*b32;;
1320 //float c33 = a31*b13 + a32*b23 + a33*b33;;
1322 d->dc[d->level].worldTransform.eM11 = c11;;
1323 d->dc[d->level].worldTransform.eM12 = c12;;
1324 d->dc[d->level].worldTransform.eM21 = c21;;
1325 d->dc[d->level].worldTransform.eM22 = c22;;
1326 d->dc[d->level].worldTransform.eDx = c31;
1327 d->dc[d->level].worldTransform.eDy = c32;
1329 break;
1330 }
1331 case MWT_RIGHTMULTIPLY:
1332 {
1333 // d->dc[d->level].worldTransform = worldTransform * pEmr->xform;
1335 float a11 = d->dc[d->level].worldTransform.eM11;
1336 float a12 = d->dc[d->level].worldTransform.eM12;
1337 float a13 = 0.0;
1338 float a21 = d->dc[d->level].worldTransform.eM21;
1339 float a22 = d->dc[d->level].worldTransform.eM22;
1340 float a23 = 0.0;
1341 float a31 = d->dc[d->level].worldTransform.eDx;
1342 float a32 = d->dc[d->level].worldTransform.eDy;
1343 float a33 = 1.0;
1345 float b11 = pEmr->xform.eM11;
1346 float b12 = pEmr->xform.eM12;
1347 //float b13 = 0.0;
1348 float b21 = pEmr->xform.eM21;
1349 float b22 = pEmr->xform.eM22;
1350 //float b23 = 0.0;
1351 float b31 = pEmr->xform.eDx;
1352 float b32 = pEmr->xform.eDy;
1353 //float b33 = 1.0;
1355 float c11 = a11*b11 + a12*b21 + a13*b31;;
1356 float c12 = a11*b12 + a12*b22 + a13*b32;;
1357 //float c13 = a11*b13 + a12*b23 + a13*b33;;
1358 float c21 = a21*b11 + a22*b21 + a23*b31;;
1359 float c22 = a21*b12 + a22*b22 + a23*b32;;
1360 //float c23 = a21*b13 + a22*b23 + a23*b33;;
1361 float c31 = a31*b11 + a32*b21 + a33*b31;;
1362 float c32 = a31*b12 + a32*b22 + a33*b32;;
1363 //float c33 = a31*b13 + a32*b23 + a33*b33;;
1365 d->dc[d->level].worldTransform.eM11 = c11;;
1366 d->dc[d->level].worldTransform.eM12 = c12;;
1367 d->dc[d->level].worldTransform.eM21 = c21;;
1368 d->dc[d->level].worldTransform.eM22 = c22;;
1369 d->dc[d->level].worldTransform.eDx = c31;
1370 d->dc[d->level].worldTransform.eDy = c32;
1372 break;
1373 }
1374 // case MWT_SET:
1375 default:
1376 d->dc[d->level].worldTransform = pEmr->xform;
1377 break;
1378 }
1379 break;
1380 }
1381 case EMR_SELECTOBJECT:
1382 {
1383 dbg_str << "<!-- EMR_SELECTOBJECT -->\n";
1385 PEMRSELECTOBJECT pEmr = (PEMRSELECTOBJECT) lpEMFR;
1386 unsigned int index = pEmr->ihObject;
1388 if (index >= ENHMETA_STOCK_OBJECT) {
1389 index -= ENHMETA_STOCK_OBJECT;
1390 switch (index) {
1391 case NULL_BRUSH:
1392 d->dc[d->level].fill_set = false;
1393 break;
1394 case BLACK_BRUSH:
1395 case DKGRAY_BRUSH:
1396 case GRAY_BRUSH:
1397 case LTGRAY_BRUSH:
1398 case WHITE_BRUSH:
1399 {
1400 float val = 0;
1401 switch (index) {
1402 case BLACK_BRUSH:
1403 val = 0.0 / 255.0;
1404 break;
1405 case DKGRAY_BRUSH:
1406 val = 64.0 / 255.0;
1407 break;
1408 case GRAY_BRUSH:
1409 val = 128.0 / 255.0;
1410 break;
1411 case LTGRAY_BRUSH:
1412 val = 192.0 / 255.0;
1413 break;
1414 case WHITE_BRUSH:
1415 val = 255.0 / 255.0;
1416 break;
1417 }
1418 d->dc[d->level].style.fill.value.color.set( val, val, val );
1420 d->dc[d->level].fill_set = true;
1421 break;
1422 }
1423 case NULL_PEN:
1424 d->dc[d->level].stroke_set = false;
1425 break;
1426 case BLACK_PEN:
1427 case WHITE_PEN:
1428 {
1429 float val = index == BLACK_PEN ? 0 : 1;
1430 d->dc[d->level].style.stroke_dasharray_set = 0;
1431 d->dc[d->level].style.stroke_width.value = 1.0;
1432 d->dc[d->level].style.stroke.value.color.set( val, val, val );
1434 d->dc[d->level].stroke_set = true;
1436 break;
1437 }
1438 }
1439 } else {
1440 if ( /*index >= 0 &&*/ index < (unsigned int) d->n_obj) {
1441 switch (d->emf_obj[index].type)
1442 {
1443 case EMR_CREATEPEN:
1444 select_pen(d, index);
1445 break;
1446 case EMR_CREATEBRUSHINDIRECT:
1447 select_brush(d, index);
1448 break;
1449 case EMR_EXTCREATEPEN:
1450 select_extpen(d, index);
1451 break;
1452 case EMR_EXTCREATEFONTINDIRECTW:
1453 select_font(d, index);
1454 break;
1455 }
1456 }
1457 }
1458 break;
1459 }
1460 case EMR_CREATEPEN:
1461 {
1462 dbg_str << "<!-- EMR_CREATEPEN -->\n";
1464 PEMRCREATEPEN pEmr = (PEMRCREATEPEN) lpEMFR;
1465 int index = pEmr->ihPen;
1467 EMRCREATEPEN *pPen =
1468 (EMRCREATEPEN *) malloc( sizeof(EMRCREATEPEN) );
1469 pPen->lopn = pEmr->lopn;
1470 insert_object(d, index, EMR_CREATEPEN, (ENHMETARECORD *) pPen);
1472 break;
1473 }
1474 case EMR_CREATEBRUSHINDIRECT:
1475 {
1476 dbg_str << "<!-- EMR_CREATEBRUSHINDIRECT -->\n";
1478 PEMRCREATEBRUSHINDIRECT pEmr = (PEMRCREATEBRUSHINDIRECT) lpEMFR;
1479 int index = pEmr->ihBrush;
1481 EMRCREATEBRUSHINDIRECT *pBrush =
1482 (EMRCREATEBRUSHINDIRECT *) malloc( sizeof(EMRCREATEBRUSHINDIRECT) );
1483 pBrush->lb = pEmr->lb;
1484 insert_object(d, index, EMR_CREATEBRUSHINDIRECT, (ENHMETARECORD *) pBrush);
1486 break;
1487 }
1488 case EMR_DELETEOBJECT:
1489 dbg_str << "<!-- EMR_DELETEOBJECT -->\n";
1490 break;
1491 case EMR_ANGLEARC:
1492 dbg_str << "<!-- EMR_ANGLEARC -->\n";
1493 break;
1494 case EMR_ELLIPSE:
1495 {
1496 dbg_str << "<!-- EMR_ELLIPSE -->\n";
1498 PEMRELLIPSE pEmr = (PEMRELLIPSE) lpEMFR;
1499 RECTL rclBox = pEmr->rclBox;
1501 double l = pix_to_x_point( d, pEmr->rclBox.left, pEmr->rclBox.top );
1502 double t = pix_to_y_point( d, pEmr->rclBox.left, pEmr->rclBox.top );
1503 double r = pix_to_x_point( d, pEmr->rclBox.right, pEmr->rclBox.bottom );
1504 double b = pix_to_y_point( d, pEmr->rclBox.right, pEmr->rclBox.bottom );
1506 double cx = (l + r) / 2.0;
1507 double cy = (t + b) / 2.0;
1508 double rx = fabs(l - r) / 2.0;
1509 double ry = fabs(t - b) / 2.0;
1511 SVGOStringStream tmp_ellipse;
1512 tmp_ellipse << "cx=\"" << cx << "\" ";
1513 tmp_ellipse << "cy=\"" << cy << "\" ";
1514 tmp_ellipse << "rx=\"" << rx << "\" ";
1515 tmp_ellipse << "ry=\"" << ry << "\" ";
1517 assert_empty_path(d, "EMR_ELLIPSE");
1519 *(d->outsvg) += " <ellipse ";
1520 output_style(d, lpEMFR->iType);
1521 *(d->outsvg) += "\n\t";
1522 *(d->outsvg) += tmp_ellipse.str().c_str();
1523 *(d->outsvg) += "/> \n";
1524 *(d->path) = "";
1525 break;
1526 }
1527 case EMR_RECTANGLE:
1528 {
1529 dbg_str << "<!-- EMR_RECTANGLE -->\n";
1531 PEMRRECTANGLE pEmr = (PEMRRECTANGLE) lpEMFR;
1532 RECTL rc = pEmr->rclBox;
1534 double l = pix_to_x_point( d, rc.left, rc.top );
1535 double t = pix_to_y_point( d, rc.left, rc.top );
1536 double r = pix_to_x_point( d, rc.right, rc.bottom );
1537 double b = pix_to_y_point( d, rc.right, rc.bottom );
1539 SVGOStringStream tmp_rectangle;
1540 tmp_rectangle << "d=\"";
1541 tmp_rectangle << "\n\tM " << l << " " << t << " ";
1542 tmp_rectangle << "\n\tL " << r << " " << t << " ";
1543 tmp_rectangle << "\n\tL " << r << " " << b << " ";
1544 tmp_rectangle << "\n\tL " << l << " " << b << " ";
1545 tmp_rectangle << "\n\tz";
1547 assert_empty_path(d, "EMR_RECTANGLE");
1549 *(d->outsvg) += " <path ";
1550 output_style(d, lpEMFR->iType);
1551 *(d->outsvg) += "\n\t";
1552 *(d->outsvg) += tmp_rectangle.str().c_str();
1553 *(d->outsvg) += " \" /> \n";
1554 *(d->path) = "";
1555 break;
1556 }
1557 case EMR_ROUNDRECT:
1558 dbg_str << "<!-- EMR_ROUNDRECT -->\n";
1559 break;
1560 case EMR_ARC:
1561 dbg_str << "<!-- EMR_ARC -->\n";
1562 break;
1563 case EMR_CHORD:
1564 dbg_str << "<!-- EMR_CHORD -->\n";
1565 break;
1566 case EMR_PIE:
1567 dbg_str << "<!-- EMR_PIE -->\n";
1568 break;
1569 case EMR_SELECTPALETTE:
1570 dbg_str << "<!-- EMR_SELECTPALETTE -->\n";
1571 break;
1572 case EMR_CREATEPALETTE:
1573 dbg_str << "<!-- EMR_CREATEPALETTE -->\n";
1574 break;
1575 case EMR_SETPALETTEENTRIES:
1576 dbg_str << "<!-- EMR_SETPALETTEENTRIES -->\n";
1577 break;
1578 case EMR_RESIZEPALETTE:
1579 dbg_str << "<!-- EMR_RESIZEPALETTE -->\n";
1580 break;
1581 case EMR_REALIZEPALETTE:
1582 dbg_str << "<!-- EMR_REALIZEPALETTE -->\n";
1583 break;
1584 case EMR_EXTFLOODFILL:
1585 dbg_str << "<!-- EMR_EXTFLOODFILL -->\n";
1586 break;
1587 case EMR_LINETO:
1588 {
1589 dbg_str << "<!-- EMR_LINETO -->\n";
1591 PEMRLINETO pEmr = (PEMRLINETO) lpEMFR;
1593 if (d->path->empty()) {
1594 d->pathless_stroke = true;
1595 *(d->path) = "d=\"";
1596 }
1598 tmp_path <<
1599 "\n\tL " <<
1600 pix_to_x_point( d, pEmr->ptl.x, pEmr->ptl.y ) << " " <<
1601 pix_to_y_point( d, pEmr->ptl.x, pEmr->ptl.y ) << " ";
1602 break;
1603 }
1604 case EMR_ARCTO:
1605 dbg_str << "<!-- EMR_ARCTO -->\n";
1606 break;
1607 case EMR_POLYDRAW:
1608 dbg_str << "<!-- EMR_POLYDRAW -->\n";
1609 break;
1610 case EMR_SETARCDIRECTION:
1611 dbg_str << "<!-- EMR_SETARCDIRECTION -->\n";
1612 break;
1613 case EMR_SETMITERLIMIT:
1614 {
1615 dbg_str << "<!-- EMR_SETMITERLIMIT -->\n";
1617 PEMRSETMITERLIMIT pEmr = (PEMRSETMITERLIMIT) lpEMFR;
1619 float miterlimit = pEmr->eMiterLimit;
1620 miterlimit = miterlimit * 4.0 / 10.0;
1621 d->dc[d->level].style.stroke_miterlimit.value = pix_to_size_point( d, miterlimit );
1622 if (d->dc[d->level].style.stroke_miterlimit.value < 1)
1623 d->dc[d->level].style.stroke_miterlimit.value = 4.0;
1624 break;
1625 }
1626 case EMR_BEGINPATH:
1627 {
1628 dbg_str << "<!-- EMR_BEGINPATH -->\n";
1630 tmp_path << "d=\"";
1631 *(d->path) = "";
1632 d->inpath = true;
1633 break;
1634 }
1635 case EMR_ENDPATH:
1636 {
1637 dbg_str << "<!-- EMR_ENDPATH -->\n";
1639 tmp_path << "\"";
1640 d->inpath = false;
1641 break;
1642 }
1643 case EMR_CLOSEFIGURE:
1644 {
1645 dbg_str << "<!-- EMR_CLOSEFIGURE -->\n";
1647 tmp_path << "\n\tz";
1648 break;
1649 }
1650 case EMR_FILLPATH:
1651 case EMR_STROKEANDFILLPATH:
1652 case EMR_STROKEPATH:
1653 {
1654 if (lpEMFR->iType == EMR_FILLPATH)
1655 dbg_str << "<!-- EMR_FILLPATH -->\n";
1656 if (lpEMFR->iType == EMR_STROKEANDFILLPATH)
1657 dbg_str << "<!-- EMR_STROKEANDFILLPATH -->\n";
1658 if (lpEMFR->iType == EMR_STROKEPATH)
1659 dbg_str << "<!-- EMR_STROKEPATH -->\n";
1661 *(d->outsvg) += " <path ";
1662 output_style(d, lpEMFR->iType);
1663 *(d->outsvg) += "\n\t";
1664 *(d->outsvg) += *(d->path);
1665 *(d->outsvg) += " /> \n";
1666 *(d->path) = "";
1667 break;
1668 }
1669 case EMR_FLATTENPATH:
1670 dbg_str << "<!-- EMR_FLATTENPATH -->\n";
1671 break;
1672 case EMR_WIDENPATH:
1673 dbg_str << "<!-- EMR_WIDENPATH -->\n";
1674 break;
1675 case EMR_SELECTCLIPPATH:
1676 dbg_str << "<!-- EMR_SELECTCLIPPATH -->\n";
1677 break;
1678 case EMR_ABORTPATH:
1679 dbg_str << "<!-- EMR_ABORTPATH -->\n";
1680 break;
1681 case EMR_GDICOMMENT:
1682 {
1683 dbg_str << "<!-- EMR_GDICOMMENT -->\n";
1685 PEMRGDICOMMENT pEmr = (PEMRGDICOMMENT) lpEMFR;
1687 CHAR *szTxt = (CHAR *) pEmr->Data;
1689 for (DWORD i = 0; i < pEmr->cbData; i++) {
1690 if ( *szTxt) {
1691 if ( *szTxt >= ' ' && *szTxt < 'z' && *szTxt != '<' && *szTxt != '>' ) {
1692 tmp_str << *szTxt;
1693 }
1694 szTxt++;
1695 }
1696 }
1698 if (0 && strlen(tmp_str.str().c_str())) {
1699 tmp_outsvg << " <!-- \"";
1700 tmp_outsvg << tmp_str.str().c_str();
1701 tmp_outsvg << "\" -->\n";
1702 }
1704 break;
1705 }
1706 case EMR_FILLRGN:
1707 dbg_str << "<!-- EMR_FILLRGN -->\n";
1708 break;
1709 case EMR_FRAMERGN:
1710 dbg_str << "<!-- EMR_FRAMERGN -->\n";
1711 break;
1712 case EMR_INVERTRGN:
1713 dbg_str << "<!-- EMR_INVERTRGN -->\n";
1714 break;
1715 case EMR_PAINTRGN:
1716 dbg_str << "<!-- EMR_PAINTRGN -->\n";
1717 break;
1718 case EMR_EXTSELECTCLIPRGN:
1719 dbg_str << "<!-- EMR_EXTSELECTCLIPRGN -->\n";
1720 break;
1721 case EMR_BITBLT:
1722 dbg_str << "<!-- EMR_BITBLT -->\n";
1723 break;
1724 case EMR_STRETCHBLT:
1725 dbg_str << "<!-- EMR_STRETCHBLT -->\n";
1726 break;
1727 case EMR_MASKBLT:
1728 dbg_str << "<!-- EMR_MASKBLT -->\n";
1729 break;
1730 case EMR_PLGBLT:
1731 dbg_str << "<!-- EMR_PLGBLT -->\n";
1732 break;
1733 case EMR_SETDIBITSTODEVICE:
1734 dbg_str << "<!-- EMR_SETDIBITSTODEVICE -->\n";
1735 break;
1736 case EMR_STRETCHDIBITS:
1737 dbg_str << "<!-- EMR_STRETCHDIBITS -->\n";
1738 break;
1739 case EMR_EXTCREATEFONTINDIRECTW:
1740 {
1741 dbg_str << "<!-- EMR_EXTCREATEFONTINDIRECTW -->\n";
1743 PEMREXTCREATEFONTINDIRECTW pEmr = (PEMREXTCREATEFONTINDIRECTW) lpEMFR;
1744 int index = pEmr->ihFont;
1746 EMREXTCREATEFONTINDIRECTW *pFont =
1747 (EMREXTCREATEFONTINDIRECTW *) malloc( sizeof(EMREXTCREATEFONTINDIRECTW) );
1748 pFont->elfw = pEmr->elfw;
1749 insert_object(d, index, EMR_EXTCREATEFONTINDIRECTW, (ENHMETARECORD *) pFont);
1750 break;
1751 }
1752 case EMR_EXTTEXTOUTA:
1753 {
1754 dbg_str << "<!-- EMR_EXTTEXTOUTA -->\n";
1755 break;
1756 }
1757 case EMR_EXTTEXTOUTW:
1758 {
1759 dbg_str << "<!-- EMR_EXTTEXTOUTW -->\n";
1761 PEMREXTTEXTOUTW pEmr = (PEMREXTTEXTOUTW) lpEMFR;
1763 double x1 = pEmr->emrtext.ptlReference.x;
1764 double y1 = pEmr->emrtext.ptlReference.y;
1766 if (d->dc[d->level].textAlign & TA_UPDATECP) {
1767 x1 = d->dc[d->level].cur.x;
1768 y1 = d->dc[d->level].cur.y;
1769 }
1771 if (!(d->dc[d->level].textAlign & TA_BOTTOM))
1772 y1 += fabs(d->dc[d->level].style.font_size.computed);
1774 double x = pix_to_x_point(d, x1, y1);
1775 double y = pix_to_y_point(d, x1, y1);
1777 wchar_t *wide_text = (wchar_t *) ((char *) pEmr + pEmr->emrtext.offString);
1779 gchar *ansi_text =
1780 (gchar *) g_utf16_to_utf8( (gunichar2 *) wide_text, pEmr->emrtext.nChars, NULL, NULL, NULL );
1782 if (ansi_text) {
1783 gchar *p = ansi_text;
1784 while (*p) {
1785 if (*p < 32 || *p >= 127) {
1786 g_free(ansi_text);
1787 ansi_text = g_strdup("");
1788 break;
1789 }
1790 p++;
1791 }
1793 SVGOStringStream ts;
1795 gchar *escaped_text = g_markup_escape_text(ansi_text, -1);
1797 float text_rgb[3];
1798 sp_color_get_rgb_floatv( &(d->dc[d->level].style.fill.value.color), text_rgb );
1800 if (!d->dc[d->level].textColorSet) {
1801 d->dc[d->level].textColor = RGB(SP_COLOR_F_TO_U(text_rgb[0]),
1802 SP_COLOR_F_TO_U(text_rgb[1]),
1803 SP_COLOR_F_TO_U(text_rgb[2]));
1804 }
1806 char tmp[128];
1807 snprintf(tmp, 127,
1808 "fill:#%02x%02x%02x;",
1809 GetRValue(d->dc[d->level].textColor),
1810 GetGValue(d->dc[d->level].textColor),
1811 GetBValue(d->dc[d->level].textColor));
1813 bool i = (d->dc[d->level].style.font_style.value == SP_CSS_FONT_STYLE_ITALIC);
1814 //bool o = (d->dc[d->level].style.font_style.value == SP_CSS_FONT_STYLE_OBLIQUE);
1815 bool b = (d->dc[d->level].style.font_weight.value == SP_CSS_FONT_WEIGHT_BOLD) ||
1816 (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);
1817 int lcr = ((d->dc[d->level].textAlign & TA_CENTER) == TA_CENTER) ? 2 : ((d->dc[d->level].textAlign & TA_RIGHT) == TA_RIGHT) ? 1 : 0;
1819 assert_empty_path(d, "EMR_EXTTEXTOUTW");
1821 ts << " <text\n";
1822 ts << " id=\"" << (d->id++) << "\"\n";
1823 ts << " xml:space=\"preserve\"\n";
1824 ts << " x=\"" << x << "\"\n";
1825 ts << " y=\"" << y << "\"\n";
1826 if (d->dc[d->level].style.text_transform.value) {
1827 ts << " transform=\""
1828 << "rotate(-" << d->dc[d->level].style.text_transform.value
1829 << " " << x << " " << y << ")"
1830 << "\"\n";
1831 }
1832 ts << " style=\""
1833 << "font-size:" << fabs(d->dc[d->level].style.font_size.computed) << "px;"
1834 << tmp
1835 << "font-style:" << (i ? "italic" : "normal") << ";"
1836 << "font-weight:" << (b ? "bold" : "normal") << ";"
1837 << "text-align:" << (lcr==2 ? "center" : lcr==1 ? "end" : "start") << ";"
1838 << "text-anchor:" << (lcr==2 ? "middle" : lcr==1 ? "end" : "start") << ";"
1839 << "font-family:" << d->dc[d->level].tstyle.font_family.value << ";"
1840 << "\"\n";
1841 ts << " >";
1842 ts << escaped_text;
1843 ts << "</text>\n";
1845 *(d->outsvg) += ts.str().c_str();
1847 g_free(escaped_text);
1848 g_free(ansi_text);
1849 }
1851 break;
1852 }
1853 case EMR_POLYBEZIER16:
1854 {
1855 dbg_str << "<!-- EMR_POLYBEZIER16 -->\n";
1857 PEMRPOLYBEZIER16 pEmr = (PEMRPOLYBEZIER16) lpEMFR;
1858 POINTS *apts = (POINTS *) pEmr->apts; // Bug in MinGW wingdi.h ?
1859 DWORD i,j;
1861 if (pEmr->cpts<4)
1862 break;
1864 if (!d->inpath) {
1865 assert_empty_path(d, "EMR_POLYBEZIER16");
1867 *(d->outsvg) += " <path ";
1868 output_style(d, EMR_STROKEPATH);
1869 *(d->outsvg) += "\n\td=\"";
1870 }
1872 tmp_str <<
1873 "\n\tM " <<
1874 pix_to_x_point( d, apts[0].x, apts[0].y ) << " " <<
1875 pix_to_y_point( d, apts[0].x, apts[0].y ) << " ";
1877 for (i=1; i<pEmr->cpts; ) {
1878 tmp_str << "\n\tC ";
1879 for (j=0; j<3 && i<pEmr->cpts; j++,i++) {
1880 tmp_str <<
1881 pix_to_x_point( d, apts[i].x, apts[i].y ) << " " <<
1882 pix_to_y_point( d, apts[i].x, apts[i].y ) << " ";
1883 }
1884 }
1886 if (d->inpath) {
1887 tmp_path << tmp_str.str().c_str();
1888 }
1889 else {
1890 *(d->outsvg) += tmp_str.str().c_str();
1891 *(d->outsvg) += " \" /> \n";
1892 }
1894 break;
1895 }
1896 case EMR_POLYGON16:
1897 {
1898 dbg_str << "<!-- EMR_POLYGON16 -->\n";
1900 PEMRPOLYGON16 pEmr = (PEMRPOLYGON16) lpEMFR;
1901 POINTS *apts = (POINTS *) pEmr->apts; // Bug in MinGW wingdi.h ?
1902 SVGOStringStream tmp_poly;
1903 unsigned int i;
1904 unsigned int first = 0;
1906 assert_empty_path(d, "EMR_POLYGON16");
1908 *(d->outsvg) += " <path ";
1909 output_style(d, EMR_STROKEANDFILLPATH);
1910 *(d->outsvg) += "\n\td=\"";
1912 // skip the first point?
1913 tmp_poly << "\n\tM " <<
1914 pix_to_x_point( d, apts[first].x, apts[first].y ) << " " <<
1915 pix_to_y_point( d, apts[first].x, apts[first].y ) << " ";
1917 for (i=first+1; i<pEmr->cpts; i++) {
1918 tmp_poly << "\n\tL " <<
1919 pix_to_x_point( d, apts[i].x, apts[i].y ) << " " <<
1920 pix_to_y_point( d, apts[i].x, apts[i].y ) << " ";
1921 }
1923 *(d->outsvg) += tmp_poly.str().c_str();
1924 *(d->outsvg) += " z \" /> \n";
1926 break;
1927 }
1928 case EMR_POLYLINE16:
1929 {
1930 dbg_str << "<!-- EMR_POLYLINE16 -->\n";
1932 EMRPOLYLINE16 *pEmr = (EMRPOLYLINE16 *) lpEMFR;
1933 POINTS *apts = (POINTS *) pEmr->apts; // Bug in MinGW wingdi.h ?
1934 DWORD i;
1936 if (pEmr->cpts<2)
1937 break;
1939 if (!d->inpath) {
1940 assert_empty_path(d, "EMR_POLYLINE16");
1942 *(d->outsvg) += " <path ";
1943 output_style(d, EMR_STROKEPATH);
1944 *(d->outsvg) += "\n\td=\"";
1945 }
1947 tmp_str <<
1948 "\n\tM " <<
1949 pix_to_x_point( d, apts[0].x, apts[0].y ) << " " <<
1950 pix_to_y_point( d, apts[0].x, apts[0].y ) << " ";
1952 for (i=1; i<pEmr->cpts; i++) {
1953 tmp_str <<
1954 "\n\tL " <<
1955 pix_to_x_point( d, apts[i].x, apts[i].y ) << " " <<
1956 pix_to_y_point( d, apts[i].x, apts[i].y ) << " ";
1957 }
1959 if (d->inpath) {
1960 tmp_path << tmp_str.str().c_str();
1961 }
1962 else {
1963 *(d->outsvg) += tmp_str.str().c_str();
1964 *(d->outsvg) += " \" /> \n";
1965 }
1967 break;
1968 }
1969 case EMR_POLYBEZIERTO16:
1970 {
1971 dbg_str << "<!-- EMR_POLYBEZIERTO16 -->\n";
1973 PEMRPOLYBEZIERTO16 pEmr = (PEMRPOLYBEZIERTO16) lpEMFR;
1974 POINTS *apts = (POINTS *) pEmr->apts; // Bug in MinGW wingdi.h ?
1975 DWORD i,j;
1977 if (d->path->empty()) {
1978 d->pathless_stroke = true;
1979 *(d->path) = "d=\"";
1980 }
1982 for (i=0; i<pEmr->cpts;) {
1983 tmp_path << "\n\tC ";
1984 for (j=0; j<3 && i<pEmr->cpts; j++,i++) {
1985 tmp_path <<
1986 pix_to_x_point( d, apts[i].x, apts[i].y ) << " " <<
1987 pix_to_y_point( d, apts[i].x, apts[i].y ) << " ";
1988 }
1989 }
1991 break;
1992 }
1993 case EMR_POLYLINETO16:
1994 {
1995 dbg_str << "<!-- EMR_POLYLINETO16 -->\n";
1997 PEMRPOLYLINETO16 pEmr = (PEMRPOLYLINETO16) lpEMFR;
1998 POINTS *apts = (POINTS *) pEmr->apts; // Bug in MinGW wingdi.h ?
1999 DWORD i;
2001 if (d->path->empty()) {
2002 d->pathless_stroke = true;
2003 *(d->path) = "d=\"";
2004 }
2006 for (i=0; i<pEmr->cpts;i++) {
2007 tmp_path <<
2008 "\n\tL " <<
2009 pix_to_x_point( d, apts[i].x, apts[i].y ) << " " <<
2010 pix_to_y_point( d, apts[i].x, apts[i].y ) << " ";
2011 }
2013 break;
2014 }
2015 case EMR_POLYPOLYLINE16:
2016 case EMR_POLYPOLYGON16:
2017 {
2018 if (lpEMFR->iType == EMR_POLYPOLYLINE16)
2019 dbg_str << "<!-- EMR_POLYPOLYLINE16 -->\n";
2020 if (lpEMFR->iType == EMR_POLYPOLYGON16)
2021 dbg_str << "<!-- EMR_POLYPOLYGON16 -->\n";
2023 PEMRPOLYPOLYGON16 pEmr = (PEMRPOLYPOLYGON16) lpEMFR;
2024 unsigned int n, i, j;
2026 if (!d->inpath) {
2027 assert_empty_path(d, lpEMFR->iType == EMR_POLYPOLYGON16 ? "EMR_POLYPOLYGON16" : "EMR_POLYPOLYLINE16");
2029 *(d->outsvg) += " <path ";
2030 output_style(d, lpEMFR->iType==EMR_POLYPOLYGON16 ? EMR_STROKEANDFILLPATH : EMR_STROKEPATH);
2031 *(d->outsvg) += "\n\td=\"";
2032 }
2034 POINTS *apts = (POINTS *) &pEmr->aPolyCounts[pEmr->nPolys];
2036 i = 0;
2037 for (n=0; n<pEmr->nPolys && i<pEmr->cpts; n++) {
2038 SVGOStringStream poly_path;
2040 poly_path << "\n\tM " <<
2041 pix_to_x_point( d, apts[i].x, apts[i].y ) << " " <<
2042 pix_to_y_point( d, apts[i].x, apts[i].y ) << " ";
2043 i++;
2045 for (j=1; j<pEmr->aPolyCounts[n] && i<pEmr->cpts; j++) {
2046 poly_path << "\n\tL " <<
2047 pix_to_x_point( d, apts[i].x, apts[i].y ) << " " <<
2048 pix_to_y_point( d, apts[i].x, apts[i].y ) << " ";
2049 i++;
2050 }
2052 tmp_str << poly_path.str().c_str();
2053 if (lpEMFR->iType == EMR_POLYPOLYGON16)
2054 tmp_str << " z";
2055 tmp_str << " \n";
2056 }
2058 if (d->inpath) {
2059 tmp_path << tmp_str.str().c_str();
2060 }
2061 else {
2062 *(d->outsvg) += tmp_str.str().c_str();
2063 *(d->outsvg) += " \" /> \n";
2064 }
2066 break;
2067 }
2068 case EMR_POLYDRAW16:
2069 dbg_str << "<!-- EMR_POLYDRAW16 -->\n";
2070 break;
2071 case EMR_CREATEMONOBRUSH:
2072 dbg_str << "<!-- EMR_CREATEMONOBRUSH -->\n";
2073 break;
2074 case EMR_CREATEDIBPATTERNBRUSHPT:
2075 dbg_str << "<!-- EMR_CREATEDIBPATTERNBRUSHPT -->\n";
2076 break;
2077 case EMR_EXTCREATEPEN:
2078 {
2079 dbg_str << "<!-- EMR_EXTCREATEPEN -->\n";
2081 PEMREXTCREATEPEN pEmr = (PEMREXTCREATEPEN) lpEMFR;
2082 int index = pEmr->ihPen;
2084 EMREXTCREATEPEN *pPen =
2085 (EMREXTCREATEPEN *) malloc( sizeof(EMREXTCREATEPEN) +
2086 sizeof(DWORD) * pEmr->elp.elpNumEntries );
2087 pPen->ihPen = pEmr->ihPen;
2088 pPen->offBmi = pEmr->offBmi;
2089 pPen->cbBmi = pEmr->cbBmi;
2090 pPen->offBits = pEmr->offBits;
2091 pPen->cbBits = pEmr->cbBits;
2092 pPen->elp = pEmr->elp;
2093 for (unsigned int i=0; i<pEmr->elp.elpNumEntries; i++) {
2094 pPen->elp.elpStyleEntry[i] = pEmr->elp.elpStyleEntry[i];
2095 }
2096 insert_object(d, index, EMR_EXTCREATEPEN, (ENHMETARECORD *) pPen);
2098 break;
2099 }
2100 case EMR_POLYTEXTOUTA:
2101 dbg_str << "<!-- EMR_POLYTEXTOUTA -->\n";
2102 break;
2103 case EMR_POLYTEXTOUTW:
2104 dbg_str << "<!-- EMR_POLYTEXTOUTW -->\n";
2105 break;
2106 case EMR_SETICMMODE:
2107 dbg_str << "<!-- EMR_SETICMMODE -->\n";
2108 break;
2109 case EMR_CREATECOLORSPACE:
2110 dbg_str << "<!-- EMR_CREATECOLORSPACE -->\n";
2111 break;
2112 case EMR_SETCOLORSPACE:
2113 dbg_str << "<!-- EMR_SETCOLORSPACE -->\n";
2114 break;
2115 case EMR_DELETECOLORSPACE:
2116 dbg_str << "<!-- EMR_DELETECOLORSPACE -->\n";
2117 break;
2118 case EMR_GLSRECORD:
2119 dbg_str << "<!-- EMR_GLSRECORD -->\n";
2120 break;
2121 case EMR_GLSBOUNDEDRECORD:
2122 dbg_str << "<!-- EMR_GLSBOUNDEDRECORD -->\n";
2123 break;
2124 case EMR_PIXELFORMAT:
2125 dbg_str << "<!-- EMR_PIXELFORMAT -->\n";
2126 break;
2127 default:
2128 dbg_str << "<!-- EMR_??? -->\n";
2129 break;
2130 }
2132 // *(d->outsvg) += dbg_str.str().c_str();
2133 *(d->outsvg) += tmp_outsvg.str().c_str();
2134 *(d->path) += tmp_path.str().c_str();
2136 return 1;
2137 }
2139 static int CALLBACK
2140 myMetaFileProc(HDC /*hDC*/, HANDLETABLE * /*lpHTable*/, METARECORD * /*lpMFR*/, int /*nObj*/, LPARAM /*lpData*/)
2141 {
2142 g_warning("Unable to import Windows Meta File.\n");
2143 return 0;
2144 }
2146 // Aldus Placeable Header ===================================================
2147 // Since we are a 32bit app, we have to be sure this structure compiles to
2148 // be identical to a 16 bit app's version. To do this, we use the #pragma
2149 // to adjust packing, we use a WORD for the hmf handle, and a SMALL_RECT
2150 // for the bbox rectangle.
2151 #pragma pack( push )
2152 #pragma pack( 2 )
2153 typedef struct
2154 {
2155 DWORD dwKey;
2156 WORD hmf;
2157 SMALL_RECT bbox;
2158 WORD wInch;
2159 DWORD dwReserved;
2160 WORD wCheckSum;
2161 } APMHEADER, *PAPMHEADER;
2162 #pragma pack( pop )
2165 SPDocument *
2166 EmfWin32::open( Inkscape::Extension::Input * /*mod*/, const gchar *uri )
2167 {
2168 EMF_CALLBACK_DATA d;
2170 memset(&d, 0, sizeof(d));
2172 d.dc[0].worldTransform.eM11 = 1.0;
2173 d.dc[0].worldTransform.eM12 = 0.0;
2174 d.dc[0].worldTransform.eM21 = 0.0;
2175 d.dc[0].worldTransform.eM22 = 1.0;
2176 d.dc[0].worldTransform.eDx = 0.0;
2177 d.dc[0].worldTransform.eDy = 0.0;
2179 gsize bytesRead = 0;
2180 gsize bytesWritten = 0;
2181 GError* error = NULL;
2182 gchar *local_fn =
2183 g_filename_from_utf8( uri, -1, &bytesRead, &bytesWritten, &error );
2185 if (local_fn == NULL) {
2186 return NULL;
2187 }
2189 d.outsvg = new Glib::ustring("");
2190 d.path = new Glib::ustring("");
2192 CHAR *ansi_uri = (CHAR *) local_fn;
2193 gunichar2 *unicode_fn = g_utf8_to_utf16( local_fn, -1, NULL, NULL, NULL );
2194 WCHAR *unicode_uri = (WCHAR *) unicode_fn;
2196 DWORD filesize = 0;
2197 HANDLE fp = NULL;
2199 HMETAFILE hmf;
2200 HENHMETAFILE hemf;
2202 if (PrintWin32::is_os_wide()) {
2203 fp = CreateFileW(unicode_uri, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
2204 }
2205 else {
2206 fp = CreateFileA(ansi_uri, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
2207 }
2209 if ( fp != INVALID_HANDLE_VALUE ) {
2210 filesize = GetFileSize(fp, NULL);
2211 CloseHandle(fp);
2212 }
2214 // Try open as Enhanced Metafile
2215 if (PrintWin32::is_os_wide())
2216 hemf = GetEnhMetaFileW(unicode_uri);
2217 else
2218 hemf = GetEnhMetaFileA(ansi_uri);
2220 if (!hemf) {
2221 // Try open as Windows Metafile
2222 if (PrintWin32::is_os_wide())
2223 hmf = GetMetaFileW(unicode_uri);
2224 else
2225 hmf = GetMetaFileA(ansi_uri);
2227 METAFILEPICT mp;
2228 HDC hDC;
2230 if (!hmf) {
2231 if (PrintWin32::is_os_wide()) {
2232 WCHAR szTemp[MAX_PATH];
2234 DWORD dw = GetShortPathNameW( unicode_uri, szTemp, MAX_PATH );
2235 if (dw) {
2236 hmf = GetMetaFileW( szTemp );
2237 }
2238 } else {
2239 CHAR szTemp[MAX_PATH];
2241 DWORD dw = GetShortPathNameA( ansi_uri, szTemp, MAX_PATH );
2242 if (dw) {
2243 hmf = GetMetaFileA( szTemp );
2244 }
2245 }
2246 }
2248 if (hmf) {
2249 DWORD nSize = GetMetaFileBitsEx( hmf, 0, NULL );
2251 if (!nSize)
2252 nSize = filesize;
2254 if (nSize) {
2255 BYTE *lpvData = new BYTE[nSize];
2256 if (lpvData) {
2257 DWORD dw = GetMetaFileBitsEx( hmf, nSize, lpvData );
2258 if (dw) {
2259 // Fill out a METAFILEPICT structure
2260 mp.mm = MM_ANISOTROPIC;
2261 mp.xExt = 1000;
2262 mp.yExt = 1000;
2263 mp.hMF = NULL;
2264 // Get a reference DC
2265 hDC = GetDC( NULL );
2266 // Make an enhanced metafile from the windows metafile
2267 hemf = SetWinMetaFileBits( nSize, lpvData, hDC, &mp );
2268 // Clean up
2269 ReleaseDC( NULL, hDC );
2270 DeleteMetaFile( hmf );
2271 hmf = NULL;
2272 }
2273 else {
2274 // EnumMetaFile
2275 }
2276 delete[] lpvData;
2277 }
2278 else {
2279 DeleteMetaFile( hmf );
2280 hmf = NULL;
2281 }
2282 }
2283 else {
2284 DeleteMetaFile( hmf );
2285 hmf = NULL;
2286 }
2287 }
2288 else {
2289 // Try open as Aldus Placeable Metafile
2290 HANDLE hFile;
2291 if (PrintWin32::is_os_wide())
2292 hFile = CreateFileW( unicode_uri, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
2293 else
2294 hFile = CreateFileA( ansi_uri, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
2296 if (hFile != INVALID_HANDLE_VALUE) {
2297 DWORD nSize = GetFileSize( hFile, NULL );
2298 if (nSize) {
2299 BYTE *lpvData = new BYTE[nSize];
2300 if (lpvData) {
2301 DWORD dw = ReadFile( hFile, lpvData, nSize, &nSize, NULL );
2302 if (dw) {
2303 if ( ((PAPMHEADER)lpvData)->dwKey == 0x9ac6cdd7l ) {
2304 // Fill out a METAFILEPICT structure
2305 mp.mm = MM_ANISOTROPIC;
2306 mp.xExt = ((PAPMHEADER)lpvData)->bbox.Right - ((PAPMHEADER)lpvData)->bbox.Left;
2307 mp.xExt = ( mp.xExt * 2540l ) / (DWORD)(((PAPMHEADER)lpvData)->wInch);
2308 mp.yExt = ((PAPMHEADER)lpvData)->bbox.Bottom - ((PAPMHEADER)lpvData)->bbox.Top;
2309 mp.yExt = ( mp.yExt * 2540l ) / (DWORD)(((PAPMHEADER)lpvData)->wInch);
2310 mp.hMF = NULL;
2311 // Get a reference DC
2312 hDC = GetDC( NULL );
2313 // Create an enhanced metafile from the bits
2314 hemf = SetWinMetaFileBits( nSize, lpvData+sizeof(APMHEADER), hDC, &mp );
2315 // Clean up
2316 ReleaseDC( NULL, hDC );
2317 }
2318 }
2319 delete[] lpvData;
2320 }
2321 }
2322 CloseHandle( hFile );
2323 }
2324 }
2325 }
2327 if ((!hemf && !hmf) || !d.outsvg || !d.path) {
2328 if (d.outsvg)
2329 delete d.outsvg;
2330 if (d.path)
2331 delete d.path;
2332 if (local_fn)
2333 g_free(local_fn);
2334 if (unicode_fn)
2335 g_free(unicode_fn);
2336 if (hemf)
2337 DeleteEnhMetaFile(hemf);
2338 if (hmf)
2339 DeleteMetaFile(hmf);
2340 return NULL;
2341 }
2343 d.pDesc = NULL;
2345 if (hemf) {
2346 DWORD dwNeeded = GetEnhMetaFileDescriptionA( hemf, 0, NULL );
2347 if ( dwNeeded > 0 ) {
2348 d.pDesc = (CHAR *) malloc( dwNeeded + 1 );
2349 if ( GetEnhMetaFileDescription( hemf, dwNeeded, d.pDesc ) == 0 )
2350 lstrcpy( d.pDesc, "" );
2351 if ( lstrlen( d.pDesc ) > 1 )
2352 d.pDesc[lstrlen(d.pDesc)] = '#';
2353 }
2355 EnumEnhMetaFile(NULL, hemf, myEnhMetaFileProc, (LPVOID) &d, NULL);
2356 DeleteEnhMetaFile(hemf);
2357 }
2358 else {
2359 EnumMetaFile(NULL, hmf, myMetaFileProc, (LPARAM) &d);
2360 DeleteMetaFile(hmf);
2361 }
2363 if (d.pDesc)
2364 free( d.pDesc );
2366 // std::cout << "SVG Output: " << std::endl << *(d.outsvg) << std::endl;
2368 SPDocument *doc = sp_document_new_from_mem(d.outsvg->c_str(), d.outsvg->length(), TRUE);
2370 delete d.outsvg;
2371 delete d.path;
2373 if (d.emf_obj) {
2374 int i;
2375 for (i=0; i<d.n_obj; i++)
2376 delete_object(&d, i);
2377 delete[] d.emf_obj;
2378 }
2380 if (d.dc[0].style.stroke_dash.dash)
2381 delete[] d.dc[0].style.stroke_dash.dash;
2383 if (local_fn)
2384 g_free(local_fn);
2385 if (unicode_fn)
2386 g_free(unicode_fn);
2388 return doc;
2389 }
2392 void
2393 EmfWin32::init (void)
2394 {
2395 Inkscape::Extension::Extension * ext;
2397 /* EMF in */
2398 ext = Inkscape::Extension::build_from_mem(
2399 "<inkscape-extension xmlns=\"" INKSCAPE_EXTENSION_URI "\">\n"
2400 "<name>" N_("EMF Input") "</name>\n"
2401 "<id>org.inkscape.input.emf.win32</id>\n"
2402 "<input>\n"
2403 "<extension>.emf</extension>\n"
2404 "<mimetype>image/x-emf</mimetype>\n"
2405 "<filetypename>" N_("Enhanced Metafiles (*.emf)") "</filetypename>\n"
2406 "<filetypetooltip>" N_("Enhanced Metafiles") "</filetypetooltip>\n"
2407 "<output_extension>org.inkscape.output.emf.win32</output_extension>\n"
2408 "</input>\n"
2409 "</inkscape-extension>", new EmfWin32());
2411 /* WMF in */
2412 ext = Inkscape::Extension::build_from_mem(
2413 "<inkscape-extension xmlns=\"" INKSCAPE_EXTENSION_URI "\">\n"
2414 "<name>" N_("WMF Input") "</name>\n"
2415 "<id>org.inkscape.input.wmf.win32</id>\n"
2416 "<input>\n"
2417 "<extension>.wmf</extension>\n"
2418 "<mimetype>image/x-wmf</mimetype>\n"
2419 "<filetypename>" N_("Windows Metafiles (*.wmf)") "</filetypename>\n"
2420 "<filetypetooltip>" N_("Windows Metafiles") "</filetypetooltip>\n"
2421 "<output_extension>org.inkscape.output.emf.win32</output_extension>\n"
2422 "</input>\n"
2423 "</inkscape-extension>", new EmfWin32());
2425 /* EMF out */
2426 ext = Inkscape::Extension::build_from_mem(
2427 "<inkscape-extension xmlns=\"" INKSCAPE_EXTENSION_URI "\">\n"
2428 "<name>" N_("EMF Output") "</name>\n"
2429 "<id>org.inkscape.output.emf.win32</id>\n"
2430 "<param name=\"textToPath\" gui-text=\"" N_("Convert texts to paths") "\" type=\"boolean\">true</param>\n"
2431 "<output>\n"
2432 "<extension>.emf</extension>\n"
2433 "<mimetype>image/x-emf</mimetype>\n"
2434 "<filetypename>" N_("Enhanced Metafile (*.emf)") "</filetypename>\n"
2435 "<filetypetooltip>" N_("Enhanced Metafile") "</filetypetooltip>\n"
2436 "</output>\n"
2437 "</inkscape-extension>", new EmfWin32());
2439 return;
2440 }
2443 } } } /* namespace Inkscape, Extension, Implementation */
2445 #endif /* WIN32 */
2446 /*
2447 Local Variables:
2448 mode:c++
2449 c-file-style:"stroustrup"
2450 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
2451 indent-tabs-mode:nil
2452 fill-column:99
2453 End:
2454 */
2455 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :