screenlets.drawing

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