zusammenf?hrung
[darcs-mirror-ozeanien.git] / cairoboard.py
1 #!/usr/bin/python
2 # encoding:utf8
3
4
5 import pygtk
6 pygtk.require('2.0')
7 import gtk
8 import cairo
9 import math
10 import random
11
12 # Constants
13
14 GRIDWIDTH = 70
15 SCALE = GRIDWIDTH/2
16 GRIDPAD = 30
17
18 PILE_X = 2 * GRIDPAD + 10 * GRIDWIDTH
19 PILE_Y = 3 * GRIDWIDTH
20
21 BH_X = 2 * GRIDPAD + 10*GRIDWIDTH
22 BH_Y = 5 * GRIDWIDTH
23
24 class CairoBoard(gtk.DrawingArea):
25     def __init__(self,board):
26         assert board
27         self.board = board
28
29         self.base_surface = None
30         self.hand_x = 0
31         self.hand_y = 0
32         
33         self.highlighted_slot = None
34
35         gtk.DrawingArea.__init__(self)
36         self.add_events(gtk.gdk.BUTTON_PRESS_MASK |
37                 gtk.gdk.BUTTON_RELEASE_MASK |
38                 gtk.gdk.LEAVE_NOTIFY_MASK |
39                 gtk.gdk.EXPOSURE_MASK |
40                 gtk.gdk.POINTER_MOTION_MASK)
41         self.connect_after("expose-event",self.do_expose_event)
42         self.connect("motion-notify-event",self.hover)
43
44         self.set_size_request(
45             2 * GRIDPAD + 9 * GRIDWIDTH + 2 * GRIDWIDTH,
46             2 * GRIDPAD + 6 * GRIDWIDTH
47         )
48         
49         self.reset()
50
51     def reset(self):
52         self.queue_draw()
53
54     def do_expose_event(self,widget,event):
55         gc = self.window.new_gc()
56         gc.set_clip_rectangle(event.area)
57         cr = self.window.cairo_create()
58         # set a clip region for the expose event
59         cr.rectangle(event.area.x, event.area.y, event.area.width, event.area.height)
60         cr.clip()
61
62         self.draw_board(self.board, self.window)
63
64     def hover(self, widget, event):
65         self.hand_x = event.x
66         self.hand_y = event.y
67         if not self.board.hand.is_empty():
68             self.queue_draw()
69
70         slot = self.event2slot(event)
71         if self.highlighted_slot and self.highlighted_slot != slot: 
72             self.highlighted_slot.highlighted = False
73             self.highlighted_slot = None
74             self.queue_draw()
75         if slot:
76             slot.highlighted = True
77             self.highlighted_slot = slot
78             self.queue_draw()
79
80
81     def pileclick(self, event):
82         return (2*abs(event.x - PILE_X) < GRIDWIDTH and
83                 2*abs(event.y - PILE_Y + 3*SCALE) < GRIDWIDTH)
84
85     def pilerotclick(self, event):
86         if   PILE_Y + GRIDWIDTH/2 <= event.y <= PILE_Y + GRIDWIDTH and\
87                 PILE_X + GRIDWIDTH/4 <= event.x <= PILE_X + GRIDWIDTH:
88             return 1
89         elif PILE_Y + GRIDWIDTH/2 <= event.y <= PILE_Y + GRIDWIDTH and\
90                 PILE_X - GRIDWIDTH/4 >= event.x >= PILE_X - GRIDWIDTH:
91             return -1
92         else:
93             return 0
94
95
96     def event2slot(self, event):
97         x = int((event.x - GRIDPAD) // GRIDWIDTH)
98         y = int((event.y - GRIDPAD) // GRIDWIDTH)
99         if 0 <= x < len(self.board.slots) and 0 <= y < len(self.board.slots[x]):
100             return self.board.slots[x][y]
101         elif (2*abs(event.x - PILE_X) < GRIDWIDTH and
102               2*abs(event.y - PILE_Y) < GRIDWIDTH):
103             return self.board.pile
104         elif (2*abs(event.x - BH_X) < GRIDWIDTH and
105               2*abs(event.y - BH_Y) < GRIDWIDTH):
106             return self.board.bh
107         else:
108             return None
109
110     def draw_board(self, board, window):
111         self.draw_cached_base(window)
112
113         for col in board.slots:
114             for slot in col:
115                 self.draw_boardslot(slot,window)
116
117         self.draw_bh(board.bh, window)
118         self.draw_points(board.points, window)
119         self.draw_pile(board.pile, window)
120         self.draw_hand(board.hand, window, self.hand_x, self.hand_y)
121
122     
123     def draw_arrow(self, cr):
124         cr.arc(1, 1, 0.5, 0, math.pi/2)
125         cr.set_source_rgb(0, 0, 0)
126         cr.set_line_width(0.1)
127         cr.set_line_cap(cairo.LINE_CAP_ROUND)
128         cr.move_to(1,    1.5)
129         cr.line_to(0.75, 1.5)
130         cr.move_to(0.75, 1.5)
131         cr.line_to(1   , 1.75)
132         cr.move_to(0.75, 1.5)
133         cr.line_to(1   , 1.25)
134         cr.stroke()
135
136     def draw_pile(self, pile, window):
137         cr = window.cairo_create()
138         cr.translate(PILE_X, PILE_Y)
139         cr.scale(SCALE, SCALE)
140
141         cr.set_source_rgb(0.8, 0.8, 0.8)
142         cr.rectangle(-1, -1, 2, 2)
143         cr.fill()
144
145         matrix = cr.get_matrix()
146         self.draw_arrow(cr)
147         cr.scale(-1,1)
148         self.draw_arrow(cr)
149         cr.set_matrix(matrix)
150
151         cr.set_line_cap(cairo.LINE_CAP_SQUARE)
152         cr.translate(0,-3)
153         if pile.cards:
154             cr.set_source_rgb(0, 0, 0.5)
155             cr.rectangle(-1, -1, 2, 2)
156             cr.fill()
157         else:
158             cr.set_source_rgb(0, 0, 0)
159             cr.set_line_width(0.05)
160             cr.rectangle(-1, -1, 2, 2)
161             cr.stroke()
162
163         cr.set_font_size(1)
164         cr.set_source_rgb(1,1,1)
165         (_,_,w,h,_,_) = cr.text_extents(str(len(pile.cards)))
166
167         cr.move_to(-w/2, h/2)
168         cr.show_text(str(len(pile.cards)))
169         cr.fill()
170
171         self.draw_slot(pile, window, PILE_X, PILE_Y)
172
173     def draw_points(self, points, window):
174         cr = window.cairo_create()
175         cr.translate(2 * GRIDPAD + 10*GRIDWIDTH, 6 * GRIDWIDTH)
176         cr.scale(SCALE, SCALE)
177
178         txt = "%ip" % points
179
180         cr.set_font_size(1)
181         cr.set_source_rgb(0,0,0)
182         (_,_,w,h,_,_) = cr.text_extents(txt)
183
184         cr.move_to(-w/2, h/2)
185         cr.show_text(txt)
186         cr.fill()
187
188     def draw_bh(self, bh, window):
189         cr = window.cairo_create()
190         cr.translate(BH_X, BH_Y)
191         cr.scale(SCALE, SCALE)
192
193         cr.rectangle(-1, -1, 2, 2)
194         cr.clip()
195
196         cr.set_source_rgb(0,0,0)
197         cr.arc(0, 0, 0.8, 0, 2*math.pi)
198         cr.fill()
199         
200         cr.set_font_size(1)
201         cr.set_source_rgb(1,1,1)
202         (_,_,w,h,_,_) = cr.text_extents(str(bh.count))
203
204         cr.move_to(-w/2, h/2)
205         cr.show_text(str(bh.count))
206         cr.fill()
207
208     def draw_boardslot(self, slot, window):
209         self.draw_slot(slot, window,
210             GRIDPAD + (slot.x+0.5) * GRIDWIDTH,
211             GRIDPAD + (slot.y+0.5) * GRIDWIDTH)
212
213     def draw_slot(self, slot, window, x, y):
214         if slot.card or slot.ship:
215             cr = window.cairo_create()
216             cr.translate(x, y)
217             cr.scale(SCALE, SCALE)
218
219             #cr.rectangle(-1, -1, 2, 2)
220             #cr.clip()
221
222             matrix = cr.get_matrix()
223             if slot.card:
224                 self.draw_cached_card(slot.card, cr)
225                 cr.set_matrix(matrix)
226             if slot.ship:
227                 self.draw_cached_ship(slot.ship, cr)
228                 cr.set_matrix(matrix)
229
230             if slot.highlighted:
231                 cr.set_source_rgba(1, 1, 1, 0.5)
232                 cr.rectangle(-1, -1, 2, 2)
233                 cr.fill()
234
235     def draw_ship(self, ship, cr):
236         cr.move_to(0.9, 0)
237         cr.arc(0, 0, 0.3, math.pi, 0) 
238         cr.line_to(-0.9,0)
239         cr.line_to(-0.6, 0.6)
240         cr.line_to( 0.6, 0.6)
241
242         cr.set_source_rgb(1, 0, 0)
243         cr.fill()
244
245     draw_hand = draw_slot
246
247     def draw_card(self, card, cr):
248         # Meer
249         cr.set_source_rgb(0, 0, 1)
250         cr.rectangle(-1, -1, 2, 2)
251         cr.fill()
252
253         cr.set_source_rgb(0, 1, 0)
254         cr.set_line_cap(cairo.LINE_CAP_ROUND)
255         cr.set_line_join(cairo.LINE_JOIN_ROUND)
256         cr.set_line_width(0.9)
257
258         p2c = [ (1,0), (0,-1), (-1,0), (0,1) ]
259
260         # Land
261         for island in card.islands:
262             point = island[0]
263             cr.move_to( *p2c[point] )
264             for point in island[1:]:
265                 cr.line_to( *p2c[point] )
266             cr.close_path()
267             cr.stroke()
268         
269         # Border
270         cr.set_source_rgb(0, 0, 0)
271         cr.set_line_cap(cairo.LINE_CAP_ROUND)
272         cr.set_line_width(0.05)
273         cr.rectangle(-1, -1, 2, 2)
274         cr.stroke()
275
276     def draw_base(self, cr):
277         cr.translate(GRIDPAD, GRIDPAD)
278         cr.scale(GRIDWIDTH, GRIDWIDTH)
279
280         # Sea Background
281         # Unten
282         pat = cairo.LinearGradient (0, 5, 0, 5.5)
283         pat.add_color_stop_rgba(0, 0, 0, 1,1)
284         pat.add_color_stop_rgba(1, 0, 0, 1,0)
285         cr.rectangle(1, 5, 7, 0.5)
286         cr.set_source(pat)
287         cr.fill()
288
289         # Oben
290         pat = cairo.LinearGradient (0, 0, 0, -0.5)
291         pat.add_color_stop_rgba(0, 0, 0, 1,1)
292         pat.add_color_stop_rgba(1, 0, 0, 1,0)
293         cr.rectangle(1, -0.5, 7, 0.5)
294         cr.set_source(pat)
295         cr.fill()
296
297         # Links
298         pat = cairo.LinearGradient (1, 0, 0.5, 0)
299         pat.add_color_stop_rgba(0, 0, 0, 1,1)
300         pat.add_color_stop_rgba(1, 0, 0, 1,0)
301         cr.rectangle(0.5, 0, 0.5, 5)
302         cr.set_source(pat)
303         cr.fill()
304
305         # Rechts
306         pat = cairo.LinearGradient (8, 0, 8.5, 0)
307         pat.add_color_stop_rgba(0, 0, 0, 1,1)
308         pat.add_color_stop_rgba(1, 0, 0, 1,0)
309         cr.rectangle(8, 0, 0.5, 5)
310         cr.set_source(pat)
311         cr.fill()
312
313         # Oben Links
314         pat = cairo.RadialGradient(1,0,0, 1,0, 0.5)
315         pat.add_color_stop_rgba(0, 0, 0, 1, 1)
316         pat.add_color_stop_rgba(1, 0, 0, 1, 0)
317         cr.rectangle(0.5, -0.5, 0.5, 0.5)
318         cr.set_source(pat)
319         cr.fill()
320
321         # Oben Rechts
322         pat = cairo.RadialGradient(8,0,0, 8,0, 0.5)
323         pat.add_color_stop_rgba(0, 0, 0, 1, 1)
324         pat.add_color_stop_rgba(1, 0, 0, 1, 0)
325         cr.rectangle(8, -0.5, 8.5, 0.5)
326         cr.set_source(pat)
327         cr.fill()
328
329         # Unten Rechts
330         pat = cairo.RadialGradient(8,5,0, 8,5, 0.5)
331         pat.add_color_stop_rgba(0, 0, 0, 1, 1)
332         pat.add_color_stop_rgba(1, 0, 0, 1, 0)
333         cr.rectangle(8, 5, 8.5, 5.5)
334         cr.set_source(pat)
335         cr.fill()
336
337         # Unten Links
338         pat = cairo.RadialGradient(1,5,0, 1,5, 0.5)
339         pat.add_color_stop_rgba(0, 0, 0, 1, 1)
340         pat.add_color_stop_rgba(1, 0, 0, 1, 0)
341         cr.rectangle(0.5, 5, 1, 5.5)
342         cr.set_source(pat)
343         cr.fill()
344
345
346         # Frame
347         cr.set_source_rgb(1,1,1)
348         cr.set_line_width(0.05)
349         cr.set_line_cap(cairo.LINE_CAP_ROUND)
350         for x in range(0,8):
351             cr.move_to(1+x, 0)
352             cr.line_to(1+x, 5.5)
353             cr.stroke()
354         for y in range(0,6):
355             cr.move_to(0.5, y)
356             cr.line_to(8.5, y)
357             cr.stroke()
358
359     def draw_cached_ship(self,ship,cr):
360         cr.rotate(-(ship.rotation * math.pi / 2))
361         cr.rotate(math.pi / 2) # Koordinaten unten passen sonst nicht
362
363         if not ship.guiinfo:
364             ship.guiinfo = cr.get_target().create_similar(cairo.CONTENT_COLOR_ALPHA, 
365                     GRIDWIDTH + GRIDPAD, GRIDWIDTH + GRIDPAD)
366             scr = cairo.Context(ship.guiinfo)
367             scr.translate((GRIDWIDTH + GRIDPAD)/2, (GRIDWIDTH+GRIDPAD)/2)
368             scr.scale(SCALE, SCALE)
369
370             self.draw_ship(ship, scr)
371
372         cr.scale(1.0/SCALE, 1.0/SCALE)
373         cr.set_source_surface(ship.guiinfo,-(GRIDWIDTH + GRIDPAD)/2,-(GRIDWIDTH + GRIDPAD)/2)
374         cr.paint()
375
376     def draw_cached_card(self,card,cr):
377         cr.rotate(-(card.rotation * math.pi / 2))
378
379         if not card.guiinfo:
380             card.guiinfo = cr.get_target().create_similar(cairo.CONTENT_COLOR_ALPHA, 
381                     GRIDWIDTH + GRIDPAD, GRIDWIDTH + GRIDPAD)
382             scr = cairo.Context(card.guiinfo)
383             scr.translate((GRIDWIDTH + GRIDPAD)/2, (GRIDWIDTH+GRIDPAD)/2)
384             scr.scale(SCALE, SCALE)
385
386             self.draw_card(card, scr)
387
388         cr.scale(1.0/SCALE, 1.0/SCALE)
389         cr.set_source_surface(card.guiinfo,-(GRIDWIDTH + GRIDPAD)/2,-(GRIDWIDTH + GRIDPAD)/2)
390         cr.paint()
391
392     def draw_cached_base(self,window):
393         ocr = window.cairo_create()
394         if not self.base_surface:
395             self.base_surface = ocr.get_target().create_similar(cairo.CONTENT_COLOR_ALPHA, 
396                     2*GRIDPAD + 9*GRIDWIDTH, 2*GRIDPAD + 6*GRIDWIDTH)
397
398             cr = cairo.Context(self.base_surface)
399             self.draw_base(cr)
400
401         ocr.set_source_surface(self.base_surface,0,0)
402         ocr.rectangle(0,0,
403                 2*GRIDPAD + 9*GRIDWIDTH, 2*GRIDPAD + 6*GRIDWIDTH)
404         ocr.fill()
405
406 class GrassBoard(CairoBoard):
407     #Karte füllen
408     def draw_card(self, card, cr):
409         orientation=0;
410         cr.set_source_rgb(0.6, 0.4, 0.3)
411         cr.rectangle(-1, -1, 2, 2)
412         cr.fill()
413         p2c = [ (0.7,0), (0,-0.7), (-0.7,0), (0,0.7) ]
414         between_p2c = [ (0.6,-0.6), (-0.6,-0.6), (-0.6,0.6), (0.6,0.6) ]
415         matrix=cr.get_matrix()
416         for c in [
417                     (-0.7,-0.6), 
418                     (0,-0.65),
419                     (-0.5,-0.6),
420                     (0.4,-0.55),
421                     (0.8,-0.6),
422                     (-0.3,-0.4),
423                     (0.6,-0.35),
424                     (-0.85,-0.3),
425                     (0.3,-0.3),
426                     (0,-0.25),
427                     (-0.6,-0.2),
428                     (0.75,-0.2),
429                     (0.5,-0.1),
430                     (-0.5,0),
431                     (0.3,0.1),
432                     (-0.1,0.1),
433                     (-0.8,0.2),
434                     (0.7,0.2),
435                     (-0.4,0.3),
436                     (0.85,0.3),
437                     (-0.1,0.35),
438                     (0.25,0.4),
439                     (-0.75,0.4),
440                     (0.6,0.45),
441                     (-0.45,0.5),
442                     (0,0.6),
443                     (-0.8,0.7),
444                     (0.75,0.7),
445                     (-0.4,0.75),
446                     (0.5,0.75),
447                     (0.15,0.8),
448                     (-0.2,0.85),
449                     (-0.85,0.9),
450                     (0.85,0.9),
451                     (0,0.95),
452                     (-0.5,1),
453                     (0.45,1),
454                     
455                 ]:
456             cr.translate(*c)
457             self.draw_gras(card, cr, 0)
458             self.draw_gras(card, cr, 1)
459             cr.set_matrix(matrix)
460
461         for island in card.islands:
462             for dir in island:
463                 cr.translate(*p2c[dir])
464                 self.draw_flower(card, cr)
465                 cr.set_matrix(matrix)
466             for dir in island[:-1]:
467                 cr.translate(*between_p2c[dir])
468                 self.draw_flower(card, cr)
469                 cr.set_matrix(matrix)
470         #self.draw_gras(card, cr, orientation)
471         #self.draw_flower(card, cr)
472
473     #Einen Grashalm malen
474     def draw_gras(self, card, cr, orientation):
475         x=random.uniform(0.1,0.2)
476         y=random.uniform(0.2,0.3)
477         matrix=cr.get_matrix()
478         if orientation == 0: 
479             cr.scale(x, y)
480         else:
481             cr.scale(-x, y)
482         cr.translate(-1,-1)
483         cr.set_source_rgb(0, 1, 0)
484         cr.move_to(-1,-1)
485         cr.curve_to(0,-1,1,0,1,1)
486         cr.curve_to(0,1,0,-1,-1,-1)
487         cr.fill_preserve()
488         cr.set_source_rgb(0, 0, 0)
489         cr.set_line_width(0.1)
490         cr.stroke()
491         cr.set_matrix(matrix)
492             
493     #Eine Blume malen
494     def draw_flower(self, card,cr):
495         cr.rotate(random.uniform(0,2*math.pi))
496         matrix=cr.get_matrix()
497         cr.scale(0.25, 0.25)
498         color = ( 
499                     random.random(),
500                     random.random(),
501                     random.random() )
502
503         for n in range(5):
504             cr.set_source_rgb(*color)
505             cr.move_to(0,0)
506             cr.curve_to(0,-0.8,-0.2,-1,-1,-1)
507             cr.curve_to(-1,-0.2,-0.8,0.2,0,0)
508             cr.fill_preserve()
509             cr.set_source_rgb(0, 0, 0)
510             cr.set_line_width(0.1)
511             cr.stroke()
512             cr.rotate(2* math.pi / 5)
513         cr.set_matrix(matrix)
514     
515     def draw_ship(self, ship, cr):
516         
517         # Grundkörper (noch abzurunden)
518         cr.move_to(-0.5, -0.75)
519         cr.line_to(0.5, -0.75)
520         cr.line_to(0.5, 0.5)
521         cr.line_to(-0.5, 0.5)
522         cr.close_path()
523         cr.set_source_rgb(1, 0.2, 0.2)
524         cr.fill_preserve()
525         cr.set_source_rgb(0, 0, 0)
526         cr.set_line_width(0.05)
527         cr.stroke()
528
529         # Griff
530         cr.move_to(-0.25, 0.25)
531         cr.line_to(-0.55,  0.75)
532         cr.line_to( 0.55,  0.75)
533         cr.line_to( 0.25, 0.25)
534         cr.set_line_width(0.1)
535         cr.set_line_join(cairo.LINE_JOIN_ROUND)
536         cr.stroke()
537         
538         # Motor
539         cr.arc(0, -0.1 , 0.3, 0, 2*math.pi)
540         cr.set_source_rgb(0, 0, 0)
541         cr.fill()
542
543         # Augen
544         for _ in range(2):
545             cr.scale(-1,1)
546             cr.arc(0.3, -0.55 , 0.15, 0, 2*math.pi)
547             cr.set_source_rgb(1, 1, 1)
548             cr.fill_preserve()
549             cr.set_source_rgb(0, 0, 0)
550             cr.set_line_width(0.05)
551             cr.stroke()
552             cr.arc(0.25, -0.6 , 0.05, 0, 2*math.pi)
553             cr.set_source_rgb(0, 0, 0)
554             cr.fill()
555
556     def draw_base(self,cr):
557         cr.translate(GRIDPAD, GRIDPAD)
558         cr.scale(GRIDWIDTH, GRIDWIDTH)
559
560         # Sea Background
561
562         # Unten
563         pat = cairo.LinearGradient (0, 5, 0, 5.5)
564         pat.add_color_stop_rgba(0.3, 0.6, 0.4, 0.4,1)
565         pat.add_color_stop_rgba(1, 0.6, 0.4, 0.4,0)
566         cr.rectangle(1, 5, 7, 0.5)
567         cr.set_source(pat)
568         cr.fill()
569
570         # Oben
571         pat = cairo.LinearGradient (0, 0, 0, -0.5)
572         pat.add_color_stop_rgba(0.3, 0.6, 0.4, 0.4,1)
573         pat.add_color_stop_rgba(1, 0.6, 0.4, 0.4,0)
574         cr.rectangle(1, -0.5, 7, 0.5)
575         cr.set_source(pat)
576         cr.fill()
577
578         # Links
579         pat = cairo.LinearGradient (1, 0, 0.5, 0)
580         pat.add_color_stop_rgba(0.3, 0.6, 0.4, 0.4,1)
581         pat.add_color_stop_rgba(1, 0.6, 0.4, 0.4,0)
582         cr.rectangle(0.5, 0, 0.5, 5)
583         cr.set_source(pat)
584         cr.fill()
585
586         # Rechts
587         pat = cairo.LinearGradient (8, 0, 8.5, 0)
588         pat.add_color_stop_rgba(0.3, 0.6, 0.4, 0.4,1)
589         pat.add_color_stop_rgba(1, 0.6, 0.4, 0.4,0)
590         cr.rectangle(8, 0, 0.5, 5)
591         cr.set_source(pat)
592         cr.fill()
593
594         # Oben Links
595         pat = cairo.RadialGradient(1,0,0, 1,0, 0.5)
596         pat.add_color_stop_rgba(0.3, 0.6, 0.4, 0.4, 1)
597         pat.add_color_stop_rgba(1, 0.6, 0.4, 0.4, 0)
598         cr.rectangle(0.5, -0.5, 0.5, 0.5)
599         cr.set_source(pat)
600         cr.fill()
601
602         # Oben Rechts
603         pat = cairo.RadialGradient(8,0,0, 8,0, 0.5)
604         pat.add_color_stop_rgba(0.3, 0.6, 0.4, 0.4, 1)
605         pat.add_color_stop_rgba(1, 0.6, 0.4, 0.4, 0)
606         cr.rectangle(8, -0.5, 8.5, 0.5)
607         cr.set_source(pat)
608         cr.fill()
609
610         # Unten Rechts
611         pat = cairo.RadialGradient(8,5,0, 8,5, 0.5)
612         pat.add_color_stop_rgba(0.3, 0.6, 0.4, 0.4, 1)
613         pat.add_color_stop_rgba(1, 0.6, 0.4, 0.4, 0)
614         cr.rectangle(8, 5, 8.5, 5.5)
615         cr.set_source(pat)
616         cr.fill()
617
618         # Unten Links
619         pat = cairo.RadialGradient(1,5,0, 1,5, 0.5)
620         pat.add_color_stop_rgba(0.3, 0.6, 0.4, 0.4, 1)
621         pat.add_color_stop_rgba(1, 0.6, 0.4, 0.4, 0)
622         cr.rectangle(0.5, 5, 0.5, 5.5)
623         cr.set_source(pat)
624         cr.fill()
625
626
627         # Frame
628         cr.set_source_rgb(1,1,1)
629         cr.set_line_width(0.05)
630         cr.set_line_cap(cairo.LINE_CAP_ROUND)
631         for x in range(0,8):
632             cr.move_to(1+x, 0)
633             cr.line_to(1+x, 5.5)
634             cr.stroke()
635         for y in range(0,6):
636             cr.move_to(0.5, y)
637             cr.line_to(8.5, y)
638             cr.stroke()
639
640
641 # vim:ts=4:sw=4:sts=4:et