• Main Page
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

plqt.cpp

Go to the documentation of this file.
00001 // This software was donated under the LGPL to the PLplot project in
00002 // March 2009 by the
00003 // Cluster Science Centre
00004 // QSAS team,
00005 // Imperial College, London
00006 //
00007 // Copyright (C) 2009  Imperial College, London
00008 // Copyright (C) 2009-2011  Alan W. Irwin
00009 //
00010 // This is free software; you can redistribute it and/or modify
00011 // it under the terms of the GNU General Lesser Public License as published
00012 // by the Free Software Foundation; either version 2 of the License, or
00013 // (at your option) any later version.
00014 //
00015 // This software 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
00018 // GNU Lesser General Public License for more details.
00019 //
00020 // To received a copy of the GNU Library General Public License
00021 // write to the Free Software Foundation, Inc.,
00022 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00023 //
00024 
00025 #include "qt.h"
00026 
00027 // Global variables for Qt driver.
00028 PLDLLIMPEXP_QT_DATA( int ) vectorize = 0;
00029 PLDLLIMPEXP_QT_DATA( int ) lines_aa  = 1;
00030 PLDLLIMPEXP_QT_DATA( MasterHandler ) handler;
00031 
00032 // Master Device Handler for multiple streams
00033 // Only handles multiple Qt devices
00034 MasterHandler::MasterHandler() : QObject()
00035 {
00036     masterDevice = NULL;
00037 }
00038 
00039 bool MasterHandler::isMasterDevice( QtPLDriver* d )
00040 {
00041     return d == masterDevice;
00042 }
00043 
00044 void MasterHandler::setMasterDevice( QtPLDriver* d )
00045 {
00046     masterDevice = d;
00047 }
00048 
00049 void MasterHandler::DeviceChangedPage( QtPLDriver* d )
00050 {
00051     if ( d == masterDevice )
00052     {
00053         emit MasterChangedPage();
00054     }
00055 }
00056 
00057 void MasterHandler::DeviceClosed( QtPLDriver* d )
00058 {
00059     if ( d == masterDevice )
00060     {
00061         emit MasterClosed();
00062         masterDevice = NULL;
00063     }
00064 }
00065 
00067 QMutex QtPLDriver::mutex;
00068 
00069 QtPLDriver::QtPLDriver( PLINT i_iWidth, PLINT i_iHeight )
00070 {
00071     m_dWidth  = i_iWidth;
00072     m_dHeight = i_iHeight;
00073 }
00074 
00075 QtPLDriver::~QtPLDriver()
00076 {
00077 }
00078 
00079 void QtPLDriver::setPLStream( PLStream *p )
00080 {
00081     pls = p;
00082 }
00083 
00084 void QtPLDriver::drawArc( short x, short y, short a, short b, PLFLT angle1, PLFLT angle2, PLFLT rotate, bool fill )
00085 {
00086     if ( !m_painterP->isActive() )
00087         return;
00088     QRectF rect( (PLFLT) ( x - a ) * downscale,
00089                  m_dHeight - (PLFLT) ( y + b ) * downscale,
00090                  (PLFLT) a * downscale * 2,
00091                  (PLFLT) b * downscale * 2
00092                  );
00093     if ( rotate != 0.0 )
00094     {
00095         m_painterP->save();
00096         m_painterP->translate( (PLFLT) x * downscale, m_dHeight - (PLFLT) y * downscale );
00097         m_painterP->rotate( -rotate );
00098         m_painterP->translate( -(PLFLT) x * downscale, -m_dHeight + (PLFLT) y * downscale );
00099     }
00100 
00101     if ( fill )
00102         m_painterP->drawPie( rect, (int) ( angle1 * 16 ), (int) ( ( angle2 - angle1 ) * 16 ) );
00103     else
00104         m_painterP->drawArc( rect, (int) ( angle1 * 16 ), (int) ( ( angle2 - angle1 ) * 16 ) );
00105 
00106     if ( rotate != 0.0 )
00107     {
00108         m_painterP->restore();
00109     }
00110 }
00111 
00112 void QtPLDriver::drawLine( short x1, short y1, short x2, short y2 )
00113 {
00114     if ( !m_painterP->isActive() )
00115         return;
00116     QLineF line( (PLFLT) x1 * downscale,
00117                  m_dHeight - (PLFLT) y1 * downscale,
00118                  (PLFLT) x2 * downscale,
00119                  m_dHeight - (PLFLT) y2 * downscale
00120                  );
00121 
00122     m_painterP->drawLine( line );
00123 }
00124 
00125 void QtPLDriver::drawPolyline( short * x, short * y, PLINT npts )
00126 {
00127     if ( !m_painterP->isActive() )
00128         return;
00129     QPointF * polyline = new QPointF[npts];
00130     for ( int i = 0; i < npts; ++i )
00131     {
00132         polyline[i].setX( (PLFLT) x[i] * downscale );
00133         polyline[i].setY( m_dHeight - (PLFLT) y[i] * downscale );
00134     }
00135     m_painterP->drawPolyline( polyline, npts );
00136     delete[] polyline;
00137 }
00138 
00139 void QtPLDriver::drawPolygon( short * x, short * y, PLINT npts )
00140 {
00141     if ( !m_painterP->isActive() )
00142         return;
00143     QPointF * polygon = new QPointF[npts];
00144     for ( int i = 0; i < npts; ++i )
00145     {
00146         polygon[i].setX( (PLFLT) x[i] * downscale );
00147         polygon[i].setY( m_dHeight - (PLFLT) y[i] * downscale );
00148     }
00149     if ( plsc->dev_eofill )
00150         m_painterP->drawPolygon( polygon, npts, Qt::OddEvenFill );
00151     else
00152         m_painterP->drawPolygon( polygon, npts, Qt::WindingFill );
00153     delete[] polygon;
00154 }
00155 
00156 
00157 QFont QtPLDriver::getFont( PLUNICODE unicode )
00158 {
00159     // Get new font parameters
00160     unsigned char fontFamily, fontStyle, fontWeight;
00161 
00162     plP_fci2hex( unicode, &fontFamily, PL_FCI_FAMILY );
00163     plP_fci2hex( unicode, &fontStyle, PL_FCI_STYLE );
00164     plP_fci2hex( unicode, &fontWeight, PL_FCI_WEIGHT );
00165 
00166     QFont f;
00167 
00168     f.setPointSizeF( currentFontSize * currentFontScale < 4 ? 4 : currentFontSize * currentFontScale );
00169 
00170     switch ( fontFamily )
00171     {
00172     case 1:
00173         f.setStyleHint( QFont::Serif );
00174         break;
00175     case 2:
00176         f.setStyleHint( QFont::TypeWriter );
00177         break;
00178     case 0: case 3: case 4: default:
00179         f.setStyleHint( QFont::SansSerif );
00180         break;
00181     }
00182     f.setFamily( "" ); // no family name, forcing Qt to find an appropriate font by itself
00183 
00184     if ( fontStyle )
00185         f.setItalic( true );
00186     if ( fontWeight )
00187         f.setWeight( QFont::Bold );
00188     else
00189         f.setWeight( QFont::Normal );
00190 
00191     f.setUnderline( underlined );
00192     f.setOverline( overlined );
00193 
00194     return f;
00195 }
00196 
00197 void QtPLDriver::drawTextInPicture( QPainter* p, const QString& text )
00198 {
00199     QRectF   rect( 0., 0., 0., 0. );
00200     QRectF   bounding;
00201     QPicture tempPic;
00202     QPainter tempPainter( &tempPic );
00203     tempPainter.setFont( p->font() );
00204 
00205     if ( vectorize )
00206     {
00207         bounding = tempPainter.boundingRect( rect, Qt::AlignHCenter | Qt::AlignVCenter | Qt::TextDontClip, text );
00208 
00209         tempPainter.save();
00210 //         QPen savePen=tempPainter.pen();
00211         QPen pen = QPen( Qt::NoPen );
00212         tempPainter.setPen( pen );
00213 
00214         double       offset = QFontMetrics( tempPainter.font(), &tempPic ).boundingRect( text ).top(); // Distance between the baseline and the top of the bounding box
00215 
00216         QPainterPath path;
00217         path.addText( QPointF( bounding.left(), bounding.top() - offset ), tempPainter.font(), text );
00218         tempPainter.drawPath( path );
00219         tempPainter.restore();
00220     }
00221     else
00222     {
00223         tempPainter.drawText( rect, Qt::AlignHCenter | Qt::AlignVCenter | Qt::TextDontClip, text, &bounding );
00224     }
00225 
00226     tempPainter.end();
00227 
00228     p->drawPicture( (int) ( xOffset + bounding.width() / 2. ), (int) -yOffset, tempPic );
00229 
00230     xOffset += bounding.width();
00231 }
00232 
00233 // 0.8 mimics the offset of first superscript/subscript level implemented
00234 // in plstr (plsym.c) for Hershey fonts.  Indeed when comparing with
00235 // -dev xwin results this factor appears to offset the centers of the
00236 // letters appropriately (but not their edges since different font sizes
00237 // are involved).
00238 # define RISE_FACTOR    0.8
00239 
00240 QPicture QtPLDriver::getTextPicture( PLUNICODE fci, PLUNICODE* text, int len, PLFLT chrht )
00241 {
00242     char plplotEsc;
00243     plgesc( &plplotEsc );
00244 
00245     QPicture res;
00246     QPainter p( &res );
00247 
00248     QString  currentString;
00249     PLFLT    old_sscale, sscale, old_soffset, soffset;
00250     PLINT    level    = 0;
00251     PLFLT    dyOffset = 0.;
00252 
00253     yOffset = 0.;
00254     xOffset = 0.;
00255 
00256     // Scaling factor of 1.45 determined empirically to make all qt results
00257     // have the same character size as cairo results (taking into account
00258     // the slightly different actual glyph sizes for the different
00259     // default fonts found by cairo and qt).
00260     currentFontSize  = chrht * POINTS_PER_INCH / 25.4 * 1.45;
00261     currentFontScale = 1.;
00262     underlined       = false;
00263     overlined        = false;
00264 
00265     p.setFont( getFont( fci ) );
00266 
00267     int i = 0;
00268     while ( i < len )
00269     {
00270         if ( text[i] < PL_FCI_MARK ) // Not a font change
00271         {
00272             if ( text[i] != (PLUNICODE) plplotEsc )
00273             {
00274                 currentString.append( QString( QChar( text[i] ) ) );
00275                 ++i;
00276                 continue;
00277             }
00278             ++i; // Now analyse the escaped character
00279             switch ( text[i] )
00280             {
00281             case 'd': //subscript
00282                 drawTextInPicture( &p, currentString );
00283                 currentString.clear();
00284                 plP_script_scale( FALSE, &level,
00285                     &old_sscale, &sscale, &old_soffset, &soffset );
00286                 currentFontScale = sscale;
00287 
00288                 // The correction for the difference in magnitude
00289                 // between the baseline and middle coordinate systems
00290                 // for subscripts should be
00291                 // -0.5*(fontSize - superscript/subscript fontSize).
00292                 // dyOffset = -0.5 * currentFontSize * ( 1.0 - sscale );
00293                 // But empirically this change in offset should not be applied
00294                 // so leave it at its initial value of zero.
00295                 yOffset = -( currentFontSize * RISE_FACTOR * soffset + dyOffset );
00296 
00297                 p.setFont( getFont( fci ) );
00298                 break;
00299 
00300             case 'u':  //superscript
00301                 drawTextInPicture( &p, currentString );
00302 
00303                 currentString.clear();
00304                 plP_script_scale( TRUE, &level,
00305                     &old_sscale, &sscale, &old_soffset, &soffset );
00306                 currentFontScale = sscale;
00307 
00308                 // The correction for the difference in magnitude
00309                 // between the baseline and middle coordinate systems
00310                 // for superscripts should be
00311                 // 0.5*(fontSize - superscript/subscript fontSize).
00312                 // dyOffset = 0.5 * currentFontSize * ( 1.0 - sscale );
00313                 // But empirically this change in offset should not be applied
00314                 // so leave it at its initial value of zero.
00315                 yOffset = currentFontSize * RISE_FACTOR * soffset + dyOffset;
00316 
00317                 p.setFont( getFont( fci ) );
00318                 break;
00319 
00320             case '-':
00321                 drawTextInPicture( &p, currentString );
00322 
00323                 currentString.clear();
00324                 underlined = !underlined;
00325                 p.setFont( getFont( fci ) );
00326                 break;
00327 
00328             case '+':
00329                 drawTextInPicture( &p, currentString );
00330 
00331                 currentString.clear();
00332                 overlined = !overlined;
00333                 p.setFont( getFont( fci ) );
00334                 break;
00335 
00336 
00337             case '#':
00338                 currentString.append( QString( (QChar *) &( text[i] ), 1 ) );
00339                 break;
00340 
00341             default:
00342                 std::cout << "unknown escape char " << ( (QChar) text[i] ).toLatin1() << std::endl;
00343                 break;
00344             }
00345         }
00346         else // Font change
00347         {
00348             drawTextInPicture( &p, currentString );
00349 
00350             currentString.clear();
00351             fci = text[i];
00352             p.setFont( getFont( fci ) );
00353         }
00354         ++i;
00355     }
00356     drawTextInPicture( &p, currentString );
00357 
00358     p.end();
00359 
00360     return res;
00361 }
00362 
00363 void QtPLDriver::drawText( EscText* txt )
00364 {
00365     if ( !m_painterP->isActive() )
00366         return;
00367 
00368     // Check that we got unicode, warning message and return if not
00369     if ( txt->unicode_array_len == 0 )
00370     {
00371         printf( "Non unicode string passed to a Qt driver, ignoring\n" );
00372         return;
00373     }
00374 
00375     // Check that unicode string isn't longer then the max we allow
00376     if ( txt->unicode_array_len >= 500 )
00377     {
00378         printf( "Sorry, the Qt drivers only handle strings of length < %d\n", 500 );
00379         return;
00380     }
00381 
00382     PLFLT rotation, shear, stride;
00383     plRotationShear( txt->xform, &rotation, &shear, &stride );
00384 
00385     double    picDpi;
00386     PLUNICODE fci;
00387     plgfci( &fci );
00388     QPicture  picText = getTextPicture( fci, txt->unicode_array, txt->unicode_array_len, pls->chrht );
00389     picDpi = picText.logicalDpiY();
00390 
00391     if ( pls->get_string_length )
00392     {
00393         pls->string_length = ( (PLFLT) xOffset / picDpi ) * 25.4;
00394         return;
00395     }
00396 
00397     m_painterP->setClipping( true );
00398     m_painterP->setClipRect( QRect( (int) ( pls->clpxmi * downscale ), (int) ( m_dHeight - pls->clpyma * downscale ), (int) ( ( pls->clpxma - pls->clpxmi ) * downscale ), (int) ( ( pls->clpyma - pls->clpymi ) * downscale ) ), Qt::ReplaceClip );
00399 
00400     rotation -= pls->diorot * M_PI / 2.0;
00401     m_painterP->translate( txt->x * downscale, m_dHeight - txt->y * downscale );
00402     QMatrix rotShearMatrix( cos( rotation ) * stride, -sin( rotation ) * stride, cos( rotation ) * sin( shear ) + sin( rotation ) * cos( shear ), -sin( rotation ) * sin( shear ) + cos( rotation ) * cos( shear ), 0., 0. );
00403 
00404     m_painterP->setWorldMatrix( rotShearMatrix, true );
00405 
00406     m_painterP->translate( -txt->just * xOffset * m_painterP->device()->logicalDpiY() / picDpi, 0. );
00407 
00408     m_painterP->drawPicture( 0, 0, picText );
00409 
00410     m_painterP->resetTransform();;
00411     m_painterP->setClipping( false );
00412 }
00413 
00414 void QtPLDriver::setColor( int r, int g, int b, double alpha )
00415 {
00416     if ( !m_painterP->isActive() )
00417         return;
00418 
00419     QPen p = m_painterP->pen();
00420     p.setColor( QColor( r, g, b, (int) ( alpha * 255 ) ) );
00421     m_painterP->setPen( p );
00422 
00423     QBrush B = m_painterP->brush();
00424     B.setColor( QColor( r, g, b, (int) ( alpha * 255 ) ) );
00425     B.setStyle( Qt::SolidPattern );
00426     m_painterP->setBrush( B );
00427 }
00428 
00429 void QtPLDriver::setGradient( int x1, int x2, int y1, int y2,
00430                               unsigned char *r, unsigned char *g,
00431                               unsigned char *b, PLFLT *alpha, PLINT ncol1 )
00432 {
00433     if ( !m_painterP->isActive() || ncol1 < 2 )
00434         return;
00435 
00436     int             i;
00437     qreal           stop_arg;
00438     QLinearGradient linear_gradient;
00439     QGradientStops  stops;
00440 
00441     linear_gradient = QLinearGradient(
00442         QPointF( (qreal) ( x1 * downscale ), (qreal) ( m_dHeight - y1 * downscale ) ),
00443         QPointF( (qreal) ( x2 * downscale ), (qreal) ( m_dHeight - y2 * downscale ) ) );
00444 
00445     for ( i = 0; i < ncol1; i++ )
00446     {
00447         stop_arg = (qreal) i / (qreal) ( ncol1 - 1 );
00448         stops << QGradientStop( stop_arg, QColor( r[i], g[i],
00449                 b[i], (int) ( alpha[i] * 255 ) ) );
00450     }
00451     linear_gradient.setStops( stops );
00452     m_painterP->setBrush( linear_gradient );
00453 }
00454 
00455 void QtPLDriver::setWidth( PLINT w )
00456 {
00457     if ( !m_painterP->isActive() )
00458         return;
00459 
00460     QPen p = m_painterP->pen();
00461     p.setWidth( w );
00462     m_painterP->setPen( p );
00463 }
00464 
00465 // void QtPLDriver::setDashed(PLINT nms, PLINT* mark, PLINT* space)
00466 // {
00467 //     if(!m_painterP->isActive()) return;
00468 //
00469 //     QVector<qreal> vect;
00470 //     for(int i=0; i<nms; ++i)
00471 //     {
00472 //         vect << (PLFLT)mark[i]*m_painterP->device()->logicalDpiX()/25400.;
00473 //         vect << (PLFLT)space[i]*m_painterP->device()->logicalDpiX()/25400.;
00474 //     }
00475 //     QPen p=m_painterP->pen();
00476 //     p.setDashPattern(vect);
00477 //     m_painterP->setPen(p);
00478 // }
00479 
00480 void QtPLDriver::setSolid()
00481 {
00482     if ( !m_painterP->isActive() )
00483         return;
00484 
00485     QPen p = m_painterP->pen();
00486     p.setStyle( Qt::SolidLine );
00487     m_painterP->setPen( p );
00488 }
00489 
00491 #if defined ( PLD_bmpqt ) || defined ( PLD_jpgqt ) || defined ( PLD_pngqt ) || defined ( PLD_ppmqt ) || defined ( PLD_tiffqt )
00492 QtRasterDevice::QtRasterDevice( int i_iWidth, int i_iHeight ) :
00493     QtPLDriver( i_iWidth, i_iHeight ),
00494     QImage( i_iWidth, i_iHeight, QImage::Format_RGB32 )
00495 {
00496     // Painter initialised in the constructor contrary
00497     // to buffered drivers, which paint only in doPlot().
00498     m_painterP = new QPainter( this );
00499     QBrush b = m_painterP->brush();
00500     b.setStyle( Qt::SolidPattern );
00501     m_painterP->setBrush( b );
00502     m_painterP->setRenderHint( QPainter::Antialiasing, (bool) lines_aa );
00503 }
00504 
00505 QtRasterDevice::~QtRasterDevice()
00506 {
00507     delete m_painterP;
00508 }
00509 
00510 void QtRasterDevice::definePlotName( const char* fileName, const char* format )
00511 {
00512     // Avoid buffer overflows
00513     strncpy( this->format, format, 4 );
00514     this->format[4] = '\0';
00515 
00516     this->fileName = QString( fileName );
00517 }
00518 
00519 void QtRasterDevice::savePlot()
00520 {
00521     m_painterP->end();
00522     save( fileName, format, 85 );
00523 
00524     m_painterP->begin( this );
00525     m_painterP->setRenderHint( QPainter::Antialiasing, (bool) lines_aa );
00526     QBrush b = m_painterP->brush();
00527     b.setStyle( Qt::SolidPattern );
00528     m_painterP->setBrush( b );
00529 }
00530 
00531 void QtRasterDevice::setBackgroundColor( int r, int g, int b, double alpha )
00532 {
00533     if ( !m_painterP->isActive() )
00534         return;
00535 
00536     QBrush brush( QColor( r, g, b, (int) ( alpha * 255 ) ) );
00537     m_painterP->fillRect( 0, 0, width(), height(), brush );
00538 }
00539 #endif
00540 
00541 #if defined ( PLD_svgqt ) && QT_VERSION >= 0x040300
00542 QtSVGDevice::QtSVGDevice( int i_iWidth, int i_iHeight ) :
00543     QtPLDriver( i_iWidth, i_iHeight )
00544 {
00545     m_painterP = NULL;
00546 }
00547 
00548 QtSVGDevice::~QtSVGDevice()
00549 {
00550     delete m_painterP;
00551 }
00552 
00553 void QtSVGDevice::definePlotName( const char* fileName )
00554 {
00555     setFileName( QString( fileName ) );
00556     setResolution( POINTS_PER_INCH );
00557     setSize( QSize( (int) m_dWidth, (int) m_dHeight ) );
00558 #if QT_VERSION >= 0x040500
00559     setViewBox( QRect( 0, 0, (int) m_dWidth, (int) m_dHeight ) );
00560 #endif
00561 
00562     m_painterP = new QPainter( this );
00563 }
00564 
00565 void QtSVGDevice::savePlot()
00566 {
00567     m_painterP->end();
00568 }
00569 
00570 void QtSVGDevice::setBackgroundColor( int r, int g, int b, double alpha )
00571 {
00572     if ( !m_painterP->isActive() )
00573         return;
00574 
00575     QBrush brush( QColor( r, g, b, (int) ( alpha * 255 ) ) );
00576     m_painterP->fillRect( 0, 0, width(), height(), brush );
00577 }
00578 #endif
00579 
00580 #if defined ( PLD_epsqt ) || defined ( PLD_pdfqt )
00581 QtEPSDevice::QtEPSDevice( int i_iWidth, int i_iHeight )
00582 {
00583 #if QT_VERSION < 0x040400
00584     setPageSize( QPrinter::A4 );
00585 #else
00586     setFullPage( true );
00587     setPaperSize( QSizeF( i_iHeight, i_iWidth ), QPrinter::Point );
00588 #endif
00589     setResolution( POINTS_PER_INCH );
00590     setColorMode( QPrinter::Color );
00591     setOrientation( QPrinter::Landscape );
00592     setPrintProgram( QString( "lpr" ) );
00593 
00594     if ( i_iWidth <= 0 || i_iHeight <= 0 )
00595     {
00596         m_dWidth  = pageRect().width();
00597         m_dHeight = pageRect().height();
00598     }
00599     else
00600     {
00601         m_dWidth  = i_iWidth;
00602         m_dHeight = i_iHeight;
00603     }
00604     m_painterP = NULL;
00605 }
00606 
00607 QtEPSDevice::~QtEPSDevice()
00608 {
00609     delete m_painterP;
00610 }
00611 
00612 void QtEPSDevice::definePlotName( const char* fileName, int ifeps )
00613 {
00614     setOutputFileName( QString( fileName ) );
00615     if ( ifeps )
00616     {
00617         setOutputFormat( QPrinter::PostScriptFormat );
00618     }
00619     else
00620     {
00621         setOutputFormat( QPrinter::PdfFormat );
00622     }
00623 
00624     m_painterP = new QPainter( this );
00625 }
00626 
00627 void QtEPSDevice::savePlot()
00628 {
00629     m_painterP->end();
00630 }
00631 
00632 void QtEPSDevice::setBackgroundColor( int r, int g, int b, double alpha )
00633 {
00634     if ( !m_painterP->isActive() )
00635         return;
00636 
00637     QBrush brush( QColor( r, g, b, (int) ( alpha * 255 ) ) );
00638     m_painterP->fillRect( 0, 0, width(), height(), brush );
00639 }
00640 #endif
00641 
00642 #if defined ( PLD_qtwidget ) || defined ( PLD_extqt )
00643 QtPLWidget::QtPLWidget( int i_iWidth, int i_iHeight, QWidget* parent ) :
00644     QWidget( parent ), QtPLDriver( i_iWidth, i_iHeight )
00645 {
00646     m_painterP = new QPainter;
00647 
00648     m_dAspectRatio = m_dWidth / m_dHeight;
00649 
00650     m_pixPixmap = NULL;
00651 //     m_iOldSize=0;
00652     pageNumber = 0;
00653     resize( i_iWidth, i_iHeight );
00654     lastColour.r = -1;
00655     setVisible( true );
00656     QApplication::processEvents();
00657     redrawFromLastFlush = false;
00658     redrawAll           = true;
00659 
00660     NoPen = QPen( Qt::NoPen );
00661     NoPen.setWidthF( 0. );
00662 
00663     locate_mode = 0;
00664 }
00665 
00666 QtPLWidget::~QtPLWidget()
00667 {
00668     clearBuffer();
00669     delete m_pixPixmap;
00670 }
00671 
00672 void QtPLWidget::clearWidget()
00673 {
00674     clearBuffer();
00675     setBackgroundColor( bgColour.r, bgColour.g, bgColour.b, bgColour.alpha );
00676     redrawAll = true;
00677 //     m_bAwaitingRedraw=true;
00678     update();
00679 }
00680 
00681 void QtPLWidget::flush()
00682 {
00683     repaint();
00684     QApplication::processEvents();
00685 }
00686 
00687 void QtPLWidget::clearBuffer()
00688 {
00689     lastColour.r = -1;
00690     for ( QLinkedList<BufferElement>::iterator i = m_listBuffer.begin(); i != m_listBuffer.end(); ++i )
00691     {
00692         switch ( i->Element )
00693         {
00694         case LINE:
00695             delete i->Data.Line;
00696             break;
00697         case RECTANGLE:
00698             delete i->Data.Rect;
00699             break;
00700 
00701         case POLYLINE:
00702         case POLYGON:
00703             delete i->Data.Polyline;
00704             break;
00705 
00706         case TEXT:
00707             delete[] i->Data.TextStruct->text;
00708             delete i->Data.TextStruct;
00709             break;
00710 
00711         case SET_COLOUR:
00712         case SET_BG_COLOUR:
00713             delete i->Data.ColourStruct;
00714             break;
00715 
00716         case SET_GRADIENT:
00717             delete i->Data.LinearGradient;
00718             break;
00719 
00720         case ARC:
00721             delete i->Data.ArcStruct->rect;
00722             delete i->Data.ArcStruct->dx;
00723             delete i->Data.ArcStruct;
00724 
00725         default:
00726             break;
00727         }
00728     }
00729 
00730     m_listBuffer.clear();
00731     start_iterator = m_listBuffer.constBegin();
00732     redrawAll      = true;
00733 }
00734 
00735 
00736 void QtPLWidget::drawArc( short x, short y, short a, short b, PLFLT angle1, PLFLT angle2, PLFLT rotate, bool fill )
00737 {
00738     BufferElement el;
00739     el.Element              = ARC;
00740     el.Data.ArcStruct       = new struct ArcStruct_;
00741     el.Data.ArcStruct->rect = new QRectF( (PLFLT) ( x - a ) * downscale,
00742         m_dHeight - (PLFLT) ( y + b ) * downscale,
00743         (PLFLT) a * downscale * 2,
00744         (PLFLT) b * downscale * 2
00745         );
00746     el.Data.ArcStruct->startAngle = (int) ( angle1 * 16 );
00747     el.Data.ArcStruct->spanAngle  = (int) ( ( angle2 - angle1 ) * 16 );
00748     el.Data.ArcStruct->rotate     = rotate;
00749     el.Data.ArcStruct->dx         = new QPointF( (PLFLT) x * downscale, m_dHeight - (PLFLT) y * downscale );
00750     el.Data.ArcStruct->fill       = fill;
00751 
00752     m_listBuffer.append( el );
00753     redrawFromLastFlush = true;
00754 }
00755 
00756 
00757 void QtPLWidget::drawLine( short x1, short y1, short x2, short y2 )
00758 {
00759     BufferElement el;
00760     el.Element   = LINE;
00761     el.Data.Line = new QLineF( QPointF( (PLFLT) x1 * downscale, (PLFLT) ( m_dHeight - y1 * downscale ) ), QPointF( (PLFLT) x2 * downscale, (PLFLT) ( m_dHeight - y2 * downscale ) ) );
00762 
00763     m_listBuffer.append( el );
00764     redrawFromLastFlush = true;
00765 }
00766 
00767 void QtPLWidget::drawPolyline( short * x, short * y, PLINT npts )
00768 {
00769     BufferElement el;
00770     el.Element       = POLYLINE;
00771     el.Data.Polyline = new QPolygonF;
00772     for ( int i = 0; i < npts; ++i )
00773     {
00774         ( *el.Data.Polyline ) << QPointF( (PLFLT) ( x[i] ) * downscale, (PLFLT) ( m_dHeight - ( y[i] ) * downscale ) );
00775     }
00776 
00777     m_listBuffer.append( el );
00778     redrawFromLastFlush = true;
00779 }
00780 
00781 void QtPLWidget::drawPolygon( short * x, short * y, PLINT npts )
00782 {
00783     BufferElement el;
00784 
00785     bool          isRect = false;
00786     if ( npts == 4 ) // Check if it's a rectangle. If so, it can be made faster to display
00787     {
00788         if ( x[0] == x[1] && x[2] == x[3] && y[0] == y[3] && y[1] == y[2] )
00789         {
00790             isRect = true;
00791         }
00792         else if ( x[0] == x[3] && x[1] == x[2] && y[0] == y[1] && y[2] == y[3] )
00793         {
00794             isRect = true;
00795         }
00796     }
00797     if ( npts == 5 )
00798     {
00799         if ( x[0] == x[4] && y[0] == y[4] )
00800         {
00801             if ( x[0] == x[1] && x[2] == x[3] && y[0] == y[3] && y[1] == y[2] )
00802             {
00803                 isRect = true;
00804             }
00805             else if ( x[0] == x[3] && x[1] == x[2] && y[0] == y[1] && y[2] == y[3] )
00806             {
00807                 isRect = true;
00808             }
00809         }
00810     }
00811 
00812     if ( isRect )
00813     {
00814         el.Element = RECTANGLE;
00815 
00816         double x1, y1, x2, y2, x0, y0, width, height;
00817         x1 = (PLFLT) ( x[0] ) * downscale;
00818         x2 = (PLFLT) ( x[2] ) * downscale;
00819         y1 = (PLFLT) ( m_dHeight - ( y[0] ) * downscale );
00820         y2 = (PLFLT) ( m_dHeight - ( y[2] ) * downscale );
00821         if ( x1 < x2 )
00822         {
00823             x0    = x1;
00824             width = x2 - x1;
00825         }
00826         else
00827         {
00828             x0    = x2;
00829             width = x1 - x2;
00830         }
00831         if ( y1 < y2 )
00832         {
00833             y0     = y1;
00834             height = y2 - y1;
00835         }
00836         else
00837         {
00838             y0     = y2;
00839             height = y1 - y2;
00840         }
00841         el.Data.Rect = new QRectF( x0, y0, width, height );
00842     }
00843     else
00844     {
00845         el.Element       = POLYGON;
00846         el.Data.Polyline = new QPolygonF;
00847         for ( int i = 0; i < npts; ++i )
00848         {
00849             ( *el.Data.Polyline ) << QPointF( (PLFLT) ( x[i] ) * downscale, (PLFLT) ( m_dHeight - ( y[i] ) * downscale ) );
00850         }
00851     }
00852 
00853     m_listBuffer.append( el );
00854     redrawFromLastFlush = true;
00855 }
00856 
00857 void QtPLWidget::setColor( int r, int g, int b, double alpha )
00858 {
00859     if ( lastColour.r != r || lastColour.g != g || lastColour.b != b || lastColour.alpha != alpha )
00860     {
00861         BufferElement el;
00862         el.Element              = SET_COLOUR;
00863         el.Data.ColourStruct    = new struct ColourStruct_;
00864         el.Data.ColourStruct->R = r;
00865         el.Data.ColourStruct->G = g;
00866         el.Data.ColourStruct->B = b;
00867         el.Data.ColourStruct->A = (PLINT) ( alpha * 255. );
00868 
00869         m_listBuffer.append( el );
00870 
00871         lastColour.r     = r;
00872         lastColour.g     = g;
00873         lastColour.b     = b;
00874         lastColour.alpha = alpha;
00875     }
00876     // No need to ask for a redraw at this point. The color only affects subsequent items
00877 //     redrawFromLastFlush=true;
00878 }
00879 
00880 void QtPLWidget::setGradient( int x1, int x2, int y1, int y2,
00881                               unsigned char *r, unsigned char *g,
00882                               unsigned char *b, PLFLT *alpha, PLINT ncol1 )
00883 {
00884     int            i;
00885     BufferElement  el;
00886     qreal          stop_arg;
00887     QGradientStops stops;
00888 
00889     el.Element = SET_GRADIENT;
00890 
00891     el.Data.LinearGradient  = new QLinearGradient;
00892     *el.Data.LinearGradient = QLinearGradient(
00893         QPointF( (qreal) ( x1 * downscale ), (qreal) ( m_dHeight - y1 * downscale ) ),
00894         QPointF( (qreal) ( x2 * downscale ), (qreal) ( m_dHeight - y2 * downscale ) ) );
00895     for ( i = 0; i < ncol1; i++ )
00896     {
00897         stop_arg = (qreal) i / (qreal) ( ncol1 - 1 );
00898         stops << QGradientStop( stop_arg, QColor( r[i], g[i],
00899                 b[i], (int) ( alpha[i] * 255 ) ) );
00900     }
00901     ( *el.Data.LinearGradient ).setStops( stops );
00902     m_listBuffer.append( el );
00903 
00904     // No need to ask for a redraw at this point. The gradient only
00905     // affects subsequent items.
00906     //redrawFromLastFlush=true;
00907 }
00908 
00909 void QtPLWidget::setBackgroundColor( int r, int g, int b, double alpha )
00910 {
00911     BufferElement el;
00912     el.Element              = SET_BG_COLOUR;
00913     el.Data.ColourStruct    = new struct ColourStruct_;
00914     el.Data.ColourStruct->R = r;
00915     el.Data.ColourStruct->G = g;
00916     el.Data.ColourStruct->B = b;
00917     el.Data.ColourStruct->A = (PLINT) ( alpha * 255. );
00918 
00919     bgColour.r     = r;
00920     bgColour.g     = g;
00921     bgColour.b     = b;
00922     bgColour.alpha = alpha;
00923     if ( alpha >= 0.999 )
00924     {
00925         clearBuffer();
00926     }
00927     m_listBuffer.append( el );
00928     redrawFromLastFlush = true;
00929 }
00930 
00931 void QtPLWidget::setWidth( PLINT w )
00932 {
00933     BufferElement el;
00934     el.Element       = SET_WIDTH;
00935     el.Data.intParam = w;
00936     m_listBuffer.append( el );
00937 //     redrawFromLastFlush=true;
00938 }
00939 
00940 void QtPLWidget::drawText( EscText* txt )
00941 {
00942     if ( pls->get_string_length )
00943     {
00944         PLUNICODE fci;
00945         QPicture  picText;
00946         double    picDpi;
00947         PLUNICODE *text;
00948 
00949         plgfci( &fci );
00950         text = new PLUNICODE[txt->unicode_array_len];
00951         memcpy( text, txt->unicode_array, txt->unicode_array_len * sizeof ( PLUNICODE ) );
00952         picText = getTextPicture( fci,
00953             text,
00954             txt->unicode_array_len,
00955             pls->chrht );
00956         //
00957         // I'm assuming that y_fact is 1.0 here, as it is impossible
00958         // to know in advance (or so I believe). When the text is
00959         // rendered "for real" it will be: pls->chrht * y_fact.
00960         //
00961         // Hazen 6/2011
00962         //
00963         picDpi             = picText.logicalDpiY();
00964         pls->string_length = ( (PLFLT) xOffset / picDpi ) * 25.4;
00965         delete[] text;
00966         return;
00967     }
00968 
00969     BufferElement el;
00970 
00971     el.Element                   = TEXT;
00972     el.Data.TextStruct           = new struct TextStruct_;
00973     el.Data.TextStruct->x        = txt->x * downscale;
00974     el.Data.TextStruct->y        = m_dHeight - txt->y * downscale;
00975     el.Data.TextStruct->clipxmin = pls->clpxmi * downscale;
00976     el.Data.TextStruct->clipymin = m_dHeight - pls->clpymi * downscale;
00977     el.Data.TextStruct->clipxmax = pls->clpxma * downscale;
00978     el.Data.TextStruct->clipymax = m_dHeight - pls->clpyma * downscale;
00979     PLUNICODE fci;
00980     plgfci( &fci );
00981     el.Data.TextStruct->fci = fci;
00982     PLFLT rotation, shear, stride;
00983     plRotationShear( txt->xform, &rotation, &shear, &stride );
00984     rotation -= pls->diorot * M_PI / 2.0;
00985     el.Data.TextStruct->rotation = rotation;
00986     el.Data.TextStruct->shear    = shear;
00987     el.Data.TextStruct->stride   = stride;
00988     el.Data.TextStruct->just     = txt->just;
00989     el.Data.TextStruct->text     = new PLUNICODE[txt->unicode_array_len];
00990     memcpy( el.Data.TextStruct->text, txt->unicode_array, txt->unicode_array_len * sizeof ( PLUNICODE ) );
00991     el.Data.TextStruct->len   = txt->unicode_array_len;
00992     el.Data.TextStruct->chrht = pls->chrht;
00993 
00994     m_listBuffer.append( el );
00995     redrawFromLastFlush = true;
00996 }
00997 
00998 void QtPLWidget::renderText( QPainter* p, struct TextStruct_* s, double x_fact, double x_offset, double y_fact, double y_offset )
00999 {
01000     if ( s->len <= 0 || s->len >= 500 )
01001         return;
01002     QPicture picText = getTextPicture( s->fci, s->text, s->len, s->chrht * y_fact );
01003 
01004     double   picDpi = picText.logicalDpiY();
01005 
01006     p->setClipping( true );
01007     p->setClipRect( QRectF( s->clipxmin * x_fact + x_offset, s->clipymax * y_fact + y_offset, ( s->clipxmax - s->clipxmin ) * x_fact, ( -s->clipymax + s->clipymin ) * y_fact ), Qt::ReplaceClip );
01008     p->translate( s->x * x_fact + x_offset, s->y * y_fact + y_offset );
01009     QMatrix rotShearMatrix( cos( s->rotation ) * s->stride, -sin( s->rotation ) * s->stride, cos( s->rotation ) * sin( s->shear ) + sin( s->rotation ) * cos( s->shear ), -sin( s->rotation ) * sin( s->shear ) + cos( s->rotation ) * cos( s->shear ), 0., 0. );
01010     p->setWorldMatrix( rotShearMatrix, true );
01011 
01012     p->translate( -s->just * xOffset * p->device()->logicalDpiY() / picDpi, 0. );
01013 
01014     p->drawPicture( 0, 0, picText );
01015 
01016     p->resetTransform();
01017 
01018     p->setClipping( false );
01019 }
01020 
01021 void QtPLWidget::resetPensAndBrushes( QPainter* painter )
01022 {
01023     SolidPen = QPen();
01024     hasPen   = true;
01025     painter->setPen( SolidPen );
01026     SolidBrush = QBrush( Qt::SolidPattern );
01027 }
01028 
01029 void QtPLWidget::lookupButtonEvent( QMouseEvent * event )
01030 {
01031     Qt::MouseButtons      buttons   = event->buttons();
01032     Qt::KeyboardModifiers modifiers = event->modifiers();
01033     gin.pX = event->x();
01034     gin.pY = height() - event->y();
01035     gin.dX = (PLFLT) event->x() / width();
01036     gin.dY = (PLFLT) ( height() - event->y() ) / height();
01037 
01038     switch ( event->button() )
01039     {
01040     case Qt::LeftButton:
01041         gin.button = 1;
01042         break;
01043     case Qt::MidButton:
01044         gin.button = 2;
01045         break;
01046     case Qt::RightButton:
01047         gin.button = 3;
01048         break;
01049     }
01050 
01051     // Map Qt button and key states to the (X windows) values used
01052     // by plplot.
01053     gin.state = 0;
01054     if ( buttons & Qt::LeftButton )
01055         gin.state |= 1 << 8;
01056     if ( buttons & Qt::MidButton )
01057         gin.state |= 1 << 9;
01058     if ( buttons & Qt::RightButton )
01059         gin.state |= 1 << 10;
01060     if ( modifiers & Qt::ShiftModifier )
01061         gin.state |= 1 << 0;
01062     if ( modifiers & Qt::ControlModifier )
01063         gin.state |= 1 << 2;
01064     if ( modifiers & Qt::AltModifier )
01065         gin.state |= 1 << 3;
01066     if ( modifiers & Qt::MetaModifier )
01067         gin.state |= 1 << 3;
01068 
01069     gin.keysym = 0x20;
01070 }
01071 
01072 void QtPLWidget::locate()
01073 {
01074     if ( plTranslateCursor( &gin ) )
01075     {
01076         if ( locate_mode == 2 )
01077         {
01078             pltext();
01079             if ( gin.keysym < 0xFF && isprint( gin.keysym ) )
01080                 std::cout << gin.wX << " " << gin.wY << " " << (char) gin.keysym << std::endl;
01081             else
01082                 std::cout << gin.wX << " " << gin.wY << " " << std::hex << gin.keysym << std::endl;
01083 
01084             plgra();
01085         }
01086     }
01087     else
01088     {
01089         locate_mode = 0;
01090         QApplication::restoreOverrideCursor();
01091     }
01092 }
01093 
01094 void QtPLWidget::mouseEvent( QMouseEvent * event )
01095 {
01096     lookupButtonEvent( event );
01097 
01098     if ( locate_mode )
01099     {
01100         if ( event->button() == Qt::LeftButton )
01101         {
01102             locate();
01103         }
01104     }
01105     else
01106     {
01107         if ( event->button() == Qt::RightButton )
01108         {
01109             handler.DeviceChangedPage( this );
01110         }
01111     }
01112 }
01113 
01114 void QtPLWidget::mousePressEvent( QMouseEvent * event )
01115 {
01116     mouseEvent( event );
01117 }
01118 
01119 void QtPLWidget::mouseReleaseEvent( QMouseEvent * event )
01120 {
01121     mouseEvent( event );
01122 }
01123 
01124 void QtPLWidget::mouseMoveEvent( QMouseEvent * event )
01125 {
01126     mouseEvent( event );
01127 }
01128 
01129 void QtPLWidget::keyPressEvent( QKeyEvent* event )
01130 {
01131     if ( locate_mode )
01132     {
01133         Qt::KeyboardModifiers modifiers = event->modifiers();
01134         QPoint p = QCursor::pos();
01135         gin.pX = p.x();
01136         gin.pY = height() - p.y();
01137         gin.dX = (PLFLT) p.x() / width();
01138         gin.dY = (PLFLT) ( height() - p.y() ) / height();
01139 
01140         switch ( event->key() )
01141         {
01142         case Qt::Key_Escape:
01143             locate_mode = 0;
01144             QApplication::restoreOverrideCursor();
01145             plGinInit( &gin );
01146             break;
01147         case Qt::Key_Shift:
01148         case Qt::Key_Control:
01149         case Qt::Key_Alt:
01150         case Qt::Key_Meta:
01151         case Qt::Key_AltGr:
01152             plGinInit( &gin );
01153         case Qt::Key_Left:
01154         case Qt::Key_Right:
01155         case Qt::Key_Up:
01156         case Qt::Key_Down:
01157         {
01158             int x1, y1, dx = 0, dy = 0;
01159             int xmin = 0, xmax = width() - 1, ymin = 0, ymax = height() - 1;
01160             switch ( event->key() )
01161             {
01162             case Qt::Key_Left:
01163                 dx = -1;
01164                 break;
01165             case Qt::Key_Right:
01166                 dx = 1;
01167                 break;
01168             case Qt::Key_Up:
01169                 dy = -1;
01170                 break;
01171             case Qt::Key_Down:
01172                 dy = 1;
01173                 break;
01174             }
01175             if ( event->modifiers() & Qt::ShiftModifier )
01176             {
01177                 dx *= 5;
01178                 dy *= 5;
01179             }
01180             if ( event->modifiers() & Qt::ControlModifier )
01181             {
01182                 dx *= 5;
01183                 dy *= 5;
01184             }
01185             if ( event->modifiers() & Qt::AltModifier )
01186             {
01187                 dx *= 5;
01188                 dy *= 5;
01189             }
01190             x1 = gin.pX + dx;
01191             y1 = gin.pY + dy;
01192 
01193             if ( x1 < xmin )
01194                 dx = xmin - gin.pX;
01195             if ( y1 < ymin )
01196                 dy = ymin - gin.pY;
01197             if ( x1 > xmax )
01198                 dx = xmax - gin.pX;
01199             if ( y1 > ymax )
01200                 dy = ymax - gin.pY;
01201 
01202             QCursor::setPos( p.x() + dx, p.y() + dy );
01203             plGinInit( &gin );
01204             break;
01205         }
01206         default:
01207             locate();
01208             break;
01209         }
01210     }
01211     else
01212     {
01213         if ( event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return )
01214         {
01215             handler.DeviceChangedPage( this );
01216         }
01217         if ( event->text() == "Q" )
01218         {
01219             // Terminate on a 'Q' (not 'q', since it's too easy to hit by mistake)
01220             pls->nopause = TRUE;
01221             plexit( "" );
01222         }
01223         else if ( event->text() == "L" )
01224         // Begin locate mode
01225         {
01226             locate_mode = 2;
01227             QApplication::setOverrideCursor( Qt::CrossCursor );
01228         }
01229     }
01230 }
01231 
01232 void QtPLWidget::closeEvent( QCloseEvent* event )
01233 {
01234     handler.DeviceClosed( this );
01235     event->ignore();
01236 }
01237 
01238 void QtPLWidget::nextPage()
01239 {
01240     clearWidget();
01241     pageNumber++;
01242 }
01243 
01244 void QtPLWidget::resizeEvent( QResizeEvent * )
01245 {
01246 //     m_bAwaitingRedraw=true;
01247     redrawAll = true;
01248     delete m_pixPixmap;
01249     m_pixPixmap = NULL;
01250 }
01251 
01252 void QtPLWidget::paintEvent( QPaintEvent * )
01253 {
01254     double x_fact, y_fact, x_offset( 0. ), y_offset( 0. ); //Parameters to scale and center the plot on the widget
01255 
01256     getPlotParameters( x_fact, y_fact, x_offset, y_offset );
01257 
01258     if ( redrawAll || m_pixPixmap == NULL )
01259     {
01260         if ( m_pixPixmap != NULL )
01261         {
01262             delete m_pixPixmap;
01263         }
01264         m_pixPixmap = new QPixmap( width(), height() );
01265         QPainter* painter = new QPainter;
01266         painter->begin( m_pixPixmap );
01267 
01268         // Draw the margins and the background
01269         painter->fillRect( 0, 0, width(), height(), QBrush( Qt::white ) );
01270         painter->fillRect( 0, 0, width(), height(), QBrush( Qt::gray, Qt::Dense4Pattern ) );
01271 
01272         // Re-initialise pens etc.
01273         resetPensAndBrushes( painter );
01274 
01275         start_iterator = m_listBuffer.constBegin();
01276 
01277         // Draw the plot
01278         doPlot( painter, x_fact, y_fact, x_offset, y_offset );
01279         painter->end();
01280 
01281 //             m_iOldSize=m_listBuffer.size();
01282 
01283         delete painter;
01284     }
01285     else
01286     {
01287         QPainter* painter = new QPainter;
01288         painter->begin( m_pixPixmap );
01289         if ( hasPen )
01290             painter->setPen( SolidPen );
01291         else
01292             painter->setPen( NoPen );
01293 
01294         // Draw the plot
01295         doPlot( painter, x_fact, y_fact, x_offset, y_offset );
01296         painter->end();
01297     }
01298 
01299     // draw the current pixmap
01300     m_painterP->begin( this );
01301 
01302     m_painterP->drawPixmap( 0, 0, *m_pixPixmap );
01303 
01304     m_painterP->end();
01305 }
01306 
01307 void QtPLWidget::doPlot( QPainter* p, double x_fact, double y_fact, double x_offset, double y_offset )
01308 {
01309     QLineF         line;
01310     QVector<qreal> vect;
01311     QRectF         rect;
01312 
01313 
01314 //     QPen SolidPen;
01315 //
01316 //     QPen NoPen(Qt::NoPen);
01317 //     NoPen.setWidthF(0.); // Cosmetic pen
01318 //     p->setPen(SolidPen);
01319 //     bool hasPen=true;
01320 
01321     p->setRenderHints( QPainter::Antialiasing, (bool) lines_aa );
01322 
01323 //     QBrush SolidBrush(Qt::SolidPattern);
01324     p->setBrush( SolidBrush );
01325 
01326     QTransform trans;
01327     trans = trans.translate( x_offset, y_offset );
01328     trans = trans.scale( x_fact, y_fact );
01329 
01330     p->setTransform( trans );
01331 
01332     if ( m_listBuffer.empty() )
01333     {
01334         p->fillRect( 0, 0, 1, 1, QBrush() );
01335         return;
01336     }
01337 
01338     // unrolls the buffer and draws each element accordingly
01339     for ( QLinkedList<BufferElement>::const_iterator i = start_iterator; i != m_listBuffer.constEnd(); ++i )
01340     {
01341         switch ( i->Element )
01342         {
01343         case SET_COLOUR:
01344             SolidPen.setColor( QColor( i->Data.ColourStruct->R, i->Data.ColourStruct->G, i->Data.ColourStruct->B, i->Data.ColourStruct->A ) );
01345             if ( hasPen )
01346             {
01347                 p->setPen( SolidPen );
01348             }
01349             SolidBrush.setColor( QColor( i->Data.ColourStruct->R, i->Data.ColourStruct->G, i->Data.ColourStruct->B, i->Data.ColourStruct->A ) );
01350             p->setBrush( SolidBrush );
01351             break;
01352 
01353         case SET_GRADIENT:
01354             p->setBrush( *( i->Data.LinearGradient ) );
01355             break;
01356 
01357         case LINE:
01358             if ( !hasPen )
01359             {
01360                 p->setPen( SolidPen );
01361                 hasPen = true;
01362             }
01363             p->drawLine( *( i->Data.Line ) );
01364 
01365             break;
01366 
01367         case POLYLINE:
01368             if ( !hasPen )
01369             {
01370                 p->setPen( SolidPen );
01371                 hasPen = true;
01372             }
01373             p->drawPolyline( *( i->Data.Polyline ) );
01374             break;
01375 
01376         case RECTANGLE:
01377             p->setRenderHints( QPainter::Antialiasing, false );
01378             if ( hasPen )
01379             {
01380                 p->setPen( NoPen );
01381                 hasPen = false;
01382             }
01383             p->drawRect( *( i->Data.Rect ) );
01384             p->setRenderHints( QPainter::Antialiasing, (bool) lines_aa );
01385             break;
01386 
01387         case POLYGON:
01388             p->setRenderHints( QPainter::Antialiasing, false );
01389             if ( hasPen )
01390             {
01391                 p->setPen( NoPen );
01392                 hasPen = false;
01393             }
01394             if ( plsc->dev_eofill )
01395                 p->drawPolygon( *( i->Data.Polyline ), Qt::OddEvenFill );
01396             else
01397                 p->drawPolygon( *( i->Data.Polyline ), Qt::WindingFill );
01398             p->setRenderHints( QPainter::Antialiasing, (bool) lines_aa );
01399             break;
01400 
01401         case TEXT:
01402             if ( !hasPen )
01403             {
01404                 p->setPen( SolidPen );
01405                 hasPen = true;
01406             }
01407             p->save();
01408             p->resetTransform();
01409 
01410             renderText( p, i->Data.TextStruct, x_fact, x_offset, y_fact, y_offset );
01411             p->restore();
01412             break;
01413 
01414         case SET_WIDTH:
01415             SolidPen.setWidthF( i->Data.intParam );
01416             if ( hasPen )
01417             {
01418                 p->setPen( SolidPen );
01419             }
01420             break;
01421 
01422         case SET_BG_COLOUR:
01423             SolidBrush.setColor( QColor( i->Data.ColourStruct->R, i->Data.ColourStruct->G, i->Data.ColourStruct->B, i->Data.ColourStruct->A ) );
01424             p->fillRect( 0, 0, (int) m_dWidth, (int) m_dHeight, SolidBrush );
01425             break;
01426 
01427         case ARC:
01428             if ( !hasPen )
01429             {
01430                 p->setPen( SolidPen );
01431                 hasPen = true;
01432             }
01433             if ( i->Data.ArcStruct->rotate != 0.0 )
01434             {
01435                 p->save();
01436                 p->translate( *( i->Data.ArcStruct->dx ) );
01437                 p->rotate( -i->Data.ArcStruct->rotate );
01438                 p->translate( -*( i->Data.ArcStruct->dx ) );
01439             }
01440 
01441             if ( i->Data.ArcStruct->fill )
01442                 p->drawPie( *( i->Data.ArcStruct->rect ), i->Data.ArcStruct->startAngle, i->Data.ArcStruct->spanAngle );
01443             else
01444                 p->drawArc( *( i->Data.ArcStruct->rect ), i->Data.ArcStruct->startAngle, i->Data.ArcStruct->spanAngle );
01445 
01446             if ( i->Data.ArcStruct->rotate != 0.0 )
01447             {
01448                 p->restore();
01449             }
01450 
01451             break;
01452         default:
01453             break;
01454         }
01455     }
01456 
01457     start_iterator = m_listBuffer.constEnd();
01458     --start_iterator;
01459     redrawFromLastFlush = false;
01460     redrawAll           = false;
01461 }
01462 
01463 void QtPLWidget::getPlotParameters( double & io_dXFact, double & io_dYFact, double & io_dXOffset, double & io_dYOffset )
01464 {
01465     double w = (double) width();
01466     double h = (double) height();
01467     if ( w / h > m_dAspectRatio ) //Too wide, h is the limitating factor
01468     {
01469         io_dYFact   = h / m_dHeight;
01470         io_dXFact   = h * m_dAspectRatio / m_dWidth;
01471         io_dYOffset = 0.;
01472         io_dXOffset = ( w - io_dXFact * m_dWidth ) / 2.;
01473     }
01474     else
01475     {
01476         io_dXFact   = w / m_dWidth;
01477         io_dYFact   = w / m_dAspectRatio / m_dHeight;
01478         io_dXOffset = 0.;
01479         io_dYOffset = ( h - io_dYFact * m_dHeight ) / 2.;
01480     }
01481 }
01482 
01483 void QtPLWidget::getCursorCmd( PLGraphicsIn *ptr )
01484 {
01485     plGinInit( &gin );
01486 
01487     locate_mode = 1;
01488     QApplication::setOverrideCursor( Qt::CrossCursor );
01489 
01490     while ( gin.pX < 0 && locate_mode )
01491         QCoreApplication::processEvents( QEventLoop::AllEvents, 10 );
01492 
01493     QApplication::restoreOverrideCursor();
01494     *ptr = gin;
01495 }
01496 
01497 #endif
01498 
01499 #if defined ( PLD_extqt )
01500 QtExtWidget::QtExtWidget( int i_iWidth, int i_iHeight, QWidget* parent ) :
01501     QtPLWidget( i_iWidth, i_iHeight, parent )
01502 {
01503     cursorParameters.isTracking = false;
01504     cursorParameters.cursor_x   = -1.0;
01505     cursorParameters.cursor_y   = -1.0;
01506     killed = false;
01507 }
01508 
01509 QtExtWidget::~QtExtWidget()
01510 {
01511     killed = true;
01512     QCoreApplication::processEvents( QEventLoop::AllEvents, 10 );
01513     delete m_pixPixmap;
01514     delete m_painterP;
01515     m_pixPixmap = NULL;
01516     m_painterP  = NULL;
01517 }
01518 
01519 void QtExtWidget::captureMousePlotCoords( PLFLT* x, PLFLT* y )
01520 {
01521     setMouseTracking( true );
01522     cursorParameters.isTracking   = true;
01523     cursorParameters.cursor_x     =
01524         cursorParameters.cursor_y = -1.;
01525     do
01526     {
01527         QCoreApplication::processEvents( QEventLoop::AllEvents, 10 );
01528     } while ( cursorParameters.isTracking && !killed );
01529 
01530     *x = cursorParameters.cursor_x;
01531     *y = cursorParameters.cursor_y;
01532 }
01533 
01534 void QtExtWidget::mouseMoveEvent( QMouseEvent* event )
01535 {
01536     if ( !cursorParameters.isTracking )
01537         return;
01538 
01539     double x_fact, y_fact, x_offset, y_offset; //Parameters to scale and center the plot on the widget
01540 
01541     getPlotParameters( x_fact, y_fact, x_offset, y_offset );
01542 
01543     cursorParameters.cursor_x = (PLFLT) event->x();
01544     cursorParameters.cursor_y = (PLFLT) event->y();
01545 
01546     double ratio_x;
01547     double ratio_y;
01548     ratio_x = ( cursorParameters.cursor_x - x_offset ) / ( width() - 2. * x_offset );
01549     ratio_y = ( cursorParameters.cursor_y - y_offset ) / ( height() - 2. * y_offset );
01550 
01551     PLFLT a, b;
01552     PLINT c;
01553     plcalc_world( ratio_x, 1. - ratio_y, &a, &b, &c );
01554 
01555     if ( c < 0 )
01556     {
01557         cursorParameters.cursor_x = -1.;
01558         cursorParameters.cursor_y = -1.;
01559     }
01560 
01561     update();
01562 }
01563 
01564 void QtExtWidget::mousePressEvent( QMouseEvent* event )
01565 {
01566 }
01567 
01568 void QtExtWidget::mouseReleaseEvent( QMouseEvent* event )
01569 {
01570     if ( !cursorParameters.isTracking )
01571         return;
01572 
01573     double x_fact, y_fact, x_offset, y_offset; //Parameters to scale and center the plot on the widget
01574 
01575     getPlotParameters( x_fact, y_fact, x_offset, y_offset );
01576 
01577     cursorParameters.cursor_x   = (PLFLT) event->x();
01578     cursorParameters.cursor_y   = (PLFLT) event->y();
01579     cursorParameters.isTracking = false;
01580     setMouseTracking( false );
01581 
01582     double ratio_x;
01583     double ratio_y;
01584     ratio_x = ( cursorParameters.cursor_x - x_offset ) / ( width() - 2. * x_offset );
01585     ratio_y = ( cursorParameters.cursor_y - y_offset ) / ( height() - 2. * y_offset );
01586 
01587     PLFLT a, b;
01588     PLINT c;
01589     plcalc_world( ratio_x, 1. - ratio_y, &a, &b, &c );
01590 
01591     if ( c < 0 )
01592     {
01593         cursorParameters.cursor_x = -1.;
01594         cursorParameters.cursor_y = -1.;
01595     }
01596     else
01597     {
01598         cursorParameters.cursor_x = a;
01599         cursorParameters.cursor_y = b;
01600     }
01601 
01602     update();
01603 }
01604 
01605 void QtExtWidget::paintEvent( QPaintEvent* event )
01606 {
01607     QtPLWidget::paintEvent( event );
01608 
01609     if ( !cursorParameters.isTracking || cursorParameters.cursor_x < 0 )
01610         return;
01611 
01612     QPainter p( this );
01613 
01614     p.setPen( QPen( Qt::white ) );
01615 
01616     p.drawLine( (int) cursorParameters.cursor_x, 0, (int) cursorParameters.cursor_x, height() );
01617     p.drawLine( 0, (int) cursorParameters.cursor_y, width(), (int) cursorParameters.cursor_y );
01618 
01619     p.end();
01620 }
01621 
01622 void plsetqtdev( QtExtWidget* widget )
01623 {
01624     plsc->dev = (void *) widget;
01625     widget->setPLStream( plsc );
01626 }
01627 
01628 void plsetqtdev( QtExtWidget* widget, int argc, char** argv )
01629 {
01630     plparseopts( &argc, (const char **) argv, PL_PARSE_FULL );
01631     plsc->dev = (void *) widget;
01632     widget->setPLStream( plsc );
01633 }
01634 
01635 void plfreeqtdev()
01636 {
01637     delete ( (QtExtWidget *) plsc->dev );
01638     plsc->dev = NULL;
01639 }
01640 #endif
01641 
01642 #include "moc_files.h"

Generated on Wed Oct 12 2011 20:42:22 for PLplot by  doxygen 1.7.1