Package screenlets :: Module drawing
[hide private]
[frames] | no frames]

Source Code for Module screenlets.drawing

  1  # This application is released under the GNU General Public License  
  2  # v3 (or, at your option, any later version). You can find the full  
  3  # text of the license under http://www.gnu.org/licenses/gpl.txt.  
  4  # By using, editing and/or distributing this software you agree to  
  5  # the terms and conditions of this license.  
  6  # Thank you for using free software! 
  7   
  8  # Screenlets Drawing Helder Fraga aka Whise <helder.fraga@hotmail.com> 
  9   
 10   
 11  import gtk, cairo, pango, math 
 12   
13 -class Drawing(object):
14 """Contains static drawing functions.""" 15 16 # ---------------------------------------------------------------------- 17 # Screenlet's Drawing functions 18 # ---------------------------------------------------------------------- 19 p_context = None # PangoContext 20 p_layout = None # PangoLayout 21
22 - def get_text_width(self, ctx, text, font):
23 """Returns the pixel width of a given text""" 24 ctx.save() 25 if self.p_layout == None : 26 27 self.p_layout = ctx.create_layout() 28 else: 29 30 ctx.update_layout(self.p_layout) 31 if self.p_fdesc == None:self.p_fdesc = pango.FontDescription() 32 else: pass 33 self.p_fdesc.set_family_static(font) 34 self.p_layout.set_font_description(self.p_fdesc) 35 self.p_layout.set_text(text) 36 extents, lextents = self.p_layout.get_pixel_extents() 37 ctx.restore() 38 return extents[2]
39
40 - def get_text_height(self, ctx, text, font):
41 """Returns the pixel height of a given text""" 42 ctx.save() 43 if self.p_layout == None : 44 45 self.p_layout = ctx.create_layout() 46 else: 47 48 ctx.update_layout(self.p_layout) 49 if self.p_fdesc == None:self.p_fdesc = pango.FontDescription() 50 else: pass 51 self.p_fdesc.set_family_static(font) 52 self.p_layout.set_font_description(self.p_fdesc) 53 self.p_layout.set_text(text) 54 extents, lextents = self.p_layout.get_pixel_extents() 55 ctx.restore() 56 return extents[3]
57
58 - def get_text_line_count(self, ctx, text, font, size = None):
59 """Returns the line count of a given text""" 60 ctx.save() 61 if self.p_layout == None : 62 63 self.p_layout = ctx.create_layout() 64 else: 65 66 ctx.update_layout(self.p_layout) 67 if self.p_fdesc == None:self.p_fdesc = pango.FontDescription() 68 else: pass 69 self.p_fdesc.set_family_static(font) 70 if size is not None: 71 self.p_fdesc.set_size(size * pango.SCALE) 72 else: pass 73 self.p_layout.set_font_description(self.p_fdesc) 74 self.p_layout.set_text(text) 75 ctx.restore() 76 return self.p_layout.get_line_count()
77
78 - def get_text_line(self, ctx, text, font, line):
79 """Returns a line of a given text""" 80 ctx.save() 81 if self.p_layout == None : 82 83 self.p_layout = ctx.create_layout() 84 else: 85 86 ctx.update_layout(self.p_layout) 87 if self.p_fdesc == None:self.p_fdesc = pango.FontDescription() 88 else: pass 89 self.p_fdesc.set_family_static(font) 90 self.p_layout.set_font_description(self.p_fdesc) 91 self.p_layout.set_text(text) 92 ctx.restore() 93 return self.p_layout.get_line(line)
94
95 - def check_for_icon(self,icon):
96 try: 97 icontheme = gtk.icon_theme_get_default() 98 image = icontheme.load_icon (icon,32,32) 99 image = None 100 icontheme = None 101 return True 102 except: 103 return False
104
105 - def draw_text(self, ctx, text, x, y, font, size = None, width = 200, allignment=pango.ALIGN_LEFT,alignment=None,justify = False,weight = None, ellipsize = pango.ELLIPSIZE_NONE):
106 """Draws text""" 107 if size is not None: 108 size = int(size) 109 110 ctx.save() 111 ctx.translate(x, y) 112 if self.p_layout == None : 113 114 self.p_layout = ctx.create_layout() 115 else: 116 117 ctx.update_layout(self.p_layout) 118 if self.p_fdesc == None:self.p_fdesc = pango.FontDescription(font) 119 else: pass 120 # using "Ubuntu Bold 12" is new standard, detecting spaces is lousy, but no better idea 121 if font.find(" ") >= 0: 122 self.p_fdesc = pango.FontDescription(font) 123 # but we should keep old standard describing just font family "Ubuntu" 124 # this is probably not needed, but max compatibility!!! 125 else: 126 self.p_fdesc.set_family_static(font) 127 if size is not None: 128 self.p_fdesc.set_size(size * pango.SCALE) 129 if weight is not None: 130 self.p_fdesc.set_weight(weight) 131 self.p_layout.set_font_description(self.p_fdesc) 132 self.p_layout.set_width(width * pango.SCALE) 133 self.p_layout.set_alignment(allignment) 134 if alignment != None:self.p_layout.set_alignment(alignment) 135 self.p_layout.set_justify(justify) 136 self.p_layout.set_ellipsize(ellipsize) 137 self.p_layout.set_markup(text) 138 ctx.show_layout(self.p_layout) 139 ctx.restore()
140 141
142 - def draw_circle(self,ctx,x,y,width,height,fill=True):
143 """Draws a circule""" 144 ctx.save() 145 ctx.translate(x, y) 146 ctx.arc(width/2,height/2,min(height,width)/2,0,2*math.pi) 147 if fill:ctx.fill() 148 else: ctx.stroke() 149 ctx.restore()
150 151
152 - def draw_triangle(self,ctx,x,y,width,height,fill=True):
153 """Draws a circule""" 154 ctx.save() 155 ctx.translate(x, y) 156 ctx.move_to(width-(width/3), height/3) 157 ctx.line_to(width,height) 158 ctx.rel_line_to(-(width-(width/3)), 0) 159 ctx.close_path() 160 if fill:ctx.fill() 161 else: ctx.stroke() 162 ctx.restore()
163
164 - def draw_line(self,ctx,start_x,start_y,end_x,end_y,line_width = 1,close=False,preserve=False):
165 """Draws a line""" 166 ctx.save() 167 ctx.move_to(start_x, start_y) 168 ctx.set_line_width(line_width) 169 ctx.rel_line_to(end_x, end_y) 170 if close : ctx.close_path() 171 if preserve: ctx.stroke_preserve() 172 else: ctx.stroke() 173 ctx.restore()
174
175 - def draw_rectangle(self,ctx,x,y,width,height,fill=True):
176 """Draws a rectangle""" 177 ctx.save() 178 ctx.translate(x, y) 179 ctx.rectangle (0,0,width,height) 180 if fill:ctx.fill() 181 else: ctx.stroke() 182 ctx.restore()
183 184
185 - def draw_rectangle_advanced (self, ctx, x, y, width, height, rounded_angles=(0,0,0,0), fill=True, border_size=0, border_color=(0,0,0,1), shadow_size=0, shadow_color=(0,0,0,0.5)):
186 '''with this funktion you can create a rectangle in advanced mode''' 187 ctx.save() 188 ctx.translate(x, y) 189 s = shadow_size 190 w = width 191 h = height 192 rounded = rounded_angles 193 if shadow_size > 0: 194 ctx.save() 195 #top shadow 196 gradient = cairo.LinearGradient(0,s,0,0) 197 gradient.add_color_stop_rgba(0,*shadow_color) 198 gradient.add_color_stop_rgba(1,shadow_color[0], shadow_color[1], shadow_color[2], 0) 199 ctx.set_source(gradient) 200 ctx.rectangle(s+rounded[0],0, w-rounded[0]-rounded[1], s) 201 ctx.fill() 202 203 #bottom 204 gradient = cairo.LinearGradient(0, s+h, 0, h+(s*2)) 205 gradient.add_color_stop_rgba(0,*shadow_color) 206 gradient.add_color_stop_rgba(1,shadow_color[0], shadow_color[1], shadow_color[2], 0) 207 ctx.set_source(gradient) 208 ctx.rectangle(s+rounded[2], s+h, w-rounded[2]-rounded[3], s) 209 ctx.fill() 210 211 #left 212 gradient = cairo.LinearGradient(s, 0, 0, 0) 213 gradient.add_color_stop_rgba(0,*shadow_color) 214 gradient.add_color_stop_rgba(1,shadow_color[0], shadow_color[1], shadow_color[2], 0) 215 ctx.set_source(gradient) 216 ctx.rectangle(0, s+rounded[0], s, h-rounded[0]-rounded[2]) 217 ctx.fill() 218 219 #right 220 gradient = cairo.LinearGradient(s+w, 0, (s*2)+w, 0) 221 gradient.add_color_stop_rgba(0,*shadow_color) 222 gradient.add_color_stop_rgba(1,shadow_color[0], shadow_color[1], shadow_color[2], 0) 223 ctx.set_source(gradient) 224 ctx.rectangle(s+w, s+rounded[1], s, h-rounded[1]-rounded[3]) 225 ctx.fill() 226 ctx.restore 227 228 #top-left 229 gradient = cairo.RadialGradient(s+rounded[0], s+rounded[0], rounded[0], s+rounded[0], s+rounded[0], s+rounded[0]) 230 gradient.add_color_stop_rgba(0,*shadow_color) 231 gradient.add_color_stop_rgba(1,shadow_color[0], shadow_color[1], shadow_color[2], 0) 232 ctx.set_source(gradient) 233 ctx.new_sub_path() 234 ctx.arc(s,s,s, -math.pi, -math.pi/2) 235 ctx.line_to(s+rounded[0],0) 236 ctx.line_to(s+rounded[0],s) 237 ctx.arc_negative(s+rounded[0],s+rounded[0],rounded[0], -math.pi/2, math.pi) 238 ctx.line_to(0, s+rounded[0]) 239 ctx.close_path() 240 ctx.fill() 241 242 #top-right 243 gradient = cairo.RadialGradient(w+s-rounded[1], s+rounded[1], rounded[1], w+s-rounded[1], s+rounded[1], s+rounded[1]) 244 gradient.add_color_stop_rgba(0,*shadow_color) 245 gradient.add_color_stop_rgba(1,shadow_color[0], shadow_color[1], shadow_color[2], 0) 246 ctx.set_source(gradient) 247 ctx.new_sub_path() 248 ctx.arc(w+s,s,s, -math.pi/2, 0) 249 ctx.line_to(w+(s*2), s+rounded[1]) 250 ctx.line_to(w+s, s+rounded[1]) 251 ctx.arc_negative(w+s-rounded[1], s+rounded[1], rounded[1], 0, -math.pi/2) 252 ctx.line_to(w+s-rounded[1], 0) 253 ctx.close_path() 254 ctx.fill() 255 256 #bottom-left 257 gradient = cairo.RadialGradient(s+rounded[2], h+s-rounded[2], rounded[2], s+rounded[2], h+s-rounded[2], s+rounded[2]) 258 gradient.add_color_stop_rgba(0,*shadow_color) 259 gradient.add_color_stop_rgba(1,shadow_color[0], shadow_color[1], shadow_color[2], 0) 260 ctx.set_source(gradient) 261 ctx.new_sub_path() 262 ctx.arc(s,h+s,s, math.pi/2, math.pi) 263 ctx.line_to(0, h+s-rounded[2]) 264 ctx.line_to(s, h+s-rounded[2]) 265 ctx.arc_negative(s+rounded[2], h+s-rounded[2], rounded[2], -math.pi, math.pi/2) 266 ctx.line_to(s+rounded[2], h+(s*2)) 267 ctx.close_path() 268 ctx.fill() 269 270 #bottom-right 271 gradient = cairo.RadialGradient(w+s-rounded[3], h+s-rounded[3], rounded[3], w+s-rounded[3], h+s-rounded[3], s+rounded[3]) 272 gradient.add_color_stop_rgba(0,*shadow_color) 273 gradient.add_color_stop_rgba(1,shadow_color[0], shadow_color[1], shadow_color[2], 0) 274 ctx.set_source(gradient) 275 ctx.new_sub_path() 276 ctx.arc(w+s,h+s,s, 0, math.pi/2) 277 ctx.line_to(w+s-rounded[3], h+(s*2)) 278 ctx.line_to(w+s-rounded[3], h+s) 279 ctx.arc_negative(s+w-rounded[3], s+h-rounded[3], rounded[3], math.pi/2, 0) 280 ctx.line_to((s*2)+w, s+h-rounded[3]) 281 ctx.close_path() 282 ctx.fill() 283 ctx.restore() 284 285 #the content starts here! 286 ctx.translate(s, s) 287 else: 288 ctx.translate(border_size, border_size) 289 290 #and now the rectangle 291 if fill: 292 ctx.line_to(0, rounded[0]) 293 ctx.arc(rounded[0], rounded[0], rounded[0], math.pi, -math.pi/2) 294 ctx.line_to(w-rounded[1], 0) 295 ctx.arc(w-rounded[1], rounded[1], rounded[1], -math.pi/2, 0) 296 ctx.line_to(w, h-rounded[3]) 297 ctx.arc(w-rounded[3], h-rounded[3], rounded[3], 0, math.pi/2) 298 ctx.line_to(rounded[2], h) 299 ctx.arc(rounded[2], h-rounded[2], rounded[2], math.pi/2, -math.pi) 300 ctx.close_path() 301 ctx.fill() 302 303 if border_size > 0: 304 ctx.save() 305 ctx.line_to(0, rounded[0]) 306 ctx.arc(rounded[0], rounded[0], rounded[0], math.pi, -math.pi/2) 307 ctx.line_to(w-rounded[1], 0) 308 ctx.arc(w-rounded[1], rounded[1], rounded[1], -math.pi/2, 0) 309 ctx.line_to(w, h-rounded[3]) 310 ctx.arc(w-rounded[3], h-rounded[3], rounded[3], 0, math.pi/2) 311 ctx.line_to(rounded[2], h) 312 ctx.arc(rounded[2], h-rounded[2], rounded[2], math.pi/2, -math.pi) 313 ctx.close_path() 314 ctx.set_source_rgba(*border_color) 315 ctx.set_line_width(border_size) 316 ctx.stroke() 317 ctx.restore() 318 ctx.restore()
319
320 - def draw_rounded_rectangle(self,ctx,x,y,rounded_angle,width,height,round_top_left = True ,round_top_right = True,round_bottom_left = True,round_bottom_right = True, fill=True):
321 """Draws a rounded rectangle""" 322 ctx.save() 323 ctx.translate(x, y) 324 padding=0 # Padding from the edges of the window 325 rounded=rounded_angle # How round to make the edges 20 is ok 326 w = width 327 h = height 328 329 # Move to top corner 330 ctx.move_to(0+padding+rounded, 0+padding) 331 332 # Top right corner and round the edge 333 if round_top_right: 334 ctx.line_to(w-padding-rounded, 0+padding) 335 ctx.arc(w-padding-rounded, 0+padding+rounded, rounded, (math.pi/2 )+(math.pi) , 0) 336 else: 337 ctx.line_to(w-padding, 0+padding) 338 339 # Bottom right corner and round the edge 340 if round_bottom_right: 341 ctx.line_to(w-padding, h-padding-rounded) 342 ctx.arc(w-padding-rounded, h-padding-rounded, rounded, 0, math.pi/2) 343 else: 344 ctx.line_to(w-padding, h-padding) 345 # Bottom left corner and round the edge. 346 if round_bottom_left: 347 ctx.line_to(0+padding+rounded, h-padding) 348 ctx.arc(0+padding+rounded, h-padding-rounded, rounded,math.pi/2, math.pi) 349 else: 350 ctx.line_to(0+padding, h-padding) 351 # Top left corner and round the edge 352 if round_top_left: 353 ctx.line_to(0+padding, 0+padding+rounded) 354 ctx.arc(0+padding+rounded, 0+padding+rounded, rounded, math.pi, (math.pi/2 )+(math.pi)) 355 else: 356 ctx.line_to(0+padding, 0+padding) 357 # Fill in the shape. 358 if fill:ctx.fill() 359 else: ctx.stroke() 360 ctx.restore()
361
362 - def draw_quadrant_shadow(self, ctx, x, y, from_r, to_r, quad, col):
363 gradient = cairo.RadialGradient(x,y,from_r,x,y,to_r) 364 gradient.add_color_stop_rgba(0,col[0],col[1],col[2],col[3]) 365 gradient.add_color_stop_rgba(1,col[0],col[1],col[2],0) 366 ctx.set_source(gradient) 367 ctx.new_sub_path() 368 if quad==0: ctx.arc(x,y,to_r, -math.pi, -math.pi/2) 369 elif quad==1: ctx.arc(x,y,to_r, -math.pi/2, 0) 370 elif quad==2: ctx.arc(x,y,to_r, math.pi/2, math.pi) 371 elif quad==3: ctx.arc(x,y,to_r, 0, math.pi/2) 372 ctx.line_to(x,y) 373 ctx.close_path() 374 ctx.fill()
375 376 # side: 0 - left, 1 - right, 2 - top, 3 - bottom
377 - def draw_side_shadow(self, ctx, x, y, w, h, side, col):
378 gradient = None 379 if side==0: 380 gradient = cairo.LinearGradient(x+w,y,x,y) 381 elif side==1: 382 gradient = cairo.LinearGradient(x,y,x+w,y) 383 elif side==2: 384 gradient = cairo.LinearGradient(x,y+h,x,y) 385 elif side==3: 386 gradient = cairo.LinearGradient(x,y,x,y+h) 387 if gradient: 388 gradient.add_color_stop_rgba(0,col[0],col[1],col[2],col[3]) 389 gradient.add_color_stop_rgba(1,col[0],col[1],col[2],0) 390 ctx.set_source(gradient) 391 ctx.rectangle(x,y,w,h) 392 ctx.fill()
393
394 - def draw_shadow(self, ctx, x, y, w, h, shadow_size, col):
395 s = shadow_size 396 #r = self.layout.window.radius 397 r = s 398 rr = r+s 399 h = h-r 400 if h < 2*r: h = 2*r 401 402 # TODO: Offsets [Will need to change all places doing 403 # x+=shadow_size/2 or such to use the offsets then 404 ctx.save() 405 ctx.translate(x,y) 406 407 # Top Left 408 self.draw_quadrant_shadow(ctx, rr, rr, 0, rr, 0, col) 409 # Left 410 self.draw_side_shadow(ctx, 0, rr, r+s, h-2*r, 0, col) 411 # Bottom Left 412 self.draw_quadrant_shadow(ctx, rr, h-r+s, 0, rr, 2, col) 413 # Bottom 414 self.draw_side_shadow(ctx, rr, h-r+s, w-2*r, s+r, 3, col) 415 # Bottom Right 416 self.draw_quadrant_shadow(ctx, w-r+s, h-r+s, 0, rr, 3, col) 417 # Right 418 self.draw_side_shadow(ctx, w-r+s, rr, s+r, h-2*r, 1, col) 419 # Top Right 420 self.draw_quadrant_shadow(ctx, w-r+s, rr, 0, rr, 1, col) 421 # Top 422 self.draw_side_shadow(ctx, rr, 0, w-2*r, s+r, 2, col) 423 424 ctx.restore()
425 426 427
428 - def get_image_size(self,pix):
429 """Gets a picture width and height""" 430 431 pixbuf = gtk.gdk.pixbuf_new_from_file(pix) 432 iw = pixbuf.get_width() 433 ih = pixbuf.get_height() 434 puxbuf = None 435 return iw,ih
436
437 - def draw_image(self,ctx,x,y, pix):
438 """Draws a picture from specified path""" 439 440 ctx.save() 441 ctx.translate(x, y) 442 pixbuf = gtk.gdk.pixbuf_new_from_file(pix) 443 format = cairo.FORMAT_RGB24 444 if pixbuf.get_has_alpha(): 445 format = cairo.FORMAT_ARGB32 446 447 iw = pixbuf.get_width() 448 ih = pixbuf.get_height() 449 image = cairo.ImageSurface(format, iw, ih) 450 image = ctx.set_source_pixbuf(pixbuf, 0, 0) 451 452 ctx.paint() 453 puxbuf = None 454 image = None 455 ctx.restore()
456
457 - def draw_icon(self,ctx,x,y, pix,width=32,height=32):
458 """Draws a gtk icon """ 459 460 ctx.save() 461 ctx.translate(x, y) 462 icontheme = gtk.icon_theme_get_default() 463 image = icontheme.load_icon (pix,width,height) 464 ctx.set_source_pixbuf(image, 0, 0) 465 ctx.paint() 466 icontheme = None 467 image = None 468 ctx.restore()
469
470 - def draw_scaled_image(self,ctx,x,y, pix, w, h):
471 """Draws a picture from specified path with a certain width and height""" 472 w = int(w) 473 h = int(h) 474 475 ctx.save() 476 ctx.translate(x, y) 477 pixbuf = gtk.gdk.pixbuf_new_from_file(pix).scale_simple(w,h,gtk.gdk.INTERP_HYPER) 478 format = cairo.FORMAT_RGB24 479 if pixbuf.get_has_alpha(): 480 format = cairo.FORMAT_ARGB32 481 482 iw = pixbuf.get_width() 483 ih = pixbuf.get_height() 484 image = cairo.ImageSurface(format, iw, ih) 485 486 matrix = cairo.Matrix(xx=iw/w, yy=ih/h) 487 image = ctx.set_source_pixbuf(pixbuf, 0, 0) 488 if image != None :image.set_matrix(matrix) 489 ctx.paint() 490 puxbuf = None 491 image = None 492 ctx.restore()
493