Scribus Developer Documentation - API
logo-pen

Scribus Developer Documentation - API

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 #include "scribusdoc.h"
00038 #include "scpainterex_gdi.h"
00039 #include "sccolorengine.h"
00040 #include "util.h"
00041 
00042 #include <QImage>
00043 #include <QList>
00044 #include <QPaintDevice>
00045 #include <QPixmap>
00046 
00047 #include <iostream>
00048 using namespace std;
00049  
00050 #include <math.h>
00051 
00052 typedef struct { 
00053     BITMAPINFOHEADER bmiHeader; 
00054     RGBQUAD bmiColors[256]; 
00055 } BITMAPINFO256;
00056 
00057 ScPainterEx_GDI::ScPainterEx_GDI( HDC hDC, QRect& rect,  ScribusDoc* doc, bool gray ) : ScPainterExBase()
00058 {
00059     m_doc = doc;
00060     m_width = rect.width();
00061     m_height= rect.height();
00062     m_strokeColor = ScColorShade( QColor(0,0,0), 100 );
00063     m_fillColor = ScColorShade( QColor(0,0,0), 100 );
00064     m_fillTrans = 1.0;
00065     m_strokeTrans = 1.0;
00066     m_fillRule = true;
00067     m_fillMode = 1;
00068     m_lineWidth = 1.0;
00069     m_offset = 0;
00070     m_array.clear();
00071     m_lineEnd = Qt::SquareCap;
00072     m_lineJoin = Qt::RoundJoin;
00073     m_fillGradient = VGradientEx(VGradientEx::linear);
00074     m_strokeGradient = VGradientEx(VGradientEx::linear);
00075     m_matrix = QMatrix();
00076     // Grayscale conversion parameter
00077     m_convertToGray = gray;
00078     // Initialization of Windows GDI data
00079     m_dc = hDC;
00080     m_hBmp = NULL;
00081     m_hMsImg32 = NULL;
00082     m_gradientFill = NULL;
00083     m_pathIsClosed = true;
00084     m_drawingClosedPath = false;
00085     m_deviceDimX = GetDeviceCaps(m_dc, PHYSICALWIDTH);
00086     m_deviceDimY = GetDeviceCaps(m_dc, PHYSICALHEIGHT);
00087     m_deviceResX = GetDeviceCaps(m_dc, LOGPIXELSX);
00088     m_deviceResY = GetDeviceCaps(m_dc, LOGPIXELSY);
00089     SetGraphicsMode( m_dc, GM_ADVANCED );
00090     SetPolyFillMode( m_dc, ALTERNATE);
00091     loadMsImg32();
00092     clear();
00093 }
00094 
00095 ScPainterEx_GDI::~ScPainterEx_GDI()
00096 {
00097     if ( m_hMsImg32 )
00098         FreeLibrary( m_hMsImg32 );
00099 }
00100 
00101 void ScPainterEx_GDI::loadMsImg32( void )
00102 {
00103     m_hMsImg32 = LoadLibraryW( L"msimg32.dll" );
00104     if( m_hMsImg32 )
00105         m_gradientFill = (gradientFillFunc) GetProcAddress( m_hMsImg32, "GradientFill" );
00106 }
00107 
00108 QColor ScPainterEx_GDI::transformColor( ScColorShade& colorShade, double trans )
00109 {
00110     QColor c, color;
00111     c = ScColorEngine::getShadeColor(colorShade.color, m_doc, colorShade.shade);
00112     color = qRgba( qRed(c.rgb()), qGreen(c.rgb()), qBlue(c.rgb()), qAlpha(trans * 255));
00113     if ( m_convertToGray )
00114     {
00115         int grayLevel;
00116         QColor grayColor;
00117         grayLevel = 0.3 * color.red() + 0.59 * color.green() + 0.11 * color.blue();
00118         grayColor = qRgba( grayLevel, grayLevel, grayLevel, qAlpha(color.rgb()));
00119         color = grayColor;
00120     }
00121     return color;
00122 }
00123 
00124 void ScPainterEx_GDI::transformImage( QImage* image, uchar* data, int scan)
00125 {
00126     int rgb, grey;
00127     int imageWidth = image->width();
00128     int imageHeight = image->height();
00129     QRgb* imageBits = (QRgb *) image->bits();
00130     QRgb*  pscani;
00131     uchar *pscand;
00132 
00133     pscand = data;
00134     for ( int j = 0; j < imageHeight; j++ )
00135     {
00136         pscani = (QRgb *) image->scanLine(j);
00137         for (int i = 0; i < imageWidth; i++ )
00138         {
00139             rgb = pscani[i];
00140             grey = 0.3 * qRed(rgb) + 0.59 * qGreen(rgb) + 0.11 * qBlue(rgb);
00141             pscand[i] = grey;
00142         }
00143         pscand += scan;
00144     }
00145 
00146 }
00147 
00148 void ScPainterEx_GDI::begin()
00149 {
00150 }
00151 
00152 void ScPainterEx_GDI::end()
00153 {
00154     ModifyWorldTransform(m_dc, NULL, MWT_IDENTITY);
00155 }
00156 
00157 void ScPainterEx_GDI::clear()
00158 {
00159     RECT rect;
00160     HBRUSH brush = CreateSolidBrush( RGB(255, 255, 255) );
00161     rect.bottom = 0;
00162     rect.left = 0;
00163     rect.right = m_width;
00164     rect.top = m_height;
00165     FillRect(m_dc, &rect, brush);
00166     DeleteObject( brush );
00167 }
00168 
00169 void ScPainterEx_GDI::clear( ScColorShade &c )
00170 {
00171     QColor color = transformColor( c, 1.0 );
00172     RECT rect;
00173     HBRUSH brush = CreateSolidBrush( RGB( qRed(color.rgb()), qGreen(color.rgb()), qBlue(color.rgb()) ) );
00174     rect.bottom = 0;
00175     rect.left = 0;
00176     rect.right = m_width;
00177     rect.top = m_height;
00178     FillRect(m_dc, &rect, brush);
00179     DeleteObject( brush );
00180 }
00181 
00182 const QMatrix ScPainterEx_GDI::worldMatrix()
00183 {
00184     return m_matrix;
00185 }
00186 
00187 void ScPainterEx_GDI::setWorldMatrix( const QMatrix &mat )
00188 {
00189     m_matrix = mat;
00190 }
00191 
00192 void ScPainterEx_GDI::transformPoint( const FPoint& in, FPoint& out )
00193 {
00194     double x, y;
00195     x = in.x() * m_matrix.m11() + in.y() * m_matrix.m21() + m_matrix.dx();
00196     y = in.x() * m_matrix.m12() + in.y() * m_matrix.m22() + m_matrix.dy();
00197     out.setX( x );
00198     out.setY( y );
00199 }
00200 
00201 void ScPainterEx_GDI::transformPoints( const FPoint* ArrayIn, FPoint* ArrayOut, uint length )
00202 {
00203     for( uint i = 0; i < length; i++ )
00204     {
00205         transformPoint( ArrayIn[i], ArrayOut[i] );
00206     }
00207 }
00208 
00209 void ScPainterEx_GDI::translate( double x, double y )
00210 {
00211     m_matrix.translate(x, y);
00212 }
00213 
00214 void ScPainterEx_GDI::rotate( double r )
00215 {
00216     m_matrix.rotate(r);
00217 }
00218 
00219 void ScPainterEx_GDI::scale( double x, double y )
00220 {
00221     m_matrix.scale(x, y);
00222 }
00223 
00224 void ScPainterEx_GDI::moveTo( const double &x, const double &y )
00225 {
00226     FPoint pp( x, y );
00227     transformPoint( pp, pp );
00228     MoveToEx(m_dc, (int) pp.x(), (int) pp.y(), NULL);
00229 }
00230 
00231 void ScPainterEx_GDI::lineTo( const double &x, const double &y )
00232 {
00233     FPoint pp( x, y );
00234     transformPoint( pp, pp );
00235     LineTo(m_dc, (int) pp.x(), (int) pp.y());
00236 }
00237 
00238 void ScPainterEx_GDI::curveTo( FPoint p1, FPoint p2, FPoint p3 )
00239 {
00240     FPoint fpoints[3];
00241     fpoints[0].setXY( p1.x(), p1.y() );
00242     fpoints[1].setXY( p2.x(), p2.y() );
00243     fpoints[2].setXY( p3.x(), p3.y() );
00244     transformPoints( fpoints, fpoints, 3 );
00245     POINT points[3];
00246     points[0].x = fpoints[0].x();
00247     points[0].y = fpoints[0].y();
00248     points[1].x = fpoints[1].x();
00249     points[1].y = fpoints[1].y();
00250     points[2].x = fpoints[2].x();
00251     points[2].y = fpoints[2].y();
00252     PolyBezierTo(m_dc, points, 3);
00253 }
00254 
00255 void ScPainterEx_GDI::newPath()
00256 {
00257     bool done = BeginPath( m_dc );
00258     if(!done)
00259         cout << "BeginPath fuction has failed." << endl;
00260     m_pathIsClosed = false;
00261     m_drawingClosedPath = false;
00262 }
00263 
00264 void ScPainterEx_GDI::setFillRule( bool fillRule )
00265 {
00266     m_fillRule = fillRule;
00267 }
00268 
00269 void ScPainterEx_GDI::setFillMode( int fill )
00270 {
00271     m_fillMode = fill;
00272 }
00273 
00274 void ScPainterEx_GDI::setGradient(VGradientEx::Type mode, FPoint orig, FPoint vec, FPoint foc)
00275 {
00276     m_fillGradient.setType(mode);
00277     m_fillGradient.setOrigin(orig);
00278     m_fillGradient.setVector(vec);
00279     m_fillGradient.setFocalPoint(foc);
00280 }
00281 
00282 void ScPainterEx_GDI::setPattern( ScPattern* pattern, QMatrix& patternTransform )
00283 {
00284     m_pattern = pattern;
00285     m_patternTransform = patternTransform;
00286 }
00287 
00288 void ScPainterEx_GDI::fillTextPath()
00289 {
00290     drawVPath( 0 );
00291 }
00292 
00293 void ScPainterEx_GDI::strokeTextPath()
00294 {
00295     if( m_lineWidth == 0 )
00296         return;
00297     drawVPath( 1 );
00298 }
00299 
00300 void ScPainterEx_GDI::fillPath()
00301 {
00302     if( !m_pathIsClosed )
00303     {
00304         EndPath( m_dc );
00305         m_pathIsClosed = true;
00306     }
00307     if( m_fillMode != 0)
00308         drawVPath( 0 );
00309 }
00310 
00311 void ScPainterEx_GDI::strokePath()
00312 {
00313     if( m_lineWidth == 0 )
00314         return;
00315     if( !m_pathIsClosed )
00316         EndPath( m_dc );
00317     m_pathIsClosed = true;
00318     drawVPath( 1 );
00319 }
00320 
00321 ScColorShade ScPainterEx_GDI::pen()
00322 {
00323     return m_strokeColor;
00324 }
00325 
00326 ScColorShade ScPainterEx_GDI::brush()
00327 {
00328     return m_fillColor;
00329 }
00330 
00331 void ScPainterEx_GDI::setPen( const ScColorShade &c )
00332 {
00333     m_strokeColor = c;
00334 }
00335 
00336 void ScPainterEx_GDI::setPen( const ScColorShade &c, double w, Qt::PenStyle st, Qt::PenCapStyle ca, Qt::PenJoinStyle jo )
00337 {
00338     m_strokeColor = c;
00339     m_lineWidth = w;
00340     m_lineEnd = ca;
00341     m_lineJoin = jo;
00342 //  double Dt = qMax(1*w, 1.0);
00343 //  double Sp = qMax(2*w, 1.0);
00344 //  double Da = qMax(4*w, 1.0);
00345 //  QList<double> tmp;
00346     m_array.clear();
00347     m_offset = 0;
00348     getDashArray(st, w, m_array);
00349 /*  switch (st)
00350     {
00351         case Qt::SolidLine:
00352             break;
00353         case Qt::DashLine:
00354             m_array.append(Da);
00355             m_array.append(Sp);
00356             break;
00357         case Qt::DotLine:
00358             m_array.append(Dt);
00359             m_array.append(Sp);
00360 #ifdef SC_USE_GDIPLUS
00361             m_array.append(Dt);
00362 #endif
00363             break;
00364         case Qt::DashDotLine:
00365             m_array.append(Da);
00366             m_array.append(Sp);
00367             m_array.append(Dt);
00368             m_array.append(Sp);
00369             break;
00370         case Qt::DashDotDotLine:
00371             m_array.append(Da);
00372             m_array.append(Sp);
00373             m_array.append(Dt);
00374             m_array.append(Sp);
00375             m_array.append(Dt);
00376             m_array.append(Sp);
00377             break;
00378         default:
00379             break;
00380     } */
00381 }
00382 
00383 void ScPainterEx_GDI::setLineWidth( double w )
00384 {
00385     m_lineWidth = w;
00386 }
00387 
00388 void ScPainterEx_GDI::setPenOpacity( double op )
00389 {
00390     m_strokeTrans = op;
00391 }
00392 
00393 
00394 void ScPainterEx_GDI::setDash(const QList<double>& array, double ofs)
00395 {
00396     m_array = array;
00397     m_offset = ofs;
00398 }
00399 
00400 void ScPainterEx_GDI::setBrush( const ScColorShade &c )
00401 {
00402     m_fillColor = c;
00403 }
00404 
00405 void ScPainterEx_GDI::setBrushOpacity( double op )
00406 {
00407     m_fillTrans = op;
00408 }
00409 
00410 void ScPainterEx_GDI::setOpacity( double op )
00411 {
00412     m_fillTrans = op;
00413     m_strokeTrans = op;
00414 }
00415 
00416 void ScPainterEx_GDI::setFont( const QFont &f)
00417 {
00418     m_font = f;
00419 }
00420 
00421 QFont ScPainterEx_GDI::font()
00422 {
00423     return m_font;
00424 }
00425 
00426 void ScPainterEx_GDI::save()
00427 {
00428     m_stack.push( m_matrix );
00429     SaveDC( m_dc );
00430 }
00431 
00432 void ScPainterEx_GDI::restore()
00433 {
00434     m_matrix = m_stack.pop();
00435     RestoreDC( m_dc, -1 );
00436 }
00437 
00438 void ScPainterEx_GDI::setRasterOp( int   )
00439 {
00440 }
00441 
00442 void ScPainterEx_GDI::drawVPath( int mode )
00443 {
00444     int dcState;
00445     dcState = SaveDC( m_dc );
00446     if (mode == 0)
00447     {
00448         if( m_fillRule )
00449             SetPolyFillMode(m_dc, ALTERNATE);
00450         else
00451             SetPolyFillMode(m_dc, WINDING);
00452         if (m_fillMode == ScPainterExBase::Gradient)
00453         {
00454             drawGradient( m_fillGradient );
00455         }
00456         else
00457         {
00458             QColor fillColor = transformColor( m_fillColor, 1.0 );
00459             HBRUSH brush = CreateSolidBrush( RGB( qRed(fillColor.rgb()), qGreen(fillColor.rgb()), qBlue(fillColor.rgb()) ) );
00460             HGDIOBJ obj = SelectObject(m_dc, brush);
00461             FillPath(m_dc);
00462             SelectObject(m_dc, obj);
00463             DeleteObject(brush);
00464         }
00465     }
00466     else
00467     {
00468         DWORD penStyle = PS_GEOMETRIC;
00469         DWORD penWidth = 0;
00470         LOGBRUSH logBrush;
00471         DWORD *dashes = NULL;
00472 
00473         QColor strokeColor = transformColor( m_strokeColor, 1.0 );
00474         logBrush.lbStyle = BS_SOLID;
00475         logBrush.lbColor = RGB( qRed(strokeColor.rgb()), qGreen(strokeColor.rgb()), qBlue(strokeColor.rgb()) );
00476         logBrush.lbHatch = 0;
00477 
00478         double m11 = m_matrix.m11();
00479         double m12 = m_matrix.m12();
00480         double m21 = m_matrix.m21();
00481         double m22 = m_matrix.m22();
00482         double norm2 = m11 * m11 + m12 * m12 + m21 * m21 + m22 * m22;
00483         double penScale = sqrt(norm2 /2.0);
00484         penWidth = (int) (m_lineWidth * penScale);
00485         
00486         if( m_array.count() > 0 )
00487         {
00488             dashes = new DWORD[ m_array.count() ];
00489             for(int i = 0; i < m_array.count();++ i )
00490             {
00491                 dashes[i] = (DWORD) (m_array[i] * penScale);
00492             }
00493             penStyle = penStyle | PS_USERSTYLE; 
00494         }
00495         if( m_lineEnd == Qt::RoundCap )
00496             penStyle = penStyle | PS_ENDCAP_ROUND;
00497         else if( m_lineEnd == Qt::SquareCap )
00498             penStyle = penStyle | PS_ENDCAP_SQUARE;
00499         else if( m_lineEnd == Qt::FlatCap && m_array.count() == 0 && m_drawingClosedPath )
00500             penStyle = penStyle | PS_ENDCAP_SQUARE;
00501         else if( m_lineEnd == Qt::FlatCap )
00502             penStyle = penStyle | PS_ENDCAP_FLAT;
00503         if( m_lineJoin == Qt::RoundJoin )
00504             penStyle = penStyle | PS_JOIN_ROUND;
00505         else if( m_lineJoin == Qt::BevelJoin )
00506             penStyle = penStyle | PS_JOIN_BEVEL;
00507         else if( m_lineJoin == Qt::MiterJoin )
00508             penStyle = penStyle | PS_JOIN_MITER;
00509 
00510         HPEN pen = ExtCreatePen(penStyle, penWidth, &logBrush, m_array.count(), dashes);
00511         HGDIOBJ obj = SelectObject( m_dc, pen);
00512         StrokePath( m_dc );
00513         SelectObject( m_dc, obj);
00514         DeleteObject( pen);
00515         if( dashes )
00516             delete [] dashes;
00517     }
00518     RestoreDC( m_dc, dcState );
00519 }
00520 
00521 void ScPainterEx_GDI::setClipPath()
00522 {
00523     SelectClipPath( m_dc, RGN_AND );
00524 }
00525 
00526 void ScPainterEx_GDI::drawImage( ScImage *image, ScPainterExBase::ImageMode mode )
00527 {
00528     save();
00529     int usage = 0;
00530     unsigned char* data = NULL;
00531     unsigned char* imageData = (unsigned char*) image->qImage().bits();
00532     XFORM xform = { m_matrix.m11(), m_matrix.m12(), m_matrix.m21(), m_matrix.m22(), m_matrix.dx(), m_matrix.dy() } ;
00533     ModifyWorldTransform(m_dc, &xform, MWT_LEFTMULTIPLY);
00534     BITMAPINFO256 bmpInfo;
00535     ZeroMemory( &bmpInfo, sizeof(bmpInfo));
00536     bmpInfo.bmiHeader.biSize = sizeof( bmpInfo.bmiHeader );
00537     bmpInfo.bmiHeader.biWidth = image->width();
00538     bmpInfo.bmiHeader.biHeight = -image->height();
00539     bmpInfo.bmiHeader.biPlanes = 1;
00540     bmpInfo.bmiHeader.biBitCount = 32;
00541     bmpInfo.bmiHeader.biCompression = BI_RGB;
00542     bmpInfo.bmiHeader.biSizeImage = 0;
00543     if ( m_convertToGray )
00544     {
00545         int scanline = (image->width() + image->width() % 4);
00546         bmpInfo.bmiHeader.biBitCount = 8;
00547         bmpInfo.bmiHeader.biSizeImage = scanline * image->height();
00548         for( int i = 0; i < 256; i++ )
00549         {
00550             bmpInfo.bmiColors[i].rgbRed = i;
00551             bmpInfo.bmiColors[i].rgbGreen = i;
00552             bmpInfo.bmiColors[i].rgbBlue = i;
00553         }
00554         QImage imTemp = image->qImage();
00555         data = new uchar[bmpInfo.bmiHeader.biSizeImage];
00556         transformImage( &imTemp, data, scanline );
00557         imageData = data;
00558         usage = DIB_RGB_COLORS;
00559     }
00560     StretchDIBits( m_dc, 0, 0 , image->width(), image->height(), 0, 0, image->width(), image->height(), 
00561         imageData, (BITMAPINFO*) &bmpInfo, usage, SRCCOPY );
00562     if( data )
00563         delete[] data;
00564     restore();
00565 }
00566 
00567 void ScPainterEx_GDI::setupPolygon(FPointArray *points, bool closed)
00568 {
00569     bool nPath = true;
00570     FPoint np, np1, np2, np3;
00571     if (points->size() > 3)
00572     {
00573         newPath();
00574         for (uint poi=0; poi<points->size()-3; poi += 4)
00575         {
00576             if (points->point(poi).x() > 900000)
00577             {
00578                 nPath = true;
00579                 continue;
00580             }
00581             if (nPath)
00582             {
00583                 np = points->point(poi);
00584                 moveTo( np.x(), np.y() );
00585                 nPath = false;
00586             }
00587             np = points->point(poi);
00588             np1 = points->point(poi+1);
00589             np2 = points->point(poi+3);
00590             np3 = points->point(poi+2);
00591             if ((np == np1) && (np2 == np3))
00592                 lineTo( np3.x(), np3.y() );
00593             else
00594                 curveTo(np1, np2, np3);
00595         }
00596         if (closed)
00597         {
00598             EndPath( m_dc );
00599             m_pathIsClosed = true;
00600             m_drawingClosedPath = true;
00601         }
00602     }
00603 }
00604 
00605 void ScPainterEx_GDI::setupTextPolygon(FPointArray *points)
00606 {
00607     bool nPath = true;
00608     FPoint np, np1, np2, np3;
00609     if (points->size() > 3)
00610     {
00611         newPath();
00612         for (uint poi=0; poi<points->size()-3; poi += 4)
00613         {
00614             if (points->point(poi).x() > 900000)
00615             {
00616                 nPath = true;
00617                 continue;
00618             }
00619             if (nPath)
00620             {
00621                 np = points->point(poi);
00622                 moveTo( np.x(), np.y() );
00623                 nPath = false;
00624             }
00625             np.setXY( points->point(poi).x(), points->point(poi).y() );
00626             np1.setXY( points->point(poi+1).x(), points->point(poi+1).y() );
00627             np2.setXY( points->point(poi+3).x(), points->point(poi+3).y() );
00628             np3.setXY( points->point(poi+2).x(), points->point(poi+2).y() );
00629             if ((np == np1) && (np2 == np3))
00630                 lineTo( np3.x(), np3.y() );
00631             else
00632                 curveTo( np1, np2, np3 );
00633         }
00634         EndPath( m_dc );
00635         m_pathIsClosed = true;
00636     }
00637 }
00638 
00639 void ScPainterEx_GDI::drawPolygon()
00640 {
00641     fillPath();
00642 }
00643 
00644 void ScPainterEx_GDI::drawPolyLine()
00645 {
00646     strokePath();
00647 }
00648 
00649 void ScPainterEx_GDI::drawLine(FPoint start, FPoint end)
00650 {
00651     newPath();
00652     moveTo(start.x(), start.y());
00653     lineTo(end.x(), end.y());
00654     strokePath();
00655 }
00656 
00657 void ScPainterEx_GDI::drawRect(double x, double y, double w, double h)
00658 {
00659     newPath();
00660     moveTo( x, y );
00661     lineTo( x+w, y );
00662     lineTo( x+w, y+h );
00663     lineTo( x, y+h );
00664     lineTo( x, y );
00665     EndPath(m_dc);
00666     m_pathIsClosed = true;
00667     m_drawingClosedPath = true;
00668     fillPath();
00669     strokePath();
00670 }
00671 
00672 void ScPainterEx_GDI::drawGradient( VGradientEx& gradient )
00673 {
00674     QRect clipPathRect;
00675     SaveDC( m_dc );
00676     SelectClipPath( m_dc, RGN_COPY );
00677     getClipPathDimensions( clipPathRect );
00678     bool haveMsImg32 = ( m_hMsImg32 != NULL && m_gradientFill != NULL );
00679     if ( gradient.type() == VGradientEx::linear && haveMsImg32 )
00680         drawLinearGradient_GradientFill( gradient, clipPathRect );
00681     else if ( gradient.type() == VGradientEx::linear )
00682         drawLinearGradient( gradient, clipPathRect );
00683     else if (gradient.type() == VGradientEx::radial)
00684         drawCircularGradient( gradient, clipPathRect );
00685     RestoreDC( m_dc, -1 );
00686 }
00687 
00688 void ScPainterEx_GDI::drawLinearGradient( VGradientEx& gradient, const QRect& rect )
00689 {
00690     XFORM xform;
00691     int xCurrent;
00692     int increment;
00693     int r1, g1, b1, a1;
00694     int r2, g2, b2, a2;
00695     int r3, g3, b3, a3;
00696     double colorCoeff;
00697     double cosa, sina;
00698     double ramp1, ramp2;
00699     double scale1, scale2;
00700     double length, scale;
00701     double x1, y1, x2, y2, dx, dy;
00702     int clipBoxWidth, clipBoxHeight, maxDim;
00703     QList<VColorStopEx*> colorStops = gradient.colorStops();
00704     VColorStopEx stop1( *colorStops[0] );
00705     VColorStopEx stop2( *colorStops[0] );
00706     FPoint p1, p1a, p2, p2a;
00707     QColor color;
00708 
00709     if ( gradient.Stops() < 2 ) 
00710         return;
00711 
00712     clipBoxWidth = rect.width();
00713     clipBoxHeight = rect.height();
00714     maxDim = sqrt((double) (clipBoxWidth * clipBoxWidth + clipBoxHeight * clipBoxHeight)) * 2;
00715     if ( maxDim <= 0 ) return;
00716     
00717     scale1 = sqrt( m_matrix.m11() * m_matrix.m11() + m_matrix.m12() * m_matrix.m12() );
00718     scale2 = sqrt( m_matrix.m21() * m_matrix.m21() + m_matrix.m22() * m_matrix.m22() );
00719     increment = (int) max( scale1, scale2 );
00720     increment = (increment < 2) ? 2 : increment;
00721 
00722     x1 = m_matrix.dx() + gradient.origin().x() * m_matrix.m11();
00723     y1 = m_matrix.dy() + gradient.origin().y() * m_matrix.m22();
00724     x2 = m_matrix.dx() + gradient.vector().x() * m_matrix.m11();
00725     y2 = m_matrix.dy() + gradient.vector().y() * m_matrix.m22();
00726     p1.setXY( x1, y1 );
00727     p2.setXY( x2, y2 );
00728 
00729     dx = ( p2.x() - p1.x() );
00730     dy = ( p2.y() - p1.y() );
00731     length = sqrt(( dx * dx + dy * dy ));
00732     if ( length == 0.0 )
00733         scale = 1.0;
00734     else
00735         scale = 1.0 / length;
00736     cosa = dx * scale;
00737     sina = dy * scale;
00738 
00739     ramp1 = stop1.rampPoint;
00740     color =  transformColor( ScColorShade(stop1.color, stop1.shade), 1.0 );
00741     r1 = color.red();
00742     g1 = color.green();
00743     b1 = color.blue();
00744     a1 = stop1.opacity * 255;
00745     drawRectangleStrip( m_matrix.dx(), m_matrix.dy(), maxDim, maxDim, r1, g1, b1, a1);
00746 
00747     xform.eM11 = cosa;
00748     xform.eM12 = sina;
00749     xform.eM21 = -sina;
00750     xform.eM22 = cosa;
00751     xform.eDx = x1;
00752     xform.eDy = y1;
00753     ModifyWorldTransform(m_dc, &xform, MWT_LEFTMULTIPLY);
00754 
00755     for( uint index = 1; index < gradient.Stops(); index++)
00756     {
00757         stop2 = *colorStops[index];
00758         ramp2 = stop2.rampPoint;
00759         color =  transformColor( ScColorShade(stop2.color, stop2.shade), 1.0 );
00760         r2 = color.red();
00761         g2 = color.green();
00762         b2 = color.blue();
00763         a2 = stop2.opacity * 255;
00764         int xMin = length * ramp1;
00765         int xMax = length * ramp2;
00766         int r4= -1, b4= -1, g4= -1, a4= -1;
00767         for( xCurrent = xMin; xCurrent < xMax; xCurrent += increment )
00768         {
00769             colorCoeff = ( xCurrent - xMin ) / ( (double) xMax - xMin ) ;
00770             r3 = ( 1 - colorCoeff ) * r1 + colorCoeff * r2;
00771             g3 = ( 1 - colorCoeff ) * g1 + colorCoeff * g2;
00772             b3 = ( 1 - colorCoeff ) * b1 + colorCoeff * b2;
00773             a3 = ( 1 - colorCoeff ) * a1 + colorCoeff * a2;
00774             if( (r3 != r4) || (g3 != g4) || (b3 != b4) )
00775             {
00776                 drawRectangleStrip( xCurrent, -maxDim/2, maxDim, maxDim, r3, g3, b3, a3 );
00777                 r4 = r3;
00778                 g4 = g3;
00779                 b4 = b3;
00780             }
00781         }
00782         stop1 = stop2;
00783         ramp1 = ramp2;
00784         r1 = r2;
00785         g1 = g2;
00786         b1 = b2;
00787         a1 = a2;
00788     }
00789 }
00790 
00791 void ScPainterEx_GDI::drawLinearGradient_GradientFill( VGradientEx& gradient, const QRect& rect )
00792 {
00793     XFORM xform;
00794     int r1, g1, b1;
00795     int r2, g2, b2;
00796     double cosa, sina;
00797     double ramp1, ramp2;
00798     double length, scale;
00799     double x1, y1, x2, y2, dx, dy;
00800     int clipBoxWidth, clipBoxHeight, maxDim;
00801     QList<VColorStopEx*> colorStops = gradient.colorStops();
00802     VColorStopEx stop1( *colorStops[0] );
00803     VColorStopEx stop2( *colorStops[0] );
00804     FPoint p1, p2;
00805     QColor color;
00806 
00807     if ( gradient.Stops() < 2 ) 
00808         return;
00809 
00810     clipBoxWidth = rect.width();
00811     clipBoxHeight = rect.height();
00812     maxDim = sqrt( (double) (clipBoxWidth * clipBoxWidth + clipBoxHeight * clipBoxHeight) ) * 2;
00813     if ( maxDim <= 0 ) return;
00814 
00815     x1 = m_matrix.dx() + gradient.origin().x() * m_matrix.m11();
00816     y1 = m_matrix.dy() + gradient.origin().y() * m_matrix.m22();
00817     x2 = m_matrix.dx() + gradient.vector().x() * m_matrix.m11();
00818     y2 = m_matrix.dy() + gradient.vector().y() * m_matrix.m22();
00819     p1.setXY( x1, y1 );
00820     p2.setXY( x2, y2 );
00821 
00822     dx = ( p2.x() - p1.x() );
00823     dy = ( p2.y() - p1.y() );
00824     length = sqrt(( dx * dx + dy * dy ));
00825     if ( length == 0.0 )
00826         scale = 1.0;
00827     else
00828         scale = 1.0 / length;
00829     cosa = dx * scale;
00830     sina = dy * scale;
00831 
00832     xform.eM11 = cosa;
00833     xform.eM12 = sina;
00834     xform.eM21 = -sina;
00835     xform.eM22 = cosa;
00836     xform.eDx = x1;
00837     xform.eDy = y1;
00838     ModifyWorldTransform(m_dc, &xform, MWT_LEFTMULTIPLY);
00839 
00840     x1 = -maxDim;
00841     stop1 = *colorStops[0];
00842     ramp1 = stop1.rampPoint;
00843     color =  transformColor( ScColorShade(stop1.color, stop1.shade), 1.0 );
00844     r1 = color.red();
00845     g1 = color.green();
00846     b1 = color.blue();
00847 
00848     int numMeshes = colorStops.size() + 1;
00849     int numVertices = numMeshes * 2;
00850     TRIVERTEX* vertices = new TRIVERTEX[numVertices];
00851     GRADIENT_RECT* meshes = new GRADIENT_RECT[numMeshes];
00852 
00853     vertices[0].x = x1;
00854     vertices[0].y = -maxDim / 2;
00855     vertices[0].Red = r1 << 8;
00856     vertices[0].Green = g1 << 8;
00857     vertices[0].Blue = b1 << 8;
00858     vertices[0].Alpha = 0;
00859     meshes[0].UpperLeft = 0;
00860     
00861     uint vIndex = 1;
00862     for( uint index = 0; index < gradient.Stops(); index++, vIndex += 2)
00863     {
00864         stop2 = *colorStops[index];
00865         ramp2 =  stop2.rampPoint;
00866         color =  transformColor( ScColorShade(stop2.color, stop2.shade), 1.0 );
00867         r2 = color.red() << 8;
00868         g2 = color.green() << 8;
00869         b2 = color.blue() << 8;
00870         x2 = /*maxDim +*/ length * ramp2;
00871         vertices[vIndex].x = x2;
00872         vertices[vIndex].y = maxDim / 2;
00873         vertices[vIndex].Red = r2;
00874         vertices[vIndex].Green = g2;
00875         vertices[vIndex].Blue = b2;
00876         vertices[vIndex].Alpha = 0;
00877         vertices[vIndex + 1].x = x2;
00878         vertices[vIndex + 1].y = -maxDim / 2;
00879         vertices[vIndex + 1].Red = r2;
00880         vertices[vIndex + 1].Green = g2;
00881         vertices[vIndex + 1].Blue = b2;
00882         vertices[vIndex + 1].Alpha = 0;
00883         meshes[index].LowerRight = vIndex;
00884         meshes[index + 1].UpperLeft = vIndex + 1;
00885     }
00886 
00887     vertices[numVertices - 1].x = length + maxDim;
00888     vertices[numVertices - 1].y = maxDim / 2;
00889     vertices[numVertices - 1].Red = r2 << 8;
00890     vertices[numVertices - 1].Green = g2 << 8;
00891     vertices[numVertices - 1].Blue = b2 << 8;
00892     vertices[numVertices - 1].Alpha = 0;
00893     meshes[numMeshes - 1].LowerRight = numVertices - 1;
00894 
00895     // Finally call the gradient fill function
00896     (*m_gradientFill)( m_dc, vertices, numVertices, meshes, numMeshes, GRADIENT_FILL_RECT_H );
00897 
00898     // Delete used arrays
00899     delete[] vertices;
00900     delete[] meshes;
00901 }
00902 
00903 void ScPainterEx_GDI::drawRectangleStrip( int x, int y, int w, int h, int r, int g, int b, int a )
00904 {
00905     SaveDC( m_dc );
00906     HPEN hPen = CreatePen( PS_NULL, 0, RGB(255,255,255));
00907     HBRUSH hBrush = CreateSolidBrush( RGB(r, g, b));
00908     HGDIOBJ obj1 = SelectObject( m_dc, hPen );
00909     HGDIOBJ obj2 = SelectObject( m_dc, hBrush );
00910     Rectangle( m_dc, x, y, x + w, y + h );
00911     SelectObject( m_dc, obj2 );
00912     SelectObject( m_dc, obj1 );
00913     DeleteObject( hBrush );
00914     DeleteObject( hPen );
00915     RestoreDC( m_dc, -1 );
00916 }
00917 
00918 void ScPainterEx_GDI::drawCircularGradient( VGradientEx& gradient, const QRect& rect )
00919 {
00920     int radius;
00921     int increment;
00922     int r1, g1, b1, a1;
00923     int r2, g2, b2, a2;
00924     int r3, g3, b3, a3;
00925     double colorCoeff;
00926     double ramp1, ramp2;
00927     double scale1, scale2;
00928     int clipBoxWidth, clipBoxHeight, maxDim;
00929     QList<VColorStopEx*> colorStops = gradient.colorStops();
00930     VColorStopEx stop1( *colorStops[gradient.Stops() - 1] );
00931     VColorStopEx stop2( *colorStops[gradient.Stops() - 1] );
00932     QColor color;
00933 
00934     clipBoxWidth = rect.width();
00935     clipBoxHeight = rect.height();
00936     maxDim = sqrt((double) (clipBoxWidth * clipBoxWidth + clipBoxHeight * clipBoxHeight)) * 2;
00937     if ( maxDim <= 0 ) return;
00938 
00939     scale1 = sqrt( m_matrix.m11() * m_matrix.m11() + m_matrix.m21() * m_matrix.m21() );
00940     scale2 = sqrt( m_matrix.m12() * m_matrix.m12() + m_matrix.m22() * m_matrix.m22() );
00941     increment = (int) max( scale1, scale2 );
00942     increment = (increment < 2) ? 2 : increment;
00943 
00944     FPoint pc( gradient.origin().x(), gradient.origin().y() );
00945     FPoint pcz( gradient.origin().x(), gradient.origin().y() );
00946     FPoint pf( gradient.focalPoint().x(), gradient.focalPoint().y() );
00947     FPoint pfz( gradient.focalPoint().x(), gradient.focalPoint().y() );
00948     FPoint pv( gradient.vector().x(), gradient.vector().y() );
00949     transformPoint( pc, pc );
00950     transformPoint( pf, pf );
00951     transformPoint( pv, pv );
00952     transformPoint( pcz, pcz );
00953     transformPoint( pfz, pfz );
00954     double cx = pcz.x();
00955     double cy = pcz.y();
00956     double fx = pfz.x();
00957     double fy = pfz.y();
00958     double rad = sqrt( pow(pv.x() -pc.x(), 2) + pow(pv.y() - pc.y(), 2) );
00959 
00960     ramp2 = stop2.rampPoint;
00961     color =  transformColor( ScColorShade(stop2.color, stop2.shade), 1.0 );
00962     r2 = color.red();
00963     g2 = color.green();
00964     b2 = color.blue();
00965     a2 = stop2.opacity * 255;
00966     drawCircleStrip( cx - maxDim / 2, cy - maxDim / 2, maxDim, maxDim, color.red(), color.green(), color.blue(), a2);
00967     if ( gradient.Stops() < 2 ) return;
00968 
00969     for( int index = gradient.Stops() - 2; index >= 0; index--)
00970     {
00971         stop1 = *colorStops[index];
00972         ramp1 = stop1.rampPoint;
00973         color =  transformColor( ScColorShade(stop1.color, stop1.shade), 1.0 );
00974         r1 = color.red();
00975         g1 = color.green();
00976         b1 = color.blue();
00977         a1 = stop1.opacity * 255;
00978         int radMax = rad * ramp2;
00979         int radMin = rad * ramp1;
00980         int r4= -1, b4= -1, g4= -1, a4= -1;
00981         for( radius = radMax; radius > radMin; radius -= increment )
00982         {
00983             colorCoeff = ( radius - radMin ) / ( (double) radMax - radMin );
00984             r3 = (1 - colorCoeff) * r1 + colorCoeff * r2;
00985             g3 = (1 - colorCoeff) * g1 + colorCoeff * g2;
00986             b3 = (1 - colorCoeff) * b1 + colorCoeff * b2;
00987             a3 = (1 - colorCoeff) * a1 + colorCoeff * a2;
00988             if( (r3 != r4) || (g3 != g4) || (b3 != b4) )
00989             {
00990                 drawCircleStrip( cx - radius, cy - radius, radius * 2, radius * 2, r3, g3, b3, a3 );
00991                 r4 = r3;
00992                 g4 = g3;
00993                 b4 = b3;
00994             }
00995         }
00996         stop2 = stop1;
00997         ramp2 = ramp1;
00998         r2 = r1;
00999         g2 = g1;
01000         b2 = b1;
01001         a2 = a1;
01002     }
01003 }
01004 
01005 void ScPainterEx_GDI::drawCircleStrip( int x, int y, int w, int h, int r, int g, int b, int a )
01006 {
01007     SaveDC( m_dc );
01008     HPEN hPen = CreatePen( PS_NULL, 0, RGB(255,255,255));
01009     HBRUSH hBrush = CreateSolidBrush( RGB(r, g, b));
01010     HGDIOBJ obj1 = SelectObject( m_dc, hPen );
01011     HGDIOBJ obj2 = SelectObject( m_dc, hBrush );
01012     Ellipse( m_dc, x, y, x + w, y + h );
01013     SelectObject( m_dc, obj2 );
01014     SelectObject( m_dc, obj1 );
01015     DeleteObject( hBrush );
01016     DeleteObject( hPen );
01017     RestoreDC( m_dc, -1 );
01018 }
01019 
01020 void ScPainterEx_GDI::getClipPathDimensions( QRect& r )
01021 {
01022     RECT rect = { 0, 0, 0, 0 };
01023     int result = GetClipBox( m_dc, &rect );
01024     if( result != NULLREGION && result != ERROR )
01025     {
01026         r.setLeft( rect.left );
01027         r.setRight( rect.right );
01028         r.setBottom( rect.bottom );
01029         r.setTop( rect.top );   
01030     }
01031 }
01032 
Created with personalized Doxygen. This is documentation for GPL software Scribus - Open Source Desktop Publishing.