Xdrawstring not drawing text on Pixmap

Hi,

I have recently started x and motif programming and I am trying to write something in a pixmap created using XCreatePixmap but I don't know why is there no valid and correct output for the text. Here is my code through which i am trying to write to the pixmap, BTW there is not graphic card on the system so i am using virtual frame buffer xvfb for drawin.

The thing is when i do XWriteBitmapFile (display, "drawing.xpm", pix, width, height, -1, -1); after doing everything on the pixmap instead of window -- the pixmap generated is not valid?

Anybody can help me with how to generate bitmap or pixmap file from the background rendering pixmap?

///////
Code :
///////

Display *display;
int screen;
Pixmap pix, icon_pixmap;
Window win;

void main(int argc, char **argv)
{
unsigned int width, height, display_width, display_height, display_depth;
int x = 0, y = 0;
unsigned int border_width = 4;
char *window_name = "Basic Window Program";
char *icon_name = "basicwin";

XSizeHints size_hints;
XEvent report;
GC gc;
XFontStruct *font_info;
char display_name[256];
if (argc > 1)
strcpy(display_name, argv[1]);
else
strcpy(display_name, ":0");

int window_size = 0;
int status = 0;

if ((display=XOpenDisplay(display_name)) == NULL)
{
fprintf(stderr,"basicwin: cannot connect to X server %s\n",
XDisplayName(display_name));
exit(-1);
}

screen = DefaultScreen(display);

display_width = 400;//DisplayWidth(display,screen);
display_height = 400;//DisplayHeight(display,screen);
display_depth = DefaultDepth(display,screen);

width = display_width;
height = display_height;

pix = XCreatePixmap(display, DefaultRootWindow(display), width, height, display_depth);

load_font(&font_info);
get_GC(pix, &gc, font_info);
draw_text(pix, gc, font_info, width, height);
draw_graphics(pix, gc, width, height);

const int inBufSize = 1024*1024*4;
unsigned char *inBuf = new unsigned char [inBufSize];

status = XWriteBitmapFile (display, "drawing.xpm", pix, width, height, -1, -1);
if (status != BitmapSuccess)
{
printf("\nCan't write the pixmap");
}

XUnloadFont(display, font_info->fid);
XFreeGC(display, gc);
XFreePixmap(display, pix);
XCloseDisplay(display);
}

////////////////////////////////////
Drawing on pixmap methods
/////////////////////////////////////
void draw_text(Pixmap win, GC gc, XFontStruct *font_info, unsigned int win_width, int win_height)
{
int y = 20;
char *string1 = "Hi! I'm a window, who are you?";
char *string2 = "To terminate program; Press any key";
char *string3 = "or button while in this window.";
char *string4 = "Screen Dimensions:";
int len1, len2, len3, len4;
int width1, width2, width3;
char cd_height[50], cd_width[50], cd_depth[50];
int font_height;
int y_offset, x_offset;

len1 = strlen(string1);
len2 = strlen(string2);
len3 = strlen(string3);

width1 = XTextWidth(font_info, string1, len1);
width2 = XTextWidth(font_info, string2, len2);
width3 = XTextWidth(font_info, string3, len3);

XDrawString(display, win, gc, (win_width-width1)/2, y, string1, len1);
XDrawString(display, win, gc, (win_width-width2)/2, (int)(win_height-35), string2, len2);
XDrawString(display, win, gc, (win_width-width3)/2, (int)(win_height-15), string3, len3);

sprintf(cd_height,"Height - %d pixels", DisplayHeight(display,screen));
sprintf(cd_width,"Width - %d pixels", DisplayWidth(display,screen));
sprintf(cd_depth,"Depth - %d plane(s)", DefaultDepth(display,screen));

len4 = strlen(string4);
len1 = strlen(cd_height);
len2 = strlen(cd_width);
len3 = strlen(cd_depth);

font_height = font_info->max_bounds.ascent +
font_info->max_bounds.descent;

y_offset = win_height/2 - font_height - font_info->max_bounds.descent;
x_offset = (int) win_width/4;

XDrawString(display, win, gc, x_offset, y_offset, string4, len4);
y_offset += font_height;

XDrawString(display, win, gc, x_offset, y_offset, cd_height, len1);
y_offset += font_height;

XDrawString(display, win, gc, x_offset, y_offset, cd_width, len2);
y_offset += font_height;

XDrawString(display, win, gc, x_offset, y_offset, cd_depth, len3);
}

void draw_graphics(Pixmap win, GC gc, unsigned int window_width, unsigned int window_height)
{
int x,y;
unsigned int width, height;

height = window_height/2;
width = 3 * window_width/4;

x = window_width/2 - width/2;
y = window_height/2 - height/2;

XDrawRectangle(display, win, gc, x, y, width, height);
}

void get_GC(Pixmap win, GC *gc, XFontStruct *font_info)
{
unsigned long valuemask = 0;
XGCValues values;
unsigned int line_width = 1;
int line_style = LineSolid; /*LineOnOffDash;*/
int cap_style = CapButt;
int join_style = JoinMiter;
int dash_offset = 0;
static char dash_list[] = {20, 40};
int list_length = sizeof(dash_list);

*gc = XCreateGC(display, win, valuemask, &values);

XSetFont(display, *gc, font_info->fid);

XSetForeground(display, *gc, BlackPixel(display,screen));

XSetLineAttributes(display, *gc, line_width, line_style, cap_style, join_style);

XSetDashes(display, *gc, dash_offset, dash_list, list_length);
}

void load_font(XFontStruct **font_info)
{
char *fontname = "9x15";

if ((*font_info=XLoadQueryFont(display,fontname)) == NULL)
{
printf("stderr, basicwin: cannot open 9x15 font\n");
exit(-1);
}
}

Best regards,
RUI


rui

rui's picture

Re: Xdrawstring not drawing text on Pixmap

Here is the compilable code -- any help would be greatly appreciated.

#include
#include
#include

#include

Display *display;
int screen;

#define icon_bitmap_width 20
#define icon_bitmap_height 20
static unsigned char icon_bitmap_bits[] = {
0x60, 0x00, 0x01, 0xb0, 0x00, 0x07, 0x0c, 0x03, 0x00, 0x04, 0x04, 0x00,
0xc2, 0x18, 0x00, 0x03, 0x30, 0x00, 0x01, 0x60, 0x00, 0xf1, 0xdf, 0x00,
0xc1, 0xf0, 0x01, 0x82, 0x01, 0x00, 0x02, 0x03, 0x00, 0x02, 0x0c, 0x00,
0x02, 0x38, 0x00, 0x04, 0x60, 0x00, 0x04, 0xe0, 0x00, 0x04, 0x38, 0x00,
0x84, 0x06, 0x00, 0x14, 0x14, 0x00, 0x0c, 0x34, 0x00, 0x00, 0x00, 0x00};

void main(argc, argv)
int argc;
char **argv;
{
Pixmap pix, icon_pixmap;
Window win;
unsigned int width, height, display_width, display_height, display_depth;
int x = 0, y = 0;
unsigned int border_width = 4;
char *window_name = "Basic Window Program";
char *icon_name = "basicwin";

XSizeHints size_hints;
XEvent report;
GC gc;
XFontStruct *font_info;
char *display_name = "localhost:1";

int window_size = 0;
int status = 0;

if ((display=XOpenDisplay(display_name)) == NULL)
{
fprintf(stderr,"basicwin: cannot connect to X server %s\n",
XDisplayName(display_name));
exit(-1);
}

screen = DefaultScreen(display);

display_width = 400;//DisplayWidth(display,screen);
display_height = 400;//DisplayHeight(display,screen);
display_depth = DefaultDepth(display,screen);

width = display_width;
height = display_height;

pix = XCreatePixmap(display, DefaultRootWindow(display), width, height, display_depth);

icon_pixmap = XCreateBitmapFromData(display, DefaultRootWindow(display),
icon_bitmap_bits, icon_bitmap_width, icon_bitmap_height);

load_font(&font_info);
get_GC(pix, &gc, font_info);
draw_text(pix, gc, font_info, width, height);
draw_graphics(pix, gc, width, height);

status = XWriteBitmapFile (display, "drawing.xpm", pix, width, height, -1, -1);
if (status != BitmapSuccess)
{
printf("\nCan't write the pixmap");
}

XUnloadFont(display, font_info->fid);
XFreeGC(display, gc);
XFreePixmap(display, pix);
XCloseDisplay(display);
}

get_GC(win, gc, font_info)
Pixmap win;
GC *gc;
XFontStruct *font_info;
{
unsigned long valuemask = 0;
XGCValues values;
unsigned int line_width = 1;
int line_style = LineSolid; /*LineOnOffDash;*/
int cap_style = CapButt;
int join_style = JoinMiter;
int dash_offset = 0;
static char dash_list[] = {20, 40};
int list_length = sizeof(dash_list);

*gc = XCreateGC(display, win, valuemask, &values);

XSetFont(display, *gc, font_info->fid);

XSetForeground(display, *gc, BlackPixel(display,screen));
XSetLineAttributes(display, *gc, line_width, line_style, cap_style, join_style);
XSetDashes(display, *gc, dash_offset, dash_list, list_length);
}

load_font(font_info)
XFontStruct **font_info;
{
char *fontname = "9x15";

if ((*font_info=XLoadQueryFont(display,fontname)) == NULL)
{
printf("stderr, basicwin: cannot open 9x15 font\n");
exit(-1);
}
}

draw_text(win, gc, font_info, win_width, win_height)
Pixmap win;
GC gc;
XFontStruct *font_info;
unsigned int win_width, win_height;
{
int y = 20;
char *string1 = "Hi! I'm a window, who are you?";
char *string2 = "To terminate program; Press any key";
char *string3 = "or button while in this window.";
char *string4 = "Screen Dimensions:";
int len1, len2, len3, len4;
int width1, width2, width3;
char cd_height[50], cd_width[50], cd_depth[50];
int font_height;
int y_offset, x_offset;

len1 = strlen(string1);
len2 = strlen(string2);
len3 = strlen(string3);

width1 = XTextWidth(font_info, string1, len1);
width2 = XTextWidth(font_info, string2, len2);
width3 = XTextWidth(font_info, string3, len3);

XDrawString(display, win, gc, (win_width-width1)/2, y, string1, len1);
XDrawString(display, win, gc, (win_width-width2)/2, (int)(win_height-35), string2, len2);
XDrawString(display, win, gc, (win_width-width3)/2, (int)(win_height-15), string3, len3);

sprintf(cd_height,"Height - %d pixels", DisplayHeight(display,screen));
sprintf(cd_width,"Width - %d pixels", DisplayWidth(display,screen));
sprintf(cd_depth,"Depth - %d plane(s)", DefaultDepth(display,screen));

len4 = strlen(string4);
len1 = strlen(cd_height);
len2 = strlen(cd_width);
len3 = strlen(cd_depth);

font_height = font_info->max_bounds.ascent +
font_info->max_bounds.descent;

y_offset = win_height/2 - font_height - font_info->max_bounds.descent;
x_offset = (int) win_width/4;

XDrawString(display, win, gc, x_offset, y_offset, string4, len4);
y_offset += font_height;

XDrawString(display, win, gc, x_offset, y_offset, cd_height, len1);
y_offset += font_height;

XDrawString(display, win, gc, x_offset, y_offset, cd_width, len2);
y_offset += font_height;

XDrawString(display, win, gc, x_offset, y_offset, cd_depth, len3);
}

draw_graphics(win, gc, window_width, window_height)
Pixmap win;
GC gc;
unsigned int window_width, window_height;
{
int x,y;
unsigned int width, height;

height = window_height/2;
width = 3 * window_width/4;

x = window_width/2 - width/2;
y = window_height/2 - height/2;

XDrawRectangle(display, win, gc, x, y, width, height);
}


vtorshyn

vtorshyn's picture

Re: Xdrawstring not drawing text on Pixmap

Hi rui,

The reason of the bad pixmap is not initializing data in the pixmap (in your case garbage on the pixmap).
Please try to use XFillRectangle() (or similar) function to initialize pixels by foreground values values data before drawing the text.

Here is slightly modified example with XFillRectangle():

#include
#include
#include

#include

Display *display;
int screen;

#define icon_bitmap_width 20
#define icon_bitmap_height 20
static unsigned char icon_bitmap_bits[] = {
0x60, 0x00, 0x01, 0xb0, 0x00, 0x07, 0x0c, 0x03, 0x00, 0x04, 0x04, 0x00,
0xc2, 0x18, 0x00, 0x03, 0x30, 0x00, 0x01, 0x60, 0x00, 0xf1, 0xdf, 0x00,
0xc1, 0xf0, 0x01, 0x82, 0x01, 0x00, 0x02, 0x03, 0x00, 0x02, 0x0c, 0x00,
0x02, 0x38, 0x00, 0x04, 0x60, 0x00, 0x04, 0xe0, 0x00, 0x04, 0x38, 0x00,
0x84, 0x06, 0x00, 0x14, 0x14, 0x00, 0x0c, 0x34, 0x00, 0x00, 0x00, 0x00};

int main(argc, argv)
int argc;
char **argv;
{
Pixmap pix, icon_pixmap;
Window win;
unsigned int width, height, display_width, display_height, display_depth;
int x = 0, y = 0;
unsigned int border_width = 4;
char *window_name = "Basic Window Program";
char *icon_name = "basicwin";

XSizeHints size_hints;
XEvent report;
GC gc;
XFontStruct *font_info;
char *display_name = ":0";

int window_size = 0;
int status = 0;

if ((display=XOpenDisplay(display_name)) == NULL)
{
fprintf(stderr,"basicwin: cannot connect to X server %s\n",
XDisplayName(display_name));
exit(-1);
}

screen = DefaultScreen(display);

display_width = 400;//DisplayWidth(display,screen);
display_height = 400;//DisplayHeight(display,screen);
display_depth = DefaultDepth(display,screen);

width = display_width;
height = display_height;

pix = XCreatePixmap(display, DefaultRootWindow(display), width, height, display_depth);

icon_pixmap = XCreateBitmapFromData(display, DefaultRootWindow(display),
icon_bitmap_bits, icon_bitmap_width, icon_bitmap_height);

load_font(&font_info);
get_GC(pix, &gc, font_info);
XSetForeground(display, gc, WhitePixel(display,screen)); // Set foreground before filling the rectanlge
XFillRectangle(display, pix, gc, 0, 0, width, height); // Fill rectangle
XSetForeground(display, gc, BlackPixel(display,screen)); // Restore foreground pixel
draw_text(pix, gc, font_info, width, height);
draw_graphics(pix, gc, width, height);

status = XWriteBitmapFile (display, "drawing.xpm", pix, width, height, -1, -1);
if (status != BitmapSuccess)
{
printf("\nCan't write the pixmap");
}

XUnloadFont(display, font_info->fid);
XFreeGC(display, gc);
XFreePixmap(display, pix);
XCloseDisplay(display);
}

get_GC(win, gc, font_info)
Pixmap win;
GC *gc;
XFontStruct *font_info;
{
unsigned long valuemask = 0;
XGCValues values;
unsigned int line_width = 1;
int line_style = LineSolid; /*LineOnOffDash;*/
int cap_style = CapButt;
int join_style = JoinMiter;
int dash_offset = 0;
static char dash_list[] = {20, 40};
int list_length = sizeof(dash_list);

*gc = XCreateGC(display, win, valuemask, &values);

XSetFont(display, *gc, font_info->fid);

XSetForeground(display, *gc, BlackPixel(display,screen));
XSetLineAttributes(display, *gc, line_width, line_style, cap_style, join_style);
XSetDashes(display, *gc, dash_offset, dash_list, list_length);
}

load_font(font_info)
XFontStruct **font_info;
{
char *fontname = "9x15";

if ((*font_info=XLoadQueryFont(display,fontname)) == NULL)
{
printf("stderr, basicwin: cannot open 9x15 font\n");
exit(-1);
}
}

draw_text(win, gc, font_info, win_width, win_height)
Pixmap win;
GC gc;
XFontStruct *font_info;
unsigned int win_width, win_height;
{
int y = 20;
char *string1 = "Hi! I'm a window, who are you?";
char *string2 = "To terminate program; Press any key";
char *string3 = "or button while in this window.";
char *string4 = "Screen Dimensions:";
int len1, len2, len3, len4;
int width1, width2, width3;
char cd_height[50], cd_width[50], cd_depth[50];
int font_height;
int y_offset, x_offset;

len1 = strlen(string1);
len2 = strlen(string2);
len3 = strlen(string3);

width1 = XTextWidth(font_info, string1, len1);
width2 = XTextWidth(font_info, string2, len2);
width3 = XTextWidth(font_info, string3, len3);

XDrawString(display, win, gc, (win_width-width1)/2, y, string1, len1);
XDrawString(display, win, gc, (win_width-width2)/2, (int)(win_height-35), string2, len2);
XDrawString(display, win, gc, (win_width-width3)/2, (int)(win_height-15), string3, len3);

sprintf(cd_height,"Height - %d pixels", DisplayHeight(display,screen));
sprintf(cd_width,"Width - %d pixels", DisplayWidth(display,screen));
sprintf(cd_depth,"Depth - %d plane(s)", DefaultDepth(display,screen));

len4 = strlen(string4);
len1 = strlen(cd_height);
len2 = strlen(cd_width);
len3 = strlen(cd_depth);

font_height = font_info->max_bounds.ascent +
font_info->max_bounds.descent;

y_offset = win_height/2 - font_height - font_info->max_bounds.descent;
x_offset = (int) win_width/4;

XDrawString(display, win, gc, x_offset, y_offset, string4, len4);
y_offset += font_height;

XDrawString(display, win, gc, x_offset, y_offset, cd_height, len1);
y_offset += font_height;

XDrawString(display, win, gc, x_offset, y_offset, cd_width, len2);
y_offset += font_height;

XDrawString(display, win, gc, x_offset, y_offset, cd_depth, len3);
}

draw_graphics(win, gc, window_width, window_height)
Pixmap win;
GC gc;
unsigned int window_width, window_height;
{
int x,y;
unsigned int width, height;

height = window_height/2;
width = 3 * window_width/4;

x = window_width/2 - width/2;
y = window_height/2 - height/2;

XDrawRectangle(display, win, gc, x, y, width, height);
}