Subversion Repositories Scribus

Rev

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

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