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