~valavanisalex/ubuntu/oneiric/inkscape/inkscape_0.48.1-2ubuntu4

« back to all changes in this revision

Viewing changes to src/extension/internal/emf-win32-print.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Kees Cook, Kees Cook, Ted Gould
  • Date: 2008-02-10 14:20:16 UTC
  • mfrom: (1.1.6 upstream)
  • Revision ID: james.westby@ubuntu.com-20080210142016-vcnb2zqyhszu0xvb
Tags: 0.46~pre1-0ubuntu1
[ Kees Cook ]
* debian/control:
  - add libgtkspell-dev build-dep to gain GtkSpell features (LP: #183547).
  - update Standards version (no changes needed).
  - add Vcs and Homepage fields.
  - switch to new python-lxml dep.
* debian/{control,rules}: switch from dpatch to quilt for more sanity.
* debian/patches/20_fix_glib_and_gxx43_ftbfs.patch:
  - merged against upstream fixes.
  - added additional fixes for newly written code.
* debian/rules: enable parallel building.

[ Ted Gould ]
* Updating POTFILES.in to make it so things build correctly.
* debian/control:
  - add ImageMagick++ and libboost-dev to build-deps

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
 
 */
23
 
 
24
 
#ifdef WIN32
25
 
 
26
 
#ifdef HAVE_CONFIG_H
27
 
# include "config.h"
28
 
#endif
29
 
 
30
 
#include <string.h>
31
 
#include <signal.h>
32
 
#include <errno.h>
33
 
 
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"
43
 
 
44
 
#include "glib.h"
45
 
#include "gtk/gtkdialog.h"
46
 
#include "gtk/gtkbox.h"
47
 
#include "gtk/gtkstock.h"
48
 
 
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"
55
 
 
56
 
#include "win32.h"
57
 
#include "emf-win32-print.h"
58
 
 
59
 
#include "unit-constants.h"
60
 
 
61
 
#include "extension/extension.h"
62
 
#include "extension/system.h"
63
 
#include "extension/print.h"
64
 
 
65
 
#include "io/sys.h"
66
 
 
67
 
#include "macros.h"
68
 
 
69
 
#define WIN32_LEAN_AND_MEAN
70
 
#include <windows.h>
71
 
 
72
 
namespace Inkscape {
73
 
namespace Extension {
74
 
namespace Internal {
75
 
 
76
 
static float dwDPI = 2540;
77
 
 
78
 
 
79
 
PrintEmfWin32::PrintEmfWin32 (void):
80
 
    hdc(NULL),
81
 
    hbrush(NULL),
82
 
    hpen(NULL),
83
 
    fill_path(NULL)
84
 
{
85
 
}
86
 
 
87
 
 
88
 
PrintEmfWin32::~PrintEmfWin32 (void)
89
 
{
90
 
    if (hdc) {
91
 
        HENHMETAFILE metafile = CloseEnhMetaFile( hdc );
92
 
        if ( metafile ) {
93
 
            DeleteEnhMetaFile( metafile );
94
 
        }
95
 
        DeleteDC( hdc );
96
 
    }
97
 
 
98
 
    /* restore default signal handling for SIGPIPE */
99
 
#if !defined(_WIN32) && !defined(__WIN32__)
100
 
    (void) signal(SIGPIPE, SIG_DFL);
101
 
#endif
102
 
        return;
103
 
}
104
 
 
105
 
 
106
 
unsigned int
107
 
PrintEmfWin32::setup (Inkscape::Extension::Print *mod)
108
 
{
109
 
    return TRUE;
110
 
}
111
 
 
112
 
 
113
 
unsigned int
114
 
PrintEmfWin32::begin (Inkscape::Extension::Print *mod, SPDocument *doc)
115
 
{
116
 
    gchar const *utf8_fn = mod->get_param_string("destination");
117
 
 
118
 
    gsize bytesRead = 0;
119
 
    gsize bytesWritten = 0;
120
 
    GError* error = NULL;
121
 
    gchar *local_fn =
122
 
        g_filename_from_utf8( utf8_fn, -1,  &bytesRead,  &bytesWritten, &error );
123
 
 
124
 
    if (local_fn == NULL) {
125
 
        return 1;
126
 
    }
127
 
 
128
 
    CHAR *ansi_uri = (CHAR *) local_fn;
129
 
    gunichar2 *unicode_fn = g_utf8_to_utf16( local_fn, -1, NULL, NULL, NULL );
130
 
    WCHAR *unicode_uri = (WCHAR *) unicode_fn;
131
 
 
132
 
    // width and height in px
133
 
    _width = sp_document_width(doc);
134
 
    _height = sp_document_height(doc);
135
 
 
136
 
    NRRect d;
137
 
    bool pageBoundingBox;
138
 
    pageBoundingBox = mod->get_param_bool("pageBoundingBox");
139
 
    if (pageBoundingBox) {
140
 
        d.x0 = d.y0 = 0;
141
 
        d.x1 = _width;
142
 
        d.y1 = _height;
143
 
    } else {
144
 
        SPItem* doc_item = SP_ITEM(sp_document_root(doc));
145
 
        sp_item_invoke_bbox(doc_item, &d, sp_item_i2r_affine(doc_item), TRUE);
146
 
    }
147
 
 
148
 
    d.x0 *= IN_PER_PX;
149
 
    d.y0 *= IN_PER_PX;
150
 
    d.x1 *= IN_PER_PX;
151
 
    d.y1 *= IN_PER_PX;
152
 
 
153
 
    float dwInchesX = (d.x1 - d.x0);
154
 
    float dwInchesY = (d.y1 - d.y0);
155
 
 
156
 
    // dwInchesX x dwInchesY in .01mm units
157
 
    SetRect( &rc, 0, 0, (int) ceil(dwInchesX*2540), (int) ceil(dwInchesY*2540) );
158
 
 
159
 
    // Get a Reference DC
160
 
    HDC hScreenDC = GetDC( NULL );
161
 
 
162
 
    // Get the physical characteristics of the reference DC
163
 
    float PixelsX = (float) GetDeviceCaps( hScreenDC, HORZRES );
164
 
    float PixelsY = (float) GetDeviceCaps( hScreenDC, VERTRES );
165
 
    float MMX = (float) GetDeviceCaps( hScreenDC, HORZSIZE );
166
 
    float MMY = (float) GetDeviceCaps( hScreenDC, VERTSIZE );
167
 
 
168
 
    // Create the Metafile
169
 
    if (PrintWin32::is_os_wide())
170
 
        hdc = CreateEnhMetaFileW( hScreenDC, unicode_uri, &rc, NULL );
171
 
    else
172
 
        hdc = CreateEnhMetaFileA( hScreenDC, ansi_uri, &rc, NULL );
173
 
 
174
 
    // Release the reference DC
175
 
    ReleaseDC( NULL, hScreenDC );
176
 
 
177
 
    // Did we get a good metafile?
178
 
    if (hdc == NULL)
179
 
    {
180
 
        g_free(local_fn);
181
 
        g_free(unicode_fn);
182
 
        return 1;
183
 
    }
184
 
 
185
 
    // Anisotropic mapping mode
186
 
    SetMapMode( hdc, MM_ANISOTROPIC );
187
 
 
188
 
    // Set the Windows extent
189
 
    SetWindowExtEx( hdc, (int) (dwInchesX*dwDPI), (int) (dwInchesY*dwDPI), NULL );
190
 
 
191
 
    // Set the viewport extent to reflect
192
 
    // dwInchesX" x dwInchesY" in device units
193
 
    SetViewportExtEx( hdc,
194
 
                      (int) ((float) dwInchesX*25.4f*PixelsX/MMX),
195
 
                      (int) ((float) dwInchesY*25.4f*PixelsY/MMY),
196
 
                      NULL );
197
 
 
198
 
    SetRect( &rc, 0, 0, (int) ceil(dwInchesX*dwDPI), (int) ceil(dwInchesY*dwDPI) );
199
 
 
200
 
    g_free(local_fn);
201
 
    g_free(unicode_fn);
202
 
 
203
 
    return 0;
204
 
}
205
 
 
206
 
 
207
 
unsigned int
208
 
PrintEmfWin32::finish (Inkscape::Extension::Print *mod)
209
 
{
210
 
    if (!hdc) return 0;
211
 
 
212
 
    flush_fill(); // flush any pending fills
213
 
 
214
 
    HENHMETAFILE metafile = CloseEnhMetaFile( hdc );
215
 
    if ( metafile ) {
216
 
        DeleteEnhMetaFile( metafile );
217
 
    }
218
 
    DeleteDC( hdc );
219
 
 
220
 
    hdc = NULL;
221
 
 
222
 
    return 0;
223
 
}
224
 
 
225
 
 
226
 
unsigned int
227
 
PrintEmfWin32::comment (Inkscape::Extension::Print * module,
228
 
                                const char *comment)
229
 
{
230
 
    if (!hdc) return 0;
231
 
 
232
 
    flush_fill(); // flush any pending fills
233
 
 
234
 
    return 0;
235
 
}
236
 
 
237
 
 
238
 
void
239
 
PrintEmfWin32::create_brush(SPStyle const *style)
240
 
{
241
 
    float rgb[3];
242
 
 
243
 
    if (style) {
244
 
        sp_color_get_rgb_floatv( &style->fill.value.color, rgb );
245
 
        hbrush = CreateSolidBrush( RGB(255*rgb[0], 255*rgb[1], 255*rgb[2]) );
246
 
        hbrushOld = (HBRUSH) SelectObject( hdc, hbrush );
247
 
 
248
 
        SetPolyFillMode( hdc,
249
 
                         style->fill_rule.computed == 0 ? WINDING :
250
 
                         style->fill_rule.computed == 2 ? ALTERNATE : ALTERNATE );
251
 
    } else { // if (!style)
252
 
        hbrush = CreateSolidBrush( RGB(255, 255, 255) );
253
 
        hbrushOld = (HBRUSH) SelectObject( hdc, hbrush );
254
 
        SetPolyFillMode( hdc, ALTERNATE );
255
 
    }
256
 
}
257
 
 
258
 
 
259
 
void
260
 
PrintEmfWin32::destroy_brush()
261
 
{
262
 
    SelectObject( hdc, hbrushOld );
263
 
    if (hbrush)
264
 
        DeleteObject( hbrush );
265
 
    hbrush = NULL;
266
 
}
267
 
 
268
 
 
269
 
void
270
 
PrintEmfWin32::create_pen(SPStyle const *style)
271
 
{
272
 
    if (style) {
273
 
        float rgb[3];
274
 
 
275
 
        sp_color_get_rgb_floatv(&style->stroke.value.color, rgb);
276
 
 
277
 
        LOGBRUSH lb = {0};
278
 
        lb.lbStyle = BS_SOLID;
279
 
        lb.lbColor = RGB( 255*rgb[0], 255*rgb[1], 255*rgb[2] );
280
 
 
281
 
        int linestyle = PS_SOLID;
282
 
        int linecap = 0;
283
 
        int linejoin = 0;
284
 
        DWORD n_dash = 0;
285
 
        DWORD *dash = NULL;
286
 
        float oldmiterlimit;
287
 
 
288
 
        DWORD linewidth = MAX( 1, (DWORD) (style->stroke_width.computed * IN_PER_PX * dwDPI) );
289
 
 
290
 
        if (style->stroke_linecap.computed == 0) {
291
 
            linecap = PS_ENDCAP_FLAT;
292
 
        }
293
 
        else if (style->stroke_linecap.computed == 1) {
294
 
            linecap = PS_ENDCAP_ROUND;
295
 
        }
296
 
        else if (style->stroke_linecap.computed == 2) {
297
 
            linecap = PS_ENDCAP_SQUARE;
298
 
        }
299
 
 
300
 
        if (style->stroke_linejoin.computed == 0) {
301
 
            linejoin = PS_JOIN_MITER;
302
 
        }
303
 
        else if (style->stroke_linejoin.computed == 1) {
304
 
            linejoin = PS_JOIN_ROUND;
305
 
        }
306
 
        else if (style->stroke_linejoin.computed == 2) {
307
 
            linejoin = PS_JOIN_BEVEL;
308
 
        }
309
 
 
310
 
        if (style->stroke_dash.n_dash   &&
311
 
            style->stroke_dash.dash       )
312
 
        {
313
 
            int i = 0;
314
 
            while (linestyle != PS_USERSTYLE &&
315
 
                   (i < style->stroke_dash.n_dash)) {
316
 
                if (style->stroke_dash.dash[i] > 0.00000001)
317
 
                    linestyle = PS_USERSTYLE;
318
 
                i++;
319
 
            }
320
 
 
321
 
            if (linestyle == PS_USERSTYLE) {
322
 
                n_dash = style->stroke_dash.n_dash;
323
 
                dash = new DWORD[n_dash];
324
 
                for (i = 0; i < style->stroke_dash.n_dash; i++) {
325
 
                    dash[i] = (DWORD) (style->stroke_dash.dash[i] * IN_PER_PX * dwDPI);
326
 
                }
327
 
            }
328
 
        }
329
 
 
330
 
        hpen = ExtCreatePen(
331
 
            PS_GEOMETRIC | linestyle | linecap | linejoin,
332
 
            linewidth,
333
 
            &lb,
334
 
            n_dash,
335
 
            dash );
336
 
 
337
 
        if ( !hpen && linestyle == PS_USERSTYLE ) {
338
 
            hpen = ExtCreatePen(
339
 
                PS_GEOMETRIC | PS_SOLID | linecap | linejoin,
340
 
                linewidth,
341
 
                &lb,
342
 
                0,
343
 
                NULL );
344
 
        }
345
 
 
346
 
        if ( !hpen ) {
347
 
            hpen = CreatePen(
348
 
                PS_SOLID,
349
 
                linewidth,
350
 
                lb.lbColor );
351
 
        }
352
 
 
353
 
        hpenOld = (HPEN) SelectObject( hdc, hpen );
354
 
 
355
 
        if (linejoin == PS_JOIN_MITER) {
356
 
            float miterlimit = style->stroke_miterlimit.value;
357
 
            if (miterlimit < 1)
358
 
                miterlimit = 4.0;
359
 
            SetMiterLimit(
360
 
                hdc,
361
 
                miterlimit * IN_PER_PX * dwDPI,
362
 
                &oldmiterlimit );
363
 
        }
364
 
 
365
 
        if (n_dash) {
366
 
            delete[] dash;
367
 
        }
368
 
    }
369
 
    else { // if (!style)
370
 
        hpen = CreatePen( PS_SOLID, 1, RGB(0, 0, 0) );
371
 
        hpenOld = (HPEN) SelectObject( hdc, hpen );
372
 
    }
373
 
}
374
 
 
375
 
 
376
 
void
377
 
PrintEmfWin32::destroy_pen()
378
 
{
379
 
    SelectObject( hdc, hpenOld );
380
 
    if (hpen)
381
 
        DeleteObject( hpen );
382
 
    hpen = NULL;
383
 
}
384
 
 
385
 
 
386
 
void
387
 
PrintEmfWin32::flush_fill()
388
 
{
389
 
    if (fill_path) {
390
 
        print_bpath(fill_path, &fill_transform, &fill_pbox);
391
 
        FillPath( hdc );
392
 
        destroy_brush();
393
 
        delete[] fill_path;
394
 
        fill_path = NULL;
395
 
    }
396
 
}
397
 
 
398
 
 
399
 
NArtBpath *
400
 
PrintEmfWin32::copy_bpath(const NArtBpath *bp)
401
 
{
402
 
    NArtBpath *tmp = (NArtBpath *) bp;
403
 
    int num = 1;
404
 
    
405
 
    while (tmp->code != NR_END) {
406
 
        num++;
407
 
        tmp += 1;
408
 
    }
409
 
 
410
 
    tmp = new NArtBpath[num];
411
 
    while (num--) {
412
 
        tmp[num] = bp[num];
413
 
    }
414
 
 
415
 
    return tmp;
416
 
}
417
 
 
418
 
 
419
 
int
420
 
PrintEmfWin32::cmp_bpath(const NArtBpath *bp1, const NArtBpath *bp2)
421
 
{
422
 
    if (!bp1 || !bp2) {
423
 
        return 1;
424
 
    }
425
 
    
426
 
    while (bp1->code != NR_END && bp2->code != NR_END) {
427
 
        if (bp1->code != bp2->code) {
428
 
            return 1;
429
 
        }
430
 
 
431
 
        if ( fabs(bp1->x1 - bp2->x1) > 0.00000001 ||
432
 
             fabs(bp1->y1 - bp2->y1) > 0.00000001 ||
433
 
             fabs(bp1->x2 - bp2->x2) > 0.00000001 ||
434
 
             fabs(bp1->y2 - bp2->y2) > 0.00000001 ||
435
 
             fabs(bp1->x3 - bp2->x3) > 0.00000001 ||
436
 
             fabs(bp1->y3 - bp2->y3) > 0.00000001 )
437
 
        {
438
 
            return 1;
439
 
        }
440
 
        
441
 
        bp1 += 1;
442
 
        bp2 += 1;
443
 
    }
444
 
    
445
 
    return bp1->code != NR_END || bp2->code != NR_END;
446
 
}
447
 
 
448
 
 
449
 
unsigned int
450
 
PrintEmfWin32::fill(Inkscape::Extension::Print *mod,
451
 
               NRBPath const *bpath, NRMatrix const *transform, SPStyle const *style,
452
 
               NRRect const *pbox, NRRect const *dbox, NRRect const *bbox)
453
 
{
454
 
    if (!hdc) return 0;
455
 
 
456
 
    flush_fill(); // flush any pending fills
457
 
 
458
 
    if (style->fill.type == SP_PAINT_TYPE_COLOR) {
459
 
        create_brush(style);
460
 
    } else {
461
 
        // create_brush(NULL);
462
 
        return 0;
463
 
    }
464
 
 
465
 
    fill_path = copy_bpath( bpath->path );
466
 
    fill_transform = *transform;
467
 
    fill_pbox = *pbox;
468
 
 
469
 
    // postpone fill in case of stroke-and-fill
470
 
 
471
 
    return 0;
472
 
}
473
 
 
474
 
 
475
 
unsigned int
476
 
PrintEmfWin32::stroke (Inkscape::Extension::Print *mod,
477
 
                  const NRBPath *bpath, const NRMatrix *transform, const SPStyle *style,
478
 
                  const NRRect *pbox, const NRRect *dbox, const NRRect *bbox)
479
 
{
480
 
    if (!hdc) return 0;
481
 
 
482
 
    bool stroke_and_fill = ( cmp_bpath( bpath->path, fill_path ) == 0 );
483
 
 
484
 
    if (!stroke_and_fill) {
485
 
        flush_fill(); // flush any pending fills
486
 
    }
487
 
 
488
 
    if (style->stroke.type == SP_PAINT_TYPE_COLOR) {
489
 
        create_pen(style);
490
 
    } else {
491
 
        // create_pen(NULL);
492
 
        return 0;
493
 
    }
494
 
 
495
 
    print_bpath(bpath->path, transform, pbox);
496
 
 
497
 
    if (stroke_and_fill) {
498
 
        StrokeAndFillPath( hdc );
499
 
        destroy_brush();
500
 
        delete[] fill_path;
501
 
        fill_path = NULL;
502
 
    } else {
503
 
        StrokePath( hdc );
504
 
    }
505
 
 
506
 
    destroy_pen();
507
 
 
508
 
    return 0;
509
 
}
510
 
 
511
 
 
512
 
unsigned int
513
 
PrintEmfWin32::print_bpath(const NArtBpath *bp, const NRMatrix *transform, NRRect const *pbox)
514
 
{
515
 
    unsigned int closed;
516
 
    NR::Matrix tf = *transform;
517
 
 
518
 
    BeginPath( hdc );
519
 
    closed = FALSE;
520
 
    while (bp->code != NR_END) {
521
 
        using NR::X;
522
 
        using NR::Y;
523
 
 
524
 
        NR::Point p1(bp->c(1) * tf);
525
 
        NR::Point p2(bp->c(2) * tf);
526
 
        NR::Point p3(bp->c(3) * tf);
527
 
 
528
 
        p1[X] = (p1[X] * IN_PER_PX * dwDPI);
529
 
        p2[X] = (p2[X] * IN_PER_PX * dwDPI);
530
 
        p3[X] = (p3[X] * IN_PER_PX * dwDPI);
531
 
        p1[Y] = (p1[Y] * IN_PER_PX * dwDPI);
532
 
        p2[Y] = (p2[Y] * IN_PER_PX * dwDPI);
533
 
        p3[Y] = (p3[Y] * IN_PER_PX * dwDPI);
534
 
 
535
 
        LONG const x1 = (LONG) round(p1[X]);
536
 
        LONG const y1 = (LONG) round(rc.bottom-p1[Y]);
537
 
        LONG const x2 = (LONG) round(p2[X]);
538
 
        LONG const y2 = (LONG) round(rc.bottom-p2[Y]);
539
 
        LONG const x3 = (LONG) round(p3[X]);
540
 
        LONG const y3 = (LONG) round(rc.bottom-p3[Y]);
541
 
 
542
 
        switch (bp->code) {
543
 
            case NR_MOVETO:
544
 
                if (closed) {
545
 
                    CloseFigure( hdc );
546
 
                }
547
 
                closed = TRUE;
548
 
                MoveToEx( hdc, x3, y3, NULL );
549
 
                break;
550
 
            case NR_MOVETO_OPEN:
551
 
                if (closed) {
552
 
                    CloseFigure( hdc );
553
 
                }
554
 
                closed = FALSE;
555
 
                MoveToEx( hdc, x3, y3, NULL );
556
 
                break;
557
 
            case NR_LINETO:
558
 
                LineTo( hdc, x3, y3 );
559
 
                break;
560
 
            case NR_CURVETO:
561
 
            {
562
 
                POINT pt[3];
563
 
                pt[0].x = x1;
564
 
                pt[0].y = y1;
565
 
                pt[1].x = x2;
566
 
                pt[1].y = y2;
567
 
                pt[2].x = x3;
568
 
                pt[2].y = y3;
569
 
 
570
 
                PolyBezierTo( hdc, pt, 3 );
571
 
                break;
572
 
            }
573
 
            default:
574
 
                break;
575
 
        }
576
 
        bp += 1;
577
 
    }
578
 
    if (closed) {
579
 
        CloseFigure( hdc );
580
 
    }
581
 
    EndPath( hdc );
582
 
 
583
 
    return closed;
584
 
}
585
 
 
586
 
 
587
 
bool
588
 
PrintEmfWin32::textToPath(Inkscape::Extension::Print * ext)
589
 
{
590
 
    return ext->get_param_bool("textToPath");
591
 
}
592
 
 
593
 
 
594
 
void
595
 
PrintEmfWin32::init (void)
596
 
{
597
 
    Inkscape::Extension::Extension * ext;
598
 
 
599
 
    /* EMF print */
600
 
    ext = Inkscape::Extension::build_from_mem(
601
 
        "<inkscape-extension>\n"
602
 
        "<name>Enhanced Metafile Print</name>\n"
603
 
        "<id>org.inkscape.print.emf.win32</id>\n"
604
 
        "<param name=\"destination\" type=\"string\"></param>\n"
605
 
        "<param name=\"textToPath\" type=\"boolean\">TRUE</param>\n"
606
 
        "<param name=\"pageBoundingBox\" type=\"boolean\">TRUE</param>\n"
607
 
        "<print/>\n"
608
 
        "</inkscape-extension>", new PrintEmfWin32());
609
 
 
610
 
    return;
611
 
}
612
 
 
613
 
 
614
 
}  /* namespace Internal */
615
 
}  /* namespace Extension */
616
 
}  /* namespace Inkscape */
617
 
 
618
 
#endif /* WIN32 */
619
 
 
620
 
/*
621
 
  Local Variables:
622
 
  mode:c++
623
 
  c-file-style:"stroustrup"
624
 
  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
625
 
  indent-tabs-mode:nil
626
 
  fill-column:99
627
 
  End:
628
 
*/
629
 
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
 
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
 */
 
23
 
 
24
#ifdef WIN32
 
25
 
 
26
#ifdef HAVE_CONFIG_H
 
27
# include "config.h"
 
28
#endif
 
29
 
 
30
#include <string.h>
 
31
#include <signal.h>
 
32
#include <errno.h>
 
33
 
 
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"
 
43
 
 
44
#include "glib.h"
 
45
#include "gtk/gtkdialog.h"
 
46
#include "gtk/gtkbox.h"
 
47
#include "gtk/gtkstock.h"
 
48
 
 
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"
 
55
 
 
56
#include "FontFactory.h"
 
57
#include "libnrtype/font-instance.h"
 
58
#include "libnrtype/font-style-to-pos.h"
 
59
 
 
60
#include "win32.h"
 
61
#include "emf-win32-print.h"
 
62
 
 
63
#include "unit-constants.h"
 
64
 
 
65
#include "extension/extension.h"
 
66
#include "extension/system.h"
 
67
#include "extension/print.h"
 
68
 
 
69
#include "io/sys.h"
 
70
 
 
71
#include "macros.h"
 
72
 
 
73
#define WIN32_LEAN_AND_MEAN
 
74
#include <windows.h>
 
75
 
 
76
namespace Inkscape {
 
77
namespace Extension {
 
78
namespace Internal {
 
79
 
 
80
static float dwDPI = 2540;
 
81
 
 
82
 
 
83
PrintEmfWin32::PrintEmfWin32 (void):
 
84
    hdc(NULL),
 
85
    hbrush(NULL),
 
86
    hbrushOld(NULL),
 
87
    hpen(NULL),
 
88
    fill_path(NULL)
 
89
{
 
90
}
 
91
 
 
92
 
 
93
PrintEmfWin32::~PrintEmfWin32 (void)
 
94
{
 
95
    if (hdc) {
 
96
        HENHMETAFILE metafile = CloseEnhMetaFile( hdc );
 
97
        if ( metafile ) {
 
98
            DeleteEnhMetaFile( metafile );
 
99
        }
 
100
        DeleteDC( hdc );
 
101
    }
 
102
 
 
103
    /* restore default signal handling for SIGPIPE */
 
104
#if !defined(_WIN32) && !defined(__WIN32__)
 
105
    (void) signal(SIGPIPE, SIG_DFL);
 
106
#endif
 
107
        return;
 
108
}
 
109
 
 
110
 
 
111
unsigned int
 
112
PrintEmfWin32::setup (Inkscape::Extension::Print *mod)
 
113
{
 
114
    return TRUE;
 
115
}
 
116
 
 
117
 
 
118
unsigned int
 
119
PrintEmfWin32::begin (Inkscape::Extension::Print *mod, SPDocument *doc)
 
120
{
 
121
    gchar const *utf8_fn = mod->get_param_string("destination");
 
122
 
 
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 );
 
128
 
 
129
    if (local_fn == NULL) {
 
130
        return 1;
 
131
    }
 
132
 
 
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;
 
136
 
 
137
    // width and height in px
 
138
    _width = sp_document_width(doc);
 
139
    _height = sp_document_height(doc);
 
140
 
 
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
    }
 
152
 
 
153
    d.x0 *= IN_PER_PX;
 
154
    d.y0 *= IN_PER_PX;
 
155
    d.x1 *= IN_PER_PX;
 
156
    d.y1 *= IN_PER_PX;
 
157
 
 
158
    float dwInchesX = (d.x1 - d.x0);
 
159
    float dwInchesY = (d.y1 - d.y0);
 
160
 
 
161
    // dwInchesX x dwInchesY in .01mm units
 
162
    SetRect( &rc, 0, 0, (int) ceil(dwInchesX*2540), (int) ceil(dwInchesY*2540) );
 
163
 
 
164
    // Get a Reference DC
 
165
    HDC hScreenDC = GetDC( NULL );
 
166
 
 
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 );
 
172
 
 
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 );
 
178
 
 
179
    // Release the reference DC
 
180
    ReleaseDC( NULL, hScreenDC );
 
181
 
 
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
    }
 
189
 
 
190
    // Anisotropic mapping mode
 
191
    SetMapMode( hdc, MM_ANISOTROPIC );
 
192
 
 
193
    // Set the Windows extent
 
194
    SetWindowExtEx( hdc, (int) (dwInchesX*dwDPI), (int) (dwInchesY*dwDPI), NULL );
 
195
 
 
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 );
 
202
 
 
203
    SetRect( &rc, 0, 0, (int) ceil(dwInchesX*dwDPI), (int) ceil(dwInchesY*dwDPI) );
 
204
 
 
205
    g_free(local_fn);
 
206
    g_free(unicode_fn);
 
207
 
 
208
    return 0;
 
209
}
 
210
 
 
211
 
 
212
unsigned int
 
213
PrintEmfWin32::finish (Inkscape::Extension::Print *mod)
 
214
{
 
215
    if (!hdc) return 0;
 
216
 
 
217
    flush_fill(); // flush any pending fills
 
218
 
 
219
    HENHMETAFILE metafile = CloseEnhMetaFile( hdc );
 
220
    if ( metafile ) {
 
221
        DeleteEnhMetaFile( metafile );
 
222
    }
 
223
    DeleteDC( hdc );
 
224
 
 
225
    hdc = NULL;
 
226
 
 
227
    return 0;
 
228
}
 
229
 
 
230
 
 
231
unsigned int
 
232
PrintEmfWin32::comment (Inkscape::Extension::Print * module,
 
233
                                const char *comment)
 
234
{
 
235
    if (!hdc) return 0;
 
236
 
 
237
    flush_fill(); // flush any pending fills
 
238
 
 
239
    return 0;
 
240
}
 
241
 
 
242
 
 
243
int
 
244
PrintEmfWin32::create_brush(SPStyle const *style)
 
245
{
 
246
    float rgb[3];
 
247
 
 
248
    if (style) {
 
249
        float opacity = SP_SCALE24_TO_FLOAT(style->fill_opacity.value);
 
250
        if (opacity <= 0.0)
 
251
            return 1;
 
252
 
 
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 );
 
256
 
 
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
    }
 
265
 
 
266
    return 0;
 
267
}
 
268
 
 
269
 
 
270
void
 
271
PrintEmfWin32::destroy_brush()
 
272
{
 
273
    SelectObject( hdc, hbrushOld );
 
274
    if (hbrush)
 
275
        DeleteObject( hbrush );
 
276
    hbrush = NULL;
 
277
    hbrushOld = NULL;
 
278
}
 
279
 
 
280
 
 
281
void
 
282
PrintEmfWin32::create_pen(SPStyle const *style, const NRMatrix *transform)
 
283
{
 
284
    if (style) {
 
285
        float rgb[3];
 
286
 
 
287
        sp_color_get_rgb_floatv(&style->stroke.value.color, rgb);
 
288
 
 
289
        LOGBRUSH lb = {0};
 
290
        lb.lbStyle = BS_SOLID;
 
291
        lb.lbColor = RGB( 255*rgb[0], 255*rgb[1], 255*rgb[2] );
 
292
 
 
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;
 
299
 
 
300
        using NR::X;
 
301
        using NR::Y;
 
302
 
 
303
        NR::Matrix tf = *transform;
 
304
 
 
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);
 
310
 
 
311
        double scale = sqrt( (p[X]*p[X]) + (p[Y]*p[Y]) ) / sqrt(2);
 
312
 
 
313
        DWORD linewidth = MAX( 1, (DWORD) (scale * style->stroke_width.computed * IN_PER_PX * dwDPI) );
 
314
 
 
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
        }
 
324
 
 
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
        }
 
334
 
 
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
            }
 
345
 
 
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
        }
 
354
 
 
355
        hpen = ExtCreatePen(
 
356
            PS_GEOMETRIC | linestyle | linecap | linejoin,
 
357
            linewidth,
 
358
            &lb,
 
359
            n_dash,
 
360
            dash );
 
361
 
 
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
        }
 
370
 
 
371
        if ( !hpen ) {
 
372
            hpen = CreatePen(
 
373
                PS_SOLID,
 
374
                linewidth,
 
375
                lb.lbColor );
 
376
        }
 
377
 
 
378
        hpenOld = (HPEN) SelectObject( hdc, hpen );
 
379
 
 
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
        }
 
389
 
 
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
}
 
399
 
 
400
 
 
401
void
 
402
PrintEmfWin32::destroy_pen()
 
403
{
 
404
    SelectObject( hdc, hpenOld );
 
405
    if (hpen)
 
406
        DeleteObject( hpen );
 
407
    hpen = NULL;
 
408
}
 
409
 
 
410
 
 
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
}
 
422
 
 
423
 
 
424
NArtBpath *
 
425
PrintEmfWin32::copy_bpath(const NArtBpath *bp)
 
426
{
 
427
    NArtBpath *tmp = (NArtBpath *) bp;
 
428
    int num = 1;
 
429
    
 
430
    while (tmp->code != NR_END) {
 
431
        num++;
 
432
        tmp += 1;
 
433
    }
 
434
 
 
435
    tmp = new NArtBpath[num];
 
436
    while (num--) {
 
437
        tmp[num] = bp[num];
 
438
    }
 
439
 
 
440
    return tmp;
 
441
}
 
442
 
 
443
 
 
444
int
 
445
PrintEmfWin32::cmp_bpath(const NArtBpath *bp1, const NArtBpath *bp2)
 
446
{
 
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
        }
 
455
 
 
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;
 
471
}
 
472
 
 
473
unsigned int
 
474
PrintEmfWin32::bind(Inkscape::Extension::Print *mod, NRMatrix const *transform, float opacity)
 
475
{
 
476
    text_transform = *transform;
 
477
    return 0;
 
478
}
 
479
 
 
480
unsigned int
 
481
PrintEmfWin32::release(Inkscape::Extension::Print *mod)
 
482
{
 
483
    return 0;
 
484
}
 
485
 
 
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;
 
492
 
 
493
    flush_fill(); // flush any pending fills
 
494
 
 
495
    if (style->fill.isColor()) {
 
496
        if (create_brush(style))
 
497
            return 0;
 
498
    } else {
 
499
        // create_brush(NULL);
 
500
        return 0;
 
501
    }
 
502
 
 
503
    fill_path = copy_bpath( bpath->path );
 
504
    fill_transform = *transform;
 
505
    fill_pbox = *pbox;
 
506
 
 
507
    // postpone fill in case of stroke-and-fill
 
508
 
 
509
    return 0;
 
510
}
 
511
 
 
512
 
 
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;
 
519
 
 
520
    bool stroke_and_fill = ( cmp_bpath( bpath->path, fill_path ) == 0 );
 
521
 
 
522
    if (!stroke_and_fill) {
 
523
        flush_fill(); // flush any pending fills
 
524
    }
 
525
 
 
526
    if (style->stroke.isColor()) {
 
527
        create_pen(style, transform);
 
528
    } else {
 
529
        // create_pen(NULL, transform);
 
530
        return 0;
 
531
    }
 
532
 
 
533
    print_bpath(bpath->path, transform, pbox);
 
534
 
 
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
    }
 
543
 
 
544
    destroy_pen();
 
545
 
 
546
    return 0;
 
547
}
 
548
 
 
549
 
 
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;
 
555
 
 
556
    BeginPath( hdc );
 
557
    closed = FALSE;
 
558
    while (bp->code != NR_END) {
 
559
        using NR::X;
 
560
        using NR::Y;
 
561
 
 
562
        NR::Point p1(bp->c(1) * tf);
 
563
        NR::Point p2(bp->c(2) * tf);
 
564
        NR::Point p3(bp->c(3) * tf);
 
565
 
 
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);
 
572
 
 
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]);
 
579
 
 
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;
 
607
 
 
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 );
 
620
 
 
621
    return closed;
 
622
}
 
623
 
 
624
 
 
625
bool
 
626
PrintEmfWin32::textToPath(Inkscape::Extension::Print * ext)
 
627
{
 
628
    return ext->get_param_bool("textToPath");
 
629
}
 
630
 
 
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;
 
636
 
 
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
 
650
 
 
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);
 
725
 
 
726
            hfont = CreateFontIndirectA(lf);
 
727
            
 
728
            g_free(lf);
 
729
        }
 
730
    }
 
731
        
 
732
    HFONT hfontOld = (HFONT) SelectObject(hdc, hfont);
 
733
 
 
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]));
 
737
 
 
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);
 
742
 
 
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);
 
746
 
 
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
    }
 
754
 
 
755
    SelectObject(hdc, hfontOld);
 
756
    DeleteObject(hfont);
 
757
    
 
758
    return 0;
 
759
 
 
760
 
 
761
 
 
762
    return 0;
 
763
}
 
764
 
 
765
void
 
766
PrintEmfWin32::init (void)
 
767
{
 
768
    Inkscape::Extension::Extension * ext;
 
769
 
 
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());
 
780
 
 
781
    return;
 
782
}
 
783
 
 
784
 
 
785
}  /* namespace Internal */
 
786
}  /* namespace Extension */
 
787
}  /* namespace Inkscape */
 
788
 
 
789
#endif /* WIN32 */
 
790
 
 
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 :