Overhaul attributes parsing
Currently we process SVG element attributes in a very convoluted/inefficient way:
-
rsvg_start_element()
gets called from libxml2, with a key/value list of attributes. - We turn that list into a hash table, the
RsvgPropertyBag
. - For most elements,
rsvg_start_element()
callsrsvg_standard_element_start()
, which callsnode_set_atts()
, which callsrsvg_node_set_atts()
. This last one is the entry point to theNode::set_atts()
method.
- Each node implementation looks in the property bag (one hash table lookup) for each attribute it wants. This isn't too bad, but it means that we lookup for every possible property, even for ones that the elements don't have in the SVG data.
-
node_set_atts()
then callsrsvg_parse_style_attrs()
, which callsrsvg_parse_style_pairs()
.
- which does a lookup for each attribute it knows, via
rsvg_lookup_parse_style_pair()
... - which calls
rsvg_parse_style_pair()
if the lookup succeeds... - which then has a big chain of
if strcmp(key, "foo") {} else if strcmp (key, "bar") {} ...
The problematic things are the lookups for all the attributes in the ::set_atts()
implementations, and the big chain of if strcmp()
in the styling code.
Perfect hashing
We could start by adding a perfect hash function for attribute names. Take an attribute name and map it to an enum.
#[repr(C)]
enum Attribute {
BaselineShift,
ClipPath,
ClipRule,
...
}
fn attribute(name: &str) -> Option<Attribute>;
Later to be mapped to this for the C code:
typedef enum {
BASELINE_SHIFT,
CLIP_PATH,
CLIP_RULE,
...
UNKNOWN
} Attribute;
Note that while Rust uses an Option<Attribute>
for the lookup, to handle unknown attribute names, the C code tacks an extra UNKNOWN
value to the enum. This is just an idea and can be done in other ways.
Fixing the styles code
The big chain of if strcmp()
can be turned into a switch
statement. The compiler can optimize that to hell.
rsvg_parse_style_pairs()
should basically go away, and be replaced with iteration over the atts
.
Removing the property bag
Have ::set_atts()
implementations iterate over the atts
and use the PHF values instead of doing lookups.
Maybe provide a Rust wrapper over libxml2's array of key/value strings, with a nice iterator?