In the next few sections, we shall discuss various types of resources that most Athena widgets have in common, such as resources for setting fonts, some colour resources, and resources that can set a particular cursor for a widget.
We shall first treat the underlying concepts. After that, in section 6, the mysteries of the resources and widgets themselves will be unraveled.
So, off we go. The subject: pixmaps and bitmaps.
A pixmap is an area of memory that contains an image. In the X Window System, one can use the same functions to draw in both windows and pixmaps; both windows and pixmaps are so-called drawables.
A bitmap is a pixmap, but the colour depth of a bitmap is 1. That means that it only uses one bit per pixel, so that a bitmap is a black-and-white image.
From now on, unless explicitly stated otherwise, 'pixmap' will refer to both pixmaps and bitmaps.
Pixmaps have many uses in the X Window System. They can be used as icons, as cursors, as fill patterns, and as many other things as well. In this section, we shall find out how to create and modify pixmaps, and how to use them as resources for widgets.
The first thing we need to do in order to create a pixmap is reserving space for it on the X server. This can be done with the XCreatePixmap function. Its prototype is as follows:
Pixmap XCreatePixmap (Display *display,
Drawable d,
unsigned int width,
unsigned int height,
unsigned int depth)
If we have a pixmap that is no longer needed, we can return the space it occupies to the X server. This is done using XFreePixmap (display, pixmap), where display is the display that the pixmap pixmap is associated with.
A bitmap is, as said before, a pixmap with a depth of 1. As every screen has a depth of at least 1, bitmaps can be used everywhere.
It is very probable that a program named bitmap exists on your system. With this program, you can create bitmaps, store them in files, read bitmap files, etcetera.
The standard format for storing bitmaps is a text file with C code in it that defines an array containing the values for the bitmap. It looks like this:
#define name_width www
#define name_height xxx
#define name_x_hot yyy
#define name_y_hot zzz
static char name_bits[] = {
...
}
In this, name has to be replaced by the name of the bitmap (bitmap calls this its basename). www through zzz also have to be replaced by proper values. The purpose of name_width and name_height seem clear; the purpose of name_x_hot and name_y_hot is to define the hot spot of the bitmap.
A hot spot is necessary only when the bitmap is used as a cursor. The hot spot will in this case be the exact pixel that the cursor points to.
The array name_bits contains the bitmap itself. It consists of xxx numbers, the bit patterns of which represent one line of the bitmap.
An example might be useful. Suppose that we have the following bitmap, named cross:
1 0 0 0 0 0 0 1 0 1 0 0 0 0 1 0 0 0 1 0 0 1 0 0 0 0 0 1 1 0 0 0 0 0 0 1 1 0 0 0 0 0 1 0 0 1 0 0 0 1 0 0 0 0 1 0 1 0 0 0 0 0 0 1
Its bitmap file would look like this:
#define cross_width 8
#define cross_height 8
static char name_bits[] = {
0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81};
If the bitmap is wider than 8 pixels, more numbers are used to define one line. For example in this standard X bitmap, xlogo16, two numbers are used for every line:
#define xlogo16_width 16
#define xlogo16_height 16
static char xlogo16_bits[] = {
0x0f, 0x80, 0x1e, 0x80, 0x3c, 0x40, 0x78, 0x20, 0x78, 0x10, 0xf0, 0x08,
0xe0, 0x09, 0xc0, 0x05, 0xc0, 0x02, 0x40, 0x07, 0x20, 0x0f, 0x20, 0x1e,
0x10, 0x1e, 0x08, 0x3c, 0x04, 0x78, 0x02, 0xf0};
We see here that it is not necessary for a bitmap to have a hot spot.
Due to the nature of a bitmap file, there are two methods of using a bitmap file in your program. You can either just include it (using #include) and use the XCreateBitmapFromData function to register the bitmap, or use the XReadBitmapFile function to register the bitmap directly from the bitmap file.
Obviously, the first method is useful for bitmaps that you want to be accessible no matter what (for example standard cursors for your program), and the second method can be used for bitmaps that are variable (for a bitmap viewing program, for example).
First, an example of the include method. Suppose we want to use xlogo16 somewhere. This is a standard X11 bitmap, which means that it can be found in /usr/local/X11/include/bitmaps (where, as always, you have to replace /usr/local/X11 with your own X install ation directory). We simply include it and use XCreateBitmapFromData:
#include <X11/bitmaps/xlogo16>
(...)
Pixmap xlogo16;
int main (int argc, char **argv)
{
Widget w;
(...)
xlogo16 = XCreateBitmapFromData (XtDisplay (w), RootWindowOfScreen (XtScreen
(w)), xlogo16_bits, xlogo16_width,
xlogo16_height);
(...)
}
The parameters for XCreateBitmapFromData are straightforward: a display, a screen, an array of bitmap data and bitmap width and height.
If we wanted to read xlogo16 using XReadBitmapFile, we would proceed as follows:
(...)
Pixmap xlogo16;
unsigned int width, height, x_hot, y_hot;
int main (int args, char **argv)
{ Widget w;
(...)
XReadBitmapFile (XtDisplay (w), RootWindowOfScreen (XtScreen (w)),
"/usr/local/X11/include/bitmaps/xlogo16", &width,
&height, &xlogo16, &x_hot, &y_hot);
(...)
}
Values for width, height, xlogo16, x_hot and y_hot will be filled in from the file. If there is no hot spot, both x_hot and y_hot will have the value -1.
It is also possible to write a given bitmap to a file with, not surprisingly, the XWriteBitmapFile function. It has the same parameters as XReadBitmapFile, with the exception that the last five parameters are not pointers that are filled in from the file, but values that are used to fill the file. If we want to store a bitmap that has no hot spot, the values of the last two parameters should be -1.
Finally, it is also possible to convert a bitmap to a pixmap. This pixmap will only have two colours (not necessarily black and white), but it can be of any colour depth.
For this conversion, the XCreatePixmapFromBitmapData function is used. Its parameters, in order:
The function returns a pixmap.
Reading pixmaps from files and writing them to files is not possible with standard X libraries. For that, you need the Xpm library, which is installed by default on many systems.
Here is an example of a pixmap (XPM) file (a 16-by-16 Union Jack):
/* XPM */
static char * english_flag_xpm[] = {
"16 16 3 1",
" c #FFFF00000000",
". c #FFFFFFFFFFFF",
"X c #00000000FFFF",
" .XXXX. .XXXX. ",
". .XXX. .XXX. .",
"X. .XX. .XX. .X",
"XX. .X. .X. .XX",
"XXX. .. .. .XXX",
"XXXX. . . .XXXX",
"...... ......",
" ",
" ",
"...... ......",
"XXXX. . . .XXXX",
"XXX. .. .. .XXX",
"XX. .X. .X. .XX",
"X. .XX. .XX. .X",
". .XXX. .XXX. .",
" .XXXX. .XXXX. "};
The first string (16 16 3 1) contains, in order, the pixmap's width and height, the number of colours in the pixmap and the number of characters per colour.
Then follows a mapping from colours to characters; in this case, the space is mapped to red, the dot to white and the X to blue.
And after that comes the data, one string for every line and one character for every pixel.
So we see that, like bitmap files, we can use pixmap files in two ways. Here is an example of the include method:
#include <X11/xpm.h>
#include <random/pixmap/file.xpm>
(...)
Pixmap random_pixmap, shape;
XpmAttributes attributes;
int main (int argc, char **argv)
{ Widget w;
(...)
XpmCreatePixmapFromData (XtDisplay (w), RootWindowOfScreen (XtScreen (w)),
english_flag_xpm, &random_pixmap, &shape,
&attributes);
(...)
}
The parameters for XpmCreatePixmapFromData are almost the same as for XCreateBitmapFromData: a display, a drawable, an array containing the pixmap data, a pointer to the pixmap that should be created, a pointer to the shape mask, which I gather can be used for transparent imaged, and a pointer to a structure with attributes, which include height, width and hotspot.
The file method works similarly:
(...)
Pixmap random_pixmap, shape;
XpmAttributes attributes;
int main (int argc, char **argv)
{ Widget w;
(...)
XpmReadFileToPixmap (XtDisplay (w), RootWindowOfScreen (XtScreen (w)),
"random/pixmap/file.xpm", &random_pixmap, &shape,
&attributes);
(..)
}
There is also a function named XpmWriteFileFromPixmap, which has exactly the parameters one would suspect: a display, a filename, the pixmap, the shape mask, and a pointer to the attributes.
For more information on the Xpm library, you should read the Xpm manual.
Last updated: January 31, 2003 by Jaap Boender