views:

51

answers:

1

I am using python-clutter 1.0

My question in the form of a challenge

Write code to allow zooming up to a CairoTexture actor, by pressing a key, in steps such that at each the actor can be re-drawn (by cairo) so that the image remains high-res but still scales as expected, without re-sizing the actor.

Think of something like Inkscape and how you can zoom into the vectors; how the vectors remain clean at any magnification. Put a path (bunch of cairo line_to commands, say) onto an CairoTexture actor and then allow the same trick to happen.

More detail

I am aiming at a small SVG editor which uses groups of actors. Each actor is devoted to one path. I 'zoom' by using SomeGroup.set_depth(z) and then make z bigger/smaller. All fine so far. However, the closer the actor(s) get to the camera, the more the texture is stretched to fit their new apparent size.

I can't seem to find a way to get Clutter to do both:

  1. Leave the actor's actual size static (i.e. what it started as.)
  2. Swap-out its underlying surface for larger ones (on zooming in) that I can then re-draw the path onto (and use a cairo matrix to perform the scaling of the context.)

If I use set_size or set_surface_size, the actor gets larger which is not intended. I only want it's surface (underlying data) to get larger.

(I'm not sure of the terminology for this, mipmapping perhaps? )

Put another way: a polygon is getting larger, increase the size of its texture array so that it can map onto the larger polygon.

I have even tried an end-run around clutter by keeping a second surface (using pycairo) that I re-create to the apparent size of the actor (get_transformed_size) and then I use clutter's set_from_rgb_data and point it at my second surface, forcing a re-size of the surface but not of the actor's dimensions.

The problem with this is that a)clutter ignores the new size and only draws into the old width/height and b)the RGBA vs ARGB32 thing kind of causes a colour meltdown.

I'm open to any alternative ideas, I hope I'm standing in the woods missing all the trees!

\d

A: 

Well, despite all my tests and hacks, it was right under my nose all along.

Thanks to Neil on the clutter-project list, here's the scoop:

CT = SomeCairoTextureActor()

# record the old height, once:
old_width, old_height = CT.get_size()

Start a loop:
# Do stuff to the depth of CT (or it's parent)
...

# Get the apparent width and height (absolute size in pixels)
appr_w,appr_h = CT.get_transformed_size()

# Make the new surface to the new size
CT.set_surface_size( appr_w, appr_h )

# Crunch the actor back down to old size 
# but leave the texture surface something other!
CT.set_size(old_width, old_height)

loop back again

The surface size and the size of the actor don't have to be the same. The surface size is just by default the preferred size of the actor. You can override the preferred size by just setting the size on the actor. If the size of the actor is different from the surface size then the texture will be squished to fit in the actor size (which I think is what you want).

Nice to put this little mystery to bed. Thanks clutter list!

\d