PLplot
5.10.0
|
00001 // 00002 // 00003 // This software is provided under the LGPL in March 2009 by the 00004 // Cluster Science Centre 00005 // QSAS team, 00006 // Imperial College, London 00007 // 00008 // Copyright (C) 2009 Imperial College, London 00009 // Copyright (C) 2009 Alan W. Irwin 00010 // 00011 // This is free software; you can redistribute it and/or modify 00012 // it under the terms of the GNU General Lesser Public License as published 00013 // by the Free Software Foundation; either version 2 of the License, or 00014 // (at your option) any later version. 00015 // 00016 // This software is distributed in the hope that it will be useful, 00017 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 // GNU Lesser General Public License for more details. 00020 // 00021 // To received a copy of the GNU Library General Public License 00022 // write to the Free Software Foundation, Inc., 00023 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00024 // 00025 // History: 00026 // 00027 // 00028 // March 2009: v1.00 00029 // Initial release. 00030 // 00031 // 00032 00033 // 00034 // Interpretation of the -geometry XSIZExYSIZE option (or the third and fourth 00035 // parameters of plspage if those are specified by the user instead) for 00036 // the various devices: 00037 // - the raster devices (bmpqt, jpgqt, pngqt, ppmqt, tiffqt): 00038 // XSIZE and YSIZE define the x and y size in pixels 00039 // - qtwidget: 00040 // XSIZE and YSIZE define the default x and y size of the widget in 00041 // pixels, as well as its aspect ratio, which is kept when the widget is 00042 // resized. 00043 // - svgqt, epsqt, pdfqt: 00044 // XSIZE and YSIZE define the x and y size in points (1/72 of inches). 00045 // EPS and PDF files will be drawn in A4 pages for Qt versions before 4.4 00046 // 00047 // Interpretation of the -dpi DPI option (or the first parameter of 00048 // plspage if that is specified by the user instead). 00049 // DPI is ignored for all but the raster devices. For those devices 00050 // DPI should be set to the DPI value of the monitor being used to view 00051 // the results if exact character sizes are desired. Otherwise, DEFAULT_DPI 00052 // (set to an average value for modern monitors) is used instead. 00053 // 00054 00055 #ifndef QT_H 00056 #define QT_H 00057 00058 #include <iostream> 00059 #include <QImage> 00060 #include <QPainter> 00061 #include <QLinkedList> 00062 #include <QPrinter> 00063 #include <QApplication> 00064 #include <QWidget> 00065 #include <QMouseEvent> 00066 #include <QTabWidget> 00067 #include <QMainWindow> 00068 #include <QPicture> 00069 #include <QMutex> 00070 00071 #include "plDevs.h" 00072 #include "plplotP.h" 00073 #include "drivers.h" 00074 00075 // Used for devices (epsqt, pdfqt, svgqt) with known physical size in points. 00076 #define POINTS_PER_INCH 72 00077 00078 // Average value of dots per inch assumed for modern monitors if the user 00079 // does not specify a value appropriate to their monitor with plspage or 00080 // the -dpi option. Used only for devices with size specified in pixels 00081 // but not qtwidget since it has independent access to information (e.g., 00082 // delivered by X) about the DPI of the monitor. So this value is only 00083 // used for the raster devices (bmpqt, jpgqt, pngqt, ppmqt, tiffqt). 00084 #define DEFAULT_DPI 72 00085 00086 // These values are in units of pixels (the raster devices and qtwidget) 00087 // or points (epsqt, pdfqt, svgqt). In the points case, this corresponds 00088 // to the A4 paper size. 00089 #define QT_DEFAULT_X 842 00090 #define QT_DEFAULT_Y 595 00091 00092 class QtPLDriver; 00093 00094 // Master Device Handler for multiple streams 00095 // Only handles multiple Qt devices 00096 class PLDLLIMPEXP_QT MasterHandler : public QObject 00097 { 00098 Q_OBJECT 00099 00100 public: 00101 MasterHandler(); 00102 00103 bool isMasterDevice( QtPLDriver* d ); 00104 void setMasterDevice( QtPLDriver* d ); 00105 void DeviceChangedPage( QtPLDriver* d ); 00106 void DeviceClosed( QtPLDriver* d ); 00107 00108 signals: 00109 void MasterChangedPage(); 00110 void MasterClosed(); 00111 00112 protected: 00113 QtPLDriver* masterDevice; 00114 }; 00115 00116 // Basic class, offering the common interface to all Qt plplot devices 00117 class PLDLLIMPEXP_QT QtPLDriver 00118 { 00119 public: 00120 // Constructor, taking the device size as arguments 00121 QtPLDriver( PLINT i_iWidth = QT_DEFAULT_X, PLINT i_iHeight = QT_DEFAULT_Y ); 00122 00123 virtual ~QtPLDriver(); // does not delete emitter! 00124 00125 void setPLStream( PLStream *pls ); // store the related stream 00126 00127 virtual void drawArc( short x, short y, short width, short height, PLFLT angle1, PLFLT angle2, PLFLT rotate, bool fill ); 00128 // Draws a line from (x1, y1) to (x2, y2) in internal plplot coordinates 00129 virtual void drawLine( short x1, short y1, short x2, short y2 ); 00130 virtual void drawPolyline( short * x, short * y, PLINT npts ); 00131 virtual void drawPolygon( short * x, short * y, PLINT npts ); 00132 virtual void drawText( EscText* txt ); 00133 virtual void setColor( int r, int g, int b, double alpha ); 00134 virtual void setBackgroundColor( int /* r */, int /* g */, int /* b */, double /* alpha */ ){} 00135 virtual void setGradient( int x1, int x2, int y1, int y2, 00136 unsigned char *r, unsigned char *g, 00137 unsigned char *b, PLFLT *alpha, PLINT ncol1 ); 00138 virtual void setWidthF( PLFLT w ); 00139 // Set pen to draw solid strokes (called after drawing dashed strokes) 00140 virtual void setSolid(); 00141 // Conversion factor from internal plplot coordinates to device coordinates 00142 double downscale; 00143 double m_dWidth, m_dHeight; 00144 static QMutex mutex; // All-purpose mutex 00145 00146 protected: 00147 // Returns font with the good size for a QPicture's resolution 00148 QFont getFont( PLUNICODE code ); 00149 // Draws text in a QPicture using a sub-QPicture (!), updates the current xOffset 00150 void drawTextInPicture( QPainter*, const QString& ); 00151 // Gets the QPicture displaying text, with the base chrht char height 00152 QPicture getTextPicture( PLUNICODE fci, PLUNICODE* text, int len, PLFLT chrht ); 00153 00154 // Text-related variables 00155 bool underlined; 00156 bool overlined; 00157 double currentFontScale; 00158 double currentFontSize; 00159 double yOffset; 00160 double xOffset; 00161 00162 PLStream *pls; 00163 00164 QPainter * m_painterP; 00165 }; 00166 00167 #if defined ( PLD_bmpqt ) || defined ( PLD_jpgqt ) || defined ( PLD_pngqt ) || defined ( PLD_ppmqt ) || defined ( PLD_tiffqt ) 00168 // Driver painting whatever raster format Qt can save 00169 class PLDLLIMPEXP_QT QtRasterDevice : public QtPLDriver, public QImage 00170 { 00171 public: 00172 QtRasterDevice( int i_iWidth = QT_DEFAULT_X, 00173 int i_iHeight = QT_DEFAULT_Y ); 00174 virtual ~QtRasterDevice(); 00175 00176 virtual void setBackgroundColor( int r, int g, int b, double alpha ); 00177 void definePlotName( const char* fileName, const char* format ); 00178 void savePlot(); 00179 virtual void setResolution( double dotsPerInch ) 00180 { 00181 setDotsPerMeterX( (int) ( ( dotsPerInch / 25.4 ) * 1000. ) ); 00182 setDotsPerMeterY( (int) ( ( dotsPerInch / 25.4 ) * 1000. ) ); 00183 } 00184 // used by the memqt driver 00185 unsigned char *memory; 00186 00187 protected: 00188 char format[5]; 00189 QString fileName; 00190 }; 00191 #endif 00192 00193 #if defined ( PLD_svgqt ) && QT_VERSION >= 0x040300 00194 #include <QSvgGenerator> 00195 // Driver painting on an SVG device 00196 class PLDLLIMPEXP_QT QtSVGDevice : public QtPLDriver, public QSvgGenerator 00197 { 00198 public: 00199 QtSVGDevice( int i_iWidth = QT_DEFAULT_X, 00200 int i_iHeight = QT_DEFAULT_Y ); 00201 00202 virtual ~QtSVGDevice(); 00203 00204 virtual void setBackgroundColor( int r, int g, int b, double alpha ); 00205 void definePlotName( const char* fileName ); 00206 void savePlot(); 00207 00208 protected: 00209 }; 00210 #endif 00211 00212 #if defined ( PLD_epsqt ) || defined ( PLD_pdfqt ) 00213 // Driver painting on an EPS or PDF device, uses QPrinter 00214 // A (possibly dummy) QApplication must be declared before use 00215 class PLDLLIMPEXP_QT QtEPSDevice : public QtPLDriver, public QPrinter 00216 { 00217 public: 00218 #if QT_VERSION < 0x040400 00219 QtEPSDevice( int i_iWidth = -1, int i_iHeight = -1 ); 00220 #else 00221 QtEPSDevice( int i_iWidth = QT_DEFAULT_X, int i_iHeight = QT_DEFAULT_Y ); 00222 #endif 00223 00224 virtual ~QtEPSDevice(); 00225 00226 virtual void setBackgroundColor( int r, int g, int b, double alpha ); 00227 void definePlotName( const char* fileName, int ifeps ); 00228 void savePlot(); 00229 00230 protected: 00231 }; 00232 #endif 00233 00234 #if defined ( PLD_qtwidget ) || defined ( PLD_extqt ) 00235 00236 typedef enum ElementType_ 00237 { 00238 LINE, 00239 POLYLINE, 00240 POLYGON, 00241 RECTANGLE, 00242 SET_WIDTH, 00243 SET_COLOUR, 00244 SET_GRADIENT, 00245 SET_SMOOTH, 00246 TEXT, 00247 SET_BG_COLOUR, 00248 ARC 00249 } ElementType; // Identifiers for elements of the buffer 00250 00251 struct ColourStruct_ 00252 { 00253 PLINT R, G, B, A; 00254 }; 00255 00256 struct TextStruct_ 00257 { 00258 PLFLT x; 00259 PLFLT y; 00260 PLFLT clipxmin; 00261 PLFLT clipymin; 00262 PLFLT clipxmax; 00263 PLFLT clipymax; 00264 PLFLT rotation; 00265 PLFLT shear; 00266 PLFLT stride; 00267 PLFLT just; 00268 PLUNICODE * text; 00269 PLUNICODE fci; 00270 PLINT len; 00271 PLFLT chrht; 00272 }; 00273 00274 struct ArcStruct_ 00275 { 00276 QRectF *rect; 00277 QPointF *dx; 00278 int startAngle; 00279 int spanAngle; 00280 PLFLT rotate; 00281 bool fill; 00282 }; 00283 00284 class BufferElement 00285 { 00286 public: 00287 ElementType Element; 00288 00289 union DataType 00290 { 00291 QLineF * Line; 00292 QPolygonF * Polyline; 00293 QRectF * Rect; 00294 QLinearGradient * LinearGradient; 00295 struct ColourStruct_* ColourStruct; 00296 struct TextStruct_ * TextStruct; 00297 struct ArcStruct_ * ArcStruct; 00298 PLINT intParam; 00299 PLFLT fltParam; 00300 } Data; 00301 }; 00302 00303 // This widget allows to use plplot as a plotting engine in a Qt Application 00304 // The aspect ratio of the plotted data is constant, so gray strips are used 00305 // to delimit the page when the widget aspect ratio is not the one of the plotted page 00306 class PLDLLIMPEXP_QT QtPLWidget : public QWidget, public QtPLDriver 00307 { 00308 Q_OBJECT 00309 00310 public: 00311 // Parameters are the actual size of the page, NOT the size of the widget 00312 // Call QWidget::resize for that 00313 QtPLWidget( int i_iWidth = QT_DEFAULT_X, int i_iHeight = QT_DEFAULT_Y, QWidget * parent = 0 ); 00314 00315 virtual ~QtPLWidget(); 00316 00317 void clearWidget(); 00318 void clearBuffer(); 00319 00320 int pageNumber; 00321 00322 void drawArc( short x, short y, short width, short height, PLFLT angle1, PLFLT angle2, PLFLT rotate, bool fill ); 00323 void drawLine( short x1, short y1, short x2, short y2 ); 00324 void drawPolyline( short * x, short * y, PLINT npts ); 00325 void drawPolygon( short * x, short * y, PLINT npts ); 00326 void setColor( int r, int g, int b, double alpha ); 00327 void setBackgroundColor( int r, int g, int b, double alpha ); 00328 void setGradient( int x1, int x2, int y1, int y2, 00329 unsigned char *r, unsigned char *g, 00330 unsigned char *b, PLFLT *alpha, PLINT ncol1 ); 00331 void setWidthF( PLFLT r ); 00332 void drawText( EscText* txt ); 00333 void flush(); 00334 void getCursorCmd( PLGraphicsIn *ptr ); 00335 00336 protected: 00337 00338 void resizeEvent( QResizeEvent* ); 00339 void paintEvent( QPaintEvent* ); 00340 void mouseEvent( QMouseEvent * event ); 00341 00342 void getPlotParameters( double & io_dXFact, double & io_dYFact, double & io_dXOffset, double & io_dYOffset ); // gives the parameters to scale and center the plot on the page 00343 void doPlot( QPainter* p, double x_fact, double y_fact, double x_offset, double y_offset ); // Actually draws the plot. Deported in a function for readability 00344 void renderText( QPainter* p, struct TextStruct_* s, double x_fact, double x_offset, double y_fact, double y_offset ); 00345 void lookupButtonEvent( QMouseEvent * event ); 00346 void locate(); 00347 00348 void resetPensAndBrushes( QPainter* ); 00349 00350 double m_dAspectRatio; // Is kept constant during resizes 00351 QPixmap * m_pixPixmap; // stores the drawn image as long as it does not have to be regenerated 00352 00353 QLinkedList<BufferElement> m_listBuffer; // Buffer holding the draw instructions 00354 // bool m_bAwaitingRedraw; 00355 // int m_iOldSize; // Holds the size of the buffer. Modified => image has to be redrawn 00356 bool redrawFromLastFlush; 00357 bool redrawAll; 00358 00359 // Pens and brushes required to maintain the status between 2 flushes 00360 QPen SolidPen; 00361 QPen NoPen; 00362 bool hasPen; 00363 QBrush SolidBrush; 00364 // end parameters 00365 00366 QLinkedList<BufferElement>::const_iterator start_iterator; 00367 00368 struct 00369 { 00370 int r; 00371 int g; 00372 int b; 00373 double alpha; 00374 } lastColour; 00375 00376 struct 00377 { 00378 int r; 00379 int g; 00380 int b; 00381 double alpha; 00382 } bgColour; 00383 00384 PLGraphicsIn gin; // Graphics Input Structure 00385 int locate_mode; // Set while in locate mode 00386 00387 protected slots: 00388 void mousePressEvent( QMouseEvent * event ); 00389 void mouseReleaseEvent( QMouseEvent * event ); 00390 void mouseMoveEvent( QMouseEvent * event ); 00391 void keyPressEvent( QKeyEvent* event ); 00392 void closeEvent( QCloseEvent* event ); 00393 void nextPage(); 00394 }; 00395 00396 #endif 00397 00398 #if defined ( PLD_extqt ) 00399 class PLDLLIMPEXP_QT QtExtWidget : public QtPLWidget 00400 { 00401 Q_OBJECT 00402 00403 public: 00404 QtExtWidget( int i_iWidth = QT_DEFAULT_X, int i_iHeight = QT_DEFAULT_Y, QWidget * parent = 0 ); 00405 00406 virtual ~QtExtWidget(); 00407 00408 void captureMousePlotCoords( PLFLT* x, PLFLT* y ); 00409 00410 public slots: 00411 00412 void mouseMoveEvent( QMouseEvent* event ); 00413 void mouseReleaseEvent( QMouseEvent* event ); 00414 void mousePressEvent( QMouseEvent* event ); 00415 00416 protected: 00417 void paintEvent( QPaintEvent* ); 00418 00419 struct 00420 { 00421 bool isTracking; 00422 double cursor_x, cursor_y; 00423 } cursorParameters; 00424 00425 bool killed; 00426 }; 00427 00428 PLDLLIMPEXP_QT void plsetqtdev( QtExtWidget* widget ); // Registers the widget as plot device, as the widget has to be created in the Qt application GUI, prior to any plplot call. Must be called before plinit(). 00429 00430 PLDLLIMPEXP_QT void plsetqtdev( QtExtWidget* widget, int argc, char** argv ); // Registers the widget as plot device, as the widget has to be created in the Qt application GUI, prior to any plplot call. Must be called before plinit(). 00431 00432 PLDLLIMPEXP_QT void plfreeqtdev(); // Deletes and unregisters the device. 00433 00434 #endif 00435 00436 // These variables are declared in plqt.cpp but also needed 00437 // by the qt driver. 00438 extern PLDLLIMPEXP_QT_DATA( int ) vectorize; 00439 extern PLDLLIMPEXP_QT_DATA( int ) lines_aa; 00440 extern PLDLLIMPEXP_QT_DATA( MasterHandler ) handler; 00441 00442 #if defined ( plplot_pyqt4_EXPORTS ) 00443 #define initplplot_pyqt4 PLDLLIMPEXP_PYQT4 initplplot_pyqt4 00444 #endif 00445 00446 #endif