The R Project SVN R

Rev

Rev 27236 | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 27236 Rev 28342
1
 /*
1
 /*
2
 *  R : A Computer Language for Statistical Data Analysis
2
 *  R : A Computer Language for Statistical Data Analysis
3
 *  file devQuartz.c
3
 *  file devQuartz.c
4
 *  Copyright (C) 2002-2003  Stefano M. Iacus and the R core team
4
 *  Copyright (C) 2002-2003  Stefano M. Iacus and the R core team
5
 *
5
 *
6
 *  This program is free software; you can redistribute it and/or modify
6
 *  This program is free software; you can redistribute it and/or modify
7
 *  it under the terms of the GNU General Public License as published by
7
 *  it under the terms of the GNU General Public License as published by
8
 *  the Free Software Foundation; either version 2 of the License, or
8
 *  the Free Software Foundation; either version 2 of the License, or
9
 *  (at your option) any later version.
9
 *  (at your option) any later version.
10
 *
10
 *
11
 *  This program is distributed in the hope that it will be useful,
11
 *  This program is distributed in the hope that it will be useful,
12
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 *  GNU General Public License for more details.
14
 *  GNU General Public License for more details.
15
 *
15
 *
16
 *  You should have received a copy of the GNU General Public License
16
 *  You should have received a copy of the GNU General Public License
17
 *  along with this program; if not, write to the Free Software
17
 *  along with this program; if not, write to the Free Software
18
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19
 */
19
 */
20
 
20
 
21
#ifndef __QUARTZ_DEVICE__
21
#ifndef __QUARTZ_DEVICE__
22
#define __QUARTZ_DEVICE__
22
#define __QUARTZ_DEVICE__
23
 
23
 
24
 
24
 
25
#ifdef HAVE_CONFIG_H
25
#ifdef HAVE_CONFIG_H
26
#include <config.h>
26
#include <config.h>
27
#endif
27
#endif
28
#include <Defn.h>
28
#include <Defn.h>
29
#include <Graphics.h>
29
#include <Graphics.h>
30
#include <Rdevices.h>
30
#include <Rdevices.h>
31
 
31
 
32
 
32
 
33
#if defined(__APPLE_CC__) && defined(HAVE_AQUA)
33
#if defined(__APPLE_CC__) && defined(HAVE_AQUA)
34
#define __DEBUGGING__
34
#define __DEBUGGING__
35
 
35
 
36
unsigned char Lat2Mac[] = { 
36
unsigned char Lat2Mac[] = { 
37
 32,  32,  32,  32,  32,  32,  32,  32,  32,  32, 
37
 32,  32,  32,  32,  32,  32,  32,  32,  32,  32, 
38
 32,  32,  32,  32,  32,  32, 245,  96, 171, 246,
38
 32,  32,  32,  32,  32,  32, 245,  96, 171, 246,
39
247, 248, 249, 250, 172,  32, 251, 252,  32, 253, 
39
247, 248, 249, 250, 172,  32, 251, 252,  32, 253, 
40
254, 255,  32, 193, 162, 163,  32, 180,  32, 164, 
40
254, 255,  32, 193, 162, 163,  32, 180,  32, 164, 
41
172, 169, 187, 199, 194,  45, 168, 248, 161, 177,
41
172, 169, 187, 199, 194,  45, 168, 248, 161, 177,
42
 32,  32, 171, 181, 166, 225, 252,  32, 188, 200, 
42
 32,  32, 171, 181, 166, 225, 252,  32, 188, 200, 
43
 32,  32,  32, 192, 203, 231, 229, 204, 128, 129,
43
 32,  32,  32, 192, 203, 231, 229, 204, 128, 129,
44
174, 130, 233, 131, 230, 232, 237, 234, 235, 236,
44
174, 130, 233, 131, 230, 232, 237, 234, 235, 236,
45
 32, 132, 241, 238, 239, 205, 133,  32, 175, 244,
45
 32, 132, 241, 238, 239, 205, 133,  32, 175, 244,
46
242, 243, 134,  32,  32, 167, 136, 135, 137, 139,
46
242, 243, 134,  32,  32, 167, 136, 135, 137, 139,
47
138, 140, 190, 141, 143, 142, 144, 145, 147, 146,
47
138, 140, 190, 141, 143, 142, 144, 145, 147, 146,
48
148, 149,  32, 150, 152, 151, 153, 155, 154, 214, 
48
148, 149,  32, 150, 152, 151, 153, 155, 154, 214, 
49
191, 157, 156, 158, 159,  32,  32, 216};
49
191, 157, 156, 158, 159,  32,  32, 216};
50
 
50
 
-
 
51
#define MAX_NON_SYMBS 17
-
 
52
unsigned char NotSymbols[] = {
-
 
53
 32, 33, 37, 38, 40, 41, 42, 43, 44, 58, 
-
 
54
 60, 61, 62, 91, 93, 95, 123, 125
-
 
55
};
-
 
56
 
-
 
57
/* conversion table to use symbol font enoded as
-
 
58
   unicode under MacOSX and no longer MacRoman
-
 
59
*/
-
 
60
unsigned char Lat2Uni[] = { 
-
 
61
    32, /* space */
-
 
62
	33, /* exclam */
-
 
63
    34, /* universal" */
-
 
64
	35, /* numbersign */
-
 
65
   154, /* existential */
-
 
66
	37, /* percent */
-
 
67
	38, /* ampersand */
-
 
68
	39, /* suchthat */
-
 
69
    40, /* parenleft */
-
 
70
    41, /* parenright */
-
 
71
   155, /* asteriskmath */
-
 
72
	 3, /* plus */
-
 
73
	44, /* comma */
-
 
74
	60, /* minus */
-
 
75
	46, /* period */
-
 
76
	58, /* slash*/
-
 
77
	48, /* 0 */
-
 
78
	49, /* 1 */
-
 
79
	50, /* 2 */
-
 
80
	51, /* 3 */
-
 
81
	52, /* 4 */
-
 
82
	53, /* 5 */
-
 
83
	54, /* 6 */
-
 
84
	55, /* 7 */
-
 
85
	56, /* 8 */
-
 
86
	57, /* 9 */
-
 
87
    58, /* colon */
-
 
88
	59, /* semicolon */
-
 
89
	60, /* less */
-
 
90
	62, /* equal */
-
 
91
	62, /* greater */
-
 
92
	63, /* question */
-
 
93
   129, /* congruent */
-
 
94
    73, /* Alpha */
-
 
95
	74, /* Beta */
-
 
96
	93, /* Chi */
-
 
97
	54, /* Delta */
-
 
98
	76, /* Epsilon */
-
 
99
	92, /* Phi */
-
 
100
	75, /* Gamma */
-
 
101
	78, /* Eta */
-
 
102
	80, /* Iota */
-
 
103
	85, /* theta1 */
-
 
104
	81, /* Kappa */
-
 
105
	82, /* Lambda */
-
 
106
	83, /* Mu */
-
 
107
	84, /* Nu */
-
 
108
	86, /* Omicron */
-
 
109
	87, /* Pi */
-
 
110
	79, /* Theta */
-
 
111
	88, /* Rho */
-
 
112
	89, /* Sigma */
-
 
113
	90, /* Tau */
-
 
114
	91, /* Upsilon */
-
 
115
	45, /* sigma1 */
-
 
116
	49, /* Omega */
-
 
117
	93, /* Xi */
-
 
118
	94, /* Psi */
-
 
119
	77, /* Zeta */
-
 
120
	33, /* bracketleft */  /* Miscellaneous Special Characters */
-
 
121
    92, /* therefore */
-
 
122
	35, /* bracketright */
-
 
123
   140, /* perpendicular */
-
 
124
	32, /* underscore */
-
 
125
	51, /* radicalex */
-
 
126
 95, /* alpha */
-
 
127
 96, /* beta */
-
 
128
114, /* chi */
-
 
129
 98, /* delta */
-
 
130
 161, /* epsilon */
-
 
131
 113, /* phi */
-
 
132
 97, /* gamma */
-
 
133
 100, /* eta */
-
 
134
 102, /* iota */
-
 
135
 160, /* phi1 */
-
 
136
 103, /* kappa */
-
 
137
 104, /* lambda */
-
 
138
  43, /* mu */
-
 
139
 105, /* nu */
-
 
140
 107, /* omicron */
-
 
141
 47, /* pi */
-
 
142
 101, /* theta */
-
 
143
 108, /* rho */
-
 
144
 109, /* sigma */
-
 
145
 111, /* tau */
-
 
146
 112, /* upsilon */
-
 
147
 159, /* omega1 */
-
 
148
 116, /* omega */
-
 
149
 106, /* xi */
-
 
150
 115, /* psi */
-
 
151
 110, /* zeta */
-
 
152
 123, /* braceleft */
-
 
153
 180, /* bar */
-
 
154
 125, /* braceright */
-
 
155
 126, /* similar */
-
 
156
 32, 32, 32, 32, 
-
 
157
 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
-
 
158
 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
-
 
159
 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
-
 
160
 175, /* Upsilon1 */	/* Lone Greek */
-
 
161
 118, /* minute */
-
 
162
  41, /* lessequal */
-
 
163
 177, /* fraction */
-
 
164
  39, /* infinity */
-
 
165
 166, /* florin      ??? */
-
 
166
 121, /* club */
-
 
167
 122, /* diamond */
-
 
168
 120, /* heart */
-
 
169
 123, /* spade */
-
 
170
  67, /* arrowboth */
-
 
171
  64, /* arrowleft */
-
 
172
  66, /* arrowup */
-
 
173
  65, /* arrowright */
-
 
174
  63, /* arrowdown */
-
 
175
  36, /* degree */
-
 
176
  40, /* plusminus */
-
 
177
 119, /* second */
-
 
178
  42, /* greaterequal */
-
 
179
 155, /* multiply */
-
 
180
 124, /* proportional */
-
 
181
  44, /* partialdiff */
-
 
182
  20, /* bullet */
-
 
183
  56, /* divide */
-
 
184
  38, /* notequal */
-
 
185
  62, /* equivalence */
-
 
186
  53, /* approxequal ??? */
-
 
187
  55, /* ellipsis    ??? */
-
 
188
 189, /* arrowvertex ??? */ 
-
 
189
 190, /* arrowhorizex ??? */
-
 
190
 191, /* carriagereturn */
-
 
191
 148, /* aleph */
-
 
192
 188, /* Ifraktur */
-
 
193
 189, /* Rfraktur */
-
 
194
 195, /* weierstrass ??? */
-
 
195
 128, /* circlemultiply */
-
 
196
 127, /* circleplus */
-
 
197
 146, /* emptyset */
-
 
198
  69, /* intersection */
-
 
199
  70, /* union */
-
 
200
 130, /* propersuperset */
-
 
201
 131, /* reflexsuperset */
-
 
202
 134, /* notsubset */
-
 
203
 132, /* propersubset */
-
 
204
 133, /* reflexsubset */
-
 
205
  68, /* element */
-
 
206
 141, /* notelement */
-
 
207
 144, /* angle */
-
 
208
 162, /* gradient */
-
 
209
 186, /* registerserif */
-
 
210
 185, /* copyrightserif */
-
 
211
 184, /* trademarkserif */
-
 
212
  87, /* product */
-
 
213
  51, /* radical */
-
 
214
  46, /* dotmath */
-
 
215
  32,
-
 
216
 217, /* logicaland ???*/
-
 
217
 218, /* logicalor ???*/
-
 
218
 139, /* arrowdblboth */
-
 
219
 136, /* arrowdblleft */
-
 
220
 138, /* arrowdblup */
-
 
221
 137, /* arrowdblright */
-
 
222
 135, /* arrowdbldown */
-
 
223
  57, /* lozenge */
-
 
224
 225, /* angleleft ???*/
-
 
225
 183, /* registersans */
-
 
226
 182, /* copyrightsans */
-
 
227
 181, /* trademarksans */
-
 
228
  89, /* summation */
-
 
229
 163, /* parenlefttp */
-
 
230
 179, /* parenleftex */
-
 
231
 164, /* parenleftbt */
-
 
232
 149, /* bracketlefttp */
-
 
233
 147, /* bracketleftex */
-
 
234
 150, /* bracketleftbt */
-
 
235
 168, /* bracelefttp */
-
 
236
 169, /* braceleftmid */
-
 
237
 170, /* braceleftbt */
-
 
238
 172, /* braceex */
-
 
239
  32,
-
 
240
 241, /* angleright */
-
 
241
  48, /* integral */
-
 
242
  71, /* integraltp */
-
 
243
 180, /* integralex */
-
 
244
  72, /* integralbt */
-
 
245
 165, /* parenrighttp */
-
 
246
 181, /* parenrightex */
-
 
247
 166, /* parenrightbt */
-
 
248
 151, /* bracketrighttp */
-
 
249
 166, /* bracketrightex */
-
 
250
 152, /* bracketrightbt */
-
 
251
 172, /* bracerighttp */
-
 
252
 173, /* bracerightmid */
-
 
253
 174, /* bracerightbt */
-
 
254
 255 /* NULL */
-
 
255
};
-
 
256
 
51
unsigned char Mac2Lat[] = { 
257
unsigned char Mac2Lat[] = { 
52
196, 197, 199, 201, 209, 214, 220, 225, 224, 226, 
258
196, 197, 199, 201, 209, 214, 220, 225, 224, 226, 
53
228, 227, 229, 231, 233, 232, 234, 235, 237, 236, 
259
228, 227, 229, 231, 233, 232, 234, 235, 237, 236, 
54
238, 239, 241, 243, 242, 244, 246, 245, 250, 249, 
260
238, 239, 241, 243, 242, 244, 246, 245, 250, 249, 
55
251, 252,  32, 176, 162, 163, 167,  32, 182, 223, 
261
251, 252,  32, 176, 162, 163, 167,  32, 182, 223, 
56
174, 169,  32, 146, 152,  32, 198, 216,  32, 177,
262
174, 169,  32, 146, 152,  32, 198, 216,  32, 177,
57
 32,  32, 165, 181,  32,  32,  32,  32,  32, 170, 
263
 32,  32, 165, 181,  32,  32,  32,  32,  32, 170, 
58
186,  32, 230, 248, 191, 161, 172,  32,  32,  32,
264
186,  32, 230, 248, 191, 161, 172,  32,  32,  32,
59
 32, 171, 187,  32,  32, 192, 195, 213,  32,  32,
265
 32, 171, 187,  32,  32, 192, 195, 213,  32,  32,
60
 32,  32,  32,  32,  96,  39, 247,  32, 255,  32, 
266
 32,  32,  32,  32,  96,  39, 247,  32, 255,  32, 
61
 32,  32,  32,  32,  32,  32,  32, 183,  32,  32,
267
 32,  32,  32,  32,  32,  32,  32, 183,  32,  32,
62
 32, 194, 202, 193, 203, 200, 205, 206, 207, 204, 
268
 32, 194, 202, 193, 203, 200, 205, 206, 207, 204, 
63
211, 212,  32, 210, 218, 219, 217, 144, 147, 148, 
269
211, 212,  32, 210, 218, 219, 217, 144, 147, 148, 
64
149, 150, 151, 154, 155, 157, 158, 159};
270
149, 150, 151, 154, 155, 157, 158, 159};
65
 
271
 
66
#include <Carbon/Carbon.h>
272
#include <Carbon/Carbon.h>
67
#include <CoreFoundation/CoreFoundation.h>
273
#include <CoreFoundation/CoreFoundation.h>
68
#include <ApplicationServices/ApplicationServices.h>
274
#include <ApplicationServices/ApplicationServices.h>
69
 
275
 
70
 
276
 
71
#define R_RED(col)	(((col)	   )&255)
277
#define R_RED(col)	(((col)	   )&255)
72
#define R_GREEN(col)	(((col)>> 8)&255)
278
#define R_GREEN(col)	(((col)>> 8)&255)
73
#define R_BLUE(col)	(((col)>>16)&255)
279
#define R_BLUE(col)	(((col)>>16)&255)
74
#define kRAppSignature '0FFF'
280
#define kRAppSignature '0FFF'
75
 
281
 
76
#if HAVE_AQUA
282
#if HAVE_AQUA
77
extern  DL_FUNC ptr_GetQuartzParameters;
283
extern  DL_FUNC ptr_GetQuartzParameters;
78
extern	Rboolean useaqua;
284
extern	Rboolean useaqua;
79
 
285
 
80
void GetQuartzParameters(double *width, double *height, double *ps, char *family, Rboolean *antialias, Rboolean *autorefresh) {ptr_GetQuartzParameters(width, height, ps, family, antialias, autorefresh);}
286
void GetQuartzParameters(double *width, double *height, double *ps, char *family, Rboolean *antialias, Rboolean *autorefresh) {ptr_GetQuartzParameters(width, height, ps, family, antialias, autorefresh);}
81
#endif
287
#endif
82
 
288
 
83
#define kOnScreen 	0
289
#define kOnScreen 	0
84
#define kOnFilePDF 	1
290
#define kOnFilePDF 	1
85
#define kOnFilePICT	2
291
#define kOnFilePICT	2
86
#define kOnClipboard 	3
292
#define kOnClipboard 	3
87
#define kOnPrinter	4
293
#define kOnPrinter	4
88
 
294
 
89
 
295
 
90
   /***************************************************************************/
296
   /***************************************************************************/
91
   /* Each driver can have its own device-specic graphical                    */
297
   /* Each driver can have its own device-specic graphical                    */
92
   /* parameters and resources.  these should be wrapped                      */
298
   /* parameters and resources.  these should be wrapped                      */
93
   /* in a structure (like the x11Desc structure below)                       */
299
   /* in a structure (like the x11Desc structure below)                       */
94
   /* and attached to the overall device description via                      */
300
   /* and attached to the overall device description via                      */
95
   /* the dd->deviceSpecific pointer                                          */
301
   /* the dd->deviceSpecific pointer                                          */
96
   /* NOTE that there are generic graphical parameters                        */
302
   /* NOTE that there are generic graphical parameters                        */
97
   /* which must be set by the device driver, but are                         */
303
   /* which must be set by the device driver, but are                         */
98
   /* common to all device types (see Graphics.h)                             */
304
   /* common to all device types (see Graphics.h)                             */
99
   /* so go in the GPar structure rather than this device-                    */
305
   /* so go in the GPar structure rather than this device-                    */
100
   /* specific structure                                                      */
306
   /* specific structure                                                      */
101
   /***************************************************************************/
307
   /***************************************************************************/
102
 
308
 
103
typedef struct {
309
typedef struct {
104
    int cex;
310
    int cex;
105
    int windowWidth;
311
    int windowWidth;
106
    int windowHeight;
312
    int windowHeight;
107
    Boolean resize;
313
    Boolean resize;
108
    int Text_Font;          /* 0 is system font and 4 is monaco */
314
    int Text_Font;          /* 0 is system font and 4 is monaco */
109
    int fontface;           /* Typeface */
315
    int fontface;           /* Typeface */
110
    int fontsize;           /* Size in points */
316
    int fontsize;           /* Size in points */
111
    int usefixed;
317
    int usefixed;
112
    int color;		        /* color */
318
    int color;		        /* color */
113
    int fill;	        	/* fill color */
319
    int fill;	        	/* fill color */
114
    WindowPtr window;
320
    WindowPtr window;
115
    int	lineType;
321
    int	lineType;
116
    int lineWidth;
322
    int lineWidth;
117
    Boolean Antialias;		/* Use Antialiasing */
323
    Boolean Antialias;		/* Use Antialiasing */
118
    Boolean Autorefresh;
324
    Boolean Autorefresh;
119
    char	*family;
325
    char	*family;
120
    CGContextRef context;     /* This is the context used by Quartz for OnScreen drawings */
326
    CGContextRef context;     /* This is the context used by Quartz for OnScreen drawings */
121
    CGContextRef auxcontext;  /* Additional context used for: cliboard, printer, file     */
327
    CGContextRef auxcontext;  /* Additional context used for: cliboard, printer, file     */
122
    double	xscale;
328
    double	xscale;
123
    double	yscale;
329
    double	yscale;
124
    int		where;
330
    int		where;
125
}
331
}
126
QuartzDesc;
332
QuartzDesc;
127
 
333
 
128
OSStatus QuartzEventHandler(EventHandlerCallRef inCallRef, EventRef inEvent, void* inUserData);
334
OSStatus QuartzEventHandler(EventHandlerCallRef inCallRef, EventRef inEvent, void* inUserData);
129
 
335
 
130
static const EventTypeSpec	QuartzEvents[] =
336
static const EventTypeSpec	QuartzEvents[] =
131
{
337
{
132
        { kEventClassWindow, kEventWindowClose },
338
        { kEventClassWindow, kEventWindowClose },
133
        { kEventClassWindow, kEventWindowBoundsChanged }
339
        { kEventClassWindow, kEventWindowBoundsChanged }
134
};
340
};
135
 
341
 
136
Rboolean innerQuartzDeviceDriver(NewDevDesc *dd, char *display,
342
Rboolean innerQuartzDeviceDriver(NewDevDesc *dd, char *display,
137
			 double width, double height, double pointsize,
343
			 double width, double height, double pointsize,
138
			 char *family, Rboolean antialias, Rboolean autorefresh);
344
			 char *family, Rboolean antialias, Rboolean autorefresh);
139
 
345
 
140
Rboolean QuartzDeviceDriver(DevDesc *dd, char *display,
346
Rboolean QuartzDeviceDriver(DevDesc *dd, char *display,
141
			 double width, double height, double pointsize,
347
			 double width, double height, double pointsize,
142
			 char *family, Rboolean antialias, Rboolean autorefresh);
348
			 char *family, Rboolean antialias, Rboolean autorefresh);
143
 
349
 
144
OSStatus SetCGContext(QuartzDesc *xd);
350
OSStatus SetCGContext(QuartzDesc *xd);
145
 
351
 
146
 
352
 
147
/* Device primitives */
353
/* Device primitives */
148
 
354
 
149
static Rboolean	Quartz_Open(NewDevDesc *, QuartzDesc *, char *,double, double);
355
static Rboolean	Quartz_Open(NewDevDesc *, QuartzDesc *, char *,double, double);
150
static void 	Quartz_Close(NewDevDesc *dd);
356
static void 	Quartz_Close(NewDevDesc *dd);
151
static void 	Quartz_Activate(NewDevDesc *dd);
357
static void 	Quartz_Activate(NewDevDesc *dd);
152
static void 	Quartz_Deactivate(NewDevDesc *dd);
358
static void 	Quartz_Deactivate(NewDevDesc *dd);
153
static void 	Quartz_Size(double *left, double *right,
359
static void 	Quartz_Size(double *left, double *right,
154
		     	 double *bottom, double *top, NewDevDesc *dd);
360
		     	 double *bottom, double *top, NewDevDesc *dd);
155
static void 	Quartz_NewPage(R_GE_gcontext *gc, NewDevDesc *dd);
361
static void 	Quartz_NewPage(R_GE_gcontext *gc, NewDevDesc *dd);
156
static void 	Quartz_Clip(double x0, double x1, double y0, double y1,
362
static void 	Quartz_Clip(double x0, double x1, double y0, double y1,
157
			    NewDevDesc *dd);
363
			    NewDevDesc *dd);
158
static double 	Quartz_StrWidth(char *str, 
364
static double 	Quartz_StrWidth(char *str, 
159
				R_GE_gcontext *gc,
365
				R_GE_gcontext *gc,
160
				NewDevDesc *dd);
366
				NewDevDesc *dd);
161
static void 	Quartz_Text(double x, double y, char *str,
367
static void 	Quartz_Text(double x, double y, char *str,
162
			    double rot, double hadj, 
368
			    double rot, double hadj, 
163
			    R_GE_gcontext *gc,
369
			    R_GE_gcontext *gc,
164
			    NewDevDesc *dd);
370
			    NewDevDesc *dd);
165
static void 	Quartz_Rect(double x0, double y0, double x1, double y1,
371
static void 	Quartz_Rect(double x0, double y0, double x1, double y1,
166
			    R_GE_gcontext *gc,
372
			    R_GE_gcontext *gc,
167
			    NewDevDesc *dd);
373
			    NewDevDesc *dd);
168
static void 	Quartz_Circle(double x, double y, double r, 
374
static void 	Quartz_Circle(double x, double y, double r, 
169
			      R_GE_gcontext *gc,
375
			      R_GE_gcontext *gc,
170
			      NewDevDesc *dd);
376
			      NewDevDesc *dd);
171
static void 	Quartz_Line(double x1, double y1, double x2, double y2,
377
static void 	Quartz_Line(double x1, double y1, double x2, double y2,
172
			    R_GE_gcontext *gc,
378
			    R_GE_gcontext *gc,
173
			    NewDevDesc *dd);
379
			    NewDevDesc *dd);
174
static void 	Quartz_Polyline(int n, double *x, double *y, 
380
static void 	Quartz_Polyline(int n, double *x, double *y, 
175
				R_GE_gcontext *gc,
381
				R_GE_gcontext *gc,
176
				NewDevDesc *dd);
382
				NewDevDesc *dd);
177
static void 	Quartz_Polygon(int n, double *x, double *y, 
383
static void 	Quartz_Polygon(int n, double *x, double *y, 
178
			       R_GE_gcontext *gc,
384
			       R_GE_gcontext *gc,
179
			       NewDevDesc *dd);
385
			       NewDevDesc *dd);
180
static Rboolean Quartz_Locator(double *x, double *y, NewDevDesc *dd);
386
static Rboolean Quartz_Locator(double *x, double *y, NewDevDesc *dd);
181
static void 	Quartz_Mode(int mode, NewDevDesc *dd);
387
static void 	Quartz_Mode(int mode, NewDevDesc *dd);
182
static void 	Quartz_Hold(NewDevDesc *dd);
388
static void 	Quartz_Hold(NewDevDesc *dd);
183
static void 	Quartz_MetricInfo(int c,
389
static void 	Quartz_MetricInfo(int c,
184
				  R_GE_gcontext *gc,
390
				  R_GE_gcontext *gc,
185
				  double* ascent, double* descent, 
391
				  double* ascent, double* descent, 
186
				  double* width,
392
				  double* width,
187
				  NewDevDesc *dd);
393
				  NewDevDesc *dd);
188
 
394
 
189
 
395
 
190
static void Quartz_SetFill(int fill, double gamma,  NewDevDesc *dd);
396
static void Quartz_SetFill(int fill, double gamma,  NewDevDesc *dd);
191
static void Quartz_SetStroke(int color, double gamma,  NewDevDesc *dd);
397
static void Quartz_SetStroke(int color, double gamma,  NewDevDesc *dd);
192
static void Quartz_SetLineDash(int lty, double lwd, NewDevDesc *dd);
398
static void Quartz_SetLineDash(int lty, double lwd, NewDevDesc *dd);
193
static void Quartz_SetLineWidth(double lwd,  NewDevDesc *dd);
399
static void Quartz_SetLineWidth(double lwd,  NewDevDesc *dd);
194
static void Quartz_SetFont(int style,  double cex, double ps,  NewDevDesc *dd);
400
static void Quartz_SetFont(int style,  double cex, double ps,  NewDevDesc *dd);
195
static CGContextRef	GetContext(QuartzDesc *xd);
401
static CGContextRef	GetContext(QuartzDesc *xd);
196
 
402
 
197
 
403
 
198
 
404
 
199
 
405
 
200
static SEXP gcall;
406
static SEXP gcall;
201
static char *SaveString(SEXP sxp, int offset)
407
static char *SaveString(SEXP sxp, int offset)
202
{
408
{
203
    char *s;
409
    char *s;
204
    if(!isString(sxp) || length(sxp) <= offset)
410
    if(!isString(sxp) || length(sxp) <= offset)
205
	errorcall(gcall, "invalid string argument");
411
	errorcall(gcall, "invalid string argument");
206
    s = R_alloc(strlen(CHAR(STRING_ELT(sxp, offset)))+1, sizeof(char));
412
    s = R_alloc(strlen(CHAR(STRING_ELT(sxp, offset)))+1, sizeof(char));
207
    strcpy(s, CHAR(STRING_ELT(sxp, offset)));
413
    strcpy(s, CHAR(STRING_ELT(sxp, offset)));
208
    return s;
414
    return s;
209
}
415
}
210
 
416
 
211
 
417
 
212
/*  Quartz Device Driver Parameters:
418
/*  Quartz Device Driver Parameters:
213
 *  -----------------		cf with ../unix/X11/devX11.c
419
 *  -----------------		cf with ../unix/X11/devX11.c
214
 *  display	= display
420
 *  display	= display
215
 *  width	= width in inches
421
 *  width	= width in inches
216
 *  height	= height in inches
422
 *  height	= height in inches
217
 *  ps		= pointsize
423
 *  ps		= pointsize
218
 *  family  = Postscript fon family name
424
 *  family  = Postscript fon family name
219
 *  Antialias = wheter to make antialiasing
425
 *  Antialias = wheter to make antialiasing
220
 */
426
 */
221
 
427
 
222
 
428
 
223
SEXP do_Quartz(SEXP call, SEXP op, SEXP args, SEXP env)
429
SEXP do_Quartz(SEXP call, SEXP op, SEXP args, SEXP env)
224
{
430
{
225
    NewDevDesc *dev = NULL;
431
    NewDevDesc *dev = NULL;
226
    GEDevDesc *dd;
432
    GEDevDesc *dd;
227
    char *display, *vmax, *family=NULL;
433
    char *display, *vmax, *family=NULL;
228
    char fontfamily[255];
434
    char fontfamily[255];
229
    double height, width, ps;
435
    double height, width, ps;
230
    Rboolean  antialias, autorefresh;
436
    Rboolean  antialias, autorefresh;
231
    gcall = call;
437
    gcall = call;
232
    vmax = vmaxget();
438
    vmax = vmaxget();
233
    display = SaveString(CAR(args), 0);
439
    display = SaveString(CAR(args), 0);
234
    args = CDR(args);
440
    args = CDR(args);
235
    width = asReal(CAR(args));	args = CDR(args);
441
    width = asReal(CAR(args));	args = CDR(args);
236
    height = asReal(CAR(args)); args = CDR(args);
442
    height = asReal(CAR(args)); args = CDR(args);
237
    if (width <= 0 || height <= 0)
443
    if (width <= 0 || height <= 0)
238
	errorcall(call, "invalid width or height");
444
	errorcall(call, "invalid width or height");
239
    ps = asReal(CAR(args));  args = CDR(args);
445
    ps = asReal(CAR(args));  args = CDR(args);
240
    family = SaveString(CAR(args), 0);    args = CDR(args);
446
    family = SaveString(CAR(args), 0);    args = CDR(args);
241
    antialias = asLogical(CAR(args));   args = CDR(args);
447
    antialias = asLogical(CAR(args));   args = CDR(args);
242
    autorefresh = asLogical(CAR(args));
448
    autorefresh = asLogical(CAR(args));
243
 
449
 
244
 
450
 
245
 
451
 
246
     R_CheckDeviceAvailable();
452
     R_CheckDeviceAvailable();
247
    /* Allocate and initialize the device driver data */
453
    /* Allocate and initialize the device driver data */
248
     BEGIN_SUSPEND_INTERRUPTS {
454
     BEGIN_SUSPEND_INTERRUPTS {
249
      if (!(dev = (NewDevDesc *) calloc(1, sizeof(NewDevDesc))))
455
      if (!(dev = (NewDevDesc *) calloc(1, sizeof(NewDevDesc))))
250
	   return 0;
456
	   return 0;
251
    /* Do this for early redraw attempts */
457
    /* Do this for early redraw attempts */
252
    dev->displayList = R_NilValue;
458
    dev->displayList = R_NilValue;
253
    /* Make sure that this is initialised before a GC can occur.
459
    /* Make sure that this is initialised before a GC can occur.
254
     * This (and displayList) get protected during GC
460
     * This (and displayList) get protected during GC
255
     */
461
     */
256
    dev->savedSnapshot = R_NilValue;
462
    dev->savedSnapshot = R_NilValue;
257
 
463
 
258
    strcpy(fontfamily, family);
464
    strcpy(fontfamily, family);
259
#ifdef HAVE_AQUA
465
#ifdef HAVE_AQUA
260
    if(useaqua)
466
    if(useaqua)
261
     GetQuartzParameters(&width, &height, &ps, fontfamily, &antialias, &autorefresh);
467
     GetQuartzParameters(&width, &height, &ps, fontfamily, &antialias, &autorefresh);
262
#endif
468
#endif
263
 
469
 
264
    if (!QuartzDeviceDriver((DevDesc *)dev, display, width, height, ps,
470
    if (!QuartzDeviceDriver((DevDesc *)dev, display, width, height, ps,
265
       fontfamily, antialias, autorefresh)) {
471
       fontfamily, antialias, autorefresh)) {
266
	 free(dev);
472
	 free(dev);
267
	 errorcall(call, "unable to start device Quartz\n");
473
	 errorcall(call, "unable to start device Quartz\n");
268
    }
474
    }
269
    gsetVar(install(".Device"), mkString("quartz"), R_NilValue);
475
    gsetVar(install(".Device"), mkString("quartz"), R_NilValue);
270
    dd = GEcreateDevDesc(dev);
476
    dd = GEcreateDevDesc(dev);
271
    addDevice((DevDesc*)dd);
477
    addDevice((DevDesc*)dd);
272
    GEinitDisplayList(dd);
478
    GEinitDisplayList(dd);
273
    } END_SUSPEND_INTERRUPTS;
479
    } END_SUSPEND_INTERRUPTS;
274
    vmaxset(vmax);
480
    vmaxset(vmax);
275
    return R_NilValue;
481
    return R_NilValue;
276
}
482
}
277
 
483
 
278
 
484
 
279
 
485
 
280
 
486
 
281
 
487
 
282
Rboolean QuartzDeviceDriver(DevDesc *dd, char *display,
488
Rboolean QuartzDeviceDriver(DevDesc *dd, char *display,
283
			 double width, double height, double pointsize,
489
			 double width, double height, double pointsize,
284
			 char *family, Rboolean antialias, Rboolean autorefresh)
490
			 char *family, Rboolean antialias, Rboolean autorefresh)
285
{
491
{
286
return innerQuartzDeviceDriver((NewDevDesc *)dd, display,
492
return innerQuartzDeviceDriver((NewDevDesc *)dd, display,
287
			 width,  height,  pointsize, family, antialias, autorefresh);
493
			 width,  height,  pointsize, family, antialias, autorefresh);
288
}
494
}
289
 
495
 
290
 
496
 
291
Rboolean innerQuartzDeviceDriver(NewDevDesc *dd, char *display,
497
Rboolean innerQuartzDeviceDriver(NewDevDesc *dd, char *display,
292
			 double width, double height, double pointsize,
498
			 double width, double height, double pointsize,
293
			 char *family, Rboolean antialias, Rboolean autorefresh)
499
			 char *family, Rboolean antialias, Rboolean autorefresh)
294
{
500
{
295
    QuartzDesc *xd;
501
    QuartzDesc *xd;
296
    int ps;
502
    int ps;
297
    Rect rect;
503
    Rect rect;
298
    OSStatus err;
504
    OSStatus err;
299
 
505
 
300
 
506
 
301
    if (!(xd = (QuartzDesc *)malloc(sizeof(QuartzDesc))))
507
    if (!(xd = (QuartzDesc *)malloc(sizeof(QuartzDesc))))
302
	return 0;
508
	return 0;
303
 
509
 
304
    if(!Quartz_Open(dd, xd, display, width, height))
510
    if(!Quartz_Open(dd, xd, display, width, height))
305
     return(FALSE);
511
     return(FALSE);
306
 
512
 
307
    ps = pointsize;
513
    ps = pointsize;
308
    if (ps < 6 || ps > 24) ps = 10;
514
    if (ps < 6 || ps > 24) ps = 10;
309
    ps = 2 * (ps / 2);
515
    ps = 2 * (ps / 2);
310
    dd->startps = ps;
516
    dd->startps = ps;
311
    dd->startfont = 1;
517
    dd->startfont = 1;
312
    dd->startlty = LTY_SOLID;
518
    dd->startlty = LTY_SOLID;
313
    dd->startgamma = 1;
519
    dd->startgamma = 1;
314
 
520
 
315
    dd->newDevStruct = 1;
521
    dd->newDevStruct = 1;
316
 
522
 
317
    dd->open       = Quartz_Open;
523
    dd->open       = Quartz_Open;
318
    dd->close      = Quartz_Close;
524
    dd->close      = Quartz_Close;
319
    dd->activate   = Quartz_Activate;
525
    dd->activate   = Quartz_Activate;
320
    dd->deactivate = Quartz_Deactivate;
526
    dd->deactivate = Quartz_Deactivate;
321
    dd->size       = Quartz_Size;
527
    dd->size       = Quartz_Size;
322
    dd->newPage    = Quartz_NewPage;
528
    dd->newPage    = Quartz_NewPage;
323
    dd->clip       = Quartz_Clip;
529
    dd->clip       = Quartz_Clip;
324
    dd->strWidth   = Quartz_StrWidth;
530
    dd->strWidth   = Quartz_StrWidth;
325
    dd->text       = Quartz_Text;
531
    dd->text       = Quartz_Text;
326
    dd->rect       = Quartz_Rect;
532
    dd->rect       = Quartz_Rect;
327
    dd->circle     = Quartz_Circle;
533
    dd->circle     = Quartz_Circle;
328
    dd->line       = Quartz_Line;
534
    dd->line       = Quartz_Line;
329
    dd->polyline   = Quartz_Polyline;
535
    dd->polyline   = Quartz_Polyline;
330
    dd->polygon    = Quartz_Polygon;
536
    dd->polygon    = Quartz_Polygon;
331
    dd->locator    = Quartz_Locator;
537
    dd->locator    = Quartz_Locator;
332
    dd->mode       = Quartz_Mode;
538
    dd->mode       = Quartz_Mode;
333
    dd->hold       = Quartz_Hold;
539
    dd->hold       = Quartz_Hold;
334
 
540
 
335
    dd->metricInfo = Quartz_MetricInfo;
541
    dd->metricInfo = Quartz_MetricInfo;
336
 
542
 
337
    dd->left        = 0;
543
    dd->left        = 0;
338
    dd->right       =  xd->windowWidth;
544
    dd->right       =  xd->windowWidth;
339
    dd->bottom      =  xd->windowHeight;
545
    dd->bottom      =  xd->windowHeight;
340
    dd->top         = 0;
546
    dd->top         = 0;
341
 
547
 
342
    dd->xCharOffset = 0.4900;
548
    dd->xCharOffset = 0.4900;
343
    dd->yCharOffset = 0.3333;
549
    dd->yCharOffset = 0.3333;
344
    dd->yLineBias = 0.1;
550
    dd->yLineBias = 0.1;
345
 
551
 
346
    dd->cra[0] = ps / 2;
552
    dd->cra[0] = ps / 2;
347
    dd->cra[1] = ps;
553
    dd->cra[1] = ps;
348
 
554
 
349
    dd->ipr[0] = 1.0 / 72;
555
    dd->ipr[0] = 1.0 / 72;
350
    dd->ipr[1] = 1.0 / 72;
556
    dd->ipr[1] = 1.0 / 72;
351
 
557
 
352
    dd->canResizePlot = TRUE;
558
    dd->canResizePlot = TRUE;
353
    dd->canChangeFont = TRUE;
559
    dd->canChangeFont = TRUE;
354
    dd->canRotateText = TRUE;
560
    dd->canRotateText = TRUE;
355
    dd->canResizeText = TRUE;
561
    dd->canResizeText = TRUE;
356
    dd->canClip       = FALSE;
562
    dd->canClip       = FALSE;
357
    dd->canHAdj = 0;
563
    dd->canHAdj = 0;
358
    dd->canChangeGamma = FALSE;
564
    dd->canChangeGamma = FALSE;
359
 
565
 
360
 
566
 
361
    /* It is used to set the font that you will be used on the postscript and
567
    /* It is used to set the font that you will be used on the postscript and
362
       drawing.
568
       drawing.
363
    */
569
    */
364
 
570
 
365
    /* There is the place for you to set the default value of the MAC Devices */
571
    /* There is the place for you to set the default value of the MAC Devices */
366
    xd->cex = 1.0;
572
    xd->cex = 1.0;
367
    xd->resize = 0;
573
    xd->resize = 0;
368
    xd->Text_Font = 4; /* initial is monaco */
574
    xd->Text_Font = 4; /* initial is monaco */
369
    xd->fontface = 0;  /* initial is plain text */
575
    xd->fontface = 0;  /* initial is plain text */
370
    xd->fontsize = 12; /* initial is 12 size */
576
    xd->fontsize = 12; /* initial is 12 size */
371
    xd->Antialias = antialias; /* by default Antialias if on */
577
    xd->Antialias = antialias; /* by default Antialias if on */
372
    xd->Autorefresh = autorefresh; /* by default it is on */
578
    xd->Autorefresh = autorefresh; /* by default it is on */
373
 
579
 
374
    if(family){
580
    if(family){
375
     xd->family = malloc(sizeof(family)+1);
581
     xd->family = malloc(sizeof(family)+1);
376
     strcpy(xd->family,family);
582
     strcpy(xd->family,family);
377
    }
583
    }
378
    else
584
    else
379
     xd->family = NULL;
585
     xd->family = NULL;
380
 
586
 
381
    xd->where  = kOnScreen;
587
    xd->where  = kOnScreen;
382
    err = SetCGContext(xd);
588
    err = SetCGContext(xd);
383
 
589
 
384
/* This scale factor is needed in MetricInfo */
590
/* This scale factor is needed in MetricInfo */
385
    xd->xscale = width/72.0;
591
    xd->xscale = width/72.0;
386
    xd->yscale = height/72.0;
592
    xd->yscale = height/72.0;
387
 
593
 
388
    dd->deviceSpecific = (void *) xd;
594
    dd->deviceSpecific = (void *) xd;
389
    dd->displayListOn = TRUE;
595
    dd->displayListOn = TRUE;
390
 
596
 
391
    return 1;
597
    return 1;
392
}
598
}
393
 
599
 
394
OSStatus SetCGContext(QuartzDesc *xd)
600
OSStatus SetCGContext(QuartzDesc *xd)
395
{
601
{
396
    Rect rect;
602
    Rect rect;
397
    OSStatus	err = noErr;
603
    OSStatus	err = noErr;
398
    CGRect    cgRect;
604
    CGRect    cgRect;
399
 
605
 
400
    if(xd->context)
606
    if(xd->context)
401
        CGContextRelease(xd->context);
607
        CGContextRelease(xd->context);
402
 
608
 
403
    if(xd->auxcontext)
609
    if(xd->auxcontext)
404
        CGContextRelease(xd->auxcontext);
610
        CGContextRelease(xd->auxcontext);
405
 
611
 
406
    err = CreateCGContextForPort(GetWindowPort(xd->window), &xd->context);
612
    err = CreateCGContextForPort(GetWindowPort(xd->window), &xd->context);
407
 
613
 
408
    /*  Translate to QuickDraw coordinate system */
614
    /*  Translate to QuickDraw coordinate system */
409
 
615
 
410
    GetPortBounds(GetWindowPort(xd->window), &rect);
616
    GetPortBounds(GetWindowPort(xd->window), &rect);
411
    CGContextTranslateCTM(xd->context,0, (float)(rect.bottom - rect.top));
617
    CGContextTranslateCTM(xd->context,0, (float)(rect.bottom - rect.top));
412
 
618
 
413
/* Be aware that by performing a negative scale in the following line of
619
/* Be aware that by performing a negative scale in the following line of
414
   code, your text will also be flipped
620
   code, your text will also be flipped
415
*/
621
*/
416
    CGContextScaleCTM(xd->context, 1, -1);
622
    CGContextScaleCTM(xd->context, 1, -1);
417
 
623
 
418
  /* We apply here Antialiasing if necessary */
624
  /* We apply here Antialiasing if necessary */
419
    CGContextSetShouldAntialias(xd->context, xd->Antialias);
625
    CGContextSetShouldAntialias(xd->context, xd->Antialias);
420
 
626
 
421
   return err;
627
   return err;
422
}
628
}
423
 
629
 
424
static Rboolean	Quartz_Open(NewDevDesc *dd, QuartzDesc *xd, char *dsp,
630
static Rboolean	Quartz_Open(NewDevDesc *dd, QuartzDesc *xd, char *dsp,
425
		    double wid, double hgt)
631
		    double wid, double hgt)
426
{
632
{
427
 
633
 
428
	OSStatus	err;
634
	OSStatus	err;
429
	WindowRef 	devWindow =  NULL;
635
	WindowRef 	devWindow =  NULL;
430
	Rect		devBounds;
636
	Rect		devBounds;
431
        Str255		Title;
637
        Str255		Title;
432
	char		buffer[250];
638
	char		buffer[250];
433
	int 		devnum = devNumber((DevDesc *)dd);
639
	int 		devnum = devNumber((DevDesc *)dd);
434
 
640
 
435
    xd->windowWidth = wid*72;
641
    xd->windowWidth = wid*72;
436
    xd->windowHeight = hgt*72;
642
    xd->windowHeight = hgt*72;
437
    xd->window = NULL;
643
    xd->window = NULL;
438
    xd->context = NULL;
644
    xd->context = NULL;
439
    xd->auxcontext = NULL;
645
    xd->auxcontext = NULL;
440
    dd->startfill = R_RGB(255, 255, 255);
646
    dd->startfill = R_RGB(255, 255, 255);
441
    dd->startcol = R_RGB(0, 0, 0);
647
    dd->startcol = R_RGB(0, 0, 0);
442
    /* Create a new window with the specified size */
648
    /* Create a new window with the specified size */
443
 
649
 
444
 
650
 
445
	SetRect(&devBounds, 400, 400, 400 + xd->windowWidth, 400 + xd->windowHeight ) ;
651
	SetRect(&devBounds, 400, 400, 400 + xd->windowWidth, 400 + xd->windowHeight ) ;
446
 
652
 
447
        err = CreateNewWindow( kDocumentWindowClass, kWindowStandardHandlerAttribute|kWindowVerticalZoomAttribute | kWindowCollapseBoxAttribute|kWindowResizableAttribute | kWindowCloseBoxAttribute ,
653
        err = CreateNewWindow( kDocumentWindowClass, kWindowStandardHandlerAttribute|kWindowVerticalZoomAttribute | kWindowCollapseBoxAttribute|kWindowResizableAttribute | kWindowCloseBoxAttribute ,
448
		& devBounds, & devWindow);
654
		& devBounds, & devWindow);
449
 
655
 
450
	sprintf(buffer,"Quartz (%d) - Active",devnum+1);
656
	sprintf(buffer,"Quartz (%d) - Active",devnum+1);
451
	CopyCStringToPascal(buffer,Title);
657
	CopyCStringToPascal(buffer,Title);
452
        SetWTitle(devWindow, Title);
658
        SetWTitle(devWindow, Title);
453
 
659
 
454
	ShowWindow(devWindow);
660
	ShowWindow(devWindow);
455
 
661
 
456
	err = InstallWindowEventHandler( devWindow, NewEventHandlerUPP(QuartzEventHandler),
662
	err = InstallWindowEventHandler( devWindow, NewEventHandlerUPP(QuartzEventHandler),
457
                                          GetEventTypeCount(QuartzEvents),
663
                                          GetEventTypeCount(QuartzEvents),
458
                                          QuartzEvents, (void *)devWindow, NULL);
664
                                          QuartzEvents, (void *)devWindow, NULL);
459
                                          
665
                                          
460
    if(err != noErr)
666
    if(err != noErr)
461
     return(0);
667
     return(0);
462
 
668
 
463
    xd->window = devWindow;
669
    xd->window = devWindow;
464
    xd->color = xd->fill = NA_INTEGER;
670
    xd->color = xd->fill = NA_INTEGER;
465
    xd->resize = false;
671
    xd->resize = false;
466
    xd->lineType = 0;
672
    xd->lineType = 0;
467
    xd->lineWidth = 1;
673
    xd->lineWidth = 1;
468
    return TRUE;
674
    return TRUE;
469
}
675
}
470
 
676
 
471
static void 	Quartz_Close(NewDevDesc *dd)
677
static void 	Quartz_Close(NewDevDesc *dd)
472
{
678
{
473
  QuartzDesc *xd = (QuartzDesc *) dd->deviceSpecific;
679
  QuartzDesc *xd = (QuartzDesc *) dd->deviceSpecific;
474
 
680
 
475
  if(xd->window)
681
  if(xd->window)
476
   DisposeWindow(xd->window);
682
   DisposeWindow(xd->window);
477
 
683
 
478
  if(xd->family)
684
  if(xd->family)
479
   free(xd->family);
685
   free(xd->family);
480
 
686
 
481
  if(xd->context)
687
  if(xd->context)
482
   CGContextRelease(xd->context);
688
   CGContextRelease(xd->context);
483
 
689
 
484
  if(xd->auxcontext)
690
  if(xd->auxcontext)
485
   CGContextRelease(xd->auxcontext);
691
   CGContextRelease(xd->auxcontext);
486
 
692
 
487
  free(xd);
693
  free(xd);
488
}
694
}
489
 
695
 
490
static void 	Quartz_Activate(NewDevDesc *dd)
696
static void 	Quartz_Activate(NewDevDesc *dd)
491
{
697
{
492
	Str255	Title;
698
	Str255	Title;
493
	char	buffer[250];
699
	char	buffer[250];
494
	QuartzDesc *xd = (QuartzDesc*)dd->deviceSpecific;
700
	QuartzDesc *xd = (QuartzDesc*)dd->deviceSpecific;
495
	int devnum = devNumber((DevDesc *)dd);
701
	int devnum = devNumber((DevDesc *)dd);
496
        OSStatus err;
702
        OSStatus err;
497
 
703
 
498
	sprintf(buffer,"Quartz (%d) - Active",devnum+1);
704
	sprintf(buffer,"Quartz (%d) - Active",devnum+1);
499
	CopyCStringToPascal(buffer,Title);
705
	CopyCStringToPascal(buffer,Title);
500
	SetWTitle(xd->window,Title);
706
	SetWTitle(xd->window,Title);
501
 
707
 
502
/*
708
/*
503
   We add a property to the Window each time we activate it.
709
   We add a property to the Window each time we activate it.
504
   We should only make this the first time we open the device.
710
   We should only make this the first time we open the device.
505
*/
711
*/
506
        err = SetWindowProperty(xd->window,kRAppSignature,'QRTZ',sizeof(int),&devnum);
712
        err = SetWindowProperty(xd->window,kRAppSignature,'QRTZ',sizeof(int),&devnum);
507
 
713
 
508
	ShowWindow(xd->window);
714
	ShowWindow(xd->window);
509
 
715
 
510
}
716
}
511
 
717
 
512
 
718
 
513
 
719
 
514
static void 	Quartz_Deactivate(NewDevDesc *dd)
720
static void 	Quartz_Deactivate(NewDevDesc *dd)
515
{
721
{
516
	Str255	Title;
722
	Str255	Title;
517
	char	buffer[250];
723
	char	buffer[250];
518
	QuartzDesc *xd = (QuartzDesc*)dd->deviceSpecific;
724
	QuartzDesc *xd = (QuartzDesc*)dd->deviceSpecific;
519
	int devnum = devNumber((DevDesc *)dd);
725
	int devnum = devNumber((DevDesc *)dd);
520
 
726
 
521
	sprintf(buffer,"Quartz (%d) - Not Active",devnum+1);
727
	sprintf(buffer,"Quartz (%d) - Not Active",devnum+1);
522
	CopyCStringToPascal(buffer,Title);
728
	CopyCStringToPascal(buffer,Title);
523
	SetWTitle(xd->window,Title);
729
	SetWTitle(xd->window,Title);
524
	ShowWindow(xd->window);
730
	ShowWindow(xd->window);
525
}
731
}
526
 
732
 
527
 
733
 
528
static void 	Quartz_Size(double *left, double *right,
734
static void 	Quartz_Size(double *left, double *right,
529
		     	 double *bottom, double *top, NewDevDesc *dd)
735
		     	 double *bottom, double *top, NewDevDesc *dd)
530
{
736
{
531
    QuartzDesc *xd = (QuartzDesc*)dd->deviceSpecific;
737
    QuartzDesc *xd = (QuartzDesc*)dd->deviceSpecific;
532
    Rect portRect;
738
    Rect portRect;
533
 
739
 
534
    GetWindowPortBounds ( xd->window, & portRect ) ;
740
    GetWindowPortBounds ( xd->window, & portRect ) ;
535
 
741
 
536
    *left = 0.0;
742
    *left = 0.0;
537
    *right = portRect.right;
743
    *right = portRect.right;
538
    *bottom = portRect.bottom;
744
    *bottom = portRect.bottom;
539
    *top = 0.0;
745
    *top = 0.0;
540
 
746
 
541
    xd->windowWidth = *right - *left;
747
    xd->windowWidth = *right - *left;
542
    xd->windowHeight = *bottom - *top;
748
    xd->windowHeight = *bottom - *top;
543
    SetCGContext(xd);
749
    SetCGContext(xd);
544
 
750
 
545
    return;
751
    return;
546
}
752
}
547
 
753
 
548
void Quartz_ReSizeWin(NewDevDesc *dd)
754
void Quartz_ReSizeWin(NewDevDesc *dd)
549
{
755
{
550
 
756
 
551
}
757
}
552
 
758
 
553
static CGContextRef     GetContext(QuartzDesc *xd){
759
static CGContextRef     GetContext(QuartzDesc *xd){
554
 
760
 
555
   switch(xd->where){
761
   switch(xd->where){
556
   
762
   
557
    case kOnScreen:
763
    case kOnScreen:
558
        return(xd->context);
764
        return(xd->context);
559
    break;
765
    break;
560
 
766
 
561
    case kOnFilePDF:
767
    case kOnFilePDF:
562
        return(xd->auxcontext);
768
        return(xd->auxcontext);
563
    break;
769
    break;
564
 
770
 
565
    default:
771
    default:
566
        return(NULL);
772
        return(NULL);
567
    break;
773
    break;
568
   
774
   
569
   }
775
   }
570
}
776
}
571
 
777
 
572
static void 	Quartz_NewPage(R_GE_gcontext *gc,
778
static void 	Quartz_NewPage(R_GE_gcontext *gc,
573
			       NewDevDesc *dd)
779
			       NewDevDesc *dd)
574
{
780
{
575
    QuartzDesc *xd = (QuartzDesc*)dd->deviceSpecific;
781
    QuartzDesc *xd = (QuartzDesc*)dd->deviceSpecific;
576
    CGPoint origin = {0.0, 0.0};
782
    CGPoint origin = {0.0, 0.0};
577
    CGSize  size;
783
    CGSize  size;
578
    CGRect area;
784
    CGRect area;
579
 
785
 
580
    size.width = xd->windowWidth;
786
    size.width = xd->windowWidth;
581
    size.height = xd->windowHeight;
787
    size.height = xd->windowHeight;
582
 
788
 
583
    area.origin = origin;
789
    area.origin = origin;
584
    area.size = size;
790
    area.size = size;
585
 
791
 
586
    if(gc->fill == NA_INTEGER)
792
    if(gc->fill == NA_INTEGER)
587
      gc->fill = R_RGB(255, 255, 255);
793
      gc->fill = R_RGB(255, 255, 255);
588
      
794
      
589
    Quartz_SetFill(gc->fill, gc->gamma, dd);
795
    Quartz_SetFill(gc->fill, gc->gamma, dd);
590
 
796
 
591
    CGContextFillRect( GetContext(xd), area);
797
    CGContextFillRect( GetContext(xd), area);
592
    CGContextFlush( GetContext(xd) );   /* we need to flash it just now */
798
    CGContextFlush( GetContext(xd) );   /* we need to flash it just now */
593
 
799
 
594
}
800
}
595
 
801
 
596
static void 	Quartz_Clip(double x0, double x1, double y0, double y1,
802
static void 	Quartz_Clip(double x0, double x1, double y0, double y1,
597
		     	NewDevDesc *dd)
803
		     	NewDevDesc *dd)
598
{
804
{
599
 return;
805
 return;
600
}
806
}
601
 
807
 
602
static double 	Quartz_StrWidth(char *str, 
808
static double 	Quartz_StrWidth(char *str, 
603
				R_GE_gcontext *gc,
809
				R_GE_gcontext *gc,
604
				NewDevDesc *dd)
810
				NewDevDesc *dd)
605
{
811
{
606
    QuartzDesc *xd = (QuartzDesc*)dd->deviceSpecific;
812
    QuartzDesc *xd = (QuartzDesc*)dd->deviceSpecific;
607
    CGPoint position;
813
    CGPoint position;
608
 
814
 
609
    CGContextSaveGState( GetContext(xd) );
815
    CGContextSaveGState( GetContext(xd) );
610
    CGContextTranslateCTM( GetContext(xd), 0, 0 );
816
    CGContextTranslateCTM( GetContext(xd), 0, 0 );
611
 
817
 
612
    CGContextScaleCTM( GetContext(xd), -1, 1);
818
    CGContextScaleCTM( GetContext(xd), -1, 1);
613
 
819
 
614
    CGContextRotateCTM( GetContext(xd), -1.0 * 3.1416);
820
    CGContextRotateCTM( GetContext(xd), -1.0 * 3.1416);
615
 
821
 
616
    CGContextSetTextDrawingMode( GetContext(xd), kCGTextInvisible );
822
    CGContextSetTextDrawingMode( GetContext(xd), kCGTextInvisible );
617
 
823
 
618
    Quartz_SetFont(gc->fontface, gc->cex,  gc->ps, dd);
824
    Quartz_SetFont(gc->fontface, gc->cex,  gc->ps, dd);
619
 
825
 
620
    CGContextShowTextAtPoint( GetContext(xd), 0, 0, str, strlen(str) );
826
    CGContextShowTextAtPoint( GetContext(xd), 0, 0, str, strlen(str) );
621
 
827
 
622
    position = CGContextGetTextPosition( GetContext(xd) );
828
    position = CGContextGetTextPosition( GetContext(xd) );
623
 
829
 
624
    CGContextRestoreGState( GetContext(xd) );
830
    CGContextRestoreGState( GetContext(xd) );
625
    return(position.x);
831
    return(position.x);
626
}
832
}
627
 
833
 
628
 
834
 
629
 
835
 
-
 
836
/* This new version of Quartz_SetFont handles correctly the unicode encoding of
-
 
837
   the Symbol font under Panther
-
 
838
 */
630
 
839
 
631
static void Quartz_SetFont(int style,  double cex, double ps, NewDevDesc *dd)
840
static void Quartz_SetFont(int style,  double cex, double ps, NewDevDesc *dd)
632
{
841
{
633
    QuartzDesc *xd = (QuartzDesc*)dd->deviceSpecific;
842
    QuartzDesc *xd = (QuartzDesc*)dd->deviceSpecific;
634
    int size = cex * ps + 0.5;
843
    int size = cex * ps + 0.5;
635
    FMFontFamily CurrFontId;
844
    FMFontFamily CurrFontId;
636
    GrafPtr 	savePort;
845
    GrafPtr 	savePort;
637
    Str255	CurrFontName;
846
    Str255	CurrFontName;
638
    char	CurrFont[256];
847
    char	CurrFont[256];
639
    
848
    
640
    GetPort(&savePort);
849
    GetPort(&savePort);
641
    SetPortWindowPort(xd->window);
850
    SetPortWindowPort(xd->window);
642
    
851
    
643
    switch(style){
852
    switch(style){
644
     case 5:
853
     case 5:
645
      strcpy(CurrFont,"Symbol");
854
      strcpy(CurrFont,"Symbol");
-
 
855
	  CGContextSelectFont( GetContext(xd), CurrFont, size,kCGEncodingFontSpecific);
646
     break;
856
     break;
647
 
857
 
648
     default:
858
     default:
649
        if(xd->family)
859
        if(xd->family)
650
            strcpy(CurrFont,xd->family);
860
            strcpy(CurrFont,xd->family);
651
        else
861
        else
652
            strcpy(CurrFont,"Helvetica");
862
            strcpy(CurrFont,"Helvetica");
-
 
863
		    CGContextSelectFont( GetContext(xd), CurrFont, size, kCGEncodingMacRoman);	
653
     break;
864
     break;
654
    }
865
    }
655
 
866
 
-
 
867
/* This is needed for test only purposes 
-
 
868
    if(strcmp(CurrFont,"Symbol")==0)
656
    CGContextSelectFont( GetContext(xd), CurrFont, size, kCGEncodingMacRoman);
869
     CGContextSelectFont( GetContext(xd), CurrFont, size, kCGEncodingFontSpecific);
-
 
870
*/
657
    CopyCStringToPascal(CurrFont,CurrFontName);
871
    CopyCStringToPascal(CurrFont,CurrFontName);
658
    GetFNum(CurrFontName, &CurrFontId);
872
    GetFNum(CurrFontName, &CurrFontId);
659
    TextSize(size);
873
    TextSize(size);
660
    TextFont(CurrFontId);
874
    TextFont(CurrFontId);
661
    SetPort(savePort);
875
    SetPort(savePort);
662
}
876
}
663
 
877
 
664
 
878
 
-
 
879
 
-
 
880
Boolean IsThisASymbol(unsigned char c);
-
 
881
Boolean IsThisASymbol(unsigned char c){
-
 
882
 int i;
-
 
883
 for(i=0; i <  MAX_NON_SYMBS; i++){
-
 
884
  if(c == NotSymbols[i])
-
 
885
   return(false);
-
 
886
  }
-
 
887
     
-
 
888
  return(true); 
-
 
889
}
-
 
890
 
-
 
891
/* This new version of Quartz_Text handles correctly the symbol font under Panther */
-
 
892
 
-
 
893
 
665
static void 	Quartz_Text(double x, double y, char *str,
894
static void 	Quartz_Text(double x, double y, char *str,
666
			    double rot, double hadj, 
895
			    double rot, double hadj, 
667
			    R_GE_gcontext *gc,
896
			    R_GE_gcontext *gc,
668
			    NewDevDesc *dd)
897
			    NewDevDesc *dd)
669
{
898
{
670
    int len,i;
899
    int len,i;
671
    char *buf=NULL;
900
    char *buf=NULL;
-
 
901
	char symbuf;
672
    unsigned char tmp;
902
    unsigned char tmp;
673
    QuartzDesc *xd = (QuartzDesc*)dd->deviceSpecific;
903
    QuartzDesc *xd = (QuartzDesc*)dd->deviceSpecific;
674
 
904
	 
675
    CGContextSaveGState( GetContext(xd) );
905
    CGContextSaveGState( GetContext(xd) );
676
    CGContextTranslateCTM( GetContext(xd), x, y );
906
    CGContextTranslateCTM( GetContext(xd), x, y );
677
 
907
 
678
    CGContextScaleCTM( GetContext(xd) , -1, 1);
908
    CGContextScaleCTM( GetContext(xd) , -1, 1);
679
 
909
 
680
    CGContextRotateCTM( GetContext(xd) , (-1.0  + 2*rot/360)  * 3.1416);
910
    CGContextRotateCTM( GetContext(xd) , (-1.0  + 2*rot/360)  * 3.1416);
681
 
911
 
682
    Quartz_SetStroke( gc->col, gc->gamma, dd);
912
    Quartz_SetStroke( gc->col, gc->gamma, dd);
683
 
913
 
684
    CGContextSetTextDrawingMode( GetContext(xd), kCGTextFill );
914
    CGContextSetTextDrawingMode( GetContext(xd), kCGTextFill );
685
    Quartz_SetFill(gc->col, gc->gamma, dd);
915
    Quartz_SetFill(gc->col, gc->gamma, dd);
686
    Quartz_SetFont(gc->fontface, gc->cex,  gc->ps, dd);
916
    Quartz_SetFont(gc->fontface, gc->cex,  gc->ps, dd);
687
    len = strlen(str);
917
    len = strlen(str);
688
 
918
 
689
    if(gc->fontface == 5)
919
    if( (gc->fontface == 5) && (len==1) ){
-
 
920
	   tmp = (unsigned char)str[0];
-
 
921
       if(tmp>31)
-
 
922
        symbuf = (char)Lat2Uni[tmp-31-1];
-
 
923
	   else
-
 
924
	    symbuf = str[0];
-
 
925
       if( !IsThisASymbol(tmp) ){
-
 
926
		 Quartz_SetFont(-1, gc->cex,  gc->ps, dd);
-
 
927
		 symbuf = str[0];
-
 
928
       }
690
     CGContextShowTextAtPoint( GetContext(xd), 0, 0, str, strlen(str) );
929
     CGContextShowTextAtPoint( GetContext(xd), 0, 0, &symbuf, len );
691
    else {
930
     } else {
692
     if( (buf = malloc(len)) != NULL){
931
     if( (buf = malloc(len)) != NULL){
693
      for(i=0;i <len;i++){
932
      for(i=0;i <len;i++){
694
        tmp = (unsigned char)str[i];
933
        tmp = (unsigned char)str[i];
695
      if(tmp>127)
934
      if(tmp>127)
696
       buf[i] = (char)Lat2Mac[tmp-127-1];
935
       buf[i] = (char)Lat2Mac[tmp-127-1];
697
      else
936
      else
698
       buf[i] = str[i]; 
937
       buf[i] = str[i]; 
699
      }
938
      }
700
     CGContextShowTextAtPoint( GetContext(xd), 0, 0, buf, len );
939
     CGContextShowTextAtPoint( GetContext(xd), 0, 0, buf, len );
701
     free(buf);
940
     free(buf);
702
     }  
941
     }  
703
    }
942
    }
704
    CGContextRestoreGState( GetContext(xd) );
943
    CGContextRestoreGState( GetContext(xd) );
705
}
944
}
706
 
945
 
707
 
946
 
-
 
947
 
708
static void 	Quartz_Rect(double x0, double y0, double x1, double y1,
948
static void 	Quartz_Rect(double x0, double y0, double x1, double y1,
709
			    R_GE_gcontext *gc,
949
			    R_GE_gcontext *gc,
710
			    NewDevDesc *dd)
950
			    NewDevDesc *dd)
711
{
951
{
712
    QuartzDesc *xd = (QuartzDesc*)dd->deviceSpecific;
952
    QuartzDesc *xd = (QuartzDesc*)dd->deviceSpecific;
713
	CGRect rect;
953
	CGRect rect;
714
    CGPoint origin;
954
    CGPoint origin;
715
    CGSize  size;
955
    CGSize  size;
716
 
956
 
717
    origin.x = x0;
957
    origin.x = x0;
718
    origin.y = y0;
958
    origin.y = y0;
719
 
959
 
720
    size.width = x1-x0;
960
    size.width = x1-x0;
721
    size.height = y1-y0;
961
    size.height = y1-y0;
722
 
962
 
723
    rect.size = size;
963
    rect.size = size;
724
    rect.origin = origin;
964
    rect.origin = origin;
725
 
965
 
726
    CGContextSaveGState( GetContext(xd) );
966
    CGContextSaveGState( GetContext(xd) );
727
 
967
 
728
    Quartz_SetLineWidth(gc->lwd, dd);
968
    Quartz_SetLineWidth(gc->lwd, dd);
729
    Quartz_SetLineDash(gc->lty, gc->lwd, dd);
969
    Quartz_SetLineDash(gc->lty, gc->lwd, dd);
730
 
970
 
731
    Quartz_SetFill( gc->fill, gc->gamma, dd);
971
    Quartz_SetFill( gc->fill, gc->gamma, dd);
732
    CGContextFillRect( GetContext(xd), rect);
972
    CGContextFillRect( GetContext(xd), rect);
733
 
973
 
734
    Quartz_SetStroke( gc->col, gc->gamma, dd);
974
    Quartz_SetStroke( gc->col, gc->gamma, dd);
735
    CGContextStrokeRect( GetContext(xd), rect);
975
    CGContextStrokeRect( GetContext(xd), rect);
736
 
976
 
737
    CGContextRestoreGState( GetContext(xd) );
977
    CGContextRestoreGState( GetContext(xd) );
738
 
978
 
739
 
979
 
740
}
980
}
741
 
981
 
742
static void 	Quartz_Circle(double x, double y, double r,
982
static void 	Quartz_Circle(double x, double y, double r,
743
			      R_GE_gcontext *gc,
983
			      R_GE_gcontext *gc,
744
			      NewDevDesc *dd)
984
			      NewDevDesc *dd)
745
{
985
{
746
    QuartzDesc *xd = (QuartzDesc*)dd->deviceSpecific;
986
    QuartzDesc *xd = (QuartzDesc*)dd->deviceSpecific;
747
 
987
 
748
    CGContextSaveGState( GetContext(xd) );
988
    CGContextSaveGState( GetContext(xd) );
749
 
989
 
750
 
990
 
751
    CGContextBeginPath( GetContext(xd) );
991
    CGContextBeginPath( GetContext(xd) );
752
 
992
 
753
    Quartz_SetLineWidth(gc->lwd, dd);
993
    Quartz_SetLineWidth(gc->lwd, dd);
754
    Quartz_SetLineDash(gc->lty, gc->lwd, dd);
994
    Quartz_SetLineDash(gc->lty, gc->lwd, dd);
755
 
995
 
756
    CGContextAddArc( GetContext(xd), (float)x , (float)y, (float)r, 3.141592654 * 2.0, 0.0, 0);
996
    CGContextAddArc( GetContext(xd), (float)x , (float)y, (float)r, 3.141592654 * 2.0, 0.0, 0);
757
    Quartz_SetFill( gc->fill, gc->gamma, dd);
997
    Quartz_SetFill( gc->fill, gc->gamma, dd);
758
    CGContextFillPath( GetContext(xd) );
998
    CGContextFillPath( GetContext(xd) );
759
 
999
 
760
    Quartz_SetStroke( gc->col, gc->gamma, dd);
1000
    Quartz_SetStroke( gc->col, gc->gamma, dd);
761
    CGContextAddArc( GetContext(xd), (float)x , (float)y, (float)r, 3.141592654 * 2.0, 0.0, 0);
1001
    CGContextAddArc( GetContext(xd), (float)x , (float)y, (float)r, 3.141592654 * 2.0, 0.0, 0);
762
    CGContextStrokePath( GetContext(xd) );
1002
    CGContextStrokePath( GetContext(xd) );
763
 
1003
 
764
 
1004
 
765
    CGContextRestoreGState( GetContext(xd) );
1005
    CGContextRestoreGState( GetContext(xd) );
766
 
1006
 
767
}
1007
}
768
 
1008
 
769
 
1009
 
770
static void 	Quartz_Line(double x1, double y1, double x2, double y2,
1010
static void 	Quartz_Line(double x1, double y1, double x2, double y2,
771
			    R_GE_gcontext *gc,
1011
			    R_GE_gcontext *gc,
772
			    NewDevDesc *dd)
1012
			    NewDevDesc *dd)
773
{
1013
{
774
    QuartzDesc *xd = (QuartzDesc*)dd->deviceSpecific;
1014
    QuartzDesc *xd = (QuartzDesc*)dd->deviceSpecific;
775
    CGPoint lines[ 2 ];
1015
    CGPoint lines[ 2 ];
776
    Rect rect;
1016
    Rect rect;
777
 
1017
 
778
    CGContextSaveGState( GetContext(xd) );
1018
    CGContextSaveGState( GetContext(xd) );
779
 
1019
 
780
 
1020
 
781
    CGContextBeginPath( GetContext(xd) );
1021
    CGContextBeginPath( GetContext(xd) );
782
 
1022
 
783
    lines[0].x = (float)x1;
1023
    lines[0].x = (float)x1;
784
    lines[0].y = (float)y1;
1024
    lines[0].y = (float)y1;
785
    lines[1].x = (float)x2;
1025
    lines[1].x = (float)x2;
786
    lines[1].y = (float)y2;
1026
    lines[1].y = (float)y2;
787
 
1027
 
788
 
1028
 
789
    Quartz_SetLineWidth(gc->lwd,  dd);
1029
    Quartz_SetLineWidth(gc->lwd,  dd);
790
    Quartz_SetLineDash(gc->lty, gc->lwd, dd);
1030
    Quartz_SetLineDash(gc->lty, gc->lwd, dd);
791
 
1031
 
792
    CGContextAddLines( GetContext(xd), &lines[0], 2 );
1032
    CGContextAddLines( GetContext(xd), &lines[0], 2 );
793
 
1033
 
794
    Quartz_SetStroke( gc->col, gc->gamma,  dd);
1034
    Quartz_SetStroke( gc->col, gc->gamma,  dd);
795
 
1035
 
796
    CGContextStrokePath( GetContext(xd) );
1036
    CGContextStrokePath( GetContext(xd) );
797
 
1037
 
798
    CGContextRestoreGState( GetContext(xd) );
1038
    CGContextRestoreGState( GetContext(xd) );
799
 
1039
 
800
}
1040
}
801
 
1041
 
802
 
1042
 
803
static void 	Quartz_Polyline(int n, double *x, double *y,
1043
static void 	Quartz_Polyline(int n, double *x, double *y,
804
				R_GE_gcontext *gc,
1044
				R_GE_gcontext *gc,
805
				NewDevDesc *dd)
1045
				NewDevDesc *dd)
806
{
1046
{
807
  	CGPoint *lines;
1047
  	CGPoint *lines;
808
    int	i;
1048
    int	i;
809
    CGrafPtr savedPort, port;
1049
    CGrafPtr savedPort, port;
810
    QuartzDesc *xd = (QuartzDesc*)dd->deviceSpecific;
1050
    QuartzDesc *xd = (QuartzDesc*)dd->deviceSpecific;
811
 
1051
 
812
    lines = (CGPoint *)malloc(sizeof(CGPoint)*n);
1052
    lines = (CGPoint *)malloc(sizeof(CGPoint)*n);
813
 
1053
 
814
    if(lines == NULL)
1054
    if(lines == NULL)
815
     return;
1055
     return;
816
 
1056
 
817
    for (i = 0; i < n; i++) {
1057
    for (i = 0; i < n; i++) {
818
	  lines[i].x = (float)x[i];
1058
	  lines[i].x = (float)x[i];
819
	  lines[i].y = (float)y[i];
1059
	  lines[i].y = (float)y[i];
820
	 }
1060
	 }
821
 
1061
 
822
 
1062
 
823
    CGContextSaveGState( GetContext(xd) );
1063
    CGContextSaveGState( GetContext(xd) );
824
 
1064
 
825
    Quartz_SetLineWidth(gc->lwd,  dd);
1065
    Quartz_SetLineWidth(gc->lwd,  dd);
826
    Quartz_SetLineDash(gc->lty, gc->lwd,  dd);
1066
    Quartz_SetLineDash(gc->lty, gc->lwd,  dd);
827
 
1067
 
828
    CGContextBeginPath( GetContext(xd) );
1068
    CGContextBeginPath( GetContext(xd) );
829
    CGContextAddLines( GetContext(xd), &lines[0], n );
1069
    CGContextAddLines( GetContext(xd), &lines[0], n );
830
    Quartz_SetStroke( gc->col, gc->gamma, dd);
1070
    Quartz_SetStroke( gc->col, gc->gamma, dd);
831
    CGContextStrokePath( GetContext(xd) );
1071
    CGContextStrokePath( GetContext(xd) );
832
 
1072
 
833
    CGContextRestoreGState( GetContext(xd) );
1073
    CGContextRestoreGState( GetContext(xd) );
834
 
1074
 
835
}
1075
}
836
 
1076
 
837
 
1077
 
838
 
1078
 
839
static void Quartz_SetLineDash(int newlty, double lwd, NewDevDesc *dd)
1079
static void Quartz_SetLineDash(int newlty, double lwd, NewDevDesc *dd)
840
{
1080
{
841
    QuartzDesc *xd = (QuartzDesc*)dd->deviceSpecific;
1081
    QuartzDesc *xd = (QuartzDesc*)dd->deviceSpecific;
842
    float dashlist[8];
1082
    float dashlist[8];
843
    int i, ndash = 0;
1083
    int i, ndash = 0;
844
    
1084
    
845
    lwd *= 0.75;  /* kludge from postscript/pdf */
1085
    lwd *= 0.75;  /* kludge from postscript/pdf */
846
    for(i = 0; i < 8 && newlty & 15 ; i++) {
1086
    for(i = 0; i < 8 && newlty & 15 ; i++) {
847
	dashlist[ndash++] = (lwd >= 1 ? lwd: 1) * (newlty & 15);
1087
	dashlist[ndash++] = (lwd >= 1 ? lwd: 1) * (newlty & 15);
848
	newlty = newlty >> 4;
1088
	newlty = newlty >> 4;
849
    }
1089
    }
850
    CGContextSetLineDash( GetContext(xd), 0, dashlist, ndash);
1090
    CGContextSetLineDash( GetContext(xd), 0, dashlist, ndash);
851
    xd->lineType = newlty;
1091
    xd->lineType = newlty;
852
}
1092
}
853
 
1093
 
854
 
1094
 
855
static void Quartz_SetLineWidth(double lwd, NewDevDesc *dd)
1095
static void Quartz_SetLineWidth(double lwd, NewDevDesc *dd)
856
{
1096
{
857
 	QuartzDesc *xd = (QuartzDesc*)dd->deviceSpecific;
1097
 	QuartzDesc *xd = (QuartzDesc*)dd->deviceSpecific;
858
 
1098
 
859
	if(lwd < 1)
1099
	if(lwd < 1)
860
	 lwd=1;
1100
	 lwd=1;
861
 
1101
 
862
 	xd->lineWidth = lwd;
1102
 	xd->lineWidth = lwd;
863
 
1103
 
864
 
1104
 
865
    CGContextSetLineWidth( GetContext(xd), lwd );
1105
    CGContextSetLineWidth( GetContext(xd), lwd );
866
 
1106
 
867
}
1107
}
868
 
1108
 
869
 
1109
 
870
 
1110
 
871
static void Quartz_SetStroke(int color, double gamma, NewDevDesc *dd)
1111
static void Quartz_SetStroke(int color, double gamma, NewDevDesc *dd)
872
{
1112
{
873
    QuartzDesc *xd = (QuartzDesc*)dd->deviceSpecific;
1113
    QuartzDesc *xd = (QuartzDesc*)dd->deviceSpecific;
874
    float alpha = 1.0;
1114
    float alpha = 1.0;
875
 
1115
 
876
 	xd->color = color;
1116
 	xd->color = color;
877
 
1117
 
878
	if(color == NA_INTEGER)
1118
	if(color == NA_INTEGER)
879
	 alpha = 0.0;
1119
	 alpha = 0.0;
880
 
1120
 
881
    CGContextSetRGBStrokeColor( GetContext(xd), (float)R_RED(color)/255.0, (float)R_GREEN(color)/255.0, (float)R_BLUE(color)/255.0, alpha);
1121
    CGContextSetRGBStrokeColor( GetContext(xd), (float)R_RED(color)/255.0, (float)R_GREEN(color)/255.0, (float)R_BLUE(color)/255.0, alpha);
882
 
1122
 
883
}
1123
}
884
 
1124
 
885
static void Quartz_SetFill(int fill, double gamma, NewDevDesc *dd)
1125
static void Quartz_SetFill(int fill, double gamma, NewDevDesc *dd)
886
{
1126
{
887
    QuartzDesc *xd = (QuartzDesc*)dd->deviceSpecific;
1127
    QuartzDesc *xd = (QuartzDesc*)dd->deviceSpecific;
888
    float alpha = 1.0;
1128
    float alpha = 1.0;
889
 
1129
 
890
    xd->fill = fill;
1130
    xd->fill = fill;
891
 
1131
 
892
 	if(fill == NA_INTEGER)
1132
 	if(fill == NA_INTEGER)
893
 	 alpha = 0.0;
1133
 	 alpha = 0.0;
894
 
1134
 
895
    CGContextSetRGBFillColor( GetContext(xd), (float)R_RED(fill)/255.0, (float)R_GREEN(fill)/255.0, (float)R_BLUE(fill)/255.0, alpha);
1135
    CGContextSetRGBFillColor( GetContext(xd), (float)R_RED(fill)/255.0, (float)R_GREEN(fill)/255.0, (float)R_BLUE(fill)/255.0, alpha);
896
 
1136
 
897
}
1137
}
898
 
1138
 
899
static void 	Quartz_Polygon(int n, double *x, double *y, 
1139
static void 	Quartz_Polygon(int n, double *x, double *y, 
900
			       R_GE_gcontext *gc,
1140
			       R_GE_gcontext *gc,
901
			       NewDevDesc *dd)
1141
			       NewDevDesc *dd)
902
{
1142
{
903
   int	i;
1143
   int	i;
904
   QuartzDesc *xd = (QuartzDesc*)dd->deviceSpecific;
1144
   QuartzDesc *xd = (QuartzDesc*)dd->deviceSpecific;
905
   CGPoint *lines;
1145
   CGPoint *lines;
906
 
1146
 
907
 
1147
 
908
   CGContextSaveGState( GetContext(xd) );
1148
   CGContextSaveGState( GetContext(xd) );
909
 
1149
 
910
 
1150
 
911
   CGContextBeginPath( GetContext(xd) );
1151
   CGContextBeginPath( GetContext(xd) );
912
   Quartz_SetLineWidth(gc->lwd, dd);
1152
   Quartz_SetLineWidth(gc->lwd, dd);
913
   Quartz_SetLineDash(gc->lty,  gc->lwd, dd);
1153
   Quartz_SetLineDash(gc->lty,  gc->lwd, dd);
914
 
1154
 
915
 
1155
 
916
    lines = (CGPoint *)malloc(sizeof(CGPoint)*(n+1));
1156
    lines = (CGPoint *)malloc(sizeof(CGPoint)*(n+1));
917
 
1157
 
918
    if(lines == NULL)
1158
    if(lines == NULL)
919
     return;
1159
     return;
920
 
1160
 
921
    for (i = 0; i < n; i++) {
1161
    for (i = 0; i < n; i++) {
922
	  lines[i].x = (float)x[i];
1162
	  lines[i].x = (float)x[i];
923
	  lines[i].y = (float)y[i];
1163
	  lines[i].y = (float)y[i];
924
    }
1164
    }
925
    lines[n].x = (float)x[0];
1165
    lines[n].x = (float)x[0];
926
    lines[n].y = (float)y[0];
1166
    lines[n].y = (float)y[0];
927
 
1167
 
928
    CGContextAddLines( GetContext(xd), &lines[0], n+1 );
1168
    CGContextAddLines( GetContext(xd), &lines[0], n+1 );
929
    Quartz_SetFill( gc->fill, gc->gamma, dd);
1169
    Quartz_SetFill( gc->fill, gc->gamma, dd);
930
    CGContextFillPath( GetContext(xd) );
1170
    CGContextFillPath( GetContext(xd) );
931
 
1171
 
932
    CGContextAddLines( GetContext(xd), &lines[0], n+1 );
1172
    CGContextAddLines( GetContext(xd), &lines[0], n+1 );
933
    Quartz_SetStroke( gc->col, gc->gamma,  dd);
1173
    Quartz_SetStroke( gc->col, gc->gamma,  dd);
934
    CGContextStrokePath( GetContext(xd) );
1174
    CGContextStrokePath( GetContext(xd) );
935
 
1175
 
936
    CGContextRestoreGState( GetContext(xd) );
1176
    CGContextRestoreGState( GetContext(xd) );
937
 
1177
 
938
}
1178
}
939
 
1179
 
940
static Rboolean Quartz_Locator(double *x, double *y, NewDevDesc *dd)
1180
static Rboolean Quartz_Locator(double *x, double *y, NewDevDesc *dd)
941
{
1181
{
942
    EventRecord event;
1182
    EventRecord event;
943
    SInt16 key;
1183
    SInt16 key;
944
    Boolean gotEvent;
1184
    Boolean gotEvent;
945
    Boolean mouseClick = false;
1185
    Boolean mouseClick = false;
946
    Point myPoint;
1186
    Point myPoint;
947
    WindowPtr window;
1187
    WindowPtr window;
948
    SInt16 partCode;
1188
    SInt16 partCode;
949
    GrafPtr savePort;
1189
    GrafPtr savePort;
950
    Cursor		arrow ;
1190
    Cursor		arrow ;
951
    QuartzDesc *xd = (QuartzDesc*)dd->deviceSpecific;
1191
    QuartzDesc *xd = (QuartzDesc*)dd->deviceSpecific;
952
 
1192
 
953
    GetPort(&savePort);
1193
    GetPort(&savePort);
954
 
1194
 
955
    SetPortWindowPort(xd->window);
1195
    SetPortWindowPort(xd->window);
956
    SetCursor( GetQDGlobalsArrow ( & arrow ) ) ;
1196
    SetCursor( GetQDGlobalsArrow ( & arrow ) ) ;
957
 
1197
 
958
 
1198
 
959
    while(!mouseClick) {
1199
    while(!mouseClick) {
960
	
1200
	
961
    
1201
    
962
	gotEvent = WaitNextEvent( everyEvent, &event, 0, nil);
1202
	gotEvent = WaitNextEvent( everyEvent, &event, 0, nil);
963
 
1203
 
964
   
1204
   
965
	if (event.what == mouseDown) {
1205
	if (event.what == mouseDown) {
966
	    partCode = FindWindow(event.where, &window);
1206
	    partCode = FindWindow(event.where, &window);
967
	    if ((window == (xd->window)) && (partCode == inContent)) {
1207
	    if ((window == (xd->window)) && (partCode == inContent)) {
968
		myPoint = event.where;
1208
		myPoint = event.where;
969
		GlobalToLocal(&myPoint);
1209
		GlobalToLocal(&myPoint);
970
		*x = (double)(myPoint.h);
1210
		*x = (double)(myPoint.h);
971
		*y = (double)(myPoint.v);
1211
		*y = (double)(myPoint.v);
972
		mouseClick = true;
1212
		mouseClick = true;
973
	    }
1213
	    }
974
 
1214
 
975
	}
1215
	}
976
 
1216
 
977
	if (event.what == keyDown) {
1217
	if (event.what == keyDown) {
978
	    key = (event.message & charCodeMask);
1218
	    key = (event.message & charCodeMask);
979
	    if (key == 0x0D){
1219
	    if (key == 0x0D){
980
		SetPort(savePort);
1220
		SetPort(savePort);
981
		return FALSE;
1221
		return FALSE;
982
	    }
1222
	    }
983
	}
1223
	}
984
    }
1224
    }
985
 
1225
 
986
    SetPort(savePort);
1226
    SetPort(savePort);
987
    return TRUE;
1227
    return TRUE;
988
}
1228
}
989
 
1229
 
990
static void 	Quartz_Mode(int mode, NewDevDesc *dd)
1230
static void 	Quartz_Mode(int mode, NewDevDesc *dd)
991
{
1231
{
992
  QuartzDesc *xd = (QuartzDesc*)dd->deviceSpecific;
1232
  QuartzDesc *xd = (QuartzDesc*)dd->deviceSpecific;
993
 
1233
 
994
  if(mode == 0)
1234
  if(mode == 0)
995
   CGContextFlush( GetContext(xd) );
1235
   CGContextFlush( GetContext(xd) );
996
}
1236
}
997
 
1237
 
998
static void 	Quartz_Hold(NewDevDesc *dd)
1238
static void 	Quartz_Hold(NewDevDesc *dd)
999
{
1239
{
1000
 return;
1240
 return;
1001
}
1241
}
1002
 
1242
 
-
 
1243
#if !defined(FixedToFloat)
1003
#define FixedToFloat(a)	((float)(a) / fixed1)
1244
# define FixedToFloat(a)	((float)(a) / fixed1)
1004
#define FloatToFixed(a)	((Fixed)((float) (a) * fixed1))
1245
# define FloatToFixed(a)	((Fixed)((float) (a) * fixed1))
-
 
1246
#endif
1005
 
1247
 
1006
static void 	Quartz_MetricInfo(int c, 
1248
static void 	Quartz_MetricInfo(int c, 
1007
				  R_GE_gcontext *gc,
1249
				  R_GE_gcontext *gc,
1008
				  double* ascent, double* descent, 
1250
				  double* ascent, double* descent, 
1009
				  double* width,
1251
				  double* width,
1010
				  NewDevDesc *dd)
1252
				  NewDevDesc *dd)
1011
{
1253
{
1012
    FMetricRec myFMetric;
1254
    FMetricRec myFMetric;
1013
    QuartzDesc *xd = (QuartzDesc *) dd-> deviceSpecific;
1255
    QuartzDesc *xd = (QuartzDesc *) dd-> deviceSpecific;
1014
    char testo[2];
1256
    char testo[2];
1015
    CGrafPtr savedPort;
1257
    CGrafPtr savedPort;
1016
    Rect bounds;
1258
    Rect bounds;
1017
    CGPoint position;
1259
    CGPoint position;
-
 
1260
	unsigned char tmp;
1018
 
1261
 
1019
    testo[0] = c;
1262
    testo[0] = c;
1020
    testo[1] = '\0';
1263
    testo[1] = '\0';
1021
 
1264
 
1022
    GetPort(&savedPort);
1265
    GetPort(&savedPort);
1023
 
1266
 
1024
    SetPort(GetWindowPort(xd->window));
1267
    SetPort(GetWindowPort(xd->window));
1025
 
1268
 
1026
    Quartz_SetFont(gc->fontface, gc->cex,  gc->ps, dd);
1269
    Quartz_SetFont(gc->fontface, gc->cex,  gc->ps, dd);
1027
 
1270
 
1028
    if(c==0){
1271
    if(c==0){
1029
        FontMetrics(&myFMetric);
1272
        FontMetrics(&myFMetric);
1030
        *ascent = xd->yscale *floor(gc->cex * gc->ps + 0.5) * FixedToFloat(myFMetric.ascent);
1273
        *ascent = xd->yscale *floor(gc->cex * gc->ps + 0.5) * FixedToFloat(myFMetric.ascent);
1031
        *descent = xd->yscale*floor(gc->cex * gc->ps + 0.5) * FixedToFloat(myFMetric.descent);
1274
        *descent = xd->yscale*floor(gc->cex * gc->ps + 0.5) * FixedToFloat(myFMetric.descent);
1032
    } else {
1275
    } else {
1033
 
1276
 
1034
    CGContextSaveGState( GetContext(xd) );
1277
    CGContextSaveGState( GetContext(xd) );
1035
    CGContextTranslateCTM( GetContext(xd), 0, 0 );
1278
    CGContextTranslateCTM( GetContext(xd), 0, 0 );
1036
    CGContextScaleCTM( GetContext(xd), -1, 1);
1279
    CGContextScaleCTM( GetContext(xd), -1, 1);
1037
    CGContextRotateCTM( GetContext(xd), -1.0 * 3.1416);
1280
    CGContextRotateCTM( GetContext(xd), -1.0 * 3.1416);
1038
    CGContextSetTextDrawingMode( GetContext(xd), kCGTextInvisible );
1281
    CGContextSetTextDrawingMode( GetContext(xd), kCGTextInvisible );
1039
    Quartz_SetFont(gc->fontface, gc->cex,  gc->ps, dd);
1282
    Quartz_SetFont(gc->fontface, gc->cex,  gc->ps, dd);
-
 
1283
	
-
 
1284
	tmp = (unsigned char)c;
-
 
1285
    if( (gc->fontface == 5) ){
-
 
1286
       if( (tmp>31) && IsThisASymbol(tmp))
-
 
1287
        testo[0] = (char)Lat2Uni[tmp-31-1];
-
 
1288
       else	
-
 
1289
		Quartz_SetFont(-1, gc->cex,  gc->ps, dd);
-
 
1290
	 } else {
-
 
1291
        if(tmp>127)
-
 
1292
         testo[0] = (char)Lat2Mac[tmp-127-1];
-
 
1293
     }	 
-
 
1294
 
1040
    CGContextShowTextAtPoint( GetContext(xd), 0, 0, testo, 1 );
1295
    CGContextShowTextAtPoint( GetContext(xd), 0, 0, testo, 1 );
-
 
1296
    
-
 
1297
	
1041
    position = CGContextGetTextPosition( GetContext(xd) );
1298
    position = CGContextGetTextPosition( GetContext(xd) );
1042
    CGContextRestoreGState( GetContext(xd) );
1299
    CGContextRestoreGState( GetContext(xd) );
1043
    
1300
    
1044
        QDTextBounds(1,testo,&bounds);
1301
        QDTextBounds(1,testo,&bounds);
1045
        *ascent = -bounds.top;
1302
        *ascent = -bounds.top;
1046
        *descent = bounds.bottom;
1303
        *descent = bounds.bottom;
1047
        *width = bounds.right - bounds.left;
1304
        *width = bounds.right - bounds.left;
1048
        *width = position.x;
1305
        *width = position.x;
1049
    }    
1306
    }    
1050
    
1307
    
1051
    SetPort(savedPort);
1308
    SetPort(savedPort);
1052
 
1309
 
1053
 
1310
 
1054
 return;
1311
 return;
1055
}
1312
}
1056
 
1313
 
1057
OSStatus QuartzEventHandler( EventHandlerCallRef inCallRef, EventRef inEvent, void* inUserData )
1314
OSStatus QuartzEventHandler( EventHandlerCallRef inCallRef, EventRef inEvent, void* inUserData )
1058
{
1315
{
1059
	OSStatus 	err = eventNotHandledErr;
1316
	OSStatus 	err = eventNotHandledErr;
1060
	UInt32		eventKind = GetEventKind( inEvent ), RWinCode, devsize;
1317
	UInt32		eventKind = GetEventKind( inEvent ), RWinCode, devsize;
1061
        int		devnum;
1318
        int		devnum;
1062
        WindowRef 	EventWindow;
1319
        WindowRef 	EventWindow;
1063
        EventRef	REvent;
1320
        EventRef	REvent;
1064
        NewDevDesc 	*dd;
1321
        NewDevDesc 	*dd;
1065
 	
1322
 	
1066
        if( GetEventClass(inEvent) != kEventClassWindow)
1323
        if( GetEventClass(inEvent) != kEventClassWindow)
1067
         return(err);
1324
         return(err);
1068
         
1325
         
1069
        GetEventParameter(inEvent, kEventParamDirectObject, typeWindowRef, NULL, sizeof(EventWindow),
1326
        GetEventParameter(inEvent, kEventParamDirectObject, typeWindowRef, NULL, sizeof(EventWindow),
1070
                                NULL, &EventWindow);
1327
                                NULL, &EventWindow);
1071
                                
1328
                                
1072
        if(GetWindowProperty(EventWindow, kRAppSignature, 'QRTZ', sizeof(int), NULL, &devnum) != noErr)
1329
        if(GetWindowProperty(EventWindow, kRAppSignature, 'QRTZ', sizeof(int), NULL, &devnum) != noErr)
1073
           return eventNotHandledErr;
1330
           return eventNotHandledErr;
1074
                                
1331
                                
1075
        switch(eventKind){
1332
        switch(eventKind){
1076
            case kEventWindowClose:
1333
            case kEventWindowClose:
1077
            {
1334
            {
1078
                KillDevice(GetDevice(devnum));
1335
                KillDevice(GetDevice(devnum));
1079
                err= noErr; 
1336
                err= noErr; 
1080
            }
1337
            }
1081
            break;
1338
            break;
1082
         
1339
         
1083
            case kEventWindowBoundsChanged:
1340
            case kEventWindowBoundsChanged:
1084
                if( (dd = ((GEDevDesc*) GetDevice(devnum))->dev) ){
1341
                if( (dd = ((GEDevDesc*) GetDevice(devnum))->dev) ){
1085
                    QuartzDesc *xd = (QuartzDesc *) dd-> deviceSpecific;
1342
                    QuartzDesc *xd = (QuartzDesc *) dd-> deviceSpecific;
1086
                    Rect portRect;
1343
                    Rect portRect;
1087
                    GetWindowPortBounds ( xd->window, & portRect ) ;
1344
                    GetWindowPortBounds ( xd->window, & portRect ) ;
1088
                    if( (xd->windowWidth != portRect.right) || (xd->windowHeight != portRect.bottom) ){
1345
                    if( (xd->windowWidth != portRect.right) || (xd->windowHeight != portRect.bottom) ){
1089
                     dd->size(&(dd->left), &(dd->right), &(dd->bottom), &(dd->top), dd);
1346
                     dd->size(&(dd->left), &(dd->right), &(dd->bottom), &(dd->top), dd);
1090
                     GEplayDisplayList((GEDevDesc*) GetDevice(devnum));      
1347
                     GEplayDisplayList((GEDevDesc*) GetDevice(devnum));      
1091
                    }  
1348
                    }  
1092
                    err = noErr;
1349
                    err = noErr;
1093
                }
1350
                }
1094
            break;
1351
            break;
1095
 
1352
 
1096
            default:
1353
            default:
1097
            break;
1354
            break;
1098
        }    
1355
        }    
1099
 	   
1356
 	   
1100
	return err;
1357
	return err;
1101
}
1358
}
1102
 
1359
 
1103
#else
1360
#else
1104
SEXP do_Quartz(SEXP call, SEXP op, SEXP args, SEXP env)
1361
SEXP do_Quartz(SEXP call, SEXP op, SEXP args, SEXP env)
1105
{
1362
{
1106
	warning("Quartz device not available on this platform\n");
1363
	warning("Quartz device not available on this platform\n");
1107
    return R_NilValue;
1364
    return R_NilValue;
1108
}
1365
}
1109
#endif  /* __APPLE_CC__  && HAVE_AQUA*/
1366
#endif  /* __APPLE_CC__  && HAVE_AQUA*/
1110
 
1367
 
1111
#endif /* __QUARTZ_DEVICE__ */
1368
#endif /* __QUARTZ_DEVICE__ */