docs:cairographics
اختلافات
عرض الاختلافات بين النسخة المختارة و النسخة الحالية من الصفحة.
جانبي المراجعة السابقةالمراجعة السابقة | |||
docs:cairographics [2009/06/26 09:49] – ayoussef | docs:cairographics [2015/04/23 03:19] (حالي) – تحرير خارجي 127.0.0.1 | ||
---|---|---|---|
سطر 1: | سطر 1: | ||
+ | {{tag> | ||
+ | ~~ODT~~ | ||
+ | |||
+ | ====== مكتبة الرسم المتجهي Cairo ====== | ||
+ | |||
+ | * مقالة من تأليف Jan Bodnar | ||
+ | * المصدر http:// | ||
+ | * ترجمة // | ||
+ | * قيد المراجعة | ||
+ | |||
+ | هذه دروس عن كايرو تم كتابتها بلغة سي، ومناسبة للمطورين مبتدأين ومتوسطين. لاتنس الإطلاع على دروس GTK+ | ||
+ | |||
+ | |||
+ | ===== كايرو مكتبة الرسوميات ===== | ||
+ | |||
+ | |||
+ | مرحبا بك فى دروس كايرو، فى هذه الدروس ستتعلم الأساسيات وبعض المواضيع المتقدمة فى مكتبة كايرو للرسم المتجهى. لمعظم الأمثلة سنستخدم مكتبة GTK+ ولغة السى | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ==== الرسم المتجهى ==== | ||
+ | |||
+ | |||
+ | هنا نوعان من جرافيك الكمبيوتر **متجهى** و **raster** | ||
+ | ال Raster يمثل الصور على انها مجموعة من البكسلز بينما المتجهى يعتمد على اساسيات الأشكال من نقاط وخطوط ومنحنيات ليعبر عن الصور. ويتم عملها بناء على معادلات رياضية. | ||
+ | كلا النوعين لهما ميزات وعيوب.. من مميزات المتجهى على ال raster التالى: | ||
+ | |||
+ | * مساحة اصغر | ||
+ | * امكانية التكبير -zoom- لانهائى | ||
+ | * النقل والتوسيع والملأ او الدوران لا تقلل من جودة الصورة | ||
+ | |||
+ | ==== كايرو ==== | ||
+ | |||
+ | كايرو هى مكتبة للرسم المتجهى ثنائى الأبعاد. مكتوبة بلغة C ويمكن استخدامها عن طريق لغات اخرى مثل Python, Perl, C++, Java, | ||
+ | |||
+ | |||
+ | تتدعم كايرو backends مختلفة مثلا | ||
+ | |||
+ | * X Window System | ||
+ | * Win32 GDI | ||
+ | * Mac OS X Quartz | ||
+ | * PNG | ||
+ | |||
+ | * PostScript | ||
+ | * SVG | ||
+ | |||
+ | |||
+ | |||
+ | مما يعنى اننا نستطيع ان نرسم على ويندوز، على لينكس او غيرهم ونستطيع استخدامها لعمل صور PNG وملفات PDF وملفات PostScript وايضا ملفات SVG | ||
+ | |||
+ | نستطيع انا نقارن مكتبة كايرو بال **GDI** فى ويندوز او **Quartz 2D** فى ماك. كايرو مكتبة مفتوحة المصدر. ومنذ الإصدار 2.8 اصبحت جزء من **GTK+** | ||
+ | |||
+ | ==== ترجمة الأمثلة ==== | ||
+ | |||
+ | |||
+ | الأمثلة مكتوبة بلغة C .فسنستخدم GCC لترجمتهم | ||
+ | |||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | gcc -o example `pkg-config --cflags --libs gtk+-2.0` example.c | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ===== تعريفات كايرو ===== | ||
+ | |||
+ | فى هذه الجزئية سنقدم بعض التعريفات المفيدة لفهم افضل مع نظام الرسم فى كايرو | ||
+ | |||
+ | |||
+ | |||
+ | ==== السياق ==== | ||
+ | |||
+ | لعمل بعض الرسم فى كايرو، يجب اولا انشاء سياق، ليحمل كل معاملات حالة الرسم. وهذا يشمل معلومات مثل سمك الخط واللون. | ||
+ | السطح: هو المكان للرسم اليه وبعض الأشياء الأخرى. فهو يسمح لدوال الرسم الأصلية بأخذ معاملات اقل لتسهيل ال Interface مثلا **gdk_cairo_create()** تنشئ سياق للرسم الى المرسوم | ||
+ | |||
+ | |||
+ | |||
+ | To do some drawing in Cairo, we must first create a Cairo context. The Cairo context holds all of the graphics state parameters that describe how drawing is to be done. This includes information such as line width, color, the surface to draw to, and many other things. This allows the actual drawing functions to take fewer arguments to simplify the interface. The **gdk_cairo_create()** function call creates a cairo context for drawing to drawable. | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | cairo_t *cr; | ||
+ | cr = gdk_cairo_create(widget-> | ||
+ | </ | ||
+ | |||
+ | |||
+ | السطرين السابقين انشأو سياق. لاحظ ان السياق مرتبط ب **GdkDrawable** | ||
+ | البناء cairo_t يشمل حالة المٌرندر واحداثيات الأشكال اللتى سترسم. الكائنات المنشئة من البناء cairo_t تدعى سياقات كايرو | ||
+ | |||
+ | |||
+ | كل الرسم يتم دائما الى كائن cairo_t .السياق مرتبط بسطح ما، PDF, SVG, PNG, GtkDrawable .. الخ | ||
+ | |||
+ | GDK لاتغلف Cairo. تسمح بإنشاء سياق ليستخدم فى الرسم على اى سطح قابل للرسم عليه. الدوال الإضافية تسمح بتحويل المستطيلات والمناطق الخاصة بGDK الى مسارات و pixbufs كمصدر لعملية الرسم | ||
+ | |||
+ | |||
+ | |||
+ | ==== المسار ==== | ||
+ | |||
+ | |||
+ | المسار يتكون من خط او اكثر، كل من الخطوط مرتبط بنقطتين او اكتر. | ||
+ | المسارات ممكن ان تتكون من خطوط مستقيمة او منحنيات. | ||
+ | هناك نوعين من المسارات: | ||
+ | |||
+ | فى كايرو نبدأ بمسار خالى. اولا نقوم بتعريف المسار ثم نجعله ظاهرة بال stroking والملء. | ||
+ | ملحوظة مهمة: بعد كل استدعاء ل **cairo_stroke()** او **cairo_fill()** يتم تفريغ المسار. فيجب علينا اعادة تعريف مسار جديد. | ||
+ | المسار يتكون من عدة مسارات فرعية | ||
+ | |||
+ | |||
+ | |||
+ | ==== المصدر ==== | ||
+ | |||
+ | هو الدهان او الطلاء الذى سنستخدمه فى الرسم. نستطيع ان نشبه بالحبر. وسنستخدمه لعملية التحديد الخارجى وملء الأشكال. | ||
+ | هناك 4 انواع من المصادر: | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ==== السطح ==== | ||
+ | |||
+ | |||
+ | السطح هو الوجهة اللتى سنرسم اليها. نستطيع " | ||
+ | |||
+ | |||
+ | الوثائق ذكرت الأسطح التالية: | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | typedef enum _cairo_surface_type { | ||
+ | CAIRO_SURFACE_TYPE_IMAGE, | ||
+ | CAIRO_SURFACE_TYPE_PDF, | ||
+ | CAIRO_SURFACE_TYPE_PS, | ||
+ | CAIRO_SURFACE_TYPE_XLIB, | ||
+ | CAIRO_SURFACE_TYPE_XCB, | ||
+ | CAIRO_SURFACE_TYPE_GLITZ, | ||
+ | CAIRO_SURFACE_TYPE_QUARTZ, | ||
+ | CAIRO_SURFACE_TYPE_WIN32, | ||
+ | CAIRO_SURFACE_TYPE_BEOS, | ||
+ | CAIRO_SURFACE_TYPE_DIRECTFB, | ||
+ | CAIRO_SURFACE_TYPE_SVG, | ||
+ | CAIRO_SURFACE_TYPE_OS2 | ||
+ | } cairo_surface_type_t; | ||
+ | </ | ||
+ | |||
+ | ==== القناع ==== | ||
+ | |||
+ | قبل ان يتم تطبيق المصدر على السطح يتم ترشيحه -فلترته- اولا. فيستخدم القناع كمرشح -فلتر-. يحدد اي الأماكن سيتم تطبيق المصدر | ||
+ | |||
+ | الأجزاء الغير شفافة فى القناع تتيح نسخ المصدر بعكس الأجزاء الشفافة | ||
+ | Before the source is applied to the surface, it is filtered first. The mask is used as a filter. The mask determines, | ||
+ | where the sourse is applied and where not. Opaque parts of the mask allow to copy the source. Transparent parts do not | ||
+ | let to copy the source to the surface. | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ==== النمط ==== | ||
+ | |||
+ | النمط فى كايرو يعبر عن المصدر عند الرسم، فى كايرو: النمط هو شئ تستطيع ان تقرا منه يستخدم كمصدر او مرشح لعملية الرسم وقد يكون مصمت او متدرج او غيره | ||
+ | |||
+ | |||
+ | A cairo pattern represents a source when drawing onto a surface. | ||
+ | In cairo, a pattern is something that you can read from, that is used as the source or mask of a drawing operation. Patterns in cairo can be solid, surface-based, | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ===== Cairo backends ===== | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | The Cairo library supports various backends. In this section of the Cairo graphics tutorial, we will use | ||
+ | Cairo to create a PNG image, PDF file, SVG file and we will draw on a GTK window. | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ==== PNG image ==== | ||
+ | |||
+ | |||
+ | |||
+ | فى اول مثال سننشئ صورة PNG | ||
+ | |||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | #include & | ||
+ | |||
+ | int main (int argc, char *argv[]) | ||
+ | { | ||
+ | cairo_surface_t *surface; | ||
+ | cairo_t *cr; | ||
+ | |||
+ | surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, | ||
+ | cr = cairo_create(surface); | ||
+ | |||
+ | cairo_set_source_rgb(cr, | ||
+ | cairo_select_font_face(cr, | ||
+ | CAIRO_FONT_WEIGHT_NORMAL); | ||
+ | cairo_set_font_size(cr, | ||
+ | |||
+ | cairo_move_to(cr, | ||
+ | cairo_show_text(cr, | ||
+ | |||
+ | cairo_surface_write_to_png(surface, | ||
+ | |||
+ | cairo_destroy(cr); | ||
+ | cairo_surface_destroy(surface); | ||
+ | |||
+ | return 0; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | المثال تطبيق console لإنشاء صورة PNG | ||
+ | |||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | # | ||
+ | </ | ||
+ | |||
+ | |||
+ | فى الملف الرأسى نجد التعريفات للدوال والثوابت الخاصة بنا. | ||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | | ||
+ | </ | ||
+ | |||
+ | |||
+ | هنا نعرف السطح وسياق كايرو | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | cr = cairo_create(surface); | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | هنا انشئنا السطح والسياق. السطح 390*60 بكسل | ||
+ | |||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | </ | ||
+ | سنرسم بالحبر الإسود | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | CAIRO_FONT_WEIGHT_NORMAL); | ||
+ | | ||
+ | </ | ||
+ | |||
+ | |||
+ | نختار نوع الخط ونحدد الحجم | ||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | | ||
+ | </ | ||
+ | |||
+ | ننتقل الى الموضع a (10.0, 50.0) فى الصورة ونرسم النص | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | الدالة السابقة تنشئ صورة ال PNG | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | فى النهاية نقوم بالتخلص من المصادر -عملية تنظيف للمصادر المستخدمة- | ||
+ | |||
+ | |||
+ | |||
+ | {{ http:// | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ==== PDF file ==== | ||
+ | |||
+ | |||
+ | فى المثال التالى، سنستخدم مكتبة Cairo لعمل ملف PDF بسيط | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | #include & | ||
+ | #include & | ||
+ | |||
+ | int main() { | ||
+ | |||
+ | cairo_surface_t *surface; | ||
+ | cairo_t *cr; | ||
+ | |||
+ | surface = cairo_pdf_surface_create(" | ||
+ | cr = cairo_create(surface); | ||
+ | |||
+ | cairo_set_source_rgb(cr, | ||
+ | cairo_select_font_face (cr, " | ||
+ | CAIRO_FONT_WEIGHT_NORMAL); | ||
+ | cairo_set_font_size (cr, 40.0); | ||
+ | |||
+ | cairo_move_to(cr, | ||
+ | cairo_show_text(cr, | ||
+ | |||
+ | cairo_show_page(cr); | ||
+ | |||
+ | cairo_surface_destroy(surface); | ||
+ | cairo_destroy(cr); | ||
+ | |||
+ | return 0; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | يجب فتح الملف فى عارض PDF .مستخدمى لينكس يستطيعو استخدام KPDF او Evnice | ||
+ | |||
+ | We must open the pdf file in a pdf viewer. Linux users can use KPDF or Evince viewers. | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | </ | ||
+ | |||
+ | |||
+ | ل" | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | </ | ||
+ | |||
+ | الدالة **cairo_show_page()** تنهى ال " | ||
+ | |||
+ | |||
+ | |||
+ | {{ http:// | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ==== SVG file ==== | ||
+ | |||
+ | فى المثال التالى سننشئ ملف SVG (Scalable Vector Graphics) | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | #include & | ||
+ | #include & | ||
+ | |||
+ | int main() { | ||
+ | |||
+ | cairo_surface_t *surface; | ||
+ | cairo_t *cr; | ||
+ | |||
+ | surface = cairo_svg_surface_create(" | ||
+ | cr = cairo_create(surface); | ||
+ | |||
+ | cairo_set_source_rgb(cr, | ||
+ | cairo_select_font_face (cr, " | ||
+ | CAIRO_FONT_WEIGHT_NORMAL); | ||
+ | cairo_set_font_size (cr, 40.0); | ||
+ | |||
+ | cairo_move_to(cr, | ||
+ | cairo_show_text(cr, | ||
+ | |||
+ | cairo_surface_destroy(surface); | ||
+ | cairo_destroy(cr); | ||
+ | |||
+ | return 0; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | نستخدم فيرفكس ، اوبرا او انكسكيب لعرض ملفات ال svg | ||
+ | |||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | </ | ||
+ | |||
+ | لإنشاء ملف SVG يجب اولا انشاء سطح SVG عن طريق **cairo_svg_surface_create()** | ||
+ | |||
+ | |||
+ | باقى الكود مشابة للسابق | ||
+ | |||
+ | |||
+ | |||
+ | {{ http:// | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ==== نافذة GTK ==== | ||
+ | |||
+ | فى المثال الأخير سنقوم بالرسم على نافذة GTK وسنقوم بإستخدامها على مدار باقى الدروس | ||
+ | |||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | #include & | ||
+ | #include & | ||
+ | |||
+ | static gboolean | ||
+ | on_expose_event(GtkWidget | ||
+ | GdkEventExpose *event, | ||
+ | gpointer | ||
+ | { | ||
+ | cairo_t *cr; | ||
+ | |||
+ | cr = gdk_cairo_create(widget-> | ||
+ | |||
+ | cairo_set_source_rgb(cr, | ||
+ | cairo_select_font_face(cr, | ||
+ | CAIRO_FONT_WEIGHT_NORMAL); | ||
+ | cairo_set_font_size(cr, | ||
+ | |||
+ | cairo_move_to(cr, | ||
+ | cairo_show_text(cr, | ||
+ | |||
+ | cairo_destroy(cr); | ||
+ | |||
+ | return FALSE; | ||
+ | } | ||
+ | |||
+ | |||
+ | int | ||
+ | main (int argc, char *argv[]) | ||
+ | { | ||
+ | |||
+ | GtkWidget *window; | ||
+ | |||
+ | gtk_init(& | ||
+ | |||
+ | window = gtk_window_new(GTK_WINDOW_TOPLEVEL); | ||
+ | |||
+ | g_signal_connect(window, | ||
+ | G_CALLBACK (on_expose_event), | ||
+ | g_signal_connect(window, | ||
+ | G_CALLBACK (gtk_main_quit), | ||
+ | |||
+ | gtk_window_set_position(GTK_WINDOW(window), | ||
+ | gtk_window_set_default_size(GTK_WINDOW(window), | ||
+ | gtk_widget_set_app_paintable(window, | ||
+ | |||
+ | gtk_widget_show_all(window); | ||
+ | |||
+ | gtk_main(); | ||
+ | |||
+ | return 0; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | المثال يعرض نافذة فى منتصف الشاشة -متسنترة- نرسم عليها النص " | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | #include & | ||
+ | #include & | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | We include the necessary Cairo and GTK headers. | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | | ||
+ | </ | ||
+ | |||
+ | |||
+ | عند اعادة رسم النافذة يتم بعث الإشارة **expose-event** فنقوم بربطها بمعالج الإشارة | ||
+ | |||
+ | |||
+ | تقوم اداة التطوير بإعادة رسم المناطق المكشوفة بالنسبة للنوافذ العادية فستقوم بتصفية -محو- الخلفية. واذا اردت ان تقوم برسوماتك الخاصة يجب ان تعلم GTK عن ذلك عن طريق الدالة **gtk_widget_set_app_paintable** | ||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | </ | ||
+ | |||
+ | |||
+ | اذا اردت الرسم فى GTK+ فيمكننا الرسم على ويدجت **GtkDrawingArea** | ||
+ | للرسم على | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | |||
+ | cr = gdk_cairo_create(widget-> | ||
+ | </ | ||
+ | |||
+ | |||
+ | يتم الرسم فى معالج الإشارة **on_expose_event** ، فيه نقوم بإنشاء سياق كايرو ونرسم النص كالمعتاد. | ||
+ | |||
+ | |||
+ | {{ http:// | ||
+ | |||
+ | ===== اساسيات الرسم فى كايرو ===== | ||
+ | |||
+ | فى هذه الجزئية، سنقوم برسم بعض الأساسيات مثل الخطوط سنقوم بعمليتى الملء والتحديد وسنتكلم عن الداشات -dashes- وربط الخطوط | ||
+ | |||
+ | |||
+ | ==== الخطوط ==== | ||
+ | |||
+ | الخطوط هى كائنات اساسية فى المتجهات. لرسم سطر نستدعى دالتين.لتحديد نقطة البداية ب **cairo_move_to()** بينما نقطة النهاية تحدد ب **cairo_line_to()** | ||
+ | |||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | #include & | ||
+ | #include & | ||
+ | |||
+ | |||
+ | double coordx[100]; | ||
+ | double coordy[100]; | ||
+ | |||
+ | int count = 0; | ||
+ | |||
+ | static gboolean | ||
+ | on_expose_event(GtkWidget *widget, | ||
+ | GdkEventExpose *event, | ||
+ | gpointer data) | ||
+ | { | ||
+ | cairo_t *cr; | ||
+ | |||
+ | cr = gdk_cairo_create(widget-> | ||
+ | |||
+ | cairo_set_source_rgb(cr, | ||
+ | cairo_set_line_width (cr, 0.5); | ||
+ | |||
+ | int i, j; | ||
+ | for ( i = 0; i <= count - 1; i++ ) { | ||
+ | for ( j = 0; j <= count -1; j++ ) { | ||
+ | cairo_move_to(cr, | ||
+ | cairo_line_to(cr, | ||
+ | } | ||
+ | } | ||
+ | |||
+ | count = 0; | ||
+ | cairo_stroke(cr); | ||
+ | cairo_destroy(cr); | ||
+ | |||
+ | return FALSE; | ||
+ | } | ||
+ | |||
+ | gboolean clicked(GtkWidget *widget, GdkEventButton *event, | ||
+ | gpointer user_data) | ||
+ | { | ||
+ | if (event-> | ||
+ | coordx[count] = event-> | ||
+ | coordy[count++] = event-> | ||
+ | } | ||
+ | |||
+ | if (event-> | ||
+ | gtk_widget_queue_draw(widget); | ||
+ | } | ||
+ | |||
+ | return TRUE; | ||
+ | } | ||
+ | |||
+ | |||
+ | int | ||
+ | main (int argc, char *argv[]) | ||
+ | { | ||
+ | |||
+ | GtkWidget *window; | ||
+ | |||
+ | gtk_init(& | ||
+ | | ||
+ | window = gtk_window_new(GTK_WINDOW_TOPLEVEL); | ||
+ | |||
+ | gtk_widget_add_events (window, GDK_BUTTON_PRESS_MASK); | ||
+ | |||
+ | g_signal_connect(window, | ||
+ | G_CALLBACK(on_expose_event), | ||
+ | g_signal_connect(window, | ||
+ | G_CALLBACK(gtk_main_quit), | ||
+ | g_signal_connect(window, | ||
+ | G_CALLBACK(clicked), | ||
+ | |||
+ | gtk_window_set_position(GTK_WINDOW(window), | ||
+ | gtk_window_set_title(GTK_WINDOW(window), | ||
+ | gtk_window_set_default_size(GTK_WINDOW(window), | ||
+ | gtk_widget_set_app_paintable(window, | ||
+ | |||
+ | gtk_widget_show_all(window); | ||
+ | |||
+ | gtk_main(); | ||
+ | |||
+ | return 0; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | فى المثال، نضغط عشوائيا على النافذة بالزر الأيسر للفأرة، يتم تخزين كل ضغطه فى مصفوفة وعندما نضغط بالزر الأيمن يتم دمج جميع النقاط فى المصفوفة. بهذه الطريقة نستطيع عمل كائنات مثيرة للإهتمام. الضغط بالزر الأيمن يقوم بتصفية -تنظيف- النافذة ، ونستطيع الضغط لكائن اخر | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | هذه السطور سترسم بالحبر الإسود مع سمك 0.5 | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | int i, j; | ||
+ | for ( i = 0; i <= count - 1; i++ ) { | ||
+ | for ( j = 0; j <= count -1; j++ ) { | ||
+ | | ||
+ | | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | نربط كل النقاط مع النقط الأخرى | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | </ | ||
+ | الدالة **cairo_stroke()** تقوم برسم الخطوط | ||
+ | |||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | | ||
+ | </ | ||
+ | |||
+ | |||
+ | نربط **button-press-event** بالمعالج clicked | ||
+ | |||
+ | We connect the **button-press-event** to the clicked callback. | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | if (event-> | ||
+ | | ||
+ | | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | داخل المعالج clicked نقوم بتحديد هل كانت الضغطة على الفأرة بالزر الأيمن او الأيسر، إذا كان الأيسر نقوم بتخزين احداثيات x,y | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | if (event-> | ||
+ | | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | بالضغط على الزر الأيمن نعيد رسم النافذة | ||
+ | |||
+ | |||
+ | {{ http:// | ||
+ | |||
+ | |||
+ | ==== الملء والتحديد ==== | ||
+ | |||
+ | عملية ال stroke تقوم برسم الحدود الخارجية للشكل | ||
+ | عملية ال fill تقوم بملء ماداخل الشكل | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | #include & | ||
+ | #include & | ||
+ | #include & | ||
+ | |||
+ | static gboolean | ||
+ | on_expose_event (GtkWidget *widget, | ||
+ | GdkEventExpose *event, | ||
+ | gpointer data) | ||
+ | { | ||
+ | cairo_t *cr; | ||
+ | |||
+ | cr = gdk_cairo_create (widget-> | ||
+ | |||
+ | int width, height; | ||
+ | gtk_window_get_size(GTK_WINDOW(widget), | ||
+ | cairo_set_line_width(cr, | ||
+ | |||
+ | cairo_set_source_rgb(cr, | ||
+ | cairo_arc(cr, | ||
+ | (width < height ? width : height) / 2 - 10, 0, 2 * M_PI); | ||
+ | cairo_stroke_preserve(cr); | ||
+ | |||
+ | cairo_set_source_rgb(cr, | ||
+ | cairo_fill(cr); | ||
+ | |||
+ | cairo_destroy(cr); | ||
+ | |||
+ | return FALSE; | ||
+ | } | ||
+ | |||
+ | |||
+ | int | ||
+ | main (int argc, char *argv[]) | ||
+ | { | ||
+ | GtkWidget *window; | ||
+ | |||
+ | gtk_init(& | ||
+ | |||
+ | window = gtk_window_new(GTK_WINDOW_TOPLEVEL); | ||
+ | |||
+ | g_signal_connect(G_OBJECT(window), | ||
+ | G_CALLBACK(on_expose_event), | ||
+ | g_signal_connect(G_OBJECT(window), | ||
+ | G_CALLBACK(gtk_main_quit), | ||
+ | |||
+ | gtk_window_set_position(GTK_WINDOW(window), | ||
+ | gtk_window_set_default_size(GTK_WINDOW(window), | ||
+ | |||
+ | gtk_widget_set_app_paintable(window, | ||
+ | gtk_widget_show_all(window); | ||
+ | |||
+ | gtk_main(); | ||
+ | |||
+ | return 0; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | فى المثال سنقوم برسم دائرة | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | # | ||
+ | </ | ||
+ | |||
+ | |||
+ | نحتاج هذا الملف الرأسى للثابت **M_PI** | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | int width, height; | ||
+ | | ||
+ | </ | ||
+ | |||
+ | |||
+ | نحصل على عرض وارتفاع النافذة، نحتاج هذه القيم ليتم اعادة تحجيم الدائرة عند اعادة تحجيم النافذة | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | </ | ||
+ | |||
+ | نرسم الحدود الخارجية للدائرة | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | نملئها بلون ازرق | ||
+ | |||
+ | |||
+ | |||
+ | {{ http:// | ||
+ | |||
+ | |||
+ | < | ||
+ | |||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | --> | ||
+ | |||
+ | ==== Dash ==== | ||
+ | |||
+ | كل سطر يمكن ان يرسم ب داش مختلف. مما يحدد ستايل الخط. يستخدم الداش فى الدالة | ||
+ | |||
+ | نمط الداش يتم تحديده بالدالة **cairo_set_dash()** .ويتم تحديده من خلال مصفوفة الداش -مصفوفة من القيم الموجبة لتحديد الأماكن اللتى سيتم فيها رسم الخط داخل السطر. ايضا نقوم بتحديد طول المصفوفة وال offset . فى حال كان الطول للمصفوفة 0 يتم الغاء الداشينج. واذا كانت 1 يعتبر متماثل. ويحدد ال offset قيمة البداية -او بكلمات اخرى المساحة الفارغة عند البداية | ||
+ | |||
+ | <code cpp> | ||
+ | #include & | ||
+ | #include & | ||
+ | |||
+ | |||
+ | static gboolean | ||
+ | on_expose_event(GtkWidget *widget, | ||
+ | GdkEventExpose *event, | ||
+ | gpointer data) | ||
+ | { | ||
+ | cairo_t *cr; | ||
+ | |||
+ | cr = gdk_cairo_create (widget-> | ||
+ | |||
+ | cairo_set_source_rgba(cr, | ||
+ | |||
+ | static const double dashed1[] = {4.0, 1.0}; | ||
+ | static int len1 = sizeof(dashed1) / sizeof(dashed1[0]); | ||
+ | |||
+ | static const double dashed2[] = {4.0, 1.0, 4.0}; | ||
+ | static int len2 = sizeof(dashed2) / sizeof(dashed2[0]); | ||
+ | |||
+ | static const double dashed3[] = {1.0}; | ||
+ | |||
+ | cairo_set_line_width(cr, | ||
+ | |||
+ | cairo_set_dash(cr, | ||
+ | |||
+ | cairo_move_to(cr, | ||
+ | cairo_line_to(cr, | ||
+ | cairo_stroke(cr); | ||
+ | |||
+ | cairo_set_dash(cr, | ||
+ | |||
+ | cairo_move_to(cr, | ||
+ | cairo_line_to(cr, | ||
+ | cairo_stroke(cr); | ||
+ | |||
+ | cairo_set_dash(cr, | ||
+ | |||
+ | cairo_move_to(cr, | ||
+ | cairo_line_to(cr, | ||
+ | cairo_stroke(cr); | ||
+ | |||
+ | cairo_destroy(cr); | ||
+ | |||
+ | return FALSE; | ||
+ | } | ||
+ | |||
+ | |||
+ | int | ||
+ | main (int argc, char *argv[]) | ||
+ | { | ||
+ | |||
+ | GtkWidget *window; | ||
+ | GtkWidget *darea; | ||
+ | |||
+ | gtk_init(& | ||
+ | |||
+ | window = gtk_window_new(GTK_WINDOW_TOPLEVEL); | ||
+ | |||
+ | darea = gtk_drawing_area_new(); | ||
+ | gtk_container_add(GTK_CONTAINER(window), | ||
+ | |||
+ | g_signal_connect(darea, | ||
+ | G_CALLBACK (on_expose_event), | ||
+ | g_signal_connect(window, | ||
+ | G_CALLBACK (gtk_main_quit), | ||
+ | |||
+ | gtk_window_set_position(GTK_WINDOW(window), | ||
+ | gtk_window_set_default_size(GTK_WINDOW(window), | ||
+ | |||
+ | gtk_widget_show_all(window); | ||
+ | |||
+ | gtk_main(); | ||
+ | |||
+ | return 0; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | فى المثال، سنرسم 3 خطوط مع انماط داش مختلفة | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | </ | ||
+ | |||
+ | |||
+ | هنا نحدد اول نمط. سنرسم نمط من 4 بكسل ونقطة فارغة | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | </ | ||
+ | |||
+ | |||
+ | نحصل على حجم ال array | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | نحدد الداش | ||
+ | |||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | darea = gtk_drawing_area_new(); | ||
+ | | ||
+ | </ | ||
+ | |||
+ | |||
+ | فى المثال لانقوم بالرسم مباشرة ولكن عبر ال drawing area | ||
+ | |||
+ | |||
+ | |||
+ | {{ http:// | ||
+ | |||
+ | |||
+ | |||
+ | ==== Line caps ==== | ||
+ | |||
+ | ال Line caps هى نقط النهاية للخط | ||
+ | |||
+ | |||
+ | * CAIRO_LINE_CAP_SQUARE | ||
+ | * CAIRO_LINE_CAP_ROUND | ||
+ | * CAIRO_LINE_CAP_BUTT | ||
+ | |||
+ | |||
+ | |||
+ | هناك 3 انواع مختلفة فى كايرو | ||
+ | |||
+ | |||
+ | {{ http:// | ||
+ | |||
+ | الخط ب **CAIRO_LINE_CAP_SQUARE** سيكون لديه حجم مختلف عن خط ب **CAIRO_LINE_CAP_BUTT** | ||
+ | لو كان خط بعرض 1 بكسل فسيكون الخط ب **CAIRO_LINE_CAP_SQUARE** | ||
+ | ##FIXME | ||
+ | |||
+ | A line with a **CAIRO_LINE_CAP_SQUARE** cap will have a different size, than a line with a | ||
+ | **CAIRO_LINE_CAP_BUTT** cap. If a line is width px wide, the line with a **CAIRO_LINE_CAP_SQUARE** cap will be exactly width px greater in size. width/2 px at the beginning and width/2 px at the end. | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | #include & | ||
+ | #include & | ||
+ | |||
+ | |||
+ | static gboolean | ||
+ | on_expose_event(GtkWidget *widget, | ||
+ | GdkEventExpose *event, | ||
+ | gpointer data) | ||
+ | { | ||
+ | cairo_t *cr; | ||
+ | |||
+ | cr = gdk_cairo_create (widget-> | ||
+ | |||
+ | cairo_set_source_rgba(cr, | ||
+ | cairo_set_line_width(cr, | ||
+ | |||
+ | cairo_set_line_cap(cr, | ||
+ | cairo_move_to(cr, | ||
+ | cairo_line_to(cr, | ||
+ | cairo_stroke(cr); | ||
+ | |||
+ | cairo_set_line_cap(cr, | ||
+ | cairo_move_to(cr, | ||
+ | cairo_line_to(cr, | ||
+ | cairo_stroke(cr); | ||
+ | |||
+ | cairo_set_line_cap(cr, | ||
+ | cairo_move_to(cr, | ||
+ | cairo_line_to(cr, | ||
+ | cairo_stroke(cr); | ||
+ | |||
+ | cairo_set_line_width(cr, | ||
+ | |||
+ | cairo_move_to(cr, | ||
+ | cairo_line_to(cr, | ||
+ | cairo_stroke(cr); | ||
+ | |||
+ | cairo_move_to(cr, | ||
+ | cairo_line_to(cr, | ||
+ | cairo_stroke(cr); | ||
+ | |||
+ | cairo_move_to(cr, | ||
+ | cairo_line_to(cr, | ||
+ | cairo_stroke(cr); | ||
+ | |||
+ | cairo_destroy(cr); | ||
+ | |||
+ | return FALSE; | ||
+ | } | ||
+ | |||
+ | |||
+ | int | ||
+ | main (int argc, char *argv[]) | ||
+ | { | ||
+ | |||
+ | GtkWidget *window; | ||
+ | GtkWidget *darea; | ||
+ | |||
+ | gtk_init(& | ||
+ | |||
+ | window = gtk_window_new(GTK_WINDOW_TOPLEVEL); | ||
+ | |||
+ | darea = gtk_drawing_area_new (); | ||
+ | gtk_container_add(GTK_CONTAINER (window), darea); | ||
+ | |||
+ | g_signal_connect(darea, | ||
+ | G_CALLBACK(on_expose_event), | ||
+ | g_signal_connect(window, | ||
+ | G_CALLBACK(gtk_main_quit), | ||
+ | |||
+ | gtk_window_set_position(GTK_WINDOW(window), | ||
+ | gtk_window_set_default_size(GTK_WINDOW(window), | ||
+ | |||
+ | gtk_widget_show_all(window); | ||
+ | |||
+ | gtk_main(); | ||
+ | |||
+ | return 0; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | فى المثال نرسم 3 خطوط ب 3 caps مختلفة. سيعرضلنا ايضا الإختلاف فى المساحة للخطوط | ||
+ | The example draws three lines with three different caps. It will also graphically demonstrate the differences is size of the lines. | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | </ | ||
+ | |||
+ | |||
+ | خطوطنا ستكون بعرض 10 بكسل | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | </ | ||
+ | |||
+ | هنا نرسم خط افقى ب **CAIRO_LINE_CAP_ROUND** | ||
+ | |||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | |||
+ | | ||
+ | | ||
+ | | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | هذا الخط من ال 3 خطوط الرأسية يستخدم لعرض الفرق فى المساحة | ||
+ | This is one of the three vertical lines used to demostrate the differences in size. | ||
+ | |||
+ | |||
+ | {{ http:// | ||
+ | |||
+ | |||
+ | ==== رابطات الخطوط ==== | ||
+ | |||
+ | نستطيع ربط الخطوط ب3 ستايلات | ||
+ | |||
+ | |||
+ | * CAIRO_LINE_JOIN_MITER | ||
+ | * CAIRO_LINE_JOIN_BEVEL | ||
+ | * CAIRO_LINE_JOIN_ROUND | ||
+ | |||
+ | |||
+ | |||
+ | {{ http:// | ||
+ | |||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | #include & | ||
+ | #include & | ||
+ | |||
+ | static gboolean | ||
+ | on_expose_event(GtkWidget *widget, | ||
+ | GdkEventExpose *event, | ||
+ | gpointer data) | ||
+ | { | ||
+ | cairo_t *cr; | ||
+ | |||
+ | cr = gdk_cairo_create (widget-> | ||
+ | |||
+ | cairo_set_source_rgb(cr, | ||
+ | |||
+ | cairo_rectangle(cr, | ||
+ | cairo_set_line_width(cr, | ||
+ | cairo_set_line_join(cr, | ||
+ | cairo_stroke(cr); | ||
+ | |||
+ | cairo_rectangle(cr, | ||
+ | cairo_set_line_width(cr, | ||
+ | cairo_set_line_join(cr, | ||
+ | cairo_stroke(cr); | ||
+ | |||
+ | cairo_rectangle(cr, | ||
+ | cairo_set_line_width(cr, | ||
+ | cairo_set_line_join(cr, | ||
+ | cairo_stroke(cr); | ||
+ | |||
+ | cairo_destroy(cr); | ||
+ | |||
+ | return FALSE; | ||
+ | } | ||
+ | |||
+ | int | ||
+ | main (int argc, char *argv[]) | ||
+ | { | ||
+ | GtkWidget *window; | ||
+ | GtkWidget *darea; | ||
+ | |||
+ | gtk_init(& | ||
+ | |||
+ | window = gtk_window_new(GTK_WINDOW_TOPLEVEL); | ||
+ | |||
+ | darea = gtk_drawing_area_new(); | ||
+ | gtk_container_add(GTK_CONTAINER(window), | ||
+ | |||
+ | g_signal_connect(darea, | ||
+ | G_CALLBACK(on_expose_event), | ||
+ | g_signal_connect(window, | ||
+ | G_CALLBACK(gtk_main_quit), | ||
+ | |||
+ | gtk_window_set_position(GTK_WINDOW(window), | ||
+ | gtk_window_set_default_size(GTK_WINDOW(window), | ||
+ | |||
+ | gtk_widget_show_all(window); | ||
+ | |||
+ | gtk_main(); | ||
+ | |||
+ | return 0; | ||
+ | |||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | فى المثال نرسم 3 مستطيلات سميكة مع رابطات خطوط متنوعة. | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | فى هذا الكود، رسمنا مستطيل برابط **CAIRO_LINE_JOIN_MITER** | ||
+ | |||
+ | |||
+ | {{ http:// | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ===== الأشكال والملء فى كايرو ===== | ||
+ | |||
+ | |||
+ | فى هذه الجزئية سننشئ بعض الأشكال البسيطة والمتقدمة وسنملئهم بصورة بألوان مصمته، وانماط،وتدرجات | ||
+ | |||
+ | |||
+ | |||
+ | ==== الأشكال الأساسية ==== | ||
+ | |||
+ | تقدم لنا كايرو العديد من الدوال لإنشاء الأشكال الأساسية. | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | #include & | ||
+ | #include & | ||
+ | #include & | ||
+ | |||
+ | |||
+ | static gboolean | ||
+ | on_expose_event(GtkWidget *widget, | ||
+ | GdkEventExpose *event, | ||
+ | gpointer data) | ||
+ | { | ||
+ | cairo_t *cr; | ||
+ | |||
+ | cr = gdk_cairo_create (widget-> | ||
+ | |||
+ | cairo_set_source_rgb(cr, | ||
+ | cairo_set_line_width(cr, | ||
+ | |||
+ | cairo_rectangle(cr, | ||
+ | cairo_rectangle(cr, | ||
+ | cairo_stroke_preserve(cr); | ||
+ | cairo_set_source_rgb(cr, | ||
+ | cairo_fill(cr); | ||
+ | |||
+ | cairo_set_source_rgb(cr, | ||
+ | cairo_arc(cr, | ||
+ | cairo_stroke_preserve(cr); | ||
+ | cairo_set_source_rgb(cr, | ||
+ | cairo_fill(cr); | ||
+ | |||
+ | cairo_set_source_rgb(cr, | ||
+ | cairo_arc(cr, | ||
+ | cairo_close_path(cr); | ||
+ | cairo_stroke_preserve(cr); | ||
+ | cairo_set_source_rgb(cr, | ||
+ | cairo_fill(cr); | ||
+ | |||
+ | cairo_set_source_rgb(cr, | ||
+ | cairo_translate(cr, | ||
+ | cairo_scale(cr, | ||
+ | cairo_arc(cr, | ||
+ | cairo_stroke_preserve(cr); | ||
+ | cairo_set_source_rgb(cr, | ||
+ | cairo_fill(cr); | ||
+ | |||
+ | cairo_destroy(cr); | ||
+ | |||
+ | return FALSE; | ||
+ | } | ||
+ | |||
+ | |||
+ | int | ||
+ | main (int argc, char *argv[]) | ||
+ | { | ||
+ | |||
+ | GtkWidget *window; | ||
+ | GtkWidget *darea; | ||
+ | |||
+ | gtk_init(& | ||
+ | |||
+ | window = gtk_window_new(GTK_WINDOW_TOPLEVEL); | ||
+ | |||
+ | darea = gtk_drawing_area_new(); | ||
+ | gtk_container_add(GTK_CONTAINER (window), darea); | ||
+ | |||
+ | g_signal_connect(darea, | ||
+ | G_CALLBACK(on_expose_event), | ||
+ | g_signal_connect(window, | ||
+ | G_CALLBACK(gtk_main_quit), | ||
+ | |||
+ | gtk_window_set_position(GTK_WINDOW(window), | ||
+ | gtk_window_set_default_size(GTK_WINDOW(window), | ||
+ | |||
+ | gtk_widget_show_all(window); | ||
+ | |||
+ | gtk_main(); | ||
+ | |||
+ | return 0; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | فى المثال نرسم مستطيل، مربع، دائرة، قوس و قطع ناقص | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | | ||
+ | </ | ||
+ | |||
+ | الدالة **cairo_rectangle()** تستخدم لعمل مربعات ومستطيلات | ||
+ | -المربع هو نوع خاص من المستطيلات فيه الطول=العرض- | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | </ | ||
+ | |||
+ | هذا السطر ينشئ الدائرة | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | | ||
+ | </ | ||
+ | |||
+ | نستخدم **cairo_scale()** لإنشاء القطع الناقص | ||
+ | |||
+ | |||
+ | |||
+ | {{ http:// | ||
+ | الأشكال الأخرى -المعقد منها خصوصا- نستطيع انشاءها بتجميع الأساسيات | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | #include & | ||
+ | #include & | ||
+ | |||
+ | |||
+ | int points[11][2] = { | ||
+ | { 0, 85 }, | ||
+ | { 75, 75 }, | ||
+ | { 100, 10 }, | ||
+ | { 125, 75 }, | ||
+ | { 200, 85 }, | ||
+ | { 150, 125 }, | ||
+ | { 160, 190 }, | ||
+ | { 100, 150 }, | ||
+ | { 40, 190 }, | ||
+ | { 50, 125 }, | ||
+ | { 0, 85 } | ||
+ | }; | ||
+ | |||
+ | static gboolean | ||
+ | on_expose_event(GtkWidget *widget, | ||
+ | GdkEventExpose *event, | ||
+ | gpointer data) | ||
+ | { | ||
+ | cairo_t *cr; | ||
+ | |||
+ | cr = gdk_cairo_create (widget-> | ||
+ | |||
+ | cairo_set_source_rgb(cr, | ||
+ | cairo_set_line_width(cr, | ||
+ | |||
+ | |||
+ | gint i; | ||
+ | for ( i = 0; i < 10; i++ ) { | ||
+ | cairo_line_to(cr, | ||
+ | } | ||
+ | |||
+ | cairo_close_path(cr); | ||
+ | cairo_stroke_preserve(cr); | ||
+ | cairo_set_source_rgb(cr, | ||
+ | cairo_fill(cr); | ||
+ | |||
+ | |||
+ | cairo_move_to(cr, | ||
+ | cairo_line_to(cr, | ||
+ | cairo_line_to(cr, | ||
+ | cairo_close_path(cr); | ||
+ | |||
+ | cairo_set_source_rgb(cr, | ||
+ | cairo_stroke_preserve(cr); | ||
+ | cairo_set_source_rgb(cr, | ||
+ | cairo_fill(cr); | ||
+ | |||
+ | cairo_move_to(cr, | ||
+ | cairo_line_to(cr, | ||
+ | cairo_line_to(cr, | ||
+ | cairo_curve_to(cr, | ||
+ | |||
+ | cairo_set_source_rgb(cr, | ||
+ | cairo_stroke_preserve(cr); | ||
+ | cairo_set_source_rgb(cr, | ||
+ | cairo_fill(cr); | ||
+ | |||
+ | cairo_destroy(cr); | ||
+ | |||
+ | return FALSE; | ||
+ | } | ||
+ | |||
+ | |||
+ | int | ||
+ | main (int argc, char *argv[]) | ||
+ | { | ||
+ | |||
+ | GtkWidget *window; | ||
+ | GtkWidget *darea; | ||
+ | |||
+ | gtk_init(& | ||
+ | |||
+ | window = gtk_window_new(GTK_WINDOW_TOPLEVEL); | ||
+ | |||
+ | darea = gtk_drawing_area_new(); | ||
+ | gtk_container_add(GTK_CONTAINER (window), darea); | ||
+ | |||
+ | g_signal_connect(darea, | ||
+ | G_CALLBACK(on_expose_event), | ||
+ | g_signal_connect(window, | ||
+ | G_CALLBACK(gtk_main_quit), | ||
+ | |||
+ | gtk_window_set_position(GTK_WINDOW(window), | ||
+ | gtk_window_set_default_size(GTK_WINDOW(window), | ||
+ | |||
+ | gtk_widget_show_all(window); | ||
+ | |||
+ | gtk_main(); | ||
+ | |||
+ | return 0; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | فى هذا المثال ننشئ نجمة، مثلث -هذه الأشكال تنشئ عن طريق الخطوط ومنحنى | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | gint i; | ||
+ | for ( i = 0; i < 10; i++ ) { | ||
+ | | ||
+ | } | ||
+ | |||
+ | | ||
+ | </ | ||
+ | |||
+ | |||
+ | النجمة ترسم عن طريق جمع كل النقاط -الموجودة فى مصفوفة النقط-ويتم انهاء النجمة بإستدعاء **cairo_close_path()** | ||
+ | | ||
+ | <code cpp> | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | </ | ||
+ | |||
+ | |||
+ | المستطيل المعدل هو عبارة عن دمج لخطين ومنحنى. | ||
+ | |||
+ | |||
+ | {{ http:// | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ==== Fills ==== | ||
+ | |||
+ | |||
+ | |||
+ | المالئات ؟ | ||
+ | #FIXME : مش الأصل fillers ? | ||
+ | |||
+ | |||
+ | Fills fill the interiors of shapes. Fills can be solid colors, patters or gradients. | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | === Solid colors === | ||
+ | |||
+ | |||
+ | اللون هو كائن يمثل تجميعة من الأحمر والأخضر والأزرق RGB القيم المسموحة بين الفترة 0 و 1 | ||
+ | |||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | #include & | ||
+ | #include & | ||
+ | |||
+ | |||
+ | static gboolean | ||
+ | on_expose_event(GtkWidget *widget, | ||
+ | GdkEventExpose *event, | ||
+ | gpointer data) | ||
+ | { | ||
+ | cairo_t *cr; | ||
+ | |||
+ | cr = gdk_cairo_create(widget-> | ||
+ | |||
+ | int width, height; | ||
+ | gtk_window_get_size(GTK_WINDOW(widget), | ||
+ | |||
+ | |||
+ | cairo_set_source_rgb(cr, | ||
+ | cairo_rectangle(cr, | ||
+ | cairo_fill(cr); | ||
+ | |||
+ | cairo_set_source_rgb(cr, | ||
+ | cairo_rectangle(cr, | ||
+ | cairo_fill(cr); | ||
+ | |||
+ | cairo_set_source_rgb(cr, | ||
+ | cairo_rectangle(cr, | ||
+ | cairo_fill(cr); | ||
+ | |||
+ | cairo_set_source_rgb(cr, | ||
+ | cairo_rectangle(cr, | ||
+ | cairo_fill(cr); | ||
+ | |||
+ | cairo_destroy(cr); | ||
+ | |||
+ | return FALSE; | ||
+ | } | ||
+ | |||
+ | |||
+ | int | ||
+ | main (int argc, char *argv[]) | ||
+ | { | ||
+ | GtkWidget *window; | ||
+ | |||
+ | gtk_init(& | ||
+ | |||
+ | window = gtk_window_new(GTK_WINDOW_TOPLEVEL); | ||
+ | |||
+ | g_signal_connect(G_OBJECT(window), | ||
+ | G_CALLBACK(on_expose_event), | ||
+ | g_signal_connect(G_OBJECT(window), | ||
+ | G_CALLBACK(gtk_main_quit), | ||
+ | |||
+ | gtk_window_set_position(GTK_WINDOW(window), | ||
+ | gtk_window_set_default_size(GTK_WINDOW(window), | ||
+ | gtk_window_set_title(GTK_WINDOW(window), | ||
+ | |||
+ | gtk_widget_set_app_paintable(window, | ||
+ | gtk_widget_show_all(window); | ||
+ | |||
+ | gtk_main(); | ||
+ | |||
+ | return 0; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | فى المثال نرسم 4 مستطيلات ملونة. | ||
+ | |||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | | ||
+ | | ||
+ | </ | ||
+ | |||
+ | الدالة **cairo_set_source_rgb** تقوم بتحديد المصدر الى لون غير شفاف ومعاملاتها هى قيم الأحمر والأخضر والأزرق. | ||
+ | المصدر سيستخدم لملء داخل المستطيل ويتم ذلك عن طريق الدالة **cairo_fill** | ||
+ | |||
+ | |||
+ | |||
+ | {{ http:// | ||
+ | |||
+ | |||
+ | === الأنماط === | ||
+ | |||
+ | |||
+ | الأنماط هى كائنات رسومية معقدة يمكن ان تملء الأشكال. | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | #include & | ||
+ | #include & | ||
+ | |||
+ | cairo_surface_t *surface1; | ||
+ | cairo_surface_t *surface2; | ||
+ | cairo_surface_t *surface3; | ||
+ | cairo_surface_t *surface4; | ||
+ | |||
+ | static void create_surfaces() { | ||
+ | surface1 = cairo_image_surface_create_from_png(" | ||
+ | surface2 = cairo_image_surface_create_from_png(" | ||
+ | surface3 = cairo_image_surface_create_from_png(" | ||
+ | surface4 = cairo_image_surface_create_from_png(" | ||
+ | } | ||
+ | |||
+ | static void destroy_surfaces() { | ||
+ | g_print(" | ||
+ | cairo_surface_destroy(surface1); | ||
+ | cairo_surface_destroy(surface2); | ||
+ | cairo_surface_destroy(surface3); | ||
+ | cairo_surface_destroy(surface4); | ||
+ | } | ||
+ | |||
+ | |||
+ | static gboolean | ||
+ | on_expose_event(GtkWidget *widget, | ||
+ | GdkEventExpose *event, | ||
+ | gpointer data) | ||
+ | { | ||
+ | cairo_t *cr; | ||
+ | |||
+ | cairo_pattern_t *pattern1; | ||
+ | cairo_pattern_t *pattern2; | ||
+ | cairo_pattern_t *pattern3; | ||
+ | cairo_pattern_t *pattern4; | ||
+ | |||
+ | cr = gdk_cairo_create(widget-> | ||
+ | |||
+ | int width, height; | ||
+ | gtk_window_get_size(GTK_WINDOW(widget), | ||
+ | |||
+ | |||
+ | pattern1 = cairo_pattern_create_for_surface(surface1); | ||
+ | pattern2 = cairo_pattern_create_for_surface(surface2); | ||
+ | pattern3 = cairo_pattern_create_for_surface(surface3); | ||
+ | pattern4 = cairo_pattern_create_for_surface(surface4); | ||
+ | |||
+ | |||
+ | cairo_set_source(cr, | ||
+ | cairo_pattern_set_extend(cairo_get_source(cr), | ||
+ | cairo_rectangle(cr, | ||
+ | cairo_fill(cr); | ||
+ | |||
+ | cairo_set_source(cr, | ||
+ | cairo_pattern_set_extend(cairo_get_source(cr), | ||
+ | cairo_rectangle(cr, | ||
+ | cairo_fill(cr); | ||
+ | |||
+ | cairo_set_source(cr, | ||
+ | cairo_pattern_set_extend(cairo_get_source(cr), | ||
+ | cairo_rectangle(cr, | ||
+ | cairo_fill(cr); | ||
+ | |||
+ | cairo_set_source(cr, | ||
+ | cairo_pattern_set_extend(cairo_get_source(cr), | ||
+ | cairo_rectangle(cr, | ||
+ | cairo_fill(cr); | ||
+ | |||
+ | cairo_pattern_destroy(pattern1); | ||
+ | cairo_pattern_destroy(pattern2); | ||
+ | cairo_pattern_destroy(pattern3); | ||
+ | cairo_pattern_destroy(pattern4); | ||
+ | |||
+ | cairo_destroy(cr); | ||
+ | |||
+ | return FALSE; | ||
+ | } | ||
+ | |||
+ | |||
+ | int | ||
+ | main (int argc, char *argv[]) | ||
+ | { | ||
+ | GtkWidget *window; | ||
+ | |||
+ | gtk_init(& | ||
+ | |||
+ | window = gtk_window_new(GTK_WINDOW_TOPLEVEL); | ||
+ | |||
+ | g_signal_connect(G_OBJECT(window), | ||
+ | G_CALLBACK(on_expose_event), | ||
+ | g_signal_connect(G_OBJECT(window), | ||
+ | G_CALLBACK(gtk_main_quit), | ||
+ | |||
+ | create_surfaces(); | ||
+ | |||
+ | gtk_window_set_position(GTK_WINDOW(window), | ||
+ | gtk_window_set_default_size(GTK_WINDOW(window), | ||
+ | gtk_window_set_title(GTK_WINDOW(window), | ||
+ | |||
+ | gtk_widget_set_app_paintable(window, | ||
+ | gtk_widget_show_all(window); | ||
+ | |||
+ | gtk_main(); | ||
+ | |||
+ | destroy_surfaces(); | ||
+ | |||
+ | return 0; | ||
+ | } | ||
+ | |||
+ | </ | ||
+ | |||
+ | فى هذا المثال نرسم 4 مستطيلات مرة اخرى، ولكن هذه المرة نملئهم بإستخدام الأنماط -patterns-. نستخدم 4 انماط من برنامج **Gimp** لمعالجة الصور. | ||
+ | يجب ان نحتفظ بالحجم الأساسى للأنماط.. لأننا سوف ن tile هم ؟ | ||
+ | FIXME: هل تترجم على اننا سوف نبلطهم ؟ | ||
+ | |||
+ | ننشئ الأسطح خارج الدالة **on_expose_event** لأنا لانريد قرائتها من القرص الصلب كل مرة تريد فيها النافذة اعادة رسم نفسها. | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | We create a pattern from the surface by calling the **cairo_pattern_create_for_surface()** function. | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | cairo_set_source(cr, | ||
+ | cairo_pattern_set_extend(cairo_get_source(cr), | ||
+ | cairo_rectangle(cr, | ||
+ | cairo_fill(cr); | ||
+ | </ | ||
+ | |||
+ | **cairo_set_source** تخبر سياق كايرو ان تستخدم نمط كمصدر للرسم، ربما لاتتناسب الأنماط مع الشكل لذا نقوم بتحديدال mode الى **CAIRO_EXTEND_REPEAT** مما يقوم بتكرير النمط! | ||
+ | الدالة **cairo_rectangle** تنشئ مسار مستطيلى، واخيرا **cairo_fill** تملء ذلك المسار بالمصدر | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | {{ http:// | ||
+ | |||
+ | |||
+ | |||
+ | === Gradients === | ||
+ | |||
+ | #FIXME: التعبير المناسب لل Gradient ؟ | ||
+ | |||
+ | |||
+ | 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) | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | #include & | ||
+ | #include & | ||
+ | |||
+ | static gboolean | ||
+ | on_expose_event(GtkWidget *widget, | ||
+ | GdkEventExpose *event, | ||
+ | gpointer data) | ||
+ | { | ||
+ | cairo_t *cr; | ||
+ | cairo_pattern_t *pat1; | ||
+ | cairo_pattern_t *pat2; | ||
+ | cairo_pattern_t *pat3; | ||
+ | |||
+ | cr = gdk_cairo_create(widget-> | ||
+ | |||
+ | pat1 = cairo_pattern_create_linear(0.0, | ||
+ | |||
+ | gdouble j; | ||
+ | gint count = 1; | ||
+ | for ( j = 0.1; j < 1; j += 0.1 ) { | ||
+ | if (( count % 2 )) { | ||
+ | cairo_pattern_add_color_stop_rgb(pat1, | ||
+ | } else { | ||
+ | cairo_pattern_add_color_stop_rgb(pat1, | ||
+ | } | ||
+ | | ||
+ | } | ||
+ | |||
+ | cairo_rectangle(cr, | ||
+ | cairo_set_source(cr, | ||
+ | cairo_fill(cr); | ||
+ | |||
+ | |||
+ | pat2 = cairo_pattern_create_linear(0.0, | ||
+ | |||
+ | gdouble i; | ||
+ | count = 1; | ||
+ | for ( i = 0.05; i < 0.95; i += 0.025 ) { | ||
+ | if (( count % 2 )) { | ||
+ | cairo_pattern_add_color_stop_rgb(pat2, | ||
+ | } else { | ||
+ | cairo_pattern_add_color_stop_rgb(pat2, | ||
+ | } | ||
+ | | ||
+ | } | ||
+ | |||
+ | cairo_rectangle(cr, | ||
+ | cairo_set_source(cr, | ||
+ | cairo_fill(cr); | ||
+ | |||
+ | |||
+ | pat3 = cairo_pattern_create_linear(20.0, | ||
+ | |||
+ | cairo_pattern_add_color_stop_rgb(pat3, | ||
+ | cairo_pattern_add_color_stop_rgb(pat3, | ||
+ | cairo_pattern_add_color_stop_rgb(pat3, | ||
+ | |||
+ | cairo_rectangle(cr, | ||
+ | cairo_set_source(cr, | ||
+ | cairo_fill(cr); | ||
+ | |||
+ | cairo_pattern_destroy(pat1); | ||
+ | cairo_pattern_destroy(pat2); | ||
+ | cairo_pattern_destroy(pat3); | ||
+ | |||
+ | cairo_destroy(cr); | ||
+ | |||
+ | return FALSE; | ||
+ | } | ||
+ | |||
+ | |||
+ | int | ||
+ | main (int argc, char *argv[]) | ||
+ | { | ||
+ | GtkWidget *window; | ||
+ | |||
+ | gtk_init(& | ||
+ | |||
+ | window = gtk_window_new(GTK_WINDOW_TOPLEVEL); | ||
+ | |||
+ | g_signal_connect(G_OBJECT(window), | ||
+ | G_CALLBACK(on_expose_event), | ||
+ | g_signal_connect(G_OBJECT(window), | ||
+ | G_CALLBACK(gtk_main_quit), | ||
+ | |||
+ | gtk_window_set_position(GTK_WINDOW(window), | ||
+ | gtk_window_set_default_size(GTK_WINDOW(window), | ||
+ | gtk_window_set_title(GTK_WINDOW(window), | ||
+ | |||
+ | gtk_widget_set_app_paintable(window, | ||
+ | gtk_widget_show_all(window); | ||
+ | |||
+ | gtk_main(); | ||
+ | |||
+ | return 0; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | نقوم فى المثال برسم 3 مستطيلات ب 3 (تدرجات؟) مختلفة | ||
+ | In our example, we draw three rectangles with three different gradients. | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | pat3 = cairo_pattern_create_linear(20.0, | ||
+ | </ | ||
+ | |||
+ | |||
+ | هنا ننشئ نمط لجرادينت خطى.. والمعاملات هى السطر اللذى عليه نرسم الجرادينت.. فى حالتنا هنا هو خط رأسى | ||
+ | |||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | | ||
+ | | ||
+ | </ | ||
+ | |||
+ | |||
+ | نحدد موقفات للون لإنشاء نمط الجرادينت وهنا يجمع بين الأسود والأصفر.. وبإضافة لونين اسود وتوقف اصفر ننشئ نمط جرادينت افقى.. ماذا تعنى تلك التوقفات حقيقة ؟فى حالتنا هذه نبدأ باللون الأسود اللذى يتوقف عند عشر مساحته ثم يبدأ برسم الأصفر تصاعديا التى ستتوج مركز الشكل.. ويتوقف الأصفر عند 9 من 10 المساحة حيث نعود نرسم الأسود مجددا وهكذا | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | {{ http:// | ||
+ | |||
+ | ===== الشفافية ===== | ||
+ | |||
+ | فى هذه الجزئية سنتخدث عن الشفافية وبعض التعريفات الأساسية وتأثيرين مثيرين للإهتمام | ||
+ | |||
+ | الشفافية هى الجودة للقدرة على الرؤية عبر المادة. | ||
+ | ابسط طريقة لفهمها هى تخيل قطع من الزجاج او الماء، تقنيا اشعة الضوء تعبر سطح الزجاج او الماء لذا نستطيع ان نرى الأشياء خلفها | ||
+ | فى الحاسب، نستطيع الوصول لتأثيرات الشفافية عن طريق **alpha compositing**. | ||
+ | |||
+ | **alpha compositing** هى عملية لدمج صورة مع خلفية لجعل المظهر شفاف جزئيا. عملية ال composition تستخدم **alpha channel**. | ||
+ | |||
+ | alpha channel هى طبقة من 8 بت فى ملف جرافيك تستخدم للتعبير عن الشفافية. ال8 بت الإضافية لكل بكسل تعمل كقناع تعبر عن 256 مستوى للشفافية | ||
+ | |||
+ | In computer graphics, we can achieve transparency effects using | ||
+ | Alpha compositing is the process of combining an image with a background to create the appearance of partial transparency. | ||
+ | |||
+ | The composition process uses an **alpha channel**. | ||
+ | Alpha channel is an 8-bit layer in a graphics file format that is used for expressing translucency (transparency). The extra eight bits per pixel serves as a mask and represents 256 levels of translucency. | ||
+ | |||
+ | |||
+ | (answers.com, | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ==== المستطيلات الشفافة ==== | ||
+ | |||
+ | فى المثال سنرسم 10 مستطيلات ذات مستويات مختلفة من الشفافية | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | #include & | ||
+ | #include & | ||
+ | |||
+ | static gboolean | ||
+ | on_expose_event(GtkWidget *widget, | ||
+ | GdkEventExpose *event, | ||
+ | gpointer data) | ||
+ | { | ||
+ | cairo_t *cr; | ||
+ | |||
+ | cr = gdk_cairo_create(widget-> | ||
+ | |||
+ | gint i; | ||
+ | for ( i = 1; i <= 10; i++) { | ||
+ | cairo_set_source_rgba(cr, | ||
+ | cairo_rectangle(cr, | ||
+ | cairo_fill(cr); | ||
+ | } | ||
+ | |||
+ | |||
+ | cairo_destroy(cr); | ||
+ | |||
+ | return FALSE; | ||
+ | } | ||
+ | |||
+ | |||
+ | int | ||
+ | main (int argc, char *argv[]) | ||
+ | { | ||
+ | |||
+ | GtkWidget *window; | ||
+ | |||
+ | gtk_init(& | ||
+ | |||
+ | window = gtk_window_new(GTK_WINDOW_TOPLEVEL); | ||
+ | |||
+ | g_signal_connect(G_OBJECT(window), | ||
+ | G_CALLBACK(on_expose_event), | ||
+ | g_signal_connect(G_OBJECT(window), | ||
+ | G_CALLBACK(gtk_main_quit), | ||
+ | |||
+ | gtk_window_set_position(GTK_WINDOW(window), | ||
+ | gtk_window_set_default_size(GTK_WINDOW(window), | ||
+ | gtk_window_set_title(GTK_WINDOW(window), | ||
+ | |||
+ | gtk_widget_set_app_paintable(window, | ||
+ | gtk_widget_show_all(window); | ||
+ | |||
+ | gtk_main(); | ||
+ | |||
+ | return 0; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | **cairo_set_source_rgba()** لديها معامل اختيارى لقيمة الألفا للشفافية | ||
+ | |||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | gint i; | ||
+ | for ( i = 1; i <= 10; i++) { | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | هذا الكود ينشئ 10 مستطيلات ب قيم الفا تتدرج من 0.1 الى 1 | ||
+ | |||
+ | |||
+ | |||
+ | {{ http:// | ||
+ | |||
+ | |||
+ | |||
+ | ==== تأثير التلاشى ==== | ||
+ | |||
+ | |||
+ | فى المثال سنقوم بملاشاة صورة، ستزداد شفافيتها حتى تصبح مخفية تماما | ||
+ | |||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | #include & | ||
+ | #include & | ||
+ | |||
+ | |||
+ | cairo_surface_t *image; | ||
+ | gboolean timer = TRUE; | ||
+ | |||
+ | static gboolean | ||
+ | on_expose_event(GtkWidget *widget, | ||
+ | GdkEventExpose *event, | ||
+ | gpointer data) | ||
+ | { | ||
+ | cairo_t *cr; | ||
+ | |||
+ | cr = gdk_cairo_create(widget-> | ||
+ | |||
+ | static double alpha = 1; | ||
+ | double const delta = 0.01; | ||
+ | |||
+ | cairo_set_source_surface(cr, | ||
+ | cairo_paint_with_alpha(cr, | ||
+ | |||
+ | alpha -= delta; | ||
+ | |||
+ | if (alpha <= 0) timer = FALSE; | ||
+ | |||
+ | cairo_destroy(cr); | ||
+ | |||
+ | return FALSE; | ||
+ | } | ||
+ | |||
+ | static gboolean | ||
+ | time_handler (GtkWidget *widget) | ||
+ | { | ||
+ | if (widget-> | ||
+ | |||
+ | if (!timer) return FALSE; | ||
+ | |||
+ | gtk_widget_queue_draw(widget); | ||
+ | return TRUE; | ||
+ | } | ||
+ | |||
+ | int | ||
+ | main (int argc, char *argv[]) | ||
+ | { | ||
+ | |||
+ | GtkWidget *window; | ||
+ | GtkWidget *darea; | ||
+ | |||
+ | gint width, height; | ||
+ | |||
+ | image = cairo_image_surface_create_from_png(" | ||
+ | width = cairo_image_surface_get_width(image); | ||
+ | height = cairo_image_surface_get_height(image); | ||
+ | |||
+ | gtk_init(& | ||
+ | |||
+ | window = gtk_window_new(GTK_WINDOW_TOPLEVEL); | ||
+ | |||
+ | darea = gtk_drawing_area_new(); | ||
+ | gtk_container_add(GTK_CONTAINER (window), darea); | ||
+ | |||
+ | g_signal_connect(darea, | ||
+ | G_CALLBACK(on_expose_event), | ||
+ | g_signal_connect(window, | ||
+ | G_CALLBACK(gtk_main_quit), | ||
+ | |||
+ | gtk_window_set_position(GTK_WINDOW(window), | ||
+ | gtk_window_set_default_size(GTK_WINDOW(window), | ||
+ | |||
+ | gtk_window_set_title(GTK_WINDOW(window), | ||
+ | g_timeout_add(50, | ||
+ | gtk_widget_show_all(window); | ||
+ | |||
+ | gtk_main(); | ||
+ | |||
+ | cairo_surface_destroy(image); | ||
+ | |||
+ | return 0; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | فى المثال سنقوم بملاشاة صورة، ستزداد شفافيتها حتى تصبح مخفية تماما | ||
+ | استخدمنا صورة بقايا قلعة Turna فى شرق سلوفاكيا تستطيع تحميلها <a href=" | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | image = cairo_image_surface_create_from_png(" | ||
+ | </ | ||
+ | |||
+ | |||
+ | لأسباب خاصة بالكفاءة، انشاء سطح الصورة نجعله فى الدالة main | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | </ | ||
+ | |||
+ | هنا نحدد المصدر | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | </ | ||
+ | |||
+ | تأثير التلاشى ينشئ بإستخدام الدالة **cairo_paint_with_alpha()** تلك الدالة تستخدم الشفافية كقناع | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | alpha -= delta; | ||
+ | </ | ||
+ | |||
+ | هنا قللنا قيمة الفا كل مرة يتم فيها تنفيذ **on_expose_event()** | ||
+ | |||
+ | <code cpp> | ||
+ | if (alpha <= 0) timer = FALSE; | ||
+ | </ | ||
+ | |||
+ | |||
+ | اذا كانت قيمة الفا اقل من او تساوى 0 ننهى تأثير التلاشى -بجعل قيمة المؤقت الى FALSE -لاننا لانحتاجه بعد ذلك-- | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | </ | ||
+ | |||
+ | |||
+ | ننشئ دالة مؤقت تستدعى **time_handler** كل 50 ms | ||
+ | |||
+ | We create a timer function. This function will call **time_handler** every 50 ms. | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | | ||
+ | { | ||
+ | if (widget-> | ||
+ | |||
+ | if (!timer) return FALSE; | ||
+ | |||
+ | | ||
+ | | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | الهدف الأساسى ل **time_handler** لإعادة رسم النافذة بصورة منتظمة حتى تصبح قيمته FALSE | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | if (widget-> | ||
+ | </ | ||
+ | |||
+ | قد تحتاج لماذا هذا الكود هنا؟ هنا نقوم بعمل اختبار بسيط اذا كانت قيمة timeout صغيرة جدا مثلا 5ms فيحدث عند غلق التطبيق يكون تم تدمير النافذة بالفعل ويتم تنفيذ ال timeout function. فيمنع هذا السطر معالجة النافذة فى مثل تلك الحالات. | ||
+ | |||
+ | {{ http:// | ||
+ | |||
+ | |||
+ | ==== Waiting demo ==== | ||
+ | |||
+ | |||
+ | |||
+ | فى هذا المثال سنستخدم الشفافية لإنشاء " | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | #include & | ||
+ | #include & | ||
+ | #include & | ||
+ | |||
+ | static gushort count = 0; | ||
+ | |||
+ | static gboolean | ||
+ | on_expose_event(GtkWidget *widget, | ||
+ | GdkEventExpose *event, | ||
+ | gpointer data) | ||
+ | { | ||
+ | cairo_t *cr; | ||
+ | |||
+ | cr = gdk_cairo_create(widget-> | ||
+ | |||
+ | static gdouble const trs[8][8] = { | ||
+ | { 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, } | ||
+ | }; | ||
+ | |||
+ | |||
+ | gint width, height; | ||
+ | gtk_window_get_size(GTK_WINDOW(widget), | ||
+ | |||
+ | cairo_translate(cr, | ||
+ | |||
+ | gint i = 0; | ||
+ | for (i = 0; i < 8; i++) { | ||
+ | cairo_set_line_width(cr, | ||
+ | cairo_set_line_cap(cr, | ||
+ | cairo_set_source_rgba(cr, | ||
+ | |||
+ | cairo_move_to(cr, | ||
+ | cairo_line_to(cr, | ||
+ | cairo_rotate(cr, | ||
+ | |||
+ | cairo_stroke(cr); | ||
+ | } | ||
+ | |||
+ | cairo_destroy(cr); | ||
+ | |||
+ | return FALSE; | ||
+ | } | ||
+ | |||
+ | static gboolean | ||
+ | time_handler (GtkWidget *widget) | ||
+ | { | ||
+ | count += 1; | ||
+ | gtk_widget_queue_draw(widget); | ||
+ | return TRUE; | ||
+ | } | ||
+ | |||
+ | int main(int argc, char *argv[]) | ||
+ | { | ||
+ | GtkWidget *window; | ||
+ | GtkWidget *darea; | ||
+ | |||
+ | gtk_init(& | ||
+ | |||
+ | window = gtk_window_new(GTK_WINDOW_TOPLEVEL); | ||
+ | |||
+ | g_signal_connect(G_OBJECT(window), | ||
+ | G_CALLBACK(on_expose_event), | ||
+ | g_signal_connect(G_OBJECT(window), | ||
+ | G_CALLBACK(gtk_main_quit), | ||
+ | |||
+ | gtk_window_set_position(GTK_WINDOW(window), | ||
+ | gtk_window_set_default_size(GTK_WINDOW(window), | ||
+ | |||
+ | gtk_window_set_title(GTK_WINDOW(window), | ||
+ | |||
+ | gtk_widget_set_app_paintable(window, | ||
+ | gtk_widget_show_all(window); | ||
+ | g_timeout_add(100, | ||
+ | |||
+ | gtk_main(); | ||
+ | |||
+ | return 0; | ||
+ | } | ||
+ | |||
+ | </ | ||
+ | |||
+ | |||
+ | نرسم ال 8 اسطر بقيم الفا مختلفة | ||
+ | |||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | { 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, } | ||
+ | }; | ||
+ | </ | ||
+ | |||
+ | |||
+ | هذه مصفوفة ثنائية الأبعاد مستخدمه فى هذا العرض.. هناك 8 صفوف كل منها لحالة.. كل من ال 8 اسطر يستخدمها | ||
+ | |||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | | ||
+ | </ | ||
+ | |||
+ | |||
+ | نجعل الأسطر اسمك، ليصبحو اكثر وضوحا.. نرسم | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | </ | ||
+ | |||
+ | هنا نحدد الشفافية لسطر | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | | ||
+ | | ||
+ | </ | ||
+ | |||
+ | |||
+ | هذا الكود سيرسم كل من ال 8 خطوط | ||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | </ | ||
+ | |||
+ | |||
+ | نستخدم دالة مؤقت لعمل الأنيميشن. | ||
+ | |||
+ | |||
+ | {{ http:// | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ===== التركيب ===== | ||
+ | |||
+ | فى هذه الجزئية سنقوم بتعريف عمليات التركيب. | ||
+ | |||
+ | |||
+ | **Compositing** هو دمج اكثر من عنصر مرئى من مصادر مختلفة الى صورة واحدة. يستخدمو لإيهام ان كل تلك العناصر هى جزء من نفس المشهد. | ||
+ | يستخدم التركيب بكثرة فى صناعة الأفلام لإنشاء الحشود، عوالم جديدة.. الخ | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ==== العمليات ==== | ||
+ | |||
+ | يوجد العديد من عمليات التركيب، تقدم كايرو 14 عملية تركيب مختلفة. | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | #include & | ||
+ | #include & | ||
+ | |||
+ | |||
+ | static void draw(cairo_t *cr, gint x, gint w, | ||
+ | gint h, cairo_operator_t op) | ||
+ | { | ||
+ | |||
+ | cairo_t *first_cr, *second_cr; | ||
+ | cairo_surface_t *first, *second; | ||
+ | |||
+ | first = cairo_surface_create_similar(cairo_get_target(cr), | ||
+ | CAIRO_CONTENT_COLOR_ALPHA, | ||
+ | |||
+ | second = cairo_surface_create_similar(cairo_get_target(cr), | ||
+ | CAIRO_CONTENT_COLOR_ALPHA, | ||
+ | |||
+ | first_cr = cairo_create(first); | ||
+ | cairo_set_source_rgb(first_cr, | ||
+ | cairo_rectangle(first_cr, | ||
+ | cairo_fill(first_cr); | ||
+ | |||
+ | second_cr = cairo_create(second); | ||
+ | cairo_set_source_rgb(second_cr, | ||
+ | cairo_rectangle(second_cr, | ||
+ | cairo_fill(second_cr); | ||
+ | |||
+ | cairo_set_operator(first_cr, | ||
+ | cairo_set_source_surface(first_cr, | ||
+ | cairo_paint(first_cr); | ||
+ | |||
+ | cairo_set_source_surface(cr, | ||
+ | cairo_paint(cr); | ||
+ | |||
+ | cairo_surface_destroy(first); | ||
+ | cairo_surface_destroy(second); | ||
+ | |||
+ | cairo_destroy(first_cr); | ||
+ | cairo_destroy(second_cr); | ||
+ | |||
+ | } | ||
+ | |||
+ | static gboolean | ||
+ | on_expose_event(GtkWidget *widget, | ||
+ | GdkEventExpose *event, | ||
+ | gpointer data) | ||
+ | { | ||
+ | cairo_t *cr; | ||
+ | gint w, h; | ||
+ | gint x, y; | ||
+ | |||
+ | cairo_operator_t oper[] = { | ||
+ | CAIRO_OPERATOR_DEST_OVER, | ||
+ | CAIRO_OPERATOR_DEST_IN, | ||
+ | CAIRO_OPERATOR_OUT, | ||
+ | CAIRO_OPERATOR_ADD, | ||
+ | CAIRO_OPERATOR_ATOP, | ||
+ | CAIRO_OPERATOR_DEST_ATOP, | ||
+ | }; | ||
+ | |||
+ | gtk_window_get_size(GTK_WINDOW(widget), | ||
+ | |||
+ | cr = gdk_cairo_create(widget-> | ||
+ | |||
+ | gint i; | ||
+ | for(x=20, y=20, i=0; i < 6; x+=80, i++) { | ||
+ | draw(cr, x, w, h, oper[i] ); | ||
+ | } | ||
+ | |||
+ | cairo_destroy(cr); | ||
+ | |||
+ | return FALSE; | ||
+ | } | ||
+ | |||
+ | |||
+ | int main (int argc, char *argv[]) | ||
+ | { | ||
+ | GtkWidget *window; | ||
+ | |||
+ | gtk_init(& | ||
+ | |||
+ | window = gtk_window_new(GTK_WINDOW_TOPLEVEL); | ||
+ | |||
+ | g_signal_connect(window, | ||
+ | G_CALLBACK(on_expose_event), | ||
+ | g_signal_connect(window, | ||
+ | G_CALLBACK(gtk_main_quit), | ||
+ | |||
+ | gtk_window_set_position(GTK_WINDOW(window), | ||
+ | gtk_window_set_default_size(GTK_WINDOW(window), | ||
+ | gtk_widget_set_app_paintable(window, | ||
+ | |||
+ | gtk_widget_show_all(window); | ||
+ | |||
+ | gtk_main(); | ||
+ | |||
+ | return 0; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | فى المثال نعرض 6 عمليات تركيب على مربعين. | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | first = cairo_surface_create_similar(cairo_get_target(cr), | ||
+ | | ||
+ | |||
+ | | ||
+ | | ||
+ | </ | ||
+ | |||
+ | |||
+ | ننشئ سطحين. | ||
+ | |||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | </ | ||
+ | |||
+ | |||
+ | نرسم مستطيل على السطح. | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | | ||
+ | | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | نقوم بتطبيق عملية التركيب على السطحين. | ||
+ | |||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | اخيرانقوم بالرسم على النافذة. | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | }; | ||
+ | </ | ||
+ | |||
+ | |||
+ | فى مثالنا استخدمنا هذه الستة عمليات تركيب | ||
+ | |||
+ | In our example, we use these six compositing operations. | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | {{ http:// | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ===== Clipping and masking ===== | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | فى هذه الجزئية سنتحدث عن ال clipping -القصر- وال masking -التقنيع- | ||
+ | In this part of the Cairo tutorial, we will talk about clipping and masking. | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ==== Clipping ==== | ||
+ | |||
+ | |||
+ | |||
+ | ال clipping هى عملية قصر للرسم فى منطقة محددة ويستخدم لأسباب متعلقة بالكفاءة ولإنشاء تأثيرات مثيرة. | ||
+ | |||
+ | --سنستخدم كلمة قصاصة للتعبير عن clip | ||
+ | |||
+ | === تقصيص صورة === | ||
+ | |||
+ | |||
+ | فى المثال سنوضح كيف نقوم بعمل تقصيص لصورة. | ||
+ | |||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | #include & | ||
+ | #include & | ||
+ | #include & | ||
+ | |||
+ | cairo_surface_t *image; | ||
+ | |||
+ | static gboolean | ||
+ | on_expose_event(GtkWidget *widget, | ||
+ | GdkEventExpose *event, | ||
+ | gpointer data) | ||
+ | { | ||
+ | cairo_t *cr; | ||
+ | |||
+ | static gint pos_x = 128; | ||
+ | static gint pos_y = 128; | ||
+ | gint radius = 40; | ||
+ | |||
+ | static gint delta[] = { 3, 3 }; | ||
+ | |||
+ | cr = gdk_cairo_create(widget-> | ||
+ | |||
+ | gint width, height; | ||
+ | gtk_window_get_size(GTK_WINDOW(widget), | ||
+ | |||
+ | if (pos_x < 0 + radius) { | ||
+ | delta[0] = rand() % 4 + 5; | ||
+ | } else if (pos_x > width - radius) { | ||
+ | delta[0] = -(rand() % 4 + 5); | ||
+ | } | ||
+ | |||
+ | if (pos_y < 0 + radius) { | ||
+ | delta[1] = rand() % 4 + 5; | ||
+ | } else if (pos_y > height - radius) { | ||
+ | delta[1] = -(rand() % 4 + 5); | ||
+ | } | ||
+ | |||
+ | pos_x += delta[0]; | ||
+ | pos_y += delta[1]; | ||
+ | |||
+ | cairo_set_source_surface(cr, | ||
+ | cairo_arc(cr, | ||
+ | cairo_clip(cr); | ||
+ | cairo_paint(cr); | ||
+ | |||
+ | cairo_destroy(cr); | ||
+ | |||
+ | return FALSE; | ||
+ | } | ||
+ | |||
+ | static gboolean | ||
+ | time_handler (GtkWidget *widget) | ||
+ | { | ||
+ | if (widget-> | ||
+ | gtk_widget_queue_draw(widget); | ||
+ | return TRUE; | ||
+ | } | ||
+ | |||
+ | int main(int argc, char *argv[]) | ||
+ | { | ||
+ | GtkWidget *window; | ||
+ | gint width, height; | ||
+ | |||
+ | image = cairo_image_surface_create_from_png(" | ||
+ | width = cairo_image_surface_get_width(image); | ||
+ | height = cairo_image_surface_get_height(image); | ||
+ | |||
+ | |||
+ | gtk_init(& | ||
+ | |||
+ | window = gtk_window_new(GTK_WINDOW_TOPLEVEL); | ||
+ | |||
+ | g_signal_connect(G_OBJECT(window), | ||
+ | G_CALLBACK(on_expose_event), | ||
+ | g_signal_connect(G_OBJECT(window), | ||
+ | G_CALLBACK(gtk_main_quit), | ||
+ | |||
+ | gtk_window_set_position(GTK_WINDOW(window), | ||
+ | gtk_window_set_default_size(GTK_WINDOW(window), | ||
+ | |||
+ | gtk_widget_set_app_paintable(window, | ||
+ | gtk_widget_show_all(window); | ||
+ | g_timeout_add(100, | ||
+ | |||
+ | gtk_main(); | ||
+ | |||
+ | cairo_surface_destroy(image); | ||
+ | |||
+ | return 0; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | فى المثال سنقوم بعمل قصاصة لصورة. دائرة تتحرك على الشاشة وتعرض الجزء الظاهر تحتها كأننا ننظر من ثقب. | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | if (pos_x < 0 + radius) { | ||
+ | | ||
+ | } else if (pos_x > width - radius) { | ||
+ | | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | اذا مرت الدائرة بالجانب الأيسر او الأيمن للنافذة يتم تغيير اتجاة حركة الدائرة عشوائيا ونفس الشئ للجانب الأعلى والأسفل. | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | | ||
+ | </ | ||
+ | |||
+ | |||
+ | هنا نرسم الصورة والدائرة -لاحظ اننا لانرسم على النافذة فى هذه اللحظة.. فقط فى الذاكرة. | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | </ | ||
+ | |||
+ | |||
+ | الدالة **cairo_clip** تقوم بتقصيص منطقة- منقطة القصاصة هى المسار الحالى المستخدم اللذى انشئ بواسطة الدالة **cairo_arc** | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | The **cairo_paint()** paints the current source everywhere within the current clip region. | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | {{ http:// | ||
+ | |||
+ | |||
+ | === تقصيص مستطيل === | ||
+ | |||
+ | |||
+ | المثال التالى مستوحى من مثال وجدته فى امثلة Java2D | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | #include & | ||
+ | #include & | ||
+ | #include & | ||
+ | |||
+ | |||
+ | static gboolean | ||
+ | on_expose_event(GtkWidget *widget, | ||
+ | GdkEventExpose *event, | ||
+ | gpointer data) | ||
+ | { | ||
+ | cairo_t *cr; | ||
+ | cr = gdk_cairo_create(widget-> | ||
+ | |||
+ | static gboolean xdirection = TRUE; | ||
+ | static gint counter = 0; | ||
+ | |||
+ | int width, height; | ||
+ | gtk_window_get_size(GTK_WINDOW(widget), | ||
+ | |||
+ | static gdouble rotate = 0; | ||
+ | |||
+ | static gint bigx = 20; | ||
+ | static gint bigy = 200; | ||
+ | static gint delta = 1; | ||
+ | |||
+ | counter += 1; | ||
+ | |||
+ | |||
+ | if (bigx > width) { | ||
+ | xdirection = FALSE; | ||
+ | delta = -delta; | ||
+ | bigx = width; | ||
+ | } | ||
+ | |||
+ | if (bigx < 1) { | ||
+ | bigx = 1; | ||
+ | delta = -delta; | ||
+ | } | ||
+ | |||
+ | if (bigy > height) { | ||
+ | xdirection = TRUE; | ||
+ | delta = -delta; | ||
+ | bigy = height; | ||
+ | } | ||
+ | |||
+ | if (bigy < 1) { | ||
+ | delta = -delta; | ||
+ | bigy = 1; | ||
+ | } | ||
+ | |||
+ | if (xdirection) { | ||
+ | bigx += delta; | ||
+ | } else { | ||
+ | bigy += delta; | ||
+ | } | ||
+ | |||
+ | cairo_translate(cr, | ||
+ | |||
+ | cairo_rectangle(cr, | ||
+ | cairo_set_source_rgb(cr, | ||
+ | cairo_set_line_width(cr, | ||
+ | cairo_stroke(cr); | ||
+ | |||
+ | cairo_rotate(cr, | ||
+ | rotate += 0.01; | ||
+ | |||
+ | cairo_rectangle(cr, | ||
+ | cairo_stroke(cr); | ||
+ | |||
+ | GdkRectangle bigrect; | ||
+ | GdkRectangle rect; | ||
+ | GdkRectangle intersect; | ||
+ | |||
+ | bigrect.x = -bigx/2; | ||
+ | bigrect.y = -bigy/2; | ||
+ | bigrect.width = bigx -2; | ||
+ | bigrect.height = bigy -2; | ||
+ | |||
+ | rect.x = -50; | ||
+ | rect.y = -25; | ||
+ | rect.width = 100; | ||
+ | rect.height = 50; | ||
+ | |||
+ | gdk_rectangle_intersect(& | ||
+ | cairo_rectangle(cr, | ||
+ | cairo_fill(cr); | ||
+ | |||
+ | cairo_destroy(cr); | ||
+ | |||
+ | return FALSE; | ||
+ | } | ||
+ | |||
+ | static gboolean | ||
+ | time_handler (GtkWidget *widget) | ||
+ | { | ||
+ | if (widget-> | ||
+ | gtk_widget_queue_draw(widget); | ||
+ | return TRUE; | ||
+ | } | ||
+ | |||
+ | int | ||
+ | main (int argc, char *argv[]) | ||
+ | { | ||
+ | |||
+ | GtkWidget *window; | ||
+ | |||
+ | gtk_init(& | ||
+ | |||
+ | window = gtk_window_new(GTK_WINDOW_TOPLEVEL); | ||
+ | |||
+ | g_signal_connect(G_OBJECT(window), | ||
+ | G_CALLBACK(on_expose_event), | ||
+ | g_signal_connect(G_OBJECT(window), | ||
+ | G_CALLBACK(gtk_main_quit), | ||
+ | |||
+ | gtk_window_set_position(GTK_WINDOW(window), | ||
+ | gtk_window_set_default_size(GTK_WINDOW(window), | ||
+ | |||
+ | gtk_widget_set_app_paintable(window, | ||
+ | gtk_widget_show_all(window); | ||
+ | g_timeout_add(5, | ||
+ | |||
+ | gtk_main(); | ||
+ | |||
+ | return 0; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | فى المثال لدينا مستطيلين (واحد كبير واخر يدور- الكبير يتقلص وينمو بصورة مستمرة. والصغير بدور. هنا نقوم بتطبيق عملية التقاطع على الإثنين. فيتم تلوين منقطة التقاطع بينهم باللون الأسود. | ||
+ | لاحظ ان التقاطع ليس مستطيل تام ولكن للتسهيل سنقوم بتقريب المساحة لمستطيل | ||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | </ | ||
+ | |||
+ | |||
+ | هذا المتغير يحدد اتجاه حركة المستطيل الكبير. | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | if (bigx > width) { | ||
+ | | ||
+ | delta = -delta; | ||
+ | bigx = width; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | المستطيل الكبير بنفس عرض النافذة ونقوم بتغير الإتجاه، فيبدأ تقلص المستطيل فى اتجاه ص | ||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | </ | ||
+ | |||
+ | |||
+ | الدالة **cairo_rotate** تدير المستطيل الأصغر. | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | | ||
+ | | ||
+ | </ | ||
+ | |||
+ | |||
+ | هنا نقوم بتعريف 3 مستطيلات. مستطيل **التقاطع** هو ناتج تقاطع المستطيلين. | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | </ | ||
+ | |||
+ | هنا نقوم بتطبيق عملية التقاطع. | ||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | | ||
+ | </ | ||
+ | نرسم مساحة التقاطع. | ||
+ | |||
+ | |||
+ | |||
+ | {{ http:// | ||
+ | |||
+ | |||
+ | ==== قناع ==== | ||
+ | |||
+ | قبل ان يتم تطبيق المصدر على السطح يتم ترشيحه اولا، يتم استخدام القناع كمرشح. ويقوم القناع بتحديد اى الأماكن اللتى سيتم تطبيق المصدر عليها. | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | #include & | ||
+ | #include & | ||
+ | |||
+ | |||
+ | static gboolean | ||
+ | on_expose_event(GtkWidget *widget, | ||
+ | GdkEventExpose *event, | ||
+ | gpointer data) | ||
+ | { | ||
+ | cairo_t *cr; | ||
+ | cairo_surface_t *surface; | ||
+ | cairo_set_source_rgb(cr, | ||
+ | |||
+ | cr = gdk_cairo_create(widget-> | ||
+ | surface = cairo_image_surface_create_from_png(" | ||
+ | cairo_mask_surface(cr, | ||
+ | cairo_fill(cr); | ||
+ | |||
+ | cairo_surface_destroy(surface); | ||
+ | cairo_destroy(cr); | ||
+ | |||
+ | return FALSE; | ||
+ | } | ||
+ | |||
+ | |||
+ | int main(int argc, char *argv[]) | ||
+ | { | ||
+ | GtkWidget *window; | ||
+ | |||
+ | gtk_init(& | ||
+ | |||
+ | window = gtk_window_new(GTK_WINDOW_TOPLEVEL); | ||
+ | |||
+ | g_signal_connect(G_OBJECT(window), | ||
+ | G_CALLBACK(on_expose_event), | ||
+ | g_signal_connect(G_OBJECT(window), | ||
+ | G_CALLBACK(gtk_main_quit), | ||
+ | |||
+ | gtk_window_set_position(GTK_WINDOW(window), | ||
+ | gtk_window_set_default_size(GTK_WINDOW(window), | ||
+ | |||
+ | gtk_window_set_title(GTK_WINDOW(window), | ||
+ | gtk_widget_set_app_paintable(window, | ||
+ | gtk_widget_show_all(window); | ||
+ | |||
+ | gtk_main(); | ||
+ | |||
+ | return 0; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | فى هذا المثال السيط نوضح الفكرة الأساسية وراء القناع. يحدد القناع اي الأماكن يتم فيها الرسم | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | | ||
+ | | ||
+ | </ | ||
+ | نستخدم الصورة كقناع ومن ثم عرضها على النافذة. | ||
+ | |||
+ | |||
+ | |||
+ | {{ http:// | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ===== التحويلات ===== | ||
+ | |||
+ | فى هذه الجزئية سنتخدث عن التحويلات | ||
+ | |||
+ | **affine transform** " | ||
+ | |||
+ | عدة تحويلات خطية يمكن ان دمج سويا لمصفوفة واحدة. | ||
+ | **rotation** او الدوران يقوم بتدوير الجسم حول نقطة محددة. | ||
+ | **scaling** او التوسع يقوم بتكيير ابعاد الكائنات. ويكون معامل التوسيع واحد فى جميع الإتجاهات | ||
+ | **translation** او الترجمة هى تحويل يقوم بإزاحة كل النقاط الى مسافة ثابتة فى اتجاة ثابت | ||
+ | **shear** او القص هو تحويل يقوم بإزاحة الكائن بصورة عمودية على محور معين مع قيمة اعلى اعلى فى محور عن الآخر | ||
+ | #FIXME: توضيح افضل للقص | ||
+ | |||
+ | **An affine transform** is composed of zero or more linear transformations (rotation, scaling or shear) and translation (shift). Several linear transformations can be combined into a single matrix. | ||
+ | A **rotation** is a transformation that moves a rigid body around a fixed point. | ||
+ | A **scaling** is a transformation that enlarges or diminishes objects. The scale factor is the same in all directions. | ||
+ | A **translation** is a transformation that moves every point a constant distance in a specified direction. | ||
+ | A **shear** is a transformation that moves an object perpendicular to a given axis, with greater value on one side of the axis than the other. | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | sources: (wikipedia.org, | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ==== الترجمة ==== | ||
+ | |||
+ | المثال التالى يوصف ترجمة بسيطة. | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | #include & | ||
+ | #include & | ||
+ | |||
+ | |||
+ | static gboolean | ||
+ | on_expose_event(GtkWidget *widget, | ||
+ | GdkEventExpose *event, | ||
+ | gpointer data) | ||
+ | { | ||
+ | cairo_t *cr; | ||
+ | |||
+ | cr = gdk_cairo_create (widget-> | ||
+ | |||
+ | cairo_set_source_rgb(cr, | ||
+ | cairo_rectangle(cr, | ||
+ | cairo_stroke_preserve(cr); | ||
+ | cairo_set_source_rgb(cr, | ||
+ | cairo_fill(cr); | ||
+ | |||
+ | cairo_translate(cr, | ||
+ | |||
+ | cairo_set_source_rgb(cr, | ||
+ | cairo_rectangle(cr, | ||
+ | cairo_stroke_preserve(cr); | ||
+ | cairo_set_source_rgb(cr, | ||
+ | cairo_fill(cr); | ||
+ | |||
+ | cairo_destroy(cr); | ||
+ | |||
+ | return FALSE; | ||
+ | } | ||
+ | |||
+ | |||
+ | int main(int argc, char *argv[]) | ||
+ | { | ||
+ | GtkWidget *window; | ||
+ | |||
+ | gtk_init(& | ||
+ | |||
+ | window = gtk_window_new(GTK_WINDOW_TOPLEVEL); | ||
+ | |||
+ | g_signal_connect(window, | ||
+ | G_CALLBACK (on_expose_event), | ||
+ | g_signal_connect(window, | ||
+ | G_CALLBACK (gtk_main_quit), | ||
+ | |||
+ | gtk_window_set_position(GTK_WINDOW(window), | ||
+ | gtk_window_set_default_size(GTK_WINDOW(window), | ||
+ | gtk_widget_set_app_paintable(window, | ||
+ | |||
+ | gtk_widget_show_all(window); | ||
+ | |||
+ | gtk_main(); | ||
+ | |||
+ | return 0; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | المثال يرسم مستطيل، ثم نقوم بعمل ترجمة ونرسم نفس المستطيل مرة اخرى. | ||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | </ | ||
+ | |||
+ | **cairo_translate()** تعدل مصفوفة التحويل عن طريق ترجمة نقطة اصل مساحة المستخدم.. فى حالتنا هذه قمنا بتحويل نقطة الأصل 100 وحدة فى الإتجاهين. | ||
+ | |||
+ | |||
+ | |||
+ | {{ http:// | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ==== الدواران ==== | ||
+ | |||
+ | المثال التالى يوضح لنا مفهوم الدوران | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | #include & | ||
+ | #include & | ||
+ | #include & | ||
+ | |||
+ | |||
+ | static gboolean | ||
+ | on_expose_event(GtkWidget *widget, | ||
+ | GdkEventExpose *event, | ||
+ | gpointer data) | ||
+ | { | ||
+ | cairo_t *cr; | ||
+ | |||
+ | cr = gdk_cairo_create (widget-> | ||
+ | |||
+ | cairo_set_source_rgb(cr, | ||
+ | cairo_rectangle(cr, | ||
+ | cairo_stroke_preserve(cr); | ||
+ | cairo_set_source_rgb(cr, | ||
+ | cairo_fill(cr); | ||
+ | |||
+ | cairo_translate(cr, | ||
+ | cairo_rotate(cr, | ||
+ | |||
+ | cairo_set_source_rgb(cr, | ||
+ | cairo_rectangle(cr, | ||
+ | cairo_stroke_preserve(cr); | ||
+ | cairo_set_source_rgb(cr, | ||
+ | cairo_fill(cr); | ||
+ | |||
+ | cairo_destroy(cr); | ||
+ | |||
+ | return FALSE; | ||
+ | } | ||
+ | |||
+ | |||
+ | int main(int argc, char *argv[]) | ||
+ | { | ||
+ | GtkWidget *window; | ||
+ | |||
+ | gtk_init(& | ||
+ | |||
+ | window = gtk_window_new(GTK_WINDOW_TOPLEVEL); | ||
+ | |||
+ | g_signal_connect(window, | ||
+ | G_CALLBACK (on_expose_event), | ||
+ | g_signal_connect(window, | ||
+ | G_CALLBACK (gtk_main_quit), | ||
+ | |||
+ | gtk_window_set_position(GTK_WINDOW(window), | ||
+ | gtk_window_set_default_size(GTK_WINDOW(window), | ||
+ | gtk_widget_set_app_paintable(window, | ||
+ | |||
+ | gtk_widget_show_all(window); | ||
+ | |||
+ | gtk_main(); | ||
+ | |||
+ | return 0; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | المثال نرسم فيه مستطيل، ونقوم بعمل ترجمة ودوران ثم نرسم نفس المستطيل مرة اخرى | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | | ||
+ | </ | ||
+ | |||
+ | |||
+ | اولا نقوم بإزاحة نقطة الأصل للمستخدم ونقوم بتدويرها بمقدار 180درجة -لاحظ ان الزاوية بالتقدير الدائرى- | ||
+ | |||
+ | 2 ط = 360 | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | {{ http:// | ||
+ | |||
+ | |||
+ | ==== Scale ==== | ||
+ | |||
+ | |||
+ | |||
+ | المثال التالى يتعرض لعملية ال scaling -التوسيع- | ||
+ | |||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | #include & | ||
+ | #include & | ||
+ | |||
+ | |||
+ | static gboolean | ||
+ | on_expose_event(GtkWidget *widget, | ||
+ | GdkEventExpose *event, | ||
+ | gpointer data) | ||
+ | { | ||
+ | cairo_t *cr; | ||
+ | |||
+ | cr = gdk_cairo_create (widget-> | ||
+ | |||
+ | cairo_save(cr); | ||
+ | cairo_set_source_rgb(cr, | ||
+ | cairo_rectangle(cr, | ||
+ | cairo_stroke_preserve(cr); | ||
+ | cairo_set_source_rgb(cr, | ||
+ | cairo_fill(cr); | ||
+ | cairo_restore(cr); | ||
+ | |||
+ | cairo_save(cr); | ||
+ | cairo_translate(cr, | ||
+ | cairo_scale(cr, | ||
+ | |||
+ | cairo_set_source_rgb(cr, | ||
+ | cairo_rectangle(cr, | ||
+ | cairo_stroke_preserve(cr); | ||
+ | cairo_set_source_rgb(cr, | ||
+ | cairo_fill(cr); | ||
+ | cairo_restore(cr); | ||
+ | |||
+ | cairo_save(cr); | ||
+ | cairo_translate(cr, | ||
+ | cairo_scale(cr, | ||
+ | |||
+ | cairo_set_source_rgb(cr, | ||
+ | cairo_rectangle(cr, | ||
+ | cairo_stroke_preserve(cr); | ||
+ | cairo_set_source_rgb(cr, | ||
+ | cairo_fill(cr); | ||
+ | cairo_restore(cr); | ||
+ | |||
+ | cairo_destroy(cr); | ||
+ | |||
+ | return FALSE; | ||
+ | } | ||
+ | |||
+ | |||
+ | int main(int argc, char *argv[]) | ||
+ | { | ||
+ | GtkWidget *window; | ||
+ | |||
+ | gtk_init(& | ||
+ | |||
+ | window = gtk_window_new(GTK_WINDOW_TOPLEVEL); | ||
+ | |||
+ | g_signal_connect(window, | ||
+ | G_CALLBACK (on_expose_event), | ||
+ | g_signal_connect(window, | ||
+ | G_CALLBACK (gtk_main_quit), | ||
+ | |||
+ | gtk_window_set_position(GTK_WINDOW(window), | ||
+ | gtk_window_set_default_size(GTK_WINDOW(window), | ||
+ | gtk_widget_set_app_paintable(window, | ||
+ | |||
+ | gtk_widget_show_all(window); | ||
+ | |||
+ | gtk_main(); | ||
+ | |||
+ | return 0; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | هذه المرة نجعل المستطيل الأصلى اصغر ثم اكبر بإستخدام معامل توسيع محدد | ||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | ... | ||
+ | | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | We want to perform two scaling operations on the initial rectangle. Therefore, we need to save the initial transformation matrix. This is done by a pair of **cairo_save()** and **cairo_restore()** functions. | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | | ||
+ | </ | ||
+ | |||
+ | |||
+ | ننقل نقطة الأصل ونقوم بالتوسيع بنسبة 0.7 | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | {{ http:// | ||
+ | |||
+ | |||
+ | |||
+ | ==== القص ==== | ||
+ | |||
+ | |||
+ | فى المثال التالى سنقوم بعمل قص shearing | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | #include & | ||
+ | #include & | ||
+ | |||
+ | |||
+ | static gboolean | ||
+ | on_expose_event(GtkWidget *widget, | ||
+ | GdkEventExpose *event, | ||
+ | gpointer data) | ||
+ | { | ||
+ | cairo_t *cr; | ||
+ | cairo_matrix_t matrix; | ||
+ | |||
+ | cr = gdk_cairo_create (widget-> | ||
+ | |||
+ | cairo_save(cr); | ||
+ | cairo_set_source_rgb(cr, | ||
+ | cairo_rectangle(cr, | ||
+ | cairo_stroke_preserve(cr); | ||
+ | cairo_set_source_rgb(cr, | ||
+ | cairo_fill(cr); | ||
+ | cairo_restore(cr); | ||
+ | |||
+ | cairo_save(cr); | ||
+ | cairo_translate(cr, | ||
+ | cairo_matrix_init(& | ||
+ | 1.0, 0.5, | ||
+ | 0.0, 1.0, | ||
+ | 0.0, 0.0); | ||
+ | |||
+ | cairo_transform (cr, & | ||
+ | |||
+ | cairo_set_source_rgb(cr, | ||
+ | cairo_rectangle(cr, | ||
+ | cairo_stroke_preserve(cr); | ||
+ | cairo_set_source_rgb(cr, | ||
+ | cairo_fill(cr); | ||
+ | cairo_restore(cr); | ||
+ | |||
+ | cairo_save(cr); | ||
+ | cairo_translate(cr, | ||
+ | cairo_matrix_init(& | ||
+ | 1.0, 0.0, | ||
+ | 0.7, 1.0, | ||
+ | 0.0, 0.0); | ||
+ | |||
+ | cairo_transform(cr, | ||
+ | |||
+ | cairo_set_source_rgb(cr, | ||
+ | cairo_rectangle(cr, | ||
+ | cairo_stroke_preserve(cr); | ||
+ | cairo_set_source_rgb(cr, | ||
+ | cairo_fill(cr); | ||
+ | cairo_restore(cr); | ||
+ | |||
+ | cairo_destroy(cr); | ||
+ | |||
+ | return FALSE; | ||
+ | } | ||
+ | |||
+ | |||
+ | int main(int argc, char *argv[]) | ||
+ | { | ||
+ | GtkWidget *window; | ||
+ | |||
+ | gtk_init(& | ||
+ | |||
+ | window = gtk_window_new(GTK_WINDOW_TOPLEVEL); | ||
+ | |||
+ | g_signal_connect(window, | ||
+ | G_CALLBACK(on_expose_event), | ||
+ | g_signal_connect(window, | ||
+ | G_CALLBACK(gtk_main_quit), | ||
+ | |||
+ | gtk_window_set_position(GTK_WINDOW(window), | ||
+ | gtk_window_set_default_size(GTK_WINDOW(window), | ||
+ | gtk_widget_set_app_paintable(window, | ||
+ | |||
+ | gtk_widget_show_all(window); | ||
+ | |||
+ | gtk_main(); | ||
+ | |||
+ | return 0; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | In this code example, we perform two shear transformations. For a shear transformation, | ||
+ | function. We must use matrices. | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | </ | ||
+ | |||
+ | **cairo_matrix_t** هى هيكل يحمل تحول قريب | ||
+ | #FIXME: اعادة صياغة | ||
+ | |||
+ | |||
+ | The **cairo_matrix_t** is a structure that holds an affine transformation. | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | 1.0, 0.5, | ||
+ | 0.0, 1.0, | ||
+ | 0.0, 0.0); | ||
+ | |||
+ | | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | هذا التحول يقص قيم ص بمقدار 0.5 من قيم س | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | 1.0, 0.0, | ||
+ | 0.7, 1.0, | ||
+ | 0.0, 0.0); | ||
+ | |||
+ | | ||
+ | </ | ||
+ | |||
+ | |||
+ | وهذا التحول يضاعف قيم س على الإحداثيات بمقدار 0.7 من ص | ||
+ | |||
+ | And this transformation multiplies the x value of each coordinate by 0.7 of the y. | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | {{ http:// | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ==== Ellipses ==== | ||
+ | |||
+ | فى المثال التالى سننشئ شكل معقد عبر الدوران ومجموعة قطاعات. | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | #include & | ||
+ | #include & | ||
+ | |||
+ | static gboolean | ||
+ | on_expose_event(GtkWidget *widget, | ||
+ | GdkEventExpose *event, | ||
+ | gpointer data) | ||
+ | { | ||
+ | cairo_t *cr; | ||
+ | |||
+ | cr = gdk_cairo_create(widget-> | ||
+ | |||
+ | gint width, height; | ||
+ | gtk_window_get_size(GTK_WINDOW(widget), | ||
+ | |||
+ | cairo_set_line_width(cr, | ||
+ | cairo_translate(cr, | ||
+ | cairo_arc(cr, | ||
+ | cairo_stroke(cr); | ||
+ | |||
+ | gint i; | ||
+ | |||
+ | cairo_save(cr); | ||
+ | for ( i = 0; i < 36; i++) { | ||
+ | cairo_rotate(cr, | ||
+ | cairo_scale(cr, | ||
+ | cairo_arc(cr, | ||
+ | cairo_restore(cr); | ||
+ | cairo_stroke(cr); | ||
+ | cairo_save(cr); | ||
+ | } | ||
+ | |||
+ | cairo_destroy(cr); | ||
+ | |||
+ | return FALSE; | ||
+ | } | ||
+ | |||
+ | |||
+ | int main(int argc, char *argv[]) | ||
+ | { | ||
+ | |||
+ | GtkWidget *window; | ||
+ | |||
+ | gtk_init(& | ||
+ | |||
+ | window = gtk_window_new(GTK_WINDOW_TOPLEVEL); | ||
+ | |||
+ | g_signal_connect(G_OBJECT(window), | ||
+ | G_CALLBACK(on_expose_event), | ||
+ | g_signal_connect(G_OBJECT(window), | ||
+ | G_CALLBACK(gtk_main_quit), | ||
+ | |||
+ | gtk_window_set_position(GTK_WINDOW(window), | ||
+ | gtk_window_set_default_size(GTK_WINDOW(window), | ||
+ | |||
+ | gtk_widget_set_app_paintable(window, | ||
+ | gtk_widget_show_all(window); | ||
+ | |||
+ | gtk_main(); | ||
+ | |||
+ | return 0; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | | ||
+ | | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | فى منتصف النافذة ننشئ دائرة | ||
+ | In the middle of the GTK+ window, we create a circle. This will be a bounding circle for our ellipses. | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | for ( i = 0; i < 36; i++) { | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | ننشئ 36 قطع ناقص على طول الدائرة ونقوم بتدويرهم لننشئ شكل مثير جدا :) | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | {{ http:// | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ==== نجمة ==== | ||
+ | |||
+ | المثال التالى يعرض تدوير وتوسيع نجمة. | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | #include & | ||
+ | #include & | ||
+ | #include & | ||
+ | |||
+ | int points[11][2] = { | ||
+ | { 0, 85 }, | ||
+ | { 75, 75 }, | ||
+ | { 100, 10 }, | ||
+ | { 125, 75 }, | ||
+ | { 200, 85 }, | ||
+ | { 150, 125 }, | ||
+ | { 160, 190 }, | ||
+ | { 100, 150 }, | ||
+ | { 40, 190 }, | ||
+ | { 50, 125 }, | ||
+ | { 0, 85 } | ||
+ | }; | ||
+ | |||
+ | |||
+ | static gboolean | ||
+ | on_expose_event(GtkWidget *widget, | ||
+ | GdkEventExpose *event, | ||
+ | gpointer data) | ||
+ | { | ||
+ | cairo_t *cr; | ||
+ | |||
+ | static gdouble angle = 0; | ||
+ | static gdouble scale = 1; | ||
+ | static gdouble delta = 0.01; | ||
+ | |||
+ | gint width, height; | ||
+ | gtk_window_get_size(GTK_WINDOW(widget), | ||
+ | |||
+ | cr = gdk_cairo_create(widget-> | ||
+ | |||
+ | cairo_set_source_rgb(cr, | ||
+ | cairo_set_line_width(cr, | ||
+ | |||
+ | cairo_translate(cr, | ||
+ | cairo_rotate(cr, | ||
+ | cairo_scale(cr, | ||
+ | |||
+ | gint i; | ||
+ | |||
+ | for ( i = 0; i < 10; i++ ) { | ||
+ | cairo_line_to(cr, | ||
+ | } | ||
+ | |||
+ | cairo_close_path(cr); | ||
+ | cairo_fill(cr); | ||
+ | cairo_stroke(cr); | ||
+ | |||
+ | if ( scale < 0.01 ) { | ||
+ | delta = -delta; | ||
+ | } else if (scale > 0.99) { | ||
+ | delta = -delta; | ||
+ | } | ||
+ | |||
+ | scale += delta; | ||
+ | angle += 0.01; | ||
+ | |||
+ | cairo_destroy(cr); | ||
+ | |||
+ | return FALSE; | ||
+ | } | ||
+ | |||
+ | static gboolean | ||
+ | time_handler (GtkWidget *widget) | ||
+ | { | ||
+ | if (widget-> | ||
+ | gtk_widget_queue_draw(widget); | ||
+ | return TRUE; | ||
+ | } | ||
+ | |||
+ | |||
+ | int main(int argc, char *argv[]) | ||
+ | { | ||
+ | |||
+ | GtkWidget *window; | ||
+ | |||
+ | gtk_init(& | ||
+ | |||
+ | window = gtk_window_new(GTK_WINDOW_TOPLEVEL); | ||
+ | |||
+ | gtk_widget_add_events (window, GDK_BUTTON_PRESS_MASK); | ||
+ | |||
+ | g_signal_connect(window, | ||
+ | G_CALLBACK(on_expose_event), | ||
+ | g_signal_connect(window, | ||
+ | G_CALLBACK(gtk_main_quit), | ||
+ | |||
+ | |||
+ | gtk_window_set_position(GTK_WINDOW(window), | ||
+ | gtk_window_set_title(GTK_WINDOW(window), | ||
+ | gtk_window_set_default_size(GTK_WINDOW(window), | ||
+ | gtk_widget_set_app_paintable(window, | ||
+ | |||
+ | g_timeout_add(10, | ||
+ | |||
+ | gtk_widget_show_all(window); | ||
+ | |||
+ | gtk_main(); | ||
+ | |||
+ | return 0; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | فى المثال ننشئ كائن نجمة، ونقوم بترجمته وتدويره ثم توسيعه. | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | | ||
+ | | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | نقوم بإزاحة النجمة الى منتصف النافذة وتدويرها وتوسيعها. | ||
+ | |||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | for ( i = 0; i < 10; i++ ) { | ||
+ | cairo_line_to(cr, | ||
+ | } | ||
+ | |||
+ | cairo_close_path(cr); | ||
+ | cairo_fill(cr); | ||
+ | cairo_stroke(cr); | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | هنا نرسم كائن النجمة. | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | if ( scale < 0.01 ) { | ||
+ | delta = -delta; | ||
+ | } else if (scale > 0.99) { | ||
+ | delta = -delta; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | هذه الأسطر تتحكم فى نمو او تقلص النجمة. | ||
+ | |||
+ | |||
+ | {{ http:// | ||
+ | |||
+ | |||
+ | ===== النص فى كايرو ===== | ||
+ | |||
+ | |||
+ | فى هذه الجزئية سنتعامل مع النصوص. | ||
+ | |||
+ | ==== Soulmate ==== | ||
+ | |||
+ | |||
+ | |||
+ | فى التالى سنرسم بعض النص على النافذة. | ||
+ | |||
+ | <code cpp> | ||
+ | #include & | ||
+ | #include & | ||
+ | |||
+ | |||
+ | static gboolean | ||
+ | on_expose_event(GtkWidget *widget, | ||
+ | GdkEventExpose *event, | ||
+ | gpointer data) | ||
+ | { | ||
+ | cairo_t *cr; | ||
+ | |||
+ | cr = gdk_cairo_create(widget-> | ||
+ | |||
+ | cairo_set_source_rgb(cr, | ||
+ | |||
+ | cairo_select_font_face(cr, | ||
+ | CAIRO_FONT_SLANT_NORMAL, | ||
+ | CAIRO_FONT_WEIGHT_BOLD); | ||
+ | |||
+ | cairo_set_font_size(cr, | ||
+ | |||
+ | cairo_move_to(cr, | ||
+ | cairo_show_text(cr, | ||
+ | cairo_move_to(cr, | ||
+ | cairo_show_text(cr, | ||
+ | |||
+ | cairo_move_to(cr, | ||
+ | cairo_show_text(cr, | ||
+ | |||
+ | cairo_move_to(cr, | ||
+ | cairo_show_text(cr, | ||
+ | cairo_move_to(cr, | ||
+ | cairo_show_text(cr, | ||
+ | cairo_move_to(cr, | ||
+ | cairo_show_text(cr, | ||
+ | |||
+ | cairo_destroy(cr); | ||
+ | |||
+ | return FALSE; | ||
+ | } | ||
+ | |||
+ | |||
+ | |||
+ | int main (int argc, char *argv[]) | ||
+ | { | ||
+ | GtkWidget *window; | ||
+ | |||
+ | gtk_init(& | ||
+ | |||
+ | window = gtk_window_new(GTK_WINDOW_TOPLEVEL); | ||
+ | |||
+ | g_signal_connect(window, | ||
+ | G_CALLBACK(on_expose_event), | ||
+ | g_signal_connect(window, | ||
+ | G_CALLBACK(gtk_main_quit), | ||
+ | |||
+ | gtk_window_set_position(GTK_WINDOW(window), | ||
+ | gtk_window_set_default_size(GTK_WINDOW(window), | ||
+ | gtk_window_set_title(GTK_WINDOW(window), | ||
+ | gtk_widget_set_app_paintable(window, | ||
+ | |||
+ | gtk_widget_show_all(window); | ||
+ | |||
+ | gtk_main(); | ||
+ | |||
+ | return 0; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | هنا عرضنا جزء كلمات اغنية soulmate ل Natasha Bedingfields | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | CAIRO_FONT_SLANT_NORMAL, | ||
+ | CAIRO_FONT_WEIGHT_BOLD); | ||
+ | </ | ||
+ | |||
+ | هنا حددنا الخط واستخدمنا Pursia bold | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | </ | ||
+ | |||
+ | نحدد حجم الخط | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | ننتقل الى النقطة حيث نرسم النص بإستخدام **cairo_show_text()** | ||
+ | |||
+ | |||
+ | |||
+ | {{ http:// | ||
+ | |||
+ | |||
+ | ==== حرف حرف ==== | ||
+ | |||
+ | |||
+ | فى هذا التأثير، سنعرض النص حرف حرف مع بعض التأخير. | ||
+ | |||
+ | <code cpp> | ||
+ | #include & | ||
+ | #include & | ||
+ | |||
+ | gpointer text[7] = { " | ||
+ | gboolean timer = TRUE; | ||
+ | |||
+ | |||
+ | static gboolean | ||
+ | on_expose_event(GtkWidget *widget, | ||
+ | GdkEventExpose *event, | ||
+ | gpointer data) | ||
+ | { | ||
+ | cairo_t *cr; | ||
+ | cairo_text_extents_t extents; | ||
+ | static gint count = 0; | ||
+ | |||
+ | cr = gdk_cairo_create(widget-> | ||
+ | |||
+ | cairo_select_font_face(cr, | ||
+ | CAIRO_FONT_SLANT_NORMAL, | ||
+ | CAIRO_FONT_WEIGHT_BOLD); | ||
+ | |||
+ | cairo_set_font_size(cr, | ||
+ | cairo_set_source_rgb(cr, | ||
+ | |||
+ | gint i; | ||
+ | gint x = 0; | ||
+ | |||
+ | for (i = 0; i < count; i++) { | ||
+ | cairo_text_extents(cr, | ||
+ | x += extents.width + 2; | ||
+ | cairo_move_to(cr, | ||
+ | cairo_show_text(cr, | ||
+ | } | ||
+ | |||
+ | count++; | ||
+ | |||
+ | if (count == 8) { | ||
+ | timer = FALSE; | ||
+ | count = 0; | ||
+ | } | ||
+ | |||
+ | cairo_destroy(cr); | ||
+ | |||
+ | return FALSE; | ||
+ | } | ||
+ | |||
+ | static gboolean | ||
+ | time_handler (GtkWidget *widget) | ||
+ | { | ||
+ | if (widget-> | ||
+ | |||
+ | if (!timer) return FALSE; | ||
+ | |||
+ | gtk_widget_queue_draw(widget); | ||
+ | return TRUE; | ||
+ | } | ||
+ | |||
+ | |||
+ | int main (int argc, char *argv[]) | ||
+ | { | ||
+ | GtkWidget *window; | ||
+ | |||
+ | gtk_init(& | ||
+ | |||
+ | window = gtk_window_new(GTK_WINDOW_TOPLEVEL); | ||
+ | |||
+ | g_signal_connect(window, | ||
+ | G_CALLBACK(on_expose_event), | ||
+ | g_signal_connect(window, | ||
+ | G_CALLBACK(gtk_main_quit), | ||
+ | |||
+ | gtk_window_set_position(GTK_WINDOW(window), | ||
+ | gtk_window_set_default_size(GTK_WINDOW(window), | ||
+ | gtk_window_set_title(GTK_WINDOW(window), | ||
+ | gtk_widget_set_app_paintable(window, | ||
+ | |||
+ | g_timeout_add(1000, | ||
+ | |||
+ | gtk_widget_show_all(window); | ||
+ | |||
+ | |||
+ | gtk_main(); | ||
+ | |||
+ | return 0; | ||
+ | } | ||
+ | |||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | فى هذا المثال، سنقوم برسم النص " | ||
+ | |||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | </ | ||
+ | |||
+ | ننشئ مصفوفة من السلاسل الحرفية | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | CAIRO_FONT_SLANT_NORMAL, | ||
+ | CAIRO_FONT_WEIGHT_BOLD); | ||
+ | </ | ||
+ | نختار الخط Courier | ||
+ | |||
+ | <code cpp> | ||
+ | for (i = 0; i < count; i++) { | ||
+ | cairo_text_extents(cr, | ||
+ | x += extents.width + 2; | ||
+ | cairo_move_to(cr, | ||
+ | cairo_show_text(cr, | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | نرسم النص حرف حرف. | ||
+ | **extents.width** | ||
+ | |||
+ | |||
+ | {{ http:// | ||
+ | |||
+ | |||
+ | |||
+ | ==== Puff ==== | ||
+ | |||
+ | |||
+ | |||
+ | فى المثال التالى سننشئ تأثير puff.. فى المثال نعرض نص فى المنتصف يكبر حتى حد معين ثم يتلاشى | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | #include & | ||
+ | #include & | ||
+ | |||
+ | |||
+ | gpointer text[7] = { " | ||
+ | gboolean timer = TRUE; | ||
+ | |||
+ | |||
+ | static gboolean | ||
+ | on_expose_event(GtkWidget *widget, | ||
+ | GdkEventExpose *event, | ||
+ | gpointer data) | ||
+ | { | ||
+ | cairo_t *cr; | ||
+ | cairo_text_extents_t extents; | ||
+ | |||
+ | static gdouble alpha = 1.0; | ||
+ | static gdouble size = 1; | ||
+ | |||
+ | |||
+ | gint x = widget-> | ||
+ | gint y = widget-> | ||
+ | |||
+ | cr = gdk_cairo_create(widget-> | ||
+ | |||
+ | cairo_set_source_rgb(cr, | ||
+ | cairo_paint(cr); | ||
+ | |||
+ | cairo_select_font_face(cr, | ||
+ | CAIRO_FONT_SLANT_NORMAL, | ||
+ | CAIRO_FONT_WEIGHT_BOLD); | ||
+ | |||
+ | size += 0.8; | ||
+ | |||
+ | if (size > 20) { | ||
+ | alpha -= 0.01; | ||
+ | } | ||
+ | |||
+ | cairo_set_font_size(cr, | ||
+ | |||
+ | cairo_set_source_rgb(cr, | ||
+ | |||
+ | cairo_text_extents(cr, | ||
+ | cairo_move_to(cr, | ||
+ | cairo_text_path(cr, | ||
+ | cairo_clip(cr); | ||
+ | cairo_stroke(cr); | ||
+ | cairo_paint_with_alpha(cr, | ||
+ | |||
+ | if (alpha <= 0) { | ||
+ | timer = FALSE; | ||
+ | } | ||
+ | |||
+ | cairo_destroy(cr); | ||
+ | |||
+ | return FALSE; | ||
+ | } | ||
+ | |||
+ | static gboolean | ||
+ | time_handler (GtkWidget *widget) | ||
+ | { | ||
+ | if (widget-> | ||
+ | |||
+ | if (!timer) return FALSE; | ||
+ | |||
+ | gtk_widget_queue_draw(widget); | ||
+ | |||
+ | return TRUE; | ||
+ | } | ||
+ | |||
+ | |||
+ | int main (int argc, char *argv[]) | ||
+ | { | ||
+ | GtkWidget *window; | ||
+ | |||
+ | gtk_init(& | ||
+ | |||
+ | window = gtk_window_new(GTK_WINDOW_TOPLEVEL); | ||
+ | |||
+ | g_signal_connect(window, | ||
+ | G_CALLBACK(on_expose_event), | ||
+ | g_signal_connect(window, | ||
+ | G_CALLBACK(gtk_main_quit), | ||
+ | |||
+ | gtk_window_set_position(GTK_WINDOW(window), | ||
+ | gtk_window_set_default_size(GTK_WINDOW(window), | ||
+ | gtk_window_set_title(GTK_WINDOW(window), | ||
+ | gtk_widget_set_app_paintable(window, | ||
+ | |||
+ | g_timeout_add(14, | ||
+ | |||
+ | gtk_widget_show_all(window); | ||
+ | |||
+ | gtk_main(); | ||
+ | |||
+ | return 0; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | فى هذا المثال سننشئ نص يكبر ويتلاشى على النافذة. | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | gint x = widget-> | ||
+ | gint y = widget-> | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | Coordinates of the middle point. | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | نجعل الخلفية احمر غامق. | ||
+ | |||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | size += 0.8; | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | مع كل دورة يزيد حجم الخط بمقدار 0.8 | ||
+ | |||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | if (size > 20) { | ||
+ | alpha -= 0.01; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | التلاشى يبدأ عندما يزيد حجم الخط عن 20 | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | </ | ||
+ | |||
+ | نحصل على مقاييس النص. | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | </ | ||
+ | |||
+ | |||
+ | نستخدم مقاييس النص لسنترته -وضعه بالمنتصف- على النافذه | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | | ||
+ | </ | ||
+ | |||
+ | |||
+ | نحصل على مسار النص ونحدد منطقة القصاصة الحالية | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | نرسم المسار مع استخدام قيمة الفا | ||
+ | |||
+ | |||
+ | |||
+ | {{ http:// | ||
+ | |||
+ | |||
+ | ===== الصور فى كايرو ===== | ||
+ | |||
+ | |||
+ | |||
+ | فى هذه الجزئية سنتحدث عن الصور. سنوضح كيفية عرض صورة على نافذة. وسنقوم بعمل بعض التأثيرات على الصور. | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ==== عرض صورة ==== | ||
+ | |||
+ | فى اول مثال سنقوم بعرض صورة | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | #include & | ||
+ | #include & | ||
+ | |||
+ | cairo_surface_t *image; | ||
+ | |||
+ | static gboolean | ||
+ | on_expose_event(GtkWidget *widget, | ||
+ | GdkEventExpose *event, | ||
+ | gpointer data) | ||
+ | { | ||
+ | cairo_t *cr; | ||
+ | |||
+ | cr = gdk_cairo_create (widget-> | ||
+ | |||
+ | cairo_set_source_surface(cr, | ||
+ | cairo_paint(cr); | ||
+ | |||
+ | cairo_destroy(cr); | ||
+ | |||
+ | return FALSE; | ||
+ | } | ||
+ | |||
+ | |||
+ | int main(int argc, char *argv[]) | ||
+ | { | ||
+ | GtkWidget *window; | ||
+ | |||
+ | image = cairo_image_surface_create_from_png(" | ||
+ | |||
+ | gtk_init(& | ||
+ | |||
+ | window = gtk_window_new(GTK_WINDOW_TOPLEVEL); | ||
+ | |||
+ | g_signal_connect(window, | ||
+ | G_CALLBACK (on_expose_event), | ||
+ | g_signal_connect(window, | ||
+ | G_CALLBACK (gtk_main_quit), | ||
+ | |||
+ | gtk_window_set_position(GTK_WINDOW(window), | ||
+ | gtk_window_set_default_size(GTK_WINDOW(window), | ||
+ | gtk_widget_set_app_paintable(window, | ||
+ | |||
+ | gtk_widget_show_all(window); | ||
+ | |||
+ | gtk_main(); | ||
+ | |||
+ | cairo_surface_destroy(image); | ||
+ | |||
+ | return 0; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | المثال يعرض صورة 300x225 .. تستطيع تحميلها من <a href=" | ||
+ | هذه قلعة medieval فى Palvecke Podharadie فى غرب سلوفاكيا | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | image = cairo_image_surface_create_from_png(" | ||
+ | </ | ||
+ | |||
+ | |||
+ | ننشئ سطح صورة من صورة PNG ولأسباب متعلفة بالكفاءة يتم استدعائها فى الدالة الرئيسية | ||
+ | |||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | </ | ||
+ | نحدد المصدر للرسم من سطح الصورة المنشئ سابقا | ||
+ | |||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | نرسم على النافذة | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | {{ http:// | ||
+ | |||
+ | |||
+ | |||
+ | ==== تأثير الستارة ==== | ||
+ | |||
+ | فى هذا المثال سنقوم بتأثير كاننا نرفع ستارة من على صورة من اعلى لأسفل حتى تظهر الصورة كاملة. | ||
+ | |||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | #include & | ||
+ | #include & | ||
+ | |||
+ | |||
+ | gboolean timer = TRUE; | ||
+ | cairo_surface_t *image; | ||
+ | |||
+ | |||
+ | static gboolean | ||
+ | on_expose_event(GtkWidget *widget, | ||
+ | GdkEventExpose *event, | ||
+ | gpointer data) | ||
+ | { | ||
+ | cairo_t *cr; | ||
+ | cairo_t *ic; | ||
+ | |||
+ | cairo_surface_t *surface; | ||
+ | |||
+ | static gdouble angle = 0; | ||
+ | static gint image_width = 0; | ||
+ | static gint image_height = 0; | ||
+ | |||
+ | static gint w = 0; | ||
+ | static gint h = 0; | ||
+ | |||
+ | cr = gdk_cairo_create(widget-> | ||
+ | |||
+ | gint width, height; | ||
+ | gtk_window_get_size(GTK_WINDOW(widget), | ||
+ | |||
+ | image_width = cairo_image_surface_get_width(image); | ||
+ | image_height = cairo_image_surface_get_height(image); | ||
+ | w = image_width; | ||
+ | |||
+ | surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, | ||
+ | ic = cairo_create(surface); | ||
+ | |||
+ | cairo_rectangle(ic, | ||
+ | cairo_fill(ic); | ||
+ | |||
+ | h += 1; | ||
+ | if ( h == image_height) timer = FALSE; | ||
+ | |||
+ | cairo_set_source_surface(cr, | ||
+ | cairo_mask_surface(cr, | ||
+ | |||
+ | cairo_surface_destroy(surface); | ||
+ | |||
+ | cairo_destroy(cr); | ||
+ | cairo_destroy(ic); | ||
+ | return FALSE; | ||
+ | } | ||
+ | |||
+ | static gboolean | ||
+ | time_handler(GtkWidget *widget) | ||
+ | { | ||
+ | if (widget-> | ||
+ | |||
+ | if (!timer) return FALSE; | ||
+ | |||
+ | gtk_widget_queue_draw(widget); | ||
+ | return TRUE; | ||
+ | } | ||
+ | |||
+ | int main(int argc, char *argv[]) | ||
+ | { | ||
+ | GtkWidget *window; | ||
+ | |||
+ | image = cairo_image_surface_create_from_png(" | ||
+ | |||
+ | gtk_init(& | ||
+ | |||
+ | window = gtk_window_new(GTK_WINDOW_TOPLEVEL); | ||
+ | |||
+ | g_signal_connect(G_OBJECT(window), | ||
+ | G_CALLBACK(on_expose_event), | ||
+ | g_signal_connect(G_OBJECT(window), | ||
+ | G_CALLBACK(gtk_main_quit), | ||
+ | |||
+ | gtk_window_set_position(GTK_WINDOW(window), | ||
+ | gtk_window_set_default_size(GTK_WINDOW(window), | ||
+ | gtk_window_set_title(GTK_WINDOW(window), | ||
+ | |||
+ | gtk_widget_set_app_paintable(window, | ||
+ | g_timeout_add(15, | ||
+ | |||
+ | gtk_widget_show_all(window); | ||
+ | |||
+ | gtk_main(); | ||
+ | |||
+ | cairo_surface_destroy(image); | ||
+ | |||
+ | return 0; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | الفكرة وراء هذا التأثير بسيطة جدا اذا كانت الصورة بإرتفاع م بكسل فإننا نقوم برسم الخطوط من 0 الى م بإرتفاع 1 بكسل حتى تظهر الصورة كاملة. | ||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | | ||
+ | </ | ||
+ | |||
+ | |||
+ | هنا نقوم بتعريف سياقين كايرو، واحد ليربط بالنافذة والآخر بالصورة. | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | ic = cairo_create(surface); | ||
+ | </ | ||
+ | |||
+ | ننشئ سطح صورة ومنه ننشئ سياق كايرو. | ||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | | ||
+ | </ | ||
+ | |||
+ | |||
+ | هنا نرسم ابتدائيا مستطيل فارغ وفى كل دورة يزداد 1 بكسل والصورة المنشئة بهذه الطريقة سوق تخدم كقناع لاحقا. | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | h += 1; | ||
+ | if ( h == image_height) timer = FALSE; | ||
+ | </ | ||
+ | |||
+ | |||
+ | هنا نوقف المؤقت عندما يتم رسم الصورة كاملة -الإرتفاع الحالى = ارتفاع الصورة. | ||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | | ||
+ | </ | ||
+ | |||
+ | |||
+ | صورة القلعة يتم استخدامها كمصدر للرسم والدالة **cairo_mask_surface** ترسم المصدر الحالى عبر قناة الفا للسطح كقناع. | ||
+ | |||
+ | ==== تأثير الطيف ==== | ||
+ | |||
+ | |||
+ | لم استطع ان افكر فى اسم افضل من " | ||
+ | فى المثال التالى سنقوم بتحميل صورة تظهر تدريجيا على الشاشة. | ||
+ | |||
+ | #FIXME :تنفيذ المثال | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | #include & | ||
+ | #include & | ||
+ | |||
+ | |||
+ | gboolean timer = TRUE; | ||
+ | cairo_surface_t *image; | ||
+ | |||
+ | static gboolean | ||
+ | on_expose_event(GtkWidget *widget, | ||
+ | GdkEventExpose *event, | ||
+ | gpointer data) | ||
+ | { | ||
+ | cairo_t *cr; | ||
+ | cairo_t *ic; | ||
+ | |||
+ | cairo_surface_t *surface; | ||
+ | |||
+ | static gdouble angle = 0; | ||
+ | static gint w = 0; | ||
+ | static gint h = 0; | ||
+ | |||
+ | static gint image_width = 0; | ||
+ | static gint image_height = 0; | ||
+ | |||
+ | static gint count = 0; | ||
+ | |||
+ | cr = gdk_cairo_create(widget-> | ||
+ | |||
+ | gint width, height; | ||
+ | gtk_window_get_size(GTK_WINDOW(widget), | ||
+ | |||
+ | surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, | ||
+ | |||
+ | image_width = cairo_image_surface_get_width(image); | ||
+ | image_height = cairo_image_surface_get_height(image); | ||
+ | w = image_width; | ||
+ | |||
+ | ic = cairo_create(surface); | ||
+ | |||
+ | gint i, j; | ||
+ | for (i = 0; i <= image_height; | ||
+ | for (j=0 ; j < count; j++) { | ||
+ | cairo_move_to(ic, | ||
+ | cairo_line_to(ic, | ||
+ | } | ||
+ | } | ||
+ | |||
+ | count++; | ||
+ | if ( count == 8) timer = FALSE; | ||
+ | |||
+ | cairo_stroke(ic); | ||
+ | |||
+ | cairo_set_source_surface(cr, | ||
+ | cairo_mask_surface(cr, | ||
+ | |||
+ | cairo_surface_destroy(surface); | ||
+ | |||
+ | cairo_destroy(cr); | ||
+ | cairo_destroy(ic); | ||
+ | return FALSE; | ||
+ | } | ||
+ | |||
+ | static gboolean | ||
+ | time_handler (GtkWidget *widget) | ||
+ | { | ||
+ | if (widget-> | ||
+ | |||
+ | if (!timer) return FALSE; | ||
+ | |||
+ | gtk_widget_queue_draw(widget); | ||
+ | return TRUE; | ||
+ | } | ||
+ | |||
+ | int main(int argc, char *argv[]) | ||
+ | { | ||
+ | GtkWidget *window; | ||
+ | |||
+ | image = cairo_image_surface_create_from_png(" | ||
+ | |||
+ | gtk_init(& | ||
+ | |||
+ | window = gtk_window_new(GTK_WINDOW_TOPLEVEL); | ||
+ | |||
+ | g_signal_connect(G_OBJECT(window), | ||
+ | G_CALLBACK(on_expose_event), | ||
+ | g_signal_connect(G_OBJECT(window), | ||
+ | G_CALLBACK(gtk_main_quit), | ||
+ | |||
+ | gtk_window_set_position(GTK_WINDOW(window), | ||
+ | gtk_window_set_default_size(GTK_WINDOW(window), | ||
+ | |||
+ | gtk_widget_set_app_paintable(window, | ||
+ | g_timeout_add(400, | ||
+ | |||
+ | gtk_widget_show_all(window); | ||
+ | |||
+ | gtk_main(); | ||
+ | |||
+ | cairo_surface_destroy(image); | ||
+ | |||
+ | return 0; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | المثال مشابه للمثال السابق ولكن هنا نقوم بتقسيم الصورة الى 8 خطوط كل قطعة يزداد حجمها بمقدار 1 بكسل وتعمل كقناع لعرض صورة القلعة | ||
+ | |||
+ | In most details, the example is similar to the previous one. This time, we divide the image into n parts consisting of 8 lines. | ||
+ | Each cycle each part of the image will get bigger by one pixel. The created image will serve again as a mask for displaying | ||
+ | the image of the castle. | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | gint i, j; | ||
+ | for (i = 0; i <= image_height; | ||
+ | for (j=0 ; j < count; j++) { | ||
+ | | ||
+ | | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | هنا المنطق وراء هذا المثال، نرسم الخطوط تدريجيا الى كل جزء من الأجزاء | ||
+ | |||
+ | |||
+ | {{ http:// | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ===== ودجت مخصص ===== | ||
+ | |||
+ | |||
+ | |||
+ | فى هذه الجزئية سنقوم بعمل ودجت مخصص بإستخدام كايرو. | ||
+ | |||
+ | |||
+ | |||
+ | ==== ودجت CPU ==== | ||
+ | |||
+ | |||
+ | فى المثال سننشئ ودجت لل CPU | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | /* cpu.h */ | ||
+ | |||
+ | #ifndef __CPU_H | ||
+ | #define __CPU_H | ||
+ | |||
+ | #include & | ||
+ | #include & | ||
+ | |||
+ | G_BEGIN_DECLS | ||
+ | |||
+ | |||
+ | #define GTK_CPU(obj) GTK_CHECK_CAST(obj, | ||
+ | #define GTK_CPU_CLASS(klass) GTK_CHECK_CLASS_CAST(klass, | ||
+ | #define GTK_IS_CPU(obj) GTK_CHECK_TYPE(obj, | ||
+ | |||
+ | |||
+ | typedef struct _GtkCpu GtkCpu; | ||
+ | typedef struct _GtkCpuClass GtkCpuClass; | ||
+ | |||
+ | |||
+ | struct _GtkCpu { | ||
+ | GtkWidget widget; | ||
+ | |||
+ | gint sel; | ||
+ | }; | ||
+ | |||
+ | struct _GtkCpuClass { | ||
+ | GtkWidgetClass parent_class; | ||
+ | }; | ||
+ | |||
+ | |||
+ | GtkType gtk_cpu_get_type(void); | ||
+ | void gtk_cpu_set_sel(GtkCpu *cpu, gint sel); | ||
+ | GtkWidget * gtk_cpu_new(); | ||
+ | |||
+ | |||
+ | G_END_DECLS | ||
+ | |||
+ | #endif /* __CPU_H */ | ||
+ | </ | ||
+ | |||
+ | <code cpp> | ||
+ | /* cpu.c */ | ||
+ | |||
+ | #include " | ||
+ | |||
+ | |||
+ | static void gtk_cpu_class_init(GtkCpuClass *klass); | ||
+ | static void gtk_cpu_init(GtkCpu *cpu); | ||
+ | static void gtk_cpu_size_request(GtkWidget *widget, | ||
+ | GtkRequisition *requisition); | ||
+ | static void gtk_cpu_size_allocate(GtkWidget *widget, | ||
+ | GtkAllocation *allocation); | ||
+ | static void gtk_cpu_realize(GtkWidget *widget); | ||
+ | static gboolean gtk_cpu_expose(GtkWidget *widget, | ||
+ | GdkEventExpose *event); | ||
+ | static void gtk_cpu_paint(GtkWidget *widget); | ||
+ | static void gtk_cpu_destroy(GtkObject *object); | ||
+ | |||
+ | |||
+ | GtkType | ||
+ | gtk_cpu_get_type(void) | ||
+ | { | ||
+ | static GtkType gtk_cpu_type = 0; | ||
+ | |||
+ | |||
+ | if (!gtk_cpu_type) { | ||
+ | static const GtkTypeInfo gtk_cpu_info = { | ||
+ | " | ||
+ | sizeof(GtkCpu), | ||
+ | sizeof(GtkCpuClass), | ||
+ | (GtkClassInitFunc) gtk_cpu_class_init, | ||
+ | (GtkObjectInitFunc) gtk_cpu_init, | ||
+ | NULL, | ||
+ | NULL, | ||
+ | (GtkClassInitFunc) NULL | ||
+ | }; | ||
+ | gtk_cpu_type = gtk_type_unique(GTK_TYPE_WIDGET, | ||
+ | } | ||
+ | |||
+ | |||
+ | return gtk_cpu_type; | ||
+ | } | ||
+ | |||
+ | void | ||
+ | gtk_cpu_set_state(GtkCpu *cpu, gint num) | ||
+ | { | ||
+ | | ||
+ | | ||
+ | } | ||
+ | |||
+ | |||
+ | GtkWidget * gtk_cpu_new() | ||
+ | { | ||
+ | | ||
+ | } | ||
+ | |||
+ | |||
+ | static void | ||
+ | gtk_cpu_class_init(GtkCpuClass *klass) | ||
+ | { | ||
+ | GtkWidgetClass *widget_class; | ||
+ | GtkObjectClass *object_class; | ||
+ | |||
+ | |||
+ | widget_class = (GtkWidgetClass *) klass; | ||
+ | object_class = (GtkObjectClass *) klass; | ||
+ | |||
+ | widget_class-> | ||
+ | widget_class-> | ||
+ | widget_class-> | ||
+ | widget_class-> | ||
+ | |||
+ | object_class-> | ||
+ | } | ||
+ | |||
+ | |||
+ | static void | ||
+ | gtk_cpu_init(GtkCpu *cpu) | ||
+ | { | ||
+ | | ||
+ | } | ||
+ | |||
+ | |||
+ | static void | ||
+ | gtk_cpu_size_request(GtkWidget *widget, | ||
+ | GtkRequisition *requisition) | ||
+ | { | ||
+ | g_return_if_fail(widget != NULL); | ||
+ | g_return_if_fail(GTK_IS_CPU(widget)); | ||
+ | g_return_if_fail(requisition != NULL); | ||
+ | |||
+ | requisition-> | ||
+ | requisition-> | ||
+ | } | ||
+ | |||
+ | |||
+ | static void | ||
+ | gtk_cpu_size_allocate(GtkWidget *widget, | ||
+ | GtkAllocation *allocation) | ||
+ | { | ||
+ | g_return_if_fail(widget != NULL); | ||
+ | g_return_if_fail(GTK_IS_CPU(widget)); | ||
+ | g_return_if_fail(allocation != NULL); | ||
+ | |||
+ | widget-> | ||
+ | |||
+ | if (GTK_WIDGET_REALIZED(widget)) { | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | ); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | |||
+ | static void | ||
+ | gtk_cpu_realize(GtkWidget *widget) | ||
+ | { | ||
+ | GdkWindowAttr attributes; | ||
+ | guint attributes_mask; | ||
+ | |||
+ | g_return_if_fail(widget != NULL); | ||
+ | g_return_if_fail(GTK_IS_CPU(widget)); | ||
+ | |||
+ | GTK_WIDGET_SET_FLAGS(widget, | ||
+ | |||
+ | attributes.window_type = GDK_WINDOW_CHILD; | ||
+ | attributes.x = widget-> | ||
+ | attributes.y = widget-> | ||
+ | attributes.width = 80; | ||
+ | attributes.height = 100; | ||
+ | |||
+ | attributes.wclass = GDK_INPUT_OUTPUT; | ||
+ | attributes.event_mask = gtk_widget_get_events(widget) | GDK_EXPOSURE_MASK; | ||
+ | |||
+ | attributes_mask = GDK_WA_X | GDK_WA_Y; | ||
+ | |||
+ | widget-> | ||
+ | | ||
+ | & attributes, attributes_mask | ||
+ | ); | ||
+ | |||
+ | gdk_window_set_user_data(widget-> | ||
+ | |||
+ | widget-> | ||
+ | gtk_style_set_background(widget-> | ||
+ | } | ||
+ | |||
+ | |||
+ | static gboolean | ||
+ | gtk_cpu_expose(GtkWidget *widget, | ||
+ | GdkEventExpose *event) | ||
+ | { | ||
+ | g_return_val_if_fail(widget != NULL, FALSE); | ||
+ | g_return_val_if_fail(GTK_IS_CPU(widget), | ||
+ | g_return_val_if_fail(event != NULL, FALSE); | ||
+ | |||
+ | gtk_cpu_paint(widget); | ||
+ | |||
+ | return FALSE; | ||
+ | } | ||
+ | |||
+ | |||
+ | static void | ||
+ | gtk_cpu_paint(GtkWidget *widget) | ||
+ | { | ||
+ | cairo_t *cr; | ||
+ | |||
+ | cr = gdk_cairo_create(widget-> | ||
+ | |||
+ | cairo_translate(cr, | ||
+ | |||
+ | cairo_set_source_rgb(cr, | ||
+ | cairo_paint(cr); | ||
+ | |||
+ | gint pos = GTK_CPU(widget)-> | ||
+ | gint rect = pos / 5; | ||
+ | |||
+ | cairo_set_source_rgb(cr, | ||
+ | |||
+ | gint i; | ||
+ | for ( i = 1; i <= 20; i++) { | ||
+ | if (i > 20 - rect) { | ||
+ | cairo_set_source_rgb(cr, | ||
+ | } else { | ||
+ | cairo_set_source_rgb(cr, | ||
+ | } | ||
+ | cairo_rectangle(cr, | ||
+ | cairo_rectangle(cr, | ||
+ | cairo_fill(cr); | ||
+ | } | ||
+ | |||
+ | cairo_destroy(cr); | ||
+ | } | ||
+ | |||
+ | |||
+ | static void | ||
+ | gtk_cpu_destroy(GtkObject *object) | ||
+ | { | ||
+ | GtkCpu *cpu; | ||
+ | GtkCpuClass *klass; | ||
+ | |||
+ | g_return_if_fail(object != NULL); | ||
+ | g_return_if_fail(GTK_IS_CPU(object)); | ||
+ | |||
+ | cpu = GTK_CPU(object); | ||
+ | |||
+ | klass = gtk_type_class(gtk_widget_get_type()); | ||
+ | |||
+ | if (GTK_OBJECT_CLASS(klass)-> | ||
+ | (* GTK_OBJECT_CLASS(klass)-> | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | <code cpp> | ||
+ | /* main.c */ | ||
+ | |||
+ | #include " | ||
+ | |||
+ | |||
+ | static void set_value(GtkWidget * widget, gpointer data) | ||
+ | { | ||
+ | GdkRegion *region; | ||
+ | |||
+ | GtkRange *range = (GtkRange *) widget; | ||
+ | GtkWidget *cpu = (GtkWidget *) data; | ||
+ | GTK_CPU(cpu)-> | ||
+ | |||
+ | region = gdk_drawable_get_clip_region(cpu-> | ||
+ | gdk_window_invalidate_region(cpu-> | ||
+ | gdk_window_process_updates(cpu-> | ||
+ | } | ||
+ | |||
+ | |||
+ | int main (int argc, char ** argv) | ||
+ | { | ||
+ | GtkWidget *window; | ||
+ | GtkWidget *cpu; | ||
+ | GtkWidget *fixed; | ||
+ | GtkWidget *scale; | ||
+ | |||
+ | gtk_init(& | ||
+ | |||
+ | |||
+ | window = gtk_window_new(GTK_WINDOW_TOPLEVEL); | ||
+ | gtk_window_set_title(GTK_WINDOW(window), | ||
+ | gtk_window_set_position(GTK_WINDOW(window), | ||
+ | gtk_window_set_default_size(GTK_WINDOW(window), | ||
+ | |||
+ | |||
+ | g_signal_connect(G_OBJECT(window), | ||
+ | | ||
+ | |||
+ | fixed = gtk_fixed_new(); | ||
+ | gtk_container_add(GTK_CONTAINER(window), | ||
+ | |||
+ | cpu = gtk_cpu_new(); | ||
+ | gtk_fixed_put(GTK_FIXED(fixed), | ||
+ | |||
+ | |||
+ | scale = gtk_vscale_new_with_range(0.0, | ||
+ | gtk_range_set_inverted(GTK_RANGE(scale), | ||
+ | gtk_scale_set_value_pos(GTK_SCALE(scale), | ||
+ | gtk_widget_set_size_request(scale, | ||
+ | gtk_fixed_put(GTK_FIXED(fixed), | ||
+ | |||
+ | g_signal_connect(G_OBJECT(scale), | ||
+ | |||
+ | gtk_widget_show(cpu); | ||
+ | gtk_widget_show(fixed); | ||
+ | gtk_widget_show_all(window); | ||
+ | gtk_main(); | ||
+ | |||
+ | return 0; | ||
+ | } | ||
+ | </ | ||
+ | | ||
+ | | ||
+ | | ||
+ | |||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | cairo_t *cr; | ||
+ | |||
+ | cr = gdk_cairo_create(widget-> | ||
+ | |||
+ | cairo_translate(cr, | ||
+ | |||
+ | cairo_set_source_rgb(cr, | ||
+ | cairo_paint(cr); | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | كالمعتاد، ننشئ سياق كايرو ونزيج نقطة الأصل 7 وحدات ونقوم برسم الخلفية باللون الأسود. | ||
+ | |||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | gint pos = GTK_CPU(widget)-> | ||
+ | gint rect = pos / 5; | ||
+ | </ | ||
+ | |||
+ | |||
+ | هنا نحصل على sel -الرقم الذى حصلنا عليه من ويدجت المقياس -scale- | ||
+ | المنزلق يحوى 100 رقم والمعامل rect يقوم بالتحويل من قيم المنزلق الى المستطيل -يتم رسمها بالأخضر الفاقع- | ||
+ | |||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | gint i; | ||
+ | for ( i = 1; i <= 20; i++) { | ||
+ | if (i > 20 - rect) { | ||
+ | | ||
+ | } else { | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | بناءا على رقم ال rect نرسم 40 مستطيل باللونين الأخضر الغامق والفاقع، تذكر اننا نقوم برسم هذه المستطيلات من اعلى لأسفل. | ||
+ | |||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | | ||
+ | | ||
+ | </ | ||
+ | |||
+ | |||
+ | استدعاء الدالة **set_value** نحصل على مرجع -reference - لويدجت ال CPU ونحدد قيمة " | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | | ||
+ | ... | ||
+ | | ||
+ | | ||
+ | | ||
+ | </ | ||
+ | |||
+ | هذا الكود يلغى مفعولة النافذة لويدجت ال CPU فقتوم بإعادة رسم نفسها. | ||
+ | |||
+ | |||
+ | {{ http:// | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
docs/cairographics.txt · آخر تعديل: 2015/04/23 03:19 (تحرير خارجي)