The R Project SVN R

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5148 ripley 1
/*
2
 *  A PicTeX device, (C) 1996 Valerio Aimale, for
3
 *  R : A Computer Language for Statistical Data Analysis
4
 *  Copyright (C) 1995, 1996  Robert Gentleman and Ross Ihaka
12976 pd 5
 *  Copyright (C) 2001  The R Development Core Team
5148 ripley 6
 *
7
 *  This program is free software; you can redistribute it and/or modify
8
 *  it under the terms of the GNU General Public License as published by
9
 *  the Free Software Foundation; either version 2 of the License, or
10
 *  (at your option) any later version.
11
 *
12
 *  This program is distributed in the hope that it will be useful,
13
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 *  GNU General Public License for more details.
16
 *
17
 *  You should have received a copy of the GNU General Public License
18
 *  along with this program; if not, write to the Free Software
5458 ripley 19
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
5148 ripley 20
 */
21
 
5187 hornik 22
#ifdef HAVE_CONFIG_H
7701 hornik 23
#include <config.h>
5187 hornik 24
#endif
25
 
10960 ripley 26
#include "Defn.h"
5148 ripley 27
#include "Graphics.h"
28
#include "Fileio.h"
12778 pd 29
#include <Rdevices.h>
5148 ripley 30
 
31
	/* device-specific information per picTeX device */
32
 
11067 maechler 33
#define DOTSperIN	72.27
34
#define in2dots(x) 	(DOTSperIN * x)
35
 
5148 ripley 36
typedef struct {
9004 ripley 37
    FILE *texfp;
38
    char filename[128];
39
    int pageno;
40
    int landscape;
41
    double width;
42
    double height;
43
    double pagewidth;
44
    double pageheight;
45
    double xlast;
46
    double ylast;
47
    double clipleft, clipright, cliptop, clipbottom;
48
    double clippedx0, clippedy0, clippedx1, clippedy1;
49
    int lty;
50
    rcolor col;
17112 murrell 51
    rcolor fill;
9004 ripley 52
    int fontsize;
53
    int fontface;
11067 maechler 54
    Rboolean debug;
5148 ripley 55
} picTeXDesc;
56
 
57
 
58
	/* Global device information */
59
 
19912 duncan 60
static const double charwidth[4][128] = {
5148 ripley 61
{
6844 maechler 62
  0.5416690, 0.8333360, 0.7777810, 0.6111145, 0.6666690, 0.7083380, 0.7222240,
63
  0.7777810, 0.7222240, 0.7777810, 0.7222240, 0.5833360, 0.5361130, 0.5361130,
64
  0.8138910, 0.8138910, 0.2388900, 0.2666680, 0.5000020, 0.5000020, 0.5000020,
65
  0.5000020, 0.5000020, 0.6666700, 0.4444460, 0.4805580, 0.7222240, 0.7777810,
66
  0.5000020, 0.8611145, 0.9722260, 0.7777810, 0.2388900, 0.3194460, 0.5000020,
67
  0.8333360, 0.5000020, 0.8333360, 0.7583360, 0.2777790, 0.3888900, 0.3888900,
68
  0.5000020, 0.7777810, 0.2777790, 0.3333340, 0.2777790, 0.5000020, 0.5000020,
69
  0.5000020, 0.5000020, 0.5000020, 0.5000020, 0.5000020, 0.5000020, 0.5000020,
70
  0.5000020, 0.5000020, 0.2777790, 0.2777790, 0.3194460, 0.7777810, 0.4722240,
71
  0.4722240, 0.6666690, 0.6666700, 0.6666700, 0.6388910, 0.7222260, 0.5972240,
72
  0.5694475, 0.6666690, 0.7083380, 0.2777810, 0.4722240, 0.6944480, 0.5416690,
73
  0.8750050, 0.7083380, 0.7361130, 0.6388910, 0.7361130, 0.6458360, 0.5555570,
74
  0.6805570, 0.6875050, 0.6666700, 0.9444480, 0.6666700, 0.6666700, 0.6111130,
75
  0.2888900, 0.5000020, 0.2888900, 0.5000020, 0.2777790, 0.2777790, 0.4805570,
76
  0.5166680, 0.4444460, 0.5166680, 0.4444460, 0.3055570, 0.5000020, 0.5166680,
77
  0.2388900, 0.2666680, 0.4888920, 0.2388900, 0.7944470, 0.5166680, 0.5000020,
78
  0.5166680, 0.5166680, 0.3416690, 0.3833340, 0.3611120, 0.5166680, 0.4611130,
79
  0.6833360, 0.4611130, 0.4611130, 0.4347230, 0.5000020, 1.0000030, 0.5000020,
5148 ripley 80
  0.5000020, 0.5000020
81
},
82
{
6844 maechler 83
  0.5805590, 0.9166720, 0.8555600, 0.6722260, 0.7333370, 0.7944490, 0.7944490,
84
  0.8555600, 0.7944490, 0.8555600, 0.7944490, 0.6416700, 0.5861150, 0.5861150,
85
  0.8916720, 0.8916720, 0.2555570, 0.2861130, 0.5500030, 0.5500030, 0.5500030,
86
  0.5500030, 0.5500030, 0.7333370, 0.4888920, 0.5652800, 0.7944490, 0.8555600,
87
  0.5500030, 0.9472275, 1.0694500, 0.8555600, 0.2555570, 0.3666690, 0.5583360,
88
  0.9166720, 0.5500030, 1.0291190, 0.8305610, 0.3055570, 0.4277800, 0.4277800,
89
  0.5500030, 0.8555600, 0.3055570, 0.3666690, 0.3055570, 0.5500030, 0.5500030,
90
  0.5500030, 0.5500030, 0.5500030, 0.5500030, 0.5500030, 0.5500030, 0.5500030,
91
  0.5500030, 0.5500030, 0.3055570, 0.3055570, 0.3666690, 0.8555600, 0.5194470,
92
  0.5194470, 0.7333370, 0.7333370, 0.7333370, 0.7027820, 0.7944490, 0.6416700,
93
  0.6111145, 0.7333370, 0.7944490, 0.3305570, 0.5194470, 0.7638930, 0.5805590,
94
  0.9777830, 0.7944490, 0.7944490, 0.7027820, 0.7944490, 0.7027820, 0.6111145,
95
  0.7333370, 0.7638930, 0.7333370, 1.0388950, 0.7333370, 0.7333370, 0.6722260,
96
  0.3430580, 0.5583360, 0.3430580, 0.5500030, 0.3055570, 0.3055570, 0.5250030,
97
  0.5611140, 0.4888920, 0.5611140, 0.5111140, 0.3361130, 0.5500030, 0.5611140,
98
  0.2555570, 0.2861130, 0.5305590, 0.2555570, 0.8666720, 0.5611140, 0.5500030,
99
  0.5611140, 0.5611140, 0.3722250, 0.4216690, 0.4041690, 0.5611140, 0.5000030,
100
  0.7444490, 0.5000030, 0.5000030, 0.4763920, 0.5500030, 1.1000060, 0.5500030,
101
  0.5500030, 0.550003 },
5148 ripley 102
{
6844 maechler 103
  0.5416690, 0.8333360, 0.7777810, 0.6111145, 0.6666690, 0.7083380, 0.7222240,
104
  0.7777810, 0.7222240, 0.7777810, 0.7222240, 0.5833360, 0.5361130, 0.5361130,
105
  0.8138910, 0.8138910, 0.2388900, 0.2666680, 0.5000020, 0.5000020, 0.5000020,
106
  0.5000020, 0.5000020, 0.7375210, 0.4444460, 0.4805580, 0.7222240, 0.7777810,
107
  0.5000020, 0.8611145, 0.9722260, 0.7777810, 0.2388900, 0.3194460, 0.5000020,
108
  0.8333360, 0.5000020, 0.8333360, 0.7583360, 0.2777790, 0.3888900, 0.3888900,
109
  0.5000020, 0.7777810, 0.2777790, 0.3333340, 0.2777790, 0.5000020, 0.5000020,
110
  0.5000020, 0.5000020, 0.5000020, 0.5000020, 0.5000020, 0.5000020, 0.5000020,
111
  0.5000020, 0.5000020, 0.2777790, 0.2777790, 0.3194460, 0.7777810, 0.4722240,
112
  0.4722240, 0.6666690, 0.6666700, 0.6666700, 0.6388910, 0.7222260, 0.5972240,
113
  0.5694475, 0.6666690, 0.7083380, 0.2777810, 0.4722240, 0.6944480, 0.5416690,
114
  0.8750050, 0.7083380, 0.7361130, 0.6388910, 0.7361130, 0.6458360, 0.5555570,
115
  0.6805570, 0.6875050, 0.6666700, 0.9444480, 0.6666700, 0.6666700, 0.6111130,
116
  0.2888900, 0.5000020, 0.2888900, 0.5000020, 0.2777790, 0.2777790, 0.4805570,
117
  0.5166680, 0.4444460, 0.5166680, 0.4444460, 0.3055570, 0.5000020, 0.5166680,
118
  0.2388900, 0.2666680, 0.4888920, 0.2388900, 0.7944470, 0.5166680, 0.5000020,
119
  0.5166680, 0.5166680, 0.3416690, 0.3833340, 0.3611120, 0.5166680, 0.4611130,
120
  0.6833360, 0.4611130, 0.4611130, 0.4347230, 0.5000020, 1.0000030, 0.5000020,
121
  0.5000020, 0.5000020 },
5148 ripley 122
{
6844 maechler 123
  0.5805590, 0.9166720, 0.8555600, 0.6722260, 0.7333370, 0.7944490, 0.7944490,
124
  0.8555600, 0.7944490, 0.8555600, 0.7944490, 0.6416700, 0.5861150, 0.5861150,
125
  0.8916720, 0.8916720, 0.2555570, 0.2861130, 0.5500030, 0.5500030, 0.5500030,
126
  0.5500030, 0.5500030, 0.8002530, 0.4888920, 0.5652800, 0.7944490, 0.8555600,
127
  0.5500030, 0.9472275, 1.0694500, 0.8555600, 0.2555570, 0.3666690, 0.5583360,
128
  0.9166720, 0.5500030, 1.0291190, 0.8305610, 0.3055570, 0.4277800, 0.4277800,
129
  0.5500030, 0.8555600, 0.3055570, 0.3666690, 0.3055570, 0.5500030, 0.5500030,
130
  0.5500030, 0.5500030, 0.5500030, 0.5500030, 0.5500030, 0.5500030, 0.5500030,
131
  0.5500030, 0.5500030, 0.3055570, 0.3055570, 0.3666690, 0.8555600, 0.5194470,
132
  0.5194470, 0.7333370, 0.7333370, 0.7333370, 0.7027820, 0.7944490, 0.6416700,
133
  0.6111145, 0.7333370, 0.7944490, 0.3305570, 0.5194470, 0.7638930, 0.5805590,
134
  0.9777830, 0.7944490, 0.7944490, 0.7027820, 0.7944490, 0.7027820, 0.6111145,
135
  0.7333370, 0.7638930, 0.7333370, 1.0388950, 0.7333370, 0.7333370, 0.6722260,
136
  0.3430580, 0.5583360, 0.3430580, 0.5500030, 0.3055570, 0.3055570, 0.5250030,
137
  0.5611140, 0.4888920, 0.5611140, 0.5111140, 0.3361130, 0.5500030, 0.5611140,
138
  0.2555570, 0.2861130, 0.5305590, 0.2555570, 0.8666720, 0.5611140, 0.5500030,
139
  0.5611140, 0.5611140, 0.3722250, 0.4216690, 0.4041690, 0.5611140, 0.5000030,
140
  0.7444490, 0.5000030, 0.5000030, 0.4763920, 0.5500030, 1.1000060, 0.5500030,
5148 ripley 141
  0.5500030, 0.550003
142
}
143
};
144
 
19912 duncan 145
static const char * const fontname[] = {
12976 pd 146
    "cmss10",
147
    "cmssbx10",
148
    "cmssi10",
149
    "cmssxi10"
5148 ripley 150
};
151
 
152
 
153
	/* Device driver actions */
154
 
17112 murrell 155
static void PicTeX_Activate(NewDevDesc *dd);
156
static void PicTeX_Circle(double x, double y, double r,
27236 murrell 157
			  R_GE_gcontext *gc,
158
			  NewDevDesc *dd);
17112 murrell 159
static void PicTeX_Clip(double x0, double x1, double y0, double y1, 
27236 murrell 160
			NewDevDesc *dd);
17112 murrell 161
static void PicTeX_Close(NewDevDesc *dd);
162
static void PicTeX_Deactivate(NewDevDesc *dd);
163
static void PicTeX_Hold(NewDevDesc *dd);
164
static Rboolean PicTeX_Locator(double *x, double *y, NewDevDesc *dd);
165
static void PicTeX_Line(double x1, double y1, double x2, double y2,
27236 murrell 166
			R_GE_gcontext *gc,
167
			NewDevDesc *dd);
168
static void PicTeX_MetricInfo(int c,
169
			      R_GE_gcontext *gc,
17112 murrell 170
			      double* ascent, double* descent,
171
			      double* width, NewDevDesc *dd);
172
static void PicTeX_Mode(int mode, NewDevDesc *dd);
27236 murrell 173
static void PicTeX_NewPage(R_GE_gcontext *gc, NewDevDesc *dd);
17112 murrell 174
static void PicTeX_Polygon(int n, double *x, double *y, 
27236 murrell 175
			   R_GE_gcontext *gc,
176
			   NewDevDesc *dd);
177
static void PicTeX_Rect(double x0, double y0, double x1, double y1,
178
			R_GE_gcontext *gc,
17112 murrell 179
			NewDevDesc *dd);
180
static void PicTeX_Size(double *left, double *right,
27236 murrell 181
			double *bottom, double *top,
182
			NewDevDesc *dd);
183
static double PicTeX_StrWidth(char *str, 
184
			      R_GE_gcontext *gc,
185
			      NewDevDesc *dd);
17112 murrell 186
static void PicTeX_Text(double x, double y, char *str, 
27236 murrell 187
			double rot, double hadj, 
188
			R_GE_gcontext *gc,
189
			NewDevDesc *dd);
17112 murrell 190
static Rboolean PicTeX_Open(NewDevDesc*, picTeXDesc*);
5148 ripley 191
 
192
	/* Support routines */
193
 
17112 murrell 194
static void SetLinetype(int newlty, int newlwd, NewDevDesc *dd)
5148 ripley 195
{
9004 ripley 196
    picTeXDesc *ptd = (picTeXDesc *) dd->deviceSpecific;
5148 ripley 197
 
9004 ripley 198
    int i, templty;
199
    ptd->lty = newlty;
200
    if (ptd->lty) {
201
	fprintf(ptd->texfp,"\\setdashpattern <");
202
	for(i=0 ; i<8 && newlty&15 ; i++) {
203
	    fprintf(ptd->texfp,"%dpt", newlwd * newlty&15);
204
	    templty = newlty>>4;
205
	    if ((i+1)<8 && templty&15) fprintf(ptd->texfp,", ");
206
	    newlty = newlty>>4;
207
	}
208
	fprintf(ptd->texfp,">\n");
209
    } else fprintf(ptd->texfp,"\\setsolid\n");
5148 ripley 210
}
211
 
212
 
213
static void SetFont(int face, int size, picTeXDesc *ptd)
214
{
9004 ripley 215
    int lface=face, lsize= size;
27236 murrell 216
    if(lface < 1 || lface > 4 ) lface = 1;
9004 ripley 217
    if(lsize < 1 || lsize > 24) lsize = 10;
218
    if(lsize != ptd->fontsize || lface != ptd->fontface) {
219
	fprintf(ptd->texfp, "\\font\\picfont %s at %dpt\\picfont\n",
220
		fontname[lface-1], lsize);
221
	ptd->fontsize = lsize;
222
	ptd->fontface = lface;
223
    }
5148 ripley 224
}
225
 
17112 murrell 226
static void PicTeX_Activate(NewDevDesc *dd)
5148 ripley 227
{
228
}
229
 
17112 murrell 230
static void PicTeX_Deactivate(NewDevDesc *dd)
5148 ripley 231
{
232
}
233
 
27236 murrell 234
static void PicTeX_MetricInfo(int c, 
235
			      R_GE_gcontext *gc,
17112 murrell 236
			      double* ascent, double* descent,
237
			      double* width, NewDevDesc *dd)
5148 ripley 238
{
6994 pd 239
    /* metric information not available => return 0,0,0 */
240
    *ascent = 0.0;
241
    *descent = 0.0;
242
    *width = 0.0;
5148 ripley 243
}
6994 pd 244
 
5148 ripley 245
	/* Initialize the device */
246
 
17112 murrell 247
static Rboolean PicTeX_Open(NewDevDesc *dd, picTeXDesc *ptd)
5148 ripley 248
{
249
    ptd->fontsize = 0;
250
    ptd->fontface = 0;
11067 maechler 251
    ptd->debug = FALSE;
5148 ripley 252
    if (!(ptd->texfp = R_fopen(R_ExpandFileName(ptd->filename), "w")))
11067 maechler 253
	return FALSE;
5148 ripley 254
    fprintf(ptd->texfp, "\\hbox{\\beginpicture\n");
255
    fprintf(ptd->texfp, "\\setcoordinatesystem units <1pt,1pt>\n");
256
    fprintf(ptd->texfp,
257
	    "\\setplotarea x from 0 to %.2f, y from 0 to %.2f\n",
11067 maechler 258
	    in2dots(ptd->width), in2dots(ptd->height));
5148 ripley 259
    fprintf(ptd->texfp,"\\setlinear\n");
260
    fprintf(ptd->texfp, "\\font\\picfont cmss10\\picfont\n");
261
    SetFont(1, 10, ptd);
11067 maechler 262
    ptd->pageno++;
263
    return TRUE;
5148 ripley 264
}
265
 
266
 
267
	/* Interactive Resize */
268
 
17112 murrell 269
static void PicTeX_Size(double *left, double *right,
270
		     double *bottom, double *top,
271
		     NewDevDesc *dd)
5148 ripley 272
{
17112 murrell 273
    *left = dd->left;		/* left */
274
    *right = dd->right;/* right */
275
    *bottom = dd->bottom;		/* bottom */
276
    *top = dd->top;/* top */
5148 ripley 277
}
278
 
279
static void PicTeX_Clip(double x0, double x1, double y0, double y1,
17112 murrell 280
			NewDevDesc *dd)
5148 ripley 281
{
9004 ripley 282
    picTeXDesc *ptd = (picTeXDesc *) dd->deviceSpecific;
5148 ripley 283
 
9004 ripley 284
    if(ptd->debug)
5148 ripley 285
	fprintf(ptd->texfp, "%% Setting Clip Region to %.2f %.2f %.2f %.2f\n",
286
		x0, y0, x1, y1);
9004 ripley 287
    ptd->clipleft = x0;
288
    ptd->clipright = x1;
289
    ptd->clipbottom = y0;
290
    ptd->cliptop = y1;
5148 ripley 291
}
292
 
293
	/* Start a new page */
294
 
27236 murrell 295
static void PicTeX_NewPage(R_GE_gcontext *gc,
296
			   NewDevDesc *dd)
5148 ripley 297
{
9004 ripley 298
    picTeXDesc *ptd = (picTeXDesc *) dd->deviceSpecific;
5148 ripley 299
 
9004 ripley 300
    int face, size;
301
    if (ptd->pageno) {
302
	fprintf(ptd->texfp, "\\endpicture\n}\n\n\n");
303
	fprintf(ptd->texfp, "\\hbox{\\beginpicture\n");
304
	fprintf(ptd->texfp, "\\setcoordinatesystem units <1pt,1pt>\n");
305
	fprintf(ptd->texfp,
306
		"\\setplotarea x from 0 to %.2f, y from 0 to %.2f\n",
11067 maechler 307
		in2dots(ptd->width), in2dots(ptd->height));
9004 ripley 308
	fprintf(ptd->texfp,"\\setlinear\n");
309
	fprintf(ptd->texfp, "\\font\\picfont cmss10\\picfont\n");
310
    }
11067 maechler 311
    ptd->pageno++;
9004 ripley 312
    face = ptd->fontface;
313
    size = ptd->fontsize;
314
    ptd->fontface = 0;
315
    ptd->fontsize = 0;
316
    SetFont(face, size, ptd);
5148 ripley 317
}
318
 
319
	/* Close down the driver */
320
 
17112 murrell 321
static void PicTeX_Close(NewDevDesc *dd)
5148 ripley 322
{
12976 pd 323
    picTeXDesc *ptd = (picTeXDesc *) dd->deviceSpecific;
5148 ripley 324
 
12976 pd 325
    fprintf(ptd->texfp, "\\endpicture\n}\n");
326
    fclose(ptd->texfp);
5148 ripley 327
 
12976 pd 328
    free(ptd);
5148 ripley 329
}
330
 
331
	/* Draw To */
332
 
333
static void PicTeX_ClipLine(double x0, double y0, double x1, double y1,
334
			    picTeXDesc *ptd)
335
{
9004 ripley 336
    ptd->clippedx0 = x0; ptd->clippedx1 = x1;
337
    ptd->clippedy0 = y0; ptd->clippedy1 = y1;
5148 ripley 338
 
9004 ripley 339
    if ((ptd->clippedx0 < ptd->clipleft &&
340
	 ptd->clippedx1 < ptd->clipleft) ||
341
	(ptd->clippedx0 > ptd->clipright &&
342
	 ptd->clippedx1 > ptd->clipright) ||
343
	(ptd->clippedy0 < ptd->clipbottom &&
344
	 ptd->clippedy1 < ptd->clipbottom) ||
345
	(ptd->clippedy0 > ptd->cliptop &&
346
	 ptd->clippedy1 > ptd->cliptop)) {
347
	ptd->clippedx0 = ptd->clippedx1;
348
	ptd->clippedy0 = ptd->clippedy1;
349
	return;
350
    }
5148 ripley 351
 
9004 ripley 352
    /*Clipping Left */
353
    if (ptd->clippedx1 >= ptd->clipleft && ptd->clippedx0 < ptd->clipleft) {
354
	ptd->clippedy0 = ((ptd->clippedy1-ptd->clippedy0) /
355
			  (ptd->clippedx1-ptd->clippedx0) *
356
			  (ptd->clipleft-ptd->clippedx0)) +
357
	    ptd->clippedy0;
358
	ptd->clippedx0 = ptd->clipleft;
359
    }
360
    if (ptd->clippedx1 <= ptd->clipleft && ptd->clippedx0 > ptd->clipleft) {
361
	ptd->clippedy1 = ((ptd->clippedy1-ptd->clippedy0) /
362
			  (ptd->clippedx1-ptd->clippedx0) *
363
			  (ptd->clipleft-ptd->clippedx0)) +
364
	    ptd->clippedy0;
365
	ptd->clippedx1 = ptd->clipleft;
366
    }
367
    /* Clipping Right */
368
    if (ptd->clippedx1 >= ptd->clipright &&
369
	ptd->clippedx0 < ptd->clipright) {
370
	ptd->clippedy1 = ((ptd->clippedy1-ptd->clippedy0) /
371
			  (ptd->clippedx1-ptd->clippedx0) *
372
			  (ptd->clipright-ptd->clippedx0)) +
373
	    ptd->clippedy0;
374
	ptd->clippedx1 = ptd->clipright;
375
    }
376
    if (ptd->clippedx1 <= ptd->clipright &&
377
	ptd->clippedx0 > ptd->clipright) {
378
	ptd->clippedy0 = ((ptd->clippedy1-ptd->clippedy0) /
379
			  (ptd->clippedx1-ptd->clippedx0) *
380
			  (ptd->clipright-ptd->clippedx0)) +
381
	    ptd->clippedy0;
382
	ptd->clippedx0 = ptd->clipright;
383
    }
384
    /*Clipping Bottom */
385
    if (ptd->clippedy1 >= ptd->clipbottom  &&
386
	ptd->clippedy0 < ptd->clipbottom ) {
387
	ptd->clippedx0 = ((ptd->clippedx1-ptd->clippedx0) /
388
			  (ptd->clippedy1-ptd->clippedy0) *
389
			  (ptd->clipbottom -ptd->clippedy0)) +
390
	    ptd->clippedx0;
391
	ptd->clippedy0 = ptd->clipbottom ;
392
    }
393
    if (ptd->clippedy1 <= ptd->clipbottom &&
394
	ptd->clippedy0 > ptd->clipbottom ) {
395
	ptd->clippedx1 = ((ptd->clippedx1-ptd->clippedx0) /
396
			  (ptd->clippedy1-ptd->clippedy0) *
397
			  (ptd->clipbottom -ptd->clippedy0)) +
398
	    ptd->clippedx0;
399
	ptd->clippedy1 = ptd->clipbottom ;
400
    }
401
    /*Clipping Top */
402
    if (ptd->clippedy1 >= ptd->cliptop  && ptd->clippedy0 < ptd->cliptop ) {
403
	ptd->clippedx1 = ((ptd->clippedx1-ptd->clippedx0) /
404
			  (ptd->clippedy1-ptd->clippedy0) *
405
			  (ptd->cliptop -ptd->clippedy0)) +
406
	    ptd->clippedx0;
407
	ptd->clippedy1 = ptd->cliptop ;
408
    }
409
    if (ptd->clippedy1 <= ptd->cliptop && ptd->clippedy0 > ptd->cliptop ) {
410
	ptd->clippedx0 = ((ptd->clippedx1-ptd->clippedx0) /
411
			  (ptd->clippedy1-ptd->clippedy0) *
412
			  (ptd->cliptop -ptd->clippedy0)) +
413
	    ptd->clippedx0;
414
	ptd->clippedy0 = ptd->cliptop ;
415
    }
5148 ripley 416
}
417
 
418
static void PicTeX_Line(double x1, double y1, double x2, double y2,
27236 murrell 419
			R_GE_gcontext *gc,
420
			NewDevDesc *dd)
5148 ripley 421
{
12976 pd 422
    picTeXDesc *ptd = (picTeXDesc *) dd->deviceSpecific;
5148 ripley 423
 
12976 pd 424
    if (x1 != x2 || y1 != y2) {
27236 murrell 425
	SetLinetype(gc->lty, gc->lwd, dd);
5148 ripley 426
	if(ptd->debug)
12976 pd 427
	    fprintf(ptd->texfp,
428
		    "%% Drawing line from %.2f, %.2f to %.2f, %.2f\n",
429
		    x1, y1, x2, y2);
5148 ripley 430
	PicTeX_ClipLine(x1, y1, x2, y2, ptd);
431
	if (ptd->debug)
12976 pd 432
	    fprintf(ptd->texfp,
433
		    "%% Drawing clipped line from %.2f, %.2f to %.2f, %.2f\n",
434
		    ptd->clippedx0, ptd->clippedy0,
435
		    ptd->clippedx1, ptd->clippedy1);
5148 ripley 436
	fprintf(ptd->texfp, "\\plot %.2f %.2f %.2f %.2f /\n",
437
		ptd->clippedx0, ptd->clippedy0,
438
		ptd->clippedx1, ptd->clippedy1);
12976 pd 439
    }
5148 ripley 440
}
441
 
17112 murrell 442
static void PicTeX_Polyline(int n, double *x, double *y, 
27236 murrell 443
			    R_GE_gcontext *gc,
17112 murrell 444
			    NewDevDesc *dd)
5148 ripley 445
{
9004 ripley 446
    double x1, y1, x2, y2;
447
    int i;
448
    picTeXDesc *ptd = (picTeXDesc *) dd->deviceSpecific;
5148 ripley 449
 
27236 murrell 450
    SetLinetype(gc->lty, gc->lwd, dd);
9004 ripley 451
    x1 = x[0];
452
    y1 = y[0];
12976 pd 453
    for (i = 1; i < n; i++) {
9004 ripley 454
	x2 = x[i];
455
	y2 = y[i];
456
	PicTeX_ClipLine(x1, y1, x2, y2, ptd);
457
	fprintf(ptd->texfp, "\\plot %.2f %.2f %.2f %.2f /\n",
458
		ptd->clippedx0, ptd->clippedy0,
459
		ptd->clippedx1, ptd->clippedy1);
12976 pd 460
	x1 = x2;
461
	y1 = y2;
9004 ripley 462
    }
5148 ripley 463
}
464
 
465
	/* String Width in Rasters */
466
	/* For the current font in pointsize fontsize */
467
 
27236 murrell 468
static double PicTeX_StrWidth(char *str, 
469
			      R_GE_gcontext *gc,
470
			      NewDevDesc *dd)
5148 ripley 471
{
9004 ripley 472
    picTeXDesc *ptd = (picTeXDesc *) dd->deviceSpecific;
5148 ripley 473
 
9004 ripley 474
    char *p;
475
    int size;
476
    double sum;
27236 murrell 477
    size = gc->cex * gc->ps + 0.5;
478
    SetFont(gc->fontface, size, ptd);
9004 ripley 479
    sum = 0;
480
    for(p=str ; *p ; p++)
481
	sum += charwidth[ptd->fontface-1][(int)*p];
482
    return sum * ptd->fontsize;
5148 ripley 483
}
484
 
485
 
486
/* Possibly Filled Rectangle */
487
static void PicTeX_Rect(double x0, double y0, double x1, double y1,
27236 murrell 488
			R_GE_gcontext *gc,
489
			NewDevDesc *dd)
5148 ripley 490
{
9004 ripley 491
    double x[4], y[4];
12976 pd 492
 
9004 ripley 493
    x[0] = x0; y[0] = y0;
494
    x[1] = x0; y[1] = y1;
495
    x[2] = x1; y[2] = y1;
496
    x[3] = x1; y[3] = y0;
27236 murrell 497
    PicTeX_Polygon(4, x, y, gc, dd);
5148 ripley 498
}
499
 
17112 murrell 500
static void PicTeX_Circle(double x, double y, double r,
27236 murrell 501
			  R_GE_gcontext *gc,
502
			  NewDevDesc *dd)
5148 ripley 503
{
9004 ripley 504
    picTeXDesc *ptd = (picTeXDesc *) dd->deviceSpecific;
5148 ripley 505
 
9004 ripley 506
    fprintf(ptd->texfp,
507
	    "\\circulararc 360 degrees from %.2f %.2f center at %.2f %.2f\n",
508
	    x, (y + r), x, y);
5148 ripley 509
}
510
 
17112 murrell 511
static void PicTeX_Polygon(int n, double *x, double *y, 
27236 murrell 512
			   R_GE_gcontext *gc,
513
			   NewDevDesc *dd)
5148 ripley 514
{
9004 ripley 515
    double x1, y1, x2, y2;
516
    int i;
517
    picTeXDesc *ptd = (picTeXDesc *) dd->deviceSpecific;
5148 ripley 518
 
27236 murrell 519
    SetLinetype(gc->lty, gc->lwd, dd);
9004 ripley 520
    x1 = x[0];
521
    y1 = y[0];
522
    for (i=1; i<n; i++) {
523
	x2 = x[i];
524
	y2 = y[i];
5148 ripley 525
	PicTeX_ClipLine(x1, y1, x2, y2, ptd);
526
	fprintf(ptd->texfp, "\\plot %.2f %.2f %.2f %.2f /\n",
527
		ptd->clippedx0, ptd->clippedy0,
528
		ptd->clippedx1, ptd->clippedy1);
9004 ripley 529
	x1 = x2;
530
	y1 = y2;
531
    }
532
    x2 = x[0];
533
    y2 = y[0];
534
    PicTeX_ClipLine(x1, y1, x2, y2, ptd);
535
    fprintf(ptd->texfp, "\\plot %.2f %.2f %.2f %.2f /\n",
536
	    ptd->clippedx0, ptd->clippedy0,
537
	    ptd->clippedx1, ptd->clippedy1);
5148 ripley 538
}
539
 
540
/* TeX Text Translations */
541
static void textext(char *str, picTeXDesc *ptd)
542
{
9004 ripley 543
    fputc('{', ptd->texfp);
544
    for( ; *str ; str++)
545
	switch(*str) {
546
	case '$':
547
	    fprintf(ptd->texfp, "\\$");
548
	    break;
5148 ripley 549
 
9004 ripley 550
	case '%':
551
	    fprintf(ptd->texfp, "\\%%");
552
	    break;
5148 ripley 553
 
9004 ripley 554
	case '{':
555
	    fprintf(ptd->texfp, "\\{");
556
	    break;
5148 ripley 557
 
9004 ripley 558
	case '}':
559
	    fprintf(ptd->texfp, "\\}");
560
	    break;
5148 ripley 561
 
9004 ripley 562
	case '^':
563
	    fprintf(ptd->texfp, "\\^{}");
564
	    break;
5148 ripley 565
 
9004 ripley 566
	default:
567
	    fputc(*str, ptd->texfp);
568
	    break;
569
	}
570
    fprintf(ptd->texfp,"} ");
5148 ripley 571
}
572
 
573
/* Rotated Text */
574
 
17112 murrell 575
static void PicTeX_Text(double x, double y, char *str, 
27236 murrell 576
			double rot, double hadj, 
577
			R_GE_gcontext *gc,
578
			NewDevDesc *dd)
5148 ripley 579
{
9004 ripley 580
    int size;
581
    double xoff = 0.0, yoff = 0.0;
582
    picTeXDesc *ptd = (picTeXDesc *) dd->deviceSpecific;
5148 ripley 583
 
27236 murrell 584
    size = gc->cex * gc->ps + 0.5;
585
    SetFont(gc->fontface, size, ptd);
11067 maechler 586
    if(ptd->debug) 
587
	fprintf(ptd->texfp,
588
		"%% Writing string of length %.2f, at %.2f %.2f, xc = %.2f yc = %.2f\n",
27236 murrell 589
		(double)PicTeX_StrWidth(str, gc, dd), 
17112 murrell 590
		x, y, 0.0, 0.0);
9004 ripley 591
    fprintf(ptd->texfp,"\\put ");
592
    textext(str, ptd);
593
    if (rot == 90 )
12976 pd 594
	fprintf(ptd->texfp," [rB] <%.2fpt,%.2fpt>", xoff, yoff);
9004 ripley 595
    else fprintf(ptd->texfp," [lB] <%.2fpt,%.2fpt>", xoff, yoff);
596
    fprintf(ptd->texfp," at %.2f %.2f\n", x, y);
5148 ripley 597
}
598
 
599
/* Pick */
17112 murrell 600
static Rboolean PicTeX_Locator(double *x, double *y, NewDevDesc *dd)
5148 ripley 601
{
11067 maechler 602
    return FALSE;
5148 ripley 603
}
604
 
605
 
17112 murrell 606
static void PicTeX_Mode(int mode, NewDevDesc* dd)
5148 ripley 607
{
608
}
609
 
17112 murrell 610
static void PicTeX_Hold(NewDevDesc *dd)
5148 ripley 611
{
612
}
613
 
17112 murrell 614
Rboolean internalPicTeXDeviceDriver(NewDevDesc *dd, char *filename, 
615
				    char *bg, char *fg,
616
				    double width, double height, 
617
				    Rboolean debug)
5148 ripley 618
{
9004 ripley 619
    picTeXDesc *ptd;
5148 ripley 620
 
9004 ripley 621
    if (!(ptd = (picTeXDesc *) malloc(sizeof(picTeXDesc))))
11067 maechler 622
	return FALSE;
5148 ripley 623
 
9004 ripley 624
    strcpy(ptd->filename, filename);
5148 ripley 625
 
17112 murrell 626
    dd->startfill = str2col(bg);
627
    dd->startcol = str2col(fg);
17165 murrell 628
    dd->startps = 10;
629
    dd->startlty = 0;
630
    dd->startfont = 1;
631
    dd->startgamma = 1;
632
 
17112 murrell 633
    dd->newDevStruct = 1;
634
 
635
    dd->activate = PicTeX_Activate;
636
    dd->deactivate = PicTeX_Deactivate;
637
    dd->open = PicTeX_Open;
638
    dd->close = PicTeX_Close;
639
    dd->clip = PicTeX_Clip;
640
    dd->size = PicTeX_Size;
641
    dd->newPage = PicTeX_NewPage;
642
    dd->line = PicTeX_Line;
643
    dd->text = PicTeX_Text;
644
    dd->strWidth = PicTeX_StrWidth;
645
    dd->rect = PicTeX_Rect;
646
    dd->circle = PicTeX_Circle;
647
    dd->polygon = PicTeX_Polygon;
648
    dd->polyline = PicTeX_Polyline;
649
    dd->locator = PicTeX_Locator;
650
    dd->mode = PicTeX_Mode;
651
    dd->hold = PicTeX_Hold;
652
    dd->metricInfo = PicTeX_MetricInfo;
5148 ripley 653
 
9004 ripley 654
    /* Screen Dimensions in Pixels */
6251 pd 655
 
17112 murrell 656
    dd->left = 0;		/* left */
657
    dd->right = in2dots(width);/* right */
658
    dd->bottom = 0;		/* bottom */
659
    dd->top = in2dots(height);/* top */
9004 ripley 660
    ptd->width = width;
661
    ptd->height = height;
5148 ripley 662
 
11067 maechler 663
    if( ! PicTeX_Open(dd, ptd) ) 
664
	return FALSE;
5148 ripley 665
 
9004 ripley 666
    /* Base Pointsize */
667
    /* Nominal Character Sizes in Pixels */
5148 ripley 668
 
17112 murrell 669
    dd->cra[0] =	 (6.0/12.0) * 10.0;
670
    dd->cra[1] =	(10.0/12.0) * 10.0;
5148 ripley 671
 
9004 ripley 672
    /* Character Addressing Offsets */
673
    /* These offsets should center a single */
674
    /* plotting character over the plotting point. */
675
    /* Pure guesswork and eyeballing ... */
5148 ripley 676
 
17112 murrell 677
    dd->xCharOffset =  0; /*0.4900;*/
678
    dd->yCharOffset =  0; /*0.3333;*/
679
    dd->yLineBias = 0; /*0.1;*/
5148 ripley 680
 
9004 ripley 681
    /* Inches per Raster Unit */
11067 maechler 682
    /* We use printer points, i.e. 72.27 dots per inch : */
17112 murrell 683
    dd->ipr[0] = dd->ipr[1] = 1./DOTSperIN;
5148 ripley 684
 
17112 murrell 685
    dd->canResizePlot = FALSE;
686
    dd->canChangeFont = TRUE;
687
    dd->canRotateText = FALSE;
688
    dd->canResizeText = TRUE;
689
    dd->canClip = TRUE;
690
    dd->canHAdj = 0;
17165 murrell 691
    dd->canChangeGamma = FALSE;
5148 ripley 692
 
9004 ripley 693
    ptd->lty = 1;
694
    ptd->pageno = 0;
695
    ptd->debug = debug;
5148 ripley 696
 
9004 ripley 697
    dd->deviceSpecific = (void *) ptd;
11067 maechler 698
    dd->displayListOn = FALSE;
699
    return TRUE;
5148 ripley 700
}
17112 murrell 701
 
702
Rboolean PicTeXDeviceDriver(DevDesc *dd, char *filename, char *bg, char *fg,
703
			    double width, double height, Rboolean debug)
704
{
705
    return internalPicTeXDeviceDriver((NewDevDesc*) dd, filename, bg, fg,
706
				      width, height, debug);
707
}
708