… | |
… | |
21 | } |
21 | } |
22 | $self; |
22 | $self; |
23 | } |
23 | } |
24 | |
24 | |
25 | sub INSTANCE_INIT { |
25 | sub INSTANCE_INIT { |
26 | warn "instance_init @_\n"; |
|
|
27 | my $self = shift; |
26 | my $self = shift; |
28 | |
27 | |
29 | $self->double_buffered (0); |
28 | $self->double_buffered (0); |
30 | |
29 | |
31 | $self->signal_connect(configure_event => \&configure_event); |
30 | $self->signal_connect(configure_event => \&configure_event); |
… | |
… | |
42 | 1; |
41 | 1; |
43 | } |
42 | } |
44 | |
43 | |
45 | sub configure_event { |
44 | sub configure_event { |
46 | my ($self, $event) = @_; |
45 | my ($self, $event) = @_; |
47 | warn "configure @_\n";#d# |
|
|
48 | |
46 | |
49 | delete $self->{stack}; |
47 | delete $self->{stack}; |
50 | |
48 | |
51 | my $s = $self->{width} = $self->allocation->width; |
49 | my $s = $self->{width} = $self->allocation->width; |
52 | $self->{backgroundpb} = $self->draw_board ($s); |
50 | $self->draw_board ($s); |
53 | |
|
|
54 | $self->{backgroundpm} = new Gtk2::Gdk::Pixmap $self->window, $self->{width}, $self->{width}, -1; |
|
|
55 | $self->{backgroundpm}->draw_pixbuf ($self->style->white_gc, |
|
|
56 | $self->{backgroundpb}, |
|
|
57 | 0, 0, 0, 0, $self->{width}, $self->{width}, |
|
|
58 | "normal", 0, 0); |
|
|
59 | $self->window->set_back_pixmap ($self->{backgroundpm}, 0); |
|
|
60 | |
51 | |
61 | $self->repaint_board (delete $self->{board}, 0); |
52 | $self->repaint_board (delete $self->{board}, 0); |
62 | $self->window->clear_area (0, 0, $self->{width}, $self->{width}); |
53 | $self->window->clear_area (0, 0, $self->{width}, $self->{width}); |
63 | |
54 | |
64 | 1; |
55 | 1; |
… | |
… | |
157 | } |
148 | } |
158 | |
149 | |
159 | $$c->[$rand % @$$c]; |
150 | $$c->[$rand % @$$c]; |
160 | } |
151 | } |
161 | |
152 | |
162 | sub pixbuf_text { |
|
|
163 | my ($self, $pixbuf, $colour, $x, $y, $height, $text) = @_; |
|
|
164 | |
|
|
165 | #my $layout = $self->create_pango_layout ($text); |
|
|
166 | #my ($w, $h) = $layout->get_pixel_size; |
|
|
167 | #print "$w $h\n";#d# |
|
|
168 | |
|
|
169 | my @c = grep $_, |
|
|
170 | map $::font[$colour][$::fontmap{$_}], |
|
|
171 | split //, $text; |
|
|
172 | |
|
|
173 | if (@c) { |
|
|
174 | my $spacing = $height * 0.1; |
|
|
175 | my $s = $height / List::Util::max map $_->get_height, @c; |
|
|
176 | my $W = List::Util::sum map $_->get_width, @c; |
|
|
177 | |
|
|
178 | $x -= ($W * $s + $spacing * (@c - 1)) * 0.5; |
|
|
179 | $y -= $height * 0.5; |
|
|
180 | |
|
|
181 | for (@c) { |
|
|
182 | my $w = $_->get_width * $s; |
|
|
183 | # +2 == don't fight the rounding |
|
|
184 | $_->composite ($pixbuf, |
|
|
185 | $x, $y, $w+2, $height+2, $x, $y, $s, $s, |
|
|
186 | $::config->{speed} ? 'tiles' : 'bilinear', 255); |
|
|
187 | |
|
|
188 | $x += $w + $spacing; |
|
|
189 | } |
|
|
190 | } |
|
|
191 | } |
|
|
192 | |
|
|
193 | sub pixbuf_rect { |
153 | sub pixbuf_rect { |
194 | my ($pb, $colour, $x1, $y1, $x2, $y2, $alpha) = @_; |
154 | my ($pb, $colour, $x1, $y1, $x2, $y2, $alpha) = @_; |
195 | # we fake lines by... a horrible method :/ |
155 | # we fake lines by... a horrible method :/ |
196 | my $colour_pb = new_pixbuf 1, 1, 0, $colour; |
156 | my $colour_pb = new_pixbuf 1, 1, 0, $colour; |
197 | $colour_pb->composite ($pb, $x1, $y1, $x2 - $x1 + 1, $y2 - $y1 + 1, $x1, $y1, $x2 + 1, $y2 + 1, |
157 | $colour_pb->composite ($pb, $x1, $y1, $x2 - $x1 + 1, $y2 - $y1 + 1, $x1, $y1, $x2 + 1, $y2 + 1, |
… | |
… | |
202 | my ($self, $board) = @_; |
162 | my ($self, $board) = @_; |
203 | |
163 | |
204 | $self->repaint_board ($board, 1); |
164 | $self->repaint_board ($board, 1); |
205 | } |
165 | } |
206 | |
166 | |
207 | # draw an empty board |
167 | sub center_text { |
|
|
168 | my ($self, $drawable, $colour, $x, $y, $size, $text) = @_; |
|
|
169 | |
|
|
170 | my $context = $self->get_pango_context; |
|
|
171 | my $font = $context->get_font_description; |
|
|
172 | $font->set_size ($size * Gtk2::Pango->scale); |
|
|
173 | |
|
|
174 | my $layout = new Gtk2::Pango::Layout $context; |
|
|
175 | $layout->set_text ($text); |
|
|
176 | my ($w, $h) = $layout->get_pixel_size; |
|
|
177 | |
|
|
178 | #d# does not work |
|
|
179 | my $gc = $self->style->black_gc; |
|
|
180 | $gc->set_foreground (new Gtk2::Gdk::Color +($colour > 24) & 255, +($colour > 16) & 255, +($colour > 8) & 255); |
|
|
181 | |
|
|
182 | $drawable->draw_layout ($gc, |
|
|
183 | $x - $w*0.5, $y - $h*0.5, $layout); |
|
|
184 | } |
|
|
185 | |
|
|
186 | # draw an empty board and attach the bg pixmap |
208 | sub draw_board { |
187 | sub draw_board { |
209 | my ($self, $s) = @_; |
188 | my ($self, $s) = @_; |
210 | my $canvas = $self->{canvas}; |
189 | my $canvas = $self->{canvas}; |
211 | |
190 | |
212 | my $size = $self->{size}; |
191 | my $size = $self->{size}; |
|
|
192 | |
|
|
193 | my $pixmap = new Gtk2::Gdk::Pixmap $self->window, $self->{width}, $self->{width}, -1; |
213 | |
194 | |
214 | # we leave enough space for the shadows.. I like smaller stones, and we |
195 | # we leave enough space for the shadows.. I like smaller stones, and we |
215 | # do no need to do the nifty recursive screen updates that goban2 does |
196 | # do no need to do the nifty recursive screen updates that goban2 does |
216 | my $border = int ($s / ($size + 3) * 0.5); |
197 | my $border = int ($s / ($size + 3) * 0.5); |
217 | my $s2 = $s - $border * 2; |
198 | my $s2 = $s - $border * 2; |
… | |
… | |
242 | pixbuf_rect $pixbuf, 0xffcc7700, 0, $s-$linew-1, $s-1, $s-1, 255; |
223 | pixbuf_rect $pixbuf, 0xffcc7700, 0, $s-$linew-1, $s-1, $s-1, 255; |
243 | |
224 | |
244 | for my $i (1 .. $size) { |
225 | for my $i (1 .. $size) { |
245 | pixbuf_rect $pixbuf, 0x44111100, $k[$i] - $linew, $k[1] - $linew, $k[$i] + $linew, $k[$size] + $linew, 192; |
226 | pixbuf_rect $pixbuf, 0x44111100, $k[$i] - $linew, $k[1] - $linew, $k[$i] + $linew, $k[$size] + $linew, 192; |
246 | pixbuf_rect $pixbuf, 0x44111100, $k[1] - $linew, $k[$i] - $linew, $k[$size] + $linew, $k[$i] + $linew, 192; |
227 | pixbuf_rect $pixbuf, 0x44111100, $k[1] - $linew, $k[$i] - $linew, $k[$size] + $linew, $k[$i] + $linew, 192; |
247 | |
|
|
248 | # 38 max, but we allow a bit more |
|
|
249 | my $label = (qw(- A B C D E F G H J K L M N O P Q R S T U V W X Y Z |
|
|
250 | AA BB CC DD EE FF GG HH JJ KK LL MM NN OO PP QQ RR SS TT UU VV WW XX YY ZZ))[$i]; |
|
|
251 | |
|
|
252 | pixbuf_text $self, $pixbuf, 0, $k[$i], $border, $ofs, $label; |
|
|
253 | pixbuf_text $self, $pixbuf, 0, $k[$i], $s2 + $border, $ofs, $label; |
|
|
254 | pixbuf_text $self, $pixbuf, 0, $border, $k[$i], $ofs, $size - $i + 1; |
|
|
255 | pixbuf_text $self, $pixbuf, 0, $s2 + $border, $k[$i], $ofs, $size - $i + 1; |
|
|
256 | |
|
|
257 | $a++; |
|
|
258 | $a++ if $a eq "I"; # not correct, instead of AA AB, we should get HH JJ KK... |
|
|
259 | } |
228 | } |
260 | |
229 | |
261 | # hoshi points |
230 | # hoshi points |
262 | my $hoshi = sub { |
231 | my $hoshi = sub { |
263 | my ($x, $y) = @_; |
232 | my ($x, $y) = @_; |
… | |
… | |
287 | } |
256 | } |
288 | # the tengen |
257 | # the tengen |
289 | $hoshi->($h2, $h2); |
258 | $hoshi->($h2, $h2); |
290 | } |
259 | } |
291 | |
260 | |
292 | $pixbuf; |
261 | # now we have a board sans text |
|
|
262 | $pixmap->draw_pixbuf ($self->style->white_gc, |
|
|
263 | $pixbuf, |
|
|
264 | 0, 0, 0, 0, $self->{width}, $self->{width}, |
|
|
265 | "normal", 0, 0); |
|
|
266 | |
|
|
267 | # now draw the labels |
|
|
268 | for my $i (1 .. $size) { |
|
|
269 | # 38 max, but we allow a bit more |
|
|
270 | my $label = (qw(- A B C D E F G H J K L M N O P Q R S T U V W X Y Z |
|
|
271 | AA BB CC DD EE FF GG HH JJ KK LL MM NN OO PP QQ RR SS TT UU VV WW XX YY ZZ))[$i]; |
|
|
272 | |
|
|
273 | $self->center_text ($pixmap, 0, $k[$i], $border, $ofs, $label); |
|
|
274 | $self->center_text ($pixmap, 0, $k[$i], $s2 + $border, $ofs, $label); |
|
|
275 | $self->center_text ($pixmap, 0, $border, $k[$i], $ofs, $size - $i + 1); |
|
|
276 | $self->center_text ($pixmap, 0, $s2 + $border, $k[$i], $ofs, $size - $i + 1); |
|
|
277 | |
|
|
278 | $a++; |
|
|
279 | $a++ if $a eq "I"; # not correct, instead of AA AB, we should get HH JJ KK... |
|
|
280 | } |
|
|
281 | |
|
|
282 | $self->window->set_back_pixmap ($pixmap, 0); |
|
|
283 | |
|
|
284 | $self->{backgroundpm} = $pixmap; |
|
|
285 | $self->{backgroundpb} = $pixbuf; |
293 | } |
286 | } |
294 | |
287 | |
295 | sub repaint_board { |
288 | sub repaint_board { |
296 | my ($self, $board, $dopaint) = @_; |
289 | my ($self, $board, $dopaint) = @_; |
297 | |
290 | |
… | |
… | |
317 | $edge + $shadow, $edge + $shadow); |
310 | $edge + $shadow, $edge + $shadow); |
318 | |
311 | |
319 | my $pb = new_pixbuf @area[2,3]; |
312 | my $pb = new_pixbuf @area[2,3]; |
320 | $self->{backgroundpb}->copy_area (@area, $pb, 0, 0); |
313 | $self->{backgroundpb}->copy_area (@area, $pb, 0, 0); |
321 | |
314 | |
322 | if ($mark) { |
315 | if ($mark & ~MARK_LABEL) { |
323 | my $stack = $self->create_stack($mark, $edge, $rand); |
316 | my $stack = $self->create_stack($mark, $edge, $rand); |
324 | |
317 | |
325 | $stack->composite ($pb, 0, 0, @area[2,3], 0, 0, 1, 1, |
318 | $stack->composite ($pb, 0, 0, @area[2,3], 0, 0, 1, 1, |
326 | 'nearest', 255); |
319 | 'nearest', 255); |
327 | |
|
|
328 | # labels are handled here because they are quite rare |
|
|
329 | if ($mark & MARK_LABEL) { |
|
|
330 | my $white = $mark & (MARK_W | MARK_GRAY_W) ? 0 : 1; |
|
|
331 | |
|
|
332 | if ($white) { |
|
|
333 | pixbuf_text $pb, 0, |
|
|
334 | $ofs * 0.1, $ofs * 0.1, $ofs * 0.7, |
|
|
335 | $self->{board}{label}[$x-1][$y-1]; |
|
|
336 | } |
|
|
337 | pixbuf_text $pb, $white, |
|
|
338 | 0, 0, $ofs * 0.7, |
|
|
339 | $self->{board}{label}[$x-1][$y-1]; |
|
|
340 | } |
|
|
341 | } |
320 | } |
342 | |
321 | |
343 | # speed none, normal, max |
322 | # speed none, normal, max |
344 | $self->{backgroundpm}->draw_pixbuf ($self->style->black_gc, $pb, |
323 | $self->{backgroundpm}->draw_pixbuf ($self->style->black_gc, $pb, |
345 | 0, 0, @area, 'max', 0, 0); |
324 | 0, 0, @area, 'max', 0, 0); |
|
|
325 | |
|
|
326 | # labels are handled here because they are quite rare |
|
|
327 | if ($mark & MARK_LABEL) { |
|
|
328 | my $white = $mark & (MARK_W | MARK_GRAY_W) ? 0 : 0xffffff00; |
|
|
329 | |
|
|
330 | if ($white) { |
|
|
331 | $self->center_text ($self->{backgroundpm}, 0, |
|
|
332 | $area[0] + $ofs * 1.1, $area[1] + $ofs * 1.1, |
|
|
333 | $ofs * 0.7, $self->{board}{label}[$x-1][$y-1]); |
|
|
334 | } |
|
|
335 | $self->center_text ($self->{backgroundpm}, $white, |
|
|
336 | $area[0] + $ofs, $area[1] + $ofs, |
|
|
337 | $ofs * 0.7, $self->{board}{label}[$x-1][$y-1]); |
|
|
338 | } |
|
|
339 | |
346 | # a single full clear_area is way faster than many single calls here |
340 | # a single full clear_area is way faster than many single calls here |
347 | push @areas, \@area if $dopaint; |
341 | push @areas, \@area if $dopaint; |
348 | } |
342 | } |
349 | } |
343 | } |
350 | } |
344 | } |
… | |
… | |
365 | $self->{board} = $board; |
359 | $self->{board} = $board; |
366 | #d# save |
360 | #d# save |
367 | #Storable::nstore { board => $self->{board}, size => $self->{size}, path => $self->{path}}, "testboard.storable"; |
361 | #Storable::nstore { board => $self->{board}, size => $self->{size}, path => $self->{path}}, "testboard.storable"; |
368 | } |
362 | } |
369 | |
363 | |
370 | sub redraw { |
|
|
371 | my ($self, $area) = @_; |
|
|
372 | |
|
|
373 | if ($area && $self->{pixbuf}) { |
|
|
374 | my ($x, $y, $w, $h) = $area->values; |
|
|
375 | |
|
|
376 | $self->{canvas}->window->draw_pixbuf ($self->{canvas}->style->white_gc, $self->{pixbuf}, |
|
|
377 | $x, $y, $x, $y, $w, $h, |
|
|
378 | "normal", 0, 0); |
|
|
379 | $self->{canvas}->window->draw_rectangle ($self->{canvas}->style->black_gc, 0, |
|
|
380 | $x - 1, $y - 1, $w + 2, $h + 2) if $::DEBUG_EXPOSE; |
|
|
381 | } |
|
|
382 | } |
|
|
383 | |
|
|
384 | sub FINALIZE { |
364 | sub FINALIZE { |
385 | warn "FINALIZE(@_)\n";#d# |
365 | warn "FINALIZE(@_)\n";#d# |
386 | my ($self) = @_; |
366 | my ($self) = @_; |
387 | $self->{userpanel}[$_] && (delete $self->{userpanel}[$_])->destroy |
367 | $self->{userpanel}[$_] && (delete $self->{userpanel}[$_])->destroy |
388 | for BLACK, WHITE; |
368 | for BLACK, WHITE; |