GTK+
The GIMP Toolkit
|
Pixmaps are data structures that contain pictures. These pictures can
be used in various places, but most commonly as icons on the X
desktop, or as cursors. A pixmap which only has 2 colors is called a bitmap, and there are a
few additional routines for handling this common special case. To understand pixmaps, it would help to understand how X window
system works. Under X, applications do not need to be running on the
same computer that is interacting with the user. Instead, the various
applications, called "clients", all communicate with a program which
displays the graphics and handles the keyboard and mouse. This
program which interacts directly with the user is called a "display
server" or "X server." Since the communication might take place over
a network, it's important to keep some information with the X server.
Pixmaps, for example, are stored in the memory of the X server. This
means that once pixmap values are set, they don't need to keep getting
transmitted over the network; instead a command is sent to "display
pixmap number XYZ here." Even if you aren't using X with GTK
currently, using constructs such as Pixmaps will make your programs
work acceptably under X. To use pixmaps in GTK, we must first build a GdkPixmap structure using
routines from the GDK layer. Pixmaps can either be created from
in-memory data, or from data read from a file. We'll go through each
of the calls to create a pixmap. GdkPixmap *gdk_bitmap_create_from_data( GdkWindow *window,
gchar *data,
gint width,
gint height ); |
This routine is used to create a single-plane pixmap (2 colors) from
data in memory. Each bit of the data represents whether that pixel is
off or on. Width and height are in pixels. The GdkWindow pointer is to
the current window, since a pixmap's resources are meaningful only in
the context of the screen where it is to be displayed. GdkPixmap *gdk_pixmap_create_from_data( GdkWindow *window,
gchar *data,
gint width,
gint height,
gint depth,
GdkColor *fg,
GdkColor *bg ); |
This is used to create a pixmap of the given depth (number of colors) from
the bitmap data specified. fg and bg are the foreground and
background color to use. GdkPixmap *gdk_pixmap_create_from_xpm( GdkWindow *window,
GdkBitmap **mask,
GdkColor *transparent_color,
const gchar *filename ); |
XPM format is a readable pixmap representation for the X Window
System. It is widely used and many different utilities are available
for creating image files in this format. The file specified by
filename must contain an image in that format and it is loaded into
the pixmap structure. The mask specifies which bits of the pixmap are
opaque. All other bits are colored using the color specified by
transparent_color. An example using this follows below. GdkPixmap *gdk_pixmap_create_from_xpm_d( GdkWindow *window,
GdkBitmap **mask,
GdkColor *transparent_color,
gchar **data ); |
Small images can be incorporated into a program as data in the XPM
format. A pixmap is created using this data, instead of reading it
from a file. An example of such data is /* XPM */
static const char * xpm_data[] = {
"16 16 3 1",
" c None",
". c #000000000000",
"X c #FFFFFFFFFFFF",
" ",
" ...... ",
" .XXX.X. ",
" .XXX.XX. ",
" .XXX.XXX. ",
" .XXX..... ",
" .XXXXXXX. ",
" .XXXXXXX. ",
" .XXXXXXX. ",
" .XXXXXXX. ",
" .XXXXXXX. ",
" .XXXXXXX. ",
" .XXXXXXX. ",
" ......... ",
" ",
" "}; |
When we're done using a pixmap and not likely to reuse it again soon,
it is a good idea to release the resource using
gdk_pixmap_unref(). Pixmaps should be considered a precious resource,
because they take up memory in the end-user's X server process. Even
though the X client you write may run on a powerful "server" computer,
the user may be running the X server on a small personal computer. Once we've created a pixmap, we can display it as a GTK widget. We
must create a GTK pixmap widget to contain the GDK pixmap. This is
done using GtkWidget *gtk_pixmap_new( GdkPixmap *pixmap,
GdkBitmap *mask ); |
The other pixmap widget calls are guint gtk_pixmap_get_type( void );
void gtk_pixmap_set( GtkPixmap *pixmap,
GdkPixmap *val,
GdkBitmap *mask );
void gtk_pixmap_get( GtkPixmap *pixmap,
GdkPixmap **val,
GdkBitmap **mask); |
gtk_pixmap_set is used to change the pixmap that the widget is currently
managing. Val is the pixmap created using GDK. The following is an example of using a pixmap in a button. /* example-start pixmap pixmap.c */
#include <gtk/gtk.h>
/* XPM data of Open-File icon */
static const char * xpm_data[] = {
"16 16 3 1",
" c None",
". c #000000000000",
"X c #FFFFFFFFFFFF",
" ",
" ...... ",
" .XXX.X. ",
" .XXX.XX. ",
" .XXX.XXX. ",
" .XXX..... ",
" .XXXXXXX. ",
" .XXXXXXX. ",
" .XXXXXXX. ",
" .XXXXXXX. ",
" .XXXXXXX. ",
" .XXXXXXX. ",
" .XXXXXXX. ",
" ......... ",
" ",
" "};
/* when invoked (via signal delete_event), terminates the application.
*/
gint close_application( GtkWidget *widget,
GdkEvent *event,
gpointer data )
{
gtk_main_quit();
return(FALSE);
}
/* is invoked when the button is clicked. It just prints a message.
*/
void button_clicked( GtkWidget *widget,
gpointer data ) {
g_print( "button clicked\n" );
}
int main( int argc,
char *argv[] )
{
/* GtkWidget is the storage type for widgets */
GtkWidget *window, *pixmapwid, *button;
GdkPixmap *pixmap;
GdkBitmap *mask;
GtkStyle *style;
/* create the main window, and attach delete_event signal to terminating
the application */
gtk_init( &argc, &argv );
window = gtk_window_new( GTK_WINDOW_TOPLEVEL );
gtk_signal_connect( GTK_OBJECT (window), "delete_event",
GTK_SIGNAL_FUNC (close_application), NULL );
gtk_container_set_border_width( GTK_CONTAINER (window), 10 );
gtk_widget_show( window );
/* now for the pixmap from gdk */
style = gtk_widget_get_style( window );
pixmap = gdk_pixmap_create_from_xpm_d( window->window, &mask,
&style->bg[GTK_STATE_NORMAL],
(gchar **)xpm_data );
/* a pixmap widget to contain the pixmap */
pixmapwid = gtk_pixmap_new( pixmap, mask );
gtk_widget_show( pixmapwid );
/* a button to contain the pixmap widget */
button = gtk_button_new();
gtk_container_add( GTK_CONTAINER(button), pixmapwid );
gtk_container_add( GTK_CONTAINER(window), button );
gtk_widget_show( button );
gtk_signal_connect( GTK_OBJECT(button), "clicked",
GTK_SIGNAL_FUNC(button_clicked), NULL );
/* show the window */
gtk_main ();
return 0;
}
/* example-end */ |
To load a file from an XPM data file called icon0.xpm in the current
directory, we would have created the pixmap thus /* load a pixmap from a file */
pixmap = gdk_pixmap_create_from_xpm( window->window, &mask,
&style->bg[GTK_STATE_NORMAL],
"./icon0.xpm" );
pixmapwid = gtk_pixmap_new( pixmap, mask );
gtk_widget_show( pixmapwid );
gtk_container_add( GTK_CONTAINER(window), pixmapwid ); |
A disadvantage of using pixmaps is that the displayed object is always
rectangular, regardless of the image. We would like to create desktops
and applications with icons that have more natural shapes. For
example, for a game interface, we would like to have round buttons to
push. The way to do this is using shaped windows. A shaped window is simply a pixmap where the background pixels are
transparent. This way, when the background image is multi-colored, we
don't overwrite it with a rectangular, non-matching border around our
icon. The following example displays a full wheelbarrow image on the
desktop. /* example-start wheelbarrow wheelbarrow.c */
#include <gtk/gtk.h>
/* XPM */
static char * WheelbarrowFull_xpm[] = {
"48 48 64 1",
" c None",
". c #DF7DCF3CC71B",
"X c #965875D669A6",
"o c #71C671C671C6",
"O c #A699A289A699",
"+ c #965892489658",
"@ c #8E38410330C2",
"# c #D75C7DF769A6",
"$ c #F7DECF3CC71B",
"% c #96588A288E38",
"& c #A69992489E79",
"* c #8E3886178E38",
"= c #104008200820",
"- c #596510401040",
"; c #C71B30C230C2",
": c #C71B9A699658",
"> c #618561856185",
", c #20811C712081",
"< c #104000000000",
"1 c #861720812081",
"2 c #DF7D4D344103",
"3 c #79E769A671C6",
"4 c #861782078617",
"5 c #41033CF34103",
"6 c #000000000000",
"7 c #49241C711040",
"8 c #492445144924",
"9 c #082008200820",
"0 c #69A618611861",
"q c #B6DA71C65144",
"w c #410330C238E3",
"e c #CF3CBAEAB6DA",
"r c #71C6451430C2",
"t c #EFBEDB6CD75C",
"y c #28A208200820",
"u c #186110401040",
"i c #596528A21861",
"p c #71C661855965",
"a c #A69996589658",
"s c #30C228A230C2",
"d c #BEFBA289AEBA",
"f c #596545145144",
"g c #30C230C230C2",
"h c #8E3882078617",
"j c #208118612081",
"k c #38E30C300820",
"l c #30C2208128A2",
"z c #38E328A238E3",
"x c #514438E34924",
"c c #618555555965",
"v c #30C2208130C2",
"b c #38E328A230C2",
"n c #28A228A228A2",
"m c #41032CB228A2",
"M c #104010401040",
"N c #492438E34103",
"B c #28A2208128A2",
"V c #A699596538E3",
"C c #30C21C711040",
"Z c #30C218611040",
"A c #965865955965",
"S c #618534D32081",
"D c #38E31C711040",
"F c #082000000820",
" ",
" .XoO ",
" +@#$%o& ",
" *=-;#::o+ ",
" >,<12#:34 ",
" 45671#:X3 ",
" +89<02qwo ",
"e* >,67;ro ",
"ty> 459@>+&& ",
"$2u+ ><ipas8* ",
"%$;=* *3:.Xa.dfg> ",
"Oh$;ya *3d.a8j,Xe.d3g8+ ",
" Oh$;ka *3d$a8lz,,xxc:.e3g54 ",
" Oh$;kO *pd$%svbzz,sxxxxfX..&wn> ",
" Oh$@mO *3dthwlsslszjzxxxxxxx3:td8M4 ",
" Oh$@g& *3d$XNlvvvlllm,mNwxxxxxxxfa.:,B* ",
" Oh$@,Od.czlllllzlmmqV@V#V@fxxxxxxxf:%j5& ",
" Oh$1hd5lllslllCCZrV#r#:#2AxxxxxxxxxcdwM* ",
" OXq6c.%8vvvllZZiqqApA:mq:Xxcpcxxxxxfdc9* ",
" 2r<6gde3bllZZrVi7S@SV77A::qApxxxxxxfdcM ",
" :,q-6MN.dfmZZrrSS:#riirDSAX@Af5xxxxxfevo",
" +A26jguXtAZZZC7iDiCCrVVii7Cmmmxxxxxx%3g",
" *#16jszN..3DZZZZrCVSA2rZrV7Dmmwxxxx&en",
" p2yFvzssXe:fCZZCiiD7iiZDiDSSZwwxx8e*>",
" OA1<jzxwwc:$d%NDZZZZCCCZCCZZCmxxfd.B ",
" 3206Bwxxszx%et.eaAp77m77mmmf3&eeeg* ",
" @26MvzxNzvlbwfpdettttttttttt.c,n& ",
" *;16=lsNwwNwgsvslbwwvccc3pcfu<o ",
" p;<69BvwwsszslllbBlllllllu<5+ ",
" OS0y6FBlvvvzvzss,u=Blllj=54 ",
" c1-699Blvlllllu7k96MMMg4 ",
" *10y8n6FjvllllB<166668 ",
" S-kg+>666<M<996-y6n<8* ",
" p71=4 m69996kD8Z-66698&& ",
" &i0ycm6n4 ogk17,0<6666g ",
" N-k-<> >=01-kuu666> ",
" ,6ky& &46-10ul,66, ",
" Ou0<> o66y<ulw<66& ",
" *kk5 >66By7=xu664 ",
" <<M4 466lj<Mxu66o ",
" *>> +66uv,zN666* ",
" 566,xxj669 ",
" 4666FF666> ",
" >966666M ",
" oM6668+ ",
" *4 ",
" ",
" "};
/* When invoked (via signal delete_event), terminates the application */
gint close_application( GtkWidget *widget,
GdkEvent *event,
gpointer data )
{
gtk_main_quit();
return(FALSE);
}
int main (int argc,
char *argv[] )
{
/* GtkWidget is the storage type for widgets */
GtkWidget *window, *pixmap, *fixed;
GdkPixmap *gdk_pixmap;
GdkBitmap *mask;
GtkStyle *style;
GdkGC *gc;
/* Create the main window, and attach delete_event signal to terminate
* the application. Note that the main window will not have a titlebar
* since we're making it a popup. */
gtk_init (&argc, &argv);
window = gtk_window_new( GTK_WINDOW_POPUP );
gtk_signal_connect (GTK_OBJECT (window), "delete_event",
GTK_SIGNAL_FUNC (close_application), NULL);
gtk_widget_show (window);
/* Now for the pixmap and the pixmap widget */
style = gtk_widget_get_default_style();
gc = style->black_gc;
gdk_pixmap = gdk_pixmap_create_from_xpm_d( window->window, &mask,
&style->bg[GTK_STATE_NORMAL],
WheelbarrowFull_xpm );
pixmap = gtk_pixmap_new( gdk_pixmap, mask );
gtk_widget_show( pixmap );
/* To display the pixmap, we use a fixed widget to place the pixmap */
fixed = gtk_fixed_new();
gtk_widget_set_usize( fixed, 200, 200 );
gtk_fixed_put( GTK_FIXED(fixed), pixmap, 0, 0 );
gtk_container_add( GTK_CONTAINER(window), fixed );
gtk_widget_show( fixed );
/* This masks out everything except for the image itself */
gtk_widget_shape_combine_mask( window, mask, 0, 0 );
/* show the window */
gtk_widget_set_uposition( window, 20, 400 );
gtk_widget_show( window );
gtk_main ();
return(0);
}
/* example-end */ |
To make the wheelbarrow image sensitive, we could attach the button
press event signal to make it do something. The following few lines
would make the picture sensitive to a mouse button being pressed which
makes the application terminate. gtk_widget_set_events( window,
gtk_widget_get_events( window ) |
GDK_BUTTON_PRESS_MASK );
gtk_signal_connect( GTK_OBJECT(window), "button_press_event",
GTK_SIGNAL_FUNC(close_application), NULL ); |
|