GD-Text-Arc
view release on metacpan or search on metacpan
#
# theta seemed simpler to adjust.
#
# thetaL = thetaN - (1/2 radWidth * orientation)
#
# where:
# angles are measured from 12-o'clock, positive
# increasing clockwise.
#
# thetaN = the angle of the letter to calculate its position.
# thetaL = the angle to draw the letter at.
# radWidth = letter width in radians
# orientation = -1 for counterclockwise, +1 for clockwise
#######################################################################
# calculate start angle for positioning (x,y) with thetaN
my $thetaN = 0;
foreach my $n (@widths) {
$thetaN += ($n * $orientation);
}
$thetaN /= 2; # 1/2 width, in pixels
$thetaN /= $r; # ..in radians,
$thetaN /= $compressFactor; # ..with compression factor
$thetaN += PI if ($orientation < 0);
# draw each letter
foreach my $n (0..$#letters) {
my $radWidth = ($widths[$n]) / ($r * $compressFactor);
my $thetaL = $thetaN - ($radWidth/2 * $orientation) ;
$thetaL = $thetaL - PI if ($orientation < 0);
my $xN = $centerX - $r * sin($thetaN);
my $yN = $centerY - $r * cos($thetaN);
$self->{gd}->stringFT($colour, $font, $fontsize, $thetaL,
$xN, $yN, $letters[$n]) || return 0;
$thetaN -= ($radWidth * $orientation);
}
return 1;
}
#
# get_widths - in array context, return a list of character-widths in pixels.
# in scalar context, return a total width of the string.
sub get_widths {
my $self = shift;
my @widths;
my $total;
my @letters = split //, $self->get('text');
#######################################################################
# for character x, width(x) is not useful because .ttf fonts
# account for kerning. width(x1) + width(x2) + width(x3)
# is categorically different from width(x1.x2.x3).
#
# By process of elimination: an OK formula to find width(x2):
# assume x1 is a space, and perform:
# width(x1.x2.x3) - (width(x1) + width(x3)).
#
# If x2 is a space, make it wider; if it is (A|C|V) make it narrower.
#
# Whew. This should probably be simplified.
#######################################################################
foreach my $n (0..$#letters) {
my $nextLetter = $letters[$n+1] || " ";
my $lastLetter = " ";
my $thiswidth = ($self->width($lastLetter.$letters[$n].$nextLetter)
-
($self->width($lastLetter) +
$self->width($nextLetter)));
$thiswidth -=2 if ($letters[$n] =~ /[AVC]/);
$thiswidth +=2 if ($letters[$n] =~ / /);
push @widths, $thiswidth;
$total += $thiswidth;
}
return (wantarray ? @widths : $total);
}
#
# get_height - return the best guess for the height of the letters in pixels.
sub get_height {
my $self = shift;
return $self->get('ptsize') * $self->get('points_to_pixels_factor');
}
sub _min {
return ($_[0] < $_[1] ? $_[0] : $_[1]);
}
=head1 NAME
GD::Text::Arc - draw TrueType text along an arc.
=head1 SYNOPSIS
use GD::Text::Arc;
my $image = GD::Image->new(600,500);
my $gray = $image->colorAllocate(75,75,75);
my $boldfont = "Adventure.ttf";
my $text = "here's a line.";
my $ta = GD::Text::Arc->new($image,
colour => $gray,
ptsize => $size,
font => $boldfont,
radius => $radius,
center_x => $centerX,
center_y => $centerY,
( run in 0.783 second using v1.01-cache-2.11-cpan-39bf76dae61 )