00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include <stdio.h>
00031 #include <string.h>
00032 #include <math.h>
00033
00034 #include <cairo.h>
00035 #include <pango/pangocairo.h>
00036
00037
00038
00039 #include "plDevs.h"
00040 #include "plplotP.h"
00041 #include "drivers.h"
00042
00043
00044 #if defined ( PLD_xcairo )
00045 #include <cairo-xlib.h>
00046 #include <X11/X.h>
00047 #include <X11/Xlib.h>
00048 #include <X11/Xutil.h>
00049 #include <X11/cursorfont.h>
00050 #include <X11/keysym.h>
00051 #endif
00052 #if defined ( PLD_pdfcairo )
00053 #include <cairo-pdf.h>
00054 #endif
00055 #if defined ( PLD_pscairo )
00056 #include <cairo-ps.h>
00057 #endif
00058 #if defined ( PLD_svgcairo )
00059 #include <cairo-svg.h>
00060 #endif
00061 #if defined ( PLD_wincairo )
00062 #include <windows.h>
00063 #endif
00064
00065
00066
00067
00068
00069 #define DPI 72
00070 #define PLCAIRO_DEFAULT_X 720
00071 #define PLCAIRO_DEFAULT_Y 540
00072
00073 #define MAX_STRING_LEN 500
00074 #define MAX_MARKUP_LEN MAX_STRING_LEN * 10
00075
00076 static int text_clipping;
00077 static int text_anti_aliasing;
00078 static int graphics_anti_aliasing;
00079 static int external_drawable;
00080 static int rasterize_image;
00081 static int set_background;
00082 static int image_buffering;
00083
00084 static DrvOpt cairo_options[] = { { "text_clipping", DRV_INT, &text_clipping, "Use text clipping (text_clipping=0|1)" },
00085 { "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)" },
00086 { "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" },
00087 { "external_drawable", DRV_INT, &external_drawable, "Plot to external X drawable" },
00088 { "rasterize_image", DRV_INT, &rasterize_image, "Raster or vector image rendering (rasterize_image=0|1)" },
00089 { "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" },
00090 { "image_buffering", DRV_INT, &image_buffering, "Buffered offscreen rendering for the xcairo device (image_buffering=0|1)." },
00091 { NULL, DRV_INT, NULL, NULL } };
00092
00093 typedef struct
00094 {
00095 cairo_surface_t *cairoSurface;
00096 cairo_t *cairoContext;
00097 cairo_surface_t *cairoSurface_raster;
00098 cairo_t *cairoContext_raster;
00099 short text_clipping;
00100 short text_anti_aliasing;
00101 short graphics_anti_aliasing;
00102 short rasterize_image;
00103 short set_background;
00104 short image_buffering;
00105 double downscale;
00106 char *pangoMarkupString;
00107 short upDown;
00108 float fontSize;
00109
00110
00111
00112
00113
00114
00115
00116 PLFLT old_sscale, sscale, old_soffset, soffset;
00117 PLINT level;
00118
00119 #if defined ( PLD_xcairo )
00120 cairo_surface_t *cairoSurface_X;
00121 cairo_t *cairoContext_X;
00122 short exit_event_loop;
00123 Display *XDisplay;
00124 Window XWindow;
00125 unsigned int xdrawable_mode;
00126 #endif
00127 #if defined ( PLD_memcairo )
00128 unsigned char *memory;
00129 unsigned char *cairo_format_memory;
00130 char bigendian;
00131 #endif
00132 #if defined ( PLD_wincairo )
00133 cairo_surface_t *cairoSurface_win;
00134 cairo_t *cairoContext_win;
00135 WNDCLASSEX wndclass;
00136 HWND hwnd;
00137 MSG msg;
00138 HDC hdc;
00139 HDC SCRN_hdc;
00140 COLORREF oldcolour;
00141 RECT rect;
00142 #endif
00143 } PLCairo;
00144
00145 PLDLLIMPEXP_DRIVER const char* plD_DEVICE_INFO_cairo =
00146 #if defined ( PLD_xcairo )
00147 "xcairo:Cairo X Windows Driver:1:cairo:100:xcairo\n"
00148 #endif
00149 #if defined ( PLD_pdfcairo )
00150 "pdfcairo:Cairo PDF Driver:0:cairo:101:pdfcairo\n"
00151 #endif
00152 #if defined ( PLD_pscairo )
00153 "pscairo:Cairo PS Driver:0:cairo:102:pscairo\n"
00154 #endif
00155 #if defined ( PLD_svgcairo )
00156 "svgcairo:Cairo SVG Driver:0:cairo:103:svgcairo\n"
00157 #endif
00158 #if defined ( PLD_pngcairo )
00159 "pngcairo:Cairo PNG Driver:0:cairo:104:pngcairo\n"
00160 #endif
00161 #if defined ( PLD_memcairo )
00162 "memcairo:Cairo Memory Driver:0:cairo:105:memcairo\n"
00163 #endif
00164 #if defined ( PLD_extcairo )
00165 "extcairo:Cairo External Context Driver:0:cairo:106:extcairo\n"
00166 #endif
00167 #if defined ( PLD_wincairo )
00168 "wincairo:Cairo Microscoft Windows Driver:0:cairo:107:wincairo\n"
00169 #endif
00170 ;
00171
00172
00173
00174
00175
00176 #if defined ( PLD_xcairo )
00177 typedef struct
00178 {
00179 Display *display;
00180 Drawable drawable;
00181 } PLXcairoDrawableInfo;
00182 #endif
00183
00184
00185
00186
00187
00188
00189 #define NPANGOLOOKUP 5
00190
00191 const char *defaultFamilyLookup[NPANGOLOOKUP] = {
00192 "sans",
00193 "serif",
00194 "monospace",
00195 "sans,serif",
00196 "sans,serif"
00197 };
00198
00199 const char *envFamilyLookup[NPANGOLOOKUP] = {
00200 "PLPLOT_FREETYPE_SANS_FAMILY",
00201 "PLPLOT_FREETYPE_SERIF_FAMILY",
00202 "PLPLOT_FREETYPE_MONO_FAMILY",
00203 "PLPLOT_FREETYPE_SCRIPT_FAMILY",
00204 "PLPLOT_FREETYPE_SYMBOL_FAMILY"
00205 };
00206
00207 #define FAMILY_LOOKUP_LEN 1024
00208 char familyLookup[NPANGOLOOKUP][FAMILY_LOOKUP_LEN];
00209
00210 #define TAG_LEN 200
00211
00212 const char *weightLookup[2] = {
00213 "normal",
00214 "bold"
00215 };
00216
00217 const char *styleLookup[3] = {
00218 "normal",
00219 "italic",
00220 "oblique"
00221 };
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238 PLCairo *stream_and_font_setup( PLStream *, int );
00239 cairo_status_t write_to_stream( void *, unsigned char *, unsigned int );
00240 void set_clip( PLStream *pls );
00241
00242
00243
00244 static void proc_str( PLStream *, EscText * );
00245 static void text_begin_cairo( PLStream *pls, EscText *args );
00246 static void text_char_cairo( PLStream *pls, EscText *args );
00247 static void text_esc_cairo( PLStream *pls, EscText *args );
00248 static void text_end_cairo( PLStream *pls, EscText *args );
00249 static char *ucs4_to_pango_markup_format( PLUNICODE *, int, float );
00250 static void open_span_tag( char *, PLUNICODE, float, int );
00251 static void close_span_tag( char *, int );
00252 static char *rise_span_tag( int, float, float, float );
00253
00254
00255
00256 static void set_current_context( PLStream * );
00257 static void poly_line( PLStream *, short *, short *, PLINT );
00258 static void filled_polygon( PLStream *pls, short *xa, short *ya, PLINT npts );
00259 static void gradient( PLStream *pls, short *xa, short *ya, PLINT npts );
00260 static void arc( PLStream *, arc_struct * );
00261 static void rotate_cairo_surface( PLStream *, float, float, float, float, float, float, PLBOOL );
00262
00263 static void start_raster( PLStream* );
00264 static void end_raster( PLStream* );
00265
00266 static void set_mode( PLStream*, PLINT* );
00267 static void get_mode( PLStream*, PLINT* );
00268
00269
00270
00271
00272 void plD_bop_cairo( PLStream * );
00273 void plD_eop_cairo( PLStream * );
00274 void plD_state_cairo( PLStream *, PLINT );
00275 void plD_esc_cairo( PLStream *, PLINT, void * );
00276 void plD_tidy_cairo( PLStream * );
00277 void plD_line_cairo( PLStream *, short, short, short, short );
00278 void plD_polyline_cairo( PLStream *, short *, short *, PLINT );
00279
00280
00281
00282
00283
00284
00285
00286 void start_raster( PLStream *pls )
00287 {
00288 PLCairo *aStream;
00289 cairo_surface_t *tmp_sfc;
00290 cairo_t *tmp_context;
00291
00292 aStream = (PLCairo *) pls->dev;
00293
00294
00295 if ( !aStream->rasterize_image )
00296 return;
00297
00298
00299 aStream->cairoSurface_raster =
00300
00301
00302
00303
00304
00305 cairo_image_surface_create( CAIRO_FORMAT_ARGB32,
00306 pls->xlength, pls->ylength );
00307 aStream->cairoContext_raster = cairo_create( aStream->cairoSurface_raster );
00308
00309
00310
00311 cairo_set_antialias( aStream->cairoContext_raster, CAIRO_ANTIALIAS_NONE );
00312
00313
00314 tmp_sfc = aStream->cairoSurface;
00315 tmp_context = aStream->cairoContext;
00316 aStream->cairoSurface = aStream->cairoSurface_raster;
00317 aStream->cairoContext = aStream->cairoContext_raster;
00318
00319 aStream->cairoSurface_raster = tmp_sfc;
00320 aStream->cairoContext_raster = tmp_context;
00321 }
00322
00323
00324
00325
00326
00327
00328
00329
00330 void end_raster( PLStream *pls )
00331 {
00332 PLCairo *aStream;
00333 cairo_surface_t *tmp_sfc;
00334 cairo_t *tmp_context;
00335
00336 aStream = (PLCairo *) pls->dev;
00337
00338
00339
00340
00341
00342 if ( !aStream->rasterize_image )
00343 return;
00344
00345
00346
00347 if ( aStream->cairoContext == NULL )
00348 plexit( "Can not plot to a Cairo device with no context" );
00349
00350
00351 tmp_sfc = aStream->cairoSurface;
00352 tmp_context = aStream->cairoContext;
00353 aStream->cairoSurface = aStream->cairoSurface_raster;
00354 aStream->cairoContext = aStream->cairoContext_raster;
00355 aStream->cairoSurface_raster = tmp_sfc;
00356 aStream->cairoContext_raster = tmp_context;
00357
00358
00359 cairo_set_source_surface( aStream->cairoContext, aStream->cairoSurface_raster, 0.0, 0.0 );
00360 cairo_paint( aStream->cairoContext );
00361
00362
00363 cairo_destroy( aStream->cairoContext_raster );
00364 cairo_surface_destroy( aStream->cairoSurface_raster );
00365 }
00366
00367
00368
00369
00370
00371
00372
00373 void plD_bop_cairo( PLStream *pls )
00374 {
00375 PLCairo *aStream;
00376
00377 aStream = (PLCairo *) pls->dev;
00378
00379
00380
00381 if ( aStream->cairoContext == NULL )
00382 return;
00383
00384
00385 cairo_rectangle( aStream->cairoContext, 0.0, 0.0, pls->xlength, pls->ylength );
00386 if ( (double) pls->cmap0[0].a < 1.0 )
00387 {
00388 cairo_set_source_rgba( aStream->cairoContext, 1.0, 1.0, 1.0, 1.0 );
00389 cairo_fill_preserve( aStream->cairoContext );
00390 }
00391 cairo_set_source_rgba( aStream->cairoContext,
00392 (double) pls->cmap0[0].r / 255.0,
00393 (double) pls->cmap0[0].g / 255.0,
00394 (double) pls->cmap0[0].b / 255.0,
00395 (double) pls->cmap0[0].a );
00396 cairo_fill( aStream->cairoContext );
00397 }
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410 void get_line_properties( PLCairo *aStream, cairo_line_join_t *join, cairo_line_cap_t *cap )
00411 {
00412 *join = cairo_get_line_join( aStream->cairoContext );
00413 *cap = cairo_get_line_cap( aStream->cairoContext );
00414 }
00415
00416 void set_line_properties( PLCairo *aStream, cairo_line_join_t join, cairo_line_cap_t cap )
00417 {
00418 cairo_set_line_join( aStream->cairoContext, join );
00419 cairo_set_line_cap( aStream->cairoContext, cap );
00420 }
00421
00422 void plD_line_cairo( PLStream *pls, short x1a, short y1a, short x2a, short y2a )
00423 {
00424 PLCairo *aStream;
00425
00426 aStream = (PLCairo *) pls->dev;
00427
00428 set_current_context( pls );
00429
00430 cairo_save( aStream->cairoContext );
00431
00432 set_line_properties( aStream, CAIRO_LINE_JOIN_BEVEL, CAIRO_LINE_CAP_ROUND );
00433
00434 cairo_move_to( aStream->cairoContext, aStream->downscale * (double) x1a, aStream->downscale * (double) y1a );
00435 cairo_line_to( aStream->cairoContext, aStream->downscale * (double) x2a, aStream->downscale * (double) y2a );
00436
00437 cairo_stroke( aStream->cairoContext );
00438
00439 cairo_restore( aStream->cairoContext );
00440 }
00441
00442
00443
00444
00445
00446
00447
00448 void plD_polyline_cairo( PLStream *pls, short *xa, short *ya, PLINT npts )
00449 {
00450 PLCairo *aStream;
00451
00452 aStream = (PLCairo *) pls->dev;
00453
00454 cairo_save( aStream->cairoContext );
00455
00456 set_line_properties( aStream, CAIRO_LINE_JOIN_BEVEL, CAIRO_LINE_CAP_BUTT );
00457
00458 poly_line( pls, xa, ya, npts );
00459
00460 cairo_stroke( aStream->cairoContext );
00461
00462 cairo_restore( aStream->cairoContext );
00463 }
00464
00465
00466
00467
00468
00469
00470
00471 void plD_eop_cairo( PLStream *pls )
00472 {
00473 PLCairo *aStream;
00474
00475 aStream = (PLCairo *) pls->dev;
00476
00477 cairo_show_page( aStream->cairoContext );
00478 }
00479
00480
00481
00482
00483
00484
00485
00486 void plD_tidy_cairo( PLStream *pls )
00487 {
00488 PLCairo *aStream;
00489
00490 aStream = (PLCairo *) pls->dev;
00491
00492
00493 cairo_destroy( aStream->cairoContext );
00494 cairo_surface_destroy( aStream->cairoSurface );
00495
00496 plCloseFile( pls );
00497 }
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508 void plD_state_cairo( PLStream *pls, PLINT op )
00509 {
00510 }
00511
00512
00513
00514
00515
00516
00517
00518 void plD_esc_cairo( PLStream *pls, PLINT op, void *ptr )
00519 {
00520 PLCairo *aStream;
00521
00522 aStream = (PLCairo *) pls->dev;
00523
00524 switch ( op )
00525 {
00526 case PLESC_FILL:
00527 filled_polygon( pls, pls->dev_x, pls->dev_y, pls->dev_npts );
00528 break;
00529 case PLESC_GRADIENT:
00530 gradient( pls, pls->dev_x, pls->dev_y, pls->dev_npts );
00531 break;
00532 case PLESC_HAS_TEXT:
00533 if ( !pls->alt_unicode )
00534 {
00535 proc_str( pls, (EscText *) ptr );
00536 }
00537 break;
00538 case PLESC_BEGIN_TEXT:
00539 text_begin_cairo( pls, (EscText *) ptr );
00540 break;
00541 case PLESC_TEXT_CHAR:
00542 text_char_cairo( pls, (EscText *) ptr );
00543 break;
00544 case PLESC_CONTROL_CHAR:
00545 text_esc_cairo( pls, (EscText *) ptr );
00546 break;
00547 case PLESC_END_TEXT:
00548 text_end_cairo( pls, (EscText *) ptr );
00549 break;
00550 case PLESC_START_RASTERIZE:
00551 start_raster( pls );
00552 break;
00553 case PLESC_END_RASTERIZE:
00554 end_raster( pls );
00555 break;
00556 case PLESC_ARC:
00557 arc( pls, (arc_struct *) ptr );
00558 break;
00559 case PLESC_MODESET:
00560 set_mode( pls, (int *) ptr );
00561 break;
00562 case PLESC_MODEGET:
00563 get_mode( pls, (int *) ptr );
00564 break;
00565 }
00566 }
00567
00568
00569
00570
00571
00572
00573
00574 void set_mode( PLStream *pls, PLINT *mode )
00575 {
00576 PLCairo *aStream;
00577
00578 aStream = (PLCairo *) pls->dev;
00579
00580 switch ( *mode )
00581 {
00582 case PL_DRAWMODE_UNKNOWN:
00583 break;
00584 case PL_DRAWMODE_DEFAULT:
00585 cairo_set_operator( aStream->cairoContext, CAIRO_OPERATOR_OVER );
00586 break;
00587 case PL_DRAWMODE_REPLACE:
00588 cairo_set_operator( aStream->cairoContext, CAIRO_OPERATOR_SOURCE );
00589 break;
00590 case PL_DRAWMODE_XOR:
00591 cairo_set_operator( aStream->cairoContext, CAIRO_OPERATOR_XOR );
00592 break;
00593 }
00594 return;
00595 }
00596
00597
00598
00599
00600
00601
00602 void get_mode( PLStream *pls, PLINT *mode )
00603 {
00604 PLCairo *aStream;
00605 cairo_operator_t op;
00606
00607 aStream = (PLCairo *) pls->dev;
00608
00609 op = cairo_get_operator( aStream->cairoContext );
00610
00611 switch ( op )
00612 {
00613 case CAIRO_OPERATOR_OVER:
00614 *mode = PL_DRAWMODE_DEFAULT;
00615 break;
00616 case CAIRO_OPERATOR_SOURCE:
00617 *mode = PL_DRAWMODE_REPLACE;
00618 break;
00619 case CAIRO_OPERATOR_XOR:
00620 *mode = PL_DRAWMODE_XOR;
00621 break;
00622 default:
00623 *mode = PL_DRAWMODE_UNKNOWN;
00624 }
00625 return;
00626 }
00627
00628
00629
00630
00631
00632
00633
00634 void text_begin_cairo( PLStream *pls, EscText *args )
00635 {
00636 int i;
00637 PLCairo *aStream;
00638
00639 aStream = (PLCairo *) pls->dev;
00640 aStream->upDown = 0;
00641 aStream->level = 0;
00642 aStream->pangoMarkupString = (char *) malloc( sizeof ( char ) * MAX_MARKUP_LEN );
00643
00644 aStream->fontSize = pls->chrht * DPI / 25.4;
00645 for ( i = 0; i < MAX_MARKUP_LEN; i++ )
00646 {
00647 aStream->pangoMarkupString[i] = 0;
00648 }
00649 open_span_tag( aStream->pangoMarkupString, args->n_fci, aStream->fontSize, 0 );
00650 }
00651
00652
00653
00654
00655
00656
00657
00658 void text_char_cairo( PLStream *pls, EscText *args )
00659 {
00660 char utf8[5];
00661 PLCairo *aStream;
00662
00663 aStream = (PLCairo *) pls->dev;
00664
00665 if ( strlen( aStream->pangoMarkupString ) < ( MAX_MARKUP_LEN - 50 ) )
00666 {
00667 switch ( args->n_char )
00668 {
00669 case 38:
00670 strncat( aStream->pangoMarkupString, "&", MAX_MARKUP_LEN - 1 - strlen( aStream->pangoMarkupString ) );
00671 break;
00672 case 60:
00673 strncat( aStream->pangoMarkupString, "<", MAX_MARKUP_LEN - 1 - strlen( aStream->pangoMarkupString ) );
00674 break;
00675 case 62:
00676 strncat( aStream->pangoMarkupString, ">", MAX_MARKUP_LEN - 1 - strlen( aStream->pangoMarkupString ) );
00677 break;
00678 default:
00679 ucs4_to_utf8( args->n_char, utf8 );
00680 strncat( aStream->pangoMarkupString, utf8, MAX_MARKUP_LEN - 1 - strlen( aStream->pangoMarkupString ) );
00681 break;
00682 }
00683 }
00684 }
00685
00686
00687
00688
00689
00690
00691
00692 void text_esc_cairo( PLStream *pls, EscText *args )
00693 {
00694 PLCairo *aStream;
00695
00696 aStream = (PLCairo *) pls->dev;
00697 switch ( args->n_ctrl_char )
00698 {
00699 case PLTEXT_FONTCHANGE:
00700 close_span_tag( aStream->pangoMarkupString, aStream->upDown );
00701 open_span_tag( aStream->pangoMarkupString, args->n_fci, aStream->fontSize, aStream->upDown );
00702 break;
00703 case PLTEXT_SUPERSCRIPT:
00704 if ( aStream->upDown < 0 )
00705 {
00706 strncat( aStream->pangoMarkupString, "</span>", MAX_MARKUP_LEN - 1 - strlen( aStream->pangoMarkupString ) );
00707 aStream->level++;
00708 }
00709 else
00710 {
00711 plP_script_scale( TRUE, &aStream->level,
00712 &aStream->old_sscale, &aStream->sscale, &aStream->old_soffset, &aStream->soffset );
00713 strncat( aStream->pangoMarkupString,
00714 rise_span_tag( TRUE, aStream->fontSize, aStream->sscale, aStream->soffset ),
00715 MAX_MARKUP_LEN - 1 - strlen( aStream->pangoMarkupString ) );
00716 }
00717 aStream->upDown++;
00718 break;
00719 case PLTEXT_SUBSCRIPT:
00720 if ( aStream->upDown > 0 )
00721 {
00722 strncat( aStream->pangoMarkupString, "</span>", MAX_MARKUP_LEN - 1 - strlen( aStream->pangoMarkupString ) );
00723 aStream->level--;
00724 }
00725 else
00726 {
00727 plP_script_scale( FALSE, &aStream->level,
00728 &aStream->old_sscale, &aStream->sscale, &aStream->old_soffset, &aStream->soffset );
00729 strncat( aStream->pangoMarkupString,
00730 rise_span_tag( FALSE, aStream->fontSize, aStream->sscale, aStream->soffset ),
00731 MAX_MARKUP_LEN - 1 - strlen( aStream->pangoMarkupString ) );
00732 }
00733 aStream->upDown--;
00734 break;
00735 }
00736 }
00737
00738
00739
00740
00741
00742
00743
00744 void text_end_cairo( PLStream *pls, EscText *args )
00745 {
00746 int textXExtent, textYExtent, baseline;
00747 PLFLT rotation, shear, stride, cos_rot, sin_rot, cos_shear, sin_shear;
00748 cairo_matrix_t *cairoTransformMatrix;
00749 cairo_font_options_t *cairoFontOptions;
00750 PangoContext *context;
00751 PangoLayout *layout;
00752 PLCairo *aStream;
00753
00754 aStream = (PLCairo *) pls->dev;
00755
00756 set_current_context( pls );
00757
00758
00759 close_span_tag( aStream->pangoMarkupString, aStream->upDown );
00760
00761
00762
00763
00764 layout = pango_cairo_create_layout( aStream->cairoContext );
00765 pango_layout_set_markup( layout, aStream->pangoMarkupString, -1 );
00766 pango_layout_get_pixel_size( layout, &textXExtent, &textYExtent );
00767 baseline = pango_layout_get_baseline( layout );
00768
00769
00770 if ( pls->get_string_length )
00771 {
00772 pls->string_length = (PLFLT) textXExtent * 25.4 / DPI;
00773 return;
00774 }
00775
00776
00777 context = pango_layout_get_context( layout );
00778 cairoFontOptions = cairo_font_options_create();
00779 cairo_font_options_set_antialias( cairoFontOptions, aStream->text_anti_aliasing );
00780 pango_cairo_context_set_font_options( context, cairoFontOptions );
00781 pango_layout_context_changed( layout );
00782 cairo_font_options_destroy( cairoFontOptions );
00783
00784
00785 cairo_save( aStream->cairoContext );
00786
00787
00788 if ( aStream->text_clipping )
00789 {
00790 set_clip( pls );
00791 }
00792
00793
00794 cairo_move_to( aStream->cairoContext, aStream->downscale * (double) args->x, aStream->downscale * (double) args->y );
00795
00796
00797 cairoTransformMatrix = (cairo_matrix_t *) malloc( sizeof ( cairo_matrix_t ) );
00798 cairo_matrix_init( cairoTransformMatrix, 1.0, 0.0, 0.0, -1.0, 0.0, 0.0 );
00799 cairo_transform( aStream->cairoContext, cairoTransformMatrix );
00800
00801
00802
00803 plRotationShear( args->xform, &rotation, &shear, &stride );
00804 rotation -= pls->diorot * PI / 2.0;
00805 cos_rot = cos( rotation );
00806 sin_rot = sin( rotation );
00807 cos_shear = cos( shear );
00808 sin_shear = sin( shear );
00809
00810
00811 cairo_matrix_init( cairoTransformMatrix,
00812 cos_rot * stride,
00813 -sin_rot * stride,
00814 cos_rot * sin_shear + sin_rot * cos_shear,
00815 -sin_rot * sin_shear + cos_rot * cos_shear,
00816 0, 0 );
00817 cairo_transform( aStream->cairoContext, cairoTransformMatrix );
00818 free( cairoTransformMatrix );
00819
00820
00821
00822 cairo_rel_move_to( aStream->cairoContext,
00823 (double) ( -1.0 * args->just * (double) textXExtent ),
00824 (double) 0.5 * aStream->fontSize - baseline / 1024.0 );
00825
00826
00827 pango_cairo_show_layout( aStream->cairoContext, layout );
00828
00829
00830 cairo_restore( aStream->cairoContext );
00831
00832
00833 g_object_unref( layout );
00834 free( aStream->pangoMarkupString );
00835 }
00836
00837
00838
00839
00840
00841
00842
00843 void proc_str( PLStream *pls, EscText *args )
00844 {
00845 float fontSize;
00846 int textXExtent, textYExtent, baseline;
00847 char *textWithPangoMarkup;
00848 PLFLT rotation, shear, stride, cos_rot, sin_rot, cos_shear, sin_shear;
00849 cairo_matrix_t *cairoTransformMatrix;
00850 cairo_font_options_t *cairoFontOptions;
00851 PangoContext *context;
00852 PangoLayout *layout;
00853 PLCairo *aStream;
00854
00855 aStream = (PLCairo *) pls->dev;
00856
00857 set_current_context( pls );
00858
00859
00860 if ( args->unicode_array_len == 0 )
00861 {
00862 printf( "Non unicode string passed to a cairo driver, ignoring\n" );
00863 return;
00864 }
00865
00866
00867 if ( args->unicode_array_len >= MAX_STRING_LEN )
00868 {
00869 printf( "Sorry, the cairo drivers only handles strings of length < %d\n", MAX_STRING_LEN );
00870 return;
00871 }
00872
00873
00874 fontSize = pls->chrht * DPI / 25.4;
00875
00876
00877 textWithPangoMarkup = ucs4_to_pango_markup_format( args->unicode_array, args->unicode_array_len, fontSize );
00878
00879
00880 layout = pango_cairo_create_layout( aStream->cairoContext );
00881 pango_layout_set_markup( layout, textWithPangoMarkup, -1 );
00882 pango_layout_get_pixel_size( layout, &textXExtent, &textYExtent );
00883 baseline = pango_layout_get_baseline( layout );
00884
00885
00886 if ( pls->get_string_length )
00887 {
00888 pls->string_length = (PLFLT) textXExtent * 25.4 / DPI;
00889 return;
00890 }
00891
00892
00893 context = pango_layout_get_context( layout );
00894 cairoFontOptions = cairo_font_options_create();
00895 cairo_font_options_set_antialias( cairoFontOptions, aStream->text_anti_aliasing );
00896 pango_cairo_context_set_font_options( context, cairoFontOptions );
00897 pango_layout_context_changed( layout );
00898 cairo_font_options_destroy( cairoFontOptions );
00899
00900
00901 cairo_save( aStream->cairoContext );
00902
00903
00904 if ( aStream->text_clipping )
00905 {
00906 set_clip( pls );
00907 }
00908
00909
00910 cairo_move_to( aStream->cairoContext, aStream->downscale * (double) args->x, aStream->downscale * (double) args->y );
00911
00912
00913 cairoTransformMatrix = (cairo_matrix_t *) malloc( sizeof ( cairo_matrix_t ) );
00914 cairo_matrix_init( cairoTransformMatrix, 1.0, 0.0, 0.0, -1.0, 0.0, 0.0 );
00915 cairo_transform( aStream->cairoContext, cairoTransformMatrix );
00916
00917
00918
00919 plRotationShear( args->xform, &rotation, &shear, &stride );
00920 rotation -= pls->diorot * PI / 2.0;
00921 cos_rot = cos( rotation );
00922 sin_rot = sin( rotation );
00923 cos_shear = cos( shear );
00924 sin_shear = sin( shear );
00925
00926
00927 cairo_matrix_init( cairoTransformMatrix,
00928 cos_rot * stride,
00929 -sin_rot * stride,
00930 cos_rot * sin_shear + sin_rot * cos_shear,
00931 -sin_rot * sin_shear + cos_rot * cos_shear,
00932 0, 0 );
00933 cairo_transform( aStream->cairoContext, cairoTransformMatrix );
00934 free( cairoTransformMatrix );
00935
00936
00937
00938 cairo_rel_move_to( aStream->cairoContext,
00939 (double) ( -1.0 * args->just * (double) textXExtent ),
00940 (double) 0.5 * fontSize - baseline / 1024.0 );
00941
00942
00943 pango_cairo_show_layout( aStream->cairoContext, layout );
00944
00945
00946 cairo_restore( aStream->cairoContext );
00947
00948
00949 g_object_unref( layout );
00950 free( textWithPangoMarkup );
00951 }
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962 char *ucs4_to_pango_markup_format( PLUNICODE *ucs4, int ucs4Len, float fontSize )
00963 {
00964 char plplotEsc;
00965 int i;
00966 int upDown = 0;
00967 PLUNICODE fci;
00968 char utf8[5];
00969 char *pangoMarkupString;
00970 PLFLT old_sscale, sscale, old_soffset, soffset;
00971 PLINT level = 0.;
00972
00973
00974 pangoMarkupString = (char *) malloc( sizeof ( char ) * MAX_MARKUP_LEN );
00975 for ( i = 0; i < MAX_MARKUP_LEN; i++ )
00976 {
00977 pangoMarkupString[i] = 0;
00978 }
00979
00980
00981 plgesc( &plplotEsc );
00982
00983
00984 plgfci( &fci );
00985 open_span_tag( pangoMarkupString, fci, fontSize, 0 );
00986
00987
00988 i = 0;
00989 while ( i < ucs4Len )
00990 {
00991
00992 if ( strlen( pangoMarkupString ) > ( MAX_MARKUP_LEN - 50 ) )
00993 {
00994 continue;
00995 }
00996 if ( ucs4[i] < PL_FCI_MARK )
00997 {
00998 if ( ucs4[i] != (PLUNICODE) plplotEsc )
00999 {
01000 switch ( ucs4[i] )
01001 {
01002 case 38:
01003 strncat( pangoMarkupString, "&", MAX_MARKUP_LEN - 1 - strlen( pangoMarkupString ) );
01004 break;
01005 case 60:
01006 strncat( pangoMarkupString, "<", MAX_MARKUP_LEN - 1 - strlen( pangoMarkupString ) );
01007 break;
01008 case 62:
01009 strncat( pangoMarkupString, ">", MAX_MARKUP_LEN - 1 - strlen( pangoMarkupString ) );
01010 break;
01011 default:
01012 ucs4_to_utf8( ucs4[i], utf8 );
01013 strncat( pangoMarkupString, utf8, MAX_MARKUP_LEN - 1 - strlen( pangoMarkupString ) );
01014 break;
01015 }
01016 i++;
01017 continue;
01018 }
01019 i++;
01020 if ( ucs4[i] == (PLUNICODE) plplotEsc )
01021 {
01022 ucs4_to_utf8( ucs4[i], utf8 );
01023 strncat( pangoMarkupString, utf8, MAX_MARKUP_LEN - 1 - strlen( pangoMarkupString ) );
01024 i++;
01025 continue;
01026 }
01027 else
01028 {
01029 if ( ucs4[i] == (PLUNICODE) 'u' )
01030 {
01031 if ( upDown < 0 )
01032 {
01033 strncat( pangoMarkupString, "</span>", MAX_MARKUP_LEN - 1 - strlen( pangoMarkupString ) );
01034 level++;
01035 }
01036 else
01037 {
01038 plP_script_scale( TRUE, &level,
01039 &old_sscale, &sscale, &old_soffset, &soffset );
01040 strncat( pangoMarkupString,
01041 rise_span_tag( TRUE, fontSize, sscale, soffset ),
01042 MAX_MARKUP_LEN - 1 - strlen( pangoMarkupString ) );
01043 }
01044 upDown++;
01045 }
01046 if ( ucs4[i] == (PLUNICODE) 'd' )
01047 {
01048 if ( upDown > 0 )
01049 {
01050 strncat( pangoMarkupString, "</span>", MAX_MARKUP_LEN - 1 - strlen( pangoMarkupString ) );
01051 level--;
01052 }
01053 else
01054 {
01055 plP_script_scale( FALSE, &level,
01056 &old_sscale, &sscale, &old_soffset, &soffset );
01057 strncat( pangoMarkupString,
01058 rise_span_tag( FALSE, fontSize, sscale, soffset ),
01059 MAX_MARKUP_LEN - 1 - strlen( pangoMarkupString ) );
01060 }
01061 upDown--;
01062 }
01063 i++;
01064 }
01065 }
01066 else
01067 {
01068 close_span_tag( pangoMarkupString, upDown );
01069 open_span_tag( pangoMarkupString, ucs4[i], fontSize, upDown );
01070 i++;
01071 }
01072 }
01073
01074
01075 close_span_tag( pangoMarkupString, upDown );
01076
01077
01078
01079 return pangoMarkupString;
01080 }
01081
01082
01083
01084
01085
01086
01087
01088
01089
01090
01091 void open_span_tag( char *pangoMarkupString, PLUNICODE fci, float fontSize, int upDown )
01092 {
01093 unsigned char fontFamily, fontStyle, fontWeight;
01094 char openTag[TAG_LEN];
01095 int upDown_level;
01096 PLFLT old_sscale, sscale, old_soffset, soffset;
01097 PLINT level = 0.;
01098
01099
01100
01101 plP_fci2hex( fci, &fontFamily, PL_FCI_FAMILY );
01102 plP_fci2hex( fci, &fontStyle, PL_FCI_STYLE );
01103 plP_fci2hex( fci, &fontWeight, PL_FCI_WEIGHT );
01104
01105
01106
01107 snprintf( openTag, TAG_LEN, "<span font_desc=\"%s\" size=\"%d\" ", familyLookup[fontFamily], (int) ( fontSize * 1024. ) );
01108 strncat( pangoMarkupString, openTag, MAX_MARKUP_LEN - 1 - strlen( pangoMarkupString ) );
01109
01110 snprintf( openTag, TAG_LEN, "style=\"%s\" ", styleLookup[fontStyle] );
01111 strncat( pangoMarkupString, openTag, MAX_MARKUP_LEN - 1 - strlen( pangoMarkupString ) );
01112
01113 snprintf( openTag, TAG_LEN, "weight=\"%s\">", weightLookup[fontWeight] );
01114 strncat( pangoMarkupString, openTag, MAX_MARKUP_LEN - 1 - strlen( pangoMarkupString ) );
01115
01116
01117 for ( upDown_level = 0; upDown_level < upDown; upDown_level++ )
01118 {
01119 plP_script_scale( TRUE, &level,
01120 &old_sscale, &sscale, &old_soffset, &soffset );
01121 strncat( pangoMarkupString,
01122 rise_span_tag( TRUE, fontSize, sscale, soffset ),
01123 MAX_MARKUP_LEN - 1 - strlen( pangoMarkupString ) );
01124 }
01125 for ( upDown_level = 0; upDown_level > upDown; upDown_level-- )
01126 {
01127 plP_script_scale( FALSE, &level,
01128 &old_sscale, &sscale, &old_soffset, &soffset );
01129 strncat( pangoMarkupString,
01130 rise_span_tag( FALSE, fontSize, sscale, soffset ),
01131 MAX_MARKUP_LEN - 1 - strlen( pangoMarkupString ) );
01132 }
01133 }
01134
01135
01136
01137
01138
01139
01140
01141 void close_span_tag( char *pangoMarkupString, int upDown )
01142 {
01143 if ( upDown > 0 )
01144 {
01145 while ( upDown > 0 )
01146 {
01147 strncat( pangoMarkupString, "</span>", MAX_MARKUP_LEN - 1 - strlen( pangoMarkupString ) );
01148 upDown--;
01149 }
01150 }
01151 if ( upDown < 0 )
01152 {
01153 while ( upDown < 0 )
01154 {
01155 strncat( pangoMarkupString, "</span>", MAX_MARKUP_LEN - 1 - strlen( pangoMarkupString ) );
01156 upDown++;
01157 }
01158 }
01159
01160 strncat( pangoMarkupString, "</span>", MAX_MARKUP_LEN - 1 - strlen( pangoMarkupString ) );
01161 }
01162
01163
01164
01165
01166
01167
01168 # define RISE_FACTOR 0.8
01169
01170
01171
01172
01173
01174
01175
01176
01177
01178
01179
01180
01181 char *rise_span_tag( int ifsuperscript, float fontSize, float multiplier, float rise )
01182 {
01183 float offset;
01184 static char tag[100];
01185
01186
01187
01188
01189
01190
01191 rise = 1024. * fontSize * RISE_FACTOR * rise;
01192
01193
01194
01195
01196 offset = 1024. * 0.5 * fontSize * ( 1.0 - multiplier );
01197
01198 if ( ifsuperscript )
01199 {
01200 sprintf( tag, "<span rise=\"%d\" size=\"%d\">",
01201 (int) ( rise + offset ), (int) ( fontSize * 1024. * multiplier ) );
01202 }
01203 else
01204 {
01205 sprintf( tag, "<span rise=\"%d\" size=\"%d\">",
01206 (int) -( rise - offset ), (int) ( fontSize * 1024. * multiplier ) );
01207 }
01208
01209 return ( tag );
01210 }
01211
01212
01213
01214
01215
01216
01217
01218
01219 cairo_status_t write_to_stream( void *filePointer, unsigned char *data, unsigned int length )
01220 {
01221 int bytes_written;
01222
01223 bytes_written = fwrite( data, 1, length, (FILE *) filePointer );
01224 if ( bytes_written == length )
01225 {
01226 return CAIRO_STATUS_SUCCESS;
01227 }
01228 else
01229 {
01230 return CAIRO_STATUS_WRITE_ERROR;
01231 }
01232 }
01233
01234
01235
01236
01237
01238
01239
01240
01241
01242
01243 PLCairo *stream_and_font_setup( PLStream *pls, int interactive )
01244 {
01245 int i;
01246 char *a;
01247 PLCairo *aStream;
01248 PLFLT downscale;
01249 downscale = 0.0;
01250
01251
01252 pls->termin = interactive;
01253 pls->dev_flush = 1;
01254 pls->color = 1;
01255 pls->dev_text = 1;
01256 pls->dev_unicode = 1;
01257 pls->dev_clear = 0;
01258 pls->alt_unicode = 1;
01259 pls->page = 0;
01260 pls->dev_fill0 = 1;
01261 pls->dev_gradient = 1;
01262 pls->dev_arc = 1;
01263 pls->plbuf_write = interactive;
01264 pls->has_string_length = 1;
01265 pls->dev_modeset = 1;
01266
01267 if ( pls->xlength <= 0 || pls->ylength <= 0 )
01268 {
01269 pls->xlength = PLCAIRO_DEFAULT_X;
01270 pls->ylength = PLCAIRO_DEFAULT_Y;
01271 }
01272
01273
01274 if ( pls->xlength > pls->ylength )
01275 downscale = (double) pls->xlength / (double) ( PIXELS_X - 1 );
01276 else
01277 downscale = (double) pls->ylength / (double) PIXELS_Y;
01278 plP_setphy( (PLINT) 0, (PLINT) ( pls->xlength / downscale ), (PLINT) 0, (PLINT) ( pls->ylength / downscale ) );
01279 plP_setpxl( DPI / 25.4 / downscale, DPI / 25.4 / downscale );
01280
01281
01282
01283 for ( i = 0; i < NPANGOLOOKUP; i++ )
01284 {
01285 if ( ( a = getenv( envFamilyLookup[i] ) ) != NULL )
01286 {
01287 strncpy( familyLookup[i], a, FAMILY_LOOKUP_LEN - 1 );
01288 familyLookup[i][FAMILY_LOOKUP_LEN - 1] = '\0';
01289 }
01290 else
01291 {
01292 strncpy( familyLookup[i], defaultFamilyLookup[i], FAMILY_LOOKUP_LEN - 1 );
01293 familyLookup[i][FAMILY_LOOKUP_LEN - 1] = '\0';
01294 }
01295 }
01296
01297
01298 aStream = malloc( sizeof ( PLCairo ) );
01299 #if defined ( PLD_xcairo )
01300 aStream->XDisplay = NULL;
01301 aStream->XWindow = -1;
01302 #endif
01303 aStream->cairoSurface = NULL;
01304 aStream->cairoContext = NULL;
01305 aStream->downscale = downscale;
01306
01307
01308
01309 aStream->text_clipping = 1;
01310 text_clipping = 1;
01311 text_anti_aliasing = 0;
01312 graphics_anti_aliasing = 0;
01313 rasterize_image = 1;
01314 set_background = 0;
01315 image_buffering = 1;
01316
01317
01318 plParseDrvOpts( cairo_options );
01319
01320
01321 if ( !text_clipping )
01322 {
01323 aStream->text_clipping = 0;
01324 }
01325
01326
01327 aStream->text_anti_aliasing = text_anti_aliasing;
01328 aStream->graphics_anti_aliasing = graphics_anti_aliasing;
01329 aStream->rasterize_image = rasterize_image;
01330 aStream->set_background = set_background;
01331 aStream->image_buffering = image_buffering;
01332
01333 return aStream;
01334 }
01335
01336
01337
01338
01339
01340
01341
01342
01343 void set_current_context( PLStream *pls )
01344 {
01345 PLCairo *aStream;
01346
01347 aStream = (PLCairo *) pls->dev;
01348 cairo_set_source_rgba( aStream->cairoContext,
01349 (double) pls->curcolor.r / 255.0,
01350 (double) pls->curcolor.g / 255.0,
01351 (double) pls->curcolor.b / 255.0,
01352 (double) pls->curcolor.a );
01353
01354 if ( pls->width < 1 )
01355 {
01356 cairo_set_line_width( aStream->cairoContext, 1.0 );
01357 }
01358 else
01359 {
01360 cairo_set_line_width( aStream->cairoContext, (double) pls->width );
01361 }
01362 }
01363
01364
01365
01366
01367
01368
01369
01370
01371
01372 void poly_line( PLStream *pls, short *xa, short *ya, PLINT npts )
01373 {
01374 int i;
01375 PLCairo *aStream;
01376
01377 aStream = (PLCairo *) pls->dev;
01378
01379 set_current_context( pls );
01380
01381 cairo_move_to( aStream->cairoContext, aStream->downscale * (double) xa[0], aStream->downscale * (double) ya[0] );
01382 for ( i = 1; i < npts; i++ )
01383 {
01384 cairo_line_to( aStream->cairoContext, aStream->downscale * (double) xa[i], aStream->downscale * (double) ya[i] );
01385 }
01386 }
01387
01388
01389
01390
01391
01392
01393
01394 void filled_polygon( PLStream *pls, short *xa, short *ya, PLINT npts )
01395 {
01396 int i;
01397 PLCairo *aStream;
01398
01399 aStream = (PLCairo *) pls->dev;
01400
01401 cairo_save( aStream->cairoContext );
01402
01403
01404 poly_line( pls, xa, ya, npts );
01405
01406 cairo_set_source_rgba( aStream->cairoContext,
01407 (double) pls->curcolor.r / 255.0,
01408 (double) pls->curcolor.g / 255.0,
01409 (double) pls->curcolor.b / 255.0,
01410 (double) pls->curcolor.a );
01411
01412 if ( cairo_get_antialias( aStream->cairoContext ) != CAIRO_ANTIALIAS_NONE )
01413 {
01414 cairo_fill_preserve( aStream->cairoContext );
01415
01416
01417 set_line_properties( aStream, CAIRO_LINE_JOIN_BEVEL, CAIRO_LINE_CAP_BUTT );
01418 cairo_set_line_width( aStream->cairoContext, 1.0 );
01419 cairo_stroke( aStream->cairoContext );
01420 }
01421 else
01422 {
01423 cairo_fill( aStream->cairoContext );
01424 }
01425
01426 cairo_restore( aStream->cairoContext );
01427 }
01428
01429
01430
01431
01432
01433
01434
01435 void gradient( PLStream *pls, short *xa, short *ya, PLINT npts )
01436 {
01437 int i;
01438 PLCairo *aStream;
01439 cairo_pattern_t *linear_gradient;
01440
01441 aStream = (PLCairo *) pls->dev;
01442
01443
01444 set_line_properties( aStream, CAIRO_LINE_JOIN_BEVEL, CAIRO_LINE_CAP_BUTT );
01445
01446 linear_gradient = cairo_pattern_create_linear(
01447 aStream->downscale * pls->xgradient[0],
01448 aStream->downscale * pls->ygradient[0],
01449 aStream->downscale * pls->xgradient[1],
01450 aStream->downscale * pls->ygradient[1] );
01451
01452 cairo_pattern_reference( linear_gradient );
01453 for ( i = 0; i < pls->ncol1; i++ )
01454 {
01455 cairo_pattern_add_color_stop_rgba( linear_gradient,
01456 (double) i / (double) ( pls->ncol1 - 1 ),
01457 (double) pls->cmap1[i].r / 255.,
01458 (double) pls->cmap1[i].g / 255.,
01459 (double) pls->cmap1[i].b / 255.,
01460 (double) pls->cmap1[i].a );
01461 }
01462
01463
01464 poly_line( pls, xa, ya, npts );
01465
01466 cairo_set_source( aStream->cairoContext, linear_gradient );
01467 cairo_fill( aStream->cairoContext );
01468 cairo_pattern_destroy( linear_gradient );
01469 }
01470
01471
01472
01473
01474
01475
01476
01477
01478
01479 void set_clip( PLStream *pls )
01480 {
01481 PLINT rcx[4], rcy[4];
01482 PLCairo *aStream;
01483 aStream = (PLCairo *) pls->dev;
01484
01485
01486 difilt_clip( rcx, rcy );
01487
01488
01489
01490 cairo_move_to( aStream->cairoContext,
01491 aStream->downscale * (double) rcx[0],
01492 aStream->downscale * (double) rcy[0] );
01493 cairo_line_to( aStream->cairoContext,
01494 aStream->downscale * (double) rcx[1],
01495 aStream->downscale * (double) rcy[1] );
01496 cairo_line_to( aStream->cairoContext,
01497 aStream->downscale * (double) rcx[2],
01498 aStream->downscale * (double) rcy[2] );
01499 cairo_line_to( aStream->cairoContext,
01500 aStream->downscale * (double) rcx[3],
01501 aStream->downscale * (double) rcy[3] );
01502 cairo_line_to( aStream->cairoContext,
01503 aStream->downscale * (double) rcx[0],
01504 aStream->downscale * (double) rcy[0] );
01505
01506
01507 cairo_clip( aStream->cairoContext );
01508
01509
01510
01511 cairo_new_path( aStream->cairoContext );
01512 }
01513
01514
01515
01516
01517
01518
01519
01520 void arc( PLStream *pls, arc_struct *arc_info )
01521 {
01522 PLCairo *aStream;
01523 double x, y, a, b;
01524 double angle1, angle2, rotate;
01525
01526 set_current_context( pls );
01527
01528 aStream = (PLCairo *) pls->dev;
01529
01530
01531 x = aStream->downscale * arc_info->x;
01532 y = aStream->downscale * arc_info->y;
01533 a = aStream->downscale * arc_info->a;
01534 b = aStream->downscale * arc_info->b;
01535
01536
01537 angle1 = arc_info->angle1 * M_PI / 180.0;
01538 angle2 = arc_info->angle2 * M_PI / 180.0;
01539 rotate = arc_info->rotate * M_PI / 180.0;
01540
01541 cairo_save( aStream->cairoContext );
01542
01543
01544 set_clip( pls );
01545
01546
01547 cairo_save( aStream->cairoContext );
01548 cairo_translate( aStream->cairoContext, x, y );
01549 cairo_rotate( aStream->cairoContext, rotate );
01550 cairo_scale( aStream->cairoContext, a, b );
01551 cairo_arc( aStream->cairoContext, 0.0, 0.0, 1.0, angle1, angle2 );
01552 if ( arc_info->fill )
01553 cairo_line_to( aStream->cairoContext, 0.0, 0.0 );
01554 cairo_restore( aStream->cairoContext );
01555
01556 cairo_set_source_rgba( aStream->cairoContext,
01557 (double) pls->curcolor.r / 255.0,
01558 (double) pls->curcolor.g / 255.0,
01559 (double) pls->curcolor.b / 255.0,
01560 (double) pls->curcolor.a );
01561 if ( arc_info->fill )
01562 {
01563 cairo_fill( aStream->cairoContext );
01564 }
01565 else
01566 {
01567 cairo_stroke( aStream->cairoContext );
01568 }
01569 cairo_restore( aStream->cairoContext );
01570 }
01571
01572
01573
01574
01575
01576
01577
01578 void rotate_cairo_surface( PLStream *pls, float x11, float x12, float x21, float x22, float x0, float y0, PLBOOL is_xcairo )
01579 {
01580 cairo_matrix_t *matrix;
01581 PLCairo *aStream;
01582
01583 aStream = (PLCairo *) pls->dev;
01584
01585 matrix = (cairo_matrix_t *) malloc( sizeof ( cairo_matrix_t ) );
01586 cairo_matrix_init( matrix, x11, x12, x21, x22, x0, y0 );
01587 #if defined ( PLD_xcairo )
01588 if ( is_xcairo )
01589 {
01590 cairo_transform( aStream->cairoContext_X, matrix );
01591 }
01592 else
01593 {
01594 cairo_transform( aStream->cairoContext, matrix );
01595 }
01596 #else
01597 cairo_transform( aStream->cairoContext, matrix );
01598 #endif
01599 free( matrix );
01600 }
01601
01602
01603
01604
01605
01606
01607
01608
01609 #if defined ( PLD_pngcairo ) || defined ( PLD_svgcairo )
01610
01611 void plD_bop_famcairo( PLStream * );
01612
01613
01614
01615
01616
01617
01618 void plD_bop_famcairo( PLStream *pls )
01619 {
01620 PLCairo *aStream;
01621
01622 aStream = (PLCairo *) pls->dev;
01623
01624
01625 plGetFam( pls );
01626 pls->famadv = 1;
01627 pls->page++;
01628
01629
01630 cairo_rectangle( aStream->cairoContext, 0.0, 0.0, pls->xlength, pls->ylength );
01631 cairo_set_source_rgba( aStream->cairoContext,
01632 (double) pls->cmap0[0].r / 255.0,
01633 (double) pls->cmap0[0].g / 255.0,
01634 (double) pls->cmap0[0].b / 255.0,
01635 (double) pls->cmap0[0].a );
01636 cairo_fill( aStream->cairoContext );
01637 }
01638
01639 #endif
01640
01641
01642
01643
01644
01645
01646
01647
01648 #if defined ( PLD_xcairo )
01649
01650 static int XScreen;
01651 static Window rootWindow;
01652
01653 void plD_dispatch_init_xcairo( PLDispatchTable *pdt );
01654 void plD_init_xcairo( PLStream * );
01655 void plD_bop_xcairo( PLStream * );
01656 void plD_eop_xcairo( PLStream * );
01657 void plD_tidy_xcairo( PLStream * );
01658 void plD_esc_xcairo( PLStream *, PLINT, void * );
01659 static void xcairo_get_cursor( PLStream *, PLGraphicsIn * );
01660
01661
01662
01663
01664
01665
01666
01667 void plD_dispatch_init_xcairo( PLDispatchTable *pdt )
01668 {
01669 #ifndef ENABLE_DYNDRIVERS
01670 pdt->pl_MenuStr = "Cairo X Windows Driver";
01671 pdt->pl_DevName = "xcairo";
01672 #endif
01673 pdt->pl_type = plDevType_Interactive;
01674 pdt->pl_seq = 100;
01675 pdt->pl_init = (plD_init_fp) plD_init_xcairo;
01676 pdt->pl_line = (plD_line_fp) plD_line_cairo;
01677 pdt->pl_polyline = (plD_polyline_fp) plD_polyline_cairo;
01678 pdt->pl_eop = (plD_eop_fp) plD_eop_xcairo;
01679 pdt->pl_bop = (plD_bop_fp) plD_bop_xcairo;
01680 pdt->pl_tidy = (plD_tidy_fp) plD_tidy_xcairo;
01681 pdt->pl_state = (plD_state_fp) plD_state_cairo;
01682 pdt->pl_esc = (plD_esc_fp) plD_esc_xcairo;
01683 }
01684
01685
01686
01687
01688
01689
01690
01691
01692
01693
01694
01695
01696
01697 static signed int xcairo_init_cairo( PLStream *pls )
01698 {
01699 PLCairo *aStream;
01700 Visual *defaultVisual;
01701
01702 aStream = (PLCairo *) pls->dev;
01703
01704
01705 defaultVisual = DefaultVisual( aStream->XDisplay, 0 );
01706
01707
01708 aStream->cairoSurface_X = cairo_xlib_surface_create( aStream->XDisplay, aStream->XWindow, defaultVisual, pls->xlength, pls->ylength );
01709 aStream->cairoContext_X = cairo_create( aStream->cairoSurface_X );
01710
01711 if ( aStream->image_buffering == 0 )
01712 {
01713 aStream->cairoSurface = cairo_surface_create_similar( aStream->cairoSurface_X, CAIRO_CONTENT_COLOR_ALPHA, pls->xlength, pls->ylength );
01714 aStream->cairoContext = cairo_create( aStream->cairoSurface );
01715 }
01716 else
01717 {
01718
01719 aStream->cairoSurface =
01720 cairo_image_surface_create( CAIRO_FORMAT_ARGB32,
01721 pls->xlength, pls->ylength );
01722 aStream->cairoContext = cairo_create( aStream->cairoSurface );
01723 }
01724
01725
01726 rotate_cairo_surface( pls, 1.0, 0.0, 0.0, -1.0, 0.0, pls->ylength, TRUE );
01727
01728
01729 cairo_set_antialias( aStream->cairoContext, aStream->graphics_anti_aliasing );
01730
01731
01732 if ( pls->dev_eofill )
01733 cairo_set_fill_rule( aStream->cairoContext, CAIRO_FILL_RULE_EVEN_ODD );
01734 else
01735 cairo_set_fill_rule( aStream->cairoContext, CAIRO_FILL_RULE_WINDING );
01736
01737
01738
01739 cairo_rectangle( aStream->cairoContext_X, 0.0, 0.0, pls->xlength, pls->ylength );
01740 cairo_set_source_rgba( aStream->cairoContext_X,
01741 (double) pls->cmap0[0].r / 255.0,
01742 (double) pls->cmap0[0].g / 255.0,
01743 (double) pls->cmap0[0].b / 255.0,
01744 (double) pls->cmap0[0].a );
01745 cairo_fill( aStream->cairoContext_X );
01746
01747 XFlush( aStream->XDisplay );
01748
01749 return 0;
01750 }
01751
01752
01753
01754
01755
01756
01757
01758 void plD_init_xcairo( PLStream *pls )
01759 {
01760 PLCairo *aStream;
01761 Atom wmDelete;
01762
01763
01764 aStream = stream_and_font_setup( pls, 1 );
01765
01766
01767 pls->dev = aStream;
01768
01769
01770 if ( external_drawable != 0 )
01771 {
01772 aStream->xdrawable_mode = 1;
01773 }
01774 else
01775 {
01776
01777 aStream->XDisplay = NULL;
01778 aStream->XDisplay = XOpenDisplay( NULL );
01779 if ( aStream->XDisplay == NULL )
01780 {
01781 printf( "Failed to open X Windows display\n" );
01782
01783 }
01784 XScreen = DefaultScreen( aStream->XDisplay );
01785 rootWindow = RootWindow( aStream->XDisplay, XScreen );
01786
01787 aStream->XWindow = XCreateSimpleWindow( aStream->XDisplay, rootWindow, 0, 0, pls->xlength, pls->ylength,
01788 1, BlackPixel( aStream->XDisplay, XScreen ), BlackPixel( aStream->XDisplay, XScreen ) );
01789 XStoreName( aStream->XDisplay, aStream->XWindow, pls->plwindow );
01790 XSelectInput( aStream->XDisplay, aStream->XWindow, NoEventMask );
01791 XMapWindow( aStream->XDisplay, aStream->XWindow );
01792 aStream->xdrawable_mode = 0;
01793
01794 wmDelete = XInternAtom( aStream->XDisplay, "WM_DELETE_WINDOW", True );
01795 XSetWMProtocols( aStream->XDisplay, aStream->XWindow, &wmDelete, 1 );
01796
01797 xcairo_init_cairo( pls );
01798 }
01799
01800 aStream->exit_event_loop = 0;
01801 }
01802
01803
01804
01805
01806
01807
01808
01809
01810 void blit_to_x( PLStream *pls, double x, double y, double w, double h )
01811 {
01812 PLCairo *aStream;
01813
01814 aStream = pls->dev;
01815
01816 cairo_save( aStream->cairoContext );
01817
01818
01819 cairo_rectangle( aStream->cairoContext, x, y, w, h );
01820 cairo_set_operator( aStream->cairoContext, CAIRO_OPERATOR_DEST_OVER );
01821 cairo_set_source_rgba( aStream->cairoContext,
01822 (double) pls->cmap0[0].r / 255.0,
01823 (double) pls->cmap0[0].g / 255.0,
01824 (double) pls->cmap0[0].b / 255.0,
01825 (double) pls->cmap0[0].a );
01826 cairo_fill( aStream->cairoContext );
01827 cairo_restore( aStream->cairoContext );
01828
01829 cairo_save( aStream->cairoContext_X );
01830
01831 cairo_rectangle( aStream->cairoContext_X, x, y, w, h );
01832 cairo_set_operator( aStream->cairoContext_X, CAIRO_OPERATOR_SOURCE );
01833 cairo_set_source_surface( aStream->cairoContext_X,
01834 aStream->cairoSurface, 0.0, 0.0 );
01835 cairo_fill( aStream->cairoContext_X );
01836 cairo_restore( aStream->cairoContext_X );
01837 }
01838
01839
01840
01841
01842
01843
01844
01845 void plD_bop_xcairo( PLStream *pls )
01846 {
01847 PLCairo *aStream;
01848
01849 aStream = (PLCairo *) pls->dev;
01850
01851 plD_bop_cairo( pls );
01852
01853 if ( aStream->xdrawable_mode )
01854 return;
01855
01856 XFlush( aStream->XDisplay );
01857 }
01858
01859
01860
01861
01862
01863
01864
01865 void plD_eop_xcairo( PLStream *pls )
01866 {
01867 int number_chars;
01868 long event_mask;
01869 char event_string[10];
01870 KeySym keysym;
01871 XComposeStatus cs;
01872 XEvent event;
01873 XExposeEvent *expose;
01874 PLCairo *aStream;
01875 char helpmsg[] = " - Press Enter or right-click to continue";
01876 char *plotTitle;
01877
01878 aStream = (PLCairo *) pls->dev;
01879
01880
01881 blit_to_x( pls, 0.0, 0.0, pls->xlength, pls->ylength );
01882
01883 if ( aStream->xdrawable_mode )
01884 return;
01885
01886
01887 if ( pls->nopause )
01888 aStream->exit_event_loop = 1;
01889
01890
01891 event_mask = ButtonPressMask | KeyPressMask | ExposureMask;
01892 XSelectInput( aStream->XDisplay, aStream->XWindow, event_mask );
01893 while ( !aStream->exit_event_loop )
01894 {
01895
01896 XNextEvent( aStream->XDisplay, &event );
01897 switch ( event.type )
01898 {
01899 case KeyPress:
01900 number_chars = XLookupString( (XKeyEvent *) &event, event_string, 10, &keysym, &cs );
01901 event_string[number_chars] = '\0';
01902 if ( keysym == XK_Return )
01903 {
01904 aStream->exit_event_loop = 1;
01905 }
01906 break;
01907 case ButtonPress:
01908 if ( ( (XButtonEvent *) &event )->button == Button3 )
01909 aStream->exit_event_loop = 1;
01910 break;
01911 case ClientMessage:
01912
01913 pls->stream_closed = TRUE;
01914 aStream->exit_event_loop = 1;
01915 break;
01916 case Expose:
01917
01918
01919 expose = (XExposeEvent *) &event;
01920 if ( expose->count == 0 )
01921 {
01922 blit_to_x( pls, expose->x, expose->y,
01923 expose->width, expose->height );
01924 }
01925 break;
01926 }
01927 }
01928 aStream->exit_event_loop = 0;
01929 }
01930
01931
01932
01933
01934
01935
01936
01937 void plD_tidy_xcairo( PLStream *pls )
01938 {
01939 PLCairo *aStream;
01940
01941 aStream = (PLCairo *) pls->dev;
01942
01943 plD_tidy_cairo( pls );
01944
01945
01946 cairo_destroy( aStream->cairoContext_X );
01947 cairo_surface_destroy( aStream->cairoSurface_X );
01948
01949 if ( aStream->xdrawable_mode )
01950 return;
01951
01952
01953 XFlush( aStream->XDisplay );
01954
01955 XDestroyWindow( aStream->XDisplay, aStream->XWindow );
01956
01957 XCloseDisplay( aStream->XDisplay );
01958 }
01959
01960
01961
01962
01963
01964
01965
01966 void plD_esc_xcairo( PLStream *pls, PLINT op, void *ptr )
01967 {
01968 PLCairo *aStream;
01969
01970 aStream = (PLCairo *) pls->dev;
01971
01972 switch ( op )
01973 {
01974 case PLESC_FLUSH:
01975 blit_to_x( pls, 0.0, 0.0, pls->xlength, pls->ylength );
01976 XFlush( aStream->XDisplay );
01977 break;
01978 case PLESC_GETC:
01979 blit_to_x( pls, 0.0, 0.0, pls->xlength, pls->ylength );
01980 XFlush( aStream->XDisplay );
01981 xcairo_get_cursor( pls, (PLGraphicsIn *) ptr );
01982 break;
01983 case PLESC_DEVINIT: {
01984 Window rootwin;
01985 PLXcairoDrawableInfo *xinfo = (PLXcairoDrawableInfo *) ptr;
01986 signed int x, y;
01987 unsigned int w, h, b, d;
01988 if ( xinfo == NULL )
01989 {
01990 printf( "xcairo: PLESC_DEVINIT ignored, no drawable info provided\n" );
01991 return;
01992 }
01993 if ( aStream->xdrawable_mode == 0 )
01994 {
01995 printf( "xcairo: PLESC_DEVINIT called with drawable but stream not in xdrawable mode\n" );
01996 return;
01997 }
01998 aStream->XDisplay = xinfo->display;
01999 aStream->XWindow = xinfo->drawable;
02000
02001
02002 XGetGeometry( aStream->XDisplay, aStream->XWindow, &rootwin,
02003 &x, &y, &w, &h, &b, &d );
02004 pls->xlength = w;
02005 pls->ylength = h;
02006 plP_setphy( (PLINT) 0, (PLINT) ( pls->xlength / aStream->downscale ), (PLINT) 0,
02007 (PLINT) ( pls->ylength / aStream->downscale ) );
02008
02009
02010 xcairo_init_cairo( pls );
02011
02012
02013 plbop();
02014
02015 break;
02016 }
02017 default:
02018 plD_esc_cairo( pls, op, ptr );
02019 break;
02020 }
02021 }
02022
02023
02024
02025
02026
02027
02028
02029 void xcairo_get_cursor( PLStream *pls, PLGraphicsIn *gin )
02030 {
02031 int number_chars;
02032 char *ksname;
02033 char str[257];
02034 KeySym keysym;
02035 XComposeStatus cs;
02036 XEvent event;
02037 XButtonEvent *xButtonEvent;
02038 Cursor xHairCursor;
02039 PLCairo *aStream;
02040
02041 aStream = (PLCairo *) pls->dev;
02042
02043
02044 plGinInit( gin );
02045
02046
02047 xHairCursor = XCreateFontCursor( aStream->XDisplay, XC_crosshair );
02048 XDefineCursor( aStream->XDisplay, aStream->XWindow, xHairCursor );
02049
02050
02051 XSelectInput( aStream->XDisplay, aStream->XWindow, ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask | ButtonMotionMask );
02052 XMaskEvent( aStream->XDisplay, ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask | ButtonMotionMask, &event );
02053 XSelectInput( aStream->XDisplay, aStream->XWindow, NoEventMask );
02054
02055
02056 xButtonEvent = (XButtonEvent *) &event;
02057 gin->state = xButtonEvent->state;
02058 gin->button = xButtonEvent->button;
02059 gin->pX = event.xbutton.x;
02060 gin->pY = pls->ylength - event.xbutton.y;
02061 gin->dX = (PLFLT) event.xbutton.x / ( (PLFLT) ( pls->xlength ) );
02062 gin->dY = (PLFLT) ( pls->ylength - event.xbutton.y ) / ( (PLFLT) ( pls->ylength ) );
02063
02064
02065 if ( event.type == KeyPress || event.type == KeyRelease )
02066 {
02067 number_chars = XLookupString( (XKeyEvent *) &event, str, 100, &keysym, NULL );
02068 if ( keysym == NoSymbol )
02069 ksname = "NoSymbol";
02070 else if ( !( ksname = XKeysymToString( keysym ) ) )
02071 ksname = "(no name)";
02072 strcpy( gin->string, ksname );
02073
02074 switch ( keysym )
02075 {
02076 case XK_BackSpace:
02077 case XK_Tab:
02078 case XK_Linefeed:
02079 case XK_Return:
02080 case XK_Escape:
02081 case XK_Delete:
02082 gin->keysym = 0xFF & keysym;
02083 break;
02084 default:
02085 gin->keysym = keysym;
02086 }
02087 }
02088 else
02089 {
02090 sprintf( gin->string, "button %u", gin->button );
02091 gin->keysym = 0x20;
02092 }
02093
02094
02095 XUndefineCursor( aStream->XDisplay, aStream->XWindow );
02096 XFlush( aStream->XDisplay );
02097 }
02098
02099 #endif
02100
02101
02102
02103
02104
02105
02106
02107
02108
02109
02110 #if defined ( PLD_pdfcairo )
02111
02112 void plD_dispatch_init_pdfcairo( PLDispatchTable *pdt );
02113 void plD_init_pdfcairo( PLStream * );
02114
02115
02116
02117
02118
02119
02120
02121
02122 void plD_dispatch_init_pdfcairo( PLDispatchTable *pdt )
02123 {
02124 #ifndef ENABLE_DYNDRIVERS
02125 pdt->pl_MenuStr = "Cairo PDF Driver";
02126 pdt->pl_DevName = "pdfcairo";
02127 #endif
02128 pdt->pl_type = plDevType_FileOriented;
02129 pdt->pl_seq = 101;
02130 pdt->pl_init = (plD_init_fp) plD_init_pdfcairo;
02131 pdt->pl_line = (plD_line_fp) plD_line_cairo;
02132 pdt->pl_polyline = (plD_polyline_fp) plD_polyline_cairo;
02133 pdt->pl_eop = (plD_eop_fp) plD_eop_cairo;
02134 pdt->pl_bop = (plD_bop_fp) plD_bop_cairo;
02135 pdt->pl_tidy = (plD_tidy_fp) plD_tidy_cairo;
02136 pdt->pl_state = (plD_state_fp) plD_state_cairo;
02137 pdt->pl_esc = (plD_esc_fp) plD_esc_cairo;
02138 }
02139
02140
02141
02142
02143
02144
02145
02146 void plD_init_pdfcairo( PLStream *pls )
02147 {
02148 PLCairo *aStream;
02149
02150
02151 aStream = stream_and_font_setup( pls, 0 );
02152
02153
02154 plOpenFile( pls );
02155
02156
02157
02158 aStream->cairoSurface = cairo_pdf_surface_create_for_stream( (cairo_write_func_t) write_to_stream, pls->OutFile, (double) pls->xlength, (double) pls->ylength );
02159 aStream->cairoContext = cairo_create( aStream->cairoSurface );
02160
02161
02162 pls->dev = aStream;
02163
02164
02165 rotate_cairo_surface( pls, 1.0, 0.0, 0.0, -1.0, 0.0, pls->ylength, FALSE );
02166
02167
02168 cairo_set_antialias( aStream->cairoContext, aStream->graphics_anti_aliasing );
02169
02170
02171 if ( pls->dev_eofill )
02172 cairo_set_fill_rule( aStream->cairoContext, CAIRO_FILL_RULE_EVEN_ODD );
02173 else
02174 cairo_set_fill_rule( aStream->cairoContext, CAIRO_FILL_RULE_WINDING );
02175 }
02176
02177 #endif
02178
02179
02180
02181
02182
02183
02184
02185
02186
02187
02188 #if defined ( PLD_pscairo )
02189
02190 void plD_dispatch_init_pscairo( PLDispatchTable *pdt );
02191 void plD_init_pscairo( PLStream * );
02192
02193
02194
02195
02196
02197
02198
02199
02200 void plD_dispatch_init_pscairo( PLDispatchTable *pdt )
02201 {
02202 #ifndef ENABLE_DYNDRIVERS
02203 pdt->pl_MenuStr = "Cairo PS Driver";
02204 pdt->pl_DevName = "pscairo";
02205 #endif
02206 pdt->pl_type = plDevType_FileOriented;
02207 pdt->pl_seq = 102;
02208 pdt->pl_init = (plD_init_fp) plD_init_pscairo;
02209 pdt->pl_line = (plD_line_fp) plD_line_cairo;
02210 pdt->pl_polyline = (plD_polyline_fp) plD_polyline_cairo;
02211 pdt->pl_eop = (plD_eop_fp) plD_eop_cairo;
02212 pdt->pl_bop = (plD_bop_fp) plD_bop_cairo;
02213 pdt->pl_tidy = (plD_tidy_fp) plD_tidy_cairo;
02214 pdt->pl_state = (plD_state_fp) plD_state_cairo;
02215 pdt->pl_esc = (plD_esc_fp) plD_esc_cairo;
02216 }
02217
02218
02219
02220
02221
02222
02223
02224 void plD_init_pscairo( PLStream *pls )
02225 {
02226 PLCairo *aStream;
02227
02228
02229 aStream = stream_and_font_setup( pls, 0 );
02230
02231
02232 plOpenFile( pls );
02233
02234
02235
02236 aStream->cairoSurface = cairo_ps_surface_create_for_stream( (cairo_write_func_t) write_to_stream, pls->OutFile, (double) pls->ylength, (double) pls->xlength );
02237 aStream->cairoContext = cairo_create( aStream->cairoSurface );
02238
02239
02240 pls->dev = aStream;
02241
02242
02243 if ( pls->portrait )
02244 {
02245 plsdiori( 1 );
02246 pls->freeaspect = 1;
02247 }
02248 rotate_cairo_surface( pls, 0.0, -1.0, -1.0, 0.0, pls->ylength, pls->xlength, FALSE );
02249
02250
02251 if ( pls->dev_eofill )
02252 cairo_set_fill_rule( aStream->cairoContext, CAIRO_FILL_RULE_EVEN_ODD );
02253 else
02254 cairo_set_fill_rule( aStream->cairoContext, CAIRO_FILL_RULE_WINDING );
02255 }
02256
02257 #endif
02258
02259
02260
02261
02262
02263
02264
02265
02266
02267
02268 #if defined ( PLD_svgcairo )
02269
02270 void plD_dispatch_init_svgcairo( PLDispatchTable *pdt );
02271 void plD_init_svgcairo( PLStream * );
02272
02273
02274
02275
02276
02277
02278
02279
02280 void plD_dispatch_init_svgcairo( PLDispatchTable *pdt )
02281 {
02282 #ifndef ENABLE_DYNDRIVERS
02283 pdt->pl_MenuStr = "Cairo SVG Driver";
02284 pdt->pl_DevName = "svgcairo";
02285 #endif
02286 pdt->pl_type = plDevType_FileOriented;
02287 pdt->pl_seq = 103;
02288 pdt->pl_init = (plD_init_fp) plD_init_svgcairo;
02289 pdt->pl_line = (plD_line_fp) plD_line_cairo;
02290 pdt->pl_polyline = (plD_polyline_fp) plD_polyline_cairo;
02291 pdt->pl_eop = (plD_eop_fp) plD_eop_cairo;
02292 pdt->pl_bop = (plD_bop_fp) plD_bop_famcairo;
02293 pdt->pl_tidy = (plD_tidy_fp) plD_tidy_cairo;
02294 pdt->pl_state = (plD_state_fp) plD_state_cairo;
02295 pdt->pl_esc = (plD_esc_fp) plD_esc_cairo;
02296 }
02297
02298
02299
02300
02301
02302
02303
02304 void plD_init_svgcairo( PLStream *pls )
02305 {
02306 PLCairo *aStream;
02307
02308
02309
02310
02311
02312
02313
02314
02315
02316
02317
02318
02319 if ( pls->dev == NULL )
02320 {
02321 aStream = stream_and_font_setup( pls, 0 );
02322 }
02323 else
02324 {
02325 stream_and_font_setup( pls, 0 );
02326 aStream = pls->dev;
02327 }
02328
02329
02330 plFamInit( pls );
02331
02332
02333 plOpenFile( pls );
02334
02335
02336 pls->dev = aStream;
02337
02338
02339
02340 aStream->cairoSurface = cairo_svg_surface_create_for_stream( (cairo_write_func_t) write_to_stream, pls->OutFile, (double) pls->xlength, (double) pls->ylength );
02341 aStream->cairoContext = cairo_create( aStream->cairoSurface );
02342
02343
02344 rotate_cairo_surface( pls, 1.0, 0.0, 0.0, -1.0, 0.0, pls->ylength, FALSE );
02345
02346
02347 cairo_set_antialias( aStream->cairoContext, aStream->graphics_anti_aliasing );
02348
02349
02350 if ( pls->dev_eofill )
02351 cairo_set_fill_rule( aStream->cairoContext, CAIRO_FILL_RULE_EVEN_ODD );
02352 else
02353 cairo_set_fill_rule( aStream->cairoContext, CAIRO_FILL_RULE_WINDING );
02354 }
02355
02356 #endif
02357
02358
02359
02360
02361
02362
02363
02364
02365
02366
02367 #if defined ( PLD_pngcairo )
02368
02369 void plD_dispatch_init_pngcairo( PLDispatchTable *pdt );
02370 void plD_init_pngcairo( PLStream * );
02371 void plD_eop_pngcairo( PLStream * );
02372
02373
02374
02375
02376
02377
02378
02379
02380 void plD_dispatch_init_pngcairo( PLDispatchTable *pdt )
02381 {
02382 #ifndef ENABLE_DYNDRIVERS
02383 pdt->pl_MenuStr = "Cairo PNG Driver";
02384 pdt->pl_DevName = "pngcairo";
02385 #endif
02386 pdt->pl_type = plDevType_FileOriented;
02387 pdt->pl_seq = 104;
02388 pdt->pl_init = (plD_init_fp) plD_init_pngcairo;
02389 pdt->pl_line = (plD_line_fp) plD_line_cairo;
02390 pdt->pl_polyline = (plD_polyline_fp) plD_polyline_cairo;
02391 pdt->pl_eop = (plD_eop_fp) plD_eop_pngcairo;
02392 pdt->pl_bop = (plD_bop_fp) plD_bop_famcairo;
02393 pdt->pl_tidy = (plD_tidy_fp) plD_tidy_cairo;
02394 pdt->pl_state = (plD_state_fp) plD_state_cairo;
02395 pdt->pl_esc = (plD_esc_fp) plD_esc_cairo;
02396 }
02397
02398
02399
02400
02401
02402
02403
02404 void plD_init_pngcairo( PLStream *pls )
02405 {
02406 PLCairo *aStream;
02407
02408
02409
02410
02411
02412
02413
02414
02415
02416
02417
02418
02419 if ( pls->dev == NULL )
02420 {
02421 aStream = stream_and_font_setup( pls, 0 );
02422 }
02423 else
02424 {
02425 stream_and_font_setup( pls, 0 );
02426 aStream = pls->dev;
02427 }
02428
02429
02430 plFamInit( pls );
02431
02432
02433 plOpenFile( pls );
02434
02435
02436 pls->dev = aStream;
02437
02438
02439
02440 aStream->cairoSurface = cairo_image_surface_create( CAIRO_FORMAT_ARGB32, (double) pls->xlength, (double) pls->ylength );
02441 aStream->cairoContext = cairo_create( aStream->cairoSurface );
02442
02443
02444 rotate_cairo_surface( pls, 1.0, 0.0, 0.0, -1.0, 0.0, pls->ylength, FALSE );
02445
02446
02447 cairo_set_antialias( aStream->cairoContext, aStream->graphics_anti_aliasing );
02448
02449
02450 if ( pls->dev_eofill )
02451 cairo_set_fill_rule( aStream->cairoContext, CAIRO_FILL_RULE_EVEN_ODD );
02452 else
02453 cairo_set_fill_rule( aStream->cairoContext, CAIRO_FILL_RULE_WINDING );
02454 }
02455
02456
02457
02458
02459
02460
02461
02462 void plD_eop_pngcairo( PLStream *pls )
02463 {
02464 PLCairo *aStream;
02465
02466 aStream = (PLCairo *) pls->dev;
02467 cairo_surface_write_to_png_stream( aStream->cairoSurface, (cairo_write_func_t) write_to_stream, pls->OutFile );
02468 }
02469
02470 #endif
02471
02472
02473
02474
02475
02476
02477
02478
02479
02480
02481 #if defined ( PLD_memcairo )
02482
02483 void plD_dispatch_init_memcairo( PLDispatchTable *pdt );
02484 void plD_init_memcairo( PLStream * );
02485 void plD_eop_memcairo( PLStream * );
02486 void plD_bop_memcairo( PLStream * );
02487
02488
02489
02490
02491
02492
02493
02494
02495 void plD_dispatch_init_memcairo( PLDispatchTable *pdt )
02496 {
02497 #ifndef ENABLE_DYNDRIVERS
02498 pdt->pl_MenuStr = "Cairo memory driver";
02499 pdt->pl_DevName = "memcairo";
02500 #endif
02501 pdt->pl_type = plDevType_FileOriented;
02502 pdt->pl_seq = 105;
02503 pdt->pl_init = (plD_init_fp) plD_init_memcairo;
02504 pdt->pl_line = (plD_line_fp) plD_line_cairo;
02505 pdt->pl_polyline = (plD_polyline_fp) plD_polyline_cairo;
02506 pdt->pl_eop = (plD_eop_fp) plD_eop_memcairo;
02507 pdt->pl_bop = (plD_bop_fp) plD_bop_memcairo;
02508 pdt->pl_tidy = (plD_tidy_fp) plD_tidy_cairo;
02509 pdt->pl_state = (plD_state_fp) plD_state_cairo;
02510 pdt->pl_esc = (plD_esc_fp) plD_esc_cairo;
02511 }
02512
02513
02514
02515
02516
02517
02518
02519 void plD_bop_memcairo( PLStream *pls )
02520 {
02521
02522 }
02523
02524
02525
02526
02527
02528
02529
02530 void plD_init_memcairo( PLStream *pls )
02531 {
02532 PLCairo *aStream;
02533 int stride, i;
02534 unsigned char *cairo_mem;
02535 unsigned char *input_mem;
02536
02537
02538 union
02539 {
02540 int testWord;
02541 char testByte[sizeof ( int )];
02542 } endianTest;
02543 endianTest.testWord = 1;
02544
02545
02546
02547 pls->xlength = pls->phyxma;
02548 pls->ylength = pls->phyyma;
02549
02550
02551
02552 aStream = stream_and_font_setup( pls, 0 );
02553
02554
02555 if ( endianTest.testByte[0] == 1 )
02556 aStream->bigendian = 0;
02557 else
02558 aStream->bigendian = 1;
02559
02560
02561 if ( pls->dev == NULL )
02562 {
02563 plexit( "Must call plsmem first to set user plotting area!" );
02564 }
02565
02566
02567 aStream->memory = pls->dev;
02568
02569
02570
02571
02572
02573
02574
02575 stride = pls->xlength * 4;
02576
02577 aStream->cairo_format_memory = (unsigned char *) calloc( stride * pls->ylength, 1 );
02578
02579
02580 cairo_mem = aStream->cairo_format_memory;
02581 input_mem = aStream->memory;
02582
02583
02584
02585
02586
02587 if ( aStream->bigendian )
02588 {
02589 for ( i = 0; i < ( pls->xlength * pls->ylength ); i++ )
02590 {
02591 cairo_mem[1] = input_mem[0];
02592 cairo_mem[2] = input_mem[1];
02593 cairo_mem[3] = input_mem[2];
02594 if ( pls->dev_mem_alpha == 1 )
02595 {
02596 cairo_mem[0] = input_mem[3];
02597 input_mem += 4;
02598 }
02599 else
02600 {
02601 input_mem += 3;
02602 }
02603 cairo_mem += 4;
02604 }
02605 }
02606 else
02607 {
02608 for ( i = 0; i < ( pls->xlength * pls->ylength ); i++ )
02609 {
02610 cairo_mem[2] = input_mem[0];
02611 cairo_mem[1] = input_mem[1];
02612 cairo_mem[0] = input_mem[2];
02613 if ( pls->dev_mem_alpha == 1 )
02614 {
02615 cairo_mem[3] = input_mem[3];
02616 input_mem += 4;
02617 }
02618 else
02619 {
02620 input_mem += 3;
02621 }
02622 cairo_mem += 4;
02623 }
02624 }
02625
02626
02627 aStream->cairoSurface =
02628
02629
02630 cairo_image_surface_create_for_data( aStream->cairo_format_memory, CAIRO_FORMAT_RGB24, pls->xlength, pls->ylength, stride );
02631 aStream->cairoContext = cairo_create( aStream->cairoSurface );
02632
02633
02634
02635 pls->dev = aStream;
02636
02637
02638 rotate_cairo_surface( pls, 1.0, 0.0, 0.0, -1.0, 0.0, pls->ylength, FALSE );
02639
02640
02641 cairo_set_antialias( aStream->cairoContext, aStream->graphics_anti_aliasing );
02642
02643
02644 if ( pls->dev_eofill )
02645 cairo_set_fill_rule( aStream->cairoContext, CAIRO_FILL_RULE_EVEN_ODD );
02646 else
02647 cairo_set_fill_rule( aStream->cairoContext, CAIRO_FILL_RULE_WINDING );
02648 }
02649
02650
02651
02652
02653
02654
02655
02656
02657 void plD_eop_memcairo( PLStream *pls )
02658 {
02659 int i;
02660 unsigned char *memory;
02661 unsigned char *cairo_surface_data;
02662 PLCairo *aStream;
02663
02664 aStream = (PLCairo *) pls->dev;
02665 memory = aStream->memory;
02666 cairo_surface_data = cairo_image_surface_get_data( aStream->cairoSurface );
02667
02668
02669
02670 if ( aStream->bigendian )
02671 {
02672 for ( i = 0; i < ( pls->xlength * pls->ylength ); i++ )
02673 {
02674 memory[0] = cairo_surface_data[1];
02675 memory[1] = cairo_surface_data[2];
02676 memory[2] = cairo_surface_data[3];
02677 if ( pls->dev_mem_alpha == 1 )
02678 {
02679 memory[3] = cairo_surface_data[0];
02680 memory += 4;
02681 }
02682 else
02683 {
02684 memory += 3;
02685 }
02686 cairo_surface_data += 4;
02687 }
02688 }
02689 else
02690 {
02691 for ( i = 0; i < ( pls->xlength * pls->ylength ); i++ )
02692 {
02693 memory[0] = cairo_surface_data[2];
02694 memory[1] = cairo_surface_data[1];
02695 memory[2] = cairo_surface_data[0];
02696 if ( pls->dev_mem_alpha == 1 )
02697 {
02698 memory[3] = cairo_surface_data[3];
02699 memory += 4;
02700 }
02701 else
02702 {
02703 memory += 3;
02704 }
02705 cairo_surface_data += 4;
02706 }
02707 }
02708
02709
02710 free( aStream->cairo_format_memory );
02711 }
02712
02713 #endif
02714
02715
02716
02717
02718
02719
02720
02721
02722
02723 #if defined ( PLD_extcairo )
02724
02725 void extcairo_setbackground( PLStream * );
02726 void plD_dispatch_init_extcairo( PLDispatchTable *pdt );
02727 void plD_init_extcairo( PLStream * );
02728 void plD_bop_extcairo( PLStream * );
02729 void plD_eop_extcairo( PLStream * );
02730 void plD_esc_extcairo( PLStream *, PLINT, void * );
02731 void plD_tidy_extcairo( PLStream * );
02732
02733
02734
02735
02736
02737
02738
02739 void extcairo_setbackground( PLStream *pls )
02740 {
02741 PLCairo *aStream;
02742
02743 aStream = (PLCairo *) pls->dev;
02744
02745
02746 if ( aStream->cairoContext != NULL )
02747 {
02748 cairo_rectangle( aStream->cairoContext, 0.0, 0.0, pls->xlength, pls->ylength );
02749 cairo_set_source_rgba( aStream->cairoContext,
02750 (double) pls->cmap0[0].r / 255.0,
02751 (double) pls->cmap0[0].g / 255.0,
02752 (double) pls->cmap0[0].b / 255.0,
02753 (double) pls->cmap0[0].a );
02754 cairo_fill( aStream->cairoContext );
02755 }
02756 }
02757
02758
02759
02760
02761
02762
02763
02764
02765 void plD_dispatch_init_extcairo( PLDispatchTable *pdt )
02766 {
02767 #ifndef ENABLE_DYNDRIVERS
02768 pdt->pl_MenuStr = "Cairo external context driver";
02769 pdt->pl_DevName = "extcairo";
02770 #endif
02771 pdt->pl_type = plDevType_Interactive;
02772 pdt->pl_seq = 106;
02773 pdt->pl_init = (plD_init_fp) plD_init_extcairo;
02774 pdt->pl_line = (plD_line_fp) plD_line_cairo;
02775 pdt->pl_polyline = (plD_polyline_fp) plD_polyline_cairo;
02776 pdt->pl_bop = (plD_bop_fp) plD_bop_extcairo;
02777 pdt->pl_eop = (plD_eop_fp) plD_eop_extcairo;
02778 pdt->pl_tidy = (plD_tidy_fp) plD_tidy_extcairo;
02779 pdt->pl_state = (plD_state_fp) plD_state_cairo;
02780 pdt->pl_esc = (plD_esc_fp) plD_esc_extcairo;
02781 }
02782
02783
02784
02785
02786
02787
02788
02789 void plD_init_extcairo( PLStream *pls )
02790 {
02791 PLCairo *aStream;
02792
02793
02794 aStream = stream_and_font_setup( pls, 0 );
02795
02796
02797 pls->dev = aStream;
02798 }
02799
02800
02801
02802
02803
02804
02805
02806 void plD_bop_extcairo( PLStream *pls )
02807 {
02808 PLCairo *aStream;
02809
02810 aStream = (PLCairo *) pls->dev;
02811
02812
02813 if ( aStream->set_background )
02814 {
02815 extcairo_setbackground( pls );
02816 }
02817 }
02818
02819
02820
02821
02822
02823
02824
02825 void plD_eop_extcairo( PLStream *pls )
02826 {
02827
02828
02829 }
02830
02831
02832
02833
02834
02835
02836
02837
02838 void plD_esc_extcairo( PLStream *pls, PLINT op, void *ptr )
02839 {
02840 PLCairo *aStream;
02841
02842 aStream = (PLCairo *) pls->dev;
02843
02844 switch ( op )
02845 {
02846 case PLESC_DEVINIT:
02847 aStream->cairoContext = (cairo_t *) ptr;
02848
02849 cairo_set_antialias( aStream->cairoContext, aStream->graphics_anti_aliasing );
02850
02851
02852 rotate_cairo_surface( pls, 1.0, 0.0, 0.0, -1.0, 0.0, pls->ylength, FALSE );
02853
02854
02855
02856
02857
02858 if ( aStream->set_background )
02859 {
02860 extcairo_setbackground( pls );
02861 }
02862
02863
02864 if ( pls->dev_eofill )
02865 cairo_set_fill_rule( aStream->cairoContext, CAIRO_FILL_RULE_EVEN_ODD );
02866 else
02867 cairo_set_fill_rule( aStream->cairoContext, CAIRO_FILL_RULE_WINDING );
02868 break;
02869 default:
02870 plD_esc_cairo( pls, op, ptr );
02871 break;
02872 }
02873 }
02874
02875
02876
02877
02878
02879
02880
02881
02882 void plD_tidy_extcairo( PLStream *pls )
02883 {
02884 }
02885
02886 #endif
02887
02888
02889
02890
02891
02892
02893
02894
02895
02896
02897
02898
02899
02900 #if defined ( PLD_wincairo )
02901
02902 static char* szWndClass = "PLplot WinCairo";
02903
02904 void plD_dispatch_init_wincairo( PLDispatchTable *pdt );
02905 void plD_init_wincairo( PLStream * );
02906
02907 void plD_eop_wincairo( PLStream * );
02908 void plD_esc_wincairo( PLStream *, PLINT, void * );
02909 void plD_tidy_wincairo( PLStream * );
02910
02911
02912
02913
02914
02915
02916
02917 void blit_to_win( PLCairo *aStream )
02918 {
02919 cairo_set_source_surface( aStream->cairoContext_win, aStream->cairoSurface, 0.0, 0.0 );
02920 cairo_paint( aStream->cairoContext_win );
02921 }
02922
02923
02924
02925
02926
02927
02928
02929 LRESULT CALLBACK PlplotCairoWndProc( HWND hwnd, UINT nMsg, WPARAM wParam, LPARAM lParam )
02930 {
02931 PLStream *pls = NULL;
02932 PLCairo *dev = NULL;
02933
02934
02935
02936
02937
02938
02939
02940
02941
02942
02943
02944 if ( nMsg == WM_CREATE )
02945 {
02946 return ( 0 );
02947 }
02948 else
02949 {
02950 pls = (PLStream *) GetWindowLong( hwnd, GWL_USERDATA );
02951 if ( pls )
02952 {
02953 dev = (PLCairo *) pls->dev;
02954 }
02955 }
02956
02957
02958
02959
02960
02961
02962
02963
02964
02965
02966
02967 switch ( nMsg )
02968 {
02969 case WM_DESTROY:
02970
02971
02972 PostQuitMessage( 0 );
02973 return ( 0 );
02974 break;
02975
02976 case WM_PAINT:
02977 blit_to_win( dev );
02978 return ( 1 );
02979 break;
02980
02981 case WM_SIZE:
02982 GetClientRect( dev->hwnd, &dev->rect );
02983 return ( 0 );
02984 break;
02985
02986 case WM_ENTERSIZEMOVE:
02987 return ( 0 );
02988 break;
02989
02990 case WM_EXITSIZEMOVE:
02991 return ( 0 );
02992 break;
02993
02994 case WM_ERASEBKGND:
02995 if ( dev )
02996 {
02997 dev->oldcolour = SetBkColor( dev->hdc, RGB( pls->cmap0[0].r, pls->cmap0[0].g, pls->cmap0[0].b ) );
02998 ExtTextOut( dev->hdc, 0, 0, ETO_OPAQUE, &dev->rect, "", 0, 0 );
02999 SetBkColor( dev->hdc, dev->oldcolour );
03000 }
03001 return ( 1 );
03002 break;
03003
03004 case WM_COMMAND:
03005 return ( 0 );
03006 break;
03007 }
03008
03009
03010
03011 return DefWindowProc( hwnd, nMsg, wParam, lParam );
03012 }
03013
03014
03015
03016
03017
03018
03019
03020 void
03021 handle_locate( PLStream *pls, PLGraphicsIn *gin )
03022 {
03023 int located = 0;
03024 PLCairo *aStream = (PLCairo *) pls->dev;
03025
03026
03027 plGinInit( gin );
03028
03029 while ( GetMessage( &aStream->msg, NULL, 0, 0 ) && !located )
03030 {
03031 TranslateMessage( &aStream->msg );
03032
03033 switch ( (int) aStream->msg.message )
03034 {
03035 case WM_MOUSEMOVE:
03036 case WM_LBUTTONDOWN:
03037 gin->state = 1;
03038 gin->button = 1;
03039 gin->pX = LOWORD( aStream->msg.lParam );
03040 gin->pY = pls->ylength - HIWORD( aStream->msg.lParam );
03041 gin->dX = (PLFLT) LOWORD( aStream->msg.lParam ) / ( (PLFLT) pls->xlength );
03042 gin->dY = (PLFLT) ( pls->ylength - HIWORD( aStream->msg.lParam ) ) / ( (PLFLT) pls->ylength );
03043 break;
03044 case WM_CHAR:
03045 gin->keysym = aStream->msg.wParam;
03046 located = 1;
03047 break;
03048
03049 default:
03050 DispatchMessage( &aStream->msg );
03051 break;
03052 }
03053 }
03054 }
03055
03056
03057
03058
03059
03060
03061
03062
03063 void plD_dispatch_init_wincairo( PLDispatchTable *pdt )
03064 {
03065 #ifndef ENABLE_DYNDRIVERS
03066 pdt->pl_MenuStr = "Cairo Microsoft Windows driver";
03067 pdt->pl_DevName = "wincairo";
03068 #endif
03069 pdt->pl_type = plDevType_Interactive;
03070 pdt->pl_seq = 107;
03071 pdt->pl_init = (plD_init_fp) plD_init_wincairo;
03072 pdt->pl_line = (plD_line_fp) plD_line_cairo;
03073 pdt->pl_polyline = (plD_polyline_fp) plD_polyline_cairo;
03074 pdt->pl_bop = (plD_bop_fp) plD_bop_cairo;
03075 pdt->pl_eop = (plD_eop_fp) plD_eop_wincairo;
03076 pdt->pl_tidy = (plD_tidy_fp) plD_tidy_wincairo;
03077 pdt->pl_state = (plD_state_fp) plD_state_cairo;
03078 pdt->pl_esc = (plD_esc_fp) plD_esc_wincairo;
03079 }
03080
03081
03082
03083
03084
03085
03086
03087 void plD_init_wincairo( PLStream *pls )
03088 {
03089 PLCairo *aStream;
03090
03091
03092 aStream = stream_and_font_setup( pls, 1 );
03093
03094
03095 pls->dev = aStream;
03096
03097
03098 memset( &aStream->wndclass, 0, sizeof ( WNDCLASSEX ) );
03099
03100
03101 aStream->wndclass.lpszClassName = szWndClass;
03102
03103
03104 aStream->wndclass.cbSize = sizeof ( WNDCLASSEX );
03105
03106
03107 aStream->wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS | CS_OWNDC | CS_PARENTDC;
03108
03109
03110 aStream->wndclass.lpfnWndProc = PlplotCairoWndProc;
03111
03112
03113
03114 aStream->wndclass.hInstance = GetModuleHandle( NULL );
03115
03116
03117 aStream->wndclass.hIcon = LoadIcon( NULL, IDI_APPLICATION );
03118 aStream->wndclass.hIconSm = LoadIcon( NULL, IDI_APPLICATION );
03119 aStream->wndclass.hCursor = LoadCursor( NULL, IDC_ARROW );
03120
03121 aStream->wndclass.hbrBackground = NULL;
03122
03123 aStream->wndclass.cbWndExtra = sizeof ( pls );
03124
03125
03126
03127
03128
03129
03130 RegisterClassEx( &aStream->wndclass );
03131
03132
03133
03134
03135 aStream->hwnd = CreateWindowEx( WS_EX_WINDOWEDGE + WS_EX_LEFT,
03136 szWndClass,
03137 pls->program,
03138 WS_OVERLAPPEDWINDOW,
03139 pls->xoffset,
03140 pls->yoffset,
03141
03142 pls->xlength + 5,
03143 pls->ylength + 30,
03144 NULL,
03145 NULL,
03146 aStream->wndclass.hInstance,
03147 NULL
03148 );
03149
03150
03151
03152
03153
03154
03155
03156
03157 SetWindowLong( aStream->hwnd, GWL_USERDATA, (long) pls );
03158 aStream->SCRN_hdc = aStream->hdc = GetDC( aStream->hwnd );
03159
03160
03161
03162
03163
03164
03165
03166
03167
03168
03169
03170
03171
03172
03173
03174
03175
03176
03177 ShowWindow( aStream->hwnd, SW_SHOWDEFAULT );
03178 SetForegroundWindow( aStream->hwnd );
03179
03180
03181
03182
03183
03184
03185
03186
03187
03188
03189
03190
03191
03192
03193
03194
03195
03196
03197
03198 aStream->cairoSurface_win = (cairo_surface_t *) cairo_win32_surface_create( aStream->hdc );
03199 aStream->cairoContext_win = cairo_create( aStream->cairoSurface_win );
03200
03201
03202 aStream->cairoSurface = cairo_image_surface_create( CAIRO_FORMAT_RGB24, pls->xlength, pls->ylength );
03203 aStream->cairoContext = cairo_create( aStream->cairoSurface );
03204
03205
03206 rotate_cairo_surface( pls, 1.0, 0.0, 0.0, -1.0, 0.0, pls->ylength, FALSE );
03207
03208
03209 cairo_set_antialias( aStream->cairoContext, aStream->graphics_anti_aliasing );
03210
03211
03212 if ( pls->dev_eofill )
03213 cairo_set_fill_rule( aStream->cairoContext, CAIRO_FILL_RULE_EVEN_ODD );
03214 else
03215 cairo_set_fill_rule( aStream->cairoContext, CAIRO_FILL_RULE_WINDING );
03216 }
03217
03218
03219
03220
03221
03222
03223
03224 void
03225 plD_eop_wincairo( PLStream *pls )
03226 {
03227 PLCairo *aStream = (PLCairo *) pls->dev;
03228
03229 if ( !pls->nopause )
03230 {
03231 while ( GetMessage( &aStream->msg, NULL, 0, 0 ) )
03232 {
03233 TranslateMessage( &aStream->msg );
03234 switch ( (int) aStream->msg.message )
03235 {
03236 case WM_CHAR:
03237 if ( ( (TCHAR) ( aStream->msg.wParam ) == 13 ) ||
03238 ( (TCHAR) ( aStream->msg.wParam ) == 'q' ) ||
03239 ( (TCHAR) ( aStream->msg.wParam ) == 'Q' ) )
03240 {
03241 PostQuitMessage( 0 );
03242 }
03243 break;
03244
03245 default:
03246 DispatchMessage( &aStream->msg );
03247 break;
03248 }
03249 }
03250 }
03251 }
03252
03253
03254
03255
03256
03257
03258
03259 void plD_tidy_wincairo( PLStream *pls )
03260 {
03261 PLCairo *aStream = (PLCairo *) pls->dev;
03262
03263 plD_tidy_cairo( pls );
03264
03265
03266 cairo_destroy( aStream->cairoContext_win );
03267 cairo_surface_destroy( aStream->cairoSurface_win );
03268
03269 if ( aStream != NULL )
03270 {
03271 if ( aStream->hdc != NULL )
03272 ReleaseDC( aStream->hwnd, aStream->hdc );
03273 free_mem( pls->dev );
03274 }
03275 }
03276
03277
03278
03279
03280
03281
03282
03283 void plD_esc_wincairo( PLStream *pls, PLINT op, void *ptr )
03284 {
03285 PLCairo *aStream;
03286
03287 aStream = (PLCairo *) pls->dev;
03288
03289 switch ( op )
03290 {
03291 case PLESC_FLUSH:
03292 InvalidateRect( aStream->hwnd, NULL, TRUE );
03293 break;
03294 case PLESC_GETC:
03295 handle_locate( pls, (PLGraphicsIn *) ptr );
03296 break;
03297 default:
03298 plD_esc_cairo( pls, op, ptr );
03299 break;
03300 }
03301 }
03302
03303 #endif