232 penWidth =
qRound(penWidth);
236 int vertexStride =
g->sizeOfVertex();
240 SmoothVertex *smoothVertices;
245 Color4ub transparent = { 0, 0, 0, 0 };
252 int nextGradientStop = 0;
253 float gradientPos = penWidth / gradientLength;
254 while (nextGradientStop < stops.
size() && stops.
at(nextGradientStop).first <= gradientPos)
256 int lastGradientStop = stops.
size() - 1;
257 float lastGradientPos = 1.0f - penWidth / gradientLength;
258 while (lastGradientStop >= nextGradientStop && stops.
at(lastGradientStop).first >= lastGradientPos)
260 int gradientIntersections = (lastGradientStop - nextGradientStop + 1);
288 const float innerRadiusTL =
qMax(radiusTL - penWidth * 1.0f, 0.01);
289 const float innerRadiusTR =
qMax(radiusTR - penWidth * 1.0f, 0.01);
290 const float innerRadiusBL =
qMax(radiusBL - penWidth * 1.0f, 0.01);
291 const float innerRadiusBR =
qMax(radiusBR - penWidth * 1.0f, 0.01);
292 const float outerRadiusTL = radiusTL;
293 const float outerRadiusTR = radiusTR;
294 const float outerRadiusBL = radiusBL;
295 const float outerRadiusBR = radiusBR;
298 int segmentsTL = radiusTL == 0 ? 0 :
qBound(3,
qCeil(radiusTL * (
M_PI / 6)), 18);
299 int segmentsTR = radiusTR == 0 ? 0 :
qBound(3,
qCeil(radiusTR * (
M_PI / 6)), 18);
300 int segmentsBL = radiusBL == 0 ? 0 :
qBound(3,
qCeil(radiusBL * (
M_PI / 6)), 18);
301 int segmentsBR = radiusBR == 0 ? 0 :
qBound(3,
qCeil(radiusBR * (
M_PI / 6)), 18);
307 if (innerRadiusTL == innerRadiusTR) {
308 if (segmentsTL <= segmentsTR)
313 if (innerRadiusBL == innerRadiusBR){
314 if (segmentsBL <= segmentsBR)
320 if (innerRadiusTL == innerRadiusBL) {
321 if (segmentsTL <= segmentsBL)
326 if (innerRadiusTR == innerRadiusBR) {
327 if (segmentsTR <= segmentsBR)
334 const int sumSegments = segmentsTL + segmentsTR + segmentsBL + segmentsBR;
356 const int innerVertexCount = (sumSegments + 4) * 2 + gradientIntersections * 2;
357 const int outerVertexCount = (sumSegments + 4) * 2;
358 int vertexCount = innerVertexCount;
360 vertexCount += innerVertexCount;
362 vertexCount += outerVertexCount;
364 vertexCount += outerVertexCount;
367 const int fillIndexCount = innerVertexCount;
368 const int innerAAIndexCount = innerVertexCount * 2 + 2;
369 const int borderIndexCount = innerVertexCount * 2 + 2;
370 const int outerAAIndexCount = outerVertexCount * 2 + 2;
381 indexCount += fillIndexCount;
383 innerAATail = innerAAHead = indexCount + (innerAAIndexCount >> 1) + 1;
384 indexCount += innerAAIndexCount;
387 borderTail = borderHead = indexCount + (borderIndexCount >> 1) + 1;
388 indexCount += borderIndexCount;
391 outerAATail = outerAAHead = indexCount + (outerAAIndexCount >> 1) + 1;
392 indexCount += outerAAIndexCount;
395 g->allocate(vertexCount, indexCount);
396 vertices =
reinterpret_cast<Vertex *
>(
g->vertexData());
397 memset(vertices, 0, vertexCount * vertexStride);
402 float innerXPrev = 0.;
403 float innerYLeftPrev = 0.;
404 float innerYRightPrev = 0.;
406 const float angleTL = 0.5f * float(
M_PI) / segmentsTL;
407 const float cosStepTL =
qFastCos(angleTL);
408 const float sinStepTL =
qFastSin(angleTL);
409 const float angleTR = 0.5f * float(
M_PI) / segmentsTR;
410 const float cosStepTR =
qFastCos(angleTR);
411 const float sinStepTR =
qFastSin(angleTR);
412 const float angleBL = 0.5f * float(
M_PI) / segmentsBL;
413 const float cosStepBL =
qFastCos(angleBL);
414 const float sinStepBL =
qFastSin(angleBL);
415 const float angleBR = 0.5f * float(
M_PI) / segmentsBR;
416 const float cosStepBR =
qFastCos(angleBR);
417 const float sinStepBR =
qFastSin(angleBR);
449 const float outerXCenter[][2] = {{
457 const float outerYCenter[][2] = {{
465 const float innerXCenter[][2] = { {
473 const float innerYCenter[][2] = { {
481 const float innerRadius[][2] = {{
489 const float outerRadius[][2] = {{
505 const float cosStep[][2] = {{
513 const float sinStep[][2] = {{
521 auto fillColorFromX = [&](
float x) {
523 float t = (
x - gradientStart) / gradientLength;
527 if (
t < stops.
first().first)
529 while (
i < stops.
size()) {
532 if (prev.first <=
t &&
next.first >
t) {
533 t = (
t - prev.first) / (
next.first - prev.first);
540 for (
int part = 0; part < 2; ++part) {
542 float cosSegmentAngleLeft = 1. - part;
544 float sinSegmentAngleLeft = part;
546 float cosSegmentAngleRight = 1. - part;
547 float sinSegmentAngleRight = part;
549 bool advanceLeft =
true;
554 for (
int iLeft = 0, iRight = 0; iLeft <=
segments[part][0] || iRight <=
segments[part][1]; ) {
559 float outerXLeft, outerYLeft,
560 outerXRight, outerYRight;
562 float sinAngleLeft, cosAngleLeft,
563 sinAngleRight, cosAngleRight;
566 xLeft = innerXCenter[part][0] - innerRadius[part][0] * cosSegmentAngleLeft;
567 xRight = innerXCenter[part][1] - innerRadius[part][1] * cosSegmentAngleRight;
570 yLeft = innerYCenter[part][0] - innerRadius[part][0] * sinSegmentAngleLeft;
571 yRight = innerYCenter[part][1] + innerRadius[part][1] * sinSegmentAngleRight;
577 if ((iLeft <=
segments[part][0] && xLeft <= xRight) || iRight >
segments[part][1]) {
586 if (innerRadius[part][0] == innerRadius[part][1]) {
591 if (outerRadius[part][0] == 0) {
593 cosAngleLeft = part ? -1. : 1.;
595 sinAngleLeft = sinSegmentAngleLeft;
596 cosAngleLeft = cosSegmentAngleLeft;
598 if (outerRadius[part][1] == 0) {
600 cosAngleRight = part ? -1. : 1.;
602 sinAngleRight = sinSegmentAngleLeft;
603 cosAngleRight = cosSegmentAngleLeft;
606 yRight = innerYCenter[part][1] + innerRadius[part][1] * sinAngleRight;
608 if (outerRadius[part][0] == 0) {
610 cosAngleLeft = part ? -1. : 1.;
612 sinAngleLeft = sinSegmentAngleRight;
613 cosAngleLeft = cosSegmentAngleRight;
615 if (outerRadius[part][1] == 0) {
617 cosAngleRight = part ? -1. : 1.;
619 sinAngleRight = sinSegmentAngleRight;
620 cosAngleRight = cosSegmentAngleRight;
623 yLeft = innerYCenter[part][0] - innerRadius[part][0] * sinAngleLeft;
625 }
else if (advanceLeft) {
626 if (outerRadius[part][0] == 0) {
628 cosAngleLeft = part ? -1. : 1.;
630 sinAngleLeft = sinSegmentAngleLeft;
631 cosAngleLeft = cosSegmentAngleLeft;
633 if (outerRadius[part][1] == 0) {
638 cosAngleRight = part ? -1. : 1.;
640 yRight = innerYCenter[part][1] + innerRadius[part][1] * sinAngleRight;
641 }
else if (xLeft >= innerXCenter[0][1] && xLeft <= innerXCenter[1][1]) {
648 yRight = innerYCenter[part][1] + innerRadius[part][1] * sinAngleRight;
655 if (xRight != innerXPrev) {
656 float t = (xLeft - innerXPrev) / (xRight - innerXPrev);
657 yRight = innerYRightPrev * (1. -
t) + yRight *
t;
662 sinAngleRight = (yRight - innerYCenter[part][1]) / innerRadius[part][1];
663 cosAngleRight = -(xRight - innerXCenter[part][1]) / innerRadius[part][1];
667 if (outerRadius[part][1] == 0) {
669 cosAngleRight = part ? -1. : 1.;
671 sinAngleRight = sinSegmentAngleRight;
672 cosAngleRight = cosSegmentAngleRight;
674 if (outerRadius[part][0] == 0) {
676 cosAngleLeft = part ? -1. : 1.;
678 yLeft = innerYCenter[part][0] - innerRadius[part][0] * sinAngleLeft;
679 }
else if (xRight >= innerXCenter[0][0] && xRight <= innerXCenter[1][0]) {
683 yLeft = innerYCenter[part][0] - innerRadius[part][0] * sinAngleLeft;
685 if (xLeft != innerXPrev) {
686 float t = (xRight - innerXPrev) / (xLeft - innerXPrev);
687 yLeft = innerYLeftPrev * (1. -
t) + yLeft *
t;
690 sinAngleLeft = -(yLeft - innerYCenter[part][0]) / innerRadius[part][0];
691 cosAngleLeft = -(xLeft - innerXCenter[part][0]) / innerRadius[part][0];
695 gradientPos = (xLeft - gradientStart) / gradientLength;
698 outerXLeft = outerXCenter[part][0] - outerRadius[part][0] * cosAngleLeft;
699 outerYLeft = outerYCenter[part][0] - outerRadius[part][0] * sinAngleLeft;
700 outerXRight = outerXCenter[part][1] - outerRadius[part][1] * cosAngleRight;
701 outerYRight = outerYCenter[part][1] + outerRadius[part][1] * sinAngleRight;
704 while (nextGradientStop <= lastGradientStop && stops.
at(nextGradientStop).first <= gradientPos) {
707 float gradientYRight;
710 gradientX = gradientStart + stops.
at(nextGradientStop).first * gradientLength;
712 float t = (gradientX - innerXPrev) / (xLeft - innerXPrev);
713 gradientYLeft = innerYLeftPrev * (1. -
t) +
t * yLeft;
714 gradientYRight = innerYRightPrev * (1. -
t) +
t * yRight;
716 fillColor = fillColorFromX(gradientX);
738 bool lower = stops.
at(nextGradientStop).first > 0.5f;
739 float dp = lower ?
qMin(0.0f, gradientLength - gradientX - delta) :
qMax(0.0f, delta - gradientX);
740 smoothVertices[
index++].set(gradientX, gradientYRight, fillColor, dp, secondaryLength - gradientYRight - delta,
m_gradient_is_vertical);
743 smoothVertices[
index++].set(gradientX, gradientYRight, borderColor, -0.49f * penWidth * cosAngleRight, 0.49f * penWidth * sinAngleRight,
m_gradient_is_vertical);
744 smoothVertices[
index++].set(gradientX, gradientYLeft, borderColor, -0.49f * penWidth * cosAngleLeft, -0.49f * penWidth * sinAngleLeft,
m_gradient_is_vertical);
746 dp = lower ? delta : -delta;
759 innerXPrev = gradientX;
760 innerYLeftPrev = gradientYLeft;
761 innerYRightPrev = gradientYRight;
767 fillColor = fillColorFromX(xLeft);
788 float dp = part ?
qMin(0.0f, gradientLength - xRight - delta) :
qMax(0.0f, delta - xRight);
792 dp = part ? delta : -delta;
794 smoothVertices[
index++].set(xRight, yRight, borderColor, -0.49f * penWidth * cosAngleRight, 0.49f * penWidth * sinAngleRight,
m_gradient_is_vertical);
795 smoothVertices[
index++].set(xLeft, yLeft, borderColor, -0.49f * penWidth * cosAngleLeft, -0.49f * penWidth * sinAngleLeft,
m_gradient_is_vertical);
796 smoothVertices[
index++].set(outerXRight, outerYRight, borderColor, 0.49f * penWidth * cosAngleRight, -0.49f * penWidth * sinAngleRight,
m_gradient_is_vertical);
797 smoothVertices[
index++].set(outerXLeft, outerYLeft, borderColor, 0.49f * penWidth * cosAngleLeft, 0.49f * penWidth * sinAngleLeft,
m_gradient_is_vertical);
821 innerYLeftPrev = yLeft;
822 innerYRightPrev = yRight;
827 qreal tmp = cosSegmentAngleLeft;
828 cosSegmentAngleLeft = cosSegmentAngleLeft * cosStep[part][0] - sinSegmentAngleLeft * sinStep[part][0];
829 sinSegmentAngleLeft = sinSegmentAngleLeft * cosStep[part][0] + tmp * sinStep[part][0];
832 qreal tmp = cosSegmentAngleRight;
833 cosSegmentAngleRight = cosSegmentAngleRight * cosStep[part][1] - sinSegmentAngleRight * sinStep[part][1];
834 sinSegmentAngleRight = sinSegmentAngleRight * cosStep[part][1] + tmp * sinStep[part][1];
845 Q_ASSERT(innerAATail <= indexCount);
855 Q_ASSERT(outerAATail == indexCount);
863 innerRect.
adjust(1.0f * penWidth, 1.0f * penWidth, -1.0f * penWidth, -1.0f * penWidth);
866 int innerVertexCount = 4 + gradientIntersections * 2;
867 int outerVertexCount = 4;
868 int vertexCount = innerVertexCount;
870 vertexCount += innerVertexCount;
872 vertexCount += outerVertexCount;
874 vertexCount += outerVertexCount;
876 int fillIndexCount = innerVertexCount;
877 int innerAAIndexCount = innerVertexCount * 2 + 2;
878 int borderIndexCount = innerVertexCount * 2 + 2;
879 int outerAAIndexCount = outerVertexCount * 2 + 2;
890 indexCount += fillIndexCount;
892 innerAATail = innerAAHead = indexCount + (innerAAIndexCount >> 1) + 1;
893 indexCount += innerAAIndexCount;
896 borderTail = borderHead = indexCount + (borderIndexCount >> 1) + 1;
897 indexCount += borderIndexCount;
900 outerAATail = outerAAHead = indexCount + (outerAAIndexCount >> 1) + 1;
901 indexCount += outerAAIndexCount;
904 g->allocate(vertexCount, indexCount);
905 vertices =
reinterpret_cast<Vertex *
>(
g->vertexData());
906 memset(vertices, 0, vertexCount * vertexStride);
920 for (
int part = -1; part <= 1; part += 2) {
921 float innerEdge = (part == 1 ? innerEnd : innerStart);
922 float outerEdge = (part == 1 ? outerEnd : outerStart);
923 gradientPos = (innerEdge - innerStart + penWidth) / gradientLength;
925 while (nextGradientStop <= lastGradientStop && stops.
at(nextGradientStop).first <= gradientPos) {
927 float gp = (innerStart - penWidth) + stops.
at(nextGradientStop).first * gradientLength;
951 bool lower = stops.
at(nextGradientStop).first > 0.5f;
952 float dp = lower ?
qMin(0.0f, gradientLength -
gp - delta) :
qMax(0.0f, delta -
gp);
956 smoothVertices[
index++].set(
gp, innerSecondaryEnd, borderColor, (lower ? 0.49f : -0.49f) * penWidth, 0.49f * penWidth,
m_gradient_is_vertical);
957 smoothVertices[
index++].set(
gp, innerSecondaryStart, borderColor, (lower ? 0.49f : -0.49f) * penWidth, -0.49f * penWidth,
m_gradient_is_vertical);
974 if (nextGradientStop == 0) {
976 }
else if (nextGradientStop == stops.
size()) {
981 float t = (gradientPos - prev.first) / (
next.first - prev.first);
1004 float dp = part == 1 ?
qMin(0.0f, gradientLength - innerEdge - delta) :
qMax(0.0f, delta - innerEdge);
1005 smoothVertices[
index++].set(innerEdge, innerSecondaryEnd, fillColor, dp, secondaryLength - innerSecondaryEnd - delta,
m_gradient_is_vertical);
1009 smoothVertices[
index++].set(innerEdge, innerSecondaryEnd, borderColor, 0.49f * penWidth * part, 0.49f * penWidth,
m_gradient_is_vertical);
1010 smoothVertices[
index++].set(innerEdge, innerSecondaryStart, borderColor, 0.49f * penWidth * part, -0.49f * penWidth,
m_gradient_is_vertical);
1011 smoothVertices[
index++].set(outerEdge, outerSecondaryEnd, borderColor, -0.49f * penWidth * part, -0.49f * penWidth,
m_gradient_is_vertical);
1012 smoothVertices[
index++].set(outerEdge, outerSecondaryStart, borderColor, -0.49f * penWidth * part, 0.49f * penWidth,
m_gradient_is_vertical);
1041 Q_ASSERT(innerAATail <= indexCount);
1046 Q_ASSERT(borderTail <= indexCount);
1051 Q_ASSERT(outerAATail == indexCount);