[rt #73359] draw non-AA text using FT2 in normal mode
authorTony Cook <tony@develop-help.com>
Mon, 10 Jun 2013 02:58:22 +0000 (12:58 +1000)
committerTony Cook <tony@develop-help.com>
Mon, 10 Jun 2013 02:58:22 +0000 (12:58 +1000)
FT2/Changes
FT2/FT2.pm
FT2/freetyp2.c
FT2/t/t10ft2.t

index f72bcbd..fc1b12e 100644 (file)
@@ -1,3 +1,9 @@
+Imager-Font-FT2 0.92
+====================
+
+ - drawing non-AA text is now done in alpha-combining mode
+   https://rt.cpan.org/Ticket/Display.html?id=73359
+
 Imager-Font-FT2 0.91
 ====================
 
index 4d1fec9..0c112a4 100644 (file)
@@ -6,7 +6,7 @@ use vars qw($VERSION @ISA);
 @ISA = qw(Imager::Font);
 
 BEGIN {
-  $VERSION = "0.91";
+  $VERSION = "0.92";
 
   require XSLoader;
   XSLoader::load('Imager::Font::FT2', $VERSION);
index 8d096a1..ac97b26 100644 (file)
@@ -739,15 +739,18 @@ i_ft2_text(FT2_Fonthandle *handle, i_img *im, i_img_dim tx, i_img_dim ty, const
   i_img_dim bbox[BOUNDING_BOX_COUNT];
   FT_GlyphSlot slot;
   int x, y;
-  unsigned char *bmp;
   unsigned char map[256];
   char last_mode = ft_pixel_mode_none; 
   int last_grays = -1;
   int loadFlags = FT_LOAD_DEFAULT;
   i_render *render = NULL;
+  unsigned char *work_bmp = NULL;
+  size_t work_bmp_size = 0;
 
-  mm_log((1, "i_ft2_text(handle %p, im %p, (tx,ty) (" i_DFp "), cl %p, cheight %f, cwidth %f, text %p, len %u, align %d, aa %d, vlayout %d, utf8 %d)\n",
-         handle, im, i_DFcp(tx, ty), cl, cheight, cwidth, text, (unsigned)len, align, aa, vlayout, utf8));
+  mm_log((1, "i_ft2_text(handle %p, im %p, (tx,ty) (" i_DFp "), cl %p (#%02x%02x%02x%02x), cheight %f, cwidth %f, text %p, len %u, align %d, aa %d, vlayout %d, utf8 %d)\n",
+         handle, im, i_DFcp(tx, ty), cl, cl->rgba.r, cl->rgba.g, cl->rgba.b,
+         cl->rgba.a, cheight, cwidth, text, (unsigned)len, align, aa,
+         vlayout, utf8));
 
   i_clear_error();
 
@@ -765,8 +768,10 @@ i_ft2_text(FT2_Fonthandle *handle, i_img *im, i_img_dim tx, i_img_dim ty, const
   if (!i_ft2_bbox(handle, cheight, cwidth, text, len, bbox, utf8))
     return 0;
 
-  if (aa)
-    render = i_render_new(im, bbox[BBOX_POS_WIDTH] - bbox[BBOX_NEG_WIDTH]);
+  render = i_render_new(im, bbox[BBOX_POS_WIDTH] - bbox[BBOX_NEG_WIDTH]);
+
+  work_bmp_size = bbox[BBOX_POS_WIDTH] - bbox[BBOX_NEG_WIDTH];
+  work_bmp = mymalloc(work_bmp_size);
 
   if (!align) {
     /* this may need adjustment */
@@ -805,29 +810,38 @@ i_ft2_text(FT2_Fonthandle *handle, i_img *im, i_img_dim tx, i_img_dim ty, const
       if (error) {
        ft2_push_message(error);
        i_push_errorf(0, "rendering glyph 0x%04lX (character \\x%02X)", c, index);
-      if (render)
-        i_render_delete(render);
+       if (render)
+         i_render_delete(render);
        return 0;
       }
       if (slot->bitmap.pixel_mode == ft_pixel_mode_mono) {
-       bmp = slot->bitmap.buffer;
+       unsigned char *bmp = slot->bitmap.buffer;
+       if (work_bmp_size < slot->bitmap.width) {
+         work_bmp_size = slot->bitmap.width;
+         work_bmp =  myrealloc(work_bmp, work_bmp_size);
+       }
        for (y = 0; y < slot->bitmap.rows; ++y) {
          int pos = 0;
          int bit = 0x80;
+         unsigned char *p = work_bmp;
          for (x = 0; x < slot->bitmap.width; ++x) {
-           if (bmp[pos] & bit)
-             i_ppix(im, tx+x+slot->bitmap_left, ty+y-slot->bitmap_top, cl);
-           
+           *p++ = (bmp[pos] & bit) ? 0xff : 0;
+
            bit >>= 1;
            if (bit == 0) {
              bit = 0x80;
              ++pos;
            }
          }
+          i_render_color(render, tx + slot->bitmap_left, ty-slot->bitmap_top+y,
+                         slot->bitmap.width, work_bmp, cl);
+
          bmp += slot->bitmap.pitch;
        }
       }
       else {
+       unsigned char *bmp = slot->bitmap.buffer;
+
        /* grey scale or something we can treat as greyscale */
        /* we create a map to convert from the bitmap values to 0-255 */
        if (last_mode != slot->bitmap.pixel_mode 
@@ -838,7 +852,6 @@ i_ft2_text(FT2_Fonthandle *handle, i_img *im, i_img_dim tx, i_img_dim ty, const
          last_grays = slot->bitmap.num_grays;
        }
 
-       bmp = slot->bitmap.buffer;
        for (y = 0; y < slot->bitmap.rows; ++y) {
           if (last_mode == ft_pixel_mode_grays &&
               last_grays != 255) {
@@ -859,6 +872,9 @@ i_ft2_text(FT2_Fonthandle *handle, i_img *im, i_img_dim tx, i_img_dim ty, const
   if (render)
     i_render_delete(render);
 
+  if (work_bmp)
+    myfree(work_bmp);
+
   return 1;
 }
 
index 3810014..af96545 100644 (file)
@@ -1,6 +1,6 @@
 #!perl -w
 use strict;
-use Test::More tests => 193;
+use Test::More tests => 204;
 use Cwd qw(getcwd abs_path);
 
 use Imager qw(:all);
@@ -9,7 +9,11 @@ use Imager::Test qw(diff_text_with_nul is_color3 is_color4 isnt_image is_image);
 
 -d "testout" or mkdir "testout";
 
-init_log("testout/t38ft2font.log",2);
+my @test_output;
+
+push @test_output, "t38ft2font.log";
+
+Imager->open_log(log => "testout/t38ft2font.log");
 
 my $deffont = "fontfiles/dodge.ttf";
 
@@ -42,6 +46,7 @@ SKIP:
   ok(Imager::Font::FT2::i_ft2_cp($ttraw,$overlay,5,50,1,50.0,50, 'XMCLH',1,1, 0, 0), "drawn to channel");
   i_line($overlay,0,50,100,50,$bgcolor,1);
 
+  push @test_output, "t38ft2font.ppm";
   open(FH,">testout/t38ft2font.ppm") || die "cannot open testout/t38ft2font.ppm\n";
   binmode(FH);
   my $IO = Imager::io_new_fd(fileno(FH));
@@ -57,6 +62,7 @@ SKIP:
   ok(Imager::Font::FT2::i_ft2_text($ttraw,$backgr,100,150,NC(0, 128, 0),200.0,50, 'MAW',0,1, 0, 0), "drew rotated MAW");
   i_line($backgr, 0,150, 499, 150, NC(0, 0, 255),1);
 
+  push @test_output, "t38ft2font2.ppm";
   open(FH,">testout/t38ft2font2.ppm") || die "cannot open testout/t38ft2font.ppm\n";
   binmode(FH);
   $IO = Imager::io_new_fd(fileno(FH));
@@ -174,6 +180,7 @@ SKIP:
                 align=>0, );
   }
 
+  push @test_output, "t38_oo.ppm";
   $im->write(file=>'testout/t38_oo.ppm')
     or print "# could not save OO output: ",$im->errstr,"\n";
   
@@ -216,6 +223,7 @@ SKIP:
   align_test('center', 'bottom', 150, 220, $oof, $alimg);
   align_test('center', 'baseline', 150, 250, $oof, $alimg);
   
+  push @test_output, "t38aligned.ppm";
   ok($alimg->write(file=>'testout/t38aligned.ppm'), 
      "saving aligned output image");
   
@@ -374,6 +382,7 @@ SKIP:
     }
   }
 
+  push @test_output, "t38mm.ppm";
   ok($mmim->write(file=>"testout/t38mm.ppm"), "save MM output");
 
  SKIP:
@@ -399,6 +408,7 @@ SKIP:
       ok($im->string(%common, @$args, 'y'=>90, align=>1), "A align=1");
       ok($im->string(%common, @$args, 'y'=>110, align=>0), "A align=0");
     }
+    push @test_output, "t38align.ppm";
     ok($im->write(file=>'testout/t38align.ppm'), "save align image");
   }
 
@@ -536,6 +546,59 @@ SKIP:
       isnt_image($work, $cmp, "make sure something was drawn");
     }
   }
+
+  { # RT 73359
+    # non-AA font drawing isn't normal mode
+
+    Imager->log("testing no-aa normal output\n");
+
+    my $font = Imager::Font->new(file => "fontfiles/ImUgly.ttf", type => "ft2");
+
+    ok($font, "make a work font");
+
+    my %common =
+      (
+       x => 10,
+       font => $font,
+       size => 25,
+       aa => 0,
+       align => 0,
+      );
+
+    # build our comparison image
+    my $cmp = Imager->new(xsize => 120, ysize => 100);
+    my $layer = Imager->new(xsize => 120, ysize => 100, channels => 4);
+    ok($layer->string(%common, y => 10, text => "full", color => "#8080FF"),
+       "draw non-aa text at full coverage to layer image");
+    ok($layer->string(%common, y => 40, text => "half", color => "#FF808080"),
+       "draw non-aa text at half coverage to layer image");
+    ok($layer->string(%common, y => 70, text => "quarter", color => "#80FF8040"),
+       "draw non-aa text at zero coverage to layer image");
+    ok($cmp->rubthrough(src => $layer), "rub layer onto comparison image");
+
+    my $im = Imager->new(xsize => 120, ysize => 100);
+    ok($im->string(%common, y => 10, text => "full", color => "#8080FF"),
+       "draw non-aa text at full coverage");
+    ok($im->string(%common, y => 40, text => "half", color => "#FF808080"),
+       "draw non-aa text at half coverage");
+    ok($im->string(%common, y => 70, text => "quarter", color => "#80FF8040"),
+       "draw non-aa text at zero coverage");
+    is_image($im, $cmp, "check the result");
+
+    push @test_output, "noaanorm.ppm", "noaacmp.ppm";
+    ok($cmp->write(file => "testout/noaacmp.ppm"), "save cmp image")
+      or diag "Saving cmp image: ", $cmp->errstr;
+    ok($im->write(file => "testout/noaanorm.ppm"), "save test image")
+      or diag "Saving result image: ", $im->errstr;
+  }
+}
+
+Imager->close_log();
+
+END {
+  unless ($ENV{IMAGER_KEEP_FILES}) {
+    unlink map "testout/$_", @test_output;
+  }
 }
 
 sub align_test {