Dibujar líneas curvas

Además de dibujar líneas rectas, Cairo le permite dibujar líneas curvas fácilmente. (técnicamente, una spline cúbica de Bézier) usando las funciones Cairo::Context::curve_to() y Cairo::Context::rel_curve_to(). Estas funciones toman las coordenadas de un punto de destino y de dos puntos de «control». Esto se entiende mejor con un ejemplo, así que analícelo en profundidad.

17.3.1. Ejemplo

Esta aplicación simple dibuja una curva con Cairo y muestra los puntos de control para cada punta de la curva.

Figura 17-4Área de dibujo: líneas

Código fuente

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();

  double x0=0.1, y0=0.5, // start point
         x1=0.4, y1=0.9,  // control point #1
         x2=0.6, y2=0.1,  // control point #2
         x3=0.9, y3=0.5;  // end point

  // scale to unit square (0 to 1 width and height)
  cr->scale(width, height);

  cr->set_line_width(0.05);
  // draw curve
  cr->move_to(x0, y0);
  cr->curve_to(x1, y1, x2, y2, x3, y3);
  cr->stroke();
  // show control points
  cr->set_source_rgba(1, 0.2, 0.2, 0.6);
  cr->move_to(x0, y0);
  cr->line_to (x1, y1);
  cr->move_to(x2, y2);
  cr->line_to (x3, y3);
  cr->stroke();

  return true;
}

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

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

int main(int argc, char** argv)
{
   Glib::RefPtr<Gtk::Application> app = Gtk::Application::create(argc, argv, "org.gtkmm.example");

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

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

   return app->run(win);
}

La única diferencia entre este ejemplo y el de la línea recta está en la función on_draw(), pero hay unos conceptos y funciones nuevas presentadas aquí, así que se examinarán brevemente.

Se hace una llamada a Cairo::Context::scale(), pasándole la anchura y altura del área de dibujo. Esto escala el sistema de coordenadas de espacio del usuario de tal manera que la anchura y altura del widget correspondan ambas a 1.0 «unidades». No hay una razón en particular para escalar el sistema de coordenadas en este caso, pero a veces, puede hacer las operaciones de dibujo más fáciles.

La llamada a Cairo::Context::curve_to() debería ser bastante autodescriptiva. El primer par de coordenadas define el punto de control para el inicio de la curva. El segundo par define el punto del control para el fin de la curva, y el último par define el punto de destino. Para hacer el concepto de puntos de control un poco más fácil de visualizar, se ha dibujado una línea desde cada punto de control al punto de finalización de la curva al que están asociados. Tenga en cuenta que estas líneas de puntos de control son ambas traslúcidas. Esto se logra con una variante de set_source_rgb() llamada set_source_rgba(). Esta función toma un cuarto argumento que especifica el valor de alfa del color (los valores válidos están entre 0 y 1).