[Nautilus-list] SVG Gorilla performance in nautilus ...



Hi Guys,

	I've been doing a little idle research on nautilus performance with the
svg theme in my spare time, and it turns out we have several
sub-optimalities in the svg rendering inside nautilus of both emblems
and icons.

	Primarily the problem is that the SVG view of the world has a somewhat
arbitrary width/height that we equate with pixels in librsvg.

	The code in libnautilus-private/nautilus-icon-factory.c has some
interesting features such as:

static CacheIcon *
scale_icon (CacheIcon *icon,
	    double scale_x,
	    double scale_y)

	auto-icon scaling for icons & emblems that are too large to start with,
thus it seems most svg elements are initially rendered far too large,
and then interpolated down at some considerable computational expense -
not least that we have to render far more gradient pixels that we might
otherwise need to.

	This of course is substantially hidden by the auto-scaling. For
example, while many emblems are around the right size needing minimal
scaling, some are pretty out of line:

Opened (570,570) at zoom
'/home/michael/.nautilus/themes/ScalableGorilla/emblem-nowrite.svg':
0x85bc3f0
Scaling icon to '47,47

	So we render the nowrite emblem at 570 pixels square and then
interpolate it down to 47x47 :-)

	Worse than the emblem issue is the more commonly rendered svg icons
themselves, for which I've lost the data, but it seems we render them
somewhat too large by a factor of ~4 - and worse, in scaling them we get
some nasty artifacts and chew RAM.

	So - clearly the solution is to scale them to the correct size as we
render them from svg[1], and win on rendering and scaling, so I added
this to librsvg:

Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/librsvg/ChangeLog,v
retrieving revision 1.75
diff -u -p -u -r1.75 ChangeLog
--- ChangeLog	2002/02/20 19:39:25	1.75
+++ ChangeLog	2002/02/23 21:17:38
@@ -1,3 +1,11 @@
+2002-02-21  Michael Meeks  <michael ximian com>
+
+	* rsvg.c (rsvg_size_callback): handle -1 width /
+	height in such a way as to preserve the aspect ratio.
+
+	* test-performance.c (main): time file_at_size, and
+	dump resulting pixbuf dimensions.
+
 2002-02-20  Michael Meeks  <michael ximian com>
 
 	* Makefile.am: add test-performance.c
Index: rsvg.c
===================================================================
RCS file: /cvs/gnome/librsvg/rsvg.c,v
retrieving revision 1.25
diff -u -p -u -r1.25 rsvg.c
--- rsvg.c	2002/02/20 19:39:25	1.25
+++ rsvg.c	2002/02/23 21:17:39
@@ -1629,7 +1629,8 @@ rsvg_size_callback (gint     *width,
 {
   struct RsvgSizeCallbackData *real_data = (struct RsvgSizeCallbackData
*)data;
 
-  if (real_data->zoom_set)
+  if (real_data->zoom_set ||
+      (real_data->width == -1 && real_data->height == -1))
     {
       (* width) = real_data->x_zoom * (* width);
       (* height) = real_data->y_zoom * (* height);
@@ -1637,9 +1638,15 @@ rsvg_size_callback (gint     *width,
   else
     {
       if (real_data->width != -1)
-	*width = real_data->width;
+        {
+          *height = (1.0 * *height / *width) * real_data->width;
+	  *width = real_data->width;
+	}
       if (real_data->height != -1)
-	*height = real_data->height;
+        {
+          *width = (1.0 * *width / *height) * real_data->height;
+	  *height = real_data->height;
+	}
     }
 }
 
	Allowing us to pass -1 for a height and getting a sensible (constant)
aspect ratio when we use rsvg_pixbuf_from_file_at_size.

	Then I added:

Index: nautilus-icon-factory.c
===================================================================
RCS file:
/cvs/gnome/nautilus/libnautilus-private/nautilus-icon-factory.c,v
retrieving revision 1.255
diff -u -p -u -r1.255 nautilus-icon-factory.c
--- nautilus-icon-factory.c	2002/02/21 19:26:46	1.255
+++ nautilus-icon-factory.c	2002/02/23 21:18:56
@@ -1396,7 +1396,12 @@ load_pixbuf_svg (const char *path, guint
 	}
 	zoom = actual_size_in_pixels / NAUTILUS_ICON_SIZE_STANDARD;
 	
-	return rsvg_pixbuf_from_file_at_zoom (path, zoom, zoom, NULL);
+	if (is_emblem)
+		return rsvg_pixbuf_from_file_at_zoom (path, zoom, zoom, NULL);
+	else {
+		fprintf (stderr, "'%s' not an emblem\n", path);
+		return rsvg_pixbuf_from_file_at_size (path, size_in_pixels * 2, -1,
NULL);
+	}
 }
 
 static gboolean

	To get the scaling right first time - so, this results in a fairly
substantial improvement, making really large svg icon rendering
relatively snappy - but there are several issues:

	* Not enough information is propagated to where we render the
	  svg, indeed we only have a 'size_in_pixels' parameter pushed
	  down the last several layers. It is really not clear what this
	  number is good for, with a factor of 2 multiplier it provides
	  something approximating what you might expect in layout terms,
	  otherwise you get a really odd layout effect in the icon view.

	* This doesn't fix the emblem rendering / scaling issues, which
	  perhaps are victims of the same size_in_pixels uncertainty I
	  suffer, but could do with the same sort of loving.

	* The in-icon text display information is synched to the old
	  version of what the rendered size should be, and worse, since
	  we effectively scale the icon for free here we need to be able
	  to scale the available text area as well, cf. the code in 
	  scale_icon that does that.

	So - the first 2 issues are fairly soluble I imagine, the 3rd issue is
a more painful. I imagine the best way to solve it to avoid scaling
issues would be to express the text region not in pixels but in some
normalized proportion of icon size.

	It would seem that we could keep compatibility with old text
information:

  <icon size="48" embedded_text_rectangle="38,0,130,110"/>

	by doing compatibility maths on load, and adding some tag there to flag
new data as being proportional - or have a single new tag for all icon
sizes that is proportional.

	Anyway - clearly this needs some design attention before I do anything,
so I thought I'd post my findings and beg input,

	Thoughts ?

		Michael.

[1] - ok so the other solution is to 'fix' the svg files themselves so
librsvg renders them to what nautilus thinks is an in-bounds
width/height at a given zoom - this is apparently not easy with the svg
tools.

-- 
 mmeeks gnu org  <><, Pseudo Engineer, itinerant idiot





[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]