1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 from constant import DEFAULT_FONT, DEFAULT_FONT_SIZE
24 from math import pi
25 import cairo
26 import dtk_cairo_blur
27 import gtk
28 import math
29 import pango
30 import pangocairo
31 from utils import (cairo_state, cairo_disable_antialias, color_hex_to_cairo,
32 add_color_stop_rgba, propagate_expose,
33 alpha_color_hex_to_cairo, layout_set_markup)
34
36 '''
37 Draw radial ring.
38
39 @param cr: Cairo context.
40 @param x: X coordinate of draw area.
41 @param y: Y coordinate of draw area.
42 @param outer_radius: Radious for outter ring.
43 @param inner_radius: Radious for inner ring.
44 @param color_infos: A list of ColorInfo, ColorInfo format as [(color_pos, (color_hex_value, color_alpha))].
45 '''
46 with cairo_state(cr):
47
48 cr.arc(x, y, outer_radius, 0, pi * 2)
49 cr.arc(x, y, inner_radius, 0, pi * 2)
50 cr.set_fill_rule(cairo.FILL_RULE_EVEN_ODD)
51 cr.clip()
52
53
54 draw_radial_round(cr, x, y, outer_radius, color_infos)
55
57 '''
58 Get screenshot of desktop.
59
60 @return: Return desktop screenshot as gtk.gdk.Pixbuf.
61 '''
62 rootWindow = gtk.gdk.get_default_root_window()
63 [width, height] = rootWindow.get_size()
64 pixbuf = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, False, 8, width, height)
65 return pixbuf.get_from_drawable(rootWindow, rootWindow.get_colormap(), 0, 0, 0, 0, width, height)
66
68 '''
69 Draw round rectangle.
70
71 @param cr: Cairo context.
72 @param x: X coordiante of rectangle area.
73 @param y: Y coordiante of rectangle area.
74 @param width: Width of rectangle area.
75 @param height: Width of rectangle area.
76 @param r: Radious of rectangle corner.
77 '''
78
79 if width < 0:
80 x = x + width
81 width = -width
82 if height < 0:
83 y = y + height
84 height = -height
85
86
87 cr.move_to(x + r, y)
88 cr.line_to(x + width - r, y)
89
90
91 cr.arc(x + width - r, y + r, r, pi * 3 / 2, pi * 2)
92
93
94 cr.line_to(x + width, y + height - r)
95
96
97 cr.arc(x + width - r, y + height - r, r, 0, pi / 2)
98
99
100 cr.line_to(x + r, y + height)
101
102
103 cr.arc(x + r, y + height - r, r, pi / 2, pi)
104
105
106 cr.line_to(x, y + r)
107
108
109 cr.arc(x + r, y + r, r, pi, pi * 3 / 2)
110
111
112 cr.close_path()
113
115 '''
116 Draw pixbuf on cairo context, this function use frequently for image render.
117
118 @param cr: Cairo context.
119 @param pixbuf: gtk.gdk.Pixbuf
120 @param x: X coordiante of draw area.
121 @param y: Y coordiante of draw area.
122 @param alpha: Alpha value to render pixbuf, float value between 0 and 1.0
123 '''
124 if pixbuf != None:
125 cr.set_source_pixbuf(pixbuf, x, y)
126 cr.paint_with_alpha(alpha)
127
128 -def draw_window_frame(cr, x, y, w, h,
129 color_frame_outside_1,
130 color_frame_outside_2,
131 color_frame_outside_3,
132 color_frame_inside_1,
133 color_frame_inside_2,
134 ):
135 '''
136 Draw window frame.
137
138 @param cr: Cairo context.
139 @param x: X coordiante of draw area.
140 @param y: Y coordiante of draw area.
141 @param w: Width of draw area.
142 @param h: Height of draw area.
143 @param color_frame_outside_1: Use for draw outside 8 points.
144 @param color_frame_outside_2: Use for draw middle 4 points.
145 @param color_frame_outside_3: Use for draw inside 4 points.
146 @param color_frame_inside_1: Use for draw outside frame.
147 @param color_frame_inside_2: Use for draw inner frame and inside 4 points.
148 '''
149 with cairo_disable_antialias(cr):
150
151 cr.set_line_width(1)
152
153
154 cr.set_operator(cairo.OPERATOR_OVER)
155
156
157 cr.set_source_rgba(*alpha_color_hex_to_cairo(color_frame_outside_1.get_color_info()))
158
159 cr.rectangle(x, y + 1, 1, 1)
160 cr.rectangle(x + 1, y, 1, 1)
161
162 cr.rectangle(x + w - 1, y + 1, 1, 1)
163 cr.rectangle(x + w - 2, y, 1, 1)
164
165 cr.rectangle(x, y + h - 2, 1, 1)
166 cr.rectangle(x + 1, y + h - 1, 1, 1)
167
168 cr.rectangle(x + w - 1, y + h - 2, 1, 1)
169 cr.rectangle(x + w - 2, y + h - 1, 1, 1)
170
171 cr.fill()
172
173
174 cr.set_source_rgba(*alpha_color_hex_to_cairo(color_frame_outside_2.get_color_info()))
175
176 cr.rectangle(x + 1, y + 1, 1, 1)
177
178 cr.rectangle(x + w - 2, y + 1, 1, 1)
179
180 cr.rectangle(x + 1, y + h - 2, 1, 1)
181
182 cr.rectangle(x + w - 2, y + h - 2, 1, 1)
183
184 cr.fill()
185
186
187 cr.set_source_rgba(*alpha_color_hex_to_cairo(color_frame_outside_3.get_color_info()))
188
189 cr.rectangle(x + 2, y, w - 4, 1)
190
191 cr.rectangle(x + 2, y + h - 1, w - 4, 1)
192
193 cr.rectangle(x, y + 2, 1, h - 4)
194
195 cr.rectangle(x + w - 1, y + 2, 1, h - 4)
196
197 cr.fill()
198
199
200 cr.set_source_rgba(*alpha_color_hex_to_cairo(color_frame_inside_1.get_color_info()))
201
202 cr.rectangle(x + 1, y + 1, 1, 1)
203
204 cr.rectangle(x + w - 2, y + 1, 1, 1)
205
206 cr.rectangle(x + 1, y + h - 2, 1, 1)
207
208 cr.rectangle(x + w - 2, y + h - 2, 1, 1)
209
210 cr.fill()
211
212
213 cr.set_source_rgba(*alpha_color_hex_to_cairo(color_frame_inside_1.get_color_info()))
214
215 cr.rectangle(x + 2, y + 2, 1, 1)
216
217 cr.rectangle(x + w - 3, y + 2, 1, 1)
218
219 cr.rectangle(x + 2, y + h - 3, 1, 1)
220
221 cr.rectangle(x + w - 3, y + h - 3, 1, 1)
222
223 cr.fill()
224
225
226 cr.set_source_rgba(*alpha_color_hex_to_cairo(color_frame_inside_2.get_color_info()))
227
228 cr.rectangle(x + 2, y + 1, w - 4, 1)
229
230 cr.rectangle(x + 2, y + h - 2, w - 4, 1)
231
232 cr.rectangle(x + 1, y + 2, 1, h - 4)
233
234 cr.rectangle(x + w - 2, y + 2, 1, h - 4)
235
236 cr.fill()
237
239 '''
240 Draw window rectangle.
241
242 @param cr: Cairo context.
243 @param sx: Source x coordinate.
244 @param sy: Source y coordinate.
245 @param ex: Target x coordinate.
246 @param ey: Target x coordinate.
247 @param r: Window frame radious.
248 '''
249 with cairo_disable_antialias(cr):
250
251 cr.set_line_width(1)
252
253
254 cr.set_operator(cairo.OPERATOR_OVER)
255
256 cr.move_to(sx + r, sy)
257 cr.line_to(ex - r, sy)
258 cr.stroke()
259
260 cr.move_to(ex, sy + r)
261 cr.line_to(ex, ey - r)
262 cr.stroke()
263
264 cr.move_to(ex - r, ey)
265 cr.line_to(sx + r, ey)
266 cr.stroke()
267
268 cr.move_to(sx, ey - r)
269 cr.line_to(sx, sy + r)
270 cr.stroke()
271
272 cr.arc(sx + r, sy + r, r, pi, pi * 3 / 2)
273 cr.stroke()
274
275 cr.arc(ex - r, sy + r, r, pi * 3 / 2, pi * 2)
276 cr.stroke()
277
278 cr.arc(ex - r, ey - r, r, 0, pi / 2)
279 cr.stroke()
280
281 cr.arc(sx + r, ey - r, r, pi / 2, pi)
282 cr.stroke()
283
284 -def draw_text(cr, markup, x, y, w, h, text_size=DEFAULT_FONT_SIZE, text_color="#000000",
285 text_font=DEFAULT_FONT, alignment=pango.ALIGN_LEFT,
286 gaussian_radious=None, gaussian_color=None,
287 border_radious=None, border_color=None,
288 wrap_width=None,
289 ):
290 '''
291 Standard function for draw text.
292
293 @param cr: Cairo context.
294 @param markup: Pango markup string.
295 @param x: X coordinate of draw area.
296 @param y: Y coordinate of draw area.
297 @param w: Width of draw area.
298 @param h: Height of draw area.
299 @param text_size: Text size, default is DEFAULT_FONT_SIZE.
300 @param text_color: Text color, default is \"#000000\".
301 @param text_font: Text font, default is DEFAULT_FONT.
302 @param alignment: Font alignment option, default is pango.ALIGN_LEFT. You can set pango.ALIGN_MIDDLE or pango.ALIGN_RIGHT.
303 @param gaussian_radious: Gaussian radious, default is None.
304 @param gaussian_color: Gaussian color, default is None.
305 @param border_radious: Border radious, default is None.
306 @param border_color: Border color, default is None.
307 @param wrap_width: Wrap width of text, default is None.
308 '''
309 if border_radious == None and border_color == None and gaussian_radious == None and gaussian_color == None:
310 render_text(cr, markup, x, y, w, h, text_size, text_color, text_font, alignment,
311 wrap_width=wrap_width)
312 elif (border_radious != None and border_color != None) or (gaussian_radious != None and gaussian_color != None):
313
314 surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h)
315 text_cr = cairo.Context(surface)
316
317
318 if gaussian_radious != None and gaussian_color != None:
319 text_cr.save()
320 render_text(text_cr, markup, gaussian_radious,
321 gaussian_radious, w - gaussian_radious * 2, h - gaussian_radious * 2,
322 text_size, gaussian_color, alignment=alignment,
323 wrap_width=wrap_width)
324 dtk_cairo_blur.gaussian_blur(surface, gaussian_radious)
325 text_cr.restore()
326
327
328 if gaussian_radious == None:
329 gaussian_radious = 0
330
331
332 if border_radious != None and border_radious != 0 and border_color != None:
333 render_text(text_cr, markup, gaussian_radious, gaussian_radious, w - gaussian_radious * 2,
334 h - gaussian_radious * 2, text_size, border_color, alignment=alignment,
335 wrap_width=wrap_width)
336 dtk_cairo_blur.gaussian_blur(surface, border_radious)
337
338
339 render_text(text_cr, markup, gaussian_radious, gaussian_radious, w - gaussian_radious * 2,
340 h - gaussian_radious * 2, text_size, text_color, alignment=alignment,
341 wrap_width=wrap_width)
342
343
344 cr.set_source_surface(surface, x, y)
345 cr.paint()
346
347 -def render_text(cr, markup, x, y, w, h, text_size=DEFAULT_FONT_SIZE, text_color="#000000",
348 text_font=DEFAULT_FONT, alignment=pango.ALIGN_LEFT,
349 wrap_width=None):
350 '''
351 Render text for function L{ I{draw_text} <draw_text>}, you can use this function individually.
352
353 @param cr: Cairo context.
354 @param markup: Pango markup string.
355 @param x: X coordinate of draw area.
356 @param y: Y coordinate of draw area.
357 @param w: Width of draw area.
358 @param h: Height of draw area.
359 @param text_size: Text size, default is DEFAULT_FONT_SIZE.
360 @param text_color: Text color, default is \"#000000\".
361 @param text_font: Text font, default is DEFAULT_FONT.
362 @param alignment: Font alignment option, default is pango.ALIGN_LEFT. You can set pango.ALIGN_MIDDLE or pango.ALIGN_RIGHT.
363 @param wrap_width: Wrap width of text, default is None.
364 '''
365
366 context = pangocairo.CairoContext(cr)
367
368
369 layout = context.create_layout()
370 layout.set_font_description(pango.FontDescription("%s %s" % (text_font, text_size)))
371 layout_set_markup(layout, markup)
372 layout.set_alignment(alignment)
373 if wrap_width == None:
374 layout.set_single_paragraph_mode(True)
375 layout.set_width(w * pango.SCALE)
376 layout.set_ellipsize(pango.ELLIPSIZE_END)
377 else:
378 layout.set_width(wrap_width * pango.SCALE)
379 layout.set_wrap(pango.WRAP_WORD)
380 (text_width, text_height) = layout.get_pixel_size()
381
382
383 cr.move_to(x, y + (h - text_height) / 2)
384 cr.set_source_rgb(*color_hex_to_cairo(text_color))
385 context.update_layout(layout)
386 context.show_layout(layout)
387
388 -def draw_line(cr, sx, sy, ex, ey, line_width=1, antialias_status=cairo.ANTIALIAS_NONE):
389 '''
390 Draw line.
391
392 @param cr: Cairo context.
393 @param sx: Souce X coordinate.
394 @param sy: Souce Y coordinate.
395 @param ex: Target X coordinate.
396 @param ey: Target Y coordinate.
397 @param line_width: Line width, default is 1 pixel.
398 @param antialias_status: Antialias status, default is cairo.ANTIALITAS_NONE.
399 '''
400
401 antialias = cr.get_antialias()
402
403
404 cr.set_line_width(line_width)
405 cr.set_antialias(antialias_status)
406 cr.move_to(sx, sy)
407 cr.line_to(ex, ey)
408 cr.stroke()
409
410
411 cr.set_antialias(antialias)
412
413 -def draw_vlinear(cr, x, y, w, h, color_infos, radius=0, top_to_bottom=True):
414 '''
415 Draw linear area vertically.
416
417 @param cr: Cairo context.
418 @param x: X coordinate of draw area.
419 @param y: Y coordinate of draw area.
420 @param w: Width of draw area.
421 @param h: Height of draw area.
422 @param color_infos: A list of ColorInfo, ColorInfo format: (color_stop_position, (color_hex_value, color_alpha))
423 @param radius: Rectangle corner radious.
424 @param top_to_bottom: Draw direction, default is from top to bottom, function will draw from bottom to top if set option as False.
425 '''
426 with cairo_state(cr):
427
428 cr.translate(0, y)
429
430 if top_to_bottom:
431 pat = cairo.LinearGradient(0, 0, 0, h)
432 else:
433 pat = cairo.LinearGradient(0, h, 0, 0)
434
435 for (pos, color_info) in color_infos:
436 add_color_stop_rgba(pat, pos, color_info)
437 cr.set_operator(cairo.OPERATOR_OVER)
438 cr.set_source(pat)
439 draw_round_rectangle(cr, x, 0, w, h, radius)
440
441 cr.fill()
442
443 -def draw_hlinear(cr, x, y, w, h, color_infos, radius=0, left_to_right=True):
444 '''
445 Draw linear area horticulturally.
446
447 @param cr: Cairo context.
448 @param x: X coordinate of draw area.
449 @param y: Y coordinate of draw area.
450 @param w: Width of draw area.
451 @param h: Height of draw area.
452 @param color_infos: A list of ColorInfo, ColorInfo format: (color_stop_position, (color_hex_value, color_alpha))
453 @param radius: Rectangle corner radious.
454 @param left_to_right: Draw direction, default is from left to right, function will draw from right to left if set option as False.
455 '''
456 with cairo_state(cr):
457
458 cr.translate(x, 0)
459
460 if left_to_right:
461 pat = cairo.LinearGradient(0, 0, w, 0)
462 else:
463 pat = cairo.LinearGradient(w, 0, 0, 0)
464 for (pos, color_info) in color_infos:
465 add_color_stop_rgba(pat, pos, color_info)
466 cr.set_operator(cairo.OPERATOR_OVER)
467 cr.set_source(pat)
468 draw_round_rectangle(cr, 0, y, w, h, radius)
469 cr.fill()
470
472 '''
473 Expose linear background.
474
475 @param widget: Gtk.Widget instance.
476 @param event: Expose event.
477 @param color_infos: A list of ColorInfo, ColorInfo format: (color_stop_position, (color_hex_value, color_alpha))
478 '''
479
480 cr = widget.window.cairo_create()
481 rect = widget.allocation
482
483
484 draw_vlinear(cr, rect.x, rect.y, rect.width, rect.height, color_infos)
485
486
487 propagate_expose(widget, event)
488
489 return True
490
492 '''
493 Draw window shadow.
494
495 @param cr: Cairo context.
496 @param x: X coordinate of draw area.
497 @param y: Y coordinate of draw area.
498 @param w: Width of draw area.
499 @param h: Height of draw area.
500 @param r: Radious of window shadow corner.
501 @param p: Padding between window shadow and window frame.
502 @param color_window_shadow: theme.DyanmicShadowColor.
503 '''
504 color_infos = color_window_shadow.get_color_info()
505 with cairo_state(cr):
506
507 cr.rectangle(x, y, r - 1, r - 1)
508 cr.rectangle(x + r - 1, y, 1, r - 2)
509 cr.rectangle(x, y + r - 1, r - 2, 1)
510
511 cr.rectangle(x + w - r + 1, y, r - 1, r - 1)
512 cr.rectangle(x + w - r, y, 1, r - 2)
513 cr.rectangle(x + w - r + 2, y + r - 1, r - 2, 1)
514
515 cr.rectangle(x, y + h - r + 1, r - 1, r - 1)
516 cr.rectangle(x + r - 1, y + h - r + 2, 1, r - 2)
517 cr.rectangle(x, y + h - r, r - 2, 1)
518
519 cr.rectangle(x + w - r + 1, y + h - r + 1, r - 1, r - 1)
520 cr.rectangle(x + w - r, y + h - r + 2, 1, r - 2)
521 cr.rectangle(x + w - r + 2, y + h - r, r - 2, 1)
522
523 cr.clip()
524
525
526 draw_radial_round(cr, x + r, y + r, r, color_infos)
527 draw_radial_round(cr, x + r, y + h - r, r, color_infos)
528 draw_radial_round(cr, x + w - r, y + r, r, color_infos)
529 draw_radial_round(cr, x + w - r, y + h - r, r, color_infos)
530
531 with cairo_state(cr):
532
533 cr.rectangle(x, y + r, p, h - r * 2)
534 cr.rectangle(x + w - p, y + r, p, h - r * 2)
535 cr.rectangle(x + r, y, w - r * 2, p)
536 cr.rectangle(x + r, y + h - p, w - r * 2, p)
537 cr.clip()
538
539
540 draw_vlinear(
541 cr,
542 x + r, y,
543 w - r * 2, r, color_infos)
544 draw_vlinear(
545 cr,
546 x + r, y + h - r,
547 w - r * 2, r, color_infos, 0, False)
548 draw_hlinear(
549 cr,
550 x, y + r,
551 r, h - r * 2, color_infos)
552 draw_hlinear(
553 cr,
554 x + w - r, y + r,
555 r, h - r * 2, color_infos, 0, False)
556
558 '''
559 Draw radial round.
560
561 @param cr: Cairo context.
562 @param x: X coordinate of draw area.
563 @param y: Y coordinate of draw area.
564 @param r: Radious of radial round.
565 @param color_infos: A list of ColorInfo, ColorInfo format: (color_stop_position, (color_hex_value, color_alpha))
566 '''
567 radial = cairo.RadialGradient(x, y, r, x, y, 0)
568 for (pos, color_info) in color_infos:
569 add_color_stop_rgba(radial, pos, color_info)
570 cr.arc(x, y, r, 0, 2 * math.pi)
571 cr.set_source(radial)
572 cr.fill()
573
575 '''
576 Draw blank mask, use for default mask function.
577
578 @param cr: Cairo context.
579 @param x: X coordiante of rectangle area.
580 @param y: Y coordiante of rectangle area.
581 @param w: Width of rectangle area.
582 @param h: Width of rectangle area.
583 '''
584 pass
585