Avoid crash in font distancefield computation

A very particular glyph in one particular font would hit an assert in
the glyph path simplification code. It is not clear why this happens,
but at least it should not crash. So instead, this patch makes the
code bail out cleanly, just leaving that glyph empty (invisible).

Task-number: QTBUG-124310
Change-Id: Id3b9c0b03fb82800f029fc718000ee6ca81408f7
Pick-to: 6.7 6.5 6.2 5.15
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
(cherry picked from commit b6f962c87f5084eaf962bfb033b1398f80475120)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Eirik Aavitsland 2024-06-24 11:07:00 +02:00 committed by Qt Cherry-pick Bot
parent 84971028ea
commit 985bc72f22
2 changed files with 18 additions and 5 deletions

View File

@ -312,7 +312,7 @@ private:
void initElements(const QVectorPath &path, const QTransform &matrix);
void removeIntersections();
void connectElements();
bool connectElements();
void fillIndices();
BVHNode *buildTree(Element **elements, int elementCount);
bool intersectNodes(QDataBuffer<Element *> &elements, BVHNode *elementNode, BVHNode *treeNode);
@ -461,12 +461,18 @@ PathSimplifier::PathSimplifier(const QVectorPath &path, QDataBuffer<QPoint> &ver
{
m_points->reset();
m_indices->reset();
bool ok = true;
initElements(path, matrix);
if (!m_elements.isEmpty()) {
removeIntersections();
connectElements();
ok = connectElements();
if (ok)
fillIndices();
}
if (!ok) {
m_points->reset();
m_indices->reset();
}
}
void PathSimplifier::initElements(const QVectorPath &path, const QTransform &matrix)
@ -650,7 +656,7 @@ void PathSimplifier::removeIntersections()
m_bvh.free(); // The bounding volume hierarchy is not needed anymore.
}
void PathSimplifier::connectElements()
bool PathSimplifier::connectElements()
{
Q_ASSERT(!m_elements.isEmpty());
QDataBuffer<Event> events(m_elements.size() * 2);
@ -830,7 +836,8 @@ void PathSimplifier::connectElements()
}
if (!orderedElements.isEmpty()) {
Q_ASSERT((orderedElements.size() & 1) == 0);
if (orderedElements.size() & 1) // Unexpected path structure
return false;
int i = 0;
Element *firstElement = orderedElements.at(0);
if (m_points->at(firstElement->indices[0]) != eventPoint) {
@ -856,6 +863,7 @@ void PathSimplifier::connectElements()
Q_ASSERT((element->next == nullptr) == (element->previous == nullptr));
}
#endif
return true;
}
void PathSimplifier::fillIndices()

View File

@ -474,6 +474,11 @@ static void makeDistanceField(QDistanceFieldData *data, const QPainterPath &path
QDataBuffer<quint32> pathIndices(0);
QDataBuffer<QPoint> pathVertices(0);
qSimplifyPath(path, pathVertices, pathIndices, transform);
if (pathVertices.isEmpty()) {
qCWarning(lcDistanceField) << "Unexpected glyph path structure, bailing out";
memset(data->data, 0, data->nbytes);
return;
}
const qint32 interiorColor = -0x7f80; // 8:8 signed format, -127.5
const qint32 exteriorColor = 0x7f80; // 8:8 signed format, 127.5