Gtk2-GoBoard
view release on metacpan or search on metacpan
}
sub pixbuf_rect {
my ($pb, $colour, $x1, $y1, $x2, $y2, $alpha) = @_;
# we fake lines by... a horrible method :/
my $colour_pb = new_pixbuf 1, 1, 0, $colour;
$colour_pb->composite ($pb, $x1, $y1, $x2 - $x1 + 1, $y2 - $y1 + 1, $x1, $y1, $x2 + 1, $y2 + 1,
'nearest', $alpha);
}
sub center_text {
my ($self, $drawable, $colour, $x, $y, $size, $text) = @_;
# could be optimized by caching quite a bit
my $context = $self->get_pango_context;
my $font = $context->get_font_description;
$font->set_size ($size * Gtk2::Pango->scale);
my $layout = new Gtk2::Pango::Layout $context;
$layout->set_text ($text);
my ($w, $h) = $layout->get_pixel_size;
my $gc = new Gtk2::Gdk::GC $drawable;
my $r = (($colour >> 24) & 255) * (65535 / 255);
my $g = (($colour >> 16) & 255) * (65535 / 255);
my $b = (($colour >> 8) & 255) * (65535 / 255);
$gc->set_rgb_fg_color (new Gtk2::Gdk::Color $r, $g, $b);
$drawable->draw_layout ($gc, $x - $w*0.5, $y - $h*0.5, $layout);
}
# draw an empty board and attach the bg pixmap
sub draw_background {
my ($self) = @_;
my $canvas = $self->{canvas};
my $size = $self->{size};
my $w = $self->{width};
my $h = $self->{height};
delete $self->{backgroundpm};
delete $self->{backgroundpb};
my $pixmap = new Gtk2::Gdk::Pixmap $self->window, $w, $h, -1;
my $gridcolour = 0x44444400; # black is traditional, but only with overlapping stones
my $labelcolour = 0x88444400;
my $borderw = int $w / ($size + 1) * 0.5;
my $borderh = $borderw;
my $w2 = $w - $borderw * 2;
my $h2 = $h - $borderh * 2;
my $edge = ceil $w2 / ($size + 1);
my $ofs = $edge * 0.5;
# we need a certain minimum size, and just fudge some formula here
return if $w < $size * 5 + 2 + $borderw
|| $h < $size * 6 + 2 + $borderh;
my @kx = map int ($w2 * $_ / ($size+1) + $borderw + 0.5), 0 .. $size; $self->{kx} = \@kx;
my @ky = map int ($h2 * $_ / ($size+1) + $borderh + 0.5), 0 .. $size; $self->{ky} = \@ky;
my $pixbuf;
my ($bw, $bh) = ($board_img->get_width, $board_img->get_height);
if ($w < $bw && $h < $bh) {
$pixbuf = new_pixbuf $w, $h, 0;
$board_img->copy_area (0, 0, $w, $h, $pixbuf, 0, 0);
} else {
$pixbuf = scale_pixbuf $board_img, $w, $h, 'bilinear', 0; # nearest for extra speed
}
my $linew = int $w / 40 / $size;
# ornamental border... we have time to waste :/
pixbuf_rect $pixbuf, 0xffcc7700, 0, 0, $w-1, $linew, 255;
pixbuf_rect $pixbuf, 0xffcc7700, 0, 0, $linew, $h-1, 255;
pixbuf_rect $pixbuf, 0xffcc7700, $w-$linew-1, 0, $w-1, $h-1, 255;
pixbuf_rect $pixbuf, 0xffcc7700, 0, $h-$linew-1, $w-1, $h-1, 255;
for my $i (1 .. $size) {
pixbuf_rect $pixbuf, $gridcolour, $kx[$i] - $linew, $ky[1] - $linew, $kx[$i] + $linew, $ky[$size] + $linew, 255;
pixbuf_rect $pixbuf, $gridcolour, $kx[1] - $linew, $ky[$i] - $linew, $kx[$size] + $linew, $ky[$i] + $linew, 255;
}
# hoshi points
my $hoshi = sub {
my ($x, $y) = @_;
my $hs = 1 | int $edge / 4;
$hs = 5 if $hs < 5;
$x = $kx[$x] - $hs / 2; $y = $ky[$y] - $hs / 2;
# we use the shadow mask... not perfect, but I want to finish this
$shadow_img->composite ($pixbuf,
$x, $y, ($hs + 1) x2, $x, $y,
$hs / $shadow_img->get_width, $hs / $shadow_img->get_height,
'bilinear', 255);
};
if ($size > 6) {
my $h1 = $size < 10 ? 3 : 4; # corner / edge offset
$hoshi->($h1, $h1);
$hoshi->($size - $h1 + 1, $h1);
$hoshi->($h1, $size - $h1 + 1);
$hoshi->($size - $h1 + 1, $size - $h1 + 1);
if ($size % 2) { # on odd boards, also the remaining 5
my $h2 = ($size + 1) / 2;
if ($size > 10) {
$hoshi->($h1, $h2);
$hoshi->($size - $h1 + 1, $h2);
$hoshi->($h2, $size - $h1 + 1);
$hoshi->($h2, $h1);
}
# the tengen
( run in 3.152 seconds using v1.01-cache-2.11-cpan-5837b0d9d2c )