Showing posts with label cairo. Show all posts
Showing posts with label cairo. Show all posts

Wednesday, 6 January 2010

Sneak Preview of Conky 1.8.0

So...

I was tipped off whilst trolling the #conky channel on IRC that there would be new ARGB support in the 1.8.0 release candidate of Conky, so naturally I HAAAAD to try it out! I grabbed the latest version from here, and had a go...

First things first, I wanted to try out ARGB, in other words, REAL transparency, as opposed to pseudotransparency. For those of you who don't know the difference, pseudotransparency, rather than actually being see-through, detects what's drawn on the desktop window, and draws it as the Conky background, so it appears, on a blank desktop, as though it's clear. However, as we've seen before, pseudotransparency can cause some hiccups, if you're expecting it to behave like real transparency. It's a particular problem in KDE, for instance, which doesn't draw anything to the desktop window by default, so Conky ends up with a blank background.

In order to test the ARGB functionality, I made a little widget in Lua/Cairo that would be able to sit on top of my other windows, and here's what it came out as:
From My Little Desktop Photos
Note how you can see the corner of my window *through* the Conky widget...That's ARGB!

Some of you eagle-eyed readers may also have noticed that I said I used Lua/Cairo to draw the widget, but the last time I posted about text manipulation in Cairo, I was frustrated by the lack of a cairo_text_extents() object, which allows for centering and alignment of text. But it's now been compiled into the Cairo bindings Conky uses, so from v1.8.0, you'll be able to use it. The desktop I'm currently using has only Conky widgets on it:
From Screenshots
With the current setup, I'm starting to wonder what the benefits are of using Conky over Screenlets...I first thought that it would actually be more efficient to use Screenlets, because I thought they were compiled, but some clever clog pointed out to me that they are written in Python, so not compiled! I think the only barrier to Conky completely taking over Screenlets' territory now is the user-friendliness of Screenlets...Hm...

Thursday, 5 November 2009

Memory usage with imlib2 for Lua

I recently started working with imlib2 bindings for Lua as part of the work I'm doing with learning the whole Cairo thing...Please see my latest post over on the Conky Blog.

However, I ran into an interesting problem when I was writing that script, not having written anything with imlib2 bindings before! As I was testing my photo album script, I found that I had a memory leak...The longer I left my script to run, the more and more my memory usage would ramp up until it topped out and I found I couldn't display any more photos. Eep! Not really what you want from a photo album.

So I thought I'd share with you a little bit about how imlib2 draws pictures, as opposed to the way Cairo does it, because having had a bit of experience with Cairo actually led me to think about image drawing in a way that made it difficult to work with imlib2, because the two are so different.

First of all, why use imlib2 at all when you can, to some extent, use Cairo to draw pictures? Well, the reason I turned my hand to it was because I wanted to be able to render .jpg images in my Conky, and the Cairo bindings we use can only interpret .png at the moment, through cairo_image_surface_create_from_png(...). By contrast, if you load an image using imlib2, it auto-detects the type and scans its own internal libraries to find a suitable decoder. So imlib2 has a much broader range of image type support, with no fiddling.

If you want to manipulate existing images in imlib2, first you need to load the image into memory with imlib_load_image(...). Eventually, if you want to then draw that image onto the Conky window, you'll use the imlib_render_image_on_drawable(...) function. However, if you want to manipulate that image first, you will need to do all your manipulation on a "buffer" image before you render it onto the surface.

Now, I'm not very good (yet!) at working with transformations in Cairo, so I'm used to thinking of things like a plotter...Move to (a, b), draw a line to (x, y) and stroke. So when I want to draw an image to a window, what I really want to do is load an image, select the rectangle to draw it into, and then "fill" it in...But that's not really the way to do it with imlib2. My example will be my photo album script...Essentially, I wanted to load an image and draw it onto the Conky window at a set (smaller) size. However, I found that if I just load the image and then draw the image at a smaller size using the following:
imlib_blend_image_onto_image(image, 0, 0, 0, w_img, h_img, 0, 0, width, height)
imlib_render_image_on_drawable(xc - width/2, yc - height/2)
I wound up with a horrific memory leak...Basically, I was loading the images into memory and LEAVING THEM THERE. AT FULL SIZE. Ouch.

(For those of you who are wondering, the lines above shrink the image from w_img x h_img down to a specified width x height, then draw it on the Conky window at the coordinates in the second line...)

What you need to do to avoid the memory leak is to very carefully manage your memory usage by freeing your images after you're done with them. The good way, then, to draw my reduced images onto the Conky window is to use the following method:
image = imlib_load_image(album_dir .. filename)
if image == nil then return end
imlib_context_set_image(image)

w_img, h_img = imlib_image_get_width(), imlib_image_get_height()
buffer = imlib_create_image(width, height)
imlib_context_set_image(buffer)

imlib_blend_image_onto_image(image, 0, 0, 0, w_img, h_img, 0, 0, width, height)
imlib_context_set_image(image)
imlib_free_image()

imlib_context_set_image(buffer)
imlib_render_image_on_drawable(xc - width/2, yc - height/2)
imlib_free_image()
This code does the following:
  1. loads the given image into memory, in a variable called "image"
  2. checks to see if the image has loaded successfully; if not, breaks out of the function
  3. sets the imlib2 context to be "image"
  4. grabs the dimensions of the loaded image
  5. creates a "buffer" image
  6. sets the context to be "buffer", so we can blend onto it
  7. draws a scaled-down version of the image onto "buffer"
  8. sets the context back to "image", so we can release it
  9. releases the original loaded image, so we are then just left with the scaled down version, still held in memory
  10. sets the context back to "buffer", so we can draw what's on it onto the drawable window
  11. draws whatever's in "buffer" onto the Conky window
  12. releases the buffer image
You can start to see from this how you can also use the buffer image (or a series of them!) to do some fairly sophisticated image & text manipulation before rendering onto the drawable window.

For more information on the functions available to you in imlib2, check out their documentation.

In the meantime, here, have a screenie :)
From Screenshots
You can also grab the script that made it, from the Conky Blog, or my DevArt account.

Monday, 26 October 2009

Argh. My first snag with my lovely Lua/Cairo!

So I've been working on making a lovely little eye-candy calendar widget to display with my Conky Widgets script, but I ran into a snag...Here's the best version I got before giving up (for now!):
From My Little Desktop Photos
Can you spot the annoyingness yet?

The text is misaligned!

As it turns out, Cairo draws text from an anchor point roughly at the lower left corner of the text being displayed. In this code, the month name/year, days of the week and day numbers are all evenly spaced on a square grid, but they look uneven because they are anchored at that lower-left position.

What I really want is for each element to be centered in a block. So the month/year is centered in a block that spans the top of the widget, and each of the day numbers is centered in a small square, like on a printed calendar.

However, in Cairo, you can't change where a text element is anchored, but you CAN use a function called cairo_text_extents() to give you some size information about the text block you want to manipulate, and then move to an appropriate start point. (See the Cairo tutorial for a more detailed explanation.)

I must have spent hours trying to get this function to work before I finally gave in and asked the Conky devs...and got this response: "tolua++ doesn't export any creation functions (or constructors) for C structures, only C++ classes." Basically, the third argument in the cairo_text_extents() function is of the structure cairo_text_extents_t, which isn't recognised by Lua.

All this roughly translated: as it stands now, we can't do any sophisticated text manipulation using Cairo in Lua. Booooo.

So the calendar is going to one side for the time being. Incidentally, if you would like to grab the Lua code for this widget, here you go.

Thursday, 1 October 2009

If you haven't tried Lua/Cairo yet, you're missing out!

Wow. So, it's been a while, huh? Well, don't you worry, I've been busy. I started teaching myself Lua, so I could do some scripting with the new Cairo bindings.

I've done a little Getting Started Guide over at the Conky Blog, and I've done some scripts, which are posted over at Conky Hardcore. If you haven't tried it yet, I HIGHLY RECOMMEND IT!!! Here are some screenies to whet your appetite :)
From Screenshots
From Screenshots
From Screenshots
From Screenshots
...All done with Conky, and only Conky :)

Saturday, 29 August 2009

Can someone please teach me (instantly) how to program Lua/Cairo?!

Weeeeeellll. Another feature of Conky 1.7.2 that, it has to be said, makes it closer to TAKING OVER THE ENTIRE WORLD, is the built-in set of Cairo & imlib2 bindings for Lua. (Don't worry, I'm not entirely sure what that means either...) What it does is make things, like the following, possible:
From Screenshots

The pies in this little beauty were accomplished with a script by Conky's own main dev, Brenden, using Cairo in a Lua script. The .conkyrc, Brenden's original script, the modified version that got me the screenie above, along with the screenie to guide you, are all packaged together over on my gnome-look.org site.

I only WISH I had this kind of skill!!! (Hence begging for someone to teach me!) But alas, I have no patience, and my brain is already onto the next thing. I must admit, I depend on y'all, my loyal Conky fans, to come up with something brilliant instead...

Happy Conkying!