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
78static int text_clipping;
82static int rasterize_image;
83static int set_background;
84static int image_buffering;
85static int already_warned = 0;
86
87static 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
96typedef struct
97{
98 cairo_surface_t *cairoSurface;
99 cairo_t *cairoContext;
100 cairo_surface_t *cairoSurface_raster;
108 double downscale;
110 short upDown;
111 float fontSize;
112 short uline;
113
114 // These are arguments for plP_script_scale which must be retained
115 // in aStream for the alt_unicode approach. level has an
116 // identical meaning to upDown above, but it is incremented and
117 // decremented in plP_script_scale as well as other places in the
118 // code so the only safe thing to do is to treat level separately
119 // from upDown.
120 PLFLT old_sscale, sscale, old_soffset, soffset;
122
123#if defined ( PLD_xcairo )
124 cairo_surface_t *cairoSurface_X;
125 cairo_t *cairoContext_X;
126 short exit_event_loop;
127 Display *XDisplay;
128 Window XWindow;
129 unsigned int xdrawable_mode;
130#endif
131#if defined ( PLD_memcairo )
132 unsigned char *memory;
133 unsigned char *cairo_format_memory;
134 char bigendian;
135#endif
136#if defined ( PLD_wincairo )
137 cairo_surface_t *cairoSurface_win;
138 cairo_t *cairoContext_win;
139 WNDCLASSEX wndclass;
140 HWND hwnd;
141 MSG msg;
142 HDC hdc;
143 HDC SCRN_hdc;
144 COLORREF oldcolour;
145 RECT rect;
146#endif
147} PLCairo;
148
150#if defined ( PLD_xcairo )
151 "xcairo:Cairo X Windows Driver:1:cairo:100:xcairo\n"
152#endif
153#if defined ( PLD_pdfcairo )
154 "pdfcairo:Cairo PDF Driver:0:cairo:101:pdfcairo\n"
155#endif
156#if defined ( PLD_pscairo )
157 "pscairo:Cairo PS Driver:0:cairo:102:pscairo\n"
158#endif
159#if defined ( PLD_epscairo )
160 "epscairo:Cairo EPS Driver:0:cairo:103:epscairo\n"
161#endif
162#if defined ( PLD_svgcairo )
163 "svgcairo:Cairo SVG Driver:0:cairo:104:svgcairo\n"
164#endif
165#if defined ( PLD_pngcairo )
166 "pngcairo:Cairo PNG Driver:0:cairo:105:pngcairo\n"
167#endif
168#if defined ( PLD_memcairo )
169 "memcairo:Cairo Memory Driver:0:cairo:106:memcairo\n"
170#endif
171#if defined ( PLD_extcairo )
172 "extcairo:Cairo External Context Driver:0:cairo:107:extcairo\n"
173#endif
174#if defined ( PLD_wincairo )
175 "wincairo:Cairo Microscoft Windows Driver:0:cairo:108:wincairo\n"
176#endif
177;
178
179//
180// Structure for passing external drawables to xcairo devices via
181// the PLESC_DEVINIT escape function.
182//
183#if defined ( PLD_xcairo )
184typedef struct
185{
186 Display *display;
187 Drawable drawable;
188} PLXcairoDrawableInfo;
189#endif
190
191//--------------------------------------------------------------------------
192// Font style and weight lookup tables (copied
193// from the psttf driver).
194//--------------------------------------------------------------------------
195
196#define NPANGOLOOKUP 5
197
199 "sans",
200 "serif",
201 "monospace",
202 "sans,serif",
203 "sans,serif"
204};
205
207 "PLPLOT_FREETYPE_SANS_FAMILY",
208 "PLPLOT_FREETYPE_SERIF_FAMILY",
209 "PLPLOT_FREETYPE_MONO_FAMILY",
210 "PLPLOT_FREETYPE_SCRIPT_FAMILY",
211 "PLPLOT_FREETYPE_SYMBOL_FAMILY"
212};
213
214#define FAMILY_LOOKUP_LEN 1024
216
217#define TAG_LEN 200
218
219const char *weightLookup[2] = {
220 "normal",
221 "bold"
222};
223
224const 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
245cairo_status_t write_to_stream( void *, unsigned char *, unsigned int );
246void set_clip( PLStream *pls );
248
249// String processing
250
251static void proc_str( PLStream *, EscText * );
252static void text_begin_cairo( PLStream *pls, EscText *args );
253static void text_char_cairo( PLStream *pls, EscText *args );
254static void text_esc_cairo( PLStream *pls, EscText *args );
255static void text_end_cairo( PLStream *pls, EscText *args );
256static char *ucs4_to_pango_markup_format( PLUNICODE *, int, float );
257static void open_span_tag( char *, PLUNICODE, float, int );
258static void close_span_tag( char *, int );
259static char *rise_span_tag( int, float, float, float );
260
261// Graphics
262
263static void set_current_context( PLStream * );
264static void poly_line( PLStream *, short *, short *, PLINT );
265static void filled_polygon( PLStream *pls, short *xa, short *ya, PLINT npts );
266static void gradient( PLStream *pls, short *xa, short *ya, PLINT npts );
267static void arc( PLStream *, arc_struct * );
268static void rotate_cairo_surface( PLStream *, float, float, float, float, float, float, PLBOOL );
269static void blit_to_x( PLStream *pls, double x, double y, double w, double h );
270// Rasterization of plotted material
271static void start_raster( PLStream* );
272static void end_raster( PLStream* );
273// Get/set drawing mode
274static void set_mode( PLStream*, PLINT* );
275static void get_mode( PLStream*, PLINT* );
276// Get / set line properties
277void get_line_properties( PLCairo *aStream, cairo_line_join_t *join, cairo_line_cap_t *cap );
278void set_line_properties( PLCairo *aStream, cairo_line_join_t join, cairo_line_cap_t cap );
279
280
281// PLplot interface functions
282
283// general
284void plD_bop_cairo( PLStream * );
285void plD_eop_cairo( PLStream * );
287void plD_esc_cairo( PLStream *, PLINT, void * );
288void plD_tidy_cairo( PLStream * );
289void plD_line_cairo( PLStream *, short, short, short, short );
290void plD_polyline_cairo( PLStream *, short *, short *, PLINT );
291
292//--------------------------------------------------------------------------
293// start_raster()
294//
295// Set up off-screen rasterized rendering
296//--------------------------------------------------------------------------
297
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
343{
344 PLCairo *aStream;
345 cairo_surface_t *tmp_sfc;
346 cairo_t *tmp_context;
347
348 aStream = (PLCairo *) pls->dev;
349
350 // TODO FIXME: This should really only copy the used portion of the
351 // offscreen pixmap.
352
353 // Do not use the external surface if the user says not to
354 if ( !aStream->rasterize_image )
355 return;
356
357 // Some Cairo devices support delayed device setup (eg: xcairo with
358 // external drawable and extcairo with an external context).
359 if ( aStream->cairoContext == NULL )
360 plexit( "Can not plot to a Cairo device with no context" );
361
362 // Restore the main plot surface and context for future plotting
363 tmp_sfc = aStream->cairoSurface;
364 tmp_context = aStream->cairoContext;
365 aStream->cairoSurface = aStream->cairoSurface_raster;
366 aStream->cairoContext = aStream->cairoContext_raster;
367 aStream->cairoSurface_raster = tmp_sfc;
368 aStream->cairoContext_raster = tmp_context;
369
370 // Blit the raster surface on to the main plot
371 cairo_set_source_surface( aStream->cairoContext, aStream->cairoSurface_raster, 0.0, 0.0 );
372 cairo_paint( aStream->cairoContext );
373
374 // Free the now extraneous surface and context
375 cairo_destroy( aStream->cairoContext_raster );
376 cairo_surface_destroy( aStream->cairoSurface_raster );
377}
378
379//--------------------------------------------------------------------------
380// plD_bop_cairo()
381//
382// Set up for the next page.
383//--------------------------------------------------------------------------
384
386{
387 PLCairo *aStream;
388
389 aStream = (PLCairo *) pls->dev;
390
391 // Some Cairo devices support delayed device setup (eg: xcairo with
392 // external drawable and extcairo with an external context).
393 if ( aStream->cairoContext == NULL )
394 return;
395
396 // Fill in the window with the background color.
397 cairo_rectangle( aStream->cairoContext, 0.0, 0.0, pls->xlength, pls->ylength );
398 if ( (double) pls->cmap0[0].a < 1.0 )
399 {
400 cairo_set_source_rgba( aStream->cairoContext, 1.0, 1.0, 1.0, 1.0 );
401 cairo_fill_preserve( aStream->cairoContext );
402 }
403 cairo_set_source_rgba( aStream->cairoContext,
404 (double) pls->cmap0[0].r / 255.0,
405 (double) pls->cmap0[0].g / 255.0,
406 (double) pls->cmap0[0].b / 255.0,
407 (double) pls->cmap0[0].a );
408 cairo_fill( aStream->cairoContext );
409}
410
411//--------------------------------------------------------------------------
412// plD_line_cairo()
413//
414// Draw a line in the current color from (x1,y1) to (x2,y2).
415//--------------------------------------------------------------------------
416
417//--------------------------------------------------------------------------
418// (get|set)_line_properties
419//
420// (Get|Set) the current Cairo line drawing properties.
421//--------------------------------------------------------------------------
422void 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
428void 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
434void plD_line_cairo( PLStream *pls, short x1a, short y1a, short x2a, short y2a )
435{
436 PLCairo *aStream;
437
438 aStream = (PLCairo *) pls->dev;
439
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
460void plD_polyline_cairo( PLStream *pls, short *xa, short *ya, PLINT npts )
461{
462 PLCairo *aStream;
463
464 aStream = (PLCairo *) pls->dev;
465
466 cairo_save( aStream->cairoContext );
467
468 set_line_properties( aStream, CAIRO_LINE_JOIN_BEVEL, CAIRO_LINE_CAP_BUTT );
469
470 poly_line( pls, xa, ya, npts );
471
472 cairo_stroke( aStream->cairoContext );
473
474 cairo_restore( aStream->cairoContext );
475}
476
477//--------------------------------------------------------------------------
478// plD_eop_cairo()
479//
480// Generic end of page.
481//--------------------------------------------------------------------------
482
484{
485 PLCairo *aStream;
486
487 aStream = (PLCairo *) pls->dev;
488
489 cairo_show_page( aStream->cairoContext );
490}
491
492//--------------------------------------------------------------------------
493// plD_tidy_cairo()
494//
495// General: Close graphics file or otherwise clean up.
496//--------------------------------------------------------------------------
497
499{
500 PLCairo *aStream;
501
502 aStream = (PLCairo *) pls->dev;
503
504 // Free the cairo context and surface.
505 cairo_destroy( aStream->cairoContext );
506 cairo_surface_destroy( aStream->cairoSurface );
507
508 plCloseFile( pls );
509}
510
511//--------------------------------------------------------------------------
512// plD_state_cairo()
513//
514// Handle change in PLStream state (color, pen width, fill attribute, etc).
515//
516// Nothing is done here because these attributes are acquired from
517// PLStream for each element that is drawn.
518//--------------------------------------------------------------------------
519
521{
522}
523
524//--------------------------------------------------------------------------
525// plD_esc_cairo()
526//
527// Generic escape function.
528//--------------------------------------------------------------------------
529
530void 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
540 break;
541 case PLESC_GRADIENT: // render a gradient within a polygon.
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//--------------------------------------------------------------------------
586void 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;
597 cairo_set_operator( aStream->cairoContext, CAIRO_OPERATOR_OVER );
598 break;
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//--------------------------------------------------------------------------
614void 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
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
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
705{
706 PLCairo *aStream;
707
708 aStream = (PLCairo *) pls->dev;
709 switch ( args->n_ctrl_char )
710 {
712 close_span_tag( aStream->pangoMarkupString, aStream->upDown );
713 open_span_tag( aStream->pangoMarkupString, args->n_fci, aStream->fontSize, aStream->upDown );
714 break;
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
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
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
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
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
992char *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
1137void 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
1199void 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
1239char *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
1277cairo_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
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 {
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
1377
1378 // Turn off text clipping if the user desires this
1379 if ( !text_clipping )
1380 {
1381 aStream->text_clipping = 0;
1382 }
1383
1384 // Record users desired text and graphics aliasing and rasterization
1385 aStream->text_anti_aliasing = (short) text_anti_aliasing;
1387 aStream->rasterize_image = (short) rasterize_image;
1388 aStream->set_background = (short) set_background;
1389 aStream->image_buffering = (short) image_buffering;
1390
1391 return aStream;
1392}
1393
1394//--------------------------------------------------------------------------
1395// set_current_context()
1396//
1397// Updates the cairo graphics context with the current values in
1398// PLStream.
1399//--------------------------------------------------------------------------
1400
1402{
1403 PLCairo *aStream;
1404
1405 aStream = (PLCairo *) pls->dev;
1406 cairo_set_source_rgba( aStream->cairoContext,
1407 (double) pls->curcolor.r / 255.0,
1408 (double) pls->curcolor.g / 255.0,
1409 (double) pls->curcolor.b / 255.0,
1410 (double) pls->curcolor.a );
1411 // In Cairo, zero width lines are not hairlines, they are completely invisible.
1412 if ( pls->width <= 0. )
1413 {
1414 cairo_set_line_width( aStream->cairoContext, 1.0 );
1415 }
1416 else
1417 {
1418 cairo_set_line_width( aStream->cairoContext, (double) pls->width );
1419 }
1420}
1421
1422//--------------------------------------------------------------------------
1423// poly_line()
1424//
1425// Draws a multi-segmented line. It is then up to the calling function
1426// to decide whether to just draw the line, or fill in the area
1427// enclosed by the line.
1428//--------------------------------------------------------------------------
1429
1430void poly_line( PLStream *pls, short *xa, short *ya, PLINT npts )
1431{
1432 int i;
1433 PLCairo *aStream;
1434
1435 aStream = (PLCairo *) pls->dev;
1436
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
1452void 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
1499void 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
1544{
1545 PLINT rcx[4], rcy[4];
1546 PLCairo *aStream;
1547 aStream = (PLCairo *) pls->dev;
1548
1549 // Use PLplot core routine to get the corners of the clipping rectangle
1550 difilt_clip( rcx, rcy );
1551
1552 // Layout the bounds of the clipping region
1553 // Should we convert PLINT to short and use the polyline routine?
1554 cairo_move_to( aStream->cairoContext,
1555 aStream->downscale * (double) rcx[0],
1556 aStream->downscale * (double) rcy[0] );
1557 cairo_line_to( aStream->cairoContext,
1558 aStream->downscale * (double) rcx[1],
1559 aStream->downscale * (double) rcy[1] );
1560 cairo_line_to( aStream->cairoContext,
1561 aStream->downscale * (double) rcx[2],
1562 aStream->downscale * (double) rcy[2] );
1563 cairo_line_to( aStream->cairoContext,
1564 aStream->downscale * (double) rcx[3],
1565 aStream->downscale * (double) rcy[3] );
1566 cairo_line_to( aStream->cairoContext,
1567 aStream->downscale * (double) rcx[0],
1568 aStream->downscale * (double) rcy[0] );
1569
1570 // Set the clipping region
1571 cairo_clip( aStream->cairoContext );
1572
1573 // Apparently, in some older Cairo versions, cairo_clip does not consume
1574 // the current path.
1575 cairo_new_path( aStream->cairoContext );
1576}
1577
1578//--------------------------------------------------------------------------
1579// cairo_family_check ()
1580//
1581// support function to help supress more than one page if family file
1582// output not specified by the user (e.g., with the -fam command-line option).
1583//--------------------------------------------------------------------------
1584
1586{
1587 if ( pls->family || pls->page == 1 )
1588 {
1589 return 0;
1590 }
1591 else
1592 {
1593 if ( !already_warned )
1594 {
1595 already_warned = 1;
1596 plwarn( "All pages after the first skipped because family file output not specified.\n" );
1597 }
1598 return 1;
1599 }
1600}
1601
1602//--------------------------------------------------------------------------
1603// arc()
1604//
1605// Draws an arc, possibly filled.
1606//--------------------------------------------------------------------------
1607
1608void arc( PLStream *pls, arc_struct *arc_info )
1609{
1610 PLCairo *aStream;
1611 double x, y, a, b;
1612 double angle1, angle2, rotate;
1613
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
1666void 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
1699void plD_bop_cairo_fam( PLStream * );
1700void plD_eop_cairo_fam( PLStream * );
1701void plD_state_cairo_fam( PLStream *, PLINT );
1702void plD_esc_cairo_fam( PLStream *, PLINT, void * );
1703void plD_tidy_cairo_fam( PLStream * );
1704void plD_line_cairo_fam( PLStream *, short, short, short, short );
1705void 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
1713void 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
1748void 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
1764void 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
1780void 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
1796void plD_tidy_cairo_fam( PLStream *pls )
1797{
1799}
1800
1801//--------------------------------------------------------------------------
1802// plD_line_cairo_fam()
1803//
1804// Draw a line.
1805//--------------------------------------------------------------------------
1806
1807void 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
1823void 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
1844static int XScreen;
1845static Window rootWindow;
1846
1848void plD_init_xcairo( PLStream * );
1849void plD_bop_xcairo( PLStream * );
1850void plD_eop_xcairo( PLStream * );
1851void plD_tidy_xcairo( PLStream * );
1852void plD_wait_xcairo( PLStream * );
1853void plD_esc_xcairo( PLStream *, PLINT, void * );
1854static void xcairo_get_cursor( PLStream *, PLGraphicsIn * );
1855
1856//--------------------------------------------------------------------------
1857// plD_dispatch_init_xcairo()
1858//
1859// xcairo dispatch table initialization.
1860//--------------------------------------------------------------------------
1861
1863{
1864#ifndef ENABLE_DYNDRIVERS
1865 pdt->pl_MenuStr = "Cairo X Windows Driver";
1866 pdt->pl_DevName = "xcairo";
1867#endif
1869 pdt->pl_seq = 100;
1870 pdt->pl_init = (plD_init_fp) plD_init_xcairo;
1873 pdt->pl_eop = (plD_eop_fp) plD_eop_xcairo;
1874 pdt->pl_bop = (plD_bop_fp) plD_bop_xcairo;
1875 pdt->pl_tidy = (plD_tidy_fp) plD_tidy_xcairo;
1877 pdt->pl_esc = (plD_esc_fp) plD_esc_xcairo;
1878 pdt->pl_wait = (plD_wait_fp) plD_wait_xcairo;
1879}
1880
1881//--------------------------------------------------------------------------
1882// xcairo_init_cairo()
1883//
1884// Configures Cairo to use whichever X Drawable is set up in the given
1885// stream. This is called by plD_init_xcairo() in the event we are
1886// drawing into a plplot-managed window, and plD_esc_xcairo() if
1887// we are using an external X Drawable.
1888//
1889// A return value of 0 indicates success. Currently this function only
1890// returns 0.
1891//--------------------------------------------------------------------------
1892
1893static 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
1969void 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
2031void 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
2066void 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
2086void 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
2102void plD_tidy_xcairo( PLStream *pls )
2103{
2104 PLCairo *aStream;
2105
2106 aStream = (PLCairo *) pls->dev;
2107
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
2131void 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");
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
2196void 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
2265void 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
2347void plD_init_pdfcairo( PLStream * );
2348
2349//--------------------------------------------------------------------------
2350// dispatch_init_init()
2351//
2352// Initialize device dispatch table
2353//--------------------------------------------------------------------------
2354
2355// pdfcairo
2357{
2358#ifndef ENABLE_DYNDRIVERS
2359 pdt->pl_MenuStr = "Cairo PDF Driver";
2360 pdt->pl_DevName = "pdfcairo";
2361#endif
2363 pdt->pl_seq = 101;
2364 pdt->pl_init = (plD_init_fp) plD_init_pdfcairo;
2372}
2373
2374//--------------------------------------------------------------------------
2375// plD_init_pdfcairo()
2376//
2377// Initialize Cairo PDF device
2378//--------------------------------------------------------------------------
2379
2380void 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
2425void plD_init_pscairo( PLStream * );
2426
2427//--------------------------------------------------------------------------
2428// dispatch_init_init()
2429//
2430// Initialize device dispatch table
2431//--------------------------------------------------------------------------
2432
2433// pscairo
2435{
2436#ifndef ENABLE_DYNDRIVERS
2437 pdt->pl_MenuStr = "Cairo PS Driver";
2438 pdt->pl_DevName = "pscairo";
2439#endif
2441 pdt->pl_seq = 102;
2442 pdt->pl_init = (plD_init_fp) plD_init_pscairo;
2450}
2451
2452//--------------------------------------------------------------------------
2453// plD_init_pscairo()
2454//
2455// Initialize Cairo PS device
2456//--------------------------------------------------------------------------
2457
2458void 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
2505void plD_init_epscairo( PLStream * );
2506
2507//--------------------------------------------------------------------------
2508// dispatch_init_init()
2509//
2510// Initialize device dispatch table
2511//--------------------------------------------------------------------------
2512
2513// epscairo
2515{
2516#ifndef ENABLE_DYNDRIVERS
2517 pdt->pl_MenuStr = "Cairo EPS Driver";
2518 pdt->pl_DevName = "epscairo";
2519#endif
2521 pdt->pl_seq = 102;
2522 pdt->pl_init = (plD_init_fp) plD_init_epscairo;
2523 pdt->pl_line = (plD_line_fp) plD_line_cairo_fam;
2524 pdt->pl_polyline = (plD_polyline_fp) plD_polyline_cairo_fam;
2525 pdt->pl_eop = (plD_eop_fp) plD_eop_cairo_fam;
2526 pdt->pl_bop = (plD_bop_fp) plD_bop_cairo_fam;
2527 pdt->pl_tidy = (plD_tidy_fp) plD_tidy_cairo_fam;
2528 pdt->pl_state = (plD_state_fp) plD_state_cairo_fam;
2529 pdt->pl_esc = (plD_esc_fp) plD_esc_cairo_fam;
2530}
2531
2532//--------------------------------------------------------------------------
2533// plD_init_epscairo()
2534//
2535// Initialize Cairo EPS device
2536//--------------------------------------------------------------------------
2537
2538void 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 {
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
2609void plD_init_svgcairo( PLStream * );
2610
2611//--------------------------------------------------------------------------
2612// dispatch_init_init()
2613//
2614// Initialize device dispatch table
2615//--------------------------------------------------------------------------
2616
2617// svgcairo
2619{
2620#ifndef ENABLE_DYNDRIVERS
2621 pdt->pl_MenuStr = "Cairo SVG Driver";
2622 pdt->pl_DevName = "svgcairo";
2623#endif
2625 pdt->pl_seq = 103;
2626 pdt->pl_init = (plD_init_fp) plD_init_svgcairo;
2627 pdt->pl_line = (plD_line_fp) plD_line_cairo_fam;
2628 pdt->pl_polyline = (plD_polyline_fp) plD_polyline_cairo_fam;
2629 pdt->pl_eop = (plD_eop_fp) plD_eop_cairo_fam;
2630 pdt->pl_bop = (plD_bop_fp) plD_bop_cairo_fam;
2631 pdt->pl_tidy = (plD_tidy_fp) plD_tidy_cairo_fam;
2632 pdt->pl_state = (plD_state_fp) plD_state_cairo_fam;
2633 pdt->pl_esc = (plD_esc_fp) plD_esc_cairo_fam;
2634}
2635
2636//--------------------------------------------------------------------------
2637// plD_init_svgcairo()
2638//
2639// Initialize Cairo SVG device
2640//--------------------------------------------------------------------------
2641
2642void 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 {
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
2708void plD_init_pngcairo( PLStream * );
2709void plD_eop_pngcairo( PLStream * );
2710
2711//--------------------------------------------------------------------------
2712// dispatch_init_init()
2713//
2714// Initialize device dispatch table
2715//--------------------------------------------------------------------------
2716
2717// pngcairo
2719{
2720#ifndef ENABLE_DYNDRIVERS
2721 pdt->pl_MenuStr = "Cairo PNG Driver";
2722 pdt->pl_DevName = "pngcairo";
2723#endif
2725 pdt->pl_seq = 104;
2726 pdt->pl_init = (plD_init_fp) plD_init_pngcairo;
2727 pdt->pl_line = (plD_line_fp) plD_line_cairo_fam;
2728 pdt->pl_polyline = (plD_polyline_fp) plD_polyline_cairo_fam;
2729 pdt->pl_eop = (plD_eop_fp) plD_eop_pngcairo;
2730 pdt->pl_bop = (plD_bop_fp) plD_bop_cairo_fam;
2731 pdt->pl_tidy = (plD_tidy_fp) plD_tidy_cairo_fam;
2732 pdt->pl_state = (plD_state_fp) plD_state_cairo_fam;
2733 pdt->pl_esc = (plD_esc_fp) plD_esc_cairo_fam;
2734}
2735
2736//--------------------------------------------------------------------------
2737// plD_init_pngcairo()
2738//
2739// Initialize Cairo PNG device
2740//--------------------------------------------------------------------------
2741
2742void 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 {
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
2800void 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
2827void plD_init_memcairo( PLStream * );
2828void plD_eop_memcairo( PLStream * );
2829void plD_bop_memcairo( PLStream * );
2830
2831//--------------------------------------------------------------------------
2832// dispatch_init_init()
2833//
2834// Initialize device dispatch table
2835//--------------------------------------------------------------------------
2836
2837// memcairo
2839{
2840#ifndef ENABLE_DYNDRIVERS
2841 pdt->pl_MenuStr = "Cairo memory driver";
2842 pdt->pl_DevName = "memcairo";
2843#endif
2845 pdt->pl_seq = 105;
2846 pdt->pl_init = (plD_init_fp) plD_init_memcairo;
2849 pdt->pl_eop = (plD_eop_fp) plD_eop_memcairo;
2850 pdt->pl_bop = (plD_bop_fp) plD_bop_memcairo;
2854}
2855
2856//--------------------------------------------------------------------------
2857// plD_bop_memcairo()
2858//
2859// Set up for the next page.
2860//--------------------------------------------------------------------------
2861
2862void 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
2873void 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
3000void 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
3068void extcairo_setbackground( PLStream * );
3070void plD_init_extcairo( PLStream * );
3071void plD_bop_extcairo( PLStream * );
3072void plD_eop_extcairo( PLStream * );
3073void plD_esc_extcairo( PLStream *, PLINT, void * );
3074void plD_tidy_extcairo( PLStream * );
3075
3076//--------------------------------------------------------------------------
3077// extcairo_setbackground()
3078//
3079// Set the background color for the extcairo device
3080//--------------------------------------------------------------------------
3081
3082void extcairo_setbackground( PLStream *pls )
3083{
3084 PLCairo *aStream;
3085
3086 aStream = (PLCairo *) pls->dev;
3087
3088 // Fill the context with the background color if the user so desires.
3089 if ( aStream->cairoContext != NULL )
3090 {
3091 cairo_rectangle( aStream->cairoContext, 0.0, 0.0, pls->xlength, pls->ylength );
3092 cairo_set_source_rgba( aStream->cairoContext,
3093 (double) pls->cmap0[0].r / 255.0,
3094 (double) pls->cmap0[0].g / 255.0,
3095 (double) pls->cmap0[0].b / 255.0,
3096 (double) pls->cmap0[0].a );
3097 cairo_fill( aStream->cairoContext );
3098 }
3099}
3100
3101//--------------------------------------------------------------------------
3102// dispatch_init_init()
3103//
3104// Initialize device dispatch table
3105//--------------------------------------------------------------------------
3106
3107// extcairo
3109{
3110#ifndef ENABLE_DYNDRIVERS
3111 pdt->pl_MenuStr = "Cairo external context driver";
3112 pdt->pl_DevName = "extcairo";
3113#endif
3115 pdt->pl_seq = 106;
3116 pdt->pl_init = (plD_init_fp) plD_init_extcairo;
3119 pdt->pl_bop = (plD_bop_fp) plD_bop_extcairo;
3120 pdt->pl_eop = (plD_eop_fp) plD_eop_extcairo;
3121 pdt->pl_tidy = (plD_tidy_fp) plD_tidy_extcairo;
3123 pdt->pl_esc = (plD_esc_fp) plD_esc_extcairo;
3124}
3125
3126//--------------------------------------------------------------------------
3127// plD_init_extcairo()
3128//
3129// Initialize Cairo external context driver.
3130//--------------------------------------------------------------------------
3131
3132void 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
3149void 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
3168void 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
3181void 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
3225void 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
3245static char* szWndClass = "PLplot WinCairo";
3246
3248void plD_init_wincairo( PLStream * );
3249//void plD_bop_extcairo( PLStream * );
3250void plD_eop_wincairo( PLStream * );
3251void plD_wait_wincairo( PLStream * );
3252void plD_esc_wincairo( PLStream *, PLINT, void * );
3253void plD_tidy_wincairo( PLStream * );
3254
3255//--------------------------------------------------------------------------
3256// blit_to_win()
3257//
3258// Blit the offscreen image to the Windows window.
3259//--------------------------------------------------------------------------
3260
3261void 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
3273LRESULT 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
3364void
3365handle_locate( PLStream *pls, PLGraphicsIn *gin )
3366{
3367 int located = 0;
3368 PLCairo *aStream = (PLCairo *) pls->dev;
3369
3370 // Initialize PLplot mouse event structure
3371 plGinInit( gin );
3372
3373 while ( GetMessage( &aStream->msg, NULL, 0, 0 ) && !located )
3374 {
3375 TranslateMessage( &aStream->msg );
3376
3377 switch ( (int) aStream->msg.message )
3378 {
3379 case WM_MOUSEMOVE:
3380 case WM_LBUTTONDOWN:
3381 gin->state = 1;
3382 gin->button = 1;
3383 gin->pX = LOWORD( aStream->msg.lParam );
3384 gin->pY = pls->ylength - HIWORD( aStream->msg.lParam );
3385 gin->dX = (PLFLT) LOWORD( aStream->msg.lParam ) / ( (PLFLT) pls->xlength );
3386 gin->dY = (PLFLT) ( pls->ylength - HIWORD( aStream->msg.lParam ) ) / ( (PLFLT) pls->ylength );
3387 break;
3388 case WM_CHAR:
3389 gin->keysym = aStream->msg.wParam;
3390 located = 1;
3391 break;
3392
3393 default:
3394 DispatchMessage( &aStream->msg );
3395 break;
3396 }
3397 }
3398}
3399
3400//--------------------------------------------------------------------------
3401// dispatch_init_init()
3402//
3403// Initialize device dispatch table
3404//--------------------------------------------------------------------------
3405
3406// extcairo
3408{
3409#ifndef ENABLE_DYNDRIVERS
3410 pdt->pl_MenuStr = "Cairo Microsoft Windows driver";
3411 pdt->pl_DevName = "wincairo";
3412#endif
3414 pdt->pl_seq = 107;
3415 pdt->pl_init = (plD_init_fp) plD_init_wincairo;
3419 pdt->pl_eop = (plD_eop_fp) plD_eop_wincairo;
3420 pdt->pl_tidy = (plD_tidy_fp) plD_tidy_wincairo;
3422 pdt->pl_esc = (plD_esc_fp) plD_esc_wincairo;
3423 pdt->pl_wait = (plD_wait_fp) plD_wait_wincairo;
3424}
3425
3426//--------------------------------------------------------------------------
3427// plD_init_wincairo()
3428//
3429// Initialize Cairo Microsoft Windows driver.
3430//--------------------------------------------------------------------------
3431
3432void 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
3569void
3570plD_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
3581void
3582plD_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
3613void plD_tidy_wincairo( PLStream *pls )
3614{
3615 PLCairo *aStream = (PLCairo *) pls->dev;
3616
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
3637void 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
const char * envFamilyLookup[NPANGOLOOKUP]
Definition: cairo.c:206
static void proc_str(PLStream *, EscText *)
Definition: cairo.c:873
void set_line_properties(PLCairo *aStream, cairo_line_join_t join, cairo_line_cap_t cap)
Definition: cairo.c:428
static void close_span_tag(char *, int)
Definition: cairo.c:1199
static DrvOpt cairo_options[]
Definition: cairo.c:87
#define RISE_FACTOR
Definition: cairo.c:1226
void set_clip(PLStream *pls)
Definition: cairo.c:1543
void plD_state_cairo(PLStream *, PLINT)
static void text_esc_cairo(PLStream *pls, EscText *args)
Definition: cairo.c:704
static int graphics_anti_aliasing
Definition: cairo.c:80
static void gradient(PLStream *pls, short *xa, short *ya, PLINT npts)
Definition: cairo.c:1499
static void poly_line(PLStream *, short *, short *, PLINT)
Definition: cairo.c:1430
#define TAG_LEN
Definition: cairo.c:217
#define MAX_MARKUP_LEN
Definition: cairo.c:76
#define MAX_STRING_LEN
Definition: cairo.c:75
PLDLLIMPEXP_DRIVER const char * plD_DEVICE_INFO_cairo
Definition: cairo.c:149
static int text_clipping
Definition: cairo.c:78
static void end_raster(PLStream *)
Definition: cairo.c:342
void plD_tidy_cairo(PLStream *)
Definition: cairo.c:498
static void set_mode(PLStream *, PLINT *)
Definition: cairo.c:586
#define PLCAIRO_DEFAULT_Y
Definition: cairo.c:73
static void rotate_cairo_surface(PLStream *, float, float, float, float, float, float, PLBOOL)
Definition: cairo.c:1666
static int text_anti_aliasing
Definition: cairo.c:79
void get_line_properties(PLCairo *aStream, cairo_line_join_t *join, cairo_line_cap_t *cap)
Definition: cairo.c:422
const char * defaultFamilyLookup[NPANGOLOOKUP]
Definition: cairo.c:198
static void set_current_context(PLStream *)
Definition: cairo.c:1401
static void open_span_tag(char *, PLUNICODE, float, int)
Definition: cairo.c:1137
#define NPANGOLOOKUP
Definition: cairo.c:196
const char * styleLookup[3]
Definition: cairo.c:224
const char * weightLookup[2]
Definition: cairo.c:219
static void start_raster(PLStream *)
Definition: cairo.c:298
static int already_warned
Definition: cairo.c:85
static int external_drawable
Definition: cairo.c:81
#define DPI
Definition: cairo.c:71
static void get_mode(PLStream *, PLINT *)
Definition: cairo.c:614
void plD_line_cairo(PLStream *, short, short, short, short)
Definition: cairo.c:434
static void text_begin_cairo(PLStream *pls, EscText *args)
Definition: cairo.c:646
static int set_background
Definition: cairo.c:83
#define PLCAIRO_DEFAULT_X
Definition: cairo.c:72
static void text_end_cairo(PLStream *pls, EscText *args)
Definition: cairo.c:773
#define FAMILY_LOOKUP_LEN
Definition: cairo.c:214
void plD_esc_cairo(PLStream *, PLINT, void *)
Definition: cairo.c:530
static char * rise_span_tag(int, float, float, float)
Definition: cairo.c:1239
static int image_buffering
Definition: cairo.c:84
static void blit_to_x(PLStream *pls, double x, double y, double w, double h)
char familyLookup[NPANGOLOOKUP][FAMILY_LOOKUP_LEN]
Definition: cairo.c:215
static int rasterize_image
Definition: cairo.c:82
static char * ucs4_to_pango_markup_format(PLUNICODE *, int, float)
Definition: cairo.c:992
PLCairo * stream_and_font_setup(PLStream *, int)
Definition: cairo.c:1301
cairo_status_t write_to_stream(void *, unsigned char *, unsigned int)
Definition: cairo.c:1277
void plD_polyline_cairo(PLStream *, short *, short *, PLINT)
Definition: cairo.c:460
static void text_char_cairo(PLStream *pls, EscText *args)
Definition: cairo.c:670
static void arc(PLStream *, arc_struct *)
Definition: cairo.c:1608
void plD_bop_cairo(PLStream *)
Definition: cairo.c:385
int cairo_family_check(PLStream *pls)
Definition: cairo.c:1585
static void filled_polygon(PLStream *pls, short *xa, short *ya, PLINT npts)
Definition: cairo.c:1452
void plD_eop_cairo(PLStream *)
Definition: cairo.c:483
void(* plD_line_fp)(struct PLStream_struct *, short, short, short, short)
Definition: disptab.h:68
void(* plD_tidy_fp)(struct PLStream_struct *)
Definition: disptab.h:72
void(* plD_bop_fp)(struct PLStream_struct *)
Definition: disptab.h:71
void(* plD_wait_fp)(struct PLStream_struct *)
Definition: disptab.h:75
void(* plD_state_fp)(struct PLStream_struct *, PLINT)
Definition: disptab.h:73
void(* plD_eop_fp)(struct PLStream_struct *)
Definition: disptab.h:70
@ plDevType_Interactive
Definition: disptab.h:14
@ plDevType_FileOriented
Definition: disptab.h:13
void(* plD_init_fp)(struct PLStream_struct *)
Definition: disptab.h:67
void(* plD_esc_fp)(struct PLStream_struct *, PLINT, void *)
Definition: disptab.h:74
void(* plD_polyline_fp)(struct PLStream_struct *, short *, short *, PLINT)
Definition: disptab.h:69
PLDLLIMPEXP_DRIVER void plD_dispatch_init_xcairo(PLDispatchTable *pdt)
PLDLLIMPEXP_DRIVER void plD_dispatch_init_svgcairo(PLDispatchTable *pdt)
PLDLLIMPEXP_DRIVER void plD_dispatch_init_wincairo(PLDispatchTable *pdt)
PLDLLIMPEXP_DRIVER void plD_dispatch_init_memcairo(PLDispatchTable *pdt)
PLDLLIMPEXP_DRIVER void plD_dispatch_init_epscairo(PLDispatchTable *pdt)
PLDLLIMPEXP_DRIVER void plD_dispatch_init_extcairo(PLDispatchTable *pdt)
PLDLLIMPEXP_DRIVER void plD_dispatch_init_pdfcairo(PLDispatchTable *pdt)
PLDLLIMPEXP_DRIVER void plD_dispatch_init_pscairo(PLDispatchTable *pdt)
PLDLLIMPEXP_DRIVER void plD_dispatch_init_pngcairo(PLDispatchTable *pdt)
int plParseDrvOpts(DrvOpt *acc_opt)
Definition: plargs.c:1461
void plP_fci2hex(PLUNICODE fci, unsigned char *phexdigit, unsigned char hexpower)
Definition: plcore.c:3958
void difilt_clip(PLINT *x_coords, PLINT *y_coords)
Definition: plcore.c:1603
void plP_setpxl(PLFLT xpmm, PLFLT ypmm)
Definition: plcore.c:4238
int ucs4_to_utf8(PLUNICODE unichar, char *ptr)
Definition: plcore.c:1329
void plgesc(char *p_esc)
Definition: plcore.c:3914
void plP_setphy(PLINT xmin, PLINT xmax, PLINT ymin, PLINT ymax)
Definition: plcore.c:4249
static PLStream * pls[PL_NSTREAMS]
Definition: plcore.h:88
void plFamInit(PLStream *pls)
Definition: plctrl.c:2751
void plwarn(PLCHAR_VECTOR errormsg)
Definition: plctrl.c:1863
void plCloseFile(PLStream *pls)
Definition: plctrl.c:2635
void plGinInit(PLGraphicsIn *gin)
Definition: plctrl.c:2887
void plOpenFile(PLStream *pls)
Definition: plctrl.c:2571
void plexit(PLCHAR_VECTOR errormsg)
Definition: plctrl.c:1958
void plGetFam(PLStream *pls)
Definition: plctrl.c:2780
#define PLDLLIMPEXP_DRIVER
Definition: pldll.h:81
void plRotationShear(PLFLT *xFormMatrix, PLFLT *rotation, PLFLT *shear, PLFLT *stride)
Definition: plot3d.c:2767
#define PI
Definition: plplotP.h:290
#define PIXELS_X
Definition: plplotP.h:304
#define snprintf
Definition: plplotP.h:235
#define TRUE
Definition: plplotP.h:176
#define FALSE
Definition: plplotP.h:177
@ DRV_INT
Definition: plplotP.h:758
#define M_PI
Definition: plplotP.h:119
#define free_mem(a)
Definition: plplotP.h:182
#define PIXELS_Y
Definition: plplotP.h:305
#define plgfci
Definition: plplot.h:735
#define PLESC_GETC
Definition: plplot.h:283
#define PLESC_MODEGET
Definition: plplot.h:307
#define PLESC_HAS_TEXT
Definition: plplot.h:290
#define PLESC_CONTROL_CHAR
Definition: plplot.h:300
PLUINT PLUNICODE
Definition: plplot.h:201
#define PLTEXT_SUPERSCRIPT
Definition: plplot.h:315
float PLFLT
Definition: plplot.h:163
#define plbop
Definition: plplot.h:696
#define PLESC_END_TEXT
Definition: plplot.h:301
#define PLESC_START_RASTERIZE
Definition: plplot.h:302
#define PLTEXT_OVERLINE
Definition: plplot.h:318
#define PL_FCI_WEIGHT
Definition: plplot.h:378
#define PLESC_GRADIENT
Definition: plplot.h:305
#define PLESC_DEVINIT
Definition: plplot.h:296
#define PLESC_FLUSH
Definition: plplot.h:281
#define PL_UNUSED(x)
Definition: plplot.h:138
#define PLTEXT_FONTCHANGE
Definition: plplot.h:314
#define plsdiori
Definition: plplot.h:809
#define PLESC_TEXT_CHAR
Definition: plplot.h:299
#define PLTEXT_SUBSCRIPT
Definition: plplot.h:316
#define PLTEXT_BACKCHAR
Definition: plplot.h:317
#define PLESC_MODESET
Definition: plplot.h:306
#define PLESC_FILL
Definition: plplot.h:279
#define PLESC_ARC
Definition: plplot.h:304
#define PL_FCI_STYLE
Definition: plplot.h:377
#define PL_FCI_FAMILY
Definition: plplot.h:376
#define PLESC_BEGIN_TEXT
Definition: plplot.h:298
int PLINT
Definition: plplot.h:181
#define PLESC_END_RASTERIZE
Definition: plplot.h:303
PLINT PLBOOL
Definition: plplot.h:204
#define PLTEXT_UNDERLINE
Definition: plplot.h:319
#define PL_FCI_MARK
Definition: plplot.h:370
@ PL_DRAWMODE_REPLACE
Definition: plplot_core.h:136
@ PL_DRAWMODE_DEFAULT
Definition: plplot_core.h:135
@ PL_DRAWMODE_UNKNOWN
Definition: plplot_core.h:134
@ PL_DRAWMODE_XOR
Definition: plplot_core.h:137
void plP_script_scale(PLBOOL ifupper, PLINT *level, PLFLT *old_scale, PLFLT *scale, PLFLT *old_offset, PLFLT *offset)
Definition: plsym.c:1302
unsigned short unicode_array_len
Definition: plplotP.h:736
PLUNICODE n_fci
Definition: plplotP.h:726
PLUNICODE n_char
Definition: plplotP.h:727
PLINT n_ctrl_char
Definition: plplotP.h:728
PLFLT just
Definition: plplotP.h:708
PLINT x
Definition: plplotP.h:712
PLUNICODE * unicode_array
Definition: plplotP.h:735
PLINT y
Definition: plplotP.h:713
PLFLT * xform
Definition: plplotP.h:709
Definition: cairo.c:97
PLFLT old_soffset
Definition: cairo.c:120
float fontSize
Definition: cairo.c:111
cairo_surface_t * cairoSurface
Definition: cairo.c:98
cairo_surface_t * cairoSurface_raster
Definition: cairo.c:100
PLFLT old_sscale
Definition: cairo.c:120
short image_buffering
Definition: cairo.c:107
PLFLT sscale
Definition: cairo.c:120
short set_background
Definition: cairo.c:106
PLFLT soffset
Definition: cairo.c:120
double downscale
Definition: cairo.c:108
char * pangoMarkupString
Definition: cairo.c:109
short rasterize_image
Definition: cairo.c:105
short uline
Definition: cairo.c:112
short text_clipping
Definition: cairo.c:102
short graphics_anti_aliasing
Definition: cairo.c:104
cairo_t * cairoContext_raster
Definition: cairo.c:101
short text_anti_aliasing
Definition: cairo.c:103
short upDown
Definition: cairo.c:110
cairo_t * cairoContext
Definition: cairo.c:99
PLINT level
Definition: cairo.c:121
PLFLT a
Definition: plplot.h:551
unsigned char r
Definition: plplot.h:548
unsigned char g
Definition: plplot.h:549
unsigned char b
Definition: plplot.h:550
plD_eop_fp pl_eop
Definition: disptab.h:86
const char * pl_DevName
Definition: disptab.h:80
plD_esc_fp pl_esc
Definition: disptab.h:90
plD_wait_fp pl_wait
Definition: disptab.h:91
plD_polyline_fp pl_polyline
Definition: disptab.h:85
plD_state_fp pl_state
Definition: disptab.h:89
plD_tidy_fp pl_tidy
Definition: disptab.h:88
plD_line_fp pl_line
Definition: disptab.h:84
plD_init_fp pl_init
Definition: disptab.h:83
plD_bop_fp pl_bop
Definition: disptab.h:87
const char * pl_MenuStr
Definition: disptab.h:79
char string[PL_MAXKEY]
Definition: plplot.h:440
PLFLT dY
Definition: plplot.h:442
unsigned int state
Definition: plplot.h:436
unsigned int keysym
Definition: plplot.h:437
PLFLT dX
Definition: plplot.h:442
unsigned int button
Definition: plplot.h:438
PLINT ncol1
Definition: plstrm.h:539
PLINT famadv
Definition: plstrm.h:570
PLINT ylength
Definition: plstrm.h:617
PLINT dev_arc
Definition: plstrm.h:572
PLColor * cmap0
Definition: plstrm.h:544
PLINT dev_fill0
Definition: plstrm.h:571
PLINT page
Definition: plstrm.h:578
PLINT family
Definition: plstrm.h:570
PLINT dev_npts
Definition: plstrm.h:581
PLINT dev_modeset
Definition: plstrm.h:791
PLINT color
Definition: plstrm.h:569
short * dev_y
Definition: plstrm.h:582
PLBOOL stream_closed
Definition: plstrm.h:782
PLINT xoffset
Definition: plstrm.h:618
PLINT plbuf_write
Definition: plstrm.h:567
PLFLT width
Definition: plstrm.h:552
PLINT dev_clear
Definition: plstrm.h:572
FILE * OutFile
Definition: plstrm.h:575
PLINT yoffset
Definition: plstrm.h:618
short * dev_x
Definition: plstrm.h:582
PLFLT chrht
Definition: plstrm.h:686
char * plwindow
Definition: plstrm.h:640
PLINT dev_gradient
Definition: plstrm.h:773
PLINT dev_unicode
Definition: plstrm.h:747
PLColor curcolor
Definition: plstrm.h:543
char * FileName
Definition: plstrm.h:576
char * program
Definition: plstrm.h:530
PLINT * xgradient
Definition: plstrm.h:775
PLINT get_string_length
Definition: plstrm.h:787
PLINT freeaspect
Definition: plstrm.h:665
PLINT dev_text
Definition: plstrm.h:572
PLINT phyyma
Definition: plstrm.h:705
PLINT termin
Definition: plstrm.h:568
PLINT dev_mem_alpha
Definition: plstrm.h:784
PLINT has_string_length
Definition: plstrm.h:785
PLFLT string_length
Definition: plstrm.h:786
void * dev
Definition: plstrm.h:594
PLColor * cmap1
Definition: plstrm.h:545
PLINT xlength
Definition: plstrm.h:617
PLINT portrait
Definition: plstrm.h:665
PLINT alt_unicode
Definition: plstrm.h:749
PLINT dev_flush
Definition: plstrm.h:571
PLINT * ygradient
Definition: plstrm.h:775
PLINT dev_eofill
Definition: plstrm.h:788
PLINT phyxma
Definition: plstrm.h:705
PLFLT diorot
Definition: plstrm.h:661
PLFLT x
Definition: plplotP.h:1103
PLFLT b
Definition: plplotP.h:1106
PLFLT angle2
Definition: plplotP.h:1108
PLFLT y
Definition: plplotP.h:1104
PLFLT rotate
Definition: plplotP.h:1109
PLFLT a
Definition: plplotP.h:1105
PLFLT angle1
Definition: plplotP.h:1107
PLBOOL fill
Definition: plplotP.h:1110
static const char * display
Definition: tkMain.c:136