34 Commits
Author SHA1 Message Date
Matthias RauterandQt Cherry-pick Bot 07e1268235 Extend benchmark for rendering
With the exended features it is important to have an eye on rendering
performance. Both rendering on a QPicture and QImage are tested to
isolate the processing in QSvgRenderer and QPainter.

Tested are standard path drawing with tiger.svg as well as elements that
operate on pixel buffers, that are filters, mask and the correct
implementation of group opacity.

Manually cherry-picked from 90114ae5da84714b5c5ec88151a3bf133363c43f

Task-number: QTBUG-135075
Change-Id: I2a877c72f6000725f1b4372a04184c26e5c74243
Reviewed-by: Hatem ElKharashy <hatem.elkharashy@qt.io>
Reviewed-by: Robert Löhning <robert.loehning@qt.io>
(cherry picked from commit c6f5af72db2021ac160ddbb5669ca51109b7a5c3)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
2025-05-16 16:22:21 +00:00
Matthias RauterandQt Cherry-pick Bot 3532ad641b Port benchmark to cmake
Task-number: QTBUG-135075
Change-Id: Id580c50a889ab04a7b710fb84493d9b40c66b247
Reviewed-by: Hatem ElKharashy <hatem.elkharashy@qt.io>
(cherry picked from commit e7a313f0a7349839d4a6966b233f07014d478e9b)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
(cherry picked from commit 2e59dd89b90d119a6cef20ea5d2f675a0b1635e7)
2025-03-28 17:51:06 +00:00
Matthias RauterandQt Cherry-pick Bot 3773e1392c Use qDecodeDataUrl to parse image from data url
The old code scanned for the "base64," token from the end
(lastIndexOf()), even though the token appears near the beginning of a
data: URL and cannot repeat. This means we scan potentially large
amounts of (base-64-encoded) image data without purpose.

Instead of using indexOf(), port to QtCore's qDecodeDataUrl(), which
also takes non-base64-encoded data into account. The disadvantage is
that this now requires several recodings (QString -> QUrl -> QString ->
QByteArray). Created QTBUG-134665 to ask for a faster implementation.

Pick-to: 6.5
Task-number: QTBUG-134665
Change-Id: I59e7039be44cd2e0a1a97d78db203a330196d13f
Reviewed-by: Hatem ElKharashy <hatem.elkharashy@qt.io>
Reviewed-by: Marc Mutz <marc.mutz@qt.io>
(cherry picked from commit b65af14a2599cd7ad155bd254db9e86d795505d3)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
(cherry picked from commit aac71446db072ee43a9efc9852c261daefb4de80)
2025-03-27 10:40:52 +00:00
Matthias Rauter 2e35b700f3 Correct the calculation of the buffer sizes in filter
There were various issues in the calculation of the buffer size in the
filter. This patch corrects many missconceptions and incorrect fallback
values that were in the previous implementation.

Some function names have been changed to better reflect their role.

Task-number: QTBUG-126486
Pick-to: 6.7
Change-Id: Iebc10f71b5743cac40064200b3be9388ecb32e46
Reviewed-by: Hatem ElKharashy <hatem.elkharashy@qt.io>
(cherry picked from commit 186a8fbcb76336ef294ac60571160b7a5f8e24b3)
2024-08-09 09:35:41 +02:00
Matthias RauterandQt Cherry-pick Bot 5ee8905616 Add assert to silence code checker and remove pointers
The code checker complained about a possible division by 0, however,
which is not possible. This patch adds an assert to indicate that this
was thought about.

It further modernizes a lambda function by not using pointers and adding
const where possible. Amends e7c3e2c2f73348def6a46b76c3d84dc6e24f6502

Pick-to: 6.7
Change-Id: I6119636462a9bb5d3029e2e135922a02ab0bc96e
Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io>
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
(cherry picked from commit 90ff35d6929e32df166340301e14a694013b46fb)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
2024-08-08 18:56:20 +00:00
Matthias RauterandQt Cherry-pick Bot 2b0684f3fb Avoid int overflow in multiplication
Coverity Scan complained about the product of two integers that
might overflow as it is used in context with unit64_t. To
circumvent this issue the int types are converted to uint64_t
before multiplication.

Coverity-Id: 466430
Pick-to: 6.7
Change-Id: Iaf5dbb32e1d5087052a8fa2e1f7640617b1777b3
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
(cherry picked from commit f9a069cae1533c6541c0f5e2e8fd25d53c5747c0)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
2024-07-15 07:43:30 +00:00
Matthias Rauter b827662949 Improve Gaussian blur filter performance
The Gaussian blur filter is based on a repeated application of the box
blur filter. This filter requires a large amount of average pixel values
in a subarea. The old implementation used a naive implementation that
scales with O(n*r²) where n is the pixel number and r the blur radius.
This is a considerable problem and can take the majority of the render
duration of an svg image. The blur radius r often grows with the zoom
factor and can thus become very large.

The algorithm can be optimized to O(n) with some smart buffering of pixel
value sums. Then the algorithm is independent of the blur radius and
zooming has a much lower impact on the rendering duration.

This patch applies the optimization and the Gaussian blur filter now
scales with O(n). With help from Jan-Arve Sæther.

Some simple tests with the old and new code showed the following render
duration (only the application of the filter):

Test           |   old version    |   new version
small picture  |       0.5 ms     |      0.2 ms
large picture  |       330 ms     |      135 ms
large radius   |     20700 ms     |      160 ms

Pick-to: 6.7
Change-Id: I886965efe7121e7afea9aaca657aeceb8ece7c63
Reviewed-by: Jan Arve Sæther <jan-arve.saether@qt.io>
(cherry picked from commit e7c3e2c2f73348def6a46b76c3d84dc6e24f6502)
2024-07-09 16:05:17 +02:00
Matthias RauterandQt Cherry-pick Bot 72ab071e8b Remove duplicated code with new function
Pick-to: 6.7
Change-Id: I68a04953a0fb3ed003710ab1ae7896c153ff2bd6
Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io>
(cherry picked from commit 4db03802fc75c3f25bf1ed541eece5651e9987c2)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
2024-07-02 12:55:13 +00:00
Matthias RauterandQt Cherry-pick Bot cd7b92243b Also accept href in addtion to xlink:href
Since Svg 2.0 image elements expect href instead of xlink:href. With
this patch QtSvg also accepts href if the options do not limit the
features to 1.2 tiny.

This allows to view the same svg in browsers and the Qt svgviewer which
makes debugging possible.

Pick-to: 6.7
Change-Id: I6601993304e8b2518acc2b274ad7f7caf906ed82
Reviewed-by: Hatem ElKharashy <hatem.elkharashy@qt.io>
Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io>
(cherry picked from commit 9d56eba7d5a36197055bbe2b0d15cab49f4c6989)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
2024-06-18 10:46:31 +00:00
Matthias RauterandQt Cherry-pick Bot 89d0cf3b06 Revert style recursive after it has been applied recursive
The mask and pattern node have a drawing hierarchy that does not match
the document hierarchy, as they can be called from any point in the
document.

Therefore we have to reconstruct the painter state recursivly (see
commit 247453e7d5). However, we also have
to revert the style recursivly which is done in this patch.

Pick-to: 6.7
Change-Id: I939595182674f8aed6b265bc633476e78807727c
Reviewed-by: Hatem ElKharashy <hatem.elkharashy@qt.io>
(cherry picked from commit cffa99bdffbf31820c7ad29e9903966be2194759)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
2024-06-18 10:46:31 +00:00
Matthias RauterandQt Cherry-pick Bot c23b301ebb Do not try to optimize filter size
In the original filter patch I tried to be smart and reduce the buffer
size by calculating the required rectangle and limiting the buffer to
it.

This does not work with a pipeline of multiple filters, as it cannot be
predicted what the following filters need. Therefore this change
removes the respective code.

Pick-to: 6.7
Change-Id: If765f9b5e4fc8db186e2c2dba7c16e5517bec6e8
Reviewed-by: Hatem ElKharashy <hatem.elkharashy@qt.io>
Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io>
(cherry picked from commit bc9b5de9f9a0f1da2ad82ad861ccfb1256a8b41c)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
2024-06-11 14:59:44 +00:00
Matthias RauterandQt Cherry-pick Bot 51db8ff9ab Set flood-opacity even when flood-color is missing
Pick-to: 6.7
Change-Id: I66b01f1239fd3a58f720601c928d3abbbaae20ec
Reviewed-by: Hatem ElKharashy <hatem.elkharashy@qt.io>
(cherry picked from commit f82beb17059afa2ef2de144f6e67f717dcab50c8)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
2024-06-11 11:41:53 +00:00
Matthias Rauter ba44960d8f Fix transformed Gaussian blur filter
The Gaussian blur filter is applied after the item is transformed to
ensure that the effect is resolved well and no single pixels can be
seen.

However, this leads to errors when the item is rotated or skewed,
since the gaussian blur effect has to be applied in the local
coordinate system (see stdDeviation description in standard).

This patch decomposes the transformation matrix into a scaling and a
remaining component. The blur effect is applied in the local but
scaled coordinate system to ensure a high resolution of the effect.
The result is then transformed with the remaining component of the
transformation matrix to get the final fitered item.

Pick-to: 6.7
Change-Id: I48f1837e5f34fef3bccf7d537a458bed857067b0
Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io>
2024-05-27 09:33:15 +02:00
Matthias Rauter 9d189e7ccd Remove autogenerated code to recognize supported features
This function is rarely called so the performance improvement
from the autogenerated code is not worth the difficult to
maintain code.

Change-Id: I825e41180577d0245d41a13761d5823ef54941fe
Reviewed-by: Hatem ElKharashy <hatem.elkharashy@qt.io>
2024-05-13 09:15:58 +02:00
Matthias Rauter c58e6c9f27 Fix filter offset with transformations
There was a missconception in the calculation of localFilterBoundingBox
that lead to a rendering error of filter elements if there was a
transformation set.

The bounding box is always positioned relative to the node that the
filter is applied to. This patch corrects the calculation of the
bounding box.

Fixes: QTBUG-123138
Change-Id: I9ed5ed3a2bb55bc61002cd0c506c1f2310962156
Reviewed-by: Hatem ElKharashy <hatem.elkharashy@qt.io>
Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io>
2024-05-08 13:44:27 +02:00
Matthias Rauter bcfbccf327 Consider the % symbol for the filter size
The % symbol was not parsed in the filter size, leading to filter sizes
100 times too big. This is corrected by considering the % symbol during
parsing.

Fixes: QTBUG-124287
Pick-to: 6.7
Change-Id: I517df1ef989890d0e6ed62e9bd7f91575af8e691
Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io>
Reviewed-by: Hatem ElKharashy <hatem.elkharashy@qt.io>
2024-04-19 08:31:26 +02:00
Matthias Rauter 0e21fd0ee2 Propagate states correctly in <pattern> element
There was a missconseption about the propagation of states in the
<pattern>, similar as in the <mask>, that was partially responsible
for QTBUG-123010.

This change applies the correction to the <pattern> element.

Pick-to: 6.7 6.7.0
Change-Id: I63bef1cef287b9d94133b299c9f68665dc1ac02c
Reviewed-by: Hatem ElKharashy <hatem.elkharashy@qt.io>
2024-03-15 16:35:09 +01:00
Matthias Rauter 247453e7d5 Enable <use> elements in <mask> and propagate state to mask children
The use node could not be created within a mask due to a missing entry
in a switch statement. This is corrected with this patch.

The mask element was implemented such that states do not propagate to
it's children. This is not correct and states are propagated correctly
with this patch.

Pick-to: 6.7 6.7.0
Fixes: QTBUG-123010
Change-Id: I4aab070c73b2e8a9bd0c642c70ea5b28eaef3416
Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io>
2024-03-15 16:35:04 +01:00
Matthias RauterandEirik Aavitsland eb1ff0e19e Fix a crash when SVG files are loaded recursively
This bug was triggered by a test in the resvg:
structure/image/recursive-2.svg

The issue is solved by not loading SVG files in the image element.
This is in line with SVG 1.2 Tiny: "SVG Tiny 1.2 does not allow an
SVG document to be referenced by the 'image' element", see:
https://www.w3.org/TR/SVGTiny12/struct.html#ImageElement

The old behavior can be reproduced by enabling trusted source mode,
currently only by available by setting the environment variable
QT_SVG_ASSUME_TRUSTED_SOURCE. In that case, there is no protection
against recursively loaded SVG files.

Pick-to: 6.7 6.6 6.5
Change-Id: I08a4842cd36d183448b1ad1c19fbfca6339a3dd6
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
2024-02-20 10:35:01 +01:00
Matthias Rauter a062cc96ab Don't parse symbol element if Tiny12FeaturesOnly is set
Pick-to: 6.7
Change-Id: If41625419766ce1f0dafa9499e5b75425ca794d0
Reviewed-by: Hatem ElKharashy <hatem.elkharashy@qt.io>
Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io>
2024-02-12 19:14:14 +01:00
Matthias Rauter a79e790120 Fix some mistakes in the documentation
Pick-to: 6.7
Change-Id: If322957c3dd8222b2c7f0aa9916cd9fb695c2c22
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
2024-01-26 10:11:49 +01:00
Matthias Rauter fd8224cdb8 Fix a bug where description and title were rendered
Parts of SvgHandler wrongfully claim that description and title are
handled. However, this is not the case and the current element is not
invalidated. This in turn leads to the acceptance of the text in the
respective element which is added to the parent and in case of text
rendered.

This patch removes the claim that these elements are handled which is
enough to fix the bug.

Fixes: QTBUG-120233
Pick-to: 6.7
Change-Id: I60eab19c96a556647c3e96526f7d1135cbdac91e
Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
2024-01-24 10:01:13 +01:00
Matthias Rauter 122c53f4e0 Add documentation for extended SVG features
Pick-to: 6.7
Fixes: QTBUG-120223
Change-Id: I72c76ba50a889b8b74de598865c151fd7b2b81e7
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
2024-01-17 12:43:31 +01:00
Matthias Rauter 35faa32a04 Remove nodeStringList in favor of QSvgNode::typeName()
When adding node types (e.g. mask) the QSvgStyleSelector_nodeString
was not updated. With this patch we use QSvgNode::typeName()
instead. The return values were adjusted to ensure that we are
backwards compatible.

This list is required to make CSS work properly. The missing strings
triggered a crash when testing the resvg test suit. This patch fixes
the crash.

Pick-to: 6.7
Change-Id: Ia715664c87d531b125627554129b8e4d930ced44
Reviewed-by: Paul Olav Tvete <paul.tvete@qt.io>
2024-01-06 11:17:30 +01:00
Matthias Rauter 604fe97dd1 Fix a crash when SVG filters fail
This bug was triggered by a test in the resvg test suit:
filters/filters/in=BackgroundAlpha.svg

The patch further includes a small optimization: The sourceAlpha
filter buffer is only created on request.

Pick-to: 6.7
Change-Id: I208d43c54f07d530f476b459f30c1b8aa62c2018
Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io>
2024-01-06 11:17:10 +01:00
Matthias RauterandVolker Hilsheimer e4b4153383 Add filter attribute/element and various filter primitives
The primitive filters that can be used to build <filter> are:
* feMerge
* feColorMatrix
* feGaussianBlur
* feOffset
* feComposite
* feFlood

[ChangeLog] Added support for the <filter> element to QtSvg. The most
important but not all filter primitves are supported: feMerge,
feColorMatrix, feGaussianBlur, feOffset, feComposite, feFlood.

Task-number: QTBUG-115223
Task-number: QTBUG-115541
Task-number: QTBUG-115548
Task-number: QTBUG-115549
Task-number: QTBUG-115550
Task-number: QTBUG-115551
Change-Id: I01ab0477cc5fe13dd03a094fc21028c182b62f5e
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io>
2023-12-07 12:03:35 +01:00
Matthias Rauter 5bfaae976f Remove unnecessary and potentially harmfull code from QSvgHandler
This is a correction for 534d072fe9.
The opportunity was used to change parseLength(...) to accept a pointer
to type instead of a reference, to highlight that it will be changed.

Change-Id: I72a43dd6339fe61094199f4580cf7dc54129afa0
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
2023-11-24 15:39:46 +01:00
Matthias Rauter ddd4c910b4 Fix an issue in the svg parser leading to use after free
The mask, marker and symbol patches,
534d072fe9 and
29b848e9ac wrongly converted
a QStringView to a QString.
This patch removes the conversion.

Change-Id: I551863da1d905d71f56f7ff126fa1fccd09083de
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
2023-11-24 12:19:29 +01:00
Matthias Rauter 55e317db51 Fix a use after free introduced by a previous patch
Commit 5720e42469 introduced
a bug where a deleted svg node was accessed.
This patch fixes the issue.

Change-Id: Iab225bc158130586199289b0cf69832fa25a222c
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
2023-11-24 12:19:29 +01:00
Matthias Rauter 5720e42469 Replace a Q_ASSERT with an if statement in QSvgHander
Sometimes we return a nullptr in QSvgHandler, in case parsing
might have been dangerous. A Q_ASSERT was not in line with this
strategy and was replaced in favor of an if statement.

Change-Id: I86a387c2b1dfb551316df781791c77df4fb4e315
Reviewed-by: Paul Olav Tvete <paul.tvete@qt.io>
2023-11-23 15:25:51 +01:00
Matthias Rauter 534d072fe9 Add symbol and marker to QSvg
The QSvgHandler can now parse the symbol and marker element and the
marker-start, marker-mid and marker-end attributes of paths, polygons,
polylines and lines.

[ChangeLog] Added <symbol> and <marker> to the supported elements of
QtSvg.

Task-number: QTBUG-115223
Task-number: QTBUG-115545
Task-number: QTBUG-115546
Change-Id: I1a615e9977bd8ddd19d7711651a0988c0f41f83f
Reviewed-by: Paul Olav Tvete <paul.tvete@qt.io>
2023-11-23 10:09:14 +01:00
Matthias Rauter 29b848e9ac Add mask element and mask attribute to QSvg
The QSvgHandler can now parse the mask element and the mask attribute of
all other elements. If a mask is set on an element, the rendering is
redirected into a buffer and the mask is applied to this buffer before
it is drawn onto the canvas.

Task-number: QTBUG-115223
Task-number: QTBUG-115543
Change-Id: I14b2966f7b9ee2717c8f29f9090f986c2a968c3a
Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io>
2023-11-20 14:35:38 +01:00
Matthias Rauter 101982c650 Refactor QSvgNode draw architecture
In preparation for the mask and filter tag, the draw infrastructure
is changed from a C-style macro to virtual member functions.
Commonalities between all nodes are encapsulated in the draw()
function. The actual draw command is encapsulated in the
drawCommand() function that is called by the draw function along with
some common code for setting styles, masking, filtering and
benchmarking.

Change-Id: I19aa79be9500eff6faa6b6f12fd13d6c0fe2d0ad
Reviewed-by: Paul Olav Tvete <paul.tvete@qt.io>
2023-11-03 10:22:18 +01:00
Matthias RauterandHatem ElKharashy a7a08b157e Add selectable featureSet to all QSvg classes
In preparation of adding additional svg elements, that go beyond the Tiny
1.2 standard, a member variable and respective getters and setters are
added to all relevant classes to let the application developers decide
which SVG features they want to be parsed.

Task-number: QTBUG-115223
Change-Id: Ia862548de815ca67e3ae8939141dc60f31696bb2
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
2023-09-20 15:20:09 +03:00