Subversion Repositories Scribus

Rev

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