Tuesday, April 16, 2013

Drawing with Cairo in Visual Basic GTK#

Drawing with Cairo

In this part of the Visual Basic GTK# tutorial, we will do some painting with the Cairo library.
Cairo is a library for creating 2D vector graphics. We can use it to draw our own widgets, charts or various effects or animations.

Colors

In the first example, we will work with colors. A color is an object representing a combination of Red, Green, and Blue (RGB) intensity values. Cairo valid RGB values are in the range 0 to 1.
' ZetCode Mono Visual Basic GTK# tutorial
'
' This program draws three rectangles.
' The interiors are filled with
' different colors.
'
' author jan bodnar
' last modified May 2009
' website www.zetcode.com


Imports Gtk

Public Class GtkVBApp
Inherits Window

Public Sub New

MyBase.New("Colors")

Me.InitUI

Me.SetDefaultSize(360, 100)
Me.SetPosition(WindowPosition.Center)
AddHandler Me.DeleteEvent, AddressOf Me.OnDelete

Me.ShowAll

End Sub

Private Sub InitUI

Dim darea As New DrawingArea
AddHandler darea.ExposeEvent, AddressOf Me.OnExpose
Me.Add(darea)

End Sub

Private Sub OnExpose(ByVal sender As Object, ByVal args As ExposeEventArgs)

Dim cc As Cairo.Context = Gdk.CairoHelper.Create(sender.GdkWindow)

Me.DrawColors(cc)

Dim disposeTarget As IDisposable = CType(cc.Target, IDisposable)
disposeTarget.Dispose

Dim disposeContext As IDisposable = CType(cc, IDisposable)
disposeContext.Dispose

End Sub

Private Sub DrawColors(ByVal cc As Cairo.Context)

cc.SetSourceRGB(0.2, 0.23, 0.9)
cc.Rectangle(10, 15, 90, 60)
cc.Fill

cc.SetSourceRGB(0.9, 0.1, 0.1)
cc.Rectangle(130, 15, 90, 60)
cc.Fill

cc.SetSourceRGB(0.4, 0.9, 0.4)
cc.Rectangle(250, 15, 90, 60)
cc.Fill

End Sub


Private Sub OnDelete(ByVal sender As Object, _
ByVal args As DeleteEventArgs)
Application.Quit
End Sub

Public Shared Sub Main

Application.Init
Dim app As New GtkVBApp
Application.Run

End Sub

End Class
In our example, we will draw three rectangles and fill them with three different colors.
vbnc -r:/usr/lib/mono/gtk-sharp-2.0/gtk-sharp.dll 
-r:/usr/lib/mono/gtk-sharp-2.0/gdk-sharp.dll
-r:/usr/lib/mono/2.0/Mono.Cairo.dll colors.vb
Here is how we compile the example.
 Dim darea As New DrawingArea
We will be doing our drawing operations on the DrawingArea widget.
 AddHandler darea.ExposeEvent, AddressOf Me.OnExpose
All drawing is done in a method, that we plug into the ExposeEvent.
 Dim cc As Cairo.Context = Gdk.CairoHelper.Create(sender.GdkWindow)
We create the Cairo.Context object from the GdkWindow of the drawing area. The context is an object onto which we do all our drawings.
 Me.DrawColors(cc)
The actual drawing is delegated to the DrawColors method.
 Dim disposeTarget As IDisposable = CType(cc.Target, IDisposable)
disposeTarget.Dispose

Dim disposeContext As IDisposable = CType(cc, IDisposable)
disposeContext.Dispose
Here we dispose the resources, that were used during the drawing process.
 cc.SetSourceRGB(0.2, 0.23, 0.9)
The SetSourceRGB method sets a color for the cairo context. The three parameters of the method are the color intensity values.
 cc.Rectangle(10, 15, 90, 60)
We draw a rectangle. The first two parameters are the x, y coordinates of the top left corner of the rectangle. The last two parameters are the width and height of the rectangle.
cc.Fill
We fill the inside of the rectangle with the current color.

Colors
Figure: Colors

Basic shapes

The next example draws some basic shapes onto the window.
' ZetCode Mono Visual Basic GTK# tutorial
'
' This program draws basic shapes
' available in Cairo
'
' author jan bodnar
' last modified May 2009
' website www.zetcode.com


Imports Gtk

Public Class GtkVBApp
Inherits Window

Public Sub New

MyBase.New("Basic Shapes")

Me.InitUI

Me.SetDefaultSize(400, 250)
Me.SetPosition(WindowPosition.Center)
AddHandler Me.DeleteEvent, AddressOf Me.OnDelete

Me.ShowAll

End Sub

Private Sub InitUI

Dim darea As New DrawingArea
AddHandler darea.ExposeEvent, AddressOf Me.OnExpose
Me.Add(darea)

End Sub

Private Sub OnExpose(ByVal sender As Object, ByVal args As ExposeEventArgs)

Dim cc As Cairo.Context = Gdk.CairoHelper.Create(sender.GdkWindow)

Me.DrawShapes(cc)

Dim disposeTarget As IDisposable = CType(cc.Target, IDisposable)
disposeTarget.Dispose

Dim disposeContext As IDisposable = CType(cc, IDisposable)
disposeContext.Dispose

End Sub

Private Sub DrawShapes(ByVal cc As Cairo.Context)

cc.SetSourceRGB(0.5, 0.5, 0.5)

cc.Rectangle(20, 20, 120, 80)
cc.Rectangle(180, 20, 80, 80)
cc.Fill

cc.Arc(330, 60, 40, 0, 2*Math.PI)
cc.Fill

cc.Arc(90, 160, 40, Math.PI/4, Math.PI)
cc.ClosePath
cc.Fill

cc.Translate(220, 180)
cc.Scale(1, 0.7)
cc.Arc(0, 0, 50, 0, 2*Math.PI)
cc.Fill

End Sub


Private Sub OnDelete(ByVal sender As Object, _
ByVal args As DeleteEventArgs)
Application.Quit
End Sub

Public Shared Sub Main

Application.Init
Dim app As New GtkVBApp
Application.Run

End Sub

End Class
In this example, we will create a rectangle, a square, a circle, an arc and an ellipse.
 cc.Rectangle(20, 20, 120, 80)
cc.Rectangle(180, 20, 80, 80)
cc.Fill
These lines draw a rectangle and a square.
 cc.Arc(330, 60, 40, 0, 2*Math.PI)
cc.Fill
Here the Arc method draws a full circle.
 cc.Translate(220, 180)
cc.Scale(1, 0.7)
cc.Arc(0, 0, 50, 0, 2*Math.PI)
cc.Fill
The Translate method moves the object to a specific point. If we want to draw an oval, we do some scaling first. Here the Scale method shrinks the y axis.

Basic shapes
Figure: Basic shapes

Transparent rectangles

Transparency is the quality of being able to see through a material. The easiest way to understand transparency is to imagine a piece of glass or water. Technically, the rays of light can go through the glass and this way we can see objects behind the glass.
In computer graphics, we can achieve transparency effects using alpha compositing. Alpha compositing is the process of combining an image with a background to create the appearance of partial transparency. The composition process uses an alpha channel. (wikipedia.org, answers.com)
' ZetCode Mono Visual Basic GTK# tutorial
'
' This program draws ten
' rectangles with different
' levels of transparency
'
' author jan bodnar
' last modified May 2009
' website www.zetcode.com


Imports Gtk

Public Class GtkVBApp
Inherits Window

Public Sub New

MyBase.New("Transparent rectangles")

Me.InitUI

Me.SetDefaultSize(590, 90)
Me.SetPosition(WindowPosition.Center)
AddHandler Me.DeleteEvent, AddressOf Me.OnDelete

Me.ShowAll

End Sub

Private Sub InitUI

Dim darea As New DrawingArea
AddHandler darea.ExposeEvent, AddressOf Me.OnExpose
Me.Add(darea)

End Sub

Private Sub OnExpose(ByVal sender As Object, ByVal args As ExposeEventArgs)

Dim cc As Cairo.Context = Gdk.CairoHelper.Create(sender.GdkWindow)

Me.DrawRectangles(cc)

Dim disposeTarget As IDisposable = CType(cc.Target, IDisposable)
disposeTarget.Dispose()

Dim disposeContext As IDisposable = CType(cc, IDisposable)
disposeContext.Dispose()

End Sub

Private Sub DrawRectangles(ByVal cc As Cairo.Context)

For i As Integer = 1 To 10
cc.SetSourceRGBA(0, 0, 1, i*0.1)
cc.Rectangle(50*i, 20, 40, 40)
cc.Fill
Next

End Sub


Private Sub OnDelete(ByVal sender As Object, _
ByVal args As DeleteEventArgs)
Application.Quit
End Sub

Public Shared Sub Main

Application.Init
Dim app As New GtkVBApp
Application.Run

End Sub

End Class
In the example we will draw ten rectangles with different levels of transparency.
 cc.SetSourceRGBA(0, 0, 1, i*0.1)
The last parameter of the SetSourceRGBA method is the alpha transparency.

Transparent rectangles
Figure: Transparent rectangles

Donut

In the following example we create n complex shape by rotating a bunch of ellipses.
' ZetCode Mono Visual Basic GTK# tutorial
'
' This program draws basic shapes
' available in Cairo
'
' author jan bodnar
' last modified May 2009
' website www.zetcode.com


Imports Gtk

Public Class GtkVBApp
Inherits Window

Public Sub New

MyBase.New("Donut")

Me.InitUI

Me.SetDefaultSize(400, 250)
Me.SetPosition(WindowPosition.Center)
AddHandler Me.DeleteEvent, AddressOf Me.OnDelete

Me.ShowAll

End Sub

Private Sub InitUI

Dim darea As New DrawingArea
AddHandler darea.ExposeEvent, AddressOf Me.OnExpose
Me.Add(darea)

End Sub

Private Sub OnExpose(ByVal sender As Object, ByVal args As ExposeEventArgs)

Dim cc As Cairo.Context = Gdk.CairoHelper.Create(sender.GdkWindow)

Me.DrawDonut(cc)

Dim disposeTarget As IDisposable = CType(cc.Target, IDisposable)
disposeTarget.Dispose

Dim disposeContext As IDisposable = CType(cc, IDisposable)
disposeContext.Dispose

End Sub

Private Sub DrawDonut(ByVal cc As Cairo.Context)

cc.LineWidth = 0.5

Dim width, height As Integer
width = Allocation.Width
height = Allocation.Height

cc.Translate(width/2, height/2)
cc.Arc(0, 0, 120, 0, 2*Math.PI)
cc.Stroke

cc.Save

For i As Integer = 0 To 35
cc.Rotate( i*Math.PI/36)
cc.Scale(0.3, 1)
cc.Arc(0, 0, 120, 0, 2*Math.PI)
cc.Restore
cc.Stroke
cc.Save
Next

End Sub


Private Sub OnDelete(ByVal sender As Object, _
ByVal args As DeleteEventArgs)
Application.Quit
End Sub

Public Shared Sub Main

Application.Init
Dim app As New GtkVBApp
Application.Run

End Sub

End Class
In this example, we create a donut. The shape resembles a cookie, hence the name donut.
 cc.Translate(width/2, height/2)
cc.Arc(0, 0, 120, 0, 2*Math.PI)
cc.Stroke
In the beginning there is an ellipse.
 For i As Integer = 0 To 35
cc.Rotate( i*Math.PI/36)
cc.Scale(0.3, 1)
cc.Arc(0, 0, 120, 0, 2*Math.PI)
cc.Restore
cc.Stroke
cc.Save
Next
After several rotations, there is a donut.

Donut
Figure: Donut

Drawing text

In the next example, we draw some text on the window.
' ZetCode Mono Visual Basic GTK# tutorial
'
' This program draws text
' on the window
'
' author jan bodnar
' last modified May 2009
' website www.zetcode.com


Imports Gtk

Public Class GtkVBApp
Inherits Window

Public Sub New

MyBase.New("Soulmate")

Me.InitUI

Me.SetDefaultSize(400, 250)
Me.SetPosition(WindowPosition.Center)
AddHandler Me.DeleteEvent, AddressOf Me.OnDelete

Me.ShowAll

End Sub

Private Sub InitUI

Dim darea As New DrawingArea
AddHandler darea.ExposeEvent, AddressOf Me.OnExpose
Me.Add(darea)

End Sub

Private Sub OnExpose(ByVal sender As Object, ByVal args As ExposeEventArgs)

Dim cc As Cairo.Context = Gdk.CairoHelper.Create(sender.GdkWindow)

Me.DrawLyrics(cc)

Dim disposeTarget As IDisposable = CType(cc.Target, IDisposable)
disposeTarget.Dispose

Dim disposeContext As IDisposable = CType(cc, IDisposable)
disposeContext.Dispose

End Sub

Private Sub DrawLyrics(ByVal cc As Cairo.Context)

cc.SetSourceRGB(0.1, 0.1, 0.1)

cc.SelectFontFace("Purisa", Cairo.FontSlant.Normal, Cairo.FontWeight.Bold)
cc.SetFontSize(13)

cc.MoveTo(20, 30)
cc.ShowText("Most relationships seem so transitory")
cc.MoveTo(20, 60)
cc.ShowText("They're all good but not the permanent one")
cc.MoveTo(20, 120)
cc.ShowText("Who doesn't long for someone to hold")
cc.MoveTo(20, 150)
cc.ShowText("Who knows how to love without being told")
cc.MoveTo(20, 180)
cc.ShowText("Somebody tell me why I'm on my own")
cc.MoveTo(20, 210)
cc.ShowText("If there's a soulmate for everyone")

End Sub


Private Sub OnDelete(ByVal sender As Object, _
ByVal args As DeleteEventArgs)
Application.Quit
End Sub

Public Shared Sub Main

Application.Init
Dim app As New GtkVBApp
Application.Run

End Sub

End Class
We display part of the lyrics from the Natasha Bedingfields Soulmate song.
 cc.SelectFontFace("Purisa", Cairo.FontSlant.Normal, Cairo.FontWeight.Bold)
Here we specify the font, that we use. Purisa bold.
 cc.SetFontSize(13)
We specify the size of the font.
 cc.MoveTo(20, 30)
We move to the point, where we will draw the text.
 cc.ShowText("Most relationships seem so transitory")
The ShowText method draws text onto the window.

Soulmate
Figure: Soulmate

In this chapter of the Visual Basic GTK# tutorial, we were painting with Cairo library.

No comments:

Post a Comment