1 /** \file\r
2 * Enhanced Metafile Input and Output.\r
3 */\r
4 /*\r
5 * Authors:\r
6 * Ulf Erikson <ulferikson@users.sf.net>\r
7 *\r
8 * Copyright (C) 2006 Authors\r
9 *\r
10 * Released under GNU GPL, read the file 'COPYING' for more information\r
11 */\r
12 /*\r
13 * References:\r
14 * - How to Create & Play Enhanced Metafiles in Win32\r
15 * http://support.microsoft.com/kb/q145999/\r
16 * - INFO: Windows Metafile Functions & Aldus Placeable Metafiles\r
17 * http://support.microsoft.com/kb/q66949/\r
18 * - Metafile Functions\r
19 * http://msdn.microsoft.com/library/en-us/gdi/metafile_0whf.asp\r
20 * - Metafile Structures\r
21 * http://msdn.microsoft.com/library/en-us/gdi/metafile_5hkj.asp\r
22 */\r
23 \r
24 #ifdef WIN32\r
25 \r
26 #ifdef HAVE_CONFIG_H\r
27 # include "config.h"\r
28 #endif\r
29 \r
30 #include "win32.h"\r
31 #include "emf-win32-print.h"\r
32 #include "emf-win32-inout.h"\r
33 #include "inkscape.h"\r
34 #include "sp-path.h"\r
35 #include "style.h"\r
36 #include "color.h"\r
37 #include "display/curve.h"\r
38 #include "libnr/n-art-bpath.h"\r
39 #include "libnr/nr-point-matrix-ops.h"\r
40 #include "gtk/gtk.h"\r
41 #include "print.h"\r
42 #include "glibmm/i18n.h"\r
43 #include "extension/extension.h"\r
44 #include "extension/system.h"\r
45 #include "extension/print.h"\r
46 #include "extension/db.h"\r
47 #include "extension/output.h"\r
48 #include "document.h"\r
49 #include "display/nr-arena.h"\r
50 #include "display/nr-arena-item.h"\r
51 \r
52 #include "libnr/nr-rect.h"\r
53 #include "libnr/nr-matrix.h"\r
54 #include "libnr/nr-pixblock.h"\r
55 \r
56 #include <stdio.h>\r
57 #include <string.h>\r
58 \r
59 #include <vector>\r
60 #include <string>\r
61 \r
62 #include "io/sys.h"\r
63 \r
64 #include "unit-constants.h"\r
65 \r
66 #include "clear-n_.h"\r
67 \r
68 \r
69 #define PRINT_EMF_WIN32 "org.inkscape.print.emf.win32"\r
70 \r
71 #ifndef PS_JOIN_MASK\r
72 #define PS_JOIN_MASK (PS_JOIN_BEVEL|PS_JOIN_MITER|PS_JOIN_ROUND)\r
73 #endif\r
74 \r
75 \r
76 namespace Inkscape {\r
77 namespace Extension {\r
78 namespace Internal {\r
79 \r
80 \r
81 EmfWin32::EmfWin32 (void) // The null constructor\r
82 {\r
83 return;\r
84 }\r
85 \r
86 \r
87 EmfWin32::~EmfWin32 (void) //The destructor\r
88 {\r
89 return;\r
90 }\r
91 \r
92 \r
93 bool\r
94 EmfWin32::check (Inkscape::Extension::Extension * module)\r
95 {\r
96 if (NULL == Inkscape::Extension::db.get(PRINT_EMF_WIN32))\r
97 return FALSE;\r
98 return TRUE;\r
99 }\r
100 \r
101 \r
102 static void\r
103 emf_print_document_to_file(SPDocument *doc, gchar const *filename)\r
104 {\r
105 Inkscape::Extension::Print *mod;\r
106 SPPrintContext context;\r
107 gchar const *oldconst;\r
108 gchar *oldoutput;\r
109 unsigned int ret;\r
110 \r
111 sp_document_ensure_up_to_date(doc);\r
112 \r
113 mod = Inkscape::Extension::get_print(PRINT_EMF_WIN32);\r
114 oldconst = mod->get_param_string("destination");\r
115 oldoutput = g_strdup(oldconst);\r
116 mod->set_param_string("destination", (gchar *)filename);\r
117 \r
118 /* Start */\r
119 context.module = mod;\r
120 /* fixme: This has to go into module constructor somehow */\r
121 /* Create new arena */\r
122 mod->base = SP_ITEM(sp_document_root(doc));\r
123 mod->arena = NRArena::create();\r
124 mod->dkey = sp_item_display_key_new(1);\r
125 mod->root = sp_item_invoke_show(mod->base, mod->arena, mod->dkey, SP_ITEM_SHOW_DISPLAY);\r
126 /* Print document */\r
127 ret = mod->begin(doc);\r
128 if (ret) {\r
129 throw Inkscape::Extension::Output::save_failed();\r
130 }\r
131 sp_item_invoke_print(mod->base, &context);\r
132 ret = mod->finish();\r
133 /* Release arena */\r
134 sp_item_invoke_hide(mod->base, mod->dkey);\r
135 mod->base = NULL;\r
136 nr_arena_item_unref(mod->root);\r
137 mod->root = NULL;\r
138 nr_object_unref((NRObject *) mod->arena);\r
139 mod->arena = NULL;\r
140 /* end */\r
141 \r
142 mod->set_param_string("destination", oldoutput);\r
143 g_free(oldoutput);\r
144 \r
145 return;\r
146 }\r
147 \r
148 \r
149 void\r
150 EmfWin32::save (Inkscape::Extension::Output *mod, SPDocument *doc, const gchar *uri)\r
151 {\r
152 Inkscape::Extension::Extension * ext;\r
153 \r
154 ext = Inkscape::Extension::db.get(PRINT_EMF_WIN32);\r
155 if (ext == NULL)\r
156 return;\r
157 \r
158 // bool old_textToPath = ext->get_param_bool("textToPath");\r
159 // bool new_val = mod->get_param_bool("textToPath");\r
160 // ext->set_param_bool("textToPath", new_val);\r
161 \r
162 gchar * final_name;\r
163 final_name = g_strdup_printf("%s", uri);\r
164 emf_print_document_to_file(doc, final_name);\r
165 g_free(final_name);\r
166 \r
167 // ext->set_param_bool("textToPath", old_textToPath);\r
168 \r
169 return;\r
170 }\r
171 \r
172 \r
173 \r
174 typedef struct {\r
175 int type;\r
176 ENHMETARECORD *lpEMFR;\r
177 } EMF_OBJECT, *PEMF_OBJECT;\r
178 \r
179 typedef struct emf_callback_data {\r
180 Glib::ustring *outsvg;\r
181 Glib::ustring *path;\r
182 struct SPStyle style;\r
183 bool stroke_set;\r
184 bool fill_set;\r
185 double xDPI, yDPI;\r
186 \r
187 SIZEL sizeWnd;\r
188 SIZEL sizeView;\r
189 float PixelsX;\r
190 float PixelsY;\r
191 float MMX;\r
192 float MMY;\r
193 float dwInchesX;\r
194 float dwInchesY;\r
195 POINTL winorg;\r
196 POINTL vieworg;\r
197 double ScaleX, ScaleY;\r
198 \r
199 int n_obj;\r
200 PEMF_OBJECT emf_obj;\r
201 } EMF_CALLBACK_DATA, *PEMF_CALLBACK_DATA;\r
202 \r
203 \r
204 static void\r
205 output_style(PEMF_CALLBACK_DATA d, int iType)\r
206 {\r
207 SVGOStringStream tmp_style;\r
208 char tmp[1024] = {0};\r
209 \r
210 *(d->outsvg) += "\n\tstyle=\"";\r
211 if (iType == EMR_STROKEPATH || !d->fill_set) {\r
212 tmp_style << "fill:none;";\r
213 } else {\r
214 float rgb[3];\r
215 sp_color_get_rgb_floatv( &(d->style.fill.value.color), rgb );\r
216 snprintf(tmp, 1023,\r
217 "fill:#%02x%02x%02x;",\r
218 SP_COLOR_F_TO_U(rgb[0]),\r
219 SP_COLOR_F_TO_U(rgb[1]),\r
220 SP_COLOR_F_TO_U(rgb[2]));\r
221 tmp_style << tmp;\r
222 snprintf(tmp, 1023,\r
223 "fill-rule:%s;",\r
224 d->style.fill_rule.value != 0 ? "evenodd" : "nonzero");\r
225 tmp_style << tmp;\r
226 tmp_style << "fill-opacity:1;";\r
227 }\r
228 \r
229 if (iType == EMR_FILLPATH || !d->stroke_set) {\r
230 tmp_style << "stroke:none;";\r
231 } else {\r
232 float rgb[3];\r
233 sp_color_get_rgb_floatv(&(d->style.stroke.value.color), rgb);\r
234 snprintf(tmp, 1023,\r
235 "stroke:#%02x%02x%02x;",\r
236 SP_COLOR_F_TO_U(rgb[0]),\r
237 SP_COLOR_F_TO_U(rgb[1]),\r
238 SP_COLOR_F_TO_U(rgb[2]));\r
239 tmp_style << tmp;\r
240 \r
241 tmp_style << "stroke-width:" <<\r
242 MAX( 0.001, d->style.stroke_width.value ) << "px;";\r
243 \r
244 tmp_style << "stroke-linejoin:" <<\r
245 (d->style.stroke_linejoin.computed == 0 ? "miter" :\r
246 d->style.stroke_linejoin.computed == 1 ? "round" :\r
247 d->style.stroke_linejoin.computed == 2 ? "bevel" :\r
248 "unknown") << ";";\r
249 \r
250 if (d->style.stroke_linejoin.computed == 0) {\r
251 tmp_style << "stroke-miterlimit:" <<\r
252 MAX( 0.01, d->style.stroke_miterlimit.value ) << ";";\r
253 }\r
254 \r
255 if (d->style.stroke_dasharray_set &&\r
256 d->style.stroke_dash.n_dash && d->style.stroke_dash.dash)\r
257 {\r
258 tmp_style << "stroke-dasharray:";\r
259 for (int i=0; i<d->style.stroke_dash.n_dash; i++) {\r
260 if (i)\r
261 tmp_style << ",";\r
262 tmp_style << d->style.stroke_dash.dash[i];\r
263 }\r
264 tmp_style << ";";\r
265 tmp_style << "stroke-dashoffset:0;";\r
266 } else {\r
267 tmp_style << "stroke-dasharray:none;";\r
268 }\r
269 tmp_style << "stroke-opacity:1;";\r
270 }\r
271 tmp_style << "\" ";\r
272 \r
273 *(d->outsvg) += tmp_style.str().c_str();\r
274 }\r
275 \r
276 \r
277 static double\r
278 pix_x_to_point(PEMF_CALLBACK_DATA d, double px)\r
279 {\r
280 double tmp = px - d->winorg.x;\r
281 tmp *= (double) PX_PER_IN / d->ScaleX;\r
282 tmp += d->vieworg.x;\r
283 return tmp;\r
284 }\r
285 \r
286 \r
287 static double\r
288 pix_y_to_point(PEMF_CALLBACK_DATA d, double px)\r
289 {\r
290 double tmp = px - d->winorg.y;\r
291 tmp *= (double) PX_PER_IN / d->ScaleY;\r
292 tmp += d->vieworg.y;\r
293 return tmp;\r
294 }\r
295 \r
296 \r
297 static double\r
298 pix_size_to_point(PEMF_CALLBACK_DATA d, double px)\r
299 {\r
300 double tmp = px;\r
301 tmp *= (double) PX_PER_IN / d->ScaleX;\r
302 return tmp;\r
303 }\r
304 \r
305 \r
306 static void\r
307 select_pen(PEMF_CALLBACK_DATA d, int index)\r
308 {\r
309 PEMRCREATEPEN pEmr = NULL;\r
310 \r
311 if (index >= 0 && index < d->n_obj)\r
312 pEmr = (PEMRCREATEPEN) d->emf_obj[index].lpEMFR;\r
313 \r
314 if (!pEmr)\r
315 return;\r
316 \r
317 switch (pEmr->lopn.lopnStyle) {\r
318 default:\r
319 {\r
320 d->style.stroke_dasharray_set = 0;\r
321 break;\r
322 }\r
323 }\r
324 \r
325 if (pEmr->lopn.lopnWidth.x) {\r
326 d->style.stroke_width.value = pix_size_to_point( d, pEmr->lopn.lopnWidth.x );\r
327 } else { // this stroke should always be rendered as 1 pixel wide, independent of zoom level (can that be done in SVG?)\r
328 d->style.stroke_width.value = 1.0;\r
329 }\r
330 \r
331 double r, g, b;\r
332 r = SP_COLOR_U_TO_F( GetRValue(pEmr->lopn.lopnColor) );\r
333 g = SP_COLOR_U_TO_F( GetGValue(pEmr->lopn.lopnColor) );\r
334 b = SP_COLOR_U_TO_F( GetBValue(pEmr->lopn.lopnColor) );\r
335 sp_color_set_rgb_float( &(d->style.stroke.value.color), r,g,b );\r
336 \r
337 d->style.stroke_linejoin.computed = 1;\r
338 \r
339 d->stroke_set = true;\r
340 }\r
341 \r
342 \r
343 static void\r
344 select_extpen(PEMF_CALLBACK_DATA d, int index)\r
345 {\r
346 PEMREXTCREATEPEN pEmr = NULL;\r
347 \r
348 if (index >= 0 && index < d->n_obj)\r
349 pEmr = (PEMREXTCREATEPEN) d->emf_obj[index].lpEMFR;\r
350 \r
351 if (!pEmr)\r
352 return;\r
353 \r
354 switch (pEmr->elp.elpPenStyle & PS_STYLE_MASK) {\r
355 case PS_USERSTYLE:\r
356 {\r
357 if (pEmr->elp.elpNumEntries) {\r
358 d->style.stroke_dash.n_dash = pEmr->elp.elpNumEntries;\r
359 if (d->style.stroke_dash.dash)\r
360 delete[] d->style.stroke_dash.dash;\r
361 d->style.stroke_dash.dash = new double[pEmr->elp.elpNumEntries];\r
362 for (unsigned int i=0; i<pEmr->elp.elpNumEntries; i++) {\r
363 d->style.stroke_dash.dash[i] = pix_size_to_point( d, pEmr->elp.elpStyleEntry[i] );\r
364 }\r
365 d->style.stroke_dasharray_set = 1;\r
366 } else {\r
367 d->style.stroke_dasharray_set = 0;\r
368 }\r
369 break;\r
370 }\r
371 default:\r
372 {\r
373 d->style.stroke_dasharray_set = 0;\r
374 break;\r
375 }\r
376 }\r
377 \r
378 switch (pEmr->elp.elpPenStyle & PS_ENDCAP_MASK) {\r
379 case PS_ENDCAP_ROUND:\r
380 {\r
381 d->style.stroke_linecap.computed = 1;\r
382 break;\r
383 }\r
384 case PS_ENDCAP_SQUARE:\r
385 {\r
386 d->style.stroke_linecap.computed = 2;\r
387 break;\r
388 }\r
389 case PS_ENDCAP_FLAT:\r
390 default:\r
391 {\r
392 d->style.stroke_linecap.computed = 0;\r
393 break;\r
394 }\r
395 }\r
396 \r
397 switch (pEmr->elp.elpPenStyle & PS_JOIN_MASK) {\r
398 case PS_JOIN_BEVEL:\r
399 {\r
400 d->style.stroke_linejoin.computed = 2;\r
401 break;\r
402 }\r
403 case PS_JOIN_MITER:\r
404 {\r
405 d->style.stroke_linejoin.computed = 0;\r
406 break;\r
407 }\r
408 case PS_JOIN_ROUND:\r
409 default:\r
410 {\r
411 d->style.stroke_linejoin.computed = 1;\r
412 break;\r
413 }\r
414 }\r
415 \r
416 d->style.stroke_width.value = pix_size_to_point( d, pEmr->elp.elpWidth );\r
417 \r
418 double r, g, b;\r
419 r = SP_COLOR_U_TO_F( GetRValue(pEmr->elp.elpColor) );\r
420 g = SP_COLOR_U_TO_F( GetGValue(pEmr->elp.elpColor) );\r
421 b = SP_COLOR_U_TO_F( GetBValue(pEmr->elp.elpColor) );\r
422 \r
423 sp_color_set_rgb_float( &(d->style.stroke.value.color), r,g,b );\r
424 \r
425 d->stroke_set = true;\r
426 }\r
427 \r
428 \r
429 static void\r
430 select_brush(PEMF_CALLBACK_DATA d, int index)\r
431 {\r
432 PEMRCREATEBRUSHINDIRECT pEmr = NULL;\r
433 \r
434 if (index >= 0 && index < d->n_obj)\r
435 pEmr = (PEMRCREATEBRUSHINDIRECT) d->emf_obj[index].lpEMFR;\r
436 \r
437 if (!pEmr)\r
438 return;\r
439 \r
440 if (pEmr->lb.lbStyle == BS_SOLID) {\r
441 double r, g, b;\r
442 r = SP_COLOR_U_TO_F( GetRValue(pEmr->lb.lbColor) );\r
443 g = SP_COLOR_U_TO_F( GetGValue(pEmr->lb.lbColor) );\r
444 b = SP_COLOR_U_TO_F( GetBValue(pEmr->lb.lbColor) );\r
445 sp_color_set_rgb_float( &(d->style.fill.value.color), r,g,b );\r
446 }\r
447 \r
448 d->fill_set = true;\r
449 }\r
450 \r
451 \r
452 static void\r
453 delete_object(PEMF_CALLBACK_DATA d, int index)\r
454 {\r
455 if (index >= 0 && index < d->n_obj) {\r
456 d->emf_obj[index].type = 0;\r
457 if (d->emf_obj[index].lpEMFR)\r
458 free(d->emf_obj[index].lpEMFR);\r
459 d->emf_obj[index].lpEMFR = NULL;\r
460 }\r
461 }\r
462 \r
463 \r
464 static void\r
465 insert_object(PEMF_CALLBACK_DATA d, int index, int type, ENHMETARECORD *pObj)\r
466 {\r
467 if (index >= 0 && index < d->n_obj) {\r
468 delete_object(d, index);\r
469 d->emf_obj[index].type = type;\r
470 d->emf_obj[index].lpEMFR = pObj;\r
471 }\r
472 }\r
473 \r
474 \r
475 static int CALLBACK\r
476 myEnhMetaFileProc(HDC hDC, HANDLETABLE *lpHTable, ENHMETARECORD *lpEMFR, int nObj, LPARAM lpData)\r
477 {\r
478 PEMF_CALLBACK_DATA d;\r
479 SVGOStringStream tmp_outsvg;\r
480 SVGOStringStream tmp_path;\r
481 SVGOStringStream tmp_str;\r
482 \r
483 d = (PEMF_CALLBACK_DATA) lpData;\r
484 \r
485 switch (lpEMFR->iType)\r
486 {\r
487 case EMR_HEADER:\r
488 {\r
489 ENHMETAHEADER *pEmr = (ENHMETAHEADER *) lpEMFR;\r
490 tmp_outsvg << "<svg\n";\r
491 \r
492 d->xDPI = 2540;\r
493 d->yDPI = 2540;\r
494 \r
495 d->PixelsX = pEmr->rclFrame.right - pEmr->rclFrame.left;\r
496 d->PixelsY = pEmr->rclFrame.bottom - pEmr->rclFrame.top;\r
497 \r
498 d->MMX = d->PixelsX / 100.0;\r
499 d->MMY = d->PixelsY / 100.0;\r
500 \r
501 tmp_outsvg <<\r
502 " width=\"" << d->MMX << "mm\"\n" <<\r
503 " height=\"" << d->MMY << "mm\">\n";\r
504 \r
505 if (pEmr->nHandles) {\r
506 d->n_obj = pEmr->nHandles;\r
507 d->emf_obj = new EMF_OBJECT[d->n_obj];\r
508 } else {\r
509 d->emf_obj = NULL;\r
510 }\r
511 \r
512 break;\r
513 }\r
514 case EMR_POLYBEZIER:\r
515 {\r
516 PEMRPOLYBEZIER pEmr = (PEMRPOLYBEZIER) lpEMFR;\r
517 DWORD i,j;\r
518 \r
519 if (pEmr->cptl<4)\r
520 break;\r
521 \r
522 *(d->outsvg) += " <path ";\r
523 output_style(d, EMR_STROKEPATH);\r
524 *(d->outsvg) += "\n\td=\"";\r
525 \r
526 tmp_str <<\r
527 "\n\tM " <<\r
528 pix_x_to_point( d, pEmr->aptl[0].x ) << " " <<\r
529 pix_x_to_point( d, pEmr->aptl[0].y) << " ";\r
530 \r
531 for (i=1; i<pEmr->cptl; ) {\r
532 tmp_str << "\n\tC ";\r
533 for (j=0; j<3 && i<pEmr->cptl; j++,i++) {\r
534 tmp_str <<\r
535 pix_x_to_point( d, pEmr->aptl[i].x ) << " " <<\r
536 pix_y_to_point( d, pEmr->aptl[i].y ) << " ";\r
537 }\r
538 }\r
539 \r
540 *(d->outsvg) += tmp_str.str().c_str();\r
541 *(d->outsvg) += " \" /> \n";\r
542 \r
543 break;\r
544 }\r
545 case EMR_POLYGON:\r
546 {\r
547 EMRPOLYGON *pEmr = (EMRPOLYGON *) lpEMFR;\r
548 DWORD i;\r
549 \r
550 if (pEmr->cptl < 2)\r
551 break;\r
552 \r
553 *(d->outsvg) += " <path ";\r
554 output_style(d, EMR_STROKEANDFILLPATH);\r
555 *(d->outsvg) += "\n\td=\"";\r
556 \r
557 tmp_str <<\r
558 "\n\tM " <<\r
559 pix_x_to_point( d, pEmr->aptl[0].x ) << " " <<\r
560 pix_y_to_point( d, pEmr->aptl[0].y ) << " ";\r
561 \r
562 for (i=1; i<pEmr->cptl; i++) {\r
563 tmp_str <<\r
564 "\n\tL " <<\r
565 pix_x_to_point( d, pEmr->aptl[i].x ) << " " <<\r
566 pix_y_to_point( d, pEmr->aptl[i].y ) << " ";\r
567 }\r
568 \r
569 *(d->outsvg) += tmp_str.str().c_str();\r
570 *(d->outsvg) += " z \" /> \n";\r
571 \r
572 break;\r
573 }\r
574 case EMR_POLYLINE:\r
575 {\r
576 EMRPOLYLINE *pEmr = (EMRPOLYLINE *) lpEMFR;\r
577 DWORD i;\r
578 \r
579 if (pEmr->cptl<2)\r
580 break;\r
581 \r
582 *(d->outsvg) += " <path ";\r
583 output_style(d, EMR_STROKEPATH);\r
584 *(d->outsvg) += "\n\td=\"";\r
585 \r
586 tmp_str <<\r
587 "\n\tM " <<\r
588 pix_x_to_point( d, pEmr->aptl[0].x ) << " " <<\r
589 pix_y_to_point( d, pEmr->aptl[0].y ) << " ";\r
590 \r
591 for (i=1; i<pEmr->cptl; i++) {\r
592 tmp_str <<\r
593 "\n\tL " <<\r
594 pix_x_to_point( d, pEmr->aptl[i].x ) << " " <<\r
595 pix_y_to_point( d, pEmr->aptl[i].y ) << " ";\r
596 }\r
597 \r
598 *(d->outsvg) += tmp_str.str().c_str();\r
599 *(d->outsvg) += " \" /> \n";\r
600 \r
601 break;\r
602 }\r
603 case EMR_POLYBEZIERTO:\r
604 {\r
605 PEMRPOLYBEZIERTO pEmr = (PEMRPOLYBEZIERTO) lpEMFR;\r
606 DWORD i,j;\r
607 \r
608 for (i=0; i<pEmr->cptl;) {\r
609 tmp_path << "\n\tC ";\r
610 for (j=0; j<3 && i<pEmr->cptl; j++,i++) {\r
611 tmp_path <<\r
612 pix_x_to_point( d, pEmr->aptl[i].x ) << " " <<\r
613 pix_y_to_point( d, pEmr->aptl[i].y ) << " ";\r
614 }\r
615 }\r
616 \r
617 break;\r
618 }\r
619 case EMR_POLYLINETO:\r
620 {\r
621 PEMRPOLYLINETO pEmr = (PEMRPOLYLINETO) lpEMFR;\r
622 DWORD i;\r
623 \r
624 for (i=0; i<pEmr->cptl;i++) {\r
625 tmp_path <<\r
626 "\n\tL " <<\r
627 pix_x_to_point( d, pEmr->aptl[i].x ) << " " <<\r
628 pix_y_to_point( d, pEmr->aptl[i].y ) << " ";\r
629 }\r
630 \r
631 break;\r
632 }\r
633 case EMR_POLYPOLYLINE:\r
634 break;\r
635 case EMR_POLYPOLYGON:\r
636 break;\r
637 case EMR_SETWINDOWEXTEX:\r
638 {\r
639 PEMRSETWINDOWEXTEX pEmr = (PEMRSETWINDOWEXTEX) lpEMFR;\r
640 \r
641 d->sizeWnd = pEmr->szlExtent;\r
642 d->PixelsX = d->sizeWnd.cx;\r
643 d->PixelsY = d->sizeWnd.cy;\r
644 \r
645 d->ScaleX = d->xDPI / (100*d->MMX / d->PixelsX);\r
646 d->ScaleY = d->yDPI / (100*d->MMY / d->PixelsY);\r
647 \r
648 break;\r
649 }\r
650 case EMR_SETWINDOWORGEX:\r
651 {\r
652 PEMRSETWINDOWORGEX pEmr = (PEMRSETWINDOWORGEX) lpEMFR;\r
653 d->winorg = pEmr->ptlOrigin;\r
654 break;\r
655 }\r
656 case EMR_SETVIEWPORTEXTEX:\r
657 {\r
658 PEMRSETVIEWPORTEXTEX pEmr = (PEMRSETVIEWPORTEXTEX) lpEMFR;\r
659 \r
660 d->sizeView = pEmr->szlExtent;\r
661 \r
662 if (d->sizeWnd.cx && d->sizeWnd.cy) {\r
663 HDC hScreenDC = GetDC( NULL );\r
664 \r
665 float scrPixelsX = (float)GetDeviceCaps( hScreenDC, HORZRES );\r
666 float scrPixelsY = (float)GetDeviceCaps( hScreenDC, VERTRES );\r
667 float scrMMX = (float)GetDeviceCaps( hScreenDC, HORZSIZE );\r
668 float scrMMY = (float)GetDeviceCaps( hScreenDC, VERTSIZE );\r
669 \r
670 ReleaseDC( NULL, hScreenDC );\r
671 \r
672 d->dwInchesX = d->sizeView.cx / (25.4f*scrPixelsX/scrMMX);\r
673 d->dwInchesY = d->sizeView.cy / (25.4f*scrPixelsY/scrMMY);\r
674 d->xDPI = d->sizeWnd.cx / d->dwInchesX;\r
675 d->yDPI = d->sizeWnd.cy / d->dwInchesY;\r
676 \r
677 if (1) {\r
678 d->xDPI = 2540;\r
679 d->yDPI = 2540;\r
680 d->dwInchesX = d->PixelsX / d->xDPI;\r
681 d->dwInchesY = d->PixelsY / d->yDPI;\r
682 d->ScaleX = d->xDPI;\r
683 d->ScaleY = d->yDPI;\r
684 }\r
685 \r
686 d->MMX = d->dwInchesX * MM_PER_IN;\r
687 d->MMY = d->dwInchesY * MM_PER_IN;\r
688 }\r
689 \r
690 break;\r
691 }\r
692 case EMR_SETVIEWPORTORGEX:\r
693 {\r
694 PEMRSETVIEWPORTORGEX pEmr = (PEMRSETVIEWPORTORGEX) lpEMFR;\r
695 d->vieworg = pEmr->ptlOrigin;\r
696 break;\r
697 }\r
698 case EMR_SETBRUSHORGEX:\r
699 break;\r
700 case EMR_EOF:\r
701 {\r
702 tmp_outsvg << "</svg>\n";\r
703 break;\r
704 }\r
705 case EMR_SETPIXELV:\r
706 break;\r
707 case EMR_SETMAPPERFLAGS:\r
708 break;\r
709 case EMR_SETMAPMODE:\r
710 break;\r
711 case EMR_SETBKMODE:\r
712 break;\r
713 case EMR_SETPOLYFILLMODE:\r
714 {\r
715 PEMRSETPOLYFILLMODE pEmr = (PEMRSETPOLYFILLMODE) lpEMFR;\r
716 d->style.fill_rule.value =\r
717 (pEmr->iMode == WINDING ? 0 :\r
718 pEmr->iMode == ALTERNATE ? 1 : 0);\r
719 break;\r
720 }\r
721 case EMR_SETROP2:\r
722 break;\r
723 case EMR_SETSTRETCHBLTMODE:\r
724 break;\r
725 case EMR_SETTEXTALIGN:\r
726 break;\r
727 case EMR_SETCOLORADJUSTMENT:\r
728 break;\r
729 case EMR_SETTEXTCOLOR:\r
730 break;\r
731 case EMR_SETBKCOLOR:\r
732 break;\r
733 case EMR_OFFSETCLIPRGN:\r
734 break;\r
735 case EMR_MOVETOEX:\r
736 {\r
737 PEMRMOVETOEX pEmr = (PEMRMOVETOEX) lpEMFR;\r
738 tmp_path <<\r
739 "\n\tM " <<\r
740 pix_x_to_point( d, pEmr->ptl.x ) << " " <<\r
741 pix_y_to_point( d, pEmr->ptl.y ) << " ";\r
742 break;\r
743 }\r
744 case EMR_SETMETARGN:\r
745 break;\r
746 case EMR_EXCLUDECLIPRECT:\r
747 break;\r
748 case EMR_INTERSECTCLIPRECT:\r
749 break;\r
750 case EMR_SCALEVIEWPORTEXTEX:\r
751 break;\r
752 case EMR_SCALEWINDOWEXTEX:\r
753 break;\r
754 case EMR_SAVEDC:\r
755 break;\r
756 case EMR_RESTOREDC:\r
757 break;\r
758 case EMR_SETWORLDTRANSFORM:\r
759 break;\r
760 case EMR_MODIFYWORLDTRANSFORM:\r
761 break;\r
762 case EMR_SELECTOBJECT:\r
763 {\r
764 PEMRSELECTOBJECT pEmr = (PEMRSELECTOBJECT) lpEMFR;\r
765 unsigned int index = pEmr->ihObject;\r
766 \r
767 if (index >= ENHMETA_STOCK_OBJECT) {\r
768 index -= ENHMETA_STOCK_OBJECT;\r
769 switch (index) {\r
770 case NULL_BRUSH:\r
771 d->fill_set = false;\r
772 break;\r
773 case BLACK_BRUSH:\r
774 case DKGRAY_BRUSH:\r
775 case GRAY_BRUSH:\r
776 case LTGRAY_BRUSH:\r
777 case WHITE_BRUSH:\r
778 {\r
779 float val = 0;\r
780 switch (index) {\r
781 case BLACK_BRUSH:\r
782 val = 0.0 / 255.0;\r
783 break;\r
784 case DKGRAY_BRUSH:\r
785 val = 64.0 / 255.0;\r
786 break;\r
787 case GRAY_BRUSH:\r
788 val = 128.0 / 255.0;\r
789 break;\r
790 case LTGRAY_BRUSH:\r
791 val = 192.0 / 255.0;\r
792 break;\r
793 case WHITE_BRUSH:\r
794 val = 255.0 / 255.0;\r
795 break;\r
796 }\r
797 sp_color_set_rgb_float( &(d->style.fill.value.color), val,val,val );\r
798 \r
799 d->fill_set = true;\r
800 break;\r
801 }\r
802 case NULL_PEN:\r
803 d->stroke_set = false;\r
804 break;\r
805 case BLACK_PEN:\r
806 case WHITE_PEN:\r
807 {\r
808 float val = index == BLACK_PEN ? 0 : 1;\r
809 d->style.stroke_dasharray_set = 0;\r
810 d->style.stroke_width.value = 1.0;\r
811 sp_color_set_rgb_float( &(d->style.stroke.value.color), val,val,val );\r
812 \r
813 d->stroke_set = true;\r
814 \r
815 break;\r
816 }\r
817 }\r
818 } else {\r
819 if (index >= 0 && index < d->n_obj) {\r
820 switch (d->emf_obj[index].type)\r
821 {\r
822 case EMR_CREATEPEN:\r
823 select_pen(d, index);\r
824 break;\r
825 case EMR_CREATEBRUSHINDIRECT:\r
826 select_brush(d, index);\r
827 break;\r
828 case EMR_EXTCREATEPEN:\r
829 select_extpen(d, index);\r
830 break;\r
831 }\r
832 }\r
833 }\r
834 break;\r
835 }\r
836 case EMR_CREATEPEN:\r
837 {\r
838 PEMRCREATEPEN pEmr = (PEMRCREATEPEN) lpEMFR;\r
839 int index = pEmr->ihPen;\r
840 \r
841 EMRCREATEPEN *pPen =\r
842 (EMRCREATEPEN *) malloc( sizeof(EMREXTCREATEPEN) );\r
843 pPen->lopn = pEmr->lopn;\r
844 insert_object(d, index, EMR_CREATEPEN, (ENHMETARECORD *) pPen);\r
845 \r
846 break;\r
847 }\r
848 case EMR_CREATEBRUSHINDIRECT:\r
849 {\r
850 PEMRCREATEBRUSHINDIRECT pEmr = (PEMRCREATEBRUSHINDIRECT) lpEMFR;\r
851 int index = pEmr->ihBrush;\r
852 \r
853 EMRCREATEBRUSHINDIRECT *pBrush =\r
854 (EMRCREATEBRUSHINDIRECT *) malloc( sizeof(EMRCREATEBRUSHINDIRECT) );\r
855 pBrush->lb = pEmr->lb;\r
856 insert_object(d, index, EMR_CREATEBRUSHINDIRECT, (ENHMETARECORD *) pBrush);\r
857 \r
858 break;\r
859 }\r
860 case EMR_DELETEOBJECT:\r
861 break;\r
862 case EMR_ANGLEARC:\r
863 break;\r
864 case EMR_ELLIPSE:\r
865 break;\r
866 case EMR_RECTANGLE:\r
867 break;\r
868 case EMR_ROUNDRECT:\r
869 break;\r
870 case EMR_ARC:\r
871 break;\r
872 case EMR_CHORD:\r
873 break;\r
874 case EMR_PIE:\r
875 break;\r
876 case EMR_SELECTPALETTE:\r
877 break;\r
878 case EMR_CREATEPALETTE:\r
879 break;\r
880 case EMR_SETPALETTEENTRIES:\r
881 break;\r
882 case EMR_RESIZEPALETTE:\r
883 break;\r
884 case EMR_REALIZEPALETTE:\r
885 break;\r
886 case EMR_EXTFLOODFILL:\r
887 break;\r
888 case EMR_LINETO:\r
889 {\r
890 PEMRLINETO pEmr = (PEMRLINETO) lpEMFR;\r
891 tmp_path <<\r
892 "\n\tL " <<\r
893 pix_x_to_point( d, pEmr->ptl.x ) << " " <<\r
894 pix_y_to_point( d, pEmr->ptl.y ) << " ";\r
895 break;\r
896 }\r
897 case EMR_ARCTO:\r
898 break;\r
899 case EMR_POLYDRAW:\r
900 break;\r
901 case EMR_SETARCDIRECTION:\r
902 break;\r
903 case EMR_SETMITERLIMIT:\r
904 {\r
905 PEMRSETMITERLIMIT pEmr = (PEMRSETMITERLIMIT) lpEMFR;\r
906 d->style.stroke_miterlimit.value = pix_size_to_point( d, pEmr->eMiterLimit );\r
907 \r
908 if (d->style.stroke_miterlimit.value < 1)\r
909 d->style.stroke_miterlimit.value = 1.0;\r
910 \r
911 break;\r
912 }\r
913 case EMR_BEGINPATH:\r
914 {\r
915 tmp_path << " d=\"";\r
916 *(d->path) = "";\r
917 break;\r
918 }\r
919 case EMR_ENDPATH:\r
920 {\r
921 tmp_path << "\"";\r
922 break;\r
923 }\r
924 case EMR_CLOSEFIGURE:\r
925 {\r
926 tmp_path << "\n\tz";\r
927 break;\r
928 }\r
929 case EMR_FILLPATH:\r
930 case EMR_STROKEANDFILLPATH:\r
931 case EMR_STROKEPATH:\r
932 {\r
933 *(d->outsvg) += " <path ";\r
934 output_style(d, lpEMFR->iType);\r
935 *(d->outsvg) += "\n\t";\r
936 *(d->outsvg) += *(d->path);\r
937 *(d->outsvg) += " /> \n";\r
938 break;\r
939 }\r
940 case EMR_FLATTENPATH:\r
941 break;\r
942 case EMR_WIDENPATH:\r
943 break;\r
944 case EMR_SELECTCLIPPATH:\r
945 break;\r
946 case EMR_ABORTPATH:\r
947 break;\r
948 case EMR_GDICOMMENT:\r
949 break;\r
950 case EMR_FILLRGN:\r
951 break;\r
952 case EMR_FRAMERGN:\r
953 break;\r
954 case EMR_INVERTRGN:\r
955 break;\r
956 case EMR_PAINTRGN:\r
957 break;\r
958 case EMR_EXTSELECTCLIPRGN:\r
959 break;\r
960 case EMR_BITBLT:\r
961 break;\r
962 case EMR_STRETCHBLT:\r
963 break;\r
964 case EMR_MASKBLT:\r
965 break;\r
966 case EMR_PLGBLT:\r
967 break;\r
968 case EMR_SETDIBITSTODEVICE:\r
969 break;\r
970 case EMR_STRETCHDIBITS:\r
971 break;\r
972 case EMR_EXTCREATEFONTINDIRECTW:\r
973 break;\r
974 case EMR_EXTTEXTOUTA:\r
975 break;\r
976 case EMR_EXTTEXTOUTW:\r
977 break;\r
978 case EMR_POLYBEZIER16:\r
979 {\r
980 PEMRPOLYBEZIER16 pEmr = (PEMRPOLYBEZIER16) lpEMFR;\r
981 POINTS *apts = (POINTS *) pEmr->apts; // Bug in MinGW wingdi.h ?\r
982 DWORD i,j;\r
983 \r
984 if (pEmr->cpts<4)\r
985 break;\r
986 \r
987 *(d->outsvg) += " <path ";\r
988 output_style(d, EMR_STROKEPATH);\r
989 *(d->outsvg) += "\n\td=\"";\r
990 \r
991 tmp_str <<\r
992 "\n\tM " <<\r
993 pix_x_to_point( d, apts[0].x ) << " " <<\r
994 pix_y_to_point( d, apts[0].y ) << " ";\r
995 \r
996 for (i=1; i<pEmr->cpts; ) {\r
997 tmp_str << "\n\tC ";\r
998 for (j=0; j<3 && i<pEmr->cpts; j++,i++) {\r
999 tmp_str <<\r
1000 pix_x_to_point( d, apts[i].x ) << " " <<\r
1001 pix_y_to_point( d, apts[i].y ) << " ";\r
1002 }\r
1003 }\r
1004 \r
1005 *(d->outsvg) += tmp_str.str().c_str();\r
1006 *(d->outsvg) += " \" /> \n";\r
1007 \r
1008 break;\r
1009 }\r
1010 case EMR_POLYGON16:\r
1011 {\r
1012 PEMRPOLYGON16 pEmr = (PEMRPOLYGON16) lpEMFR;\r
1013 POINTS *apts = (POINTS *) pEmr->apts; // Bug in MinGW wingdi.h ?\r
1014 unsigned int i;\r
1015 \r
1016 *(d->outsvg) += "<path ";\r
1017 output_style(d, EMR_STROKEANDFILLPATH);\r
1018 *(d->outsvg) += "\n\td=\"";\r
1019 \r
1020 // skip the first point?\r
1021 tmp_path << "\n\tM " <<\r
1022 pix_x_to_point( d, apts[1].x ) << " " <<\r
1023 pix_y_to_point( d, apts[1].y ) << " ";\r
1024 \r
1025 for (i=2; i<pEmr->cpts; i++) {\r
1026 tmp_path << "\n\tL " <<\r
1027 pix_x_to_point( d, apts[i].x ) << " " <<\r
1028 pix_y_to_point( d, apts[i].y ) << " ";\r
1029 }\r
1030 \r
1031 *(d->outsvg) += tmp_path.str().c_str();\r
1032 *(d->outsvg) += " z \" /> \n";\r
1033 \r
1034 break;\r
1035 }\r
1036 case EMR_POLYLINE16:\r
1037 {\r
1038 EMRPOLYLINE16 *pEmr = (EMRPOLYLINE16 *) lpEMFR;\r
1039 POINTS *apts = (POINTS *) pEmr->apts; // Bug in MinGW wingdi.h ?\r
1040 DWORD i;\r
1041 \r
1042 if (pEmr->cpts<2)\r
1043 break;\r
1044 \r
1045 *(d->outsvg) += " <path ";\r
1046 output_style(d, EMR_STROKEPATH);\r
1047 *(d->outsvg) += "\n\td=\"";\r
1048 \r
1049 tmp_str <<\r
1050 "\n\tM " <<\r
1051 pix_x_to_point( d, apts[0].x ) << " " <<\r
1052 pix_y_to_point( d, apts[0].y ) << " ";\r
1053 \r
1054 for (i=1; i<pEmr->cpts; i++) {\r
1055 tmp_str <<\r
1056 "\n\tL " <<\r
1057 pix_x_to_point( d, apts[i].x ) << " " <<\r
1058 pix_y_to_point( d, apts[i].y ) << " ";\r
1059 }\r
1060 \r
1061 *(d->outsvg) += tmp_str.str().c_str();\r
1062 *(d->outsvg) += " \" /> \n";\r
1063 \r
1064 break;\r
1065 }\r
1066 case EMR_POLYBEZIERTO16:\r
1067 {\r
1068 PEMRPOLYBEZIERTO16 pEmr = (PEMRPOLYBEZIERTO16) lpEMFR;\r
1069 POINTS *apts = (POINTS *) pEmr->apts; // Bug in MinGW wingdi.h ?\r
1070 DWORD i,j;\r
1071 \r
1072 for (i=0; i<pEmr->cpts;) {\r
1073 tmp_path << "\n\tC ";\r
1074 for (j=0; j<3 && i<pEmr->cpts; j++,i++) {\r
1075 tmp_path <<\r
1076 pix_x_to_point( d, apts[i].x ) << " " <<\r
1077 pix_y_to_point( d, apts[i].y ) << " ";\r
1078 }\r
1079 }\r
1080 \r
1081 break;\r
1082 }\r
1083 case EMR_POLYLINETO16:\r
1084 {\r
1085 PEMRPOLYLINETO16 pEmr = (PEMRPOLYLINETO16) lpEMFR;\r
1086 POINTS *apts = (POINTS *) pEmr->apts; // Bug in MinGW wingdi.h ?\r
1087 DWORD i;\r
1088 \r
1089 for (i=0; i<pEmr->cpts;i++) {\r
1090 tmp_path <<\r
1091 "\n\tL " <<\r
1092 pix_x_to_point( d, apts[i].x ) << " " <<\r
1093 pix_y_to_point( d, apts[i].y ) << " ";\r
1094 }\r
1095 \r
1096 break;\r
1097 }\r
1098 case EMR_POLYPOLYLINE16:\r
1099 break;\r
1100 case EMR_POLYPOLYGON16:\r
1101 {\r
1102 PEMRPOLYPOLYGON16 pEmr = (PEMRPOLYPOLYGON16) lpEMFR;\r
1103 unsigned int n, i, j;\r
1104 \r
1105 *(d->outsvg) += "<path ";\r
1106 output_style(d, EMR_STROKEANDFILLPATH);\r
1107 *(d->outsvg) += "\n\td=\"";\r
1108 \r
1109 i = pEmr->nPolys-1; // ???\r
1110 for (n=0; n<pEmr->nPolys /*&& i<pEmr->cpts*/; n++) {\r
1111 SVGOStringStream poly_path;\r
1112 \r
1113 poly_path << "\n\tM " <<\r
1114 pix_x_to_point( d, pEmr->apts[i].x ) << " " <<\r
1115 pix_y_to_point( d, pEmr->apts[i].y ) << " ";\r
1116 i++;\r
1117 \r
1118 for (j=1; j<pEmr->aPolyCounts[n] /*&& i<pEmr->cpts*/; j++) {\r
1119 poly_path << "\n\tL " <<\r
1120 pix_x_to_point( d, pEmr->apts[i].x ) << " " <<\r
1121 pix_y_to_point( d, pEmr->apts[i].y ) << " ";\r
1122 i++;\r
1123 }\r
1124 \r
1125 *(d->outsvg) += poly_path.str().c_str();\r
1126 *(d->outsvg) += " z \n";\r
1127 }\r
1128 \r
1129 *(d->outsvg) += " \" /> \n";\r
1130 break;\r
1131 }\r
1132 case EMR_POLYDRAW16:\r
1133 break;\r
1134 case EMR_CREATEMONOBRUSH:\r
1135 break;\r
1136 case EMR_CREATEDIBPATTERNBRUSHPT:\r
1137 break;\r
1138 case EMR_EXTCREATEPEN:\r
1139 {\r
1140 PEMREXTCREATEPEN pEmr = (PEMREXTCREATEPEN) lpEMFR;\r
1141 int index = pEmr->ihPen;\r
1142 \r
1143 EMREXTCREATEPEN *pPen =\r
1144 (EMREXTCREATEPEN *) malloc( sizeof(EMREXTCREATEPEN) +\r
1145 sizeof(DWORD) * pEmr->elp.elpNumEntries );\r
1146 pPen->ihPen = pEmr->ihPen;\r
1147 pPen->offBmi = pEmr->offBmi;\r
1148 pPen->cbBmi = pEmr->cbBmi;\r
1149 pPen->offBits = pEmr->offBits;\r
1150 pPen->cbBits = pEmr->cbBits;\r
1151 pPen->elp = pEmr->elp;\r
1152 for (unsigned int i=0; i<pEmr->elp.elpNumEntries; i++) {\r
1153 pPen->elp.elpStyleEntry[i] = pEmr->elp.elpStyleEntry[i];\r
1154 }\r
1155 insert_object(d, index, EMR_EXTCREATEPEN, (ENHMETARECORD *) pPen);\r
1156 \r
1157 break;\r
1158 }\r
1159 case EMR_POLYTEXTOUTA:\r
1160 break;\r
1161 case EMR_POLYTEXTOUTW:\r
1162 break;\r
1163 case EMR_SETICMMODE:\r
1164 break;\r
1165 case EMR_CREATECOLORSPACE:\r
1166 break;\r
1167 case EMR_SETCOLORSPACE:\r
1168 break;\r
1169 case EMR_DELETECOLORSPACE:\r
1170 break;\r
1171 case EMR_GLSRECORD:\r
1172 break;\r
1173 case EMR_GLSBOUNDEDRECORD:\r
1174 break;\r
1175 case EMR_PIXELFORMAT:\r
1176 break;\r
1177 }\r
1178 \r
1179 *(d->outsvg) += tmp_outsvg.str().c_str();\r
1180 *(d->path) += tmp_path.str().c_str();\r
1181 \r
1182 return 1;\r
1183 }\r
1184 \r
1185 \r
1186 // Aldus Placeable Header ===================================================\r
1187 // Since we are a 32bit app, we have to be sure this structure compiles to\r
1188 // be identical to a 16 bit app's version. To do this, we use the #pragma\r
1189 // to adjust packing, we use a WORD for the hmf handle, and a SMALL_RECT\r
1190 // for the bbox rectangle.\r
1191 #pragma pack( push )\r
1192 #pragma pack( 2 )\r
1193 typedef struct\r
1194 {\r
1195 DWORD dwKey;\r
1196 WORD hmf;\r
1197 SMALL_RECT bbox;\r
1198 WORD wInch;\r
1199 DWORD dwReserved;\r
1200 WORD wCheckSum;\r
1201 } APMHEADER, *PAPMHEADER;\r
1202 #pragma pack( pop )\r
1203 \r
1204 \r
1205 SPDocument *\r
1206 EmfWin32::open( Inkscape::Extension::Input *mod, const gchar *uri )\r
1207 {\r
1208 EMF_CALLBACK_DATA d = {0};\r
1209 \r
1210 gsize bytesRead = 0;\r
1211 gsize bytesWritten = 0;\r
1212 GError* error = NULL;\r
1213 gchar *local_fn =\r
1214 g_filename_from_utf8( uri, -1, &bytesRead, &bytesWritten, &error );\r
1215 \r
1216 if (local_fn == NULL) {\r
1217 return NULL;\r
1218 }\r
1219 \r
1220 d.outsvg = new Glib::ustring("");\r
1221 d.path = new Glib::ustring("");\r
1222 \r
1223 CHAR *ansi_uri = (CHAR *) local_fn;\r
1224 gunichar2 *unicode_fn = g_utf8_to_utf16( local_fn, -1, NULL, NULL, NULL );\r
1225 WCHAR *unicode_uri = (WCHAR *) unicode_fn;\r
1226 \r
1227 // Try open as Enhanced Metafile\r
1228 HENHMETAFILE hemf;\r
1229 if (PrintWin32::is_os_wide())\r
1230 hemf = GetEnhMetaFileW(unicode_uri);\r
1231 else\r
1232 hemf = GetEnhMetaFileA(ansi_uri);\r
1233 \r
1234 if (!hemf) {\r
1235 // Try open as Windows Metafile\r
1236 HMETAFILE hmf;\r
1237 if (PrintWin32::is_os_wide())\r
1238 hmf = GetMetaFileW(unicode_uri);\r
1239 else\r
1240 hmf = GetMetaFileA(ansi_uri);\r
1241 \r
1242 METAFILEPICT mp;\r
1243 HDC hDC;\r
1244 \r
1245 if (!hmf) {\r
1246 if (PrintWin32::is_os_wide()) {\r
1247 WCHAR szTemp[MAX_PATH];\r
1248 \r
1249 DWORD dw = GetShortPathNameW( unicode_uri, szTemp, MAX_PATH );\r
1250 if (dw) {\r
1251 hmf = GetMetaFileW( szTemp );\r
1252 }\r
1253 } else {\r
1254 CHAR szTemp[MAX_PATH];\r
1255 \r
1256 DWORD dw = GetShortPathNameA( ansi_uri, szTemp, MAX_PATH );\r
1257 if (dw) {\r
1258 hmf = GetMetaFileA( szTemp );\r
1259 }\r
1260 }\r
1261 }\r
1262 \r
1263 if (hmf) {\r
1264 DWORD nSize = GetMetaFileBitsEx( hmf, 0, NULL );\r
1265 if (nSize) {\r
1266 BYTE *lpvData = new BYTE[nSize];\r
1267 if (lpvData) {\r
1268 DWORD dw = GetMetaFileBitsEx( hmf, nSize, lpvData );\r
1269 if (dw) {\r
1270 // Fill out a METAFILEPICT structure\r
1271 mp.mm = MM_ANISOTROPIC;\r
1272 mp.xExt = 1000;\r
1273 mp.yExt = 1000;\r
1274 mp.hMF = NULL;\r
1275 // Get a reference DC\r
1276 hDC = GetDC( NULL );\r
1277 // Make an enhanced metafile from the windows metafile\r
1278 hemf = SetWinMetaFileBits( nSize, lpvData, hDC, &mp );\r
1279 // Clean up\r
1280 ReleaseDC( NULL, hDC );\r
1281 }\r
1282 delete[] lpvData;\r
1283 }\r
1284 DeleteMetaFile( hmf );\r
1285 }\r
1286 } else {\r
1287 // Try open as Aldus Placeable Metafile\r
1288 HANDLE hFile;\r
1289 if (PrintWin32::is_os_wide())\r
1290 hFile = CreateFileW( unicode_uri, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );\r
1291 else\r
1292 hFile = CreateFileA( ansi_uri, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );\r
1293 if (hFile != INVALID_HANDLE_VALUE) {\r
1294 DWORD nSize = GetFileSize( hFile, NULL );\r
1295 if (nSize) {\r
1296 BYTE *lpvData = new BYTE[nSize];\r
1297 if (lpvData) {\r
1298 DWORD dw = ReadFile( hFile, lpvData, nSize, &nSize, NULL );\r
1299 if (dw) {\r
1300 if ( ((PAPMHEADER)lpvData)->dwKey == 0x9ac6cdd7l ) {\r
1301 // Fill out a METAFILEPICT structure\r
1302 mp.mm = MM_ANISOTROPIC;\r
1303 mp.xExt = ((PAPMHEADER)lpvData)->bbox.Right - ((PAPMHEADER)lpvData)->bbox.Left;\r
1304 mp.xExt = ( mp.xExt * 2540l ) / (DWORD)(((PAPMHEADER)lpvData)->wInch);\r
1305 mp.yExt = ((PAPMHEADER)lpvData)->bbox.Bottom - ((PAPMHEADER)lpvData)->bbox.Top;\r
1306 mp.yExt = ( mp.yExt * 2540l ) / (DWORD)(((PAPMHEADER)lpvData)->wInch);\r
1307 mp.hMF = NULL;\r
1308 // Get a reference DC\r
1309 hDC = GetDC( NULL );\r
1310 // Create an enhanced metafile from the bits\r
1311 hemf = SetWinMetaFileBits( nSize, lpvData+sizeof(APMHEADER), hDC, &mp );\r
1312 // Clean up\r
1313 ReleaseDC( NULL, hDC );\r
1314 }\r
1315 }\r
1316 delete[] lpvData;\r
1317 }\r
1318 }\r
1319 CloseHandle( hFile );\r
1320 }\r
1321 }\r
1322 }\r
1323 \r
1324 if (!hemf || !d.outsvg || !d.path) {\r
1325 if (d.outsvg)\r
1326 delete d.outsvg;\r
1327 if (d.path)\r
1328 delete d.path;\r
1329 if (local_fn)\r
1330 g_free(local_fn);\r
1331 if (unicode_fn)\r
1332 g_free(unicode_fn);\r
1333 return NULL;\r
1334 }\r
1335 \r
1336 EnumEnhMetaFile(NULL, hemf, myEnhMetaFileProc, (LPVOID) &d, NULL);\r
1337 DeleteEnhMetaFile(hemf);\r
1338 \r
1339 // std::cout << "SVG Output: " << std::endl << *(d.outsvg) << std::endl;\r
1340 \r
1341 SPDocument *doc = sp_document_new_from_mem(d.outsvg->c_str(), d.outsvg->length(), TRUE);\r
1342 \r
1343 delete d.outsvg;\r
1344 delete d.path;\r
1345 \r
1346 if (d.emf_obj) {\r
1347 int i;\r
1348 for (i=0; i<d.n_obj; i++)\r
1349 delete_object(&d, i);\r
1350 delete[] d.emf_obj;\r
1351 }\r
1352 \r
1353 if (d.style.stroke_dash.dash)\r
1354 delete[] d.style.stroke_dash.dash;\r
1355 \r
1356 if (local_fn)\r
1357 g_free(local_fn);\r
1358 if (unicode_fn)\r
1359 g_free(unicode_fn);\r
1360 \r
1361 return doc;\r
1362 }\r
1363 \r
1364 \r
1365 void\r
1366 EmfWin32::init (void)\r
1367 {\r
1368 Inkscape::Extension::Extension * ext;\r
1369 \r
1370 /* EMF in */\r
1371 ext = Inkscape::Extension::build_from_mem(\r
1372 "<inkscape-extension>\n"\r
1373 "<name>" N_("EMF Input") "</name>\n"\r
1374 "<id>org.inkscape.input.emf.win32</id>\n"\r
1375 "<input>\n"\r
1376 "<extension>.emf</extension>\n"\r
1377 "<mimetype>image/x-emf</mimetype>\n"\r
1378 "<filetypename>" N_("Enhanced Metafiles (*.emf)") "</filetypename>\n"\r
1379 "<filetypetooltip>" N_("Enhanced Metafiles") "</filetypetooltip>\n"\r
1380 "<output_extension>org.inkscape.output.emf.win32</output_extension>\n"\r
1381 "</input>\n"\r
1382 "</inkscape-extension>", new EmfWin32());\r
1383 \r
1384 /* WMF in */\r
1385 ext = Inkscape::Extension::build_from_mem(\r
1386 "<inkscape-extension>\n"\r
1387 "<name>" N_("WMF Input") "</name>\n"\r
1388 "<id>org.inkscape.input.wmf.win32</id>\n"\r
1389 "<input>\n"\r
1390 "<extension>.wmf</extension>\n"\r
1391 "<mimetype>image/x-wmf</mimetype>\n"\r
1392 "<filetypename>" N_("Windows Metafiles (*.wmf)") "</filetypename>\n"\r
1393 "<filetypetooltip>" N_("Windows Metafiles") "</filetypetooltip>\n"\r
1394 "<output_extension>org.inkscape.output.emf.win32</output_extension>\n"\r
1395 "</input>\n"\r
1396 "</inkscape-extension>", new EmfWin32());\r
1397 \r
1398 /* EMF out */\r
1399 ext = Inkscape::Extension::build_from_mem(\r
1400 "<inkscape-extension>\n"\r
1401 "<name>" N_("EMF Output") "</name>\n"\r
1402 "<id>org.inkscape.output.emf.win32</id>\n"\r
1403 "<output>\n"\r
1404 "<extension>.emf</extension>\n"\r
1405 "<mimetype>image/x-emf</mimetype>\n"\r
1406 "<filetypename>" N_("Enhanced Metafile (*.emf)") "</filetypename>\n"\r
1407 "<filetypetooltip>" N_("Enhanced Metafile") "</filetypetooltip>\n"\r
1408 "</output>\n"\r
1409 "</inkscape-extension>", new EmfWin32());\r
1410 \r
1411 return;\r
1412 }\r
1413 \r
1414 \r
1415 } } } /* namespace Inkscape, Extension, Implementation */\r
1416 \r
1417 \r
1418 #endif /* WIN32 */\r
1419 \r
1420 \r
1421 /*\r
1422 Local Variables:\r
1423 mode:cpp\r
1424 c-file-style:"stroustrup"\r
1425 c-file-offsets:((innamespace . 0)(inline-open . 0))\r
1426 indent-tabs-mode:nil\r
1427 fill-column:99\r
1428 End:\r
1429 */\r
1430 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :\r