PLplot: plsym.c Source File

PLplot 5.15.0

plsym.c
Go to the documentation of this file.
1 // Point, symbol, and string plotting routines.
2 // Also font management code. See the description of plLibOpen() for
3 // the search path used in finding the font files.
4 //
5 // Copyright (C) 1992 Geoffrey Furnish
6 // Copyright (C) 1993-2002 Maurice LeBrun
7 // Copyright (C) 1996 Rady Shouman
8 // Copyright (C) 2000-2019 Alan W. Irwin
9 // Copyright (C) 2001 Joao Cardoso
10 // Copyright (C) 2002 Vince Darley
11 // Copyright (C) 2003-2005 Rafael Laboissiere
12 // Copyright (C) 2004-2005 Andrew Roach
13 // Copyright (C) 2004-2011 Andrew Ross
14 // Copyright (C) 2005 Thomas Duck
15 // Copyright (C) 2006-2010 Hazen Babcock
16 // Copyright (C) 2009 Werner Smekal
17 // Copyright (C) 2010 Hezekiah M. Carty
18 // Copyright (C) 2015 Phil Rosenberg
19 // Copyright (C) 2015 jdishaw
20 //
21 // This file is part of PLplot.
22 //
23 // PLplot is free software; you can redistribute it and/or modify
24 // it under the terms of the GNU Library General Public License as published
25 // by the Free Software Foundation; either version 2 of the License, or
26 // (at your option) any later version.
27 //
28 // PLplot is distributed in the hope that it will be useful,
29 // but WITHOUT ANY WARRANTY; without even the implied warranty of
30 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31 // GNU Library General Public License for more details.
32 //
33 // You should have received a copy of the GNU Library General Public License
34 // along with PLplot; if not, write to the Free Software
35 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
36 //
37
42
43 #ifndef __PLSYM_H__
44 #define __PLSYM_H__
45 #define DEBUG
46 #define NEED_PLDEBUG
47
48 #include "plplotP.h"
49 #include <float.h>
50 #include <ctype.h>
51 #include "plhershey-unicode.h"
52
53 // Declarations
54
55 static short int *fntlkup;
56 static short int *fntindx;
57 static signed char *fntbffr;
58 static short int numberfonts, numberchars;
59 static short int indxleng;
60
61 static short fontloaded = 0;
62 // moved to plstr.h, plsc->cfont static PLINT font = 1; current font
63
64 #define PLMAXSTR 300
65 #define STLEN 250
66
67 static const char font_types[] = "nris";
68
69 static short symbol_buffer[PLMAXSTR];
70 static signed char xygrid[STLEN];
71
72 int hershey2unicode( int in );
73
74 // Static function prototypes
75
76 static void
77 pldeco( short int **sym, PLINT *length, PLCHAR_VECTOR text );
78
79 static void
80 plchar( signed char *xygrid, PLFLT *xform, PLINT base, PLINT oline, PLINT uline,
81 PLINT refx, PLINT refy, PLFLT scale, PLFLT xpmm, PLFLT ypmm,
82 PLFLT *p_xorg, PLFLT *p_yorg, PLFLT *p_width );
83
84 static PLINT
85 plcvec( PLINT ch, signed char **xygr );
86
87 static void
88 plhrsh2( PLINT ch, PLINT x, PLINT y );
89
90 //--------------------------------------------------------------------------
105 //--------------------------------------------------------------------------
106
107 void
108 c_plstring( PLINT n, PLFLT_VECTOR x, PLFLT_VECTOR y, PLCHAR_VECTOR string )
109 {
110 PLINT i;
111 for ( i = 0; i < n; i++ )
112 {
113 c_plptex( x[i], y[i], 1., 0., 0.5, string );
114 }
115 }
116
117 //--------------------------------------------------------------------------
125 //--------------------------------------------------------------------------
126
127 void
128 c_plsym( PLINT n, PLFLT_VECTOR x, PLFLT_VECTOR y, PLINT code )
129 {
130 PLINT i;
131 PLFLT xt, yt;
132
133 if ( plsc->level < 3 )
134 {
135 plabort( "plsym: Please set up window first" );
136 return;
137 }
138 if ( code < 0 )
139 {
140 plabort( "plsym: Invalid code" );
141 return;
142 }
143
144 for ( i = 0; i < n; i++ )
145 {
146 TRANSFORM( x[i], y[i], &xt, &yt );
147 plhrsh( code, plP_wcpcx( xt ), plP_wcpcy( yt ) );
148 }
149 }
150
151 //--------------------------------------------------------------------------
169 //--------------------------------------------------------------------------
170
171 void
172 c_plpoin( PLINT n, PLFLT_VECTOR x, PLFLT_VECTOR y, PLINT code )
173 {
174 PLINT i, sym, ifont = plsc->cfont;
175 PLFLT xt, yt;
176
177 if ( plsc->level < 3 )
178 {
179 plabort( "plpoin: Please set up window first" );
180 return;
181 }
182 if ( code < -1 || code > 127 )
183 {
184 plabort( "plpoin: Invalid code" );
185 return;
186 }
187
188 if ( code == -1 )
189 {
190 for ( i = 0; i < n; i++ )
191 {
192 TRANSFORM( x[i], y[i], &xt, &yt );
193 pljoin( xt, yt, xt, yt );
194 }
195 }
196 else
197 {
198 if ( ifont > numberfonts )
199 ifont = 1;
200 sym = *( fntlkup + ( ifont - 1 ) * numberchars + code );
201 // One-time diagnostic output.
202 // fprintf(stdout, "plploin code, sym = %d, %d\n", code, sym);
203
204 for ( i = 0; i < n; i++ )
205 {
206 TRANSFORM( x[i], y[i], &xt, &yt );
207 plhrsh( sym, plP_wcpcx( xt ), plP_wcpcy( yt ) );
208 }
209 }
210 }
211
212 //--------------------------------------------------------------------------
232 //--------------------------------------------------------------------------
233
234 void
235 c_plpoin3( PLINT n, PLFLT_VECTOR x, PLFLT_VECTOR y, PLFLT_VECTOR z, PLINT code )
236 {
237 PLINT i, sym, ifont = plsc->cfont;
238 PLFLT u, v;
239 PLFLT xmin, xmax, ymin, ymax, zmin, zmax, zscale;
240
241 if ( plsc->level < 3 )
242 {
243 plabort( "plpoin3: Please set up window first" );
244 return;
245 }
246 if ( code < -1 || code > 127 )
247 {
248 plabort( "plpoin3: Invalid code" );
249 return;
250 }
251
252 plP_gdom( &xmin, &xmax, &ymin, &ymax );
253 plP_grange( &zscale, &zmin, &zmax );
254
255 if ( code == -1 )
256 {
257 for ( i = 0; i < n; i++ )
258 {
259 if ( x[i] >= xmin && x[i] <= xmax &&
260 y[i] >= ymin && y[i] <= ymax &&
261 z[i] >= zmin && z[i] <= zmax )
262 {
263 u = plP_wcpcx( plP_w3wcx( x[i], y[i], z[i] ) );
264 v = plP_wcpcy( plP_w3wcy( x[i], y[i], z[i] ) );
265 plP_movphy( (PLINT) u, (PLINT) v );
266 plP_draphy( (PLINT) u, (PLINT) v );
267 }
268 }
269 }
270 else
271 {
272 if ( ifont > numberfonts )
273 ifont = 1;
274 sym = *( fntlkup + ( ifont - 1 ) * numberchars + code );
275
276 for ( i = 0; i < n; i++ )
277 {
278 if ( x[i] >= xmin && x[i] <= xmax &&
279 y[i] >= ymin && y[i] <= ymax &&
280 z[i] >= zmin && z[i] <= zmax )
281 {
282 u = plP_wcpcx( plP_w3wcx( x[i], y[i], z[i] ) );
283 v = plP_wcpcy( plP_w3wcy( x[i], y[i], z[i] ) );
284 plhrsh( sym, (PLINT) u, (PLINT) v );
285 }
286 }
287 }
288 }
289
290 //--------------------------------------------------------------------------
308 //--------------------------------------------------------------------------
309
310 void
311 c_plstring3( PLINT n, PLFLT_VECTOR x, PLFLT_VECTOR y, PLFLT_VECTOR z, PLCHAR_VECTOR string )
312 {
313 PLINT i;
314 PLFLT u, v;
315 PLFLT xmin, xmax, ymin, ymax, zmin, zmax, zscale;
316
317 if ( plsc->level < 3 )
318 {
319 plabort( "plstring3: Please set up window first" );
320 return;
321 }
322
323 plP_gdom( &xmin, &xmax, &ymin, &ymax );
324 plP_grange( &zscale, &zmin, &zmax );
325
326 for ( i = 0; i < n; i++ )
327 {
328 if ( x[i] >= xmin && x[i] <= xmax &&
329 y[i] >= ymin && y[i] <= ymax &&
330 z[i] >= zmin && z[i] <= zmax )
331 {
332 u = plP_w3wcx( x[i], y[i], z[i] );
333 v = plP_w3wcy( x[i], y[i], z[i] );
334 c_plptex( u, v, 1., 0., 0.5, string );
335 }
336 }
337 }
338
339 //--------------------------------------------------------------------------
340 // void plhrsh(PLINT ch, PLINT x, PLINT y)
341 // PLINT ch - hershey code to plot
342 // PLINT x - device-world x coordinate of hershey character
343 // PLINT y - device-world y coordinate of hershey character
344 //
345 // Writes the Hershey symbol "ch" centred at the physical coordinate (x,y).
346 // This function is now just a "spoof" front end to the old plhersh,
347 // which has now been renamed to plhrsh2(). All this function does is
348 // decide whether or not we should render natively as unicode, and then
349 // convert between hershey and unicode.
350 //
351 // If the function KNOWS there isn't a unicode equivalent, then it will
352 // try to render it as a hershey font. Understandably, this might make
353 // testing out the unicode functions a little tricky, so if you want
354 // to disable this behaviour, recompile with PL_TEST_FOR_MISSING_GLYPHS
355 // defined.
356 //--------------------------------------------------------------------------
357
358 void
359 plhrsh( PLINT ch, PLINT x, PLINT y )
360 {
361 EscText args;
362 int idx;
363 PLUNICODE unicode_char;
364
365 // Check to see if the device understands unicode and wants to draw
366 // symbols.
367 //
368 if ( ( plsc->dev_text ) && ( plsc->dev_unicode ) && ( !plsc->dev_hrshsym ) )
369 {
370 // Get the index in the lookup table and the unicode character
371 idx = plhershey2unicode( ch );
372 if ( 0 <= idx && idx <= number_of_entries_in_hershey_to_unicode_table )
373 unicode_char = hershey_to_unicode_lookup_table[idx].Unicode;
374 else
375 unicode_char = (PLUNICODE) 0x00;
376
377 pldebug( "plhrsh", "ch, idx, unicode_char = %d, %d, %#x\n", ch, idx, unicode_char );
378 //
379 // Test to see if there is a defined unicode glyph for this hershey
380 // code; if there isn't, then we pass the glyph to plhersh, and have
381 // it rendered the old fashioned way.
382 // Otherwise, we let the driver render it as unicode
383 //
384
385 if ( ( unicode_char == 0 ) || ( idx == -1 ) )
386 {
387 #ifndef PL_TEST_FOR_MISSING_GLYPHS
388 plhrsh2( ch, x, y );
389 #endif
390 }
391 else
392 {
393 PLUNICODE plhrsh_unicode_buffer[3], fci;
394 PLFLT xform[] = { 1.0, 0.0, 0.0, 1.0 };
395 char esc;
396
397 // Get the current escape character
398 plgesc( &esc );
399
400 // Setup to render a unicode character
401 args.text_type = PL_STRING_SYMBOL;
402 args.unicode_char = unicode_char;
403 if ( 0 <= idx && idx <= number_of_entries_in_hershey_to_unicode_table )
404 args.font_face = hershey_to_unicode_lookup_table[idx].Font;
405 else
406 // Unknown font face indicated by 0 value.
407 args.font_face = 0;
408 // Comment out to fix problem with ps, psttf drivers
409 //args.base = 1;
410 args.base = 0;
411 args.just = 0.5;
412 args.xform = xform;
413 args.x = x;
414 args.y = y;
415 args.string = NULL;
416 args.symbol = ch;
417
418 // Get address of the unicode buffer (even though it is
419 // currently static)
420 args.unicode_array = &plhrsh_unicode_buffer[0];
421 args.unicode_array_len = 1;
422 plhrsh_unicode_buffer[0] = unicode_char;
423 // watch out for escape character and unescape it by appending
424 // one extra.
425 if ( unicode_char == (PLUNICODE) esc )
426 {
427 args.unicode_array_len = 2;
428 plhrsh_unicode_buffer[1] = unicode_char;
429 }
430
431 // No need to change font back since only one character.
432
433 // Swap the sym and chr information so that the text
434 // rendering (which uses chrht and chrdef) will
435 // render the symbol correctly
436 plsc->original_chrht = plsc->chrht;
437 plsc->original_chrdef = plsc->chrdef;
438 plsc->chrht = plsc->symht;
439 plsc->chrdef = plsc->symdef;
440
441 if ( plsc->alt_unicode )
442 {
443 // Character at a time method
444 plgfci( &fci );
445 args.n_fci = fci;
446 args.n_char = unicode_char;
447
448 plP_esc( PLESC_BEGIN_TEXT, &args );
449 plP_esc( PLESC_TEXT_CHAR, &args );
450 plP_esc( PLESC_END_TEXT, &args );
451 }
452 else
453 {
454 // "array method"
455 plP_esc( PLESC_HAS_TEXT, &args );
456 }
457
458 plsc->chrht = plsc->original_chrht;
459 plsc->chrdef = plsc->original_chrdef;
460 }
461 }
462 else
463 {
464 plhrsh2( ch, x, y );
465 }
466 }
467
468 //--------------------------------------------------------------------------
469 // void plhrsh2()
470 //
471 // Writes the Hershey symbol "ch" centred at the physical coordinate (x,y).
472 //--------------------------------------------------------------------------
473
474 static void
475 plhrsh2( PLINT ch, PLINT x, PLINT y )
476 {
477 PLINT cx, cy, k, penup, style;
478 signed char *vxygrid = 0;
479 PLFLT scale, xscale, yscale;
480 PLINT llx[STLEN], lly[STLEN], l = 0;
481
482 penup = 1;
483 scale = 0.05 * plsc->symht;
484
485 if ( !plcvec( ch, &vxygrid ) )
486 {
487 plP_movphy( x, y );
488 return;
489 }
490
491 // Line style must be continuous
492
493 style = plsc->nms;
494 plsc->nms = 0;
495
496 // Compute how many physical pixels correspond to a character pixel
497
498 xscale = scale * plsc->xpmm;
499 yscale = scale * plsc->ypmm;
500
501 k = 4;
502 for (;; )
503 {
504 cx = vxygrid[k++];
505 cy = vxygrid[k++];
506 if ( cx == 64 && cy == 64 )
507 {
508 if ( l )
509 {
510 plP_draphy_poly( llx, lly, l );
511 l = 0;
512 }
513 plP_movphy( x, y );
514 plsc->nms = style;
515 return;
516 }
517 else if ( cx == 64 && cy == 0 )
518 penup = 1;
519 else
520 {
521 if ( penup == 1 )
522 {
523 if ( l )
524 {
525 plP_draphy_poly( llx, lly, l );
526 l = 0;
527 }
528 llx[l] = ROUND( x + xscale * cx );
529 lly[l++] = ROUND( y + yscale * cy );
530 plP_movphy( llx[l - 1], lly[l - 1] );
531 penup = 0;
532 }
533 else
534 {
535 llx[l] = ROUND( x + xscale * cx );
536 lly[l++] = ROUND( y + yscale * cy );
537 }
538 }
539 }
540 }
541
542 //--------------------------------------------------------------------------
543 // void pllab()
544 //
545 // Simple routine for labelling graphs.
546 //--------------------------------------------------------------------------
547
548 void
549 c_pllab( PLCHAR_VECTOR xlabel, PLCHAR_VECTOR ylabel, PLCHAR_VECTOR tlabel )
550 {
551 if ( plsc->level < 2 )
552 {
553 plabort( "pllab: Please set up viewport first" );
554 return;
555 }
556
557 plmtex( "t", (PLFLT) 2.0, (PLFLT) 0.5, (PLFLT) 0.5, tlabel );
558 plmtex( "b", (PLFLT) 3.2, (PLFLT) 0.5, (PLFLT) 0.5, xlabel );
559 plmtex( "l", (PLFLT) 5.0, (PLFLT) 0.5, (PLFLT) 0.5, ylabel );
560 }
561
562 //--------------------------------------------------------------------------
563 // void plmtex()
564 //
565 // Prints out "text" at specified position relative to viewport
566 // (may be inside or outside)
567 //
568 // side String which is one of the following:
569 // B or b : Bottom of viewport
570 // T or t : Top of viewport
571 // BV or bv : Bottom of viewport, vertical text
572 // TV or tv : Top of viewport, vertical text
573 // L or l : Left of viewport
574 // R or r : Right of viewport
575 // LV or lv : Left of viewport, vertical text
576 // RV or rv : Right of viewport, vertical text
577 //
578 // disp Displacement from specified edge of viewport, measured outwards from
579 // the viewport in units of the current character height. The
580 // centerlines of the characters are aligned with the specified
581 // position.
582 //
583 // pos Position of the reference point of the string relative to the
584 // viewport edge, ranging from 0.0 (left-hand edge) to 1.0 (right-hand
585 // edge)
586 //
587 // just Justification of string relative to reference point
588 // just = 0.0 => left hand edge of string is at reference
589 // just = 1.0 => right hand edge of string is at reference
590 // just = 0.5 => center of string is at reference
591 //--------------------------------------------------------------------------
592
593 void
594 c_plmtex( PLCHAR_VECTOR side, PLFLT disp, PLFLT pos, PLFLT just,
595 PLCHAR_VECTOR text )
596 {
597 PLINT clpxmi, clpxma, clpymi, clpyma;
598 PLINT vert, refx, refy, x, y;
599 PLFLT xdv, ydv, xmm, ymm, refxmm, refymm, shift, xform[4];
600 PLFLT chrdef, chrht;
601 PLFLT dispx, dispy;
602
603 if ( plsc->level < 2 )
604 {
605 plabort( "plmtex: Please set up viewport first" );
606 return;
607 }
608
609 // Open clip limits to subpage limits
610
611 plP_gclp( &clpxmi, &clpxma, &clpymi, &clpyma ); // get and store current clip limits
612 plP_sclp( plsc->sppxmi, plsc->sppxma, plsc->sppymi, plsc->sppyma );
613
614 if ( plP_stindex( side, "BV" ) != -1 || plP_stindex( side, "bv" ) != -1 )
615 {
616 vert = 1;
617 xdv = plsc->vpdxmi + ( plsc->vpdxma - plsc->vpdxmi ) * pos;
618 ydv = plsc->vpdymi;
619 dispx = 0;
620 dispy = -disp;
621 }
622 else if ( plP_stindex( side, "TV" ) != -1 || plP_stindex( side, "tv" ) != -1 )
623 {
624 vert = 1;
625 xdv = plsc->vpdxmi + ( plsc->vpdxma - plsc->vpdxmi ) * pos;
626 ydv = plsc->vpdyma;
627 dispx = 0;
628 dispy = disp;
629 }
630 else if ( plP_stsearch( side, 'b' ) )
631 {
632 vert = 0;
633 xdv = plsc->vpdxmi + ( plsc->vpdxma - plsc->vpdxmi ) * pos;
634 ydv = plsc->vpdymi;
635 dispx = 0;
636 dispy = -disp;
637 }
638 else if ( plP_stsearch( side, 't' ) )
639 {
640 vert = 0;
641 xdv = plsc->vpdxmi + ( plsc->vpdxma - plsc->vpdxmi ) * pos;
642 ydv = plsc->vpdyma;
643 dispx = 0;
644 dispy = disp;
645 }
646 else if ( plP_stindex( side, "LV" ) != -1 || plP_stindex( side, "lv" ) != -1 )
647 {
648 vert = 0;
649 xdv = plsc->vpdxmi;
650 ydv = plsc->vpdymi + ( plsc->vpdyma - plsc->vpdymi ) * pos;
651 dispx = -disp;
652 dispy = 0;
653 }
654 else if ( plP_stindex( side, "RV" ) != -1 || plP_stindex( side, "rv" ) != -1 )
655 {
656 vert = 0;
657 xdv = plsc->vpdxma;
658 ydv = plsc->vpdymi + ( plsc->vpdyma - plsc->vpdymi ) * pos;
659 dispx = disp;
660 dispy = 0;
661 }
662 else if ( plP_stsearch( side, 'l' ) )
663 {
664 vert = 1;
665 xdv = plsc->vpdxmi;
666 ydv = plsc->vpdymi + ( plsc->vpdyma - plsc->vpdymi ) * pos;
667 dispx = -disp;
668 dispy = 0;
669 }
670 else if ( plP_stsearch( side, 'r' ) )
671 {
672 vert = 1;
673 xdv = plsc->vpdxma;
674 ydv = plsc->vpdymi + ( plsc->vpdyma - plsc->vpdymi ) * pos;
675 dispx = disp;
676 dispy = 0;
677 }
678 else
679 {
680 plP_sclp( clpxmi, clpxma, clpymi, clpyma ); // restore initial clip limits
681 return;
682 }
683
684 // Transformation matrix
685
686 if ( vert != 0 )
687 {
688 xform[0] = 0.0;
689 xform[1] = -1.0;
690 xform[2] = 1.0;
691 xform[3] = 0.0;
692 }
693 else
694 {
695 xform[0] = 1.0;
696 xform[1] = 0.0;
697 xform[2] = 0.0;
698 xform[3] = 1.0;
699 }
700
701 // Convert to physical units (mm) and compute shifts
702
703 plgchr( &chrdef, &chrht );
704 shift = ( just == 0.0 ) ? 0.0 : plstrl( text ) * just;
705
706 xmm = plP_dcmmx( xdv ) + dispx * chrht;
707 ymm = plP_dcmmy( ydv ) + dispy * chrht;
708 refxmm = xmm - shift * xform[0];
709 refymm = ymm - shift * xform[2];
710
711 // Convert to device units (pixels) and call text plotter
712
713 x = plP_mmpcx( xmm );
714 y = plP_mmpcy( ymm );
715 refx = plP_mmpcx( refxmm );
716 refy = plP_mmpcy( refymm );
717
718 plP_text( 0, just, xform, x, y, refx, refy, text );
719 plP_sclp( clpxmi, clpxma, clpymi, clpyma ); // restore clip limits
720 }
721
722 //--------------------------------------------------------------------------
723 // void plptex()
724 //
725 // Prints out "text" at world cooordinate (wx,wy). The text may be
726 // at any angle "angle" relative to the horizontal. The parameter
727 // "just" adjusts the horizontal justification of the string:
728 // just = 0.0 => left hand edge of string is at (wx,wy)
729 // just = 1.0 => right hand edge of string is at (wx,wy)
730 // just = 0.5 => center of string is at (wx,wy) etc.
731 //--------------------------------------------------------------------------
732
733 void
734 c_plptex( PLFLT wx, PLFLT wy, PLFLT dx, PLFLT dy, PLFLT just, PLCHAR_VECTOR text )
735 {
736 PLINT x, y, refx, refy;
737 PLFLT xdv, ydv, xmm, ymm, refxmm, refymm, shift, cc, ss;
738 PLFLT xform[4], diag;
739 PLFLT chrdef, chrht;
740 PLFLT dispx, dispy;
741 PLFLT wxt, wyt, dxt, dyt;
742
743 if ( plsc->level < 3 )
744 {
745 plabort( "plptex: Please set up window first" );
746 return;
747 }
748
749 // Transform both the origin and offset values
750 TRANSFORM( wx, wy, &wxt, &wyt );
751 TRANSFORM( wx + dx, wy + dy, &dxt, &dyt );
752 dxt = dxt - wxt;
753 dyt = dyt - wyt;
754 if ( dxt == 0.0 && dyt == 0.0 )
755 {
756 dxt = 1.0;
757 dyt = 0.0;
758 }
759
760 cc = plsc->wmxscl * dxt;
761 ss = plsc->wmyscl * dyt;
762 diag = sqrt( cc * cc + ss * ss );
763 cc /= diag;
764 ss /= diag;
765
766 xform[0] = cc;
767 xform[1] = -ss;
768 xform[2] = ss;
769 xform[3] = cc;
770
771 xdv = plP_wcdcx( wxt );
772 ydv = plP_wcdcy( wyt );
773
774 dispx = 0.;
775 dispy = 0.;
776
777 // Convert to physical units (mm) and compute shifts
778
779 plgchr( &chrdef, &chrht );
780 shift = ( just == 0.0 ) ? 0.0 : plstrl( text ) * just;
781
782 xmm = plP_dcmmx( xdv ) + dispx * chrht;
783 ymm = plP_dcmmy( ydv ) + dispy * chrht;
784 refxmm = xmm - shift * xform[0];
785 refymm = ymm - shift * xform[2];
786
787 x = plP_mmpcx( xmm );
788 y = plP_mmpcy( ymm );
789 refx = plP_mmpcx( refxmm );
790 refy = plP_mmpcy( refymm );
791
792 plP_text( 0, just, xform, x, y, refx, refy, text );
793 }
794
795 //--------------------------------------------------------------------------
796 // void plstr()
797 //
798 // Prints out a "string" at reference position with physical coordinates
799 // (refx,refy). The coordinates of the vectors defining the string are
800 // passed through the linear mapping defined by the 2 x 2 matrix xform()
801 // before being plotted. The reference position is at the left-hand edge of
802 // the string. If base = 1, it is aligned with the baseline of the string.
803 // If base = 0, it is aligned with the center of the character box.
804 //
805 // Note, all calculations are done in terms of millimetres. These are scaled
806 // as necessary before plotting the string on the page.
807 //--------------------------------------------------------------------------
808
809 void
810 plstr( PLINT base, PLFLT *xform, PLINT refx, PLINT refy, PLCHAR_VECTOR string )
811 {
812 short int *symbol;
813 signed char *vxygrid = 0;
814
815 PLINT ch, i, length, level = 0, style, oline = 0, uline = 0;
816 PLFLT width = 0., xorg = 0., yorg = 0., def, ht, dscale, scale;
817 PLFLT old_sscale, sscale, old_soffset, soffset;
818
819 plgchr( &def, &ht );
820 dscale = 0.05 * ht;
821 scale = dscale;
822
823 // Line style must be continuous
824
825 style = plsc->nms;
826 plsc->nms = 0;
827
828 pldeco( &symbol, &length, string );
829
830 for ( i = 0; i < length; i++ )
831 {
832 ch = symbol[i];
833 if ( ch == -1 ) // superscript
834 {
835 plP_script_scale( TRUE, &level,
836 &old_sscale, &sscale, &old_soffset, &soffset );
837 yorg = 16.0 * dscale * soffset;
838 scale = dscale * sscale;
839 }
840 else if ( ch == -2 ) // subscript
841 {
842 plP_script_scale( FALSE, &level,
843 &old_sscale, &sscale, &old_soffset, &soffset );
844 yorg = -16.0 * dscale * soffset;
845 scale = dscale * sscale;
846 }
847 else if ( ch == -3 ) // back-char
848 xorg -= width * scale;
849 else if ( ch == -4 ) // toogle overline
850 oline = !oline;
851 else if ( ch == -5 ) // toogle underline
852 uline = !uline;
853 else
854 {
855 if ( plcvec( ch, &vxygrid ) )
856 plchar( vxygrid, xform, base, oline, uline, refx, refy, scale,
857 plsc->xpmm, plsc->ypmm, &xorg, &yorg, &width );
858 }
859 }
860 plsc->nms = style;
861 }
862
863 //--------------------------------------------------------------------------
864 // plchar()
865 //
866 // Plots out a given stroke font character.
867 //--------------------------------------------------------------------------
868
869 static void
870 plchar( signed char *vxygrid, PLFLT *xform, PLINT base, PLINT oline, PLINT uline,
871 PLINT refx, PLINT refy, PLFLT scale, PLFLT xpmm, PLFLT ypmm,
872 PLFLT *p_xorg, PLFLT *p_yorg, PLFLT *p_width )
873 {
874 PLINT xbase, ybase, ydisp, lx, ly, cx, cy;
875 PLINT k, penup;
876 PLFLT x, y;
877 PLINT llx[STLEN], lly[STLEN], l = 0;
878
879 xbase = vxygrid[2];
880 *p_width = vxygrid[3] - xbase;
881 if ( base == 0 )
882 {
883 ybase = 0;
884 ydisp = vxygrid[0];
885 }
886 else
887 {
888 ybase = vxygrid[0];
889 ydisp = 0;
890 }
891 k = 4;
892 penup = 1;
893
894 for (;; )
895 {
896 cx = vxygrid[k++];
897 cy = vxygrid[k++];
898 if ( cx == 64 && cy == 64 )
899 {
900 if ( l )
901 {
902 plP_draphy_poly( llx, lly, l );
903 l = 0;
904 }
905 break;
906 }
907 if ( cx == 64 && cy == 0 )
908 {
909 if ( l )
910 {
911 plP_draphy_poly( llx, lly, l );
912 l = 0;
913 }
914 penup = 1;
915 }
916 else
917 {
918 x = *p_xorg + ( cx - xbase ) * scale;
919 y = *p_yorg + ( cy - ybase ) * scale;
920 lx = refx + ROUND( xpmm * ( xform[0] * x + xform[1] * y ) );
921 ly = refy + ROUND( ypmm * ( xform[2] * x + xform[3] * y ) );
922 if ( penup == 1 )
923 {
924 if ( l )
925 {
926 plP_draphy_poly( llx, lly, l );
927 l = 0;
928 }
929 llx[l] = lx;
930 lly[l++] = ly; // store 1st point !
931 plP_movphy( lx, ly );
932 penup = 0;
933 }
934 else
935 {
936 llx[l] = lx;
937 lly[l++] = ly;
938 }
939 }
940 }
941
942 if ( oline )
943 {
944 x = *p_xorg;
945 y = *p_yorg + ( 30 + ydisp ) * scale;
946 lx = refx + ROUND( xpmm * ( xform[0] * x + xform[1] * y ) );
947 ly = refy + ROUND( ypmm * ( xform[2] * x + xform[3] * y ) );
948 plP_movphy( lx, ly );
949 x = *p_xorg + *p_width * scale;
950 lx = refx + ROUND( xpmm * ( xform[0] * x + xform[1] * y ) );
951 ly = refy + ROUND( ypmm * ( xform[2] * x + xform[3] * y ) );
952 plP_draphy( lx, ly );
953 }
954 if ( uline )
955 {
956 x = *p_xorg;
957 y = *p_yorg + ( -5 + ydisp ) * scale;
958 lx = refx + ROUND( xpmm * ( xform[0] * x + xform[1] * y ) );
959 ly = refy + ROUND( ypmm * ( xform[2] * x + xform[3] * y ) );
960 plP_movphy( lx, ly );
961 x = *p_xorg + *p_width * scale;
962 lx = refx + ROUND( xpmm * ( xform[0] * x + xform[1] * y ) );
963 ly = refy + ROUND( ypmm * ( xform[2] * x + xform[3] * y ) );
964 plP_draphy( lx, ly );
965 }
966 *p_xorg = *p_xorg + *p_width * scale;
967 }
968
969 //--------------------------------------------------------------------------
970 // PLFLT plstrl()
971 //
972 // Computes the length of a string in mm, including escape sequences.
973 //--------------------------------------------------------------------------
974
975 PLFLT
976 plstrl( PLCHAR_VECTOR string )
977 {
978 short int *symbol;
979 signed char *vxygrid = 0;
980 PLINT ch, i, length, level = 0;
981 PLFLT width = 0., xorg = 0., dscale, scale, def, ht;
982
983 // If the driver will compute string lengths for us then we ask
984 // it do so by setting get_string_length flag. When this is set
985 // the driver will set the string_length variable instead of
986 // actually rendering the string.
987 // Note we must make sure that this text command does not end up
988 // in the buffer.
989 //
990 // TODO:
991 // Is plmtex the best string diplay routine to use?
992 // Will this work for buffered plots?
993
994 if ( plsc->has_string_length )
995 {
996 PLINT plbuf_write = plsc->plbuf_write;
997 plsc->plbuf_write = FALSE;
998 plsc->get_string_length = 1;
999 c_plmtex( "t", 0.0, 0.0, 0.0, string );
1000 plsc->get_string_length = 0;
1001 plsc->plbuf_write = plbuf_write;
1002 return (PLFLT) plsc->string_length;
1003 }
1004
1005
1006 plgchr( &def, &ht );
1007 dscale = 0.05 * ht;
1008 scale = dscale;
1009 pldeco( &symbol, &length, string );
1010
1011 for ( i = 0; i < length; i++ )
1012 {
1013 ch = symbol[i];
1014 if ( ch == -1 )
1015 {
1016 level++;
1017 scale = dscale * pow( 0.75, (double) ABS( level ) );
1018 }
1019 else if ( ch == -2 )
1020 {
1021 level--;
1022 scale = dscale * pow( 0.75, (double) ABS( level ) );
1023 }
1024 else if ( ch == -3 )
1025 xorg -= width * scale;
1026 else if ( ch == -4 || ch == -5 )
1027 ;
1028 else
1029 {
1030 if ( plcvec( ch, &vxygrid ) )
1031 {
1032 width = vxygrid[3] - vxygrid[2];
1033 xorg += width * scale;
1034 }
1035 }
1036 }
1037 return (PLFLT) xorg;
1038 }
1039
1040 //--------------------------------------------------------------------------
1041 // PLINT plcvec()
1042 //
1043 // Gets the character digitisation of Hershey table entry "char".
1044 // Returns 1 if there is a valid entry.
1045 //--------------------------------------------------------------------------
1046
1047 static PLINT
1048 plcvec( PLINT ch, signed char **xygr )
1049 {
1050 PLINT k = 0, ib;
1051 signed char x, y;
1052
1053 ch--;
1054 if ( ch < 0 || ch >= indxleng )
1055 return (PLINT) 0;
1056 ib = fntindx[ch] - 2;
1057 if ( ib == -2 )
1058 return (PLINT) 0;
1059
1060 do
1061 {
1062 ib++;
1063 x = fntbffr[2 * ib];
1064 y = fntbffr[2 * ib + 1];
1065 xygrid[k++] = x;
1066 xygrid[k++] = y;
1067 } while ( ( x != 64 || y != 64 ) && k <= ( STLEN - 2 ) );
1068
1069 if ( k == ( STLEN - 1 ) )
1070 {
1071 // This is bad if we get here
1072 xygrid[k] = 64;
1073 xygrid[k] = 64;
1074 }
1075
1076 *xygr = xygrid;
1077 return (PLINT) 1;
1078 }
1079
1080 //--------------------------------------------------------------------------
1081 // void pldeco()
1082 //
1083 // Decode a character string, and return an array of float integer symbol
1084 // numbers. This routine is responsible for interpreting all escape sequences.
1085 // At present the following escape sequences are defined (the letter following
1086 // the <esc> may be either upper or lower case):
1087 //
1088 // <esc>u : up one level (returns -1)
1089 // <esc>d : down one level (returns -2)
1090 // <esc>b : backspace (returns -3)
1091 // <esc>+ : toggles overline mode (returns -4)
1092 // <esc>- : toggles underline mode (returns -5)
1093 // <esc><esc> : <esc>
1094 // <esc>gx : greek letter corresponding to roman letter x
1095 // <esc>fn : switch to Normal font
1096 // <esc>fr : switch to Roman font
1097 // <esc>fi : switch to Italic font
1098 // <esc>fs : switch to Script font
1099 // <esc>(nnn) : Hershey symbol number nnn (any number of digits)
1100 //
1101 // The escape character defaults to '#', but can be changed to any of
1102 // [!#$%&*@^~] via a call to plsesc.
1103 //--------------------------------------------------------------------------
1104
1105 static void
1106 pldeco( short int **symbol, PLINT *length, PLCHAR_VECTOR text )
1107 {
1108 PLINT ch, ifont = plsc->cfont, ig, j = 0, lentxt = (PLINT) strlen( text );
1109 char test, esc;
1110 short int *sym = symbol_buffer;
1111
1112 // Initialize parameters.
1113
1114 *length = 0;
1115 *symbol = symbol_buffer;
1116 plgesc( &esc );
1117 if ( ifont > numberfonts )
1118 ifont = 1;
1119
1120 // Get next character; treat non-printing characters as spaces.
1121
1122 while ( j < lentxt )
1123 {
1124 if ( *length >= PLMAXSTR )
1125 return;
1126 test = text[j++];
1127 ch = test;
1128 if ( ch < 0 || ch > 175 )
1129 ch = 32;
1130
1131 // Test for escape sequence (#)
1132
1133 if ( ch == esc && ( lentxt - j ) >= 1 )
1134 {
1135 test = text[j++];
1136 if ( test == esc )
1137 sym[( *length )++] = *( fntlkup + ( ifont - 1 ) * numberchars + ch );
1138
1139 else if ( test == 'u' || test == 'U' )
1140 sym[( *length )++] = -1;
1141
1142 else if ( test == 'd' || test == 'D' )
1143 sym[( *length )++] = -2;
1144
1145 else if ( test == 'b' || test == 'B' )
1146 sym[( *length )++] = -3;
1147
1148 else if ( test == '+' )
1149 sym[( *length )++] = -4;
1150
1151 else if ( test == '-' )
1152 sym[( *length )++] = -5;
1153
1154 else if ( test == '(' )
1155 {
1156 sym[*length] = 0;
1157 while ( '0' <= text[j] && text[j] <= '9' )
1158 {
1159 sym[*length] = (short) ( (int) sym[*length] * 10 + text[j] - '0' );
1160 j++;
1161 }
1162 ( *length )++;
1163 if ( text[j] == ')' )
1164 j++;
1165 }
1166 else if ( test == 'f' || test == 'F' )
1167 {
1168 test = text[j++];
1169 ifont = 1 + plP_strpos( font_types,
1170 isupper( test ) ? tolower( test ) : test );
1171 if ( ifont == 0 || ifont > numberfonts )
1172 ifont = 1;
1173 }
1174 else if ( test == 'g' || test == 'G' )
1175 {
1176 test = text[j++];
1177 ig = plP_strpos( plP_greek_mnemonic, test ) + 1;
1178 // This accesses the Hershey glyphs using the same
1179 // "ascii" index as plpoin. So the order of the Greek
1180 // glyphs in this case depends on the subhersh[0-3]
1181 // indices in fonts/font11.c which for lower-case epsilon,
1182 // theta, and phi substitutes (684, 685, and 686) for
1183 // (631, 634, and 647) in the compact case and (2184,
1184 // 2185, and 2186) for (2131, 2134, and 2147) in the
1185 // extended case.
1186 sym[( *length )++] =
1187 *( fntlkup + ( ifont - 1 ) * numberchars + 127 + ig );
1188 }
1189 else
1190 {
1191 ;
1192 }
1193 }
1194 else
1195 {
1196 // Decode character.
1197 // >>PC<< removed increment from following expression to fix
1198 // compiler bug
1199
1200 sym[( *length )] = *( fntlkup + ( ifont - 1 ) * numberchars + ch );
1201 ( *length )++;
1202 }
1203 }
1204 }
1205
1206 //--------------------------------------------------------------------------
1207 // PLINT plP_strpos()
1208 //
1209 // Searches string str for first occurence of character chr. If found
1210 // the position of the character in the string is returned (the first
1211 // character has position 0). If the character is not found a -1 is
1212 // returned.
1213 //--------------------------------------------------------------------------
1214
1215 PLINT
1216 plP_strpos( PLCHAR_VECTOR str, int chr )
1217 {
1218 char *temp;
1219
1220 if ( ( temp = strchr( str, chr ) ) )
1221 return (PLINT) ( temp - str );
1222 else
1223 return (PLINT) -1;
1224 }
1225
1226 //--------------------------------------------------------------------------
1227 // PLINT plP_stindex()
1228 //
1229 // Similar to strpos, but searches for occurence of string str2.
1230 //--------------------------------------------------------------------------
1231
1232 PLINT
1233 plP_stindex( PLCHAR_VECTOR str1, PLCHAR_VECTOR str2 )
1234 {
1235 PLINT base, str1ind, str2ind;
1236
1237 for ( base = 0; *( str1 + base ) != '\0'; base++ )
1238 {
1239 for ( str1ind = base, str2ind = 0; *( str2 + str2ind ) != '\0' &&
1240 *( str2 + str2ind ) == *( str1 + str1ind ); str1ind++, str2ind++ )
1241 ;
1242
1243 if ( *( str2 + str2ind ) == '\0' )
1244 return (PLINT) base;
1245 }
1246 return (PLINT) -1; // search failed
1247 }
1248
1249 //--------------------------------------------------------------------------
1250 // PLBOOL plP_stsearch()
1251 //
1252 // Searches string str for character chr (case insensitive).
1253 //--------------------------------------------------------------------------
1254
1255 PLBOOL
1256 plP_stsearch( PLCHAR_VECTOR str, int chr )
1257 {
1258 if ( strchr( str, chr ) )
1259 return TRUE;
1260 else if ( strchr( str, toupper( chr ) ) )
1261 return TRUE;
1262 else
1263 return FALSE;
1264 }
1265
1266 //--------------------------------------------------------------------------
1300
1301 void
1302 plP_script_scale( PLBOOL ifupper, PLINT *level,
1303 PLFLT *old_scale, PLFLT *scale,
1304 PLFLT *old_offset, PLFLT *offset )
1305 {
1306 if ( *level == 0 )
1307 {
1308 *old_scale = 1.;
1309 *old_offset = 0.;
1310 }
1311 else
1312 {
1313 *old_scale = *scale;
1314 *old_offset = *offset;
1315 }
1316 if ( ( *level >= 0 && ifupper ) || ( *level <= 0 && !ifupper ) )
1317 {
1318 // If superscript of subscript moves further away from centerline....
1319 *scale = 0.75 * *old_scale;
1320 *offset = *old_offset + *old_scale;
1321 }
1322 else
1323 {
1324 // If superscript of subscript moves closer to centerline....
1325 *scale = *old_scale / 0.75;
1326 *offset = *old_offset - *scale;
1327 }
1328 if ( ifupper )
1329 ( *level )++;
1330 else
1331 ( *level )--;
1332 }
1333
1334 //--------------------------------------------------------------------------
1335 // void c_plfont(ifont)
1336 //
1337 // Sets the global font flag to 'ifont'.
1338 //--------------------------------------------------------------------------
1339
1340 void
1341 c_plfont( PLINT ifont )
1342 {
1343 PLUNICODE fci = PL_FCI_MARK;
1344 if ( plsc->level < 1 )
1345 {
1346 plabort( "plfont: Please call plinit first" );
1347 return;
1348 }
1349 if ( ifont < 1 || ifont > 4 )
1350 {
1351 plabort( "plfont: Invalid font" );
1352 return;
1353 }
1354
1355 plsc->cfont = ifont;
1356
1357 // Provide some degree of forward compatibility if dealing with
1358 // unicode font. But better procedure is to call plsfci directly rather
1359 // than using this lame Hershey font interface.
1360 //
1361 switch ( ifont )
1362 {
1363 case 1:
1364 // normal = (medium, upright, sans serif)
1365 plP_hex2fci( PL_FCI_SANS, PL_FCI_FAMILY, &fci );
1366 plsfci( fci );
1367 break;
1368 // roman = (medium, upright, serif)
1369 case 2:
1370 plP_hex2fci( PL_FCI_SERIF, PL_FCI_FAMILY, &fci );
1371 plsfci( fci );
1372 break;
1373 // italic = (medium, italic, serif)
1374 case 3:
1375 plP_hex2fci( PL_FCI_ITALIC, PL_FCI_STYLE, &fci );
1376 plP_hex2fci( PL_FCI_SERIF, PL_FCI_FAMILY, &fci );
1377 plsfci( fci );
1378 break;
1379 // script = (medium, upright, script)
1380 case 4:
1381 plP_hex2fci( PL_FCI_SCRIPT, PL_FCI_FAMILY, &fci );
1382 plsfci( fci );
1383 break;
1384 }
1385 }
1386
1387 //--------------------------------------------------------------------------
1388 // void plfntld(fnt)
1389 //
1390 // Loads either the standard or extended font.
1391 //--------------------------------------------------------------------------
1392
1393 void
1394 plfntld( PLINT fnt )
1395 {
1396 static PLINT charset;
1397 short bffrleng;
1398 PDFstrm *pdfs;
1399
1400 if ( fontloaded && ( charset == fnt ) )
1401 return;
1402
1403 plfontrel();
1404 fontloaded = 1;
1405 charset = fnt;
1406
1407 if ( fnt )
1408 pdfs = plLibOpenPdfstrm( PL_XFONT );
1409 else
1410 pdfs = plLibOpenPdfstrm( PL_SFONT );
1411
1412 if ( pdfs == NULL )
1413 plexit( "Unable to either (1) open/find or (2) allocate memory for the font file" );
1414
1415 // Read fntlkup[]
1416
1417 pdf_rd_2bytes( pdfs, (U_SHORT *) &bffrleng );
1418 numberfonts = bffrleng / 256;
1419 numberchars = bffrleng & 0xff;
1420 bffrleng = (short) ( numberfonts * numberchars );
1421 fntlkup = (short int *) malloc( (size_t) bffrleng * sizeof ( short int ) );
1422 if ( !fntlkup )
1423 plexit( "plfntld: Out of memory while allocating font buffer." );
1424
1425 pdf_rd_2nbytes( pdfs, (U_SHORT *) fntlkup, bffrleng );
1426
1427 // Read fntindx[]
1428
1429 pdf_rd_2bytes( pdfs, (U_SHORT *) &indxleng );
1430 fntindx = (short int *) malloc( (size_t) indxleng * sizeof ( short int ) );
1431 if ( !fntindx )
1432 plexit( "plfntld: Out of memory while allocating font buffer." );
1433
1434 pdf_rd_2nbytes( pdfs, (U_SHORT *) fntindx, indxleng );
1435
1436 // Read fntbffr[]
1437 // Since this is an array of char, there are no endian problems
1438
1439 pdf_rd_2bytes( pdfs, (U_SHORT *) &bffrleng );
1440 fntbffr = (signed char *) malloc( 2 * (size_t) bffrleng * sizeof ( signed char ) );
1441 if ( !fntbffr )
1442 plexit( "plfntld: Out of memory while allocating font buffer." );
1443
1444 #if PLPLOT_USE_TCL_CHANNELS
1445 pdf_rdx( fntbffr, sizeof ( signed char ) * (size_t) ( 2 * bffrleng ), pdfs );
1446 #else
1447 plio_fread( (void *) fntbffr, (size_t) sizeof ( signed char ),
1448 (size_t) ( 2 * bffrleng ), pdfs->file );
1449 #endif
1450
1451 // Done
1452
1453 pdf_close( pdfs );
1454 }
1455
1456 //--------------------------------------------------------------------------
1457 // void plfontrel()
1458 //
1459 // Release memory for fonts.
1460 //--------------------------------------------------------------------------
1461
1462 void
1463 plfontrel( void )
1464 {
1465 if ( fontloaded )
1466 {
1467 free_mem( fntindx )
1468 free_mem( fntbffr )
1469 free_mem( fntlkup )
1470 fontloaded = 0;
1471 }
1472 }
1473
1474 //--------------------------------------------------------------------------
1475 // int plhershey2unicode ( int in )
1476 //
1477 // Function searches for in, the input hershey code, in a lookup table and
1478 // returns the corresponding index in that table.
1479 // Using this index you can work out the unicode equivalent as well as
1480 // the closest approximate to the font-face. If the returned index is
1481 // -1 then no match was possible.
1482 //
1483 // Two versions of the function exist, a simple linear search version,
1484 // and a more complex, but significantly faster, binary search version.
1485 // If there seem to be problems with the binary search method, the brain-dead
1486 // linear search can be enabled by defining SIMPLE_BUT_SAFE_HERSHEY_LOOKUP
1487 // at compile time.
1488 //--------------------------------------------------------------------------
1489
1490 int plhershey2unicode( int in )
1491 {
1492 #ifdef SIMPLE_BUT_SAFE_HERSHEY_LOOKUP
1493 int ret = -1;
1494 int i;
1495
1496 for ( i = 0; ( i < number_of_entries_in_hershey_to_unicode_table ) && ( ret == -1 ); i++ )
1497 {
1498 if ( hershey_to_unicode_lookup_table[i].Hershey == in )
1499 ret = i;
1500 }
1501
1502 return ( ret );
1503
1504 #else
1505
1506 int jlo = -1, jmid, jhi = number_of_entries_in_hershey_to_unicode_table;
1507 while ( jhi - jlo > 1 )
1508 {
1509 // Note that although jlo or jhi can be just outside valid
1510 // range (see initialization above) because of while condition
1511 // jlo < jmid < jhi and jmid must be in valid range.
1512 //
1513 jmid = ( jlo + jhi ) / 2;
1514 // convert hershey_to_unicode_lookup_table[jmid].Hershey to signed
1515 // integer since we don't lose information - the number range
1516 // is from 1 and 2932 at the moment
1517 if ( in > (int) ( hershey_to_unicode_lookup_table[jmid].Hershey ) )
1518 jlo = jmid;
1519 else if ( in < (int) ( hershey_to_unicode_lookup_table[jmid].Hershey ) )
1520 jhi = jmid;
1521 else
1522 // We have found it!
1523 // in == hershey_to_unicode_lookup_table[jmid].Hershey
1524 //
1525 return ( jmid );
1526 }
1527 // jlo is invalid or it is valid and in > hershey_to_unicode_lookup_table[jlo].Hershey.
1528 // jhi is invalid or it is valid and in < hershey_to_unicode_lookup_table[jhi].Hershey.
1529 // All these conditions together imply in cannot be found in
1530 // hershey_to_unicode_lookup_table[j].Hershey, for all j.
1531 //
1532 return ( -1 );
1533 #endif
1534 }
1535
1536 //--------------------------------------------------------------------------
1537 // char *
1538 // plP_FCI2FontName ( PLUNICODE fci,
1539 // const FCI_to_FontName_Table lookup[], const int nlookup)
1540 //
1541 // Function takes an input FCI (font characterization integer) index,
1542 // looks through the lookup table (which must be sorted by PLUNICODE fci),
1543 // then returns the corresponding pointer to a valid font name. If the FCI
1544 // index is not present the returned value is NULL.
1545 //--------------------------------------------------------------------------
1546
1547 PLCHAR_VECTOR
1548 plP_FCI2FontName( PLUNICODE fci,
1549 const FCI_to_FontName_Table lookup[], const int nlookup )
1550 {
1551 int jlo = -1, jmid, jhi = nlookup;
1552 while ( jhi - jlo > 1 )
1553 {
1554 // Note that although jlo or jhi can be just outside valid
1555 // range (see initialization above) because of while condition
1556 // jlo < jmid < jhi and jmid must be in valid range.
1557 //
1558 jmid = ( jlo + jhi ) / 2;
1559 if ( fci > lookup[jmid].fci )
1560 jlo = jmid;
1561 else if ( fci < lookup[jmid].fci )
1562 jhi = jmid;
1563 else
1564 // We have found it!
1565 // fci == lookup[jmid].fci
1566 //
1567 return (PLCHAR_VECTOR) ( lookup[jmid].pfont );
1568 }
1569 // jlo is invalid or it is valid and fci > lookup[jlo].Unicode.
1570 // jhi is invalid or it is valid and fci < lookup[jhi].Unicode.
1571 // All these conditions together imply fci index cannot be found in lookup.
1572 // Mark lookup failure with NULL pointer.
1573 //
1574 return ( NULL );
1575 }
1576
1577 //--------------------------------------------------------------------------
1578 // void plmtex3()
1579 //
1580 // This is the 3d equivalent of plmtex(). It prints out "text" at specified
1581 // position relative to viewport (may be inside or outside)
1582 //
1583 // side String contains one or more of the following characters
1584 // x,y,z : Specify which axis is to be labeled
1585 // p,s : Label the "primary" or the "secondary" axis. The "primary" axis
1586 // being somewhat arbitrary, but basically it is the one that you'd
1587 // expect to labeled in a 3d graph of standard orientation. Example:
1588 // for z this would be the left hand axis.
1589 // v : draw the text perpendicular to the axis.
1590 //
1591 // disp Displacement from specified edge of axis, measured outwards from
1592 // the axis in units of the current character height. The
1593 // centerlines of the characters are aligned with the specified
1594 // position.
1595 //
1596 // pos Position of the reference point of the string relative to the
1597 // axis ends, ranging from 0.0 (left-hand end) to 1.0 (right-hand
1598 // end)
1599 //
1600 // just Justification of string relative to reference point
1601 // just = 0.0 => left hand edge of string is at reference
1602 // just = 1.0 => right hand edge of string is at reference
1603 // just = 0.5 => center of string is at reference
1604 //
1605 // All calculations are done in physical coordinates.
1606 //
1607 //--------------------------------------------------------------------------
1608
1609 void
1610 c_plmtex3( PLCHAR_VECTOR side, PLFLT disp, PLFLT pos, PLFLT just, PLCHAR_VECTOR text )
1611 {
1612 // local storage
1613 PLFLT xmin, xmax, ymin, ymax, zmin, zmax, zscale;
1614 PLFLT chrdef, chrht;
1615
1616 // calculated
1617 PLFLT xpc, ypc, xrefpc, yrefpc;
1618 PLFLT epx1 = 0.0, epy1 = 0.0, epx2 = 0.0, epy2 = 0.0, epx3 = 0.0, epy3 = 0.0;
1619 PLFLT dispx, dispy, xform[4];
1620 PLFLT shift, theta, temp;
1621
1622 // check that the plotting environment is set up
1623 if ( plsc->level < 3 )
1624 {
1625 plabort( "plmtex3: Please set up window first" );
1626 return;
1627 }
1628
1629 // get plotting environment information
1630 plP_gdom( &xmin, &xmax, &ymin, &ymax );
1631 plP_grange( &zscale, &zmin, &zmax );
1632 plgchr( &chrdef, &chrht );
1633
1634 // handle x/y axises
1635 if ( ( plP_stindex( side, "x" ) != -1 ) || ( plP_stindex( side, "y" ) != -1 ) )
1636 {
1637 // get the locations of the end points of the relevant axis
1638
1639 // x axis label
1640 if ( plP_stindex( side, "x" ) != -1 )
1641 {
1642 // primary
1643 if ( plP_stindex( side, "p" ) != -1 )
1644 {
1645 epx1 = plP_wcpcx( plP_w3wcx( xmin, ymin, zmin ) );
1646 epy1 = plP_wcpcy( plP_w3wcy( xmin, ymin, zmin ) );
1647 epx2 = plP_wcpcx( plP_w3wcx( xmax, ymin, zmin ) );
1648 epy2 = plP_wcpcy( plP_w3wcy( xmax, ymin, zmin ) );
1649 }
1650 else
1651 {
1652 epx1 = plP_wcpcx( plP_w3wcx( xmin, ymax, zmin ) );
1653 epy1 = plP_wcpcy( plP_w3wcy( xmin, ymax, zmin ) );
1654 epx2 = plP_wcpcx( plP_w3wcx( xmax, ymax, zmin ) );
1655 epy2 = plP_wcpcy( plP_w3wcy( xmax, ymax, zmin ) );
1656 }
1657 }
1658 else
1659 {
1660 if ( plP_stindex( side, "p" ) != -1 )
1661 {
1662 epx1 = plP_wcpcx( plP_w3wcx( xmin, ymin, zmin ) );
1663 epy1 = plP_wcpcy( plP_w3wcy( xmin, ymin, zmin ) );
1664 epx2 = plP_wcpcx( plP_w3wcx( xmin, ymax, zmin ) );
1665 epy2 = plP_wcpcy( plP_w3wcy( xmin, ymax, zmin ) );
1666 }
1667 else
1668 {
1669 epx1 = plP_wcpcx( plP_w3wcx( xmax, ymin, zmin ) );
1670 epy1 = plP_wcpcy( plP_w3wcy( xmax, ymin, zmin ) );
1671 epx2 = plP_wcpcx( plP_w3wcx( xmax, ymax, zmin ) );
1672 epy2 = plP_wcpcy( plP_w3wcy( xmax, ymax, zmin ) );
1673 }
1674 }
1675
1676 // text always goes from left to right
1677 if ( epx1 > epx2 )
1678 {
1679 temp = epx1;
1680 epx1 = epx2;
1681 epx2 = temp;
1682 temp = epy1;
1683 epy1 = epy2;
1684 epy2 = temp;
1685 // recalculate position assuming the user specified
1686 // it in the min -> max direction of the axis.
1687 pos = 1.0 - pos;
1688 }
1689
1690 // calculate location of text center point
1691
1692 // 1. calculate the angle of the axis we are to
1693 // draw the text on relative to the horizontal
1694
1695 if ( ( epx2 - epx1 ) != 0.0 )
1696 {
1697 theta = atan( ( epy2 - epy1 ) / ( epx2 - epx1 ) );
1698 }
1699 else
1700 {
1701 if ( epy2 > epy1 )
1702 {
1703 theta = 0.5 * PI;
1704 }
1705 else
1706 {
1707 theta = -0.5 * PI;
1708 }
1709 }
1710
1711 // 2. calculate the perpendicular vector
1712
1713 dispy = disp * chrht;
1714
1715 // 3. calculate x & y center points
1716
1717 xpc = pos * ( epx2 - epx1 ) + epx1;
1718 ypc = pos * ( epy2 - epy1 ) + epy1;
1719
1720 // 4. compute reference point
1721 // It appears that drivers that cannot handle text justification
1722 // use this as the starting point of the string.
1723 // Calculations must be done in millimeters for this part
1724 // so we convert to mm, do the calculation and convert back.
1725 // The calculation is also dependent of the orientation
1726 // (perpendicular or parallel) of the text.
1727
1728 xpc = plP_dcmmx( plP_pcdcx( (PLINT) xpc ) );
1729 ypc = plP_dcmmy( plP_pcdcy( (PLINT) ypc ) ) - dispy;
1730
1731 shift = plstrl( text ) * just;
1732
1733 if ( plP_stindex( side, "v" ) != -1 )
1734 {
1735 xrefpc = xpc;
1736 yrefpc = ypc - shift;
1737 }
1738 else
1739 {
1740 xrefpc = xpc - cos( theta ) * shift;
1741 yrefpc = ypc - sin( theta ) * shift;
1742 }
1743
1744 xpc = plP_mmpcx( xpc );
1745 ypc = plP_mmpcy( ypc );
1746 xrefpc = plP_mmpcx( xrefpc );
1747 yrefpc = plP_mmpcy( yrefpc );
1748
1749 // 5. compute transform matrix & draw text
1750
1751 // perpendicular, rotate 90 degrees & shear
1752
1753 if ( plP_stindex( side, "v" ) != -1 )
1754 {
1755 xform[0] = 0.0;
1756 xform[1] = -cos( theta );
1757 xform[2] = 1.0;
1758 xform[3] = -sin( theta );
1759 plP_text( 0, just, xform, (PLINT) xpc, (PLINT) ypc, (PLINT) xrefpc, (PLINT) yrefpc, text );
1760 }
1761
1762 // parallel, rotate & shear by angle
1763 else
1764 {
1765 xform[0] = cos( theta );
1766 xform[1] = 0.0;
1767 xform[2] = sin( theta );
1768 xform[3] = 1.0;
1769
1770 plP_text( 0, just, xform, (PLINT) xpc, (PLINT) ypc, (PLINT) xrefpc, (PLINT) yrefpc, text );
1771 }
1772 }
1773
1774 // handle z axises
1775 if ( plP_stindex( side, "z" ) != -1 )
1776 {
1777 // Find the left most of the 4 z axis options for "primary"
1778 // Also find the location of frontmost point in the graph,
1779 // which will be needed to calculate at what angle to shear
1780 // the text.
1781
1782 if ( plP_stindex( side, "p" ) != -1 )
1783 {
1784 epx1 = plP_wcpcx( plP_w3wcx( xmin, ymin, zmin ) );
1785 epy1 = plP_wcpcy( plP_w3wcy( xmin, ymin, zmin ) );
1786 epy2 = plP_wcpcy( plP_w3wcy( xmin, ymin, zmax ) );
1787 epx3 = plP_wcpcx( plP_w3wcx( xmax, ymin, zmin ) );
1788 epy3 = plP_wcpcy( plP_w3wcy( xmax, ymin, zmin ) );
1789
1790 if ( plP_wcpcx( plP_w3wcx( xmin, ymax, zmin ) ) < epx1 )
1791 {
1792 epx1 = plP_wcpcx( plP_w3wcx( xmin, ymax, zmin ) );
1793 epy1 = plP_wcpcy( plP_w3wcy( xmin, ymax, zmin ) );
1794 epy2 = plP_wcpcy( plP_w3wcy( xmin, ymax, zmax ) );
1795 epx3 = plP_wcpcx( plP_w3wcx( xmin, ymin, zmin ) );
1796 epy3 = plP_wcpcy( plP_w3wcy( xmin, ymin, zmin ) );
1797 }
1798
1799 if ( plP_wcpcx( plP_w3wcx( xmax, ymin, zmin ) ) < epx1 )
1800 {
1801 epx1 = plP_wcpcx( plP_w3wcx( xmax, ymin, zmin ) );
1802 epy1 = plP_wcpcy( plP_w3wcy( xmax, ymin, zmin ) );
1803 epy2 = plP_wcpcy( plP_w3wcy( xmax, ymin, zmax ) );
1804 epx3 = plP_wcpcx( plP_w3wcx( xmax, ymax, zmin ) );
1805 epy3 = plP_wcpcy( plP_w3wcy( xmax, ymax, zmin ) );
1806 }
1807
1808 if ( plP_wcpcx( plP_w3wcx( xmax, ymax, zmin ) ) < epx1 )
1809 {
1810 epx1 = plP_wcpcx( plP_w3wcx( xmax, ymax, zmin ) );
1811 epy1 = plP_wcpcy( plP_w3wcy( xmax, ymax, zmin ) );
1812 epy2 = plP_wcpcy( plP_w3wcy( xmax, ymax, zmax ) );
1813 epx3 = plP_wcpcx( plP_w3wcx( xmin, ymax, zmin ) );
1814 epy3 = plP_wcpcy( plP_w3wcy( xmin, ymax, zmin ) );
1815 }
1816 }
1817
1818 // find the right most of the 4 z axis options for "primary"
1819 if ( plP_stindex( side, "s" ) != -1 )
1820 {
1821 epx1 = plP_wcpcx( plP_w3wcx( xmin, ymin, zmin ) );
1822 epy1 = plP_wcpcy( plP_w3wcy( xmin, ymin, zmin ) );
1823 epy2 = plP_wcpcy( plP_w3wcy( xmin, ymin, zmax ) );
1824 epx3 = plP_wcpcx( plP_w3wcx( xmin, ymax, zmin ) );
1825 epy3 = plP_wcpcy( plP_w3wcy( xmin, ymax, zmin ) );
1826
1827 if ( plP_wcpcx( plP_w3wcx( xmin, ymax, zmin ) ) > epx1 )
1828 {
1829 epx1 = plP_wcpcx( plP_w3wcx( xmin, ymax, zmin ) );
1830 epy1 = plP_wcpcy( plP_w3wcy( xmin, ymax, zmin ) );
1831 epy2 = plP_wcpcy( plP_w3wcy( xmin, ymax, zmax ) );
1832 epx3 = plP_wcpcx( plP_w3wcx( xmax, ymax, zmin ) );
1833 epy3 = plP_wcpcy( plP_w3wcy( xmax, ymax, zmin ) );
1834 }
1835
1836 if ( plP_wcpcx( plP_w3wcx( xmax, ymin, zmin ) ) > epx1 )
1837 {
1838 epx1 = plP_wcpcx( plP_w3wcx( xmax, ymin, zmin ) );
1839 epy1 = plP_wcpcy( plP_w3wcy( xmax, ymin, zmin ) );
1840 epy2 = plP_wcpcy( plP_w3wcy( xmax, ymin, zmax ) );
1841 epx3 = plP_wcpcx( plP_w3wcx( xmin, ymin, zmin ) );
1842 epy3 = plP_wcpcy( plP_w3wcy( xmin, ymin, zmin ) );
1843 }
1844
1845 if ( plP_wcpcx( plP_w3wcx( xmax, ymax, zmin ) ) > epx1 )
1846 {
1847 epx1 = plP_wcpcx( plP_w3wcx( xmax, ymax, zmin ) );
1848 epy1 = plP_wcpcy( plP_w3wcy( xmax, ymax, zmin ) );
1849 epy2 = plP_wcpcy( plP_w3wcy( xmax, ymax, zmax ) );
1850 epx3 = plP_wcpcx( plP_w3wcx( xmax, ymin, zmin ) );
1851 epy3 = plP_wcpcy( plP_w3wcy( xmax, ymin, zmin ) );
1852 }
1853 }
1854
1855 // Calculate location of text center point.
1856 // This is very similiar for the z axis.
1857
1858 // primary and secondary have to be handled separately here
1859
1860 if ( plP_stindex( side, "p" ) != -1 )
1861 {
1862 // 1. Calculate the angle of the axis we are to
1863 // draw the text on relative to the horizontal.
1864
1865 if ( ( epx3 - epx1 ) != 0.0 )
1866 {
1867 theta = atan( ( epy3 - epy1 ) / ( epx3 - epx1 ) );
1868 }
1869 else
1870 {
1871 if ( epy3 > epy1 )
1872 {
1873 theta = 0.5 * PI;
1874 }
1875 else
1876 {
1877 theta = -0.5 * PI;
1878 }
1879 }
1880
1881 // 2. Calculate the perpendicular vector.
1882
1883 dispx = -cos( theta ) * disp * chrht;
1884 dispy = -sin( theta ) * disp * chrht;
1885 }
1886 else
1887 {
1888 if ( ( epx1 - epx3 ) != 0.0 )
1889 {
1890 theta = -atan( ( epy3 - epy1 ) / ( epx1 - epx3 ) );
1891 }
1892 else
1893 {
1894 if ( epy3 > epy1 )
1895 {
1896 theta = -0.5 * PI;
1897 }
1898 else
1899 {
1900 theta = 0.5 * PI;
1901 }
1902 }
1903
1904 dispx = cos( theta ) * disp * chrht;
1905 dispy = sin( theta ) * disp * chrht;
1906 }
1907
1908 // 3. Calculate x & y center points.
1909
1910 xpc = epx1;
1911 ypc = pos * ( epy2 - epy1 ) + epy1;
1912
1913 // 4. Compute the reference point.
1914
1915 xpc = plP_dcmmx( plP_pcdcx( (PLINT) xpc ) ) + dispx;
1916 ypc = plP_dcmmy( plP_pcdcy( (PLINT) ypc ) ) + dispy;
1917
1918 shift = plstrl( text ) * just;
1919
1920 if ( plP_stindex( side, "v" ) != -1 )
1921 {
1922 xrefpc = xpc - cos( theta ) * shift;
1923 yrefpc = ypc - sin( theta ) * shift;
1924 }
1925 else
1926 {
1927 xrefpc = xpc;
1928 yrefpc = ypc - shift;
1929 }
1930
1931 xpc = plP_mmpcx( xpc );
1932 ypc = plP_mmpcy( ypc );
1933 xrefpc = plP_mmpcx( xrefpc );
1934 yrefpc = plP_mmpcy( yrefpc );
1935
1936 // 5. Compute transform matrix & draw text.
1937
1938 if ( plP_stindex( side, "v" ) != -1 )
1939 {
1940 xform[0] = cos( theta );
1941 xform[1] = 0.0;
1942 xform[2] = sin( theta );
1943 xform[3] = 1.0;
1944
1945 plP_text( 0, just, xform, (PLINT) xpc, (PLINT) ypc, (PLINT) xrefpc, (PLINT) yrefpc, text );
1946 }
1947
1948 else
1949 {
1950 xform[0] = 0.0;
1951 xform[1] = -cos( theta );
1952 xform[2] = 1.0;
1953 xform[3] = -sin( theta );
1954
1955 plP_text( 0, just, xform, (PLINT) xpc, (PLINT) ypc, (PLINT) xrefpc, (PLINT) yrefpc, text );
1956 }
1957 }
1958 }
1959
1960 //--------------------------------------------------------------------------
1961 // void plptex3()
1962 //
1963 // Prints out "text" at world cooordinate (wx,wy,wz).
1964 //
1965 // The text is drawn parallel to the line between (wx,wy,wz) and
1966 // (wx+dx,wy+dy,wz+dz).
1967 //
1968 // The text is sheared so that it is "vertically" parallel to the
1969 // line between (wx,wy,wz) and (wx+sx, wy+sy, wz+sz). If sx=sy=sz=0 then
1970 // the text is simply rotated to parallel to the baseline.
1971 //
1972 // "just" adjusts the horizontal justification of the string:
1973 // just = 0.0 => left hand edge of string is at (wx,wy)
1974 // just = 1.0 => right hand edge of string is at (wx,wy)
1975 // just = 0.5 => center of string is at (wx,wy) etc.
1976 //
1977 // Calculations are done in physical coordinates.
1978 //
1979 //--------------------------------------------------------------------------
1980
1981 void
1982 c_plptex3( PLFLT wx, PLFLT wy, PLFLT wz, PLFLT dx, PLFLT dy, PLFLT dz,
1983 PLFLT sx, PLFLT sy, PLFLT sz, PLFLT just, PLCHAR_VECTOR text )
1984 {
1985 PLFLT xpc, ypc, xrefpc, yrefpc, xdpc, ydpc, xspc, yspc, ld, ls, cp, shift;
1986 PLFLT x_o, y_o, z_o, x_dx, y_dy, z_dz;
1987 PLFLT theta, phi, stride, xform[6], affineL[6], cosphi;
1988
1989 // check that the plotting environment is set up
1990 if ( plsc->level < 3 )
1991 {
1992 plabort( "plptex3: Please set up window first" );
1993 return;
1994 }
1995
1996 // compute text x,y location in physical coordinates
1997 xpc = plP_wcpcx( plP_w3wcx( wx, wy, wz ) );
1998 ypc = plP_wcpcy( plP_w3wcy( wx, wy, wz ) );
1999
2000 // determine angle to rotate text in the x-y plane
2001 xdpc = plP_wcpcx( plP_w3wcx( wx + dx, wy + dy, wz + dz ) );
2002 ydpc = plP_wcpcy( plP_w3wcy( wx + dx, wy + dy, wz + dz ) );
2003 theta = atan2( ydpc - ypc, xdpc - xpc );
2004
2005 // Determine angle to shear text in the x-y plane. This is a little
2006 // messy, but basically the idea is:
2007 //
2008 // Compute the dot product of the vector d and the vector s to
2009 // determine the angle between them (acos(t) = d . s / |d| |s|).
2010 // Then because acos will return a number from 0.0 to PI, i.e.
2011 // only in quadrants 1 or 2, compute the cross product of the
2012 // two vectors. If this is negative then the angle is adjusted
2013 // 0.0 to -PI.
2014
2015 if ( ( sx == 0.0 ) && ( sy == 0.0 ) && ( sz == 0.0 ) )
2016 {
2017 phi = 0.0;
2018 }
2019 else
2020 {
2021 xspc = plP_wcpcx( plP_w3wcx( wx + sx, wy + sy, wz + sz ) );
2022 yspc = plP_wcpcy( plP_w3wcy( wx + sx, wy + sy, wz + sz ) );
2023 ld = sqrt( ( xpc - xdpc ) * ( xpc - xdpc ) + ( ypc - ydpc ) * ( ypc - ydpc ) );
2024 ls = sqrt( ( xpc - xspc ) * ( xpc - xspc ) + ( ypc - yspc ) * ( ypc - yspc ) );
2025 phi = acos( ( ( xdpc - xpc ) * ( xspc - xpc ) + ( ydpc - ypc ) * ( yspc - ypc ) ) / ( ld * ls ) );
2026 cp = ( xdpc - xpc ) * ( yspc - ypc ) - ( ydpc - ypc ) * ( xspc - xpc );
2027 if ( cp < 0.0 )
2028 {
2029 phi = -phi;
2030 }
2031 phi = 0.5 * PI - phi;
2032 }
2033
2034 // Determine how to adjust the "stride" of the text to make it
2035 // appear that it is going into (or out of) the page. Basically
2036 // scale the x baseline of the text by the normalized length of
2037 // the d vector projected into the x-y plane.
2038 x_o = plP_w3wcx( wx, wy, wz );
2039 y_o = plP_w3wcy( wx, wy, wz );
2040 z_o = plP_w3wcz( wx, wy, wz );
2041 x_dx = x_o - plP_w3wcx( wx + dx, wy + dy, wz + dz );
2042 y_dy = y_o - plP_w3wcy( wx + dx, wy + dy, wz + dz );
2043 z_dz = z_o - plP_w3wcz( wx + dx, wy + dy, wz + dz );
2044
2045 stride = sqrt( x_dx * x_dx + y_dy * y_dy );
2046 stride = stride / sqrt( x_dx * x_dx + y_dy * y_dy + z_dz * z_dz );
2047
2048 // compute the reference point
2049 xpc = plP_dcmmx( plP_pcdcx( (PLINT) xpc ) );
2050 ypc = plP_dcmmy( plP_pcdcy( (PLINT) ypc ) );
2051
2052 shift = plstrl( text ) * just;
2053 xrefpc = xpc - cos( theta ) * shift * stride;
2054 yrefpc = ypc - sin( theta ) * shift * stride;
2055
2056 xpc = plP_mmpcx( xpc );
2057 ypc = plP_mmpcy( ypc );
2058 xrefpc = plP_mmpcx( xrefpc );
2059 yrefpc = plP_mmpcy( yrefpc );
2060
2061 // compute the transform
2062 // This affine transformation corresponds to transforming from old
2063 // coordinates to new coordinates by rotating axes, y shearing
2064 // or (y skewing), and scaling.
2065 // Comment out the explicit xform calculations because we use
2066 // the affine utilities for that calculation instead.
2067 //
2068 // xform[0] = cos( theta ) * stride;
2069 // xform[1] = cos( theta ) * sin( phi ) - sin( theta ) * cos( phi );
2070 // xform[2] = sin( theta ) * stride;
2071 // xform[3] = sin( theta ) * sin( phi ) + cos( theta ) * cos( phi );
2072 //
2073 plP_affine_rotate( xform, 180. * theta / PI );
2074 plP_affine_yskew( affineL, -180. * phi / PI );
2075 plP_affine_multiply( xform, affineL, xform );
2076 cosphi = cos( phi );
2077 if ( fabs( cosphi ) > 1.e-300 )
2078 plP_affine_scale( affineL, 1. / stride, 1. / cosphi );
2079 else
2080 plP_affine_scale( affineL, 1. / stride, 1.e300 );
2081 plP_affine_multiply( xform, affineL, xform );
2082
2083 plP_text( 0, just, xform, (PLINT) xpc, (PLINT) ypc, (PLINT) xrefpc, (PLINT) yrefpc, text );
2084 }
2085
2086 //--------------------------------------------------------------------------
2087 // void plsfont()
2088 //
2089 // Set the family, style and weight of the current font.
2090 // This is a user-friendly front-end to plsfci.
2091 // Note: A negative value signifies that this element should not be changed.
2092 //--------------------------------------------------------------------------
2093 void
2094 c_plsfont( PLINT family, PLINT style, PLINT weight )
2095 {
2096 PLUNICODE fci;
2097
2098 plgfci( &fci );
2099
2100 if ( family >= 0 )
2101 {
2102 // Bounds checking assumes symbol is last font
2103 if ( family > PL_FCI_SYMBOL )
2104 plwarn( "plsfont: Value for family is out of range" );
2105 else
2106 plP_hex2fci( (unsigned char) family, PL_FCI_FAMILY, &fci );
2107 }
2108
2109 if ( style >= 0 )
2110 {
2111 // Bounds checking assumes oblique is last style
2112 if ( style > PL_FCI_OBLIQUE )
2113 plwarn( "plsfont: Value for style is out of range" );
2114 else
2115 plP_hex2fci( (unsigned char) style, PL_FCI_STYLE, &fci );
2116 }
2117
2118 if ( weight >= 0 )
2119 {
2120 // Bounds checking assumes bold is last weight
2121 if ( weight > PL_FCI_BOLD )
2122 plwarn( "plsfont: Value for weight is out of range" );
2123 else
2124 plP_hex2fci( (unsigned char) weight, PL_FCI_WEIGHT, &fci );
2125 }
2126
2127 plsfci( fci );
2128 }
2129
2130 //--------------------------------------------------------------------------
2131 // void plgfont()
2132 //
2133 // Get the family, style and weight of the current font.
2134 // This is a user-friendly front-end to plgfci.
2135 // Note: A NULL pointer signifies that this value should not be returned.
2136 //--------------------------------------------------------------------------
2137 void
2138 c_plgfont( PLINT *p_family, PLINT *p_style, PLINT *p_weight )
2139 {
2140 PLUNICODE fci;
2141 unsigned char val;
2142
2143 plgfci( &fci );
2144
2145 if ( p_family )
2146 {
2147 plP_fci2hex( fci, &val, PL_FCI_FAMILY );
2148 *p_family = (PLINT) val;
2149 }
2150
2151 if ( p_style )
2152 {
2153 plP_fci2hex( fci, &val, PL_FCI_STYLE );
2154 *p_style = (PLINT) val;
2155 }
2156
2157 if ( p_weight )
2158 {
2159 plP_fci2hex( fci, &val, PL_FCI_WEIGHT );
2160 *p_weight = (PLINT) val;
2161 }
2162 }
2163
2164
2165 #undef PLSYM_H
2166 #endif
plP_script_scale
void plP_script_scale(PLBOOL ifupper, PLINT *level, PLFLT *old_scale, PLFLT *scale, PLFLT *old_offset, PLFLT *offset)
Definition: plsym.c:1302
plplotP.h
PL_FCI_BOLD
#define PL_FCI_BOLD
Definition: plplot.h:391
pdf_rdx
int pdf_rdx(U_CHAR *x, long nitems, PDFstrm *pdfs)
Definition: pdfutils.c:464
PLMAXSTR
#define PLMAXSTR
Definition: plsym.c:64
plgesc
void plgesc(char *p_esc)
Definition: plcore.c:3914
plexit
void plexit(PLCHAR_VECTOR errormsg)
Definition: plctrl.c:1958
PlPlotter::width
int width
Definition: plplotter.c:119
c_plstring3
void c_plstring3(PLINT n, PLFLT_VECTOR x, PLFLT_VECTOR y, PLFLT_VECTOR z, PLCHAR_VECTOR string)
Definition: plsym.c:311
plP_esc
void plP_esc(PLINT op, void *ptr)
Definition: plcore.c:273
c_plmtex
void c_plmtex(PLCHAR_VECTOR side, PLFLT disp, PLFLT pos, PLFLT just, PLCHAR_VECTOR text)
Definition: plsym.c:594
EscText::just
PLFLT just
Definition: plplotP.h:708
plP_fci2hex
void plP_fci2hex(PLUNICODE fci, unsigned char *phexdigit, unsigned char hexpower)
Definition: plcore.c:3958
plP_w3wcz
PLFLT plP_w3wcz(PLFLT x, PLFLT y, PLFLT z)
Definition: plcvt.c:233
plP_pcdcy
PLFLT plP_pcdcy(PLINT y)
Definition: plcvt.c:95
plP_wcpcx
PLINT plP_wcpcx(PLFLT x)
Definition: plcvt.c:63
plhrsh2
static void plhrsh2(PLINT ch, PLINT x, PLINT y)
Definition: plsym.c:475
pldeco
static void pldeco(short int **sym, PLINT *length, PLCHAR_VECTOR text)
Definition: plsym.c:1106
PDFstrm
Definition: pdf.h:49
PLUNICODE
PLUINT PLUNICODE
Definition: plplot.h:201
PL_FCI_SYMBOL
#define PL_FCI_SYMBOL
Definition: plplot.h:384
PL_FCI_SERIF
#define PL_FCI_SERIF
Definition: plplot.h:381
ROUND
#define ROUND(a)
Definition: plplotP.h:202
plP_stindex
PLINT plP_stindex(PLCHAR_VECTOR str1, PLCHAR_VECTOR str2)
Definition: plsym.c:1233
plfontrel
void plfontrel(void)
Definition: plsym.c:1463
plP_greek_mnemonic
const char plP_greek_mnemonic[]
Definition: plcore.c:142
plfntld
void plfntld(PLINT fnt)
Definition: plsym.c:1394
fntindx
static short int * fntindx
Definition: plsym.c:56
plP_grange
void plP_grange(PLFLT *p_zscl, PLFLT *p_zmin, PLFLT *p_zmax)
Definition: plcore.c:4152
PLCHAR_VECTOR
const char * PLCHAR_VECTOR
Definition: plplot.h:243
PL_FCI_OBLIQUE
#define PL_FCI_OBLIQUE
Definition: plplot.h:388
plP_text
void plP_text(PLINT base, PLFLT just, PLFLT *xform, PLINT x, PLINT y, PLINT refx, PLINT refy, PLCHAR_VECTOR string)
Definition: plcore.c:1186
plchar
static void plchar(signed char *xygrid, PLFLT *xform, PLINT base, PLINT oline, PLINT uline, PLINT refx, PLINT refy, PLFLT scale, PLFLT xpmm, PLFLT ypmm, PLFLT *p_xorg, PLFLT *p_yorg, PLFLT *p_width)
Definition: plsym.c:870
PLESC_END_TEXT
#define PLESC_END_TEXT
Definition: plplot.h:301
plP_stsearch
PLBOOL plP_stsearch(PLCHAR_VECTOR str, int chr)
Definition: plsym.c:1256
c_plpoin3
void c_plpoin3(PLINT n, PLFLT_VECTOR x, PLFLT_VECTOR y, PLFLT_VECTOR z, PLINT code)
Definition: plsym.c:235
pdf_rd_2bytes
int pdf_rd_2bytes(PDFstrm *pdfs, U_SHORT *ps)
Definition: pdfutils.c:710
Hershey_to_Unicode_table::Hershey
unsigned int Hershey
Definition: plplotP.h:458
numberfonts
static short int numberfonts
Definition: plsym.c:58
fontloaded
static short fontloaded
Definition: plsym.c:61
plabort
void plabort(PLCHAR_VECTOR errormsg)
Definition: plctrl.c:1894
PL_SFONT
#define PL_SFONT
Definition: plplotP.h:395
hershey2unicode
int hershey2unicode(int in)
symbol_buffer
static short symbol_buffer[PLMAXSTR]
Definition: plsym.c:69
PL_FCI_ITALIC
#define PL_FCI_ITALIC
Definition: plplot.h:387
c_plstring
void c_plstring(PLINT n, PLFLT_VECTOR x, PLFLT_VECTOR y, PLCHAR_VECTOR string)
Definition: plsym.c:108
U_SHORT
#define U_SHORT
Definition: pdf.h:30
c_plpoin
void c_plpoin(PLINT n, PLFLT_VECTOR x, PLFLT_VECTOR y, PLINT code)
Definition: plsym.c:172
plstrl
PLFLT plstrl(PLCHAR_VECTOR string)
Definition: plsym.c:976
STLEN
#define STLEN
Definition: plsym.c:65
plP_affine_yskew
void plP_affine_yskew(PLFLT *affine_vector, PLFLT angle)
Definition: plaffine.c:162
c_plmtex3
void c_plmtex3(PLCHAR_VECTOR side, PLFLT disp, PLFLT pos, PLFLT just, PLCHAR_VECTOR text)
Definition: plsym.c:1610
plstr
void plstr(PLINT base, PLFLT *xform, PLINT refx, PLINT refy, PLCHAR_VECTOR string)
Definition: plsym.c:810
plcvec
static PLINT plcvec(PLINT ch, signed char **xygr)
Definition: plsym.c:1048
font_types
static const char font_types[]
Definition: plsym.c:67
PLESC_TEXT_CHAR
#define PLESC_TEXT_CHAR
Definition: plplot.h:299
plP_mmpcy
PLINT plP_mmpcy(PLFLT y)
Definition: plcvt.c:55
PLINT
int PLINT
Definition: plplot.h:181
PLBOOL
PLINT PLBOOL
Definition: plplot.h:204
plP_gclp
void plP_gclp(PLINT *p_ixmin, PLINT *p_ixmax, PLINT *p_iymin, PLINT *p_iymax)
Definition: plcore.c:4174
EscText::n_fci
PLUNICODE n_fci
Definition: plplotP.h:726
pljoin
#define pljoin
Definition: plplot.h:756
FCI_to_FontName_Table::pfont
const unsigned char * pfont
Definition: plplotP.h:1232
c_plsfont
void c_plsfont(PLINT family, PLINT style, PLINT weight)
Definition: plsym.c:2094
fntbffr
static signed char * fntbffr
Definition: plsym.c:57
EscText
Definition: plplotP.h:699
plgchr
#define plgchr
Definition: plplot.h:722
c_plgfont
void c_plgfont(PLINT *p_family, PLINT *p_style, PLINT *p_weight)
Definition: plsym.c:2138
plio_fread
void plio_fread(void *buf, size_t size, size_t nmemb, FILE *stream)
Definition: plstdio.c:98
TRUE
#define TRUE
Definition: plplotP.h:176
EscText::text_type
enum EscText::@5 text_type
numberchars
static short int numberchars
Definition: plsym.c:58
plP_dcmmy
PLFLT plP_dcmmy(PLFLT y)
Definition: plcvt.c:163
FALSE
#define FALSE
Definition: plplotP.h:177
c_plsym
void c_plsym(PLINT n, PLFLT_VECTOR x, PLFLT_VECTOR y, PLINT code)
Definition: plsym.c:128
c_pllab
void c_pllab(PLCHAR_VECTOR xlabel, PLCHAR_VECTOR ylabel, PLCHAR_VECTOR tlabel)
Definition: plsym.c:549
PL_FCI_STYLE
#define PL_FCI_STYLE
Definition: plplot.h:377
PL_FCI_SCRIPT
#define PL_FCI_SCRIPT
Definition: plplot.h:383
TRANSFORM
#define TRANSFORM(x, y, xnew, ynew)
Definition: plplotP.h:214
PL_XFONT
#define PL_XFONT
Definition: plplotP.h:394
xform
void xform(PLFLT x, PLFLT y, PLFLT *tx, PLFLT *ty, PLPointer pltr_data)
Definition: plplot_octaveOCTAVE_wrap.cxx:2917
hershey_to_unicode_lookup_table
Hershey_to_Unicode_table hershey_to_unicode_lookup_table[]
Definition: plhershey-unicode.h:48
plP_affine_multiply
void plP_affine_multiply(PLFLT *affine_vectorA, PLFLT_VECTOR affine_vectorB, PLFLT_VECTOR affine_vectorC)
Definition: plaffine.c:184
plP_affine_rotate
void plP_affine_rotate(PLFLT *affine_vector, PLFLT angle)
Definition: plaffine.c:123
plP_w3wcy
PLFLT plP_w3wcy(PLFLT x, PLFLT y, PLFLT z)
Definition: plcvt.c:222
FCI_to_FontName_Table
Definition: plplotP.h:1229
plgfci
#define plgfci
Definition: plplot.h:735
PLESC_BEGIN_TEXT
#define PLESC_BEGIN_TEXT
Definition: plplot.h:298
plP_pcdcx
PLFLT plP_pcdcx(PLINT x)
Definition: plcvt.c:87
plhrsh
void plhrsh(PLINT ch, PLINT x, PLINT y)
Definition: plsym.c:359
EscText::unicode_array_len
unsigned short unicode_array_len
Definition: plplotP.h:736
PDFstrm::file
FILE * file
Definition: pdf.h:51
plhershey2unicode
int plhershey2unicode(int in)
Definition: plsym.c:1490
text
static int text
Definition: ps.c:77
plP_draphy
void plP_draphy(PLINT x, PLINT y)
Definition: plline.c:472
Hershey_to_Unicode_table::Unicode
PLUNICODE Unicode
Definition: plplotP.h:459
c_plfont
void c_plfont(PLINT ifont)
Definition: plsym.c:1341
fntlkup
static short int * fntlkup
Definition: plsym.c:55
PLFLT
float PLFLT
Definition: plplot.h:163
plP_w3wcx
PLFLT plP_w3wcx(PLFLT x, PLFLT y, PLFLT PL_UNUSED(z))
Definition: plcvt.c:212
pdf_close
int pdf_close(PDFstrm *pdfs)
Definition: pdfutils.c:238
PL_FCI_FAMILY
#define PL_FCI_FAMILY
Definition: plplot.h:376
plP_draphy_poly
void plP_draphy_poly(PLINT *x, PLINT *y, PLINT n)
Definition: plline.c:527
plP_hex2fci
void plP_hex2fci(unsigned char hexdigit, unsigned char hexpower, PLUNICODE *pfci)
Definition: plcore.c:3945
plhershey-unicode.h
plP_movphy
void plP_movphy(PLINT x, PLINT y)
Definition: plline.c:459
EscText::symbol
PLINT symbol
Definition: plplotP.h:740
free_mem
#define free_mem(a)
Definition: plplotP.h:182
PL_FCI_WEIGHT
#define PL_FCI_WEIGHT
Definition: plplot.h:378
plP_mmpcx
PLINT plP_mmpcx(PLFLT x)
Definition: plcvt.c:47
plP_wcdcx
PLFLT plP_wcdcx(PLFLT x)
Definition: plcvt.c:119
PI
#define PI
Definition: plplotP.h:290
plP_FCI2FontName
PLCHAR_VECTOR plP_FCI2FontName(PLUNICODE fci, const FCI_to_FontName_Table lookup[], const int nlookup)
Definition: plsym.c:1548
plP_wcpcy
PLINT plP_wcpcy(PLFLT y)
Definition: plcvt.c:73
Hershey_to_Unicode_table::Font
char Font
Definition: plplotP.h:460
c_plptex
void c_plptex(PLFLT wx, PLFLT wy, PLFLT dx, PLFLT dy, PLFLT just, PLCHAR_VECTOR text)
Definition: plsym.c:734
PLESC_HAS_TEXT
#define PLESC_HAS_TEXT
Definition: plplot.h:290
plwarn
void plwarn(PLCHAR_VECTOR errormsg)
Definition: plctrl.c:1863
EscText::y
PLINT y
Definition: plplotP.h:713
c_plptex3
void c_plptex3(PLFLT wx, PLFLT wy, PLFLT wz, PLFLT dx, PLFLT dy, PLFLT dz, PLFLT sx, PLFLT sy, PLFLT sz, PLFLT just, PLCHAR_VECTOR text)
Definition: plsym.c:1982
pdf_rd_2nbytes
int pdf_rd_2nbytes(PDFstrm *pdfs, U_SHORT *s, PLINT n)
Definition: pdfutils.c:771
EscText::string
const char * string
Definition: plplotP.h:739
plP_sclp
void plP_sclp(PLINT ixmin, PLINT ixmax, PLINT iymin, PLINT iymax)
Definition: plcore.c:4185
indxleng
static short int indxleng
Definition: plsym.c:59
plbuf_write
void plbuf_write(PLStream *pls, void *data, size_t bytes)
Definition: plbuf.c:660
number_of_entries_in_hershey_to_unicode_table
int number_of_entries_in_hershey_to_unicode_table
Definition: plhershey-unicode.h:40
ABS
#define ABS(a)
Definition: plplotP.h:199
xygrid
static signed char xygrid[STLEN]
Definition: plsym.c:70
PLFLT_VECTOR
const PLFLT * PLFLT_VECTOR
Definition: plplot.h:244
EscText::x
PLINT x
Definition: plplotP.h:712
EscText::unicode_char
PLUNICODE unicode_char
Definition: plplotP.h:731
PL_FCI_SANS
#define PL_FCI_SANS
Definition: plplot.h:380
EscText::n_char
PLUNICODE n_char
Definition: plplotP.h:727
plsfci
#define plsfci
Definition: plplot.h:817
plLibOpenPdfstrm
PDFstrm * plLibOpenPdfstrm(PLCHAR_VECTOR fn)
Definition: plctrl.c:2263
plP_wcdcy
PLFLT plP_wcdcy(PLFLT y)
Definition: plcvt.c:127
EscText::unicode_array
PLUNICODE * unicode_array
Definition: plplotP.h:735
EscText::font_face
char font_face
Definition: plplotP.h:720
plmtex
#define plmtex
Definition: plplot.h:773
plP_affine_scale
void plP_affine_scale(PLFLT *affine_vector, PLFLT xscale, PLFLT yscale)
Definition: plaffine.c:93
plP_dcmmx
PLFLT plP_dcmmx(PLFLT x)
Definition: plcvt.c:155
plP_gdom
void plP_gdom(PLFLT *p_xmin, PLFLT *p_xmax, PLFLT *p_ymin, PLFLT *p_ymax)
Definition: plcore.c:4141
EscText::xform
PLFLT * xform
Definition: plplotP.h:709
EscText::base
PLINT base
Definition: plplotP.h:707
plP_strpos
PLINT plP_strpos(PLCHAR_VECTOR str, int chr)
Definition: plsym.c:1216
PL_FCI_MARK
#define PL_FCI_MARK
Definition: plplot.h:370