PLplot  5.15.0
cairo.c
Go to the documentation of this file.
1 // June 2, 2007
2 //
3 // Graphics drivers that are based on the Cairo / Pango Libraries.
4 //
5 // Copyright (C) 2008 Hazen Babcock
6 // Copyright (C) 2009, 2010 Hezekiah M. Carty
7 //
8 // This file is part of PLplot.
9 //
10 // PLplot is free software; you can redistribute it and/or modify
11 // it under the terms of the GNU Library General Public License as published
12 // by the Free Software Foundation; either version 2 of the License, or
13 // (at your option) any later version.
14 //
15 // PLplot is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU Library General Public License for more details.
19 //
20 // You should have received a copy of the GNU Library General Public License
21 // along with PLplot; if not, write to the Free Software
22 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 //
24 //
25 
26 //--------------------------------------------------------------------------
27 // Header files
28 //--------------------------------------------------------------------------
29 
30 #include <stdio.h>
31 #include <string.h>
32 #include <math.h>
33 
34 #include <cairo.h>
35 #include <pango/pangocairo.h>
36 
37 // PLplot header files (must occur before driver-dependent includes)
38 
39 #include "plDevs.h"
40 #include "plplotP.h"
41 #include "drivers.h"
42 
43 // Driver-dependent includes
44 #if defined ( PLD_wincairo )
45 #include <windows.h>
46 #include <cairo-win32.h>
47 #endif
48 #if defined ( PLD_xcairo )
49 #include <cairo-xlib.h>
50 #include <X11/X.h>
51 #include <X11/Xlib.h>
52 #include <X11/Xutil.h>
53 #include <X11/cursorfont.h>
54 #include <X11/keysym.h>
55 #endif
56 #if defined ( PLD_pdfcairo )
57 #include <cairo-pdf.h>
58 #endif
59 #if defined ( PLD_pscairo )
60 #include <cairo-ps.h>
61 #endif
62 #if defined ( PLD_svgcairo )
63 #include <cairo-svg.h>
64 #endif
65 
66 
67 //--------------------------------------------------------------------------
68 // Constants & global (to this file) variables
69 //--------------------------------------------------------------------------
70 
71 #define DPI 72
72 #define PLCAIRO_DEFAULT_X 720
73 #define PLCAIRO_DEFAULT_Y 540
74 
75 #define MAX_STRING_LEN 500
76 #define MAX_MARKUP_LEN MAX_STRING_LEN * 10
77 
78 static int text_clipping;
79 static int text_anti_aliasing;
81 static int external_drawable;
82 static int rasterize_image;
83 static int set_background;
84 static int image_buffering;
85 static int already_warned = 0;
86 
87 static DrvOpt cairo_options[] = { { "text_clipping", DRV_INT, &text_clipping, "Use text clipping (text_clipping=0|1)" },
88  { "text_anti_aliasing", DRV_INT, &text_anti_aliasing, "Set desired text anti-aliasing (text_anti_aliasing=0|1|2|3). The numbers are in the same order as the cairo_antialias_t enumeration documented at http://cairographics.org/manual/cairo-cairo-t.html#cairo-antialias-t)" },
89  { "graphics_anti_aliasing", DRV_INT, &graphics_anti_aliasing, "Set desired graphics anti-aliasing (graphics_anti_aliasing=0|1|2|3). The numbers are in the same order as the cairo_antialias_t enumeration documented at http://cairographics.org/manual/cairo-cairo-t.html#cairo-antialias-t" },
90  { "external_drawable", DRV_INT, &external_drawable, "Plot to external X drawable" },
91  { "rasterize_image", DRV_INT, &rasterize_image, "Raster or vector image rendering (rasterize_image=0|1)" },
92  { "set_background", DRV_INT, &set_background, "Set the background for the extcairo device (set_background=0|1). If 1 then the plot background will set by PLplot" },
93  { "image_buffering", DRV_INT, &image_buffering, "Buffered offscreen rendering for the xcairo device (image_buffering=0|1)." },
94  { NULL, DRV_INT, NULL, NULL } };
95 
96 typedef struct
97 {
98  cairo_surface_t *cairoSurface;
99  cairo_t *cairoContext;
100  cairo_surface_t *cairoSurface_raster;
108  double downscale;
110  short upDown;
111  float fontSize;
112  short uline;
113 
114  // These are arguments for plP_script_scale which must be retained
115  // in aStream for the alt_unicode approach. level has an
116  // identical meaning to upDown above, but it is incremented and
117  // decremented in plP_script_scale as well as other places in the
118  // code so the only safe thing to do is to treat level separately
119  // from upDown.
120  PLFLT old_sscale, sscale, old_soffset, soffset;
122 
123 #if defined ( PLD_xcairo )
124  cairo_surface_t *cairoSurface_X;
125  cairo_t *cairoContext_X;
126  short exit_event_loop;
127  Display *XDisplay;
128  Window XWindow;
129  unsigned int xdrawable_mode;
130 #endif
131 #if defined ( PLD_memcairo )
132  unsigned char *memory;
133  unsigned char *cairo_format_memory;
134  char bigendian;
135 #endif
136 #if defined ( PLD_wincairo )
137  cairo_surface_t *cairoSurface_win;
138  cairo_t *cairoContext_win;
139  WNDCLASSEX wndclass;
140  HWND hwnd;
141  MSG msg;
142  HDC hdc;
143  HDC SCRN_hdc;
144  COLORREF oldcolour;
145  RECT rect;
146 #endif
147 } PLCairo;
148 
150 #if defined ( PLD_xcairo )
151  "xcairo:Cairo X Windows Driver:1:cairo:100:xcairo\n"
152 #endif
153 #if defined ( PLD_pdfcairo )
154  "pdfcairo:Cairo PDF Driver:0:cairo:101:pdfcairo\n"
155 #endif
156 #if defined ( PLD_pscairo )
157  "pscairo:Cairo PS Driver:0:cairo:102:pscairo\n"
158 #endif
159 #if defined ( PLD_epscairo )
160  "epscairo:Cairo EPS Driver:0:cairo:103:epscairo\n"
161 #endif
162 #if defined ( PLD_svgcairo )
163  "svgcairo:Cairo SVG Driver:0:cairo:104:svgcairo\n"
164 #endif
165 #if defined ( PLD_pngcairo )
166  "pngcairo:Cairo PNG Driver:0:cairo:105:pngcairo\n"
167 #endif
168 #if defined ( PLD_memcairo )
169  "memcairo:Cairo Memory Driver:0:cairo:106:memcairo\n"
170 #endif
171 #if defined ( PLD_extcairo )
172  "extcairo:Cairo External Context Driver:0:cairo:107:extcairo\n"
173 #endif
174 #if defined ( PLD_wincairo )
175  "wincairo:Cairo Microscoft Windows Driver:0:cairo:108:wincairo\n"
176 #endif
177 ;
178 
179 //
180 // Structure for passing external drawables to xcairo devices via
181 // the PLESC_DEVINIT escape function.
182 //
183 #if defined ( PLD_xcairo )
184 typedef struct
185 {
186  Display *display;
187  Drawable drawable;
188 } PLXcairoDrawableInfo;
189 #endif
190 
191 //--------------------------------------------------------------------------
192 // Font style and weight lookup tables (copied
193 // from the psttf driver).
194 //--------------------------------------------------------------------------
195 
196 #define NPANGOLOOKUP 5
197 
199  "sans",
200  "serif",
201  "monospace",
202  "sans,serif",
203  "sans,serif"
204 };
205 
207  "PLPLOT_FREETYPE_SANS_FAMILY",
208  "PLPLOT_FREETYPE_SERIF_FAMILY",
209  "PLPLOT_FREETYPE_MONO_FAMILY",
210  "PLPLOT_FREETYPE_SCRIPT_FAMILY",
211  "PLPLOT_FREETYPE_SYMBOL_FAMILY"
212 };
213 
214 #define FAMILY_LOOKUP_LEN 1024
216 
217 #define TAG_LEN 200
218 
219 const char *weightLookup[2] = {
220  "normal",
221  "bold"
222 };
223 
224 const char *styleLookup[3] = {
225  "normal",
226  "italic",
227  "oblique"
228 };
229 
230 //--------------------------------------------------------------------------
231 //--------------------------------------------------------------------------
232 //
233 // That which is common to all the Cairo Drivers
234 //
235 //--------------------------------------------------------------------------
236 //--------------------------------------------------------------------------
237 
238 //--------------------------------------------------------------------------
239 // function declarations
240 //--------------------------------------------------------------------------
241 
242 // General
243 
245 cairo_status_t write_to_stream( void *, unsigned char *, unsigned int );
246 void set_clip( PLStream *pls );
247 int cairo_family_check( PLStream *pls );
248 
249 // String processing
250 
251 static void proc_str( PLStream *, EscText * );
252 static void text_begin_cairo( PLStream *pls, EscText *args );
253 static void text_char_cairo( PLStream *pls, EscText *args );
254 static void text_esc_cairo( PLStream *pls, EscText *args );
255 static void text_end_cairo( PLStream *pls, EscText *args );
256 static char *ucs4_to_pango_markup_format( PLUNICODE *, int, float );
257 static void open_span_tag( char *, PLUNICODE, float, int );
258 static void close_span_tag( char *, int );
259 static char *rise_span_tag( int, float, float, float );
260 
261 // Graphics
262 
263 static void set_current_context( PLStream * );
264 static void poly_line( PLStream *, short *, short *, PLINT );
265 static void filled_polygon( PLStream *pls, short *xa, short *ya, PLINT npts );
266 static void gradient( PLStream *pls, short *xa, short *ya, PLINT npts );
267 static void arc( PLStream *, arc_struct * );
268 static void rotate_cairo_surface( PLStream *, float, float, float, float, float, float, PLBOOL );
269 static void blit_to_x( PLStream *pls, double x, double y, double w, double h );
270 // Rasterization of plotted material
271 static void start_raster( PLStream* );
272 static void end_raster( PLStream* );
273 // Get/set drawing mode
274 static void set_mode( PLStream*, PLINT* );
275 static void get_mode( PLStream*, PLINT* );
276 // Get / set line properties
277 void get_line_properties( PLCairo *aStream, cairo_line_join_t *join, cairo_line_cap_t *cap );
278 void set_line_properties( PLCairo *aStream, cairo_line_join_t join, cairo_line_cap_t cap );
279 
280 
281 // PLplot interface functions
282 
283 // general
284 void plD_bop_cairo( PLStream * );
285 void plD_eop_cairo( PLStream * );
286 void plD_state_cairo( PLStream *, PLINT );
287 void plD_esc_cairo( PLStream *, PLINT, void * );
288 void plD_tidy_cairo( PLStream * );
289 void plD_line_cairo( PLStream *, short, short, short, short );
290 void plD_polyline_cairo( PLStream *, short *, short *, PLINT );
291 
292 //--------------------------------------------------------------------------
293 // start_raster()
294 //
295 // Set up off-screen rasterized rendering
296 //--------------------------------------------------------------------------
297 
298 void start_raster( PLStream *pls )
299 {
300  PLCairo *aStream;
301  cairo_surface_t *tmp_sfc;
302  cairo_t *tmp_context;
303 
304  aStream = (PLCairo *) pls->dev;
305 
306  // Do not use the external surface if the user says not to
307  if ( !aStream->rasterize_image )
308  return;
309 
310  // Create an image surface and context for the offscreen rendering
311  aStream->cairoSurface_raster =
312  //
313  // cairo_surface_create_similar( aStream->cairoSurface,
314  // CAIRO_CONTENT_COLOR,
315  // pls->xlength, pls->ylength );
316  //
317  cairo_image_surface_create( CAIRO_FORMAT_ARGB32,
318  pls->xlength, pls->ylength );
319  aStream->cairoContext_raster = cairo_create( aStream->cairoSurface_raster );
320 
321  // Disable antialiasing for the raster surface. The output seems to look
322  // better that way.
323  cairo_set_antialias( aStream->cairoContext_raster, CAIRO_ANTIALIAS_NONE );
324 
325  // Swap the raster and main plot surfaces and contexts
326  tmp_sfc = aStream->cairoSurface;
327  tmp_context = aStream->cairoContext;
328  aStream->cairoSurface = aStream->cairoSurface_raster;
329  aStream->cairoContext = aStream->cairoContext_raster;
330  // Save the main plot surface and context for when we are finished
331  aStream->cairoSurface_raster = tmp_sfc;
332  aStream->cairoContext_raster = tmp_context;
333 }
334 
335 //--------------------------------------------------------------------------
336 // end_raster()
337 //
338 // Finish off-screen rasterized rendering and copy the result on to the
339 // main plot surface.
340 //--------------------------------------------------------------------------
341 
342 void end_raster( PLStream *pls )
343 {
344  PLCairo *aStream;
345  cairo_surface_t *tmp_sfc;
346  cairo_t *tmp_context;
347 
348  aStream = (PLCairo *) pls->dev;
349 
350  // TODO FIXME: This should really only copy the used portion of the
351  // offscreen pixmap.
352 
353  // Do not use the external surface if the user says not to
354  if ( !aStream->rasterize_image )
355  return;
356 
357  // Some Cairo devices support delayed device setup (eg: xcairo with
358  // external drawable and extcairo with an external context).
359  if ( aStream->cairoContext == NULL )
360  plexit( "Can not plot to a Cairo device with no context" );
361 
362  // Restore the main plot surface and context for future plotting
363  tmp_sfc = aStream->cairoSurface;
364  tmp_context = aStream->cairoContext;
365  aStream->cairoSurface = aStream->cairoSurface_raster;
366  aStream->cairoContext = aStream->cairoContext_raster;
367  aStream->cairoSurface_raster = tmp_sfc;
368  aStream->cairoContext_raster = tmp_context;
369 
370  // Blit the raster surface on to the main plot
371  cairo_set_source_surface( aStream->cairoContext, aStream->cairoSurface_raster, 0.0, 0.0 );
372  cairo_paint( aStream->cairoContext );
373 
374  // Free the now extraneous surface and context
375  cairo_destroy( aStream->cairoContext_raster );
376  cairo_surface_destroy( aStream->cairoSurface_raster );
377 }
378 
379 //--------------------------------------------------------------------------
380 // plD_bop_cairo()
381 //
382 // Set up for the next page.
383 //--------------------------------------------------------------------------
384 
386 {
387  PLCairo *aStream;
388 
389  aStream = (PLCairo *) pls->dev;
390 
391  // Some Cairo devices support delayed device setup (eg: xcairo with
392  // external drawable and extcairo with an external context).
393  if ( aStream->cairoContext == NULL )
394  return;
395 
396  // Fill in the window with the background color.
397  cairo_rectangle( aStream->cairoContext, 0.0, 0.0, pls->xlength, pls->ylength );
398  if ( (double) pls->cmap0[0].a < 1.0 )
399  {
400  cairo_set_source_rgba( aStream->cairoContext, 1.0, 1.0, 1.0, 1.0 );
401  cairo_fill_preserve( aStream->cairoContext );
402  }
403  cairo_set_source_rgba( aStream->cairoContext,
404  (double) pls->cmap0[0].r / 255.0,
405  (double) pls->cmap0[0].g / 255.0,
406  (double) pls->cmap0[0].b / 255.0,
407  (double) pls->cmap0[0].a );
408  cairo_fill( aStream->cairoContext );
409 }
410 
411 //--------------------------------------------------------------------------
412 // plD_line_cairo()
413 //
414 // Draw a line in the current color from (x1,y1) to (x2,y2).
415 //--------------------------------------------------------------------------
416 
417 //--------------------------------------------------------------------------
418 // (get|set)_line_properties
419 //
420 // (Get|Set) the current Cairo line drawing properties.
421 //--------------------------------------------------------------------------
422 void get_line_properties( PLCairo *aStream, cairo_line_join_t *join, cairo_line_cap_t *cap )
423 {
424  *join = cairo_get_line_join( aStream->cairoContext );
425  *cap = cairo_get_line_cap( aStream->cairoContext );
426 }
427 
428 void set_line_properties( PLCairo *aStream, cairo_line_join_t join, cairo_line_cap_t cap )
429 {
430  cairo_set_line_join( aStream->cairoContext, join );
431  cairo_set_line_cap( aStream->cairoContext, cap );
432 }
433 
434 void plD_line_cairo( PLStream *pls, short x1a, short y1a, short x2a, short y2a )
435 {
436  PLCairo *aStream;
437 
438  aStream = (PLCairo *) pls->dev;
439 
440  set_current_context( pls );
441 
442  cairo_save( aStream->cairoContext );
443 
444  set_line_properties( aStream, CAIRO_LINE_JOIN_BEVEL, CAIRO_LINE_CAP_ROUND );
445 
446  cairo_move_to( aStream->cairoContext, aStream->downscale * (double) x1a, aStream->downscale * (double) y1a );
447  cairo_line_to( aStream->cairoContext, aStream->downscale * (double) x2a, aStream->downscale * (double) y2a );
448 
449  cairo_stroke( aStream->cairoContext );
450 
451  cairo_restore( aStream->cairoContext );
452 }
453 
454 //--------------------------------------------------------------------------
455 // plD_polyline_cairo()
456 //
457 // Draw a polyline in the current color.
458 //--------------------------------------------------------------------------
459 
460 void plD_polyline_cairo( PLStream *pls, short *xa, short *ya, PLINT npts )
461 {
462  PLCairo *aStream;
463 
464  aStream = (PLCairo *) pls->dev;
465 
466  cairo_save( aStream->cairoContext );
467 
468  set_line_properties( aStream, CAIRO_LINE_JOIN_BEVEL, CAIRO_LINE_CAP_BUTT );
469 
470  poly_line( pls, xa, ya, npts );
471 
472  cairo_stroke( aStream->cairoContext );
473 
474  cairo_restore( aStream->cairoContext );
475 }
476 
477 //--------------------------------------------------------------------------
478 // plD_eop_cairo()
479 //
480 // Generic end of page.
481 //--------------------------------------------------------------------------
482 
484 {
485  PLCairo *aStream;
486 
487  aStream = (PLCairo *) pls->dev;
488 
489  cairo_show_page( aStream->cairoContext );
490 }
491 
492 //--------------------------------------------------------------------------
493 // plD_tidy_cairo()
494 //
495 // General: Close graphics file or otherwise clean up.
496 //--------------------------------------------------------------------------
497 
499 {
500  PLCairo *aStream;
501 
502  aStream = (PLCairo *) pls->dev;
503 
504  // Free the cairo context and surface.
505  cairo_destroy( aStream->cairoContext );
506  cairo_surface_destroy( aStream->cairoSurface );
507 
508  plCloseFile( pls );
509 }
510 
511 //--------------------------------------------------------------------------
512 // plD_state_cairo()
513 //
514 // Handle change in PLStream state (color, pen width, fill attribute, etc).
515 //
516 // Nothing is done here because these attributes are acquired from
517 // PLStream for each element that is drawn.
518 //--------------------------------------------------------------------------
519 
521 {
522 }
523 
524 //--------------------------------------------------------------------------
525 // plD_esc_cairo()
526 //
527 // Generic escape function.
528 //--------------------------------------------------------------------------
529 
530 void plD_esc_cairo( PLStream *pls, PLINT op, void *ptr )
531 {
532  //PLCairo *aStream;
533 
534  //aStream = (PLCairo *) pls->dev;
535 
536  switch ( op )
537  {
538  case PLESC_FILL: // filled polygon
539  filled_polygon( pls, pls->dev_x, pls->dev_y, pls->dev_npts );
540  break;
541  case PLESC_GRADIENT: // render a gradient within a polygon.
542  gradient( pls, pls->dev_x, pls->dev_y, pls->dev_npts );
543  break;
544  case PLESC_HAS_TEXT:
545  if ( !pls->alt_unicode )
546  {
547  proc_str( pls, (EscText *) ptr );
548  }
549  break;
550  case PLESC_BEGIN_TEXT: // get ready to get a handle a string of text
551  text_begin_cairo( pls, (EscText *) ptr );
552  break;
553  case PLESC_TEXT_CHAR: // handle a character of text to display
554  text_char_cairo( pls, (EscText *) ptr );
555  break;
556  case PLESC_CONTROL_CHAR: // handle a control character (super/subscript of fontchange)
557  text_esc_cairo( pls, (EscText *) ptr );
558  break;
559  case PLESC_END_TEXT: // finish a string of text
560  text_end_cairo( pls, (EscText *) ptr );
561  break;
562  case PLESC_START_RASTERIZE: // Start offscreen/rasterized rendering
563  start_raster( pls );
564  break;
565  case PLESC_END_RASTERIZE: // End offscreen/rasterized rendering
566  end_raster( pls );
567  break;
568  case PLESC_ARC: // Draw an arc, either filled or outline
569  arc( pls, (arc_struct *) ptr );
570  break;
571  case PLESC_MODESET: // Set drawing mode
572  set_mode( pls, (int *) ptr );
573  break;
574  case PLESC_MODEGET: // Get drawing mode
575  get_mode( pls, (int *) ptr );
576  break;
577  }
578 }
579 
580 
581 //--------------------------------------------------------------------------
582 // set_mode
583 //
584 // Set drawing mode.
585 //--------------------------------------------------------------------------
586 void set_mode( PLStream *pls, PLINT *mode )
587 {
588  PLCairo *aStream;
589 
590  aStream = (PLCairo *) pls->dev;
591 
592  switch ( *mode )
593  {
594  case PL_DRAWMODE_UNKNOWN: // Invalid - do nothing
595  break;
596  case PL_DRAWMODE_DEFAULT:
597  cairo_set_operator( aStream->cairoContext, CAIRO_OPERATOR_OVER );
598  break;
599  case PL_DRAWMODE_REPLACE:
600  cairo_set_operator( aStream->cairoContext, CAIRO_OPERATOR_SOURCE );
601  break;
602  case PL_DRAWMODE_XOR:
603  cairo_set_operator( aStream->cairoContext, CAIRO_OPERATOR_XOR );
604  break;
605  }
606  return;
607 }
608 
609 //--------------------------------------------------------------------------
610 // get_mode
611 //
612 // Get drawing mode.
613 //--------------------------------------------------------------------------
614 void get_mode( PLStream *pls, PLINT *mode )
615 {
616  PLCairo *aStream;
617  cairo_operator_t op;
618 
619  aStream = (PLCairo *) pls->dev;
620 
621  op = cairo_get_operator( aStream->cairoContext );
622 
623  switch ( op )
624  {
625  case CAIRO_OPERATOR_OVER:
626  *mode = PL_DRAWMODE_DEFAULT;
627  break;
628  case CAIRO_OPERATOR_SOURCE:
629  *mode = PL_DRAWMODE_REPLACE;
630  break;
631  case CAIRO_OPERATOR_XOR:
632  *mode = PL_DRAWMODE_XOR;
633  break;
634  default:
635  *mode = PL_DRAWMODE_UNKNOWN;
636  }
637  return;
638 }
639 
640 //--------------------------------------------------------------------------
641 // text_begin_cairo()
642 //
643 // Begin text.
644 //--------------------------------------------------------------------------
645 
646 void text_begin_cairo( PLStream *pls, EscText *args )
647 {
648  PLCairo *aStream;
649 
650  aStream = (PLCairo *) pls->dev;
651  aStream->upDown = 0;
652  aStream->uline = 0;
653  aStream->level = 0;
654  aStream->pangoMarkupString = (char *) malloc( sizeof ( char ) * MAX_MARKUP_LEN );
655  // Calculate the font size (in points since DPI = 72).
656  aStream->fontSize = (float) ( pls->chrht * DPI / 25.4 );
657 
658  // Initialize the markup string array
659  memset( aStream->pangoMarkupString, 0, MAX_MARKUP_LEN );
660 
661  open_span_tag( aStream->pangoMarkupString, args->n_fci, aStream->fontSize, 0 );
662 }
663 
664 //--------------------------------------------------------------------------
665 // text_char_cairo()
666 //
667 // Add text.
668 //--------------------------------------------------------------------------
669 
670 void text_char_cairo( PLStream *pls, EscText *args )
671 {
672  char utf8[5];
673  PLCairo *aStream;
674 
675  aStream = (PLCairo *) pls->dev;
676  // make sure we are not too close to the end of the string
677  if ( strlen( aStream->pangoMarkupString ) < ( MAX_MARKUP_LEN - 50 ) )
678  {
679  switch ( args->n_char )
680  {
681  case 38:
682  strncat( aStream->pangoMarkupString, "&#38;", MAX_MARKUP_LEN - 1 - strlen( aStream->pangoMarkupString ) );
683  break;
684  case 60:
685  strncat( aStream->pangoMarkupString, "&#60;", MAX_MARKUP_LEN - 1 - strlen( aStream->pangoMarkupString ) );
686  break;
687  case 62:
688  strncat( aStream->pangoMarkupString, "&#62;", MAX_MARKUP_LEN - 1 - strlen( aStream->pangoMarkupString ) );
689  break;
690  default:
691  ucs4_to_utf8( args->n_char, utf8 );
692  strncat( aStream->pangoMarkupString, utf8, MAX_MARKUP_LEN - 1 - strlen( aStream->pangoMarkupString ) );
693  break;
694  }
695  }
696 }
697 
698 //--------------------------------------------------------------------------
699 // text_esc_cairo()
700 //
701 // A font change, superscript, subscript, etc...
702 //--------------------------------------------------------------------------
703 
704 void text_esc_cairo( PLStream *pls, EscText *args )
705 {
706  PLCairo *aStream;
707 
708  aStream = (PLCairo *) pls->dev;
709  switch ( args->n_ctrl_char )
710  {
711  case PLTEXT_FONTCHANGE:
712  close_span_tag( aStream->pangoMarkupString, aStream->upDown );
713  open_span_tag( aStream->pangoMarkupString, args->n_fci, aStream->fontSize, aStream->upDown );
714  break;
715  case PLTEXT_SUPERSCRIPT:
716  if ( aStream->upDown < 0 )
717  {
718  strncat( aStream->pangoMarkupString, "</span>", MAX_MARKUP_LEN - 1 - strlen( aStream->pangoMarkupString ) );
719  aStream->level++;
720  }
721  else
722  {
723  plP_script_scale( TRUE, &aStream->level,
724  &aStream->old_sscale, &aStream->sscale, &aStream->old_soffset, &aStream->soffset );
725  strncat( aStream->pangoMarkupString,
726  rise_span_tag( TRUE, aStream->fontSize, (float) aStream->sscale, (float) aStream->soffset ),
727  MAX_MARKUP_LEN - 1 - strlen( aStream->pangoMarkupString ) );
728  }
729  aStream->upDown++;
730  break;
731  case PLTEXT_SUBSCRIPT:
732  if ( aStream->upDown > 0 )
733  {
734  strncat( aStream->pangoMarkupString, "</span>", MAX_MARKUP_LEN - 1 - strlen( aStream->pangoMarkupString ) );
735  aStream->level--;
736  }
737  else
738  {
739  plP_script_scale( FALSE, &aStream->level,
740  &aStream->old_sscale, &aStream->sscale, &aStream->old_soffset, &aStream->soffset );
741  strncat( aStream->pangoMarkupString,
742  rise_span_tag( FALSE, aStream->fontSize, (float) aStream->sscale, (float) aStream->soffset ),
743  MAX_MARKUP_LEN - 1 - strlen( aStream->pangoMarkupString ) );
744  }
745  aStream->upDown--;
746  break;
747  case PLTEXT_UNDERLINE:
748  if ( aStream->uline == 1 )
749  {
750  strncat( aStream->pangoMarkupString, "</span>", MAX_MARKUP_LEN - 1 - strlen( aStream->pangoMarkupString ) );
751  aStream->level++;
752  }
753  else
754  {
755  strncat( aStream->pangoMarkupString, "<span underline=\"single\">", MAX_MARKUP_LEN - 1 - strlen( aStream->pangoMarkupString ) );
756  aStream->level++;
757  }
758  aStream->uline = !aStream->uline;
759  break;
760  case PLTEXT_BACKCHAR:
761  case PLTEXT_OVERLINE:
762  plwarn( "'-', and 'b/B' text escape sequences not processed." );
763  break;
764  }
765 }
766 
767 //--------------------------------------------------------------------------
768 // text_end_cairo()
769 //
770 // Draw the text and clean up.
771 //--------------------------------------------------------------------------
772 
773 void text_end_cairo( PLStream *pls, EscText *args )
774 {
775  int textXExtent, textYExtent, baseline;
776  PLFLT rotation, shear, stride, cos_rot, sin_rot, cos_shear, sin_shear;
777  cairo_matrix_t *cairoTransformMatrix;
778  cairo_font_options_t *cairoFontOptions;
779  PangoContext *context;
780  PangoLayout *layout;
781  PLCairo *aStream;
782 
783  aStream = (PLCairo *) pls->dev;
784 
785  set_current_context( pls );
786 
787  // Close the last span tag.
788  close_span_tag( aStream->pangoMarkupString, aStream->upDown );
789 
790  // printf("%s\n", aStream->pangoMarkupString);
791 
792  // Create the Pango text layout so we can figure out how big it is
793  layout = pango_cairo_create_layout( aStream->cairoContext );
794  pango_layout_set_markup( layout, aStream->pangoMarkupString, -1 );
795  pango_layout_get_pixel_size( layout, &textXExtent, &textYExtent );
796  baseline = pango_layout_get_baseline( layout );
797 
798  // If asked, set the string length (in mm) and return
799  if ( pls->get_string_length )
800  {
801  pls->string_length = (PLFLT) textXExtent * 25.4 / DPI;
802  }
803  else
804  {
805  // Set font aliasing
806  context = pango_layout_get_context( layout );
807  cairoFontOptions = cairo_font_options_create();
808  cairo_font_options_set_antialias( cairoFontOptions, aStream->text_anti_aliasing );
809  pango_cairo_context_set_font_options( context, cairoFontOptions );
810  pango_layout_context_changed( layout );
811  cairo_font_options_destroy( cairoFontOptions );
812 
813  // Save current transform matrix & clipping region
814  cairo_save( aStream->cairoContext );
815 
816  // Set up the clipping region if we are doing text clipping
817  if ( aStream->text_clipping )
818  {
819  set_clip( pls );
820  }
821 
822  // Move to the string reference point
823  cairo_move_to( aStream->cairoContext, aStream->downscale * (double) args->x, aStream->downscale * (double) args->y );
824 
825  // Invert the coordinate system so that the text is drawn right side up
826  cairoTransformMatrix = (cairo_matrix_t *) malloc( sizeof ( cairo_matrix_t ) );
827  cairo_matrix_init( cairoTransformMatrix, 1.0, 0.0, 0.0, -1.0, 0.0, 0.0 );
828  cairo_transform( aStream->cairoContext, cairoTransformMatrix );
829 
830  // Extract rotation angle and shear from the PLplot tranformation matrix.
831  // Compute sines and cosines of the angles as an optimization.
832  plRotationShear( args->xform, &rotation, &shear, &stride );
833  rotation -= pls->diorot * PI / 2.0;
834  cos_rot = cos( rotation );
835  sin_rot = sin( rotation );
836  cos_shear = cos( shear );
837  sin_shear = sin( shear );
838 
839  // Apply the transform matrix
840  cairo_matrix_init( cairoTransformMatrix,
841  cos_rot * stride,
842  -sin_rot * stride,
843  cos_rot * sin_shear + sin_rot * cos_shear,
844  -sin_rot * sin_shear + cos_rot * cos_shear,
845  0, 0 );
846  cairo_transform( aStream->cairoContext, cairoTransformMatrix );
847  free( cairoTransformMatrix );
848 
849  // Move to the text starting point
850  // printf("baseline %d %d\n", baseline, textYExtent);
851  cairo_rel_move_to( aStream->cairoContext,
852  (double) ( -1.0 * args->just * (double) textXExtent ),
853  (double) 0.5 * aStream->fontSize - baseline / 1024.0 );
854 
855  // Render the text
856  pango_cairo_show_layout( aStream->cairoContext, layout );
857 
858  // Restore the transform matrix to its state prior to the text transform.
859  cairo_restore( aStream->cairoContext );
860  }
861 
862  // Free the layout object and the markup string
863  g_object_unref( layout );
864  free( aStream->pangoMarkupString );
865 }
866 
867 //--------------------------------------------------------------------------
868 // proc_str()
869 //
870 // Processes strings for display.
871 //--------------------------------------------------------------------------
872 
873 void proc_str( PLStream *pls, EscText *args )
874 {
875  float fontSize;
876  int textXExtent, textYExtent, baseline;
877  char *textWithPangoMarkup;
878  PLFLT rotation, shear, stride, cos_rot, sin_rot, cos_shear, sin_shear;
879  cairo_matrix_t *cairoTransformMatrix;
880  cairo_font_options_t *cairoFontOptions;
881  PangoContext *context;
882  PangoLayout *layout;
883  PLCairo *aStream;
884 
885  aStream = (PLCairo *) pls->dev;
886 
887  set_current_context( pls );
888 
889  // Check that we got unicode, warning message and return if not
890  if ( args->unicode_array_len == 0 )
891  {
892  printf( "Non unicode string passed to a cairo driver, ignoring\n" );
893  return;
894  }
895 
896  // Check that unicode string isn't longer then the max we allow
897  if ( args->unicode_array_len >= MAX_STRING_LEN )
898  {
899  printf( "Sorry, the cairo drivers only handles strings of length < %d\n", MAX_STRING_LEN );
900  return;
901  }
902 
903  // Calculate the font size (in points since DPI = 72).
904  fontSize = (float) ( pls->chrht * DPI / 25.4 );
905 
906  // Convert the escape characters into the appropriate Pango markup
907  textWithPangoMarkup = ucs4_to_pango_markup_format( args->unicode_array, args->unicode_array_len, fontSize );
908 
909  // Create the Pango text layout so we can figure out how big it is
910  layout = pango_cairo_create_layout( aStream->cairoContext );
911  pango_layout_set_markup( layout, textWithPangoMarkup, -1 );
912  pango_layout_get_pixel_size( layout, &textXExtent, &textYExtent );
913  baseline = pango_layout_get_baseline( layout );
914 
915  // If asked, set the string length (in mm) and return
916  if ( pls->get_string_length )
917  {
918  pls->string_length = (PLFLT) textXExtent * 25.4 / DPI;
919  return;
920  }
921 
922  // Set font aliasing
923  context = pango_layout_get_context( layout );
924  cairoFontOptions = cairo_font_options_create();
925  cairo_font_options_set_antialias( cairoFontOptions, aStream->text_anti_aliasing );
926  pango_cairo_context_set_font_options( context, cairoFontOptions );
927  pango_layout_context_changed( layout );
928  cairo_font_options_destroy( cairoFontOptions );
929 
930  // Save current transform matrix & clipping region
931  cairo_save( aStream->cairoContext );
932 
933  // Set up the clipping region if we are doing text clipping
934  if ( aStream->text_clipping )
935  {
936  set_clip( pls );
937  }
938 
939  // Move to the string reference point
940  cairo_move_to( aStream->cairoContext, aStream->downscale * (double) args->x, aStream->downscale * (double) args->y );
941 
942  // Invert the coordinate system so that the text is drawn right side up
943  cairoTransformMatrix = (cairo_matrix_t *) malloc( sizeof ( cairo_matrix_t ) );
944  cairo_matrix_init( cairoTransformMatrix, 1.0, 0.0, 0.0, -1.0, 0.0, 0.0 );
945  cairo_transform( aStream->cairoContext, cairoTransformMatrix );
946 
947  // Extract rotation angle and shear from the PLplot tranformation matrix.
948  // Compute sines and cosines of the angles as an optimization.
949  plRotationShear( args->xform, &rotation, &shear, &stride );
950  rotation -= pls->diorot * PI / 2.0;
951  cos_rot = cos( rotation );
952  sin_rot = sin( rotation );
953  cos_shear = cos( shear );
954  sin_shear = sin( shear );
955 
956  // Apply the transform matrix
957  cairo_matrix_init( cairoTransformMatrix,
958  cos_rot * stride,
959  -sin_rot * stride,
960  cos_rot * sin_shear + sin_rot * cos_shear,
961  -sin_rot * sin_shear + cos_rot * cos_shear,
962  0, 0 );
963  cairo_transform( aStream->cairoContext, cairoTransformMatrix );
964  free( cairoTransformMatrix );
965 
966  // printf("baseline (ps) %d %d %f\n", baseline, textYExtent, aStream->fontSize);
967  // Move to the text starting point
968  cairo_rel_move_to( aStream->cairoContext,
969  (double) ( -1.0 * args->just * (double) textXExtent ),
970  (double) 0.5 * fontSize - baseline / 1024.0 );
971 
972  // Render the text
973  pango_cairo_show_layout( aStream->cairoContext, layout );
974 
975  // Restore the transform matrix to its state prior to the text transform.
976  cairo_restore( aStream->cairoContext );
977 
978  // Free the layout object and the markup string.
979  g_object_unref( layout );
980  free( textWithPangoMarkup );
981 }
982 
983 //--------------------------------------------------------------------------
984 // ucs4_to_pango_markup_format()
985 //
986 // Converts the plplot string (in ucs4) to a utf8 string that includes
987 // pango markup.
988 //
989 // http://developer.gnome.org/doc/API/2.0/pango/PangoMarkupFormat.html
990 //--------------------------------------------------------------------------
991 
992 char *ucs4_to_pango_markup_format( PLUNICODE *ucs4, int ucs4Len, float fontSize )
993 {
994  char plplotEsc;
995  int i;
996  int upDown = 0;
997  PLUNICODE fci;
998  char utf8[5];
999  char *pangoMarkupString;
1000  PLFLT old_sscale, sscale, old_soffset, soffset;
1001  PLINT level = 0;
1002  short uline = 0;
1003 
1004  // Will this be big enough? We might have lots of markup.
1005  pangoMarkupString = (char *) malloc( sizeof ( char ) * MAX_MARKUP_LEN );
1006  for ( i = 0; i < MAX_MARKUP_LEN; i++ )
1007  {
1008  pangoMarkupString[i] = 0;
1009  }
1010 
1011  // Get PLplot escape character
1012  plgesc( &plplotEsc );
1013 
1014  // Get the curent font and open the first span tag
1015  plgfci( &fci );
1016  open_span_tag( pangoMarkupString, fci, fontSize, 0 );
1017 
1018  // Parse the string to generate the tags
1019  i = 0;
1020  while ( i < ucs4Len )
1021  {
1022  // Try to avoid going off the end of the string
1023  if ( strlen( pangoMarkupString ) > ( MAX_MARKUP_LEN - 50 ) )
1024  {
1025  continue;
1026  }
1027  if ( ucs4[i] < PL_FCI_MARK ) // not a font change
1028  {
1029  if ( ucs4[i] != (PLUNICODE) plplotEsc ) // a character to display
1030  { // we have to handle "<", ">" and "&" separately since they throw off the XML
1031  switch ( ucs4[i] )
1032  {
1033  case 38:
1034  strncat( pangoMarkupString, "&#38;", MAX_MARKUP_LEN - 1 - strlen( pangoMarkupString ) );
1035  break;
1036  case 60:
1037  strncat( pangoMarkupString, "&#60;", MAX_MARKUP_LEN - 1 - strlen( pangoMarkupString ) );
1038  break;
1039  case 62:
1040  strncat( pangoMarkupString, "&#62;", MAX_MARKUP_LEN - 1 - strlen( pangoMarkupString ) );
1041  break;
1042  default:
1043  ucs4_to_utf8( ucs4[i], utf8 );
1044  strncat( pangoMarkupString, utf8, MAX_MARKUP_LEN - 1 - strlen( pangoMarkupString ) );
1045  break;
1046  }
1047  i++;
1048  continue;
1049  }
1050  i++;
1051  if ( ucs4[i] == (PLUNICODE) plplotEsc ) // a escape character to display
1052  {
1053  ucs4_to_utf8( ucs4[i], utf8 );
1054  strncat( pangoMarkupString, utf8, MAX_MARKUP_LEN - 1 - strlen( pangoMarkupString ) );
1055  i++;
1056  continue;
1057  }
1058  else
1059  {
1060  if ( ucs4[i] == (PLUNICODE) 'u' ) // Superscript
1061  {
1062  if ( upDown < 0 )
1063  {
1064  strncat( pangoMarkupString, "</span>", MAX_MARKUP_LEN - 1 - strlen( pangoMarkupString ) );
1065  level++;
1066  }
1067  else
1068  {
1069  plP_script_scale( TRUE, &level,
1070  &old_sscale, &sscale, &old_soffset, &soffset );
1071  strncat( pangoMarkupString,
1072  rise_span_tag( TRUE, fontSize, (float) sscale, (float) soffset ),
1073  MAX_MARKUP_LEN - 1 - strlen( pangoMarkupString ) );
1074  }
1075  upDown++;
1076  }
1077  if ( ucs4[i] == (PLUNICODE) 'd' ) // Subscript
1078  {
1079  if ( upDown > 0 )
1080  {
1081  strncat( pangoMarkupString, "</span>", MAX_MARKUP_LEN - 1 - strlen( pangoMarkupString ) );
1082  level--;
1083  }
1084  else
1085  {
1086  plP_script_scale( FALSE, &level,
1087  &old_sscale, &sscale, &old_soffset, &soffset );
1088  strncat( pangoMarkupString,
1089  rise_span_tag( FALSE, fontSize, (float) sscale, (float) soffset ),
1090  MAX_MARKUP_LEN - 1 - strlen( pangoMarkupString ) );
1091  }
1092  upDown--;
1093  }
1094  if ( ucs4[i] == (PLUNICODE) '-' ) // Superscript
1095  {
1096  if ( uline == 1 )
1097  {
1098  strncat( pangoMarkupString, "</span>", MAX_MARKUP_LEN - 1 - strlen( pangoMarkupString ) );
1099  level++;
1100  }
1101  else
1102  {
1103  strncat( pangoMarkupString,
1104  "<span underline=\"single\">",
1105  MAX_MARKUP_LEN - 1 - strlen( pangoMarkupString ) );
1106  }
1107  uline = uline;
1108  }
1109  i++;
1110  }
1111  }
1112  else // a font change
1113  {
1114  close_span_tag( pangoMarkupString, upDown );
1115  open_span_tag( pangoMarkupString, ucs4[i], fontSize, upDown );
1116  i++;
1117  }
1118  }
1119 
1120  // Close the last span tag.
1121  close_span_tag( pangoMarkupString, upDown );
1122 
1123  // printf("%s\n", pangoMarkupString);
1124 
1125  return pangoMarkupString;
1126 }
1127 
1128 //--------------------------------------------------------------------------
1129 // open_span_tag
1130 //
1131 // 1. Opens a span tag with the appropriate font description given the
1132 // current fci.
1133 // 2. Add the appropriate number of <sub> or <sup> tags to bring us
1134 // back to our current sub/super-script level.
1135 //--------------------------------------------------------------------------
1136 
1137 void open_span_tag( char *pangoMarkupString, PLUNICODE fci, float fontSize, int upDown )
1138 {
1139  unsigned char fontFamily, fontStyle, fontWeight;
1140  char openTag[TAG_LEN];
1141  int upDown_level;
1142  PLFLT old_sscale, sscale, old_soffset, soffset;
1143  PLINT level = 0.;
1144 
1145  // Generate the font info for the open tag & concatenate this
1146  // onto the markup string.
1147  plP_fci2hex( fci, &fontFamily, PL_FCI_FAMILY );
1148  plP_fci2hex( fci, &fontStyle, PL_FCI_STYLE );
1149  plP_fci2hex( fci, &fontWeight, PL_FCI_WEIGHT );
1150 
1151  // Check for unreasonable values and raise a warning
1152  if ( fontStyle >= 3 )
1153  {
1154  plwarn( "cairo: Unknown font style specified, forcing normal\n" );
1155  fontStyle = 0;
1156  }
1157  if ( fontWeight >= 2 )
1158  {
1159  plwarn( "cairo: Unknown font weight specified, forcing normal\n" );
1160  fontWeight = 0;
1161  }
1162 
1163  // From http://library.gnome.org/devel/pango/unstable/PangoMarkupFormat.html
1164  // size = font size in 1024ths of a point.
1165  snprintf( openTag, TAG_LEN, "<span font_desc=\"%s\" size=\"%d\" ", familyLookup[fontFamily], (int) ( fontSize * 1024. ) );
1166  strncat( pangoMarkupString, openTag, MAX_MARKUP_LEN - 1 - strlen( pangoMarkupString ) );
1167 
1168  snprintf( openTag, TAG_LEN, "style=\"%s\" ", styleLookup[fontStyle] );
1169  strncat( pangoMarkupString, openTag, MAX_MARKUP_LEN - 1 - strlen( pangoMarkupString ) );
1170 
1171  snprintf( openTag, TAG_LEN, "weight=\"%s\">", weightLookup[fontWeight] );
1172  strncat( pangoMarkupString, openTag, MAX_MARKUP_LEN - 1 - strlen( pangoMarkupString ) );
1173 
1174  // Move to the right superscript/subscript level
1175  for ( upDown_level = 0; upDown_level < upDown; upDown_level++ )
1176  {
1177  plP_script_scale( TRUE, &level,
1178  &old_sscale, &sscale, &old_soffset, &soffset );
1179  strncat( pangoMarkupString,
1180  rise_span_tag( TRUE, fontSize, (float) sscale, (float) soffset ),
1181  MAX_MARKUP_LEN - 1 - strlen( pangoMarkupString ) );
1182  }
1183  for ( upDown_level = 0; upDown_level > upDown; upDown_level-- )
1184  {
1185  plP_script_scale( FALSE, &level,
1186  &old_sscale, &sscale, &old_soffset, &soffset );
1187  strncat( pangoMarkupString,
1188  rise_span_tag( FALSE, fontSize, (float) sscale, (float) soffset ),
1189  MAX_MARKUP_LEN - 1 - strlen( pangoMarkupString ) );
1190  }
1191 }
1192 
1193 //--------------------------------------------------------------------------
1194 // close_span_tag
1195 //
1196 // Close a span tag & brings us down to zero sub/super-script level.
1197 //--------------------------------------------------------------------------
1198 
1199 void close_span_tag( char *pangoMarkupString, int upDown )
1200 {
1201  if ( upDown > 0 )
1202  {
1203  while ( upDown > 0 )
1204  {
1205  strncat( pangoMarkupString, "</span>", MAX_MARKUP_LEN - 1 - strlen( pangoMarkupString ) );
1206  upDown--;
1207  }
1208  }
1209  if ( upDown < 0 )
1210  {
1211  while ( upDown < 0 )
1212  {
1213  strncat( pangoMarkupString, "</span>", MAX_MARKUP_LEN - 1 - strlen( pangoMarkupString ) );
1214  upDown++;
1215  }
1216  }
1217 
1218  strncat( pangoMarkupString, "</span>", MAX_MARKUP_LEN - 1 - strlen( pangoMarkupString ) );
1219 }
1220 
1221 // 0.8 mimics the offset of first superscript/subscript level implemented
1222 // in plstr (plsym.c) for Hershey fonts. Indeed when comparing with
1223 // -dev xwin results this factor appears to offset the centers of the
1224 // letters appropriately (but not their edges since different font sizes
1225 // are involved).
1226 # define RISE_FACTOR 0.8
1227 
1228 //--------------------------------------------------------------------------
1229 // rise_span_tag
1230 //
1231 // Create a rise span tag w/ appropriate font size & baseline offset
1232 // fontSize is the baseline font size in points (1/72 of an inch),
1233 // multiplier is a scaling factor for that font size for superscript
1234 // or subscript, and rise is the vertical offset (in units of font
1235 // size) for that superscript or subscript.
1236 
1237 //--------------------------------------------------------------------------
1238 
1239 char *rise_span_tag( int ifsuperscript, float fontSize, float multiplier, float rise )
1240 {
1241  float offset;
1242  static char tag[100];
1243 
1244  // http://developer.gnome.org/pango/unstable/PangoMarkupFormat.html says
1245  // rise should be in units of 10000 em's, but empirical evidence shows
1246  // it is in units of 1024th of a point. Therefore, since FontSize
1247  // is in points, a rise of 1024. * fontSize corresponds a rise of
1248  // a full character height.
1249  rise = 1024.f * fontSize * (float) RISE_FACTOR * rise;
1250 
1251  // This is the correction for the difference between baseline and
1252  // middle coordinate systems. This offset should be
1253  // 0.5*(fontSize - superscript/subscript fontSize).
1254  offset = 1024.f * 0.5f * fontSize * ( 1.0f - multiplier );
1255 
1256  if ( ifsuperscript )
1257  {
1258  sprintf( tag, "<span rise=\"%d\" size=\"%d\">",
1259  (int) ( rise + offset ), (int) ( fontSize * 1024. * multiplier ) );
1260  }
1261  else
1262  {
1263  sprintf( tag, "<span rise=\"%d\" size=\"%d\">",
1264  (int) -( rise - offset ), (int) ( fontSize * 1024. * multiplier ) );
1265  }
1266 
1267  return ( tag );
1268 }
1269 
1270 //--------------------------------------------------------------------------
1271 // write_to_stream()
1272 //
1273 // Writes data to a open file stream. This function is passed to the
1274 // Cairo file IO devices.
1275 //--------------------------------------------------------------------------
1276 
1277 cairo_status_t write_to_stream( void *filePointer, unsigned char *data, unsigned int length )
1278 {
1279  unsigned int bytes_written;
1280 
1281  bytes_written = (unsigned int) fwrite( data, 1, (size_t) length, (FILE *) filePointer );
1282  if ( bytes_written == length )
1283  {
1284  return CAIRO_STATUS_SUCCESS;
1285  }
1286  else
1287  {
1288  return CAIRO_STATUS_WRITE_ERROR;
1289  }
1290 }
1291 
1292 //--------------------------------------------------------------------------
1293 // stream_and_font_setup()
1294 //
1295 // Initializes the PLStream structure for the cairo devices.
1296 // Initializes the font lookup table.
1297 // Checks for cairo specific user options.
1298 // Returns a new PLCairo structure.
1299 //--------------------------------------------------------------------------
1300 
1301 PLCairo *stream_and_font_setup( PLStream *pls, int interactive )
1302 {
1303  int i;
1304  char *a;
1305  PLCairo *aStream;
1306  PLFLT downscale;
1307  downscale = 0.0;
1308 
1309  // Stream setup
1310  pls->termin = interactive; // Interactive device
1311  pls->dev_flush = 1; // Handles flushes
1312  pls->color = 1; // Supports color
1313  pls->dev_text = 1; // Handles text
1314  pls->dev_unicode = 1; // Wants unicode text
1315  pls->dev_clear = 0;
1316  pls->alt_unicode = 1; // Wants to handle unicode character by character
1317  pls->page = 0;
1318  pls->dev_fill0 = 1; // Supports hardware solid fills
1319  pls->dev_gradient = 1; // driver renders gradient
1320  pls->dev_arc = 1; // Supports driver-level arcs
1321  pls->plbuf_write = interactive; // Activate plot buffer
1322  pls->has_string_length = 1; // Driver supports string length calculations
1323  pls->dev_modeset = 1; // Driver supports drawing mode setting
1324 
1325  if ( pls->xlength <= 0 || pls->ylength <= 0 )
1326  {
1327  pls->xlength = PLCAIRO_DEFAULT_X;
1328  pls->ylength = PLCAIRO_DEFAULT_Y;
1329  }
1330  // Calculate ratio of (smaller) external coordinates used for cairo
1331  // devices to (larger) internal PLplot coordinates.
1332  if ( pls->xlength > pls->ylength )
1333  downscale = (double) pls->xlength / (double) ( PIXELS_X - 1 );
1334  else
1335  downscale = (double) pls->ylength / (double) PIXELS_Y;
1336  plP_setphy( (PLINT) 0, (PLINT) ( pls->xlength / downscale ), (PLINT) 0, (PLINT) ( pls->ylength / downscale ) );
1337  plP_setpxl( DPI / 25.4 / downscale, DPI / 25.4 / downscale );
1338 
1339  // Initialize font table with either enviroment variables or defaults.
1340  // This was copied from the psttf driver.
1341  for ( i = 0; i < NPANGOLOOKUP; i++ )
1342  {
1343  if ( ( a = getenv( envFamilyLookup[i] ) ) != NULL )
1344  {
1345  strncpy( familyLookup[i], a, FAMILY_LOOKUP_LEN - 1 );
1346  familyLookup[i][FAMILY_LOOKUP_LEN - 1] = '\0';
1347  }
1348  else
1349  {
1350  strncpy( familyLookup[i], defaultFamilyLookup[i], FAMILY_LOOKUP_LEN - 1 );
1351  familyLookup[i][FAMILY_LOOKUP_LEN - 1] = '\0';
1352  }
1353  }
1354 
1355  // Allocate a cairo stream structure
1356  aStream = malloc( sizeof ( PLCairo ) );
1357 #if defined ( PLD_xcairo )
1358  aStream->XDisplay = NULL;
1359  aStream->XWindow = 0;
1360 #endif
1361  aStream->cairoSurface = NULL;
1362  aStream->cairoContext = NULL;
1363  aStream->downscale = downscale;
1364 
1365  // Set text clipping on by default since it makes little difference in
1366  // speed for a modern cairo stack.
1367  aStream->text_clipping = 1;
1368  text_clipping = 1;
1369  text_anti_aliasing = 0; // use 'default' text aliasing by default
1370  graphics_anti_aliasing = 0; // use 'default' graphics aliasing by default
1371  rasterize_image = 1; // Enable rasterization by default
1372  set_background = 0; // Default for extcairo is that PLplot not change the background
1373  image_buffering = 1; // Default to image-based buffered rendering
1374 
1375  // Check for cairo specific options
1376  plParseDrvOpts( cairo_options );
1377 
1378  // Turn off text clipping if the user desires this
1379  if ( !text_clipping )
1380  {
1381  aStream->text_clipping = 0;
1382  }
1383 
1384  // Record users desired text and graphics aliasing and rasterization
1385  aStream->text_anti_aliasing = (short) text_anti_aliasing;
1387  aStream->rasterize_image = (short) rasterize_image;
1388  aStream->set_background = (short) set_background;
1389  aStream->image_buffering = (short) image_buffering;
1390 
1391  return aStream;
1392 }
1393 
1394 //--------------------------------------------------------------------------
1395 // set_current_context()
1396 //
1397 // Updates the cairo graphics context with the current values in
1398 // PLStream.
1399 //--------------------------------------------------------------------------
1400 
1402 {
1403  PLCairo *aStream;
1404 
1405  aStream = (PLCairo *) pls->dev;
1406  cairo_set_source_rgba( aStream->cairoContext,
1407  (double) pls->curcolor.r / 255.0,
1408  (double) pls->curcolor.g / 255.0,
1409  (double) pls->curcolor.b / 255.0,
1410  (double) pls->curcolor.a );
1411  // In Cairo, zero width lines are not hairlines, they are completely invisible.
1412  if ( pls->width <= 0. )
1413  {
1414  cairo_set_line_width( aStream->cairoContext, 1.0 );
1415  }
1416  else
1417  {
1418  cairo_set_line_width( aStream->cairoContext, (double) pls->width );
1419  }
1420 }
1421 
1422 //--------------------------------------------------------------------------
1423 // poly_line()
1424 //
1425 // Draws a multi-segmented line. It is then up to the calling function
1426 // to decide whether to just draw the line, or fill in the area
1427 // enclosed by the line.
1428 //--------------------------------------------------------------------------
1429 
1430 void poly_line( PLStream *pls, short *xa, short *ya, PLINT npts )
1431 {
1432  int i;
1433  PLCairo *aStream;
1434 
1435  aStream = (PLCairo *) pls->dev;
1436 
1437  set_current_context( pls );
1438 
1439  cairo_move_to( aStream->cairoContext, aStream->downscale * (double) xa[0], aStream->downscale * (double) ya[0] );
1440  for ( i = 1; i < npts; i++ )
1441  {
1442  cairo_line_to( aStream->cairoContext, aStream->downscale * (double) xa[i], aStream->downscale * (double) ya[i] );
1443  }
1444 }
1445 
1446 //--------------------------------------------------------------------------
1447 // filled_polygon()
1448 //
1449 // Draws a filled polygon.
1450 //--------------------------------------------------------------------------
1451 
1452 void filled_polygon( PLStream *pls, short *xa, short *ya, PLINT npts )
1453 {
1454  PLCairo *aStream;
1455 
1456  aStream = (PLCairo *) pls->dev;
1457 
1458  cairo_save( aStream->cairoContext );
1459 
1460  // Draw the polygons
1461  poly_line( pls, xa, ya, npts );
1462 
1463  cairo_set_source_rgba( aStream->cairoContext,
1464  (double) pls->curcolor.r / 255.0,
1465  (double) pls->curcolor.g / 255.0,
1466  (double) pls->curcolor.b / 255.0,
1467  (double) pls->curcolor.a );
1468 
1469  if ( cairo_get_antialias( aStream->cairoContext ) != CAIRO_ANTIALIAS_NONE )
1470  {
1471  cairo_fill_preserve( aStream->cairoContext );
1472 
1473  // These line properties make for a nicer looking polygon mesh
1474  set_line_properties( aStream, CAIRO_LINE_JOIN_BEVEL, CAIRO_LINE_CAP_BUTT );
1475  // Comment out the following call to cairo_set_line width
1476  // since the hard-coded width value of 1.0 is not appropriate
1477  // for fills of small areas. Instead, use the line width that
1478  // has already been set by the user via the above call of
1479  // poly_line which in turn calls set_current_context which in
1480  // turn calls cairo_set_line_width for the user-specified
1481  // width.
1482  // cairo_set_line_width( aStream->cairoContext, 1.0 );
1483  cairo_stroke( aStream->cairoContext );
1484  }
1485  else
1486  {
1487  cairo_fill( aStream->cairoContext );
1488  }
1489 
1490  cairo_restore( aStream->cairoContext );
1491 }
1492 
1493 //--------------------------------------------------------------------------
1494 // gradient()
1495 //
1496 // Render a gradient within a polygon.
1497 //--------------------------------------------------------------------------
1498 
1499 void gradient( PLStream *pls, short *xa, short *ya, PLINT npts )
1500 {
1501  int i;
1502  PLCairo *aStream;
1503  cairo_pattern_t *linear_gradient;
1504 
1505  aStream = (PLCairo *) pls->dev;
1506 
1507  // These line properties make for a nicer looking polygon mesh
1508  set_line_properties( aStream, CAIRO_LINE_JOIN_BEVEL, CAIRO_LINE_CAP_BUTT );
1509 
1510  linear_gradient = cairo_pattern_create_linear(
1511  aStream->downscale * pls->xgradient[0],
1512  aStream->downscale * pls->ygradient[0],
1513  aStream->downscale * pls->xgradient[1],
1514  aStream->downscale * pls->ygradient[1] );
1515 
1516  cairo_pattern_reference( linear_gradient );
1517  for ( i = 0; i < pls->ncol1; i++ )
1518  {
1519  cairo_pattern_add_color_stop_rgba( linear_gradient,
1520  (double) i / (double) ( pls->ncol1 - 1 ),
1521  (double) pls->cmap1[i].r / 255.,
1522  (double) pls->cmap1[i].g / 255.,
1523  (double) pls->cmap1[i].b / 255.,
1524  (double) pls->cmap1[i].a );
1525  }
1526 
1527  // Draw the polygon using the gradient.
1528  poly_line( pls, xa, ya, npts );
1529 
1530  cairo_set_source( aStream->cairoContext, linear_gradient );
1531  cairo_fill( aStream->cairoContext );
1532  cairo_pattern_destroy( linear_gradient );
1533 }
1534 
1535 //--------------------------------------------------------------------------
1536 // set_clip()
1537 //
1538 // Set the clipping region to the plot window.
1539 // NOTE: cairo_save() and cairo_restore() should probably be called before
1540 // and after this, respectively.
1541 //--------------------------------------------------------------------------
1542 
1543 void set_clip( PLStream *pls )
1544 {
1545  PLINT rcx[4], rcy[4];
1546  PLCairo *aStream;
1547  aStream = (PLCairo *) pls->dev;
1548 
1549  // Use PLplot core routine to get the corners of the clipping rectangle
1550  difilt_clip( rcx, rcy );
1551 
1552  // Layout the bounds of the clipping region
1553  // Should we convert PLINT to short and use the polyline routine?
1554  cairo_move_to( aStream->cairoContext,
1555  aStream->downscale * (double) rcx[0],
1556  aStream->downscale * (double) rcy[0] );
1557  cairo_line_to( aStream->cairoContext,
1558  aStream->downscale * (double) rcx[1],
1559  aStream->downscale * (double) rcy[1] );
1560  cairo_line_to( aStream->cairoContext,
1561  aStream->downscale * (double) rcx[2],
1562  aStream->downscale * (double) rcy[2] );
1563  cairo_line_to( aStream->cairoContext,
1564  aStream->downscale * (double) rcx[3],
1565  aStream->downscale * (double) rcy[3] );
1566  cairo_line_to( aStream->cairoContext,
1567  aStream->downscale * (double) rcx[0],
1568  aStream->downscale * (double) rcy[0] );
1569 
1570  // Set the clipping region
1571  cairo_clip( aStream->cairoContext );
1572 
1573  // Apparently, in some older Cairo versions, cairo_clip does not consume
1574  // the current path.
1575  cairo_new_path( aStream->cairoContext );
1576 }
1577 
1578 //--------------------------------------------------------------------------
1579 // cairo_family_check ()
1580 //
1581 // support function to help supress more than one page if family file
1582 // output not specified by the user (e.g., with the -fam command-line option).
1583 //--------------------------------------------------------------------------
1584 
1586 {
1587  if ( pls->family || pls->page == 1 )
1588  {
1589  return 0;
1590  }
1591  else
1592  {
1593  if ( !already_warned )
1594  {
1595  already_warned = 1;
1596  plwarn( "All pages after the first skipped because family file output not specified.\n" );
1597  }
1598  return 1;
1599  }
1600 }
1601 
1602 //--------------------------------------------------------------------------
1603 // arc()
1604 //
1605 // Draws an arc, possibly filled.
1606 //--------------------------------------------------------------------------
1607 
1608 void arc( PLStream *pls, arc_struct *arc_info )
1609 {
1610  PLCairo *aStream;
1611  double x, y, a, b;
1612  double angle1, angle2, rotate;
1613 
1614  set_current_context( pls );
1615 
1616  aStream = (PLCairo *) pls->dev;
1617 
1618  // Scale to the proper Cairo coordinates
1619  x = aStream->downscale * arc_info->x;
1620  y = aStream->downscale * arc_info->y;
1621  a = aStream->downscale * arc_info->a;
1622  b = aStream->downscale * arc_info->b;
1623 
1624  // Degrees to radians
1625  angle1 = arc_info->angle1 * M_PI / 180.0;
1626  angle2 = arc_info->angle2 * M_PI / 180.0;
1627  rotate = arc_info->rotate * M_PI / 180.0;
1628 
1629  cairo_save( aStream->cairoContext );
1630 
1631  // Clip the output to the plotting window
1632  set_clip( pls );
1633 
1634  // Make sure the arc is properly shaped and oriented
1635  cairo_save( aStream->cairoContext );
1636  cairo_translate( aStream->cairoContext, x, y );
1637  cairo_rotate( aStream->cairoContext, rotate );
1638  cairo_scale( aStream->cairoContext, a, b );
1639  cairo_arc( aStream->cairoContext, 0.0, 0.0, 1.0, angle1, angle2 );
1640  if ( arc_info->fill )
1641  cairo_line_to( aStream->cairoContext, 0.0, 0.0 );
1642  cairo_restore( aStream->cairoContext );
1643 
1644  cairo_set_source_rgba( aStream->cairoContext,
1645  (double) pls->curcolor.r / 255.0,
1646  (double) pls->curcolor.g / 255.0,
1647  (double) pls->curcolor.b / 255.0,
1648  (double) pls->curcolor.a );
1649  if ( arc_info->fill )
1650  {
1651  cairo_fill( aStream->cairoContext );
1652  }
1653  else
1654  {
1655  cairo_stroke( aStream->cairoContext );
1656  }
1657  cairo_restore( aStream->cairoContext );
1658 }
1659 
1660 //--------------------------------------------------------------------------
1661 // rotate_cairo_surface()
1662 //
1663 // Rotates the cairo surface to the appropriate orientation.
1664 //--------------------------------------------------------------------------
1665 
1666 void rotate_cairo_surface( PLStream *pls, float x11, float x12, float x21, float x22, float x0, float y0, PLBOOL is_xcairo )
1667 {
1668  cairo_matrix_t *matrix;
1669  PLCairo *aStream;
1670 
1671  aStream = (PLCairo *) pls->dev;
1672 
1673  matrix = (cairo_matrix_t *) malloc( sizeof ( cairo_matrix_t ) );
1674  cairo_matrix_init( matrix, x11, x12, x21, x22, x0, y0 );
1675 #if defined ( PLD_xcairo )
1676  if ( is_xcairo )
1677  {
1678  cairo_transform( aStream->cairoContext_X, matrix );
1679  }
1680  else
1681  {
1682  cairo_transform( aStream->cairoContext, matrix );
1683  }
1684 #else
1685  cairo_transform( aStream->cairoContext, matrix );
1686 #endif
1687  free( matrix );
1688 }
1689 
1690 //--------------------------------------------------------------------------
1691 //--------------------------------------------------------------------------
1692 //
1693 // That which is common to all familying Cairo Drivers
1694 //
1695 //--------------------------------------------------------------------------
1696 //--------------------------------------------------------------------------
1697 #if defined ( PLD_pngcairo ) || defined ( PLD_svgcairo ) || defined ( PLD_epscairo )
1698 
1699 void plD_bop_cairo_fam( PLStream * );
1700 void plD_eop_cairo_fam( PLStream * );
1701 void plD_state_cairo_fam( PLStream *, PLINT );
1702 void plD_esc_cairo_fam( PLStream *, PLINT, void * );
1703 void plD_tidy_cairo_fam( PLStream * );
1704 void plD_line_cairo_fam( PLStream *, short, short, short, short );
1705 void plD_polyline_cairo_fam( PLStream *, short *, short *, PLINT );
1706 
1707 //--------------------------------------------------------------------------
1708 // plD_bop_cairo_fam()
1709 //
1710 // Familying Devices: Set up for the next page.
1711 //--------------------------------------------------------------------------
1712 
1713 void plD_bop_cairo_fam( PLStream *pls )
1714 {
1715  PLCairo *aStream;
1716 
1717  // Plot familying stuff. Not really understood, just copying gd.c
1718  plGetFam( pls );
1719 
1720  aStream = (PLCairo *) pls->dev;
1721 
1722  pls->famadv = 1;
1723  pls->page++;
1724 
1725  // Suppress multi-page output if family file output is not
1726  // specified by the user.
1727  if ( cairo_family_check( pls ) )
1728  {
1729  return;
1730  }
1731 
1732  // Fill in the window with the background color.
1733  cairo_rectangle( aStream->cairoContext, 0.0, 0.0, pls->xlength, pls->ylength );
1734  cairo_set_source_rgba( aStream->cairoContext,
1735  (double) pls->cmap0[0].r / 255.0,
1736  (double) pls->cmap0[0].g / 255.0,
1737  (double) pls->cmap0[0].b / 255.0,
1738  (double) pls->cmap0[0].a );
1739  cairo_fill( aStream->cairoContext );
1740 }
1741 
1742 //--------------------------------------------------------------------------
1743 // plD_eop_cairo()
1744 //
1745 // End of page.
1746 //--------------------------------------------------------------------------
1747 
1748 void plD_eop_cairo_fam( PLStream *pls )
1749 {
1750  if ( cairo_family_check( pls ) )
1751  {
1752  return;
1753  }
1754 
1755  plD_eop_cairo( pls );
1756 }
1757 
1758 //--------------------------------------------------------------------------
1759 // plD_state_cairo_fam()
1760 //
1761 // Handle change in PLStream state (color, pen width, fill attribute, etc).
1762 //--------------------------------------------------------------------------
1763 
1764 void plD_state_cairo_fam( PLStream *pls, PLINT op )
1765 {
1766  if ( cairo_family_check( pls ) )
1767  {
1768  return;
1769  }
1770 
1771  plD_state_cairo( pls, op );
1772 }
1773 
1774 //--------------------------------------------------------------------------
1775 // plD_esc_cairo_fam()
1776 //
1777 // Generic escape function.
1778 //--------------------------------------------------------------------------
1779 
1780 void plD_esc_cairo_fam( PLStream *pls, PLINT op, void *ptr )
1781 {
1782  if ( cairo_family_check( pls ) )
1783  {
1784  return;
1785  }
1786 
1787  plD_esc_cairo( pls, op, ptr );
1788 }
1789 
1790 //--------------------------------------------------------------------------
1791 // plD_tidy_cairo_fam()
1792 //
1793 // Close graphics file or otherwise clean up.
1794 //--------------------------------------------------------------------------
1795 
1796 void plD_tidy_cairo_fam( PLStream *pls )
1797 {
1798  plD_tidy_cairo( pls );
1799 }
1800 
1801 //--------------------------------------------------------------------------
1802 // plD_line_cairo_fam()
1803 //
1804 // Draw a line.
1805 //--------------------------------------------------------------------------
1806 
1807 void plD_line_cairo_fam( PLStream *pls, short x1a, short y1a, short x2a, short y2a )
1808 {
1809  if ( cairo_family_check( pls ) )
1810  {
1811  return;
1812  }
1813 
1814  plD_line_cairo( pls, x1a, y1a, x2a, y2a );
1815 }
1816 
1817 //--------------------------------------------------------------------------
1818 // plD_polyline_cairo_fam()
1819 //
1820 // Draw a polyline in the current color.
1821 //--------------------------------------------------------------------------
1822 
1823 void plD_polyline_cairo_fam( PLStream *pls, short *xa, short *ya, PLINT npts )
1824 {
1825  if ( cairo_family_check( pls ) )
1826  {
1827  return;
1828  }
1829 
1830  plD_polyline_cairo( pls, xa, ya, npts );
1831 }
1832 
1833 #endif
1834 //--------------------------------------------------------------------------
1835 //--------------------------------------------------------------------------
1836 //
1837 // That which is specific to the xcairo driver.
1838 //
1839 //--------------------------------------------------------------------------
1840 //--------------------------------------------------------------------------
1841 
1842 #if defined ( PLD_xcairo )
1843 
1844 static int XScreen;
1845 static Window rootWindow;
1846 
1848 void plD_init_xcairo( PLStream * );
1849 void plD_bop_xcairo( PLStream * );
1850 void plD_eop_xcairo( PLStream * );
1851 void plD_tidy_xcairo( PLStream * );
1852 void plD_wait_xcairo( PLStream * );
1853 void plD_esc_xcairo( PLStream *, PLINT, void * );
1854 static void xcairo_get_cursor( PLStream *, PLGraphicsIn * );
1855 
1856 //--------------------------------------------------------------------------
1857 // plD_dispatch_init_xcairo()
1858 //
1859 // xcairo dispatch table initialization.
1860 //--------------------------------------------------------------------------
1861 
1863 {
1864 #ifndef ENABLE_DYNDRIVERS
1865  pdt->pl_MenuStr = "Cairo X Windows Driver";
1866  pdt->pl_DevName = "xcairo";
1867 #endif
1869  pdt->pl_seq = 100;
1870  pdt->pl_init = (plD_init_fp) plD_init_xcairo;
1873  pdt->pl_eop = (plD_eop_fp) plD_eop_xcairo;
1874  pdt->pl_bop = (plD_bop_fp) plD_bop_xcairo;
1875  pdt->pl_tidy = (plD_tidy_fp) plD_tidy_xcairo;
1877  pdt->pl_esc = (plD_esc_fp) plD_esc_xcairo;
1878  pdt->pl_wait = (plD_wait_fp) plD_wait_xcairo;
1879 }
1880 
1881 //--------------------------------------------------------------------------
1882 // xcairo_init_cairo()
1883 //
1884 // Configures Cairo to use whichever X Drawable is set up in the given
1885 // stream. This is called by plD_init_xcairo() in the event we are
1886 // drawing into a plplot-managed window, and plD_esc_xcairo() if
1887 // we are using an external X Drawable.
1888 //
1889 // A return value of 0 indicates success. Currently this function only
1890 // returns 0.
1891 //--------------------------------------------------------------------------
1892 
1893 static signed int xcairo_init_cairo( PLStream *pls )
1894 {
1895  PLCairo *aStream;
1896  Visual *defaultVisual;
1897 
1898  aStream = (PLCairo *) pls->dev;
1899 
1900  // Create an cairo surface & context that are associated with the X window.
1901  defaultVisual = DefaultVisual( aStream->XDisplay, 0 );
1902 
1903  // Dimension units are pixels from cairo documentation.
1904  // This is the X window Cairo surface.
1905  aStream->cairoSurface_X = cairo_xlib_surface_create(
1906  aStream->XDisplay,
1907  aStream->XWindow,
1908  defaultVisual,
1909  pls->xlength,
1910  pls->ylength );
1911 
1912  aStream->cairoContext_X = cairo_create( aStream->cairoSurface_X );
1913 
1914  // This is the Cairo surface PLplot will actually plot to.
1915  if ( aStream->image_buffering == 0 )
1916  {
1917  aStream->cairoSurface = cairo_surface_create_similar(
1918  aStream->cairoSurface_X,
1919  CAIRO_CONTENT_COLOR_ALPHA,
1920  pls->xlength,
1921  pls->ylength );
1922 
1923  aStream->cairoContext = cairo_create( aStream->cairoSurface );
1924  }
1925  else
1926  {
1927  // Plot to an off-screen image
1928  aStream->cairoSurface =
1929  cairo_image_surface_create(
1930  CAIRO_FORMAT_ARGB32,
1931  pls->xlength,
1932  pls->ylength );
1933  aStream->cairoContext = cairo_create( aStream->cairoSurface );
1934  }
1935 
1936  // Invert the surface so that the graphs are drawn right side up.
1937  rotate_cairo_surface( pls, 1.0, 0.0, 0.0, -1.0, 0.0, (float) pls->ylength, TRUE );
1938 
1939  // Set graphics aliasing
1940  cairo_set_antialias( aStream->cairoContext, aStream->graphics_anti_aliasing );
1941 
1942  // Set fill rule for the case of self-intersecting boundaries.
1943  if ( pls->dev_eofill )
1944  cairo_set_fill_rule( aStream->cairoContext, CAIRO_FILL_RULE_EVEN_ODD );
1945  else
1946  cairo_set_fill_rule( aStream->cairoContext, CAIRO_FILL_RULE_WINDING );
1947 
1948  // Fill in the X window with the background color to avoid starting out
1949  // with a blank window of an unexpected color.
1950  cairo_rectangle( aStream->cairoContext_X, 0.0, 0.0, pls->xlength, pls->ylength );
1951  cairo_set_source_rgba( aStream->cairoContext_X,
1952  (double) pls->cmap0[0].r / 255.0,
1953  (double) pls->cmap0[0].g / 255.0,
1954  (double) pls->cmap0[0].b / 255.0,
1955  (double) pls->cmap0[0].a );
1956  cairo_fill( aStream->cairoContext_X );
1957 
1958  XFlush( aStream->XDisplay );
1959 
1960  return 0;
1961 }
1962 
1963 //--------------------------------------------------------------------------
1964 // plD_init_xcairo()
1965 //
1966 // Initialize Cairo X Windows device.
1967 //--------------------------------------------------------------------------
1968 
1969 void plD_init_xcairo( PLStream *pls )
1970 {
1971  PLCairo *aStream;
1972  Atom wmDelete;
1973 
1974  // Setup the PLStream and the font lookup table.
1975  aStream = stream_and_font_setup( pls, 1 );
1976 
1977  // Save the pointer to the structure in the PLplot stream
1978  pls->dev = aStream;
1979 
1980  // Create a X Window if required.
1981  if ( external_drawable != 0 )
1982  {
1983  aStream->xdrawable_mode = 1;
1984  }
1985  else
1986  {
1987  // X Windows setup
1988  aStream->XDisplay = NULL;
1989  if ( pls->FileName != NULL )
1990  aStream->XDisplay = XOpenDisplay( pls->FileName );
1991  else
1992  aStream->XDisplay = XOpenDisplay( NULL );
1993  if ( aStream->XDisplay == NULL )
1994  {
1995  plexit( "Failed to open X Windows display\n" );
1996  // some sort of error here
1997  }
1998  XScreen = DefaultScreen( aStream->XDisplay );
1999  rootWindow = RootWindow( aStream->XDisplay, XScreen );
2000 
2001  aStream->XWindow = XCreateSimpleWindow(
2002  aStream->XDisplay,
2003  rootWindow, 0, 0,
2004  (unsigned int) pls->xlength,
2005  (unsigned int) pls->ylength,
2006  1,
2007  BlackPixel( aStream->XDisplay, XScreen ),
2008  BlackPixel( aStream->XDisplay, XScreen ) );
2009 
2010  XStoreName( aStream->XDisplay, aStream->XWindow, pls->plwindow );
2011  XSelectInput( aStream->XDisplay, aStream->XWindow, NoEventMask );
2012  XMapWindow( aStream->XDisplay, aStream->XWindow );
2013  aStream->xdrawable_mode = 0;
2014 
2015  wmDelete = XInternAtom( aStream->XDisplay, "WM_DELETE_WINDOW", True );
2016  XSetWMProtocols( aStream->XDisplay, aStream->XWindow, &wmDelete, 1 );
2017 
2018  xcairo_init_cairo( pls );
2019  }
2020 
2021  aStream->exit_event_loop = 0;
2022 }
2023 
2024 //--------------------------------------------------------------------------
2025 // blit_to_x()
2026 //
2027 //
2028 // Blit the offscreen image to the X window.
2029 //--------------------------------------------------------------------------
2030 
2031 void blit_to_x( PLStream *pls, double x, double y, double w, double h )
2032 {
2033  PLCairo *aStream;
2034 
2035  aStream = pls->dev;
2036 
2037  cairo_save( aStream->cairoContext );
2038  // "Flatten" any transparent regions to look like they were drawn over the
2039  // correct background color
2040  cairo_rectangle( aStream->cairoContext, x, y, w, h );
2041  cairo_set_operator( aStream->cairoContext, CAIRO_OPERATOR_DEST_OVER );
2042  cairo_set_source_rgba( aStream->cairoContext,
2043  (double) pls->cmap0[0].r / 255.0,
2044  (double) pls->cmap0[0].g / 255.0,
2045  (double) pls->cmap0[0].b / 255.0,
2046  (double) pls->cmap0[0].a );
2047  cairo_fill( aStream->cairoContext );
2048  cairo_restore( aStream->cairoContext );
2049 
2050  cairo_save( aStream->cairoContext_X );
2051  // Copy a portion of the surface
2052  cairo_rectangle( aStream->cairoContext_X, x, y, w, h );
2053  cairo_set_operator( aStream->cairoContext_X, CAIRO_OPERATOR_SOURCE );
2054  cairo_set_source_surface( aStream->cairoContext_X,
2055  aStream->cairoSurface, 0.0, 0.0 );
2056  cairo_fill( aStream->cairoContext_X );
2057  cairo_restore( aStream->cairoContext_X );
2058 }
2059 
2060 //--------------------------------------------------------------------------
2061 // plD_bop_xcairo()
2062 //
2063 // X Windows specific start of page.
2064 //--------------------------------------------------------------------------
2065 
2066 void plD_bop_xcairo( PLStream *pls )
2067 {
2068  PLCairo *aStream;
2069 
2070  aStream = (PLCairo *) pls->dev;
2071 
2072  plD_bop_cairo( pls );
2073 
2074  if ( aStream->xdrawable_mode )
2075  return;
2076 
2077  XFlush( aStream->XDisplay );
2078 }
2079 
2080 //--------------------------------------------------------------------------
2081 // plD_eop_xcairo()
2082 //
2083 // X Windows specific end of page.
2084 //--------------------------------------------------------------------------
2085 
2086 void plD_eop_xcairo( PLStream *pls )
2087 {
2088  PLCairo *aStream;
2089 
2090  aStream = (PLCairo *) pls->dev;
2091 
2092  // Blit the offscreen image to the X window.
2093  blit_to_x( pls, 0.0, 0.0, pls->xlength, pls->ylength );
2094 }
2095 
2096 //--------------------------------------------------------------------------
2097 // plD_tidy_xcairo()
2098 //
2099 // X Windows: close graphics file or otherwise clean up.
2100 //--------------------------------------------------------------------------
2101 
2102 void plD_tidy_xcairo( PLStream *pls )
2103 {
2104  PLCairo *aStream;
2105 
2106  aStream = (PLCairo *) pls->dev;
2107 
2108  plD_tidy_cairo( pls );
2109 
2110  // Also free up the Cairo X surface and context
2111  cairo_destroy( aStream->cairoContext_X );
2112  cairo_surface_destroy( aStream->cairoSurface_X );
2113 
2114  if ( aStream->xdrawable_mode )
2115  return;
2116 
2117  // Close the window and the display.
2118  XFlush( aStream->XDisplay );
2119 
2120  XDestroyWindow( aStream->XDisplay, aStream->XWindow );
2121 
2122  XCloseDisplay( aStream->XDisplay );
2123 }
2124 
2125 //--------------------------------------------------------------------------
2126 // plD_wait_xcairo()
2127 //
2128 // Wait for user input
2129 //--------------------------------------------------------------------------
2130 
2131 void plD_wait_xcairo( PLStream *pls )
2132 {
2133  PLCairo *aStream;
2134  long event_mask;
2135  char event_string[10];
2136  int number_chars;
2137  KeySym keysym;
2138  XComposeStatus cs;
2139  XEvent event;
2140  XExposeEvent *expose;
2141 
2142  aStream = (PLCairo *) pls->dev;
2143 
2144  if ( aStream->xdrawable_mode )
2145  return;
2146 
2147  aStream->exit_event_loop = 0;
2148 
2149  // Loop, handling selected events, till the user elects to close the plot.
2150  event_mask = ButtonPressMask | KeyPressMask | ExposureMask;
2151  XSelectInput( aStream->XDisplay, aStream->XWindow, event_mask );
2152  while ( !aStream->exit_event_loop )
2153  {
2154  //XWindowEvent( aStream->XDisplay, aStream->XWindow, event_mask, &event );
2155  XNextEvent( aStream->XDisplay, &event );
2156  switch ( event.type )
2157  {
2158  case KeyPress:
2159  number_chars = XLookupString( (XKeyEvent *) &event, event_string, 10, &keysym, &cs );
2160  event_string[number_chars] = '\0';
2161  if ( keysym == XK_Return )
2162  {
2163  aStream->exit_event_loop = 1;
2164  }
2165  break;
2166  case ButtonPress:
2167  if ( ( (XButtonEvent *) &event )->button == Button3 )
2168  aStream->exit_event_loop = 1;
2169  break;
2170  case ClientMessage:
2171  // plexit("X Window closed");
2172  pls->stream_closed = TRUE;
2173  aStream->exit_event_loop = 1;
2174  break;
2175  case Expose:
2176  // Blit the image again after an expose event, but only for the last
2177  // available event. Otherwise multiple redraws occur needlessly.
2178  expose = (XExposeEvent *) &event;
2179  if ( expose->count == 0 )
2180  {
2181  blit_to_x( pls, expose->x, expose->y,
2182  expose->width, expose->height );
2183  }
2184  break;
2185  }
2186  }
2187  aStream->exit_event_loop = 0;
2188 }
2189 
2190 //--------------------------------------------------------------------------
2191 // plD_esc_xcairo()
2192 //
2193 // Escape function, specialized for the xcairo driver
2194 //--------------------------------------------------------------------------
2195 
2196 void plD_esc_xcairo( PLStream *pls, PLINT op, void *ptr )
2197 {
2198  PLCairo *aStream;
2199 
2200  aStream = (PLCairo *) pls->dev;
2201 
2202  switch ( op )
2203  {
2204  case PLESC_FLUSH: // forced update of the window
2205  blit_to_x( pls, 0.0, 0.0, pls->xlength, pls->ylength );
2206  XFlush( aStream->XDisplay );
2207  break;
2208  case PLESC_GETC: // get cursor position
2209  blit_to_x( pls, 0.0, 0.0, pls->xlength, pls->ylength );
2210  XFlush( aStream->XDisplay );
2211  xcairo_get_cursor( pls, (PLGraphicsIn *) ptr );
2212  break;
2213  case PLESC_DEVINIT: { // Set external drawable
2214  Window rootwin;
2215  PLXcairoDrawableInfo *xinfo = (PLXcairoDrawableInfo *) ptr;
2216  signed int x, y;
2217  unsigned int w, h, b, d;
2218  if ( xinfo == NULL )
2219  {
2220  printf( "xcairo: PLESC_DEVINIT ignored, no drawable info provided\n" );
2221  return;
2222  }
2223  if ( aStream->xdrawable_mode == 0 )
2224  {
2225  printf( "xcairo: PLESC_DEVINIT called with drawable but stream not in xdrawable mode\n" );
2226  return;
2227  }
2228  aStream->XDisplay = xinfo->display;
2229  aStream->XWindow = xinfo->drawable;
2230 
2231  // Ensure plplot knows the real dimensions of the drawable
2232  XGetGeometry( aStream->XDisplay, aStream->XWindow, &rootwin,
2233  &x, &y, &w, &h, &b, &d );
2234  pls->xlength = (PLINT) w;
2235  pls->ylength = (PLINT) h;
2236  // Calculate ratio of (smaller) external coordinates used for cairo
2237  // devices to (larger) internal PLplot coordinates.
2238  if ( pls->xlength > pls->ylength )
2239  aStream->downscale = (double) pls->xlength / (double) ( PIXELS_X - 1 );
2240  else
2241  aStream->downscale = (double) pls->ylength / (double) PIXELS_Y;
2242  plP_setphy( (PLINT) 0, (PLINT) ( pls->xlength / aStream->downscale ), (PLINT) 0,
2243  (PLINT) ( pls->ylength / aStream->downscale ) );
2244 
2245  // Associate cairo with the supplied drawable
2246  xcairo_init_cairo( pls );
2247 
2248  // Recalculate dimensions and the like now that the drawable is known
2249  plbop();
2250 
2251  break;
2252  }
2253  default:
2254  plD_esc_cairo( pls, op, ptr );
2255  break;
2256  }
2257 }
2258 
2259 //--------------------------------------------------------------------------
2260 // xcairo_get_cursor()
2261 //
2262 // X Windows: returns the location of the next mouse click or key press.
2263 //--------------------------------------------------------------------------
2264 
2265 void xcairo_get_cursor( PLStream *pls, PLGraphicsIn *gin )
2266 {
2267  const char *ksname;
2268  char str[257];
2269  KeySym keysym;
2270  XEvent event;
2271  XButtonEvent *xButtonEvent;
2272  Cursor xHairCursor;
2273  PLCairo *aStream;
2274 
2275  aStream = (PLCairo *) pls->dev;
2276 
2277  // Initialize PLplot mouse event structure
2278  plGinInit( gin );
2279 
2280  // Create cross hair cursor & switch to using it
2281  xHairCursor = XCreateFontCursor( aStream->XDisplay, XC_crosshair );
2282  XDefineCursor( aStream->XDisplay, aStream->XWindow, xHairCursor );
2283 
2284  // Get the next mouse button release or key press event
2285  XSelectInput( aStream->XDisplay, aStream->XWindow, ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask | ButtonMotionMask );
2286  XMaskEvent( aStream->XDisplay, ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask | ButtonMotionMask, &event );
2287  XSelectInput( aStream->XDisplay, aStream->XWindow, NoEventMask );
2288 
2289  // Update PLplot's mouse event structure
2290  xButtonEvent = (XButtonEvent *) &event;
2291  gin->state = xButtonEvent->state;
2292  gin->button = xButtonEvent->button;
2293  gin->pX = event.xbutton.x;
2294  gin->pY = pls->ylength - event.xbutton.y;
2295  gin->dX = (PLFLT) event.xbutton.x / ( (PLFLT) ( pls->xlength ) );
2296  gin->dY = (PLFLT) ( pls->ylength - event.xbutton.y ) / ( (PLFLT) ( pls->ylength ) );
2297 
2298  // Get key pressed (if any)
2299  if ( event.type == KeyPress || event.type == KeyRelease )
2300  {
2301  XLookupString( (XKeyEvent *) &event, str, 100, &keysym, NULL );
2302  if ( keysym == NoSymbol )
2303  ksname = "NoSymbol";
2304  else if ( !( ksname = XKeysymToString( keysym ) ) )
2305  ksname = "(no name)";
2306  strcpy( gin->string, ksname );
2307  // gin->string[number_chars] = '\0';
2308  switch ( keysym )
2309  {
2310  case XK_BackSpace:
2311  case XK_Tab:
2312  case XK_Linefeed:
2313  case XK_Return:
2314  case XK_Escape:
2315  case XK_Delete:
2316  gin->keysym = 0xFF & keysym;
2317  break;
2318  default:
2319  gin->keysym = (unsigned int) keysym;
2320  }
2321  }
2322  else // button press
2323  {
2324  sprintf( gin->string, "button %u", gin->button );
2325  gin->keysym = 0x20;
2326  }
2327 
2328  // Switch back to normal cursor
2329  XUndefineCursor( aStream->XDisplay, aStream->XWindow );
2330  XFlush( aStream->XDisplay );
2331 }
2332 
2333 #endif
2334 
2335 
2336 //--------------------------------------------------------------------------
2337 //--------------------------------------------------------------------------
2338 //
2339 // That which is specific to the cairo PDF driver.
2340 //
2341 //--------------------------------------------------------------------------
2342 //--------------------------------------------------------------------------
2343 
2344 #if defined ( PLD_pdfcairo )
2345 
2347 void plD_init_pdfcairo( PLStream * );
2348 
2349 //--------------------------------------------------------------------------
2350 // dispatch_init_init()
2351 //
2352 // Initialize device dispatch table
2353 //--------------------------------------------------------------------------
2354 
2355 // pdfcairo
2357 {
2358 #ifndef ENABLE_DYNDRIVERS
2359  pdt->pl_MenuStr = "Cairo PDF Driver";
2360  pdt->pl_DevName = "pdfcairo";
2361 #endif
2363  pdt->pl_seq = 101;
2364  pdt->pl_init = (plD_init_fp) plD_init_pdfcairo;
2367  pdt->pl_eop = (plD_eop_fp) plD_eop_cairo;
2368  pdt->pl_bop = (plD_bop_fp) plD_bop_cairo;
2371  pdt->pl_esc = (plD_esc_fp) plD_esc_cairo;
2372 }
2373 
2374 //--------------------------------------------------------------------------
2375 // plD_init_pdfcairo()
2376 //
2377 // Initialize Cairo PDF device
2378 //--------------------------------------------------------------------------
2379 
2380 void plD_init_pdfcairo( PLStream *pls )
2381 {
2382  PLCairo *aStream;
2383 
2384  // Setup the PLStream and the font lookup table
2385  aStream = stream_and_font_setup( pls, 0 );
2386 
2387  // Prompt for a file name if not already set.
2388  plOpenFile( pls );
2389 
2390  // Create an cairo surface & context for PDF file.
2391  // Dimension units are pts = 1/72 inches from cairo documentation.
2392  aStream->cairoSurface = cairo_pdf_surface_create_for_stream( (cairo_write_func_t) write_to_stream, pls->OutFile, (double) pls->xlength, (double) pls->ylength );
2393  aStream->cairoContext = cairo_create( aStream->cairoSurface );
2394 
2395  // Save the pointer to the structure in the PLplot stream
2396  pls->dev = aStream;
2397 
2398  // Invert the surface so that the graphs are drawn right side up.
2399  rotate_cairo_surface( pls, 1.0, 0.0, 0.0, -1.0, 0.0, (float) pls->ylength, FALSE );
2400 
2401  // Set graphics aliasing
2402  cairo_set_antialias( aStream->cairoContext, aStream->graphics_anti_aliasing );
2403 
2404  // Set fill rule for the case of self-intersecting boundaries.
2405  if ( pls->dev_eofill )
2406  cairo_set_fill_rule( aStream->cairoContext, CAIRO_FILL_RULE_EVEN_ODD );
2407  else
2408  cairo_set_fill_rule( aStream->cairoContext, CAIRO_FILL_RULE_WINDING );
2409 }
2410 
2411 #endif
2412 
2413 
2414 //--------------------------------------------------------------------------
2415 //--------------------------------------------------------------------------
2416 //
2417 // That which is specific to the cairo PS driver.
2418 //
2419 //--------------------------------------------------------------------------
2420 //--------------------------------------------------------------------------
2421 
2422 #if defined ( PLD_pscairo )
2423 
2425 void plD_init_pscairo( PLStream * );
2426 
2427 //--------------------------------------------------------------------------
2428 // dispatch_init_init()
2429 //
2430 // Initialize device dispatch table
2431 //--------------------------------------------------------------------------
2432 
2433 // pscairo
2435 {
2436 #ifndef ENABLE_DYNDRIVERS
2437  pdt->pl_MenuStr = "Cairo PS Driver";
2438  pdt->pl_DevName = "pscairo";
2439 #endif
2441  pdt->pl_seq = 102;
2442  pdt->pl_init = (plD_init_fp) plD_init_pscairo;
2445  pdt->pl_eop = (plD_eop_fp) plD_eop_cairo;
2446  pdt->pl_bop = (plD_bop_fp) plD_bop_cairo;
2449  pdt->pl_esc = (plD_esc_fp) plD_esc_cairo;
2450 }
2451 
2452 //--------------------------------------------------------------------------
2453 // plD_init_pscairo()
2454 //
2455 // Initialize Cairo PS device
2456 //--------------------------------------------------------------------------
2457 
2458 void plD_init_pscairo( PLStream *pls )
2459 {
2460  PLCairo *aStream;
2461 
2462  // Setup the PLStream and the font lookup table
2463  aStream = stream_and_font_setup( pls, 0 );
2464 
2465  // Prompt for a file name if not already set.
2466  plOpenFile( pls );
2467 
2468  // Create an cairo surface & context for PS file.
2469  // Dimension units are pts = 1/72 inches from cairo documentation.
2470  aStream->cairoSurface = cairo_ps_surface_create_for_stream( (cairo_write_func_t) write_to_stream, pls->OutFile, (double) pls->ylength, (double) pls->xlength );
2471  aStream->cairoContext = cairo_create( aStream->cairoSurface );
2472 
2473  // Save the pointer to the structure in the PLplot stream
2474  pls->dev = aStream;
2475 
2476  // Handle portrait or landscape
2477  if ( pls->portrait )
2478  {
2479  plsdiori( 1 );
2480  pls->freeaspect = 1;
2481  }
2482  rotate_cairo_surface( pls, 0.0, -1.0, -1.0, 0.0, (float) pls->ylength, (float) pls->xlength, FALSE );
2483 
2484  // Set fill rule for the case of self-intersecting boundaries.
2485  if ( pls->dev_eofill )
2486  cairo_set_fill_rule( aStream->cairoContext, CAIRO_FILL_RULE_EVEN_ODD );
2487  else
2488  cairo_set_fill_rule( aStream->cairoContext, CAIRO_FILL_RULE_WINDING );
2489 }
2490 
2491 #endif
2492 
2493 
2494 //--------------------------------------------------------------------------
2495 //--------------------------------------------------------------------------
2496 //
2497 // That which is specific to the cairo EPS driver.
2498 //
2499 //--------------------------------------------------------------------------
2500 //--------------------------------------------------------------------------
2501 
2502 #if defined ( PLD_epscairo )
2503 
2505 void plD_init_epscairo( PLStream * );
2506 
2507 //--------------------------------------------------------------------------
2508 // dispatch_init_init()
2509 //
2510 // Initialize device dispatch table
2511 //--------------------------------------------------------------------------
2512 
2513 // epscairo
2515 {
2516 #ifndef ENABLE_DYNDRIVERS
2517  pdt->pl_MenuStr = "Cairo EPS Driver";
2518  pdt->pl_DevName = "epscairo";
2519 #endif
2521  pdt->pl_seq = 102;
2522  pdt->pl_init = (plD_init_fp) plD_init_epscairo;
2523  pdt->pl_line = (plD_line_fp) plD_line_cairo_fam;
2524  pdt->pl_polyline = (plD_polyline_fp) plD_polyline_cairo_fam;
2525  pdt->pl_eop = (plD_eop_fp) plD_eop_cairo_fam;
2526  pdt->pl_bop = (plD_bop_fp) plD_bop_cairo_fam;
2527  pdt->pl_tidy = (plD_tidy_fp) plD_tidy_cairo_fam;
2528  pdt->pl_state = (plD_state_fp) plD_state_cairo_fam;
2529  pdt->pl_esc = (plD_esc_fp) plD_esc_cairo_fam;
2530 }
2531 
2532 //--------------------------------------------------------------------------
2533 // plD_init_epscairo()
2534 //
2535 // Initialize Cairo EPS device
2536 //--------------------------------------------------------------------------
2537 
2538 void plD_init_epscairo( PLStream *pls )
2539 {
2540  PLCairo *aStream;
2541 
2542  // Setup the PLStream and the font lookup table and allocate a cairo
2543  // stream structure.
2544  //
2545  // NOTE: The check below is necessary since, in family mode, this function
2546  // will be called multiple times. While you might think that it is
2547  // sufficient to update what *should* be the only pointer to the contents
2548  // of pls->dev, i.e. the pointer pls->dev itself, it appears that
2549  // something else somewhere else is also pointing to pls->dev. If you
2550  // change what pls->dev points to then you will get a "bus error", from
2551  // which I infer the existence of said bad stale pointer.
2552  //
2553  if ( pls->dev == NULL )
2554  {
2555  aStream = stream_and_font_setup( pls, 0 );
2556  }
2557  else
2558  {
2559  stream_and_font_setup( pls, 0 );
2560  aStream = pls->dev;
2561  }
2562 
2563  // Initialize family file info
2564  plFamInit( pls );
2565 
2566  // Prompt for a file name if not already set.
2567  plOpenFile( pls );
2568 
2569  // Create an cairo surface & context for EPS file.
2570  // Dimension units are pts = 1/72 inches from cairo documentation.
2571  aStream->cairoSurface = cairo_ps_surface_create_for_stream( (cairo_write_func_t) write_to_stream, pls->OutFile, (double) pls->ylength, (double) pls->xlength );
2572  aStream->cairoContext = cairo_create( aStream->cairoSurface );
2573 
2574  // Set the PS surface to be EPS.
2575  cairo_ps_surface_set_eps( aStream->cairoSurface, 1 );
2576 
2577  // Save the pointer to the structure in the PLplot stream
2578  pls->dev = aStream;
2579 
2580  // Handle portrait or landscape
2581  if ( pls->portrait )
2582  {
2583  plsdiori( 1 );
2584  pls->freeaspect = 1;
2585  }
2586  rotate_cairo_surface( pls, 0.0, -1.0, -1.0, 0.0, (float) pls->ylength, (float) pls->xlength, FALSE );
2587 
2588  // Set fill rule for the case of self-intersecting boundaries.
2589  if ( pls->dev_eofill )
2590  cairo_set_fill_rule( aStream->cairoContext, CAIRO_FILL_RULE_EVEN_ODD );
2591  else
2592  cairo_set_fill_rule( aStream->cairoContext, CAIRO_FILL_RULE_WINDING );
2593 }
2594 
2595 #endif
2596 
2597 
2598 //--------------------------------------------------------------------------
2599 //--------------------------------------------------------------------------
2600 //
2601 // That which is specific to the cairo SVG driver.
2602 //
2603 //--------------------------------------------------------------------------
2604 //--------------------------------------------------------------------------
2605 
2606 #if defined ( PLD_svgcairo )
2607 
2609 void plD_init_svgcairo( PLStream * );
2610 
2611 //--------------------------------------------------------------------------
2612 // dispatch_init_init()
2613 //
2614 // Initialize device dispatch table
2615 //--------------------------------------------------------------------------
2616 
2617 // svgcairo
2619 {
2620 #ifndef ENABLE_DYNDRIVERS
2621  pdt->pl_MenuStr = "Cairo SVG Driver";
2622  pdt->pl_DevName = "svgcairo";
2623 #endif
2625  pdt->pl_seq = 103;
2626  pdt->pl_init = (plD_init_fp) plD_init_svgcairo;
2627  pdt->pl_line = (plD_line_fp) plD_line_cairo_fam;
2628  pdt->pl_polyline = (plD_polyline_fp) plD_polyline_cairo_fam;
2629  pdt->pl_eop = (plD_eop_fp) plD_eop_cairo_fam;
2630  pdt->pl_bop = (plD_bop_fp) plD_bop_cairo_fam;
2631  pdt->pl_tidy = (plD_tidy_fp) plD_tidy_cairo_fam;
2632  pdt->pl_state = (plD_state_fp) plD_state_cairo_fam;
2633  pdt->pl_esc = (plD_esc_fp) plD_esc_cairo_fam;
2634 }
2635 
2636 //--------------------------------------------------------------------------
2637 // plD_init_svgcairo()
2638 //
2639 // Initialize Cairo SVG device
2640 //--------------------------------------------------------------------------
2641 
2642 void plD_init_svgcairo( PLStream *pls )
2643 {
2644  PLCairo *aStream;
2645 
2646  // Setup the PLStream and the font lookup table and allocate a cairo
2647  // stream structure.
2648  //
2649  // NOTE: The check below is necessary since, in family mode, this function
2650  // will be called multiple times. While you might think that it is
2651  // sufficient to update what *should* be the only pointer to the contents
2652  // of pls->dev, i.e. the pointer pls->dev itself, it appears that
2653  // something else somewhere else is also pointing to pls->dev. If you
2654  // change what pls->dev points to then you will get a "bus error", from
2655  // which I infer the existence of said bad stale pointer.
2656  //
2657  if ( pls->dev == NULL )
2658  {
2659  aStream = stream_and_font_setup( pls, 0 );
2660  }
2661  else
2662  {
2663  stream_and_font_setup( pls, 0 );
2664  aStream = pls->dev;
2665  }
2666 
2667  // Initialize family file info
2668  plFamInit( pls );
2669 
2670  // Prompt for a file name if not already set.
2671  plOpenFile( pls );
2672 
2673  // Save the pointer to the structure in the PLplot stream
2674  pls->dev = aStream;
2675 
2676  // Create an cairo surface & context for SVG file.
2677  // Dimension units are pts = 1/72 inches from cairo documentation.
2678  aStream->cairoSurface = cairo_svg_surface_create_for_stream( (cairo_write_func_t) write_to_stream, pls->OutFile, (double) pls->xlength, (double) pls->ylength );
2679  aStream->cairoContext = cairo_create( aStream->cairoSurface );
2680 
2681  // Invert the surface so that the graphs are drawn right side up.
2682  rotate_cairo_surface( pls, 1.0, 0.0, 0.0, -1.0, 0.0, (float) pls->ylength, FALSE );
2683 
2684  // Set graphics aliasing
2685  cairo_set_antialias( aStream->cairoContext, aStream->graphics_anti_aliasing );
2686 
2687  // Set fill rule for the case of self-intersecting boundaries.
2688  if ( pls->dev_eofill )
2689  cairo_set_fill_rule( aStream->cairoContext, CAIRO_FILL_RULE_EVEN_ODD );
2690  else
2691  cairo_set_fill_rule( aStream->cairoContext, CAIRO_FILL_RULE_WINDING );
2692 }
2693 
2694 #endif
2695 
2696 
2697 //--------------------------------------------------------------------------
2698 //--------------------------------------------------------------------------
2699 //
2700 // That which is specific to the cairo PNG driver.
2701 //
2702 //--------------------------------------------------------------------------
2703 //--------------------------------------------------------------------------
2704 
2705 #if defined ( PLD_pngcairo )
2706 
2708 void plD_init_pngcairo( PLStream * );
2709 void plD_eop_pngcairo( PLStream * );
2710 
2711 //--------------------------------------------------------------------------
2712 // dispatch_init_init()
2713 //
2714 // Initialize device dispatch table
2715 //--------------------------------------------------------------------------
2716 
2717 // pngcairo
2719 {
2720 #ifndef ENABLE_DYNDRIVERS
2721  pdt->pl_MenuStr = "Cairo PNG Driver";
2722  pdt->pl_DevName = "pngcairo";
2723 #endif
2725  pdt->pl_seq = 104;
2726  pdt->pl_init = (plD_init_fp) plD_init_pngcairo;
2727  pdt->pl_line = (plD_line_fp) plD_line_cairo_fam;
2728  pdt->pl_polyline = (plD_polyline_fp) plD_polyline_cairo_fam;
2729  pdt->pl_eop = (plD_eop_fp) plD_eop_pngcairo;
2730  pdt->pl_bop = (plD_bop_fp) plD_bop_cairo_fam;
2731  pdt->pl_tidy = (plD_tidy_fp) plD_tidy_cairo_fam;
2732  pdt->pl_state = (plD_state_fp) plD_state_cairo_fam;
2733  pdt->pl_esc = (plD_esc_fp) plD_esc_cairo_fam;
2734 }
2735 
2736 //--------------------------------------------------------------------------
2737 // plD_init_pngcairo()
2738 //
2739 // Initialize Cairo PNG device
2740 //--------------------------------------------------------------------------
2741 
2742 void plD_init_pngcairo( PLStream *pls )
2743 {
2744  PLCairo *aStream;
2745 
2746  // Setup the PLStream and the font lookup table and allocate a cairo
2747  // stream structure.
2748  //
2749  // NOTE: The check below is necessary since, in family mode, this function
2750  // will be called multiple times. While you might think that it is
2751  // sufficient to update what *should* be the only pointer to the contents
2752  // of pls->dev, i.e. the pointer pls->dev itself, it appears that
2753  // something else somewhere else is also pointing to pls->dev. If you
2754  // change what pls->dev points to then you will get a "bus error", from
2755  // which I infer the existence of said bad stale pointer.
2756  //
2757  if ( pls->dev == NULL )
2758  {
2759  aStream = stream_and_font_setup( pls, 0 );
2760  }
2761  else
2762  {
2763  stream_and_font_setup( pls, 0 );
2764  aStream = pls->dev;
2765  }
2766 
2767  // Initialize family file info
2768  plFamInit( pls );
2769 
2770  // Prompt for a file name if not already set.
2771  plOpenFile( pls );
2772 
2773  // Save the pointer to the structure in the PLplot stream
2774  pls->dev = aStream;
2775 
2776  // Create a new cairo surface & context for PNG file.
2777  // Dimension units are pixels from cairo documentation.
2778  aStream->cairoSurface = cairo_image_surface_create( CAIRO_FORMAT_ARGB32, (int) pls->xlength, (int) pls->ylength );
2779  aStream->cairoContext = cairo_create( aStream->cairoSurface );
2780 
2781  // Invert the surface so that the graphs are drawn right side up.
2782  rotate_cairo_surface( pls, 1.0, 0.0, 0.0, -1.0, 0.0, (float) pls->ylength, FALSE );
2783 
2784  // Set graphics aliasing
2785  cairo_set_antialias( aStream->cairoContext, aStream->graphics_anti_aliasing );
2786 
2787  // Set fill rule for the case of self-intersecting boundaries.
2788  if ( pls->dev_eofill )
2789  cairo_set_fill_rule( aStream->cairoContext, CAIRO_FILL_RULE_EVEN_ODD );
2790  else
2791  cairo_set_fill_rule( aStream->cairoContext, CAIRO_FILL_RULE_WINDING );
2792 }
2793 
2794 //--------------------------------------------------------------------------
2795 // plD_eop_pngcairo()
2796 //
2797 // PNG: End of page.
2798 //--------------------------------------------------------------------------
2799 
2800 void plD_eop_pngcairo( PLStream *pls )
2801 {
2802  PLCairo *aStream;
2803 
2804  if ( cairo_family_check( pls ) )
2805  {
2806  return;
2807  }
2808 
2809  aStream = (PLCairo *) pls->dev;
2810  cairo_surface_write_to_png_stream( aStream->cairoSurface, (cairo_write_func_t) write_to_stream, pls->OutFile );
2811 }
2812 
2813 #endif
2814 
2815 
2816 //--------------------------------------------------------------------------
2817 //--------------------------------------------------------------------------
2818 //
2819 // That which is specific to the cairo memory driver.
2820 //
2821 //--------------------------------------------------------------------------
2822 //--------------------------------------------------------------------------
2823 
2824 #if defined ( PLD_memcairo )
2825 
2827 void plD_init_memcairo( PLStream * );
2828 void plD_eop_memcairo( PLStream * );
2829 void plD_bop_memcairo( PLStream * );
2830 
2831 //--------------------------------------------------------------------------
2832 // dispatch_init_init()
2833 //
2834 // Initialize device dispatch table
2835 //--------------------------------------------------------------------------
2836 
2837 // memcairo
2839 {
2840 #ifndef ENABLE_DYNDRIVERS
2841  pdt->pl_MenuStr = "Cairo memory driver";
2842  pdt->pl_DevName = "memcairo";
2843 #endif
2845  pdt->pl_seq = 105;
2846  pdt->pl_init = (plD_init_fp) plD_init_memcairo;
2849  pdt->pl_eop = (plD_eop_fp) plD_eop_memcairo;
2850  pdt->pl_bop = (plD_bop_fp) plD_bop_memcairo;
2853  pdt->pl_esc = (plD_esc_fp) plD_esc_cairo;
2854 }
2855 
2856 //--------------------------------------------------------------------------
2857 // plD_bop_memcairo()
2858 //
2859 // Set up for the next page.
2860 //--------------------------------------------------------------------------
2861 
2862 void plD_bop_memcairo( PLStream * PL_UNUSED( pls ) )
2863 {
2864  // nothing to do here (we want to preserve the memory as it is)
2865 }
2866 
2867 //--------------------------------------------------------------------------
2868 // plD_init_memcairo()
2869 //
2870 // Initialize Cairo memory device
2871 //--------------------------------------------------------------------------
2872 
2873 void plD_init_memcairo( PLStream *pls )
2874 {
2875  PLCairo *aStream;
2876  int stride, i;
2877  unsigned char *cairo_mem;
2878  unsigned char *input_mem;
2879 
2880  // used for checking byte order
2881  union
2882  {
2883  int testWord;
2884  char testByte[sizeof ( int )];
2885  } endianTest;
2886  endianTest.testWord = 1;
2887 
2888  // Set the plot size to the memory buffer size, on the off chance
2889  // that they are different.
2890  pls->xlength = pls->phyxma;
2891  pls->ylength = pls->phyyma;
2892 
2893 
2894  // Setup the PLStream and the font lookup table
2895  aStream = stream_and_font_setup( pls, 0 );
2896 
2897  // Test byte order
2898  if ( endianTest.testByte[0] == 1 )
2899  aStream->bigendian = 0;
2900  else
2901  aStream->bigendian = 1;
2902 
2903  // Check that user supplied us with some memory to draw in
2904  if ( pls->dev == NULL )
2905  {
2906  plexit( "Must call plsmem first to set user plotting area!" );
2907  }
2908 
2909  // Save a pointer to the memory.
2910  aStream->memory = pls->dev;
2911 
2912  // Create a cairo surface & context. Copy data in from the input memory area
2913 
2914  // Malloc memory the way cairo likes it. Aligned on the stride computed by cairo_format_stride_for_width
2915  // and in the RGB24 format (from http://cairographics.org/manual/cairo-Image-Surfaces.html):
2916  // Each pixel is a 32-bit quantity, with the upper 8 bits unused.
2917  // Red, Green, and Blue are stored in the remaining 24 bits in that order
2918  stride = pls->xlength * 4;
2919  // stride = cairo_format_stride_for_width (CAIRO_FORMAT_RGB24, pls->xlength); This function missing from version 1.4 :-(
2920  aStream->cairo_format_memory = (unsigned char *) calloc( (size_t) ( stride * pls->ylength ), 1 );
2921 
2922  // Copy the input data into the Cairo data format
2923  cairo_mem = aStream->cairo_format_memory;
2924  input_mem = aStream->memory;
2925 
2926  // 32 bit word order
2927  // cairo mem: Big endian: 0=A, 1=R, 2=G, 3=B
2928  // Little endian: 3=A, 2=R, 1=G, 0=B
2929 
2930  if ( aStream->bigendian )
2931  {
2932  for ( i = 0; i < ( pls->xlength * pls->ylength ); i++ )
2933  {
2934  cairo_mem[1] = input_mem[0]; // R
2935  cairo_mem[2] = input_mem[1]; // G
2936  cairo_mem[3] = input_mem[2]; // B
2937  if ( pls->dev_mem_alpha == 1 )
2938  {
2939  cairo_mem[0] = input_mem[3];
2940  input_mem += 4;
2941  }
2942  else
2943  {
2944  input_mem += 3;
2945  }
2946  cairo_mem += 4;
2947  }
2948  }
2949  else
2950  {
2951  for ( i = 0; i < ( pls->xlength * pls->ylength ); i++ )
2952  {
2953  cairo_mem[2] = input_mem[0]; // R
2954  cairo_mem[1] = input_mem[1]; // G
2955  cairo_mem[0] = input_mem[2]; // B
2956  if ( pls->dev_mem_alpha == 1 )
2957  {
2958  cairo_mem[3] = input_mem[3];
2959  input_mem += 4;
2960  }
2961  else
2962  {
2963  input_mem += 3;
2964  }
2965  cairo_mem += 4;
2966  }
2967  }
2968 
2969  // Create a Cairo drawing surface from the input data
2970  aStream->cairoSurface =
2971  // Dimension units are width, height of buffer image from cairo
2972  // documentation.
2973  cairo_image_surface_create_for_data( aStream->cairo_format_memory, CAIRO_FORMAT_RGB24, pls->xlength, pls->ylength, stride );
2974  aStream->cairoContext = cairo_create( aStream->cairoSurface );
2975 
2976  // Save the pointer to the structure in the PLplot stream.
2977  // Note that this wipes out the direct pointer to the memory buffer.
2978  pls->dev = aStream;
2979 
2980  // Invert the surface so that the graphs are drawn right side up.
2981  rotate_cairo_surface( pls, 1.0, 0.0, 0.0, -1.0, 0.0, (float) pls->ylength, FALSE );
2982 
2983  // Set graphics aliasing
2984  cairo_set_antialias( aStream->cairoContext, aStream->graphics_anti_aliasing );
2985 
2986  // Set fill rule for the case of self-intersecting boundaries.
2987  if ( pls->dev_eofill )
2988  cairo_set_fill_rule( aStream->cairoContext, CAIRO_FILL_RULE_EVEN_ODD );
2989  else
2990  cairo_set_fill_rule( aStream->cairoContext, CAIRO_FILL_RULE_WINDING );
2991 }
2992 
2993 //--------------------------------------------------------------------------
2994 // plD_eop_memcairo()
2995 //
2996 // Memory device specific end of page. This copies the contents
2997 // of the cairo surface into the user supplied memory buffer.
2998 //--------------------------------------------------------------------------
2999 
3000 void plD_eop_memcairo( PLStream *pls )
3001 {
3002  int i;
3003  unsigned char *memory;
3004  unsigned char *cairo_surface_data;
3005  PLCairo *aStream;
3006 
3007  aStream = (PLCairo *) pls->dev;
3008  memory = aStream->memory;
3009  cairo_surface_data = cairo_image_surface_get_data( aStream->cairoSurface );
3010  // 32 bit word order
3011  // cairo mem: Big endian: 0=A, 1=R, 2=G, 3=B
3012  // Little endian: 3=A, 2=R, 1=G, 0=B
3013  if ( aStream->bigendian )
3014  {
3015  for ( i = 0; i < ( pls->xlength * pls->ylength ); i++ )
3016  {
3017  memory[0] = cairo_surface_data[1]; // R
3018  memory[1] = cairo_surface_data[2]; // G
3019  memory[2] = cairo_surface_data[3]; // B
3020  if ( pls->dev_mem_alpha == 1 )
3021  {
3022  memory[3] = cairo_surface_data[0];
3023  memory += 4;
3024  }
3025  else
3026  {
3027  memory += 3;
3028  }
3029  cairo_surface_data += 4;
3030  }
3031  }
3032  else
3033  {
3034  for ( i = 0; i < ( pls->xlength * pls->ylength ); i++ )
3035  {
3036  memory[0] = cairo_surface_data[2]; // R
3037  memory[1] = cairo_surface_data[1]; // G
3038  memory[2] = cairo_surface_data[0]; // B
3039  if ( pls->dev_mem_alpha == 1 )
3040  {
3041  memory[3] = cairo_surface_data[3];
3042  memory += 4;
3043  }
3044  else
3045  {
3046  memory += 3;
3047  }
3048  cairo_surface_data += 4;
3049  }
3050  }
3051 
3052  // Free up the temporary memory malloc'ed in plD_init_memcairo
3053  free( aStream->cairo_format_memory );
3054 }
3055 
3056 #endif
3057 
3058 //--------------------------------------------------------------------------
3059 //--------------------------------------------------------------------------
3060 //
3061 // That which is specific to the cairo external context driver.
3062 //
3063 //--------------------------------------------------------------------------
3064 //--------------------------------------------------------------------------
3065 
3066 #if defined ( PLD_extcairo )
3067 
3068 void extcairo_setbackground( PLStream * );
3070 void plD_init_extcairo( PLStream * );
3071 void plD_bop_extcairo( PLStream * );
3072 void plD_eop_extcairo( PLStream * );
3073 void plD_esc_extcairo( PLStream *, PLINT, void * );
3074 void plD_tidy_extcairo( PLStream * );
3075 
3076 //--------------------------------------------------------------------------
3077 // extcairo_setbackground()
3078 //
3079 // Set the background color for the extcairo device
3080 //--------------------------------------------------------------------------
3081 
3082 void extcairo_setbackground( PLStream *pls )
3083 {
3084  PLCairo *aStream;
3085 
3086  aStream = (PLCairo *) pls->dev;
3087 
3088  // Fill the context with the background color if the user so desires.
3089  if ( aStream->cairoContext != NULL )
3090  {
3091  cairo_rectangle( aStream->cairoContext, 0.0, 0.0, pls->xlength, pls->ylength );
3092  cairo_set_source_rgba( aStream->cairoContext,
3093  (double) pls->cmap0[0].r / 255.0,
3094  (double) pls->cmap0[0].g / 255.0,
3095  (double) pls->cmap0[0].b / 255.0,
3096  (double) pls->cmap0[0].a );
3097  cairo_fill( aStream->cairoContext );
3098  }
3099 }
3100 
3101 //--------------------------------------------------------------------------
3102 // dispatch_init_init()
3103 //
3104 // Initialize device dispatch table
3105 //--------------------------------------------------------------------------
3106 
3107 // extcairo
3109 {
3110 #ifndef ENABLE_DYNDRIVERS
3111  pdt->pl_MenuStr = "Cairo external context driver";
3112  pdt->pl_DevName = "extcairo";
3113 #endif
3115  pdt->pl_seq = 106;
3116  pdt->pl_init = (plD_init_fp) plD_init_extcairo;
3119  pdt->pl_bop = (plD_bop_fp) plD_bop_extcairo;
3120  pdt->pl_eop = (plD_eop_fp) plD_eop_extcairo;
3121  pdt->pl_tidy = (plD_tidy_fp) plD_tidy_extcairo;
3123  pdt->pl_esc = (plD_esc_fp) plD_esc_extcairo;
3124 }
3125 
3126 //--------------------------------------------------------------------------
3127 // plD_init_extcairo()
3128 //
3129 // Initialize Cairo external context driver.
3130 //--------------------------------------------------------------------------
3131 
3132 void plD_init_extcairo( PLStream *pls )
3133 {
3134  PLCairo *aStream;
3135 
3136  // Setup the PLStream and the font lookup table
3137  aStream = stream_and_font_setup( pls, 0 );
3138 
3139  // Save the pointer to the structure in the PLplot stream
3140  pls->dev = aStream;
3141 }
3142 
3143 //--------------------------------------------------------------------------
3144 // plD_bop_extcairo()
3145 //
3146 // Set up for the next page.
3147 //--------------------------------------------------------------------------
3148 
3149 void plD_bop_extcairo( PLStream *pls )
3150 {
3151  PLCairo *aStream;
3152 
3153  aStream = (PLCairo *) pls->dev;
3154 
3155  // Set background if desired
3156  if ( aStream->set_background )
3157  {
3158  extcairo_setbackground( pls );
3159  }
3160 }
3161 
3162 //--------------------------------------------------------------------------
3163 // plD_eop_extcairo()
3164 //
3165 // End of page.
3166 //--------------------------------------------------------------------------
3167 
3168 void plD_eop_extcairo( PLStream * PL_UNUSED( pls ) )
3169 {
3170  // nothing to do here, we leave it to the calling program to display
3171  // (or not) the update cairo context.
3172 }
3173 
3174 //--------------------------------------------------------------------------
3175 // plD_esc_extcairo()
3176 //
3177 // The generic escape function, extended so that user can pass in
3178 // an external Cairo context to use for rendering.
3179 //--------------------------------------------------------------------------
3180 
3181 void plD_esc_extcairo( PLStream *pls, PLINT op, void *ptr )
3182 {
3183  PLCairo *aStream;
3184 
3185  aStream = (PLCairo *) pls->dev;
3186 
3187  switch ( op )
3188  {
3189  case PLESC_DEVINIT: // Set external context
3190  aStream->cairoContext = (cairo_t *) ptr;
3191  // Set graphics aliasing
3192  cairo_set_antialias( aStream->cairoContext, aStream->graphics_anti_aliasing );
3193 
3194  // Invert the surface so that the graphs are drawn right side up.
3195  rotate_cairo_surface( pls, 1.0, 0.0, 0.0, -1.0, 0.0, (float) pls->ylength, FALSE );
3196 
3197  // Should adjust plot size to fit in the given cairo context?
3198  // Cairo does not provide a way to query the dimensions of a context?
3199 
3200  // Set background if desired
3201  if ( aStream->set_background )
3202  {
3203  extcairo_setbackground( pls );
3204  }
3205 
3206  // Set fill rule for the case of self-intersecting boundaries.
3207  if ( pls->dev_eofill )
3208  cairo_set_fill_rule( aStream->cairoContext, CAIRO_FILL_RULE_EVEN_ODD );
3209  else
3210  cairo_set_fill_rule( aStream->cairoContext, CAIRO_FILL_RULE_WINDING );
3211  break;
3212  default: // Fall back on default Cairo actions
3213  plD_esc_cairo( pls, op, ptr );
3214  break;
3215  }
3216 }
3217 
3218 //--------------------------------------------------------------------------
3219 // plD_tidy_extcairo()
3220 //
3221 // This is nop, it is up to the calling program to clean up the Cairo
3222 // context, etc...
3223 //--------------------------------------------------------------------------
3224 
3225 void plD_tidy_extcairo( PLStream * PL_UNUSED( pls ) )
3226 {
3227 }
3228 
3229 #endif
3230 
3231 
3232 //--------------------------------------------------------------------------
3233 //--------------------------------------------------------------------------
3234 //
3235 // That which is specific to the cairo microsoft windows driver.
3236 //
3237 // Much of the Windows specific code here was lifted from the wingcc
3238 // driver.
3239 //
3240 //--------------------------------------------------------------------------
3241 //--------------------------------------------------------------------------
3242 
3243 #if defined ( PLD_wincairo )
3244 
3245 static char* szWndClass = "PLplot WinCairo";
3246 
3248 void plD_init_wincairo( PLStream * );
3249 //void plD_bop_extcairo( PLStream * );
3250 void plD_eop_wincairo( PLStream * );
3251 void plD_wait_wincairo( PLStream * );
3252 void plD_esc_wincairo( PLStream *, PLINT, void * );
3253 void plD_tidy_wincairo( PLStream * );
3254 
3255 //--------------------------------------------------------------------------
3256 // blit_to_win()
3257 //
3258 // Blit the offscreen image to the Windows window.
3259 //--------------------------------------------------------------------------
3260 
3261 void blit_to_win( PLCairo *aStream )
3262 {
3263  cairo_set_source_surface( aStream->cairoContext_win, aStream->cairoSurface, 0.0, 0.0 );
3264  cairo_paint( aStream->cairoContext_win );
3265 }
3266 
3267 //--------------------------------------------------------------------------
3268 // This is the window function for the plot window. Whenever a message is
3269 // dispatched using DispatchMessage (or sent with SendMessage) this function
3270 // gets called with the contents of the message.
3271 //--------------------------------------------------------------------------
3272 
3273 LRESULT CALLBACK PlplotCairoWndProc( HWND hwnd, UINT nMsg, WPARAM wParam, LPARAM lParam )
3274 {
3275  PLStream *pls = NULL;
3276  PLCairo *dev = NULL;
3277 
3278 //
3279 // The window carries a 32bit user defined pointer which points to the
3280 // plplot stream (pls). This is used for tracking the window.
3281 // Unfortunately, this is "attached" to the window AFTER it is created
3282 // so we can not initialise PLStream or wincairo "blindly" because
3283 // they may not yet have been initialised.
3284 // WM_CREATE is called before we get to initialise those variables, so
3285 // we wont try to set them.
3286 //
3287 
3288  if ( nMsg == WM_CREATE )
3289  {
3290  return ( 0 );
3291  }
3292  else
3293  {
3294  pls = (PLStream *) GetWindowLongPtr( hwnd, GWLP_USERDATA ); // Try to get the address to pls for this window
3295  if ( pls ) // If we got it, then we will initialise this windows plplot private data area
3296  {
3297  dev = (PLCairo *) pls->dev;
3298  }
3299  }
3300 
3301 //
3302 // Process the windows messages
3303 //
3304 // Everything except WM_CREATE is done here and it is generally hoped that
3305 // pls and dev are defined already by this stage.
3306 // That will be true MOST of the time. Some times WM_PAINT will be called
3307 // before we get to initialise the user data area of the window with the
3308 // pointer to the windows plplot stream
3309 //
3310 
3311  switch ( nMsg )
3312  {
3313  case WM_DESTROY:
3314  // if ( dev )
3315  // Debug( "WM_DESTROY\t" );
3316  PostQuitMessage( 0 );
3317  return ( 0 );
3318  break;
3319 
3320  case WM_PAINT:
3321  blit_to_win( dev );
3322  return ( 1 );
3323  break;
3324 
3325  case WM_SIZE:
3326  GetClientRect( dev->hwnd, &dev->rect );
3327  return ( 0 );
3328  break;
3329 
3330  case WM_ENTERSIZEMOVE:
3331  return ( 0 );
3332  break;
3333 
3334  case WM_EXITSIZEMOVE:
3335  return ( 0 );
3336  break;
3337 
3338  case WM_ERASEBKGND:
3339  if ( dev )
3340  {
3341  dev->oldcolour = SetBkColor( dev->hdc, RGB( pls->cmap0[0].r, pls->cmap0[0].g, pls->cmap0[0].b ) );
3342  ExtTextOut( dev->hdc, 0, 0, ETO_OPAQUE, &dev->rect, "", 0, 0 );
3343  SetBkColor( dev->hdc, dev->oldcolour );
3344  }
3345  return ( 1 );
3346  break;
3347 
3348  case WM_COMMAND:
3349  return ( 0 );
3350  break;
3351  }
3352 
3353  // If we don't handle a message completely we hand it to the system
3354  // provided default window function.
3355  return DefWindowProc( hwnd, nMsg, wParam, lParam );
3356 }
3357 
3358 //--------------------------------------------------------------------------
3359 // handle_locate()
3360 //
3361 // Handle getting the cursor location.
3362 //--------------------------------------------------------------------------
3363 
3364 void
3365 handle_locate( PLStream *pls, PLGraphicsIn *gin )
3366 {
3367  int located = 0;
3368  PLCairo *aStream = (PLCairo *) pls->dev;
3369 
3370  // Initialize PLplot mouse event structure
3371  plGinInit( gin );
3372 
3373  while ( GetMessage( &aStream->msg, NULL, 0, 0 ) && !located )
3374  {
3375  TranslateMessage( &aStream->msg );
3376 
3377  switch ( (int) aStream->msg.message )
3378  {
3379  case WM_MOUSEMOVE:
3380  case WM_LBUTTONDOWN:
3381  gin->state = 1;
3382  gin->button = 1;
3383  gin->pX = LOWORD( aStream->msg.lParam );
3384  gin->pY = pls->ylength - HIWORD( aStream->msg.lParam );
3385  gin->dX = (PLFLT) LOWORD( aStream->msg.lParam ) / ( (PLFLT) pls->xlength );
3386  gin->dY = (PLFLT) ( pls->ylength - HIWORD( aStream->msg.lParam ) ) / ( (PLFLT) pls->ylength );
3387  break;
3388  case WM_CHAR:
3389  gin->keysym = aStream->msg.wParam;
3390  located = 1;
3391  break;
3392 
3393  default:
3394  DispatchMessage( &aStream->msg );
3395  break;
3396  }
3397  }
3398 }
3399 
3400 //--------------------------------------------------------------------------
3401 // dispatch_init_init()
3402 //
3403 // Initialize device dispatch table
3404 //--------------------------------------------------------------------------
3405 
3406 // extcairo
3408 {
3409 #ifndef ENABLE_DYNDRIVERS
3410  pdt->pl_MenuStr = "Cairo Microsoft Windows driver";
3411  pdt->pl_DevName = "wincairo";
3412 #endif
3414  pdt->pl_seq = 107;
3415  pdt->pl_init = (plD_init_fp) plD_init_wincairo;
3418  pdt->pl_bop = (plD_bop_fp) plD_bop_cairo;
3419  pdt->pl_eop = (plD_eop_fp) plD_eop_wincairo;
3420  pdt->pl_tidy = (plD_tidy_fp) plD_tidy_wincairo;
3422  pdt->pl_esc = (plD_esc_fp) plD_esc_wincairo;
3423  pdt->pl_wait = (plD_wait_fp) plD_wait_wincairo;
3424 }
3425 
3426 //--------------------------------------------------------------------------
3427 // plD_init_wincairo()
3428 //
3429 // Initialize Cairo Microsoft Windows driver.
3430 //--------------------------------------------------------------------------
3431 
3432 void plD_init_wincairo( PLStream *pls )
3433 {
3434  PLCairo *aStream;
3435 
3436  // Setup the PLStream and the font lookup table
3437  aStream = stream_and_font_setup( pls, 1 );
3438 
3439  // Save the pointer to the structure in the PLplot stream
3440  pls->dev = aStream;
3441 
3442  // Create window
3443  memset( &aStream->wndclass, 0, sizeof ( WNDCLASSEX ) );
3444 
3445  // This class is called WinTestWin
3446  aStream->wndclass.lpszClassName = szWndClass;
3447 
3448  // cbSize gives the size of the structure for extensibility.
3449  aStream->wndclass.cbSize = sizeof ( WNDCLASSEX );
3450 
3451  // All windows of this class redraw when resized.
3452  aStream->wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS | CS_OWNDC | CS_PARENTDC;
3453 
3454  // All windows of this class use the PlplotCairoWndProc window function.
3455  aStream->wndclass.lpfnWndProc = PlplotCairoWndProc;
3456 
3457  // This class is used with the current program instance.
3458 
3459  aStream->wndclass.hInstance = GetModuleHandle( NULL );
3460 
3461  // Use standard application icon and arrow cursor provided by the OS
3462  aStream->wndclass.hIcon = LoadIcon( NULL, IDI_APPLICATION );
3463  aStream->wndclass.hIconSm = LoadIcon( NULL, IDI_APPLICATION );
3464  aStream->wndclass.hCursor = LoadCursor( NULL, IDC_ARROW );
3465  // Color the background white
3466  aStream->wndclass.hbrBackground = NULL;
3467 
3468  aStream->wndclass.cbWndExtra = sizeof ( pls );
3469 
3470 
3471  //
3472  // Now register the window class for use.
3473  //
3474 
3475  RegisterClassEx( &aStream->wndclass );
3476 
3477  //
3478  // Create our main window using that window class.
3479  //
3480  aStream->hwnd = CreateWindowEx( WS_EX_WINDOWEDGE + WS_EX_LEFT,
3481  szWndClass, // Class name
3482  pls->program, // Caption
3483  WS_OVERLAPPEDWINDOW, // Style
3484  pls->xoffset, // Initial x (use default)
3485  pls->yoffset, // Initial y (use default)
3486  // This is a little lame since the window border size might change.
3487  pls->xlength + 5, // Initial x size (use default)
3488  pls->ylength + 30, // Initial y size (use default)
3489  NULL, // No parent window
3490  NULL, // No menu
3491  aStream->wndclass.hInstance, // This program instance
3492  NULL // Creation parameters
3493  );
3494 
3495 
3496 //
3497 // Attach a pointer to the stream to the window's user area
3498 // this pointer will be used by the windows call back for
3499 // process this window
3500 //
3501 
3502  SetWindowLongPtr( aStream->hwnd, GWLP_USERDATA, (LONG_PTR) pls );
3503  aStream->SCRN_hdc = aStream->hdc = GetDC( aStream->hwnd );
3504 
3505 //
3506 // Setup the popup menu
3507 //
3508 
3509 //
3510 // dev->PopupMenu = CreatePopupMenu();
3511 // AppendMenu( dev->PopupMenu, MF_STRING, PopupPrint, "Print" );
3512 // AppendMenu( dev->PopupMenu, MF_STRING, PopupNextPage, "Next Page" );
3513 // AppendMenu( dev->PopupMenu, MF_STRING, PopupQuit, "Quit" );
3514 //
3515 
3516  // plD_state_wingcc( pls, PLSTATE_COLOR0 );
3517  //
3518  // Display the window which we just created (using the nShow
3519  // passed by the OS, which allows for start minimized and that
3520  // sort of thing).
3521  //
3522  ShowWindow( aStream->hwnd, SW_SHOWDEFAULT );
3523  SetForegroundWindow( aStream->hwnd );
3524 
3525 //
3526 // Now we have to find out, from windows, just how big our drawing area is
3527 // when we specified the page size earlier on, that includes the borders,
3528 // title bar etc... so now that windows has done all its initialisations,
3529 // we will ask how big the drawing area is, and tell plplot
3530 //
3531 
3532 //
3533 // GetClientRect( dev->hwnd, &dev->rect );
3534 // dev->width = dev->rect.right;
3535 // dev->height = dev->rect.bottom;
3536 //
3537 
3538 //
3539 // Initialize Cairo Surface using the windows hdc.
3540 //
3541 
3542  // This is the Win32 Cairo surface.
3543  aStream->cairoSurface_win = (cairo_surface_t *) cairo_win32_surface_create( aStream->hdc );
3544  aStream->cairoContext_win = cairo_create( aStream->cairoSurface_win );
3545 
3546  // This is the Cairo surface PLplot will actually plot to.
3547  aStream->cairoSurface = cairo_image_surface_create( CAIRO_FORMAT_RGB24, pls->xlength, pls->ylength );
3548  aStream->cairoContext = cairo_create( aStream->cairoSurface );
3549 
3550  // Invert the surface so that the graphs are drawn right side up.
3551  rotate_cairo_surface( pls, 1.0, 0.0, 0.0, -1.0, 0.0, pls->ylength, FALSE );
3552 
3553  // Set graphics aliasing
3554  cairo_set_antialias( aStream->cairoContext, aStream->graphics_anti_aliasing );
3555 
3556  // Set fill rule for the case of self-intersecting boundaries.
3557  if ( pls->dev_eofill )
3558  cairo_set_fill_rule( aStream->cairoContext, CAIRO_FILL_RULE_EVEN_ODD );
3559  else
3560  cairo_set_fill_rule( aStream->cairoContext, CAIRO_FILL_RULE_WINDING );
3561 }
3562 
3563 //--------------------------------------------------------------------------
3564 // plD_eop_wincairo()
3565 //
3566 // Clean up Cairo Microsoft Windows driver.
3567 //--------------------------------------------------------------------------
3568 
3569 void
3570 plD_eop_wincairo( PLStream *pls )
3571 {
3572  // Nothing to do for the pls->nopause true case.
3573 }
3574 
3575 //--------------------------------------------------------------------------
3576 // plD_wait_wincairo()
3577 //
3578 // Processing of wait (only occurs when pls->nopause false) for the Cairo Microsoft Windows driver.
3579 //--------------------------------------------------------------------------
3580 
3581 void
3582 plD_wait_wincairo( PLStream *pls )
3583 {
3584  PLCairo *aStream = (PLCairo *) pls->dev;
3585 
3586  while ( GetMessage( &aStream->msg, NULL, 0, 0 ) )
3587  {
3588  TranslateMessage( &aStream->msg );
3589  switch ( (int) aStream->msg.message )
3590  {
3591  case WM_CHAR:
3592  if ( ( (TCHAR) ( aStream->msg.wParam ) == 13 ) ||
3593  ( (TCHAR) ( aStream->msg.wParam ) == 'q' ) ||
3594  ( (TCHAR) ( aStream->msg.wParam ) == 'Q' ) )
3595  {
3596  PostQuitMessage( 0 );
3597  }
3598  break;
3599 
3600  default:
3601  DispatchMessage( &aStream->msg );
3602  break;
3603  }
3604  }
3605 }
3606 
3607 //--------------------------------------------------------------------------
3608 // plD_tidy_wincairo()
3609 //
3610 // Clean up Cairo Microsoft Windows driver.
3611 //--------------------------------------------------------------------------
3612 
3613 void plD_tidy_wincairo( PLStream *pls )
3614 {
3615  PLCairo *aStream = (PLCairo *) pls->dev;
3616 
3617  plD_tidy_cairo( pls );
3618 
3619  // Also free up the Cairo win32 surface and context
3620  cairo_destroy( aStream->cairoContext_win );
3621  cairo_surface_destroy( aStream->cairoSurface_win );
3622 
3623  if ( aStream != NULL )
3624  {
3625  if ( aStream->hdc != NULL )
3626  ReleaseDC( aStream->hwnd, aStream->hdc );
3627  free_mem( pls->dev );
3628  }
3629 }
3630 
3631 //--------------------------------------------------------------------------
3632 // plD_esc_wincairo()
3633 //
3634 // Escape function, specialized for the wincairo driver
3635 //--------------------------------------------------------------------------
3636 
3637 void plD_esc_wincairo( PLStream *pls, PLINT op, void *ptr )
3638 {
3639  PLCairo *aStream;
3640 
3641  aStream = (PLCairo *) pls->dev;
3642 
3643  switch ( op )
3644  {
3645  case PLESC_FLUSH:
3646  InvalidateRect( aStream->hwnd, NULL, TRUE );
3647  break;
3648  case PLESC_GETC:
3649  handle_locate( pls, (PLGraphicsIn *) ptr );
3650  break;
3651  default:
3652  plD_esc_cairo( pls, op, ptr );
3653  break;
3654  }
3655 }
3656 
3657 #endif
int plParseDrvOpts(DrvOpt *acc_opt)
Definition: plargs.c:1461
PLDLLIMPEXP_DRIVER void plD_dispatch_init_pscairo(PLDispatchTable *pdt)
void plP_script_scale(PLBOOL ifupper, PLINT *level, PLFLT *old_scale, PLFLT *scale, PLFLT *old_offset, PLFLT *offset)
Definition: plsym.c:1302
char * plwindow
Definition: plstrm.h:640
double downscale
Definition: cairo.c:108
void plD_tidy_cairo(PLStream *)
Definition: cairo.c:498
short set_background
Definition: cairo.c:106
static void start_raster(PLStream *)
Definition: cairo.c:298
void plgesc(char *p_esc)
Definition: plcore.c:3914
#define PLESC_DEVINIT
Definition: plplot.h:296
void plexit(PLCHAR_VECTOR errormsg)
Definition: plctrl.c:1958
static void rotate_cairo_surface(PLStream *, float, float, float, float, float, float, PLBOOL)
Definition: cairo.c:1666
static void proc_str(PLStream *, EscText *)
Definition: cairo.c:873
PLDLLIMPEXP_DRIVER void plD_dispatch_init_wincairo(PLDispatchTable *pdt)
PLFLT sscale
Definition: cairo.c:120
#define PLTEXT_OVERLINE
Definition: plplot.h:318
PLINT dev_arc
Definition: plstrm.h:572
#define PLESC_CONTROL_CHAR
Definition: plplot.h:300
PLFLT just
Definition: plplotP.h:708
static char * ucs4_to_pango_markup_format(PLUNICODE *, int, float)
Definition: cairo.c:992
static void arc(PLStream *, arc_struct *)
Definition: cairo.c:1608
void plP_fci2hex(PLUNICODE fci, unsigned char *phexdigit, unsigned char hexpower)
Definition: plcore.c:3958
short image_buffering
Definition: cairo.c:107
unsigned char b
Definition: plplot.h:550
const char * envFamilyLookup[NPANGOLOOKUP]
Definition: cairo.c:206
PLFLT dX
Definition: plplot.h:442
PLINT * ygradient
Definition: plstrm.h:775
#define RISE_FACTOR
Definition: cairo.c:1226
PLINT alt_unicode
Definition: plstrm.h:749
FILE * OutFile
Definition: plstrm.h:575
#define PLESC_FILL
Definition: plplot.h:279
static void get_mode(PLStream *, PLINT *)
Definition: cairo.c:614
void get_line_properties(PLCairo *aStream, cairo_line_join_t *join, cairo_line_cap_t *cap)
Definition: cairo.c:422
plD_esc_fp pl_esc
Definition: disptab.h:90
PLUINT PLUNICODE
Definition: plplot.h:201
void plOpenFile(PLStream *pls)
Definition: plctrl.c:2571
void plCloseFile(PLStream *pls)
Definition: plctrl.c:2635
void plGetFam(PLStream *pls)
Definition: plctrl.c:2780
void(* plD_tidy_fp)(struct PLStream_struct *)
Definition: disptab.h:72
static DrvOpt cairo_options[]
Definition: cairo.c:87
#define PLTEXT_SUBSCRIPT
Definition: plplot.h:316
int ucs4_to_utf8(PLUNICODE unichar, char *ptr)
Definition: plcore.c:1329
PLINT dev_text
Definition: plstrm.h:572
void plGinInit(PLGraphicsIn *gin)
Definition: plctrl.c:2887
PLINT dev_npts
Definition: plstrm.h:581
const char * pl_MenuStr
Definition: disptab.h:79
PLINT color
Definition: plstrm.h:569
#define FAMILY_LOOKUP_LEN
Definition: cairo.c:214
PLINT dev_unicode
Definition: plstrm.h:747
#define PLESC_END_TEXT
Definition: plplot.h:301
#define TAG_LEN
Definition: cairo.c:217
PLINT * xgradient
Definition: plstrm.h:775
plD_tidy_fp pl_tidy
Definition: disptab.h:88
PLFLT old_sscale
Definition: cairo.c:120
PLINT plbuf_write
Definition: plstrm.h:567
void(* plD_init_fp)(struct PLStream_struct *)
Definition: disptab.h:67
static void text_esc_cairo(PLStream *pls, EscText *args)
Definition: cairo.c:704
#define plsdiori
Definition: plplot.h:809
PLINT dev_clear
Definition: plstrm.h:572
PLFLT diorot
Definition: plstrm.h:661
#define NPANGOLOOKUP
Definition: cairo.c:196
PLFLT a
Definition: plplot.h:551
static int already_warned
Definition: cairo.c:85
void(* plD_eop_fp)(struct PLStream_struct *)
Definition: disptab.h:70
void(* plD_wait_fp)(struct PLStream_struct *)
Definition: disptab.h:75
const char * pl_DevName
Definition: disptab.h:80
#define plbop
Definition: plplot.h:696
#define PLTEXT_SUPERSCRIPT
Definition: plplot.h:315
plD_init_fp pl_init
Definition: disptab.h:83
static void open_span_tag(char *, PLUNICODE, float, int)
Definition: cairo.c:1137
short upDown
Definition: cairo.c:110
#define PLTEXT_BACKCHAR
Definition: plplot.h:317
Definition: cairo.c:96
char * program
Definition: plstrm.h:530
PLBOOL fill
Definition: plplotP.h:1110
PLBOOL stream_closed
Definition: plstrm.h:782
PLColor * cmap1
Definition: plstrm.h:545
PLDLLIMPEXP_DRIVER void plD_dispatch_init_pngcairo(PLDispatchTable *pdt)
short * dev_x
Definition: plstrm.h:582
PLDLLIMPEXP_DRIVER void plD_dispatch_init_extcairo(PLDispatchTable *pdt)
PLINT n_ctrl_char
Definition: plplotP.h:728
#define PLESC_TEXT_CHAR
Definition: plplot.h:299
void plFamInit(PLStream *pls)
Definition: plctrl.c:2751
short graphics_anti_aliasing
Definition: cairo.c:104
#define PLTEXT_FONTCHANGE
Definition: plplot.h:314
static void text_char_cairo(PLStream *pls, EscText *args)
Definition: cairo.c:670
int PLINT
Definition: plplot.h:181
void plD_eop_cairo(PLStream *)
Definition: cairo.c:483
PLINT PLBOOL
Definition: plplot.h:204
PLUNICODE n_fci
Definition: plplotP.h:726
cairo_surface_t * cairoSurface_raster
Definition: cairo.c:100
PLINT portrait
Definition: plstrm.h:665
cairo_surface_t * cairoSurface
Definition: cairo.c:98
void(* plD_line_fp)(struct PLStream_struct *, short, short, short, short)
Definition: disptab.h:68
static char * rise_span_tag(int, float, float, float)
Definition: cairo.c:1239
unsigned char g
Definition: plplot.h:549
PLDLLIMPEXP_DRIVER void plD_dispatch_init_svgcairo(PLDispatchTable *pdt)
static int image_buffering
Definition: cairo.c:84
cairo_t * cairoContext
Definition: cairo.c:99
const char * weightLookup[2]
Definition: cairo.c:219
void(* plD_esc_fp)(struct PLStream_struct *, PLINT, void *)
Definition: disptab.h:74
void set_line_properties(PLCairo *aStream, cairo_line_join_t join, cairo_line_cap_t cap)
Definition: cairo.c:428
int cairo_family_check(PLStream *pls)
Definition: cairo.c:1585
void(* plD_polyline_fp)(struct PLStream_struct *, short *, short *, PLINT)
Definition: disptab.h:69
static void end_raster(PLStream *)
Definition: cairo.c:342
#define snprintf
Definition: plplotP.h:235
PLINT termin
Definition: plstrm.h:568
#define PIXELS_X
Definition: plplotP.h:304
PLFLT b
Definition: plplotP.h:1106
#define PL_DRAWMODE_XOR
Definition: plplot.h:1321
void set_clip(PLStream *pls)
Definition: cairo.c:1543
#define PLESC_MODESET
Definition: plplot.h:306
#define TRUE
Definition: plplotP.h:176
PLINT ylength
Definition: plstrm.h:617
static int rasterize_image
Definition: cairo.c:82
char * FileName
Definition: plstrm.h:576
short text_clipping
Definition: cairo.c:102
#define FALSE
Definition: plplotP.h:177
PLFLT soffset
Definition: cairo.c:120
static int text_clipping
Definition: cairo.c:78
void plD_bop_cairo(PLStream *)
Definition: cairo.c:385
void difilt_clip(PLINT *x_coords, PLINT *y_coords)
Definition: plcore.c:1603
plD_bop_fp pl_bop
Definition: disptab.h:87
static void poly_line(PLStream *, short *, short *, PLINT)
Definition: cairo.c:1430
#define PL_FCI_STYLE
Definition: plplot.h:377
PLINT phyyma
Definition: plstrm.h:705
#define PL_DRAWMODE_UNKNOWN
Definition: plplot.h:1318
#define PLESC_END_RASTERIZE
Definition: plplot.h:303
static void gradient(PLStream *pls, short *xa, short *ya, PLINT npts)
Definition: cairo.c:1499
PLINT dev_gradient
Definition: plstrm.h:773
void plD_polyline_cairo(PLStream *, short *, short *, PLINT)
Definition: cairo.c:460
plD_line_fp pl_line
Definition: disptab.h:84
short rasterize_image
Definition: cairo.c:105
static int text_anti_aliasing
Definition: cairo.c:79
PLINT get_string_length
Definition: plstrm.h:787
PLFLT rotate
Definition: plplotP.h:1109
void plP_setpxl(PLFLT xpmm, PLFLT ypmm)
Definition: plcore.c:4238
static void set_mode(PLStream *, PLINT *)
Definition: cairo.c:586
static void close_span_tag(char *, int)
Definition: cairo.c:1199
PLDLLIMPEXP_DRIVER void plD_dispatch_init_pdfcairo(PLDispatchTable *pdt)
static int graphics_anti_aliasing
Definition: cairo.c:80
PLColor * cmap0
Definition: plstrm.h:544
void plD_esc_cairo(PLStream *, PLINT, void *)
Definition: cairo.c:530
#define PLDLLIMPEXP_DRIVER
Definition: pldll.h:81
unsigned int keysym
Definition: plplot.h:437
PLFLT old_soffset
Definition: cairo.c:120
PLINT famadv
Definition: plstrm.h:570
static PLStream * pls[PL_NSTREAMS]
Definition: plcore.h:88
void plP_setphy(PLINT xmin, PLINT xmax, PLINT ymin, PLINT ymax)
Definition: plcore.c:4249
PLFLT x
Definition: plplotP.h:1103
PLFLT angle2
Definition: plplotP.h:1108
#define PLESC_MODEGET
Definition: plplot.h:307
#define plgfci
Definition: plplot.h:735
float fontSize
Definition: cairo.c:111
PLINT family
Definition: plstrm.h:570
PLINT xlength
Definition: plstrm.h:617
#define PLESC_BEGIN_TEXT
Definition: plplot.h:298
void plRotationShear(PLFLT *xFormMatrix, PLFLT *rotation, PLFLT *shear, PLFLT *stride)
Definition: plot3d.c:2767
PLINT yoffset
Definition: plstrm.h:618
PLFLT a
Definition: plplotP.h:1105
const char * styleLookup[3]
Definition: cairo.c:224
unsigned short unicode_array_len
Definition: plplotP.h:736
#define DPI
Definition: cairo.c:71
short * dev_y
Definition: plstrm.h:582
PLINT dev_modeset
Definition: plstrm.h:791
static void text_begin_cairo(PLStream *pls, EscText *args)
Definition: cairo.c:646
#define PL_DRAWMODE_REPLACE
Definition: plplot.h:1320
PLDLLIMPEXP_DRIVER void plD_dispatch_init_xcairo(PLDispatchTable *pdt)
#define MAX_STRING_LEN
Definition: cairo.c:75
#define PIXELS_Y
Definition: plplotP.h:305
char familyLookup[NPANGOLOOKUP][FAMILY_LOOKUP_LEN]
Definition: cairo.c:215
static int external_drawable
Definition: cairo.c:81
plD_wait_fp pl_wait
Definition: disptab.h:91
char * pangoMarkupString
Definition: cairo.c:109
PLDLLIMPEXP_DRIVER void plD_dispatch_init_epscairo(PLDispatchTable *pdt)
#define PL_UNUSED(x)
Definition: plplot.h:138
float PLFLT
Definition: plplot.h:163
cairo_t * cairoContext_raster
Definition: cairo.c:101
#define PLESC_START_RASTERIZE
Definition: plplot.h:302
PLFLT y
Definition: plplotP.h:1104
#define PL_FCI_FAMILY
Definition: plplot.h:376
#define PLTEXT_UNDERLINE
Definition: plplot.h:319
PLINT page
Definition: plstrm.h:578
PLFLT chrht
Definition: plstrm.h:686
void(* plD_bop_fp)(struct PLStream_struct *)
Definition: disptab.h:71
static int set_background
Definition: cairo.c:83
#define free_mem(a)
Definition: plplotP.h:182
PLDLLIMPEXP_DRIVER void plD_dispatch_init_memcairo(PLDispatchTable *pdt)
PLINT phyxma
Definition: plstrm.h:705
#define PL_FCI_WEIGHT
Definition: plplot.h:378
#define PI
Definition: plplotP.h:290
cairo_status_t write_to_stream(void *, unsigned char *, unsigned int)
Definition: cairo.c:1277
#define PLCAIRO_DEFAULT_Y
Definition: cairo.c:73
unsigned int state
Definition: plplot.h:436
void plD_line_cairo(PLStream *, short, short, short, short)
Definition: cairo.c:434
unsigned char r
Definition: plplot.h:548
static void set_current_context(PLStream *)
Definition: cairo.c:1401
#define PLESC_HAS_TEXT
Definition: plplot.h:290
PLFLT width
Definition: plstrm.h:552
void plwarn(PLCHAR_VECTOR errormsg)
Definition: plctrl.c:1863
static void text_end_cairo(PLStream *pls, EscText *args)
Definition: cairo.c:773
#define PLCAIRO_DEFAULT_X
Definition: cairo.c:72
#define PLESC_ARC
Definition: plplot.h:304
PLINT y
Definition: plplotP.h:713
PLINT dev_mem_alpha
Definition: plstrm.h:784
static const char * display
Definition: tkMain.c:136
unsigned int button
Definition: plplot.h:438
PLColor curcolor
Definition: plstrm.h:543
static void filled_polygon(PLStream *pls, short *xa, short *ya, PLINT npts)
Definition: cairo.c:1452
plD_state_fp pl_state
Definition: disptab.h:89
#define MAX_MARKUP_LEN
Definition: cairo.c:76
short text_anti_aliasing
Definition: cairo.c:103
PLFLT dY
Definition: plplot.h:442
plD_eop_fp pl_eop
Definition: disptab.h:86
PLINT xoffset
Definition: plstrm.h:618
const char * defaultFamilyLookup[NPANGOLOOKUP]
Definition: cairo.c:198
short uline
Definition: cairo.c:112
PLINT ncol1
Definition: plstrm.h:539
#define PLESC_GRADIENT
Definition: plplot.h:305
PLINT x
Definition: plplotP.h:712
#define PLESC_GETC
Definition: plplot.h:283
PLFLT string_length
Definition: plstrm.h:786
static void blit_to_x(PLStream *pls, double x, double y, double w, double h)
PLINT level
Definition: cairo.c:121
PLINT dev_flush
Definition: plstrm.h:571
PLUNICODE n_char
Definition: plplotP.h:727
#define PL_DRAWMODE_DEFAULT
Definition: plplot.h:1319
plD_polyline_fp pl_polyline
Definition: disptab.h:85
void(* plD_state_fp)(struct PLStream_struct *, PLINT)
Definition: disptab.h:73
PLUNICODE * unicode_array
Definition: plplotP.h:735
PLFLT angle1
Definition: plplotP.h:1107
void * dev
Definition: plstrm.h:594
char string[PL_MAXKEY]
Definition: plplot.h:440
PLDLLIMPEXP_DRIVER const char * plD_DEVICE_INFO_cairo
Definition: cairo.c:149
#define M_PI
Definition: plplotP.h:119
PLINT freeaspect
Definition: plstrm.h:665
PLINT dev_fill0
Definition: plstrm.h:571
PLFLT * xform
Definition: plplotP.h:709
PLCairo * stream_and_font_setup(PLStream *, int)
Definition: cairo.c:1301
void plD_state_cairo(PLStream *, PLINT)
PLINT dev_eofill
Definition: plstrm.h:788
#define PLESC_FLUSH
Definition: plplot.h:281
#define PL_FCI_MARK
Definition: plplot.h:370
PLINT has_string_length
Definition: plstrm.h:785