[cairo] Problem with degenerate lines

Steve Harrington steven.harrington at comcast.net
Sat Nov 6 12:20:56 PDT 2010


Searching the archives I found this method of drawing a single point:
       cairo_move_to( cr, x, y );
       cairo_close_path( cr );
       cairo_stroke( cr );

Which works fine in some cases.  However, the following code (in the 
expose handler) doesn't work as expected.  See the comments in the code 
for the results and times needed to draw them.  BTW is also seems to 
show a fairly gross inefficiency somewhere in the drawing chain.

Program attached.
/*
  * Test program for drawing single points.  Compile with:
  *        gcc -o Test Test.c  `pkg-config --cflags --libs gtk+-2.0`
  *
  *  This program is free software; you can redistribute it and/or
  *  modify it under the terms of version 2 of the GNU General Public 
License
  *  as published by the Free Software Foundation.
  *
  *  This program is distributed in the hope that it will be useful,
  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  *  GNU General Public License for more details.
  *
  *  You should have received a copy of the GNU General Public License
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 
02111-1307, USA.
  *  Or, point your browser to http://www.gnu.org/copyleft/gpl.html
  *
  *  Copyright (C) Steven Harrington 2010 <steven.harrington at comcast.net>
  */

#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <stdint.h>
#include <unistd.h>
#include <locale.h>
#include <error.h>
#include <errno.h>

#include <gtk/gtk.h>

static GtkWindow        *MainWindow;
static GtkDrawingArea   *DrawingArea;

static gboolean ExposeCB( GtkDrawingArea *w, GdkEventExpose *event,
               gpointer user_data )
{
   cairo_t        *cr;
   GtkAllocation   Allocation;
   int             i, j;
   clock_t         start, end;

   cr = gdk_cairo_create( gtk_widget_get_window(GTK_WIDGET(w)) );
   cairo_set_antialias( cr, CAIRO_ANTIALIAS_NONE );
   gtk_widget_get_allocation( GTK_WIDGET(w), &Allocation );

   start = clock();
   for( j=0; j< Allocation.height; j++ )
     for( i = 0; i < Allocation.width; i++ )
       {
     /* Set each point to a different color    */
     cairo_set_source_rgb( cr,
                   (double)i/Allocation.width,
                   (double)j/Allocation.height,
                   (double)(i*j)/(Allocation.width*Allocation.height)
                   );
       cairo_move_to( cr, i, j );
     
/*********************************************************************/
     /* Without one of these lines nothing gets drawn in    ~0.32 
seconds */
     /* With one of the next two lines an image is drawn in ~0.88 
seconds */
     cairo_line_to( cr, i, j+1 );
     cairo_line_to( cr, i+1, j );
     /* With this line an image is drawn in                 ~3.72 
seconds */
     cairo_line_to( cr, i+1, j+1 );
     
/*********************************************************************/
     cairo_close_path( cr );
     cairo_stroke( cr );
       }
   end = clock();
   fprintf( stderr, "CPU time used = %6.3lf seconds\n",
        ((double) (end - start)) / CLOCKS_PER_SEC );
   cairo_destroy( cr );
   return TRUE;
}

int main( int argc, char **argv )
{
   int    *argcP;
   char ***argvP;

   argcP = &argc;
   argvP = &argv;

   /* Initialize gtk                                     */
   gtk_init( argcP, argvP );

   /* Create the top level window                        */
   MainWindow = GTK_WINDOW( gtk_window_new(GTK_WINDOW_TOPLEVEL) );

   /* Connect the main signals                           */
   g_signal_connect_swapped ( MainWindow, "destroy",
                  G_CALLBACK(gtk_main_quit), NULL );
   /* Create the drawing area                            */
   DrawingArea = GTK_DRAWING_AREA( gtk_drawing_area_new( ) );
   gtk_widget_set_size_request( GTK_WIDGET(DrawingArea), 600, 600 );
   /* Connect the signals                                */
   gtk_widget_set_events( GTK_WIDGET(DrawingArea),
              GDK_EXPOSURE_MASK       |
              GDK_BUTTON_MOTION_MASK |
              GDK_BUTTON_PRESS_MASK   |
              GDK_BUTTON_RELEASE_MASK  );
   g_signal_connect( DrawingArea, "expose-event",
             G_CALLBACK(ExposeCB), NULL );
   /* Stick the drawing in the main window               */
   gtk_container_add( GTK_CONTAINER(MainWindow), GTK_WIDGET(DrawingArea) );
   /* Display the widgets                                */
   gtk_widget_show_all( GTK_WIDGET(MainWindow) );

   gtk_main( );

   exit( EXIT_SUCCESS );
}



More information about the cairo mailing list