Issue 120616

Summary: svg: wrong rendering for gradientUnits="objectBoundingBox"
Product: Draw Reporter: Regina Henschel <rb.henschel>
Component: codeAssignee: AOO issues mailing list <issues>
Status: CLOSED FIXED QA Contact:
Severity: Normal    
Priority: P3 CC: Armin.Le.Grand
Version: 3.4.0   
Target Milestone: 4.0.0   
Hardware: PC   
OS: Windows XP   
Issue Type: DEFECT Latest Confirmation in: ---
Developer Difficulty: ---
Attachments:
Description Flags
example with gradient transform and obejectBoundingBox
none
Screenshots
none
Example hich contains all four cases of SVG gradients
none
Another example showing the difference with GradientUnits none

Description Regina Henschel 2012-08-19 13:19:27 UTC
Created attachment 79000 [details]
example with gradient transform and obejectBoundingBox

The gradient is defined from (0|0) to (1|0). So the points (1|y) mark the line g, where the gradient ends and filling will be continued with last stop color.

The gradient gets a gradientTransform="rotate(45)". So the point (1|0) will be transformed to (0.707|0.707) and point (1|1) will be transformed to (0|1.414).

The transformed line g will intersect the right border of the bounding box in (1|0.414) and the top border line of the bounding box in (1.414|0), which is right side out of the bounding box.

Insert the attached svg image to see, that this is not drawn in this way.
Comment 1 Armin Le Grand 2012-08-20 12:10:35 UTC
ALG: I did not do the calculations, but I loaded the example in AOO3.4.1, Firefox, Safari and Inkscape, all look the same. I see no problem here (except all these are wrong, too).
Comment 2 Regina Henschel 2012-08-20 13:52:47 UTC
Created attachment 79007 [details]
Screenshots

I don't know whether you see the same as I. I have used AOO r1370716. The attached file contains a screenshot what I see in AOO and screenshots of Seamonkey and Inkscape.

The error becomes more visible if the rectangle is much wider than high. Look at the small rectangle. You should see the different direction in AOO and the others.
I have inserted a cross to mark the gradient direction and its orthogonal line.
Comment 3 Regina Henschel 2012-08-20 20:07:29 UTC
I've made a new build of r1374948 on WinXP and still see the bug as described. The bug is not in AOO3.4.1 but only in trunk.
Comment 4 Armin Le Grand 2012-08-22 16:03:08 UTC
ALG: I also made a new build and can now reproduce it. After some search (compare debug between rel version and trunc) I found out that it is because of #120397#. That fix changed the way linear gradients are rendered in respect to their aspect ratio. That fix is correct.
That fix masked another error in svgio import; the gradientTransform (see SVG spec 1.2, 13.2.2 Linear gradients) is applied to the unit object coordinate system. This is unscaled and thus the aspect ratio is lost.
Incredible that two errors can mask themselves in such a form. Good catch Regina!
Comment 5 Armin Le Grand 2012-08-23 11:32:18 UTC
ALG: Problem is completely different from what I thought. First, #120397# was not the right fix and I took it back.
The general problem is that gradients use gradientUnits as objectBoundingBox or userSpaceOnUse. Both define in which coordinate system the data is to be interpreted, thus it is possible to map both to the unit coordinate system (0,0,1,1) relative to an object (by mapping start/end/radius, etc.). That's what I did with the primitive representation for SVG gradients. The gradientTransform makes no difference here, it can be included to the mapping.
But it is differently interpreted by SVG:

(a) When gradientUnits, the gradient is interpreted in unit coordinates and then transformed using the object transformation.
(b) When userSpaceOnUse, the gradient is interpreted in world coordinates (first apply oblect transformation, then interpolate).

Case (a) leads to the gradient being 'scaled' to the object's aspect ratio, since the object transformation is applied to gradient data in unit coordinates. Case (b) will keep the aspect ratio of the object unrecognized since interpreted after the object transform is applied.

Thus, in reality, SVG has four different kind of gradients, not two. I did not see this clearly stated/explained in SVG1.2 spec, maybe I overlooked it.

The solution is to give the gradient primitive a flag in which order the object transformation and the gradient interpretation has to be done. Done that, works well. I'll add an example with all four cases.

One remark on primitive usage: Luckily I have only to adapt two primitives to change this, it is just differently decomposed to primitive atoms (one color range only); without primitives there would be implementations in each viewer/exporter (PDF, vcl, convert to bitmap, break, ...) which would need to be changed...
Comment 6 Armin Le Grand 2012-08-23 11:33:05 UTC
Created attachment 79098 [details]
Example hich contains all four cases of SVG gradients
Comment 7 SVN Robot 2012-08-23 11:38:23 UTC
"alg" committed SVN revision 1376444 into trunk:
#120616# Corrected SVG gradient primitive and it's decomposition
Comment 8 Armin Le Grand 2012-08-23 11:45:25 UTC
ALG: Double-checked with the attached example, we look now the same as Firefox and Safari; my Inkscape has a problem with interpreting 'myGradient1', but this may be an error there.
Done so far. Regina, please update, build and have a look...
Comment 9 Armin Le Grand 2012-08-23 12:10:53 UTC
Created attachment 79099 [details]
Another example showing the difference with GradientUnits

One more example to show how different it is interpreted, using radial gradients; "myGradient4" is just a version of "myGradient3" where I changed from objectBoundingBox to userSpaceOnUse and calculated the absolute values corresponding to the relative ones per hand so that the only diference *is* the gradientUnits setting. See how different it looks...
Comment 10 Regina Henschel 2012-08-23 17:03:34 UTC
Start AOO3.5 newly. Open the attached file "Example hich contains all four cases of SVG gradients" via clicking on the "Open" button. I get the error

"Error: SvgGradient Atom creation with no step width (!) From File c:/AOO_2012_07_git/trunk/main/drawinglayer/source/primitive2d/svggradientprimitive2d.cxx at Line 628"

I get the same error, when I insert it via Insert > Picture and switch on "Preview".

The rendering of the gradients looks correct now.
Comment 11 Armin Le Grand 2012-08-23 18:03:02 UTC
ALG: Hopps, have to check that, did not see it. Isn't that SVG stuff intersting, esp. with the same parameters for both modes...?
Comment 12 Regina Henschel 2012-08-23 18:46:58 UTC
Yes. And I'm glad you are working to get SVG to AOO.

I came across "objectBoundingBox" when I looked at the gradient definitions in ODF1.2. There are svg:LinearGradient and svg:radialGradient allowed (16.40.2/3) but only with svg:gradientUnits value "objectBoundingBox".

In general I see a lot of prospects. These svg:LinearGradient and svg:radialGradient as method for draw objects would be good for import from Calligra and for converting SVG graphic to draw objects. And if SVG animation were working in Impress, that would be fantastic.
Comment 13 Armin Le Grand 2012-08-23 19:11:15 UTC
ALG->Regina: +1 for these, exactly the direction I wanna go :-) Each of these...