package textlib;

use Font::FreeType;
use Image::Magick;

my %fonts;
$fonts{'MAGIC'}{'FILE'} = "/usr/local/swami/MAGIC.TTF";
#$fonts{'MAGIC'}{'FILE'} = "/usr/local/swami/magmed.ttf";
$fonts{'MAGIC'}{''} = "MAGIC";
$fonts{'MAGIC'}{'I'} = "MAGIC";
$fonts{'MAGIC'}{'B'} = "MAGIC";
$fonts{'MAGIC'}{'BI'} = "MAGIC";
$fonts{'Times-Roman'}{'FILE'} = "/usr/share/fonts/urw-fonts/n021003l.pfb";
$fonts{'Times-Roman'}{''} = "Times-Roman";
$fonts{'Times-Roman'}{'I'} = "Times-Italic";
$fonts{'Times-Roman'}{'B'} = "Times-Bold";
$fonts{'Times-Roman'}{'BI'} = "Times-BoldItalic";
$fonts{'Times-Italic'}{'FILE'} = "/usr/share/fonts/urw-fonts/n021023l.pfb";
$fonts{'Times-Italic'}{''} = "Times-Italic";
$fonts{'Times-Italic'}{'I'} = "Times-Roman";
$fonts{'Times-Italic'}{'B'} = "Times-BoldItalic";
$fonts{'Times-Italic'}{'BI'} = "Times-Bold";
$fonts{'Times-Bold'}{'FILE'} = "/usr/share/fonts/urw-fonts/n021004l.pfb";
$fonts{'Times-Bold'}{''} = "Times-Bold";
$fonts{'Times-Bold'}{'I'} = "Times-BoldItalic";
$fonts{'Times-Bold'}{'B'} = "Times-Roman";
$fonts{'Times-Bold'}{'BI'} = "Times-Italic";
$fonts{'Times-BoldItalic'}{'FILE'} = "/usr/share/fonts/urw-fonts/n021024l.pfb";
$fonts{'Times-BoldItalic'}{''} = "Times-Italic";
$fonts{'Times-BoldItalic'}{'I'} = "Times-Bold";
$fonts{'Times-BoldItalic'}{'B'} = "Times-Italic";
$fonts{'Times-BoldItalic'}{'BI'} = "Times-Roman";
$fonts{'Chancery'}{'FILE'} = "/usr/share/fonts/default/ghostscript/z003034l.pfb";
$fonts{'Chancery'}{''} = "Chancery";
$fonts{'Chancery'}{'I'} = "Chancery";
$fonts{'Chancery'}{'B'} = "Chancery";
$fonts{'Chancery'}{'BI'} = "Chancery";

sub rendertext
{ # &rendertext(image, string, font, size, color, dpi, positioning, x, y, boxwidth, alignment)
  my $image = $_[1];
  my $string = $_[2];
  $string =~ s/\r//gms;
  $string =~ s/ +\n/\n/gms;
  my $color = $_[5];
  my $positioning = uc($_[7]);
  my $originx = $_[8];
  my $originy = $_[9];
  my $boxwidth = $_[10];
  my $alignment = $_[11];
  my %font;

  $font{'FACE'} = $_[3];
  $font{'SIZE'} = $_[4];
  $font{'DPI'} = $_[6];

  my $xoffset;
  my $yoffset;
  my $x = 0;
  my $y = 0;
  my $finalstring;

  my $face = &getface(\%font, $string);

  while($string =~ /^([\n]|[\[\{ ]*[^\]\[\}\{ \n]+[\]\}]*)/sm)
  {
    my %font = %font;
    my $face = $face;
    my $line = $1;
    $string = substr($string, length($line));
    if($line eq "\n")
    {
      $x = 0;
      $y += $face->height();
      $finalstring .= "\n";
      next;
    }

    my $width = &strwidth($line, \%font);
    if(($width + $x <= $boxwidth) || $x == 0)
    {
      $finalstring .= $line;
      $x += $width;
    }
    else
    {
      $line =~ s/^ *//g;
      $width = &strwidth($line, \%font);
      $finalstring .= "\n$line";
      $x = $width;
      $y += $face->height();
    }
  }

  $finalstring .= $string;

  $x = 0;
  $y = 0;
  my $lastglyph;
  my $glyph = $face->glyph_from_char("L");
  
  (my $tmp, $tmp, my $leading) = $glyph->bitmap_magick;
  $leading -= $face->descender;

  if($positioning eq "ABS")
  {
    $originy += $leading;
    $originx += $glyph->horizontal_advance();
  }

  if($alignment =~ /BOTTOM/)
  {
    my $height = &strheight($finalstring, \%font);
    $yoffset = -$height;
  }

  my $lenfinal = length($finalstring);
  for(my $count = 0;$count < $lenfinal;$count++)
  {
    my $char = substr($finalstring, 0, 1);
    $finalstring = substr($finalstring, 1);

    ### Bug fix.  With ImageMagick 6.3.0.5, repeated fetches of the same glyph get corrupted.
    my $glyph = $face->glyph_from_char_code(ord("^"));
    $glyph->bitmap_magick;
    ### end bug fix

    $glyph = $face->glyph_from_char_code(ord($char)); 

    if(($alignment =~ /RIGHT/) && ($x == 0))
    {
      my $string = $char.$finalstring;
      $string =~ s/\n.*//g;
      my $length = &strwidth($string, \%font);
      $xoffset = -$length;
    }

    if($char eq "[")
    {
      my $symbol;
      if($finalstring =~ /^([^\]]*)\]/)
      {
	$symbol = $1;
      }
      $finalstring = substr($finalstring, length($symbol) + 1);
      $count += length($symbol) + 1;
      my $symimg = Image::Magick->new;
      $symimg->Read($symbol);
      my $symw = $symimg->Get("width");
      my $symh = $symimg->Get("height");
      my $symratio;
      if($symh && $symw){ $symratio = $symw / $symh;}
      #$symh = $leading + ($face->descender * .75);
      $symh = $face->ascender;
      $symw = $symratio * $symh;
      $symimg->Scale(width=>$symw, height=>$symh);
      
      $image->Composite(geometry=>"+".($originx + $x + $xoffset).
				 #"+".($originy + $y + $yoffset - $symh - ($face->descender / 4)),
				 "+".($originy + $y + $yoffset - $symh - ($face->descender / 2)),
			compose=>"over",
			image=>$symimg);
      $x += $symw;
    }

    elsif($char eq "{")
    {
      my $attrib;
      my $value;
      if($finalstring =~ /^([^\}]*)\}/)
      {
	$attrib = uc($1);
      }
      $finalstring = substr($finalstring, length($attrib) + 1);
      $count += length($attrib) + 1;
      if($attrib =~ /^[\/](.+)/)
      {
	$attrib = $1;
	delete $font{$attrib};
      }
      else
      {
	$value = $attrib;
	if($attrib =~ /([^=]+)=(.*)/)
	{
	  $attrib = $1;
	  $value = $2;
	}
	$font{$attrib} = $value;
      }

      $face = &getface(\%font);
      (my $tmp, $tmp, $leading) = $face->glyph_from_char("L")->bitmap_magick;
      $leading -= $face->descender;

    }
      
    elsif($char eq "\n")
    {
      $y += $leading;
      $x = 0;
    }
    elsif($char eq " ")
    {
      $x += $glyph->horizontal_advance();
    }
    else
    {
      my $kern = 0;
      my $xadj = 0;
      my $yadj = 0;
      if($lastglyph) { $kern = $face->kerning($lastglyph->index, $glyph->index); }
      $lastglyph = $glyph;
      my $glimg;
#n      ($glimg, my $left, my $top) = $face->glyph_from_char("1")->bitmap_magick;
#n      ($glimg, my $left, my $top) = $face->glyph_from_char("2")->bitmap_magick;
#      $glyph = $face->glyph_from_char_code(ord($char));
      ($glimg, my $left, my $top) = $glyph->bitmap_magick;
      my $matte = 0;
      my $flatcolor = $color;
      if($color =~ /rgba.(.+), *(.+), *(.+), *([0-9]+)/)
      {
	$matte = $4 * 256;
	$flatcolor = "rgb($1, $2, $3)";
      }
      $glimg->Level(gamma=>"1.5");
      my $mask = $glimg->Clone;
      if($font{'STROKE'})
      {
        #Increase the size of our images
	$glimg->Border(width=>6, height=>6, fill=>"rgb(ffff,ffff,ffff)");
	$mask->Border(width=>6, height=>6, fill=>"rgb(ffff,ffff,ffff)");
        #Increase the size of the glyphmask
	$mask->Blur(radius=>3,sigma=>8);
	#Bring it back up to full opacity
	$mask->Threshold(threshold=>"10%");
	#Soften the edges again
	$mask->Blur(radius=>1,sigma=>8);
	$xadj -= 6;
	$yadj -= 6;
	$glimg->Colorize(fill=>"rgb(ffff,ffff,ffff)", opacity=>100);
	$glimg->Negate();
      }
      else
      {
        $glimg->Colorize(fill=>$flatcolor, opacity=>100);
      }
#      $glimg->ColorFloodfill(fill=>$flatcolor, fuzz=>999999, x=>2, y=>2);
#      $glimg->MatteFloodfill(matte=>$matte, fuzz=>999999, x=>2, y=>2);
      $mask->Colorize(fill=>"rgb(0,0,0)", opacity=>$matte/655.36);
      $glimg->Composite(image=>$mask, compose=>'CopyOpacity');
      $image->Composite(geometry=>"+".($originx + $x + $xoffset + $left + $xadj).
				 "+".($originy + $y + $yoffset - $top + $yadj),
			compose=>"over",
			image=>$glimg);
      $x += $glyph->horizontal_advance() + $kern;
    }
  }
  
  return 1;
}

sub getWidth
{
  my $string = $_[1];
  $string =~ s/\r//g;
  my $boxwidth = $_[2];
  my %font;

  $font{'FACE'} = $_[3];
  $font{'SIZE'} = $_[4];
  $font{'DPI'} = $_[5];

  my $face = &getface(\%font, $string);
  return &strwidth($string, \%font);
}

sub getHeight
{
  my $string = $_[1];
  $string =~ s/\r//g;
  my $boxwidth = $_[2];
  my %font;

  $font{'FACE'} = $_[3];
  $font{'SIZE'} = $_[4];
  $font{'DPI'} = $_[5];

  my $face = &getface(\%font, $string);
  return &strheight($string, \%font);
}

sub getSize
{
  my $string = $_[1];
  $string =~ s/\r//g;
  my $boxwidth = $_[2];
  my %font;

  $font{'FACE'} = $_[3];
  $font{'SIZE'} = $_[4];
  $font{'DPI'} = $_[5];

  my $face = &getface(\%font, $string);
  return &strsize($string, \%font);
}

sub getface
{ # $face = getface(\%font, [string]);
  my %font = %{$_[0]};
  my $string = $_[1];
  my $freetype = Font::FreeType->new;
  my $face = $freetype->face(
	$fonts
	{
	  $fonts
	  {
	    $font{'FACE'}
	  }
	  {
	    $font{'B'}.
	    $font{'I'}
	  }
	}
	{'FILE'}) or die "$! font '$font{'FACE'}' for '$string' is most likely unknown";
  $face->set_char_size($font{'SIZE'}, $font{'SIZE'}, $font{'DPI'}, $font{'DPI'});
  return $face;
}

sub strwidth
{ # $width = &strwidth($line, %font);

  (my $width, my $height) = &strsize($_[0], $_[1]);
  return $width;
}

sub strheight
{ # $height = &strheight($line, %font);
  (my $width, my $height) = &strsize($_[0], $_[1]);
  return $height;
}

sub strsize
{ # ($width, $height) = &strsize($line, %font);
  my $line = $_[0];
  my %font = %{$_[1]};
  my $width = 0;
  my $height = 0;
  my $size = 0;
  my $last_glyph;
  my $length;

  my $face = &getface(\%font);

  (my $tmp, $tmp, my $leading) = $face->glyph_from_char("L")->bitmap_magick;
  $leading -= $face->descender;

  my $linelen = length($line);
  for(my $count = 0;$count < $linelen;$count++)
  {
    my $char = substr($line, 0, 1);
    $line = substr($line, 1);

    if($char eq "[")
    {
      my $symbol;
      if($line =~ /^([^\]]*)\]/)
      {
	$symbol = $1;
      }
      $line = substr($line, length($symbol) + 1);
      $count += length($symbol) + 1;
      my $symimg = Image::Magick->new;
      $symimg->Read($symbol);
      my $symw = $symimg->Get("width");
      my $symh = $symimg->Get("height");
      my $symratio;
      if($symw && $symh){ $symratio = $symw / $symh;}
      #$symh = $leading + ($face->descender * .75);
      $symh = $face->ascender;
      $symw = $symratio * $symh;
      $width += $symw;
    }

    elsif($char eq "{")
    {
      my $attrib;
      if($line =~ /^([^\}]+)\}/)
      {
	$attrib = uc($1);
      }
      $line = substr($line, length($attrib) + 1);
      $count += length($attrib) + 1;
      if($attrib =~ /^[\/](.+)/)
      {
	$attrib = $1;
	delete $font{$attrib};
      }
      else
      {
	$value = $attrib;
	if($attrib =~ /([^=]+)=(.*)/)
	{
	  $attrib = $1;
	  $value = $2;
	}
	$font{$attrib} = $value;
      }

      $face = &getface(\%font);
      (my $tmp, $tmp, $leading) = $face->glyph_from_char("L")->bitmap_magick;
      $leading -= $face->descender;

    }

    elsif($char eq "\n")
    {
      if($width > $length)
      {
        $length = $width;
      }
      $width = 0;
      $height += $leading;
    }
    else
    {
      my $kern = 0;
      my $glyph = $face->glyph_from_char_code(ord($char));
      if($lastglyph) { $kern = $face->kerning($lastglyph->index, $glyph->index); }
      $lastglyph = $glyph;
      $width += $glyph->horizontal_advance() + $kern;
    }
  }

  if($width > $length)
  { return ($width, $height); }
  else
  { return ($length, $height); }
}

1;
