CXXR (C++ R) API
QuartzDevice.h
1 /*
2  * R : A Computer Language for Statistical Data Analysis
3  * Copyright (C) 2007 The R Core Team
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 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 General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, a copy is available at
17  * http://www.r-project.org/Licenses/
18  *
19  *---------------------------------------------------------------------
20  * This header file constitutes the (unofficial) API to the Quartz
21  * device. Being unofficial, the API may change at any point without
22  * warning.
23  *
24  * Quartz is a general device-independent way of drawing in Mac OS X,
25  * therefore the Quartz device modularizes the actual drawing target
26  * implementation into separate modules (e.g. Carbon and Cocoa for
27  * on-screen display and PDF, Bitmap for off-screen drawing). The API
28  * below is used by the modules to talk to the Quartz device without
29  * having to know anything about R graphics device API.
30  *
31  * Key functions are listed here:
32  * QuartzDevice_Create - creates a Quartz device
33  * QuartzDevice_ResetContext - should be called after the target
34  * context has been created to initialize it.
35  * QuartzDevice_Kill - closes the Quartz device (e.g. on window close)
36  * QuartzDevice_SetScaledSize - resize device (does not include
37  * re-painting, it should be followed by a call to
38  * QuartzDevice_ReplayDisplayList)
39  * QuartzDevice_ReplayDisplayList - replays all plot commands
40  *
41  * Key concepts
42  * - all Quartz modules are expected to provide a device context
43  * (CGContextRef) for drawing. A device can temporarily return NULL
44  * (e.g. if the context is not available immediately) and replay
45  * the display list later to catch up.
46  *
47  * - interactive devices can use QuartzDevice_SetScaledSize to resize
48  * the device (no context is necessary), then prepare the context
49  * (call QuartzDevice_ResetContext if a new context was created)
50  * and finally re-draw using QuartzDevice_ReplayDisplayList.
51  *
52  * - snapshots can be created either off the current display list
53  * (last=0) or off the last known one (last=1). NewPage callback
54  * can only use last=1 as there is no display list during that
55  * call. Restored snapshots become the current display list and
56  * thus can be extended by further painting (yet the original saved
57  * copy is not influenced). Also note that all snapshots are SEXPs
58  * (the declaration doesn't use SEXP as to not depend on
59  * Rinternals.h) therefore must be protected or preserved immediately
60  * (i.e. the Quartz device does NOT protect them - except in the
61  * call to RestoreSnapshot).
62  *
63  * - dirty flag: the dirty flag is not used internally by the Quartz
64  * device, but can be useful for the modules to determine whether
65  * the current graphics is a restored copy or in-progress
66  * drawing. The Quartz device manages the flag as follows: a)
67  * display list replay does NOT change the flag, b) snapshot
68  * restoration resets the flag, c) all other paint operations
69  * (i.e. outside of restore/replay) set the flag. Most common use
70  * is to determine whether restored snapshots have been
71  * subsequently modified.
72  *
73  * - history: currently the history management is not used by any
74  * modules and as such is untested and strictly experimental. It
75  * may be removed in the future as it is not clear whether it makes
76  * sense to be part of the device. See Cocoa module for a
77  * module-internal implementation of the display history.
78  *
79  * Quartz device creation path:
80  * quartz() function -> SEXP Quartz(args) ->
81  * setup QuartzParameters_t, call backend constructor
82  * [e.g. QuartzCocoa_DeviceCreate(dd, fn, QuartzParameters_t *pars)] ->
83  * create backend definition (QuartzBackend_t backend) ->
84  * fn->Create(dd, &backend), return the result
85  */
86 
87 #ifndef R_EXT_QUARTZDEVICE_H_
88 #define R_EXT_QUARTZDEVICE_H_
89 
90 /* FIXME: this is installed, but can it really work without config.h */
91 
92 #ifdef HAVE_CONFIG_H
93 #include <config.h>
94 #endif
95 
96 #ifdef __cplusplus
97 extern "C" {
98 #endif
99 
100 #if HAVE_AQUA
101 #include <ApplicationServices/ApplicationServices.h>
102 #else
103  typedef void* CGContextRef;
104 #endif
105 
106 /* flags passed to the newPage callback */
107 #define QNPF_REDRAW 0x0001 /* is set when NewPage really means re-draw of an existing page */
108 
109 /* flags passed to QuartzDevice_Create (as fs parameter) */
110 #define QDFLAG_DISPLAY_LIST 0x0001
111 #define QDFLAG_INTERACTIVE 0x0002
112 #define QDFLAG_RASTERIZED 0x0004 /* rasterized media - may imply disabling AA paritally for rects etc. */
113 
114 /* parameter flags (they should not conflict with QDFLAGS to allow chaining) */
115 #define QPFLAG_ANTIALIAS 0x0100
116 
117 typedef void* QuartzDesc_t;
118 
119 typedef struct QuartzBackend_s {
120  int size; /* structure size */
121  double width, height;
122  double scalex, scaley, pointsize;
123  int bg, canvas;
124  int flags;
125  void* userInfo;
126  CGContextRef (*getCGContext)(QuartzDesc_t dev, void*userInfo); /* Get the context for this device */
127  int (*locatePoint)(QuartzDesc_t dev, void*userInfo, double*x, double*y);
128  void (*close)(QuartzDesc_t dev, void*userInfo);
129  void (*newPage)(QuartzDesc_t dev, void*userInfo, int flags);
130  void (*state)(QuartzDesc_t dev, void*userInfo, int state);
131  void* (*par)(QuartzDesc_t dev, void*userInfo, int set, const char *key, void *value);
132  void (*sync)(QuartzDesc_t dev, void*userInfo);
133  void* (*cap)(QuartzDesc_t dev, void*userInfo);
134 } QuartzBackend_t;
135 
136 /* parameters that are passed to functions that create backends */
137 typedef struct QuartzParameters_s {
138  int size; /* structure size */
139  const char *type, *file, *title;
140  double x, y, width, height, pointsize;
141  const char *family;
142  int flags;
143  int connection;
144  int bg, canvas;
145  double *dpi;
146  /* the following parameters can be used to pass custom parameters when desired */
147  double pard1, pard2;
148  int pari1, pari2;
149  const char *pars1, *pars2;
150  void *parv;
151 } QuartzParameters_t;
152 
153 /* all device implementations have to call this general Quartz device constructor at some point */
154 QuartzDesc_t QuartzDevice_Create(void *dd, QuartzBackend_t* def);
155 
156 typedef struct QuartzFunctons_s {
157  void* (*Create)(void *, QuartzBackend_t *); /* create a new device */
158  int (*DevNumber)(QuartzDesc_t desc); /* returns device number */
159  void (*Kill)(QuartzDesc_t desc); /* call to close the device */
160  void (*ResetContext)(QuartzDesc_t desc); /* notifies Q back-end that the implementation has created a new context */
161  double (*GetWidth)(QuartzDesc_t desc); /* get device width (in inches) */
162  double (*GetHeight)(QuartzDesc_t desc); /* get device height (in inches) */
163  void (*SetSize)(QuartzDesc_t desc, double width, double height); /* set device size (in inches) */
164 
165  double (*GetScaledWidth)(QuartzDesc_t desc); /* get device width (in pixels) */
166  double (*GetScaledHeight)(QuartzDesc_t desc); /* get device height (in pixels) */
167  void (*SetScaledSize)(QuartzDesc_t desc, double width, double height); /* set device size (in pixels) */
168 
169  double (*GetXScale)(QuartzDesc_t desc); /* get x scale factor (px/pt ratio) */
170  double (*GetYScale)(QuartzDesc_t desc); /* get y scale factor (px/pt ratio) */
171  void (*SetScale)(QuartzDesc_t desc,double scalex, double scaley); /* sets both scale factors (px/pt ratio) */
172 
173  void (*SetTextScale)(QuartzDesc_t desc,double scale); /* sets text scale factor */
174  double (*GetTextScale)(QuartzDesc_t desc); /* sets text scale factor */
175 
176  void (*SetPointSize)(QuartzDesc_t desc,double ps); /* sets point size */
177  double (*GetPointSize)(QuartzDesc_t desc); /* gets point size */
178 
179  int (*GetDirty)(QuartzDesc_t desc); /* sets dirty flag */
180  void (*SetDirty)(QuartzDesc_t desc,int dirty); /* gets dirty flag */
181 
182  void (*ReplayDisplayList)(QuartzDesc_t desc); /* replay display list
183  Note: it inhibits sync calls during repaint,
184  the caller is responsible for calling sync if needed.
185  Dirty flag is kept unmodified */
186  void* (*GetSnapshot)(QuartzDesc_t desc, int last);
187  /* create a (replayable) snapshot of the device contents.
188  when 'last' is set then the last stored display list is used,
189  otherwise a new snapshot is created */
190  void (*RestoreSnapshot)(QuartzDesc_t desc,void* snapshot);
191  /* restore a snapshot. also clears the dirty flag */
192 
193  int (*GetAntialias)(QuartzDesc_t desc); /* get anti-alias flag */
194  void (*SetAntialias)(QuartzDesc_t desc, int aa); /* set anti-alias flag */
195 
196  int (*GetBackground)(QuartzDesc_t desc); /* get background color */
197  void (*Activate)(QuartzDesc_t desc); /* activate/select the device */
198  /* get/set Quartz-specific parameters. desc can be NULL for global parameters */
199  void* (*SetParameter)(QuartzDesc_t desc, const char *key, void *value);
200  void* (*GetParameter)(QuartzDesc_t desc, const char *key);
201 } QuartzFunctions_t;
202 
203 #define QuartzParam_EmbeddingFlags "embeddeding flags" /* value: int[1] */
204 #define QP_Flags_CFLoop 0x0001 /* drives application event loop */
205 #define QP_Flags_Cocoa 0x0002 /* Cocoa is fully initialized */
206 #define QP_Flags_Front 0x0004 /* is front application */
207 
208 /* from unix/aqua.c - loads grDevices if necessary and returns NULL on failure */
209 QuartzFunctions_t *getQuartzFunctions();
210 
211 /* type of a Quartz contructor */
212 typedef QuartzDesc_t (*quartz_create_fn_t)(void *dd, QuartzFunctions_t *fn, QuartzParameters_t *par);
213 
214 /* grDevices currently supply following constructors:
215  QuartzCocoa_DeviceCreate, QuartzCarbon_DeviceCreate,
216  QuartzBitmap_DeviceCreate, QuartzPDF_DeviceCreate */
217 
218 /* embedded Quartz support hook (defined in unix/aqua.c):
219  dd = should be passed-through to QuartzDevice_Create
220  fn = Quartz API functions
221  par = parameters (see above) */
222 #ifndef IN_AQUA_C
223  extern
224 #endif
225  QuartzDesc_t (*ptr_QuartzBackend)(void *dd, QuartzFunctions_t *fn, QuartzParameters_t *par);
226 
227 /* C version of the Quartz call (experimental)
228  returns 0 on success, error code on failure */
229 QuartzDesc_t Quartz_C(QuartzParameters_t *par, quartz_create_fn_t q_create, int *errorCode);
230 
231 #ifdef __cplusplus
232 }
233 #endif
234 
235 #endif