a simple cubic going crazy
it's a just a simple cubic, but for some degenerate cases it takes seconds and gigabytes of memory !
// a simple cubic,
// it is a degenerate curve for beta 0, PI/2, PI, ...
// it works for beta = 0.0
// BUT for beta = 2*PI (same curve as for beta = 0)
// it uses GigaBYTES !
BLPath mycurve(double R, double beta) {
BLPath path;
double x = R*cos(beta);
double y = R*sin(beta);
path.moveTo(x,y);
path.cubicTo(0.0,2*y, 0.0,-2*y, x,-2*y);
return path;
}
BLImage render(const BLContextCreateInfo& cci) {
BLImage img(512, 512, BL_FORMAT_PRGB32);
BLContext ctx(img, cci);
ctx.clearAll();
BLPoint P;
double R = 200.0;
// build a path p0 with beta 0.0
BLPath path0 = mycurve(R, 0.0);
// for beta=360, mycurve(R,2*PI) should be equal to mycurve(R,0)
// but ...
// we have an approx PI ...
double PI =3.141592653589793;
BLPath path360 = mycurve(R, 2*PI);
// TEST !!! repeat 50 times ... Strace gives <Execution timed out>
ctx.setStrokeStyle(BLRgba32(0xFFFFFFFF));
for (int i=0; i< 50; ++i) {
ctx.strokePath(path0);
ctx.strokePath(path360);
}
return img;
}
Should be fixed by 2f79eb23ab0b00c5a00535c4f2477c15e626dfa4
Tested your fix: I should say that it's only partially fixed. The worst cases causing huge processing times are fixed, but there are still simple (degenerate cubics) that are not drawn.
Consider this cubic {0,0} ,{200,0}, {200,0}, {0, 0} it should be rendered as a straight line from (0,0) to (150,0) (and then back to (0,0)) but this curve is not drawn at all.
----- here is a fiddle for testing ----
BLPath mycubic(BLPoint P0, BLPoint P1, BLPoint P2, BLPoint P3) { BLPath path;
path.moveTo(P0); path.cubicTo(P1,P2,P3); return path; }
BLImage render(const BLContextCreateInfo& cci) { BLImage img(512, 512, BL_FORMAT_PRGB32); BLContext ctx(img, cci);
ctx.clearAll();
double width = ctx.targetWidth(); double height = ctx.targetHeight();
// translate origin at center of the screen ctx.translate(width/2.0,height/2.0);
// draw XY axis
ctx.setFillStyle(BLRgba32(0xFF808080)); ctx.setStrokeStyle(BLRgba32(0xFF404040)); ctx.strokeLine(0.0,height,0.0,-height); ctx.strokeLine(-width, 0.0,width,0.0);
// set color for the next cubics .. ctx.setStrokeStyle(BLRgba32(0xFFFFFFFF));
ctx.strokePath(mycubic( {0,0},{200,0},{200,0},{0, 0} )); // nothing is drawn !!
// translate the same cubic vertically
// then apply a minimal variation to a coord
ctx.translate(0,50);
ctx.strokePath(mycubic( {0,0},{200.001,0},{200,0},{0, 0} )); // OK
return img; }
I'm not sure what I've found regarding degenerate cubics not rendered
such as (0,0) (0,100) (0,100) (0,0)
or more generally cubics like {pA pB pB pA}
but I've found some strange suspicious things in "pathstroke.cpp"
The first thing I noted is at line 288 BLPoint p[7] // ? why 7 ? 4 is enough ! this could be not important (just some unused space on the stack), but then I noted that isCubicFlat(..) (at line 299) on curves like the ones above returns "true". Is it correct ? I agree that {pA pB pB pA} are 4 aligned points, but this is not a flat curve, it's a 'folded' curve starting from pA, going straight to pB, and then going back to pA .. Anyway, after this isCubicFlat test, this curve is treated as a Line from p0 to the last point p3, but this is a null segment and so it's skipped.
I could be wrong, I didn't debug the code, just read it, and honestly, I didn't understand the used algorithm, but this "isCubicFlat()" looks strange to me.