Thursday, March 25, 2010

gnocl::pixMap

The distinction between a GdkPixBuf and the GdkPixMap/GdkBitmap is not to easy to appreciate -at the beginning at least. Its easy to assume that they are the something of the same thing but this isn't quite so. The GdkPixBuf is basically a means of loading imagery into memory where as the PixMap and BitMap objects allow direct drawing. Ok, the pixBuf can be drawn onto a pixel at a time and its contents filled but that's about it. The notion is to handle chunks of data at a more basic level rather than working with the niceties. Would it be more reasonable then, to move some of the image manipulations functionality found the gnocl::pixBuf module to a new module, gnocl::pixMap along with the drawing funcs etc? Both are 'off screen' yet the PixMap object can obtain the drawing surface of specific on-screen objects.
This approach would leave the pixbuf module for the sole process of working with the buffer in terms of composting and input/output.
Whilst it would be nice to find some clear distinctions between graphics packages, the practicality of it isn't that simple. There are many package layers, some of whose compenent functions have counterparts elsewhere. The challenge then, lies in deciding which area of functionality is best included in which gnocl package.

Colour formatting on the Tcl Side

The Tcl formt command can be used to easily convert decimal rgb colour coordinates into hexadecimal.

set color [format #%02x%02x%02x $r $g $b]

Ok, from the Gnocl view point the goal is also to allow decimal values to be passed as colours, but, of course its useful to have a Tcl way of solving the problem, especially when developing the bare bones of a new widget binding which hasn't yet had all the colour manipulation functions wired into place.




Tuesday, March 23, 2010

gnocl::curve and gnocl::gamma

Because I was feeling a little annoyed with myself after coming to a sleepy, unproductive halt over the weekend hacking away at the filters; I decided to have a look at extending the current support for the GtkCurve and GtkGamma widgets. Am I less annoyed? Not really, I’m at one of those times when the old mental agility is at a low. Got some code changes, added a few typos rather than bugs, but oh no! Keep hitting problems again. I think I’ll give Gnocl a rest for a few days, just to let the old brain recharge itself!



Sunday, March 21, 2010

New widget and pixbuf filters

No new posting to the Blogsite have been made over that past few days, not because of inactivity but due to quite the opposite -too much! My daily coding sessions between Thursday and Saturday this week have have resulted in the addition of one new widget type and a bagful of image processing filters. This is what has been added:

gnocl::colorWheel

Gnocl already has bindings to the GtkColorSelectionDialog which includes the familiar HSV colour selection wheel. This is what it looks like:



The colour ring itself is a widget in its own right simply called: GtkHSV. The inclusion of this binding was really straightforward as the widget itself has only minimal signals and not specific properties (but of all, the object is easily configured in Gnocl). Whilst it may be a specialist item such as the various deprecated GIMP specific widgets, the decision to include it in the forthcoming release was rather impulsive and largely as the result of the range of pixbuf processing tools coming into Gnocl. Which of course leads to the next thing to report, the inclusion of the pixBufFilters.c module.

Pixbuf filters

At the time of writing the pixbuf.c module itself had grown into some 2500 lines of code which, for me, is too much. I’m a minimalist. I prefer smaller, well-ordered discrete bites of code rather than sprawling heaps of code leviathans. The pixBufFilter.c module then is not intented to be a Imagemagick or Gimp replacement, but set of simple useful image manipulation and processing tools. At the moment the functionality is compiled into the gnocl core itself, but it would be more in keeping with the idea of the main Gnocl module to purely handler Gtk+ objects to later move the filter extensions into a separate package.
The list of filters in by no means complete. Those currently included in the code are:
brightness
color
gamma
grayscale
invert
contrast

Wednesday, March 17, 2010

Some more obscure Text widget commands

This morning I added a few extra commands to the text widget which, are somewhat odd, I admit, but does provide further widget introspection for those who might need it.

text-id getCoords start
text-id getCoords cursor
text-id getCoords {1 0}
text-id getIndex {15 15}
text-id getRect
These commands are derived from the GtkTextView widget rather than GtkTextBuffer and GtkTextIter and so are more focussed on how text is rendered to the display rather than the text content itself. Internally, the Gtk+ keeps track of what is kept in the current text display buffer. Looking at the above examples one can see that getCoord takes as its argument either a text index, ie line 1, row 1 (of the text buffer) or one of several positioning keywords. What is returned is the window x,y pixel coordinates for that position. The opposite effect is produced by getIndex, here 15 15 is the pixel x,y coords whose content we want to determine in terms of its corresponding position in the textBuffer. Finally, getRect returns the window position and size of the rendered region of the text. If a specified position is not in the textView, then a negative value will be returned.

I’ve always found the idea of matched data and display buffers (i.e. a viewport) to be a little hard to work with. When I have the time I’ll create an illustrative diagram.


NEW COMMANDS for gnocl::text - getIndex and lorem

In response to a support enquiry I received a few days ago, I’ve just added a new widget command for gnocl::text that returns the line and character position under  specified window coordinates. Here’s how it can be used: 

set txt [gnocl::text -wrapMode word -baseFont {ILShakeFest 12} ]
$txt lorem


gnocl::window -child $txt -widthRequest 320 -heightRequest 200
$txt configure -onButtonPress {
   puts "x = %x y = %y ; index = [%w getIndex %x %y]"
}

Also, because I’m getting annoyed always having to cut-n-paste text clips into a text widget for preview purposes, I’ve decided to add a further command: lorem. This will insert a paragraph of the well-recognised typesetter dummy text. Add to it an antique typeface and it looks totally wacky and completely illegible! Here’s a screenshot. (NB: I Wouldn't recommend ILShakeFest as a system font!]


Tuesday, March 16, 2010

Save pixBufs with compression etc..

The Gtk+ libraries upon which the pixBuf save command is implement are in to forms, one that does a ‘plain vanilla’ save and one which receives a list of parameters whose names and values change in relation to the file type being saved out to. Saving with compression, for instance, can result in a marked reduction in file size so this feature needed to be available from the scripting point of view. The following lines of Tcl/Gnocl code illustrate the usage:

$pb2 save -fileName test2.tif -fileType tiff
$pb2 save -fileName test3.jpg -fileType jpeg
$pb2 save -fileName test4.jpg -fileType jpeg -parameters [list quality=50]

Here the option -fileType is specified as there is no internal checking of file extensions. (Put this on the todo list!).


Monday, March 15, 2010

Create pixBufs properly..

When I was looking over my buffer code this morning I felt that something was not quite right. Ok, the code was fine. I did ‘what it says on the tin’, but there was something wrong. After I realised what it was, ie creating a pixbuf like this:

set pb1 [gnocl::pixBuf new {640 480 8 0} ]

I re-worked the buffer code the result of which alows the creation of this:

set pb1 [gnocl::pixBuf new \
   -width 640 -height 480 \
   -bitsPerSample 8 \
   -alpha 1 \
   -colorSpace RGB]

Much more Gnoclish! The former wasn’t wrong, there is only one command to create a buffer, and once set it cannot be re-configured like widgets. Ok, so now all is fine. Or is it? We now have an anachronistic info command, the one I blogged about this morning. Well, scrap that. Use cget instead! Ah, yes, its all coming together. Perhaps a bit of ‘weeding’ late this afternoon. In the garden? Nay, to the source code, I need to weed out all the unwanted bits of comments, debugging calls and redundant stuff.

NEW COMMAND: gnocl::inventory

Yesterday I put together some code to list the registered widgets and this morning I implemented the equivalent to display pixbufs. After assembling all the code together, it all looked a little clumsy, with two commands performing the same fundamental operations. So, I re-thought what was going on and created a new command, ‘inventory’ which then enables the script to specify registered types which, in this case, are ‘widget’ and ‘pixbuf’. This works fine. The general structure means that a framework exists for deeper gnocl introspection.

Whilst putting a test script together I noticed that another simple function was missing, the ability to get details regarding any existing pixBuf. So, I added a pixBuf ‘info’ sub-command. This is what one gets when development is ‘evolutionary’ rather than ‘ planned’.

Here's an illustrative script sample:

for {set i 1} {$i <12} {incr i} {
    gnocl::window -title "win $i"
    gnocl::pixBuf new {100 100 8}
}
foreach item [gnocl::inventry widget] {
    puts "$item is a [$item class]"
}
foreach item [gnocl::inventry pixBuf] {
    puts "$item [$item info]"
}

Sunday, March 14, 2010

Command Deleted: gnocl::windowList

I expect that no one has experimented with this anyway besides, it would have given an error. This was a binding to a Gdk library function that returned a list of GdkWindows and not GtkWindows. This information is not much use to the Gnocl scripter and so it has been removed.


New command gnocl::widgetList

Simply put, this command will return a list of all widgets known to the Tcl/Gnocl interpreter.

Looking at the resultant code, it looks as though a gnocl::pixBufList is a logical progression as both types of object are registered in their own hash-lists.

Builder -packing specific widgets -DONE!

Completed this section of the code. It works well and lots of error trapping. In fact this would account for about 95% of the code for the options.

There are other ways that this could be done within a script, builder created widgets should be given aliases and these can than be manipulated in the usual way. What is good here though, is the idea of creating widget instances. With the pure scripting route only one set of widgets are built. Using the builder route, multiple instances of widgets from a XML description file could be used. Keeping track of them, however, is a different matter!

Saturday, March 13, 2010

Gradient Fills and Other Pixbuf Drawing Funcs

A few days have now passed since I was working on the pixBuf gradient fills. Clearly adding code of my own is a pointless exercise. Cairo does all this sort of thing and its and integral layer of the Gtk+ rendering pipeline. So, indulgence over. Leave it all for gnocl::cairo sometime during the summer.

Given it some thought and a decision made.

The aim behind creating Gnocl is to facilitate the creation of complex layouts. This assumes that the appropriate level or error checking will be made internally and decisions made on how best to proceed based upon the values passed from from the calling script. The answer then is to modify the current buider.c code to detect whether single item or multiple object lists have been received and then to determine which packing call to use, that is either gtk_box_pack_end () or gtk_container_add (). The sequence of items in the list will, by default, be assumed to be the right packing order.





Loading object from a builder UI buffer

I’ve now got the code running to pack objects (i.e. widgets) defined in a builder XML file into a specified, pre-existing container. Containers as such only have one child object, whereas other objects such as tables and boxes. In general the only container which accommodates a single child is a toplevel window. The code as it stand will allow the script to pass a list of objects to be packed, but at it stands, only one, item will be successfully packed using the current code.
Although in practice, the recipient container will be a box, so, should I replace the container test to and throw an error if it cannot accept a list of children, or, should the size of the array be tested and then the appropriate Gtk call made to perform the packing process for adding a child to a container, or packing into boxes. If the latter, then what level of support should be given for the padding, fill and expand properties?



Wednesday, March 10, 2010

Applications Developer feedback coming in

I’m getting more feedback regarding development issues now that the Discussion Group and Web site are now on line. This is great! It means that not only are others using Gnocl, but in many cases looking at the source itself -just as the packages are intended. Got one this evening regarding the loading of builder UI xml files. This was  pretty good error spotting! The error, though not fatal on my system, was to load an entire UI description file using a command basically intended to load named UI objects (and their child sub-tree) into a named, pre-existing container.

Why was this left there?

After working quite intensely on Glade over the Yuletide I needed a change (hence the move onto the gnocl::pixbuf package). The point at which I left it was at this exact stage. So, the task for the next day or so is the implementation of a new set of options for the buffer load command. This will be along the lines:

gnocl::builder buffer <buffer> -object <list> -container widget-id

Tuesday, March 09, 2010

Gradient Fills at Arbitrary Angles

A bit fiddly this one. Nested loops, checks and operations all that sort of thing! Had very little time to work on the project today, answered some group messages, did a little bit of tidying up on the website.


Monday, March 08, 2010

Gnocl on Windows -Working

Just installed all the necessary requirements to get Gnocl running on MS-Windows, and all works well. I would post a screen grab of the GnoclEditor script running but my laptop key mapping isn’t having any of it! Haven’t run the combination for long yet and so I think that are there might things to iron out but, it looks promising. This time, however, the tables are reversed for Tk/Gnocl. Gtk still retains something of its native look at the moment, whereas the Tk looks native on Windows. The fonts are larger and the Icons are the familiar Crystal icon set. Still, early days. I need to completely install a development environment on my laptop and attempt to recompile the code. After that, I’ll put the package up for adoption.



Sunday, March 07, 2010

Gradient fills

Ever since I got into graphics in the early eighties I’ve always wanted to have the excuse to put together code for gradient fills and working on gnocl::pixBuf gives me just that. At the moment, the fills are generated on the Tcl script side of things, but later on I hope to produce a module for image manipulation and processing on the gnocl::pixBuf and will convert these routines to C equivalents when the time comes to it.
Here’s the screenshot...






Get the script here: [1]



Saturday, March 06, 2010

Getting single pixel values -DONE!

Just finished the function to obtain specific pixel values. This is really useful now as it means that pixbuf can now be accessed for some controlled drawing operations.

Usage:  pixBuf-id getPixel {x y}
Returns: RGBA 

Setting single pixels values in a gnocl::pixBuf

Ok, its pretty clear that I'm a Penguin. I love Linux, Gnome and the principles of OpenSource. But, and its only a small, yet annoying’ but’ typical of any loving relationship, that there are little things not done that we take for granted will be done. Sounds familiar? The Gdk libraries contain some really useful tools, so why some of the simpler things are omited? For example, there is a gdk_pixBuf_fill command, for clearing the screen to a single colour by painting each pixel individually, yet there is no library command for painting a single pixel itself! Not an insurmountable problem, but a capability that one would expect to be there.
The assumption is, perhaps, that any drawing operations will be done to GdkDrawables, i.e. anything in a window rendered to the screen. GtkPixBufs are ‘off-screen’, the buffers that can be draw and worked with independently or prior to any rendering operation. My guess too is that if a programmer needs to draw to a buffer, its better done by rendering to it using Cairo.
To resolve this omission, I’ve examined the Gdk source code for something useful to hack. Of the course the right func is the above said gdk_pixbuf_fill. Now I have a usable pixel painting function that runs nicely, having put together what might be described as the missing gdk_pixbuf_set_pixel. Now the complement, a gdk_pixbuf_get_pixel function, is the thing to put together. Where’s all this leading, one might ask... to the addition of a set of pixbuf image manipulation commands! More on this later.

Here's the screenshot,











And the script that built it.

set pb1 [gnocl::pixBuf load "vyrnwy_small.png"] 
set img1 [gnocl::image -image "%?$pb1"] 

set box [gnocl::eventBox -child $img1] 

$box configure -onMotion { 
    $pb1 setPixel [list %x %y] #FF0000 
    $img1 configure -image "%?$pb1" 
    gnocl::update}

gnocl::window -child $box

Friday, March 05, 2010

PixBuf commands: saturations and pixelation

On a roller today! Added two more pixBuf commands: saturation and pixelate. The test script tells all:

set pb1 [gnocl::pixBuf load "vyrnwy_small.png"]
set pb2 [$pb1 saturation 0.0]
set pb3 [$pb1 saturation 5.0]
set pb4 [$pb1 pixelate]
 
set box [gnocl::box -orientation vertical]
 
gnocl::window -child $box
 
$box add [gnocl::image -image "%?$pb1"]
$box add [gnocl::image -image "%?$pb2"]
$box add [gnocl::image -image "%?$pb3"]
$box add [gnocl::image -image "%?$pb4"]

Here’s the screenshots to shows the result:


Added cget command to pixBuf objects

Just implemented the cget command for pixBufs. It usage takes the form:

     pixBuf-id cget [-option]

These being the options that can be queried.

     -bitsPerSample
     -colorSpace   
     -hasAlpha
     -height
     -nChannels
     -pixels
     -rowStride
     -width

These correspond to the GdkPixBuf ‘ properties’ as described in the docs. A further option

     -key

is taken from the library docs relating to the function that ‘get’ the values of these properties. Semantically, if there is a cget, then ought to be a configure equivalent. Also, a new buffer should also be created using the familiar syntax.

     gnocl::pixBuf
-width 100 -height 100 -bitsPerSample 8 -hasAlpha 1

Currently, this is initiated with:
    
     gnocl::pixBuf
new width height depth

This is clearly inconsistent with the required syntax. This needs to be recoded.Of the options, I’m still not certain in my min d what the options actually - pixels and -key do. But, I’m sure all will be clear, or at least less confusing with time.

Creating Circles and Arcs on the Gnocl Canvas

The gnocl canvas has no direct support for arc, is that odd? Not really, examination of the source for the Gnome Canvas shows that the ellipse is in fact a bezier circle. So, not only is this an approximation to a circle but the creation of arcs is going to be a nightmare. Ok, I've seen it done on Graphics apps such as animation systems using nurbs modelling, but we want to avoid curves as much as possible! What is needed is a simple solution on the scripting side. Build a list of coordinates that generate a circle or arc and pass these to the gnocl::canvas object line command. This will create a suitable polyline.
Here's a sample script that I've just puts together which does the job. Notice too, that the segments count for the arc is dependent upon the angle sweep. This could be modified to take into account the radius of the curve of the object if needed. Here's a screenshot:




And here's the script:

#!/bin/sh
# the next line restarts using tclsh \
exec tclsh "$0" "$@"
package require Gnocl
package require GnoclCanvas

# x y co-ordinates of the centre of the arc
# r radius of the arc
# angle of start point
# angle of subtended by the arc # minium of step in the arc
proc rads {a}{return[expr $a * 0.017453333] ;# ie PI/180}

proc poly_arc {x y r a1 a2 {s 4}} {
# calculate the number of segments
set j [expr $a2 / 5]
if {$j >= $s } {set s $j}
# calculate angle increment
set delta [expr $a2 / $s]
# create coordinates for the polyline
for {set da $a1} {$da <= [expr $a1+ $a2] } {incr da $delta} {
set x2 [expr $x + cos( [rads $da] ) * $r]
set y2 [expr $y - sin( [rads $da] ) * $r]
lappend coords $x2
lappend coords $y2
}
return $coords
}

set canv [gnocl::canvas -background white]

gnocl::window \
-width 250 \
-height 250 \
-child $canv \
-title concentrics \
-onDelete exit

foreach {ang clr} {0 red 120 green 240 blue} {
for {set i 100} {$i >= 5} {incr i -5} {
# draw the line
$canv create line \
-coords [poly_arc 125 125 $i $ang 120] \
-fill $clr \
-width 1 \
-tags "concentric"
}
}
 
gnocl::mainLoop 













Gnocl Web Resources Gaining Support

Ok, its early days, but the interest, or curiosity at least I guess, is gathering around the use of the Gnocl Google group pages as well as the on-line docs themeselves. Already got postings regarding feed back and support on the canvas widget. Its good to be of help.

The GSOC announcement came via the Tcl Wiki and newgroup today which was kindly forwarded by Bob, proposed Gnocl as a possible focus for some coding over the summer. There's lots to choose from. The completion of the GtkPrint bindings or some work on the Abiwidget would be my own personal choice, but then there are some many interesting packages to work with.

Didn't make any Blog posts yesterday, I was spent the extra minutes studying the GdkPixbuf docs for features to support.

One item to add to the todo list is are more options for the gnocl::canvas. Parametrically, an ellipse in a squashed circle, but interactively there are some differences. Indeed, many CAD systems have different ways of defining a circle. It might be useful to add include some of these options as new a new 'circle' command for the canvas.

Tuesday, March 02, 2010

Getting a copy of a GdkDrawable window

After a couple of days break, its back to gnocl::pixBuf. Today's implemented feature is grabbing a copy of the widget's graphics. For this to work, of course, the item needs to be rendered. Here's the test snippet, clicking a button will result in its picture being 'grabbed'.

set but1 [gnocl::button -text "Hello World" ]
set win1gnocl::window -child $but1]

$but1 configure \
     -onClicked {
         set pb1 [gnocl::pixBuf get drawable $win1]
         $pb1 save fileName.png}