Re: using cairo surfaces
- From: Ivan Baldo <ibaldo adinet com uy>
- To: Tommi Sakari Uimonen <tuimonen cc hut fi>
- Cc: gtk-app-devel-list gnome org
- Subject: Re: using cairo surfaces
- Date: Wed, 18 Oct 2006 20:32:22 -0200
Hello Tommi.
El 18/10/06 04:41, Tommi Sakari Uimonen escribió:
Hi, thanks for your answer!
You are welcome! I also get some help from people here so its nice
to give something in return :).
Yes, this I already did. But I still have problems with gtk regarding
what kind of widgets to use as the container and child. Currently the
child is GtkImage. The container is the hard part. I have managed to
use GtkHBox, but I would like to use something like GtkLayout, or
actually I don't know what would be best. The container has also some
cairo drawing, which draws on top of the child widgets.
Mmm... I don't quite understand what you are trying to accomplish so
I don't know what to tell you here.
Are you sure you need a container and various child widgets?
Can you instead use only a GtkDrawingArea?
Now, since the stored surface is the same height and width as the
whole widget, I set startPosH and startPosV to 0, otherwise the
rectangle to be drawn is not taken from the correct position in the
stored surface.
Yes, if your "cached" surface has the same dimensions as your
current surface then you should use 0 there and use a cairo_rectangle
with 0,0 and yourWidth,yourHeight to fill the cached surface in it.
Or am I wrong? I'm not quite sure, maybe the next example lights
things up:
Let's imagine the surfaces as two identical playing cards. If small
area on the center of the card needs to be redrawn, I just place the
new card on top of the old one and draw the needed area from the new
card, while other areas in the old card remain untouched. If I put
nonzero values to startPosH/V the cards are no longer aligned and
yields to incorrect result.
You are right.
Though, I don't understand: the new card and the old card are two
cards or are the same card but you just want to modify a portion of it?
If the latter, then GTK already does the cache of the old card for
you, you just need to draw what GTK tells you to draw and nothing more.
In the expose event, you have a parameter that is a GdkEventExpose,
in it, you have some ways to find out what needs to be drawn. One way is
to use the gdkEventExpose->area.x, area.y, area.width and area.height;
that gives you the rectangle you need to draw (relative to your
container, for example, a GtkImage or GtkDrawingArea). That method isn't
the most performant one, the best one is to use the event->region
information, which gives more exact information about what needs to be
drawn.
You can tell Cairo what to draw and what to skip with:
gdk_cairo_region( myCairo_t, myGdkEventExpose->region );
cairo_clip( myCairo_t );
That speeds things up because Cairo doesn't draw things that it
doesn't need, though AFAIK Cairo needs to be more smart about it and
optimize things more, but at least it already do some things and likely
it will just improve with time :). You can help it though: there are
gdk_cairo_* functions to find out if a point is inside the region or
not, you can use that for two things: one is to avoid bothering Cairo
and another is to avoid doing some unecessary computations in your own
application too.
What does the cairo_rectangle actually do? And how does the
set_cairo_surface restrict to drawing only to the exposed area, or
does cairo handle the drawing for the exposed area only even if I draw
the whole surface?
The cairo_rectangle serves as a container for the fill of the cached
surface you have.
When you use cairo_clip() (and you should do) Cairo knows what to
draw and what not and will never draw outside the clipping path that you
defined with cairo_clip().
I'm not quite sure how to copy a small part of previously stored
surface to current surface at the same position, or if I do scrolling
I just copy most of the stored surface to slightly different position
and draw the new information.
It depends on your performance needs.
You can do things smart (and more complex) by getting the contents
of the drawable and slide it according to the scroll size and then draw
only the remaining part; or you can do things more easily: just draw
everything again with the new offsets or different translation in your
transformation matrix.
What happens, no matter what size the exposed event area is, if I draw
the whole wiget area? Does cairo ignore the draw commands that affect
outside the exposed area? Does this give bad performace?
If you use cairo_clip(), then Cairo will not draw outside of the
clipping path.
You may cache different parts of your drawing to speed things up. In
my application for example, there is a background image that I
translate, rotate, scale, sheer, change brightness and contrast, and
that is all slow, so I just cache the result of that and I regenerate it
only when the user changes the Zoom level.
It needs some logic to decide what to draw and where, if I'm supposed
to draw only the exposed area. I know I'm bound to do that at some
point, but for now I just draw the whole thing. It's nothing very
complex, it's just text.
Thats all good if it gives you acceptable performance, be sure to
use cairo_clip though as that gives extra performance and its easy to
do, just a couple of library calls in your expose handler.
I suggest to follow the examples, there is a Clock Widget done using
Cairo
(http://www.gnomejournal.org/article/34/writing-a-widget-using-cairo-and-gtk28)
and is a good example for a lot of things and a good start, though
instead of using the cairo_rectangle for clipping just use the
gdk_cairo_region for clipping, that gives better performance, thats the
only thing that I would change to that tutorial.
Hope this helps.
Happy coding! :)
--
Ivan Baldo - ibaldo adinet com uy - http://ibaldo.codigolibre.net/
ICQ 10215364 - Phone/FAX (598) (2) 613 3223.
Caldas 1781, Malvin, Montevideo, Uruguay, South America.
We believe that we are free, but in reality we are not! Are we?
Alternatives: ibaldo codigolibre net - http://go.to/ibaldo
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]