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.
9
#include "util_color.h"
15
#include <cairo-win32.h>
16
#elif defined(Q_WS_X11)
17
#include <cairo-xlib.h>
18
#elif defined(Q_WS_MAC)
19
// #include <cairo-quartz.h>
21
#include <cairo-svg.h>
28
ScPainter::ScPainter( QImage *target, unsigned int w, unsigned int h, double transparency, int blendmode )
32
m_stroke = QColor(0,0,0);
33
m_fill = QColor(0,0,0);
40
m_layerTransparency = transparency;
41
m_blendMode = blendmode;
47
PLineEnd = Qt::FlatCap;
48
PLineJoin = Qt::MiterJoin;
49
fill_gradient = VGradient(VGradient::linear);
50
stroke_gradient = VGradient(VGradient::linear);
57
cairo_surface_t *img = cairo_image_surface_create_for_data(m_image->bits(), CAIRO_FORMAT_ARGB32, w, h, w*4);
58
m_cr = cairo_create(img);
60
cairo_set_fill_rule (m_cr, CAIRO_FILL_RULE_EVEN_ODD);
61
cairo_set_operator(m_cr, CAIRO_OPERATOR_OVER);
62
cairo_set_tolerance( m_cr, 0.5 );
66
ScPainter::ScPainter( QString target, unsigned int w, unsigned int h, double transparency, int blendmode )
70
m_stroke = QColor(0,0,0);
71
m_fill = QColor(0,0,0);
78
m_layerTransparency = transparency;
79
m_blendMode = blendmode;
85
PLineEnd = Qt::FlatCap;
86
PLineJoin = Qt::MiterJoin;
87
fill_gradient = VGradient(VGradient::linear);
88
stroke_gradient = VGradient(VGradient::linear);
94
cairo_surface_t *img = cairo_svg_surface_create(target.toLocal8Bit().constData(), w, h);
95
m_cr = cairo_create(img);
97
cairo_set_fill_rule (m_cr, CAIRO_FILL_RULE_EVEN_ODD);
98
cairo_set_operator(m_cr, CAIRO_OPERATOR_OVER);
99
cairo_set_tolerance( m_cr, 0.5 );
104
ScPainter::ScPainter( QImage *target, unsigned int w, unsigned int h, double transparency, int blendmode )
106
m_path = QPainterPath();
109
m_stroke = QColor(0,0,0);
110
m_fill = QColor(0,0,0);
117
m_layerTransparency = transparency;
118
m_blendMode = blendmode;
120
mf_underline = false;
121
mf_strikeout = false;
124
PLineEnd = Qt::FlatCap;
125
PLineJoin = Qt::MiterJoin;
126
PLineStyle = Qt::SolidLine;
127
fill_gradient = VGradient(VGradient::linear);
128
stroke_gradient = VGradient(VGradient::linear);
134
m_matrix = QMatrix();
135
painter.begin(m_image);
136
painter.setRenderHint(QPainter::Antialiasing, true);
137
painter.setRenderHint(QPainter::SmoothPixmapTransform, true);
141
ScPainter::~ScPainter()
144
cairo_surface_destroy(cairo_get_target(m_cr));
145
cairo_destroy( m_cr );
151
void ScPainter::beginLayer(double transparency, int blendmode, FPointArray *clipArray)
154
la.blendmode = m_blendMode;
155
la.tranparency = m_layerTransparency;
156
m_layerTransparency = transparency;
157
m_blendMode = blendmode;
159
la.groupClip.resize(0);
160
if (clipArray != NULL)
161
la.groupClip = *clipArray;
163
la.data = cairo_get_group_target(m_cr);
164
cairo_push_group(m_cr);
165
/* if (clipArray != NULL)
167
setupPolygon(clipArray);
171
la.data = new QImage(m_image->copy());
172
m_image->fill(qRgba(255, 255, 255, 0));
178
void ScPainter::endLayer()
181
if (Layers.count() == 0)
187
if ((m_blendMode != 0) && (Layers.count() != 0))
189
cairo_surface_t *tmp = cairo_get_group_target(m_cr);
190
cairo_surface_t *tmpB = Layers.top().data;
191
if ((tmp != NULL) && (tmpB != NULL))
193
if ((cairo_surface_get_type(tmp) == CAIRO_SURFACE_TYPE_IMAGE) && (cairo_surface_get_type(tmpB) == CAIRO_SURFACE_TYPE_IMAGE))
195
cairo_surface_flush(tmp);
196
int stride = cairo_image_surface_get_stride(tmp);
197
unsigned char *s = cairo_image_surface_get_data(tmp);
198
unsigned char *d = cairo_image_surface_get_data(tmpB);
199
int h = cairo_image_surface_get_height(tmp);
200
int w = cairo_image_surface_get_width(tmp);
207
uchar src_a, src_r, src_g, src_b, dst_a, dst_r, dst_g, dst_b, new_r, new_g, new_b;
208
for( int yi=0; yi < h; ++yi )
212
for( int xi=0; xi < w; ++xi )
215
src_g = qGreen(*src);
217
src_a = qAlpha(*src);
219
dst_g = qGreen(*dst);
221
dst_a = qAlpha(*dst);
222
if ((src_a > 0) && (dst_a > 0))
224
if (((*dst) != oldDst) || ((*src) != oldSrc) || (first))
226
if (m_blendMode == 1)
228
src_r = dst_r < src_r ? dst_r : src_r;
229
src_g = dst_g < src_g ? dst_g : src_g;
230
src_b = dst_b < src_b ? dst_b : src_b;
232
else if (m_blendMode == 2)
234
src_r = dst_r < src_r ? src_r : dst_r;
235
src_g = dst_g < src_g ? src_g : dst_g;
236
src_b = dst_b < src_b ? src_b : dst_b;
238
else if (m_blendMode == 3)
240
src_r = INT_MULT(src_r, dst_r);
241
src_g = INT_MULT(src_g, dst_g);
242
src_b = INT_MULT(src_b, dst_b);
244
else if (m_blendMode == 4)
246
src_r = 255 - ((255-src_r) * (255-dst_r) / 255);
247
src_g = 255 - ((255-src_g) * (255-dst_g) / 255);
248
src_b = 255 - ((255-src_b) * (255-dst_b) / 255);
250
else if (m_blendMode == 5)
252
src_r = dst_r < 128 ? src_r * dst_r / 128 : 255 - ((255-src_r) * (255-dst_r) / 128);
253
src_g = dst_g < 128 ? src_g * dst_g / 128 : 255 - ((255-src_g) * (255-dst_g) / 128);
254
src_b = dst_b < 128 ? src_b * dst_b / 128 : 255 - ((255-src_b) * (255-dst_b) / 128);
256
else if (m_blendMode == 6)
258
src_r = src_r < 128 ? src_r * dst_r / 128 : 255 - ((255-src_r) * (255-dst_r) / 128);
259
src_g = src_g < 128 ? src_g * dst_g / 128 : 255 - ((255-src_g) * (255-dst_g) / 128);
260
src_b = src_b < 128 ? src_b * dst_b / 128 : 255 - ((255-src_b) * (255-dst_b) / 128);
262
else if (m_blendMode == 7)
264
float s_r = (255 - src_r) / 255.0;
265
float s_g = (255 - src_g) / 255.0;
266
float s_b = (255 - src_b) / 255.0;
267
float d_r = (255 - dst_r) / 255.0;
268
float d_g = (255 - dst_g) / 255.0;
269
float d_b = (255 - dst_b) / 255.0;
270
float dzr = d_r > 0.25 ? sqrt(d_r) : ((16 * d_r - 12) * d_r + 4) * d_r;
271
float dzg = d_g > 0.25 ? sqrt(d_g) : ((16 * d_g - 12) * d_g + 4) * d_g;
272
float dzb = d_b > 0.25 ? sqrt(d_b) : ((16 * d_b - 12) * d_b + 4) * d_b;
273
s_r = s_r <= 0.5 ? d_r - (1 - 2 * s_r) * d_r * (1 - d_r) : d_r + (2 * s_r - 1) * (dzr - d_r);
274
s_g = s_g <= 0.5 ? d_g - (1 - 2 * s_g) * d_g * (1 - d_g) : d_g + (2 * s_g - 1) * (dzg - d_g);
275
s_b = s_b <= 0.5 ? d_b - (1 - 2 * s_b) * d_b * (1 - d_b) : d_b + (2 * s_b - 1) * (dzb - d_b);
276
src_r = 255 - qRound(s_r * 255);
277
src_g = 255 - qRound(s_g * 255);
278
src_b = 255 - qRound(s_b * 255);
280
else if (m_blendMode == 8)
282
src_r = dst_r > src_r ? dst_r - src_r : src_r - dst_r;
283
src_g = dst_g > src_g ? dst_g - src_g : src_g - dst_g;
284
src_b = dst_b > src_b ? dst_b - src_b : src_b - dst_b;
286
else if (m_blendMode == 9)
288
src_r = dst_r + src_r - src_r * dst_r / 128;
289
src_g = dst_g + src_g - src_g * dst_g / 128;
290
src_b = dst_b + src_b - src_b * dst_b / 128;
292
else if (m_blendMode == 10)
294
src_r = src_r == 255 ? qMin(255, dst_r * 256) : qMin(255, ((dst_r * 256) / (255-src_r)));
295
src_g = src_g == 255 ? qMin(255, dst_g * 256) : qMin(255, ((dst_g * 256) / (255-src_g)));
296
src_b = src_b == 255 ? qMin(255, dst_b * 256) : qMin(255, ((dst_b * 256) / (255-src_b)));
298
else if (m_blendMode == 11)
300
src_r = qMax<uchar>(1, src_r);
301
src_g = qMax<uchar>(1, src_g);
302
src_b = qMax<uchar>(1, src_b);
303
src_r = static_cast<int>(255 - (((255-dst_r) * 256) / src_r)) < 0 ? 0 : 255 - (((255-dst_r) * 256) / src_r);
304
src_g = static_cast<int>(255 - (((255-dst_g) * 256) / src_g)) < 0 ? 0 : 255 - (((255-dst_g) * 256) / src_g);
305
src_b = static_cast<int>(255 - (((255-dst_b) * 256) / src_b)) < 0 ? 0 : 255 - (((255-dst_b) * 256) / src_b);
307
else if (m_blendMode == 12)
312
RGBTOHLS(src_r, src_g, src_b);
313
RGBTOHLS(new_r, new_g, new_b);
315
HLSTORGB(new_r, new_g, new_b);
320
else if (m_blendMode == 13)
325
RGBTOHLS(src_r, src_g, src_b);
326
RGBTOHLS(new_r, new_g, new_b);
328
HLSTORGB(new_r, new_g, new_b);
333
else if (m_blendMode == 14)
338
setLum(new_r, new_g, new_b, Lum(dst_r, dst_g, dst_b));
343
else if (m_blendMode == 15)
348
setLum(new_r, new_g, new_b, Lum(src_r, src_g, src_b));
353
newResult = qRgba(src_r, src_g, src_b, src_a);
366
cairo_surface_mark_dirty(tmp);
371
if ((m_blendMode > 0) && (m_blendMode < 12) && (Layers.count() != 0))
373
int h = m_image->height();
374
int w = m_image->width();
381
uchar src_a, src_r, src_g, src_b, dst_a, dst_r, dst_g, dst_b, new_r, new_g, new_b;
382
for( int yi = 0; yi < h; ++yi )
384
dst = (QRgb*)la.data->scanLine(yi);
385
src = (QRgb*)m_image->scanLine(yi);
386
for( int xi=0; xi < w; ++xi )
389
src_g = qGreen(*src);
391
src_a = qAlpha(*src);
393
dst_g = qGreen(*dst);
395
dst_a = qAlpha(*dst);
396
if ((src_a > 0) && (dst_a > 0))
398
if (((*dst) != oldDst) || ((*src) != oldSrc) || (first))
400
/* if (m_blendMode == 1)
402
src_r = dst_r < src_r ? dst_r : src_r;
403
src_g = dst_g < src_g ? dst_g : src_g;
404
src_b = dst_b < src_b ? dst_b : src_b;
406
else if (m_blendMode == 2)
408
src_r = dst_r < src_r ? src_r : dst_r;
409
src_g = dst_g < src_g ? src_g : dst_g;
410
src_b = dst_b < src_b ? src_b : dst_b;
412
else if (m_blendMode == 3)
414
src_r = INT_MULT(src_r, dst_r);
415
src_g = INT_MULT(src_g, dst_g);
416
src_b = INT_MULT(src_b, dst_b);
418
else if (m_blendMode == 4)
420
src_r = 255 - ((255-src_r) * (255-dst_r) / 255);
421
src_g = 255 - ((255-src_g) * (255-dst_g) / 255);
422
src_b = 255 - ((255-src_b) * (255-dst_b) / 255);
424
else if (m_blendMode == 5)
426
src_r = dst_r < 128 ? src_r * dst_r / 128 : 255 - ((255-src_r) * (255-dst_r) / 128);
427
src_g = dst_g < 128 ? src_g * dst_g / 128 : 255 - ((255-src_g) * (255-dst_g) / 128);
428
src_b = dst_b < 128 ? src_b * dst_b / 128 : 255 - ((255-src_b) * (255-dst_b) / 128);
430
else if (m_blendMode == 6)
432
src_r = src_r < 128 ? src_r * dst_r / 128 : 255 - ((255-src_r) * (255-dst_r) / 128);
433
src_g = src_g < 128 ? src_g * dst_g / 128 : 255 - ((255-src_g) * (255-dst_g) / 128);
434
src_b = src_b < 128 ? src_b * dst_b / 128 : 255 - ((255-src_b) * (255-dst_b) / 128);
436
else if (m_blendMode == 7)
438
float s_r = (255 - src_r) / 255.0;
439
float s_g = (255 - src_g) / 255.0;
440
float s_b = (255 - src_b) / 255.0;
441
float d_r = (255 - dst_r) / 255.0;
442
float d_g = (255 - dst_g) / 255.0;
443
float d_b = (255 - dst_b) / 255.0;
444
float dzr = d_r > 0.25 ? sqrt(d_r) : ((16 * d_r - 12) * d_r + 4) * d_r;
445
float dzg = d_g > 0.25 ? sqrt(d_g) : ((16 * d_g - 12) * d_g + 4) * d_g;
446
float dzb = d_b > 0.25 ? sqrt(d_b) : ((16 * d_b - 12) * d_b + 4) * d_b;
447
s_r = s_r <= 0.5 ? d_r - (1 - 2 * s_r) * d_r * (1 - d_r) : d_r + (2 * s_r - 1) * (dzr - d_r);
448
s_g = s_g <= 0.5 ? d_g - (1 - 2 * s_g) * d_g * (1 - d_g) : d_g + (2 * s_g - 1) * (dzg - d_g);
449
s_b = s_b <= 0.5 ? d_b - (1 - 2 * s_b) * d_b * (1 - d_b) : d_b + (2 * s_b - 1) * (dzb - d_b);
450
src_r = 255 - qRound(s_r * 255);
451
src_g = 255 - qRound(s_g * 255);
452
src_b = 255 - qRound(s_b * 255);
454
else if (m_blendMode == 8)
456
src_r = dst_r > src_r ? dst_r - src_r : src_r - dst_r;
457
src_g = dst_g > src_g ? dst_g - src_g : src_g - dst_g;
458
src_b = dst_b > src_b ? dst_b - src_b : src_b - dst_b;
460
else if (m_blendMode == 9)
462
src_r = dst_r + src_r - src_r * dst_r / 128;
463
src_g = dst_g + src_g - src_g * dst_g / 128;
464
src_b = dst_b + src_b - src_b * dst_b / 128;
466
else if (m_blendMode == 10)
468
src_r = src_r == 255 ? qMin(255, dst_r * 256) : qMin(255, ((dst_r * 256) / (255-src_r)));
469
src_g = src_g == 255 ? qMin(255, dst_g * 256) : qMin(255, ((dst_g * 256) / (255-src_g)));
470
src_b = src_b == 255 ? qMin(255, dst_b * 256) : qMin(255, ((dst_b * 256) / (255-src_b)));
472
else if (m_blendMode == 11)
474
src_r = qMax<uchar>(1, src_r);
475
src_g = qMax<uchar>(1, src_g);
476
src_b = qMax<uchar>(1, src_b);
477
src_r = static_cast<int>(255 - (((255-dst_r) * 256) / src_r)) < 0 ? 0 : 255 - (((255-dst_r) * 256) / src_r);
478
src_g = static_cast<int>(255 - (((255-dst_g) * 256) / src_g)) < 0 ? 0 : 255 - (((255-dst_g) * 256) / src_g);
479
src_b = static_cast<int>(255 - (((255-dst_b) * 256) / src_b)) < 0 ? 0 : 255 - (((255-dst_b) * 256) / src_b);
481
if (m_blendMode == 12)
486
RGBTOHLS(src_r, src_g, src_b);
487
RGBTOHLS(new_r, new_g, new_b);
489
HLSTORGB(new_r, new_g, new_b);
494
else if (m_blendMode == 13)
499
RGBTOHLS(src_r, src_g, src_b);
500
RGBTOHLS(new_r, new_g, new_b);
502
HLSTORGB(new_r, new_g, new_b);
507
else if (m_blendMode == 14)
512
setLum(new_r, new_g, new_b, Lum(dst_r, dst_g, dst_b));
517
else if (m_blendMode == 15)
522
setLum(new_r, new_g, new_b, Lum(src_r, src_g, src_b));
527
newResult = qRgba(src_r, src_g, src_b, src_a);
545
cairo_pop_group_to_source (m_cr);
546
if (la.groupClip.size() != 0)
548
setupPolygon(&la.groupClip);
551
if (m_blendMode == 0)
553
cairo_set_operator(m_cr, CAIRO_OPERATOR_OVER);
554
cairo_paint_with_alpha (m_cr, m_layerTransparency);
558
cairo_set_operator(m_cr, CAIRO_OPERATOR_DEST_OUT);
559
cairo_paint_with_alpha (m_cr, m_layerTransparency);
560
cairo_set_operator(m_cr, CAIRO_OPERATOR_ADD);
561
cairo_paint_with_alpha (m_cr, m_layerTransparency);
563
cairo_set_operator(m_cr, CAIRO_OPERATOR_OVER);
568
int h = m_image->height();
569
int w = m_image->width();
570
for( int yi = 0; yi < h; ++yi )
572
src = (QRgb*)la.data->scanLine(yi);
573
dst = (QRgb*)m_image->scanLine(yi);
574
for( int xi=0; xi < w; ++xi )
584
if (la.groupClip.size() != 0)
586
setupPolygon(&la.groupClip);
589
painter.resetMatrix();
590
if ((m_blendMode > 0) && (m_blendMode < 12))
592
if (m_blendMode == 1)
593
painter.setCompositionMode(QPainter::CompositionMode_Darken);
594
else if (m_blendMode == 2)
595
painter.setCompositionMode(QPainter::CompositionMode_Lighten);
596
else if (m_blendMode == 3)
597
painter.setCompositionMode(QPainter::CompositionMode_Multiply);
598
else if (m_blendMode == 4)
599
painter.setCompositionMode(QPainter::CompositionMode_Screen);
600
else if (m_blendMode == 5)
601
painter.setCompositionMode(QPainter::CompositionMode_Overlay);
602
else if (m_blendMode == 6)
603
painter.setCompositionMode(QPainter::CompositionMode_HardLight);
604
else if (m_blendMode == 7)
605
painter.setCompositionMode(QPainter::CompositionMode_SoftLight);
606
else if (m_blendMode == 8)
607
painter.setCompositionMode(QPainter::CompositionMode_Difference);
608
else if (m_blendMode == 9)
609
painter.setCompositionMode(QPainter::CompositionMode_Exclusion);
610
else if (m_blendMode == 10)
611
painter.setCompositionMode(QPainter::CompositionMode_ColorDodge);
612
else if (m_blendMode == 11)
613
painter.setCompositionMode(QPainter::CompositionMode_ColorBurn);
615
painter.setOpacity(m_layerTransparency);
616
painter.drawImage(0, 0, *la.data);
617
painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
622
m_layerTransparency = la.tranparency;
623
m_blendMode = la.blendmode;
626
void ScPainter::begin()
630
void ScPainter::end()
634
cairo_show_page (m_cr);
637
cairo_surface_flush(cairo_get_target(m_cr));
638
cairo_restore( m_cr );
644
void ScPainter::clear()
648
m_image->fill( qRgba(255, 255, 255, 255) );
650
m_image->fill(qRgba(255, 255, 255, 255));
654
void ScPainter::clear( const QColor &c )
659
m_image->fill( qRgba(qRed(cs), qGreen(cs), qBlue(cs), qAlpha(cs)) );
661
m_image->fill(qRgba(qRed(cs), qGreen(cs), qBlue(cs), qAlpha(cs)));
665
const QMatrix ScPainter::worldMatrix()
668
cairo_matrix_t matrix;
669
cairo_get_matrix(m_cr, &matrix);
671
mat.setMatrix ( matrix.xx, matrix.yx, matrix.xy, matrix.yy, matrix.x0, matrix.y0 );
674
return painter.worldMatrix();
678
void ScPainter::setWorldMatrix( const QMatrix &mat )
681
cairo_matrix_t matrix;
682
cairo_matrix_init(&matrix, mat.m11(), mat.m12(), mat.m21(), mat.m22(), mat.dx(), mat.dy());
683
cairo_set_matrix(m_cr, &matrix);
685
painter.setWorldMatrix(mat);
689
void ScPainter::setAntialiasing(bool enable)
693
cairo_set_antialias(m_cr, CAIRO_ANTIALIAS_DEFAULT);
695
cairo_set_antialias(m_cr, CAIRO_ANTIALIAS_NONE);
697
painter.setRenderHint(QPainter::Antialiasing, enable);
701
void ScPainter::setZoomFactor( double zoomFactor )
703
m_zoomFactor = zoomFactor;
705
cairo_scale (m_cr, m_zoomFactor, m_zoomFactor);
707
painter.scale(m_zoomFactor, m_zoomFactor);
711
void ScPainter::translate( double x, double y )
714
cairo_translate (m_cr, x, y);
716
painter.translate(x, y);
720
void ScPainter::rotate( double r )
723
cairo_rotate (m_cr, r * 3.1415927 / 180.0);
729
void ScPainter::scale( double x, double y )
732
cairo_scale (m_cr, x, y);
738
void ScPainter::moveTo( const double &x, const double &y )
741
cairo_move_to( m_cr, x, y);
748
ScPainter::lineTo( const double &x, const double &y )
751
cairo_line_to( m_cr, x, y);
757
void ScPainter::curveTo( FPoint p1, FPoint p2, FPoint p3 )
760
cairo_curve_to(m_cr, p1.x(), p1.y(), p2.x(), p2.y(), p3.x(), p3.y());
762
m_path.cubicTo(p1.x(), p1.y(), p2.x(), p2.y(), p3.x(), p3.y());
766
void ScPainter::newPath()
769
cairo_new_path( m_cr );
771
m_path = QPainterPath();
775
void ScPainter::closePath()
778
cairo_close_path( m_cr );
780
m_path.closeSubpath();
784
void ScPainter::setFillRule( bool fillRule )
786
m_fillRule = fillRule;
789
void ScPainter::setFillMode( int fill )
794
void ScPainter::setGradient(VGradient::VGradientType mode, FPoint orig, FPoint vec, FPoint foc)
796
fill_gradient.setType(mode);
797
fill_gradient.setOrigin(orig);
798
fill_gradient.setVector(vec);
799
fill_gradient.setFocalPoint(foc);
802
void ScPainter::fillTextPath()
807
void ScPainter::strokeTextPath()
809
// if( LineWidth == 0 )
814
void ScPainter::fillPath()
820
void ScPainter::strokePath()
822
// if( LineWidth == 0 )
827
QColor ScPainter::pen()
832
QColor ScPainter::brush()
837
void ScPainter::setPen( const QColor &c )
842
void ScPainter::setPen( const QColor &c, double w, Qt::PenStyle st, Qt::PenCapStyle ca, Qt::PenJoinStyle jo )
850
getDashArray(st, w, m_array);
857
void ScPainter::setLineWidth( double w )
862
void ScPainter::setPenOpacity( double op )
868
void ScPainter::setDash(const QVector<double>& array, double ofs)
874
void ScPainter::setBrush( const QColor &c )
879
void ScPainter::setBrushOpacity( double op )
884
void ScPainter::setOpacity( double op )
890
void ScPainter::setFont( const QFont &f)
895
QFont ScPainter::font()
900
void ScPainter::save()
909
void ScPainter::restore()
912
cairo_restore( m_cr );
918
void ScPainter::setRasterOp( int )
922
void ScPainter::setPattern(ScPattern *pattern, double scaleX, double scaleY, double offsetX, double offsetY, double rotation)
925
patternScaleX = scaleX / 100.0;
926
patternScaleY = scaleY / 100.0;
927
patternOffsetX = offsetX;
928
patternOffsetY = offsetY;
929
patternRotation = rotation;
933
void ScPainter::drawVPath( int mode )
939
cairo_set_fill_rule (m_cr, CAIRO_FILL_RULE_EVEN_ODD);
941
cairo_set_fill_rule (m_cr, CAIRO_FILL_RULE_WINDING);
945
m_fill.getRgbF(&r, &g, &b);
946
cairo_set_source_rgba( m_cr, r, g, b, fill_trans );
947
// if (fill_trans != 1.0)
948
cairo_set_operator(m_cr, CAIRO_OPERATOR_OVER);
950
// cairo_set_operator(m_cr, CAIRO_OPERATOR_SOURCE);
951
cairo_fill_preserve( m_cr );
953
else if (fillMode == 2)
955
cairo_pattern_t *pat;
957
double rampPoint, lastPoint = 0.0;
958
double x1 = fill_gradient.origin().x();
959
double y1 = fill_gradient.origin().y();
960
double x2 = fill_gradient.vector().x();
961
double y2 = fill_gradient.vector().y();
962
if (fill_gradient.type() == VGradient::linear)
963
pat = cairo_pattern_create_linear (x1, y1, x2, y2);
965
pat = cairo_pattern_create_radial (x1, y1, 0.1, x1, y1, sqrt(pow(x2 - x1, 2) + pow(y2 - y1,2)));
966
QList<VColorStop*> colorStops = fill_gradient.colorStops();
968
for( int offset = 0 ; offset < colorStops.count() ; offset++ )
970
qStopColor = colorStops[ offset ]->color;
971
rampPoint = colorStops[ offset ]->rampPoint;
972
if ((lastPoint == rampPoint) && (!isFirst))
975
int h, s, v, sneu, vneu;
976
int shad = colorStops[offset]->shade;
977
qStopColor.getHsv(&h, &s, &v);
978
sneu = s * shad / 100;
979
vneu = 255 - ((255 - v) * shad / 100);
980
qStopColor.setHsv(h, sneu, vneu);
981
double a = colorStops[offset]->opacity;
983
qStopColor.getRgbF(&r, &g, &b);
984
cairo_pattern_add_color_stop_rgba (pat, rampPoint, r, g, b, a);
985
lastPoint = rampPoint;
987
cairo_set_source (m_cr, pat);
988
cairo_clip_preserve (m_cr);
989
cairo_paint_with_alpha (m_cr, fill_trans);
990
cairo_pattern_destroy (pat);
992
else if (fillMode == 3)
994
cairo_set_antialias(m_cr, CAIRO_ANTIALIAS_NONE);
995
cairo_surface_t *image2 = cairo_image_surface_create_for_data ((uchar*)m_pattern->getPattern()->bits(), CAIRO_FORMAT_ARGB32, m_pattern->getPattern()->width(), m_pattern->getPattern()->height(), m_pattern->getPattern()->width()*4);
996
cairo_pattern_t *m_pat = cairo_pattern_create_for_surface(image2);
997
cairo_pattern_set_extend(m_pat, CAIRO_EXTEND_REPEAT);
998
cairo_pattern_set_filter(m_pat, CAIRO_FILTER_BEST);
999
cairo_matrix_t matrix;
1001
// qmatrix.scale(m_zoomFactor, m_zoomFactor);
1002
qmatrix.translate(patternOffsetX, patternOffsetY);
1003
qmatrix.rotate(patternRotation);
1004
qmatrix.scale(patternScaleX, patternScaleY);
1005
qmatrix.scale(m_pattern->width / static_cast<double>(m_pattern->getPattern()->width()), m_pattern->height / static_cast<double>(m_pattern->getPattern()->height()));
1006
cairo_matrix_init(&matrix, qmatrix.m11(), qmatrix.m12(), qmatrix.m21(), qmatrix.m22(), qmatrix.dx(), qmatrix.dy());
1007
cairo_matrix_invert(&matrix);
1008
cairo_pattern_set_matrix (m_pat, &matrix);
1009
cairo_set_source (m_cr, m_pat);
1010
cairo_clip_preserve (m_cr);
1011
cairo_paint_with_alpha (m_cr, fill_trans);
1012
cairo_pattern_destroy (m_pat);
1013
cairo_surface_destroy (image2);
1014
cairo_set_antialias(m_cr, CAIRO_ANTIALIAS_DEFAULT);
1019
if( LineWidth == 0 )
1020
cairo_set_line_width( m_cr, 1.0 / m_zoomFactor );
1022
cairo_set_line_width( m_cr, LineWidth );
1023
if( m_array.count() > 0 )
1024
cairo_set_dash( m_cr, m_array.data(), m_array.count(), m_offset);
1026
cairo_set_dash( m_cr, NULL, 0, 0 );
1028
m_stroke.getRgbF(&r, &g, &b);
1029
cairo_set_source_rgba( m_cr, r, g, b, stroke_trans );
1030
// if (stroke_trans != 1.0)
1031
cairo_set_operator(m_cr, CAIRO_OPERATOR_OVER);
1033
// cairo_set_operator(m_cr, CAIRO_OPERATOR_SOURCE);
1034
if( PLineEnd == Qt::RoundCap )
1035
cairo_set_line_cap (m_cr, CAIRO_LINE_CAP_ROUND);
1036
else if( PLineEnd == Qt::SquareCap )
1037
cairo_set_line_cap (m_cr, CAIRO_LINE_CAP_SQUARE);
1038
else if( PLineEnd == Qt::FlatCap )
1039
cairo_set_line_cap (m_cr, CAIRO_LINE_CAP_BUTT);
1040
if( PLineJoin == Qt::RoundJoin )
1041
cairo_set_line_join( m_cr, CAIRO_LINE_JOIN_ROUND );
1042
else if( PLineJoin == Qt::BevelJoin )
1043
cairo_set_line_join( m_cr, CAIRO_LINE_JOIN_BEVEL );
1044
else if( PLineJoin == Qt::MiterJoin )
1045
cairo_set_line_join( m_cr, CAIRO_LINE_JOIN_MITER );
1046
cairo_stroke_preserve( m_cr );
1048
// cairo_set_operator(m_cr, CAIRO_OPERATOR_OVER);
1049
cairo_restore( m_cr );
1053
void ScPainter::drawVPath(int mode)
1059
m_path.setFillRule(Qt::OddEvenFill);
1061
m_path.setFillRule(Qt::WindingFill);
1064
QColor paint = m_fill;
1065
paint.setAlphaF(fill_trans);
1066
painter.fillPath(m_path, paint);
1068
else if (fillMode == 2)
1071
bool isFirst = true;
1072
double rampPoint, lastPoint = 0.0;
1073
double x1 = fill_gradient.origin().x();
1074
double y1 = fill_gradient.origin().y();
1075
double x2 = fill_gradient.vector().x();
1076
double y2 = fill_gradient.vector().y();
1077
if (fill_gradient.type() == VGradient::linear)
1078
pat = QLinearGradient(x1, y1, x2, y2);
1080
pat = QRadialGradient(x1, y1, sqrt(pow(x2 - x1, 2) + pow(y2 - y1,2)), x1, y1);
1081
QList<VColorStop*> colorStops = fill_gradient.colorStops();
1083
for( int offset = 0 ; offset < colorStops.count() ; offset++ )
1085
qStopColor = colorStops[ offset ]->color;
1086
rampPoint = colorStops[ offset ]->rampPoint;
1087
if ((lastPoint == rampPoint) && (!isFirst))
1090
int h, s, v, sneu, vneu;
1091
int shad = colorStops[offset]->shade;
1092
qStopColor.getHsv(&h, &s, &v);
1093
sneu = s * shad / 100;
1094
vneu = 255 - ((255 - v) * shad / 100);
1095
qStopColor.setHsv(h, sneu, vneu);
1096
qStopColor.setAlphaF(colorStops[offset]->opacity);
1097
pat.setColorAt(colorStops[ offset ]->rampPoint, qStopColor);
1098
lastPoint = rampPoint;
1100
painter.setOpacity(fill_trans);
1101
painter.fillPath(m_path, pat);
1103
else if (fillMode == 3)
1105
painter.setRenderHint(QPainter::Antialiasing, false);
1106
painter.setRenderHint(QPainter::SmoothPixmapTransform, false);
1108
qmatrix.translate(patternOffsetX, patternOffsetY);
1109
qmatrix.rotate(patternRotation);
1110
qmatrix.scale(patternScaleX, patternScaleY);
1111
qmatrix.scale(m_pattern->width / static_cast<double>(m_pattern->getPattern()->width()), m_pattern->height / static_cast<double>(m_pattern->getPattern()->height()));
1112
QBrush brush = QBrush(*m_pattern->getPattern());
1113
brush.setMatrix(qmatrix);
1114
painter.rotate(0.0001); // hack to get Qt-4's strange pattern rendering working
1115
painter.setOpacity(fill_trans);
1116
painter.fillPath(m_path, brush);
1117
painter.setRenderHint(QPainter::Antialiasing, true);
1118
painter.setRenderHint(QPainter::SmoothPixmapTransform, true);
1123
QColor paint = m_stroke;
1124
paint.setAlphaF(stroke_trans);
1126
if( m_array.count() == 0 )
1128
if (PLineStyle == Qt::SolidLine)
1129
pen = QPen(paint, LineWidth, PLineStyle, PLineEnd, PLineJoin);
1132
getDashArray(PLineStyle, 1, m_array);
1133
pen.setDashPattern(m_array);
1134
pen.setColor(paint);
1135
pen.setWidthF(LineWidth);
1136
pen.setCapStyle(PLineEnd);
1137
pen.setJoinStyle(PLineJoin);
1142
double lw = LineWidth;
1143
if( LineWidth == 0 )
1144
lw = 1.0 / m_zoomFactor;
1145
QVector<qreal> dashes;
1146
for (int a = 0; a < m_array.count(); a++)
1148
dashes.append(m_array[a] / lw);
1150
pen.setDashPattern(dashes);
1151
pen.setDashOffset(m_offset / lw);
1152
pen.setColor(paint);
1153
pen.setWidthF(LineWidth);
1154
pen.setCapStyle(PLineEnd);
1155
pen.setJoinStyle(PLineJoin);
1157
painter.strokePath(m_path, pen);
1163
void ScPainter::setClipPath()
1168
painter.setClipPath(m_path, Qt::IntersectClip);
1169
m_path = QPainterPath();
1173
void ScPainter::drawImage( QImage *image )
1176
#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 2, 6)
1178
cairo_surface_t *image3 = cairo_image_surface_create_for_data ((uchar*)image->bits(), CAIRO_FORMAT_ARGB32, image->width(), image->height(), image->width()*4);
1179
cairo_set_source_surface (m_cr, image3, 0, 0);
1180
cairo_paint_with_alpha (m_cr, fill_trans);
1181
cairo_surface_destroy (image3);
1183
/* Code with Layers, crashes on cairo_push_group */
1184
// cairo_scale(m_cr, m_zoomFactor, m_zoomFactor);
1185
cairo_push_group(m_cr);
1186
cairo_set_fill_rule(m_cr, cairo_get_fill_rule(m_cr));
1187
cairo_surface_t *image2 = cairo_image_surface_create_for_data ((uchar*)image->bits(), CAIRO_FORMAT_RGB24, image->width(), image->height(), image->width()*4);
1188
cairo_surface_t *image3 = cairo_image_surface_create_for_data ((uchar*)image->bits(), CAIRO_FORMAT_ARGB32, image->width(), image->height(), image->width()*4);
1189
cairo_set_source_surface (m_cr, image2, 0, 0);
1190
cairo_mask_surface (m_cr, image3, 0, 0);
1191
cairo_surface_destroy (image2);
1192
cairo_surface_destroy (image3);
1193
cairo_pop_group_to_source (m_cr);
1194
cairo_paint_with_alpha (m_cr, fill_trans);
1196
/* Working code, sadly we need to create an additional mask image with the same size as the image to be painted */
1197
cairo_surface_t *image3;
1199
cairo_set_fill_rule(m_cr, cairo_get_fill_rule(m_cr));
1200
cairo_surface_t *image2 = cairo_image_surface_create_for_data ((uchar*)image->bits(), CAIRO_FORMAT_RGB24, image->width(), image->height(), image->width()*4);
1201
if (fill_trans != 1.0)
1203
mask = QImage(image->width(), image->height(), QImage::Format_Mono);
1204
for( int yi = 0; yi < image->height(); ++yi )
1206
QRgb * s = (QRgb*)(image->scanLine( yi ));
1207
unsigned char *d = (unsigned char *)(mask.scanLine( yi ));
1208
for( int xi=0; xi < image->width(); ++xi )
1210
*d++ = static_cast<unsigned char>(qAlpha(*s++) * fill_trans);
1214
if (image->width() % 4 == 0)
1217
adj = 4 - (image->width() % 4);
1218
image3 = cairo_image_surface_create_for_data ((uchar*)mask.bits(), CAIRO_FORMAT_A8, image->width(), image->height(), image->width() + adj);
1221
image3 = cairo_image_surface_create_for_data ((uchar*)image->bits(), CAIRO_FORMAT_ARGB32, image->width(), image->height(), image->width()*4);
1222
cairo_set_source_surface (m_cr, image2, 0, 0);
1223
cairo_mask_surface (m_cr, image3, 0, 0);
1224
cairo_surface_destroy (image2);
1225
cairo_surface_destroy (image3);
1228
painter.setOpacity(fill_trans);
1229
painter.drawImage(0, 0, *image);
1233
void ScPainter::setupPolygon(FPointArray *points, bool closed)
1237
FPoint np, np1, np2, np3;
1239
if (points->size() > 3)
1242
for (uint poi=0; poi<points->size()-3; poi += 4)
1244
if (points->point(poi).x() > 900000)
1251
np = points->point(poi);
1252
if ((!first) && (closed))
1253
cairo_close_path( m_cr );
1254
cairo_move_to( m_cr, np.x(), np.y());
1258
np = points->point(poi);
1259
np1 = points->point(poi+1);
1260
np2 = points->point(poi+3);
1261
np3 = points->point(poi+2);
1262
if ((np == np1) && (np2 == np3))
1263
cairo_line_to( m_cr, np3.x(), np3.y());
1265
cairo_curve_to(m_cr, np1.x(), np1.y(), np2.x(), np2.y(), np3.x(), np3.y());
1268
cairo_close_path( m_cr );
1272
if (points->size() > 3)
1275
for (uint poi=0; poi<points->size()-3; poi += 4)
1277
if (points->point(poi).x() > 900000)
1284
np = points->point(poi);
1285
if ((!first) && (closed))
1286
m_path.closeSubpath();
1287
m_path.moveTo(np.x(), np.y());
1291
np = points->point(poi);
1292
np1 = points->point(poi+1);
1293
np2 = points->point(poi+3);
1294
np3 = points->point(poi+2);
1295
if ((np == np1) && (np2 == np3))
1296
m_path.lineTo(np3.x(), np3.y());
1298
m_path.cubicTo(np1.x(), np1.y(), np2.x(), np2.y(), np3.x(), np3.y());
1301
m_path.closeSubpath();
1306
void ScPainter::drawPolygon()
1311
void ScPainter::drawPolyLine()
1316
void ScPainter::drawLine(FPoint start, FPoint end)
1319
moveTo(start.x(), start.y());
1320
lineTo(end.x(), end.y());
1324
void ScPainter::drawRect(double x, double y, double w, double h)
1328
cairo_rectangle(m_cr, x, y, w, h);
1330
// lineTo( x+w, y );
1331
// lineTo( x+w, y+h );
1332
// lineTo( x, y+h );
1334
// cairo_close_path( m_cr );
1336
m_path.addRect(x, y, w, h);
1342
void ScPainter::drawText(QRectF area, QString text)
1345
cairo_text_extents_t extents;
1346
cairo_font_extents_t extentsF;
1347
double x = area.center().x();
1352
cairo_select_font_face(m_cr, m_font.family().toLatin1(), CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
1353
cairo_set_font_size(m_cr, m_font.pointSizeF());
1354
cairo_font_extents (m_cr, &extentsF);
1355
QStringList textList = text.split("\n");
1356
for (int a = 0; a < textList.count(); ++a)
1358
cairo_text_extents (m_cr, textList[a].toUtf8(), &extents);
1359
x = qMin(area.center().x() - (extents.width / 2.0 + extents.x_bearing), x);
1360
ww = qMax(ww, extents.width);
1362
hh = extentsF.height * textList.count();
1363
y = area.center().y() - ((extentsF.height * textList.count()) / 2.0);
1364
m_fill.getRgbF(&r, &g, &b);
1365
cairo_set_source_rgba( m_cr, r, g, b, fill_trans );
1366
cairo_new_path( m_cr );
1367
cairo_rectangle(m_cr, x, y, ww, hh);
1369
cairo_new_path( m_cr );
1370
y += extentsF.ascent;
1371
cairo_move_to (m_cr, x, y);
1372
m_stroke.getRgbF(&r, &g, &b);
1373
cairo_set_source_rgba( m_cr, r, g, b, stroke_trans );
1374
for (int a = 0; a < textList.count(); ++a)
1376
cairo_show_text (m_cr, textList[a].toUtf8());
1377
y += extentsF.height;
1378
cairo_move_to (m_cr, x, y);
1381
painter.setFont(m_font);
1382
painter.setPen(m_stroke);
1383
painter.drawText(area, text, QTextOption(Qt::AlignCenter));