demonelf 发表于 2013-8-22 20:03:23

GNOME 平台的2D图形编程(GTK,GDK,Cairo...) 简介

1、用到的库重要 是
GDK的函数库 http://library.gnome.org/devel/gdk/stable/
和cairo库 http://cairographics.org/documentation/

GTK+ 底层本身也就是用的cairo了。
根本 的画图 点,线、弧 、多变形都可以在上面说的两个库内里找到
比如 gdk_draw_line    等函数。。。

2、GdkPixbuf 就是一个Bitmap 的封装类,很多 画图操纵都要通过它,

(1)从文件加载 png jpeg可能bmp图形。比拟 好的是支持 多种技俩的。
    GdkPixbuf * widebright_png = gdk_pixbuf_new_from_file ("widebright.png",&error);
      生涯到文件
   gdk_pixbuf_save(pixbuf, "screenshot.jpg", "jpeg", NULL, "quality", "100",NULL);   

(2) 把 GdkPixbuf 内里图形信息绘制到表现窗体,
gdk_draw_pixbuf ((GdkDrawable *) gdk_window,
                                 gc,
                              pixbuf,
                              0,
                              0,
                              0,
                              0,
                              w,
                              h,
                              GDK_RGB_DITHER_NONE                         ,
                               1,
                               1);

(3) 获取窗体上面的 图形到GdkPixbuf

GdkPixbuf * pixbuf = gdk_pixbuf_get_from_drawable(NULL, root_window, NULL,
                   0, 0, 0, 0, w, h); // 抓图

3、GtkWindow 到 GdkWindow 。由于图形操纵都是通过 GdkWindow 来举办的,以是常常要从Gtk控件的到它的GdkWindow,手法举办画图操纵。
着实 就是通过GtkWidget结构的window成员

   GdkWindow * gdk_window =GTK_WIDGET( window)->window;



4。 抓屏

   这个很大略 ,获取到root窗体的 GdkWindow 就可以用上面的办法来操纵了。
GdkScreen *screen = gdk_screen_get_default();
//GdkWindow * rootWindow =gdk_screen_get_root_window(screen);
GdkWindow * root_window = gdk_get_default_root_window (); //这个和上面谁人函数一样的
if (!root_window )
{   
return TRUE;
}

int w = gdk_screen_get_width(screen);
int h = gdk_screen_get_height(screen);


5。 绘制

可以本身处理赏罚 expose_event signal动静, 着实 就相等于 windows平台的WM_PAINT动静
假如在其他地方 绘制图形,又想有靠山缓存的话,可以调用这两个函数
gdk_window_begin_paint_rect ((GdkDrawable *)gdk_window,&rect);

gdk_window_end_paint ((GdkDrawable *)gdk_window);


6、cairo 库绘制的话也很利便
直策应用 gdk_cairo_create 来从 GdkWindow来得到一个 cairo_t 画图环境 就可以画图 了,
cairo_t *         gdk_cairo_create                  (GdkDrawable *drawable);
void                gdk_cairo_set_source_color          (cairo_t *cr,
                                                         const GdkColor *color);
void                gdk_cairo_set_source_pixbuf         (cairo_t *cr,
                                                         const GdkPixbuf *pixbuf,
                                                         double pixbuf_x,



gdk_cairo_set_source_pixbuf 可以把GdkPixbuf 内里图形传到 cairo画图外貌上去。
cairo风趣的地方 是他可以设置 mask 蒙版,尚有 “线性渐变” “径状辐射渐变”等,可以发生半透明的含混效果了。
不外的对象,蒙版也都是不错的。 还可以利便的设置 alpha通道举办半透明绘制等。


下面的是七零八落的一个例子,看懂了一样平常的画图都不成题目了,哈哈,忘怀了的时间还可以来看一下。
===========================================
GdkWindow * gdk_window = window->window;   

// GdkScreen *screen1 = gdk_screen_get_default();   
// GdkColormap * colormap = gdk_screen_get_rgba_colormap(screen1);
// gtk_widget_set_colormap(window, colormap);
   
   cairo_t *cr2 = gdk_cairo_create(gdk_window);

//gdk_pixbuf_new_from_file行动 手法生涯 alpha通道的透明信息,
//cairo_image_surface_create_from_png 好像 不可
GError * error =NULL;
GdkPixbuf * widebright_png = gdk_pixbuf_new_from_file ("widebright.png",&error);
                                          
   
   cairo_surface_t *image = cairo_image_surface_create_from_png("Screenshot.png");             // cairo函数读取png文件
   cairo_surface_t *icon = cairo_image_surface_create_from_png("widebrigh.png");             // cairo函数读取png文件

   cairo_t *cr = cairo_create(image);

   
///默认是CAIRO_OPERATOR_OVER   draw source layer on top of destination layer (bounded)
cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);       //replace destination layer (bounded)
cairo_set_operator(cr2, CAIRO_OPERATOR_SOURCE);       //replace destination layer (bounded)


cairo_pattern_t *linpat, *radpat;
linpat = cairo_pattern_create_linear (0, 0, 0, 100);
cairo_pattern_add_color_stop_rgb (linpat, 0, 0, 0.8, 0.8);
cairo_pattern_add_color_stop_rgb (linpat, 100, 0.8, 0.8, 0.0);

radpat = cairo_pattern_create_radial (100,100, 0, 100, 100, 100);
cairo_pattern_add_color_stop_rgba (radpat, 0, 0, 0, 0, 1);
cairo_pattern_add_color_stop_rgba (radpat, 100, 0, 0, 0, 0);

//cairo_set_source (cr, linpat);


   
GdkGC * gc = gdk_gc_new ( (GdkDrawable *) gdk_window);
if (!gc)   {
    gtk_label_set_text(label_message,"error");
   return TRUE;
}


GdkColor color;
      color.red = 0;
      color.green = 0;
      color.blue = 30000;
gdk_gc_set_rgb_bg_color(gc , &color);
gdk_gc_set_rgb_fg_color(gc , &color);

GdkScreen *screen = gdk_screen_get_default();
//GdkWindow * rootWindow =gdk_screen_get_root_window(screen);
GdkWindow * root_window = gdk_get_default_root_window (); //这个和上面谁人函数一样的
if (!root_window )
{   
return TRUE;
}

int w = gdk_screen_get_width(screen);
int h = gdk_screen_get_height(screen);

GdkPixbuf * pixbuf = gdk_pixbuf_get_from_drawable(NULL, root_window, NULL,
                   0, 0, 0, 0, w, h); // 抓图
//gdk_pixbuf_save(pixbuf, "screenshot.jpg", "jpeg", NULL, "quality", "100",
//                            NULL);      // 将图片存为jpg技俩


GdkRectangle rect;
rect.x =0;
rect.y =0;
rect.width = w;
rect.height =h;
//文档说调用这个会预备好 靠山缓冲区,画图时不闪烁。gdk_window_end_paint后图形就一次性表现
//不调用这个画图时就一步一步的来,立刻表现在屏幕上
//gdk_window_begin_paint_rect ((GdkDrawable *)gdk_window,&rect);   


/*
typedef enum
{
GDK_RGB_DITHER_NONE,
GDK_RGB_DITHER_NORMAL,
GDK_RGB_DITHER_MAX
} GdkRgbDither;
*/

//直接调用gdk_draw_drawable () 从 root_window 到 gdk_window的复制不可,
//也许必要 转换成RGB(A)放到GdkPixbuf 内里才行吧
/*
gdk_draw_pixbuf ((GdkDrawable *) gdk_window,
                                 gc,
                              pixbuf,
                              0,
                              0,
                              0,
                              0,
                              w,
                              h,
                              GDK_RGB_DITHER_NONE                         ,
                               1,
                               1);
*/

gdk_cairo_set_source_pixbuf(cr ,pixbuf,0,0);
cairo_paint_with_alpha (cr, 0.65);

gdk_cairo_set_source_pixbuf(cr ,widebright_png,0,0);
cairo_paint_with_alpha (cr, 0.5);

cairo_mask (cr, radpat);
                  
cairo_set_source_surface(cr2, image, 0, 0);
cairo_paint(cr2);


cairo_destroy(cr2);
cairo_destroy(cr);


g_object_unref(pixbuf);   // pixbuf是gdk_pixbuf_get_from_drawable新创建 的,要开释


//gdk_draw_rectangle((GdkDrawable *) gdk_window, gc ,
//                TRUE , 0 , 0 ,
//            500 ,
//               500);


//gdk_window_end_paint ((GdkDrawable *)gdk_window);
//gdk_window_invalidate_rect (gdk_window,&rect,FALSE);
//gdk_window_clear (gdk_window);
g_object_unref(gc);

   
return TRUE;

========================================


上面代码 绘制出来的就是半透明 的图形叠加等效果了,像下面如许。
页: [1]
查看完整版本: GNOME 平台的2D图形编程(GTK,GDK,Cairo...) 简介