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>
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)
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)
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>
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>
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)
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>