PLplot 5.15.0
Loading...
Searching...
No Matches
pdf.c
Go to the documentation of this file.
1// PLplot driver for PDF based on the haru library http://www.libharu.org.
2//
3// Copyright (C) 2006, 2008 Werner Smekal
4//
5// This file is part of PLplot.
6//
7// PLplot is free software; you can redistribute it and/or modify
8// it under the terms of the GNU Library General Public License as published
9// by the Free Software Foundation; either version 2 of the License, or
10// (at your option) any later version.
11//
12// PLplot is distributed in the hope that it will be useful,
13// but WITHOUT ANY WARRANTY; without even the implied warranty of
14// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15// GNU Library General Public License for more details.
16//
17// You should have received a copy of the GNU Library General Public License
18// along with PLplot; if not, write to the Free Software
19// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20//
21//
22
23// TODO:
24// - page orientation
25// - text clipping
26//
27
28//--------------------------------------------------------------------------
29// Header files, defines and local variables
30//--------------------------------------------------------------------------
31#include "plDevs.h"
32
33#ifdef PLD_pdf
34
35#include <stdarg.h>
36#include <math.h>
37#include <setjmp.h>
38#include <strings.h>
39
40#include "hpdf.h"
41
42// PLplot header files
43//#define DEBUG
44//#define NEED_PLDEBUG
45#include "plplotP.h"
46#include "drivers.h"
47#include "plunicode-type1.h"
48#include "plfci-type1.h"
49
50// Workaround for caseless string comparison
51#ifndef _WIN32
52 #define stricmp strcasecmp
53 #define strnicmp strncasecmp
54#endif
55
56// constants
57
58// We define a virtual page and scale it down to the
59// paper size chosen by the user (A4 is default).
60//
61
62// Default dimensions of the canvas (in inches) and DPI
63#define CANVAS_WIDTH ( 50.0 )
64#define CANVAS_HEIGHT ( 37.5 )
65#define DEVICE_PIXELS_PER_INCH ( 72 )
66
67// mm per inch
68#define MM_PER_INCH ( 25.4 )
69
70// pixels per mm
71#define DEVICE_PIXELS_PER_MM ( DEVICE_PIXELS_PER_INCH / MM_PER_INCH )
72
73// maximum string length for own font handling
74#define MAX_STRING_LEN 1000
75
76// container for device specific data
77typedef struct
78{
79 HPDF_Doc pdf;
80 HPDF_Page page;
81 HPDF_PageSizes pageSize;
82 FILE *pdfFile;
83 PLFLT scalex, scaley;
84
85 // font variables
86 HPDF_Font m_font;
87 int nlookup, if_symbol_font;
88 const Unicode_to_Type1_table *lookup;
89 HPDF_REAL fontSize;
90 HPDF_REAL fontScale;
91 HPDF_REAL textWidth, textHeight;
92 HPDF_REAL yOffset;
93 HPDF_REAL textRed, textGreen, textBlue;
94} pdfdev;
95
96// local variables
97PLDLLIMPEXP_DRIVER const char* plD_DEVICE_INFO_pdf = "pdf:Portable Document Format PDF:1:pdf:58:pdf\n";
98static jmp_buf env;
99
100//--------------------------------------------------------------------------
101// function declarations
102//--------------------------------------------------------------------------
103
104// General
105//static short desired_offset( short, double );
106static void poly_line( PLStream *pls, short *xa, short *ya, PLINT npts, short fill );
107
108// String processing
109static void process_string( PLStream *, EscText * );
110
111// PLplot interface functions
113void plD_init_pdf( PLStream * );
114void plD_line_pdf( PLStream *, short, short, short, short );
115void plD_polyline_pdf( PLStream *, short *, short *, PLINT );
116void plD_eop_pdf( PLStream * );
117void plD_bop_pdf( PLStream * );
118void plD_tidy_pdf( PLStream * );
119void plD_state_pdf( PLStream *, PLINT );
120void plD_esc_pdf( PLStream *, PLINT, void * );
121void error_handler( HPDF_STATUS error_no, HPDF_STATUS detail_no, void *user_data );
122void PSDrawTextToCanvas( pdfdev* dev, unsigned char* type1_string, short drawText );
123void PSSetFont( pdfdev* dev, PLUNICODE fci );
124void PSDrawText( pdfdev* dev, PLUNICODE* ucs4, int ucs4Len, short drawText );
125
126//--------------------------------------------------------------------------
127// error_handler( HPDF_STATUS error_no, HPDF_STATUS detail_no,
128// void *user_data )
129//
130// Error handler for haru library.
131//--------------------------------------------------------------------------
132#ifdef HPDF_DLL
133void __stdcall
134#else
135void
136#endif
137error_handler( HPDF_STATUS error_no, HPDF_STATUS detail_no, void * PL_UNUSED( user_data ) )
138{
139 // invoke longjmp() when an error has occurred
140 printf( "ERROR: error_no=%04X, detail_no=%d\n", (unsigned int) error_no, (int) detail_no );
141 longjmp( env, 1 );
142}
143
144
145//--------------------------------------------------------------------------
146// plD_dispatch_init_pdf( PLDispatchTable *pdt )
147//
148// Initialize device dispatch table.
149//--------------------------------------------------------------------------
151{
152#ifndef ENABLE_DYNDRIVERS
153 pdt->pl_MenuStr = "Portable Document Format PDF";
154 pdt->pl_DevName = "pdf";
155#endif
157 pdt->pl_seq = 58;
158 pdt->pl_init = (plD_init_fp) plD_init_pdf;
159 pdt->pl_line = (plD_line_fp) plD_line_pdf;
160 pdt->pl_polyline = (plD_polyline_fp) plD_polyline_pdf;
161 pdt->pl_eop = (plD_eop_fp) plD_eop_pdf;
162 pdt->pl_bop = (plD_bop_fp) plD_bop_pdf;
163 pdt->pl_tidy = (plD_tidy_fp) plD_tidy_pdf;
164 pdt->pl_state = (plD_state_fp) plD_state_pdf;
165 pdt->pl_esc = (plD_esc_fp) plD_esc_pdf;
166}
167
168
169// driver specific options
170static PLINT text = 1;
171static PLINT compress = 1;
172static PLINT hrshsym = 1;
173static PLINT color = 1;
174static char * pageSize = NULL;
175
176DrvOpt pdf_options[] = {
177 { "text", DRV_INT, &text, "Use own text routines (text=0|1)" },
178 { "color", DRV_INT, &color, "Use color (color=0|1)" },
179 { "compress", DRV_INT, &compress, "Compress pdf output (compress=0|1)" },
180 { "hrshsym", DRV_INT, &hrshsym, "Use Hershey symbol set (hrshsym=0|1)" },
181 { "pagesize", DRV_STR, &pageSize, "Set page size (pagesize=A4|letter|A3|A5)" },
182 { NULL, DRV_INT, NULL, NULL }
183};
184
185
186//--------------------------------------------------------------------------
187// plD_init_pdf( PLStream *pls )
188//
189// Initialize device.
190//--------------------------------------------------------------------------
191void plD_init_pdf( PLStream *pls )
192{
193 pdfdev* dev;
194
195 // allocate memory for the device storage
196 dev = (pdfdev *) calloc( 1, sizeof ( pdfdev ) );
197 if ( dev == NULL )
198 plexit( "Insufficient memory\n" );
199 pls->dev = (void *) dev;
200
201 // Check for and set up driver options
202 plParseDrvOpts( pdf_options );
203
204 pls->termin = 0; // not an interactive device
205 if ( color )
206 pls->color = 1; // supports color
207 else
208 pls->color = 0; // monochrome
209 pls->width = 1;
210 pls->bytecnt = 0;
211
212 if ( text )
213 {
214 pls->dev_text = 1; // handles text
215 pls->dev_unicode = 1; // wants text as unicode
216 if ( hrshsym )
217 pls->dev_hrshsym = 1;
218 }
219
220 pls->page = 0;
221 pls->dev_fill0 = 1; // supports hardware solid fills
222 pls->dev_fill1 = 0; // Use PLplot core fallback for pattern fills
223
225
226 if ( !pls->colorset )
227 pls->color = 1;
228
229 // Set the (virtual) page size. The geometry option is
230 // neglected. Page sizes are set with the pagesize option.
231 plspage( DEVICE_PIXELS_PER_INCH, DEVICE_PIXELS_PER_INCH,
232 (PLINT) ( CANVAS_WIDTH * DEVICE_PIXELS_PER_INCH ), (PLINT) ( CANVAS_HEIGHT * DEVICE_PIXELS_PER_INCH ), 0, 0 );
233
234 // Set up physical limits of plotting device (in drawing units)
235 plP_setphy( 0, (PLINT) ( CANVAS_WIDTH * DEVICE_PIXELS_PER_INCH ),
236 0, (PLINT) ( CANVAS_HEIGHT * DEVICE_PIXELS_PER_INCH ) );
237
238 // Set the number of pixels per mm
239 plP_setpxl( (PLFLT) DEVICE_PIXELS_PER_MM, (PLFLT) DEVICE_PIXELS_PER_MM );
240
241 // If portrait mode is specified, then set up an additional rotation
242 // transformation with aspect ratio allowed to adjust via freeaspect.
243 // Default orientation is landscape (ORIENTATION == 3 or 90 deg rotation
244 // counter-clockwise from portrait). (Legacy PLplot used seascape
245 // which was equivalent to ORIENTATION == 1 or 90 deg clockwise rotation
246 // from portrait.)
247 if ( pls->portrait )
248 {
249 plsdiori( (PLFLT) ( 4 - ORIENTATION ) );
250 pls->freeaspect = 1;
251 }
252
253 // Initialize family file info
254 plFamInit( pls );
255
256 // Prompt for a file name if not already set
257 plOpenFile( pls );
258 dev->pdfFile = pls->OutFile;
259
260 dev->pdf = HPDF_New( error_handler, NULL );
261 if ( !dev->pdf )
262 plexit( "ERROR: cannot create pdf object.\n" );
263
264 if ( compress )
265 HPDF_SetCompressionMode( dev->pdf, HPDF_COMP_ALL );
266
267 // determine size of pdf page - A4 is default
268 dev->pageSize = HPDF_PAGE_SIZE_EOF;
269 if ( pageSize == NULL )
270 dev->pageSize = HPDF_PAGE_SIZE_A4;
271 else if ( !stricmp( pageSize, "letter" ) )
272 dev->pageSize = HPDF_PAGE_SIZE_LETTER;
273 else if ( !stricmp( pageSize, "A3" ) )
274 dev->pageSize = HPDF_PAGE_SIZE_A3;
275 else if ( !stricmp( pageSize, "A4" ) )
276 dev->pageSize = HPDF_PAGE_SIZE_A4;
277 else if ( !stricmp( pageSize, "A5" ) )
278 dev->pageSize = HPDF_PAGE_SIZE_A5;
279
280 if ( dev->pageSize == HPDF_PAGE_SIZE_EOF )
281 plexit( "ERROR: Unknown page size. Allowed strings are: letter, A3, A4, A5.\n" );
282
283 if ( setjmp( env ) )
284 {
285 // HPDF_Free segfaults after error so skip this nicety.
286 //HPDF_Free( dev->pdf );
287 // can't call plexit because that appears to be circular via
288 // what happens with plend. Therefore, print out an error message
289 // and exit.
290 fprintf( stderr, "ERROR in haru library\n" );
291 exit( 1 );
292 }
293}
294
295//--------------------------------------------------------------------------
296// plD_bop_pdf( PLStream *pls )
297//
298// Set up for the next page.
299//--------------------------------------------------------------------------
300void plD_bop_pdf( PLStream *pls )
301{
302 pdfdev * dev = (pdfdev *) pls->dev;
303 HPDF_REAL width, height;
304
305 pls->page++;
306
307 // add page and set size (default is A4)
308 dev->page = HPDF_AddPage( dev->pdf );
309 if ( pls->portrait )
310 HPDF_Page_SetSize( dev->page, dev->pageSize, HPDF_PAGE_PORTRAIT );
311 else
312 HPDF_Page_SetSize( dev->page, dev->pageSize, HPDF_PAGE_LANDSCAPE );
313
314 // Determine scaling parameters.
315 width = HPDF_Page_GetWidth( dev->page ); // in pixels/dots
316 height = HPDF_Page_GetHeight( dev->page ); // in pixels/dots
317 dev->scalex = (PLFLT) ( width / ( CANVAS_WIDTH * DEVICE_PIXELS_PER_INCH ) );
318 dev->scaley = (PLFLT) ( height / ( CANVAS_HEIGHT * DEVICE_PIXELS_PER_INCH ) );
319 HPDF_Page_Concat( dev->page, (HPDF_REAL) ( dev->scalex ), 0, 0, (HPDF_REAL) ( dev->scaley ), 0, 0 );
320
321 // Set the background by drawing a rectangle that is the size of
322 // of the canvas and filling it with the background color.
323 HPDF_Page_SetRGBFill( dev->page, (HPDF_REAL) ( pls->cmap0[0].r / 255.0 ),
324 (HPDF_REAL) ( pls->cmap0[0].g / 255.0 ), (HPDF_REAL) ( pls->cmap0[0].b / 255.0 ) );
325 width /= (HPDF_REAL) ( dev->scalex );
326 height /= (HPDF_REAL) ( dev->scaley );
327 HPDF_Page_MoveTo( dev->page, (HPDF_REAL) 0.0, (HPDF_REAL) 0.0 );
328 HPDF_Page_LineTo( dev->page, width, (HPDF_REAL) 0.0 );
329 HPDF_Page_LineTo( dev->page, width, (HPDF_REAL) height );
330 HPDF_Page_LineTo( dev->page, 0.0, (HPDF_REAL) height );
331 HPDF_Page_Fill( dev->page );
332}
333
334
335//--------------------------------------------------------------------------
336// pdf_line()
337//
338// Draw a line in the current color from (x1,y1) to (x2,y2).
339//--------------------------------------------------------------------------
340void plD_line_pdf( PLStream *pls, short x1a, short y1a, short x2a, short y2a )
341{
342 short xa[2], ya[2];
343
344 xa[0] = x1a; xa[1] = x2a;
345 ya[0] = y1a; ya[1] = y2a;
346
347 poly_line( pls, xa, ya, 2, 0 );
348}
349
350
351//--------------------------------------------------------------------------
352// pdf_polyline()
353//
354// Draw a polyline in the current color.
355//--------------------------------------------------------------------------
356void plD_polyline_pdf( PLStream *pls, short *xa, short *ya, PLINT npts )
357{
358 poly_line( pls, xa, ya, npts, 0 );
359}
360
361
362//--------------------------------------------------------------------------
363// pdf_eop()
364//
365// End of page
366//--------------------------------------------------------------------------
367void plD_eop_pdf( PLStream * PL_UNUSED( pls ) )
368{
369 // nothing to be done here
370}
371
372
373//--------------------------------------------------------------------------
374// pdf_tidy()
375//
376// Close graphics file or otherwise clean up.
377//--------------------------------------------------------------------------
378void plD_tidy_pdf( PLStream *pls )
379{
380 pdfdev* dev = (pdfdev *) pls->dev;
381
382 // save the document to a stream
383 HPDF_SaveToStream( dev->pdf );
384
385 // rewind the stream.
386 HPDF_ResetStream( dev->pdf );
387
388 // get the data from the stream and output it to stdout.
389 for (;; )
390 {
391 HPDF_BYTE buf[4096]; // TODO: not good
392 HPDF_UINT32 size = 4096;
393 // HPDF_STATUS ret = HPDF_ReadFromStream( dev->pdf, buf, &size );
394 HPDF_ReadFromStream( dev->pdf, buf, &size );
395
396 if ( size == 0 )
397 break;
398
399 if ( fwrite( buf, size, 1, dev->pdfFile ) != 1 )
400 plexit( "ERROR: Cannot write to file!" );
401 }
402
403 plCloseFile( pls );
404
405 // cleanup
406 HPDF_Free( dev->pdf );
407}
408
409
410//--------------------------------------------------------------------------
411// plD_state_pdf()
412//
413// Handle change in PLStream state (color, pen width, fill attribute, etc).
414//
415// Nothing is done here because these attributes are aquired from
416// PLStream for each element that is drawn.
417//--------------------------------------------------------------------------
418void plD_state_pdf( PLStream * PL_UNUSED( pls ), PLINT PL_UNUSED( op ) )
419{
420 // Nothing to be done here.
421}
422
423
424//--------------------------------------------------------------------------
425// pdf_esc()
426//
427// Escape function.
428//--------------------------------------------------------------------------
429void plD_esc_pdf( PLStream *pls, PLINT op, void *ptr )
430{
431 switch ( op )
432 {
433 case PLESC_FILL: // fill polygon
435 break;
436 case PLESC_HAS_TEXT: // render text
437 process_string( pls, (EscText *) ptr );
438 break;
439 }
440}
441
442
443//--------------------------------------------------------------------------
444// poly_line()
445//
446// Handles drawing filled and unfilled polygons
447//--------------------------------------------------------------------------
448void poly_line( PLStream *pls, short *xa, short *ya, PLINT npts, short fill )
449{
450 pdfdev* dev = (pdfdev *) pls->dev;
451 PLINT i;
452
453 HPDF_Page_SetLineWidth( dev->page, (HPDF_REAL) ( pls->width ) );
454 HPDF_Page_SetLineCap( dev->page, HPDF_ROUND_END );
455 HPDF_Page_SetLineJoin( dev->page, HPDF_ROUND_JOIN );
456 HPDF_Page_SetRGBStroke( dev->page, (HPDF_REAL) ( pls->curcolor.r / 255.0 ),
457 (HPDF_REAL) ( pls->curcolor.g / 255.0 ), (HPDF_REAL) ( pls->curcolor.b / 255.0 ) );
458 HPDF_Page_SetRGBFill( dev->page, (HPDF_REAL) ( pls->curcolor.r / 255.0 ),
459 (HPDF_REAL) ( pls->curcolor.g / 255.0 ), (HPDF_REAL) ( pls->curcolor.b / 255.0 ) );
460
461 HPDF_Page_MoveTo( dev->page, (HPDF_REAL) xa[0], (HPDF_REAL) ya[0] );
462 for ( i = 1; i < npts; i++ )
463 HPDF_Page_LineTo( dev->page, (HPDF_REAL) xa[i], (HPDF_REAL) ya[i] );
464
465 if ( fill == 1 )
466 {
467 if ( pls->dev_eofill )
468 HPDF_Page_EofillStroke( dev->page );
469 else
470 HPDF_Page_FillStroke( dev->page );
471 }
472 else
473 {
474 HPDF_Page_Stroke( dev->page );
475 }
476}
477
478
479//--------------------------------------------------------------------------
480// unsigned char plunicode2type1 (const PLUNICODE index,
481// const Unicode_to_Type1_table lookup[], const int number_of_entries)
482//
483// Function takes an input unicode index, looks through the lookup
484// table (which must be sorted by PLUNICODE Unicode), then returns the
485// corresponding Type1 code in the lookup table. If the Unicode index
486// is not present the returned value is 32 (which is normally a blank
487// for Type 1 fonts).
488//--------------------------------------------------------------------------
489static unsigned char plunicode2type1( const PLUNICODE index,
490 const Unicode_to_Type1_table lookup[],
491 const int nlookup )
492{
493 int jlo = -1, jmid, jhi = nlookup;
494
495 while ( jhi - jlo > 1 )
496 {
497 // Note that although jlo or jhi can be just outside valid
498 // range (see initialization above) because of while condition
499 // jlo < jmid < jhi and jmid must be in valid range.
500 //
501 jmid = ( jlo + jhi ) / 2;
502 if ( index > lookup[jmid].Unicode )
503 jlo = jmid;
504 else if ( index < lookup[jmid].Unicode )
505 jhi = jmid;
506 else
507 // We have found it!
508 // index == lookup[jmid].Unicode
509 //
510 return ( lookup[jmid].Type1 );
511 }
512 // jlo is invalid or it is valid and index > lookup[jlo].Unicode.
513 // jhi is invalid or it is valid and index < lookup[jhi].Unicode.
514 // All these conditions together imply index cannot be found in lookup.
515 // Mark with ' ' (which is normally the index for blank in type 1 fonts).
516 //
517 return ( ' ' );
518}
519
520
521//--------------------------------------------------------------------------
522// PSDrawTextToCanvas( pdfdev* dev, unsigned char* type1_string, short drawText )
523//
524// This function determines the extent of the string and does
525// the actual drawing to the page if drawText is true.
526//--------------------------------------------------------------------------
527void PSDrawTextToCanvas( pdfdev* dev, unsigned char* type1_string, short drawText )
528{
529 HPDF_REAL th;
530
531 // write text to page
532 if ( drawText )
533 {
534 HPDF_Page_BeginText( dev->page );
535 HPDF_Page_SetTextRenderingMode( dev->page, HPDF_FILL );
536 HPDF_Page_SetRGBFill( dev->page, dev->textRed, dev->textGreen, dev->textBlue );
537 HPDF_Page_MoveTextPos( dev->page, dev->textWidth, dev->yOffset );
538 HPDF_Page_ShowText( dev->page, (char *) type1_string ); // TODO: this conversion must be wrong
539 HPDF_Page_EndText( dev->page );
540 }
541
542 // determine text width and height
543 dev->textWidth += HPDF_Page_TextWidth( dev->page, (char *) type1_string ); // TODO: this conversion must be wrong
544 th = (HPDF_REAL) ( (HPDF_REAL) HPDF_Font_GetCapHeight( dev->m_font ) * dev->fontSize * dev->fontScale / 1000.0 );
545 dev->textHeight = dev->textHeight > ( th + dev->yOffset ) ? dev->textHeight : ( th + dev->yOffset );
546
547 // clear string
548 memset( type1_string, '\0', MAX_STRING_LEN );
549}
550
551
552//--------------------------------------------------------------------------
553// PSSetFont( pdfdev* dev, PLUNICODE fci )
554//
555// Sets the font.
556//--------------------------------------------------------------------------
557void PSSetFont( pdfdev* dev, PLUNICODE fci )
558{
559 const char *font;
560
561 // fci = 0 is a special value indicating the Type 1 Symbol font
562 // is desired. This value cannot be confused with a normal FCI value
563 // because it doesn't have the PL_FCI_MARK.
564 if ( fci == 0 )
565 {
566 font = "Symbol";
568 dev->lookup = unicode_to_symbol_lookup_table;
569 dev->if_symbol_font = 1;
570 }
571 else
572 {
573 // convert the fci to Base14/Type1 font information
577 dev->if_symbol_font = 0;
578 }
579
580 if ( !( dev->m_font = HPDF_GetFont( dev->pdf, font, NULL ) ) )
581 plexit( "ERROR: Couldn't open font\n" );
582 //pldebug( "PSSetFont", "HPDF requested font size = %f\n", dev->fontSize * dev->fontScale );
583 HPDF_Page_SetFontAndSize( dev->page, dev->m_font, dev->fontSize * dev->fontScale );
584}
585
586// 0.8 should mimic the offset of first superscript/subscript level
587// implemented in plstr (plsym.c) for Hershey fonts. However, when
588// comparing with -dev xwin and -dev xcairo results changing this
589// factor to 0.6 appears to offset the centers of the letters
590// appropriately while 0.8 gives much poorer agreement with the
591// other devices.
592# define RISE_FACTOR 0.6
593
594//--------------------------------------------------------------------------
595// PSDrawText( pdfdev* dev, PLUNICODE* ucs4, int ucs4Len, short drawText )
596//
597// This function is called twice, first to determine the extent of the
598// text written to the page and then a second time to actually draw
599// the text.
600//--------------------------------------------------------------------------
601void PSDrawText( pdfdev* dev, PLUNICODE* ucs4, int ucs4Len, short drawText )
602{
603 int i, s;
604 unsigned char type1_string[MAX_STRING_LEN];
605 char plplotEsc;
606 PLUNICODE fci;
607 int last_chance = 0;
608 PLFLT old_sscale, sscale, old_soffset, soffset, dup;
609 PLINT level = 0;
610
611 memset( type1_string, '\0', MAX_STRING_LEN );
612
613 // Get PLplot escape character
614 plgesc( &plplotEsc );
615
616 // Get the current font
617 dev->fontScale = 1.0;
618 dev->yOffset = 0.0;
619 plgfci( &fci );
620 PSSetFont( dev, fci );
621 dev->textWidth = 0;
622 dev->textHeight = 0;
623
624 i = 0; s = 0;
625 while ( i < ucs4Len )
626 {
627 if ( ucs4[i] < PL_FCI_MARK ) // not a font change
628 {
629 if ( ucs4[i] != (PLUNICODE) plplotEsc ) // a character to display
630 {
631 type1_string[s] = plunicode2type1( ucs4[i], dev->lookup, dev->nlookup );
632 if ( ucs4[i] != ' ' && type1_string[s] == ' ' )
633 {
634 // failed lookup
635 if ( !dev->if_symbol_font )
636 {
637 // failed standard font lookup. Try "last chance"
638 // symbol font instead.
639 type1_string[s] = '\0';
640 PSDrawTextToCanvas( dev, type1_string, drawText );
641 s = 0;
642 last_chance = 1;
643 PSSetFont( dev, 0 );
644 continue;
645 }
646 else if ( !last_chance )
647 {
648 // failed symbol font lookup that is not right
649 // after a failed standard font lookup (i.e.,
650 // last_change = 0). Try standard fonts lookup instead.
651 type1_string[s] = '\0';
652 PSDrawTextToCanvas( dev, type1_string, drawText );
653 s = 0;
654 last_chance = 0;
655 PSSetFont( dev, fci );
656 continue;
657 }
658 else
659 {
660 // failed "last_chance" symbol font lookup that
661 // has occurred right after a failed standard
662 // fonts lookup. Just accept blank result and
663 // move on using standard fonts.
664 PSDrawTextToCanvas( dev, type1_string, drawText );
665 s = 0;
666 last_chance = 0;
667 PSSetFont( dev, fci );
668 i++;
669 continue;
670 }
671 }
672 else
673 {
674 // font lookup succeeded.
675 s++;
676 i++;
677 last_chance = 0;
678 continue;
679 }
680 }
681 i++;
682 if ( ucs4[i] == (PLUNICODE) plplotEsc ) // a escape character to display
683 {
684 type1_string[s] = plunicode2type1( ucs4[i], dev->lookup, dev->nlookup );
685 if ( ucs4[i] != ' ' && type1_string[s] == ' ' )
686 {
687 // failed lookup
688 if ( !dev->if_symbol_font )
689 {
690 // failed standard font lookup. Try "last chance"
691 // symbol font instead.
692 type1_string[s] = '\0';
693 PSDrawTextToCanvas( dev, type1_string, drawText );
694 s = 0;
695 last_chance = 1;
696 PSSetFont( dev, 0 );
697 continue;
698 }
699 else if ( !last_chance )
700 {
701 // failed symbol font lookup that is not right
702 // after a failed standard font lookup (i.e.,
703 // last_change = 0). Try standard fonts lookup instead.
704 type1_string[s] = '\0';
705 PSDrawTextToCanvas( dev, type1_string, drawText );
706 s = 0;
707 last_chance = 0;
708 PSSetFont( dev, fci );
709 continue;
710 }
711 else
712 {
713 // failed "last_chance" symbol font lookup that
714 // has occurred right after a failed standard
715 // fonts lookup. Just accept blank result and
716 // move on using standard fonts.
717 PSDrawTextToCanvas( dev, type1_string, drawText );
718 s = 0;
719 last_chance = 0;
720 PSSetFont( dev, fci );
721 i++;
722 continue;
723 }
724 }
725 else
726 {
727 // font lookup succeeded.
728 s++;
729 i++;
730 last_chance = 0;
731 continue;
732 }
733 }
734 else
735 {
736 if ( ucs4[i] == (PLUNICODE) 'u' ) // Superscript
737 {
738 // draw string so far
739 PSDrawTextToCanvas( dev, type1_string, drawText );
740 s = 0;
741
742 plP_script_scale( TRUE, &level,
743 &old_sscale, &sscale, &old_soffset, &soffset );
744 // The correction for the difference in magnitude
745 // between the baseline and middle coordinate systems
746 // for superscripts should be
747 // 0.5*(base font size - superscript/subscript font size).
748 dup = 0.5 * ( 1.0 - sscale );
749 dev->fontScale = (HPDF_REAL) sscale;
750 PSSetFont( dev, fci );
751 dev->yOffset = (HPDF_REAL) ( dev->fontSize * ( soffset * RISE_FACTOR + dup ) );
752 }
753 if ( ucs4[i] == (PLUNICODE) 'd' ) // Subscript
754 {
755 // draw string so far
756 PSDrawTextToCanvas( dev, type1_string, drawText );
757 s = 0;
758
759 plP_script_scale( FALSE, &level,
760 &old_sscale, &sscale, &old_soffset, &soffset );
761 // The correction for the difference in magnitude
762 // between the baseline and middle coordinate systems
763 // for subcripts should be
764 // 0.5*(base font size - superscript/subscript font size).
765 dup = -0.5 * ( 1.0 - sscale );
766 dev->fontScale = (HPDF_REAL) sscale;
767 PSSetFont( dev, fci );
768 dev->yOffset = (HPDF_REAL) ( -dev->fontSize * ( soffset * RISE_FACTOR + dup ) );
769 }
770 if ( ucs4[i] == (PLUNICODE) '-' ) // underline
771 { // draw string so far
772 PSDrawTextToCanvas( dev, type1_string, drawText );
773 s = 0;
774
775 // dev->underlined = !dev->underlined;
776 PSSetFont( dev, fci );
777 }
778 if ( ucs4[i] == (PLUNICODE) '+' ) // overline
779 { // not implemented yet
780 }
781 i++;
782 }
783 }
784 else // a font change
785 {
786 // draw string so far
787 PSDrawTextToCanvas( dev, type1_string, drawText );
788 s = 0;
789
790 // get new font
791 fci = ucs4[i];
792 PSSetFont( dev, fci );
793 i++;
794 }
795 }
796
797 PSDrawTextToCanvas( dev, type1_string, drawText );
798}
799
800
801//--------------------------------------------------------------------------
802// process_string( PLStream* pls, EscText* args )
803//
804// Handles the output of the text on the page.
805//--------------------------------------------------------------------------
806void process_string( PLStream* pls, EscText* args )
807{
808 pdfdev * dev = (pdfdev *) pls->dev;
809 PLFLT rotation, shear, stride;
810 HPDF_REAL cos_rot, sin_rot, cos_shear, sin_shear;
811
812 // Check that we got unicode, warning message and return if not
813 if ( args->unicode_array_len == 0 )
814 {
815 printf( "Non unicode string passed to a pdf driver, ignoring\n" );
816 return;
817 }
818
819 // Check that unicode string isn't longer then the max we allow
820 if ( args->unicode_array_len >= MAX_STRING_LEN )
821 {
822 printf( "Sorry, the pdf drivers only handles strings of length < %d\n", MAX_STRING_LEN );
823 return;
824 }
825
826 // Calculate the font size (in pixels)
827 dev->fontSize = (HPDF_REAL) ( pls->chrht * DEVICE_PIXELS_PER_INCH / 25.4 * 1.6 );
828
829 // text color
830 dev->textRed = (HPDF_REAL) ( pls->curcolor.r / 255.0 );
831 dev->textGreen = (HPDF_REAL) ( pls->curcolor.g / 255.0 );
832 dev->textBlue = (HPDF_REAL) ( pls->curcolor.b / 255.0 );
833
834 // calculate transformation matrix (rotation and shear of text)
835 plRotationShear( args->xform, &rotation, &shear, &stride );
836 rotation -= pls->diorot * M_PI / 2.0;
837 cos_rot = (HPDF_REAL) cos( rotation );
838 sin_rot = (HPDF_REAL) sin( rotation );
839 cos_shear = (HPDF_REAL) cos( shear );
840 sin_shear = (HPDF_REAL) sin( shear );
841
842 // calculate text extend -> stored in dev->textWidth and dev->textHeight
843 PSDrawText( dev, args->unicode_array, args->unicode_array_len, 0 );
844
845 // apply transformation matrix and draw text
846 HPDF_Page_GSave( dev->page );
847 HPDF_Page_Concat( dev->page, cos_rot, sin_rot,
848 -cos_rot * sin_shear - sin_rot * cos_shear,
849 -sin_rot * sin_shear + cos_rot * cos_shear,
850 (HPDF_REAL) ( args->x ), (HPDF_REAL) ( args->y ) );
851 HPDF_Page_Concat( dev->page, (HPDF_REAL) 1.0, (HPDF_REAL) 0.0, (HPDF_REAL) 0.0, (HPDF_REAL) 1.0,
852 (HPDF_REAL) ( -args->just * dev->textWidth ), (HPDF_REAL) ( -0.5 * dev->textHeight ) );
853 PSDrawText( dev, args->unicode_array, args->unicode_array_len, 1 );
854 HPDF_Page_GRestore( dev->page );
855}
856
857#else
858
859//--------------------------------------------------------------------------
860// pldummy_pdf()
861//
862// Dummy function if driver should not be available.
863//--------------------------------------------------------------------------
865{
866 return 0;
867}
868
869#endif // PLD_pdf
870
#define MAX_STRING_LEN
Definition aqt.c:47
#define RISE_FACTOR
Definition cairo.c:1226
static void poly_line(PLStream *, short *, short *, PLINT)
Definition cairo.c:1430
@ plDevType_FileOriented
Definition disptab.h:13
void(* plD_line_fp)(struct PLStream_struct *, short, short, short, short)
Definition disptab.h:68
void(* plD_tidy_fp)(struct PLStream_struct *)
Definition disptab.h:72
void(* plD_bop_fp)(struct PLStream_struct *)
Definition disptab.h:71
void(* plD_state_fp)(struct PLStream_struct *, PLINT)
Definition disptab.h:73
void(* plD_eop_fp)(struct PLStream_struct *)
Definition disptab.h:70
void(* plD_init_fp)(struct PLStream_struct *)
Definition disptab.h:67
void(* plD_esc_fp)(struct PLStream_struct *, PLINT, void *)
Definition disptab.h:74
void(* plD_polyline_fp)(struct PLStream_struct *, short *, short *, PLINT)
Definition disptab.h:69
PLDLLIMPEXP_DRIVER void plD_dispatch_init_pdf(PLDispatchTable *pdt)
int pldummy_pdf()
Definition pdf.c:864
int plParseDrvOpts(DrvOpt *acc_opt)
Definition plargs.c:1461
void plP_setpxl(PLFLT xpmm, PLFLT ypmm)
Definition plcore.c:4238
void plgesc(char *p_esc)
Definition plcore.c:3914
void plP_setphy(PLINT xmin, PLINT xmax, PLINT ymin, PLINT ymax)
Definition plcore.c:4249
static PLStream * pls[PL_NSTREAMS]
Definition plcore.h:88
void plFamInit(PLStream *pls)
Definition plctrl.c:2751
void plCloseFile(PLStream *pls)
Definition plctrl.c:2635
void plOpenFile(PLStream *pls)
Definition plctrl.c:2571
void plexit(PLCHAR_VECTOR errormsg)
Definition plctrl.c:1958
#define PLDLLIMPEXP_DRIVER
Definition pldll.h:81
static const FCI_to_FontName_Table Type1Lookup[N_Type1Lookup]
Definition plfci-type1.h:42
#define N_Type1Lookup
Definition plfci-type1.h:41
void plRotationShear(PLFLT *xFormMatrix, PLFLT *rotation, PLFLT *shear, PLFLT *stride)
Definition plot3d.c:2767
#define GRAPHICS_MODE
Definition plplotP.h:288
@ DRV_INT
Definition plplotP.h:758
@ DRV_STR
Definition plplotP.h:758
#define TRUE
Definition plplotP.h:176
#define FALSE
Definition plplotP.h:177
#define ORIENTATION
Definition plplotP.h:358
#define M_PI
Definition plplotP.h:119
#define plgfci
Definition plplot.h:735
#define PLESC_HAS_TEXT
Definition plplot.h:290
PLUINT PLUNICODE
Definition plplot.h:201
float PLFLT
Definition plplot.h:163
#define PL_UNUSED(x)
Definition plplot.h:138
#define plsdiori
Definition plplot.h:809
#define plspage
Definition plplot.h:831
#define PLESC_FILL
Definition plplot.h:279
int PLINT
Definition plplot.h:181
#define PL_FCI_MARK
Definition plplot.h:370
PLCHAR_VECTOR plP_FCI2FontName(PLUNICODE fci, const FCI_to_FontName_Table lookup[], const int nlookup)
Definition plsym.c:1548
void plP_script_scale(PLBOOL ifupper, PLINT *level, PLFLT *old_scale, PLFLT *scale, PLFLT *old_offset, PLFLT *offset)
Definition plsym.c:1302
static const Unicode_to_Type1_table unicode_to_symbol_lookup_table[194]
static const int number_of_entries_in_unicode_to_standard_table
static const int number_of_entries_in_unicode_to_symbol_table
static const Unicode_to_Type1_table unicode_to_standard_lookup_table[154]
static int color
Definition ps.c:78
static unsigned char plunicode2type1(const PLUNICODE index, const Unicode_to_Type1_table lookup[], const int number_of_entries)
Definition ps.c:1172
static int hrshsym
Definition ps.c:79
static int text
Definition ps.c:77
unsigned char r
Definition plplot.h:548
unsigned char g
Definition plplot.h:549
unsigned char b
Definition plplot.h:550
plD_eop_fp pl_eop
Definition disptab.h:86
const char * pl_DevName
Definition disptab.h:80
plD_esc_fp pl_esc
Definition disptab.h:90
plD_polyline_fp pl_polyline
Definition disptab.h:85
plD_state_fp pl_state
Definition disptab.h:89
plD_tidy_fp pl_tidy
Definition disptab.h:88
plD_line_fp pl_line
Definition disptab.h:84
plD_init_fp pl_init
Definition disptab.h:83
plD_bop_fp pl_bop
Definition disptab.h:87
const char * pl_MenuStr
Definition disptab.h:79
PLINT bytecnt
Definition plstrm.h:578
PLColor * cmap0
Definition plstrm.h:544
PLINT dev_fill0
Definition plstrm.h:571
PLINT dev_hrshsym
Definition plstrm.h:753
PLINT page
Definition plstrm.h:578
PLINT dev_npts
Definition plstrm.h:581
PLINT color
Definition plstrm.h:569
short * dev_y
Definition plstrm.h:582
PLFLT width
Definition plstrm.h:552
FILE * OutFile
Definition plstrm.h:575
short * dev_x
Definition plstrm.h:582
PLFLT chrht
Definition plstrm.h:686
PLINT dev_unicode
Definition plstrm.h:747
PLColor curcolor
Definition plstrm.h:543
PLINT freeaspect
Definition plstrm.h:665
PLINT dev_text
Definition plstrm.h:572
PLINT termin
Definition plstrm.h:568
void * dev
Definition plstrm.h:594
PLINT portrait
Definition plstrm.h:665
PLINT graphx
Definition plstrm.h:568
PLINT dev_fill1
Definition plstrm.h:571
PLINT colorset
Definition plstrm.h:569
PLINT dev_eofill
Definition plstrm.h:788
PLFLT diorot
Definition plstrm.h:661
static char buf[200]
Definition tclAPI.c:873