日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

cairo填充_Cairo 图形指南 (5) —— 形状与填充

發(fā)布時(shí)間:2025/3/12 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 cairo填充_Cairo 图形指南 (5) —— 形状与填充 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

這一部分,講述一些基本的以及較為高級(jí)的形狀繪制及其純色 (solid color)、圖案 (pattern) 與漸變 (gradient) 填充方法。

基本形狀

Cairo 提供了幾個(gè)用于繪制基本形狀的函數(shù)。

#include

#include

#include

static gboolean

on_expose_event (GtkWidget * widget,

GdkEventExpose * event, gpointer data)

{

cairo_t *cr;

cr = gdk_cairo_create (widget->window);

cairo_set_source_rgb (cr, 0, 0, 0);

cairo_set_line_width (cr, 1);

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

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

cairo_stroke_preserve (cr);

cairo_set_source_rgb (cr, 1, 1, 1);

cairo_fill (cr);

cairo_set_source_rgb (cr, 0, 0, 0);

cairo_arc (cr, 330, 60, 40, 0, 2 * M_PI);

cairo_stroke_preserve (cr);

cairo_set_source_rgb (cr, 1, 1, 1);

cairo_fill (cr);

cairo_set_source_rgb (cr, 0, 0, 0);

cairo_arc (cr, 90, 160, 40, M_PI / 4, M_PI);

cairo_close_path (cr);

cairo_stroke_preserve (cr);

cairo_set_source_rgb (cr, 1, 1, 1);

cairo_fill (cr);

cairo_set_source_rgb (cr, 0, 0, 0);

cairo_translate (cr, 220, 180);

cairo_scale (cr, 1, 0.7);

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

cairo_stroke_preserve (cr);

cairo_set_source_rgb (cr, 1, 1, 1);

cairo_fill (cr);

cairo_destroy (cr);

return FALSE;

}

int

main (int argc, char *argv[])

{

GtkWidget *window;

GtkWidget *darea;

gtk_init (&argc, &argv);

window = gtk_window_new (GTK_WINDOW_TOPLEVEL);

darea = gtk_drawing_area_new ();

gtk_container_add (GTK_CONTAINER (window), darea);

g_signal_connect (darea, "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), 390, 240);

gtk_widget_show_all (window);

gtk_main ();

return 0;

}

這個(gè)示例,繪制了矩形、正方形、圓、圓弧和橢圓。

下面對(duì)關(guān)鍵代碼簡(jiǎn)單分析:

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

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

繪制矩形與正方形。正方形在 cairo 中是矩形的一種特例。

cairo_arc (cr, 330, 60, 40, 0, 2 * M_PI);

畫(huà)了一個(gè)圓,圓心為 (330, 60)px,半徑為 40px。Cairo 所謂的圓,其實(shí)是起始角為 0 度,終止角為 360 度的弧線。

cairo_scale (cr, 1, 0.7);

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

畫(huà)橢圓的方法也與畫(huà)圓類似,只是需要先設(shè)定長(zhǎng)軸與短軸的比例,在本例中為 1:0.7。

復(fù)雜的圖形

復(fù)雜的圖形是由簡(jiǎn)單的圖形拼湊出來(lái)的,譬如下面這個(gè)繪制圓角矩形的程序。

#include

#include

#include

static void

draw_round_rectangle (cairo_t * cr,

double x, double y,

double width, double height, double r)

{

cairo_move_to (cr, x + r, y);

cairo_line_to (cr, x + width - r, y);

cairo_move_to (cr, x + width, y + r);

cairo_line_to (cr, x + width, y + height - r);

cairo_move_to (cr, x + width - r, y + height);

cairo_line_to (cr, x + r, y + height);

cairo_move_to (cr, x, y + height - r);

cairo_line_to (cr, x, y + r);

cairo_arc (cr, x + r, y + r, r, M_PI, 3 * M_PI / 2.0);

cairo_arc (cr, x + width - r, y + r, r, 3 * M_PI / 2, 2 * M_PI);

cairo_arc (cr, x + width - r, y + height - r, r, 0, M_PI / 2);

cairo_arc (cr, x + r, y + height - r, r, M_PI / 2, M_PI);

}

static gboolean

on_expose_event (GtkWidget * widget,

GdkEventExpose * event, gpointer data)

{

cairo_t *cr;

int width, height;

double w, h, x, y, r;

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

x = width / 5.0;

y = height / 5.0;

w = 3 * width / 5.0;

h = 3 * height / 5.0;

r = h / 4.0;

cr = gdk_cairo_create (widget->window);

cairo_set_source_rgb (cr, 0.8, 0.4, 0);

cairo_set_line_width (cr, 6);

draw_round_rectangle (cr, x, y, w, h, r);

cairo_stroke_preserve (cr);

cairo_set_source_rgb (cr, 0.8, 0.8, 0.2);

cairo_fill (cr);

cairo_destroy (cr);

g_print ("test\n");

return FALSE;

}

static gboolean

on_configure_event (GtkWidget * widget,

GdkEventConfigure * event, gpointer data)

{

gdk_window_invalidate_rect (widget->window,

&widget->allocation,

FALSE);

return FALSE;

}

int

main (int argc, char *argv[])

{

GtkWidget *window;

GtkWidget *darea;

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

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

G_CALLBACK(on_configure_event), NULL);

gtk_window_set_position (GTK_WINDOW (window),

GTK_WIN_POS_CENTER);

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

gtk_widget_set_app_paintable (window, TRUE);

gtk_widget_show_all (window);

gtk_main ();

return 0;

}

注:因?yàn)?"The cairo graphics tutorial" 在這一部分所提供的示例程序不具代表性,因此寫(xiě)了這個(gè)程序。

該示例程序繪制了一個(gè)可跟隨窗口尺寸進(jìn)行縮放變化的圓角矩形。

自定義的 draw_round_rectangle () 函數(shù)利用 Cairo 提供的基本圖元函數(shù),利用直線段與圓弧拼湊出圓角矩形。on_configure_event () 函數(shù)用于響應(yīng)窗口尺寸變化事件,在其中調(diào)用 gdk_window_invalidate_rect () 函數(shù)讓窗口繪圖區(qū)域失效,并產(chǎn)生窗口重繪制事件(即 expose 事件)。

填充 (Fill)

雖然上一篇已經(jīng)講述了一些有關(guān)填充的知識(shí),但這里所講述的內(nèi)容是與形狀相關(guān)的。填充可分為三種類型:純色、圖案、漸變。

純色 (Solid color)

對(duì)象的顏色是采用紅 (R)、綠 (G)、藍(lán) (B) 三原色描述的,Cairo 的 RGB 取值是從 0 到 1 的雙精浮點(diǎn)數(shù)。

#include

#include

static gboolean

on_expose_event (GtkWidget * widget,

GdkEventExpose * event, gpointer data)

{

cairo_t *cr;

cr = gdk_cairo_create (widget->window);

int width, height;

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

cairo_set_source_rgb (cr, 0.5, 0.5, 1);

cairo_rectangle (cr, 20, 20, 100, 100);

cairo_fill (cr);

cairo_set_source_rgb (cr, 0.6, 0.6, 0.6);

cairo_rectangle (cr, 150, 20, 100, 100);

cairo_fill (cr);

cairo_set_source_rgb (cr, 0, 0.3, 0);

cairo_rectangle (cr, 20, 140, 100, 100);

cairo_fill (cr);

cairo_set_source_rgb (cr, 1, 0, 0.5);

cairo_rectangle (cr, 150, 140, 100, 100);

cairo_fill (cr);

cairo_destroy (cr);

return FALSE;

}

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), 270, 260);

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

gtk_widget_set_app_paintable (window, TRUE);

gtk_widget_show_all (window);

gtk_main ();

return 0;

}

該示例繪制了 4 個(gè)正方形,分別采用四種不同顏色進(jìn)行填充。這個(gè)例子,由于很簡(jiǎn)單,就不再像原作者那樣自作多情的分析了。

圖案 (Pattern)

所謂圖案填充,就是將圖片填充到形狀內(nèi)部。

#include

#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 ("blueweb.png");

surface2 = cairo_image_surface_create_from_png ("maple.png");

surface3 = cairo_image_surface_create_from_png ("crack.png");

surface4 =

cairo_image_surface_create_from_png ("chocolate.png");

}

static void

destroy_surfaces ()

{

g_print ("destroying surfaces");

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

int width, height;

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

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

cairo_pattern_set_extend (cairo_get_source (cr),

CAIRO_EXTEND_REPEAT);

cairo_rectangle (cr, 20, 20, 100, 100);

cairo_fill (cr);

cairo_set_source (cr, pattern2);

cairo_pattern_set_extend (cairo_get_source (cr),

CAIRO_EXTEND_REPEAT);

cairo_arc (cr, 200, 70, 50, 0, 2 * M_PI);

cairo_fill (cr);

cairo_set_source (cr, pattern3);

cairo_pattern_set_extend (cairo_get_source (cr),

CAIRO_EXTEND_REPEAT);

cairo_rectangle (cr, 20, 140, 100, 100);

cairo_fill (cr);

cairo_set_source (cr, pattern4);

cairo_pattern_set_extend (cairo_get_source (cr),

CAIRO_EXTEND_REPEAT);

cairo_rectangle (cr, 150, 140, 100, 100);

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

create_surfaces ();

gtk_window_set_position (GTK_WINDOW (window),

GTK_WIN_POS_CENTER);

gtk_window_set_default_size (GTK_WINDOW (window), 270, 260);

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

gtk_widget_set_app_paintable (window, TRUE);

gtk_widget_show_all (window);

gtk_main ();

destroy_surfaces ();

return 0;

}

該示例,載入 4 張圖片,分別填充至三個(gè)矩形與一個(gè)圓形內(nèi)部區(qū)域。所使用的 4 幅圖,均采用 GIMP 制作。程序中,圖片的外觀 (surface) 實(shí)在 on_expose_event () 函數(shù)中創(chuàng)建的,這并不是很妥當(dāng),因?yàn)榇翱诿看伪恢乩L時(shí),都需要從硬盤中讀取圖片。

pattern1 = cairo_pattern_create_for_surface (surface1);

由圖片外觀創(chuàng)建一個(gè)圖案。

cairo_set_source (cr, pattern1);

cairo_pattern_set_extend (cairo_get_source (cr),

CAIRO_EXTEND_REPEAT);

cairo_rectangle (cr, 20, 20, 100, 100);

cairo_fill (cr);

這里,繪制第一個(gè)矩形。cairo_set_source () 函數(shù)通知 Cairo 環(huán)境,讓它使用一份圖案作為源 (source)。圖片所形成的圖案或許并不適合于形狀,當(dāng)使用 cairo_pattern_set_extend () 函數(shù)講圖案填充模式設(shè)為 CAIRO_EXTEND_REPEAT 時(shí),可以讓圖案像瓦片那樣填充于形狀內(nèi)部。cairo_rectangle () 函數(shù)創(chuàng)建一個(gè)矩形路徑,cairo_fill () 函數(shù)將已經(jīng)準(zhǔn)備好的圖案填充到矩形路徑所構(gòu)成的封閉區(qū)域中。

漸變 (Gradient)

在計(jì)算機(jī)圖形學(xué)中,漸變是形狀由明到暗或者從一種顏色向另一種顏色的平滑過(guò)度。在 2D 繪圖與渲染程序中,漸變通常被用于創(chuàng)造多彩的背景與一些特效,比如光影的仿真。

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

pat1 = cairo_pattern_create_linear (0.0, 0.0, 350.0, 350.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, j, 0, 0,

0);

} else {

cairo_pattern_add_color_stop_rgb (pat1, j, 1, 0,

0);

}

count++;

}

cairo_rectangle (cr, 20, 20, 300, 100);

cairo_set_source (cr, pat1);

cairo_fill (cr);

pat2 = cairo_pattern_create_linear (0.0, 0.0, 350.0, 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, i, 0, 0,

0);

} else {

cairo_pattern_add_color_stop_rgb (pat2, i, 0, 0,

1);

}

count++;

}

cairo_rectangle (cr, 20, 140, 300, 100);

cairo_set_source (cr, pat2);

cairo_fill (cr);

pat3 = cairo_pattern_create_linear (20.0, 260.0, 20.0, 360.0);

cairo_pattern_add_color_stop_rgb (pat3, 0.1, 0, 0, 0);

cairo_pattern_add_color_stop_rgb (pat3, 0.5, 1, 1, 0);

cairo_pattern_add_color_stop_rgb (pat3, 0.9, 0, 0, 0);

cairo_rectangle (cr, 20, 260, 300, 100);

cairo_set_source (cr, pat3);

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 (&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), 340, 390);

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

gtk_widget_set_app_paintable (window, TRUE);

gtk_widget_show_all (window);

gtk_main ();

return 0;

}

在這一示例程序中,我們繪制了三個(gè)具有不同漸變風(fēng)格的矩形。

pat3 = cairo_pattern_create_linear (20.0, 260.0, 20.0, 360.0);

這里,創(chuàng)建了一個(gè)線性漸變圖案。參數(shù)設(shè)定了繪制漸變方向的直線,在示例中,它是一條豎線。

cairo_pattern_add_color_stop_rgb (pat3, 0.1, 0, 0, 0);

cairo_pattern_add_color_stop_rgb (pat3, 0.5, 1, 1, 0);

cairo_pattern_add_color_stop_rgb (pat3, 0.9, 0, 0, 0);

定義了漸變圖案的斷點(diǎn)。在示例中,漸變圖案表現(xiàn)為黑色與黃色的過(guò)渡。通過(guò)添加兩個(gè)黑色斷點(diǎn)和一個(gè)黃色斷點(diǎn),就可以構(gòu)成一個(gè)水平方向的漸變圖案,顏色 的變化方向則是沿豎直方向。漸變圖案從矩形的上端至下端,開(kāi)始是黑色,到 1/10 寬度時(shí),黑色便停止了,然后就是由黑色向黃色的漸變渲染;到達(dá)矩形中部時(shí),黃色達(dá)到飽和狀態(tài)。黃色斷點(diǎn)會(huì)在 9/10 寬度處終止,最后的 1/10 又是黑色。

總結(jié)

以上是生活随笔為你收集整理的cairo填充_Cairo 图形指南 (5) —— 形状与填充的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。