1 /** \file
2 * Enhanced Metafile Printing.
3 */
4 /*
5 * Authors:
6 * Ulf Erikson <ulferikson@users.sf.net>
7 *
8 * Copyright (C) 2006 Authors
9 *
10 * Released under GNU GPL, read the file 'COPYING' for more information
11 */
12 /*
13 * References:
14 * - How to Create & Play Enhanced Metafiles in Win32
15 * http://support.microsoft.com/kb/q145999/
16 * - INFO: Windows Metafile Functions & Aldus Placeable Metafiles
17 * http://support.microsoft.com/kb/q66949/
18 * - Metafile Functions
19 * http://msdn.microsoft.com/library/en-us/gdi/metafile_0whf.asp
20 * - Metafile Structures
21 * http://msdn.microsoft.com/library/en-us/gdi/metafile_5hkj.asp
22 */
24 #ifdef WIN32
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
30 #include <string.h>
31 #include <signal.h>
32 #include <errno.h>
34 #include "libnr/n-art-bpath.h"
35 #include "libnr/nr-point-matrix-ops.h"
36 #include "libnr/nr-rect.h"
37 #include "libnr/nr-matrix.h"
38 #include "libnr/nr-matrix-fns.h"
39 #include "libnr/nr-path.h"
40 #include "libnr/nr-pixblock.h"
41 #include "display/canvas-bpath.h"
42 #include "sp-item.h"
44 #include "glib.h"
45 #include "gtk/gtkdialog.h"
46 #include "gtk/gtkbox.h"
47 #include "gtk/gtkstock.h"
49 #include "glibmm/i18n.h"
50 #include "enums.h"
51 #include "document.h"
52 #include "style.h"
53 #include "sp-paint-server.h"
54 #include "inkscape_version.h"
56 #include "FontFactory.h"
57 #include "libnrtype/font-instance.h"
58 #include "libnrtype/font-style-to-pos.h"
60 #include "win32.h"
61 #include "emf-win32-print.h"
63 #include "unit-constants.h"
65 #include "extension/extension.h"
66 #include "extension/system.h"
67 #include "extension/print.h"
69 #include "io/sys.h"
71 #include "macros.h"
73 #define WIN32_LEAN_AND_MEAN
74 #include <windows.h>
76 namespace Inkscape {
77 namespace Extension {
78 namespace Internal {
80 static float dwDPI = 2540;
83 PrintEmfWin32::PrintEmfWin32 (void):
84 hdc(NULL),
85 hbrush(NULL),
86 hbrushOld(NULL),
87 hpen(NULL),
88 fill_path(NULL)
89 {
90 }
93 PrintEmfWin32::~PrintEmfWin32 (void)
94 {
95 if (hdc) {
96 HENHMETAFILE metafile = CloseEnhMetaFile( hdc );
97 if ( metafile ) {
98 DeleteEnhMetaFile( metafile );
99 }
100 DeleteDC( hdc );
101 }
103 /* restore default signal handling for SIGPIPE */
104 #if !defined(_WIN32) && !defined(__WIN32__)
105 (void) signal(SIGPIPE, SIG_DFL);
106 #endif
107 return;
108 }
111 unsigned int
112 PrintEmfWin32::setup (Inkscape::Extension::Print *mod)
113 {
114 return TRUE;
115 }
118 unsigned int
119 PrintEmfWin32::begin (Inkscape::Extension::Print *mod, SPDocument *doc)
120 {
121 gchar const *utf8_fn = mod->get_param_string("destination");
123 gsize bytesRead = 0;
124 gsize bytesWritten = 0;
125 GError* error = NULL;
126 gchar *local_fn =
127 g_filename_from_utf8( utf8_fn, -1, &bytesRead, &bytesWritten, &error );
129 if (local_fn == NULL) {
130 return 1;
131 }
133 CHAR *ansi_uri = (CHAR *) local_fn;
134 gunichar2 *unicode_fn = g_utf8_to_utf16( local_fn, -1, NULL, NULL, NULL );
135 WCHAR *unicode_uri = (WCHAR *) unicode_fn;
137 // width and height in px
138 _width = sp_document_width(doc);
139 _height = sp_document_height(doc);
141 NRRect d;
142 bool pageBoundingBox;
143 pageBoundingBox = mod->get_param_bool("pageBoundingBox");
144 if (pageBoundingBox) {
145 d.x0 = d.y0 = 0;
146 d.x1 = _width;
147 d.y1 = _height;
148 } else {
149 SPItem* doc_item = SP_ITEM(sp_document_root(doc));
150 sp_item_invoke_bbox(doc_item, &d, sp_item_i2r_affine(doc_item), TRUE);
151 }
153 d.x0 *= IN_PER_PX;
154 d.y0 *= IN_PER_PX;
155 d.x1 *= IN_PER_PX;
156 d.y1 *= IN_PER_PX;
158 float dwInchesX = (d.x1 - d.x0);
159 float dwInchesY = (d.y1 - d.y0);
161 // dwInchesX x dwInchesY in .01mm units
162 SetRect( &rc, 0, 0, (int) ceil(dwInchesX*2540), (int) ceil(dwInchesY*2540) );
164 // Get a Reference DC
165 HDC hScreenDC = GetDC( NULL );
167 // Get the physical characteristics of the reference DC
168 float PixelsX = (float) GetDeviceCaps( hScreenDC, HORZRES );
169 float PixelsY = (float) GetDeviceCaps( hScreenDC, VERTRES );
170 float MMX = (float) GetDeviceCaps( hScreenDC, HORZSIZE );
171 float MMY = (float) GetDeviceCaps( hScreenDC, VERTSIZE );
173 // Create the Metafile
174 if (PrintWin32::is_os_wide())
175 hdc = CreateEnhMetaFileW( hScreenDC, unicode_uri, &rc, NULL );
176 else
177 hdc = CreateEnhMetaFileA( hScreenDC, ansi_uri, &rc, NULL );
179 // Release the reference DC
180 ReleaseDC( NULL, hScreenDC );
182 // Did we get a good metafile?
183 if (hdc == NULL)
184 {
185 g_free(local_fn);
186 g_free(unicode_fn);
187 return 1;
188 }
190 // Anisotropic mapping mode
191 SetMapMode( hdc, MM_ANISOTROPIC );
193 // Set the Windows extent
194 SetWindowExtEx( hdc, (int) (dwInchesX*dwDPI), (int) (dwInchesY*dwDPI), NULL );
196 // Set the viewport extent to reflect
197 // dwInchesX" x dwInchesY" in device units
198 SetViewportExtEx( hdc,
199 (int) ((float) dwInchesX*25.4f*PixelsX/MMX),
200 (int) ((float) dwInchesY*25.4f*PixelsY/MMY),
201 NULL );
203 SetRect( &rc, 0, 0, (int) ceil(dwInchesX*dwDPI), (int) ceil(dwInchesY*dwDPI) );
205 g_free(local_fn);
206 g_free(unicode_fn);
208 return 0;
209 }
212 unsigned int
213 PrintEmfWin32::finish (Inkscape::Extension::Print *mod)
214 {
215 if (!hdc) return 0;
217 flush_fill(); // flush any pending fills
219 HENHMETAFILE metafile = CloseEnhMetaFile( hdc );
220 if ( metafile ) {
221 DeleteEnhMetaFile( metafile );
222 }
223 DeleteDC( hdc );
225 hdc = NULL;
227 return 0;
228 }
231 unsigned int
232 PrintEmfWin32::comment (Inkscape::Extension::Print * module,
233 const char *comment)
234 {
235 if (!hdc) return 0;
237 flush_fill(); // flush any pending fills
239 return 0;
240 }
243 int
244 PrintEmfWin32::create_brush(SPStyle const *style)
245 {
246 float rgb[3];
248 if (style) {
249 float opacity = SP_SCALE24_TO_FLOAT(style->fill_opacity.value);
250 if (opacity <= 0.0)
251 return 1;
253 sp_color_get_rgb_floatv( &style->fill.value.color, rgb );
254 hbrush = CreateSolidBrush( RGB(255*rgb[0], 255*rgb[1], 255*rgb[2]) );
255 hbrushOld = (HBRUSH) SelectObject( hdc, hbrush );
257 SetPolyFillMode( hdc,
258 style->fill_rule.computed == 0 ? WINDING :
259 style->fill_rule.computed == 2 ? ALTERNATE : ALTERNATE );
260 } else { // if (!style)
261 hbrush = CreateSolidBrush( RGB(255, 255, 255) );
262 hbrushOld = (HBRUSH) SelectObject( hdc, hbrush );
263 SetPolyFillMode( hdc, ALTERNATE );
264 }
266 return 0;
267 }
270 void
271 PrintEmfWin32::destroy_brush()
272 {
273 SelectObject( hdc, hbrushOld );
274 if (hbrush)
275 DeleteObject( hbrush );
276 hbrush = NULL;
277 hbrushOld = NULL;
278 }
281 void
282 PrintEmfWin32::create_pen(SPStyle const *style, const NRMatrix *transform)
283 {
284 if (style) {
285 float rgb[3];
287 sp_color_get_rgb_floatv(&style->stroke.value.color, rgb);
289 LOGBRUSH lb = {0};
290 lb.lbStyle = BS_SOLID;
291 lb.lbColor = RGB( 255*rgb[0], 255*rgb[1], 255*rgb[2] );
293 int linestyle = PS_SOLID;
294 int linecap = 0;
295 int linejoin = 0;
296 DWORD n_dash = 0;
297 DWORD *dash = NULL;
298 float oldmiterlimit;
300 using NR::X;
301 using NR::Y;
303 NR::Matrix tf = *transform;
305 NR::Point zero(0, 0);
306 NR::Point one(1, 1);
307 NR::Point p0(zero * tf);
308 NR::Point p1(one * tf);
309 NR::Point p(p1 - p0);
311 double scale = sqrt( (p[X]*p[X]) + (p[Y]*p[Y]) ) / sqrt(2);
313 DWORD linewidth = MAX( 1, (DWORD) (scale * style->stroke_width.computed * IN_PER_PX * dwDPI) );
315 if (style->stroke_linecap.computed == 0) {
316 linecap = PS_ENDCAP_FLAT;
317 }
318 else if (style->stroke_linecap.computed == 1) {
319 linecap = PS_ENDCAP_ROUND;
320 }
321 else if (style->stroke_linecap.computed == 2) {
322 linecap = PS_ENDCAP_SQUARE;
323 }
325 if (style->stroke_linejoin.computed == 0) {
326 linejoin = PS_JOIN_MITER;
327 }
328 else if (style->stroke_linejoin.computed == 1) {
329 linejoin = PS_JOIN_ROUND;
330 }
331 else if (style->stroke_linejoin.computed == 2) {
332 linejoin = PS_JOIN_BEVEL;
333 }
335 if (style->stroke_dash.n_dash &&
336 style->stroke_dash.dash )
337 {
338 int i = 0;
339 while (linestyle != PS_USERSTYLE &&
340 (i < style->stroke_dash.n_dash)) {
341 if (style->stroke_dash.dash[i] > 0.00000001)
342 linestyle = PS_USERSTYLE;
343 i++;
344 }
346 if (linestyle == PS_USERSTYLE) {
347 n_dash = style->stroke_dash.n_dash;
348 dash = new DWORD[n_dash];
349 for (i = 0; i < style->stroke_dash.n_dash; i++) {
350 dash[i] = (DWORD) (style->stroke_dash.dash[i] * IN_PER_PX * dwDPI);
351 }
352 }
353 }
355 hpen = ExtCreatePen(
356 PS_GEOMETRIC | linestyle | linecap | linejoin,
357 linewidth,
358 &lb,
359 n_dash,
360 dash );
362 if ( !hpen && linestyle == PS_USERSTYLE ) {
363 hpen = ExtCreatePen(
364 PS_GEOMETRIC | PS_SOLID | linecap | linejoin,
365 linewidth,
366 &lb,
367 0,
368 NULL );
369 }
371 if ( !hpen ) {
372 hpen = CreatePen(
373 PS_SOLID,
374 linewidth,
375 lb.lbColor );
376 }
378 hpenOld = (HPEN) SelectObject( hdc, hpen );
380 if (linejoin == PS_JOIN_MITER) {
381 float miterlimit = style->stroke_miterlimit.value;
382 if (miterlimit < 1)
383 miterlimit = 4.0;
384 SetMiterLimit(
385 hdc,
386 miterlimit * IN_PER_PX * dwDPI,
387 &oldmiterlimit );
388 }
390 if (n_dash) {
391 delete[] dash;
392 }
393 }
394 else { // if (!style)
395 hpen = CreatePen( PS_SOLID, 1, RGB(0, 0, 0) );
396 hpenOld = (HPEN) SelectObject( hdc, hpen );
397 }
398 }
401 void
402 PrintEmfWin32::destroy_pen()
403 {
404 SelectObject( hdc, hpenOld );
405 if (hpen)
406 DeleteObject( hpen );
407 hpen = NULL;
408 }
411 void
412 PrintEmfWin32::flush_fill()
413 {
414 if (fill_path) {
415 print_bpath(fill_path, &fill_transform, &fill_pbox);
416 FillPath( hdc );
417 destroy_brush();
418 delete[] fill_path;
419 fill_path = NULL;
420 }
421 }
424 NArtBpath *
425 PrintEmfWin32::copy_bpath(const NArtBpath *bp)
426 {
427 NArtBpath *tmp = (NArtBpath *) bp;
428 int num = 1;
430 while (tmp->code != NR_END) {
431 num++;
432 tmp += 1;
433 }
435 tmp = new NArtBpath[num];
436 while (num--) {
437 tmp[num] = bp[num];
438 }
440 return tmp;
441 }
444 int
445 PrintEmfWin32::cmp_bpath(const NArtBpath *bp1, const NArtBpath *bp2)
446 {
447 if (!bp1 || !bp2) {
448 return 1;
449 }
451 while (bp1->code != NR_END && bp2->code != NR_END) {
452 if (bp1->code != bp2->code) {
453 return 1;
454 }
456 if ( fabs(bp1->x1 - bp2->x1) > 0.00000001 ||
457 fabs(bp1->y1 - bp2->y1) > 0.00000001 ||
458 fabs(bp1->x2 - bp2->x2) > 0.00000001 ||
459 fabs(bp1->y2 - bp2->y2) > 0.00000001 ||
460 fabs(bp1->x3 - bp2->x3) > 0.00000001 ||
461 fabs(bp1->y3 - bp2->y3) > 0.00000001 )
462 {
463 return 1;
464 }
466 bp1 += 1;
467 bp2 += 1;
468 }
470 return bp1->code != NR_END || bp2->code != NR_END;
471 }
473 unsigned int
474 PrintEmfWin32::bind(Inkscape::Extension::Print *mod, NRMatrix const *transform, float opacity)
475 {
476 text_transform = *transform;
477 return 0;
478 }
480 unsigned int
481 PrintEmfWin32::release(Inkscape::Extension::Print *mod)
482 {
483 return 0;
484 }
486 unsigned int
487 PrintEmfWin32::fill(Inkscape::Extension::Print *mod,
488 NRBPath const *bpath, NRMatrix const *transform, SPStyle const *style,
489 NRRect const *pbox, NRRect const *dbox, NRRect const *bbox)
490 {
491 if (!hdc) return 0;
493 flush_fill(); // flush any pending fills
495 if (style->fill.isColor()) {
496 if (create_brush(style))
497 return 0;
498 } else {
499 // create_brush(NULL);
500 return 0;
501 }
503 fill_path = copy_bpath( bpath->path );
504 fill_transform = *transform;
505 fill_pbox = *pbox;
507 // postpone fill in case of stroke-and-fill
509 return 0;
510 }
513 unsigned int
514 PrintEmfWin32::stroke (Inkscape::Extension::Print *mod,
515 const NRBPath *bpath, const NRMatrix *transform, const SPStyle *style,
516 const NRRect *pbox, const NRRect *dbox, const NRRect *bbox)
517 {
518 if (!hdc) return 0;
520 bool stroke_and_fill = ( cmp_bpath( bpath->path, fill_path ) == 0 );
522 if (!stroke_and_fill) {
523 flush_fill(); // flush any pending fills
524 }
526 if (style->stroke.isColor()) {
527 create_pen(style, transform);
528 } else {
529 // create_pen(NULL, transform);
530 return 0;
531 }
533 print_bpath(bpath->path, transform, pbox);
535 if (stroke_and_fill) {
536 StrokeAndFillPath( hdc );
537 destroy_brush();
538 delete[] fill_path;
539 fill_path = NULL;
540 } else {
541 StrokePath( hdc );
542 }
544 destroy_pen();
546 return 0;
547 }
550 unsigned int
551 PrintEmfWin32::print_bpath(const NArtBpath *bp, const NRMatrix *transform, NRRect const *pbox)
552 {
553 unsigned int closed;
554 NR::Matrix tf = *transform;
556 BeginPath( hdc );
557 closed = FALSE;
558 while (bp->code != NR_END) {
559 using NR::X;
560 using NR::Y;
562 NR::Point p1(bp->c(1) * tf);
563 NR::Point p2(bp->c(2) * tf);
564 NR::Point p3(bp->c(3) * tf);
566 p1[X] = (p1[X] * IN_PER_PX * dwDPI);
567 p2[X] = (p2[X] * IN_PER_PX * dwDPI);
568 p3[X] = (p3[X] * IN_PER_PX * dwDPI);
569 p1[Y] = (p1[Y] * IN_PER_PX * dwDPI);
570 p2[Y] = (p2[Y] * IN_PER_PX * dwDPI);
571 p3[Y] = (p3[Y] * IN_PER_PX * dwDPI);
573 LONG const x1 = (LONG) round(p1[X]);
574 LONG const y1 = (LONG) round(rc.bottom-p1[Y]);
575 LONG const x2 = (LONG) round(p2[X]);
576 LONG const y2 = (LONG) round(rc.bottom-p2[Y]);
577 LONG const x3 = (LONG) round(p3[X]);
578 LONG const y3 = (LONG) round(rc.bottom-p3[Y]);
580 switch (bp->code) {
581 case NR_MOVETO:
582 if (closed) {
583 CloseFigure( hdc );
584 }
585 closed = TRUE;
586 MoveToEx( hdc, x3, y3, NULL );
587 break;
588 case NR_MOVETO_OPEN:
589 if (closed) {
590 CloseFigure( hdc );
591 }
592 closed = FALSE;
593 MoveToEx( hdc, x3, y3, NULL );
594 break;
595 case NR_LINETO:
596 LineTo( hdc, x3, y3 );
597 break;
598 case NR_CURVETO:
599 {
600 POINT pt[3];
601 pt[0].x = x1;
602 pt[0].y = y1;
603 pt[1].x = x2;
604 pt[1].y = y2;
605 pt[2].x = x3;
606 pt[2].y = y3;
608 PolyBezierTo( hdc, pt, 3 );
609 break;
610 }
611 default:
612 break;
613 }
614 bp += 1;
615 }
616 if (closed) {
617 CloseFigure( hdc );
618 }
619 EndPath( hdc );
621 return closed;
622 }
625 bool
626 PrintEmfWin32::textToPath(Inkscape::Extension::Print * ext)
627 {
628 return ext->get_param_bool("textToPath");
629 }
631 unsigned int
632 PrintEmfWin32::text(Inkscape::Extension::Print *mod, char const *text, NR::Point p,
633 SPStyle const *const style)
634 {
635 if (!hdc) return 0;
637 HFONT hfont = NULL;
639 #ifdef USE_PANGO_WIN32
640 /*
641 font_instance *tf = (font_factory::Default())->Face(style->text->font_family.value, font_style_to_pos(*style));
642 if (tf) {
643 LOGFONT *lf = pango_win32_font_logfont(tf->pFont);
644 tf->Unref();
645 hfont = CreateFontIndirect(lf);
646 g_free(lf);
647 }
648 */
649 #endif
651 if (!hfont) {
652 if (PrintWin32::is_os_wide()) {
653 LOGFONTW *lf = (LOGFONTW*)g_malloc(sizeof(LOGFONTW));
654 g_assert(lf != NULL);
656 lf->lfHeight = style->font_size.computed * IN_PER_PX * dwDPI;
657 lf->lfWidth = 0;
658 lf->lfEscapement = 0;
659 lf->lfOrientation = 0;
660 lf->lfWeight =
661 style->font_weight.value == SP_CSS_FONT_WEIGHT_100 ? FW_THIN :
662 style->font_weight.value == SP_CSS_FONT_WEIGHT_200 ? FW_EXTRALIGHT :
663 style->font_weight.value == SP_CSS_FONT_WEIGHT_300 ? FW_LIGHT :
664 style->font_weight.value == SP_CSS_FONT_WEIGHT_400 ? FW_NORMAL :
665 style->font_weight.value == SP_CSS_FONT_WEIGHT_500 ? FW_MEDIUM :
666 style->font_weight.value == SP_CSS_FONT_WEIGHT_600 ? FW_SEMIBOLD :
667 style->font_weight.value == SP_CSS_FONT_WEIGHT_700 ? FW_BOLD :
668 style->font_weight.value == SP_CSS_FONT_WEIGHT_800 ? FW_EXTRABOLD :
669 style->font_weight.value == SP_CSS_FONT_WEIGHT_900 ? FW_HEAVY :
670 style->font_weight.value == SP_CSS_FONT_WEIGHT_NORMAL ? FW_NORMAL :
671 style->font_weight.value == SP_CSS_FONT_WEIGHT_BOLD ? FW_BOLD :
672 style->font_weight.value == SP_CSS_FONT_WEIGHT_LIGHTER ? FW_EXTRALIGHT :
673 style->font_weight.value == SP_CSS_FONT_WEIGHT_BOLDER ? FW_EXTRABOLD :
674 FW_NORMAL;
675 lf->lfItalic = (style->font_style.value == SP_CSS_FONT_STYLE_ITALIC);
676 lf->lfUnderline = style->text_decoration.underline;
677 lf->lfStrikeOut = style->text_decoration.line_through;
678 lf->lfCharSet = DEFAULT_CHARSET;
679 lf->lfOutPrecision = OUT_DEFAULT_PRECIS;
680 lf->lfClipPrecision = CLIP_DEFAULT_PRECIS;
681 lf->lfQuality = DEFAULT_QUALITY;
682 lf->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
684 gunichar2 *unicode_name = g_utf8_to_utf16( style->text->font_family.value, -1, NULL, NULL, NULL );
685 wcsncpy(lf->lfFaceName, (wchar_t*) unicode_name, LF_FACESIZE-1);
686 g_free(unicode_name);
688 hfont = CreateFontIndirectW(lf);
690 g_free(lf);
691 }
692 else {
693 LOGFONTA *lf = (LOGFONTA*)g_malloc(sizeof(LOGFONTA));
694 g_assert(lf != NULL);
696 lf->lfHeight = style->font_size.computed * IN_PER_PX * dwDPI;
697 lf->lfWidth = 0;
698 lf->lfEscapement = 0;
699 lf->lfOrientation = 0;
700 lf->lfWeight =
701 style->font_weight.value == SP_CSS_FONT_WEIGHT_100 ? FW_THIN :
702 style->font_weight.value == SP_CSS_FONT_WEIGHT_200 ? FW_EXTRALIGHT :
703 style->font_weight.value == SP_CSS_FONT_WEIGHT_300 ? FW_LIGHT :
704 style->font_weight.value == SP_CSS_FONT_WEIGHT_400 ? FW_NORMAL :
705 style->font_weight.value == SP_CSS_FONT_WEIGHT_500 ? FW_MEDIUM :
706 style->font_weight.value == SP_CSS_FONT_WEIGHT_600 ? FW_SEMIBOLD :
707 style->font_weight.value == SP_CSS_FONT_WEIGHT_700 ? FW_BOLD :
708 style->font_weight.value == SP_CSS_FONT_WEIGHT_800 ? FW_EXTRABOLD :
709 style->font_weight.value == SP_CSS_FONT_WEIGHT_900 ? FW_HEAVY :
710 style->font_weight.value == SP_CSS_FONT_WEIGHT_NORMAL ? FW_NORMAL :
711 style->font_weight.value == SP_CSS_FONT_WEIGHT_BOLD ? FW_BOLD :
712 style->font_weight.value == SP_CSS_FONT_WEIGHT_LIGHTER ? FW_EXTRALIGHT :
713 style->font_weight.value == SP_CSS_FONT_WEIGHT_BOLDER ? FW_EXTRABOLD :
714 FW_NORMAL;
715 lf->lfItalic = (style->font_style.value == SP_CSS_FONT_STYLE_ITALIC);
716 lf->lfUnderline = style->text_decoration.underline;
717 lf->lfStrikeOut = style->text_decoration.line_through;
718 lf->lfCharSet = DEFAULT_CHARSET;
719 lf->lfOutPrecision = OUT_DEFAULT_PRECIS;
720 lf->lfClipPrecision = CLIP_DEFAULT_PRECIS;
721 lf->lfQuality = DEFAULT_QUALITY;
722 lf->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
724 strncpy(lf->lfFaceName, (char*) style->text->font_family.value, LF_FACESIZE-1);
726 hfont = CreateFontIndirectA(lf);
728 g_free(lf);
729 }
730 }
732 HFONT hfontOld = (HFONT) SelectObject(hdc, hfont);
734 float rgb[3];
735 sp_color_get_rgb_floatv( &style->fill.value.color, rgb );
736 SetTextColor(hdc, RGB(255*rgb[0], 255*rgb[1], 255*rgb[2]));
738 int align =
739 style->text_align.value == SP_CSS_TEXT_ALIGN_RIGHT ? TA_RIGHT :
740 style->text_align.value == SP_CSS_TEXT_ALIGN_CENTER ? TA_CENTER : TA_LEFT;
741 SetTextAlign(hdc, TA_BASELINE | align);
743 p = p * text_transform;
744 p[NR::X] = (p[NR::X] * IN_PER_PX * dwDPI);
745 p[NR::Y] = (p[NR::Y] * IN_PER_PX * dwDPI);
747 if (PrintWin32::is_os_wide()) {
748 gunichar2 *unicode_text = g_utf8_to_utf16( text, -1, NULL, NULL, NULL );
749 TextOutW(hdc, p[NR::X], p[NR::Y], (WCHAR*)unicode_text, wcslen((wchar_t*)unicode_text));
750 }
751 else {
752 TextOutA(hdc, p[NR::X], p[NR::Y], (CHAR*)text, strlen((char*)text));
753 }
755 SelectObject(hdc, hfontOld);
756 DeleteObject(hfont);
758 return 0;
762 return 0;
763 }
765 void
766 PrintEmfWin32::init (void)
767 {
768 Inkscape::Extension::Extension * ext;
770 /* EMF print */
771 ext = Inkscape::Extension::build_from_mem(
772 "<inkscape-extension>\n"
773 "<name>Enhanced Metafile Print</name>\n"
774 "<id>org.inkscape.print.emf.win32</id>\n"
775 "<param name=\"destination\" type=\"string\"></param>\n"
776 "<param name=\"textToPath\" type=\"boolean\">TRUE</param>\n"
777 "<param name=\"pageBoundingBox\" type=\"boolean\">TRUE</param>\n"
778 "<print/>\n"
779 "</inkscape-extension>", new PrintEmfWin32());
781 return;
782 }
785 } /* namespace Internal */
786 } /* namespace Extension */
787 } /* namespace Inkscape */
789 #endif /* WIN32 */
791 /*
792 Local Variables:
793 mode:c++
794 c-file-style:"stroustrup"
795 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
796 indent-tabs-mode:nil
797 fill-column:99
798 End:
799 */
800 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :