Graphics-Framebuffer
view release on metacpan or search on metacpan
lib/Graphics/Framebuffer.pm view on Meta::CPAN
if (col8 != 0) res8 = fb / col8;
break;
default:
break;
}
*p = res8;
} break;
case 1: {
/* Not supported yet; no-op */
} break;
default:
break;
}
}
/* Draws a line */
void c_line(char *framebuffer,
short x1,
short y1,
short x2,
short y2,
short x_clip,
short y_clip,
short xx_clip,
short yy_clip,
unsigned int color,
unsigned int bcolor,
unsigned char alpha,
unsigned char draw_mode,
unsigned char bytes_per_pixel,
unsigned char bits_per_pixel,
unsigned int bytes_per_line,
short xoffset,
short yoffset,
bool antialiased) {
/* If antialiasing is requested, use Xiaolin Wu's algorithm... */
if (antialiased) {
double x0 = (double)x1;
double y0 = (double)y1;
double x1d = (double)x2;
double y1d = (double)y2;
int steep = fabs(y1d - y0) > fabs(x1d - x0);
if (steep) {
swap_(x0, y0);
swap_(x1d, y1d);
}
if (x0 > x1d) {
swap_(x0, x1d);
swap_(y0, y1d);
}
double dx = x1d - x0;
double dy = y1d - y0;
double gradient = (dx == 0.0) ? 1.0 : dy / dx;
/* handle first endpoint */
double xend = roundd(x0);
double yend = y0 + gradient * (xend - x0);
double xgap = rfpart(x0 + 0.5);
long xpxl1 = (long)xend;
long ypxl1 = (long)floor(yend);
/* plot first endpoint */
double intery = yend + gradient; /* first y-intersection for the main loop */
/* First endpoint pixels */
plot_aa_pixel(framebuffer,
color,
bcolor,
alpha,
bytes_per_pixel,
bits_per_pixel,
bytes_per_line,
x_clip,
y_clip,
xx_clip,
yy_clip,
xoffset,
yoffset,
steep,
xpxl1,
ypxl1,
rfpart(yend) * xgap);
plot_aa_pixel(framebuffer,
color,
bcolor,
alpha,
bytes_per_pixel,
bits_per_pixel,
bytes_per_line,
x_clip,
y_clip,
xx_clip,
yy_clip,
xoffset,
yoffset,
steep,
xpxl1,
ypxl1 + 1,
fpart(yend) * xgap);
/* handle second endpoint */
xend = roundd(x1d);
yend = y1d + gradient * (xend - x1d);
xgap = fpart(x1d + 0.5);
long xpxl2 = (long)xend;
long ypxl2 = (long)floor(yend);
plot_aa_pixel(framebuffer,
color,
bcolor,
alpha,
bytes_per_pixel,
bits_per_pixel,
bytes_per_line,
x_clip,
y_clip,
xx_clip,
yy_clip,
xoffset,
yoffset,
steep,
xpxl2,
ypxl2,
rfpart(yend) * xgap);
plot_aa_pixel(framebuffer,
color,
bcolor,
alpha,
bytes_per_pixel,
bits_per_pixel,
bytes_per_line,
x_clip,
y_clip,
xx_clip,
yy_clip,
xoffset,
yoffset,
steep,
xpxl2,
ypxl2 + 1,
fpart(yend) * xgap);
/* main loop */
long x;
if (xpxl1 + 1 <= xpxl2 - 1) {
for (x = xpxl1 + 1; x <= xpxl2 - 1; x++) {
double iy = intery;
long yint = (long)floor(iy);
plot_aa_pixel(framebuffer,
color,
bcolor,
alpha,
bytes_per_pixel,
bits_per_pixel,
bytes_per_line,
x_clip,
y_clip,
xx_clip,
yy_clip,
xoffset,
yoffset,
lib/Graphics/Framebuffer.pm view on Meta::CPAN
$self->plot({ 'x' => $start_x, 'y' => $start_y });
$start_x--;
$start_y--;
}
} ## end elsif (($start_x > $x_end...))
} ## end else [ if (($x_end == $start_x...))]
} ## end else [ if ($self->{'ACCELERATED'...})]
$self->{'X'} = $XX;
$self->{'Y'} = $YY;
} ## end sub drawto
sub _flush_screen {
# Since the framebuffer is mappeed as a string device, Perl buffers the output, and this must be flushed.
my $self = shift;
if ($self->{'DEVICE'} eq 'EMULATED') {
select(STDERR);
$| = 1;
} elsif (defined($self->{'FB'})) {
select($self->{'FB'});
$| = 1;
$self->{'FB'}->flush();
eval {sync $self->{'SCREEN'}, TRUE;};
$self->vsync();
}
$self->{'LAST_FLUSHED'} = time;
} ## end sub _flush_screen
sub _adj_plot {
# Part of antialiased drawing
my ($self, $x, $y, $c, $s) = @_;
$self->set_color({ 'red' => $s->{'red'} * $c, 'green' => $s->{'green'} * $c, 'blue' => $s->{'blue'} * $c });
$self->plot({ 'x' => $x, 'y' => $y });
} ## end sub _adj_plot
sub _draw_line_antialiased {
my ($self, $x0, $y0, $x1, $y1) = @_;
my $saved = { %{ $self->{'SET_RAW_FOREGROUND_COLOR'} } };
my $plot = \&_adj_plot;
if (abs($y1 - $y0) > abs($x1 - $x0)) {
$plot = sub { _adj_plot(@_[0, 2, 1, 3, 4]) };
($x0, $y0, $x1, $y1) = ($y0, $x0, $y1, $x1);
}
if ($x0 > $x1) {
($x0, $x1, $y0, $y1) = ($x1, $x0, $y1, $y0);
}
my $dx = $x1 - $x0;
my $dy = $y1 - $y0;
my $gradient = $dy / $dx;
my @xends;
my $intery;
# handle the endpoints
foreach my $xy ([$x0, $y0], [$x1, $y1]) {
my ($x, $y) = @{$xy};
my $xend = int($x + 0.5); # POSIX::lround($x);
my $yend = $y + $gradient * ($xend - $x);
my $xgap = _rfpart($x + 0.5);
my $x_pixel = $xend;
my $y_pixel = int($yend);
push(@xends, $x_pixel);
$plot->($self, $x_pixel, $y_pixel, _rfpart($yend) * $xgap, $saved);
$plot->($self, $x_pixel, $y_pixel + 1, _fpart($yend) * $xgap, $saved);
next if (defined($intery));
# first y-intersection for the main loop
$intery = $yend + $gradient;
} ## end foreach my $xy ([$x0, $y0],...)
# main loop
foreach my $x ($xends[0] + 1 .. $xends[1] - 1) {
$plot->($self, $x, int($intery), _rfpart($intery), $saved);
$plot->($self, $x, int($intery) + 1, _fpart($intery), $saved);
$intery += $gradient;
}
$self->set_color($saved);
} ## end sub _draw_line_antialiased
=head2 bezier
Draws a Bezier curve, based on a list of control points.
=over 4
$fb->bezier(
{
'coordinates' => [
x0,y0,
x1,y1,
... # As many as needed, there MUST be an even number of elements
],
'points' => 100, # Number of total points plotted for curve
# The higher the number, the smoother the curve.
'closed' => 1, # optional, close it and make it a full shape.
'filled' => 1 # Results may vary, optional
'gradient' => {
'direction' => 'horizontal', # or vertical
'colors' => { # 2 to any number of transitions allowed
'red' => [255,255,0], # Red to yellow to cyan
'green' => [0,255,255],
'blue' => [0,0,255]
}
}
}
);
=back
* This is not affected by the Acceleration setting
( run in 1.774 second using v1.01-cache-2.11-cpan-524268b4103 )