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.

16.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 16-4Área de dibujo: líneas

Source Code

File: myarea.h (For use with gtkmm 4)

#ifndef GTKMM_EXAMPLE_MYAREA_H
#define GTKMM_EXAMPLE_MYAREA_H

#include <gtkmm/drawingarea.h>

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

protected:
  void on_draw(const Cairo::RefPtr<Cairo::Context>& cr, int width, int height);
};

#endif // GTKMM_EXAMPLE_MYAREA_H

File: main.cc (For use with gtkmm 4)

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

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

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

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

   return app->run(win, argc, argv);
}

File: myarea.cc (For use with gtkmm 4)

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

MyArea::MyArea()
{
  set_draw_func(sigc::mem_fun(*this, &MyArea::on_draw));
}

MyArea::~MyArea()
{
}

void MyArea::on_draw(const Cairo::RefPtr<Cairo::Context>& cr, int width, int 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();
}

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.

The call to Cairo::Context::curve_to() should be fairly self-explanatory. The first pair of coordinates define the control point for the beginning of the curve. The second set of coordinates define the control point for the end of the curve, and the last set of coordinates define the destination point. To make the concept of control points a bit easier to visualize, a line has been drawn from each control point to the end-point on the curve that it is associated with. Note that these control point lines are both translucent. This is achieved with a variant of set_source_rgb() called set_source_rgba(). This function takes a fourth argument specifying the alpha value of the color (valid values are between 0 and 1).