00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
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
00077 m_convertToGray = gray;
00078
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
00343
00344
00345
00346 m_array.clear();
00347 m_offset = 0;
00348 getDashArray(st, w, m_array);
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
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 = 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
00896 (*m_gradientFill)( m_dc, vertices, numVertices, meshes, numMeshes, GRADIENT_FILL_RECT_H );
00897
00898
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