Squib of the day: SVG theme support

Brutality against mosquitoes.GNOME bug 107012 brings up the perennial question of SVG support in themes, otherwise known as Vectacity. We’ve already covered this in a few places, but I think it may be worth mentioning here the two main reasons SVG-based themes is a good thing (there may be any number of other reasons they’re a bad thing, as well):

  • SVG is now a clear standard for vector graphics.  So theme artists will be able to reuse their existing knowledge about SVG when coming to design Metacity themes.
  • It means we can remove large amounts of code from Metacity and use whatever SVG library we end up depending on instead.  (There is a heavy presumption that this library will be GNOME’s own librsvg.)  Having less code around is generally a positive thing.

However, stretching SVG to meet our needs, or indeed stretching librsvg to meet our needs, rather negates the second benefit: it’s possible that including CSS will let us do what we need, but it’s also possible that librsvg is not clever enough to let this happen without so much coaxing on our side that we may as well have written an entire SVG library of our own, which is something we’d like to avoid.

If Vectacity ever becomes a reality, it certainly needs to be possible to convert a v1 or v2 theme to Vectacity automatically.  This is partly for the theme artists’ benefit, but also because it means if a Vectacity-enabled Metacity finds itself having to load a v1 or v2 theme, it can do the conversion by spawning a separate program rather than having to keep the legacy code for reading v1 and v2 themes lying around, which again negates the second benefit.

Forthcoming versions of SVG are specifically considering use by window managers, but we may have to wait a while for them to get into a usable format. It may be best to WONTFIX this one, at least until v4.  On the other hand, the two benefits given are indeed important benefits, and I’d like to see it happen sooner.

Photo © freebird (bobinson|ബോബിന്‍സണ്), cc-by-nc-sa.

Squib of the day: Special frame style for warning dialogues

GNOME bug 102548 suggests that warning dialogues should have a special frame style, and it’s suggested that this could look like safety tape wrapped around the edge.

This is not unlike the special frame style suggested here for root windows.  However, while there’s already a way for the window manager to tell whether a window belongs to the superuser, there’s currently no way to tell whether a window is a warning, so this would need a change made to the EWMH and then need all the toolkits fixing to use it.  It’s thus rather nontrivial, although it may still be worth it if it helps users.

Because this requires a change to the theme format, it must be committed first on a branch.

I am seriously entertaining the idea of doing away with the window and frame_style_set tags in v3 of the format, and just using tags on frame styles such as maximized, shaded, focused, unfocused, root, warning, modal, and so on, with some well-defined and intuitive rule about how to break ties:

<frame_style geometry="foo" tags="border focused maximized">
<piece position="title">   ...

Photo © Robin Gallagher, cc-by.

Squib of the day: line weight

Empty Victoria Line Tube TrainAt present all lines are drawn at the same thickness.  However, some people such as partially-sighted users require particularly thick lines.  GNOME bug 86040 suggests that the line format be extended to give the width as a fraction of the current icon height.

Since this is a change to the format, it must appear first on a branch. This bug actually predates v2, but wasn’t included in that version because it wasn’t marked as blocking the v2 tracker bug.

If this would still be useful to anyone, it could certainly still go into v3 of the theme format.

This bug is perhaps the first place where the use of SVG was suggested as a workaround for having to add new features.  Elsewhere, someone also suggests a novel idea of allowing themes to ship TrueType fonts which contain unusual glyphs, in order to have access to another well-defined vector graphics language.  Of course, this would be subsumed if we decided to use SVG.

Photo © Callistobreeze, cc-by-nc-sa.

Policy about theme versions

a day's workMetacity has a policy about enhancements which require changes to the theme format.  Metacity has to be both backwards and forward compatible.  In other words, it’s not enough that a later version of Metacity can run with themes intended for an earlier version.  Earlier versions must also be able to run with themes intended for a later version.

In order to accomplish this goal, themes are kept in a file named metacity-theme-n.xml, where n is the number of the version of the theme format.  A theme which supports a version should also have files for all the preceding versions, and Metacity will read only the highest version found which it can understand and leave the rest alone.

This works.  However, if there were hundreds of theme versions, it would become unwieldy.  So we save up enhancements and commit a bunch of them all together.  The only time this has happened so far was in October 2006, when v2 was introduced.  (Not many people are using v2, even over three years later, and even though users evidently want the features it brings.  This may be because theme artists aren’t sure how to create them.  One of the advantages of a theme editor would be that it would be able to take care of creating valid intermediate versions for you.)

Some enhancements still being suggested will involve changes to the theme format.  For example, Screwtape has suggested a special window state representing windows which are running as root, so that they can be drawn using a different colour or something.  Enhancements such as these will all have to be made on a branch and merged all together at some time in the medium future, perhaps next year.  I have made a category to group posts about such enhancement requests into.

One of the big questions about v3 is whether it should be SVG-based– the so-called Vectacity format.  This will quite possibly win us very little for the extra effort that will be required to mould SVG into a format which can adequately represent window decorations, so Vectacity may not happen in version 3, or at all.

Photo © Tim McFarlane, cc-by-nc-nd.

Quick mention: a theme editor

Someone is working on a Metacity theme editor called Metacity Themer. It appears to take rather a different approach from Opacity; it’ll be interesting to see how this turns out. I’m not sure whether I should abandon Opacity; I wasn’t working on it anyway much (though I had thought about it quite a bit) and I don’t really have time to finish a theme editor anyway with the amount of work that Metacity needs, so Opacity would have been a while off prime time anyway. Let us know what you think of Metacity Themer.

More on themes, and on why Human’s slow

On The RocksFour points of note in theming today.  Your thoughts on these, gentle reader, are appreciated.

  1. Screwtape has been working on a Metacity theme to look like Mac OS Classic.  The resulting list of tips and tricks for writing Metacity themes ought to be required reading for all themers.  Screwtape, would you mind if we linked to it from the sidebar of this blog?
  2. I have added a small amount of optimisation to line drawing:  if a line is horizontal or vertical, the second x or y coordinate is not stored, and if a line’s beginning and ending coordinates are identical, neither the second x nor the second y coordinate are stored, and the line is drawn as a point.  This seems to have sped things up a little.  (Note, by the way, that speeding up Metacity themes will also help Compiz along too.)
  3. As a followup to my previous post about Human, I have checked to see what part of drawing the gradient is so slow.  The results are clear: preparing the bitmap is fast, and painting it is slow.  Almost the whole wait is  taken up with the call to gdk_draw_pixbuf()The docs contain a stern warning:

    On older X servers, rendering pixbufs with an alpha channel involves round trips to the X server, and may be somewhat slow.

    Since all the gradients have an alpha channel, I am led to wonder whether the delay is caused by this problem, and what possible workarounds there might be. (Update: But removing the alpha channel doesn’t make much of a difference, so maybe it’s just that painting this large an area is inherently slow.  I wonder whether we can create a 1xn pixel tile instead and tile it along the length of the area, and whether that would be faster.)

  4. The RPN version of the expression parser is rather faster than the existing parser, and (I believe) simpler to understand, but expression parsing is not a major timesink at present anyway, so it saves at most a few hundred microseconds per frame draw.  I am wondering whether merging it is worth the chance that it might misinterpret some theme somewhere.  Perhaps now immediately after a branch is the best time to consider it, though.

Photo © Auntie K, cc-by.

So, why is Human slow?

A Man And A WomanI mentioned a while back that Human is the slowest of all common themes, taking 6ms to draw the average frame.  It occurred to me to wonder why this might be, of course, so I took the opportunity to instrument it.  Here are the results.  The height of the diagram spans six milliseconds.  You will note firstly that the theme carries out a large number of very simple operations like lines and rectangles, which are very fast, and next that there are four long pauses which I have numbered in red:

  1. Drawing a gradient.  This is the first gradient in title_background, covering the entire width of the titlebar and half its height. There are three other gradient operations, and none of them take that long; this could be some caching mechanism in GDK but is more likely to be because at least one of them is only a single pixel high.  The other two are a bit of a mystery; the output says they should be part of piece 11, bottom_edge, but that isn’t used in Human.
  2. Drawing a tint.  Again, it’s the first one in corners_hilight_shaded, so maybe some caching effect, but this is also the only tint which is 1×2 pixels high instead of just 1×1; there is one tint which is 2×1, and this is visible taking longer slightly below the number 2.
  3. Drawing the title text.  This happens four times, and two are very fast and one is very slow.  I can’t account for this.
  4. Drawing the title text again; see above.

I think this shows that gradients and tints need to be faster.

(Update follows >>>)

Photo © just.Luc, cc-by-nc-sa.

More failed experiments in theming

Underwater Feet

  1. Not very surprisingly, replacing horizontal and vertical lines with rectangles doesn’t speed things up detectably.  (There once were systems where this made a difference, but I think GTK is probably clever enough that this doesn’t matter.)
  2. More interestingly, plotting the title to a monochrome bitmap, and then setting that bitmap as a stipple and drawing a filled rectangle instead of drawing the title also does not speed things up detectably.  I thought avoiding a Pango hit for some common themes which plot the title more than once might make a difference.  (Human plots the title of the active window four times, for example, and is the slowest common theme.)

(I am working on things other than this sort of thing, it’s just that this is producing results which are interesting to talk about and other bugs and problems aren’t so much.)

Photo © kagey_b, cc-by-nc-nd.

Version 3 themes

Mosquito biteSeveral ideas have come up recently about extensions to the theme format.  Here are some rather disjointed notes about the problems we face here.  I apologise for their fragmentary nature.

According to policy, incompatible changes must be made all at once with a new version of the theme format, to preserve backward compatibility.  (This has only happened once so far, so the only versions of the theme format to exist are v1 and v2.)

One feature I’d like in a new theme format is to have everything in the same file.  At present we have almost everything together except the pixmaps.  I’d like to put them in the same file; rather than using base64, we should use xpm for this, which gdk supports out of the box.  That way, you can have just one single file to download.  Also for ease of sharing, it should have the theme name in the filename this time, rather than the directory name.

As to the format of the new files, there’s a strong suggestion around that they should be SVG.  Such a format could either be designed from the ground up or be an evolution of the current system.  However, I believe that what is needed is a clear upgrade path, and so we need an evolutionary approach.  If we can build a conversion utility to convert v1 and v2 themes into v3 themes, then not only will people be able to work with all their existing themes immediately, but we can support only v3 in Metacity itself and call the conversion utility when a theme is encountered which only supports v1 or v2.

One problem with both the evolutionary and revolutionary approaches is that there are ideas in Metacity themes which cannot be expressed in SVG: for example, some themes place a graphic to the left or right of a piece of text of unknown length.  I have spoken informally to a member of the SVG Working Group who has confirmed that this is not possible in current pure SVG designs.  However, it is possible with scripting.  So we can consider a simple refinement of our existing coordinate-expression system as a form of SVG scripting system, where we set the dimensions and positions of elements with respect to other elements.

Something like this could be achieved using librsvg by building a text buffer containing the XML with sufficient whitespace to the left of every decimal.  As our homegrown scripting language was parsed we’d build up a set of pairs of (char*, expression) and every time a frame was drawn we’d simply write the new value into the buffer.  It would obviously be simpler if we could modify the parsed form of the SVG inside librsvg, but I don’t believe it allows that.  More importantly, we need to be able to find the widths and heights of various elements, especially the title, in order to position other elements, and I don’t believe librsvg allows us to read its parsed form either.  (Do you know otherwise?)  If not, where can we go?

Of course we could possibly keep doing it in house as we do now, but use an SVG-like syntax instead.  Effectively we’d be writing our own SVG library.  This is not exactly a cause for rejoicing.

Photo © James Jordan, cc-by-nd.

Sorry for the silence

Banshees on the WindSorry for the silence of the past few days; I’ve been working on a possible fix to the theme rendering code, after the test suite told me that the part which calculates the value of expressions was a bit slow.  Currently it tokenises during theme load but parses every evaluation.  I thought that if I parsed it into some stack-based form on theme load, it might take slightly longer to load a theme, but everything would draw faster by just evaluating the stack-based version.  (I also took the opportunity to do all floating-point arithmetic using scaled integers, because I’m stuck in 1988.)

In practice, though, the results have been disappointing: it only seems to have saved a few microseconds here and there.  So it’s probably not worth the disruption of merging it, though it does also make the code 584 lines shorter, mainly through its use of a GScanner instead of tokenising in house.  I think it also makes the code a bit easier to read.  I’ve put the patch up in case anyone fancies suggesting how it can be sped up a bit further.

(One optimisation that the existing version does that the patch doesn’t do is evaluate constant expressions at theme load time– so if you have Fred+1 where Fred is a constant equal to 2, it will store just 3 and not bother doing the evaluation.  I’m not sure whether that would give much extra speed to the new code.)

Still, experiments are worth doing even if they fail!

Photo © Dead Air, cc-by-nc-sa.

Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported.