From 75a7e642e03660290c7608532997541af751f249 Mon Sep 17 00:00:00 2001 From: ispyisail Date: Thu, 1 Oct 2026 15:21:51 +1300 Subject: [PATCH] Fix bugtracker #266: skip shapes with a nan coordinate in the element editor A symbol with a "nan" or "inf" coordinate (bugtracker #266 had a line with x1="nan" x2="nan") opened with that shape invisible and the view off-centre. Moving the selection then snapped NaN through qRound() to INT_MIN, and saving wrote width="-2147483630", breaking the symbol. The folio already leaves such a shape out (ElementPictureFactory reads it with QET::attributeIsAReal()). Do the same in the element editor, and have --check-elements warn about it. Only geometry attributes are read, so a text whose content is "inf" is not affected. Co-Authored-By: Claude Opus 5.5 --- sources/cli_export.cpp | 13 +++++++++++++ sources/editor/elementscene.cpp | 8 ++++++++ sources/qet.cpp | 28 ++++++++++++++++++++++++++++ sources/qet.h | 1 + 4 files changed, 50 insertions(+) diff --git a/sources/cli_export.cpp b/sources/cli_export.cpp index 2927e6115..c8734cac8 100644 --- a/sources/cli_export.cpp +++ b/sources/cli_export.cpp @@ -529,6 +529,19 @@ int checkOneElement(const QString &path) return 2; } + // QET loads the element but leaves out a shape with a "nan" or "inf" + // coordinate, on the folio and in the element editor. + const QDomNodeList description = root.elementsByTagName("description"); + for (QDomNode n = description.isEmpty() ? QDomNode() + : description.at(0).firstChild() ; + !n.isNull() ; n = n.nextSibling()) { + const QDomElement shape = n.toElement(); + if (!shape.isNull() && QET::hasNonFiniteGeometry(shape)) { + out << "WARN " << path << " (<" << shape.tagName() + << "> with a non-finite coordinate is not drawn)\n"; + return 1; + } + } // Negative dimensions are malformed but QET still loads them; surface as a // warning rather than a failure so this agrees with QET's own loader. if (w < 0 || h < 0) { diff --git a/sources/editor/elementscene.cpp b/sources/editor/elementscene.cpp index d5f0c6fa2..a9b8d85d2 100644 --- a/sources/editor/elementscene.cpp +++ b/sources/editor/elementscene.cpp @@ -1272,6 +1272,14 @@ ElementContent ElementScene::loadContent(const QDomDocument &xml_document) CustomElementPart *cep = nullptr; PartDynamicTextField *pdtf = nullptr; + //A shape with a "nan" or "inf" coordinate is not drawn + //on the folio either; loading it would only break the view + if (QET::hasNonFiniteGeometry(qde)) { + qWarning() << "Element editor: skipped a" << qde.tagName() + << "with a non-finite coordinate"; + continue; + } + if (qde.tagName() == "line") cep = new PartLine (m_element_editor); else if (qde.tagName() == "rect") cep = new PartRectangle (m_element_editor); else if (qde.tagName() == "ellipse") cep = new PartEllipse (m_element_editor); diff --git a/sources/qet.cpp b/sources/qet.cpp index 4e5db31d8..46f0bfb63 100644 --- a/sources/qet.cpp +++ b/sources/qet.cpp @@ -256,6 +256,34 @@ bool QET::attributeIsAReal( return(true); } +/** + @brief QET::hasNonFiniteGeometry + @param shape a shape of an element definition (, , ...) + @return true if one of its coordinates or sizes is "nan" or "inf". + The folio does not draw such a shape (see attributeIsAReal()), and the + element editor cannot show or edit it. +*/ +bool QET::hasNonFiniteGeometry(const QDomElement &shape) +{ + static const QStringList geometry { + "x", "y", "x1", "y1", "x2", "y2", "width", "height", "diameter", + "rx", "ry", "start", "angle", "rotation", "length1", "length2"}; + static const QRegularExpression polygon_point("^[xy][0-9]+$"); + + const QDomNamedNodeMap attributes = shape.attributes(); + for (int i = 0 ; i < attributes.count() ; ++i) + { + const QDomAttr attribute = attributes.item(i).toAttr(); + if (!geometry.contains(attribute.name()) + && !polygon_point.match(attribute.name()).hasMatch()) + continue; + bool ok; + const qreal value = attribute.value().toDouble(&ok); + if (ok && !std::isfinite(value)) return(true); + } + return(false); +} + /** @brief QET::infoFlagIsTrue @see the header comment for why this exists rather than a bare diff --git a/sources/qet.h b/sources/qet.h index 11438d2c2..6901446a0 100644 --- a/sources/qet.h +++ b/sources/qet.h @@ -162,6 +162,7 @@ namespace QET { bool orthogonalProjection(const QPointF &, const QLineF &, QPointF * = nullptr); bool attributeIsAnInteger(const QDomElement &, const QString& , int * = nullptr); bool attributeIsAReal(const QDomElement &, const QString& , qreal * = nullptr); + bool hasNonFiniteGeometry(const QDomElement &); /** Whether an elementInformations flag (auto_num_locked, potential_isolating, exclude_from_bom, ...) counts as "on".