SVG:Icons
A summary of the information obtained from bug 1054016 and its "See also" bugs.
Contents
Advantages of SVG
We would like to use SVG for icons in the UI. The reasons for this include:
- Icons can be styled with different colors, especially on customized Linux distros where our icons may be hard to see or clash.
- Avoid multiple versions of icons for various platforms, various platform themes and different scaling factors, which is difficult to maintain.
- HiDPI display support without needing many different icon sets (apparently bit twiddling is not necessary).
- Improve themeability.
- Make it easier for add-on authors to supply icons that work well everywhere.
See shorlander's SVG Asset Process doc for more.
Requirements for Firefox Desktop
- Are filters necessary to switch to SVG icons? Apparently to color icons, and possibly for drop shadows in future.
- How much of a performance regression is acceptable, if any?
Performance tips
Bundle multiple icons together in a single SVG
SVG has some relatively fixed overhead regardless of image size or complexity, and for a simple SVG image rendered at small sizes this overhead can make it noticeably slower than an equivalent raster image. Specifically, creating a document object (into which the SVG will be parsed), creating the document's ancillary data structures and including UA style sheets is fairly fixed and non-trivial overhead. If the SVG is simple and renders at a small size this fixed overhead can dwarf the rest of the work Mozilla has to do to parse and render the SVG image. (Bug 999931 has more analysis of this issue.) To offset that up front expense it is best to bundle multiple icons into a single SVG document (sometimes loosely called an "SVG sprite document") and use -moz-image-region/-moz-image-rect when referencing the icons. That way the cost of the document creation etc. is largely shared between multiple icons.
Don't bundle too many icons together
While it can be good to bundle icons into a sprite document to share the cost of document creation across multiple icons, note that in Mozilla's implementation as it currently stands referencing just one icon in the sprite document and using -moz-image-rect/-moz-image-region requires the entire document (all the icons it contains) to render. Therefore the more icons that are in the sprite document, the longer it takes to show the first icon referenced from that document. This can be particularly bad, say, if some of the icons is shown during startup but most of them are not. We would then pay the cost during startup of rendering even the icons that are not shown during startup, regressing our startup performance tests (and hurting user experience!). So, in short, while it is good to share document creation overhead between as many icons as possible, consider this issue too and what trade offs should be made.
Avoid filter effects if possible
Raster images have the advantage that the work to apply filters and other expensive effects is done when the image is created, not when it is shown. This is not the case for SVG. Effects in SVG must be applied when the SVG is rendered, and this can mean that SVG can take longer to render than an equivalent raster image. Bear this potential for performance regressions in mind if switching from a raster format to SVG. See for example bug 1054016 comment 16 where the vast majority of the performance regression was due to filters. In particular try to avoid complex or expensive filters.
Group filtered icons under a single filtered <g>
Grouping icons that have the same filter applied under a single <g> with the filter applied to that makes sure the filter is applied only once.
See roc's other suggestions too.
Sprite sheets
As suggested above, performance can be improved by embedding multiple icons into a single sprite sheet. There are different methods that can be used to reference the icons in a sprite sheet though, and some performance gotchas.
Hash references with :not(:target)
One way to create a sprite sheet is to stack all the icons in the sheet on top of each other and then use CSS to only show the icon targeted by the URL. In Mozilla's current implementation this approach has serious performance drawbacks. See [ ]. However, there is the create-svg-icon-set-file.py tool to help in creating a sprite sheet this way.
Hash references without :not(:target)
In principal the SVG specification allows elements in an SVG image that are targeted by the URL to be "zoomed in" to that element. Mozilla does not currently support this, but if it did it could be more performant than the :not(:target) approach.
-moz-image-region/-moz-image-rect
The most performant way to implement a sprite sheet in Mozilla is currently to reference the sprite sheet image and use -moz-image-region/-moz-image-rect to display only the area that is occupied by the desired icon.
Performance impact
- ts_paint regressed on original test
- Experiment #1 and #2 regress ts_paint and sessionrestore, and #2 regresses tpaint, on linux64.
To test
From bug 1054016 comment 10:
- Test if the patch from bug 1064875 helps filter performance on Linux.
- Test if color-interpolation-filters="sRGB" helps filter performance.
- Test using "filter: drop-shadow(0 1px rgba(0,0,0,.25));" instead of SVG filters.
To-do
- Get mstange to look at roc's suggestion to speed up filters ("There are some optimizations we could do inside Gecko to speed this up, without an enormous amount of work").
Fallback strategies
In case SVG performance isn't good enough. See bug 1054016 comment 43-49, comment 64, comment 69 and comment 73.