PLplot 5.9.6
|
00001 /* $Id$ 00002 * 00003 * Point, symbol, and string plotting routines. 00004 * Also font management code. See the description of plLibOpen() for 00005 * the search path used in finding the font files. 00006 * 00007 * Copyright (C) 1992 Geoffrey Furnish 00008 * Copyright (C) 1993, 1994, 1995, 2000, 2001, 2002 Maurice LeBrun 00009 * Copyright (C) 2000, 2002, 2004, 2005 Alan W. Irwin 00010 * Copyright (C) 2001, 2003, 2004 Rafael Laboissiere 00011 * Copyright (C) 2002 Vincent Darley 00012 * Copyright (C) 2004 Andrew Ross 00013 * Copyright (C) 2007 Hazen Babcock 00014 * 00015 * This file is part of PLplot. 00016 * 00017 * PLplot is free software; you can redistribute it and/or modify 00018 * it under the terms of the GNU General Library Public License as published 00019 * by the Free Software Foundation; either version 2 of the License, or 00020 * (at your option) any later version. 00021 * 00022 * PLplot is distributed in the hope that it will be useful, 00023 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00024 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00025 * GNU Library General Public License for more details. 00026 * 00027 * You should have received a copy of the GNU Library General Public License 00028 * along with PLplot; if not, write to the Free Software 00029 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00030 */ 00031 00032 #ifndef __PLSYM_H__ 00033 #define __PLSYM_H__ 00034 00035 #include "plplotP.h" 00036 #include <float.h> 00037 #include <ctype.h> 00038 #include "plhershey-unicode.h" 00039 00040 /* Declarations */ 00041 00042 static short int *fntlkup; 00043 static short int *fntindx; 00044 static signed char *fntbffr; 00045 static short int numberfonts, numberchars; 00046 static short int indxleng; 00047 00048 static short fontloaded = 0; 00049 /* moved to plstr.h, plsc->cfont static PLINT font = 1; current font */ 00050 00051 #define PLMAXSTR 300 00052 #define STLEN 250 00053 00054 static const char font_types[] = "nris"; 00055 00056 static short symbol_buffer[PLMAXSTR]; 00057 static signed char xygrid[STLEN]; 00058 00059 int hershey2unicode( int in ); 00060 00061 /* Static function prototypes */ 00062 00063 static void 00064 pldeco( short int **sym, PLINT *length, const char *text ); 00065 00066 static void 00067 plchar( signed char *xygrid, PLFLT *xform, PLINT base, PLINT oline, PLINT uline, 00068 PLINT refx, PLINT refy, PLFLT scale, PLFLT xpmm, PLFLT ypmm, 00069 PLFLT *p_xorg, PLFLT *p_yorg, PLFLT *p_width ); 00070 00071 static PLINT 00072 plcvec( PLINT ch, signed char **xygr ); 00073 00074 static void 00075 plhrsh( PLINT ch, PLINT x, PLINT y ); 00076 00077 static void 00078 plhrsh2( PLINT ch, PLINT x, PLINT y ); 00079 00080 /*--------------------------------------------------------------------------*\ 00081 * void plsym() 00082 * 00083 * Plots array y against x for n points using Hershey symbol "code". 00084 \*--------------------------------------------------------------------------*/ 00085 00086 void 00087 c_plsym( PLINT n, PLFLT *x, PLFLT *y, PLINT code ) 00088 { 00089 PLINT i; 00090 PLFLT xt, yt; 00091 00092 if ( plsc->level < 3 ) 00093 { 00094 plabort( "plsym: Please set up window first" ); 00095 return; 00096 } 00097 if ( code < 0 ) 00098 { 00099 plabort( "plsym: Invalid code" ); 00100 return; 00101 } 00102 00103 for ( i = 0; i < n; i++ ) 00104 { 00105 TRANSFORM( x[i], y[i], &xt, &yt ); 00106 plhrsh( code, plP_wcpcx( xt ), plP_wcpcy( yt ) ); 00107 } 00108 } 00109 00110 /*--------------------------------------------------------------------------*\ 00111 * void plpoin() 00112 * 00113 * Plots array y against x for n points using ASCII code "code". 00114 * 00115 * code=-1 means try to just draw a point. Right now it's just a move and 00116 * a draw at the same place. Not ideal, since a sufficiently intelligent 00117 * output device may optimize it away, or there may be faster ways of 00118 * doing it. This is OK for now, though, and offers a 4X speedup over 00119 * drawing a Hershey font "point" (which is actually diamond shaped and 00120 * therefore takes 4 strokes to draw). 00121 \*--------------------------------------------------------------------------*/ 00122 00123 void 00124 c_plpoin( PLINT n, PLFLT *x, PLFLT *y, PLINT code ) 00125 { 00126 PLINT i, sym, ifont = plsc->cfont; 00127 PLFLT xt, yt; 00128 00129 if ( plsc->level < 3 ) 00130 { 00131 plabort( "plpoin: Please set up window first" ); 00132 return; 00133 } 00134 if ( code < -1 || code > 127 ) 00135 { 00136 plabort( "plpoin: Invalid code" ); 00137 return; 00138 } 00139 00140 if ( code == -1 ) 00141 { 00142 for ( i = 0; i < n; i++ ) 00143 { 00144 TRANSFORM( x[i], y[i], &xt, &yt ); 00145 pljoin( xt, yt, xt, yt ); 00146 } 00147 } 00148 else 00149 { 00150 if ( ifont > numberfonts ) 00151 ifont = 1; 00152 sym = *( fntlkup + ( ifont - 1 ) * numberchars + code ); 00153 // One-time diagnostic output. 00154 // fprintf(stdout, "plploin code, sym = %d, %d\n", code, sym); 00155 00156 for ( i = 0; i < n; i++ ) 00157 { 00158 TRANSFORM( x[i], y[i], &xt, &yt ); 00159 plhrsh( sym, plP_wcpcx( xt ), plP_wcpcy( yt ) ); 00160 } 00161 } 00162 } 00163 00164 /*--------------------------------------------------------------------------*\ 00165 * void plpoin3(n, x, y, z, code) 00166 * 00167 * Draws a series of points in 3 space. Setup similar to plline3(). 00168 \*--------------------------------------------------------------------------*/ 00169 00170 void 00171 c_plpoin3( PLINT n, PLFLT *x, PLFLT *y, PLFLT *z, PLINT code ) 00172 { 00173 PLINT i, sym, ifont = plsc->cfont; 00174 PLFLT u, v; 00175 PLFLT xmin, xmax, ymin, ymax, zmin, zmax, zscale; 00176 00177 if ( plsc->level < 3 ) 00178 { 00179 plabort( "plpoin3: Please set up window first" ); 00180 return; 00181 } 00182 if ( code < -1 || code > 127 ) 00183 { 00184 plabort( "plpoin3: Invalid code" ); 00185 return; 00186 } 00187 00188 plP_gdom( &xmin, &xmax, &ymin, &ymax ); 00189 plP_grange( &zscale, &zmin, &zmax ); 00190 00191 if ( code == -1 ) 00192 { 00193 for ( i = 0; i < n; i++ ) 00194 { 00195 if ( x[i] >= xmin && x[i] <= xmax && 00196 y[i] >= ymin && y[i] <= ymax && 00197 z[i] >= zmin && z[i] <= zmax ) 00198 { 00199 u = plP_wcpcx( plP_w3wcx( x[i], y[i], z[i] ) ); 00200 v = plP_wcpcy( plP_w3wcy( x[i], y[i], z[i] ) ); 00201 plP_movphy( (PLINT) u, (PLINT) v ); 00202 plP_draphy( (PLINT) u, (PLINT) v ); 00203 } 00204 } 00205 } 00206 else 00207 { 00208 if ( ifont > numberfonts ) 00209 ifont = 1; 00210 sym = *( fntlkup + ( ifont - 1 ) * numberchars + code ); 00211 00212 for ( i = 0; i < n; i++ ) 00213 { 00214 if ( x[i] >= xmin && x[i] <= xmax && 00215 y[i] >= ymin && y[i] <= ymax && 00216 z[i] >= zmin && z[i] <= zmax ) 00217 { 00218 u = plP_wcpcx( plP_w3wcx( x[i], y[i], z[i] ) ); 00219 v = plP_wcpcy( plP_w3wcy( x[i], y[i], z[i] ) ); 00220 plhrsh( sym, (PLINT) u, (PLINT) v ); 00221 } 00222 } 00223 } 00224 return; 00225 } 00226 00227 /*--------------------------------------------------------------------------*\ 00228 * static void plhrsh(PLINT ch, PLINT x, PLINT y) 00229 * PLINT ch - hershey code to plot 00230 * PLINT x - device-world x coordinate of hershey character 00231 * PLINT y - device-world y coordinate of hershey character 00232 * 00233 * Writes the Hershey symbol "ch" centred at the physical coordinate (x,y). 00234 * This function is now just a "spoof" front end to the old plhersh, 00235 * which has now been renamed to plhrsh2(). All this function does is 00236 * decide whether or not we should render natively as unicode, and then 00237 * convert between hershey and unicode. 00238 * 00239 * If the function KNOWS there isn't a unicode equivalent, then it will 00240 * try to render it as a hershey font. Understandably, this might make 00241 * testing out the unicode functions a little tricky, so if you want 00242 * to disable this behaviour, recompile with PL_TEST_FOR_MISSING_GLYPHS 00243 * defined. 00244 \*--------------------------------------------------------------------------*/ 00245 00246 static void 00247 plhrsh( PLINT ch, PLINT x, PLINT y ) 00248 { 00249 EscText args; 00250 int idx; 00251 PLUNICODE unicode_char; 00252 00253 /* Check to see if the device understands unicode and wants to draw 00254 * symbols. 00255 */ 00256 if ( ( plsc->dev_text ) && ( plsc->dev_unicode ) && ( !plsc->dev_hrshsym ) ) 00257 { 00258 idx = plhershey2unicode( ch ); /* Get the index in the lookup table */ 00259 unicode_char = hershey_to_unicode_lookup_table[idx].Unicode; 00260 00261 /* 00262 * Test to see if there is a defined unicode glyph for this hershey code; 00263 * if there isn't, then we pass the glyph to plhersh, and have it 00264 * rendered the old fashioned way. 00265 * Otherwise, we let the driver render it as unicode 00266 */ 00267 00268 if ( ( unicode_char == 0 ) || ( idx == -1 ) ) 00269 { 00270 #ifndef PL_TEST_FOR_MISSING_GLYPHS 00271 plhrsh2( ch, x, y ); 00272 #endif 00273 } 00274 else 00275 { 00276 PLUNICODE plhrsh_unicode_buffer[3], fci; 00277 PLFLT xform[] = { 1.0, 0.0, 0.0, 1.0 }; 00278 char esc; 00279 args.unicode_char = unicode_char; 00280 args.font_face = hershey_to_unicode_lookup_table[idx].Font; 00281 /* Comment out to fix problem with ps, psttf drivers */ 00282 /*args.base = 1;*/ 00283 args.base = 0; 00284 args.just = .5; 00285 args.xform = 0; 00286 args.x = x; 00287 args.y = y; 00288 args.string = NULL; /* Since we are using unicode, we want this to be NULL */ 00289 /* "array method" */ 00290 plgesc( &esc ); 00291 args.xform = xform; 00292 args.unicode_array_len = 1; 00293 plhrsh_unicode_buffer[0] = unicode_char; 00294 /* watch out for escape character and unescape it by appending 00295 * one extra. */ 00296 if ( unicode_char == esc ) 00297 { 00298 args.unicode_array_len = 2; 00299 plhrsh_unicode_buffer[1] = unicode_char; 00300 } 00301 00302 /* No need to change font back since only one character. */ 00303 args.unicode_array = &plhrsh_unicode_buffer[0]; /* Get address of the unicode buffer (even though it is currently static) */ 00304 00305 plsc->original_chrht = plsc->chrht; 00306 plsc->original_chrdef = plsc->chrdef; 00307 plsc->chrht = plsc->symht; 00308 plsc->chrdef = plsc->symdef; 00309 00310 if ( plsc->alt_unicode ) 00311 { 00312 plgfci( &fci ); 00313 args.n_fci = fci; 00314 args.n_char = unicode_char; 00315 plP_esc( PLESC_BEGIN_TEXT, &args ); 00316 plP_esc( PLESC_TEXT_CHAR, &args ); 00317 plP_esc( PLESC_END_TEXT, &args ); 00318 } 00319 else 00320 { 00321 plP_esc( PLESC_HAS_TEXT, &args ); 00322 } 00323 00324 plsc->chrht = plsc->original_chrht; 00325 plsc->chrdef = plsc->original_chrdef; 00326 } 00327 } 00328 else 00329 { 00330 plhrsh2( ch, x, y ); 00331 } 00332 } 00333 00334 /*--------------------------------------------------------------------------*\ 00335 * void plhrsh2() 00336 * 00337 * Writes the Hershey symbol "ch" centred at the physical coordinate (x,y). 00338 \*--------------------------------------------------------------------------*/ 00339 00340 static void 00341 plhrsh2( PLINT ch, PLINT x, PLINT y ) 00342 { 00343 PLINT cx, cy, k, penup, style; 00344 signed char *vxygrid = 0; 00345 PLFLT scale, xscale, yscale; 00346 PLINT llx[STLEN], lly[STLEN], l = 0; 00347 00348 penup = 1; 00349 scale = 0.05 * plsc->symht; 00350 00351 if ( !plcvec( ch, &vxygrid ) ) 00352 { 00353 plP_movphy( x, y ); 00354 return; 00355 } 00356 00357 /* Line style must be continuous */ 00358 00359 style = plsc->nms; 00360 plsc->nms = 0; 00361 00362 /* Compute how many physical pixels correspond to a character pixel */ 00363 00364 xscale = scale * plsc->xpmm; 00365 yscale = scale * plsc->ypmm; 00366 00367 k = 4; 00368 for (;; ) 00369 { 00370 cx = vxygrid[k++]; 00371 cy = vxygrid[k++]; 00372 if ( cx == 64 && cy == 64 ) 00373 { 00374 if ( l ) 00375 { 00376 plP_draphy_poly( llx, lly, l ); 00377 l = 0; 00378 } 00379 plP_movphy( x, y ); 00380 plsc->nms = style; 00381 return; 00382 } 00383 else if ( cx == 64 && cy == 0 ) 00384 penup = 1; 00385 else 00386 { 00387 if ( penup == 1 ) 00388 { 00389 if ( l ) 00390 { 00391 plP_draphy_poly( llx, lly, l ); 00392 l = 0; 00393 } 00394 llx[l] = ROUND( x + xscale * cx ); 00395 lly[l++] = ROUND( y + yscale * cy ); 00396 plP_movphy( llx[l - 1], lly[l - 1] ); 00397 penup = 0; 00398 } 00399 else 00400 { 00401 llx[l] = ROUND( x + xscale * cx ); 00402 lly[l++] = ROUND( y + yscale * cy ); 00403 } 00404 } 00405 } 00406 } 00407 00408 /*--------------------------------------------------------------------------*\ 00409 * void pllab() 00410 * 00411 * Simple routine for labelling graphs. 00412 \*--------------------------------------------------------------------------*/ 00413 00414 void 00415 c_pllab( const char *xlabel, const char *ylabel, const char *tlabel ) 00416 { 00417 if ( plsc->level < 2 ) 00418 { 00419 plabort( "pllab: Please set up viewport first" ); 00420 return; 00421 } 00422 00423 plmtex( "t", (PLFLT) 2.0, (PLFLT) 0.5, (PLFLT) 0.5, tlabel ); 00424 plmtex( "b", (PLFLT) 3.2, (PLFLT) 0.5, (PLFLT) 0.5, xlabel ); 00425 plmtex( "l", (PLFLT) 5.0, (PLFLT) 0.5, (PLFLT) 0.5, ylabel ); 00426 } 00427 00428 /*--------------------------------------------------------------------------*\ 00429 * void plmtex() 00430 * 00431 * Prints out "text" at specified position relative to viewport 00432 * (may be inside or outside) 00433 * 00434 * side String which is one of the following: 00435 * B or b : Bottom of viewport 00436 * T or t : Top of viewport 00437 * BV or bv : Bottom of viewport, vertical text 00438 * TV or tv : Top of viewport, vertical text 00439 * L or l : Left of viewport 00440 * R or r : Right of viewport 00441 * LV or lv : Left of viewport, vertical text 00442 * RV or rv : Right of viewport, vertical text 00443 * 00444 * disp Displacement from specified edge of viewport, measured outwards from 00445 * the viewport in units of the current character height. The 00446 * centerlines of the characters are aligned with the specified 00447 * position. 00448 * 00449 * pos Position of the reference point of the string relative to the 00450 * viewport edge, ranging from 0.0 (left-hand edge) to 1.0 (right-hand 00451 * edge) 00452 * 00453 * just Justification of string relative to reference point 00454 * just = 0.0 => left hand edge of string is at reference 00455 * just = 1.0 => right hand edge of string is at reference 00456 * just = 0.5 => center of string is at reference 00457 \*--------------------------------------------------------------------------*/ 00458 00459 void 00460 c_plmtex( const char *side, PLFLT disp, PLFLT pos, PLFLT just, 00461 const char *text ) 00462 { 00463 PLINT clpxmi, clpxma, clpymi, clpyma; 00464 PLINT vert, refx, refy, x, y; 00465 PLFLT xdv, ydv, xmm, ymm, refxmm, refymm, shift, xform[4]; 00466 PLFLT chrdef, chrht; 00467 PLFLT dispx, dispy; 00468 00469 if ( plsc->level < 2 ) 00470 { 00471 plabort( "plmtex: Please set up viewport first" ); 00472 return; 00473 } 00474 00475 /* Open clip limits to subpage limits */ 00476 00477 plP_gclp( &clpxmi, &clpxma, &clpymi, &clpyma ); /* get and store current clip limits */ 00478 plP_sclp( plsc->sppxmi, plsc->sppxma, plsc->sppymi, plsc->sppyma ); 00479 00480 if ( plP_stindex( side, "BV" ) != -1 || plP_stindex( side, "bv" ) != -1 ) 00481 { 00482 vert = 1; 00483 xdv = plsc->vpdxmi + ( plsc->vpdxma - plsc->vpdxmi ) * pos; 00484 ydv = plsc->vpdymi; 00485 dispx = 0; 00486 dispy = -disp; 00487 } 00488 else if ( plP_stindex( side, "TV" ) != -1 || plP_stindex( side, "tv" ) != -1 ) 00489 { 00490 vert = 1; 00491 xdv = plsc->vpdxmi + ( plsc->vpdxma - plsc->vpdxmi ) * pos; 00492 ydv = plsc->vpdyma; 00493 dispx = 0; 00494 dispy = disp; 00495 } 00496 else if ( plP_stsearch( side, 'b' ) ) 00497 { 00498 vert = 0; 00499 xdv = plsc->vpdxmi + ( plsc->vpdxma - plsc->vpdxmi ) * pos; 00500 ydv = plsc->vpdymi; 00501 dispx = 0; 00502 dispy = -disp; 00503 } 00504 else if ( plP_stsearch( side, 't' ) ) 00505 { 00506 vert = 0; 00507 xdv = plsc->vpdxmi + ( plsc->vpdxma - plsc->vpdxmi ) * pos; 00508 ydv = plsc->vpdyma; 00509 dispx = 0; 00510 dispy = disp; 00511 } 00512 else if ( plP_stindex( side, "LV" ) != -1 || plP_stindex( side, "lv" ) != -1 ) 00513 { 00514 vert = 0; 00515 xdv = plsc->vpdxmi; 00516 ydv = plsc->vpdymi + ( plsc->vpdyma - plsc->vpdymi ) * pos; 00517 dispx = -disp; 00518 dispy = 0; 00519 } 00520 else if ( plP_stindex( side, "RV" ) != -1 || plP_stindex( side, "rv" ) != -1 ) 00521 { 00522 vert = 0; 00523 xdv = plsc->vpdxma; 00524 ydv = plsc->vpdymi + ( plsc->vpdyma - plsc->vpdymi ) * pos; 00525 dispx = disp; 00526 dispy = 0; 00527 } 00528 else if ( plP_stsearch( side, 'l' ) ) 00529 { 00530 vert = 1; 00531 xdv = plsc->vpdxmi; 00532 ydv = plsc->vpdymi + ( plsc->vpdyma - plsc->vpdymi ) * pos; 00533 dispx = -disp; 00534 dispy = 0; 00535 } 00536 else if ( plP_stsearch( side, 'r' ) ) 00537 { 00538 vert = 1; 00539 xdv = plsc->vpdxma; 00540 ydv = plsc->vpdymi + ( plsc->vpdyma - plsc->vpdymi ) * pos; 00541 dispx = disp; 00542 dispy = 0; 00543 } 00544 else 00545 { 00546 plP_sclp( clpxmi, clpxma, clpymi, clpyma ); /* restore initial clip limits */ 00547 return; 00548 } 00549 00550 /* Transformation matrix */ 00551 00552 if ( vert != 0 ) 00553 { 00554 xform[0] = 0.0; 00555 xform[1] = -1.0; 00556 xform[2] = 1.0; 00557 xform[3] = 0.0; 00558 } 00559 else 00560 { 00561 xform[0] = 1.0; 00562 xform[1] = 0.0; 00563 xform[2] = 0.0; 00564 xform[3] = 1.0; 00565 } 00566 00567 /* Convert to physical units (mm) and compute shifts */ 00568 00569 plgchr( &chrdef, &chrht ); 00570 shift = ( just == 0.0 ) ? 0.0 : plstrl( text ) * just; 00571 00572 xmm = plP_dcmmx( xdv ) + dispx * chrht; 00573 ymm = plP_dcmmy( ydv ) + dispy * chrht; 00574 refxmm = xmm - shift * xform[0]; 00575 refymm = ymm - shift * xform[2]; 00576 00577 /* Convert to device units (pixels) and call text plotter */ 00578 00579 x = plP_mmpcx( xmm ); 00580 y = plP_mmpcy( ymm ); 00581 refx = plP_mmpcx( refxmm ); 00582 refy = plP_mmpcy( refymm ); 00583 00584 plP_text( 0, just, xform, x, y, refx, refy, text ); 00585 plP_sclp( clpxmi, clpxma, clpymi, clpyma ); /* restore clip limits */ 00586 } 00587 00588 /*--------------------------------------------------------------------------*\ 00589 * void plptex() 00590 * 00591 * Prints out "text" at world cooordinate (wx,wy). The text may be 00592 * at any angle "angle" relative to the horizontal. The parameter 00593 * "just" adjusts the horizontal justification of the string: 00594 * just = 0.0 => left hand edge of string is at (wx,wy) 00595 * just = 1.0 => right hand edge of string is at (wx,wy) 00596 * just = 0.5 => center of string is at (wx,wy) etc. 00597 \*--------------------------------------------------------------------------*/ 00598 00599 void 00600 c_plptex( PLFLT wx, PLFLT wy, PLFLT dx, PLFLT dy, PLFLT just, const char *text ) 00601 { 00602 PLINT x, y, refx, refy; 00603 PLFLT xdv, ydv, xmm, ymm, refxmm, refymm, shift, cc, ss; 00604 PLFLT xform[4], diag; 00605 PLFLT chrdef, chrht; 00606 PLFLT dispx, dispy; 00607 PLFLT wxt, wyt, dxt, dyt; 00608 00609 if ( plsc->level < 3 ) 00610 { 00611 plabort( "plptex: Please set up window first" ); 00612 return; 00613 } 00614 00615 /* Transform both the origin and offset values */ 00616 TRANSFORM( wx, wy, &wxt, &wyt ); 00617 TRANSFORM( wx + dx, wy + dy, &dxt, &dyt ); 00618 dxt = dxt - wxt; 00619 dyt = dyt - wyt; 00620 if ( dxt == 0.0 && dyt == 0.0 ) 00621 { 00622 dxt = 1.0; 00623 dyt = 0.0; 00624 } 00625 00626 cc = plsc->wmxscl * dxt; 00627 ss = plsc->wmyscl * dyt; 00628 diag = sqrt( cc * cc + ss * ss ); 00629 cc /= diag; 00630 ss /= diag; 00631 00632 xform[0] = cc; 00633 xform[1] = -ss; 00634 xform[2] = ss; 00635 xform[3] = cc; 00636 00637 xdv = plP_wcdcx( wxt ); 00638 ydv = plP_wcdcy( wyt ); 00639 00640 dispx = 0.; 00641 dispy = 0.; 00642 00643 /* Convert to physical units (mm) and compute shifts */ 00644 00645 plgchr( &chrdef, &chrht ); 00646 shift = ( just == 0.0 ) ? 0.0 : plstrl( text ) * just; 00647 00648 xmm = plP_dcmmx( xdv ) + dispx * chrht; 00649 ymm = plP_dcmmy( ydv ) + dispy * chrht; 00650 refxmm = xmm - shift * xform[0]; 00651 refymm = ymm - shift * xform[2]; 00652 00653 x = plP_mmpcx( xmm ); 00654 y = plP_mmpcy( ymm ); 00655 refx = plP_mmpcx( refxmm ); 00656 refy = plP_mmpcy( refymm ); 00657 00658 plP_text( 0, just, xform, x, y, refx, refy, text ); 00659 } 00660 00661 /*--------------------------------------------------------------------------*\ 00662 * void plstr() 00663 * 00664 * Prints out a "string" at reference position with physical coordinates 00665 * (refx,refy). The coordinates of the vectors defining the string are 00666 * passed through the linear mapping defined by the 2 x 2 matrix xform() 00667 * before being plotted. The reference position is at the left-hand edge of 00668 * the string. If base = 1, it is aligned with the baseline of the string. 00669 * If base = 0, it is aligned with the center of the character box. 00670 * 00671 * Note, all calculations are done in terms of millimetres. These are scaled 00672 * as necessary before plotting the string on the page. 00673 \*--------------------------------------------------------------------------*/ 00674 00675 void 00676 plstr( PLINT base, PLFLT *xform, PLINT refx, PLINT refy, const char *string ) 00677 { 00678 short int *symbol; 00679 signed char *vxygrid = 0; 00680 00681 PLINT ch, i, length, level = 0, style, oline = 0, uline = 0; 00682 PLFLT width = 0., xorg = 0., yorg = 0., def, ht, dscale, scale; 00683 00684 plgchr( &def, &ht ); 00685 dscale = 0.05 * ht; 00686 scale = dscale; 00687 00688 /* Line style must be continuous */ 00689 00690 style = plsc->nms; 00691 plsc->nms = 0; 00692 00693 pldeco( &symbol, &length, string ); 00694 00695 for ( i = 0; i < length; i++ ) 00696 { 00697 ch = symbol[i]; 00698 if ( ch == -1 ) /* super-script */ 00699 { 00700 level++; 00701 yorg += 16.0 * scale; 00702 scale = dscale * pow( 0.75, (double) ABS( level ) ); 00703 } 00704 else if ( ch == -2 ) /* sub-script */ 00705 { 00706 level--; 00707 scale = dscale * pow( 0.75, (double) ABS( level ) ); 00708 yorg -= 16.0 * scale; 00709 } 00710 else if ( ch == -3 ) /* back-char */ 00711 xorg -= width * scale; 00712 else if ( ch == -4 ) /* toogle overline */ 00713 oline = !oline; 00714 else if ( ch == -5 ) /* toogle underline */ 00715 uline = !uline; 00716 else 00717 { 00718 if ( plcvec( ch, &vxygrid ) ) 00719 plchar( vxygrid, xform, base, oline, uline, refx, refy, scale, 00720 plsc->xpmm, plsc->ypmm, &xorg, &yorg, &width ); 00721 } 00722 } 00723 plsc->nms = style; 00724 } 00725 00726 /*--------------------------------------------------------------------------*\ 00727 * plchar() 00728 * 00729 * Plots out a given stroke font character. 00730 \*--------------------------------------------------------------------------*/ 00731 00732 static void 00733 plchar( signed char *vxygrid, PLFLT *xform, PLINT base, PLINT oline, PLINT uline, 00734 PLINT refx, PLINT refy, PLFLT scale, PLFLT xpmm, PLFLT ypmm, 00735 PLFLT *p_xorg, PLFLT *p_yorg, PLFLT *p_width ) 00736 { 00737 PLINT xbase, ybase, ydisp, lx, ly, cx, cy; 00738 PLINT k, penup; 00739 PLFLT x, y; 00740 PLINT llx[STLEN], lly[STLEN], l = 0; 00741 00742 xbase = vxygrid[2]; 00743 *p_width = vxygrid[3] - xbase; 00744 if ( base == 0 ) 00745 { 00746 ybase = 0; 00747 ydisp = vxygrid[0]; 00748 } 00749 else 00750 { 00751 ybase = vxygrid[0]; 00752 ydisp = 0; 00753 } 00754 k = 4; 00755 penup = 1; 00756 00757 for (;; ) 00758 { 00759 cx = vxygrid[k++]; 00760 cy = vxygrid[k++]; 00761 if ( cx == 64 && cy == 64 ) 00762 { 00763 if ( l ) 00764 { 00765 plP_draphy_poly( llx, lly, l ); 00766 l = 0; 00767 } 00768 break; 00769 } 00770 if ( cx == 64 && cy == 0 ) 00771 { 00772 if ( l ) 00773 { 00774 plP_draphy_poly( llx, lly, l ); 00775 l = 0; 00776 } 00777 penup = 1; 00778 } 00779 else 00780 { 00781 x = *p_xorg + ( cx - xbase ) * scale; 00782 y = *p_yorg + ( cy - ybase ) * scale; 00783 lx = refx + ROUND( xpmm * ( xform[0] * x + xform[1] * y ) ); 00784 ly = refy + ROUND( ypmm * ( xform[2] * x + xform[3] * y ) ); 00785 if ( penup == 1 ) 00786 { 00787 if ( l ) 00788 { 00789 plP_draphy_poly( llx, lly, l ); 00790 l = 0; 00791 } 00792 llx[l] = lx; 00793 lly[l++] = ly; /* store 1st point ! */ 00794 plP_movphy( lx, ly ); 00795 penup = 0; 00796 } 00797 else 00798 { 00799 llx[l] = lx; 00800 lly[l++] = ly; 00801 } 00802 } 00803 } 00804 00805 if ( oline ) 00806 { 00807 x = *p_xorg; 00808 y = *p_yorg + ( 30 + ydisp ) * scale; 00809 lx = refx + ROUND( xpmm * ( xform[0] * x + xform[1] * y ) ); 00810 ly = refy + ROUND( ypmm * ( xform[2] * x + xform[3] * y ) ); 00811 plP_movphy( lx, ly ); 00812 x = *p_xorg + *p_width * scale; 00813 lx = refx + ROUND( xpmm * ( xform[0] * x + xform[1] * y ) ); 00814 ly = refy + ROUND( ypmm * ( xform[2] * x + xform[3] * y ) ); 00815 plP_draphy( lx, ly ); 00816 } 00817 if ( uline ) 00818 { 00819 x = *p_xorg; 00820 y = *p_yorg + ( -5 + ydisp ) * scale; 00821 lx = refx + ROUND( xpmm * ( xform[0] * x + xform[1] * y ) ); 00822 ly = refy + ROUND( ypmm * ( xform[2] * x + xform[3] * y ) ); 00823 plP_movphy( lx, ly ); 00824 x = *p_xorg + *p_width * scale; 00825 lx = refx + ROUND( xpmm * ( xform[0] * x + xform[1] * y ) ); 00826 ly = refy + ROUND( ypmm * ( xform[2] * x + xform[3] * y ) ); 00827 plP_draphy( lx, ly ); 00828 } 00829 *p_xorg = *p_xorg + *p_width * scale; 00830 } 00831 00832 /*--------------------------------------------------------------------------*\ 00833 * PLFLT plstrl() 00834 * 00835 * Computes the length of a string in mm, including escape sequences. 00836 \*--------------------------------------------------------------------------*/ 00837 00838 PLFLT 00839 plstrl( const char *string ) 00840 { 00841 short int *symbol; 00842 signed char *vxygrid = 0; 00843 PLINT ch, i, length, level = 0; 00844 PLFLT width = 0., xorg = 0., dscale, scale, def, ht; 00845 00846 plgchr( &def, &ht ); 00847 dscale = 0.05 * ht; 00848 scale = dscale; 00849 pldeco( &symbol, &length, string ); 00850 00851 for ( i = 0; i < length; i++ ) 00852 { 00853 ch = symbol[i]; 00854 if ( ch == -1 ) 00855 { 00856 level++; 00857 scale = dscale * pow( 0.75, (double) ABS( level ) ); 00858 } 00859 else if ( ch == -2 ) 00860 { 00861 level--; 00862 scale = dscale * pow( 0.75, (double) ABS( level ) ); 00863 } 00864 else if ( ch == -3 ) 00865 xorg -= width * scale; 00866 else if ( ch == -4 || ch == -5 ) 00867 ; 00868 else 00869 { 00870 if ( plcvec( ch, &vxygrid ) ) 00871 { 00872 width = vxygrid[3] - vxygrid[2]; 00873 xorg += width * scale; 00874 } 00875 } 00876 } 00877 return (PLFLT) xorg; 00878 } 00879 00880 /*--------------------------------------------------------------------------*\ 00881 * PLINT plcvec() 00882 * 00883 * Gets the character digitisation of Hershey table entry "char". 00884 * Returns 1 if there is a valid entry. 00885 \*--------------------------------------------------------------------------*/ 00886 00887 static PLINT 00888 plcvec( PLINT ch, signed char **xygr ) 00889 { 00890 PLINT k = 0, ib; 00891 signed char x, y; 00892 00893 ch--; 00894 if ( ch < 0 || ch >= indxleng ) 00895 return (PLINT) 0; 00896 ib = fntindx[ch] - 2; 00897 if ( ib == -2 ) 00898 return (PLINT) 0; 00899 00900 do 00901 { 00902 ib++; 00903 x = fntbffr[2 * ib]; 00904 y = fntbffr[2 * ib + 1]; 00905 xygrid[k++] = x; 00906 xygrid[k++] = y; 00907 } while ( ( x != 64 || y != 64 ) && k <= ( STLEN - 2 ) ); 00908 00909 if ( k == ( STLEN - 1 ) ) 00910 { 00911 /* This is bad if we get here */ 00912 xygrid[k] = 64; 00913 xygrid[k] = 64; 00914 } 00915 00916 *xygr = xygrid; 00917 return (PLINT) 1; 00918 } 00919 00920 /*--------------------------------------------------------------------------*\ 00921 * void pldeco() 00922 * 00923 * Decode a character string, and return an array of float integer symbol 00924 * numbers. This routine is responsible for interpreting all escape sequences. 00925 * At present the following escape sequences are defined (the letter following 00926 * the <esc> may be either upper or lower case): 00927 * 00928 * <esc>u : up one level (returns -1) 00929 * <esc>d : down one level (returns -2) 00930 * <esc>b : backspace (returns -3) 00931 * <esc>+ : toggles overline mode (returns -4) 00932 * <esc>- : toggles underline mode (returns -5) 00933 * <esc><esc> : <esc> 00934 * <esc>gx : greek letter corresponding to roman letter x 00935 * <esc>fn : switch to Normal font 00936 * <esc>fr : switch to Roman font 00937 * <esc>fi : switch to Italic font 00938 * <esc>fs : switch to Script font 00939 * <esc>(nnn) : Hershey symbol number nnn (any number of digits) 00940 * 00941 * The escape character defaults to '#', but can be changed to any of 00942 * [!#$%&*@^~] via a call to plsesc. 00943 \*--------------------------------------------------------------------------*/ 00944 00945 static void 00946 pldeco( short int **symbol, PLINT *length, const char *text ) 00947 { 00948 PLINT ch, ifont = plsc->cfont, ig, j = 0, lentxt = strlen( text ); 00949 char test, esc; 00950 short int *sym = symbol_buffer; 00951 00952 /* Initialize parameters. */ 00953 00954 *length = 0; 00955 *symbol = symbol_buffer; 00956 plgesc( &esc ); 00957 if ( ifont > numberfonts ) 00958 ifont = 1; 00959 00960 /* Get next character; treat non-printing characters as spaces. */ 00961 00962 while ( j < lentxt ) 00963 { 00964 if ( *length >= PLMAXSTR ) 00965 return; 00966 test = text[j++]; 00967 ch = test; 00968 if ( ch < 0 || ch > 175 ) 00969 ch = 32; 00970 00971 /* Test for escape sequence (#) */ 00972 00973 if ( ch == esc && ( lentxt - j ) >= 1 ) 00974 { 00975 test = text[j++]; 00976 if ( test == esc ) 00977 sym[( *length )++] = *( fntlkup + ( ifont - 1 ) * numberchars + ch ); 00978 00979 else if ( test == 'u' || test == 'U' ) 00980 sym[( *length )++] = -1; 00981 00982 else if ( test == 'd' || test == 'D' ) 00983 sym[( *length )++] = -2; 00984 00985 else if ( test == 'b' || test == 'B' ) 00986 sym[( *length )++] = -3; 00987 00988 else if ( test == '+' ) 00989 sym[( *length )++] = -4; 00990 00991 else if ( test == '-' ) 00992 sym[( *length )++] = -5; 00993 00994 else if ( test == '(' ) 00995 { 00996 sym[*length] = 0; 00997 while ( '0' <= text[j] && text[j] <= '9' ) 00998 { 00999 sym[*length] = sym[*length] * 10 + text[j] - '0'; 01000 j++; 01001 } 01002 ( *length )++; 01003 if ( text[j] == ')' ) 01004 j++; 01005 } 01006 else if ( test == 'f' || test == 'F' ) 01007 { 01008 test = text[j++]; 01009 ifont = 1 + plP_strpos( font_types, 01010 isupper( test ) ? tolower( test ) : test ); 01011 if ( ifont == 0 || ifont > numberfonts ) 01012 ifont = 1; 01013 } 01014 else if ( test == 'g' || test == 'G' ) 01015 { 01016 test = text[j++]; 01017 ig = plP_strpos( plP_greek_mnemonic, test ) + 1; 01018 sym[( *length )++] = 01019 *( fntlkup + ( ifont - 1 ) * numberchars + 127 + ig ); 01020 } 01021 else 01022 { 01023 ; 01024 } 01025 } 01026 else 01027 { 01028 /* Decode character. */ 01029 /* >>PC<< removed increment from following expression to fix */ 01030 /* compiler bug */ 01031 01032 sym[( *length )] = *( fntlkup + ( ifont - 1 ) * numberchars + ch ); 01033 ( *length )++; 01034 } 01035 } 01036 } 01037 01038 /*--------------------------------------------------------------------------*\ 01039 * PLINT plP_strpos() 01040 * 01041 * Searches string str for first occurence of character chr. If found 01042 * the position of the character in the string is returned (the first 01043 * character has position 0). If the character is not found a -1 is 01044 * returned. 01045 \*--------------------------------------------------------------------------*/ 01046 01047 PLINT 01048 plP_strpos( const char *str, int chr ) 01049 { 01050 char *temp; 01051 01052 if ( ( temp = strchr( str, chr ) ) ) 01053 return (PLINT) ( temp - str ); 01054 else 01055 return (PLINT) -1; 01056 } 01057 01058 /*--------------------------------------------------------------------------*\ 01059 * PLINT plP_stindex() 01060 * 01061 * Similar to strpos, but searches for occurence of string str2. 01062 \*--------------------------------------------------------------------------*/ 01063 01064 PLINT 01065 plP_stindex( const char *str1, const char *str2 ) 01066 { 01067 PLINT base, str1ind, str2ind; 01068 01069 for ( base = 0; *( str1 + base ) != '\0'; base++ ) 01070 { 01071 for ( str1ind = base, str2ind = 0; *( str2 + str2ind ) != '\0' && 01072 *( str2 + str2ind ) == *( str1 + str1ind ); str1ind++, str2ind++ ) 01073 ; 01074 01075 if ( *( str2 + str2ind ) == '\0' ) 01076 return (PLINT) base; 01077 } 01078 return (PLINT) -1; /* search failed */ 01079 } 01080 01081 /*--------------------------------------------------------------------------*\ 01082 * PLBOOL plP_stsearch() 01083 * 01084 * Searches string str for character chr (case insensitive). 01085 \*--------------------------------------------------------------------------*/ 01086 01087 PLBOOL 01088 plP_stsearch( const char *str, int chr ) 01089 { 01090 if ( strchr( str, chr ) ) 01091 return TRUE; 01092 else if ( strchr( str, toupper( chr ) ) ) 01093 return TRUE; 01094 else 01095 return FALSE; 01096 } 01097 01098 /*--------------------------------------------------------------------------*\ 01099 * void c_plfont(ifont) 01100 * 01101 * Sets the global font flag to 'ifont'. 01102 \*--------------------------------------------------------------------------*/ 01103 01104 void 01105 c_plfont( PLINT ifont ) 01106 { 01107 PLUNICODE fci = PL_FCI_MARK; 01108 if ( plsc->level < 1 ) 01109 { 01110 plabort( "plfont: Please call plinit first" ); 01111 return; 01112 } 01113 if ( ifont < 1 || ifont > 4 ) 01114 { 01115 plabort( "plfont: Invalid font" ); 01116 return; 01117 } 01118 01119 plsc->cfont = ifont; 01120 01121 /* Provide some degree of forward compatibility if dealing with 01122 * unicode font. But better procedure is to call plsfci directly rather 01123 * than using this lame Hershey font interface. 01124 */ 01125 switch ( ifont ) 01126 { 01127 case 1: 01128 /* normal = (medium, upright, sans serif) */ 01129 plP_hex2fci( PL_FCI_SANS, PL_FCI_FAMILY, &fci ); 01130 plsfci( fci ); 01131 break; 01132 /* roman = (medium, upright, serif) */ 01133 case 2: 01134 plP_hex2fci( PL_FCI_SERIF, PL_FCI_FAMILY, &fci ); 01135 plsfci( fci ); 01136 break; 01137 /* italic = (medium, italic, serif) */ 01138 case 3: 01139 plP_hex2fci( PL_FCI_ITALIC, PL_FCI_STYLE, &fci ); 01140 plP_hex2fci( PL_FCI_SERIF, PL_FCI_FAMILY, &fci ); 01141 plsfci( fci ); 01142 break; 01143 /* script = (medium, upright, script) */ 01144 case 4: 01145 plP_hex2fci( PL_FCI_SCRIPT, PL_FCI_FAMILY, &fci ); 01146 plsfci( fci ); 01147 break; 01148 } 01149 } 01150 01151 /*--------------------------------------------------------------------------*\ 01152 * void plfntld(fnt) 01153 * 01154 * Loads either the standard or extended font. 01155 \*--------------------------------------------------------------------------*/ 01156 01157 void 01158 plfntld( PLINT fnt ) 01159 { 01160 static PLINT charset; 01161 short bffrleng; 01162 PDFstrm *pdfs; 01163 01164 if ( fontloaded && ( charset == fnt ) ) 01165 return; 01166 01167 plfontrel(); 01168 fontloaded = 1; 01169 charset = fnt; 01170 01171 if ( fnt ) 01172 pdfs = plLibOpenPdfstrm( PL_XFONT ); 01173 else 01174 pdfs = plLibOpenPdfstrm( PL_SFONT ); 01175 01176 if ( pdfs == NULL ) 01177 plexit( "Unable to either (1) open/find or (2) allocate memory for the font file" ); 01178 01179 /* Read fntlkup[] */ 01180 01181 pdf_rd_2bytes( pdfs, (U_SHORT *) &bffrleng ); 01182 numberfonts = bffrleng / 256; 01183 numberchars = bffrleng & 0xff; 01184 bffrleng = numberfonts * numberchars; 01185 fntlkup = (short int *) malloc( bffrleng * sizeof ( short int ) ); 01186 if ( !fntlkup ) 01187 plexit( "plfntld: Out of memory while allocating font buffer." ); 01188 01189 pdf_rd_2nbytes( pdfs, (U_SHORT *) fntlkup, bffrleng ); 01190 01191 /* Read fntindx[] */ 01192 01193 pdf_rd_2bytes( pdfs, (U_SHORT *) &indxleng ); 01194 fntindx = (short int *) malloc( indxleng * sizeof ( short int ) ); 01195 if ( !fntindx ) 01196 plexit( "plfntld: Out of memory while allocating font buffer." ); 01197 01198 pdf_rd_2nbytes( pdfs, (U_SHORT *) fntindx, indxleng ); 01199 01200 /* Read fntbffr[] */ 01201 /* Since this is an array of char, there are no endian problems */ 01202 01203 pdf_rd_2bytes( pdfs, (U_SHORT *) &bffrleng ); 01204 fntbffr = (signed char *) malloc( 2 * bffrleng * sizeof ( signed char ) ); 01205 if ( !fntbffr ) 01206 plexit( "plfntld: Out of memory while allocating font buffer." ); 01207 01208 #if PLPLOT_USE_TCL_CHANNELS 01209 pdf_rdx( fntbffr, sizeof ( signed char ) * ( 2 * bffrleng ), pdfs ); 01210 #else 01211 plio_fread( (void *) fntbffr, (size_t) sizeof ( signed char ), 01212 (size_t) ( 2 * bffrleng ), pdfs->file ); 01213 #endif 01214 01215 /* Done */ 01216 01217 pdf_close( pdfs ); 01218 } 01219 01220 /*--------------------------------------------------------------------------*\ 01221 * void plfontrel() 01222 * 01223 * Release memory for fonts. 01224 \*--------------------------------------------------------------------------*/ 01225 01226 void 01227 plfontrel( void ) 01228 { 01229 if ( fontloaded ) 01230 { 01231 free_mem( fntindx ) 01232 free_mem( fntbffr ) 01233 free_mem( fntlkup ) 01234 fontloaded = 0; 01235 } 01236 } 01237 01238 /*--------------------------------------------------------------------------*\ 01239 * int plhershey2unicode ( int in ) 01240 * 01241 * Function searches for in, the input hershey code, in a lookup table and 01242 * returns the corresponding index in that table. 01243 * Using this index you can work out the unicode equivalent as well as 01244 * the closest approximate to the font-face. If the returned index is 01245 * -1 then no match was possible. 01246 * 01247 * Two versions of the function exist, a simple linear search version, 01248 * and a more complex, but significantly faster, binary search version. 01249 * If there seem to be problems with the binary search method, the brain-dead 01250 * linear search can be enabled by defining SIMPLE_BUT_SAFE_HERSHEY_LOOKUP 01251 * at compile time. 01252 \*--------------------------------------------------------------------------*/ 01253 01254 int plhershey2unicode( int in ) 01255 { 01256 #ifdef SIMPLE_BUT_SAFE_HERSHEY_LOOKUP 01257 int ret = -1; 01258 int i; 01259 01260 for ( i = 0; ( i < number_of_entries_in_hershey_to_unicode_table ) && ( ret == -1 ); i++ ) 01261 { 01262 if ( hershey_to_unicode_lookup_table[i].Hershey == in ) 01263 ret = i; 01264 } 01265 01266 return ( ret ); 01267 01268 #else 01269 01270 int jlo = -1, jmid, jhi = number_of_entries_in_hershey_to_unicode_table; 01271 while ( jhi - jlo > 1 ) 01272 { 01273 /* Note that although jlo or jhi can be just outside valid 01274 * range (see initialization above) because of while condition 01275 * jlo < jmid < jhi and jmid must be in valid range. 01276 */ 01277 jmid = ( jlo + jhi ) / 2; 01278 /* convert hershey_to_unicode_lookup_table[jmid].Hershey to signed 01279 * integer since we don't loose information - the number range 01280 * is from 1 and 2932 at the moment */ 01281 if ( in > (int) ( hershey_to_unicode_lookup_table[jmid].Hershey ) ) 01282 jlo = jmid; 01283 else if ( in < (int) ( hershey_to_unicode_lookup_table[jmid].Hershey ) ) 01284 jhi = jmid; 01285 else 01286 /* We have found it! 01287 * in == hershey_to_unicode_lookup_table[jmid].Hershey 01288 */ 01289 return ( jmid ); 01290 } 01291 /* jlo is invalid or it is valid and in > hershey_to_unicode_lookup_table[jlo].Hershey. 01292 * jhi is invalid or it is valid and in < hershey_to_unicode_lookup_table[jhi].Hershey. 01293 * All these conditions together imply in cannot be found in 01294 * hershey_to_unicode_lookup_table[j].Hershey, for all j. 01295 */ 01296 return ( -1 ); 01297 #endif 01298 } 01299 01300 /*--------------------------------------------------------------------------*\ 01301 * char * 01302 * plP_FCI2FontName ( PLUNICODE fci, 01303 * const FCI_to_FontName_Table lookup[], const int nlookup) 01304 * 01305 * Function takes an input FCI (font characterization integer) index, 01306 * looks through the lookup table (which must be sorted by PLUNICODE fci), 01307 * then returns the corresponding pointer to a valid font name. If the FCI 01308 * index is not present the returned value is NULL. 01309 \*--------------------------------------------------------------------------*/ 01310 01311 char * 01312 plP_FCI2FontName( PLUNICODE fci, 01313 const FCI_to_FontName_Table lookup[], const int nlookup ) 01314 { 01315 int jlo = -1, jmid, jhi = nlookup; 01316 while ( jhi - jlo > 1 ) 01317 { 01318 /* Note that although jlo or jhi can be just outside valid 01319 * range (see initialization above) because of while condition 01320 * jlo < jmid < jhi and jmid must be in valid range. 01321 */ 01322 jmid = ( jlo + jhi ) / 2; 01323 if ( fci > lookup[jmid].fci ) 01324 jlo = jmid; 01325 else if ( fci < lookup[jmid].fci ) 01326 jhi = jmid; 01327 else 01328 /* We have found it! 01329 * fci == lookup[jmid].fci 01330 */ 01331 return (char *) ( lookup[jmid].pfont ); 01332 } 01333 /* jlo is invalid or it is valid and fci > lookup[jlo].Unicode. 01334 * jhi is invalid or it is valid and fci < lookup[jhi].Unicode. 01335 * All these conditions together imply fci index cannot be found in lookup. 01336 * Mark lookup failure with NULL pointer. 01337 */ 01338 return ( NULL ); 01339 } 01340 01341 /*--------------------------------------------------------------------------*\ 01342 * void plmtex3() 01343 * 01344 * This is the 3d equivalent of plmtex(). It prints out "text" at specified 01345 * position relative to viewport (may be inside or outside) 01346 * 01347 * side String contains one or more of the following characters 01348 * x,y,z : Specify which axis is to be labeled 01349 * p,s : Label the "primary" or the "secondary" axis. The "primary" axis 01350 * being somewhat arbitrary, but basically it is the one that you'd 01351 * expect to labeled in a 3d graph of standard orientation. Example: 01352 * for z this would be the left hand axis. 01353 * v : draw the text perpendicular to the axis. 01354 * 01355 * disp Displacement from specified edge of axis, measured outwards from 01356 * the axis in units of the current character height. The 01357 * centerlines of the characters are aligned with the specified 01358 * position. 01359 * 01360 * pos Position of the reference point of the string relative to the 01361 * axis ends, ranging from 0.0 (left-hand end) to 1.0 (right-hand 01362 * end) 01363 * 01364 * just Justification of string relative to reference point 01365 * just = 0.0 => left hand edge of string is at reference 01366 * just = 1.0 => right hand edge of string is at reference 01367 * just = 0.5 => center of string is at reference 01368 * 01369 * All calculations are done in physical coordinates. 01370 * 01371 \*--------------------------------------------------------------------------*/ 01372 01373 void 01374 c_plmtex3( const char *side, PLFLT disp, PLFLT pos, PLFLT just, const char *text ) 01375 { 01376 /* local storage */ 01377 PLFLT xmin, xmax, ymin, ymax, zmin, zmax, zscale; 01378 PLFLT chrdef, chrht; 01379 01380 /* calculated */ 01381 PLFLT xpc, ypc, xrefpc, yrefpc; 01382 PLFLT epx1, epy1, epx2, epy2, epx3, epy3; 01383 PLFLT dispx, dispy, xform[4]; 01384 PLFLT shift, theta, temp; 01385 01386 /* check that the plotting environment is set up */ 01387 if ( plsc->level < 3 ) 01388 { 01389 plabort( "plmtex3: Please set up window first" ); 01390 return; 01391 } 01392 01393 /* get plotting environment information */ 01394 plP_gdom( &xmin, &xmax, &ymin, &ymax ); 01395 plP_grange( &zscale, &zmin, &zmax ); 01396 plgchr( &chrdef, &chrht ); 01397 01398 /* handle x/y axises */ 01399 if ( ( plP_stindex( side, "x" ) != -1 ) || ( plP_stindex( side, "y" ) != -1 ) ) 01400 { 01401 /* get the locations of the end points of the relevant axis */ 01402 01403 /* x axis label */ 01404 if ( plP_stindex( side, "x" ) != -1 ) 01405 { 01406 /* primary */ 01407 if ( plP_stindex( side, "p" ) != -1 ) 01408 { 01409 epx1 = plP_wcpcx( plP_w3wcx( xmin, ymin, zmin ) ); 01410 epy1 = plP_wcpcy( plP_w3wcy( xmin, ymin, zmin ) ); 01411 epx2 = plP_wcpcx( plP_w3wcx( xmax, ymin, zmin ) ); 01412 epy2 = plP_wcpcy( plP_w3wcy( xmax, ymin, zmin ) ); 01413 } 01414 else 01415 { 01416 epx1 = plP_wcpcx( plP_w3wcx( xmin, ymax, zmin ) ); 01417 epy1 = plP_wcpcy( plP_w3wcy( xmin, ymax, zmin ) ); 01418 epx2 = plP_wcpcx( plP_w3wcx( xmax, ymax, zmin ) ); 01419 epy2 = plP_wcpcy( plP_w3wcy( xmax, ymax, zmin ) ); 01420 } 01421 } 01422 else 01423 { 01424 if ( plP_stindex( side, "p" ) != -1 ) 01425 { 01426 epx1 = plP_wcpcx( plP_w3wcx( xmin, ymin, zmin ) ); 01427 epy1 = plP_wcpcy( plP_w3wcy( xmin, ymin, zmin ) ); 01428 epx2 = plP_wcpcx( plP_w3wcx( xmin, ymax, zmin ) ); 01429 epy2 = plP_wcpcy( plP_w3wcy( xmin, ymax, zmin ) ); 01430 } 01431 else 01432 { 01433 epx1 = plP_wcpcx( plP_w3wcx( xmax, ymin, zmin ) ); 01434 epy1 = plP_wcpcy( plP_w3wcy( xmax, ymin, zmin ) ); 01435 epx2 = plP_wcpcx( plP_w3wcx( xmax, ymax, zmin ) ); 01436 epy2 = plP_wcpcy( plP_w3wcy( xmax, ymax, zmin ) ); 01437 } 01438 } 01439 01440 /* text always goes from left to right */ 01441 if ( epx1 > epx2 ) 01442 { 01443 temp = epx1; 01444 epx1 = epx2; 01445 epx2 = temp; 01446 temp = epy1; 01447 epy1 = epy2; 01448 epy2 = temp; 01449 /* recalculate position assuming the user specified 01450 * it in the min -> max direction of the axis. */ 01451 pos = 1.0 - pos; 01452 } 01453 01454 /* calculate location of text center point */ 01455 01456 /* 1. calculate the angle of the axis we are to 01457 * draw the text on relative to the horizontal */ 01458 01459 if ( ( epx2 - epx1 ) != 0.0 ) 01460 { 01461 theta = atan( ( epy2 - epy1 ) / ( epx2 - epx1 ) ); 01462 } 01463 else 01464 { 01465 if ( epy2 > epy1 ) 01466 { 01467 theta = 0.5 * PI; 01468 } 01469 else 01470 { 01471 theta = -0.5 * PI; 01472 } 01473 } 01474 01475 /* 2. calculate the perpendicular vector */ 01476 01477 dispy = disp * chrht; 01478 01479 /* 3. calculate x & y center points */ 01480 01481 xpc = pos * ( epx2 - epx1 ) + epx1; 01482 ypc = pos * ( epy2 - epy1 ) + epy1; 01483 01484 /* 4. compute reference point 01485 * It appears that drivers that cannot handle text justification 01486 * use this as the starting point of the string. 01487 * Calculations must be done in millimeters for this part 01488 * so we convert to mm, do the calculation and convert back. 01489 * The calculation is also dependent of the orientation 01490 * (perpendicular or parallel) of the text. */ 01491 01492 xpc = plP_dcmmx( plP_pcdcx( (PLINT) xpc ) ); 01493 ypc = plP_dcmmy( plP_pcdcy( (PLINT) ypc ) ) - dispy; 01494 01495 shift = plstrl( text ) * just; 01496 01497 if ( plP_stindex( side, "v" ) != -1 ) 01498 { 01499 xrefpc = xpc; 01500 yrefpc = ypc - shift; 01501 } 01502 else 01503 { 01504 xrefpc = xpc - cos( theta ) * shift; 01505 yrefpc = ypc - sin( theta ) * shift; 01506 } 01507 01508 xpc = plP_mmpcx( xpc ); 01509 ypc = plP_mmpcy( ypc ); 01510 xrefpc = plP_mmpcx( xrefpc ); 01511 yrefpc = plP_mmpcy( yrefpc ); 01512 01513 /* 5. compute transform matrix & draw text */ 01514 01515 /* perpendicular, rotate 90 degrees & shear */ 01516 01517 if ( plP_stindex( side, "v" ) != -1 ) 01518 { 01519 xform[0] = 0.0; 01520 xform[1] = -cos( theta ); 01521 xform[2] = 1.0; 01522 xform[3] = -sin( theta ); 01523 plP_text( 0, just, xform, (PLINT) xpc, (PLINT) ypc, (PLINT) xrefpc, (PLINT) yrefpc, text ); 01524 } 01525 01526 /* parallel, rotate & shear by angle */ 01527 else 01528 { 01529 xform[0] = cos( theta ); 01530 xform[1] = 0.0; 01531 xform[2] = sin( theta ); 01532 xform[3] = 1.0; 01533 01534 plP_text( 0, just, xform, (PLINT) xpc, (PLINT) ypc, (PLINT) xrefpc, (PLINT) yrefpc, text ); 01535 } 01536 } 01537 01538 /* handle z axises */ 01539 if ( plP_stindex( side, "z" ) != -1 ) 01540 { 01541 /* Find the left most of the 4 z axis options for "primary" 01542 * Also find the location of frontmost point in the graph, 01543 * which will be needed to calculate at what angle to shear 01544 * the text. */ 01545 01546 if ( plP_stindex( side, "p" ) != -1 ) 01547 { 01548 epx1 = plP_wcpcx( plP_w3wcx( xmin, ymin, zmin ) ); 01549 epy1 = plP_wcpcy( plP_w3wcy( xmin, ymin, zmin ) ); 01550 epy2 = plP_wcpcy( plP_w3wcy( xmin, ymin, zmax ) ); 01551 epx3 = plP_wcpcx( plP_w3wcx( xmax, ymin, zmin ) ); 01552 epy3 = plP_wcpcy( plP_w3wcy( xmax, ymin, zmin ) ); 01553 01554 if ( plP_wcpcx( plP_w3wcx( xmin, ymax, zmin ) ) < epx1 ) 01555 { 01556 epx1 = plP_wcpcx( plP_w3wcx( xmin, ymax, zmin ) ); 01557 epy1 = plP_wcpcy( plP_w3wcy( xmin, ymax, zmin ) ); 01558 epy2 = plP_wcpcy( plP_w3wcy( xmin, ymax, zmax ) ); 01559 epx3 = plP_wcpcx( plP_w3wcx( xmin, ymin, zmin ) ); 01560 epy3 = plP_wcpcy( plP_w3wcy( xmin, ymin, zmin ) ); 01561 } 01562 01563 if ( plP_wcpcx( plP_w3wcx( xmax, ymin, zmin ) ) < epx1 ) 01564 { 01565 epx1 = plP_wcpcx( plP_w3wcx( xmax, ymin, zmin ) ); 01566 epy1 = plP_wcpcy( plP_w3wcy( xmax, ymin, zmin ) ); 01567 epy2 = plP_wcpcy( plP_w3wcy( xmax, ymin, zmax ) ); 01568 epx3 = plP_wcpcx( plP_w3wcx( xmax, ymax, zmin ) ); 01569 epy3 = plP_wcpcy( plP_w3wcy( xmax, ymax, zmin ) ); 01570 } 01571 01572 if ( plP_wcpcx( plP_w3wcx( xmax, ymax, zmin ) ) < epx1 ) 01573 { 01574 epx1 = plP_wcpcx( plP_w3wcx( xmax, ymax, zmin ) ); 01575 epy1 = plP_wcpcy( plP_w3wcy( xmax, ymax, zmin ) ); 01576 epy2 = plP_wcpcy( plP_w3wcy( xmax, ymax, zmax ) ); 01577 epx3 = plP_wcpcx( plP_w3wcx( xmin, ymax, zmin ) ); 01578 epy3 = plP_wcpcy( plP_w3wcy( xmin, ymax, zmin ) ); 01579 } 01580 } 01581 01582 /* find the right most of the 4 z axis options for "primary" */ 01583 if ( plP_stindex( side, "s" ) != -1 ) 01584 { 01585 epx1 = plP_wcpcx( plP_w3wcx( xmin, ymin, zmin ) ); 01586 epy1 = plP_wcpcy( plP_w3wcy( xmin, ymin, zmin ) ); 01587 epy2 = plP_wcpcy( plP_w3wcy( xmin, ymin, zmax ) ); 01588 epx3 = plP_wcpcx( plP_w3wcx( xmin, ymax, zmin ) ); 01589 epy3 = plP_wcpcy( plP_w3wcy( xmin, ymax, zmin ) ); 01590 01591 if ( plP_wcpcx( plP_w3wcx( xmin, ymax, zmin ) ) > epx1 ) 01592 { 01593 epx1 = plP_wcpcx( plP_w3wcx( xmin, ymax, zmin ) ); 01594 epy1 = plP_wcpcy( plP_w3wcy( xmin, ymax, zmin ) ); 01595 epy2 = plP_wcpcy( plP_w3wcy( xmin, ymax, zmax ) ); 01596 epx3 = plP_wcpcx( plP_w3wcx( xmax, ymax, zmin ) ); 01597 epy3 = plP_wcpcy( plP_w3wcy( xmax, ymax, zmin ) ); 01598 } 01599 01600 if ( plP_wcpcx( plP_w3wcx( xmax, ymin, zmin ) ) > epx1 ) 01601 { 01602 epx1 = plP_wcpcx( plP_w3wcx( xmax, ymin, zmin ) ); 01603 epy1 = plP_wcpcy( plP_w3wcy( xmax, ymin, zmin ) ); 01604 epy2 = plP_wcpcy( plP_w3wcy( xmax, ymin, zmax ) ); 01605 epx3 = plP_wcpcx( plP_w3wcx( xmin, ymin, zmin ) ); 01606 epy3 = plP_wcpcy( plP_w3wcy( xmin, ymin, zmin ) ); 01607 } 01608 01609 if ( plP_wcpcx( plP_w3wcx( xmax, ymax, zmin ) ) > epx1 ) 01610 { 01611 epx1 = plP_wcpcx( plP_w3wcx( xmax, ymax, zmin ) ); 01612 epy1 = plP_wcpcy( plP_w3wcy( xmax, ymax, zmin ) ); 01613 epy2 = plP_wcpcy( plP_w3wcy( xmax, ymax, zmax ) ); 01614 epx3 = plP_wcpcx( plP_w3wcx( xmax, ymin, zmin ) ); 01615 epy3 = plP_wcpcy( plP_w3wcy( xmax, ymin, zmin ) ); 01616 } 01617 } 01618 01619 /* Calculate location of text center point. 01620 * This is very similiar for the z axis. */ 01621 01622 /* primary and secondary have to be handled separately here */ 01623 01624 if ( plP_stindex( side, "p" ) != -1 ) 01625 { 01626 /* 1. Calculate the angle of the axis we are to 01627 * draw the text on relative to the horizontal. */ 01628 01629 if ( ( epx3 - epx1 ) != 0.0 ) 01630 { 01631 theta = atan( ( epy3 - epy1 ) / ( epx3 - epx1 ) ); 01632 } 01633 else 01634 { 01635 if ( epy3 > epy1 ) 01636 { 01637 theta = 0.5 * PI; 01638 } 01639 else 01640 { 01641 theta = -0.5 * PI; 01642 } 01643 } 01644 01645 /* 2. Calculate the perpendicular vector. */ 01646 01647 dispx = -cos( theta ) * disp * chrht; 01648 dispy = -sin( theta ) * disp * chrht; 01649 } 01650 else 01651 { 01652 if ( ( epx1 - epx3 ) != 0.0 ) 01653 { 01654 theta = -atan( ( epy3 - epy1 ) / ( epx1 - epx3 ) ); 01655 } 01656 else 01657 { 01658 if ( epy3 > epy1 ) 01659 { 01660 theta = -0.5 * PI; 01661 } 01662 else 01663 { 01664 theta = 0.5 * PI; 01665 } 01666 } 01667 01668 dispx = cos( theta ) * disp * chrht; 01669 dispy = sin( theta ) * disp * chrht; 01670 } 01671 01672 /* 3. Calculate x & y center points. */ 01673 01674 xpc = epx1; 01675 ypc = pos * ( epy2 - epy1 ) + epy1; 01676 01677 /* 4. Compute the reference point. */ 01678 01679 xpc = plP_dcmmx( plP_pcdcx( (PLINT) xpc ) ) + dispx; 01680 ypc = plP_dcmmy( plP_pcdcy( (PLINT) ypc ) ) + dispy; 01681 01682 shift = plstrl( text ) * just; 01683 01684 if ( plP_stindex( side, "v" ) != -1 ) 01685 { 01686 xrefpc = xpc - cos( theta ) * shift; 01687 yrefpc = ypc - sin( theta ) * shift; 01688 } 01689 else 01690 { 01691 xrefpc = xpc; 01692 yrefpc = ypc - shift; 01693 } 01694 01695 xpc = plP_mmpcx( xpc ); 01696 ypc = plP_mmpcy( ypc ); 01697 xrefpc = plP_mmpcx( xrefpc ); 01698 yrefpc = plP_mmpcy( yrefpc ); 01699 01700 /* 5. Compute transform matrix & draw text. */ 01701 01702 if ( plP_stindex( side, "v" ) != -1 ) 01703 { 01704 xform[0] = cos( theta ); 01705 xform[1] = 0.0; 01706 xform[2] = sin( theta ); 01707 xform[3] = 1.0; 01708 01709 plP_text( 0, just, xform, (PLINT) xpc, (PLINT) ypc, (PLINT) xrefpc, (PLINT) yrefpc, text ); 01710 } 01711 01712 else 01713 { 01714 xform[0] = 0.0; 01715 xform[1] = -cos( theta ); 01716 xform[2] = 1.0; 01717 xform[3] = -sin( theta ); 01718 01719 plP_text( 0, just, xform, (PLINT) xpc, (PLINT) ypc, (PLINT) xrefpc, (PLINT) yrefpc, text ); 01720 } 01721 } 01722 } 01723 01724 /*--------------------------------------------------------------------------*\ 01725 * void plptex3() 01726 * 01727 * Prints out "text" at world cooordinate (wx,wy,wz). 01728 * 01729 * The text is drawn parallel to the line between (wx,wy,wz) and 01730 * (wx+dx,wy+dy,wz+dz). 01731 * 01732 * The text is sheared so that it is "vertically" parallel to the 01733 * line between (wx,wy,wz) and (wx+sx, wy+sy, wz+sz). If sx=sy=sz=0 then 01734 * the text is simply rotated to parallel to the baseline. 01735 * 01736 * "just" adjusts the horizontal justification of the string: 01737 * just = 0.0 => left hand edge of string is at (wx,wy) 01738 * just = 1.0 => right hand edge of string is at (wx,wy) 01739 * just = 0.5 => center of string is at (wx,wy) etc. 01740 * 01741 * Calculations are done in physical coordinates. 01742 * 01743 \*--------------------------------------------------------------------------*/ 01744 01745 void 01746 c_plptex3( PLFLT wx, PLFLT wy, PLFLT wz, PLFLT dx, PLFLT dy, PLFLT dz, 01747 PLFLT sx, PLFLT sy, PLFLT sz, PLFLT just, const char *text ) 01748 { 01749 PLFLT xpc, ypc, xrefpc, yrefpc, xdpc, ydpc, xspc, yspc, ld, ls, cp, shift; 01750 PLFLT x_o, y_o, z_o, x_dx, y_dy, z_dz; 01751 PLFLT theta, phi, stride, xform[6], affineL[6], cosphi; 01752 01753 /* check that the plotting environment is set up */ 01754 if ( plsc->level < 3 ) 01755 { 01756 plabort( "plptex3: Please set up window first" ); 01757 return; 01758 } 01759 01760 /* compute text x,y location in physical coordinates */ 01761 xpc = plP_wcpcx( plP_w3wcx( wx, wy, wz ) ); 01762 ypc = plP_wcpcy( plP_w3wcy( wx, wy, wz ) ); 01763 01764 /* determine angle to rotate text in the x-y plane */ 01765 xdpc = plP_wcpcx( plP_w3wcx( wx + dx, wy + dy, wz + dz ) ); 01766 ydpc = plP_wcpcy( plP_w3wcy( wx + dx, wy + dy, wz + dz ) ); 01767 theta = atan2( ydpc - ypc, xdpc - xpc ); 01768 01769 /* Determine angle to shear text in the x-y plane. This is a little 01770 * messy, but basically the idea is: 01771 * 01772 * Compute the dot product of the vector d and the vector s to 01773 * determine the angle between them (acos(t) = d . s / |d| |s|). 01774 * Then because acos will return a number from 0.0 to PI, i.e. 01775 * only in quadrants 1 or 2, compute the cross product of the 01776 * two vectors. If this is negative then the angle is adjusted 01777 * 0.0 to -PI. */ 01778 01779 if ( ( sx == 0.0 ) && ( sy == 0.0 ) && ( sz == 0.0 ) ) 01780 { 01781 phi = 0.0; 01782 } 01783 else 01784 { 01785 xspc = plP_wcpcx( plP_w3wcx( wx + sx, wy + sy, wz + sz ) ); 01786 yspc = plP_wcpcy( plP_w3wcy( wx + sx, wy + sy, wz + sz ) ); 01787 ld = sqrt( ( xpc - xdpc ) * ( xpc - xdpc ) + ( ypc - ydpc ) * ( ypc - ydpc ) ); 01788 ls = sqrt( ( xpc - xspc ) * ( xpc - xspc ) + ( ypc - yspc ) * ( ypc - yspc ) ); 01789 phi = acos( ( ( xdpc - xpc ) * ( xspc - xpc ) + ( ydpc - ypc ) * ( yspc - ypc ) ) / ( ld * ls ) ); 01790 cp = ( xdpc - xpc ) * ( yspc - ypc ) - ( ydpc - ypc ) * ( xspc - xpc ); 01791 if ( cp < 0.0 ) 01792 { 01793 phi = -phi; 01794 } 01795 phi = 0.5 * PI - phi; 01796 } 01797 01798 /* Determine how to adjust the "stride" of the text to make it 01799 * appear that it is going into (or out of) the page. Basically 01800 * scale the x baseline of the text by the normalized length of 01801 * the d vector projected into the x-y plane. */ 01802 x_o = plP_w3wcx( wx, wy, wz ); 01803 y_o = plP_w3wcy( wx, wy, wz ); 01804 z_o = plP_w3wcz( wx, wy, wz ); 01805 x_dx = x_o - plP_w3wcx( wx + dx, wy + dy, wz + dz ); 01806 y_dy = y_o - plP_w3wcy( wx + dx, wy + dy, wz + dz ); 01807 z_dz = z_o - plP_w3wcz( wx + dx, wy + dy, wz + dz ); 01808 01809 stride = sqrt( x_dx * x_dx + y_dy * y_dy ); 01810 stride = stride / sqrt( x_dx * x_dx + y_dy * y_dy + z_dz * z_dz ); 01811 01812 /* compute the reference point */ 01813 xpc = plP_dcmmx( plP_pcdcx( (PLINT) xpc ) ); 01814 ypc = plP_dcmmy( plP_pcdcy( (PLINT) ypc ) ); 01815 01816 shift = plstrl( text ) * just; 01817 xrefpc = xpc - cos( theta ) * shift * stride; 01818 yrefpc = ypc - sin( theta ) * shift * stride; 01819 01820 xpc = plP_mmpcx( xpc ); 01821 ypc = plP_mmpcy( ypc ); 01822 xrefpc = plP_mmpcx( xrefpc ); 01823 yrefpc = plP_mmpcy( yrefpc ); 01824 01825 /* compute the transform */ 01826 /* This affine transformation corresponds to transforming from old 01827 * coordinates to new coordinates by rotating axes, y shearing 01828 * or (y skewing), and scaling. 01829 * Comment out the explicit xform calculations because we use 01830 * the affine utilities for that calculation instead. */ 01831 /* 01832 * xform[0] = cos( theta ) * stride; 01833 * xform[1] = cos( theta ) * sin( phi ) - sin( theta ) * cos( phi ); 01834 * xform[2] = sin( theta ) * stride; 01835 * xform[3] = sin( theta ) * sin( phi ) + cos( theta ) * cos( phi ); 01836 */ 01837 plP_affine_rotate( xform, 180. * theta / PI ); 01838 plP_affine_yskew( affineL, -180. * phi / PI ); 01839 plP_affine_multiply( xform, affineL, xform ); 01840 cosphi = cos( phi ); 01841 if ( fabs( cosphi ) > 1.e-300 ) 01842 plP_affine_scale( affineL, 1. / stride, 1. / cosphi ); 01843 else 01844 plP_affine_scale( affineL, 1. / stride, 1.e300 ); 01845 plP_affine_multiply( xform, affineL, xform ); 01846 01847 plP_text( 0, just, xform, (PLINT) xpc, (PLINT) ypc, (PLINT) xrefpc, (PLINT) yrefpc, text ); 01848 } 01849 01850 /*------------------------------------------------------------------------*\ 01851 * void plsfont() 01852 * 01853 * Set the family, style and weight of the current font. 01854 * This is a user-friendly front-end to plsfci. 01855 * Note: A negative value signifies that this element should not be changed. 01856 \*------------------------------------------------------------------------*/ 01857 void 01858 c_plsfont( PLINT family, PLINT style, PLINT weight ) 01859 { 01860 PLUNICODE fci; 01861 01862 plgfci( &fci ); 01863 01864 if ( family >= 0 ) 01865 { 01866 /* Bounds checking assumes symbol is last font */ 01867 if ( family > PL_FCI_SYMBOL ) 01868 plwarn( "plsfont: Value for family is out of range" ); 01869 else 01870 plP_hex2fci( (unsigned char) family, PL_FCI_FAMILY, &fci ); 01871 } 01872 01873 if ( style >= 0 ) 01874 { 01875 /* Bounds checking assumes oblique is last style */ 01876 if ( style > PL_FCI_OBLIQUE ) 01877 plwarn( "plsfont: Value for style is out of range" ); 01878 else 01879 plP_hex2fci( (unsigned char) style, PL_FCI_STYLE, &fci ); 01880 } 01881 01882 if ( weight >= 0 ) 01883 { 01884 /* Bounds checking assumes bold is last weight */ 01885 if ( weight > PL_FCI_BOLD ) 01886 plwarn( "plsfont: Value for weight is out of range" ); 01887 else 01888 plP_hex2fci( (unsigned char) weight, PL_FCI_WEIGHT, &fci ); 01889 } 01890 01891 plsfci( fci ); 01892 } 01893 01894 /*------------------------------------------------------------------------*\ 01895 * void plgfont() 01896 * 01897 * Get the family, style and weight of the current font. 01898 * This is a user-friendly front-end to plgfci. 01899 * Note: A NULL pointer signifies that this value should not be returned. 01900 \*------------------------------------------------------------------------*/ 01901 void 01902 c_plgfont( PLINT *p_family, PLINT *p_style, PLINT *p_weight ) 01903 { 01904 PLUNICODE fci; 01905 unsigned char val; 01906 01907 plgfci( &fci ); 01908 01909 if ( p_family ) 01910 { 01911 plP_fci2hex( fci, &val, PL_FCI_FAMILY ); 01912 *p_family = (PLINT) val; 01913 } 01914 01915 if ( p_style ) 01916 { 01917 plP_fci2hex( fci, &val, PL_FCI_STYLE ); 01918 *p_style = (PLINT) val; 01919 } 01920 01921 if ( p_weight ) 01922 { 01923 plP_fci2hex( fci, &val, PL_FCI_WEIGHT ); 01924 *p_weight = (PLINT) val; 01925 } 01926 } 01927 01928 01929 #undef PLSYM_H 01930 #endif