The R Project SVN R

Rev

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

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