天天看點

Cairo 圖形指南 (3) —— 變換

這一篇講述變換(Transformation) 仿射變換是由一些線性變換與平移構成的。線性變換可以寫為單個矩陣的形式。旋轉是讓一個剛體繞一點運動的變換。縮放變換是讓物體的形狀擴大與減小,并且在各個方向上的縮放因子都相同。平移變換将每個點沿着指定的方向移動常量距離。錯切對于給定軸線,沿垂直于它的方向對物體進行移動的變換,并且在軸線的一側的移動距離大于另一側。

——上述内容來自維基百科全書

平移

下面這個例子示範了一個簡單的平移變換。

[html] view plain copy print ?

  1. #include <cairo.h>  
  2. #include <gtk/gtk.h>  
  3. staticgboolean  
  4. on_expose_event(GtkWidget *widget,  
  5.     GdkEventExpose *event,  
  6.     gpointer data)  
  7. {  
  8.   cairo_t *cr;  
  9.   cr = gdk_cairo_create (widget->window);  
  10.   cairo_set_source_rgb(cr, 0.6, 0.6, 0.6);  
  11.   cairo_rectangle(cr, 20, 20, 80, 50);  
  12.   cairo_stroke_preserve(cr);  
  13.   cairo_set_source_rgb(cr, 1, 1, 1);  
  14.   cairo_fill(cr);  
  15.   cairo_translate(cr, 100, 100);  
  16.   cairo_set_source_rgb(cr, 0.6, 0.6, 0.6);  
  17.   cairo_rectangle(cr, 20, 20, 80, 50);  
  18.   cairo_stroke_preserve(cr);  
  19.   cairo_set_source_rgb(cr, 1, 1, 1);  
  20.   cairo_fill(cr);  
  21.   cairo_destroy(cr);  
  22.   returnFALSE;  
  23. }  
  24. int main(int argc,char *argv[])  
  25. {  
  26.   GtkWidget *window;  
  27.   gtk_init(&argc, &argv);  
  28.   window = gtk_window_new(GTK_WINDOW_TOPLEVEL);  
  29.   g_signal_connect(window,"expose-event",  
  30.       G_CALLBACK (on_expose_event), NULL);  
  31.   g_signal_connect(window,"destroy",  
  32.       G_CALLBACK (gtk_main_quit), NULL);  
  33.   gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);  
  34.   gtk_window_set_default_size(GTK_WINDOW(window), 300, 230);  
  35.   gtk_widget_set_app_paintable(window, TRUE);  
  36.   gtk_widget_show_all(window);  
  37.   gtk_main();  
  38.   return0;  
  39. }  

#include

<cairo.h>

#include <gtk/gtk.h>

staticgboolean

on_expose_event(GtkWidget *widget,

GdkEventExpose *event,

gpointer data)

{

cairo_t *cr;

cr = gdk_cairo_create (widget->window);

cairo_set_source_rgb(cr, 0.6, 0.6, 0.6);

cairo_rectangle(cr, 20, 20, 80, 50);

cairo_stroke_preserve(cr);

cairo_set_source_rgb(cr, 1, 1, 1);

cairo_fill(cr);

cairo_translate(cr, 100, 100);

cairo_set_source_rgb(cr, 0.6, 0.6, 0.6);

cairo_rectangle(cr, 20, 20, 80, 50);

cairo_stroke_preserve(cr);

cairo_set_source_rgb(cr, 1, 1, 1);

cairo_fill(cr);

cairo_destroy(cr);

returnFALSE;

}

int main(int argc,char *argv[])

{

GtkWidget *window;

gtk_init(&argc, &argv);

window = gtk_window_new(GTK_WINDOW_TOPLEVEL);

g_signal_connect(window,"expose-event",

G_CALLBACK (on_expose_event), NULL);

g_signal_connect(window,"destroy",

G_CALLBACK (gtk_main_quit), NULL);

gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);

gtk_window_set_default_size(GTK_WINDOW(window), 300, 230);

gtk_widget_set_app_paintable(window, TRUE);

gtk_widget_show_all(window);

gtk_main();

return0;

}

這個例子先是畫了個矩形,然後将它平移并繪制出平移結果。

cairo_translate(cr, 100, 100);

cairo_translate() 函數可通過平移用于空間的原點來修改目前的變換矩陣。在這個示例中,是将原點沿水準和豎直方向平移了 100 個機關長度。

Cairo 圖形指南 (3) —— 變換

旋轉

下面這個例子示範了一個簡單的旋轉變換。

[html] view plain copy print ?

  1. #include <cairo.h>  
  2. #include <gtk/gtk.h>  
  3. #include <math.h>  
  4. staticgboolean  
  5. on_expose_event(GtkWidget *widget,  
  6.     GdkEventExpose *event,  
  7.     gpointer data)  
  8. {  
  9.   cairo_t *cr;  
  10.   cr = gdk_cairo_create (widget->window);  
  11.   cairo_set_source_rgb(cr, 0.6, 0.6, 0.6);  
  12.   cairo_rectangle(cr, 20, 20, 80, 50);  
  13.   cairo_stroke_preserve(cr);  
  14.   cairo_set_source_rgb(cr, 1, 1, 1);  
  15.   cairo_fill(cr);  
  16.   cairo_translate(cr, 150, 100);  
  17.   cairo_rotate(cr, M_PI/2);  
  18.   cairo_set_source_rgb(cr, 0.6, 0.6, 0.6);  
  19.   cairo_rectangle(cr, 20, 20, 80, 50);  
  20.   cairo_stroke_preserve(cr);  
  21.   cairo_set_source_rgb(cr, 1, 1, 1);  
  22.   cairo_fill(cr);  
  23.   cairo_destroy(cr);  
  24.   returnFALSE;  
  25. }  
  26. int main(int argc,char *argv[])  
  27. {  
  28.   GtkWidget *window;  
  29.   gtk_init(&argc, &argv);  
  30.   window = gtk_window_new(GTK_WINDOW_TOPLEVEL);  
  31.   g_signal_connect(window,"expose-event",  
  32.       G_CALLBACK (on_expose_event), NULL);  
  33.   g_signal_connect(window,"destroy",  
  34.       G_CALLBACK (gtk_main_quit), NULL);  
  35.   gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);  
  36.   gtk_window_set_default_size(GTK_WINDOW(window), 300, 230);  
  37.   gtk_widget_set_app_paintable(window, TRUE);  
  38.   gtk_widget_show_all(window);  
  39.   gtk_main();  
  40.   return0;  
  41. }  

#include

<cairo.h>

#include <gtk/gtk.h>

#include <math.h>

staticgboolean

on_expose_event(GtkWidget *widget,

GdkEventExpose *event,

gpointer data)

{

cairo_t *cr;

cr = gdk_cairo_create (widget->window);

cairo_set_source_rgb(cr, 0.6, 0.6, 0.6);

cairo_rectangle(cr, 20, 20, 80, 50);

cairo_stroke_preserve(cr);

cairo_set_source_rgb(cr, 1, 1, 1);

cairo_fill(cr);

cairo_translate(cr, 150, 100);

cairo_rotate(cr, M_PI/2);

cairo_set_source_rgb(cr, 0.6, 0.6, 0.6);

cairo_rectangle(cr, 20, 20, 80, 50);

cairo_stroke_preserve(cr);

cairo_set_source_rgb(cr, 1, 1, 1);

cairo_fill(cr);

cairo_destroy(cr);

returnFALSE;

}

int main(int argc,char *argv[])

{

GtkWidget *window;

gtk_init(&argc, &argv);

window = gtk_window_new(GTK_WINDOW_TOPLEVEL);

g_signal_connect(window,"expose-event",

G_CALLBACK (on_expose_event), NULL);

g_signal_connect(window,"destroy",

G_CALLBACK (gtk_main_quit), NULL);

gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);

gtk_window_set_default_size(GTK_WINDOW(window), 300, 230);

gtk_widget_set_app_paintable(window, TRUE);

gtk_widget_show_all(window);

gtk_main();

return0;

}

這個例子先是畫了個矩形,然後對它進行了平移和旋轉變換,并繪制出變換結果。

cairo_translate(cr, 150, 100);

cairo_rotate(cr, M_PI/2);

首先對使用者空間的原點進行平移,然後再圍繞它旋轉 180°。注意:旋轉角度是弧度,而非角度。

Cairo 圖形指南 (3) —— 變換

縮放

下面這個例子示範了一個對象的縮放變換。(作者還真是沉悶阿,相同的句式連用了 n 次,這個可憐的矩形被折騰的痛苦不堪!)

[html] view plain copy print ?

  1. #include <cairo.h>  
  2. #include <gtk/gtk.h>  
  3. staticgboolean  
  4. on_expose_event(GtkWidget *widget,  
  5.     GdkEventExpose *event,  
  6.     gpointer data)  
  7. {  
  8.   cairo_t *cr;  
  9.   cr = gdk_cairo_create (widget->window);  
  10.   cairo_save(cr);  
  11.   cairo_set_source_rgb(cr, 0.6, 0.6, 0.6);  
  12.   cairo_rectangle(cr, 20, 30, 80, 50);  
  13.   cairo_stroke_preserve(cr);  
  14.   cairo_set_source_rgb(cr, 1, 1, 1);  
  15.   cairo_fill(cr);  
  16.   cairo_restore(cr);  
  17.   cairo_save(cr);  
  18.   cairo_translate(cr, 130, 30);  
  19.   cairo_scale(cr, 0.7, 0.7);  
  20.   cairo_set_source_rgb(cr, 0.6, 0.6, 0.6);  
  21.   cairo_rectangle(cr, 0, 0, 80, 50);  
  22.   cairo_stroke_preserve(cr);  
  23.   cairo_set_source_rgb(cr, 1, 1, 1);  
  24.   cairo_fill(cr);  
  25.   cairo_restore(cr);  
  26.   cairo_save(cr);  
  27.   cairo_translate(cr, 220, 30);  
  28.   cairo_scale(cr, 1.5, 1.5);  
  29.   cairo_set_source_rgb(cr, 0.6, 0.6, 0.6);  
  30.   cairo_rectangle(cr, 0, 0, 80, 50);  
  31.   cairo_stroke_preserve(cr);  
  32.   cairo_set_source_rgb(cr, 1, 1, 1);  
  33.   cairo_fill(cr);  
  34.   cairo_restore(cr);  
  35.   cairo_destroy(cr);  
  36.   returnFALSE;  
  37. }  
  38. int main(int argc,char *argv[])  
  39. {  
  40.   GtkWidget *window;  
  41.   gtk_init(&argc, &argv);  
  42.   window = gtk_window_new(GTK_WINDOW_TOPLEVEL);  
  43.   g_signal_connect(window,"expose-event",  
  44.       G_CALLBACK (on_expose_event), NULL);  
  45.   g_signal_connect(window,"destroy",  
  46.       G_CALLBACK (gtk_main_quit), NULL);  
  47.   gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);  
  48.   gtk_window_set_default_size(GTK_WINDOW(window), 360, 140);  
  49.   gtk_widget_set_app_paintable(window, TRUE);  
  50.   gtk_widget_show_all(window);  
  51.   gtk_main();  
  52.   return0;  
  53. }  

#include

<cairo.h>

#include <gtk/gtk.h>

staticgboolean

on_expose_event(GtkWidget *widget,

GdkEventExpose *event,

gpointer data)

{

cairo_t *cr;

cr = gdk_cairo_create (widget->window);

cairo_save(cr);

cairo_set_source_rgb(cr, 0.6, 0.6, 0.6);

cairo_rectangle(cr, 20, 30, 80, 50);

cairo_stroke_preserve(cr);

cairo_set_source_rgb(cr, 1, 1, 1);

cairo_fill(cr);

cairo_restore(cr);

cairo_save(cr);

cairo_translate(cr, 130, 30);

cairo_scale(cr, 0.7, 0.7);

cairo_set_source_rgb(cr, 0.6, 0.6, 0.6);

cairo_rectangle(cr, 0, 0, 80, 50);

cairo_stroke_preserve(cr);

cairo_set_source_rgb(cr, 1, 1, 1);

cairo_fill(cr);

cairo_restore(cr);

cairo_save(cr);

cairo_translate(cr, 220, 30);

cairo_scale(cr, 1.5, 1.5);

cairo_set_source_rgb(cr, 0.6, 0.6, 0.6);

cairo_rectangle(cr, 0, 0, 80, 50);

cairo_stroke_preserve(cr);

cairo_set_source_rgb(cr, 1, 1, 1);

cairo_fill(cr);

cairo_restore(cr);

cairo_destroy(cr);

returnFALSE;

}

int main(int argc,char *argv[])

{

GtkWidget *window;

gtk_init(&argc, &argv);

window = gtk_window_new(GTK_WINDOW_TOPLEVEL);

g_signal_connect(window,"expose-event",

G_CALLBACK (on_expose_event), NULL);

g_signal_connect(window,"destroy",

G_CALLBACK (gtk_main_quit), NULL);

gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);

gtk_window_set_default_size(GTK_WINDOW(window), 360, 140);

gtk_widget_set_app_paintable(window, TRUE);

gtk_widget_show_all(window);

gtk_main();

return0;

}

這次的例子是用指定的縮放因子,把初始的矩形變的小了點,然後又把它變的大了點。

cairo_save(cr);

...

cairo_restore(cr);

若對初始的矩形完成兩次縮放操作,需要将初始的變換矩陣儲存一下,這個可通過 cairo_save() 和 cairo_restore() 函數來實作。

cairo_translate(cr, 130, 30);

cairo_scale(cr, 0.7, 0.7);

這裡首先将使用者空間的原點平移了一下,然後又開始用 0.7 作為因子進行縮放變換。

Cairo 圖形指南 (3) —— 變換

錯切

在下面的示例中,我們來實作錯切變換。

[html] view plain copy print ?

  1. #include <cairo.h>  
  2. #include <gtk/gtk.h>  
  3. staticgboolean  
  4. on_expose_event(GtkWidget *widget,  
  5.     GdkEventExpose *event,  
  6.     gpointer data)  
  7. {  
  8.   cairo_t *cr;  
  9.   cairo_matrix_t matrix;  
  10.   cr = gdk_cairo_create (widget->window);  
  11.   cairo_save(cr);  
  12.   cairo_set_source_rgb(cr, 0.6, 0.6, 0.6);  
  13.   cairo_rectangle(cr, 20, 30, 80, 50);  
  14.   cairo_stroke_preserve(cr);  
  15.   cairo_set_source_rgb(cr, 1, 1, 1);  
  16.   cairo_fill(cr);  
  17.   cairo_restore(cr);  
  18.   cairo_save(cr);  
  19.   cairo_translate(cr, 130, 30);  
  20.   cairo_matrix_init(&matrix,  
  21.       1.0, 0.5,  
  22.       0.0, 1.0,  
  23.       0.0, 0.0);  
  24.   cairo_transform (cr, &matrix);  
  25.   cairo_set_source_rgb(cr, 0.6, 0.6, 0.6);  
  26.   cairo_rectangle(cr, 0, 0, 80, 50);  
  27.   cairo_stroke_preserve(cr);  
  28.   cairo_set_source_rgb(cr, 1, 1, 1);  
  29.   cairo_fill(cr);  
  30.   cairo_restore(cr);  
  31.   cairo_save(cr);  
  32.   cairo_translate(cr, 220, 30);  
  33.   cairo_matrix_init(&matrix,  
  34.       1.0, 0.0,  
  35.       0.7, 1.0,  
  36.       0.0, 0.0);  
  37.   cairo_transform(cr, &matrix);  
  38.   cairo_set_source_rgb(cr, 0.6, 0.6, 0.6);  
  39.   cairo_rectangle(cr, 0, 0, 80, 50);  
  40.   cairo_stroke_preserve(cr);  
  41.   cairo_set_source_rgb(cr, 1, 1, 1);  
  42.   cairo_fill(cr);  
  43.   cairo_restore(cr);  
  44.   cairo_destroy(cr);  
  45.   returnFALSE;  
  46. }  
  47. int main(int argc,char *argv[])  
  48. {  
  49.   GtkWidget *window;  
  50.   gtk_init(&argc, &argv);  
  51.   window = gtk_window_new(GTK_WINDOW_TOPLEVEL);  
  52.   g_signal_connect(window,"expose-event",  
  53.       G_CALLBACK(on_expose_event), NULL);  
  54.   g_signal_connect(window,"destroy",  
  55.       G_CALLBACK(gtk_main_quit), NULL);  
  56.   gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);  
  57.   gtk_window_set_default_size(GTK_WINDOW(window), 360, 140);  
  58.   gtk_widget_set_app_paintable(window, TRUE);  
  59.   gtk_widget_show_all(window);  
  60.   gtk_main();  
  61.   return0;  
  62. }  

#include

<cairo.h>

#include <gtk/gtk.h>

staticgboolean

on_expose_event(GtkWidget *widget,

GdkEventExpose *event,

gpointer data)

{

cairo_t *cr;

cairo_matrix_t matrix;

cr = gdk_cairo_create (widget->window);

cairo_save(cr);

cairo_set_source_rgb(cr, 0.6, 0.6, 0.6);

cairo_rectangle(cr, 20, 30, 80, 50);

cairo_stroke_preserve(cr);

cairo_set_source_rgb(cr, 1, 1, 1);

cairo_fill(cr);

cairo_restore(cr);

cairo_save(cr);

cairo_translate(cr, 130, 30);

cairo_matrix_init(&matrix,

1.0, 0.5,

0.0, 1.0,

0.0, 0.0);

cairo_transform (cr, &matrix);

cairo_set_source_rgb(cr, 0.6, 0.6, 0.6);

cairo_rectangle(cr, 0, 0, 80, 50);

cairo_stroke_preserve(cr);

cairo_set_source_rgb(cr, 1, 1, 1);

cairo_fill(cr);

cairo_restore(cr);

cairo_save(cr);

cairo_translate(cr, 220, 30);

cairo_matrix_init(&matrix,

1.0, 0.0,

0.7, 1.0,

0.0, 0.0);

cairo_transform(cr, &matrix);

cairo_set_source_rgb(cr, 0.6, 0.6, 0.6);

cairo_rectangle(cr, 0, 0, 80, 50);

cairo_stroke_preserve(cr);

cairo_set_source_rgb(cr, 1, 1, 1);

cairo_fill(cr);

cairo_restore(cr);

cairo_destroy(cr);

returnFALSE;

}

int main(int argc,char *argv[])

{

GtkWidget *window;

gtk_init(&argc, &argv);

window = gtk_window_new(GTK_WINDOW_TOPLEVEL);

g_signal_connect(window,"expose-event",

G_CALLBACK(on_expose_event), NULL);

g_signal_connect(window,"destroy",

G_CALLBACK(gtk_main_quit), NULL);

gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);

gtk_window_set_default_size(GTK_WINDOW(window), 360, 140);

gtk_widget_set_app_paintable(window, TRUE);

gtk_widget_show_all(window);

gtk_main();

return0;

}

這份示例代碼實作了兩次錯切變換。對于錯切變換,沒有特定的函數,必須使用矩陣來實作。

cairo_matrix_t matrix;

這個 cairo_matrix 是存儲仿射變換的資料結構。 

cairo_matrix_init(&matrix,

1.0, 0.5,

0.0, 1.0,

0.0, 0.0);

cairo_transform (cr, &matrix);

這一變換的數學形式可表示為:

Cairo 圖形指南 (3) —— 變換

cairo_matrix_init(&matrix,

1.0, 0.0,

0.7, 1.0,

0.0, 0.0);

cairo_transform(cr, &matrix);

這一變換的數學形式可表示為:

Cairo 圖形指南 (3) —— 變換
Cairo 圖形指南 (3) —— 變換

橢圓

下面的這個例子,畫了一個灰常複雜的形狀,它由一串旋轉的橢圓形成。

[html] view plain copy print ?

  1. #include <cairo.h>  
  2. #include <gtk/gtk.h>  
  3. staticgboolean  
  4. on_expose_event(GtkWidget *widget,  
  5.     GdkEventExpose *event,  
  6.     gpointer data)  
  7. {  
  8.   cairo_t *cr;  
  9.   cr = gdk_cairo_create(widget->window);  
  10.   gint width, height;  
  11.   gtk_window_get_size(GTK_WINDOW(widget), &width, &height);  
  12.   cairo_set_line_width(cr, 0.5);  
  13.   cairo_translate(cr, width/2, height/2);  
  14.   cairo_arc(cr, 0, 0, 120, 0, 2 * M_PI);  
  15.   cairo_stroke(cr);  
  16.   gint i;  
  17.   cairo_save(cr);  
  18.   for( i = 0; i < 36; i++) {  
  19.       cairo_rotate(cr, i*M_PI/36);  
  20.       cairo_scale(cr, 0.3, 1);  
  21.       cairo_arc(cr, 0, 0, 120, 0, 2 * M_PI);  
  22.       cairo_restore(cr);  
  23.       cairo_stroke(cr);  
  24.       cairo_save(cr);  
  25.   }  
  26.   cairo_destroy(cr);  
  27.   returnFALSE;  
  28. }  
  29. int main(int argc,char *argv[])  
  30. {  
  31.   GtkWidget *window;  
  32.   gtk_init(&argc, &argv);  
  33.   window = gtk_window_new(GTK_WINDOW_TOPLEVEL);  
  34.   g_signal_connect(G_OBJECT(window),"expose-event",  
  35.       G_CALLBACK(on_expose_event), NULL);  
  36.   g_signal_connect(G_OBJECT(window),"destroy",  
  37.       G_CALLBACK(gtk_main_quit), NULL);  
  38.   gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);  
  39.   gtk_window_set_default_size(GTK_WINDOW(window), 350, 250);  
  40.   gtk_widget_set_app_paintable(window, TRUE);  
  41.   gtk_widget_show_all(window);  
  42.   gtk_main();  
  43.   return0;  
  44. }  

#include

<cairo.h>

#include <gtk/gtk.h>

staticgboolean

on_expose_event(GtkWidget *widget,

GdkEventExpose *event,

gpointer data)

{

cairo_t *cr;

cr = gdk_cairo_create(widget->window);

gint width, height;

gtk_window_get_size(GTK_WINDOW(widget), &width, &height);

cairo_set_line_width(cr, 0.5);

cairo_translate(cr, width/2, height/2);

cairo_arc(cr, 0, 0, 120, 0, 2 * M_PI);

cairo_stroke(cr);

gint i;

cairo_save(cr);

for( i = 0; i < 36; i++) {

cairo_rotate(cr, i*M_PI/36);

cairo_scale(cr, 0.3, 1);

cairo_arc(cr, 0, 0, 120, 0, 2 * M_PI);

cairo_restore(cr);

cairo_stroke(cr);

cairo_save(cr);

}

cairo_destroy(cr);

returnFALSE;

}

int main(int argc,char *argv[])

{

GtkWidget *window;

gtk_init(&argc, &argv);

window = gtk_window_new(GTK_WINDOW_TOPLEVEL);

g_signal_connect(G_OBJECT(window),"expose-event",

G_CALLBACK(on_expose_event), NULL);

g_signal_connect(G_OBJECT(window),"destroy",

G_CALLBACK(gtk_main_quit), NULL);

gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);

gtk_window_set_default_size(GTK_WINDOW(window), 350, 250);

gtk_widget_set_app_paintable(window, TRUE);

gtk_widget_show_all(window);

gtk_main();

return0;

}

cairo_translate(cr, width/2, height/2);

cairo_arc(cr, 0, 0, 120, 0, 2 * M_PI);

cairo_stroke(cr);

在 GTK+ 的視窗中間,繪制了一個圓,它是那些橢圓的邊界圓。

cairo_save(cr);

for

( i = 0; i < 36; i++) {

cairo_rotate(cr, i*M_PI/36);

cairo_scale(cr, 0.3, 1);

cairo_arc(cr, 0, 0, 120, 0, 2 * M_PI);

cairo_restore(cr);

cairo_stroke(cr);

cairo_save(cr);

}

沿着邊界圓畫 36 個橢圓。橢圓可用圓的縮放變換而獲得。旋轉這個橢圓,這樣就建立了一個有趣的形狀。

Cairo 圖形指南 (3) —— 變換

星星

下面的示例繪制了一個又旋轉又縮放的星星,可惜不會發光呃。

[html] view plain copy print ?

  1. #include <cairo.h>  
  2. #include <gtk/gtk.h>  
  3. #include <math.h>  
  4. int points[11][2] = {  
  5.     { 0, 85 },  
  6.     { 75, 75 },  
  7.     { 100, 10 },  
  8.     { 125, 75 },  
  9.     { 200, 85 },  
  10.     { 150, 125 },  
  11.     { 160, 190 },  
  12.     { 100, 150 },  
  13.     { 40, 190 },  
  14.     { 50, 125 },  
  15.     { 0, 85 }  
  16. };  
  17. staticgboolean  
  18. on_expose_event(GtkWidget *widget,  
  19.     GdkEventExpose *event,  
  20.     gpointer data)  
  21. {  
  22.   cairo_t *cr;  
  23.   staticgdouble angle = 0;  
  24.   staticgdouble scale = 1;  
  25.   staticgdouble delta = 0.01;  
  26.   gint width, height;  
  27.   gtk_window_get_size(GTK_WINDOW(widget), &width, &height);  
  28.   cr = gdk_cairo_create(widget->window);  
  29.   cairo_set_source_rgb(cr, 0, 0.44, 0.7);  
  30.   cairo_set_line_width(cr, 1);  
  31.   cairo_translate(cr, width / 2, height / 2 );  
  32.   cairo_rotate(cr, angle);  
  33.   cairo_scale(cr, scale, scale);  
  34.   gint i;  
  35.   for( i = 0; i < 10; i++ ) {  
  36.       cairo_line_to(cr, points[i][0], points[i][1]);  
  37.   }  
  38.   cairo_close_path(cr);  
  39.   cairo_fill(cr);  
  40.   cairo_stroke(cr);  
  41.   if( scale < 0.01 ) {  
  42.       delta = -delta;  
  43.   }else if (scale > 0.99) {  
  44.       delta = -delta;  
  45.   }  
  46.   scale += delta;  
  47.   angle += 0.01;  
  48.   cairo_destroy(cr);  
  49.   returnFALSE;  
  50. }  
  51. staticgboolean  
  52. time_handler (GtkWidget *widget)  
  53. {  
  54.   if(widget->window == NULL) returnFALSE;  
  55.   gtk_widget_queue_draw(widget);  
  56.   returnTRUE;  
  57. }  
  58. int main(int argc,char *argv[])  
  59. {  
  60.   GtkWidget *window;  
  61.   gtk_init(&argc, &argv);  
  62.   window = gtk_window_new(GTK_WINDOW_TOPLEVEL);  
  63.   gtk_widget_add_events (window, GDK_BUTTON_PRESS_MASK);  
  64.   g_signal_connect(window,"expose-event",  
  65.       G_CALLBACK(on_expose_event), NULL);  
  66.   g_signal_connect(window,"destroy",  
  67.       G_CALLBACK(gtk_main_quit), NULL);  
  68.   gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);  
  69.   gtk_window_set_title(GTK_WINDOW(window),"star");  
  70.   gtk_window_set_default_size(GTK_WINDOW(window), 400, 300);  
  71.   gtk_widget_set_app_paintable(window, TRUE);  
  72.   g_timeout_add(10, (GSourceFunc) time_handler, (gpointer) window);   
  73.   gtk_widget_show_all(window);  
  74.   gtk_main();  
  75.   return0;  
  76. }  

#include

<cairo.h>

#include <gtk/gtk.h>

#include <math.h>

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 }

};

staticgboolean

on_expose_event(GtkWidget *widget,

GdkEventExpose *event,

gpointer data)

{

cairo_t *cr;

staticgdouble angle = 0;

staticgdouble scale = 1;

staticgdouble delta = 0.01;

gint width, height;

gtk_window_get_size(GTK_WINDOW(widget), &width, &height);

cr = gdk_cairo_create(widget->window);

cairo_set_source_rgb(cr, 0, 0.44, 0.7);

cairo_set_line_width(cr, 1);

cairo_translate(cr, width / 2, height / 2 );

cairo_rotate(cr, angle);

cairo_scale(cr, scale, scale);

gint i;

for( i = 0; i < 10; i++ ) {

cairo_line_to(cr, points[i][0], points[i][1]);

}

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);

returnFALSE;

}

staticgboolean

time_handler (GtkWidget *widget)

{

if(widget->window == NULL) returnFALSE;

gtk_widget_queue_draw(widget);

returnTRUE;

}

int main(int argc,char *argv[])

{

GtkWidget *window;

gtk_init(&argc, &argv);

window = gtk_window_new(GTK_WINDOW_TOPLEVEL);

gtk_widget_add_events (window, GDK_BUTTON_PRESS_MASK);

g_signal_connect(window,"expose-event",

G_CALLBACK(on_expose_event), NULL);

g_signal_connect(window,"destroy",

G_CALLBACK(gtk_main_quit), NULL);

gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);

gtk_window_set_title(GTK_WINDOW(window),"star");

gtk_window_set_default_size(GTK_WINDOW(window), 400, 300);

gtk_widget_set_app_paintable(window, TRUE);

g_timeout_add(10, (GSourceFunc) time_handler, (gpointer) window);

gtk_widget_show_all(window);

gtk_main();

return0;

}

在這個示例中,畫了一顆星星,然後平移它,旋轉它,縮放它。

cairo_translate(cr, width / 2, height / 2 );

cairo_rotate(cr, angle);

cairo_scale(cr, scale, scale

先将星星平移到視窗中間,旋轉它,縮放它。(作者還真不是一般的羅嗦)

for

( i = 0; i < 10; i++ ) {

cairo_line_to(cr, points[i][0], points[i][1]);

}

cairo_close_path(cr);

cairo_fill(cr);

cairo_stroke(cr);

畫它!

if

( scale < 0.01 ) {

delta = -delta;

}

else

if

(scale > 0.99) {

delta = -delta;

}

這幾行代碼控制星星的縮放過程。

轉自    http://blog.csdn.net/haiwil/article/details/6771768

繼續閱讀