Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1546994
  • 博文数量: 596
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 173
  • 用 户 组: 普通用户
  • 注册时间: 2016-07-06 15:50
个人简介

在线笔记

文章分类

全部博文(596)

文章存档

2016年(1)

2015年(104)

2014年(228)

2013年(226)

2012年(26)

2011年(11)

分类: LINUX

2013-07-05 09:53:15

Drawing With A Color
使用颜色绘图

After we have allocated the desired colors, we can use them when drawing text or graphics. To do that, we need to set these colors as the foreground and background colors of some GC (Graphics Context), and then use this GC to make the drawing. This is done using the XSetForeground() and XSetBackground() functions, as follows:
在我们已经分配了所需的颜色后,我们能在绘出文本和图形的过程中使用他们。要这么作,我们需要设置这些颜色为某GC(图形上下文)的前景色和背景色,然后使用这个GC进行绘图。整个过程使用XSetForeground()和XSetBackground()函数,如下:

/* use the previously defined colors as the foreground and background */
/* colors for drawing using the given GC. assume my_gc is a handle to */
/* a previously allocated GC. */
XSetForeground(display, my_gc, screen_color_1.pixel);
XSetForeground(display, my_gc, screen_color_2.pixel);

As you see, this is rather simple. The actual drawing is done using the same functions we have seen earlier. Note that in order to draw using many different colors, we can do one of two things. We can either change the foreground and/or background colors of the GC before any drawing function, or we can use several different GCs to draw in different colors. The decision as of which option to use is yours. Note that allocating many GCs will use more resources of the X server, but this will sometime lead to more compact code, and will might it easier to replace the drawn colors.
如你所见,这个相当简单。实际的绘画使用我们已经在前面看过的函数来完成。注意为了使用许多不同的颜色来绘图,我们能采取这两个办法中的一个。我们要么在调用任何绘图函数之前改变GC的前景以及/或者背景色,或者我们能使用几个不同的GC以不同的颜色绘画。最终采用那种办法是你各人选择的事情。注意分配虚度GC将使用X服务器更多的资源,但有时能使得代码更紧凑,而且替换画出的颜色要容易些。

As an example to drawing using colors, look at the color-drawing.c program. This is a copy of the simple-drawing.c program, except that here we also allocate colors and use them to paint the rainbow...
作为一个使用颜色绘图的例子,看看color-drawing.c程序。这是simple-drawing.c程序的复制,除去我们还分配了颜色,并用它们来画彩虹……。

X Bitmaps And Pixmaps
X Bitmap 和 Pixmap

One thing many so-called "Multi-Media" applications need to do, is display images. In the X world, this is done using bitmaps and pixmaps. We have already seen some usage of them when setting an icon for our application. Lets study them further, and see how to draw these images inside a window, along side the simple graphics and text we have seen so far.
许多所谓的“多媒体”程序需要做的一件事情是显示图片。在X世界中,这个是通过使用bitmap和pixmap来完成的。我门已经在给我们程序设置图标时看到了他们的一些使用。让我们进一步学习他们,来看看如何在窗口中与我们已经看过了的简单图形和文本一起,画出这些图像。

One thing to note before delving further, is that Xlib supplies no means of manipulating popular image formats, such as gif, jpeg or tiff. It is left up to the programmer (or to higher level graphics libraries) to translate these image formats into formats that the X server is familiar with - x bitmaps, and x pixmaps.
在进行更深的钻研之前要注意一件事情是Xlib没有提供一种操作流行图像格式的办法,如gif,jpeg或者tiff。这些是留给程序员(或者是更高层的图形库)来翻译这些图像格式为X服务器熟悉的格式 - x bitmap与x pixmap。

What Is An X Bitmap? An X Pixmap?
什么是X Bitmap?X Pixmap?

An X bitmap is a two-color image stored in a format specific to the X window system. When stored in a file, the bitmap data looks like a C source file. It contains variables defining the width and height of the bitmap, an array containing the bit values of the bitmap (the size of the array = width * height), and an optional hot-spot location (will be explained later, when discussing mouse cursors).
X bitmap是以X window系统规定的格式存储的双色图像。当存为文件时,bitmap数据看上去和C源代码一样。它包含定义bitmap宽和高的变量,一个包含bitmap的各个位的值的数组(数组的尺寸=width*height),以及可选的热区位置(将在后面讨论鼠标光标时解释)。

A X pixmap is a format used to store images in the memory of an X server. This format can store both black and white images (such as x bitmaps) as well as color images. It is the only image format supported by the X protocol, and any image to be drawn on screen, should be first translated into this format.
X pixmap时用来在X服务器内存中储存图像的格式。该格式既能够储存黑白图像(和X bitmap一样)也可以时彩色图像。这个时X协议唯一支持的图像格式,而且显示于屏幕上的图像首先也要翻译为这种格式。

In actuality, an X pixmap can be thought of as a window that does not appear on the screen. Many graphics operations that work on windows, will also work on pixmaps - just supply the pixmap ID instead of a window ID. In fact, if you check the manual pages, you will see that all these functions accept a 'Drawable', not a 'Window'. since both windows and pixmaps are drawables, they both can be used to "draw on" using functions such as XDrawArc(), XDrawText(), etc.
实际上,X pixmap能够认为是一个不显示在屏幕上的窗口。许多工作于窗口之上的图形操作,也能够工作于pixmap之上 - 仅仅以pixmap ID替代window ID来提供。事实上,如果你查阅手册,你能看到所有这些函数结构一个“可画”对象,不是一个“窗口”。窗口和pixmap都是可画的,因为他们都能用像XDrawArc()函数来“在其上做画”。

Loading A Bitmap From A File
从文件载入Bitmap

We have already seen how to load a bitmap from a file to memory, when we demonstrated setting an icon for an application. The method we showed earlier required the inclusion of the bitmap file in our program, using the C pre-processor '#include' directive. We will see here how we can access the file directly.
在我们演示给程序设置图标时,我们已经看到如何从文件载入bitmap到内存中。我们前面展示的方法需要在我们的程序中使用C预处理器的“#include”指示符包含bitmap文件。我们将在这儿看到如何直接访问文件。

/* this variable will contain the ID of the newly created pixmap. */
Pixmap bitmap;

/* these variables will contain the dimensions of the loaded bitmap. */
unsigned int bitmap_width, bitmap_height;

/* these variables will contain the location of the hot-spot of the */
/* loaded bitmap. */
int hotspot_x, hotspot_y;

/* this variable will contain the ID of the root window of the screen */
/* for which we want the pixmap to be created. */
Window root_win = DefaultRootWindow(display);

/* load the bitmap found in the file "icon.bmp", create a pixmap */
/* containing its data in the server, and put its ID in the 'bitmap' */
/* variable. */
int rc = XReadBitmapFile(display, root_win,
"icon.bmp",
&bitmap_width, &bitmap_height,
&bitmap,
&hotspot_x, &hotspot_y);
/* check for failure or success. */
switch (rc) {
case BitmapOpenFailed:
fprintf(stderr, "XReadBitmapFile - could not open file 'icon.bmp'.\n");
break;
case BitmapFileInvalid:
fprintf(stderr,
"XReadBitmapFile - file '%s' doesn't contain a valid bitmap.\n",
"icon.bmp");
break;
case BitmapNoMemory:
fprintf(stderr, "XReadBitmapFile - not enough memory.\n");
break;
case BitmapSuccess:
/* bitmap loaded successfully - do something with it... */
.
.
break;
}

Note that the 'root_win' parameter has nothing to do with the given bitmap - the bitmap is not associated with this window. This window handle is used just to specify the screen that we want the pixmap to be created for. This is important, as the pixmap must support the same number of colors as the screen does, in order to make it useful.
注意'root_win'参数对于给定bitmap没有影响 - bitmap没有关联到这个窗口。这个窗口句柄仅仅用于指定我们想要bitmap创建到的窗口。这很重要,因为pixmap为了使得它有用,必须支持屏幕一样多的色彩数。

Drawing A Bitmap In A Window
在窗口中画出Bitmap

Once we got a handle to the pixmap generated from a bitmap, we can draw it on some window, using the XCopyPlane() function. This function allows us to specify what drawable (a window, or even another pixmap) to draw the given pixmap onto, and at what location in that drawable.
一旦我们得到一个从bitmap产生的pixmap的句柄,我们能够使用XCopyPlane(),在某个窗口中把它画出来。这个函数允许我们指定可画的物体(一个窗口,甚至是另外一个pixmap)来把给定的pixmap画到上面去,以及指定画出的位置。

/* draw the previously loaded bitmap on the given window, at location */
/* 'x=100, y=50' in that window. we want to copy the whole bitmap, so */
/* we specify location 'x=0, y=0' of the bitmap to start the copy from, */
/* and the full size of the bitmap, to specify how much of it to copy. */
XCopyPlane(display, bitmap, win, gc,
0, 0,
bitmap_width, bitmap_height,
100, 50,
1);

As you can see, we could also copy a given rectangle of the pixmap, instead of the whole pixmap. Also note the last parameter to the XCopyPlane function (the '1' at the end). This parameter specifies which plane of the source image we want to copy to the target window. For bitmaps, we always copy plane number 1. This will become clearer when we discuss color depths below.
如你所能看到的,我们还能拷贝pixmap个给定矩形内的内容,而不是整个pixmap。还要注意传递给XCopyPlane函数额最后一个参数(最后的'1')。该参数指定了我们想要拷贝到目标窗口的源图像是什么plane的。对于bitmap,我们总是拷贝第一号plane。这在我们下面 讨论色深的时候会变得明白一点。

Creating A Pixmap
创建Pixmap

Sometimes we want to create an un-initialized pixmap, so we can later draw into it. This is useful for image drawing programs (creating a new empty canvas will cause the creation of a new pixmap on which the drawing can be stored). It is also useful when reading various image formats - we load the image data into memory, cerate a pixmap on the server, and then draw the decoded image data onto that pixmap.
有时我们想要创建一个未初始化的pixmap,然后我们能在它上面画图。这对于作图程序来说有用(创建一个新的空画布将导致一个新的将要在其上储存绘画内容的pixmap的创建)。在读取各种图像格式的时候也有用处 - 我们把图像数据载入到内存中,在服务器上创建pixmap,然后把图像数据解码之后画到pixmap上。

/* this variable will store the handle of the newly created pixmap. */
Pixmap pixmap;

/* this variable will contain the ID of the root window of the screen */
/* for which we want the pixmap to be created. */
Window root_win = DefaultRootWindow(display);

/* this variable will contain the color depth of the pixmap to create. */
/* this 'depth' specifies the number of bits used to represent a color */
/* index in the color map. the number of colors is 2 to the power of */
/* this depth. */
int depth = DefaultDepth(display, DefaultScreen(display));

/* create a new pixmap, with a width of 30 pixels, and height of 40 pixels. */
pixmap = XCreatePixmap(display, root_win, 30, 40, depth);

/* just for fun, draw a pixel in the middle of this pixmap. */
XDrawPoint(display, pixmap, gc, 15, 20);

Drawing A Pixmap In A Window
在窗口中画出Pixmap

Once we got a handle to pixmap, we can draw it on some window, using the XCopyArea() function. This function allows us to specify what drawable (a window, or even another pixmap) to draw the given pixmap onto, and at what location in that drawable.
一旦我们获得了pixmap的句柄,我们能在某个窗口上用XCopyArea()函数把它画出来。这个函数允许我们指定给定pixmap要画到的是那个可画对象(窗口,甚至是另一个pixmap),以及画出的位置。

/* draw the previously loaded bitmap on the given window, at location */
/* 'x=100, y=50' in that window. we want to copy the whole bitmap, so */
/* we specify location 'x=0, y=0' of the bitmap to start the copy from, */
/* and the full size of the bitmap, to specify how much of it to copy. */
XCopyArea(display, bitmap, win, gc,
0, 0,
bitmap_width, bitmap_height,
100, 50);

As you can see, we could also copy a given rectangle of the pixmap, instead of the whole pixmap.
如你能看到的,我们也能拷贝pixmap的给定区域,而不是整个pixmap。

One important note should be made - it is possible to create pixmaps of different depths on the same screen. When we perform copy operations (a pixmap onto a window, etc), we should make sure that both source and target have the same depth. If they have a different depth, the operation would fail. The exception to this is if we copy a specific bit plane of the source pixmap, using the XCopyPlane() function shown earlier. In such an event, we can copy a specific plain to the target window - in actuality, setting a specific bit in the color of each pixel copied. This can be used to generate strange graphic effects in window, but is beyond the scope of out tutorial.
一点重要的值得注意的是 - 能够在同一窗口上创建不同色深的pixmap。当我们执行拷贝操作的时候(把pixmap拷贝到窗口,等),我们应当确保源和目标有相同的色深。如果他们色深不同,操作将失败。例外是如果我们使用前面展示的XCopyPlane()函数,拷贝源pixmap的指定bit plane。在这种情况下,我们能拷贝指定plain到目标窗口上 - 实际上,设置一个指定位位每个拷贝象素的颜色。这能用于在窗口中产生奇异的图形效果,但是超过了我们教程的范围。

Freeing A Pixmap
释放Pixmap

Finally, when we are done using a given pixmap, we should free it, in order to free resources of the X server. This is done using the XFreePixmap() function:
最后,当我们用完给定pixmap,为了释放X服务器的资源,我们应当释放它。这通过使用XFreePixmap()函数来完成。

/* free the pixmap with the given ID. */
XFreePixmap(display, pixmap);

After freeing a pixmap - we must not try accessing it again.
在释放pixmap之后 - 我们不能再次访问了。

To summarize this section, take a look at the draw-pixmap.c program, to see a pixmap being created using a bitmap file, and then tiled up on a window on your screen.
总结本节,看看draw-pixmap.c程序,看看使用bitmap文件创建出一个pixmap,并且然后再屏幕上显示于窗口中。

Messing With The Mouse Cursor
改变鼠标光标

Often we see programs that modify the shape of the mouse pointer (also called the X pointer) when in certain states. For example, a busy application would often display a sand clock over its main window, to give the user a visual hint that they should wait. Without such a visual hint, the user might think that the application got stuck. Lets see how we can change the mouse cursor for our windows.
我们时常看到程序在某个状态下改变鼠标指针(也称为X指针)的外形。例如,一个繁忙中的程序时常在它的主窗口上显示沙漏时钟,以给用户一个你应当等待的可视化提示。没有这么一个视觉提示,用户可能认为程序死掉了。让我们看看我们如何改变我们窗口的鼠标光标。

Creating And Destroying A Mouse Cursor
创建和销毁鼠标光标

There are two methods for creating cursors. One of them is by using a set of pre-defined cursors, that are supplied by Xlib. The other is by using user-supplied bitmaps.
有两种创建光标的办法。其中的一种是使用一套预先定义好了的光标,它们是由Xlib提供的。另一个是使用用户提供的bitmap。

In the first method, we use a special font named "cursor", and the function XCreateFontCursor(). This function accepts a shape identifier, and returns a handle to the generated cursor. The list of allowed font identifiers is found in the include file . Here are a few such cursors:
在第一种方法中,我们使用一个名为“光标”的特殊字体,和XCreateFontCursor()函数。这个函数接受一个外形标识符,并且返回产生的光标的句柄。能用的字体标识符的列表可以在中找到。这儿是一些这样的光标:

XC_arrow
The normal pointing-arrow cursor displayed by the server.
XC_pencil
A cursor shaped as a pencil.
XC_watch
A sand watch.
And creating a cursor using these symbols is very easy:

#include /* defines XC_watch, etc. */

/* this variable will hold the handle of the newly created cursor. */
Cursor watch_cursor;

/* create a sand watch cursor. */
watch_cursor = XCreateFontCursor(display, XC_watch);


The other methods of creating a cursor is by using a pair of pixmaps with depth of one (that is, two color pixmaps). One pixmap defines the shape of the cursor, while the other works as a mask, specifying which pixels of the cursor will be actually drawn. The rest of the pixels will be transparent. Creating such a cursor is done using the XCreatePixmapCursor() function. As an example, we will create a cursor using the "icon.bmp" bitmap. We will assume that it was already loaded into memory, and turned into a pixmap, and its handle is stored in the 'bitmap' variable. We will want it to be fully transparent. That is, only the parts of it that are black will be drawn, while the white parts will be transparent. To achieve this effect, we will use the icon both as the cursor pixmap and as the mask pixmap. Try to figure out why...
另一个创建光标的方法是使用一对色深为1的pixmap(也就是,双色的pixmap)。一个pixmap定义了光标的外形,另一个作为一个遮罩,指定了光标的哪些象素是要画出来的。剩下的象素将是透明的。创建这样的光标是使用XCreatePixmapCursor()函数来实现的。作为一个例子,我们将使用"icon.bmp"bitmap来创建光标。我们将假定它已经载入了内存,并且转换为pixmap了,而且它的句柄储存在'bitmap'变量中。我们想它全部是透明的。也就是,只有黑色的部分将被画出来,而白色的部分将是透明的。为了达到这个效果,我们是同时把图标用作光标的pixmap和遮罩pixmap。试着想想看为什么……


/* this variable will hold the handle of the newly created cursor. */
Cursor icon_cursor;

/* first, we need to define foreground and background colors for the cursor. */
XColor cursor_fg, cursor_bg;

/* access the default color map of our screen. */
Colormap screen_colormap = DefaultColormap(display, DefaultScreen(display));

/* allocate black and while colors. */
Status rc = XAllocNamedColor(display,
screen_colormap,
"black",
&cursor_fg,
&cursor_fg);
if (rc == 0) {
fprintf(stderr, "XAllocNamedColor - cannot allocate 'black' ??!!??\n");
exit(1);
}
Status rc = XAllocNamedColor(display,
screen_colormap,
"white",
&cursor_bg,
&cursor_bg);
if (rc == 0) {
fprintf(stderr, "XAllocNamedColor - cannot allocate 'white' ??!!??\n");
exit(1);
}

/* finally, generate the cursor. make the 'hot spot' be close to the */
/* top-left corner of the cursor - location (x=5, y=4). */
icon_cursor = XCreatePixmapCursor(display, bitmap, bitmap,
&cursor_fg, &cursor_bg,
5, 4);

One thing to be explained is the 'hot spot' parameters. When we define a cursor, we need to define which pixel of the cursor is the pointer delivered to the user in the various mouse events. Usually, we will choose a location of the cursor that visually looks like a hot spot. For example, in an arrow cursor, the tip of the arrow will be defined as the hot spot.
这儿要解释的一件事情是'热区'参数。当我们定义了光标,我们需要定义光标的那个象素是投递给用户的各种鼠标事件的指针位置。通常,我们将选择通常看来像热区的光标位置。例如,在一个箭头状的光标中,箭的尖端将被定义为热区。

Finally, when we are done with a cursor and no longer need it, we can release it using the XFreeCursor() function:
最后,当我们用完了光标不再需要它了,我们能够使用XFreeCursor()函数释放它:

XFreeCursor(display, icon_cursor);

Setting A Window's Mouse Cursor
设置窗口的鼠标光标

After we have created a cursor, we can tell the X server to attach this cursor to any of our windows. This is done using the XDefineCursor(), and causes the X server to change the mouse pointer to the shape of that cursor, each time the mouse pointer moves into and across that window. We can later detach this cursor from our window using the XUndefineCursor() function. This will cause the default cursor to be shown when the mouse enter that windows.
在我们创建了光标之后,我们能告诉X服务器把这个光标附着在我们任意一个窗口上。这是通过使用XDefineCursor()来完成的,并且导致X服务器在鼠标每次移入或者通过那个窗口时,把鼠标指针改变为那个光标的样子。我们然后用XUndefineCursor()函数把光标和我们的窗口解开。这个将导致当进入能够窗口时,缺省的鼠标显示出来。

/* attach the icon cursor to our window. */
XDefineCursor(display, win, icon_cursor);

/* detach the icon cursor from our window. */
XUndefineCursor(display, win);


As an example, look at our cursor.c program, and see how mouse cursors are set, changed and removed. Run the program, place the mouse pointer over the created window, and watch.
作为一个例子,看看我们的cursor.c程序,并且看看鼠标光标是如何被设置,改变和移除的。运行这个程序,把鼠标指针放在创建的窗口之上,观察。

阅读(1524) | 评论(0) | 转发(0) |
0

上一篇:perl 排序

下一篇:SHELL 四则运算

给主人留下些什么吧!~~