152void QQuickRectangleShapePrivate::maybeUpdateElements()
154 if (!componentComplete)
157 auto *shapePathPrivate = QQuickShapePathPrivate::get(shapePath);
160 qCDebug(lcMaybeUpdateElements).nospace() <<
"maybeUpdateElements called on "
162 <<
static_cast<
void *>(q_func()) <<
"; deleting and clearing path elements";
163 shapePathPrivate->clearPathElements(QQuickPathPrivate::DeleteElementPolicy::Delete);
165 static const QQuickPathPrivate::ProcessPathPolicy DontProcessPath
166 = QQuickPathPrivate::ProcessPathPolicy::DontProcess;
172 const std::array visibleEdges = {drawTop, drawRight, drawBottom, drawLeft };
174 for (
int currentEdge =
static_cast<
int>(Edge::Top); currentEdge <
static_cast<
int>(Edge::NEdges); ++currentEdge) {
175 const int previousEdge = (currentEdge + 3) % 4;
176 if (!visibleEdges[previousEdge] && visibleEdges[currentEdge]) {
177 startIndex = currentEdge;
182 firstVisibleEdge =
static_cast<Edge>(startIndex);
183 qCDebug(lcMaybeUpdateElements) <<
"firstVisibleEdge:" << startIndex;
185 for (
int i = 0; i < 4; i++) {
186 const int currentEdge = (startIndex + i) % 4;
187 const int nextEdge = (startIndex + i + 1) % 4;
189 switch (
static_cast<Edge>(currentEdge)) {
191 if (visibleEdges[currentEdge]) {
192 topPathLine = createElement<QQuickPathLine>(shapePath,
"topPathLine");
193 shapePathPrivate->appendPathElement(topPathLine, DontProcessPath);
194 topPathMove =
nullptr;
196 topPathLine =
nullptr;
197 topPathMove = createElement<QQuickPathMove>(shapePath,
"topPathMove");
198 shapePathPrivate->appendPathElement(topPathMove, DontProcessPath);
202 if (visibleEdges[currentEdge] && visibleEdges[nextEdge]) {
203 topRightPathArc = createElement<QQuickPathArc>(shapePath,
"topRightPathArc");
204 shapePathPrivate->appendPathElement(topRightPathArc, DontProcessPath);
206 topRightPathArc =
nullptr;
210 if (visibleEdges[currentEdge]) {
211 rightPathLine = createElement<QQuickPathLine>(shapePath,
"rightPathLine");
212 shapePathPrivate->appendPathElement(rightPathLine, DontProcessPath);
213 rightPathMove =
nullptr;
215 rightPathLine =
nullptr;
216 rightPathMove = createElement<QQuickPathMove>(shapePath,
"rightPathMove");
217 shapePathPrivate->appendPathElement(rightPathMove, DontProcessPath);
221 if (visibleEdges[currentEdge] && visibleEdges[nextEdge]) {
222 bottomRightPathArc = createElement<QQuickPathArc>(shapePath,
"bottomRightPathArc");
223 shapePathPrivate->appendPathElement(bottomRightPathArc, DontProcessPath);
225 bottomRightPathArc =
nullptr;
229 if (visibleEdges[currentEdge]) {
230 bottomPathLine = createElement<QQuickPathLine>(shapePath,
"bottomPathLine");
231 shapePathPrivate->appendPathElement(bottomPathLine, DontProcessPath);
232 bottomPathMove =
nullptr;
234 bottomPathLine =
nullptr;
235 bottomPathMove = createElement<QQuickPathMove>(shapePath,
"bottomPathMove");
236 shapePathPrivate->appendPathElement(bottomPathMove, DontProcessPath);
240 if (visibleEdges[currentEdge] && visibleEdges[nextEdge]) {
241 bottomLeftPathArc = createElement<QQuickPathArc>(shapePath,
"bottomLeftPathArc");
242 shapePathPrivate->appendPathElement(bottomLeftPathArc, DontProcessPath);
244 bottomLeftPathArc =
nullptr;
248 if (visibleEdges[currentEdge]) {
249 leftPathLine = createElement<QQuickPathLine>(shapePath,
"leftPathLine");
250 shapePathPrivate->appendPathElement(leftPathLine, DontProcessPath);
252 leftPathLine =
nullptr;
261 if (visibleEdges[currentEdge] && visibleEdges[nextEdge]) {
262 topLeftPathArc = createElement<QQuickPathArc>(shapePath,
"topLeftPathArc");
263 shapePathPrivate->appendPathElement(topLeftPathArc, DontProcessPath);
265 topLeftPathArc =
nullptr;
273 qCDebug(lcMaybeUpdateElements) <<
"about to process path";
274 shapePath->processPath();
275 qCDebug(lcMaybeUpdateElements) <<
"about to call _q_shapePathChanged (i.e. polish and update implicit size)";
276 _q_shapePathChanged();
279void QQuickRectangleShapePrivate::calculateIndependentRadii()
281 Q_Q(
const QQuickRectangleShape);
282 const qreal rectWidth = width.valueBypassingBindings();
283 const qreal rectHeight = height.valueBypassingBindings();
284 const int minDimension = qMin(rectWidth, rectHeight);
285 const int maxRadius = minDimension / 2;
286 const int topLeftRadius = q->topLeftRadius();
287 const int topRightRadius = q->topRightRadius();
288 const int bottomRightRadius = q->bottomRightRadius();
289 const int bottomLeftRadius = q->bottomLeftRadius();
290 const bool mixed = !(radius == topLeftRadius
291 && radius == topRightRadius
292 && radius == bottomLeftRadius
293 && radius == bottomRightRadius);
297 effectiveTopLeftRadius = qMin(topLeftRadius, maxRadius);
298 effectiveTopRightRadius = qMin(topRightRadius, maxRadius);
299 effectiveBottomRightRadius = qMin(bottomRightRadius, maxRadius);
300 effectiveBottomLeftRadius = qMin(bottomLeftRadius, maxRadius);
301 qCDebug(lcCalculateIndependentRadii) <<
"calculateIndependentRadii: using uniform radii of" << radius
302 <<
"width" << rectWidth
303 <<
"height" << rectHeight
304 <<
"minDimension" << minDimension
305 <<
"tlr" << topLeftRadius
306 <<
"etlr" << effectiveTopLeftRadius
307 <<
"trr" << topRightRadius
308 <<
"etrr" << effectiveTopRightRadius
309 <<
"blr" << bottomLeftRadius
310 <<
"eblr" << effectiveBottomLeftRadius
311 <<
"brr" << bottomRightRadius
312 <<
"ebrr" << effectiveBottomRightRadius;
317 qreal topLeftRadiusMin = qMin(minDimension, topLeftRadius);
318 qreal topRightRadiusMin = qMin(minDimension, topRightRadius);
319 qreal bottomLeftRadiusMin = qMin(minDimension, bottomLeftRadius);
320 qreal bottomRightRadiusMin = qMin(minDimension, bottomRightRadius);
323 const qreal topRadii = topLeftRadius + topRightRadius;
325 if (topRadii > rectWidth) {
326 const qreal topLeftRadiusFactor = topLeftRadius / topRadii;
327 const qreal tlr = qRound(rectWidth * topLeftRadiusFactor);
329 topLeftRadiusMin = qMin(topLeftRadiusMin, tlr);
330 topRightRadiusMin = qMin(topRightRadiusMin, rectWidth - tlr);
334 const qreal rightRadii = topRightRadius + bottomRightRadius;
336 if (rightRadii > rectHeight) {
337 const qreal topRightRadiusFactor = topRightRadius / rightRadii;
338 const qreal trr = qRound(rectHeight * topRightRadiusFactor);
340 topRightRadiusMin = qMin(topRightRadiusMin, trr);
341 bottomRightRadiusMin = qMin(bottomRightRadiusMin, rectHeight - trr);
345 const qreal bottomRadii = bottomRightRadius + bottomLeftRadius;
347 if (bottomRadii > rectWidth) {
348 const qreal bottomRightRadiusFactor = bottomRightRadius / bottomRadii;
349 const qreal brr = qRound(rectWidth * bottomRightRadiusFactor);
351 bottomRightRadiusMin = qMin(bottomRightRadiusMin, brr);
352 bottomLeftRadiusMin = qMin(bottomLeftRadiusMin, rectWidth - brr);
356 const qreal leftRadii = bottomLeftRadius + topLeftRadius;
358 if (leftRadii > rectHeight) {
359 const qreal bottomLeftRadiusFactor = bottomLeftRadius / leftRadii;
360 const qreal blr = qRound(rectHeight * bottomLeftRadiusFactor);
362 bottomLeftRadiusMin = qMin(bottomLeftRadiusMin, blr);
363 topLeftRadiusMin = qMin(topLeftRadiusMin, rectHeight - blr);
366 effectiveTopLeftRadius = topLeftRadiusMin;
367 effectiveTopRightRadius = topRightRadiusMin;
368 effectiveBottomLeftRadius = bottomLeftRadiusMin;
369 effectiveBottomRightRadius = bottomRightRadiusMin;
371 qCDebug(lcCalculateIndependentRadii) <<
"calculateIndependentRadii:"
372 <<
"width" << rectWidth
373 <<
"height" << rectHeight
374 <<
"borderMode" << borderMode
375 <<
"strokeWidth" << shapePath->strokeWidth()
376 <<
"minDimension" << minDimension
377 <<
"tlr" << topLeftRadius
378 <<
"etlr" << effectiveTopLeftRadius
379 <<
"trr" << topRightRadius
380 <<
"etrr" << effectiveTopRightRadius
381 <<
"blr" << bottomLeftRadius
382 <<
"eblr" << effectiveBottomLeftRadius
383 <<
"brr" << bottomRightRadius
384 <<
"ebrr" << effectiveBottomRightRadius
385 <<
"borderOffset" << borderOffset
386 <<
"startX" << shapePath->startX()
387 <<
"startY" << shapePath->startY();
422QQuickRectangleShape::QQuickRectangleShape(QQuickItem *parent)
423 : QQuickShape(*(
new QQuickRectangleShapePrivate), parent)
425 Q_D(QQuickRectangleShape);
429 setPreferredRendererType(CurveRenderer);
432 d->shapePath =
new QQuickShapePath(
this);
433 d->shapePath->setObjectName(
"rectangleShapeShapePath");
434 d->shapePath->setStrokeWidth(4);
435 d->shapePath->setStrokeColor(QColorConstants::Black);
436 d->shapePath->setFillColor(QColorConstants::Transparent);
437 d->shapePath->setJoinStyle(QQuickShapePath::BevelJoin);
440 connect(d->shapePath, &QQuickShapePath::strokeColorChanged,
this, &QQuickRectangleShape::strokeColorChanged);
441 connect(d->shapePath, &QQuickShapePath::strokeWidthChanged,
this, &QQuickRectangleShape::strokeWidthChanged);
442 connect(d->shapePath, &QQuickShapePath::fillColorChanged,
this, &QQuickRectangleShape::fillColorChanged);
443 connect(d->shapePath, &QQuickShapePath::joinStyleChanged,
this, &QQuickRectangleShape::joinStyleChanged);
444 connect(d->shapePath, &QQuickShapePath::capStyleChanged,
this, &QQuickRectangleShape::capStyleChanged);
445 connect(d->shapePath, &QQuickShapePath::strokeStyleChanged,
this, &QQuickRectangleShape::strokeStyleChanged);
446 connect(d->shapePath, &QQuickShapePath::dashOffsetChanged,
this, &QQuickRectangleShape::dashOffsetChanged);
447 connect(d->shapePath, &QQuickShapePath::dashPatternChanged,
this, &QQuickRectangleShape::dashPatternChanged);
453 d->sp.append(d->shapePath);
455 d->shapePath->setParent(
this);
457 d->extra.value().resourcesList.append(d->shapePath);
596void QQuickRectangleShape::setRadius(
int radius)
598 Q_D(QQuickRectangleShape);
599 if (radius == d->radius)
602 const int oldTopLeftRadius = topLeftRadius();
603 const int oldTopRightRadius = topRightRadius();
604 const int oldBottomRightRadius = bottomRightRadius();
605 const int oldBottomLeftRadius = bottomLeftRadius();
609 emit radiusChanged();
610 if (topLeftRadius() != oldTopLeftRadius)
611 emit topLeftRadiusChanged();
612 if (topRightRadius() != oldTopRightRadius)
613 emit topRightRadiusChanged();
614 if (bottomRightRadius() != oldBottomRightRadius)
615 emit bottomRightRadiusChanged();
616 if (bottomLeftRadius() != oldBottomLeftRadius)
617 emit bottomLeftRadiusChanged();
718void QQuickRectangleShape::setBevel(
bool bevel)
720 Q_D(QQuickRectangleShape);
721 if (bevel == d->bevel)
724 const bool oldTopLeftBevel = hasTopLeftBevel();
725 const bool oldTopRightBevel = hasTopRightBevel();
726 const bool oldBottomRightBevel = hasBottomRightBevel();
727 const bool oldBottomLeftBevel = hasBottomLeftBevel();
732 if (hasTopLeftBevel() != oldTopLeftBevel)
733 emit topLeftBevelChanged();
734 if (hasTopRightBevel() != oldTopRightBevel)
735 emit topRightBevelChanged();
736 if (hasBottomRightBevel() != oldBottomRightBevel)
737 emit bottomRightBevelChanged();
738 if (hasBottomLeftBevel() != oldBottomLeftBevel)
739 emit bottomLeftBevelChanged();
1089void QQuickRectangleShape::updatePolish()
1091 Q_D(QQuickRectangleShape);
1092 const qreal rectWidth = d->width.valueBypassingBindings();
1093 const qreal rectHeight = d->height.valueBypassingBindings();
1095 d->calculateIndependentRadii();
1097 switch (d->borderMode) {
1098 case QQuickRectangleShape::BorderMode::Inside:
1099 d->borderOffset = d->shapePath->strokeWidth() * 0.5;
1101 case QQuickRectangleShape::BorderMode::Middle:
1102 d->borderOffset = 0;
1104 case QQuickRectangleShape::BorderMode::Outside:
1105 d->borderOffset = -d->shapePath->strokeWidth() * 0.5;
1109 switch (d->borderMode) {
1110 case QQuickRectangleShape::BorderMode::Outside:
1111 d->borderRadiusAdjustment = d->shapePath->strokeWidth() * 0.5;
1113 case QQuickRectangleShape::BorderMode::Middle:
1114 d->borderRadiusAdjustment = d->shapePath->strokeWidth();
1117 d->borderRadiusAdjustment = 0;
1121 switch (d->firstVisibleEdge) {
1122 case QQuickRectangleShapePrivate::Edge::Top:
1123 d->shapePath->setStartX(d->effectiveTopLeftRadius + d->borderOffset + d->borderRadiusAdjustment);
1124 d->shapePath->setStartY(d->borderOffset);
1126 case QQuickRectangleShapePrivate::Edge::Right:
1127 d->shapePath->setStartX(rectWidth - d->borderOffset);
1128 d->shapePath->setStartY(d->effectiveTopRightRadius + d->borderOffset + d->borderRadiusAdjustment);
1130 case QQuickRectangleShapePrivate::Edge::Bottom:
1131 d->shapePath->setStartX(rectWidth - d->effectiveBottomRightRadius - d->borderOffset - d->borderRadiusAdjustment);
1132 d->shapePath->setStartY(rectHeight - d->borderOffset);
1134 case QQuickRectangleShapePrivate::Edge::Left:
1135 d->shapePath->setStartX(d->borderOffset);
1136 d->shapePath->setStartY(rectHeight - d->effectiveBottomLeftRadius - d->borderOffset - d->borderRadiusAdjustment);
1142 if (d->topPathLine) {
1143 d->topPathLine->setX(rectWidth - d->effectiveTopRightRadius - d->borderOffset - d->borderRadiusAdjustment);
1144 d->topPathLine->setY(d->borderOffset);
1146 d->topPathMove->setX(rectWidth - d->borderOffset);
1147 d->topPathMove->setY(d->effectiveTopRightRadius + d->borderOffset + d->borderRadiusAdjustment);
1150 if (d->topRightPathArc) {
1151 d->topRightPathArc->setX(rectWidth - d->borderOffset);
1152 d->topRightPathArc->setY(d->effectiveTopRightRadius + d->borderOffset + d->borderRadiusAdjustment);
1153 d->topRightPathArc->setRadiusX(d->topRightBevel ? 50000 : d->effectiveTopRightRadius + d->borderRadiusAdjustment);
1154 d->topRightPathArc->setRadiusY(d->topRightBevel ? 50000 : d->effectiveTopRightRadius + d->borderRadiusAdjustment);
1157 if (d->rightPathLine) {
1158 d->rightPathLine->setX(rectWidth - d->borderOffset);
1159 d->rightPathLine->setY(rectHeight - d->effectiveBottomRightRadius - d->borderOffset - d->borderRadiusAdjustment);
1161 d->rightPathMove->setX(rectWidth - d->effectiveBottomRightRadius - d->borderOffset - d->borderRadiusAdjustment);
1162 d->rightPathMove->setY(rectHeight - d->borderOffset);
1165 if (d->bottomRightPathArc) {
1166 d->bottomRightPathArc->setX(rectWidth - d->effectiveBottomRightRadius - d->borderOffset - d->borderRadiusAdjustment);
1167 d->bottomRightPathArc->setY(rectHeight - d->borderOffset);
1168 d->bottomRightPathArc->setRadiusX(d->bottomRightBevel ? 50000 : d->effectiveBottomRightRadius + d->borderRadiusAdjustment);
1169 d->bottomRightPathArc->setRadiusY(d->bottomRightBevel ? 50000 : d->effectiveBottomRightRadius + d->borderRadiusAdjustment);
1172 if (d->bottomPathLine) {
1173 d->bottomPathLine->setX(d->effectiveBottomLeftRadius + d->borderOffset + d->borderRadiusAdjustment);
1174 d->bottomPathLine->setY(rectHeight - d->borderOffset);
1176 d->bottomPathMove->setX(d->borderOffset);
1177 d->bottomPathMove->setY(rectHeight - d->effectiveBottomLeftRadius - d->borderOffset - d->borderRadiusAdjustment);
1180 if (d->bottomLeftPathArc) {
1181 d->bottomLeftPathArc->setX(d->borderOffset);
1182 d->bottomLeftPathArc->setY(rectHeight - d->effectiveBottomLeftRadius - d->borderOffset - d->borderRadiusAdjustment);
1183 d->bottomLeftPathArc->setRadiusX(d->bottomLeftBevel ? 50000 : d->effectiveBottomLeftRadius + d->borderRadiusAdjustment);
1184 d->bottomLeftPathArc->setRadiusY(d->bottomLeftBevel ? 50000 : d->effectiveBottomLeftRadius + d->borderRadiusAdjustment);
1187 if (d->leftPathLine) {
1188 d->leftPathLine->setX(d->borderOffset);
1189 d->leftPathLine->setY(d->effectiveTopLeftRadius + d->borderOffset + d->borderRadiusAdjustment);
1192 if (d->topLeftPathArc) {
1193 d->topLeftPathArc->setX(d->effectiveTopLeftRadius + d->borderOffset + d->borderRadiusAdjustment);
1194 d->topLeftPathArc->setY(d->borderOffset);
1195 d->topLeftPathArc->setRadiusX(d->topLeftBevel ? 50000 : d->effectiveTopLeftRadius + d->borderRadiusAdjustment);
1196 d->topLeftPathArc->setRadiusY(d->topLeftBevel ? 50000 : d->effectiveTopLeftRadius + d->borderRadiusAdjustment);
1200 QQuickShape::updatePolish();
1202 qCDebug(lcUpdatePolish) <<
"updatePolish:"
1203 <<
"width" << rectWidth
1204 <<
"height" << rectHeight
1205 <<
"borderMode" << d->borderMode
1206 <<
"strokeWidth" << d->shapePath->strokeWidth()
1207 <<
"etlr" << d->effectiveTopLeftRadius
1208 <<
"etrr" << d->effectiveTopRightRadius
1209 <<
"eblr" << d->effectiveBottomLeftRadius
1210 <<
"ebrr" << d->effectiveBottomRightRadius
1211 <<
"borderOffset" << d->borderOffset
1212 <<
"startX" << d->shapePath->startX()
1213 <<
"startY" << d->shapePath->startY();