Scribus Developer Documentation - API
logo-pen

Scribus Developer Documentation - API

scpainter.cpp

Go to the documentation of this file.
00001 /*
00002 For general Scribus (>=1.3.2) copyright and licensing information please refer
00003 to the COPYING file provided with the program. Following this notice may exist
00004 a copyright and/or license notice that predates the release of Scribus 1.3.2
00005 for which a new license (GPL+exception) is in place.
00006 */
00007 
00008 #include "scpainter.h"
00009 #include "util_color.h"
00010 #include "util.h"
00011 
00012 #ifdef HAVE_CAIRO
00013     #include <cairo.h>
00014     #if defined(_WIN32)
00015     #include <cairo-win32.h>
00016     #elif defined(Q_WS_X11)
00017     #include <cairo-xlib.h>
00018     #elif defined(Q_WS_MAC)
00019 //  #include <cairo-quartz.h>
00020     #endif
00021     #include <cairo-svg.h>
00022 #endif
00023 
00024 #include <math.h>
00025 
00026 #ifdef HAVE_CAIRO
00028 ScPainter::ScPainter( QImage *target, unsigned int w, unsigned int h, double transparency, int blendmode )
00029 {
00030     m_width = w;
00031     m_height= h;
00032     m_stroke = QColor(0,0,0);
00033     m_fill = QColor(0,0,0);
00034     fill_trans = 1.0;
00035     stroke_trans = 1.0;
00036     m_fillRule = true;
00037     fillMode = 1;
00038     LineWidth = 1.0;
00039     m_offset = 0;
00040     m_layerTransparency = transparency;
00041     m_blendMode = blendmode;
00042     m_array.clear();
00043     mf_underline = false;
00044     mf_strikeout = false;
00045     mf_shadow = false;
00046     mf_outlined = false;
00047     PLineEnd = Qt::FlatCap;
00048     PLineJoin = Qt::MiterJoin;
00049     fill_gradient = VGradient(VGradient::linear);
00050     stroke_gradient = VGradient(VGradient::linear);
00051     m_zoomFactor = 1;
00052     layeredMode = true;
00053     imageMode = true;
00054     svgMode = false;
00055     m_image = target;
00056     m_matrix = QMatrix();
00057     cairo_surface_t *img = cairo_image_surface_create_for_data(m_image->bits(), CAIRO_FORMAT_ARGB32, w, h, w*4);
00058     m_cr = cairo_create(img);
00059     cairo_save( m_cr );
00060     cairo_set_fill_rule (m_cr, CAIRO_FILL_RULE_EVEN_ODD);
00061     cairo_set_operator(m_cr, CAIRO_OPERATOR_OVER);
00062     cairo_set_tolerance( m_cr, 0.5 );
00063 }
00064 
00066 ScPainter::ScPainter( QString target, unsigned int w, unsigned int h, double transparency, int blendmode )
00067 {
00068     m_width = w;
00069     m_height= h;
00070     m_stroke = QColor(0,0,0);
00071     m_fill = QColor(0,0,0);
00072     fill_trans = 1.0;
00073     stroke_trans = 1.0;
00074     m_fillRule = true;
00075     fillMode = 1;
00076     LineWidth = 1.0;
00077     m_offset = 0;
00078     m_layerTransparency = transparency;
00079     m_blendMode = blendmode;
00080     m_array.clear();
00081     mf_underline = false;
00082     mf_strikeout = false;
00083     mf_shadow = false;
00084     mf_outlined = false;
00085     PLineEnd = Qt::FlatCap;
00086     PLineJoin = Qt::MiterJoin;
00087     fill_gradient = VGradient(VGradient::linear);
00088     stroke_gradient = VGradient(VGradient::linear);
00089     m_zoomFactor = 1;
00090     layeredMode = true;
00091     imageMode = false;
00092     svgMode = true;
00093     m_matrix = QMatrix();
00094     cairo_surface_t *img = cairo_svg_surface_create(target.toLocal8Bit().constData(), w, h);
00095     m_cr = cairo_create(img);
00096     cairo_save( m_cr );
00097     cairo_set_fill_rule (m_cr, CAIRO_FILL_RULE_EVEN_ODD);
00098     cairo_set_operator(m_cr, CAIRO_OPERATOR_OVER);
00099     cairo_set_tolerance( m_cr, 0.5 );
00100 }
00101 // HAVE_CAIRO
00102 #else
00104 ScPainter::ScPainter( QImage *target, unsigned int w, unsigned int h, double transparency, int blendmode )
00105 {
00106     m_path = QPainterPath();
00107     m_width = w;
00108     m_height= h;
00109     m_stroke = QColor(0,0,0);
00110     m_fill = QColor(0,0,0);
00111     fill_trans = 1.0;
00112     stroke_trans = 1.0;
00113     m_fillRule = true;
00114     fillMode = 1;
00115     LineWidth = 1.0;
00116     m_offset = 0;
00117     m_layerTransparency = transparency;
00118     m_blendMode = blendmode;
00119     m_array.clear();
00120     mf_underline = false;
00121     mf_strikeout = false;
00122     mf_shadow = false;
00123     mf_outlined = false;
00124     PLineEnd = Qt::FlatCap;
00125     PLineJoin = Qt::MiterJoin;
00126     PLineStyle = Qt::SolidLine;
00127     fill_gradient = VGradient(VGradient::linear);
00128     stroke_gradient = VGradient(VGradient::linear);
00129     m_zoomFactor = 1;
00130     layeredMode = true;
00131     imageMode = true;
00132     svgMode = false;
00133     m_image = target;
00134     m_matrix = QMatrix();
00135     painter.begin(m_image);
00136     painter.setRenderHint(QPainter::Antialiasing, true);
00137     painter.setRenderHint(QPainter::SmoothPixmapTransform, true);
00138 }
00139 #endif
00140 
00141 ScPainter::~ScPainter()
00142 {
00143 #ifdef HAVE_CAIRO
00144     cairo_surface_destroy(cairo_get_target(m_cr));
00145     cairo_destroy( m_cr );
00146 #else
00147     painter.end();
00148 #endif
00149 }
00150 
00151 void ScPainter::beginLayer(double transparency, int blendmode, FPointArray *clipArray)
00152 {
00153     layerProp la;
00154     la.blendmode = m_blendMode;
00155     la.tranparency = m_layerTransparency;
00156     m_layerTransparency = transparency;
00157     m_blendMode = blendmode;
00158     la.pushed = false;
00159     la.groupClip.resize(0);
00160     if (clipArray != NULL)
00161         la.groupClip = *clipArray;
00162 #ifdef HAVE_CAIRO
00163     la.data = cairo_get_group_target(m_cr);
00164     cairo_push_group(m_cr);
00165 /*  if (clipArray != NULL)
00166     {
00167         setupPolygon(clipArray);
00168         setClipPath();
00169     } */
00170 #else
00171     la.data = new QImage(m_image->copy());
00172     m_image->fill(qRgba(255, 255, 255, 0));
00173 #endif
00174     la.pushed = true;
00175     Layers.push(la);
00176 }
00177 
00178 void ScPainter::endLayer()
00179 {
00180     layerProp la;
00181     if (Layers.count() == 0)
00182         return;
00183     la = Layers.top();
00184     if (la.pushed)
00185     {
00186         if ((m_blendMode != 0) && (Layers.count() != 0))
00187         {
00188 #ifdef HAVE_CAIRO
00189             cairo_surface_t *tmp = cairo_get_group_target(m_cr);
00190             cairo_surface_t *tmpB = Layers.top().data;
00191             if ((tmp != NULL) && (tmpB != NULL))
00192             {
00193                 if ((cairo_surface_get_type(tmp) == CAIRO_SURFACE_TYPE_IMAGE) && (cairo_surface_get_type(tmpB) == CAIRO_SURFACE_TYPE_IMAGE))
00194                 {
00195                     cairo_surface_flush(tmp);
00196                     int stride = cairo_image_surface_get_stride(tmp);
00197                     unsigned char *s = cairo_image_surface_get_data(tmp);
00198                     unsigned char *d = cairo_image_surface_get_data(tmpB);
00199                     int h = cairo_image_surface_get_height(tmp);
00200                     int w = cairo_image_surface_get_width(tmp);
00201                     uint oldDst = 1;
00202                     uint oldSrc = 2;
00203                     uint newResult = 0;
00204                     bool first = true;
00205                     QRgb *src;
00206                     QRgb *dst;
00207                     uchar src_a, src_r, src_g, src_b, dst_a, dst_r, dst_g, dst_b, new_r, new_g, new_b;
00208                     for( int yi=0; yi < h; ++yi )
00209                     {
00210                         dst = (QRgb*)d;
00211                         src = (QRgb*)s;
00212                         for( int xi=0; xi < w; ++xi )
00213                         {
00214                             src_r = qRed(*src);
00215                             src_g = qGreen(*src);
00216                             src_b = qBlue(*src);
00217                             src_a = qAlpha(*src);
00218                             dst_r = qRed(*dst);
00219                             dst_g = qGreen(*dst);
00220                             dst_b = qBlue(*dst);
00221                             dst_a = qAlpha(*dst);
00222                             if ((src_a > 0) && (dst_a > 0))
00223                             {
00224                                 if (((*dst) != oldDst) || ((*src) != oldSrc) || (first))
00225                                 {
00226                                     if (m_blendMode == 1)
00227                                     {
00228                                         src_r = dst_r  < src_r ? dst_r  : src_r;
00229                                         src_g = dst_g < src_g ? dst_g : src_g;
00230                                         src_b = dst_b < src_b ? dst_b : src_b;
00231                                     }
00232                                     else if (m_blendMode == 2)
00233                                     {
00234                                         src_r = dst_r  < src_r ? src_r : dst_r;
00235                                         src_g = dst_g < src_g ? src_g : dst_g;
00236                                         src_b = dst_b < src_b ? src_b : dst_b;
00237                                     }
00238                                     else if (m_blendMode == 3)
00239                                     {
00240                                         src_r = INT_MULT(src_r, dst_r);
00241                                         src_g = INT_MULT(src_g, dst_g);
00242                                         src_b = INT_MULT(src_b, dst_b);
00243                                     }
00244                                     else if (m_blendMode == 4)
00245                                     {
00246                                         src_r = 255 - ((255-src_r) * (255-dst_r) / 128);
00247                                         src_g = 255 - ((255-src_g) * (255-dst_g) / 128);
00248                                         src_b = 255 - ((255-src_b) * (255-dst_b) / 128);
00249                                     }
00250                                     else if (m_blendMode == 5)
00251                                     {
00252                                         src_r = dst_r < 128 ? src_r * dst_r / 128 : 255 - ((255-src_r) * (255-dst_r) / 128);
00253                                         src_g = dst_g < 128 ? src_g * dst_g / 128 : 255 - ((255-src_g) * (255-dst_g) / 128);
00254                                         src_b = dst_b < 128 ? src_b * dst_b / 128 : 255 - ((255-src_b) * (255-dst_b) / 128);
00255                                     }
00256                                     else if (m_blendMode == 6)
00257                                     {
00258                                         src_r = src_r < 128 ? src_r * dst_r / 128 : 255 - ((255-src_r) * (255-dst_r) / 128);
00259                                         src_g = src_g < 128 ? src_g * dst_g / 128 : 255 - ((255-src_g) * (255-dst_g) / 128);
00260                                         src_b = src_b < 128 ? src_b * dst_b / 128 : 255 - ((255-src_b) * (255-dst_b) / 128);
00261                                     }
00262                                     else if (m_blendMode == 7)
00263                                     {
00264                                         float s_r = (255 - src_r) / 255.0;
00265                                         float s_g = (255 - src_g) / 255.0;
00266                                         float s_b = (255 - src_b) / 255.0;
00267                                         float d_r = (255 - dst_r) / 255.0;
00268                                         float d_g = (255 - dst_g) / 255.0;
00269                                         float d_b = (255 - dst_b) / 255.0;
00270                                         float dzr = d_r > 0.25 ? sqrt(d_r) : ((16 * d_r - 12) * d_r + 4) * d_r;
00271                                         float dzg = d_g > 0.25 ? sqrt(d_g) : ((16 * d_g - 12) * d_g + 4) * d_g;
00272                                         float dzb = d_b > 0.25 ? sqrt(d_b) : ((16 * d_b - 12) * d_b + 4) * d_b;
00273                                         s_r = s_r <= 0.5 ? d_r - (1 - 2 * s_r) * d_r * (1 - d_r) : d_r + (2 * s_r - 1) * (dzr  - d_r);
00274                                         s_g = s_g <= 0.5 ? d_g - (1 - 2 * s_g) * d_g * (1 - d_g) : d_g + (2 * s_g - 1) * (dzg  - d_g);
00275                                         s_b = s_b <= 0.5 ? d_b - (1 - 2 * s_b) * d_b * (1 - d_b) : d_b + (2 * s_b - 1) * (dzb  - d_b);
00276                                         src_r = 255 - qRound(s_r * 255);
00277                                         src_g = 255 - qRound(s_g * 255);
00278                                         src_b = 255 - qRound(s_b * 255);
00279                                     }
00280                                     else if (m_blendMode == 8)
00281                                     {
00282                                         src_r = dst_r > src_r ? dst_r - src_r : src_r - dst_r;
00283                                         src_g = dst_g > src_g ? dst_g - src_g : src_g - dst_g;
00284                                         src_b = dst_b > src_b ? dst_b - src_b : src_b - dst_b;
00285                                     }
00286                                     else if (m_blendMode == 9)
00287                                     {
00288                                         src_r = dst_r + src_r - src_r * dst_r / 128;
00289                                         src_g = dst_g + src_g - src_g * dst_g / 128;
00290                                         src_b = dst_b + src_b - src_b * dst_b / 128;
00291                                     }
00292                                     else if (m_blendMode == 10)
00293                                     {
00294                                         src_r = src_r == 255 ? qMin(255, dst_r * 256) : qMin(255, ((dst_r * 256) / (255-src_r)));
00295                                         src_g = src_g == 255 ? qMin(255, dst_g * 256) : qMin(255, ((dst_g * 256) / (255-src_g)));
00296                                         src_b = src_b == 255 ? qMin(255, dst_b * 256) : qMin(255, ((dst_b * 256) / (255-src_b)));
00297                                     }
00298                                     else if (m_blendMode == 11)
00299                                     {
00300                                         src_r = qMax<uchar>(1, src_r);
00301                                         src_g = qMax<uchar>(1, src_g);
00302                                         src_b = qMax<uchar>(1, src_b);
00303                                         src_r = static_cast<int>(255 - (((255-dst_r) * 256) / src_r)) < 0 ? 0 : 255 - (((255-dst_r) * 256) / src_r);
00304                                         src_g = static_cast<int>(255 - (((255-dst_g) * 256) / src_g)) < 0 ? 0 : 255 - (((255-dst_g) * 256) / src_g);
00305                                         src_b = static_cast<int>(255 - (((255-dst_b) * 256) / src_b)) < 0 ? 0 : 255 - (((255-dst_b) * 256) / src_b);
00306                                     }
00307                                     else if (m_blendMode == 12)
00308                                     {
00309                                         new_r = dst_r;
00310                                         new_g = dst_g;
00311                                         new_b = dst_b;
00312                                         RGBTOHLS(src_r, src_g, src_b);
00313                                         RGBTOHLS(new_r, new_g, new_b);
00314                                         new_r = src_r;
00315                                         HLSTORGB(new_r, new_g, new_b);
00316                                         src_r = new_r;
00317                                         src_g = new_g;
00318                                         src_b = new_b;
00319                                     }
00320                                     else if (m_blendMode == 13)
00321                                     {
00322                                         new_r = dst_r;
00323                                         new_g = dst_g;
00324                                         new_b = dst_b;
00325                                         RGBTOHLS(src_r, src_g, src_b);
00326                                         RGBTOHLS(new_r, new_g, new_b);
00327                                         new_b = src_b;
00328                                         HLSTORGB(new_r, new_g, new_b);
00329                                         src_r = new_r;
00330                                         src_g = new_g;
00331                                         src_b = new_b;
00332                                     }
00333                                     else if (m_blendMode == 14)
00334                                     {
00335                                         new_r = src_r;
00336                                         new_g = src_g;
00337                                         new_b = src_b;
00338                                         setLum(new_r, new_g, new_b, Lum(dst_r, dst_g, dst_b));
00339                                         src_r = new_r;
00340                                         src_g = new_g;
00341                                         src_b = new_b;
00342                                     }
00343                                     else if (m_blendMode == 15)
00344                                     {
00345                                         new_r = dst_r;
00346                                         new_g = dst_g;
00347                                         new_b = dst_b;
00348                                         setLum(new_r, new_g, new_b, Lum(src_r, src_g, src_b));
00349                                         src_r = new_r;
00350                                         src_g = new_g;
00351                                         src_b = new_b;
00352                                     }
00353                                     newResult = qRgba(src_r, src_g, src_b, src_a);
00354                                     oldDst = (*dst);
00355                                     oldSrc = (*src);
00356                                     first = false;
00357                                 }
00358                                 (*src) = newResult;
00359                             }
00360                             src++;
00361                             dst++;
00362                         }
00363                         s += stride;
00364                         d += stride;
00365                     }
00366                     cairo_surface_mark_dirty(tmp);
00367                 }
00368             }
00369 #else
00370             int h = m_image->height();
00371             int w = m_image->width();
00372             uint oldDst = 1;
00373             uint oldSrc = 2;
00374             uint newResult = 0;
00375             bool first = true;
00376             QRgb *src;
00377             QRgb *dst;
00378             uchar src_a, src_r, src_g, src_b, dst_a, dst_r, dst_g, dst_b, new_r, new_g, new_b;
00379             for( int yi = 0; yi < h; ++yi )
00380             {
00381                 dst = (QRgb*)la.data->scanLine(yi);
00382                 src = (QRgb*)m_image->scanLine(yi);
00383                 for( int xi=0; xi < w; ++xi )
00384                 {
00385                     src_r = qRed(*src);
00386                     src_g = qGreen(*src);
00387                     src_b = qBlue(*src);
00388                     src_a = qAlpha(*src);
00389                     dst_r = qRed(*dst);
00390                     dst_g = qGreen(*dst);
00391                     dst_b = qBlue(*dst);
00392                     dst_a = qAlpha(*dst);
00393                     if ((src_a > 0) && (dst_a > 0))
00394                     {
00395                         if (((*dst) != oldDst) || ((*src) != oldSrc) || (first))
00396                         {
00397                             if (m_blendMode == 1)
00398                             {
00399                                 src_r = dst_r  < src_r ? dst_r  : src_r;
00400                                 src_g = dst_g < src_g ? dst_g : src_g;
00401                                 src_b = dst_b < src_b ? dst_b : src_b;
00402                             }
00403                             else if (m_blendMode == 2)
00404                             {
00405                                 src_r = dst_r  < src_r ? src_r : dst_r;
00406                                 src_g = dst_g < src_g ? src_g : dst_g;
00407                                 src_b = dst_b < src_b ? src_b : dst_b;
00408                             }
00409                             else if (m_blendMode == 3)
00410                             {
00411                                 src_r = INT_MULT(src_r, dst_r);
00412                                 src_g = INT_MULT(src_g, dst_g);
00413                                 src_b = INT_MULT(src_b, dst_b);
00414                             }
00415                             else if (m_blendMode == 4)
00416                             {
00417                                 src_r = 255 - ((255-src_r) * (255-dst_r) / 128);
00418                                 src_g = 255 - ((255-src_g) * (255-dst_g) / 128);
00419                                 src_b = 255 - ((255-src_b) * (255-dst_b) / 128);
00420                             }
00421                             else if (m_blendMode == 5)
00422                             {
00423                                 src_r = dst_r < 128 ? src_r * dst_r / 128 : 255 - ((255-src_r) * (255-dst_r) / 128);
00424                                 src_g = dst_g < 128 ? src_g * dst_g / 128 : 255 - ((255-src_g) * (255-dst_g) / 128);
00425                                 src_b = dst_b < 128 ? src_b * dst_b / 128 : 255 - ((255-src_b) * (255-dst_b) / 128);
00426                             }
00427                             else if (m_blendMode == 6)
00428                             {
00429                                 src_r = src_r < 128 ? src_r * dst_r / 128 : 255 - ((255-src_r) * (255-dst_r) / 128);
00430                                 src_g = src_g < 128 ? src_g * dst_g / 128 : 255 - ((255-src_g) * (255-dst_g) / 128);
00431                                 src_b = src_b < 128 ? src_b * dst_b / 128 : 255 - ((255-src_b) * (255-dst_b) / 128);
00432                             }
00433                             else if (m_blendMode == 7)
00434                             {
00435                                 float s_r = (255 - src_r) / 255.0;
00436                                 float s_g = (255 - src_g) / 255.0;
00437                                 float s_b = (255 - src_b) / 255.0;
00438                                 float d_r = (255 - dst_r) / 255.0;
00439                                 float d_g = (255 - dst_g) / 255.0;
00440                                 float d_b = (255 - dst_b) / 255.0;
00441                                 float dzr = d_r > 0.25 ? sqrt(d_r) : ((16 * d_r - 12) * d_r + 4) * d_r;
00442                                 float dzg = d_g > 0.25 ? sqrt(d_g) : ((16 * d_g - 12) * d_g + 4) * d_g;
00443                                 float dzb = d_b > 0.25 ? sqrt(d_b) : ((16 * d_b - 12) * d_b + 4) * d_b;
00444                                 s_r = s_r <= 0.5 ? d_r - (1 - 2 * s_r) * d_r * (1 - d_r) : d_r + (2 * s_r - 1) * (dzr  - d_r);
00445                                 s_g = s_g <= 0.5 ? d_g - (1 - 2 * s_g) * d_g * (1 - d_g) : d_g + (2 * s_g - 1) * (dzg  - d_g);
00446                                 s_b = s_b <= 0.5 ? d_b - (1 - 2 * s_b) * d_b * (1 - d_b) : d_b + (2 * s_b - 1) * (dzb  - d_b);
00447                                 src_r = 255 - qRound(s_r * 255);
00448                                 src_g = 255 - qRound(s_g * 255);
00449                                 src_b = 255 - qRound(s_b * 255);
00450                             }
00451                             else if (m_blendMode == 8)
00452                             {
00453                                 src_r = dst_r > src_r ? dst_r - src_r : src_r - dst_r;
00454                                 src_g = dst_g > src_g ? dst_g - src_g : src_g - dst_g;
00455                                 src_b = dst_b > src_b ? dst_b - src_b : src_b - dst_b;
00456                             }
00457                             else if (m_blendMode == 9)
00458                             {
00459                                 src_r = dst_r + src_r - src_r * dst_r / 128;
00460                                 src_g = dst_g + src_g - src_g * dst_g / 128;
00461                                 src_b = dst_b + src_b - src_b * dst_b / 128;
00462                             }
00463                             else if (m_blendMode == 10)
00464                             {
00465                                 src_r = src_r == 255 ? qMin(255, dst_r * 256) : qMin(255, ((dst_r * 256) / (255-src_r)));
00466                                 src_g = src_g == 255 ? qMin(255, dst_g * 256) : qMin(255, ((dst_g * 256) / (255-src_g)));
00467                                 src_b = src_b == 255 ? qMin(255, dst_b * 256) : qMin(255, ((dst_b * 256) / (255-src_b)));
00468                             }
00469                             else if (m_blendMode == 11)
00470                             {
00471                                 src_r = qMax<uchar>(1, src_r);
00472                                 src_g = qMax<uchar>(1, src_g);
00473                                 src_b = qMax<uchar>(1, src_b);
00474                                 src_r = static_cast<int>(255 - (((255-dst_r) * 256) / src_r)) < 0 ? 0 : 255 - (((255-dst_r) * 256) / src_r);
00475                                 src_g = static_cast<int>(255 - (((255-dst_g) * 256) / src_g)) < 0 ? 0 : 255 - (((255-dst_g) * 256) / src_g);
00476                                 src_b = static_cast<int>(255 - (((255-dst_b) * 256) / src_b)) < 0 ? 0 : 255 - (((255-dst_b) * 256) / src_b);
00477                             }
00478                             else if (m_blendMode == 12)
00479                             {
00480                                 new_r = dst_r;
00481                                 new_g = dst_g;
00482                                 new_b = dst_b;
00483                                 RGBTOHLS(src_r, src_g, src_b);
00484                                 RGBTOHLS(new_r, new_g, new_b);
00485                                 new_r = src_r;
00486                                 HLSTORGB(new_r, new_g, new_b);
00487                                 src_r = new_r;
00488                                 src_g = new_g;
00489                                 src_b = new_b;
00490                             }
00491                             else if (m_blendMode == 13)
00492                             {
00493                                 new_r = dst_r;
00494                                 new_g = dst_g;
00495                                 new_b = dst_b;
00496                                 RGBTOHLS(src_r, src_g, src_b);
00497                                 RGBTOHLS(new_r, new_g, new_b);
00498                                 new_b = src_b;
00499                                 HLSTORGB(new_r, new_g, new_b);
00500                                 src_r = new_r;
00501                                 src_g = new_g;
00502                                 src_b = new_b;
00503                             }
00504                             else if (m_blendMode == 14)
00505                             {
00506                                 new_r = src_r;
00507                                 new_g = src_g;
00508                                 new_b = src_b;
00509                                 setLum(new_r, new_g, new_b, Lum(dst_r, dst_g, dst_b));
00510                                 src_r = new_r;
00511                                 src_g = new_g;
00512                                 src_b = new_b;
00513                             }
00514                             else if (m_blendMode == 15)
00515                             {
00516                                 new_r = dst_r;
00517                                 new_g = dst_g;
00518                                 new_b = dst_b;
00519                                 setLum(new_r, new_g, new_b, Lum(src_r, src_g, src_b));
00520                                 src_r = new_r;
00521                                 src_g = new_g;
00522                                 src_b = new_b;
00523                             }
00524                             newResult = qRgba(src_r, src_g, src_b, src_a);
00525                             oldDst = (*dst);
00526                             oldSrc = (*src);
00527                             first = false;
00528                         }
00529                         (*src) = newResult;
00530                     }
00531                     src++;
00532                     dst++;
00533                 }
00534             }
00535 #endif
00536         }
00537     }
00538     la = Layers.pop();
00539     if (la.pushed)
00540     {
00541 #ifdef HAVE_CAIRO
00542         cairo_pop_group_to_source (m_cr);
00543         if (la.groupClip.size() != 0)
00544         {
00545             setupPolygon(&la.groupClip);
00546             setClipPath();
00547         }
00548         if (m_blendMode == 0)
00549         {
00550             cairo_set_operator(m_cr, CAIRO_OPERATOR_OVER);
00551             cairo_paint_with_alpha (m_cr, m_layerTransparency);
00552         }
00553         else
00554         {
00555             cairo_set_operator(m_cr, CAIRO_OPERATOR_DEST_OUT);
00556             cairo_paint_with_alpha (m_cr, m_layerTransparency);
00557             cairo_set_operator(m_cr, CAIRO_OPERATOR_ADD);
00558             cairo_paint_with_alpha (m_cr, m_layerTransparency);
00559         }
00560         cairo_set_operator(m_cr, CAIRO_OPERATOR_OVER);
00561 #else
00562         QRgb *src;
00563         QRgb *dst;
00564         QRgb tmp;
00565         int h = m_image->height();
00566         int w = m_image->width();
00567         for( int yi = 0; yi < h; ++yi )
00568         {
00569             src = (QRgb*)la.data->scanLine(yi);
00570             dst = (QRgb*)m_image->scanLine(yi);
00571             for( int xi=0; xi < w; ++xi )
00572             {
00573                 tmp = *dst;
00574                 *dst = *src;
00575                 *src = tmp;
00576                 dst++;
00577                 src++;
00578             }
00579         }
00580         painter.save();
00581         if (la.groupClip.size() != 0)
00582         {
00583             setupPolygon(&la.groupClip);
00584             setClipPath();
00585         }
00586         painter.resetMatrix();
00587         painter.setOpacity(m_layerTransparency);
00588         painter.drawImage(0, 0, *la.data);
00589         painter.restore();
00590         delete la.data;
00591 #endif
00592     }
00593     m_layerTransparency = la.tranparency;
00594     m_blendMode = la.blendmode;
00595 }
00596 
00597 void ScPainter::begin()
00598 {
00599 }
00600 
00601 void ScPainter::end()
00602 {
00603 #ifdef HAVE_CAIRO
00604     if (svgMode)
00605         cairo_show_page (m_cr);
00606     if (layeredMode)
00607     {
00608         cairo_surface_flush(cairo_get_target(m_cr));
00609         cairo_restore( m_cr );
00610         return;
00611     }
00612 #endif
00613 }
00614 
00615 void ScPainter::clear()
00616 {
00617 #ifdef HAVE_CAIRO
00618     if (imageMode)
00619         m_image->fill( qRgba(255, 255, 255, 255) );
00620 #else
00621     m_image->fill(qRgba(255, 255, 255, 255));
00622 #endif
00623 }
00624 
00625 void ScPainter::clear( const QColor &c )
00626 {
00627     QRgb cs = c.rgb();
00628 #ifdef HAVE_CAIRO
00629     if (imageMode)
00630         m_image->fill( qRgba(qRed(cs), qGreen(cs), qBlue(cs), qAlpha(cs)) );
00631 #else
00632     m_image->fill(qRgba(qRed(cs), qGreen(cs), qBlue(cs), qAlpha(cs)));
00633 #endif
00634 }
00635 
00636 const QMatrix ScPainter::worldMatrix()
00637 {
00638 #ifdef HAVE_CAIRO
00639     cairo_matrix_t matrix;
00640     cairo_get_matrix(m_cr, &matrix);
00641     QMatrix mat;
00642     mat.setMatrix ( matrix.xx, matrix.yx, matrix.xy, matrix.yy, matrix.x0, matrix.y0 );
00643     return mat;
00644 #else
00645     return painter.worldMatrix();
00646 #endif
00647 }
00648 
00649 void ScPainter::setWorldMatrix( const QMatrix &mat )
00650 {
00651 #ifdef HAVE_CAIRO
00652     cairo_matrix_t matrix;
00653     cairo_matrix_init(&matrix, mat.m11(), mat.m12(), mat.m21(), mat.m22(), mat.dx(), mat.dy());
00654     cairo_set_matrix(m_cr, &matrix);
00655 #else
00656     painter.setWorldMatrix(mat);
00657 #endif
00658 }
00659 
00660 void ScPainter::setAntialiasing(bool enable)
00661 {
00662 #ifdef HAVE_CAIRO
00663     if (enable)
00664         cairo_set_antialias(m_cr, CAIRO_ANTIALIAS_DEFAULT);
00665     else
00666         cairo_set_antialias(m_cr, CAIRO_ANTIALIAS_NONE);
00667 #else
00668     painter.setRenderHint(QPainter::Antialiasing, enable);
00669 #endif
00670 }
00671 
00672 void ScPainter::setZoomFactor( double zoomFactor )
00673 {
00674     m_zoomFactor = zoomFactor;
00675 #ifdef HAVE_CAIRO
00676     cairo_scale (m_cr, m_zoomFactor, m_zoomFactor);
00677 #else
00678     painter.scale(m_zoomFactor, m_zoomFactor);
00679 #endif
00680 }
00681 
00682 void ScPainter::translate( double x, double y )
00683 {
00684 #ifdef HAVE_CAIRO
00685     cairo_translate (m_cr, x, y);
00686 #else
00687     painter.translate(x, y);
00688 #endif
00689 }
00690 
00691 void ScPainter::rotate( double r )
00692 {
00693 #ifdef HAVE_CAIRO
00694     cairo_rotate (m_cr, r * 3.1415927 / 180.0);
00695 #else
00696     painter.rotate(r);
00697 #endif
00698 }
00699 
00700 void ScPainter::scale( double x, double y )
00701 {
00702 #ifdef HAVE_CAIRO
00703     cairo_scale (m_cr, x, y);
00704 #else
00705     painter.scale(x, y);
00706 #endif
00707 }
00708 
00709 void ScPainter::moveTo( const double &x, const double &y )
00710 {
00711 #ifdef HAVE_CAIRO
00712     cairo_move_to( m_cr, x, y);
00713 #else
00714     m_path.moveTo(x, y);
00715 #endif
00716 }
00717 
00718 void
00719 ScPainter::lineTo( const double &x, const double &y )
00720 {
00721 #ifdef HAVE_CAIRO
00722     cairo_line_to( m_cr, x, y);
00723 #else
00724     m_path.lineTo(x, y);
00725 #endif
00726 }
00727 
00728 void ScPainter::curveTo( FPoint p1, FPoint p2, FPoint p3 )
00729 {
00730 #ifdef HAVE_CAIRO
00731     cairo_curve_to(m_cr, p1.x(), p1.y(), p2.x(), p2.y(), p3.x(), p3.y());
00732 #else
00733     m_path.cubicTo(p1.x(), p1.y(), p2.x(), p2.y(), p3.x(), p3.y());
00734 #endif
00735 }
00736 
00737 void ScPainter::newPath()
00738 {
00739 #ifdef HAVE_CAIRO
00740     cairo_new_path( m_cr );
00741 #else
00742     m_path = QPainterPath();
00743 #endif
00744 }
00745 
00746 void ScPainter::closePath()
00747 {
00748 #ifdef HAVE_CAIRO
00749     cairo_close_path( m_cr );
00750 #else
00751     m_path.closeSubpath();
00752 #endif
00753 }
00754 
00755 void ScPainter::setFillRule( bool fillRule )
00756 {
00757     m_fillRule = fillRule;
00758 }
00759 
00760 void ScPainter::setFillMode( int fill )
00761 {
00762     fillMode = fill;
00763 }
00764 
00765 void ScPainter::setGradient(VGradient::VGradientType mode, FPoint orig, FPoint vec, FPoint foc)
00766 {
00767     fill_gradient.setType(mode);
00768     fill_gradient.setOrigin(orig);
00769     fill_gradient.setVector(vec);
00770     fill_gradient.setFocalPoint(foc);
00771 }
00772 
00773 void ScPainter::fillTextPath()
00774 {
00775     drawVPath( 0 );
00776 }
00777 
00778 void ScPainter::strokeTextPath()
00779 {
00780     if( LineWidth == 0 )
00781         return;
00782     drawVPath( 1 );
00783 }
00784 
00785 void ScPainter::fillPath()
00786 {
00787     if( fillMode != 0)
00788         drawVPath( 0 );
00789 }
00790 
00791 void ScPainter::strokePath()
00792 {
00793     if( LineWidth == 0 )
00794         return;
00795     drawVPath( 1 );
00796 }
00797 
00798 QColor ScPainter::pen()
00799 {
00800     return m_stroke;
00801 }
00802 
00803 QColor ScPainter::brush()
00804 {
00805     return m_fill;
00806 }
00807 
00808 void ScPainter::setPen( const QColor &c )
00809 {
00810     m_stroke = c;
00811 }
00812 
00813 void ScPainter::setPen( const QColor &c, double w, Qt::PenStyle st, Qt::PenCapStyle ca, Qt::PenJoinStyle jo )
00814 {
00815     m_stroke = c;
00816     LineWidth = w;
00817     PLineEnd = ca;
00818     PLineJoin = jo;
00819 #ifdef HAVE_CAIRO
00820     m_offset = 0;
00821     getDashArray(st, w, m_array);
00822 #else
00823     PLineStyle = st;
00824 #endif
00825 }
00826 
00827 void ScPainter::setLineWidth( double w )
00828 {
00829     LineWidth = w;
00830 }
00831 
00832 void ScPainter::setPenOpacity( double op )
00833 {
00834     stroke_trans = op;
00835 }
00836 
00837 
00838 void ScPainter::setDash(const QList<double>& array, double ofs)
00839 {
00840     m_array = array;
00841     m_offset = ofs;
00842 }
00843 
00844 void ScPainter::setBrush( const QColor &c )
00845 {
00846     m_fill = c;
00847 }
00848 
00849 void ScPainter::setBrushOpacity( double op )
00850 {
00851     fill_trans = op;
00852 }
00853 
00854 void ScPainter::setOpacity( double op )
00855 {
00856     fill_trans = op;
00857     stroke_trans = op;
00858 }
00859 
00860 void ScPainter::setFont( const QFont &f)
00861 {
00862     m_font = f;
00863 }
00864 
00865 QFont ScPainter::font()
00866 {
00867     return m_font;
00868 }
00869 
00870 void ScPainter::save()
00871 {
00872 #ifdef HAVE_CAIRO
00873     cairo_save( m_cr );
00874 #else
00875     painter.save();
00876 #endif
00877 }
00878 
00879 void ScPainter::restore()
00880 {
00881 #ifdef HAVE_CAIRO
00882     cairo_restore( m_cr );
00883 #else
00884     painter.restore();
00885 #endif
00886 }
00887 
00888 void ScPainter::setRasterOp( int   )
00889 {
00890 }
00891 
00892 void ScPainter::setPattern(ScPattern *pattern, double scaleX, double scaleY, double offsetX, double offsetY, double rotation)
00893 {
00894     m_pattern = pattern;
00895     patternScaleX = scaleX / 100.0;
00896     patternScaleY = scaleY / 100.0;
00897     patternOffsetX = offsetX;
00898     patternOffsetY = offsetY;
00899     patternRotation = rotation;
00900 }
00901 
00902 #ifdef HAVE_CAIRO
00903 void ScPainter::drawVPath( int mode )
00904 {
00905     cairo_save( m_cr );
00906     if (mode == 0)
00907     {
00908         if( m_fillRule )
00909             cairo_set_fill_rule (m_cr, CAIRO_FILL_RULE_EVEN_ODD);
00910         else
00911             cairo_set_fill_rule (m_cr, CAIRO_FILL_RULE_WINDING);
00912         if (fillMode == 1)
00913         {
00914             double r, g, b;
00915             m_fill.getRgbF(&r, &g, &b);
00916             cairo_set_source_rgba( m_cr, r, g, b, fill_trans );
00917             if (fill_trans != 1.0)
00918                 cairo_set_operator(m_cr, CAIRO_OPERATOR_OVER);
00919             else
00920                 cairo_set_operator(m_cr, CAIRO_OPERATOR_SOURCE);
00921             cairo_fill_preserve( m_cr );
00922         }
00923         else if (fillMode == 2)
00924         {
00925             cairo_pattern_t *pat;
00926             double x1 = fill_gradient.origin().x();
00927             double y1 = fill_gradient.origin().y();
00928             double x2 = fill_gradient.vector().x();
00929             double y2 = fill_gradient.vector().y();
00930             if (fill_gradient.type() == VGradient::linear)
00931                 pat = cairo_pattern_create_linear (x1, y1,  x2, y2);
00932             else
00933                 pat = cairo_pattern_create_radial (x1, y1, 0.1, x1, y1, sqrt(pow(x2 - x1, 2) + pow(y2 - y1,2)));
00934             QList<VColorStop*> colorStops = fill_gradient.colorStops();
00935             QColor qStopColor;
00936             for( int offset = 0 ; offset < colorStops.count() ; offset++ )
00937             {
00938                 qStopColor = colorStops[ offset ]->color;
00939                 int h, s, v, sneu, vneu;
00940                 int shad = colorStops[offset]->shade;
00941                 qStopColor.getHsv(&h, &s, &v);
00942                 sneu = s * shad / 100;
00943                 vneu = 255 - ((255 - v) * shad / 100);
00944                 qStopColor.setHsv(h, sneu, vneu);
00945                 double a = colorStops[offset]->opacity;
00946                 double r, g, b;
00947                 qStopColor.getRgbF(&r, &g, &b);
00948                 cairo_pattern_add_color_stop_rgba (pat, colorStops[ offset ]->rampPoint, r, g, b, a);
00949             }
00950             cairo_set_source (m_cr, pat);
00951             cairo_clip_preserve (m_cr);
00952             cairo_paint_with_alpha (m_cr, fill_trans);
00953             cairo_pattern_destroy (pat);
00954         }
00955         else if (fillMode == 3)
00956         {
00957             cairo_surface_t *image2 = cairo_image_surface_create_for_data ((uchar*)m_pattern->getPattern()->bits(), CAIRO_FORMAT_ARGB32, m_pattern->getPattern()->width(), m_pattern->getPattern()->height(), m_pattern->getPattern()->width()*4);
00958             cairo_pattern_t *m_pat = cairo_pattern_create_for_surface(image2);
00959             cairo_pattern_set_extend(m_pat, CAIRO_EXTEND_REPEAT);
00960             cairo_pattern_set_filter(m_pat, CAIRO_FILTER_BEST);
00961             cairo_matrix_t matrix;
00962             QMatrix qmatrix;
00963             qmatrix.scale(m_zoomFactor, m_zoomFactor);
00964             qmatrix.translate(patternOffsetX, patternOffsetY);
00965             qmatrix.rotate(patternRotation);
00966             qmatrix.scale(patternScaleX, patternScaleY);
00967             cairo_matrix_init(&matrix, qmatrix.m11(), qmatrix.m12(), qmatrix.m21(), qmatrix.m22(), qmatrix.dx(), qmatrix.dy());
00968             cairo_matrix_invert(&matrix);
00969             cairo_pattern_set_matrix (m_pat, &matrix);
00970             cairo_set_source (m_cr, m_pat);
00971             cairo_clip_preserve (m_cr);
00972             cairo_paint_with_alpha (m_cr, fill_trans);
00973             cairo_pattern_destroy (m_pat);
00974             cairo_surface_destroy (image2);
00975         }
00976     }
00977     else
00978     {
00979         double *dashes = NULL;
00980         cairo_set_line_width( m_cr, LineWidth );
00981         if( m_array.count() > 0 )
00982         {
00983             dashes = new double[ m_array.count() ];
00984             for( int i = 0; i < m_array.count();++ i )
00985             {
00986                 dashes[i] = static_cast<double>(m_array[i]);
00987             }
00988             cairo_set_dash( m_cr, dashes, m_array.count(), static_cast<double>(m_offset));
00989         }
00990         else
00991             cairo_set_dash( m_cr, NULL, 0, 0 );
00992         double r, g, b;
00993         m_stroke.getRgbF(&r, &g, &b);
00994         cairo_set_source_rgba( m_cr, r, g, b, stroke_trans );
00995         if (stroke_trans != 1.0)
00996             cairo_set_operator(m_cr, CAIRO_OPERATOR_OVER);
00997         else
00998             cairo_set_operator(m_cr, CAIRO_OPERATOR_SOURCE);
00999         if( PLineEnd == Qt::RoundCap )
01000             cairo_set_line_cap (m_cr, CAIRO_LINE_CAP_ROUND);
01001         else if( PLineEnd == Qt::SquareCap )
01002             cairo_set_line_cap (m_cr, CAIRO_LINE_CAP_SQUARE);
01003         else if( PLineEnd == Qt::FlatCap )
01004             cairo_set_line_cap (m_cr, CAIRO_LINE_CAP_BUTT);
01005         if( PLineJoin == Qt::RoundJoin )
01006             cairo_set_line_join( m_cr, CAIRO_LINE_JOIN_ROUND );
01007         else if( PLineJoin == Qt::BevelJoin )
01008             cairo_set_line_join( m_cr, CAIRO_LINE_JOIN_BEVEL );
01009         else if( PLineJoin == Qt::MiterJoin )
01010             cairo_set_line_join( m_cr, CAIRO_LINE_JOIN_MITER );
01011         cairo_stroke_preserve( m_cr );
01012         if( m_array.count() > 0 )
01013             delete [] dashes;
01014     }
01015     cairo_set_operator(m_cr, CAIRO_OPERATOR_OVER);
01016     cairo_restore( m_cr );
01017 }
01018 #else
01019     // not HAVE_CAIRO
01020 void ScPainter::drawVPath(int mode)
01021 {
01022     painter.save();
01023     if (mode == 0)
01024     {
01025         if( m_fillRule )
01026             m_path.setFillRule(Qt::OddEvenFill);
01027         else
01028             m_path.setFillRule(Qt::WindingFill);
01029         if (fillMode == 1)
01030         {
01031             QColor paint = m_fill;
01032             paint.setAlphaF(fill_trans);
01033             painter.fillPath(m_path, paint);
01034         }
01035         else if (fillMode == 2)
01036         {
01037             QGradient pat;
01038             double x1 = fill_gradient.origin().x();
01039             double y1 = fill_gradient.origin().y();
01040             double x2 = fill_gradient.vector().x();
01041             double y2 = fill_gradient.vector().y();
01042             if (fill_gradient.type() == VGradient::linear)
01043                 pat = QLinearGradient(x1, y1,  x2, y2);
01044             else
01045                 pat = QRadialGradient(x1, y1, sqrt(pow(x2 - x1, 2) + pow(y2 - y1,2)), x1, y1);
01046             QList<VColorStop*> colorStops = fill_gradient.colorStops();
01047             QColor qStopColor;
01048             for( int offset = 0 ; offset < colorStops.count() ; offset++ )
01049             {
01050                 qStopColor = colorStops[ offset ]->color;
01051                 int h, s, v, sneu, vneu;
01052                 int shad = colorStops[offset]->shade;
01053                 qStopColor.getHsv(&h, &s, &v);
01054                 sneu = s * shad / 100;
01055                 vneu = 255 - ((255 - v) * shad / 100);
01056                 qStopColor.setHsv(h, sneu, vneu);
01057                 qStopColor.setAlphaF(colorStops[offset]->opacity);
01058                 pat.setColorAt(colorStops[ offset ]->rampPoint, qStopColor);
01059             }
01060             painter.setOpacity(fill_trans);
01061             painter.fillPath(m_path, pat);
01062         }
01063         else if (fillMode == 3)
01064         {
01065             QMatrix qmatrix;
01066             qmatrix.translate(patternOffsetX, patternOffsetY);
01067             qmatrix.rotate(patternRotation);
01068             qmatrix.scale(patternScaleX, patternScaleY);
01069             QBrush brush = QBrush(*m_pattern->getPattern());
01070             brush.setMatrix(qmatrix);
01071             painter.rotate(0.0001); // hack to get Qt-4's strange pattern rendering working
01072             painter.setOpacity(fill_trans);
01073             painter.fillPath(m_path, brush);
01074         }
01075     }
01076     else
01077     {
01078         QColor paint = m_stroke;
01079         paint.setAlphaF(stroke_trans);
01080         QPen pen;
01081         if( m_array.count() == 0 )
01082         {
01083             if (PLineStyle == Qt::SolidLine)
01084                 pen = QPen(paint, LineWidth, PLineStyle, PLineEnd, PLineJoin);