Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for percentage coordinates #21

Open
RMariowski opened this issue Dec 13, 2014 · 14 comments
Open

Support for percentage coordinates #21

RMariowski opened this issue Dec 13, 2014 · 14 comments

Comments

@RMariowski
Copy link

NanoSVG does not properly support percentage coordinates.
At least percentage coordinates should be supported in gradient definitions.

SVG Example

@memononen
Copy link
Owner

@xandev can you check if the recent changes fixed your problem and close the issue accordinly?

@RMariowski
Copy link
Author

Now it's looks like this http://i.imgur.com/8l8qsHw.png

@memononen
Copy link
Owner

How should I interpret that image? :) The original on left, and nanosvg rendered at right? That is, it does not work yet?

@RMariowski
Copy link
Author

Exactly. As you can see rectangle has been cut and gradient still isn't working.
That's the result of update nanosvg headers without any code change etc.

@chrismile
Copy link
Contributor

I don't think that the problem with the cut rectangle is about the percentage coordinates. Even when I render your SVG file with the fill mode set to any solid color, I get the same results.
output

@RMariowski
Copy link
Author

Dunno what is causing cut, but it was fine before update.

@memononen
Copy link
Owner

It's probably this one:
46e8b78#diff-a5adee86dee0bb074ce7e3cfa42ec19bR2525

I have to refresh that logic and see what is causing the problem.

@chrismile
Copy link
Contributor

Yes, probably the calculation of the view box is wrong. However, reverting 46e8b78#diff-a5adee86dee0bb074ce7e3cfa42ec19bR2525 probably won't be enough.
Here's the output of the code with the source before this code merge (transparency highlighted with magenta):
output_old
... and the output of the current code base:
output_new
So neither of them seems to be actually correct (provided of course that I'm calling nsvgRasterize correctly).

And now to the percentage coordinates: Yes, something still seems to be missing.
NanoSVG is currently able to rasterize http://www.w3.org/TR/SVG/images/pservers/lingrad01.svg correctly, so I'd assume that something is mixed up with x1/y1/x2/y2.
I'll have a look at it.

@chrismile
Copy link
Contributor

It seems the problem with the percentage coordinates lies in "nsvg__convertToPixels". According to the passed value of "dir", the value is multiplied with either the the viewWidth, viewHeight or the diagonal of the view box. However, both of them are 0, as the view box is computed after parsing the file.

if (dir == 0)
    return (val/100.0f) * nsvg__actualWidth(p);
else if (dir == 1)
    return (val/100.0f) * nsvg__actualHeight(p);
else if (dir == 2)
    return (val/100.0f) * nsvg__actualLength(p);

Is there a deeper reason why NanoSVG should multiply percentage values with e.g. the view width? At least for gradients, the percentage values always refer to the object bounding box, not the view box. So in this case, the percentage values should just be returned as "val/100.0f". With this change the gradient is rendered correctly (but of course it changes nothing for the incorrect view box):
output

@chrismile
Copy link
Contributor

I looked into the view box logic and I think I found the source of the bug. "p->viewMinx" and "p->viewMiny" are set to 0 when no view box was set in the SVG document. In this case they should be set to "-bounds[0]" and "-bounds[1]".
However, there's one thing that is a bit odd:
When I render the test image without this change, I get this output:
output_edges
However, when I either set x/y of the rectangle to 0 or when I apply the change to the view box code, I get this output with really wrong edges:
output_edges2
I can also reproduce this behavior with upstream code, both current code and older code e.g. from https://github.com/memononen/nanosvg/tree/0874d4917d03e916437d329ff9e57e9facda4e59 and the following file: http://pastebin.com/syLxrLM4

EDIT: I just realized that these odd edges might occur because the view box doesn't take into account the outline width and the rendered image is cropped?

EDIT 2: Added some code in "nsvg__imageBounds" to include the stroke width when computing the image bounds, and now it works. I'll send a pull request for all the changes soon.
output

@chrismile
Copy link
Contributor

I'd really like to hear your feedback on these changes before I open a pull request: chrismile@abc2d41
I'm not sure whether some things like my changes in "nsvg__convertToPixels" are OK for you (memononen), as it changes the return values of percentages for non-gradient code, too. And the new code in "nsvg__imageBounds" is also more a workaround than a real solution. However, I think you can't generally include the stroke width in the bounding boxes, as this might break e.g. gradients.

@memononen
Copy link
Owner

I have to dive into the bounds issue properly. I remember that there was some things I could not implement properly because not all the information was not available at the time parseFloat was called.

@memononen
Copy link
Owner

I'm looking into this right now, will take a little while, though. I'll take bits and pieces from your CL.

I tested quikly how the image bounds are calculated on different viewers. Chrome considers outline on right/bottom of the image, but not on left/tip edges. OSX preview does not consider the outline at all. I think your proposal is better, though. Unless there's a spec saying otherwise. If you define the viewport, then those bounds will be used.

@chrismile
Copy link
Contributor

The bounding box computation seems to be inconsistent across different browsers.

http://stackoverflow.com/questions/12355349/the-bounding-box-of-the-svg-elements-is-not-consistent-between-browsers

Firefox includes the stroke in the bounding box. We have asked for the specification to change to reflect that this is correct.

I agree with you, I guess a view box including the object stroke is more useful as a standard behaviour. The standard behavior one would probably expect from a bounding box encompassing the whole renderable area is a boundig box including the stroke. I mean, a user who wants to rasterize all visible objects will probably expect not to have clipped object strokes. It would also look very odd if e.g. Inkscape decided to not include strokes in the bounding box.
However, from what I could find in a fast Google search, the specs are interpreted differently by different browsers/SVG viewers.

But of course a bounding box without the stroke is somethings that makes sense, too. I think that for example percentage coordinates for gradients always refer to this box without the stroke included.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants