00001
00002
00003
00004
00005
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
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
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
00166
00167
00168
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
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);
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);