-
-
Notifications
You must be signed in to change notification settings - Fork 107
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
Rectangles with zero sizes are drawn incorrectly #174
Comments
Hi, this is expected behavior because the default stroke join is BLImage render(const BLContextCreateInfo& cci) {
BLImage img(500, 140, BL_FORMAT_PRGB32);
BLContext ctx(img, cci);
ctx.setFillStyle(BLRgba32(0xFFFFFFFFu));
ctx.fillRect(0, 0, 500, 140);
ctx.setStrokeWidth(10);
ctx.setStrokeJoin(BL_STROKE_JOIN_MITER_BEVEL);
ctx.setStrokeStyle(BLRgba32(0xFF000000u));
ctx.strokeRect( 50, 70, 1, 1); // 1 x 1 px --> draws a small 11 x 11 px rect perfect
ctx.strokeRect(150, 70, 0, 0); // 0 x 0 px --> draws nothing fair
ctx.strokeRect(250, 70, 1, 0); // 1 x 0 px --> draws a long 41 x 10 px line, this is wrong
ctx.strokeRect(350, 70, 0, 1); // 0 x 1 px --> draws a long 10 x 41 px line, this is wrong
return img;
} Did you expect the output of this code? |
Hi, yes, this looks like what I had in mind. Also thanks for the reference to MITER, as it completely explains what is going on. So here is what I assume is happening. With one side being 0px, the stroke is approximated with 2 points instead of 4, as two are the same. Both points now have an opening angle of 0° instead of 90° and a miter is added. As it is infinitely long it is clipped at the miter limit. I did some research on the topic, and saw some discussions around SVG 2.0 and I tried to make an SVG to see what other implementations make of Still I am not sure if the behavior is the correct one. The corner being treated as having 0° is not a good limit when one side going to zero, from a mathematical point of view. It should remain at having 90° and therefore not justify a meter to be added. For now I am checking my width and height of my rectangles and not drawing them if one is zero as a workaround. I might consider changing the meter behavior, so I don't need to do this anymore. Thank you. |
This is a tricky border case. I will try to explain what is happening, and why the current behavior is maybe the only one that makes sense. When you want to stroke a rectangle, the stroker in general doesn't see a rectangle, only the path commands that represent the rectangle. In a regular case, it would go something like:
If one w/h is zero, it really appears as a command that has the exact coordinate of the previous command, which then basically changes the angle between the vertices as the vertex that is equal to the previous vertex (or very very close to it) is ignored by the stroker. Then, if
so it really becomes a line and joins apply to its start/end points basically. What you see is actually miter-clip, as miter- clip ( |
Thank you. I agree, on a path level given the 4 points this is the only behavior that makes sense. I looked a bit more into SVG, although I don't know if the goal here is to follow them even. In the SVG1.1 specification there is a section about the size properties of
The new SVG2 specification is missing that sentence, although someone made an issue about adding it, without further comment. Maybe we should not generate a path on the rect level if one side is zero. |
Yeah that's an interesting question. At the moment, when you fill a zero width/height rectangle, the rendering context returns SUCCESS, when w/h is negative, it should return INVALID_GEOMETRY. It's an interesting case - is zero invalid or should it just prevent the rendering? And, when you add zero width/height to a path, should the geometry be added or rejected? I don't really know what is the right behavior to be honest. One can do |
Currently when rects are stroked with one being exactly 0, Blend2d draws something weird.
Fiddle example
As you can see, the things drawn with zero sizes are even bigger than the ones with size 1x1 px.
I guess it should draw the same as for the case 0x1px, namely no stroking at all.
At max 10 x 11 px, but nothing that is 41 px long.
The text was updated successfully, but these errors were encountered: