cairo学习笔记(初级入门)
Tofloor
poster avatar
z85525006
deepin
2012-02-15 08:26
Author
  1. #!/usr/bin/env python
  2. # coding:utf-8
  3. import gtk
  4. class App:
  5.     def __init__ (self):
  6.         window = gtk.Window(gtk.WINDOW_TOPLEVEL)
  7.         window.add_events(gtk.gdk.BUTTON_PRESS_MASK)
  8.         window.connect("expose_event", lambda w,e:self.on_expose_event(w,e))
  9.         window.connect("destroy", lambda w:gtk.main_quit())
  10.         window.show_all()
  11.         gtk.main()
  12.     def on_expose_event(self, widget, event,data=None):
  13.         cr = widget.window.cairo_create()
  14.         cr.set_source_rgb(0, 0, 0)
  15.         cr.set_line_width(100)
  16.         #画线段的起点和终点
  17.         cr.move_to(12,12)
  18.         cr.line_to(12,52)
  19.                
  20.         cr.stroke()
  21.         
  22.         return True
  23. App()
Copy the Code
==========================================
  1. #!/usr/bin/env python
  2. # coding:utf-8
  3. import cairo
  4. import gtk
  5. class App:
  6.     def __init__ (self):
  7.         window = gtk.Window(gtk.WINDOW_TOPLEVEL)
  8.         window.add_events(gtk.gdk.BUTTON_PRESS_MASK)
  9.         window.connect("expose_event", lambda w,e:self.expose_event(w,e))
  10.         window.connect("destroy", lambda w:gtk.main_quit())
  11.         window.show_all()
  12.         gtk.main()
  13.     def expose_event(self, widget, event):
  14.         cr = widget.window.cairo_create()
  15.         rect = widget.allocation
  16.         #宽度
  17.         cr.set_line_width(9)
  18.         #
  19.         
  20.         cr.arc(rect.width/2, rect.height/2, rect.width/2-10, 0,2*1.14)
  21.         #stroke_preserve函数将它绘制的路径保存在cairo环境中
  22.         #描绘stroke绘制形状的轮廓.
  23.         cr.set_source_rgb(0.3, 0.4, 0.6)
  24.         cr.stroke_preserve()
  25.         
  26.         #填充fill 向形状内部灌注颜色
  27.         cr.set_source_rgb(0.69, 0.19, 0)
  28.         cr.fill()
  29.         #注:
  30.         #  cr.stroke_preserve () 函数会将它绘制的路径依然保存在 cairo 环境中,
  31.         #而 cr.stroke () 所绘制的路径,在绘制完成后,就从 cairo的环境中清除了
  32.         return True
  33. App()
Copy the Code
产生疑问:  什么情况下使用cr.stroke_preserve和cr.stroke? 如何灵活的使用,需要注意什么?(明天问王勇同学)   :
(王勇)答:
======================================
虚线 (Dash)

每条线都可以用不同的虚线笔 (dash pen) 来画。虚线模式是通过 cairo_set_dash () 函数来设定。模式类型通过一个数组来定义,数组中的值均为正数,它们用于设置虚线的虚部分与实部分。数组的长度与偏移量可以在程序中设定。如果数组的长度 为 0,虚线模式就是被禁止了,那所绘制的线是实线。如果数组长度为 1,则对应着虚实均匀分布的虚线模式。偏移量是用来设置在虚线的始端在一个虚线周期(包含一个实部单元和一个虚部单元)内的起始位置。
  1. #!/usr/bin/env python
  2. # coding:utf-8
  3. import cairo
  4. import gtk
  5. #虚线 dash
  6. class App:
  7.     def __init__ (self):
  8.         window = gtk.Window(gtk.WINDOW_TOPLEVEL)
  9.         window.add_events(gtk.gdk.BUTTON_PRESS_MASK)
  10.         window.connect("expose_event", lambda w,e:self.expose_event(w,e))
  11.         window.connect("destroy", lambda w:gtk.main_quit())
  12.         window.show_all()
  13.         gtk.main()
  14.     def expose_event(self, widget, event):
  15.         cr = widget.window.cairo_create()
  16.         cr.set_source_rgba(0, 0, 0.1)
  17.         cr.set_line_width(15)
  18.         
  19.         cr.set_dash([4.0,1.0],0)
  20.         cr.move_to(40,60)
  21.         cr.line_to(360, 360)
  22.         cr.stroke()
  23.         return True
  24. App()
Copy the Code
虚线=========
  1. #!/usr/bin/env python
  2. # coding:utf-8
  3. import cairo
  4. import gtk
  5. #虚线 dash
  6. class App:
  7.     def __init__ (self):
  8.         window = gtk.Window(gtk.WINDOW_TOPLEVEL)
  9.         window.add_events(gtk.gdk.BUTTON_PRESS_MASK)
  10.         
  11.         window.add_events(gtk.gdk.BUTTON_PRESS_MASK)
  12.         window.add_events(gtk.gdk.BUTTON_RELEASE_MASK)
  13.         window.add_events(gtk.gdk.POINTER_MOTION_MASK)
  14.          
  15.         window.connect("expose_event", lambda w,e:self.expose_event(w,e))
  16.         window.connect("button-press-event", lambda w,e:self.press_event(w,e))
  17.         window.connect("button-release-event", lambda w,e:self.release_event(w,e))
  18.         window.connect("motion-notify-event", lambda w,e:self.motion_event(w,e))
  19.         
  20.         window.connect("destroy", lambda w:gtk.main_quit())
  21.         self.state = 0
  22.         self.x = 0
  23.         self.y = 0
  24.         window.show_all()
  25.         gtk.main()
  26.         
  27.     def motion_event(self, widget, event):
  28.         if self.state == 1:
  29.             cr = widget.window.cairo_create()
  30.             cr.set_source_rgba(1, 0, 0)
  31.             cr.set_line_width(5)
  32.         
  33.             cr.move_to(self.x, self.y)
  34.             cr.line_to(event.x, event.y)
  35.             cr.stroke()
  36.             self.x = event.x
  37.             self.y = event.y
  38.             
  39.             
  40.     def release_event(self, widget, event):
  41.         self.state = 0
  42.         
  43.     def press_event(self, widget, event):
  44.         if event.button == 1:
  45.             self.state = 1
  46.             self.x  = event.x
  47.             self.y   = event.y
  48.             
  49.     def expose_event(self, widget, event):
  50.         cr = widget.window.cairo_create()
  51.         cr.set_source_rgba(0, 0, 0.1)
  52.         cr.set_line_width(5)
  53.         
  54.         cr.set_dash([5,15, 15, 14,12,32,23], 4)
  55.         cr.move_to(40,60)
  56.         cr.line_to(360, 360)
  57.         
  58.         cr.stroke()
  59.         return True
  60. App()
Copy the Code

线帽 (Line caps)====
  1. #!/usr/bin/env python
  2. # coding:utf-8
  3. import cairo
  4. import gtk
  5. #虚线 dash
  6. class App:
  7.     def __init__ (self):
  8.         window = gtk.Window(gtk.WINDOW_TOPLEVEL)
  9.    
  10.         window.connect("expose_event", lambda w,e:self.expose_event(w,e))        
  11.         window.connect("destroy", lambda w:gtk.main_quit())
  12.         window.show_all()
  13.         gtk.main()
  14.     def expose_event(self, widget, event):
  15.         
  16.         cr = widget.window.cairo_create()
  17.         
  18.         cr.set_source_rgba(0, 0, 0, 1)
  19.         #设置线的宽度为 10px
  20.         cr.set_line_width(10)
  21.         #线帽 (Line caps)
  22.         #cairo.LINE_CAP_SQUARE 头: 正的
  23.         #cairo.LINE_CAP_ROUND  头: 半圆
  24.         #cairo.LINE_CAP_BUTT   头: 无
  25.         cr.set_line_cap(cairo.LINE_CAP_BUTT)
  26.         cr.move_to(40, 60)
  27.         cr.line_to(360, 60)
  28.         cr.stroke()
  29.         
  30.         cr.set_line_cap(cairo.LINE_CAP_ROUND) #半圆
  31.         cr.move_to(40, 140)
  32.         cr.line_to(360, 150)
  33.         cr.stroke()
  34.         
  35.         cr.set_line_cap(cairo.LINE_CAP_SQUARE) #方形
  36.         cr.move_to(40, 240)
  37.         cr.line_to(360, 240)
  38.         cr.stroke()
  39.         cr.set_line_width(1.5)
  40.         cr.move_to(40, 40)
  41.         cr.line_to(40, 260)
  42.         cr.stroke()
  43.         
  44.         cr.move_to(360, 40)
  45.         cr.line_to(360,260)
  46.         cr.stroke()
  47.         
  48.         cr.move_to(365, 40)
  49.         cr.line_to(365, 260)
  50.         cr.stroke()
  51.         return True
  52. App()
Copy the Code
http://liyanrui.is-programmer.co ... torial-04.7729.html
  1. #!/usr/bin/env python
  2. # coding:utf-8
  3. import cairo
  4. import gtk
  5. #虚线 dash
  6. class App:
  7.     def __init__ (self):
  8.         window = gtk.Window(gtk.WINDOW_TOPLEVEL)
  9.    
  10.         window.connect("expose_event", lambda w,e:self.expose_event(w,e))        
  11.         window.connect("destroy", lambda w:gtk.main_quit())
  12.         window.show_all()
  13.    
  14.     def expose_event(self, widget, event):
  15.         cr = widget.window.cairo_create()
  16.         cr.set_source_rgb(0.1, 0, 0)
  17.         
  18.         # x,y,宽,高
  19.         cr.rectangle(30, 30, 100, 100)
  20.         cr.set_line_width(14)
  21.         # 线的交合(line joins)
  22.         # cairo.LINE_JOIN_MITER
  23.         # cairo.LINE_JOIN_BEVEL
  24.         # cairo.LINE_JOIN_ROUND
  25.         cr.set_line_join(cairo.LINE_JOIN_MITER)
  26.         cr.stroke()
  27.         
  28.         cr.rectangle(160, 30, 100, 100)
  29.         cr.set_line_width(14)
  30.         cr.set_line_join(cairo.LINE_JOIN_BEVEL)
  31.         cr.stroke()
  32.         
  33.         cr.rectangle(100, 160, 100, 100)
  34.         cr.set_line_width(14)
  35.         cr.set_line_join(cairo.LINE_JOIN_ROUND)
  36.         cr.stroke()
  37.         return True
  38.         
  39. App()
  40. gtk.main()
Copy the Code

渐变
  1. #!/usr/bin/env python
  2. # coding:utf-8
  3. import cairo
  4. import gtk
  5. #虚线 dash
  6. class App:
  7.     def __init__ (self):
  8.         window = gtk.Window(gtk.WINDOW_TOPLEVEL)
  9.         window.set_position(gtk.WIN_POS_CENTER)
  10.         window.set_title("图片处理")
  11.         window.set_default_size(270, 270)
  12.         window.connect("expose_event", lambda w,e:self.on_expose_event(w,e))     
  13.         window.connect("destroy", lambda w:gtk.main_quit())        
  14.         
  15.         self.surface1 = cairo.ImageSurface.create_from_png("/home/long/图片/linux.png")
  16.         self.surface2 = cairo.ImageSurface.create_from_png("/home/long/图片/linux.png")
  17.         self.surface3 = cairo.ImageSurface.create_from_png("/home/long/图片/linux.png")
  18.         self.surface4 = cairo.ImageSurface.create_from_png("/home/long/图片/linux.png")
  19.         window.set_default_size(300, 300)
  20.         window.set_app_paintable(True)
  21.         window.show_all()
  22.                
  23.         
  24.     def on_expose_event(self, widget, event):
  25.         cr = widget.window.cairo_create()
  26.         rect = widget.allocation
  27.         
  28.         pattern1 = cairo.SurfacePattern(self.surface1)
  29.         pattern2 = cairo.SurfacePattern(self.surface2)
  30.         pattern3 = cairo.SurfacePattern(self.surface3)
  31.         pattern4 = cairo.SurfacePattern(self.surface4)
  32.         #图案 pattern
  33.         cr.set_source(pattern1)
  34.         cr.get_source().set_extend(cairo.EXTEND_REPEAT)
  35.         cr.rectangle(20, 20, 100, 100)
  36.         cr.fill()
  37.         
  38.         cr.set_source(pattern2)
  39.         cr.get_source().set_extend(cairo.EXTEND_REPEAT)
  40.         cr.rectangle(20, 140, 100, 100)
  41.         cr.fill()
  42.         
  43.         cr.set_source(pattern3)
  44.         cr.get_source().set_extend(cairo.EXTEND_REPEAT)
  45.         cr.arc(200, 70, 50, 0, 2*3.14)
  46.         cr.fill()
  47.         
  48.         #渐变 Gradline
  49.         pat1 = cairo.LinearGradient(0.0, 0.0, 350.0, 350.0)
  50.         count = 1
  51.         j = 0.1
  52.         while j<1:
  53.             if count % 2:
  54.                 pat1.add_color_stop_rgb(j, 0, 0, 1)
  55.             else:
  56.                 pat1.add_color_stop_rgb(j, 1, 0, 0)
  57.                
  58.             j += 0.1
  59.             count += 1
  60.         
  61.         cr.rectangle(20, 20, 300, 300)
  62.         cr.set_source(pat1)
  63.         cr.fill()
  64.         pat2 = cairo.LinearGradient(0.0, 0.0, 350.0, 0.0)
  65.         i = 0.05
  66.         count = 1
  67.         
  68.         while i<0.95:
  69.             if count % 2:
  70.                 pat2.add_color_stop_rgb(i, 0, 0, 0)
  71.             else:
  72.                 pat2.add_color_stop_rgb(i, 0, 0, 1)
  73.             count += 1
  74.             i += 0.025
  75.         
  76.         cr.rectangle(20, 140, 300, 100)
  77.         cr.set_source(pat2)
  78.         cr.fill()
  79.         
  80.         pat3 = cairo.LinearGradient(20.0, 260.0, 20.0, 360.0)
  81.         
  82.         pat3.add_color_stop_rgb(0.1, 0, 0, 0)
  83.         pat3.add_color_stop_rgb(0.5, 1, 1, 0)
  84.         pat3.add_color_stop_rgb(0.9, 0, 0, 0)
  85.         cr.rectangle(20, 260, 300, 100)
  86.         cr.set_source(pat3)
  87.         cr.fill()
  88.         
  89. App()
  90. gtk.main()
Copy the Code

透明
  1. #!/usr/bin/env python
  2. # coding:utf-8
  3. import cairo
  4. import gtk
  5. class App:
  6.     def __init__ (self):
  7.         window = gtk.Window(gtk.WINDOW_TOPLEVEL)
  8.         window.set_position(gtk.WIN_POS_CENTER)
  9.         window.set_title("透明")
  10.         window.set_default_size(270, 270)
  11.         darea = gtk.DrawingArea()
  12.         window.add(darea)
  13.         darea.connect("expose_event", lambda w,e:self.on_expose_event(w,e))     
  14.         window.connect("destroy", lambda w:gtk.main_quit())        
  15.         #加载图片
  16.         self.image = cairo.ImageSurface.create_from_png("/home/long/图片/linux.png")
  17.         self.width = self.image.get_width()
  18.         self.height = self.image.get_height()
  19.         self.alpha = 1
  20.         self.dalta = 0.01
  21.         window.set_default_size(300, 300)
  22.         window.set_app_paintable(True)
  23.         
  24.         self.timeID = gtk.timeout_add(50, self.time_handler, window)
  25.         
  26.         window.show_all()
  27.                
  28.     def time_handler(self, widget):
  29.         #if widget.window == None:
  30.          #   return False
  31.         
  32.         widget.queue_draw()
  33.         
  34.         return True
  35.    
  36.     def on_expose_event(self, widget, event):
  37.         cr = widget.window.cairo_create()
  38.         i = 1
  39.         while i <=10:
  40.             cr.set_source_rgba(0, 0, 1, i*0.1)
  41.             cr.rectangle(50*i, 20, 40, 40)
  42.             cr.fill()
  43.             i += 1
  44.         
  45.         
  46.         
  47.         cr.set_source_surface(self.image, 10, 10)
  48.         cr.paint_with_alpha(self.alpha)
  49.         
  50.         self.alpha -= self.dalta
  51.         
  52.         if self.alpha <= 0:
  53.             self.alpha = 1
  54.             
  55.         return True
  56.    
  57. App()
  58. gtk.main()
Copy the Code
  1. #!/usr/bin/env python
  2. # coding:utf-8
  3. import cairo
  4. import gtk
  5. class App:
  6.     def __init__ (self):
  7.         window = gtk.Window(gtk.WINDOW_TOPLEVEL)
  8.         window.set_position(gtk.WIN_POS_CENTER)
  9.         window.set_title("等待的演示")
  10.         window.set_default_size(270, 270)
  11.         window.set_default_size(300, 300)
  12.         window.set_position(gtk.WIN_POS_CENTER)
  13.         
  14.         self.darea = gtk.ProgressBar()
  15.         self.count = 1
  16.         
  17.         self.darea.connect("expose_event", lambda w,e:self.on_expose_event(w,e))     
  18.         window.connect("destroy", lambda w:gtk.main_quit())        
  19.         
  20.         self.time_ID = gtk.timeout_add(100, self.time_handler,window)
  21.         
  22.         window.add(self.darea)
  23.         window.show_all()
  24.    
  25.     def time_handler(self, widget):
  26.         widget.queue_draw()
  27.         self.count += 1
  28.         print 'fsdfds'
  29.         return True
  30.     def on_expose_event(self, widget, event):
  31.         cr = widget.window.cairo_create()
  32.         rect = widget.allocation
  33.         
  34.         trs = [
  35.               [0.0, 0.15, 0.30, 0.5, 0.65, 0.80, 0.9, 1.0],
  36.               [1.0, 0.0, 0.15, 0.30, 0.5, 0.65, 0.8, 0.9],
  37.               [0.9, 1.0, 0.0, 0.15, 0.3, 0.5, 0.65, 0.8],
  38.               [0.8, 0.9, 1.0, 0.0, 0.15, 0.3, 0.5, 0.65],
  39.               [0.65, 0.8, 0.9, 1.0, 0.0, 0.15, 0.3, 0.5],
  40.               [0.5, 0.65, 0.8, 0.9, 1.0, 0.0, 0.15, 0.3],
  41.               [0.3, 0.5, 0.65, 0.8, 0.9, 1.0, 0.0, 0.15],
  42.               [0.15, 0.3, 0.5, 0.65, 0.8, 0.9, 1.0, 0.0]
  43.               ]
  44.         #设置坐标
  45.         cr.translate(rect.width/2, rect.height/2)
  46.         
  47.         self.i = 0
  48.         while self.i<8:
  49.             
  50.             cr.set_line_width(3)
  51.             # ROUND 半圆
  52.             cr.set_line_cap(cairo.LINE_CAP_ROUND)
  53.             cr.set_source_rgba(0, 0, 0, trs[self.count%8][self.i])
  54.             
  55.             cr.move_to(0.0, -10.0)
  56.             cr.line_to(0.0, -40.0)
  57.             #旋转变换, 每次在前一次的基础上继续逆时旋转 X 角度...
  58.             cr.rotate(3.14/4)
  59.             cr.stroke()
  60.             self.i += 1
  61.         return True
  62.    
  63. App()
  64. gtk.main()
Copy the Code
===============

合成 (Compositing) 可以将一些单独的源 (source) 所生成可视元素组合成到单幅图像中去,主要用于创建所有的可视元素作为同一场景的一部分这
样一种假象。合成在电影工业中被广为使用,用于创建人群、不寻常的世界等画面,因为这样的画面在现实中的制作代价非常昂贵甚至难以实现。

Cairo 图形库提供了 14 种不同的合成操作。
  1. #!/usr/bin/env python
  2. # coding:utf-8
  3. import cairo
  4. import gtk
  5. class App(object):
  6.     def __init__(self):
  7.         window = gtk.Window(gtk.WINDOW_TOPLEVEL)
  8.         window.set_position(gtk.WIN_POS_CENTER)
  9.         window.set_title("等待的演示")
  10.         window.set_default_size(800, 600)
  11.         window.set_position(gtk.WIN_POS_CENTER)
  12.         window.set_app_paintable(True)
  13.         
  14.         
  15.         window.connect("expose-event", lambda w,e:self.on_expose_event(w,e))  
  16.         window.connect("destroy", lambda w:gtk.main_quit())        
  17.         self.x = 20
  18.         
  19.         # window.add(self.darea)
  20.         window.show_all()
  21.         
  22.     def on_expose_event(self, widget, event):
  23.         oper = [cairo.OPERATOR_DEST_OVER,
  24.                 cairo.OPERATOR_DEST_IN,
  25.                 cairo.OPERATOR_OUT,
  26.                 cairo.OPERATOR_ADD,
  27.                 cairo.OPERATOR_ATOP,
  28.                 cairo.OPERATOR_DEST_ATOP]
  29.         
  30.         width, height = widget.get_size()
  31.         cr = widget.window.cairo_create()
  32.         
  33.         for i in oper:
  34.             self.draw(cr,  self.x, width, height, i)
  35.             self.x += 80
  36.             
  37.         return True
  38.    
  39.     def draw(self, cr, x, w, h, op):
  40.         
  41.         #cairo.CONTENT_COLOR
  42.         #cairo.CONTENT_ALPHA
  43.         #cairo.CONTENT_COLOR_ALPHA
  44.         first = cr.get_target().create_similar(cairo.CONTENT_COLOR_ALPHA,w,h)
  45.         second = cr.get_target().create_similar(cairo.CONTENT_COLOR_ALPHA,w,h)
  46.         
  47.         first_cr = cairo.Context(first)
  48.         first_cr.set_source_rgb(0, 0, 0.4)
  49.         first_cr.rectangle(x, 20, 50, 50)
  50.         first_cr.fill()
  51.         
  52.         second_cr = cairo.Context(second)
  53.         second_cr.set_source_rgb(0.5, 0.5, 0)
  54.         second_cr.rectangle(x+10, 40, 50, 50)
  55.         second_cr.fill()
  56.         first_cr.set_operator(op)
  57.         first_cr.set_source_surface(second, 0, 0)
  58.         first_cr.paint()
  59.         cr.set_source_surface(first, 0, 0)
  60.         cr.paint()
  61.         
  62. App()
  63. gtk.main()
Copy the Code
=======================================
裁剪(Clipping)与遮蔽(Masking)
  1. #!/usr/bin/env python
  2. # coding:utf-8
  3. import cairo
  4. import gtk
  5. import random
  6. class App(object):
  7.     def __init__(self):
  8.         window = gtk.Window(gtk.WINDOW_TOPLEVEL)
  9.         window.set_position(gtk.WIN_POS_CENTER)
  10.         window.set_title("等待的演示")
  11.         
  12.         window.set_position(gtk.WIN_POS_CENTER)
  13.         window.set_app_paintable(True)
  14.         self.image = cairo.ImageSurface.create_from_png("/home/long/图片/aabb.png")
  15.         self.width = self.image.get_width()
  16.         self.height = self.image.get_height()
  17.         window.set_default_size(self.width, self.height)
  18.         window.connect_after("expose-event", lambda w,e:self.on_expose_event(w,e))  
  19.         window.connect("destroy", lambda w:gtk.main_quit())        
  20.         
  21.         self.pos_x = 128
  22.         self.pos_y = 128
  23.         self.radius = 40
  24.         self.delta = [3,3]
  25.         
  26.         window.set_app_paintable(True)
  27.         self.time_ID = gtk.timeout_add(10, self.time_handler, window)
  28.         window.show_all()
  29.         
  30.     def on_expose_event(self, widget, event):
  31.         
  32.         cr = widget.window.cairo_create()  
  33.         width, height = widget.get_size()
  34.         
  35.         if self.pos_x < 0 + self.radius:
  36.             self.delta[0] = random.randint(0,3) + 5
  37.             print self.pos_x
  38.         elif self.pos_x > width - self.radius:
  39.             self.delta[0] = -(random.randint(0,3)  + 5)
  40.             print self.pos_y
  41.         
  42.         if self.pos_y < 0 + self.radius:
  43.             self.delta[1] = random.randint(0,3) + 5
  44.             print self.pos_y
  45.         elif self.pos_y > height - self.radius:
  46.             self.delta[1] = -(random.randint(0,3) + 5)
  47.             print self.pos_y
  48.             
  49.         self.pos_x += self.delta[0]
  50.         self.pos_y += self.delta[1]
  51.         
  52.         cr.set_source_surface(self.image, 1, 1)
  53.         cr.arc(self.pos_x, self.pos_y, self.radius, 0, 2*3.14)
  54.         cr.clip()
  55.         cr.paint()
  56.         
  57.         return True
  58.    
  59.     def time_handler(self, widget):
  60.         widget.queue_draw()
  61.         return True
  62.                
  63. App()
  64. gtk.main()
  65.         
  66.         
Copy the Code

======================
裁剪矩形
  1. #!/usr/bin/env python
  2. # coding:utf-8
  3. import cairo
  4. import gtk
  5. import random
  6. class App(object):
  7.     def __init__(self):
  8.         window = gtk.Window(gtk.WINDOW_TOPLEVEL)
  9.         window.set_position(gtk.WIN_POS_CENTER)
  10.         window.set_title("裁剪矩形")
  11.         
  12.         window.set_position(gtk.WIN_POS_CENTER)
  13.         window.set_app_paintable(True)
  14.       
  15.         window.set_default_size(200, 300)
  16.         
  17.         self.rotate = 0
  18.         self.counter = 0
  19.         self.xdirection = True
  20.         
  21.         self.bigx = 20
  22.         self.bigy = 200
  23.         self.delta = 1
  24.         
  25.         window.connect("destroy", lambda w:gtk.main_quit())        
  26.         window.connect_after("expose-event", lambda w,e:self.on_expose_event(w,e))     
  27.         window.set_app_paintable(True)
  28.         window.show_all()
  29.         
  30.     def on_expose_event(self, widget, event):
  31.         
  32.         cr = widget.window.cairo_create()
  33.         self.width, self.height = widget.get_size()
  34.         
  35.         self.counter += 1
  36.         
  37.         if self.bigx > self.width:
  38.             self.xdirection = False
  39.             self.delta = -self.dalta
  40.             self.bigx  = self.width
  41.         
  42.         if self.bigx < 1:
  43.             self.bigx = 1
  44.             self.delta = -self.delta
  45.         if self.bigy > self.height:
  46.             self.xdirection = True
  47.             self.delta = -self.delta
  48.             self.bigy = self.height
  49.         
  50.         if self.bigy < 1:
  51.             self.delta = -self.delta
  52.             self.bigy = 1
  53.         if self.xdirection:
  54.             self.bigx += self.delta
  55.         else:
  56.             self.bigy += self.delta
  57.         cr.translate(self.width/2, self.height/2)
  58.         cr.rectangle(-self.bigx/2, -self.bigy/2, self.bigx-2, self.bigy-2)
  59.         cr.set_source_rgb(0, 0, 0)
  60.         cr.set_line_width(1)
  61.         cr.stroke()
  62.         
  63.         cr.rotate(self.rotate)
  64.         self.rotate += 0.01
  65.         
  66.         cr.rectangle(-50, -25, 100, 50)
  67.         cr.stroke()
  68.         
  69.         bigrect = gtk.gdk.Rectangle()
  70.         
  71.         bigrect.x = -self.bigx/2
  72.         bigrect.y = -self.bigy/2
  73.         bigrect.width = self.bigx - 2
  74.         bigrect.height = self.bigy - 2
  75.         
  76.         rect = gtk.gdk.Rectangle()
  77.         
  78.         rect.x = -50
  79.         rect.y = -25
  80.         rect.width = 100
  81.         rect.height = 50
  82.         
  83.         intersect1 = gtk.gdk.Rectangle()
  84.         
  85.         intersect1.intersect(bigrect)
  86.         intersect1.intersect(rect)
  87.         
  88.         cr.rectangle(intersect1.x, intersect1.y, intersect1.width, intersect1.height)
  89.         cr.fill()
  90.         return True
  91.         
  92. App()
  93. gtk.main()
  94.         
Copy the Code
==================
遮蔽

因为在源被用于外观之前,首先要被过滤。遮蔽可作为一种过滤器。遮蔽用于决定源的哪部分要被显示,哪部分不可被显示。遮蔽的不透明部分允许将源复制到外观,透明部分则不允许将源复制给外观。
  1. #!/usr/bin/env python
  2. # coding:utf-8
  3. import cairo
  4. import gtk
  5. import random
  6. #遮蔽
  7. class App(object):
  8.     def __init__(self):
  9.         window = gtk.Window(gtk.WINDOW_TOPLEVEL)
  10.         window.set_position(gtk.WIN_POS_CENTER)
  11.         window.set_title("遮蔽")
  12.       
  13.         window.set_position(gtk.WIN_POS_CENTER)
  14.         window.set_app_paintable(True)
  15.       
  16.         window.set_default_size(200, 300)
  17.         
  18.         window.connect("destroy", lambda w:gtk.main_quit())      
  19.         window.connect_after("expose-event", lambda w,e:self.on_expose_event(w,e))     
  20.         window.set_app_paintable(True)
  21.         window.show_all()
  22.       
  23.     def on_expose_event(self, widget, event):
  24.         cr = widget.window.cairo_create()
  25.         cr.set_source_rgb(0, 0, 0)
  26.         self.image = cairo.ImageSurface.create_from_png("/home/long/图片/linuxdeepin.png")
  27.         
  28.         cr.mask_surface(self.image, 0, 0)
  29.         cr.fill()
  30.         
  31.         return True
  32. App()
  33. gtk.main()
Copy the Code

========================================================================
这一篇讲述变换(Transformation)仿射变换是由一些线性变换与平移构成的。线性变换
可以写为单个矩阵的形式。旋转是让一个刚体绕一点运动的变换。缩放变换是让物体的形
状扩大与减小,并且在各个方向上的缩放因子都相同。平移变换将每个点沿着指定的方向
移动常量距离。错切对于给定轴线,沿垂直于它的方向对物体进行移动的变换,并且在轴
线的一侧的移动距离大于另一侧。

平移
  1. #平移
  2.         cr = widget.window.cairo_create()
  3.         
  4.         cr.set_source_rgb(0.6, 0.6, 0.6)
  5.         cr.rectangle(20, 20, 80, 50)
  6.         cr.stroke_preserve()
  7.         cr.set_source_rgb(1, 1, 1)
  8.         cr.fill()
  9.         
  10.         cr.translate(100, 100)
  11.         
  12.         cr.set_source_rgb(0.6, 0.6, 0.6)
  13.         cr.rectangle(20, 20, 80, 50)
  14.         cr.stroke_preserve()
  15.         cr.set_source_rgb(1, 1, 1)
  16.         cr.fill()
  17.         #旋转
  18.         cr.set_source_rgb(0.6, 0.6, 0.6)
  19.         cr.rectangle(20, 20, 80, 50)
  20.         cr.stroke_preserve()
  21.         cr.set_source_rgb(1, 1, 1)
  22.         cr.fill()
  23.         
  24.         cr.translate(150, 100) #平移
  25.         cr.rotate(3.14/2)#旋转180
  26.         
  27.         cr.set_source_rgb(0.6, 0.6, 0.6)
  28.         cr.rectangle(20,20, 80, 50)
  29.         cr.stroke_preserve()
  30.         cr.set_source_rgb(1, 1, 1)
  31.         cr.fill()
  32.         
Copy the Code
\

缩放
  1. #!/usr/bin/env python
  2. # coding:utf-8
  3. import cairo
  4. import gtk
  5. import random
  6. #缩放
  7. class App(object):
  8.     def __init__(self):
  9.         window = gtk.Window(gtk.WINDOW_TOPLEVEL)
  10.         window.set_position(gtk.WIN_POS_CENTER)
  11.         window.set_title("缩放")
  12.       
  13.         window.set_position(gtk.WIN_POS_CENTER)
  14.         window.set_app_paintable(True)
  15.       
  16.         window.set_default_size(300, 300)
  17.         
  18.         window.connect("destroy", lambda w:gtk.main_quit())      
  19.         window.connect_after("expose-event", lambda w,e:self.on_expose_event(w,e))     
  20.         window.set_app_paintable(True)
  21.         window.show_all()
  22.       
  23.     def on_expose_event(self, widget, event):
  24.         cr = widget.window.cairo_create()
  25.         #缩放
  26.         cr.save() #初始的变换矩阵保存一下. 通过 save, restore
  27.         cr.set_source_rgb(0.6, 0.6, 0.6)
  28.         cr.rectangle(20, 30, 80, 50)
  29.         cr.stroke_preserve()
  30.         cr.set_source_rgb(1, 1, 1)
  31.         cr.fill()
  32.         cr.restore()
  33.         
  34.         cr.save()
  35.         cr.translate(130, 30)
  36.         cr.scale(0.7, 0.7)
  37.         
  38.         cr.set_source_rgb(0.6, 0.6, 0.6)
  39.         cr.rectangle(0, 0, 80, 50)
  40.         cr.stroke_preserve()
  41.         cr.set_source_rgb(1, 1, 1)
  42.         cr.fill()
  43.         cr.restore()
  44.         
  45.         cr.save()
  46.         cr.translate(220, 30)
  47.         cr.scale(1.5, 1.5)
  48.         
  49.         cr.set_source_rgb(0.6, 0.6, 0.6)
  50.         cr.rectangle(0, 0, 80, 50)
  51.         cr.stroke_preserve()
  52.         cr.set_source_rgb(1, 1, 1)
  53.         cr.fill()
  54.         cr.restore() #恢复前面用 save保存下来的图形. 有点想 出栈的感觉
  55.         return True
  56. App()
  57. gtk.main()
Copy the Code
  1. #!/usr/bin/env python
  2. # coding:utf-8
  3. import cairo
  4. import gtk
  5. import random
  6. #错切
  7. class App(object):
  8.     def __init__(self):
  9.         window = gtk.Window(gtk.WINDOW_TOPLEVEL)
  10.         window.set_position(gtk.WIN_POS_CENTER)
  11.         window.set_title("错切")
  12.       
  13.         window.set_position(gtk.WIN_POS_CENTER)
  14.         window.set_app_paintable(True)
  15.       
  16.         window.set_default_size(300, 300)
  17.         
  18.         window.connect("destroy", lambda w:gtk.main_quit())      
  19.         window.connect_after("expose-event", lambda w,e:self.on_expose_event(w,e))     
  20.         window.set_app_paintable(True)
  21.         window.show_all()
  22.       
  23.     def on_expose_event(self, widget, event):
  24.         cr = widget.window.cairo_create()
  25.         matrix = cairo.Matrix(1.0, 0.5,
  26.                               0.0, 1.0,
  27.                               0.0, 0.0)
  28.         
  29.         cr.save()
  30.         cr.set_source_rgb(0.6, 0.6, 0.6)
  31.         cr.rectangle(20, 30, 80, 50)
  32.         cr.stroke_preserve()
  33.         cr.set_source_rgb(1, 1, 1)
  34.         cr.fill()
  35.         cr.restore()
  36.         
  37.         cr.save()
  38.         cr.translate(130, 30)
  39.         cr.transform(matrix) #用户空间轴转换矩阵
  40.         
  41.         cr.set_source_rgb(0.6, 0.6, 0.6)
  42.         cr.rectangle(0, 0, 80, 50)
  43.         cr.set_source_rgb(1, 1, 1)
  44.         cr.fill()
  45.         cr.restore()
  46.         
  47.         cr.save()
  48.         cr.translate(220, 30)
  49.         #class cairo.Matrix(xx = 1.0, yx = 0.0, xy = 0.0, yy = 1.0, x0 = 0.0, y0 = 0.0)
  50.         #x_new = xx * x + xy * y + x0
  51.         #y_new = yx * x + yy * y + y0
  52.         #x_new =
  53.         #matrix = cairo.Matrix(1.0, 0.0,
  54.         #                      0.0, 1.0,
  55.         #                      0.0, 0.0)
  56.         #对照看下,发现什么问题没有, 看下 对角方向的参数. 1.0 1.0   0.0 0.0
  57.         matrix  = cairo.Matrix(2.0, 1.0,
  58.                                1.0, 3.0,
  59.                                5.0, 10.0)
  60.         cr.transform(matrix)
  61.         
  62.         cr.set_source_rgb(0.6, 0.6, 0.6)
  63.         cr.rectangle(0, 0, 80, 50)
  64.         cr.stroke_preserve()
  65.         cr.set_source_rgb(1, 1, 1)
  66.         cr.fill()
  67.         cr.restore()
  68.         #代码实现了两次错切变换,对于错切变换没有特定函数,必须使用矩阵来实现. 看原作者给出来的坐标.
  69.         #我的矩阵学的也不好,只是上课的时候听过,哎.各位python爱好者,往高处跑,还是要学好底层和数学啊.T_T
  70.         # cairo.Matrix 是存储防射变换的数据结构.
  71.         return True
  72. App()
  73. gtk.main()
Copy the Code

椭圆

下面的这个例子,画了一个灰常复杂的形状,它由一串旋转的椭圆形成。
  1. #!/usr/bin/env python
  2. # coding:utf-8
  3. import cairo
  4. import gtk
  5. import random
  6. #椭圆
  7. class App(object):
  8.     def __init__(self):
  9.         window = gtk.Window(gtk.WINDOW_TOPLEVEL)
  10.         window.set_position(gtk.WIN_POS_CENTER)
  11.         window.set_title("椭圆")
  12.       
  13.         window.set_position(gtk.WIN_POS_CENTER)
  14.         window.set_app_paintable(True)
  15.       
  16.         window.set_default_size(300, 300)
  17.         self.i = 0     
  18.         window.connect("destroy", lambda w:gtk.main_quit())      
  19.         window.connect_after("expose-event",
  20.                              lambda w,e:self.on_expose_event(w,e))   
  21.         window.set_app_paintable(True)
  22.         window.show_all()
  23.       
  24.     def on_expose_event(self, widget, event):
  25.         cr = widget.window.cairo_create()
  26.         width, height = widget.get_size()
  27.         
  28.         #画线宽度
  29.         cr.set_line_width(0.5)
  30.         #画正方形
  31.         cr.translate(width/2, height/2)
  32.         #画圆
  33.         cr.arc(0, 0, 120, 0, 2*3.14)
  34.         cr.stroke()
  35.         
  36.         cr.save()
  37.         
  38.         for i in range(0, 36):
  39.             cr.rotate(i*3.14/36)#旋转
  40.             cr.scale(0.3, 1) #缩放
  41.             cr.arc(0, 0, 120, 0, 2*3.14)
  42.             cr.restore() #恢复前面保存的画图
  43.             cr.stroke()
  44.             cr.save()
  45.             
  46.         return True
  47.    
  48. App()
  49. gtk.main()
Copy the Code
沿着边界圆画 36 个椭圆。椭圆可用圆的缩放变换而获得。旋转这个椭圆,这样就创建了一个有趣的形状
  1. #!/usr/bin/env python
  2. # coding:utf-8
  3. #星星
  4. #下面的示例绘制了一个又旋转又缩放的星星,可惜不会发光呃。
  5. #
  6. import cairo
  7. import gtk
  8. import random
  9. #星星
  10. points = [[0, 85],
  11.           [75, 75],
  12.           [100, 10],
  13.           [125, 75],
  14.           [200, 85],
  15.           [150, 125],
  16.           [160, 190],
  17.           [100, 150],
  18.           [40, 190],
  19.           [50, 125],
  20.           [0, 85]]
  21. class App(object):
  22.     def __init__(self):
  23.         window = gtk.Window(gtk.WINDOW_TOPLEVEL)
  24.         window.set_position(gtk.WIN_POS_CENTER)
  25.         window.set_title("星星")
  26.       
  27.         window.set_position(gtk.WIN_POS_CENTER)
  28.         window.set_app_paintable(True)
  29.       
  30.         window.set_default_size(300, 300)
  31.         window.connect("destroy", lambda w:gtk.main_quit())      
  32.         window.connect_after("expose-event",
  33.                              lambda w,e:self.on_expose_event(w,e))   
  34.         
  35.         self.timeout_ID = gtk.timeout_add(10, self.time_handler, window)
  36.         self.angle = 0
  37.         self.scale = 1
  38.         self.delta = 0.01
  39.         
  40.         window.set_app_paintable(True)
  41.         window.show_all()
  42.         
  43.     def time_handler(self, widget):
  44.         widget.queue_draw()
  45.         return True
  46.     def on_expose_event(self, widget, event):
  47.         width, height = widget.get_size()
  48.         cr = widget.window.cairo_create()
  49.         
  50.         cr.set_source_rgb(0, 0.44, 0.7)
  51.         cr.set_line_width(1)
  52.         
  53.         cr.translate(width/2, height/2) #平移
  54.         cr.rotate(self.angle)#旋转
  55.         #cr.scale(self.scale, self.scale) #缩放
  56.         cr.scale(0.2,0.2)
  57.         for i in range(0, 10):
  58.             cr.line_to(points[i][0], points[i][1])
  59.             
  60.         cr.close_path()
  61.         cr.fill()
  62.         cr.stroke()
  63.         
  64.         #if self.scale < 0.01:
  65.         #   self.delta = -self.delta
  66.         #elif self.scale > 0.99:
  67.         #    self.delta = -self.delta
  68.         #self.scale += self.delta
  69.         self.angle += 0.01
  70.         #这里的旋转和平移没有什么悬念了,就是这样了
  71.         #看看缩放  < 0.01 和 > 0.99的时候.
  72.         #就是这个 scale有作用. 缩小,放大,
  73.         return True
  74. App()
  75. gtk.main()
Copy the Code

最后来一个总的例子:
去画歌词.
  1. import gtk
  2. import cairo
  3. import pangocairo
  4. import pango
  5. import gobject
  6. TEST_LRC = "深度影音播放器 歌词测试播放"
  7. INIT_FONT_TYPE = "文泉驿等宽微米黑"
  8. INIT_FONT_SIZE = 25
  9. class Lrc(gobject.GObject):
  10.     __gsignals__ = {
  11.         "lrc-changed" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE,
  12.                          ())
  13.         }
  14.     def __init__(self):
  15.         gobject.GObject.__init__(self)
  16.         self.pango_list = pango.AttrList()
  17.         
  18.         self.lrc_text = ""
  19.         self.end_index = 0
  20.         self.offset_x = 0
  21.         self.alpha = 0.5        
  22.         self.time_delay = 250
  23.         self.show_lrc_bool = True
  24.         self.timeout_add_bool = True
  25.         self.timeout_add_id = None
  26.         self.init_font()
  27.         
  28.     def start_lrc(self):   
  29.         self.timeout_add_bool = True
  30.         
  31.     def stop_lrc(self):   
  32.         self.timeout_add_bool = False
  33.         
  34.     def init_timeout(self, time_delay=0):     
  35.         if self.timeout_add_id:
  36.             gtk.timeout_remove(self.timeout_add_id) # remove timeout id.
  37.         self.time_delay = time_delay
  38.         self.timeout_add_id = gtk.timeout_add(self.time_delay, self.draw_lrc_timeout_add)
  39.         
  40.     def draw_lrc_timeout_add(self):   
  41.         self.pango_list.insert(pango.AttrForeground(65535, 0, 0, 0, self.end_index))
  42.         # self.end_index += 1
  43.         self.offset_x += 10
  44.         self.emit("lrc-changed")
  45.         return self.timeout_add_bool
  46.    
  47.     def init_font(self, font_type=INIT_FONT_TYPE, font_size=INIT_FONT_SIZE):
  48.         self.font_type = font_type
  49.         self.font_size = font_size
  50.         
  51.     def show_text(self, lrc_text):
  52.         self.lrc_text = lrc_text
  53.         self.emit("lrc-changed")
  54.         
  55.     def expose_lrc_text_function(self, cr):
  56.         if self.show_lrc_bool:            
  57.             # cr.set_source_rgb(0, 0, 0)
  58.             self.draw_lrc_text(self.lrc_text, cr)
  59.             
  60.     def draw_lrc_text(self, ch, cr, init_fg_color="#FF0000"):
  61.         
  62.         context = pangocairo.CairoContext(cr)
  63.         layout = context.create_layout()
  64.         layout.set_font_description(pango.FontDescription("%s %s" % (self.font_type, self.font_size)))
  65.         
  66.         # Set font position.
  67.         cr.set_source_rgb(1, 0, 0)
  68.         layout.set_text(ch)
  69.         layout.set_attributes(self.pango_list)
  70.         ch_width, ch_height = layout.get_pixel_size()
  71.         
  72.         cr.move_to(0, 0)
  73.         #########################        
  74.         cr.save()        
  75.         #########################
  76.         cr.layout_path(layout) #
  77.         # Set font rgb.
  78.         cr.set_source_rgba(0, 0.5, 0.5)
  79.         # if #draw 填充的字体.
  80.         cr.set_line_width(5) # 设置宽        
  81.         cr.stroke_preserve() # 保存绘制的路径
  82.         cr.set_source_rgba(0, 1, 0)
  83.         cr.fill()
  84.         # else 里面空的字体.
  85.         # cr.stroke()        
  86.         
  87.         #######################
  88.         cr.restore()
  89.         #######################
  90.         
  91.         cr.save()
  92.         cr.new_path()
  93.         
  94.         pattern = cairo.LinearGradient(self.offset_x, 0.0,
  95.                                        self.offset_x, ch_height )        
  96.         pattern.add_color_stop_rgba(0, 0.5, 1.0, 0.5, 1.0)
  97.         pattern.add_color_stop_rgba(0.5, 0.5, 0.5, 0.5, 1.0)
  98.         pattern.add_color_stop_rgba(1.0, 0.1, 0.5, 0.1, 1.5)
  99.         cr.set_source(pattern)
  100.         cr.set_operator(cairo.OPERATOR_OVER)
  101.         cr.move_to(0, 0)        
  102.         ##############################
  103.         # Show font.
  104.         context.show_layout(layout)
  105.         cr.restore()
  106.         
  107. if __name__ == "__main__":
  108.     def test_osd_lrc_function(widget, event):
  109.         cr = widget.window.cairo_create()
  110.         cr.set_source_rgba(1.0, 1.0, 1.0, 0.1)
  111.         cr.set_operator(cairo.OPERATOR_SOURCE)
  112.         cr.paint()
  113.         lrc.expose_lrc_text_function(cr)
  114.         return True
  115.    
  116.     def active_expose_window(LRC):
  117.         win.queue_draw()
  118.         
  119.     def modify_lrc_time(widget):   
  120.         pass
  121.         
  122.     def realize_win(widget):
  123.         widget.window.input_shape_combine_region(gtk.gdk.Region(), 0, 0)
  124.         widget.window.set_back_pixmap(None, False)
  125.         
  126.     win = gtk.Window(gtk.WINDOW_TOPLEVEL)
  127.     win.set_position(gtk.WIN_POS_CENTER)
  128.     win.set_size_request(500, 500)
  129.     win.set_decorated(False)
  130.     win.set_skip_taskbar_hint(True)
  131.     win.set_keep_above(True)
  132.     win.set_colormap(gtk.gdk.Screen().get_rgba_colormap())
  133.     # win.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DIALOG)   
  134.     win.add_events(gtk.gdk.ALL_EVENTS_MASK)
  135.    
  136.     lrc = Lrc()   
  137.     lrc.show_text("深度LINUX DEEPIN 深度影音")   
  138.     lrc.init_timeout(500)
  139.     lrc.connect("lrc-changed", active_expose_window)
  140.    
  141.     ##############
  142.     win.connect("expose-event", test_osd_lrc_function)
  143.     win.connect("realize", realize_win) ; 注释掉这行看看, 鼠标是否还可以穿透.
  144.     win.show_all()
  145.     gtk.main()
Copy the Code
效果如下:
选区_003.png


歌词最简单的实现方式... 如果字幕也能这样,岂不是快哉.
歌词的时间读取只要将前后的时间相减,你明白的.. 小学数学.
总的路程(总的字体宽度), 时间.... 你明白..的!!
  1. #!/usr/bin/env python
  2. # coding:utf-8
  3. import cairo
  4. import gtk
  5. import random
  6. import pango
  7. import pangocairo
  8. #遮蔽
  9. class App(object):
  10.     def __init__(self):
  11.         self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
  12.         self.window.set_position(gtk.WIN_POS_CENTER)
  13.         self.window.set_title("遮蔽")
  14.       
  15.         self.window.set_position(gtk.WIN_POS_CENTER)
  16.         self.window.set_app_paintable(True)
  17.       
  18.         self.window.set_default_size(200, 300)
  19.         
  20.         self.window.connect("destroy", lambda w:gtk.main_quit())      
  21.         self.window.connect_after("expose-event", lambda w,e:self.on_expose_event(w,e))     
  22.         self.window.set_app_paintable(True)
  23.         
  24.         self.window.show_all()
  25.         self.i = 0
  26.         gtk.timeout_add(100, self.test)
  27.         
  28.     def test(self):   
  29.         self.i = self.i + 1
  30.         self.window.queue_draw()
  31.         return True
  32.    
  33.     def on_expose_event(self, widget, event):
  34.         cr = widget.window.cairo_create()
  35.         
  36.         # active_surface = self.get_image_surface([1, 1, 1])
  37.         # inactive_surface = self.get_image_surface([1, 0, 0])
  38.         
  39.         pangocairo_cr = pangocairo.CairoContext(cr)
  40.         layout = pangocairo_cr.create_layout()
  41.         layout.set_font_description(pango.FontDescription("%s %s" % ("文泉驿等宽微米黑", 20)))
  42.         layout.set_text("深度影音--Linux deepin 12.12")
  43.         pangocairo_cr.move_to(0, 0)
  44.         pangocairo_cr.set_source_rgb(0, 0, 1)
  45.         pangocairo_cr.show_layout(layout)
  46.         cr.save()
  47.         cr.rectangle(0, 0, self.i, 200)
  48.         cr.clip()
  49.         cr.set_source_rgb(1, 0, 0)
  50.         cr.fill()
  51.         pangocairo_cr.set_source_rgb(0, 1, 0)
  52.         pangocairo_cr.show_layout(layout)
  53.         cr.restore()
  54.                
  55.         return True
  56.    
  57. App()
  58. gtk.main()
Copy the Code

一起来吧..
  1. #! /usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. # Copyright (C) 2012 Deepin, Inc.
  4. #               2012 Hailong Qiu
  5. #
  6. # Author:     Hailong Qiu <356752238@qq.com>
  7. # Maintainer: Hailong Qiu <356752238@qq.com>
  8. #
  9. # This program is free software: you can redistribute it and/or modify
  10. # it under the terms of the GNU General Public License as published by
  11. # the Free Software Foundation, either version 3 of the License, or
  12. # any later version.
  13. #
  14. # This program is distributed in the hope that it will be useful,
  15. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17. # GNU General Public License for more details.
  18. #
  19. # You should have received a copy of the GNU General Public License
  20. # along with this program.  If not, see .
  21. import gtk
  22. import cairo
  23. import pangocairo
  24. import pango
  25. import gobject
  26. TEST_LRC = "深度影音播放器 歌词测试播放"
  27. INIT_FONT_TYPE = "文泉驿等宽微米黑"
  28. INIT_FONT_SIZE = 25
  29. class Lrc(gobject.GObject):
  30.     __gsignals__ = {
  31.         "lrc-changed" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE,
  32.                          ())
  33.         }
  34.     def __init__(self):
  35.         gobject.GObject.__init__(self)
  36.         self.pango_list = pango.AttrList()
  37.         
  38.         self.lrc_text = ""
  39.         self.end_index = 0
  40.         self.offset_x = 0
  41.         self.alpha = 0.5        
  42.         self.time_delay = 250
  43.         self.show_width = 0
  44.         self.show_lrc_bool = True
  45.         self.timeout_add_bool = True
  46.         self.timeout_add_id = None
  47.         self.init_font()
  48.         
  49.     def start_lrc(self):   
  50.         self.timeout_add_bool = True
  51.         
  52.     def stop_lrc(self):   
  53.         self.timeout_add_bool = False
  54.         
  55.     def init_timeout(self, time_delay=0):     
  56.         if self.timeout_add_id:
  57.             gtk.timeout_remove(self.timeout_add_id) # remove timeout id.
  58.         self.time_delay = time_delay
  59.         self.timeout_add_id = gtk.timeout_add(self.time_delay, self.draw_lrc_timeout_add)
  60.         
  61.     def draw_lrc_timeout_add(self):   
  62.         self.pango_list.insert(pango.AttrForeground(65535, 0, 0, 0, self.end_index))
  63.         # self.offset_x += 100
  64.         self.show_width += 1
  65.         self.emit("lrc-changed")
  66.         return self.timeout_add_bool
  67.    
  68.     def init_font(self, font_type=INIT_FONT_TYPE, font_size=INIT_FONT_SIZE):
  69.         self.font_type = font_type
  70.         self.font_size = font_size
  71.         
  72.     def show_text(self, lrc_text):
  73.         self.lrc_text = lrc_text
  74.         self.emit("lrc-changed")
  75.         
  76.     def expose_lrc_text_function(self, cr):
  77.         if self.show_lrc_bool:            
  78.             # cr.set_source_rgb(0, 0, 0)
  79.             self.draw_lrc_text(self.lrc_text, cr)
  80.             
  81.     def draw_lrc_text(self, ch, cr, init_fg_color="#FF0000"):
  82.         
  83.         context = pangocairo.CairoContext(cr)
  84.         layout = context.create_layout()
  85.         layout.set_font_description(pango.FontDescription("%s %s" % (self.font_type, self.font_size)))
  86.         
  87.         # Set font position.
  88.         cr.set_source_rgb(1, 0, 0)
  89.         layout.set_text(ch)
  90.         layout.set_attributes(self.pango_list)
  91.         ch_width, ch_height = layout.get_pixel_size()
  92.         
  93.         cr.move_to(30, 0)
  94.         #
  95.         cr.save()        
  96.         cr.layout_path(layout)
  97.         # cr.set_source_rgba(1, 0, 0)
  98.         # if #draw 填充的字体.
  99.         cr.set_line_width(1) # 设置宽        
  100.         cr.stroke_preserve() # 保存绘制的路径
  101.         # cr.set_source_rgba(0, 1, 0)
  102.         cr.fill()
  103.         # else 里面空的字体.
  104.         # cr.stroke()               
  105.         #
  106.         cr.restore()
  107.         #        
  108.         pattern = cairo.LinearGradient(self.offset_x, 0.0,
  109.                                        self.offset_x, ch_height )        
  110.         pattern.add_color_stop_rgba(0.0, 0.5, 1.0, 0.5, 1.0)
  111.         pattern.add_color_stop_rgba(0.5, 0.5, 0.5, 0.5, 1.0)
  112.         pattern.add_color_stop_rgba(1.0, 0.1, 0.5, 0.1, 1.5)
  113.         cr.set_source(pattern)
  114.         cr.set_operator(cairo.OPERATOR_OVER)               
  115.         #
  116.         cr.save()
  117.         cr.rectangle(0, 0, self.show_width, 200)
  118.         cr.clip()        
  119.         #
  120.         cr.move_to(30, 0)        
  121.         context.show_layout(layout)
  122.         cr.restore()
  123.         
  124. if __name__ == "__main__":
  125.     def test_osd_lrc_function(widget, event):
  126.         cr = widget.window.cairo_create()
  127.         cr.set_source_rgba(1.0, 1.0, 1.0, 0.1)
  128.         cr.set_operator(cairo.OPERATOR_SOURCE)
  129.         cr.paint()
  130.         lrc.expose_lrc_text_function(cr)
  131.         return True
  132.    
  133.     def active_expose_window(LRC):
  134.         win.queue_draw()
  135.         
  136.     def modify_lrc_time(widget):   
  137.         pass
  138.         
  139.     def realize_win(widget):
  140.         widget.window.input_shape_combine_region(gtk.gdk.Region(), 0, 0)
  141.         widget.window.set_back_pixmap(None, False)
  142.         
  143.     ##############################################   
  144.     win = gtk.Window(gtk.WINDOW_TOPLEVEL)
  145.     win.set_position(gtk.WIN_POS_CENTER)
  146.     win.set_size_request(500, 500)
  147.    
  148.     win.set_decorated(False)
  149.     win.set_skip_taskbar_hint(True)
  150.     # win.set_keep_above(True)
  151.     win.set_colormap(gtk.gdk.Screen().get_rgba_colormap())
  152.     # win.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DIALOG)   
  153.     win.add_events(gtk.gdk.ALL_EVENTS_MASK)
  154.    
  155.     lrc = Lrc()   
  156.     lrc.show_text("深度LINUX DEEPIN 深度影音")   
  157.     lrc.init_timeout(50)
  158.     lrc.connect("lrc-changed", active_expose_window)
  159.    
  160.     ################################################
  161.     win.connect("expose-event", test_osd_lrc_function)
  162.     win.connect("realize", realize_win)
  163.     win.show_all()
  164.     gtk.main()
Copy the Code

选区_004.png
选区_005.png

简单代码编辑器编写: PANGO + CAIRO + GTK+.
自从写了assembly IDE开发环境以后,有一些朋友对里面的代码编辑器很感兴趣,我和他说,我没有你想象中那么厉害,里面东西都比较简单,他说我谦虚了,我无语了。可能是由于他没接触类似的东西,所以有点懵,这个很正常,接触了,就没有那么神秘了.我写这些文章,不是炫耀我懂这些东西,是希望大家也能交流,把你们所学的东西共享出来给大家。哪怕抽一点时间,写一点,也是有益很多人的。大家就互相大家交流吧,由于技术水平有限,有什么不对的地方还请多多指教。
我们先来看PANGO的一个小例子:
将所有东西化简后,就是这样啦. 就像一个大片电影,其实简单将的就是 一个王朝的建立而已,然后扩展起来而已.
  1. #coding:utf-8
  2. import gtk
  3. import pango
  4. import pangocairo
  5. # 这些常量看的很不舒服. 不知道是全局变量还是伪常量.
  6. INIT_FONT_TYPE = "文泉驿等宽微米黑"
  7. INIT_FONT_SIZE = 11
  8. class Test(object):
  9.     def __init__(self):        
  10.         
  11.         self.win = gtk.Window(gtk.WINDOW_TOPLEVEL)
  12.         self.btn = gtk.Button()               
  13.         
  14.         self.win.set_size_request(500, 500)
  15.         #
  16.         # self.btn
  17.         #
  18.         self.btn.connect("expose-event", self.btn_expose_event)
  19.         
  20.         self.win.add(self.btn)
  21.         self.win.show_all()
  22.         
  23.     def btn_expose_event(self, widget, event):     
  24.         cr = widget.window.cairo_create()
  25.         rect = widget.allocation
  26.         pango_list = pango.AttrList()
  27.         # 设置属性.
  28.         r = 65535 # 0 ~ 65535
  29.         g = 0
  30.         b = 0
  31.         start_index = 1
  32.         end_index = 3
  33.         pango_list.insert(pango.AttrForeground(
  34.                 r, g, b, start_index, end_index))
  35.         r = 0
  36.         g = 0
  37.         b = 65535
  38.         pango_list.insert(pango.AttrBackground(
  39.                 r, g, b, start_index, end_index))
  40.         self.expose_event_text_buffer(cr, rect, pango_list)
  41.         return True
  42.    
  43.     def expose_event_text_buffer(self, cr, rect, pango_list):
  44.         offset_x = 10
  45.         offset_y = 10
  46.         context = pangocairo.CairoContext(cr)
  47.         layout = context.create_layout() # 创建 layout
  48.         layout.set_font_description(pango.FontDescription("%s %s" % (INIT_FONT_TYPE, INIT_FONT_SIZE)))        # 设置字体 和字号
  49.         
  50.         layout.set_text("Linux Deepin 深度影音!!")
  51.         layout.set_attributes(pango_list) # 设置前景和背景颜色属性.
  52.         cr.set_source_rgb(0, 0, 0)
  53.         cr.move_to(offset_x, offset_y) # 显示的位置
  54.         context.update_layout(layout) # 更新
  55.         context.show_layout(layout) # 显示
  56.                
  57.         
  58. Test()        
  59. gtk.main()
Copy the Code
看完代码后,真的没有那么神秘了,不是吗?
代码编辑器图一.png
词法分析了解: http://my.oschina.net/hailongqiu/blog/81546
词法分析很简单,每个人都能写出不同的版本,我提醒的就是千万不要忘记写符号表来保存这些关键字的信息.
代码提示的话,原理也很简单,因为我以前写过简单的文件管理器,就是这样的智能补足的.就是将你需要的东西匹配出来就可以啦,然后显示在下拉对话框中.
可以模仿我们最初学习线程的那个例子. 一个在前面处理 输入,一个在后面处理 编辑.
还有一个输入法的管理: GtkIMMulticontext... 详细请查询GTK手册吧.

在LINUX这个世界,高手实在是太多了,对于刚进入LINUX世界的菜鸟的我,以前学的东西都不好在高手们面前显眼,因为我以前学的那些东西在在他们面前时不值得一提的。“菜”,非常菜,所以别人说我的时候,我感觉确实和LINUX的C语言高手差距很大,所以都沉默了。找机会要好好锻炼一下,多看看C语言的开源项目,自己也写一个项目(创造一门语言,将这门语言翻译成NASM,这是我的狂想:http://my.oschina.net/hailongqiu/blog/75072, 但是比这个还要简单的更简单些吧,呵呵),忘记曾经的思维,忘记学校的事情,努力追上C语言高手的水平。

visual python 拖拉界面中的 难题解决:[笔记]
  1. #!coding:utf-8
  2. import gtk
  3. class Test(object):
  4.     def __init__(self):
  5.         self.win = gtk.Window(gtk.WINDOW_TOPLEVEL)
  6.         self.win.set_size_request(500, 500)
  7.         self.textview = gtk.TextView()
  8.         # self.textview = gtk.Entry()
  9.         self.textview.set_size_request(200, 100)
  10.        
  11.         self.win.connect_after("expose-event", self.expose_event_win)
  12.         self.fixed = gtk.Fixed()
  13.         self.fixed.put(self.textview, 20, 30)
  14.         self.win.add(self.fixed)
  15.         self.win.show_all()
  16.         self.textview.window.set_composited(True)
  17.        
  18.     def expose_event_win(self, widget, event):
  19.         cr = widget.window.cairo_create()
  20.        
  21.         cr.set_source_pixmap (self.textview.window,
  22.                               self.textview.allocation.x,
  23.                               self.textview.allocation.y)            
  24.         region = gtk.gdk.region_rectangle(self.textview.allocation)
  25.         r = gtk.gdk.region_rectangle(event.area)
  26.         region.intersect(r)
  27.         cr.region (region)
  28.         cr.fill()
  29.        
  30.         cr.set_dash([1.0,1.0],0)
  31.         cr.set_source_rgba(1, 0, 0, 0.4)
  32.         cr.rectangle(0, 0, 200, 200)
  33.         cr.stroke()
  34.        
  35.         return True
  36.    
  37. Test()
  38. gtk.main()
Copy the Code
虚线画.png
Reply Favorite View the author
All Replies
hfy1991
deepin
2012-02-18 03:43
#1
楼主的内容很受用,PyGTK太不详细了,要是早点看到这篇就好了
Reply View the author
z85525006
deepin
2012-02-18 09:20
#2
楼主的内容很受用,PyGTK太不详细了,要是早点看到这篇就好了
这些内容其实早就出来了.
是C语言版本的,我改写成PYTHON的版本,我作个笔记而已! :
Reply View the author
z85525006
deepin
2012-02-24 19:03
#3
  1. cr.save()
  2.         cr.rectangle(x+1, y, w-2, 1)
  3.         cr.rectangle(x, y+1, w, h-2)
  4.         cr.rectangle(x+1, h-1, w-2, 1)
  5.         cr.clip()
  6.         
  7.         #渐变
  8.         #draw_vlinear(cr, x, y, w, h, theme.get_dynamic_shadow_color("progressbarBackground").get_color_info())
  9.         cr.restore()
Copy the Code
Reply View the author
z85525006
deepin
2012-09-07 11:12
#4
http://blog.csdn.net/zddmail/article/details/7450033
这是一段高斯的算法....
我们明白, 图片其实 在屏幕就是画了点而已.
汇编读取出来, 也是按照 图片格式的规则去而已.
在屏幕显示就是一个个点画出来的.
Reply View the author
mjwolf
deepin
2012-09-07 21:36
#5
好贴,希望坛中多多有这种技术贴。
Reply View the author