tl;dr has anyone tried to use libcss to add CSS support to libsvgtiny?

I have a small project that renders GTK icons using libsvgtiny. Its
main missing feature is that it can't handle GTK's "symbolic" SVGs,
which are basically just regular SVGs wrapped in an include with a
<style> element at the top. The styles themselves are trivial,
consisting of only a few !important color changes.

That got me wondering about CSS support in libsvgtiny. I could
probably hack in special cases for the exact <style> elements I need
(they're hard-coded in GTK), but it would be a lot more elegant -- and
fix a bunch of existing rendering bugs -- if CSS were supported
properly. To that end, I wrote a very ugly proof-of-concept that
handles the SVG fill-opacity and stroke-opacity properties:

1. First, I chose to implement the fill-opacity and stroke-opacity
   properties because they're easy. They have the same form as the
   usual CSS "opacity" property. To implement them, I basically
   git grep'd for "opacity" in libcss and copy/pasted everything to
   fill-opacity and stroke-opacity. It was tedious, but otherwise
   not difficult because opacity is easy to parse.

   Handling the more complicated properties or factoring out the
   shared implementations of opacity, fill-opacity, and stroke-opacity
   would likely require someone who knows libcss better.

   I dumped the new properties into the default level, but this raises
   a question: should libcss use a different CSS level for SVG?

2. In libsvgtiny, I added a libcss context to the parser state, and
   then taught the SVG parser to parse a <style> element into a sheet,
   and append the sheet to said context. This part is just boilerplate.
   The build system needs to be updated to build/link against libcss.

3. I copied the css_select_handler and css_unit_ctx from netsurf into
   svgtiny.c. Thankfully, I didn't have to think about the unit
   conversions at all because opacity is a float. The select handler
   callbacks were tedious, but most of them can be copied from netsurf
   with minimal changes, fudging interned string names and replacing
   html-only function calls. I wound up copying the user data handler
   too. Who knows if any of this stuff works, but it hasn't crashed.

   Ultimately, since netsurf uses libsvgtiny, copy-pasting the select
   handler wouldn't be a great solution. I think it would make sense
   to factor out the libdom/libcss integration into something like a
   libdom-css that provides a generic css_select_handler
   implementation.

4. I added fill_opacity and stroke_opacity members to the SVG parser
   context.

5. I taught svgtiny_parse_paint_attributes() how to find the computed
   fill- and stroke-opacities. We're already parsing the inline style
   so that part is pretty easy. Once we have them, they can be set in
   the context. Disclaimer: I skipped composition with the parent
   style to save time, but that could probably be copied from netsurf
   too.

   There's a problem here: the SVG parser makes one pass through the
   file, using a big struct to keep track of the current color, stroke
   width, et cetera, as we create and append shapes to the resulting
   abstract representation. If a <style> element appears at the end of
   the SVG, its rules won't affect the shapes created earlier. (This
   isn't a huge problem, it's just worth noting that I half-assed this
   part to get the thing working.)

6. You can now render each shape with the fill_opacity and
   stroke_opacity from the context.


Now I can say I wasn't lying when I thought "I could probably do
that." Of course I skipped over the boring/hard parts, but when all is
said and done, the framework can be put in place without too much
extra code.

Has anyone tried this before? Does it make sense for libsvgtiny?
_______________________________________________
netsurf-dev mailing list -- netsurf-dev@netsurf-browser.org
To unsubscribe send an email to netsurf-dev-le...@netsurf-browser.org

Reply via email to