Code

6b2fd912c455098c4ce6b8ac97614d21c13e0bc5
[inkscape.git] / src / extension / internal / emf-win32-print.cpp
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;
111 unsigned int
112 PrintEmfWin32::setup (Inkscape::Extension::Print *mod)
114     return TRUE;
118 unsigned int
119 PrintEmfWin32::begin (Inkscape::Extension::Print *mod, SPDocument *doc)
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;
212 unsigned int
213 PrintEmfWin32::finish (Inkscape::Extension::Print *mod)
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;
231 unsigned int
232 PrintEmfWin32::comment (Inkscape::Extension::Print * module,
233                                 const char *comment)
235     if (!hdc) return 0;
237     flush_fill(); // flush any pending fills
239     return 0;
243 int
244 PrintEmfWin32::create_brush(SPStyle const *style)
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;
270 void
271 PrintEmfWin32::destroy_brush()
273     SelectObject( hdc, hbrushOld );
274     if (hbrush)
275         DeleteObject( hbrush );
276     hbrush = NULL;
277     hbrushOld = NULL;
281 void
282 PrintEmfWin32::create_pen(SPStyle const *style, const NRMatrix *transform)
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     }
401 void
402 PrintEmfWin32::destroy_pen()
404     SelectObject( hdc, hpenOld );
405     if (hpen)
406         DeleteObject( hpen );
407     hpen = NULL;
411 void
412 PrintEmfWin32::flush_fill()
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     }
424 NArtBpath *
425 PrintEmfWin32::copy_bpath(const NArtBpath *bp)
427     NArtBpath *tmp = (NArtBpath *) bp;
428     int num = 1;
429     
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;
444 int
445 PrintEmfWin32::cmp_bpath(const NArtBpath *bp1, const NArtBpath *bp2)
447     if (!bp1 || !bp2) {
448         return 1;
449     }
450     
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         }
465         
466         bp1 += 1;
467         bp2 += 1;
468     }
469     
470     return bp1->code != NR_END || bp2->code != NR_END;
473 unsigned int
474 PrintEmfWin32::bind(Inkscape::Extension::Print *mod, NRMatrix const *transform, float opacity)
476     text_transform = *transform;
477     return 0;
480 unsigned int
481 PrintEmfWin32::release(Inkscape::Extension::Print *mod)
483     return 0;
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)
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;
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)
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;
550 unsigned int
551 PrintEmfWin32::print_bpath(const NArtBpath *bp, const NRMatrix *transform, NRRect const *pbox)
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;
625 bool
626 PrintEmfWin32::textToPath(Inkscape::Extension::Print * ext)
628     return ext->get_param_bool("textToPath");
631 unsigned int
632 PrintEmfWin32::text(Inkscape::Extension::Print *mod, char const *text, NR::Point p,
633               SPStyle const *const style)
635     if (!hdc) return 0;
637     HFONT hfont = NULL;
638     
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);
655             
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;
683             
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);
687             
688             hfont = CreateFontIndirectW(lf);
689             
690             g_free(lf);
691         }
692         else {
693             LOGFONTA *lf = (LOGFONTA*)g_malloc(sizeof(LOGFONTA));
694             g_assert(lf != NULL);
695             
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;
723             
724             strncpy(lf->lfFaceName, (char*) style->text->font_family.value, LF_FACESIZE-1);
726             hfont = CreateFontIndirectA(lf);
727             
728             g_free(lf);
729         }
730     }
731         
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);
757     
758     return 0;
762     return 0;
765 void
766 PrintEmfWin32::init (void)
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;
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 :