#!/usr/bin/perl -w

use strict;

use Graphics::Framebuffer;
use List::Util qw(min max);

$| = 1;
system('clear');

my $mali = 0;
my $file = 0;
my $arg = join('',@ARGV);

$mali = 1 if ($arg =~ /mali/i); # Mali GPU correction mode
$file = 1 if ($arg =~ /file/i); # File Handle drawing mode

my $F = Graphics::Framebuffer->new('MALI' => $mali, 'FB_DEVICE' => '/dev/fb0','FILE_MODE' => $file,'SHOW_ERRORS' => 1,'LINE_PADDING'=> 0);

$SIG{'QUIT'} = sub { $F->cls('ON'); exit(0); };
$SIG{'INT'}  = sub { $F->cls('ON'); exit(0); };

my $screen_width  = $F->{'XRES'};
my $screen_height = $F->{'YRES'};
my $xm            = 1920 / $F->{'XRES'};
my $ym            = 1080 / $F->{'YRES'};
my $XX            = $screen_width;
my $YY            = $screen_height;
my $center_x      = $XX / 2;
my $center_y      = $YY / 2;
my $factor        = 5;

$F->cls('OFF');

print_it($F, 'Plotting Test');
my $s = time + $factor;
while (time < $s) {
    my $x = int(rand($screen_width));
    my $y = int(rand($screen_height));
    $F->set_color({'alpha' => 255,'red' => rand(256), 'green' => rand(256), 'blue' => rand(256)});
    $F->plot({'x' => $x, 'y' => $y});
}

print_it($F, 'Line Test');
for (my $l = $F->{'Y_CLIP'} ; $l < $YY ; $l += 4) {
    $F->set_color({'red' => rand(256), 'green' => rand(256), 'blue' => rand(256)});
    $F->line({'x' => 0, 'y' => $l, 'xx' => $XX, 'yy' => $l});

    $F->set_color({'red' => rand(256), 'green' => rand(256), 'blue' => rand(256)});
    $F->line({'x' => 0, 'y' => $l, 'xx' => $l, 'yy' => $F->{'Y_CLIP'}});

    $F->set_color({'red' => rand(256), 'green' => rand(256), 'blue' => rand(256)});
    $F->line({'x' => $XX, 'y' => $l, 'xx' => $XX - $l, 'yy' => $F->{'Y_CLIP'}});
    
    $F->set_color({'red' => rand(256), 'green' => rand(256), 'blue' => rand(256)});
    $F->line({'x' => $XX, 'y' => $YY - $l, 'xx' => $XX - $l, 'yy' => $F->{'Y_CLIP'}});

} ## end for (my $l = 40 ; $l < ...)
for (my $l = 0 ; $l < $XX ; $l += 4) {
    $F->set_color({'red' => rand(256), 'green' => rand(256), 'blue' => rand(256)});
    $F->line({'x' => $l, 'y' => $F->{'Y_CLIP'}, 'xx' => $l, 'yy' => $YY});
}

print_it($F, 'Box Test');
$s = time + $factor;
while (time < $s) {
    $F->set_color({'red' => rand(256), 'green' => rand(256), 'blue' => rand(256)});
    $F->box({'x' => rand($XX), 'y' => rand($YY), 'xx' => rand($XX), 'yy' => rand($YY)});
}

print_it($F, 'Filled Box Test');
$s = time + $factor;
while (time < $s) {
    $F->set_color({'red' => rand(256), 'green' => rand(256), 'blue' => rand(256)});
    $F->box({'x' => rand($XX), 'y' => rand($YY), 'xx' => rand($XX), 'yy' => rand($YY), 'filled' => 1});
}

print_it($F, 'Gradient Box Test');
$s = time + $factor;
while (time < $s) {
    $F->set_color({'red' => rand(256), 'green' => rand(256), 'blue' => rand(256)});
    $F->box(
        {
            'x'        => rand($XX),
              'y'        => rand($YY),
              'xx'       => rand($XX),
              'yy'       => rand($YY),
              'filled'   => 1,
              'gradient' => {
                  'start' => {
                      'red'   => rand(256),
                      'green' => rand(256),
                      'blue'  => rand(256)
                  },
                  'end' => {
                      'red'   => rand(256),
                      'green' => rand(256),
                      'blue'  => rand(256)
                  }
              }
        }
    );
} ## end foreach my $p (1 .. (20 * $factor...))

print_it($F, 'Rounded Box Test');
$s = time + $factor;
while (time < $s) {
    $F->set_color({'red' => rand(256), 'green' => rand(256), 'blue' => rand(256)});
    $F->box({'x' => rand($XX), 'y' => rand($YY), 'xx' => rand($XX), 'yy' => rand($YY), 'radius' => rand(20) + 1});
}

print_it($F, 'Filled Rounded Box Test');
$s = time + $factor;
while (time < $s) {
    $F->set_color({'red' => rand(256), 'green' => rand(256), 'blue' => rand(256)});
    $F->box({'x' => rand($XX), 'y' => rand($YY), 'xx' => rand($XX), 'yy' => rand($YY), 'radius' => rand(80) + 1, 'filled' => 1});
}

print_it($F, 'Gradient Rounded Box Test');
$s = time + $factor;
while (time < $s) {
    $F->set_color({'red' => rand(256), 'green' => rand(256), 'blue' => rand(256)});
    $F->box(
            {
                'x'        => rand($XX),
                  'y'        => rand($YY),
                  'xx'       => rand($XX),
                  'yy'       => rand($YY),
                  'radius'   => rand(80) + 1,
                  'filled'   => 1,
                  'gradient' => {
                      'start' => {
                          'red'   => rand(256),
                          'green' => rand(256),
                          'blue'  => rand(256)
                    },
                      'end' => {
                          'red'   => rand(256),
                          'green' => rand(256),
                          'blue'  => rand(256)
                      }
                  }
            }
        );
} ## end foreach my $p (1 .. (20 * $factor...))

print_it($F, 'Circle Test');
$s = time + $factor;
while (time < $s) {
    $F->set_color({'red' => rand(256), 'green' => rand(256), 'blue' => rand(256)});
    $F->circle({'x' => rand($XX), 'y' => rand($YY), 'radius' => rand($center_y)});
}

print_it($F, 'Filled Circle Test');
$s = time + $factor;
while (time < $s) {
    $F->set_color({'red' => rand(256), 'green' => rand(256), 'blue' => rand(256)});
    $F->circle({'x' => rand($XX), 'y' => rand($YY), 'radius' => rand($center_y), 'filled' => 1});
}

print_it($F, 'Gradient Circle Test');
$s = time + $factor;
while (time < $s) {
    $F->set_color({'red' => rand(256), 'green' => rand(256), 'blue' => rand(256)});
    $F->circle(
        {
            'x'        => rand($XX),
              'y'        => rand($YY),
              'radius'   => rand($center_y),
              'filled'   => 1,
              'gradient' => {
                  'start' => {
                      'red'   => rand(256),
                      'green' => rand(256),
                      'blue'  => rand(256)
                  },
                  'end' => {
                      'red'   => rand(256),
                      'green' => rand(256),
                      'blue'  => rand(256)
                  }
              }
        }
    );
}

print_it($F, 'Arc Test');
$s = time + $factor;
while (time < $s) {
    $F->set_color({'red' => rand(256), 'green' => rand(256), 'blue' => rand(256)});
    $F->arc({'x' => rand($XX), 'y' => rand($YY), 'radius' => rand($center_y),'start_degrees' => rand(360),'end_degrees' => rand(360)});
}

print_it($F, 'Poly Arc Test');
$s = time + $factor;
while (time < $s) {
    $F->set_color({'red' => rand(256), 'green' => rand(256), 'blue' => rand(256)});
    $F->poly_arc({'x' => rand($XX), 'y' => rand($YY), 'radius' => rand($center_y),'start_degrees' => rand(360),'end_degrees' => rand(360)});
}

print_it($F, 'Filled Pie Test');
$s = time + $factor;
while (time < $s) {
    $F->set_color({'red' => rand(256), 'green' => rand(256), 'blue' => rand(256)});
    $F->filled_pie({'x' => rand($XX), 'y' => rand($YY), 'radius' => rand($center_y),'start_degrees' => rand(360),'end_degrees' => rand(360)});
}

print_it($F, 'Gradient Filled Pie Test');
$s = time + $factor;
while (time < $s) {
    $F->set_color({'red' => rand(256), 'green' => rand(256), 'blue' => rand(256)});
    $F->filled_pie(
        {
            'x'        => rand($XX),
              'y'        => rand($YY),
              'radius'   => rand($center_y),
              'start_degrees' => rand(360),
              'end_degrees'   => rand(360),
              'gradient' => {
                  'start' => {
                      'red'   => rand(256),
                      'green' => rand(256),
                      'blue'  => rand(256)
                  },
                  'end' => {
                      'red'   => rand(256),
                      'green' => rand(256),
                      'blue'  => rand(256)
                  }
              }
        }
    );
}

print_it($F, 'Ellipse Test');
$s = time + $factor;
while (time < $s) {
    $F->set_color({'red' => rand(256), 'green' => rand(256), 'blue' => rand(256)});
    $F->ellipse({'x' => rand($XX), 'y' => rand($YY), 'xradius' => rand($center_x), 'yradius' => rand($center_y)});
}

print_it($F, 'Filled Ellipse Test');
$s = time + $factor;
while (time < $s) {
    $F->set_color({'red' => rand(256), 'green' => rand(256), 'blue' => rand(256)});
    $F->ellipse({'x' => rand($XX), 'y' => rand($YY), 'xradius' => rand($center_x), 'yradius' => rand($center_y), 'filled' => 1});
}

print_it($F, 'Gradient Ellipse Test');
$s = time + $factor;
while (time < $s) {
    $F->set_color({'red' => rand(256), 'green' => rand(256), 'blue' => rand(256)});
    $F->ellipse(
        {
            'x'        => rand($XX),
              'y'        => rand($YY),
              'xradius'  => rand($center_x),
              'yradius'  => rand($center_y),
              'filled'   => 1,
              'gradient' => {
                  'start' => {
                      'red'   => rand(256),
                      'green' => rand(256),
                      'blue'  => rand(256)
                  },
                  'end' => {
                      'red'   => rand(256),
                      'green' => rand(256),
                      'blue'  => rand(256)
                  }
              }
        }
    );
}

print_it($F, 'Polygon Test');
$s = time + $factor;
while (time < $s) {
    $F->set_color({'red' => rand(256), 'green' => rand(256), 'blue' => rand(256)});
    $F->polygon({'coordinates' => [rand($XX), rand($YY), rand($XX), rand($YY), rand($XX), rand($YY), rand($XX), rand($YY)]});
}

print_it($F, 'Filled Polygon Test');
$s = time + $factor;
while (time < $s) {
    $F->set_color({'red' => rand(256), 'green' => rand(256), 'blue' => rand(256)});
    $F->polygon({'coordinates' => [rand($XX), rand($YY), rand($XX), rand($YY), rand($XX), rand($YY), rand($XX), rand($YY)], 'filled' => 1});
}

print_it($F, 'Gradient Polygon Test');
$s = time + $factor;
while (time < $s) {
    $F->set_color({'red' => rand(256), 'green' => rand(256), 'blue' => rand(256)});
    $F->polygon(
        {
            'coordinates' => [rand($XX), rand($YY), rand($XX), rand($YY), rand($XX), rand($YY), rand($XX), rand($YY)],
              'filled'      => 1,
              'gradient'    => {
                  'start' => {
                      'red'   => rand(256),
                      'green' => rand(256),
                      'blue'  => rand(256)
                  },
                  'end' => {
                      'red'   => rand(256),
                      'green' => rand(256),
                      'blue'  => rand(256)
                  }
              }
        }
    );
}

print_it($F, 'Testing Bezier Curves');

$s = time + $factor;
while (time < $s) {
    $F->set_color({'red' => rand(256), 'green' => rand(256), 'blue' => rand(256)});
    my @coords = ();
    foreach my $c (1 .. int(rand(20))) {
        push(@coords, int(rand($XX)), int(rand($YY)));
    }
    $F->bezier({'coordinates' => \@coords, 'points' => 100});
} ## end foreach my $z (1 .. (40 * $factor...))

if ($XX > 255) {
    print_it($F, 'Testing TrueType Font Rendering (random height/width)');

    my $g = time + $factor;
    while( time < $g) {
        my $x  = int(rand(600 * $xm));
        my $y  = int(rand(900 * $ym));
        my $h  = int(rand(300 * $ym));
        my $ws = rand(4);
    
        my $b = $F->ttf_print(
            {
                'x'            => $x,
                  'y'            => $y,
                  'height'       => $h,
                  'wscale'       => $ws,
                  'color'        => sprintf('%x%x%x%x', int(rand(256)), int(rand(256)), int(rand(256)), 255),
                  'text'         => 'GFB',
                  'bounding_box' => 1,
                  'center'       => 3
            }
        );
        if (defined($b)) {
            $b->{'x'} = rand($F->{'XX_CLIP'} - $b->{'pwidth'});
            $F->ttf_print($b);
        }
    }
}
print_it($F, 'Testing flood fill');
if ($XX > 255) {
    $F->set_color({'red' => rand(256), 'green' => rand(256), 'blue' => rand(256)});
    $F->polygon({'coordinates' => [220 * $xm, 190 * $ym, 1520 * $xm, 80 * $xm, 1160 * $xm, $YY, 960 * $xm, 540 * $ym, 760 * $xm, 1080 * $ym]});
    $F->set_color({'red' => rand(256), 'green' => rand(256), 'blue' => rand(256)});
    $F->polygon({'coordinates' => [1270 * $xm, 570 * $ym, 970 * $xm, 170 * $ym, 600 * $xm, 500 * $ym]});
    $F->set_color({'red' => rand(256), 'green' => rand(256), 'blue' => rand(256)});
    $F->circle({'x' => 500 * $xm, 'y' => 320 * $ym, 'radius' => 100 * $xm});
    
    $F->set_color({'red' => rand(256), 'green' => rand(256), 'blue' => rand(256)});
    $F->fill({'x' => 240 * $xm, 'y' => 200 * $ym});
    
    $F->set_color({'red' => rand(256), 'green' => rand(256), 'blue' => rand(256)});
    $F->fill({'x' => 960 *$xm, 'y' => 440 * $ym});
} else {
    $F->set_color({'red' => rand(256), 'green' => rand(256), 'blue' => rand(256)});
    $F->polygon({'coordinates' => [$center_x,3, 3,$YY - 3, $center_x,$center_y, $XX - 3,$YY - 4]});
    $F->set_color({'red' => rand(256), 'green' => rand(256), 'blue' => rand(256)});
    $F->fill({'x' => 3, 'y' => 3});
}

print_it($F, 'Testing Color Replace (clipping on)');

my $x = $F->{'XRES'} / 4;
my $y = $F->{'YRES'} / 4;
$F->splash();
$F->clip_set({'x' => $x, 'y' => $y, 'xx' => $x * 3, 'yy' => $y * 3});
my $r = 128;
my $g = 0;
my $b = 0;
$s = time + $factor;
while (time < $s) {
    my $R = int(rand(256));
    my $G = int(rand(256));
    my $B = int(rand(256));
    $F->replace_color(
        {
            'old_red'   => $r,
              'old_green' => $g,
              'old_blue'  => $b,
              'new_red'   => $R,
              'new_green' => $G,
              'new_blue'  => $B
        }
    );
    ($r, $g, $b) = ($R, $G, $B);
}

print_it($F, 'Testing Color Replace (clipping off)');

$F->splash();

$F->clip_reset();

$r = 128;
$g = 0;
$b = 0;
$s = time + $factor;
while (time < $s) {
    my $R = int(rand(256));
    my $G = int(rand(256));
    my $B = int(rand(256));
    $F->replace_color(
        {
            'old_red'   => $r,
              'old_green' => $g,
              'old_blue'  => $b,
              'new_red'   => $R,
              'new_green' => $G,
              'new_blue'  => $B
        }
    );
    ($r, $g, $b) = ($R, $G, $B);
}

print_it($F, 'Testing Image load (different sizes)');

$s = time + $factor;
while (time < $s) {
    my $image = $F->load_image(
        {
            'x' => 0,
              'y' => 0,
            'width'  => rand($XX),
              'height' => rand($YY),
              'file'   => 'examples/RWBY_Faces.png'
        }
    );
    $F->blit_write($image);
}

print_it($F, 'Testing Image blitting');

my $image = $F->load_image(
    {
        'x'    => 0,
          'y'    => 0,
          'width' => min(640,$XX/2),
          'height' => min(405,$YY/2),
          'file' => 'examples/RWBY_Faces.png'
    }
);
$s = time + $factor;
while (time < $s) {
    $image->{'x'} = rand($XX - $image->{'width'});
    $image->{'y'} = rand($YY - $image->{'height'});
    $F->blit_write($image);
}

$F->cls('ON');

exit(0);

sub print_it {
    my $fb      = shift;
    my $message = shift;

    $fb->normal_mode();
    $fb->clip_reset();
    $fb->cls();
    unless ($XX < 256) {
        $fb->or_mode();

        my $b = $fb->ttf_print(
            {
                'x'            => 5  * $xm,
                'y'            => 30 * $ym,
                'height'       => 30 * $ym,
                'color'        => '00FF00',
                'text'         => $message,
                'bounding_box' => 1,
                'center'       => 0,
                'antialias'    => 1
            }
        );
        $fb->ttf_print($b);
        $fb->clip_set({'x' => 0, 'y' => $b->{'pheight'}, 'xx' => $XX, 'yy' => $YY});
        $fb->normal_mode();
    } else {
        print "$message\n";
    }
} ## end sub print_it

__END__

