Rev 18114 |
Rev 20630 |
Go to most recent revision |
Blame |
Compare with Previous |
Last modification |
View Log
| RSS feed
/*
For general Scribus (>=1.3.2) copyright and licensing information please refer
to the COPYING file provided with the program. Following this notice may exist
a copyright and/or license notice that predates the release of Scribus 1.3.2
for which a new license (GPL+exception) is in place.
*/
#include "scpainterex_cairo.h"
#include "sccolorengine.h"
#include "util.h"
#include "util_math.h"
ScPainterEx_Cairo::ScPainterEx_Cairo( cairo_t* context, QRect& rect, ScribusDoc* doc, bool gray ) : ScPainterExBase()
{
m_doc = doc;
m_width = rect.width();
m_height = rect.height();
m_blendModeLayer = 0;
m_blendModeFill = 0;
m_blendModeStroke = 0;
m_strokeColor = ScColorShade( QColor(0,0,0), 100 );
m_fillColor = ScColorShade( QColor(0,0,0), 100 );
m_fillTrans = 1.0;
m_strokeTrans = 1.0;
m_fillRule = true;
m_fillMode = 1;
m_lineWidth = 1.0;
m_offset = 0;
m_lineEnd = Qt::SquareCap;
m_lineJoin = Qt::RoundJoin;
m_fillGradient = VGradientEx(VGradientEx::linear);
m_strokeGradient = VGradientEx(VGradientEx::linear);
// Grayscale conversion parameter
m_convertToGray = gray;
// Initialization of Windows GDI data
m_cr = context;
m_positionX = m_positionY = 0;
clear();
}
ScPainterEx_Cairo::~ScPainterEx_Cairo()
{
}
QColor ScPainterEx_Cairo::transformColor( ScColorShade& colorShade, double trans )
{
QColor c, color;
c = ScColorEngine::getShadeColor(colorShade.color, m_doc, colorShade.shade);
color = qRgba( qRed(c.rgb()), qGreen(c.rgb()), qBlue(c.rgb()), qAlpha(trans * 255));
if ( m_convertToGray )
{
int grayLevel;
QColor grayColor;
grayLevel = 0.3 * color.red() + 0.59 * color.green() + 0.11 * color.blue();
grayColor = qRgba( grayLevel, grayLevel, grayLevel, qAlpha(color.rgb()));
color = grayColor;
}
return color;
}
void ScPainterEx_Cairo::transformImage(QImage& image)
{
int rgb, grey;
int imageWidth = image.width();
int imageHeight = image.height();
QRgb *pscan;
for ( int j = 0; j < imageHeight; j++ )
{
pscan = (QRgb *) image.scanLine(j);
for (int i = 0; i < imageWidth; i++ )
{
rgb = pscan[i];
grey = 0.3 * qRed(rgb) + 0.59 * qGreen(rgb) + 0.11 * qBlue(rgb);
pscan[i] = qRgba(grey, grey, grey, qAlpha(rgb));
}
}
}
void ScPainterEx_Cairo::begin()
{
}
void ScPainterEx_Cairo::end()
{
}
void ScPainterEx_Cairo::clear()
{
/*SolidBrush brush( Color(255,255,255) );
m_graphics->FillRectangle(&brush, 0, 0, m_width, m_height);*/
}
void ScPainterEx_Cairo::clear( ScColorShade &c )
{
/*QColor color = transformColor( c, 1.0 );
QRgb cs = color.rgb();
SolidBrush brush( Color(qAlpha(cs), qRed(cs), qGreen(cs),qBlue(cs)) );
m_graphics->FillRectangle(&brush, 0, 0, m_width, m_height);*/
}
const QTransform ScPainterEx_Cairo::worldMatrix()
{
cairo_matrix_t matrix;
cairo_get_matrix(m_cr, &matrix);
QTransform mat(matrix.xx, matrix.yx, matrix.xy, matrix.yy, matrix.x0, matrix.y0);
return mat;
}
void ScPainterEx_Cairo::setWorldMatrix( const QTransform &mat )
{
cairo_matrix_t matrix;
cairo_matrix_init(&matrix, mat.m11(), mat.m12(), mat.m21(), mat.m22(), mat.dx(), mat.dy());
cairo_set_matrix(m_cr, &matrix);
}
void ScPainterEx_Cairo::translate( double x, double y )
{
cairo_translate(m_cr, x, y);
}
void ScPainterEx_Cairo::rotate( double r )
{
cairo_rotate(m_cr, r * 3.1415927 / 180.0);
}
void ScPainterEx_Cairo::scale( double x, double y )
{
cairo_scale(m_cr, x, y);
}
void ScPainterEx_Cairo::moveTo( const double &x, const double &y )
{
cairo_move_to(m_cr, x, y);
}
void ScPainterEx_Cairo::lineTo( const double &x, const double &y )
{
cairo_line_to(m_cr, x, y);
}
void ScPainterEx_Cairo::curveTo( FPoint p1, FPoint p2, FPoint p3 )
{
cairo_curve_to(m_cr, p1.x(), p1.y(), p2.x(), p2.y(), p3.x(), p3.y() );
}
void ScPainterEx_Cairo::newPath()
{
cairo_new_path( m_cr );
}
void ScPainterEx_Cairo::closePath()
{
cairo_close_path( m_cr);
}
void ScPainterEx_Cairo::setFillRule( bool fillRule )
{
m_fillRule = fillRule;
}
void ScPainterEx_Cairo::setFillMode( int fill )
{
m_fillMode = fill;
}
void ScPainterEx_Cairo::setStrokeMode( int stroke )
{
m_strokeMode = stroke;
}
void ScPainterEx_Cairo::setGradient(VGradientEx::Type mode, FPoint orig, FPoint vec, FPoint foc, double scale, double skew)
{
m_fillGradient.setType(mode);
m_fillGradient.setOrigin(orig);
m_fillGradient.setVector(vec);
m_fillGradient.setFocalPoint(foc);
m_strokeGradient.setType(mode);
m_strokeGradient.setOrigin(orig);
m_strokeGradient.setVector(vec);
m_strokeGradient.setFocalPoint(foc);
m_gradientScale = scale;
if (skew == 90)
m_gradientSkew = 1;
else if (skew == 180)
m_gradientSkew = 0;
else if (skew == 270)
m_gradientSkew = -1;
else if (skew == 360)
m_gradientSkew = 0;
else
m_gradientSkew = tan(M_PI / 180.0 * skew);
}
void ScPainterEx_Cairo::setMaskMode(int mask)
{
m_maskMode = mask;
}
void ScPainterEx_Cairo::setGradientMask(VGradientEx::Type mode, FPoint orig, FPoint vec, FPoint foc, double scale, double skew)
{
m_maskGradient.setType(mode);
m_maskGradient.setOrigin(orig);
m_maskGradient.setVector(vec);
m_maskGradient.setFocalPoint(foc);
m_maskGradientScale = scale;
if (skew == 90)
m_maskGradientSkew = 1;
else if (skew == 180)
m_maskGradientSkew = 0;
else if (skew == 270)
m_maskGradientSkew = -1;
else if (skew == 360)
m_maskGradientSkew = 0;
else
m_maskGradientSkew = tan(M_PI / 180.0 * skew);
}
void ScPainterEx_Cairo::setPatternMask(ScPattern *pattern, double scaleX, double scaleY, double offsetX, double offsetY, double rotation, double skewX, double skewY, bool mirrorX, bool mirrorY)
{
m_maskPattern = pattern;
m_maskPatternScaleX = scaleX / 100.0;
m_maskPatternScaleY = scaleY / 100.0;
m_maskPatternOffsetX = offsetX;
m_maskPatternOffsetY = offsetY;
m_maskPatternRotation = rotation;
m_maskPatternSkewX = skewX;
m_maskPatternSkewY = skewY;
m_maskPatternMirrorX = mirrorX;
m_maskPatternMirrorY = mirrorY;
}
void ScPainterEx_Cairo::setPattern(ScPattern *pattern, double scaleX, double scaleY, double offsetX, double offsetY, double rotation, double skewX, double skewY, bool mirrorX, bool mirrorY)
{
m_pattern = pattern;
m_patternScaleX = scaleX / 100.0;
m_patternScaleY = scaleY / 100.0;
m_patternOffsetX = offsetX;
m_patternOffsetY = offsetY;
m_patternRotation = rotation;
m_patternSkewX = skewX;
m_patternSkewY = skewY;
m_patternMirrorX = mirrorX;
m_patternMirrorY = mirrorY;
}
void ScPainterEx_Cairo::set4ColorGeometry(FPoint p1, FPoint p2, FPoint p3, FPoint p4, FPoint c1, FPoint c2, FPoint c3, FPoint c4)
{
m_fillGradient.setType(VGradientEx::fourcolor);
m_gradPatchP1 = p1;
m_gradPatchP2 = p2;
m_gradPatchP3 = p3;
m_gradPatchP4 = p4;
m_gradControlP1 = c1;
m_gradControlP2 = c2;
m_gradControlP3 = c3;
m_gradControlP4 = c4;
}
void ScPainterEx_Cairo::set4ColorColors(const ScColorShade& col1, const ScColorShade& col2, const ScColorShade& col3, const ScColorShade& col4)
{
m_gradPatchColor1 = col1;
m_gradPatchColor2 = col2;
m_gradPatchColor3 = col3;
m_gradPatchColor4 = col4;
}
void ScPainterEx_Cairo::setDiamondGeometry(FPoint p1, FPoint p2, FPoint p3, FPoint p4, FPoint c1, FPoint c2, FPoint c3, FPoint c4, FPoint c5)
{
m_fillGradient.setType(VGradientEx::diamond);
m_gradPatchP1 = p1;
m_gradPatchP2 = p2;
m_gradPatchP3 = p3;
m_gradPatchP4 = p4;
m_gradControlP1 = c1;
m_gradControlP2 = c2;
m_gradControlP3 = c3;
m_gradControlP4 = c4;
m_gradControlP5 = c5;
}
void ScPainterEx_Cairo::setMeshGradient(FPoint p1, FPoint p2, FPoint p3, FPoint p4, QList<QList<meshPoint> > meshArray)
{
m_fillGradient.setType(VGradientEx::mesh);
m_meshGradientArray = meshArray;
m_gradPatchP1 = p1;
m_gradPatchP2 = p2;
m_gradPatchP3 = p3;
m_gradPatchP4 = p4;
}
void ScPainterEx_Cairo::setMeshGradient(FPoint p1, FPoint p2, FPoint p3, FPoint p4, QList<meshGradientPatch> meshPatches)
{
m_fillGradient.setType(VGradientEx::freemesh);
m_meshGradientPatches = meshPatches;
m_gradPatchP1 = p1;
m_gradPatchP2 = p2;
m_gradPatchP3 = p3;
m_gradPatchP4 = p4;
}
void ScPainterEx_Cairo::fillPath()
{
if (m_fillMode != 0)
fillPathHelper();
}
void ScPainterEx_Cairo::strokePath()
{
//if (m_lineWidth == 0)
// return;
if (m_strokeMode != 0)
strokePathHelper();
}
ScColorShade ScPainterEx_Cairo::pen()
{
return m_strokeColor;
}
ScColorShade ScPainterEx_Cairo::brush()
{
return m_fillColor;
}
void ScPainterEx_Cairo::setPen( const ScColorShade &c )
{
m_strokeColor = c;
}
void ScPainterEx_Cairo::setPen( const ScColorShade &c, double w, Qt::PenStyle st, Qt::PenCapStyle ca, Qt::PenJoinStyle jo )
{
m_strokeColor = c;
m_lineWidth = w;
m_lineEnd = ca;
m_lineJoin = jo;
m_array.clear();
m_offset = 0;
getDashArray(st, w, m_array);
}
void ScPainterEx_Cairo::setLineWidth( double w )
{
m_lineWidth = w;
}
void ScPainterEx_Cairo::setPenOpacity( double op )
{
m_strokeTrans = op;
}
void ScPainterEx_Cairo::setDash(const QVector<double>& array, double ofs)
{
m_array = array;
m_offset = ofs;
}
void ScPainterEx_Cairo::setBrush( const ScColorShade &c )
{
m_fillColor = c;
}
void ScPainterEx_Cairo::setBrushOpacity( double op )
{
m_fillTrans = op;
}
void ScPainterEx_Cairo::setOpacity( double op )
{
m_fillTrans = op;
m_strokeTrans = op;
}
void ScPainterEx_Cairo::setFont( const QFont &f)
{
m_font = f;
}
QFont ScPainterEx_Cairo::font()
{
return m_font;
}
void ScPainterEx_Cairo::save()
{
cairo_save(m_cr);
}
void ScPainterEx_Cairo::restore()
{
cairo_restore( m_cr );
}
void ScPainterEx_Cairo::setRasterOp(int blendMode)
{
if (blendMode == 0)
cairo_set_operator(m_cr, CAIRO_OPERATOR_OVER);
else if (blendMode == 1)
cairo_set_operator(m_cr, CAIRO_OPERATOR_DARKEN);
else if (blendMode == 2)
cairo_set_operator(m_cr, CAIRO_OPERATOR_LIGHTEN);
else if (blendMode == 3)
cairo_set_operator(m_cr, CAIRO_OPERATOR_MULTIPLY);
else if (blendMode == 4)
cairo_set_operator(m_cr, CAIRO_OPERATOR_SCREEN);
else if (blendMode == 5)
cairo_set_operator(m_cr, CAIRO_OPERATOR_OVERLAY);
else if (blendMode == 6)
cairo_set_operator(m_cr, CAIRO_OPERATOR_HARD_LIGHT);
else if (blendMode == 7)
cairo_set_operator(m_cr, CAIRO_OPERATOR_SOFT_LIGHT);
else if (blendMode == 8)
cairo_set_operator(m_cr, CAIRO_OPERATOR_DIFFERENCE);
else if (blendMode == 9)
cairo_set_operator(m_cr, CAIRO_OPERATOR_EXCLUSION);
else if (blendMode == 10)
cairo_set_operator(m_cr, CAIRO_OPERATOR_COLOR_DODGE);
else if (blendMode == 11)
cairo_set_operator(m_cr, CAIRO_OPERATOR_COLOR_BURN);
else if (blendMode == 12)
cairo_set_operator(m_cr, CAIRO_OPERATOR_HSL_HUE);
else if (blendMode == 13)
cairo_set_operator(m_cr, CAIRO_OPERATOR_HSL_SATURATION);
else if (blendMode == 14)
cairo_set_operator(m_cr, CAIRO_OPERATOR_HSL_COLOR);
else if (blendMode == 15)
cairo_set_operator(m_cr, CAIRO_OPERATOR_HSL_LUMINOSITY);
else
cairo_set_operator(m_cr, CAIRO_OPERATOR_OVER);
}
void ScPainterEx_Cairo::setBlendModeFill( int blendMode )
{
m_blendModeFill = blendMode;
}
void ScPainterEx_Cairo::setBlendModeStroke( int blendMode )
{
m_blendModeStroke = blendMode;
}
void ScPainterEx_Cairo::fillPathHelper()
{
cairo_save( m_cr );
cairo_set_operator(m_cr, CAIRO_OPERATOR_OVER);
if( m_fillRule )
cairo_set_fill_rule (m_cr, CAIRO_FILL_RULE_EVEN_ODD);
else
cairo_set_fill_rule (m_cr, CAIRO_FILL_RULE_WINDING);
if (m_fillMode == ScPainterExBase::Solid)
{
double r, g, b;
QColor fillColor = transformColor(m_fillColor, 1.0);
fillColor.getRgbF(&r, &g, &b);
if (m_maskMode > 0)
{
/*cairo_pattern_t *pat = getMaskPattern();
cairo_set_source_rgb( m_cr, r, g, b );
setRasterOp(m_blendModeFill);
cairo_clip_preserve(m_cr);
cairo_mask(m_cr, pat);
if ((maskMode == 2) || (maskMode == 4) || (maskMode == 5) || (maskMode == 6))
cairo_surface_destroy(imageMask);
cairo_pattern_destroy(pat);*/
}
else
{
cairo_set_source_rgba(m_cr, r, g, b, m_fillTrans);
setRasterOp(m_blendModeFill);
cairo_fill_preserve(m_cr);
}
}
else if (m_fillMode == ScPainterExBase::Gradient)
{
drawGradient( m_fillGradient );
}
else if (m_fillMode == ScPainterExBase::Pattern)
{
}
cairo_restore( m_cr );
cairo_set_operator(m_cr, CAIRO_OPERATOR_OVER);
}
void ScPainterEx_Cairo::strokePathHelper()
{
cairo_save( m_cr );
cairo_set_line_width( m_cr, m_lineWidth );
if( m_array.count() > 0 )
cairo_set_dash( m_cr, m_array.data(), m_array.count(), static_cast<double>(m_offset));
else
cairo_set_dash( m_cr, NULL, 0, 0 );
cairo_set_operator(m_cr, CAIRO_OPERATOR_OVER);
if( m_lineEnd == Qt::RoundCap )
cairo_set_line_cap (m_cr, CAIRO_LINE_CAP_ROUND);
else if( m_lineEnd == Qt::SquareCap )
cairo_set_line_cap (m_cr, CAIRO_LINE_CAP_SQUARE);
else if( m_lineEnd == Qt::FlatCap )
cairo_set_line_cap (m_cr, CAIRO_LINE_CAP_BUTT);
if( m_lineJoin == Qt::RoundJoin )
cairo_set_line_join( m_cr, CAIRO_LINE_JOIN_ROUND );
else if( m_lineJoin == Qt::BevelJoin )
cairo_set_line_join( m_cr, CAIRO_LINE_JOIN_BEVEL );
else if( m_lineJoin == Qt::MiterJoin )
cairo_set_line_join( m_cr, CAIRO_LINE_JOIN_MITER );
if (m_strokeMode == 3)
{
}
else if (m_strokeMode == 2)
{
strokeGradient(m_strokeGradient);
}
else
{
double r, g, b;
QColor strokeColor = transformColor( m_strokeColor, 1.0 );
strokeColor.getRgbF(&r, &g, &b);
cairo_set_source_rgba( m_cr, r, g, b, m_strokeTrans );
setRasterOp(m_blendModeStroke);
cairo_stroke_preserve( m_cr );
}
cairo_set_operator(m_cr, CAIRO_OPERATOR_OVER);
cairo_restore( m_cr );
}
void ScPainterEx_Cairo::setClipPath()
{
cairo_clip (m_cr);
}
void ScPainterEx_Cairo::drawImage( ScImage *image, ScPainterExBase::ImageMode mode )
{
QImage qImage(image->qImage());
if (m_convertToGray)
transformImage(qImage);
cairo_save(m_cr);
cairo_set_fill_rule(m_cr, cairo_get_fill_rule(m_cr));
cairo_surface_t *image2 = cairo_image_surface_create_for_data ((uchar*)qImage.bits(), CAIRO_FORMAT_ARGB32, qImage.width(), qImage.height(), qImage.width()*4);
cairo_set_source_surface (m_cr, image2, 0, 0);
cairo_paint_with_alpha (m_cr, m_fillTrans);
cairo_surface_destroy (image2);
cairo_restore(m_cr);
}
void ScPainterEx_Cairo::setupPolygon(FPointArray *points, bool closed)
{
bool nPath = true, first = true;
FPoint np, np1, np2, np3, np4, firstP;
if (points->size() <= 3)
return;
newPath();
for (int poi=0; poi<points->size()-3; poi += 4)
{
if (points->isMarker(poi))
{
nPath = true;
continue;
}
if (nPath)
{
np = points->point(poi);
if ((!first) && (closed) && (np4 == firstP))
cairo_close_path( m_cr );
moveTo( np.x(), np.y() );
first = nPath = false;
firstP = np4 = np;
}
np = points->point(poi);
np1 = points->point(poi + 1);
np2 = points->point(poi + 3);
np3 = points->point(poi + 2);
if (np4 == np3)
continue;
if ((np == np1) && (np2 == np3))
lineTo( np3.x(), np3.y() );
else
curveTo(np1, np2, np3);
np4 = np3;
}
if (closed)
cairo_close_path( m_cr );
}
void ScPainterEx_Cairo::drawPolygon()
{
fillPath();
}
void ScPainterEx_Cairo::drawPolyLine()
{
strokePath();
}
void ScPainterEx_Cairo::drawLine(FPoint start, FPoint end)
{
newPath();
moveTo(start.x(), start.y());
lineTo(end.x(), end.y());
strokePath();
}
void ScPainterEx_Cairo::drawRect(double x, double y, double w, double h)
{
newPath();
moveTo( x, y );
lineTo( x+w, y );
lineTo( x+w, y+h );
lineTo( x, y+h );
lineTo( x, y );
cairo_close_path( m_cr );
fillPath();
strokePath();
}
void ScPainterEx_Cairo::drawGradient( VGradientEx& gradient )
{
QRect clipPathRect;
save();
setClipPath();
getClipPathDimensions( clipPathRect );
if ( gradient.type() == VGradientEx::linear )
drawLinearGradient( gradient, clipPathRect );
else if ( gradient.type() == VGradientEx::radial )
drawCircularGradient( gradient, clipPathRect );
else if ( gradient.type() == VGradientEx::fourcolor )
drawFourColorGradient( clipPathRect );
else if ( gradient.type() == VGradientEx::diamond )
drawDiamondGradient( gradient, clipPathRect );
else if ( gradient.type() == VGradientEx::mesh )
drawMeshGradient( clipPathRect );
else if ( gradient.type() == VGradientEx::freemesh )
drawFreeMeshGradient( clipPathRect );
restore();
}
void ScPainterEx_Cairo::drawLinearGradient( VGradientEx& gradient, const QRect& rect )
{
int index = 0;
double r, g, b;
QList<VColorStopEx*> colorStops = gradient.colorStops();
VColorStopEx* stop = NULL;
QColor color;
if ( gradient.Stops() < 2 )
return;
double x1 = gradient.origin().x();
double y1 = gradient.origin().y();
double x2 = gradient.vector().x();
double y2 = gradient.vector().y();
cairo_pattern_t *pat = cairo_pattern_create_linear (x1, y1, x2, y2);
cairo_pattern_set_extend(pat, CAIRO_EXTEND_PAD);
cairo_pattern_set_filter(pat, CAIRO_FILTER_GOOD);
bool isFirst = true;
double lastStop = 0.0;
for( uint index = 0 ; index < gradient.Stops(); index++)
{
stop = colorStops.at(index);
if ((lastStop == stop->rampPoint) && (!isFirst))
continue;
isFirst = false;
color = transformColor( ScColorShade(stop->color, stop->shade), 1.0 );
color.getRgbF(&r, &g, &b);
cairo_pattern_add_color_stop_rgba (pat, stop->rampPoint, r, g, b, stop->opacity);
lastStop = stop->rampPoint;
}
QTransform qmatrix;
qmatrix.translate(x1, y1);
qmatrix.shear(-m_gradientSkew, 0);
qmatrix.translate(-x1, -y1);
cairo_matrix_t matrix;
cairo_matrix_init(&matrix, qmatrix.m11(), qmatrix.m12(), qmatrix.m21(), qmatrix.m22(), qmatrix.dx(), qmatrix.dy());
cairo_matrix_invert(&matrix);
cairo_pattern_set_matrix (pat, &matrix);
setRasterOp(m_blendModeFill);
cairo_set_source (m_cr, pat);
//cairo_clip_preserve (m_cr);
cairo_paint_with_alpha (m_cr, m_fillTrans);
cairo_pattern_destroy (pat);
}
void ScPainterEx_Cairo::drawCircularGradient( VGradientEx& gradient, const QRect& rect )
{
int offset = 0;
double r, g, b;
QList<VColorStopEx*> colorStops = gradient.colorStops();
VColorStopEx* stop = NULL;
QColor color;
double x1 = gradient.origin().x();
double y1 = gradient.origin().y();
double x2 = gradient.vector().x();
double y2 = gradient.vector().y();
double fx = gradient.focalPoint().x();
double fy = gradient.focalPoint().y();
double rad = sqrt( pow(x2 - x1, 2) + pow(y2 - y1, 2) );
cairo_pattern_t* pat = cairo_pattern_create_radial (fx, fy, 0, x1, y1, rad);
cairo_pattern_set_extend(pat, CAIRO_EXTEND_PAD);
cairo_pattern_set_filter(pat, CAIRO_FILTER_GOOD);
bool isFirst = true;
double lastStop = 0.0;
for( uint index = 0 ; index < gradient.Stops() ; index++)
{
stop = colorStops.at(index);
if ((lastStop == stop->rampPoint) && (!isFirst))
continue;
isFirst = false;
color = transformColor( ScColorShade(stop->color, stop->shade), 1.0 );
color.getRgbF(&r, &g, &b);
cairo_pattern_add_color_stop_rgba (pat, stop->rampPoint, r, g, b, stop->opacity);
lastStop = stop->rampPoint;
}
QTransform qmatrix;
double rotEnd = xy2Deg(x2 - x1, y2 - y1);
qmatrix.translate(x1, y1);
qmatrix.rotate(rotEnd);
qmatrix.shear(m_gradientSkew, 0);
qmatrix.translate(0, y1 * (1.0 - m_gradientScale));
qmatrix.translate(-x1, -y1);
qmatrix.scale(1, m_gradientScale);
cairo_set_source (m_cr, pat);
//cairo_clip_preserve (m_cr);
setRasterOp(m_blendModeFill);
cairo_paint_with_alpha (m_cr, m_fillTrans);
cairo_pattern_destroy (pat);
}
void ScPainterEx_Cairo::drawFourColorGradient( const QRect& rect )
{
cairo_pattern_t *pat = NULL;
cairo_surface_t *img = NULL;
cairo_t *cr = NULL;
cairo_pattern_t *mpat = NULL;
QColor color;
double p1x = m_gradPatchP1.x();
double p1y = m_gradPatchP1.y();
double p2x = m_gradPatchP2.x();
double p2y = m_gradPatchP2.y();
double p3x = m_gradPatchP3.x();
double p3y = m_gradPatchP3.y();
double p4x = m_gradPatchP4.x();
double p4y = m_gradPatchP4.y();
img = cairo_surface_create_similar(cairo_get_target(m_cr), CAIRO_CONTENT_COLOR_ALPHA, p3x, p3y);
cr = cairo_create(img);
cairo_set_fill_rule(cr, CAIRO_FILL_RULE_EVEN_ODD);
cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
cairo_set_tolerance(cr, 0.5 );
double r, g, b, a;
mpat = cairo_pattern_create_mesh();
cairo_mesh_pattern_begin_patch(mpat);
cairo_mesh_pattern_move_to(mpat, p1x, p1y);
cairo_mesh_pattern_line_to(mpat, p2x, p2y);
cairo_mesh_pattern_line_to(mpat, p3x, p3y);
cairo_mesh_pattern_line_to(mpat, p4x, p4y);
cairo_mesh_pattern_line_to(mpat, p1x, p1y);
cairo_mesh_pattern_set_control_point(mpat, 0, m_gradControlP1.x(), m_gradControlP1.y());
cairo_mesh_pattern_set_control_point(mpat, 1, m_gradControlP2.x(), m_gradControlP2.y());
cairo_mesh_pattern_set_control_point(mpat, 2, m_gradControlP3.x(), m_gradControlP3.y());
cairo_mesh_pattern_set_control_point(mpat, 3, m_gradControlP4.x(), m_gradControlP4.y());
color = transformColor(m_gradPatchColor1, 1.0);
color.getRgbF(&r, &g, &b, &a);
cairo_mesh_pattern_set_corner_color_rgba(mpat, 0, r, g, b, a);
color = transformColor(m_gradPatchColor2, 1.0);
color.getRgbF(&r, &g, &b, &a);
cairo_mesh_pattern_set_corner_color_rgba(mpat, 1, r, g, b, a);
color = transformColor(m_gradPatchColor3, 1.0);
color.getRgbF(&r, &g, &b, &a);
cairo_mesh_pattern_set_corner_color_rgba(mpat, 2, r, g, b, a);
color = transformColor(m_gradPatchColor4, 1.0);
color.getRgbF(&r, &g, &b, &a);
cairo_mesh_pattern_set_corner_color_rgba(mpat, 3, r, g, b, a);
cairo_mesh_pattern_end_patch(mpat);
cairo_pattern_set_filter(mpat, CAIRO_FILTER_GOOD);
cairo_set_source(cr, mpat);
cairo_paint_with_alpha(cr, 1.0);
pat = cairo_pattern_create_for_surface(img);
cairo_pattern_set_extend(pat, CAIRO_EXTEND_NONE);
cairo_pattern_set_filter(pat, CAIRO_FILTER_GOOD);
cairo_set_source (m_cr, pat);
//cairo_clip_preserve (m_cr);
if (m_maskMode > 0)
{
/*cairo_pattern_t *patM = getMaskPattern();
setRasterOp(m_blendModeFill);
cairo_mask(m_cr, patM);
if ((m_maskMode == 2) || (m_maskMode == 4) || (m_maskMode == 5) || (m_maskMode == 6))
cairo_surface_destroy(imageMask);
cairo_pattern_destroy (patM);*/
}
else
{
setRasterOp(m_blendModeFill);
cairo_paint_with_alpha (m_cr, m_fillTrans);
}
cairo_pattern_destroy (pat);
if (img) cairo_surface_destroy(img);
if (mpat) cairo_pattern_destroy(mpat);
if (cr) cairo_destroy( cr );
}
void ScPainterEx_Cairo::drawDiamondGradient( VGradientEx& gradient, const QRect& rect )
{
cairo_pattern_t *pat = NULL;
cairo_surface_t *img = NULL;
cairo_t *cr = NULL;
cairo_pattern_t *mpat = NULL;
VColorStopEx* stop = NULL;
QColor color;
double p1x = m_gradControlP1.x();
double p1y = m_gradControlP1.y();
double p2x = m_gradControlP2.x();
double p2y = m_gradControlP2.y();
double p3x = m_gradControlP3.x();
double p3y = m_gradControlP3.y();
double p4x = m_gradControlP4.x();
double p4y = m_gradControlP4.y();
img = cairo_surface_create_similar(cairo_get_target(m_cr), CAIRO_CONTENT_COLOR_ALPHA, m_gradPatchP3.x(), m_gradPatchP3.y());
cr = cairo_create(img);
cairo_set_fill_rule(cr, CAIRO_FILL_RULE_EVEN_ODD);
cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
cairo_set_tolerance(cr, 0.5 );
double r, g, b, a;
QList<VColorStopEx*> colorStops = gradient.colorStops();
QList<QColor> qStopColors;
QColor qStopColor;
for( int offset = 0 ; offset < colorStops.count() ; offset++ )
{
stop = colorStops.at(offset);
qStopColor = transformColor( ScColorShade(stop->color, stop->shade), 1.0);
int h, s, v, sneu, vneu;
int shad = stop->shade;
qStopColor.getHsv(&h, &s, &v);
sneu = s * shad / 100;
vneu = 255 - ((255 - v) * shad / 100);
qStopColor.setHsv(h, sneu, vneu);
qStopColor.setAlphaF(colorStops[offset]->opacity);
qStopColors.append(qStopColor);
}
qStopColors.last().getRgbF(&r, &g, &b, &a);
QPointF centerP = QPointF(m_gradControlP5.x(), m_gradControlP5.y());
QLineF edge1 = QLineF(centerP, QPointF(p1x, p1y));
QLineF edge2 = QLineF(centerP, QPointF(p2x, p2y));
QLineF edge3 = QLineF(centerP, QPointF(p3x, p3y));
QLineF edge4 = QLineF(centerP, QPointF(p4x, p4y));
QPointF p1 = edge1.pointAt(colorStops.last()->rampPoint);
QPointF p2 = edge2.pointAt(colorStops.last()->rampPoint);
QPointF p3 = edge3.pointAt(colorStops.last()->rampPoint);
QPointF p4 = edge4.pointAt(colorStops.last()->rampPoint);
cairo_set_source_rgba(cr, r, g, b, a);
cairo_paint_with_alpha(cr, 1.0);
cairo_set_operator(cr, CAIRO_OPERATOR_DEST_OUT);
cairo_new_path(cr);
cairo_move_to(cr, p1.x(), p1.y());
cairo_line_to(cr, p2.x(), p2.y());
cairo_line_to(cr, p3.x(), p3.y());
cairo_line_to(cr, p4.x(), p4.y());
cairo_close_path(cr);
cairo_set_source_rgba(cr, 0, 0, 0, 1);
cairo_fill(cr);
cairo_set_operator(cr, CAIRO_OPERATOR_ADD);
mpat = cairo_pattern_create_mesh();
for( int offset = 1 ; offset < colorStops.count() ; offset++ )
{
QLineF e1 = edge1;
QLineF e1s = edge1;
QLineF e2 = edge2;
QLineF e2s = edge2;
QLineF e3 = edge3;
QLineF e3s = edge3;
QLineF e4 = edge4;
QLineF e4s = edge4;
e1.setLength(edge1.length() * colorStops[ offset ]->rampPoint);
e2.setLength(edge2.length() * colorStops[ offset ]->rampPoint);
e3.setLength(edge3.length() * colorStops[ offset ]->rampPoint);
e4.setLength(edge4.length() * colorStops[ offset ]->rampPoint);
e1s.setLength(edge1.length() * colorStops[ offset - 1 ]->rampPoint);
e2s.setLength(edge2.length() * colorStops[ offset - 1 ]->rampPoint);
e3s.setLength(edge3.length() * colorStops[ offset - 1 ]->rampPoint);
e4s.setLength(edge4.length() * colorStops[ offset - 1 ]->rampPoint);
if (offset == 1)
{
cairo_mesh_pattern_begin_patch(mpat);
cairo_mesh_pattern_move_to(mpat, centerP.x(), centerP.y());
cairo_mesh_pattern_line_to(mpat, e1.x2(), e1.y2());
cairo_mesh_pattern_line_to(mpat, e2.x2(), e2.y2());
cairo_mesh_pattern_line_to(mpat, centerP.x(), centerP.y());
qStopColors[0].getRgbF(&r, &g, &b, &a);
cairo_mesh_pattern_set_corner_color_rgba(mpat, 0, r, g, b, a);
qStopColors[1].getRgbF(&r, &g, &b, &a);
cairo_mesh_pattern_set_corner_color_rgba(mpat, 1, r, g, b, a);
cairo_mesh_pattern_set_corner_color_rgba(mpat, 2, r, g, b, a);
cairo_mesh_pattern_end_patch(mpat);
cairo_mesh_pattern_begin_patch(mpat);
cairo_mesh_pattern_move_to(mpat, centerP.x(), centerP.y());
cairo_mesh_pattern_line_to(mpat, e2.x2(), e2.y2());
cairo_mesh_pattern_line_to(mpat, e3.x2(), e3.y2());
cairo_mesh_pattern_line_to(mpat, centerP.x(), centerP.y());
qStopColors[0].getRgbF(&r, &g, &b, &a);
cairo_mesh_pattern_set_corner_color_rgba(mpat, 0, r, g, b, a);
qStopColors[1].getRgbF(&r, &g, &b, &a);
cairo_mesh_pattern_set_corner_color_rgba(mpat, 1, r, g, b, a);
cairo_mesh_pattern_set_corner_color_rgba(mpat, 2, r, g, b, a);
cairo_mesh_pattern_end_patch(mpat);
cairo_mesh_pattern_begin_patch(mpat);
cairo_mesh_pattern_move_to(mpat, centerP.x(), centerP.y());
cairo_mesh_pattern_line_to(mpat, e3.x2(), e3.y2());
cairo_mesh_pattern_line_to(mpat, e4.x2(), e4.y2());
cairo_mesh_pattern_line_to(mpat, centerP.x(), centerP.y());
qStopColors[0].getRgbF(&r, &g, &b, &a);
cairo_mesh_pattern_set_corner_color_rgba(mpat, 0, r, g, b, a);
qStopColors[1].getRgbF(&r, &g, &b, &a);
cairo_mesh_pattern_set_corner_color_rgba(mpat, 1, r, g, b, a);
cairo_mesh_pattern_set_corner_color_rgba(mpat, 2, r, g, b, a);
cairo_mesh_pattern_end_patch(mpat);
cairo_mesh_pattern_begin_patch(mpat);
cairo_mesh_pattern_move_to(mpat, centerP.x(), centerP.y());
cairo_mesh_pattern_line_to(mpat, e4.x2(), e4.y2());
cairo_mesh_pattern_line_to(mpat, e1.x2(), e1.y2());
cairo_mesh_pattern_line_to(mpat, centerP.x(), centerP.y());
qStopColors[0].getRgbF(&r, &g, &b, &a);
cairo_mesh_pattern_set_corner_color_rgba(mpat, 0, r, g, b, a);
qStopColors[1].getRgbF(&r, &g, &b, &a);
cairo_mesh_pattern_set_corner_color_rgba(mpat, 1, r, g, b, a);
cairo_mesh_pattern_set_corner_color_rgba(mpat, 2, r, g, b, a);
cairo_mesh_pattern_end_patch(mpat);
}
else
{
cairo_mesh_pattern_begin_patch(mpat);
cairo_mesh_pattern_move_to(mpat, e1s.x2(), e1s.y2());
cairo_mesh_pattern_line_to(mpat, e1.x2(), e1.y2());
cairo_mesh_pattern_line_to(mpat, e2.x2(), e2.y2());
cairo_mesh_pattern_line_to(mpat, e2s.x2(), e2s.y2());
qStopColors[offset-1].getRgbF(&r, &g, &b, &a);
cairo_mesh_pattern_set_corner_color_rgba(mpat, 0, r, g, b, a);
qStopColors[offset].getRgbF(&r, &g, &b, &a);
cairo_mesh_pattern_set_corner_color_rgba(mpat, 1, r, g, b, a);
cairo_mesh_pattern_set_corner_color_rgba(mpat, 2, r, g, b, a);
qStopColors[offset-1].getRgbF(&r, &g, &b, &a);
cairo_mesh_pattern_set_corner_color_rgba(mpat, 3, r, g, b, a);
cairo_mesh_pattern_end_patch(mpat);
cairo_mesh_pattern_begin_patch(mpat);
cairo_mesh_pattern_move_to(mpat, e2s.x2(), e2s.y2());
cairo_mesh_pattern_line_to(mpat, e2.x2(), e2.y2());
cairo_mesh_pattern_line_to(mpat, e3.x2(), e3.y2());
cairo_mesh_pattern_line_to(mpat, e3s.x2(), e3s.y2());
qStopColors[offset - 1].getRgbF(&r, &g, &b, &a);
cairo_mesh_pattern_set_corner_color_rgba(mpat, 0, r, g, b, a);
qStopColors[offset].getRgbF(&r, &g, &b, &a);
cairo_mesh_pattern_set_corner_color_rgba(mpat, 1, r, g, b, a);
cairo_mesh_pattern_set_corner_color_rgba(mpat, 2, r, g, b, a);
qStopColors[offset-1].getRgbF(&r, &g, &b, &a);
cairo_mesh_pattern_set_corner_color_rgba(mpat, 3, r, g, b, a);
cairo_mesh_pattern_end_patch(mpat);
cairo_mesh_pattern_begin_patch(mpat);
cairo_mesh_pattern_move_to(mpat, e3s.x2(), e3s.y2());
cairo_mesh_pattern_line_to(mpat, e3.x2(), e3.y2());
cairo_mesh_pattern_line_to(mpat, e4.x2(), e4.y2());
cairo_mesh_pattern_line_to(mpat, e4s.x2(), e4s.y2());
qStopColors[offset - 1].getRgbF(&r, &g, &b, &a);
cairo_mesh_pattern_set_corner_color_rgba(mpat, 0, r, g, b, a);
qStopColors[offset].getRgbF(&r, &g, &b, &a);
cairo_mesh_pattern_set_corner_color_rgba(mpat, 1, r, g, b, a);
cairo_mesh_pattern_set_corner_color_rgba(mpat, 2, r, g, b, a);
qStopColors[offset-1].getRgbF(&r, &g, &b, &a);
cairo_mesh_pattern_set_corner_color_rgba(mpat, 3, r, g, b, a);
cairo_mesh_pattern_end_patch(mpat);
cairo_mesh_pattern_begin_patch(mpat);
cairo_mesh_pattern_move_to(mpat, e4s.x2(), e4s.y2());
cairo_mesh_pattern_line_to(mpat, e4.x2(), e4.y2());
cairo_mesh_pattern_line_to(mpat, e1.x2(), e1.y2());
cairo_mesh_pattern_line_to(mpat, e1s.x2(), e1s.y2());
qStopColors[offset-1].getRgbF(&r, &g, &b, &a);
cairo_mesh_pattern_set_corner_color_rgba(mpat, 0, r, g, b, a);
qStopColors[offset].getRgbF(&r, &g, &b, &a);
cairo_mesh_pattern_set_corner_color_rgba(mpat, 1, r, g, b, a);
cairo_mesh_pattern_set_corner_color_rgba(mpat, 2, r, g, b, a);
qStopColors[offset-1].getRgbF(&r, &g, &b, &a);
cairo_mesh_pattern_set_corner_color_rgba(mpat, 3, r, g, b, a);
cairo_mesh_pattern_end_patch(mpat);
}
}
cairo_pattern_set_filter(mpat, CAIRO_FILTER_GOOD);
cairo_set_source(cr, mpat);
cairo_paint_with_alpha(cr, 1.0);
pat = cairo_pattern_create_for_surface(img);
cairo_pattern_set_extend(pat, CAIRO_EXTEND_PAD);
cairo_pattern_set_filter(pat, CAIRO_FILTER_GOOD);
cairo_set_source (m_cr, pat);
//cairo_clip_preserve (m_cr);
if (m_maskMode > 0)
{
/*cairo_pattern_t *patM = getMaskPattern();
setRasterOp(m_blendModeFill);
cairo_mask(m_cr, patM);
if ((m_maskMode == 2) || (m_maskMode == 4) || (m_maskMode == 5) || (m_maskMode == 6))
cairo_surface_destroy(imageMask);
cairo_pattern_destroy (patM);*/
}
else
{
setRasterOp(m_blendModeFill);
cairo_paint_with_alpha (m_cr, m_fillTrans);
}
cairo_pattern_destroy (pat);
if (img) cairo_surface_destroy(img);
if (mpat) cairo_pattern_destroy(mpat);
if (cr) cairo_destroy( cr );
}
void ScPainterEx_Cairo::drawMeshGradient( const QRect& rect )
{
cairo_pattern_t *pat = NULL;
cairo_surface_t *img = NULL;
cairo_t *cr = NULL;
cairo_pattern_t *mpat = NULL;
VColorStopEx* stop = NULL;
QColor color;
double p3x = m_gradPatchP3.x();
double p3y = m_gradPatchP3.y();
img = cairo_surface_create_similar(cairo_get_target(m_cr), CAIRO_CONTENT_COLOR_ALPHA, p3x, p3y);
cr = cairo_create(img);
cairo_set_fill_rule(cr, CAIRO_FILL_RULE_EVEN_ODD);
cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
cairo_set_tolerance(cr, 0.5 );
double r, g, b, a;
mpat = cairo_pattern_create_mesh();
for (int grow = 0; grow < m_meshGradientArray.count()-1; grow++)
{
for (int gcol = 0; gcol < m_meshGradientArray[grow].count()-1; gcol++)
{
meshPoint mp1 = m_meshGradientArray[grow][gcol];
meshPoint mp2 = m_meshGradientArray[grow][gcol+1];
meshPoint mp3 = m_meshGradientArray[grow+1][gcol+1];
meshPoint mp4 = m_meshGradientArray[grow+1][gcol];
cairo_mesh_pattern_begin_patch(mpat);
cairo_mesh_pattern_move_to(mpat, mp1.gridPoint.x(), mp1.gridPoint.y());
cairo_mesh_pattern_curve_to(mpat, mp1.controlRight.x(), mp1.controlRight.y(), mp2.controlLeft.x(), mp2.controlLeft.y(), mp2.gridPoint.x(), mp2.gridPoint.y());
cairo_mesh_pattern_curve_to(mpat, mp2.controlBottom.x(), mp2.controlBottom.y(), mp3.controlTop.x(), mp3.controlTop.y(), mp3.gridPoint.x(), mp3.gridPoint.y());
cairo_mesh_pattern_curve_to(mpat, mp3.controlLeft.x(), mp3.controlLeft.y(), mp4.controlRight.x(), mp4.controlRight.y(), mp4.gridPoint.x(), mp4.gridPoint.y());
cairo_mesh_pattern_curve_to(mpat, mp4.controlTop.x(), mp4.controlTop.y(), mp1.controlBottom.x(), mp1.controlBottom.y(), mp1.gridPoint.x(), mp1.gridPoint.y());
cairo_mesh_pattern_set_control_point(mpat, 0, mp1.controlColor.x(), mp1.controlColor.y());
cairo_mesh_pattern_set_control_point(mpat, 1, mp2.controlColor.x(), mp2.controlColor.y());
cairo_mesh_pattern_set_control_point(mpat, 2, mp3.controlColor.x(), mp3.controlColor.y());
cairo_mesh_pattern_set_control_point(mpat, 3, mp4.controlColor.x(), mp4.controlColor.y());
mp1.color.getRgbF(&r, &g, &b, &a);
cairo_mesh_pattern_set_corner_color_rgba(mpat, 0, r, g, b, a);
mp2.color.getRgbF(&r, &g, &b, &a);
cairo_mesh_pattern_set_corner_color_rgba(mpat, 1, r, g, b, a);
mp3.color.getRgbF(&r, &g, &b, &a);
cairo_mesh_pattern_set_corner_color_rgba(mpat, 2, r, g, b, a);
mp4.color.getRgbF(&r, &g, &b, &a);
cairo_mesh_pattern_set_corner_color_rgba(mpat, 3, r, g, b, a);
cairo_mesh_pattern_end_patch(mpat);
}
}
cairo_pattern_set_filter(mpat, CAIRO_FILTER_BEST);
cairo_set_source(cr, mpat);
cairo_paint_with_alpha(cr, 1.0);
pat = cairo_pattern_create_for_surface(img);
cairo_pattern_set_extend(pat, CAIRO_EXTEND_NONE);
cairo_pattern_set_filter(pat, CAIRO_FILTER_BEST);
cairo_set_source (m_cr, pat);
//cairo_clip_preserve (m_cr);
if (m_maskMode > 0)
{
/*cairo_pattern_t *patM = getMaskPattern();
setRasterOp(m_blendModeFill);
cairo_mask(m_cr, patM);
if ((m_maskMode == 2) || (m_maskMode == 4) || (m_maskMode == 5) || (m_maskMode == 6))
cairo_surface_destroy(imageMask);
cairo_pattern_destroy (patM);*/
}
else
{
setRasterOp(m_blendModeFill);
cairo_paint_with_alpha (m_cr, m_fillTrans);
}
cairo_pattern_destroy (pat);
if (img) cairo_surface_destroy(img);
if (mpat) cairo_pattern_destroy(mpat);
if (cr) cairo_destroy( cr );
}
void ScPainterEx_Cairo::drawFreeMeshGradient( const QRect& rect )
{
cairo_pattern_t *pat = NULL;
cairo_surface_t *img = NULL;
cairo_t *cr = NULL;
cairo_pattern_t *mpat = NULL;
VColorStopEx* stop = NULL;
QColor color;
double p3x = m_gradPatchP3.x();
double p3y = m_gradPatchP3.y();
img = cairo_surface_create_similar(cairo_get_target(m_cr), CAIRO_CONTENT_COLOR_ALPHA, p3x, p3y);
cr = cairo_create(img);
cairo_set_fill_rule(cr, CAIRO_FILL_RULE_EVEN_ODD);
cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
cairo_set_tolerance(cr, 0.5 );
double r, g, b, a;
mpat = cairo_pattern_create_mesh();
for (int col = 0; col < m_meshGradientPatches.count(); col++)
{
meshGradientPatch patch = m_meshGradientPatches[col];
meshPoint mp1 = patch.TL;
meshPoint mp2 = patch.TR;
meshPoint mp3 = patch.BR;
meshPoint mp4 = patch.BL;
cairo_mesh_pattern_begin_patch(mpat);
cairo_mesh_pattern_move_to(mpat, mp1.gridPoint.x(), mp1.gridPoint.y());
cairo_mesh_pattern_curve_to(mpat, mp1.controlRight.x(), mp1.controlRight.y(), mp2.controlLeft.x(), mp2.controlLeft.y(), mp2.gridPoint.x(), mp2.gridPoint.y());
cairo_mesh_pattern_curve_to(mpat, mp2.controlBottom.x(), mp2.controlBottom.y(), mp3.controlTop.x(), mp3.controlTop.y(), mp3.gridPoint.x(), mp3.gridPoint.y());
cairo_mesh_pattern_curve_to(mpat, mp3.controlLeft.x(), mp3.controlLeft.y(), mp4.controlRight.x(), mp4.controlRight.y(), mp4.gridPoint.x(), mp4.gridPoint.y());
cairo_mesh_pattern_curve_to(mpat, mp4.controlTop.x(), mp4.controlTop.y(), mp1.controlBottom.x(), mp1.controlBottom.y(), mp1.gridPoint.x(), mp1.gridPoint.y());
cairo_mesh_pattern_set_control_point(mpat, 0, mp1.controlColor.x(), mp1.controlColor.y());
cairo_mesh_pattern_set_control_point(mpat, 1, mp2.controlColor.x(), mp2.controlColor.y());
cairo_mesh_pattern_set_control_point(mpat, 2, mp3.controlColor.x(), mp3.controlColor.y());
cairo_mesh_pattern_set_control_point(mpat, 3, mp4.controlColor.x(), mp4.controlColor.y());
mp1.color.getRgbF(&r, &g, &b, &a);
cairo_mesh_pattern_set_corner_color_rgba(mpat, 0, r, g, b, a);
mp2.color.getRgbF(&r, &g, &b, &a);
cairo_mesh_pattern_set_corner_color_rgba(mpat, 1, r, g, b, a);
mp3.color.getRgbF(&r, &g, &b, &a);
cairo_mesh_pattern_set_corner_color_rgba(mpat, 2, r, g, b, a);
mp4.color.getRgbF(&r, &g, &b, &a);
cairo_mesh_pattern_set_corner_color_rgba(mpat, 3, r, g, b, a);
cairo_mesh_pattern_end_patch(mpat);
}
cairo_pattern_set_filter(mpat, CAIRO_FILTER_BEST);
cairo_set_source(cr, mpat);
cairo_paint_with_alpha(cr, 1.0);
pat = cairo_pattern_create_for_surface(img);
cairo_pattern_set_extend(pat, CAIRO_EXTEND_NONE);
cairo_pattern_set_filter(pat, CAIRO_FILTER_BEST);
cairo_set_source (m_cr, pat);
//cairo_clip_preserve (m_cr);
if (m_maskMode > 0)
{
/*cairo_pattern_t *patM = getMaskPattern();
setRasterOp(m_blendModeFill);
cairo_mask(m_cr, patM);
if ((m_maskMode == 2) || (m_maskMode == 4) || (m_maskMode == 5) || (m_maskMode == 6))
cairo_surface_destroy(imageMask);
cairo_pattern_destroy (patM);*/
}
else
{
setRasterOp(m_blendModeFill);
cairo_paint_with_alpha (m_cr, m_fillTrans);
}
cairo_pattern_destroy (pat);
if (img) cairo_surface_destroy(img);
if (mpat) cairo_pattern_destroy(mpat);
if (cr) cairo_destroy( cr );
}
void ScPainterEx_Cairo::strokeGradient(VGradientEx& gradient)
{
save();
if ( gradient.type() == VGradientEx::linear )
strokeLinearGradient(gradient);
else if ( gradient.type() == VGradientEx::radial )
strokeCircularGradient(gradient);
restore();
}
void ScPainterEx_Cairo::strokeLinearGradient(VGradientEx& gradient)
{
cairo_pattern_t *pat = NULL;
double r, g, b, lastPoint = 0.0;
double x1 = gradient.origin().x();
double y1 = gradient.origin().y();
double x2 = gradient.vector().x();
double y2 = gradient.vector().y();
double fx = gradient.focalPoint().x();
double fy = gradient.focalPoint().y();
QList<VColorStopEx*> colorStops = gradient.colorStops();
VColorStopEx* stop = NULL;
QColor color;
cairo_push_group(m_cr);
pat = cairo_pattern_create_linear (x1, y1, x2, y2);
cairo_pattern_set_extend(pat, CAIRO_EXTEND_PAD);
cairo_pattern_set_filter(pat, CAIRO_FILTER_GOOD);
bool isFirst = true;
double lastStop = 0.0;
for( uint index = 0 ; index < gradient.Stops(); index++)
{
stop = colorStops.at(index);
if ((lastStop == stop->rampPoint) && (!isFirst))
continue;
isFirst = false;
color = transformColor( ScColorShade(stop->color, stop->shade), 1.0 );
color.getRgbF(&r, &g, &b);
cairo_pattern_add_color_stop_rgba (pat, stop->rampPoint, r, g, b, stop->opacity);
lastStop = stop->rampPoint;
}
cairo_matrix_t matrix;
QTransform qmatrix;
qmatrix.translate(x1, y1);
qmatrix.shear(-m_gradientSkew, 0);
qmatrix.translate(-x1, -y1);
cairo_matrix_init(&matrix, qmatrix.m11(), qmatrix.m12(), qmatrix.m21(), qmatrix.m22(), qmatrix.dx(), qmatrix.dy());
cairo_matrix_invert(&matrix);
cairo_pattern_set_matrix (pat, &matrix);
cairo_set_source (m_cr, pat);
cairo_stroke_preserve( m_cr );
cairo_pattern_destroy (pat);
cairo_pop_group_to_source (m_cr);
setRasterOp(m_blendModeStroke);
cairo_paint_with_alpha (m_cr, m_strokeTrans);
}
void ScPainterEx_Cairo::strokeCircularGradient(VGradientEx& gradient)
{
cairo_pattern_t *pat = NULL;
double r, g, b, lastPoint = 0.0;
double x1 = gradient.origin().x();
double y1 = gradient.origin().y();
double x2 = gradient.vector().x();
double y2 = gradient.vector().y();
double fx = gradient.focalPoint().x();
double fy = gradient.focalPoint().y();
QList<VColorStopEx*> colorStops = gradient.colorStops();
VColorStopEx* stop = NULL;
QColor color;
cairo_push_group(m_cr);
pat = cairo_pattern_create_radial (fx, fy, 0, x1, y1, sqrt(pow(x2 - x1, 2) + pow(y2 - y1,2)));
cairo_pattern_set_extend(pat, CAIRO_EXTEND_PAD);
cairo_pattern_set_filter(pat, CAIRO_FILTER_GOOD);
bool isFirst = true;
double lastStop = 0.0;
for( uint index = 0 ; index < gradient.Stops(); index++)
{
stop = colorStops.at(index);
if ((lastStop == stop->rampPoint) && (!isFirst))
continue;
isFirst = false;
color = transformColor( ScColorShade(stop->color, stop->shade), 1.0 );
color.getRgbF(&r, &g, &b);
cairo_pattern_add_color_stop_rgba (pat, stop->rampPoint, r, g, b, stop->opacity);
lastStop = stop->rampPoint;
}
cairo_matrix_t matrix;
QTransform qmatrix;
double rotEnd = xy2Deg(x2 - x1, y2 - y1);
qmatrix.translate(x1, y1);
qmatrix.rotate(rotEnd);
qmatrix.shear(m_gradientSkew, 0);
qmatrix.translate(0, y1 * (1.0 - m_gradientScale));
qmatrix.translate(-x1, -y1);
qmatrix.scale(1, m_gradientScale);
cairo_matrix_init(&matrix, qmatrix.m11(), qmatrix.m12(), qmatrix.m21(), qmatrix.m22(), qmatrix.dx(), qmatrix.dy());
cairo_matrix_invert(&matrix);
cairo_pattern_set_matrix (pat, &matrix);
cairo_set_source (m_cr, pat);
cairo_stroke_preserve( m_cr );
cairo_pattern_destroy (pat);
cairo_pop_group_to_source (m_cr);
setRasterOp(m_blendModeStroke);
cairo_paint_with_alpha (m_cr, m_strokeTrans);
}
void ScPainterEx_Cairo::getClipPathDimensions( QRect& r )
{
double left = 0.0, right = 0.0, bottom = 0.0, top = 0.0;
cairo_clip_extents(m_cr, &left, &bottom, &right, &top);
r.setLeft( left );
r.setRight( right );
r.setBottom( bottom );
r.setTop( top );
}