PLplot  5.10.0
aqt.c
Go to the documentation of this file.
00001 // March 12, 2005
00002 //
00003 //      PLplot driver for AquaTerm and Mac OS X.
00004 //
00005 //      Copyright (C) Per Persson
00006 //      Copyright (C) 2005 Hazen Babcock
00007 //
00008 //      This file is part of PLplot.
00009 //
00010 //      PLplot is free software; you can redistribute it and/or modify
00011 //      it under the terms of the GNU Library General Public License as published
00012 //      by the Free Software Foundation; either version 2 of the License, or
00013 //      (at your option) any later version.
00014 //
00015 //      PLplot is distributed in the hope that it will be useful,
00016 //      but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 //      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018 //      GNU Library General Public License for more details.
00019 //
00020 //      You should have received a copy of the GNU Library General Public License
00021 //      along with PLplot; if not, write to the Free Software
00022 //      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00023 //
00024 //
00025 
00026 //---------------------------------------------
00027 // Header files, defines and local variables
00028 // ---------------------------------------------
00029 
00030 // OS X specific header files
00031 
00032 #import <Foundation/Foundation.h>
00033 #import <AquaTerm/AQTAdapter.h>
00034 
00035 // PLplot header files
00036 
00037 #include "plplotP.h"
00038 #include "drivers.h"
00039 
00040 // constants
00041 
00042 #define SCALE             0.1
00043 #define AQT_Default_X     720
00044 #define AQT_Default_Y     540
00045 #define DPI               72.0
00046 
00047 #define MAX_STRING_LEN    1000
00048 
00049 // local variables
00050 
00051 static NSAutoreleasePool *arpool;     // Objective-C autorelease pool
00052 static id adapter;                    // Adapter object
00053 
00054 PLDLLIMPEXP_DRIVER const char* plD_DEVICE_INFO_aqt = "aqt:AquaTerm (Mac OS X):1:aqt:50:aqt\n";
00055 
00056 static int  currentPlot = 0;
00057 static int  maxWindows  = 30;
00058 static int  windowXSize = 0;
00059 static int  windowYSize = 0;
00060 
00061 static bool didTests = false;
00062 static bool hasShear = false;
00063 static bool hasAlpha = false;
00064 
00065 // font stuff
00066 
00067 //
00068 //      AquaTerm font look-up table
00069 //
00070 //      The table is initialized with lowest common denominator truetype
00071 //      fonts that (I hope) most Macs will have.
00072 //
00073 
00074 #define AQT_N_FontLookup    30
00075 static FCI_to_FontName_Table AQT_FontLookup[AQT_N_FontLookup] = {
00076     { PL_FCI_MARK | 0x000, (unsigned char *) "Helvetica"             },
00077     { PL_FCI_MARK | 0x001, (unsigned char *) "Times-Roman"           },
00078     { PL_FCI_MARK | 0x002, (unsigned char *) "Courier"               },
00079     { PL_FCI_MARK | 0x003, (unsigned char *) "Times-Roman"           },
00080     { PL_FCI_MARK | 0x004, (unsigned char *) "LucidaGrande Regular"  },
00081     { PL_FCI_MARK | 0x010, (unsigned char *) "Helvetica-Oblique"     },
00082     { PL_FCI_MARK | 0x011, (unsigned char *) "Times-Italic"          },
00083     { PL_FCI_MARK | 0x012, (unsigned char *) "Courier-Oblique"       },
00084     { PL_FCI_MARK | 0x013, (unsigned char *) "Times-Italic"          },
00085     { PL_FCI_MARK | 0x014, (unsigned char *) "LucidaGrande Regular"  },
00086     { PL_FCI_MARK | 0x020, (unsigned char *) "Helvetica-Oblique"     },
00087     { PL_FCI_MARK | 0x021, (unsigned char *) "Times-Italic"          },
00088     { PL_FCI_MARK | 0x022, (unsigned char *) "Courier-Oblique"       },
00089     { PL_FCI_MARK | 0x023, (unsigned char *) "Times-Italic"          },
00090     { PL_FCI_MARK | 0x024, (unsigned char *) "LucidaGrande Regular"  },
00091     { PL_FCI_MARK | 0x100, (unsigned char *) "Helvetica-Bold"        },
00092     { PL_FCI_MARK | 0x101, (unsigned char *) "Times-Bold"            },
00093     { PL_FCI_MARK | 0x102, (unsigned char *) "Courier-Bold"          },
00094     { PL_FCI_MARK | 0x103, (unsigned char *) "Times-Bold"            },
00095     { PL_FCI_MARK | 0x104, (unsigned char *) "LucidaGrande Regular"  },
00096     { PL_FCI_MARK | 0x110, (unsigned char *) "Helvetica-BoldOblique" },
00097     { PL_FCI_MARK | 0x111, (unsigned char *) "Times-BoldItalic"      },
00098     { PL_FCI_MARK | 0x112, (unsigned char *) "Courier-BoldOblique"   },
00099     { PL_FCI_MARK | 0x113, (unsigned char *) "Times-BoldItalic"      },
00100     { PL_FCI_MARK | 0x114, (unsigned char *) "LucidaGrande Regular"  },
00101     { PL_FCI_MARK | 0x120, (unsigned char *) "Helvetica-BoldOblique" },
00102     { PL_FCI_MARK | 0x121, (unsigned char *) "Times-BoldItalic"      },
00103     { PL_FCI_MARK | 0x122, (unsigned char *) "Courier-BoldOblique"   },
00104     { PL_FCI_MARK | 0x123, (unsigned char *) "Times-BoldItalic"      },
00105     { PL_FCI_MARK | 0x124, (unsigned char *) "LucidaGrande Regular"  }
00106 };
00107 
00108 //
00109 //      AquaTerm font environment variables
00110 //
00111 //      When the driver is initialized it will check to see if
00112 //      the user has opted to overide one of the above fonts by
00113 //      setting one of the environment variables below.
00114 //
00115 //      This list must be in the same order with the same number of
00116 //      elements as the above list
00117 //
00118 //      These are the same environment variable names as would be used
00119 //      on a linux system, but they have a slightly different meaning.
00120 //      Since AquaTerm will find the font for us (if it can) given
00121 //      just the font name, you should only set the environment
00122 //      variable to the font name. You don't need to provide
00123 //      a path. If you installed the font using Font Book, AquaTerm
00124 //      should not have any trouble finding it.
00125 //
00126 //      FIXME: Would it be better to use different environment variable
00127 //              names then plfreetype.c? If not, then it probably isn't
00128 //              ideal to have two different copies of the same list of
00129 //              environment variable names.
00130 //
00131 
00132 const char *aqt_font_env_names[AQT_N_FontLookup] = {
00133     "PLPLOT_FREETYPE_SANS_FONT",
00134     "PLPLOT_FREETYPE_SERIF_FONT",
00135     "PLPLOT_FREETYPE_MONO_FONT",
00136     "PLPLOT_FREETYPE_SCRIPT_FONT",
00137     "PLPLOT_FREETYPE_SYMBOL_FONT",
00138     "PLPLOT_FREETYPE_SANS_ITALIC_FONT",
00139     "PLPLOT_FREETYPE_SERIF_ITALIC_FONT",
00140     "PLPLOT_FREETYPE_MONO_ITALIC_FONT",
00141     "PLPLOT_FREETYPE_SCRIPT_ITALIC_FONT",
00142     "PLPLOT_FREETYPE_SYMBOL_ITALIC_FONT",
00143     "PLPLOT_FREETYPE_SANS_OBLIQUE_FONT",
00144     "PLPLOT_FREETYPE_SERIF_OBLIQUE_FONT",
00145     "PLPLOT_FREETYPE_MONO_OBLIQUE_FONT",
00146     "PLPLOT_FREETYPE_SCRIPT_OBLIQUE_FONT",
00147     "PLPLOT_FREETYPE_SYMBOL_OBLIQUE_FONT",
00148     "PLPLOT_FREETYPE_SANS_BOLD_FONT",
00149     "PLPLOT_FREETYPE_SERIF_BOLD_FONT",
00150     "PLPLOT_FREETYPE_MONO_BOLD_FONT",
00151     "PLPLOT_FREETYPE_SCRIPT_BOLD_FONT",
00152     "PLPLOT_FREETYPE_SYMBOL_BOLD_FONT",
00153     "PLPLOT_FREETYPE_SANS_BOLD_ITALIC_FONT",
00154     "PLPLOT_FREETYPE_SERIF_BOLD_ITALIC_FONT",
00155     "PLPLOT_FREETYPE_MONO_BOLD_ITALIC_FONT",
00156     "PLPLOT_FREETYPE_SCRIPT_BOLD_ITALIC_FONT",
00157     "PLPLOT_FREETYPE_SYMBOL_BOLD_ITALIC_FONT",
00158     "PLPLOT_FREETYPE_SANS_BOLD_OBLIQUE_FONT",
00159     "PLPLOT_FREETYPE_SERIF_BOLD_OBLIQUE_FONT",
00160     "PLPLOT_FREETYPE_MONO_BOLD_OBLIQUE_FONT",
00161     "PLPLOT_FREETYPE_SCRIPT_BOLD_OBLIQUE_FONT",
00162     "PLPLOT_FREETYPE_SYMBOL_BOLD_OBLIQUE_FONT"
00163 };
00164 
00165 // Debugging extras
00166 
00167 static inline void NOOP_( id x, ... )
00168 {
00169     ;
00170 }
00171 
00172 #ifdef LOGGING
00173 #define LOG    NSLog
00174 #else
00175 #define LOG    NOOP_
00176 #endif  // LOGGING
00177 
00178 //-----------------------------------------------
00179 // function declarations
00180 // -----------------------------------------------
00181 
00182 // helper functions
00183 
00184 static void get_cursor( PLStream *, PLGraphicsIn * );
00185 static void proc_str( PLStream *, EscText * );
00186 NSMutableAttributedString * create_string( const PLUNICODE *, int, PLFLT );
00187 static void set_font_and_size( NSMutableAttributedString *, PLUNICODE, PLFLT, int );
00188 static void check_font_environment_variables( void );
00189 
00190 // PLplot interface functions
00191 
00192 void plD_dispatch_init_aqt( PLDispatchTable *pdt );
00193 void plD_init_aqt( PLStream * );
00194 void plD_line_aqt( PLStream *, short, short, short, short );
00195 void plD_polyline_aqt( PLStream *, short *, short *, PLINT );
00196 void plD_eop_aqt( PLStream * );
00197 void plD_bop_aqt( PLStream * );
00198 void plD_tidy_aqt( PLStream * );
00199 void plD_state_aqt( PLStream *, PLINT );
00200 void plD_esc_aqt( PLStream *, PLINT, void * );
00201 
00202 //--------------------------------------------------------------------------
00203 // dispatch_init_init()
00204 //
00205 // Initialize device dispatch table
00206 //--------------------------------------------------------------------------
00207 
00208 void plD_dispatch_init_aqt( PLDispatchTable *pdt )
00209 {
00210 #ifndef ENABLE_DYNDRIVERS
00211     pdt->pl_MenuStr = "AquaTerm - Mac OS X";
00212     pdt->pl_DevName = "aqt";
00213 #endif
00214     pdt->pl_type     = plDevType_Interactive;
00215     pdt->pl_seq      = 1;
00216     pdt->pl_init     = (plD_init_fp) plD_init_aqt;
00217     pdt->pl_line     = (plD_line_fp) plD_line_aqt;
00218     pdt->pl_polyline = (plD_polyline_fp) plD_polyline_aqt;
00219     pdt->pl_eop      = (plD_eop_fp) plD_eop_aqt;
00220     pdt->pl_bop      = (plD_bop_fp) plD_bop_aqt;
00221     pdt->pl_tidy     = (plD_tidy_fp) plD_tidy_aqt;
00222     pdt->pl_state    = (plD_state_fp) plD_state_aqt;
00223     pdt->pl_esc      = (plD_esc_fp) plD_esc_aqt;
00224 }
00225 
00226 //--------------------------------------------------------------------------
00227 // aqt_init()
00228 //
00229 // Initialize device
00230 //--------------------------------------------------------------------------
00231 
00232 void plD_init_aqt( PLStream *pls )
00233 {
00234     if ( arpool == NULL ) // Make sure we don't leak mem by allocating every time
00235     {
00236         arpool  = [[NSAutoreleasePool alloc] init];
00237         adapter = [[AQTAdapter alloc] init];
00238     }
00239     [adapter setBackgroundColorRed : 0.5 green : 0.5 blue : 0.5];
00240 
00241     pls->termin      = 1;               // interactive device
00242     pls->dev_flush   = 1;               // Handle our own flushes
00243     pls->color       = 1;               // supports color
00244     pls->width       = 1;
00245     pls->verbose     = 1;
00246     pls->bytecnt     = 0;
00247     pls->debug       = 1;
00248     pls->dev_text    = 1;       // handles text
00249     pls->dev_unicode = 1;       // wants text as unicode
00250     pls->page        = 0;
00251     pls->dev_fill0   = 1;       // supports hardware solid fills
00252     pls->dev_fill1   = 1;
00253 
00254     pls->graphx = GRAPHICS_MODE;
00255 
00256     if ( !pls->colorset )
00257         pls->color = 1;
00258 
00259     // Set up device parameters
00260 
00261     plP_setpxl( DPI / 25.4 / SCALE, DPI / 25.4 / SCALE ); // Pixels/mm.
00262 
00263     // Set the bounds for plotting.  default is AQT_Default_X x AQT_Default_Y unless otherwise specified.
00264 
00265     if ( pls->xlength <= 0 || pls->ylength <= 0 )
00266     {
00267         windowXSize = AQT_Default_X;
00268         windowYSize = AQT_Default_Y;
00269         plP_setphy( (PLINT) 0, (PLINT) ( AQT_Default_X / SCALE ), (PLINT) 0, (PLINT) ( AQT_Default_Y / SCALE ) );
00270     }
00271     else
00272     {
00273         windowXSize = pls->xlength;
00274         windowYSize = pls->ylength;
00275         plP_setphy( (PLINT) 0, (PLINT) ( pls->xlength / SCALE ), (PLINT) 0, (PLINT) ( pls->ylength / SCALE ) );
00276     }
00277 
00278     // check font environment variables & update font table as necessary
00279 
00280     check_font_environment_variables();
00281 
00282     // Check to see if the users version of aquaterm supports sheared labels.
00283     // If it isn't available 3D plots will look a little strange but things should otherwise be okay.
00284 
00285     if ( !didTests )
00286     {
00287         hasShear = [adapter respondsToSelector:@selector( addLabel:atPoint:angle:shearAngle:align: )];
00288         hasAlpha = [adapter respondsToSelector:@selector( setColorRed:green:blue:alpha: )];
00289         didTests = true;
00290     }
00291 }
00292 
00293 //--------------------------------------------------------------------------
00294 // aqt_bop()
00295 //
00296 // Set up for the next page.
00297 //--------------------------------------------------------------------------
00298 
00299 void plD_bop_aqt( PLStream *pls )
00300 {
00301     currentPlot = currentPlot >= maxWindows ? 0 : currentPlot;
00302     [adapter openPlotWithIndex : currentPlot++];
00303     [adapter setPlotSize : NSMakeSize( windowXSize, windowYSize )];
00304     [adapter setLinewidth : 1.0];
00305     if ( hasAlpha )
00306     {
00307         [adapter setColorRed : (float) ( pls->curcolor.r / 255. )
00308          green : (float) ( pls->curcolor.g / 255. )
00309          blue : (float) ( pls->curcolor.b / 255. )
00310          alpha : (float) ( pls->curcolor.a )];
00311     }
00312     else
00313     {
00314         [adapter setColorRed : (float) ( pls->curcolor.r / 255. )
00315          green : (float) ( pls->curcolor.g / 255. )
00316          blue : (float) ( pls->curcolor.b / 255. )];
00317     }
00318 
00319     pls->page++;
00320 }
00321 
00322 //--------------------------------------------------------------------------
00323 // aqt_line()
00324 //
00325 // Draw a line in the current color from (x1,y1) to (x2,y2).
00326 //--------------------------------------------------------------------------
00327 
00328 void plD_line_aqt( PLStream *pls, short x1a, short y1a, short x2a, short y2a )
00329 {
00330     [adapter moveToPoint : NSMakePoint( (float) x1a * SCALE, (float) y1a * SCALE )];
00331     [adapter addLineToPoint : NSMakePoint( (float) x2a * SCALE, (float) y2a * SCALE )];
00332 }
00333 
00334 //--------------------------------------------------------------------------
00335 // aqt_polyline()
00336 //
00337 // Draw a polyline in the current color.
00338 //--------------------------------------------------------------------------
00339 
00340 void plD_polyline_aqt( PLStream *pls, short *xa, short *ya, PLINT npts )
00341 {
00342     int i;
00343 
00344     for ( i = 0; i < npts - 1; i++ )
00345         plD_line_aqt( pls, xa[i], ya[i], xa[i + 1], ya[i + 1] );
00346 }
00347 
00348 //--------------------------------------------------------------------------
00349 // aqt_eop()
00350 //
00351 // End of page
00352 //--------------------------------------------------------------------------
00353 
00354 void plD_eop_aqt( PLStream *pls )
00355 {
00356     [arpool release]; // prevents a memory leak by freeing everything in
00357                       // the auto-release pool when the plot is closed.
00358     arpool = [[NSAutoreleasePool alloc] init];
00359     [adapter renderPlot];
00360 }
00361 
00362 //--------------------------------------------------------------------------
00363 // aqt_tidy()
00364 //
00365 // Close graphics file or otherwise clean up.
00366 //--------------------------------------------------------------------------
00367 
00368 void plD_tidy_aqt( PLStream *pls )
00369 {
00370     [adapter closePlot];
00371 }
00372 
00373 //--------------------------------------------------------------------------
00374 // plD_state_aqt()
00375 //
00376 // Handle change in PLStream state (color, pen width, fill attribute, etc).
00377 //--------------------------------------------------------------------------
00378 
00379 void plD_state_aqt( PLStream *pls, PLINT op )
00380 {
00381     int   i;
00382     float r, g, b;
00383 
00384     switch ( op )
00385     {
00386     case PLSTATE_WIDTH:
00387         [adapter setLinewidth : (float) pls->width];
00388         break;
00389 
00390     case PLSTATE_COLOR0:        // this seems to work, but that isn't to say that it is done right...
00391         if ( hasAlpha )
00392         {
00393             [adapter setBackgroundColorRed : (float) ( plsc->cmap0[0].r / 255.0 )
00394              green : (float) ( plsc->cmap0[0].g / 255.0 )
00395              blue : (float) ( plsc->cmap0[0].b / 255.0 )
00396              alpha : (float) ( plsc->cmap0[0].a )];
00397         }
00398         else
00399         {
00400             [adapter setBackgroundColorRed : (float) ( plsc->cmap0[0].r / 255.0 )
00401              green : (float) ( plsc->cmap0[0].g / 255.0 )
00402              blue : (float) ( plsc->cmap0[0].b / 255.0 )];
00403         }
00404     case PLSTATE_COLOR1:
00405     case PLSTATE_FILL:
00406         if ( hasAlpha )
00407         {
00408             [adapter setColorRed : (float) ( pls->curcolor.r / 255. )
00409              green : (float) ( pls->curcolor.g / 255. )
00410              blue : (float) ( pls->curcolor.b / 255. )
00411              alpha : (float) ( pls->curcolor.a )];
00412         }
00413         else
00414         {
00415             [adapter setColorRed : (float) ( pls->curcolor.r / 255. )
00416              green : (float) ( pls->curcolor.g / 255. )
00417              blue : (float) ( pls->curcolor.b / 255. )];
00418         }
00419         break;
00420 
00421     case PLSTATE_CMAP0:
00422         break;
00423 
00424     case PLSTATE_CMAP1:
00425         break;
00426     }
00427 }
00428 
00429 //--------------------------------------------------------------------------
00430 // aqt_esc()
00431 //
00432 // Escape function.
00433 //
00434 // Functions:
00435 //
00436 // PLESC_EH        Handle pending events
00437 // PLESC_EXPOSE    Force an expose
00438 // PLESC_FILL      Fill polygon
00439 // PLESC_FLUSH     Flush X event buffer
00440 // PLESC_GETC      Get coordinates upon mouse click
00441 // PLESC_REDRAW    Force a redraw
00442 // PLESC_RESIZE    Force a resize
00443 //--------------------------------------------------------------------------
00444 
00445 void plD_esc_aqt( PLStream *pls, PLINT op, void *ptr )
00446 {
00447     int i;
00448     switch ( op )
00449     {
00450     case PLESC_EXPOSE:             // handle window expose
00451         break;
00452     case PLESC_RESIZE:             // handle window resize
00453         break;
00454     case PLESC_REDRAW:             // handle window redraw
00455         break;
00456     case PLESC_TEXT:               // switch to text screen
00457         break;
00458     case PLESC_GRAPH:              // switch to graphics screen
00459         break;
00460     case PLESC_FILL:               // fill polygon
00461         [adapter moveToVertexPoint : NSMakePoint( pls->dev_x[0] * SCALE, pls->dev_y[0] * SCALE )];
00462         for ( i = 1; i < pls->dev_npts; i++ )
00463         {
00464             [adapter addEdgeToVertexPoint : NSMakePoint( pls->dev_x[i] * SCALE, pls->dev_y[i] * SCALE )];
00465         }
00466         ;
00467         break;
00468     case PLESC_DI:                 // handle DI command
00469         break;
00470     case PLESC_FLUSH:              // flush output
00471         [adapter renderPlot];
00472         break;
00473     case PLESC_EH:                 // handle Window events
00474         break;
00475     case PLESC_GETC:               // get cursor position
00476         [adapter renderPlot];      // needed to give the user something to click on
00477         get_cursor( pls, (PLGraphicsIn *) ptr );
00478         break;
00479     case PLESC_SWIN:               // set window parameters
00480         break;
00481     case PLESC_HAS_TEXT:
00482         proc_str( pls, (EscText *) ptr );
00483         break;
00484     }
00485 }
00486 
00487 //--------------------------------------------------------------------------
00488 // get_cursor()
00489 //
00490 // returns the location of the next mouse click
00491 //--------------------------------------------------------------------------
00492 
00493 void get_cursor( PLStream *pls, PLGraphicsIn *gin )
00494 {
00495     int      scanned, x, y, button;
00496     NSString *temp;
00497 
00498     plGinInit( gin );
00499 
00500     temp    = [adapter waitNextEvent];
00501     scanned = sscanf([temp cString], "1:{%d, %d}:%d", &x, &y, &button );
00502 
00503     if ( scanned == 3 )         // check that we did actually get a reasonable event string
00504     {
00505         gin->button = button;
00506         gin->pX     = x;
00507         gin->pY     = y;
00508         gin->dX     = (PLFLT) x / ( (PLFLT) ( pls->xlength ) );
00509         gin->dY     = (PLFLT) y / ( (PLFLT) ( pls->ylength ) );
00510     }
00511     else                // just return zeroes if we did not
00512     {
00513         printf( "AquaTerm did not return a valid mouse location!\n" );
00514         gin->button = 0;
00515         gin->pX     = 0;
00516         gin->pY     = 0;
00517         gin->dX     = 0.0;
00518         gin->dY     = 0.0;
00519     }
00520 }
00521 
00522 //--------------------------------------------------------------------------
00523 // proc_str()
00524 //
00525 // Processes strings for display. The actual parsing of the unicode
00526 // string is handled by the sub-routine create_string.
00527 //--------------------------------------------------------------------------
00528 
00529 void proc_str( PLStream *pls, EscText *args )
00530 {
00531     PLFLT a1, ft_ht, angle, shear, stride;
00532     PLINT clxmin, clxmax, clymin, clymax;
00533     int   i, jst, ref;
00534     NSMutableAttributedString *str;
00535 
00536     // check that we got unicode, warning message and return if not
00537 
00538     if ( args->unicode_array_len == 0 )
00539     {
00540         printf( "Non unicode string passed to AquaTerm driver, ignoring\n" );
00541         return;
00542     }
00543 
00544     // check that unicode string isn't longer then the max we allow
00545 
00546     if ( args->unicode_array_len >= MAX_STRING_LEN )
00547     {
00548         printf( "Sorry, the AquaTerm driver only handles strings of length < %d\n", MAX_STRING_LEN );
00549         return;
00550     }
00551 
00552     // set the font height - the 1.2 factor was trial and error
00553 
00554     ft_ht = 1.2 * pls->chrht * DPI / 25.4; // ft_ht in points. ht is in mm
00555 
00556     // given transform, calculate rotation angle & shear angle
00557     plRotationShear( args->xform, &angle, &shear, &stride );
00558     angle *= 180.0 / PI;
00559     shear *= -180.0 / PI;
00560 
00561     // text justification, AquaTerm only supports 3 options, so we round appropriately
00562 
00563     if ( args->just < 0.33 )
00564         jst = AQTAlignLeft;                         // left
00565     else if ( args->just > 0.66 )
00566         jst = AQTAlignRight;                        // right
00567     else
00568         jst = AQTAlignCenter;                       // center
00569 
00570     // set the baseline of the string
00571     // Middle and Bottom are set to Middle since this seems to be what PLplot expects
00572     // as judged by where it renders the symbols in example 1.
00573 
00574     if ( args->base == 2 )      // Top
00575         ref = AQTAlignTop;
00576     else if ( args->base == 1 ) // Bottom
00577         ref = AQTAlignMiddle;
00578     else
00579         ref = AQTAlignMiddle; // Middle
00580 
00581     // create an appropriately formatted, etc... unicode string
00582 
00583     str = create_string( args->unicode_array, args->unicode_array_len, ft_ht );
00584 
00585     // display the string
00586 
00587     if ( hasAlpha )
00588     {
00589         [adapter setColorRed : (float) ( pls->curcolor.r / 255. )
00590          green : (float) ( pls->curcolor.g / 255. )
00591          blue : (float) ( pls->curcolor.b / 255. )
00592          alpha : (float) ( pls->curcolor.a )];
00593     }
00594     else
00595     {
00596         [adapter setColorRed : (float) ( pls->curcolor.r / 255. )
00597          green : (float) ( pls->curcolor.g / 255. )
00598          blue : (float) ( pls->curcolor.b / 255. )];
00599     }
00600 
00601     if ( hasShear )
00602     {
00603         [adapter addLabel : str
00604          atPoint : NSMakePoint( (float) args->x * SCALE, (float) args->y * SCALE )
00605          angle : angle
00606          shearAngle : shear
00607          align : ( jst | ref )];
00608     }
00609     else
00610     {
00611         [adapter addLabel : str
00612          atPoint : NSMakePoint( (float) args->x * SCALE, (float) args->y * SCALE )
00613          angle : angle
00614          align : ( jst | ref )];
00615     }
00616 
00617     [str release];
00618 }
00619 
00620 //--------------------------------------------------------------------------
00621 // create_string()
00622 //
00623 // create a NSMutableAttributedString from the plplot ucs4 string
00624 //
00625 // assumptions :
00626 // 1. font changes are unicode >= PL_FCI_MARK
00627 // 2. we'll never have to deal with a string longer then MAX_STRING_LEN characters
00628 // 3. <esc><esc> means we desired <esc> as a character & not actually as <esc>
00629 // 4. there are no two character <esc> sequences... i.e. <esc>fn is now covered by fci
00630 //
00631 //--------------------------------------------------------------------------
00632 
00633 NSMutableAttributedString  * create_string( const PLUNICODE *ucs4, int ucs4_len, PLFLT font_height )
00634 {
00635     PLUNICODE fci;
00636     char      plplot_esc;
00637     int       i;
00638     int       cur_loc;
00639     int       utf8_len;
00640     int       updown;
00641     char      dummy[MAX_STRING_LEN + 1];
00642     char                      *font;
00643     char      utf8[5];
00644     NSMutableAttributedString *str;
00645 
00646     updown = 0;
00647 
00648     // initialize the attributed string
00649 
00650     for ( i = 0; i < MAX_STRING_LEN; i++ )
00651         dummy[i] = 'i';
00652     dummy[MAX_STRING_LEN] = '\0';
00653     str = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithCString:dummy]];
00654 
00655     // get plplot escape character & current font
00656 
00657     plgesc( &plplot_esc );
00658     plgfci( &fci );
00659 
00660     // set the font for the string based on the current font & size
00661 
00662     set_font_and_size( str, fci, font_height, 0 );
00663 
00664     // parse plplot ucs4 string
00665 
00666     cur_loc = 0;
00667     i       = 0;
00668     while ( i < ucs4_len )
00669     {
00670         if ( ucs4[i] < PL_FCI_MARK )                                    // not a font change
00671         {
00672             if ( ucs4[i] != (PLUNICODE) plplot_esc )                    // a character to display
00673             {
00674                 ucs4_to_utf8( ucs4[i], utf8 );
00675                 [str replaceCharactersInRange : NSMakeRange( cur_loc, 1 )
00676                  withString :[NSString stringWithUTF8String : utf8]];
00677                 i++;
00678                 cur_loc++;
00679                 continue;
00680             }
00681             i++;
00682             if ( ucs4[i] == (PLUNICODE) plplot_esc )
00683             {
00684                 ucs4_to_utf8( ucs4[i], utf8 );
00685                 [str replaceCharactersInRange : NSMakeRange( cur_loc, 1 )
00686                  withString :[NSString stringWithUTF8String : utf8]];
00687                 i++;
00688                 cur_loc++;
00689                 continue;
00690             }
00691             else
00692             {
00693                 if ( ucs4[i] == (PLUNICODE) 'f' )       // font change
00694                 {
00695                     i++;
00696                     printf( "hmm, unicode string apparently not following fci convention...\n" );
00697                 }
00698                 if ( ucs4[i] == (PLUNICODE) 'd' )       // Subscript
00699                 {
00700                     updown--;
00701                     [str addAttribute : @ "NSSuperScript"
00702                      value :[NSNumber numberWithInt : updown]
00703                      range : NSMakeRange( cur_loc, ( MAX_STRING_LEN - cur_loc ) )];
00704                 }
00705                 if ( ucs4[i] == (PLUNICODE) 'u' )       // Superscript
00706                 {
00707                     updown++;
00708                     [str addAttribute : @ "NSSuperScript"
00709                      value :[NSNumber numberWithInt : updown]
00710                      range : NSMakeRange( cur_loc, ( MAX_STRING_LEN - cur_loc ) )];
00711                 }
00712                 i++;
00713             }
00714         }
00715         else    // a font change
00716         {
00717             set_font_and_size( str, ucs4[i], font_height, cur_loc );
00718             i++;
00719         }
00720     }
00721 
00722     // trim string to appropriate final length
00723 
00724     [str deleteCharactersInRange : NSMakeRange( cur_loc, ( MAX_STRING_LEN - cur_loc ) )];
00725 
00726     return str;
00727 }
00728 
00729 //--------------------------------------------------------------------------
00730 // set_font_and_size
00731 //
00732 // set the font & size of a attributable string object
00733 //--------------------------------------------------------------------------
00734 
00735 void set_font_and_size( NSMutableAttributedString * str, PLUNICODE fci, PLFLT font_height, int cur_loc )
00736 {
00737     char *font;
00738 
00739     font = plP_FCI2FontName( fci, AQT_FontLookup, AQT_N_FontLookup );
00740 
00741     // check whether that font exists & if not, use standard font instead
00742 
00743     if ( font == NULL )
00744     {
00745         printf( "AquaTerm : Warning, could not find font given by fci = 0x%x\n", fci );
00746         font = "Helvetica";
00747     }
00748     /* font = "FreeSerif";      *//* force the font for debugging purposes */
00749     // printf("Font at %d is : %s\n", cur_loc, font);
00750 
00751     [str addAttribute : @ "AQTFontname"
00752      value :[NSString stringWithCString : font]
00753      range : NSMakeRange( cur_loc, ( MAX_STRING_LEN - cur_loc ) )];
00754     [str addAttribute : @ "AQTFontsize"
00755      value :[NSNumber numberWithFloat : font_height]
00756      range : NSMakeRange( cur_loc, ( MAX_STRING_LEN - cur_loc ) )];
00757 }
00758 
00759 //--------------------------------------------------------------------------
00760 // check_font_environment_variables
00761 //
00762 // Checks to see if any font environment variables are defined.
00763 // If a font environment variable is defined, then the appropriate
00764 // element of the default font table is replaced with the font name
00765 // string specified by the environment variable.
00766 //--------------------------------------------------------------------------
00767 
00768 
00769 void check_font_environment_variables( void )
00770 {
00771     int  i;
00772     char *new_font;
00773     char *begin;
00774     char *end;
00775 
00776     for ( i = 0; i < AQT_N_FontLookup; i++ )
00777     {
00778         if ( ( new_font = getenv( aqt_font_env_names[i] ) ) != NULL )
00779         {
00780             // If the user is just blindly following the suggestions in
00781             // the plplot examples then we might get a font name with
00782             // a path and extension. We need to remove that since it
00783             // isn't relevant and will only cause trouble. We warn them
00784             // AquaTerm was not expecting a path or extension.
00785 
00786             begin = strrchr( new_font, '/' );
00787             end   = strrchr( new_font, '.' );
00788 
00789             if ( end != NULL )
00790             {
00791                 printf( "Aquaterm : Warning, removing extension from font name : %s\n", new_font );
00792                 *end = '\0';
00793             }
00794             if ( begin != NULL )
00795             {
00796                 printf( "AquaTerm : Warning, removing path from font name : %s\n", new_font );
00797                 new_font = begin + 1;
00798             }
00799 
00800             // printf("new font : %s\n", new_font);
00801 
00802             AQT_FontLookup[i].pfont = (unsigned char *) new_font;
00803         }
00804     }
00805 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines