Gtk2-GoBoard

 view release on metacpan or  search on metacpan

GoBoard.pm  view on Meta::CPAN

}

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 )