Tracé de droites

Maintenant que nous connaissons les bases de la bibliothèque graphique Cairo, nous voilà prêts pour débuter un tracé. Commençons par le plus simple des éléments de tracé : la droite. Mais d'abord, il est nécessaire d'en savoir un peu plus sur le système de coordonnées de Cairo. L'origine du système de coordonnées de Cairo se situe dans l'angle supérieur gauche de la fenêtre avec les valeurs positives de x vers la droite et de y vers le bas.

Étant donné que la bibliothèque graphique Cairo a été écrite pour prendre en charge de multiples cibles en sortie (le système de fenêtrage X, les images PNG, Open GL, etc.), une distinction est faite entre les coordonnées dans l'espace-utilisateur et les coordonnées dans l'espace du périphérique d'affichage. La correspondance entre ces deux systèmes de coordonnées est par défaut de un pour un, de sorte que les valeurs entières du premier système correspondent grosso modo à des pixels à l'écran, mais ce réglage peut être modifié si vous le souhaitez. Quelquefois il peut être commode d'échelonner les coordonnées de sorte que la largeur et la hauteur totale d'une fenêtre se situent tous deux dans la plage de 0 à 1 (carré « unité »), ou tout autre correspondance qui fonctionnerait bien pour votre application. Ces modifications d'échelle sont effectuées à l'aide de la fonction Cairo::Context::scale().

XVII.II.I. Exemple

Dans cet exemple, nous allons écrire un programme gtkmm petit, mais pleinement fonctionnel, et tracer quelques lignes dans la fenêtre. Les lignes sont dessinées en créant un chemin, puis en le traçant. Un tracé est créé avec les fonctions Cairo::Context::move_to() et Cairo::Context::line_to(). La fonction move_to() est semblable à l'action de lever la pointe de votre crayon au dessus du papier et de la placer quelque part ailleurs — aucune ligne n'est tracée entre le point où vous étiez et celui où vous vous êtes déplacé. Pour tracer une ligne entre deux points, utilisez la fonction line_to().

Après avoir terminé la création de votre chemin, vous n'avez encore dessiné rien de visible. Pour rendre le chemin visible, il faut utiliser la fonction stroke() qui dessine le tracé actuel avec une ligne d'épaisseur et de style précisés dans l'objet Cairo::Context. Après le traçage, le chemin actuel est effacé ; vous pouvez donc en débuter un nouveau.

Beaucoup de fonctions de dessin de Cairo disposent d'une variante _preserve(). Normalement, les fonctions de dessin telles que clip(), fill() ou stroke() effacent le chemin actuel. Si vous utilisez la variante _preserve(), le chemin actuel sera préservé de sorte que vous pouvez à nouveau l'utiliser avec une autre fonction de dessin.

Figure XVII.1 Zone de dessin ‑ Lignes

Code source

File: myarea.h (For use with gtkmm 3, not gtkmm 2)

#ifndef GTKMM_EXAMPLE_MYAREA_H
#define GTKMM_EXAMPLE_MYAREA_H

#include <gtkmm/drawingarea.h>

class MyArea : public Gtk::DrawingArea
{
public:
  MyArea();
  virtual ~MyArea();

protected:
  //Override default signal handler:
  virtual bool on_draw(const Cairo::RefPtr<Cairo::Context>& cr);
};

#endif // GTKMM_EXAMPLE_MYAREA_H

File: myarea.cc (For use with gtkmm 3, not gtkmm 2)

#include "myarea.h"
#include <cairomm/context.h>

MyArea::MyArea()
{
}

MyArea::~MyArea()
{
}

bool MyArea::on_draw(const Cairo::RefPtr<Cairo::Context>& cr)
{
  Gtk::Allocation allocation = get_allocation();
  const int width = allocation.get_width();
  const int height = allocation.get_height();

  // coordinates for the center of the window
  int xc, yc;
  xc = width / 2;
  yc = height / 2;

  cr->set_line_width(10.0);

  // draw red lines out from the center of the window
  cr->set_source_rgb(0.8, 0.0, 0.0);
  cr->move_to(0, 0);
  cr->line_to(xc, yc);
  cr->line_to(0, height);
  cr->move_to(xc, yc);
  cr->line_to(width, yc);
  cr->stroke();

  return true;
}

File: main.cc (For use with gtkmm 3, not gtkmm 2)

#include "myarea.h"
#include <gtkmm/main.h>
#include <gtkmm/window.h>

int main(int argc, char** argv)
{
   Gtk::Main kit(argc, argv);

   Gtk::Window win;
   win.set_title("DrawingArea");

   MyArea area;
   win.add(area);
   area.show();

   Gtk::Main::run(win);

   return 0;
}

Ce programme ne comporte qu'une seule classe, MyArea, sous-classe de Gtk::DrawingArea avec une fonction membre on_expose_event(). Cette fonction membre est appelée chaque fois que l'image dans la zone de tracé a besoin d'être retracée. À cette fonction est passé un pointeur sur une structure GdkEventExpose définissant la zone ayant besoin d'être redessinée. Nous utilisons ces valeurs pour créer un chemin de rectangle dans Cairo (avec la fonction rectangle()) puis découper ce chemin avec clip(). La fonction clip() définit une zone de découpe. Cette zone affecte toutes les opérations de tracé en occultant effectivement toute modification sur la surface extérieure à la découpe. Cela nous permet de limiter le retraçage à la zone qui le nécessite. Le code de tracé définit la couleur que nous voulons en fait utiliser avec set_source_rgb() dont les paramètres définissent les composantes rouge, verte et bleue de la couleur voulue (les valeurs correctes sont comprises entre 0 et 1). Après avoir précisé la couleur, nous créons un nouveau chemin avec les fonctions move_to() et line_to() et nous le traçons avec stroke().

Tracé en coordonnées relatives

Dans l'exemple ci-dessus nous avons tout tracé en utilisant des coordonnées absolues. Nous pouvons également tracer en coordonnées relatives. Pour une droite, on utilise la fonction Cairo::Context::rel_line_to().

XVII.II.II. Styles de trait

En plus du tracé élémentaire de droites, vous pouvez personnaliser un certain nombre de choses dans les tracés de lignes. Nous avons déjà vu des exemples de paramétrage de couleur et d'épaisseur de trait, mais il en existe bien d'autres.

Si vous avez tiré une série de traits formant un chemin, vous pouvez vouloir les raccorder d'une certaine façon. Cairo offre trois façons différentes de raccorder les lignes entre elles : l'onglet, le biseau et l'arrondi. Voyez-les ci-dessous :

Figure XVII.2 Différents types de raccord dans Cairo

Le type de raccord est défini avec la fonction Cairo::Context::set_line_join().

Les fins de ligne peuvent avoir différents styles également. Le style par défaut est de débuter et arrêter la ligne exactement aux points de définition. On nomme cela la coupe droite. Les autres options sont l'arrondi (utilise une terminaison en demi-cercle, le centre du demi-cercle étant au point terminal de la ligne) ou le carré (utilise une terminaison carrée diagonale, le centre du carré étant au point terminal de la ligne). Ce paramétrage est défini avec la fonction Cairo::Context::set_line_cap().

Vous pouvez encore personnaliser d'autres paramètres, y compris la création de pointillés entre autres. Pour plus d'informations, consultez la documentation de l'API Cairo.