PLplot: cairo.c Source File

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;
80 static int graphics_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;
101 cairo_t *cairoContext_raster;
102 short text_clipping;
103 short text_anti_aliasing;
104 short graphics_anti_aliasing;
105 short rasterize_image;
106 short set_background;
107 short image_buffering;
108 double downscale;
109 char *pangoMarkupString;
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;
121 PLINT level;
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
149 PLDLLIMPEXP_DRIVER const char* plD_DEVICE_INFO_cairo =
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
198 const char *defaultFamilyLookup[NPANGOLOOKUP] = {
199 "sans",
200 "serif",
201 "monospace",
202 "sans,serif",
203 "sans,serif"
204 };
205
206 const char *envFamilyLookup[NPANGOLOOKUP] = {
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
215 char familyLookup[NPANGOLOOKUP][FAMILY_LOOKUP_LEN];
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
244 PLCairo *stream_and_font_setup( PLStream *, int );
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
385 void plD_bop_cairo( PLStream *pls )
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
483 void plD_eop_cairo( PLStream *pls )
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
498 void plD_tidy_cairo( PLStream *pls )
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
520 void plD_state_cairo( PLStream * PL_UNUSED( pls ), PLINT PL_UNUSED( op ) )
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;
1386 aStream->graphics_anti_aliasing = (short) graphics_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
1401 void set_current_context( PLStream *pls )
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
1585 int cairo_family_check( PLStream *pls )
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
1847 void plD_dispatch_init_xcairo( PLDispatchTable *pdt );
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
1862 void plD_dispatch_init_xcairo( PLDispatchTable *pdt )
1863 {
1864 #ifndef ENABLE_DYNDRIVERS
1865 pdt->pl_MenuStr = "Cairo X Windows Driver";
1866 pdt->pl_DevName = "xcairo";
1867 #endif
1868 pdt->pl_type = plDevType_Interactive;
1869 pdt->pl_seq = 100;
1870 pdt->pl_init = (plD_init_fp) plD_init_xcairo;
1871 pdt->pl_line = (plD_line_fp) plD_line_cairo;
1872 pdt->pl_polyline = (plD_polyline_fp) plD_polyline_cairo;
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;
1876 pdt->pl_state = (plD_state_fp) plD_state_cairo;
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
2346 void plD_dispatch_init_pdfcairo( PLDispatchTable *pdt );
2347 void plD_init_pdfcairo( PLStream * );
2348
2349 //--------------------------------------------------------------------------
2350 // dispatch_init_init()
2351 //
2352 // Initialize device dispatch table
2353 //--------------------------------------------------------------------------
2354
2355 // pdfcairo
2356 void plD_dispatch_init_pdfcairo( PLDispatchTable *pdt )
2357 {
2358 #ifndef ENABLE_DYNDRIVERS
2359 pdt->pl_MenuStr = "Cairo PDF Driver";
2360 pdt->pl_DevName = "pdfcairo";
2361 #endif
2362 pdt->pl_type = plDevType_FileOriented;
2363 pdt->pl_seq = 101;
2364 pdt->pl_init = (plD_init_fp) plD_init_pdfcairo;
2365 pdt->pl_line = (plD_line_fp) plD_line_cairo;
2366 pdt->pl_polyline = (plD_polyline_fp) plD_polyline_cairo;
2367 pdt->pl_eop = (plD_eop_fp) plD_eop_cairo;
2368 pdt->pl_bop = (plD_bop_fp) plD_bop_cairo;
2369 pdt->pl_tidy = (plD_tidy_fp) plD_tidy_cairo;
2370 pdt->pl_state = (plD_state_fp) plD_state_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
2424 void plD_dispatch_init_pscairo( PLDispatchTable *pdt );
2425 void plD_init_pscairo( PLStream * );
2426
2427 //--------------------------------------------------------------------------
2428 // dispatch_init_init()
2429 //
2430 // Initialize device dispatch table
2431 //--------------------------------------------------------------------------
2432
2433 // pscairo
2434 void plD_dispatch_init_pscairo( PLDispatchTable *pdt )
2435 {
2436 #ifndef ENABLE_DYNDRIVERS
2437 pdt->pl_MenuStr = "Cairo PS Driver";
2438 pdt->pl_DevName = "pscairo";
2439 #endif
2440 pdt->pl_type = plDevType_FileOriented;
2441 pdt->pl_seq = 102;
2442 pdt->pl_init = (plD_init_fp) plD_init_pscairo;
2443 pdt->pl_line = (plD_line_fp) plD_line_cairo;
2444 pdt->pl_polyline = (plD_polyline_fp) plD_polyline_cairo;
2445 pdt->pl_eop = (plD_eop_fp) plD_eop_cairo;
2446 pdt->pl_bop = (plD_bop_fp) plD_bop_cairo;
2447 pdt->pl_tidy = (plD_tidy_fp) plD_tidy_cairo;
2448 pdt->pl_state = (plD_state_fp) plD_state_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
2504 void plD_dispatch_init_epscairo( PLDispatchTable *pdt );
2505 void plD_init_epscairo( PLStream * );
2506
2507 //--------------------------------------------------------------------------
2508 // dispatch_init_init()
2509 //
2510 // Initialize device dispatch table
2511 //--------------------------------------------------------------------------
2512
2513 // epscairo
2514 void plD_dispatch_init_epscairo( PLDispatchTable *pdt )
2515 {
2516 #ifndef ENABLE_DYNDRIVERS
2517 pdt->pl_MenuStr = "Cairo EPS Driver";
2518 pdt->pl_DevName = "epscairo";
2519 #endif
2520 pdt->pl_type = plDevType_FileOriented;
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
2608 void plD_dispatch_init_svgcairo( PLDispatchTable *pdt );
2609 void plD_init_svgcairo( PLStream * );
2610
2611 //--------------------------------------------------------------------------
2612 // dispatch_init_init()
2613 //
2614 // Initialize device dispatch table
2615 //--------------------------------------------------------------------------
2616
2617 // svgcairo
2618 void plD_dispatch_init_svgcairo( PLDispatchTable *pdt )
2619 {
2620 #ifndef ENABLE_DYNDRIVERS
2621 pdt->pl_MenuStr = "Cairo SVG Driver";
2622 pdt->pl_DevName = "svgcairo";
2623 #endif
2624 pdt->pl_type = plDevType_FileOriented;
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
2707 void plD_dispatch_init_pngcairo( PLDispatchTable *pdt );
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
2718 void plD_dispatch_init_pngcairo( PLDispatchTable *pdt )
2719 {
2720 #ifndef ENABLE_DYNDRIVERS
2721 pdt->pl_MenuStr = "Cairo PNG Driver";
2722 pdt->pl_DevName = "pngcairo";
2723 #endif
2724 pdt->pl_type = plDevType_FileOriented;
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
2826 void plD_dispatch_init_memcairo( PLDispatchTable *pdt );
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
2838 void plD_dispatch_init_memcairo( PLDispatchTable *pdt )
2839 {
2840 #ifndef ENABLE_DYNDRIVERS
2841 pdt->pl_MenuStr = "Cairo memory driver";
2842 pdt->pl_DevName = "memcairo";
2843 #endif
2844 pdt->pl_type = plDevType_FileOriented;
2845 pdt->pl_seq = 105;
2846 pdt->pl_init = (plD_init_fp) plD_init_memcairo;
2847 pdt->pl_line = (plD_line_fp) plD_line_cairo;
2848 pdt->pl_polyline = (plD_polyline_fp) plD_polyline_cairo;
2849 pdt->pl_eop = (plD_eop_fp) plD_eop_memcairo;
2850 pdt->pl_bop = (plD_bop_fp) plD_bop_memcairo;
2851 pdt->pl_tidy = (plD_tidy_fp) plD_tidy_cairo;
2852 pdt->pl_state = (plD_state_fp) plD_state_cairo;
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 * );
3069 void plD_dispatch_init_extcairo( PLDispatchTable *pdt );
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
3108 void plD_dispatch_init_extcairo( PLDispatchTable *pdt )
3109 {
3110 #ifndef ENABLE_DYNDRIVERS
3111 pdt->pl_MenuStr = "Cairo external context driver";
3112 pdt->pl_DevName = "extcairo";
3113 #endif
3114 pdt->pl_type = plDevType_Interactive;
3115 pdt->pl_seq = 106;
3116 pdt->pl_init = (plD_init_fp) plD_init_extcairo;
3117 pdt->pl_line = (plD_line_fp) plD_line_cairo;
3118 pdt->pl_polyline = (plD_polyline_fp) plD_polyline_cairo;
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;
3122 pdt->pl_state = (plD_state_fp) plD_state_cairo;
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
3247 void plD_dispatch_init_wincairo( PLDispatchTable *pdt );
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
3407 void plD_dispatch_init_wincairo( PLDispatchTable *pdt )
3408 {
3409 #ifndef ENABLE_DYNDRIVERS
3410 pdt->pl_MenuStr = "Cairo Microsoft Windows driver";
3411 pdt->pl_DevName = "wincairo";
3412 #endif
3413 pdt->pl_type = plDevType_Interactive;
3414 pdt->pl_seq = 107;
3415 pdt->pl_init = (plD_init_fp) plD_init_wincairo;
3416 pdt->pl_line = (plD_line_fp) plD_line_cairo;
3417 pdt->pl_polyline = (plD_polyline_fp) plD_polyline_cairo;
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;
3421 pdt->pl_state = (plD_state_fp) plD_state_cairo;
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
plParseDrvOpts
int plParseDrvOpts(DrvOpt *acc_opt)
Definition: plargs.c:1461
plD_dispatch_init_pscairo
PLDLLIMPEXP_DRIVER void plD_dispatch_init_pscairo(PLDispatchTable *pdt)
plP_script_scale
void plP_script_scale(PLBOOL ifupper, PLINT *level, PLFLT *old_scale, PLFLT *scale, PLFLT *old_offset, PLFLT *offset)
Definition: plsym.c:1302
plplotP.h
PLStream::plwindow
char * plwindow
Definition: plstrm.h:640
PLCairo::downscale
double downscale
Definition: cairo.c:108
plD_tidy_cairo
void plD_tidy_cairo(PLStream *)
Definition: cairo.c:498
PLCairo::set_background
short set_background
Definition: cairo.c:106
start_raster
static void start_raster(PLStream *)
Definition: cairo.c:298
plgesc
void plgesc(char *p_esc)
Definition: plcore.c:3914
PLESC_DEVINIT
#define PLESC_DEVINIT
Definition: plplot.h:296
plexit
void plexit(PLCHAR_VECTOR errormsg)
Definition: plctrl.c:1958
rotate_cairo_surface
static void rotate_cairo_surface(PLStream *, float, float, float, float, float, float, PLBOOL)
Definition: cairo.c:1666
proc_str
static void proc_str(PLStream *, EscText *)
Definition: cairo.c:873
plD_dispatch_init_wincairo
PLDLLIMPEXP_DRIVER void plD_dispatch_init_wincairo(PLDispatchTable *pdt)
PLCairo::sscale
PLFLT sscale
Definition: cairo.c:120
PLTEXT_OVERLINE
#define PLTEXT_OVERLINE
Definition: plplot.h:318
PLStream::dev_arc
PLINT dev_arc
Definition: plstrm.h:572
PLESC_CONTROL_CHAR
#define PLESC_CONTROL_CHAR
Definition: plplot.h:300
plDevType_Interactive
Definition: disptab.h:14
EscText::just
PLFLT just
Definition: plplotP.h:708
ucs4_to_pango_markup_format
static char * ucs4_to_pango_markup_format(PLUNICODE *, int, float)
Definition: cairo.c:992
arc
static void arc(PLStream *, arc_struct *)
Definition: cairo.c:1608
plP_fci2hex
void plP_fci2hex(PLUNICODE fci, unsigned char *phexdigit, unsigned char hexpower)
Definition: plcore.c:3958
PLCairo::image_buffering
short image_buffering
Definition: cairo.c:107
PLColor::b
unsigned char b
Definition: plplot.h:550
envFamilyLookup
const char * envFamilyLookup[NPANGOLOOKUP]
Definition: cairo.c:206
PLGraphicsIn::dX
PLFLT dX
Definition: plplot.h:442
PLStream::ygradient
PLINT * ygradient
Definition: plstrm.h:775
RISE_FACTOR
#define RISE_FACTOR
Definition: cairo.c:1226
PLStream::alt_unicode
PLINT alt_unicode
Definition: plstrm.h:749
PLStream::OutFile
FILE * OutFile
Definition: plstrm.h:575
PLESC_FILL
#define PLESC_FILL
Definition: plplot.h:279
get_mode
static void get_mode(PLStream *, PLINT *)
Definition: cairo.c:614
get_line_properties
void get_line_properties(PLCairo *aStream, cairo_line_join_t *join, cairo_line_cap_t *cap)
Definition: cairo.c:422
PLDispatchTable::pl_esc
plD_esc_fp pl_esc
Definition: disptab.h:90
PLUNICODE
PLUINT PLUNICODE
Definition: plplot.h:201
plOpenFile
void plOpenFile(PLStream *pls)
Definition: plctrl.c:2571
plCloseFile
void plCloseFile(PLStream *pls)
Definition: plctrl.c:2635
plDevType_FileOriented
Definition: disptab.h:13
plGetFam
void plGetFam(PLStream *pls)
Definition: plctrl.c:2780
plD_tidy_fp
void(* plD_tidy_fp)(struct PLStream_struct *)
Definition: disptab.h:72
cairo_options
static DrvOpt cairo_options[]
Definition: cairo.c:87
PLDispatchTable::pl_seq
int pl_seq
Definition: disptab.h:82
PLTEXT_SUBSCRIPT
#define PLTEXT_SUBSCRIPT
Definition: plplot.h:316
ucs4_to_utf8
int ucs4_to_utf8(PLUNICODE unichar, char *ptr)
Definition: plcore.c:1329
PLStream::dev_text
PLINT dev_text
Definition: plstrm.h:572
plGinInit
void plGinInit(PLGraphicsIn *gin)
Definition: plctrl.c:2887
PLStream::dev_npts
PLINT dev_npts
Definition: plstrm.h:581
PLDispatchTable::pl_MenuStr
const char * pl_MenuStr
Definition: disptab.h:79
PLStream::color
PLINT color
Definition: plstrm.h:569
FAMILY_LOOKUP_LEN
#define FAMILY_LOOKUP_LEN
Definition: cairo.c:214
PLStream::dev_unicode
PLINT dev_unicode
Definition: plstrm.h:747
PLESC_END_TEXT
#define PLESC_END_TEXT
Definition: plplot.h:301
TAG_LEN
#define TAG_LEN
Definition: cairo.c:217
PLStream::xgradient
PLINT * xgradient
Definition: plstrm.h:775
PLDispatchTable::pl_tidy
plD_tidy_fp pl_tidy
Definition: disptab.h:88
PLCairo::old_sscale
PLFLT old_sscale
Definition: cairo.c:120
PLStream::plbuf_write
PLINT plbuf_write
Definition: plstrm.h:567
plD_init_fp
void(* plD_init_fp)(struct PLStream_struct *)
Definition: disptab.h:67
text_esc_cairo
static void text_esc_cairo(PLStream *pls, EscText *args)
Definition: cairo.c:704
plsdiori
#define plsdiori
Definition: plplot.h:809
PLStream::dev_clear
PLINT dev_clear
Definition: plstrm.h:572
PLStream::diorot
PLFLT diorot
Definition: plstrm.h:661
NPANGOLOOKUP
#define NPANGOLOOKUP
Definition: cairo.c:196
PLColor::a
PLFLT a
Definition: plplot.h:551
already_warned
static int already_warned
Definition: cairo.c:85
plD_eop_fp
void(* plD_eop_fp)(struct PLStream_struct *)
Definition: disptab.h:70
plD_wait_fp
void(* plD_wait_fp)(struct PLStream_struct *)
Definition: disptab.h:75
PLDispatchTable::pl_DevName
const char * pl_DevName
Definition: disptab.h:80
plbop
#define plbop
Definition: plplot.h:696
PLTEXT_SUPERSCRIPT
#define PLTEXT_SUPERSCRIPT
Definition: plplot.h:315
PLDispatchTable::pl_init
plD_init_fp pl_init
Definition: disptab.h:83
open_span_tag
static void open_span_tag(char *, PLUNICODE, float, int)
Definition: cairo.c:1137
PLCairo::upDown
short upDown
Definition: cairo.c:110
PLTEXT_BACKCHAR
#define PLTEXT_BACKCHAR
Definition: plplot.h:317
PLCairo
Definition: cairo.c:96
PLStream::program
char * program
Definition: plstrm.h:530
arc_struct::fill
PLBOOL fill
Definition: plplotP.h:1110
PLStream::stream_closed
PLBOOL stream_closed
Definition: plstrm.h:782
PLStream::cmap1
PLColor * cmap1
Definition: plstrm.h:545
plD_dispatch_init_pngcairo
PLDLLIMPEXP_DRIVER void plD_dispatch_init_pngcairo(PLDispatchTable *pdt)
PLStream::dev_x
short * dev_x
Definition: plstrm.h:582
plD_dispatch_init_extcairo
PLDLLIMPEXP_DRIVER void plD_dispatch_init_extcairo(PLDispatchTable *pdt)
EscText::n_ctrl_char
PLINT n_ctrl_char
Definition: plplotP.h:728
PLESC_TEXT_CHAR
#define PLESC_TEXT_CHAR
Definition: plplot.h:299
plFamInit
void plFamInit(PLStream *pls)
Definition: plctrl.c:2751
PLCairo::graphics_anti_aliasing
short graphics_anti_aliasing
Definition: cairo.c:104
PLTEXT_FONTCHANGE
#define PLTEXT_FONTCHANGE
Definition: plplot.h:314
text_char_cairo
static void text_char_cairo(PLStream *pls, EscText *args)
Definition: cairo.c:670
PLINT
int PLINT
Definition: plplot.h:181
plD_eop_cairo
void plD_eop_cairo(PLStream *)
Definition: cairo.c:483
PLBOOL
PLINT PLBOOL
Definition: plplot.h:204
EscText::n_fci
PLUNICODE n_fci
Definition: plplotP.h:726
PLCairo::cairoSurface_raster
cairo_surface_t * cairoSurface_raster
Definition: cairo.c:100
PLStream::portrait
PLINT portrait
Definition: plstrm.h:665
PLCairo::cairoSurface
cairo_surface_t * cairoSurface
Definition: cairo.c:98
plD_line_fp
void(* plD_line_fp)(struct PLStream_struct *, short, short, short, short)
Definition: disptab.h:68
rise_span_tag
static char * rise_span_tag(int, float, float, float)
Definition: cairo.c:1239
PLColor::g
unsigned char g
Definition: plplot.h:549
plD_dispatch_init_svgcairo
PLDLLIMPEXP_DRIVER void plD_dispatch_init_svgcairo(PLDispatchTable *pdt)
image_buffering
static int image_buffering
Definition: cairo.c:84
PLCairo::cairoContext
cairo_t * cairoContext
Definition: cairo.c:99
weightLookup
const char * weightLookup[2]
Definition: cairo.c:219
plD_esc_fp
void(* plD_esc_fp)(struct PLStream_struct *, PLINT, void *)
Definition: disptab.h:74
set_line_properties
void set_line_properties(PLCairo *aStream, cairo_line_join_t join, cairo_line_cap_t cap)
Definition: cairo.c:428
EscText
Definition: plplotP.h:699
cairo_family_check
int cairo_family_check(PLStream *pls)
Definition: cairo.c:1585
plD_polyline_fp
void(* plD_polyline_fp)(struct PLStream_struct *, short *, short *, PLINT)
Definition: disptab.h:69
end_raster
static void end_raster(PLStream *)
Definition: cairo.c:342
snprintf
#define snprintf
Definition: plplotP.h:235
PLStream::termin
PLINT termin
Definition: plstrm.h:568
PIXELS_X
#define PIXELS_X
Definition: plplotP.h:304
arc_struct::b
PLFLT b
Definition: plplotP.h:1106
PL_DRAWMODE_XOR
#define PL_DRAWMODE_XOR
Definition: plplot.h:1321
set_clip
void set_clip(PLStream *pls)
Definition: cairo.c:1543
PLESC_MODESET
#define PLESC_MODESET
Definition: plplot.h:306
TRUE
#define TRUE
Definition: plplotP.h:176
PLStream::ylength
PLINT ylength
Definition: plstrm.h:617
rasterize_image
static int rasterize_image
Definition: cairo.c:82
PLDispatchTable
Definition: disptab.h:77
PLStream::FileName
char * FileName
Definition: plstrm.h:576
PLCairo::text_clipping
short text_clipping
Definition: cairo.c:102
FALSE
#define FALSE
Definition: plplotP.h:177
PLCairo::soffset
PLFLT soffset
Definition: cairo.c:120
text_clipping
static int text_clipping
Definition: cairo.c:78
plD_bop_cairo
void plD_bop_cairo(PLStream *)
Definition: cairo.c:385
difilt_clip
void difilt_clip(PLINT *x_coords, PLINT *y_coords)
Definition: plcore.c:1603
PLDispatchTable::pl_bop
plD_bop_fp pl_bop
Definition: disptab.h:87
poly_line
static void poly_line(PLStream *, short *, short *, PLINT)
Definition: cairo.c:1430
PL_FCI_STYLE
#define PL_FCI_STYLE
Definition: plplot.h:377
PLStream::phyyma
PLINT phyyma
Definition: plstrm.h:705
PL_DRAWMODE_UNKNOWN
#define PL_DRAWMODE_UNKNOWN
Definition: plplot.h:1318
DrvOpt
Definition: plplotP.h:748
PLESC_END_RASTERIZE
#define PLESC_END_RASTERIZE
Definition: plplot.h:303
gradient
static void gradient(PLStream *pls, short *xa, short *ya, PLINT npts)
Definition: cairo.c:1499
PLStream::dev_gradient
PLINT dev_gradient
Definition: plstrm.h:773
plD_polyline_cairo
void plD_polyline_cairo(PLStream *, short *, short *, PLINT)
Definition: cairo.c:460
PLDispatchTable::pl_line
plD_line_fp pl_line
Definition: disptab.h:84
PLCairo::rasterize_image
short rasterize_image
Definition: cairo.c:105
text_anti_aliasing
static int text_anti_aliasing
Definition: cairo.c:79
PLStream::get_string_length
PLINT get_string_length
Definition: plstrm.h:787
arc_struct::rotate
PLFLT rotate
Definition: plplotP.h:1109
plP_setpxl
void plP_setpxl(PLFLT xpmm, PLFLT ypmm)
Definition: plcore.c:4238
set_mode
static void set_mode(PLStream *, PLINT *)
Definition: cairo.c:586
close_span_tag
static void close_span_tag(char *, int)
Definition: cairo.c:1199
plD_dispatch_init_pdfcairo
PLDLLIMPEXP_DRIVER void plD_dispatch_init_pdfcairo(PLDispatchTable *pdt)
graphics_anti_aliasing
static int graphics_anti_aliasing
Definition: cairo.c:80
PLStream::cmap0
PLColor * cmap0
Definition: plstrm.h:544
plD_esc_cairo
void plD_esc_cairo(PLStream *, PLINT, void *)
Definition: cairo.c:530
drivers.h
plDevs.h
PLDLLIMPEXP_DRIVER
#define PLDLLIMPEXP_DRIVER
Definition: pldll.h:81
PLGraphicsIn::keysym
unsigned int keysym
Definition: plplot.h:437
PLCairo::old_soffset
PLFLT old_soffset
Definition: cairo.c:120
PLStream::famadv
PLINT famadv
Definition: plstrm.h:570
pls
static PLStream * pls[PL_NSTREAMS]
Definition: plcore.h:88
plP_setphy
void plP_setphy(PLINT xmin, PLINT xmax, PLINT ymin, PLINT ymax)
Definition: plcore.c:4249
arc_struct::x
PLFLT x
Definition: plplotP.h:1103
arc_struct::angle2
PLFLT angle2
Definition: plplotP.h:1108
PLESC_MODEGET
#define PLESC_MODEGET
Definition: plplot.h:307
plgfci
#define plgfci
Definition: plplot.h:735
PLCairo::fontSize
float fontSize
Definition: cairo.c:111
PLStream::family
PLINT family
Definition: plstrm.h:570
PLStream::xlength
PLINT xlength
Definition: plstrm.h:617
PLESC_BEGIN_TEXT
#define PLESC_BEGIN_TEXT
Definition: plplot.h:298
plRotationShear
void plRotationShear(PLFLT *xFormMatrix, PLFLT *rotation, PLFLT *shear, PLFLT *stride)
Definition: plot3d.c:2767
PLStream::yoffset
PLINT yoffset
Definition: plstrm.h:618
arc_struct::a
PLFLT a
Definition: plplotP.h:1105
styleLookup
const char * styleLookup[3]
Definition: cairo.c:224
EscText::unicode_array_len
unsigned short unicode_array_len
Definition: plplotP.h:736
DPI
#define DPI
Definition: cairo.c:71
PLStream::dev_y
short * dev_y
Definition: plstrm.h:582
PLStream::dev_modeset
PLINT dev_modeset
Definition: plstrm.h:791
PLStream
Definition: plstrm.h:523
text_begin_cairo
static void text_begin_cairo(PLStream *pls, EscText *args)
Definition: cairo.c:646
PL_DRAWMODE_REPLACE
#define PL_DRAWMODE_REPLACE
Definition: plplot.h:1320
plD_dispatch_init_xcairo
PLDLLIMPEXP_DRIVER void plD_dispatch_init_xcairo(PLDispatchTable *pdt)
MAX_STRING_LEN
#define MAX_STRING_LEN
Definition: cairo.c:75
PIXELS_Y
#define PIXELS_Y
Definition: plplotP.h:305
familyLookup
char familyLookup[NPANGOLOOKUP][FAMILY_LOOKUP_LEN]
Definition: cairo.c:215
external_drawable
static int external_drawable
Definition: cairo.c:81
PLDispatchTable::pl_wait
plD_wait_fp pl_wait
Definition: disptab.h:91
PLCairo::pangoMarkupString
char * pangoMarkupString
Definition: cairo.c:109
plD_dispatch_init_epscairo
PLDLLIMPEXP_DRIVER void plD_dispatch_init_epscairo(PLDispatchTable *pdt)
PL_UNUSED
#define PL_UNUSED(x)
Definition: plplot.h:138
PLGraphicsIn::pX
int pX
Definition: plplot.h:441
PLFLT
float PLFLT
Definition: plplot.h:163
PLCairo::cairoContext_raster
cairo_t * cairoContext_raster
Definition: cairo.c:101
PLESC_START_RASTERIZE
#define PLESC_START_RASTERIZE
Definition: plplot.h:302
arc_struct::y
PLFLT y
Definition: plplotP.h:1104
PL_FCI_FAMILY
#define PL_FCI_FAMILY
Definition: plplot.h:376
PLTEXT_UNDERLINE
#define PLTEXT_UNDERLINE
Definition: plplot.h:319
PLStream::page
PLINT page
Definition: plstrm.h:578
PLStream::chrht
PLFLT chrht
Definition: plstrm.h:686
plD_bop_fp
void(* plD_bop_fp)(struct PLStream_struct *)
Definition: disptab.h:71
set_background
static int set_background
Definition: cairo.c:83
free_mem
#define free_mem(a)
Definition: plplotP.h:182
plD_dispatch_init_memcairo
PLDLLIMPEXP_DRIVER void plD_dispatch_init_memcairo(PLDispatchTable *pdt)
PLStream::phyxma
PLINT phyxma
Definition: plstrm.h:705
PL_FCI_WEIGHT
#define PL_FCI_WEIGHT
Definition: plplot.h:378
PI
#define PI
Definition: plplotP.h:290
write_to_stream
cairo_status_t write_to_stream(void *, unsigned char *, unsigned int)
Definition: cairo.c:1277
arc_struct
Definition: plplotP.h:1101
PLCAIRO_DEFAULT_Y
#define PLCAIRO_DEFAULT_Y
Definition: cairo.c:73
PLGraphicsIn::state
unsigned int state
Definition: plplot.h:436
plD_line_cairo
void plD_line_cairo(PLStream *, short, short, short, short)
Definition: cairo.c:434
PLColor::r
unsigned char r
Definition: plplot.h:548
set_current_context
static void set_current_context(PLStream *)
Definition: cairo.c:1401
PLESC_HAS_TEXT
#define PLESC_HAS_TEXT
Definition: plplot.h:290
PLStream::width
PLFLT width
Definition: plstrm.h:552
plwarn
void plwarn(PLCHAR_VECTOR errormsg)
Definition: plctrl.c:1863
text_end_cairo
static void text_end_cairo(PLStream *pls, EscText *args)
Definition: cairo.c:773
PLCAIRO_DEFAULT_X
#define PLCAIRO_DEFAULT_X
Definition: cairo.c:72
PLESC_ARC
#define PLESC_ARC
Definition: plplot.h:304
EscText::y
PLINT y
Definition: plplotP.h:713
DRV_INT
Definition: plplotP.h:758
PLStream::dev_mem_alpha
PLINT dev_mem_alpha
Definition: plstrm.h:784
display
static const char * display
Definition: tkMain.c:136
PLGraphicsIn::button
unsigned int button
Definition: plplot.h:438
PLStream::curcolor
PLColor curcolor
Definition: plstrm.h:543
filled_polygon
static void filled_polygon(PLStream *pls, short *xa, short *ya, PLINT npts)
Definition: cairo.c:1452
PLDispatchTable::pl_state
plD_state_fp pl_state
Definition: disptab.h:89
MAX_MARKUP_LEN
#define MAX_MARKUP_LEN
Definition: cairo.c:76
PLCairo::text_anti_aliasing
short text_anti_aliasing
Definition: cairo.c:103
PLGraphicsIn::dY
PLFLT dY
Definition: plplot.h:442
PLDispatchTable::pl_eop
plD_eop_fp pl_eop
Definition: disptab.h:86
PLStream::xoffset
PLINT xoffset
Definition: plstrm.h:618
defaultFamilyLookup
const char * defaultFamilyLookup[NPANGOLOOKUP]
Definition: cairo.c:198
PLCairo::uline
short uline
Definition: cairo.c:112
PLStream::ncol1
PLINT ncol1
Definition: plstrm.h:539
PLESC_GRADIENT
#define PLESC_GRADIENT
Definition: plplot.h:305
EscText::x
PLINT x
Definition: plplotP.h:712
PLESC_GETC
#define PLESC_GETC
Definition: plplot.h:283
PLStream::string_length
PLFLT string_length
Definition: plstrm.h:786
blit_to_x
static void blit_to_x(PLStream *pls, double x, double y, double w, double h)
PLCairo::level
PLINT level
Definition: cairo.c:121
PLStream::dev_flush
PLINT dev_flush
Definition: plstrm.h:571
EscText::n_char
PLUNICODE n_char
Definition: plplotP.h:727
PL_DRAWMODE_DEFAULT
#define PL_DRAWMODE_DEFAULT
Definition: plplot.h:1319
PLGraphicsIn::pY
int pY
Definition: plplot.h:441
PLDispatchTable::pl_polyline
plD_polyline_fp pl_polyline
Definition: disptab.h:85
plD_state_fp
void(* plD_state_fp)(struct PLStream_struct *, PLINT)
Definition: disptab.h:73
EscText::unicode_array
PLUNICODE * unicode_array
Definition: plplotP.h:735
arc_struct::angle1
PLFLT angle1
Definition: plplotP.h:1107
PLStream::dev
void * dev
Definition: plstrm.h:594
PLGraphicsIn::string
char string[PL_MAXKEY]
Definition: plplot.h:440
plD_DEVICE_INFO_cairo
PLDLLIMPEXP_DRIVER const char * plD_DEVICE_INFO_cairo
Definition: cairo.c:149
M_PI
#define M_PI
Definition: plplotP.h:119
PLStream::freeaspect
PLINT freeaspect
Definition: plstrm.h:665
PLStream::dev_fill0
PLINT dev_fill0
Definition: plstrm.h:571
PLDispatchTable::pl_type
int pl_type
Definition: disptab.h:81
EscText::xform
PLFLT * xform
Definition: plplotP.h:709
stream_and_font_setup
PLCairo * stream_and_font_setup(PLStream *, int)
Definition: cairo.c:1301
plD_state_cairo
void plD_state_cairo(PLStream *, PLINT)
PLStream::dev_eofill
PLINT dev_eofill
Definition: plstrm.h:788
PLESC_FLUSH
#define PLESC_FLUSH
Definition: plplot.h:281
PL_FCI_MARK
#define PL_FCI_MARK
Definition: plplot.h:370
PLStream::has_string_length
PLINT has_string_length
Definition: plstrm.h:785
PLGraphicsIn
Definition: plplot.h:433