Back to index

scribus-ng  1.3.4.dfsg+svn20071115
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 /* This file is part of the KDE project.
00008    Copyright (C) 2001, 2002, 2003 The Karbon Developers
00009 
00010    This library is free software; you can redistribute it and/or
00011    modify it under the terms of the GNU Library General Public
00012    License as published by the Free Software Foundation; either
00013    version 2 of the License, or (at your option) any later version.
00014 
00015    This library is distributed in the hope that it will be useful,
00016    but WITHOUT ANY WARRANTY; without even the implied warranty of
00017    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018    Library General Public License for more details.
00019 
00020    You should have received a copy of the GNU Library General Public License
00021    along with this library; see the file COPYING.LIB.  If not, write to
00022    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00023    Boston, MA 02111-1307, USA.
00024 */
00025 /* Adapted for Scribus 22.08.2003 by Franz Schmid */
00026 // kopainter/libart wrapper
00027 
00028 #include <qpaintdevice.h>
00029 #include <qpixmap.h>
00030 #include <qpointarray.h>
00031 #include <qimage.h>
00032 
00033 #include "scpainter.h"
00034 
00035 #ifdef HAVE_CAIRO
00036        #include <cairo.h>
00037        #include "colorutil.h"
00038        #if defined(_WIN32)
00039        #include <cairo-win32.h>
00040        #elif defined(Q_WS_X11)
00041        #include <cairo-xlib.h>
00042        #elif defined(Q_WS_MAC)
00043 //     #include <cairo-quartz.h>
00044        #endif
00045 // #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 1, 6)
00046        #include <cairo-svg.h>
00047 // #endif
00048 #else
00049 // not HAVE_CAIRO
00050 #include <libart_lgpl/art_vpath.h>
00051 #include <libart_lgpl/art_bpath.h>
00052 #include <libart_lgpl/art_vpath_bpath.h>
00053 #include <libart_lgpl/art_svp_vpath.h>
00054 #include <libart_lgpl/art_svp_vpath_stroke.h>
00055 #include <libart_lgpl/art_svp.h>
00056 #include <libart_lgpl/art_svp_ops.h>
00057 #include <libart_lgpl/art_affine.h>
00058 #include <libart_lgpl/art_svp_intersect.h>
00059 #include <libart_lgpl/art_rect_svp.h>
00060 #include <libart_lgpl/art_pathcode.h>
00061 #include <libart_lgpl/art_vpath_dash.h>
00062 #include <libart_lgpl/art_render_svp.h>
00063 #include <libart_lgpl/art_vpath_svp.h>
00064 #include "libart/art_render_misc.h"
00065 #include "libart/art_rgb_svp.h"
00066 #include "libart/art_render_pattern.h"
00067 #include "libart/art_kmisc.h"
00068 #define INITIAL_ALLOC       300
00069 #define ALLOC_INCREMENT     100
00070 #endif
00071 
00072 #if defined(Q_WS_X11) && defined(SC_USE_PIXBUF)
00073 #include <X11/Xlib.h>
00074 #include "pixbuf/gdk-pixbuf-xlibrgb.h"
00075 #endif
00076 
00077 #if defined(_WIN32) && defined(SC_USE_GDI)
00078 #include <windows.h>
00079 #endif
00080 
00081 #if defined(Q_WS_MAC) && defined(SC_USE_QUARTZ)
00082 // #include ???
00083 #endif
00084 
00085 #include <math.h>
00086 
00087 
00089 ScPainter::ScPainter( QPaintDevice *target, unsigned int w, unsigned int h, unsigned int x, unsigned int y )
00090 {
00091        m_target = target;
00092        m_width = w;
00093        m_height= h;
00094        m_x = x;
00095        m_y = y;
00096        m_buffer = 0L;
00097 #ifdef HAVE_CAIRO
00098 #else
00099        m_path = 0L;
00100        m_clipPath = 0L;
00101 #endif
00102        m_index = 0;
00103        m_stroke = QColor(0,0,0);
00104        m_fill = QColor(0,0,0);
00105        fill_trans = 1.0;
00106        stroke_trans = 1.0;
00107        m_fillRule = true;
00108        fillMode = 1;
00109        LineWidth = 1.0;
00110        m_offset = 0;
00111        m_array.clear();
00112        mf_underline = false;
00113        mf_strikeout = false;
00114        mf_shadow = false;
00115        mf_outlined = false;
00116        PLineEnd = Qt::SquareCap;
00117        PLineJoin = Qt::RoundJoin;
00118        fill_gradient = VGradient(VGradient::linear);
00119        stroke_gradient = VGradient(VGradient::linear);
00120        m_zoomFactor = 1;
00121        imageMode = false;
00122        m_matrix = QWMatrix();
00123 #ifdef HAVE_CAIRO
00124        layeredMode = false;
00125        svgMode = false;
00126        cairo_surface_t *img;
00127 #ifdef Q_WS_X11
00128        pixm = QPixmap(w, h);
00129        Display *dpy = pixm.x11AppDisplay();
00130        Drawable drw = pixm.handle();
00131        img = cairo_xlib_surface_create(dpy, drw, (Visual*)pixm.x11Visual(), w, h);
00132 #elif defined(_WIN32)
00133        pixm = QPixmap(w, h, 32);
00134        img = cairo_win32_surface_create(pixm.handle());
00135 #elif defined(SC_USE_QUARTZ)
00136        // ???
00137 #else
00138        m_img.create(w, h, 32);
00139        img = cairo_image_surface_create_for_data(m_img.bits(), CAIRO_FORMAT_ARGB32, w, h, w*4);
00140 #endif
00141        m_cr = cairo_create(img);
00142        clear();
00143        cairo_save( m_cr );
00144        cairo_set_fill_rule (m_cr, CAIRO_FILL_RULE_EVEN_ODD);
00145        cairo_set_operator(m_cr, CAIRO_OPERATOR_OVER);
00146 /*     Setting to 0.5 here gives a good tradeoff between speed and precision
00147        the former setting of 0.2 is just too precise, and setting it to 0.9 or greater will give bad rendering */
00148        cairo_set_tolerance( m_cr, 0.5 );
00149 #else 
00150        // not HAVE_CAIRO
00151 #if defined(Q_WS_X11) && defined(SC_USE_PIXBUF)
00152        resize( m_width, m_height );
00153        clear();
00154        xlib_rgb_init_with_depth( target->x11Display(), XScreenOfDisplay( target->x11Display(), target->x11Screen() ), target->x11Depth() );
00155        gc = XCreateGC( target->x11Display(), target->handle(), 0, 0 );
00156 #elif defined(_WIN32) && defined(SC_USE_GDI)
00157        resize( m_width, m_height );
00158        clear();
00159        dc = CreateCompatibleDC( target->handle() );
00160 #else
00161        resize( m_width, m_height );
00162        clear();
00163 #endif
00164 #endif
00165 }
00166 
00168 ScPainter::ScPainter( QImage *target, unsigned int w, unsigned int h, unsigned int x, unsigned int y )
00169 {
00170        m_target = 0L;
00171        m_width = w;
00172        m_height= h;
00173        m_x = x;
00174        m_y = y;
00175        m_buffer = 0L;
00176        m_index = 0;
00177        m_stroke = QColor(0,0,0);
00178        m_fill = QColor(0,0,0);
00179        fill_trans = 1.0;
00180        stroke_trans = 1.0;
00181        m_fillRule = true;
00182        fillMode = 1;
00183        LineWidth = 1.0;
00184        m_offset = 0;
00185        m_array.clear();
00186        mf_underline = false;
00187        mf_strikeout = false;
00188        mf_shadow = false;
00189        mf_outlined = false;
00190        PLineEnd = Qt::SquareCap;
00191        PLineJoin = Qt::RoundJoin;
00192        fill_gradient = VGradient(VGradient::linear);
00193        stroke_gradient = VGradient(VGradient::linear);
00194        m_zoomFactor = 1;
00195        imageMode = true;
00196        m_image = target;
00197        m_matrix = QWMatrix();
00198 #ifdef HAVE_CAIRO
00199        layeredMode = false;
00200        svgMode = false;
00201        cairo_surface_t *img = cairo_image_surface_create_for_data(target->bits(), CAIRO_FORMAT_ARGB32, w, h, w*4);
00202        m_cr = cairo_create(img);
00203        clear();
00204        cairo_save( m_cr );
00205        cairo_set_fill_rule (m_cr, CAIRO_FILL_RULE_EVEN_ODD);
00206        cairo_set_operator(m_cr, CAIRO_OPERATOR_OVER);
00207 /*     Setting to 0.5 here gives a good tradeoff between speed and precision
00208        the former setting of 0.2 is just too precise, and setting it to 0.9 or greater will give bad rendering */
00209        cairo_set_tolerance( m_cr, 0.5 );
00210 #else
00211        resize( m_width, m_height );
00212        clear();
00213        m_path = 0L;
00214        m_clipPath = 0L;
00215 #endif
00216 }
00217 
00218 #ifdef HAVE_CAIRO
00219 
00220 ScPainter::ScPainter( QImage *target, unsigned int w, unsigned int h, double transparency, int blendmode )
00221 {
00222        m_target = 0L;
00223        m_width = w;
00224        m_height= h;
00225        m_buffer = 0L;
00226        m_index = 0;
00227        m_stroke = QColor(0,0,0);
00228        m_fill = QColor(0,0,0);
00229        fill_trans = 1.0;
00230        stroke_trans = 1.0;
00231        m_fillRule = true;
00232        fillMode = 1;
00233        LineWidth = 1.0;
00234        m_offset = 0;
00235        m_layerTransparency = transparency;
00236        m_blendMode = blendmode;
00237        m_array.clear();
00238        mf_underline = false;
00239        mf_strikeout = false;
00240        mf_shadow = false;
00241        mf_outlined = false;
00242        PLineEnd = Qt::SquareCap;
00243        PLineJoin = Qt::RoundJoin;
00244        fill_gradient = VGradient(VGradient::linear);
00245        stroke_gradient = VGradient(VGradient::linear);
00246        m_zoomFactor = 1;
00247        layeredMode = true;
00248        imageMode = true;
00249        svgMode = false;
00250        m_image = target;
00251        m_matrix = QWMatrix();
00252 /*
00253 #if CAIRO_VERSION < CAIRO_VERSION_ENCODE(1, 1, 6)
00254        tmp_image = QImage(w, h, 32, QImage::BigEndian);
00255        tmp_image.fill( qRgba(255, 255, 255, 0) );
00256        cairo_surface_t *img = cairo_image_surface_create_for_data(tmp_image.bits(), CAIRO_FORMAT_ARGB32, w, h, w*4);
00257        m_cr = cairo_create(img);
00258        clear();
00259 #else
00260 */
00261 //     m_image->fill( qRgba(255, 255, 255, 0) );
00262        cairo_surface_t *img = cairo_image_surface_create_for_data(m_image->bits(), CAIRO_FORMAT_ARGB32, w, h, w*4);
00263        m_cr = cairo_create(img);
00264 // #endif
00265        cairo_save( m_cr );
00266        cairo_set_fill_rule (m_cr, CAIRO_FILL_RULE_EVEN_ODD);
00267        cairo_set_operator(m_cr, CAIRO_OPERATOR_OVER);
00268        cairo_set_tolerance( m_cr, 0.5 );
00269 }
00270 
00271 // #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 1, 6)
00273 ScPainter::ScPainter( QString target, unsigned int w, unsigned int h, 
00274                                      double transparency, int blendmode )
00275 {
00276        m_target = 0L;
00277        m_width = w;
00278        m_height= h;
00279        m_buffer = 0L;
00280        m_index = 0;
00281        m_stroke = QColor(0,0,0);
00282        m_fill = QColor(0,0,0);
00283        fill_trans = 1.0;
00284        stroke_trans = 1.0;
00285        m_fillRule = true;
00286        fillMode = 1;
00287        LineWidth = 1.0;
00288        m_offset = 0;
00289        m_layerTransparency = transparency;
00290        m_blendMode = blendmode;
00291        m_array.clear();
00292        mf_underline = false;
00293        mf_strikeout = false;
00294        mf_shadow = false;
00295        mf_outlined = false;
00296        PLineEnd = Qt::SquareCap;
00297        PLineJoin = Qt::RoundJoin;
00298        fill_gradient = VGradient(VGradient::linear);
00299        stroke_gradient = VGradient(VGradient::linear);
00300        m_zoomFactor = 1;
00301        layeredMode = true;
00302        imageMode = false;
00303        svgMode = true;
00304        m_matrix = QWMatrix();
00305        cairo_surface_t *img = cairo_svg_surface_create(target, w, h);
00306        m_cr = cairo_create(img);
00307        cairo_save( m_cr );
00308        cairo_set_fill_rule (m_cr, CAIRO_FILL_RULE_EVEN_ODD);
00309        cairo_set_operator(m_cr, CAIRO_OPERATOR_OVER);
00310        cairo_set_tolerance( m_cr, 0.5 );
00311 }
00312 // #endif
00313 // HAVE_CAIRO
00314 #endif
00315 
00316 ScPainter::~ScPainter()
00317 {
00318 #ifdef HAVE_CAIRO
00319 #else
00320        // If we are in target mode, we created a buffer, else if we used the other ctor
00321        // we didnt.
00322        if (( m_target ) || ( imageMode))
00323               art_free( m_buffer );
00324        if( m_path )
00325               art_free( m_path );
00326 #endif
00327        
00328        
00329 #ifdef HAVE_CAIRO
00330        cairo_surface_destroy(cairo_get_target(m_cr));
00331        cairo_destroy( m_cr );
00332 #else
00333        // not HAVE_CAIRO
00334 #if defined(Q_WS_X11) && defined(SC_USE_PIXBUF)
00335        if ((imageMode) || (svgMode))
00336               return;
00337        if( gc )
00338               XFreeGC( m_target->x11Display(), gc );
00339 #elif defined(_WIN32) && defined(SC_USE_GDI)
00340        if (imageMode || svgMode)
00341               return;
00342        if( dc )
00343               DeleteDC( dc );
00344 #endif
00345 #endif
00346 }
00347 
00348 #ifdef HAVE_CAIRO
00349 void ScPainter::beginLayer(double transparency, int blendmode, FPointArray *clipArray)
00350 {
00351 // #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 1, 6)
00352        layerProp la;
00353 //     #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 1, 8)
00354        la.data = cairo_get_group_target(m_cr);
00355 //     #endif
00356        la.blendmode = m_blendMode;
00357        la.tranparency = m_layerTransparency;
00358        m_layerTransparency = transparency;
00359        m_blendMode = blendmode;
00360        la.pushed = false;
00361        la.groupClip.resize(0);
00362 //     if (clipArray != NULL)
00363 //     {
00364 //            la.groupClip = *clipArray;
00365 //     }
00366 //     if ((transparency != 1.0) || (blendmode != 0) || (clipArray != NULL))
00367 //     {
00368               if (clipArray != NULL)
00369               {
00370                      setupPolygon(clipArray);
00371                      setClipPath();
00372               }
00373               cairo_push_group(m_cr);
00374               la.pushed = true;
00375 //     }
00376        Layers.push(la);
00377 /*
00378 #else
00379        tmp_image.fill( qRgba(255, 255, 255, 0) );
00380 #endif
00381 */
00382 }
00383 
00384 void ScPainter::endLayer()
00385 {
00386        layerProp la;
00387        if (Layers.count() == 0)
00388               return;
00389        la = Layers.top();
00390 // #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 1, 6)
00391        if (la.pushed)
00392        {
00393 //     #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 1, 8)
00394               if ((m_blendMode != 0) && (Layers.count() != 0))
00395               {
00396                      cairo_surface_t *tmp = cairo_get_group_target(m_cr);
00397                      cairo_surface_t *tmpB = Layers.top().data;
00398                      if ((tmp != NULL) && (tmpB != NULL))
00399                      {
00400                             if ((cairo_surface_get_type(tmp) == CAIRO_SURFACE_TYPE_IMAGE) && (cairo_surface_get_type(tmpB) == CAIRO_SURFACE_TYPE_IMAGE))
00401                             {
00402                                    cairo_surface_flush(tmp);
00403                                    int stride = cairo_image_surface_get_stride(tmp);
00404                                    unsigned char *s = cairo_image_surface_get_data(tmp);
00405                                    unsigned char *d = cairo_image_surface_get_data(tmpB);
00406                                    int h = cairo_image_surface_get_height(tmp);
00407                                    int w = cairo_image_surface_get_width(tmp);
00408                                    uint oldDst = 1;
00409                                    uint oldSrc = 2;
00410                                    uint newResult = 0;
00411                                    bool first = true;
00412                                    QRgb *src;
00413                                    QRgb *dst;
00414                                    uchar src_a, src_r, src_g, src_b, dst_a, dst_r, dst_g, dst_b, new_r, new_g, new_b;
00415                                    for( int yi=0; yi < h; ++yi )
00416                                    {
00417                                           dst = (QRgb*)d;
00418                                           src = (QRgb*)s;
00419                                           for( int xi=0; xi < w; ++xi )
00420                                           {
00421                                                  src_r = qRed(*src);
00422                                                  src_g = qGreen(*src);
00423                                                  src_b = qBlue(*src);
00424                                                  src_a = qAlpha(*src);
00425                                                  dst_r = qRed(*dst);
00426                                                  dst_g = qGreen(*dst);
00427                                                  dst_b = qBlue(*dst);
00428                                                  dst_a = qAlpha(*dst);
00429                                                  if ((src_a > 0) && (dst_a > 0))
00430                                                  {
00431                                                         if (((*dst) != oldDst) || ((*src) != oldSrc) || (first))
00432                                                         {
00433                                                                if (m_blendMode == 1)
00434                                                                {
00435                                                                       src_r = dst_r  < src_r ? dst_r  : src_r;
00436                                                                       src_g = dst_g < src_g ? dst_g : src_g;
00437                                                                       src_b = dst_b < src_b ? dst_b : src_b;
00438                                                                }
00439                                                                else if (m_blendMode == 2)
00440                                                                {
00441                                                                       src_r = dst_r  < src_r ? src_r : dst_r;
00442                                                                       src_g = dst_g < src_g ? src_g : dst_g;
00443                                                                       src_b = dst_b < src_b ? src_b : dst_b;
00444                                                                }
00445                                                                else if (m_blendMode == 3)
00446                                                                {
00447                                                                       src_r = INT_MULT(src_r, dst_r);
00448                                                                       src_g = INT_MULT(src_g, dst_g);
00449                                                                       src_b = INT_MULT(src_b, dst_b);
00450                                                                }
00451                                                                else if (m_blendMode == 4)
00452                                                                {
00453                                                                       src_r = 255 - ((255-src_r) * (255-dst_r) / 128);
00454                                                                       src_g = 255 - ((255-src_g) * (255-dst_g) / 128);
00455                                                                       src_b = 255 - ((255-src_b) * (255-dst_b) / 128);
00456                                                                }
00457                                                                else if (m_blendMode == 5)
00458                                                                {
00459                                                                       src_r = dst_r < 128 ? src_r * dst_r / 128 : 255 - ((255-src_r) * (255-dst_r) / 128);
00460                                                                       src_g = dst_g < 128 ? src_g * dst_g / 128 : 255 - ((255-src_g) * (255-dst_g) / 128);
00461                                                                       src_b = dst_b < 128 ? src_b * dst_b / 128 : 255 - ((255-src_b) * (255-dst_b) / 128);
00462                                                                }
00463                                                                else if (m_blendMode == 6)
00464                                                                {
00465                                                                       src_r = src_r < 128 ? src_r * dst_r / 128 : 255 - ((255-src_r) * (255-dst_r) / 128);
00466                                                                       src_g = src_g < 128 ? src_g * dst_g / 128 : 255 - ((255-src_g) * (255-dst_g) / 128);
00467                                                                       src_b = src_b < 128 ? src_b * dst_b / 128 : 255 - ((255-src_b) * (255-dst_b) / 128);
00468                                                                }
00469                                                                else if (m_blendMode == 7)
00470                                                                {
00471                                                                       float s_r = (255 - src_r) / 255.0;
00472                                                                       float s_g = (255 - src_g) / 255.0;
00473                                                                       float s_b = (255 - src_b) / 255.0;
00474                                                                       float d_r = (255 - dst_r) / 255.0;
00475                                                                       float d_g = (255 - dst_g) / 255.0;
00476                                                                       float d_b = (255 - dst_b) / 255.0;
00477                                                                       float dzr = d_r > 0.25 ? sqrt(d_r) : ((16 * d_r - 12) * d_r + 4) * d_r;
00478                                                                       float dzg = d_g > 0.25 ? sqrt(d_g) : ((16 * d_g - 12) * d_g + 4) * d_g;
00479                                                                       float dzb = d_b > 0.25 ? sqrt(d_b) : ((16 * d_b - 12) * d_b + 4) * d_b;
00480                                                                       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);
00481                                                                       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);
00482                                                                       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);
00483                                                                       src_r = 255 - qRound(s_r * 255);
00484                                                                       src_g = 255 - qRound(s_g * 255);
00485                                                                       src_b = 255 - qRound(s_b * 255);
00486                                                                }
00487                                                                else if (m_blendMode == 8)
00488                                                                {
00489                                                                       src_r = dst_r > src_r ? dst_r - src_r : src_r - dst_r;
00490                                                                       src_g = dst_g > src_g ? dst_g - src_g : src_g - dst_g;
00491                                                                       src_b = dst_b > src_b ? dst_b - src_b : src_b - dst_b;
00492                                                                }
00493                                                                else if (m_blendMode == 9)
00494                                                                {
00495                                                                       src_r = dst_r + src_r - src_r * dst_r / 128;
00496                                                                       src_g = dst_g + src_g - src_g * dst_g / 128;
00497                                                                       src_b = dst_b + src_b - src_b * dst_b / 128;
00498                                                                }
00499                                                                else if (m_blendMode == 10)
00500                                                                {
00501                                                                       src_r = src_r == 255 ? QMIN(255, dst_r * 256) : QMIN(255, ((dst_r * 256) / (255-src_r)));
00502                                                                       src_g = src_g == 255 ? QMIN(255, dst_g * 256) : QMIN(255, ((dst_g * 256) / (255-src_g)));
00503                                                                       src_b = src_b == 255 ? QMIN(255, dst_b * 256) : QMIN(255, ((dst_b * 256) / (255-src_b)));
00504                                                                }
00505                                                                else if (m_blendMode == 11)
00506                                                                {
00507                                                                       src_r = QMAX(1, src_r);
00508                                                                       src_g = QMAX(1, src_g);
00509                                                                       src_b = QMAX(1, src_b);
00510                                                                       src_r = static_cast<int>(255 - (((255-dst_r) * 256) / src_r)) < 0 ? 0 : 255 - (((255-dst_r) * 256) / src_r);
00511                                                                       src_g = static_cast<int>(255 - (((255-dst_g) * 256) / src_g)) < 0 ? 0 : 255 - (((255-dst_g) * 256) / src_g);
00512                                                                       src_b = static_cast<int>(255 - (((255-dst_b) * 256) / src_b)) < 0 ? 0 : 255 - (((255-dst_b) * 256) / src_b);
00513                                                                }
00514        //                                               else if (m_blendMode == 12)
00515        //                                               {
00516                      /*                                        This code is a blendmode that simulates the effect of overprinting
00517                                                                Works by converting source and destination colour to CMYK and adding them together
00518                                                                Finally the result is converted back to RGB */
00519        /*                                                      int K1 = QMIN(QMIN(255 - src_r, 255 - src_g), 255 - src_b);
00520                                                                int K2 = QMIN(QMIN(255 - dst_r, 255 - dst_g), 255 - dst_b);
00521                                                                int C = QMIN(QMIN(255 - src_r - K1, 255) + QMIN(255 - dst_r - K2, 255), 255);
00522                                                                int M = QMIN(QMIN(255 - src_g - K1, 255) + QMIN(255 - dst_g - K2, 255), 255) ;
00523                                                                int Y = QMIN(QMIN(255 - src_b - K1, 255) + QMIN(255 - dst_b - K2, 255), 255) ;
00524                                                                int K = QMIN(K1 + K2, 255);
00525                                                                src_r = 255 - QMIN(255, C + K);
00526                                                                src_g = 255 - QMIN(255, M + K);
00527                                                                src_b = 255 - QMIN(255, Y+ K);
00528                                                         } */
00529                                                                else if (m_blendMode == 12)
00530                                                                {
00531                                                                       new_r = dst_r;
00532                                                                       new_g = dst_g;
00533                                                                       new_b = dst_b;
00534                                                                       RGBTOHLS(src_r, src_g, src_b);
00535                                                                       RGBTOHLS(new_r, new_g, new_b);
00536                                                                       new_r = src_r;
00537                                                                       HLSTORGB(new_r, new_g, new_b);
00538 /*                                                                    RGBTOHSV(src_r, src_g, src_b);
00539                                                                       RGBTOHSV(new_r, new_g, new_b);
00540                                                                       new_r = src_r;
00541                                                                       HSVTORGB(new_r, new_g, new_b); */
00542                                                                       src_r = new_r;
00543                                                                       src_g = new_g;
00544                                                                       src_b = new_b;
00545                                                                }
00546                                                                else if (m_blendMode == 13)
00547                                                                {
00548                                                                       new_r = dst_r;
00549                                                                       new_g = dst_g;
00550                                                                       new_b = dst_b;
00551                                                                       RGBTOHLS(src_r, src_g, src_b);
00552                                                                       RGBTOHLS(new_r, new_g, new_b);
00553                                                                       new_b = src_b;
00554                                                                       HLSTORGB(new_r, new_g, new_b);
00555 /*                                                                    RGBTOHSV(src_r, src_g, src_b);
00556                                                                       RGBTOHSV(new_r, new_g, new_b);
00557                                                                       new_g = src_g;
00558                                                                       HSVTORGB(new_r, new_g, new_b); */
00559                                                                       src_r = new_r;
00560                                                                       src_g = new_g;
00561                                                                       src_b = new_b;
00562                                                                }
00563                                                                else if (m_blendMode == 14)
00564                                                                {
00565                                                                       new_r = src_r;
00566                                                                       new_g = src_g;
00567                                                                       new_b = src_b;
00568                                                                       setLum(new_r, new_g, new_b, Lum(dst_r, dst_g, dst_b));
00569 /*                                                                    RGBTOHLS(src_r, src_g, src_b);
00570                                                                       RGBTOHLS(new_r, new_g, new_b);
00571                                                                       new_r = src_r;
00572                                                                       new_b = src_b;
00573                                                                       HLSTORGB(new_r, new_g, new_b); */
00574                                                                       src_r = new_r;
00575                                                                       src_g = new_g;
00576                                                                       src_b = new_b;
00577                                                                }
00578                                                                else if (m_blendMode == 15)
00579                                                                {
00580                                                                       new_r = dst_r;
00581                                                                       new_g = dst_g;
00582                                                                       new_b = dst_b;
00583                                                                       setLum(new_r, new_g, new_b, Lum(src_r, src_g, src_b));
00584 /*                                                                    RGBTOHSV(src_r, src_g, src_b);
00585                                                                       RGBTOHSV(new_r, new_g, new_b);
00586                                                                       new_b = src_b;
00587                                                                       HSVTORGB(new_r, new_g, new_b); */
00588                                                                       src_r = new_r;
00589                                                                       src_g = new_g;
00590                                                                       src_b = new_b;
00591                                                                }
00592                                                                newResult = qRgba(src_r, src_g, src_b, src_a);
00593                                                                oldDst = (*dst);
00594                                                                oldSrc = (*src);
00595                                                                first = false;
00596                                                         }
00597                                                         (*src) = newResult;
00598                                                  }
00599                                                  src++;
00600                                                  dst++;
00601                                           }
00602                                           s += stride;
00603                                           d += stride;
00604                                    }
00605                                    cairo_surface_mark_dirty(tmp);
00606                             }
00607                      }
00608               }
00609 //            #endif
00610        }
00611        la = Layers.pop();
00612        if (la.pushed)
00613        {
00614               cairo_pop_group_to_source (m_cr);
00615 //            if (la.groupClip.size() != 0)
00616 //            {
00617 //                   setupPolygon(&la.groupClip);
00618 //                   setClipPath();
00619 //            }
00620               if (m_blendMode == 0)
00621               {
00622                      cairo_set_operator(m_cr, CAIRO_OPERATOR_OVER);
00623                      cairo_paint_with_alpha (m_cr, m_layerTransparency);
00624               }
00625               else
00626               {
00627                      cairo_set_operator(m_cr, CAIRO_OPERATOR_DEST_OUT);
00628                      cairo_paint_with_alpha (m_cr, m_layerTransparency);
00629                      cairo_set_operator(m_cr, CAIRO_OPERATOR_ADD);
00630                      cairo_paint_with_alpha (m_cr, m_layerTransparency);
00631               }
00632               cairo_set_operator(m_cr, CAIRO_OPERATOR_OVER);
00633        }
00634        m_layerTransparency = la.tranparency;
00635        m_blendMode = la.blendmode;
00636 /*
00637 #else
00638        cairo_surface_flush(cairo_get_target(m_cr));
00639        int words = m_image->numBytes() / 4;
00640        QRgb *s = (QRgb*)(tmp_image.bits());
00641        QRgb *d = (QRgb*)(m_image->bits());
00642        QRgb src, dst;
00643        uchar src_a, src_r, src_g, src_b, dst_a, dst_r, dst_g, dst_b;
00644        int layOpa;
00645        for(int x = 0; x < words; ++x )
00646        {
00647               src = (*s);
00648               dst = (*d);
00649               src_a = qAlpha(src);
00650               if (src_a > 0)
00651               {
00652                      src_r = qRed(src);
00653                      src_g = qGreen(src);
00654                      src_b = qBlue(src);
00655                      dst_a = qAlpha(dst);
00656                      dst_r = qRed(dst);
00657                      dst_g = qGreen(dst);
00658                      dst_b = qBlue(dst);
00659                      layOpa = qRound(255 * m_layerTransparency);
00660                      src_a = INT_MULT(src_a, layOpa);
00661                      if ((dst_a > 0) && (src_a > 0))
00662                             (*d) = qRgba((dst_r * (255 - layOpa) + src_r * layOpa) / 255, (dst_g * (255 - layOpa) + src_g * layOpa) / 255, (dst_b * (255 - layOpa) + src_b * layOpa) / 255, dst_a + INT_MULT(255 - dst_a, src_a));
00663                      else if (src_a > 0)
00664                             (*d) = qRgba(src_r, src_g, src_b, src_a);
00665               }
00666               s++;
00667               d++;
00668        }
00669 #endif
00670 */
00671 }
00672 //HAVE_CAIRO
00673 #endif
00674 
00675 void ScPainter::begin()
00676 {
00677 }
00678 
00679 void ScPainter::end()
00680 {
00681 #ifdef HAVE_CAIRO
00682        if (svgMode)
00683               cairo_show_page (m_cr);
00684        if (layeredMode)
00685        {
00686 /*
00687 #if CAIRO_VERSION < CAIRO_VERSION_ENCODE(1, 1, 6)
00688               endLayer();
00689 #endif
00690 */
00691               cairo_surface_flush(cairo_get_target(m_cr));
00692               cairo_restore( m_cr );
00693               return;
00694        }
00695 #endif
00696        if (imageMode)
00697        {
00698 #ifdef HAVE_CAIRO
00699               cairo_surface_flush(cairo_get_target(m_cr));
00700               cairo_restore( m_cr );
00701 #else
00702               QRgb * bits = (QRgb *) m_image->bits();
00703               int words = m_image->numBytes() / 4;
00704               art_u8 * p = m_buffer;;
00705               for (int i=0; i < words; ++i)
00706               {
00707                      art_u8 r = *p++;
00708                      art_u8 g = *p++;
00709                      art_u8 b = *p++;
00710                      art_u8 a = *p++;
00711                      *bits++ = qRgba(r,g,b,a);
00712               }
00713 #endif
00714        }
00715        else
00716        {
00717 #ifdef HAVE_CAIRO
00718               cairo_surface_flush(cairo_get_target(m_cr));
00719 #ifdef Q_WS_X11
00720               bitBlt( m_target, m_x, m_y, &pixm, 0, 0, m_width, m_height );
00721 #elif defined(_WIN32)
00722               bitBlt( m_target, m_x, m_y, &pixm, 0, 0, m_width, m_height );
00723 #elif defined(SC_USE_QUARTZ)
00724               // ???
00725 #else
00726               bitBlt( m_target, m_x, m_y, &m_img, 0, 0, m_width, m_height );
00727 #endif
00728               cairo_restore( m_cr );
00729 #else
00730               // not HAVE_CAIRO
00731   #if defined(Q_WS_X11) && defined(SC_USE_PIXBUF)
00732               // Use the original gdk-pixbuf based bitblit on X11
00733               xlib_draw_rgb_32_image( m_target->handle(), gc, m_x, m_y, m_width, m_height, XLIB_RGB_DITHER_NONE, m_buffer, m_width * 4 );
00734   #elif defined(_WIN32) && defined(SC_USE_GDI)
00735               // Use Win32 implementation
00736               BITMAPINFO bmpInfo;
00737               BITMAPINFOHEADER *bmpHeader;
00738               long* bmpData;
00739 
00740               bmpHeader = &(bmpInfo.bmiHeader);
00741               bmpHeader->biSize = sizeof(BITMAPINFOHEADER);
00742               bmpHeader->biWidth = m_width;
00743               bmpHeader->biHeight = -m_height;
00744               bmpHeader->biPlanes = 1;
00745               bmpHeader->biBitCount = 32;
00746               bmpHeader->biCompression = BI_RGB;
00747               bmpHeader->biSizeImage = 0; // Valid only if biCompression = BI_RGB
00748               bmpHeader->biXPelsPerMeter = 0;
00749               bmpHeader->biYPelsPerMeter = 0;
00750               bmpHeader->biClrUsed = 0;
00751               bmpHeader->biClrImportant = 0;
00752 
00753               // Create a device independent Bitmap
00754               HBITMAP hBmp = CreateDIBSection(dc, &bmpInfo, DIB_RGB_COLORS, (void** ) (&bmpData), NULL, NULL);
00755               art_u8 * p = m_buffer;
00756               art_u8 r, g, b, a;
00757               int words = m_width * m_height; // Valid only if biBitCount = 32
00758 
00759               for (int i = 0; i < words; ++i) {
00760                      r = *p++;
00761                      g = *p++;
00762                      b = *p++;
00763                      a = *p++;
00764                      *bmpData++ = ( (a << 24) + (r << 16) + (g << 8) + b);
00765               }
00766 
00767               HGDIOBJ obj = SelectObject( dc, hBmp);
00768               BitBlt( m_target->handle() , m_x, m_y, m_width, m_height, dc, 0, 0, SRCCOPY);
00769               SelectObject( dc, obj);
00770               DeleteObject( hBmp );
00771   #else
00772               // Portable copying onto the canvas with no X11 dependency by Andreas Vox
00773               QImage qimg(m_width, m_height, 32, QImage::BigEndian);
00774               QRgb * bits = (QRgb *) qimg.bits();
00775               int words = qimg.numBytes() / 4;
00776               art_u8 * p = m_buffer;;
00777               for (int i=0; i < words; ++i) {
00778                      art_u8 r = *p++;
00779                      art_u8 g = *p++;
00780                      art_u8 b = *p++;
00781                      art_u8 a = *p++;
00782                      *bits++ = qRgba(r,g,b,a);
00783               }
00784               bitBlt(m_target, m_x, m_y, &qimg);
00785   #endif
00786 #endif
00787        }
00788 }
00789 
00790 void ScPainter::clear()
00791 {
00792 #ifdef HAVE_CAIRO
00793        if (imageMode)
00794               m_image->fill( qRgba(255, 255, 255, 255) );
00795        else {
00796               if (! m_img.isNull())
00797                      m_img.fill( qRgba(255, 255, 255, 255) );
00798               else
00799                      pixm.fill( Qt::white );
00800        }
00801 #else
00802        if( m_buffer )
00803               memset( m_buffer, 255, m_width * m_height * 4 );
00804 #endif
00805 }
00806 
00807 void ScPainter::clear( const QColor &c )
00808 {
00809 #ifdef HAVE_CAIRO
00810        QRgb cs = c.rgb();
00811        if (imageMode)
00812               m_image->fill( qRgba(qRed(cs), qGreen(cs), qBlue(cs), qAlpha(cs)) );
00813        else {
00814               if (!m_img.isNull())
00815                      m_img.fill( qRgba(qRed(cs), qGreen(cs), qBlue(cs), qAlpha(cs)) );
00816               else
00817                      pixm.fill( c );
00818        }
00819 #else
00820        if( m_buffer )
00821        {
00822               unsigned int *src = (unsigned int*)m_buffer;
00823               unsigned int co = qRgba(c.blue(), c.green(),  c.red(), 255);
00824               for(unsigned int cc = 0; cc < (m_width * m_height); ++cc)
00825               {
00826                      *src++ = co;
00827               }
00828        }
00829 #endif
00830 }
00831 
00832 const QWMatrix ScPainter::worldMatrix()
00833 {
00834 #ifdef HAVE_CAIRO
00835        cairo_matrix_t matrix;
00836        cairo_get_matrix(m_cr, &matrix);
00837        QWMatrix mat;
00838        mat.setMatrix ( matrix.xx, matrix.yx, matrix.xy, matrix.yy, matrix.x0, matrix.y0 );
00839        return mat;
00840 #else
00841        return m_matrix;
00842 #endif
00843 }
00844 
00845 void ScPainter::setWorldMatrix( const QWMatrix &mat )
00846 {
00847 #ifdef HAVE_CAIRO
00848        cairo_matrix_t matrix;
00849        cairo_matrix_init(&matrix, mat.m11(), mat.m12(), mat.m21(), mat.m22(), mat.dx(), mat.dy());
00850        cairo_set_matrix(m_cr, &matrix);
00851 #else
00852        m_matrix = mat;
00853 #endif
00854 }
00855 
00856 #ifdef HAVE_CAIRO
00857 void ScPainter::setAntialiasing(bool enable)
00858 {
00859        if (enable)
00860               cairo_set_antialias(m_cr, CAIRO_ANTIALIAS_DEFAULT);
00861        else
00862               cairo_set_antialias(m_cr, CAIRO_ANTIALIAS_NONE);
00863 }
00864 #endif
00865 
00866 void ScPainter::setZoomFactor( double zoomFactor )
00867 {
00868        m_zoomFactor = zoomFactor;
00869 #ifdef HAVE_CAIRO
00870        cairo_scale (m_cr, m_zoomFactor, m_zoomFactor);
00871 #endif
00872 }
00873 
00874 void ScPainter::translate( double x, double y )
00875 {
00876 #ifdef HAVE_CAIRO
00877        cairo_translate (m_cr, x, y);
00878 #else
00879        m_matrix.translate(x, y);
00880 #endif
00881 }
00882 
00883 void ScPainter::rotate( double r )
00884 {
00885 #ifdef HAVE_CAIRO
00886        cairo_rotate (m_cr, r * 3.1415927 / 180.0);
00887 #else
00888        m_matrix.rotate(r);
00889 #endif
00890 }
00891 
00892 void ScPainter::scale( double x, double y )
00893 {
00894 #ifdef HAVE_CAIRO
00895        cairo_scale (m_cr, x, y);
00896 #else
00897        m_matrix.scale(x, y);
00898 #endif
00899 }
00900 
00901 void ScPainter::moveTo( const double &x, const double &y )
00902 {
00903 #ifdef HAVE_CAIRO
00904        cairo_move_to( m_cr, x, y);
00905 #else
00906        ensureSpace( m_index + 1 );
00907        m_path[ m_index ].code = ART_MOVETO;
00908        m_path[ m_index ].x3 = x * m_zoomFactor;
00909        m_path[ m_index ].y3 = y * m_zoomFactor;
00910        m_index++;
00911 #endif
00912 }
00913 
00914 void
00915 ScPainter::lineTo( const double &x, const double &y )
00916 {
00917 #ifdef HAVE_CAIRO
00918        cairo_line_to( m_cr, x, y);
00919 #else
00920        ensureSpace( m_index + 1 );
00921        m_path[ m_index ].code = ART_LINETO;
00922        m_path[ m_index ].x3 = x * m_zoomFactor;
00923        m_path[ m_index ].y3 = y * m_zoomFactor;
00924        m_index++;
00925 #endif
00926 }
00927 
00928 void ScPainter::curveTo( FPoint p1, FPoint p2, FPoint p3 )
00929 {
00930 #ifdef HAVE_CAIRO
00931        cairo_curve_to(m_cr, p1.x(), p1.y(), p2.x(), p2.y(), p3.x(), p3.y());
00932 #else
00933        ensureSpace( m_index + 1 );
00934        m_path[ m_index ].code = ART_CURVETO;
00935        m_path[ m_index ].x1 = p1.x() * m_zoomFactor;
00936        m_path[ m_index ].y1 = p1.y() * m_zoomFactor;
00937        m_path[ m_index ].x2 = p2.x() * m_zoomFactor;
00938        m_path[ m_index ].y2 = p2.y() * m_zoomFactor;
00939        m_path[ m_index ].x3 = p3.x() * m_zoomFactor;
00940        m_path[ m_index ].y3 = p3.y() * m_zoomFactor;
00941        m_index++;
00942 #endif
00943 }
00944 
00945 void ScPainter::newPath()
00946 {
00947 #ifdef HAVE_CAIRO
00948        cairo_new_path( m_cr );
00949 #else
00950        m_index = 0;
00951 #endif
00952 }
00953 
00954 void ScPainter::closePath()
00955 {
00956 #ifdef HAVE_CAIRO
00957        cairo_close_path( m_cr );
00958 #else
00959        ensureSpace( m_index + 1 );
00960        m_path[ m_index ].code = ART_END;
00961        m_index++;
00962 #endif
00963 }
00964 
00965 void ScPainter::setFillRule( bool fillRule )
00966 {
00967        m_fillRule = fillRule;
00968 }
00969 
00970 void ScPainter::setFillMode( int fill )
00971 {
00972        fillMode = fill;
00973 }
00974 
00975 void ScPainter::setGradient(VGradient::VGradientType mode, FPoint orig, FPoint vec, FPoint foc)
00976 {
00977        fill_gradient.setType(mode);
00978        fill_gradient.setOrigin(orig);
00979        fill_gradient.setVector(vec);
00980        fill_gradient.setFocalPoint(foc);
00981 }
00982 
00983 void ScPainter::fillTextPath()
00984 {
00985 #ifdef HAVE_CAIRO
00986        drawVPath( 0 );
00987 #else
00988        ArtVpath *path = art_bez_path_to_vec( m_path , 0.25 );
00989        drawVPath( path, 0, true );
00990 #endif
00991 }
00992 
00993 void ScPainter::strokeTextPath()
00994 {
00995        if( LineWidth == 0 )
00996               return;
00997 #ifdef HAVE_CAIRO
00998        drawVPath( 1 );
00999 #else
01000        ArtVpath *path = art_bez_path_to_vec( m_path , 0.25 );
01001        drawVPath( path, 1, true );
01002 #endif
01003 }
01004 
01005 void ScPainter::fillPath()
01006 {
01007 #ifdef HAVE_CAIRO
01008        if( fillMode != 0)
01009               drawVPath( 0 );
01010 #else
01011        if( m_index == 0 )
01012               return;
01013        if( fillMode != 0)
01014        {
01015               ArtVpath *path = art_bez_path_to_vec( m_path , 0.25 );
01016               drawVPath( path, 0 );
01017        }
01018 #endif
01019 }
01020 
01021 void ScPainter::strokePath()
01022 {
01023        if( LineWidth == 0 )
01024               return;
01025 #ifdef HAVE_CAIRO
01026        drawVPath( 1 );
01027 #else
01028        if( m_index == 0 )
01029               return;
01030        if( m_path[ m_index ].code != ART_END)
01031               m_path[ m_index ].code = ART_END;
01032        ArtVpath *path = art_bez_path_to_vec( m_path , 0.25 );
01033        drawVPath( path, 1 );
01034 #endif
01035 }
01036 
01037 QColor ScPainter::pen()
01038 {
01039        return m_stroke;
01040 }
01041 
01042 QColor ScPainter::brush()
01043 {
01044        return m_fill;
01045 }
01046 
01047 void ScPainter::setPen( const QColor &c )
01048 {
01049        m_stroke = c;
01050 }
01051 
01052 void ScPainter::setPen( const QColor &c, double w, Qt::PenStyle st, Qt::PenCapStyle ca, Qt::PenJoinStyle jo )
01053 {
01054        m_stroke = c;
01055        LineWidth = w;
01056        PLineEnd = ca;
01057        PLineJoin = jo;
01058        double Dt = QMAX(2*w, 1);
01059        double Da = QMAX(6*w, 1);
01060        QValueList<double> tmp;
01061        m_array.clear();
01062        m_offset = 0;
01063        switch (st)
01064               {
01065               case Qt::SolidLine:
01066                      break;
01067               case Qt::DashLine:
01068                      m_array.append(Da);
01069                      m_array.append(Dt);
01070                      break;
01071               case Qt::DotLine:
01072                      m_array.append(Dt);
01073                      break;
01074               case Qt::DashDotLine:
01075                      m_array.append(Da);
01076                      m_array.append(Dt);
01077                      m_array.append(Dt);
01078                      m_array.append(Dt);
01079                      break;
01080               case Qt::DashDotDotLine:
01081                      m_array.append(Da);
01082                      m_array.append(Dt);
01083                      m_array.append(Dt);
01084                      m_array.append(Dt);
01085                      m_array.append(Dt);
01086                      m_array.append(Dt);
01087                      break;
01088               default:
01089                      break;
01090               }
01091 }
01092 
01093 void ScPainter::setLineWidth( double w )
01094 {
01095        LineWidth = w;
01096 }
01097 
01098 void ScPainter::setPenOpacity( double op )
01099 {
01100        stroke_trans = op;
01101 }
01102 
01103 
01104 void ScPainter::setDash(const QValueList<double>& array, double ofs)
01105 {
01106        m_array = array;
01107        m_offset = ofs;
01108 }
01109 
01110 void ScPainter::setBrush( const QColor &c )
01111 {
01112        m_fill = c;
01113 }
01114 
01115 void ScPainter::setBrushOpacity( double op )
01116 {
01117        fill_trans = op;
01118 }
01119 
01120 void ScPainter::setOpacity( double op )
01121 {
01122        fill_trans = op;
01123        stroke_trans = op;
01124 }
01125 
01126 void ScPainter::setFont( const QFont &f)
01127 {
01128        m_font = f;
01129 }
01130 
01131 QFont ScPainter::font()
01132 {
01133        return m_font;
01134 }
01135 
01136 void ScPainter::save()
01137 {
01138 #ifdef HAVE_CAIRO
01139        cairo_save( m_cr );
01140 #else
01141        MStack.push(m_matrix);
01142 #endif
01143 }
01144 
01145 void ScPainter::restore()
01146 {
01147 #ifdef HAVE_CAIRO
01148        cairo_restore( m_cr );
01149 #else
01150        m_matrix = MStack.pop();
01151 #endif
01152 }
01153 
01154 void ScPainter::setRasterOp( int   )
01155 {
01156 }
01157 
01158 void ScPainter::setPattern(ScPattern *pattern, double scaleX, double scaleY, double offsetX, double offsetY, double rotation)
01159 {
01160        m_pattern = pattern;
01161        patternScaleX = scaleX / 100.0;
01162        patternScaleY = scaleY / 100.0;
01163        patternOffsetX = offsetX;
01164        patternOffsetY = offsetY;
01165        patternRotation = rotation;
01166 }
01167 
01168 #ifdef HAVE_CAIRO
01169 void ScPainter::drawVPath( int mode )
01170 {
01171        cairo_save( m_cr );
01172        if (mode == 0)
01173        {
01174               if( m_fillRule )
01175                      cairo_set_fill_rule (m_cr, CAIRO_FILL_RULE_EVEN_ODD);
01176               else
01177                      cairo_set_fill_rule (m_cr, CAIRO_FILL_RULE_WINDING);
01178               if (fillMode == 1)
01179               {
01180                      double r = qRed( m_fill.rgb() ) / 255.0;
01181                      double g = qGreen( m_fill.rgb() ) / 255.0;
01182                      double b = qBlue( m_fill.rgb() ) / 255.0;
01183                      cairo_set_source_rgba( m_cr, r, g, b, fill_trans );
01184                      cairo_fill_preserve( m_cr );
01185               }
01186               else if (fillMode == 2)
01187               {
01188                      cairo_pattern_t *pat;
01189                      double x1 = fill_gradient.origin().x();
01190                      double y1 = fill_gradient.origin().y();
01191                      double x2 = fill_gradient.vector().x();
01192                      double y2 = fill_gradient.vector().y();
01193                      if (fill_gradient.type() == VGradient::linear)
01194                             pat = cairo_pattern_create_linear (x1, y1,  x2, y2);
01195                      else
01196                             pat = cairo_pattern_create_radial (x1, y1, 0.1, x1, y1, sqrt(pow(x2 - x1, 2) + pow(y2 - y1,2)));
01197                      QPtrVector<VColorStop> colorStops = fill_gradient.colorStops();
01198                      QColor qStopColor;
01199                      for( uint offset = 0 ; offset < colorStops.count() ; offset++ )
01200                      {
01201                             qStopColor = colorStops[ offset ]->color;
01202                             int h, s, v, sneu, vneu;
01203                             int shad = colorStops[offset]->shade;
01204                             qStopColor.hsv(&h, &s, &v);
01205                             sneu = s * shad / 100;
01206                             vneu = 255 - ((255 - v) * shad / 100);
01207                             qStopColor.setHsv(h, sneu, vneu);
01208                             double r = qRed( qStopColor.rgb() ) / 255.0;
01209                             double g = qGreen( qStopColor.rgb() ) / 255.0;
01210                             double b = qBlue( qStopColor.rgb() ) / 255.0;
01211                             double a = colorStops[offset]->opacity;
01212                             cairo_pattern_add_color_stop_rgba (pat, colorStops[ offset ]->rampPoint, r, g, b, a);
01213                      }
01214                      cairo_set_source (m_cr, pat);
01215                      cairo_clip_preserve (m_cr);
01216                      cairo_paint_with_alpha (m_cr, fill_trans);
01217                      cairo_pattern_destroy (pat);
01218               }
01219               else if (fillMode == 3)
01220               {
01221                      cairo_surface_t *image2 = cairo_image_surface_create_for_data ((uchar*)m_pattern->getPattern()->bits(), CAIRO_FORMAT_RGB24, m_pattern->getPattern()->width(), m_pattern->getPattern()->height(), m_pattern->getPattern()->width()*4);
01222                      cairo_pattern_t *m_pat = cairo_pattern_create_for_surface(image2);
01223                      cairo_pattern_set_extend(m_pat, CAIRO_EXTEND_REPEAT);
01224                      QImage mask;
01225                      cairo_surface_t *image3;
01226                      if (fill_trans != 1.0)
01227                      {
01228                             mask.create(m_pattern->getPattern()->width(), m_pattern->getPattern()->height(), 8);
01229                             QRgb * s;
01230                             unsigned char *d;
01231                             for( int yi = 0; yi < m_pattern->getPattern()->height(); ++yi )
01232                             {
01233                                    s = (QRgb*)(m_pattern->getPattern()->scanLine( yi ));
01234                                    d = (unsigned char *)(mask.scanLine( yi ));
01235                                    for( int xi=0; xi < m_pattern->getPattern()->width(); ++xi )
01236                                    {
01237                                           *d++ = static_cast<unsigned char>(qAlpha(*s++) * fill_trans);
01238                                    }
01239                             }
01240                             int adj;
01241                             if (m_pattern->getPattern()->width() % 4 == 0)
01242                                    adj = 0;
01243                             else
01244                                    adj = 4 - (m_pattern->getPattern()->width() % 4);
01245                             image3 = cairo_image_surface_create_for_data ((uchar*)mask.bits(), CAIRO_FORMAT_A8, m_pattern->getPattern()->width(), m_pattern->getPattern()->height(), m_pattern->getPattern()->width() + adj);
01246                      }
01247                      else
01248                             image3 = 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);
01249                      cairo_matrix_t matrix;
01250                      QWMatrix qmatrix;
01251 //                   qmatrix.scale(m_zoomFactor, m_zoomFactor);
01252                      qmatrix.translate(patternOffsetX, patternOffsetY);
01253                      qmatrix.rotate(patternRotation);
01254                      qmatrix.scale(patternScaleX, patternScaleY);
01255                      cairo_matrix_init(&matrix, qmatrix.m11(), qmatrix.m12(), qmatrix.m21(), qmatrix.m22(), qmatrix.dx(), qmatrix.dy());
01256                      cairo_matrix_invert(&matrix);
01257                      cairo_pattern_set_matrix (m_pat, &matrix);
01258                      cairo_set_source (m_cr, m_pat);
01259                      cairo_clip_preserve (m_cr);
01260                      cairo_pattern_t *m_pat2 = cairo_pattern_create_for_surface(image3);
01261                      cairo_pattern_set_extend(m_pat2, CAIRO_EXTEND_REPEAT);
01262                      cairo_pattern_set_matrix (m_pat2, &matrix);
01263                      cairo_mask (m_cr, m_pat2);
01264                      cairo_pattern_destroy (m_pat);
01265                      cairo_pattern_destroy (m_pat2);
01266                      cairo_surface_destroy (image2);
01267                      cairo_surface_destroy (image3);
01268               }
01269        }
01270        else
01271        {
01272               double *dashes = NULL;
01273               cairo_set_line_width( m_cr, LineWidth );
01274               if( m_array.count() > 0 )
01275               {
01276                      dashes = new double[ m_array.count() ];
01277                      for( uint i = 0; i < m_array.count();++ i )
01278                      {
01279                             dashes[i] = static_cast<double>(m_array[i]);
01280                      }
01281                      cairo_set_dash( m_cr, dashes, m_array.count(), static_cast<double>(m_offset));
01282               }
01283               else
01284                      cairo_set_dash( m_cr, NULL, 0, 0 );
01285               double r = qRed( m_stroke.rgb() ) / 255.0;
01286               double g = qGreen( m_stroke.rgb() ) / 255.0;
01287               double b = qBlue( m_stroke.rgb() ) / 255.0;
01288               cairo_set_source_rgba( m_cr, r, g, b, stroke_trans );
01289               if( PLineEnd == Qt::RoundCap )
01290                      cairo_set_line_cap (m_cr, CAIRO_LINE_CAP_ROUND);
01291               else if( PLineEnd == Qt::SquareCap )
01292                      cairo_set_line_cap (m_cr, CAIRO_LINE_CAP_SQUARE);
01293               else if( PLineEnd == Qt::FlatCap )
01294                      cairo_set_line_cap (m_cr, CAIRO_LINE_CAP_BUTT);
01295               if( PLineJoin == Qt::RoundJoin )
01296                      cairo_set_line_join( m_cr, CAIRO_LINE_JOIN_ROUND );
01297               else if( PLineJoin == Qt::BevelJoin )
01298                      cairo_set_line_join( m_cr, CAIRO_LINE_JOIN_BEVEL );
01299               else if( PLineJoin == Qt::MiterJoin )
01300                      cairo_set_line_join( m_cr, CAIRO_LINE_JOIN_MITER );
01301               cairo_stroke_preserve( m_cr );
01302               if( m_array.count() > 0 )
01303                      delete [] dashes;
01304        }
01305        cairo_restore( m_cr );
01306 #else
01307        // not HAVE_CAIRO
01308 void ScPainter::drawVPath( struct _ArtVpath *vec, int mode, bool preCal )
01309 {
01310        ArtSVP *strokeSvp = 0L;
01311        ArtSVP *fillSvp = 0L;
01312        if (!preCal)
01313        {
01314               double affine[6];
01315               affine[0] = m_matrix.m11();
01316               affine[1] = m_matrix.m12();
01317               affine[2] = m_matrix.m21();
01318               affine[3] = m_matrix.m22();
01319               affine[4] = m_matrix.dx();
01320               affine[5] = m_matrix.dy();
01321               ArtVpath *temp1 = art_vpath_affine_transform( vec, affine );
01322               art_free( vec );
01323               vec = temp1;
01324        }
01325        int af = 0;
01326        int as = 0;
01327        art_u32 fillColor = 0;
01328        QColor color;
01329        if (mode == 0)
01330               {
01331               color = m_fill;
01332               af = qRound( 255 * fill_trans );
01333 #ifdef WORDS_BIGENDIAN
01334               fillColor = ( color.red() << 24 ) | ( color.green() << 16 ) | ( color.blue() << 8 );
01335 #else
01336               fillColor = ( 0 << 24 ) | ( color.blue() << 16 ) | ( color.green() << 8 ) | color.red();
01337 #endif
01338               ArtSvpWriter *swr;
01339               ArtSVP *temp;
01340               ArtSVP *temp2;
01341               temp = art_svp_from_vpath( vec );
01342               if( m_fillRule )
01343                      swr = art_svp_writer_rewind_new( ART_WIND_RULE_ODDEVEN );
01344               else
01345                      swr = art_svp_writer_rewind_new( ART_WIND_RULE_NONZERO );
01346               art_svp_intersector( temp, swr );
01347               fillSvp = art_svp_writer_rewind_reap( swr );
01348               art_svp_free( temp );
01349               }
01350        art_u32 strokeColor = 0;
01351        if (mode == 1)
01352               {
01353               ArtPathStrokeCapType capStyle = ART_PATH_STROKE_CAP_BUTT;
01354               ArtPathStrokeJoinType joinStyle = ART_PATH_STROKE_JOIN_MITER;
01355               color = m_stroke;
01356               as = qRound( 255 * stroke_trans );
01357 #ifdef WORDS_BIGENDIAN
01358               strokeColor = ( color.red() << 24 ) | ( color.green() << 16 ) | ( color.blue() << 8 );
01359 #else
01360               strokeColor = ( 0 << 24 ) | ( color.blue() << 16 ) | ( color.green() << 8 ) | color.red();
01361 #endif
01362               double ratio = m_zoomFactor;
01363               if( m_array.count() > 0 )
01364                      {
01365                      ArtVpathDash dash;
01366                      dash.offset = static_cast<double>(m_offset) * ratio;
01367                      dash.n_dash = m_array.count();
01368                      double *dashes = new double[ dash.n_dash ];
01369                      for( int i = 0; i < dash.n_dash; i++ )
01370                             {
01371                             dashes[i] = static_cast<double>(m_array[i]) * ratio;
01372                             }
01373                      dash.dash = dashes;
01374                      ArtVpath *vec2 = art_vpath_dash( vec, &dash );
01375                      art_free( vec );
01376                      vec = vec2;
01377                      delete [] dashes;
01378                      }
01379               if( PLineEnd == Qt::RoundCap )
01380                      capStyle = ART_PATH_STROKE_CAP_ROUND;
01381               else if( PLineEnd == Qt::SquareCap )
01382                      capStyle = ART_PATH_STROKE_CAP_SQUARE;
01383               if( PLineJoin == Qt::RoundJoin )
01384                      joinStyle = ART_PATH_STROKE_JOIN_ROUND;
01385               else if( PLineJoin == Qt::BevelJoin )
01386                      joinStyle = ART_PATH_STROKE_JOIN_BEVEL;
01387               //strokeSvp = art_svp_vpath_stroke( vec, joinStyle, capStyle, ratio * LineWidth, 10, 0.25 );
01388               ArtVpath* strokeVpath = art_svp_vpath_stroke_raw( vec, joinStyle, capStyle, ratio * LineWidth, 10, 0.25 );
01389               strokeSvp = art_svp_from_vpath( strokeVpath );
01390               art_free(strokeVpath);
01391               }
01392        int x0, y0, x1, y1;
01393        if(( fillSvp ) && (mode == 0))
01394               {
01395               if (fillMode == 2)
01396                      applyGradient( fillSvp, true );
01397               else if (fillMode == 3)
01398                      applyPattern(fillSvp);
01399               else
01400               {
01401                      clampToViewport( *fillSvp, x0, y0, x1, y1 );
01402                      if( x0 != x1 && y0 != y1 )
01403                             art_rgb_svp_alpha_( fillSvp, x0, y0, x1, y1, fillColor, af, m_buffer + x0 * 4 + y0 * m_width * 4, m_width * 4, 0 );
01404               }
01405               art_svp_free( fillSvp );
01406               }
01407        if(( strokeSvp ) && (mode == 1))
01408        {
01409                      clampToViewport( *strokeSvp, x0, y0, x1, y1 );
01410                      if( x0 != x1 && y0 != y1 )
01411                             art_rgb_svp_alpha_( strokeSvp, x0, y0, x1, y1, strokeColor, as, m_buffer + x0 * 4 + y0 * m_width * 4, m_width * 4, 0 );
01412               art_svp_free( strokeSvp );
01413        }
01414        art_free( vec );
01415 #endif
01416 }
01417 
01418 void ScPainter::setClipPath()
01419 {
01420 #ifdef HAVE_CAIRO
01421        cairo_clip (m_cr);
01422 #else
01423        ArtVpath *vec = art_bez_path_to_vec( m_path , 0.25 );
01424        double affine[6];
01425        affine[0] = m_matrix.m11();
01426        affine[1] = m_matrix.m12();
01427        affine[2] = m_matrix.m21();
01428        affine[3] = m_matrix.m22();
01429        affine[4] = m_matrix.dx();
01430        affine[5] = m_matrix.dy();
01431        ArtVpath *temp1 = art_vpath_affine_transform( vec, affine );
01432        art_free( vec );
01433        ArtSvpWriter *swr;
01434        ArtSVP *temp = art_svp_from_vpath( temp1 );
01435        if( m_fillRule )
01436               swr = art_svp_writer_rewind_new( ART_WIND_RULE_ODDEVEN );
01437        else
01438               swr = art_svp_writer_rewind_new( ART_WIND_RULE_NONZERO );
01439        art_svp_intersector( temp, swr );
01440        m_clipPath = art_svp_writer_rewind_reap( swr );
01441        art_svp_free( temp );
01442        art_free( temp1 );
01443 #endif
01444 }
01445 
01446 #ifdef HAVE_CAIRO
01447 #else
01448 void ScPainter::setClipPath2(FPointArray *points, bool closed)
01449 {
01450        setClipPath();
01451        setupPolygon(points, closed);
01452        ArtVpath *vec = art_bez_path_to_vec( m_path , 0.25 );
01453        double affine[6];
01454        affine[0] = m_matrix.m11();
01455        affine[1] = m_matrix.m12();
01456        affine[2] = m_matrix.m21();
01457        affine[3] = m_matrix.m22();
01458        affine[4] = m_matrix.dx();
01459        affine[5] = m_matrix.dy();
01460        ArtVpath *temp1 = art_vpath_affine_transform( vec, affine );
01461        art_free( vec );
01462        ArtSvpWriter *swr;
01463        ArtSVP *temp = art_svp_from_vpath( temp1 );
01464        if( m_fillRule )
01465               swr = art_svp_writer_rewind_new( ART_WIND_RULE_ODDEVEN );
01466        else
01467               swr = art_svp_writer_rewind_new( ART_WIND_RULE_NONZERO );
01468        art_svp_intersector( temp, swr );
01469        temp = art_svp_writer_rewind_reap( swr );
01470        ArtSVP *temp2 = art_svp_intersect( temp, m_clipPath );
01471        m_clipPath = temp2;
01472        art_svp_free( temp );
01473        art_free( temp1 );
01474 }
01475 // not HAVE_CAIRO
01476 #endif
01477 
01478 void ScPainter::drawImage( QImage *image )
01479 {
01480 #ifdef HAVE_CAIRO
01481 #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 2, 6)
01482 /* Code with Layers, crashes on cairo_push_group */
01483 //     cairo_scale(m_cr, m_zoomFactor, m_zoomFactor);
01484        cairo_push_group(m_cr);
01485        cairo_set_fill_rule(m_cr, cairo_get_fill_rule(m_cr));
01486        cairo_surface_t *image2  = cairo_image_surface_create_for_data ((uchar*)image->bits(), CAIRO_FORMAT_RGB24, image->width(), image->height(), image->width()*4);
01487        cairo_surface_t *image3 = cairo_image_surface_create_for_data ((uchar*)image->bits(), CAIRO_FORMAT_ARGB32, image->width(), image->height(), image->width()*4);
01488        cairo_set_source_surface (m_cr, image2, 0, 0);
01489     cairo_mask_surface (m_cr, image3, 0, 0);
01490        cairo_surface_destroy (image2);
01491        cairo_surface_destroy (image3);
01492        cairo_pop_group_to_source (m_cr);
01493        cairo_paint_with_alpha (m_cr, fill_trans);
01494 #else
01495 /* Working code, sadly we need to create an additional mask image with the same size as the image to be painted */
01496        cairo_surface_t *image3;
01497        QImage mask;
01498        cairo_set_fill_rule(m_cr, cairo_get_fill_rule(m_cr));
01499        cairo_surface_t *image2  = cairo_image_surface_create_for_data ((uchar*)image->bits(), CAIRO_FORMAT_RGB24, image->width(), image->height(), image->width()*4);
01500        if (fill_trans != 1.0)
01501        {
01502               mask.create(image->width(), image->height(), 8);
01503               for( int yi = 0; yi < image->height(); ++yi )
01504               {
01505                      QRgb * s = (QRgb*)(image->scanLine( yi ));
01506                      unsigned char *d = (unsigned char *)(mask.scanLine( yi ));
01507                      for( int xi=0; xi < image->width(); ++xi )
01508                      {
01509                             *d++ = static_cast<unsigned char>(qAlpha(*s++) * fill_trans);
01510                      }
01511               }
01512               int adj;
01513               if (image->width() % 4 == 0)
01514                      adj = 0;
01515               else
01516                      adj = 4 - (image->width() % 4);
01517               image3 = cairo_image_surface_create_for_data ((uchar*)mask.bits(), CAIRO_FORMAT_A8, image->width(), image->height(), image->width() + adj);
01518        }
01519        else
01520               image3 = cairo_image_surface_create_for_data ((uchar*)image->bits(), CAIRO_FORMAT_ARGB32, image->width(), image->height(), image->width()*4);
01521 //     cairo_scale(m_cr, m_zoomFactor, m_zoomFactor);
01522        cairo_set_source_surface (m_cr, image2, 0, 0);
01523        cairo_mask_surface (m_cr, image3, 0, 0);
01524        cairo_surface_destroy (image2);
01525        cairo_surface_destroy (image3);
01526 #endif
01527 /* Original Code     
01528        cairo_set_fill_rule(m_cr, cairo_get_fill_rule(m_cr));
01529        cairo_surface_t *image2  = cairo_image_surface_create_for_data ((uchar*)image->bits(), CAIRO_FORMAT_ARGB32, image->width(), image->height(), image->width()*4);
01530        cairo_scale(m_cr, m_zoomFactor, m_zoomFactor);
01531        cairo_set_source_surface (m_cr, image2, 0, 0);
01532        cairo_paint_with_alpha(m_cr, fill_trans);
01533        cairo_surface_destroy (image2);
01534 */
01535 #else
01536        double affineresult[6];
01537        affineresult[0] = m_matrix.m11() * m_zoomFactor;
01538        affineresult[1] = m_matrix.m12() * m_zoomFactor;
01539        affineresult[2] = m_matrix.m21() * m_zoomFactor;
01540        affineresult[3] = m_matrix.m22() * m_zoomFactor;
01541        affineresult[4] = m_matrix.dx();
01542        affineresult[5] = m_matrix.dy();
01543        ksvg_art_rgb_affine_clip( m_clipPath, m_buffer, 0, 0, m_width, m_height, m_width * 4, 4,
01544                                     image->bits(), image->width(), image->height(), image->width() * 4,
01545                                     affineresult, qRound( 255 * fill_trans ), 0L );
01546        art_svp_free( m_clipPath );
01547        m_clipPath = 0;
01548 #endif
01549 }
01550 
01551 void ScPainter::setupPolygon(FPointArray *points, bool closed)
01552 {
01553        bool nPath = true;
01554        FPoint np, np1, np2, np3;
01555 #ifdef HAVE_CAIRO
01556        if (points->size() > 3)
01557        {
01558               newPath();
01559               for (uint poi=0; poi<points->size()-3; poi += 4)
01560               {
01561                      if (points->point(poi).x() > 900000)
01562                      {
01563                             nPath = true;
01564                             continue;
01565                      }
01566                      if (nPath)
01567                      {
01568                             np = points->point(poi);
01569                      cairo_move_to( m_cr, np.x(), np.y());
01570                             nPath = false;
01571                      }
01572                      np = points->point(poi);
01573                      np1 = points->point(poi+1);
01574                      np2 = points->point(poi+3);
01575                      np3 = points->point(poi+2);
01576                      if ((np == np1) && (np2 == np3))
01577                             cairo_line_to( m_cr, np3.x(), np3.y());
01578                      else
01579                             cairo_curve_to(m_cr, np1.x(), np1.y(), np2.x(), np2.y(), np3.x(), np3.y());
01580               }
01581               if (closed)
01582               cairo_close_path( m_cr );
01583        }
01584 #else
01585        // not HAVE_CAIRO
01586        if (points->size() > 3)
01587               {
01588               newPath();
01589               for (uint poi=0; poi<points->size()-3; poi += 4)
01590                      {
01591                      if (points->point(poi).x() > 900000)
01592                             {
01593                             nPath = true;
01594                             ensureSpace( m_index + 1 );
01595                             m_path[ m_index ].code = ART_END;
01596                             continue;
01597                             }
01598                      if (nPath)
01599                             {
01600                             np = points->point(poi);
01601                             ensureSpace( m_index + 1 );
01602                             if (closed)
01603                                    m_path[ m_index ].code = ART_MOVETO;
01604                             else
01605                                    m_path[ m_index ].code = ART_MOVETO_OPEN;
01606                             m_path[ m_index ].x3 = np.x() * m_zoomFactor;
01607                             m_path[ m_index ].y3 = np.y() * m_zoomFactor;
01608                             m_index++;
01609                             nPath = false;
01610                             }
01611                      np = points->point(poi);
01612                      np1 = points->point(poi+1);
01613                      np2 = points->point(poi+3);
01614                      np3 = points->point(poi+2);
01615                      ensureSpace( m_index + 1 );
01616                      if ((np == np1) && (np2 == np3))
01617                             {
01618                             m_path[ m_index ].code = ART_LINETO;
01619                             m_path[ m_index ].x3 = np3.x() * m_zoomFactor;
01620                             m_path[ m_index ].y3 = np3.y() * m_zoomFactor;
01621                             }
01622                      else
01623                             {
01624                             m_path[ m_index ].code = ART_CURVETO;
01625                             m_path[ m_index ].x1 = np1.x() * m_zoomFactor;
01626                             m_path[ m_index ].y1 = np1.y() * m_zoomFactor;
01627                             m_path[ m_index ].x2 = np2.x() * m_zoomFactor;
01628                             m_path[ m_index ].y2 = np2.y() * m_zoomFactor;
01629                             m_path[ m_index ].x3 = np3.x() * m_zoomFactor;
01630                             m_path[ m_index ].y3 = np3.y() * m_zoomFactor;
01631                             }
01632                      m_index++;
01633                      }
01634               ensureSpace( m_index + 1 );
01635               m_path[ m_index ].code = ART_END;
01636               m_index++;
01637               }
01638 #endif
01639 }
01640 
01641 void ScPainter::setupTextPolygon(FPointArray *points)
01642 {
01643        bool nPath = true;
01644        FPoint np, np1, np2, np3;
01645 #ifdef HAVE_CAIRO
01646        if (points->size() > 3)
01647        {
01648               newPath();
01649               for (uint poi=0; poi<points->size()-3; poi += 4)
01650               {
01651                      if (points->point(poi).x() > 900000)
01652                      {
01653                             nPath = true;
01654                             continue;
01655                      }
01656                      if (nPath)
01657                      {
01658                             np = points->point(poi);
01659                      cairo_move_to( m_cr, np.x(), np.y());
01660                             nPath = false;
01661                      }
01662                      np = points->point(poi);
01663                      np1 = points->point(poi+1);
01664                      np2 = points->point(poi+3);
01665                      np3 = points->point(poi+2);
01666                      if ((np == np1) && (np2 == np3))
01667                             cairo_line_to( m_cr, np3.x(), np3.y());
01668                      else
01669                             cairo_curve_to(m_cr, np1.x(), np1.y(), np2.x(), np2.y(), np3.x(), np3.y());
01670               }
01671        cairo_close_path( m_cr );
01672        }
01673 #else
01674        newPath();
01675        for (uint poi=0; poi<points->size()-3; poi += 4)
01676        {
01677               if (points->point(poi).x() > 900000)
01678               {
01679                      nPath = true;
01680                      ensureSpace( m_index + 1 );
01681                      m_path[ m_index ].code = ART_END;
01682                      continue;
01683               }
01684               if (nPath)
01685               {
01686                      np = points->point(poi);
01687                      ensureSpace( m_index + 1 );
01688                      m_path[ m_index ].code = ART_MOVETO;
01689                      m_path[ m_index ].x3 = np.x();
01690                      m_path[ m_index ].y3 = np.y();
01691                      m_index++;
01692                      nPath = false;
01693               }
01694               np = points->point(poi);
01695               np1 = points->point(poi+1);
01696               np2 = points->point(poi+3);
01697               np3 = points->point(poi+2);
01698               ensureSpace( m_index + 1 );
01699               if ((np == np1) && (np2 == np3))
01700               {
01701                      m_path[ m_index ].code = ART_LINETO;
01702                      m_path[ m_index ].x3 = np3.x();
01703                      m_path[ m_index ].y3 = np3.y();
01704               }
01705               else
01706               {
01707                      m_path[ m_index ].code = ART_CURVETO;
01708                      m_path[ m_index ].x1 = np1.x();
01709                      m_path[ m_index ].y1 = np1.y();
01710                      m_path[ m_index ].x2 = np2.x();
01711                      m_path[ m_index ].y2 = np2.y();
01712                      m_path[ m_index ].x3 = np3.x();
01713                      m_path[ m_index ].y3 = np3.y();
01714               }
01715               m_index++;
01716        }
01717        ensureSpace( m_index + 1 );
01718        m_path[ m_index ].code = ART_END;
01719        m_index++;
01720 #endif
01721 }
01722 
01723 void ScPainter::drawPolygon()
01724 {
01725        fillPath();
01726 }
01727 
01728 void ScPainter::drawPolyLine()
01729 {
01730        strokePath();
01731 }
01732 
01733 void ScPainter::drawLine(FPoint start, FPoint end)
01734 {
01735        newPath();
01736        moveTo(start.x(), start.y());
01737        lineTo(end.x(), end.y());
01738        strokePath();
01739 }
01740 
01741 void ScPainter::drawRect(double x, double y, double w, double h)
01742 {
01743        newPath();
01744        moveTo( x, y );
01745        lineTo( x+w, y );
01746        lineTo( x+w, y+h );
01747        lineTo( x, y+h );
01748        lineTo( x, y );
01749 #ifdef HAVE_CAIRO
01750        cairo_close_path( m_cr );
01751 #else
01752        ensureSpace( m_index + 1 );
01753        m_path[ m_index ].code = ART_END;
01754        m_index++;
01755 #endif
01756        fillPath();
01757        strokePath();
01758 }
01759 
01760 #ifdef HAVE_CAIRO
01761 #else
01762 void ScPainter::ensureSpace( unsigned int newindex )
01763 {
01764        if( m_index == 0 )
01765               {
01766               if( !m_path )
01767                      m_path = art_new( ArtBpath, INITIAL_ALLOC );
01768               m_alloccount = INITIAL_ALLOC;
01769               }
01770        else if( newindex > m_alloccount )
01771               {
01772               m_alloccount += ALLOC_INCREMENT;
01773               m_path = art_renew( m_path, ArtBpath, m_alloccount );
01774               }
01775 }
01776 
01777 void ScPainter::resize( unsigned int w, unsigned int h )
01778 {
01779        if( !m_buffer || w != m_width || h != m_height )
01780        {
01781               // TODO : realloc?
01782               art_free( m_buffer );
01783               m_buffer = 0;
01784               m_width = w;
01785               m_height = h;
01786               if ( m_width != 0 && m_height != 0 )
01787                      m_buffer = art_new( art_u8, m_width * m_height * 4 );
01788               clear();
01789        }
01790 }
01791 
01792 void ScPainter::clampToViewport( int &x0, int &y0, int &x1, int &y1 )
01793 {
01794        x0 = QMAX( x0, 0 );
01795        x0 = QMIN( x0, static_cast<int>( m_width ) );
01796        y0 = QMAX( y0, 0 );
01797        y0 = QMIN( y0, static_cast<int>( m_height ) );
01798        x1 = QMAX( x1, 0 );
01799        x1 = QMIN( x1, static_cast<int>( m_width ) );
01800        y1 = QMAX( y1, 0 );
01801        y1 = QMIN( y1, static_cast<int>( m_height ) );
01802 }
01803 
01804 void ScPainter::clampToViewport( const _ArtSVP &svp, int &x0, int &y0, int &x1, int &y1 )
01805 {
01806        ArtDRect bbox;
01807        art_drect_svp( &bbox, &svp );
01808        x0 = static_cast<int>( bbox.x0 );
01809        x0 = QMAX( x0, 0 );
01810        x0 = QMIN( x0, static_cast<int>( m_width ) );
01811        y0 = static_cast<int>( bbox.y0 );
01812        y0 = QMAX( y0, 0 );
01813        y0 = QMIN( y0, static_cast<int>( m_height ) );
01814        x1 = static_cast<int>( bbox.x1 ) + 1;
01815        x1 = QMAX( x1, 0 );
01816        x1 = QMIN( x1, static_cast<int>( m_width ) );
01817        y1 = static_cast<int>( bbox.y1 ) + 1;
01818        y1 = QMAX( y1, 0 );
01819        y1 = QMIN( y1, static_cast<int>( m_height ) );
01820 }
01821 
01822 void ScPainter::applyGradient( _ArtSVP *svp, bool fill )
01823 {
01824        int x0, y0, x1, y1;
01825        clampToViewport( *svp, x0, y0, x1, y1 );
01826        ArtRender *render = 0L;
01827        VGradient gradient;
01828        if (fill)
01829               gradient = fill_gradient;
01830        else
01831               gradient = stroke_gradient;
01832        double opa = fill ? fill_trans : stroke_trans;
01833        if (gradient.type() == VGradient::linear)
01834        {
01835               ArtGradientLinear *linear = art_new( ArtGradientLinear, 1 );
01836               linear->spread = ART_GRADIENT_PAD;
01837               double _x1 = static_cast<double>(gradient.origin().x());
01838               double _x2 = static_cast<double>(gradient.vector().x());
01839               double _y2 = static_cast<double>(gradient.origin().y());
01840               double _y1 = static_cast<double>(gradient.vector().y());
01841               double dx = ( _x2 - _x1 ) * m_zoomFactor;
01842               _y1 =  _y1 + m_matrix.dy() / m_zoomFactor;
01843               _y2 =  _y2 + m_matrix.dy() / m_zoomFactor;
01844               if (dx == 0.0)
01845                      dx = 1;
01846               double dy = ( _y1 - _y2 ) * m_zoomFactor;
01847               if (dy == 0.0)
01848                      dy = 1;
01849               double scale = 1.0 / ( dx * dx + dy * dy );
01850               linear->a = dx * scale;
01851               linear->b = dy * scale;
01852               linear->c = -( ( _x1 * m_zoomFactor + m_matrix.dx() ) * linear->a + ( _y2 * m_zoomFactor ) * linear->b );
01853               int offsets = -1;
01854               linear->stops = buildStopArray( gradient, offsets );
01855               linear->n_stops = offsets;
01856               if( x0 != x1 && y0 != y1 )
01857               {
01858                      render = art_render_new( x0, y0, x1, y1, m_buffer + 4 * static_cast<int>(x0) + m_width * 4 * static_cast<int>(y0), m_width * 4, 3, 8, ART_ALPHA_PREMUL, 0 );
01859                      int opacity = static_cast<int>( opa * 255.0 );
01860                      art_render_svp( render, svp );
01861                      art_render_mask_solid (render, (opacity << 8) + opacity + (opacity >> 7));
01862                      art_karbon_render_gradient_linear( render, linear, ART_FILTER_NEAREST );
01863                      art_render_invoke( render );
01864               }
01865               art_free( linear->stops );
01866               art_free( linear );
01867        }
01868        else if( gradient.type() == VGradient::radial )
01869        {
01870               ArtGradientRadial *radial = art_new( ArtGradientRadial, 1 );
01871               radial->spread = ART_GRADIENT_PAD;
01872               radial->affine[0] = m_matrix.m11();
01873               radial->affine[1] = m_matrix.m12();
01874               radial->affine[2] = m_matrix.m21();
01875               radial->affine[3] = m_matrix.m22();
01876               radial->affine[4] = m_matrix.dx();
01877               radial->affine[5] = m_matrix.dy();
01878               double cx = gradient.origin().x() * m_zoomFactor;
01879               double cy = gradient.origin().y() * m_zoomFactor;
01880               double fx = gradient.focalPoint().x() * m_zoomFactor;
01881               double fy = gradient.focalPoint().y() * m_zoomFactor;
01882               double r = sqrt( pow( gradient.vector().x() - gradient.origin().x(), 2 ) + pow( gradient.vector().y() - gradient.origin().y(), 2 ) );
01883               r *= m_zoomFactor;
01884               radial->fx = (fx - cx) / r;
01885               radial->fy = (fy - cy) / r;
01886               double aff1[6], aff2[6];
01887               art_affine_scale( aff1, r, r);
01888               art_affine_translate( aff2, cx, cy );
01889               art_affine_multiply( aff1, aff1, aff2 );
01890               art_affine_multiply( aff1, aff1, radial->affine );
01891               art_affine_invert( radial->affine, aff1 );
01892               int offsets = -1;
01893               radial->stops = buildStopArray( gradient, offsets );
01894               radial->n_stops = offsets;
01895               if( x0 != x1 && y0 != y1 )
01896               {
01897                      render = art_render_new( x0, y0, x1, y1, m_buffer + 4 * x0 + m_width * 4 * y0, m_width * 4, 3, 8, ART_ALPHA_PREMUL, 0 );
01898                      int opacity = static_cast<int>( opa * 255.0 );
01899                      art_render_svp( render, svp );
01900                      art_render_mask_solid (render, (opacity << 8) + opacity + (opacity >> 7));
01901                      art_karbon_render_gradient_radial( render, radial, ART_FILTER_NEAREST );
01902                      art_render_invoke( render );
01903               }
01904               art_free( radial->stops );
01905               art_free( radial );
01906        }
01907 }
01908 
01909 ArtGradientStop * ScPainter::buildStopArray( VGradient &gradient, int &offsets )
01910 {
01911        QPtrVector<VColorStop> colorStops = gradient.colorStops();
01912        offsets = colorStops.count();
01913        ArtGradientStop *stopArray = art_new( ArtGradientStop, offsets * 2 - 1 );
01914        for( int offset = 0 ; offset < offsets ; offset++ )
01915        {
01916               double ramp = colorStops[ offset ]->rampPoint;
01917               stopArray[ offset * 2 ].offset = ramp;
01918               QColor qStopColor = colorStops[ offset ]->color;
01919               int h, s, v, sneu, vneu;
01920               int shad = colorStops[offset]->shade;
01921               qStopColor.hsv(&h, &s, &v);
01922               sneu = s * shad / 100;
01923               vneu = 255 - ((255 - v) * shad / 100);
01924               qStopColor.setHsv(h, sneu, vneu);
01925               int r = qRed( qStopColor.rgb() );
01926               int g = qGreen( qStopColor.rgb() );
01927               int b = qBlue( qStopColor.rgb() );
01928               art_u32 rgba = (r << 24) | (g << 16) | (b << 8) | qAlpha(qStopColor.rgb());
01929               int a = static_cast<int>( colorStops[offset]->opacity * 255.0 );
01930               r = (rgba >> 24) * a + 0x80;
01931               r = (r + (r >> 8)) >> 8;
01932               g = ((rgba >> 16) & 0xff) * a + 0x80;
01933               g = (g + (g >> 8)) >> 8;
01934               b = ((rgba >> 8) & 0xff) * a + 0x80;
01935               b = (b + (b >> 8)) >> 8;
01936               stopArray[ offset * 2 ].color[ 0 ] = ART_PIX_MAX_FROM_8(r);
01937               stopArray[ offset * 2 ].color[ 1 ] = ART_PIX_MAX_FROM_8(g);
01938               stopArray[ offset * 2 ].color[ 2 ] = ART_PIX_MAX_FROM_8(b);
01939               stopArray[ offset * 2 ].color[ 3 ] = ART_PIX_MAX_FROM_8(a);
01940               if( offset + 1 != offsets )
01941               {
01942                      stopArray[ offset * 2 + 1 ].offset = ramp + ( colorStops[ offset + 1 ]->rampPoint - ramp ) * colorStops[ offset ]->midPoint;
01943                      QColor qStopColor2 = colorStops[ offset + 1 ]->color;
01944                      rgba = static_cast<int>(r + ((qRed(qStopColor2.rgb()) - r)) * 0.5) << 24 |
01945                                            static_cast<int>(g + ((qGreen(qStopColor2.rgb()) - g)) * 0.5) << 16 |
01946                                            static_cast<int>(b + ((qBlue(qStopColor2.rgb()) - b)) * 0.5) << 8 |
01947                                           qAlpha(qStopColor2.rgb());
01948                      int a = static_cast<int>( colorStops[offset]->opacity * 255.0 );
01949                      r = (rgba >> 24) * a + 0x80;
01950                      r = (r + (r >> 8)) >> 8;
01951                      g = ((rgba >> 16) & 0xff) * a + 0x80;
01952                      g = (g + (g >> 8)) >> 8;
01953                      b = ((rgba >> 8) & 0xff) * a + 0x80;
01954                      b = (b + (b >> 8)) >> 8;
01955                      stopArray[ offset * 2 + 1 ].color[ 0 ] = ART_PIX_MAX_FROM_8(r);
01956                      stopArray[ offset * 2 + 1 ].color[ 1 ] = ART_PIX_MAX_FROM_8(g);
01957                      stopArray[ offset * 2 + 1 ].color[ 2 ] = ART_PIX_MAX_FROM_8(b);
01958                      stopArray[ offset * 2 + 1 ].color[ 3 ] = ART_PIX_MAX_FROM_8(a);
01959               }
01960        }
01961        offsets = offsets * 2 - 1;
01962        return stopArray;
01963 }
01964 
01965 void ScPainter::applyPattern( ArtSVP *svp)
01966 {
01967        if(!svp)
01968               return;
01969        int x0, y0, x1, y1;
01970        clampToViewport( *svp, x0, y0, x1, y1 );
01971        ArtRender *render = 0L;
01972        ArtPattern *pattern = art_new( ArtPattern, 1 );
01973        double dx = 0.0;
01974        double dy =0.0;
01975        QImage pat = m_pattern->getPattern()->scale(m_pattern->getPattern()->width() * m_zoomFactor * patternScaleX, m_pattern->getPattern()->height() * m_zoomFactor * patternScaleY);
01976        pattern->twidth = pat.width();
01977        pattern->theight = pat.height();
01978        pattern->buffer = pat.bits();
01979        pattern->opacity = qRound( 255 * fill_trans );
01980        pattern->angle = patternRotation * 3.1415927 / 180.0;
01981        if( x0 != x1 && y0 != y1 )
01982        {
01983               render = art_render_new( x0, y0, x1, y1, m_buffer + 4 * int(x0) + m_width * 4 * int(y0), m_width * 4, 3, 8, ART_ALPHA_PREMUL, 0 );
01984               art_render_svp( render, svp );
01985               art_render_pattern( render, pattern, ART_FILTER_HYPER );
01986        }
01987        if( render )
01988               art_render_invoke( render );
01989        art_free( pattern );
01990 }
01991 //not HAVE_CAIRO
01992 #endif