Hello. I’ve got an assignment to mimic gradient behaviour from SVG on OpenVG platform. I’ve managed to get identical results with horizontal linear, vertical linear and radial gradients, but, I cannot anyhow get proper result with linear gradient that has angle.
Here is an example…
This is a snapshot of (20, 20)-(460, 120) gradient drawn by a SVG viewer (tried with few of them; the result is ever the same):
If drawn with OpenVG, this is what I get:
‘Stripes’ are obviously placed in the wrong direction. I’ve tried many things and I’ve simply cannot get them right.
However, there is one thing I’ve noticed - stripes are always at the 90 degrees compared to the SVG ones, so, if I swap x and y coordinates, stripes indeed start looking into the right direction, but, color stops aren’t good at all then (of course).
First, could I ask you which OpenVG implmentations you’ve tried?
The problem you describe stems from a different approach to handling linear gradients.
SVG defines it’s linear gradients into a square box, and scales the gradient to the bounding box of the object. This causes the normals of the gradients to also undergo a transformation thereby the angles of the color bands are not at 90 degrees to the gradient line.
In VG, the approach is different. You are given 2 points in paint space and an equation. Conceptually the approach used when rendering is that for every point being rendered you apply the inverse of the paint*user transform to get a point in paint space. This point is then evaluated to get the color ramp value.
Since a full matrix transform is impractical, shortcuts are taken - and paint gradients are calculated which are interpolated in screen space.
Now here is the vaguer part. The way that is natural to calculate the gradients, in essense, loses the normal information at this point as it only transforms the 2 end points. But 3 non-colinear points are required to get true gradients (the third point would have to be generated). As a result, the banding you see in the VG linear gradients are always at 90 degrees to the gradient line if only 2 points are used to calculate the gradients.
From my reading of the spec (on p101):
Gradients are patterns used for filling or stroking. They are defined mathematically in two parts; a scalar-valued gradient function defined at every point in the two-dimensional plane (in paint coordinates), followed by a color ramp mapping.
The SVG behaviour is the correct behaviour for OpenVG as well, making implementations that use the 2 point approach non-conformant. If it turns are they are conformant and that it’s my understanding which is not correct, then you’re in for some math to create the second point on the linear gradient to be on a 90 normal of the actual point.
This is just my understanding though, you’ll have to wait for a more official answer if you want to be sure.
To mimic the bevahiour of SVG, you should be setting the linear gradients relative to the square (1x1 was it?) bounding box and using the paint transform matrix to scale the paint to the bounding box of the entire path.
You should NOT be leaving the paint matrix at the identity and simply setting the start and end points of the gradients to the path bounding box. This will result in paint bands at 90 degrees to the gradient line as you saw in your example.