The R Project SVN R

Rev

Rev 41909 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
29921 ripley 1
/*
2
 *  R : A Computer Language for Statistical Data Analysis
41909 ripley 3
 *  Copyright (C) 2001-7 The R Development Core Team.
29921 ripley 4
 *
5
 *  This program is free software; you can redistribute it and/or modify
6
 *  it under the terms of the GNU Lesser General Public License as published by
7
 *  the Free Software Foundation; either version 2.1 of the License, or
8
 *  (at your option) any later version.
9
 *
10
 *  This program is distributed in the hope that it will be useful,
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 *  GNU Lesser General Public License for more details.
14
 *
15
 *  You should have received a copy of the GNU Lesser General Public License
16
 *  along with this program; if not, write to the Free Software
36820 ripley 17
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
29921 ripley 18
 */
17204 hornik 19
 
29921 ripley 20
/* Used by third-party graphics devices */
21
 
34747 ripley 22
#ifndef R_GRAPHICSDEVICE_H_
23
#define R_GRAPHICSDEVICE_H_
24
 
25
#ifdef __cplusplus
26
extern "C" {
27
#endif
28
 
17204 hornik 29
/* New device driver structure
30
 * NOTES:
31
 * 1. All locations and dimensions are in device coordinates.
32
 * 2. I found this comment in the doc for dev_Open -- looks nasty
33
 *    Any known instances of such a thing happening?  Should be
34
 *    replaced by a function to query the device for preferred gpars
35
 *    settings? (to be called when the device is initialised)
36
         *
37
         * NOTE that it is perfectly acceptable for this	
38
         * function to set generic graphics parameters too	
39
         * (i.e., override the generic parameter settings	
40
         * which GInit sets up) all at the author's own risk	
41
         * of course :)						
42
	 *
43
 * 3. Do we really need dev_StrWidth as well as dev_MetricInfo?
44
 *    I can see the difference between the two -- its just a 
45
 *    question of whether dev_MetricInfo should just return
46
 *    what dev_StrWidth would give if font metric information is
47
 *    not available.  I guess having both allows the developer
48
 *    to decide when to ask for which sort of value, and to decide
49
 *    what to do when font metric information is not available.
50
 *    And why not a dev_StrHeight?
27236 murrell 51
 * 4. Should "ipr", "asp", and "cra" be in the device description?
17204 hornik 52
 *    If not, then where?
53
 *    I guess they don't need to be if no device makes use of them.
54
 *    On the other hand, they would need to be replaced by a device
55
 *    call that R base graphics could use to get enough information
56
 *    to figure them out.  (e.g., some sort of dpi() function to
57
 *    complement the size() function.)
58
 */
27236 murrell 59
 
17204 hornik 60
typedef struct {
61
    /* The first element is a boolean indicating whether this is 
62
     * a new device driver (always 1) -- the old device driver structure
63
     * has had a similar element added (which will always be 0)
19874 murrell 64
     *
65
     * This needs to be removed once the old DevDesc structure has been
66
     * removed from the system.
17204 hornik 67
     */
68
    int newDevStruct; 
69
    /********************************************************
19874 murrell 70
     * Device physical characteristics
17204 hornik 71
     ********************************************************/
72
    double left;	        /* left raster coordinate */
73
    double right;	        /* right raster coordinate */
74
    double bottom;	        /* bottom raster coordinate */
75
    double top;		        /* top raster coordinate */
19874 murrell 76
    /* R only has the notion of a rectangular clipping region
77
     */
17204 hornik 78
    double clipLeft;
79
    double clipRight;
80
    double clipBottom;
81
    double clipTop;
19874 murrell 82
    /* I hate these next three -- they seem like a real fudge
83
     * BUT I'm not sure what to replace them with so they stay for now.
84
     */
17204 hornik 85
    double xCharOffset;	        /* x character addressing offset */
86
    double yCharOffset;	        /* y character addressing offset */
87
    double yLineBias;	        /* 1/2 interline space as frac of line hght */
19874 murrell 88
    double ipr[2];	        /* Inches per raster; [0]=x, [1]=y */
89
    double asp;		        /* Pixel aspect ratio = ipr[1]/ipr[0] */
90
    /* I hate this guy too -- seems to assume that a device can only
91
     * have one font size during its lifetime
92
     * BUT removing/replacing it would take quite a lot of work
93
     * to design and insert a good replacement so it stays for now.
94
     */
95
    double cra[2];	        /* Character size in rasters; [0]=x, [1]=y */
96
    double gamma;	        /* Device Gamma Correction */
97
    /********************************************************
98
     * Device capabilities
99
     ********************************************************/
17204 hornik 100
    Rboolean canResizePlot;	/* can the graphics surface be resized */
101
    Rboolean canChangeFont;	/* device has multiple fonts */
102
    Rboolean canRotateText;	/* text can be rotated */
103
    Rboolean canResizeText;	/* text can be resized */
104
    Rboolean canClip;		/* Hardware clipping */
105
    Rboolean canChangeGamma;    /* can the gamma factor be modified */
106
    int canHAdj;	        /* Can do at least some horiz adjust of text
107
 
19874 murrell 108
    /********************************************************
109
     * Device initial settings
110
     ********************************************************/
111
    /* These are things that the device must set up when it is created.
112
     * The graphics system can modify them and track current values,
113
     * but some devices want to know what the original setting was.
114
     */
17204 hornik 115
    double startps;             
116
    int startcol;
117
    int startfill;
118
    int startlty;
119
    int startfont;
120
    double startgamma;
19874 murrell 121
    /********************************************************
122
     * Device specific information
123
     ********************************************************/
17204 hornik 124
    void *deviceSpecific;	/* pointer to device specific parameters */
19874 murrell 125
    /********************************************************
126
     * Device display list
127
     ********************************************************/
128
    /* I think it would feel nicer if this stuff was part of the 
129
     * graphics engine (GEDevDesc), but this is another thing that
130
     * needs more time to implement a change properly.
131
     */
17204 hornik 132
    Rboolean displayListOn;     /* toggle for display list status */
133
    SEXP displayList;           /* display list */
31643 murrell 134
    SEXP DLlastElt;
18917 murrell 135
    SEXP savedSnapshot;         /* The last value of the display list
136
				 * just prior to when the display list
137
				 * was last initialised
138
				 */
32151 murdoch 139
 
140
    /********************************************************				 
141
     * Event handling entries
142
     ********************************************************/
143
 
144
    /* These determine whether getGraphicsEvent will try to set an event handler */
145
 
146
    Rboolean canGenMouseDown; /* can the device generate mousedown events */
147
    Rboolean canGenMouseMove; /* can the device generate mousemove events */
148
    Rboolean canGenMouseUp;   /* can the device generate mouseup events */
149
    Rboolean canGenKeybd;     /* can the device generate keyboard events */
150
 
151
    Rboolean gettingEvent;    /* This is set while getGraphicsEvent is actively looking for events */
152
 
17204 hornik 153
    /********************************************************
154
     * Device procedures.
155
     ********************************************************/
27236 murrell 156
 
17204 hornik 157
    /*
27236 murrell 158
     * ---------------------------------------
159
     * GENERAL COMMENT ON GRAPHICS PARAMETERS:
160
     * ---------------------------------------
161
     * Graphical parameters are now passed in a graphics context
162
     * structure (R_GE_gcontext*) rather than individually.
163
     * Each device action should extract the parameters it needs
164
     * and ignore the others.  Thought should be given to which 
165
     * parameters are relevant in each case -- the graphics engine
166
     * does not REQUIRE that each parameter is honoured, but if
167
     * a parameter is NOT honoured, it might be a good idea to
168
     * issue a warning when a parameter is not honoured (or at
169
     * the very least document which parameters are not honoured
170
     * in the user-level documentation for the device).  [An example
171
     * of a parameter that may not be honoured by many devices is
172
     * transparency.]
173
     */
174
 
175
    /*
17204 hornik 176
     * device_Activate is called when a device becomes the	
177
     * active device.  For example, it can be used to change the
178
     * title of a window to indicate the active status of	
179
     * the device to the user.  Not all device types will	
180
     * do anything.			
181
     * The only parameter is a device driver structure.
182
     * An example is ...
183
     *
184
     * static void   X11_Activate(NewDevDesc *dd);
185
     *
186
     */
187
    void (*activate)();
188
    /*
189
     * device_Circle should have the side-effect that a	
190
     * circle is drawn, centred at the given location, with 
191
     * the given radius.  The border of the circle should be
192
     * drawn in the given "col", and the circle should be	
193
     * filled with the given "fill" colour.		
194
     * If "col" is NA_INTEGER then no border should be drawn
195
     * If "fill" is NA_INTEGER then the circle should not 
196
     * be filled.
197
     * An example is ...
198
     *
199
     * static void X11_Circle(double x, double y, double r,
27236 murrell 200
     *                        R_GE_gcontext *gc,
17204 hornik 201
     *                        NewDevDesc *dd);
202
     *
27236 murrell 203
     * R_GE_gcontext parameters that should be honoured (if possible):
204
     *   col, fill, gamma, lty, lwd
17204 hornik 205
     */
206
    void (*circle)();
207
    /*
208
     * device_Clip is given the left, right, bottom, and	
209
     * top of a rectangle (in DEVICE coordinates).	
210
     * It should have the side-effect that subsequent output	
211
     * is clipped to the given rectangle.
212
     * NOTE that R's graphics engine already clips to the 
213
     * extent of the device.
214
     * NOTE also that this will probably only be called if
215
     * the flag canClip is true.
216
     * An example is ...
217
     *
218
     * static void X11_Clip(double x0, double x1, double y0, double y1, 
219
     *                      NewDevDesc *dd)
220
     */
221
    void (*clip)();
222
    /*
223
     * device_Close is called when the device is killed.
224
     * This function is responsible for destroying any	
225
     * device-specific resources that were created in	
226
     * device_Open and for FREEing the device-specific	
227
     * parameters structure.	
228
     * An example is ...
229
     *
230
     * static void X11_Close(NewDevDesc *dd)
231
     *
232
     */
233
    void (*close)();
234
    /*
235
     * device_Deactivate is called when a device becomes	
236
     * inactive.  
237
     * This allows the device to undo anything it did in 
238
     * dev_Activate.
239
     * Not all device types will do anything.
240
     * An example is ...
241
     *
242
     * static void X11_Deactivate(NewDevDesc *dd)
243
     *
244
     */
245
    void (*deactivate)();
246
    void (*dot)();
247
    /*
248
     * I don't know what this is for and i can't find it	
249
     * being used anywhere, but i'm loath to kill it in	
250
     * case i'm missing something important			
251
     * An example is ...
252
     *
253
     * static void X11_Hold(NewDevDesc *dd)
254
     *
255
     */
256
    void (*hold)();
257
    /*
258
     * device_Locator should return the location of the next
259
     * mouse click (in DEVICE coordinates)	
260
     * Not all devices will do anything (e.g., postscript)	
261
     * An example is ...
262
     *
263
     * static Rboolean X11_Locator(double *x, double *y, NewDevDesc *dd)
264
     *
265
     */
266
    Rboolean (*locator)();
267
    /*
268
     * device_Line should have the side-effect that a single
269
     * line is drawn (from x1,y1 to x2,y2)			
270
     * An example is ...
271
     *
272
     * static void X11_Line(double x1, double y1, double x2, double y2,
27236 murrell 273
     *                      R_GE_gcontext *gc,
17204 hornik 274
     *                      NewDevDesc *dd);
275
     *
27236 murrell 276
     * R_GE_gcontext parameters that should be honoured (if possible):
277
     *   col, gamma, lty, lwd
17204 hornik 278
     */
279
    void (*line)();
280
    /*
281
     * device_MetricInfo should return height, depth, and	
282
     * width information for the given character in DEVICE	
283
     * units.
284
     * This is used for formatting mathematical expressions	
285
     * and for exact centering of text (see GText)		
286
     * If the device cannot provide metric information then 
287
     * it MUST return 0.0 for ascent, descent, and width.
288
     * An example is ...
289
     *
27236 murrell 290
     * static void X11_MetricInfo(int c,
291
     *                            R_GE_gcontext *gc,
17204 hornik 292
     *                            double* ascent, double* descent,
293
     *                            double* width, NewDevDesc *dd);
27236 murrell 294
     *
295
     * R_GE_gcontext parameters that should be honoured (if possible):
296
     *   font, cex, ps
17204 hornik 297
     */
298
    void (*metricInfo)();
299
    /*
300
     * device_Mode is called whenever the graphics engine	
301
     * starts drawing (mode=1) or stops drawing (mode=0)	
302
     * The device is not required to do anything		
303
     * An example is ...
304
     *
305
     * static void X11_Mode(int mode, NewDevDesc *dd);
306
     *
307
     */
308
    void (*mode)();
309
    /*
310
     * device_NewPage is called whenever a new plot requires
311
     * a new page.	
312
     * A new page might mean just clearing the	
313
     * device (e.g., X11) or moving to a new page	
314
     * (e.g., postscript)					
315
     * An example is ...
316
     *
317
     *
27236 murrell 318
     * static void X11_NewPage(R_GE_gcontext *gc,
319
     *                         NewDevDesc *dd);
17204 hornik 320
     *
321
     */
322
    void (*newPage)();
323
    /*
324
     * device_Open is not usually called directly by the	
325
     * graphics engine;  it is usually only called from	
326
     * the device-driver entry point.			
327
     * This function should set up all of the device-	
328
     * specific resources for a new device			
329
     * This function is given a newly-allocated NewDevDesc structure 
330
     * and it must FREE the structure if anything goes seriously wrong.
331
     * NOTE that different devices will accept different parameter
332
     * lists, corresponding to different device-specific preferences.
333
     * An example is ...
334
     *
41851 ripley 335
     * Rboolean X11_Open(NewDevDesc *dd, const char *dsp, double w, double h, 
17204 hornik 336
     *                   double gamma_fac, X_COLORTYPE colormodel, 
337
     *                   int maxcube, int canvascolor);
338
     *
339
     */
340
    Rboolean (*open)();
341
    /*
342
     * device_Polygon should have the side-effect that a	
343
     * polygon is drawn using the given x and y values	
344
     * the polygon border should be drawn in the "col"	
345
     * colour and filled with the "fill" colour.
346
     * If "col" is NA_INTEGER don't draw the border		
347
     * If "fill" is NA_INTEGER don't fill the polygon		
348
     * An example is ...
349
     *
350
     * static void X11_Polygon(int n, double *x, double *y, 
27236 murrell 351
     *                         R_GE_gcontext *gc,
17204 hornik 352
     *                         NewDevDesc *dd);
353
     *
27236 murrell 354
     * R_GE_gcontext parameters that should be honoured (if possible):
355
     *   col, fill, gamma, lty, lwd
17204 hornik 356
     */
357
    void (*polygon)();
358
    /*
359
     * device_Polyline should have the side-effect that a	
360
     * series of line segments are drawn using the given x	
361
     * and y values.
362
     * An example is ...
363
     *
364
     * static void X11_Polyline(int n, double *x, double *y, 
27236 murrell 365
     *                          R_GE_gcontext *gc,
17204 hornik 366
     *                          NewDevDesc *dd);
367
     *
27236 murrell 368
     * R_GE_gcontext parameters that should be honoured (if possible):
369
     *   col, gamma, lty, lwd
17204 hornik 370
     */
371
    void (*polyline)();
372
    /*
373
     * device_Rect should have the side-effect that a	
374
     * rectangle is drawn with the given locations for its	
375
     * opposite corners.  The border of the rectangle	
376
     * should be in the given "col" colour and the rectangle	
377
     * should be filled with the given "fill" colour.
378
     * If "col" is NA_INTEGER then no border should be drawn 
379
     * If "fill" is NA_INTEGER then the rectangle should not	
380
     * be filled.						
381
     * An example is ...
382
     *
383
     * static void X11_Rect(double x0, double y0, double x1, double y1,
27236 murrell 384
     *                      R_GE_gcontext *gc,
17204 hornik 385
     *                      NewDevDesc *dd);
386
     *
387
     */
388
    void (*rect)();
389
    /*
390
     * device_Size is called whenever the device is	
391
     * resized.  
392
     * The function returns (left, right, bottom, and top) for the	
393
     * new device size.					
394
     * This is not usually called directly by the graphics	
395
     * engine because the detection of device resizes	
396
     * (e.g., a window resize) are usually detected by	
397
     * device-specific code.
398
     * An example is ...
399
     *
400
     * static void X11_Size(double *left, double *right,
401
     *                      double *bottom, double *top,
402
     *                      NewDevDesc *dd);
403
     *
27236 murrell 404
     * R_GE_gcontext parameters that should be honoured (if possible):
405
     *   col, fill, gamma, lty, lwd
17204 hornik 406
     */
407
    void (*size)();
408
    /*
409
     * device_StrWidth should return the width of the given 
410
     * string in DEVICE units.				
411
     * An example is ...
412
     *
41851 ripley 413
     * static double X11_StrWidth(const char *str, 
27236 murrell 414
     *                            R_GE_gcontext *gc,
17204 hornik 415
     *                            NewDevDesc *dd)
416
     *
27236 murrell 417
     * R_GE_gcontext parameters that should be honoured (if possible):
418
     *   font, cex, ps
17204 hornik 419
     */
420
    double (*strWidth)();
421
    /*
422
     * device_Text should have the side-effect that the	
423
     * given text is drawn at the given location.
424
     * The text should be rotated according to rot (degrees)
425
     * An example is ...
426
     *
41851 ripley 427
     * static void X11_Text(double x, double y, const char *str, 
17204 hornik 428
     *                      double rot, double hadj, 
27236 murrell 429
     *                      R_GE_gcontext *gc,
17204 hornik 430
     * 	                    NewDevDesc *dd);
431
     *
27236 murrell 432
     * R_GE_gcontext parameters that should be honoured (if possible):
433
     *   font, cex, ps, col, gamma
17204 hornik 434
     */
435
    void (*text)();
32133 murdoch 436
    /*
437
     * device_onExit is called by GEonExit when the user has aborted
438
     * some operation, and so an R_ProcessEvents call may not return normally.
439
     * It need not be set to any value; if null, it will not be called.
440
     * 
441
     * An example is ...
442
     *
443
     * static void X11_onExit(NewDevDesc *dd);
444
    */    
445
    void (*onExit)();
32151 murdoch 446
    /*
447
     * device_getEvent is called by do_getGraphicsEvent to get a modal
448
     * graphics event.  It should call R_ProcessEvents() until one
449
     * of the event handlers sets eventResult to a non-null value,
450
     * and then return it
451
     * An example is ...
452
     *
41851 ripley 453
     * static SEXP GA_getEvent(SEXP eventRho, const char *prompt);
32151 murdoch 454
     */
455
    SEXP (*getEvent)();
456
 
17204 hornik 457
} NewDevDesc;
458
 
459
	/********************************************************/
460
	/* the device-driver entry point is given a device	*/
461
	/* description structure that it must set up.  this	*/
462
	/* involves several important jobs ...			*/
463
	/* (1) it must ALLOCATE a new device-specific parameters*/
464
	/* structure and FREE that structure if anything goes	*/
465
	/* wrong (i.e., it won't report a successful setup to	*/
466
	/* the graphics engine (the graphics engine is NOT	*/
467
	/* responsible for allocating or freeing device-specific*/
468
	/* resources or parameters)				*/
469
	/* (2) it must initialise the device-specific resources */
470
	/* and parameters (mostly done by calling device_Open)	*/
471
	/* (3) it must initialise the generic graphical		*/
472
	/* parameters that are not initialised by GInit (because*/
473
	/* only the device knows what values they should have)	*/
474
	/* see Graphics.h for the official list of these	*/
475
	/* (4) it may reset generic graphics parameters that	*/
476
	/* have already been initialised by GInit (although you	*/
477
	/* should know what you are doing if you do this)	*/
478
	/* (5) it must attach the device-specific parameters	*/
479
	/* structure to the device description structure	*/
480
	/* e.g., dd->deviceSpecfic = (void *) xd;		*/
481
	/* (6) it must FREE the overall device description if	*/
482
	/* it wants to bail out to the top-level		*/
483
	/* the graphics engine is responsible for allocating	*/
484
	/* the device description and freeing it in most cases	*/
485
	/* but if the device driver freaks out it needs to do	*/
486
	/* the clean-up itself					*/
487
	/********************************************************/
488
 
34747 ripley 489
 
41909 ripley 490
/* Graphics events */
491
 
492
/* These give the indices of some known keys */    
493
 
494
typedef enum {knUNKNOWN = -1,
495
              knLEFT = 0, knUP, knRIGHT, knDOWN,
496
              knF1, knF2, knF3, knF4, knF5, knF6, knF7, knF8, knF9, knF10,
497
              knF11, knF12,
498
              knPGUP, knPGDN, knEND, knHOME, knINS, knDEL} R_KeyName;
499
 
500
/* These are the three possible mouse events */
501
 
502
typedef enum {meMouseDown = 0,
503
	      meMouseUp,
504
	      meMouseMove} R_MouseEvent;
505
 
506
#define leftButton   1
507
#define middleButton 2
508
#define rightButton  4
509
 
510
#define doKeybd			Rf_doKeybd
511
#define doMouseEvent		Rf_doMouseEvent
512
 
513
SEXP doMouseEvent(SEXP eventRho, NewDevDesc *dd, R_MouseEvent event, 
514
                  int buttons, double x, double y);
515
SEXP doKeybd(SEXP eventRho, NewDevDesc *dd, R_KeyName rkey, 
516
	     const char *keyname);
517
 
518
 
34747 ripley 519
#ifdef __cplusplus
520
}
521
#endif
522
 
523
#endif /* R_GRAPHICSDEVICE_ */