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

Source Code for Module screenlets.drawing

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