Using librsvg library and cairo graphics with vala

Recently, I was doing some research regarding possibilities of chess pieces drawing on a gtk+ widget. Taking out the most of the ideas from the glchess source code I have written a little application with vala, which shows a preview of chess pieces, found on wikipedia’s chess piece site or here on wikimedia and I would like to memorize it for me and share it with you. Especially, I liked the Maurizio Monge chess piece set.

So, in the following code snippet is demonstrated how to:

  • draw something in gtk+-3.0 within a widget named DrawingArea
  • access and read svg vector graphic files with a librsvg library and to render them afterwards with cairo
  • proceed mouse wheel and mouse click events using gdk and gtk+ respectively
  • transfer a svg file to a temporary created surface in memory for a later accelerated rendering on the widget

So, there are snapshots:



And the code below:

class PiecePreviewWindow : Gtk.Window
{
	public PiecePreviewWindow( ) {
		set_title( "Piece Preview" );
		add( new PieceView( ) );
		show_all( );
	}

	public override void destroy( ) {
		Gtk.main_quit( );
	}

	public static int main( string[] args ) {
		Gtk.init( ref args );
		new PiecePreviewWindow( );
		Gtk.main( );

		return 0;
	}
}

class PieceView : Gtk.DrawingArea
{
	public PieceView( ) {
		set_size_request( 400, 400 );
		add_events( Gdk.EventMask.BUTTON_PRESS_MASK | Gdk.EventMask.SCROLL_MASK );

		temp_surface = new Cairo.ImageSurface( Cairo.Format.ARGB32, 12 * square_size, square_size );

		string format = "./pieces/Maurizio Monge/Chess_Maurizio_Monge_Fantasy_%s%s.svg";
		string[] color = { "b", "w" };
		string[] piece = { "p", "r", "n", "b", "q", "k" };

		for( int c = 0; c < 2; c ++ ) {
			for(int p = 0; p < 6; p ++ ) {
				render_piece( format.printf( color[c], piece[p] ), 6 * c + p );
			}
		}
	}

	public override bool draw( Cairo.Context cr ) {
		cr.set_source_rgb( 0.5, 0.5, 0.5 );
		cr.rectangle( 0.0, 0.0, 400.0, 400.0 );
		cr.fill( );

		cr.scale( 400.0 / square_size, 400.0 / square_size );
		cr.set_source_surface( temp_surface, -offset * square_size, 0 );
		cr.rectangle( 0, 0, square_size, square_size );
		cr.clip( );
		cr.paint( );

		return false;
	}

	void render_piece( string file_name, int offset ) {
		Rsvg.Handle handle;
		try {
			handle = new Rsvg.Handle.from_file( file_name );
		} catch( Error e ) {
			stderr.printf( "can not open svg file\n" );
			return;
		}

		temp_cr = new Cairo.Context( temp_surface );
		temp_cr.save( );
		temp_cr.translate( square_size * offset, 0 );
		temp_cr.scale( (double) square_size / handle.width, (double) square_size / handle.height );
		handle.render_cairo( temp_cr );
		temp_cr.restore( );
	}

	public override bool button_press_event( Gdk.EventButton event ) {
		if( event.button  == 1 ) {
		 	change_piece( true );
		} else if( event.button == 3 ) {
			change_piece( false );
		} else
			return false;

		return true;
	}

	public override bool scroll_event( Gdk.EventScroll event ) {
		if( event.direction == Gdk.ScrollDirection.UP ) {
			change_piece( true );
		} else if( event.direction == Gdk.ScrollDirection.DOWN ) {
			change_piece( false );
		} else
			return false;
		return true;
	}

	private void change_piece( bool forward ) {
		if( forward ) offset ++;
		else offset --;

		if( offset < 0 ) offset = 11; 		if( offset > 11) offset = 0;

		queue_draw( );
	}

	private Cairo.ImageSurface temp_surface;
	private Cairo.Context temp_cr;
	private int square_size = 500;
	private int offset;
}

All this can be compiled with

# valac gtk-svg.vala --pkg librsvg-2.0 --pkg gtk+-3.0

Hidden portage functionality: bypassing time consuming compilation

Once you decide to update your gentoo system, looking scared at the long long update list, you probably start to think of skipping or postponing some of the time demanding compilations to get the most important things done at the first place. And luckily emerge command provides such a functionality with a –exclude option, followed by the list of items separated by a space. So, here is a small preview, showing how to use it:

# emerge --ask --verbose --newuse --deep --update world --exclude "chromium libreoffice"

And everything is fine! The only mistake, which seems often to happen to me, is, that time to time I forget to put quotation marks around the list of items, I want to exclude. So, please take care not to fall in this trap! And as you probably have seen on the IRC channels, how often people remind each other to put specified options in quotation marks, you can guess, how ashamed I feel, each time this happens to me:) cheers

Mighty Perl-like regular expressions (Regex) with Glib and Vala

A new version of Glib 2.32 has been released just about a week ago. Inspired by this fact, or by another one I started to read the glib documentation, regarding the regular expression syntax and play around with it. To do so the GRegex structure has to be created by calling g_regex_new function, where the first parameter received is the regular expression pattern, followed by compile and match flags. The last parameter is the address of the error pointer, which is created, in the case that, the function fails to interpret the pattern. In the example I want to catch the occurrence of words “moon, soon and noon” summarized by the pattern “(m|n|s)oon” in the given string.

#include <glib.h>
#include <stdlib.h>


typedef void (*HandleFunc)( void );

void 
handle_error( GError **error, HandleFunc func_pointer );

void exit_app( void ) { exit( 1 ); }

int
main( int argc, char **argv )
{
	GError *error = NULL;
	GRegex *regex;
	GMatchInfo *match_info;
	
	gchar *input_string = "soon you will see the moon in the afternoon";
	gchar *pattern_string = "(m|n|s)oon";
	
	regex = g_regex_new( pattern_string, 0, 0, &error );
	
	handle_error( &error, exit_app );
	
	g_regex_match( regex, input_string, 0, &match_info );
	
	g_print( "searching for a match \"%s\" in the string:\n\"%s\"\n\n", pattern_string, input_string );
	
	
	while( g_match_info_matches( match_info ) ) {
		gchar *match = g_match_info_fetch( match_info, 0 );
		
		g_print( "found match: \"%s\"\n", match );
		
		g_match_info_next( match_info, &error );
		
		handle_error( &error, NULL );
	
		g_free( match );
	}
	
	g_match_info_free( match_info );
	g_regex_unref( regex );
	
	return 0;
}

void 
handle_error( GError **error, HandleFunc func_pointer )
{
	if( error != NULL && *error != NULL ) {
		g_print( "%s\n", (*error)->message );
		g_clear_error( error );
		
		if( func_pointer != NULL ) func_pointer( );	
	}
}

The above example can be compiled with the following makefile:

APP = regex-test

${APP}: ${APP}.c
	gcc -o $@ $^ $(shell pkg-config --cflags --libs glib-2.0) -Wall -pedantic
	
clean:
	rm -rf ${APP}

Here is one more example written in Vala, dealing with parentheses issues, containing the balanced number of opening and closing brackets:

void main( ) {
	string exp1_pattern = "(?<exp1>( [^()]* | (?>[^()]*) (?<pn> \\( ( (?>[^()]*) | (?&pn) )* \\) ) [^()]* ))";
	string exp2_pattern = "(?<exp2>( [^()]* | (?>[^()]*) (?<pm> \\( ( (?>[^()]*) | (?&pm) )* \\) ) [^()]* ))";
	
	string pattern = "^" + exp1_pattern + "\\s(?<opn>(and|or|xor))\\s" + exp2_pattern + "$";
	
	string[] text_lines = new string[]
	{ "true and (x)", "a and b", "(ab(cd)e or y", "(a(b)cde) xor ( s )",
	  "(true and x) or (y and (not x ))", "xandy", " and b", 
	  " (x  and y) or ( true or y()) ", "a and b or c" };
	
	Regex regex;
	MatchInfo match_info;
	
	try {
		regex = new Regex( pattern, RegexCompileFlags.EXTENDED );
		foreach( string text in text_lines ) {
			stdout.printf( "\"%s\"\n", text );
			regex.match( text, 0, out match_info );
	
			while( match_info.matches( ) ) {
				stdout.printf( "\t\"%s\"\n", match_info.fetch( 0 ) );
				stdout.printf( "\toperator name: \"%s\"\n", match_info.fetch_named( "opn" ) );
				stdout.printf( "\t     left exp: \"%s\"\n", match_info.fetch_named( "exp1" ) );
				stdout.printf( "\t    right exp: \"%s\"\n", match_info.fetch_named( "exp2" ) );
				match_info.next( );
			}
		} 
	} catch( RegexError re ) {
			stderr.printf( "%s\n", re.message );	
	}	
}

This one can be compiled with:

# valac regex-test.vala