The R Project SVN R

Rev

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

Rev 41807 Rev 42208
1
/*
1
/*
2
 *  R : A Computer Language for Statistical Data Analysis
2
 *  R : A Computer Language for Statistical Data Analysis
3
 *  Copyright (C) 1995, 1996, 1997 Robert Gentleman and Ross Ihaka
3
 *  Copyright (C) 1995, 1996, 1997 Robert Gentleman and Ross Ihaka
4
 *  Copyright (C) 1998-2007	The R Development Core Team
4
 *  Copyright (C) 1998-2007	The R Development Core Team
5
 *
5
 *
6
 *  This source code module:
6
 *  This source code module:
7
 *  Copyright (C) 1997, 1998 Paul Murrell and Ross Ihaka
7
 *  Copyright (C) 1997, 1998 Paul Murrell and Ross Ihaka
8
 *  Copyright (C) 1998-2006	The R Development Core Team
8
 *  Copyright (C) 1998-2006	The R Development Core Team
9
 *
9
 *
10
 *  This program is free software; you can redistribute it and/or modify
10
 *  This program is free software; you can redistribute it and/or modify
11
 *  it under the terms of the GNU General Public License as published by
11
 *  it under the terms of the GNU General Public License as published by
12
 *  the Free Software Foundation; either version 2 of the License, or
12
 *  the Free Software Foundation; either version 2 of the License, or
13
 *  (at your option) any later version.
13
 *  (at your option) any later version.
14
 *
14
 *
15
 *  This program is distributed in the hope that it will be useful,
15
 *  This program is distributed in the hope that it will be useful,
16
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
 *  GNU General Public License for more details.
18
 *  GNU General Public License for more details.
19
 *
19
 *
20
 *  You should have received a copy of the GNU General Public License
20
 *  You should have received a copy of the GNU General Public License
21
 *  along with this program; if not, write to the Free Software
21
 *  along with this program; if not, write to the Free Software
22
 *  Foundation, Inc., 51 Franklin Street Fifth Floor, Boston, MA 02110-1301  USA
22
 *  Foundation, Inc., 51 Franklin Street Fifth Floor, Boston, MA 02110-1301  USA
23
 */
23
 */
24
 
24
 
25
/* <UTF8-FIXME>
25
/* <UTF8-FIXME>
26
   byte-level access and use of ctype functions for symbol font
26
   byte-level access and use of ctype functions for symbol font
27
 
27
 
28
   Has encoding of symbol font hard-coded.  Not clear if this is enough.
28
   Has encoding of symbol font hard-coded.  Not clear if this is enough.
29
*/
29
*/
30
 
30
 
31
#ifdef HAVE_CONFIG_H
31
#ifdef HAVE_CONFIG_H
32
#include <config.h>
32
#include <config.h>
33
#endif
33
#endif
34
#include <Defn.h>
34
#include <Defn.h>
35
 
35
 
36
#include <ctype.h>
36
#include <ctype.h>
37
#ifdef SUPPORT_MBCS
37
#ifdef SUPPORT_MBCS
38
# include <R_ext/rlocale.h>
38
# include <R_ext/rlocale.h>
39
# include <wchar.h>
39
# include <wchar.h>
40
# include <wctype.h>
40
# include <wctype.h>
41
#endif
41
#endif
42
 
42
 
43
 
43
 
44
#include <Rmath.h>
44
#include <Rmath.h>
45
#include <Graphics.h>
45
#include <Graphics.h>
46
 
46
 
47
 
47
 
48
/*
48
/*
49
 *  TeX Math Styles
49
 *  TeX Math Styles
50
 *
50
 *
51
 *  The TeXBook, Appendix G, Page 441.
51
 *  The TeXBook, Appendix G, Page 441.
52
 *
52
 *
53
 */
53
 */
54
 
54
 
55
typedef enum {
55
typedef enum {
56
    STYLE_SS1 = 1,
56
    STYLE_SS1 = 1,
57
    STYLE_SS  = 2,
57
    STYLE_SS  = 2,
58
    STYLE_S1  = 3,
58
    STYLE_S1  = 3,
59
    STYLE_S   = 4,
59
    STYLE_S   = 4,
60
    STYLE_T1  = 5,
60
    STYLE_T1  = 5,
61
    STYLE_T   = 6,
61
    STYLE_T   = 6,
62
    STYLE_D1  = 7,
62
    STYLE_D1  = 7,
63
    STYLE_D   = 8
63
    STYLE_D   = 8
64
} STYLE;
64
} STYLE;
65
 
65
 
66
typedef struct {
66
typedef struct {
67
    unsigned int BoxColor;
67
    unsigned int BoxColor;
68
    double BaseCex;
68
    double BaseCex;
69
    double ReferenceX;
69
    double ReferenceX;
70
    double ReferenceY;
70
    double ReferenceY;
71
    double CurrentX;
71
    double CurrentX;
72
    double CurrentY;
72
    double CurrentY;
73
    double CurrentAngle;
73
    double CurrentAngle;
74
    double CosAngle;
74
    double CosAngle;
75
    double SinAngle;
75
    double SinAngle;
76
    STYLE CurrentStyle;
76
    STYLE CurrentStyle;
77
} mathContext;
77
} mathContext;
78
 
78
 
79
static GEUnit MetricUnit = GE_INCHES;
79
static GEUnit MetricUnit = GE_INCHES;
80
 
80
 
81
/* Font Definitions */
81
/* Font Definitions */
82
 
82
 
83
typedef enum {
83
typedef enum {
84
    PlainFont	   = 1,
84
    PlainFont	   = 1,
85
    BoldFont	   = 2,
85
    BoldFont	   = 2,
86
    ItalicFont	   = 3,
86
    ItalicFont	   = 3,
87
    BoldItalicFont = 4,
87
    BoldItalicFont = 4,
88
    SymbolFont	   = 5
88
    SymbolFont	   = 5
89
} FontType;
89
} FontType;
90
 
90
 
91
/*
91
/*
92
 *  Italic Correction Factor
92
 *  Italic Correction Factor
93
 *
93
 *
94
 *  The correction for a character is computed as ItalicFactor
94
 *  The correction for a character is computed as ItalicFactor
95
 *  times the height (above the baseline) of the character's
95
 *  times the height (above the baseline) of the character's
96
 *  bounding box.
96
 *  bounding box.
97
 *
97
 *
98
 */
98
 */
99
 
99
 
100
static double ItalicFactor = 0.15;
100
static double ItalicFactor = 0.15;
101
 
101
 
102
/* Drawing basics */
102
/* Drawing basics */
103
 
103
 
104
 
104
 
105
/* Convert CurrentX and CurrentY from */
105
/* Convert CurrentX and CurrentY from */
106
/* 0 angle to and CurrentAngle */
106
/* 0 angle to and CurrentAngle */
107
 
107
 
108
static double ConvertedX(mathContext *mc, GEDevDesc *dd)
108
static double ConvertedX(mathContext *mc, GEDevDesc *dd)
109
{
109
{
110
    double rotatedX = mc->ReferenceX +
110
    double rotatedX = mc->ReferenceX +
111
	(mc->CurrentX - mc->ReferenceX) * mc->CosAngle -
111
	(mc->CurrentX - mc->ReferenceX) * mc->CosAngle -
112
	(mc->CurrentY - mc->ReferenceY) * mc->SinAngle;
112
	(mc->CurrentY - mc->ReferenceY) * mc->SinAngle;
113
    return toDeviceX(rotatedX, MetricUnit, dd);
113
    return toDeviceX(rotatedX, MetricUnit, dd);
114
}
114
}
115
 
115
 
116
static double ConvertedY(mathContext *mc, GEDevDesc *dd)
116
static double ConvertedY(mathContext *mc, GEDevDesc *dd)
117
{
117
{
118
    double rotatedY = mc->ReferenceY +
118
    double rotatedY = mc->ReferenceY +
119
	(mc->CurrentY - mc->ReferenceY) * mc->CosAngle +
119
	(mc->CurrentY - mc->ReferenceY) * mc->CosAngle +
120
	(mc->CurrentX - mc->ReferenceX) * mc->SinAngle;
120
	(mc->CurrentX - mc->ReferenceX) * mc->SinAngle;
121
    return toDeviceY(rotatedY, MetricUnit, dd);
121
    return toDeviceY(rotatedY, MetricUnit, dd);
122
}
122
}
123
 
123
 
124
static void PMoveAcross(double xamount, mathContext *mc)
124
static void PMoveAcross(double xamount, mathContext *mc)
125
{
125
{
126
    mc->CurrentX += xamount;
126
    mc->CurrentX += xamount;
127
}
127
}
128
 
128
 
129
static void PMoveUp(double yamount, mathContext *mc)
129
static void PMoveUp(double yamount, mathContext *mc)
130
{
130
{
131
    mc->CurrentY += yamount;
131
    mc->CurrentY += yamount;
132
}
132
}
133
 
133
 
134
static void PMoveTo(double x, double y, mathContext *mc)
134
static void PMoveTo(double x, double y, mathContext *mc)
135
{
135
{
136
    mc->CurrentX = x;
136
    mc->CurrentX = x;
137
    mc->CurrentY = y;
137
    mc->CurrentY = y;
138
}
138
}
139
 
139
 
140
/* Basic Font Properties */
140
/* Basic Font Properties */
141
 
141
 
142
static double xHeight(R_GE_gcontext *gc, GEDevDesc *dd)
142
static double xHeight(R_GE_gcontext *gc, GEDevDesc *dd)
143
{
143
{
144
    double height, depth, width;
144
    double height, depth, width;
145
    GEMetricInfo('x', gc,
145
    GEMetricInfo('x', gc,
146
		&height, &depth, &width, dd);
146
		&height, &depth, &width, dd);
147
    return fromDeviceHeight(height, MetricUnit, dd);
147
    return fromDeviceHeight(height, MetricUnit, dd);
148
}
148
}
149
 
149
 
150
static double XHeight(R_GE_gcontext *gc, GEDevDesc *dd)
150
static double XHeight(R_GE_gcontext *gc, GEDevDesc *dd)
151
{
151
{
152
    double height, depth, width;
152
    double height, depth, width;
153
    GEMetricInfo('X', gc,
153
    GEMetricInfo('X', gc,
154
		&height, &depth, &width, dd);
154
		&height, &depth, &width, dd);
155
    return fromDeviceHeight(height, MetricUnit, dd);
155
    return fromDeviceHeight(height, MetricUnit, dd);
156
}
156
}
157
 
157
 
158
static double AxisHeight(R_GE_gcontext *gc, GEDevDesc *dd)
158
static double AxisHeight(R_GE_gcontext *gc, GEDevDesc *dd)
159
{
159
{
160
    double height, depth, width;
160
    double height, depth, width;
161
    GEMetricInfo('+', gc,
161
    GEMetricInfo('+', gc,
162
		&height, &depth, &width, dd);
162
		&height, &depth, &width, dd);
163
    return fromDeviceHeight(0.5 * height, MetricUnit, dd);
163
    return fromDeviceHeight(0.5 * height, MetricUnit, dd);
164
}
164
}
165
 
165
 
166
static double Quad(R_GE_gcontext *gc, GEDevDesc *dd)
166
static double Quad(R_GE_gcontext *gc, GEDevDesc *dd)
167
{
167
{
168
    double height, depth, width;
168
    double height, depth, width;
169
    GEMetricInfo('M', gc,
169
    GEMetricInfo('M', gc,
170
		&height, &depth, &width, dd);
170
		&height, &depth, &width, dd);
171
    return fromDeviceHeight(width, MetricUnit, dd);
171
    return fromDeviceHeight(width, MetricUnit, dd);
172
}
172
}
173
 
173
 
174
/* The height of digits */
174
/* The height of digits */
175
static double FigHeight(R_GE_gcontext *gc, GEDevDesc *dd)
175
static double FigHeight(R_GE_gcontext *gc, GEDevDesc *dd)
176
{
176
{
177
    double height, depth, width;
177
    double height, depth, width;
178
    GEMetricInfo('0', gc,
178
    GEMetricInfo('0', gc,
179
		&height, &depth, &width, dd);
179
		&height, &depth, &width, dd);
180
    return fromDeviceHeight(height, MetricUnit, dd);
180
    return fromDeviceHeight(height, MetricUnit, dd);
181
}
181
}
182
 
182
 
183
/* Depth of lower case descenders */
183
/* Depth of lower case descenders */
184
static double DescDepth(R_GE_gcontext *gc, GEDevDesc *dd)
184
static double DescDepth(R_GE_gcontext *gc, GEDevDesc *dd)
185
{
185
{
186
    double height, depth, width;
186
    double height, depth, width;
187
    GEMetricInfo('g', gc,
187
    GEMetricInfo('g', gc,
188
		&height, &depth, &width, dd);
188
		&height, &depth, &width, dd);
189
    return fromDeviceHeight(depth, MetricUnit, dd);
189
    return fromDeviceHeight(depth, MetricUnit, dd);
190
}
190
}
191
 
191
 
192
/* Thickness of rules */
192
/* Thickness of rules */
193
static double RuleThickness()
193
static double RuleThickness()
194
{
194
{
195
    return 0.015;
195
    return 0.015;
196
}
196
}
197
 
197
 
198
static double ThinSpace(R_GE_gcontext *gc, GEDevDesc *dd)
198
static double ThinSpace(R_GE_gcontext *gc, GEDevDesc *dd)
199
{
199
{
200
    double height, depth, width;
200
    double height, depth, width;
201
    static double OneSixth = 0.16666666666666666666;
201
    static double OneSixth = 0.16666666666666666666;
202
    GEMetricInfo('M', gc,
202
    GEMetricInfo('M', gc,
203
		&height, &depth, &width, dd);
203
		&height, &depth, &width, dd);
204
    return fromDeviceHeight(OneSixth * width, MetricUnit, dd);
204
    return fromDeviceHeight(OneSixth * width, MetricUnit, dd);
205
}
205
}
206
 
206
 
207
static double MediumSpace(R_GE_gcontext *gc, GEDevDesc *dd)
207
static double MediumSpace(R_GE_gcontext *gc, GEDevDesc *dd)
208
{
208
{
209
    double height, depth, width;
209
    double height, depth, width;
210
    static double TwoNinths = 0.22222222222222222222;
210
    static double TwoNinths = 0.22222222222222222222;
211
    GEMetricInfo('M', gc,
211
    GEMetricInfo('M', gc,
212
		&height, &depth, &width, dd);
212
		&height, &depth, &width, dd);
213
    return fromDeviceHeight(TwoNinths * width, MetricUnit, dd);
213
    return fromDeviceHeight(TwoNinths * width, MetricUnit, dd);
214
}
214
}
215
 
215
 
216
static double ThickSpace(R_GE_gcontext *gc, GEDevDesc *dd)
216
static double ThickSpace(R_GE_gcontext *gc, GEDevDesc *dd)
217
{
217
{
218
    double height, depth, width;
218
    double height, depth, width;
219
    static double FiveEighteenths = 0.27777777777777777777;
219
    static double FiveEighteenths = 0.27777777777777777777;
220
    GEMetricInfo('M', gc,
220
    GEMetricInfo('M', gc,
221
		&height, &depth, &width, dd);
221
		&height, &depth, &width, dd);
222
    return fromDeviceHeight(FiveEighteenths * width, MetricUnit, dd);
222
    return fromDeviceHeight(FiveEighteenths * width, MetricUnit, dd);
223
}
223
}
224
 
224
 
225
static double MuSpace(R_GE_gcontext *gc, GEDevDesc *dd)
225
static double MuSpace(R_GE_gcontext *gc, GEDevDesc *dd)
226
{
226
{
227
    double height, depth, width;
227
    double height, depth, width;
228
    static double OneEighteenth = 0.05555555555555555555;
228
    static double OneEighteenth = 0.05555555555555555555;
229
    GEMetricInfo('M', gc,
229
    GEMetricInfo('M', gc,
230
		&height, &depth, &width, dd);
230
		&height, &depth, &width, dd);
231
    return fromDeviceHeight(OneEighteenth * width, MetricUnit, dd);
231
    return fromDeviceHeight(OneEighteenth * width, MetricUnit, dd);
232
}
232
}
233
 
233
 
234
 
234
 
235
/*
235
/*
236
 *  Mathematics Layout Parameters
236
 *  Mathematics Layout Parameters
237
 *
237
 *
238
 *  The TeXBook, Appendix G, Page 447.
238
 *  The TeXBook, Appendix G, Page 447.
239
 *
239
 *
240
 *  These values are based on an inspection of TeX metafont files
240
 *  These values are based on an inspection of TeX metafont files
241
 *  together with some visual simplification.
241
 *  together with some visual simplification.
242
 *
242
 *
243
 *  Note : The values are ``optimised'' for PostScript.
243
 *  Note : The values are ``optimised'' for PostScript.
244
 *
244
 *
245
 */
245
 */
246
 
246
 
247
typedef enum {
247
typedef enum {
248
    sigma2,  sigma5,  sigma6,  sigma8,	sigma9,	 sigma10, sigma11,
248
    sigma2,  sigma5,  sigma6,  sigma8,	sigma9,	 sigma10, sigma11,
249
    sigma12, sigma13, sigma14, sigma15, sigma16, sigma17, sigma18,
249
    sigma12, sigma13, sigma14, sigma15, sigma16, sigma17, sigma18,
250
    sigma19, sigma20, sigma21, sigma22, xi8, xi9, xi10, xi11, xi12, xi13
250
    sigma19, sigma20, sigma21, sigma22, xi8, xi9, xi10, xi11, xi12, xi13
251
}
251
}
252
TEXPAR;
252
TEXPAR;
253
 
253
 
254
#define SUBS	       0.7
254
#define SUBS	       0.7
255
 
255
 
256
static double TeX(TEXPAR which, R_GE_gcontext *gc, GEDevDesc *dd)
256
static double TeX(TEXPAR which, R_GE_gcontext *gc, GEDevDesc *dd)
257
{
257
{
258
    switch(which) {
258
    switch(which) {
259
    case sigma2:  /* space */
259
    case sigma2:  /* space */
260
    case sigma5:  /* x_height */
260
    case sigma5:  /* x_height */
261
	return xHeight(gc, dd);
261
	return xHeight(gc, dd);
262
 
262
 
263
    case sigma6:  /* quad */
263
    case sigma6:  /* quad */
264
	return Quad(gc, dd);
264
	return Quad(gc, dd);
265
 
265
 
266
    case sigma8:  /* num1 */
266
    case sigma8:  /* num1 */
267
	return AxisHeight(gc, dd)
267
	return AxisHeight(gc, dd)
268
	    + 3.51 * RuleThickness()
268
	    + 3.51 * RuleThickness()
269
	    + 0.15 * XHeight(gc, dd)		/* 54/36 * 0.1 */
269
	    + 0.15 * XHeight(gc, dd)		/* 54/36 * 0.1 */
270
	    + SUBS * DescDepth(gc, dd);
270
	    + SUBS * DescDepth(gc, dd);
271
    case sigma9:  /* num2 */
271
    case sigma9:  /* num2 */
272
	return AxisHeight(gc, dd)
272
	return AxisHeight(gc, dd)
273
	    + 1.51 * RuleThickness()
273
	    + 1.51 * RuleThickness()
274
	    + 0.08333333 * XHeight(gc, dd);	/* 30/36 * 0.1 */
274
	    + 0.08333333 * XHeight(gc, dd);	/* 30/36 * 0.1 */
275
    case sigma10: /* num3 */
275
    case sigma10: /* num3 */
276
	return AxisHeight(gc, dd)
276
	return AxisHeight(gc, dd)
277
	    + 1.51 * RuleThickness()
277
	    + 1.51 * RuleThickness()
278
	    + 0.1333333 * XHeight(gc, dd);	/* 48/36 * 0.1 */
278
	    + 0.1333333 * XHeight(gc, dd);	/* 48/36 * 0.1 */
279
    case sigma11: /* denom1 */
279
    case sigma11: /* denom1 */
280
	return	- AxisHeight(gc, dd)
280
	return	- AxisHeight(gc, dd)
281
	    + 3.51 * RuleThickness()
281
	    + 3.51 * RuleThickness()
282
	    + SUBS * FigHeight(gc, dd)
282
	    + SUBS * FigHeight(gc, dd)
283
	    + 0.344444 * XHeight(gc, dd);	/* 124/36 * 0.1 */
283
	    + 0.344444 * XHeight(gc, dd);	/* 124/36 * 0.1 */
284
    case sigma12: /* denom2 */
284
    case sigma12: /* denom2 */
285
	return	- AxisHeight(gc, dd)
285
	return	- AxisHeight(gc, dd)
286
	    + 1.51 * RuleThickness()
286
	    + 1.51 * RuleThickness()
287
	    + SUBS * FigHeight(gc, dd)
287
	    + SUBS * FigHeight(gc, dd)
288
	    + 0.08333333 * XHeight(gc, dd);	/* 30/36 * 0.1 */
288
	    + 0.08333333 * XHeight(gc, dd);	/* 30/36 * 0.1 */
289
 
289
 
290
    case sigma13: /* sup1 */
290
    case sigma13: /* sup1 */
291
	return 0.95 * xHeight(gc, dd);
291
	return 0.95 * xHeight(gc, dd);
292
    case sigma14: /* sup2 */
292
    case sigma14: /* sup2 */
293
	return 0.825 * xHeight(gc, dd);
293
	return 0.825 * xHeight(gc, dd);
294
    case sigma15: /* sup3 */
294
    case sigma15: /* sup3 */
295
	return 0.7 * xHeight(gc, dd);
295
	return 0.7 * xHeight(gc, dd);
296
 
296
 
297
    case sigma16: /* sub1 */
297
    case sigma16: /* sub1 */
298
	return 0.35 * xHeight(gc, dd);
298
	return 0.35 * xHeight(gc, dd);
299
    case sigma17: /* sub2 */
299
    case sigma17: /* sub2 */
300
	return 0.45 * XHeight(gc, dd);
300
	return 0.45 * XHeight(gc, dd);
301
 
301
 
302
    case sigma18: /* sup_drop */
302
    case sigma18: /* sup_drop */
303
	return 0.3861111 * XHeight(gc, dd);
303
	return 0.3861111 * XHeight(gc, dd);
304
 
304
 
305
    case sigma19: /* sub_drop */
305
    case sigma19: /* sub_drop */
306
	return 0.05 * XHeight(gc, dd);
306
	return 0.05 * XHeight(gc, dd);
307
 
307
 
308
    case sigma20: /* delim1 */
308
    case sigma20: /* delim1 */
309
	return 2.39 * XHeight(gc, dd);
309
	return 2.39 * XHeight(gc, dd);
310
    case sigma21: /* delim2 */
310
    case sigma21: /* delim2 */
311
	return 1.01 *XHeight(gc, dd);
311
	return 1.01 *XHeight(gc, dd);
312
 
312
 
313
    case sigma22: /* axis_height */
313
    case sigma22: /* axis_height */
314
	return AxisHeight(gc, dd);
314
	return AxisHeight(gc, dd);
315
 
315
 
316
    case xi8:	  /* default_rule_thickness */
316
    case xi8:	  /* default_rule_thickness */
317
	return RuleThickness();
317
	return RuleThickness();
318
 
318
 
319
    case xi9:	  /* big_op_spacing1 */
319
    case xi9:	  /* big_op_spacing1 */
320
    case xi10:	  /* big_op_spacing2 */
320
    case xi10:	  /* big_op_spacing2 */
321
    case xi11:	  /* big_op_spacing3 */
321
    case xi11:	  /* big_op_spacing3 */
322
    case xi12:	  /* big_op_spacing4 */
322
    case xi12:	  /* big_op_spacing4 */
323
    case xi13:	  /* big_op_spacing5 */
323
    case xi13:	  /* big_op_spacing5 */
324
	return 0.15 * XHeight(gc, dd);
324
	return 0.15 * XHeight(gc, dd);
325
    default:/* never happens (enum type) */
325
    default:/* never happens (enum type) */
326
	error(_("invalid `which' in TeX")); return 0;/*-Wall*/
326
	error(_("invalid `which' in TeX")); return 0;/*-Wall*/
327
    }
327
    }
328
}
328
}
329
 
329
 
330
static STYLE GetStyle(mathContext *mc)
330
static STYLE GetStyle(mathContext *mc)
331
{
331
{
332
    return mc->CurrentStyle;
332
    return mc->CurrentStyle;
333
}
333
}
334
 
334
 
335
static void SetStyle(STYLE newstyle, mathContext *mc, R_GE_gcontext *gc)
335
static void SetStyle(STYLE newstyle, mathContext *mc, R_GE_gcontext *gc)
336
{
336
{
337
    switch (newstyle) {
337
    switch (newstyle) {
338
    case STYLE_D:
338
    case STYLE_D:
339
    case STYLE_T:
339
    case STYLE_T:
340
    case STYLE_D1:
340
    case STYLE_D1:
341
    case STYLE_T1:
341
    case STYLE_T1:
342
	gc->cex = 1.0 * mc->BaseCex;
342
	gc->cex = 1.0 * mc->BaseCex;
343
	break;
343
	break;
344
    case STYLE_S:
344
    case STYLE_S:
345
    case STYLE_S1:
345
    case STYLE_S1:
346
	gc->cex = 0.7 * mc->BaseCex;
346
	gc->cex = 0.7 * mc->BaseCex;
347
	break;
347
	break;
348
    case STYLE_SS:
348
    case STYLE_SS:
349
    case STYLE_SS1:
349
    case STYLE_SS1:
350
	gc->cex = 0.5 * mc->BaseCex;
350
	gc->cex = 0.5 * mc->BaseCex;
351
	break;
351
	break;
352
    default:
352
    default:
353
	error(_("invalid math style encountered"));
353
	error(_("invalid math style encountered"));
354
    }
354
    }
355
    mc->CurrentStyle = newstyle;
355
    mc->CurrentStyle = newstyle;
356
}
356
}
357
 
357
 
358
static void SetPrimeStyle(STYLE style, mathContext *mc, R_GE_gcontext *gc)
358
static void SetPrimeStyle(STYLE style, mathContext *mc, R_GE_gcontext *gc)
359
{
359
{
360
    switch (style) {
360
    switch (style) {
361
    case STYLE_D:
361
    case STYLE_D:
362
    case STYLE_D1:
362
    case STYLE_D1:
363
	SetStyle(STYLE_D1, mc, gc);
363
	SetStyle(STYLE_D1, mc, gc);
364
	break;
364
	break;
365
    case STYLE_T:
365
    case STYLE_T:
366
    case STYLE_T1:
366
    case STYLE_T1:
367
	SetStyle(STYLE_T1, mc, gc);
367
	SetStyle(STYLE_T1, mc, gc);
368
	break;
368
	break;
369
    case STYLE_S:
369
    case STYLE_S:
370
    case STYLE_S1:
370
    case STYLE_S1:
371
	SetStyle(STYLE_S1, mc, gc);
371
	SetStyle(STYLE_S1, mc, gc);
372
	break;
372
	break;
373
    case STYLE_SS:
373
    case STYLE_SS:
374
    case STYLE_SS1:
374
    case STYLE_SS1:
375
	SetStyle(STYLE_SS1, mc, gc);
375
	SetStyle(STYLE_SS1, mc, gc);
376
	break;
376
	break;
377
    }
377
    }
378
}
378
}
379
 
379
 
380
static void SetSupStyle(STYLE style, mathContext *mc, R_GE_gcontext *gc)
380
static void SetSupStyle(STYLE style, mathContext *mc, R_GE_gcontext *gc)
381
{
381
{
382
    switch (style) {
382
    switch (style) {
383
    case STYLE_D:
383
    case STYLE_D:
384
    case STYLE_T:
384
    case STYLE_T:
385
	SetStyle(STYLE_S, mc, gc);
385
	SetStyle(STYLE_S, mc, gc);
386
	break;
386
	break;
387
    case STYLE_D1:
387
    case STYLE_D1:
388
    case STYLE_T1:
388
    case STYLE_T1:
389
	SetStyle(STYLE_S1, mc, gc);
389
	SetStyle(STYLE_S1, mc, gc);
390
	break;
390
	break;
391
    case STYLE_S:
391
    case STYLE_S:
392
    case STYLE_SS:
392
    case STYLE_SS:
393
	SetStyle(STYLE_SS, mc, gc);
393
	SetStyle(STYLE_SS, mc, gc);
394
	break;
394
	break;
395
    case STYLE_S1:
395
    case STYLE_S1:
396
    case STYLE_SS1:
396
    case STYLE_SS1:
397
	SetStyle(STYLE_SS1, mc, gc);
397
	SetStyle(STYLE_SS1, mc, gc);
398
	break;
398
	break;
399
    }
399
    }
400
}
400
}
401
 
401
 
402
static void SetSubStyle(STYLE style, mathContext *mc, R_GE_gcontext *gc)
402
static void SetSubStyle(STYLE style, mathContext *mc, R_GE_gcontext *gc)
403
{
403
{
404
    switch (style) {
404
    switch (style) {
405
    case STYLE_D:
405
    case STYLE_D:
406
    case STYLE_T:
406
    case STYLE_T:
407
    case STYLE_D1:
407
    case STYLE_D1:
408
    case STYLE_T1:
408
    case STYLE_T1:
409
	SetStyle(STYLE_S1, mc, gc);
409
	SetStyle(STYLE_S1, mc, gc);
410
	break;
410
	break;
411
    case STYLE_S:
411
    case STYLE_S:
412
    case STYLE_SS:
412
    case STYLE_SS:
413
    case STYLE_S1:
413
    case STYLE_S1:
414
    case STYLE_SS1:
414
    case STYLE_SS1:
415
	SetStyle(STYLE_SS1, mc, gc);
415
	SetStyle(STYLE_SS1, mc, gc);
416
	break;
416
	break;
417
    }
417
    }
418
}
418
}
419
 
419
 
420
static void SetNumStyle(STYLE style, mathContext *mc, R_GE_gcontext *gc)
420
static void SetNumStyle(STYLE style, mathContext *mc, R_GE_gcontext *gc)
421
{
421
{
422
    switch (style) {
422
    switch (style) {
423
    case STYLE_D:
423
    case STYLE_D:
424
	SetStyle(STYLE_T, mc, gc);
424
	SetStyle(STYLE_T, mc, gc);
425
	break;
425
	break;
426
    case STYLE_D1:
426
    case STYLE_D1:
427
	SetStyle(STYLE_T1, mc, gc);
427
	SetStyle(STYLE_T1, mc, gc);
428
	break;
428
	break;
429
    default:
429
    default:
430
	SetSupStyle(style, mc, gc);
430
	SetSupStyle(style, mc, gc);
431
    }
431
    }
432
}
432
}
433
 
433
 
434
static void SetDenomStyle(STYLE style, mathContext *mc, R_GE_gcontext *gc)
434
static void SetDenomStyle(STYLE style, mathContext *mc, R_GE_gcontext *gc)
435
{
435
{
436
    if (style > STYLE_T)
436
    if (style > STYLE_T)
437
	SetStyle(STYLE_T1, mc, gc);
437
	SetStyle(STYLE_T1, mc, gc);
438
    else
438
    else
439
	SetSubStyle(style, mc, gc);
439
	SetSubStyle(style, mc, gc);
440
}
440
}
441
 
441
 
442
static int IsCompactStyle(STYLE style, mathContext *mc, R_GE_gcontext *gc)
442
static int IsCompactStyle(STYLE style, mathContext *mc, R_GE_gcontext *gc)
443
{
443
{
444
    switch (style) {
444
    switch (style) {
445
    case STYLE_D1:
445
    case STYLE_D1:
446
    case STYLE_T1:
446
    case STYLE_T1:
447
    case STYLE_S1:
447
    case STYLE_S1:
448
    case STYLE_SS1:
448
    case STYLE_SS1:
449
	return 1;
449
	return 1;
450
    default:
450
    default:
451
	return 0;
451
	return 0;
452
    }
452
    }
453
}
453
}
454
 
454
 
455
 
455
 
456
#ifdef max
456
#ifdef max
457
#undef max
457
#undef max
458
#endif
458
#endif
459
/* Return maximum of two doubles. */
459
/* Return maximum of two doubles. */
460
static double max(double x, double y)
460
static double max(double x, double y)
461
{
461
{
462
    if (x > y) return x;
462
    if (x > y) return x;
463
    else return y;
463
    else return y;
464
}
464
}
465
 
465
 
466
 
466
 
467
/* Bounding Boxes */
467
/* Bounding Boxes */
468
/* These including italic corrections and an */
468
/* These including italic corrections and an */
469
/* indication of whether the nucleus was simple. */
469
/* indication of whether the nucleus was simple. */
470
 
470
 
471
typedef struct {
471
typedef struct {
472
    double height;
472
    double height;
473
    double depth;
473
    double depth;
474
    double width;
474
    double width;
475
    double italic;
475
    double italic;
476
    int simple;
476
    int simple;
477
} BBOX;
477
} BBOX;
478
 
478
 
479
 
479
 
480
#define bboxHeight(bbox) bbox.height
480
#define bboxHeight(bbox) bbox.height
481
#define bboxDepth(bbox) bbox.depth
481
#define bboxDepth(bbox) bbox.depth
482
#define bboxWidth(bbox) bbox.width
482
#define bboxWidth(bbox) bbox.width
483
#define bboxItalic(bbox) bbox.italic
483
#define bboxItalic(bbox) bbox.italic
484
#define bboxSimple(bbox) bbox.simple
484
#define bboxSimple(bbox) bbox.simple
485
 
485
 
486
 
486
 
487
static BBOX MakeBBox(double height, double depth, double width)
487
static BBOX MakeBBox(double height, double depth, double width)
488
{
488
{
489
    BBOX bbox;
489
    BBOX bbox;
490
    bboxHeight(bbox) = height;
490
    bboxHeight(bbox) = height;
491
    bboxDepth(bbox)  = depth;
491
    bboxDepth(bbox)  = depth;
492
    bboxWidth(bbox)  = width;
492
    bboxWidth(bbox)  = width;
493
    bboxItalic(bbox) = 0;
493
    bboxItalic(bbox) = 0;
494
    bboxSimple(bbox) = 0;
494
    bboxSimple(bbox) = 0;
495
    return bbox;
495
    return bbox;
496
}
496
}
497
 
497
 
498
static BBOX NullBBox()
498
static BBOX NullBBox()
499
{
499
{
500
    BBOX bbox;
500
    BBOX bbox;
501
    bboxHeight(bbox) = 0;
501
    bboxHeight(bbox) = 0;
502
    bboxDepth(bbox)  = 0;
502
    bboxDepth(bbox)  = 0;
503
    bboxWidth(bbox)  = 0;
503
    bboxWidth(bbox)  = 0;
504
    bboxItalic(bbox) = 0;
504
    bboxItalic(bbox) = 0;
505
    bboxSimple(bbox) = 0;
505
    bboxSimple(bbox) = 0;
506
    return bbox;
506
    return bbox;
507
}
507
}
508
 
508
 
509
static BBOX ShiftBBox(BBOX bbox1, double shiftV)
509
static BBOX ShiftBBox(BBOX bbox1, double shiftV)
510
{
510
{
511
    bboxHeight(bbox1) = bboxHeight(bbox1) + shiftV;
511
    bboxHeight(bbox1) = bboxHeight(bbox1) + shiftV;
512
    bboxDepth(bbox1)  = bboxDepth(bbox1) - shiftV;
512
    bboxDepth(bbox1)  = bboxDepth(bbox1) - shiftV;
513
    bboxWidth(bbox1)  = bboxWidth(bbox1);
513
    bboxWidth(bbox1)  = bboxWidth(bbox1);
514
    bboxItalic(bbox1) = bboxItalic(bbox1);
514
    bboxItalic(bbox1) = bboxItalic(bbox1);
515
    bboxSimple(bbox1) = bboxSimple(bbox1);
515
    bboxSimple(bbox1) = bboxSimple(bbox1);
516
    return bbox1;
516
    return bbox1;
517
}
517
}
518
 
518
 
519
static BBOX EnlargeBBox(BBOX bbox, double deltaHeight, double deltaDepth,
519
static BBOX EnlargeBBox(BBOX bbox, double deltaHeight, double deltaDepth,
520
		      double deltaWidth)
520
		      double deltaWidth)
521
{
521
{
522
    bboxHeight(bbox) += deltaHeight;
522
    bboxHeight(bbox) += deltaHeight;
523
    bboxDepth(bbox)  += deltaDepth;
523
    bboxDepth(bbox)  += deltaDepth;
524
    bboxWidth(bbox)  += deltaWidth;
524
    bboxWidth(bbox)  += deltaWidth;
525
    return bbox;
525
    return bbox;
526
}
526
}
527
 
527
 
528
static BBOX CombineBBoxes(BBOX bbox1, BBOX bbox2)
528
static BBOX CombineBBoxes(BBOX bbox1, BBOX bbox2)
529
{
529
{
530
    bboxHeight(bbox1) = max(bboxHeight(bbox1), bboxHeight(bbox2));
530
    bboxHeight(bbox1) = max(bboxHeight(bbox1), bboxHeight(bbox2));
531
    bboxDepth(bbox1)  = max(bboxDepth(bbox1), bboxDepth(bbox2));
531
    bboxDepth(bbox1)  = max(bboxDepth(bbox1), bboxDepth(bbox2));
532
    bboxWidth(bbox1)  = bboxWidth(bbox1) + bboxWidth(bbox2);
532
    bboxWidth(bbox1)  = bboxWidth(bbox1) + bboxWidth(bbox2);
533
    bboxItalic(bbox1) = bboxItalic(bbox2);
533
    bboxItalic(bbox1) = bboxItalic(bbox2);
534
    bboxSimple(bbox1) = bboxSimple(bbox2);
534
    bboxSimple(bbox1) = bboxSimple(bbox2);
535
    return bbox1;
535
    return bbox1;
536
}
536
}
537
 
537
 
538
static BBOX CombineAlignedBBoxes(BBOX bbox1, BBOX bbox2)
538
static BBOX CombineAlignedBBoxes(BBOX bbox1, BBOX bbox2)
539
{
539
{
540
    bboxHeight(bbox1) = max(bboxHeight(bbox1), bboxHeight(bbox2));
540
    bboxHeight(bbox1) = max(bboxHeight(bbox1), bboxHeight(bbox2));
541
    bboxDepth(bbox1)  = max(bboxDepth(bbox1), bboxDepth(bbox2));
541
    bboxDepth(bbox1)  = max(bboxDepth(bbox1), bboxDepth(bbox2));
542
    bboxWidth(bbox1)  = max(bboxWidth(bbox1), bboxWidth(bbox2));
542
    bboxWidth(bbox1)  = max(bboxWidth(bbox1), bboxWidth(bbox2));
543
    bboxItalic(bbox1) = 0;
543
    bboxItalic(bbox1) = 0;
544
    bboxSimple(bbox1) = 0;
544
    bboxSimple(bbox1) = 0;
545
    return bbox1;
545
    return bbox1;
546
}
546
}
547
 
547
 
548
static BBOX CombineOffsetBBoxes(BBOX bbox1, int italic1,
548
static BBOX CombineOffsetBBoxes(BBOX bbox1, int italic1,
549
				BBOX bbox2, int italic2,
549
				BBOX bbox2, int italic2,
550
				double xoffset,
550
				double xoffset,
551
				double yoffset)
551
				double yoffset)
552
{
552
{
553
    double width1 = bboxWidth(bbox1) + (italic1 ? bboxItalic(bbox1) : 0);
553
    double width1 = bboxWidth(bbox1) + (italic1 ? bboxItalic(bbox1) : 0);
554
    double width2 = bboxWidth(bbox2) + (italic2 ? bboxItalic(bbox2) : 0);
554
    double width2 = bboxWidth(bbox2) + (italic2 ? bboxItalic(bbox2) : 0);
555
    bboxWidth(bbox1) = max(width1, width2 + xoffset);
555
    bboxWidth(bbox1) = max(width1, width2 + xoffset);
556
    bboxHeight(bbox1) = max(bboxHeight(bbox1), bboxHeight(bbox2) + yoffset);
556
    bboxHeight(bbox1) = max(bboxHeight(bbox1), bboxHeight(bbox2) + yoffset);
557
    bboxDepth(bbox1) = max(bboxDepth(bbox1), bboxDepth(bbox2) - yoffset);
557
    bboxDepth(bbox1) = max(bboxDepth(bbox1), bboxDepth(bbox2) - yoffset);
558
    bboxItalic(bbox1) = 0;
558
    bboxItalic(bbox1) = 0;
559
    bboxSimple(bbox1) = 0;
559
    bboxSimple(bbox1) = 0;
560
    return bbox1;
560
    return bbox1;
561
}
561
}
562
 
562
 
563
static double CenterShift(BBOX bbox)
563
static double CenterShift(BBOX bbox)
564
{
564
{
565
    return 0.5 * (bboxHeight(bbox) - bboxDepth(bbox));
565
    return 0.5 * (bboxHeight(bbox) - bboxDepth(bbox));
566
}
566
}
567
 
567
 
568
#ifdef NOT_used_currently/*-- out 'def'	 (-Wall) --*/
568
#ifdef NOT_used_currently/*-- out 'def'	 (-Wall) --*/
569
static BBOX DrawBBox(BBOX bbox, double xoffset, double yoffset,
569
static BBOX DrawBBox(BBOX bbox, double xoffset, double yoffset,
570
		     mathContext *mc, R_GE_gcontext *gc, GEDevDesc *dd)
570
		     mathContext *mc, R_GE_gcontext *gc, GEDevDesc *dd)
571
{
571
{
572
    double xsaved = mc->CurrentX;
572
    double xsaved = mc->CurrentX;
573
    double ysaved = mc->CurrentY;
573
    double ysaved = mc->CurrentY;
574
    double x[5], y[5];
574
    double x[5], y[5];
575
    int savedcol = gc->col;
575
    int savedcol = gc->col;
576
    int savedlty = gc->lty;
576
    int savedlty = gc->lty;
577
    double savedlwd = gc->lwd;
577
    double savedlwd = gc->lwd;
578
    mc->CurrentX += xoffset;
578
    mc->CurrentX += xoffset;
579
    mc->CurrentY += yoffset;
579
    mc->CurrentY += yoffset;
580
    PMoveUp(-bboxDepth(bbox), mc);
580
    PMoveUp(-bboxDepth(bbox), mc);
581
    x[4] = x[0] = ConvertedX(mc, dd);
581
    x[4] = x[0] = ConvertedX(mc, dd);
582
    y[4] = y[0] = ConvertedY(mc, dd);
582
    y[4] = y[0] = ConvertedY(mc, dd);
583
    PMoveAcross(bboxWidth(bbox), mc);
583
    PMoveAcross(bboxWidth(bbox), mc);
584
    x[1] = ConvertedX(mc, dd);
584
    x[1] = ConvertedX(mc, dd);
585
    y[1] = ConvertedY(mc, dd);
585
    y[1] = ConvertedY(mc, dd);
586
    PMoveUp(bboxHeight(bbox) + bboxDepth(bbox), mc);
586
    PMoveUp(bboxHeight(bbox) + bboxDepth(bbox), mc);
587
    x[2] = ConvertedX(mc, dd);
587
    x[2] = ConvertedX(mc, dd);
588
    y[2] = ConvertedY(mc, dd);
588
    y[2] = ConvertedY(mc, dd);
589
    PMoveAcross(-bboxWidth(bbox), mc);
589
    PMoveAcross(-bboxWidth(bbox), mc);
590
    x[3] = ConvertedX(mc, dd);
590
    x[3] = ConvertedX(mc, dd);
591
    y[3] = ConvertedY(mc, dd);
591
    y[3] = ConvertedY(mc, dd);
592
    gc->col = mc->BoxColor;
592
    gc->col = mc->BoxColor;
593
    gc->lty = LTY_SOLID;
593
    gc->lty = LTY_SOLID;
594
    /*
594
    /*
595
     * We used to just force lwd = 1, which is a reasonable sanity check
595
     * We used to just force lwd = 1, which is a reasonable sanity check
596
     * because if the user had set lwd = 10 for something, your
596
     * because if the user had set lwd = 10 for something, your
597
     * mathematical annotation would look REALLY bad.
597
     * mathematical annotation would look REALLY bad.
598
     * Unfortunately, this meant that the user could not set a nice
598
     * Unfortunately, this meant that the user could not set a nice
599
     * small lwd to get a finer line;  we always bumped it back up to 1.
599
     * small lwd to get a finer line;  we always bumped it back up to 1.
600
     * NOW we just reduce lwd to 1 (as a sanity check) ONLY if 
600
     * NOW we just reduce lwd to 1 (as a sanity check) ONLY if 
601
     * lwd is greater than 1.
601
     * lwd is greater than 1.
602
     */
602
     */
603
    if (gc->lwd > 1)
603
    if (gc->lwd > 1)
604
	gc->lwd = 1;
604
	gc->lwd = 1;
605
    GEPolyline(5, x, y, gc, dd);
605
    GEPolyline(5, x, y, gc, dd);
606
    PMoveTo(xsaved, ysaved, mc);
606
    PMoveTo(xsaved, ysaved, mc);
607
    gc->col = savedcol;
607
    gc->col = savedcol;
608
    gc->lty = savedlty;
608
    gc->lty = savedlty;
609
    gc->lwd = savedlwd;
609
    gc->lwd = savedlwd;
610
    return bbox;
610
    return bbox;
611
}
611
}
612
#endif
612
#endif
613
 
613
 
614
typedef struct {
614
typedef struct {
615
    char *name;
615
    char *name;
616
    int code;
616
    int code;
617
} SymTab;
617
} SymTab;
618
 
618
 
619
/* Determine a match between symbol name and string. */
619
/* Determine a match between symbol name and string. */
620
 
620
 
621
static int NameMatch(SEXP expr, const char *aString)
621
static int NameMatch(SEXP expr, const char *aString)
622
{
622
{
623
    if (!isSymbol(expr)) return 0;
623
    if (!isSymbol(expr)) return 0;
624
    return !strcmp(CHAR(PRINTNAME(expr)), aString);
624
    return !strcmp(CHAR(PRINTNAME(expr)), aString);
625
}
625
}
626
 
626
 
627
static int StringMatch(SEXP expr, const char *aString)
627
static int StringMatch(SEXP expr, const char *aString)
628
{
628
{
629
    return !strcmp(translateChar(STRING_ELT(expr, 0)), aString);
629
    return !strcmp(translateChar(STRING_ELT(expr, 0)), aString);
630
}
630
}
631
/* Code to determine the ascii code corresponding */
631
/* Code to determine the ascii code corresponding */
632
/* to an element of a mathematical expression. */
632
/* to an element of a mathematical expression. */
633
 
633
 
634
#define A_HAT		  94
634
#define A_HAT		  94
635
#define A_TILDE		 126
635
#define A_TILDE		 126
636
 
636
 
637
#define S_SPACE		  32
637
#define S_SPACE		  32
638
#define S_PARENLEFT	  40
638
#define S_PARENLEFT	  40
639
#define S_PARENRIGHT	  41
639
#define S_PARENRIGHT	  41
640
#define S_ASTERISKMATH	  42
640
#define S_ASTERISKMATH	  42
641
#define S_COMMA		  44
641
#define S_COMMA		  44
642
#define S_SLASH		  47
642
#define S_SLASH		  47
643
#define S_RADICALEX	  96
643
#define S_RADICALEX	  96
644
#define S_FRACTION	 164
644
#define S_FRACTION	 164
645
#define S_ELLIPSIS	 188
645
#define S_ELLIPSIS	 188
646
#define S_INTERSECTION	 199
646
#define S_INTERSECTION	 199
647
#define S_UNION		 200
647
#define S_UNION		 200
648
#define S_PRODUCT	 213
648
#define S_PRODUCT	 213
649
#define S_RADICAL	 214
649
#define S_RADICAL	 214
650
#define S_SUM		 229
650
#define S_SUM		 229
651
#define S_INTEGRAL	 242
651
#define S_INTEGRAL	 242
652
#define S_BRACKETLEFTTP	 233
652
#define S_BRACKETLEFTTP	 233
653
#define S_BRACKETLEFTBT	 235
653
#define S_BRACKETLEFTBT	 235
654
#define S_BRACKETRIGHTTP 249
654
#define S_BRACKETRIGHTTP 249
655
#define S_BRACKETRIGHTBT 251
655
#define S_BRACKETRIGHTBT 251
656
 
656
 
657
#define N_LIM		1001
657
#define N_LIM		1001
658
#define N_LIMINF	1002
658
#define N_LIMINF	1002
659
#define N_LIMSUP	1003
659
#define N_LIMSUP	1003
660
#define N_INF		1004
660
#define N_INF		1004
661
#define N_SUP		1005
661
#define N_SUP		1005
662
#define N_MIN		1006
662
#define N_MIN		1006
663
#define N_MAX		1007
663
#define N_MAX		1007
664
 
664
 
665
 
665
 
666
/* The Full Adobe Symbol Font */
666
/* The Full Adobe Symbol Font */
667
 
667
 
668
static SymTab
668
static SymTab
669
SymbolTable[] = {
669
SymbolTable[] = {
670
    { "space",		 32 },
670
    { "space",		 32 },
671
    { "exclam",		 33 },
671
    { "exclam",		 33 },
672
    { "universal",	 34 },
672
    { "universal",	 34 },
673
    { "numbersign",	 35 },
673
    { "numbersign",	 35 },
674
    { "existential",	 36 },
674
    { "existential",	 36 },
675
    { "percent",	 37 },
675
    { "percent",	 37 },
676
    { "ampersand",	 38 },
676
    { "ampersand",	 38 },
677
    { "suchthat",	 39 },
677
    { "suchthat",	 39 },
678
    { "parenleft",	 40 },
678
    { "parenleft",	 40 },
679
    { "parenright",	 41 },
679
    { "parenright",	 41 },
680
    { "asteriskmath",	 42 },
680
    { "asteriskmath",	 42 },
681
    { "plus",		 43 },
681
    { "plus",		 43 },
682
    { "comma",		 44 },
682
    { "comma",		 44 },
683
    { "minus",		 45 },
683
    { "minus",		 45 },
684
    { "period",		 46 },
684
    { "period",		 46 },
685
    { "slash",		 47 },
685
    { "slash",		 47 },
686
    { "0",		 48 },
686
    { "0",		 48 },
687
    { "1",		 49 },
687
    { "1",		 49 },
688
    { "2",		 50 },
688
    { "2",		 50 },
689
    { "3",		 51 },
689
    { "3",		 51 },
690
    { "4",		 52 },
690
    { "4",		 52 },
691
    { "5",		 53 },
691
    { "5",		 53 },
692
    { "6",		 54 },
692
    { "6",		 54 },
693
    { "7",		 55 },
693
    { "7",		 55 },
694
    { "8",		 56 },
694
    { "8",		 56 },
695
    { "9",		 57 },
695
    { "9",		 57 },
696
    { "colon",		 58 },
696
    { "colon",		 58 },
697
    { "semicolon",	 59 },
697
    { "semicolon",	 59 },
698
    { "less",		 60 },
698
    { "less",		 60 },
699
    { "equal",		 61 },
699
    { "equal",		 61 },
700
    { "greater",	 62 },
700
    { "greater",	 62 },
701
    { "question",	 63 },
701
    { "question",	 63 },
702
    { "congruent",	 64 },
702
    { "congruent",	 64 },
703
 
703
 
704
    { "Alpha",/* 0101= */65 }, /* Upper Case Greek Characters */
704
    { "Alpha",/* 0101= */65 }, /* Upper Case Greek Characters */
705
    { "Beta",		 66 },
705
    { "Beta",		 66 },
706
    { "Chi",		 67 },
706
    { "Chi",		 67 },
707
    { "Delta",		 68 },
707
    { "Delta",		 68 },
708
    { "Epsilon",	 69 },
708
    { "Epsilon",	 69 },
709
    { "Phi",		 70 },
709
    { "Phi",		 70 },
710
    { "Gamma",		 71 },
710
    { "Gamma",		 71 },
711
    { "Eta",		 72 },
711
    { "Eta",		 72 },
712
    { "Iota",		 73 },
712
    { "Iota",		 73 },
713
    { "theta1",		 74 },
713
    { "theta1",		 74 },
714
    { "vartheta",	 74 },
714
    { "vartheta",	 74 },
715
    { "Kappa",		 75 },
715
    { "Kappa",		 75 },
716
    { "Lambda",		 76 },
716
    { "Lambda",		 76 },
717
    { "Mu",		 77 },
717
    { "Mu",		 77 },
718
    { "Nu",		 78 },
718
    { "Nu",		 78 },
719
    { "Omicron",	 79 },
719
    { "Omicron",	 79 },
720
    { "Pi",		 80 },
720
    { "Pi",		 80 },
721
    { "Theta",		 81 },
721
    { "Theta",		 81 },
722
    { "Rho",		 82 },
722
    { "Rho",		 82 },
723
    { "Sigma",		 83 },
723
    { "Sigma",		 83 },
724
    { "Tau",		 84 },
724
    { "Tau",		 84 },
725
    { "Upsilon",	 85 },
725
    { "Upsilon",	 85 },
726
    { "sigma1",		 86 },
726
    { "sigma1",		 86 },
727
    { "varsigma",	 86 },
727
    { "varsigma",	 86 },
728
    { "stigma",		 86 },
728
    { "stigma",		 86 },
729
    { "Omega",		 87 },
729
    { "Omega",		 87 },
730
    { "Xi",		 88 },
730
    { "Xi",		 88 },
731
    { "Psi",		 89 },
731
    { "Psi",		 89 },
732
    { "Zeta",/* 0132 = */90 },
732
    { "Zeta",/* 0132 = */90 },
733
 
733
 
734
    { "bracketleft",	 91 },	/* Miscellaneous Special Characters */
734
    { "bracketleft",	 91 },	/* Miscellaneous Special Characters */
735
    { "therefore",	 92 },
735
    { "therefore",	 92 },
736
    { "bracketright",	 93 },
736
    { "bracketright",	 93 },
737
    { "perpendicular",	 94 },
737
    { "perpendicular",	 94 },
738
    { "underscore",	 95 },
738
    { "underscore",	 95 },
739
    { "radicalex",	 96 },
739
    { "radicalex",	 96 },
740
 
740
 
741
    { "alpha",/* 0141= */97 },	/* Lower Case Greek Characters */
741
    { "alpha",/* 0141= */97 },	/* Lower Case Greek Characters */
742
    { "beta",		 98 },
742
    { "beta",		 98 },
743
    { "chi",		 99 },
743
    { "chi",		 99 },
744
    { "delta",		100 },
744
    { "delta",		100 },
745
    { "epsilon",	101 },
745
    { "epsilon",	101 },
746
    { "phi",		102 },
746
    { "phi",		102 },
747
    { "gamma",		103 },
747
    { "gamma",		103 },
748
    { "eta",		104 },
748
    { "eta",		104 },
749
    { "iota",		105 },
749
    { "iota",		105 },
750
    { "phi1",		106 },
750
    { "phi1",		106 },
751
    { "varphi",		106 },
751
    { "varphi",		106 },
752
    { "kappa",		107 },
752
    { "kappa",		107 },
753
    { "lambda",		108 },
753
    { "lambda",		108 },
754
    { "mu",		109 },
754
    { "mu",		109 },
755
    { "nu",		110 },
755
    { "nu",		110 },
756
    { "omicron",	111 },
756
    { "omicron",	111 },
757
    { "pi",		112 },
757
    { "pi",		112 },
758
    { "theta",		113 },
758
    { "theta",		113 },
759
    { "rho",		114 },
759
    { "rho",		114 },
760
    { "sigma",		115 },
760
    { "sigma",		115 },
761
    { "tau",		116 },
761
    { "tau",		116 },
762
    { "upsilon",	117 },
762
    { "upsilon",	117 },
763
    { "omega1",		118 },
763
    { "omega1",		118 },
764
    { "omega",		119 },
764
    { "omega",		119 },
765
    { "xi",		120 },
765
    { "xi",		120 },
766
    { "psi",		121 },
766
    { "psi",		121 },
767
    { "zeta",/* 0172= */122 },
767
    { "zeta",/* 0172= */122 },
768
 
768
 
769
    { "braceleft",	123 },	/* Miscellaneous Special Characters */
769
    { "braceleft",	123 },	/* Miscellaneous Special Characters */
770
    { "bar",		124 },
770
    { "bar",		124 },
771
    { "braceright",	125 },
771
    { "braceright",	125 },
772
    { "similar",	126 },
772
    { "similar",	126 },
773
 
773
 
774
    { "Upsilon1",	161 },	/* Lone Greek */
774
    { "Upsilon1",	161 },	/* Lone Greek */
775
    { "minute",		162 },
775
    { "minute",		162 },
776
    { "lessequal",	163 },
776
    { "lessequal",	163 },
777
    { "fraction",	164 },
777
    { "fraction",	164 },
778
    { "infinity",	165 },
778
    { "infinity",	165 },
779
    { "florin",		166 },
779
    { "florin",		166 },
780
    { "club",		167 },
780
    { "club",		167 },
781
    { "diamond",	168 },
781
    { "diamond",	168 },
782
    { "heart",		169 },
782
    { "heart",		169 },
783
    { "spade",		170 },
783
    { "spade",		170 },
784
    { "arrowboth",	171 },
784
    { "arrowboth",	171 },
785
    { "arrowleft",	172 },
785
    { "arrowleft",	172 },
786
    { "arrowup",	173 },
786
    { "arrowup",	173 },
787
    { "arrowright",	174 },
787
    { "arrowright",	174 },
788
    { "arrowdown",	175 },
788
    { "arrowdown",	175 },
789
    { "degree",		176 },
789
    { "degree",		176 },
790
    { "plusminus",	177 },
790
    { "plusminus",	177 },
791
    { "second",		178 },
791
    { "second",		178 },
792
    { "greaterequal",	179 },
792
    { "greaterequal",	179 },
793
    { "multiply",	180 },
793
    { "multiply",	180 },
794
    { "proportional",	181 },
794
    { "proportional",	181 },
795
    { "partialdiff",	182 },
795
    { "partialdiff",	182 },
796
    { "bullet",		183 },
796
    { "bullet",		183 },
797
    { "divide",		184 },
797
    { "divide",		184 },
798
    { "notequal",	185 },
798
    { "notequal",	185 },
799
    { "equivalence",	186 },
799
    { "equivalence",	186 },
800
    { "approxequal",	187 },
800
    { "approxequal",	187 },
801
    { "ellipsis",	188 },
801
    { "ellipsis",	188 },
802
    { "arrowvertex",	189 },
802
    { "arrowvertex",	189 },
803
    { "arrowhorizex",	190 },
803
    { "arrowhorizex",	190 },
804
    { "carriagereturn", 191 },
804
    { "carriagereturn", 191 },
805
    { "aleph",		192 },
805
    { "aleph",		192 },
806
    { "Ifraktur",	193 },
806
    { "Ifraktur",	193 },
807
    { "Rfraktur",	194 },
807
    { "Rfraktur",	194 },
808
    { "weierstrass",	195 },
808
    { "weierstrass",	195 },
809
    { "circlemultiply", 196 },
809
    { "circlemultiply", 196 },
810
    { "circleplus",	197 },
810
    { "circleplus",	197 },
811
    { "emptyset",	198 },
811
    { "emptyset",	198 },
812
    { "intersection",	199 },/* = 0307 */
812
    { "intersection",	199 },/* = 0307 */
813
    { "union",		200 },/* = 0310 */
813
    { "union",		200 },/* = 0310 */
814
    { "propersuperset", 201 },
814
    { "propersuperset", 201 },
815
    { "reflexsuperset", 202 },
815
    { "reflexsuperset", 202 },
816
    { "notsubset",	203 },
816
    { "notsubset",	203 },
817
    { "propersubset",	204 },
817
    { "propersubset",	204 },
818
    { "reflexsubset",	205 },
818
    { "reflexsubset",	205 },
819
    { "element",	206 },
819
    { "element",	206 },
820
    { "notelement",	207 },
820
    { "notelement",	207 },
821
    { "angle",		208 },
821
    { "angle",		208 },
822
    { "gradient",	209 },
822
    { "gradient",	209 },
823
    { "registerserif",	210 },
823
    { "registerserif",	210 },
824
    { "copyrightserif", 211 },
824
    { "copyrightserif", 211 },
825
    { "trademarkserif", 212 },
825
    { "trademarkserif", 212 },
826
    { "product",	213 },
826
    { "product",	213 },
827
    { "radical",	214 },
827
    { "radical",	214 },
828
    { "dotmath",	215 },
828
    { "dotmath",	215 },
829
    { "logicaland",	217 },
829
    { "logicaland",	217 },
830
    { "logicalor",	218 },
830
    { "logicalor",	218 },
831
    { "arrowdblboth",	219 },
831
    { "arrowdblboth",	219 },
832
    { "arrowdblleft",	220 },
832
    { "arrowdblleft",	220 },
833
    { "arrowdblup",	221 },
833
    { "arrowdblup",	221 },
834
    { "arrowdblright",	222 },
834
    { "arrowdblright",	222 },
835
    { "arrowdbldown",	223 },
835
    { "arrowdbldown",	223 },
836
    { "lozenge",	224 },
836
    { "lozenge",	224 },
837
    { "angleleft",	225 },
837
    { "angleleft",	225 },
838
    { "registersans",	226 },
838
    { "registersans",	226 },
839
    { "copyrightsans",	227 },
839
    { "copyrightsans",	227 },
840
    { "trademarksans",	228 },
840
    { "trademarksans",	228 },
841
    { "summation",	229 },
841
    { "summation",	229 },
842
    { "parenlefttp",	230 },
842
    { "parenlefttp",	230 },
843
    { "parenleftex",	231 },
843
    { "parenleftex",	231 },
844
    { "parenleftbt",	232 },
844
    { "parenleftbt",	232 },
845
    { "bracketlefttp",	233 },
845
    { "bracketlefttp",	233 },
846
    { "bracketleftex",	234 },
846
    { "bracketleftex",	234 },
847
    { "bracketleftbt",	235 },
847
    { "bracketleftbt",	235 },
848
    { "bracelefttp",	236 },
848
    { "bracelefttp",	236 },
849
    { "braceleftmid",	237 },
849
    { "braceleftmid",	237 },
850
    { "braceleftbt",	238 },
850
    { "braceleftbt",	238 },
851
    { "braceex",	239 },
851
    { "braceex",	239 },
852
    { "angleright",	241 },
852
    { "angleright",	241 },
853
    { "integral",	242 },
853
    { "integral",	242 },
854
    { "integraltp",	243 },
854
    { "integraltp",	243 },
855
    { "integralex",	244 },
855
    { "integralex",	244 },
856
    { "integralbt",	245 },
856
    { "integralbt",	245 },
857
    { "parenrighttp",	246 },
857
    { "parenrighttp",	246 },
858
    { "parenrightex",	247 },
858
    { "parenrightex",	247 },
859
    { "parenrightbt",	248 },
859
    { "parenrightbt",	248 },
860
    { "bracketrighttp", 249 },
860
    { "bracketrighttp", 249 },
861
    { "bracketrightex", 250 },
861
    { "bracketrightex", 250 },
862
    { "bracketrightbt", 251 },
862
    { "bracketrightbt", 251 },
863
    { "bracerighttp",	252 },
863
    { "bracerighttp",	252 },
864
    { "bracerightmid",	253 },
864
    { "bracerightmid",	253 },
865
    { "bracerightbt",	254 },
865
    { "bracerightbt",	254 },
866
 
866
 
867
    { NULL,		  0 },
867
    { NULL,		  0 },
868
};
868
};
869
 
869
 
870
static int SymbolCode(SEXP expr)
870
static int SymbolCode(SEXP expr)
871
{
871
{
872
    int i;
872
    int i;
873
    for (i = 0; SymbolTable[i].code; i++)
873
    for (i = 0; SymbolTable[i].code; i++)
874
	if (NameMatch(expr, SymbolTable[i].name))
874
	if (NameMatch(expr, SymbolTable[i].name))
875
	    return SymbolTable[i].code;
875
	    return SymbolTable[i].code;
876
    return 0;
876
    return 0;
877
}
877
}
878
 
878
 
879
/* this is the one really used: */
879
/* this is the one really used: */
880
static int TranslatedSymbol(SEXP expr)
880
static int TranslatedSymbol(SEXP expr)
881
{
881
{
882
    int code = SymbolCode(expr);
882
    int code = SymbolCode(expr);
883
    if ((0101 <= code && code <= 0132)	||   /* Greek */
883
    if ((0101 <= code && code <= 0132)	||   /* Greek */
884
	(0141 <= code && code <= 0172)	||   /* Greek */
884
	(0141 <= code && code <= 0172)	||   /* Greek */
885
	code == 0241			||   /* Upsilon1 */
885
	code == 0241			||   /* Upsilon1 */
886
	code == 0242			||   /* minute */
886
	code == 0242			||   /* minute */
887
	code == 0245			||   /* infinity */
887
	code == 0245			||   /* infinity */
888
	code == 0260			||   /* degree */
888
	code == 0260			||   /* degree */
889
	code == 0262			||   /* second */
889
	code == 0262			||   /* second */
890
	code == 0266                    ||   /* partialdiff */
890
	code == 0266                    ||   /* partialdiff */
891
	0)
891
	0)
892
	return code;
892
	return code;
893
    else
893
    else
894
	return 0;
894
	return 0;
895
}
895
}
896
 
896
 
897
/* Code to determine the nature of an expression. */
897
/* Code to determine the nature of an expression. */
898
 
898
 
899
static int FormulaExpression(SEXP expr)
899
static int FormulaExpression(SEXP expr)
900
{
900
{
901
    return (TYPEOF(expr) == LANGSXP);
901
    return (TYPEOF(expr) == LANGSXP);
902
}
902
}
903
 
903
 
904
static int NameAtom(SEXP expr)
904
static int NameAtom(SEXP expr)
905
{
905
{
906
    return (TYPEOF(expr) == SYMSXP);
906
    return (TYPEOF(expr) == SYMSXP);
907
}
907
}
908
 
908
 
909
static int NumberAtom(SEXP expr)
909
static int NumberAtom(SEXP expr)
910
{
910
{
911
    return ((TYPEOF(expr) == REALSXP) ||
911
    return ((TYPEOF(expr) == REALSXP) ||
912
	    (TYPEOF(expr) == INTSXP)  ||
912
	    (TYPEOF(expr) == INTSXP)  ||
913
	    (TYPEOF(expr) == CPLXSXP));
913
	    (TYPEOF(expr) == CPLXSXP));
914
}
914
}
915
 
915
 
916
static int StringAtom(SEXP expr)
916
static int StringAtom(SEXP expr)
917
{
917
{
918
    return (TYPEOF(expr) == STRSXP);
918
    return (TYPEOF(expr) == STRSXP);
919
}
919
}
920
 
920
 
921
#ifdef NOT_used_currently/*-- out 'def'	 (-Wall) --*/
921
#ifdef NOT_used_currently/*-- out 'def'	 (-Wall) --*/
922
static int symbolAtom(SEXP expr)
922
static int symbolAtom(SEXP expr)
923
{
923
{
924
    int i;
924
    int i;
925
    if (NameAtom(expr)) {
925
    if (NameAtom(expr)) {
926
	for (i = 0; SymbolTable[i].code; i++)
926
	for (i = 0; SymbolTable[i].code; i++)
927
	    if (NameMatch(expr, SymbolTable[i].name))
927
	    if (NameMatch(expr, SymbolTable[i].name))
928
		return 1;
928
		return 1;
929
    }
929
    }
930
    return 0;
930
    return 0;
931
}
931
}
932
#endif
932
#endif
933
/* Code to determine a font from the */
933
/* Code to determine a font from the */
934
/* nature of the expression */
934
/* nature of the expression */
935
 
935
 
936
#ifdef NOT_used_currently/*-- out 'def'	 (-Wall) --*/
936
#ifdef NOT_used_currently/*-- out 'def'	 (-Wall) --*/
937
static FontType mc->CurrentFont = 3;
937
static FontType mc->CurrentFont = 3;
938
#endif
938
#endif
939
static FontType GetFont(R_GE_gcontext *gc)
939
static FontType GetFont(R_GE_gcontext *gc)
940
{
940
{
941
    return gc->fontface;
941
    return gc->fontface;
942
}
942
}
943
 
943
 
944
static FontType SetFont(FontType font, R_GE_gcontext *gc)
944
static FontType SetFont(FontType font, R_GE_gcontext *gc)
945
{
945
{
946
    FontType prevfont = gc->fontface;
946
    FontType prevfont = gc->fontface;
947
    gc->fontface = font;
947
    gc->fontface = font;
948
    return prevfont;
948
    return prevfont;
949
}
949
}
950
 
950
 
951
static int UsingItalics(R_GE_gcontext *gc)
951
static int UsingItalics(R_GE_gcontext *gc)
952
{
952
{
953
    return (gc->fontface == ItalicFont ||
953
    return (gc->fontface == ItalicFont ||
954
	    gc->fontface == BoldItalicFont);
954
	    gc->fontface == BoldItalicFont);
955
}
955
}
956
 
956
 
957
static BBOX GlyphBBox(int chr, R_GE_gcontext *gc, GEDevDesc *dd)
957
static BBOX GlyphBBox(int chr, R_GE_gcontext *gc, GEDevDesc *dd)
958
{
958
{
959
    BBOX bbox;
959
    BBOX bbox;
960
    double height, depth, width;
960
    double height, depth, width;
961
    GEMetricInfo(chr, gc,
961
    GEMetricInfo(chr, gc,
962
		&height, &depth, &width, dd);
962
		&height, &depth, &width, dd);
963
    bboxHeight(bbox) = fromDeviceHeight(height, MetricUnit, dd);
963
    bboxHeight(bbox) = fromDeviceHeight(height, MetricUnit, dd);
964
    bboxDepth(bbox)  = fromDeviceHeight(depth, MetricUnit, dd);
964
    bboxDepth(bbox)  = fromDeviceHeight(depth, MetricUnit, dd);
965
    bboxWidth(bbox)  = fromDeviceHeight(width, MetricUnit, dd);
965
    bboxWidth(bbox)  = fromDeviceHeight(width, MetricUnit, dd);
966
    bboxItalic(bbox) = 0;
966
    bboxItalic(bbox) = 0;
967
    bboxSimple(bbox) = 1;
967
    bboxSimple(bbox) = 1;
968
    return bbox;
968
    return bbox;
969
}
969
}
970
 
970
 
971
static BBOX RenderElement(SEXP, int,
971
static BBOX RenderElement(SEXP, int,
972
			  mathContext*, R_GE_gcontext*, GEDevDesc*);
972
			  mathContext*, R_GE_gcontext*, GEDevDesc*);
973
static BBOX RenderOffsetElement(SEXP, double, double, int,
973
static BBOX RenderOffsetElement(SEXP, double, double, int,
974
				mathContext*, R_GE_gcontext*, GEDevDesc*);
974
				mathContext*, R_GE_gcontext*, GEDevDesc*);
975
static BBOX RenderExpression(SEXP, int,
975
static BBOX RenderExpression(SEXP, int,
976
			     mathContext*, R_GE_gcontext*, GEDevDesc*);
976
			     mathContext*, R_GE_gcontext*, GEDevDesc*);
977
static BBOX RenderSymbolChar(int, int,
977
static BBOX RenderSymbolChar(int, int,
978
			     mathContext*, R_GE_gcontext*, GEDevDesc*);
978
			     mathContext*, R_GE_gcontext*, GEDevDesc*);
979
 
979
 
980
 
980
 
981
/*  Code to Generate Bounding Boxes and Draw Formulae.	*/
981
/*  Code to Generate Bounding Boxes and Draw Formulae.	*/
982
 
982
 
983
static BBOX RenderItalicCorr(BBOX bbox, int draw, mathContext *mc,
983
static BBOX RenderItalicCorr(BBOX bbox, int draw, mathContext *mc,
984
			     R_GE_gcontext *gc, GEDevDesc *dd)
984
			     R_GE_gcontext *gc, GEDevDesc *dd)
985
{
985
{
986
    if (bboxItalic(bbox) > 0) {
986
    if (bboxItalic(bbox) > 0) {
987
	if (draw)
987
	if (draw)
988
	    PMoveAcross(bboxItalic(bbox), mc);
988
	    PMoveAcross(bboxItalic(bbox), mc);
989
	bboxWidth(bbox) += bboxItalic(bbox);
989
	bboxWidth(bbox) += bboxItalic(bbox);
990
	bboxItalic(bbox) = 0;
990
	bboxItalic(bbox) = 0;
991
    }
991
    }
992
    return bbox;
992
    return bbox;
993
}
993
}
994
 
994
 
995
static BBOX RenderGap(double gap, int draw, mathContext *mc,
995
static BBOX RenderGap(double gap, int draw, mathContext *mc,
996
		      R_GE_gcontext *gc, GEDevDesc *dd)
996
		      R_GE_gcontext *gc, GEDevDesc *dd)
997
{
997
{
998
    if (draw)
998
    if (draw)
999
	PMoveAcross(gap, mc);
999
	PMoveAcross(gap, mc);
1000
    return MakeBBox(0, 0, gap);
1000
    return MakeBBox(0, 0, gap);
1001
}
1001
}
1002
 
1002
 
1003
/* Draw a Symbol from the Special Font:
1003
/* Draw a Symbol from the Special Font:
1004
   this is assumed to be 8-bit encoded in Adobe Symbol.
1004
   this is assumed to be 8-bit encoded in Adobe Symbol.
1005
 */
1005
 */
1006
 
1006
 
1007
static BBOX RenderSymbolChar(int ascii, int draw, mathContext *mc,
1007
static BBOX RenderSymbolChar(int ascii, int draw, mathContext *mc,
1008
			     R_GE_gcontext *gc, GEDevDesc *dd)
1008
			     R_GE_gcontext *gc, GEDevDesc *dd)
1009
{
1009
{
1010
    FontType prev;
1010
    FontType prev;
1011
    BBOX bbox;
1011
    BBOX bbox;
1012
    char asciiStr[2];
1012
    char asciiStr[2];
1013
    if (ascii == A_HAT || ascii == A_TILDE)
1013
    if (ascii == A_HAT || ascii == A_TILDE)
1014
	prev = SetFont(PlainFont, gc);
1014
	prev = SetFont(PlainFont, gc);
1015
    else
1015
    else
1016
	prev = SetFont(SymbolFont, gc);
1016
	prev = SetFont(SymbolFont, gc);
1017
    bbox = GlyphBBox(ascii, gc, dd);
1017
    bbox = GlyphBBox(ascii, gc, dd);
1018
    if (draw) {
1018
    if (draw) {
1019
	asciiStr[0] = ascii;
1019
	asciiStr[0] = ascii;
1020
	asciiStr[1] = '\0';
1020
	asciiStr[1] = '\0';
1021
	GEText(ConvertedX(mc ,dd), ConvertedY(mc, dd), asciiStr,
1021
	GEText(ConvertedX(mc ,dd), ConvertedY(mc, dd), asciiStr,
1022
	       0.0, 0.0, mc->CurrentAngle, gc,
1022
	       0.0, 0.0, mc->CurrentAngle, gc,
1023
	       dd);
1023
	       dd);
1024
	PMoveAcross(bboxWidth(bbox), mc);
1024
	PMoveAcross(bboxWidth(bbox), mc);
1025
    }
1025
    }
1026
    SetFont(prev, gc);
1026
    SetFont(prev, gc);
1027
    return bbox;
1027
    return bbox;
1028
}
1028
}
1029
 
1029
 
1030
/* Draw a Symbol String in "Math Mode" */
1030
/* Draw a Symbol String in "Math Mode" */
1031
/* This code inserts italic corrections after */
1031
/* This code inserts italic corrections after */
1032
/* every character. */
1032
/* every character. */
1033
 
1033
 
1034
static BBOX RenderSymbolStr(const char *str, int draw, mathContext *mc,
1034
static BBOX RenderSymbolStr(const char *str, int draw, mathContext *mc,
1035
			    R_GE_gcontext *gc, GEDevDesc *dd)
1035
			    R_GE_gcontext *gc, GEDevDesc *dd)
1036
{
1036
{
1037
    char chr[7] = "";
1037
    char chr[7] = "";
1038
    const char *s = str;
1038
    const char *s = str;
1039
    BBOX glyphBBox;
1039
    BBOX glyphBBox;
1040
    BBOX resultBBox = NullBBox();
1040
    BBOX resultBBox = NullBBox();
1041
    double lastItalicCorr = 0;
1041
    double lastItalicCorr = 0;
1042
    FontType prevfont = GetFont(gc);
1042
    FontType prevfont = GetFont(gc);
1043
    FontType font = prevfont;
1043
    FontType font = prevfont;
1044
 
1044
 
1045
    if (str) {
1045
    if (str) {
1046
#ifdef SUPPORT_MBCS
1046
#ifdef SUPPORT_MBCS
1047
	if(mbcslocale) {  /* need to advance by character, not byte */
1047
	if(mbcslocale) {  /* need to advance by character, not byte */
1048
	    wchar_t wc;
1048
	    wchar_t wc;
1049
	    mbstate_t mb_st;
1049
	    mbstate_t mb_st;
1050
	    size_t res;
1050
	    size_t res;
1051
 
1051
 
1052
	    memset(&mb_st, 0, sizeof(mb_st));
1052
	    memset(&mb_st, 0, sizeof(mb_st));
1053
	    while (*s) {
1053
	    while (*s) {
1054
		wc = 0;
1054
		wc = 0;
1055
		res = mbrtowc(&wc, s, MB_LEN_MAX, &mb_st);
1055
		res = mbrtowc(&wc, s, MB_LEN_MAX, &mb_st);
1056
		if(res == -1) error("invalid multibyte string");
1056
		if(res == -1) error("invalid multibyte string");
1057
		if (iswdigit(wc) && font != PlainFont) {
1057
		if (iswdigit(wc) && font != PlainFont) {
1058
		    font = PlainFont;
1058
		    font = PlainFont;
1059
		    SetFont(PlainFont, gc);
1059
		    SetFont(PlainFont, gc);
1060
		}
1060
		}
1061
		else if (font != prevfont) {
1061
		else if (font != prevfont) {
1062
		    font = prevfont;
1062
		    font = prevfont;
1063
		    SetFont(prevfont, gc);
1063
		    SetFont(prevfont, gc);
1064
		}
1064
		}
1065
		glyphBBox = GlyphBBox((int)wc, gc, dd);
1065
		glyphBBox = GlyphBBox((int)wc, gc, dd);
1066
		if (UsingItalics(gc))
1066
		if (UsingItalics(gc))
1067
		    bboxItalic(glyphBBox) =
1067
		    bboxItalic(glyphBBox) =
1068
			ItalicFactor * bboxHeight(glyphBBox);
1068
			ItalicFactor * bboxHeight(glyphBBox);
1069
		else
1069
		else
1070
		    bboxItalic(glyphBBox) = 0;
1070
		    bboxItalic(glyphBBox) = 0;
1071
		if (draw) {
1071
		if (draw) {
1072
		    memset(chr, 0, sizeof(chr));
1072
		    memset(chr, 0, sizeof(chr));
1073
		    res  = wcrtomb(chr, wc, &mb_st);
1073
		    res  = wcrtomb(chr, wc, &mb_st);
1074
		    if(res == -1) error("invalid multibyte string");
1074
		    if(res == -1) error("invalid multibyte string");
1075
		    PMoveAcross(lastItalicCorr, mc);
1075
		    PMoveAcross(lastItalicCorr, mc);
1076
		    GEText(ConvertedX(mc ,dd), ConvertedY(mc, dd), chr,
1076
		    GEText(ConvertedX(mc ,dd), ConvertedY(mc, dd), chr,
1077
			   0.0, 0.0, mc->CurrentAngle, gc,
1077
			   0.0, 0.0, mc->CurrentAngle, gc,
1078
			   dd);
1078
			   dd);
1079
		    PMoveAcross(bboxWidth(glyphBBox), mc);
1079
		    PMoveAcross(bboxWidth(glyphBBox), mc);
1080
		}
1080
		}
1081
		bboxWidth(resultBBox) += lastItalicCorr;
1081
		bboxWidth(resultBBox) += lastItalicCorr;
1082
		resultBBox = CombineBBoxes(resultBBox, glyphBBox);
1082
		resultBBox = CombineBBoxes(resultBBox, glyphBBox);
1083
		lastItalicCorr = bboxItalic(glyphBBox);
1083
		lastItalicCorr = bboxItalic(glyphBBox);
1084
		s += res;
1084
		s += res;
1085
	    }
1085
	    }
1086
	} else
1086
	} else
1087
#endif
1087
#endif
1088
	{
1088
	{
1089
	    while (*s) {
1089
	    while (*s) {
1090
		if (isdigit((int)*s) && font != PlainFont) {
1090
		if (isdigit((int)*s) && font != PlainFont) {
1091
		    font = PlainFont;
1091
		    font = PlainFont;
1092
		    SetFont(PlainFont, gc);
1092
		    SetFont(PlainFont, gc);
1093
		}
1093
		}
1094
		else if (font != prevfont) {
1094
		else if (font != prevfont) {
1095
		    font = prevfont;
1095
		    font = prevfont;
1096
		    SetFont(prevfont, gc);
1096
		    SetFont(prevfont, gc);
1097
		}
1097
		}
1098
		glyphBBox = GlyphBBox(*s, gc, dd);
1098
		glyphBBox = GlyphBBox(*s, gc, dd);
1099
		if (UsingItalics(gc))
1099
		if (UsingItalics(gc))
1100
		    bboxItalic(glyphBBox) =
1100
		    bboxItalic(glyphBBox) =
1101
			ItalicFactor * bboxHeight(glyphBBox);
1101
			ItalicFactor * bboxHeight(glyphBBox);
1102
		else
1102
		else
1103
		    bboxItalic(glyphBBox) = 0;
1103
		    bboxItalic(glyphBBox) = 0;
1104
		if (draw) {
1104
		if (draw) {
1105
		    chr[0] = *s;
1105
		    chr[0] = *s;
1106
		    PMoveAcross(lastItalicCorr, mc);
1106
		    PMoveAcross(lastItalicCorr, mc);
1107
		    GEText(ConvertedX(mc ,dd), ConvertedY(mc, dd), chr,
1107
		    GEText(ConvertedX(mc ,dd), ConvertedY(mc, dd), chr,
1108
			   0.0, 0.0, mc->CurrentAngle, gc,
1108
			   0.0, 0.0, mc->CurrentAngle, gc,
1109
			   dd);
1109
			   dd);
1110
		    PMoveAcross(bboxWidth(glyphBBox), mc);
1110
		    PMoveAcross(bboxWidth(glyphBBox), mc);
1111
		}
1111
		}
1112
		bboxWidth(resultBBox) += lastItalicCorr;
1112
		bboxWidth(resultBBox) += lastItalicCorr;
1113
		resultBBox = CombineBBoxes(resultBBox, glyphBBox);
1113
		resultBBox = CombineBBoxes(resultBBox, glyphBBox);
1114
		lastItalicCorr = bboxItalic(glyphBBox);
1114
		lastItalicCorr = bboxItalic(glyphBBox);
1115
		s++;
1115
		s++;
1116
	    }
1116
	    }
1117
	}
1117
	}
1118
	if (font != prevfont)
1118
	if (font != prevfont)
1119
	    SetFont(prevfont, gc);
1119
	    SetFont(prevfont, gc);
1120
    }
1120
    }
1121
    bboxSimple(resultBBox) = 1;
1121
    bboxSimple(resultBBox) = 1;
1122
    return resultBBox;
1122
    return resultBBox;
1123
}
1123
}
1124
 
1124
 
1125
/* Code for Character String Atoms. */
1125
/* Code for Character String Atoms. */
1126
 
1126
 
1127
/* This only gets called from RenderAccent */
1127
/* This only gets called from RenderAccent */
1128
static BBOX RenderChar(int ascii, int draw, mathContext *mc,
1128
static BBOX RenderChar(int ascii, int draw, mathContext *mc,
1129
		       R_GE_gcontext *gc, GEDevDesc *dd)
1129
		       R_GE_gcontext *gc, GEDevDesc *dd)
1130
{
1130
{
1131
    BBOX bbox;
1131
    BBOX bbox;
1132
    char asciiStr[7];
1132
    char asciiStr[7];
1133
 
1133
 
1134
    bbox = GlyphBBox(ascii, gc, dd);
1134
    bbox = GlyphBBox(ascii, gc, dd);
1135
    if (draw) {
1135
    if (draw) {
1136
        memset(asciiStr, 0, sizeof(asciiStr));
1136
        memset(asciiStr, 0, sizeof(asciiStr));
1137
#ifdef SUPPORT_MBCS
1137
#ifdef SUPPORT_MBCS
1138
	if(mbcslocale) {
1138
	if(mbcslocale) {
1139
	    size_t res = wcrtomb(asciiStr, ascii, NULL);
1139
	    size_t res = wcrtomb(asciiStr, ascii, NULL);
1140
	    if(res == -1)
1140
	    if(res == -1)
1141
		error("invalid character in current multibyte locale");
1141
		error("invalid character in current multibyte locale");
1142
	} else
1142
	} else
1143
#endif
1143
#endif
1144
	    asciiStr[0] = ascii;
1144
	    asciiStr[0] = ascii;
1145
	GEText(ConvertedX(mc ,dd), ConvertedY(mc, dd), asciiStr,
1145
	GEText(ConvertedX(mc ,dd), ConvertedY(mc, dd), asciiStr,
1146
	       0.0, 0.0, mc->CurrentAngle, gc,
1146
	       0.0, 0.0, mc->CurrentAngle, gc,
1147
	       dd);
1147
	       dd);
1148
	PMoveAcross(bboxWidth(bbox), mc);
1148
	PMoveAcross(bboxWidth(bbox), mc);
1149
    }
1149
    }
1150
    return bbox;
1150
    return bbox;
1151
}
1151
}
1152
 
1152
 
1153
/* This gets called on strings and PRINTNAMES */
1153
/* This gets called on strings and PRINTNAMES */
1154
static BBOX RenderStr(const char *str, int draw, mathContext *mc,
1154
static BBOX RenderStr(const char *str, int draw, mathContext *mc,
1155
		      R_GE_gcontext *gc, GEDevDesc *dd)
1155
		      R_GE_gcontext *gc, GEDevDesc *dd)
1156
{
1156
{
1157
    BBOX glyphBBox;
1157
    BBOX glyphBBox;
1158
    BBOX resultBBox = NullBBox();
1158
    BBOX resultBBox = NullBBox();
1159
    if (str) {
1159
    if (str) {
1160
#ifdef SUPPORT_MBCS
1160
#ifdef SUPPORT_MBCS
1161
	int n = strlen(str), used;
1161
	int n = strlen(str), used;
1162
	wchar_t wc;
1162
	wchar_t wc;
1163
	const char *p = str;
1163
	const char *p = str;
1164
	mbstate_t mb_st;
1164
	mbstate_t mb_st;
1165
	mbs_init(&mb_st);
1165
	mbs_init(&mb_st);
1166
	while ((used = Mbrtowc(&wc, p, n, &mb_st)) > 0) {
1166
	while ((used = Mbrtowc(&wc, p, n, &mb_st)) > 0) {
1167
	    glyphBBox = GlyphBBox(wc, gc, dd);
1167
	    glyphBBox = GlyphBBox(wc, gc, dd);
1168
	    resultBBox = CombineBBoxes(resultBBox, glyphBBox);
1168
	    resultBBox = CombineBBoxes(resultBBox, glyphBBox);
1169
	    p += used; n -= used;
1169
	    p += used; n -= used;
1170
	}
1170
	}
1171
#else
1171
#else
1172
	const char *s = str;
1172
	const char *s = str;
1173
	while (*s) {
1173
	while (*s) {
1174
	    glyphBBox = GlyphBBox(*s, gc, dd);
1174
	    glyphBBox = GlyphBBox(*s, gc, dd);
1175
	    resultBBox = CombineBBoxes(resultBBox, glyphBBox);
1175
	    resultBBox = CombineBBoxes(resultBBox, glyphBBox);
1176
	    s++;
1176
	    s++;
1177
	}
1177
	}
1178
#endif
1178
#endif
1179
	if (draw) {
1179
	if (draw) {
1180
	    GEText(ConvertedX(mc ,dd), ConvertedY(mc, dd), str,
1180
	    GEText(ConvertedX(mc ,dd), ConvertedY(mc, dd), str,
1181
		   0.0, 0.0, mc->CurrentAngle, gc,
1181
		   0.0, 0.0, mc->CurrentAngle, gc,
1182
		   dd);
1182
		   dd);
1183
	    PMoveAcross(bboxWidth(resultBBox), mc);
1183
	    PMoveAcross(bboxWidth(resultBBox), mc);
1184
	}
1184
	}
1185
	if (UsingItalics(gc))
1185
	if (UsingItalics(gc))
1186
	    bboxItalic(resultBBox) = ItalicFactor * bboxHeight(glyphBBox);
1186
	    bboxItalic(resultBBox) = ItalicFactor * bboxHeight(glyphBBox);
1187
	else
1187
	else
1188
	    bboxItalic(resultBBox) = 0;
1188
	    bboxItalic(resultBBox) = 0;
1189
    }
1189
    }
1190
    bboxSimple(resultBBox) = 1;
1190
    bboxSimple(resultBBox) = 1;
1191
    return resultBBox;
1191
    return resultBBox;
1192
}
1192
}
1193
 
1193
 
1194
 
1194
 
1195
/* Code for Symbol Font Atoms */
1195
/* Code for Symbol Font Atoms */
1196
 
1196
 
1197
static BBOX RenderSymbol(SEXP expr, int draw, mathContext *mc,
1197
static BBOX RenderSymbol(SEXP expr, int draw, mathContext *mc,
1198
			 R_GE_gcontext *gc, GEDevDesc *dd)
1198
			 R_GE_gcontext *gc, GEDevDesc *dd)
1199
{
1199
{
1200
    int code;
1200
    int code;
1201
    if ((code = TranslatedSymbol(expr)))
1201
    if ((code = TranslatedSymbol(expr)))
1202
	return RenderSymbolChar(code, draw, mc, gc, dd);
1202
	return RenderSymbolChar(code, draw, mc, gc, dd);
1203
    else
1203
    else
1204
	return RenderSymbolStr(CHAR(PRINTNAME(expr)), draw, mc, gc, dd);
1204
	return RenderSymbolStr(CHAR(PRINTNAME(expr)), draw, mc, gc, dd);
1205
}
1205
}
1206
 
1206
 
1207
static BBOX RenderSymbolString(SEXP expr, int draw, mathContext *mc,
1207
static BBOX RenderSymbolString(SEXP expr, int draw, mathContext *mc,
1208
			       R_GE_gcontext *gc, GEDevDesc *dd)
1208
			       R_GE_gcontext *gc, GEDevDesc *dd)
1209
{
1209
{
1210
    int code;
1210
    int code;
1211
    if ((code = TranslatedSymbol(expr)))
1211
    if ((code = TranslatedSymbol(expr)))
1212
	return RenderSymbolChar(code, draw, mc, gc, dd);
1212
	return RenderSymbolChar(code, draw, mc, gc, dd);
1213
    else
1213
    else
1214
	return RenderStr(CHAR(PRINTNAME(expr)), draw, mc, gc, dd);
1214
	return RenderStr(CHAR(PRINTNAME(expr)), draw, mc, gc, dd);
1215
}
1215
}
1216
 
1216
 
1217
 
1217
 
1218
/* Code for Numeric Atoms */
1218
/* Code for Numeric Atoms */
1219
 
1219
 
1220
static BBOX RenderNumber(SEXP expr, int draw, mathContext *mc,
1220
static BBOX RenderNumber(SEXP expr, int draw, mathContext *mc,
1221
			 R_GE_gcontext *gc, GEDevDesc *dd)
1221
			 R_GE_gcontext *gc, GEDevDesc *dd)
1222
{
1222
{
1223
    BBOX bbox;
1223
    BBOX bbox;
1224
    FontType prevfont = SetFont(PlainFont, gc);
1224
    FontType prevfont = SetFont(PlainFont, gc);
1225
    bbox = RenderStr(CHAR(asChar(expr)), draw, mc, gc, dd);
1225
    bbox = RenderStr(CHAR(asChar(expr)), draw, mc, gc, dd);
1226
    SetFont(prevfont, gc);
1226
    SetFont(prevfont, gc);
1227
    return bbox;
1227
    return bbox;
1228
}
1228
}
1229
 
1229
 
1230
/* Code for String Atoms */
1230
/* Code for String Atoms */
1231
 
1231
 
1232
static BBOX RenderString(SEXP expr, int draw, mathContext *mc,
1232
static BBOX RenderString(SEXP expr, int draw, mathContext *mc,
1233
			 R_GE_gcontext *gc, GEDevDesc *dd)
1233
			 R_GE_gcontext *gc, GEDevDesc *dd)
1234
{
1234
{
1235
    return RenderStr(translateChar(STRING_ELT(expr, 0)), draw, mc, gc, dd);
1235
    return RenderStr(translateChar(STRING_ELT(expr, 0)), draw, mc, gc, dd);
1236
}
1236
}
1237
 
1237
 
1238
/* Code for Ellipsis (ldots, cdots, ...) */
1238
/* Code for Ellipsis (ldots, cdots, ...) */
1239
 
1239
 
1240
static int DotsAtom(SEXP expr)
1240
static int DotsAtom(SEXP expr)
1241
{
1241
{
1242
    if (NameMatch(expr, "cdots") ||
1242
    if (NameMatch(expr, "cdots") ||
1243
	NameMatch(expr, "...")	 ||
1243
	NameMatch(expr, "...")	 ||
1244
	NameMatch(expr, "ldots"))
1244
	NameMatch(expr, "ldots"))
1245
	    return 1;
1245
	    return 1;
1246
    return 0;
1246
    return 0;
1247
}
1247
}
1248
 
1248
 
1249
static BBOX RenderDots(SEXP expr, int draw, mathContext *mc,
1249
static BBOX RenderDots(SEXP expr, int draw, mathContext *mc,
1250
		       R_GE_gcontext *gc, GEDevDesc *dd)
1250
		       R_GE_gcontext *gc, GEDevDesc *dd)
1251
{
1251
{
1252
    BBOX bbox = RenderSymbolChar(S_ELLIPSIS, 0, mc, gc, dd);
1252
    BBOX bbox = RenderSymbolChar(S_ELLIPSIS, 0, mc, gc, dd);
1253
    if (NameMatch(expr, "cdots") || NameMatch(expr, "...")) {
1253
    if (NameMatch(expr, "cdots") || NameMatch(expr, "...")) {
1254
	double shift = AxisHeight(gc, dd) - 0.5 * bboxHeight(bbox);
1254
	double shift = AxisHeight(gc, dd) - 0.5 * bboxHeight(bbox);
1255
	if (draw) {
1255
	if (draw) {
1256
	    PMoveUp(shift, mc);
1256
	    PMoveUp(shift, mc);
1257
	    RenderSymbolChar(S_ELLIPSIS, 1, mc, gc, dd);
1257
	    RenderSymbolChar(S_ELLIPSIS, 1, mc, gc, dd);
1258
	    PMoveUp(-shift, mc);
1258
	    PMoveUp(-shift, mc);
1259
	}
1259
	}
1260
	return ShiftBBox(bbox, shift);
1260
	return ShiftBBox(bbox, shift);
1261
    }
1261
    }
1262
    else {
1262
    else {
1263
	if (draw)
1263
	if (draw)
1264
	    RenderSymbolChar(S_ELLIPSIS, 1, mc, gc, dd);
1264
	    RenderSymbolChar(S_ELLIPSIS, 1, mc, gc, dd);
1265
	return bbox;
1265
	return bbox;
1266
    }
1266
    }
1267
}
1267
}
1268
 
1268
 
1269
/*----------------------------------------------------------------------
1269
/*----------------------------------------------------------------------
1270
 *
1270
 *
1271
 *  Code for Atoms
1271
 *  Code for Atoms
1272
 *
1272
 *
1273
 */
1273
 */
1274
 
1274
 
1275
static BBOX RenderAtom(SEXP expr, int draw, mathContext *mc,
1275
static BBOX RenderAtom(SEXP expr, int draw, mathContext *mc,
1276
		       R_GE_gcontext *gc, GEDevDesc *dd)
1276
		       R_GE_gcontext *gc, GEDevDesc *dd)
1277
{
1277
{
1278
    if (NameAtom(expr)) {
1278
    if (NameAtom(expr)) {
1279
	if (DotsAtom(expr))
1279
	if (DotsAtom(expr))
1280
	    return RenderDots(expr, draw, mc, gc, dd);
1280
	    return RenderDots(expr, draw, mc, gc, dd);
1281
	else
1281
	else
1282
	    return RenderSymbol(expr, draw, mc, gc, dd);
1282
	    return RenderSymbol(expr, draw, mc, gc, dd);
1283
    }
1283
    }
1284
    else if (NumberAtom(expr))
1284
    else if (NumberAtom(expr))
1285
	return RenderNumber(expr, draw, mc, gc, dd);
1285
	return RenderNumber(expr, draw, mc, gc, dd);
1286
    else if (StringAtom(expr))
1286
    else if (StringAtom(expr))
1287
	return RenderString(expr, draw, mc, gc, dd);
1287
	return RenderString(expr, draw, mc, gc, dd);
1288
 
1288
 
1289
    return NullBBox();		/* -Wall */
1289
    return NullBBox();		/* -Wall */
1290
}
1290
}
1291
 
1291
 
1292
 
1292
 
1293
/*----------------------------------------------------------------------
1293
/*----------------------------------------------------------------------
1294
 *
1294
 *
1295
 *  Code for Binary / Unary Operators  (~, +, -, ... )
1295
 *  Code for Binary / Unary Operators  (~, +, -, ... )
1296
 *
1296
 *
1297
 *  Note that there are unary and binary ~ s.
1297
 *  Note that there are unary and binary ~ s.
1298
 *
1298
 *
1299
 */
1299
 */
1300
 
1300
 
1301
static int SpaceAtom(SEXP expr)
1301
static int SpaceAtom(SEXP expr)
1302
{
1302
{
1303
    return NameAtom(expr) && NameMatch(expr, "~");
1303
    return NameAtom(expr) && NameMatch(expr, "~");
1304
}
1304
}
1305
 
1305
 
1306
 
1306
 
1307
static BBOX RenderSpace(SEXP expr, int draw, mathContext *mc,
1307
static BBOX RenderSpace(SEXP expr, int draw, mathContext *mc,
1308
			R_GE_gcontext *gc, GEDevDesc *dd)
1308
			R_GE_gcontext *gc, GEDevDesc *dd)
1309
{
1309
{
1310
 
1310
 
1311
    BBOX opBBox, arg1BBox, arg2BBox;
1311
    BBOX opBBox, arg1BBox, arg2BBox;
1312
    int nexpr = length(expr);
1312
    int nexpr = length(expr);
1313
 
1313
 
1314
    if (nexpr == 2) {
1314
    if (nexpr == 2) {
1315
	opBBox = RenderSymbolChar(' ', draw, mc, gc, dd);
1315
	opBBox = RenderSymbolChar(' ', draw, mc, gc, dd);
1316
	arg1BBox = RenderElement(CADR(expr), draw, mc, gc, dd);
1316
	arg1BBox = RenderElement(CADR(expr), draw, mc, gc, dd);
1317
	return CombineBBoxes(opBBox, arg1BBox);
1317
	return CombineBBoxes(opBBox, arg1BBox);
1318
    }
1318
    }
1319
    else if (nexpr == 3) {
1319
    else if (nexpr == 3) {
1320
	arg1BBox = RenderElement(CADR(expr), draw, mc, gc, dd);
1320
	arg1BBox = RenderElement(CADR(expr), draw, mc, gc, dd);
1321
	opBBox = RenderSymbolChar(' ', draw, mc, gc, dd);
1321
	opBBox = RenderSymbolChar(' ', draw, mc, gc, dd);
1322
	arg2BBox = RenderElement(CADDR(expr), draw, mc, gc, dd);
1322
	arg2BBox = RenderElement(CADDR(expr), draw, mc, gc, dd);
1323
	opBBox = CombineBBoxes(arg1BBox, opBBox);
1323
	opBBox = CombineBBoxes(arg1BBox, opBBox);
1324
	opBBox = CombineBBoxes(opBBox, arg2BBox);
1324
	opBBox = CombineBBoxes(opBBox, arg2BBox);
1325
	return opBBox;
1325
	return opBBox;
1326
    }
1326
    }
1327
    else
1327
    else
1328
	error(_("invalid mathematical annotation"));
1328
	error(_("invalid mathematical annotation"));
1329
 
1329
 
1330
    return NullBBox();		/* -Wall */
1330
    return NullBBox();		/* -Wall */
1331
}
1331
}
1332
 
1332
 
1333
static SymTab BinTable[] = {
1333
static SymTab BinTable[] = {
1334
    { "*",		 052 },	/* Binary Operators */
1334
    { "*",		 052 },	/* Binary Operators */
1335
    { "+",		 053 },
1335
    { "+",		 053 },
1336
    { "-",		 055 },
1336
    { "-",		 055 },
1337
    { "/",		 057 },
1337
    { "/",		 057 },
1338
    { ":",		 072 },
1338
    { ":",		 072 },
1339
    { "%+-%",		0261 },
1339
    { "%+-%",		0261 },
1340
    { "%*%",		0264 },
1340
    { "%*%",		0264 },
1341
    { "%/%",		0270 },
1341
    { "%/%",		0270 },
1342
    { "%intersection%", 0307 },
1342
    { "%intersection%", 0307 },
1343
    { "%union%",	0310 },
1343
    { "%union%",	0310 },
1344
    { "%.%",            0327 }, /* cdot or dotmath */
1344
    { "%.%",            0327 }, /* cdot or dotmath */
1345
    { NULL,		   0 }
1345
    { NULL,		   0 }
1346
};
1346
};
1347
 
1347
 
1348
static int BinAtom(SEXP expr)
1348
static int BinAtom(SEXP expr)
1349
{
1349
{
1350
    int i;
1350
    int i;
1351
 
1351
 
1352
    for (i = 0; BinTable[i].code; i++)
1352
    for (i = 0; BinTable[i].code; i++)
1353
	if (NameMatch(expr, BinTable[i].name))
1353
	if (NameMatch(expr, BinTable[i].name))
1354
	    return BinTable[i].code;
1354
	    return BinTable[i].code;
1355
    return 0;
1355
    return 0;
1356
}
1356
}
1357
 
1357
 
1358
#define SLASH2
1358
#define SLASH2
1359
 
1359
 
1360
static BBOX RenderSlash(int draw, mathContext *mc, R_GE_gcontext *gc,
1360
static BBOX RenderSlash(int draw, mathContext *mc, R_GE_gcontext *gc,
1361
			GEDevDesc *dd)
1361
			GEDevDesc *dd)
1362
{
1362
{
1363
#ifdef SLASH0
1363
#ifdef SLASH0
1364
    /* The Default Font Character */
1364
    /* The Default Font Character */
1365
    return RenderSymbolChar(S_SLASH, draw, mc, gc, dd);
1365
    return RenderSymbolChar(S_SLASH, draw, mc, gc, dd);
1366
#endif
1366
#endif
1367
#ifdef SLASH1
1367
#ifdef SLASH1
1368
    /* Symbol Magnify Version */
1368
    /* Symbol Magnify Version */
1369
    double savecex = gc->cex;
1369
    double savecex = gc->cex;
1370
    BBOX bbox;
1370
    BBOX bbox;
1371
    double height1, height2;
1371
    double height1, height2;
1372
    height1 = bboxHeight(RenderSymbolChar(S_SLASH, 0), mc, gc, dd);
1372
    height1 = bboxHeight(RenderSymbolChar(S_SLASH, 0), mc, gc, dd);
1373
    gc->cex = 1.2 * gc->cex;
1373
    gc->cex = 1.2 * gc->cex;
1374
    height2 = bboxHeight(RenderSymbolChar(S_SLASH, 0), mc, gc, dd);
1374
    height2 = bboxHeight(RenderSymbolChar(S_SLASH, 0), mc, gc, dd);
1375
    if (draw)
1375
    if (draw)
1376
	PMoveUp(- 0.5 * (height2 - height1), mc);
1376
	PMoveUp(- 0.5 * (height2 - height1), mc);
1377
    bbox = RenderSymbolChar(S_SLASH, draw, mc, gc, dd);
1377
    bbox = RenderSymbolChar(S_SLASH, draw, mc, gc, dd);
1378
    if (draw)
1378
    if (draw)
1379
	PMoveUp(0.5 * (height2 - height1), mc);
1379
	PMoveUp(0.5 * (height2 - height1), mc);
1380
    gc->cex = savecex;
1380
    gc->cex = savecex;
1381
    return bbox;
1381
    return bbox;
1382
#endif
1382
#endif
1383
#ifdef SLASH2
1383
#ifdef SLASH2
1384
    /* Line Drawing Version */
1384
    /* Line Drawing Version */
1385
    double x[2], y[2];
1385
    double x[2], y[2];
1386
    double depth = 0.5 * TeX(sigma22, gc, dd);
1386
    double depth = 0.5 * TeX(sigma22, gc, dd);
1387
    double height = XHeight(gc, dd) + 0.5 * TeX(sigma22, gc, dd);
1387
    double height = XHeight(gc, dd) + 0.5 * TeX(sigma22, gc, dd);
1388
    double width = 0.5 * xHeight(gc, dd);
1388
    double width = 0.5 * xHeight(gc, dd);
1389
    if (draw) {
1389
    if (draw) {
1390
	int savedlty = gc->lty;
1390
	int savedlty = gc->lty;
1391
	double savedlwd = gc->lwd;
1391
	double savedlwd = gc->lwd;
1392
	PMoveAcross(0.5 * width, mc);
1392
	PMoveAcross(0.5 * width, mc);
1393
	PMoveUp(-depth, mc);
1393
	PMoveUp(-depth, mc);
1394
	x[0] = ConvertedX(mc, dd);
1394
	x[0] = ConvertedX(mc, dd);
1395
	y[0] = ConvertedY(mc, dd);
1395
	y[0] = ConvertedY(mc, dd);
1396
	PMoveAcross(width, mc);
1396
	PMoveAcross(width, mc);
1397
	PMoveUp(depth + height, mc);
1397
	PMoveUp(depth + height, mc);
1398
	x[1] = ConvertedX(mc, dd);
1398
	x[1] = ConvertedX(mc, dd);
1399
	y[1] = ConvertedY(mc, dd);
1399
	y[1] = ConvertedY(mc, dd);
1400
	PMoveUp(-height, mc);
1400
	PMoveUp(-height, mc);
1401
	gc->lty = LTY_SOLID;
1401
	gc->lty = LTY_SOLID;
1402
	if (gc->lwd > 1)
1402
	if (gc->lwd > 1)
1403
	    gc->lwd = 1;
1403
	    gc->lwd = 1;
1404
	GEPolyline(2, x, y, gc, dd);
1404
	GEPolyline(2, x, y, gc, dd);
1405
	PMoveAcross(0.5 * width, mc);
1405
	PMoveAcross(0.5 * width, mc);
1406
	gc->lty = savedlty;
1406
	gc->lty = savedlty;
1407
	gc->lwd = savedlwd;
1407
	gc->lwd = savedlwd;
1408
    }
1408
    }
1409
    return MakeBBox(height, depth, 2 * width);
1409
    return MakeBBox(height, depth, 2 * width);
1410
#endif
1410
#endif
1411
#ifdef SLASH3
1411
#ifdef SLASH3
1412
    /* Offset Overprinting - A Failure! */
1412
    /* Offset Overprinting - A Failure! */
1413
    BBOX slashBBox = RenderSymbolChar(S_SLASH, 0, mc, gc, dd);
1413
    BBOX slashBBox = RenderSymbolChar(S_SLASH, 0, mc, gc, dd);
1414
    BBOX ansBBox;
1414
    BBOX ansBBox;
1415
    double height = bboxHeight(slashBBox);
1415
    double height = bboxHeight(slashBBox);
1416
    double depth = bboxDepth(slashBBox);
1416
    double depth = bboxDepth(slashBBox);
1417
    double width = bboxWidth(slashBBox);
1417
    double width = bboxWidth(slashBBox);
1418
    double slope = (height + depth) / slope;
1418
    double slope = (height + depth) / slope;
1419
    double delta = TeX(sigma22, gc, dd);
1419
    double delta = TeX(sigma22, gc, dd);
1420
    if (draw)
1420
    if (draw)
1421
	PMoveUp(-delta, mc);
1421
	PMoveUp(-delta, mc);
1422
    ansBBox = ShiftBBox(RenderSymbolChar(S_SLASH, draw), -delta, mc, gc, dd);
1422
    ansBBox = ShiftBBox(RenderSymbolChar(S_SLASH, draw), -delta, mc, gc, dd);
1423
    PMoveUp(2 * delta, mc);
1423
    PMoveUp(2 * delta, mc);
1424
    ansBBox = CombineBBoxes(ansBBox, RenderGap(2 * delta / slope, draw,
1424
    ansBBox = CombineBBoxes(ansBBox, RenderGap(2 * delta / slope, draw,
1425
					       mc, gc, dd));
1425
					       mc, gc, dd));
1426
    ansBBox = ShiftBBox(RenderSymbolChar(S_SLASH, draw), 2 * delta,
1426
    ansBBox = ShiftBBox(RenderSymbolChar(S_SLASH, draw), 2 * delta,
1427
			mc, gc, dd);
1427
			mc, gc, dd);
1428
    PMoveUp(-delta, mc);
1428
    PMoveUp(-delta, mc);
1429
    return ansBBox;
1429
    return ansBBox;
1430
#endif
1430
#endif
1431
}
1431
}
1432
 
1432
 
1433
static BBOX RenderBin(SEXP expr, int draw, mathContext *mc,
1433
static BBOX RenderBin(SEXP expr, int draw, mathContext *mc,
1434
		      R_GE_gcontext *gc, GEDevDesc *dd)
1434
		      R_GE_gcontext *gc, GEDevDesc *dd)
1435
{
1435
{
1436
    int op = BinAtom(CAR(expr));
1436
    int op = BinAtom(CAR(expr));
1437
    int nexpr = length(expr);
1437
    int nexpr = length(expr);
1438
    BBOX bbox;
1438
    BBOX bbox;
1439
    double gap;
1439
    double gap;
1440
 
1440
 
1441
    if(nexpr == 3) {
1441
    if(nexpr == 3) {
1442
	if (op == S_ASTERISKMATH) {
1442
	if (op == S_ASTERISKMATH) {
1443
	    bbox = RenderElement(CADR(expr), draw, mc, gc, dd);
1443
	    bbox = RenderElement(CADR(expr), draw, mc, gc, dd);
1444
	    bbox = RenderItalicCorr(bbox, draw, mc, gc, dd);
1444
	    bbox = RenderItalicCorr(bbox, draw, mc, gc, dd);
1445
	    return CombineBBoxes(bbox, RenderElement(CADDR(expr), draw,
1445
	    return CombineBBoxes(bbox, RenderElement(CADDR(expr), draw,
1446
						     mc, gc, dd));
1446
						     mc, gc, dd));
1447
	}
1447
	}
1448
	else if (op == S_SLASH) {
1448
	else if (op == S_SLASH) {
1449
	    gap = 0;
1449
	    gap = 0;
1450
	    bbox = RenderElement(CADR(expr), draw, mc, gc, dd);
1450
	    bbox = RenderElement(CADR(expr), draw, mc, gc, dd);
1451
	    bbox = RenderItalicCorr(bbox, draw, mc, gc, dd);
1451
	    bbox = RenderItalicCorr(bbox, draw, mc, gc, dd);
1452
	    bbox = CombineBBoxes(bbox, RenderGap(gap, draw, mc, gc, dd));
1452
	    bbox = CombineBBoxes(bbox, RenderGap(gap, draw, mc, gc, dd));
1453
	    bbox = CombineBBoxes(bbox, RenderSlash(draw, mc, gc, dd));
1453
	    bbox = CombineBBoxes(bbox, RenderSlash(draw, mc, gc, dd));
1454
	    bbox = CombineBBoxes(bbox, RenderGap(gap, draw, mc, gc, dd));
1454
	    bbox = CombineBBoxes(bbox, RenderGap(gap, draw, mc, gc, dd));
1455
	    return CombineBBoxes(bbox, RenderElement(CADDR(expr), draw,
1455
	    return CombineBBoxes(bbox, RenderElement(CADDR(expr), draw,
1456
						     mc, gc, dd));
1456
						     mc, gc, dd));
1457
	}
1457
	}
1458
	else {
1458
	else {
1459
	    gap = (mc->CurrentStyle > STYLE_S) ? MediumSpace(gc, dd) : 0;
1459
	    gap = (mc->CurrentStyle > STYLE_S) ? MediumSpace(gc, dd) : 0;
1460
	    bbox = RenderElement(CADR(expr), draw, mc, gc, dd);
1460
	    bbox = RenderElement(CADR(expr), draw, mc, gc, dd);
1461
	    bbox = RenderItalicCorr(bbox, draw, mc, gc, dd);
1461
	    bbox = RenderItalicCorr(bbox, draw, mc, gc, dd);
1462
	    bbox = CombineBBoxes(bbox, RenderGap(gap, draw, mc, gc, dd));
1462
	    bbox = CombineBBoxes(bbox, RenderGap(gap, draw, mc, gc, dd));
1463
	    bbox = CombineBBoxes(bbox, RenderSymbolChar(op, draw, mc, gc, dd));
1463
	    bbox = CombineBBoxes(bbox, RenderSymbolChar(op, draw, mc, gc, dd));
1464
	    bbox = CombineBBoxes(bbox, RenderGap(gap, draw, mc, gc, dd));
1464
	    bbox = CombineBBoxes(bbox, RenderGap(gap, draw, mc, gc, dd));
1465
	    return CombineBBoxes(bbox, RenderElement(CADDR(expr), draw,
1465
	    return CombineBBoxes(bbox, RenderElement(CADDR(expr), draw,
1466
						     mc, gc, dd));
1466
						     mc, gc, dd));
1467
	}
1467
	}
1468
    }
1468
    }
1469
    else if(nexpr == 2) {
1469
    else if(nexpr == 2) {
1470
	gap = (mc->CurrentStyle > STYLE_S) ? ThinSpace(gc, dd) : 0;
1470
	gap = (mc->CurrentStyle > STYLE_S) ? ThinSpace(gc, dd) : 0;
1471
	bbox = RenderSymbolChar(op, draw, mc, gc, dd);
1471
	bbox = RenderSymbolChar(op, draw, mc, gc, dd);
1472
	bbox = CombineBBoxes(bbox, RenderGap(gap, draw, mc, gc, dd));
1472
	bbox = CombineBBoxes(bbox, RenderGap(gap, draw, mc, gc, dd));
1473
	return CombineBBoxes(bbox, RenderElement(CADR(expr), draw, mc,
1473
	return CombineBBoxes(bbox, RenderElement(CADR(expr), draw, mc,
1474
						 gc, dd));
1474
						 gc, dd));
1475
    }
1475
    }
1476
    else
1476
    else
1477
	error(_("invalid mathematical annotation"));
1477
	error(_("invalid mathematical annotation"));
1478
 
1478
 
1479
    return NullBBox();		/* -Wall */
1479
    return NullBBox();		/* -Wall */
1480
 
1480
 
1481
}
1481
}
1482
 
1482
 
1483
 
1483
 
1484
/*----------------------------------------------------------------------
1484
/*----------------------------------------------------------------------
1485
 *
1485
 *
1486
 *  Code for Subscript and Superscipt Expressions
1486
 *  Code for Subscript and Superscipt Expressions
1487
 *
1487
 *
1488
 *  Rules 18, 18a, ..., 18f of the TeXBook.
1488
 *  Rules 18, 18a, ..., 18f of the TeXBook.
1489
 *
1489
 *
1490
 */
1490
 */
1491
 
1491
 
1492
static int SuperAtom(SEXP expr)
1492
static int SuperAtom(SEXP expr)
1493
{
1493
{
1494
    return NameAtom(expr) && NameMatch(expr, "^");
1494
    return NameAtom(expr) && NameMatch(expr, "^");
1495
}
1495
}
1496
 
1496
 
1497
static int SubAtom(SEXP expr)
1497
static int SubAtom(SEXP expr)
1498
{
1498
{
1499
    return NameAtom(expr) && NameMatch(expr, "[");
1499
    return NameAtom(expr) && NameMatch(expr, "[");
1500
}
1500
}
1501
 
1501
 
1502
/* Note : If all computations are correct */
1502
/* Note : If all computations are correct */
1503
/* We do not need to save and restore the */
1503
/* We do not need to save and restore the */
1504
/* current location here.  This is paranoia. */
1504
/* current location here.  This is paranoia. */
1505
static BBOX RenderSub(SEXP expr, int draw, mathContext *mc,
1505
static BBOX RenderSub(SEXP expr, int draw, mathContext *mc,
1506
		      R_GE_gcontext *gc, GEDevDesc *dd)
1506
		      R_GE_gcontext *gc, GEDevDesc *dd)
1507
{
1507
{
1508
    BBOX bodyBBox, subBBox;
1508
    BBOX bodyBBox, subBBox;
1509
    SEXP body = CADR(expr);
1509
    SEXP body = CADR(expr);
1510
    SEXP sub = CADDR(expr);
1510
    SEXP sub = CADDR(expr);
1511
    STYLE style = GetStyle(mc);
1511
    STYLE style = GetStyle(mc);
1512
    double savedX = mc->CurrentX;
1512
    double savedX = mc->CurrentX;
1513
    double savedY = mc->CurrentY;
1513
    double savedY = mc->CurrentY;
1514
    double v, s5, s16;
1514
    double v, s5, s16;
1515
    bodyBBox = RenderElement(body, draw, mc, gc, dd);
1515
    bodyBBox = RenderElement(body, draw, mc, gc, dd);
1516
    bodyBBox = RenderItalicCorr(bodyBBox, draw, mc, gc, dd);
1516
    bodyBBox = RenderItalicCorr(bodyBBox, draw, mc, gc, dd);
1517
    v = bboxSimple(bodyBBox) ? 0 : bboxDepth(bodyBBox) + TeX(sigma19, gc, dd);
1517
    v = bboxSimple(bodyBBox) ? 0 : bboxDepth(bodyBBox) + TeX(sigma19, gc, dd);
1518
    s5 = TeX(sigma5, gc, dd);
1518
    s5 = TeX(sigma5, gc, dd);
1519
    s16 = TeX(sigma16, gc, dd);
1519
    s16 = TeX(sigma16, gc, dd);
1520
    SetSubStyle(style, mc, gc);
1520
    SetSubStyle(style, mc, gc);
1521
    subBBox = RenderElement(sub, 0, mc, gc, dd);
1521
    subBBox = RenderElement(sub, 0, mc, gc, dd);
1522
    v = max(max(v, s16), bboxHeight(subBBox) - 0.8 * sigma5);
1522
    v = max(max(v, s16), bboxHeight(subBBox) - 0.8 * sigma5);
1523
    subBBox = RenderOffsetElement(sub, 0, -v, draw, mc, gc, dd);
1523
    subBBox = RenderOffsetElement(sub, 0, -v, draw, mc, gc, dd);
1524
    bodyBBox = CombineBBoxes(bodyBBox, subBBox);
1524
    bodyBBox = CombineBBoxes(bodyBBox, subBBox);
1525
    SetStyle(style, mc, gc);
1525
    SetStyle(style, mc, gc);
1526
    if (draw)
1526
    if (draw)
1527
	PMoveTo(savedX + bboxWidth(bodyBBox), savedY, mc);
1527
	PMoveTo(savedX + bboxWidth(bodyBBox), savedY, mc);
1528
    return bodyBBox;
1528
    return bodyBBox;
1529
}
1529
}
1530
 
1530
 
1531
static BBOX RenderSup(SEXP expr, int draw, mathContext *mc,
1531
static BBOX RenderSup(SEXP expr, int draw, mathContext *mc,
1532
		      R_GE_gcontext *gc, GEDevDesc *dd)
1532
		      R_GE_gcontext *gc, GEDevDesc *dd)
1533
{
1533
{
1534
    BBOX bodyBBox, subBBox, supBBox;
1534
    BBOX bodyBBox, subBBox, supBBox;
1535
    SEXP body = CADR(expr);
1535
    SEXP body = CADR(expr);
1536
    SEXP sup = CADDR(expr);
1536
    SEXP sup = CADDR(expr);
1537
    SEXP sub = R_NilValue;	/* -Wall */
1537
    SEXP sub = R_NilValue;	/* -Wall */
1538
    STYLE style = GetStyle(mc);
1538
    STYLE style = GetStyle(mc);
1539
    double savedX = mc->CurrentX;
1539
    double savedX = mc->CurrentX;
1540
    double savedY = mc->CurrentY;
1540
    double savedY = mc->CurrentY;
1541
    double theta, delta, width;
1541
    double theta, delta, width;
1542
    double u, p;
1542
    double u, p;
1543
    double v, s5, s17;
1543
    double v, s5, s17;
1544
    int haveSub;
1544
    int haveSub;
1545
    if (FormulaExpression(body) && SubAtom(CAR(body))) {
1545
    if (FormulaExpression(body) && SubAtom(CAR(body))) {
1546
	sub = CADDR(body);
1546
	sub = CADDR(body);
1547
	body = CADR(body);
1547
	body = CADR(body);
1548
	haveSub = 1;
1548
	haveSub = 1;
1549
    }
1549
    }
1550
    else haveSub = 0;
1550
    else haveSub = 0;
1551
    bodyBBox = RenderElement(body, draw, mc, gc, dd);
1551
    bodyBBox = RenderElement(body, draw, mc, gc, dd);
1552
    delta = bboxItalic(bodyBBox);
1552
    delta = bboxItalic(bodyBBox);
1553
    bodyBBox = RenderItalicCorr(bodyBBox, draw, mc, gc, dd);
1553
    bodyBBox = RenderItalicCorr(bodyBBox, draw, mc, gc, dd);
1554
    width = bboxWidth(bodyBBox);
1554
    width = bboxWidth(bodyBBox);
1555
    if (bboxSimple(bodyBBox)) {
1555
    if (bboxSimple(bodyBBox)) {
1556
	u = 0;
1556
	u = 0;
1557
	v = 0;
1557
	v = 0;
1558
    }
1558
    }
1559
    else {
1559
    else {
1560
	u = bboxHeight(bodyBBox) - TeX(sigma18, gc, dd);
1560
	u = bboxHeight(bodyBBox) - TeX(sigma18, gc, dd);
1561
	v = bboxDepth(bodyBBox) + TeX(sigma19, gc, dd);
1561
	v = bboxDepth(bodyBBox) + TeX(sigma19, gc, dd);
1562
    }
1562
    }
1563
    theta = TeX(xi8, gc, dd);
1563
    theta = TeX(xi8, gc, dd);
1564
    s5 = TeX(sigma5, gc, dd);
1564
    s5 = TeX(sigma5, gc, dd);
1565
    s17 = TeX(sigma17, gc, dd);
1565
    s17 = TeX(sigma17, gc, dd);
1566
    if (style == STYLE_D)
1566
    if (style == STYLE_D)
1567
	p = TeX(sigma13, gc, dd);
1567
	p = TeX(sigma13, gc, dd);
1568
    else if (IsCompactStyle(style, mc, gc))
1568
    else if (IsCompactStyle(style, mc, gc))
1569
	p = TeX(sigma15, gc, dd);
1569
	p = TeX(sigma15, gc, dd);
1570
    else
1570
    else
1571
	p = TeX(sigma14, gc, dd);
1571
	p = TeX(sigma14, gc, dd);
1572
    SetSupStyle(style, mc, gc);
1572
    SetSupStyle(style, mc, gc);
1573
    supBBox = RenderElement(sup, 0, mc, gc, dd);
1573
    supBBox = RenderElement(sup, 0, mc, gc, dd);
1574
    u = max(max(u, p), bboxDepth(supBBox) + 0.25 * s5);
1574
    u = max(max(u, p), bboxDepth(supBBox) + 0.25 * s5);
1575
 
1575
 
1576
    if (haveSub) {
1576
    if (haveSub) {
1577
	SetSubStyle(style, mc, gc);
1577
	SetSubStyle(style, mc, gc);
1578
	subBBox = RenderElement(sub, 0, mc, gc, dd);
1578
	subBBox = RenderElement(sub, 0, mc, gc, dd);
1579
	v = max(v, s17);
1579
	v = max(v, s17);
1580
	if ((u - bboxDepth(supBBox)) - (bboxHeight(subBBox) - v) < 4 * theta) {
1580
	if ((u - bboxDepth(supBBox)) - (bboxHeight(subBBox) - v) < 4 * theta) {
1581
	    double psi = 0.8 * s5 - (u - bboxDepth(supBBox));
1581
	    double psi = 0.8 * s5 - (u - bboxDepth(supBBox));
1582
	    if (psi > 0) {
1582
	    if (psi > 0) {
1583
		u += psi;
1583
		u += psi;
1584
		v -= psi;
1584
		v -= psi;
1585
	    }
1585
	    }
1586
	}
1586
	}
1587
	if (draw)
1587
	if (draw)
1588
	    PMoveTo(savedX, savedY, mc);
1588
	    PMoveTo(savedX, savedY, mc);
1589
	subBBox = RenderOffsetElement(sub, width, -v, draw, mc, gc, dd);
1589
	subBBox = RenderOffsetElement(sub, width, -v, draw, mc, gc, dd);
1590
	if (draw)
1590
	if (draw)
1591
	    PMoveTo(savedX, savedY, mc);
1591
	    PMoveTo(savedX, savedY, mc);
1592
	SetSupStyle(style, mc, gc);
1592
	SetSupStyle(style, mc, gc);
1593
	supBBox = RenderOffsetElement(sup, width + delta, u, draw, mc, gc, dd);
1593
	supBBox = RenderOffsetElement(sup, width + delta, u, draw, mc, gc, dd);
1594
	bodyBBox = CombineAlignedBBoxes(bodyBBox, subBBox);
1594
	bodyBBox = CombineAlignedBBoxes(bodyBBox, subBBox);
1595
	bodyBBox = CombineAlignedBBoxes(bodyBBox, supBBox);
1595
	bodyBBox = CombineAlignedBBoxes(bodyBBox, supBBox);
1596
    }
1596
    }
1597
    else {
1597
    else {
1598
	supBBox = RenderOffsetElement(sup, 0, u, draw, mc, gc, dd);
1598
	supBBox = RenderOffsetElement(sup, 0, u, draw, mc, gc, dd);
1599
	bodyBBox = CombineBBoxes(bodyBBox, supBBox);
1599
	bodyBBox = CombineBBoxes(bodyBBox, supBBox);
1600
    }
1600
    }
1601
    if (draw)
1601
    if (draw)
1602
	PMoveTo(savedX + bboxWidth(bodyBBox), savedY, mc);
1602
	PMoveTo(savedX + bboxWidth(bodyBBox), savedY, mc);
1603
    SetStyle(style, mc, gc);
1603
    SetStyle(style, mc, gc);
1604
    return bodyBBox;
1604
    return bodyBBox;
1605
}
1605
}
1606
 
1606
 
1607
 
1607
 
1608
/*----------------------------------------------------------------------
1608
/*----------------------------------------------------------------------
1609
 *
1609
 *
1610
 *  Code for Accented Expressions (widehat, bar, widetilde, ...)
1610
 *  Code for Accented Expressions (widehat, bar, widetilde, ...)
1611
 *
1611
 *
1612
 */
1612
 */
1613
 
1613
 
1614
#define ACCENT_GAP  0.2
1614
#define ACCENT_GAP  0.2
1615
#define HAT_HEIGHT  0.3
1615
#define HAT_HEIGHT  0.3
1616
 
1616
 
1617
#define NTILDE	    8
1617
#define NTILDE	    8
1618
#define DELTA	    0.05
1618
#define DELTA	    0.05
1619
 
1619
 
1620
static int WideTildeAtom(SEXP expr)
1620
static int WideTildeAtom(SEXP expr)
1621
{
1621
{
1622
    return NameAtom(expr) && NameMatch(expr, "widetilde");
1622
    return NameAtom(expr) && NameMatch(expr, "widetilde");
1623
}
1623
}
1624
 
1624
 
1625
static BBOX RenderWideTilde(SEXP expr, int draw, mathContext *mc,
1625
static BBOX RenderWideTilde(SEXP expr, int draw, mathContext *mc,
1626
			    R_GE_gcontext *gc, GEDevDesc *dd)
1626
			    R_GE_gcontext *gc, GEDevDesc *dd)
1627
{
1627
{
1628
    double savedX = mc->CurrentX;
1628
    double savedX = mc->CurrentX;
1629
    double savedY = mc->CurrentY;
1629
    double savedY = mc->CurrentY;
1630
    BBOX bbox = RenderElement(CADR(expr), draw, mc, gc, dd);
1630
    BBOX bbox = RenderElement(CADR(expr), draw, mc, gc, dd);
1631
    double height = bboxHeight(bbox);
1631
    double height = bboxHeight(bbox);
1632
    /*double width = bboxWidth(bbox);*/
1632
    /*double width = bboxWidth(bbox);*/
1633
    double totalwidth = bboxWidth(bbox) + bboxItalic(bbox);
1633
    double totalwidth = bboxWidth(bbox) + bboxItalic(bbox);
1634
    double delta = totalwidth * (1 - 2 * DELTA) / NTILDE;
1634
    double delta = totalwidth * (1 - 2 * DELTA) / NTILDE;
1635
    double start = DELTA * totalwidth;
1635
    double start = DELTA * totalwidth;
1636
    double accentGap = ACCENT_GAP * XHeight(gc, dd);
1636
    double accentGap = ACCENT_GAP * XHeight(gc, dd);
1637
    double hatHeight = 0.5 * HAT_HEIGHT * XHeight(gc, dd);
1637
    double hatHeight = 0.5 * HAT_HEIGHT * XHeight(gc, dd);
1638
    double c = 8 * atan(1.0) / NTILDE;
1638
    double c = 8 * atan(1.0) / NTILDE;
1639
    double x[NTILDE + 3], y[NTILDE + 3];
1639
    double x[NTILDE + 3], y[NTILDE + 3];
1640
    double baseX, baseY, xval, yval;
1640
    double baseX, baseY, xval, yval;
1641
    int i;
1641
    int i;
1642
 
1642
 
1643
    if (draw) {
1643
    if (draw) {
1644
	int savedlty = gc->lty;
1644
	int savedlty = gc->lty;
1645
	double savedlwd = gc->lwd;
1645
	double savedlwd = gc->lwd;
1646
	baseX = savedX;
1646
	baseX = savedX;
1647
	baseY = savedY + height + accentGap;
1647
	baseY = savedY + height + accentGap;
1648
	PMoveTo(baseX, baseY, mc);
1648
	PMoveTo(baseX, baseY, mc);
1649
	x[0] = ConvertedX(mc, dd);
1649
	x[0] = ConvertedX(mc, dd);
1650
	y[0] = ConvertedY(mc, dd);
1650
	y[0] = ConvertedY(mc, dd);
1651
	for (i = 0; i <= NTILDE; i++) {
1651
	for (i = 0; i <= NTILDE; i++) {
1652
	    xval = start + i * delta;
1652
	    xval = start + i * delta;
1653
	    yval = 0.5 * hatHeight * (sin(c * i) + 1);
1653
	    yval = 0.5 * hatHeight * (sin(c * i) + 1);
1654
	    PMoveTo(baseX + xval, baseY + yval, mc);
1654
	    PMoveTo(baseX + xval, baseY + yval, mc);
1655
	    x[i + 1] = ConvertedX(mc, dd);
1655
	    x[i + 1] = ConvertedX(mc, dd);
1656
	    y[i + 1] = ConvertedY(mc, dd);
1656
	    y[i + 1] = ConvertedY(mc, dd);
1657
	}
1657
	}
1658
	PMoveTo(baseX + totalwidth, baseY + hatHeight, mc);
1658
	PMoveTo(baseX + totalwidth, baseY + hatHeight, mc);
1659
	x[NTILDE + 2] = ConvertedX(mc, dd);
1659
	x[NTILDE + 2] = ConvertedX(mc, dd);
1660
	y[NTILDE + 2] = ConvertedY(mc, dd);
1660
	y[NTILDE + 2] = ConvertedY(mc, dd);
1661
	gc->lty = LTY_SOLID;
1661
	gc->lty = LTY_SOLID;
1662
	if (gc->lwd > 1)
1662
	if (gc->lwd > 1)
1663
	    gc->lwd = 1;
1663
	    gc->lwd = 1;
1664
	GEPolyline(NTILDE + 3, x, y, gc, dd);
1664
	GEPolyline(NTILDE + 3, x, y, gc, dd);
1665
	PMoveTo(savedX + totalwidth, savedY, mc);
1665
	PMoveTo(savedX + totalwidth, savedY, mc);
1666
	gc->lty = savedlty;
1666
	gc->lty = savedlty;
1667
	gc->lwd = savedlwd;
1667
	gc->lwd = savedlwd;
1668
    }
1668
    }
1669
    return MakeBBox(height + accentGap + hatHeight,
1669
    return MakeBBox(height + accentGap + hatHeight,
1670
		    bboxDepth(bbox), totalwidth);
1670
		    bboxDepth(bbox), totalwidth);
1671
}
1671
}
1672
 
1672
 
1673
static int WideHatAtom(SEXP expr)
1673
static int WideHatAtom(SEXP expr)
1674
{
1674
{
1675
    return NameAtom(expr) && NameMatch(expr, "widehat");
1675
    return NameAtom(expr) && NameMatch(expr, "widehat");
1676
}
1676
}
1677
 
1677
 
1678
static BBOX RenderWideHat(SEXP expr, int draw, mathContext *mc,
1678
static BBOX RenderWideHat(SEXP expr, int draw, mathContext *mc,
1679
			  R_GE_gcontext *gc, GEDevDesc *dd)
1679
			  R_GE_gcontext *gc, GEDevDesc *dd)
1680
{
1680
{
1681
    double savedX = mc->CurrentX;
1681
    double savedX = mc->CurrentX;
1682
    double savedY = mc->CurrentY;
1682
    double savedY = mc->CurrentY;
1683
    BBOX bbox = RenderElement(CADR(expr), draw, mc, gc, dd);
1683
    BBOX bbox = RenderElement(CADR(expr), draw, mc, gc, dd);
1684
    double accentGap = ACCENT_GAP * XHeight(gc, dd);
1684
    double accentGap = ACCENT_GAP * XHeight(gc, dd);
1685
    double hatHeight = HAT_HEIGHT * XHeight(gc, dd);
1685
    double hatHeight = HAT_HEIGHT * XHeight(gc, dd);
1686
    double totalwidth = bboxWidth(bbox) + bboxItalic(bbox);
1686
    double totalwidth = bboxWidth(bbox) + bboxItalic(bbox);
1687
    double height = bboxHeight(bbox);
1687
    double height = bboxHeight(bbox);
1688
    double width = bboxWidth(bbox);
1688
    double width = bboxWidth(bbox);
1689
    double x[3], y[3];
1689
    double x[3], y[3];
1690
 
1690
 
1691
    if (draw) {
1691
    if (draw) {
1692
	int savedlty = gc->lty;
1692
	int savedlty = gc->lty;
1693
	double savedlwd = gc->lwd;
1693
	double savedlwd = gc->lwd;
1694
	PMoveTo(savedX, savedY + height + accentGap, mc);
1694
	PMoveTo(savedX, savedY + height + accentGap, mc);
1695
	x[0] = ConvertedX(mc, dd);
1695
	x[0] = ConvertedX(mc, dd);
1696
	y[0] = ConvertedY(mc, dd);
1696
	y[0] = ConvertedY(mc, dd);
1697
	PMoveAcross(0.5 * totalwidth, mc);
1697
	PMoveAcross(0.5 * totalwidth, mc);
1698
	PMoveUp(hatHeight, mc);
1698
	PMoveUp(hatHeight, mc);
1699
	x[1] = ConvertedX(mc, dd);
1699
	x[1] = ConvertedX(mc, dd);
1700
	y[1] = ConvertedY(mc, dd);
1700
	y[1] = ConvertedY(mc, dd);
1701
	PMoveAcross(0.5 * totalwidth, mc);
1701
	PMoveAcross(0.5 * totalwidth, mc);
1702
	PMoveUp(-hatHeight, mc);
1702
	PMoveUp(-hatHeight, mc);
1703
	x[2] = ConvertedX(mc, dd);
1703
	x[2] = ConvertedX(mc, dd);
1704
	y[2] = ConvertedY(mc, dd);
1704
	y[2] = ConvertedY(mc, dd);
1705
	gc->lty = LTY_SOLID;
1705
	gc->lty = LTY_SOLID;
1706
	if (gc->lwd > 1)
1706
	if (gc->lwd > 1)
1707
	    gc->lwd = 1;
1707
	    gc->lwd = 1;
1708
	GEPolyline(3, x, y, gc, dd);
1708
	GEPolyline(3, x, y, gc, dd);
1709
	PMoveTo(savedX + width, savedY, mc);
1709
	PMoveTo(savedX + width, savedY, mc);
1710
	gc->lty = savedlty;
1710
	gc->lty = savedlty;
1711
	gc->lwd = savedlwd;
1711
	gc->lwd = savedlwd;
1712
    }
1712
    }
1713
    return EnlargeBBox(bbox, accentGap + hatHeight, 0, 0);
1713
    return EnlargeBBox(bbox, accentGap + hatHeight, 0, 0);
1714
}
1714
}
1715
 
1715
 
1716
static int BarAtom(SEXP expr)
1716
static int BarAtom(SEXP expr)
1717
{
1717
{
1718
    return NameAtom(expr) && NameMatch(expr, "bar");
1718
    return NameAtom(expr) && NameMatch(expr, "bar");
1719
}
1719
}
1720
 
1720
 
1721
static BBOX RenderBar(SEXP expr, int draw, mathContext *mc,
1721
static BBOX RenderBar(SEXP expr, int draw, mathContext *mc,
1722
		      R_GE_gcontext *gc, GEDevDesc *dd)
1722
		      R_GE_gcontext *gc, GEDevDesc *dd)
1723
{
1723
{
1724
    double savedX = mc->CurrentX;
1724
    double savedX = mc->CurrentX;
1725
    double savedY = mc->CurrentY;
1725
    double savedY = mc->CurrentY;
1726
    BBOX bbox = RenderElement(CADR(expr), draw, mc, gc, dd);
1726
    BBOX bbox = RenderElement(CADR(expr), draw, mc, gc, dd);
1727
    double accentGap = ACCENT_GAP * XHeight(gc, dd);
1727
    double accentGap = ACCENT_GAP * XHeight(gc, dd);
1728
    /*double hatHeight = HAT_HEIGHT * XHeight(gc, dd);*/
1728
    /*double hatHeight = HAT_HEIGHT * XHeight(gc, dd);*/
1729
    double height = bboxHeight(bbox);
1729
    double height = bboxHeight(bbox);
1730
    double width = bboxWidth(bbox);
1730
    double width = bboxWidth(bbox);
1731
    double offset = bboxItalic(bbox);
1731
    double offset = bboxItalic(bbox);
1732
    double x[2], y[2];
1732
    double x[2], y[2];
1733
 
1733
 
1734
    if (draw) {
1734
    if (draw) {
1735
	int savedlty = gc->lty;
1735
	int savedlty = gc->lty;
1736
	double savedlwd = gc->lwd;
1736
	double savedlwd = gc->lwd;
1737
	PMoveTo(savedX + offset, savedY + height + accentGap, mc);
1737
	PMoveTo(savedX + offset, savedY + height + accentGap, mc);
1738
	x[0] = ConvertedX(mc, dd);
1738
	x[0] = ConvertedX(mc, dd);
1739
	y[0] = ConvertedY(mc, dd);
1739
	y[0] = ConvertedY(mc, dd);
1740
	PMoveAcross(width, mc);
1740
	PMoveAcross(width, mc);
1741
	x[1] = ConvertedX(mc, dd);
1741
	x[1] = ConvertedX(mc, dd);
1742
	y[1] = ConvertedY(mc, dd);
1742
	y[1] = ConvertedY(mc, dd);
1743
	gc->lty = LTY_SOLID;
1743
	gc->lty = LTY_SOLID;
1744
	if (gc->lwd > 1)
1744
	if (gc->lwd > 1)
1745
	    gc->lwd = 1;
1745
	    gc->lwd = 1;
1746
	GEPolyline(2, x, y, gc, dd);
1746
	GEPolyline(2, x, y, gc, dd);
1747
	PMoveTo(savedX + width, savedY, mc);
1747
	PMoveTo(savedX + width, savedY, mc);
1748
	gc->lty = savedlty;
1748
	gc->lty = savedlty;
1749
	gc->lwd = savedlwd;
1749
	gc->lwd = savedlwd;
1750
    }
1750
    }
1751
    return EnlargeBBox(bbox, accentGap, 0, 0);
1751
    return EnlargeBBox(bbox, accentGap, 0, 0);
1752
}
1752
}
1753
 
1753
 
1754
static struct {
1754
static struct {
1755
    char *name;
1755
    char *name;
1756
    int code;
1756
    int code;
1757
}
1757
}
1758
AccentTable[] = {
1758
AccentTable[] = {
1759
    { "hat",		 94 },
1759
    { "hat",		 94 },
1760
    { "ring",		176 },
1760
    { "ring",		176 },
1761
    { "tilde",		126 },
1761
    { "tilde",		126 },
1762
    { "dot",            215 },
1762
    { "dot",            215 },
1763
    { NULL,		  0 },
1763
    { NULL,		  0 },
1764
};
1764
};
1765
 
1765
 
1766
static int AccentCode(SEXP expr)
1766
static int AccentCode(SEXP expr)
1767
{
1767
{
1768
    int i;
1768
    int i;
1769
    for (i = 0; AccentTable[i].code; i++)
1769
    for (i = 0; AccentTable[i].code; i++)
1770
	if (NameMatch(expr, AccentTable[i].name))
1770
	if (NameMatch(expr, AccentTable[i].name))
1771
	    return AccentTable[i].code;
1771
	    return AccentTable[i].code;
1772
    return 0;
1772
    return 0;
1773
}
1773
}
1774
 
1774
 
1775
static int AccentAtom(SEXP expr)
1775
static int AccentAtom(SEXP expr)
1776
{
1776
{
1777
    return NameAtom(expr) && (AccentCode(expr) != 0);
1777
    return NameAtom(expr) && (AccentCode(expr) != 0);
1778
}
1778
}
1779
 
1779
 
1780
static void InvalidAccent(SEXP expr)
1780
static void InvalidAccent(SEXP expr)
1781
{
1781
{
1782
    errorcall(expr, _("invalid accent"));
1782
    errorcall(expr, _("invalid accent"));
1783
}
1783
}
1784
 
1784
 
1785
static BBOX RenderAccent(SEXP expr, int draw, mathContext *mc,
1785
static BBOX RenderAccent(SEXP expr, int draw, mathContext *mc,
1786
			 R_GE_gcontext *gc, GEDevDesc *dd)
1786
			 R_GE_gcontext *gc, GEDevDesc *dd)
1787
{
1787
{
1788
    SEXP body, accent;
1788
    SEXP body, accent;
1789
    double savedX = mc->CurrentX;
1789
    double savedX = mc->CurrentX;
1790
    double savedY = mc->CurrentY;
1790
    double savedY = mc->CurrentY;
1791
    BBOX bodyBBox, accentBBox;
1791
    BBOX bodyBBox, accentBBox;
1792
    double xoffset, yoffset, width, italic;
1792
    double xoffset, yoffset, width, italic;
1793
    int code;
1793
    int code;
1794
    if (length(expr) != 2)
1794
    if (length(expr) != 2)
1795
	InvalidAccent(expr);
1795
	InvalidAccent(expr);
1796
    accent = CAR(expr);
1796
    accent = CAR(expr);
1797
    body = CADR(expr);
1797
    body = CADR(expr);
1798
    code = AccentCode(accent);
1798
    code = AccentCode(accent);
1799
    if (code == 0)
1799
    if (code == 0)
1800
	InvalidAccent(expr);
1800
	InvalidAccent(expr);
1801
    bodyBBox = RenderElement(body, 0, mc, gc, dd);
1801
    bodyBBox = RenderElement(body, 0, mc, gc, dd);
1802
    italic = bboxItalic(bodyBBox);
1802
    italic = bboxItalic(bodyBBox);
1803
    if (code == 176 || /* ring (as degree) */
1803
    if (code == 176 || /* ring (as degree) */
1804
	code == 215)   /* dotmath */
1804
	code == 215)   /* dotmath */
1805
	accentBBox = RenderSymbolChar(code, 0, mc, gc, dd);
1805
	accentBBox = RenderSymbolChar(code, 0, mc, gc, dd);
1806
    else
1806
    else
1807
	accentBBox = RenderChar(code, 0, mc, gc, dd);
1807
	accentBBox = RenderChar(code, 0, mc, gc, dd);
1808
    width = max(bboxWidth(bodyBBox) + bboxItalic(bodyBBox),
1808
    width = max(bboxWidth(bodyBBox) + bboxItalic(bodyBBox),
1809
		bboxWidth(accentBBox));
1809
		bboxWidth(accentBBox));
1810
    xoffset = 0.5 *(width - bboxWidth(bodyBBox));
1810
    xoffset = 0.5 *(width - bboxWidth(bodyBBox));
1811
    bodyBBox = RenderGap(xoffset, draw, mc, gc, dd);
1811
    bodyBBox = RenderGap(xoffset, draw, mc, gc, dd);
1812
    bodyBBox = CombineBBoxes(bodyBBox, RenderElement(body, draw, mc, gc, dd));
1812
    bodyBBox = CombineBBoxes(bodyBBox, RenderElement(body, draw, mc, gc, dd));
1813
    bodyBBox = CombineBBoxes(bodyBBox, RenderGap(xoffset, draw, mc, gc, dd));
1813
    bodyBBox = CombineBBoxes(bodyBBox, RenderGap(xoffset, draw, mc, gc, dd));
1814
    PMoveTo(savedX, savedY, mc);
1814
    PMoveTo(savedX, savedY, mc);
1815
    xoffset = 0.5 *(width - bboxWidth(accentBBox))
1815
    xoffset = 0.5 *(width - bboxWidth(accentBBox))
1816
	+ 0.9 * italic;
1816
	+ 0.9 * italic;
1817
    yoffset = bboxHeight(bodyBBox) + bboxDepth(accentBBox) +
1817
    yoffset = bboxHeight(bodyBBox) + bboxDepth(accentBBox) +
1818
	0.1 * XHeight(gc, dd);
1818
	0.1 * XHeight(gc, dd);
1819
    if (draw) {
1819
    if (draw) {
1820
	PMoveTo(savedX + xoffset, savedY + yoffset, mc);
1820
	PMoveTo(savedX + xoffset, savedY + yoffset, mc);
1821
	if (code == 176 || /* ring (as degree) */
1821
	if (code == 176 || /* ring (as degree) */
1822
	    code == 215) /* dotmath */
1822
	    code == 215) /* dotmath */
1823
	    RenderSymbolChar(code, draw, mc, gc, dd);
1823
	    RenderSymbolChar(code, draw, mc, gc, dd);
1824
	else
1824
	else
1825
	    RenderChar(code, draw, mc, gc, dd);
1825
	    RenderChar(code, draw, mc, gc, dd);
1826
    }
1826
    }
1827
    bodyBBox = CombineOffsetBBoxes(bodyBBox, 0, accentBBox, 0,
1827
    bodyBBox = CombineOffsetBBoxes(bodyBBox, 0, accentBBox, 0,
1828
				   xoffset, yoffset);
1828
				   xoffset, yoffset);
1829
    if (draw)
1829
    if (draw)
1830
	PMoveTo(savedX + width, savedY, mc);
1830
	PMoveTo(savedX + width, savedY, mc);
1831
    return bodyBBox;
1831
    return bodyBBox;
1832
}
1832
}
1833
 
1833
 
1834
 
1834
 
1835
/*----------------------------------------------------------------------
1835
/*----------------------------------------------------------------------
1836
 *
1836
 *
1837
 *  Code for Fraction Expressions  (over, atop)
1837
 *  Code for Fraction Expressions  (over, atop)
1838
 *
1838
 *
1839
 *  Rules 15, 15a, ..., 15e of the TeXBook
1839
 *  Rules 15, 15a, ..., 15e of the TeXBook
1840
 *
1840
 *
1841
 */
1841
 */
1842
 
1842
 
1843
static void NumDenomVShift(BBOX numBBox, BBOX denomBBox,
1843
static void NumDenomVShift(BBOX numBBox, BBOX denomBBox,
1844
			   double *u, double *v,
1844
			   double *u, double *v,
1845
			   mathContext *mc, R_GE_gcontext *gc, GEDevDesc *dd)
1845
			   mathContext *mc, R_GE_gcontext *gc, GEDevDesc *dd)
1846
{
1846
{
1847
    double a, delta, phi, theta;
1847
    double a, delta, phi, theta;
1848
    a = TeX(sigma22, gc, dd);
1848
    a = TeX(sigma22, gc, dd);
1849
    theta = TeX(xi8, gc, dd);
1849
    theta = TeX(xi8, gc, dd);
1850
    if(mc->CurrentStyle > STYLE_T) {
1850
    if(mc->CurrentStyle > STYLE_T) {
1851
	*u = TeX(sigma8, gc, dd);
1851
	*u = TeX(sigma8, gc, dd);
1852
	*v = TeX(sigma11, gc, dd);
1852
	*v = TeX(sigma11, gc, dd);
1853
	phi = 3 * theta;
1853
	phi = 3 * theta;
1854
    }
1854
    }
1855
    else {
1855
    else {
1856
	*u = TeX(sigma9, gc, dd);
1856
	*u = TeX(sigma9, gc, dd);
1857
	*v = TeX(sigma12, gc, dd);
1857
	*v = TeX(sigma12, gc, dd);
1858
	phi = theta;
1858
	phi = theta;
1859
    }
1859
    }
1860
    delta = (*u - bboxDepth(numBBox)) - (a + 0.5 * theta);
1860
    delta = (*u - bboxDepth(numBBox)) - (a + 0.5 * theta);
1861
    /*
1861
    /*
1862
     * Numerators and denominators on fractions appear too far from
1862
     * Numerators and denominators on fractions appear too far from
1863
     * horizontal bar. 
1863
     * horizontal bar. 
1864
     * Reread of Knuth suggests removing "+ theta" components below.
1864
     * Reread of Knuth suggests removing "+ theta" components below.
1865
     */ 
1865
     */ 
1866
    if (delta < phi)
1866
    if (delta < phi)
1867
	*u += (phi - delta); /* + theta; */
1867
	*u += (phi - delta); /* + theta; */
1868
    delta = (a + 0.5 * theta) - (bboxHeight(denomBBox) - *v);
1868
    delta = (a + 0.5 * theta) - (bboxHeight(denomBBox) - *v);
1869
    if (delta < phi)
1869
    if (delta < phi)
1870
	*v += (phi - delta); /* + theta; */
1870
	*v += (phi - delta); /* + theta; */
1871
}
1871
}
1872
 
1872
 
1873
static void NumDenomHShift(BBOX numBBox, BBOX denomBBox,
1873
static void NumDenomHShift(BBOX numBBox, BBOX denomBBox,
1874
			   double *numShift, double *denomShift)
1874
			   double *numShift, double *denomShift)
1875
{
1875
{
1876
    double numWidth = bboxWidth(numBBox);
1876
    double numWidth = bboxWidth(numBBox);
1877
    double denomWidth = bboxWidth(denomBBox);
1877
    double denomWidth = bboxWidth(denomBBox);
1878
    if (numWidth > denomWidth) {
1878
    if (numWidth > denomWidth) {
1879
	*numShift = 0;
1879
	*numShift = 0;
1880
	*denomShift = (numWidth - denomWidth) / 2;
1880
	*denomShift = (numWidth - denomWidth) / 2;
1881
    }
1881
    }
1882
    else {
1882
    else {
1883
	*numShift = (denomWidth - numWidth) / 2;
1883
	*numShift = (denomWidth - numWidth) / 2;
1884
	*denomShift = 0;
1884
	*denomShift = 0;
1885
    }
1885
    }
1886
}
1886
}
1887
 
1887
 
1888
static BBOX RenderFraction(SEXP expr, int rule, int draw,
1888
static BBOX RenderFraction(SEXP expr, int rule, int draw,
1889
			   mathContext *mc, R_GE_gcontext *gc, GEDevDesc *dd)
1889
			   mathContext *mc, R_GE_gcontext *gc, GEDevDesc *dd)
1890
{
1890
{
1891
    SEXP numerator = CADR(expr);
1891
    SEXP numerator = CADR(expr);
1892
    SEXP denominator = CADDR(expr);
1892
    SEXP denominator = CADDR(expr);
1893
    BBOX numBBox, denomBBox;
1893
    BBOX numBBox, denomBBox;
1894
    double nHShift, dHShift;
1894
    double nHShift, dHShift;
1895
    double nVShift, dVShift;
1895
    double nVShift, dVShift;
1896
    double width, x[2], y[2];
1896
    double width, x[2], y[2];
1897
    double savedX = mc->CurrentX;
1897
    double savedX = mc->CurrentX;
1898
    double savedY = mc->CurrentY;
1898
    double savedY = mc->CurrentY;
1899
    STYLE style;
1899
    STYLE style;
1900
 
1900
 
1901
    style = GetStyle(mc);
1901
    style = GetStyle(mc);
1902
    SetNumStyle(style, mc, gc);
1902
    SetNumStyle(style, mc, gc);
1903
    numBBox = RenderItalicCorr(RenderElement(numerator, 0, mc, gc, dd), 0,
1903
    numBBox = RenderItalicCorr(RenderElement(numerator, 0, mc, gc, dd), 0,
1904
			       mc, gc, dd);
1904
			       mc, gc, dd);
1905
    SetDenomStyle(style, mc, gc);
1905
    SetDenomStyle(style, mc, gc);
1906
    denomBBox = RenderItalicCorr(RenderElement(denominator, 0, mc, gc, dd), 0,
1906
    denomBBox = RenderItalicCorr(RenderElement(denominator, 0, mc, gc, dd), 0,
1907
				 mc, gc, dd);
1907
				 mc, gc, dd);
1908
    SetStyle(style, mc, gc);
1908
    SetStyle(style, mc, gc);
1909
 
1909
 
1910
    width = max(bboxWidth(numBBox), bboxWidth(denomBBox));
1910
    width = max(bboxWidth(numBBox), bboxWidth(denomBBox));
1911
    NumDenomHShift(numBBox, denomBBox, &nHShift, &dHShift);
1911
    NumDenomHShift(numBBox, denomBBox, &nHShift, &dHShift);
1912
    NumDenomVShift(numBBox, denomBBox, &nVShift, &dVShift, mc, gc, dd);
1912
    NumDenomVShift(numBBox, denomBBox, &nVShift, &dVShift, mc, gc, dd);
1913
 
1913
 
1914
    mc->CurrentX = savedX;
1914
    mc->CurrentX = savedX;
1915
    mc->CurrentY = savedY;
1915
    mc->CurrentY = savedY;
1916
    SetNumStyle(style, mc, gc);
1916
    SetNumStyle(style, mc, gc);
1917
    numBBox = RenderOffsetElement(numerator, nHShift, nVShift, draw, mc,
1917
    numBBox = RenderOffsetElement(numerator, nHShift, nVShift, draw, mc,
1918
				  gc, dd);
1918
				  gc, dd);
1919
 
1919
 
1920
    mc->CurrentX = savedX;
1920
    mc->CurrentX = savedX;
1921
    mc->CurrentY = savedY;
1921
    mc->CurrentY = savedY;
1922
    SetDenomStyle(style, mc, gc);
1922
    SetDenomStyle(style, mc, gc);
1923
    denomBBox = RenderOffsetElement(denominator, dHShift, -dVShift, draw,
1923
    denomBBox = RenderOffsetElement(denominator, dHShift, -dVShift, draw,
1924
				    mc, gc, dd);
1924
				    mc, gc, dd);
1925
 
1925
 
1926
    SetStyle(style, mc, gc);
1926
    SetStyle(style, mc, gc);
1927
 
1927
 
1928
    if (draw) {
1928
    if (draw) {
1929
	if (rule) {
1929
	if (rule) {
1930
	    int savedlty = gc->lty;
1930
	    int savedlty = gc->lty;
1931
	    double savedlwd = gc->lwd;
1931
	    double savedlwd = gc->lwd;
1932
	    mc->CurrentX = savedX;
1932
	    mc->CurrentX = savedX;
1933
	    mc->CurrentY = savedY;
1933
	    mc->CurrentY = savedY;
1934
	    PMoveUp(AxisHeight(gc, dd), mc);
1934
	    PMoveUp(AxisHeight(gc, dd), mc);
1935
	    x[0] = ConvertedX(mc, dd);
1935
	    x[0] = ConvertedX(mc, dd);
1936
	    y[0] = ConvertedY(mc, dd);
1936
	    y[0] = ConvertedY(mc, dd);
1937
	    PMoveAcross(width, mc);
1937
	    PMoveAcross(width, mc);
1938
	    x[1] = ConvertedX(mc, dd);
1938
	    x[1] = ConvertedX(mc, dd);
1939
	    y[1] = ConvertedY(mc, dd);
1939
	    y[1] = ConvertedY(mc, dd);
1940
	    gc->lty = LTY_SOLID;
1940
	    gc->lty = LTY_SOLID;
1941
	    if (gc->lwd > 1)
1941
	    if (gc->lwd > 1)
1942
		gc->lwd = 1;
1942
		gc->lwd = 1;
1943
	    GEPolyline(2, x, y, gc, dd);
1943
	    GEPolyline(2, x, y, gc, dd);
1944
	    PMoveUp(-AxisHeight(gc, dd), mc);
1944
	    PMoveUp(-AxisHeight(gc, dd), mc);
1945
	    gc->lty = savedlty;
1945
	    gc->lty = savedlty;
1946
	    gc->lwd = savedlwd;
1946
	    gc->lwd = savedlwd;
1947
	}
1947
	}
1948
	PMoveTo(savedX + width, savedY, mc);
1948
	PMoveTo(savedX + width, savedY, mc);
1949
    }
1949
    }
1950
    return CombineAlignedBBoxes(numBBox, denomBBox);
1950
    return CombineAlignedBBoxes(numBBox, denomBBox);
1951
}
1951
}
1952
 
1952
 
1953
static BBOX RenderUnderline(SEXP expr, int draw, mathContext *mc,
1953
static BBOX RenderUnderline(SEXP expr, int draw, mathContext *mc,
1954
	        	    R_GE_gcontext *gc, GEDevDesc *dd)
1954
	        	    R_GE_gcontext *gc, GEDevDesc *dd)
1955
{
1955
{
1956
    SEXP body = CADR(expr);
1956
    SEXP body = CADR(expr);
1957
    BBOX BBox;
1957
    BBOX BBox;
1958
    double width, adepth, depth, x[2], y[2];
1958
    double width, adepth, depth, x[2], y[2];
1959
    double savedX = mc->CurrentX;
1959
    double savedX = mc->CurrentX;
1960
    double savedY = mc->CurrentY;
1960
    double savedY = mc->CurrentY;
1961
 
1961
 
1962
    BBox = RenderItalicCorr(RenderElement(body, 0, mc, gc, dd), 0, mc, gc, dd);
1962
    BBox = RenderItalicCorr(RenderElement(body, 0, mc, gc, dd), 0, mc, gc, dd);
1963
    width = bboxWidth(BBox);
1963
    width = bboxWidth(BBox);
1964
 
1964
 
1965
    mc->CurrentX = savedX;
1965
    mc->CurrentX = savedX;
1966
    mc->CurrentY = savedY;
1966
    mc->CurrentY = savedY;
1967
    BBox = RenderElement(body, draw, mc, gc, dd);
1967
    BBox = RenderElement(body, draw, mc, gc, dd);
1968
    adepth = 0.1 * XHeight(gc, dd);
1968
    adepth = 0.1 * XHeight(gc, dd);
1969
    depth = bboxDepth(BBox) + adepth;
1969
    depth = bboxDepth(BBox) + adepth;
1970
 
1970
 
1971
    if (draw) {
1971
    if (draw) {
1972
        int savedlty = gc->lty;
1972
        int savedlty = gc->lty;
1973
        double savedlwd = gc->lwd;
1973
        double savedlwd = gc->lwd;
1974
        mc->CurrentX = savedX;
1974
        mc->CurrentX = savedX;
1975
        mc->CurrentY = savedY;
1975
        mc->CurrentY = savedY;
1976
        PMoveUp(-depth, mc);
1976
        PMoveUp(-depth, mc);
1977
        x[0] = ConvertedX(mc, dd);
1977
        x[0] = ConvertedX(mc, dd);
1978
        y[0] = ConvertedY(mc, dd);
1978
        y[0] = ConvertedY(mc, dd);
1979
        PMoveAcross(width, mc);
1979
        PMoveAcross(width, mc);
1980
        x[1] = ConvertedX(mc, dd);
1980
        x[1] = ConvertedX(mc, dd);
1981
        y[1] = ConvertedY(mc, dd);
1981
        y[1] = ConvertedY(mc, dd);
1982
        gc->lty = LTY_SOLID;
1982
        gc->lty = LTY_SOLID;
1983
	if (gc->lwd > 1)
1983
	if (gc->lwd > 1)
1984
	    gc->lwd = 1;
1984
	    gc->lwd = 1;
1985
        GEPolyline(2, x, y, gc, dd);
1985
        GEPolyline(2, x, y, gc, dd);
1986
        PMoveUp(depth, mc);
1986
        PMoveUp(depth, mc);
1987
        gc->lty = savedlty;
1987
        gc->lty = savedlty;
1988
        gc->lwd = savedlwd;
1988
        gc->lwd = savedlwd;
1989
        PMoveTo(savedX + width, savedY, mc);
1989
        PMoveTo(savedX + width, savedY, mc);
1990
    }
1990
    }
1991
    return EnlargeBBox(BBox, 0.0, adepth, 0.0);
1991
    return EnlargeBBox(BBox, 0.0, adepth, 0.0);
1992
}
1992
}
1993
 
1993
 
1994
 
1994
 
1995
static int OverAtom(SEXP expr)
1995
static int OverAtom(SEXP expr)
1996
{
1996
{
1997
    return NameAtom(expr) &&
1997
    return NameAtom(expr) &&
1998
	(NameMatch(expr, "over") || NameMatch(expr, "frac"));
1998
	(NameMatch(expr, "over") || NameMatch(expr, "frac"));
1999
}
1999
}
2000
 
2000
 
2001
static BBOX RenderOver(SEXP expr, int draw, mathContext *mc,
2001
static BBOX RenderOver(SEXP expr, int draw, mathContext *mc,
2002
		       R_GE_gcontext *gc, GEDevDesc *dd)
2002
		       R_GE_gcontext *gc, GEDevDesc *dd)
2003
{
2003
{
2004
    return RenderFraction(expr, 1, draw, mc, gc, dd);
2004
    return RenderFraction(expr, 1, draw, mc, gc, dd);
2005
}
2005
}
2006
 
2006
 
2007
static int UnderlAtom(SEXP expr)
2007
static int UnderlAtom(SEXP expr)
2008
{
2008
{
2009
    return NameAtom(expr) && NameMatch(expr, "underline");
2009
    return NameAtom(expr) && NameMatch(expr, "underline");
2010
}
2010
}
2011
 
2011
 
2012
static BBOX RenderUnderl(SEXP expr, int draw, mathContext *mc,
2012
static BBOX RenderUnderl(SEXP expr, int draw, mathContext *mc,
2013
			 R_GE_gcontext *gc, GEDevDesc *dd)
2013
			 R_GE_gcontext *gc, GEDevDesc *dd)
2014
{
2014
{
2015
    return RenderUnderline(expr, draw, mc, gc, dd);
2015
    return RenderUnderline(expr, draw, mc, gc, dd);
2016
}
2016
}
2017
 
2017
 
2018
 
2018
 
2019
static int AtopAtom(SEXP expr)
2019
static int AtopAtom(SEXP expr)
2020
{
2020
{
2021
    return NameAtom(expr) && NameMatch(expr, "atop");
2021
    return NameAtom(expr) && NameMatch(expr, "atop");
2022
}
2022
}
2023
 
2023
 
2024
static BBOX RenderAtop(SEXP expr, int draw, mathContext *mc,
2024
static BBOX RenderAtop(SEXP expr, int draw, mathContext *mc,
2025
		       R_GE_gcontext *gc, GEDevDesc *dd)
2025
		       R_GE_gcontext *gc, GEDevDesc *dd)
2026
{
2026
{
2027
    return RenderFraction(expr, 0, draw, mc, gc, dd);
2027
    return RenderFraction(expr, 0, draw, mc, gc, dd);
2028
}
2028
}
2029
 
2029
 
2030
/*----------------------------------------------------------------------
2030
/*----------------------------------------------------------------------
2031
 *
2031
 *
2032
 *  Code for Grouped Expressions  (e.g. ( ... ))
2032
 *  Code for Grouped Expressions  (e.g. ( ... ))
2033
 *
2033
 *
2034
 *    group(ldelim, body, rdelim)
2034
 *    group(ldelim, body, rdelim)
2035
 *
2035
 *
2036
 *    bgroup(ldelim, body, rdelim)
2036
 *    bgroup(ldelim, body, rdelim)
2037
 *
2037
 *
2038
 */
2038
 */
2039
 
2039
 
2040
#define DelimSymbolMag 1.25
2040
#define DelimSymbolMag 1.25
2041
 
2041
 
2042
static int DelimCode(SEXP expr, SEXP head)
2042
static int DelimCode(SEXP expr, SEXP head)
2043
{
2043
{
2044
    int code = 0;
2044
    int code = 0;
2045
    if (NameAtom(head)) {
2045
    if (NameAtom(head)) {
2046
	if (NameMatch(head, "lfloor"))
2046
	if (NameMatch(head, "lfloor"))
2047
	    code = S_BRACKETLEFTBT;
2047
	    code = S_BRACKETLEFTBT;
2048
	else if (NameMatch(head, "rfloor"))
2048
	else if (NameMatch(head, "rfloor"))
2049
	    code = S_BRACKETRIGHTBT;
2049
	    code = S_BRACKETRIGHTBT;
2050
	if (NameMatch(head, "lceil"))
2050
	if (NameMatch(head, "lceil"))
2051
	    code = S_BRACKETLEFTTP;
2051
	    code = S_BRACKETLEFTTP;
2052
	else if (NameMatch(head, "rceil"))
2052
	else if (NameMatch(head, "rceil"))
2053
	    code = S_BRACKETRIGHTTP;
2053
	    code = S_BRACKETRIGHTTP;
2054
    }
2054
    }
2055
    else if (StringAtom(head) && length(head) > 0) {
2055
    else if (StringAtom(head) && length(head) > 0) {
2056
	if (StringMatch(head, "|"))
2056
	if (StringMatch(head, "|"))
2057
	    code = '|';
2057
	    code = '|';
2058
	else if (StringMatch(head, "||"))
2058
	else if (StringMatch(head, "||"))
2059
	    code = 2;
2059
	    code = 2;
2060
	else if (StringMatch(head, "("))
2060
	else if (StringMatch(head, "("))
2061
	    code = '(';
2061
	    code = '(';
2062
	else if (StringMatch(head, ")"))
2062
	else if (StringMatch(head, ")"))
2063
	    code = ')';
2063
	    code = ')';
2064
	else if (StringMatch(head, "["))
2064
	else if (StringMatch(head, "["))
2065
	    code = '[';
2065
	    code = '[';
2066
	else if (StringMatch(head, "]"))
2066
	else if (StringMatch(head, "]"))
2067
	    code = ']';
2067
	    code = ']';
2068
	else if (StringMatch(head, "{"))
2068
	else if (StringMatch(head, "{"))
2069
	    code = '{';
2069
	    code = '{';
2070
	else if (StringMatch(head, "}"))
2070
	else if (StringMatch(head, "}"))
2071
	    code = '}';
2071
	    code = '}';
2072
	else if (StringMatch(head, "") || StringMatch(head, "."))
2072
	else if (StringMatch(head, "") || StringMatch(head, "."))
2073
	    code = '.';
2073
	    code = '.';
2074
    }
2074
    }
2075
    if (code == 0)
2075
    if (code == 0)
2076
	errorcall(expr, _("invalid group delimiter"));
2076
	errorcall(expr, _("invalid group delimiter"));
2077
    return code;
2077
    return code;
2078
}
2078
}
2079
 
2079
 
2080
static BBOX RenderDelimiter(int delim, int draw, mathContext *mc,
2080
static BBOX RenderDelimiter(int delim, int draw, mathContext *mc,
2081
			    R_GE_gcontext *gc, GEDevDesc *dd)
2081
			    R_GE_gcontext *gc, GEDevDesc *dd)
2082
{
2082
{
2083
    BBOX bbox;
2083
    BBOX bbox;
2084
    double savecex = gc->cex;
2084
    double savecex = gc->cex;
2085
    gc->cex = DelimSymbolMag * gc->cex;
2085
    gc->cex = DelimSymbolMag * gc->cex;
2086
    bbox = RenderSymbolChar(delim, draw, mc, gc, dd);
2086
    bbox = RenderSymbolChar(delim, draw, mc, gc, dd);
2087
    gc->cex = savecex;
2087
    gc->cex = savecex;
2088
    return bbox;
2088
    return bbox;
2089
}
2089
}
2090
 
2090
 
2091
static int GroupAtom(SEXP expr)
2091
static int GroupAtom(SEXP expr)
2092
{
2092
{
2093
    return NameAtom(expr) && NameMatch(expr, "group");
2093
    return NameAtom(expr) && NameMatch(expr, "group");
2094
}
2094
}
2095
 
2095
 
2096
static BBOX RenderGroup(SEXP expr, int draw, mathContext *mc,
2096
static BBOX RenderGroup(SEXP expr, int draw, mathContext *mc,
2097
			R_GE_gcontext *gc, GEDevDesc *dd)
2097
			R_GE_gcontext *gc, GEDevDesc *dd)
2098
{
2098
{
2099
    double cexSaved = gc->cex;
2099
    double cexSaved = gc->cex;
2100
    BBOX bbox;
2100
    BBOX bbox;
2101
    int code;
2101
    int code;
2102
    if (length(expr) != 4)
2102
    if (length(expr) != 4)
2103
	errorcall(expr, _("invalid group specification"));
2103
	errorcall(expr, _("invalid group specification"));
2104
    bbox = NullBBox();
2104
    bbox = NullBBox();
2105
    code = DelimCode(expr, CADR(expr));
2105
    code = DelimCode(expr, CADR(expr));
2106
    gc->cex = DelimSymbolMag * gc->cex;
2106
    gc->cex = DelimSymbolMag * gc->cex;
2107
    if (code == 2) {
2107
    if (code == 2) {
2108
	bbox = RenderSymbolChar('|', draw, mc, gc, dd);
2108
	bbox = RenderSymbolChar('|', draw, mc, gc, dd);
2109
	bbox = RenderSymbolChar('|', draw, mc, gc, dd);
2109
	bbox = RenderSymbolChar('|', draw, mc, gc, dd);
2110
    }
2110
    }
2111
    else if (code != '.')
2111
    else if (code != '.')
2112
	bbox = RenderSymbolChar(code, draw, mc, gc, dd);
2112
	bbox = RenderSymbolChar(code, draw, mc, gc, dd);
2113
    gc->cex = cexSaved;
2113
    gc->cex = cexSaved;
2114
    bbox = CombineBBoxes(bbox, RenderElement(CADDR(expr), draw, mc, gc, dd));
2114
    bbox = CombineBBoxes(bbox, RenderElement(CADDR(expr), draw, mc, gc, dd));
2115
    bbox = RenderItalicCorr(bbox, draw, mc, gc, dd);
2115
    bbox = RenderItalicCorr(bbox, draw, mc, gc, dd);
2116
    code = DelimCode(expr, CADDDR(expr));
2116
    code = DelimCode(expr, CADDDR(expr));
2117
    gc->cex = DelimSymbolMag * gc->cex;
2117
    gc->cex = DelimSymbolMag * gc->cex;
2118
    if (code == 2) {
2118
    if (code == 2) {
2119
	bbox = CombineBBoxes(bbox, RenderSymbolChar('|', draw, mc, gc, dd));
2119
	bbox = CombineBBoxes(bbox, RenderSymbolChar('|', draw, mc, gc, dd));
2120
	bbox = CombineBBoxes(bbox, RenderSymbolChar('|', draw, mc, gc, dd));
2120
	bbox = CombineBBoxes(bbox, RenderSymbolChar('|', draw, mc, gc, dd));
2121
    }
2121
    }
2122
    else if (code != '.')
2122
    else if (code != '.')
2123
	bbox = CombineBBoxes(bbox, RenderSymbolChar(code, draw, mc, gc, dd));
2123
	bbox = CombineBBoxes(bbox, RenderSymbolChar(code, draw, mc, gc, dd));
2124
    gc->cex = cexSaved;
2124
    gc->cex = cexSaved;
2125
    return bbox;
2125
    return bbox;
2126
}
2126
}
2127
 
2127
 
2128
static int BGroupAtom(SEXP expr)
2128
static int BGroupAtom(SEXP expr)
2129
{
2129
{
2130
    return NameAtom(expr) && NameMatch(expr, "bgroup");
2130
    return NameAtom(expr) && NameMatch(expr, "bgroup");
2131
}
2131
}
2132
 
2132
 
2133
static BBOX RenderDelim(int which, double dist, int draw, mathContext *mc,
2133
static BBOX RenderDelim(int which, double dist, int draw, mathContext *mc,
2134
			R_GE_gcontext *gc, GEDevDesc *dd)
2134
			R_GE_gcontext *gc, GEDevDesc *dd)
2135
{
2135
{
2136
    double savedX = mc->CurrentX;
2136
    double savedX = mc->CurrentX;
2137
    double savedY = mc->CurrentY;
2137
    double savedY = mc->CurrentY;
2138
    FontType prev = SetFont(SymbolFont, gc);
2138
    FontType prev = SetFont(SymbolFont, gc);
2139
    BBOX ansBBox, topBBox, botBBox, extBBox, midBBox;
2139
    BBOX ansBBox, topBBox, botBBox, extBBox, midBBox;
2140
    int top, bot, ext, mid;
2140
    int top, bot, ext, mid;
2141
    int i, n;
2141
    int i, n;
2142
    double topShift, botShift, extShift, midShift;
2142
    double topShift, botShift, extShift, midShift;
2143
    double ytop, ybot, extHeight, delta;
2143
    double ytop, ybot, extHeight, delta;
2144
    double axisHeight = TeX(sigma22, gc, dd);
2144
    double axisHeight = TeX(sigma22, gc, dd);
2145
 
2145
 
2146
    switch(which) {
2146
    switch(which) {
2147
    case '.':
2147
    case '.':
2148
	SetFont(prev, gc);
2148
	SetFont(prev, gc);
2149
	return NullBBox();
2149
	return NullBBox();
2150
	break;
2150
	break;
2151
    case '|':
2151
    case '|':
2152
    case 2:
2152
    case 2:
2153
	top = 239; ext = 239; bot = 239; mid = 0;
2153
	top = 239; ext = 239; bot = 239; mid = 0;
2154
	break;
2154
	break;
2155
    case '(':
2155
    case '(':
2156
	top = 230; ext = 231; bot = 232; mid = 0;
2156
	top = 230; ext = 231; bot = 232; mid = 0;
2157
	break;
2157
	break;
2158
    case ')':
2158
    case ')':
2159
	top = 246; ext = 247; bot = 248; mid = 0;
2159
	top = 246; ext = 247; bot = 248; mid = 0;
2160
	break;
2160
	break;
2161
    case '[':
2161
    case '[':
2162
	top = 233; ext = 234; bot = 235; mid = 0;
2162
	top = 233; ext = 234; bot = 235; mid = 0;
2163
	break;
2163
	break;
2164
    case ']':
2164
    case ']':
2165
	top = 249; ext = 250; bot = 251; mid = 0;
2165
	top = 249; ext = 250; bot = 251; mid = 0;
2166
	break;
2166
	break;
2167
    case '{':
2167
    case '{':
2168
	top = 236; ext = 239; bot = 238; mid = 237;
2168
	top = 236; ext = 239; bot = 238; mid = 237;
2169
	break;
2169
	break;
2170
    case '}':
2170
    case '}':
2171
	top = 252; ext = 239; bot = 254; mid = 253;
2171
	top = 252; ext = 239; bot = 254; mid = 253;
2172
	break;
2172
	break;
2173
    default:
2173
    default:
2174
	error(_("group is incomplete"));
2174
	error(_("group is incomplete"));
2175
	return NullBBox();/*never reached*/
2175
	return NullBBox();/*never reached*/
2176
    }
2176
    }
2177
    topBBox = GlyphBBox(top, gc, dd);
2177
    topBBox = GlyphBBox(top, gc, dd);
2178
    extBBox = GlyphBBox(ext, gc, dd);
2178
    extBBox = GlyphBBox(ext, gc, dd);
2179
    botBBox = GlyphBBox(bot, gc, dd);
2179
    botBBox = GlyphBBox(bot, gc, dd);
2180
    if (which == '{' || which == '}') {
2180
    if (which == '{' || which == '}') {
2181
	if (1.2 * (bboxHeight(topBBox) + bboxDepth(topBBox)) > dist)
2181
	if (1.2 * (bboxHeight(topBBox) + bboxDepth(topBBox)) > dist)
2182
	    dist = 1.2 * (bboxHeight(topBBox) + bboxDepth(botBBox));
2182
	    dist = 1.2 * (bboxHeight(topBBox) + bboxDepth(botBBox));
2183
    }
2183
    }
2184
    else {
2184
    else {
2185
	if (0.8 * (bboxHeight(topBBox) + bboxDepth(topBBox)) > dist)
2185
	if (0.8 * (bboxHeight(topBBox) + bboxDepth(topBBox)) > dist)
2186
	    dist = 0.8 * (bboxHeight(topBBox) + bboxDepth(topBBox));
2186
	    dist = 0.8 * (bboxHeight(topBBox) + bboxDepth(topBBox));
2187
    }
2187
    }
2188
    extHeight = bboxHeight(extBBox) + bboxDepth(extBBox);
2188
    extHeight = bboxHeight(extBBox) + bboxDepth(extBBox);
2189
    topShift = dist - bboxHeight(topBBox) + axisHeight;
2189
    topShift = dist - bboxHeight(topBBox) + axisHeight;
2190
    botShift = dist - bboxDepth(botBBox) - axisHeight;
2190
    botShift = dist - bboxDepth(botBBox) - axisHeight;
2191
    extShift = 0.5 * (bboxHeight(extBBox) - bboxDepth(extBBox));
2191
    extShift = 0.5 * (bboxHeight(extBBox) - bboxDepth(extBBox));
2192
    topBBox = ShiftBBox(topBBox, topShift);
2192
    topBBox = ShiftBBox(topBBox, topShift);
2193
    botBBox = ShiftBBox(botBBox, -botShift);
2193
    botBBox = ShiftBBox(botBBox, -botShift);
2194
    ansBBox = CombineAlignedBBoxes(topBBox, botBBox);
2194
    ansBBox = CombineAlignedBBoxes(topBBox, botBBox);
2195
    if (which == '{' || which == '}') {
2195
    if (which == '{' || which == '}') {
2196
	midBBox = GlyphBBox(mid, gc, dd);
2196
	midBBox = GlyphBBox(mid, gc, dd);
2197
	midShift = axisHeight
2197
	midShift = axisHeight
2198
	    - 0.5 * (bboxHeight(midBBox) - bboxDepth(midBBox));
2198
	    - 0.5 * (bboxHeight(midBBox) - bboxDepth(midBBox));
2199
	midBBox = ShiftBBox(midBBox, midShift);
2199
	midBBox = ShiftBBox(midBBox, midShift);
2200
	ansBBox = CombineAlignedBBoxes(ansBBox, midBBox);
2200
	ansBBox = CombineAlignedBBoxes(ansBBox, midBBox);
2201
	if (draw) {
2201
	if (draw) {
2202
	    PMoveTo(savedX, savedY + topShift, mc);
2202
	    PMoveTo(savedX, savedY + topShift, mc);
2203
	    RenderSymbolChar(top, draw, mc, gc, dd);
2203
	    RenderSymbolChar(top, draw, mc, gc, dd);
2204
	    PMoveTo(savedX, savedY + midShift, mc);
2204
	    PMoveTo(savedX, savedY + midShift, mc);
2205
	    RenderSymbolChar(mid, draw, mc, gc, dd);
2205
	    RenderSymbolChar(mid, draw, mc, gc, dd);
2206
	    PMoveTo(savedX, savedY - botShift, mc);
2206
	    PMoveTo(savedX, savedY - botShift, mc);
2207
	    RenderSymbolChar(bot, draw, mc, gc, dd);
2207
	    RenderSymbolChar(bot, draw, mc, gc, dd);
2208
	    PMoveTo(savedX + bboxWidth(ansBBox), savedY, mc);
2208
	    PMoveTo(savedX + bboxWidth(ansBBox), savedY, mc);
2209
	}
2209
	}
2210
    }
2210
    }
2211
    else {
2211
    else {
2212
	if (draw) {
2212
	if (draw) {
2213
	    /* draw the top and bottom elements */
2213
	    /* draw the top and bottom elements */
2214
	    PMoveTo(savedX, savedY + topShift, mc);
2214
	    PMoveTo(savedX, savedY + topShift, mc);
2215
	    RenderSymbolChar(top, draw, mc, gc, dd);
2215
	    RenderSymbolChar(top, draw, mc, gc, dd);
2216
	    PMoveTo(savedX, savedY - botShift, mc);
2216
	    PMoveTo(savedX, savedY - botShift, mc);
2217
	    RenderSymbolChar(bot, draw, mc, gc, dd);
2217
	    RenderSymbolChar(bot, draw, mc, gc, dd);
2218
	    /* now join with extenders */
2218
	    /* now join with extenders */
2219
	    ytop = axisHeight + dist
2219
	    ytop = axisHeight + dist
2220
		- (bboxHeight(topBBox) + bboxDepth(topBBox));
2220
		- (bboxHeight(topBBox) + bboxDepth(topBBox));
2221
	    ybot = axisHeight - dist
2221
	    ybot = axisHeight - dist
2222
		+ (bboxHeight(botBBox) + bboxDepth(botBBox));
2222
		+ (bboxHeight(botBBox) + bboxDepth(botBBox));
2223
	    n = ceil((ytop - ybot) / (0.99 * extHeight));
2223
	    n = ceil((ytop - ybot) / (0.99 * extHeight));
2224
	    if (n > 0) {
2224
	    if (n > 0) {
2225
		delta = (ytop - ybot) / n;
2225
		delta = (ytop - ybot) / n;
2226
		for (i = 0; i < n; i++) {
2226
		for (i = 0; i < n; i++) {
2227
		    PMoveTo(savedX, savedY + ybot +
2227
		    PMoveTo(savedX, savedY + ybot +
2228
			    (i + 0.5) * delta - extShift, mc);
2228
			    (i + 0.5) * delta - extShift, mc);
2229
		    RenderSymbolChar(ext, draw, mc, gc, dd);
2229
		    RenderSymbolChar(ext, draw, mc, gc, dd);
2230
		}
2230
		}
2231
	    }
2231
	    }
2232
	    PMoveTo(savedX + bboxWidth(ansBBox), savedY, mc);
2232
	    PMoveTo(savedX + bboxWidth(ansBBox), savedY, mc);
2233
 
2233
 
2234
	}
2234
	}
2235
    }
2235
    }
2236
    SetFont(prev, gc);
2236
    SetFont(prev, gc);
2237
    return ansBBox;
2237
    return ansBBox;
2238
}
2238
}
2239
 
2239
 
2240
static BBOX RenderBGroup(SEXP expr, int draw, mathContext *mc,
2240
static BBOX RenderBGroup(SEXP expr, int draw, mathContext *mc,
2241
			 R_GE_gcontext *gc, GEDevDesc *dd)
2241
			 R_GE_gcontext *gc, GEDevDesc *dd)
2242
{
2242
{
2243
    double dist;
2243
    double dist;
2244
    BBOX bbox;
2244
    BBOX bbox;
2245
    double axisHeight = TeX(sigma22, gc, dd);
2245
    double axisHeight = TeX(sigma22, gc, dd);
2246
    double extra = 0.2 * xHeight(gc, dd);
2246
    double extra = 0.2 * xHeight(gc, dd);
2247
    int delim1, delim2;
2247
    int delim1, delim2;
2248
    if (length(expr) != 4)
2248
    if (length(expr) != 4)
2249
	errorcall(expr, _("invalid group specification"));
2249
	errorcall(expr, _("invalid group specification"));
2250
    bbox = NullBBox();
2250
    bbox = NullBBox();
2251
    delim1 = DelimCode(expr, CADR(expr));
2251
    delim1 = DelimCode(expr, CADR(expr));
2252
    delim2 = DelimCode(expr, CADDDR(expr));
2252
    delim2 = DelimCode(expr, CADDDR(expr));
2253
    bbox = RenderElement(CADDR(expr), 0, mc, gc, dd);
2253
    bbox = RenderElement(CADDR(expr), 0, mc, gc, dd);
2254
    dist = max(bboxHeight(bbox) - axisHeight, bboxDepth(bbox) + axisHeight);
2254
    dist = max(bboxHeight(bbox) - axisHeight, bboxDepth(bbox) + axisHeight);
2255
    bbox = RenderDelim(delim1, dist + extra, draw, mc, gc, dd);
2255
    bbox = RenderDelim(delim1, dist + extra, draw, mc, gc, dd);
2256
    bbox = CombineBBoxes(bbox,	RenderElement(CADDR(expr), draw, mc, gc, dd));
2256
    bbox = CombineBBoxes(bbox,	RenderElement(CADDR(expr), draw, mc, gc, dd));
2257
    bbox = RenderItalicCorr(bbox, draw, mc, gc, dd);
2257
    bbox = RenderItalicCorr(bbox, draw, mc, gc, dd);
2258
    bbox = CombineBBoxes(bbox,	RenderDelim(delim2, dist + extra, draw, mc,
2258
    bbox = CombineBBoxes(bbox,	RenderDelim(delim2, dist + extra, draw, mc,
2259
					    gc, dd));
2259
					    gc, dd));
2260
    return bbox;
2260
    return bbox;
2261
}
2261
}
2262
 
2262
 
2263
/*----------------------------------------------------------------------
2263
/*----------------------------------------------------------------------
2264
 *
2264
 *
2265
 *  Code for Parenthetic Expressions  (i.e. ( ... ))
2265
 *  Code for Parenthetic Expressions  (i.e. ( ... ))
2266
 *
2266
 *
2267
 */
2267
 */
2268
 
2268
 
2269
static int ParenAtom(SEXP expr)
2269
static int ParenAtom(SEXP expr)
2270
{
2270
{
2271
    return NameAtom(expr) && NameMatch(expr, "(");
2271
    return NameAtom(expr) && NameMatch(expr, "(");
2272
}
2272
}
2273
 
2273
 
2274
static BBOX RenderParen(SEXP expr, int draw, mathContext *mc,
2274
static BBOX RenderParen(SEXP expr, int draw, mathContext *mc,
2275
			R_GE_gcontext *gc, GEDevDesc *dd)
2275
			R_GE_gcontext *gc, GEDevDesc *dd)
2276
{
2276
{
2277
    BBOX bbox;
2277
    BBOX bbox;
2278
    bbox = RenderDelimiter(S_PARENLEFT, draw, mc, gc, dd);
2278
    bbox = RenderDelimiter(S_PARENLEFT, draw, mc, gc, dd);
2279
    bbox = CombineBBoxes(bbox, RenderElement(CADR(expr), draw, mc, gc, dd));
2279
    bbox = CombineBBoxes(bbox, RenderElement(CADR(expr), draw, mc, gc, dd));
2280
    bbox = RenderItalicCorr(bbox, draw, mc, gc, dd);
2280
    bbox = RenderItalicCorr(bbox, draw, mc, gc, dd);
2281
    return CombineBBoxes(bbox, RenderDelimiter(S_PARENRIGHT, draw, mc, gc, dd));
2281
    return CombineBBoxes(bbox, RenderDelimiter(S_PARENRIGHT, draw, mc, gc, dd));
2282
}
2282
}
2283
 
2283
 
2284
/*----------------------------------------------------------------------
2284
/*----------------------------------------------------------------------
2285
 *
2285
 *
2286
 *  Code for Integral Operators.
2286
 *  Code for Integral Operators.
2287
 *
2287
 *
2288
 */
2288
 */
2289
 
2289
 
2290
static int IntAtom(SEXP expr)
2290
static int IntAtom(SEXP expr)
2291
{
2291
{
2292
    return NameAtom(expr) && NameMatch(expr, "integral");
2292
    return NameAtom(expr) && NameMatch(expr, "integral");
2293
}
2293
}
2294
 
2294
 
2295
 
2295
 
2296
static BBOX RenderIntSymbol(int draw, mathContext *mc, R_GE_gcontext *gc,
2296
static BBOX RenderIntSymbol(int draw, mathContext *mc, R_GE_gcontext *gc,
2297
			    GEDevDesc *dd)
2297
			    GEDevDesc *dd)
2298
{
2298
{
2299
    double savedX = mc->CurrentX;
2299
    double savedX = mc->CurrentX;
2300
    double savedY = mc->CurrentY;
2300
    double savedY = mc->CurrentY;
2301
    if (GetStyle(mc) > STYLE_T) {
2301
    if (GetStyle(mc) > STYLE_T) {
2302
	BBOX bbox1 = RenderSymbolChar(243, 0, mc, gc, dd);
2302
	BBOX bbox1 = RenderSymbolChar(243, 0, mc, gc, dd);
2303
	BBOX bbox2 = RenderSymbolChar(245, 0, mc, gc, dd);
2303
	BBOX bbox2 = RenderSymbolChar(245, 0, mc, gc, dd);
2304
	double shift;
2304
	double shift;
2305
	shift = TeX(sigma22, gc, dd) + 0.99 * bboxDepth(bbox1);
2305
	shift = TeX(sigma22, gc, dd) + 0.99 * bboxDepth(bbox1);
2306
	PMoveUp(shift, mc);
2306
	PMoveUp(shift, mc);
2307
	bbox1 = ShiftBBox(RenderSymbolChar(243, draw, mc, gc, dd), shift);
2307
	bbox1 = ShiftBBox(RenderSymbolChar(243, draw, mc, gc, dd), shift);
2308
	mc->CurrentX = savedX;
2308
	mc->CurrentX = savedX;
2309
	mc->CurrentY = savedY;
2309
	mc->CurrentY = savedY;
2310
	shift = TeX(sigma22, gc, dd) - 0.99 * bboxHeight(bbox2);
2310
	shift = TeX(sigma22, gc, dd) - 0.99 * bboxHeight(bbox2);
2311
	PMoveUp(shift, mc);
2311
	PMoveUp(shift, mc);
2312
	bbox2 = ShiftBBox(RenderSymbolChar(245, draw, mc, gc, dd), shift);
2312
	bbox2 = ShiftBBox(RenderSymbolChar(245, draw, mc, gc, dd), shift);
2313
	if (draw)
2313
	if (draw)
2314
	    PMoveTo(savedX + max(bboxWidth(bbox1), bboxWidth(bbox2)),
2314
	    PMoveTo(savedX + max(bboxWidth(bbox1), bboxWidth(bbox2)),
2315
		    savedY, mc);
2315
		    savedY, mc);
2316
	else
2316
	else
2317
	    PMoveTo(savedX, savedY, mc);
2317
	    PMoveTo(savedX, savedY, mc);
2318
	return CombineAlignedBBoxes(bbox1, bbox2);
2318
	return CombineAlignedBBoxes(bbox1, bbox2);
2319
    }
2319
    }
2320
    else {
2320
    else {
2321
	return RenderSymbolChar(0362, draw, mc, gc, dd);
2321
	return RenderSymbolChar(0362, draw, mc, gc, dd);
2322
    }
2322
    }
2323
}
2323
}
2324
 
2324
 
2325
static BBOX RenderInt(SEXP expr, int draw, mathContext *mc,
2325
static BBOX RenderInt(SEXP expr, int draw, mathContext *mc,
2326
		      R_GE_gcontext *gc, GEDevDesc *dd)
2326
		      R_GE_gcontext *gc, GEDevDesc *dd)
2327
{
2327
{
2328
    BBOX opBBox, lowerBBox, upperBBox, bodyBBox;
2328
    BBOX opBBox, lowerBBox, upperBBox, bodyBBox;
2329
    int nexpr = length(expr);
2329
    int nexpr = length(expr);
2330
    STYLE style = GetStyle(mc);
2330
    STYLE style = GetStyle(mc);
2331
    double savedX = mc->CurrentX;
2331
    double savedX = mc->CurrentX;
2332
    double savedY = mc->CurrentY;
2332
    double savedY = mc->CurrentY;
2333
    double hshift, vshift, width;
2333
    double hshift, vshift, width;
2334
 
2334
 
2335
    opBBox = RenderIntSymbol(draw, mc, gc, dd);
2335
    opBBox = RenderIntSymbol(draw, mc, gc, dd);
2336
    width = bboxWidth(opBBox);
2336
    width = bboxWidth(opBBox);
2337
    mc->CurrentX = savedX;
2337
    mc->CurrentX = savedX;
2338
    mc->CurrentY = savedY;
2338
    mc->CurrentY = savedY;
2339
    if (nexpr > 2) {
2339
    if (nexpr > 2) {
2340
	hshift = 0.5 * width + ThinSpace(gc, dd);
2340
	hshift = 0.5 * width + ThinSpace(gc, dd);
2341
	SetSubStyle(style, mc, gc);
2341
	SetSubStyle(style, mc, gc);
2342
	lowerBBox = RenderElement(CADDR(expr), 0, mc, gc, dd);
2342
	lowerBBox = RenderElement(CADDR(expr), 0, mc, gc, dd);
2343
	vshift = bboxDepth(opBBox) + CenterShift(lowerBBox);
2343
	vshift = bboxDepth(opBBox) + CenterShift(lowerBBox);
2344
	lowerBBox = RenderOffsetElement(CADDR(expr), hshift, -vshift, draw,
2344
	lowerBBox = RenderOffsetElement(CADDR(expr), hshift, -vshift, draw,
2345
					mc, gc, dd);
2345
					mc, gc, dd);
2346
	opBBox = CombineAlignedBBoxes(opBBox, lowerBBox);
2346
	opBBox = CombineAlignedBBoxes(opBBox, lowerBBox);
2347
	SetStyle(style, mc, gc);
2347
	SetStyle(style, mc, gc);
2348
	mc->CurrentX = savedX;
2348
	mc->CurrentX = savedX;
2349
	mc->CurrentY = savedY;
2349
	mc->CurrentY = savedY;
2350
    }
2350
    }
2351
    if (nexpr > 3) {
2351
    if (nexpr > 3) {
2352
	hshift = width + ThinSpace(gc, dd);
2352
	hshift = width + ThinSpace(gc, dd);
2353
	SetSupStyle(style, mc, gc);
2353
	SetSupStyle(style, mc, gc);
2354
	upperBBox = RenderElement(CADDDR(expr), 0, mc, gc, dd);
2354
	upperBBox = RenderElement(CADDDR(expr), 0, mc, gc, dd);
2355
	vshift = bboxHeight(opBBox) - CenterShift(upperBBox);
2355
	vshift = bboxHeight(opBBox) - CenterShift(upperBBox);
2356
	upperBBox = RenderOffsetElement(CADDDR(expr), hshift, vshift, draw,
2356
	upperBBox = RenderOffsetElement(CADDDR(expr), hshift, vshift, draw,
2357
					mc, gc, dd);
2357
					mc, gc, dd);
2358
	opBBox = CombineAlignedBBoxes(opBBox, upperBBox);
2358
	opBBox = CombineAlignedBBoxes(opBBox, upperBBox);
2359
	SetStyle(style, mc, gc);
2359
	SetStyle(style, mc, gc);
2360
	mc->CurrentX = savedX;
2360
	mc->CurrentX = savedX;
2361
	mc->CurrentY = savedY;
2361
	mc->CurrentY = savedY;
2362
    }
2362
    }
2363
    PMoveAcross(bboxWidth(opBBox), mc);
2363
    PMoveAcross(bboxWidth(opBBox), mc);
2364
    if (nexpr > 1) {
2364
    if (nexpr > 1) {
2365
	bodyBBox = RenderElement(CADR(expr), draw, mc, gc, dd);
2365
	bodyBBox = RenderElement(CADR(expr), draw, mc, gc, dd);
2366
	opBBox = CombineBBoxes(opBBox, bodyBBox);
2366
	opBBox = CombineBBoxes(opBBox, bodyBBox);
2367
    }
2367
    }
2368
    return opBBox;
2368
    return opBBox;
2369
}
2369
}
2370
 
2370
 
2371
 
2371
 
2372
/*----------------------------------------------------------------------
2372
/*----------------------------------------------------------------------
2373
 *
2373
 *
2374
 *  Code for Operator Expressions (sum, product, lim, inf, sup, ...)
2374
 *  Code for Operator Expressions (sum, product, lim, inf, sup, ...)
2375
 *
2375
 *
2376
 */
2376
 */
2377
 
2377
 
2378
#define OperatorSymbolMag  1.25
2378
#define OperatorSymbolMag  1.25
2379
 
2379
 
2380
static SymTab OpTable[] = {
2380
static SymTab OpTable[] = {
2381
    { "prod",		S_PRODUCT },
2381
    { "prod",		S_PRODUCT },
2382
    { "sum",		S_SUM },
2382
    { "sum",		S_SUM },
2383
    { "union",		S_UNION },
2383
    { "union",		S_UNION },
2384
    { "intersect",	S_INTERSECTION },
2384
    { "intersect",	S_INTERSECTION },
2385
    { "lim",		N_LIM },
2385
    { "lim",		N_LIM },
2386
    { "liminf",		N_LIMINF },
2386
    { "liminf",		N_LIMINF },
2387
    { "limsup",		N_LIMINF },
2387
    { "limsup",		N_LIMINF },
2388
    { "inf",		N_INF },
2388
    { "inf",		N_INF },
2389
    { "sup",		N_SUP },
2389
    { "sup",		N_SUP },
2390
    { "min",		N_MIN },
2390
    { "min",		N_MIN },
2391
    { "max",		N_MAX },
2391
    { "max",		N_MAX },
2392
    { NULL,		0 }
2392
    { NULL,		0 }
2393
};
2393
};
2394
 
2394
 
2395
static int OpAtom(SEXP expr)
2395
static int OpAtom(SEXP expr)
2396
{
2396
{
2397
    int i;
2397
    int i;
2398
    for (i = 0; OpTable[i].code; i++)
2398
    for (i = 0; OpTable[i].code; i++)
2399
	if (NameMatch(expr, OpTable[i].name))
2399
	if (NameMatch(expr, OpTable[i].name))
2400
	    return OpTable[i].code;
2400
	    return OpTable[i].code;
2401
    return 0;
2401
    return 0;
2402
}
2402
}
2403
 
2403
 
2404
static BBOX RenderOpSymbol(SEXP op, int draw, mathContext *mc,
2404
static BBOX RenderOpSymbol(SEXP op, int draw, mathContext *mc,
2405
			   R_GE_gcontext *gc, GEDevDesc *dd)
2405
			   R_GE_gcontext *gc, GEDevDesc *dd)
2406
{
2406
{
2407
    BBOX bbox;
2407
    BBOX bbox;
2408
    double cexSaved = gc->cex;
2408
    double cexSaved = gc->cex;
2409
    /*double savedX = mc->CurrentX;*/
2409
    /*double savedX = mc->CurrentX;*/
2410
    /*double savedY = mc->CurrentY;*/
2410
    /*double savedY = mc->CurrentY;*/
2411
    double shift;
2411
    double shift;
2412
    int display = (GetStyle(mc) > STYLE_T);
2412
    int display = (GetStyle(mc) > STYLE_T);
2413
    int opId = OpAtom(op);
2413
    int opId = OpAtom(op);
2414
 
2414
 
2415
    if (opId == S_SUM || opId == S_PRODUCT ||
2415
    if (opId == S_SUM || opId == S_PRODUCT ||
2416
	opId == S_UNION || opId == S_INTERSECTION) {
2416
	opId == S_UNION || opId == S_INTERSECTION) {
2417
	if (display) {
2417
	if (display) {
2418
	    gc->cex = OperatorSymbolMag * gc->cex;
2418
	    gc->cex = OperatorSymbolMag * gc->cex;
2419
	    bbox = RenderSymbolChar(OpAtom(op), 0, mc, gc, dd);
2419
	    bbox = RenderSymbolChar(OpAtom(op), 0, mc, gc, dd);
2420
	    shift = 0.5 * (bboxHeight(bbox) - bboxDepth(bbox)) -
2420
	    shift = 0.5 * (bboxHeight(bbox) - bboxDepth(bbox)) -
2421
		TeX(sigma22, gc, dd);
2421
		TeX(sigma22, gc, dd);
2422
	    if (draw) {
2422
	    if (draw) {
2423
		PMoveUp(-shift, mc);
2423
		PMoveUp(-shift, mc);
2424
		bbox = RenderSymbolChar(opId, 1, mc, gc, dd);
2424
		bbox = RenderSymbolChar(opId, 1, mc, gc, dd);
2425
		PMoveUp(shift, mc);
2425
		PMoveUp(shift, mc);
2426
	    }
2426
	    }
2427
	    gc->cex = cexSaved;
2427
	    gc->cex = cexSaved;
2428
	    return ShiftBBox(bbox, -shift);
2428
	    return ShiftBBox(bbox, -shift);
2429
	}
2429
	}
2430
	else return RenderSymbolChar(opId, draw, mc, gc, dd);
2430
	else return RenderSymbolChar(opId, draw, mc, gc, dd);
2431
    }
2431
    }
2432
    else {
2432
    else {
2433
	FontType prevfont = SetFont(PlainFont, gc);
2433
	FontType prevfont = SetFont(PlainFont, gc);
2434
	bbox = RenderStr(CHAR(PRINTNAME(op)), draw, mc, gc, dd);
2434
	bbox = RenderStr(CHAR(PRINTNAME(op)), draw, mc, gc, dd);
2435
	SetFont(prevfont, gc);
2435
	SetFont(prevfont, gc);
2436
	return bbox;
2436
	return bbox;
2437
    }
2437
    }
2438
}
2438
}
2439
 
2439
 
2440
static BBOX RenderOp(SEXP expr, int draw, mathContext *mc,
2440
static BBOX RenderOp(SEXP expr, int draw, mathContext *mc,
2441
		     R_GE_gcontext *gc, GEDevDesc *dd)
2441
		     R_GE_gcontext *gc, GEDevDesc *dd)
2442
{
2442
{
2443
    BBOX lowerBBox, upperBBox, bodyBBox;
2443
    BBOX lowerBBox, upperBBox, bodyBBox;
2444
    double savedX = mc->CurrentX;
2444
    double savedX = mc->CurrentX;
2445
    double savedY = mc->CurrentY;
2445
    double savedY = mc->CurrentY;
2446
    int nexpr = length(expr);
2446
    int nexpr = length(expr);
2447
    STYLE style = GetStyle(mc);
2447
    STYLE style = GetStyle(mc);
2448
    BBOX opBBox = RenderOpSymbol(CAR(expr), 0, mc, gc, dd);
2448
    BBOX opBBox = RenderOpSymbol(CAR(expr), 0, mc, gc, dd);
2449
    double width = bboxWidth(opBBox);
2449
    double width = bboxWidth(opBBox);
2450
    double hshift, lvshift, uvshift;
2450
    double hshift, lvshift, uvshift;
2451
    lvshift = uvshift = 0;	/* -Wall */
2451
    lvshift = uvshift = 0;	/* -Wall */
2452
    if (nexpr > 2) {
2452
    if (nexpr > 2) {
2453
	SetSubStyle(style, mc, gc);
2453
	SetSubStyle(style, mc, gc);
2454
	lowerBBox = RenderElement(CADDR(expr), 0, mc, gc, dd);
2454
	lowerBBox = RenderElement(CADDR(expr), 0, mc, gc, dd);
2455
	SetStyle(style, mc, gc);
2455
	SetStyle(style, mc, gc);
2456
	width = max(width, bboxWidth(lowerBBox));
2456
	width = max(width, bboxWidth(lowerBBox));
2457
	lvshift = max(TeX(xi10, gc, dd), TeX(xi12, gc, dd) -
2457
	lvshift = max(TeX(xi10, gc, dd), TeX(xi12, gc, dd) -
2458
		      bboxHeight(lowerBBox));
2458
		      bboxHeight(lowerBBox));
2459
	lvshift = bboxDepth(opBBox) + bboxHeight(lowerBBox) + lvshift;
2459
	lvshift = bboxDepth(opBBox) + bboxHeight(lowerBBox) + lvshift;
2460
    }
2460
    }
2461
    if (nexpr > 3) {
2461
    if (nexpr > 3) {
2462
	SetSupStyle(style, mc, gc);
2462
	SetSupStyle(style, mc, gc);
2463
	upperBBox = RenderElement(CADDDR(expr), 0, mc, gc, dd);
2463
	upperBBox = RenderElement(CADDDR(expr), 0, mc, gc, dd);
2464
	SetStyle(style, mc, gc);
2464
	SetStyle(style, mc, gc);
2465
	width = max(width, bboxWidth(upperBBox));
2465
	width = max(width, bboxWidth(upperBBox));
2466
	uvshift = max(TeX(xi9, gc, dd), TeX(xi11, gc, dd) -
2466
	uvshift = max(TeX(xi9, gc, dd), TeX(xi11, gc, dd) -
2467
		      bboxDepth(upperBBox));
2467
		      bboxDepth(upperBBox));
2468
	uvshift = bboxHeight(opBBox) + bboxDepth(upperBBox) + uvshift;
2468
	uvshift = bboxHeight(opBBox) + bboxDepth(upperBBox) + uvshift;
2469
    }
2469
    }
2470
    hshift = 0.5 * (width - bboxWidth(opBBox));
2470
    hshift = 0.5 * (width - bboxWidth(opBBox));
2471
    opBBox = RenderGap(hshift, draw, mc, gc, dd);
2471
    opBBox = RenderGap(hshift, draw, mc, gc, dd);
2472
    opBBox = CombineBBoxes(opBBox,
2472
    opBBox = CombineBBoxes(opBBox,
2473
			   RenderOpSymbol(CAR(expr), draw, mc, gc, dd));
2473
			   RenderOpSymbol(CAR(expr), draw, mc, gc, dd));
2474
    mc->CurrentX = savedX;
2474
    mc->CurrentX = savedX;
2475
    mc->CurrentY = savedY;
2475
    mc->CurrentY = savedY;
2476
    if (nexpr > 2) {
2476
    if (nexpr > 2) {
2477
	SetSubStyle(style, mc, gc);
2477
	SetSubStyle(style, mc, gc);
2478
	hshift = 0.5 * (width - bboxWidth(lowerBBox));
2478
	hshift = 0.5 * (width - bboxWidth(lowerBBox));
2479
	lowerBBox = RenderOffsetElement(CADDR(expr), hshift, -lvshift, draw,
2479
	lowerBBox = RenderOffsetElement(CADDR(expr), hshift, -lvshift, draw,
2480
					mc, gc, dd);
2480
					mc, gc, dd);
2481
	SetStyle(style, mc, gc);
2481
	SetStyle(style, mc, gc);
2482
	opBBox = CombineAlignedBBoxes(opBBox, lowerBBox);
2482
	opBBox = CombineAlignedBBoxes(opBBox, lowerBBox);
2483
	mc->CurrentX = savedX;
2483
	mc->CurrentX = savedX;
2484
	mc->CurrentY = savedY;
2484
	mc->CurrentY = savedY;
2485
    }
2485
    }
2486
    if (nexpr > 3) {
2486
    if (nexpr > 3) {
2487
	SetSupStyle(style, mc, gc);
2487
	SetSupStyle(style, mc, gc);
2488
	hshift = 0.5 * (width - bboxWidth(upperBBox));
2488
	hshift = 0.5 * (width - bboxWidth(upperBBox));
2489
	upperBBox = RenderOffsetElement(CADDDR(expr), hshift, uvshift, draw,
2489
	upperBBox = RenderOffsetElement(CADDDR(expr), hshift, uvshift, draw,
2490
					mc, gc, dd);
2490
					mc, gc, dd);
2491
	SetStyle(style, mc, gc);
2491
	SetStyle(style, mc, gc);
2492
	opBBox = CombineAlignedBBoxes(opBBox, upperBBox);
2492
	opBBox = CombineAlignedBBoxes(opBBox, upperBBox);
2493
	mc->CurrentX = savedX;
2493
	mc->CurrentX = savedX;
2494
	mc->CurrentY = savedY;
2494
	mc->CurrentY = savedY;
2495
    }
2495
    }
2496
    opBBox = EnlargeBBox(opBBox, TeX(xi13, gc, dd), TeX(xi13, gc, dd), 0);
2496
    opBBox = EnlargeBBox(opBBox, TeX(xi13, gc, dd), TeX(xi13, gc, dd), 0);
2497
    if (draw)
2497
    if (draw)
2498
	PMoveAcross(width, mc);
2498
	PMoveAcross(width, mc);
2499
    opBBox = CombineBBoxes(opBBox,
2499
    opBBox = CombineBBoxes(opBBox,
2500
			   RenderGap(ThinSpace(gc, dd), draw, mc, gc, dd));
2500
			   RenderGap(ThinSpace(gc, dd), draw, mc, gc, dd));
2501
    bodyBBox = RenderElement(CADR(expr), draw, mc, gc, dd);
2501
    bodyBBox = RenderElement(CADR(expr), draw, mc, gc, dd);
2502
    return CombineBBoxes(opBBox, bodyBBox);
2502
    return CombineBBoxes(opBBox, bodyBBox);
2503
}
2503
}
2504
 
2504
 
2505
 
2505
 
2506
/*----------------------------------------------------------------------
2506
/*----------------------------------------------------------------------
2507
 *
2507
 *
2508
 *  Code for radical expressions (root, sqrt)
2508
 *  Code for radical expressions (root, sqrt)
2509
 *
2509
 *
2510
 *  Tunable parameteters :
2510
 *  Tunable parameteters :
2511
 *
2511
 *
2512
 *  RADICAL_GAP	   The gap between the nucleus and the radical extension.
2512
 *  RADICAL_GAP	   The gap between the nucleus and the radical extension.
2513
 *  RADICAL_SPACE  Extra space to the left and right of the nucleus.
2513
 *  RADICAL_SPACE  Extra space to the left and right of the nucleus.
2514
 *
2514
 *
2515
 */
2515
 */
2516
 
2516
 
2517
#define RADICAL_GAP    0.4
2517
#define RADICAL_GAP    0.4
2518
#define RADICAL_SPACE  0.2
2518
#define RADICAL_SPACE  0.2
2519
 
2519
 
2520
static int RadicalAtom(SEXP expr)
2520
static int RadicalAtom(SEXP expr)
2521
{
2521
{
2522
    return NameAtom(expr) &&
2522
    return NameAtom(expr) &&
2523
	(NameMatch(expr, "root") ||
2523
	(NameMatch(expr, "root") ||
2524
	 NameMatch(expr, "sqrt"));
2524
	 NameMatch(expr, "sqrt"));
2525
}
2525
}
2526
 
2526
 
2527
static BBOX RenderScript(SEXP expr, int draw, mathContext *mc,
2527
static BBOX RenderScript(SEXP expr, int draw, mathContext *mc,
2528
			 R_GE_gcontext *gc, GEDevDesc *dd)
2528
			 R_GE_gcontext *gc, GEDevDesc *dd)
2529
{
2529
{
2530
    BBOX bbox;
2530
    BBOX bbox;
2531
    STYLE style = GetStyle(mc);
2531
    STYLE style = GetStyle(mc);
2532
    SetSupStyle(style, mc, gc);
2532
    SetSupStyle(style, mc, gc);
2533
    bbox = RenderElement(expr, draw, mc, gc, dd);
2533
    bbox = RenderElement(expr, draw, mc, gc, dd);
2534
    SetStyle(style, mc, gc);
2534
    SetStyle(style, mc, gc);
2535
    return bbox;
2535
    return bbox;
2536
}
2536
}
2537
 
2537
 
2538
static BBOX RenderRadical(SEXP expr, int draw, mathContext *mc,
2538
static BBOX RenderRadical(SEXP expr, int draw, mathContext *mc,
2539
			  R_GE_gcontext *gc, GEDevDesc *dd)
2539
			  R_GE_gcontext *gc, GEDevDesc *dd)
2540
{
2540
{
2541
    SEXP body = CADR(expr);
2541
    SEXP body = CADR(expr);
2542
    SEXP order = CADDR(expr);
2542
    SEXP order = CADDR(expr);
2543
    BBOX bodyBBox, orderBBox;
2543
    BBOX bodyBBox, orderBBox;
2544
    double radWidth, radHeight, radDepth;
2544
    double radWidth, radHeight, radDepth;
2545
    double leadWidth, leadHeight, twiddleHeight;
2545
    double leadWidth, leadHeight, twiddleHeight;
2546
    double hshift, vshift;
2546
    double hshift, vshift;
2547
    double radGap, radSpace, radTrail;
2547
    double radGap, radSpace, radTrail;
2548
    STYLE style = GetStyle(mc);
2548
    STYLE style = GetStyle(mc);
2549
    double savedX = mc->CurrentX;
2549
    double savedX = mc->CurrentX;
2550
    double savedY = mc->CurrentY;
2550
    double savedY = mc->CurrentY;
2551
    double x[5], y[5];
2551
    double x[5], y[5];
2552
 
2552
 
2553
    radGap = RADICAL_GAP * xHeight(gc, dd);
2553
    radGap = RADICAL_GAP * xHeight(gc, dd);
2554
    radSpace = RADICAL_SPACE * xHeight(gc, dd);
2554
    radSpace = RADICAL_SPACE * xHeight(gc, dd);
2555
    radTrail = MuSpace(gc, dd);
2555
    radTrail = MuSpace(gc, dd);
2556
    SetPrimeStyle(style, mc, gc);
2556
    SetPrimeStyle(style, mc, gc);
2557
    bodyBBox = RenderElement(body, 0, mc, gc, dd);
2557
    bodyBBox = RenderElement(body, 0, mc, gc, dd);
2558
    bodyBBox = RenderItalicCorr(bodyBBox, 0, mc, gc, dd);
2558
    bodyBBox = RenderItalicCorr(bodyBBox, 0, mc, gc, dd);
2559
 
2559
 
2560
    radWidth = 0.6 *XHeight(gc, dd);
2560
    radWidth = 0.6 *XHeight(gc, dd);
2561
    radHeight = bboxHeight(bodyBBox) + radGap;
2561
    radHeight = bboxHeight(bodyBBox) + radGap;
2562
    radDepth = bboxDepth(bodyBBox);
2562
    radDepth = bboxDepth(bodyBBox);
2563
    twiddleHeight = CenterShift(bodyBBox);
2563
    twiddleHeight = CenterShift(bodyBBox);
2564
 
2564
 
2565
    leadWidth = radWidth;
2565
    leadWidth = radWidth;
2566
    leadHeight = radHeight;
2566
    leadHeight = radHeight;
2567
    if (order != R_NilValue) {
2567
    if (order != R_NilValue) {
2568
	SetSupStyle(style, mc, gc);
2568
	SetSupStyle(style, mc, gc);
2569
	orderBBox = RenderScript(order, 0, mc, gc, dd);
2569
	orderBBox = RenderScript(order, 0, mc, gc, dd);
2570
	leadWidth = max(leadWidth, bboxWidth(orderBBox) + 0.4 * radWidth);
2570
	leadWidth = max(leadWidth, bboxWidth(orderBBox) + 0.4 * radWidth);
2571
	hshift = leadWidth - bboxWidth(orderBBox) - 0.4 * radWidth;
2571
	hshift = leadWidth - bboxWidth(orderBBox) - 0.4 * radWidth;
2572
	vshift = leadHeight - bboxHeight(orderBBox);
2572
	vshift = leadHeight - bboxHeight(orderBBox);
2573
	if (vshift - bboxDepth(orderBBox) < twiddleHeight + radGap)
2573
	if (vshift - bboxDepth(orderBBox) < twiddleHeight + radGap)
2574
	    vshift = twiddleHeight + bboxDepth(orderBBox) + radGap;
2574
	    vshift = twiddleHeight + bboxDepth(orderBBox) + radGap;
2575
	if (draw) {
2575
	if (draw) {
2576
	    PMoveTo(savedX + hshift, savedY + vshift, mc);
2576
	    PMoveTo(savedX + hshift, savedY + vshift, mc);
2577
	    orderBBox = RenderScript(order, draw, mc, gc, dd);
2577
	    orderBBox = RenderScript(order, draw, mc, gc, dd);
2578
	}
2578
	}
2579
	orderBBox = EnlargeBBox(orderBBox, vshift, 0, hshift);
2579
	orderBBox = EnlargeBBox(orderBBox, vshift, 0, hshift);
2580
    }
2580
    }
2581
    else
2581
    else
2582
	orderBBox = NullBBox();
2582
	orderBBox = NullBBox();
2583
    if (draw) {
2583
    if (draw) {
2584
	int savedlty = gc->lty;
2584
	int savedlty = gc->lty;
2585
	double savedlwd = gc->lwd;
2585
	double savedlwd = gc->lwd;
2586
	PMoveTo(savedX + leadWidth - radWidth, savedY, mc);
2586
	PMoveTo(savedX + leadWidth - radWidth, savedY, mc);
2587
	PMoveUp(0.8 * twiddleHeight, mc);
2587
	PMoveUp(0.8 * twiddleHeight, mc);
2588
	x[0] = ConvertedX(mc, dd);
2588
	x[0] = ConvertedX(mc, dd);
2589
	y[0] = ConvertedY(mc, dd);
2589
	y[0] = ConvertedY(mc, dd);
2590
	PMoveUp(0.2 * twiddleHeight, mc);
2590
	PMoveUp(0.2 * twiddleHeight, mc);
2591
	PMoveAcross(0.3 * radWidth, mc);
2591
	PMoveAcross(0.3 * radWidth, mc);
2592
	x[1] = ConvertedX(mc, dd);
2592
	x[1] = ConvertedX(mc, dd);
2593
	y[1] = ConvertedY(mc, dd);
2593
	y[1] = ConvertedY(mc, dd);
2594
	PMoveUp(-(twiddleHeight + bboxDepth(bodyBBox)), mc);
2594
	PMoveUp(-(twiddleHeight + bboxDepth(bodyBBox)), mc);
2595
	PMoveAcross(0.3 * radWidth, mc);
2595
	PMoveAcross(0.3 * radWidth, mc);
2596
	x[2] = ConvertedX(mc, dd);
2596
	x[2] = ConvertedX(mc, dd);
2597
	y[2] = ConvertedY(mc, dd);
2597
	y[2] = ConvertedY(mc, dd);
2598
	PMoveUp(bboxDepth(bodyBBox) + bboxHeight(bodyBBox) + radGap, mc);
2598
	PMoveUp(bboxDepth(bodyBBox) + bboxHeight(bodyBBox) + radGap, mc);
2599
	PMoveAcross(0.4 * radWidth, mc);
2599
	PMoveAcross(0.4 * radWidth, mc);
2600
	x[3] = ConvertedX(mc, dd);
2600
	x[3] = ConvertedX(mc, dd);
2601
	y[3] = ConvertedY(mc, dd);
2601
	y[3] = ConvertedY(mc, dd);
2602
	PMoveAcross(radSpace + bboxWidth(bodyBBox) + radTrail, mc);
2602
	PMoveAcross(radSpace + bboxWidth(bodyBBox) + radTrail, mc);
2603
	x[4] = ConvertedX(mc, dd);
2603
	x[4] = ConvertedX(mc, dd);
2604
	y[4] = ConvertedY(mc, dd);
2604
	y[4] = ConvertedY(mc, dd);
2605
	gc->lty = LTY_SOLID;
2605
	gc->lty = LTY_SOLID;
2606
	if (gc->lwd > 1)
2606
	if (gc->lwd > 1)
2607
	    gc->lwd = 1;
2607
	    gc->lwd = 1;
2608
	GEPolyline(5, x, y, gc, dd);
2608
	GEPolyline(5, x, y, gc, dd);
2609
	PMoveTo(savedX, savedY, mc);
2609
	PMoveTo(savedX, savedY, mc);
2610
	gc->lty = savedlty;
2610
	gc->lty = savedlty;
2611
	gc->lwd = savedlwd;
2611
	gc->lwd = savedlwd;
2612
    }
2612
    }
2613
    orderBBox =
2613
    orderBBox =
2614
	CombineAlignedBBoxes(orderBBox,
2614
	CombineAlignedBBoxes(orderBBox,
2615
			     RenderGap(leadWidth + radSpace, draw, mc, gc, dd));
2615
			     RenderGap(leadWidth + radSpace, draw, mc, gc, dd));
2616
    SetPrimeStyle(style, mc, gc);
2616
    SetPrimeStyle(style, mc, gc);
2617
    orderBBox = CombineBBoxes(orderBBox,
2617
    orderBBox = CombineBBoxes(orderBBox,
2618
			      RenderElement(body, draw, mc, gc, dd));
2618
			      RenderElement(body, draw, mc, gc, dd));
2619
    orderBBox = CombineBBoxes(orderBBox,
2619
    orderBBox = CombineBBoxes(orderBBox,
2620
			      RenderGap(2 * radTrail, draw, mc, gc, dd));
2620
			      RenderGap(2 * radTrail, draw, mc, gc, dd));
2621
    orderBBox = EnlargeBBox(orderBBox, radGap, 0, 0);/* << fixes PR#1101 */
2621
    orderBBox = EnlargeBBox(orderBBox, radGap, 0, 0);/* << fixes PR#1101 */
2622
    SetStyle(style, mc, gc);
2622
    SetStyle(style, mc, gc);
2623
    return orderBBox;
2623
    return orderBBox;
2624
}
2624
}
2625
 
2625
 
2626
/*----------------------------------------------------------------------
2626
/*----------------------------------------------------------------------
2627
 *
2627
 *
2628
 *  Code for Absolute Value Expressions (abs)
2628
 *  Code for Absolute Value Expressions (abs)
2629
 *
2629
 *
2630
 */
2630
 */
2631
 
2631
 
2632
static int AbsAtom(SEXP expr)
2632
static int AbsAtom(SEXP expr)
2633
{
2633
{
2634
    return NameAtom(expr) && NameMatch(expr, "abs");
2634
    return NameAtom(expr) && NameMatch(expr, "abs");
2635
}
2635
}
2636
 
2636
 
2637
static BBOX RenderAbs(SEXP expr, int draw, mathContext *mc,
2637
static BBOX RenderAbs(SEXP expr, int draw, mathContext *mc,
2638
		      R_GE_gcontext *gc, GEDevDesc *dd)
2638
		      R_GE_gcontext *gc, GEDevDesc *dd)
2639
{
2639
{
2640
    BBOX bbox = RenderElement(CADR(expr), 0, mc, gc, dd);
2640
    BBOX bbox = RenderElement(CADR(expr), 0, mc, gc, dd);
2641
    double height = bboxHeight(bbox);
2641
    double height = bboxHeight(bbox);
2642
    double depth = bboxDepth(bbox);
2642
    double depth = bboxDepth(bbox);
2643
    double x[2], y[2];
2643
    double x[2], y[2];
2644
 
2644
 
2645
    bbox= RenderGap(MuSpace(gc, dd), draw, mc, gc, dd);
2645
    bbox= RenderGap(MuSpace(gc, dd), draw, mc, gc, dd);
2646
    if (draw) {
2646
    if (draw) {
2647
	int savedlty = gc->lty;
2647
	int savedlty = gc->lty;
2648
	double savedlwd = gc->lwd;
2648
	double savedlwd = gc->lwd;
2649
	PMoveUp(-depth, mc);
2649
	PMoveUp(-depth, mc);
2650
	x[0] = ConvertedX(mc, dd);
2650
	x[0] = ConvertedX(mc, dd);
2651
	y[0] = ConvertedY(mc, dd);
2651
	y[0] = ConvertedY(mc, dd);
2652
	PMoveUp(depth + height, mc);
2652
	PMoveUp(depth + height, mc);
2653
	x[1] = ConvertedX(mc, dd);
2653
	x[1] = ConvertedX(mc, dd);
2654
	y[1] = ConvertedY(mc, dd);
2654
	y[1] = ConvertedY(mc, dd);
2655
	gc->lty = LTY_SOLID;
2655
	gc->lty = LTY_SOLID;
2656
	if (gc->lwd > 1)
2656
	if (gc->lwd > 1)
2657
	    gc->lwd = 1;
2657
	    gc->lwd = 1;
2658
	GEPolyline(2, x, y, gc, dd);
2658
	GEPolyline(2, x, y, gc, dd);
2659
	PMoveUp(-height, mc);
2659
	PMoveUp(-height, mc);
2660
	gc->lty = savedlty;
2660
	gc->lty = savedlty;
2661
	gc->lwd = savedlwd;
2661
	gc->lwd = savedlwd;
2662
    }
2662
    }
2663
    bbox = CombineBBoxes(bbox, RenderGap(MuSpace(gc, dd), draw, mc, gc, dd));
2663
    bbox = CombineBBoxes(bbox, RenderGap(MuSpace(gc, dd), draw, mc, gc, dd));
2664
    bbox = CombineBBoxes(bbox, RenderElement(CADR(expr), draw, mc, gc, dd));
2664
    bbox = CombineBBoxes(bbox, RenderElement(CADR(expr), draw, mc, gc, dd));
2665
    bbox = RenderItalicCorr(bbox, draw, mc, gc, dd);
2665
    bbox = RenderItalicCorr(bbox, draw, mc, gc, dd);
2666
    bbox = CombineBBoxes(bbox, RenderGap(MuSpace(gc, dd), draw, mc, gc, dd));
2666
    bbox = CombineBBoxes(bbox, RenderGap(MuSpace(gc, dd), draw, mc, gc, dd));
2667
    if (draw) {
2667
    if (draw) {
2668
	int savedlty = gc->lty;
2668
	int savedlty = gc->lty;
2669
	double savedlwd = gc->lwd;
2669
	double savedlwd = gc->lwd;
2670
	PMoveUp(-depth, mc);
2670
	PMoveUp(-depth, mc);
2671
	x[0] = ConvertedX(mc, dd);
2671
	x[0] = ConvertedX(mc, dd);
2672
	y[0] = ConvertedY(mc, dd);
2672
	y[0] = ConvertedY(mc, dd);
2673
	PMoveUp(depth + height, mc);
2673
	PMoveUp(depth + height, mc);
2674
	x[1] = ConvertedX(mc, dd);
2674
	x[1] = ConvertedX(mc, dd);
2675
	y[1] = ConvertedY(mc, dd);
2675
	y[1] = ConvertedY(mc, dd);
2676
	gc->lty = LTY_SOLID;
2676
	gc->lty = LTY_SOLID;
2677
	if (gc->lwd > 1)
2677
	if (gc->lwd > 1)
2678
	    gc->lwd = 1;
2678
	    gc->lwd = 1;
2679
	GEPolyline(2, x, y, gc, dd);
2679
	GEPolyline(2, x, y, gc, dd);
2680
	PMoveUp(-height, mc);
2680
	PMoveUp(-height, mc);
2681
	gc->lty = savedlty;
2681
	gc->lty = savedlty;
2682
	gc->lwd = savedlwd;
2682
	gc->lwd = savedlwd;
2683
    }
2683
    }
2684
    bbox = CombineBBoxes(bbox, RenderGap(MuSpace(gc, dd), draw, mc, gc, dd));
2684
    bbox = CombineBBoxes(bbox, RenderGap(MuSpace(gc, dd), draw, mc, gc, dd));
2685
    return bbox;
2685
    return bbox;
2686
}
2686
}
2687
 
2687
 
2688
/*----------------------------------------------------------------------
2688
/*----------------------------------------------------------------------
2689
 *
2689
 *
2690
 *  Code for Grouped Expressions (i.e. { ... } )
2690
 *  Code for Grouped Expressions (i.e. { ... } )
2691
 *
2691
 *
2692
 */
2692
 */
2693
 
2693
 
2694
static int CurlyAtom(SEXP expr)
2694
static int CurlyAtom(SEXP expr)
2695
{
2695
{
2696
    return NameAtom(expr) &&
2696
    return NameAtom(expr) &&
2697
	NameMatch(expr, "{");
2697
	NameMatch(expr, "{");
2698
}
2698
}
2699
 
2699
 
2700
static BBOX RenderCurly(SEXP expr, int draw, mathContext *mc,
2700
static BBOX RenderCurly(SEXP expr, int draw, mathContext *mc,
2701
			R_GE_gcontext *gc, GEDevDesc *dd)
2701
			R_GE_gcontext *gc, GEDevDesc *dd)
2702
{
2702
{
2703
    return RenderElement(CADR(expr), draw, mc, gc, dd);
2703
    return RenderElement(CADR(expr), draw, mc, gc, dd);
2704
}
2704
}
2705
 
2705
 
2706
 
2706
 
2707
/*----------------------------------------------------------------------
2707
/*----------------------------------------------------------------------
2708
 *
2708
 *
2709
 *  Code for Relation Expressions (i.e. ... ==, !=, ...)
2709
 *  Code for Relation Expressions (i.e. ... ==, !=, ...)
2710
 *
2710
 *
2711
 */
2711
 */
2712
 
2712
 
2713
				/* Binary Relationships */
2713
				/* Binary Relationships */
2714
static
2714
static
2715
SymTab RelTable[] = {
2715
SymTab RelTable[] = {
2716
    { "<",		 60 },	/* less */
2716
    { "<",		 60 },	/* less */
2717
    { "==",		 61 },	/* equal */
2717
    { "==",		 61 },	/* equal */
2718
    { ">",		 62 },	/* greater */
2718
    { ">",		 62 },	/* greater */
2719
    { "%=~%",		 64 },	/* congruent */
2719
    { "%=~%",		 64 },	/* congruent */
2720
    { "!=",		185 },	/* not equal */
2720
    { "!=",		185 },	/* not equal */
2721
    { "<=",		163 },	/* less or equal */
2721
    { "<=",		163 },	/* less or equal */
2722
    { ">=",		179 },	/* greater or equal */
2722
    { ">=",		179 },	/* greater or equal */
2723
    { "%==%",		186 },	/* equivalence */
2723
    { "%==%",		186 },	/* equivalence */
2724
    { "%~~%",		187 },	/* approxequal */
2724
    { "%~~%",		187 },	/* approxequal */
2725
    { "%prop%",         181 },  /* proportional to */
2725
    { "%prop%",         181 },  /* proportional to */
2726
 
2726
 
2727
    { "%<->%",		171 },	/* Arrows */
2727
    { "%<->%",		171 },	/* Arrows */
2728
    { "%<-%",		172 },
2728
    { "%<-%",		172 },
2729
    { "%up%",		173 },
2729
    { "%up%",		173 },
2730
    { "%->%",		174 },
2730
    { "%->%",		174 },
2731
    { "%down%",		175 },
2731
    { "%down%",		175 },
2732
    { "%<=>%",		219 },
2732
    { "%<=>%",		219 },
2733
    { "%<=%",		220 },
2733
    { "%<=%",		220 },
2734
    { "%dblup%",	221 },
2734
    { "%dblup%",	221 },
2735
    { "%=>%",		222 },
2735
    { "%=>%",		222 },
2736
    { "%dbldown%",	223 },
2736
    { "%dbldown%",	223 },
2737
 
2737
 
2738
    { "%supset%",	201 },	/* Sets (TeX Names) */
2738
    { "%supset%",	201 },	/* Sets (TeX Names) */
2739
    { "%supseteq%",	202 },
2739
    { "%supseteq%",	202 },
2740
    { "%notsubset%",	203 },
2740
    { "%notsubset%",	203 },
2741
    { "%subset%",	204 },
2741
    { "%subset%",	204 },
2742
    { "%subseteq%",	205 },
2742
    { "%subseteq%",	205 },
2743
    { "%in%",		206 },
2743
    { "%in%",		206 },
2744
    { "%notin%",	207 },
2744
    { "%notin%",	207 },
2745
 
2745
 
2746
    { NULL,		  0 },
2746
    { NULL,		  0 },
2747
};
2747
};
2748
 
2748
 
2749
static int RelAtom(SEXP expr)
2749
static int RelAtom(SEXP expr)
2750
{
2750
{
2751
    int i;
2751
    int i;
2752
    for (i = 0; RelTable[i].code; i++)
2752
    for (i = 0; RelTable[i].code; i++)
2753
	if (NameMatch(expr, RelTable[i].name))
2753
	if (NameMatch(expr, RelTable[i].name))
2754
	    return RelTable[i].code;
2754
	    return RelTable[i].code;
2755
    return 0;
2755
    return 0;
2756
}
2756
}
2757
 
2757
 
2758
static BBOX RenderRel(SEXP expr, int draw, mathContext *mc,
2758
static BBOX RenderRel(SEXP expr, int draw, mathContext *mc,
2759
		      R_GE_gcontext *gc, GEDevDesc *dd)
2759
		      R_GE_gcontext *gc, GEDevDesc *dd)
2760
{
2760
{
2761
    int op = RelAtom(CAR(expr));
2761
    int op = RelAtom(CAR(expr));
2762
    int nexpr = length(expr);
2762
    int nexpr = length(expr);
2763
    BBOX bbox;
2763
    BBOX bbox;
2764
    double gap;
2764
    double gap;
2765
 
2765
 
2766
    if(nexpr == 3) {
2766
    if(nexpr == 3) {
2767
	gap = (mc->CurrentStyle > STYLE_S) ? ThickSpace(gc, dd) : 0;
2767
	gap = (mc->CurrentStyle > STYLE_S) ? ThickSpace(gc, dd) : 0;
2768
	bbox = RenderElement(CADR(expr), draw, mc, gc, dd);
2768
	bbox = RenderElement(CADR(expr), draw, mc, gc, dd);
2769
	bbox = RenderItalicCorr(bbox, draw, mc, gc, dd);
2769
	bbox = RenderItalicCorr(bbox, draw, mc, gc, dd);
2770
	bbox = CombineBBoxes(bbox, RenderGap(gap, draw, mc, gc, dd));
2770
	bbox = CombineBBoxes(bbox, RenderGap(gap, draw, mc, gc, dd));
2771
	bbox = CombineBBoxes(bbox, RenderSymbolChar(op, draw, mc, gc, dd));
2771
	bbox = CombineBBoxes(bbox, RenderSymbolChar(op, draw, mc, gc, dd));
2772
	bbox = CombineBBoxes(bbox, RenderGap(gap, draw, mc, gc, dd));
2772
	bbox = CombineBBoxes(bbox, RenderGap(gap, draw, mc, gc, dd));
2773
	return
2773
	return
2774
	    CombineBBoxes(bbox, RenderElement(CADDR(expr), draw, mc, gc, dd));
2774
	    CombineBBoxes(bbox, RenderElement(CADDR(expr), draw, mc, gc, dd));
2775
    }
2775
    }
2776
    else error(_("invalid mathematical annotation"));
2776
    else error(_("invalid mathematical annotation"));
2777
 
2777
 
2778
    return NullBBox();		/* -Wall */
2778
    return NullBBox();		/* -Wall */
2779
}
2779
}
2780
 
2780
 
2781
 
2781
 
2782
/*----------------------------------------------------------------------
2782
/*----------------------------------------------------------------------
2783
 *
2783
 *
2784
 *  Code for Boldface Expressions
2784
 *  Code for Boldface Expressions
2785
 *
2785
 *
2786
 */
2786
 */
2787
 
2787
 
2788
static int BoldAtom(SEXP expr)
2788
static int BoldAtom(SEXP expr)
2789
{
2789
{
2790
    return NameAtom(expr) &&
2790
    return NameAtom(expr) &&
2791
	NameMatch(expr, "bold");
2791
	NameMatch(expr, "bold");
2792
}
2792
}
2793
 
2793
 
2794
static BBOX RenderBold(SEXP expr, int draw, mathContext *mc,
2794
static BBOX RenderBold(SEXP expr, int draw, mathContext *mc,
2795
		       R_GE_gcontext *gc, GEDevDesc *dd)
2795
		       R_GE_gcontext *gc, GEDevDesc *dd)
2796
{
2796
{
2797
    BBOX bbox;
2797
    BBOX bbox;
2798
    FontType prevfont = SetFont(BoldFont, gc);
2798
    FontType prevfont = SetFont(BoldFont, gc);
2799
    bbox = RenderElement(CADR(expr), draw, mc, gc, dd);
2799
    bbox = RenderElement(CADR(expr), draw, mc, gc, dd);
2800
    SetFont(prevfont, gc);
2800
    SetFont(prevfont, gc);
2801
    return bbox;
2801
    return bbox;
2802
}
2802
}
2803
 
2803
 
2804
/*----------------------------------------------------------------------
2804
/*----------------------------------------------------------------------
2805
 *
2805
 *
2806
 *  Code for Italic Expressions
2806
 *  Code for Italic Expressions
2807
 *
2807
 *
2808
 */
2808
 */
2809
 
2809
 
2810
static int ItalicAtom(SEXP expr)
2810
static int ItalicAtom(SEXP expr)
2811
{
2811
{
2812
    return NameAtom(expr) &&
2812
    return NameAtom(expr) &&
2813
	(NameMatch(expr, "italic") || NameMatch(expr, "math"));
2813
	(NameMatch(expr, "italic") || NameMatch(expr, "math"));
2814
}
2814
}
2815
 
2815
 
2816
static BBOX RenderItalic(SEXP expr, int draw, mathContext *mc,
2816
static BBOX RenderItalic(SEXP expr, int draw, mathContext *mc,
2817
			 R_GE_gcontext *gc, GEDevDesc *dd)
2817
			 R_GE_gcontext *gc, GEDevDesc *dd)
2818
{
2818
{
2819
    BBOX bbox;
2819
    BBOX bbox;
2820
    FontType prevfont = SetFont(ItalicFont, gc);
2820
    FontType prevfont = SetFont(ItalicFont, gc);
2821
    bbox = RenderElement(CADR(expr), draw, mc, gc, dd);
2821
    bbox = RenderElement(CADR(expr), draw, mc, gc, dd);
2822
    SetFont(prevfont, gc);
2822
    SetFont(prevfont, gc);
2823
    return bbox;
2823
    return bbox;
2824
}
2824
}
2825
 
2825
 
2826
/*----------------------------------------------------------------------
2826
/*----------------------------------------------------------------------
2827
 *
2827
 *
2828
 *  Code for Plain (i.e. Roman) Expressions
2828
 *  Code for Plain (i.e. Roman) Expressions
2829
 *
2829
 *
2830
 */
2830
 */
2831
 
2831
 
2832
static int PlainAtom(SEXP expr)
2832
static int PlainAtom(SEXP expr)
2833
{
2833
{
2834
    return NameAtom(expr) &&
2834
    return NameAtom(expr) &&
2835
	NameMatch(expr, "plain");
2835
	NameMatch(expr, "plain");
2836
}
2836
}
2837
 
2837
 
2838
static BBOX RenderPlain(SEXP expr, int draw, mathContext *mc,
2838
static BBOX RenderPlain(SEXP expr, int draw, mathContext *mc,
2839
			R_GE_gcontext *gc, GEDevDesc *dd)
2839
			R_GE_gcontext *gc, GEDevDesc *dd)
2840
{
2840
{
2841
    BBOX bbox;
2841
    BBOX bbox;
2842
    int prevfont = SetFont(PlainFont, gc);
2842
    int prevfont = SetFont(PlainFont, gc);
2843
    bbox = RenderElement(CADR(expr), draw, mc, gc, dd);
2843
    bbox = RenderElement(CADR(expr), draw, mc, gc, dd);
2844
    SetFont(prevfont, gc);
2844
    SetFont(prevfont, gc);
2845
    return bbox;
2845
    return bbox;
2846
}
2846
}
2847
 
2847
 
2848
/*----------------------------------------------------------------------
2848
/*----------------------------------------------------------------------
2849
 *
2849
 *
2850
 *  Code for Bold Italic Expressions
2850
 *  Code for Bold Italic Expressions
2851
 *
2851
 *
2852
 */
2852
 */
2853
 
2853
 
2854
static int BoldItalicAtom(SEXP expr)
2854
static int BoldItalicAtom(SEXP expr)
2855
{
2855
{
2856
    return NameAtom(expr) &&
2856
    return NameAtom(expr) &&
2857
	(NameMatch(expr, "bolditalic") || NameMatch(expr, "boldmath"));
2857
	(NameMatch(expr, "bolditalic") || NameMatch(expr, "boldmath"));
2858
}
2858
}
2859
 
2859
 
2860
static BBOX RenderBoldItalic(SEXP expr, int draw, mathContext *mc,
2860
static BBOX RenderBoldItalic(SEXP expr, int draw, mathContext *mc,
2861
			     R_GE_gcontext *gc, GEDevDesc *dd)
2861
			     R_GE_gcontext *gc, GEDevDesc *dd)
2862
{
2862
{
2863
    BBOX bbox;
2863
    BBOX bbox;
2864
    int prevfont = SetFont(BoldItalicFont, gc);
2864
    int prevfont = SetFont(BoldItalicFont, gc);
2865
    bbox = RenderElement(CADR(expr), draw, mc, gc, dd);
2865
    bbox = RenderElement(CADR(expr), draw, mc, gc, dd);
2866
    SetFont(prevfont, gc);
2866
    SetFont(prevfont, gc);
2867
    return bbox;
2867
    return bbox;
2868
}
2868
}
2869
 
2869
 
2870
/*----------------------------------------------------------------------
2870
/*----------------------------------------------------------------------
2871
 *
2871
 *
2872
 *  Code for Styles
2872
 *  Code for Styles
2873
 *
2873
 *
2874
 */
2874
 */
2875
 
2875
 
2876
static int StyleAtom(SEXP expr)
2876
static int StyleAtom(SEXP expr)
2877
{
2877
{
2878
    return (NameAtom(expr) &&
2878
    return (NameAtom(expr) &&
2879
	    (NameMatch(expr, "displaystyle") ||
2879
	    (NameMatch(expr, "displaystyle") ||
2880
	     NameMatch(expr, "textstyle")    ||
2880
	     NameMatch(expr, "textstyle")    ||
2881
	     NameMatch(expr, "scriptstyle")   ||
2881
	     NameMatch(expr, "scriptstyle")   ||
2882
	     NameMatch(expr, "scriptscriptstyle")));
2882
	     NameMatch(expr, "scriptscriptstyle")));
2883
}
2883
}
2884
 
2884
 
2885
static BBOX RenderStyle(SEXP expr, int draw, mathContext *mc,
2885
static BBOX RenderStyle(SEXP expr, int draw, mathContext *mc,
2886
			R_GE_gcontext *gc, GEDevDesc *dd)
2886
			R_GE_gcontext *gc, GEDevDesc *dd)
2887
{
2887
{
2888
    STYLE prevstyle = GetStyle(mc);
2888
    STYLE prevstyle = GetStyle(mc);
2889
    BBOX bbox;
2889
    BBOX bbox;
2890
    if (NameMatch(CAR(expr), "displaystyle"))
2890
    if (NameMatch(CAR(expr), "displaystyle"))
2891
	SetStyle(STYLE_D, mc, gc);
2891
	SetStyle(STYLE_D, mc, gc);
2892
    else if (NameMatch(CAR(expr), "textstyle"))
2892
    else if (NameMatch(CAR(expr), "textstyle"))
2893
	SetStyle(STYLE_T, mc, gc);
2893
	SetStyle(STYLE_T, mc, gc);
2894
    else if (NameMatch(CAR(expr), "scriptstyle"))
2894
    else if (NameMatch(CAR(expr), "scriptstyle"))
2895
	SetStyle(STYLE_S, mc, gc);
2895
	SetStyle(STYLE_S, mc, gc);
2896
    else if (NameMatch(CAR(expr), "scriptscriptstyle"))
2896
    else if (NameMatch(CAR(expr), "scriptscriptstyle"))
2897
	SetStyle(STYLE_SS, mc, gc);
2897
	SetStyle(STYLE_SS, mc, gc);
2898
    bbox = RenderElement(CADR(expr), draw, mc, gc, dd);
2898
    bbox = RenderElement(CADR(expr), draw, mc, gc, dd);
2899
    SetStyle(prevstyle, mc, gc);
2899
    SetStyle(prevstyle, mc, gc);
2900
    return bbox;
2900
    return bbox;
2901
}
2901
}
2902
 
2902
 
2903
/*----------------------------------------------------------------------
2903
/*----------------------------------------------------------------------
2904
 *
2904
 *
2905
 *  Code for Phantom Expressions
2905
 *  Code for Phantom Expressions
2906
 *
2906
 *
2907
 */
2907
 */
2908
 
2908
 
2909
static int PhantomAtom(SEXP expr)
2909
static int PhantomAtom(SEXP expr)
2910
{
2910
{
2911
    return (NameAtom(expr) &&
2911
    return (NameAtom(expr) &&
2912
	    (NameMatch(expr, "phantom") ||
2912
	    (NameMatch(expr, "phantom") ||
2913
	     NameMatch(expr, "vphantom")));
2913
	     NameMatch(expr, "vphantom")));
2914
}
2914
}
2915
 
2915
 
2916
static BBOX RenderPhantom(SEXP expr, int draw, mathContext *mc,
2916
static BBOX RenderPhantom(SEXP expr, int draw, mathContext *mc,
2917
			  R_GE_gcontext *gc, GEDevDesc *dd)
2917
			  R_GE_gcontext *gc, GEDevDesc *dd)
2918
{
2918
{
2919
    BBOX bbox = RenderElement(CADR(expr), 0, mc, gc, dd);
2919
    BBOX bbox = RenderElement(CADR(expr), 0, mc, gc, dd);
2920
    if (NameMatch(CAR(expr), "vphantom")) {
2920
    if (NameMatch(CAR(expr), "vphantom")) {
2921
	bboxWidth(bbox) = 0;
2921
	bboxWidth(bbox) = 0;
2922
	bboxItalic(bbox) = 0;
2922
	bboxItalic(bbox) = 0;
2923
    }
2923
    }
2924
    else RenderGap(bboxWidth(bbox), draw, mc, gc, dd);
2924
    else RenderGap(bboxWidth(bbox), draw, mc, gc, dd);
2925
    return bbox;
2925
    return bbox;
2926
}
2926
}
2927
 
2927
 
2928
/*----------------------------------------------------------------------
2928
/*----------------------------------------------------------------------
2929
 *
2929
 *
2930
 *  Code for Concatenate Expressions
2930
 *  Code for Concatenate Expressions
2931
 *
2931
 *
2932
 */
2932
 */
2933
 
2933
 
2934
static int ConcatenateAtom(SEXP expr)
2934
static int ConcatenateAtom(SEXP expr)
2935
{
2935
{
2936
    return NameAtom(expr) && NameMatch(expr, "paste");
2936
    return NameAtom(expr) && NameMatch(expr, "paste");
2937
}
2937
}
2938
 
2938
 
2939
static BBOX RenderConcatenate(SEXP expr, int draw, mathContext *mc,
2939
static BBOX RenderConcatenate(SEXP expr, int draw, mathContext *mc,
2940
			      R_GE_gcontext *gc, GEDevDesc *dd)
2940
			      R_GE_gcontext *gc, GEDevDesc *dd)
2941
{
2941
{
2942
    BBOX bbox = NullBBox();
2942
    BBOX bbox = NullBBox();
2943
    int i, n;
2943
    int i, n;
2944
 
2944
 
2945
    expr = CDR(expr);
2945
    expr = CDR(expr);
2946
    n = length(expr);
2946
    n = length(expr);
2947
 
2947
 
2948
    for (i = 0; i < n; i++) {
2948
    for (i = 0; i < n; i++) {
2949
	bbox = CombineBBoxes(bbox, RenderElement(CAR(expr), draw, mc, gc, dd));
2949
	bbox = CombineBBoxes(bbox, RenderElement(CAR(expr), draw, mc, gc, dd));
2950
	if (i != n - 1)
2950
	if (i != n - 1)
2951
	    bbox = RenderItalicCorr(bbox, draw, mc, gc, dd);
2951
	    bbox = RenderItalicCorr(bbox, draw, mc, gc, dd);
2952
	expr = CDR(expr);
2952
	expr = CDR(expr);
2953
    }
2953
    }
2954
    return bbox;
2954
    return bbox;
2955
}
2955
}
2956
 
2956
 
2957
/*----------------------------------------------------------------------
2957
/*----------------------------------------------------------------------
2958
 *
2958
 *
2959
 *  Code for Comma-Separated Lists
2959
 *  Code for Comma-Separated Lists
2960
 *
2960
 *
2961
 */
2961
 */
2962
 
2962
 
2963
static BBOX RenderCommaList(SEXP expr, int draw, mathContext *mc,
2963
static BBOX RenderCommaList(SEXP expr, int draw, mathContext *mc,
2964
			    R_GE_gcontext *gc, GEDevDesc *dd)
2964
			    R_GE_gcontext *gc, GEDevDesc *dd)
2965
{
2965
{
2966
    BBOX bbox = NullBBox();
2966
    BBOX bbox = NullBBox();
2967
    double small = 0.4 * ThinSpace(gc, dd);
2967
    double small = 0.4 * ThinSpace(gc, dd);
2968
    int i, n;
2968
    int i, n;
2969
    n = length(expr);
2969
    n = length(expr);
2970
    for (i = 0; i < n; i++) {
2970
    for (i = 0; i < n; i++) {
2971
	if (NameAtom(CAR(expr)) && NameMatch(CAR(expr), "...")) {
2971
	if (NameAtom(CAR(expr)) && NameMatch(CAR(expr), "...")) {
2972
	    if (i > 0) {
2972
	    if (i > 0) {
2973
		bbox = CombineBBoxes(bbox, RenderSymbolChar(S_COMMA, draw,
2973
		bbox = CombineBBoxes(bbox, RenderSymbolChar(S_COMMA, draw,
2974
							    mc, gc, dd));
2974
							    mc, gc, dd));
2975
		bbox = CombineBBoxes(bbox, RenderSymbolChar(S_SPACE, draw,
2975
		bbox = CombineBBoxes(bbox, RenderSymbolChar(S_SPACE, draw,
2976
							    mc, gc, dd));
2976
							    mc, gc, dd));
2977
	    }
2977
	    }
2978
	    bbox = CombineBBoxes(bbox, RenderSymbolChar(S_ELLIPSIS, draw,
2978
	    bbox = CombineBBoxes(bbox, RenderSymbolChar(S_ELLIPSIS, draw,
2979
							mc, gc, dd));
2979
							mc, gc, dd));
2980
	    bbox = CombineBBoxes(bbox, RenderGap(small, draw, mc, gc, dd));
2980
	    bbox = CombineBBoxes(bbox, RenderGap(small, draw, mc, gc, dd));
2981
	}
2981
	}
2982
	else {
2982
	else {
2983
	    if (i > 0) {
2983
	    if (i > 0) {
2984
		bbox = CombineBBoxes(bbox, RenderSymbolChar(S_COMMA, draw,
2984
		bbox = CombineBBoxes(bbox, RenderSymbolChar(S_COMMA, draw,
2985
							    mc, gc, dd));
2985
							    mc, gc, dd));
2986
		bbox = CombineBBoxes(bbox, RenderSymbolChar(S_SPACE, draw,
2986
		bbox = CombineBBoxes(bbox, RenderSymbolChar(S_SPACE, draw,
2987
							    mc, gc, dd));
2987
							    mc, gc, dd));
2988
	    }
2988
	    }
2989
	    bbox = CombineBBoxes(bbox, RenderElement(CAR(expr), draw, mc,
2989
	    bbox = CombineBBoxes(bbox, RenderElement(CAR(expr), draw, mc,
2990
						     gc, dd));
2990
						     gc, dd));
2991
	}
2991
	}
2992
	expr = CDR(expr);
2992
	expr = CDR(expr);
2993
    }
2993
    }
2994
    return bbox;
2994
    return bbox;
2995
}
2995
}
2996
 
2996
 
2997
/*----------------------------------------------------------------------
2997
/*----------------------------------------------------------------------
2998
 *
2998
 *
2999
 *  Code for General Expressions
2999
 *  Code for General Expressions
3000
 *
3000
 *
3001
 */
3001
 */
3002
 
3002
 
3003
static BBOX RenderExpression(SEXP expr, int draw, mathContext *mc,
3003
static BBOX RenderExpression(SEXP expr, int draw, mathContext *mc,
3004
			     R_GE_gcontext *gc, GEDevDesc *dd)
3004
			     R_GE_gcontext *gc, GEDevDesc *dd)
3005
{
3005
{
3006
    BBOX bbox;
3006
    BBOX bbox;
3007
    if (NameAtom(CAR(expr)))
3007
    if (NameAtom(CAR(expr)))
3008
	bbox = RenderSymbolString(CAR(expr), draw, mc, gc, dd);
3008
	bbox = RenderSymbolString(CAR(expr), draw, mc, gc, dd);
3009
    else
3009
    else
3010
	bbox = RenderElement(CAR(expr), draw, mc, gc, dd);
3010
	bbox = RenderElement(CAR(expr), draw, mc, gc, dd);
3011
    bbox = RenderItalicCorr(bbox, draw, mc, gc, dd);
3011
    bbox = RenderItalicCorr(bbox, draw, mc, gc, dd);
3012
    bbox = CombineBBoxes(bbox, RenderDelimiter(S_PARENLEFT, draw, mc, gc, dd));
3012
    bbox = CombineBBoxes(bbox, RenderDelimiter(S_PARENLEFT, draw, mc, gc, dd));
3013
    bbox = CombineBBoxes(bbox, RenderCommaList(CDR(expr), draw, mc, gc, dd));
3013
    bbox = CombineBBoxes(bbox, RenderCommaList(CDR(expr), draw, mc, gc, dd));
3014
    bbox = RenderItalicCorr(bbox, draw, mc, gc, dd);
3014
    bbox = RenderItalicCorr(bbox, draw, mc, gc, dd);
3015
    bbox = CombineBBoxes(bbox, RenderDelimiter(S_PARENRIGHT, draw, mc, gc, dd));
3015
    bbox = CombineBBoxes(bbox, RenderDelimiter(S_PARENRIGHT, draw, mc, gc, dd));
3016
    return bbox;
3016
    return bbox;
3017
}
3017
}
3018
 
3018
 
3019
/*----------------------------------------------------------------------
3019
/*----------------------------------------------------------------------
3020
 *
3020
 *
3021
 *  Code for Comma Separated List Expressions
3021
 *  Code for Comma Separated List Expressions
3022
 *
3022
 *
3023
 */
3023
 */
3024
 
3024
 
3025
static int ListAtom(SEXP expr)
3025
static int ListAtom(SEXP expr)
3026
{
3026
{
3027
    return NameAtom(expr) && NameMatch(expr, "list");
3027
    return NameAtom(expr) && NameMatch(expr, "list");
3028
}
3028
}
3029
 
3029
 
3030
static BBOX RenderList(SEXP expr, int draw, mathContext *mc,
3030
static BBOX RenderList(SEXP expr, int draw, mathContext *mc,
3031
		       R_GE_gcontext *gc, GEDevDesc *dd)
3031
		       R_GE_gcontext *gc, GEDevDesc *dd)
3032
{
3032
{
3033
    return RenderCommaList(CDR(expr), draw, mc, gc, dd);
3033
    return RenderCommaList(CDR(expr), draw, mc, gc, dd);
3034
}
3034
}
3035
 
3035
 
3036
/* Dispatching procedure which determines nature of expression. */
3036
/* Dispatching procedure which determines nature of expression. */
3037
 
3037
 
3038
 
3038
 
3039
static BBOX RenderFormula(SEXP expr, int draw, mathContext *mc,
3039
static BBOX RenderFormula(SEXP expr, int draw, mathContext *mc,
3040
			  R_GE_gcontext *gc, GEDevDesc *dd)
3040
			  R_GE_gcontext *gc, GEDevDesc *dd)
3041
{
3041
{
3042
    SEXP head = CAR(expr);
3042
    SEXP head = CAR(expr);
3043
 
3043
 
3044
    if (SpaceAtom(head))
3044
    if (SpaceAtom(head))
3045
	return RenderSpace(expr, draw, mc, gc, dd);
3045
	return RenderSpace(expr, draw, mc, gc, dd);
3046
    else if (BinAtom(head))
3046
    else if (BinAtom(head))
3047
	return RenderBin(expr, draw, mc, gc, dd);
3047
	return RenderBin(expr, draw, mc, gc, dd);
3048
    else if (SuperAtom(head))
3048
    else if (SuperAtom(head))
3049
	return RenderSup(expr, draw, mc, gc, dd);
3049
	return RenderSup(expr, draw, mc, gc, dd);
3050
    else if (SubAtom(head))
3050
    else if (SubAtom(head))
3051
	return RenderSub(expr, draw, mc, gc, dd);
3051
	return RenderSub(expr, draw, mc, gc, dd);
3052
    else if (WideTildeAtom(head))
3052
    else if (WideTildeAtom(head))
3053
	return RenderWideTilde(expr, draw, mc, gc, dd);
3053
	return RenderWideTilde(expr, draw, mc, gc, dd);
3054
    else if (WideHatAtom(head))
3054
    else if (WideHatAtom(head))
3055
	return RenderWideHat(expr, draw, mc, gc, dd);
3055
	return RenderWideHat(expr, draw, mc, gc, dd);
3056
    else if (BarAtom(head))
3056
    else if (BarAtom(head))
3057
	return RenderBar(expr, draw, mc, gc, dd);
3057
	return RenderBar(expr, draw, mc, gc, dd);
3058
    else if (AccentAtom(head))
3058
    else if (AccentAtom(head))
3059
	return RenderAccent(expr, draw, mc, gc, dd);
3059
	return RenderAccent(expr, draw, mc, gc, dd);
3060
    else if (OverAtom(head))
3060
    else if (OverAtom(head))
3061
	return RenderOver(expr, draw, mc, gc, dd);
3061
	return RenderOver(expr, draw, mc, gc, dd);
3062
    else if (UnderlAtom(head))
3062
    else if (UnderlAtom(head))
3063
        return RenderUnderl(expr, draw, mc, gc, dd);
3063
        return RenderUnderl(expr, draw, mc, gc, dd);
3064
    else if (AtopAtom(head))
3064
    else if (AtopAtom(head))
3065
	return RenderAtop(expr, draw, mc, gc, dd);
3065
	return RenderAtop(expr, draw, mc, gc, dd);
3066
    else if (ParenAtom(head))
3066
    else if (ParenAtom(head))
3067
	return RenderParen(expr, draw, mc, gc, dd);
3067
	return RenderParen(expr, draw, mc, gc, dd);
3068
    else if (BGroupAtom(head))
3068
    else if (BGroupAtom(head))
3069
	return RenderBGroup(expr, draw, mc, gc, dd);
3069
	return RenderBGroup(expr, draw, mc, gc, dd);
3070
    else if (GroupAtom(head))
3070
    else if (GroupAtom(head))
3071
	return RenderGroup(expr, draw, mc, gc, dd);
3071
	return RenderGroup(expr, draw, mc, gc, dd);
3072
    else if (IntAtom(head))
3072
    else if (IntAtom(head))
3073
	return RenderInt(expr, draw, mc, gc, dd);
3073
	return RenderInt(expr, draw, mc, gc, dd);
3074
    else if (OpAtom(head))
3074
    else if (OpAtom(head))
3075
	return RenderOp(expr, draw, mc, gc, dd);
3075
	return RenderOp(expr, draw, mc, gc, dd);
3076
    else if (RadicalAtom(head))
3076
    else if (RadicalAtom(head))
3077
	return RenderRadical(expr, draw, mc, gc, dd);
3077
	return RenderRadical(expr, draw, mc, gc, dd);
3078
    else if (AbsAtom(head))
3078
    else if (AbsAtom(head))
3079
	return RenderAbs(expr, draw, mc, gc, dd);
3079
	return RenderAbs(expr, draw, mc, gc, dd);
3080
    else if (CurlyAtom(head))
3080
    else if (CurlyAtom(head))
3081
	return RenderCurly(expr, draw, mc, gc, dd);
3081
	return RenderCurly(expr, draw, mc, gc, dd);
3082
    else if (RelAtom(head))
3082
    else if (RelAtom(head))
3083
	return RenderRel(expr, draw, mc, gc, dd);
3083
	return RenderRel(expr, draw, mc, gc, dd);
3084
    else if (BoldAtom(head))
3084
    else if (BoldAtom(head))
3085
	return RenderBold(expr, draw, mc, gc, dd);
3085
	return RenderBold(expr, draw, mc, gc, dd);
3086
    else if (ItalicAtom(head))
3086
    else if (ItalicAtom(head))
3087
	return RenderItalic(expr, draw, mc, gc, dd);
3087
	return RenderItalic(expr, draw, mc, gc, dd);
3088
    else if (PlainAtom(head))
3088
    else if (PlainAtom(head))
3089
	return RenderPlain(expr, draw, mc, gc, dd);
3089
	return RenderPlain(expr, draw, mc, gc, dd);
3090
    else if (BoldItalicAtom(head))
3090
    else if (BoldItalicAtom(head))
3091
	return RenderBoldItalic(expr, draw, mc, gc, dd);
3091
	return RenderBoldItalic(expr, draw, mc, gc, dd);
3092
    else if (StyleAtom(head))
3092
    else if (StyleAtom(head))
3093
	return RenderStyle(expr, draw, mc, gc, dd);
3093
	return RenderStyle(expr, draw, mc, gc, dd);
3094
    else if (PhantomAtom(head))
3094
    else if (PhantomAtom(head))
3095
	return RenderPhantom(expr, draw, mc, gc, dd);
3095
	return RenderPhantom(expr, draw, mc, gc, dd);
3096
    else if (ConcatenateAtom(head))
3096
    else if (ConcatenateAtom(head))
3097
	return RenderConcatenate(expr, draw, mc, gc, dd);
3097
	return RenderConcatenate(expr, draw, mc, gc, dd);
3098
    else if (ListAtom(head))
3098
    else if (ListAtom(head))
3099
	return RenderList(expr, draw, mc, gc, dd);
3099
	return RenderList(expr, draw, mc, gc, dd);
3100
    else
3100
    else
3101
	return RenderExpression(expr, draw, mc, gc, dd);
3101
	return RenderExpression(expr, draw, mc, gc, dd);
3102
}
3102
}
3103
 
3103
 
3104
 
3104
 
3105
/* Dispatch on whether atom (symbol, string, number, ...) */
3105
/* Dispatch on whether atom (symbol, string, number, ...) */
3106
/* or formula (some sort of expression) */
3106
/* or formula (some sort of expression) */
3107
 
3107
 
3108
static BBOX RenderElement(SEXP expr, int draw, mathContext *mc,
3108
static BBOX RenderElement(SEXP expr, int draw, mathContext *mc,
3109
			  R_GE_gcontext *gc, GEDevDesc *dd)
3109
			  R_GE_gcontext *gc, GEDevDesc *dd)
3110
{
3110
{
3111
    if (FormulaExpression(expr))
3111
    if (FormulaExpression(expr))
3112
	return RenderFormula(expr, draw, mc, gc, dd);
3112
	return RenderFormula(expr, draw, mc, gc, dd);
3113
    else
3113
    else
3114
	return RenderAtom(expr, draw, mc, gc, dd);
3114
	return RenderAtom(expr, draw, mc, gc, dd);
3115
}
3115
}
3116
 
3116
 
3117
static BBOX RenderOffsetElement(SEXP expr, double x, double y, int draw,
3117
static BBOX RenderOffsetElement(SEXP expr, double x, double y, int draw,
3118
				mathContext *mc, R_GE_gcontext *gc,
3118
				mathContext *mc, R_GE_gcontext *gc,
3119
				GEDevDesc *dd)
3119
				GEDevDesc *dd)
3120
{
3120
{
3121
    BBOX bbox;
3121
    BBOX bbox;
3122
    double savedX = mc->CurrentX;
3122
    double savedX = mc->CurrentX;
3123
    double savedY = mc->CurrentY;
3123
    double savedY = mc->CurrentY;
3124
    if (draw) {
3124
    if (draw) {
3125
	mc->CurrentX += x;
3125
	mc->CurrentX += x;
3126
	mc->CurrentY += y;
3126
	mc->CurrentY += y;
3127
    }
3127
    }
3128
    bbox = RenderElement(expr, draw, mc, gc, dd);
3128
    bbox = RenderElement(expr, draw, mc, gc, dd);
3129
    bboxWidth(bbox) += x;
3129
    bboxWidth(bbox) += x;
3130
    bboxHeight(bbox) += y;
3130
    bboxHeight(bbox) += y;
3131
    bboxDepth(bbox) -= y;
3131
    bboxDepth(bbox) -= y;
3132
    mc->CurrentX = savedX;
3132
    mc->CurrentX = savedX;
3133
    mc->CurrentY = savedY;
3133
    mc->CurrentY = savedY;
3134
    return bbox;
3134
    return bbox;
3135
 
3135
 
3136
}
3136
}
3137
 
3137
 
3138
/* Functions forming the R API */
3138
/* Functions forming the R API */
3139
 
3139
 
3140
/* Calculate width of expression */
3140
/* Calculate width of expression */
3141
/* BBOXes are in INCHES (see MetricUnit) */
3141
/* BBOXes are in INCHES (see MetricUnit) */
3142
 
3142
 
3143
double GEExpressionWidth(SEXP expr,
3143
double GEExpressionWidth(SEXP expr,
3144
			 R_GE_gcontext *gc,
3144
			 R_GE_gcontext *gc,
3145
			 GEDevDesc *dd)
3145
			 GEDevDesc *dd)
3146
{
3146
{
3147
    BBOX bbox;
3147
    BBOX bbox;
3148
    double width;
3148
    double width;
3149
 
3149
 
3150
    /*
3150
    /*
3151
     * Build a "drawing context" for the current expression
3151
     * Build a "drawing context" for the current expression
3152
     */
3152
     */
3153
    mathContext mc;
3153
    mathContext mc;
3154
    mc.BaseCex = gc->cex;
3154
    mc.BaseCex = gc->cex;
3155
    mc.BoxColor = name2col("pink");
3155
    mc.BoxColor = name2col("pink");
3156
    mc.CurrentStyle = STYLE_D;
3156
    mc.CurrentStyle = STYLE_D;
3157
    /*
3157
    /*
3158
     * Some "empty" values.  Will be filled in after BBox is calc'ed
3158
     * Some "empty" values.  Will be filled in after BBox is calc'ed
3159
     */
3159
     */
3160
    mc.ReferenceX = 0;
3160
    mc.ReferenceX = 0;
3161
    mc.ReferenceY = 0;
3161
    mc.ReferenceY = 0;
3162
    mc.CurrentX = 0;
3162
    mc.CurrentX = 0;
3163
    mc.CurrentY = 0;
3163
    mc.CurrentY = 0;
3164
    mc.CurrentAngle = 0;
3164
    mc.CurrentAngle = 0;
3165
    mc.CosAngle = 0;
3165
    mc.CosAngle = 0;
3166
    mc.SinAngle = 0;
3166
    mc.SinAngle = 0;
3167
 
3167
 
3168
    SetFont(PlainFont, gc);
3168
    SetFont(PlainFont, gc);
3169
    bbox = RenderElement(expr, 0, &mc, gc, dd);
3169
    bbox = RenderElement(expr, 0, &mc, gc, dd);
3170
    width  = bboxWidth(bbox);
3170
    width  = bboxWidth(bbox);
3171
    /*
3171
    /*
3172
     * NOTE that we do fabs() here in case the device
3172
     * NOTE that we do fabs() here in case the device
3173
     * runs right-to-left.
3173
     * runs right-to-left.
3174
     * This is so that these calculations match those
3174
     * This is so that these calculations match those
3175
     * for string widths and heights, where the width
3175
     * for string widths and heights, where the width
3176
     * and height of text is positive no matter how
3176
     * and height of text is positive no matter how
3177
     * the device drawing is oriented.
3177
     * the device drawing is oriented.
3178
     */
3178
     */
3179
    return fabs(toDeviceWidth(width, GE_INCHES, dd));
3179
    return fabs(toDeviceWidth(width, GE_INCHES, dd));
3180
}
3180
}
3181
 
3181
 
3182
double GEExpressionHeight(SEXP expr,
3182
double GEExpressionHeight(SEXP expr,
3183
			  R_GE_gcontext *gc,
3183
			  R_GE_gcontext *gc,
3184
			  GEDevDesc *dd)
3184
			  GEDevDesc *dd)
3185
{
3185
{
3186
    BBOX bbox;
3186
    BBOX bbox;
3187
    double height;
3187
    double height;
3188
 
3188
 
3189
    /*
3189
    /*
3190
     * Build a "drawing context" for the current expression
3190
     * Build a "drawing context" for the current expression
3191
     */
3191
     */
3192
    mathContext mc;
3192
    mathContext mc;
3193
    mc.BaseCex = gc->cex;
3193
    mc.BaseCex = gc->cex;
3194
    mc.BoxColor = name2col("pink");
3194
    mc.BoxColor = name2col("pink");
3195
    mc.CurrentStyle = STYLE_D;
3195
    mc.CurrentStyle = STYLE_D;
3196
    /*
3196
    /*
3197
     * Some "empty" values.  Will be filled in after BBox is calc'ed
3197
     * Some "empty" values.  Will be filled in after BBox is calc'ed
3198
     */
3198
     */
3199
    mc.ReferenceX = 0;
3199
    mc.ReferenceX = 0;
3200
    mc.ReferenceY = 0;
3200
    mc.ReferenceY = 0;
3201
    mc.CurrentX = 0;
3201
    mc.CurrentX = 0;
3202
    mc.CurrentY = 0;
3202
    mc.CurrentY = 0;
3203
    mc.CurrentAngle = 0;
3203
    mc.CurrentAngle = 0;
3204
    mc.CosAngle = 0;
3204
    mc.CosAngle = 0;
3205
    mc.SinAngle = 0;
3205
    mc.SinAngle = 0;
3206
 
3206
 
3207
    SetFont(PlainFont, gc);
3207
    SetFont(PlainFont, gc);
3208
    bbox = RenderElement(expr, 0, &mc, gc, dd);
3208
    bbox = RenderElement(expr, 0, &mc, gc, dd);
3209
    height = bboxHeight(bbox) + bboxDepth(bbox);
3209
    height = bboxHeight(bbox) + bboxDepth(bbox);
3210
    /* NOTE that we do fabs() here in case the device
3210
    /* NOTE that we do fabs() here in case the device
3211
     * draws top-to-bottom (like an X11 window).
3211
     * draws top-to-bottom (like an X11 window).
3212
     * This is so that these calculations match those
3212
     * This is so that these calculations match those
3213
     * for string widths and heights, where the width
3213
     * for string widths and heights, where the width
3214
     * and height of text is positive no matter how
3214
     * and height of text is positive no matter how
3215
     * the device drawing is oriented.
3215
     * the device drawing is oriented.
3216
     */
3216
     */
3217
    return fabs(toDeviceHeight(height, GE_INCHES, dd));
3217
    return fabs(toDeviceHeight(height, GE_INCHES, dd));
3218
}
3218
}
3219
 
3219
 
3220
void GEMathText(double x, double y, SEXP expr,
3220
void GEMathText(double x, double y, SEXP expr,
3221
		double xc, double yc, double rot,
3221
		double xc, double yc, double rot,
3222
		R_GE_gcontext *gc,
3222
		R_GE_gcontext *gc,
3223
		GEDevDesc *dd)
3223
		GEDevDesc *dd)
3224
{
3224
{
3225
    BBOX bbox;
3225
    BBOX bbox;
3226
    mathContext mc;
3226
    mathContext mc;
3227
 
3227
 
3228
#ifdef BUG61
3228
#ifdef BUG61
3229
#else
3229
#else
3230
    /* IF font metric information is not available for device */
3230
    /* IF font metric information is not available for device */
3231
    /* then bail out */
3231
    /* then bail out */
3232
    double ascent, descent, width;
3232
    double ascent, descent, width;
3233
    GEMetricInfo(0, gc,
3233
    GEMetricInfo(0, gc,
3234
		&ascent, &descent, &width, dd);
3234
		&ascent, &descent, &width, dd);
3235
    if ((ascent==0) && (descent==0) && (width==0))
3235
    if ((ascent==0) && (descent==0) && (width==0))
3236
	error(_("Metric information not available for this device"));
3236
	error(_("Metric information not available for this device"));
3237
#endif
3237
#endif
3238
 
3238
 
3239
    /*
3239
    /*
3240
     * Build a "drawing context" for the current expression
3240
     * Build a "drawing context" for the current expression
3241
     */
3241
     */
3242
    mc.BaseCex = gc->cex;
3242
    mc.BaseCex = gc->cex;
3243
    mc.BoxColor = name2col("pink");
3243
    mc.BoxColor = name2col("pink");
3244
    mc.CurrentStyle = STYLE_D;
3244
    mc.CurrentStyle = STYLE_D;
3245
    /*
3245
    /*
3246
     * Some "empty" values.  Will be filled in after BBox is calc'ed
3246
     * Some "empty" values.  Will be filled in after BBox is calc'ed
3247
     */
3247
     */
3248
    mc.ReferenceX = 0;
3248
    mc.ReferenceX = 0;
3249
    mc.ReferenceY = 0;
3249
    mc.ReferenceY = 0;
3250
    mc.CurrentX = 0;
3250
    mc.CurrentX = 0;
3251
    mc.CurrentY = 0;
3251
    mc.CurrentY = 0;
3252
    mc.CurrentAngle = 0;
3252
    mc.CurrentAngle = 0;
3253
    mc.CosAngle = 0;
3253
    mc.CosAngle = 0;
3254
    mc.SinAngle = 0;
3254
    mc.SinAngle = 0;
3255
 
3255
 
3256
    SetFont(PlainFont, gc);
3256
    SetFont(PlainFont, gc);
3257
    bbox = RenderElement(expr, 0, &mc, gc, dd);
3257
    bbox = RenderElement(expr, 0, &mc, gc, dd);
3258
    mc.ReferenceX = fromDeviceX(x, GE_INCHES, dd);
3258
    mc.ReferenceX = fromDeviceX(x, GE_INCHES, dd);
3259
    mc.ReferenceY = fromDeviceY(y, GE_INCHES, dd);
3259
    mc.ReferenceY = fromDeviceY(y, GE_INCHES, dd);
3260
    if (R_FINITE(xc))
3260
    if (R_FINITE(xc))
3261
	mc.CurrentX = mc.ReferenceX - xc * bboxWidth(bbox);
3261
	mc.CurrentX = mc.ReferenceX - xc * bboxWidth(bbox);
3262
    else
3262
    else
3263
	/* Paul 11/2/02
3263
	/* Paul 11/2/02
3264
	 * If xc == NA then should centre horizontally.
3264
	 * If xc == NA then should centre horizontally.
3265
	 * Used to left-adjust.
3265
	 * Used to left-adjust.
3266
	 */
3266
	 */
3267
	mc.CurrentX = mc.ReferenceX - 0.5 * bboxWidth(bbox);
3267
	mc.CurrentX = mc.ReferenceX - 0.5 * bboxWidth(bbox);
3268
    if (R_FINITE(yc))
3268
    if (R_FINITE(yc))
3269
	mc.CurrentY = mc.ReferenceY + bboxDepth(bbox)
3269
	mc.CurrentY = mc.ReferenceY + bboxDepth(bbox)
3270
	    - yc * (bboxHeight(bbox) + bboxDepth(bbox));
3270
	    - yc * (bboxHeight(bbox) + bboxDepth(bbox));
3271
    else
3271
    else
3272
	/* Paul 11/2/02
3272
	/* Paul 11/2/02
3273
	 * If xc == NA then should centre vertically.
3273
	 * If xc == NA then should centre vertically.
3274
	 * Used to bottom-adjust.
3274
	 * Used to bottom-adjust.
3275
	 */
3275
	 */
3276
	mc.CurrentY = mc.ReferenceY + bboxDepth(bbox)
3276
	mc.CurrentY = mc.ReferenceY + bboxDepth(bbox)
3277
	    - 0.5 * (bboxHeight(bbox) + bboxDepth(bbox));
3277
	    - 0.5 * (bboxHeight(bbox) + bboxDepth(bbox));
3278
    mc.CurrentAngle = rot;
3278
    mc.CurrentAngle = rot;
3279
    rot *= M_PI_2 / 90 ;/* radians */
3279
    rot *= M_PI_2 / 90 ;/* radians */
3280
    mc.CosAngle = cos(rot);
3280
    mc.CosAngle = cos(rot);
3281
    mc.SinAngle = sin(rot);
3281
    mc.SinAngle = sin(rot);
3282
    RenderElement(expr, 1, &mc, gc, dd);
3282
    RenderElement(expr, 1, &mc, gc, dd);
3283
}/* GMathText */
3283
}/* GMathText */
3284
 
3284
 
3285
 
3285
 
3286
/********************************
3286
/********************************
3287
 * Code below here ...
3287
 * Code below here ...
3288
 * ... should be moved to base.c and
3288
 * ... should be moved to base.c and
3289
 * ... is part of the base graphics API NOT the graphics engine API
3289
 * ... is part of the base graphics API NOT the graphics engine API
3290
 ********************************
3290
 ********************************
3291
 */
3291
 */
3292
double GExpressionWidth(SEXP expr, GUnit units, DevDesc *dd)
3292
double GExpressionWidth(SEXP expr, GUnit units, DevDesc *dd)
3293
{
3293
{
3294
    R_GE_gcontext gc;
3294
    R_GE_gcontext gc;
3295
    double width;
3295
    double width;
3296
    gcontextFromGP(&gc, dd);
3296
    gcontextFromGP(&gc, dd);
3297
    width = GEExpressionWidth(expr, &gc, (GEDevDesc*) dd);
3297
    width = GEExpressionWidth(expr, &gc, (GEDevDesc*) dd);
3298
    if (units == DEVICE)
3298
    if (units == DEVICE)
3299
	return width;
3299
	return width;
3300
    else
3300
    else
3301
	return GConvertXUnits(width, DEVICE, units, dd);
3301
	return GConvertXUnits(width, DEVICE, units, dd);
3302
}
3302
}
3303
 
3303
 
3304
double GExpressionHeight(SEXP expr, GUnit units, DevDesc *dd)
3304
double GExpressionHeight(SEXP expr, GUnit units, DevDesc *dd)
3305
{
3305
{
3306
    R_GE_gcontext gc;
3306
    R_GE_gcontext gc;
3307
    double height;
3307
    double height;
3308
    gcontextFromGP(&gc, dd);
3308
    gcontextFromGP(&gc, dd);
3309
    height = GEExpressionHeight(expr, &gc, (GEDevDesc*) dd);
3309
    height = GEExpressionHeight(expr, &gc, (GEDevDesc*) dd);
3310
    if (units == DEVICE)
3310
    if (units == DEVICE)
3311
	return height;
3311
	return height;
3312
    else
3312
    else
3313
	return GConvertYUnits(height, DEVICE, units, dd);
3313
	return GConvertYUnits(height, DEVICE, units, dd);
3314
}
3314
}
3315
 
3315
 
3316
/* This is just here to satisfy the Rgraphics.h API.
3316
/* This is just here to satisfy the Rgraphics.h API.
3317
 * This allows new graphics API (GraphicsDevice.h, GraphicsEngine.h)
3317
 * This allows new graphics API (GraphicsDevice.h, GraphicsEngine.h)
3318
 * to be developed alongside.
3318
 * to be developed alongside.
3319
 * Could be removed if Rgraphics.h ever gets REPLACED by new API
3319
 * Could be removed if Rgraphics.h ever gets REPLACED by new API
3320
 * NOTE that base graphics code no longer calls this -- the base
3320
 * NOTE that base graphics code no longer calls this -- the base
3321
 * graphics system directly calls the graphics engine for mathematical
3321
 * graphics system directly calls the graphics engine for mathematical
3322
 * annotation (GEMathText)
3322
 * annotation (GEMathText)
3323
 */
3323
 */
3324
void GMathText(double x, double y, int coords, SEXP expr,
3324
void GMathText(double x, double y, int coords, SEXP expr,
3325
	       double xc, double yc, double rot,
3325
	       double xc, double yc, double rot,
3326
	       DevDesc *dd)
3326
	       DevDesc *dd)
3327
{
3327
{
3328
    R_GE_gcontext gc;
3328
    R_GE_gcontext gc;
3329
    gcontextFromGP(&gc, dd);
3329
    gcontextFromGP(&gc, dd);
3330
    GConvert(&x, &y, coords, DEVICE, dd);
3330
    GConvert(&x, &y, coords, DEVICE, dd);
3331
    GClip(dd);
3331
    GClip(dd);
3332
    GEMathText(x, y, expr, xc, yc, rot, &gc, (GEDevDesc*) dd);
3332
    GEMathText(x, y, expr, xc, yc, rot, &gc, (GEDevDesc*) dd);
3333
}
3333
}
3334
 
3334
 
3335
void GMMathText(SEXP str, int side, double line, int outer,
3335
void GMMathText(SEXP str, int side, double line, int outer,
3336
		double at, int las, double yadj, DevDesc *dd)
3336
		double at, int las, double yadj, DevDesc *dd)
3337
{
3337
{
3338
    int coords = 0, subcoords;
3338
    int coords = 0, subcoords;
3339
    double xadj, angle = 0;
3339
    double xadj, angle = 0;
3340
 
3340
 
3341
#ifdef BUG61
3341
#ifdef BUG61
3342
#else
3342
#else
3343
    /* IF font metric information is not available for device */
3343
    /* IF font metric information is not available for device */
3344
    /* then bail out */
3344
    /* then bail out */
3345
    double ascent, descent, width;
3345
    double ascent, descent, width;
3346
    GMetricInfo(0, &ascent, &descent, &width, DEVICE, dd);
3346
    GMetricInfo(0, &ascent, &descent, &width, DEVICE, dd);
3347
    if ((ascent==0) && (descent==0) && (width==0))
3347
    if ((ascent==0) && (descent==0) && (width==0))
3348
	error(_("Metric information not available for this device"));
3348
	error(_("Metric information not available for this device"));
3349
#endif
3349
#endif
3350
 
3350
 
3351
    xadj = Rf_gpptr(dd)->adj;
3351
    xadj = Rf_gpptr(dd)->adj;
3352
 
3352
 
3353
    /* This is MOSTLY the same as the same section of GMtext
3353
    /* This is MOSTLY the same as the same section of GMtext
3354
     * BUT it differs because it sets different values for yadj for
3354
     * BUT it differs because it sets different values for yadj for
3355
     * different situations.
3355
     * different situations.
3356
     * Paul
3356
     * Paul
3357
     */
3357
     */
3358
     /* changed to unify behaviour with changes in GMText. Uwe */
3358
     /* changed to unify behaviour with changes in GMText. Uwe */
3359
    if(outer) {
3359
    if(outer) {
3360
	switch(side) {
3360
	switch(side) {
3361
	case 1:	    coords = OMA1;	break;
3361
	case 1:	    coords = OMA1;	break;
3362
	case 2:	    coords = OMA2;	break;
3362
	case 2:	    coords = OMA2;	break;
3363
	case 3:	    coords = OMA3;	break;
3363
	case 3:	    coords = OMA3;	break;
3364
	case 4:	    coords = OMA4;	break;
3364
	case 4:	    coords = OMA4;	break;
3365
	}
3365
	}
3366
	subcoords = NIC;
3366
	subcoords = NIC;
3367
    }
3367
    }
3368
    else {
3368
    else {
3369
	switch(side) {
3369
	switch(side) {
3370
	case 1:	    coords = MAR1;	break;
3370
	case 1:	    coords = MAR1;	break;
3371
	case 2:	    coords = MAR2;	break;
3371
	case 2:	    coords = MAR2;	break;
3372
	case 3:	    coords = MAR3;	break;
3372
	case 3:	    coords = MAR3;	break;
3373
	case 4:	    coords = MAR4;	break;
3373
	case 4:	    coords = MAR4;	break;
3374
	}
3374
	}
3375
	subcoords = USER;
3375
	subcoords = USER;
3376
    }
3376
    }
3377
    /* Note: I changed Rf_gpptr(dd)->yLineBias to 0.3 here. */
3377
    /* Note: I changed Rf_gpptr(dd)->yLineBias to 0.3 here. */
3378
    /* Purely visual tuning. RI */
3378
    /* Purely visual tuning. RI */
3379
    /* Note: I removed the 0.3 fiddle here because mathematical
3379
    /* Note: I removed the 0.3 fiddle here because mathematical
3380
     * annotation stuff can do "exact" centering.
3380
     * annotation stuff can do "exact" centering.
3381
     * i.e., 0.3 fiddle is effectively replaced by yadj=0.5
3381
     * i.e., 0.3 fiddle is effectively replaced by yadj=0.5
3382
     */
3382
     */
3383
    switch(side) {
3383
    switch(side) {
3384
    case 1:
3384
    case 1:
3385
	if(las == 2 || las == 3) {
3385
	if(las == 2 || las == 3) {
3386
	    angle = 90;
3386
	    angle = 90;
3387
	}
3387
	}
3388
	else {
3388
	else {
3389
	    /*	    line = line + 1 - Rf_gpptr(dd)->yLineBias;
3389
	    /*	    line = line + 1 - Rf_gpptr(dd)->yLineBias;
3390
		    angle = 0;
3390
		    angle = 0;
3391
		    yadj = NA_REAL; */
3391
		    yadj = NA_REAL; */
3392
	    line = line + 1;
3392
	    line = line + 1;
3393
	    angle = 0;
3393
	    angle = 0;
3394
	}
3394
	}
3395
	break;
3395
	break;
3396
    case 2:
3396
    case 2:
3397
	if(las == 1 || las == 2) {
3397
	if(las == 1 || las == 2) {
3398
	    angle = 0;
3398
	    angle = 0;
3399
	}
3399
	}
3400
	else {
3400
	else {
3401
	    /*	    line = line + Rf_gpptr(dd)->yLineBias;
3401
	    /*	    line = line + Rf_gpptr(dd)->yLineBias;
3402
		    angle = 90;
3402
		    angle = 90;
3403
		    yadj = NA_REAL; */
3403
		    yadj = NA_REAL; */
3404
	    angle = 90;
3404
	    angle = 90;
3405
	}
3405
	}
3406
	break;
3406
	break;
3407
    case 3:
3407
    case 3:
3408
	if(las == 2 || las == 3) {
3408
	if(las == 2 || las == 3) {
3409
	    angle = 90;
3409
	    angle = 90;
3410
	}
3410
	}
3411
	else {
3411
	else {
3412
	    /*   line = line + Rf_gpptr(dd)->yLineBias;
3412
	    /*   line = line + Rf_gpptr(dd)->yLineBias;
3413
		 angle = 0;
3413
		 angle = 0;
3414
		 yadj = NA_REAL; */
3414
		 yadj = NA_REAL; */
3415
	    angle = 0;
3415
	    angle = 0;
3416
	}
3416
	}
3417
	break;
3417
	break;
3418
    case 4:
3418
    case 4:
3419
	if(las == 1 || las == 2) {
3419
	if(las == 1 || las == 2) {
3420
	    angle = 0;
3420
	    angle = 0;
3421
	}
3421
	}
3422
	else {
3422
	else {
3423
	    /*   line = line + 1 - Rf_gpptr(dd)->yLineBias;
3423
	    /*   line = line + 1 - Rf_gpptr(dd)->yLineBias;
3424
		 angle = 90;
3424
		 angle = 90;
3425
		 yadj = NA_REAL; */
3425
		 yadj = NA_REAL; */
3426
	    line = line + 1;
3426
	    line = line + 1;
3427
	    angle = 90;
3427
	    angle = 90;
3428
	}
3428
	}
3429
	break;
3429
	break;
3430
    }
3430
    }
3431
    GMathText(at, line, coords, str, xadj, yadj, angle, dd);
3431
    GMathText(at, line, coords, str, xadj, yadj, angle, dd);
3432
}/* GMMathText */
3432
}/* GMMathText */