Subversion Repositories Scribus

Rev

Rev 10260 | Rev 11545 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
4430 cbradney 1
/*
2
For general Scribus (>=1.3.2) copyright and licensing information please refer
3
to the COPYING file provided with the program. Following this notice may exist
4
a copyright and/or license notice that predates the release of Scribus 1.3.2
5
for which a new license (GPL+exception) is in place.
6
*/
68 Franz 7
/* This file is part of the KDE project.
8
   Copyright (C) 2001, 2002, 2003 The Karbon Developers
9
 
10
   This library is free software; you can redistribute it and/or
11
   modify it under the terms of the GNU Library General Public
12
   License as published by the Free Software Foundation; either
13
   version 2 of the License, or (at your option) any later version.
14
 
15
   This library is distributed in the hope that it will be useful,
16
   but WITHOUT ANY WARRANTY; without even the implied warranty of
17
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18
   Library General Public License for more details.
19
 
20
   You should have received a copy of the GNU Library General Public License
21
   along with this library; see the file COPYING.LIB.  If not, write to
22
   the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23
   Boston, MA 02111-1307, USA.
24
*/
25
/* Adapted for Scribus 22.08.2003 by Franz Schmid */
26
// kopainter/libart wrapper
27
 
28
#include "scpainter.h"
128 Franz 29
 
68 Franz 30
#include <qpaintdevice.h>
31
#include <qpixmap.h>
32
#include <qpointarray.h>
33
#include <qimage.h>
34
 
3113 fschmid 35
#ifdef HAVE_CAIRO
36
#include <cairo.h>
11376 jghali 37
        #if defined(_WIN32)
38
                #include <cairo-win32.h>
39
        #else
40
                #include <cairo-xlib.h>
41
        #endif
3113 fschmid 42
#else
68 Franz 43
#include <libart_lgpl/art_vpath.h>
44
#include <libart_lgpl/art_bpath.h>
45
#include <libart_lgpl/art_vpath_bpath.h>
46
#include <libart_lgpl/art_svp_vpath.h>
47
#include <libart_lgpl/art_svp_vpath_stroke.h>
48
#include <libart_lgpl/art_svp.h>
49
#include <libart_lgpl/art_svp_ops.h>
50
#include <libart_lgpl/art_affine.h>
51
#include <libart_lgpl/art_svp_intersect.h>
52
#include <libart_lgpl/art_rect_svp.h>
53
#include <libart_lgpl/art_pathcode.h>
54
#include <libart_lgpl/art_vpath_dash.h>
55
#include <libart_lgpl/art_render_svp.h>
56
#include <libart_lgpl/art_vpath_svp.h>
3369 craig 57
#include "libart/art_render_misc.h"
58
#include "libart/art_rgb_svp.h"
59
#include "libart/art_render_pattern.h"
60
#include "libart/art_kmisc.h"
3113 fschmid 61
#define INITIAL_ALLOC   300
62
#define ALLOC_INCREMENT 100
63
#endif
68 Franz 64
 
1669 craig 65
#if defined(Q_WS_X11) && defined(SC_USE_PIXBUF)
68 Franz 66
#include <X11/Xlib.h>
5064 cbradney 67
#include "pixbuf/gdk-pixbuf-xlibrgb.h"
1669 craig 68
#endif
68 Franz 69
 
2686 craig 70
#if defined(_WIN32) && defined(SC_USE_GDI)
71
#include <windows.h>
72
#endif
73
 
68 Franz 74
#include <math.h>
75
 
1624 fschmid 76
ScPainter::ScPainter( QPaintDevice *target, unsigned int w, unsigned int h, unsigned int x, unsigned int y )
68 Franz 77
{
78
        m_target = target;
79
        m_width = w;
80
        m_height= h;
1624 fschmid 81
        m_x = x;
82
        m_y = y;
68 Franz 83
        m_buffer = 0L;
3113 fschmid 84
#ifndef HAVE_CAIRO
68 Franz 85
        m_path = 0L;
3113 fschmid 86
#endif
68 Franz 87
        m_index = 0;
88
        m_stroke = QColor(0,0,0);
89
        m_fill = QColor(0,0,0);
90
        fill_trans = 1.0;
91
        stroke_trans = 1.0;
92
        m_fillRule = true;
93
        fillMode = 1;
94
        LineWidth = 1.0;
95
        m_offset = 0;
96
        m_array.clear();
97
        mf_underline = false;
98
        mf_strikeout = false;
99
        mf_shadow = false;
100
        mf_outlined = false;
205 Franz 101
        PLineEnd = Qt::SquareCap;
102
        PLineJoin = Qt::RoundJoin;
68 Franz 103
        fill_gradient = VGradient(VGradient::linear);
104
        stroke_gradient = VGradient(VGradient::linear);
1669 craig 105
        m_zoomFactor = 1;
1815 fschmid 106
        imageMode = false;
3113 fschmid 107
        m_matrix = QWMatrix();
11376 jghali 108
#if defined(HAVE_CAIRO) && defined(_WIN32)
109
        pixm = QPixmap(w, h, 32);
110
        cairo_surface_t *img;
111
        img = cairo_win32_surface_create(pixm.handle());
112
        m_cr = cairo_create(img);
113
        clear();
114
        cairo_save( m_cr );
115
        cairo_set_fill_rule (m_cr, CAIRO_FILL_RULE_EVEN_ODD);
116
        cairo_set_operator(m_cr, CAIRO_OPERATOR_OVER);
117
        cairo_set_tolerance( m_cr, 0.5 );
118
#elif defined(HAVE_CAIRO)
3113 fschmid 119
        pixm = QPixmap(w, h);
120
        Display *dpy = pixm.x11AppDisplay();
121
        Drawable drw = pixm.handle();
122
        cairo_surface_t *img;
123
        img = cairo_xlib_surface_create(dpy, drw, (Visual*)pixm.x11Visual(), w, h);
124
        m_cr = cairo_create(img);
125
        clear();
126
        cairo_save( m_cr );
127
        cairo_set_fill_rule (m_cr, CAIRO_FILL_RULE_EVEN_ODD);
3173 fschmid 128
        cairo_set_operator(m_cr, CAIRO_OPERATOR_OVER);
3120 fschmid 129
/*      Setting to 0.5 here gives a good tradeoff between speed and precision
130
        the former setting of 0.2 is just too precise, and setting it to 0.9 or greater will give bad rendering */
131
        cairo_set_tolerance( m_cr, 0.5 );
11376 jghali 132
#elif defined(Q_WS_X11) && defined(SC_USE_PIXBUF)
3113 fschmid 133
        resize( m_width, m_height );
134
        clear();
1624 fschmid 135
        xlib_rgb_init_with_depth( target->x11Display(), XScreenOfDisplay( target->x11Display(), target->x11Screen() ), target->x11Depth() );
68 Franz 136
        gc = XCreateGC( target->x11Display(), target->handle(), 0, 0 );
2686 craig 137
#elif defined(_WIN32) && defined(SC_USE_GDI)
3113 fschmid 138
        resize( m_width, m_height );
139
        clear();
2686 craig 140
        dc = CreateCompatibleDC( target->handle() );
3175 avox 141
#else
142
        resize( m_width, m_height );
143
        clear();
1669 craig 144
#endif
68 Franz 145
}
146
 
1815 fschmid 147
ScPainter::ScPainter( QImage *target, unsigned int w, unsigned int h, unsigned int x, unsigned int y )
148
{
149
        m_target = 0L;
150
        m_width = w;
151
        m_height= h;
152
        m_x = x;
153
        m_y = y;
154
        m_buffer = 0L;
3113 fschmid 155
        m_index = 0;
1815 fschmid 156
        m_stroke = QColor(0,0,0);
157
        m_fill = QColor(0,0,0);
158
        fill_trans = 1.0;
159
        stroke_trans = 1.0;
160
        m_fillRule = true;
161
        fillMode = 1;
162
        LineWidth = 1.0;
163
        m_offset = 0;
164
        m_array.clear();
165
        mf_underline = false;
166
        mf_strikeout = false;
167
        mf_shadow = false;
168
        mf_outlined = false;
169
        PLineEnd = Qt::SquareCap;
170
        PLineJoin = Qt::RoundJoin;
171
        fill_gradient = VGradient(VGradient::linear);
172
        stroke_gradient = VGradient(VGradient::linear);
173
        m_zoomFactor = 1;
174
        imageMode = true;
175
        m_image = target;
3376 fschmid 176
#ifdef HAVE_CAIRO
177
        cairo_surface_t *img = cairo_image_surface_create_for_data(target->bits(), CAIRO_FORMAT_ARGB32, w, h, w*4);
178
        m_cr = cairo_create(img);
179
        clear();
180
        cairo_save( m_cr );
181
        cairo_set_fill_rule (m_cr, CAIRO_FILL_RULE_EVEN_ODD);
182
        cairo_set_operator(m_cr, CAIRO_OPERATOR_OVER);
183
/*      Setting to 0.5 here gives a good tradeoff between speed and precision
184
        the former setting of 0.2 is just too precise, and setting it to 0.9 or greater will give bad rendering */
185
        cairo_set_tolerance( m_cr, 0.5 );
186
#else
187
        resize( m_width, m_height );
188
        clear();
189
        m_path = 0L;
190
#endif
1815 fschmid 191
}
192
 
68 Franz 193
ScPainter::~ScPainter()
194
{
195
        // If we are in target mode, we created a buffer, else if we used the other ctor
196
        // we didnt.
3113 fschmid 197
#ifndef HAVE_CAIRO
1815 fschmid 198
        if (( m_target ) || ( imageMode))
68 Franz 199
                art_free( m_buffer );
200
        if( m_path )
201
                art_free( m_path );
3113 fschmid 202
#endif
203
#ifdef HAVE_CAIRO
4447 fschmid 204
        cairo_surface_destroy(cairo_get_target(m_cr));
3113 fschmid 205
        cairo_destroy( m_cr );
11376 jghali 206
#elif defined(Q_WS_X11) && defined(SC_USE_PIXBUF)
3376 fschmid 207
        if (imageMode)
208
                return;
68 Franz 209
        if( gc )
210
                XFreeGC( m_target->x11Display(), gc );
2686 craig 211
#elif defined(_WIN32) && defined(SC_USE_GDI)
3376 fschmid 212
        if (imageMode)
213
                return;
2686 craig 214
        if( dc )
215
                DeleteDC( dc );
1669 craig 216
#endif
68 Franz 217
}
218
 
219
void ScPainter::begin()
220
{
221
}
222
 
223
void ScPainter::end()
224
{
1815 fschmid 225
        if (imageMode)
226
        {
3376 fschmid 227
#ifdef HAVE_CAIRO
228
                cairo_surface_flush(cairo_get_target(m_cr));
229
                cairo_restore( m_cr );
230
#else
1815 fschmid 231
                QRgb * bits = (QRgb *) m_image->bits();
232
                int words = m_image->numBytes() / 4;
233
                art_u8 * p = m_buffer;;
234
                for (int i=0; i < words; ++i)
235
                {
236
                        art_u8 r = *p++;
237
                        art_u8 g = *p++;
238
                        art_u8 b = *p++;
239
                        art_u8 a = *p++;
240
                        *bits++ = qRgba(r,g,b,a);
241
                }
3113 fschmid 242
#endif
1815 fschmid 243
        }
244
        else
245
        {
3113 fschmid 246
#ifdef HAVE_CAIRO
247
                cairo_surface_flush(cairo_get_target(m_cr));
248
                bitBlt( m_target, m_x, m_y, &pixm, 0, 0, m_width, m_height );
249
                cairo_restore( m_cr );
11376 jghali 250
#elif defined(Q_WS_X11) && defined(SC_USE_PIXBUF)
1815 fschmid 251
                // Use the original gdk-pixbuf based bitblit on X11
252
                xlib_draw_rgb_32_image( m_target->handle(), gc, m_x, m_y, m_width, m_height, XLIB_RGB_DITHER_NONE, m_buffer, m_width * 4 );
2686 craig 253
#elif defined(_WIN32) && defined(SC_USE_GDI)
254
                // Use Win32 implementation
255
                BITMAPINFO bmpInfo;
256
                BITMAPINFOHEADER *bmpHeader;
257
                long* bmpData;
258
 
259
                bmpHeader = &(bmpInfo.bmiHeader);
260
                bmpHeader->biSize = sizeof(BITMAPINFOHEADER);
261
                bmpHeader->biWidth = m_width;
10260 jghali 262
                bmpHeader->biHeight = -(int) m_height;
2686 craig 263
                bmpHeader->biPlanes = 1;
264
                bmpHeader->biBitCount = 32;
265
                bmpHeader->biCompression = BI_RGB;
266
                bmpHeader->biSizeImage = 0; // Valid only if biCompression = BI_RGB
267
                bmpHeader->biXPelsPerMeter = 0;
268
                bmpHeader->biYPelsPerMeter = 0;
269
                bmpHeader->biClrUsed = 0;
270
                bmpHeader->biClrImportant = 0;
271
 
272
                // Create a device independent Bitmap
273
                HBITMAP hBmp = CreateDIBSection(dc, &bmpInfo, DIB_RGB_COLORS, (void** ) (&bmpData), NULL, NULL);
274
                art_u8 * p = m_buffer;
275
                art_u8 r, g, b, a;
276
                int words = m_width * m_height; // Valid only if biBitCount = 32
277
 
278
                for (int i = 0; i < words; ++i) {
279
                        r = *p++;
280
                        g = *p++;
281
                        b = *p++;
282
                        a = *p++;
283
                        *bmpData++ = ( (a << 24) + (r << 16) + (g << 8) + b);
284
                }
285
 
286
                HGDIOBJ obj = SelectObject( dc, hBmp);
287
                BitBlt( m_target->handle() , m_x, m_y, m_width, m_height, dc, 0, 0, SRCCOPY);
288
                SelectObject( dc, obj);
289
                DeleteObject( hBmp );
1669 craig 290
#else
1815 fschmid 291
                // Portable copying onto the canvas with no X11 dependency by Andreas Vox
292
                QImage qimg(m_width, m_height, 32, QImage::BigEndian);
293
                QRgb * bits = (QRgb *) qimg.bits();
294
                int words = qimg.numBytes() / 4;
295
                art_u8 * p = m_buffer;;
296
                for (int i=0; i < words; ++i) {
297
                        art_u8 r = *p++;
298
                        art_u8 g = *p++;
299
                        art_u8 b = *p++;
300
                        art_u8 a = *p++;
301
                        *bits++ = qRgba(r,g,b,a);
302
                }
303
                bitBlt(m_target, m_x, m_y, &qimg);
304
#endif
1669 craig 305
        }
68 Franz 306
}
307
 
1624 fschmid 308
void ScPainter::clear()
68 Franz 309
{
3113 fschmid 310
#ifdef HAVE_CAIRO
3376 fschmid 311
        if (imageMode)
312
                m_image->fill( qRgba(255, 255, 255, 255) );
313
        else
314
                pixm.fill( Qt::white );
3113 fschmid 315
#else
68 Franz 316
        if( m_buffer )
214 Franz 317
                memset( m_buffer, 255, m_width * m_height * 4 );
3113 fschmid 318
#endif
68 Franz 319
}
320
 
1624 fschmid 321
void ScPainter::clear( const QColor &c )
68 Franz 322
{
3113 fschmid 323
#ifdef HAVE_CAIRO
3376 fschmid 324
        QRgb cs = c.rgb();
325
        if (imageMode)
326
                m_image->fill( qRgba(qRed(cs), qGreen(cs), qBlue(cs), qAlpha(cs)) );
327
        else
328
                pixm.fill( c );
3113 fschmid 329
#else
68 Franz 330
        if( m_buffer )
214 Franz 331
        {
332
                unsigned int *src = (unsigned int*)m_buffer;
333
                unsigned int co = qRgba(c.blue(), c.green(),  c.red(), 255);
334
                for(unsigned int cc = 0; cc < (m_width * m_height); ++cc)
335
                {
336
                        *src++ = co;
337
                }
338
        }
3113 fschmid 339
#endif
68 Franz 340
}
341
 
3113 fschmid 342
const QWMatrix ScPainter::worldMatrix()
343
{
344
#ifdef HAVE_CAIRO
345
        cairo_matrix_t matrix;
346
        cairo_get_matrix(m_cr, &matrix);
347
        QWMatrix mat;
348
        mat.setMatrix ( matrix.xx, matrix.yx, matrix.xy, matrix.yy, matrix.x0, matrix.y0 );
349
        return mat;
350
#else
351
        return m_matrix;
352
#endif
353
}
354
 
68 Franz 355
void ScPainter::setWorldMatrix( const QWMatrix &mat )
356
{
3113 fschmid 357
#ifdef HAVE_CAIRO
358
        cairo_matrix_t matrix;
359
        cairo_matrix_init(&matrix, mat.m11(), mat.m12(), mat.m21(), mat.m22(), mat.dx(), mat.dy());
360
        cairo_set_matrix(m_cr, &matrix);
361
#else
68 Franz 362
        m_matrix = mat;
3113 fschmid 363
#endif
68 Franz 364
}
365
 
366
void ScPainter::setZoomFactor( double zoomFactor )
367
{
368
        m_zoomFactor = zoomFactor;
369
}
370
 
371
void ScPainter::translate( double x, double y )
372
{
3113 fschmid 373
#ifdef HAVE_CAIRO
374
        cairo_translate (m_cr, x, y);
375
#else
68 Franz 376
        m_matrix.translate(x, y);
3113 fschmid 377
#endif
68 Franz 378
}
379
 
380
void ScPainter::rotate( double r )
381
{
3113 fschmid 382
#ifdef HAVE_CAIRO
383
        cairo_rotate (m_cr, r * 3.1415927 / 180.0);
384
#else
68 Franz 385
        m_matrix.rotate(r);
3113 fschmid 386
#endif
68 Franz 387
}
388
 
389
void ScPainter::scale( double x, double y )
390
{
3113 fschmid 391
#ifdef HAVE_CAIRO
392
        cairo_scale (m_cr, x, y);
393
#else
68 Franz 394
        m_matrix.scale(x, y);
3113 fschmid 395
#endif
68 Franz 396
}
397
 
398
void ScPainter::moveTo( const double &x, const double &y )
399
{
3113 fschmid 400
#ifdef HAVE_CAIRO
401
        cairo_move_to( m_cr, x * m_zoomFactor, y * m_zoomFactor);
402
#else
68 Franz 403
        ensureSpace( m_index + 1 );
404
        m_path[ m_index ].code = ART_MOVETO;
405
        m_path[ m_index ].x3 = x * m_zoomFactor;
406
        m_path[ m_index ].y3 = y * m_zoomFactor;
407
        m_index++;
3113 fschmid 408
#endif
68 Franz 409
}
410
 
4646 subik 411
void
68 Franz 412
ScPainter::lineTo( const double &x, const double &y )
413
{
3113 fschmid 414
#ifdef HAVE_CAIRO
415
        cairo_line_to( m_cr, x * m_zoomFactor, y * m_zoomFactor);
416
#else
68 Franz 417
        ensureSpace( m_index + 1 );
418
        m_path[ m_index ].code = ART_LINETO;
419
        m_path[ m_index ].x3    = x * m_zoomFactor;
420
        m_path[ m_index ].y3    = y * m_zoomFactor;
421
        m_index++;
3113 fschmid 422
#endif
68 Franz 423
}
424
 
425
void ScPainter::curveTo( FPoint p1, FPoint p2, FPoint p3 )
426
{
3113 fschmid 427
#ifdef HAVE_CAIRO
4646 subik 428
        cairo_curve_to(m_cr,
429
                                                                p1.x() * m_zoomFactor,
430
                                                                p1.y() * m_zoomFactor,
431
                                                                p2.x() * m_zoomFactor,
432
                                                                p2.y() * m_zoomFactor,
433
                                                                p3.x() * m_zoomFactor,
3113 fschmid 434
                                                                p3.y() * m_zoomFactor);
435
#else
68 Franz 436
        ensureSpace( m_index + 1 );
437
        m_path[ m_index ].code = ART_CURVETO;
86 Franz 438
        m_path[ m_index ].x1    = p1.x() * m_zoomFactor;
439
        m_path[ m_index ].y1    = p1.y() * m_zoomFactor;
440
        m_path[ m_index ].x2    = p2.x() * m_zoomFactor;
441
        m_path[ m_index ].y2    = p2.y() * m_zoomFactor;
442
        m_path[ m_index ].x3    = p3.x() * m_zoomFactor;
443
        m_path[ m_index ].y3    = p3.y() * m_zoomFactor;
68 Franz 444
        m_index++;
3113 fschmid 445
#endif
68 Franz 446
}
447
 
448
void ScPainter::newPath()
449
{
3113 fschmid 450
#ifdef HAVE_CAIRO
451
        cairo_new_path( m_cr );
452
#else
68 Franz 453
        m_index = 0;
3113 fschmid 454
#endif
68 Franz 455
}
456
 
457
void ScPainter::setFillRule( bool fillRule )
458
{
459
        m_fillRule = fillRule;
460
}
461
 
462
void ScPainter::setFillMode( int fill )
463
{
464
        fillMode = fill;
465
}
466
 
467
void ScPainter::setGradient(VGradient::VGradientType mode, FPoint orig, FPoint vec, FPoint foc)
468
{
469
        fill_gradient.setType(mode);
470
        fill_gradient.setOrigin(orig);
471
        fill_gradient.setVector(vec);
472
        fill_gradient.setFocalPoint(foc);
473
}
474
 
1998 fschmid 475
void ScPainter::fillTextPath()
476
{
3113 fschmid 477
#ifdef HAVE_CAIRO
478
        drawVPath( 0 );
479
#else
1998 fschmid 480
        ArtVpath *path = art_bez_path_to_vec( m_path , 0.25 );
481
        drawVPath( path, 0, true );
3113 fschmid 482
#endif
1998 fschmid 483
}
484
 
485
void ScPainter::strokeTextPath()
486
{
487
        if( LineWidth == 0 )
488
                return;
3113 fschmid 489
#ifdef HAVE_CAIRO
490
        drawVPath( 1 );
491
#else
1998 fschmid 492
        ArtVpath *path = art_bez_path_to_vec( m_path , 0.25 );
493
        drawVPath( path, 1, true );
3113 fschmid 494
#endif
1998 fschmid 495
}
496
 
68 Franz 497
void ScPainter::fillPath()
498
{
3113 fschmid 499
#ifdef HAVE_CAIRO
500
        if( fillMode != 0)
501
                drawVPath( 0 );
502
#else
4646 subik 503
        if( m_index == 0 )
1998 fschmid 504
                return;
68 Franz 505
        if( fillMode != 0)
384 Franz 506
        {
68 Franz 507
                ArtVpath *path = art_bez_path_to_vec( m_path , 0.25 );
508
                drawVPath( path, 0 );
384 Franz 509
        }
3113 fschmid 510
#endif
68 Franz 511
}
512
 
513
void ScPainter::strokePath()
514
{
3113 fschmid 515
        if( LineWidth == 0 )
516
                return;
517
#ifdef HAVE_CAIRO
518
        drawVPath( 1 );
519
#else
68 Franz 520
        if( m_index == 0 )
521
                return;
522
        if( m_path[ m_index ].code != ART_END)
523
                m_path[ m_index ].code = ART_END;
524
        ArtVpath *path = art_bez_path_to_vec( m_path , 0.25 );
525
        drawVPath( path, 1 );
3113 fschmid 526
#endif
68 Franz 527
}
528
 
529
QColor ScPainter::pen()
530
{
531
        return m_stroke;
532
}
533
 
534
QColor ScPainter::brush()
535
{
536
        return m_fill;
537
}
538
 
539
void ScPainter::setPen( const QColor &c )
540
{
541
        m_stroke = c;
542
}
543
 
80 Franz 544
void ScPainter::setPen( const QColor &c, double w, Qt::PenStyle st, Qt::PenCapStyle ca, Qt::PenJoinStyle jo )
68 Franz 545
{
546
        m_stroke = c;
547
        LineWidth = w;
548
        PLineEnd = ca;
549
        PLineJoin = jo;
80 Franz 550
        double Dt = QMAX(2*w, 1);
551
        double Da = QMAX(6*w, 1);
552
        QValueList<double> tmp;
68 Franz 553
        m_array.clear();
554
        m_offset = 0;
555
        switch (st)
556
                {
557
                case Qt::SolidLine:
558
                        break;
559
                case Qt::DashLine:
560
                        m_array.append(Da);
561
                        m_array.append(Dt);
562
                        break;
563
                case Qt::DotLine:
564
                        m_array.append(Dt);
565
                        break;
566
                case Qt::DashDotLine:
567
                        m_array.append(Da);
568
                        m_array.append(Dt);
569
                        m_array.append(Dt);
570
                        m_array.append(Dt);
571
                        break;
572
                case Qt::DashDotDotLine:
573
                        m_array.append(Da);
574
                        m_array.append(Dt);
575
                        m_array.append(Dt);
576
                        m_array.append(Dt);
577
                        m_array.append(Dt);
578
                        m_array.append(Dt);
579
                        break;
580
                default:
581
                        break;
582
                }
583
}
584
 
80 Franz 585
void ScPainter::setLineWidth( double w )
68 Franz 586
{
587
        LineWidth = w;
588
}
589
 
80 Franz 590
void ScPainter::setPenOpacity( double op )
68 Franz 591
{
592
        stroke_trans = op;
593
}
594
 
595
 
80 Franz 596
void ScPainter::setDash(const QValueList<double>& array, double ofs)
68 Franz 597
{
598
        m_array = array;
599
        m_offset = ofs;
600
}
601
 
602
void ScPainter::setBrush( const QColor &c )
603
{
604
        m_fill = c;
605
}
606
 
80 Franz 607
void ScPainter::setBrushOpacity( double op )
68 Franz 608
{
609
        fill_trans = op;
610
}
611
 
80 Franz 612
void ScPainter::setOpacity( double op )
68 Franz 613
{
614
        fill_trans = op;
615
        stroke_trans = op;
616
}
617
 
618
void ScPainter::setFont( const QFont &f)
619
{
620
        m_font = f;
621
}
622
 
623
QFont ScPainter::font()
624
{
625
        return m_font;
626
}
627
 
628
void ScPainter::save()
629
{
3113 fschmid 630
#ifdef HAVE_CAIRO
631
        cairo_save( m_cr );
632
#else
68 Franz 633
        MStack.push(m_matrix);
3113 fschmid 634
#endif
68 Franz 635
}
636
 
637
void ScPainter::restore()
638
{
3113 fschmid 639
#ifdef HAVE_CAIRO
640
        cairo_restore( m_cr );
641
#else
68 Franz 642
        m_matrix = MStack.pop();
3113 fschmid 643
#endif
68 Franz 644
}
645
 
3240 fschmid 646
void ScPainter::setRasterOp( int   )
68 Franz 647
{
648
}
649
 
3113 fschmid 650
#ifdef HAVE_CAIRO
651
void ScPainter::drawVPath( int mode )
68 Franz 652
{
3113 fschmid 653
        cairo_save( m_cr );
654
        if (mode == 0)
655
        {
656
                if( m_fillRule )
657
                        cairo_set_fill_rule (m_cr, CAIRO_FILL_RULE_EVEN_ODD);
658
                else
659
                        cairo_set_fill_rule (m_cr, CAIRO_FILL_RULE_WINDING);
660
                if (fillMode == 2)
661
                {
662
                        cairo_pattern_t *pat;
663
                        double x1 = fill_gradient.origin().x() * m_zoomFactor;
664
                        double y1 = fill_gradient.origin().y() * m_zoomFactor;
665
                        double x2 = fill_gradient.vector().x() * m_zoomFactor;
666
                        double y2 = fill_gradient.vector().y() * m_zoomFactor;
667
                        if (fill_gradient.type() == VGradient::linear)
668
                                pat = cairo_pattern_create_linear (x1, y1,  x2, y2);
669
                        else
670
                                pat = cairo_pattern_create_radial (x1, y1, 0.1, x1, y1, sqrt(pow(x2 - x1, 2) + pow(y2 - y1,2)));
671
                        QPtrVector<VColorStop> colorStops = fill_gradient.colorStops();
672
                        for( uint offset = 0 ; offset < colorStops.count() ; offset++ )
673
                        {
674
                                QColor qStopColor = colorStops[ offset ]->color;
675
                                int h, s, v, sneu;
676
                                int shad = colorStops[offset]->shade;
677
                                qStopColor.rgb(&h, &s, &v);
678
                                if ((h == s) && (s == v))
679
                                {
680
                                        qStopColor.hsv(&h, &s, &v);
681
                                        sneu = 255 - ((255 - v) * shad / 100);
682
                                        qStopColor.setHsv(h, s, sneu);
683
                                }
684
                                else
685
                                {
686
                                        qStopColor.hsv(&h, &s, &v);
687
                                        sneu = s * shad / 100;
688
                                        qStopColor.setHsv(h, sneu, v);
689
                                }
690
                                double r = qRed( qStopColor.rgb() ) / 255.0;
691
                                double g = qGreen( qStopColor.rgb() ) / 255.0;
692
                                double b = qBlue( qStopColor.rgb() ) / 255.0;
693
                                double a = colorStops[offset]->opacity;
694
                                cairo_pattern_add_color_stop_rgba (pat, colorStops[ offset ]->rampPoint, r, g, b, a);
695
                        }
696
                        cairo_set_source (m_cr, pat);
697
                        cairo_clip_preserve (m_cr);
698
                        cairo_paint_with_alpha (m_cr, fill_trans);
699
                        cairo_pattern_destroy (pat);
700
                }
701
                else
702
                {
703
                        double r = qRed( m_fill.rgb() ) / 255.0;
704
                        double g = qGreen( m_fill.rgb() ) / 255.0;
705
                        double b = qBlue( m_fill.rgb() ) / 255.0;
706
                        cairo_set_source_rgba( m_cr, r, g, b, fill_trans );
707
                        cairo_fill_preserve( m_cr );
708
                }
709
        }
710
        else
711
        {
712
                double *dashes;
713
                cairo_set_line_width( m_cr, LineWidth * m_zoomFactor );
714
                if( m_array.count() > 0 )
715
                {
716
                        dashes = new double[ m_array.count() ];
717
                        for( uint i = 0; i < m_array.count();++ i )
718
                        {
719
                                dashes[i] = static_cast<double>(m_array[i]) * m_zoomFactor;
720
                        }
721
                        cairo_set_dash( m_cr, dashes, m_array.count(), static_cast<double>(m_offset) * m_zoomFactor );
722
                }
723
                else
724
                        cairo_set_dash( m_cr, NULL, 0, 0 );
725
                double r = qRed( m_stroke.rgb() ) / 255.0;
726
                double g = qGreen( m_stroke.rgb() ) / 255.0;
727
                double b = qBlue( m_stroke.rgb() ) / 255.0;
728
                cairo_set_source_rgba( m_cr, r, g, b, stroke_trans );
729
                if( PLineEnd == Qt::RoundCap )
730
                        cairo_set_line_cap (m_cr, CAIRO_LINE_CAP_ROUND);
731
                else if( PLineEnd == Qt::SquareCap )
732
                        cairo_set_line_cap (m_cr, CAIRO_LINE_CAP_SQUARE);
733
                else if( PLineEnd == Qt::FlatCap )
734
                        cairo_set_line_cap (m_cr, CAIRO_LINE_CAP_BUTT);
735
                if( PLineJoin == Qt::RoundJoin )
736
                        cairo_set_line_join( m_cr, CAIRO_LINE_JOIN_ROUND );
737
                else if( PLineJoin == Qt::BevelJoin )
738
                        cairo_set_line_join( m_cr, CAIRO_LINE_JOIN_BEVEL );
739
                else if( PLineJoin == Qt::MiterJoin )
740
                        cairo_set_line_join( m_cr, CAIRO_LINE_JOIN_MITER );
741
                cairo_stroke_preserve( m_cr );
742
                if( m_array.count() > 0 )
743
                        delete [] dashes;
744
        }
745
        cairo_restore( m_cr );
746
#else
4646 subik 747
void ScPainter::drawVPath( struct _ArtVpath *vec, int mode, bool preCal )
68 Franz 748
{
749
        ArtSVP *strokeSvp = 0L;
750
        ArtSVP *fillSvp = 0L;
1998 fschmid 751
        if (!preCal)
752
        {
753
                double affine[6];
754
                affine[0] = m_matrix.m11();
755
                affine[1] = m_matrix.m12();
756
                affine[2] = m_matrix.m21();
757
                affine[3] = m_matrix.m22();
758
                affine[4] = m_matrix.dx();
759
                affine[5] = m_matrix.dy();
760
                ArtVpath *temp1 = art_vpath_affine_transform( vec, affine );
761
                art_free( vec );
762
                vec = temp1;
763
        }
68 Franz 764
        int af = 0;
765
        int as = 0;
766
        art_u32 fillColor = 0;
767
        QColor color;
768
        if (mode == 0)
769
                {
770
                color = m_fill;
771
                af = qRound( 255 * fill_trans );
86 Franz 772
#ifdef WORDS_BIGENDIAN
773
                fillColor = ( color.red() << 24 ) | ( color.green() << 16 ) | ( color.blue() << 8 );
774
#else
775
                fillColor = ( 0 << 24 ) | ( color.blue() << 16 ) | ( color.green() << 8 ) | color.red();
776
#endif
68 Franz 777
                ArtSvpWriter *swr;
778
                ArtSVP *temp;
779
                temp = art_svp_from_vpath( vec );
780
                if( m_fillRule )
781
                        swr = art_svp_writer_rewind_new( ART_WIND_RULE_ODDEVEN );
782
                else
783
                        swr = art_svp_writer_rewind_new( ART_WIND_RULE_NONZERO );
784
                art_svp_intersector( temp, swr );
785
                fillSvp = art_svp_writer_rewind_reap( swr );
786
                art_svp_free( temp );
787
                }
788
        art_u32 strokeColor = 0;
789
        if (mode == 1)
790
                {
791
                ArtPathStrokeCapType capStyle = ART_PATH_STROKE_CAP_BUTT;
792
                ArtPathStrokeJoinType joinStyle = ART_PATH_STROKE_JOIN_MITER;
793
                color = m_stroke;
794
                as = qRound( 255 * stroke_trans );
86 Franz 795
#ifdef WORDS_BIGENDIAN
796
    strokeColor = ( color.red() << 24 ) | ( color.green() << 16 ) | ( color.blue() << 8 );
797
#else
68 Franz 798
                strokeColor = ( 0 << 24 ) | ( color.blue() << 16 ) | ( color.green() << 8 ) | color.red();
86 Franz 799
#endif
3113 fschmid 800
                double ratio = m_zoomFactor;
68 Franz 801
                if( m_array.count() > 0 )
802
                        {
803
                        ArtVpathDash dash;
804
                        dash.offset = static_cast<double>(m_offset) * ratio;
805
                        dash.n_dash = m_array.count();
806
                        double *dashes = new double[ dash.n_dash ];
807
                        for( int i = 0; i < dash.n_dash; i++ )
808
                                {
809
                                dashes[i] = static_cast<double>(m_array[i]) * ratio;
810
                                }
811
                        dash.dash = dashes;
812
                        ArtVpath *vec2 = art_vpath_dash( vec, &dash );
813
                        art_free( vec );
814
                        vec = vec2;
815
                        delete [] dashes;
816
                        }
817
                if( PLineEnd == Qt::RoundCap )
818
                        capStyle = ART_PATH_STROKE_CAP_ROUND;
819
                else if( PLineEnd == Qt::SquareCap )
820
                        capStyle = ART_PATH_STROKE_CAP_SQUARE;
821
                if( PLineJoin == Qt::RoundJoin )
822
                        joinStyle = ART_PATH_STROKE_JOIN_ROUND;
823
                else if( PLineJoin == Qt::BevelJoin )
824
                        joinStyle = ART_PATH_STROKE_JOIN_BEVEL;
5095 mrdocs 825
                //strokeSvp = art_svp_vpath_stroke( vec, joinStyle, capStyle, ratio * LineWidth, 10, 0.25 );
826
                ArtVpath* strokeVpath = art_svp_vpath_stroke_raw( vec, joinStyle, capStyle, ratio * LineWidth, 10, 0.25 );
827
                strokeSvp = art_svp_from_vpath( strokeVpath );
828
                art_free(strokeVpath);
68 Franz 829
                }
830
        int x0, y0, x1, y1;
237 Franz 831
        if(( fillSvp ) && (mode == 0))
68 Franz 832
                {
833
                if (fillMode == 2)
834
                        applyGradient( fillSvp, true );
835
                else
836
                        {
837
                        clampToViewport( *fillSvp, x0, y0, x1, y1 );
838
                        if( x0 != x1 && y0 != y1 )
839
                                art_rgb_svp_alpha_( fillSvp, x0, y0, x1, y1, fillColor, af, m_buffer + x0 * 4 + y0 * m_width * 4, m_width * 4, 0 );
840
                        }
841
                art_svp_free( fillSvp );
842
                }
237 Franz 843
        if(( strokeSvp ) && (mode == 1))
68 Franz 844
        {
845
                        clampToViewport( *strokeSvp, x0, y0, x1, y1 );
846
                        if( x0 != x1 && y0 != y1 )
847
                                art_rgb_svp_alpha_( strokeSvp, x0, y0, x1, y1, strokeColor, as, m_buffer + x0 * 4 + y0 * m_width * 4, m_width * 4, 0 );
848
                art_svp_free( strokeSvp );
849
        }
850
        art_free( vec );
3113 fschmid 851
#endif
68 Franz 852
}
853
 
267 Franz 854
void ScPainter::setClipPath()
855
{
3113 fschmid 856
#ifdef HAVE_CAIRO
857
        cairo_clip (m_cr);
858
#else
267 Franz 859
        ArtVpath *vec = art_bez_path_to_vec( m_path , 0.25 );
860
        double affine[6];
861
        affine[0] = m_matrix.m11();
632 fschmid 862
        affine[1] = m_matrix.m12();
863
        affine[2] = m_matrix.m21();
267 Franz 864
        affine[3] = m_matrix.m22();
865
        affine[4] = m_matrix.dx();
866
        affine[5] = m_matrix.dy();
867
        ArtVpath *temp1 = art_vpath_affine_transform( vec, affine );
868
        art_free( vec );
869
        ArtSvpWriter *swr;
268 Franz 870
        ArtSVP *temp = art_svp_from_vpath( temp1 );
267 Franz 871
        if( m_fillRule )
872
                swr = art_svp_writer_rewind_new( ART_WIND_RULE_ODDEVEN );
873
        else
874
                swr = art_svp_writer_rewind_new( ART_WIND_RULE_NONZERO );
875
        art_svp_intersector( temp, swr );
876
        m_clipPath = art_svp_writer_rewind_reap( swr );
877
        art_svp_free( temp );
268 Franz 878
        art_free( temp1 );
3113 fschmid 879
#endif
267 Franz 880
}
881
 
4748 fschmid 882
#ifndef HAVE_CAIRO
883
void ScPainter::setClipPath2(FPointArray *points, bool closed)
884
{
885
        setClipPath();
886
        setupPolygon(points, closed);
887
        ArtVpath *vec = art_bez_path_to_vec( m_path , 0.25 );
888
        double affine[6];
889
        affine[0] = m_matrix.m11();
890
        affine[1] = m_matrix.m12();
891
        affine[2] = m_matrix.m21();
892
        affine[3] = m_matrix.m22();
893
        affine[4] = m_matrix.dx();
894
        affine[5] = m_matrix.dy();
895
        ArtVpath *temp1 = art_vpath_affine_transform( vec, affine );
896
        art_free( vec );
897
        ArtSvpWriter *swr;
898
        ArtSVP *temp = art_svp_from_vpath( temp1 );
899
        if( m_fillRule )
900
                swr = art_svp_writer_rewind_new( ART_WIND_RULE_ODDEVEN );
901
        else
902
                swr = art_svp_writer_rewind_new( ART_WIND_RULE_NONZERO );
903
        art_svp_intersector( temp, swr );
904
        temp = art_svp_writer_rewind_reap( swr );
905
        ArtSVP *temp2 = art_svp_intersect( temp, m_clipPath );
906
        m_clipPath = temp2;
907
        art_svp_free( temp );
908
        art_free( temp1 );
909
}
910
#endif
911
 
270 Franz 912
void ScPainter::drawImage( QImage *image )
68 Franz 913
{
3113 fschmid 914
#ifdef HAVE_CAIRO
915
        cairo_set_fill_rule(m_cr, cairo_get_fill_rule(m_cr));
916
        cairo_surface_t *image2;
917
        image2  = cairo_image_surface_create_for_data ((uchar*)image->bits(), CAIRO_FORMAT_ARGB32, image->width(), image->height(), image->width()*4);
918
        cairo_scale(m_cr, m_zoomFactor, m_zoomFactor);
919
        cairo_set_source_surface (m_cr, image2, 0, 0);
920
        cairo_paint_with_alpha(m_cr, fill_trans);
921
        cairo_surface_destroy (image2);
922
#else
68 Franz 923
        double affineresult[6];
924
        affineresult[0] = m_matrix.m11() * m_zoomFactor;
925
        affineresult[1] = m_matrix.m12() * m_zoomFactor;
926
        affineresult[2] = m_matrix.m21() * m_zoomFactor;
927
        affineresult[3] = m_matrix.m22() * m_zoomFactor;
632 fschmid 928
        affineresult[4] = m_matrix.dx();
929
        affineresult[5] = m_matrix.dy();
267 Franz 930
        ksvg_art_rgb_affine_clip( m_clipPath, m_buffer, 0, 0, m_width, m_height, m_width * 4, 4,
270 Franz 931
                                         image->bits(), image->width(), image->height(), image->width() * 4,
267 Franz 932
                                         affineresult, qRound( 255 * fill_trans ), 0L );
933
        art_svp_free( m_clipPath );
3113 fschmid 934
#endif
68 Franz 935
}
936
 
264 Franz 937
void ScPainter::setupPolygon(FPointArray *points, bool closed)
68 Franz 938
{
939
        bool nPath = true;
940
        FPoint np, np1, np2, np3;
3113 fschmid 941
#ifdef HAVE_CAIRO
68 Franz 942
        if (points->size() > 3)
3113 fschmid 943
        {
944
                newPath();
945
                for (uint poi=0; poi<points->size()-3; poi += 4)
68 Franz 946
                {
3113 fschmid 947
                        if (points->point(poi).x() > 900000)
948
                        {
949
                                nPath = true;
950
//                      cairo_close_path( m_cr );
951
                                continue;
952
                        }
953
                        if (nPath)
954
                        {
955
                                np = points->point(poi);
956
                        cairo_move_to( m_cr, np.x() * m_zoomFactor, np.y() * m_zoomFactor);
957
                                nPath = false;
958
                        }
959
                        np = points->point(poi);
960
                        np1 = points->point(poi+1);
961
                        np2 = points->point(poi+3);
962
                        np3 = points->point(poi+2);
963
                        if ((np == np1) && (np2 == np3))
964
                                cairo_line_to( m_cr, np3.x() * m_zoomFactor, np3.y() * m_zoomFactor);
965
                        else
4646 subik 966
                                cairo_curve_to(m_cr,
967
                                                                                        np1.x() * m_zoomFactor,
968
                                                                                        np1.y() * m_zoomFactor,
969
                                                                                        np2.x() * m_zoomFactor,
970
                                                                                        np2.y() * m_zoomFactor,
971
                                                                                        np3.x() * m_zoomFactor,
3113 fschmid 972
                                                                                        np3.y() * m_zoomFactor);
973
                }
974
                if (closed)
975
                cairo_close_path( m_cr );
976
        }
977
#else
978
        if (points->size() > 3)
979
                {
68 Franz 980
                newPath();
981
                for (uint poi=0; poi<points->size()-3; poi += 4)
982
                        {
983
                        if (points->point(poi).x() > 900000)
984
                                {
985
                                nPath = true;
173 Franz 986
                                ensureSpace( m_index + 1 );
987
                                m_path[ m_index ].code = ART_END;
68 Franz 988
                                continue;
989
                                }
990
                        if (nPath)
991
                                {
992
                                np = points->point(poi);
993
                                ensureSpace( m_index + 1 );
264 Franz 994
                                if (closed)
995
                                        m_path[ m_index ].code = ART_MOVETO;
996
                                else
997
                                        m_path[ m_index ].code = ART_MOVETO_OPEN;
86 Franz 998
                                m_path[ m_index ].x3 = np.x() * m_zoomFactor;
999
                                m_path[ m_index ].y3 = np.y() * m_zoomFactor;
68 Franz 1000
                                m_index++;
1001
                                nPath = false;
1002
                                }
1003
                        np = points->point(poi);
1004
                        np1 = points->point(poi+1);
1005
                        np2 = points->point(poi+3);
1006
                        np3 = points->point(poi+2);
1007
                        ensureSpace( m_index + 1 );
1008
                        if ((np == np1) && (np2 == np3))
1009
                                {
1010
                                m_path[ m_index ].code = ART_LINETO;
86 Franz 1011
                                m_path[ m_index ].x3    = np3.x() * m_zoomFactor;
1012
                                m_path[ m_index ].y3    = np3.y() * m_zoomFactor;
68 Franz 1013
                                }
1014
                        else
1015
                                {
1016
                                m_path[ m_index ].code = ART_CURVETO;
86 Franz 1017
                                m_path[ m_index ].x1    = np1.x() * m_zoomFactor;
1018
                                m_path[ m_index ].y1    = np1.y() * m_zoomFactor;
1019
                                m_path[ m_index ].x2    = np2.x() * m_zoomFactor;
1020
                                m_path[ m_index ].y2    = np2.y() * m_zoomFactor;
1021
                                m_path[ m_index ].x3    = np3.x() * m_zoomFactor;
1022
                                m_path[ m_index ].y3    = np3.y() * m_zoomFactor;
68 Franz 1023
                                }
1024
                        m_index++;
1025
                        }
173 Franz 1026
                ensureSpace( m_index + 1 );
1027
                m_path[ m_index ].code = ART_END;
1028
                m_index++;
68 Franz 1029
                }
3113 fschmid 1030
#endif
68 Franz 1031
}
1032
 
638 fschmid 1033
void ScPainter::setupTextPolygon(FPointArray *points)
1034
{
1035
        bool nPath = true;
1036
        FPoint np, np1, np2, np3;
3113 fschmid 1037
#ifdef HAVE_CAIRO
1038
        if (points->size() > 3)
1039
        {
1040
                newPath();
1041
                for (uint poi=0; poi<points->size()-3; poi += 4)
1042
                {
1043
                        if (points->point(poi).x() > 900000)
1044
                        {
1045
                                nPath = true;
1046
                                continue;
1047
                        }
1048
                        if (nPath)
1049
                        {
1050
                                np = points->point(poi);
1051
                        cairo_move_to( m_cr, np.x(), np.y());
1052
                                nPath = false;
1053
                        }
1054
                        np = points->point(poi);
1055
                        np1 = points->point(poi+1);
1056
                        np2 = points->point(poi+3);
1057
                        np3 = points->point(poi+2);
1058
                        if ((np == np1) && (np2 == np3))
1059
                                cairo_line_to( m_cr, np3.x(), np3.y());
1060
                        else
1061
                                cairo_curve_to(m_cr, np1.x(), np1.y(), np2.x(), np2.y(), np3.x(), np3.y());
1062
                }
1063
        cairo_close_path( m_cr );
1064
        }
1065
#else
638 fschmid 1066
        newPath();
1067
        for (uint poi=0; poi<points->size()-3; poi += 4)
1068
        {
1069
                if (points->point(poi).x() > 900000)
1070
                {
1071
                        nPath = true;
1072
                        ensureSpace( m_index + 1 );
1073
                        m_path[ m_index ].code = ART_END;
1074
                        continue;
1075
                }
1076
                if (nPath)
1077
                {
1078
                        np = points->point(poi);
1079
                        ensureSpace( m_index + 1 );
1080
                        m_path[ m_index ].code = ART_MOVETO;
1081
                        m_path[ m_index ].x3 = np.x();
1082
                        m_path[ m_index ].y3 = np.y();
1083
                        m_index++;
1084
                        nPath = false;
1085
                }
1086
                np = points->point(poi);
1087
                np1 = points->point(poi+1);
1088
                np2 = points->point(poi+3);
1089
                np3 = points->point(poi+2);
1090
                ensureSpace( m_index + 1 );
1091
                if ((np == np1) && (np2 == np3))
1092
                {
1093
                        m_path[ m_index ].code = ART_LINETO;
1094
                        m_path[ m_index ].x3    = np3.x();
1095
                        m_path[ m_index ].y3    = np3.y();
1096
                }
1097
                else
1098
                {
1099
                        m_path[ m_index ].code = ART_CURVETO;
1100
                        m_path[ m_index ].x1    = np1.x();
1101
                        m_path[ m_index ].y1    = np1.y();
1102
                        m_path[ m_index ].x2    = np2.x();
1103
                        m_path[ m_index ].y2    = np2.y();
1104
                        m_path[ m_index ].x3    = np3.x();
1105
                        m_path[ m_index ].y3    = np3.y();
1106
                }
1107
                m_index++;
1108
        }
1109
        ensureSpace( m_index + 1 );
1110
        m_path[ m_index ].code = ART_END;
1111
        m_index++;
3113 fschmid 1112
#endif
638 fschmid 1113
}
1114
 
68 Franz 1115
void ScPainter::drawPolygon()
1116
{
1117
        fillPath();
1118
}
1119
 
1120
void ScPainter::drawPolyLine()
1121
{
1122
        strokePath();
1123
}
1124
 
1125
void ScPainter::drawLine(FPoint start, FPoint end)
1126
{
1127
        newPath();
1128
        moveTo(start.x(), start.y());
1129
        lineTo(end.x(), end.y());
1130
        strokePath();
1131
}
1132
 
1133
void ScPainter::drawRect(double x, double y, double w, double h)
1134
{
1135
        newPath();
1136
        moveTo( x, y );
1137
        lineTo( x+w, y );
1138
        lineTo( x+w, y+h );
1139
        lineTo( x, y+h );
1140
        lineTo( x, y );
3113 fschmid 1141
#ifdef HAVE_CAIRO
1142
        cairo_close_path( m_cr );
1143
#else
173 Franz 1144
        ensureSpace( m_index + 1 );
1145
        m_path[ m_index ].code = ART_END;
1146
        m_index++;
3113 fschmid 1147
#endif
68 Franz 1148
        fillPath();
1149
        strokePath();
1150
}
3113 fschmid 1151
 
1152
#ifndef HAVE_CAIRO
1153
void ScPainter::ensureSpace( unsigned int newindex )
1154
{
1155
        if( m_index == 0 )
1156
                {
1157
                if( !m_path )
1158
                        m_path = art_new( ArtBpath, INITIAL_ALLOC );
1159
                m_alloccount = INITIAL_ALLOC;
1160
                }
1161
        else if( newindex > m_alloccount )
1162
                {
1163
                m_alloccount += ALLOC_INCREMENT;
1164
                m_path = art_renew( m_path, ArtBpath, m_alloccount );
1165
                }
1166
}
1167
 
1168
void ScPainter::resize( unsigned int w, unsigned int h )
1169
{
1170
        if( !m_buffer || w != m_width || h != m_height )
1171
        {
1172
                // TODO : realloc?
1173
                art_free( m_buffer );
1174
                m_buffer = 0;
1175
                m_width = w;
1176
                m_height = h;
1177
                if ( m_width != 0 && m_height != 0 )
1178
                        m_buffer = art_new( art_u8, m_width * m_height * 4 );
1179
                clear();
1180
        }
1181
}
1182
 
1183
void ScPainter::clampToViewport( int &x0, int &y0, int &x1, int &y1 )
1184
{
1185
        x0 = QMAX( x0, 0 );
1186
        x0 = QMIN( x0, static_cast<int>( m_width ) );
1187
        y0 = QMAX( y0, 0 );
1188
        y0 = QMIN( y0, static_cast<int>( m_height ) );
1189
        x1 = QMAX( x1, 0 );
1190
        x1 = QMIN( x1, static_cast<int>( m_width ) );
1191
        y1 = QMAX( y1, 0 );
1192
        y1 = QMIN( y1, static_cast<int>( m_height ) );
1193
}
1194
 
4646 subik 1195
void ScPainter::clampToViewport( const _ArtSVP &svp, int &x0, int &y0, int &x1, int &y1 )
3113 fschmid 1196
{
1197
        ArtDRect bbox;
1198
        art_drect_svp( &bbox, &svp );
1199
        x0 = static_cast<int>( bbox.x0 );
1200
        x0 = QMAX( x0, 0 );
1201
        x0 = QMIN( x0, static_cast<int>( m_width ) );
1202
        y0 = static_cast<int>( bbox.y0 );
1203
        y0 = QMAX( y0, 0 );
1204
        y0 = QMIN( y0, static_cast<int>( m_height ) );
1205
        x1 = static_cast<int>( bbox.x1 ) + 1;
1206
        x1 = QMAX( x1, 0 );
1207
        x1 = QMIN( x1, static_cast<int>( m_width ) );
1208
        y1 = static_cast<int>( bbox.y1 ) + 1;
1209
        y1 = QMAX( y1, 0 );
1210
        y1 = QMIN( y1, static_cast<int>( m_height ) );
1211
}
1212
 
4646 subik 1213
void ScPainter::applyGradient( _ArtSVP *svp, bool fill )
3113 fschmid 1214
{
1215
        int x0, y0, x1, y1;
1216
        clampToViewport( *svp, x0, y0, x1, y1 );
1217
        ArtRender *render = 0L;
1218
        VGradient gradient;
1219
        if (fill)
1220
                gradient = fill_gradient;
1221
        else
1222
                gradient = stroke_gradient;
1223
        double opa = fill ? fill_trans : stroke_trans;
1224
        if (gradient.type() == VGradient::linear)
1225
        {
1226
                ArtGradientLinear *linear = art_new( ArtGradientLinear, 1 );
1227
                linear->spread = ART_GRADIENT_PAD;
1228
                double _x1 = static_cast<double>(gradient.origin().x());
1229
                double _x2 = static_cast<double>(gradient.vector().x());
1230
                double _y2 = static_cast<double>(gradient.origin().y());
1231
                double _y1 = static_cast<double>(gradient.vector().y());
1232
                double dx = ( _x2 - _x1 ) * m_zoomFactor;
1233
                _y1 =  _y1 + m_matrix.dy() / m_zoomFactor;
1234
                _y2 =  _y2 + m_matrix.dy() / m_zoomFactor;
1235
                if (dx == 0.0)
1236
                        dx = 1;
1237
                double dy = ( _y1 - _y2 ) * m_zoomFactor;
1238
                if (dy == 0.0)
1239
                        dy = 1;
1240
                double scale = 1.0 / ( dx * dx + dy * dy );
1241
                linear->a = dx * scale;
1242
                linear->b = dy * scale;
1243
                linear->c = -( ( _x1 * m_zoomFactor + m_matrix.dx() ) * linear->a + ( _y2 * m_zoomFactor ) * linear->b );
1244
                int offsets = -1;
1245
                linear->stops = buildStopArray( gradient, offsets );
1246
                linear->n_stops = offsets;
1247
                if( x0 != x1 && y0 != y1 )
1248
                {
1249
                        render = art_render_new( x0, y0, x1, y1, m_buffer + 4 * static_cast<int>(x0) + m_width * 4 * static_cast<int>(y0), m_width * 4, 3, 8, ART_ALPHA_PREMUL, 0 );
1250
                        int opacity = static_cast<int>( opa * 255.0 );
1251
                        art_render_svp( render, svp );
1252
                        art_render_mask_solid (render, (opacity << 8) + opacity + (opacity >> 7));
1253
                        art_karbon_render_gradient_linear( render, linear, ART_FILTER_NEAREST );
1254
                        art_render_invoke( render );
1255
                }
1256
                art_free( linear->stops );
1257
                art_free( linear );
1258
        }
1259
        else if( gradient.type() == VGradient::radial )
1260
        {
1261
                ArtGradientRadial *radial = art_new( ArtGradientRadial, 1 );
1262
                radial->spread = ART_GRADIENT_PAD;
1263
                radial->affine[0] = m_matrix.m11();
1264
                radial->affine[1] = m_matrix.m12();
1265
                radial->affine[2] = m_matrix.m21();
1266
                radial->affine[3] = m_matrix.m22();
1267
                radial->affine[4] = m_matrix.dx();
1268
                radial->affine[5] = m_matrix.dy();
1269
                double cx = gradient.origin().x() * m_zoomFactor;
1270
                double cy = gradient.origin().y() * m_zoomFactor;
1271
                double fx = gradient.focalPoint().x() * m_zoomFactor;
1272
                double fy = gradient.focalPoint().y() * m_zoomFactor;
1273
                double r = sqrt( pow( gradient.vector().x() - gradient.origin().x(), 2 ) + pow( gradient.vector().y() - gradient.origin().y(), 2 ) );
1274
                r *= m_zoomFactor;
1275
                radial->fx = (fx - cx) / r;
1276
                radial->fy = (fy - cy) / r;
1277
                double aff1[6], aff2[6];
1278
                art_affine_scale( aff1, r, r);
1279
                art_affine_translate( aff2, cx, cy );
1280
                art_affine_multiply( aff1, aff1, aff2 );
1281
                art_affine_multiply( aff1, aff1, radial->affine );
1282
                art_affine_invert( radial->affine, aff1 );
1283
                int offsets = -1;
1284
                radial->stops = buildStopArray( gradient, offsets );
1285
                radial->n_stops = offsets;
1286
                if( x0 != x1 && y0 != y1 )
1287
                {
1288
                        render = art_render_new( x0, y0, x1, y1, m_buffer + 4 * x0 + m_width * 4 * y0, m_width * 4, 3, 8, ART_ALPHA_PREMUL, 0 );
1289
                        int opacity = static_cast<int>( opa * 255.0 );
1290
                        art_render_svp( render, svp );
1291
                        art_render_mask_solid (render, (opacity << 8) + opacity + (opacity >> 7));
1292
                        art_karbon_render_gradient_radial( render, radial, ART_FILTER_NEAREST );
1293
                        art_render_invoke( render );
1294
                }
1295
                art_free( radial->stops );
1296
                art_free( radial );
1297
        }
1298
}
1299
 
1300
ArtGradientStop * ScPainter::buildStopArray( VGradient &gradient, int &offsets )
1301
{
1302
        QPtrVector<VColorStop> colorStops = gradient.colorStops();
1303
        offsets = colorStops.count();
1304
        ArtGradientStop *stopArray = art_new( ArtGradientStop, offsets * 2 - 1 );
1305
        for( int offset = 0 ; offset < offsets ; offset++ )
1306
        {
1307
                double ramp = colorStops[ offset ]->rampPoint;
1308
                stopArray[ offset * 2 ].offset = ramp;
1309
                QColor qStopColor = colorStops[ offset ]->color;
1310
                int h, s, v, sneu;
1311
                int shad = colorStops[offset]->shade;
1312
                qStopColor.rgb(&h, &s, &v);
1313
                if ((h == s) && (s == v))
1314
                {
1315
                        qStopColor.hsv(&h, &s, &v);
1316
                        sneu = 255 - ((255 - v) * shad / 100);
1317
                        qStopColor.setHsv(h, s, sneu);
1318
                }
1319
                else
1320
                {
1321
                        qStopColor.hsv(&h, &s, &v);
1322
                        sneu = s * shad / 100;
1323
                        qStopColor.setHsv(h, sneu, v);
1324
                }
1325
                int r = qRed( qStopColor.rgb() );
1326
                int g = qGreen( qStopColor.rgb() );
1327
                int b = qBlue( qStopColor.rgb() );
1328
                art_u32 rgba = (r << 24) | (g << 16) | (b << 8) | qAlpha(qStopColor.rgb());
1329
                int a = static_cast<int>( colorStops[offset]->opacity * 255.0 );
1330
                r = (rgba >> 24) * a + 0x80;
1331
                r = (r + (r >> 8)) >> 8;
1332
                g = ((rgba >> 16) & 0xff) * a + 0x80;
1333
                g = (g + (g >> 8)) >> 8;
1334
                b = ((rgba >> 8) & 0xff) * a + 0x80;
1335
                b = (b + (b >> 8)) >> 8;
1336
                stopArray[ offset * 2 ].color[ 0 ] = ART_PIX_MAX_FROM_8(r);
1337
                stopArray[ offset * 2 ].color[ 1 ] = ART_PIX_MAX_FROM_8(g);
1338
                stopArray[ offset * 2 ].color[ 2 ] = ART_PIX_MAX_FROM_8(b);
1339
                stopArray[ offset * 2 ].color[ 3 ] = ART_PIX_MAX_FROM_8(a);
1340
                if( offset + 1 != offsets )
1341
                {
1342
                        stopArray[ offset * 2 + 1 ].offset = ramp + ( colorStops[ offset + 1 ]->rampPoint - ramp ) * colorStops[ offset ]->midPoint;
1343
                        QColor qStopColor2 = colorStops[ offset + 1 ]->color;
1344
                        rgba = static_cast<int>(r + ((qRed(qStopColor2.rgb()) - r)) * 0.5) << 24 |
1345
                                                 static_cast<int>(g + ((qGreen(qStopColor2.rgb()) - g)) * 0.5) << 16 |
1346
                                                 static_cast<int>(b + ((qBlue(qStopColor2.rgb()) - b)) * 0.5) << 8 |
1347
                                                qAlpha(qStopColor2.rgb());
1348
                        int a = static_cast<int>( colorStops[offset]->opacity * 255.0 );
1349
                        r = (rgba >> 24) * a + 0x80;
1350
                        r = (r + (r >> 8)) >> 8;
1351
                        g = ((rgba >> 16) & 0xff) * a + 0x80;
1352
                        g = (g + (g >> 8)) >> 8;
1353
                        b = ((rgba >> 8) & 0xff) * a + 0x80;
1354
                        b = (b + (b >> 8)) >> 8;
1355
                        stopArray[ offset * 2 + 1 ].color[ 0 ] = ART_PIX_MAX_FROM_8(r);
1356
                        stopArray[ offset * 2 + 1 ].color[ 1 ] = ART_PIX_MAX_FROM_8(g);
1357
                        stopArray[ offset * 2 + 1 ].color[ 2 ] = ART_PIX_MAX_FROM_8(b);
1358
                        stopArray[ offset * 2 + 1 ].color[ 3 ] = ART_PIX_MAX_FROM_8(a);
1359
                }
1360
        }
1361
        offsets = offsets * 2 - 1;
1362
        return stopArray;
1363
}
1364
#endif