1package Starlink::AST::PGPLOT;
2
3use strict;
4use vars qw/ $VERSION /;
5use constant R2D     => 57.29578;        # Radians to degrees factor
6use constant FLT_MAX => 3.40282347e+38;  # Maximum float on ix86 platform
7
8use PGPLOT;
9use Starlink::AST;
10use Carp;
11
12$VERSION = '2.00';
13
14=head1 NAME
15
16Starlink::AST::PGPLOT - AST wrapper to the PGPLOT library
17
18=head1 SYNOPSIS
19
20   use Starlink::AST::PGPLOT
21
22The main methods which need to be registered with the AST package
23are shown below,
24
25   $status = _GFlush();
26   $status = _GLine( \@x, \@y );
27   $status = _GMark( \@x, \@y, $type );
28   $status = _GText( $text, $x, $y, $just, $upx, $upy );
29   ( $status, $xb, $yb ) = _GTxExt( $text, $x, $y, $just, $upx, $upy );
30   ( $status, $chv, $chh ) = _GQch();
31   ( $status, $old_value ) = _GAttr( $attr, $value, $prim );
32   ( $status, $alpha, $beta) = _GScales();
33
34=head1 DESCRIPTION
35
36This file implements the low level graphics functions required by the rest
37of AST, by calling suitable PGPLOT functions (the FORTRAN PGPLOT interface
38is used).
39
40This file can be used as a template for the development of similar modules
41to support alternative graphics systems.
42
43=head1 NOTES
44
45All teh functions in this module are private, and are intended to be called
46from the AST module. None of these functions should be considered to be part
47of the packages public interface.
48
49=head1 METHODS
50
51=over 4
52
53=item B<_GBBuf>
54
55Start a new graphics buffering context.
56
57  my $status = _GBBuf();
58
59=cut
60
61sub _GBBuf {
62  pgbbuf();
63  return 1;
64}
65
66=item B<_GEBuf>
67
68End a graphics buffering context.
69
70  my $status = _GEBuf();
71
72=cut
73
74sub _GEBuf {
75  pgebuf();
76  return 1;
77}
78
79=item B<_GFlush>
80
81This function ensures that the display device is up-to-date, by flushing
82any pending graphics to the output device.
83
84   my $status = _GFlush();
85
86=cut
87
88sub _GFlush {
89   pgupdt();
90   return 1;
91}
92
93=item B<_GLine>
94
95This function displays lines joining the given positions.
96
97   my $status = _GLine( \@x, \@y );
98
99=cut
100
101sub _GLine {
102   my $x = shift;
103   my $y = shift;
104
105   if( scalar(@$x) > 1 && scalar(@$x) == scalar(@$y) ) {
106      pgline( scalar(@$x), $x, $y );
107   }
108   return 1;
109}
110
111=item B<_GMark>
112
113This function displays markers at the given positions.
114
115   my $status = _GMark( \@x, \@y, $type );
116
117where $type is an integer used to indicate the type of marker required.
118
119=cut
120
121sub _GMark {
122   my $x = shift;
123   my $y = shift;
124   my $type = shift;
125
126   if( scalar(@$x) >= 1 && scalar(@$x) == scalar(@$y) ) {
127      pgpt( scalar(@$x), $x, $y, $type );
128   }
129   return 1;
130}
131
132=item B<_GText>
133
134This function displays a character string $text at a given position using
135a specified justification and up-vector.
136
137   my $status = _GText( $text, $x, $y, $just, $upx, $upy );
138
139where $x is the reference x coordinate, $y is the reference y coordinate,
140and where $just is a character string which specifies the location within
141the text string which is to be placed at the reference position given by x
142and y. The first character may be 'T' for "top", 'C' for "centre", or 'B'
143for "bottom", and specifies the vertical location of the reference position.
144Note, "bottom" corresponds to the base-line of normal text. Some characters
145(eg "y", "g", "p", etc) descend below the base-line. The second  character
146may be 'L' for "left", 'C' for "centre", or 'R'  for "right", and specifies
147the horizontal location of the  reference position. If the string has less
148than 2 characters then 'C' is used for the missing characters.
149
150And $upx is the x component of the up-vector for the text, in graphics
151world coordinates. If necessary the supplied value should be negated to
152ensure that positive values always refer to displacements from  left to
153right on the screen.
154
155While $upy is the y component of the up-vector for the text, in graphics
156world coordinates. If necessary the supplied value should be negated to
157ensure that positive values always refer to displacements from  bottom to
158top on the screen.
159
160=cut
161
162sub _GText {
163   my ( $text, $x, $y, $just, $upx, $upy ) = @_;
164
165   # check we have a string to print
166   if( defined $text && length($text) != 0 ) {
167
168      # validate the justifcation
169      my $just1 = substr $just, 0, 1;
170      my $just2 = substr $just, 1, 1;
171      if ( defined $just && length($just) == 2 ) {
172
173        # if we have a bogus justification string default it
174        unless( $just1 =~ /^[TBC]/ ) {
175           warn "_GText: bad vertical justification defaulting to 'C'\n";
176           $just1 = "C";
177        }
178        unless( $just2 =~ /[LCR]/ ) {
179           warn "_GText: bad horizontal justification defaulting to 'C'\n";
180           $just2 = "C";
181        }
182      } else {
183         warn "_GText: No justification string defaulting to 'CC'\n";
184         $just1 = "C";
185         $just2 = "C";
186      }
187      $just = $just1 . $just2;
188
189      # get the axis scaling
190      my ( $ret, $alpha, $beta ) = _GScales();
191      return 0 if $ret == 0;
192
193      # If either axis is reversed, reverse the supplied up-vector
194      # components so that they refer to the world-coordinates axes.
195      $upx = -$upx if $alpha < 0.0;
196      $upy = -$upy if $beta < 0.0;
197
198      # Get the angle between the text base-line and horizontal.
199      my $angle = atan2( -$upx*$alpha, $upy*$beta)*R2D;
200
201      # Get the fractional horizontal justification as needed by PGPLOT.
202      my $fjust;
203      if( $just2 eq "L" ) {
204        $fjust = 0.0;
205      } elsif ( $just2 eq "R" ) {
206        $fjust = 1.0;
207      } else {
208        $fjust = 0.5;
209      }
210
211      # Unless the requested justification is "Bottom", we need to adjust
212      # the supplied reference position before we use it with PGPLOT because
213      # PGPLOT assumes "Bottom" justification.
214      if( $just1 ne "B" ) {
215
216         # Get the bounding box of the string. Note, only the size of the box
217         # is significant here, not its position. Also note, leading and
218         # trailing spaces are not included in the bounding box.
219         my ( @xbox, @ybox );
220         pgqtxt( $x, $y, $angle, $fjust, $text, \@xbox, \@ybox );
221
222         # Normalise the up-vector in world coordinates.
223         my $uplen = sqrt( $upx*$upx + $upy*$upy );
224         if( $uplen > 0.0 ){
225            $upx /= $uplen;
226            $upy /= $uplen;
227         } else {
228            ReportGrfError("_GText: Zero length up-vector supplied.");
229            return 0;
230         }
231
232         # Find the height of the text above the base-line. Note, the PGPLOT
233         # manual is not clear about the order of the corners returned by
234         # pgqtxt, so we have to find the largest distance between the corners
235         # in the direction of the supplied up-vector.
236         my $hu = 0.0;
237         for my $i ( 0 ... 3 ) {
238            my $test = $upx*( $xbox[$i] - $x ) + $upy*( $ybox[$i] - $y );
239            $hu = $test if $test > $hu;
240         }
241
242         # Adjust the vertical position of the reference point, since PGPLOT
243         # requires it to be at the bottom of the text.
244         if( $just1 eq 'T' ) {
245            $x -= $upx*$hu;
246            $y -= $upy*$hu;
247         } elsif( $just1 eq 'C' ){
248            $x -= 0.5*$upx*$hu;
249            $y -= 0.5*$upy*$hu;
250         }
251      }
252
253      # Display the text, erasing any graphics.
254      my $tbg;
255      pgqtbg( $tbg );
256      pgstbg( 0 );
257      pgptxt( $x, $y, $angle, $fjust, $text );
258      pgstbg( $tbg );
259   }
260
261   # Return, all is well strangely
262   return 1;
263}
264
265
266=item B<_GScales>
267
268This function returns two values (one for each axis) which scale
269increments on the corresponding axis into a "normal" coordinate system in
270which: The axes have equal scale in terms of (for instance) millimetres
271per unit distance, X values increase from left to right and the Y values
272increase from bottom to top.
273
274   my ( $status, $alpha, $beta ) = _GScales()
275
276=cut
277
278sub _GScales {
279    my $alpha = shift;
280    my $beta = shift;
281
282    my ( $nx1, $nx2, $ny1, $ny2, $wx1, $wx2, $wy1, $wy2, $ret );
283    pgqvp( 2, $nx1, $nx2, $ny1, $ny2 );
284    pgqwin( $wx1, $wx2, $wy1, $wy2 );
285
286    if( $wx2 != $wx1 && $wy2 != $wy1 && $nx2 != $nx1 && $ny2 != $ny1 ) {
287       $alpha = ( $nx2 - $nx1 ) / ( $wx2 - $wx1 );
288       $beta = ( $ny2 - $ny1 ) / ( $wy2 - $wy1 );
289       $ret = 1
290    } else {
291       ReportGrfError("_GScales: The graphics window has zero size\n");
292       $ret = 0;
293    }
294    return ( $ret, $alpha, $beta );
295}
296
297
298=item B<_GTxExt>
299
300This function returns the corners of a box which would enclose the
301supplied character string if it were displayed using astGText. The
302returned box INCLUDES any leading or trailing spaces.
303
304   my ( $status, $xb, $yb ) = _GTxtExt( $text, $x, $y, $just, $upx, $upy);
305
306where $x is the reference x coordinate, $y is the reference y coordinate,
307and where $justification is a character string which specifies the
308location within the text string which is to be placed at the reference
309position given by x and y. The first character may be 'T' for "top", 'C'
310for "centre", or 'B' for "bottom", and specifies the vertical location of
311the reference position. Note, "bottom" corresponds to the base-line of
312normal text. Some characters  (eg "y", "g", "p", etc) descend below the
313base-line. The second  character may be 'L' for "left", 'C' for "centre",
314or 'R'  for "right", and specifies the horizontal location of the
315reference position. If the string has less than 2 characters then 'C' is
316used for the missing characters.
317
318And $upx is the x component of the up-vector for the text, in graphics
319world coordinates. If necessary the supplied value should be negated to
320ensure that positive values always refer to displacements from  left to
321right on the screen.
322
323While $upy is the y component of the up-vector for the text, in graphics
324world coordinates. If necessary the supplied value should be negated to
325ensure that positive values always refer to displacements from  bottom to
326top on the screen.
327
328Finally $xb is a refernce to an array of 4 elements in which to return the
329x coordinate of each corner of the bounding box, and $yb is a reference to
330an array of 4 elements in which to return the y coordinate of each corner
331of the bounding box.
332
333Notes:
334     -  The order of the corners is anti-clockwise (in world coordinates)
335        starting at the bottom left.
336     -  A NULL value for "just" causes a value of "CC" to be used.
337     -  Both "upx" and "upy" being zero causes an error.
338     -  Any unrecognised character in "just" causes an error.
339     -  Zero is returned for all bounds of the box if an error occurs.
340
341=cut
342
343sub _GTxExt {
344   my ( $text, $x, $y, $just, $upx, $upy ) = @_;
345
346   # initalise @$xb and @$yb
347   my ( @xb, @yb );
348   foreach my $i ( 0 ... 3 ) {
349      $xb[$i] = 0.0;
350      $yb[$i] = 0.0;
351   }
352
353   # check we have a string to print
354   if( defined $text && length($text) != 0 ) {
355
356      # validate the justifcation
357      my $just1 = substr $just, 0, 1;
358      my $just2 = substr $just, 1, 1;
359      if ( defined $just && length($just) == 2 ) {
360
361        # if we have a bogus justification string default it
362        unless( $just1 =~ /[TBC]/ ) {
363           warn "_GText: bad vertical justification defaulting to 'C'\n";
364           $just1 = "C";
365        }
366        unless( $just2 =~ /[LCR]/ ) {
367           warn "_GText: bad horizontal justification defaulting to 'C'\n";
368           $just2 = "C";
369        }
370      } else {
371         warn "_GText: No justification string defaulting to 'CC'\n";
372         $just1 = "C";
373         $just2 = "C";
374      }
375      $just = $just1 . $just2;
376
377      # get the axis scaling
378      my ( $ret, $alpha, $beta ) = _GScales();
379      return ( 0 ) if $ret == 0;
380
381      # If either axis is reversed, reverse the supplied up-vector
382      # components so that they refer to the world-coordinates axes.
383      $upx = -$upx if $alpha < 0.0;
384      $upy = -$upy if $beta < 0.0;
385
386      # convert the up-vector into millimetres
387      my $ux = $alpha*$upx;
388      my $uy = $beta*$upy;
389
390      # normalise the up-vector to a length of 1 millimetre
391      my $uplen = sqrt( $ux*$ux + $uy*$uy );
392      if ( $uplen > 0.0 ) {
393         $ux /= $uplen;
394         $uy /= $uplen;
395      } else {
396         ReportGrfError("_GTxtExt: Zero length up-vector supplied.");
397         return ( 0 );
398      }
399
400      # Form the base-line vector by rotating the up-vector by 90 degrees
401      # clockwise.
402      my $vx = $uy;
403      my $vy = -$ux;
404
405      # Get the angle between the text base-line and horizontal.
406      my $angle = atan2( $vy, $vx )*R2D;
407
408      # Get the bounding box of the string drawn with its bottom left corner
409      # at the origin.
410      my ( @xbox, @ybox );
411      pgqtxt( 0.0, 0.0, $angle, 0.0, $text, \@xbox, \@ybox );
412
413      # Convert the returned bounding box world coordinates into millimetres.
414      for my $i ( 0 ... 3 ){
415         $xbox[ $i ] *= $alpha;
416         $ybox[ $i ] *= $beta;
417      }
418
419      # Find the height of the bounding box, in millimetres. Note,
420      # the PGPLOT manual is not clear about the order of the corners
421      # returned by pgqtxt, so we have to find the largest distance between
422      # the corners in the direction of the supplied up-vector. The reference
423      # point is on the text base-line which is not usually at the bottom of
424      # the bounding box (some letters - like "y" - extend below the base-line).
425      # Find the distance from the base-line to the top (hu) and bottom (hd)
426      # of the bounding box.
427      my $hu = -(FLT_MAX);
428      my $hd = FLT_MAX;
429      foreach my $i ( 0 ... 3 ) {
430         my $test = $ux*$xbox[ $i ] + $uy*$ybox[ $i ];
431         $hu = $test if $test > $hu;
432         $hd = $test if $test < $hd;
433      }
434
435      # Get an up and a down vector scaled to the height/depth of the
436      # bounding box above/below the text base-line .
437      my $uxu = $ux*$hu;
438      my $uyu = $uy*$hu;
439      my $uxd = $ux*$hd;
440      my $uyd = $uy*$hd;
441
442      # The bounding box returned by pgqtxt does not include any leading or
443      # trailing spaces. We need to include such spaces in the returned box.
444      # To do this we get the length of the text string in millimetres
445      # using pglen instead of using the bounding box returned by pgqtxt.
446      my ( $xl, $yl );
447      pglen( 2, $text, $xl, $yl );
448
449      # The abolute width of the string in millimetres may depend on the
450      # up-vector. The values returned by pglen are for horizontal and
451      # vertical text. Find the width using the supplied up-vector.
452      my $a = $uy*$xl;
453      my $b = $ux*$yl;
454      my $width = sqrt( $a*$a + $b*$b );
455
456      # The pglen function returns a value which is slightly smaller than
457      # the area cleared to hold the text when written using pgptxt. Increase
458      # the text width so that it is about equal to the area cleared.
459      $width += 0.2*$hu;
460
461      # Scale the base-line vector so that its length is equal to the width
462      # of the bounding box (including spaces).
463      $vx *= $width;
464      $vy *= $width;
465
466      # Convert the base-line vector back into world coordinates.
467      $vx /= $alpha;
468      $vy /= $beta;
469
470      # Convert the up and down vectors into world coordinates.
471      $uxu /= $alpha;
472      $uyu /= $beta;
473      $uxd /= $alpha;
474      $uyd /= $beta;
475
476      # Find the coordinates at the centre of the bounding box in world
477      # coordinates.
478      my $xc = $x;
479      my $yc = $y;
480
481      if( $just1 eq 'B' ) {
482         $xc += 0.5*$uxu;
483         $yc += 0.5*$uyu;
484      } elsif( $just1 eq 'T' ) {
485         $xc -= 0.5*$uxu;
486         $yc -= 0.5*$uyu;
487      }
488
489      if( $just2 eq 'L' ) {
490         $xc += 0.5*$vx;
491         $yc += 0.5*$vy;
492      } elsif( $just2 eq 'R' ) {
493         $xc -= 0.5*$vx;
494         $yc -= 0.5*$vy;
495      }
496
497      # Get the corners of the bounding box.
498      my $vdx = 0.5*$vx;
499      my $vdy = 0.5*$vy;
500      my $udx = 0.5*$uxu;
501      my $udy = 0.5*$uyu;
502
503      # Bottom left corner...
504      $xb[ 0 ] = $xc - $vdx - $udx + $uxd;
505      $yb[ 0 ] = $yc - $vdy - $udy + $uyd;
506
507      # Bottom right corner...
508      $xb[ 1 ] = $xc + $vdx - $udx + $uxd;
509      $yb[ 1 ] = $yc + $vdy - $udy + $uyd;
510
511      # Top right corner...
512      $xb[ 2 ] = $xc + $vdx + $udx;
513      $yb[ 2 ] = $yc + $vdy + $udy;
514
515      # Top left corner...
516      $xb[ 3 ] = $xc - $vdx + $udx;
517      $yb[ 3 ] = $yc - $vdy + $udy;
518
519   }
520
521   # Return
522   return (1, \@xb, \@yb );
523
524}
525
526=item B<_GQch>
527
528This function returns the heights of characters drawn vertically and
529horizontally in world coordinates.
530
531   my ( $status, $chv, $chh ) = _GQch( );
532
533Where $chv is the height of characters drawn with a vertical
534baseline. This will be an increment in the X axis.  Where $chh is the
535height of characters drawn with a horizontal baseline. This will be an
536increment in the Y axis.
537
538=cut
539
540sub _GQch {
541   # return variables
542   my ( $status, $chv, $chh );
543
544   # local variables
545   my ( $vx1, $vx2, $vy1, $vy2, $wx1, $wx2, $wy1, $wy2);
546
547   # Get the character height in normalised device coordinates
548   pgqcs( 0, $chv, $chh );
549
550   # Get the bounds of the PGPLOT viewport in normalised device
551   # coordinates.
552   pgqvp( 0, $vx1, $vx2, $vy1, $vy2 );
553
554   # Get the bounds of the PGPLOT window in world coordinates.
555   pgqwin( $wx1, $wx2, $wy1, $wy2 );
556
557   # Convert the text height from normalised device coordinates into world
558   # coordinates for vertical text. Print an error message if the viewport
559   # has zero size.
560   if( $vx1 != $vx2 ){
561      $chv *= ( $wx2 - $wx1 )/( $vx2 - $vx1 );
562   } else {
563      ReportGrfError("_GQch: The graphics viewport has zero size in the X direction.");
564      return (0);
565   }
566
567   # Convert the text height from normalised device coordinates into world
568   # coordinates for horizontal text. Print an error message if the viewport
569   # has zero size.
570   if( $vy1 != $vy2 ){
571      $chh *= ( $wy2 - $wy1 )/( $vy2 - $vy1 );
572   } else {
573      ReportGrfError("_GQch: The graphics viewport has zero size in the Y direction.");
574      return (0);
575   }
576
577   # Return.
578   return ( 1, $chv, $chh );
579}
580
581
582=item B<_GAttr>
583
584This function returns the current value of a specified graphics
585attribute, and optionally establishes a new value. The supplied
586value is converted to an integer value if necessary before use.
587
588
589   my ( $status, $old_value ) = _GAttr( $attr, $value, $prim );
590
591Where $attr is an integer value identifying the required attribute.
592The following symbolic values are defined in the AST grf.h:
593
594           GRF__STYLE  - Line style.
595           GRF__WIDTH  - Line width.
596           GRF__SIZE   - Character and marker size scale factor.
597           GRF__FONT   - Character font.
598           GRF__COLOUR - Colour index.
599
600$value is a new value to store for the attribute. If this is
601AST__BAD no value is stored, and $old_value is a scalar containing
602the old attribute value, if this is NULL no value is returned.
603
604Finally $prim is the sort of graphics primitive to be drawn with
605the new attribute. Identified by the following values defined in
606AST's grf.h:
607
608           GRF__LINE
609           GRF__MARK
610           GRF__TEXT
611
612=cut
613
614sub _GAttr {
615   my $attr = shift;
616   my $value = shift;
617   my $prim = shift;
618
619   my ( $ival, $rval, $dx, $dy, $deflw, $x1, $x2, $y1, $y2 );
620   my $old_value = undef;
621
622   # If required retrieve the current line style, and set a new line style.
623   if( $attr == Starlink::AST::Grf::GRF__STYLE() ){
624      pgqls( $ival );
625      $old_value = $ival;
626
627      if( $value != Starlink::AST::AST__BAD() ){
628         $ival = int( $value + 0.5 );
629         $ival -= 1 if $value < 0.0;
630
631         $ival = ( $ival - 1 ) % 5;
632         $ival += ( $ival < 0 ) ? 6 : 1;
633
634         pgsls( $ival );
635      }
636
637   # If required retrieve the current line width, and set a new line width.
638   # Line width is stored in Plot as a scale factor (1.0 for the default line
639   # width which is a fixed fraction of the diagonal of the view surface), but
640   # pgplot stores it in units of 0.005 of an inch.
641   } elsif( $attr == Starlink::AST::Grf::GRF__WIDTH() ){
642
643      # Get the bounds of the view surface in inches.
644      pgqvsz( 1, $x1, $x2, $y1, $y2 );
645
646      # Find the default line width in inches (i.e. 0.0005 of the length
647      # of the view surface diagonal).
648      $dx = ( $x1 - $x2 );
649      $dy = ( $y1 - $y2 );
650      $deflw = 0.0005*sqrt( $dx*$dx + $dy*$dy );
651
652      # Get the current pgplot line width in units of 0.005 of an inch.
653      pgqlw( $ival );
654
655      # If required, return the factor by which this exceeds the default line
656      # width found above.
657      $old_value = $ival/( 200.0 * $deflw );
658
659      # If a new line width has been provided, the pgplot line width needs to
660      # be set to the corresponding absolute value.
661      if( $value != Starlink::AST::AST__BAD() ){
662         $ival = 200.0*$value*$deflw;
663         if( $ival < 1 ) {
664            $ival = 1;
665         } elsif( $ival > 201 ){
666            $ival = 201;
667         }
668         pgslw( $ival );
669      }
670
671   # If required retrieve the current character size, and set a new size.
672   # The attribute value should be a factor by which to multiply the
673   # default character size.
674   } elsif( $attr == Starlink::AST::Grf::GRF__SIZE() ){
675      pgqch( $rval );
676      $old_value = $rval;
677
678      if( $value != Starlink::AST::AST__BAD() ){
679         pgsch( $value );
680      }
681
682   # If required retrieve the current character font, and set a new font.
683   } elsif( $attr == Starlink::AST::Grf::GRF__FONT() ){
684      pgqcf( $ival );
685      $old_value = $ival;
686
687      if( $value != Starlink::AST::AST__BAD() ){
688         $ival = int( $value + 0.5 );
689         $ival -= 1 if $value < 0.0;
690
691         $ival = ( $ival - 1 ) % 4;
692         $ival += ( $ival < 0 ) ? 5 : 1;
693         pgscf( $ival );
694      }
695
696   # If required retrieve the current colour index, and set a new colour
697   # index.
698   } elsif( $attr == Starlink::AST::Grf::GRF__COLOUR() ){
699      pgqci( $ival );
700      $old_value = $ival;
701
702      if( $value != Starlink::AST::AST__BAD() ){
703         $ival = int( $value + 0.5 );
704         $ival = 1 if $ival < 0;
705         pgsci( $ival );
706      }
707
708   # Give an error message for any other attribute value.
709   } else {
710      ReportGrfError("_GAttr: Unknown graphics attribute $attr requested.");
711      return ( 0 );
712   }
713
714   # Return.
715   return ( 1, $old_value );
716
717}
718
719=item B<_GCap>
720
721This function is called by the AST Plot class to determine if the
722grf module has a given capability, as indicated by the "cap"
723argument.
724
725  $has_cap = _GCap( $cap, $value );
726
727The capability string should be one of the following constants
728provided in the Starlink::AST::Grf namespace:
729
730GRF__SCALES: This function should return a non-zero value if
731it implements the astGScales function, and zero otherwise. The
732supplied "value" argument should be ignored.
733
734GRF__MJUST: This function should return a non-zero value if
735the astGText and astGTxExt functions recognise "M" as a
736character in the justification string. If the first character of
737a justification string is "M", then the text should be justified
738with the given reference point at the bottom of the bounding box.
739This is different to "B" justification, which requests that the
740reference point be put on the baseline of the text, since some
741characters hang down below the baseline. If the astGText or
742astGTxExt function cannot differentiate between "M" and "B",
743then this function should return zero, in which case "M"
744justification will never be requested by Plot. The supplied
745"value" argument should be ignored.
746
747GRF__ESC: This function should return a non-zero value if the
748astGText and astGTxExt functions can recognise and interpret
749graphics escape sequences within the supplied string. These
750escape sequences are described below. Zero should be returned
751if escape sequences cannot be interpreted (in which case the
752Plot class will interpret them itself if needed). The supplied
753"value" argument should be ignored only if escape sequences cannot
754be interpreted by astGText and astGTxExt. Otherwise, "value"
755indicates whether astGText and astGTxExt should interpret escape
756sequences in subsequent calls. If "value" is non-zero then
757escape sequences should be interpreted by astGText and
758astGTxExt. Otherwise, they should be drawn as literal text.
759
760Zero should be returned if the supplied capability is not recognised.
761
762=cut
763
764sub _GCap {
765  my $cap = shift;
766  my $value = shift;
767
768  if ($cap == &Starlink::AST::Grf::GRF__SCALES) {
769    return 1;
770  }
771  return 0;
772}
773
774
775# Internal error setting routine
776sub ReportGrfError {
777  my $text = shift;
778  warn "Generated AST error in perl PGPLOT callback: $text\n";
779  Starlink::AST::_Error( &Starlink::AST::Status::AST__GRFER(), $text);
780}
781
782
783=back
784
785=head1 COPYRIGHT
786
787Copyright (C) 2004 Particle Physics and Astronomy Research Council.
788Copyright (C) 2004 University of Exeter. All Rights Reserved.
789
790This program is free software; you can redistribute it and/or modify
791it under the terms of the GNU Public License.
792
793This program is free software; you can redistribute it and/or modify it under
794the terms of the GNU General Public License as published by the Free Software
795Foundation; either version 2 of the License, or (at your option) any later
796version.
797
798This program is distributed in the hope that it will be useful,but WITHOUT ANY
799WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
800PARTICULAR PURPOSE. See the GNU General Public License for more details.
801
802You should have received a copy of the GNU General Public License along with
803this program; if not, write to the Free Software Foundation, Inc., 59 Temple
804Place,Suite 330, Boston, MA  02111-1307, USA
805
806=head1 AUTHORS
807
808Alasdair Allan E<lt>aa@astro.ex.ac.ukE<gt>,
809Tim Jenness E<lt>tjenness@jach.hawaii.eduE<gt>
810
811=cut
812
813package Starlink::AST::Plot;
814
815use strict;
816use vars qw/ $VERSION /;
817
818use Starlink::AST::PGPLOT;
819
820sub pgplot {
821  my $self = shift;
822
823  $self->GBBuf(\&Starlink::AST::PGPLOT::_GBBuf);
824  $self->GEBuf(\&Starlink::AST::PGPLOT::_GEBuf);
825  $self->GFlush(\&Starlink::AST::PGPLOT::_GFlush);
826  $self->GLine(\&Starlink::AST::PGPLOT::_GLine);
827  $self->GMark(\&Starlink::AST::PGPLOT::_GMark);
828  $self->GText(\&Starlink::AST::PGPLOT::_GText);
829  $self->GTxExt(\&Starlink::AST::PGPLOT::_GTxExt);
830  $self->GQch(\&Starlink::AST::PGPLOT::_GQch);
831  $self->GAttr(\&Starlink::AST::PGPLOT::_GAttr);
832  $self->GScales(\&Starlink::AST::PGPLOT::_GScales);
833  $self->GCap(\&Starlink::AST::PGPLOT::_GCap);
834
835  return 1;
836}
837
8381;
839