نستكمل الرسم مع مكتبة كايرو
فى هذا المثال سننشئ شكل معقد بإستخدام مجموعة من القطع الناقصة
donut.py #!/usr/bin/python # ZetCode PyGTK tutorial # # This program creates a donut # with cairo library # # author: jan bodnar # website: zetcode.com # last edited: February 2009 import gtk import math class PyApp(gtk.Window): def __init__(self): super(PyApp, self).__init__() self.set_title("Donut") self.set_size_request(350, 250) self.set_position(gtk.WIN_POS_CENTER) self.connect("destroy", gtk.main_quit) darea = gtk.DrawingArea() darea.connect("expose-event", self.expose) self.add(darea) self.show_all() def expose(self, widget, event): cr = widget.window.cairo_create() cr.set_line_width(0.5) w = self.allocation.width h = self.allocation.height cr.translate(w/2, h/2) cr.arc(0, 0, 120, 0, 2*math.pi) cr.stroke() for i in range(36): cr.save() cr.rotate(i*math.pi/36) cr.scale(0.3, 1) cr.arc(0, 0, 120, 0, 2*math.pi) cr.restore() cr.stroke() PyApp() gtk.main()
فى هذا المثال ننشئ donut “دونة"
cr.translate(w/2, h/2) cr.arc(0, 0, 120, 0, 2*math.pi) cr.stroke()
فى البداية هناك قطع
for i in range(36): cr.save() cr.rotate(i*math.pi/36) cr.scale(0.3, 1) cr.arc(0, 0, 120, 0, 2*math.pi) cr.restore() cr.stroke()
بعد عدة rotation نجد قطعة الحلوى :D
Figure: Donut
In computer graphics, gradient is a smooth blending of shades from light to dark or from one color to another. In 2D drawing programs and paint programs, gradients are used to create colorful backgrounds and special effects as well as to simulate lights and shadows. (answers.com)
gradients.py #!/usr/bin/python # ZetCode PyGTK tutorial # # This program works with # gradients in cairo # # author: jan bodnar # website: zetcode.com # last edited: February 2009 import gtk import cairo class PyApp(gtk.Window): def __init__(self): super(PyApp, self).__init__() self.set_title("Gradients") self.set_size_request(340, 390) self.set_position(gtk.WIN_POS_CENTER) self.connect("destroy", gtk.main_quit) darea = gtk.DrawingArea() darea.connect("expose-event", self.expose) self.add(darea) self.show_all() def expose(self, widget, event): cr = widget.window.cairo_create() lg1 = cairo.LinearGradient(0.0, 0.0, 350.0, 350.0) count = 1 i = 0.1 while i < 1.0: if count % 2: lg1.add_color_stop_rgba(i, 0, 0, 0, 1) else: lg1.add_color_stop_rgba(i, 1, 0, 0, 1) i = i + 0.1 count = count + 1 cr.rectangle(20, 20, 300, 100) cr.set_source(lg1) cr.fill() lg2 = cairo.LinearGradient(0.0, 0.0, 350.0, 0) count = 1 i = 0.05 while i < 0.95: if count % 2: lg2.add_color_stop_rgba(i, 0, 0, 0, 1) else: lg2.add_color_stop_rgba(i, 0, 0, 1, 1) i = i + 0.025 count = count + 1 cr.rectangle(20, 140, 300, 100) cr.set_source(lg2) cr.fill() lg3 = cairo.LinearGradient(20.0, 260.0, 20.0, 360.0) lg3.add_color_stop_rgba(0.1, 0, 0, 0, 1) lg3.add_color_stop_rgba(0.5, 1, 1, 0, 1) lg3.add_color_stop_rgba(0.9, 0, 0, 0, 1) cr.rectangle(20, 260, 300, 100) cr.set_source(lg3) cr.fill() PyApp() gtk.main()
فى مثالنا لدينا 3 مستطيلات بجرادينتات مختلفة
lg1 = cairo.LinearGradient(0.0, 0.0, 350.0, 350.0)هنا ننشئ نمط لجرادينت خطى.. والمعاملات هى السطر اللذى عليه نرسم الجرادينت.. فى حالتنا هنا هو خط رأسى
lg3 = cairo.LinearGradient(20.0, 260.0, 20.0, 360.0) lg3.add_color_stop_rgba(0.1, 0, 0, 0, 1) lg3.add_color_stop_rgba(0.5, 1, 1, 0, 1) lg3.add_color_stop_rgba(0.9, 0, 0, 0, 1)
نحدد موقفات للون لإنشاء نمط الجرادينت وهنا يجمع بين الأسود والأصفر.. وبإضافة لونين اسود وتوقف اصفر ننشئ نمط جرادينت افقى.. ماذا تعنى تلك التوقفات حقيقة ؟فى حالتنا هذه نبدأ باللون الأسود اللذى يتوقف عند عشر مساحته ثم يبدأ برسم الأصفر تصاعديا التى ستتوج مركز الشكل.. ويتوقف الأصفر عند 9 من 10 المساحة حيث نعود نرسم الأسود مجددا وهكذا
Figure: Gradients
فى المثال التالى سننشئ تأثير puff.. فى المثال نعرض نص فى المنتصف يكبر حتى حد معين ثم يتلاشى
puff.py #!/usr/bin/python # ZetCode PyGTK tutorial # # This program creates a puff # effect # # author: jan bodnar # website: zetcode.com # last edited: February 2009 import gtk import glib import cairo class PyApp(gtk.Window): def __init__(self): super(PyApp, self).__init__() self.set_title("Puff") self.resize(350, 200) self.set_position(gtk.WIN_POS_CENTER) self.connect("destroy", gtk.main_quit) self.darea = gtk.DrawingArea() self.darea.connect("expose-event", self.expose) self.add(self.darea) self.timer = True self.alpha = 1.0 self.size = 1.0 glib.timeout_add(14, self.on_timer) self.show_all() def on_timer(self): if not self.timer: return False self.darea.queue_draw() return True def expose(self, widget, event): cr = widget.window.cairo_create() w = self.allocation.width h = self.allocation.height cr.set_source_rgb(0.5, 0, 0) cr.paint() cr.select_font_face("Courier", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_BOLD) self.size = self.size + 0.8 if self.size > 20: self.alpha = self.alpha - 0.01 cr.set_font_size(self.size) cr.set_source_rgb(1, 1, 1) (x, y, width, height, dx, dy) = cr.text_extents("ZetCode") cr.move_to(w/2 - width/2, h/2) cr.text_path("ZetCode") cr.clip() cr.stroke() cr.paint_with_alpha(self.alpha) if self.alpha <= 0: self.timer = False PyApp() gtk.main()
فى هذا المثال سننشئ نص يكبر ويتلاشى على النافذة.
glib.timeout_add(14, self.on_timer)يتم استدعاء التايمر -المؤقت- كل 14 ميلى ثانية
def on_timer(self): if not self.timer: return False self.darea.queue_draw() return True
فى الطريقة on_timer نستدعى الطريقة queue_draw خلال الرسم فى منطقة الرسم مما يطلق اشارة expose
cr.set_source_rgb(0.5, 0, 0) cr.paint()
نجعل الخلفية احمر غامق
self.size = self.size + 0.8مع كل دورة يزيد حجم الخط بمقدار 0.8
if self.size > 20: self.alpha = self.alpha - 0.01
الشحوب يبدأ عندما يزيد حجم الخط عن 20
(x, y, width, height, dx, dy) = cr.text_extents("ZetCode")نحصل على مقاييس النص
cr.move_to(w/2 - width/2, h/2)نستخدم مقاييس النص لسنترته -وضعه بالمنتصف- على النافذه
cr.text_path("ZetCode") cr.clip()
نحصل على مسار النص ونحدد منطقة القصاصة الحالية
cr.stroke() cr.paint_with_alpha(self.alpha)
نرسم المسار مع استخدام قيمة الفا
Figure: Puff
فى المثال التالى سنعرض صورة منعكسة.. هذا التأثير الجميل يخلق وهم ان الصورة منعكسة فى الماء
reflection.cs #!/usr/bin/python # ZetCode PyGTK tutorial # # This program creates an # image reflection # # author: jan bodnar # website: zetcode.com # last edited: February 2009 import gtk import cairo import sys class PyApp(gtk.Window): def __init__(self): super(PyApp, self).__init__() self.set_title("Reflection") self.resize(300, 350) self.set_position(gtk.WIN_POS_CENTER) self.connect("destroy", gtk.main_quit) darea = gtk.DrawingArea() darea.connect("expose-event", self.expose) self.add(darea) try: self.surface = cairo.ImageSurface.create_from_png("slanec.png") except Exception, e: print e.message sys.exit(1) self.imageWidth = self.surface.get_width() self.imageHeight = self.surface.get_height() self.gap = 40 self.border = 20 self.show_all() def expose(self, widget, event): cr = widget.window.cairo_create() w = self.allocation.width h = self.allocation.height lg = cairo.LinearGradient(w/2, 0, w/2, h*3) lg.add_color_stop_rgba(0, 0, 0, 0, 1) lg.add_color_stop_rgba(h, 0.2, 0.2, 0.2, 1) cr.set_source(lg) cr.paint() cr.set_source_surface(self.surface, self.border, self.border) cr.paint() alpha = 0.7 step = 1.0 / self.imageHeight cr.translate(0, 2 * self.imageHeight + self.gap) cr.scale(1, -1) i = 0 while(i < self.imageHeight): cr.rectangle(self.border, self.imageHeight-i, self.imageWidth, 1) i = i + 1 cr.clip() cr.set_source_surface(self.surface, self.border, self.border) alpha = alpha - step cr.paint_with_alpha(alpha) cr.reset_clip() PyApp() gtk.main()
هذا المثال يظهر قلعة منعكسة
lg = cairo.LinearGradient(w/2, 0, w/2, h*3) lg.add_color_stop_rgba(0, 0, 0, 0, 1) lg.add_color_stop_rgba(h, 0.2, 0.2, 0.2, 1) cr.set_source(lg) cr.paint()
الخلفية ممتلئة بجرادينت يمزج بين الأسود والرمادى الغامق
cr.translate(0, 2 * self.imageHeight + self.gap) cr.scale(1, -1)
هذا الكود يعكس الصورة ويترجمها اسفل الصورة الأصلية.. عملية الترجمة مهمة لأن عملية الscaling تعكس الصورة اسفل لأعلى
cr.rectangle(self.border, self.imageHeight-i, self.imageWidth, 1) i = i + 1 cr.clip() cr.set_source_surface(self.surface, self.border, self.border) alpha = alpha - step cr.paint_with_alpha(alpha) cr.reset_clip()
الجزء الحاسم من الكود نجعل فيه الصورة الثانية شفافة -الشفافية ليست ثابته- حيث تتلاشى الصورة تصاعديا ويتم ذلك من خلال GradientPaint
Figure: Reflection
فى هذا المثال سنستخدم الشفافية لإنشاء "انتظار" فيه سنرسم 8 اسطر التى تشحب لخلق وهم بأن الخط يتحرك.. مثل هذه المؤثرات تستخدم لإعلام المستخدمين بأن مهمة طويلة تحدث فى الكواليس :)
waiting.py #!/usr/bin/python # ZetCode PyGTK tutorial # # This program creates an # waiting effect # # author: jan bodnar # website: zetcode.com # last edited: February 2009 import gtk import glib import math import cairo trs = ( ( 0.0, 0.15, 0.30, 0.5, 0.65, 0.80, 0.9, 1.0 ), ( 1.0, 0.0, 0.15, 0.30, 0.5, 0.65, 0.8, 0.9 ), ( 0.9, 1.0, 0.0, 0.15, 0.3, 0.5, 0.65, 0.8 ), ( 0.8, 0.9, 1.0, 0.0, 0.15, 0.3, 0.5, 0.65 ), ( 0.65, 0.8, 0.9, 1.0, 0.0, 0.15, 0.3, 0.5 ), ( 0.5, 0.65, 0.8, 0.9, 1.0, 0.0, 0.15, 0.3 ), ( 0.3, 0.5, 0.65, 0.8, 0.9, 1.0, 0.0, 0.15 ), ( 0.15, 0.3, 0.5, 0.65, 0.8, 0.9, 1.0, 0.0, ) ) class PyApp(gtk.Window): def __init__(self): super(PyApp, self).__init__() self.set_title("Waiting") self.set_size_request(250, 150) self.set_position(gtk.WIN_POS_CENTER) self.connect("destroy", gtk.main_quit) self.darea = gtk.DrawingArea() self.darea.connect("expose-event", self.expose) self.add(self.darea) self.count = 0 glib.timeout_add(100, self.on_timer) self.show_all() def on_timer(self): self.count = self.count + 1 self.darea.queue_draw() return True def expose(self, widget, event): cr = widget.window.cairo_create() cr.set_line_width(3) cr.set_line_cap(cairo.LINE_CAP_ROUND) w = self.allocation.width h = self.allocation.height cr.translate(w/2, h/2) for i in range(8): cr.set_source_rgba(0, 0, 0, trs[self.count%8][i]) cr.move_to(0.0, -10.0) cr.line_to(0.0, -40.0) cr.rotate(math.pi/4) cr.stroke() PyApp() gtk.main()
نرسم ال 8 اسطر بقيم الفا مختلفة
glib.timeout_add(100, self.on_timer)نستخدم التايمر لعمل الأنيميشن
trs = ( ( 0.0, 0.15, 0.30, 0.5, 0.65, 0.80, 0.9, 1.0 ), ... )
هذه مصفوفة ثنائية الأبعاد مستخدمه فى هذا العرض.. هناك 8 صفوف كل منها لحالة.. كل من ال 8 اسطر يستخدمها
cr.set_line_width(3) cr.set_line_cap(cairo.LINE_CAP_ROUND)
نجعل الأسطر اسمك، ليصبحو اكثر وضوحا.. نرسم
cr.set_source_rgba(0, 0, 0, trs[self.count%8][i]هنا نحدد الشفافية لسطر
cr.move_to(0.0, -10.0) cr.line_to(0.0, -40.0) cr.rotate(math.pi/4) cr.stroke()
هذا الكود سيقوم برسم ال 8 سطور
Figure: Waiting
فى هذا الفصل عملنا بعض الرسم المتقدم بإستخدام كايرو
Home Contents Top of Page