Thread: [Goocanvas-devel] SVG rescaling support
Status: Beta
Brought to you by:
dachaplin
From: Bruno C. <bru...@fr...> - 2007-10-13 20:30:51
|
I am currently trying to port GCompris to goocanvas. We were using the venerable gnomecanvas and since your API is close it make sense to use goocanvas and get a brain modern graphical backend from cairo. We have a specific requirement. We use SVG for our images and we use the scaling feature of the canvas. But since goocanvas-image work at pixbuf level (like gnomecanvas-pixbuf), once our svg is loaded, it is always rescaled pixel based with quality lost. Have you identified this need on your side, how would you do this with goocanvas? -- Bruno Coudoin http://gcompris.net Free educational software for kids http://toulibre.org Logiciel Libre à Toulouse |
From: Damon C. <da...@ka...> - 2007-10-15 09:30:31
Attachments:
svg-canvas-item.tgz
|
On Sat, 2007-10-13 at 22:30 +0200, Bruno Coudoin wrote: > I am currently trying to port GCompris to goocanvas. We were using the > venerable gnomecanvas and since your API is close it make sense to use > goocanvas and get a brain modern graphical backend from cairo. > > We have a specific requirement. We use SVG for our images and we use the > scaling feature of the canvas. But since goocanvas-image work at pixbuf > level (like gnomecanvas-pixbuf), once our svg is loaded, it is always > rescaled pixel based with quality lost. > > Have you identified this need on your side, how would you do this with > goocanvas? Creating an SVG item would probably be best. I wrote a simple SVG item a while back, which I've attached. Compile the demo with: gcc `pkg-config --cflags --libs goocanvas librsvg-2.0` simple-demo.c It doesn't do hit-detection though, since librsvg doesn't provide any way to do that. Damon |
From: Bruno C. <bru...@fr...> - 2007-10-15 22:48:43
|
Le lundi 15 octobre 2007 à 10:30 +0100, Damon Chaplin a écrit : > On Sat, 2007-10-13 at 22:30 +0200, Bruno Coudoin wrote: > > I am currently trying to port GCompris to goocanvas. We were using the > > venerable gnomecanvas and since your API is close it make sense to use > > goocanvas and get a brain modern graphical backend from cairo. > > > > We have a specific requirement. We use SVG for our images and we use the > > scaling feature of the canvas. But since goocanvas-image work at pixbuf > > level (like gnomecanvas-pixbuf), once our svg is loaded, it is always > > rescaled pixel based with quality lost. > > > > Have you identified this need on your side, how would you do this with > > goocanvas? > > Creating an SVG item would probably be best. > > I wrote a simple SVG item a while back, which I've attached. > > Compile the demo with: > gcc `pkg-config --cflags --libs goocanvas librsvg-2.0` simple-demo.c > > It doesn't do hit-detection though, since librsvg doesn't provide any > way to do that. Thanks, I integrated it in GCompris and it works fine. for the hit-detection, I just need a simple bounding detection, is this possible ? -- Bruno Coudoin http://gcompris.net Free educational software for kids http://toulibre.org Logiciel Libre à Toulouse |
From: Damon C. <da...@ka...> - 2007-10-17 10:15:53
|
On Tue, 2007-10-16 at 00:48 +0200, Bruno Coudoin wrote: > Le lundi 15 octobre 2007 à 10:30 +0100, Damon Chaplin a écrit : > > On Sat, 2007-10-13 at 22:30 +0200, Bruno Coudoin wrote: > > > I am currently trying to port GCompris to goocanvas. We were using the > > > venerable gnomecanvas and since your API is close it make sense to use > > > goocanvas and get a brain modern graphical backend from cairo. > > > > > > We have a specific requirement. We use SVG for our images and we use the > > > scaling feature of the canvas. But since goocanvas-image work at pixbuf > > > level (like gnomecanvas-pixbuf), once our svg is loaded, it is always > > > rescaled pixel based with quality lost. > > > > > > Have you identified this need on your side, how would you do this with > > > goocanvas? > > > > Creating an SVG item would probably be best. > > > > I wrote a simple SVG item a while back, which I've attached. > > > > Compile the demo with: > > gcc `pkg-config --cflags --libs goocanvas librsvg-2.0` simple-demo.c > > > > It doesn't do hit-detection though, since librsvg doesn't provide any > > way to do that. > > Thanks, I integrated it in GCompris and it works fine. for the > hit-detection, I just need a simple bounding detection, is this > possible ? I would think so. If you just want to use the bounding rect of the item I think you can just return TRUE in goo_svg_item_is_item_at(). Damon |
From: Bruno C. <bru...@fr...> - 2008-11-16 23:24:39
|
Le lundi 15 octobre 2007 à 10:30 +0100, Damon Chaplin a écrit : > On Sat, 2007-10-13 at 22:30 +0200, Bruno Coudoin wrote: > > I am currently trying to port GCompris to goocanvas. We were using the > > venerable gnomecanvas and since your API is close it make sense to use > > goocanvas and get a brain modern graphical backend from cairo. > > > > We have a specific requirement. We use SVG for our images and we use the > > scaling feature of the canvas. But since goocanvas-image work at pixbuf > > level (like gnomecanvas-pixbuf), once our svg is loaded, it is always > > rescaled pixel based with quality lost. > > > > Have you identified this need on your side, how would you do this with > > goocanvas? > > Creating an SVG item would probably be best. > > I wrote a simple SVG item a while back, which I've attached. > > Compile the demo with: > gcc `pkg-config --cflags --libs goocanvas librsvg-2.0` simple-demo.c > > It doesn't do hit-detection though, since librsvg doesn't provide any > way to do that. On this topic I made some improvements to your librsvg based goocanvas item. - Improved drastically the performance by making a cache copy of the svg source on an internal cairo surface. - I also added the ability to display only a given svg-id. An svg id can be a single svg element, a group or a layer. This make it possible and easy to load a single svg image in your program and create multiple goocanvas based on item's id. - Added a bounding detection so that an svg layer having a small object in it will get hit detection only at its bounds. - Added an option to disable the hit detection so that a foreground layer won't take hits when it is only there to decorate the scene. This code is in the development branch of GCompris: svn co http://svn.gnome.org/svn/gcompris/branches/gcomprixogoo The code is in src/goocanvas/src/goocanvassvg.c The python bindings is in src/boards With this, I can now avoid having to split scenes from the graphic artists in small files. I can have a single .svgz source and manipulate the items from there. Feel free to reuse it if you need. -- Bruno Coudoin http://gcompris.net Free educational software for kids http://toulibre.org Logiciel Libre à Toulouse |
From: Gustavo J. A. M. C. <gj...@in...> - 2008-11-17 11:44:36
|
On Mon, 2008-11-17 at 00:24 +0100, Bruno Coudoin wrote: > Le lundi 15 octobre 2007 à 10:30 +0100, Damon Chaplin a écrit : > > On Sat, 2007-10-13 at 22:30 +0200, Bruno Coudoin wrote: > > > I am currently trying to port GCompris to goocanvas. We were using the > > > venerable gnomecanvas and since your API is close it make sense to use > > > goocanvas and get a brain modern graphical backend from cairo. > > > > > > We have a specific requirement. We use SVG for our images and we use the > > > scaling feature of the canvas. But since goocanvas-image work at pixbuf > > > level (like gnomecanvas-pixbuf), once our svg is loaded, it is always > > > rescaled pixel based with quality lost. > > > > > > Have you identified this need on your side, how would you do this with > > > goocanvas? > > > > Creating an SVG item would probably be best. > > > > I wrote a simple SVG item a while back, which I've attached. > > > > Compile the demo with: > > gcc `pkg-config --cflags --libs goocanvas librsvg-2.0` simple-demo.c > > > > It doesn't do hit-detection though, since librsvg doesn't provide any > > way to do that. > > On this topic I made some improvements to your librsvg based goocanvas > item. > > - Improved drastically the performance by making a cache copy of the svg > source on an internal cairo surface. Interesting effort, and I don't mean to discourage you but: 1. You make a surface with the pixel dimensions from the suggested SVG width/height, when you paint the surface it could mean cairo has to scale the painted surface in real time in case non-default zoom level is in effect => slow; 2. If the canvas is zoomed by a large factor, you will see poor image quality, because the SVG resolution could be inferior to the display resolution while zoomed; 3. Printing or exporting to PDF a canvas containing such SVG item will lose all the vector qualities of SVG. All the printer will see will be a (possibly low quality) raster image, and the PDF file will be much bigger than needed. Caching is an interesting idea but it is difficult to get right. -- Gustavo J. A. M. Carneiro <gj...@in...> <gu...@us...> "The universe is always one step beyond logic" -- Frank Herbert |
From: Bruno C. <bru...@fr...> - 2008-11-17 22:55:31
|
Le lundi 17 novembre 2008 à 11:32 +0000, Gustavo J. A. M. Carneiro a écrit : > Interesting effort, and I don't mean to discourage you but: > > 1. You make a surface with the pixel dimensions from the suggested SVG > width/height, when you paint the surface it could mean cairo has to > scale the painted surface in real time in case non-default zoom level is > in effect => slow; > > 2. If the canvas is zoomed by a large factor, you will see poor image > quality, because the SVG resolution could be inferior to the display > resolution while zoomed; Yes, I did not thought about that. It's true that I loose the quality advantage of SVG in this case. On the other hand, it is way too slow to render the svg at each redraw. In my test, rendering directly the svg each time does almost work on a simple svg but it is unusable on a complex one. Also I have to take care that schools tend to have old hardware. So what can be done ? It would be ok for me to loose quality if the window size is changed manually. It would be acceptable if the svg rendering was done at the current zoom level of my application. In most case GCompris is run full screen and users don't tend to change its size. Basing my work on SVG, I no more use xvidmode to change the resolution and set the window at the native resolution. It is a must to render the SVG properly in this case. > 3. Printing or exporting to PDF a canvas containing such SVG item will > lose all the vector qualities of SVG. All the printer will see will be > a (possibly low quality) raster image, and the PDF file will be much > bigger than needed. This would be fun but is a low priority for me now. > Caching is an interesting idea but it is difficult to get right. If I don't do this, I have to stick to the way I was working before, taking svg from artist, cutting them, export to png, load each one and place them. In this case I had a more complex code and management to do and had no SVG scaling. What are the options there. How to benefit from svg now in an application using goocanvas ? -- Bruno Coudoin http://gcompris.net Free educational software for kids http://toulibre.org Logiciel Libre à Toulouse |
From: Bruno C. <bru...@fr...> - 2008-12-01 23:02:37
|
Le lundi 17 novembre 2008 à 23:55 +0100, Bruno Coudoin a écrit : > Le lundi 17 novembre 2008 à 11:32 +0000, Gustavo J. A. M. Carneiro a > écrit : > > Interesting effort, and I don't mean to discourage you but: > > > > 1. You make a surface with the pixel dimensions from the suggested SVG > > width/height, when you paint the surface it could mean cairo has to > > scale the painted surface in real time in case non-default zoom level is > > in effect => slow; > > > > 2. If the canvas is zoomed by a large factor, you will see poor image > > quality, because the SVG resolution could be inferior to the display > > resolution while zoomed; > I am still struggling on that. I don't see how I can implement a caching at the goocanvas svg item level and still rendering a full resolution svg. I mean that it would be ok for me to re-render the svg source in my cache at a full resolution. But it doesn't work since when my cache is applied on the underlying surface, it passes through the zoom factor of it (our goocanvas main scale). I am not sure I am clear but I am sad not to have a solution for this. I don't expect perfection but more or less looking for a good compromise between quality and performance (rendering the SVG all the time is way too slow with animations). I am sad because without this feature it means that even if I have SVG images in GCompris they won't be rendered properly in full screen. So moving to SVG means a slower GCompris especially on low end system but no better graphism on high end one. -- Bruno Coudoin http://gcompris.net Free educational software for kids http://toulibre.org Logiciel Libre à Toulouse http://april.org Promouvoir et défendre le Logiciel Libre |
From: Gustavo J. A. M. C. <gj...@in...> - 2008-12-02 15:11:01
|
On Tue, 2008-12-02 at 00:02 +0100, Bruno Coudoin wrote: > Le lundi 17 novembre 2008 à 23:55 +0100, Bruno Coudoin a écrit : > > Le lundi 17 novembre 2008 à 11:32 +0000, Gustavo J. A. M. Carneiro a > > écrit : > > > Interesting effort, and I don't mean to discourage you but: > > > > > > 1. You make a surface with the pixel dimensions from the suggested SVG > > > width/height, when you paint the surface it could mean cairo has to > > > scale the painted surface in real time in case non-default zoom level is > > > in effect => slow; > > > > > > 2. If the canvas is zoomed by a large factor, you will see poor image > > > quality, because the SVG resolution could be inferior to the display > > > resolution while zoomed; > > > > I am still struggling on that. I don't see how I can implement a caching > at the goocanvas svg item level and still rendering a full resolution > svg. I mean that it would be ok for me to re-render the svg source in my > cache at a full resolution. But it doesn't work since when my cache is > applied on the underlying surface, it passes through the zoom factor of > it (our goocanvas main scale). > > I am not sure I am clear but I am sad not to have a solution for this. I > don't expect perfection but more or less looking for a good compromise > between quality and performance (rendering the SVG all the time is way > too slow with animations). > > I am sad because without this feature it means that even if I have SVG > images in GCompris they won't be rendered properly in full screen. So > moving to SVG means a slower GCompris especially on low end system but > no better graphism on high end one. Well, I am sad too because of criticizing your work and not helping to fix the problems I detected. Alas, no time for everything in my life :( Anyway, I think I would be extremely happy with a SVG item in goocanvas that: 1- Will vector-draw by default every time; 2- Has an option for enabling caching via pre-rendered surface, even if in some arbitrary fixed resolution; 3- Is able to detect when printing is being done on the canvas, somehow, and vector-draws for printing regardless of option 2. I find that vector drawing for the exported print files (SVG, PDF, or EPS export) is extremely important. For the screen, doing quality-vs-speed tradeoffs is OK. Now, I think maybe Damon can help us out with 3. How would a canvas item detect it is being "printed" rather than drawn on screen? Maybe we need a new API for that? Regarding perfect rendering, well, I think it would require introspection of the full CTM applied to a canvas item, extract the final on-screen size, temporarily reverse the CTM and draw the image surface directly at the correct size. It is extremely tricky to get right and only works if no rotation/shearing effects are enabled in the CTM of the canvas item. So, don't worry about this, it is really not worth pursuing. -- Gustavo J. A. M. Carneiro <gj...@in...> <gu...@us...> "The universe is always one step beyond logic" -- Frank Herbert |
From: Damon C. <da...@ka...> - 2008-12-03 10:30:11
|
On Tue, 2008-12-02 at 15:01 +0000, Gustavo J. A. M. Carneiro wrote: > Anyway, I think I would be extremely happy with a SVG item in goocanvas > that: We'd need to depend on librsvg though, which might not suit everyone. > 1- Will vector-draw by default every time; > 2- Has an option for enabling caching via pre-rendered surface, even > if in some arbitrary fixed resolution; > 3- Is able to detect when printing is being done on the canvas, > somehow, and vector-draws for printing regardless of option 2. > > I find that vector drawing for the exported print files (SVG, PDF, or > EPS export) is extremely important. For the screen, doing > quality-vs-speed tradeoffs is OK. > > Now, I think maybe Damon can help us out with 3. How would a canvas > item detect it is being "printed" rather than drawn on screen? Maybe we > need a new API for that? Yes, a new function would probably be needed. But that is pretty simple. > Regarding perfect rendering, well, I think it would require > introspection of the full CTM applied to a canvas item, extract the > final on-screen size, temporarily reverse the CTM and draw the image > surface directly at the correct size. It is extremely tricky to get > right and only works if no rotation/shearing effects are enabled in the > CTM of the canvas item. So, don't worry about this, it is really not > worth pursuing. I think there are 2 ways to use a cache: 1) Cache an item at a certain size and use that cache whenever the item needs to be drawn, at whatever scale/rotation/skew. 2) Cache an item at its current scale/rotation, and whenever its transformation changes the cache is recreated. (1) is faster but (2) is more accurate. (the new Qt QGraphicsView canvas supports both: http://doc.trolltech.com/4.4/qgraphicsitem.html#CacheMode-enum ) It would be good to have this in GooCanvas, though it is a bit of work. It's probably best to keep using your own custom cache code for now, if that does everything you need. Damon |
From: Bruno C. <bru...@fr...> - 2008-12-02 22:43:12
|
Le mardi 02 décembre 2008 à 15:01 +0000, Gustavo J. A. M. Carneiro a écrit : > Regarding perfect rendering, well, I think it would require > introspection of the full CTM applied to a canvas item, extract the > final on-screen size, temporarily reverse the CTM and draw the image > surface directly at the correct size. It is extremely tricky to get > right and only works if no rotation/shearing effects are enabled in > the CTM of the canvas item. So, don't worry about this, it is really > not worth pursuing. > OK, I am somewhat happy that I understood the issue. In case we would like to pursue this idea, I did not found a way to draw on a cairo surface bypassing the CTM. Is this issue specific to goocanvas ? how are other users solving it. Perhaps we could ask cairo people about our problem, maybe they have or plan a solution ? -- Bruno Coudoin http://gcompris.net Free educational software for kids http://toulibre.org Logiciel Libre à Toulouse http://april.org Promouvoir et défendre le Logiciel Libre |
From: Damon C. <da...@ka...> - 2008-12-03 10:10:36
|
On Tue, 2008-12-02 at 23:43 +0100, Bruno Coudoin wrote: > Le mardi 02 décembre 2008 à 15:01 +0000, Gustavo J. A. M. Carneiro a > écrit : > > Regarding perfect rendering, well, I think it would require > > introspection of the full CTM applied to a canvas item, extract the > > final on-screen size, temporarily reverse the CTM and draw the image > > surface directly at the correct size. It is extremely tricky to get > > right and only works if no rotation/shearing effects are enabled in > > the CTM of the canvas item. So, don't worry about this, it is really > > not worth pursuing. > > > OK, I am somewhat happy that I understood the issue. In case we would > like to pursue this idea, I did not found a way to draw on a cairo > surface bypassing the CTM. Is this issue specific to goocanvas ? how are > other users solving it. Perhaps we could ask cairo people about our > problem, maybe they have or plan a solution ? You can temporarily set the CTM to the identity matrix with cairo_identity_matrix (cr); You can do a cairo_save()/cairo_restore() around it if you need the old CTM back afterwards. Damon |