PLplot 5.15.0
pstex.c
Go to the documentation of this file.
1// PLplot pstex (Postscript/LaTeX) device driver.
2//
3
4#include "plDevs.h"
5
6#ifdef PLD_pstex
7
8#include "plplotP.h"
9#include "drivers.h"
10#include "ps.h"
11
12// Device info
13PLDLLIMPEXP_DRIVER const char* plD_DEVICE_INFO_pstex =
14 "pstex:Combined Postscript/LaTeX files:0:pstex:41:pstex\n";
15
16//--------------------------------------------------------------------------
17// plD_init_pstex()
18//
19// Initialize device.
20//--------------------------------------------------------------------------
21
22
23static void parse_str( const char *str, char *dest );
24static void proc_str( PLStream *pls, EscText *args );
25static int color = 1;
26
27static DrvOpt pstex_options[] = { { "color", DRV_INT, &color,
28 "Color Postscript/LaTeX (color=1|0)" },
29 { NULL, DRV_INT, NULL, NULL} };
30
32{
33#ifndef ENABLE_DYNDRIVERS
34 pdt->pl_MenuStr = "Combined Postscript/LaTeX files";
35 pdt->pl_DevName = "pstex";
36#endif
38 pdt->pl_seq = 41;
47}
48
49void
51{
52 char *ofile;
53 size_t len;
54 PSDev *dev;
55 FILE *fp;
56
57 plParseDrvOpts( pstex_options );
58 if ( color )
59 plD_init_psc( pls ); // init color postscript driver
60 else
61 plD_init_ps( pls ); // init monochrome postscript driver
62
63 dev = (PSDev *) pls->dev;
64
65 pls->dev_text = 1; // want to draw text
66 pls->dev_unicode = 0; // don't want unicode
67
68 // open latex output file
69 len = strlen( pls->FileName ) + 3;
70 ofile = (char *) malloc( sizeof ( char ) * len );
71 snprintf( ofile, len, "%s_t", pls->FileName );
72 fp = fopen( ofile, "w" );
73 free( ofile );
74 dev->fp = fp;
75
76 fprintf( fp, "\\begin{picture}(0,0)(0,0)%%\n" );
77 fprintf( fp, "\\includegraphics[scale=1.,clip]{%s}%%\n", pls->FileName );
78 fprintf( fp, "\\end{picture}%%\n" );
79// fprintf(fp,"\\setlength{\\unitlength}{%fbp}%%\n", 72./25.4/pls->xpmm);
80 fprintf( fp, "\\setlength{\\unitlength}{%fbp}%%\n", 1.0 / ENLARGE );
81 fprintf( fp, "\\begingroup\\makeatletter\\ifx\\SetFigFont\\undefined%%\n" );
82 fprintf( fp, "\\gdef\\SetFigFont#1#2#3#4#5{%%\n" );
83 fprintf( fp, "\\reset@font\\fontsize{#1}{#2pt}%%\n" );
84 fprintf( fp, "\\fontfamily{#3}\\fontseries{#4}\\fontshape{#5}%%\n" );
85 fprintf( fp, "\\selectfont}%%\n" );
86 fprintf( fp, "\\fi\\endgroup%%\n" );
87
88 dev->cur_pos = ftell( fp );
89 fprintf( fp, "\\begin{picture}(xxxxxx,xxxxxx)(xxxxxx,xxxxxx)%%\n" );
90}
91
92void
93plD_esc_pstex( PLStream *pls, PLINT op, void *ptr )
94{
95 switch ( op )
96 {
97 case PLESC_HAS_TEXT:
98 proc_str( pls, ptr );
99 break;
100 default:
101 plD_esc_ps( pls, op, ptr );
102 }
103}
104
105void
107{
108 plD_bop_ps( pls );
109 plGetFam( pls );
110}
111
112void
114{
115 PSDev *dev = (PSDev *) pls->dev;
116 PLFLT scale;
117 FILE *fp;
118
119 plD_tidy_ps( pls );
120
121 scale = pls->xpmm * 25.4 / 72.;
122
123 fp = dev->fp;
124 fprintf( fp, "\\end{picture}\n" );
125
126 fseek( fp, dev->cur_pos, SEEK_SET );
127 fprintf( fp, "\\begin{picture}(%d,%d)(%d,%d)%%\n%%",
128 ROUND( ( dev->urx - dev->llx ) * scale ),
129 ROUND( ( dev->ury - dev->lly ) * scale ),
130 ROUND( ( dev->llx - XOFFSET ) * scale ),
131 ROUND( ( dev->lly - YOFFSET ) * scale ) );
132
133 plCloseFile( pls );
134}
135
136void
137proc_str( PLStream *pls, EscText *args )
138{
139 PLFLT *t = args->xform;
140 PLFLT a1, alpha, ft_ht, angle;
141 char cptr[256], jst, ref;
142 PSDev *dev = (PSDev *) pls->dev;
143 PLINT clxmin, clxmax, clymin, clymax;
144 FILE *fp;
145
146 fp = dev->fp;
147
148 // font height
149 ft_ht = 1.6 * pls->chrht * 72.0 / 25.4; /* ft_ht in points. ht is in mm */
150
151 // calculate baseline text angle
152 angle = ( (PLFLT) ( ORIENTATION - 1 ) + pls->diorot ) * 90.;
153 a1 = acos( t[0] ) * 180. / PI;
154 if ( t[2] > 0. )
155 alpha = a1 - angle - 90.;
156 else
157 alpha = 360. - a1 - angle - 90.;
158
159 // parse string for format (escape) characters
160 parse_str( args->string, cptr );
161
162 //
163 // Reference point (center baseline of string, not latex character reference point).
164 // If base = 0, it is aligned with the center of the text box
165 // If base = 1, it is aligned with the baseline of the text box
166 // If base = 2, it is aligned with the top of the text box
167 // Currently plplot only uses base=0
168 //
169
170 if ( args->base == 2 ) // not supported by plplot
171 ref = 't';
172 else if ( args->base == 1 )
173 ref = 'b';
174 else
175 ref = 'c';
176
177 //
178 // Text justification. Left, center and right justification, which
179 // are the more common options, are supported; variable justification is
180 // only approximate, based on plplot computation of it's string lenght
181 //
182
183 if ( args->just == 0.5 )
184 jst = 'c';
185 else if ( args->just == 1. )
186 jst = 'r';
187 else
188 {
189 jst = 'l';
190 args->x = args->refx; // use hints provided by plplot
191 args->y = args->refy;
192 }
193
194 // apply transformations
195 difilt( &args->x, &args->y, 1, &clxmin, &clxmax, &clymin, &clymax );
196
197 // check clip limits. For now, only the reference point of the string is checked;
198 // but the the whole string should be checked -- using a postscript construct
199 // such as gsave/clip/grestore. This method can also be applied to the xfig and
200 // pstex drivers. Zoom side effect: the font size must be adjusted!
201
202 if ( args->x < clxmin || args->x > clxmax || args->y < clymin || args->y > clymax )
203 return;
204
205 plRotPhy( ORIENTATION, dev->xmin, dev->ymin, dev->xmax, dev->ymax,
206 &( args->x ), &( args->y ) );
207
208#ifdef DEBUG
209 fprintf( fp, "\\put(%d,%d){\\circle{10}}\n",
210 args->x, args->y );
211#endif
212
213 fprintf( fp, "\\put(%d,%d){\\rotatebox{%.1f}{\\makebox(0,0)[%c%c]{\\SetFigFont{%.1f}{12}",
214 args->x, args->y, alpha, jst, ref, ft_ht );
215
216 //
217 // font family, serie and shape. Currently not supported by plplot
218 //
219 // Use current font instead:
220 // 1: Normal font (latex document default font)
221 // 2: Roman font
222 // 3: Italic font (most probably latex slanted)
223 // 4: Script font (latex sans serif)
224 //
225
226 switch ( pls->cfont )
227 {
228 case ( 1 ): fprintf( fp, "{\\familydefault}" ); break;
229 case ( 2 ): fprintf( fp, "{\\rmdefault}" ); break;
230 case ( 3 ): fprintf( fp, "{\\itdefault}" ); break;
231 case ( 4 ): fprintf( fp, "{\\sfdefault}" ); break;
232 default: fprintf( fp, "{\\familydefault}" );
233 }
234
235 fprintf( fp, "{\\mddefault}{\\updefault}\n" );
236
237 // font color.
238
239 if ( color )
240 fprintf( fp, "\\special{ps: %.3f %.3f %.3f setrgbcolor}{",
241 pls->curcolor.r / 255., pls->curcolor.g / 255., pls->curcolor.b / 255. );
242 else
243 fprintf( fp, "\\special{ps: 0 0 0 setrgbcolor}{" );
244
245 fprintf( fp, "%% Your text follows:\n" );
246 fprintf( fp, "%s\n", cptr );
247 fprintf( fp, "}}}}" );
248
249 //
250 // keep ps driver happy -- needed for background and orientation.
251 // arghhh! can't calculate it, as I only have the string reference
252 // point, not its extent!
253 // Quick (and final?) *hack*, ASSUME that no more than a char height
254 // extents after/before the string reference point.
255 //
256
257 dev->llx = MIN( dev->llx, args->x - ft_ht * 25.4 / 72. * pls->xpmm );
258 dev->lly = MIN( dev->lly, args->y - ft_ht * 25.4 / 72. * pls->ypmm );
259 dev->urx = MAX( dev->urx, args->x + ft_ht * 25.4 / 72. * pls->xpmm );
260 dev->ury = MAX( dev->ury, args->y + ft_ht * 25.4 / 72. * pls->ypmm );
261}
262
263void
264parse_str( const char *str, char *dest )
265{
266 int n, opened = 0, raised = 0, overline = 0, underline = 0, fontset = 0, math = 0;
267 char *tp = dest, c, esc;
268 char greek[] = "abgGdDezyhHiklLmncCopPrsStuUfFxqQwW";
269 char *mathgreek[] = { "alpha", "beta", "gamma", "Gamma", "delta", "Delta",
270 "epsilon", "zeta", "eta", "theta", "Theta", "iota",
271 "kappa", "lambda", "Lambda", "mu", "nu", "xi", "Xi",
272 "o", "pi", "Pi", "rho", "sigma", "Sigma","tau",
273 "upsilon", "Upsilon", "phi", "Phi", "chi",
274 "psi", "Psi", "omega", "Omega" };
275
276 plgesc( &esc );
277
278 while ( *str )
279 {
280 if ( *str != esc )
281 {
282 *tp++ = *str++;
283 continue;
284 }
285 str++;
286
287 switch ( *str++ )
288 {
289 case 'u': // up one level
290 if ( raised < 0 )
291 {
292 *tp++ = '}';
293 opened--;
294 }
295 else
296 {
297 n = sprintf( tp, "\\raisebox{%.2fex}{", 0.6 );
298 tp += n; opened++;
299 }
300 raised++;
301 break;
302
303 case 'd': // down one level
304 if ( raised > 0 )
305 {
306 *tp++ = '}';
307 opened--;
308 }
309 else
310 {
311 n = sprintf( tp, "\\raisebox{%.2fex}{", -0.6 );
312 tp += n; opened++;
313 }
314 raised--;
315 break;
316
317 case 'b': // backspace
318 n = sprintf( tp, "\\hspace{-1em}" );
319 tp += n;
320 break;
321
322 case '+': // toggles overline mode. Side effect, enter math mode.
323 if ( overline )
324 {
325 if ( --math )
326 *tp++ = '}';
327 else
328 {
329 n = sprintf( tp, "}$" );
330 tp += n;
331 }
332 overline--; opened--;
333 }
334 else
335 {
336 if ( !math )
337 *tp++ = '$';
338
339 n = sprintf( tp, "\\overline{" );
340 tp += n; overline++; opened++; math++;
341 }
342 break;
343
344 case '-': // toggles underline mode. Side effect, enter math mode.
345 if ( underline )
346 {
347 if ( --math )
348 *tp++ = '}';
349 else
350 {
351 n = sprintf( tp, "}$" );
352 tp += n;
353 }
354 underline--; opened--;
355 }
356 else
357 {
358 if ( !math )
359 *tp++ = '$';
360
361 n = sprintf( tp, "\\underline{" );
362 tp += n; underline++; opened++; math++;
363 }
364 break;
365
366 case 'g': // greek letter corresponding to roman letter x
367 c = *str++;
368 n = plP_strpos( greek, c );
369 if ( n != -1 )
370 {
371 if ( !math )
372 *tp++ = '$';
373
374 *tp++ = '\\';
375 strcpy( tp, mathgreek[n] );
376 if ( isupper( c ) )
377 *tp = toupper( *tp );
378 tp += strlen( mathgreek[n] );
379 if ( !math )
380 *tp++ = '$';
381 }
382 else
383 *tp++ = c;
384
385 break;
386
387 case '(': // Hershey symbol number (nnn) (any number of digits) FIXME ???
388 plwarn( "'g(...)' text escape sequence not processed." );
389 while ( *str++ != ')' )
390 ;
391 break;
392
393 case 'f': // switch font
394
395 switch ( *str++ )
396 {
397 case 'n': // Normal
398 while ( fontset-- )
399 {
400 *tp++ = '}';
401 opened--;
402 }
403
404 if ( math )
405 {
406 *tp++ = '$';
407 math = 0;
408 }
409
410 n = sprintf( tp, "\\normalfont " );
411 tp += n;
412 break;
413
414 case 'r': // Roman
415 if ( math )
416 n = sprintf( tp, "\\mathrm{" );
417 else
418 n = sprintf( tp, "\\textrm{" );
419
420 tp += n; opened++; fontset++;
421 break;
422
423 case 'i': // Italic
424 if ( math )
425 n = sprintf( tp, "\\mathit{" );
426 else
427 n = sprintf( tp, "\\textit{" );
428
429 tp += n; opened++; fontset++;
430 break;
431
432 case 's': // Script. Don't, use sans serif
433 if ( math )
434 n = sprintf( tp, "\\mathsf{" );
435 else
436 n = sprintf( tp, "\\textsf{" );
437
438 tp += n; opened++; fontset++;
439 break;
440 }
441
442 default:
443 if ( *str == esc )
444 *tp++ = esc;
445 }
446 }
447
448 while ( opened-- )
449 *tp++ = '}';
450 *tp = '\0';
451}
452
453#else
454int
456{
457 return 0;
458}
459
460#endif // PLD_pstexdev
static void proc_str(PLStream *, EscText *)
Definition: aqt.c:529
void(* plD_line_fp)(struct PLStream_struct *, short, short, short, short)
Definition: disptab.h:68
void(* plD_tidy_fp)(struct PLStream_struct *)
Definition: disptab.h:72
void(* plD_bop_fp)(struct PLStream_struct *)
Definition: disptab.h:71
void(* plD_state_fp)(struct PLStream_struct *, PLINT)
Definition: disptab.h:73
void(* plD_eop_fp)(struct PLStream_struct *)
Definition: disptab.h:70
@ plDevType_FileOriented
Definition: disptab.h:13
void(* plD_init_fp)(struct PLStream_struct *)
Definition: disptab.h:67
void(* plD_esc_fp)(struct PLStream_struct *, PLINT, void *)
Definition: disptab.h:74
void(* plD_polyline_fp)(struct PLStream_struct *, short *, short *, PLINT)
Definition: disptab.h:69
PLDLLIMPEXP_DRIVER void plD_dispatch_init_pstex(PLDispatchTable *pdt)
#define MIN(a, b)
Definition: dsplint.c:29
#define MAX(a, b)
Definition: dsplint.c:28
int plParseDrvOpts(DrvOpt *acc_opt)
Definition: plargs.c:1461
void difilt(PLINT *xsc, PLINT *ysc, PLINT npts, PLINT *clpxmi, PLINT *clpxma, PLINT *clpymi, PLINT *clpyma)
Definition: plcore.c:1460
void plgesc(char *p_esc)
Definition: plcore.c:3914
static PLStream * pls[PL_NSTREAMS]
Definition: plcore.h:88
void plwarn(PLCHAR_VECTOR errormsg)
Definition: plctrl.c:1863
void plCloseFile(PLStream *pls)
Definition: plctrl.c:2635
void plGetFam(PLStream *pls)
Definition: plctrl.c:2780
void plRotPhy(PLINT orient, PLINT xmin, PLINT ymin, PLINT xmax, PLINT ymax, PLINT *px, PLINT *py)
Definition: plctrl.c:2824
#define PLDLLIMPEXP_DRIVER
Definition: pldll.h:81
#define PI
Definition: plplotP.h:290
#define snprintf
Definition: plplotP.h:235
#define ORIENTATION
Definition: plplotP.h:358
@ DRV_INT
Definition: plplotP.h:758
#define ROUND(a)
Definition: plplotP.h:202
#define PLESC_HAS_TEXT
Definition: plplot.h:290
float PLFLT
Definition: plplot.h:163
int PLINT
Definition: plplot.h:181
PLINT plP_strpos(PLCHAR_VECTOR str, int chr)
Definition: plsym.c:1216
void plD_line_ps(PLStream *pls, short x1a, short y1a, short x2a, short y2a)
Definition: ps.c:421
static int color
Definition: ps.c:78
void plD_eop_ps(PLStream *pls)
Definition: ps.c:494
void plD_polyline_ps(PLStream *pls, short *xa, short *ya, PLINT npts)
Definition: ps.c:479
void plD_esc_ps(PLStream *pls, PLINT op, void *ptr)
Definition: ps.c:656
void plD_tidy_ps(PLStream *pls)
Definition: ps.c:555
void plD_bop_ps(PLStream *pls)
Definition: ps.c:507
void plD_state_ps(PLStream *pls, PLINT op)
Definition: ps.c:601
#define XOFFSET
Definition: ps.h:20
#define YOFFSET
Definition: ps.h:21
void plD_init_ps(PLStream *)
void plD_esc_pstex(PLStream *, PLINT, void *)
void plD_init_pstex(PLStream *)
void plD_tidy_pstex(PLStream *)
#define ENLARGE
Definition: ps.h:17
void plD_init_psc(PLStream *)
void plD_bop_pstex(PLStream *)
int pldummy_pstex()
Definition: pstex.c:455
PLINT refy
Definition: plplotP.h:717
PLINT base
Definition: plplotP.h:707
PLINT refx
Definition: plplotP.h:716
PLFLT just
Definition: plplotP.h:708
PLINT x
Definition: plplotP.h:712
const char * string
Definition: plplotP.h:739
PLINT y
Definition: plplotP.h:713
PLFLT * xform
Definition: plplotP.h:709
unsigned char r
Definition: plplot.h:548
unsigned char g
Definition: plplot.h:549
unsigned char b
Definition: plplot.h:550
plD_eop_fp pl_eop
Definition: disptab.h:86
const char * pl_DevName
Definition: disptab.h:80
plD_esc_fp pl_esc
Definition: disptab.h:90
plD_polyline_fp pl_polyline
Definition: disptab.h:85
plD_state_fp pl_state
Definition: disptab.h:89
plD_tidy_fp pl_tidy
Definition: disptab.h:88
plD_line_fp pl_line
Definition: disptab.h:84
plD_init_fp pl_init
Definition: disptab.h:83
plD_bop_fp pl_bop
Definition: disptab.h:87
const char * pl_MenuStr
Definition: disptab.h:79
PLFLT chrht
Definition: plstrm.h:686
PLINT dev_unicode
Definition: plstrm.h:747
PLColor curcolor
Definition: plstrm.h:543
char * FileName
Definition: plstrm.h:576
PLINT cfont
Definition: plstrm.h:737
PLINT dev_text
Definition: plstrm.h:572
void * dev
Definition: plstrm.h:594
PLFLT ypmm
Definition: plstrm.h:707
PLFLT xpmm
Definition: plstrm.h:707
PLFLT diorot
Definition: plstrm.h:661
Definition: ps.h:39
FILE * fp
Definition: ps.h:59
int llx
Definition: ps.h:51
int ury
Definition: ps.h:51
PLINT ymin
Definition: ps.h:44
PLINT ymax
Definition: ps.h:44
int lly
Definition: ps.h:51
PLINT xmin
Definition: ps.h:43
long cur_pos
Definition: ps.h:58
int urx
Definition: ps.h:51
PLINT xmax
Definition: ps.h:43