~ubuntu-branches/ubuntu/intrepid/plplot/intrepid

« back to all changes in this revision

Viewing changes to drivers/psttf.cc

  • Committer: Bazaar Package Importer
  • Author(s): Rafael Laboissiere
  • Date: 2006-11-04 10:19:34 UTC
  • mfrom: (2.1.8 edgy)
  • Revision ID: james.westby@ubuntu.com-20061104101934-mlirvdg4gpwi6i5q
Tags: 5.6.1-10
* Orphaning the package
* debian/control: Changed the maintainer to the Debian QA Group

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Id: psttf.cc,v 1.8 2006/05/18 11:56:39 rlaboiss Exp $
 
2
 
 
3
        PLplot PostScript device driver using LASi to provide fonts
 
4
        based on original ps.c PostScript driver
 
5
 
 
6
  Copyright (C) 1992, 2001  Geoffrey Furnish  
 
7
  Copyright (C) 1992, 1993, 1994, 1995, 2001  Maurice LeBrun
 
8
  Copyright (C) 2000, 2001, 2002, 2004, 2005  Alan W. Irwin 
 
9
  Copyright (C) 2001, 2002  Joao Cardoso  
 
10
  Copyright (C) 2001, 2003, 2004  Rafael Laboissiere
 
11
  Copyright (C) 2004, 2005  Thomas J. Duck
 
12
  Copyright (C) 2005, 2006  Andrew Ross
 
13
 
 
14
  This file is part of PLplot.
 
15
 
 
16
  PLplot is free software; you can redistribute it and/or modify
 
17
  it under the terms of the GNU General Library Public License as published
 
18
  by the Free Software Foundation; either version 2 of the License, or
 
19
  (at your option) any later version.
 
20
 
 
21
  PLplot is distributed in the hope that it will be useful,
 
22
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
23
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
24
  GNU Library General Public License for more details.
 
25
 
 
26
  You should have received a copy of the GNU Library General Public License
 
27
  along with PLplot; if not, write to the Free Software
 
28
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
29
 
 
30
*/
 
31
 
 
32
#include "plDevs.h"
 
33
 
 
34
#define DEBUG
 
35
 
 
36
#if defined(PLD_psttf)
 
37
 
 
38
#define NEED_PLDEBUG
 
39
#include "plplotP.h"
 
40
#include "drivers.h"
 
41
#include "ps.h"
 
42
 
 
43
#include <string.h>
 
44
#include <time.h>
 
45
#include "plfreetype.h"
 
46
#include <iostream>
 
47
#include <fstream>
 
48
#include <LASi.h>
 
49
 
 
50
using namespace LASi;
 
51
using namespace std;
 
52
 
 
53
/* Device info */
 
54
 
 
55
char* plD_DEVICE_INFO_psttf = 
 
56
  "psttf:PostScript File (monochrome):0:psttf:55:psttfm\n"
 
57
  "psttfc:PostScript File (color):0:psttf:56:psttfc";
 
58
 
 
59
 
 
60
/* Prototypes for functions in this file. */
 
61
 
 
62
void plD_dispatch_init_psttfm   ( PLDispatchTable *pdt );
 
63
void plD_dispatch_init_psttfc   ( PLDispatchTable *pdt );
 
64
 
 
65
static char  *ps_getdate        (void);
 
66
static void  ps_init            (PLStream *);
 
67
static void  fill_polygon       (PLStream *pls);
 
68
static void  proc_str           (PLStream *, EscText *);
 
69
static void  esc_purge          (char *, char *);
 
70
 
 
71
static char  outbuf[128];
 
72
static int text = 1;
 
73
static int color;
 
74
static int hrshsym = 0;
 
75
 
 
76
/* Font style and weight lookup tables */
 
77
 
 
78
#define N_Pango_Lookup 5
 
79
 
 
80
const char * DefaultFamilyLookup[N_Pango_Lookup] = {
 
81
  "sans",
 
82
  "serif",
 
83
  "monospace",
 
84
  "sans,serif",
 
85
  "sans,serif"
 
86
};
 
87
 
 
88
const char * EnvFamilyLookup[N_Pango_Lookup] = {
 
89
  "PLPLOT_FREETYPE_SANS_FAMILY",
 
90
  "PLPLOT_FREETYPE_SERIF_FAMILY",
 
91
  "PLPLOT_FREETYPE_MONO_FAMILY",
 
92
  "PLPLOT_FREETYPE_SCRIPT_FAMILY",
 
93
  "PLPLOT_FREETYPE_SYMBOL_FAMILY"
 
94
};
 
95
 
 
96
char FamilyLookup[N_Pango_Lookup][1024];
 
97
 
 
98
const FontWeight WeightLookup[2] = {
 
99
  NORMAL_WEIGHT,
 
100
  BOLD
 
101
};
 
102
 
 
103
const FontStyle StyleLookup[3] = {
 
104
  NORMAL_STYLE,
 
105
  ITALIC,
 
106
  OBLIQUE
 
107
};
 
108
 
 
109
static DrvOpt ps_options[] = {{"text", DRV_INT, &text, "Use Postscript text (text=0|1)"},
 
110
                              {"color", DRV_INT, &color, "Use color (color=0|1)"},
 
111
                              {"hrshsym", DRV_INT, &hrshsym, "Use Hershey symbol set (hrshsym=0|1)"},
 
112
                              {NULL, DRV_INT, NULL, NULL}};
 
113
 
 
114
/* text > 0 uses some postscript tricks, namely a transformation matrix
 
115
   that scales, rotates (with slanting) and offsets text strings.
 
116
   It has yet some bugs for 3d plots. */
 
117
 
 
118
 
 
119
static void psttf_dispatch_init_helper( PLDispatchTable *pdt,
 
120
                                     char *menustr, char *devnam,
 
121
                                     int type, int seq, plD_init_fp init )
 
122
{
 
123
#ifndef ENABLE_DYNDRIVERS
 
124
    pdt->pl_MenuStr = menustr;
 
125
    pdt->pl_DevName = devnam;
 
126
#endif
 
127
    pdt->pl_type = type;
 
128
    pdt->pl_seq = seq;
 
129
    pdt->pl_init     = init;
 
130
    pdt->pl_line     = (plD_line_fp)     plD_line_psttf;
 
131
    pdt->pl_polyline = (plD_polyline_fp) plD_polyline_psttf;
 
132
    pdt->pl_eop      = (plD_eop_fp)      plD_eop_psttf;
 
133
    pdt->pl_bop      = (plD_bop_fp)      plD_bop_psttf;
 
134
    pdt->pl_tidy     = (plD_tidy_fp)     plD_tidy_psttf;
 
135
    pdt->pl_state    = (plD_state_fp)    plD_state_psttf;
 
136
    pdt->pl_esc      = (plD_esc_fp)      plD_esc_psttf;
 
137
}
 
138
 
 
139
void plD_dispatch_init_psttfm   ( PLDispatchTable *pdt )
 
140
{
 
141
    psttf_dispatch_init_helper( pdt,
 
142
                             "PostScript File (monochrome)", "psttf",
 
143
                             plDevType_FileOriented, 55,
 
144
                             (plD_init_fp) plD_init_psttfm );
 
145
}
 
146
 
 
147
void plD_dispatch_init_psttfc   ( PLDispatchTable *pdt )
 
148
{
 
149
    psttf_dispatch_init_helper( pdt,
 
150
                             "PostScript File (color)", "psttfc",
 
151
                             plDevType_FileOriented, 56,
 
152
                             (plD_init_fp) plD_init_psttfc );
 
153
}
 
154
 
 
155
/*--------------------------------------------------------------------------*\
 
156
 * plD_init_psttf()
 
157
 *
 
158
 * Initialize device.
 
159
\*--------------------------------------------------------------------------*/
 
160
 
 
161
void
 
162
plD_init_psttfm(PLStream *pls)
 
163
{
 
164
  color = 0;
 
165
  pls->color = 0;               /* Not a color device */
 
166
 
 
167
  plParseDrvOpts(ps_options);
 
168
  if (color)
 
169
    pls->color = 1;             /* But user wants color */
 
170
  ps_init(pls);
 
171
}
 
172
 
 
173
void
 
174
plD_init_psttfc(PLStream *pls)
 
175
{
 
176
  color = 1;
 
177
  pls->color = 1;               /* Is a color device */
 
178
  plParseDrvOpts(ps_options);
 
179
 
 
180
  if (!color)
 
181
    pls->color = 0;             /* But user does not want color */
 
182
  ps_init(pls);
 
183
}
 
184
 
 
185
#define MAX_NUM_TRIES   10
 
186
static void
 
187
ps_init(PLStream *pls)
 
188
{
 
189
    int i;
 
190
    char *a;
 
191
    PSDev *dev;
 
192
 
 
193
    PLFLT pxlx = YPSSIZE/LPAGE_X;
 
194
    PLFLT pxly = XPSSIZE/LPAGE_Y;
 
195
 
 
196
    if (text) 
 
197
     {
 
198
        pls->dev_text = 1; /* want to draw text */
 
199
        pls->dev_unicode = 1; /* want unicode */
 
200
        if(hrshsym) pls->dev_hrshsym = 1; /* want Hershey symbols */
 
201
     }
 
202
 
 
203
    pls->dev_fill0 = 1;         /* Can do solid fills */
 
204
 
 
205
/* Initialize family file info */
 
206
 
 
207
    plFamInit(pls);
 
208
 
 
209
/* Prompt for a file name if not already set */
 
210
    
 
211
    plOpenFile(pls);
 
212
 
 
213
/* Create postscript document object */
 
214
    if (pls->psdoc != NULL) 
 
215
      delete (PostscriptDocument *) pls->psdoc;
 
216
 
 
217
    pls->psdoc = new PostscriptDocument();
 
218
 
 
219
/* Allocate and initialize device-specific data */
 
220
 
 
221
    if (pls->dev != NULL)
 
222
        free((void *) pls->dev);
 
223
 
 
224
    pls->dev = calloc(1, (size_t) sizeof(PSDev));
 
225
    if (pls->dev == NULL)
 
226
        plexit("ps_init: Out of memory.");
 
227
 
 
228
    dev = (PSDev *) pls->dev;
 
229
 
 
230
    dev->xold = PL_UNDEFINED;
 
231
    dev->yold = PL_UNDEFINED;
 
232
 
 
233
    plP_setpxl(pxlx, pxly);
 
234
 
 
235
    dev->llx = XPSSIZE;
 
236
    dev->lly = YPSSIZE;
 
237
    dev->urx = 0;
 
238
    dev->ury = 0;
 
239
    dev->ptcnt = 0;
 
240
 
 
241
/* Rotate by 90 degrees since portrait mode addressing is used */
 
242
 
 
243
    dev->xmin = 0;
 
244
    dev->ymin = 0;
 
245
    dev->xmax = PSY;
 
246
    dev->ymax = PSX;
 
247
    dev->xlen = dev->xmax - dev->xmin;
 
248
    dev->ylen = dev->ymax - dev->ymin;
 
249
 
 
250
    plP_setphy(dev->xmin, dev->xmax, dev->ymin, dev->ymax);
 
251
 
 
252
/* If portrait mode is specified, then set up an additional rotation 
 
253
 * transformation with aspect ratio allowed to adjust via freeaspect.  
 
254
 * Default orientation is landscape (ORIENTATION == 3 or 90 deg rotation 
 
255
 * counter-clockwise from portrait).  (Legacy PLplot used seascape
 
256
 * which was equivalent to ORIENTATION == 1 or 90 deg clockwise rotation 
 
257
 * from portrait.) */
 
258
 
 
259
    if (pls->portrait) {
 
260
       plsdiori((PLFLT)(4 - ORIENTATION));
 
261
       pls->freeaspect = 1;
 
262
    }
 
263
 
 
264
    // File table for font families using either environment variables 
 
265
    // or defaults.
 
266
    for (i=0;i<N_Pango_Lookup;i++) {
 
267
      if ( (a = getenv(EnvFamilyLookup[i])) != NULL ) {
 
268
        strcpy(FamilyLookup[i],a);
 
269
      }
 
270
      else {
 
271
        strcpy(FamilyLookup[i],DefaultFamilyLookup[i]);
 
272
      }
 
273
    }
 
274
 
 
275
}
 
276
 
 
277
 
 
278
/*--------------------------------------------------------------------------*\
 
279
 * writeHeader()
 
280
 * 
 
281
 * Write plplot postscript commands into the header
 
282
\*--------------------------------------------------------------------------*/
 
283
 
 
284
void
 
285
writeHeader(PLStream *pls) {
 
286
    PostscriptDocument *doc = (PostscriptDocument *) (pls->psdoc);
 
287
 
 
288
    doc->osHeader() << "%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
 
289
    
 
290
    doc->osHeader() << "%%Title: PLplot Graph\n";
 
291
    doc->osHeader() << "%%Creator: PLplot Version " << VERSION << "\n";
 
292
    doc->osHeader() << "%%CreationDate: " << ps_getdate() << "\n";
 
293
    doc->osHeader() << "%%Pages: (atend)\n";
 
294
    doc->osHeader() << "%%EndComments\n\n";
 
295
 
 
296
/* Definitions */
 
297
/* Save VM state */
 
298
 
 
299
    doc->osHeader() << "/PSSave save def\n";
 
300
 
 
301
/* Define a dictionary and start using it */
 
302
 
 
303
    doc->osHeader() << "/PSDict 200 dict def\n";
 
304
    doc->osHeader() << "PSDict begin\n";
 
305
 
 
306
    doc->osHeader() << "/@restore /restore load def\n";
 
307
    doc->osHeader() << "/restore\n";
 
308
    doc->osHeader() << "   {vmstatus pop\n";
 
309
    doc->osHeader() << "    dup @VMused lt {pop @VMused} if\n";
 
310
    doc->osHeader() << "    exch pop exch @restore /@VMused exch def\n";
 
311
    doc->osHeader() << "   } def\n";
 
312
    doc->osHeader() << "/@pri\n";
 
313
    doc->osHeader() << "   {\n";
 
314
    doc->osHeader() << "    ( ) print\n";
 
315
    doc->osHeader() << "    (                                       ) cvs print\n";
 
316
    doc->osHeader() << "   } def\n";
 
317
 
 
318
/* n @copies - */
 
319
 
 
320
    doc->osHeader() << "/@copies\n";
 
321
    doc->osHeader() << "   {\n";
 
322
    doc->osHeader() << "    /#copies exch def\n";
 
323
    doc->osHeader() << "   } def\n";
 
324
 
 
325
/* - @start -  -- start everything */
 
326
 
 
327
    doc->osHeader() << "/@start\n";
 
328
    doc->osHeader() << "   {\n";
 
329
    doc->osHeader() << "    vmstatus pop /@VMused exch def pop\n";
 
330
    doc->osHeader() << "   } def\n";
 
331
 
 
332
/* - @end -  -- finished */
 
333
 
 
334
    doc->osHeader() << "/@end\n";
 
335
    doc->osHeader() << "   {flush\n";
 
336
    doc->osHeader() << "    end\n";
 
337
    doc->osHeader() << "    PSSave restore\n";
 
338
    doc->osHeader() << "   } def\n";
 
339
    
 
340
/* bop -  -- begin a new page */
 
341
/* Only fill background if we are using color and if the bg isn't white */
 
342
 
 
343
    doc->osHeader() << "/bop\n";
 
344
    doc->osHeader() << "   {\n";
 
345
    doc->osHeader() << "    /SaveImage save def\n";
 
346
    doc->osHeader() << "   } def\n";
 
347
 
 
348
/* - eop -  -- end a page */
 
349
 
 
350
    doc->osHeader() << "/eop\n";
 
351
    doc->osHeader() << "   {\n";
 
352
    doc->osHeader() << "    showpage\n";
 
353
    doc->osHeader() << "    SaveImage restore\n";
 
354
    doc->osHeader() << "   } def\n";
 
355
 
 
356
/* Set line parameters */
 
357
    
 
358
    doc->osHeader() << "/@line\n";
 
359
    doc->osHeader() << "   {0 setlinecap\n";
 
360
    doc->osHeader() << "    0 setlinejoin\n";
 
361
    doc->osHeader() << "    1 setmiterlimit\n";
 
362
    doc->osHeader() << "   } def\n";
 
363
 
 
364
/* d @hsize -  horizontal clipping dimension */
 
365
 
 
366
    doc->osHeader() << "/@hsize   {/hs exch def} def\n";
 
367
    doc->osHeader() << "/@vsize   {/vs exch def} def\n";
 
368
 
 
369
/* d @hoffset - shift for the plots */
 
370
 
 
371
    doc->osHeader() << "/@hoffset {/ho exch def} def\n";
 
372
    doc->osHeader() << "/@voffset {/vo exch def} def\n";
 
373
 
 
374
/* Set line width */
 
375
 
 
376
    doc->osHeader() << "/lw " << (int) (
 
377
        (pls->width < MIN_WIDTH) ? DEF_WIDTH :
 
378
        (pls->width > MAX_WIDTH) ? MAX_WIDTH : pls->width) << " def\n";
 
379
 
 
380
/* Setup user specified offsets, scales, sizes for clipping */
 
381
 
 
382
    doc->osHeader() << "/@SetPlot\n";
 
383
    doc->osHeader() << "   {\n";
 
384
    doc->osHeader() << "    ho vo translate\n";
 
385
    doc->osHeader() << "    XScale YScale scale\n";
 
386
    doc->osHeader() << "    lw setlinewidth\n";
 
387
    doc->osHeader() << "   } def\n";
 
388
 
 
389
/* Setup x & y scales */
 
390
    
 
391
    doc->osHeader() << "/XScale\n";
 
392
    doc->osHeader() << "   {hs " << YPSSIZE << " div} def\n";
 
393
    doc->osHeader() << "/YScale\n";
 
394
    doc->osHeader() << "   {vs " << XPSSIZE << " div} def\n";
 
395
    
 
396
/* Macro definitions of common instructions, to keep output small */
 
397
 
 
398
    doc->osHeader() << "/M {moveto} def\n";
 
399
    doc->osHeader() << "/D {lineto} def\n";
 
400
    doc->osHeader() << "/A {0.5 0 360 arc} def\n";
 
401
    doc->osHeader() << "/S {stroke} def\n";
 
402
    doc->osHeader() << "/Z {stroke newpath} def\n";
 
403
    doc->osHeader() << "/F {fill} def\n";
 
404
    doc->osHeader() << "/C {setrgbcolor} def\n";
 
405
    doc->osHeader() << "/G {setgray} def\n";
 
406
    doc->osHeader() << "/W {setlinewidth} def\n";
 
407
    doc->osHeader() << "/R {rotate} def\n";
 
408
    doc->osHeader() << "/B {Z " << XMIN << " " << YMIN << " M " << XMIN << " " << YMAX << " D " << XMAX << " " << YMAX << " D " << XMAX << " " << YMIN << " D " << XMIN << " " << YMIN << " closepath} def\n";
 
409
    doc->osHeader() << "/CL {newpath M D D D closepath clip} def\n";
 
410
    
 
411
/* End of dictionary definition */
 
412
 
 
413
    doc->osHeader() << "end\n\n";
 
414
 
 
415
/* Set up the plots */
 
416
 
 
417
    doc->osHeader() << "PSDict begin\n";
 
418
    doc->osHeader() << "@start\n";
 
419
    doc->osHeader() << "%d @copies\n", COPIES;
 
420
    doc->osHeader() << "@line\n";
 
421
    doc->osHeader() << YSIZE << " @hsize\n";
 
422
    doc->osHeader() << XSIZE << " @vsize\n";
 
423
    doc->osHeader() << YOFFSET << " @hoffset\n";
 
424
    doc->osHeader() << XOFFSET << " @voffset\n";
 
425
 
 
426
    doc->osHeader() << "@SetPlot\n" << endl;
 
427
}
 
428
 
 
429
/*--------------------------------------------------------------------------*\
 
430
 * plD_line_psttf()
 
431
 *
 
432
 * Draw a line in the current color from (x1,y1) to (x2,y2).
 
433
\*--------------------------------------------------------------------------*/
 
434
 
 
435
void
 
436
plD_line_psttf(PLStream *pls, short x1a, short y1a, short x2a, short y2a)
 
437
{
 
438
    PSDev *dev = (PSDev *) pls->dev;
 
439
    PostscriptDocument *doc = (PostscriptDocument *) pls->psdoc;
 
440
    PLINT x1 = x1a, y1 = y1a, x2 = x2a, y2 = y2a;
 
441
 
 
442
/* Rotate by 90 degrees */
 
443
 
 
444
    plRotPhy(ORIENTATION, dev->xmin, dev->ymin, dev->xmax, dev->ymax, &x1, &y1);
 
445
    plRotPhy(ORIENTATION, dev->xmin, dev->ymin, dev->xmax, dev->ymax, &x2, &y2);
 
446
 
 
447
    if (x1 == dev->xold && y1 == dev->yold && dev->ptcnt < 40) {
 
448
        if (pls->linepos + 12 > LINELENGTH) {
 
449
            doc->osBody() << '\n';
 
450
            pls->linepos = 0;
 
451
        }
 
452
        else
 
453
            doc->osBody() << ' ';
 
454
 
 
455
        sprintf(outbuf, "%d %d D", x2, y2);
 
456
        dev->ptcnt++;
 
457
        pls->linepos += 12;
 
458
    }
 
459
    else {
 
460
        doc->osBody() << " Z\n";
 
461
        pls->linepos = 0;
 
462
 
 
463
        if (x1 == x2 && y1 == y2) /* must be a single dot, draw a circle */
 
464
          sprintf(outbuf, "%d %d A", x1, y1);
 
465
        else
 
466
          sprintf(outbuf, "%d %d M %d %d D", x1, y1, x2, y2);
 
467
        dev->llx = MIN(dev->llx, x1);
 
468
        dev->lly = MIN(dev->lly, y1);
 
469
        dev->urx = MAX(dev->urx, x1);
 
470
        dev->ury = MAX(dev->ury, y1);
 
471
        dev->ptcnt = 1;
 
472
        pls->linepos += 24;
 
473
    }
 
474
    dev->llx = MIN(dev->llx, x2);
 
475
    dev->lly = MIN(dev->lly, y2);
 
476
    dev->urx = MAX(dev->urx, x2);
 
477
    dev->ury = MAX(dev->ury, y2);
 
478
 
 
479
    doc->osBody() << outbuf;
 
480
    pls->bytecnt += 1 + strlen(outbuf);
 
481
    dev->xold = x2;
 
482
    dev->yold = y2;
 
483
}
 
484
 
 
485
/*--------------------------------------------------------------------------*\
 
486
 * plD_polyline_psttf()
 
487
 *
 
488
 * Draw a polyline in the current color.
 
489
\*--------------------------------------------------------------------------*/
 
490
 
 
491
void
 
492
plD_polyline_psttf(PLStream *pls, short *xa, short *ya, PLINT npts)
 
493
{
 
494
    PLINT i;
 
495
 
 
496
    for (i = 0; i < npts - 1; i++)
 
497
        plD_line_psttf(pls, xa[i], ya[i], xa[i + 1], ya[i + 1]);
 
498
}
 
499
 
 
500
/*--------------------------------------------------------------------------*\
 
501
 * plD_eop_psttf()
 
502
 *
 
503
 * End of page.
 
504
\*--------------------------------------------------------------------------*/
 
505
 
 
506
void
 
507
plD_eop_psttf(PLStream *pls)
 
508
{
 
509
    PostscriptDocument *doc = (PostscriptDocument *) pls->psdoc;
 
510
    doc->osBody() << " S\neop\n";
 
511
}
 
512
 
 
513
/*--------------------------------------------------------------------------*\
 
514
 * plD_bop_psttf()
 
515
 *
 
516
 * Set up for the next page.
 
517
 * Advance to next family file if necessary (file output).
 
518
\*--------------------------------------------------------------------------*/
 
519
 
 
520
void
 
521
plD_bop_psttf(PLStream *pls)
 
522
{
 
523
    PSDev *dev = (PSDev *) pls->dev;
 
524
    PostscriptDocument *doc = (PostscriptDocument *) pls->psdoc;
 
525
 
 
526
    dev->xold = PL_UNDEFINED;
 
527
    dev->yold = PL_UNDEFINED;
 
528
 
 
529
    if (!pls->termin)
 
530
        plGetFam(pls);
 
531
 
 
532
    pls->page++;
 
533
 
 
534
    if (pls->family)
 
535
        doc->osBody() << "%%Page: " << (int) pls->page << " 1\n";
 
536
    else
 
537
      doc->osBody() << "%%Page: " << (int) pls->page << " " << (int) pls->page << "\n";
 
538
 
 
539
    doc->osBody() << "bop\n";
 
540
    if (pls->color) {
 
541
        PLFLT r, g, b;
 
542
        if (pls->cmap0[0].r != 0xFF ||
 
543
            pls->cmap0[0].g != 0xFF ||
 
544
            pls->cmap0[0].b != 0xFF ) {
 
545
 
 
546
            r = ((PLFLT) pls->cmap0[0].r) / 255.;
 
547
            g = ((PLFLT) pls->cmap0[0].g) / 255.;
 
548
            b = ((PLFLT) pls->cmap0[0].b) / 255.;
 
549
 
 
550
            doc->osBody() << "B " << r << " " << g << " " << b << " C F\n";
 
551
        }
 
552
    }
 
553
    pls->linepos = 0;
 
554
 
 
555
/* This ensures the color and line width are set correctly at the beginning of
 
556
   each page */
 
557
 
 
558
    plD_state_psttf(pls, PLSTATE_COLOR0);
 
559
    plD_state_psttf(pls, PLSTATE_WIDTH);
 
560
}
 
561
 
 
562
/*--------------------------------------------------------------------------*\
 
563
 * plD_tidy_psttf()
 
564
 *
 
565
 * Close graphics file or otherwise clean up.
 
566
\*--------------------------------------------------------------------------*/
 
567
 
 
568
void
 
569
plD_tidy_psttf(PLStream *pls)
 
570
{
 
571
    PSDev *dev = (PSDev *) pls->dev;
 
572
    PostscriptDocument *doc = (PostscriptDocument *) pls->psdoc;
 
573
 
 
574
    dev->llx /= ENLARGE;
 
575
    dev->lly /= ENLARGE;
 
576
    dev->urx /= ENLARGE;
 
577
    dev->ury /= ENLARGE;
 
578
    dev->llx += XOFFSET;
 
579
    dev->lly += YOFFSET;
 
580
    dev->urx += XOFFSET;
 
581
    dev->ury += YOFFSET;
 
582
 
 
583
/* changed for correct Bounding boundaries Jan Thorbecke  okt 1993*/
 
584
/* occurs from the integer truncation -- postscript uses fp arithmetic */
 
585
 
 
586
    dev->urx += 1;
 
587
    dev->ury += 1;
 
588
 
 
589
    if (pls->family)
 
590
        doc->osFooter() << "%%Pages: 1\n";
 
591
    else
 
592
        doc->osFooter() << "%%Pages: " << (int) pls->page << "\n";
 
593
 
 
594
    doc->osFooter() << "@end" << endl;
 
595
 
 
596
/* Now write the rest of the header */
 
597
    writeHeader(pls);
 
598
 
 
599
/* Write out postscript document to file and close*/
 
600
    /* For C++ stream we first need to close the file using 
 
601
       the C FILE * handle, then reopen as a ofstream. Yuck! */
 
602
    fclose(pls->OutFile);
 
603
    if (! strcmp(pls->FileName,"-")) {
 
604
      doc->write(cout,dev->llx,dev->lly,dev->urx,dev->ury);
 
605
    }
 
606
    else {      
 
607
      ofstream out;
 
608
      out.open(pls->FileName);
 
609
      doc->write(out,dev->llx,dev->lly,dev->urx,dev->ury);
 
610
      out.close();      
 
611
    }
 
612
 
 
613
    delete doc;
 
614
    pls->psdoc = NULL;
 
615
 
 
616
}
 
617
 
 
618
/*--------------------------------------------------------------------------*\
 
619
 * plD_state_psttf()
 
620
 *
 
621
 * Handle change in PLStream state (color, pen width, fill attribute, etc).
 
622
\*--------------------------------------------------------------------------*/
 
623
 
 
624
void 
 
625
plD_state_psttf(PLStream *pls, PLINT op)
 
626
{
 
627
    PSDev *dev = (PSDev *) pls->dev;
 
628
    PostscriptDocument *doc = (PostscriptDocument *) pls->psdoc;
 
629
 
 
630
    switch (op) {
 
631
 
 
632
    case PLSTATE_WIDTH:{
 
633
        int width = 
 
634
            (pls->width < MIN_WIDTH) ? DEF_WIDTH :
 
635
            (pls->width > MAX_WIDTH) ? MAX_WIDTH : pls->width;
 
636
 
 
637
        doc->osBody() << " S\n" << width << " W";
 
638
 
 
639
        dev->xold = PL_UNDEFINED;
 
640
        dev->yold = PL_UNDEFINED;
 
641
        break;
 
642
    }
 
643
    case PLSTATE_COLOR0:
 
644
        if (! pls->color) {
 
645
            doc->osBody() << " S\n" << (pls->icol0 ? 0.0 : 1.0) << " G";
 
646
            break;
 
647
        }
 
648
        /* else fallthrough */
 
649
    case PLSTATE_COLOR1:
 
650
        if (pls->color) {
 
651
            PLFLT r = ((PLFLT) pls->curcolor.r) / 255.0;
 
652
            PLFLT g = ((PLFLT) pls->curcolor.g) / 255.0;
 
653
            PLFLT b = ((PLFLT) pls->curcolor.b) / 255.0;
 
654
 
 
655
            doc->osBody() << " S\n" << r << " " << g << " " << b << " C";
 
656
        }
 
657
        else {
 
658
            PLFLT r = ((PLFLT) pls->curcolor.r) / 255.0;
 
659
            doc->osBody() << " S\n" << 1.0 - r << " G";
 
660
        }
 
661
        break;
 
662
    }
 
663
 
 
664
/* Reinitialize current point location. */
 
665
 
 
666
    if (dev->xold != PL_UNDEFINED && dev->yold != PL_UNDEFINED) {
 
667
        doc->osBody() << " " << (int)dev->xold << " " << (int)dev->yold << " M \n";
 
668
    }
 
669
}
 
670
 
 
671
/*--------------------------------------------------------------------------*\
 
672
 * plD_esc_psttf()
 
673
 *
 
674
 * Escape function.
 
675
\*--------------------------------------------------------------------------*/
 
676
 
 
677
void
 
678
plD_esc_psttf(PLStream *pls, PLINT op, void *ptr)
 
679
{
 
680
    switch (op) {
 
681
    case PLESC_FILL:
 
682
      fill_polygon(pls);
 
683
      break;
 
684
    case PLESC_HAS_TEXT:
 
685
      proc_str(pls, (EscText *)ptr);
 
686
      break;
 
687
    }
 
688
}
 
689
 
 
690
/*--------------------------------------------------------------------------*\
 
691
 * fill_polygon()
 
692
 *
 
693
 * Fill polygon described in points pls->dev_x[] and pls->dev_y[].
 
694
 * Only solid color fill supported.
 
695
\*--------------------------------------------------------------------------*/
 
696
 
 
697
static void
 
698
fill_polygon(PLStream *pls)
 
699
{
 
700
    PSDev *dev = (PSDev *) pls->dev;
 
701
    PostscriptDocument *doc = (PostscriptDocument *) pls->psdoc;
 
702
    PLINT n, ix = 0, iy = 0;
 
703
    PLINT x, y;
 
704
 
 
705
    doc->osBody() << " Z\n";
 
706
 
 
707
    for (n = 0; n < pls->dev_npts; n++) {
 
708
        x = pls->dev_x[ix++];
 
709
        y = pls->dev_y[iy++];
 
710
 
 
711
/* Rotate by 90 degrees */
 
712
 
 
713
        plRotPhy(ORIENTATION, dev->xmin, dev->ymin, dev->xmax, dev->ymax, &x, &y);
 
714
 
 
715
/* First time through start with a x y moveto */
 
716
 
 
717
        if (n == 0) {
 
718
            sprintf(outbuf, "%d %d M", x, y);
 
719
            dev->llx = MIN(dev->llx, x);
 
720
            dev->lly = MIN(dev->lly, y);
 
721
            dev->urx = MAX(dev->urx, x);
 
722
            dev->ury = MAX(dev->ury, y);
 
723
            doc->osBody() << outbuf;
 
724
            pls->bytecnt += strlen(outbuf);
 
725
            continue;
 
726
        }
 
727
 
 
728
        if (pls->linepos + 21 > LINELENGTH) {
 
729
            doc->osBody() << '\n';
 
730
            pls->linepos = 0;
 
731
        }
 
732
        else
 
733
            doc->osBody() << ' ';
 
734
 
 
735
        pls->bytecnt++;
 
736
 
 
737
        sprintf(outbuf, "%d %d D", x, y);
 
738
        dev->llx = MIN(dev->llx, x);
 
739
        dev->lly = MIN(dev->lly, y);
 
740
        dev->urx = MAX(dev->urx, x);
 
741
        dev->ury = MAX(dev->ury, y);
 
742
 
 
743
        doc->osBody() << outbuf;
 
744
        pls->bytecnt += strlen(outbuf);
 
745
        pls->linepos += 21;
 
746
    }
 
747
    dev->xold = PL_UNDEFINED;
 
748
    dev->yold = PL_UNDEFINED;
 
749
    doc->osBody() << " F ";
 
750
}
 
751
 
 
752
/*--------------------------------------------------------------------------*\
 
753
 * ps_getdate()
 
754
 *
 
755
 * Get the date and time
 
756
\*--------------------------------------------------------------------------*/
 
757
 
 
758
static char *
 
759
ps_getdate(void)
 
760
{
 
761
    int len;
 
762
    time_t t;
 
763
    char *p;
 
764
 
 
765
    t = time((time_t *) 0);
 
766
    p = ctime(&t);
 
767
    len = strlen(p);
 
768
    *(p + len - 1) = '\0';      /* zap the newline character */
 
769
    return p;
 
770
}
 
771
 
 
772
 
 
773
/*--------------------------------------------------------------------------*\
 
774
 * proc_str()
 
775
 *
 
776
 * Prints postscript strings.
 
777
 * N.B. Now unicode only, no string access!
 
778
 *
 
779
\*--------------------------------------------------------------------------*/
 
780
 
 
781
void
 
782
proc_str (PLStream *pls, EscText *args)
 
783
{
 
784
  PLFLT *t = args->xform, tt[4]; /* Transform matrices */
 
785
  PLFLT theta;  /* Rotation angle and shear from the matrix */
 
786
  PLFLT ft_ht, offset; /* Font height and offset */
 
787
  PLFLT cs,sn;
 
788
  PSDev *dev = (PSDev *) pls->dev;
 
789
  PostscriptDocument *doc = (PostscriptDocument *) pls->psdoc;
 
790
  char *font, esc;
 
791
  FontStyle style;
 
792
  FontWeight weight;
 
793
  /* Be generous.  Used to store lots of font changes which take
 
794
   * 3 characters per change.*/
 
795
  #define PROC_STR_STRING_LENGTH 1000
 
796
  char *strp, str[PROC_STR_STRING_LENGTH], *cur_strp, 
 
797
     cur_str[PROC_STR_STRING_LENGTH];
 
798
  float font_factor = 1.4;
 
799
  PLINT clxmin, clxmax, clymin, clymax; /* Clip limits */
 
800
  PLINT clipx[4],clipy[4]; /* Current clip limits */
 
801
 
 
802
  PLFLT scale = 1., up = 0.; /* Font scaling and shifting parameters */
 
803
 
 
804
  double lineSpacing, xAdvance, xwid, ymintmp, ymaxtmp, ymin, ymax, xmin, xmax;
 
805
  PLINT xx[4], yy[4];
 
806
 
 
807
  int i=0; /* String index */
 
808
  int k=0;
 
809
 
 
810
  short text_len;
 
811
 
 
812
  FT_Data *FT;
 
813
 
 
814
   /* unicode only! so test for it. */
 
815
   if (args->unicode_array_len>0)
 
816
     {
 
817
 
 
818
       FT = (FT_Data *) pls->FT;
 
819
        int j,s,f;
 
820
        char  *fonts[PROC_STR_STRING_LENGTH];
 
821
        FontStyle styles[PROC_STR_STRING_LENGTH];
 
822
        FontWeight weights[PROC_STR_STRING_LENGTH];
 
823
        const PLUNICODE *cur_text;
 
824
        const PLUNICODE *cur_text_limit;
 
825
        PLUNICODE fci;
 
826
        unsigned char fontfamily, fontstyle, fontweight;
 
827
        /* translate from unicode into type 1 font index. */
 
828
        /*
 
829
         * Choose the font family, style, variant, and weight using
 
830
         * the FCI (font characterization integer).
 
831
         */
 
832
 
 
833
        plgesc(&esc);
 
834
        plgfci(&fci);
 
835
        plP_fci2hex(fci,&fontfamily,PL_FCI_FAMILY);
 
836
        plP_fci2hex(fci,&fontstyle,PL_FCI_STYLE);
 
837
        plP_fci2hex(fci,&fontweight,PL_FCI_WEIGHT);
 
838
        font = (char *) FamilyLookup[fontfamily];
 
839
        weight = WeightLookup[fontweight];
 
840
        style = StyleLookup[fontstyle];
 
841
        /* Need to add some error checking here */
 
842
        if (false) {
 
843
           fprintf(stderr, "fci = 0x%x, font name pointer = NULL \n", fci);
 
844
           plabort("proc_str: FCI inconsistent with TrueTypeLookup; "
 
845
                   "internal PLplot error");
 
846
           return;
 
847
        }
 
848
        /*pldebug("proc_str", "fci = 0x%x, font name = %s\n", fci, font);*/
 
849
        cur_text =  args->unicode_array;
 
850
        for (f=s=j=0; j < args->unicode_array_len; j++) {
 
851
           if (cur_text[j] & PL_FCI_MARK) {
 
852
              /* process an FCI by saving it and escaping cur_str
 
853
               * with an escff to make it a 2-character escape
 
854
               * that is not used in legacy Hershey code
 
855
               */
 
856
              if ((f < PROC_STR_STRING_LENGTH) && (s+3 < PROC_STR_STRING_LENGTH)) {
 
857
                 plP_fci2hex(cur_text[j],&fontfamily,PL_FCI_FAMILY);
 
858
                 plP_fci2hex(cur_text[j],&fontstyle,PL_FCI_STYLE);
 
859
                 plP_fci2hex(cur_text[j],&fontweight,PL_FCI_WEIGHT);
 
860
                 fonts[f] = (char *) FamilyLookup[fontfamily];
 
861
                 weights[f] = WeightLookup[fontweight];
 
862
                 styles[f] = StyleLookup[fontstyle];
 
863
                 if (fonts[f] == NULL) {
 
864
                    fprintf(stderr, "string-supplied FCI = 0x%x, font name pointer = NULL \n", cur_text[j]);
 
865
                    plabort("proc_str: string-supplied FCI inconsistent with font lookup;");
 
866
                    return;
 
867
                 }
 
868
                 /*pldebug("proc_str", "string-supplied FCI = 0x%x, font name = %s\n", cur_text[j], fonts[f]);*/
 
869
                 cur_str[s++] = esc;
 
870
                 cur_str[s++] = 'f';
 
871
                 cur_str[s++] = 'f';
 
872
                 f++;
 
873
              }
 
874
           }
 
875
           else if (s+1 < PROC_STR_STRING_LENGTH) {
 
876
              s += ucs4_to_utf8(cur_text[j],&cur_str[s]);
 
877
              /*pldebug("proc_str", "unicode = 0x%x, type 1 code = %d\n",
 
878
                        cur_text[j], cur_str[j]);*/
 
879
           }
 
880
        }
 
881
        cur_str[s] = '\0';
 
882
        
 
883
        /* finish previous polyline */
 
884
        
 
885
        dev->xold = PL_UNDEFINED;
 
886
        dev->yold = PL_UNDEFINED;
 
887
        
 
888
        /* Determine the font height */
 
889
        ft_ht = pls->chrht * 72.0/25.4; /* ft_ht in points, ht is in mm */
 
890
        
 
891
        
 
892
        /* The transform matrix has only rotations and shears; extract them */
 
893
        theta = acos(t[0]) * 180. / PI;  /* Determine the rotation (in degrees)... */
 
894
        if (t[2] < 0.) theta *= -1.;     /* ... and sign ... */
 
895
        cs = cos(theta*PI/180.);
 
896
        sn = sin(theta*PI/180.);
 
897
        tt[0] = t[0]*cs + t[2]*sn;
 
898
        tt[1] = t[1]*cs + t[3]*sn;
 
899
        tt[2] = -t[0]*sn + t[2]*cs;
 
900
        tt[3] = -t[1]*sn + t[3]*cs;
 
901
        
 
902
        /* 
 
903
         * Reference point conventions:
 
904
         *   If base = 0, it is aligned with the center of the text box
 
905
         *   If base = 1, it is aligned with the baseline of the text box
 
906
         *   If base = 2, it is aligned with the top of the text box
 
907
         *
 
908
         * Currently plplot only uses base=0
 
909
         * Postscript uses base=1
 
910
         *
 
911
         * We must calculate the difference between the two and apply the offset.
 
912
         */ 
 
913
        
 
914
        if (args->base == 2) /* not supported by plplot */
 
915
          offset = ENLARGE * ft_ht / 2.; /* half font height */
 
916
        else if (args->base == 1)
 
917
          offset = 0.;
 
918
        else
 
919
          offset = -ENLARGE * ft_ht / 2.;
 
920
        
 
921
        /* Determine the adjustment for page orientation */
 
922
        theta -= 90.*pls->diorot;
 
923
        args->y += (int) (offset*cos(theta*PI/180.));
 
924
        args->x -= (int) (offset*sin(theta*PI/180.));
 
925
                
 
926
        /* ps driver is rotated by default */
 
927
        plRotPhy(ORIENTATION, dev->xmin, dev->ymin, dev->xmax, dev->ymax, 
 
928
                 &(args->x), &(args->y));
 
929
        
 
930
        /* Correct for the fact ps driver uses landscape by default */
 
931
        theta += 90.;
 
932
        
 
933
        /* Output */
 
934
        /* Set clipping */
 
935
        clipx[0]=pls->clpxmi;
 
936
        clipx[2]=pls->clpxma;
 
937
        clipy[0]=pls->clpymi;
 
938
        clipy[2]=pls->clpyma;
 
939
        clipx[1]=clipx[2];
 
940
        clipy[1]=clipy[0];
 
941
        clipx[3]=clipx[0];
 
942
        clipy[3]=clipy[2];
 
943
        difilt(clipx, clipy, 4, &clxmin, &clxmax, &clymin, &clymax);
 
944
        plRotPhy(ORIENTATION, dev->xmin, dev->ymin, dev->xmax, dev->ymax,
 
945
                 &clipx[0], &clipy[0]);
 
946
        plRotPhy(ORIENTATION, dev->xmin, dev->ymin, dev->xmax, dev->ymax,
 
947
                 &clipx[1], &clipy[1]);
 
948
        plRotPhy(ORIENTATION, dev->xmin, dev->ymin, dev->xmax, dev->ymax,
 
949
                 &clipx[2], &clipy[2]);
 
950
        plRotPhy(ORIENTATION, dev->xmin, dev->ymin, dev->xmax, dev->ymax,
 
951
                 &clipx[3], &clipy[3]);
 
952
//      doc->osBody() << " gsave " << clipx[0] << " " << clipy[0] << " " << 
 
953
//        clipx[1] << " " << clipy[1] << " " << clipx[2] << " " << 
 
954
//        clipy[2] << " " << clipx[3] << " " << clipy[3] << " CL\n";
 
955
        
 
956
        /* move to string reference point */
 
957
        doc->osBody() << " " << args->x << " " << args->y << " M\n";
 
958
        
 
959
        /* Save the current position and set the string rotation */
 
960
        doc->osBody() << "gsave " << theta << " R\n";
 
961
 
 
962
        doc->osBody() << "[" << tt[0] << " " << tt[2] << " " << tt[1]
 
963
                      << " " << tt[3] << " 0 0] concat\n";
 
964
        
 
965
        /* Purge escape sequences from string, to find it's 
 
966
         * length. The string length is computed with the current font, 
 
967
         * and can thus be wrong if there are font change escape sequences 
 
968
         * in the string 
 
969
         */     
 
970
        esc_purge(str, cur_str);
 
971
 
 
972
        doc->setFont(font,style,weight);
 
973
        doc->setFontSize(font_factor*ENLARGE*ft_ht);
 
974
 
 
975
        // Get the approximate length of the string to calculate offset
 
976
        // Also used later for bounding box
 
977
        doc->get_dimensions((const char *)str, &lineSpacing, &xAdvance);
 
978
        xmin = -xAdvance*args->just;
 
979
        xmax = xmin;
 
980
        ymin = 0;
 
981
        ymax = 0;
 
982
 
 
983
        /* Move relative to position to account for justification */
 
984
        doc->osBody() << " gsave " << xmin*tt[0] << " " <<
 
985
          xmin*tt[2] << " rmoveto\n";
 
986
        
 
987
        /* Parse string for PLplot escape sequences and print everything out */
 
988
        
 
989
        cur_strp = cur_str;
 
990
        f = 0;
 
991
        do {
 
992
           
 
993
           strp = str;
 
994
           
 
995
           if (*cur_strp == esc) {
 
996
              cur_strp++;
 
997
              
 
998
              if (*cur_strp == esc) { /* <esc><esc> */
 
999
                 *strp++ = *cur_strp++;
 
1000
              }
 
1001
              else if (*cur_strp == 'f') {
 
1002
                 cur_strp++;
 
1003
                 if (*cur_strp++ != 'f') {
 
1004
                    /* escff occurs because of logic above. But any suffix
 
1005
                     * other than "f" should never happen. */
 
1006
                    plabort("proc_str, internal PLplot logic error;"
 
1007
                            "wrong escf escape sequence");
 
1008
                    return;
 
1009
                 }
 
1010
                 font = fonts[f];
 
1011
                 style = styles[f];
 
1012
                 weight = weights[f];
 
1013
                 f++;
 
1014
                 /*pldebug("proc_str", "string-specified fci = 0x%x, font name = %s\n", fci, font);*/
 
1015
                 continue;
 
1016
              }
 
1017
              else switch (*cur_strp++) {
 
1018
                 
 
1019
               case 'd':
 
1020
               case 'D':
 
1021
                 if(up>0.) scale *= 1.25;  /* Subscript scaling parameter */
 
1022
                 else scale *= 0.8;  /* Subscript scaling parameter */
 
1023
                 up -= font_factor * ENLARGE * ft_ht / 2.;
 
1024
                 break;
 
1025
                 
 
1026
               case 'u':
 
1027
               case 'U':
 
1028
                 if(up<0.) scale *= 1.25;  /* Subscript scaling parameter */
 
1029
                 else scale *= 0.8;  /* Subscript scaling parameter */
 
1030
                 up += font_factor * ENLARGE * ft_ht / 2.;
 
1031
                 break;
 
1032
                 
 
1033
                 /* ignore the next sequences */
 
1034
                 
 
1035
               case '+':
 
1036
               case '-':
 
1037
               case 'b':
 
1038
               case 'B':
 
1039
                 plwarn("'+', '-', and 'b/B' text escape sequences not processed.");
 
1040
                 break;
 
1041
              }
 
1042
           }
 
1043
           
 
1044
           /* copy from current to next token, adding a postscript escape 
 
1045
            * char '\' if necessary 
 
1046
            */
 
1047
           while(*cur_strp && *cur_strp != esc) {
 
1048
              *strp++ = *cur_strp++;
 
1049
           }
 
1050
           *strp = '\0';
 
1051
           
 
1052
           if(fabs(up)<0.001) up = 0.; /* Watch out for small differences */
 
1053
           
 
1054
           /* Set the font size */
 
1055
           doc->setFontSize(font_factor*ENLARGE*ft_ht*scale);
 
1056
           doc->setFont(font,style,weight);
 
1057
           doc->get_dimensions((const char *)str, &lineSpacing, &xAdvance, &ymintmp, &ymaxtmp);
 
1058
           ymin = MIN(ymintmp+up,ymin);
 
1059
           ymax = MAX(ymaxtmp+up,ymax);
 
1060
           xmax += xAdvance;
 
1061
 
 
1062
           /* if up/down escape sequences, save current point and adjust baseline;
 
1063
            * take the shear into account */
 
1064
           if(up!=0.) 
 
1065
             doc->osBody() << "gsave " << up*tt[1] << " " << up*tt[3] << " rmoveto\n";
 
1066
           
 
1067
           /* print the string */
 
1068
           doc->osBody() << show((const char *)str);
 
1069
           
 
1070
           /* back to baseline */
 
1071
           if (up!=0.) 
 
1072
             doc->osBody() << "grestore (" << str << ") stringwidth rmoveto\n";
 
1073
           
 
1074
        }while(*cur_strp);
 
1075
        
 
1076
        doc->osBody() << "grestore\n";
 
1077
        doc->osBody() << "grestore\n";
 
1078
        
 
1079
        /*
 
1080
         * Estimate text bounding box from LASi get_dimensions function.
 
1081
         * xmin, xmax are text left and right extents,
 
1082
         * ymin, ymax are top and bottom extents.
 
1083
         * These need to be rotated / transformed to get the correct values
 
1084
         */
 
1085
        xx[0] = (PLINT) (t[0]*xmin+t[1]*ymin);
 
1086
        yy[0] = (PLINT) (t[2]*xmin+t[3]*ymin);
 
1087
        xx[1] = (PLINT) (t[0]*xmin+t[1]*ymax);
 
1088
        yy[1] = (PLINT) (t[2]*xmin+t[3]*ymax);
 
1089
        xx[2] = (PLINT) (t[0]*xmax+t[1]*ymin);
 
1090
        yy[2] = (PLINT) (t[2]*xmax+t[3]*ymin);
 
1091
        xx[3] = (PLINT) (t[0]*xmax+t[1]*ymax);
 
1092
        yy[3] = (PLINT) (t[2]*xmax+t[3]*ymax);
 
1093
 
 
1094
        plRotPhy(ORIENTATION, 0,0,0,0, &xx[0], &yy[0]);
 
1095
        plRotPhy(ORIENTATION, 0,0,0,0, &xx[1], &yy[1]);
 
1096
        plRotPhy(ORIENTATION, 0,0,0,0, &xx[2], &yy[2]);
 
1097
        plRotPhy(ORIENTATION, 0,0,0,0, &xx[3], &yy[3]);
 
1098
 
 
1099
 
 
1100
        xmin = MIN(MIN(MIN(xx[0],xx[1]),xx[2]),xx[3])+args->x;
 
1101
        xmax = MAX(MAX(MAX(xx[0],xx[1]),xx[2]),xx[3])+args->x;
 
1102
        ymin = MIN(MIN(MIN(yy[0],yy[1]),yy[2]),yy[3])+args->y;
 
1103
        ymax = MAX(MAX(MAX(yy[0],yy[1]),yy[2]),yy[3])+args->y;
 
1104
        
 
1105
        dev->llx = (int) (MIN(dev->llx, xmin));
 
1106
        dev->lly = (int) (MIN(dev->lly, ymin));
 
1107
        dev->urx = (int) (MAX(dev->urx, xmax));
 
1108
        dev->ury = (int) (MAX(dev->ury, ymax));
 
1109
//      doc->osBody() << "Z " << xmin << " " << ymin << " M "
 
1110
//                    << xmin << " " << ymax << " D " 
 
1111
//                    << xmax << " " << ymax << " D " 
 
1112
//                    << xmax << " " << ymin << " D " 
 
1113
//                    << xmin << " " << ymin << " closepath\n"
 
1114
//                    << "Z " << args->x << " " << args->y << " A closepath\n";
 
1115
     }
 
1116
}
 
1117
 
 
1118
static void
 
1119
esc_purge(char *dstr, char *sstr) {
 
1120
  char esc;
 
1121
 
 
1122
  plgesc(&esc);
 
1123
 
 
1124
  while(*sstr){
 
1125
    if (*sstr != esc) {
 
1126
      *dstr++ = *sstr++;
 
1127
      continue;
 
1128
    }
 
1129
 
 
1130
    sstr++;
 
1131
    if (*sstr == esc) {
 
1132
      *dstr++ = *sstr++;
 
1133
      continue;
 
1134
    }
 
1135
     
 
1136
    else {
 
1137
      switch(*sstr++) {
 
1138
      case 'f':
 
1139
        sstr++;
 
1140
        break; /* two chars sequence */
 
1141
 
 
1142
      default:
 
1143
        break;  /* single char escape */
 
1144
      }
 
1145
    }
 
1146
  }
 
1147
  *dstr = '\0';
 
1148
}
 
1149
 
 
1150
#else
 
1151
int 
 
1152
pldummy_psttf()
 
1153
{
 
1154
    return 0;
 
1155
}
 
1156
 
 
1157
#endif                          /* defined(PLD_psttf) || .... */