PLplot  5.11.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
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_psm( 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
456 {
457  return 0;
458 }
459 
460 #endif // PLD_pstexdev
int plParseDrvOpts(DrvOpt *acc_opt)
Definition: plargs.c:1461
void(* plD_line_fp)(struct PLStream_struct *, short, short, short, short)
Definition: disptab.h:68
int llx
Definition: ps.h:51
void plgesc(char *p_esc)
Definition: plcore.c:3893
#define ENLARGE
Definition: ps.h:17
PLINT ymax
Definition: ps.h:44
PLINT ymin
Definition: ps.h:44
void(* plD_eop_fp)(struct PLStream_struct *)
Definition: disptab.h:70
PLFLT just
Definition: plplotP.h:704
PLFLT ypmm
Definition: plstrm.h:706
unsigned char b
Definition: plplot.h:484
PLINT xmax
Definition: ps.h:43
void(* plD_state_fp)(struct PLStream_struct *, PLINT)
Definition: disptab.h:73
void plD_polyline_ps(PLStream *, short *, short *, PLINT)
void plD_init_psc(PLStream *)
void(* plD_tidy_fp)(struct PLStream_struct *)
Definition: disptab.h:72
plD_esc_fp pl_esc
Definition: disptab.h:90
#define ROUND(a)
Definition: plplotP.h:202
void plCloseFile(PLStream *pls)
Definition: plctrl.c:2625
void plD_init_psm(PLStream *)
void plGetFam(PLStream *pls)
Definition: plctrl.c:2770
PLINT dev_text
Definition: plstrm.h:571
PLINT cfont
Definition: plstrm.h:736
const char * pl_MenuStr
Definition: disptab.h:79
PLINT dev_unicode
Definition: plstrm.h:746
void plD_esc_ps(PLStream *, PLINT, void *)
plD_tidy_fp pl_tidy
Definition: disptab.h:88
#define MAX(a, b)
Definition: dsplint.c:28
PLFLT diorot
Definition: plstrm.h:660
void plD_tidy_pstex(PLStream *)
const char * pl_DevName
Definition: disptab.h:80
plD_init_fp pl_init
Definition: disptab.h:83
PLINT xmin
Definition: ps.h:43
void plD_tidy_ps(PLStream *)
void(* plD_polyline_fp)(struct PLStream_struct *, short *, short *, PLINT)
Definition: disptab.h:69
void plD_line_ps(PLStream *, short, short, short, short)
int PLINT
Definition: plplot.h:174
#define MIN(a, b)
Definition: dsplint.c:29
void plD_state_ps(PLStream *, PLINT)
void(* plD_esc_fp)(struct PLStream_struct *, PLINT, void *)
Definition: disptab.h:74
#define YOFFSET
Definition: ps.h:21
PLINT refy
Definition: plplotP.h:713
void(* plD_bop_fp)(struct PLStream_struct *)
Definition: disptab.h:71
unsigned char g
Definition: plplot.h:483
int urx
Definition: ps.h:51
FILE * fp
Definition: ps.h:59
int ury
Definition: ps.h:51
#define snprintf
Definition: plplotP.h:235
void plD_init_pstex(PLStream *)
char * FileName
Definition: plstrm.h:575
void plD_bop_pstex(PLStream *)
plD_bop_fp pl_bop
Definition: disptab.h:87
void difilt(PLINT *xsc, PLINT *ysc, PLINT npts, PLINT *clpxmi, PLINT *clpxma, PLINT *clpymi, PLINT *clpyma)
Definition: plcore.c:1436
#define ORIENTATION
Definition: plplotP.h:358
plD_line_fp pl_line
Definition: disptab.h:84
long cur_pos
Definition: ps.h:58
#define PLDLLIMPEXP_DRIVER
Definition: pldll.h:69
#define XOFFSET
Definition: ps.h:20
static PLStream * pls[PL_NSTREAMS]
Definition: plcore.h:88
Definition: ps.h:38
void plD_bop_ps(PLStream *)
PLDLLIMPEXP_DRIVER void plD_dispatch_init_pstex(PLDispatchTable *pdt)
PLFLT xpmm
Definition: plstrm.h:706
static void proc_str(PLStream *, EscText *)
Definition: aqt.c:529
PLINT plP_strpos(const char *str, int chr)
Definition: plsym.c:1198
PLINT refx
Definition: plplotP.h:712
void plD_eop_ps(PLStream *)
float PLFLT
Definition: plplot.h:157
PLFLT chrht
Definition: plstrm.h:685
void plwarn(const char *errormsg)
Definition: plctrl.c:1853
void plRotPhy(PLINT orient, PLINT xmin, PLINT ymin, PLINT xmax, PLINT ymax, PLINT *px, PLINT *py)
Definition: plctrl.c:2814
#define PI
Definition: plplotP.h:290
int lly
Definition: ps.h:51
unsigned char r
Definition: plplot.h:482
#define PLESC_HAS_TEXT
Definition: plplot.h:229
PLINT y
Definition: plplotP.h:709
int pldummy_pstex()
Definition: pstex.c:455
PLColor curcolor
Definition: plstrm.h:543
plD_state_fp pl_state
Definition: disptab.h:89
void plD_esc_pstex(PLStream *, PLINT, void *)
const char * string
Definition: plplotP.h:735
plD_eop_fp pl_eop
Definition: disptab.h:86
PLINT x
Definition: plplotP.h:708
plD_polyline_fp pl_polyline
Definition: disptab.h:85
void * dev
Definition: plstrm.h:593
PLFLT * xform
Definition: plplotP.h:705
PLINT base
Definition: plplotP.h:703
void(* plD_init_fp)(struct PLStream_struct *)
Definition: disptab.h:67