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);
428 d->shapePath =
new QQuickShapePath(
this);
429 d->shapePath->setObjectName(
"rectangleShapeShapePath");
430 d->shapePath->setStrokeWidth(1);
431 d->shapePath->setStrokeColor(QColorConstants::Black);
432 d->shapePath->setFillColor(QColorConstants::White);
433 d->shapePath->setJoinStyle(QQuickShapePath::BevelJoin);
436 connect(d->shapePath, &QQuickShapePath::strokeColorChanged,
this, &QQuickRectangleShape::strokeColorChanged);
437 connect(d->shapePath, &QQuickShapePath::strokeWidthChanged,
this, &QQuickRectangleShape::strokeWidthChanged);
438 connect(d->shapePath, &QQuickShapePath::fillColorChanged,
this, &QQuickRectangleShape::fillColorChanged);
439 connect(d->shapePath, &QQuickShapePath::joinStyleChanged,
this, &QQuickRectangleShape::joinStyleChanged);
440 connect(d->shapePath, &QQuickShapePath::capStyleChanged,
this, &QQuickRectangleShape::capStyleChanged);
441 connect(d->shapePath, &QQuickShapePath::strokeStyleChanged,
this, &QQuickRectangleShape::strokeStyleChanged);
442 connect(d->shapePath, &QQuickShapePath::dashOffsetChanged,
this, &QQuickRectangleShape::dashOffsetChanged);
443 connect(d->shapePath, &QQuickShapePath::dashPatternChanged,
this, &QQuickRectangleShape::dashPatternChanged);
449 d->sp.append(d->shapePath);
451 d->shapePath->setParent(
this);
453 d->extra.value().resourcesList.append(d->shapePath);
457 setPreferredRendererType(CurveRenderer);
600void QQuickRectangleShape::setRadius(
int radius)
602 Q_D(QQuickRectangleShape);
603 if (radius == d->radius)
606 const int oldTopLeftRadius = topLeftRadius();
607 const int oldTopRightRadius = topRightRadius();
608 const int oldBottomRightRadius = bottomRightRadius();
609 const int oldBottomLeftRadius = bottomLeftRadius();
613 emit radiusChanged();
614 if (topLeftRadius() != oldTopLeftRadius)
615 emit topLeftRadiusChanged();
616 if (topRightRadius() != oldTopRightRadius)
617 emit topRightRadiusChanged();
618 if (bottomRightRadius() != oldBottomRightRadius)
619 emit bottomRightRadiusChanged();
620 if (bottomLeftRadius() != oldBottomLeftRadius)
621 emit bottomLeftRadiusChanged();
722void QQuickRectangleShape::setBevel(
bool bevel)
724 Q_D(QQuickRectangleShape);
725 if (bevel == d->bevel)
728 const bool oldTopLeftBevel = hasTopLeftBevel();
729 const bool oldTopRightBevel = hasTopRightBevel();
730 const bool oldBottomRightBevel = hasBottomRightBevel();
731 const bool oldBottomLeftBevel = hasBottomLeftBevel();
736 if (hasTopLeftBevel() != oldTopLeftBevel)
737 emit topLeftBevelChanged();
738 if (hasTopRightBevel() != oldTopRightBevel)
739 emit topRightBevelChanged();
740 if (hasBottomRightBevel() != oldBottomRightBevel)
741 emit bottomRightBevelChanged();
742 if (hasBottomLeftBevel() != oldBottomLeftBevel)
743 emit bottomLeftBevelChanged();
1101void QQuickRectangleShape::updatePolish()
1103 Q_D(QQuickRectangleShape);
1104 const qreal rectWidth = d->width.valueBypassingBindings();
1105 const qreal rectHeight = d->height.valueBypassingBindings();
1107 d->calculateIndependentRadii();
1109 switch (d->borderMode) {
1110 case QQuickRectangleShape::BorderMode::Inside:
1111 d->borderOffset = d->shapePath->strokeWidth() * 0.5;
1113 case QQuickRectangleShape::BorderMode::Middle:
1114 d->borderOffset = 0;
1116 case QQuickRectangleShape::BorderMode::Outside:
1117 d->borderOffset = -d->shapePath->strokeWidth() * 0.5;
1121 switch (d->borderMode) {
1122 case QQuickRectangleShape::BorderMode::Outside:
1123 d->borderRadiusAdjustment = d->shapePath->strokeWidth() * 0.5;
1125 case QQuickRectangleShape::BorderMode::Middle:
1126 d->borderRadiusAdjustment = d->shapePath->strokeWidth();
1129 d->borderRadiusAdjustment = 0;
1133 switch (d->firstVisibleEdge) {
1134 case QQuickRectangleShapePrivate::Edge::Top:
1135 d->shapePath->setStartX(d->effectiveTopLeftRadius + d->borderOffset + d->borderRadiusAdjustment);
1136 d->shapePath->setStartY(d->borderOffset);
1138 case QQuickRectangleShapePrivate::Edge::Right:
1139 d->shapePath->setStartX(rectWidth - d->borderOffset);
1140 d->shapePath->setStartY(d->effectiveTopRightRadius + d->borderOffset + d->borderRadiusAdjustment);
1142 case QQuickRectangleShapePrivate::Edge::Bottom:
1143 d->shapePath->setStartX(rectWidth - d->effectiveBottomRightRadius - d->borderOffset - d->borderRadiusAdjustment);
1144 d->shapePath->setStartY(rectHeight - d->borderOffset);
1146 case QQuickRectangleShapePrivate::Edge::Left:
1147 d->shapePath->setStartX(d->borderOffset);
1148 d->shapePath->setStartY(rectHeight - d->effectiveBottomLeftRadius - d->borderOffset - d->borderRadiusAdjustment);
1154 if (d->topPathLine) {
1155 d->topPathLine->setX(rectWidth - d->effectiveTopRightRadius - d->borderOffset - d->borderRadiusAdjustment);
1156 d->topPathLine->setY(d->borderOffset);
1158 d->topPathMove->setX(rectWidth - d->borderOffset);
1159 d->topPathMove->setY(d->effectiveTopRightRadius + d->borderOffset + d->borderRadiusAdjustment);
1162 if (d->topRightPathArc) {
1163 d->topRightPathArc->setX(rectWidth - d->borderOffset);
1164 d->topRightPathArc->setY(d->effectiveTopRightRadius + d->borderOffset + d->borderRadiusAdjustment);
1165 const bool topRightBevel = hasTopRightBevel();
1166 d->topRightPathArc->setRadiusX(topRightBevel ? 50000 : d->effectiveTopRightRadius + d->borderRadiusAdjustment);
1167 d->topRightPathArc->setRadiusY(topRightBevel ? 50000 : d->effectiveTopRightRadius + d->borderRadiusAdjustment);
1170 if (d->rightPathLine) {
1171 d->rightPathLine->setX(rectWidth - d->borderOffset);
1172 d->rightPathLine->setY(rectHeight - d->effectiveBottomRightRadius - d->borderOffset - d->borderRadiusAdjustment);
1174 d->rightPathMove->setX(rectWidth - d->effectiveBottomRightRadius - d->borderOffset - d->borderRadiusAdjustment);
1175 d->rightPathMove->setY(rectHeight - d->borderOffset);
1178 if (d->bottomRightPathArc) {
1179 d->bottomRightPathArc->setX(rectWidth - d->effectiveBottomRightRadius - d->borderOffset - d->borderRadiusAdjustment);
1180 d->bottomRightPathArc->setY(rectHeight - d->borderOffset);
1181 const bool bottomRightBevel = hasBottomRightBevel();
1182 d->bottomRightPathArc->setRadiusX(bottomRightBevel ? 50000 : d->effectiveBottomRightRadius + d->borderRadiusAdjustment);
1183 d->bottomRightPathArc->setRadiusY(bottomRightBevel ? 50000 : d->effectiveBottomRightRadius + d->borderRadiusAdjustment);
1186 if (d->bottomPathLine) {
1187 d->bottomPathLine->setX(d->effectiveBottomLeftRadius + d->borderOffset + d->borderRadiusAdjustment);
1188 d->bottomPathLine->setY(rectHeight - d->borderOffset);
1190 d->bottomPathMove->setX(d->borderOffset);
1191 d->bottomPathMove->setY(rectHeight - d->effectiveBottomLeftRadius - d->borderOffset - d->borderRadiusAdjustment);
1194 if (d->bottomLeftPathArc) {
1195 d->bottomLeftPathArc->setX(d->borderOffset);
1196 d->bottomLeftPathArc->setY(rectHeight - d->effectiveBottomLeftRadius - d->borderOffset - d->borderRadiusAdjustment);
1197 const bool bottomLeftBevel = hasBottomLeftBevel();
1198 d->bottomLeftPathArc->setRadiusX(bottomLeftBevel ? 50000 : d->effectiveBottomLeftRadius + d->borderRadiusAdjustment);
1199 d->bottomLeftPathArc->setRadiusY(bottomLeftBevel ? 50000 : d->effectiveBottomLeftRadius + d->borderRadiusAdjustment);
1202 if (d->leftPathLine) {
1203 d->leftPathLine->setX(d->borderOffset);
1204 d->leftPathLine->setY(d->effectiveTopLeftRadius + d->borderOffset + d->borderRadiusAdjustment);
1207 if (d->topLeftPathArc) {
1208 d->topLeftPathArc->setX(d->effectiveTopLeftRadius + d->borderOffset + d->borderRadiusAdjustment);
1209 d->topLeftPathArc->setY(d->borderOffset);
1210 const bool topLeftBevel = hasTopLeftBevel();
1211 d->topLeftPathArc->setRadiusX(topLeftBevel ? 50000 : d->effectiveTopLeftRadius + d->borderRadiusAdjustment);
1212 d->topLeftPathArc->setRadiusY(topLeftBevel ? 50000 : d->effectiveTopLeftRadius + d->borderRadiusAdjustment);
1216 QQuickShape::updatePolish();
1218 qCDebug(lcUpdatePolish) <<
"updatePolish:"
1219 <<
"width" << rectWidth
1220 <<
"height" << rectHeight
1221 <<
"borderMode" << d->borderMode
1222 <<
"strokeWidth" << d->shapePath->strokeWidth()
1223 <<
"etlr" << d->effectiveTopLeftRadius
1224 <<
"etrr" << d->effectiveTopRightRadius
1225 <<
"eblr" << d->effectiveBottomLeftRadius
1226 <<
"ebrr" << d->effectiveBottomRightRadius
1227 <<
"borderOffset" << d->borderOffset
1228 <<
"startX" << d->shapePath->startX()
1229 <<
"startY" << d->shapePath->startY();