圖形上下文
一個圖形上下文,或者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)