1 | // Copyright (C) 2024 The Qt Company Ltd. |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
3 | |
4 | #include "qquickgenerator_p.h" |
5 | #include "qsvgvisitorimpl_p.h" |
6 | #include "qquicknodeinfo_p.h" |
7 | |
8 | #include <private/qsgcurveprocessor_p.h> |
9 | #include <private/qquickshape_p.h> |
10 | #include <private/qquadpath_p.h> |
11 | #include <private/qquickitem_p.h> |
12 | #include <private/qquickimagebase_p_p.h> |
13 | |
14 | #include <QtCore/qloggingcategory.h> |
15 | |
16 | QT_BEGIN_NAMESPACE |
17 | |
18 | Q_LOGGING_CATEGORY(lcQuickVectorImage, "qt.quick.vectorimage" , QtWarningMsg) |
19 | |
20 | QQuickGenerator::QQuickGenerator(const QString fileName, QQuickVectorImageGenerator::GeneratorFlags flags) |
21 | : m_flags(flags) |
22 | , m_fileName(fileName) |
23 | , m_loader(nullptr) |
24 | { |
25 | } |
26 | |
27 | QQuickGenerator::~QQuickGenerator() |
28 | { |
29 | delete m_loader; |
30 | } |
31 | |
32 | void QQuickGenerator::setGeneratorFlags(QQuickVectorImageGenerator::GeneratorFlags flags) |
33 | { |
34 | m_flags = flags; |
35 | } |
36 | |
37 | QQuickVectorImageGenerator::GeneratorFlags QQuickGenerator::generatorFlags() |
38 | { |
39 | return m_flags; |
40 | } |
41 | |
42 | bool QQuickGenerator::generate() |
43 | { |
44 | m_loader = new QSvgVisitorImpl(m_fileName, this); |
45 | m_generationSucceeded = m_loader->traverse(); |
46 | return m_generationSucceeded; |
47 | } |
48 | |
49 | void QQuickGenerator::optimizePaths(const PathNodeInfo &info, const QRectF &overrideBoundingRect) |
50 | { |
51 | QPainterPath pathCopy = info.painterPath; |
52 | pathCopy.setFillRule(info.fillRule); |
53 | |
54 | const QRectF &boundingRect = overrideBoundingRect.isNull() ? pathCopy.boundingRect() : overrideBoundingRect; |
55 | if (m_flags.testFlag(flag: QQuickVectorImageGenerator::GeneratorFlag::OptimizePaths)) { |
56 | QQuadPath strokePath = QQuadPath::fromPainterPath(path: pathCopy); |
57 | bool fillPathNeededClose; |
58 | QQuadPath fillPath = strokePath.subPathsClosed(didClose: &fillPathNeededClose); |
59 | const bool intersectionsFound = QSGCurveProcessor::solveIntersections(path&: fillPath, removeNestedPaths: false); |
60 | fillPath.addCurvatureData(); |
61 | QSGCurveProcessor::solveOverlaps(path&: fillPath); |
62 | const bool compatibleStrokeAndFill = !fillPathNeededClose && !intersectionsFound; |
63 | |
64 | if (compatibleStrokeAndFill || m_flags.testFlag(flag: QQuickVectorImageGenerator::GeneratorFlag::OutlineStrokeMode)) { |
65 | outputShapePath(info, path: nullptr, quadPath: &fillPath, pathSelector: QQuickVectorImageGenerator::FillAndStroke, boundingRect); |
66 | } else { |
67 | outputShapePath(info, path: nullptr, quadPath: &fillPath, pathSelector: QQuickVectorImageGenerator::FillPath, boundingRect); |
68 | outputShapePath(info, path: nullptr, quadPath: &strokePath, pathSelector: QQuickVectorImageGenerator::StrokePath, boundingRect); |
69 | } |
70 | } else { |
71 | outputShapePath(info, path: &pathCopy, quadPath: nullptr, pathSelector: QQuickVectorImageGenerator::FillAndStroke, boundingRect); |
72 | } |
73 | } |
74 | |
75 | bool QQuickGenerator::isNodeVisible(const NodeInfo &info) |
76 | { |
77 | if (!info.isVisible || !info.isDisplayed) |
78 | return false; |
79 | |
80 | return true; |
81 | } |
82 | |
83 | QT_END_NAMESPACE |
84 | |