- int s;
- // the input (control points) is read as a stream of points, and buffered
- // by the cpprev, cpcurr, and cpnext variables (to allow subdivision in
- // overlapping memory buffers, even subdivision in-place with pre-spaced
- // control points in the buffer)
- // the output (resulting curve) is written as a stream of points
- // this subdivision is meant to be repeated until the desired flatness
- // level is reached
- if (components == 1 && instride == (int)sizeof(float) && outstride == instride)
- {
- // simple case, single component and no special stride
- float cpprev0 = 0, cpcurr0 = 0, cpnext0;
- cpnext0 = *in++;
- for (s = 0;s < inpoints - 1;s++)
- {
- cpprev0 = cpcurr0;
- cpcurr0 = cpnext0;
- if (s < inpoints - 1)
- cpnext0 = *in++;
- if (s > 0)
- {
- // 50% flattened control point
- // cp1 = average(cp1, average(cp0, cp2));
- *out++ = (cpcurr0 + (cpprev0 + cpnext0) * 0.5f) * 0.5f;
- }
- else
- {
- // copy the control point directly
- *out++ = cpcurr0;
- }
- // midpoint
- // mid = average(cp0, cp1);
- *out++ = (cpcurr0 + cpnext0) * 0.5f;
- }
- // copy the final control point
- *out++ = cpnext0;
- }
- else
- {
- // multiple components or stride is used (complex case)
- int c;
- float cpprev[4], cpcurr[4], cpnext[4];
- // check if there are too many components for the buffers
- if (components > 1)
- {
- // more components can be handled, but slowly, by calling self multiple times...
- for (c = 0;c < components;c++, in++, out++)
- QuadraticBSplineSubdivideFloat(inpoints, 1, in, instride, out, outstride);
- return;
- }
- for (c = 0;c < components;c++)
- cpnext[c] = in[c];
- (unsigned char *)in += instride;
- for (s = 0;s < inpoints - 1;s++)
- {
- for (c = 0;c < components;c++)
- cpprev[c] = cpcurr[c];
- for (c = 0;c < components;c++)
- cpcurr[c] = cpnext[c];
- for (c = 0;c < components;c++)
- cpnext[c] = in[c];
- (unsigned char *)in += instride;
- // the end points are copied as-is
- if (s > 0)
- {
- // 50% flattened control point
- // cp1 = average(cp1, average(cp0, cp2));
- for (c = 0;c < components;c++)
- out[c] = (cpcurr[c] + (cpprev[c] + cpnext[c]) * 0.5f) * 0.5f;
- }
- else
- {
- // copy the control point directly
- for (c = 0;c < components;c++)
- out[c] = cpcurr[c];
- }
- (unsigned char *)out += outstride;
- // midpoint
- // mid = average(cp0, cp1);
- for (c = 0;c < components;c++)
- out[c] = (cpcurr[c] + cpnext[c]) * 0.5f;
- (unsigned char *)out += outstride;
- }
- // copy the final control point
- for (c = 0;c < components;c++)
- out[c] = cpnext[c];
- //(unsigned char *)out += outstride;
- }