/  5
 
use strict;use warnings;use Image::Magick;my ($my_styles);$my_styles = {style1 => {font => "Arial",color => "#000000",size => "20"},style2 => {font => "Arial",color => "#00ff00",size => "25"}};#returns the image magick object after rendering the text, with given height andwidth.#it truncates the paragraph after reaching the height limit.#wraps the text, and also can support multiple styles in the same linesub draw_styled_text {my ($text, $height, $width, $default_style) = @_;my $im = Image::Magick->new();my $last_pos = 0;my ($x, $y) = (0, 0);my %lines;$im->Set(size => $width . "x" . $height);$im->Read('xc:none');#format#sentence%%$$style_name$$sentence%%sentence#for each styled sentencemy @sentences = split /\%\%/, $text;for my $sentence (@sentences) {my ($style_name, $style_details);$style_name = $default_style;if ($sentence =~ /\$\$(.*)\$\$([\w\W]*)/) {#get the style name,$style_name = $1;$sentence = $2;}#check length of the stringunless (length $sentence) {next;}#get the style details,$style_details = get_style_details($style_name);$im->Set(font => $style_details->{'font'},pointsize => $style_details->{'pointsize'});#wrap text
 
my ($new_text, $line_height);my $space_width = get_space_metrics($im);#annotate trims text. to avoid that check the no. of spaces in thebegining and in the end.#space in the begining of the stringif ($sentence =~ /^( +).*/) {$last_pos = $last_pos + ($space_width * length($1));$x = $last_pos;} ($new_text, $last_pos, $line_height) = Wrap($sentence, $im, $width,$last_pos);#space at the end of the string.if ($sentence =~ /.*( +)$/) {$last_pos = $last_pos + ($space_width * length($1));}#for each linefor my $line (split /\n/, $new_text) {$y = $line_height unless ($y);my $arr;if (defined $lines{$y}) {$arr = $lines{$y};} else {$arr = ();}#write the linepush @$arr, {x => $x,y => $y,text => $line,color => $style_details->{'color'},font => $style_details->{'font'},pointsize => $style_details->{'pointsize'},line_height => $line_height};$lines{$y} = $arr;$x = 0;$y = $y + $line_height;}$x = $last_pos;if ($new_text !~ /.*\n$/) {$y = $y - $line_height;} else {$x = $last_pos = 0;}}my $adjustment_y = 0;for my $y(sort {$a <=> $b} keys %lines) {my $arr = $lines{$y};my $max_height = 0;my $considered_height = 0;for my $line (@$arr) {
 
if ($max_height < $line->{'line_height'}) {$max_height = $line->{'line_height'};}unless ($considered_height) {$considered_height = $line->{'line_height'};}}if ($considered_height != $max_height) {$adjustment_y += $max_height - $considered_height;}$y += $adjustment_y;for my $line (@$arr) {$im->Annotate(font => $line->{'font'},fill => $line->{'color'},pointsize => $line->{'pointsize'},text => $line->{'text'},x => $line->{'x'},y => $y,);}}#returnreturn $im;}#im doesnt support spacesub get_space_metrics {my ($im) = @_;my $val = 0;#first get for amy $a_width = ($im->QueryFontMetrics(text => "a"))[4];my $a_with_space_width = ($im->QueryFontMetrics(text => "a a"))[4];$val = $a_with_space_width - (2 * $a_width);return $val;}sub Wrap {my ($text, $img, $maxwidth, $lastpos) = @_;my (@newtext, $pos);$pos = $lastpos || 0;my (@words, @lines, @char, $i, $word);@char = split //, $text;$i = 0;$word = "";for my $c (@char) {$i++;#get the wordif ($c eq " " || $c eq "-" || $c eq "\n") {push @words, $word;} else {$word = $word . $c;if ($i >= scalar @char) {push @words, $word;} else {next;}

Share & Embed

More from this user

Add a Comment

Characters: ...