GD-Text-Arc

 view release on metacpan or  search on metacpan

Arc.pm  view on Meta::CPAN

    #
    # 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 )