Wacom diagram renders incorrectly (librsvg regression)
CC @carlosg
This is similar to librsvg#347 (closed) except that this time, one of the labels in the Wacom diagram gets rendered at (0, 0) instead of at its expected position. This is a recent regression in librsvg.
As a reminder to myself - this is how it works:
- Mutter gets the filename of libwacom's SVG diagram by calling
libwacom_get_layout_filename
. - In gnome-shell,
js/ui/padOsd.js
gets that filename, and looks for elements whose id is something like#LabelA
or#LeaderA
. Libwacom names them with letters like that. - That same source file does
get_position_sub()
/get_dimensions_sub()
on the RsvgHandle and uses their geometry to render widgets at the appropriate position. - Elements in the SVG are recolored by using a wrapper SVG with a
<style>
element. In librsvg's test suite, this is347-wrapper.svg
and347-bamboo-16fg-s-pt.svg
(a Wacom tablet model).
The toplevel <svg>
in libwacom's files has this:
style="color:#000000;stroke:#7f7f7f;fill:none;stroke-width:.25;font-size:8"
which gets inherited by all the children. Note how labels will get a stroke
and stroke-width
, but fill:none
.
The wrapper which gnome-shell uses has this:
-
data/theme/pad-osd.css
- static chunk of CSS - some more CSS generated at runtime in
PadDiagram._cssString()
, to highlight the active components.
Notably, pad-osd.css
has this:
.Label {
stroke: none !important;
stroke-width: .1 !important;
font-size: .1 !important;
fill: transparent !important;
}
So it overrides the style
from the toplevel <svg>
in the wrapped file, and gives labels stroke:none
and fill:transparent
. I think this is meant to say, "don't visibly render anything, but give me its position". I believe font-size: .1
is a remnant of a time when this kind of librsvg hack was being figured out, and the intention was to make the text so tiny as to make it invisible (maybe it didn't handle unstroked/unfilled text correctly? maybe to collapse any baseline+ascender to a single pixel? no idea).
Since librsvg 2.53.1, it renders all text as Cairo paths instead of Cairo glyphs, to hack around a bug in Pango as it can't render text correctly if it has different scale factors in the X and Y axes.
However, after debugging the Wacom files for a bit, I found this in librsvg. However, note that its wrapper file was as if gnome-shell's 315c8820 had not been applied yet:
- For a label with
font-size: .1; stroke: somecolor; fill: somecolor
, if the text span isB
(as per the second label), it computes incorrect stroke_extents; it says that the stroked path goes from (0, 0) to (something, something). - But if the text span is
A
(as per the first label), it computes stroke_extents correctly and they don't go to (0, 0).
I.e. the stroke extents from Cairo are incorrect depending on the actual text
In librsvg, I "fixed" this by removing the bit from the wrapper that gnome-shell's 315c8820 removed: now, labels just get the CSS as per the chunk above.
So, gnome-shell/librsvg should compute the extents correctly!
But if it is generating (0, 0) for a label, I don't know yet what is going on.
Can you please attach the full generated SVG that gnome-shell sends to librsvg? I may be missing something from just reading the code (I don't have a Wacom tablet to bring up the relevant display).
Shot in the dark: can you remove the line with font-size: .1 !important
from pad-osd.css
and see if that changes things? Label positions may shift since now they are using the font-size:8
from the libwacom files, but I want to see if that makes none of the labels incorrectly appear at (0, 0).
(... Given the way librsvg and text work in general, I think libwacom should not use <text>
labels that way. Instead it could have something like a square at the intended anchor point of the text, and then gnome-shell could query its unambiguous position (unchanged by the font or its size), and stick its own text there.)