線や長方形など図形を描く際には、その色や模様や線の太さ、さらに
上重ねの仕方(XORなど)を細かく指定することができます。
図形のこのようなさまざまな性質はXGCValues型の構造体変数に記録、参照
され、これをグラフィックコンテキストと呼びます。
グラフィックコンテキストは同時に複数用意することができ
それぞれに異なった指定をいれておくことができます。
描画の際に使用するグラフィックコンテキストを指定することで
グラフィックコンテキストの内容を変更することなしに複数の
種類の性質の図形を描くことができます。
新たにグラフィックコンテキストを生成するにはXCreateGC()関数を 使います。
Prototype
GC XCreateGC( Display* display, Window window, unsigned long mask, XGCValues* values );windowにはルートウィンドウのWindow IDを指定すれば十分です。 この返り値はGC型のグラフィックコンテキストのIDです。 以後、このグラフィックコンテキストのIDのことを単にGCと呼びます。 後続の引数の mask と valueは本書では使用しません。
Example
これで標準設定されたGCが得られます。GC gc; gc = XCreateGC( dis, DefaultRootWindow(dis), 0, 0 );
GCの内容を変更するにはいろいろな方法があります。GCが管理している 変数はたくさんあるのでその一部だけを変更する関数を紹介します。
Prototype
XSetFunction( Display* display, GC gc, int function );
XSetForeground( Display* display, GC gc, unsigned long color );
XSetBackground( Display* display, GC gc, unsigned long color );
XSetFunction()は描画の際にxorで書くかandで書くか等の論理の設定を
します。functionの値に各論理を表す定数を指定します。
xorはGXxor、copyはGXcopyです。その他に16種類の論理があります。
XSetForeground()は図形の色を設定します。
XSetBackground()は2色の色を使う図形のもう一方の色を設定します。
他にもたくさんのGC変更関数があります。専門書を参照ください。
Example
そしてこの関数にpixel値を知りたい色の名前を文字列で渡すと そのpixel値が返ってきます。unsigned long GetColor( Display* dis, char* color_name ) { Colormap cmap; XColor near_color, true_color; cmap = DefaultColormap( dis, 0 ); XAllocNamedColor( dis, cmap, color_name, &near_color, &true_color ); return( near_color.pixel ); }
Example
色の操作については後でより詳しく解説します。XSetForeground( dis, gc, GetColor( dis, "yellow");
多くの種類がある描画関数のうち基本的なものをいくつか紹介します。 どの関数も引数にDisplayポインタとWindow IDとGCを与えます。これらの引数で どの画面のどの窓にどのように描くかを指定します。
一つの点
void XDrawPoint( Display* display, Window window, GC gc, int x, int y );(x,y)に点を描きます。
複数の点
void XDrawPoints( Display* display, Window window, GC gc, XPoint* points, int num, int mode );XPoint型の構造体は下記のように定義されています。
typedef struct {numの値は描く点の数、modeの値が CoordModeOrigin なら絶対座標で 点を描き、modeの値が CoordModePrevious なら前の点からの相対座標で 点を描きます。
short x, y;
} XPoint;
一本の線分
void XDrawLine( Display* display, Window window, GC gc, int xs, int ys, int xe, int ye );(xs,ys)-(xe,ye)に直線を引きます。
連続直線
void XDrawLines( Display* display, Window window, GC gc, XPoint* points, int num, int mode );points,num,modeはXDrawPoints()と同じでそれらの点を線で結びます。
複数の線分
void XDrawSegments( Display* display, Window window, GC gc, XSegment* segments, int num );XSegment型の構造体は下記のように定義されています。
typedef struct {short x1, y1, x2, y2; } XSegment;
一つの長方形の境界線
void XDrawRectangle( Display* display, Window window, GC gc, int xo, int yo, unsigned int width, unsigned int height );(xo,yo)を左上隅の座標とし横 width 縦 height の長方形を描きます。
複数の長方形の境界線
void XDrawRectangles( Display* display, Window window, GC gc, XRectangle* rectangles, int num );XRectangle型の構造体は下記のように定義されています。
typedef struct {
short x, y;
unsigned short width, height;
} XRectangle;
一つの長方形を塗り潰す
void XFillRectangle( Display* display, Window window, GC gc, int xo, int yo, unsigned int width, unsigned int height );
複数の長方形を塗り潰す
void XFillRectangles( Display* display, Window window, GC gc, XRectangle* rectangles, int num );
一つの円弧
void XDrawArc( Display* display, Window window, GC gc, int xo, int yo, unsigned int width, unsigned int height, int start_angle, int draw_angle );(xo,yo)を左上隅の座標とし横 width 縦 height の長方形にぴったり 収まる楕円弧で、開始角度がx軸より左周りstart_angle/64度で左回り にdraw_angle/64度だけの楕円弧を描きます。
複数の円弧
void XDrawArcs( Display* display, Window window, GC gc, XArc* arcs, int num );XArc型の構造体は下記のように定義されています。
typedef struct { short x, y; unsigned short width, height; short angle1, angle2; } XArc;
円弧を塗り潰す
void XFillArc( Display* display, Window window, GC gc, int xo, int yo, unsigned int width, unsigned int height, int start_angle, int draw_angle );複数の円弧を塗り潰す
void XFillArcs( Display* display, Window window, GC gc, XArc* arcs, int num );
void XFillPolygon( Display* display, Window window, GC gc, XPoint* points, int num, int shape, int mode );shapeの値は凸多角形の時はConvexにしてください。 そうでない時やわからない時はComplexにしてください。
diamond.ccの内容
/* diamond.cc */ #include <X11/Xlib.h> #include <X11/Xutil.h> #include <stdio.h> #include <math.h> #define N 16 unsigned long GetColor( Display* dis, char* color_name ) { Colormap cmap; XColor near_color, true_color; cmap = DefaultColormap( dis, 0 ); XAllocNamedColor( dis, cmap, color_name, &near_color, &true_color ); return( near_color.pixel ); } int main( void ) { Display* dis; Window win; XSetWindowAttributes att; GC gc; XEvent ev; int x[N],y[N]; int i,j; dis = XOpenDisplay( NULL ); win = XCreateSimpleWindow( dis, RootWindow(dis,0), 100, 100, 256, 256, 5, WhitePixel(dis,0), BlackPixel(dis,0) ); att.backing_store = WhenMapped; XChangeWindowAttributes( dis, win, CWBackingStore, &att ); XSelectInput( dis, win, ExposureMask ); XMapWindow( dis, win ); do{ XNextEvent( dis, &ev); }while( ev.type != Expose ); gc = XCreateGC( dis, DefaultRootWindow(dis), 0, 0 ); XSetForeground( dis, gc, GetColor( dis, "green") ); for( i=0 ; i<N ; i++ ){ x[i] = (int)(128*cos(2*M_PI*i/N))+128; y[i] = (int)(128*sin(2*M_PI*i/N))+128; } for( i=0 ; i<N ; i++ ){ for( j=i+1 ; j<N ; j++ ){ XDrawLine( dis, win, gc, x[i], y[i], x[j], y[j] ); } } XFlush( dis ); printf("Push return key."); getchar(); XDestroyWindow( dis , win ); XCloseDisplay( dis ); return(0); }
これで緑色でダイアモンドパターンが描かれます。