Re: using cairo surfaces



   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]