# -*- Perl -*-
# PostScript::Elements.pm
# An object for representing lines, circles, boxes, and images
# such that they can be easily output as PostScript code.
#
# You may distribute this under the same terms as Perl
# itself.
#
PostScript::Elements::VERSION = '0.06';
package PostScript::Elements;
use strict;
# @paramnames is the list of valid parameters,
# %defaults is the hash of default values for those parameters.
#
my @paramnames = qw( type points linewidth linetint filltint );
my %defaults = (
linewidth => 1, # 1 pt
filltint => -1, # -1 represents transparent
linetint => 0, # 0 == black, 1 = white
);
sub new {
# The constructor method.
# An Element object can be one or more lines, circles,
# boxes or images.
#
my $class = shift;
my $self = [];
bless($self,$class);
return $self;
}
sub addType {
# A general routine for adding lines, circle, box, or
# image objects to an Element.
#
my $self = shift;
my %params = @_;
# If a parameter is not specified, use the default...
#
foreach (@paramnames) {
$params{$_} = $defaults{$_} unless (defined($params{$_}));
};
# Add the object to the current element
#
push @$self, { type => $params{'type'},
points => $params{'points'},
linewidth => $params{'linewidth'},
filltint => $params{'filltint'},
linetint => $params{'linetint'},
};
}
sub addArc {
# Add an arc to the Element.
# A points parameter is required, consisting of a reference to
# list specifying the center coordinate, the radius
# of the arc, and two numbers specifying the starting angle
# and the ending angle describing the sweep of the arc. E.g.:
# addArc(points=>[50,50,25,0,360])
# would add a complete circle centered at 50,50 with a radius of 25.
#
my $self = shift;
$self->addType(type => 'arc',
@_);
}
sub addBox {
# Add a Box to the Element.
# The points parameter should consist of the upper left coordinate
# of the box, its width, and its height.
#
my $self = shift;
$self->addType(type => 'box',
@_);
}
sub addLine {
# Add a Line to the Element.
# The points parameter should contain the starting coordinate and
# the end coordinate.
#
my $self = shift;
$self->addType(type => 'line',
@_);
}
sub Write() {
# A method to create the PostScript code that will render the
# objects in the Element.
#
my $self = shift;
my $returnval = "";
my ($width, $height);
foreach my $element (@$self) {
# Generate the appropriate PostScript based on the
# type attribute.
# Arc:
if ($element->{type} =~ /arc/i) {
# First save the current path (if any),
# then create the path of the arc
#
$returnval .= "gsave\n".
$element->{'points'}->[0]." ". # x value
$element->{'points'}->[1]." ". # y value
$element->{'points'}->[2]." ". # radius
$element->{'points'}->[3]." ". # start angle
$element->{'points'}->[4]." ". # end angle
"arc\n";
# Don't fill the arc if filltint attribute is -1
# otherwise fill the current path with the tint specified by
# the filltint attribute. Save the path so it can be restored
# after the fill and it can be used by the stroke function.
#
if ($element->{'filltint'} >= 0 ) {
$returnval .= $element->{'filltint'}." setgray\n".
"gsave \nfill \ngrestore\n";
}
# Stroke the arc with the width indicated by linewidth
# and a greyscale percentage specified by linetint
#
$returnval .= $element->{'linetint'}." setgray\n".
$element->{'linewidth'}." setlinewidth\n".
"stroke\n".
"1 setgray\n".
$defaults{'linewidth'}." setlinewidth\n".
"grestore\n";
# Box:
#
} elsif ($element->{type} =~ /box/i) {
# A box is described by the upper left corner, a width
# and a height
#
$width = $element->{'points'}->[2];
$height = $element->{'points'}->[3];
$returnval .= "gsave\n";
$returnval .= $element->{'points'}->[0]." ". # x value
$element->{'points'}->[1]." ". # y value
"moveto\n".
# now draw it clockwise...
#
"$width 0 rlineto\n".
"0 ".(0-$height)." rlineto\n".
(0-$width)." 0 rlineto\n".
"0 $height rlineto\n".
"closepath\n";
# Don't fill the box if filltint attribute is -1
#
if ($element->{'filltint'} >= 0 ) {
$returnval .= $element->{'filltint'}." setgray\n".
"gsave \nfill \ngrestore\n";
}
$returnval .= $element->{'linetint'}." setgray\n".
$element->{'linewidth'}." setlinewidth\n".
"stroke\n".
"1 setgray\n".
$defaults{'linewidth'}." setlinewidth\n".
"grestore\n";
# Line:
#
} elsif ($element->{type} =~ /line/i) {
$returnval .= "gsave\n";
$returnval .= $element->{'points'}->[0]." ". # start x
$element->{'points'}->[1]." ". # start y
"moveto\n".
$element->{'points'}->[2]." ". # end x
$element->{'points'}->[3]." ". # end y
"lineto\n".
$element->{'linetint'}." setgray\n".
$element->{'linewidth'}." setlinewidth\n".
"stroke\n".
"1 setgray\n".
$defaults{'linewidth'}." setlinewidth\n".
"grestore\n";
} else {
# Do nothing
}
}
return ($returnval);
}
1;
__END__
=head1 NAME
PostScript::Elements - Generate PostScript code for circles, boxes, lines
=head1 DESCRIPTION
An object for representing lines, circles, boxes, and images
such that they can be easily output as PostScript code.
=head1 SYNOPSIS
=head1 AUTHOR
=cut