PLplot: pstex.c Source File

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
13 PLDLLIMPEXP_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
23 static void parse_str( const char *str, char *dest );
24 static void proc_str( PLStream *pls, EscText *args );
25 static int color = 1;
26
27 static DrvOpt pstex_options[] = { { "color", DRV_INT, &color,
28 "Color Postscript/LaTeX (color=1|0)" },
29 { NULL, DRV_INT, NULL, NULL} };
30
31 void plD_dispatch_init_pstex( PLDispatchTable *pdt )
32 {
33 #ifndef ENABLE_DYNDRIVERS
34 pdt->pl_MenuStr = "Combined Postscript/LaTeX files";
35 pdt->pl_DevName = "pstex";
36 #endif
37 pdt->pl_type = plDevType_FileOriented;
38 pdt->pl_seq = 41;
39 pdt->pl_init = (plD_init_fp) plD_init_pstex;
40 pdt->pl_line = (plD_line_fp) plD_line_ps;
41 pdt->pl_polyline = (plD_polyline_fp) plD_polyline_ps;
42 pdt->pl_eop = (plD_eop_fp) plD_eop_ps;
43 pdt->pl_bop = (plD_bop_fp) plD_bop_pstex;
44 pdt->pl_tidy = (plD_tidy_fp) plD_tidy_pstex;
45 pdt->pl_state = (plD_state_fp) plD_state_ps;
46 pdt->pl_esc = (plD_esc_fp) plD_esc_pstex;
47 }
48
49 void
50 plD_init_pstex( PLStream *pls )
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
92 void
93 plD_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
105 void
106 plD_bop_pstex( PLStream *pls )
107 {
108 plD_bop_ps( pls );
109 plGetFam( pls );
110 }
111
112 void
113 plD_tidy_pstex( PLStream *pls )
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
136 void
137 proc_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
263 void
264 parse_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
454 int
455 pldummy_pstex()
456 {
457 return 0;
458 }
459
460 #endif // PLD_pstexdev
plParseDrvOpts
int plParseDrvOpts(DrvOpt *acc_opt)
Definition: plargs.c:1461
plplotP.h
PSDev::llx
int llx
Definition: ps.h:51
plgesc
void plgesc(char *p_esc)
Definition: plcore.c:3914
ENLARGE
#define ENLARGE
Definition: ps.h:17
PSDev::ymax
PLINT ymax
Definition: ps.h:44
PSDev::ymin
PLINT ymin
Definition: ps.h:44
EscText::just
PLFLT just
Definition: plplotP.h:708
PLStream::ypmm
PLFLT ypmm
Definition: plstrm.h:707
PLColor::b
unsigned char b
Definition: plplot.h:550
PSDev::xmax
PLINT xmax
Definition: ps.h:43
plD_init_psc
void plD_init_psc(PLStream *)
ps.h
PLDispatchTable::pl_esc
plD_esc_fp pl_esc
Definition: disptab.h:90
ROUND
#define ROUND(a)
Definition: plplotP.h:202
plCloseFile
void plCloseFile(PLStream *pls)
Definition: plctrl.c:2635
plDevType_FileOriented
Definition: disptab.h:13
plGetFam
void plGetFam(PLStream *pls)
Definition: plctrl.c:2780
plD_tidy_fp
void(* plD_tidy_fp)(struct PLStream_struct *)
Definition: disptab.h:72
PLDispatchTable::pl_seq
int pl_seq
Definition: disptab.h:82
PLStream::dev_text
PLINT dev_text
Definition: plstrm.h:572
PLStream::cfont
PLINT cfont
Definition: plstrm.h:737
PLDispatchTable::pl_MenuStr
const char * pl_MenuStr
Definition: disptab.h:79
PLStream::dev_unicode
PLINT dev_unicode
Definition: plstrm.h:747
plD_init_ps
void plD_init_ps(PLStream *)
plD_esc_ps
void plD_esc_ps(PLStream *pls, PLINT op, void *ptr)
Definition: ps.c:656
PLDispatchTable::pl_tidy
plD_tidy_fp pl_tidy
Definition: disptab.h:88
MAX
#define MAX(a, b)
Definition: dsplint.c:28
plD_init_fp
void(* plD_init_fp)(struct PLStream_struct *)
Definition: disptab.h:67
PLStream::diorot
PLFLT diorot
Definition: plstrm.h:661
plD_tidy_pstex
void plD_tidy_pstex(PLStream *)
plD_eop_fp
void(* plD_eop_fp)(struct PLStream_struct *)
Definition: disptab.h:70
PLDispatchTable::pl_DevName
const char * pl_DevName
Definition: disptab.h:80
PLDispatchTable::pl_init
plD_init_fp pl_init
Definition: disptab.h:83
plD_state_ps
void plD_state_ps(PLStream *pls, PLINT op)
Definition: ps.c:601
PSDev::xmin
PLINT xmin
Definition: ps.h:43
color
static int color
Definition: ps.c:78
PLINT
int PLINT
Definition: plplot.h:181
MIN
#define MIN(a, b)
Definition: dsplint.c:29
YOFFSET
#define YOFFSET
Definition: ps.h:21
plD_line_fp
void(* plD_line_fp)(struct PLStream_struct *, short, short, short, short)
Definition: disptab.h:68
EscText::refy
PLINT refy
Definition: plplotP.h:717
PLColor::g
unsigned char g
Definition: plplot.h:549
PSDev::urx
int urx
Definition: ps.h:51
PSDev::fp
FILE * fp
Definition: ps.h:59
plD_esc_fp
void(* plD_esc_fp)(struct PLStream_struct *, PLINT, void *)
Definition: disptab.h:74
PSDev::ury
int ury
Definition: ps.h:51
EscText
Definition: plplotP.h:699
plD_polyline_fp
void(* plD_polyline_fp)(struct PLStream_struct *, short *, short *, PLINT)
Definition: disptab.h:69
snprintf
#define snprintf
Definition: plplotP.h:235
plD_init_pstex
void plD_init_pstex(PLStream *)
PLDispatchTable
Definition: disptab.h:77
PLStream::FileName
char * FileName
Definition: plstrm.h:576
plD_bop_pstex
void plD_bop_pstex(PLStream *)
PLDispatchTable::pl_bop
plD_bop_fp pl_bop
Definition: disptab.h:87
difilt
void difilt(PLINT *xsc, PLINT *ysc, PLINT npts, PLINT *clpxmi, PLINT *clpxma, PLINT *clpymi, PLINT *clpyma)
Definition: plcore.c:1460
DrvOpt
Definition: plplotP.h:748
plD_tidy_ps
void plD_tidy_ps(PLStream *pls)
Definition: ps.c:555
ORIENTATION
#define ORIENTATION
Definition: plplotP.h:358
PLDispatchTable::pl_line
plD_line_fp pl_line
Definition: disptab.h:84
PSDev::cur_pos
long cur_pos
Definition: ps.h:58
drivers.h
plDevs.h
plD_line_ps
void plD_line_ps(PLStream *pls, short x1a, short y1a, short x2a, short y2a)
Definition: ps.c:421
PLDLLIMPEXP_DRIVER
#define PLDLLIMPEXP_DRIVER
Definition: pldll.h:81
XOFFSET
#define XOFFSET
Definition: ps.h:20
pls
static PLStream * pls[PL_NSTREAMS]
Definition: plcore.h:88
PSDev
Definition: ps.h:38
plD_dispatch_init_pstex
PLDLLIMPEXP_DRIVER void plD_dispatch_init_pstex(PLDispatchTable *pdt)
PLStream::xpmm
PLFLT xpmm
Definition: plstrm.h:707
proc_str
static void proc_str(PLStream *, EscText *)
Definition: aqt.c:529
PLStream
Definition: plstrm.h:523
plD_bop_ps
void plD_bop_ps(PLStream *pls)
Definition: ps.c:507
EscText::refx
PLINT refx
Definition: plplotP.h:716
PLFLT
float PLFLT
Definition: plplot.h:163
PLStream::chrht
PLFLT chrht
Definition: plstrm.h:686
plD_bop_fp
void(* plD_bop_fp)(struct PLStream_struct *)
Definition: disptab.h:71
plRotPhy
void plRotPhy(PLINT orient, PLINT xmin, PLINT ymin, PLINT xmax, PLINT ymax, PLINT *px, PLINT *py)
Definition: plctrl.c:2824
PI
#define PI
Definition: plplotP.h:290
PSDev::lly
int lly
Definition: ps.h:51
PLColor::r
unsigned char r
Definition: plplot.h:548
PLESC_HAS_TEXT
#define PLESC_HAS_TEXT
Definition: plplot.h:290
plwarn
void plwarn(PLCHAR_VECTOR errormsg)
Definition: plctrl.c:1863
EscText::y
PLINT y
Definition: plplotP.h:713
DRV_INT
Definition: plplotP.h:758
pldummy_pstex
int pldummy_pstex()
Definition: pstex.c:455
plD_polyline_ps
void plD_polyline_ps(PLStream *pls, short *xa, short *ya, PLINT npts)
Definition: ps.c:479
PLStream::curcolor
PLColor curcolor
Definition: plstrm.h:543
PLDispatchTable::pl_state
plD_state_fp pl_state
Definition: disptab.h:89
plD_esc_pstex
void plD_esc_pstex(PLStream *, PLINT, void *)
EscText::string
const char * string
Definition: plplotP.h:739
PLDispatchTable::pl_eop
plD_eop_fp pl_eop
Definition: disptab.h:86
EscText::x
PLINT x
Definition: plplotP.h:712
PLDispatchTable::pl_polyline
plD_polyline_fp pl_polyline
Definition: disptab.h:85
plD_state_fp
void(* plD_state_fp)(struct PLStream_struct *, PLINT)
Definition: disptab.h:73
PLStream::dev
void * dev
Definition: plstrm.h:594
plD_eop_ps
void plD_eop_ps(PLStream *pls)
Definition: ps.c:494
PLDispatchTable::pl_type
int pl_type
Definition: disptab.h:81
EscText::xform
PLFLT * xform
Definition: plplotP.h:709
EscText::base
PLINT base
Definition: plplotP.h:707
plP_strpos
PLINT plP_strpos(PLCHAR_VECTOR str, int chr)
Definition: plsym.c:1216