Visit Jeremy's Blog.
Go Back > Forums > Non-*NIX Forums > Programming
User Name
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.


  Search this Thread
Old 07-25-2007, 10:03 PM   #1
Winter Knight
Registered: Nov 2005
Distribution: Debian Stable/Testing
Posts: 54

Rep: Reputation: 15
Having trouble debugging a program. Uses gtk, cairo, and allegro.

Hello. I'm having a really tough time debugging this program. It works just fine in Linux. However, on Windows, cairo only displays the first line, and then repeats it, rather than displaying the image.

The latest cairo binary for Windows is 1.4.0. The one I'm using on my linux box is 1.4.10. However, I've installed cairo 1.4.0 on my linux box, and it still works fine. Also, the original code was written on a linux box long before 1.4.0 came out.

The GTK+ library that I'm using on my Windows box is the one from I just downloaded it a few days ago.

I know that the convert_icons function looks like a hack. It's actually less so than it looks like. Both marker_image->line[][] (allegro) and gdk_icon_data (cairo) buffers are documented, and unlikely to change. The preferred solution would be to not use allegro, and use the gdk and cairo builtin functions instead to do the drawings. But it was like this when I found it, and I don't want to rewrite a bunch of code. The original program, is, of course, much bigger than this simplified version.

If you're interested in looking at the original program, it is mapdraw2, a utility that comes with KQ lives. It's in the cvs.

If anyone who would like to try to help me has any further questions, I'd be happy to answer them. Thank you for your help.

/* Minimal gtk/cairo/allegro program to duplicate KQ bug */

#include <gtk/gtk.h>
#include <allegro.h>

static cairo_surface_t * gdk_marker_image;
static cairo_user_data_key_t cairo_user_data_key;
BITMAP * marker_image;

static cairo_surface_t *convert_icon (BITMAP * icon, gboolean transparency)
   int row, col;
   unsigned char * gdk_icon_data = malloc (icon->h * icon->w * 4);
   for (row = 0; row < icon->h; ++row) {
      for (col = 0; col < icon->w; ++col) {
            gdk_icon_data[(row * 16 + col) * 4 + 2] = icon->line[row][col * 4 + 2];      // red
            gdk_icon_data[(row * 16 + col) * 4 + 1] = icon->line[row][col * 4 + 1];      // green
            gdk_icon_data[(row * 16 + col) * 4 + 0] = icon->line[row][col * 4 + 0];      // blue
            gdk_icon_data[(row * 16 + col) * 4 + 3] = 0; // No alpha channel to keep things simple.

   cairo_surface_t *s =
      cairo_image_surface_create_for_data (gdk_icon_data, CAIRO_FORMAT_RGB24,
                                           icon->w, icon->h, 0);
   cairo_surface_set_user_data (s, &cairo_user_data_key, gdk_icon_data, free);
   return s;

static void convert_icons (void)
   gdk_marker_image = convert_icon (marker_image, FALSE);

void do_draw (cairo_t * cr, GdkRectangle * area)
   cairo_set_source_rgb (cr, 0, 0, 0);
   cairo_rectangle (cr, area->x, area->y, area->width, area->height);
   cairo_fill (cr);

   cairo_set_source_surface (cr, gdk_marker_image, 100, 100);
   cairo_paint (cr);

static gboolean on_map_expose_event (GtkWidget * widget, GdkEventExpose * event, gpointer data)
   cairo_t *cr = gdk_cairo_create (widget->window);

   gdk_cairo_rectangle (cr, &event->area);
   cairo_clip (cr);

   do_draw (cr, &event->area);

   cairo_destroy (cr);
   return TRUE;

void create_allegro_marker_image()
   marker_image = create_bitmap (16, 16);
   clear_bitmap (marker_image);
   vline (marker_image, 0, 0, 16, makecol (255, 255, 255));
   vline (marker_image, 1, 0, 16, makecol (192, 192, 192));
   rectfill (marker_image, 2, 0, 10, 8, makecol (255, 0, 0));

	blit(marker_image, screen, 0, 0, 0, 0, 16, 16);

void allegro_start()
	set_gfx_mode(GFX_AUTODETECT, 320, 200, 0, 0);

int main (int argc, char **argv)
	GtkWidget *window;
	GtkWidget *picture;


	gtk_init (&argc, &argv);


	window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
	g_signal_connect (window, "destroy",
			G_CALLBACK (gtk_main_quit), NULL);

	picture = gtk_drawing_area_new();
	g_signal_connect(picture, "expose_event", G_CALLBACK
		(on_map_expose_event), NULL);
	gtk_container_add (GTK_CONTAINER (window), picture);

	gtk_widget_show_all (window);

	gtk_main ();
Old 07-26-2007, 01:46 AM   #2
Winter Knight
Registered: Nov 2005
Distribution: Debian Stable/Testing
Posts: 54

Original Poster
Rep: Reputation: 15
I got it. The guilty line is right here:
cairo_image_surface_create_for_data (gdk_icon_data, CAIRO_FORMAT_RGB24,
   icon->w, icon->h, 0);
This line should read:
cairo_image_surface_create_for_data (gdk_icon_data, CAIRO_FORMAT_RGB24,
   icon->w, icon->h, icon->w * 4);
It turns out that the last argument is the number of bytes between the start of each row, NOT the number of bytes in between the rows. Each row, it jumped this number of bytes when displaying the image. Because the number was 0, it displayed the first row over and over. I do not understand why this worked in Linux. Perhaps there is some sort of sane default when the number is 0 in Linux, but not in Windows.


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off

Similar Threads
Thread Thread Starter Forum Replies Last Post
font problem after gtk, pango and cairo update Lord_Grave Linux - Software 0 06-03-2007 05:21 AM
gnome + gtk + cairo keratos Ubuntu 0 05-18-2007 10:40 AM
FC6 Having trouble finding/using allegro lmcilwain Linux - Games 0 11-27-2006 09:00 PM
"--enable-gtk-cairo" in gcc-4.0.2 llmmix Programming 0 11-09-2005 11:38 PM
gtk+2.8 and cairo John Velman Slackware 3 10-19-2005 04:16 PM > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 09:13 PM.

Main Menu
Write for LQ is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration