This is more natural since cr->path can be used as if it was a pointer.
This means, for example, if we move on to making it a pointer, most of
the code using it does not need any change. So we get some level of
encapsulation of implementation details, if you prefer the terminology :).
This means, we have to malloc only one buffer, not two. Worst case
is that one always draws curves, which fills the arg (point) buffer
six times faster than op buffer. But that's not a big deal since
each op takes 1 byte, while each point takes 8 bytes. So op space
is cheap to spare, so to speak (about 10% memory waste at worst).
We do this by including an initial op and arg buf in cairo_path_fixed_t,
so for small paths we don't have to alloc those buffers.
The way this is done is a bit unusual. Specifically, using an array of
length one instead of a normal member:
- cairo_path_op_buf_t *op_buf_head;
+ cairo_path_op_buf_t op_buf_head[1];
Has the advantage that read-only use of the buffers does not need any
change as arrays act like pointers syntactically. All manipulation code
however needs to be updates, which the patch supposed does. Still, there
seems to be bugs remaining as cairo-perf quits with a Bad X Request error
with this patch.
On some architectures, gcc will emit a memcpy for structure copies which will
produce a valgrind warning when the source and destination pointers are the
same. Workaround this issue by explicitly checking the source and destination
for inequality before doing the structure assignment.
This patch also handles cases where r0 > r1, (one circle must still
be wholly contained within the other as that's all SVG supports).
This patch should also prevent a crash when r0 == r1.
It turns out that this case is extremely common and worth avoiding
the overhead of the path iteration and tessellation code.
The optimization here works only for device-axis-aligned rectangles
It should be possible to generalize this to catch more cases, (such
as any convex quadrilateral with 4 or fewer points).
This fix results in a 1.4-1.8x speedup for the rectangles perf case:
image-rgb rectangles-512 7.80 1.22% -> 4.35 1.62%: 1.79x speedup
▊
image-rgba rectangles-512 7.71 4.77% -> 4.37 0.30%: 1.77x speedup
▊
xlib-rgba rectangles-512 8.78 5.02% -> 5.58 5.54%: 1.57x speedup
▋
xlib-rgb rectangles-512 11.87 2.71% -> 8.75 0.08%: 1.36x speedup
▍
Which conveniently overcomes the ~ 1.3x slowdown we had been seeing
for this case since 1.2. Now, compared to 1.2.6 we see only a speedup:
image-rgba rectangles-512 6.19 0.29% -> 4.37 0.30%: 1.42x speedup
▎
image-rgb rectangles-512 6.12 1.68% -> 4.35 1.62%: 1.41x speedup
▎
xlib-rgba rectangles-512 7.48 1.07% -> 5.58 5.54%: 1.34x speedup
▏
xlib-rgb rectangles-512 10.35 1.03% -> 8.75 0.08%: 1.18x speedup
▏
With this change, the cairo-svg output is perfectly fine with
CAIRO_EXTEND_REPEAT, but is still very slightly wrong with
CAIRO_EXTEND_REFLECT, (though *much* better than it was before
this fix).