Subversion Repositories Scribus

Rev

Rev 5601 | Rev 5619 | 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>
37
#include <cairo-xlib.h>
5471 fschmid 38
#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 1, 6)
39
        #include <cairo-svg.h>
40
#endif
3113 fschmid 41
#else
68 Franz 42
#include <libart_lgpl/art_vpath.h>
43
#include <libart_lgpl/art_bpath.h>
44
#include <libart_lgpl/art_vpath_bpath.h>
45
#include <libart_lgpl/art_svp_vpath.h>
46
#include <libart_lgpl/art_svp_vpath_stroke.h>
47
#include <libart_lgpl/art_svp.h>
48
#include <libart_lgpl/art_svp_ops.h>
49
#include <libart_lgpl/art_affine.h>
50
#include <libart_lgpl/art_svp_intersect.h>
51
#include <libart_lgpl/art_rect_svp.h>
52
#include <libart_lgpl/art_pathcode.h>
53
#include <libart_lgpl/art_vpath_dash.h>
54
#include <libart_lgpl/art_render_svp.h>
55
#include <libart_lgpl/art_vpath_svp.h>
3369 craig 56
#include "libart/art_render_misc.h"
57
#include "libart/art_rgb_svp.h"
58
#include "libart/art_render_pattern.h"
59
#include "libart/art_kmisc.h"
3113 fschmid 60
#define INITIAL_ALLOC   300
61
#define ALLOC_INCREMENT 100
62
#endif
68 Franz 63
 
1669 craig 64
#if defined(Q_WS_X11) && defined(SC_USE_PIXBUF)
68 Franz 65
#include <X11/Xlib.h>
5064 cbradney 66
#include "pixbuf/gdk-pixbuf-xlibrgb.h"
1669 craig 67
#endif
68 Franz 68
 
2686 craig 69
#if defined(_WIN32) && defined(SC_USE_GDI)
70
#include <windows.h>
71
#endif
72
 
68 Franz 73
#include <math.h>
74
 
1624 fschmid 75
ScPainter::ScPainter( QPaintDevice *target, unsigned int w, unsigned int h, unsigned int x, unsigned int y )
68 Franz 76
{
77
        m_target = target;
78
        m_width = w;
79
        m_height= h;
1624 fschmid 80
        m_x = x;
81
        m_y = y;
68 Franz 82
        m_buffer = 0L;
3113 fschmid 83
#ifndef HAVE_CAIRO
68 Franz 84
        m_path = 0L;
3113 fschmid 85
#endif
68 Franz 86
        m_index = 0;
87
        m_stroke = QColor(0,0,0);
88
        m_fill = QColor(0,0,0);
89
        fill_trans = 1.0;
90
        stroke_trans = 1.0;
91
        m_fillRule = true;
92
        fillMode = 1;
93
        LineWidth = 1.0;
94
        m_offset = 0;
95
        m_array.clear();
96
        mf_underline = false;
97
        mf_strikeout = false;
98
        mf_shadow = false;
99
        mf_outlined = false;
205 Franz 100
        PLineEnd = Qt::SquareCap;
101
        PLineJoin = Qt::RoundJoin;
68 Franz 102
        fill_gradient = VGradient(VGradient::linear);
103
        stroke_gradient = VGradient(VGradient::linear);
1669 craig 104
        m_zoomFactor = 1;
1815 fschmid 105
        imageMode = false;
3113 fschmid 106
        m_matrix = QWMatrix();
1669 craig 107
#if defined(Q_WS_X11) && defined(SC_USE_PIXBUF)
3113 fschmid 108
#ifdef HAVE_CAIRO
5373 fschmid 109
        layeredMode = false;
5471 fschmid 110
        svgMode = false;
3113 fschmid 111
        pixm = QPixmap(w, h);
112
        Display *dpy = pixm.x11AppDisplay();
113
        Drawable drw = pixm.handle();
114
        cairo_surface_t *img;
115
        img = cairo_xlib_surface_create(dpy, drw, (Visual*)pixm.x11Visual(), w, h);
116
        m_cr = cairo_create(img);
117
        clear();
118
        cairo_save( m_cr );
119
        cairo_set_fill_rule (m_cr, CAIRO_FILL_RULE_EVEN_ODD);
3173 fschmid 120
        cairo_set_operator(m_cr, CAIRO_OPERATOR_OVER);
3120 fschmid 121
/*      Setting to 0.5 here gives a good tradeoff between speed and precision
122
        the former setting of 0.2 is just too precise, and setting it to 0.9 or greater will give bad rendering */
123
        cairo_set_tolerance( m_cr, 0.5 );
3113 fschmid 124
#else
125
        resize( m_width, m_height );
126
        clear();
1624 fschmid 127
        xlib_rgb_init_with_depth( target->x11Display(), XScreenOfDisplay( target->x11Display(), target->x11Screen() ), target->x11Depth() );
68 Franz 128
        gc = XCreateGC( target->x11Display(), target->handle(), 0, 0 );
3113 fschmid 129
#endif
2686 craig 130
#elif defined(_WIN32) && defined(SC_USE_GDI)
3113 fschmid 131
        resize( m_width, m_height );
132
        clear();
2686 craig 133
        dc = CreateCompatibleDC( target->handle() );
3175 avox 134
#else
135
        resize( m_width, m_height );
136
        clear();
1669 craig 137
#endif
68 Franz 138
}
139
 
1815 fschmid 140
ScPainter::ScPainter( QImage *target, unsigned int w, unsigned int h, unsigned int x, unsigned int y )
141
{
142
        m_target = 0L;
143
        m_width = w;
144
        m_height= h;
145
        m_x = x;
146
        m_y = y;
147
        m_buffer = 0L;
3113 fschmid 148
        m_index = 0;
1815 fschmid 149
        m_stroke = QColor(0,0,0);
150
        m_fill = QColor(0,0,0);
151
        fill_trans = 1.0;
152
        stroke_trans = 1.0;
153
        m_fillRule = true;
154
        fillMode = 1;
155
        LineWidth = 1.0;
156
        m_offset = 0;
157
        m_array.clear();
158
        mf_underline = false;
159
        mf_strikeout = false;
160
        mf_shadow = false;
161
        mf_outlined = false;
162
        PLineEnd = Qt::SquareCap;
163
        PLineJoin = Qt::RoundJoin;
164
        fill_gradient = VGradient(VGradient::linear);
165
        stroke_gradient = VGradient(VGradient::linear);
166
        m_zoomFactor = 1;
167
        imageMode = true;
168
        m_image = target;
5260 fschmid 169
        m_matrix = QWMatrix();
3376 fschmid 170
#ifdef HAVE_CAIRO
5373 fschmid 171
        layeredMode = false;
5471 fschmid 172
        svgMode = false;
3376 fschmid 173
        cairo_surface_t *img = cairo_image_surface_create_for_data(target->bits(), CAIRO_FORMAT_ARGB32, w, h, w*4);
174
        m_cr = cairo_create(img);
175
        clear();
176
        cairo_save( m_cr );
177
        cairo_set_fill_rule (m_cr, CAIRO_FILL_RULE_EVEN_ODD);
178
        cairo_set_operator(m_cr, CAIRO_OPERATOR_OVER);
179
/*      Setting to 0.5 here gives a good tradeoff between speed and precision
180
        the former setting of 0.2 is just too precise, and setting it to 0.9 or greater will give bad rendering */
181
        cairo_set_tolerance( m_cr, 0.5 );
182
#else
183
        resize( m_width, m_height );
184
        clear();
185
        m_path = 0L;
186
#endif
1815 fschmid 187
}
188
 
5373 fschmid 189
#ifdef HAVE_CAIRO
190
ScPainter::ScPainter( QImage *target, unsigned int w, unsigned int h, double transparency, int blendmode )
191
{
192
        m_target = 0L;
193
        m_width = w;
194
        m_height= h;
195
        m_buffer = 0L;
196
        m_index = 0;
197
        m_stroke = QColor(0,0,0);
198
        m_fill = QColor(0,0,0);
199
        fill_trans = 1.0;
200
        stroke_trans = 1.0;
201
        m_fillRule = true;
202
        fillMode = 1;
203
        LineWidth = 1.0;
204
        m_offset = 0;
205
        m_layerTransparency = transparency;
206
        m_blendMode = blendmode;
207
        m_array.clear();
208
        mf_underline = false;
209
        mf_strikeout = false;
210
        mf_shadow = false;
211
        mf_outlined = false;
212
        PLineEnd = Qt::SquareCap;
213
        PLineJoin = Qt::RoundJoin;
214
        fill_gradient = VGradient(VGradient::linear);
215
        stroke_gradient = VGradient(VGradient::linear);
216
        m_zoomFactor = 1;
217
        layeredMode = true;
218
        imageMode = true;
5471 fschmid 219
        svgMode = false;
5373 fschmid 220
        m_image = target;
221
        m_matrix = QWMatrix();
5471 fschmid 222
#if CAIRO_VERSION < CAIRO_VERSION_ENCODE(1, 1, 6)
5469 fschmid 223
        tmp_image = QImage(w, h, 32, QImage::BigEndian);
5373 fschmid 224
        tmp_image.fill( qRgba(255, 255, 255, 0) );
225
        cairo_surface_t *img = cairo_image_surface_create_for_data(tmp_image.bits(), CAIRO_FORMAT_ARGB32, w, h, w*4);
226
        m_cr = cairo_create(img);
227
        clear();
5471 fschmid 228
#else
229
        m_image->fill( qRgba(255, 255, 255, 0) );
230
        cairo_surface_t *img = cairo_image_surface_create_for_data(m_image->bits(), CAIRO_FORMAT_ARGB32, w, h, w*4);
231
        m_cr = cairo_create(img);
232
#endif
5373 fschmid 233
        cairo_save( m_cr );
234
        cairo_set_fill_rule (m_cr, CAIRO_FILL_RULE_EVEN_ODD);
235
        cairo_set_operator(m_cr, CAIRO_OPERATOR_OVER);
236
        cairo_set_tolerance( m_cr, 0.5 );
237
}
5471 fschmid 238
 
239
#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 1, 6)
240
ScPainter::ScPainter( QString target, unsigned int w, unsigned int h, double transparency, int blendmode )
241
{
242
        m_target = 0L;
243
        m_width = w;
244
        m_height= h;
245
        m_buffer = 0L;
246
        m_index = 0;
247
        m_stroke = QColor(0,0,0);
248
        m_fill = QColor(0,0,0);
249
        fill_trans = 1.0;
250
        stroke_trans = 1.0;
251
        m_fillRule = true;
252
        fillMode = 1;
253
        LineWidth = 1.0;
254
        m_offset = 0;
255
        m_layerTransparency = transparency;
256
        m_blendMode = blendmode;
257
        m_array.clear();
258
        mf_underline = false;
259
        mf_strikeout = false;
260
        mf_shadow = false;
261
        mf_outlined = false;
262
        PLineEnd = Qt::SquareCap;
263
        PLineJoin = Qt::RoundJoin;
264
        fill_gradient = VGradient(VGradient::linear);
265
        stroke_gradient = VGradient(VGradient::linear);
266
        m_zoomFactor = 1;
267
        layeredMode = true;
268
        imageMode = false;
269
        svgMode = true;
270
        m_matrix = QWMatrix();
271
        cairo_surface_t *img = cairo_svg_surface_create(target, w, h);
272
        m_cr = cairo_create(img);
273
        cairo_save( m_cr );
274
        cairo_set_fill_rule (m_cr, CAIRO_FILL_RULE_EVEN_ODD);
275
        cairo_set_operator(m_cr, CAIRO_OPERATOR_OVER);
276
        cairo_set_tolerance( m_cr, 0.5 );
277
}
5373 fschmid 278
#endif
279
 
5471 fschmid 280
#endif
281
 
68 Franz 282
ScPainter::~ScPainter()
283
{
284
        // If we are in target mode, we created a buffer, else if we used the other ctor
285
        // we didnt.
3113 fschmid 286
#ifndef HAVE_CAIRO
1815 fschmid 287
        if (( m_target ) || ( imageMode))
68 Franz 288
                art_free( m_buffer );
289
        if( m_path )
290
                art_free( m_path );
3113 fschmid 291
#endif
1669 craig 292
#if defined(Q_WS_X11) && defined(SC_USE_PIXBUF)
3113 fschmid 293
#ifdef HAVE_CAIRO
4447 fschmid 294
        cairo_surface_destroy(cairo_get_target(m_cr));
3113 fschmid 295
        cairo_destroy( m_cr );
296
#else
5471 fschmid 297
        if ((imageMode) || (svgMode))
3376 fschmid 298
                return;
68 Franz 299
        if( gc )
300
                XFreeGC( m_target->x11Display(), gc );
3113 fschmid 301
#endif
2686 craig 302
#elif defined(_WIN32) && defined(SC_USE_GDI)
3376 fschmid 303
        if (imageMode)
304
                return;
2686 craig 305
        if( dc )
306
                DeleteDC( dc );
1669 craig 307
#endif
68 Franz 308
}
309
 
5373 fschmid 310
#ifdef HAVE_CAIRO
311
void ScPainter::beginLayer(double transparency, int blendmode)
312
{
5604 fschmid 313
#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 1, 6)
314
        layerProp la;
315
        #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 1, 8)
316
        la.data = cairo_get_group_target(m_cr);
317
        #endif
318
        la.blendmode = m_blendMode;
319
        la.tranparency = m_layerTransparency;
320
        Layers.push(la);
5373 fschmid 321
        m_layerTransparency = transparency;
322
        m_blendMode = blendmode;
5471 fschmid 323
        cairo_push_group(m_cr);
5604 fschmid 324
        #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 1, 8)
325
        cairo_surface_t *tmp2 = cairo_get_group_target(m_cr);
326
        if (tmp2 != NULL)
327
        {
328
                if (cairo_surface_get_type(tmp2) == CAIRO_SURFACE_TYPE_IMAGE)
329
                {
330
                        int stride = cairo_image_surface_get_stride(tmp2);
331
                        unsigned char *s = cairo_image_surface_get_data(tmp2);
332
                        int h = m_image->height();
333
                        for( int yi=0; yi < h; ++yi )
334
                        {
335
                                memset( s, 0, stride );
336
                                s += stride;
337
                        }
338
                }
339
                cairo_surface_mark_dirty(tmp2);
340
        }
341
        #endif
5471 fschmid 342
#else
5373 fschmid 343
        tmp_image.fill( qRgba(255, 255, 255, 0) );
5471 fschmid 344
#endif
5373 fschmid 345
}
346
 
347
static unsigned char INT_MULT ( unsigned char a, unsigned char b )
348
{
349
        int c = a * b + 0x80;
350
        return (unsigned char)(( ( c >> 8 ) + c ) >> 8);
351
}
352
 
353
void ScPainter::endLayer()
354
{
5471 fschmid 355
#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 1, 6)
5601 fschmid 356
        #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 1, 8)
5604 fschmid 357
        if ((m_blendMode != 0) && (Layers.count() != 1))
5601 fschmid 358
        {
359
                cairo_surface_t *tmp = cairo_get_group_target(m_cr);
5604 fschmid 360
                cairo_surface_t *tmpB = Layers.top().data;
361
                if ((tmp != NULL) && (tmpB != NULL))
5601 fschmid 362
                {
5604 fschmid 363
                        if ((cairo_surface_get_type(tmp) == CAIRO_SURFACE_TYPE_IMAGE) && (cairo_surface_get_type(tmpB) == CAIRO_SURFACE_TYPE_IMAGE))
5601 fschmid 364
                        {
365
                                cairo_surface_flush(tmp);
366
                                int stride = cairo_image_surface_get_stride(tmp);
367
                                unsigned char *s = cairo_image_surface_get_data(tmp);
5604 fschmid 368
                                unsigned char *d = cairo_image_surface_get_data(tmpB);
5601 fschmid 369
                                int h = m_image->height();
370
                                int w = m_image->width();
371
                                for( int yi=0; yi < h; ++yi )
372
                                {
5604 fschmid 373
                                        QRgb *dst = (QRgb*)d;
5601 fschmid 374
                                        QRgb *src = (QRgb*)s;
375
                                        for( int xi=0; xi < w; ++xi )
376
                                        {
377
                                                uchar src_r = qRed(*src);
378
                                                uchar src_g = qGreen(*src);
379
                                                uchar src_b = qBlue(*src);
380
                                                uchar src_a = qAlpha(*src);
381
                                                uchar dst_r = qRed(*dst);
382
                                                uchar dst_g = qGreen(*dst);
383
                                                uchar dst_b = qBlue(*dst);
384
                                                uchar dst_a = qAlpha(*dst);
385
                                                if ((src_a > 0) && (dst_a > 0))
386
                                                {
387
                                                        if (m_blendMode == 1)
388
                                                        {
389
                                                                src_r = dst_r  < src_r ? dst_r  : src_r;
390
                                                                src_g = dst_g < src_g ? dst_g : src_g;
391
                                                                src_b = dst_b < src_b ? dst_b : src_b;
392
                                                        }
393
                                                        else if (m_blendMode == 2)
394
                                                        {
5604 fschmid 395
                                                                src_r = dst_r  < src_r ? src_r : dst_r;
5601 fschmid 396
                                                                src_g = dst_g < src_g ? src_g : dst_g;
397
                                                                src_b = dst_b < src_b ? src_b : dst_b;
398
                                                        }
399
                                                        else if (m_blendMode == 3)
400
                                                        {
401
                                                                src_r = INT_MULT(src_r, dst_r);
402
                                                                src_g = INT_MULT(src_g, dst_g);
403
                                                                src_b = INT_MULT(src_b, dst_b);
404
                                                        }
405
                                                        else if (m_blendMode == 4)
406
                                                        {
407
                                                                src_r = 255 - INT_MULT(255 - dst_r, 255 - src_r);
408
                                                                src_g = 255 - INT_MULT(255 - dst_g, 255 - src_g);
409
                                                                src_b = 255 - INT_MULT(255 - dst_b, 255 - src_b);
410
                                                        }
411
                                                        else if (m_blendMode == 5)
412
                                                        {
413
                                                                src_r = INT_MULT(dst_r, dst_r + INT_MULT(2 * src_r, 255 - dst_r));
414
                                                                src_g = INT_MULT(dst_g, dst_g + INT_MULT(2 * src_g, 255 - dst_g));
415
                                                                src_b = INT_MULT(dst_b, dst_b + INT_MULT(2 * src_b, 255 - dst_b));
416
                                                        }
417
                                                        else if (m_blendMode == 6)
418
                                                        {
419
                                                                src_r = src_r < 128 ? src_r * dst_r / 128 : 255 - ((255-src_r) * (255-dst_r) / 128);
420
                                                                src_g = src_g < 128 ? src_g * dst_g / 128 : 255 - ((255-src_g) * (255-dst_g) / 128);
421
                                                                src_b = src_b < 128 ? src_b * dst_b / 128 : 255 - ((255-src_b) * (255-dst_b) / 128);
422
                                                        }
423
                                                        else if (m_blendMode == 7)
424
                                                        {
425
                                                                src_r = src_r * dst_r / 256 + src_r * (255 - ((255-src_r)*(255-dst_r) / 256) - src_r * dst_r / 256) / 256;
426
                                                                src_g = src_g * dst_g / 256 + src_g * (255 - ((255-src_g)*(255-dst_g) / 256) - src_g * dst_g / 256) / 256;
427
                                                                src_b = src_b * dst_b / 256 + src_b * (255 - ((255-src_b)*(255-dst_b) / 256) - src_b * dst_b / 256) / 256;
428
                                                        }
429
                                                        else if (m_blendMode == 8)
430
                                                        {
431
                                                                src_r = dst_r > src_r ? dst_r - src_r : src_r - dst_r;
432
                                                                src_g = dst_g > src_g ? dst_g - src_g : src_g - dst_g;
433
                                                                src_b = dst_b > src_b ? dst_b - src_b : src_b - dst_b;
434
                                                        }
435
                                                        else if (m_blendMode == 9)
436
                                                        {
437
                                                                src_r = dst_r + src_r - src_r * dst_r / 128;
438
                                                                src_g = dst_g + src_g - src_g * dst_g / 128;
439
                                                                src_b = dst_b + src_b - src_b * dst_b / 128;
440
                                                        }
441
                                                        else if (m_blendMode == 10)
442
                                                        {
443
                                                                src_r = src_r == 255 ? 255 : ((dst_r * 256) / (255-src_r)) > 255 ? 255 : (dst_r * 256) / (255-src_r);
444
                                                                src_g = src_g == 255 ? 255 : ((dst_g * 256) / (255-src_g)) > 255 ? 255 : (dst_g * 256) / (255-src_g);
445
                                                                src_b = src_b == 255 ? 255 : ((dst_b * 256) / (255-src_b)) > 255 ? 255 : (dst_b * 256) / (255-src_b);
446
                                                        }
447
                                                        else if (m_blendMode == 11)
448
                                                        {
449
                                                                src_r = src_r == 0 ? 0 : (255 - (((255-dst_r) * 256) / src_r)) < 0 ? 0 : 255 - (((255-dst_r) * 256) / src_r);
450
                                                                src_g = src_g == 0 ? 0 : (255 - (((255-dst_g) * 256) / src_g)) < 0 ? 0 : 255 - (((255-dst_g) * 256) / src_g);
451
                                                                src_b = src_b == 0 ? 0 : (255 - (((255-dst_b) * 256) / src_b)) < 0 ? 0 : 255 - (((255-dst_b) * 256) / src_b);
452
                                                        }
453
                                                        else if (m_blendMode == 12)
454
                                                        {
455
                /*                                              This code is a blendmode that simulates the effect of overprinting
456
                                                                Works by converting source and destination colour to CMYK and adding them together
457
                                                                Finally the result is converted back to RGB */
458
                                                                int K1 = QMIN(QMIN(255 - src_r, 255 - src_g), 255 - src_b);
459
                                                                int K2 = QMIN(QMIN(255 - dst_r, 255 - dst_g), 255 - dst_b);
460
                                                                int C = QMIN(QMIN(255 - src_r - K1, 255) + QMIN(255 - dst_r - K2, 255), 255);
461
                                                                int M = QMIN(QMIN(255 - src_g - K1, 255) + QMIN(255 - dst_g - K2, 255), 255) ;
462
                                                                int Y = QMIN(QMIN(255 - src_b - K1, 255) + QMIN(255 - dst_b - K2, 255), 255) ;
463
                                                                int K = QMIN(K1 + K2, 255);
464
                                                                src_r = 255 - QMIN(255, C + K);
465
                                                                src_g = 255 - QMIN(255, M + K);
466
                                                                src_b = 255 - QMIN(255, Y+ K);
467
                                                        }
468
                                                        (*src) = qRgba(src_r, src_g, src_b, src_a);
469
                                                }
470
                                                src++;
471
                                                dst++;
472
                                        }
473
                                        s += stride;
5604 fschmid 474
                                        d += stride;
5601 fschmid 475
                                }
476
                                cairo_surface_mark_dirty(tmp);
477
                        }
478
                }
479
        }
480
        #endif
5604 fschmid 481
        layerProp la;
482
        la = Layers.pop();
5471 fschmid 483
        cairo_pop_group_to_source (m_cr);
5601 fschmid 484
        cairo_set_operator(m_cr, CAIRO_OPERATOR_OVER);
5471 fschmid 485
        cairo_paint_with_alpha (m_cr, m_layerTransparency);
5604 fschmid 486
        m_layerTransparency = la.tranparency;
487
        m_blendMode = la.blendmode;
5471 fschmid 488
#else
5373 fschmid 489
        cairo_surface_flush(cairo_get_target(m_cr));
490
        int words = m_image->numBytes() / 4;
491
        QRgb *s = (QRgb*)(tmp_image.bits());
492
        QRgb *d = (QRgb*)(m_image->bits());
493
        for(int x = 0; x < words; ++x )
494
        {
5433 fschmid 495
                QRgb src = (*s);
496
                QRgb dst = (*d);
497
                uchar src_a = qAlpha(src);
5469 fschmid 498
                if (src_a > 0)
5373 fschmid 499
                {
500
                        uchar src_r = qRed(src);
501
                        uchar src_g = qGreen(src);
502
                        uchar src_b = qBlue(src);
503
                        uchar dst_a = qAlpha(dst);
504
                        uchar dst_r = qRed(dst);
505
                        uchar dst_g = qGreen(dst);
506
                        uchar dst_b = qBlue(dst);
5433 fschmid 507
                        int layOpa = qRound(255 * m_layerTransparency);
508
                        src_a = INT_MULT(src_a, layOpa);
5469 fschmid 509
                        if ((dst_a > 0) && (src_a > 0))
5433 fschmid 510
                                (*d) = qRgba((dst_r * (255 - layOpa) + src_r * layOpa) / 255, (dst_g * (255 - layOpa) + src_g * layOpa) / 255, (dst_b * (255 - layOpa) + src_b * layOpa) / 255, dst_a + INT_MULT(255 - dst_a, src_a));
5469 fschmid 511
                        else if (src_a > 0)
5433 fschmid 512
                                (*d) = qRgba(src_r, src_g, src_b, src_a);
5373 fschmid 513
                }
514
                s++;
515
                d++;
516
        }
5471 fschmid 517
#endif
5373 fschmid 518
}
519
#endif
520
 
68 Franz 521
void ScPainter::begin()
522
{
523
}
524
 
525
void ScPainter::end()
526
{
5373 fschmid 527
#ifdef HAVE_CAIRO
5471 fschmid 528
        if (svgMode)
529
                cairo_show_page (m_cr);
5373 fschmid 530
        if (layeredMode)
531
        {
5471 fschmid 532
#if CAIRO_VERSION < CAIRO_VERSION_ENCODE(1, 1, 6)
5373 fschmid 533
                endLayer();
5471 fschmid 534
#endif
5433 fschmid 535
                cairo_surface_flush(cairo_get_target(m_cr));
5373 fschmid 536
                cairo_restore( m_cr );
537
                return;
538
        }
539
#endif
1815 fschmid 540
        if (imageMode)
541
        {
3376 fschmid 542
#ifdef HAVE_CAIRO
543
                cairo_surface_flush(cairo_get_target(m_cr));
544
                cairo_restore( m_cr );
545
#else
1815 fschmid 546
                QRgb * bits = (QRgb *) m_image->bits();
547
                int words = m_image->numBytes() / 4;
548
                art_u8 * p = m_buffer;;
549
                for (int i=0; i < words; ++i)
550
                {
551
                        art_u8 r = *p++;
552
                        art_u8 g = *p++;
553
                        art_u8 b = *p++;
554
                        art_u8 a = *p++;
555
                        *bits++ = qRgba(r,g,b,a);
556
                }
3113 fschmid 557
#endif
1815 fschmid 558
        }
559
        else
560
        {
1669 craig 561
#if defined(Q_WS_X11) && defined(SC_USE_PIXBUF)
3113 fschmid 562
#ifdef HAVE_CAIRO
563
                cairo_surface_flush(cairo_get_target(m_cr));
564
                bitBlt( m_target, m_x, m_y, &pixm, 0, 0, m_width, m_height );
565
                cairo_restore( m_cr );
566
#else
1815 fschmid 567
                // Use the original gdk-pixbuf based bitblit on X11
568
                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 );
3113 fschmid 569
#endif
2686 craig 570
#elif defined(_WIN32) && defined(SC_USE_GDI)
571
                // Use Win32 implementation
572
                BITMAPINFO bmpInfo;
573
                BITMAPINFOHEADER *bmpHeader;
574
                long* bmpData;
575
 
576
                bmpHeader = &(bmpInfo.bmiHeader);
577
                bmpHeader->biSize = sizeof(BITMAPINFOHEADER);
578
                bmpHeader->biWidth = m_width;
579
                bmpHeader->biHeight = -m_height;
580
                bmpHeader->biPlanes = 1;
581
                bmpHeader->biBitCount = 32;
582
                bmpHeader->biCompression = BI_RGB;
583
                bmpHeader->biSizeImage = 0; // Valid only if biCompression = BI_RGB
584
                bmpHeader->biXPelsPerMeter = 0;
585
                bmpHeader->biYPelsPerMeter = 0;
586
                bmpHeader->biClrUsed = 0;
587
                bmpHeader->biClrImportant = 0;
588
 
589
                // Create a device independent Bitmap
590
                HBITMAP hBmp = CreateDIBSection(dc, &bmpInfo, DIB_RGB_COLORS, (void** ) (&bmpData), NULL, NULL);
591
                art_u8 * p = m_buffer;
592
                art_u8 r, g, b, a;
593
                int words = m_width * m_height; // Valid only if biBitCount = 32
594
 
595
                for (int i = 0; i < words; ++i) {
596
                        r = *p++;
597
                        g = *p++;
598
                        b = *p++;
599
                        a = *p++;
600
                        *bmpData++ = ( (a << 24) + (r << 16) + (g << 8) + b);
601
                }
602
 
603
                HGDIOBJ obj = SelectObject( dc, hBmp);
604
                BitBlt( m_target->handle() , m_x, m_y, m_width, m_height, dc, 0, 0, SRCCOPY);
605
                SelectObject( dc, obj);
606
                DeleteObject( hBmp );
1669 craig 607
#else
1815 fschmid 608
                // Portable copying onto the canvas with no X11 dependency by Andreas Vox
609
                QImage qimg(m_width, m_height, 32, QImage::BigEndian);
610
                QRgb * bits = (QRgb *) qimg.bits();
611
                int words = qimg.numBytes() / 4;
612
                art_u8 * p = m_buffer;;
613
                for (int i=0; i < words; ++i) {
614
                        art_u8 r = *p++;
615
                        art_u8 g = *p++;
616
                        art_u8 b = *p++;
617
                        art_u8 a = *p++;
618
                        *bits++ = qRgba(r,g,b,a);
619
                }
620
                bitBlt(m_target, m_x, m_y, &qimg);
621
#endif
1669 craig 622
        }
68 Franz 623
}
624
 
1624 fschmid 625
void ScPainter::clear()
68 Franz 626
{
3113 fschmid 627
#ifdef HAVE_CAIRO
3376 fschmid 628
        if (imageMode)
629
                m_image->fill( qRgba(255, 255, 255, 255) );
630
        else
631
                pixm.fill( Qt::white );
3113 fschmid 632
#else
68 Franz 633
        if( m_buffer )
214 Franz 634
                memset( m_buffer, 255, m_width * m_height * 4 );
3113 fschmid 635
#endif
68 Franz 636
}
637
 
1624 fschmid 638
void ScPainter::clear( const QColor &c )
68 Franz 639
{
3113 fschmid 640
#ifdef HAVE_CAIRO
3376 fschmid 641
        QRgb cs = c.rgb();
642
        if (imageMode)
643
                m_image->fill( qRgba(qRed(cs), qGreen(cs), qBlue(cs), qAlpha(cs)) );
644
        else
645
                pixm.fill( c );
3113 fschmid 646
#else
68 Franz 647
        if( m_buffer )
214 Franz 648
        {
649
                unsigned int *src = (unsigned int*)m_buffer;
650
                unsigned int co = qRgba(c.blue(), c.green(),  c.red(), 255);
651
                for(unsigned int cc = 0; cc < (m_width * m_height); ++cc)
652
                {
653
                        *src++ = co;
654
                }
655
        }
3113 fschmid 656
#endif
68 Franz 657
}
658
 
3113 fschmid 659
const QWMatrix ScPainter::worldMatrix()
660
{
661
#ifdef HAVE_CAIRO
662
        cairo_matrix_t matrix;
663
        cairo_get_matrix(m_cr, &matrix);
664
        QWMatrix mat;
665
        mat.setMatrix ( matrix.xx, matrix.yx, matrix.xy, matrix.yy, matrix.x0, matrix.y0 );
666
        return mat;
667
#else
668
        return m_matrix;
669
#endif
670
}
671
 
68 Franz 672
void ScPainter::setWorldMatrix( const QWMatrix &mat )
673
{
3113 fschmid 674
#ifdef HAVE_CAIRO
675
        cairo_matrix_t matrix;
676
        cairo_matrix_init(&matrix, mat.m11(), mat.m12(), mat.m21(), mat.m22(), mat.dx(), mat.dy());
677
        cairo_set_matrix(m_cr, &matrix);
678
#else
68 Franz 679
        m_matrix = mat;
3113 fschmid 680
#endif
68 Franz 681
}
682
 
683
void ScPainter::setZoomFactor( double zoomFactor )
684
{
685
        m_zoomFactor = zoomFactor;
686
}
687
 
688
void ScPainter::translate( double x, double y )
689
{
3113 fschmid 690
#ifdef HAVE_CAIRO
691
        cairo_translate (m_cr, x, y);
692
#else
68 Franz 693
        m_matrix.translate(x, y);
3113 fschmid 694
#endif
68 Franz 695
}
696
 
697
void ScPainter::rotate( double r )
698
{
3113 fschmid 699
#ifdef HAVE_CAIRO
700
        cairo_rotate (m_cr, r * 3.1415927 / 180.0);
701
#else
68 Franz 702
        m_matrix.rotate(r);
3113 fschmid 703
#endif
68 Franz 704
}
705
 
706
void ScPainter::scale( double x, double y )
707
{
3113 fschmid 708
#ifdef HAVE_CAIRO
709
        cairo_scale (m_cr, x, y);
710
#else
68 Franz 711
        m_matrix.scale(x, y);
3113 fschmid 712
#endif
68 Franz 713
}
714
 
715
void ScPainter::moveTo( const double &x, const double &y )
716
{
3113 fschmid 717
#ifdef HAVE_CAIRO
718
        cairo_move_to( m_cr, x * m_zoomFactor, y * m_zoomFactor);
719
#else
68 Franz 720
        ensureSpace( m_index + 1 );
721
        m_path[ m_index ].code = ART_MOVETO;
722
        m_path[ m_index ].x3 = x * m_zoomFactor;
723
        m_path[ m_index ].y3 = y * m_zoomFactor;
724
        m_index++;
3113 fschmid 725
#endif
68 Franz 726
}
727
 
4646 subik 728
void
68 Franz 729
ScPainter::lineTo( const double &x, const double &y )
730
{
3113 fschmid 731
#ifdef HAVE_CAIRO
732
        cairo_line_to( m_cr, x * m_zoomFactor, y * m_zoomFactor);
733
#else
68 Franz 734
        ensureSpace( m_index + 1 );
735
        m_path[ m_index ].code = ART_LINETO;
736
        m_path[ m_index ].x3    = x * m_zoomFactor;
737
        m_path[ m_index ].y3    = y * m_zoomFactor;
738
        m_index++;
3113 fschmid 739
#endif
68 Franz 740
}
741
 
742
void ScPainter::curveTo( FPoint p1, FPoint p2, FPoint p3 )
743
{
3113 fschmid 744
#ifdef HAVE_CAIRO
4646 subik 745
        cairo_curve_to(m_cr,
746
                                                                p1.x() * m_zoomFactor,
747
                                                                p1.y() * m_zoomFactor,
748
                                                                p2.x() * m_zoomFactor,
749
                                                                p2.y() * m_zoomFactor,
750
                                                                p3.x() * m_zoomFactor,
3113 fschmid 751
                                                                p3.y() * m_zoomFactor);
752
#else
68 Franz 753
        ensureSpace( m_index + 1 );
754
        m_path[ m_index ].code = ART_CURVETO;
86 Franz 755
        m_path[ m_index ].x1    = p1.x() * m_zoomFactor;
756
        m_path[ m_index ].y1    = p1.y() * m_zoomFactor;
757
        m_path[ m_index ].x2    = p2.x() * m_zoomFactor;
758
        m_path[ m_index ].y2    = p2.y() * m_zoomFactor;
759
        m_path[ m_index ].x3    = p3.x() * m_zoomFactor;
760
        m_path[ m_index ].y3    = p3.y() * m_zoomFactor;
68 Franz 761
        m_index++;
3113 fschmid 762
#endif
68 Franz 763
}
764
 
765
void ScPainter::newPath()
766
{
3113 fschmid 767
#ifdef HAVE_CAIRO
768
        cairo_new_path( m_cr );
769
#else
68 Franz 770
        m_index = 0;
3113 fschmid 771
#endif
68 Franz 772
}
773
 
5233 fschmid 774
void ScPainter::closePath()
775
{
776
#ifdef HAVE_CAIRO
777
        cairo_close_path( m_cr );
778
#else
779
        ensureSpace( m_index + 1 );
780
        m_path[ m_index ].code = ART_END;
781
        m_index++;
782
#endif
783
}
784
 
68 Franz 785
void ScPainter::setFillRule( bool fillRule )
786
{
787
        m_fillRule = fillRule;
788
}
789
 
790
void ScPainter::setFillMode( int fill )
791
{
792
        fillMode = fill;
793
}
794
 
795
void ScPainter::setGradient(VGradient::VGradientType mode, FPoint orig, FPoint vec, FPoint foc)
796
{
797
        fill_gradient.setType(mode);
798
        fill_gradient.setOrigin(orig);
799
        fill_gradient.setVector(vec);
800
        fill_gradient.setFocalPoint(foc);
801
}
802
 
1998 fschmid 803
void ScPainter::fillTextPath()
804
{
3113 fschmid 805
#ifdef HAVE_CAIRO
806
        drawVPath( 0 );
807
#else
1998 fschmid 808
        ArtVpath *path = art_bez_path_to_vec( m_path , 0.25 );
809
        drawVPath( path, 0, true );
3113 fschmid 810
#endif
1998 fschmid 811
}
812
 
813
void ScPainter::strokeTextPath()
814
{
815
        if( LineWidth == 0 )
816
                return;
3113 fschmid 817
#ifdef HAVE_CAIRO
818
        drawVPath( 1 );
819
#else
1998 fschmid 820
        ArtVpath *path = art_bez_path_to_vec( m_path , 0.25 );
821
        drawVPath( path, 1, true );
3113 fschmid 822
#endif
1998 fschmid 823
}
824
 
68 Franz 825
void ScPainter::fillPath()
826
{
3113 fschmid 827
#ifdef HAVE_CAIRO
828
        if( fillMode != 0)
829
                drawVPath( 0 );
830
#else
4646 subik 831
        if( m_index == 0 )
1998 fschmid 832
                return;
68 Franz 833
        if( fillMode != 0)
384 Franz 834
        {
68 Franz 835
                ArtVpath *path = art_bez_path_to_vec( m_path , 0.25 );
836
                drawVPath( path, 0 );
384 Franz 837
        }
3113 fschmid 838
#endif
68 Franz 839
}
840
 
841
void ScPainter::strokePath()
842
{
3113 fschmid 843
        if( LineWidth == 0 )
844
                return;
845
#ifdef HAVE_CAIRO
846
        drawVPath( 1 );
847
#else
68 Franz 848
        if( m_index == 0 )
849
                return;
850
        if( m_path[ m_index ].code != ART_END)
851
                m_path[ m_index ].code = ART_END;
852
        ArtVpath *path = art_bez_path_to_vec( m_path , 0.25 );
853
        drawVPath( path, 1 );
3113 fschmid 854
#endif
68 Franz 855
}
856
 
857
QColor ScPainter::pen()
858
{
859
        return m_stroke;
860
}
861
 
862
QColor ScPainter::brush()
863
{
864
        return m_fill;
865
}
866
 
867
void ScPainter::setPen( const QColor &c )
868
{
869
        m_stroke = c;
870
}
871
 
80 Franz 872
void ScPainter::setPen( const QColor &c, double w, Qt::PenStyle st, Qt::PenCapStyle ca, Qt::PenJoinStyle jo )
68 Franz 873
{
874
        m_stroke = c;
875
        LineWidth = w;
876
        PLineEnd = ca;
877
        PLineJoin = jo;
80 Franz 878
        double Dt = QMAX(2*w, 1);
879
        double Da = QMAX(6*w, 1);
880
        QValueList<double> tmp;
68 Franz 881
        m_array.clear();
882
        m_offset = 0;
883
        switch (st)
884
                {
885
                case Qt::SolidLine:
886
                        break;
887
                case Qt::DashLine:
888
                        m_array.append(Da);
889
                        m_array.append(Dt);
890
                        break;
891
                case Qt::DotLine:
892
                        m_array.append(Dt);
893
                        break;
894
                case Qt::DashDotLine:
895
                        m_array.append(Da);
896
                        m_array.append(Dt);
897
                        m_array.append(Dt);
898
                        m_array.append(Dt);
899
                        break;
900
                case Qt::DashDotDotLine:
901
                        m_array.append(Da);
902
                        m_array.append(Dt);
903
                        m_array.append(Dt);
904
                        m_array.append(Dt);
905
                        m_array.append(Dt);
906
                        m_array.append(Dt);
907
                        break;
908
                default:
909
                        break;
910
                }
911
}
912
 
80 Franz 913
void ScPainter::setLineWidth( double w )
68 Franz 914
{
915
        LineWidth = w;
916
}
917
 
80 Franz 918
void ScPainter::setPenOpacity( double op )
68 Franz 919
{
920
        stroke_trans = op;
921
}
922
 
923
 
80 Franz 924
void ScPainter::setDash(const QValueList<double>& array, double ofs)
68 Franz 925
{
926
        m_array = array;
927
        m_offset = ofs;
928
}
929
 
930
void ScPainter::setBrush( const QColor &c )
931
{
932
        m_fill = c;
933
}
934
 
80 Franz 935
void ScPainter::setBrushOpacity( double op )
68 Franz 936
{
937
        fill_trans = op;
938
}
939
 
80 Franz 940
void ScPainter::setOpacity( double op )
68 Franz 941
{
942
        fill_trans = op;
943
        stroke_trans = op;
944
}
945
 
946
void ScPainter::setFont( const QFont &f)
947
{
948
        m_font = f;
949
}
950
 
951
QFont ScPainter::font()
952
{
953
        return m_font;
954
}
955
 
956
void ScPainter::save()
957
{
3113 fschmid 958
#ifdef HAVE_CAIRO
959
        cairo_save( m_cr );
960
#else
68 Franz 961
        MStack.push(m_matrix);
3113 fschmid 962
#endif
68 Franz 963
}
964
 
965
void ScPainter::restore()
966
{
3113 fschmid 967
#ifdef HAVE_CAIRO
968
        cairo_restore( m_cr );
969
#else
68 Franz 970
        m_matrix = MStack.pop();
3113 fschmid 971
#endif
68 Franz 972
}
973
 
3240 fschmid 974
void ScPainter::setRasterOp( int   )
68 Franz 975
{
976
}
977
 
3113 fschmid 978
#ifdef HAVE_CAIRO
979
void ScPainter::drawVPath( int mode )
68 Franz 980
{
3113 fschmid 981
        cairo_save( m_cr );
982
        if (mode == 0)
983
        {
984
                if( m_fillRule )
985
                        cairo_set_fill_rule (m_cr, CAIRO_FILL_RULE_EVEN_ODD);
986
                else
987
                        cairo_set_fill_rule (m_cr, CAIRO_FILL_RULE_WINDING);
988
                if (fillMode == 2)
989
                {
990
                        cairo_pattern_t *pat;
991
                        double x1 = fill_gradient.origin().x() * m_zoomFactor;
992
                        double y1 = fill_gradient.origin().y() * m_zoomFactor;
993
                        double x2 = fill_gradient.vector().x() * m_zoomFactor;
994
                        double y2 = fill_gradient.vector().y() * m_zoomFactor;
995
                        if (fill_gradient.type() == VGradient::linear)
996
                                pat = cairo_pattern_create_linear (x1, y1,  x2, y2);
997
                        else
998
                                pat = cairo_pattern_create_radial (x1, y1, 0.1, x1, y1, sqrt(pow(x2 - x1, 2) + pow(y2 - y1,2)));
999
                        QPtrVector<VColorStop> colorStops = fill_gradient.colorStops();
1000
                        for( uint offset = 0 ; offset < colorStops.count() ; offset++ )
1001
                        {
1002
                                QColor qStopColor = colorStops[ offset ]->color;
1003
                                int h, s, v, sneu;
1004
                                int shad = colorStops[offset]->shade;
1005
                                qStopColor.rgb(&h, &s, &v);
1006
                                if ((h == s) && (s == v))
1007
                                {
1008
                                        qStopColor.hsv(&h, &s, &v);
1009
                                        sneu = 255 - ((255 - v) * shad / 100);
1010
                                        qStopColor.setHsv(h, s, sneu);
1011
                                }
1012
                                else
1013
                                {
1014
                                        qStopColor.hsv(&h, &s, &v);
1015
                                        sneu = s * shad / 100;
1016
                                        qStopColor.setHsv(h, sneu, v);
1017
                                }
1018
                                double r = qRed( qStopColor.rgb() ) / 255.0;
1019
                                double g = qGreen( qStopColor.rgb() ) / 255.0;
1020
                                double b = qBlue( qStopColor.rgb() ) / 255.0;
1021
                                double a = colorStops[offset]->opacity;
1022
                                cairo_pattern_add_color_stop_rgba (pat, colorStops[ offset ]->rampPoint, r, g, b, a);
1023
                        }
1024
                        cairo_set_source (m_cr, pat);
1025
                        cairo_clip_preserve (m_cr);
1026
                        cairo_paint_with_alpha (m_cr, fill_trans);
1027
                        cairo_pattern_destroy (pat);
1028
                }
1029
                else
1030
                {
1031
                        double r = qRed( m_fill.rgb() ) / 255.0;
1032
                        double g = qGreen( m_fill.rgb() ) / 255.0;
1033
                        double b = qBlue( m_fill.rgb() ) / 255.0;
1034
                        cairo_set_source_rgba( m_cr, r, g, b, fill_trans );
1035
                        cairo_fill_preserve( m_cr );
1036
                }
1037
        }
1038
        else
1039
        {
1040
                double *dashes;
1041
                cairo_set_line_width( m_cr, LineWidth * m_zoomFactor );
1042
                if( m_array.count() > 0 )
1043
                {
1044
                        dashes = new double[ m_array.count() ];
1045
                        for( uint i = 0; i < m_array.count();++ i )
1046
                        {
1047
                                dashes[i] = static_cast<double>(m_array[i]) * m_zoomFactor;
1048
                        }
1049
                        cairo_set_dash( m_cr, dashes, m_array.count(), static_cast<double>(m_offset) * m_zoomFactor );
1050
                }
1051
                else
1052
                        cairo_set_dash( m_cr, NULL, 0, 0 );
1053
                double r = qRed( m_stroke.rgb() ) / 255.0;
1054
                double g = qGreen( m_stroke.rgb() ) / 255.0;
1055
                double b = qBlue( m_stroke.rgb() ) / 255.0;
1056
                cairo_set_source_rgba( m_cr, r, g, b, stroke_trans );
1057
                if( PLineEnd == Qt::RoundCap )
1058
                        cairo_set_line_cap (m_cr, CAIRO_LINE_CAP_ROUND);
1059
                else if( PLineEnd == Qt::SquareCap )
1060
                        cairo_set_line_cap (m_cr, CAIRO_LINE_CAP_SQUARE);
1061
                else if( PLineEnd == Qt::FlatCap )
1062
                        cairo_set_line_cap (m_cr, CAIRO_LINE_CAP_BUTT);
1063
                if( PLineJoin == Qt::RoundJoin )
1064
                        cairo_set_line_join( m_cr, CAIRO_LINE_JOIN_ROUND );
1065
                else if( PLineJoin == Qt::BevelJoin )
1066
                        cairo_set_line_join( m_cr, CAIRO_LINE_JOIN_BEVEL );
1067
                else if( PLineJoin == Qt::MiterJoin )
1068
                        cairo_set_line_join( m_cr, CAIRO_LINE_JOIN_MITER );
1069
                cairo_stroke_preserve( m_cr );
1070
                if( m_array.count() > 0 )
1071
                        delete [] dashes;
1072
        }
1073
        cairo_restore( m_cr );
1074
#else
4646 subik 1075
void ScPainter::drawVPath( struct _ArtVpath *vec, int mode, bool preCal )
68 Franz 1076
{
1077
        ArtSVP *strokeSvp = 0L;
1078
        ArtSVP *fillSvp = 0L;
1998 fschmid 1079
        if (!preCal)
1080
        {
1081
                double affine[6];
1082
                affine[0] = m_matrix.m11();
1083
                affine[1] = m_matrix.m12();
1084
                affine[2] = m_matrix.m21();
1085
                affine[3] = m_matrix.m22();
1086
                affine[4] = m_matrix.dx();
1087
                affine[5] = m_matrix.dy();
1088
                ArtVpath *temp1 = art_vpath_affine_transform( vec, affine );
1089
                art_free( vec );
1090
                vec = temp1;
1091
        }
68 Franz 1092
        int af = 0;
1093
        int as = 0;
1094
        art_u32 fillColor = 0;
1095
        QColor color;
1096
        if (mode == 0)
1097
                {
1098
                color = m_fill;
1099
                af = qRound( 255 * fill_trans );
86 Franz 1100
#ifdef WORDS_BIGENDIAN
1101
                fillColor = ( color.red() << 24 ) | ( color.green() << 16 ) | ( color.blue() << 8 );
1102
#else
1103
                fillColor = ( 0 << 24 ) | ( color.blue() << 16 ) | ( color.green() << 8 ) | color.red();
1104
#endif
68 Franz 1105
                ArtSvpWriter *swr;
1106
                ArtSVP *temp;
1107
                temp = art_svp_from_vpath( vec );
1108
                if( m_fillRule )
1109
                        swr = art_svp_writer_rewind_new( ART_WIND_RULE_ODDEVEN );
1110
                else
1111
                        swr = art_svp_writer_rewind_new( ART_WIND_RULE_NONZERO );
1112
                art_svp_intersector( temp, swr );
1113
                fillSvp = art_svp_writer_rewind_reap( swr );
1114
                art_svp_free( temp );
1115
                }
1116
        art_u32 strokeColor = 0;
1117
        if (mode == 1)
1118
                {
1119
                ArtPathStrokeCapType capStyle = ART_PATH_STROKE_CAP_BUTT;
1120
                ArtPathStrokeJoinType joinStyle = ART_PATH_STROKE_JOIN_MITER;
1121
                color = m_stroke;
1122
                as = qRound( 255 * stroke_trans );
86 Franz 1123
#ifdef WORDS_BIGENDIAN
1124
    strokeColor = ( color.red() << 24 ) | ( color.green() << 16 ) | ( color.blue() << 8 );
1125
#else
68 Franz 1126
                strokeColor = ( 0 << 24 ) | ( color.blue() << 16 ) | ( color.green() << 8 ) | color.red();
86 Franz 1127
#endif
3113 fschmid 1128
                double ratio = m_zoomFactor;
68 Franz 1129
                if( m_array.count() > 0 )
1130
                        {
1131
                        ArtVpathDash dash;
1132
                        dash.offset = static_cast<double>(m_offset) * ratio;
1133
                        dash.n_dash = m_array.count();
1134
                        double *dashes = new double[ dash.n_dash ];
1135
                        for( int i = 0; i < dash.n_dash; i++ )
1136
                                {
1137
                                dashes[i] = static_cast<double>(m_array[i]) * ratio;
1138
                                }
1139
                        dash.dash = dashes;
1140
                        ArtVpath *vec2 = art_vpath_dash( vec, &dash );
1141
                        art_free( vec );
1142
                        vec = vec2;
1143
                        delete [] dashes;
1144
                        }
1145
                if( PLineEnd == Qt::RoundCap )
1146
                        capStyle = ART_PATH_STROKE_CAP_ROUND;
1147
                else if( PLineEnd == Qt::SquareCap )
1148
                        capStyle = ART_PATH_STROKE_CAP_SQUARE;
1149
                if( PLineJoin == Qt::RoundJoin )
1150
                        joinStyle = ART_PATH_STROKE_JOIN_ROUND;
1151
                else if( PLineJoin == Qt::BevelJoin )
1152
                        joinStyle = ART_PATH_STROKE_JOIN_BEVEL;
5096 mrdocs 1153
                //strokeSvp = art_svp_vpath_stroke( vec, joinStyle, capStyle, ratio * LineWidth, 10, 0.25 );
1154
                ArtVpath* strokeVpath = art_svp_vpath_stroke_raw( vec, joinStyle, capStyle, ratio * LineWidth, 10, 0.25 );
1155
                strokeSvp = art_svp_from_vpath( strokeVpath );
1156
                art_free(strokeVpath);
68 Franz 1157
                }
1158
        int x0, y0, x1, y1;
237 Franz 1159
        if(( fillSvp ) && (mode == 0))
68 Franz 1160
                {
1161
                if (fillMode == 2)
1162
                        applyGradient( fillSvp, true );
1163
                else
1164
                        {
1165
                        clampToViewport( *fillSvp, x0, y0, x1, y1 );
1166
                        if( x0 != x1 && y0 != y1 )
1167
                                art_rgb_svp_alpha_( fillSvp, x0, y0, x1, y1, fillColor, af, m_buffer + x0 * 4 + y0 * m_width * 4, m_width * 4, 0 );
1168
                        }
1169
                art_svp_free( fillSvp );
1170
                }
237 Franz 1171
        if(( strokeSvp ) && (mode == 1))
68 Franz 1172
        {
1173
                        clampToViewport( *strokeSvp, x0, y0, x1, y1 );
1174
                        if( x0 != x1 && y0 != y1 )
1175
                                art_rgb_svp_alpha_( strokeSvp, x0, y0, x1, y1, strokeColor, as, m_buffer + x0 * 4 + y0 * m_width * 4, m_width * 4, 0 );
1176
                art_svp_free( strokeSvp );
1177
        }
1178
        art_free( vec );
3113 fschmid 1179
#endif
68 Franz 1180
}
1181
 
267 Franz 1182
void ScPainter::setClipPath()
1183
{
3113 fschmid 1184
#ifdef HAVE_CAIRO
1185
        cairo_clip (m_cr);
1186
#else
267 Franz 1187
        ArtVpath *vec = art_bez_path_to_vec( m_path , 0.25 );
1188
        double affine[6];
1189
        affine[0] = m_matrix.m11();
632 fschmid 1190
        affine[1] = m_matrix.m12();
1191
        affine[2] = m_matrix.m21();
267 Franz 1192
        affine[3] = m_matrix.m22();
1193
        affine[4] = m_matrix.dx();
1194
        affine[5] = m_matrix.dy();
1195
        ArtVpath *temp1 = art_vpath_affine_transform( vec, affine );
1196
        art_free( vec );
1197
        ArtSvpWriter *swr;
268 Franz 1198
        ArtSVP *temp = art_svp_from_vpath( temp1 );
267 Franz 1199
        if( m_fillRule )
1200
                swr = art_svp_writer_rewind_new( ART_WIND_RULE_ODDEVEN );
1201
        else
1202
                swr = art_svp_writer_rewind_new( ART_WIND_RULE_NONZERO );
1203
        art_svp_intersector( temp, swr );
1204
        m_clipPath = art_svp_writer_rewind_reap( swr );
1205
        art_svp_free( temp );
268 Franz 1206
        art_free( temp1 );
3113 fschmid 1207
#endif
267 Franz 1208
}
1209
 
4748 fschmid 1210
#ifndef HAVE_CAIRO
1211
void ScPainter::setClipPath2(FPointArray *points, bool closed)
1212
{
1213
        setClipPath();
1214
        setupPolygon(points, closed);
1215
        ArtVpath *vec = art_bez_path_to_vec( m_path , 0.25 );
1216
        double affine[6];
1217
        affine[0] = m_matrix.m11();
1218
        affine[1] = m_matrix.m12();
1219
        affine[2] = m_matrix.m21();
1220
        affine[3] = m_matrix.m22();
1221
        affine[4] = m_matrix.dx();
1222
        affine[5] = m_matrix.dy();
1223
        ArtVpath *temp1 = art_vpath_affine_transform( vec, affine );
1224
        art_free( vec );
1225
        ArtSvpWriter *swr;
1226
        ArtSVP *temp = art_svp_from_vpath( temp1 );
1227
        if( m_fillRule )
1228
                swr = art_svp_writer_rewind_new( ART_WIND_RULE_ODDEVEN );
1229
        else
1230
                swr = art_svp_writer_rewind_new( ART_WIND_RULE_NONZERO );
1231
        art_svp_intersector( temp, swr );
1232
        temp = art_svp_writer_rewind_reap( swr );
1233
        ArtSVP *temp2 = art_svp_intersect( temp, m_clipPath );
1234
        m_clipPath = temp2;
1235
        art_svp_free( temp );
1236
        art_free( temp1 );
1237
}
1238
#endif
1239
 
270 Franz 1240
void ScPainter::drawImage( QImage *image )
68 Franz 1241
{
3113 fschmid 1242
#ifdef HAVE_CAIRO
1243
        cairo_set_fill_rule(m_cr, cairo_get_fill_rule(m_cr));
1244
        cairo_surface_t *image2;
1245
        image2  = cairo_image_surface_create_for_data ((uchar*)image->bits(), CAIRO_FORMAT_ARGB32, image->width(), image->height(), image->width()*4);
1246
        cairo_scale(m_cr, m_zoomFactor, m_zoomFactor);
1247
        cairo_set_source_surface (m_cr, image2, 0, 0);
1248
        cairo_paint_with_alpha(m_cr, fill_trans);
1249
        cairo_surface_destroy (image2);
1250
#else
68 Franz 1251
        double affineresult[6];
1252
        affineresult[0] = m_matrix.m11() * m_zoomFactor;
1253
        affineresult[1] = m_matrix.m12() * m_zoomFactor;
1254
        affineresult[2] = m_matrix.m21() * m_zoomFactor;
1255
        affineresult[3] = m_matrix.m22() * m_zoomFactor;
632 fschmid 1256
        affineresult[4] = m_matrix.dx();
1257
        affineresult[5] = m_matrix.dy();
267 Franz 1258
        ksvg_art_rgb_affine_clip( m_clipPath, m_buffer, 0, 0, m_width, m_height, m_width * 4, 4,
270 Franz 1259
                                         image->bits(), image->width(), image->height(), image->width() * 4,
267 Franz 1260
                                         affineresult, qRound( 255 * fill_trans ), 0L );
1261
        art_svp_free( m_clipPath );
3113 fschmid 1262
#endif
68 Franz 1263
}
1264
 
264 Franz 1265
void ScPainter::setupPolygon(FPointArray *points, bool closed)
68 Franz 1266
{
1267
        bool nPath = true;
1268
        FPoint np, np1, np2, np3;
3113 fschmid 1269
#ifdef HAVE_CAIRO
68 Franz 1270
        if (points->size() > 3)
3113 fschmid 1271
        {
1272
                newPath();
1273
                for (uint poi=0; poi<points->size()-3; poi += 4)
68 Franz 1274
                {
3113 fschmid 1275
                        if (points->point(poi).x() > 900000)
1276
                        {
1277
                                nPath = true;
1278
//                      cairo_close_path( m_cr );
1279
                                continue;
1280
                        }
1281
                        if (nPath)
1282
                        {
1283
                                np = points->point(poi);
1284
                        cairo_move_to( m_cr, np.x() * m_zoomFactor, np.y() * m_zoomFactor);
1285
                                nPath = false;
1286
                        }
1287
                        np = points->point(poi);
1288
                        np1 = points->point(poi+1);
1289
                        np2 = points->point(poi+3);
1290
                        np3 = points->point(poi+2);
1291
                        if ((np == np1) && (np2 == np3))
1292
                                cairo_line_to( m_cr, np3.x() * m_zoomFactor, np3.y() * m_zoomFactor);
1293
                        else
4646 subik 1294
                                cairo_curve_to(m_cr,
1295
                                                                                        np1.x() * m_zoomFactor,
1296
                                                                                        np1.y() * m_zoomFactor,
1297
                                                                                        np2.x() * m_zoomFactor,
1298
                                                                                        np2.y() * m_zoomFactor,
1299
                                                                                        np3.x() * m_zoomFactor,
3113 fschmid 1300
                                                                                        np3.y() * m_zoomFactor);
1301
                }
1302
                if (closed)
1303
                cairo_close_path( m_cr );
1304
        }
1305
#else
1306
        if (points->size() > 3)
1307
                {
68 Franz 1308
                newPath();
1309
                for (uint poi=0; poi<points->size()-3; poi += 4)
1310
                        {
1311
                        if (points->point(poi).x() > 900000)
1312
                                {
1313
                                nPath = true;
173 Franz 1314
                                ensureSpace( m_index + 1 );
1315
                                m_path[ m_index ].code = ART_END;
68 Franz 1316
                                continue;
1317
                                }
1318
                        if (nPath)
1319
                                {
1320
                                np = points->point(poi);
1321
                                ensureSpace( m_index + 1 );
264 Franz 1322
                                if (closed)
1323
                                        m_path[ m_index ].code = ART_MOVETO;
1324
                                else
1325
                                        m_path[ m_index ].code = ART_MOVETO_OPEN;
86 Franz 1326
                                m_path[ m_index ].x3 = np.x() * m_zoomFactor;
1327
                                m_path[ m_index ].y3 = np.y() * m_zoomFactor;
68 Franz 1328
                                m_index++;
1329
                                nPath = false;
1330
                                }
1331
                        np = points->point(poi);
1332
                        np1 = points->point(poi+1);
1333
                        np2 = points->point(poi+3);
1334
                        np3 = points->point(poi+2);
1335
                        ensureSpace( m_index + 1 );
1336
                        if ((np == np1) && (np2 == np3))
1337
                                {
1338
                                m_path[ m_index ].code = ART_LINETO;
86 Franz 1339
                                m_path[ m_index ].x3    = np3.x() * m_zoomFactor;
1340
                                m_path[ m_index ].y3    = np3.y() * m_zoomFactor;
68 Franz 1341
                                }
1342
                        else
1343
                                {
1344
                                m_path[ m_index ].code = ART_CURVETO;
86 Franz 1345
                                m_path[ m_index ].x1    = np1.x() * m_zoomFactor;
1346
                                m_path[ m_index ].y1    = np1.y() * m_zoomFactor;
1347
                                m_path[ m_index ].x2    = np2.x() * m_zoomFactor;
1348
                                m_path[ m_index ].y2    = np2.y() * m_zoomFactor;
1349
                                m_path[ m_index ].x3    = np3.x() * m_zoomFactor;
1350
                                m_path[ m_index ].y3    = np3.y() * m_zoomFactor;
68 Franz 1351
                                }
1352
                        m_index++;
1353
                        }
173 Franz 1354
                ensureSpace( m_index + 1 );
1355
                m_path[ m_index ].code = ART_END;
1356
                m_index++;
68 Franz 1357
                }
3113 fschmid 1358
#endif
68 Franz 1359
}
1360
 
638 fschmid 1361
void ScPainter::setupTextPolygon(FPointArray *points)
1362
{
1363
        bool nPath = true;
1364
        FPoint np, np1, np2, np3;
3113 fschmid 1365
#ifdef HAVE_CAIRO
1366
        if (points->size() > 3)
1367
        {
1368
                newPath();
1369
                for (uint poi=0; poi<points->size()-3; poi += 4)
1370
                {
1371
                        if (points->point(poi).x() > 900000)
1372
                        {
1373
                                nPath = true;
1374
                                continue;
1375
                        }
1376
                        if (nPath)
1377
                        {
1378
                                np = points->point(poi);
1379
                        cairo_move_to( m_cr, np.x(), np.y());
1380
                                nPath = false;
1381
                        }
1382
                        np = points->point(poi);
1383
                        np1 = points->point(poi+1);
1384
                        np2 = points->point(poi+3);
1385
                        np3 = points->point(poi+2);
1386
                        if ((np == np1) && (np2 == np3))
1387
                                cairo_line_to( m_cr, np3.x(), np3.y());
1388
                        else
1389
                                cairo_curve_to(m_cr, np1.x(), np1.y(), np2.x(), np2.y(), np3.x(), np3.y());
1390
                }
1391
        cairo_close_path( m_cr );
1392
        }
1393
#else
638 fschmid 1394
        newPath();
1395
        for (uint poi=0; poi<points->size()-3; poi += 4)
1396
        {
1397
                if (points->point(poi).x() > 900000)
1398
                {
1399
                        nPath = true;
1400
                        ensureSpace( m_index + 1 );
1401
                        m_path[ m_index ].code = ART_END;
1402
                        continue;
1403
                }
1404
                if (nPath)
1405
                {
1406
                        np = points->point(poi);
1407
                        ensureSpace( m_index + 1 );
1408
                        m_path[ m_index ].code = ART_MOVETO;
1409
                        m_path[ m_index ].x3 = np.x();
1410
                        m_path[ m_index ].y3 = np.y();
1411
                        m_index++;
1412
                        nPath = false;
1413
                }
1414
                np = points->point(poi);
1415
                np1 = points->point(poi+1);
1416
                np2 = points->point(poi+3);
1417
                np3 = points->point(poi+2);
1418
                ensureSpace( m_index + 1 );
1419
                if ((np == np1) && (np2 == np3))
1420
                {
1421
                        m_path[ m_index ].code = ART_LINETO;
1422
                        m_path[ m_index ].x3    = np3.x();
1423
                        m_path[ m_index ].y3    = np3.y();
1424
                }
1425
                else
1426
                {
1427
                        m_path[ m_index ].code = ART_CURVETO;
1428
                        m_path[ m_index ].x1    = np1.x();
1429
                        m_path[ m_index ].y1    = np1.y();
1430
                        m_path[ m_index ].x2    = np2.x();
1431
                        m_path[ m_index ].y2    = np2.y();
1432
                        m_path[ m_index ].x3    = np3.x();
1433
                        m_path[ m_index ].y3    = np3.y();
1434
                }
1435
                m_index++;
1436
        }
1437
        ensureSpace( m_index + 1 );
1438
        m_path[ m_index ].code = ART_END;
1439
        m_index++;
3113 fschmid 1440
#endif
638 fschmid 1441
}
1442
 
68 Franz 1443
void ScPainter::drawPolygon()
1444
{
1445
        fillPath();
1446
}
1447
 
1448
void ScPainter::drawPolyLine()
1449
{
1450
        strokePath();
1451
}
1452
 
1453
void ScPainter::drawLine(FPoint start, FPoint end)
1454
{
1455
        newPath();
1456
        moveTo(start.x(), start.y());
1457
        lineTo(end.x(), end.y());
1458
        strokePath();
1459
}
1460
 
1461
void ScPainter::drawRect(double x, double y, double w, double h)
1462
{
1463
        newPath();
1464
        moveTo( x, y );
1465
        lineTo( x+w, y );
1466
        lineTo( x+w, y+h );
1467
        lineTo( x, y+h );
1468
        lineTo( x, y );
3113 fschmid 1469
#ifdef HAVE_CAIRO
1470
        cairo_close_path( m_cr );
1471
#else
173 Franz 1472
        ensureSpace( m_index + 1 );
1473
        m_path[ m_index ].code = ART_END;
1474
        m_index++;
3113 fschmid 1475
#endif
68 Franz 1476
        fillPath();
1477
        strokePath();
1478
}
3113 fschmid 1479
 
1480
#ifndef HAVE_CAIRO
1481
void ScPainter::ensureSpace( unsigned int newindex )
1482
{
1483
        if( m_index == 0 )
1484
                {
1485
                if( !m_path )
1486
                        m_path = art_new( ArtBpath, INITIAL_ALLOC );
1487
                m_alloccount = INITIAL_ALLOC;
1488
                }
1489
        else if( newindex > m_alloccount )
1490
                {
1491
                m_alloccount += ALLOC_INCREMENT;
1492
                m_path = art_renew( m_path, ArtBpath, m_alloccount );
1493
                }
1494
}
1495
 
1496
void ScPainter::resize( unsigned int w, unsigned int h )
1497
{
1498
        if( !m_buffer || w != m_width || h != m_height )
1499
        {
1500
                // TODO : realloc?
1501
                art_free( m_buffer );
1502
                m_buffer = 0;
1503
                m_width = w;
1504
                m_height = h;
1505
                if ( m_width != 0 && m_height != 0 )
1506
                        m_buffer = art_new( art_u8, m_width * m_height * 4 );
1507
                clear();
1508
        }
1509
}
1510
 
1511
void ScPainter::clampToViewport( int &x0, int &y0, int &x1, int &y1 )
1512
{
1513
        x0 = QMAX( x0, 0 );
1514
        x0 = QMIN( x0, static_cast<int>( m_width ) );
1515
        y0 = QMAX( y0, 0 );
1516
        y0 = QMIN( y0, static_cast<int>( m_height ) );
1517
        x1 = QMAX( x1, 0 );
1518
        x1 = QMIN( x1, static_cast<int>( m_width ) );
1519
        y1 = QMAX( y1, 0 );
1520
        y1 = QMIN( y1, static_cast<int>( m_height ) );
1521
}
1522
 
4646 subik 1523
void ScPainter::clampToViewport( const _ArtSVP &svp, int &x0, int &y0, int &x1, int &y1 )
3113 fschmid 1524
{
1525
        ArtDRect bbox;
1526
        art_drect_svp( &bbox, &svp );
1527
        x0 = static_cast<int>( bbox.x0 );
1528
        x0 = QMAX( x0, 0 );
1529
        x0 = QMIN( x0, static_cast<int>( m_width ) );
1530
        y0 = static_cast<int>( bbox.y0 );
1531
        y0 = QMAX( y0, 0 );
1532
        y0 = QMIN( y0, static_cast<int>( m_height ) );
1533
        x1 = static_cast<int>( bbox.x1 ) + 1;
1534
        x1 = QMAX( x1, 0 );
1535
        x1 = QMIN( x1, static_cast<int>( m_width ) );
1536
        y1 = static_cast<int>( bbox.y1 ) + 1;
1537
        y1 = QMAX( y1, 0 );
1538
        y1 = QMIN( y1, static_cast<int>( m_height ) );
1539
}
1540
 
4646 subik 1541
void ScPainter::applyGradient( _ArtSVP *svp, bool fill )
3113 fschmid 1542
{
1543
        int x0, y0, x1, y1;
1544
        clampToViewport( *svp, x0, y0, x1, y1 );
1545
        ArtRender *render = 0L;
1546
        VGradient gradient;
1547
        if (fill)
1548
                gradient = fill_gradient;
1549
        else
1550
                gradient = stroke_gradient;
1551
        double opa = fill ? fill_trans : stroke_trans;
1552
        if (gradient.type() == VGradient::linear)
1553
        {
1554
                ArtGradientLinear *linear = art_new( ArtGradientLinear, 1 );
1555
                linear->spread = ART_GRADIENT_PAD;
1556
                double _x1 = static_cast<double>(gradient.origin().x());
1557
                double _x2 = static_cast<double>(gradient.vector().x());
1558
                double _y2 = static_cast<double>(gradient.origin().y());
1559
                double _y1 = static_cast<double>(gradient.vector().y());
1560
                double dx = ( _x2 - _x1 ) * m_zoomFactor;
1561
                _y1 =  _y1 + m_matrix.dy() / m_zoomFactor;
1562
                _y2 =  _y2 + m_matrix.dy() / m_zoomFactor;
1563
                if (dx == 0.0)
1564
                        dx = 1;
1565
                double dy = ( _y1 - _y2 ) * m_zoomFactor;
1566
                if (dy == 0.0)
1567
                        dy = 1;
1568
                double scale = 1.0 / ( dx * dx + dy * dy );
1569
                linear->a = dx * scale;
1570
                linear->b = dy * scale;
1571
                linear->c = -( ( _x1 * m_zoomFactor + m_matrix.dx() ) * linear->a + ( _y2 * m_zoomFactor ) * linear->b );
1572
                int offsets = -1;
1573
                linear->stops = buildStopArray( gradient, offsets );
1574
                linear->n_stops = offsets;
1575
                if( x0 != x1 && y0 != y1 )
1576
                {
1577
                        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 );
1578
                        int opacity = static_cast<int>( opa * 255.0 );
1579
                        art_render_svp( render, svp );
1580
                        art_render_mask_solid (render, (opacity << 8) + opacity + (opacity >> 7));
1581
                        art_karbon_render_gradient_linear( render, linear, ART_FILTER_NEAREST );
1582
                        art_render_invoke( render );
1583
                }
1584
                art_free( linear->stops );
1585
                art_free( linear );
1586
        }
1587
        else if( gradient.type() == VGradient::radial )
1588
        {
1589
                ArtGradientRadial *radial = art_new( ArtGradientRadial, 1 );
1590
                radial->spread = ART_GRADIENT_PAD;
1591
                radial->affine[0] = m_matrix.m11();
1592
                radial->affine[1] = m_matrix.m12();
1593
                radial->affine[2] = m_matrix.m21();
1594
                radial->affine[3] = m_matrix.m22();
1595
                radial->affine[4] = m_matrix.dx();
1596
                radial->affine[5] = m_matrix.dy();
1597
                double cx = gradient.origin().x() * m_zoomFactor;
1598
                double cy = gradient.origin().y() * m_zoomFactor;
1599
                double fx = gradient.focalPoint().x() * m_zoomFactor;
1600
                double fy = gradient.focalPoint().y() * m_zoomFactor;
1601
                double r = sqrt( pow( gradient.vector().x() - gradient.origin().x(), 2 ) + pow( gradient.vector().y() - gradient.origin().y(), 2 ) );
1602
                r *= m_zoomFactor;
1603
                radial->fx = (fx - cx) / r;
1604
                radial->fy = (fy - cy) / r;
1605
                double aff1[6], aff2[6];
1606
                art_affine_scale( aff1, r, r);
1607
                art_affine_translate( aff2, cx, cy );
1608
                art_affine_multiply( aff1, aff1, aff2 );
1609
                art_affine_multiply( aff1, aff1, radial->affine );
1610
                art_affine_invert( radial->affine, aff1 );
1611
                int offsets = -1;
1612
                radial->stops = buildStopArray( gradient, offsets );
1613
                radial->n_stops = offsets;
1614
                if( x0 != x1 && y0 != y1 )
1615
                {
1616
                        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 );
1617
                        int opacity = static_cast<int>( opa * 255.0 );
1618
                        art_render_svp( render, svp );
1619
                        art_render_mask_solid (render, (opacity << 8) + opacity + (opacity >> 7));
1620
                        art_karbon_render_gradient_radial( render, radial, ART_FILTER_NEAREST );
1621
                        art_render_invoke( render );
1622
                }
1623
                art_free( radial->stops );
1624
                art_free( radial );
1625
        }
1626
}
1627
 
1628
ArtGradientStop * ScPainter::buildStopArray( VGradient &gradient, int &offsets )
1629
{
1630
        QPtrVector<VColorStop> colorStops = gradient.colorStops();
1631
        offsets = colorStops.count();
1632
        ArtGradientStop *stopArray = art_new( ArtGradientStop, offsets * 2 - 1 );
1633
        for( int offset = 0 ; offset < offsets ; offset++ )
1634
        {
1635
                double ramp = colorStops[ offset ]->rampPoint;
1636
                stopArray[ offset * 2 ].offset = ramp;
1637
                QColor qStopColor = colorStops[ offset ]->color;
1638
                int h, s, v, sneu;
1639
                int shad = colorStops[offset]->shade;
1640
                qStopColor.rgb(&h, &s, &v);
1641
                if ((h == s) && (s == v))
1642
                {
1643
                        qStopColor.hsv(&h, &s, &v);
1644
                        sneu = 255 - ((255 - v) * shad / 100);
1645
                        qStopColor.setHsv(h, s, sneu);
1646
                }
1647
                else
1648
                {
1649
                        qStopColor.hsv(&h, &s, &v);
1650
                        sneu = s * shad / 100;
1651
                        qStopColor.setHsv(h, sneu, v);
1652
                }
1653
                int r = qRed( qStopColor.rgb() );
1654
                int g = qGreen( qStopColor.rgb() );
1655
                int b = qBlue( qStopColor.rgb() );
1656
                art_u32 rgba = (r << 24) | (g << 16) | (b << 8) | qAlpha(qStopColor.rgb());
1657
                int a = static_cast<int>( colorStops[offset]->opacity * 255.0 );
1658
                r = (rgba >> 24) * a + 0x80;
1659
                r = (r + (r >> 8)) >> 8;
1660
                g = ((rgba >> 16) & 0xff) * a + 0x80;
1661
                g = (g + (g >> 8)) >> 8;
1662
                b = ((rgba >> 8) & 0xff) * a + 0x80;
1663
                b = (b + (b >> 8)) >> 8;
1664
                stopArray[ offset * 2 ].color[ 0 ] = ART_PIX_MAX_FROM_8(r);
1665
                stopArray[ offset * 2 ].color[ 1 ] = ART_PIX_MAX_FROM_8(g);
1666
                stopArray[ offset * 2 ].color[ 2 ] = ART_PIX_MAX_FROM_8(b);
1667
                stopArray[ offset * 2 ].color[ 3 ] = ART_PIX_MAX_FROM_8(a);
1668
                if( offset + 1 != offsets )
1669
                {
1670
                        stopArray[ offset * 2 + 1 ].offset = ramp + ( colorStops[ offset + 1 ]->rampPoint - ramp ) * colorStops[ offset ]->midPoint;
1671
                        QColor qStopColor2 = colorStops[ offset + 1 ]->color;
1672
                        rgba = static_cast<int>(r + ((qRed(qStopColor2.rgb()) - r)) * 0.5) << 24 |
1673
                                                 static_cast<int>(g + ((qGreen(qStopColor2.rgb()) - g)) * 0.5) << 16 |
1674
                                                 static_cast<int>(b + ((qBlue(qStopColor2.rgb()) - b)) * 0.5) << 8 |
1675
                                                qAlpha(qStopColor2.rgb());
1676
                        int a = static_cast<int>( colorStops[offset]->opacity * 255.0 );
1677
                        r = (rgba >> 24) * a + 0x80;
1678
                        r = (r + (r >> 8)) >> 8;
1679
                        g = ((rgba >> 16) & 0xff) * a + 0x80;
1680
                        g = (g + (g >> 8)) >> 8;
1681
                        b = ((rgba >> 8) & 0xff) * a + 0x80;
1682
                        b = (b + (b >> 8)) >> 8;
1683
                        stopArray[ offset * 2 + 1 ].color[ 0 ] = ART_PIX_MAX_FROM_8(r);
1684
                        stopArray[ offset * 2 + 1 ].color[ 1 ] = ART_PIX_MAX_FROM_8(g);
1685
                        stopArray[ offset * 2 + 1 ].color[ 2 ] = ART_PIX_MAX_FROM_8(b);
1686
                        stopArray[ offset * 2 + 1 ].color[ 3 ] = ART_PIX_MAX_FROM_8(a);
1687
                }
1688
        }
1689
        offsets = offsets * 2 - 1;
1690
        return stopArray;
1691
}
1692
#endif