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-leave@netsurf-browser.org
No comments:
Post a Comment