Skip to content

Commit

Permalink
implement antialiased lines and shapes for rop2(rop::CopyPut)
Browse files Browse the repository at this point in the history
also fix some wording in pod
  • Loading branch information
dk committed Oct 3, 2023
1 parent ad3e174 commit d3ff7ab
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 18 deletions.
109 changes: 92 additions & 17 deletions Prima/Drawable/Antialias.pm
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,28 @@ sub polyline
my ($x, $y, $w, $h) = $self->calc_poly_extents($poly);
return 0 unless defined $x;

my $bitmap = $self->alloc_surface($w, $h) or goto FALLBACK;
my $canvas = $self->{canvas};
my $lp = $canvas->linePattern;
my $r2 = $canvas->rop2;
my $lw = $canvas->lineWidth;
my $solid_line;
if ($lp eq lp::Null) {
return 1 if $r2 == rop::NoOper;
return 0 unless $canvas-> graphic_context_push;
$canvas->color($canvas->backColor);
$canvas->linePattern(lp::Solid);
my $ok = $self->polyline($poly);
$canvas->graphic_context_pop;
return $ok;
} elsif ( $lp ne lp::Solid && $r2 == rop::CopyPut ) {
$solid_line = 1;
}


my $bitmap = $self->alloc_surface($w, $h) or goto FALLBACK;

if ($canvas-> lineWidth > 1 ) {
$bitmap->region(
if ($lw > 1 ) {
my $line =
$bitmap->new_path->
scale($self->{factor})->
translate(-$x, -$y)->
Expand All @@ -103,12 +120,55 @@ sub polyline
linePattern lineJoin lineEnd miterLimit
)
)->
region(fm::Winding)
);
region(fm::Winding);

if ( $solid_line ) {
my $solid = $bitmap->new_path->
scale($self->{factor})->
translate(-$x, -$y)->
line($poly)->
widen(
lineWidth => $self->{factor} * ($canvas-> lineWidth - 1),
map { $_ => $canvas->$_() } qw(
lineJoin lineEnd miterLimit
)
)->
region(fm::Winding);

my $base = $self->alloc_surface( $w, $h ) or goto FALLBACK;
$solid->combine($line, rgnop::Xor);
$base->region($solid);
my $c = $canvas->color;
$canvas->color($canvas->backColor);
$base->bar( 0, 0, $base->size);
my $ok = $self->apply_surface($x, $y, $base);
$canvas->color($c);
return 0 unless $ok;
}

$bitmap->region($line);
$bitmap->bar( 0, 0, $bitmap->size);
} else {
$bitmap->translate(map { -1 * $self->{factor} * $_ } $x, $y);
$poly = Prima::Drawable->render_polyline( $poly, matrix => [$self->{factor},0,0,$self->{factor},0,0], integer => 1);
$poly = Prima::Drawable->render_polyline( $poly,
matrix => [($self->{factor},0,0) x 2],
integer => 1
);

if ( $solid_line ) {
my $base = $self->alloc_surface( $w, $h ) or goto FALLBACK;
my $lp = $canvas->linePattern;
$lp =~ s/(.)(.)/$2$1/gsm;
$base->linePattern($lp);
$base->polyline($poly);
my $c = $canvas->color;
$canvas->color($canvas->backColor);
$base->polyline($poly);
my $ok = $self->apply_surface($x, $y, $base);
$canvas->color($c);
return 0 unless $ok;
}
$bitmap->linePattern( $canvas->linePattern );
$bitmap->polyline($poly);
}
return $self->apply_surface($x, $y, $bitmap);
Expand Down Expand Up @@ -140,10 +200,12 @@ sub fillpoly
$bitmap->region( $rgn );

my $colors;
my $restore_color;
my $fp = $canvas->fillPattern;
if ( ref($fp) ne 'ARRAY') {
goto STIPPLE if $fp->type == im::BW && !$fp->isa('Prima::Icon');

IMAGE:
my @fp = $canvas->fillPatternOffset;
$fp[0] -= $x;
$fp[1] -= $y;
Expand All @@ -157,13 +219,26 @@ sub fillpoly
);

$colors->bar( 0, 0, $colors->size );
} elsif ( !fp::is_solid($fp) && !fp::is_empty($fp) ) {
} elsif ( fp::is_empty($fp)) {
return 1 if $canvas->rop2 == rop::NoOper;
$restore_color = $canvas->color;
$canvas->color($canvas->backColor);
} elsif ( !fp::is_solid($fp)) {
STIPPLE:
$fp = Prima::Image->new(
type => im::BW,
size => [8,8],
data => join('000', map { chr } @$fp),
) if ref($fp) eq 'ARRAY';

if ($canvas->rop2 == rop::CopyPut) {
if ($fp->type == im::BW) {
$fp->type(im::bpp1);
$fp->colormap( $canvas->backColor, $canvas->color );
}
goto IMAGE;
}

$fp = $fp->clone( size => [ map { $_ * $self->{factor} } $fp-> size ] );
$bitmap->fillPattern($fp);

Expand All @@ -174,7 +249,9 @@ sub fillpoly
}

$bitmap->bar( 0, 0, $bitmap->size);
return $self->apply_surface($x, $y, $bitmap, $colors);
my $ok = $self->apply_surface($x, $y, $bitmap, $colors);
$canvas->color($restore_color) if defined $restore_color;
return $ok;

FALLBACK:
return $self->{canvas}->fillpoly($poly);
Expand All @@ -193,9 +270,9 @@ Prima::Drawable::Antialias - plot antialiased shapes
Prima offers drawing antialiased lines and shapes, which is rather slow
but provides better visual feedback.
The module augments the C<Prima::Drawable> drawing functionality by
adding C<new_aa_surface> function, and contains two plotting functions,
C<polyline> and C<fillpoly>, identical to the ones in C<Prima::Drawable>.
The module augments the C<Prima::Drawable> drawing functionality by adding the
C<new_aa_surface> function, which features two plotting methods, C<polyline>
and C<fillpoly>, identical to the ones in C<Prima::Drawable>.
=head1 SYNOPSIS
Expand All @@ -219,15 +296,13 @@ Creates a new AA surface object. The object is cheap to keep and reuse.
=item fillpoly $POLY [ $FILLMODE ]
Paints an antialiased polygon shape. The following properties from C<$CANVAS> are respected:
color, fillPattern, fillPatternOffset. Does not plot opaque
patterned lines.
Paints an antialiased polygon shape. The following properties from the C<$CANVAS>
are respected: color, backColor, fillPattern, fillPatternOffset, rop2.
=item polyline $POLY
Plots an antialiased polyline. The following properties from C<$CANVAS> are respected:
color, linePattern, lineWidth, lineEnd, lineJoin, miterLimit. Does not plot opaque
patterned lines.
Plots an antialiased polyline. The following properties from the C<$CANVAS> are respected:
color, backColor, linePattern, lineWidth, lineEnd, lineJoin, miterLimit, rop2
=back
Expand Down
7 changes: 6 additions & 1 deletion examples/antialias.pl
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,12 @@ sub redraw
$canvas-> new_path(antialias => 1)-> ellipse(100,100,100)->fill;
$canvas-> fillPattern(fp::Solid);
$canvas->lineWidth(5);
$canvas-> new_aa_surface(alpha => 128)-> polyline([ 0, 0, $canvas->size ]);
$canvas-> graphic_context(
backColor => cl::Yellow,
rop2 => rop::CopyPut,
linePattern => lp::Dash,
sub { $canvas-> new_aa_surface(alpha => 128)-> polyline([ 0, 0, $canvas->size ]) },
);

if ( $canvas->can_draw_alpha ) {
$canvas->color(cl::Green);
Expand Down

0 comments on commit d3ff7ab

Please sign in to comment.