On 7/15/07, Øystein Johansen <[EMAIL PROTECTED]> wrote:

I've earlier suggested that the export to graphic formats
should be rewritten and based on cairo.

http://lists.gnu.org/archive/html/bug-gnubg/2007-04/msg00053.html

I don't think I have motivation to write in this right now. (or maybe.... maybe 
I feel some motivation ..... I'm visitiong my parents now, let me have a look 
when I'm back home. OK? Warning: I may lose any motivation by then....)

-Øystein

Hi Øystein,

I played a bit with designing a cairo board back then, but got tired
of it. I'm attaching the code to get you started ;)

compile with

gcc board.c main.c -o board `pkg-config --cflags --libs gtk+-2.0`

Christian.
/**
 * board.c
 *
 * A GTK+ widget that implements a backgammon board
 *
 */

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

#include "board.h"

G_DEFINE_TYPE(BgBoard, bg_board, GTK_TYPE_DRAWING_AREA);

static gboolean bg_board_expose(GtkWidget * board,
				      GdkEventExpose * event);

static void bg_board_class_init(BgBoardClass * class)
{
	GtkWidgetClass *widget_class;

	widget_class = GTK_WIDGET_CLASS(class);

	widget_class->expose_event = bg_board_expose;
}

static void bg_board_init(BgBoard * board)
{
}

static get_point_base(int i, int *x, int *y, int *direction)
{
	if (i < 7) {
		*x = 220 + (6 - i) * 20;
		*y = 320;
		*direction = -1;
	} else if (i < 13) {
		*x = 80 + (12 - i) * 20;
		*y = 320;
		*direction = -1;
	} else if (i < 19) {
		*x = 80 + (i - 13) * 20;
		*y = 80;
		*direction = 1;
	} else if (i < 25) {
		*x = 220 + (i - 19) * 20;
		*y = 80;
		*direction = 1;
	} else {
		g_assert_not_reached();
	}
}

static void draw_text(cairo_t * cr, int x, int y, double f, double size,
		      const gchar * text)
{
	PangoLayout *layout;
	PangoFontDescription *desc;
	gchar font_size[200];
	g_ascii_formatd(font_size, sizeof(font_size), "%.1f", f * size);
	gchar *font_name = g_strdup_printf("Sans %s", font_size);

	int i;
	int width, height;

	/* Create a PangoLayout, set the font and text */
	layout = pango_cairo_create_layout(cr);
	pango_layout_set_text(layout, text, -1);
	desc = pango_font_description_from_string(font_name);
	pango_layout_set_font_description(layout, desc);
	pango_font_description_free(desc);
	pango_layout_get_size(layout, &width, &height);
	cairo_move_to(cr, (x * f - width / 2.0 / PANGO_SCALE),
		      (y * f - height / 2.0 / PANGO_SCALE));
	pango_cairo_show_layout(cr, layout);
	cairo_stroke(cr);
	g_object_unref(layout);
}

static void draw_point(cairo_t * cr, double f, int i)
{
	int x, y, direction;
	int even_point;
	double point_color;
	get_point_base(i, &x, &y, &direction);

	even_point = (i % 2);
	point_color = 1.0 - (double) even_point / 2.0;

	cairo_save(cr);

	cairo_translate(cr, x * f, y * f);
	cairo_move_to(cr, -10 * f, 0);
	cairo_line_to(cr, 0, direction * 100 * f);
	cairo_line_to(cr, 10 * f, 0);
	cairo_close_path(cr);

	cairo_set_source_rgb(cr, point_color, point_color, point_color);
	cairo_fill_preserve(cr);

	cairo_set_source_rgb(cr, 0, 0, 0);
	cairo_stroke(cr);
	cairo_move_to(cr, 0, 0);
	draw_text(cr, 0, -10 * direction, f, 9.0,
		  g_strdup_printf("%d", i));
	cairo_restore(cr);
}

static void draw_cube(cairo_t * cr, double f, int i)
{
	int y;
	y = (i + 1) * 110 + 82;
	cairo_rectangle(cr, 192 * f, y * f, 16 * f, 16 * f);
	draw_text(cr, 200, y + 8, f, 9.0, "64");
	cairo_stroke(cr);
}

static void draw_turn(cairo_t * cr, double f, int i)
{
	cairo_rectangle(cr, 58 * f, 185 * f, 4 * f, 16 * f);
	cairo_fill(cr);
	cairo_move_to(cr, 53 * f, 201 * f);
	cairo_line_to(cr, 60 * f, 215 * f);
	cairo_line_to(cr, 67 * f, 201 * f);
	cairo_close_path(cr);
	cairo_fill(cr);
}

static void draw_checker(cairo_t * cr, double f, int player, int point, int c)
{
	int i, x, y, direction, p;

	g_return_if_fail( c > 0 && c < 16); 

	get_point_base(point, &x, &y, &direction);
	y -= 10*direction;
	for (p=0;c > 0 && p<5; c--,p++)
	{
		y += 20*direction;
		cairo_arc(cr, x*f, y*f, 10*f, 0, 2*M_PI);
		cairo_set_source_rgb(cr, 1, 1, 1);
		cairo_fill_preserve(cr);
		cairo_set_source_rgb(cr, 0, 0, 0);
		cairo_stroke(cr);
	}
	if (c)
		draw_text(cr, x, y, f, 8.0, g_strdup_printf("%d", c+5));
}

static void draw_checkers(cairo_t * cr, double f)
{
	int board[2][25] = {
		{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
		{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
	};
	int player, point, c;
	for (player = 0; player < 2; player++) {
		for (point = 0; point < 25; point++) {
			board[player][point] = 15;
			if (c = board[player][point])
				draw_checker(cr, f, player, point, c);
		}
	}
}


static void draw_board(double x, double y, double size, cairo_t * cr)
{
	int i;
	double f;

	f = size / 400.0;

	cairo_save(cr);
	cairo_set_line_width(cr, 2);

	cairo_rectangle(cr, 50 * f, 60 * f, 300 * f, 280 * f);
	cairo_set_source_rgb(cr, 1, 1, 1);
	cairo_fill_preserve(cr);
	cairo_set_source_rgb(cr, 0, 0, 0);

	cairo_rectangle(cr, 70 * f, 80 * f, 260 * f, 240 * f);
	cairo_rectangle(cr, 190 * f, 80 * f, 20 * f, 240 * f);

	cairo_rectangle(cr, 50 * f, 182 * f, 20 * f, 36 * f);
	cairo_rectangle(cr, 330 * f, 182 * f, 20 * f, 36 * f);

	cairo_stroke(cr);

	for (i = 1; i < 25; i++)
		draw_point(cr, f, i);
	for (i = -1; i < 2; i++)
		draw_cube(cr, f, i);
	draw_checkers(cr, f);
	draw_turn(cr, f, -1);
	cairo_restore(cr);
}

static void draw(GtkWidget * board, cairo_t * cr)
{
	double x, y;
	double size;

	x = board->allocation.x;
	y = board->allocation.y;
	size = MIN(board->allocation.width, board->allocation.height);
	draw_board(x, y, size, cr);
}

static gboolean bg_board_expose(GtkWidget * board,
				      GdkEventExpose * event)
{
	cairo_t *cr;

	/* get a cairo_t */
	cr = gdk_cairo_create(board->window);

	cairo_rectangle(cr,
			event->area.x, event->area.y,
			event->area.width, event->area.height);
	//cairo_clip(cr);

	draw(board, cr);

	cairo_destroy(cr);

	return FALSE;
}

GtkWidget *bg_board_new(void)
{
	return g_object_new(BG_TYPE_BOARD, NULL);
}
#include <gtk/gtk.h>
typedef struct _BgBoard BgBoard;
typedef struct _BgBoardClass BgBoardClass;

struct _BgBoard {
	GtkDrawingArea parent;

	/* private */
};

struct _BgBoardClass {
	GtkDrawingAreaClass parent_class;
};


#define BG_TYPE_BOARD             (bg_board_get_type ())
#define BG_BOARD(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), BG_TYPE_BOARD, BgBoard))
#define BG_BOARD_CLASS(obj)       (G_TYPE_CHECK_CLASS_CAST ((obj), BG_BOARD,  BgBoardClass))
#define BG_IS_BOARD(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), BG_TYPE_BOARD))
#define BG_IS_BOARD_CLASS(obj)    (G_TYPE_CHECK_CLASS_TYPE ((obj), BG_TYPE_BOARD))
#define BG_BOARD_GET_CLASS        (G_TYPE_INSTANCE_GET_CLASS ((obj), BG_TYPE_BOARD, BgBoardClass))

GtkWidget *bg_board_new(void);
#include "board.h"
int main(int argc, char **argv)
{
	GtkWidget *window;
	GtkWidget *board;

	gtk_init(&argc, &argv);

	window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
	gtk_window_set_default_size(GTK_WINDOW(window), 400, 400);

	board = bg_board_new();
	gtk_container_add(GTK_CONTAINER(window), board);

	g_signal_connect
	    (window, "destroy", G_CALLBACK(gtk_main_quit), NULL);

	gtk_widget_show_all(window);

	gtk_main();
}
_______________________________________________
Bug-gnubg mailing list
[email protected]
http://lists.gnu.org/mailman/listinfo/bug-gnubg

Reply via email to