153void QQuickRectangleShapePrivate::maybeUpdateElements()
155 if (!componentComplete)
158 auto *shapePathPrivate = QQuickShapePathPrivate::get(shapePath);
161 qCDebug(lcMaybeUpdateElements).nospace() <<
"maybeUpdateElements called on "
163 <<
static_cast<
void *>(q_func()) <<
"; deleting and clearing path elements";
164 shapePathPrivate->clearPathElements(QQuickPathPrivate::DeleteElementPolicy::Delete);
166 static const QQuickPathPrivate::ProcessPathPolicy DontProcessPath
167 = QQuickPathPrivate::ProcessPathPolicy::DontProcess;
173 const std::array visibleEdges = {drawTop, drawRight, drawBottom, drawLeft };
175 for (
int currentEdge =
static_cast<
int>(Edge::Top); currentEdge <
static_cast<
int>(Edge::NEdges); ++currentEdge) {
176 const int previousEdge = (currentEdge + 3) % 4;
177 if (!visibleEdges[previousEdge] && visibleEdges[currentEdge]) {
178 startIndex = currentEdge;
183 firstVisibleEdge =
static_cast<Edge>(startIndex);
184 qCDebug(lcMaybeUpdateElements) <<
"firstVisibleEdge:" << startIndex;
186 for (
int i = 0; i < 4; i++) {
187 const int currentEdge = (startIndex + i) % 4;
188 const int nextEdge = (startIndex + i + 1) % 4;
190 switch (
static_cast<Edge>(currentEdge)) {
192 if (visibleEdges[currentEdge]) {
193 topPathLine = createElement<QQuickPathLine>(shapePath,
"topPathLine");
194 shapePathPrivate->appendPathElement(topPathLine, DontProcessPath);
195 topPathMove =
nullptr;
197 topPathLine =
nullptr;
198 topPathMove = createElement<QQuickPathMove>(shapePath,
"topPathMove");
199 shapePathPrivate->appendPathElement(topPathMove, DontProcessPath);
203 if (visibleEdges[currentEdge] && visibleEdges[nextEdge]) {
204 topRightPathArc = createElement<QQuickPathArc>(shapePath,
"topRightPathArc");
205 shapePathPrivate->appendPathElement(topRightPathArc, DontProcessPath);
207 topRightPathArc =
nullptr;
211 if (visibleEdges[currentEdge]) {
212 rightPathLine = createElement<QQuickPathLine>(shapePath,
"rightPathLine");
213 shapePathPrivate->appendPathElement(rightPathLine, DontProcessPath);
214 rightPathMove =
nullptr;
216 rightPathLine =
nullptr;
217 rightPathMove = createElement<QQuickPathMove>(shapePath,
"rightPathMove");
218 shapePathPrivate->appendPathElement(rightPathMove, DontProcessPath);
222 if (visibleEdges[currentEdge] && visibleEdges[nextEdge]) {
223 bottomRightPathArc = createElement<QQuickPathArc>(shapePath,
"bottomRightPathArc");
224 shapePathPrivate->appendPathElement(bottomRightPathArc, DontProcessPath);
226 bottomRightPathArc =
nullptr;
230 if (visibleEdges[currentEdge]) {
231 bottomPathLine = createElement<QQuickPathLine>(shapePath,
"bottomPathLine");
232 shapePathPrivate->appendPathElement(bottomPathLine, DontProcessPath);
233 bottomPathMove =
nullptr;
235 bottomPathLine =
nullptr;
236 bottomPathMove = createElement<QQuickPathMove>(shapePath,
"bottomPathMove");
237 shapePathPrivate->appendPathElement(bottomPathMove, DontProcessPath);
241 if (visibleEdges[currentEdge] && visibleEdges[nextEdge]) {
242 bottomLeftPathArc = createElement<QQuickPathArc>(shapePath,
"bottomLeftPathArc");
243 shapePathPrivate->appendPathElement(bottomLeftPathArc, DontProcessPath);
245 bottomLeftPathArc =
nullptr;
249 if (visibleEdges[currentEdge]) {
250 leftPathLine = createElement<QQuickPathLine>(shapePath,
"leftPathLine");
251 shapePathPrivate->appendPathElement(leftPathLine, DontProcessPath);
253 leftPathLine =
nullptr;
262 if (visibleEdges[currentEdge] && visibleEdges[nextEdge]) {
263 topLeftPathArc = createElement<QQuickPathArc>(shapePath,
"topLeftPathArc");
264 shapePathPrivate->appendPathElement(topLeftPathArc, DontProcessPath);
266 topLeftPathArc =
nullptr;
274 qCDebug(lcMaybeUpdateElements) <<
"about to process path";
275 shapePath->processPath();
276 qCDebug(lcMaybeUpdateElements) <<
"about to call _q_shapePathChanged (i.e. polish and update implicit size)";
277 _q_shapePathChanged();
280void QQuickRectangleShapePrivate::calculateIndependentRadii()
282 Q_Q(
const QQuickRectangleShape);
283 const qreal rectWidth = width.valueBypassingBindings();
284 const qreal rectHeight = height.valueBypassingBindings();
285 const int minDimension = qMin(rectWidth, rectHeight);
286 const int maxRadius = minDimension / 2;
287 const int topLeftRadius = q->topLeftRadius();
288 const int topRightRadius = q->topRightRadius();
289 const int bottomRightRadius = q->bottomRightRadius();
290 const int bottomLeftRadius = q->bottomLeftRadius();
291 const bool mixed = !(radius == topLeftRadius
292 && radius == topRightRadius
293 && radius == bottomLeftRadius
294 && radius == bottomRightRadius);
298 effectiveTopLeftRadius = qMin(topLeftRadius, maxRadius);
299 effectiveTopRightRadius = qMin(topRightRadius, maxRadius);
300 effectiveBottomRightRadius = qMin(bottomRightRadius, maxRadius);
301 effectiveBottomLeftRadius = qMin(bottomLeftRadius, maxRadius);
302 qCDebug(lcCalculateIndependentRadii) <<
"calculateIndependentRadii: using uniform radii of" << radius
303 <<
"width" << rectWidth
304 <<
"height" << rectHeight
305 <<
"minDimension" << minDimension
306 <<
"tlr" << topLeftRadius
307 <<
"etlr" << effectiveTopLeftRadius
308 <<
"trr" << topRightRadius
309 <<
"etrr" << effectiveTopRightRadius
310 <<
"blr" << bottomLeftRadius
311 <<
"eblr" << effectiveBottomLeftRadius
312 <<
"brr" << bottomRightRadius
313 <<
"ebrr" << effectiveBottomRightRadius;
318 qreal topLeftRadiusMin = qMin(minDimension, topLeftRadius);
319 qreal topRightRadiusMin = qMin(minDimension, topRightRadius);
320 qreal bottomLeftRadiusMin = qMin(minDimension, bottomLeftRadius);
321 qreal bottomRightRadiusMin = qMin(minDimension, bottomRightRadius);
324 const qreal topRadii = topLeftRadius + topRightRadius;
326 if (topRadii > rectWidth) {
327 const qreal topLeftRadiusFactor = topLeftRadius / topRadii;
328 const qreal tlr = qRound(rectWidth * topLeftRadiusFactor);
330 topLeftRadiusMin = qMin(topLeftRadiusMin, tlr);
331 topRightRadiusMin = qMin(topRightRadiusMin, rectWidth - tlr);
335 const qreal rightRadii = topRightRadius + bottomRightRadius;
337 if (rightRadii > rectHeight) {
338 const qreal topRightRadiusFactor = topRightRadius / rightRadii;
339 const qreal trr = qRound(rectHeight * topRightRadiusFactor);
341 topRightRadiusMin = qMin(topRightRadiusMin, trr);
342 bottomRightRadiusMin = qMin(bottomRightRadiusMin, rectHeight - trr);
346 const qreal bottomRadii = bottomRightRadius + bottomLeftRadius;
348 if (bottomRadii > rectWidth) {
349 const qreal bottomRightRadiusFactor = bottomRightRadius / bottomRadii;
350 const qreal brr = qRound(rectWidth * bottomRightRadiusFactor);
352 bottomRightRadiusMin = qMin(bottomRightRadiusMin, brr);
353 bottomLeftRadiusMin = qMin(bottomLeftRadiusMin, rectWidth - brr);
357 const qreal leftRadii = bottomLeftRadius + topLeftRadius;
359 if (leftRadii > rectHeight) {
360 const qreal bottomLeftRadiusFactor = bottomLeftRadius / leftRadii;
361 const qreal blr = qRound(rectHeight * bottomLeftRadiusFactor);
363 bottomLeftRadiusMin = qMin(bottomLeftRadiusMin, blr);
364 topLeftRadiusMin = qMin(topLeftRadiusMin, rectHeight - blr);
367 effectiveTopLeftRadius = topLeftRadiusMin;
368 effectiveTopRightRadius = topRightRadiusMin;
369 effectiveBottomLeftRadius = bottomLeftRadiusMin;
370 effectiveBottomRightRadius = bottomRightRadiusMin;
372 qCDebug(lcCalculateIndependentRadii) <<
"calculateIndependentRadii:"
373 <<
"width" << rectWidth
374 <<
"height" << rectHeight
375 <<
"borderMode" << borderMode
376 <<
"strokeWidth" << shapePath->strokeWidth()
377 <<
"minDimension" << minDimension
378 <<
"tlr" << topLeftRadius
379 <<
"etlr" << effectiveTopLeftRadius
380 <<
"trr" << topRightRadius
381 <<
"etrr" << effectiveTopRightRadius
382 <<
"blr" << bottomLeftRadius
383 <<
"eblr" << effectiveBottomLeftRadius
384 <<
"brr" << bottomRightRadius
385 <<
"ebrr" << effectiveBottomRightRadius
386 <<
"borderOffset" << borderOffset
387 <<
"startX" << shapePath->startX()
388 <<
"startY" << shapePath->startY();
423QQuickRectangleShape::QQuickRectangleShape(QQuickItem *parent)
424 : QQuickShape(*(
new QQuickRectangleShapePrivate), parent)
426 Q_D(QQuickRectangleShape);
429 d->shapePath =
new QQuickShapePath(
this);
430 d->shapePath->setObjectName(
"rectangleShapeShapePath");
431 d->shapePath->setStrokeWidth(1);
432 d->shapePath->setStrokeColor(QColorConstants::Black);
433 d->shapePath->setFillColor(QColorConstants::White);
434 d->shapePath->setJoinStyle(QQuickShapePath::BevelJoin);
437 connect(d->shapePath, &QQuickShapePath::strokeColorChanged,
this, &QQuickRectangleShape::strokeColorChanged);
438 connect(d->shapePath, &QQuickShapePath::strokeWidthChanged,
this, &QQuickRectangleShape::strokeWidthChanged);
439 connect(d->shapePath, &QQuickShapePath::fillColorChanged,
this, &QQuickRectangleShape::fillColorChanged);
440 connect(d->shapePath, &QQuickShapePath::joinStyleChanged,
this, &QQuickRectangleShape::joinStyleChanged);
441 connect(d->shapePath, &QQuickShapePath::capStyleChanged,
this, &QQuickRectangleShape::capStyleChanged);
442 connect(d->shapePath, &QQuickShapePath::strokeStyleChanged,
this, &QQuickRectangleShape::strokeStyleChanged);
443 connect(d->shapePath, &QQuickShapePath::dashOffsetChanged,
this, &QQuickRectangleShape::dashOffsetChanged);
444 connect(d->shapePath, &QQuickShapePath::dashPatternChanged,
this, &QQuickRectangleShape::dashPatternChanged);
445 connect(d->shapePath, &QQuickShapePath::fillItemChanged,
this, &QQuickRectangleShape::fillItemChanged);
446 connect(d->shapePath, &QQuickShapePath::fillGradientChanged,
this, &QQuickRectangleShape::fillGradientChanged);
451 d->sp.append(d->shapePath);
453 d->shapePath->setParent(
this);
455 d->extra.value().resourcesList.append(d->shapePath);
459 setPreferredRendererType(CurveRenderer);
602void QQuickRectangleShape::setRadius(
int radius)
604 Q_D(QQuickRectangleShape);
605 if (radius == d->radius)
608 const int oldTopLeftRadius = topLeftRadius();
609 const int oldTopRightRadius = topRightRadius();
610 const int oldBottomRightRadius = bottomRightRadius();
611 const int oldBottomLeftRadius = bottomLeftRadius();
615 emit radiusChanged();
616 if (topLeftRadius() != oldTopLeftRadius)
617 emit topLeftRadiusChanged();
618 if (topRightRadius() != oldTopRightRadius)
619 emit topRightRadiusChanged();
620 if (bottomRightRadius() != oldBottomRightRadius)
621 emit bottomRightRadiusChanged();
622 if (bottomLeftRadius() != oldBottomLeftRadius)
623 emit bottomLeftRadiusChanged();
724void QQuickRectangleShape::setBevel(
bool bevel)
726 Q_D(QQuickRectangleShape);
727 if (bevel == d->bevel)
730 const bool oldTopLeftBevel = hasTopLeftBevel();
731 const bool oldTopRightBevel = hasTopRightBevel();
732 const bool oldBottomRightBevel = hasBottomRightBevel();
733 const bool oldBottomLeftBevel = hasBottomLeftBevel();
738 if (hasTopLeftBevel() != oldTopLeftBevel)
739 emit topLeftBevelChanged();
740 if (hasTopRightBevel() != oldTopRightBevel)
741 emit topRightBevelChanged();
742 if (hasBottomRightBevel() != oldBottomRightBevel)
743 emit bottomRightBevelChanged();
744 if (hasBottomLeftBevel() != oldBottomLeftBevel)
745 emit bottomLeftBevelChanged();
1115void QQuickRectangleShape::updatePolish()
1117 Q_D(QQuickRectangleShape);
1118 const qreal rectWidth = d->width.valueBypassingBindings();
1119 const qreal rectHeight = d->height.valueBypassingBindings();
1121 d->calculateIndependentRadii();
1123 switch (d->borderMode) {
1124 case QQuickRectangleShape::BorderMode::Inside:
1125 d->borderOffset = d->shapePath->strokeWidth() * 0.5;
1127 case QQuickRectangleShape::BorderMode::Middle:
1128 d->borderOffset = 0;
1130 case QQuickRectangleShape::BorderMode::Outside:
1131 d->borderOffset = -d->shapePath->strokeWidth() * 0.5;
1135 switch (d->borderMode) {
1136 case QQuickRectangleShape::BorderMode::Outside:
1137 d->borderRadiusAdjustment = d->shapePath->strokeWidth() * 0.5;
1139 case QQuickRectangleShape::BorderMode::Middle:
1140 d->borderRadiusAdjustment = d->shapePath->strokeWidth();
1143 d->borderRadiusAdjustment = 0;
1147 switch (d->firstVisibleEdge) {
1148 case QQuickRectangleShapePrivate::Edge::Top:
1149 d->shapePath->setStartX(d->effectiveTopLeftRadius + d->borderOffset + d->borderRadiusAdjustment);
1150 d->shapePath->setStartY(d->borderOffset);
1152 case QQuickRectangleShapePrivate::Edge::Right:
1153 d->shapePath->setStartX(rectWidth - d->borderOffset);
1154 d->shapePath->setStartY(d->effectiveTopRightRadius + d->borderOffset + d->borderRadiusAdjustment);
1156 case QQuickRectangleShapePrivate::Edge::Bottom:
1157 d->shapePath->setStartX(rectWidth - d->effectiveBottomRightRadius - d->borderOffset - d->borderRadiusAdjustment);
1158 d->shapePath->setStartY(rectHeight - d->borderOffset);
1160 case QQuickRectangleShapePrivate::Edge::Left:
1161 d->shapePath->setStartX(d->borderOffset);
1162 d->shapePath->setStartY(rectHeight - d->effectiveBottomLeftRadius - d->borderOffset - d->borderRadiusAdjustment);
1168 if (d->topPathLine) {
1169 d->topPathLine->setX(rectWidth - d->effectiveTopRightRadius - d->borderOffset - d->borderRadiusAdjustment);
1170 d->topPathLine->setY(d->borderOffset);
1172 d->topPathMove->setX(rectWidth - d->borderOffset);
1173 d->topPathMove->setY(d->effectiveTopRightRadius + d->borderOffset + d->borderRadiusAdjustment);
1176 if (d->topRightPathArc) {
1177 d->topRightPathArc->setX(rectWidth - d->borderOffset);
1178 d->topRightPathArc->setY(d->effectiveTopRightRadius + d->borderOffset + d->borderRadiusAdjustment);
1179 const bool topRightBevel = hasTopRightBevel();
1180 d->topRightPathArc->setRadiusX(topRightBevel ? 50000 : d->effectiveTopRightRadius + d->borderRadiusAdjustment);
1181 d->topRightPathArc->setRadiusY(topRightBevel ? 50000 : d->effectiveTopRightRadius + d->borderRadiusAdjustment);
1184 if (d->rightPathLine) {
1185 d->rightPathLine->setX(rectWidth - d->borderOffset);
1186 d->rightPathLine->setY(rectHeight - d->effectiveBottomRightRadius - d->borderOffset - d->borderRadiusAdjustment);
1188 d->rightPathMove->setX(rectWidth - d->effectiveBottomRightRadius - d->borderOffset - d->borderRadiusAdjustment);
1189 d->rightPathMove->setY(rectHeight - d->borderOffset);
1192 if (d->bottomRightPathArc) {
1193 d->bottomRightPathArc->setX(rectWidth - d->effectiveBottomRightRadius - d->borderOffset - d->borderRadiusAdjustment);
1194 d->bottomRightPathArc->setY(rectHeight - d->borderOffset);
1195 const bool bottomRightBevel = hasBottomRightBevel();
1196 d->bottomRightPathArc->setRadiusX(bottomRightBevel ? 50000 : d->effectiveBottomRightRadius + d->borderRadiusAdjustment);
1197 d->bottomRightPathArc->setRadiusY(bottomRightBevel ? 50000 : d->effectiveBottomRightRadius + d->borderRadiusAdjustment);
1200 if (d->bottomPathLine) {
1201 d->bottomPathLine->setX(d->effectiveBottomLeftRadius + d->borderOffset + d->borderRadiusAdjustment);
1202 d->bottomPathLine->setY(rectHeight - d->borderOffset);
1204 d->bottomPathMove->setX(d->borderOffset);
1205 d->bottomPathMove->setY(rectHeight - d->effectiveBottomLeftRadius - d->borderOffset - d->borderRadiusAdjustment);
1208 if (d->bottomLeftPathArc) {
1209 d->bottomLeftPathArc->setX(d->borderOffset);
1210 d->bottomLeftPathArc->setY(rectHeight - d->effectiveBottomLeftRadius - d->borderOffset - d->borderRadiusAdjustment);
1211 const bool bottomLeftBevel = hasBottomLeftBevel();
1212 d->bottomLeftPathArc->setRadiusX(bottomLeftBevel ? 50000 : d->effectiveBottomLeftRadius + d->borderRadiusAdjustment);
1213 d->bottomLeftPathArc->setRadiusY(bottomLeftBevel ? 50000 : d->effectiveBottomLeftRadius + d->borderRadiusAdjustment);
1216 if (d->leftPathLine) {
1217 d->leftPathLine->setX(d->borderOffset);
1218 d->leftPathLine->setY(d->effectiveTopLeftRadius + d->borderOffset + d->borderRadiusAdjustment);
1221 if (d->topLeftPathArc) {
1222 d->topLeftPathArc->setX(d->effectiveTopLeftRadius + d->borderOffset + d->borderRadiusAdjustment);
1223 d->topLeftPathArc->setY(d->borderOffset);
1224 const bool topLeftBevel = hasTopLeftBevel();
1225 d->topLeftPathArc->setRadiusX(topLeftBevel ? 50000 : d->effectiveTopLeftRadius + d->borderRadiusAdjustment);
1226 d->topLeftPathArc->setRadiusY(topLeftBevel ? 50000 : d->effectiveTopLeftRadius + d->borderRadiusAdjustment);
1230 QQuickShape::updatePolish();
1232 qCDebug(lcUpdatePolish) <<
"updatePolish:"
1233 <<
"width" << rectWidth
1234 <<
"height" << rectHeight
1235 <<
"borderMode" << d->borderMode
1236 <<
"strokeWidth" << d->shapePath->strokeWidth()
1237 <<
"etlr" << d->effectiveTopLeftRadius
1238 <<
"etrr" << d->effectiveTopRightRadius
1239 <<
"eblr" << d->effectiveBottomLeftRadius
1240 <<
"ebrr" << d->effectiveBottomRightRadius
1241 <<
"borderOffset" << d->borderOffset
1242 <<
"startX" << d->shapePath->startX()
1243 <<
"startY" << d->shapePath->startY();