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