World: r3wp
[SVG Renderer] SVG rendering in Draw AGG
older newer | first last |
ICarii 10-Oct-2009 [151] | I've been playing with Shadwolf/etc SVG 06 svg renderer today and am at the point where i am working on linking in gradients. The test SVG i am using (because it seems to be a good mix) is http://en.wikipedia.org/wiki/File:SVG.svg |
Steeve 10-Oct-2009 [152x3] | Icarii, your svg file is too much complicated for me. It's using both gradientUnits="objectBoundingBox" and gradientUnits="userSpaceOnUse" to render the gradients. userSpaceOnUse use real coordinates for the vectors used by gradients (what i do currently). objectBoundingBox use % vectors which have to be converted into real unit, depending of the real size of the object (after rendering) where the gradient is applied (what the fuck !!! it's magic). I have enough pain to construct correct gradients in real units for the moment.Your svg file is too much complicated. |
Currently my problem is with the linear gradients when a matrix operation is applied on them. The linear gradient use a vector v = (x1, y1) - (x2, y2) to indicate his direction and length. grad-pen is defined like this: [grad-pen linear normal xy 0 len angle [... stop colors]] And i calculate his values with: - xy = (x1,y1) - len = length of the vector v - the angle of the vector v When a matrix is associated with the gradient, i multiply the coordinates of the vector v by the matrix before calculating the other values. It's working well when the gradient is vertical or horizontal. But when the gradient is inclined , the matrix multiplication give a wrong vector and i don't know why. | |
To be precise, the resulting vector seems to have the correct position and length, but a wrong angle. | |
ICarii 10-Oct-2009 [155] | what sort of output are you getting for the angle in the grad-pen call? |
Steeve 10-Oct-2009 [156] | Well, assuming you got x1,y1,x2,y2 from the Lineargradient I calculate the angle like that: arctangent (y2 - y1) / (x2 - x1) As i said previously, the angle is correct when there is no matrix transformation on the gradient. I compare the rendering with what i see in Inskape. |
Steeve 11-Oct-2009 [157x5] | the svg i test currently (public domain) http://sites.google.com/site/rebolish/test-1/lizard.svg |
And what i got with rebol: http://sites.google.com/site/rebolish/test-1/lizard-rebol.png | |
the gradients still have the same problem | |
when matrix transformations are applied, some are wrong, but hey ! Quite a good result already ! | |
Well, i think i got it for the linear gradients... | |
ICarii 11-Oct-2009 [162] | btw the bounding box call in the second sizing mode can be gotten from the size of the canvas you are drawing to. |
Pekr 12-Oct-2009 [163] | Steeve - your work is quite impressive! Just don't become demotivated by possible lack of responses :-) If you find some bugs, or you come up with some ideas of how to make View more SVG friendly, write your notes down, we can discuss it with Cyphre. I think that we are still in rather initial phase, so we can e.g. change the way of how e.g. gradient-fills work (I do remember someone reported that you can't translate gradient definitions between /draw and SVG) |
Steeve 12-Oct-2009 [164x3] | This matrix must not be applied on the gradient's vector as-is, but on something else. And i found what, at least... The documentation of SVG is lacking of a good explanation about this curious matrix transformation. All we can read is that curious sentence: When the object's bounding box is not square, the stripes that are conceptually perpendicular to the gradient vector within object bounding box space will render non-perpendicular relative to the gradient vector in user space due to application of the non-uniform scaling transformation from bounding box space to user space What does that mean ????? It means that the SVG gradient must be rendered without using the matrix transformation. And THEN the transformation matrix must be applied on the resulting strips. You see the problem ? The matrix must not be apllied on the gradient's vector, but on the resulting strips produced by the use of the initial gradient's vector. What foolish morons have designed such a complicated way of constructing gradients. Can't they just give a matrix that can be applied on gradient's vector as-is, no they can't, it's to simple. Morons, I said !!! Because of that i had to make more transformations to obtain the REAL vector. step by step I do something like that: 1/ Take the initial gradient vector V and apply the matrix on it, it gives a vector V1 2/ RE-take the initial vector V, rotate it of 90 degrees, apply the matrix on it, and rotate back the resulting vector . It gives the vector V2 3/ Project the vector V1 on the line V2 (orthogonal projection). It gives a third vector V3. 4/ That's all, the REAL vector to use for the gradient is V3. It take me a while to figure that, by analysing the Inkscape rendering. Morons i said !!! |
I show you that part of my code... switch type [ linear [ unless x2 [x2: x1] unless y2 [y2: y1] if matrix [ ; ** apply the matrix on the vector rotated of 90°, then rotate it back, give the vector V1 set [y1' x1'] mulm y1 negate x1 matrix set [y2' x2'] mulm y2 negate x2 matrix x1': negate x1' x2': negate x2' ;** apply the matrix on the initial vector, give the vector V2 set [x1 y1] mulm x1 y1 matrix set [x2 y2] mulm x2 y2 matrix ;** project the vector V2 on the line V1 set [x1 y1] project x1' y1' x2' y2' x1 y1 set [x2 y2] project x1' y1' x2' y2' x2 y2 ] angle: atan2 x2 - x1 y2 - y1 if units = "objectBoundingBox" [ x1: box/1/x * x1 y1: box/1/y * y1 x2: box/2/x * x2 y2: box/2/y * y2 ] out as-pair x1 y1 ;** offset out 0 ;** start rng out square-root add x2 - x1 ** 2 y2 - y1 ** 2 ;** stop rng out angle ;** angle ] ... | |
Well i thought SVG 's radialGradients will be easier. I was wrong. SVG Proposes another stupid feature (yet another one). Actually they can specify 2 circles. One where the gradient is really rendered. And another one used as a window which clips the first one. What the heck is that !!!! it's why in a SVG's radial gradient, there is 2 different centers (cx, cy) (fx, fy) for the 2 separated circles. When the 2 centers are equals, then there is no prolem to render it whit the rebol's radial gradient, easy. But when they differ, it's impossible. I can't blame Rebol to not allow that, because it's a really stupid useless feature. | |
Pekr 12-Oct-2009 [167] | Now the question is - should we adapt, or do we create copy of such functions, to allow being compatible? |
Steeve 12-Oct-2009 [168x8] | I'm angry, i don't see why grad-pen in Rebol should allow such stupid feature |
in fact, i think i could simulate that behavior. By 1/ rendering the radial gradient in the initial circle. 2/ create an image with that circle and clip it with the shape of the second one. 3/ Use that image as a pattern for the fill-pen attribut But it would be a mess of computing time and of memory, because in the draw block we would have images used as pattern instead of computed gradients | |
i think that feature (2 different centers) is not used that much. In the lizard.svg example i gave, they don't use it, the 2 centers are always equal. | |
By default Inkscape don't use that feature when you design a radial vector. | |
Ok, i finished with Radial gradients (less the impossible feature: 2 different centers) SVG use a matrix transformation to convert a circular radial gradient into an ellipsoid. And you know what ? We can do the same thing with grad-pen which provides 2 scalling factors (grad-scale-x and grad-scale-y) So in that case it's easier than for linear-gradient. 1/ take the focal point of the Radial gradient (fx, fy) 2/ Create 2 vectors starting from this point: 1 vertical and 1 horizontal, using the radius as their length. 3/ apply the matrix transformation on them. 5/ get the component X of the transformed horizontal vector, and the component Y of the transformed vetical vector 6/ grad-scale-x: x / r 7/ grad-scale-y: y / r That's all folks | |
Gezz... i forget the rotation of the ellipsoid... more work... | |
Ok, done | |
Guys, i updated the lizard.svg rendered with Rebol http://sites.google.com/site/rebolish/test-1/lizard-rebol.png To compare with http://sites.google.com/site/rebolish/test-1/lizard.svg. I'm glad to announce that i see absolutly no differences inside Google chrome. All the grandients (linear and radial) are perfectly rendered by Rebol. | |
Graham 12-Oct-2009 [176] | Nice ... |
ICarii 12-Oct-2009 [177] | great work steeve! :) |
Steeve 12-Oct-2009 [178] | Basically, you can load the draw block generated for the lizard here. it's handed by the variable PANE. http://sites.google.com/site/rebolish/test-1/lizard.r |
Maxim 12-Oct-2009 [179] | GREAT WORK Steeve :-) |
Steeve 12-Oct-2009 [180] | Added a litte animation. The bumping lizard !!!! http://sites.google.com/site/rebolish/test-1/lizard.r |
Maxim 12-Oct-2009 [181] | the difference in your render and SVG render is mainly the anti-aliasing, which is crisper in the svg renderer.... probably has a better algorythm setup than the one use by R3... this is probably manageable within AGG, but AFAIK there is no control for it within R3. |
Steeve 12-Oct-2009 [182] | Not the problem of the antialiasing, I just think i made a false translation of the command used in the shapes. They use a smouthing curve, me not i guess. I have to verify that. But Rebol can draw smoothing curves too, no problemo. |
Maxim 12-Oct-2009 [183x3] | if you draw the outlines twice, they should be a bit crisper... is that what you mean? |
there seems to be two spots missing on the left left... very faint, but missing or not visible at least. | |
also the anti-aliasing was a result of my browser which rescaled the image minus 5 pixels... so it has nothing to do with your render. | |
Steeve 12-Oct-2009 [186x2] | ok |
i only checked with google chrome, it was very similar | |
BrianH 12-Oct-2009 [188] | Sorry, got tired of the shouted group name/description :) |
Steeve 12-Oct-2009 [189] | i don't know which renderer chrome uses |
BrianH 12-Oct-2009 [190] | It's a good one. It looks identical to yours, though that may be server side in your example link. |
Maxim 12-Oct-2009 [191] | we should also note that this is in R3 :-) not everyone realizes this IMO. |
BrianH 12-Oct-2009 [192] | Seriously? Cool :) |
Steeve 12-Oct-2009 [193] | yes it's R3 |
BrianH 12-Oct-2009 [194] | Draw should be the same, afaik, which isn't that far. Have the parse improvements helped? |
Steeve 12-Oct-2009 [195x2] | not so much ;-) |
but the new grad-pen command of draw is awesome | |
BrianH 12-Oct-2009 [197] | Cool :) |
Maxim 12-Oct-2009 [198] | that was seriously missing in R2 draw.. happy its in R3 :-) |
Steeve 12-Oct-2009 [199] | By the way the DRAW function can't render that, it's crashing. |
BrianH 12-Oct-2009 [200] | The DRAW function is still there? I really need to pay more attention to the graphics stuff. |
older newer | first last |