From b9459ada03d420d01b90b4c814b9d6efddabb0c8 Mon Sep 17 00:00:00 2001 From: Tony Cook Date: Mon, 10 Jun 2013 12:58:22 +1000 Subject: [PATCH] [rt #73359] draw non-AA text using FT2 in normal mode --- FT2/Changes | 6 +++++ FT2/FT2.pm | 2 +- FT2/freetyp2.c | 40 +++++++++++++++++++++--------- FT2/t/t10ft2.t | 67 ++++++++++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 100 insertions(+), 15 deletions(-) diff --git a/FT2/Changes b/FT2/Changes index f72bcbd5..fc1b12e0 100644 --- a/FT2/Changes +++ b/FT2/Changes @@ -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 ==================== diff --git a/FT2/FT2.pm b/FT2/FT2.pm index 4d1fec90..0c112a45 100644 --- a/FT2/FT2.pm +++ b/FT2/FT2.pm @@ -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); diff --git a/FT2/freetyp2.c b/FT2/freetyp2.c index 8d096a1d..ac97b26c 100644 --- a/FT2/freetyp2.c +++ b/FT2/freetyp2.c @@ -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; } diff --git a/FT2/t/t10ft2.t b/FT2/t/t10ft2.t index 3810014a..af965454 100644 --- a/FT2/t/t10ft2.t +++ b/FT2/t/t10ft2.t @@ -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 { -- 2.39.5