Subversion Repositories Scribus

Rev

Rev 25157 | 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
 
6733 avox 8
#include "scpainter.h"
19034 craig 9
#include "scpattern.h"
10988 fschmid 10
#include "util.h"
14284 fschmid 11
#include "util_math.h"
6733 avox 12
 
16281 jghali 13
#include <cairo.h>
21563 jghali 14
#if CAIRO_HAS_FC_FONT
15
#include <cairo-ft.h>
16
#endif
17
#include "text/storytext.h"
18
#include "text/textshaper.h"
19
#include "text/glyphcluster.h"
68 Franz 20
 
22652 craig 21
#include <cmath>
16732 fschmid 22
#include <QDebug>
68 Franz 23
 
24114 jghali 24
ScPainter::ScPainter(QImage *target, int w, int h, double transparency, int blendmode)
24716 jghali 25
         : m_image(target),
26
               m_layerTransparency(transparency),
24901 craig 27
                   m_blendMode(blendmode)
1815 fschmid 28
{
23337 jghali 29
        Q_ASSERT(w >= 0);
30
        Q_ASSERT(h >= 0);
24713 jghali 31
 
22315 craig 32
        setHatchParameters(0, 2, 0, false, QColor(), QColor(), 0.0, 0.0);
33
 
24713 jghali 34
        m_zoomStack.clear();
22315 craig 35
 
24115 jghali 36
        cairo_surface_t *img = cairo_image_surface_create_for_data(m_image->bits(), CAIRO_FORMAT_ARGB32, w, h, w * 4);
21327 craig 37
        cairo_surface_set_device_scale(img, m_image->devicePixelRatio(), m_image->devicePixelRatio());
3376 fschmid 38
        m_cr = cairo_create(img);
24114 jghali 39
        cairo_save(m_cr);
3376 fschmid 40
        cairo_set_fill_rule (m_cr, CAIRO_FILL_RULE_EVEN_ODD);
41
        cairo_set_operator(m_cr, CAIRO_OPERATOR_OVER);
24114 jghali 42
        cairo_set_tolerance(m_cr, 0.5);
1815 fschmid 43
}
44
 
68 Franz 45
ScPainter::~ScPainter()
46
{
4447 fschmid 47
        cairo_surface_destroy(cairo_get_target(m_cr));
24114 jghali 48
        cairo_destroy(m_cr);
68 Franz 49
}
50
 
7049 fschmid 51
void ScPainter::beginLayer(double transparency, int blendmode, FPointArray *clipArray)
5373 fschmid 52
{
5604 fschmid 53
        layerProp la;
54
        la.blendmode = m_blendMode;
55
        la.tranparency = m_layerTransparency;
5373 fschmid 56
        m_layerTransparency = transparency;
57
        m_blendMode = blendmode;
7049 fschmid 58
        la.pushed = false;
59
        la.groupClip.resize(0);
20691 craig 60
        la.maskMode = m_maskMode;
61
        la.mask_patternScaleX = m_mask_patternScaleX;
62
        la.mask_patternScaleY = m_mask_patternScaleY;
63
        la.mask_patternOffsetX = m_mask_patternOffsetX;
64
        la.mask_patternOffsetY = m_mask_patternOffsetY;
65
        la.mask_patternRotation = m_mask_patternRotation;
66
        la.mask_patternSkewX = m_mask_patternSkewX;
67
        la.mask_patternSkewY = m_mask_patternSkewY;
68
        la.mask_patternMirrorX = m_mask_patternMirrorX;
69
        la.mask_patternMirrorY = m_mask_patternMirrorY;
70
        la.mask_gradientScale = m_mask_gradientScale;
71
        la.mask_gradientSkew = m_mask_gradientSkew;
14854 fschmid 72
        la.mask_gradient = mask_gradient;
73
        la.maskPattern = m_maskPattern;
22519 craig 74
        if (clipArray != nullptr)
7049 fschmid 75
                la.groupClip = *clipArray;
9319 fschmid 76
        la.data = cairo_get_group_target(m_cr);
16744 fschmid 77
        la.fillRule = m_fillRule;
11412 fschmid 78
        cairo_push_group(m_cr);
9319 fschmid 79
        la.pushed = true;
20691 craig 80
        m_Layers.push(la);
5373 fschmid 81
}
82
 
7049 fschmid 83
void ScPainter::endLayer()
5373 fschmid 84
{
7049 fschmid 85
        layerProp la;
20691 craig 86
        if (m_Layers.count() == 0)
9099 fschmid 87
                return;
20691 craig 88
        la = m_Layers.pop();
89
        m_maskMode = la.maskMode;
90
        m_mask_patternScaleX = la.mask_patternScaleX;
91
        m_mask_patternScaleY = la.mask_patternScaleY;
92
        m_mask_patternOffsetX = la.mask_patternOffsetX;
93
        m_mask_patternOffsetY = la.mask_patternOffsetY;
94
        m_mask_patternRotation = la.mask_patternRotation;
95
        m_mask_patternSkewX = la.mask_patternSkewX;
96
        m_mask_patternSkewY = la.mask_patternSkewY;
97
        m_mask_patternMirrorX = la.mask_patternMirrorX;
98
        m_mask_patternMirrorY = la.mask_patternMirrorY;
99
        m_mask_gradientScale = la.mask_gradientScale;
100
        m_mask_gradientSkew = la.mask_gradientSkew;
14854 fschmid 101
        mask_gradient = la.mask_gradient;
102
        m_maskPattern = la.maskPattern;
16744 fschmid 103
        m_fillRule = la.fillRule;
14306 fschmid 104
        if (la.pushed)
105
        {
106
                cairo_pop_group_to_source (m_cr);
22607 craig 107
                if (!la.groupClip.empty())
14306 fschmid 108
                {
24114 jghali 109
                        if (m_fillRule)
16744 fschmid 110
                                cairo_set_fill_rule (m_cr, CAIRO_FILL_RULE_EVEN_ODD);
111
                        else
112
                                cairo_set_fill_rule (m_cr, CAIRO_FILL_RULE_WINDING);
14306 fschmid 113
                        setupPolygon(&la.groupClip);
114
                        setClipPath();
115
                }
14308 fschmid 116
                cairo_set_operator(m_cr, CAIRO_OPERATOR_OVER);
20691 craig 117
                if (m_maskMode > 0)
14306 fschmid 118
                {
119
                        cairo_pattern_t *patM = getMaskPattern();
14308 fschmid 120
                        setRasterOp(m_blendMode);
14306 fschmid 121
                        cairo_mask(m_cr, patM);
20691 craig 122
                        if ((m_maskMode == 2) || (m_maskMode == 4) || (m_maskMode == 5) || (m_maskMode == 6))
123
                                cairo_surface_destroy(m_imageMask);
14306 fschmid 124
                        cairo_pattern_destroy(patM);
125
                }
126
                else
14308 fschmid 127
                {
128
                        setRasterOp(m_blendMode);
14306 fschmid 129
                        cairo_paint_with_alpha (m_cr, m_layerTransparency);
14308 fschmid 130
                }
14306 fschmid 131
                cairo_set_operator(m_cr, CAIRO_OPERATOR_OVER);
132
        }
133
        m_layerTransparency = la.tranparency;
134
        m_blendMode = la.blendmode;
20691 craig 135
        m_maskMode = 0;
14306 fschmid 136
}
5373 fschmid 137
 
68 Franz 138
void ScPainter::begin()
139
{
140
}
141
 
142
void ScPainter::end()
143
{
20691 craig 144
        if (m_svgMode)
5471 fschmid 145
                cairo_show_page (m_cr);
20691 craig 146
        if (m_layeredMode)
5373 fschmid 147
        {
5433 fschmid 148
                cairo_surface_flush(cairo_get_target(m_cr));
24114 jghali 149
                cairo_restore(m_cr);
5373 fschmid 150
                return;
151
        }
68 Franz 152
}
153
 
1624 fschmid 154
void ScPainter::clear()
68 Franz 155
{
20691 craig 156
        if (m_imageMode)
24114 jghali 157
                m_image->fill(qRgba(255, 255, 255, 255));
68 Franz 158
}
159
 
24114 jghali 160
void ScPainter::clear(const QColor &c)
68 Franz 161
{
9319 fschmid 162
        QRgb cs = c.rgb();
20691 craig 163
        if (m_imageMode)
24114 jghali 164
                m_image->fill(qRgba(qRed(cs), qGreen(cs), qBlue(cs), qAlpha(cs)));
68 Franz 165
}
166
 
21107 craig 167
cairo_t *ScPainter::context()
168
{
169
        return m_cr;
170
}
171
 
25064 jghali 172
QTransform ScPainter::worldMatrix()
3113 fschmid 173
{
174
        cairo_matrix_t matrix;
175
        cairo_get_matrix(m_cr, &matrix);
24713 jghali 176
        QTransform mat(matrix.xx, matrix.yx, matrix.xy, matrix.yy, matrix.x0, matrix.y0);
3113 fschmid 177
        return mat;
178
}
179
 
24114 jghali 180
void ScPainter::setWorldMatrix(const QTransform &mat)
68 Franz 181
{
3113 fschmid 182
        cairo_matrix_t matrix;
183
        cairo_matrix_init(&matrix, mat.m11(), mat.m12(), mat.m21(), mat.m22(), mat.dx(), mat.dy());
184
        cairo_set_matrix(m_cr, &matrix);
68 Franz 185
}
186
 
6809 fschmid 187
void ScPainter::setAntialiasing(bool enable)
188
{
189
        if (enable)
190
                cairo_set_antialias(m_cr, CAIRO_ANTIALIAS_DEFAULT);
191
        else
192
                cairo_set_antialias(m_cr, CAIRO_ANTIALIAS_NONE);
193
}
194
 
24114 jghali 195
void ScPainter::setZoomFactor(double zoomFactor)
68 Franz 196
{
197
        m_zoomFactor = zoomFactor;
11196 fschmid 198
        cairo_scale (m_cr, m_zoomFactor, m_zoomFactor);
68 Franz 199
}
200
 
24114 jghali 201
void ScPainter::translate(double x, double y)
68 Franz 202
{
3113 fschmid 203
        cairo_translate (m_cr, x, y);
68 Franz 204
}
205
 
24114 jghali 206
void ScPainter::translate(const QPointF& offset)
16856 craig 207
{
208
        cairo_translate (m_cr, offset.x(), offset.y());
209
}
210
 
24114 jghali 211
void ScPainter::rotate(double r)
68 Franz 212
{
3113 fschmid 213
        cairo_rotate (m_cr, r * 3.1415927 / 180.0);
68 Franz 214
}
215
 
24114 jghali 216
void ScPainter::scale(double x, double y)
68 Franz 217
{
3113 fschmid 218
        cairo_scale (m_cr, x, y);
20560 fschmid 219
        m_zoomFactor *= qMax(x, y);
68 Franz 220
}
221
 
24114 jghali 222
void ScPainter::moveTo(const double &x, const double &y)
68 Franz 223
{
24114 jghali 224
        cairo_move_to(m_cr, x, y);
68 Franz 225
}
226
 
4646 subik 227
void
24114 jghali 228
ScPainter::lineTo(const double &x, const double &y)
68 Franz 229
{
24114 jghali 230
        cairo_line_to(m_cr, x, y);
68 Franz 231
}
232
 
24114 jghali 233
void ScPainter::curveTo(const FPoint& p1, const FPoint& p2, const FPoint& p3)
68 Franz 234
{
11196 fschmid 235
        cairo_curve_to(m_cr, p1.x(), p1.y(), p2.x(), p2.y(), p3.x(), p3.y());
68 Franz 236
}
237
 
238
void ScPainter::newPath()
239
{
24114 jghali 240
        cairo_new_path(m_cr);
68 Franz 241
}
242
 
5233 fschmid 243
void ScPainter::closePath()
244
{
24114 jghali 245
        cairo_close_path(m_cr);
5233 fschmid 246
}
247
 
24114 jghali 248
void ScPainter::setFillRule(bool fillRule)
68 Franz 249
{
250
        m_fillRule = fillRule;
251
}
252
 
24114 jghali 253
void ScPainter::setFillMode(int fill)
68 Franz 254
{
20640 jghali 255
        m_fillMode = fill;
68 Franz 256
}
257
 
24114 jghali 258
void ScPainter::setStrokeMode(int stroke)
14168 fschmid 259
{
20640 jghali 260
        m_strokeMode = stroke;
14168 fschmid 261
}
262
 
22635 craig 263
void ScPainter::setGradient(VGradient::VGradientType mode, const FPoint& orig, const FPoint& vec, const FPoint& foc, double scale, double skew)
68 Franz 264
{
265
        fill_gradient.setType(mode);
266
        fill_gradient.setOrigin(orig);
267
        fill_gradient.setVector(vec);
268
        fill_gradient.setFocalPoint(foc);
14168 fschmid 269
        stroke_gradient.setType(mode);
270
        stroke_gradient.setOrigin(orig);
271
        stroke_gradient.setVector(vec);
272
        stroke_gradient.setFocalPoint(foc);
20691 craig 273
        m_gradientScale = scale;
22271 craig 274
        if (skew == 90.0)
20691 craig 275
                m_gradientSkew = 1;
22271 craig 276
        else if (skew == 180.0)
20691 craig 277
                m_gradientSkew = 0;
22271 craig 278
        else if (skew == 270.0)
20691 craig 279
                m_gradientSkew = -1;
22271 craig 280
        else if (skew == 360.0)
20691 craig 281
                m_gradientSkew = 0;
14284 fschmid 282
        else
20691 craig 283
                m_gradientSkew = tan(M_PI / 180.0 * skew);
68 Franz 284
}
285
 
14297 fschmid 286
void ScPainter::setMaskMode(int mask)
287
{
20691 craig 288
        m_maskMode = mask;
14297 fschmid 289
}
290
 
22635 craig 291
void ScPainter::setGradientMask(VGradient::VGradientType mode, const FPoint& orig, const FPoint& vec, const FPoint& foc, double scale, double skew)
14297 fschmid 292
{
293
        mask_gradient.setType(mode);
294
        mask_gradient.setOrigin(orig);
295
        mask_gradient.setVector(vec);
296
        mask_gradient.setFocalPoint(foc);
20691 craig 297
        m_mask_gradientScale = scale;
22271 craig 298
        if (skew == 90.0)
20691 craig 299
                m_mask_gradientSkew = 1;
22271 craig 300
        else if (skew == 180.0)
20691 craig 301
                m_mask_gradientSkew = 0;
22271 craig 302
        else if (skew == 270.0)
20691 craig 303
                m_mask_gradientSkew = -1;
22271 craig 304
        else if (skew == 360.0)
20691 craig 305
                m_mask_gradientSkew = 0;
14297 fschmid 306
        else
20691 craig 307
                m_mask_gradientSkew = tan(M_PI / 180.0 * skew);
14297 fschmid 308
}
309
 
310
void ScPainter::setPatternMask(ScPattern *pattern, double scaleX, double scaleY, double offsetX, double offsetY, double rotation, double skewX, double skewY, bool mirrorX, bool mirrorY)
311
{
312
        m_maskPattern = pattern;
20691 craig 313
        m_mask_patternScaleX = scaleX / 100.0;
314
        m_mask_patternScaleY = scaleY / 100.0;
315
        m_mask_patternOffsetX = offsetX;
316
        m_mask_patternOffsetY = offsetY;
317
        m_mask_patternRotation = rotation;
318
        m_mask_patternSkewX = skewX;
319
        m_mask_patternSkewY = skewY;
320
        m_mask_patternMirrorX = mirrorX;
321
        m_mask_patternMirrorY = mirrorY;
14297 fschmid 322
}
323
 
22635 craig 324
void ScPainter::set4ColorGeometry(const FPoint& p1, const FPoint& p2, const FPoint& p3, const FPoint& p4, const FPoint& c1, const FPoint& c2, const FPoint& c3, const FPoint& c4)
14952 fschmid 325
{
326
        fill_gradient.setType(VGradient::fourcolor);
327
        gradPatchP1 = p1;
328
        gradPatchP2 = p2;
329
        gradPatchP3 = p3;
330
        gradPatchP4 = p4;
331
        gradControlP1 = c1;
332
        gradControlP2 = c2;
333
        gradControlP3 = c3;
334
        gradControlP4 = c4;
335
}
336
 
22635 craig 337
void ScPainter::set4ColorColors(const QColor& col1, const QColor& col2, const QColor& col3, const QColor& col4)
14952 fschmid 338
{
339
        gradPatchColor1 = col1;
340
        gradPatchColor2 = col2;
341
        gradPatchColor3 = col3;
342
        gradPatchColor4 = col4;
343
}
344
 
22635 craig 345
void ScPainter::setDiamondGeometry(const FPoint& p1, const FPoint& p2, const FPoint& p3, const FPoint& p4, const FPoint& c1, const FPoint& c2, const FPoint& c3, const FPoint& c4, const FPoint& c5)
14981 fschmid 346
{
347
        fill_gradient.setType(VGradient::diamond);
348
        gradPatchP1 = p1;
349
        gradPatchP2 = p2;
350
        gradPatchP3 = p3;
351
        gradPatchP4 = p4;
352
        gradControlP1 = c1;
353
        gradControlP2 = c2;
354
        gradControlP3 = c3;
355
        gradControlP4 = c4;
356
        gradControlP5 = c5;
357
}
358
 
22635 craig 359
void ScPainter::setMeshGradient(const FPoint& p1, const FPoint& p2, const FPoint& p3, const FPoint& p4, const QList<QList<MeshPoint>>& meshArray)
15024 fschmid 360
{
361
        fill_gradient.setType(VGradient::mesh);
362
        meshGradientArray = meshArray;
363
        gradPatchP1 = p1;
364
        gradPatchP2 = p2;
365
        gradPatchP3 = p3;
366
        gradPatchP4 = p4;
367
}
368
 
22635 craig 369
void ScPainter::setMeshGradient(const FPoint& p1, const FPoint& p2, const FPoint& p3, const FPoint& p4, const QList<meshGradientPatch>& meshPatches)
16729 fschmid 370
{
371
        fill_gradient.setType(VGradient::freemesh);
372
        meshGradientPatches = meshPatches;
373
        gradPatchP1 = p1;
374
        gradPatchP2 = p2;
375
        gradPatchP3 = p3;
376
        gradPatchP4 = p4;
377
}
378
 
22635 craig 379
void ScPainter::setHatchParameters(int mode, double distance, double angle, bool useBackground, const QColor& background, const QColor& foreground, double width, double height)
18935 fschmid 380
{
20691 craig 381
        m_hatchType = mode;
382
        m_hatchDistance = distance;
383
        m_hatchAngle = angle;
384
        m_hatchUseBackground = useBackground;
385
        m_hatchBackground = background;
386
        m_hatchForeground = foreground;
387
        m_hatchWidth = width;
388
        m_hatchHeight = height;
18935 fschmid 389
}
390
 
68 Franz 391
void ScPainter::fillPath()
392
{
20640 jghali 393
        if (m_fillMode != 0)
17288 jghali 394
                fillPathHelper();
68 Franz 395
}
396
 
397
void ScPainter::strokePath()
398
{
22721 jghali 399
//      if (LineWidth == 0)
13013 fschmid 400
//              return;
20640 jghali 401
        if (m_strokeMode != 0)
17788 fschmid 402
                strokePathHelper();
68 Franz 403
}
404
 
405
QColor ScPainter::pen()
406
{
407
        return m_stroke;
408
}
409
 
410
QColor ScPainter::brush()
411
{
412
        return m_fill;
413
}
414
 
21107 craig 415
double ScPainter::brushOpacity()
416
{
417
        return m_fill_trans;
418
}
419
 
24114 jghali 420
void ScPainter::setPen(const QColor &c)
68 Franz 421
{
422
        m_stroke = c;
423
}
424
 
24114 jghali 425
void ScPainter::setPen(const QColor &c, double w, Qt::PenStyle st, Qt::PenCapStyle ca, Qt::PenJoinStyle jo)
68 Franz 426
{
427
        m_stroke = c;
20691 craig 428
        m_LineWidth = w;
68 Franz 429
        PLineEnd = ca;
430
        PLineJoin = jo;
10988 fschmid 431
        m_offset = 0;
432
        getDashArray(st, w, m_array);
68 Franz 433
}
434
 
24114 jghali 435
void ScPainter::setLineWidth(double w)
68 Franz 436
{
20691 craig 437
        m_LineWidth = w;
68 Franz 438
}
439
 
24114 jghali 440
void ScPainter::setPenOpacity(double op)
68 Franz 441
{
20691 craig 442
        m_stroke_trans = op;
68 Franz 443
}
444
 
445
 
12055 jghali 446
void ScPainter::setDash(const QVector<double>& array, double ofs)
68 Franz 447
{
448
        m_array = array;
449
        m_offset = ofs;
450
}
451
 
24114 jghali 452
void ScPainter::setBrush(const QColor &c)
68 Franz 453
{
454
        m_fill = c;
455
}
456
 
24114 jghali 457
void ScPainter::setBrushOpacity(double op)
68 Franz 458
{
20691 craig 459
        m_fill_trans = op;
68 Franz 460
}
461
 
24114 jghali 462
void ScPainter::setOpacity(double op)
68 Franz 463
{
20691 craig 464
        m_fill_trans = op;
465
        m_stroke_trans = op;
68 Franz 466
}
467
 
21563 jghali 468
void ScPainter::setFont(const ScFace &f, double s)
68 Franz 469
{
470
        m_font = f;
21563 jghali 471
        m_fontSize = s;
68 Franz 472
}
473
 
474
void ScPainter::save()
475
{
24114 jghali 476
        cairo_save(m_cr);
20691 craig 477
        m_zoomStack.push(m_zoomFactor);
68 Franz 478
}
479
 
480
void ScPainter::restore()
481
{
24114 jghali 482
        cairo_restore(m_cr);
20691 craig 483
        if (!m_zoomStack.isEmpty())
484
                m_zoomFactor = m_zoomStack.pop();
68 Franz 485
}
486
 
21107 craig 487
int ScPainter::blendModeFill()
488
{
489
        return m_blendModeFill;
490
}
491
 
14306 fschmid 492
void ScPainter::setRasterOp(int blendMode)
68 Franz 493
{
14306 fschmid 494
        if (blendMode == 0)
495
                cairo_set_operator(m_cr, CAIRO_OPERATOR_OVER);
496
        else if (blendMode == 1)
497
                cairo_set_operator(m_cr, CAIRO_OPERATOR_DARKEN);
498
        else if (blendMode == 2)
499
                cairo_set_operator(m_cr, CAIRO_OPERATOR_LIGHTEN);
500
        else if (blendMode == 3)
501
                cairo_set_operator(m_cr, CAIRO_OPERATOR_MULTIPLY);
502
        else if (blendMode == 4)
503
                cairo_set_operator(m_cr, CAIRO_OPERATOR_SCREEN);
504
        else if (blendMode == 5)
505
                cairo_set_operator(m_cr, CAIRO_OPERATOR_OVERLAY);
506
        else if (blendMode == 6)
507
                cairo_set_operator(m_cr, CAIRO_OPERATOR_HARD_LIGHT);
508
        else if (blendMode == 7)
509
                cairo_set_operator(m_cr, CAIRO_OPERATOR_SOFT_LIGHT);
510
        else if (blendMode == 8)
511
                cairo_set_operator(m_cr, CAIRO_OPERATOR_DIFFERENCE);
512
        else if (blendMode == 9)
513
                cairo_set_operator(m_cr, CAIRO_OPERATOR_EXCLUSION);
514
        else if (blendMode == 10)
515
                cairo_set_operator(m_cr, CAIRO_OPERATOR_COLOR_DODGE);
516
        else if (blendMode == 11)
517
                cairo_set_operator(m_cr, CAIRO_OPERATOR_COLOR_BURN);
518
        else if (blendMode == 12)
519
                cairo_set_operator(m_cr, CAIRO_OPERATOR_HSL_HUE);
520
        else if (blendMode == 13)
521
                cairo_set_operator(m_cr, CAIRO_OPERATOR_HSL_SATURATION);
522
        else if (blendMode == 14)
523
                cairo_set_operator(m_cr, CAIRO_OPERATOR_HSL_COLOR);
524
        else if (blendMode == 15)
525
                cairo_set_operator(m_cr, CAIRO_OPERATOR_HSL_LUMINOSITY);
18954 fschmid 526
        else if (blendMode == 16)
527
                cairo_set_operator(m_cr, CAIRO_OPERATOR_ADD);
528
        else if (blendMode == 17)
529
                cairo_set_operator(m_cr, CAIRO_OPERATOR_DEST_IN);
530
        else if (blendMode == 18)
531
                cairo_set_operator(m_cr, CAIRO_OPERATOR_DEST_OUT);
20066 fschmid 532
        else if (blendMode == 19)
533
                cairo_set_operator(m_cr, CAIRO_OPERATOR_CLEAR);
14308 fschmid 534
        else
535
                cairo_set_operator(m_cr, CAIRO_OPERATOR_OVER);
68 Franz 536
}
537
 
24114 jghali 538
void ScPainter::setBlendModeFill(int blendMode)
14306 fschmid 539
{
540
        m_blendModeFill = blendMode;
541
}
542
 
24114 jghali 543
void ScPainter::setBlendModeStroke(int blendMode)
14306 fschmid 544
{
545
        m_blendModeStroke = blendMode;
546
}
547
 
14276 fschmid 548
void ScPainter::setPattern(ScPattern *pattern, double scaleX, double scaleY, double offsetX, double offsetY, double rotation, double skewX, double skewY, bool mirrorX, bool mirrorY)
6368 fschmid 549
{
6369 fschmid 550
        m_pattern = pattern;
20691 craig 551
        m_patternScaleX = scaleX / 100.0;
552
        m_patternScaleY = scaleY / 100.0;
553
        m_patternOffsetX = offsetX;
554
        m_patternOffsetY = offsetY;
555
        m_patternRotation = rotation;
556
        m_patternSkewX = skewX;
557
        m_patternSkewY = skewY;
558
        m_patternMirrorX = mirrorX;
559
        m_patternMirrorY = mirrorY;
6368 fschmid 560
}
561
 
14298 fschmid 562
cairo_pattern_t * ScPainter::getMaskPattern()
563
{
24114 jghali 564
        cairo_save(m_cr);
14298 fschmid 565
        cairo_pattern_t *pat;
20691 craig 566
        if ((m_maskMode == 1) || (m_maskMode == 3))
14298 fschmid 567
        {
14308 fschmid 568
                double x1 = mask_gradient.origin().x();
569
                double y1 = mask_gradient.origin().y();
570
                double x2 = mask_gradient.vector().x();
571
                double y2 = mask_gradient.vector().y();
572
                double fx = mask_gradient.focalPoint().x();
573
                double fy = mask_gradient.focalPoint().y();
574
                if (mask_gradient.type() == VGradient::linear)
575
                        pat = cairo_pattern_create_linear (x1, y1,  x2, y2);
576
                else
577
                        pat = cairo_pattern_create_radial (fx, fy, 0, x1, y1, sqrt(pow(x2 - x1, 2) + pow(y2 - y1,2)));
578
                QList<VColorStop*> colorStops = mask_gradient.colorStops();
579
                QColor qStopColor;
22723 jghali 580
                for (int offset = 0 ; offset < colorStops.count() ; offset++)
14308 fschmid 581
                {
582
                        qStopColor = colorStops[ offset ]->color;
583
                        double a = colorStops[offset]->opacity;
24834 jghali 584
                        float r, g, b;
14308 fschmid 585
                        qStopColor.getRgbF(&r, &g, &b);
20691 craig 586
                        if (m_maskMode == 3)
14825 fschmid 587
                                a = /* 1.0 - */(0.3 * r + 0.59 * g + 0.11 * b);
14308 fschmid 588
                        cairo_pattern_add_color_stop_rgba (pat, colorStops[ offset ]->rampPoint, r, g, b, a);
589
                }
590
                cairo_matrix_t matrix;
591
                QTransform qmatrix;
592
                if (mask_gradient.type() == VGradient::radial)
593
                {
594
                        double rotEnd = xy2Deg(x2 - x1, y2 - y1);
595
                        qmatrix.translate(x1, y1);
596
                        qmatrix.rotate(rotEnd);
20691 craig 597
                        qmatrix.shear(m_mask_gradientSkew, 0);
598
                        qmatrix.translate(0, y1 * (1.0 - m_mask_gradientScale));
14308 fschmid 599
                        qmatrix.translate(-x1, -y1);
20691 craig 600
                        qmatrix.scale(1, m_mask_gradientScale);
14308 fschmid 601
                }
602
                else
603
                {
604
                        qmatrix.translate(x1, y1);
20691 craig 605
                        qmatrix.shear(-m_mask_gradientSkew, 0);
14308 fschmid 606
                        qmatrix.translate(-x1, -y1);
607
                }
608
                cairo_matrix_init(&matrix, qmatrix.m11(), qmatrix.m12(), qmatrix.m21(), qmatrix.m22(), qmatrix.dx(), qmatrix.dy());
609
                cairo_matrix_invert(&matrix);
610
                cairo_pattern_set_matrix (pat, &matrix);
14298 fschmid 611
        }
612
        else
613
        {
20691 craig 614
                if ((m_maskMode == 4) || (m_maskMode == 5))
14318 fschmid 615
                {
20691 craig 616
                        m_imageQ = m_maskPattern->pattern.copy();
617
                        if (m_maskMode == 5)
618
                                m_imageQ.invertPixels();
619
                        int h = m_imageQ.height();
620
                        int w = m_imageQ.width();
14318 fschmid 621
                        int k;
622
                        QRgb *s;
623
                        QRgb r;
23337 jghali 624
                        for (int yi = 0; yi < h; ++yi)
14318 fschmid 625
                        {
24114 jghali 626
                                s = (QRgb*)(m_imageQ.scanLine(yi));
23337 jghali 627
                                for (int xi = 0; xi < w; ++xi)
14318 fschmid 628
                                {
629
                                        r = *s;
630
                                        if (qAlpha(r) == 0)
14825 fschmid 631
                                                k = 0; // 255;
14318 fschmid 632
                                        else
633
                                                k = qMin(qRound(0.3 * qRed(r) + 0.59 * qGreen(r) + 0.11 * qBlue(r)), 255);
14825 fschmid 634
                                        *s = qRgba(qRed(r), qGreen(r), qBlue(r), /* 255 - */ k);
14318 fschmid 635
                                        s++;
636
                                }
637
                        }
25064 jghali 638
                        m_imageMask = cairo_image_surface_create_for_data (m_imageQ.bits(), CAIRO_FORMAT_ARGB32, w, h, w * 4);
14318 fschmid 639
                }
640
                else
16732 fschmid 641
                {
20691 craig 642
                        m_imageQ = m_maskPattern->pattern.copy();
643
                        if (m_maskMode == 6)
644
                                m_imageQ.invertPixels(QImage::InvertRgba);
25064 jghali 645
                        m_imageMask = cairo_image_surface_create_for_data (m_imageQ.bits(), CAIRO_FORMAT_ARGB32, m_maskPattern->getPattern()->width(), m_maskPattern->getPattern()->height(), m_maskPattern->getPattern()->width() * 4);
16732 fschmid 646
                }
20691 craig 647
                pat = cairo_pattern_create_for_surface(m_imageMask);
14308 fschmid 648
                cairo_pattern_set_extend(pat, CAIRO_EXTEND_REPEAT);
14952 fschmid 649
                cairo_pattern_set_filter(pat, CAIRO_FILTER_GOOD);
14308 fschmid 650
                cairo_matrix_t matrix;
651
                QTransform qmatrix;
20691 craig 652
                qmatrix.translate(m_mask_patternOffsetX, m_mask_patternOffsetY);
653
                qmatrix.rotate(m_mask_patternRotation);
654
                qmatrix.shear(-m_mask_patternSkewX, m_mask_patternSkewY);
655
                qmatrix.scale(m_mask_patternScaleX, m_mask_patternScaleY);
14308 fschmid 656
                qmatrix.scale(m_maskPattern->width / static_cast<double>(m_maskPattern->getPattern()->width()), m_maskPattern->height / static_cast<double>(m_maskPattern->getPattern()->height()));
20691 craig 657
                if (m_mask_patternMirrorX)
14308 fschmid 658
                        qmatrix.scale(-1, 1);
20691 craig 659
                if (m_mask_patternMirrorY)
14308 fschmid 660
                        qmatrix.scale(1, -1);
661
                cairo_matrix_init(&matrix, qmatrix.m11(), qmatrix.m12(), qmatrix.m21(), qmatrix.m22(), qmatrix.dx(), qmatrix.dy());
662
                cairo_matrix_invert(&matrix);
663
                cairo_pattern_set_matrix (pat, &matrix);
14298 fschmid 664
        }
24114 jghali 665
        cairo_restore(m_cr);
14298 fschmid 666
        return pat;
667
}
668
 
17288 jghali 669
void ScPainter::fillPathHelper()
68 Franz 670
{
24114 jghali 671
        cairo_save(m_cr);
14306 fschmid 672
        cairo_set_operator(m_cr, CAIRO_OPERATOR_OVER);
22721 jghali 673
        if (m_fillRule)
17288 jghali 674
                cairo_set_fill_rule (m_cr, CAIRO_FILL_RULE_EVEN_ODD);
675
        else
676
                cairo_set_fill_rule (m_cr, CAIRO_FILL_RULE_WINDING);
20640 jghali 677
        if (m_fillMode == 1)
3113 fschmid 678
        {
24834 jghali 679
                float r, g, b;
17288 jghali 680
                m_fill.getRgbF(&r, &g, &b);
20691 craig 681
                if (m_maskMode > 0)
3113 fschmid 682
                {
17288 jghali 683
                        cairo_pattern_t *pat = getMaskPattern();
24114 jghali 684
                        cairo_set_source_rgb(m_cr, r, g, b);
17288 jghali 685
                        setRasterOp(m_blendModeFill);
686
                        cairo_clip_preserve(m_cr);
687
                        cairo_mask(m_cr, pat);
20691 craig 688
                        if ((m_maskMode == 2) || (m_maskMode == 4) || (m_maskMode == 5) || (m_maskMode == 6))
689
                                cairo_surface_destroy(m_imageMask);
17288 jghali 690
                        cairo_pattern_destroy(pat);
691
                }
692
                else
693
                {
24114 jghali 694
                        cairo_set_source_rgba(m_cr, r, g, b, m_fill_trans);
17288 jghali 695
                        setRasterOp(m_blendModeFill);
696
                        cairo_fill_preserve(m_cr);
6368 fschmid 697
                }
17288 jghali 698
        }
20640 jghali 699
        else if (m_fillMode == 2)
17288 jghali 700
        {
22519 craig 701
                cairo_pattern_t *pat = nullptr;
702
                cairo_surface_t *img = nullptr;
703
                cairo_t *cr = nullptr;
704
                cairo_pattern_t *mpat = nullptr;
17288 jghali 705
                if (fill_gradient.type() == VGradient::fourcolor)
706
                {
707
                        double p1x = gradPatchP1.x();
708
                        double p1y = gradPatchP1.y();
709
                        double p2x = gradPatchP2.x();
710
                        double p2y = gradPatchP2.y();
711
                        double p3x = gradPatchP3.x();
712
                        double p3y = gradPatchP3.y();
713
                        double p4x = gradPatchP4.x();
714
                        double p4y = gradPatchP4.y();
715
                        img = cairo_surface_create_similar(cairo_get_target(m_cr), CAIRO_CONTENT_COLOR_ALPHA, p3x, p3y);
716
                        cr = cairo_create(img);
717
                        cairo_set_fill_rule(cr, CAIRO_FILL_RULE_EVEN_ODD);
718
                        cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
24114 jghali 719
                        cairo_set_tolerance(cr, 0.5);
24834 jghali 720
                        float r, g, b, a;
17288 jghali 721
                        mpat = cairo_pattern_create_mesh();
17373 fschmid 722
                        cairo_mesh_pattern_begin_patch(mpat);
723
                        cairo_mesh_pattern_move_to(mpat, p1x, p1y);
724
                        cairo_mesh_pattern_line_to(mpat, p2x, p2y);
725
                        cairo_mesh_pattern_line_to(mpat, p3x, p3y);
726
                        cairo_mesh_pattern_line_to(mpat, p4x, p4y);
727
                        cairo_mesh_pattern_line_to(mpat, p1x, p1y);
728
                        cairo_mesh_pattern_set_control_point(mpat, 0, gradControlP1.x(),  gradControlP1.y());
729
                        cairo_mesh_pattern_set_control_point(mpat, 1, gradControlP2.x(),  gradControlP2.y());
730
                        cairo_mesh_pattern_set_control_point(mpat, 2, gradControlP3.x(),  gradControlP3.y());
731
                        cairo_mesh_pattern_set_control_point(mpat, 3, gradControlP4.x(),  gradControlP4.y());
732
                        gradPatchColor1.getRgbF(&r, &g, &b, &a);
733
                        cairo_mesh_pattern_set_corner_color_rgba(mpat, 0, r, g, b, a);
734
                        gradPatchColor2.getRgbF(&r, &g, &b, &a);
735
                        cairo_mesh_pattern_set_corner_color_rgba(mpat, 1, r, g, b, a);
736
                        gradPatchColor3.getRgbF(&r, &g, &b, &a);
737
                        cairo_mesh_pattern_set_corner_color_rgba(mpat, 2, r, g, b, a);
738
                        gradPatchColor4.getRgbF(&r, &g, &b, &a);
739
                        cairo_mesh_pattern_set_corner_color_rgba(mpat, 3, r, g, b, a);
740
                        cairo_mesh_pattern_end_patch(mpat);
17288 jghali 741
                        cairo_pattern_set_filter(mpat, CAIRO_FILTER_GOOD);
742
                        cairo_set_source(cr, mpat);
743
                        cairo_paint_with_alpha(cr, 1.0);
744
                        pat = cairo_pattern_create_for_surface(img);
745
                        cairo_pattern_set_extend(pat, CAIRO_EXTEND_NONE);
746
                        cairo_pattern_set_filter(pat, CAIRO_FILTER_GOOD);
747
                }
748
                else if (fill_gradient.type() == VGradient::diamond)
749
                {
750
                        double p1x = gradControlP1.x();
751
                        double p1y = gradControlP1.y();
752
                        double p2x = gradControlP2.x();
753
                        double p2y = gradControlP2.y();
754
                        double p3x = gradControlP3.x();
755
                        double p3y = gradControlP3.y();
756
                        double p4x = gradControlP4.x();
757
                        double p4y = gradControlP4.y();
758
                        img = cairo_surface_create_similar(cairo_get_target(m_cr), CAIRO_CONTENT_COLOR_ALPHA, gradPatchP3.x(), gradPatchP3.y());
759
                        cr = cairo_create(img);
760
                        cairo_set_fill_rule(cr, CAIRO_FILL_RULE_EVEN_ODD);
761
                        cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
24114 jghali 762
                        cairo_set_tolerance(cr, 0.5);
24834 jghali 763
                        float r, g, b, a;
17288 jghali 764
                        QList<VColorStop*> colorStops = fill_gradient.colorStops();
765
                        QList<QColor> qStopColors;
21289 fschmid 766
                        QList<double> qStopRampPoints;
17288 jghali 767
                        QColor qStopColor;
22723 jghali 768
                        for (int offset = 0 ; offset < colorStops.count() ; offset++)
17288 jghali 769
                        {
770
                                qStopColor = colorStops[ offset ]->color;
771
                                qStopColor.setAlphaF(colorStops[offset]->opacity);
21289 fschmid 772
                                if (offset == 0)
773
                                {
774
                                        if (colorStops[offset]->rampPoint > 0)
775
                                        {
776
                                                qStopRampPoints.append(0);
777
                                                qStopColors.append(qStopColor);
778
                                        }
779
                                }
17288 jghali 780
                                qStopColors.append(qStopColor);
21289 fschmid 781
                                qStopRampPoints.append(colorStops[offset]->rampPoint);
3113 fschmid 782
                        }
17295 jghali 783
                        qStopColors.last().getRgbF(&r, &g, &b, &a);
24713 jghali 784
                        QPointF centerP(gradControlP5.x(), gradControlP5.y());
785
                        QLineF edge1(centerP, QPointF(p1x, p1y));
786
                        QLineF edge2(centerP, QPointF(p2x, p2y));
787
                        QLineF edge3(centerP, QPointF(p3x, p3y));
788
                        QLineF edge4(centerP, QPointF(p4x, p4y));
17295 jghali 789
                        QPointF p1 = edge1.pointAt(colorStops.last()->rampPoint);
790
                        QPointF p2 = edge2.pointAt(colorStops.last()->rampPoint);
791
                        QPointF p3 = edge3.pointAt(colorStops.last()->rampPoint);
792
                        QPointF p4 = edge4.pointAt(colorStops.last()->rampPoint);
17288 jghali 793
                        cairo_set_source_rgba(cr, r, g, b, a);
794
                        cairo_paint_with_alpha(cr, 1.0);
795
                        cairo_set_operator(cr, CAIRO_OPERATOR_DEST_OUT);
796
                        cairo_new_path(cr);
797
                        cairo_move_to(cr, p1.x(), p1.y());
798
                        cairo_line_to(cr, p2.x(), p2.y());
799
                        cairo_line_to(cr, p3.x(), p3.y());
800
                        cairo_line_to(cr, p4.x(), p4.y());
801
                        cairo_close_path(cr);
802
                        cairo_set_source_rgba(cr, 0, 0, 0, 1);
803
                        cairo_fill(cr);
804
                        cairo_set_operator(cr, CAIRO_OPERATOR_ADD);
805
                        mpat = cairo_pattern_create_mesh();
22723 jghali 806
                        for (int offset = 1 ; offset < qStopRampPoints.count() ; offset++)
14981 fschmid 807
                        {
17288 jghali 808
                                QLineF e1 = edge1;
809
                                QLineF e1s = edge1;
810
                                QLineF e2 = edge2;
811
                                QLineF e2s = edge2;
812
                                QLineF e3 = edge3;
813
                                QLineF e3s = edge3;
814
                                QLineF e4 = edge4;
815
                                QLineF e4s = edge4;
21289 fschmid 816
                                e1.setLength(edge1.length() * qStopRampPoints[ offset ]);
817
                                e2.setLength(edge2.length() * qStopRampPoints[ offset ]);
818
                                e3.setLength(edge3.length() * qStopRampPoints[ offset ]);
819
                                e4.setLength(edge4.length() * qStopRampPoints[ offset ]);
820
                                e1s.setLength(edge1.length() * qStopRampPoints[ offset - 1 ]);
821
                                e2s.setLength(edge2.length() * qStopRampPoints[ offset - 1 ]);
822
                                e3s.setLength(edge3.length() * qStopRampPoints[ offset - 1 ]);
823
                                e4s.setLength(edge4.length() * qStopRampPoints[ offset - 1 ]);
17288 jghali 824
                                if (offset == 1)
14981 fschmid 825
                                {
17373 fschmid 826
                                        cairo_mesh_pattern_begin_patch(mpat);
827
                                        cairo_mesh_pattern_move_to(mpat, centerP.x(), centerP.y());
828
                                        cairo_mesh_pattern_line_to(mpat, e1.x2(), e1.y2());
829
                                        cairo_mesh_pattern_line_to(mpat, e2.x2(), e2.y2());
17288 jghali 830
                                        qStopColors[0].getRgbF(&r, &g, &b, &a);
17373 fschmid 831
                                        cairo_mesh_pattern_set_corner_color_rgba(mpat, 0, r, g, b, a);
832
                                        qStopColors[1].getRgbF(&r, &g, &b, &a);
833
                                        cairo_mesh_pattern_set_corner_color_rgba(mpat, 1, r, g, b, a);
834
                                        cairo_mesh_pattern_set_corner_color_rgba(mpat, 2, r, g, b, a);
835
                                        cairo_mesh_pattern_end_patch(mpat);
836
                                        cairo_mesh_pattern_begin_patch(mpat);
837
                                        cairo_mesh_pattern_move_to(mpat, centerP.x(), centerP.y());
838
                                        cairo_mesh_pattern_line_to(mpat, e2.x2(), e2.y2());
839
                                        cairo_mesh_pattern_line_to(mpat, e3.x2(), e3.y2());
17288 jghali 840
                                        qStopColors[0].getRgbF(&r, &g, &b, &a);
17373 fschmid 841
                                        cairo_mesh_pattern_set_corner_color_rgba(mpat, 0, r, g, b, a);
842
                                        qStopColors[1].getRgbF(&r, &g, &b, &a);
843
                                        cairo_mesh_pattern_set_corner_color_rgba(mpat, 1, r, g, b, a);
844
                                        cairo_mesh_pattern_set_corner_color_rgba(mpat, 2, r, g, b, a);
845
                                        cairo_mesh_pattern_end_patch(mpat);
846
                                        cairo_mesh_pattern_begin_patch(mpat);
847
                                        cairo_mesh_pattern_move_to(mpat, centerP.x(), centerP.y());
848
                                        cairo_mesh_pattern_line_to(mpat, e3.x2(), e3.y2());
849
                                        cairo_mesh_pattern_line_to(mpat, e4.x2(), e4.y2());
17288 jghali 850
                                        qStopColors[0].getRgbF(&r, &g, &b, &a);
17373 fschmid 851
                                        cairo_mesh_pattern_set_corner_color_rgba(mpat, 0, r, g, b, a);
852
                                        qStopColors[1].getRgbF(&r, &g, &b, &a);
853
                                        cairo_mesh_pattern_set_corner_color_rgba(mpat, 1, r, g, b, a);
854
                                        cairo_mesh_pattern_set_corner_color_rgba(mpat, 2, r, g, b, a);
855
                                        cairo_mesh_pattern_end_patch(mpat);
856
                                        cairo_mesh_pattern_begin_patch(mpat);
857
                                        cairo_mesh_pattern_move_to(mpat, centerP.x(), centerP.y());
858
                                        cairo_mesh_pattern_line_to(mpat, e4.x2(), e4.y2());
859
                                        cairo_mesh_pattern_line_to(mpat, e1.x2(), e1.y2());
17288 jghali 860
                                        qStopColors[0].getRgbF(&r, &g, &b, &a);
17373 fschmid 861
                                        cairo_mesh_pattern_set_corner_color_rgba(mpat, 0, r, g, b, a);
862
                                        qStopColors[1].getRgbF(&r, &g, &b, &a);
863
                                        cairo_mesh_pattern_set_corner_color_rgba(mpat, 1, r, g, b, a);
864
                                        cairo_mesh_pattern_set_corner_color_rgba(mpat, 2, r, g, b, a);
865
                                        cairo_mesh_pattern_end_patch(mpat);
14981 fschmid 866
                                }
17288 jghali 867
                                else
15024 fschmid 868
                                {
17373 fschmid 869
                                        cairo_mesh_pattern_begin_patch(mpat);
870
                                        cairo_mesh_pattern_move_to(mpat, e1s.x2(), e1s.y2());
871
                                        cairo_mesh_pattern_line_to(mpat, e1.x2(), e1.y2());
872
                                        cairo_mesh_pattern_line_to(mpat, e2.x2(), e2.y2());
873
                                        cairo_mesh_pattern_line_to(mpat, e2s.x2(), e2s.y2());
25064 jghali 874
                                        qStopColors[offset - 1].getRgbF(&r, &g, &b, &a);
17373 fschmid 875
                                        cairo_mesh_pattern_set_corner_color_rgba(mpat, 0, r, g, b, a);
876
                                        qStopColors[offset].getRgbF(&r, &g, &b, &a);
877
                                        cairo_mesh_pattern_set_corner_color_rgba(mpat, 1, r, g, b, a);
878
                                        cairo_mesh_pattern_set_corner_color_rgba(mpat, 2, r, g, b, a);
25064 jghali 879
                                        qStopColors[offset - 1].getRgbF(&r, &g, &b, &a);
17373 fschmid 880
                                        cairo_mesh_pattern_set_corner_color_rgba(mpat, 3, r, g, b, a);
881
                                        cairo_mesh_pattern_end_patch(mpat);
882
                                        cairo_mesh_pattern_begin_patch(mpat);
883
                                        cairo_mesh_pattern_move_to(mpat, e2s.x2(), e2s.y2());
884
                                        cairo_mesh_pattern_line_to(mpat, e2.x2(), e2.y2());
885
                                        cairo_mesh_pattern_line_to(mpat, e3.x2(), e3.y2());
886
                                        cairo_mesh_pattern_line_to(mpat, e3s.x2(), e3s.y2());
25064 jghali 887
                                        qStopColors[offset - 1].getRgbF(&r, &g, &b, &a);
17373 fschmid 888
                                        cairo_mesh_pattern_set_corner_color_rgba(mpat, 0, r, g, b, a);
889
                                        qStopColors[offset].getRgbF(&r, &g, &b, &a);
890
                                        cairo_mesh_pattern_set_corner_color_rgba(mpat, 1, r, g, b, a);
891
                                        cairo_mesh_pattern_set_corner_color_rgba(mpat, 2, r, g, b, a);
25064 jghali 892
                                        qStopColors[offset - 1].getRgbF(&r, &g, &b, &a);
17373 fschmid 893
                                        cairo_mesh_pattern_set_corner_color_rgba(mpat, 3, r, g, b, a);
894
                                        cairo_mesh_pattern_end_patch(mpat);
895
                                        cairo_mesh_pattern_begin_patch(mpat);
896
                                        cairo_mesh_pattern_move_to(mpat, e3s.x2(), e3s.y2());
897
                                        cairo_mesh_pattern_line_to(mpat, e3.x2(), e3.y2());
898
                                        cairo_mesh_pattern_line_to(mpat, e4.x2(), e4.y2());
899
                                        cairo_mesh_pattern_line_to(mpat, e4s.x2(), e4s.y2());
25064 jghali 900
                                        qStopColors[offset - 1].getRgbF(&r, &g, &b, &a);
17373 fschmid 901
                                        cairo_mesh_pattern_set_corner_color_rgba(mpat, 0, r, g, b, a);
902
                                        qStopColors[offset].getRgbF(&r, &g, &b, &a);
903
                                        cairo_mesh_pattern_set_corner_color_rgba(mpat, 1, r, g, b, a);
904
                                        cairo_mesh_pattern_set_corner_color_rgba(mpat, 2, r, g, b, a);
25064 jghali 905
                                        qStopColors[offset - 1].getRgbF(&r, &g, &b, &a);
17373 fschmid 906
                                        cairo_mesh_pattern_set_corner_color_rgba(mpat, 3, r, g, b, a);
907
                                        cairo_mesh_pattern_end_patch(mpat);
908
                                        cairo_mesh_pattern_begin_patch(mpat);
909
                                        cairo_mesh_pattern_move_to(mpat, e4s.x2(), e4s.y2());
910
                                        cairo_mesh_pattern_line_to(mpat, e4.x2(), e4.y2());
911
                                        cairo_mesh_pattern_line_to(mpat, e1.x2(), e1.y2());
912
                                        cairo_mesh_pattern_line_to(mpat, e1s.x2(), e1s.y2());
25064 jghali 913
                                        qStopColors[offset - 1].getRgbF(&r, &g, &b, &a);
17373 fschmid 914
                                        cairo_mesh_pattern_set_corner_color_rgba(mpat, 0, r, g, b, a);
915
                                        qStopColors[offset].getRgbF(&r, &g, &b, &a);
916
                                        cairo_mesh_pattern_set_corner_color_rgba(mpat, 1, r, g, b, a);
917
                                        cairo_mesh_pattern_set_corner_color_rgba(mpat, 2, r, g, b, a);
25064 jghali 918
                                        qStopColors[offset - 1].getRgbF(&r, &g, &b, &a);
17373 fschmid 919
                                        cairo_mesh_pattern_set_corner_color_rgba(mpat, 3, r, g, b, a);
920
                                        cairo_mesh_pattern_end_patch(mpat);
15024 fschmid 921
                                }
17288 jghali 922
                        }
923
                        cairo_pattern_set_filter(mpat, CAIRO_FILTER_GOOD);
924
                        cairo_set_source(cr, mpat);
925
                        cairo_paint_with_alpha(cr, 1.0);
926
                        pat = cairo_pattern_create_for_surface(img);
927
                        cairo_pattern_set_extend(pat, CAIRO_EXTEND_PAD);
928
                        cairo_pattern_set_filter(pat, CAIRO_FILTER_GOOD);
929
                }
930
                else if (fill_gradient.type() == VGradient::mesh)
931
                {
932
                        double p3x = gradPatchP3.x();
933
                        double p3y = gradPatchP3.y();
934
                        img = cairo_surface_create_similar(cairo_get_target(m_cr), CAIRO_CONTENT_COLOR_ALPHA, p3x, p3y);
935
                        cr = cairo_create(img);
936
                        cairo_set_fill_rule(cr, CAIRO_FILL_RULE_EVEN_ODD);
937
                        cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
24114 jghali 938
                        cairo_set_tolerance(cr, 0.5);
24834 jghali 939
                        float r, g, b, a;
17288 jghali 940
                        mpat = cairo_pattern_create_mesh();
941
                        for (int grow = 0; grow < meshGradientArray.count()-1; grow++)
942
                        {
943
                                for (int gcol = 0; gcol < meshGradientArray[grow].count()-1; gcol++)
16729 fschmid 944
                                {
22296 craig 945
                                        MeshPoint mp1 = meshGradientArray[grow][gcol];
25064 jghali 946
                                        MeshPoint mp2 = meshGradientArray[grow][gcol + 1];
947
                                        MeshPoint mp3 = meshGradientArray[grow + 1][gcol + 1];
948
                                        MeshPoint mp4 = meshGradientArray[grow + 1][gcol];
17373 fschmid 949
                                        cairo_mesh_pattern_begin_patch(mpat);
950
                                        cairo_mesh_pattern_move_to(mpat, mp1.gridPoint.x(), mp1.gridPoint.y());
951
                                        cairo_mesh_pattern_curve_to(mpat, mp1.controlRight.x(), mp1.controlRight.y(), mp2.controlLeft.x(), mp2.controlLeft.y(), mp2.gridPoint.x(), mp2.gridPoint.y());
952
                                        cairo_mesh_pattern_curve_to(mpat, mp2.controlBottom.x(), mp2.controlBottom.y(), mp3.controlTop.x(), mp3.controlTop.y(), mp3.gridPoint.x(), mp3.gridPoint.y());
953
                                        cairo_mesh_pattern_curve_to(mpat, mp3.controlLeft.x(), mp3.controlLeft.y(), mp4.controlRight.x(), mp4.controlRight.y(), mp4.gridPoint.x(), mp4.gridPoint.y());
954
                                        cairo_mesh_pattern_curve_to(mpat, mp4.controlTop.x(), mp4.controlTop.y(), mp1.controlBottom.x(), mp1.controlBottom.y(), mp1.gridPoint.x(), mp1.gridPoint.y());
955
                                        cairo_mesh_pattern_set_control_point(mpat, 0, mp1.controlColor.x(),  mp1.controlColor.y());
956
                                        cairo_mesh_pattern_set_control_point(mpat, 1, mp2.controlColor.x(),  mp2.controlColor.y());
957
                                        cairo_mesh_pattern_set_control_point(mpat, 2, mp3.controlColor.x(),  mp3.controlColor.y());
958
                                        cairo_mesh_pattern_set_control_point(mpat, 3, mp4.controlColor.x(),  mp4.controlColor.y());
959
                                        mp1.color.getRgbF(&r, &g, &b, &a);
960
                                        cairo_mesh_pattern_set_corner_color_rgba(mpat, 0, r, g, b, a);
961
                                        mp2.color.getRgbF(&r, &g, &b, &a);
962
                                        cairo_mesh_pattern_set_corner_color_rgba(mpat, 1, r, g, b, a);
963
                                        mp3.color.getRgbF(&r, &g, &b, &a);
964
                                        cairo_mesh_pattern_set_corner_color_rgba(mpat, 2, r, g, b, a);
965
                                        mp4.color.getRgbF(&r, &g, &b, &a);
966
                                        cairo_mesh_pattern_set_corner_color_rgba(mpat, 3, r, g, b, a);
967
                                        cairo_mesh_pattern_end_patch(mpat);
16729 fschmid 968
                                }
17288 jghali 969
                        }
970
                        cairo_pattern_set_filter(mpat, CAIRO_FILTER_BEST);
971
                        cairo_set_source(cr, mpat);
972
                        cairo_paint_with_alpha(cr, 1.0);
973
                        pat = cairo_pattern_create_for_surface(img);
974
                        cairo_pattern_set_extend(pat, CAIRO_EXTEND_NONE);
975
                        cairo_pattern_set_filter(pat, CAIRO_FILTER_BEST);
976
                }
977
                else if (fill_gradient.type() == VGradient::freemesh)
978
                {
979
                        double p3x = gradPatchP3.x();
980
                        double p3y = gradPatchP3.y();
981
                        img = cairo_surface_create_similar(cairo_get_target(m_cr), CAIRO_CONTENT_COLOR_ALPHA, p3x, p3y);
982
                        cr = cairo_create(img);
983
                        cairo_set_fill_rule(cr, CAIRO_FILL_RULE_EVEN_ODD);
984
                        cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
24114 jghali 985
                        cairo_set_tolerance(cr, 0.5);
24834 jghali 986
                        float r, g, b, a;
17288 jghali 987
                        mpat = cairo_pattern_create_mesh();
988
                        for (int col = 0; col < meshGradientPatches.count(); col++)
14952 fschmid 989
                        {
17288 jghali 990
                                meshGradientPatch patch = meshGradientPatches[col];
22296 craig 991
                                MeshPoint mp1 = patch.TL;
992
                                MeshPoint mp2 = patch.TR;
993
                                MeshPoint mp3 = patch.BR;
994
                                MeshPoint mp4 = patch.BL;
17373 fschmid 995
                                cairo_mesh_pattern_begin_patch(mpat);
996
                                cairo_mesh_pattern_move_to(mpat, mp1.gridPoint.x(), mp1.gridPoint.y());
997
                                cairo_mesh_pattern_curve_to(mpat, mp1.controlRight.x(), mp1.controlRight.y(), mp2.controlLeft.x(), mp2.controlLeft.y(), mp2.gridPoint.x(), mp2.gridPoint.y());
998
                                cairo_mesh_pattern_curve_to(mpat, mp2.controlBottom.x(), mp2.controlBottom.y(), mp3.controlTop.x(), mp3.controlTop.y(), mp3.gridPoint.x(), mp3.gridPoint.y());
999
                                cairo_mesh_pattern_curve_to(mpat, mp3.controlLeft.x(), mp3.controlLeft.y(), mp4.controlRight.x(), mp4.controlRight.y(), mp4.gridPoint.x(), mp4.gridPoint.y());
1000
                                cairo_mesh_pattern_curve_to(mpat, mp4.controlTop.x(), mp4.controlTop.y(), mp1.controlBottom.x(), mp1.controlBottom.y(), mp1.gridPoint.x(), mp1.gridPoint.y());
1001
                                cairo_mesh_pattern_set_control_point(mpat, 0, mp1.controlColor.x(),  mp1.controlColor.y());
1002
                                cairo_mesh_pattern_set_control_point(mpat, 1, mp2.controlColor.x(),  mp2.controlColor.y());
1003
                                cairo_mesh_pattern_set_control_point(mpat, 2, mp3.controlColor.x(),  mp3.controlColor.y());
1004
                                cairo_mesh_pattern_set_control_point(mpat, 3, mp4.controlColor.x(),  mp4.controlColor.y());
1005
                                mp1.color.getRgbF(&r, &g, &b, &a);
1006
                                cairo_mesh_pattern_set_corner_color_rgba(mpat, 0, r, g, b, a);
1007
                                mp2.color.getRgbF(&r, &g, &b, &a);
1008
                                cairo_mesh_pattern_set_corner_color_rgba(mpat, 1, r, g, b, a);
1009
                                mp3.color.getRgbF(&r, &g, &b, &a);
1010
                                cairo_mesh_pattern_set_corner_color_rgba(mpat, 2, r, g, b, a);
1011
                                mp4.color.getRgbF(&r, &g, &b, &a);
1012
                                cairo_mesh_pattern_set_corner_color_rgba(mpat, 3, r, g, b, a);
1013
                                cairo_mesh_pattern_end_patch(mpat);
14952 fschmid 1014
                        }
17288 jghali 1015
                        cairo_pattern_set_filter(mpat, CAIRO_FILTER_BEST);
1016
                        cairo_set_source(cr, mpat);
1017
                        cairo_paint_with_alpha(cr, 1.0);
1018
                        pat = cairo_pattern_create_for_surface(img);
1019
                        cairo_pattern_set_extend(pat, CAIRO_EXTEND_NONE);
1020
                        cairo_pattern_set_filter(pat, CAIRO_FILTER_BEST);
3113 fschmid 1021
                }
13013 fschmid 1022
                else
14168 fschmid 1023
                {
15202 jghali 1024
                        bool   isFirst = true;
1025
                        double rampPoint, lastPoint = 0.0;
17288 jghali 1026
                        double x1 = fill_gradient.origin().x();
1027
                        double y1 = fill_gradient.origin().y();
1028
                        double x2 = fill_gradient.vector().x();
1029
                        double y2 = fill_gradient.vector().y();
1030
                        double fx = fill_gradient.focalPoint().x();
1031
                        double fy = fill_gradient.focalPoint().y();
1032
                        if (fill_gradient.type() == VGradient::linear)
14168 fschmid 1033
                                pat = cairo_pattern_create_linear (x1, y1,  x2, y2);
1034
                        else
14278 fschmid 1035
                                pat = cairo_pattern_create_radial (fx, fy, 0, x1, y1, sqrt(pow(x2 - x1, 2) + pow(y2 - y1,2)));
19103 fschmid 1036
                        if (fill_gradient.repeatMethod() == VGradient::none)
1037
                                cairo_pattern_set_extend(pat, CAIRO_EXTEND_NONE);
1038
                        else
1039
                                cairo_pattern_set_extend(pat, CAIRO_EXTEND_PAD);
14952 fschmid 1040
                        cairo_pattern_set_filter(pat, CAIRO_FILTER_GOOD);
17288 jghali 1041
                        QList<VColorStop*> colorStops = fill_gradient.colorStops();
22723 jghali 1042
                        for (int offset = 0 ; offset < colorStops.count() ; offset++)
14168 fschmid 1043
                        {
15202 jghali 1044
                                rampPoint  = colorStops[ offset ]->rampPoint;
1045
                                if ((lastPoint == rampPoint) && (!isFirst))
1046
                                        continue;
1047
                                isFirst = false;
14168 fschmid 1048
                                double a = colorStops[offset]->opacity;
24834 jghali 1049
                                float r, g, b;
18126 fschmid 1050
                                colorStops[ offset ]->color.getRgbF(&r, &g, &b);
17288 jghali 1051
                                cairo_pattern_add_color_stop_rgba (pat, colorStops[ offset ]->rampPoint, r, g, b, a);
15202 jghali 1052
                                lastPoint = rampPoint;
14168 fschmid 1053
                        }
14284 fschmid 1054
                        cairo_matrix_t matrix;
1055
                        QTransform qmatrix;
17288 jghali 1056
                        if (fill_gradient.type() == VGradient::radial)
14284 fschmid 1057
                        {
1058
                                double rotEnd = xy2Deg(x2 - x1, y2 - y1);
1059
                                qmatrix.translate(x1, y1);
1060
                                qmatrix.rotate(rotEnd);
20691 craig 1061
                                qmatrix.shear(m_gradientSkew, 0);
1062
                                qmatrix.translate(0, y1 * (1.0 - m_gradientScale));
14284 fschmid 1063
                                qmatrix.translate(-x1, -y1);
20691 craig 1064
                                qmatrix.scale(1, m_gradientScale);
14284 fschmid 1065
                        }
1066
                        else
1067
                        {
1068
                                qmatrix.translate(x1, y1);
20691 craig 1069
                                qmatrix.shear(-m_gradientSkew, 0);
14284 fschmid 1070
                                qmatrix.translate(-x1, -y1);
1071
                        }
1072
                        cairo_matrix_init(&matrix, qmatrix.m11(), qmatrix.m12(), qmatrix.m21(), qmatrix.m22(), qmatrix.dx(), qmatrix.dy());
1073
                        cairo_matrix_invert(&matrix);
1074
                        cairo_pattern_set_matrix (pat, &matrix);
17288 jghali 1075
                }
1076
                cairo_set_source (m_cr, pat);
1077
                cairo_clip_preserve (m_cr);
20691 craig 1078
                if (m_maskMode > 0)
17288 jghali 1079
                {
1080
                        cairo_pattern_t *patM = getMaskPattern();
1081
                        setRasterOp(m_blendModeFill);
1082
                        cairo_mask(m_cr, patM);
20691 craig 1083
                        if ((m_maskMode == 2) || (m_maskMode == 4) || (m_maskMode == 5) || (m_maskMode == 6))
1084
                                cairo_surface_destroy(m_imageMask);
17288 jghali 1085
                        cairo_pattern_destroy (patM);
14168 fschmid 1086
                }
1087
                else
1088
                {
17288 jghali 1089
                        setRasterOp(m_blendModeFill);
20691 craig 1090
                        cairo_paint_with_alpha (m_cr, m_fill_trans);
14168 fschmid 1091
                }
17288 jghali 1092
                cairo_pattern_destroy (pat);
1093
                if ((fill_gradient.type() == VGradient::fourcolor) || (fill_gradient.type() == VGradient::diamond) || (fill_gradient.type() == VGradient::mesh) || (fill_gradient.type() == VGradient::freemesh))
1094
                {
1095
                        cairo_surface_destroy(img);
1096
                        cairo_pattern_destroy(mpat);
24114 jghali 1097
                        cairo_destroy(cr);
17288 jghali 1098
                }
3113 fschmid 1099
        }
20640 jghali 1100
        else if (m_fillMode == 3)
17288 jghali 1101
        {
1102
                cairo_set_antialias(m_cr, CAIRO_ANTIALIAS_NONE);
25064 jghali 1103
                cairo_surface_t *image2 = cairo_image_surface_create_for_data (m_pattern->getPattern()->bits(), CAIRO_FORMAT_ARGB32, m_pattern->getPattern()->width(), m_pattern->getPattern()->height(), m_pattern->getPattern()->width() * 4);
17288 jghali 1104
                cairo_pattern_t *m_pat = cairo_pattern_create_for_surface(image2);
1105
                cairo_pattern_set_extend(m_pat, CAIRO_EXTEND_REPEAT);
1106
                cairo_pattern_set_filter(m_pat, CAIRO_FILTER_GOOD);
1107
                cairo_matrix_t matrix;
1108
                QTransform qmatrix;
20691 craig 1109
                qmatrix.translate(m_patternOffsetX, m_patternOffsetY);
1110
                qmatrix.rotate(m_patternRotation);
1111
                qmatrix.shear(-m_patternSkewX, m_patternSkewY);
1112
                qmatrix.scale(m_patternScaleX, m_patternScaleY);
17288 jghali 1113
                qmatrix.scale(m_pattern->width / static_cast<double>(m_pattern->getPattern()->width()), m_pattern->height / static_cast<double>(m_pattern->getPattern()->height()));
20691 craig 1114
                if (m_patternMirrorX)
17288 jghali 1115
                        qmatrix.scale(-1, 1);
20691 craig 1116
                if (m_patternMirrorY)
17288 jghali 1117
                        qmatrix.scale(1, -1);
1118
                cairo_matrix_init(&matrix, qmatrix.m11(), qmatrix.m12(), qmatrix.m21(), qmatrix.m22(), qmatrix.dx(), qmatrix.dy());
1119
                cairo_matrix_invert(&matrix);
1120
                cairo_pattern_set_matrix (m_pat, &matrix);
1121
                cairo_set_source (m_cr, m_pat);
1122
                cairo_clip_preserve (m_cr);
20691 craig 1123
                if (m_maskMode > 0)
17288 jghali 1124
                {
1125
                        cairo_pattern_t *patM = getMaskPattern();
1126
                        setRasterOp(m_blendModeFill);
1127
                        cairo_mask(m_cr, patM);
20691 craig 1128
                        if ((m_maskMode == 2) || (m_maskMode == 4) || (m_maskMode == 5) || (m_maskMode == 6))
1129
                                cairo_surface_destroy(m_imageMask);
17288 jghali 1130
                        cairo_pattern_destroy (patM);
1131
                }
1132
                else
1133
                {
1134
                        setRasterOp(m_blendModeFill);
20691 craig 1135
                        cairo_paint_with_alpha (m_cr, m_fill_trans);
17288 jghali 1136
                }
1137
                cairo_pattern_destroy (m_pat);
1138
                cairo_surface_destroy (image2);
1139
                cairo_set_antialias(m_cr, CAIRO_ANTIALIAS_DEFAULT);
1140
        }
20640 jghali 1141
        else if (m_fillMode == 4)
18935 fschmid 1142
        {
1143
                cairo_path_t *path;
1144
                path = cairo_copy_path(m_cr);
1145
                cairo_push_group(m_cr);
20691 craig 1146
                if (m_hatchUseBackground && m_hatchBackground.isValid())
18935 fschmid 1147
                {
24834 jghali 1148
                        float r2, g2, b2;
20691 craig 1149
                        m_hatchBackground.getRgbF(&r2, &g2, &b2);
18935 fschmid 1150
                        cairo_set_source_rgb(m_cr, r2, g2, b2);
1151
                        cairo_fill_preserve(m_cr);
1152
                }
24834 jghali 1153
                float r, g, b;
20691 craig 1154
                m_hatchForeground.getRgbF(&r, &g, &b);
18935 fschmid 1155
                cairo_clip_preserve (m_cr);
24114 jghali 1156
                cairo_set_line_width(m_cr, 1);
18935 fschmid 1157
                cairo_set_source_rgb(m_cr, r, g, b);
20691 craig 1158
                translate(m_hatchWidth / 2.0, m_hatchHeight / 2.0);
1159
                double lineLen = sqrt((m_hatchWidth / 2.0) * (m_hatchWidth / 2.0) + (m_hatchHeight / 2.0) * (m_hatchHeight / 2.0));
18935 fschmid 1160
                double dist = 0.0;
1161
                while (dist < lineLen)
1162
                {
24114 jghali 1163
                        cairo_save(m_cr);
20691 craig 1164
                        rotate(-m_hatchAngle);
18935 fschmid 1165
                        newPath();
1166
                        moveTo(-lineLen, dist);
1167
                        lineTo(lineLen, dist);
24114 jghali 1168
                        cairo_stroke(m_cr);
18935 fschmid 1169
                        if (dist > 0)
1170
                        {
1171
                                newPath();
1172
                                moveTo(-lineLen, -dist);
1173
                                lineTo(lineLen, -dist);
24114 jghali 1174
                                cairo_stroke(m_cr);
18935 fschmid 1175
                        }
24114 jghali 1176
                        cairo_restore(m_cr);
20691 craig 1177
                        if ((m_hatchType == 1) || (m_hatchType == 2))
18935 fschmid 1178
                        {
24114 jghali 1179
                                cairo_save(m_cr);
20691 craig 1180
                                rotate(-m_hatchAngle + 90);
18935 fschmid 1181
                                newPath();
1182
                                moveTo(-lineLen, dist);
1183
                                lineTo(lineLen, dist);
24114 jghali 1184
                                cairo_stroke(m_cr);
18935 fschmid 1185
                                if (dist > 0)
1186
                                {
1187
                                        newPath();
1188
                                        moveTo(-lineLen, -dist);
1189
                                        lineTo(lineLen, -dist);
24114 jghali 1190
                                        cairo_stroke(m_cr);
18935 fschmid 1191
                                }
24114 jghali 1192
                                cairo_restore(m_cr);
18935 fschmid 1193
                        }
20691 craig 1194
                        if (m_hatchType == 2)
18935 fschmid 1195
                        {
24114 jghali 1196
                                cairo_save(m_cr);
20691 craig 1197
                                rotate(-m_hatchAngle + 45);
18935 fschmid 1198
                                double dDist = dist * sqrt(2.0);
1199
                                newPath();
1200
                                moveTo(-lineLen, dDist);
1201
                                lineTo(lineLen, dDist);
24114 jghali 1202
                                cairo_stroke(m_cr);
18935 fschmid 1203
                                if (dist > 0)
1204
                                {
1205
                                        newPath();
1206
                                        moveTo(-lineLen, -dDist);
1207
                                        lineTo(lineLen, -dDist);
24114 jghali 1208
                                        cairo_stroke(m_cr);
18935 fschmid 1209
                                }
24114 jghali 1210
                                cairo_restore(m_cr);
18935 fschmid 1211
                        }
20691 craig 1212
                        dist += m_hatchDistance;
18935 fschmid 1213
                }
1214
                cairo_pop_group_to_source (m_cr);
1215
                setRasterOp(m_blendModeFill);
20691 craig 1216
                if (m_maskMode > 0)
18935 fschmid 1217
                {
1218
                        cairo_pattern_t *patM = getMaskPattern();
1219
                        cairo_pattern_set_filter(patM, CAIRO_FILTER_FAST);
1220
                        cairo_mask(m_cr, patM);
20691 craig 1221
                        if ((m_maskMode == 2) || (m_maskMode == 4) || (m_maskMode == 5) || (m_maskMode == 6))
1222
                                cairo_surface_destroy(m_imageMask);
18935 fschmid 1223
                        cairo_pattern_destroy(patM);
1224
                }
1225
                else
20691 craig 1226
                        cairo_paint_with_alpha (m_cr, m_fill_trans);
18935 fschmid 1227
                newPath();
1228
                cairo_append_path(m_cr, path);
1229
                cairo_path_destroy(path);
1230
        }
24114 jghali 1231
        cairo_restore(m_cr);
14306 fschmid 1232
        cairo_set_operator(m_cr, CAIRO_OPERATOR_OVER);
9319 fschmid 1233
}
68 Franz 1234
 
17288 jghali 1235
void ScPainter::strokePathHelper()
1236
{
24114 jghali 1237
        cairo_save(m_cr);
17288 jghali 1238
        cairo_set_operator(m_cr, CAIRO_OPERATOR_OVER);
22721 jghali 1239
        if (m_LineWidth == 0)
24114 jghali 1240
                cairo_set_line_width(m_cr, 1.0 / m_zoomFactor);
17288 jghali 1241
        else
24114 jghali 1242
                cairo_set_line_width(m_cr, m_LineWidth);
22721 jghali 1243
        if (m_array.count() > 0)
24114 jghali 1244
                cairo_set_dash(m_cr, m_array.data(), m_array.count(), m_offset);
17288 jghali 1245
        else
24114 jghali 1246
                cairo_set_dash(m_cr, nullptr, 0, 0);
17288 jghali 1247
        cairo_set_operator(m_cr, CAIRO_OPERATOR_OVER);
22721 jghali 1248
        if (PLineEnd == Qt::RoundCap)
17288 jghali 1249
                cairo_set_line_cap (m_cr, CAIRO_LINE_CAP_ROUND);
22721 jghali 1250
        else if (PLineEnd == Qt::SquareCap)
17288 jghali 1251
                cairo_set_line_cap (m_cr, CAIRO_LINE_CAP_SQUARE);
24114 jghali 1252
        else if (PLineEnd == Qt::FlatCap)
17288 jghali 1253
                cairo_set_line_cap (m_cr, CAIRO_LINE_CAP_BUTT);
22721 jghali 1254
        if (PLineJoin == Qt::RoundJoin)
24114 jghali 1255
                cairo_set_line_join(m_cr, CAIRO_LINE_JOIN_ROUND);
22721 jghali 1256
        else if (PLineJoin == Qt::BevelJoin)
24114 jghali 1257
                cairo_set_line_join(m_cr, CAIRO_LINE_JOIN_BEVEL);
22721 jghali 1258
        else if (PLineJoin == Qt::MiterJoin)
24114 jghali 1259
                cairo_set_line_join(m_cr, CAIRO_LINE_JOIN_MITER);
20640 jghali 1260
        if (m_strokeMode == 3)
17288 jghali 1261
        {
1262
                cairo_push_group(m_cr);
1263
                cairo_set_antialias(m_cr, CAIRO_ANTIALIAS_NONE);
25064 jghali 1264
                cairo_surface_t *image2 = cairo_image_surface_create_for_data (m_pattern->getPattern()->bits(), CAIRO_FORMAT_ARGB32, m_pattern->getPattern()->width(), m_pattern->getPattern()->height(), m_pattern->getPattern()->width() * 4);
17288 jghali 1265
                cairo_pattern_t *m_pat = cairo_pattern_create_for_surface(image2);
1266
                cairo_pattern_set_extend(m_pat, CAIRO_EXTEND_REPEAT);
1267
                cairo_pattern_set_filter(m_pat, CAIRO_FILTER_GOOD);
1268
                cairo_matrix_t matrix;
1269
                QTransform qmatrix;
20691 craig 1270
                qmatrix.translate(-m_LineWidth / 2.0, -m_LineWidth / 2.0);
1271
                qmatrix.translate(m_patternOffsetX, m_patternOffsetY);
1272
                qmatrix.rotate(m_patternRotation);
1273
                qmatrix.shear(-m_patternSkewX, m_patternSkewY);
1274
                qmatrix.scale(m_patternScaleX, m_patternScaleY);
17288 jghali 1275
                qmatrix.scale(m_pattern->width / static_cast<double>(m_pattern->getPattern()->width()), m_pattern->height / static_cast<double>(m_pattern->getPattern()->height()));
20691 craig 1276
                if (m_patternMirrorX)
17288 jghali 1277
                        qmatrix.scale(-1, 1);
20691 craig 1278
                if (m_patternMirrorY)
17288 jghali 1279
                        qmatrix.scale(1, -1);
1280
                cairo_matrix_init(&matrix, qmatrix.m11(), qmatrix.m12(), qmatrix.m21(), qmatrix.m22(), qmatrix.dx(), qmatrix.dy());
1281
                cairo_matrix_invert(&matrix);
1282
                cairo_pattern_set_matrix (m_pat, &matrix);
1283
                cairo_set_source (m_cr, m_pat);
24114 jghali 1284
                cairo_stroke_preserve(m_cr);
17288 jghali 1285
                cairo_pattern_destroy (m_pat);
1286
                cairo_surface_destroy (image2);
1287
                cairo_set_antialias(m_cr, CAIRO_ANTIALIAS_DEFAULT);
1288
                cairo_pop_group_to_source (m_cr);
1289
                setRasterOp(m_blendModeStroke);
20691 craig 1290
                cairo_paint_with_alpha (m_cr, m_stroke_trans);
17288 jghali 1291
        }
20640 jghali 1292
        else if (m_strokeMode == 2)
17288 jghali 1293
        {
1294
                cairo_push_group(m_cr);
1295
                cairo_pattern_t *pat;
1296
                bool   isFirst = true;
1297
                double rampPoint, lastPoint = 0.0;
1298
                double x1 = stroke_gradient.origin().x();
1299
                double y1 = stroke_gradient.origin().y();
1300
                double x2 = stroke_gradient.vector().x();
1301
                double y2 = stroke_gradient.vector().y();
1302
                double fx = stroke_gradient.focalPoint().x();
1303
                double fy = stroke_gradient.focalPoint().y();
1304
                if (stroke_gradient.type() == VGradient::linear)
1305
                        pat = cairo_pattern_create_linear (x1, y1,  x2, y2);
1306
                else
1307
                        pat = cairo_pattern_create_radial (fx, fy, 0, x1, y1, sqrt(pow(x2 - x1, 2) + pow(y2 - y1,2)));
19103 fschmid 1308
                if (stroke_gradient.repeatMethod() == VGradient::none)
1309
                        cairo_pattern_set_extend(pat, CAIRO_EXTEND_NONE);
1310
                else
1311
                        cairo_pattern_set_extend(pat, CAIRO_EXTEND_PAD);
17288 jghali 1312
                cairo_pattern_set_filter(pat, CAIRO_FILTER_GOOD);
1313
                QList<VColorStop*> colorStops = stroke_gradient.colorStops();
22723 jghali 1314
                for (int offset = 0 ; offset < colorStops.count() ; offset++)
17288 jghali 1315
                {
1316
                        rampPoint  = colorStops[ offset ]->rampPoint;
1317
                        if ((lastPoint == rampPoint) && (!isFirst))
1318
                                continue;
1319
                        isFirst = false;
1320
                        double a = colorStops[offset]->opacity;
24834 jghali 1321
                        float r, g, b;
18126 fschmid 1322
                        colorStops[ offset ]->color.getRgbF(&r, &g, &b);
17288 jghali 1323
                        cairo_pattern_add_color_stop_rgba (pat, rampPoint, r, g, b, a);
1324
                        lastPoint = rampPoint;
1325
                }
1326
                cairo_matrix_t matrix;
1327
                QTransform qmatrix;
1328
                if (stroke_gradient.type() == VGradient::radial)
1329
                {
1330
                        double rotEnd = xy2Deg(x2 - x1, y2 - y1);
1331
                        qmatrix.translate(x1, y1);
1332
                        qmatrix.rotate(rotEnd);
20691 craig 1333
                        qmatrix.shear(m_gradientSkew, 0);
1334
                        qmatrix.translate(0, y1 * (1.0 - m_gradientScale));
17288 jghali 1335
                        qmatrix.translate(-x1, -y1);
20691 craig 1336
                        qmatrix.scale(1, m_gradientScale);
17288 jghali 1337
                }
1338
                else
1339
                {
1340
                        qmatrix.translate(x1, y1);
20691 craig 1341
                        qmatrix.shear(-m_gradientSkew, 0);
17288 jghali 1342
                        qmatrix.translate(-x1, -y1);
1343
                }
1344
                cairo_matrix_init(&matrix, qmatrix.m11(), qmatrix.m12(), qmatrix.m21(), qmatrix.m22(), qmatrix.dx(), qmatrix.dy());
1345
                cairo_matrix_invert(&matrix);
1346
                cairo_pattern_set_matrix (pat, &matrix);
1347
                cairo_set_source (m_cr, pat);
24114 jghali 1348
                cairo_stroke_preserve(m_cr);
17288 jghali 1349
                cairo_pattern_destroy (pat);
1350
                cairo_pop_group_to_source (m_cr);
1351
                setRasterOp(m_blendModeStroke);
20691 craig 1352
                cairo_paint_with_alpha (m_cr, m_stroke_trans);
17288 jghali 1353
        }
1354
        else
1355
        {
24834 jghali 1356
                float r, g, b;
17288 jghali 1357
                m_stroke.getRgbF(&r, &g, &b);
24114 jghali 1358
                cairo_set_source_rgba(m_cr, r, g, b, m_stroke_trans);
17288 jghali 1359
                setRasterOp(m_blendModeStroke);
24114 jghali 1360
                cairo_stroke_preserve(m_cr);
17288 jghali 1361
        }
24114 jghali 1362
        cairo_restore(m_cr);
17288 jghali 1363
        cairo_set_operator(m_cr, CAIRO_OPERATOR_OVER);
1364
}
1365
 
267 Franz 1366
void ScPainter::setClipPath()
1367
{
3113 fschmid 1368
        cairo_clip (m_cr);
267 Franz 1369
}
1370
 
24114 jghali 1371
void ScPainter::drawImage(QImage *image)
68 Franz 1372
{
18116 fschmid 1373
        cairo_set_antialias(m_cr, CAIRO_ANTIALIAS_NONE);
11383 fschmid 1374
/*
24115 jghali 1375
        cairo_surface_t *image3 = cairo_image_surface_create_for_data ((uchar*)image->bits(), CAIRO_FORMAT_ARGB32, image->width(), image->height(), image->width() * 4);
11383 fschmid 1376
        cairo_set_source_surface (m_cr, image3, 0, 0);
1377
        cairo_paint_with_alpha (m_cr, fill_trans);
1378
        cairo_surface_destroy (image3);
1379
*/
6856 fschmid 1380
/* Code with Layers, crashes on cairo_push_group */
7141 fschmid 1381
//      cairo_scale(m_cr, m_zoomFactor, m_zoomFactor);
6312 fschmid 1382
        cairo_push_group(m_cr);
14307 fschmid 1383
        cairo_set_operator(m_cr, CAIRO_OPERATOR_OVER);
3113 fschmid 1384
        cairo_set_fill_rule(m_cr, cairo_get_fill_rule(m_cr));
25064 jghali 1385
        cairo_surface_t *image2  = cairo_image_surface_create_for_data (image->bits(), CAIRO_FORMAT_RGB24, image->width(), image->height(), image->width() * 4);
1386
        cairo_surface_t *image3 = cairo_image_surface_create_for_data (image->bits(), CAIRO_FORMAT_ARGB32, image->width(), image->height(), image->width() * 4);
6312 fschmid 1387
        cairo_set_source_surface (m_cr, image2, 0, 0);
18982 fschmid 1388
        cairo_pattern_set_filter(cairo_get_source(m_cr), CAIRO_FILTER_GOOD);
20424 jghali 1389
        cairo_mask_surface (m_cr, image3, 0, 0);
6312 fschmid 1390
        cairo_surface_destroy (image2);
1391
        cairo_surface_destroy (image3);
1392
        cairo_pop_group_to_source (m_cr);
18982 fschmid 1393
        cairo_pattern_set_filter(cairo_get_source(m_cr), CAIRO_FILTER_GOOD);
14307 fschmid 1394
        setRasterOp(m_blendModeFill);
20691 craig 1395
        if (m_maskMode > 0)
14265 fschmid 1396
        {
14298 fschmid 1397
                cairo_pattern_t *patM = getMaskPattern();
18982 fschmid 1398
                cairo_pattern_set_filter(patM, CAIRO_FILTER_GOOD);
14298 fschmid 1399
                cairo_mask(m_cr, patM);
20691 craig 1400
                if ((m_maskMode == 2) || (m_maskMode == 4) || (m_maskMode == 5) || (m_maskMode == 6))
1401
                        cairo_surface_destroy(m_imageMask);
14298 fschmid 1402
                cairo_pattern_destroy(patM);
14265 fschmid 1403
        }
1404
        else
20691 craig 1405
                cairo_paint_with_alpha (m_cr, m_fill_trans);
14307 fschmid 1406
        cairo_set_operator(m_cr, CAIRO_OPERATOR_OVER);
18116 fschmid 1407
        cairo_set_antialias(m_cr, CAIRO_ANTIALIAS_DEFAULT);
68 Franz 1408
}
1409
 
21586 jghali 1410
void ScPainter::setupPolygon(const FPointArray *points, bool closed)
68 Franz 1411
{
1412
        bool nPath = true;
11004 fschmid 1413
        bool first = true;
16763 fschmid 1414
        FPoint np, np1, np2, np3, np4, firstP;
17369 jghali 1415
 
1416
        if (points->size() <= 3)
1417
                return;
1418
 
1419
        newPath();
23337 jghali 1420
        for (int poi = 0; poi < points->size() - 3; poi += 4)
3113 fschmid 1421
        {
18801 fschmid 1422
                if (points->isMarker(poi))
68 Franz 1423
                {
17369 jghali 1424
                        nPath = true;
1425
                        continue;
1426
                }
1427
                if (nPath)
1428
                {
3113 fschmid 1429
                        np = points->point(poi);
17369 jghali 1430
                        if ((!first) && (closed) && (np4 == firstP))
24114 jghali 1431
                                cairo_close_path(m_cr);
1432
                        cairo_move_to(m_cr, np.x(), np.y());
17369 jghali 1433
                        first = nPath = false;
1434
                        firstP = np4 = np;
1435
                }
1436
                np  = points->point(poi);
1437
                np1 = points->point(poi + 1);
1438
                np2 = points->point(poi + 3);
1439
                np3 = points->point(poi + 2);
1440
                if (np4 == np3)
1441
                        continue;
1442
                if ((np == np1) && (np2 == np3))
24114 jghali 1443
                        cairo_line_to(m_cr, np3.x(), np3.y());
17369 jghali 1444
                else
1445
                        cairo_curve_to(m_cr, np1.x(), np1.y(), np2.x(), np2.y(), np3.x(), np3.y());
1446
                np4 = np3;
3113 fschmid 1447
        }
17369 jghali 1448
        if (closed)
24114 jghali 1449
                cairo_close_path(m_cr);
638 fschmid 1450
}
1451
 
21586 jghali 1452
void ScPainter::setupSharpPolygon(const FPointArray *points, bool closed)
17790 fschmid 1453
{
1454
        bool nPath = true;
1455
        bool first = true;
1456
        FPoint np, np1, np2, np3, np4, firstP;
1457
 
1458
        if (points->size() <= 3)
1459
                return;
1460
 
1461
        newPath();
23337 jghali 1462
        for (int poi = 0; poi < points->size() - 3; poi += 4)
17790 fschmid 1463
        {
18801 fschmid 1464
                if (points->isMarker(poi))
17790 fschmid 1465
                {
1466
                        nPath = true;
1467
                        continue;
1468
                }
1469
                if (nPath)
1470
                {
1471
                        np = points->point(poi);
1472
                        if ((!first) && (closed) && (np4 == firstP))
24114 jghali 1473
                                cairo_close_path(m_cr);
17790 fschmid 1474
                        sharpLineHelper(np);
24114 jghali 1475
                        cairo_move_to(m_cr, np.x(), np.y());
17790 fschmid 1476
                        first = nPath = false;
1477
                        firstP = np4 = np;
1478
                }
1479
                np  = points->point(poi);
1480
                np1 = points->point(poi + 1);
1481
                np2 = points->point(poi + 3);
1482
                np3 = points->point(poi + 2);
1483
                if (np4 == np3)
1484
                        continue;
1485
                if ((np == np1) && (np2 == np3))
1486
                {
1487
                        sharpLineHelper(np3);
24114 jghali 1488
                        cairo_line_to(m_cr, np3.x(), np3.y());
17790 fschmid 1489
                }
1490
                else
1491
                        cairo_curve_to(m_cr, np1.x(), np1.y(), np2.x(), np2.y(), np3.x(), np3.y());
1492
                np4 = np3;
1493
        }
1494
        if (closed)
24114 jghali 1495
                cairo_close_path(m_cr);
17790 fschmid 1496
}
1497
 
1498
void ScPainter::sharpLineHelper(FPoint &pp)
1499
{
1500
        double x1 = pp.x();
1501
        double y1 = pp.y();
1502
        cairo_user_to_device (m_cr, &x1, &y1);
1503
        x1 = floor(x1) + 0.5;
1504
        y1 = floor(y1) + 0.5;
1505
        cairo_device_to_user (m_cr, &x1, &y1);
1506
        pp.setXY(x1, y1);
1507
}
1508
 
1509
void ScPainter::sharpLineHelper(QPointF &pp)
1510
{
1511
        double x1 = pp.x();
1512
        double y1 = pp.y();
1513
        cairo_user_to_device (m_cr, &x1, &y1);
1514
        x1 = floor(x1) + 0.5;
1515
        y1 = floor(y1) + 0.5;
1516
        cairo_device_to_user (m_cr, &x1, &y1);
1517
        pp.setX(x1);
1518
        pp.setY(y1);
1519
}
1520
 
68 Franz 1521
void ScPainter::drawPolygon()
1522
{
1523
        fillPath();
1524
}
1525
 
1526
void ScPainter::drawPolyLine()
1527
{
1528
        strokePath();
1529
}
1530
 
22635 craig 1531
void ScPainter::drawLine(const FPoint& start, const FPoint& end)
68 Franz 1532
{
1533
        newPath();
1534
        moveTo(start.x(), start.y());
1535
        lineTo(end.x(), end.y());
1536
        strokePath();
1537
}
1538
 
16856 craig 1539
void ScPainter::drawLine(const QPointF& start, const QPointF& end)
1540
{
1541
        newPath();
1542
        moveTo(start.x(), start.y());
1543
        lineTo(end.x(), end.y());
1544
        strokePath();
1545
}
1546
 
17790 fschmid 1547
void ScPainter::drawSharpLine(FPoint start, FPoint end)
1548
{
1549
        newPath();
1550
        sharpLineHelper(start);
1551
        sharpLineHelper(end);
1552
        moveTo(start.x(), start.y());
1553
        lineTo(end.x(), end.y());
1554
        strokePath();
1555
}
1556
 
1557
void ScPainter::drawSharpLine(QPointF start, QPointF end)
1558
{
1559
        newPath();
1560
        sharpLineHelper(start);
1561
        sharpLineHelper(end);
1562
        moveTo(start.x(), start.y());
1563
        lineTo(end.x(), end.y());
1564
        strokePath();
1565
}
1566
 
68 Franz 1567
void ScPainter::drawRect(double x, double y, double w, double h)
1568
{
1569
        newPath();
12957 fschmid 1570
        cairo_rectangle(m_cr, x, y, w, h);
68 Franz 1571
        fillPath();
1572
        strokePath();
1573
}
12957 fschmid 1574
 
17790 fschmid 1575
void ScPainter::drawSharpRect(double x, double y, double w, double h)
1576
{
1577
        newPath();
1578
        double x1 = x;
1579
        double y1 = y;
1580
        double w1 = w;
1581
        double h1 = h;
1582
        // see http://www.cairographics.org/FAQ/#sharp_lines
1583
        cairo_user_to_device (m_cr, &x1, &y1);
1584
        cairo_user_to_device (m_cr, &w1, &h1);
1585
        x1 = floor(x1) + 0.5;
1586
        y1 = floor(y1) + 0.5;
1587
        w1 = floor(w1) + 0.5;
1588
        h1 = floor(h1) + 0.5;
1589
        cairo_device_to_user (m_cr, &x1, &y1);
1590
        cairo_device_to_user (m_cr, &w1, &h1);
1591
        cairo_rectangle(m_cr, x1, y1, w1, h1);
1592
        fillPath();
1593
        strokePath();
1594
}
1595
 
24713 jghali 1596
void ScPainter::drawText(const QRectF& area, const QString& text, bool filled, int align)
12957 fschmid 1597
{
1598
        cairo_text_extents_t extents;
12959 fschmid 1599
        cairo_font_extents_t extentsF;
17788 fschmid 1600
        double x;
1601
        if (align == 0)
1602
                x = area.center().x();
1603
        else
1604
                x = area.x();
1605
        double y = area.y();
12959 fschmid 1606
        double ww = 0;
1607
        double hh = 0;
24834 jghali 1608
        float r, g, b;
21563 jghali 1609
 
1610
        assert(!m_font.isNone());
1611
 
1612
#if CAIRO_HAS_FC_FONT
22519 craig 1613
        FcPattern *pattern = FcPatternBuild(nullptr,
21563 jghali 1614
                                                                                FC_FILE, FcTypeString, QFile::encodeName(m_font.fontFilePath()).data(),
1615
                                                                                FC_INDEX, FcTypeInteger, m_font.faceIndex(),
22519 craig 1616
                                                                                nullptr);
21563 jghali 1617
        cairo_font_face_t *cairo_face = cairo_ft_font_face_create_for_pattern(pattern);
1618
        FcPatternDestroy(pattern);
1619
 
1620
        cairo_set_font_face (m_cr, cairo_face);
1621
        cairo_set_font_size(m_cr, m_fontSize);
1622
 
1623
        cairo_font_options_t* options = cairo_font_options_create();
1624
        cairo_font_options_set_hint_style(options, CAIRO_HINT_STYLE_SLIGHT);
1625
        cairo_set_font_options(m_cr, options);
1626
        cairo_font_options_destroy(options);
1627
 
12959 fschmid 1628
        cairo_font_extents (m_cr, &extentsF);
1629
        QStringList textList = text.split("\n");
1630
        for (int a = 0; a < textList.count(); ++a)
1631
        {
1632
                cairo_text_extents (m_cr, textList[a].toUtf8(), &extents);
17788 fschmid 1633
                if (align == 0)
1634
                        x = qMin(area.center().x() - (extents.width / 2.0 + extents.x_bearing), x);
12959 fschmid 1635
                ww = qMax(ww, extents.width);
1636
        }
1637
        hh = extentsF.height * textList.count();
17788 fschmid 1638
        if ((align == 0) || (align == 1))
1639
                y = area.center().y() - ((extentsF.height * textList.count()) / 2.0);
1640
        if (filled)
1641
        {
1642
                m_fill.getRgbF(&r, &g, &b);
24114 jghali 1643
                cairo_set_source_rgba(m_cr, r, g, b, m_fill_trans);
1644
                cairo_new_path(m_cr);
17788 fschmid 1645
                cairo_rectangle(m_cr, x, y, ww, hh);
24114 jghali 1646
                cairo_fill(m_cr);
17788 fschmid 1647
        }
24114 jghali 1648
        cairo_new_path(m_cr);
12959 fschmid 1649
        y += extentsF.ascent;
12957 fschmid 1650
        cairo_move_to (m_cr, x, y);
1651
        m_stroke.getRgbF(&r, &g, &b);
24114 jghali 1652
        cairo_set_source_rgba(m_cr, r, g, b, m_stroke_trans);
21563 jghali 1653
 
1654
        QVector<cairo_glyph_t> cairoGlyphs;
1655
 
12959 fschmid 1656
        for (int a = 0; a < textList.count(); ++a)
1657
        {
21563 jghali 1658
                CharStyle style(m_font, m_fontSize * 10);
1659
                StoryText story;
1660
                story.insertChars(textList[a]);
25157 craig 1661
                story.setCharStyle(0, textList[a].size(), style);
21563 jghali 1662
 
1663
                TextShaper textShaper(story, 0);
22508 jghali 1664
                const QList<GlyphCluster> glyphRuns = textShaper.shape(0, story.length()).glyphs();
21563 jghali 1665
 
1666
                double tmpx = x;
22508 jghali 1667
                for (const GlyphCluster &run : glyphRuns)
21563 jghali 1668
                {
22508 jghali 1669
                        for (const GlyphLayout &gl : run.glyphs())
21563 jghali 1670
                        {
1671
                                cairo_glyph_t glyph;
1672
                                glyph.index = gl.glyph;
1673
                                glyph.x = tmpx + gl.xoffset;
1674
                                glyph.y = y - gl.yoffset;
1675
                                tmpx += gl.xadvance;
1676
                                cairoGlyphs.append(glyph);
1677
                        }
1678
                }
1679
                y += extentsF.height;
1680
        }
1681
 
1682
        cairo_show_glyphs(m_cr, cairoGlyphs.data(), cairoGlyphs.count());
1683
#else
1684
        cairo_select_font_face(m_cr, m_font.family().toLatin1(), m_font.isItalic() ? CAIRO_FONT_SLANT_ITALIC : CAIRO_FONT_SLANT_NORMAL, m_font.isBold() ? CAIRO_FONT_WEIGHT_BOLD : CAIRO_FONT_WEIGHT_NORMAL);
1685
        cairo_set_font_size(m_cr, m_fontSize);
1686
        cairo_font_extents (m_cr, &extentsF);
1687
        QStringList textList = text.split("\n");
1688
        for (int a = 0; a < textList.count(); ++a)
1689
        {
1690
                cairo_text_extents (m_cr, textList[a].toUtf8(), &extents);
1691
                if (align == 0)
1692
                        x = qMin(area.center().x() - (extents.width / 2.0 + extents.x_bearing), x);
1693
                ww = qMax(ww, extents.width);
1694
        }
1695
        hh = extentsF.height * textList.count();
1696
        if ((align == 0) || (align == 1))
1697
                y = area.center().y() - ((extentsF.height * textList.count()) / 2.0);
1698
        if (filled)
1699
        {
1700
                m_fill.getRgbF(&r, &g, &b);
24114 jghali 1701
                cairo_set_source_rgba(m_cr, r, g, b, m_fill_trans);
1702
                cairo_new_path(m_cr);
21563 jghali 1703
                cairo_rectangle(m_cr, x, y, ww, hh);
24114 jghali 1704
                cairo_fill(m_cr);
21563 jghali 1705
        }
24114 jghali 1706
        cairo_new_path(m_cr);
21563 jghali 1707
        y += extentsF.ascent;
1708
        cairo_move_to (m_cr, x, y);
1709
        m_stroke.getRgbF(&r, &g, &b);
24114 jghali 1710
        cairo_set_source_rgba(m_cr, r, g, b, m_stroke_trans);
21563 jghali 1711
        for (int a = 0; a < textList.count(); ++a)
1712
        {
12959 fschmid 1713
                cairo_show_text (m_cr, textList[a].toUtf8());
1714
                y += extentsF.height;
1715
                cairo_move_to (m_cr, x, y);
1716
        }
21563 jghali 1717
#endif
12957 fschmid 1718
}
17788 fschmid 1719
 
22635 craig 1720
void ScPainter::drawShadeCircle(const QRectF &re, const QColor& color, bool sunken, int lineWidth)
17788 fschmid 1721
{
24527 jghali 1722
        setStrokeMode(ScPainter::Solid);
17963 fschmid 1723
        double bezierCircle = 0.55228475;
1724
        double dx = re.width();
1725
        double dy = re.height();
1726
        double cx = dx / 2.0;
1727
        double cy = dy / 2.0;
1728
        double rb = 0.5 * (dx < dy ? dx : dy);
1729
        double r = rb - 0.25 * lineWidth;
1730
        QColor shade;
1731
        shade.setRgbF(color.redF() * 0.5, color.greenF() * 0.5, color.blueF() * 0.5);
1732
        QColor light;
1733
        light.setRgbF(color.redF() * 0.5 + 0.5, color.greenF() * 0.5 + 0.5, color.blueF() * 0.5 + 0.5);
1734
        cairo_save(m_cr);
1735
        translate(0, dy);
1736
        scale(1, -1);
1737
        setPen(color, lineWidth * 0.5, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin);
1738
        newPath();
1739
        moveTo(cx + r, cy);
1740
        cairo_curve_to(m_cr, cx + r, cy + bezierCircle * r, cx + bezierCircle * r, cy + r, cx, cy + r);
1741
        cairo_curve_to(m_cr, cx - bezierCircle * r, cy + r, cx - r, cy + bezierCircle * r, cx - r, cy);
1742
        cairo_curve_to(m_cr, cx - r, cy - bezierCircle * r, cx - bezierCircle * r, cy - r, cx, cy - r);
1743
        cairo_curve_to(m_cr, cx + bezierCircle * r, cy - r, cx + r, cy - bezierCircle * r, cx + r, cy);
1744
        strokePath();
1745
        r = rb - 0.73 * lineWidth;
1746
        double r2 = r / 1.414213562;
1747
        if (sunken)
1748
                setPen(shade, lineWidth * 0.5, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin);
1749
        else
1750
                setPen(light, lineWidth * 0.5, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin);
1751
        newPath();
1752
        moveTo(cx + r2, cy + r2);
1753
        cairo_curve_to(m_cr, cx + (1 - bezierCircle) * r2, cy + (1 + bezierCircle) * r2, cx - (1 - bezierCircle) * r2, cy + (1 + bezierCircle) * r2, cx - r2, cy + r2);
1754
        cairo_curve_to(m_cr, cx - (1 + bezierCircle) * r2, cy + (1 - bezierCircle) * r2, cx - (1 + bezierCircle) * r2, cy - (1 - bezierCircle) * r2, cx - r2, cy - r2);
1755
        strokePath();
1756
        if (sunken)
1757
                setPen(light, lineWidth * 0.5, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin);
1758
        else
1759
                setPen(shade, lineWidth * 0.5, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin);
1760
        newPath();
1761
        moveTo(cx - r2, cy - r2);
1762
        cairo_curve_to(m_cr, cx - (1 - bezierCircle) * r2, cy - (1 + bezierCircle) * r2, cx + (1 - bezierCircle) * r2, cy - (1 + bezierCircle) * r2, cx + r2, cy - r2);
1763
        cairo_curve_to(m_cr, cx + (1 + bezierCircle) * r2, cy - (1 - bezierCircle) * r2, cx + (1 + bezierCircle) * r2, cy + (1 - bezierCircle) * r2, cx + r2, cy + r2);
1764
        strokePath();
24114 jghali 1765
        cairo_restore(m_cr);
17963 fschmid 1766
}
1767
 
22635 craig 1768
void ScPainter::drawShadePanel(const QRectF &r, const QColor& color, bool sunken, int lineWidth)
17963 fschmid 1769
{
1770
        QColor shade;
1771
        QColor light;
1772
        if (sunken)
1773
        {
1774
                shade.setRgbF(color.redF() * 0.5, color.greenF() * 0.5, color.blueF() * 0.5);
1775
                light.setRgbF(color.redF() * 0.5 + 0.5, color.greenF() * 0.5 + 0.5, color.blueF() * 0.5 + 0.5);
1776
        }
1777
        else
1778
        {
1779
                light.setRgbF(color.redF() * 0.5, color.greenF() * 0.5, color.blueF() * 0.5);
1780
                shade.setRgbF(color.redF() * 0.5 + 0.5, color.greenF() * 0.5 + 0.5, color.blueF() * 0.5 + 0.5);
1781
        }
1782
        double x1, y1, y2, x3;
1783
        x1 = r.x();
1784
        x3 = r.x() + r.width();
1785
        y1 = r.y() + r.height();
1786
        y2 = r.y();
1787
        setFillMode(ScPainter::Solid);
1788
        newPath();
1789
        moveTo(x1, y1);
1790
        lineTo(x1, y2);
1791
        lineTo(x3, y2);
1792
        lineTo(x3 - lineWidth, lineWidth);
1793
        lineTo(lineWidth, lineWidth);
1794
        lineTo(lineWidth, y1 - lineWidth);
1795
        closePath();
1796
        setBrush(shade);
1797
        fillPath();
1798
        newPath();
1799
        moveTo(x1, y1);
1800
        lineTo(x3, y1);
1801
        lineTo(x3, y2);
1802
        lineTo(x3 - lineWidth, lineWidth);
1803
        lineTo(x3 - lineWidth, y1 - lineWidth);
1804
        lineTo(lineWidth, y1 - lineWidth);
1805
        closePath();
1806
        setBrush(light);
1807
        fillPath();
18772 fschmid 1808
}
17963 fschmid 1809
 
22746 jghali 1810
void ScPainter::drawUnderlinedRect(const QRectF &r, const QColor& color, int lineWidth)
1811
{
1812
        setPen(color, lineWidth, Qt::DashLine, Qt::FlatCap, Qt::MiterJoin);
1813
        setStrokeMode(ScPainter::Solid);
1814
        drawLine(r.bottomLeft(), r.topLeft());
1815
        drawLine(r.topLeft(), r.topRight());
1816
        drawLine(r.bottomRight(), r.topRight());
1817
 
1818
        setPen(color, lineWidth, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin);
1819
        drawLine(r.bottomLeft(), r.bottomRight());
1820
}
1821
 
22635 craig 1822
void ScPainter::colorizeAlpha(const QColor& color)
20111 fschmid 1823
{
1824
        cairo_surface_t *data = cairo_get_group_target(m_cr);
1825
        cairo_surface_flush(data);
1826
        int w   = cairo_image_surface_get_width(data);
1827
        int h   = cairo_image_surface_get_height(data);
1828
        int stride = cairo_image_surface_get_stride(data);
1829
        unsigned char *d = cairo_image_surface_get_data(data);
1830
        int cr = color.red();
1831
        int cg = color.green();
1832
        int cb = color.blue();
22723 jghali 1833
        for (int y = 0; y < h; ++y)
20111 fschmid 1834
        {
1835
                QRgb *dst = (QRgb*)d;
22723 jghali 1836
                for (int x = 0; x < w; ++x)
20111 fschmid 1837
                {
1838
                        if (qAlpha(*dst) > 0)
1839
                                *dst = qRgba(cr, cg, cb, qAlpha(*dst));
1840
                        dst++;
1841
                }
1842
                d += stride;
1843
        }
1844
        cairo_surface_mark_dirty(data);
1845
}
1846
 
22635 craig 1847
void ScPainter::colorize(const QColor& color)
20111 fschmid 1848
{
1849
        cairo_surface_t *data = cairo_get_group_target(m_cr);
1850
        cairo_surface_flush(data);
1851
        int w   = cairo_image_surface_get_width(data);
1852
        int h   = cairo_image_surface_get_height(data);
1853
        int stride = cairo_image_surface_get_stride(data);
1854
        unsigned char *d = cairo_image_surface_get_data(data);
1855
        int cr = color.red();
1856
        int cg = color.green();
1857
        int cb = color.blue();
1858
        int hu, sa, v;
1859
        int cc2, cm2, cy2, k2;
1860
        QColor tmpR;
22723 jghali 1861
        for (int y = 0; y < h; ++y)
20111 fschmid 1862
        {
1863
                QRgb *dst = (QRgb*)d;
22723 jghali 1864
                for (int x = 0; x < w; ++x)
20111 fschmid 1865
                {
1866
                        if (qAlpha(*dst) > 0)
1867
                        {
1868
                                k2 = 255 - qMin(qRound(0.3 * qRed(*dst) + 0.59 * qGreen(*dst) + 0.11 * qBlue(*dst)), 255);
1869
                                tmpR.setRgb(cr, cg, cb);
1870
                                tmpR.getHsv(&hu, &sa, &v);
1871
                                tmpR.setHsv(hu, sa * k2 / 255, 255 - ((255 - v) * k2 / 255));
1872
                                tmpR.getRgb(&cc2, &cm2, &cy2);
1873
                                *dst = qRgba(cc2, cm2, cy2, qAlpha(*dst));
1874
                        }
1875
                        dst++;
1876
                }
1877
                d += stride;
1878
        }
1879
        cairo_surface_mark_dirty(data);
1880
}
1881
 
18772 fschmid 1882
void ScPainter::blurAlpha(int radius)
1883
{
1884
        if (radius < 1)
1885
                return;
1886
        cairo_surface_t *data = cairo_get_group_target(m_cr);
1887
        QRgb *pix = (QRgb*)cairo_image_surface_get_data(data);
1888
        int w   = cairo_image_surface_get_width(data);
1889
        int h   = cairo_image_surface_get_height(data);
25064 jghali 1890
        int wm  = w - 1;
1891
        int hm  = h - 1;
1892
        int wh  = w * h;
18772 fschmid 1893
        int div = radius+radius+1;
1894
        int *a = new int[wh];
1895
        int asum, x, y, i, yp, yi, yw;
1896
        QRgb p;
25064 jghali 1897
        int *vmin = new int[qMax(w, h)];
1898
        int divsum = (div + 1)>>1;
18772 fschmid 1899
        divsum *= divsum;
24713 jghali 1900
        int *dv = new int[256 * (size_t) divsum];
23337 jghali 1901
        for (i = 0; i < 256 * divsum; ++i)
17788 fschmid 1902
        {
23337 jghali 1903
                dv[i] = (i / divsum);
17788 fschmid 1904
        }
18772 fschmid 1905
        yw = yi = 0;
1906
        int **stack = new int*[div];
22723 jghali 1907
        for (int i = 0; i < div; ++i)
17788 fschmid 1908
        {
18772 fschmid 1909
                stack[i] = new int[1];
1910
        }
1911
        int stackpointer;
1912
        int stackstart;
1913
        int *sir;
1914
        int rbs;
1915
        int r1 = radius+1;
1916
        int aoutsum;
1917
        int ainsum;
1918
        for (y = 0; y < h; ++y)
1919
        {
1920
                ainsum = aoutsum = asum = 0;
22723 jghali 1921
                for (i = -radius; i <= radius; ++i)
18772 fschmid 1922
                {
25064 jghali 1923
                        p = pix[yi + qMin(wm, qMax(i, 0))];
1924
                        sir = stack[i + radius];
18772 fschmid 1925
                        sir[0] = qAlpha(p);
25064 jghali 1926
                        rbs = r1 - abs(i);
1927
                        asum += sir[0] * rbs;
18772 fschmid 1928
                        if (i > 0)
1929
                                ainsum += sir[0];
1930
                        else
1931
                                aoutsum += sir[0];
1932
                }
1933
                stackpointer = radius;
23337 jghali 1934
                for (x = 0; x < w; ++x)
18772 fschmid 1935
                {
1936
                        a[yi] = dv[asum];
1937
                        asum -= aoutsum;
25064 jghali 1938
                        stackstart = stackpointer - radius + div;
23337 jghali 1939
                        sir = stack[stackstart % div];
18772 fschmid 1940
                        aoutsum -= sir[0];
1941
                        if (y == 0)
23337 jghali 1942
                                vmin[x] = qMin(x + radius + 1, wm);
1943
                        p = pix[yw + vmin[x]];
18772 fschmid 1944
                        sir[0] = qAlpha(p);
1945
                        ainsum += sir[0];
1946
                        asum += ainsum;
23337 jghali 1947
                        stackpointer = (stackpointer + 1) % div;
24713 jghali 1948
                        sir = stack[stackpointer % div];
18772 fschmid 1949
                        aoutsum += sir[0];
1950
                        ainsum -= sir[0];
1951
                        ++yi;
1952
                }
1953
                yw += w;
1954
        }
23337 jghali 1955
        for (x = 0; x < w; ++x)
18772 fschmid 1956
        {
1957
                ainsum = aoutsum = asum = 0;
19596 jghali 1958
                yp = -radius * w;
22723 jghali 1959
                for (i = -radius; i <= radius; ++i)
18772 fschmid 1960
                {
23337 jghali 1961
                        yi = qMax(0, yp) + x;
1962
                        sir = stack[i + radius];
18772 fschmid 1963
                        sir[0] = a[yi];
23337 jghali 1964
                        rbs = r1 - abs(i);
1965
                        asum += a[yi] * rbs;
18772 fschmid 1966
                        if (i > 0)
1967
                                ainsum += sir[0];
1968
                        else
1969
                                aoutsum += sir[0];
1970
                        if (i < hm)
1971
                        {
1972
                                yp += w;
1973
                        }
1974
                }
1975
                yi = x;
1976
                stackpointer = radius;
23337 jghali 1977
                for (y = 0; y < h; ++y)
18772 fschmid 1978
                {
1979
                        pix[yi] = qRgba(qRed(pix[yi]), qGreen(pix[yi]), qBlue(pix[yi]), dv[asum]);
1980
                        asum -= aoutsum;
23337 jghali 1981
                        stackstart = stackpointer - radius + div;
18772 fschmid 1982
                        sir = stack[stackstart%div];
1983
                        aoutsum -= sir[0];
23337 jghali 1984
                        if (x == 0)
18772 fschmid 1985
                        {
23337 jghali 1986
                                vmin[y] = qMin(y + r1, hm) * w;
18772 fschmid 1987
                        }
23337 jghali 1988
                        p = x + vmin[y];
18772 fschmid 1989
                        sir[0] = a[p];
1990
                        ainsum += sir[0];
1991
                        asum += ainsum;
1992
                        stackpointer = (stackpointer+1)%div;
1993
                        sir = stack[stackpointer];
1994
                        aoutsum += sir[0];
1995
                        ainsum -= sir[0];
1996
                        yi += w;
1997
                }
1998
        }
1999
        delete [] a;
2000
        delete [] vmin;
2001
        delete [] dv;
22723 jghali 2002
        for (int i = 0; i < div; ++i)
18772 fschmid 2003
        {
2004
                delete [] stack[i];
2005
        }
2006
        delete [] stack;
2007
        cairo_surface_mark_dirty(data);
17788 fschmid 2008
}
18772 fschmid 2009
 
2010
void ScPainter::blur(int radius)
2011
{
2012
        if (radius < 1)
2013
                return;
2014
        cairo_surface_t *data = cairo_get_group_target(m_cr);
24713 jghali 2015
        QRgb *pix = (QRgb*) cairo_image_surface_get_data(data);
18772 fschmid 2016
        int w   = cairo_image_surface_get_width(data);
2017
        int h   = cairo_image_surface_get_height(data);
24713 jghali 2018
        int wm  = w - 1;
2019
        int hm  = h - 1;
2020
        int wh  = w * h;
2021
        int div = radius + radius + 1;
18772 fschmid 2022
        int *r = new int[wh];
2023
        int *g = new int[wh];
2024
        int *b = new int[wh];
2025
        int *a = new int[wh];
2026
        int rsum, gsum, bsum, asum, x, y, i, yp, yi, yw;
2027
        QRgb p;
24713 jghali 2028
        int *vmin = new int[qMax(w, h)];
18772 fschmid 2029
        int divsum = (div+1)>>1;
2030
        divsum *= divsum;
24713 jghali 2031
        int *dv = new int[256 * (size_t) divsum];
23337 jghali 2032
        for (i = 0; i < 256 * divsum; ++i)
18772 fschmid 2033
        {
23337 jghali 2034
                dv[i] = (i / divsum);
18772 fschmid 2035
        }
2036
        yw = yi = 0;
2037
        int **stack = new int*[div];
22723 jghali 2038
        for (int i = 0; i < div; ++i)
18772 fschmid 2039
        {
2040
                stack[i] = new int[4];
2041
        }
2042
        int stackpointer;
2043
        int stackstart;
2044
        int *sir;
2045
        int rbs;
2046
        int r1 = radius+1;
2047
        int routsum, goutsum, boutsum, aoutsum;
2048
        int rinsum, ginsum, binsum, ainsum;
2049
        for (y = 0; y < h; ++y)
2050
        {
2051
                rinsum = ginsum = binsum = ainsum = routsum = goutsum = boutsum = aoutsum = rsum = gsum = bsum = asum = 0;
22723 jghali 2052
                for (i = -radius; i <= radius; ++i)
18772 fschmid 2053
                {
23337 jghali 2054
                        p = pix[yi + qMin(wm, qMax(i, 0))];
2055
                        sir = stack[i + radius];
18772 fschmid 2056
                        sir[0] = qRed(p);
2057
                        sir[1] = qGreen(p);
2058
                        sir[2] = qBlue(p);
2059
                        sir[3] = qAlpha(p);
23337 jghali 2060
                        rbs = r1 - abs(i);
2061
                        rsum += sir[0] * rbs;
2062
                        gsum += sir[1] * rbs;
2063
                        bsum += sir[2] * rbs;
2064
                        asum += sir[3] * rbs;
18772 fschmid 2065
                        if (i > 0)
2066
                        {
2067
                                rinsum += sir[0];
2068
                                ginsum += sir[1];
2069
                                binsum += sir[2];
2070
                                ainsum += sir[3];
2071
                        }
2072
                        else
2073
                        {
2074
                                routsum += sir[0];
2075
                                goutsum += sir[1];
2076
                                boutsum += sir[2];
2077
                                aoutsum += sir[3];
2078
                        }
2079
                }
2080
                stackpointer = radius;
23337 jghali 2081
                for (x = 0; x < w; ++x)