Compilar un programa escrito en C# con Mono, GTK#, Cairo

Les cuento que Mono incorpora Cairo, que es una librería originalmente escrita en C, para el renderizado de dibujos en 2D (2 dimensiones). Que funciona con o sin aceleración gráfica para tarjetas de video. Se dice que simple de utilizar y se incorpora perfectamente con GTK, las librerías que utiliza Gnome uno de los escritorios mas utilizados en Linux.

Ahora les presento un código que hice yo, para que vean como es, espero que les guste.

    // Compilar: gmcs Clip2.cs -pkg:gtk-sharp-2.0 -r:Mono.Cairo

    using System;
    using Cairo;
    using Gtk;
    using System.Timers;

    public class GtkCairo
    {
     static void Main ()
     {
     Application.Init ();
     Gtk.Window w = new Gtk.Window ("Clip2");

     DrawingArea a = new CairoGraphic ();
     Box box = new VBox (true, 0);
     box.Add (a);

     w.Add (box);
     w.Resize (256, 256);

     w.DeleteEvent += close_window;
     w.ShowAll ();

     Application.Run ();
     }

     static void close_window (object obj, DeleteEventArgs args)
     {
     Application.Quit ();
     }

    }

    public class CairoGraphic : DrawingArea
    {
     private static double grosorLinea;
     private static double transparencia;
     private static bool contraerLinea;
     private static bool expanderLinea;
     private static bool transparenciaPos;
     private static bool transparenciaNeg;

     public CairoGraphic ()
     {
     transparenciaPos = expanderLinea = true;
     transparenciaNeg = contraerLinea = false;
     GLib.Timeout.Add (100, new GLib.TimeoutHandler (Siempre));
     grosorLinea = 20.0;
     transparencia = 0.20;
     }

     private bool Siempre ()
     {
     QueueDraw ();
     return true;
     }

     protected override bool OnExposeEvent (Gdk.EventExpose args)
     {
     //
     // Expander y contraer lineas
     //
     if (expanderLinea == true) {
     grosorLinea += 0.5;
     if (grosorLinea > 24.0) {
     expanderLinea = false;
     contraerLinea = true;
     }
     }
     else if (contraerLinea == true) {
     grosorLinea -= 0.5;
     if (grosorLinea < 21.0) {
     contraerLinea = false;
     expanderLinea = true;
     }
     }
     //
     // Aumentar y Reducir transparencia
     //
     if (transparenciaPos == true) {
     transparencia += 0.01;
     if (transparencia > 0.99) {
     transparenciaPos = false;
     transparenciaNeg = true;
     }
     }
     else if (transparenciaNeg == true) {
     transparencia -= 0.01;
     if (transparencia < 0.50) {
     transparenciaNeg = false;
     transparenciaPos = true;
     }
     }

     double PI = System.Math.PI;

     using (Context g = Gdk.CairoHelper.Create (args.Window)){
     g.Arc (128.0, 128.0, 76.8, 0, 2*PI);
     g.Clip ();
     g.NewPath ();
     g.Rectangle (0,0,256,256);
     g.Fill (); // Transfiere el Color que pasa por la mascara

     //
     // Dibuja la X
     //
     g.SetSourceRGBA (0,1,0,transparencia); // Color Verde
     g.MoveTo (0,0);
     g.LineTo (256,256);
     g.MoveTo (256,0);
     g.LineTo (0,256);

     g.LineWidth = grosorLinea;
     g.Stroke (); // Transfiere la X

     }

     return true;
     }
    }

Se compila así:

gmcs Clip2.cs -pkg:gtk-sharp-2.0 -r:Mono.Cairo

Hasta hice un video, de el programa: http://www.youtube.com/watch?v=Hr-fqaMwvLM y también lo publique en los Foro de Programación X, y ahí esta el código fuente.

¿Como compilar en Mono con Cairo y C#?

Antes compilaba los programas con la librería cairo en mono de esta manera:

mcs Clip2.cs -pkg:gtk-sharp-2.0 -pkg:mono-cairo

Y ahora no me funciona y ni siquiera me funcionan los programas que antes había compilado… Pero buscando mucho por la red me di cuenta que ahora se compila de esta forma:

gmcs Arc.cs -r:Mono.Cairo -pkg:gtk-sharp-2.0

Y es raro que no se pueda de esta otra:

writkas@writkas-desktop:~/c#/Cairo/Writkas/Listos$ smcs Arc.cs -r:Mono.Cairo -pkg:gtk-sharp-2.0
error CS0006: cannot find metadata file `Mono.Cairo'
Compilation failed: 1 error(s), 0 warnings

:S

Y por si todavía no funciona, yo instale algunos paquetes que decían por ahí:

  • Instalar libpixman-0.1.2 y libpixman-devel-0.1.2 (necesarios para Cairo)
  • Instalar cairo-0.2.0 y cairo-devel-0.2.0 (necesarios para libgdiplus)

Bueno eso es todo, espero que a alguien le aya servido 🙂

__________

Actualizado: solo había que instalar la librería libmono-cairo1.0-cil, no vienen predeterminados con mono 2.x. Ahora funcionan los ejecutables

¬¬

  1. Instalar libpixman-0.1.2 y libpixman-devel-0.1.2 (necesarios para Cairo)
  2. Instalar cairo-0.2.0 y cairo-devel-0.2.0 (necesarios para libgdiplus)
  3. Instalar libpixman-0.1.2 y libpixman-devel-0.1.2 (necesarios para Cairo)
  4. Instalar cairo-0.2.0 y cairo-devel-0.2.0 (necesarios para libgdiplus)

Ejemplo MonoDevelop: CairoEjemplo002

Ahora un ejemplo recién un poco mas interesante en Mono.Cairo, que dibuja una X de colores sobre una ventana, luego esta misma imagen la pasa a un archivo de imagen PNG. Ahora la parte mas interesante:

// MainWindow.cs

using Cairo;
using System;
using Gtk;

public partial class MainWindow: Gtk.Window
{
	public MainWindow (): base (Gtk.WindowType.Toplevel)
	{
		Build ();
	}

	protected void OnDeleteEvent (object sender, DeleteEventArgs a)
	{
		Application.Quit ();
		a.RetVal = true;
	}

	protected virtual void OnButton1Clicked (object sender, System.EventArgs e)
	{
		Cairo.ImageSurface Imsf = new ImageSurface(Format.ARGB32, 200, 200);
		using (Cairo.Context Ctx = new Cairo.Context(Imsf)) {

			Ctx.LineWidth = 20;

			Ctx.SetSourceRGB(0,0,1); //Color Azul
			Ctx.MoveTo(0,0);
			Ctx.LineTo(100,100);
			Ctx.Stroke();

			Ctx.SetSourceRGB(0.66,0.44,0.33); //Color Cafe
			Ctx.MoveTo(100,100);
			Ctx.LineTo(0,200);
			Ctx.Stroke();

			Ctx.SetSourceRGB(0,1,0); //Color Verde
			Ctx.MoveTo(100,100);
			Ctx.LineTo(200,200);
			Ctx.Stroke();

			Ctx.SetSourceRGB(1,0,0); //Color Rojo
			Ctx.MoveTo(100,100);
			Ctx.LineTo(200,0);
			Ctx.Stroke();

			Imsf.WriteToPng("Dibujo.png");
		}
		Gtk.Window Win1 = new Gtk.Window("Dibujo");

		Gtk.Image Img1 = new Image("Dibujo.png");
		Console.WriteLine("Se a creado un archivo Dibujo.png");

		Gtk.HBox hbox = new HBox();
		hbox.Add(Img1);

		Win1.Add(hbox);
		Win1.ShowAll();
	}
}

 

Entonces:

  • Un objeto del tipo Cairo.ImageSurface es en el cual se dibuja.

  • Se podría decir que un objeto Cairo.Context, son las herramientas para dibujar en una surface, como por ejemplo un Cairo.ImageSurface o en un Cairo.Surface.

  • El metodo Cairo.Context.Stroke() dibuja según argumentos establecidos por otros metodos como por ejemplo: MoveTo(), LineTo(), LineWidth()

 

Una así queda:

 

Descarga aqui el ejemplo. [enlace roto]

Por favor avisenme si existe algún error ::)

Ejemplo MonoDevelop: CairoEjemplo01

A continuación voy a presentar un ejemplo simple que muestra como insertar un texto en una clase Cairo.ImageSurface, para luego guardarlo en un archivo PNG. Esta basado en la librería Mono.Cairo versión 2.0.0. Este ejemplo lo copie de MonoDoc y yo solamente lo adapte para que funcionase en MonoDevelop 1.0.

Aquí la parte en la que me quiero enfocar del código:


// Crear una clase Cairo.ImageSurface pasándole como argumentos el formato
// (Format.ARG32), el ancho de la imagen (240) y el alto (80)
Cairo.ImageSurface surface = new Cairo.ImageSurface (Format.ARGB32, 240, 80);

// Primero se crea una clase Cairo.Context y se le añade como parámetro la
// clase creada anteriormente, después se usa el espacio de nombre Cairo.ctx
// solamente dentro de un bloque.
using (Cairo.Context ctx = new Cairo.Context (surface))
{
// Se Selecciona el Font
ctx.SelectFontFace (“serif”, FontSlant.Normal, FontWeight.Bold);
ctx.SetFontSize (32.0); // El tamaño del Font

// Selecciona el color Azul
ctx.SetSourceRGB (0, 0, 1);

// Dibujar
ctx.MoveTo (10, 50);
ctx.ShowText (“Hello, World”);

// Crea una imagen en el directorio del ejecutable o en la carpeta personal (home/usuario)
surface.WriteToPng (“test2.png”);

Console.WriteLine(“Se a creado un archivo test2.png”);
}

Build ();

Esta imagen crea Cairo:

Aquí el código completo: CairoEjemplo01

Ejemplo MonoDevelop: Gdk.Pixbuf

De ahora en adelante voy a subir algunos ejemplos hechos en MonoDevelop, la verdad es que son bastante simples, tal vez demasiado. Mas que nada es por aprender yo mismo y ayudar a alguien que puede aprovechar los ejemplos. Y también es porque, cuando busqué ejemplos en Internet no encontré muchos y la documentación de Mono es poca, incluso en ingles hay poca documentación. No trato de ofender a nadie con esto de la documentación.

Son algunas cosas de las que aprendido en MonoDevelop, ya sea Cairo, Canvas, System, GtkSharp, GdkSharp, etc… Pero por ahora voy a ocupar solamente C# como lenguaje. Y la mayoría de los ejemplos estarán dentro de una solución MonoDevelop 1.0 (por ahora), por que no esta mal decir que para abrir la solución por completo hay que ejecutar el archivo *.mds (pixbuf.mds en este caso) con la aplicación MonoDevelop.

Aquí va un ejemplo bastante sencillo. Es solo una cara que se muestra a través de una ventana, lo único que podría ser interesante es que el dibujo esta dentro del código en una clase llamada dibujo. Que no es mas que un vector de string estático, de solo lectura.

public static readonly string [] cara_xpm = new string [] {…}
Que luego se guarda dentro de una instancia de la clase Gdk.Pixbuf y se añada a una imagen (Gdk.Image), y esta se añade a una ventana.


Aquí el código: Ejemplo: Gdk.Pixbuf

Los comentarios son buen atendidos, saludos.

Ejemplo C#, Cairo, Gtk

Tengo algunos ejemplos escritos es C# con Mono, Gtk y Cairo. La mayoría los saque de otras páginas web, estaban escritos en C y los traduce a C#, y algunos los animé, para aprender.

Adjunté un link, archivo Zip que contiene los ejemplos: ejemplos en C# sobre los delegados y eventos; también ejemplos con MonoDevelop 1.0; y ejemplos que tratan de la librería Cairo.

En este Link: Aquí

Estas son las fotos de algunos de los ejemplos:



A continuación comentaré algunas partes del código, de el ejemplo Arc.cs

Arc.cs

La parte del código que quiero enfatizar:

01 c.LineWidth = 10.0;
02 c.Arc (xc, yc, radio, angulo1, angulo2);
03 c.Stroke ();
04
05 c.SetSourceRGBA (1.0,0.0,0.0,0.8);
06 c.LineWidth = 6.0;
07
08 c.Arc (xc, yc, 10.0, 0, 2 * System.Math.PI);
09 c.Fill ();
10
11 c.Arc (xc, yc, radio, angulo1, angulo1);
12 c.LineTo (xc, yc);
13 c.Arc (xc, yc, radio, angulo2, angulo2);
14 c.LineTo (xc, yc);
15 c.Stroke ();

(c.LineWidth = 10.0;) (01 línea)

La primera linea es una propiedad referenciada en modo escritura. Define el tamaño de la línea para luego escribir en el ‘destino’ con el método Stroke ()(El ‘destino’ es la superficie sobre la cual se dibuja)

(c.Arc (xc, yc, radio, angulo1, angulo2);) (02 línea)
La segunda línea en el código fuente le e definido los siguientes argumentos:
xc = yc = 128.0;
radio = 100.0;
angulo1 = 45 * (System.Math.PI / 180.0);
angulo2 = 180 * (System.Math.PI / 180.0);

Donde ‘xc’ y ‘yc’ son las posiciones del centro del arco. ‘xc’ es la columna y ‘yc’ es la fila.

En el caso de la variable de tipo double con los identificadores ‘angulo1’ y ‘angulo2’ son las que definen el tamaño del angulo. Desde el punto ‘angulo1’ o ‘angulo2’. Por que hacerlo así en vez de indicarlo con los grados, la verdad que no tengo idea. Tal vez sea un buen abito hacerlo así, de todos modos no se puede hacer con los grados.

(c.Stroke ();) (03 línea)
La tercera línea contiene método de una instancia de la clase Context, que imprime en el destino con las característica indicadas anteriormente. El color pasa por la máscara, y luego se imprime en el destino.

(c.SetSourceRGBA (1.0,0.0,0.0,0.8);) (05 línea)
Este método selecciona el color. El color se va modificando por los tres colores básicos, que son los tres primeros argumentos: Rojo, Verde, Azul y el último argumento es el grado de trasparencia el denominado Apha. ¿Por que RGBA? la respuesta es simple: Red, Green, Blue y Alpha.

(c.LineWidth = 6.0c.LineTo (xc, yc);;) (06 línea)
Definimos de nuevo el tamaño.

(c.Arc (xc, yc, 10.0, 0, 2 * System.Math.PI);) (08 línea)
Crea un circulo con el radio 10.0, que tiene 360º.

(c.Fill ();) (09 línea)
Rellena el circulo creado anteriormente con el color rojo, definido antes. Creo que debo indicar que la linea 06 no a tenido ningun efecto hasta la linea 09.

(c.Arc (xc, yc, radio, angulo1, angulo1);)) (11 línea)
Se mueve el lápiz a un solo punto de este arco, ya que el 4º y 5º argumento son lo mismo. En realidad esto no es un arco solo se hace referencia al punto de un arco.

(c.LineTo (xc, yc);) (12 línea)
Dibuja una línea desde el punto anterior hasta ‘xc’ y ‘yc’, se ve como el centro del arco.

(14 y 15 línea)
Las líneas 14 y 15 hacen algo parecido a las líneas 11 y 12, pero con otro extremo del arco.

Esto es todo, solo espero que a alguien le alla servido.