/* * R : A Computer Language for Statistical Data Analysis * Copyright (C) 2001-5 The R Development Core Team. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /* Used by third-party graphics devices */ #ifndef R_GRAPHICSDEVICE_H_ #define R_GRAPHICSDEVICE_H_ #ifdef __cplusplus extern "C" { #endif /* New device driver structure * NOTES: * 1. All locations and dimensions are in device coordinates. * 2. I found this comment in the doc for dev_Open -- looks nasty * Any known instances of such a thing happening? Should be * replaced by a function to query the device for preferred gpars * settings? (to be called when the device is initialised) * * NOTE that it is perfectly acceptable for this * function to set generic graphics parameters too * (i.e., override the generic parameter settings * which GInit sets up) all at the author's own risk * of course :) * * 3. Do we really need dev_StrWidth as well as dev_MetricInfo? * I can see the difference between the two -- its just a * question of whether dev_MetricInfo should just return * what dev_StrWidth would give if font metric information is * not available. I guess having both allows the developer * to decide when to ask for which sort of value, and to decide * what to do when font metric information is not available. * And why not a dev_StrHeight? * 4. Should "ipr", "asp", and "cra" be in the device description? * If not, then where? * I guess they don't need to be if no device makes use of them. * On the other hand, they would need to be replaced by a device * call that R base graphics could use to get enough information * to figure them out. (e.g., some sort of dpi() function to * complement the size() function.) */ typedef struct { /* The first element is a boolean indicating whether this is * a new device driver (always 1) -- the old device driver structure * has had a similar element added (which will always be 0) * * This needs to be removed once the old DevDesc structure has been * removed from the system. */ int newDevStruct; /******************************************************** * Device physical characteristics ********************************************************/ double left; /* left raster coordinate */ double right; /* right raster coordinate */ double bottom; /* bottom raster coordinate */ double top; /* top raster coordinate */ /* R only has the notion of a rectangular clipping region */ double clipLeft; double clipRight; double clipBottom; double clipTop; /* I hate these next three -- they seem like a real fudge * BUT I'm not sure what to replace them with so they stay for now. */ double xCharOffset; /* x character addressing offset */ double yCharOffset; /* y character addressing offset */ double yLineBias; /* 1/2 interline space as frac of line hght */ double ipr[2]; /* Inches per raster; [0]=x, [1]=y */ double asp; /* Pixel aspect ratio = ipr[1]/ipr[0] */ /* I hate this guy too -- seems to assume that a device can only * have one font size during its lifetime * BUT removing/replacing it would take quite a lot of work * to design and insert a good replacement so it stays for now. */ double cra[2]; /* Character size in rasters; [0]=x, [1]=y */ double gamma; /* Device Gamma Correction */ /******************************************************** * Device capabilities ********************************************************/ Rboolean canResizePlot; /* can the graphics surface be resized */ Rboolean canChangeFont; /* device has multiple fonts */ Rboolean canRotateText; /* text can be rotated */ Rboolean canResizeText; /* text can be resized */ Rboolean canClip; /* Hardware clipping */ Rboolean canChangeGamma; /* can the gamma factor be modified */ int canHAdj; /* Can do at least some horiz adjust of text 0 = none, 1 = {0,0.5, 1}, 2 = [0,1] */ /******************************************************** * Device initial settings ********************************************************/ /* These are things that the device must set up when it is created. * The graphics system can modify them and track current values, * but some devices want to know what the original setting was. */ double startps; int startcol; int startfill; int startlty; int startfont; double startgamma; /******************************************************** * Device specific information ********************************************************/ void *deviceSpecific; /* pointer to device specific parameters */ /******************************************************** * Device display list ********************************************************/ /* I think it would feel nicer if this stuff was part of the * graphics engine (GEDevDesc), but this is another thing that * needs more time to implement a change properly. */ Rboolean displayListOn; /* toggle for display list status */ SEXP displayList; /* display list */ SEXP DLlastElt; SEXP savedSnapshot; /* The last value of the display list * just prior to when the display list * was last initialised */ /******************************************************** * Event handling entries ********************************************************/ /* These determine whether getGraphicsEvent will try to set an event handler */ Rboolean canGenMouseDown; /* can the device generate mousedown events */ Rboolean canGenMouseMove; /* can the device generate mousemove events */ Rboolean canGenMouseUp; /* can the device generate mouseup events */ Rboolean canGenKeybd; /* can the device generate keyboard events */ Rboolean gettingEvent; /* This is set while getGraphicsEvent is actively looking for events */ /******************************************************** * Device procedures. ********************************************************/ /* * --------------------------------------- * GENERAL COMMENT ON GRAPHICS PARAMETERS: * --------------------------------------- * Graphical parameters are now passed in a graphics context * structure (R_GE_gcontext*) rather than individually. * Each device action should extract the parameters it needs * and ignore the others. Thought should be given to which * parameters are relevant in each case -- the graphics engine * does not REQUIRE that each parameter is honoured, but if * a parameter is NOT honoured, it might be a good idea to * issue a warning when a parameter is not honoured (or at * the very least document which parameters are not honoured * in the user-level documentation for the device). [An example * of a parameter that may not be honoured by many devices is * transparency.] */ /* * device_Activate is called when a device becomes the * active device. For example, it can be used to change the * title of a window to indicate the active status of * the device to the user. Not all device types will * do anything. * The only parameter is a device driver structure. * An example is ... * * static void X11_Activate(NewDevDesc *dd); * */ void (*activate)(); /* * device_Circle should have the side-effect that a * circle is drawn, centred at the given location, with * the given radius. The border of the circle should be * drawn in the given "col", and the circle should be * filled with the given "fill" colour. * If "col" is NA_INTEGER then no border should be drawn * If "fill" is NA_INTEGER then the circle should not * be filled. * An example is ... * * static void X11_Circle(double x, double y, double r, * R_GE_gcontext *gc, * NewDevDesc *dd); * * R_GE_gcontext parameters that should be honoured (if possible): * col, fill, gamma, lty, lwd */ void (*circle)(); /* * device_Clip is given the left, right, bottom, and * top of a rectangle (in DEVICE coordinates). * It should have the side-effect that subsequent output * is clipped to the given rectangle. * NOTE that R's graphics engine already clips to the * extent of the device. * NOTE also that this will probably only be called if * the flag canClip is true. * An example is ... * * static void X11_Clip(double x0, double x1, double y0, double y1, * NewDevDesc *dd) */ void (*clip)(); /* * device_Close is called when the device is killed. * This function is responsible for destroying any * device-specific resources that were created in * device_Open and for FREEing the device-specific * parameters structure. * An example is ... * * static void X11_Close(NewDevDesc *dd) * */ void (*close)(); /* * device_Deactivate is called when a device becomes * inactive. * This allows the device to undo anything it did in * dev_Activate. * Not all device types will do anything. * An example is ... * * static void X11_Deactivate(NewDevDesc *dd) * */ void (*deactivate)(); void (*dot)(); /* * I don't know what this is for and i can't find it * being used anywhere, but i'm loath to kill it in * case i'm missing something important * An example is ... * * static void X11_Hold(NewDevDesc *dd) * */ void (*hold)(); /* * device_Locator should return the location of the next * mouse click (in DEVICE coordinates) * Not all devices will do anything (e.g., postscript) * An example is ... * * static Rboolean X11_Locator(double *x, double *y, NewDevDesc *dd) * */ Rboolean (*locator)(); /* * device_Line should have the side-effect that a single * line is drawn (from x1,y1 to x2,y2) * An example is ... * * static void X11_Line(double x1, double y1, double x2, double y2, * R_GE_gcontext *gc, * NewDevDesc *dd); * * R_GE_gcontext parameters that should be honoured (if possible): * col, gamma, lty, lwd */ void (*line)(); /* * device_MetricInfo should return height, depth, and * width information for the given character in DEVICE * units. * This is used for formatting mathematical expressions * and for exact centering of text (see GText) * If the device cannot provide metric information then * it MUST return 0.0 for ascent, descent, and width. * An example is ... * * static void X11_MetricInfo(int c, * R_GE_gcontext *gc, * double* ascent, double* descent, * double* width, NewDevDesc *dd); * * R_GE_gcontext parameters that should be honoured (if possible): * font, cex, ps */ void (*metricInfo)(); /* * device_Mode is called whenever the graphics engine * starts drawing (mode=1) or stops drawing (mode=0) * The device is not required to do anything * An example is ... * * static void X11_Mode(int mode, NewDevDesc *dd); * */ void (*mode)(); /* * device_NewPage is called whenever a new plot requires * a new page. * A new page might mean just clearing the * device (e.g., X11) or moving to a new page * (e.g., postscript) * An example is ... * * * static void X11_NewPage(R_GE_gcontext *gc, * NewDevDesc *dd); * */ void (*newPage)(); /* * device_Open is not usually called directly by the * graphics engine; it is usually only called from * the device-driver entry point. * This function should set up all of the device- * specific resources for a new device * This function is given a newly-allocated NewDevDesc structure * and it must FREE the structure if anything goes seriously wrong. * NOTE that different devices will accept different parameter * lists, corresponding to different device-specific preferences. * An example is ... * * Rboolean X11_Open(NewDevDesc *dd, char *dsp, double w, double h, * double gamma_fac, X_COLORTYPE colormodel, * int maxcube, int canvascolor); * */ Rboolean (*open)(); /* * device_Polygon should have the side-effect that a * polygon is drawn using the given x and y values * the polygon border should be drawn in the "col" * colour and filled with the "fill" colour. * If "col" is NA_INTEGER don't draw the border * If "fill" is NA_INTEGER don't fill the polygon * An example is ... * * static void X11_Polygon(int n, double *x, double *y, * R_GE_gcontext *gc, * NewDevDesc *dd); * * R_GE_gcontext parameters that should be honoured (if possible): * col, fill, gamma, lty, lwd */ void (*polygon)(); /* * device_Polyline should have the side-effect that a * series of line segments are drawn using the given x * and y values. * An example is ... * * static void X11_Polyline(int n, double *x, double *y, * R_GE_gcontext *gc, * NewDevDesc *dd); * * R_GE_gcontext parameters that should be honoured (if possible): * col, gamma, lty, lwd */ void (*polyline)(); /* * device_Rect should have the side-effect that a * rectangle is drawn with the given locations for its * opposite corners. The border of the rectangle * should be in the given "col" colour and the rectangle * should be filled with the given "fill" colour. * If "col" is NA_INTEGER then no border should be drawn * If "fill" is NA_INTEGER then the rectangle should not * be filled. * An example is ... * * static void X11_Rect(double x0, double y0, double x1, double y1, * R_GE_gcontext *gc, * NewDevDesc *dd); * */ void (*rect)(); /* * device_Size is called whenever the device is * resized. * The function returns (left, right, bottom, and top) for the * new device size. * This is not usually called directly by the graphics * engine because the detection of device resizes * (e.g., a window resize) are usually detected by * device-specific code. * An example is ... * * static void X11_Size(double *left, double *right, * double *bottom, double *top, * NewDevDesc *dd); * * R_GE_gcontext parameters that should be honoured (if possible): * col, fill, gamma, lty, lwd */ void (*size)(); /* * device_StrWidth should return the width of the given * string in DEVICE units. * An example is ... * * static double X11_StrWidth(char *str, * R_GE_gcontext *gc, * NewDevDesc *dd) * * R_GE_gcontext parameters that should be honoured (if possible): * font, cex, ps */ double (*strWidth)(); /* * device_Text should have the side-effect that the * given text is drawn at the given location. * The text should be rotated according to rot (degrees) * An example is ... * * static void X11_Text(double x, double y, char *str, * double rot, double hadj, * R_GE_gcontext *gc, * NewDevDesc *dd); * * R_GE_gcontext parameters that should be honoured (if possible): * font, cex, ps, col, gamma */ void (*text)(); /* * device_onExit is called by GEonExit when the user has aborted * some operation, and so an R_ProcessEvents call may not return normally. * It need not be set to any value; if null, it will not be called. * * An example is ... * * static void X11_onExit(NewDevDesc *dd); */ void (*onExit)(); /* * device_getEvent is called by do_getGraphicsEvent to get a modal * graphics event. It should call R_ProcessEvents() until one * of the event handlers sets eventResult to a non-null value, * and then return it * An example is ... * * static SEXP GA_getEvent(SEXP eventRho, char *prompt); */ SEXP (*getEvent)(); } NewDevDesc; /********************************************************/ /* the device-driver entry point is given a device */ /* description structure that it must set up. this */ /* involves several important jobs ... */ /* (1) it must ALLOCATE a new device-specific parameters*/ /* structure and FREE that structure if anything goes */ /* wrong (i.e., it won't report a successful setup to */ /* the graphics engine (the graphics engine is NOT */ /* responsible for allocating or freeing device-specific*/ /* resources or parameters) */ /* (2) it must initialise the device-specific resources */ /* and parameters (mostly done by calling device_Open) */ /* (3) it must initialise the generic graphical */ /* parameters that are not initialised by GInit (because*/ /* only the device knows what values they should have) */ /* see Graphics.h for the official list of these */ /* (4) it may reset generic graphics parameters that */ /* have already been initialised by GInit (although you */ /* should know what you are doing if you do this) */ /* (5) it must attach the device-specific parameters */ /* structure to the device description structure */ /* e.g., dd->deviceSpecfic = (void *) xd; */ /* (6) it must FREE the overall device description if */ /* it wants to bail out to the top-level */ /* the graphics engine is responsible for allocating */ /* the device description and freeing it in most cases */ /* but if the device driver freaks out it needs to do */ /* the clean-up itself */ /********************************************************/ #ifdef __cplusplus } #endif #endif /* R_GRAPHICSDEVICE_ */