1 //
2 //
3 // This software is provided under the LGPL in March 2009 by the
4 // Cluster Science Centre
5 // QSAS team,
6 // Imperial College, London
7 //
8 // Copyright (C) 2009 Imperial College, London
9 // Copyright (C) 2009-2019 Alan W. Irwin
10 // Copyright (C) 2009 Werner Smekal
11 // Copyright (C) 2009-2012 Andrew Ross
12 // Copyright (C) 2009-2011 Hazen Babcock
13 // Copyright (C) 2010 Hezekiah M. Carty
14 // Copyright (C) 2015 Jim Dishaw
15 // Copyright (C) 2019 António R. Tomé
16 //
17 // This is free software; you can redistribute it and/or modify
18 // it under the terms of the GNU General Lesser Public License as published
19 // by the Free Software Foundation; either version 2 of the License, or
20 // (at your option) any later version.
21 //
22 // This software is distributed in the hope that it will be useful,
23 // but WITHOUT ANY WARRANTY; without even the implied warranty of
24 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25 // GNU Lesser General Public License for more details.
26 //
27 // To received a copy of the GNU Library General Public License
28 // write to the Free Software Foundation, Inc.,
29 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
30 //
31 // History:
32 //
33 //
34 // March 2009:  v1.00
35 // Initial release.
36 //
37 //
38 
39 
40 #include "qt.h"
41 #include <QMutexLocker>
42 
43 // Global variables used in initQtApp (which is called by all
44 // plD_init_* routines other than plD_init_extqt) and used in
45 // closeQtApp (which is called by all plD_tidy_* routines other than
46 // plD_tidy_extqt).  The use of these global variables is kept thread-safe by
47 // a QMutexLocker used by both initQtApp and closeQtApp.
48 static int  argc;
49 static char **argv;
50 static int  internal_qAppCounter = 0;
51 static bool internal_qApp        = false;
52 
53 // Drivers declaration
54 extern "C" {
55 PLDLLIMPEXP_DRIVER_DATA( const char* ) plD_DEVICE_INFO_qt =
56 #if defined ( PLD_bmpqt )
57     "bmpqt:Qt Windows bitmap driver:0:qt:66:bmpqt\n"
58 #endif
59 #if defined ( PLD_jpgqt )
60     "jpgqt:Qt jpg driver:0:qt:67:jpgqt\n"
61 #endif
62 #if defined ( PLD_pngqt )
63     "pngqt:Qt png driver:0:qt:68:pngqt\n"
64 #endif
65 #if defined ( PLD_ppmqt )
66     "ppmqt:Qt ppm driver:0:qt:69:ppmqt\n"
67 #endif
68 #if defined ( PLD_tiffqt )
69     "tiffqt:Qt tiff driver:0:qt:70:tiffqt\n"
70 #endif
71 #if defined ( PLD_svgqt ) && QT_VERSION >= 0x040300
72     "svgqt:Qt SVG driver:0:qt:71:svgqt\n"
73 #endif
74 #if defined ( PLD_qtwidget )
75     "qtwidget:Qt Widget:1:qt:72:qtwidget\n"
76 #endif
77 #if defined ( PLD_epsqt )
78     "epsqt:Qt EPS driver:0:qt:73:epsqt\n"
79 #endif
80 #if defined ( PLD_pdfqt )
81     "pdfqt:Qt PDF driver:0:qt:74:pdfqt\n"
82 #endif
83 #if defined ( PLD_extqt )
84     "extqt:External Qt driver:0:qt:75:extqt\n"
85 #endif
86 #if defined ( PLD_memqt )
87     "memqt:Memory Qt driver:0:qt:76:memqt\n"
88 #endif
89 ;
90 }  // extern "C"
91 
92 static DrvOpt qt_options[] = { { "text_vectorize",     DRV_INT, &vectorize, "Vectorize fonts on output (0|1)"     },
93                                { "lines_antialiasing", DRV_INT, &lines_aa,  "Toggles antialiasing on lines (0|1)" },
94                                { NULL,                 DRV_INT, NULL,       NULL                                  } };
95 
96 // The purpose of this routine is to create an internal qApp and the argc and argv data
97 // that qApp needs if an external or internal qApp does not exist already.
98 
initQtApp(bool isGUI)99 bool initQtApp( bool isGUI )
100 {
101     QMutexLocker locker( &QtPLDriver::mutex );
102     bool         res = false;
103 
104     if ( qApp == NULL && internal_qAppCounter == 0 )
105     {
106         internal_qApp = true;
107         argc          = 1;
108         argv          = new char*[2];
109         argv[0]       = new char[10];
110         argv[1]       = new char[1];
111         snprintf( argv[0], 10, "qt_driver" );
112         argv[1][0] = '\0';
113 #ifdef Q_WS_X11
114         // On X11 if DISPLAY is not set then cannot open GUI. This allows non-interactive devices to still work in this case.
115         if ( getenv( "DISPLAY" ) == NULL )
116             isGUI = false;
117 #endif
118         new QApplication( argc, argv, isGUI );
119         res = true;
120     }
121 
122     // Keep track of the number of uses of the internal qApp.
123     if ( internal_qApp )
124         ++internal_qAppCounter;
125 
126     return res;
127 }
128 
129 // The purpose of this routine is to delete qApp and associated argv
130 // if those were created internally by initQtApp and if it is the last
131 // use (kept track of by internal_qAppCounter) of that qApp.
closeQtApp()132 void closeQtApp()
133 {
134     QMutexLocker locker( &QtPLDriver::mutex );
135     if ( internal_qApp )
136     {
137         --internal_qAppCounter;
138         if ( qApp != NULL && internal_qAppCounter == 0 )
139         {
140             delete qApp;
141             delete[] argv[0];
142             delete[] argv[1];
143             delete[] argv;
144             argv = NULL;
145         }
146     }
147 }
148 
149 //--------------------------------------------------------------------------
150 // qt_family_check ()
151 //
152 // support function to help supress more than one page if family file
153 // output not specified by the user  (e.g., with the -fam command-line option).
154 // Adapted directly from svg.c
155 //--------------------------------------------------------------------------
156 static int already_warned = 0;
qt_family_check(PLStream * pls)157 static int qt_family_check( PLStream *pls )
158 {
159     if ( pls->family || pls->page == 1 )
160     {
161         return 0;
162     }
163     else
164     {
165         if ( !already_warned )
166         {
167             already_warned = 1;
168             plwarn( "All pages after the first skipped because family file output not specified.\n" );
169         }
170         return 1;
171     }
172 }
173 
174 // Declaration of the driver-specific interface functions
175 #if defined ( PLD_bmpqt ) || defined ( PLD_jpgqt ) || defined ( PLD_pngqt ) || defined ( PLD_ppmqt ) || defined ( PLD_tiffqt ) || defined ( PLD_memqt )
176 void plD_init_rasterqt( PLStream * );
177 void plD_eop_rasterqt( PLStream * );
178 void plD_line_rasterqt( PLStream *, short, short, short, short );
179 void plD_polyline_rasterqt( PLStream *, short*, short*, PLINT );
180 void plD_tidy_rasterqt( PLStream * );
181 void plD_state_rasterqt( PLStream *, PLINT );
182 void plD_esc_rasterqt( PLStream *, PLINT, void* );
183 #endif
184 
185 #if defined ( PLD_bmpqt )
186 void plD_dispatch_init_bmpqt( PLDispatchTable *pdt );
187 void plD_bop_bmpqt( PLStream * );
188 #endif
189 
190 #if defined ( PLD_jpgqt )
191 void plD_dispatch_init_jpgqt( PLDispatchTable *pdt );
192 void plD_bop_jpgqt( PLStream * );
193 #endif
194 
195 #if defined ( PLD_pngqt )
196 void plD_dispatch_init_pngqt( PLDispatchTable *pdt );
197 void plD_bop_pngqt( PLStream * );
198 #endif
199 
200 #if defined ( PLD_ppmqt )
201 void plD_dispatch_init_ppmqt( PLDispatchTable *pdt );
202 void plD_bop_ppmqt( PLStream * );
203 #endif
204 
205 #if defined ( PLD_tiffqt )
206 void plD_dispatch_init_tiffqt( PLDispatchTable *pdt );
207 void plD_bop_tiffqt( PLStream * );
208 #endif
209 
210 #if defined ( PLD_svgqt ) && QT_VERSION >= 0x040300
211 void plD_dispatch_init_svgqt( PLDispatchTable *pdt );
212 void plD_init_svgqt( PLStream * );
213 void plD_bop_svgqt( PLStream * );
214 void plD_eop_svgqt( PLStream * );
215 void plD_line_svgqt( PLStream *, short, short, short, short );
216 void plD_polyline_svgqt( PLStream *, short*, short*, PLINT );
217 void plD_tidy_svgqt( PLStream * );
218 void plD_state_svgqt( PLStream *, PLINT );
219 void plD_esc_svgqt( PLStream *, PLINT, void* );
220 #endif
221 
222 #if defined ( PLD_epsqt ) || defined ( PLD_pdfqt )
223 void plD_init_epspdfqt( PLStream * );
224 void plD_bop_epspdfqt_helper( PLStream *, int ifeps );
225 void plD_eop_epspdfqt( PLStream * );
226 void plD_line_epspdfqt( PLStream *, short, short, short, short );
227 void plD_polyline_epspdfqt( PLStream *, short*, short*, PLINT );
228 void plD_tidy_epspdfqt( PLStream * );
229 void plD_state_epspdfqt( PLStream *, PLINT );
230 void plD_esc_epspdfqt( PLStream *, PLINT, void* );
231 #endif
232 #if defined ( PLD_epsqt )
233 void plD_dispatch_init_epsqt( PLDispatchTable *pdt );
234 void plD_bop_epsqt( PLStream * );
235 #endif
236 #if defined ( PLD_pdfqt )
237 void plD_dispatch_init_pdfqt( PLDispatchTable *pdt );
238 void plD_bop_pdfqt( PLStream * );
239 #endif
240 
241 #if defined ( PLD_qtwidget )
242 void plD_dispatch_init_qtwidget( PLDispatchTable *pdt );
243 void plD_init_qtwidget( PLStream * );
244 void plD_eop_qtwidget( PLStream * );
245 void plD_wait_qtwidget( PLStream * );
246 void plD_line_qtwidget( PLStream *, short, short, short, short );
247 void plD_polyline_qtwidget( PLStream *, short*, short*, PLINT );
248 void plD_tidy_qtwidget( PLStream * );
249 void plD_state_qtwidget( PLStream *, PLINT );
250 void plD_esc_qtwidget( PLStream *, PLINT, void* );
251 void plD_bop_qtwidget( PLStream * );
252 #endif
253 
254 #if defined ( PLD_extqt )
255 void plD_dispatch_init_extqt( PLDispatchTable *pdt );
256 void plD_init_extqt( PLStream * );
257 void plD_eop_extqt( PLStream * );
258 void plD_line_extqt( PLStream *, short, short, short, short );
259 void plD_polyline_extqt( PLStream *, short*, short*, PLINT );
260 void plD_tidy_extqt( PLStream * );
261 void plD_state_extqt( PLStream *, PLINT );
262 void plD_esc_extqt( PLStream *, PLINT, void* );
263 void plD_bop_extqt( PLStream * );
264 #endif
265 
266 #if defined ( PLD_memqt )
267 void plD_dispatch_init_memqt( PLDispatchTable *pdt );
268 void plD_init_memqt( PLStream * );
269 void plD_bop_memqt( PLStream * );
270 void plD_eop_memqt( PLStream * );
271 #endif
272 
273 ////////////////// Raster driver-specific definitions: class and interface functions /////////
274 #if defined ( PLD_bmpqt ) || defined ( PLD_jpgqt ) || defined ( PLD_pngqt ) || defined ( PLD_ppmqt ) || defined ( PLD_tiffqt ) || defined ( PLD_memqt )
plD_init_rasterqt(PLStream * pls)275 void plD_init_rasterqt( PLStream * pls )
276 {
277     double dpi;
278 
279     vectorize = 0;
280     lines_aa  = 1;
281     plParseDrvOpts( qt_options );
282 
283     // Stream setup
284     pls->color        = 1;
285     pls->plbuf_write  = 0;
286     pls->dev_fill0    = 1;
287     pls->dev_fill1    = 0;
288     pls->dev_gradient = 1;      // driver renders gradient
289     // Let the PLplot core handle dashed lines since
290     // the driver results for this capability have a number of issues.
291     // pls->dev_dash=1;
292     pls->dev_dash  = 0;
293     pls->dev_flush = 1;
294     // Driver does not have a clear capability so use (good) PLplot core
295     // fallback for that instead.
296     pls->dev_clear         = 0;
297     pls->termin            = 0;
298     pls->page              = 0;
299     pls->dev_text          = 1; // want to draw text
300     pls->dev_unicode       = 1; // want unicode
301     pls->has_string_length = 1; // Driver supports string length calculations
302 
303     // Needs to be true only because of multi-stream case
304     bool isMaster = initQtApp( true );
305 
306     if ( pls->xdpi <= 0. )
307         dpi = DEFAULT_DPI;
308     else
309         dpi = pls->xdpi;
310 
311     // Shamelessly copied on the Cairo stuff :)
312     if ( pls->xlength <= 0 || pls->ylength <= 0 )
313     {
314         pls->dev     = new QtRasterDevice;
315         pls->xlength = (PLINT) ( ( (QtRasterDevice *) ( pls->dev ) )->m_dWidth );
316         pls->ylength = (PLINT) ( ( (QtRasterDevice *) ( pls->dev ) )->m_dHeight );
317     }
318     else
319     {
320         pls->dev = new QtRasterDevice( pls->xlength, pls->ylength );
321     }
322     ( (QtRasterDevice *) pls->dev )->setPLStream( pls );
323 
324     if ( isMaster )
325         handler.setMasterDevice( (QtRasterDevice *) ( pls->dev ) );
326 
327     if ( pls->xlength > pls->ylength )
328         ( (QtRasterDevice *) ( pls->dev ) )->downscale = (PLFLT) pls->xlength / (PLFLT) ( PIXELS_X - 1 );
329     else
330         ( (QtRasterDevice *) ( pls->dev ) )->downscale = (PLFLT) pls->ylength / (PLFLT) PIXELS_Y;
331 
332     plP_setphy( (PLINT) 0, (PLINT) ( pls->xlength / ( (QtRasterDevice *) ( pls->dev ) )->downscale ), (PLINT) 0, (PLINT) ( pls->ylength / ( (QtRasterDevice *) ( pls->dev ) )->downscale ) );
333 
334     plP_setpxl( dpi / 25.4 / ( (QtRasterDevice *) ( pls->dev ) )->downscale, dpi / 25.4 / ( (QtRasterDevice *) ( pls->dev ) )->downscale );
335 
336     ( (QtRasterDevice *) ( pls->dev ) )->setResolution( dpi );
337 
338     // Initialize family file info
339     plFamInit( pls );
340 
341     plOpenFile( pls );
342 }
343 
plD_eop_rasterqt(PLStream * pls)344 void plD_eop_rasterqt( PLStream *pls )
345 {
346     if ( qt_family_check( pls ) )
347     {
348         return;
349     }
350     ( (QtRasterDevice *) pls->dev )->savePlot();
351     handler.DeviceChangedPage( (QtRasterDevice *) pls->dev );
352 }
353 
plD_line_rasterqt(PLStream * pls,short x1a,short y1a,short x2a,short y2a)354 void plD_line_rasterqt( PLStream * pls, short x1a, short y1a, short x2a, short y2a )
355 {
356     QtRasterDevice* widget = (QtRasterDevice *) pls->dev;
357 
358     if ( widget != NULL && qt_family_check( pls ) )
359     {
360         return;
361     }
362     if ( widget == NULL )
363         return;
364 
365     widget->QtPLDriver::setColor( pls->curcolor.r, pls->curcolor.g, pls->curcolor.b, pls->curcolor.a );
366     widget->drawLine( x1a, y1a, x2a, y2a );
367 }
368 
plD_polyline_rasterqt(PLStream * pls,short * xa,short * ya,PLINT npts)369 void plD_polyline_rasterqt( PLStream *pls, short *xa, short *ya, PLINT npts )
370 {
371     QtRasterDevice * widget = (QtRasterDevice *) pls->dev;
372 
373     if ( widget != NULL && qt_family_check( pls ) )
374     {
375         return;
376     }
377     if ( widget == NULL )
378         return;
379 
380     widget->QtPLDriver::setColor( pls->curcolor.r, pls->curcolor.g, pls->curcolor.b, pls->curcolor.a );
381     widget->drawPolyline( xa, ya, npts );
382 }
383 
plD_esc_rasterqt(PLStream * pls,PLINT op,void * ptr)384 void plD_esc_rasterqt( PLStream * pls, PLINT op, void* ptr )
385 {
386     short          *xa, *ya;
387     unsigned char  *r, *g, *b;
388     PLFLT          *alpha;
389     PLINT          i;
390     QtRasterDevice * widget = (QtRasterDevice *) pls->dev;
391     if ( widget != NULL && qt_family_check( pls ) )
392     {
393         return;
394     }
395     if ( widget == NULL )
396         return;
397 
398     switch ( op )
399     {
400     //     case PLESC_DASH:
401     //       widget->setDashed(pls->nms, pls->mark, pls->space);
402     //       widget->QtPLDriver::setColor(pls->curcolor.r, pls->curcolor.g, pls->curcolor.b, pls->curcolor.a);
403     //       widget->drawPolyline(pls->dev_x, pls->dev_y, pls->dev_npts);
404     //       widget->setSolid();
405     //       break;
406 
407     case PLESC_FILL:
408         xa = new short[pls->dev_npts];
409         ya = new short[pls->dev_npts];
410 
411         for ( i = 0; i < pls->dev_npts; i++ )
412         {
413             xa[i] = pls->dev_x[i];
414             ya[i] = pls->dev_y[i];
415         }
416         widget->QtPLDriver::setColor( pls->curcolor.r, pls->curcolor.g, pls->curcolor.b, pls->curcolor.a );
417         widget->drawPolygon( xa, ya, pls->dev_npts );
418 
419         delete[] xa;
420         delete[] ya;
421         break;
422 
423     case PLESC_GRADIENT:
424         xa    = new short[pls->dev_npts];
425         ya    = new short[pls->dev_npts];
426         r     = new unsigned char[pls->ncol1];
427         g     = new unsigned char[pls->ncol1];
428         b     = new unsigned char[pls->ncol1];
429         alpha = new PLFLT[pls->ncol1];
430 
431         for ( i = 0; i < pls->ncol1; i++ )
432         {
433             r[i]     = pls->cmap1[i].r;
434             g[i]     = pls->cmap1[i].g;
435             b[i]     = pls->cmap1[i].b;
436             alpha[i] = pls->cmap1[i].a;
437         }
438         widget->setGradient( pls->xgradient[0], pls->xgradient[1], pls->ygradient[0], pls->ygradient[1], r, g, b, alpha, pls->ncol1 );
439 
440         for ( i = 0; i < pls->dev_npts; i++ )
441         {
442             xa[i] = pls->dev_x[i];
443             ya[i] = pls->dev_y[i];
444         }
445         widget->drawPolygon( xa, ya, pls->dev_npts );
446 
447         delete[] xa;
448         delete[] ya;
449         delete[] r;
450         delete[] g;
451         delete[] b;
452         delete[] alpha;
453         break;
454 
455     case PLESC_HAS_TEXT:
456         //  call the generic ProcessString function
457         //  ProcessString( pls, (EscText *)ptr );
458         widget->QtPLDriver::setColor( pls->curcolor.r, pls->curcolor.g, pls->curcolor.b, pls->curcolor.a );
459         widget->drawText( (EscText *) ptr );
460         break;
461 
462     default: break;
463     }
464 }
465 
plD_state_rasterqt(PLStream * pls,PLINT op)466 void plD_state_rasterqt( PLStream * pls, PLINT op )
467 {
468     QtRasterDevice * widget = (QtRasterDevice *) pls->dev;
469     if ( widget != NULL && qt_family_check( pls ) )
470     {
471         return;
472     }
473     if ( widget == NULL )
474         return;
475 
476     switch ( op )
477     {
478     case PLSTATE_WIDTH:
479         widget->setWidthF( pls->width );
480         break;
481 
482     case PLSTATE_COLOR0:
483         ( (QtPLDriver *) widget )->QtPLDriver::setColor( pls->curcolor.r, pls->curcolor.g, pls->curcolor.b, pls->curcolor.a );
484         break;
485 
486     case PLSTATE_COLOR1:
487         ( (QtPLDriver *) widget )->QtPLDriver::setColor( pls->curcolor.r, pls->curcolor.g, pls->curcolor.b, pls->curcolor.a );
488         break;
489 
490 
491     default: break;
492     }
493 }
494 
plD_tidy_rasterqt(PLStream * pls)495 void plD_tidy_rasterqt( PLStream * pls )
496 {
497     QtRasterDevice * widget = (QtRasterDevice *) pls->dev;
498 
499     if ( widget != NULL )
500     {
501         handler.DeviceClosed( widget );
502         delete widget;
503         pls->dev = NULL;
504     }
505     plCloseFile( pls );
506 
507     closeQtApp();
508 }
509 #endif
510 
511 #if defined ( PLD_bmpqt )
plD_dispatch_init_bmpqt(PLDispatchTable * pdt)512 void plD_dispatch_init_bmpqt( PLDispatchTable *pdt )
513 {
514 #ifndef ENABLE_DYNDRIVERS
515     pdt->pl_MenuStr = "Qt Windows bitmap Driver";
516     pdt->pl_DevName = "bmpqt";
517 #endif
518     pdt->pl_type     = plDevType_FileOriented;
519     pdt->pl_seq      = 66;
520     pdt->pl_init     = (plD_init_fp) plD_init_rasterqt;
521     pdt->pl_line     = (plD_line_fp) plD_line_rasterqt;
522     pdt->pl_polyline = (plD_polyline_fp) plD_polyline_rasterqt;
523     pdt->pl_eop      = (plD_eop_fp) plD_eop_rasterqt;
524     pdt->pl_bop      = (plD_bop_fp) plD_bop_bmpqt;
525     pdt->pl_tidy     = (plD_tidy_fp) plD_tidy_rasterqt;
526     pdt->pl_state    = (plD_state_fp) plD_state_rasterqt;
527     pdt->pl_esc      = (plD_esc_fp) plD_esc_rasterqt;
528 }
529 
plD_bop_bmpqt(PLStream * pls)530 void plD_bop_bmpqt( PLStream *pls )
531 {
532     // Plot familying stuff. Not really understood, just copying gd.c
533     plGetFam( pls );
534 
535     pls->famadv = 1;
536     pls->page++;
537     if ( qt_family_check( pls ) )
538     {
539         return;
540     }
541     ( (QtRasterDevice *) pls->dev )->definePlotName( pls->FileName, "BMP" );
542     ( (QtRasterDevice *) pls->dev )->setBackgroundColor( pls->cmap0[0].r, pls->cmap0[0].g, pls->cmap0[0].b, pls->cmap0[0].a );
543 }
544 #endif
545 
546 #if defined ( PLD_jpgqt )
plD_dispatch_init_jpgqt(PLDispatchTable * pdt)547 void plD_dispatch_init_jpgqt( PLDispatchTable *pdt )
548 {
549 #ifndef ENABLE_DYNDRIVERS
550     pdt->pl_MenuStr = "Qt jpg Driver";
551     pdt->pl_DevName = "jpgqt";
552 #endif
553     pdt->pl_type     = plDevType_FileOriented;
554     pdt->pl_seq      = 67;
555     pdt->pl_init     = (plD_init_fp) plD_init_rasterqt;
556     pdt->pl_line     = (plD_line_fp) plD_line_rasterqt;
557     pdt->pl_polyline = (plD_polyline_fp) plD_polyline_rasterqt;
558     pdt->pl_eop      = (plD_eop_fp) plD_eop_rasterqt;
559     pdt->pl_bop      = (plD_bop_fp) plD_bop_jpgqt;
560     pdt->pl_tidy     = (plD_tidy_fp) plD_tidy_rasterqt;
561     pdt->pl_state    = (plD_state_fp) plD_state_rasterqt;
562     pdt->pl_esc      = (plD_esc_fp) plD_esc_rasterqt;
563 }
564 
plD_bop_jpgqt(PLStream * pls)565 void plD_bop_jpgqt( PLStream *pls )
566 {
567     // Plot familying stuff. Not really understood, just copying gd.c
568     plGetFam( pls );
569 
570     pls->famadv = 1;
571     pls->page++;
572     if ( qt_family_check( pls ) )
573     {
574         return;
575     }
576     ( (QtRasterDevice *) pls->dev )->definePlotName( pls->FileName, "JPG" );
577     ( (QtRasterDevice *) pls->dev )->setBackgroundColor( pls->cmap0[0].r, pls->cmap0[0].g, pls->cmap0[0].b, pls->cmap0[0].a );
578 }
579 #endif
580 
581 #if defined ( PLD_pngqt )
plD_dispatch_init_pngqt(PLDispatchTable * pdt)582 void plD_dispatch_init_pngqt( PLDispatchTable *pdt )
583 {
584 #ifndef ENABLE_DYNDRIVERS
585     pdt->pl_MenuStr = "Qt png Driver";
586     pdt->pl_DevName = "pngqt";
587 #endif
588     pdt->pl_type     = plDevType_FileOriented;
589     pdt->pl_seq      = 68;
590     pdt->pl_init     = (plD_init_fp) plD_init_rasterqt;
591     pdt->pl_line     = (plD_line_fp) plD_line_rasterqt;
592     pdt->pl_polyline = (plD_polyline_fp) plD_polyline_rasterqt;
593     pdt->pl_eop      = (plD_eop_fp) plD_eop_rasterqt;
594     pdt->pl_bop      = (plD_bop_fp) plD_bop_pngqt;
595     pdt->pl_tidy     = (plD_tidy_fp) plD_tidy_rasterqt;
596     pdt->pl_state    = (plD_state_fp) plD_state_rasterqt;
597     pdt->pl_esc      = (plD_esc_fp) plD_esc_rasterqt;
598 }
599 
plD_bop_pngqt(PLStream * pls)600 void plD_bop_pngqt( PLStream *pls )
601 {
602     // Plot familying stuff. Not really understood, just copying gd.c
603     plGetFam( pls );
604 
605     pls->famadv = 1;
606     pls->page++;
607     if ( qt_family_check( pls ) )
608     {
609         return;
610     }
611     ( (QtRasterDevice *) pls->dev )->definePlotName( pls->FileName, "PNG" );
612     ( (QtRasterDevice *) pls->dev )->setBackgroundColor( pls->cmap0[0].r, pls->cmap0[0].g, pls->cmap0[0].b, pls->cmap0[0].a );
613 }
614 #endif
615 
616 #if defined ( PLD_ppmqt )
plD_dispatch_init_ppmqt(PLDispatchTable * pdt)617 void plD_dispatch_init_ppmqt( PLDispatchTable *pdt )
618 {
619 #ifndef ENABLE_DYNDRIVERS
620     pdt->pl_MenuStr = "Qt ppm Driver";
621     pdt->pl_DevName = "ppmqt";
622 #endif
623     pdt->pl_type     = plDevType_FileOriented;
624     pdt->pl_seq      = 69;
625     pdt->pl_init     = (plD_init_fp) plD_init_rasterqt;
626     pdt->pl_line     = (plD_line_fp) plD_line_rasterqt;
627     pdt->pl_polyline = (plD_polyline_fp) plD_polyline_rasterqt;
628     pdt->pl_eop      = (plD_eop_fp) plD_eop_rasterqt;
629     pdt->pl_bop      = (plD_bop_fp) plD_bop_ppmqt;
630     pdt->pl_tidy     = (plD_tidy_fp) plD_tidy_rasterqt;
631     pdt->pl_state    = (plD_state_fp) plD_state_rasterqt;
632     pdt->pl_esc      = (plD_esc_fp) plD_esc_rasterqt;
633 }
634 
plD_bop_ppmqt(PLStream * pls)635 void plD_bop_ppmqt( PLStream *pls )
636 {
637     // Plot familying stuff. Not really understood, just copying gd.c
638     plGetFam( pls );
639 
640     pls->famadv = 1;
641     pls->page++;
642     if ( qt_family_check( pls ) )
643     {
644         return;
645     }
646     ( (QtRasterDevice *) pls->dev )->definePlotName( pls->FileName, "PPM" );
647     ( (QtRasterDevice *) pls->dev )->setBackgroundColor( pls->cmap0[0].r, pls->cmap0[0].g, pls->cmap0[0].b, pls->cmap0[0].a );
648 }
649 #endif
650 
651 #if defined ( PLD_tiffqt )
plD_dispatch_init_tiffqt(PLDispatchTable * pdt)652 void plD_dispatch_init_tiffqt( PLDispatchTable *pdt )
653 {
654 #ifndef ENABLE_DYNDRIVERS
655     pdt->pl_MenuStr = "Qt tiff Driver";
656     pdt->pl_DevName = "tiffqt";
657 #endif
658     pdt->pl_type     = plDevType_FileOriented;
659     pdt->pl_seq      = 70;
660     pdt->pl_init     = (plD_init_fp) plD_init_rasterqt;
661     pdt->pl_line     = (plD_line_fp) plD_line_rasterqt;
662     pdt->pl_polyline = (plD_polyline_fp) plD_polyline_rasterqt;
663     pdt->pl_eop      = (plD_eop_fp) plD_eop_rasterqt;
664     pdt->pl_bop      = (plD_bop_fp) plD_bop_tiffqt;
665     pdt->pl_tidy     = (plD_tidy_fp) plD_tidy_rasterqt;
666     pdt->pl_state    = (plD_state_fp) plD_state_rasterqt;
667     pdt->pl_esc      = (plD_esc_fp) plD_esc_rasterqt;
668 }
669 
plD_bop_tiffqt(PLStream * pls)670 void plD_bop_tiffqt( PLStream *pls )
671 {
672     // Plot familying stuff. Not really understood, just copying gd.c
673     plGetFam( pls );
674 
675     pls->famadv = 1;
676     pls->page++;
677     if ( qt_family_check( pls ) )
678     {
679         return;
680     }
681     ( (QtRasterDevice *) pls->dev )->definePlotName( pls->FileName, "TIFF" );
682     ( (QtRasterDevice *) pls->dev )->setBackgroundColor( pls->cmap0[0].r, pls->cmap0[0].g, pls->cmap0[0].b, pls->cmap0[0].a );
683 }
684 #endif
685 
686 #if defined ( PLD_svgqt ) && QT_VERSION >= 0x040300
plD_dispatch_init_svgqt(PLDispatchTable * pdt)687 void plD_dispatch_init_svgqt( PLDispatchTable *pdt )
688 {
689 #ifndef ENABLE_DYNDRIVERS
690     pdt->pl_MenuStr = "Qt SVG Driver";
691     pdt->pl_DevName = "svgqt";
692 #endif
693     pdt->pl_type     = plDevType_FileOriented;
694     pdt->pl_seq      = 71;
695     pdt->pl_init     = (plD_init_fp) plD_init_svgqt;
696     pdt->pl_line     = (plD_line_fp) plD_line_svgqt;
697     pdt->pl_polyline = (plD_polyline_fp) plD_polyline_svgqt;
698     pdt->pl_eop      = (plD_eop_fp) plD_eop_svgqt;
699     pdt->pl_bop      = (plD_bop_fp) plD_bop_svgqt;
700     pdt->pl_tidy     = (plD_tidy_fp) plD_tidy_svgqt;
701     pdt->pl_state    = (plD_state_fp) plD_state_svgqt;
702     pdt->pl_esc      = (plD_esc_fp) plD_esc_svgqt;
703 }
704 
plD_init_svgqt(PLStream * pls)705 void plD_init_svgqt( PLStream * pls )
706 {
707     vectorize = 1;
708     lines_aa  = 1;
709     plParseDrvOpts( qt_options );
710 
711     // Stream setup
712     pls->color        = 1;
713     pls->plbuf_write  = 0;
714     pls->dev_fill0    = 1;
715     pls->dev_fill1    = 0;
716     pls->dev_gradient = 1;      // driver renders gradient
717     // Let the PLplot core handle dashed lines since
718     // the driver results for this capability have a number of issues.
719     // pls->dev_dash=1;
720     pls->dev_dash  = 0;
721     pls->dev_flush = 1;
722     // Driver does not have a clear capability so use (good) PLplot core
723     // fallback for that instead.
724     pls->dev_clear         = 0;
725     pls->termin            = 0;
726     pls->page              = 0;
727     pls->dev_text          = 1; // want to draw text
728     pls->dev_unicode       = 1; // want unicode
729     pls->has_string_length = 1; // Driver supports string length calculations
730 
731     // Needs to be true only because of multi-stream case
732     bool isMaster = initQtApp( true );
733 
734     if ( pls->xlength <= 0 || pls->ylength <= 0 )
735     {
736         pls->dev     = new QtSVGDevice;
737         pls->xlength = (int) ( ( (QtSVGDevice *) ( pls->dev ) )->m_dWidth );
738         pls->ylength = (int) ( ( (QtSVGDevice *) ( pls->dev ) )->m_dHeight );
739     }
740     else
741     {
742         pls->dev = new QtSVGDevice( pls->xlength, pls->ylength );
743     }
744     ( (QtSVGDevice *) pls->dev )->setPLStream( pls );
745 
746     if ( isMaster )
747         handler.setMasterDevice( (QtSVGDevice *) ( pls->dev ) );
748 
749     if ( pls->xlength > pls->ylength )
750         ( (QtSVGDevice *) ( pls->dev ) )->downscale = (PLFLT) pls->xlength / (PLFLT) ( PIXELS_X - 1 );
751     else
752         ( (QtSVGDevice *) ( pls->dev ) )->downscale = (PLFLT) pls->ylength / (PLFLT) PIXELS_Y;
753 
754     plP_setphy( (PLINT) 0, (PLINT) ( pls->xlength / ( (QtSVGDevice *) ( pls->dev ) )->downscale ), (PLINT) 0, (PLINT) ( pls->ylength / ( (QtSVGDevice *) ( pls->dev ) )->downscale ) );
755 
756     plP_setpxl( POINTS_PER_INCH / 25.4 / ( (QtSVGDevice *) ( pls->dev ) )->downscale, POINTS_PER_INCH / 25.4 / ( (QtSVGDevice *) ( pls->dev ) )->downscale );
757 
758     // Initialize family file info
759     plFamInit( pls );
760 
761     plOpenFile( pls );
762 }
763 
plD_bop_svgqt(PLStream * pls)764 void plD_bop_svgqt( PLStream *pls )
765 {
766     // Plot familying stuff. Not really understood, just copying gd.c
767     plGetFam( pls );
768 
769     pls->famadv = 1;
770     pls->page++;
771     if ( qt_family_check( pls ) )
772     {
773         return;
774     }
775     ( (QtSVGDevice *) pls->dev )->definePlotName( pls->FileName );
776     ( (QtSVGDevice *) pls->dev )->setBackgroundColor( pls->cmap0[0].r, pls->cmap0[0].g, pls->cmap0[0].b, pls->cmap0[0].a );
777 }
778 
plD_eop_svgqt(PLStream * pls)779 void plD_eop_svgqt( PLStream *pls )
780 {
781     double downscale;
782     QSize  s;
783 
784     if ( qt_family_check( pls ) )
785     {
786         return;
787     }
788     ( (QtSVGDevice *) pls->dev )->savePlot();
789     // Once saved, we have to create a new device with the same properties
790     // to be able to plot another page.
791     downscale = ( (QtSVGDevice *) pls->dev )->downscale;
792     s         = ( (QtSVGDevice *) pls->dev )->size();
793     bool isMaster = ( handler.isMasterDevice( (QtSVGDevice *) pls->dev ) );
794     delete ( (QtSVGDevice *) pls->dev );
795 
796     pls->dev = new QtSVGDevice( s.width(), s.height() );
797     ( (QtSVGDevice *) pls->dev )->downscale = downscale;
798     ( (QtSVGDevice *) pls->dev )->setPLStream( pls );
799 
800     if ( isMaster )
801         handler.setMasterDevice( (QtSVGDevice *) pls->dev );
802     handler.DeviceChangedPage( (QtSVGDevice *) pls->dev );
803 }
804 
plD_line_svgqt(PLStream * pls,short x1a,short y1a,short x2a,short y2a)805 void plD_line_svgqt( PLStream * pls, short x1a, short y1a, short x2a, short y2a )
806 {
807     QtSVGDevice* widget = (QtSVGDevice *) pls->dev;
808     if ( widget != NULL && qt_family_check( pls ) )
809     {
810         return;
811     }
812     if ( widget == NULL )
813         return;
814 
815     widget->setColor( pls->curcolor.r, pls->curcolor.g, pls->curcolor.b, pls->curcolor.a );
816     widget->drawLine( x1a, y1a, x2a, y2a );
817 }
818 
plD_polyline_svgqt(PLStream * pls,short * xa,short * ya,PLINT npts)819 void plD_polyline_svgqt( PLStream *pls, short *xa, short *ya, PLINT npts )
820 {
821     QtSVGDevice * widget = (QtSVGDevice *) pls->dev;
822     if ( widget != NULL && qt_family_check( pls ) )
823     {
824         return;
825     }
826     if ( widget == NULL )
827         return;
828 
829     widget->setColor( pls->curcolor.r, pls->curcolor.g, pls->curcolor.b, pls->curcolor.a );
830     widget->drawPolyline( xa, ya, npts );
831 }
832 
plD_esc_svgqt(PLStream * pls,PLINT op,void * ptr)833 void plD_esc_svgqt( PLStream * pls, PLINT op, void* ptr )
834 {
835     short         *xa, *ya;
836     unsigned char *r, *g, *b;
837     PLFLT         *alpha;
838     PLINT         i;
839     QtSVGDevice   * widget = (QtSVGDevice *) pls->dev;
840     if ( widget != NULL && qt_family_check( pls ) )
841     {
842         return;
843     }
844     if ( widget == NULL )
845         return;
846 
847     switch ( op )
848     {
849     case PLESC_FILL:
850         xa = new short[pls->dev_npts];
851         ya = new short[pls->dev_npts];
852 
853         for ( i = 0; i < pls->dev_npts; i++ )
854         {
855             xa[i] = pls->dev_x[i];
856             ya[i] = pls->dev_y[i];
857         }
858         widget->setColor( pls->curcolor.r, pls->curcolor.g, pls->curcolor.b, pls->curcolor.a );
859         widget->drawPolygon( xa, ya, pls->dev_npts );
860 
861         delete[] xa;
862         delete[] ya;
863         break;
864 
865     case PLESC_GRADIENT:
866         xa    = new short[pls->dev_npts];
867         ya    = new short[pls->dev_npts];
868         r     = new unsigned char[pls->ncol1];
869         g     = new unsigned char[pls->ncol1];
870         b     = new unsigned char[pls->ncol1];
871         alpha = new PLFLT[pls->ncol1];
872 
873         for ( i = 0; i < pls->ncol1; i++ )
874         {
875             r[i]     = pls->cmap1[i].r;
876             g[i]     = pls->cmap1[i].g;
877             b[i]     = pls->cmap1[i].b;
878             alpha[i] = pls->cmap1[i].a;
879         }
880         widget->setGradient( pls->xgradient[0], pls->xgradient[1], pls->ygradient[0], pls->ygradient[1], r, g, b, alpha, pls->ncol1 );
881 
882         for ( i = 0; i < pls->dev_npts; i++ )
883         {
884             xa[i] = pls->dev_x[i];
885             ya[i] = pls->dev_y[i];
886         }
887         widget->drawPolygon( xa, ya, pls->dev_npts );
888 
889         delete[] xa;
890         delete[] ya;
891         delete[] r;
892         delete[] g;
893         delete[] b;
894         delete[] alpha;
895         break;
896 
897     case PLESC_HAS_TEXT:
898         // call the generic ProcessString function
899         //  ProcessString( pls, (EscText *)ptr );
900         widget->setColor( pls->curcolor.r, pls->curcolor.g, pls->curcolor.b, pls->curcolor.a );
901         widget->drawText( (EscText *) ptr );
902         break;
903 
904     default:
905         break;
906     }
907 }
908 
plD_state_svgqt(PLStream * pls,PLINT op)909 void plD_state_svgqt( PLStream * pls, PLINT op )
910 {
911     QtSVGDevice * widget = (QtSVGDevice *) pls->dev;
912     if ( widget != NULL && qt_family_check( pls ) )
913     {
914         return;
915     }
916     if ( widget == NULL )
917         return;
918 
919     switch ( op )
920     {
921     case PLSTATE_WIDTH:
922         widget->setWidthF( pls->width );
923         break;
924 
925     case PLSTATE_COLOR0:
926         widget->setColor( pls->curcolor.r, pls->curcolor.g, pls->curcolor.b, pls->curcolor.a );
927         break;
928 
929     case PLSTATE_COLOR1:
930         widget->setColor( pls->curcolor.r, pls->curcolor.g, pls->curcolor.b, pls->curcolor.a );
931         break;
932 
933     default: break;
934     }
935 }
936 
plD_tidy_svgqt(PLStream * pls)937 void plD_tidy_svgqt( PLStream * pls )
938 {
939     QtSVGDevice * widget = (QtSVGDevice *) pls->dev;
940 
941     if ( widget != NULL )
942     {
943         handler.DeviceClosed( widget );
944         delete widget;
945         pls->dev = NULL;
946     }
947     plCloseFile( pls );
948 
949     closeQtApp();
950 }
951 #endif
952 
953 #if defined ( PLD_epsqt )
plD_dispatch_init_epsqt(PLDispatchTable * pdt)954 void plD_dispatch_init_epsqt( PLDispatchTable *pdt )
955 {
956 #ifndef ENABLE_DYNDRIVERS
957     pdt->pl_MenuStr = "Qt EPS Driver";
958     pdt->pl_DevName = "epsqt";
959 #endif
960     pdt->pl_type     = plDevType_FileOriented;
961     pdt->pl_seq      = 73;
962     pdt->pl_init     = (plD_init_fp) plD_init_epspdfqt;
963     pdt->pl_line     = (plD_line_fp) plD_line_epspdfqt;
964     pdt->pl_polyline = (plD_polyline_fp) plD_polyline_epspdfqt;
965     pdt->pl_eop      = (plD_eop_fp) plD_eop_epspdfqt;
966     pdt->pl_bop      = (plD_bop_fp) plD_bop_epsqt;
967     pdt->pl_tidy     = (plD_tidy_fp) plD_tidy_epspdfqt;
968     pdt->pl_state    = (plD_state_fp) plD_state_epspdfqt;
969     pdt->pl_esc      = (plD_esc_fp) plD_esc_epspdfqt;
970 }
971 #endif
972 
973 #if defined ( PLD_pdfqt )
plD_dispatch_init_pdfqt(PLDispatchTable * pdt)974 void plD_dispatch_init_pdfqt( PLDispatchTable *pdt )
975 {
976 #ifndef ENABLE_DYNDRIVERS
977     pdt->pl_MenuStr = "Qt PDF Driver";
978     pdt->pl_DevName = "pdfqt";
979 #endif
980     pdt->pl_type     = plDevType_FileOriented;
981     pdt->pl_seq      = 74;
982     pdt->pl_init     = (plD_init_fp) plD_init_epspdfqt;
983     pdt->pl_line     = (plD_line_fp) plD_line_epspdfqt;
984     pdt->pl_polyline = (plD_polyline_fp) plD_polyline_epspdfqt;
985     pdt->pl_eop      = (plD_eop_fp) plD_eop_epspdfqt;
986     pdt->pl_bop      = (plD_bop_fp) plD_bop_pdfqt;
987     pdt->pl_tidy     = (plD_tidy_fp) plD_tidy_epspdfqt;
988     pdt->pl_state    = (plD_state_fp) plD_state_epspdfqt;
989     pdt->pl_esc      = (plD_esc_fp) plD_esc_epspdfqt;
990 }
991 #endif
992 
993 #if defined ( PLD_epsqt ) || defined ( PLD_pdfqt )
plD_init_epspdfqt(PLStream * pls)994 void plD_init_epspdfqt( PLStream * pls )
995 {
996     vectorize = 0;
997     lines_aa  = 1;
998     plParseDrvOpts( qt_options );
999 
1000     // Stream setup
1001     pls->color        = 1;
1002     pls->plbuf_write  = 0;
1003     pls->dev_fill0    = 1;
1004     pls->dev_fill1    = 0;
1005     pls->dev_gradient = 1;      // driver renders gradient
1006     pls->dev_arc      = 1;      // driver renders arcs
1007     // Let the PLplot core handle dashed lines since
1008     // the driver results for this capability have a number of issues.
1009     // pls->dev_dash=1;
1010     pls->dev_dash  = 0;
1011     pls->dev_flush = 1;
1012     // Driver does not have a clear capability so use (good) PLplot core
1013     // fallback for that instead.
1014     pls->dev_clear         = 0;
1015     pls->termin            = 0;
1016     pls->page              = 0;
1017     pls->dev_text          = 1; // want to draw text
1018     pls->dev_unicode       = 1; // want unicode
1019     pls->has_string_length = 1; // Driver supports string length calculations
1020 
1021     // QPrinter devices won't create if there is no QApplication declared...
1022     // Needs to be true only because of multi-stream case
1023     bool isMaster = initQtApp( true );
1024 
1025     if ( pls->xlength <= 0 || pls->ylength <= 0 )
1026     {
1027         pls->dev     = new QtEPSDevice;
1028         pls->xlength = (int) ( ( (QtEPSDevice *) ( pls->dev ) )->m_dWidth );
1029         pls->ylength = (int) ( ( (QtEPSDevice *) ( pls->dev ) )->m_dHeight );
1030     }
1031     else
1032     {
1033         pls->dev = new QtEPSDevice( pls->xlength, pls->ylength );
1034     }
1035     ( (QtEPSDevice *) pls->dev )->setPLStream( pls );
1036 
1037     if ( isMaster )
1038         handler.setMasterDevice( (QtEPSDevice *) ( pls->dev ) );
1039 
1040     if ( pls->xlength > pls->ylength )
1041         ( (QtEPSDevice *) ( pls->dev ) )->downscale = (PLFLT) pls->xlength / (PLFLT) ( PIXELS_X - 1 );
1042     else
1043         ( (QtEPSDevice *) ( pls->dev ) )->downscale = (PLFLT) pls->ylength / (PLFLT) PIXELS_Y;
1044 
1045     plP_setphy( (PLINT) 0, (PLINT) ( pls->xlength / ( (QtEPSDevice *) ( pls->dev ) )->downscale ), (PLINT) 0, (PLINT) ( pls->ylength / ( (QtEPSDevice *) ( pls->dev ) )->downscale ) );
1046 
1047     plP_setpxl( POINTS_PER_INCH / 25.4 / ( (QtEPSDevice *) ( pls->dev ) )->downscale, POINTS_PER_INCH / 25.4 / ( (QtEPSDevice *) ( pls->dev ) )->downscale );
1048 
1049     // Initialize family file info
1050     plFamInit( pls );
1051 
1052     plOpenFile( pls );
1053 }
1054 
plD_bop_epspdfqt_helper(PLStream * pls,int ifeps)1055 void plD_bop_epspdfqt_helper( PLStream *pls, int ifeps )
1056 {
1057     // Plot familying stuff. Not really understood, just copying gd.c
1058     plGetFam( pls );
1059 
1060     pls->famadv = 1;
1061     pls->page++;
1062     if ( qt_family_check( pls ) )
1063     {
1064         return;
1065     }
1066     ( (QtEPSDevice *) pls->dev )->definePlotName( pls->FileName, ifeps );
1067     ( (QtEPSDevice *) pls->dev )->setBackgroundColor( pls->cmap0[0].r, pls->cmap0[0].g, pls->cmap0[0].b, pls->cmap0[0].a );
1068 }
1069 
plD_eop_epspdfqt(PLStream * pls)1070 void plD_eop_epspdfqt( PLStream *pls )
1071 {
1072     double downscale;
1073 
1074     if ( qt_family_check( pls ) )
1075     {
1076         return;
1077     }
1078     ( (QtEPSDevice *) pls->dev )->savePlot();
1079     // Once saved, we have to create a new device with the same properties
1080     // to be able to plot another page.
1081     downscale = ( (QtEPSDevice *) pls->dev )->downscale;
1082     bool isMaster = handler.isMasterDevice( (QtEPSDevice *) pls->dev );
1083     delete ( (QtEPSDevice *) pls->dev );
1084 
1085     pls->dev = new QtEPSDevice;
1086     ( (QtEPSDevice *) pls->dev )->downscale = downscale;
1087 
1088     if ( isMaster )
1089         handler.setMasterDevice( (QtEPSDevice *) pls->dev );
1090     handler.DeviceChangedPage( (QtEPSDevice *) pls->dev );
1091 }
1092 
plD_line_epspdfqt(PLStream * pls,short x1a,short y1a,short x2a,short y2a)1093 void plD_line_epspdfqt( PLStream * pls, short x1a, short y1a, short x2a, short y2a )
1094 {
1095     QtEPSDevice* widget = (QtEPSDevice *) pls->dev;
1096     if ( widget != NULL && qt_family_check( pls ) )
1097     {
1098         return;
1099     }
1100     if ( widget == NULL )
1101         return;
1102 
1103     widget->setColor( pls->curcolor.r, pls->curcolor.g, pls->curcolor.b, pls->curcolor.a );
1104     widget->drawLine( x1a, y1a, x2a, y2a );
1105 }
1106 
plD_polyline_epspdfqt(PLStream * pls,short * xa,short * ya,PLINT npts)1107 void plD_polyline_epspdfqt( PLStream *pls, short *xa, short *ya, PLINT npts )
1108 {
1109     QtEPSDevice * widget = (QtEPSDevice *) pls->dev;
1110     if ( widget != NULL && qt_family_check( pls ) )
1111     {
1112         return;
1113     }
1114     if ( widget == NULL )
1115         return;
1116 
1117     widget->setColor( pls->curcolor.r, pls->curcolor.g, pls->curcolor.b, pls->curcolor.a );
1118     widget->drawPolyline( xa, ya, npts );
1119 }
1120 
plD_esc_epspdfqt(PLStream * pls,PLINT op,void * ptr)1121 void plD_esc_epspdfqt( PLStream * pls, PLINT op, void* ptr )
1122 {
1123     short         *xa, *ya;
1124     unsigned char *r, *g, *b;
1125     PLFLT         *alpha;
1126     PLINT         i;
1127     QtEPSDevice   * widget  = (QtEPSDevice *) pls->dev;
1128     arc_struct    *arc_info = (arc_struct *) ptr;
1129 
1130     if ( widget != NULL && qt_family_check( pls ) )
1131     {
1132         return;
1133     }
1134     if ( widget == NULL )
1135         return;
1136 
1137     switch ( op )
1138     {
1139     case PLESC_FILL:
1140         xa = new short[pls->dev_npts];
1141         ya = new short[pls->dev_npts];
1142 
1143         for ( i = 0; i < pls->dev_npts; i++ )
1144         {
1145             xa[i] = pls->dev_x[i];
1146             ya[i] = pls->dev_y[i];
1147         }
1148         widget->setColor( pls->curcolor.r, pls->curcolor.g, pls->curcolor.b, pls->curcolor.a );
1149         widget->drawPolygon( xa, ya, pls->dev_npts );
1150 
1151         delete[] xa;
1152         delete[] ya;
1153         break;
1154 
1155     case PLESC_GRADIENT:
1156         xa    = new short[pls->dev_npts];
1157         ya    = new short[pls->dev_npts];
1158         r     = new unsigned char[pls->ncol1];
1159         g     = new unsigned char[pls->ncol1];
1160         b     = new unsigned char[pls->ncol1];
1161         alpha = new PLFLT[pls->ncol1];
1162 
1163         for ( i = 0; i < pls->ncol1; i++ )
1164         {
1165             r[i]     = pls->cmap1[i].r;
1166             g[i]     = pls->cmap1[i].g;
1167             b[i]     = pls->cmap1[i].b;
1168             alpha[i] = pls->cmap1[i].a;
1169         }
1170         widget->setGradient( pls->xgradient[0], pls->xgradient[1], pls->ygradient[0], pls->ygradient[1], r, g, b, alpha, pls->ncol1 );
1171 
1172         for ( i = 0; i < pls->dev_npts; i++ )
1173         {
1174             xa[i] = pls->dev_x[i];
1175             ya[i] = pls->dev_y[i];
1176         }
1177         widget->drawPolygon( xa, ya, pls->dev_npts );
1178 
1179         delete[] xa;
1180         delete[] ya;
1181         delete[] r;
1182         delete[] g;
1183         delete[] b;
1184         delete[] alpha;
1185         break;
1186 
1187     case PLESC_HAS_TEXT:
1188         // call the generic ProcessString function
1189         //  ProcessString( pls, (EscText *)ptr );
1190         widget->setColor( pls->curcolor.r, pls->curcolor.g, pls->curcolor.b, pls->curcolor.a );
1191         widget->drawText( (EscText *) ptr );
1192         break;
1193 
1194     case PLESC_ARC:
1195         widget->drawArc( arc_info->x, arc_info->y, arc_info->a, arc_info->b, arc_info->angle1, arc_info->angle2, arc_info->rotate, arc_info->fill );
1196         break;
1197 
1198     default: break;
1199     }
1200 }
1201 
plD_state_epspdfqt(PLStream * pls,PLINT op)1202 void plD_state_epspdfqt( PLStream * pls, PLINT op )
1203 {
1204     QtEPSDevice * widget = (QtEPSDevice *) pls->dev;
1205     if ( widget != NULL && qt_family_check( pls ) )
1206     {
1207         return;
1208     }
1209     if ( widget == NULL )
1210         return;
1211 
1212     switch ( op )
1213     {
1214     case PLSTATE_WIDTH:
1215         widget->setWidthF( pls->width );
1216         break;
1217 
1218     case PLSTATE_COLOR0:
1219         widget->setColor( pls->curcolor.r, pls->curcolor.g, pls->curcolor.b, pls->curcolor.a );
1220         break;
1221 
1222     case PLSTATE_COLOR1:
1223         widget->setColor( pls->curcolor.r, pls->curcolor.g, pls->curcolor.b, pls->curcolor.a );
1224         break;
1225 
1226 
1227     default: break;
1228     }
1229 }
1230 
plD_tidy_epspdfqt(PLStream * pls)1231 void plD_tidy_epspdfqt( PLStream * pls )
1232 {
1233     QtEPSDevice * widget = (QtEPSDevice *) pls->dev;
1234 
1235     if ( widget != NULL )
1236     {
1237         handler.DeviceClosed( widget );
1238         delete widget;
1239         pls->dev = NULL;
1240     }
1241     plCloseFile( pls );
1242 
1243     closeQtApp();
1244 }
1245 #endif
1246 
1247 #if defined ( PLD_epsqt )
plD_bop_epsqt(PLStream * pls)1248 void plD_bop_epsqt( PLStream *pls )
1249 {
1250     plD_bop_epspdfqt_helper( pls, 1 );
1251 }
1252 #endif
1253 
1254 #if defined ( PLD_pdfqt )
plD_bop_pdfqt(PLStream * pls)1255 void plD_bop_pdfqt( PLStream *pls )
1256 {
1257     plD_bop_epspdfqt_helper( pls, 0 );
1258 }
1259 #endif
1260 
1261 #if defined ( PLD_qtwidget )
plD_dispatch_init_qtwidget(PLDispatchTable * pdt)1262 void plD_dispatch_init_qtwidget( PLDispatchTable *pdt )
1263 {
1264 #ifndef ENABLE_DYNDRIVERS
1265     pdt->pl_MenuStr = "Qt Widget";
1266     pdt->pl_DevName = "qtwidget";
1267 #endif
1268     pdt->pl_type     = plDevType_Interactive;
1269     pdt->pl_seq      = 72;
1270     pdt->pl_init     = (plD_init_fp) plD_init_qtwidget;
1271     pdt->pl_line     = (plD_line_fp) plD_line_qtwidget;
1272     pdt->pl_polyline = (plD_polyline_fp) plD_polyline_qtwidget;
1273     pdt->pl_eop      = (plD_eop_fp) plD_eop_qtwidget;
1274     pdt->pl_bop      = (plD_bop_fp) plD_bop_qtwidget;
1275     pdt->pl_tidy     = (plD_tidy_fp) plD_tidy_qtwidget;
1276     pdt->pl_state    = (plD_state_fp) plD_state_qtwidget;
1277     pdt->pl_esc      = (plD_esc_fp) plD_esc_qtwidget;
1278     pdt->pl_wait     = (plD_wait_fp) plD_wait_qtwidget;
1279 }
1280 
plD_init_qtwidget(PLStream * pls)1281 void plD_init_qtwidget( PLStream * pls )
1282 {
1283     vectorize = 0;
1284     lines_aa  = 1;
1285     plParseDrvOpts( qt_options );
1286 
1287     bool      isMaster = initQtApp( true );
1288     QtPLWidget* widget;
1289 
1290     if ( pls->xlength <= 0 || pls->ylength <= 0 )
1291     {
1292         widget       = new QtPLWidget;
1293         pls->dev     = (void *) widget;
1294         pls->xlength = (int) widget->m_dWidth;
1295         pls->ylength = (int) widget->m_dHeight;
1296     }
1297     else
1298     {
1299         widget   = new QtPLWidget( pls->xlength, pls->ylength );
1300         pls->dev = (void *) widget;
1301     }
1302     widget->setPLStream( pls );
1303 
1304     if ( isMaster )
1305         handler.setMasterDevice( widget );
1306 
1307     if ( plsc->xlength > plsc->ylength )
1308         widget->downscale = (PLFLT) plsc->xlength / (PLFLT) ( PIXELS_X - 1 );
1309     else
1310         widget->downscale = (PLFLT) plsc->ylength / (PLFLT) PIXELS_Y;
1311 
1312     plP_setphy( (PLINT) 0, (PLINT) ( plsc->xlength / widget->downscale ), (PLINT) 0, (PLINT) ( plsc->ylength / widget->downscale ) );
1313 
1314     QPicture temp;
1315     QPainter tempPainter( &temp );
1316 
1317     plP_setpxl( temp.logicalDpiX() / 25.4 / widget->downscale, temp.logicalDpiY() / 25.4 / widget->downscale );
1318 
1319     pls->color        = 1;      // Is a color device
1320     pls->plbuf_write  = 1;      // Store commands to device in core buffer
1321     pls->dev_fill0    = 1;      // Handle solid fills
1322     pls->dev_fill1    = 0;
1323     pls->dev_gradient = 1;      // driver renders gradient
1324     pls->dev_arc      = 1;      // driver renders arcs
1325     // Let the PLplot core handle dashed lines since
1326     // the driver results for this capability have a number of issues.
1327     // pls->dev_dash=1;
1328     pls->dev_dash  = 0;
1329     pls->dev_flush = 1;
1330     // Driver does not have a clear capability so use (good) PLplot core
1331     // fallback for that instead.
1332     pls->dev_clear         = 0;
1333     pls->termin            = 1;
1334     pls->dev_text          = 1; // want to draw text
1335     pls->dev_unicode       = 1; // want unicode
1336     pls->has_string_length = 1; // Driver supports string length calculations
1337 
1338     widget->setVisible( true );
1339     widget->resize( plsc->xlength, plsc->ylength );
1340     widget->move( plsc->xoffset, plsc->yoffset );
1341 
1342     widget->setWindowTitle( pls->plwindow );
1343 
1344     qApp->connect( &handler, SIGNAL( MasterChangedPage() ), widget, SLOT( nextPage() ) );
1345     qApp->connect( &handler, SIGNAL( MasterClosed() ), widget, SLOT( close() ) );
1346 }
1347 
plD_eop_qtwidget(PLStream * pls)1348 void plD_eop_qtwidget( PLStream *pls )
1349 {
1350     QtPLWidget* widget = ( (QtPLWidget *) pls->dev );
1351 
1352     widget->flush();
1353     widget->raise();
1354 }
1355 
plD_wait_qtwidget(PLStream * pls)1356 void plD_wait_qtwidget( PLStream *pls )
1357 {
1358     QtPLWidget* widget    = ( (QtPLWidget *) pls->dev );
1359     int       currentPage = widget->pageNumber;
1360 
1361     widget->raise();
1362     while ( currentPage == widget->pageNumber && handler.isMasterDevice( widget ) )
1363     {
1364         qApp->processEvents( QEventLoop::WaitForMoreEvents );
1365     }
1366 }
1367 
plD_bop_qtwidget(PLStream * pls)1368 void plD_bop_qtwidget( PLStream *pls )
1369 {
1370     QtPLWidget* widget = ( (QtPLWidget *) pls->dev );
1371     widget->setBackgroundColor( pls->cmap0[0].r, pls->cmap0[0].g, pls->cmap0[0].b, pls->cmap0[0].a );
1372 }
1373 
plD_line_qtwidget(PLStream * pls,short x1a,short y1a,short x2a,short y2a)1374 void plD_line_qtwidget( PLStream * pls, short x1a, short y1a, short x2a, short y2a )
1375 {
1376     QtPLWidget* widget = (QtPLWidget *) pls->dev;
1377     if ( widget == NULL )
1378         return;
1379 
1380     widget->setColor( pls->curcolor.r, pls->curcolor.g, pls->curcolor.b, pls->curcolor.a );
1381     widget->drawLine( x1a, y1a, x2a, y2a );
1382 }
1383 
plD_polyline_qtwidget(PLStream * pls,short * xa,short * ya,PLINT npts)1384 void plD_polyline_qtwidget( PLStream *pls, short *xa, short *ya, PLINT npts )
1385 {
1386     QtPLWidget * widget = (QtPLWidget *) pls->dev;
1387     if ( widget == NULL )
1388         return;
1389 
1390     widget->setColor( pls->curcolor.r, pls->curcolor.g, pls->curcolor.b, pls->curcolor.a );
1391     widget->drawPolyline( xa, ya, npts );
1392 }
1393 
plD_esc_qtwidget(PLStream * pls,PLINT op,void * ptr)1394 void plD_esc_qtwidget( PLStream * pls, PLINT op, void* ptr )
1395 {
1396     short         *xa, *ya;
1397     PLINT         i;
1398     unsigned char *r, *g, *b;
1399     PLFLT         *alpha;
1400     QtPLWidget    * widget  = (QtPLWidget *) pls->dev;
1401     arc_struct    *arc_info = (arc_struct *) ptr;
1402     if ( widget == NULL )
1403         return;
1404 
1405     switch ( op )
1406     {
1407     case PLESC_FILL:
1408         xa = new short[pls->dev_npts];
1409         ya = new short[pls->dev_npts];
1410 
1411         for ( i = 0; i < pls->dev_npts; i++ )
1412         {
1413             xa[i] = pls->dev_x[i];
1414             ya[i] = pls->dev_y[i];
1415         }
1416 
1417         widget->setColor( pls->curcolor.r, pls->curcolor.g, pls->curcolor.b, pls->curcolor.a );
1418         widget->drawPolygon( xa, ya, pls->dev_npts );
1419 
1420         delete[] xa;
1421         delete[] ya;
1422         break;
1423 
1424     case PLESC_GRADIENT:
1425         xa    = new short[pls->dev_npts];
1426         ya    = new short[pls->dev_npts];
1427         r     = new unsigned char[pls->ncol1];
1428         g     = new unsigned char[pls->ncol1];
1429         b     = new unsigned char[pls->ncol1];
1430         alpha = new PLFLT[pls->ncol1];
1431 
1432         for ( i = 0; i < pls->ncol1; i++ )
1433         {
1434             r[i]     = pls->cmap1[i].r;
1435             g[i]     = pls->cmap1[i].g;
1436             b[i]     = pls->cmap1[i].b;
1437             alpha[i] = pls->cmap1[i].a;
1438         }
1439         widget->setGradient( pls->xgradient[0], pls->xgradient[1], pls->ygradient[0], pls->ygradient[1], r, g, b, alpha, pls->ncol1 );
1440 
1441         for ( i = 0; i < pls->dev_npts; i++ )
1442         {
1443             xa[i] = pls->dev_x[i];
1444             ya[i] = pls->dev_y[i];
1445         }
1446         widget->drawPolygon( xa, ya, pls->dev_npts );
1447 
1448         delete[] xa;
1449         delete[] ya;
1450         delete[] r;
1451         delete[] g;
1452         delete[] b;
1453         delete[] alpha;
1454         break;
1455 
1456     case PLESC_HAS_TEXT:
1457         widget->setColor( pls->curcolor.r, pls->curcolor.g, pls->curcolor.b, pls->curcolor.a );
1458         widget->drawText( (EscText *) ptr );
1459         break;
1460 
1461     case PLESC_ARC:
1462         widget->drawArc( arc_info->x, arc_info->y, arc_info->a, arc_info->b, arc_info->angle1, arc_info->angle2, arc_info->rotate, arc_info->fill );
1463         break;
1464 
1465     case PLESC_FLUSH:
1466         widget->flush();
1467         break;
1468     case PLESC_GETC:
1469         widget->getCursorCmd( (PLGraphicsIn *) ptr );
1470         break;
1471     default: break;
1472     }
1473 }
1474 
plD_state_qtwidget(PLStream * pls,PLINT op)1475 void plD_state_qtwidget( PLStream * pls, PLINT op )
1476 {
1477     QtPLWidget * widget = (QtPLWidget *) pls->dev;
1478     if ( widget == NULL )
1479         return;
1480 
1481     switch ( op )
1482     {
1483     case PLSTATE_WIDTH:
1484         widget->setWidthF( pls->width );
1485         break;
1486 
1487     case PLSTATE_COLOR0:
1488         widget->setColor( pls->curcolor.r, pls->curcolor.g, pls->curcolor.b, pls->curcolor.a );
1489         break;
1490 
1491     case PLSTATE_COLOR1:
1492         widget->setColor( pls->curcolor.r, pls->curcolor.g, pls->curcolor.b, pls->curcolor.a );
1493         break;
1494 
1495 
1496     default: break;
1497     }
1498 }
1499 
plD_tidy_qtwidget(PLStream * pls)1500 void plD_tidy_qtwidget( PLStream * pls )
1501 {
1502     QtPLWidget * widget = (QtPLWidget *) pls->dev;
1503 
1504     if ( widget != NULL )
1505     {
1506         handler.DeviceClosed( widget );
1507         delete widget;
1508         pls->dev = NULL;
1509     }
1510 
1511     closeQtApp();
1512 }
1513 #endif
1514 
1515 #if defined ( PLD_extqt )
plD_dispatch_init_extqt(PLDispatchTable * pdt)1516 void plD_dispatch_init_extqt( PLDispatchTable *pdt )
1517 {
1518 #ifndef ENABLE_DYNDRIVERS
1519     pdt->pl_MenuStr = "External Qt Widget";
1520     pdt->pl_DevName = "extqt";
1521 #endif
1522     pdt->pl_type     = plDevType_Interactive;
1523     pdt->pl_seq      = 75;
1524     pdt->pl_init     = (plD_init_fp) plD_init_extqt;
1525     pdt->pl_line     = (plD_line_fp) plD_line_extqt;
1526     pdt->pl_polyline = (plD_polyline_fp) plD_polyline_extqt;
1527     pdt->pl_eop      = (plD_eop_fp) plD_eop_extqt;
1528     pdt->pl_bop      = (plD_bop_fp) plD_bop_extqt;
1529     pdt->pl_tidy     = (plD_tidy_fp) plD_tidy_extqt;
1530     pdt->pl_state    = (plD_state_fp) plD_state_extqt;
1531     pdt->pl_esc      = (plD_esc_fp) plD_esc_extqt;
1532 }
1533 
plD_init_extqt(PLStream * pls)1534 void plD_init_extqt( PLStream * pls )
1535 {
1536     // N.B. initQtApp() not called here because internal_qApp is always false
1537     // for this device.
1538     vectorize = 0;
1539     lines_aa  = 1;
1540 
1541     if ( pls->dev == NULL /* || pls->xlength <= 0 || pls->ylength <= 0*/ )
1542     {
1543         printf( "Error: use plsetqtdev to set up the Qt device before calling plinit()\n" );
1544         return;
1545     }
1546 
1547     QtExtWidget* widget = (QtExtWidget *) ( pls->dev );
1548 
1549     if ( widget->m_dWidth > widget->m_dHeight )
1550         widget->downscale = (PLFLT) widget->m_dWidth / (PLFLT) ( PIXELS_X - 1 );
1551     else
1552         widget->downscale = (PLFLT) widget->m_dHeight / (PLFLT) PIXELS_Y;
1553 
1554     plP_setphy( (PLINT) 0, (PLINT) ( widget->m_dWidth / widget->downscale ), (PLINT) 0, (PLINT) ( widget->m_dHeight / widget->downscale ) );
1555 
1556     QPicture temp;
1557     QPainter tempPainter( &temp );
1558 
1559     plP_setpxl( temp.logicalDpiX() / 25.4 / widget->downscale, temp.logicalDpiY() / 25.4 / widget->downscale );
1560 
1561     pls->color        = 1;      // Is a color device
1562     pls->plbuf_write  = 0;
1563     pls->dev_fill0    = 1;      // Handle solid fills
1564     pls->dev_fill1    = 0;
1565     pls->dev_gradient = 1;      // driver renders gradient
1566     pls->dev_arc      = 1;      // driver renders arcs
1567     // Let the PLplot core handle dashed lines since
1568     // the driver results for this capability have a number of issues.
1569     // pls->dev_dash=1;
1570     pls->dev_dash  = 0;
1571     pls->dev_flush = 1;
1572     // Driver does not have a clear capability so use (good) PLplot core
1573     // fallback for that instead.
1574     pls->dev_clear         = 0;
1575     pls->termin            = 0;
1576     pls->dev_text          = 1; // want to draw text
1577     pls->dev_unicode       = 1; // want unicode
1578     pls->has_string_length = 1; // Driver supports string length calculations
1579 }
1580 
1581 //
1582 // These functions are separated out (instead of using dynamic_cast)
1583 // for the benefit of the PyQt4 bindings. C++ QtExtWidgets created
1584 // by PyQt4 are not properly type resolved.
1585 //
1586 
plD_line_extqt(PLStream * pls,short x1a,short y1a,short x2a,short y2a)1587 void plD_line_extqt( PLStream * pls, short x1a, short y1a, short x2a, short y2a )
1588 {
1589     QtExtWidget * widget = NULL;
1590 
1591     widget = (QtExtWidget *) pls->dev;
1592     widget->setColor( pls->curcolor.r, pls->curcolor.g, pls->curcolor.b, pls->curcolor.a );
1593     widget->drawLine( x1a, y1a, x2a, y2a );
1594 }
1595 
plD_polyline_extqt(PLStream * pls,short * xa,short * ya,PLINT npts)1596 void plD_polyline_extqt( PLStream *pls, short *xa, short *ya, PLINT npts )
1597 {
1598     QtExtWidget * widget = NULL;
1599 
1600     widget = (QtExtWidget *) pls->dev;
1601     widget->setColor( pls->curcolor.r, pls->curcolor.g, pls->curcolor.b, pls->curcolor.a );
1602     widget->drawPolyline( xa, ya, npts );
1603 }
1604 
plD_esc_extqt(PLStream * pls,PLINT op,void * ptr)1605 void plD_esc_extqt( PLStream * pls, PLINT op, void* ptr )
1606 {
1607     short         *xa, *ya;
1608     PLINT         i;
1609     unsigned char *r, *g, *b;
1610     PLFLT         *alpha;
1611     QtExtWidget   * widget  = NULL;
1612     arc_struct    *arc_info = (arc_struct *) ptr;
1613 
1614     widget = (QtExtWidget *) pls->dev;
1615     switch ( op )
1616     {
1617     case PLESC_FILL:
1618         xa = new short[pls->dev_npts];
1619         ya = new short[pls->dev_npts];
1620 
1621         for ( i = 0; i < pls->dev_npts; i++ )
1622         {
1623             xa[i] = pls->dev_x[i];
1624             ya[i] = pls->dev_y[i];
1625         }
1626         widget->setColor( pls->curcolor.r, pls->curcolor.g, pls->curcolor.b, pls->curcolor.a );
1627         widget->drawPolygon( xa, ya, pls->dev_npts );
1628 
1629         delete[] xa;
1630         delete[] ya;
1631         break;
1632 
1633     case PLESC_GRADIENT:
1634         xa    = new short[pls->dev_npts];
1635         ya    = new short[pls->dev_npts];
1636         r     = new unsigned char[pls->ncol1];
1637         g     = new unsigned char[pls->ncol1];
1638         b     = new unsigned char[pls->ncol1];
1639         alpha = new PLFLT[pls->ncol1];
1640 
1641         for ( i = 0; i < pls->ncol1; i++ )
1642         {
1643             r[i]     = pls->cmap1[i].r;
1644             g[i]     = pls->cmap1[i].g;
1645             b[i]     = pls->cmap1[i].b;
1646             alpha[i] = pls->cmap1[i].a;
1647         }
1648         widget->setGradient( pls->xgradient[0], pls->xgradient[1], pls->ygradient[0], pls->ygradient[1], r, g, b, alpha, pls->ncol1 );
1649 
1650         for ( i = 0; i < pls->dev_npts; i++ )
1651         {
1652             xa[i] = pls->dev_x[i];
1653             ya[i] = pls->dev_y[i];
1654         }
1655         widget->drawPolygon( xa, ya, pls->dev_npts );
1656 
1657         delete[] xa;
1658         delete[] ya;
1659         delete[] r;
1660         delete[] g;
1661         delete[] b;
1662         delete[] alpha;
1663         break;
1664 
1665     case PLESC_HAS_TEXT:
1666         // call the generic ProcessString function
1667         //  ProcessString( pls, (EscText *)ptr );
1668         widget->setColor( pls->curcolor.r, pls->curcolor.g, pls->curcolor.b, pls->curcolor.a );
1669         widget->drawText( (EscText *) ptr );
1670         break;
1671 
1672     case PLESC_ARC:
1673         widget->drawArc( arc_info->x, arc_info->y, arc_info->a, arc_info->b, arc_info->angle1, arc_info->angle2, arc_info->rotate, arc_info->fill );
1674         break;
1675 
1676     default: break;
1677     }
1678 }
1679 
plD_state_extqt(PLStream * pls,PLINT op)1680 void plD_state_extqt( PLStream * pls, PLINT op )
1681 {
1682     QtExtWidget * widget = NULL;
1683 
1684     widget = (QtExtWidget *) pls->dev;
1685     switch ( op )
1686     {
1687     case PLSTATE_WIDTH:
1688         widget->setWidthF( pls->width );
1689         break;
1690 
1691     case PLSTATE_COLOR0:
1692         widget->setColor( pls->curcolor.r, pls->curcolor.g, pls->curcolor.b, pls->curcolor.a );
1693         break;
1694 
1695     case PLSTATE_COLOR1:
1696         widget->setColor( pls->curcolor.r, pls->curcolor.g, pls->curcolor.b, pls->curcolor.a );
1697         break;
1698 
1699 
1700     default: break;
1701     }
1702 }
1703 
plD_tidy_extqt(PLStream * pls)1704 void plD_tidy_extqt( PLStream * pls )
1705 {
1706     QtExtWidget * widget = NULL;
1707 
1708     widget = (QtExtWidget *) pls->dev;
1709     if ( widget != NULL )
1710     {
1711         handler.DeviceClosed( widget );
1712         delete widget;
1713         pls->dev = NULL;
1714     }
1715 
1716     // closeQtApp() not called here because internal_qApp is always false
1717     // for this device.
1718 }
1719 
plD_eop_extqt(PLStream *)1720 void plD_eop_extqt( PLStream * /* pls */ )
1721 {
1722 }
1723 
plD_bop_extqt(PLStream * pls)1724 void plD_bop_extqt( PLStream *pls )
1725 {
1726     QtExtWidget * widget = NULL;
1727     widget = (QtExtWidget *) pls->dev;
1728     widget->setBackgroundColor( pls->cmap0[0].r, pls->cmap0[0].g, pls->cmap0[0].b, pls->cmap0[0].a );
1729 }
1730 #endif
1731 
1732 #if defined ( PLD_memqt )
plD_dispatch_init_memqt(PLDispatchTable * pdt)1733 void plD_dispatch_init_memqt( PLDispatchTable *pdt )
1734 {
1735 #ifndef ENABLE_DYNDRIVERS
1736     pdt->pl_MenuStr = "Qt Memory Driver";
1737     pdt->pl_DevName = "memqt";
1738 #endif
1739     pdt->pl_type     = plDevType_FileOriented;
1740     pdt->pl_seq      = 76;
1741     pdt->pl_init     = (plD_init_fp) plD_init_memqt;
1742     pdt->pl_line     = (plD_line_fp) plD_line_rasterqt;
1743     pdt->pl_polyline = (plD_polyline_fp) plD_polyline_rasterqt;
1744     pdt->pl_eop      = (plD_eop_fp) plD_eop_memqt;
1745     pdt->pl_bop      = (plD_bop_fp) plD_bop_memqt;
1746     pdt->pl_tidy     = (plD_tidy_fp) plD_tidy_rasterqt;
1747     pdt->pl_state    = (plD_state_fp) plD_state_rasterqt;
1748     pdt->pl_esc      = (plD_esc_fp) plD_esc_rasterqt;
1749 }
1750 
plD_init_memqt(PLStream * pls)1751 void plD_init_memqt( PLStream * pls )
1752 {
1753     int           i;
1754     double        dpi;
1755     unsigned char *qt_mem;
1756     unsigned char *input_mem;
1757 
1758     vectorize = 0;
1759     lines_aa  = 1;
1760     plParseDrvOpts( qt_options );
1761 
1762     // Stream setup
1763     pls->color        = 1;
1764     pls->plbuf_write  = 0;
1765     pls->dev_fill0    = 1;
1766     pls->dev_fill1    = 0;
1767     pls->dev_gradient = 1;      // driver renders gradient
1768     pls->dev_arc      = 1;      // driver renders arcs
1769     // Let the PLplot core handle dashed lines since
1770     // the driver results for this capability have a number of issues.
1771     // pls->dev_dash=1;
1772     pls->dev_dash  = 0;
1773     pls->dev_flush = 1;
1774     // Driver does not have a clear capability so use (good) PLplot core
1775     // fallback for that instead.
1776     pls->dev_clear         = 0;
1777     pls->termin            = 0;
1778     pls->page              = 0;
1779     pls->dev_text          = 1; // want to draw text
1780     pls->dev_unicode       = 1; // want unicode
1781     pls->has_string_length = 1; // Driver supports string length calculations
1782 
1783     // Needs to be true only because of multi-stream case
1784     bool isMaster = initQtApp( true );
1785 
1786     if ( pls->xdpi <= 0. )
1787         dpi = DEFAULT_DPI;
1788     else
1789         dpi = pls->xdpi;
1790 
1791     // Set the plot size to the memory buffer size, on the off chance
1792     // that they are different.
1793     pls->xlength = pls->phyxma;
1794     pls->ylength = pls->phyyma;
1795 
1796     // Save a pointer to the user supplied memory
1797     input_mem = (unsigned char *) pls->dev;
1798 
1799     // Create a appropriately sized raster device
1800     pls->dev = new QtRasterDevice( pls->xlength, pls->ylength );
1801     ( (QtRasterDevice *) pls->dev )->setPLStream( pls );
1802     ( (QtRasterDevice *) pls->dev )->memory = input_mem;
1803 
1804     if ( isMaster )
1805         handler.setMasterDevice( (QtRasterDevice *) ( pls->dev ) );
1806 
1807     if ( pls->xlength > pls->ylength )
1808         ( (QtRasterDevice *) ( pls->dev ) )->downscale = (PLFLT) pls->xlength / (PLFLT) ( PIXELS_X - 1 );
1809     else
1810         ( (QtRasterDevice *) ( pls->dev ) )->downscale = (PLFLT) pls->ylength / (PLFLT) PIXELS_Y;
1811 
1812     plP_setphy( (PLINT) 0, (PLINT) ( pls->xlength / ( (QtRasterDevice *) ( pls->dev ) )->downscale ), (PLINT) 0, (PLINT) ( pls->ylength / ( (QtRasterDevice *) ( pls->dev ) )->downscale ) );
1813 
1814     plP_setpxl( dpi / 25.4 / ( (QtRasterDevice *) ( pls->dev ) )->downscale, dpi / 25.4 / ( (QtRasterDevice *) ( pls->dev ) )->downscale );
1815 
1816     // Copy the user supplied memory into the QImage.
1817 //       This device assumes that the format of the QImage
1818 //       is RGB32 (or ARGB).
1819 
1820     qt_mem = ( (QtRasterDevice *) pls->dev )->scanLine( 0 );
1821 
1822     for ( i = 0; i < ( pls->xlength * pls->ylength ); i++ )
1823     {
1824         qt_mem[2] = input_mem[0]; // R
1825         qt_mem[1] = input_mem[1]; // G
1826         qt_mem[0] = input_mem[2]; // B
1827         if ( pls->dev_mem_alpha == 1 )
1828         {
1829             qt_mem[3]  = input_mem[3];
1830             input_mem += 4;
1831         }
1832         else
1833         {
1834             input_mem += 3;
1835         }
1836         qt_mem += 4;
1837     }
1838 
1839     ( (QtRasterDevice *) ( pls->dev ) )->setResolution( dpi );
1840 
1841     // This is set so the we'll always make it past the qt_family_check().
1842     pls->family = true;
1843 }
1844 
plD_bop_memqt(PLStream *)1845 void plD_bop_memqt( PLStream * /* pls */ )
1846 {
1847     // Do nothing to preserve user data
1848 }
1849 
plD_eop_memqt(PLStream * pls)1850 void plD_eop_memqt( PLStream *pls )
1851 {
1852     int           i;
1853     unsigned char *memory;
1854     unsigned char *qt_mem;
1855 
1856     memory = ( (QtRasterDevice *) pls->dev )->memory;
1857     qt_mem = ( (QtRasterDevice *) pls->dev )->scanLine( 0 );
1858 
1859     for ( i = 0; i < ( pls->xlength * pls->ylength ); i++ )
1860     {
1861         memory[0] = qt_mem[2];           // R
1862         memory[1] = qt_mem[1];           // G
1863         memory[2] = qt_mem[0];           // B
1864         if ( pls->dev_mem_alpha == 1 )
1865         {
1866             memory[3] = qt_mem[3];
1867             memory   += 4;
1868         }
1869         else
1870         {
1871             memory += 3;
1872         }
1873         qt_mem += 4;
1874     }
1875 }
1876 
1877 #endif
1878