6 use vars qw(@ISA @EXPORT_OK $VERSION);
7 use Carp qw(croak carp);
46 sub diff_text_with_nul {
47 my ($desc, $text1, $text2, @params) = @_;
49 my $builder = Test::Builder->new;
52 my $imbase = Imager->new(xsize => 100, ysize => 100);
53 my $imcopy = Imager->new(xsize => 100, ysize => 100);
55 $builder->ok($imbase->string(x => 5, 'y' => 50, size => 20,
57 @params), "$desc - draw text1");
58 $builder->ok($imcopy->string(x => 5, 'y' => 50, size => 20,
60 @params), "$desc - draw text2");
61 $builder->isnt_num(Imager::i_img_diff($imbase->{IMG}, $imcopy->{IMG}), 0,
62 "$desc - check result different");
65 sub is_color3($$$$$) {
66 my ($color, $red, $green, $blue, $comment) = @_;
68 my $builder = Test::Builder->new;
70 unless (defined $color) {
71 $builder->ok(0, $comment);
72 $builder->diag("color is undef");
75 unless ($color->can('rgba')) {
76 $builder->ok(0, $comment);
77 $builder->diag("color is not a color object");
81 my ($cr, $cg, $cb) = $color->rgba;
82 unless ($builder->ok($cr == $red && $cg == $green && $cb == $blue, $comment)) {
95 sub is_color_close3($$$$$$) {
96 my ($color, $red, $green, $blue, $tolerance, $comment) = @_;
98 my $builder = Test::Builder->new;
100 unless (defined $color) {
101 $builder->ok(0, $comment);
102 $builder->diag("color is undef");
105 unless ($color->can('rgba')) {
106 $builder->ok(0, $comment);
107 $builder->diag("color is not a color object");
111 my ($cr, $cg, $cb) = $color->rgba;
112 unless ($builder->ok(abs($cr - $red) <= $tolerance
113 && abs($cg - $green) <= $tolerance
114 && abs($cb - $blue) <= $tolerance, $comment)) {
115 $builder->diag(<<END_DIAG);
116 Color out of tolerance ($tolerance):
117 Red: expected $red vs received $cr
118 Green: expected $green vs received $cg
119 Blue: expected $blue vs received $cb
127 sub is_color4($$$$$$) {
128 my ($color, $red, $green, $blue, $alpha, $comment) = @_;
130 my $builder = Test::Builder->new;
132 unless (defined $color) {
133 $builder->ok(0, $comment);
134 $builder->diag("color is undef");
137 unless ($color->can('rgba')) {
138 $builder->ok(0, $comment);
139 $builder->diag("color is not a color object");
143 my ($cr, $cg, $cb, $ca) = $color->rgba;
144 unless ($builder->ok($cr == $red && $cg == $green && $cb == $blue
145 && $ca == $alpha, $comment)) {
146 $builder->diag(<<END_DIAG);
159 sub is_fcolor4($$$$$$;$) {
160 my ($color, $red, $green, $blue, $alpha, $comment_or_diff, $comment_or_undef) = @_;
161 my ($comment, $mindiff);
162 if (defined $comment_or_undef) {
163 ( $mindiff, $comment ) = ( $comment_or_diff, $comment_or_undef )
166 ( $mindiff, $comment ) = ( 0.001, $comment_or_diff )
169 my $builder = Test::Builder->new;
171 unless (defined $color) {
172 $builder->ok(0, $comment);
173 $builder->diag("color is undef");
176 unless ($color->can('rgba')) {
177 $builder->ok(0, $comment);
178 $builder->diag("color is not a color object");
182 my ($cr, $cg, $cb, $ca) = $color->rgba;
183 unless ($builder->ok(abs($cr - $red) <= $mindiff
184 && abs($cg - $green) <= $mindiff
185 && abs($cb - $blue) <= $mindiff
186 && abs($ca - $alpha) <= $mindiff, $comment)) {
187 $builder->diag(<<END_DIAG);
200 sub is_fcolor1($$$;$) {
201 my ($color, $grey, $comment_or_diff, $comment_or_undef) = @_;
202 my ($comment, $mindiff);
203 if (defined $comment_or_undef) {
204 ( $mindiff, $comment ) = ( $comment_or_diff, $comment_or_undef )
207 ( $mindiff, $comment ) = ( 0.001, $comment_or_diff )
210 my $builder = Test::Builder->new;
212 unless (defined $color) {
213 $builder->ok(0, $comment);
214 $builder->diag("color is undef");
217 unless ($color->can('rgba')) {
218 $builder->ok(0, $comment);
219 $builder->diag("color is not a color object");
223 my ($cgrey) = $color->rgba;
224 unless ($builder->ok(abs($cgrey - $grey) <= $mindiff, $comment)) {
227 Gray: $cgrey vs $grey
235 sub is_fcolor3($$$$$;$) {
236 my ($color, $red, $green, $blue, $comment_or_diff, $comment_or_undef) = @_;
237 my ($comment, $mindiff);
238 if (defined $comment_or_undef) {
239 ( $mindiff, $comment ) = ( $comment_or_diff, $comment_or_undef )
242 ( $mindiff, $comment ) = ( 0.001, $comment_or_diff )
245 my $builder = Test::Builder->new;
247 unless (defined $color) {
248 $builder->ok(0, $comment);
249 $builder->diag("color is undef");
252 unless ($color->can('rgba')) {
253 $builder->ok(0, $comment);
254 $builder->diag("color is not a color object");
258 my ($cr, $cg, $cb) = $color->rgba;
259 unless ($builder->ok(abs($cr - $red) <= $mindiff
260 && abs($cg - $green) <= $mindiff
261 && abs($cb - $blue) <= $mindiff, $comment)) {
262 $builder->diag(<<END_DIAG);
275 my ($color, $grey, $comment) = @_;
277 my $builder = Test::Builder->new;
279 unless (defined $color) {
280 $builder->ok(0, $comment);
281 $builder->diag("color is undef");
284 unless ($color->can('rgba')) {
285 $builder->ok(0, $comment);
286 $builder->diag("color is not a color object");
290 my ($cgrey) = $color->rgba;
291 unless ($builder->ok($cgrey == $grey, $comment)) {
292 $builder->diag(<<END_DIAG);
294 Grey: $grey vs $cgrey
303 my $green=Imager::i_color_new(0,255,0,255);
304 my $blue=Imager::i_color_new(0,0,255,255);
305 my $red=Imager::i_color_new(255,0,0,255);
307 my $img=Imager::ImgRaw::new(150,150,3);
309 Imager::i_box_filled($img,70,25,130,125,$green);
310 Imager::i_box_filled($img,20,25,80,125,$blue);
311 Imager::i_arc($img,75,75,30,0,361,$red);
312 Imager::i_conv($img,[0.1, 0.2, 0.4, 0.2, 0.1]);
318 my $green = Imager::Color->new(0, 255, 0, 255);
319 my $blue = Imager::Color->new(0, 0, 255, 255);
320 my $red = Imager::Color->new(255, 0, 0, 255);
321 my $img = Imager->new(xsize => 150, ysize => 150);
322 $img->box(filled => 1, color => $green, box => [ 70, 24, 130, 124 ]);
323 $img->box(filled => 1, color => $blue, box => [ 20, 26, 80, 126 ]);
324 $img->arc(x => 75, y => 75, r => 30, color => $red);
325 $img->filter(type => 'conv', coef => [ 0.1, 0.2, 0.4, 0.2, 0.1 ]);
331 my $green = Imager::Color->new(0, 255, 0, 255);
332 my $blue = Imager::Color->new(0, 0, 255, 255);
333 my $red = Imager::Color->new(255, 0, 0, 255);
334 my $img = Imager->new(xsize => 150, ysize => 150, bits => 16);
335 $img->box(filled => 1, color => $green, box => [ 70, 24, 130, 124 ]);
336 $img->box(filled => 1, color => $blue, box => [ 20, 26, 80, 126 ]);
337 $img->arc(x => 75, y => 75, r => 30, color => $red);
338 $img->filter(type => 'conv', coef => [ 0.1, 0.2, 0.4, 0.2, 0.1 ]);
343 sub test_image_double {
344 my $green = Imager::Color->new(0, 255, 0, 255);
345 my $blue = Imager::Color->new(0, 0, 255, 255);
346 my $red = Imager::Color->new(255, 0, 0, 255);
347 my $img = Imager->new(xsize => 150, ysize => 150, bits => 'double');
348 $img->box(filled => 1, color => $green, box => [ 70, 24, 130, 124 ]);
349 $img->box(filled => 1, color => $blue, box => [ 20, 26, 80, 126 ]);
350 $img->arc(x => 75, y => 75, r => 30, color => $red);
351 $img->filter(type => 'conv', coef => [ 0.1, 0.2, 0.4, 0.2, 0.1 ]);
356 sub test_image_gray {
357 my $g50 = Imager::Color->new(128, 128, 128);
358 my $g30 = Imager::Color->new(76, 76, 76);
359 my $g70 = Imager::Color->new(178, 178, 178);
360 my $img = Imager->new(xsize => 150, ysize => 150, channels => 1);
361 $img->box(filled => 1, color => $g50, box => [ 70, 24, 130, 124 ]);
362 $img->box(filled => 1, color => $g30, box => [ 20, 26, 80, 126 ]);
363 $img->arc(x => 75, y => 75, r => 30, color => $g70);
364 $img->filter(type => 'conv', coef => [ 0.1, 0.2, 0.4, 0.2, 0.1 ]);
369 sub test_image_gray_16 {
370 my $g50 = Imager::Color->new(128, 128, 128);
371 my $g30 = Imager::Color->new(76, 76, 76);
372 my $g70 = Imager::Color->new(178, 178, 178);
373 my $img = Imager->new(xsize => 150, ysize => 150, channels => 1, bits => 16);
374 $img->box(filled => 1, color => $g50, box => [ 70, 24, 130, 124 ]);
375 $img->box(filled => 1, color => $g30, box => [ 20, 26, 80, 126 ]);
376 $img->arc(x => 75, y => 75, r => 30, color => $g70);
377 $img->filter(type => 'conv', coef => [ 0.1, 0.2, 0.4, 0.2, 0.1 ]);
382 sub test_image_mono {
383 require Imager::Fill;
384 my $fh = Imager::Fill->new(hatch => 'check1x1');
385 my $img = Imager->new(xsize => 150, ysize => 150, type => "paletted");
386 my $black = Imager::Color->new(0, 0, 0);
387 my $white = Imager::Color->new(255, 255, 255);
388 $img->addcolors(colors => [ $black, $white ]);
389 $img->box(fill => $fh, box => [ 70, 24, 130, 124 ]);
390 $img->box(filled => 1, color => $white, box => [ 20, 26, 80, 126 ]);
391 $img->arc(x => 75, y => 75, r => 30, color => $black, aa => 0);
398 basic => \&test_image,
399 basic16 => \&test_image_16,
400 basic_double => \&test_image_double,
401 gray => \&test_image_gray,
402 gray16 => \&test_image_gray_16,
403 mono => \&test_image_mono,
406 sub test_image_named {
408 or croak("No name supplied to test_image_named()");
409 my $sub = $name_to_sub{$name}
410 or croak("Unknown name $name supplied to test_image_named()");
415 sub _low_image_diff_check {
416 my ($left, $right, $comment) = @_;
418 my $builder = Test::Builder->new;
420 unless (defined $left) {
421 $builder->ok(0, $comment);
422 $builder->diag("left is undef");
425 unless (defined $right) {
426 $builder->ok(0, $comment);
427 $builder->diag("right is undef");
430 unless ($left->{IMG}) {
431 $builder->ok(0, $comment);
432 $builder->diag("left image has no low level object");
435 unless ($right->{IMG}) {
436 $builder->ok(0, $comment);
437 $builder->diag("right image has no low level object");
440 unless ($left->getwidth == $right->getwidth) {
441 $builder->ok(0, $comment);
442 $builder->diag("left width " . $left->getwidth . " vs right width "
446 unless ($left->getheight == $right->getheight) {
447 $builder->ok(0, $comment);
448 $builder->diag("left height " . $left->getheight . " vs right height "
449 . $right->getheight);
452 unless ($left->getchannels == $right->getchannels) {
453 $builder->ok(0, $comment);
454 $builder->diag("left channels " . $left->getchannels . " vs right channels "
455 . $right->getchannels);
462 sub is_image_similar($$$$) {
463 my ($left, $right, $limit, $comment) = @_;
466 local $Test::Builder::Level = $Test::Builder::Level + 1;
468 _low_image_diff_check($left, $right, $comment)
472 my $builder = Test::Builder->new;
474 my $diff = Imager::i_img_diff($left->{IMG}, $right->{IMG});
475 if ($diff > $limit) {
476 $builder->ok(0, $comment);
477 $builder->diag("image data difference > $limit - $diff");
480 # find the first mismatch
482 for my $y (0 .. $left->getheight()-1) {
483 for my $x (0.. $left->getwidth()-1) {
484 my @lsamples = $left->getsamples(x => $x, y => $y, width => 1);
485 my @rsamples = $right->getsamples(x => $x, y => $y, width => 1);
486 if ("@lsamples" ne "@rsamples") {
487 $builder->diag("first mismatch at ($x, $y) - @lsamples vs @rsamples");
497 return $builder->ok(1, $comment);
501 my ($left, $right, $comment) = @_;
503 local $Test::Builder::Level = $Test::Builder::Level + 1;
505 return is_image_similar($left, $right, 0, $comment);
508 sub is_imaged($$$;$) {
509 my $epsilon = Imager::i_img_epsilonf();
511 ($epsilon) = splice @_, 2, 1;
514 my ($left, $right, $comment) = @_;
517 local $Test::Builder::Level = $Test::Builder::Level + 1;
519 _low_image_diff_check($left, $right, $comment)
523 my $builder = Test::Builder->new;
525 my $same = Imager::i_img_samef($left->{IMG}, $right->{IMG}, $epsilon, $comment);
527 $builder->ok(0, $comment);
528 $builder->diag("images different");
530 # find the first mismatch
532 for my $y (0 .. $left->getheight()-1) {
533 for my $x (0.. $left->getwidth()-1) {
534 my @lsamples = $left->getsamples(x => $x, y => $y, width => 1, type => "float");
535 my @rsamples = $right->getsamples(x => $x, y => $y, width => 1, type => "float");
536 if ("@lsamples" ne "@rsamples") {
537 $builder->diag("first mismatch at ($x, $y) - @lsamples vs @rsamples");
546 return $builder->ok(1, $comment);
550 my ($left, $right, $comment) = @_;
552 my $builder = Test::Builder->new;
554 my $diff = Imager::i_img_diff($left->{IMG}, $right->{IMG});
556 return $builder->ok($diff, "$comment");
559 sub image_bounds_checks {
562 my $builder = Test::Builder->new;
564 $builder->ok(!$im->getpixel(x => -1, y => 0), 'bounds check get (-1, 0)');
565 $builder->ok(!$im->getpixel(x => 10, y => 0), 'bounds check get (10, 0)');
566 $builder->ok(!$im->getpixel(x => 0, y => -1), 'bounds check get (0, -1)');
567 $builder->ok(!$im->getpixel(x => 0, y => 10), 'bounds check get (0, 10)');
568 $builder->ok(!$im->getpixel(x => -1, y => 0), 'bounds check get (-1, 0) float');
569 $builder->ok(!$im->getpixel(x => 10, y => 0), 'bounds check get (10, 0) float');
570 $builder->ok(!$im->getpixel(x => 0, y => -1), 'bounds check get (0, -1) float');
571 $builder->ok(!$im->getpixel(x => 0, y => 10), 'bounds check get (0, 10) float');
572 my $black = Imager::Color->new(0, 0, 0);
573 require Imager::Color::Float;
574 my $blackf = Imager::Color::Float->new(0, 0, 0);
575 $builder->ok(!$im->setpixel(x => -1, y => 0, color => $black), 'bounds check set (-1, 0)');
576 $builder->ok(!$im->setpixel(x => 10, y => 0, color => $black), 'bounds check set (10, 0)');
577 $builder->ok(!$im->setpixel(x => 0, y => -1, color => $black), 'bounds check set (0, -1)');
578 $builder->ok(!$im->setpixel(x => 0, y => 10, color => $black), 'bounds check set (0, 10)');
579 $builder->ok(!$im->setpixel(x => -1, y => 0, color => $blackf), 'bounds check set (-1, 0) float');
580 $builder->ok(!$im->setpixel(x => 10, y => 0, color => $blackf), 'bounds check set (10, 0) float');
581 $builder->ok(!$im->setpixel(x => 0, y => -1, color => $blackf), 'bounds check set (0, -1) float');
582 $builder->ok(!$im->setpixel(x => 0, y => 10, color => $blackf), 'bounds check set (0, 10) float');
585 sub test_colorf_gpix {
586 my ($im, $x, $y, $expected, $epsilon, $comment) = @_;
588 my $builder = Test::Builder->new;
590 defined $comment or $comment = '';
592 my $c = Imager::i_gpixf($im, $x, $y);
594 $builder->ok(0, "$comment - retrieve color at ($x,$y)");
597 unless ($builder->ok(colorf_cmp($c, $expected, $epsilon) == 0,
598 "$comment - got right color ($x, $y)")) {
600 my @exp = $expected->rgba;
601 $builder->diag(<<EOS);
602 # got: ($c[0], $c[1], $c[2])
603 # expected: ($exp[0], $exp[1], $exp[2])
609 sub test_color_gpix {
610 my ($im, $x, $y, $expected, $comment) = @_;
612 my $builder = Test::Builder->new;
614 defined $comment or $comment = '';
615 my $c = Imager::i_get_pixel($im, $x, $y);
617 $builder->ok(0, "$comment - retrieve color at ($x,$y)");
620 unless ($builder->ok(color_cmp($c, $expected) == 0,
621 "got right color ($x, $y)")) {
623 my @exp = $expected->rgba;
624 $builder->diag(<<EOS);
625 # got: ($c[0], $c[1], $c[2])
626 # expected: ($exp[0], $exp[1], $exp[2])
634 sub test_colorf_glin {
635 my ($im, $x, $y, $pels, $comment) = @_;
637 my $builder = Test::Builder->new;
639 my @got = Imager::i_glinf($im, $x, $x+@$pels, $y);
641 or return $builder->is_num(scalar(@got), scalar(@$pels), "$comment - pixels retrieved");
643 return $builder->ok(!grep(colorf_cmp($pels->[$_], $got[$_], 0.005), 0..$#got),
644 "$comment - check colors ($x, $y)");
648 my ($c1, $c2, $epsilon) = @_;
650 defined $epsilon or $epsilon = 0;
655 # print "# (",join(",", @s1[0..2]),") <=> (",join(",", @s2[0..2]),")\n";
656 return abs($s1[0]-$s2[0]) >= $epsilon && $s1[0] <=> $s2[0]
657 || abs($s1[1]-$s2[1]) >= $epsilon && $s1[1] <=> $s2[1]
658 || abs($s1[2]-$s2[2]) >= $epsilon && $s1[2] <=> $s2[2];
667 return $s1[0] <=> $s2[0]
669 || $s1[2] <=> $s2[2];
672 # these test the action of the channel mask on the image supplied
673 # which should be an OO image.
675 my ($im, $epsilon) = @_;
677 my $builder = Test::Builder->new;
679 defined $epsilon or $epsilon = 0;
681 # we want to check all four of ppix() and plin(), ppix() and plinf()
682 # basic test procedure:
683 # first using default/all 1s mask, set to white
684 # make sure we got white
685 # set mask to skip a channel, set to grey
686 # make sure only the right channels set
688 print "# channel mask tests\n";
690 my $white = Imager::NC(255, 255, 255);
691 my $grey = Imager::NC(128, 128, 128);
692 my $white_grey = Imager::NC(128, 255, 128);
694 print "# with ppix\n";
695 $builder->ok($im->setmask(mask=>~0), "set to default mask");
696 $builder->ok($im->setpixel(x=>0, 'y'=>0, color=>$white), "set to white all channels");
697 test_color_gpix($im->{IMG}, 0, 0, $white, "ppix");
698 $builder->ok($im->setmask(mask=>0xF-0x2), "set channel to exclude channel1");
699 $builder->ok($im->setpixel(x=>0, 'y'=>0, color=>$grey), "set to grey, no channel 2");
700 test_color_gpix($im->{IMG}, 0, 0, $white_grey, "ppix masked");
702 print "# with plin\n";
703 $builder->ok($im->setmask(mask=>~0), "set to default mask");
704 $builder->ok($im->setscanline(x=>0, 'y'=>1, pixels => [$white]),
705 "set to white all channels");
706 test_color_gpix($im->{IMG}, 0, 1, $white, "plin");
707 $builder->ok($im->setmask(mask=>0xF-0x2), "set channel to exclude channel1");
708 $builder->ok($im->setscanline(x=>0, 'y'=>1, pixels=>[$grey]),
709 "set to grey, no channel 2");
710 test_color_gpix($im->{IMG}, 0, 1, $white_grey, "plin masked");
713 my $whitef = Imager::NCF(1.0, 1.0, 1.0);
714 my $greyf = Imager::NCF(0.5, 0.5, 0.5);
715 my $white_greyf = Imager::NCF(0.5, 1.0, 0.5);
717 print "# with ppixf\n";
718 $builder->ok($im->setmask(mask=>~0), "set to default mask");
719 $builder->ok($im->setpixel(x=>0, 'y'=>2, color=>$whitef), "set to white all channels");
720 test_colorf_gpix($im->{IMG}, 0, 2, $whitef, $epsilon, "ppixf");
721 $builder->ok($im->setmask(mask=>0xF-0x2), "set channel to exclude channel1");
722 $builder->ok($im->setpixel(x=>0, 'y'=>2, color=>$greyf), "set to grey, no channel 2");
723 test_colorf_gpix($im->{IMG}, 0, 2, $white_greyf, $epsilon, "ppixf masked");
725 print "# with plinf\n";
726 $builder->ok($im->setmask(mask=>~0), "set to default mask");
727 $builder->ok($im->setscanline(x=>0, 'y'=>3, pixels => [$whitef]),
728 "set to white all channels");
729 test_colorf_gpix($im->{IMG}, 0, 3, $whitef, $epsilon, "plinf");
730 $builder->ok($im->setmask(mask=>0xF-0x2), "set channel to exclude channel1");
731 $builder->ok($im->setscanline(x=>0, 'y'=>3, pixels=>[$greyf]),
732 "set to grey, no channel 2");
733 test_colorf_gpix($im->{IMG}, 0, 3, $white_greyf, $epsilon, "plinf masked");
737 sub std_font_test_count {
744 my $font = $opts->{font}
745 or carp "Missing font parameter";
747 my $name_font = $opts->{glyph_name_font} || $font;
749 my $has_chars = $opts->{has_chars} || [ 1, '', 1 ];
751 my $glyph_names = $opts->{glyph_names} || [ "A", undef, "A" ];
754 { # check magic is handled correctly
755 # https://rt.cpan.org/Ticket/Display.html?id=83438
756 skip("no native UTF8 support in this version of perl", 11)
758 skip("overloading handling of magic is broken in this version of perl", 11)
760 Imager->log("utf8 magic tests\n");
761 my $over = bless {}, "Imager::Test::OverUtf8";
762 my $text = "A".chr(0x2010)."A";
763 my $white = Imager::Color->new("#FFF");
764 my $base_draw = Imager->new(xsize => 80, ysize => 20);
765 ok($base_draw->string(font => $font,
772 "magic: make a base image");
773 my $test_draw = Imager->new(xsize => 80, ysize => 20);
774 ok($test_draw->string(font => $font,
781 "magic: draw with overload");
782 is_image($base_draw, $test_draw, "check they match");
783 if ($opts->{files}) {
784 $test_draw->write(file => "testout/utf8tdr.ppm");
785 $base_draw->write(file => "testout/utf8bdr.ppm");
788 my $base_cp = Imager->new(xsize => 80, ysize => 20);
789 $base_cp->box(filled => 1, color => "#808080");
790 my $test_cp = $base_cp->copy;
791 ok($base_cp->string(font => $font,
798 "magic: make a base image (channel)");
799 Imager->log("magic: draw to channel with overload\n");
800 ok($test_cp->string(font => $font,
807 "magic: draw with overload (channel)");
808 is_image($test_cp, $base_cp, "check they match");
809 if ($opts->{files}) {
810 $test_cp->write(file => "testout/utf8tcp.ppm");
811 $base_cp->write(file => "testout/utf8bcp.ppm");
816 Imager->log("magic: has_chars\n");
817 $font->can("has_chars")
818 or skip "No has_chars aupport", 2;
819 is_deeply([ $font->has_chars(string => $text) ], $has_chars,
820 "magic: has_chars with normal utf8 text");
821 is_deeply([ $font->has_chars(string => $over) ], $has_chars,
822 "magic: has_chars with magic utf8 text");
825 Imager->log("magic: bounding_box\n");
826 my @base_bb = $font->bounding_box(string => $text, size => 30);
827 is_deeply([ $font->bounding_box(string => $over, size => 30) ],
829 "check bounding box magic");
833 $font->can_glyph_names
834 or skip "No glyph_names", 2;
835 Imager->log("magic: glyph_names\n");
836 my @text_names = $name_font->glyph_names(string => $text, reliable_only => 0);
837 is_deeply(\@text_names, $glyph_names,
838 "magic: glyph_names with normal utf8 text");
839 my @over_names = $name_font->glyph_names(string => $over, reliable_only => 0);
840 is_deeply(\@over_names, $glyph_names,
841 "magic: glyph_names with magic utf8 text");
845 { # invalid UTF8 handling at the OO level
846 my $im = Imager->new(xsize => 80, ysize => 20);
847 my $bad_utf8 = pack("C", 0xC0);
848 Imager->_set_error("");
849 ok(!$im->string(font => $font, size => 1, text => $bad_utf8, utf8 => 1,
851 "drawing invalid utf8 should fail");
852 is($im->errstr, "invalid UTF8 character", "check error message");
853 Imager->_set_error("");
854 ok(!$im->string(font => $font, size => 1, text => $bad_utf8, utf8 => 1,
855 y => 18, x => 2, channel => 1),
856 "drawing invalid utf8 should fail (channel)");
857 is($im->errstr, "invalid UTF8 character", "check error message");
858 Imager->_set_error("");
859 ok(!$font->bounding_box(string => $bad_utf8, size => 30, utf8 => 1),
860 "bounding_box() bad utf8 should fail");
861 is(Imager->errstr, "invalid UTF8 character", "check error message");
864 $font->can_glyph_names
865 or skip "No glyph_names support", 2;
866 Imager->_set_error("");
867 is_deeply([ $font->glyph_names(string => $bad_utf8, utf8 => 1) ],
869 "glyph_names returns empty list for bad string");
870 is(Imager->errstr, "invalid UTF8 character", "check error message");
874 $font->can("has_chars")
875 or skip "No has_chars support", 2;
876 Imager->_set_error("");
877 is_deeply([ $font->has_chars(string => $bad_utf8, utf8 => 1) ],
879 "has_chars returns empty list for bad string");
880 is(Imager->errstr, "invalid UTF8 character", "check error message");
885 package Imager::Test::OverUtf8;
886 use overload '""' => sub { "A".chr(0x2010)."A" };
895 Imager::Test - common functions used in testing Imager
899 use Imager::Test 'diff_text_with_nul';
900 diff_text_with_nul($test_name, $text1, $text2, @string_options);
904 This is a repository of functions used in testing Imager.
906 Some functions will only be useful in testing Imager itself, while
907 others should be useful in testing modules that use Imager.
909 No functions are exported by default.
913 =head2 Test functions
919 =item is_color1($color, $grey, $comment)
921 Tests if the first channel of $color matches $grey.
923 =item is_color3($color, $red, $green, $blue, $comment)
925 Tests if $color matches the given ($red, $green, $blue)
927 =item is_color4($color, $red, $green, $blue, $alpha, $comment)
929 Tests if $color matches the given ($red, $green, $blue, $alpha)
931 =item is_fcolor1($fcolor, $grey, $comment)
933 =item is_fcolor1($fcolor, $grey, $epsilon, $comment)
935 Tests if $fcolor's first channel is within $epsilon of ($grey). For
936 the first form $epsilon is taken as 0.001.
938 =item is_fcolor3($fcolor, $red, $green, $blue, $comment)
940 =item is_fcolor3($fcolor, $red, $green, $blue, $epsilon, $comment)
942 Tests if $fcolor's channels are within $epsilon of ($red, $green,
943 $blue). For the first form $epsilon is taken as 0.001.
945 =item is_fcolor4($fcolor, $red, $green, $blue, $alpha, $comment)
947 =item is_fcolor4($fcolor, $red, $green, $blue, $alpha, $epsilon, $comment)
949 Tests if $fcolor's channels are within $epsilon of ($red, $green,
950 $blue, $alpha). For the first form $epsilon is taken as 0.001.
952 =item is_image($im1, $im2, $comment)
954 Tests if the 2 images have the same content. Both images must be
955 defined, have the same width, height, channels and the same color in
956 each pixel. The color comparison is done at 8-bits per pixel. The
957 color representation such as direct vs paletted, bits per sample are
958 not checked. Equivalent to is_image_similar($im1, $im2, 0, $comment).
960 =item is_imaged($im, $im2, $comment)
962 =item is_imaged($im, $im2, $epsilon, $comment)
964 Tests if the two images have the same content at the double/sample
965 level. C<$epsilon> defaults to the platform DBL_EPSILON multiplied by
968 =item is_image_similar($im1, $im2, $maxdiff, $comment)
970 Tests if the 2 images have similar content. Both images must be
971 defined, have the same width, height and channels. The cum of the
972 squares of the differences of each sample are calculated and must be
973 less than or equal to I<$maxdiff> for the test to pass. The color
974 comparison is done at 8-bits per pixel. The color representation such
975 as direct vs paletted, bits per sample are not checked.
977 =item isnt_image($im1, $im2, $comment)
979 Tests that the two images are different. For regressions tests where
980 something (like text output of "0") produced no change, but should
981 have produced a change.
983 =item test_colorf_gpix($im, $x, $y, $expected, $epsilon, $comment)
985 Retrieves the pixel ($x,$y) from the low-level image $im and compares
986 it to the floating point color $expected, with a tolerance of epsilon.
988 =item test_color_gpix($im, $x, $y, $expected, $comment)
990 Retrieves the pixel ($x,$y) from the low-level image $im and compares
991 it to the floating point color $expected.
993 =item test_colorf_glin($im, $x, $y, $pels, $comment)
995 Retrieves the floating point pixels ($x, $y)-[$x+@$pels, $y] from the
996 low level image $im and compares them against @$pels.
998 =item is_color_close3($color, $red, $green, $blue, $tolerance, $comment)
1000 Tests if $color's first three channels are within $tolerance of ($red,
1005 =head2 Test suite functions
1007 Functions that perform one or more tests, typically used to test
1008 various parts of Imager's implementation.
1012 =item image_bounds_checks($im)
1014 Attempts to write to various pixel positions outside the edge of the
1015 image to ensure that it fails in those locations.
1017 Any new image type should pass these tests. Does 16 separate tests.
1019 =item mask_tests($im, $epsilon)
1021 Perform a standard set of mask tests on the OO image $im. Does 24
1024 =item diff_text_with_nul($test_name, $text1, $text2, @options)
1026 Creates 2 test images and writes $text1 to the first image and $text2
1027 to the second image with the string() method. Each call adds 3
1028 C<ok>/C<not ok> to the output of the test script.
1030 Extra options that should be supplied include the font and either a
1031 color or channel parameter.
1033 This was explicitly created for regression tests on #21770.
1035 =item std_font_tests({ font => $font })
1037 Perform standard font interface tests.
1039 =item std_font_test_count()
1041 The number of tests performed by std_font_tests().
1045 =head2 Helper functions
1049 =item test_image_raw()
1051 Returns a 150x150x3 Imager::ImgRaw test image.
1055 Returns a 150x150x3 8-bit/sample OO test image. Name: C<basic>.
1057 =item test_image_16()
1059 Returns a 150x150x3 16-bit/sample OO test image. Name: C<basic16>
1061 =item test_image_double()
1063 Returns a 150x150x3 double/sample OO test image. Name: C<basic_double>.
1065 =item test_image_gray()
1067 Returns a 150x150 single channel OO test image. Name: C<gray>.
1069 =item test_image_gray_16()
1071 Returns a 150x150 16-bit/sample single channel OO test image. Name:
1074 =item test_image_mono()
1076 Returns a 150x150 bilevel image that passes the is_bilevel() test.
1079 =item test_image_named($name)
1081 Return one of the other test images above based on name.
1083 =item color_cmp($c1, $c2)
1085 Performs an ordering of 3-channel colors (like <=>).
1087 =item colorf_cmp($c1, $c2)
1089 Performs an ordering of 3-channel floating point colors (like <=>).
1095 Tony Cook <tony@develop-help.com>