provide better control over AA, and improve error handling
authorTony Cook <tony@develop-help.com>
Sun, 9 Sep 2012 04:21:58 +0000 (14:21 +1000)
committerTony Cook <tony@develop-help.com>
Sat, 24 Nov 2012 03:59:26 +0000 (14:59 +1100)
T1/T1.pm
T1/imt1.c
T1/t/t10type1.t

index 2b32148..edb0b58 100644 (file)
--- a/T1/T1.pm
+++ b/T1/T1.pm
@@ -15,10 +15,7 @@ BEGIN {
 
 *_first = \&Imager::Font::_first;
 
-my $t1aa;
-
-# $T1AA is in there because for some reason (probably cache related) antialiasing
-# is a system wide setting in t1 lib.
+my $t1aa = 2;
 
 sub new {
   my $class = shift;
@@ -71,6 +68,7 @@ sub new {
                type  => 't1',
                size  => $hsh{size},
                color => $hsh{color},
+               t1aa  => $t1aa,
               }, $class;
 }
 
@@ -85,16 +83,19 @@ sub _draw {
   $flags .= 'u' if $input{underline};
   $flags .= 's' if $input{strikethrough};
   $flags .= 'o' if $input{overline};
+  my $aa = $input{aa} ? $self->{t1aa} : 0;
   if (exists $input{channel}) {
     $self->{t1font}->cp($input{image}{IMG}, $input{'x'}, $input{'y'},
                    $input{channel}, $input{size},
                    $input{string}, length($input{string}), $input{align},
-                    $input{utf8}, $flags, $input{aa});
+                    $input{utf8}, $flags, $aa)
+      or return;
   } else {
     $self->{t1font}->text($input{image}{IMG}, $input{'x'}, $input{'y'}, 
                      $input{color}, $input{size}, 
                      $input{string}, length($input{string}), 
-                     $input{align}, $input{utf8}, $flags, $input{aa});
+                     $input{align}, $input{utf8}, $flags, $aa)
+      or return;
   }
 
   return $self;
@@ -157,6 +158,27 @@ sub glyph_names {
   return $self->{t1font}->glyph_name($string, $utf8);
 }
 
+sub set_aa_level {
+  my ($self, $new_t1aa) = @_;
+
+  if (!defined $new_t1aa ||
+      ($new_t1aa != 1 && $new_t1aa != 2)) {
+    Imager->_set_error("set_aa_level: parameter must be 1 or 2");
+    return;
+  }
+
+  if (ref $self) {
+    $self->_valid
+      or return;
+
+    $self->{t1aa} = $new_t1aa;
+  }
+  else {
+    $t1aa = $new_t1aa;
+  }
+
+  return 1;
+}
 
 sub _valid {
   my $self = shift;
@@ -218,6 +240,32 @@ C<strikethrough> - Draw the text with a strikethrough.
 Obviously, if you're calculating the bounding box the size of the line
 is included in the box, and the line isn't drawn :)
 
+=head2 Anti-aliasing
+
+T1Lib supports multiple levels of anti-aliasing, by default, if you
+request anti-aliased output, Imager::Font::T1 will use the maximum
+level.
+
+You can override this with the set_t1_aa() method:
+
+=over
+
+=item set_aa_level()
+
+Usage:
+
+  $font->set_aa_level(1);
+  Imager::Font::T1->set_aa_level(2);
+
+Sets the T1Lib anti-aliasing level either for the specified font, or
+for new font objects.
+
+The only parameter must be 1 or 2.
+
+Returns true on success.
+
+=back
+
 =head1 AUTHOR
 
 Addi, Tony
index 05a0b19..d0686bb 100644 (file)
--- a/T1/imt1.c
+++ b/T1/imt1.c
@@ -56,7 +56,8 @@ i_init_t1(int t1log) {
 static undef_int
 i_init_t1_low(int t1log) {
   int init_flags = IGNORE_CONFIGFILE|IGNORE_FONTDATABASE;
-  mm_log((1,"init_t1()\n"));
+
+  mm_log((1,"init_t1(%d)\n", t1log));
 
   i_clear_error();
 
@@ -79,7 +80,6 @@ i_init_t1_low(int t1log) {
     return(1);
   }
   T1_SetLogLevel(T1LOG_DEBUG);
-  i_t1_set_aa(1); /* Default Antialias value */
 
   ++t1_initialized;
 
@@ -155,13 +155,13 @@ i_t1_new(char *pfb,char *afm) {
 
   ++t1_active_fonts;
 
-  mm_log((1, "i_t1_new() -> %d\n", font_id));
-
   i_mutex_unlock(mutex);
 
   font = mymalloc(sizeof(*font));
   font->font_id = font_id;
 
+  mm_log((1, "i_t1_new() -> %p (%d)\n", font, font_id));
+
   return font;
 }
 
@@ -181,7 +181,7 @@ i_t1_destroy(i_t1_font_t font) {
 
   i_mutex_lock(mutex);
 
-  mm_log((1,"i_t1_destroy(font_id %d)\n",font->font_id));
+  mm_log((1,"i_t1_destroy(font %p (%d))\n", font, font->font_id));
 
   --t1_active_fonts;
 
@@ -253,7 +253,7 @@ Interface to text rendering into a single channel in an image
    str     - string to render
    len     - string length
    align   - (0 - top of font glyph | 1 - baseline )
-   aa      - anti-aliasing
+   aa      - anti-aliasing level
 
 =cut
 */
@@ -268,7 +268,16 @@ i_t1_cp(i_t1_font_t font, i_img *im,i_img_dim xb,i_img_dim yb,int channel,double
 
   unsigned int ch_mask_store;
   
-  if (im == NULL) { mm_log((1,"i_t1_cp: Null image in input\n")); return(0); }
+  i_clear_error();
+
+  mm_log((1, "i_t1_cp(font %p (%d), im %p, (xb,yb)=" i_DFp ", channel %d, points %g, str %p, len %u, align %d, utf8 %d, flags '%s', aa %d)\n",
+         font, fontnum, im, i_DFcp(xb, yb), channel, points, str, (unsigned)len, align, utf8, flags, aa));
+
+  if (im == NULL) {
+    mm_log((1,"i_t1_cp: Null image in input\n"));
+    i_push_error(0, "null image");
+    return(0);
+  }
 
   i_mutex_lock(mutex);
 
@@ -284,6 +293,8 @@ i_t1_cp(i_t1_font_t font, i_img *im,i_img_dim xb,i_img_dim yb,int channel,double
     glyph=T1_AASetString( fontnum, str, len, 0, mod_flags, points, NULL);
   }
   if (glyph == NULL) {
+    t1_push_error();
+    i_push_error(0, "i_t1_cp: T1_AASetString failed");
     i_mutex_unlock(mutex);
     return 0;
   }
@@ -355,7 +366,7 @@ i_t1_bbox(i_t1_font_t font, double points,const char *str,size_t len, i_img_dim
 
   space_position = T1_GetEncodingIndex(fontnum, "space");
   
-  mm_log((1,"i_t1_bbox(fontnum %d,points %.2f,str '%.*s', len %d)\n",fontnum,points,len,str,len));
+  mm_log((1,"i_t1_bbox(font %p (%d),points %.2f,str '%.*s', len %d)\n",font, fontnum,points,len,str,len));
   T1_LoadFont(fontnum);  /* FIXME: Here a return code is ignored - haw haw haw */ 
 
   if (len == 0) {
@@ -436,7 +447,16 @@ i_t1_text(i_t1_font_t font, i_img *im, i_img_dim xb, i_img_dim yb,const i_color
   i_render *r;
   int fontnum = font->font_id;
 
-  if (im == NULL) { mm_log((1,"i_t1_cp: Null image in input\n")); return(0); }
+  mm_log((1, "i_t1_text(font %p (%d), im %p, (xb,yb)=" i_DFp ", cl (%d,%d,%d,%d), points %g, str %p, len %u, align %d, utf8 %d, flags '%s', aa %d)\n",
+         font, fontnum, im, i_DFcp(xb, yb), cl->rgba.r, cl->rgba.g, cl->rgba.b, cl->rgba.a, points, str, (unsigned)len, align, utf8, flags, aa));
+
+  i_clear_error();
+
+  if (im == NULL) {
+    i_push_error(0, "null image");
+    mm_log((1,"i_t1_text: Null image in input\n"));
+    return(0);
+  }
 
   i_mutex_lock(mutex);
 
@@ -453,6 +473,9 @@ i_t1_text(i_t1_font_t font, i_img *im, i_img_dim xb, i_img_dim yb,const i_color
     glyph=T1_AASetString( fontnum, (char *)str, len, 0, mod_flags, points, NULL);
   }
   if (glyph == NULL) {
+    mm_log((1, "T1_AASetString failed\n"));
+    t1_push_error();
+    i_push_error(0, "i_t1_text(): T1_AASetString failed");
     i_mutex_unlock(mutex);
     return 0;
   }
index dc2edb4..8d9be3b 100644 (file)
@@ -2,13 +2,13 @@
 use strict;
 use Test::More;
 use Imager ':all';
-use Imager::Test qw(diff_text_with_nul is_color3);
+use Imager::Test qw(diff_text_with_nul is_color3 is_image isnt_image);
 use Imager::Font::T1;
 use Cwd qw(getcwd abs_path);
 
 #$Imager::DEBUG=1;
 
-plan tests => 96;
+plan tests => 108;
 
 ok($Imager::formats{t1}, "must have t1");
 
@@ -361,6 +361,40 @@ SKIP:
     ok($font, "found font by drive relative path")
       or print "# path $drive_path\n";
   }
+
+  {
+    Imager->log("Testing aa levels", 1);
+    my $f1 = Imager::Font->new(file => $deffont, type => "t1");
+    is($f1->{t1aa}, 2, "should have default aa level");
+    my $imbase = Imager->new(xsize => 100, ysize => 20);
+    ok($imbase->string(text => "test", size => 18, x => 5, y => 18,
+                      color => "#FFF", font => $f1, aa => 1),
+       "draw text with def aa level");
+    ok(Imager::Font::T1->set_aa_level(1), "set aa level to 1");
+    my $f2 = Imager::Font->new(file => $deffont, type => "t1");
+    is($f2->{t1aa}, 1, "new font has new aa level");
+    my $imaa1 = Imager->new(xsize => 100, ysize => 20);
+    ok($imaa1->string(text => "test", size => 18, x => 5, y => 18,
+                      color => "#FFF", font => $f2, aa => 1),
+       "draw text with non-def aa level");
+    isnt_image($imbase, $imaa1, "images should differ");
+    ok($f2->set_aa_level(2), "set aa level of font");
+    is($f2->{t1aa}, 2, "check new aa level");
+    my $imaa2 = Imager->new(xsize => 100, ysize => 20);
+    ok($imaa2->string(text => "test", size => 18, x => 5, y => 18,
+                      color => "#FFF", font => $f2, aa => 1),
+       "draw text with non-def but 2 aa level");
+    is_image($imbase, $imaa2, "check images match");
+  }
+
+  { # error handling check
+    my $im = Imager->new(xsize => 100, ysize => 20);
+    my $fnum = Imager::Font->new(file => $deffont, type => "t1");
+    ok(!$im->string(font => $fnum, string => "text", size => -10),
+       "set invalid size");
+    is($im->errstr, "i_t1_text(): T1_AASetString failed: Invalid Argument in Function Call",
+       "check error message");
+  }
 }
 
 #malloc_state();