Stroking cubic bezier, strange behavior Ref. Implementation

I tried to create two degenerated paths (really close points), as follow:


path4 = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, 1.0f, 0.0f, 0, 0, VG_PATH_CAPABILITY_ALL);
pathSegs[0] = VG_MOVE_TO_ABS;
pathData[0] = -0.00005f;
pathData[1] = -0.00005f;
pathSegs[1] = VG_CUBIC_TO_ABS;
pathData[2] = +0.0001f;
pathData[3] = +0.0001f;
pathData[4] = -0.0001f;
pathData[5] = +0.0001f;
pathData[6] = +0.00005f;
pathData[7] = -0.00005f;
vgAppendPathData(path4, 2, pathSegs, pathData);


// NB: path5 should be the result from a path4 flattening. Code has been taken from Reference Implementation
path5 = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, 1.0f, 0.0f, 0, 0, VG_PATH_CAPABILITY_ALL);
j = 0;
for (i = 0; i < 256; ++i) {
	float p0x = -0.00005f;
	float p0y = -0.00005f;
	float p1x = +0.0001f;
	float p1y = +0.0001f;
	float p2x = -0.0001f;
	float p2y = +0.0001f;
	float p3x = +0.00005f;
	float p3y = -0.00005f;
	float t = (float)i / 255.0f;
	float u = 1.0f - t;
	pathData[j++] = u * u * u * p0x + 3.0f * t * u * u * p1x + 3.0f * t * t * u * p2x + t * t * t * p3x;
	pathData[j++] = u * u * u * p0y + 3.0f * t * u * u * p1y + 3.0f * t * t * u * p2y + t * t * t * p3y;
}
vguPolygon(path5, pathData, j / 2, VG_FALSE);

And then I’ve drawn them (using a large stroke line width) with the following code:


vgSetfv(VG_STROKE_DASH_PATTERN, 0, NULL);
vgSetf(VG_STROKE_LINE_WIDTH, 126.0f);
vgSeti(VG_STROKE_CAP_STYLE, VG_CAP_BUTT);
vgSeti(VG_STROKE_JOIN_STYLE, VG_JOIN_ROUND);
vgClear(0, 0, 256, 256);
vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE);		
vgLoadIdentity();
vgTranslate(64.0f, 128.0f);
vgDrawPath(path4, VG_STROKE_PATH);
vgLoadIdentity();
vgTranslate(192.0f, 128.0f);
vgDrawPath(path5, VG_STROKE_PATH);

Because path5 should reproduce the path4 flattening (I’ve taken the code directly from the public Reference Implementation), and given that I’ve used round joins to simulate the smooth connection of the cubic curve, I would expect to see two similar drawings, instead of the following result:

Could someone explain the reason of this different behavior?
Thanks in advance.

The coordinates you’re using are really small and you’re running close to the numeric precision threshold for floating point numbers I think.
The reference implementation, quite illogiucally IHMO, whenever it detects a cusp, adds a full 180 degree rotation of linewidth size (effectively, it draws a cricle at cusp points).
If I had to guess, I’d say it small numbers are causing a cusp to be found somewhere it shouldn’t be. That’s just my guess though. Try larger coordinates.

It seems that floating point precision doesn’t affect the rendering of this test case.

It’s clear that joins between two path segments (of any kind) and ‘smooth interpolated’ joins that take place on the points generated by the curve flattening, have a really different behaviour (expecially on the internal side of the stroke).

‘Smooth interpolated’ joins acts on the internal stroke side like a crayon with a large head, where normal path joins lets the internal stroking side untouched instead. This is really noticeable using a large stroke width on segments with high curvature values (as in the test case).

So, the wrong assumption was that VG_JOIN_ROUND should act as a ‘smooth interpolated’ join.

Regards,