一个图形上下文,或者GC(GraphicsContext),是一套在绘图时要用到的参数(比如颜色、剪裁屏蔽值、字体等等)。它是一种服务器端资 源,就像pixmap和窗口一样。GC减少了Gdk绘图函数的参数个数,也减少了每个绘图请求从客户到服务器间传递的参数的数目。
与GdkWindowAttr类似,图形上下文可以用GdkGCValues结构创建。结构中包含了图形上下文中所有的特性,还可以传递 gdk_gc_new_with_values()标志指出哪一个成员是有效的。其他的成员保留其缺省值。还可以用gdk_gc_new()函数(这种方 法通常更容易)创建一个全为缺省值的GC。创建GC之后,还有一些函数用来改变GC的设置,但是要记住,每次改变GC设置值都需要一条消息传递到X服务 器。
所有的GC都是不可以互换的,它们都与特定的深度和视件相关联。GC的深度和视 件必须与要绘图的可绘区的深度和视件相匹配。GC的深度和视件是从传递到gdk_gc_new()函数的GdkWindow*参数中获得的,所以处理这种 问题的最容易的方法就是在要绘图的窗口上创建GC。
下面是GdkGCValues结构的定义:
typedefstruct_GdkGCValuesGdkGCValues;
struct_GdkGCValues
{
GdkColorforeground;
GdkColorbackground;
GdkFont*font;
GdkFunctionfunction;
GdkFillfill;
GdkPixmap*tile;
GdkPixmap*stipple;
GdkPixmap*clip_mask;
GdkSubwindowModesubwindow_mode;
gintts_x_origin;
gintts_y_origin;
gintclip_x_origin;
gintclip_y_origin;
gintgraphics_exposures;
gintline_width;
GdkLineStyleline_style;
GdkCapStylecap_style;
GdkJoinStylejoin_style;
};
前景色(foreground成员)是画线、圆或其他形状时的“画笔颜色”。背景色(background成员)的用处依赖于特定的绘画操作。这些颜色必须是用gdk_color_alloc()函数在当前颜色表中分配的。
font成员没有用到:在Xlib中绘制文本时用它指定字体。在Gdk以前的版本中,它也有同样的作用;但是新的绘制文本的Gdk程序都要求一个 GdkFont*参数。一个Xlib图形上下文只能存储无格式的字体,但是GdkFont能够代表一个字体集(用以绘制一些外语文字)。
function成员指定要画的像素点与可绘区上已有的像素点如何结合起来。有许多种可能取值,但是只有两种是最常用的:
GDK_COPY:缺省值。它忽略已存在的像素点(只是将新的像素点画在上面)。
GDK_XOR:将旧的和新的像素点一种可反转的方式结合起来。也就是,如果执行两次GDK_OR操作,头一次绘图就会被第二次操作取消。GDK_XOR通常用于“擦除”,可以恢复可绘区原来内容。
GdkGCValues的fill成员决定如何使用GdkGCValues中的tile和stipple成员。其中tile成员是一个与目的可绘区深度 相同的pixmap图片,它被反复复制到目的可绘区,将它们拼贴起来—第一次拼贴的原点是(ts_x_origin,ts_y_origin)。而 stipple成员是一个位图(深度为1的pixmap);它也是从(ts_x_origin,ts_y_origin)开始拼贴的。下面是fill的可 能取值:
GDK_SOLID:忽略tile和stipple成员。绘图形状是用前景色和背景色绘制的。
GDK_TILED:绘图形状用tile成员指定的pixmap图片绘制,而不是用前景色和背景色。用GDK_TILED模式绘画会擦除可绘区上的任何内容,显示由tile成员指定的图片的拼贴图形。
GDK_STIPPLED:用stipple中定义的位绘制图形。也就是,在stipple成员中未设置的位不会绘出。
GDK_OPAQUE_STIPPLED:用前景色绘制在stipple中设置的位,没有在stipple中设置的位用背景色绘制。
有些X服务器并没有有效实现上面所有的fill模式值,所以使用时可能会很慢。clip_mask成员是可选的,它是一个位图,只有在这个位图中设置了的 位才会画出。从clip_mask到可绘区的映射是由clip_x_origin和clip_y_origin值决定的,这些定义了与clip_mask 中(0,0)对应的可绘区的坐标。也可以设置一个剪裁矩形(最常用的、也是最有用的形式)或一个剪裁区域(区域就是在屏幕上的任意范围,典型情况是一个多 边形或矩形列表)。
用gdk_gc_set_clip_rectangle()设置剪裁矩形:
GdkRectangleclip_rect;
clip_rect.x=10;
clip_rect.y=20;
clip_rect.width=200;
clip_rect.height=100;
gdk_gc_set_clip_rectangle(gc,&clip_rect);
要关闭“剪裁”,将剪裁的矩形、区域或剪裁屏蔽值设置为NULL。GC的subwindow_mode只与可绘区是否为一个窗口有关。缺省设置是 GDK_CLIP_BY_CHILDREN;这意指子窗口不会被在父窗口上的绘图影响。这会造成一个假象:子窗口在父窗口的“上面”,并且子窗口是不透明 的。GDK_INCLUDE_INFERIORS在所有在“上面”的
子窗口上绘制,改写子窗口上包含的任何图形—通常不使用这种模式。如果确实在使用GDK_INCLUDE_INFERIORS模式,可能要使用GDK_XOR作为绘图函数,因为它允许恢复子窗口原先的内容。
graphics_exposures是一个布尔值,缺省是TRUE,它决定gdk_window_copy_area()是否产生expose事件。
GC的最后四个值决定怎样画线。这些值用于画线,包括未填充多边形的边框以及弧线。line_width域决定线的宽度(以像素计)。宽度为0的线称为一 条“细线”,细线是一个像素宽的线,绘制得非常快(通常使用硬件加速),但是画的具体像素依赖于所使用的X服务器。为了一致性,最好使用宽度为1的线。
line_style域可以是下面三种值:
GDK_LINE_SOLID是缺省值;一条实线。
GDK_LINE_ON_OFF_DASH用前景色画一条虚线,将虚线的off(关闭)部分空着。
GDK_LINE_DOUBLE_DASH用前景色画一条虚线,但是虚线的off(关闭)部分用背景色绘制。虚线是gdk_gc_set_dashes()指定的;GdkGCValues中并不包括这个域。gdk_gc_set_dashes()需要三个参数:
dash_list是一个虚线长度的数组。偶数号的长度是“on”(打开)部分,它们是用前景色绘制的;奇数号的长度是“off”(关闭)部分,它们不画出,或者用背景色绘制,具体绘制方法依赖于line_style。长度值不能是0,所有的值必须是正数。
dash_offset是在虚线列表中第一个像素的索引号。也就是,如果在dash_list中指定了5个on和5个off,并且dash_offset是3,绘制的线将从第3个on虚线开始。
N是在dash_list中的元素的个数。可以设置一个古怪的虚线模式,例如:
gchardash_list[]={5,5,3,3,1,1,3,3};
gdk_gc_set_dashes(gc,0,dash_list,sizeof(dash_list));
缺省的dash_list是{4,4},偏移量是0。图16-1显示了一些用GDK_LINE_DOUBLE_DASH画的虚线。图形上下文的前景色是 黑色,背景色是亮灰色。头5根线是缺省的{4,4}虚线模式,偏移量分别是0、1、2、3和4。记住,缺省值是0。图16-2显示了这5根线的放大图。最 后的一根线就是上面提到的古怪虚线模式,它的放大图显示在图16-3。
cap_style决定X怎样画线的端点(或虚线端点)。它有4种可能取值:
GDK_CAP_BUTT:是缺省值,它意味着线的端点是正方形的。
GDK_CAP_NOT_LAST:对应一个像素宽度的线,最后一个像素忽略不画。其他与GDK_CAP_BUTT一样。
GDK_CAP_ROUND:在线的端点画一个小弧线,由线的端点向两边延伸。弧线的中心是线的端点,半径是线宽的一半。对一个像素宽的线,它没有什么效果(因为没有办法画一个像素宽的弧线)。
GDK_CAP_PROJECTING:将线延伸,越过它的终点半个线宽。它对一个像素的线没有效果。
join_style参数影响画多边形或在一个函数中画多条线时,各线之间如何连接。如果把线想象成一个细长的矩形,就很容易弄清楚线之间并不是平滑 连接的。在连接的两个端点之间有一个凹槽。对这个凹槽有三种处理方法,也就是join_style的三种可能取值:
GDK_JOIN_MITER:是缺省值,在线交叉的地方画一个尖角。
GDK_JOIN_ROUND:在交叉的凹槽处画一个弧线,画一个圆形的转角。
GDK_JOIN_BEVEL:用最小的可能的形状填充凹槽,画一个平坦的转角。函数列表:GdkGC
#include<gdk/gdk.h>
GdkGC*gdk_gc_new(GdkWindow*window)
GdkGC*gdk_gc_new_with_values(GdkWindow*window,
GdkGCValues*values,
GdkGCValuesMaskvalues_mask)
voidgdk_gc_set_dashes(GdkGC*gc,
gintdash_offset,
gchardash_list,
gintn)
voidgdk_gc_unref(GdkGC*gc)