Devel-WxProf

 view release on metacpan or  search on metacpan

lib/Devel/WxProf/Treemap/Output/Imager.pm  view on Meta::CPAN

    #my $top_pad = int(( $height - $metrix[5] ) * 0.1 );
    #$top_pad = ( $top_pad > 5 ) ? 5 : $top_pad;
    #$y = $y1 + $metrix[5] + $top_pad;

    $self->{IMAGE}->string(
                           font  => $self->{FONT},
                           text  => $text,
                           x     => $x1 + 1,
                           y     => $y1 + $size,
                           color => $self->{SOLID_FONT},
                           size  => $size,
                           );
   return 1;
}

## font fitting algorhythm
# moved to seperate function, merged with guessing function
sub _font_fit {
   my $self = shift;
   my ( $width, $height, $text ) = @_;
   my $DEBUG = $self->{TEXT_DEBUG};

   return unless $text && ( length( $text ) ) && $height && $width;

   my $local_iters = 0;

   # Search for suitable font size
   $self->{TEXT_DEBUG} && print STDERR "$text:\n";

   # fetch a guess at the starting point:
   # if not initialized:
   unless ( $self->{ACWPP} )
   {
      # find average character width per point
      $self->{ACWPP} = $self->_calc_avg_char_weight_per_pt();
      croak( "Initialization of font fitting algorhythm failed." )
         unless ( $self->{ACWPP} );
   }

   my $size = int( ( $width / length( $text ) ) / $self->{ACWPP} );

   # because it is guaranteed to be not worth it:
   return if ( $size <= ( $self->{MIN_FONT_SIZE} - 2 ) );
   return $self->{ MAX_FONT_SIZE } if $size > $self->{ MAX_FONT_SIZE };

   # test guess:
   my @metrix = $self->{FONT}->bounding_box(
                                       string => $text,
                                       size   => $size,
                                       canon  => 1       );

   # two corrective measures:

   # 1. if the width fits, but not the height, then we have a height
   # restricted case.  These tend to be expensive, so we "correct" our
   # guess.
   if (( $metrix[2] <= $width ) && ( $metrix[3] > $height )) {
      # if there is a major difference in height, correct guess
      if (( abs( $height - $metrix[3] ) / $height ) * $size >= 3 )
      {
         $self->{font_iters}++; $local_iters++;  # track iterations

         $self->{TEXT_DEBUG} && print STDERR "\tHeight restricted, changing $size =>";
         $size = int( $size * ( $height / $metrix[3] ));
         $self->{TEXT_DEBUG} && print STDERR "$size.\n";

         @metrix = $self->{FONT}->bounding_box(
                                       string => $text,
                                       size   => $size,
                                       canon  => 1       );
      }
   }
   # 2. if our guess is way off width-wise, correct:
   #    if a correction would yeild a size change of more than 3,
   #    it is obviously worth it.
   elsif ( ( abs( $width - $metrix[2] ) / $width ) * $size >= 3 )
   {
      $self->{font_iters}++; $local_iters++;  # track iterations
      $self->{TEXT_DEBUG} && print STDERR "\tOff by 3pts+, changing $size =>";
      $size = int( $size * ( $width / $metrix[2] ));
      $self->{TEXT_DEBUG} && print STDERR "$size.\n";
      @metrix = $self->{FONT}->bounding_box(
                                    string => $text,
                                    size   => $size,
                                    canon  => 1       );
   }

   # if our guess was too large, try smaller values until there is a fit:
   if (( $metrix[2] > $width ) || ( $metrix[3] > $height )) {
      $self->{TEXT_DEBUG} && print STDERR "\tGuess ($size) too large.\n";
      while ( ( $metrix[2] > $width ) || ( $metrix[3] > $height ) )
      {
         $self->{font_iters}++; $local_iters++;  # track iterations
         $size--;

         return if ( $size < 5 );

         @metrix = $self->{FONT}->bounding_box(
                                          string => $text,
                                          size   => $size,
                                          canon  => 1    );
      }
   }
   # if our guess is too small, try larger values until there is a -no- fit:
   elsif ( ( $metrix[2] <= $width ) && ( $metrix[3] <= $height )) {
      $self->{TEXT_DEBUG} && print STDERR "\tGuess ($size) fits, adjusting.\n";
      while ( ( $metrix[2] <= $width ) && ( $metrix[3] <= $height ) )
      {
         $self->{font_iters}++; $local_iters++;  # track iterations

         $size++;
         $size++ if ( $size > 50 );  # grow a bit faster for big fonts

         @metrix = $self->{FONT}->bounding_box(
                                          string => $text,
                                          size   => $size,
                                          canon  => 1    );
      }
      $size--;  # because this overshoots
   }

   $self->{TEXT_DEBUG} && print STDERR "\t$local_iters :: " . $self->{font_iters} . " => $size\n";

   $size = int( $size * 0.9 );  # reduce size to fit comfortably

   return if ( $size < $self->{MIN_FONT_SIZE} );

   return $size;
}

###############################################
#
# private: _calc_avg_char_weight_per_pt
# input:  none
# output: ACWPP
#
#   pardon the size of this function name
#   it only needs to be called in one place
#
sub _calc_avg_char_weight_per_pt {
   my $self = shift;
   my $wieghting_string = "rstlnaei0RST.-";
   my $sample_size = 50;

   # get metrix for sample:
   my @metrix = $self->{FONT}->bounding_box(
                                    string => $wieghting_string,
                                    size   => $sample_size,
                                    canon  => 1         );

   my $sample_width = $metrix[2];
   return unless ( $sample_width );

   # avg    width           per character                 per point
   return ( $sample_width / length( $wieghting_string ) / $sample_size );
}


sub width {
   my $self = shift;
   return $self->{WIDTH};
}

sub height {
   my $self = shift;
   return $self->{HEIGHT};
}

sub font_height {



( run in 3.599 seconds using v1.01-cache-2.11-cpan-800906f7e73 )