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