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