Back to index

scribus-ng  1.3.4.dfsg+svn20071115
scpainterex_gdi.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 #ifdef WIN32_LEAN_AND_MEAN
00029 #undef WIN32_LEAN_AND_MEAN
00030 #endif
00031 
00032 #include <valarray>
00033 #include <windows.h>
00034 
00035 #include "scconfig.h"
00036 
00037 #ifdef SC_USE_GDIPLUS
00038 #include <gdiplus.h>
00039 using namespace Gdiplus;
00040 #endif
00041 
00042 #include "scribusdoc.h"
00043 #include "scpainterex_gdi.h"
00044 #include "sccolorengine.h"
00045 
00046 #include <qpaintdevice.h>
00047 #include <qpixmap.h>
00048 #include <qpointarray.h>
00049 #include <qimage.h>
00050 
00051 #include <iostream>
00052 using namespace std;
00053  
00054 #include <math.h>
00055 
00056 typedef struct { 
00057     BITMAPINFOHEADER bmiHeader; 
00058     RGBQUAD bmiColors[256]; 
00059 } BITMAPINFO256;
00060 
00061 ScPainterEx_GDI::ScPainterEx_GDI( HDC hDC, QRect& rect,  ScribusDoc* doc, bool gray ) : ScPainterExBase()
00062 {
00063        m_doc = doc;
00064        m_width = rect.width();
00065        m_height= rect.height();
00066        m_strokeColor = ScColorShade( QColor(0,0,0), 100 );
00067        m_fillColor = ScColorShade( QColor(0,0,0), 100 );
00068        m_fillTrans = 1.0;
00069        m_strokeTrans = 1.0;
00070        m_fillRule = true;
00071        m_fillMode = 1;
00072        m_lineWidth = 1.0;
00073        m_offset = 0;
00074        m_array.clear();
00075        m_lineEnd = Qt::SquareCap;
00076        m_lineJoin = Qt::RoundJoin;
00077        m_fillGradient = VGradientEx(VGradientEx::linear);
00078        m_strokeGradient = VGradientEx(VGradientEx::linear);
00079        m_matrix = QWMatrix();
00080        // Grayscale conversion parameter
00081        m_convertToGray = gray;
00082        // Initialization of Windows GDI data
00083        m_dc = hDC;
00084        m_hBmp = NULL;
00085        m_hMsImg32 = NULL;
00086        m_gradientFill = NULL;
00087        m_pathIsClosed = true;
00088        m_drawingClosedPath = false;
00089        m_deviceDimX = GetDeviceCaps(m_dc, PHYSICALWIDTH);
00090        m_deviceDimY = GetDeviceCaps(m_dc, PHYSICALHEIGHT);
00091        m_deviceResX = GetDeviceCaps(m_dc, LOGPIXELSX);
00092        m_deviceResY = GetDeviceCaps(m_dc, LOGPIXELSY);
00093 #ifdef SC_USE_GDIPLUS
00094        m_positionX = m_positionY = 0;
00095        m_graphics = new Gdiplus::Graphics( m_dc );
00096        m_graphics->SetCompositingMode( CompositingModeSourceOver );
00097        m_graphics->SetCompositingQuality( CompositingQualityHighQuality );
00098        m_graphics->SetSmoothingMode( SmoothingModeHighQuality );
00099        m_graphics->SetPageUnit( UnitPoint );
00100        m_graphicsPath = NULL;
00101 #else
00102        SetGraphicsMode( m_dc, GM_ADVANCED );
00103        SetPolyFillMode(m_dc, ALTERNATE);
00104        loadMsImg32();
00105 #endif
00106        clear();
00107 }
00108 
00109 ScPainterEx_GDI::~ScPainterEx_GDI()
00110 {
00111        if ( m_hMsImg32 )
00112               FreeLibrary( m_hMsImg32 );
00113 #ifdef SC_USE_GDIPLUS
00114        if ( m_graphicsPath )
00115               delete m_graphicsPath;
00116        if ( m_graphics )
00117               delete m_graphics;
00118 #endif
00119 }
00120 
00121 void ScPainterEx_GDI::loadMsImg32( void )
00122 {
00123        m_hMsImg32 = LoadLibrary( "msimg32.dll" );
00124        if( m_hMsImg32 )
00125               m_gradientFill = (gradientFillFunc) GetProcAddress( m_hMsImg32, "GradientFill" );
00126 }
00127 
00128 QColor ScPainterEx_GDI::transformColor( ScColorShade& colorShade, double trans )
00129 {
00130        QColor c, color;
00131        c = ScColorEngine::getShadeColor(colorShade.color, m_doc, colorShade.shade);
00132        color = qRgba( qRed(c.rgb()), qGreen(c.rgb()), qBlue(c.rgb()), qAlpha(trans * 255));
00133        if ( m_convertToGray )
00134        {
00135               int grayLevel;
00136               QColor grayColor;
00137               grayLevel = 0.3 * color.red() + 0.59 * color.green() + 0.11 * color.blue();
00138               grayColor = qRgba( grayLevel, grayLevel, grayLevel, qAlpha(color.rgb()));
00139               color = grayColor;
00140        }
00141        return color;
00142 }
00143 
00144 void ScPainterEx_GDI::transformImage( QImage* image, uchar* data, int scan)
00145 {
00146        int rgb, grey;
00147        int imageWidth = image->width();
00148        int imageHeight = image->height();
00149        QRgb* imageBits = (QRgb *) image->bits();
00150        QRgb*  pscani;
00151        uchar *pscand;
00152 
00153        pscand = data;
00154        for ( int j = 0; j < imageHeight; j++ )
00155        {
00156               pscani = (QRgb *) image->scanLine(j);
00157               for (int i = 0; i < imageWidth; i++ )
00158               {
00159                      rgb = pscani[i];
00160                      grey = 0.3 * qRed(rgb) + 0.59 * qGreen(rgb) + 0.11 * qBlue(rgb);
00161                      pscand[i] = grey;
00162               }
00163               pscand += scan;
00164        }
00165 
00166 }
00167 
00168 void ScPainterEx_GDI::begin()
00169 {
00170 }
00171 
00172 void ScPainterEx_GDI::end()
00173 {
00174 #ifdef SC_USE_GDIPLUS
00175        m_graphics->ResetTransform();
00176 #else
00177        ModifyWorldTransform(m_dc, NULL, MWT_IDENTITY);
00178 #endif
00179 }
00180 
00181 void ScPainterEx_GDI::clear()
00182 {
00183 #ifdef SC_USE_GDIPLUS
00184        SolidBrush brush( Color(255,255,255) );
00185        m_graphics->FillRectangle(&brush, 0, 0, m_width, m_height);
00186 #else
00187        RECT rect;
00188        HBRUSH brush = CreateSolidBrush( RGB(255, 255, 255) );
00189        rect.bottom = 0;
00190        rect.left = 0;
00191        rect.right = m_width;
00192        rect.top = m_height;
00193        FillRect(m_dc, &rect, brush);
00194        DeleteObject( brush );
00195 #endif
00196 }
00197 
00198 void ScPainterEx_GDI::clear( ScColorShade &c )
00199 {
00200        QColor color = transformColor( c, 1.0 );
00201 #ifdef SC_USE_GDIPLUS
00202        QRgb cs = color.rgb();
00203        SolidBrush brush( Color(qAlpha(cs), qRed(cs), qGreen(cs),qBlue(cs)) );
00204        m_graphics->FillRectangle(&brush, 0, 0, m_width, m_height);
00205 #else
00206        RECT rect;
00207        HBRUSH brush = CreateSolidBrush( RGB( qRed(color.rgb()), qGreen(color.rgb()), qBlue(color.rgb()) ) );
00208        rect.bottom = 0;
00209        rect.left = 0;
00210        rect.right = m_width;
00211        rect.top = m_height;
00212        FillRect(m_dc, &rect, brush);
00213        DeleteObject( brush );
00214 #endif
00215 }
00216 
00217 const QWMatrix ScPainterEx_GDI::worldMatrix()
00218 {
00219        return m_matrix;
00220 }
00221 
00222 void ScPainterEx_GDI::setWorldMatrix( const QWMatrix &mat )
00223 {
00224        m_matrix = mat;
00225 }
00226 
00227 void ScPainterEx_GDI::transformPoint( const FPoint& in, FPoint& out )
00228 {
00229        double x, y;
00230        x = in.x() * m_matrix.m11() + in.y() * m_matrix.m21() + m_matrix.dx();
00231        y = in.x() * m_matrix.m12() + in.y() * m_matrix.m22() + m_matrix.dy();
00232        out.setX( x );
00233        out.setY( y );
00234 }
00235 
00236 void ScPainterEx_GDI::transformPoints( const FPoint* ArrayIn, FPoint* ArrayOut, uint length )
00237 {
00238        for( uint i = 0; i < length; i++ )
00239        {
00240               transformPoint( ArrayIn[i], ArrayOut[i] );
00241        }
00242 }
00243 
00244 void ScPainterEx_GDI::translate( double x, double y )
00245 {
00246        m_matrix.translate(x, y);
00247 }
00248 
00249 void ScPainterEx_GDI::rotate( double r )
00250 {
00251        m_matrix.rotate(r);
00252 }
00253 
00254 void ScPainterEx_GDI::scale( double x, double y )
00255 {
00256        m_matrix.scale(x, y);
00257 }
00258 
00259 void ScPainterEx_GDI::moveTo( const double &x, const double &y )
00260 {
00261        FPoint pp( x, y );
00262        transformPoint( pp, pp );
00263 #ifdef SC_USE_GDIPLUS
00264        m_positionX = pp.x();
00265        m_positionY = pp.y();
00266 #else
00267        MoveToEx(m_dc, (int) pp.x(), (int) pp.y(), NULL);
00268 #endif
00269 }
00270 
00271 void ScPainterEx_GDI::lineTo( const double &x, const double &y )
00272 {
00273        FPoint pp( x, y );
00274        transformPoint( pp, pp );
00275 #ifdef SC_USE_GDIPLUS
00276        m_graphicsPath->AddLine( (REAL) m_positionX, (REAL) m_positionY, pp.x(), pp.y() );
00277        m_positionX = pp.x();
00278        m_positionY = pp.y();
00279 #else
00280        LineTo(m_dc, (int) pp.x(), (int) pp.y());
00281 #endif
00282 }
00283 
00284 void ScPainterEx_GDI::curveTo( FPoint p1, FPoint p2, FPoint p3 )
00285 {
00286        FPoint fpoints[3];
00287        fpoints[0].setXY( p1.x(), p1.y() );
00288        fpoints[1].setXY( p2.x(), p2.y() );
00289        fpoints[2].setXY( p3.x(), p3.y() );
00290        transformPoints( fpoints, fpoints, 3 );
00291 #ifdef SC_USE_GDIPLUS
00292        double p1x = fpoints[0].x();
00293        double p1y = fpoints[0].y();
00294        double p2x = fpoints[1].x();
00295        double p2y = fpoints[1].y();
00296        double p3x = fpoints[2].x();
00297        double p3y = fpoints[2].y();
00298        m_graphicsPath->AddBezier( (REAL) m_positionX, (REAL) m_positionY, p1x, p1y, p2x, p2y, p3x, p3y );
00299        m_positionX = p3x;
00300        m_positionY = p3y;
00301 #else
00302        POINT points[3];
00303        points[0].x = fpoints[0].x();
00304        points[0].y = fpoints[0].y();
00305        points[1].x = fpoints[1].x();
00306        points[1].y = fpoints[1].y();
00307        points[2].x = fpoints[2].x();
00308        points[2].y = fpoints[2].y();
00309        PolyBezierTo(m_dc, points, 3);
00310 #endif
00311 }
00312 
00313 void ScPainterEx_GDI::newPath()
00314 {
00315 #ifdef SC_USE_GDIPLUS
00316        if( m_graphicsPath )
00317               delete m_graphicsPath;
00318        m_graphicsPath = new Gdiplus::GraphicsPath(); 
00319        m_pathIsClosed = false;
00320        m_drawingClosedPath = false;
00321 #else
00322        bool done = BeginPath( m_dc );
00323        if(!done)
00324               cout << "BeginPath fuction has failed." << endl;
00325        m_pathIsClosed = false;
00326        m_drawingClosedPath = false;
00327 #endif
00328 }
00329 
00330 void ScPainterEx_GDI::setFillRule( bool fillRule )
00331 {
00332        m_fillRule = fillRule;
00333 }
00334 
00335 void ScPainterEx_GDI::setFillMode( int fill )
00336 {
00337        m_fillMode = fill;
00338 }
00339 
00340 void ScPainterEx_GDI::setGradient(VGradientEx::Type mode, FPoint orig, FPoint vec, FPoint foc)
00341 {
00342        m_fillGradient.setType(mode);
00343        m_fillGradient.setOrigin(orig);
00344        m_fillGradient.setVector(vec);
00345        m_fillGradient.setFocalPoint(foc);
00346 }
00347 
00348 void ScPainterEx_GDI::setPattern( ScPattern* pattern, QWMatrix& patternTransform )
00349 {
00350        m_pattern = pattern;
00351        m_patternTransform = patternTransform;
00352 }
00353 
00354 void ScPainterEx_GDI::fillTextPath()
00355 {
00356        drawVPath( 0 );
00357 }
00358 
00359 void ScPainterEx_GDI::strokeTextPath()
00360 {
00361        if( m_lineWidth == 0 )
00362               return;
00363        drawVPath( 1 );
00364 }
00365 
00366 void ScPainterEx_GDI::fillPath()
00367 {
00368 #ifndef SC_USE_GDIPLUS
00369        if( !m_pathIsClosed )
00370               EndPath( m_dc );
00371 #endif
00372        m_pathIsClosed = true;
00373        if( m_fillMode != 0)
00374               drawVPath( 0 );
00375 }
00376 
00377 void ScPainterEx_GDI::strokePath()
00378 {
00379        if( m_lineWidth == 0 )
00380               return;
00381 #ifndef SC_USE_GDIPLUS
00382        if( !m_pathIsClosed )
00383               EndPath( m_dc );
00384 #endif
00385        m_pathIsClosed = true;
00386        drawVPath( 1 );
00387 }
00388 
00389 ScColorShade ScPainterEx_GDI::pen()
00390 {
00391        return m_strokeColor;
00392 }
00393 
00394 ScColorShade ScPainterEx_GDI::brush()
00395 {
00396        return m_fillColor;
00397 }
00398 
00399 void ScPainterEx_GDI::setPen( const ScColorShade &c )
00400 {
00401        m_strokeColor = c;
00402 }
00403 
00404 void ScPainterEx_GDI::setPen( const ScColorShade &c, double w, Qt::PenStyle st, Qt::PenCapStyle ca, Qt::PenJoinStyle jo )
00405 {
00406        m_strokeColor = c;
00407        m_lineWidth = w;
00408        m_lineEnd = ca;
00409        m_lineJoin = jo;
00410        double Dt = QMAX(2*w, 1);
00411        double Da = QMAX(6*w, 1);
00412        QValueList<double> tmp;
00413        m_array.clear();
00414        m_offset = 0;
00415        switch (st)
00416        {
00417               case Qt::SolidLine:
00418                      break;
00419               case Qt::DashLine:
00420                      m_array.append(Da);
00421                      m_array.append(Dt);
00422                      break;
00423               case Qt::DotLine:
00424                      m_array.append(Dt);
00425 #ifdef SC_USE_GDIPLUS
00426                      m_array.append(Dt);
00427 #endif
00428                      break;
00429               case Qt::DashDotLine:
00430                      m_array.append(Da);
00431                      m_array.append(Dt);
00432                      m_array.append(Dt);
00433                      m_array.append(Dt);
00434                      break;
00435               case Qt::DashDotDotLine:
00436                      m_array.append(Da);
00437                      m_array.append(Dt);
00438                      m_array.append(Dt);
00439                      m_array.append(Dt);
00440                      m_array.append(Dt);
00441                      m_array.append(Dt);
00442                      break;
00443               default:
00444                      break;
00445        }
00446 }
00447 
00448 void ScPainterEx_GDI::setLineWidth( double w )
00449 {
00450        m_lineWidth = w;
00451 }
00452 
00453 void ScPainterEx_GDI::setPenOpacity( double op )
00454 {
00455        m_strokeTrans = op;
00456 }
00457 
00458 
00459 void ScPainterEx_GDI::setDash(const QValueList<double>& array, double ofs)
00460 {
00461        m_array = array;
00462        m_offset = ofs;
00463 }
00464 
00465 void ScPainterEx_GDI::setBrush( const ScColorShade &c )
00466 {
00467        m_fillColor = c;
00468 }
00469 
00470 void ScPainterEx_GDI::setBrushOpacity( double op )
00471 {
00472        m_fillTrans = op;
00473 }
00474 
00475 void ScPainterEx_GDI::setOpacity( double op )
00476 {
00477        m_fillTrans = op;
00478        m_strokeTrans = op;
00479 }
00480 
00481 void ScPainterEx_GDI::setFont( const QFont &f)
00482 {
00483        m_font = f;
00484 }
00485 
00486 QFont ScPainterEx_GDI::font()
00487 {
00488        return m_font;
00489 }
00490 
00491 void ScPainterEx_GDI::save()
00492 {
00493        m_stack.push( m_matrix );
00494 #ifdef SC_USE_GDIPLUS
00495        m_gStates.push( m_graphics->Save() );
00496 #else
00497        SaveDC( m_dc );
00498 #endif
00499 }
00500 
00501 void ScPainterEx_GDI::restore()
00502 {
00503        m_matrix = m_stack.pop();
00504 #ifdef SC_USE_GDIPLUS
00505        m_graphics->Restore( m_gStates.pop() );
00506 #else
00507        RestoreDC( m_dc, -1 );
00508 #endif
00509 }
00510 
00511 void ScPainterEx_GDI::setRasterOp( int   )
00512 {
00513 }
00514 
00515 void ScPainterEx_GDI::drawVPath( int mode )
00516 {
00517 #ifdef SC_USE_GDIPLUS
00518        save();
00519        if (mode == 0)
00520        {
00521               if( m_fillRule )
00522                      m_graphicsPath->SetFillMode( FillModeAlternate);
00523               else
00524                      m_graphicsPath->SetFillMode( FillModeWinding);
00525               if (m_fillMode == ScPainterExBase::Gradient)
00526               {
00527                      drawGradient( m_fillGradient );
00528               }
00529               else
00530               {
00531                      QColor fillColor = transformColor(m_fillColor, 1.0);
00532                      SolidBrush fill_brush( Color(m_fillTrans * 255, fillColor.red(), fillColor.green(), fillColor.blue()) );
00533                      m_graphics->FillPath( &fill_brush, m_graphicsPath );
00534               }
00535        }
00536        else
00537        {
00538               double m11 = m_matrix.m11();
00539               double m12 = m_matrix.m12();
00540               double m21 = m_matrix.m21();
00541               double m22 = m_matrix.m22();
00542               double norm2 = m11 * m11 + m12 * m12 + m21 * m21 + m22 * m22;
00543               double penScale = sqrt(norm2 / 2.0);
00544               double penWidth =  m_lineWidth * penScale;
00545               QColor strokeColor = transformColor( m_strokeColor, 1.0 );
00546               SolidBrush stroke_brush( Color(m_strokeTrans * 255, strokeColor.red(), strokeColor.green(), strokeColor.blue()) );
00547               Pen stroke_pen( &stroke_brush, penWidth );
00548               REAL *dashes = NULL;
00549               
00550               if( m_array.count() > 0 )
00551               {
00552                      dashes = new REAL[ m_array.count() ];
00553                      for( uint i = 0; i < m_array.count();++ i )
00554                      {
00555                             dashes[i] = (REAL) ( m_array[i] / (double) m_lineWidth );
00556                             // The following lines are needed so that gdi+ rendering matches the libart one
00557                             if( m_lineEnd == Qt::RoundCap || m_lineEnd == Qt::SquareCap )
00558                             {
00559                                    if( (i % 2) == 0 ) 
00560                                           dashes[i] = dashes[i] + 1.0;
00561                                    else
00562                                           dashes[i] = dashes[i] - 1.0;
00563                             }
00564                      }
00565                      // The following two lines are needed so that gdi+ rendering matches the libart one
00566                      if( m_lineEnd == Qt::SquareCap && m_array.count() >= 2)
00567                             stroke_pen.SetDashOffset( dashes[1]/2 );
00568                      stroke_pen.SetDashPattern( dashes, m_array.count() );
00569               }
00570               if( m_lineEnd == Qt::RoundCap )
00571                      stroke_pen.SetLineCap( LineCapRound, LineCapRound, DashCapRound );
00572               else if( m_lineEnd == Qt::SquareCap )
00573                      stroke_pen.SetLineCap( LineCapSquare, LineCapSquare, DashCapFlat );
00574               else if( m_lineEnd == Qt::FlatCap && m_array.count() == 0 && m_drawingClosedPath )
00575                      stroke_pen.SetLineCap( LineCapSquare, LineCapSquare, DashCapFlat );
00576               else if( m_lineEnd == Qt::FlatCap )
00577                      stroke_pen.SetLineCap( LineCapFlat, LineCapFlat, DashCapFlat );
00578               if( m_lineJoin == Qt::RoundJoin )
00579                      stroke_pen.SetLineJoin( LineJoinRound );
00580               else if( m_lineJoin == Qt::BevelJoin )
00581                      stroke_pen.SetLineJoin( LineJoinBevel );
00582               else if( m_lineJoin == Qt::MiterJoin )
00583                      stroke_pen.SetLineJoin( LineJoinMiter );
00584 
00585               m_graphics->DrawPath( &stroke_pen, m_graphicsPath );
00586               if( dashes )
00587                      delete [] dashes;
00588        }
00589        restore();
00590 #else
00591        int dcState;
00592        dcState = SaveDC( m_dc );
00593        if (mode == 0)
00594        {
00595               if( m_fillRule )
00596                      SetPolyFillMode(m_dc, ALTERNATE);
00597               else
00598                      SetPolyFillMode(m_dc, WINDING);
00599               if (m_fillMode == ScPainterExBase::Gradient)
00600               {
00601                      drawGradient( m_fillGradient );
00602               }
00603               else
00604               {
00605                      QColor fillColor = transformColor( m_fillColor, 1.0 );
00606                      HBRUSH brush = CreateSolidBrush( RGB( qRed(fillColor.rgb()), qGreen(fillColor.rgb()), qBlue(fillColor.rgb()) ) );
00607                      HGDIOBJ obj = SelectObject(m_dc, brush);
00608                      FillPath(m_dc);
00609                      SelectObject(m_dc, obj);
00610                      DeleteObject(brush);
00611               }
00612        }
00613        else
00614        {
00615               DWORD penStyle = PS_GEOMETRIC;
00616               DWORD penWidth = 0;
00617               LOGBRUSH logBrush;
00618               DWORD *dashes = NULL;
00619 
00620               QColor strokeColor = transformColor( m_strokeColor, 1.0 );
00621               logBrush.lbStyle = BS_SOLID;
00622               logBrush.lbColor = RGB( qRed(strokeColor.rgb()), qGreen(strokeColor.rgb()), qBlue(strokeColor.rgb()) );
00623               logBrush.lbHatch = 0;
00624 
00625               double m11 = m_matrix.m11();
00626               double m12 = m_matrix.m12();
00627               double m21 = m_matrix.m21();
00628               double m22 = m_matrix.m22();
00629               double norm2 = m11 * m11 + m12 * m12 + m21 * m21 + m22 * m22;
00630               double penScale = sqrt(norm2 /2.0);
00631               penWidth = (int) (m_lineWidth * penScale);
00632               
00633               if( m_array.count() > 0 )
00634               {
00635                      dashes = new DWORD[ m_array.count() ];
00636                      for( uint i = 0; i < m_array.count();++ i )
00637                      {
00638                             dashes[i] = (DWORD) (m_array[i] * penScale);
00639                      }
00640                      penStyle = penStyle | PS_USERSTYLE; 
00641               }
00642               if( PLineEnd == Qt::RoundCap )
00643                      penStyle = penStyle | PS_ENDCAP_ROUND;
00644               else if( PLineEnd == Qt::SquareCap )
00645                      penStyle = penStyle | PS_ENDCAP_SQUARE;
00646               else if( PLineEnd == Qt::FlatCap && m_array.count() == 0 && m_drawingClosedPath )
00647                      penStyle = penStyle | PS_ENDCAP_SQUARE;
00648               else if( PLineEnd == Qt::FlatCap )
00649                      penStyle = penStyle | PS_ENDCAP_FLAT;
00650               if( m_lineJoin == Qt::RoundJoin )
00651                      penStyle = penStyle | PS_JOIN_ROUND;
00652               else if( m_lineJoin == Qt::BevelJoin )
00653                      penStyle = penStyle | PS_JOIN_BEVEL;
00654               else if( m_lineJoin == Qt::MiterJoin )
00655                      penStyle = penStyle | PS_JOIN_MITER;
00656 
00657               HPEN pen = ExtCreatePen(penStyle, penWidth, &logBrush, m_array.count(), dashes);
00658               HGDIOBJ obj = SelectObject( m_dc, pen);
00659               StrokePath( m_dc );
00660               SelectObject( m_dc, obj);
00661               DeleteObject( pen);
00662               if( dashes )
00663                      delete [] dashes;
00664        }
00665        RestoreDC( m_dc, dcState );
00666 #endif
00667 }
00668 
00669 void ScPainterEx_GDI::setClipPath()
00670 {
00671 #ifdef SC_USE_GDIPLUS
00672        m_graphics->SetClip( m_graphicsPath, CombineModeIntersect );
00673 #else
00674        SelectClipPath( m_dc, RGN_AND );
00675 #endif
00676 }
00677 
00678 void ScPainterEx_GDI::drawImage( ScImage *image, ScPainterExBase::ImageMode mode )
00679 {
00680 #ifdef SC_USE_GDIPLUS
00681        FPoint ulp( 0, 0 );
00682        FPoint urp( image->width(), 0 );
00683        FPoint blp( 0, image->height() );
00684        transformPoint( ulp, ulp );
00685        transformPoint( blp, blp );
00686        transformPoint( urp, urp );
00687        Point destinationPoint[] = { Point(ulp.x(), ulp.y()), Point(urp.x(), urp.y()), Point(blp.x(), blp.y()) };
00688        ColorMatrix colorMatrix = {1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
00689                                                     0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
00690                                0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
00691                                0.0f, 0.0f, 0.0f, m_fillTrans, 0.0f,
00692                                0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
00693        if ( m_convertToGray )
00694        {
00695               colorMatrix.m[0][0] = colorMatrix.m[0][1] = colorMatrix.m[0][2] = (REAL) 0.3;
00696               colorMatrix.m[1][0] = colorMatrix.m[1][1] = colorMatrix.m[1][2] = (REAL) 0.59;
00697               colorMatrix.m[2][0] = colorMatrix.m[2][1] = colorMatrix.m[2][2] = (REAL) 0.11;
00698        }
00699        ImageAttributes imageAtt;
00700        imageAtt.SetColorMatrix(&colorMatrix, ColorMatrixFlagsDefault, ColorAdjustTypeBitmap);
00701        Bitmap bitmap( image->width(), image->height(), 4 * image->width(), PixelFormat32bppARGB, image->qImage().bits() );
00702        m_graphics->DrawImage( &bitmap, destinationPoint, 3, 0, 0, image->width(), image->height(), UnitPixel, &imageAtt );
00703 #else
00704        save();
00705        int usage = 0;
00706        unsigned char* data = NULL;
00707        unsigned char* imageData = image->qImage().bits();
00708        XFORM xform = { m_matrix.m11(), m_matrix.m12(), m_matrix.m21(), m_matrix.m22(), m_matrix.dx(), m_matrix.dy() } ;
00709        ModifyWorldTransform(m_dc, &xform, MWT_LEFTMULTIPLY);
00710        BITMAPINFO256 bmpInfo;
00711        ZeroMemory( &bmpInfo, sizeof(bmpInfo));
00712        bmpInfo.bmiHeader.biSize = sizeof( bmpInfo.bmiHeader );
00713        bmpInfo.bmiHeader.biWidth = image->width();
00714        bmpInfo.bmiHeader.biHeight = -image->height();
00715        bmpInfo.bmiHeader.biPlanes = 1;
00716        bmpInfo.bmiHeader.biBitCount = 32;
00717        bmpInfo.bmiHeader.biCompression = BI_RGB;
00718        bmpInfo.bmiHeader.biSizeImage = 0;
00719        if ( m_convertToGray )
00720        {
00721               int scanline = (image->width() + image->width() % 4);
00722               bmpInfo.bmiHeader.biBitCount = 8;
00723               bmpInfo.bmiHeader.biSizeImage = scanline * image->height();
00724               for( int i = 0; i < 256; i++ )
00725               {
00726                      bmpInfo.bmiColors[i].rgbRed = i;
00727                      bmpInfo.bmiColors[i].rgbGreen = i;
00728                      bmpInfo.bmiColors[i].rgbBlue = i;
00729               }
00730               QImage imTemp = image->qImage();
00731               data = new uchar[bmpInfo.bmiHeader.biSizeImage];
00732               transformImage( &imTemp, data, scanline );
00733               imageData = data;
00734               usage = DIB_RGB_COLORS;
00735        }
00736        StretchDIBits( m_dc, 0, 0 , image->width(), image->height(), 0, 0, image->width(), image->height(), 
00737               imageData, (BITMAPINFO*) &bmpInfo, usage, SRCCOPY );
00738        if( data )
00739               delete[] data;
00740        restore();
00741 #endif
00742 }
00743 
00744 void ScPainterEx_GDI::setupPolygon(FPointArray *points, bool closed)
00745 {
00746        bool nPath = true;
00747        FPoint np, np1, np2, np3;
00748        if (points->size() > 3)
00749        {
00750               newPath();
00751               for (uint poi=0; poi<points->size()-3; poi += 4)
00752               {
00753                      if (points->point(poi).x() > 900000)
00754                      {
00755                             nPath = true;
00756                             continue;
00757                      }
00758                      if (nPath)
00759                      {
00760                             np = points->point(poi);
00761 #ifdef SC_USE_GDIPLUS
00762                             m_graphicsPath->StartFigure();
00763 #endif
00764                             moveTo( np.x(), np.y() );
00765                             nPath = false;
00766                      }
00767                      np = points->point(poi);
00768                      np1 = points->point(poi+1);
00769                      np2 = points->point(poi+3);
00770                      np3 = points->point(poi+2);
00771                      if ((np == np1) && (np2 == np3))
00772                             lineTo( np3.x(), np3.y() );
00773                      else
00774                             curveTo(np1, np2, np3);
00775               }
00776               if (closed)
00777               {
00778 #ifndef SC_USE_GDIPLUS
00779                      EndPath( m_dc );
00780 #endif
00781                      m_pathIsClosed = true;
00782                      m_drawingClosedPath = true;
00783               }
00784        }
00785 }
00786 
00787 void ScPainterEx_GDI::setupTextPolygon(FPointArray *points)
00788 {
00789        bool nPath = true;
00790        FPoint np, np1, np2, np3;
00791        if (points->size() > 3)
00792        {
00793               newPath();
00794               for (uint poi=0; poi<points->size()-3; poi += 4)
00795               {
00796                      if (points->point(poi).x() > 900000)
00797                      {
00798                             nPath = true;
00799                             continue;
00800                      }
00801                      if (nPath)
00802                      {
00803                             np = points->point(poi);
00804 #ifdef SC_USE_GDIPLUS
00805                             m_graphicsPath->CloseFigure();
00806                             m_graphicsPath->StartFigure();
00807 #endif
00808                             moveTo( np.x(), np.y() );
00809                             nPath = false;
00810                      }
00811                      np.setXY( points->point(poi).x(), points->point(poi).y() );
00812                      np1.setXY( points->point(poi+1).x(), points->point(poi+1).y() );
00813                      np2.setXY( points->point(poi+3).x(), points->point(poi+3).y() );
00814                      np3.setXY( points->point(poi+2).x(), points->point(poi+2).y() );
00815                      if ((np == np1) && (np2 == np3))
00816                             lineTo( np3.x(), np3.y() );
00817                      else
00818                             curveTo( np1, np2, np3 );
00819               }
00820 #ifdef SC_USE_GDIPLUS
00821               m_graphicsPath->CloseFigure();
00822 #else
00823        EndPath( m_dc );
00824 #endif
00825               m_pathIsClosed = true;
00826        }
00827 }
00828 
00829 void ScPainterEx_GDI::drawPolygon()
00830 {
00831        fillPath();
00832 }
00833 
00834 void ScPainterEx_GDI::drawPolyLine()
00835 {
00836        strokePath();
00837 }
00838 
00839 void ScPainterEx_GDI::drawLine(FPoint start, FPoint end)
00840 {
00841        newPath();
00842        moveTo(start.x(), start.y());
00843        lineTo(end.x(), end.y());
00844        strokePath();
00845 }
00846 
00847 void ScPainterEx_GDI::drawRect(double x, double y, double w, double h)
00848 {
00849        newPath();
00850        moveTo( x, y );
00851        lineTo( x+w, y );
00852        lineTo( x+w, y+h );
00853        lineTo( x, y+h );
00854        lineTo( x, y );
00855 #ifndef SC_USE_GDIPLUS
00856        EndPath(m_dc);
00857 #endif
00858        m_pathIsClosed = true;
00859        m_drawingClosedPath = true;
00860        fillPath();
00861        strokePath();
00862 }
00863 
00864 void ScPainterEx_GDI::drawGradient( VGradientEx& gradient )
00865 {
00866        QRect clipPathRect;
00867 #ifdef SC_USE_GDIPLUS
00868        save();
00869        setClipPath();
00870        getClipPathDimensions( clipPathRect );
00871        if ( gradient.type() == VGradientEx::linear )
00872               drawLinearGradient( gradient, clipPathRect );
00873        else if ( gradient.type() == VGradientEx::radial )
00874               drawCircularGradient( gradient, clipPathRect );
00875        restore();
00876 #else
00877        SaveDC( m_dc );
00878        SelectClipPath( m_dc, RGN_COPY );
00879        getClipPathDimensions( clipPathRect );
00880        bool haveMsImg32 = ( m_hMsImg32 != NULL && m_gradientFill != NULL );
00881        if ( gradient.type() == VGradientEx::linear && haveMsImg32 )
00882               drawLinearGradient_GradientFill( gradient, clipPathRect );
00883        else if ( gradient.type() == VGradientEx::linear )
00884               drawLinearGradient( gradient, clipPathRect );
00885        else if (gradient.type() == VGradientEx::radial)
00886               drawCircularGradient( gradient, clipPathRect );
00887        RestoreDC( m_dc, -1 );
00888 #endif
00889 }
00890 
00891 void ScPainterEx_GDI::drawLinearGradient( VGradientEx& gradient, const QRect& rect )
00892 {
00893 #ifdef SC_USE_GDIPLUS
00894        Matrix matrix;
00895        int index = 0;
00896        int numElements;
00897        int r, g, b, a;
00898        double cosa, sina;
00899        double length, scale;
00900        double x1, y1, x2, y2, dx, dy;
00901        int clipBoxWidth, clipBoxHeight, maxDim;
00902        QPtrVector<VColorStopEx> colorStops = gradient.colorStops();
00903        VColorStopEx stop( *colorStops[0] );
00904        FPoint p1, p1a, p2, p2a;
00905        QColor color;
00906 
00907        if ( gradient.Stops() < 2 )
00908               return;
00909 
00910        clipBoxWidth = rect.width();
00911        clipBoxHeight = rect.height();
00912        maxDim = sqrt( (double) (clipBoxWidth * clipBoxWidth + clipBoxHeight * clipBoxHeight) ) * 2;
00913        if ( maxDim <= 0 ) 
00914               return;
00915 
00916        x1 = m_matrix.dx() + gradient.origin().x() * m_matrix.m11();
00917        y1 = m_matrix.dy() + gradient.origin().y() * m_matrix.m22();
00918        x2 = m_matrix.dx() + gradient.vector().x() * m_matrix.m11();
00919        y2 = m_matrix.dy() + gradient.vector().y() * m_matrix.m22();
00920        p1.setXY( x1, y1 );
00921        p2.setXY( x2, y2 );
00922 
00923        dx = ( p2.x() - p1.x() );
00924        dy = ( p2.y() - p1.y() );
00925        length = sqrt(( dx * dx + dy * dy ));
00926        if ( length == 0.0 )
00927               scale = 1.0;
00928        else
00929               scale = 1.0 / length;
00930        cosa = dx * scale;
00931        sina = dy * scale;
00932 
00933        p1a.setXY( p1.x() - cosa * maxDim, p1.y() - sina * maxDim );
00934        p2a.setXY( p2.x() + cosa * maxDim, p2.y() + sina * maxDim );
00935        
00936        numElements = gradient.Stops() + 2;
00937        Color *colors = new Color[numElements];
00938        REAL  *positions = new REAL[numElements];
00939        
00940        stop = *colorStops[0];
00941        color = transformColor( ScColorShade(stop.color, stop.shade), 1.0 );
00942        colors[0] = Color(stop.opacity * 255, color.red(), color.green(), color.blue());
00943        positions[0] = 0.0;
00944 
00945        stop = *colorStops[gradient.Stops() - 1];
00946        color = transformColor( ScColorShade(stop.color, stop.shade), 1.0 );
00947        colors[numElements - 1] = Color(stop.opacity * 255, color.red(), color.green(), color.blue());
00948        positions[numElements - 1] = 1.0;
00949 
00950        for( uint index = 0 ; index < gradient.Stops(); index++)
00951        {
00952               stop = *colorStops[index];
00953               color = transformColor( ScColorShade(stop.color, stop.shade), 1.0 );
00954               r = color.red();
00955               g = color.green();
00956               b = color.blue();
00957               a = stop.opacity * 255;
00958               colors[index + 1] = Color(a, r, g, b);
00959               positions[index + 1] = ( stop.rampPoint * length + maxDim ) / ( length + 2 * maxDim );
00960        }
00961        LinearGradientBrush gradientBrush( PointF( p1a.x(), p1a.y() ) ,
00962                                                                   PointF( p2a.x(), p2a.y() ),
00963                                                                   colors[0], colors[numElements - 1] );
00964        gradientBrush.SetInterpolationColors(colors, positions, numElements);
00965        m_graphics->FillPath( &gradientBrush, m_graphicsPath );
00966 
00967        delete[] colors;
00968        delete[] positions;
00969 #else
00970        XFORM xform;
00971        int xCurrent;
00972        int increment;
00973        int r1, g1, b1, a1;
00974        int r2, g2, b2, a2;
00975        int r3, g3, b3, a3;
00976        double colorCoeff;
00977        double cosa, sina;
00978        double ramp1, ramp2;
00979        double scale1, scale2;
00980        double length, scale;
00981        double x1, y1, x2, y2, dx, dy;
00982        int clipBoxWidth, clipBoxHeight, maxDim;
00983        QPtrVector<VColorStopEx> colorStops = gradient.colorStops();
00984        VColorStopEx stop1( *colorStops[0] );
00985        VColorStopEx stop2( *colorStops[0] );
00986        FPoint p1, p1a, p2, p2a;
00987        QColor color;
00988        int rgb;
00989 
00990        if ( gradient.Stops() < 2 ) 
00991               return;
00992 
00993        clipBoxWidth = rect.width();
00994        clipBoxHeight = rect.height();
00995        maxDim = sqrt( clipBoxWidth * clipBoxWidth + clipBoxHeight * clipBoxHeight ) * 2;
00996        if ( maxDim <= 0 ) return;
00997        
00998        scale1 = sqrt( m_matrix.m11() * m_matrix.m11() + m_matrix.m12() * m_matrix.m12() );
00999        scale2 = sqrt( m_matrix.m21() * m_matrix.m21() + m_matrix.m22() * m_matrix.m22() );
01000        increment = (int) max( scale1, scale2 );
01001        increment = (increment < 2) ? 2 : increment;
01002 
01003        x1 = m_matrix.dx() + gradient.origin().x() * m_matrix.m11();
01004        y1 = m_matrix.dy() + gradient.origin().y() * m_matrix.m22();
01005        x2 = m_matrix.dx() + gradient.vector().x() * m_matrix.m11();
01006        y2 = m_matrix.dy() + gradient.vector().y() * m_matrix.m22();
01007        p1.setXY( x1, y1 );
01008        p2.setXY( x2, y2 );
01009 
01010        dx = ( p2.x() - p1.x() );
01011        dy = ( p2.y() - p1.y() );
01012        length = sqrt(( dx * dx + dy * dy ));
01013        if ( length == 0.0 )
01014               scale = 1.0;
01015        else
01016               scale = 1.0 / length;
01017        cosa = dx * scale;
01018        sina = dy * scale;
01019 
01020        ramp1 = stop1.rampPoint;
01021        color =  transformColor( ScColorShade(stop1.color, stop1.shade), 1.0 );
01022        r1 = color.red();
01023        g1 = color.green();
01024        b1 = color.blue();
01025        a1 = stop1.opacity * 255;
01026        drawRectangleStrip( m_matrix.dx(), m_matrix.dy(), maxDim, maxDim, r1, g1, b1, a1);
01027 
01028        xform.eM11 = cosa;
01029        xform.eM12 = sina;
01030        xform.eM21 = -sina;
01031        xform.eM22 = cosa;
01032        xform.eDx = x1;
01033        xform.eDy = y1;
01034        ModifyWorldTransform(m_dc, &xform, MWT_LEFTMULTIPLY);
01035 
01036        for( uint index = 1; index < gradient.Stops(); index++)
01037        {
01038               stop2 = *colorStops[index];
01039               ramp2 = stop2.rampPoint;
01040               color =  transformColor( ScColorShade(stop2.color, stop2.shade), 1.0 );
01041               r2 = color.red();
01042               g2 = color.green();
01043               b2 = color.blue();
01044               a2 = stop2.opacity * 255;
01045               int xMin = length * ramp1;
01046               int xMax = length * ramp2;
01047               int r4= -1, b4= -1, g4= -1, a4= -1;
01048               for( xCurrent = xMin; xCurrent < xMax; xCurrent += increment )
01049               {
01050                      colorCoeff = ( xCurrent - xMin ) / ( (double) xMax - xMin ) ;
01051                      r3 = ( 1 - colorCoeff ) * r1 + colorCoeff * r2;
01052                      g3 = ( 1 - colorCoeff ) * g1 + colorCoeff * g2;
01053                      b3 = ( 1 - colorCoeff ) * b1 + colorCoeff * b2;
01054                      a3 = ( 1 - colorCoeff ) * a1 + colorCoeff * a2;
01055                      if( (r3 != r4) || (g3 != g4) || (b3 != b4) )
01056                      {
01057                             drawRectangleStrip( xCurrent, -maxDim/2, maxDim, maxDim, r3, g3, b3, a3 );
01058                             r4 = r3;
01059                             g4 = g3;
01060                             b4 = b3;
01061                      }
01062               }
01063               stop1 = stop2;
01064               ramp1 = ramp2;
01065               r1 = r2;
01066               g1 = g2;
01067               b1 = b2;
01068               a1 = a2;
01069        }
01070 #endif
01071 }
01072 
01073 void ScPainterEx_GDI::drawLinearGradient_GradientFill( VGradientEx& gradient, const QRect& rect )
01074 {
01075        XFORM xform;
01076        int r1, g1, b1;
01077        int r2, g2, b2;
01078        double cosa, sina;
01079        double ramp1, ramp2;
01080        double length, scale;
01081        double x1, y1, x2, y2, dx, dy;
01082        int clipBoxWidth, clipBoxHeight, maxDim;
01083        QPtrVector<VColorStopEx> colorStops = gradient.colorStops();
01084        VColorStopEx stop1( *colorStops[0] );
01085        VColorStopEx stop2( *colorStops[0] );
01086        FPoint p1, p2;
01087        QColor color;
01088 
01089        if ( gradient.Stops() < 2 ) 
01090               return;
01091 
01092        clipBoxWidth = rect.width();
01093        clipBoxHeight = rect.height();
01094        maxDim = sqrt( (double) (clipBoxWidth * clipBoxWidth + clipBoxHeight * clipBoxHeight) ) * 2;
01095        if ( maxDim <= 0 ) return;
01096 
01097        x1 = m_matrix.dx() + gradient.origin().x() * m_matrix.m11();
01098        y1 = m_matrix.dy() + gradient.origin().y() * m_matrix.m22();
01099        x2 = m_matrix.dx() + gradient.vector().x() * m_matrix.m11();
01100        y2 = m_matrix.dy() + gradient.vector().y() * m_matrix.m22();
01101        p1.setXY( x1, y1 );
01102        p2.setXY( x2, y2 );
01103 
01104        dx = ( p2.x() - p1.x() );
01105        dy = ( p2.y() - p1.y() );
01106        length = sqrt(( dx * dx + dy * dy ));
01107        if ( length == 0.0 )
01108               scale = 1.0;
01109        else
01110               scale = 1.0 / length;
01111        cosa = dx * scale;
01112        sina = dy * scale;
01113 
01114        xform.eM11 = cosa;
01115        xform.eM12 = sina;
01116        xform.eM21 = -sina;
01117        xform.eM22 = cosa;
01118        xform.eDx = x1;
01119        xform.eDy = y1;
01120        ModifyWorldTransform(m_dc, &xform, MWT_LEFTMULTIPLY);
01121 
01122        x1 = -maxDim;
01123        stop1 = *colorStops[0];
01124        ramp1 = stop1.rampPoint;
01125        color =  transformColor( ScColorShade(stop1.color, stop1.shade), 1.0 );
01126        r1 = color.red();
01127        g1 = color.green();
01128        b1 = color.blue();
01129 
01130        int numMeshes = colorStops.size() + 1;
01131        int numVertices = numMeshes * 2;
01132        TRIVERTEX* vertices = new TRIVERTEX[numVertices];
01133        GRADIENT_RECT* meshes = new GRADIENT_RECT[numMeshes];
01134 
01135        vertices[0].x = x1;
01136        vertices[0].y = -maxDim / 2;
01137        vertices[0].Red = r1 << 8;
01138        vertices[0].Green = g1 << 8;
01139        vertices[0].Blue = b1 << 8;
01140        vertices[0].Alpha = 0;
01141        meshes[0].UpperLeft = 0;
01142        
01143        uint vIndex = 1;
01144        for( uint index = 0; index < gradient.Stops(); index++, vIndex += 2)
01145        {
01146               stop2 = *colorStops[index];
01147               ramp2 =  stop2.rampPoint;
01148               color =  transformColor( ScColorShade(stop2.color, stop2.shade), 1.0 );
01149               r2 = color.red() << 8;
01150               g2 = color.green() << 8;
01151               b2 = color.blue() << 8;
01152               x2 = /*maxDim +*/ length * ramp2;
01153               vertices[vIndex].x = x2;
01154               vertices[vIndex].y = maxDim / 2;
01155               vertices[vIndex].Red = r2;
01156               vertices[vIndex].Green = g2;
01157               vertices[vIndex].Blue = b2;
01158               vertices[vIndex].Alpha = 0;
01159               vertices[vIndex + 1].x = x2;
01160               vertices[vIndex + 1].y = -maxDim / 2;
01161               vertices[vIndex + 1].Red = r2;
01162               vertices[vIndex + 1].Green = g2;
01163               vertices[vIndex + 1].Blue = b2;
01164               vertices[vIndex + 1].Alpha = 0;
01165               meshes[index].LowerRight = vIndex;
01166               meshes[index + 1].UpperLeft = vIndex + 1;
01167        }
01168 
01169        vertices[numVertices - 1].x = length + maxDim;
01170        vertices[numVertices - 1].y = maxDim / 2;
01171        vertices[numVertices - 1].Red = r2 << 8;
01172        vertices[numVertices - 1].Green = g2 << 8;
01173        vertices[numVertices - 1].Blue = b2 << 8;
01174        vertices[numVertices - 1].Alpha = 0;
01175        meshes[numMeshes - 1].LowerRight = numVertices - 1;
01176 
01177        // Finally call the gradient fill function
01178        (*m_gradientFill)( m_dc, vertices, numVertices, meshes, numMeshes, GRADIENT_FILL_RECT_H );
01179 
01180        // Delete used arrays
01181        delete[] vertices;
01182        delete[] meshes;
01183 }
01184 
01185 void ScPainterEx_GDI::drawRectangleStrip( int x, int y, int w, int h, int r, int g, int b, int a )
01186 {
01187 #ifndef SC_USE_GDIPLUS
01188        SaveDC( m_dc );
01189        HPEN hPen = CreatePen( PS_NULL, 0, RGB(255,255,255));
01190        HBRUSH hBrush = CreateSolidBrush( RGB(r, g, b));
01191        HGDIOBJ obj1 = SelectObject( m_dc, hPen );
01192        HGDIOBJ obj2 = SelectObject( m_dc, hBrush );
01193        Rectangle( m_dc, x, y, x + w, y + h );
01194        SelectObject( m_dc, obj2 );
01195        SelectObject( m_dc, obj1 );
01196        DeleteObject( hBrush );
01197        DeleteObject( hPen );
01198        RestoreDC( m_dc, -1 );
01199 #endif
01200 }
01201 
01202 void ScPainterEx_GDI::drawCircularGradient( VGradientEx& gradient, const QRect& rect )
01203 {
01204 #ifdef SC_USE_GDIPLUS
01205        int offset = 0;
01206        int numElements;
01207        int r, g, b, a;
01208        int clipBoxWidth, clipBoxHeight, maxDim;
01209        QPtrVector<VColorStopEx> colorStops = gradient.colorStops();
01210        VColorStopEx stop( *colorStops[0] );
01211        QColor color;
01212 
01213        clipBoxWidth = rect.width();
01214        clipBoxHeight = rect.height();
01215        maxDim = sqrt( (double) (clipBoxWidth * clipBoxWidth + clipBoxHeight * clipBoxHeight) ) * 2;
01216        if ( maxDim <= 0 ) return;
01217 
01218        FPoint pc( gradient.origin().x(), gradient.origin().y() );
01219        FPoint pcz( gradient.origin().x(), gradient.origin().y() );
01220        FPoint pf( gradient.focalPoint().x(), gradient.focalPoint().y() );
01221        FPoint pfz( gradient.focalPoint().x(), gradient.focalPoint().y() );
01222        FPoint pv( gradient.vector().x(), gradient.vector().y() );
01223        transformPoint( pc, pc );
01224        transformPoint( pf, pf );
01225        transformPoint( pv, pv );
01226        transformPoint( pcz, pcz );
01227        transformPoint( pfz, pfz );
01228        double cx = pcz.x();
01229        double cy = pcz.y();
01230        double fx = pfz.x();
01231        double fy = pfz.y();
01232        double rad = sqrt( pow(pv.x() - pc.x(), 2) + pow(pv.y() - pc.y(), 2) );
01233 
01234        numElements = gradient.Stops() + 2;
01235        Color *colors = new Color[numElements];
01236        REAL  *positions = new REAL[numElements];
01237 
01238        stop = *colorStops[ 0 ];
01239        color = transformColor( ScColorShade(stop.color, stop.shade), stop.opacity);
01240        colors[numElements - 1] = Color(stop.opacity * 255, color.red(), color.green(), color.blue());
01241        positions[numElements - 1] = 1.0;         
01242        
01243        stop = *colorStops[ gradient.Stops() - 1 ];
01244        color = transformColor( ScColorShade(stop.color, stop.shade), stop.opacity);
01245        colors[0] = Color(stop.opacity * 255, color.red(), color.green(), color.blue());
01246        positions[0] = 0.0;
01247 
01248        for( uint index = 0 ; index < gradient.Stops() ; index++)
01249        {
01250               stop = *colorStops[index];
01251               color = transformColor( ScColorShade(stop.color, stop.shade), 1.0 );
01252               r = color.red();
01253               g = color.green();
01254               b = color.blue();
01255               a = stop.opacity * 255;
01256               colors[gradient.Stops() - index] = Color(a, r, g, b);
01257               positions[gradient.Stops() - index] = 1 - 2 * (stop.rampPoint * rad) / (double) maxDim;
01258        }
01259        
01260        GraphicsPath gradientPath;
01261        gradientPath.AddEllipse( cx - maxDim/2, cy - maxDim/2, maxDim, maxDim );
01262        PathGradientBrush gradientBrush( &gradientPath );
01263        gradientBrush.SetCenterPoint( PointF(cx, cy) );
01264        gradientBrush.SetCenterColor( colors[numElements - 1] );
01265        gradientBrush.SetInterpolationColors( colors, positions, numElements );
01266        m_graphics->FillPath( &gradientBrush, m_graphicsPath );
01267 
01268        delete[] colors;
01269        delete[] positions;
01270 #else
01271        int radius;
01272        int increment;
01273        int r1, g1, b1, a1;
01274        int r2, g2, b2, a2;
01275        int r3, g3, b3, a3;
01276        double colorCoeff;
01277        double ramp1, ramp2;
01278        double scale1, scale2;
01279        int clipBoxWidth, clipBoxHeight, maxDim;
01280        QPtrVector<VColorStopEx> colorStops = gradient.colorStops();
01281        VColorStopEx stop1( *colorStops[gradient.Stops() - 1] );
01282        VColorStopEx stop2( *colorStops[gradient.Stops() - 1] );
01283        QColor color;
01284 
01285        clipBoxWidth = rect.width();
01286        clipBoxHeight = rect.height();
01287        maxDim = sqrt( clipBoxWidth * clipBoxWidth + clipBoxHeight * clipBoxHeight ) * 2;
01288        if ( maxDim <= 0 ) return;
01289 
01290        scale1 = sqrt( m_matrix.m11() * m_matrix.m11() + m_matrix.m21() * m_matrix.m21() );
01291        scale2 = sqrt( m_matrix.m12() * m_matrix.m12() + m_matrix.m22() * m_matrix.m22() );
01292        increment = (int) max( scale1, scale2 );
01293        increment = (increment < 2) ? 2 : increment;
01294 
01295        FPoint pc( gradient.origin().x(), gradient.origin().y() );
01296        FPoint pcz( gradient.origin().x(), gradient.origin().y() );
01297        FPoint pf( gradient.focalPoint().x(), gradient.focalPoint().y() );
01298        FPoint pfz( gradient.focalPoint().x(), gradient.focalPoint().y() );
01299        FPoint pv( gradient.vector().x(), gradient.vector().y() );
01300        transformPoint( pc, pc );
01301        transformPoint( pf, pf );
01302        transformPoint( pv, pv );
01303        transformPoint( pcz, pcz );
01304        transformPoint( pfz, pfz );
01305        double cx = pcz.x();
01306        double cy = pcz.y();
01307        double fx = pfz.x();
01308        double fy = pfz.y();
01309        double rad = sqrt( pow(pv.x() -pc.x(), 2) + pow(pv.y() - pc.y(), 2) );
01310 
01311        ramp2 = stop2.rampPoint;
01312        color =  transformColor( ScColorShade(stop2.color, stop2.shade), 1.0 );
01313        r2 = color.red();
01314        g2 = color.green();
01315        b2 = color.blue();
01316        a2 = stop2.opacity * 255;
01317        drawCircleStrip( cx - maxDim / 2, cy - maxDim / 2, maxDim, maxDim, color.red(), color.green(), color.blue(), a2);
01318        if ( gradient.Stops() < 2 ) return;
01319 
01320        for( int index = gradient.Stops() - 2; index >= 0; index--)
01321        {
01322               stop1 = *colorStops[index];
01323               ramp1 = stop1.rampPoint;
01324               color =  transformColor( ScColorShade(stop1.color, stop1.shade), 1.0 );
01325               r1 = color.red();
01326               g1 = color.green();
01327               b1 = color.blue();
01328               a1 = stop1.opacity * 255;
01329               int radMax = rad * ramp2;
01330               int radMin = rad * ramp1;
01331               int r4= -1, b4= -1, g4= -1, a4= -1;
01332               for( radius = radMax; radius > radMin; radius -= increment )
01333               {
01334                      colorCoeff = ( radius - radMin ) / ( (double) radMax - radMin );
01335                      r3 = (1 - colorCoeff) * r1 + colorCoeff * r2;
01336                      g3 = (1 - colorCoeff) * g1 + colorCoeff * g2;
01337                      b3 = (1 - colorCoeff) * b1 + colorCoeff * b2;
01338                      a3 = (1 - colorCoeff) * a1 + colorCoeff * a2;
01339                      if( (r3 != r4) || (g3 != g4) || (b3 != b4) )
01340                      {
01341                             drawCircleStrip( cx - radius, cy - radius, radius * 2, radius * 2, r3, g3, b3, a3 );
01342                             r4 = r3;
01343                             g4 = g3;
01344                             b4 = b3;
01345                      }
01346               }
01347               stop2 = stop1;
01348               ramp2 = ramp1;
01349               r2 = r1;
01350               g2 = g1;
01351               b2 = b1;
01352               a2 = a1;
01353        }
01354 #endif
01355 }
01356 
01357 void ScPainterEx_GDI::drawCircleStrip( int x, int y, int w, int h, int r, int g, int b, int a )
01358 {
01359 #ifndef SC_USE_GDIPLUS
01360        SaveDC( m_dc );
01361        HPEN hPen = CreatePen( PS_NULL, 0, RGB(255,255,255));
01362        HBRUSH hBrush = CreateSolidBrush( RGB(r, g, b));
01363        HGDIOBJ obj1 = SelectObject( m_dc, hPen );
01364        HGDIOBJ obj2 = SelectObject( m_dc, hBrush );
01365        Ellipse( m_dc, x, y, x + w, y + h );
01366        SelectObject( m_dc, obj2 );
01367        SelectObject( m_dc, obj1 );
01368        DeleteObject( hBrush );
01369        DeleteObject( hPen );
01370        RestoreDC( m_dc, -1 );
01371 #endif
01372 }
01373 
01374 void ScPainterEx_GDI::getClipPathDimensions( QRect& r )
01375 {
01376 #ifdef SC_USE_GDIPLUS
01377        Rect rect(0, 0, 0, 0);
01378        Status result = m_graphics->GetClipBounds( &rect );
01379        if( result == Ok )
01380        {
01381               r.setLeft( rect.GetLeft() );
01382               r.setRight( rect.GetRight() );
01383               r.setBottom( rect.GetBottom() );
01384               r.setTop( rect.GetTop() );
01385        }
01386 #else
01387        RECT rect = { 0, 0, 0, 0 };
01388        int result = GetClipBox( m_dc, &rect );
01389        if( result != NULLREGION && result != ERROR )
01390        {
01391               r.setLeft( rect.left );
01392               r.setRight( rect.right );
01393               r.setBottom( rect.bottom );
01394               r.setTop( rect.top );       
01395        }
01396 #endif
01397 }
01398