1 /** pixBuf.c
2 \brief     pixBufs are offscreen drawables.
3 \author    William J Giddings email: wjgiddings@blueyonder.co.uk
4 \date      17-Jan-2010
5 \version   0.9.95
6 \note      Module generated by gnocl_template_assistant.
7 \bugs      SVG rotation and composition produce errors.
8 \history
9 			2013-07:	added commands, options, commands
10 			02/06/11	implemented PixbufParams, create pixbuf with
11 						assocated Cairo surface
12 			06/09/10	composite -completed implementation of all options
13 			17/08/10	pixbuf commands
14 							snapshot
15 							screenshot
16             09/04/10    pixbuf command
17                             duplicate
18             15/03/10    pixbuf command
19                             info
20             05/03/10
21                         pixbuf command
22                             setPixel
23             02/03/10    pixbuf command
24                             get drawable | image
25                             render
26             26/02/10    pixbuf command
27                             subpixbuf
28             20/02/10    pixbuf command
29                             copy
30             16/02/10    pixbuf command
31                             draw
32             15/02/10    pixbuf commands
33                             composite
34                             resize
35                             scale
36             14/02/10    pixbuf commands
37                             turn
38                             flip
39                             rotate
40                         commands
41                             load
42 
43             13/02/10    pixbuf commands
44                             save
45                             fill
46                             class
47             12/02/10    commands
48                             new
49             11/02/10    commands
50                             types
51                             description <type>
52                             license | licence <type>
53                             extension <type>
54                             scaleble <type>
55                             writable <type>
56                             fileInfo <fileName>
57 \todo
58         1) Resolve what acolor actually does.
59         2) Perform alpha channel operations.
60             set, erase, get
61 **/
62 
63 /**
64 \page page_pixbuf gnocl::pixBuf
65 \htmlinclude pixbuf.html
66 **/
67 
68 #include "gnocl.h"
69 #include "gnoclparams.h"
70 #include "gnocl_logo.h"
71 #include "gnocl_pointer.h"
72 
73 
74 /*****************
75  * relocated from cairo.c
76  * used to draw splash screen
77  ******************************/
78 
79 static gchar *dash;
80 
81 /* Key for automated pixbuf updating and destruction */
82 static const cairo_user_data_key_t pixbuf_key;
83 
84 cairo_t   *gnoclPixbufCairoCreate ( GdkPixbuf *pixbuf );
85 GdkPixbuf *gnoclPixbufCairoDestroy ( cairo_t   *cr, gboolean   create_new_pixbuf );
86 
87 /* Key for automated pixbuf updating and destruction */
88 static const cairo_user_data_key_t pixbuf_key;
89 
90 void gdk_pixbuf_get_pixel ( GdkPixbuf * pixbuf, guint x, guint y , guchar * r, guchar * g, guchar * b, guchar * a );
91 void gdk_pixbuf_set_pixel ( GdkPixbuf * pixbuf, guint32 pixel, guint x, guint y );
92 
93 
94 /**
95 \brief	This function will initialize new cairo context with contents of
96 		@pixbuf. You can then draw using returned context. When finished
97 		drawing, you must call gnoclPixbufCairoDestroy() or your pixbuf
98 		will not be updated with new contents!
99 
100  	Return value: New cairo_t context. When you're done with it, call
101  	gnoclPixbufCairoDestroy() to update your pixbuf and free memory.
102 **/
gnoclPixbufCairoCreate(GdkPixbuf * pixbuf)103 cairo_t * gnoclPixbufCairoCreate ( GdkPixbuf *pixbuf )
104 {
105 
106 	gint width;					/* Width of both pixbuf and surface */
107 	gint height;    			/* Height of both pixbuf and surface */
108 	gint p_stride;  			/* Pixbuf stride value */
109 	gint p_n_channels; 			/* RGB -> 3, RGBA -> 4 */
110 	gint s_stride;     			/* Surface stride value */
111 	guchar  *p_pixels;  		/* Pixbuf's pixel data */
112 	guchar *s_pixels;			/* Surface's pixel data */
113 	cairo_surface_t *surface;	/* Temporary image surface */
114 	cairo_t *cr;           		/* Final context */
115 
116 	g_object_ref ( G_OBJECT ( pixbuf ) );
117 
118 	/* Inspect input pixbuf and create compatible cairo surface */
119 	g_object_get ( G_OBJECT ( pixbuf ),
120 				   "width",		&width,
121 				   "height",		&height,
122 				   "rowstride",	&p_stride,
123 				   "n-channels",	&p_n_channels,
124 				   "pixels",		&p_pixels,
125 				   NULL );
126 	surface = cairo_image_surface_create ( CAIRO_FORMAT_ARGB32, width, height );
127 	s_stride = cairo_image_surface_get_stride ( surface );
128 	s_pixels = cairo_image_surface_get_data ( surface );
129 
130 	/* Copy pixel data from pixbuf to surface */
131 	while ( height-- )
132 	{
133 		gint    i;
134 		guchar *p_iter = p_pixels, *s_iter = s_pixels;
135 
136 		for ( i = 0; i < width; i++ )
137 		{
138 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
139 
140 			/* Pixbuf:  RGB(A)
141 			 * Surface: BGRA */
142 			if ( p_n_channels == 3 )
143 			{
144 				s_iter[0] = p_iter[2];
145 				s_iter[1] = p_iter[1];
146 				s_iter[2] = p_iter[0];
147 				s_iter[3] = 0xff;
148 			}
149 
150 			else /* p_n_channels == 4 */
151 			{
152 				gdouble alpha_factor = p_iter[3] / ( gdouble ) 0xff;
153 
154 				s_iter[0] = ( guchar ) ( p_iter[2] * alpha_factor + .5 );
155 				s_iter[1] = ( guchar ) ( p_iter[1] * alpha_factor + .5 );
156 				s_iter[2] = ( guchar ) ( p_iter[0] * alpha_factor + .5 );
157 				s_iter[3] =           p_iter[3];
158 			}
159 
160 #elif G_BYTE_ORDER == G_BIG_ENDIAN
161 
162 			/* Pixbuf:  RGB(A)
163 			 * Surface: ARGB */
164 			if ( p_n_channels == 3 )
165 			{
166 				s_iter[3] = p_iter[2];
167 				s_iter[2] = p_iter[1];
168 				s_iter[1] = p_iter[0];
169 				s_iter[0] = 0xff;
170 			}
171 
172 			else /* p_n_channels == 4 */
173 			{
174 				gdouble alpha_factor = p_iter[3] / ( gdouble ) 0xff;
175 
176 				s_iter[3] = ( guchar ) ( p_iter[2] * alpha_factor + .5 );
177 				s_iter[2] = ( guchar ) ( p_iter[1] * alpha_factor + .5 );
178 				s_iter[1] = ( guchar ) ( p_iter[0] * alpha_factor + .5 );
179 				s_iter[0] =           p_iter[3];
180 			}
181 
182 #else /* PDP endianness */
183 
184 			/* Pixbuf:  RGB(A)
185 			 * Surface: RABG */
186 			if ( p_n_channels == 3 )
187 			{
188 				s_iter[0] = p_iter[0];
189 				s_iter[1] = 0xff;
190 				s_iter[2] = p_iter[2];
191 				s_iter[3] = p_iter[1];
192 			}
193 
194 			else /* p_n_channels == 4 */
195 			{
196 				gdouble alpha_factor = p_iter[3] / ( gdouble ) 0xff;
197 
198 				s_iter[0] = ( guchar ) ( p_iter[0] * alpha_factor + .5 );
199 				s_iter[1] =           p_iter[3];
200 				s_iter[1] = ( guchar ) ( p_iter[2] * alpha_factor + .5 );
201 				s_iter[2] = ( guchar ) ( p_iter[1] * alpha_factor + .5 );
202 			}
203 
204 #endif
205 			s_iter += 4;
206 			p_iter += p_n_channels;
207 		}
208 
209 		s_pixels += s_stride;
210 		p_pixels += p_stride;
211 	}
212 
213 	/* Create context and set user data */
214 	cr = cairo_create ( surface );
215 	cairo_surface_destroy ( surface );
216 	cairo_set_user_data ( cr, &pixbuf_key, pixbuf, g_object_unref );
217 
218 	/* Return context */
219 	return ( cr );
220 }
221 
222 /**
223 
224 \note	If TRUE, new pixbuf will be created and returned.
225 		If FALSE, input pixbuf will be updated in place.
226 \brief	This function will destroy cairo context, created with gnoclPixbufCairoCreate().
227 
228 	Return value: New or updated GdkPixbuf. You own a new reference on return
229 	value, so you need to call g_object_unref() on returned pixbuf when you don't
230 	need it anymore.
231 **/
gnoclPixbufCairoDestroy(cairo_t * cr,gboolean create_new_pixbuf)232 GdkPixbuf *gnoclPixbufCairoDestroy ( cairo_t  *cr, gboolean  create_new_pixbuf )
233 {
234 	gint width;				/* Width of both pixbuf and surface */
235 	gint height;    		/* Height of both pixbuf and surface */
236 	gint p_stride;  		/* Pixbuf stride value */
237 	gint p_n_channels; 		/* RGB -> 3, RGBA -> 4 */
238 	gint s_stride;     		/* Surface stride value */
239 	guchar  *p_pixels;  	/* Pixbuf's pixel data */
240 	guchar *s_pixels;		/* Surface's pixel data */
241 	cairo_surface_t *surface;	/* Temporary image surface */
242 	GdkPixbuf *pixbuf;		/* Pixbuf to be returned */
243 	GdkPixbuf *tmp_pix;		/* Temporary storage */
244 
245 	/* Obtain pixbuf to be returned */
246 	tmp_pix = cairo_get_user_data ( cr, &pixbuf_key );
247 
248 	if ( create_new_pixbuf )
249 	{
250 		pixbuf = gdk_pixbuf_copy ( tmp_pix );
251 	}
252 
253 	else
254 	{
255 		pixbuf = g_object_ref ( G_OBJECT ( tmp_pix ) );
256 	}
257 
258 	/* Obtain surface from where pixel values will be copied */
259 	surface = cairo_get_target ( cr );
260 
261 	/* Inspect pixbuf and surface */
262 	g_object_get ( G_OBJECT ( pixbuf ), "width", &width, "height", &height, "rowstride", &p_stride,
263 				   "n-channels", &p_n_channels, "pixels", &p_pixels, NULL );
264 	s_stride = cairo_image_surface_get_stride ( surface );
265 	s_pixels = cairo_image_surface_get_data ( surface );
266 
267 	/* Copy pixel data from surface to pixbuf */
268 	while ( height-- )
269 	{
270 		gint    i;
271 		guchar *p_iter = p_pixels,
272 				*s_iter = s_pixels;
273 
274 		for ( i = 0; i < width; i++ )
275 		{
276 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
277 			/* Pixbuf:  RGB(A)
278 			 * Surface: BGRA */
279 			gdouble alpha_factor = ( gdouble ) 0xff / s_iter[3];
280 
281 			p_iter[0] = ( guchar ) ( s_iter[2] * alpha_factor + .5 );
282 			p_iter[1] = ( guchar ) ( s_iter[1] * alpha_factor + .5 );
283 			p_iter[2] = ( guchar ) ( s_iter[0] * alpha_factor + .5 );
284 
285 			if ( p_n_channels == 4 )
286 				p_iter[3] = s_iter[3];
287 
288 #elif G_BYTE_ORDER == G_BIG_ENDIAN
289 			/* Pixbuf:  RGB(A)
290 			 * Surface: ARGB */
291 			gdouble alpha_factor = ( gdouble ) 0xff / s_iter[0];
292 
293 			p_iter[0] = ( guchar ) ( s_iter[1] * alpha_factor + .5 );
294 			p_iter[1] = ( guchar ) ( s_iter[2] * alpha_factor + .5 );
295 			p_iter[2] = ( guchar ) ( s_iter[3] * alpha_factor + .5 );
296 
297 			if ( p_n_channels == 4 )
298 				p_iter[3] = s_iter[0];
299 
300 #else /* PDP endianness */
301 			/* Pixbuf:  RGB(A)
302 			 * Surface: RABG */
303 			gdouble alpha_factor = ( gdouble ) 0xff / s_iter[1];
304 
305 			p_iter[0] = ( guchar ) ( s_iter[0] * alpha_factor + .5 );
306 			p_iter[1] = ( guchar ) ( s_iter[3] * alpha_factor + .5 );
307 			p_iter[2] = ( guchar ) ( s_iter[2] * alpha_factor + .5 );
308 
309 			if ( p_n_channels == 4 )
310 				p_iter[3] = s_iter[1];
311 
312 #endif
313 			s_iter += 4;
314 			p_iter += p_n_channels;
315 		}
316 
317 		s_pixels += s_stride;
318 		p_pixels += p_stride;
319 	}
320 
321 	/* Destroy context */
322 	cairo_destroy ( cr );
323 
324 	/* Return pixbuf */
325 	return ( pixbuf );
326 }
327 
328 
329 /**********************************************************************/
330 
331 
332 PixbufParams *gnoclGetPixBufFromName ( const char *id, Tcl_Interp *interp );
333 const char *gnoclGetNameFromPixBuf ( GdkPixbuf *pixbuf );
334 guint32 convertRGBtoPixel ( gchar *clr );
335 static void set_pixel_color ( GdkPixbuf *pixbuf, int x, int y, guchar red, guchar green, guchar blue, guchar alpha );
336 //static guchar * create_gradient ( const GdkColor *primary, const GdkColor *secondary, int n_pixels );
337 
338 
339 /* needs to be public to be accessed by gnocl::inventory */
340 static GHashTable *name2pixbufList;
341 static const char idPrefix[] = "::gnocl::_PBUF";
342 
343 int gnoclOptOrientatePixBuf (	Tcl_Interp *interp,	GnoclOption *opt,	GObject *obj,	Tcl_Obj **ret );
344 
345 /*
346 canpixbufs be created and modified using standard properties?
347 */
348 static GnoclOption pixBufOptions[] =
349 {
350 	{ "-width", GNOCL_OBJ, "width"}, /* 0 */
351 	{ "-height", GNOCL_OBJ, "height"}, /* 1 */
352 	{ "-bitsPerSample", GNOCL_OBJ, "bits-per-sample"}, /* 2 */
353 	{ "-alpha", GNOCL_OBJ, "has-alpha"}, /* 3 */
354 	{ "-colorspace", GNOCL_OBJ, "colorspace"}, /* 4 */
355 	{ "-nChannels", GNOCL_OBJ, "n-channels"}, /* 5*/
356 	{ "-orientate", GNOCL_OBJ, gnoclOptOrientatePixBuf},
357 
358 	/* GtkObject Properties */
359 	{ "-data", GNOCL_OBJ, "", gnoclOptData },
360 
361 	{ NULL }
362 };
363 
364 static const int aIdx  = 0;
365 static const int bIdx  = 1;
366 static const int cIdx  = 2;
367 static const int dIdx  = 3;
368 static const int eIdx  = 4;
369 static const int fIdx  = 5;
370 
371 
372 /**
373 \note	Code taken from gnome-bg.c
374 **/
create_gradient(const GdkColor * primary,const GdkColor * secondary,int n_pixels)375 guchar * create_gradient ( const GdkColor *primary, const GdkColor *secondary, int n_pixels )
376 {
377 	guchar *result = g_malloc ( n_pixels * 3 );
378 	int i;
379 
380 	for ( i = 0; i < n_pixels; ++i )
381 	{
382 		double ratio = ( i + 0.5 ) / n_pixels;
383 
384 		result[3 * i + 0] = ( ( guint16 ) ( primary->red * ( 1 - ratio ) + secondary->red * ratio ) ) >> 8;
385 		result[3 * i + 1] = ( ( guint16 ) ( primary->green * ( 1 - ratio ) + secondary->green * ratio ) ) >> 8;
386 		result[3 * i + 2] = ( ( guint16 ) ( primary->blue * ( 1 - ratio ) + secondary->blue * ratio ) ) >> 8;
387 	}
388 
389 	return result;
390 }
391 
392 /**
393 \note	Code taken from gnome-bg.c
394 **/
pixbuf_draw_gradient(GdkPixbuf * pixbuf,gboolean horizontal,GdkColor * primary,GdkColor * secondary,GdkRectangle * rect)395 static void pixbuf_draw_gradient ( GdkPixbuf *pixbuf, gboolean horizontal, GdkColor *primary, GdkColor *secondary, GdkRectangle *rect )
396 {
397 	int width;
398 	int height;
399 	int rowstride;
400 	guchar *dst;
401 	guchar *dst_limit;
402 	int n_channels = 3;
403 
404 	rowstride = gdk_pixbuf_get_rowstride ( pixbuf );
405 	width = rect->width;
406 	height = rect->height;
407 	dst = gdk_pixbuf_get_pixels ( pixbuf ) + rect->x * n_channels + rowstride * rect->y;
408 	dst_limit = dst + height * rowstride;
409 
410 	if ( horizontal )
411 	{
412 		guchar *gradient = create_gradient ( primary, secondary, width );
413 		int copy_bytes_per_row = width * n_channels;
414 		int i;
415 
416 		for ( i = 0; i < height; i++ )
417 		{
418 			guchar *d;
419 			d = dst + rowstride * i;
420 			memcpy ( d, gradient, copy_bytes_per_row );
421 		}
422 
423 		g_free ( gradient );
424 	}
425 
426 	else
427 	{
428 		guchar *gb, *gradient;
429 		int i;
430 
431 		gradient = create_gradient ( primary, secondary, height );
432 
433 		for ( i = 0; i < height; i++ )
434 		{
435 			int j;
436 			guchar *d;
437 
438 			d = dst + rowstride * i;
439 			gb = gradient + n_channels * i;
440 
441 			for ( j = width; j > 0; j-- )
442 			{
443 				int k;
444 
445 				for ( k = 0; k < n_channels; k++ )
446 				{
447 					* ( d++ ) = gb[k];
448 				}
449 			}
450 		}
451 
452 		g_free ( gradient );
453 	}
454 }
455 
456 /**
457 \note	Code taken from gnome-bg.c
458 **/
pixbuf_blend(GdkPixbuf * src,GdkPixbuf * dest,int src_x,int src_y,int src_width,int src_height,int dest_x,int dest_y,double alpha)459 static void pixbuf_blend ( GdkPixbuf *src, GdkPixbuf *dest, int src_x, int src_y, int src_width, int src_height, int dest_x, int dest_y, double	alpha )
460 {
461 	int dest_width = gdk_pixbuf_get_width ( dest );
462 	int dest_height = gdk_pixbuf_get_height ( dest );
463 	int offset_x = dest_x - src_x;
464 	int offset_y = dest_y - src_y;
465 
466 	if ( src_width < 0 )
467 		src_width = gdk_pixbuf_get_width ( src );
468 
469 	if ( src_height < 0 )
470 		src_height = gdk_pixbuf_get_height ( src );
471 
472 	if ( dest_x < 0 )
473 		dest_x = 0;
474 
475 	if ( dest_y < 0 )
476 		dest_y = 0;
477 
478 	if ( dest_x + src_width > dest_width )
479 	{
480 		src_width = dest_width - dest_x;
481 	}
482 
483 	if ( dest_y + src_height > dest_height )
484 	{
485 		src_height = dest_height - dest_y;
486 	}
487 
488 	gdk_pixbuf_composite ( src, dest,
489 						   dest_x, dest_y,
490 						   src_width, src_height,
491 						   offset_x, offset_y,
492 						   1, 1, GDK_INTERP_NEAREST,
493 						   alpha * 0xFF + 0.5 );
494 }
495 
496 /**
497 \note	Code taken from gnome-bg.c
498 **/
pixbuf_tile(GdkPixbuf * src,GdkPixbuf * dest)499 static void pixbuf_tile ( GdkPixbuf *src, GdkPixbuf *dest )
500 {
501 	int x, y;
502 	int tile_width, tile_height;
503 	int dest_width = gdk_pixbuf_get_width ( dest );
504 	int dest_height = gdk_pixbuf_get_height ( dest );
505 
506 	tile_width = gdk_pixbuf_get_width ( src );
507 	tile_height = gdk_pixbuf_get_height ( src );
508 
509 	for ( y = 0; y < dest_height; y += tile_height )
510 	{
511 		for ( x = 0; x < dest_width; x += tile_width )
512 		{
513 			pixbuf_blend ( src, dest, 0, 0,
514 						   tile_width, tile_height, x, y, 1.0 );
515 		}
516 	}
517 }
518 
519 /**
520 \note	Code taken from gnome-bg.c
521 **/
pixbuf_clip_to_fit(GdkPixbuf * src,int max_width,int max_height)522 static GdkPixbuf * pixbuf_clip_to_fit ( GdkPixbuf *src, int max_width, int max_height )
523 {
524 	int src_width, src_height;
525 	int w, h;
526 	int src_x, src_y;
527 	GdkPixbuf *pixbuf;
528 
529 	src_width = gdk_pixbuf_get_width ( src );
530 	src_height = gdk_pixbuf_get_height ( src );
531 
532 	if ( src_width < max_width && src_height < max_height )
533 		return g_object_ref ( src );
534 
535 	w = MIN ( src_width, max_width );
536 	h = MIN ( src_height, max_height );
537 
538 	pixbuf = gdk_pixbuf_new ( GDK_COLORSPACE_RGB,
539 							  gdk_pixbuf_get_has_alpha ( src ),
540 							  8, w, h );
541 
542 	src_x = ( src_width - w ) / 2;
543 	src_y = ( src_height - h ) / 2;
544 	gdk_pixbuf_copy_area ( src,
545 						   src_x, src_y,
546 						   w, h,
547 						   pixbuf,
548 						   0, 0 );
549 	return pixbuf;
550 }
551 
552 
553 /**
554 \brief  Takes an existing pixbuf and checks for the presence of an
555 		associated "orientation" option, which may be provided by the
556 		jpeg loader (which reads the exif orientation tag) or the tiff
557 		loader (which reads the tiff orientation tag, and compensates it
558 		for the partial transforms performed by libtiff). If an
559 		orientation option/tag is present, the appropriate transform
560 		will be performed so that the pixbuf is oriented correctly.
561 
562 **/
gnoclOptOrientatePixBuf(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)563 int gnoclOptOrientatePixBuf (	Tcl_Interp *interp,	GnoclOption *opt,	GObject *obj,	Tcl_Obj **ret )
564 {
565 
566 	//GdkPixbuf * gdk_pixbuf_apply_embedded_orientation (GdkPixbuf *src);
567 }
568 
569 /**
570 \brief
571 **/
gnoclGetPixBufList(GList ** list)572 void gnoclGetPixBufList ( GList **list )
573 {
574 	g_hash_table_foreach ( name2pixbufList, hash_to_list, list );
575 }
576 
577 /**
578 \brief  Rotate a pixbuf through an arbitrary angle (degrees).
579 \author
580 \date   15/Feb/2010
581 \since  0.9.94
582 \note   Adaption of:
583      GdkPixbuf * gdk_pixbuf_rotate(GdkPixbuf *pixbuf, double angle, int acolor)
584 
585      The returned image has the same size as the original, but the
586      pixbuf envelope is increased to accomodate the rotated original
587      (e.g. a 100x100 pixbuf rotated 45 deg. needs a 142x142 pixbuf).
588 
589      Pixels added around the rotated image have all RGB values = acolor.   //  v.2.17
590 
591      Angle is in degrees. Positive direction is clockwise.
592      Pixbuf must have 8 bits per channel and 3 or 4 channels.
593      Loss of resolution is about 1/2 pixel.
594      Speed is about 18 million pixels/sec. on my 2.67 GHz CPU.             //  v.3.2
595 
596      NULL is returned if the function fails for one of the following:
597          - pixbuf not 8 bits/channel or < 3 channels
598          - unable to create output pixbuf (lack of memory?)
599 
600      Algorithm:
601          create output pixbuf big enough for rotated input pixbuf
602          compute coefficients for affine transform
603          loop all output pixels
604             get next output pixel (px2,py2)
605             convert to input pixel (px1,py1) using affine transform        //  v.3.2
606             if outside of pixmap
607                output pixel = black
608                continue
609             for 4 input pixels based at (px0,py0) = (int(px1),int(py1))
610                compute overlap (0 to 1) with (px1,py1)
611                sum RGB values * overlap
612             output aggregate RGB to pixel (px2,py2)
613 \see    http://kornelix.squarespace.com
614 
615     Note: Not really certain what the acolor variable actually does.
616 
617 **/
pixbufRotate(GdkPixbuf * pixbuf1,double angle,int acolor)618 GdkPixbuf * pixbufRotate ( GdkPixbuf *pixbuf1, double angle, int acolor )
619 {
620 
621 	g_print ( "%s 1 %f\n", __FUNCTION__, angle );
622 
623 	/* 3 RGB values, 0-255 each */
624 	typedef unsigned char  *pixel;
625 
626 	GdkPixbuf *pixbuf2;
627 	GdkColorspace color;
628 
629 	int nch, nbits, alpha;
630 	int ww1, hh1, rs1, ww2, hh2, rs2;
631 	int px2, py2, px0, py0;
632 	pixel ppix1, ppix2, pix0, pix1, pix2, pix3;
633 	double px1, py1;
634 	double f0, f1, f2, f3, red, green, blue;
635 	double a, b, d, e, ww15, hh15, ww25, hh25;
636 	double pi = 3.141593;
637 
638 	nch = gdk_pixbuf_get_n_channels ( pixbuf1 );
639 	nbits = gdk_pixbuf_get_bits_per_sample ( pixbuf1 );
640 
641 	/* must have 3+ channels (colors) */
642 	if ( nch < 3 ) return 0;
643 
644 	/* must be 8 bits per channel */
645 	if ( nbits != 8 ) return 0;
646 
647 
648 	g_print ( "%s 2\n", __FUNCTION__ );
649 
650 
651 	/* get input pixbuf1 attributes */
652 	color = gdk_pixbuf_get_colorspace ( pixbuf1 );
653 	alpha = gdk_pixbuf_get_has_alpha ( pixbuf1 );
654 	ww1 = gdk_pixbuf_get_width ( pixbuf1 );
655 	hh1 = gdk_pixbuf_get_height ( pixbuf1 );
656 	rs1 = gdk_pixbuf_get_rowstride ( pixbuf1 );
657 
658 	/* normalize, -180 to +180 */
659 	while ( angle < -180 ) angle += 360;
660 
661 	while ( angle > 180 ) angle -= 360;
662 
663 	/* radians, -pi to +pi */
664 	angle = angle * pi / 180;
665 
666 	/*  bugfix 0.01 >> 0.001   v.2.1 */
667 	if ( fabs ( angle ) < 0.001 )
668 	{
669 		/* angle is zero within my precision */
670 		pixbuf2 = gdk_pixbuf_copy ( pixbuf1 );
671 		return pixbuf2;
672 	}
673 
674 	/* rectangle containing rotated image */
675 	ww2 = ww1 * fabs ( cos ( angle ) ) + hh1 * fabs ( sin ( angle ) );
676 	hh2 = ww1 * fabs ( sin ( angle ) ) + hh1 * fabs ( cos ( angle ) );
677 
678 	/* create output pixbuf2 */
679 	pixbuf2 = gdk_pixbuf_new ( color, alpha, nbits, ww2, hh2 );
680 
681 
682 
683 
684 	if ( ! pixbuf2 ) return 0;
685 
686 	rs2 = gdk_pixbuf_get_rowstride ( pixbuf2 );
687 
688 	/* input pixel array */
689 	ppix1 = gdk_pixbuf_get_pixels ( pixbuf1 );
690 
691 	/* output pixel array */
692 	ppix2 = gdk_pixbuf_get_pixels ( pixbuf2 );
693 
694 	ww15 = 0.5 * ww1;
695 	hh15 = 0.5 * hh1;
696 	ww25 = 0.5 * ww2;
697 	hh25 = 0.5 * hh2;
698 
699 	/* affine transform coefficients   v.3.2 */
700 	a = cos ( angle );
701 	b = sin ( angle );
702 	d = - sin ( angle );
703 	e = cos ( angle );
704 
705 	/* loop through output pixels */
706 	for ( py2 = 0; py2 < hh2; py2++ )
707 		for ( px2 = 0; px2 < ww2; px2++ )
708 		{
709 			/* (px1,py1) = corresponding       v.3.2 */
710 			px1 = a * ( px2 - ww25 ) + b * ( py2 - hh25 ) + ww15;
711 
712 			/* point within input pixels */
713 			py1 = d * ( px2 - ww25 ) + e * ( py2 - hh25 ) + hh15;
714 
715 			/* pixel containing (px1,py1) */
716 			px0 = px1;
717 			py0 = py1;
718 
719 			/* if outside input pixel array */
720 			if ( px1 < 0 || px0 >= ww1 - 1 || py1 < 0 || py0 >= hh1 - 1 )
721 			{
722 				/* output is acolor    v.2.17 */
723 				pix2 = ppix2 + py2 * rs2 + px2 * nch;
724 				pix2[0] = pix2[1] = pix2[2] = acolor;
725 				continue;
726 			}
727 
728 			/* 4 input pixels based at (px0,py0) */
729 			pix0 = ppix1 + py0 * rs1 + px0 * nch;
730 			pix1 = pix0 + rs1;
731 			pix2 = pix0 + nch;
732 			pix3 = pix0 + rs1 + nch;
733 
734 			/* overlap of (px1,py1) */
735 			f0 = ( px0 + 1 - px1 ) * ( py0 + 1 - py1 );
736 
737 			/* in each of the 4 pixels */
738 			f1 = ( px0 + 1 - px1 ) * ( py1 - py0 );
739 			f2 = ( px1 - px0 ) * ( py0 + 1 - py1 );
740 			f3 = ( px1 - px0 ) * ( py1 - py0 );
741 
742 			/* sum the weighted inputs */
743 			red =   f0 * pix0[0] + f1 * pix1[0] + f2 * pix2[0] + f3 * pix3[0];
744 			green = f0 * pix0[1] + f1 * pix1[1] + f2 * pix2[1] + f3 * pix3[1];
745 			blue =  f0 * pix0[2] + f1 * pix1[2] + f2 * pix2[2] + f3 * pix3[2];
746 
747 			/* avoid acolor in image     v.2.17 */
748 			if ( red == acolor && green == acolor && blue == acolor )
749 			{
750 				if ( blue == 0 ) blue = 1;
751 				else blue--;
752 			}
753 
754 			/* output pixel */
755 			pix2 = ppix2 + py2 * rs2 + px2 * nch;
756 			pix2[0] = red;
757 			pix2[1] = green;
758 			pix2[2] = blue;
759 		}
760 
761 	return pixbuf2;
762 }
763 
764 /**
765 \brief
766 \note       From module parseoptions.c
767 **/
getShortValue(Tcl_Interp * interp,Tcl_Obj * list,int idx,int * p)768 static int getShortValue ( Tcl_Interp *interp, Tcl_Obj *list, int idx, int *p )
769 {
770 	int val;
771 	Tcl_Obj *tp;
772 
773 	if ( Tcl_ListObjIndex ( interp, list, idx, &tp ) != TCL_OK  )
774 		return TCL_ERROR;
775 
776 	if ( Tcl_GetIntFromObj ( NULL, tp, &val ) != TCL_OK )
777 	{
778 		double d;
779 
780 		if ( Tcl_GetDoubleFromObj ( NULL, tp, &d ) != TCL_OK )
781 		{
782 			Tcl_AppendResult ( interp,
783 							   "expected integer or double, but got \"",
784 							   Tcl_GetString ( tp ), "\"", NULL );
785 			return TCL_ERROR;
786 		}
787 
788 		val = d * 0xFFFF;
789 	}
790 
791 	if ( val < .0 || val > 0xFFFF )
792 	{
793 		Tcl_SetResult ( interp, "color value must be between 0 and 65535",
794 						TCL_STATIC );
795 		return TCL_ERROR;
796 	}
797 
798 	*p = val;
799 
800 	return TCL_OK;
801 }
802 
803 /**
804 \brief
805 \author     Tadej Borovšak
806 \date       14/Feb/2010
807 \note       gdk_color_parse() will only fill red, green and blue elements
808              of GdkColor. In order to fill pixel value, you'll need to
809              allocate your color using gdk_colormap_alloc_color().
810              But event if you do this, pixel value is not what you want
811              in this case, since pixel value is only meaningful in context
812              of your underlying windowing system.
813 
814 **/
convertRGBtoPixel(gchar * clr)815 guint32 convertRGBtoPixel ( gchar *clr )
816 {
817 
818 	GdkColor color;
819 	guint32 pixel;
820 
821 	/* Conversion factor from 16-bit color to 8-bit color (0xff / 0xffff) */
822 	const gdouble f = 0.00389105;
823 
824 	/* create the colour from the supplied string, added by WJG */
825 	gdk_color_parse ( clr, &color );
826 
827 	/* fill with colour */
828 	pixel = ( ( ( guint ) ( color.red   * f + 0.5 ) ) << 24 ) | /* R */
829 			( ( ( guint ) ( color.green * f + 0.5 ) ) << 16 ) | /* G */
830 			( ( ( guint ) ( color.blue  * f + 0.5 ) ) <<  8 ) | /* B */
831 			( 0xff <<  0 );                                     /* A */
832 
833 #ifdef DEBUG_PIXBUF
834 	printf ( "pixel = %d\n", pixel );
835 #endif
836 	return pixel;
837 }
838 
839 
840 /**
841 \brief
842 \note       From module parseoptions.c
843 **/
getRGBA(Tcl_Interp * interp,Tcl_Obj * obj,int * r,int * g,int * b,int * a)844 static int getRGBA ( Tcl_Interp *interp, Tcl_Obj *obj, int *r, int *g, int *b, int *a )
845 {
846 	int no;
847 
848 	if ( Tcl_ListObjLength ( interp, obj, &no ) != TCL_OK  || no < 0 || no > 4 )
849 	{
850 		Tcl_SetResult ( interp, "color must be either \"name\" or a list "
851 						"consisting of \"name alpha\", \"r g b\", or \"r g b alpha\"",
852 						TCL_STATIC );
853 		return TCL_ERROR;
854 	}
855 
856 	if ( no == 0 ) /* transparent */
857 	{
858 		*r = *g = *b = *a = 0;
859 	}
860 
861 	else if ( no < 3 )
862 	{
863 		Tcl_Obj *tp = obj;
864 		GdkColor color;
865 
866 		if ( no == 2 )
867 		{
868 			if ( Tcl_ListObjIndex ( interp, obj, 0, &tp ) != TCL_OK )
869 				return TCL_ERROR;
870 		}
871 
872 		/* take as string and reformat as a GdkColor structure */
873 
874 		if ( gdk_color_parse ( Tcl_GetString ( tp ), &color ) == 0 )
875 		{
876 			Tcl_AppendResult ( interp, "unknown color \"", Tcl_GetString ( obj ), "\".", ( char * ) NULL );
877 			return TCL_ERROR;
878 		}
879 
880 		*r = color.red;
881 		*g = color.green;
882 		*b = color.blue;
883 
884 		if ( no == 2 )
885 		{
886 			if ( getShortValue ( interp, obj, 1, a ) != TCL_OK )
887 				return TCL_ERROR;
888 		}
889 
890 		else
891 			*a = 0xFFFF;
892 	}
893 
894 	else
895 	{
896 		if ( getShortValue ( interp, obj, 0, r ) != TCL_OK
897 				|| getShortValue ( interp, obj, 1, g ) != TCL_OK
898 				|| getShortValue ( interp, obj, 2, b ) != TCL_OK )
899 			return TCL_ERROR;
900 
901 		if ( no == 4 )
902 		{
903 			if ( getShortValue ( interp, obj, 3, a ) != TCL_OK )
904 				return TCL_ERROR;
905 		}
906 
907 		else
908 			*a = 0xFFFF;
909 	}
910 
911 	return TCL_OK;
912 }
913 
914 /**
915 \brief      Take colour values from a string format and assign them to
916             location addressed by pointer *color.
917 **/
getGdkColor(Tcl_Interp * interp,Tcl_Obj * obj,GdkColor * color)918 static int getGdkColor ( Tcl_Interp *interp, Tcl_Obj *obj, GdkColor *color )
919 {
920 	int r, g, b, a;
921 
922 	if ( getRGBA ( interp, obj, &r, &g, &b, &a ) != TCL_OK )
923 	{
924 		return TCL_ERROR;
925 	}
926 
927 	/* TODO? if a != 0xFFFF: alpha not supported? */
928 	color->red = r;
929 
930 	color->green = g;
931 
932 	color->blue = b;
933 
934 	return TCL_OK;
935 }
936 
937 /**
938 \brief      Function associated with the pixbufs.
939 **/
pixBufFunc(ClientData data,Tcl_Interp * interp,int objc,Tcl_Obj * const objv[])940 int pixBufFunc ( ClientData data, Tcl_Interp *interp, int objc, Tcl_Obj * const objv[] )
941 {
942 
943 #ifdef DEBUG_PIXBUF
944 	listParameters ( objc, objv, "pixBufFunc" );
945 #endif
946 
947 	//GdkPixbuf *pixbuf;
948 	//GdkPixbuf *dest->pixbuf;
949 
950 	PixbufParams *para, *dest;
951 
952 	para = ( PixbufParams * ) data;
953 	dest = g_new ( PixbufParams, 1 );
954 
955 
956 	//pixbuf = GDK_PIXBUF ( data );
957 
958 	static const char *cmds[] =
959 	{
960 		"copy", "delete", "configure", "duplicate",
961 		"cget", "draw", "class",
962 		"fill", "flood", "save", "turn",
963 		"flip", "rotate", "composite",
964 		"subpixbuf",
965 		"saturation", "pixelate", "colorize",
966 		"getPixel", "setPixel", "info", "filter",
967 		"scale", "resize", "addAlpha", "options", "commands",
968 		NULL
969 	};
970 
971 	enum cmdIdx
972 	{
973 		CopyIdx, DeleteIdx, ConfigureIdx, DuplicateIdx,
974 		CgetIdx, DrawIdx, ClassIdx,
975 		FillIdx, FloodIdx, SaveIdx, TurnIdx,
976 		FlipIdx, RotateIdx, CompositeIdx,
977 		SubPixBufIdx,
978 		SaturationIdx, PixelateIdx, ColorizeIdx,
979 		GetPixelIdx, SetPixelIdx, InfoIdx, FilterIdx,
980 		ScaleIdx, ResizeIdx, AddAlphaIdx, OptionsIdx, CommandsIdx
981 	};
982 
983 	int idx;
984 
985 	if ( objc < 2 )
986 	{
987 		Tcl_WrongNumArgs ( interp, 1, objv, "command" );
988 		return TCL_ERROR;
989 	}
990 
991 	if ( Tcl_GetIndexFromObj ( interp, objv[1], cmds, "command", TCL_EXACT, &idx ) != TCL_OK )
992 	{
993 		return TCL_ERROR;
994 	}
995 
996 	switch ( idx )
997 	{
998 		case CommandsIdx:
999 			{
1000 				gnoclGetOptions ( interp, cmds );
1001 			}
1002 			break;
1003 		case OptionsIdx:
1004 			{
1005 				gnoclGetOptions ( interp, pixBufOptions );
1006 			}
1007 			break;
1008 		case FloodIdx:
1009 			{
1010 
1011 				g_print ( "FloodIdx\n" );
1012 
1013 				guint x, y;
1014 
1015 				sscanf ( Tcl_GetString ( objv[2] ), "%u", &x );
1016 				sscanf ( Tcl_GetString ( objv[3] ), "%u", &x );
1017 
1018 
1019 				//void gdk_pixbuf_flood_fill ( GdkPixbuf *pixbuf, guint fill_color, guint x, guint y )
1020 				//gdk_pixbuf_flood_fill ( para->pixbuf, convertRGBtoPixel (Tcl_GetString ( objv[4] )) , x, y );
1021 				gdk_pixbuf_flood_fill ( para->pixbuf, 0x0000ff00 , x, y );
1022 			}
1023 			break;
1024 		case AddAlphaIdx:
1025 			{
1026 				/*
1027 				GdkPixbuf * gdk_pixbuf_add_alpha (const GdkPixbuf *pixbuf, gboolean substitute_color, guchar r, guchar g, guchar b);
1028 				*/
1029 			}
1030 			break;
1031 		case ScaleIdx:
1032 			{
1033 
1034 				GdkInterpType interp_type;
1035 				interp_type = GDK_INTERP_BILINEAR;
1036 				float xScale, yScale;
1037 				gint w, h, i, resizeIdx;
1038 				float dest_width, dest_height;
1039 
1040 				static char *resizeOptions[] =
1041 				{
1042 					"-height", "-width",
1043 					NULL
1044 				};
1045 
1046 				static enum  optsIdx
1047 				{
1048 					heightIdx, widthIdx
1049 				};
1050 
1051 				xScale = -1;
1052 				yScale = -1;
1053 
1054 				if ( objc == 3 )
1055 				{
1056 
1057 					sscanf ( Tcl_GetString ( objv[2] ), "%f", &xScale );
1058 					yScale = xScale;
1059 
1060 				}
1061 
1062 				/* parse all the options */
1063 				i = 2;
1064 
1065 				while ( i < objc )
1066 				{
1067 					getIdx ( resizeOptions, Tcl_GetString ( objv[i] ), &resizeIdx );
1068 
1069 					switch ( resizeIdx )
1070 					{
1071 						case heightIdx:
1072 							{
1073 #ifdef DEBUG_PIXBUF
1074 								g_print ( "height\n" );
1075 #endif
1076 
1077 								sscanf ( Tcl_GetString ( objv[i+1] ), "%f", &yScale );
1078 
1079 							} break;
1080 						case widthIdx:
1081 							{
1082 #ifdef DEBUG_PIXBUF
1083 								g_print ( "width\n" );
1084 #endif
1085 								sscanf ( Tcl_GetString ( objv[i+1] ), "%f", &xScale );
1086 							} break;
1087 						default:
1088 							{
1089 							}
1090 					}
1091 
1092 					i += 2;
1093 				}
1094 
1095 				if ( xScale == -1 )
1096 				{
1097 					xScale = yScale;
1098 
1099 				}
1100 
1101 				if ( yScale == -1 )
1102 				{
1103 					yScale = xScale;
1104 				}
1105 
1106 
1107 				if ( xScale == -1 && yScale == -1 )
1108 				{
1109 					xScale = 1;
1110 					yScale = 1;
1111 				}
1112 
1113 				w = gdk_pixbuf_get_width ( para->pixbuf );
1114 				h = gdk_pixbuf_get_height ( para->pixbuf );
1115 
1116 				dest_width = ( float ) w * xScale;
1117 				dest_height = ( float ) h * yScale;
1118 
1119 #ifdef DEBUG_PIXBUF
1120 				g_print ( "i = %d dest_width, dest_height = %f %f\n", i, dest_width, dest_height );
1121 #endif
1122 				dest->pixbuf = gdk_pixbuf_scale_simple (  para->pixbuf, ( int ) dest_width, ( int ) dest_height, interp_type );
1123 
1124 				para->pixbuf = dest->pixbuf;
1125 				return gnoclRegisterPixBuf_ ( interp, para, pixBufFunc );
1126 				return gnoclRegisterPixBuf ( interp, dest->pixbuf, pixBufFunc );
1127 			}
1128 			break;
1129 		case ResizeIdx:
1130 			{
1131 
1132 				GdkInterpType interp_type;
1133 				interp_type = GDK_INTERP_BILINEAR;
1134 				gint dest_width, dest_height;
1135 				gint i, w, h;
1136 				gint resizeIdx;
1137 
1138 				dest_width = -1 ;
1139 				dest_height = -1;
1140 
1141 				static char *resizeOptions[] =
1142 				{
1143 					"-height", "-width",
1144 					NULL
1145 				};
1146 
1147 				static enum  optsIdx
1148 				{
1149 					heightIdx, widthIdx
1150 				};
1151 
1152 				/* parse all the options */
1153 				i = 2;
1154 
1155 				while ( i < objc )
1156 				{
1157 
1158 					getIdx ( resizeOptions, Tcl_GetString ( objv[i] ), &resizeIdx );
1159 
1160 					switch ( resizeIdx )
1161 					{
1162 						case heightIdx:
1163 							{
1164 #ifdef DEBUG_PIXBUF
1165 								g_print ( "height\n" );
1166 #endif
1167 
1168 								sscanf ( Tcl_GetString ( objv[i+1] ), "%d", &dest_height );
1169 
1170 							} break;
1171 						case widthIdx:
1172 							{
1173 #ifdef DEBUG_PIXBUF
1174 								g_print ( "width\n" );
1175 #endif
1176 								sscanf ( Tcl_GetString ( objv[i+1] ), "%d", &dest_width );
1177 							} break;
1178 						default:
1179 							{
1180 							}
1181 					}
1182 
1183 					i += 2;
1184 				}
1185 
1186 				//return TCL_OK;
1187 
1188 				//i = sscanf ( Tcl_GetString ( objv[2] ), "%d %d", &dest_width, &dest_height );
1189 
1190 				if ( dest_width == -1 &&  dest_height == -1 )
1191 				{
1192 
1193 #ifdef DEBUG_PIXBUF
1194 					g_print ( "plain copy\n" );
1195 #endif
1196 
1197 					dest->pixbuf = gdk_pixbuf_copy ( para->pixbuf );
1198 
1199 					/* need to create a new para here */
1200 
1201 					para->pixbuf = dest->pixbuf;
1202 					return gnoclRegisterPixBuf_ ( interp, para, pixBufFunc );
1203 					return gnoclRegisterPixBuf ( interp, dest->pixbuf, pixBufFunc );
1204 				}
1205 
1206 				if ( dest_height == -1 )
1207 				{
1208 					/* scale height in proportion to width */
1209 					w = gdk_pixbuf_get_width ( para->pixbuf );
1210 					h = gdk_pixbuf_get_height ( para->pixbuf );
1211 
1212 					dest_height = dest_width * h / w;
1213 				}
1214 
1215 				if ( dest_width == -1 )
1216 				{
1217 					/* scale height in proportion to width */
1218 					w = gdk_pixbuf_get_width ( para->pixbuf );
1219 					h = gdk_pixbuf_get_height ( para->pixbuf );
1220 
1221 					dest_width = dest_height * w / h;
1222 				}
1223 
1224 				dest->pixbuf = gdk_pixbuf_scale_simple (  para->pixbuf, dest_width, dest_height, interp_type );
1225 
1226 				para->pixbuf = dest->pixbuf;
1227 
1228 				return gnoclRegisterPixBuf_ ( interp, para, pixBufFunc );
1229 				return gnoclRegisterPixBuf ( interp, dest->pixbuf, pixBufFunc );
1230 			}
1231 		case DuplicateIdx:
1232 			{
1233 
1234 				dest->pixbuf = gdk_pixbuf_copy ( para->pixbuf );
1235 
1236 				para->pixbuf = dest->pixbuf;
1237 
1238 				return gnoclRegisterPixBuf_ ( interp, para, pixBufFunc );
1239 				return gnoclRegisterPixBuf ( interp, dest->pixbuf, pixBufFunc );
1240 			}
1241 			break;
1242 		case FilterIdx:
1243 			{
1244 				gnoclPixBufFilters ( interp, para->pixbuf ,  objc, objv );
1245 			}
1246 			break;
1247 		case InfoIdx:
1248 			{
1249 				gchar str[32];
1250 				gint w, h, a, bps, n;
1251 				w = gdk_pixbuf_get_width ( para->pixbuf );
1252 				h = gdk_pixbuf_get_height ( para->pixbuf );
1253 				a = gdk_pixbuf_get_has_alpha ( para->pixbuf );
1254 				bps = gdk_pixbuf_get_bits_per_sample ( para->pixbuf );
1255 				n = gdk_pixbuf_get_n_channels ( para->pixbuf );
1256 
1257 				sprintf ( str, "%d %d %d %d %d", w, h, a, bps, n );
1258 
1259 				Tcl_SetResult ( interp, str, TCL_STATIC );
1260 
1261 			}
1262 			break;
1263 		case SetPixelIdx:
1264 			{
1265 
1266 				gint x, y, w, h;
1267 				guchar r, g, b, a;
1268 
1269 				/* set pixel location */
1270 				sscanf ( Tcl_GetString ( objv[2] ), "%d %d", &x, &y );
1271 				sscanf ( Tcl_GetString ( objv[3] ),  "%d %d %d %d", &r, &g, &b , &a );
1272 
1273 				w = gdk_pixbuf_get_width ( para->pixbuf );
1274 				h = gdk_pixbuf_get_height ( para->pixbuf );
1275 
1276 				if ( 0 )
1277 				{
1278 					GdkColor color;
1279 
1280 					if ( getGdkColor ( interp, Tcl_GetString ( objv[3] ), &color ) != TCL_OK )
1281 					{
1282 						return TCL_ERROR;
1283 					}
1284 				}
1285 
1286 				//set_pixel_color ( pixbuf, x, y , r, g, b, a );
1287 #ifdef DEBUG_PIXBUF
1288 				g_printf ( "x =%d y =%d w =%d h =%d\n", x, y, w, h );
1289 				g_printf ( "r =%d g =%d b =%d a =%d\n", r, g, b, a );
1290 #endif
1291 
1292 				/* error checking */
1293 				if ( x < 0 || x > gdk_pixbuf_get_width ( para->pixbuf )  )
1294 				{
1295 					//   return FALSE;
1296 				}
1297 
1298 				if ( y < 0 || y > gdk_pixbuf_get_height ( para->pixbuf )  )
1299 				{
1300 					//  return FALSE;
1301 				}
1302 
1303 				gdk_pixbuf_set_pixel ( para->pixbuf, convertRGBtoPixel ( Tcl_GetString ( objv[3] ) ), x, y );
1304 
1305 			}
1306 			break;
1307 
1308 		case GetPixelIdx:
1309 			{
1310 
1311 				gint x, y;
1312 				guchar r, g, b, a;
1313 				double R, G, B, A;
1314 
1315 				gchar str[24];
1316 
1317 				/* get pixel location */
1318 				sscanf ( Tcl_GetString ( objv[2] ), "%d %d", &x, &y );
1319 #ifdef DEBUG_PIXBUF
1320 				g_printf ( "pos = %d %d\n", x, y );
1321 #endif
1322 				gdk_pixbuf_get_pixel ( para->pixbuf, x, y , &r, &g, &b, &a );
1323 
1324 
1325 				/* convert int to decimal float */
1326 
1327 				R = ( double ) r / 255;
1328 				G = ( double ) g / 255;
1329 				B = ( double ) b / 255;
1330 				A = ( double ) a / 255;
1331 
1332 				sprintf ( str, "%f %f %f %f", R, G, B, A );
1333 
1334 				Tcl_SetResult ( interp, str, TCL_STATIC );
1335 
1336 			}
1337 			break;
1338 		case PixelateIdx:
1339 			{
1340 
1341 				double saturation;
1342 
1343 				/* simplest way to get the a duplicate buffer to paste into */
1344 				dest->pixbuf = gdk_pixbuf_copy ( para->pixbuf );
1345 
1346 				if ( 0 )
1347 				{
1348 					if ( Tcl_GetDoubleFromObj ( interp, objv[2], &saturation ) != TCL_OK )
1349 					{
1350 						Tcl_SetResult ( interp, "Invalid value set for saturation, must be a float.\n", TCL_STATIC );
1351 						return TCL_ERROR;
1352 					}
1353 				}
1354 
1355 				gdk_pixbuf_saturate_and_pixelate ( para->pixbuf, dest->pixbuf, 1.0, TRUE );
1356 
1357 				para->pixbuf = dest->pixbuf;
1358 				return gnoclRegisterPixBuf_ ( interp, para, pixBufFunc );
1359 				return gnoclRegisterPixBuf ( interp, dest->pixbuf, pixBufFunc );
1360 
1361 			}
1362 			break;
1363 		case SaturationIdx:
1364 			{
1365 
1366 				double saturation;
1367 
1368 				/* simplest way to get the a duplicate buffer to paste into */
1369 				dest->pixbuf = gdk_pixbuf_copy ( para->pixbuf );
1370 
1371 				if ( Tcl_GetDoubleFromObj ( interp, objv[2], &saturation ) != TCL_OK )
1372 				{
1373 					Tcl_SetResult ( interp, "Invalid value set for saturation, must be a float.\n", TCL_STATIC );
1374 					return TCL_ERROR;
1375 				}
1376 
1377 				gdk_pixbuf_saturate_and_pixelate ( para->pixbuf, dest->pixbuf, saturation, FALSE );
1378 
1379 				para->pixbuf = dest->pixbuf;
1380 				return gnoclRegisterPixBuf_ ( interp, para, pixBufFunc );
1381 				return gnoclRegisterPixBuf ( interp, dest->pixbuf, pixBufFunc );
1382 
1383 			}
1384 			break;
1385 		case CopyIdx:
1386 			{
1387 #ifdef DEBUG_PIXBUF
1388 				g_print ( "CopyIdx %s\n", Tcl_GetString ( objv[2] ) );
1389 #endif
1390 
1391 				int src_x;
1392 				int src_y;
1393 				int width;
1394 				int height;
1395 
1396 				dest->pixbuf = gdk_pixbuf_new ( GDK_COLORSPACE_RGB, FALSE, 8, width, height );
1397 
1398 				/* if no string is passed make a simple duplicate */
1399 				if ( objc == 2 )
1400 				{
1401 #ifdef DEBUG_PIXBUF
1402 					g_print ( "total args %d\n", objc );
1403 #endif
1404 					dest->pixbuf = gdk_pixbuf_copy ( para->pixbuf );
1405 				}
1406 
1407 				/* copy as specific region of the pixbuf */
1408 				else
1409 				{
1410 
1411 					sscanf ( Tcl_GetString ( objv[2] ), "%d %d %d %d", &src_x, &src_y, &width, &height );
1412 #ifdef DEBUG_PIXBUF
1413 					g_print ( "CopyIdx %d %d %d %d\n", src_x, src_y, width, height );
1414 #endif
1415 
1416 					dest->pixbuf = gdk_pixbuf_new ( GDK_COLORSPACE_RGB, FALSE, 8, width, height );
1417 
1418 					gdk_pixbuf_copy_area ( para->pixbuf, src_x, src_y, width, height, dest->pixbuf, 0, 0 );
1419 				}
1420 
1421 				para->pixbuf = dest->pixbuf;
1422 				return gnoclRegisterPixBuf_ ( interp, para, pixBufFunc );
1423 				return gnoclRegisterPixBuf ( interp, dest->pixbuf, pixBufFunc );
1424 
1425 			}
1426 			break;
1427 		case SubPixBufIdx :
1428 			{
1429 
1430 				int src_x;
1431 				int src_y;
1432 				int width;
1433 				int height;
1434 
1435 				gint i;
1436 
1437 				if ( sscanf ( Tcl_GetString ( objv[2] ), "%d %d %d %d", &src_x, &src_y, &width, &height ) != 4 )
1438 				{
1439 					Tcl_SetResult ( interp, "Should be: pixBuf-id subpixBuf {x y w h}./n", TCL_STATIC );
1440 
1441 					return TCL_ERROR;
1442 				}
1443 
1444 				dest->pixbuf = gdk_pixbuf_new_subpixbuf ( para->pixbuf, src_x, src_y, width, height );
1445 
1446 				para->pixbuf = dest->pixbuf;
1447 				return gnoclRegisterPixBuf_ ( interp, para, pixBufFunc );
1448 				return gnoclRegisterPixBuf ( interp, dest->pixbuf, pixBufFunc );
1449 			}
1450 			break;
1451 		case DeleteIdx:
1452 			{
1453 			}
1454 			break;
1455 		case ConfigureIdx:
1456 			{
1457 			}
1458 			break;
1459 		case CgetIdx:
1460 			{
1461 
1462 				static char *cgetOptions[] =
1463 				{
1464 					"-colorSpace", "-nChannels", "-hasAlpha",
1465 					"-bitsPerSample", "-pixels", "-width",
1466 					"-height", "-rowstride", "-key",
1467 					NULL
1468 				};
1469 
1470 				static enum  optsIdx
1471 				{
1472 					ColorSpaceIdx, NChannelsIdx, HasAlphaIdx,
1473 					BitsPerSampleIdx, PixelsIdx, WidthIdx,
1474 					HeightIdx, RowStrideIdx, KeyIdx
1475 				};
1476 
1477 				int Idx;
1478 
1479 				if ( Tcl_GetIndexFromObj ( interp, objv[2], cgetOptions, "option", TCL_EXACT, &Idx ) != TCL_OK )
1480 				{
1481 					return TCL_ERROR;
1482 				}
1483 
1484 				switch ( Idx )
1485 				{
1486 					case ColorSpaceIdx:
1487 						{
1488 
1489 							/* 05/03/10 only RGB supported */
1490 							gchar *str;
1491 
1492 							switch ( gdk_pixbuf_get_colorspace ( para->pixbuf ) )
1493 							{
1494 								case GDK_COLORSPACE_RGB:
1495 									{
1496 										str = "RGB";
1497 									}
1498 									break;
1499 							}
1500 
1501 							Tcl_SetObjResult ( interp, Tcl_NewStringObj ( str, -1  ) );
1502 
1503 						} break;
1504 					case NChannelsIdx:
1505 						{
1506 							Tcl_SetObjResult ( interp, Tcl_NewIntObj ( gdk_pixbuf_get_bits_per_sample ( para->pixbuf ) ) );
1507 						} break;
1508 					case HasAlphaIdx:
1509 						{
1510 							Tcl_SetObjResult ( interp, Tcl_NewIntObj ( gdk_pixbuf_get_has_alpha ( para->pixbuf ) ) );
1511 						} break;
1512 					case BitsPerSampleIdx:
1513 						{
1514 							Tcl_SetObjResult ( interp, Tcl_NewIntObj ( gdk_pixbuf_get_bits_per_sample ( para->pixbuf ) ) );
1515 						} break;
1516 					case PixelsIdx:
1517 						{
1518 							/* Not terribly certain what this function implies */
1519 							guchar *str;
1520 							str = gdk_pixbuf_get_pixels ( para->pixbuf );
1521 
1522 							Tcl_SetObjResult ( interp, Tcl_NewStringObj ( str, -1 ) );
1523 						} break;
1524 					case WidthIdx:
1525 						{
1526 							Tcl_SetObjResult ( interp, Tcl_NewIntObj ( gdk_pixbuf_get_width ( para->pixbuf ) ) );
1527 						} break;
1528 					case HeightIdx:
1529 						{
1530 							Tcl_SetObjResult ( interp, Tcl_NewIntObj ( gdk_pixbuf_get_height ( para->pixbuf ) ) );
1531 						} break;
1532 					case RowStrideIdx:
1533 						{
1534 							Tcl_SetObjResult ( interp, Tcl_NewIntObj ( gdk_pixbuf_get_rowstride ( para->pixbuf ) ) );
1535 						} break;
1536 					case KeyIdx:
1537 						{
1538 //const gchar * gdk_pixbuf_get_option (GdkPixbuf *pixbuf,const gchar *key);
1539 						}
1540 						break;
1541 				}
1542 			}
1543 			break;
1544 		case ClassIdx:
1545 			{
1546 				Tcl_SetObjResult ( interp, Tcl_NewStringObj ( "pixbuf", -1 ) );
1547 			}
1548 			break;
1549 		case FillIdx:
1550 			{
1551 				gdk_pixbuf_fill ( para->pixbuf, convertRGBtoPixel ( Tcl_GetString ( objv[2] ) ) );
1552 			}
1553 			break;
1554 		case SaveIdx:
1555 			{
1556 				GError *err;
1557 				gchar *opt, *val;
1558 				gchar *fileType;
1559 				gchar *fileName;
1560 				gchar *parameters;
1561 
1562 				/* set a default filetype */
1563 				fileType = NULL;
1564 				fileName = NULL;
1565 				parameters = NULL;
1566 
1567 				static char *newOptions[] =
1568 				{
1569 					"-fileName", "-fileType", "-parameters",
1570 					NULL
1571 				};
1572 
1573 				static enum  optsIdx
1574 				{
1575 					FileNameIdx, FileTypeIdx, ParametersIdx
1576 				};
1577 
1578 				gint i, j;
1579 				int idx;
1580 
1581 				for ( i = 2; i < objc; i += 2 )
1582 				{
1583 					j = i + 1;
1584 
1585 					opt = Tcl_GetString ( objv[i] );
1586 					val = Tcl_GetString ( objv[j] );
1587 
1588 					if ( Tcl_GetIndexFromObj ( interp, objv[i], newOptions, "command", TCL_EXACT, &idx ) != TCL_OK )
1589 					{
1590 						return TCL_ERROR;
1591 					}
1592 
1593 					switch ( idx )
1594 					{
1595 						case FileNameIdx:
1596 							{
1597 								//g_printf ( "save file = %s val = %s\n", opt, val );
1598 								err = NULL;
1599 								fileName = val;
1600 
1601 								if ( err != NULL )
1602 								{
1603 									g_warning ( err->message );
1604 									g_error_free ( err );
1605 								}
1606 							}
1607 							break;
1608 						case FileTypeIdx:
1609 							{
1610 
1611 								GSList *p;
1612 
1613 								//g_printf ( "file type = %s val = %s\n", opt, val );
1614 
1615 								for ( p = gdk_pixbuf_get_formats (); p != NULL; p = p->next )
1616 								{
1617 									//g_printf ( "p = %s\n", gdk_pixbuf_format_get_name ( p->data ) );
1618 
1619 									if ( !strcmp ( val, gdk_pixbuf_format_get_name ( p->data ) ) )
1620 									{
1621 										//g_printf ( "ok an acceptable format!\n" );
1622 										fileType = val;
1623 										break;
1624 
1625 									}
1626 								}
1627 
1628 								if ( fileType == NULL )
1629 								{
1630 									gchar str[64];
1631 									sprintf ( str, "GNOCL ERROR: \"%s\" is not a supported file format.\n", val );
1632 									Tcl_SetResult ( interp, str, TCL_STATIC );
1633 									return TCL_ERROR;
1634 								}
1635 
1636 							}
1637 							break;
1638 						case ParametersIdx:
1639 							{
1640 								parameters = val;
1641 
1642 							}
1643 							break;
1644 						default:
1645 							{
1646 							}
1647 					}
1648 				}
1649 
1650 				//g_printf ( "parameters = %s\n", parameters );
1651 
1652 
1653 				if ( parameters == NULL )
1654 				{
1655 					gdk_pixbuf_save ( para->pixbuf, fileName, fileType, &err, NULL ) ;
1656 					break;
1657 				}
1658 
1659 				/* handle any received parameters */
1660 				if ( parameters != NULL )
1661 				{
1662 					gchar **tmp_array, **iterator;
1663 					gchar *props[10], *vals[10];
1664 					gint  k;
1665 
1666 					tmp_array = g_strsplit_set ( parameters, "= ", 0 );
1667 					iterator = tmp_array;
1668 					i = 0;
1669 
1670 					/* do the actual split */
1671 					while ( i < g_strv_length ( tmp_array ) / 2 )
1672 					{
1673 						props[i] = *iterator;
1674 						iterator++;
1675 
1676 						vals[i]  = *iterator;
1677 						iterator++;
1678 
1679 						i++;
1680 					}
1681 
1682 					props[i] = NULL; /* First array needs to be NULL terminated */
1683 
1684 					gdk_pixbuf_savev ( para->pixbuf, fileName, fileType, props, vals, NULL );
1685 					g_strfreev ( tmp_array );
1686 
1687 				}
1688 
1689 				else
1690 				{
1691 					/* "plain" save if no parameters set */
1692 					gdk_pixbuf_save ( para->pixbuf, fileName, fileType, &err, NULL );
1693 				}
1694 
1695 			} break;
1696 		case TurnIdx:
1697 			{
1698 				/*
1699 				typedef enum {
1700 				    GDK_PIXBUF_ROTATE_NONE             =   0,
1701 				    GDK_PIXBUF_ROTATE_COUNTERCLOCKWISE =  90,
1702 				    GDK_PIXBUF_ROTATE_UPSIDEDOWN       = 180,
1703 				    GDK_PIXBUF_ROTATE_CLOCKWISE        = 270
1704 				} GdkPixbufRotation;
1705 				*/
1706 
1707 				int idx;
1708 				int angle;
1709 
1710 				angle = 0;
1711 
1712 				static char *turnOptions[] =
1713 				{
1714 					"clockwise", "90",
1715 					"counterClockwise", "antiClockwise", "270", "-90",
1716 					"upsideDown", "180", "-180",
1717 					NULL
1718 				};
1719 
1720 				static enum  optsIdx
1721 				{
1722 					ClockWiseIdx, _90Idx,
1723 					CounterClockwiseIdx, AntiClockwiseIdx, _270Idx, _minus90Idx,
1724 					UpsideDownIdx, _180Idx, _minus180Idx
1725 				};
1726 
1727 				if ( Tcl_GetIndexFromObj ( interp, objv[2], turnOptions, "command", TCL_EXACT, &idx ) != TCL_OK )
1728 				{
1729 					return TCL_ERROR;
1730 				}
1731 
1732 				switch ( idx )
1733 				{
1734 					case ClockWiseIdx:
1735 					case _90Idx:
1736 						{
1737 							angle = 90;
1738 						}
1739 						break;
1740 
1741 					case CounterClockwiseIdx:
1742 					case AntiClockwiseIdx:
1743 					case _270Idx:
1744 					case _minus90Idx:
1745 						{
1746 							angle = 270;
1747 						}
1748 
1749 					case UpsideDownIdx:
1750 					case _180Idx:
1751 					case _minus180Idx:
1752 						{
1753 							angle = 180;
1754 						}
1755 						break;
1756 				}
1757 
1758 
1759 				/* get rotated copy of the buffer */
1760 				GdkPixbuf *pb;
1761 				pb = gdk_pixbuf_rotate_simple ( para->pixbuf, angle );
1762 
1763 				/* clear the parent buffer, then copy accross with composite  */
1764 				gdk_pixbuf_fill ( para->pixbuf, 0x000000000000 );
1765 				gdk_pixbuf_composite ( pb, para->pixbuf, 0, 0,
1766 									   gdk_pixbuf_get_width ( para->pixbuf ),
1767 									   gdk_pixbuf_get_height ( para->pixbuf ),
1768 									   0, 0, 1, 1,
1769 									   GDK_INTERP_BILINEAR, 255 );
1770 				/* free the intermediary pixbuf*/
1771 				g_object_unref ( pb );
1772 			}
1773 			break;
1774 		case FlipIdx:
1775 			{
1776 				GdkPixbuf *pb;
1777 
1778 				/* horizontal */
1779 				pb = gdk_pixbuf_flip ( para->pixbuf, TRUE );
1780 				/* vertical */
1781 				pb = gdk_pixbuf_flip ( para->pixbuf, FALSE );
1782 
1783 				/* clear the parent buffer, then copy accross with composite  */
1784 				gdk_pixbuf_fill ( para->pixbuf, 0x000000000000 );
1785 				gdk_pixbuf_composite ( pb, para->pixbuf, 0, 0,
1786 									   gdk_pixbuf_get_width ( para->pixbuf ),
1787 									   gdk_pixbuf_get_height ( para->pixbuf ),
1788 									   0, 0, 1, 1,
1789 									   GDK_INTERP_BILINEAR, 255 );
1790 				/* free the intermediary pixbuf*/
1791 				g_object_unref ( pb );
1792 
1793 			}
1794 			break;
1795 		case RotateIdx:
1796 			{
1797 				/* todo:
1798 				   associate the named object with the new buffer which will be enlarged.
1799 				   error check, this will not work on svg files
1800 				*/
1801 				g_print ( "RotateIdx 1\n" );
1802 				GdkPixbuf *pb;
1803 				gdouble angle;
1804 				int acolor;
1805 				gchar *name;
1806 
1807 				acolor = 255 ; /* default is black */
1808 
1809 				//name = gnoclGetNameFromPixBuf ( data );
1810 
1811 				g_print ( "RotateIdx 2\n" );
1812 
1813 				Tcl_GetDoubleFromObj ( NULL, objv[2], &angle );
1814 
1815 				/* only one option */
1816 
1817 				if ( !strcmp ( Tcl_GetString ( objv[3] ), "-backgroundColor" ) )
1818 				{
1819 					acolor = Tcl_GetIntFromObj ( NULL, objv[4], &acolor ) ;
1820 				}
1821 
1822 				else
1823 				{
1824 					Tcl_SetResult ( interp, "Unknown option. M\n", TCL_STATIC );
1825 					return TCL_ERROR;
1826 				}
1827 
1828 
1829 				g_print ( "RotateIdx 3\n" );
1830 
1831 #ifdef DEBUG_PIXBUF
1832 				g_print ( "Rotate 2 %s %f %s %d\n",
1833 						  name ,
1834 						  angle,
1835 						  Tcl_GetString ( objv[4] ),
1836 						  acolor ); // works ok!
1837 #endif
1838 				/* replace the current buffer with the new buffer */
1839 				pb = pixbufRotate ( para->pixbuf, angle, acolor );
1840 
1841 				g_print ( "RotateIdx 4\n" );
1842 
1843 				if ( pb == NULL )
1844 				{
1845 					Tcl_SetResult ( interp, "Unable to create pixBuff\n", TCL_STATIC );
1846 					return TCL_ERROR;
1847 				}
1848 
1849 				g_print ( "RotateIdx 5\n" );
1850 
1851 				para->pixbuf = pb;
1852 
1853 				return gnoclRegisterPixBuf_ ( interp, para, pixBufFunc );
1854 				//return gnoclRegisterPixBuf ( interp, pb, pixBufFunc );
1855 				g_print ( "RotateIdx 6\n" );
1856 
1857 			}
1858 			break;
1859 		case CompositeIdx:
1860 			{
1861 				/* this will clearly need parameters sorted from outset */
1862 #ifdef DEBUG_PIXBUF
1863 				g_print ( "CompositeIdx 1\n" );
1864 				g_printf ( "objc = %d\n", objc );
1865 				listParameters ( objc, objv );
1866 #endif
1867 				int compositeIdx;
1868 				static const char *compositeOpts[] =
1869 				{
1870 					"-destX", "-destY",
1871 					"-destWidth", "-destHeight",
1872 					"-offsetX", "-offsetY",
1873 					"-scaleX", "-scaleY",
1874 					"-interpType",
1875 					"-alpha",
1876 					NULL
1877 				};
1878 
1879 				enum compIdx
1880 				{
1881 					DestXIdx, DestYIdx,
1882 					DestWidthIdx, DestHeightIdx,
1883 					OffsetXIdx, OffsetYIdx,
1884 					ScaleXIdx, ScaleYIdx,
1885 					InterpTypeIdx,
1886 					AlphaIdx
1887 				};
1888 
1889 				/* check the number of arguments */
1890 				if ( objc < 2 )
1891 				{
1892 					Tcl_SetObjResult ( interp, Tcl_NewStringObj ( "ERROR: Wrong number of arguments.", -1  ) );
1893 					return TCL_ERROR;
1894 				}
1895 
1896 				GdkPixbuf *src_, *dest;
1897 				PixbufParams *src;
1898 
1899 
1900 				/* composite options */
1901 				gint dest_x, dest_y;
1902 				gint dest_width, dest_height;
1903 				gdouble offset_x, offset_y;
1904 				gdouble scale_x, scale_y;
1905 				GdkInterpType interp_type;
1906 				gint overall_alpha;
1907 
1908 
1909 				src = gnoclGetPixBufFromName ( Tcl_GetString ( objv[2] ), interp );
1910 				dest = para->pixbuf;
1911 
1912 				/* set some defaults */
1913 				dest_x = 0;
1914 				dest_y = 0;
1915 				dest_width = gdk_pixbuf_get_width ( src->pixbuf );
1916 				dest_height = gdk_pixbuf_get_height ( src->pixbuf );
1917 
1918 				offset_x = 0;
1919 				offset_y = 0;
1920 				scale_x = 1;
1921 				scale_y = 1;
1922 				interp_type = GDK_INTERP_BILINEAR;
1923 				overall_alpha = 255;
1924 
1925 				gint i; /* counter */
1926 
1927 				/* parse all the options */
1928 				i = 3;
1929 
1930 				while ( i < objc )
1931 				{
1932 
1933 					getIdx ( compositeOpts, Tcl_GetString ( objv[i] ), &compositeIdx );
1934 
1935 					switch ( compositeIdx )
1936 					{
1937 						case DestXIdx:
1938 							{
1939 								Tcl_GetIntFromObj ( NULL, objv[i+1], &dest_x );
1940 							}
1941 							break;
1942 						case DestYIdx:
1943 							{
1944 								Tcl_GetIntFromObj ( NULL, objv[i+1], &dest_y );
1945 							}
1946 							break;
1947 						case DestWidthIdx:
1948 							{
1949 								Tcl_GetIntFromObj ( NULL, objv[i+1], &dest_width );
1950 							}
1951 							break;
1952 						case DestHeightIdx:
1953 							{
1954 								Tcl_GetIntFromObj ( NULL, objv[i+1], &dest_height );
1955 							}
1956 							break;
1957 						case OffsetXIdx:
1958 							{
1959 								Tcl_GetDoubleFromObj ( NULL, objv[i+1], &offset_x );
1960 							}
1961 							break;
1962 						case OffsetYIdx:
1963 							{
1964 								Tcl_GetDoubleFromObj ( NULL, objv[i+1], &offset_y );
1965 							}
1966 							break;
1967 						case ScaleXIdx:
1968 							{
1969 								Tcl_GetDoubleFromObj ( NULL, objv[i+1], &scale_x );
1970 							}
1971 							break;
1972 						case ScaleYIdx:
1973 							{
1974 								Tcl_GetDoubleFromObj ( NULL, objv[i+1], &offset_y );
1975 							}
1976 							break;
1977 						case InterpTypeIdx:
1978 							{
1979 								interp_type = GDK_INTERP_BILINEAR;
1980 							}
1981 							break;
1982 						case AlphaIdx:
1983 							{
1984 								Tcl_GetIntFromObj ( NULL, objv[i+1], &overall_alpha );
1985 							}
1986 							break;
1987 						default: {}
1988 					}
1989 
1990 					i += 2;
1991 				}
1992 
1993 				/* reset values based upon received switches */
1994 
1995 				gdk_pixbuf_composite ( src->pixbuf, dest,
1996 									   dest_x, dest_y,
1997 									   dest_width, dest_height,
1998 									   offset_x, offset_y,
1999 									   scale_x, scale_y,
2000 									   interp_type, overall_alpha );
2001 			}
2002 			break;
2003 		case DrawIdx:
2004 			{
2005 				/* draw the pixbuf to a GdkDrawable: ie. a drawing area */
2006 				GtkWidget *widget;
2007 				GdkDrawable *dest;
2008 				gint src_x, src_y;
2009 				gint dest_x, dest_y;
2010 				gint width, height;
2011 				gint x_dither, y_dither;
2012 
2013 				/* initialize the values with defaults */
2014 				src_x = 0;
2015 				src_y = 0;
2016 				dest_x = 10;
2017 				dest_y = 10;
2018 
2019 				x_dither = 0;
2020 				y_dither = 0;
2021 
2022 				/* what size of the buffer has to be drawn */
2023 				width = gdk_pixbuf_get_width ( para->pixbuf );
2024 				height = gdk_pixbuf_get_height ( para->pixbuf );
2025 
2026 				widget = gnoclGetWidgetFromName ( Tcl_GetString ( objv[2] ), interp );
2027 
2028 				if ( widget == NULL )
2029 				{
2030 					return TCL_ERROR;
2031 				}
2032 
2033 				dest = GDK_DRAWABLE ( widget->window );
2034 
2035 				/* change values based upon switches passed */
2036 				gdk_draw_pixbuf (
2037 					dest,
2038 					gdk_gc_new ( widget->window ),
2039 					para->pixbuf,
2040 					src_x, src_y,
2041 					dest_x, dest_y,
2042 					width,
2043 					height,
2044 					GDK_RGB_DITHER_NONE,
2045 					x_dither, y_dither );
2046 
2047 			}
2048 			break;
2049 	}
2050 
2051 	return TCL_OK;
2052 }
2053 
2054 /**
2055 \brief
2056 \note      "char *" and not "const char *" because of a not very strict
2057             handling of "const char *" in Tcl e.g. Tcl_CreateObjCommand
2058 */
gnoclGetAutoPixBufId(void)2059 char *gnoclGetAutoPixBufId ( void )
2060 {
2061 	static int no = 0;
2062 	/*
2063 	static char buffer[30];
2064 	*/
2065 
2066 	char *buffer = g_new ( char, sizeof ( idPrefix ) + 15 );
2067 	strcpy ( buffer, idPrefix );
2068 
2069 	/* with namespace, since the Id is also the widget command */
2070 	sprintf ( buffer + sizeof ( idPrefix ) - 1, "%d", ++no );
2071 
2072 	return buffer;
2073 }
2074 
2075 /**
2076 \brief	Returns pointer to the pixbuf
2077 **/
2078 /* -----------------
2079    handle widget <-> name mapping
2080 -------------------- */
gnoclGetPixBufFromName(const char * id,Tcl_Interp * interp)2081 PixbufParams *gnoclGetPixBufFromName ( const char * id, Tcl_Interp * interp )
2082 {
2083 #ifdef DEBUG_PIXBUF
2084 	g_print ( "%s\n", __FUNCTION__ );
2085 #endif
2086 
2087 	PixbufParams *para = NULL;
2088 
2089 	//GdkPixbuf *pixbuf = NULL;
2090 	int       n;
2091 
2092 	if ( strncmp ( id, idPrefix, sizeof ( idPrefix ) - 1 ) == 0
2093 			&& ( n = atoi ( id + sizeof ( idPrefix ) - 1 ) ) > 0 )
2094 	{
2095 		para = g_hash_table_lookup ( name2pixbufList, GINT_TO_POINTER ( n ) );
2096 	}
2097 
2098 	if ( para == NULL && interp != NULL )
2099 	{
2100 		Tcl_AppendResult ( interp, "Unknown pixbuf \"", id, "\".", ( char * ) NULL );
2101 	}
2102 
2103 	return para;
2104 }
2105 
2106 /**
2107 \brief      Returns the widget name associated with pointer
2108 **/
gnoclGetNameFromPixBuf(GdkPixbuf * pixbuf)2109 const char *gnoclGetNameFromPixBuf ( GdkPixbuf * pixbuf )
2110 {
2111 	const char *name = g_object_get_data ( G_OBJECT ( pixbuf ), "gnocl::name" );
2112 
2113 	return name;
2114 }
2115 
2116 /**
2117 \brief
2118 **/
gnoclForgetPixBufFromName(const char * path)2119 int gnoclForgetPixBufFromName ( const char * path )
2120 {
2121 	int n = atoi ( path + sizeof ( idPrefix ) - 1 );
2122 	assert ( gnoclGetPixBufFromName ( path, NULL ) );
2123 	assert ( strncmp ( path, idPrefix, sizeof ( idPrefix ) - 1 ) == 0 );
2124 	assert ( n > 0 );
2125 
2126 	g_hash_table_remove ( name2pixbufList, GINT_TO_POINTER ( n ) );
2127 
2128 	return 0;
2129 }
2130 
2131 /**
2132 \brief
2133 **/
simpleDestroyFunc(GdkPixbuf * pixbuf,gpointer data)2134 static void simpleDestroyFunc ( GdkPixbuf * pixbuf, gpointer data )
2135 {
2136 	const char *name = gnoclGetNameFromPixBuf ( pixbuf );
2137 	gnoclForgetPixBufFromName ( name );
2138 	Tcl_DeleteCommand ( ( Tcl_Interp * ) data, ( char * ) name );
2139 	g_free ( ( char * ) name );
2140 }
2141 
2142 /**
2143 \brief
2144 **/
gnoclMemNameAndPixBuf_(const char * path,PixbufParams * para)2145 int gnoclMemNameAndPixBuf_ ( const char * path,  PixbufParams *para )
2146 {
2147 	int n ;
2148 
2149 	n = atoi ( path + sizeof ( idPrefix ) - 1 );
2150 
2151 	assert ( n > 0 );
2152 	assert ( g_hash_table_lookup ( name2pixbufList, GINT_TO_POINTER ( n ) ) == NULL );
2153 	assert ( strncmp ( path, idPrefix, sizeof ( idPrefix ) - 1 ) == 0 );
2154 
2155 	/* memorize the name of the widget in the widget */
2156 	g_object_set_data ( G_OBJECT ( para->pixbuf ), "gnocl::name", ( char * ) path );
2157 	g_hash_table_insert ( name2pixbufList, GINT_TO_POINTER ( n ), para );
2158 
2159 	return 0;
2160 }
2161 
2162 /**
2163 \brief
2164 **/
gnoclMemNameAndPixBuf(const char * path,GdkPixbuf * pixbuf)2165 int gnoclMemNameAndPixBuf ( const char * path,  GdkPixbuf * pixbuf )
2166 {
2167 	int n ;
2168 
2169 	n = atoi ( path + sizeof ( idPrefix ) - 1 );
2170 
2171 	assert ( n > 0 );
2172 	assert ( g_hash_table_lookup ( name2pixbufList, GINT_TO_POINTER ( n ) ) == NULL );
2173 	assert ( strncmp ( path, idPrefix, sizeof ( idPrefix ) - 1 ) == 0 );
2174 
2175 	/* memorize the name of the widget in the widget */
2176 	g_object_set_data ( G_OBJECT ( pixbuf ), "gnocl::name", ( char * ) path );
2177 	g_hash_table_insert ( name2pixbufList, GINT_TO_POINTER ( n ), pixbuf );
2178 
2179 	return 0;
2180 }
2181 
2182 /**
2183 \brief	Register structure for pixbuf and cairo context
2184 **/
gnoclRegisterPixBuf_(Tcl_Interp * interp,PixbufParams * para,Tcl_ObjCmdProc * proc)2185 int gnoclRegisterPixBuf_ ( Tcl_Interp * interp, PixbufParams * para, Tcl_ObjCmdProc * proc )
2186 {
2187 
2188 	const char *name;
2189 
2190 	name = gnoclGetAutoPixBufId();
2191 
2192 	/* create cairo context for this pixbuf */
2193 	para->cr = gnoclPixbufCairoCreate ( para->pixbuf );
2194 
2195 	gnoclMemNameAndPixBuf_ ( name, para ); //<--- problems here
2196 
2197 	//g_signal_connect_after ( G_OBJECT ( pixbuf ), "destroy", G_CALLBACK ( simpleDestroyFunc ), interp );
2198 
2199 	if ( proc != NULL )
2200 	{
2201 
2202 		Tcl_CreateObjCommand ( interp, ( char * ) name, proc, para, NULL );
2203 	}
2204 
2205 	Tcl_SetObjResult ( interp, Tcl_NewStringObj ( name, -1 ) );
2206 
2207 	return TCL_OK;
2208 }
2209 
2210 
2211 /**
2212 \brief
2213 **/
gnoclRegisterPixBuf(Tcl_Interp * interp,GdkPixbuf * pixbuf,Tcl_ObjCmdProc * proc)2214 int gnoclRegisterPixBuf ( Tcl_Interp * interp, GdkPixbuf * pixbuf, Tcl_ObjCmdProc * proc )
2215 {
2216 
2217 	const char *name;
2218 
2219 	name = gnoclGetAutoPixBufId();
2220 
2221 	gnoclMemNameAndPixBuf ( name, pixbuf ); //<--- problems here
2222 
2223 	//g_signal_connect_after ( G_OBJECT ( pixbuf ), "destroy", G_CALLBACK ( simpleDestroyFunc ), interp );
2224 
2225 	if ( proc != NULL )
2226 	{
2227 
2228 		Tcl_CreateObjCommand ( interp, ( char * ) name, proc, pixbuf, NULL );
2229 	}
2230 
2231 	Tcl_SetObjResult ( interp, Tcl_NewStringObj ( name, -1 ) );
2232 
2233 	return TCL_OK;
2234 }
2235 
2236 /**
2237 \brief      Convert colour to hexadecimal.
2238 **/
gnoclRGB2HexCmd(ClientData data,Tcl_Interp * interp,int objc,Tcl_Obj * const objv[])2239 int gnoclRGB2HexCmd ( ClientData data, Tcl_Interp * interp, int objc, Tcl_Obj * const objv[] )
2240 {
2241 
2242 #ifdef DEBUG_PIXBUF
2243 	listParameters ( objc, objv, "gnoclRGB2HexCmd" );
2244 #endif
2245 
2246 	GdkColor color;
2247 	gchar str[25];
2248 	gint val;
2249 
2250 	getGdkColor ( interp, objv[1], &color );
2251 	sprintf ( str, "#%.2x%.2x%.2x", color.red, color.green, color.blue );
2252 
2253 	/* differentiate between 8 / 16 bit colour */
2254 	if ( strcmp ( Tcl_GetString ( objv[2] ), "-8bit" ) == 0 )
2255 	{
2256 		Tcl_GetIntFromObj ( NULL, objv[3], &val );
2257 
2258 		/* value of 0 means 16-bit */
2259 		if ( !val )
2260 		{
2261 			color.red *= 257;
2262 			color.green *= 257;
2263 			color.blue *= 257;
2264 			sprintf ( str, "#%.4x%.4x%.4x", color.red, color.green, color.blue );
2265 		}
2266 
2267 	}
2268 
2269 	Tcl_SetObjResult ( interp, Tcl_NewStringObj ( &str, -1 ) ) ;
2270 
2271 	return TCL_OK;
2272 }
2273 
2274 /**
2275 \brief      Convert colour 16-bit RGB decimal.
2276 **/
gnoclClr2RGBCmd(ClientData data,Tcl_Interp * interp,int objc,Tcl_Obj * const objv[])2277 int gnoclClr2RGBCmd ( ClientData data, Tcl_Interp * interp, int objc, Tcl_Obj * const objv[] )
2278 {
2279 
2280 #ifdef DEBUG_PIXBUF
2281 	g_printf ( "gnoclClr2RGBCmd\n" );
2282 	gint _i;
2283 
2284 
2285 	for ( _i = 0; _i < objc; _i++ )
2286 	{
2287 		g_printf ( "\targ %d = %s\n", _i,  Tcl_GetString ( objv[_i] ) );
2288 	}
2289 
2290 #endif
2291 
2292 	GdkColor color;
2293 	gchar str[25];
2294 	gint val;
2295 
2296 	getGdkColor ( interp, objv[1], &color );
2297 
2298 	/* differentiate between 8 / 16 bit colour */
2299 	if ( strcmp ( Tcl_GetString ( objv[2] ), "-8bit" ) == 0 )
2300 	{
2301 		Tcl_GetIntFromObj ( NULL, objv[3], &val );
2302 
2303 		if ( !val )
2304 		{
2305 
2306 			color.red *= 257;
2307 			color.green *= 257;
2308 			color.blue *= 257;
2309 		}
2310 
2311 	}
2312 
2313 	sprintf ( str, "%d %d %d", color.red, color.green, color.blue );
2314 	Tcl_SetObjResult ( interp, Tcl_NewStringObj ( &str, -1 ) ) ;
2315 
2316 	return TCL_OK;
2317 }
2318 
2319 
2320 static const char *cmds[] =
2321 {
2322 	"get", "render", "types",
2323 	"description", "license", "licence",
2324 	"extensions", "scalable", "writable",
2325 	"fileInfo", "new", "load",
2326 	"snapshot", "screenshot",
2327 	"logo",
2328 	NULL
2329 };
2330 
2331 /**
2332 \brief
2333 \author     William J Giddings
2334 \date       17-Jan-2010
2335 \since      0.9.94
2336 **/
gnoclPixBufCmd(ClientData data,Tcl_Interp * interp,int objc,Tcl_Obj * const objv[])2337 int gnoclPixBufCmd ( ClientData data, Tcl_Interp * interp, int objc, Tcl_Obj * const objv[] )
2338 {
2339 
2340 	if ( gnoclGetCmdsAndOpts ( interp, cmds, pixBufOptions, objv, objc ) == TCL_OK )
2341 	{
2342 		return TCL_OK;
2343 	}
2344 
2345 
2346 #ifdef DEBUG_PIXBUF
2347 	listParameters ( objc, objv, "gnoclpixBufCmd" );
2348 #endif
2349 
2350 	GdkPixbuf *pixbuf;
2351 	PixbufParams *para;
2352 	para = g_new ( PixbufParams, 1 );
2353 
2354 	/* create new hash table if one does not exist */
2355 	if ( name2pixbufList == NULL )
2356 	{
2357 		name2pixbufList = g_hash_table_new ( g_direct_hash, g_direct_equal );
2358 	}
2359 
2360 
2361 
2362 	enum cmdIdx
2363 	{
2364 		GetIdx, RenderIdx, TypesIdx,
2365 		DescriptionIdx, LicenseIdx, LicenceIdx,
2366 		ExtensionsIdx, ScalableIdx, WritableIdx,
2367 		FileInfoIdx, NewIdx, LoadIdx,
2368 		SnapshotIdx, ScreenshotIdx,
2369 		LogoIdx
2370 	};
2371 
2372 	int cIdx;
2373 
2374 	/* set relevant options for commands / sub-commands */
2375 	const int opt1Idx = 0;
2376 	const int opt2Idx = 1;
2377 	const int opt3Idx = 2;
2378 
2379 	GnoclOption cmd2Options[] =
2380 	{
2381 		{ "-option1", GNOCL_STRING, "", NULL},
2382 		{ "-option2", GNOCL_STRING, "", NULL },
2383 		{ "-option3", GNOCL_STRING, "", NULL },
2384 		{ NULL }
2385 	};
2386 
2387 	/* must have the form <command-name> action objectName <options> */
2388 	/*
2389 		if ( objc <= 1 )
2390 		{
2391 			Tcl_WrongNumArgs ( interp, 1, objv, "command option... " );
2392 			return TCL_ERROR;
2393 		}
2394 	*/
2395 	if ( Tcl_GetIndexFromObj ( interp, objv[1], cmds, "option", TCL_EXACT, &cIdx ) != TCL_OK )
2396 	{
2397 		return TCL_ERROR;
2398 	}
2399 
2400 	switch ( cIdx )
2401 	{
2402 		case ScreenshotIdx:
2403 			{
2404 #ifdef DEBUG_PIXBUF
2405 				g_printf ( "objc = %d\n", objc );
2406 #endif
2407 				listParameters ( objc, objv );
2408 
2409 				GdkWindow *window_root;
2410 
2411 				gint x, y, x2, y2, width, height;
2412 				float cx, cy;
2413 				gint px, py;
2414 				gint rw, rh;
2415 				gint showPointer;
2416 
2417 				/* set some defaults */
2418 				x = 0, y = 0;
2419 
2420 				/* get necessary values from the root window */
2421 				window_root = gdk_get_default_root_window ();
2422 				gdk_window_get_pointer ( window_root, &px, &py, NULL );
2423 				gdk_window_get_geometry  ( window_root, NULL, NULL, &rw, &rh, NULL );
2424 
2425 				if ( objc == 2 )
2426 				{
2427 					/* grab the whole screen */
2428 					width = rw;
2429 					height = rh;
2430 
2431 				}
2432 
2433 				else if ( objc = 4 )
2434 				{
2435 					/* check sub-command, region pointer -graphic */
2436 					if ( strcmp ( Tcl_GetString ( objv[2] ), "region" ) == 0 )
2437 					{
2438 						sscanf ( Tcl_GetString ( objv[3] ), "%d %d %d %d", &x, &y, &width, &height );
2439 
2440 						if ( strcmp ( Tcl_GetString ( objv[4] ), "-pointer" ) == 0 )
2441 						{
2442 							Tcl_GetIntFromObj ( NULL, objv[5], &showPointer );
2443 						}
2444 					}
2445 
2446 					if ( strcmp ( Tcl_GetString ( objv[2] ), "pointer" ) == 0 )
2447 					{
2448 
2449 						sscanf ( Tcl_GetString ( objv[3] ), "%d %d", &width, &height );
2450 						/* ensure that pointer at the centre of the grab */
2451 						x = px - width / 2;
2452 						y = py - height / 2;
2453 
2454 						/* apply some error checks */
2455 						if ( px <= width / 2 )
2456 						{
2457 							x = 0;
2458 						}
2459 
2460 						if ( py <= height / 2 )
2461 						{
2462 							y = 0;
2463 						}
2464 
2465 						if ( px > rw - width )
2466 						{
2467 							x = px - width + 1;
2468 						}
2469 
2470 						if ( py > rh - height )
2471 						{
2472 							y = py - height + 1;
2473 						}
2474 					}
2475 
2476 				}
2477 
2478 				pixbuf = gdk_pixbuf_get_from_drawable ( NULL, window_root, NULL, x, y , 0, 0, width, height );
2479 
2480 				cx = ( float ) px - x;
2481 				cy = ( float ) py - y;
2482 
2483 				cairo_t *cr;
2484 
2485 				cr = gnoclPixbufCairoCreate ( pixbuf );
2486 
2487 				cairo_set_line_width ( cr, 9 );
2488 
2489 				//cairo_set_source_rgb ( cr, 0.69, 0.19, 0 );
2490 				cairo_set_source_rgba ( cr, 1.0, 0, 0, 0.25 );
2491 
2492 				/* do the drawing */
2493 				cairo_arc ( cr, cx, cy, 20, 0, 2 * G_PI );
2494 
2495 				cairo_stroke_preserve ( cr );
2496 
2497 				cairo_fill ( cr );
2498 
2499 				pixbuf = gnoclPixbufCairoDestroy ( cr, FALSE );
2500 
2501 				GdkPixbuf * pointerPB = gdk_pixbuf_new_from_inline ( -1, gnocl_pointer, FALSE, NULL );
2502 
2503 				gdk_pixbuf_composite ( pointerPB, pixbuf, px - x, py - y,
2504 									   gdk_pixbuf_get_width ( pointerPB ),
2505 									   gdk_pixbuf_get_height ( pointerPB ),
2506 									   0, 0, 1, 1,
2507 									   GDK_INTERP_BILINEAR, 255 );
2508 
2509 				goto registerpixbuf;
2510 
2511 			}
2512 
2513 			break;
2514 		case SnapshotIdx:
2515 			{
2516 				g_print ( "SS 1 %s\n", Tcl_GetString ( objv[2] ) );
2517 				GtkWidget *widget;
2518 				widget = gnoclGetWidgetFromName ( Tcl_GetString ( objv[2] ), interp  );
2519 
2520 				/* must be a toplevel */
2521 				widget = gtk_widget_get_toplevel ( widget );
2522 
2523 				if ( widget == NULL )
2524 				{
2525 					g_print ( "WARNING\n" );
2526 					return TCL_OK;
2527 				}
2528 
2529 				g_print ( "SS 2\n" );
2530 
2531 				GdkWindow *window_root;
2532 				GdkRectangle rect;
2533 
2534 				window_root = gdk_get_default_root_window ();
2535 				g_print ( "SS 3\n" );
2536 
2537 				gdk_window_get_frame_extents ( widget->window, &rect );
2538 				g_print ( "SS 4\n" );
2539 
2540 				g_print ( "%d %d %d %d \n", rect.x, rect.y, rect.width, rect.height );
2541 
2542 				pixbuf = gdk_pixbuf_get_from_drawable ( NULL, window_root, NULL, rect.x, rect.y, 0, 0, rect.width, rect.height );
2543 
2544 				goto registerpixbuf;
2545 
2546 			}
2547 
2548 			break;
2549 			/* create gnocl_logo from in-line data */
2550 		case LogoIdx:
2551 			{
2552 				pixbuf = gdk_pixbuf_new_from_inline ( -1, gnocl_logo, FALSE, NULL );
2553 
2554 				goto registerpixbuf;
2555 			}
2556 			break;
2557 			/* implement template with subcommands and */
2558 		case GetIdx:
2559 			{
2560 				static const char *subCmd[] = { "drawable", "image", "pointer", NULL };
2561 				enum subCmdtIdx { DrawableIdx, ImageIdx, PointerIdx };
2562 				int scIdx;
2563 				Tcl_Obj *tp;
2564 
2565 				if ( Tcl_GetIndexFromObj ( interp, objv[2], subCmd, "option", TCL_EXACT, &scIdx ) != TCL_OK )
2566 				{
2567 					return TCL_ERROR;
2568 				}
2569 
2570 				/* error handling done within swith case code */
2571 				/*
2572 								if ( objc < 3 )
2573 								{
2574 									return TCL_ERROR;
2575 								}
2576 				*/
2577 
2578 				switch ( scIdx )
2579 				{
2580 					case ImageIdx:
2581 					case DrawableIdx:
2582 						{
2583 
2584 							/* create a new buffer from the buffer associated with a specific drawable object
2585 							   only works for object already rendered to screen
2586 							*/
2587 
2588 							GtkWidget *widget;
2589 							widget = gnoclGetWidgetFromName ( Tcl_GetString ( objv[3] ), interp  );
2590 
2591 							if ( widget == NULL )
2592 							{
2593 								//widget = gnoclGetPixMapFromName ( Tcl_GetString ( objv[3] ), interp  );
2594 								//if (widget == NULL) {
2595 								return TCL_ERROR;
2596 								//}
2597 							}
2598 
2599 							int x, y, width, height, depth;
2600 
2601 							gdk_window_get_geometry ( widget->window, &x, &y, &width, &height, &depth );
2602 
2603 
2604 							pixbuf = gdk_pixbuf_get_from_drawable (
2605 										 NULL,
2606 										 GDK_DRAWABLE ( widget->window ),
2607 										 NULL,
2608 										 0, 0,
2609 										 0, 0,
2610 										 width, height );
2611 
2612 							goto registerpixbuf;
2613 
2614 						}
2615 						break;
2616 
2617 					case PointerIdx:
2618 						{
2619 
2620 							if ( objc != 3 )
2621 							{
2622 								return TCL_ERROR;
2623 							}
2624 
2625 							g_printf ( "Create a pixbuf from the current pointer\n", Tcl_GetString ( objv[3] ) );
2626 
2627 							GdkCursor *cursor;
2628 							GtkWidget *widget;
2629 
2630 							widget = gnoclGetWidgetFromName ( Tcl_GetString ( objv[3] ), interp  );
2631 							cursor = gdk_window_get_cursor ( widget->window );
2632 							pixbuf = gdk_cursor_get_image ( cursor );
2633 
2634 							goto registerpixbuf;
2635 						}
2636 						break;
2637 				}
2638 			}
2639 			break;
2640 		case RenderIdx:
2641 			{
2642 				/* set relevant options for commands / sub-commands */
2643 				static char *cmd2Options[] = { "-option1", "-option2", "-option3",  NULL};
2644 				static enum  optsIdx { opt1Idx, opt2Idx, opt3Idx };
2645 
2646 				/* this one has the options usage:
2647 				    gnocl::<CmdName> command item -option val..
2648 				*/
2649 				int ret;
2650 
2651 				ret = compare ( Tcl_GetString ( objv[2] ), cmd2Options );
2652 
2653 				switch ( ret )
2654 				{
2655 					case opt1Idx:
2656 						{
2657 							g_printf ( "\t\toption1, parameters = %s\n", Tcl_GetString ( objv[3] ) );
2658 						}
2659 						break;
2660 					case opt2Idx:
2661 						{
2662 							g_printf ( "\t\toption2, parameters = %s\n", Tcl_GetString ( objv[3] ) );
2663 						}
2664 						break;
2665 					case opt3Idx:
2666 						{
2667 							g_printf ( "\t\toption3, parameters = %s\n", Tcl_GetString ( objv[3] ) );
2668 						}
2669 						break;
2670 				}
2671 
2672 			}
2673 			break;
2674 		case TypesIdx:
2675 			{
2676 				Tcl_Obj *resList;
2677 
2678 				resList = Tcl_NewListObj ( 0, NULL );
2679 
2680 				GSList *p;
2681 
2682 				for ( p = gdk_pixbuf_get_formats (); p != NULL; p = p->next )
2683 				{
2684 
2685 					Tcl_ListObjAppendElement ( interp, resList,
2686 											   Tcl_NewStringObj ( gdk_pixbuf_format_get_name ( p->data ), -1 ) );
2687 
2688 				}
2689 
2690 				g_free ( p );
2691 				Tcl_SetObjResult ( interp, resList );
2692 			}
2693 			break;
2694 		case DescriptionIdx:
2695 			{
2696 				Tcl_Obj *resList;
2697 
2698 				resList = Tcl_NewListObj ( 0, NULL );
2699 				GSList *p;
2700 
2701 				for ( p = gdk_pixbuf_get_formats (); p != NULL; p = p->next )
2702 				{
2703 					if ( !strcmp ( gdk_pixbuf_format_get_name ( p->data ), Tcl_GetString ( objv[2] ) ) )
2704 					{
2705 						Tcl_SetObjResult ( interp, Tcl_NewStringObj ( gdk_pixbuf_format_get_description ( p->data ), -1 ) );
2706 					}
2707 				}
2708 
2709 				g_free ( p );
2710 
2711 
2712 			}
2713 			break;
2714 		case LicenceIdx:
2715 		case LicenseIdx:
2716 			{
2717 				Tcl_Obj *resList;
2718 
2719 				resList = Tcl_NewListObj ( 0, NULL );
2720 				GSList *p;
2721 
2722 				for ( p = gdk_pixbuf_get_formats (); p != NULL; p = p->next )
2723 				{
2724 					if ( !strcmp ( gdk_pixbuf_format_get_name ( p->data ), Tcl_GetString ( objv[2] ) ) )
2725 					{
2726 						Tcl_SetObjResult ( interp, Tcl_NewStringObj ( gdk_pixbuf_format_get_license ( p->data ), -1 ) );
2727 					}
2728 				}
2729 
2730 				g_free ( p );
2731 
2732 			}
2733 			break;
2734 		case ExtensionsIdx:
2735 			{
2736 				gchar * extensions;
2737 				gchar **extension_list;
2738 
2739 				Tcl_Obj *resList;
2740 
2741 				resList = Tcl_NewListObj ( 0, NULL );
2742 				GSList *p;
2743 
2744 				for ( p = gdk_pixbuf_get_formats (); p != NULL; p = p->next )
2745 				{
2746 					if ( !strcmp ( gdk_pixbuf_format_get_name ( p->data ), Tcl_GetString ( objv[2] ) ) )
2747 					{
2748 
2749 						extension_list = gdk_pixbuf_format_get_extensions ( p->data );
2750 						extensions = g_strjoinv ( " ", extension_list );
2751 						g_strfreev ( extension_list );
2752 
2753 						Tcl_SetObjResult ( interp, Tcl_NewStringObj ( extensions, -1 ) );
2754 					}
2755 				}
2756 
2757 				g_free ( p );
2758 
2759 			}
2760 			break;
2761 		case ScalableIdx:
2762 			{
2763 				GSList *p;
2764 
2765 				gint res = -1;
2766 
2767 				for ( p = gdk_pixbuf_get_formats (); p != NULL; p = p->next )
2768 				{
2769 					if ( !strcmp ( gdk_pixbuf_format_get_name ( p->data ), Tcl_GetString ( objv[2] ) ) )
2770 					{
2771 						res = gdk_pixbuf_format_is_scalable ( p->data );
2772 					}
2773 				}
2774 
2775 				g_free ( p );
2776 
2777 				Tcl_SetObjResult ( interp, Tcl_NewIntObj ( res ) ) ;
2778 
2779 			}
2780 			break;
2781 		case WritableIdx:
2782 			{
2783 				GSList *p;
2784 
2785 				gint res = -1;
2786 
2787 				for ( p = gdk_pixbuf_get_formats (); p != NULL; p = p->next )
2788 				{
2789 					if ( !strcmp ( gdk_pixbuf_format_get_name ( p->data ), Tcl_GetString ( objv[2] ) ) )
2790 					{
2791 						res = gdk_pixbuf_format_is_writable ( p->data );
2792 					}
2793 				}
2794 
2795 				g_free ( p );
2796 
2797 				Tcl_SetObjResult ( interp, Tcl_NewIntObj ( res ) ) ;
2798 			}
2799 			break;
2800 		case FileInfoIdx:
2801 			{
2802 
2803 				GdkPixbufFormat *format;
2804 				gint width;
2805 				gint height;
2806 				gchar str[128];
2807 
2808 				format = gdk_pixbuf_get_file_info ( Tcl_GetString ( objv[2] ), &width, &height );
2809 
2810 				sprintf ( str, "%d %d %s\n", width, height, gdk_pixbuf_format_get_name ( format ) );
2811 
2812 				Tcl_SetObjResult ( interp, Tcl_NewStringObj ( &str, -1 ) ) ;
2813 
2814 			}
2815 			break;
2816 		case NewIdx:
2817 			{
2818 
2819 				gchar *name;
2820 				gint width, height, bps, alpha;
2821 				gchar *opt, *val;
2822 				gint clrspace;
2823 
2824 				/* set some default values, then re-assign based upon received values */
2825 				width = 640;
2826 				height = 480;
2827 				bps = 8;
2828 				alpha = 0;
2829 				clrspace = GDK_COLORSPACE_RGB;
2830 
2831 				static char *newOptions[] =
2832 				{
2833 					"-width", "-height", "-bitsPerSample", "-colorSpace",
2834 					"-alpha", "-name", "-data",
2835 					NULL
2836 				};
2837 
2838 				static enum  optsIdx
2839 				{
2840 					WidthIdx, HeightIdx,
2841 					BitsPerSampleIdx, ColorSpaceIdx,
2842 					AlphaIdx, NameIdx, DataIdx
2843 				};
2844 
2845 				gint i, j;
2846 				int idx;
2847 
2848 				/* create the buffer,note: only RGB suported */
2849 				//sscanf ( Tcl_GetString ( objv[2] ), "%d %d %d", &width, &height, &bps );
2850 				//pixbuf = gdk_pixbuf_new ( GDK_COLORSPACE_RGB, alpha, bps, width, height );
2851 
2852 				/* parse remaining the switches */
2853 				/* set relevant options for commands / sub-commands */
2854 
2855 				for ( i = 2; i < objc; i += 2 )
2856 				{
2857 					j = i + 1;
2858 
2859 					opt = Tcl_GetString ( objv[i] );
2860 					val = Tcl_GetString ( objv[j] );
2861 
2862 					if ( Tcl_GetIndexFromObj ( interp, objv[i], newOptions, "command", TCL_EXACT, &idx ) != TCL_OK )
2863 					{
2864 						return TCL_ERROR;
2865 					}
2866 
2867 					switch ( idx )
2868 					{
2869 						case ColorSpaceIdx:
2870 							{
2871 								g_printf ( "GNOCL WARNING: Currently only GDK_COLORSPACE_RGB supported, set by default.\n" );
2872 							}
2873 							break;
2874 						case WidthIdx:
2875 							{
2876 								//g_printf ( "\t\toption1, parameters = %s val = %s\n", opt, val );
2877 								Tcl_GetIntFromObj ( NULL, objv[j], &width );
2878 							}
2879 							break;
2880 						case HeightIdx:
2881 							{
2882 								//g_printf ( "\t\toption1, parameters = %s val = %s\n", opt, val );
2883 								Tcl_GetIntFromObj ( NULL, objv[j], &height );
2884 							}
2885 							break;
2886 						case AlphaIdx:
2887 							{
2888 								//g_printf ( "\t\toption1, parameters = %s val = %s\n", opt, val );
2889 								Tcl_GetIntFromObj ( NULL, objv[j], &alpha );
2890 
2891 								if ( alpha != 0 )
2892 								{
2893 									alpha = 1;
2894 								}
2895 							}
2896 							break;
2897 						case BitsPerSampleIdx:
2898 							{
2899 								//g_printf ( "\t\toption1, parameters = %s val = %s\n", opt, val );
2900 								Tcl_GetIntFromObj ( NULL, objv[j], &bps );
2901 							} break;
2902 						case NameIdx:
2903 							{
2904 								g_printf ( "%s Yet to be implemented.", val );
2905 							}
2906 							break;
2907 						case DataIdx:
2908 							{
2909 								g_printf ( "%s Yet to be implemented.", val );;
2910 							}
2911 							break;
2912 						default:
2913 							{
2914 								return TCL_ERROR;
2915 							}
2916 					}
2917 
2918 				} /* end of switch parsing */
2919 
2920 				pixbuf = gdk_pixbuf_new ( clrspace, alpha, bps, width, height );
2921 
2922 				if ( pixbuf == NULL )
2923 				{
2924 					g_print ( "Failed to create pixbuf.\n" );
2925 					return TCL_ERROR;
2926 				}
2927 
2928 
2929 				para->pixbuf = pixbuf;
2930 				return gnoclRegisterPixBuf_ ( interp, para, pixBufFunc );
2931 
2932 
2933 				//goto registerpixbuf;
2934 
2935 			} break;
2936 		case LoadIdx:
2937 			{
2938 				// GdkPixbuf * gdk_pixbuf_new_from_file (const char *filename, GError **error);
2939 				gchar *opt, *val;
2940 				gchar *filename;
2941 
2942 				static char *newOptions[] =
2943 				{
2944 					"-file", "-width", "-height", "-aspectRatio", "-inLine", NULL
2945 				};
2946 
2947 				static enum  optsIdx
2948 				{
2949 					FileIdx, WidthIdx, HeightIdx, AspectRatioIdx, InLineIdx
2950 				};
2951 
2952 				gint i, j;
2953 				int idx;
2954 
2955 				/* set some default values */
2956 				gint height = 0;
2957 				gint width = 0;
2958 				gint aspect = 1;
2959 
2960 				for ( i = 2; i < objc; i += 2 )
2961 				{
2962 					j = i + 1;
2963 
2964 					opt = Tcl_GetString ( objv[i] );
2965 					val = Tcl_GetString ( objv[j] );
2966 
2967 
2968 					if ( Tcl_GetIndexFromObj ( interp, objv[i], newOptions, "command", TCL_EXACT, &idx ) != TCL_OK )
2969 					{
2970 						return TCL_ERROR;
2971 					}
2972 
2973 					switch ( idx )
2974 					{
2975 						case InLineIdx:
2976 							{
2977 
2978 								/* choose from a list of preset inline graphics */
2979 								static char *inlinePB[] = {"logo", "pointer", NULL };
2980 								static enum  inlinePBIdx { LogoIdx, PointerIdx };
2981 								int idx;
2982 
2983 								if ( Tcl_GetIndexFromObj ( interp,  objv[j] , inlinePB, "command", TCL_EXACT, &idx ) != TCL_OK )
2984 								{
2985 									return TCL_ERROR;
2986 								}
2987 
2988 								/* determine which built-in graphic to use */
2989 								switch ( idx )
2990 								{
2991 									case LogoIdx:
2992 										{
2993 											pixbuf = gdk_pixbuf_new_from_inline ( -1, gnocl_logo, FALSE, NULL );
2994 										}
2995 									case PointerIdx:
2996 										{
2997 											pixbuf = gdk_pixbuf_new_from_inline ( -1, gnocl_pointer, FALSE, NULL );
2998 										}
2999 								}
3000 
3001 								if ( pixbuf == NULL )
3002 								{
3003 									/* add suitable error message */
3004 									gchar *errmsg;
3005 									sprintf ( errmsg, "ERROR: Cannot load inline image \"%s\".\n", Tcl_GetString ( objv[3] ) );
3006 									Tcl_SetResult ( interp, errmsg , TCL_STATIC );
3007 									return TCL_ERROR;
3008 								}
3009 
3010 								//goto registerpixbuf;
3011 
3012 								para->pixbuf = pixbuf;
3013 								para->fname = filename;
3014 								return gnoclRegisterPixBuf_ ( interp, para, pixBufFunc );
3015 
3016 							}
3017 							break;
3018 
3019 						case HeightIdx:
3020 							{
3021 								height = atoi ( val );
3022 							}
3023 							break;
3024 						case WidthIdx:
3025 							{
3026 								width = atoi ( val );
3027 							}
3028 							break;
3029 						case FileIdx:
3030 							{
3031 								//g_printf ( "load file = %s val = %s\n", opt, val );
3032 								//pixbuf = gdk_pixbuf_new_from_file ( val, NULL );
3033 								filename = val;
3034 							}
3035 							break;
3036 						case AspectRatioIdx:
3037 							{
3038 								/* need error check, its a boolean! */
3039 								aspect = atoi ( val );
3040 							}
3041 							break;
3042 						default:
3043 							{
3044 							}
3045 					}
3046 				}
3047 
3048 
3049 				if ( height != 0 && width != 0 )
3050 				{
3051 					//printf ( "OK!! height = %d width = %d\n", height, width );
3052 					pixbuf = gdk_pixbuf_new_from_file_at_scale ( filename, width, height, aspect, NULL );
3053 				}
3054 
3055 				else
3056 				{
3057 					//printf ( "NOPE!! height = %d width = %d\n", height, width );
3058 					pixbuf = gdk_pixbuf_new_from_file ( val, NULL );
3059 				}
3060 
3061 				//goto registerpixbuf;
3062 				para->pixbuf = pixbuf;
3063 				para->fname = filename;
3064 				return gnoclRegisterPixBuf_ ( interp, para, pixBufFunc );
3065 
3066 			}
3067 			break;
3068 	}
3069 
3070 	return TCL_OK;
3071 
3072 registerpixbuf:
3073 	/* keep pointers */
3074 	para->pixbuf = pixbuf;
3075 	return gnoclRegisterPixBuf ( interp, para->pixbuf, pixBufFunc );
3076 
3077 }
3078 
3079 /**
3080 \brief      Obtain colour and alpha values from an RGBA pixBuf.
3081 \author     William J Giddings
3082 \date       06/03/10
3083 \since      0.9.94
3084 **/
gdk_pixbuf_get_pixel(GdkPixbuf * pixbuf,guint x,guint y,guchar * r,guchar * g,guchar * b,guchar * a)3085 void gdk_pixbuf_get_pixel ( GdkPixbuf * pixbuf, guint x, guint y , guchar * r, guchar * g, guchar * b, guchar * a )
3086 {
3087 	guchar *pixels;
3088 	guchar *p;
3089 	guint w, h;
3090 	guint rowstride, n_channels;
3091 
3092 	g_return_if_fail ( GDK_IS_PIXBUF ( pixbuf ) );
3093 
3094 	w = gdk_pixbuf_get_width ( pixbuf );
3095 	h = gdk_pixbuf_get_height ( pixbuf );
3096 
3097 	if ( w == 0 || h == 0 )
3098 	{
3099 		return;
3100 	}
3101 
3102 	if ( x > w || y > h )
3103 	{
3104 		return;
3105 	}
3106 
3107 	pixels = gdk_pixbuf_get_pixels ( pixbuf );
3108 	rowstride = gdk_pixbuf_get_rowstride ( pixbuf );
3109 	n_channels = gdk_pixbuf_get_n_channels ( pixbuf );
3110 
3111 	p = pixels + x * n_channels + y * rowstride;
3112 
3113 	*r = p[0];
3114 	*g = p[1];
3115 	*b = p[2];
3116 	*a = ( n_channels == 4 ) ? p[3] : 0;
3117 
3118 }
3119 
3120 
3121 /*---------------------------------------------------------------------*/
3122 
3123 /**
3124  * gdk_pixbuf_fill:
3125  * @pixbuf: a #GdkPixbuf
3126  * @pixel: RGBA pixel to clear to
3127  *         (0xffffffff is opaque white, 0x00000000 transparent black)
3128  *
3129  * Clears a pixbuf to the given RGBA value, converting the RGBA value into
3130  * the pixbuf's pixel format. The alpha will be ignored if the pixbuf
3131  * doesn't have an alpha channel.
3132  *
3133  **/
3134 /**
3135 \brief      Obtain colour and alpha values from an RGBA pixBuf.
3136 \author     William J Giddings
3137 \date       06/03/10
3138 \since      0.9.94
3139 \note       Adaptation of gdk_pixbuf_fill
3140 **/
gdk_pixbuf_set_pixel(GdkPixbuf * pixbuf,guint32 pixel,guint x,guint y)3141 void gdk_pixbuf_set_pixel ( GdkPixbuf * pixbuf, guint32 pixel, guint x, guint y )
3142 {
3143 	guchar *pixels;
3144 	guint r, g, b, a;
3145 	guchar *p;
3146 	guint w, h;
3147 	guint rowstride, n_channels;
3148 
3149 	g_return_if_fail ( GDK_IS_PIXBUF ( pixbuf ) );
3150 
3151 	w = gdk_pixbuf_get_width ( pixbuf );
3152 	h = gdk_pixbuf_get_height ( pixbuf );
3153 
3154 	if ( w == 0 || h == 0 )
3155 	{
3156 		return;
3157 	}
3158 
3159 	if ( x > w || y > h )
3160 	{
3161 		return;
3162 	}
3163 
3164 	pixels = gdk_pixbuf_get_pixels ( pixbuf );
3165 	rowstride = gdk_pixbuf_get_rowstride ( pixbuf );
3166 	n_channels = gdk_pixbuf_get_n_channels ( pixbuf );
3167 
3168 	r = ( pixel & 0xff000000 ) >> 24;
3169 	g = ( pixel & 0x00ff0000 ) >> 16;
3170 	b = ( pixel & 0x0000ff00 ) >> 8;
3171 	a = ( pixel & 0x000000ff );
3172 
3173 	p = pixels + y * rowstride + x * n_channels;
3174 
3175 	switch ( n_channels )
3176 	{
3177 		case 3:
3178 			{
3179 				p[0] = r;
3180 				p[1] = g;
3181 				p[2] = b;
3182 			}
3183 			break;
3184 		case 4:
3185 			{
3186 				p[0] = r;
3187 				p[1] = g;
3188 				p[2] = b;
3189 				p[3] = a;
3190 			}
3191 			break;
3192 		default:
3193 			break;
3194 	}
3195 }
3196 
3197 /**
3198 \brief	Draw line to pixbuf using Breseham's algorithm
3199 **/
gdk_pixbuf_draw_line(GdkPixbuf * pixbuf,guint32 pixel,gint x1,gint y1,gint x2,gint y2)3200 void gdk_pixbuf_draw_line ( GdkPixbuf *pixbuf, guint32 pixel, gint x1, gint y1, gint x2, gint y2 )
3201 {
3202 
3203 	int dx, dy, i, e;
3204 	int incx, incy, inc1, inc2;
3205 	int x, y;
3206 
3207 	dx = x2 - x1;
3208 	dy = y2 - y1;
3209 
3210 	if ( dx < 0 ) dx = -dx;
3211 
3212 	if ( dy < 0 ) dy = -dy;
3213 
3214 	incx = 1;
3215 
3216 	if ( x2 < x1 ) incx = -1;
3217 
3218 	incy = 1;
3219 
3220 	if ( y2 < y1 ) incy = -1;
3221 
3222 	x = x1;
3223 	y = y1;
3224 
3225 	if ( dx > dy )
3226 	{
3227 		gdk_pixbuf_set_pixel ( pixbuf, pixel, x, y );
3228 		e = 2 * dy - dx;
3229 		inc1 = 2 * ( dy - dx );
3230 		inc2 = 2 * dy;
3231 
3232 		for ( i = 0; i < dx; i++ )
3233 		{
3234 			if ( e >= 0 )
3235 			{
3236 				y += incy;
3237 				e += inc1;
3238 			}
3239 
3240 			else e += inc2;
3241 
3242 			x += incx;
3243 			gdk_pixbuf_set_pixel ( pixbuf, pixel, x, y );
3244 		}
3245 	}
3246 
3247 	else
3248 	{
3249 		gdk_pixbuf_set_pixel ( pixbuf, pixel, x, y );
3250 		e = 2 * dx - dy;
3251 		inc1 = 2 * ( dx - dy );
3252 		inc2 = 2 * dx;
3253 
3254 		for ( i = 0; i < dy; i++ )
3255 		{
3256 			if ( e >= 0 )
3257 			{
3258 				x += incx;
3259 				e += inc1;
3260 			}
3261 
3262 			else e += inc2;
3263 
3264 			y += incy;
3265 			gdk_pixbuf_set_pixel ( pixbuf, pixel, x, y );
3266 		}
3267 	}
3268 
3269 }
3270 
3271 /**
3272 \brief	Draw line to pixbuf using Breseham's circle algorithm
3273 **/
gdk_pixbuf_draw_circle_1(GdkPixbuf * pixbuf,guint32 pixel,gint xc,gint yc,gint r,gint fill)3274 void gdk_pixbuf_draw_circle_1 ( GdkPixbuf *pixbuf, guint32 pixel, gint xc, gint yc, gint r, gint fill )
3275 {
3276 
3277 	int x, y, p;
3278 
3279 	x = 0;
3280 	y = r;
3281 
3282 	gdk_pixbuf_set_pixel ( pixbuf, pixel, x, y );
3283 
3284 
3285 	p = 3 - ( 2 * r );
3286 
3287 	for ( x = 0; x <= y; x++ )
3288 	{
3289 		if ( p < 0 )
3290 		{
3291 			y = y;
3292 			p = ( p + ( 4 * x ) + 6 );
3293 		}
3294 
3295 		else
3296 		{
3297 			y = y - 1;
3298 
3299 			p = p + ( ( 4 * ( x - y ) + 10 ) );
3300 		}
3301 
3302 		gdk_pixbuf_set_pixel ( pixbuf, pixel, xc + x, yc - y );
3303 		gdk_pixbuf_set_pixel ( pixbuf, pixel, xc - x, yc - y );
3304 
3305 		gdk_pixbuf_set_pixel ( pixbuf, pixel, xc + x, yc + y );
3306 		gdk_pixbuf_set_pixel ( pixbuf, pixel, xc - x, yc + y );
3307 
3308 		gdk_pixbuf_set_pixel ( pixbuf, pixel, xc + y, yc - x );
3309 		gdk_pixbuf_set_pixel ( pixbuf, pixel, xc - y, yc - x );
3310 
3311 		gdk_pixbuf_set_pixel ( pixbuf, pixel, xc + y, yc + x );
3312 		gdk_pixbuf_set_pixel ( pixbuf, pixel, xc - y, yc + x );
3313 
3314 		if ( fill )
3315 		{
3316 			gdk_pixbuf_draw_line ( pixbuf, pixel, xc + x, yc - y, xc - x, yc - y );
3317 			gdk_pixbuf_draw_line ( pixbuf, pixel, xc + x, yc + y, xc - x, yc + y );
3318 			gdk_pixbuf_draw_line ( pixbuf, pixel, xc + y, yc - x, xc - y, yc - x );
3319 			gdk_pixbuf_draw_line ( pixbuf, pixel,  xc + y, yc + x, xc - y, yc + x  );
3320 		}
3321 
3322 	}
3323 }
3324 
gdk_pixbuf_draw_circle_2(GdkPixbuf * pixbuf,guint32 pixel,gint xc,gint yc,gint r,gint fill)3325 void gdk_pixbuf_draw_circle_2 ( GdkPixbuf *pixbuf, guint32 pixel, gint xc, gint yc, gint r, gint fill )
3326 {
3327 
3328 	int y, x;
3329 
3330 	if ( 0 )
3331 	{
3332 		for ( y = -r; y <= r; y++ )
3333 		{
3334 			for ( x = -r; x <= r; x++ )
3335 			{
3336 				if ( x*x + y*y <= r * r )
3337 				{
3338 					//setpixel(origin.x+x, origin.y+y);
3339 					gdk_pixbuf_set_pixel ( pixbuf, pixel, xc + x, yc + y );
3340 				}
3341 			}
3342 		}
3343 
3344 		return;
3345 	}
3346 
3347 
3348 	/* just the outline */
3349 	for ( y = -r; y <= r; y++ )
3350 	{
3351 		for ( x = -r; x <= r; x++ )
3352 		{
3353 
3354 			g_print ( "y = %d x = %d\n", y, x );
3355 
3356 			if ( x*x + y*y == r * r )
3357 			{
3358 
3359 				g_print ( "i= %d %d %d\n", y, x * x + y * y, r * r );
3360 
3361 				//setpixel(origin.x+x, origin.y+y);
3362 				gdk_pixbuf_set_pixel ( pixbuf, pixel, xc + x, yc + y );
3363 			}
3364 		}
3365 	}
3366 
3367 }
3368 
3369 
gdk_pixbuf_draw_circle(GdkPixbuf * pixbuf,guint32 pixel,gint xc,gint yc,gint r,gint solid)3370 void gdk_pixbuf_draw_circle ( GdkPixbuf *pixbuf, guint32 pixel, gint xc, gint yc, gint r, gint solid )
3371 {
3372 	int i, x, y;
3373 
3374 	/* solid circle */
3375 	if ( solid )
3376 	{
3377 		for ( y = -r; y <= r; y++ )
3378 		{
3379 			for ( x = -r; x <= r; x++ )
3380 			{
3381 				if ( x*x + y*y <= r * r )
3382 				{
3383 					//setpixel(origin.x+x, origin.y+y);
3384 					gdk_pixbuf_set_pixel ( pixbuf, pixel, xc + x, yc + y );
3385 				}
3386 			}
3387 		}
3388 
3389 		return;
3390 	}
3391 
3392 	/* outline only */
3393 	i = r * r;
3394 
3395 	for ( y = r ; y >= 0; y-- )
3396 	{
3397 		x = sqrt ( i - y * y );
3398 		gdk_pixbuf_set_pixel ( pixbuf, pixel, xc + x, yc + y );
3399 		gdk_pixbuf_set_pixel ( pixbuf, pixel, xc - x, yc - y );
3400 		gdk_pixbuf_set_pixel ( pixbuf, pixel, xc - x, yc + y );
3401 		gdk_pixbuf_set_pixel ( pixbuf, pixel, xc + x, yc - y );
3402 	}
3403 
3404 	for ( x = r ; x >= 0; x-- )
3405 	{
3406 		y = sqrt ( i - x * x );
3407 		gdk_pixbuf_set_pixel ( pixbuf, pixel, xc + x, yc + y );
3408 		gdk_pixbuf_set_pixel ( pixbuf, pixel, xc - x, yc - y );
3409 		gdk_pixbuf_set_pixel ( pixbuf, pixel, xc - x, yc + y );
3410 		gdk_pixbuf_set_pixel ( pixbuf, pixel, xc + x, yc - y );
3411 	}
3412 
3413 }
3414