~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, Ted Gould, Kees Cook
  • Date: 2009-06-24 14:00:43 UTC
  • mfrom: (1.1.8 upstream)
  • Revision ID: james.westby@ubuntu.com-20090624140043-07stp20mry48hqup
Tags: 0.47~pre0-0ubuntu1
* New upstream release

[ Ted Gould ]
* debian/control: Adding libgsl0 and removing version specifics on boost

[ Kees Cook ]
* debian/watch: updated to run uupdate and mangle pre-release versions.
* Dropped patches that have been taken upstream:
  - 01_mips
  - 02-poppler-0.8.3
  - 03-chinese-inkscape
  - 05_fix_latex_patch
  - 06_gcc-4.4
  - 07_cdr2svg
  - 08_skip-bad-utf-on-pdf-import
  - 09_gtk-clist
  - 10_belarussian
  - 11_libpng
  - 12_desktop
  - 13_slider
  - 100_svg_import_improvements
  - 102_sp_pattern_painter_free
  - 103_bitmap_type_print

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/** \file
2
 
 * Enhanced Metafile Printing.
 
1
/** @file
 
2
 * @brief Enhanced Metafile printing
3
3
 */
4
 
/*
5
 
 * Authors:
 
4
/* Authors:
6
5
 *   Ulf Erikson <ulferikson@users.sf.net>
7
6
 *
8
 
 * Copyright (C) 2006 Authors
 
7
 * Copyright (C) 2006-2009 Authors
9
8
 *
10
9
 * Released under GNU GPL, read the file 'COPYING' for more information
11
10
 */
27
26
# include "config.h"
28
27
#endif
29
28
 
30
 
#include <string.h>
31
 
#include <signal.h>
32
 
#include <errno.h>
 
29
//#include <string.h>
 
30
//#include <signal.h>
 
31
//#include <errno.h>
33
32
 
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"
 
33
#include <2geom/pathvector.h>
 
34
#include <2geom/rect.h>
 
35
#include <2geom/bezier-curve.h>
 
36
#include <2geom/hvlinesegment.h>
 
37
#include "helper/geom.h"
 
38
#include "helper/geom-curves.h"
 
39
//#include "display/canvas-bpath.h"
42
40
#include "sp-item.h"
43
41
 
44
 
#include "glib.h"
45
 
#include "gtk/gtkdialog.h"
46
 
#include "gtk/gtkbox.h"
47
 
#include "gtk/gtkstock.h"
 
42
//#include "glib.h"
 
43
//#include "gtk/gtkdialog.h"
 
44
//#include "gtk/gtkbox.h"
 
45
//#include "gtk/gtkstock.h"
48
46
 
49
 
#include "glibmm/i18n.h"
50
 
#include "enums.h"
51
 
#include "document.h"
 
47
//#include "glibmm/i18n.h"
 
48
//#include "enums.h"
 
49
//#include "document.h"
52
50
#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"
 
51
//#include "sp-paint-server.h"
 
52
#include "inkscape-version.h"
 
53
 
 
54
//#include "libnrtype/FontFactory.h"
 
55
//#include "libnrtype/font-instance.h"
 
56
//#include "libnrtype/font-style-to-pos.h"
 
57
 
 
58
#define WIN32_LEAN_AND_MEAN
 
59
#include <windows.h>
59
60
 
60
61
#include "win32.h"
61
62
#include "emf-win32-print.h"
62
63
 
63
64
#include "unit-constants.h"
64
65
 
65
 
#include "extension/extension.h"
 
66
//#include "extension/extension.h"
66
67
#include "extension/system.h"
67
68
#include "extension/print.h"
68
69
 
69
 
#include "io/sys.h"
70
 
 
71
 
#include "macros.h"
72
 
 
73
 
#define WIN32_LEAN_AND_MEAN
74
 
#include <windows.h>
 
70
//#include "io/sys.h"
 
71
 
 
72
//#include "macros.h"
75
73
 
76
74
namespace Inkscape {
77
75
namespace Extension {
85
83
    hbrush(NULL),
86
84
    hbrushOld(NULL),
87
85
    hpen(NULL),
88
 
    fill_path(NULL)
 
86
    stroke_and_fill(false),
 
87
    fill_only(false),
 
88
    simple_shape(false)
89
89
{
90
90
}
91
91
 
104
104
#if !defined(_WIN32) && !defined(__WIN32__)
105
105
    (void) signal(SIGPIPE, SIG_DFL);
106
106
#endif
107
 
        return;
 
107
    return;
108
108
}
109
109
 
110
110
 
111
111
unsigned int
112
 
PrintEmfWin32::setup (Inkscape::Extension::Print *mod)
 
112
PrintEmfWin32::setup (Inkscape::Extension::Print * /*mod*/)
113
113
{
114
114
    return TRUE;
115
115
}
147
147
        d.y1 = _height;
148
148
    } else {
149
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);
 
150
        sp_item_invoke_bbox(doc_item, &d, sp_item_i2d_affine(doc_item), TRUE);
151
151
    }
152
152
 
153
153
    d.x0 *= IN_PER_PX;
165
165
    HDC hScreenDC = GetDC( NULL );
166
166
 
167
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 );
 
168
    int PixelsX = GetDeviceCaps( hScreenDC, HORZRES );
 
169
    int PixelsY = GetDeviceCaps( hScreenDC, VERTRES );
 
170
    int MMX = GetDeviceCaps( hScreenDC, HORZSIZE );
 
171
    int MMY = GetDeviceCaps( hScreenDC, VERTSIZE );
172
172
 
 
173
    CHAR buff[1024];
 
174
    ZeroMemory(buff, sizeof(buff));
 
175
    snprintf(buff, sizeof(buff)-1, "Inkscape %s (%s)", Inkscape::version_string, __DATE__);
 
176
    INT len = strlen(buff);
 
177
    CHAR *p1 = strrchr(ansi_uri, '\\');
 
178
    CHAR *p2 = strrchr(ansi_uri, '/');
 
179
    CHAR *p = MAX(p1, p2);
 
180
    if (p)
 
181
        p++;
 
182
    else
 
183
        p = ansi_uri;
 
184
    snprintf(buff+len+1, sizeof(buff)-len-2, "%s", p);
 
185
    
173
186
    // 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 );
 
187
    if (PrintWin32::is_os_wide()) {
 
188
        WCHAR wbuff[1024];
 
189
        ZeroMemory(wbuff, sizeof(wbuff));
 
190
        MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, buff, sizeof(buff)/sizeof(buff[0]), wbuff, sizeof(wbuff)/sizeof(wbuff[0]));
 
191
        hdc = CreateEnhMetaFileW( hScreenDC, unicode_uri, &rc, wbuff );
 
192
    }
 
193
    else {
 
194
        hdc = CreateEnhMetaFileA( hScreenDC, ansi_uri, &rc, buff );
 
195
    }
178
196
 
179
197
    // Release the reference DC
180
198
    ReleaseDC( NULL, hScreenDC );
191
209
    SetMapMode( hdc, MM_ANISOTROPIC );
192
210
 
193
211
    // Set the Windows extent
194
 
    SetWindowExtEx( hdc, (int) (dwInchesX*dwDPI), (int) (dwInchesY*dwDPI), NULL );
 
212
    int windowextX = (int) ceil(dwInchesX*dwDPI);
 
213
    int windowextY = (int) ceil(dwInchesY*dwDPI);
 
214
    SetWindowExtEx( hdc, windowextX, windowextY, NULL );
195
215
 
196
216
    // Set the viewport extent to reflect
197
217
    // 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 );
 
218
    int viewportextX = (int)((float)dwInchesX*25.4f*(float)PixelsX/(float)MMX);
 
219
    int viewportextY = (int)((float)dwInchesY*25.4f*(float)PixelsY/(float)MMY);
 
220
    SetViewportExtEx( hdc, viewportextX, viewportextY, NULL );
 
221
 
 
222
    if (1) {
 
223
        snprintf(buff, sizeof(buff)-1, "Screen=%dx%dpx, %dx%dmm", PixelsX, PixelsY, MMX, MMY);
 
224
        GdiComment(hdc, strlen(buff), (BYTE*) buff);
 
225
 
 
226
        snprintf(buff, sizeof(buff)-1, "Drawing=%.1lfx%.1lfpx, %.1lfx%.1lfmm", _width, _height, dwInchesX * MM_PER_IN, dwInchesY * MM_PER_IN);
 
227
        GdiComment(hdc, strlen(buff), (BYTE*) buff);
 
228
    }
202
229
 
203
230
    SetRect( &rc, 0, 0, (int) ceil(dwInchesX*dwDPI), (int) ceil(dwInchesY*dwDPI) );
204
231
 
205
232
    g_free(local_fn);
206
233
    g_free(unicode_fn);
207
234
 
 
235
    m_tr_stack.push( Geom::Scale(1, -1) * Geom::Translate(0, sp_document_height(doc)));
 
236
 
208
237
    return 0;
209
238
}
210
239
 
211
240
 
212
241
unsigned int
213
 
PrintEmfWin32::finish (Inkscape::Extension::Print *mod)
 
242
PrintEmfWin32::finish (Inkscape::Extension::Print * /*mod*/)
214
243
{
215
244
    if (!hdc) return 0;
216
245
 
229
258
 
230
259
 
231
260
unsigned int
232
 
PrintEmfWin32::comment (Inkscape::Extension::Print * module,
233
 
                                const char *comment)
 
261
PrintEmfWin32::comment (Inkscape::Extension::Print * /*module*/,
 
262
                        const char * /*comment*/)
234
263
{
235
264
    if (!hdc) return 0;
236
265
 
279
308
 
280
309
 
281
310
void
282
 
PrintEmfWin32::create_pen(SPStyle const *style, const NRMatrix *transform)
 
311
PrintEmfWin32::create_pen(SPStyle const *style, const Geom::Matrix &transform)
283
312
{
284
313
    if (style) {
285
314
        float rgb[3];
286
315
 
287
316
        sp_color_get_rgb_floatv(&style->stroke.value.color, rgb);
288
317
 
289
 
        LOGBRUSH lb = {0};
 
318
        LOGBRUSH lb;
 
319
        ZeroMemory(&lb, sizeof(lb));
290
320
        lb.lbStyle = BS_SOLID;
291
321
        lb.lbColor = RGB( 255*rgb[0], 255*rgb[1], 255*rgb[2] );
292
322
 
295
325
        int linejoin = 0;
296
326
        DWORD n_dash = 0;
297
327
        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);
 
328
 
 
329
        using Geom::X;
 
330
        using Geom::Y;
 
331
 
 
332
        Geom::Point zero(0, 0);
 
333
        Geom::Point one(1, 1);
 
334
        Geom::Point p0(zero * transform);
 
335
        Geom::Point p1(one * transform);
 
336
        Geom::Point p(p1 - p0);
310
337
 
311
338
        double scale = sqrt( (p[X]*p[X]) + (p[Y]*p[Y]) ) / sqrt(2);
312
339
 
378
405
        hpenOld = (HPEN) SelectObject( hdc, hpen );
379
406
 
380
407
        if (linejoin == PS_JOIN_MITER) {
 
408
            float oldmiterlimit;
381
409
            float miterlimit = style->stroke_miterlimit.value;
 
410
 
 
411
            miterlimit = miterlimit * 10.0 / 4.0;
382
412
            if (miterlimit < 1)
383
 
                miterlimit = 4.0;
 
413
                miterlimit = 10.0;
 
414
 
 
415
            miterlimit = miterlimit * IN_PER_PX * dwDPI;
 
416
 
384
417
            SetMiterLimit(
385
418
                hdc,
386
 
                miterlimit * IN_PER_PX * dwDPI,
 
419
                miterlimit,
387
420
                &oldmiterlimit );
388
421
        }
389
422
 
411
444
void
412
445
PrintEmfWin32::flush_fill()
413
446
{
414
 
    if (fill_path) {
415
 
        print_bpath(fill_path, &fill_transform, &fill_pbox);
416
 
        FillPath( hdc );
 
447
    if (!fill_pathv.empty()) {
 
448
        stroke_and_fill = false;
 
449
        fill_only = true;
 
450
        print_pathv(fill_pathv, fill_transform);
 
451
        fill_only = false;
 
452
        if (!simple_shape)
 
453
            FillPath( hdc );
417
454
        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)
 
455
        fill_pathv.clear();
 
456
    }
 
457
}
 
458
 
 
459
unsigned int
 
460
PrintEmfWin32::bind(Inkscape::Extension::Print * /*mod*/, Geom::Matrix const *transform, float /*opacity*/)
 
461
{
 
462
    Geom::Matrix tr = *transform;
 
463
    
 
464
    if (m_tr_stack.size()) {
 
465
        Geom::Matrix tr_top = m_tr_stack.top();
 
466
        m_tr_stack.push(tr * tr_top);
 
467
    } else {
 
468
        m_tr_stack.push(tr);
 
469
    }
 
470
 
 
471
    return 1;
 
472
}
 
473
 
 
474
unsigned int
 
475
PrintEmfWin32::release(Inkscape::Extension::Print * /*mod*/)
 
476
{
 
477
    m_tr_stack.pop();
 
478
    return 1;
 
479
}
 
480
 
 
481
unsigned int
 
482
PrintEmfWin32::fill(Inkscape::Extension::Print * /*mod*/,
 
483
                    Geom::PathVector const &pathv, Geom::Matrix const * /*transform*/, SPStyle const *style,
 
484
                    NRRect const * /*pbox*/, NRRect const * /*dbox*/, NRRect const * /*bbox*/)
490
485
{
491
486
    if (!hdc) return 0;
492
487
 
 
488
    Geom::Matrix tf = m_tr_stack.top();
 
489
 
493
490
    flush_fill(); // flush any pending fills
494
491
 
495
492
    if (style->fill.isColor()) {
500
497
        return 0;
501
498
    }
502
499
 
503
 
    fill_path = copy_bpath( bpath->path );
504
 
    fill_transform = *transform;
505
 
    fill_pbox = *pbox;
 
500
    fill_pathv.clear();
 
501
    std::copy(pathv.begin(), pathv.end(), std::back_inserter(fill_pathv));
 
502
    fill_transform = tf;
506
503
 
507
504
    // postpone fill in case of stroke-and-fill
508
505
 
511
508
 
512
509
 
513
510
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)
 
511
PrintEmfWin32::stroke (Inkscape::Extension::Print * /*mod*/,
 
512
                       Geom::PathVector const &pathv, const Geom::Matrix * /*transform*/, const SPStyle *style,
 
513
                       const NRRect * /*pbox*/, const NRRect * /*dbox*/, const NRRect * /*bbox*/)
517
514
{
518
515
    if (!hdc) return 0;
519
516
 
520
 
    bool stroke_and_fill = ( cmp_bpath( bpath->path, fill_path ) == 0 );
 
517
    Geom::Matrix tf = m_tr_stack.top();
 
518
 
 
519
    stroke_and_fill = ( pathv == fill_pathv );
521
520
 
522
521
    if (!stroke_and_fill) {
523
522
        flush_fill(); // flush any pending fills
524
523
    }
525
524
 
526
525
    if (style->stroke.isColor()) {
527
 
        create_pen(style, transform);
 
526
        create_pen(style, tf);
528
527
    } else {
529
 
        // create_pen(NULL, transform);
 
528
        // create_pen(NULL, tf);
530
529
        return 0;
531
530
    }
532
531
 
533
 
    print_bpath(bpath->path, transform, pbox);
 
532
    print_pathv(pathv, tf);
534
533
 
535
534
    if (stroke_and_fill) {
536
 
        StrokeAndFillPath( hdc );
 
535
        if (!simple_shape)
 
536
            StrokeAndFillPath( hdc );
537
537
        destroy_brush();
538
 
        delete[] fill_path;
539
 
        fill_path = NULL;
 
538
        fill_pathv.clear();
540
539
    } else {
541
 
        StrokePath( hdc );
 
540
        if (!simple_shape)
 
541
            StrokePath( hdc );
542
542
    }
543
543
 
544
544
    destroy_pen();
547
547
}
548
548
 
549
549
 
 
550
bool
 
551
PrintEmfWin32::print_simple_shape(Geom::PathVector const &pathv, const Geom::Matrix &transform)
 
552
{
 
553
    Geom::PathVector pv = pathv_to_linear_and_cubic_beziers( pathv * transform );
 
554
    
 
555
    int nodes = 0;
 
556
    int moves = 0;
 
557
    int lines = 0;
 
558
    int curves = 0;
 
559
 
 
560
    for (Geom::PathVector::const_iterator pit = pv.begin(); pit != pv.end(); ++pit)
 
561
    {
 
562
        moves++;
 
563
        nodes++;
 
564
        
 
565
        for (Geom::Path::const_iterator cit = pit->begin(); cit != pit->end_open(); ++cit)
 
566
        {
 
567
            nodes++;
 
568
            
 
569
            if ( is_straight_curve(*cit) ) {
 
570
                lines++;
 
571
            }
 
572
            else if (Geom::CubicBezier const *cubic = dynamic_cast<Geom::CubicBezier const*>(&*cit)) {
 
573
                cubic = cubic;
 
574
                curves++;
 
575
            }
 
576
        }
 
577
    }
 
578
 
 
579
    if (!nodes)
 
580
        return false;
 
581
    
 
582
    POINT *lpPoints = new POINT[moves + lines + curves*3];
 
583
    int i = 0;
 
584
 
 
585
    /**
 
586
     * For all Subpaths in the <path>
 
587
     */      
 
588
    for (Geom::PathVector::const_iterator pit = pv.begin(); pit != pv.end(); ++pit)
 
589
    {
 
590
        using Geom::X;
 
591
        using Geom::Y;
 
592
 
 
593
        Geom::Point p0 = pit->initialPoint();
 
594
 
 
595
        p0[X] = (p0[X] * IN_PER_PX * dwDPI);
 
596
        p0[Y] = (p0[Y] * IN_PER_PX * dwDPI);
 
597
                
 
598
        LONG const x0 = (LONG) round(p0[X]);
 
599
        LONG const y0 = (LONG) round(rc.bottom-p0[Y]);
 
600
 
 
601
        lpPoints[i].x = x0;
 
602
        lpPoints[i].y = y0;
 
603
        i = i + 1;
 
604
 
 
605
        /**
 
606
         * For all segments in the subpath
 
607
         */
 
608
        for (Geom::Path::const_iterator cit = pit->begin(); cit != pit->end_open(); ++cit)
 
609
        {
 
610
            if ( is_straight_curve(*cit) )
 
611
            {
 
612
                //Geom::Point p0 = cit->initialPoint();
 
613
                Geom::Point p1 = cit->finalPoint();
 
614
 
 
615
                //p0[X] = (p0[X] * IN_PER_PX * dwDPI);
 
616
                p1[X] = (p1[X] * IN_PER_PX * dwDPI);
 
617
                //p0[Y] = (p0[Y] * IN_PER_PX * dwDPI);
 
618
                p1[Y] = (p1[Y] * IN_PER_PX * dwDPI);
 
619
                
 
620
                //LONG const x0 = (LONG) round(p0[X]);
 
621
                //LONG const y0 = (LONG) round(rc.bottom-p0[Y]);
 
622
                LONG const x1 = (LONG) round(p1[X]);
 
623
                LONG const y1 = (LONG) round(rc.bottom-p1[Y]);
 
624
 
 
625
                lpPoints[i].x = x1;
 
626
                lpPoints[i].y = y1;
 
627
                i = i + 1;
 
628
            }
 
629
            else if (Geom::CubicBezier const *cubic = dynamic_cast<Geom::CubicBezier const*>(&*cit))
 
630
            {
 
631
                std::vector<Geom::Point> points = cubic->points();
 
632
                //Geom::Point p0 = points[0];
 
633
                Geom::Point p1 = points[1];
 
634
                Geom::Point p2 = points[2];
 
635
                Geom::Point p3 = points[3];
 
636
 
 
637
                //p0[X] = (p0[X] * IN_PER_PX * dwDPI);
 
638
                p1[X] = (p1[X] * IN_PER_PX * dwDPI);
 
639
                p2[X] = (p2[X] * IN_PER_PX * dwDPI);
 
640
                p3[X] = (p3[X] * IN_PER_PX * dwDPI);
 
641
                //p0[Y] = (p0[Y] * IN_PER_PX * dwDPI);
 
642
                p1[Y] = (p1[Y] * IN_PER_PX * dwDPI);
 
643
                p2[Y] = (p2[Y] * IN_PER_PX * dwDPI);
 
644
                p3[Y] = (p3[Y] * IN_PER_PX * dwDPI);
 
645
                
 
646
                //LONG const x0 = (LONG) round(p0[X]);
 
647
                //LONG const y0 = (LONG) round(rc.bottom-p0[Y]);
 
648
                LONG const x1 = (LONG) round(p1[X]);
 
649
                LONG const y1 = (LONG) round(rc.bottom-p1[Y]);
 
650
                LONG const x2 = (LONG) round(p2[X]);
 
651
                LONG const y2 = (LONG) round(rc.bottom-p2[Y]);
 
652
                LONG const x3 = (LONG) round(p3[X]);
 
653
                LONG const y3 = (LONG) round(rc.bottom-p3[Y]);
 
654
 
 
655
                POINT pt[3];
 
656
                pt[0].x = x1;
 
657
                pt[0].y = y1;
 
658
                pt[1].x = x2;
 
659
                pt[1].y = y2;
 
660
                pt[2].x = x3;
 
661
                pt[2].y = y3;
 
662
 
 
663
                lpPoints[i].x = x1;
 
664
                lpPoints[i].y = y1;
 
665
                lpPoints[i+1].x = x2;
 
666
                lpPoints[i+1].y = y2;
 
667
                lpPoints[i+2].x = x3;
 
668
                lpPoints[i+2].y = y3;
 
669
                i = i + 3;
 
670
            }
 
671
        }
 
672
    }
 
673
 
 
674
    bool done = false;
 
675
    bool closed = (lpPoints[0].x == lpPoints[i-1].x) && (lpPoints[0].y == lpPoints[i-1].y);
 
676
    bool polygon = false;
 
677
    bool rectangle = false;
 
678
    bool ellipse = false;
 
679
    
 
680
    if (moves == 1 && moves+lines == nodes && closed) {
 
681
        polygon = true;
 
682
        if (nodes==5) {
 
683
            if (lpPoints[0].x == lpPoints[3].x && lpPoints[1].x == lpPoints[2].x &&
 
684
                lpPoints[0].y == lpPoints[1].y && lpPoints[2].y == lpPoints[3].y)
 
685
            {
 
686
                rectangle = true;
 
687
            }
 
688
        }
 
689
    }
 
690
    else if (moves == 1 && nodes == 5 && moves+curves == nodes && closed) {
 
691
        if (lpPoints[0].x == lpPoints[1].x && lpPoints[1].x == lpPoints[11].x &&
 
692
            lpPoints[5].x == lpPoints[6].x && lpPoints[6].x == lpPoints[7].x &&
 
693
            lpPoints[2].x == lpPoints[10].x && lpPoints[3].x == lpPoints[9].x && lpPoints[4].x == lpPoints[8].x &&
 
694
            lpPoints[2].y == lpPoints[3].y && lpPoints[3].y == lpPoints[4].y &&
 
695
            lpPoints[8].y == lpPoints[9].y && lpPoints[9].y == lpPoints[10].y &&
 
696
            lpPoints[5].y == lpPoints[1].y && lpPoints[6].y == lpPoints[0].y && lpPoints[7].y == lpPoints[11].y)
 
697
        {
 
698
            ellipse = true;
 
699
        }
 
700
    }
 
701
 
 
702
    if (polygon || ellipse) {
 
703
        HPEN hpenTmp = NULL;
 
704
        HPEN hpenOld = NULL;
 
705
        HBRUSH hbrushTmp = NULL;
 
706
        HBRUSH hbrushOld = NULL;
 
707
 
 
708
        if (!stroke_and_fill) {
 
709
            if (fill_only) {
 
710
                hpenTmp = (HPEN) GetStockObject(NULL_PEN);
 
711
                hpenOld = (HPEN) SelectObject( hdc, hpenTmp );
 
712
            }
 
713
            else { // if (stroke_only)
 
714
                hbrushTmp = (HBRUSH) GetStockObject(NULL_BRUSH);
 
715
                hbrushOld = (HBRUSH) SelectObject( hdc, hbrushTmp );
 
716
            }
 
717
        }
 
718
 
 
719
        if (polygon) {
 
720
            if (rectangle)
 
721
                Rectangle( hdc, lpPoints[0].x, lpPoints[0].y, lpPoints[2].x, lpPoints[2].y );
 
722
            else
 
723
                Polygon( hdc, lpPoints, nodes );
 
724
        }
 
725
        else if (ellipse) {
 
726
            Ellipse( hdc, lpPoints[6].x, lpPoints[3].y, lpPoints[0].x, lpPoints[9].y);
 
727
        }
 
728
        
 
729
        done = true;
 
730
 
 
731
        if (hpenOld)
 
732
            SelectObject( hdc, hpenOld );
 
733
        if (hpenTmp)
 
734
            DeleteObject( hpenTmp );
 
735
        if (hbrushOld)
 
736
            SelectObject( hdc, hbrushOld );
 
737
        if (hbrushTmp)
 
738
            DeleteObject( hbrushTmp );
 
739
    }
 
740
 
 
741
    delete[] lpPoints;
 
742
    
 
743
    return done;
 
744
}
 
745
 
550
746
unsigned int
551
 
PrintEmfWin32::print_bpath(const NArtBpath *bp, const NRMatrix *transform, NRRect const *pbox)
 
747
PrintEmfWin32::print_pathv(Geom::PathVector const &pathv, const Geom::Matrix &transform)
552
748
{
553
 
    unsigned int closed;
554
 
    NR::Matrix tf = *transform;
555
 
 
 
749
    simple_shape = print_simple_shape(pathv, transform);
 
750
 
 
751
    if (simple_shape)
 
752
        return TRUE;
 
753
 
 
754
    Geom::PathVector pv = pathv_to_linear_and_cubic_beziers( pathv * transform );
 
755
    
556
756
    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
 
            {
 
757
 
 
758
    /**
 
759
     * For all Subpaths in the <path>
 
760
     */      
 
761
    for (Geom::PathVector::const_iterator pit = pv.begin(); pit != pv.end(); ++pit)
 
762
    {
 
763
        using Geom::X;
 
764
        using Geom::Y;
 
765
 
 
766
        Geom::Point p0 = pit->initialPoint();
 
767
 
 
768
        p0[X] = (p0[X] * IN_PER_PX * dwDPI);
 
769
        p0[Y] = (p0[Y] * IN_PER_PX * dwDPI);
 
770
                
 
771
        LONG const x0 = (LONG) round(p0[X]);
 
772
        LONG const y0 = (LONG) round(rc.bottom-p0[Y]);
 
773
 
 
774
        MoveToEx( hdc, x0, y0, NULL );
 
775
 
 
776
        /**
 
777
         * For all segments in the subpath
 
778
         */
 
779
        for (Geom::Path::const_iterator cit = pit->begin(); cit != pit->end_open(); ++cit)
 
780
        {
 
781
            if ( is_straight_curve(*cit) )
 
782
            {
 
783
                //Geom::Point p0 = cit->initialPoint();
 
784
                Geom::Point p1 = cit->finalPoint();
 
785
 
 
786
                //p0[X] = (p0[X] * IN_PER_PX * dwDPI);
 
787
                p1[X] = (p1[X] * IN_PER_PX * dwDPI);
 
788
                //p0[Y] = (p0[Y] * IN_PER_PX * dwDPI);
 
789
                p1[Y] = (p1[Y] * IN_PER_PX * dwDPI);
 
790
                
 
791
                //LONG const x0 = (LONG) round(p0[X]);
 
792
                //LONG const y0 = (LONG) round(rc.bottom-p0[Y]);
 
793
                LONG const x1 = (LONG) round(p1[X]);
 
794
                LONG const y1 = (LONG) round(rc.bottom-p1[Y]);
 
795
 
 
796
                LineTo( hdc, x1, y1 );
 
797
            }
 
798
            else if (Geom::CubicBezier const *cubic = dynamic_cast<Geom::CubicBezier const*>(&*cit))
 
799
            {
 
800
                std::vector<Geom::Point> points = cubic->points();
 
801
                //Geom::Point p0 = points[0];
 
802
                Geom::Point p1 = points[1];
 
803
                Geom::Point p2 = points[2];
 
804
                Geom::Point p3 = points[3];
 
805
 
 
806
                //p0[X] = (p0[X] * IN_PER_PX * dwDPI);
 
807
                p1[X] = (p1[X] * IN_PER_PX * dwDPI);
 
808
                p2[X] = (p2[X] * IN_PER_PX * dwDPI);
 
809
                p3[X] = (p3[X] * IN_PER_PX * dwDPI);
 
810
                //p0[Y] = (p0[Y] * IN_PER_PX * dwDPI);
 
811
                p1[Y] = (p1[Y] * IN_PER_PX * dwDPI);
 
812
                p2[Y] = (p2[Y] * IN_PER_PX * dwDPI);
 
813
                p3[Y] = (p3[Y] * IN_PER_PX * dwDPI);
 
814
                
 
815
                //LONG const x0 = (LONG) round(p0[X]);
 
816
                //LONG const y0 = (LONG) round(rc.bottom-p0[Y]);
 
817
                LONG const x1 = (LONG) round(p1[X]);
 
818
                LONG const y1 = (LONG) round(rc.bottom-p1[Y]);
 
819
                LONG const x2 = (LONG) round(p2[X]);
 
820
                LONG const y2 = (LONG) round(rc.bottom-p2[Y]);
 
821
                LONG const x3 = (LONG) round(p3[X]);
 
822
                LONG const y3 = (LONG) round(rc.bottom-p3[Y]);
 
823
 
600
824
                POINT pt[3];
601
825
                pt[0].x = x1;
602
826
                pt[0].y = y1;
606
830
                pt[2].y = y3;
607
831
 
608
832
                PolyBezierTo( hdc, pt, 3 );
609
 
                break;
610
 
            }
611
 
            default:
612
 
                break;
613
 
        }
614
 
        bp += 1;
615
 
    }
616
 
    if (closed) {
617
 
        CloseFigure( hdc );
618
 
    }
 
833
            }
 
834
            else
 
835
            {
 
836
                g_warning("logical error, because pathv_to_linear_and_cubic_beziers was used");
 
837
            }
 
838
        }
 
839
 
 
840
        if (pit->end_default() == pit->end_closed()) {
 
841
            CloseFigure( hdc );
 
842
        }
 
843
    }
 
844
 
619
845
    EndPath( hdc );
620
846
 
621
 
    return closed;
 
847
    return TRUE;
622
848
}
623
849
 
624
850
 
629
855
}
630
856
 
631
857
unsigned int
632
 
PrintEmfWin32::text(Inkscape::Extension::Print *mod, char const *text, NR::Point p,
633
 
              SPStyle const *const style)
 
858
PrintEmfWin32::text(Inkscape::Extension::Print * /*mod*/, char const *text, Geom::Point p,
 
859
                    SPStyle const *const style)
634
860
{
635
861
    if (!hdc) return 0;
636
862
 
658
884
            lf->lfEscapement = 0;
659
885
            lf->lfOrientation = 0;
660
886
            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 :
 
887
                style->font_weight.computed == SP_CSS_FONT_WEIGHT_100 ? FW_THIN :
 
888
                style->font_weight.computed == SP_CSS_FONT_WEIGHT_200 ? FW_EXTRALIGHT :
 
889
                style->font_weight.computed == SP_CSS_FONT_WEIGHT_300 ? FW_LIGHT :
 
890
                style->font_weight.computed == SP_CSS_FONT_WEIGHT_400 ? FW_NORMAL :
 
891
                style->font_weight.computed == SP_CSS_FONT_WEIGHT_500 ? FW_MEDIUM :
 
892
                style->font_weight.computed == SP_CSS_FONT_WEIGHT_600 ? FW_SEMIBOLD :
 
893
                style->font_weight.computed == SP_CSS_FONT_WEIGHT_700 ? FW_BOLD :
 
894
                style->font_weight.computed == SP_CSS_FONT_WEIGHT_800 ? FW_EXTRABOLD :
 
895
                style->font_weight.computed == SP_CSS_FONT_WEIGHT_900 ? FW_HEAVY :
674
896
                FW_NORMAL;
675
 
            lf->lfItalic = (style->font_style.value == SP_CSS_FONT_STYLE_ITALIC);
 
897
            lf->lfItalic = (style->font_style.computed == SP_CSS_FONT_STYLE_ITALIC);
676
898
            lf->lfUnderline = style->text_decoration.underline;
677
899
            lf->lfStrikeOut = style->text_decoration.line_through;
678
900
            lf->lfCharSet = DEFAULT_CHARSET;
698
920
            lf->lfEscapement = 0;
699
921
            lf->lfOrientation = 0;
700
922
            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 :
 
923
                style->font_weight.computed == SP_CSS_FONT_WEIGHT_100 ? FW_THIN :
 
924
                style->font_weight.computed == SP_CSS_FONT_WEIGHT_200 ? FW_EXTRALIGHT :
 
925
                style->font_weight.computed == SP_CSS_FONT_WEIGHT_300 ? FW_LIGHT :
 
926
                style->font_weight.computed == SP_CSS_FONT_WEIGHT_400 ? FW_NORMAL :
 
927
                style->font_weight.computed == SP_CSS_FONT_WEIGHT_500 ? FW_MEDIUM :
 
928
                style->font_weight.computed == SP_CSS_FONT_WEIGHT_600 ? FW_SEMIBOLD :
 
929
                style->font_weight.computed == SP_CSS_FONT_WEIGHT_700 ? FW_BOLD :
 
930
                style->font_weight.computed == SP_CSS_FONT_WEIGHT_800 ? FW_EXTRABOLD :
 
931
                style->font_weight.computed == SP_CSS_FONT_WEIGHT_900 ? FW_HEAVY :
714
932
                FW_NORMAL;
715
 
            lf->lfItalic = (style->font_style.value == SP_CSS_FONT_STYLE_ITALIC);
 
933
            lf->lfItalic = (style->font_style.computed == SP_CSS_FONT_STYLE_ITALIC);
716
934
            lf->lfUnderline = style->text_decoration.underline;
717
935
            lf->lfStrikeOut = style->text_decoration.line_through;
718
936
            lf->lfCharSet = DEFAULT_CHARSET;
728
946
            g_free(lf);
729
947
        }
730
948
    }
731
 
        
 
949
    
732
950
    HFONT hfontOld = (HFONT) SelectObject(hdc, hfont);
733
951
 
734
952
    float rgb[3];
735
953
    sp_color_get_rgb_floatv( &style->fill.value.color, rgb );
736
954
    SetTextColor(hdc, RGB(255*rgb[0], 255*rgb[1], 255*rgb[2]));
737
955
 
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);
 
956
    // Text alignment:
 
957
    //   - (x,y) coordinates received by this filter are those of the point where the text
 
958
    //     actually starts, and already takes into account the text object's alignment;
 
959
    //   - for this reason, the EMF text alignment must always be TA_BASELINE|TA_LEFT.
 
960
    SetTextAlign(hdc, TA_BASELINE | TA_LEFT);
 
961
 
 
962
    // Transparent text background
 
963
    SetBkMode(hdc, TRANSPARENT);
 
964
 
 
965
    Geom::Matrix tf = m_tr_stack.top();
 
966
 
 
967
    p = p * tf;
 
968
    p[Geom::X] = (p[Geom::X] * IN_PER_PX * dwDPI);
 
969
    p[Geom::Y] = (p[Geom::Y] * IN_PER_PX * dwDPI);
 
970
 
 
971
    LONG const xpos = (LONG) round(p[Geom::X]);
 
972
    LONG const ypos = (LONG) round(rc.bottom-p[Geom::Y]);
746
973
 
747
974
    if (PrintWin32::is_os_wide()) {
748
975
        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));
 
976
        TextOutW(hdc, xpos, ypos, (WCHAR*)unicode_text, wcslen((wchar_t*)unicode_text));
750
977
    }
751
978
    else {
752
 
        TextOutA(hdc, p[NR::X], p[NR::Y], (CHAR*)text, strlen((char*)text));
 
979
        TextOutA(hdc, xpos, ypos, (CHAR*)text, strlen((char*)text));
753
980
    }
754
981
 
755
982
    SelectObject(hdc, hfontOld);
756
983
    DeleteObject(hfont);
757
984
    
758
985
    return 0;
759
 
 
760
 
 
761
 
 
762
 
    return 0;
763
986
}
764
987
 
765
988
void
769
992
 
770
993
    /* EMF print */
771
994
    ext = Inkscape::Extension::build_from_mem(
772
 
        "<inkscape-extension>\n"
 
995
        "<inkscape-extension xmlns=\"" INKSCAPE_EXTENSION_URI "\">\n"
773
996
        "<name>Enhanced Metafile Print</name>\n"
774
997
        "<id>org.inkscape.print.emf.win32</id>\n"
775
998
        "<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"
 
999
        "<param name=\"textToPath\" type=\"boolean\">true</param>\n"
 
1000
        "<param name=\"pageBoundingBox\" type=\"boolean\">true</param>\n"
778
1001
        "<print/>\n"
779
1002
        "</inkscape-extension>", new PrintEmfWin32());
780
1003