Index:
颜色
Graphics Context
Graphics
Image
例
--------------------------------------------------------------------------------
1. 颜色
在 X Window 视窗系统,程式使用颜色都是透过配置 color cell。 color cell 存放着颜色的 RGB 色值,即绘图时显示器上所显示出来 的色值。在我们使用某种颜色之前,必需先配置一个正确的 cell, 使用该 cell 做为绘图时的参数。当 server 将图形输出到显示器时 ,显示器(显示卡)会取出 cell 内所设定之 RGB 值,输出到画面。 RGB 即光学三元色红、绿、蓝,经由三元色的比例不同,可以得到不 同的颜色。
color cells 分成两种,read-only cell 和 read/write cell。 read-only cell 只能被使用,不能被应用程式修改,但是由各个应用 程式之间一起分享,共同使用。read/write cell 被配置(allocate) 之後可以修改其 RGB 值,但一般是不在各应用程式之间分享,是私有 的。
colormap 是 color cell 的集合。每个 client 都可以有自己的 colormap,所以同时可能会有多个 colormap 存在。而系统在同一 时间内,只安装一个 colormap 到显示器上(有些硬容许同时安装多 个 colormap),所以当一个视窗能显示正确的颜色时,其它视窗的颜色 可能会不正确。这是因为不同的 colormap,其 cell 和 RGB 值的对 应可能不同,所以当 server 把某个视窗的 colormap 安装到硬体上 时,其它视窗内的 cell 和 RGB 的对映,就变成新被安装的 colormap 的对映方式,导至不正确的颜色显示。也就是当 server 把某个视窗 的 colormap 安装到显示硬上时,该视窗的颜色显示就会正确。反 之,则会显示目前被安装的 colormap 的对映状况,显示不正确的颜 色。为了避免这个问题,一般建议使用预定(default)共用的 colormap ,每个视窗都使用同一个 colormap。default 的 colormap 可由 函数 XDefaultColormap 取得。
颜色是以 R、G、B 三种元色光的量值来表示,当某元色的量值越大时 ,则显示出来的颜色就越偏向该元色。Xlib 使用 XColor 记录 RGB 值。
--------------------------------------------------------------------------------
typedef struct {
unsigned long pixel; /* pixel value */
unsigned short red, green, blue; /* rgb values */
char flags; /* DoRed, DoGreen, DoBlue */
char pad;
} XColor;
--------------------------------------------------------------------------------
red、green、blue 的围从 0 到 65535。Black 用 (0,0,0) 表示, White 用 (65535,65535,65535) 表示。
每个 color cell 在 colormap 上都占有一个位子,为了分别不同的 color cell,我们为每个 color cell 指定一个编号,称之为 pixel。 所以当我们需要指定一个 cell 时,我是指定其 pixel 值。pixel 是一个 long 整数,每一个 bit 我们称之为一个 plane。因此,当我 们在 colormap 上分配 x 个 plane 时,我们就是分配 2^x^ 个 cell。
cell 有分 read-only 和 read/write:read-only cell的 RGB 值是由 server 设定的,不能更改。但是可由各 client 并同使用。每当有一 个 client 配置(allocate)read-only cell,则 server 会纪录下来, 当所有配置该 cell 的 client 都释放该 cell 後,该 cell 才算真正 被释放。否则该 cell 就只能维持其原来的值不能改变,也不能被当成 read/write cell 配置。而同一个 client 多次配置同一个 cell 则视 为多次的配置,client 也必需释放该 cell 相同次数。read/write cell 则不会有初值,但却可以由 client 设定更改其 RGB 值。当 client 分 配到 read/write cell 後,虽然其它 client 也可以设定其内容 (RGB 值),但一般我们还是认为 read/write cell是属私人的,不被分 享共用的。
--------------------------------------------------------------------------------
Status XAllocColor(display, colormap, screen_in_out)
Display *display;
Colormap colormap;
XColor *screen_in_out;
colormap 指定使用的 colormap。
screen_in_out 指定和传回 colormap 内,实际的值。
--------------------------------------------------------------------------------
可配置一个 read-only cell。client 指定一个 RGB 值,XAllocColor 分配一个对映到硬体所能提供最接近该 RGB 值的 cell。RGB 值设定在 screen_in_out 的 red、green、blue,而 cell 的 pixel 值会将由 pixel 传回。硬体实际提供的 RGB 值,则经由 red、green、blue 传 回。
--------------------------------------------------------------------------------
Status XAllocColorCells(display, colormap, contig
plane_masks_return, nplanes, pixels_return,
npixels)
Display *display;
Colormap colormap;
Bool contig;
unsigned long plane_masks_return[];
unsigned int nplanes;
unsigned long pixels_return[];
unsigned int npixels;
colormap 指定使用的 colormap
contig 一个 Boolean 值,指示配置的 planes 是否必
需是连续的。
plane_mask_return
传回 plane masks 的 array。
nplanes 指定在 plane_mask_return 要传回多少个 plane
masks。
pixels_return 传回 pixel 阵列。
npixels 指定在 pixels_return 传回多少个 pixel values。
--------------------------------------------------------------------------------
分配多个 read/write cell。这些 cell 都未指定内容,分配之後, client 程式可以更改其 RGB 值。在这你必需在 nplanes 指定你要分 配几个 plane,分配到的 plane,会经由 plane_mask_return 传回。 plane_mask_return 这个阵列内的每个元素,指定了分配到的 plane 的 mask。npixels 则指定了要分配多少个 pixel,pixel 则由 pixels_return 这个阵列传回。所有分配到的 cell 的数目为 npixels * 2^nplanes^,而 cell 的 pixel 值则为 pixels_return 传回之 pixel 值和 plane mask 做 OR 运算所能产生 的所有值。如果 contig 设为 true,则所有分配到之 plane 会是相 邻连续的,也就是所有传回之 plane mask 做 OR 运算,会得到一群 设为 1 的连续 bits。
--------------------------------------------------------------------------------
XStoreColor(display, colormap, color)
Display *display;
Colormap colormap;
XColor *color;
colormap 指定 colormap。
color 指定 pixel 和 RGB 值。
--------------------------------------------------------------------------------
使用 XStoreColor 设定指定之 cell 的 RGB 值,但只限於 read/write cell。
--------------------------------------------------------------------------------
XStoreColors(display, colormap, color, ncolors)
Display *display;
Colormap colormap;
XColor color[];
int ncolor;
colormap 指定 colormap。
color 指定要设定之颜色的结构阵列。
ncolor 指定 color 阵列中有多少个设定值。
--------------------------------------------------------------------------------
XStoreColors 可以同时设定多个 color cells 的 RGB 值,但只 限於 read/write cell,read-only cell 不能更改。
--------------------------------------------------------------------------------
XFreeColors(display, colormap, pixels, npixels, planes)
Display *display;
Colormap colormap;
unsigned long pixels[];
int npixels;
unsigned long planes;
colormap 指定使用之 colormap。
pixels 指定对映到 cells 的 pixels 值的阵列。
npixels 指定 pixels 阵列中有多少个 pixel 值。
planes 指定你要释放的 planes。
--------------------------------------------------------------------------------
当你所配置到的 color cell 不再被需要时,你可以使用 XFreeColors 释放。XFreeColors 同一时间内可以释放多个 cell ,pixels 是指定要释放掉的 cell 的阵列,npixels 则指定 cell 的数目。planes 则是要释放之 planes 的 plane mask,将要释放 之所有 plane 的 mask OR 起来所得到的 mask。所释放的 pixels 为,任一指定之 pixel 和 plane mask 之部分集合做 OR 运算後,所 有可能产生的 pixel 集合。
使用颜色名称
除了使用 RGB 值之外,你可以使用颜色的名称,并取得适当的 pixel 值。
--------------------------------------------------------------------------------
status XAllocNamedColor(display, colormap, color_name,
screen_def_return, exact_def_return)
Display *display;
Colormap colormap;
char *color_name;
XColor *screen_def_return, *exact_def_return;
colormap 指定 colormap。
color_name 颜色之名称。
screen_def_return
传回硬所能提供最接近之 RGB 值。
screen_def_exact
传回精确的 RGB 值。
--------------------------------------------------------------------------------
screen_def_exact 传回的是原本正确颜色所该有的 RGB 色值,而 screen_def_return 传回的则是目前硬所能提供颜色最接近之 RGB 色值。
操作 Colormaps
除了使用预定公用的 colormap (从 parent 视窗拷贝而来的) 分配我 们需要的颜色之外,我们也可以为每个个别的视窗建立独立的 colormap,让每个视窗能独力拥有 colormap,或者是由一群视窗来 分享(share)一个 colormap。
--------------------------------------------------------------------------------
Colormap XCreateColormap(display, w, visual, alloc)
Display *display;
Window w;
Visual *visual;
int alloc;
w 指定视窗。
visual 指定一个该 screen 所提供之 visual。
alloc 指定是否要分配在 colormap 的所有 entry。
可以是 AllocNone 或 AllocAll。
--------------------------------------------------------------------------------
XCreateColormap 会传回一个在指定视窗所在的 screen 上建立之新的 colormap。visual 指定该 colormap 所提供之 visual。
我们可以随时为视窗设定新的 colormap,但是 colormap 的 visual 必需和视窗的 visual 相同。指定视窗的 colormap,我们可以透过 XSetWindowColormap:
--------------------------------------------------------------------------------
XSetWindowColormap(display, w, colormap)
Display *display;
Window w;
Colormap colormap;
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
XFreeColormap(display, colormap)
Display *display;
Colormap colormap;
colormap 要释放之 colormap。
--------------------------------------------------------------------------------
释放一个 colormap,但对於预定之 colormap 没有作用。如果要 释放之 colormap 已被使用在某个视窗上时,则 XFreeColormap 会将该视窗之 colormap 设成 None,并对该视窗产生 ColormapNotify event ( event 在後面的章节会谈到 )。
2. Graphics Context
Graphics Context 简称 GC,是存在 server 上的一种资源。GC 是用来 存放绘图时所需要的各项资讯(例如: 线的宽度和长度,前景和背景颜色 等等),在大部分的绘图功能中,都需要使用 GC 做为参数。其实,我们 可以把 GC 看做是我们在做画时的画笔,不同的画笔会产生不同的效果 。同样的,我们也可以使用不同的 GC 内容的变化,来组合达成我们所 需要的画面效果。同一个 GC 可以在不同的视窗使用,也可以在不同的 client 间使用,但是一般来说 ,并不鼓励由不同的 client 使用,因为 Xlib 会对 GC 暂存,可能会造 成同步上的问题。GC 是和 screen 结合在一起的,同时也和 depth 有关 ,只有 screen 和 depth 和 GC 和同的视窗,才可以使用该 GC。也就是 该视窗必需和 GC 是在同一个 screen,并且要有相同的 depth。
Xlib 提供 XGCValues 这个结构, 以存放 GC 的相关资讯。我们将要 设定的值,存於这个结构,同时也经由这个结构传回 GC 的内存值。
--------------------------------------------------------------------------------
/* GC attribute value mask bits */
#define GCFunction (1L<<0)
#define GCPlaneMask (1L<<1)
#define GCForeground (1L<<2)
#define GCBackground (1L<<3)
#define GCLineWidth (1L<<4)
#define GCLineStyle (1L<<5)
#define GCCapStyle (1L<<6)
#define GCJoinStyle (1L<<7)
#define GCFillStyle (1L<<8)
#define GCFillRule (1L<<9)
#define GCTile (1L<<10)
#define GCStipple (1L<<11)
#define GCTileStipXOrigin (1L<<12)
#define GCTileStipYOrigin (1L<<13)
#define GCFont (1L<<14)
#define GCSubwindowMode (1L<<15)
#define GraphicsExposures (1L<<16)
#define GCClipXOrigin (1L<<17)
#define GCClipYOrigin (1L<<18)
#define GCClipMask (1L<<19)
#define GCDashOffset (1L<<20)
#define GCDashList (1L<<21)
#define GCArcMode (1L<<22)
/* Values */
typedef struct {
int function;
unsigned long plane_mask;
unsigned long foreground;
unsigned long background;
int line_width;
int line_style;
int cap_style;
int join_style;
int fill_style;
int fill_rule;
int arc_mode;
Pixmap tile;
Pixmap stipple;
int ts_x_origin;
int ts_y_origin;
Font font;
int subwindow_mode;
Bool graphics_exposures;
int clip_x_origin;
int clip_y_origin;
Pixmap clip_mask;
int dash_offset;
char dashes;
} XGCValues;
--------------------------------------------------------------------------------
下面是 XGCValues 的栏位说明。 栏位 预设值 说明
function GXcopy Xlib 定义了 16 种 function, 用以定义各种 X 所提供的绘图形式. Xlib 提供了一些绘图函数, 当我们在一个 drawable 上绘图时, 新绘上的 图该如何和在原本位置上的图形配合呢? function 定义了 X 所提供的 16 种可能中的一种. 当我们为 GC 设好新的 function 之後, 下一次我们使用 GC 进行绘图时, 新的 function 就开始发生了作用. 下面是 Xlib 定义的 16 种 function. GXclear 把输出图素清除为 0
GXand 把输出之图与原图素做 and 运算
GXandReverse 先把原图素反相, 然後和输出图素做 and 运算
GXcopy 直接用输出图素替代原图素
GXandInverted 先将输出图素和原图素做 and 运算後, 再将结果反相
GXnoop 维持原图素
GXxor 输出图素和原图素做 xor 运算
GXor 输出图素和原图素做 or 运算
GXnor 先分别把输出图素和原图素做反相, 再将反相後的两图做 and 运算
GXequiv 先反相输出图素,然後和原图素做 xor 运算
GXinvert 把原图素反相
GXorReverse 反相原图素, 然後和输出图素做 xor 运算
GXcopyInverted 把输出图素反相当为最後结果
GXorInverted 把输出图素反相後和原图素做 or 运算
GXnand 把输出图素和原图素做反相, 然後两图做 or 运算
GXset 把输出部分全设为 1
plane_mask AllPlanes 指定会被影的 planes, 会被影的 planes 设为 1。Xlib 中定义 AllPlanes 常数, 指定所有的 planes。绘图的最後结果是:
((输出图素 function 原图素) AND plane_mask)
foreground 1 指定图形输出时的前景所使用的图素值(pixel)
background 0 指定图形输出时的背景所使用的图素值(pixel)
line_width 0 如果输出中有线条时, 线条的宽度.
line_style LineSolid 线条的样式, Xlib 定义三个常数, 代表三种样式. LineSolid 实线
LineOnOffDash 虚线
LineDoubleDash 另一种虚线
cap_style CapButt 指定线条端线点(起点和终点)的样式。 CapNotLast 和 CapButt 相似, 只是 line width 为 0 时, 不画出端点.
CapButt 方形长角的端点
CapRound 圆弧形的端点
CapProjecting 和 CapButt 相似, 但端点会再延伸 line width 的一半长度
join_style JoinMiter 折线的折点形式。 JoinMiter 角状的折点
JoinRound 图弧状的折点
JoinBevel 像是两个 CapButt 的端点重叠在一起
fill_style FillSolid 设定线段,文字,和填充画面的来源。 FillSolid 前景填满 foreground 颜色
FillTiled 以 tile 填满
FillStippled 前景以填上 foreground 但以 stipple 遮罩起来.
FillOpaqueStippled 和 FillStippled 相似, 但被遮罩的部分(stipple 内为 0 的部分) 填上 background。
fill_rule EvenOddRule 设定呼叫 XFillPolygon 时,如何定义出内部和外部。 EvenOddRule 以通过指定点的线为基准, 通过 path 奇数次的为 inside
WindingRule 通过顺时钟方向的 path 和逆时钟方向的 path 的次数如果不同 即为 inside。
arc_mode ArcPieSlice 控制 XFillArcs 如何填满圆弧。 ArcChord 以琴弦般的填满弧
ArcPieSlice 像被切开的 pie 一样的填满弧
tile 0 和 GC 有相同 root 和深度(depth)的 pixmap
stipple 0 深度(depth)为 1 的 pixmap
ts_x_origin 0 设定 tile/stipple 的原点的 x 座标
ts_y_origin 0 设定 tile/stipple 的原点的 y 座标
font Implementation dependent 字形,XLoadFont 的传回值
subwindow_mode ClipByChildren ClipByChildren
IncludeInferiors
graphics_exposures True 控制 XCopyArea 和 XCopyPlane 的 GraphicsExpose 事件(event)的产生。
clip_x_origin 0 clip_mask 的原点相对於 drawable 的位置
clip_y_origin 0 clip_mask 的原点相对於 drawable 的位置
clip_mask None clip_mask 为深度(depth)为 1 并和 GC 相同 root 的 pixmap, 做为输出的 mask
dash_offset
dashes
你可以透过 XCreateGC 建立一新的 GC:
--------------------------------------------------------------------------------
GC XCreateGC(display, d, valuemask, values)
Display *display;
Drawable d;
unsigned long valuemask;
XGCValues *values;
d 指定 drawable。
valuemask 指定使用了那些 GC 元件。这个参数是把各元件之
mask OR 起来得到的 mask,用以指定设了那些元
件。
value 指定设定的 GC 内容。
--------------------------------------------------------------------------------
呼叫 XCreateGC 後,建立一个新的 GC,并会传回 GC。所谓的 drawable 指的是一个可以使用绘图功能,在其上进行绘图的视窗或是其它 X 上的 物件。
--------------------------------------------------------------------------------
XFreeGC(display, gc)
Display *display;
GC gc;
gc 指定要释放之 GC。
--------------------------------------------------------------------------------
释放一个己建立之 GC。
下面我们介绍一些设定 GC 的方便函数,以方便我们做 GC 设定。
--------------------------------------------------------------------------------
XSetForeground(display, gc, foreground)
Display *display;
GC gc;
usigned long foreground;
gc 指定作用对像之 GC。
foreground 指定前景颜色。
--------------------------------------------------------------------------------
设定 GC 内容的前景。当你使用该 GC 绘图时,前景颜色即为 GC 内所设的前景颜色。
--------------------------------------------------------------------------------
XSetBackground(display, gc, background)
Display *display;
GC gc;
usigned long background;
gc 指定作用对像之 GC。
background 指定背景颜色。
--------------------------------------------------------------------------------
设定 GC 的背景颜色。当你使用该 GC 绘图时,前景颜色即为 GC 内所设的前景颜色。
--------------------------------------------------------------------------------
XSetLineAttributes(display, gc, line_width, line_style,
cap_style, join_style)
Display *display;
GC gc;
unsigned int line_width;
int line_style;
int cap_style;
int join_style;
gc 指定作用对像之 GC。
line_width 线条之宽度。
line_style 线条型式,有 LineSolid、LineOnOffDash、
LineDoubleDash。
cap_style 指定线条端点之型式,有 CapNotLast、
CapButt、CapRound、CapProjecting。
join_style 指定线条转折点的型式,有 JoinMiter、
JoinRound、JoinBevel。
--------------------------------------------------------------------------------
设定线的形式。
--------------------------------------------------------------------------------
XSetFont(display, gc, font)
Display *display;
GC gc;
Font font;
gc 指定作用对像之 GC。
font 指定字型。
--------------------------------------------------------------------------------
设定字形。
--------------------------------------------------------------------------------
XSetArcMode(display, gc, arc_mode)
Display *display;
GC gc;
int arc_mode;
gc 指定作用对像之 GC。
arc_mode 指定画弧时,封口的型式,有 ArcChord、
ArcPieSlice。
--------------------------------------------------------------------------------
设定画弧时,封口的型式。
3. Graphics
Xlib 提供大量的函数,处理图形的输出。
--------------------------------------------------------------------------------
XClearWindow(display, w)
Display *display;
Window w;
--------------------------------------------------------------------------------
清除视窗。
--------------------------------------------------------------------------------
XDrawPoint(display, d, gc, x, y)
Display *display;
Drawable d;
GC gc;
int x, y;
d 指定 drawable。
gc 指定要使用之 GC。
x, y 指定画点的座标。
--------------------------------------------------------------------------------
在视窗上画一点。
--------------------------------------------------------------------------------
XDrawLine(display, d, gc, x1, y1, x2, y2)
Display *display;
Drawable d;
GC gc;
int x1, y1, x2, y2;
d 指定目的 drawable。
gc 指定使用之 GC。
x1, y1, x2, y2 指定线的两端点座标。
--------------------------------------------------------------------------------
在视窗上画一条线。
--------------------------------------------------------------------------------
XDrawRectangle(display, d, gc, x, y, width, height)
Display *display;
Drawable d;
GC gc;
int x, y;
unsigned int width, height;
x, y 指定矩形的左上角座标。
width, height 指定矩形的大小。
--------------------------------------------------------------------------------
在视窗上画一个矩形。
--------------------------------------------------------------------------------
XDrawArc(display, d, gc, x, y, width, height, angle1,
angle2)
Display *display;
Drawable d;
GC gc;
int x, y;
unsigned int width, height;
int angle1, angle2;
x, y 指定弧的中心点(原点)。
width, height 指定弧的 x 轴和 y 轴的比例。
angle1, angle2 弧的起始角度和结止角度。
--------------------------------------------------------------------------------
在视窗上画一个弧形。
--------------------------------------------------------------------------------
XFillRectangle(display, d, gc, x, y, width, height)
Display *display;
Drawable d;
GC gc;
int x, y;
unsigned int width, height;
--------------------------------------------------------------------------------
在视窗上画一个填满颜色的矩形。
--------------------------------------------------------------------------------
XFillArc(display, d, gc, x, y, width, height, angle1,
angle2)
Display *display;
Drawable d;
GC gc;
int x, y;
unsigned int width, height;
int angle1, angle2;
--------------------------------------------------------------------------------
在视窗上画一个填满颜色的弧形。
--------------------------------------------------------------------------------
Font XLoadFont(display, name)
Display *display;
char *name;
name 指定字形名称。
--------------------------------------------------------------------------------
载入字形,当我要在视窗上显示某一字形时,我们必需先载入字形, 然後才能使用。使用这个函数之後,会传回一个 Font 的 ID,这 就是我们在使用 XSetFont 函数设定 GC 所要传入的参数之一。 当我们使用传回来的 Font 设定 GC 後,就可以使用该 GC 当做 参数在萤幕上显示该字形的字串。
--------------------------------------------------------------------------------
XUnloadFont(display, font)
Display *display;
Font font;
font 指定要 unload 的字形。
--------------------------------------------------------------------------------
移除字形。当我们不再使用一字形时,我们必需将之移除。
--------------------------------------------------------------------------------
XDrawString(display, d, gc, x, y, string, lengtth)
Display *display;
Drawable d;
GC gc;
int x, y;
char *string;
int length;
gc 画字时所要用的 GC。
x, y 指定字串显示的座标。
string 要显示的字串。
length 字串的长度。
--------------------------------------------------------------------------------
在萤幕上显示一字串。
--------------------------------------------------------------------------------
XDrawString16(display, d, gc, x, y, string, length)
Display *display;
Drawable d;
GC gc;
int x, y;
XChar2b *string;
int length;
gc 指定使用之 GC。
x, y 指定字串显示的座标。
string 指定显示之字串。
length 指定字串内有多少个字。
--------------------------------------------------------------------------------
在萤幕上显示一双位元组(或 16bits)的字串。X Window 有支援双位元组 字集,用以显示双位元组的语言(如中文等)。双位元组的字元是以 XChar2b 这个 structure 来表示:
typedef struct {
unsigned char byte1;
unsigned char byte2;
} XChar2b;
byte1 存放的是双位元组字元的高位元组(MSB:most significant byte) ,byte2 存放的则是低位元组(LSB:least significant byte)。一个双 位元组的字串就是 XChar2b 的阵列。
4. Image
在 GUI 介面下, 常会需要将一张图片直接 show 在视窗上, 像是 show 照片. Xlib 提供一些可以直接在 client 和 server 间传送影像(image)的函数, 以直接处理一张张的影像, 例如, 图形档. 在这提到的 image 相关函数, 都会使用 XImage 结构做为函数的输入参数. Xlib 在 client 端使用 XImage 描述影像资料, 当你要使用 Xlib 的函数处理影像资料时, 必需透过 XImage 进行操作. XImage 提供一个物件化的介面, 透过物件提供的函数, 我们可以相同的方式, 处理不同的影像资料.
--------------------------------------------------------------------------------
/*
* Data structure for "image" data, used by image manipulation routines.
*/
typedef struct _XImage {
int width, height; /* size of image */
int xoffset; /* number of pixels offset in X direction */
int format; /* XYBitmap, XYPixmap, ZPixmap */
char *data; /* pointer to image data */
int byte_order; /* data byte order, LSBFirst, MSBFirst */
int bitmap_unit; /* quant. of scanline 8, 16, 32 */
int bitmap_bit_order; /* LSBFirst, MSBFirst */
int bitmap_pad; /* 8, 16, 32 either XY or ZPixmap */
int depth; /* depth of image */
int bytes_per_line; /* accelarator to next line */
int bits_per_pixel; /* bits per pixel (ZPixmap) */
unsigned long red_mask; /* bits in z arrangment */
unsigned long green_mask;
unsigned long blue_mask;
XPointer obdata; /* hook for the object routines to hang on */
struct funcs { /* image manipulation routines */
struct _XImage *(*create_image)();
#if NeedFunctionPrototypes
int (*destroy_image) (struct _XImage *);
unsigned long (*get_pixel) (struct _XImage *, int, int);
int (*put_pixel) (struct _XImage *, int, int, unsigned long);
struct _XImage *(*sub_image)(struct _XImage *, int, int, unsigned int, unsigned int);
int (*add_pixel) (struct _XImage *, long);
#else
int (*destroy_image)();
unsigned long (*get_pixel)();
int (*put_pixel)();
struct _XImage *(*sub_image)();
int (*add_pixel)();
#endif
} f;
} XImage;
--------------------------------------------------------------------------------
XImage 可以建过 XInitImage 和 XCreateImage 建立. 建立之後的 object, 可以使用 XGetPixel, XPutPixel, XSubImage 和 XAddPixel 读取和修改内容. 使用 XPutImage 输出到 drawable (视窗或 pixmap), 使用 XGetImage 从 drawable 读取. object 最後必需使用 XDestroyImage 释放.
--------------------------------------------------------------------------------
Status XInitImage(image)
XImage *image;
--------------------------------------------------------------------------------
XImage 在使用之前, 必需先经过 XInitImage 进行 initialize. 在呼叫 XInitImage 之前, 除了 manipulate functions 之外, 其它的栏位都必需 先设定好. 成功的话, 传回非0值, 否则传回 0.
--------------------------------------------------------------------------------
XImage *XCreateImage(display, visual, depth, format, off-
set, data, width, height, bitmap_pad,
bytes_per_line)
Display *display;
Visual *visual;
unsigned int depth;
int format;
int offset;
char *data;
unsigned int width;
unsigned int height;
int bitmap_pad;
int bytes_per_line;
--------------------------------------------------------------------------------
XCreateImage 会为输入之影像资料产生一个 XImage 结构, 并传回结构. 是一个包装 XInitImage 的函数. 'format' 指定影像储存的形式, 有 ZPixmap, XYPixmap 和 XYBitmap. ZPixmap 的储存方式是一个 pixel 接 着一个 pixel 存放. XYPixmap 则是 plane 接着 plane, 将所有 pixel 特定 plane 的内容集成 bitmap, 然後依 plane 的顺序储存各 plane 形式的 bitmap. XYBitmap 和 XYPixmap 一样, 但是 XYBitmap只有一个 plane. 而, 影像的内容则存在 data 所指定的 memory block . 使用者必需指定一块记忆(data)以储存影像, XCreateImage 并不会主动为您配置. data 的大小和 image 的大小和深度(depth)有关, format 也会影响. 下面是 data 大小和 bytes_per_line 的计算公式.
format size of data bytes_per_line
ZPixmap width * height * ((depth + 7) / 8) width * ((depth + 7) / 8)
XYPixmap ((width + 7) / 8) * height * depth (width + 7) / 8
XYBitmap ((width + 7) / 8) * height * 1 (width + 7) / 8
--------------------------------------------------------------------------------
unsigned long XGetPixel(ximage, x, y)
XImage *ximage;
int x;
int y;
--------------------------------------------------------------------------------
取得影像内的一个图点.
--------------------------------------------------------------------------------
XPutPixel(ximage, x, y, pixel)
XImage *ximage;
int x;
int y;
unsigned long pixel;
--------------------------------------------------------------------------------
在影像上放上一个点.
--------------------------------------------------------------------------------
XImage *XSubImage(ximage, x, y, subimage_width,
subimage_height)
XImage *ximage;
int x;
int y;
unsigned int subimage_width;
unsigned int subimage_height;
--------------------------------------------------------------------------------
读取影像的一部分内容, 并传回 XImage. x, y, subimage_width, 和 subimage_height 指定 image 内的一个方框的位置和大小, 读 取方框内的资料.
--------------------------------------------------------------------------------
XAddPixel(ximage, value)
XImage *ximage;
long value;
--------------------------------------------------------------------------------
把 image 内每个点的 pixel 值都加上指定的 valuex.
--------------------------------------------------------------------------------
XDestroyImage(ximage)
XImage *ximage;
--------------------------------------------------------------------------------
由上面和下面各函数所产生的 XImage 物件, 最後不用时, 都要使用 XDestroyImage 释放掉。注意, XDestroyImage 会主动将 data 释放
--------------------------------------------------------------------------------
XPutImage(display, d, gc, image, src_x, src_y, dest_x,
dest_y, width, height)
Display *display;
Drawable d;
GC gc;
XImage *image;
int src_x, src_y;
int dest_x, dest_y;
unsigned int width, height;
--------------------------------------------------------------------------------
将 image 输出 'd' 所指定的 drawable.
--------------------------------------------------------------------------------
XImage *XGetImage(display, d, x, y, width, height,
plane_mask, format)
Display *display;
Drawable d;
int x, y;
unsigned int width, height;
unsigned long plane_mask;
int format;
--------------------------------------------------------------------------------
读取 'd' 所指定之 drawable 的影像. 'plane_mask' 指定要读取的 planes. 若指定的 planes, 为 drawable 所有 planes 的 subset, 那麽传回的 image 的 depth 将和指定的 planes 数目相同.
--------------------------------------------------------------------------------
XImage *XGetSubImage(display, d, x, y, width, height,
plane_mask, format, dest_image, dest_x,
dest_y)
Display *display;
Drawable d;
int x, y;
unsigned int width, height;
unsigned long plane_mask;
int format;
XImage *dest_image;
int dest_x, dest_y;
--------------------------------------------------------------------------------
下面是处理影像的例.
--------------------------------------------------------------------------------
/* -- Image-test.c -- */
#include
#include
#include
#include
#include
#include
#include "gnu.xpm"
#include "doomface.xpm"
#include "Boss2.xpm"
struct ColorElm {
char *tag;
unsigned long pixel;
};
unsigned long
get_pixel(Display *display, Colormap colormap, char *str)
{
char *cp = str;
XColor color, excolor;
if(*cp == '#') {
int j, k;
int t;
int rgbl;
unsigned short rgb[3];
cp++;
if(strlen(cp) == 6)
rgbl = 2;
else
rgbl = 4;
for(k = 0; k < 3; k++) {
t = 0;
for(j = 0; j < rgbl; j++) {
char c = *(cp++);
t <<= 4;
if(c >= 'A' && c <= 'F')
t += c - 'A' + 10;
else if(c >= 'a' && c <= 'f')
t += c - 'a' + 10;
else
t += c - '0';
}
rgb[k] = t;
}
color.red = rgb[0];
color.green = rgb[1];
color.blue = rgb[2];
color.flags = DoRed | DoGreen | DoBlue;
XAllocColor(display, colormap, &color);
} else {
char *cp;
if(strcasecmp(str, "None") == 0)
cp = "black";
else
cp = str;
XAllocNamedColor(display, colormap, cp, &color, &excolor);
}
return color.pixel;
}
/*
* 从 *.xpm 转换成 Xlib 能处理的 image 资料形式 (ZPixmap)
*/
char *
xpm_to_data(char **xpm, Display *display,
Colormap colormap, int depth, int *width, int *height)
{
int nc, el; /* # of color, and element length */
int i;
int bpp; /* byte per pixel */
struct ColorElm *ce, *cep;
unsigned short rgb[3];
XColor color;
char *data, *dp;
sscanf(*(xpm++), "%d %d %d %d", width, height, &nc, &el);
bpp = (depth + 7) / 8;
data = (char *)malloc(sizeof(char) * bpp *
*width * *height);
ce = (struct ColorElm *)malloc(sizeof(struct ColorElm) * nc);
cep = ce;
for(i = 0; i < nc; i++) {
char *cp;
cep->tag = (char *)malloc(sizeof(char) * el);
memcpy(cep->tag, *xpm, el);
cp = *xpm + el;
/*
* skip redundant character
*/
while(isspace(*cp)) cp++;
while(*(cp++) != 'c') {
while(isspace(*cp)) cp++;
while(!isspace(*cp)) cp++;
while(isspace(*cp)) cp++;
}
/*
* get pixel of color
*/
while(isspace(*cp)) cp++;
cep->pixel = get_pixel(display, colormap, cp);
cep++;
xpm++;
}
/*
* generate image data
*/
dp = data;
for(i = 0; i < *height; i++) {
int j;
char *p;
p = *(xpm++);
for(j = 0; j < *width; j++) {
int idx;
unsigned long pixel;
/*
* find pixel of point
*/
for(idx = 0; idx < nc; idx++)
if(!memcmp(p, ce[idx].tag, el)) {
memcpy(dp, &ce[idx].pixel, bpp);
break;
}
dp += bpp;
p += el;
}
}
free(ce);
return data;
}
main()
{
Display *display;
Window window;
XSetWindowAttributes attr;
Colormap colormap;
XColor color1, color2;
XGCValues gcvalue;
GC gc;
XSizeHints *sz;
XImage *img1, *img2, *img3;
int screen;
char *data; /* image data */
int w, h; /* width & height */
int bpp; /* byte per pixel */
display = XOpenDisplay("0:0");
colormap = DefaultColormap(display, screen = DefaultScreen(display));
color1.red = color1.blue = 0xffff;
color1.green = 0;
color2.red = color2.green = color2.blue = 0xff;
color1.flags = color2.flags = DoRed | DoGreen | DoBlue;
XAllocColor(display, colormap, &color1);
XAllocColor(display, colormap, &color2);
attr.background_pixel = color2.pixel;
window = XCreateWindow(display, XDefaultRootWindow(display),
100, 100, 500, 300, 2, XDefaultDepth(display, 0),
InputOutput, CopyFromParent, CWBackPixel, &attr);
XStoreName(display, window, "hello!! world!!");
sz = XAllocSizeHints();
sz->x = 100;
sz->y = 100;
sz->width = 300;
sz->height = 500;
sz->flags = USPosition | USSize;
XSetNormalHints(display, window, sz);
XMapWindow(display, window);
gc = XCreateGC(display, window, 0, &gcvalue);
XSetForeground(display, gc, color1.pixel);
XSetBackground(display, gc, color2.pixel);
XFlush(display);
printf("Show image!!\n");
bpp = (DefaultDepth(display, screen) + 7) / 8;
/*
* Create gnu.xpm
*/
data = xpm_to_data(image_name, display, colormap,
DefaultDepth(display, screen), &w, &h);
img1 = XCreateImage(display,
DefaultVisual(display, screen),
DefaultDepth(display, screen),
ZPixmap, 0, data,
w, h, 8, w * bpp);
/* (w, h) 是影像的宽和高 */
/*
* Create doomface.xpm
*/
data = xpm_to_data(xpm, display, colormap,
DefaultDepth(display, screen), &w, &h);
img2 = XCreateImage(display,
DefaultVisual(display, screen),
DefaultDepth(display, screen),
ZPixmap, 0, data,
w, h, 8, w * bpp);
/* (w, h) 是影像的宽和高 */
/*
* Create Boss2.xpm
*/
data = xpm_to_data(Boss2_xpm, display, colormap,
DefaultDepth(display, screen), &w, &h);
img3 = XCreateImage(display,
DefaultVisual(display, screen),
DefaultDepth(display, screen),
ZPixmap, 0, data,
w, h, 8, w * bpp);
/* (w, h) 是影像的宽和高 */
/*
* Show images
*/
XPutImage(display, window, gc, img1, 0, 0, 10, 10, w, h);
XPutImage(display, window, gc, img2, 0, 0, 10, 100, w, h);
XPutImage(display, window, gc, img3, 0, 0, 200, 50, w, h);
XFlush(display);
/*
* Destroy images
*/
XDestroyImage(img1);
XDestroyImage(img2);
XDestroyImage(img3);
sleep(3);
XDestroyWindow(display, window);
XFlush(display);
XCloseDisplay(display);
}
--------------------------------------------------------------------------------
执行结果
颜色和原图有些不同, 主要原因是使用 default 的 colormap. 上面的程式 在视窗显示三张 .xpm 的图形档, 分别是 gnu.xpm, doomface.xpm 和 Boss2.xpm.
5. 例
--------------------------------------------------------------------------------
/* ---- XGraph.c ---- */
#include
#include
#include
#include
main() {
Display *display;
Window window;
XSetWindowAttributes attr;
Colormap colormap;
XColor color1, color2;
XGCValues gcvalue;
GC gc;
XSizeHints *sz;
display = XOpenDisplay("0:0");
/* 取得预设之 colormap */
colormap = DefaultColormap(display,
DefaultScreen(display));
/* 取得 colorcell */
color1.red = color1.blue = 0xffff;
color1.green = 0;
color2.red = color2.green = color2.blue = 0xff;
color1.flags = color2.flags = DoRed | DoGreen | DoBlue;
XAllocColor(display, colormap, &color1);
XAllocColor(display, colormap, &color2);
/* 设定视窗的 attribute 和建设 */
attr.background_pixel = color2.pixel; /* 背景颜色 */
window = XCreateWindow(display,
XDefaultRootWindow(display), 100, 100, 300, 300,
2, XDefaultDepth(display, 0), InputOutput,
CopyFromParent, CWBackPixel, &attr);
/* 设定和 window manager 进行沟通 */
XStoreName(display, window, "hello!! world!!");
sz = XAllocSizeHints();
sz->x = 100;
sz->y = 100;
sz->width = 300;
sz->height = 300;
sz->flags = USPosition | USSize;
XSetNormalHints(display, window, sz);
/* 显示视窗 */
printf("Map window\n");
XMapWindow(display, window);
XFlush(display);
getchar();
/* 建立并设定 GC */
gc = XCreateGC(display, window, 0, &gcvalue);
XSetForeground(display, gc, color1.pixel);
XSetBackground(display, gc, color2.pixel);
/* 画一个矩形 */
printf("Draw rectangle\n");
XDrawRectangle(display, window, gc, 10, 10, 100, 100);
XFlush(display);
getchar();
/* 清除视窗 */
XClearWindow(display, window);
/* 设定 GC 内,线的形式 */
XSetLineAttributes(display, gc, 5, LineOnOffDash,
CapButt, JoinRound);
/* 画线 (200, 10) - (200, 290) */
printf("Draw line\n");
XDrawLine(display, window, gc, 200, 10, 200, 290);
XFlush(display);
getchar();
/* 关闭视窗 */
printf("Destory Window\n");
XDestroyWindow(display, window);
XFlush(display);
getchar();
printf("close display\n");
XCloseDisplay(display);
getchar();
}
--------------------------------------------------------------------------------
gcc -o XGraph XGraph.c -L/usr/X11R6/lib -lX11
颜色
Graphics Context
Graphics
Image
例
--------------------------------------------------------------------------------
1. 颜色
在 X Window 视窗系统,程式使用颜色都是透过配置 color cell。 color cell 存放着颜色的 RGB 色值,即绘图时显示器上所显示出来 的色值。在我们使用某种颜色之前,必需先配置一个正确的 cell, 使用该 cell 做为绘图时的参数。当 server 将图形输出到显示器时 ,显示器(显示卡)会取出 cell 内所设定之 RGB 值,输出到画面。 RGB 即光学三元色红、绿、蓝,经由三元色的比例不同,可以得到不 同的颜色。
color cells 分成两种,read-only cell 和 read/write cell。 read-only cell 只能被使用,不能被应用程式修改,但是由各个应用 程式之间一起分享,共同使用。read/write cell 被配置(allocate) 之後可以修改其 RGB 值,但一般是不在各应用程式之间分享,是私有 的。
colormap 是 color cell 的集合。每个 client 都可以有自己的 colormap,所以同时可能会有多个 colormap 存在。而系统在同一 时间内,只安装一个 colormap 到显示器上(有些硬容许同时安装多 个 colormap),所以当一个视窗能显示正确的颜色时,其它视窗的颜色 可能会不正确。这是因为不同的 colormap,其 cell 和 RGB 值的对 应可能不同,所以当 server 把某个视窗的 colormap 安装到硬体上 时,其它视窗内的 cell 和 RGB 的对映,就变成新被安装的 colormap 的对映方式,导至不正确的颜色显示。也就是当 server 把某个视窗 的 colormap 安装到显示硬上时,该视窗的颜色显示就会正确。反 之,则会显示目前被安装的 colormap 的对映状况,显示不正确的颜 色。为了避免这个问题,一般建议使用预定(default)共用的 colormap ,每个视窗都使用同一个 colormap。default 的 colormap 可由 函数 XDefaultColormap 取得。
颜色是以 R、G、B 三种元色光的量值来表示,当某元色的量值越大时 ,则显示出来的颜色就越偏向该元色。Xlib 使用 XColor 记录 RGB 值。
--------------------------------------------------------------------------------
typedef struct {
unsigned long pixel; /* pixel value */
unsigned short red, green, blue; /* rgb values */
char flags; /* DoRed, DoGreen, DoBlue */
char pad;
} XColor;
--------------------------------------------------------------------------------
red、green、blue 的围从 0 到 65535。Black 用 (0,0,0) 表示, White 用 (65535,65535,65535) 表示。
每个 color cell 在 colormap 上都占有一个位子,为了分别不同的 color cell,我们为每个 color cell 指定一个编号,称之为 pixel。 所以当我们需要指定一个 cell 时,我是指定其 pixel 值。pixel 是一个 long 整数,每一个 bit 我们称之为一个 plane。因此,当我 们在 colormap 上分配 x 个 plane 时,我们就是分配 2^x^ 个 cell。
cell 有分 read-only 和 read/write:read-only cell的 RGB 值是由 server 设定的,不能更改。但是可由各 client 并同使用。每当有一 个 client 配置(allocate)read-only cell,则 server 会纪录下来, 当所有配置该 cell 的 client 都释放该 cell 後,该 cell 才算真正 被释放。否则该 cell 就只能维持其原来的值不能改变,也不能被当成 read/write cell 配置。而同一个 client 多次配置同一个 cell 则视 为多次的配置,client 也必需释放该 cell 相同次数。read/write cell 则不会有初值,但却可以由 client 设定更改其 RGB 值。当 client 分 配到 read/write cell 後,虽然其它 client 也可以设定其内容 (RGB 值),但一般我们还是认为 read/write cell是属私人的,不被分 享共用的。
--------------------------------------------------------------------------------
Status XAllocColor(display, colormap, screen_in_out)
Display *display;
Colormap colormap;
XColor *screen_in_out;
colormap 指定使用的 colormap。
screen_in_out 指定和传回 colormap 内,实际的值。
--------------------------------------------------------------------------------
可配置一个 read-only cell。client 指定一个 RGB 值,XAllocColor 分配一个对映到硬体所能提供最接近该 RGB 值的 cell。RGB 值设定在 screen_in_out 的 red、green、blue,而 cell 的 pixel 值会将由 pixel 传回。硬体实际提供的 RGB 值,则经由 red、green、blue 传 回。
--------------------------------------------------------------------------------
Status XAllocColorCells(display, colormap, contig
plane_masks_return, nplanes, pixels_return,
npixels)
Display *display;
Colormap colormap;
Bool contig;
unsigned long plane_masks_return[];
unsigned int nplanes;
unsigned long pixels_return[];
unsigned int npixels;
colormap 指定使用的 colormap
contig 一个 Boolean 值,指示配置的 planes 是否必
需是连续的。
plane_mask_return
传回 plane masks 的 array。
nplanes 指定在 plane_mask_return 要传回多少个 plane
masks。
pixels_return 传回 pixel 阵列。
npixels 指定在 pixels_return 传回多少个 pixel values。
--------------------------------------------------------------------------------
分配多个 read/write cell。这些 cell 都未指定内容,分配之後, client 程式可以更改其 RGB 值。在这你必需在 nplanes 指定你要分 配几个 plane,分配到的 plane,会经由 plane_mask_return 传回。 plane_mask_return 这个阵列内的每个元素,指定了分配到的 plane 的 mask。npixels 则指定了要分配多少个 pixel,pixel 则由 pixels_return 这个阵列传回。所有分配到的 cell 的数目为 npixels * 2^nplanes^,而 cell 的 pixel 值则为 pixels_return 传回之 pixel 值和 plane mask 做 OR 运算所能产生 的所有值。如果 contig 设为 true,则所有分配到之 plane 会是相 邻连续的,也就是所有传回之 plane mask 做 OR 运算,会得到一群 设为 1 的连续 bits。
--------------------------------------------------------------------------------
XStoreColor(display, colormap, color)
Display *display;
Colormap colormap;
XColor *color;
colormap 指定 colormap。
color 指定 pixel 和 RGB 值。
--------------------------------------------------------------------------------
使用 XStoreColor 设定指定之 cell 的 RGB 值,但只限於 read/write cell。
--------------------------------------------------------------------------------
XStoreColors(display, colormap, color, ncolors)
Display *display;
Colormap colormap;
XColor color[];
int ncolor;
colormap 指定 colormap。
color 指定要设定之颜色的结构阵列。
ncolor 指定 color 阵列中有多少个设定值。
--------------------------------------------------------------------------------
XStoreColors 可以同时设定多个 color cells 的 RGB 值,但只 限於 read/write cell,read-only cell 不能更改。
--------------------------------------------------------------------------------
XFreeColors(display, colormap, pixels, npixels, planes)
Display *display;
Colormap colormap;
unsigned long pixels[];
int npixels;
unsigned long planes;
colormap 指定使用之 colormap。
pixels 指定对映到 cells 的 pixels 值的阵列。
npixels 指定 pixels 阵列中有多少个 pixel 值。
planes 指定你要释放的 planes。
--------------------------------------------------------------------------------
当你所配置到的 color cell 不再被需要时,你可以使用 XFreeColors 释放。XFreeColors 同一时间内可以释放多个 cell ,pixels 是指定要释放掉的 cell 的阵列,npixels 则指定 cell 的数目。planes 则是要释放之 planes 的 plane mask,将要释放 之所有 plane 的 mask OR 起来所得到的 mask。所释放的 pixels 为,任一指定之 pixel 和 plane mask 之部分集合做 OR 运算後,所 有可能产生的 pixel 集合。
使用颜色名称
除了使用 RGB 值之外,你可以使用颜色的名称,并取得适当的 pixel 值。
--------------------------------------------------------------------------------
status XAllocNamedColor(display, colormap, color_name,
screen_def_return, exact_def_return)
Display *display;
Colormap colormap;
char *color_name;
XColor *screen_def_return, *exact_def_return;
colormap 指定 colormap。
color_name 颜色之名称。
screen_def_return
传回硬所能提供最接近之 RGB 值。
screen_def_exact
传回精确的 RGB 值。
--------------------------------------------------------------------------------
screen_def_exact 传回的是原本正确颜色所该有的 RGB 色值,而 screen_def_return 传回的则是目前硬所能提供颜色最接近之 RGB 色值。
操作 Colormaps
除了使用预定公用的 colormap (从 parent 视窗拷贝而来的) 分配我 们需要的颜色之外,我们也可以为每个个别的视窗建立独立的 colormap,让每个视窗能独力拥有 colormap,或者是由一群视窗来 分享(share)一个 colormap。
--------------------------------------------------------------------------------
Colormap XCreateColormap(display, w, visual, alloc)
Display *display;
Window w;
Visual *visual;
int alloc;
w 指定视窗。
visual 指定一个该 screen 所提供之 visual。
alloc 指定是否要分配在 colormap 的所有 entry。
可以是 AllocNone 或 AllocAll。
--------------------------------------------------------------------------------
XCreateColormap 会传回一个在指定视窗所在的 screen 上建立之新的 colormap。visual 指定该 colormap 所提供之 visual。
我们可以随时为视窗设定新的 colormap,但是 colormap 的 visual 必需和视窗的 visual 相同。指定视窗的 colormap,我们可以透过 XSetWindowColormap:
--------------------------------------------------------------------------------
XSetWindowColormap(display, w, colormap)
Display *display;
Window w;
Colormap colormap;
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
XFreeColormap(display, colormap)
Display *display;
Colormap colormap;
colormap 要释放之 colormap。
--------------------------------------------------------------------------------
释放一个 colormap,但对於预定之 colormap 没有作用。如果要 释放之 colormap 已被使用在某个视窗上时,则 XFreeColormap 会将该视窗之 colormap 设成 None,并对该视窗产生 ColormapNotify event ( event 在後面的章节会谈到 )。
2. Graphics Context
Graphics Context 简称 GC,是存在 server 上的一种资源。GC 是用来 存放绘图时所需要的各项资讯(例如: 线的宽度和长度,前景和背景颜色 等等),在大部分的绘图功能中,都需要使用 GC 做为参数。其实,我们 可以把 GC 看做是我们在做画时的画笔,不同的画笔会产生不同的效果 。同样的,我们也可以使用不同的 GC 内容的变化,来组合达成我们所 需要的画面效果。同一个 GC 可以在不同的视窗使用,也可以在不同的 client 间使用,但是一般来说 ,并不鼓励由不同的 client 使用,因为 Xlib 会对 GC 暂存,可能会造 成同步上的问题。GC 是和 screen 结合在一起的,同时也和 depth 有关 ,只有 screen 和 depth 和 GC 和同的视窗,才可以使用该 GC。也就是 该视窗必需和 GC 是在同一个 screen,并且要有相同的 depth。
Xlib 提供 XGCValues 这个结构, 以存放 GC 的相关资讯。我们将要 设定的值,存於这个结构,同时也经由这个结构传回 GC 的内存值。
--------------------------------------------------------------------------------
/* GC attribute value mask bits */
#define GCFunction (1L<<0)
#define GCPlaneMask (1L<<1)
#define GCForeground (1L<<2)
#define GCBackground (1L<<3)
#define GCLineWidth (1L<<4)
#define GCLineStyle (1L<<5)
#define GCCapStyle (1L<<6)
#define GCJoinStyle (1L<<7)
#define GCFillStyle (1L<<8)
#define GCFillRule (1L<<9)
#define GCTile (1L<<10)
#define GCStipple (1L<<11)
#define GCTileStipXOrigin (1L<<12)
#define GCTileStipYOrigin (1L<<13)
#define GCFont (1L<<14)
#define GCSubwindowMode (1L<<15)
#define GraphicsExposures (1L<<16)
#define GCClipXOrigin (1L<<17)
#define GCClipYOrigin (1L<<18)
#define GCClipMask (1L<<19)
#define GCDashOffset (1L<<20)
#define GCDashList (1L<<21)
#define GCArcMode (1L<<22)
/* Values */
typedef struct {
int function;
unsigned long plane_mask;
unsigned long foreground;
unsigned long background;
int line_width;
int line_style;
int cap_style;
int join_style;
int fill_style;
int fill_rule;
int arc_mode;
Pixmap tile;
Pixmap stipple;
int ts_x_origin;
int ts_y_origin;
Font font;
int subwindow_mode;
Bool graphics_exposures;
int clip_x_origin;
int clip_y_origin;
Pixmap clip_mask;
int dash_offset;
char dashes;
} XGCValues;
--------------------------------------------------------------------------------
下面是 XGCValues 的栏位说明。 栏位 预设值 说明
function GXcopy Xlib 定义了 16 种 function, 用以定义各种 X 所提供的绘图形式. Xlib 提供了一些绘图函数, 当我们在一个 drawable 上绘图时, 新绘上的 图该如何和在原本位置上的图形配合呢? function 定义了 X 所提供的 16 种可能中的一种. 当我们为 GC 设好新的 function 之後, 下一次我们使用 GC 进行绘图时, 新的 function 就开始发生了作用. 下面是 Xlib 定义的 16 种 function. GXclear 把输出图素清除为 0
GXand 把输出之图与原图素做 and 运算
GXandReverse 先把原图素反相, 然後和输出图素做 and 运算
GXcopy 直接用输出图素替代原图素
GXandInverted 先将输出图素和原图素做 and 运算後, 再将结果反相
GXnoop 维持原图素
GXxor 输出图素和原图素做 xor 运算
GXor 输出图素和原图素做 or 运算
GXnor 先分别把输出图素和原图素做反相, 再将反相後的两图做 and 运算
GXequiv 先反相输出图素,然後和原图素做 xor 运算
GXinvert 把原图素反相
GXorReverse 反相原图素, 然後和输出图素做 xor 运算
GXcopyInverted 把输出图素反相当为最後结果
GXorInverted 把输出图素反相後和原图素做 or 运算
GXnand 把输出图素和原图素做反相, 然後两图做 or 运算
GXset 把输出部分全设为 1
plane_mask AllPlanes 指定会被影的 planes, 会被影的 planes 设为 1。Xlib 中定义 AllPlanes 常数, 指定所有的 planes。绘图的最後结果是:
((输出图素 function 原图素) AND plane_mask)
foreground 1 指定图形输出时的前景所使用的图素值(pixel)
background 0 指定图形输出时的背景所使用的图素值(pixel)
line_width 0 如果输出中有线条时, 线条的宽度.
line_style LineSolid 线条的样式, Xlib 定义三个常数, 代表三种样式. LineSolid 实线
LineOnOffDash 虚线
LineDoubleDash 另一种虚线
cap_style CapButt 指定线条端线点(起点和终点)的样式。 CapNotLast 和 CapButt 相似, 只是 line width 为 0 时, 不画出端点.
CapButt 方形长角的端点
CapRound 圆弧形的端点
CapProjecting 和 CapButt 相似, 但端点会再延伸 line width 的一半长度
join_style JoinMiter 折线的折点形式。 JoinMiter 角状的折点
JoinRound 图弧状的折点
JoinBevel 像是两个 CapButt 的端点重叠在一起
fill_style FillSolid 设定线段,文字,和填充画面的来源。 FillSolid 前景填满 foreground 颜色
FillTiled 以 tile 填满
FillStippled 前景以填上 foreground 但以 stipple 遮罩起来.
FillOpaqueStippled 和 FillStippled 相似, 但被遮罩的部分(stipple 内为 0 的部分) 填上 background。
fill_rule EvenOddRule 设定呼叫 XFillPolygon 时,如何定义出内部和外部。 EvenOddRule 以通过指定点的线为基准, 通过 path 奇数次的为 inside
WindingRule 通过顺时钟方向的 path 和逆时钟方向的 path 的次数如果不同 即为 inside。
arc_mode ArcPieSlice 控制 XFillArcs 如何填满圆弧。 ArcChord 以琴弦般的填满弧
ArcPieSlice 像被切开的 pie 一样的填满弧
tile 0 和 GC 有相同 root 和深度(depth)的 pixmap
stipple 0 深度(depth)为 1 的 pixmap
ts_x_origin 0 设定 tile/stipple 的原点的 x 座标
ts_y_origin 0 设定 tile/stipple 的原点的 y 座标
font Implementation dependent 字形,XLoadFont 的传回值
subwindow_mode ClipByChildren ClipByChildren
IncludeInferiors
graphics_exposures True 控制 XCopyArea 和 XCopyPlane 的 GraphicsExpose 事件(event)的产生。
clip_x_origin 0 clip_mask 的原点相对於 drawable 的位置
clip_y_origin 0 clip_mask 的原点相对於 drawable 的位置
clip_mask None clip_mask 为深度(depth)为 1 并和 GC 相同 root 的 pixmap, 做为输出的 mask
dash_offset
dashes
你可以透过 XCreateGC 建立一新的 GC:
--------------------------------------------------------------------------------
GC XCreateGC(display, d, valuemask, values)
Display *display;
Drawable d;
unsigned long valuemask;
XGCValues *values;
d 指定 drawable。
valuemask 指定使用了那些 GC 元件。这个参数是把各元件之
mask OR 起来得到的 mask,用以指定设了那些元
件。
value 指定设定的 GC 内容。
--------------------------------------------------------------------------------
呼叫 XCreateGC 後,建立一个新的 GC,并会传回 GC。所谓的 drawable 指的是一个可以使用绘图功能,在其上进行绘图的视窗或是其它 X 上的 物件。
--------------------------------------------------------------------------------
XFreeGC(display, gc)
Display *display;
GC gc;
gc 指定要释放之 GC。
--------------------------------------------------------------------------------
释放一个己建立之 GC。
下面我们介绍一些设定 GC 的方便函数,以方便我们做 GC 设定。
--------------------------------------------------------------------------------
XSetForeground(display, gc, foreground)
Display *display;
GC gc;
usigned long foreground;
gc 指定作用对像之 GC。
foreground 指定前景颜色。
--------------------------------------------------------------------------------
设定 GC 内容的前景。当你使用该 GC 绘图时,前景颜色即为 GC 内所设的前景颜色。
--------------------------------------------------------------------------------
XSetBackground(display, gc, background)
Display *display;
GC gc;
usigned long background;
gc 指定作用对像之 GC。
background 指定背景颜色。
--------------------------------------------------------------------------------
设定 GC 的背景颜色。当你使用该 GC 绘图时,前景颜色即为 GC 内所设的前景颜色。
--------------------------------------------------------------------------------
XSetLineAttributes(display, gc, line_width, line_style,
cap_style, join_style)
Display *display;
GC gc;
unsigned int line_width;
int line_style;
int cap_style;
int join_style;
gc 指定作用对像之 GC。
line_width 线条之宽度。
line_style 线条型式,有 LineSolid、LineOnOffDash、
LineDoubleDash。
cap_style 指定线条端点之型式,有 CapNotLast、
CapButt、CapRound、CapProjecting。
join_style 指定线条转折点的型式,有 JoinMiter、
JoinRound、JoinBevel。
--------------------------------------------------------------------------------
设定线的形式。
--------------------------------------------------------------------------------
XSetFont(display, gc, font)
Display *display;
GC gc;
Font font;
gc 指定作用对像之 GC。
font 指定字型。
--------------------------------------------------------------------------------
设定字形。
--------------------------------------------------------------------------------
XSetArcMode(display, gc, arc_mode)
Display *display;
GC gc;
int arc_mode;
gc 指定作用对像之 GC。
arc_mode 指定画弧时,封口的型式,有 ArcChord、
ArcPieSlice。
--------------------------------------------------------------------------------
设定画弧时,封口的型式。
3. Graphics
Xlib 提供大量的函数,处理图形的输出。
--------------------------------------------------------------------------------
XClearWindow(display, w)
Display *display;
Window w;
--------------------------------------------------------------------------------
清除视窗。
--------------------------------------------------------------------------------
XDrawPoint(display, d, gc, x, y)
Display *display;
Drawable d;
GC gc;
int x, y;
d 指定 drawable。
gc 指定要使用之 GC。
x, y 指定画点的座标。
--------------------------------------------------------------------------------
在视窗上画一点。
--------------------------------------------------------------------------------
XDrawLine(display, d, gc, x1, y1, x2, y2)
Display *display;
Drawable d;
GC gc;
int x1, y1, x2, y2;
d 指定目的 drawable。
gc 指定使用之 GC。
x1, y1, x2, y2 指定线的两端点座标。
--------------------------------------------------------------------------------
在视窗上画一条线。
--------------------------------------------------------------------------------
XDrawRectangle(display, d, gc, x, y, width, height)
Display *display;
Drawable d;
GC gc;
int x, y;
unsigned int width, height;
x, y 指定矩形的左上角座标。
width, height 指定矩形的大小。
--------------------------------------------------------------------------------
在视窗上画一个矩形。
--------------------------------------------------------------------------------
XDrawArc(display, d, gc, x, y, width, height, angle1,
angle2)
Display *display;
Drawable d;
GC gc;
int x, y;
unsigned int width, height;
int angle1, angle2;
x, y 指定弧的中心点(原点)。
width, height 指定弧的 x 轴和 y 轴的比例。
angle1, angle2 弧的起始角度和结止角度。
--------------------------------------------------------------------------------
在视窗上画一个弧形。
--------------------------------------------------------------------------------
XFillRectangle(display, d, gc, x, y, width, height)
Display *display;
Drawable d;
GC gc;
int x, y;
unsigned int width, height;
--------------------------------------------------------------------------------
在视窗上画一个填满颜色的矩形。
--------------------------------------------------------------------------------
XFillArc(display, d, gc, x, y, width, height, angle1,
angle2)
Display *display;
Drawable d;
GC gc;
int x, y;
unsigned int width, height;
int angle1, angle2;
--------------------------------------------------------------------------------
在视窗上画一个填满颜色的弧形。
--------------------------------------------------------------------------------
Font XLoadFont(display, name)
Display *display;
char *name;
name 指定字形名称。
--------------------------------------------------------------------------------
载入字形,当我要在视窗上显示某一字形时,我们必需先载入字形, 然後才能使用。使用这个函数之後,会传回一个 Font 的 ID,这 就是我们在使用 XSetFont 函数设定 GC 所要传入的参数之一。 当我们使用传回来的 Font 设定 GC 後,就可以使用该 GC 当做 参数在萤幕上显示该字形的字串。
--------------------------------------------------------------------------------
XUnloadFont(display, font)
Display *display;
Font font;
font 指定要 unload 的字形。
--------------------------------------------------------------------------------
移除字形。当我们不再使用一字形时,我们必需将之移除。
--------------------------------------------------------------------------------
XDrawString(display, d, gc, x, y, string, lengtth)
Display *display;
Drawable d;
GC gc;
int x, y;
char *string;
int length;
gc 画字时所要用的 GC。
x, y 指定字串显示的座标。
string 要显示的字串。
length 字串的长度。
--------------------------------------------------------------------------------
在萤幕上显示一字串。
--------------------------------------------------------------------------------
XDrawString16(display, d, gc, x, y, string, length)
Display *display;
Drawable d;
GC gc;
int x, y;
XChar2b *string;
int length;
gc 指定使用之 GC。
x, y 指定字串显示的座标。
string 指定显示之字串。
length 指定字串内有多少个字。
--------------------------------------------------------------------------------
在萤幕上显示一双位元组(或 16bits)的字串。X Window 有支援双位元组 字集,用以显示双位元组的语言(如中文等)。双位元组的字元是以 XChar2b 这个 structure 来表示:
typedef struct {
unsigned char byte1;
unsigned char byte2;
} XChar2b;
byte1 存放的是双位元组字元的高位元组(MSB:most significant byte) ,byte2 存放的则是低位元组(LSB:least significant byte)。一个双 位元组的字串就是 XChar2b 的阵列。
4. Image
在 GUI 介面下, 常会需要将一张图片直接 show 在视窗上, 像是 show 照片. Xlib 提供一些可以直接在 client 和 server 间传送影像(image)的函数, 以直接处理一张张的影像, 例如, 图形档. 在这提到的 image 相关函数, 都会使用 XImage 结构做为函数的输入参数. Xlib 在 client 端使用 XImage 描述影像资料, 当你要使用 Xlib 的函数处理影像资料时, 必需透过 XImage 进行操作. XImage 提供一个物件化的介面, 透过物件提供的函数, 我们可以相同的方式, 处理不同的影像资料.
--------------------------------------------------------------------------------
/*
* Data structure for "image" data, used by image manipulation routines.
*/
typedef struct _XImage {
int width, height; /* size of image */
int xoffset; /* number of pixels offset in X direction */
int format; /* XYBitmap, XYPixmap, ZPixmap */
char *data; /* pointer to image data */
int byte_order; /* data byte order, LSBFirst, MSBFirst */
int bitmap_unit; /* quant. of scanline 8, 16, 32 */
int bitmap_bit_order; /* LSBFirst, MSBFirst */
int bitmap_pad; /* 8, 16, 32 either XY or ZPixmap */
int depth; /* depth of image */
int bytes_per_line; /* accelarator to next line */
int bits_per_pixel; /* bits per pixel (ZPixmap) */
unsigned long red_mask; /* bits in z arrangment */
unsigned long green_mask;
unsigned long blue_mask;
XPointer obdata; /* hook for the object routines to hang on */
struct funcs { /* image manipulation routines */
struct _XImage *(*create_image)();
#if NeedFunctionPrototypes
int (*destroy_image) (struct _XImage *);
unsigned long (*get_pixel) (struct _XImage *, int, int);
int (*put_pixel) (struct _XImage *, int, int, unsigned long);
struct _XImage *(*sub_image)(struct _XImage *, int, int, unsigned int, unsigned int);
int (*add_pixel) (struct _XImage *, long);
#else
int (*destroy_image)();
unsigned long (*get_pixel)();
int (*put_pixel)();
struct _XImage *(*sub_image)();
int (*add_pixel)();
#endif
} f;
} XImage;
--------------------------------------------------------------------------------
XImage 可以建过 XInitImage 和 XCreateImage 建立. 建立之後的 object, 可以使用 XGetPixel, XPutPixel, XSubImage 和 XAddPixel 读取和修改内容. 使用 XPutImage 输出到 drawable (视窗或 pixmap), 使用 XGetImage 从 drawable 读取. object 最後必需使用 XDestroyImage 释放.
--------------------------------------------------------------------------------
Status XInitImage(image)
XImage *image;
--------------------------------------------------------------------------------
XImage 在使用之前, 必需先经过 XInitImage 进行 initialize. 在呼叫 XInitImage 之前, 除了 manipulate functions 之外, 其它的栏位都必需 先设定好. 成功的话, 传回非0值, 否则传回 0.
--------------------------------------------------------------------------------
XImage *XCreateImage(display, visual, depth, format, off-
set, data, width, height, bitmap_pad,
bytes_per_line)
Display *display;
Visual *visual;
unsigned int depth;
int format;
int offset;
char *data;
unsigned int width;
unsigned int height;
int bitmap_pad;
int bytes_per_line;
--------------------------------------------------------------------------------
XCreateImage 会为输入之影像资料产生一个 XImage 结构, 并传回结构. 是一个包装 XInitImage 的函数. 'format' 指定影像储存的形式, 有 ZPixmap, XYPixmap 和 XYBitmap. ZPixmap 的储存方式是一个 pixel 接 着一个 pixel 存放. XYPixmap 则是 plane 接着 plane, 将所有 pixel 特定 plane 的内容集成 bitmap, 然後依 plane 的顺序储存各 plane 形式的 bitmap. XYBitmap 和 XYPixmap 一样, 但是 XYBitmap只有一个 plane. 而, 影像的内容则存在 data 所指定的 memory block . 使用者必需指定一块记忆(data)以储存影像, XCreateImage 并不会主动为您配置. data 的大小和 image 的大小和深度(depth)有关, format 也会影响. 下面是 data 大小和 bytes_per_line 的计算公式.
format size of data bytes_per_line
ZPixmap width * height * ((depth + 7) / 8) width * ((depth + 7) / 8)
XYPixmap ((width + 7) / 8) * height * depth (width + 7) / 8
XYBitmap ((width + 7) / 8) * height * 1 (width + 7) / 8
--------------------------------------------------------------------------------
unsigned long XGetPixel(ximage, x, y)
XImage *ximage;
int x;
int y;
--------------------------------------------------------------------------------
取得影像内的一个图点.
--------------------------------------------------------------------------------
XPutPixel(ximage, x, y, pixel)
XImage *ximage;
int x;
int y;
unsigned long pixel;
--------------------------------------------------------------------------------
在影像上放上一个点.
--------------------------------------------------------------------------------
XImage *XSubImage(ximage, x, y, subimage_width,
subimage_height)
XImage *ximage;
int x;
int y;
unsigned int subimage_width;
unsigned int subimage_height;
--------------------------------------------------------------------------------
读取影像的一部分内容, 并传回 XImage. x, y, subimage_width, 和 subimage_height 指定 image 内的一个方框的位置和大小, 读 取方框内的资料.
--------------------------------------------------------------------------------
XAddPixel(ximage, value)
XImage *ximage;
long value;
--------------------------------------------------------------------------------
把 image 内每个点的 pixel 值都加上指定的 valuex.
--------------------------------------------------------------------------------
XDestroyImage(ximage)
XImage *ximage;
--------------------------------------------------------------------------------
由上面和下面各函数所产生的 XImage 物件, 最後不用时, 都要使用 XDestroyImage 释放掉。注意, XDestroyImage 会主动将 data 释放
--------------------------------------------------------------------------------
XPutImage(display, d, gc, image, src_x, src_y, dest_x,
dest_y, width, height)
Display *display;
Drawable d;
GC gc;
XImage *image;
int src_x, src_y;
int dest_x, dest_y;
unsigned int width, height;
--------------------------------------------------------------------------------
将 image 输出 'd' 所指定的 drawable.
--------------------------------------------------------------------------------
XImage *XGetImage(display, d, x, y, width, height,
plane_mask, format)
Display *display;
Drawable d;
int x, y;
unsigned int width, height;
unsigned long plane_mask;
int format;
--------------------------------------------------------------------------------
读取 'd' 所指定之 drawable 的影像. 'plane_mask' 指定要读取的 planes. 若指定的 planes, 为 drawable 所有 planes 的 subset, 那麽传回的 image 的 depth 将和指定的 planes 数目相同.
--------------------------------------------------------------------------------
XImage *XGetSubImage(display, d, x, y, width, height,
plane_mask, format, dest_image, dest_x,
dest_y)
Display *display;
Drawable d;
int x, y;
unsigned int width, height;
unsigned long plane_mask;
int format;
XImage *dest_image;
int dest_x, dest_y;
--------------------------------------------------------------------------------
下面是处理影像的例.
--------------------------------------------------------------------------------
/* -- Image-test.c -- */
#include
#include
#include
#include
#include
#include
#include "gnu.xpm"
#include "doomface.xpm"
#include "Boss2.xpm"
struct ColorElm {
char *tag;
unsigned long pixel;
};
unsigned long
get_pixel(Display *display, Colormap colormap, char *str)
{
char *cp = str;
XColor color, excolor;
if(*cp == '#') {
int j, k;
int t;
int rgbl;
unsigned short rgb[3];
cp++;
if(strlen(cp) == 6)
rgbl = 2;
else
rgbl = 4;
for(k = 0; k < 3; k++) {
t = 0;
for(j = 0; j < rgbl; j++) {
char c = *(cp++);
t <<= 4;
if(c >= 'A' && c <= 'F')
t += c - 'A' + 10;
else if(c >= 'a' && c <= 'f')
t += c - 'a' + 10;
else
t += c - '0';
}
rgb[k] = t;
}
color.red = rgb[0];
color.green = rgb[1];
color.blue = rgb[2];
color.flags = DoRed | DoGreen | DoBlue;
XAllocColor(display, colormap, &color);
} else {
char *cp;
if(strcasecmp(str, "None") == 0)
cp = "black";
else
cp = str;
XAllocNamedColor(display, colormap, cp, &color, &excolor);
}
return color.pixel;
}
/*
* 从 *.xpm 转换成 Xlib 能处理的 image 资料形式 (ZPixmap)
*/
char *
xpm_to_data(char **xpm, Display *display,
Colormap colormap, int depth, int *width, int *height)
{
int nc, el; /* # of color, and element length */
int i;
int bpp; /* byte per pixel */
struct ColorElm *ce, *cep;
unsigned short rgb[3];
XColor color;
char *data, *dp;
sscanf(*(xpm++), "%d %d %d %d", width, height, &nc, &el);
bpp = (depth + 7) / 8;
data = (char *)malloc(sizeof(char) * bpp *
*width * *height);
ce = (struct ColorElm *)malloc(sizeof(struct ColorElm) * nc);
cep = ce;
for(i = 0; i < nc; i++) {
char *cp;
cep->tag = (char *)malloc(sizeof(char) * el);
memcpy(cep->tag, *xpm, el);
cp = *xpm + el;
/*
* skip redundant character
*/
while(isspace(*cp)) cp++;
while(*(cp++) != 'c') {
while(isspace(*cp)) cp++;
while(!isspace(*cp)) cp++;
while(isspace(*cp)) cp++;
}
/*
* get pixel of color
*/
while(isspace(*cp)) cp++;
cep->pixel = get_pixel(display, colormap, cp);
cep++;
xpm++;
}
/*
* generate image data
*/
dp = data;
for(i = 0; i < *height; i++) {
int j;
char *p;
p = *(xpm++);
for(j = 0; j < *width; j++) {
int idx;
unsigned long pixel;
/*
* find pixel of point
*/
for(idx = 0; idx < nc; idx++)
if(!memcmp(p, ce[idx].tag, el)) {
memcpy(dp, &ce[idx].pixel, bpp);
break;
}
dp += bpp;
p += el;
}
}
free(ce);
return data;
}
main()
{
Display *display;
Window window;
XSetWindowAttributes attr;
Colormap colormap;
XColor color1, color2;
XGCValues gcvalue;
GC gc;
XSizeHints *sz;
XImage *img1, *img2, *img3;
int screen;
char *data; /* image data */
int w, h; /* width & height */
int bpp; /* byte per pixel */
display = XOpenDisplay("0:0");
colormap = DefaultColormap(display, screen = DefaultScreen(display));
color1.red = color1.blue = 0xffff;
color1.green = 0;
color2.red = color2.green = color2.blue = 0xff;
color1.flags = color2.flags = DoRed | DoGreen | DoBlue;
XAllocColor(display, colormap, &color1);
XAllocColor(display, colormap, &color2);
attr.background_pixel = color2.pixel;
window = XCreateWindow(display, XDefaultRootWindow(display),
100, 100, 500, 300, 2, XDefaultDepth(display, 0),
InputOutput, CopyFromParent, CWBackPixel, &attr);
XStoreName(display, window, "hello!! world!!");
sz = XAllocSizeHints();
sz->x = 100;
sz->y = 100;
sz->width = 300;
sz->height = 500;
sz->flags = USPosition | USSize;
XSetNormalHints(display, window, sz);
XMapWindow(display, window);
gc = XCreateGC(display, window, 0, &gcvalue);
XSetForeground(display, gc, color1.pixel);
XSetBackground(display, gc, color2.pixel);
XFlush(display);
printf("Show image!!\n");
bpp = (DefaultDepth(display, screen) + 7) / 8;
/*
* Create gnu.xpm
*/
data = xpm_to_data(image_name, display, colormap,
DefaultDepth(display, screen), &w, &h);
img1 = XCreateImage(display,
DefaultVisual(display, screen),
DefaultDepth(display, screen),
ZPixmap, 0, data,
w, h, 8, w * bpp);
/* (w, h) 是影像的宽和高 */
/*
* Create doomface.xpm
*/
data = xpm_to_data(xpm, display, colormap,
DefaultDepth(display, screen), &w, &h);
img2 = XCreateImage(display,
DefaultVisual(display, screen),
DefaultDepth(display, screen),
ZPixmap, 0, data,
w, h, 8, w * bpp);
/* (w, h) 是影像的宽和高 */
/*
* Create Boss2.xpm
*/
data = xpm_to_data(Boss2_xpm, display, colormap,
DefaultDepth(display, screen), &w, &h);
img3 = XCreateImage(display,
DefaultVisual(display, screen),
DefaultDepth(display, screen),
ZPixmap, 0, data,
w, h, 8, w * bpp);
/* (w, h) 是影像的宽和高 */
/*
* Show images
*/
XPutImage(display, window, gc, img1, 0, 0, 10, 10, w, h);
XPutImage(display, window, gc, img2, 0, 0, 10, 100, w, h);
XPutImage(display, window, gc, img3, 0, 0, 200, 50, w, h);
XFlush(display);
/*
* Destroy images
*/
XDestroyImage(img1);
XDestroyImage(img2);
XDestroyImage(img3);
sleep(3);
XDestroyWindow(display, window);
XFlush(display);
XCloseDisplay(display);
}
--------------------------------------------------------------------------------
执行结果
颜色和原图有些不同, 主要原因是使用 default 的 colormap. 上面的程式 在视窗显示三张 .xpm 的图形档, 分别是 gnu.xpm, doomface.xpm 和 Boss2.xpm.
5. 例
--------------------------------------------------------------------------------
/* ---- XGraph.c ---- */
#include
#include
#include
#include
main() {
Display *display;
Window window;
XSetWindowAttributes attr;
Colormap colormap;
XColor color1, color2;
XGCValues gcvalue;
GC gc;
XSizeHints *sz;
display = XOpenDisplay("0:0");
/* 取得预设之 colormap */
colormap = DefaultColormap(display,
DefaultScreen(display));
/* 取得 colorcell */
color1.red = color1.blue = 0xffff;
color1.green = 0;
color2.red = color2.green = color2.blue = 0xff;
color1.flags = color2.flags = DoRed | DoGreen | DoBlue;
XAllocColor(display, colormap, &color1);
XAllocColor(display, colormap, &color2);
/* 设定视窗的 attribute 和建设 */
attr.background_pixel = color2.pixel; /* 背景颜色 */
window = XCreateWindow(display,
XDefaultRootWindow(display), 100, 100, 300, 300,
2, XDefaultDepth(display, 0), InputOutput,
CopyFromParent, CWBackPixel, &attr);
/* 设定和 window manager 进行沟通 */
XStoreName(display, window, "hello!! world!!");
sz = XAllocSizeHints();
sz->x = 100;
sz->y = 100;
sz->width = 300;
sz->height = 300;
sz->flags = USPosition | USSize;
XSetNormalHints(display, window, sz);
/* 显示视窗 */
printf("Map window\n");
XMapWindow(display, window);
XFlush(display);
getchar();
/* 建立并设定 GC */
gc = XCreateGC(display, window, 0, &gcvalue);
XSetForeground(display, gc, color1.pixel);
XSetBackground(display, gc, color2.pixel);
/* 画一个矩形 */
printf("Draw rectangle\n");
XDrawRectangle(display, window, gc, 10, 10, 100, 100);
XFlush(display);
getchar();
/* 清除视窗 */
XClearWindow(display, window);
/* 设定 GC 内,线的形式 */
XSetLineAttributes(display, gc, 5, LineOnOffDash,
CapButt, JoinRound);
/* 画线 (200, 10) - (200, 290) */
printf("Draw line\n");
XDrawLine(display, window, gc, 200, 10, 200, 290);
XFlush(display);
getchar();
/* 关闭视窗 */
printf("Destory Window\n");
XDestroyWindow(display, window);
XFlush(display);
getchar();
printf("close display\n");
XCloseDisplay(display);
getchar();
}
--------------------------------------------------------------------------------
gcc -o XGraph XGraph.c -L/usr/X11R6/lib -lX11