VectorImage: Add support for gradient/fill transforms
Handle the SVG gradientTransform and patternTransform attributes. Fixes: QTBUG-121661 Pick-to: 6.8 Change-Id: I79d85ebfef46527e2909440aaca94c975bf21a47 Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io> Reviewed-by: Hatem ElKharashy <hatem.elkharashy@qt.io>
This commit is contained in:
parent
ab359c11e1
commit
10637de078
|
@ -161,6 +161,8 @@ void QQuickItemGenerator::outputShapePath(const PathNodeInfo &info, const QPaint
|
||||||
shapePath->setFillColor(info.fillColor);
|
shapePath->setFillColor(info.fillColor);
|
||||||
|
|
||||||
shapePath->setFillRule(fillRule);
|
shapePath->setFillRule(fillRule);
|
||||||
|
if (!info.fillTransform.isIdentity())
|
||||||
|
shapePath->setFillTransform(info.fillTransform);
|
||||||
|
|
||||||
QString svgPathString = painterPath ? QQuickVectorImageGenerator::Utils::toSvgString(*painterPath) : QQuickVectorImageGenerator::Utils::toSvgString(*quadPath);
|
QString svgPathString = painterPath ? QQuickVectorImageGenerator::Utils::toSvgString(*painterPath) : QQuickVectorImageGenerator::Utils::toSvgString(*quadPath);
|
||||||
|
|
||||||
|
|
|
@ -76,6 +76,7 @@ struct PathNodeInfo : NodeInfo
|
||||||
QColor fillColor;
|
QColor fillColor;
|
||||||
StrokeStyle strokeStyle;
|
StrokeStyle strokeStyle;
|
||||||
QGradient grad;
|
QGradient grad;
|
||||||
|
QTransform fillTransform;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TextNodeInfo : NodeInfo
|
struct TextNodeInfo : NodeInfo
|
||||||
|
|
|
@ -80,17 +80,9 @@ void QQuickQmlGenerator::generateNodeBase(const NodeInfo &info)
|
||||||
} else if (info.transform.type() == QTransform::TxScale && !x && !y) {
|
} else if (info.transform.type() == QTransform::TxScale && !x && !y) {
|
||||||
stream() << "transform: Scale { xScale: " << sx << "; yScale: " << sy << " }";
|
stream() << "transform: Scale { xScale: " << sx << "; yScale: " << sy << " }";
|
||||||
} else {
|
} else {
|
||||||
const QMatrix4x4 m(info.transform);
|
stream() << "transform: Matrix4x4 { matrix: ";
|
||||||
{
|
generateTransform(info.transform);
|
||||||
stream() << "transform: [ Matrix4x4 { matrix: Qt.matrix4x4 (";
|
stream(SameLine) << " }";
|
||||||
m_indentLevel += 3;
|
|
||||||
const auto *data = m.data();
|
|
||||||
for (int i = 0; i < 4; i++) {
|
|
||||||
stream() << data[i] << ", " << data[i+4] << ", " << data[i+8] << ", " << data[i+12] << ", ";
|
|
||||||
}
|
|
||||||
stream() << ") } ]";
|
|
||||||
m_indentLevel -= 3;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!info.isDefaultOpacity) {
|
if (!info.isDefaultOpacity) {
|
||||||
|
@ -222,6 +214,28 @@ void QQuickQmlGenerator::generateGradient(const QGradient *grad, const QRectF &b
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QQuickQmlGenerator::generateTransform(const QTransform &xf)
|
||||||
|
{
|
||||||
|
if (xf.isAffine()) {
|
||||||
|
stream(SameLine) << "PlanarTransform.fromAffineMatrix("
|
||||||
|
<< xf.m11() << ", " << xf.m12() << ", "
|
||||||
|
<< xf.m21() << ", " << xf.m22() << ", "
|
||||||
|
<< xf.dx() << ", " << xf.dy() << ")";
|
||||||
|
} else {
|
||||||
|
QMatrix4x4 m(xf);
|
||||||
|
stream(SameLine) << "Qt.matrix4x4(";
|
||||||
|
m_indentLevel += 3;
|
||||||
|
const auto *data = m.data();
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
stream() << data[i] << ", " << data[i+4] << ", " << data[i+8] << ", " << data[i+12];
|
||||||
|
if (i < 3)
|
||||||
|
stream(SameLine) << ", ";
|
||||||
|
}
|
||||||
|
stream(SameLine) << ")";
|
||||||
|
m_indentLevel -= 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void QQuickQmlGenerator::outputShapePath(const PathNodeInfo &info, const QPainterPath *painterPath, const QQuadPath *quadPath, QQuickVectorImageGenerator::PathSelector pathSelector, const QRectF &boundingRect)
|
void QQuickQmlGenerator::outputShapePath(const PathNodeInfo &info, const QPainterPath *painterPath, const QQuadPath *quadPath, QQuickVectorImageGenerator::PathSelector pathSelector, const QRectF &boundingRect)
|
||||||
{
|
{
|
||||||
Q_UNUSED(pathSelector)
|
Q_UNUSED(pathSelector)
|
||||||
|
@ -275,6 +289,18 @@ void QQuickQmlGenerator::outputShapePath(const PathNodeInfo &info, const QPainte
|
||||||
} else {
|
} else {
|
||||||
stream() << "fillColor: \"" << info.fillColor.name(QColor::HexArgb) << "\"";
|
stream() << "fillColor: \"" << info.fillColor.name(QColor::HexArgb) << "\"";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!info.fillTransform.isIdentity()) {
|
||||||
|
const QTransform &xf = info.fillTransform;
|
||||||
|
stream() << "fillTransform: ";
|
||||||
|
if (info.fillTransform.type() == QTransform::TxTranslate)
|
||||||
|
stream(SameLine) << "PlanarTransform.fromTranslate(" << xf.dx() << ", " << xf.dy() << ")";
|
||||||
|
else if (info.fillTransform.type() == QTransform::TxScale && !xf.dx() && !xf.dy())
|
||||||
|
stream(SameLine) << "PlanarTransform.fromScale(" << xf.m11() << ", " << xf.m22() << ")";
|
||||||
|
else
|
||||||
|
generateTransform(xf);
|
||||||
|
}
|
||||||
|
|
||||||
if (fillRule == QQuickShapePath::WindingFill)
|
if (fillRule == QQuickShapePath::WindingFill)
|
||||||
stream() << "fillRule: ShapePath.WindingFill";
|
stream() << "fillRule: ShapePath.WindingFill";
|
||||||
else
|
else
|
||||||
|
|
|
@ -78,6 +78,7 @@ protected:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void generateGradient(const QGradient *grad, const QRectF &boundingRect);
|
void generateGradient(const QGradient *grad, const QRectF &boundingRect);
|
||||||
|
void generateTransform(const QTransform &xf);
|
||||||
|
|
||||||
QStringView indent();
|
QStringView indent();
|
||||||
enum StreamFlags { NoFlags = 0x0, SameLine = 0x1 };
|
enum StreamFlags { NoFlags = 0x0, SameLine = 0x1 };
|
||||||
|
|
|
@ -81,6 +81,11 @@ public:
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QTransform currentFillTransform() const
|
||||||
|
{
|
||||||
|
return m_dummyPainter.brush().transform();
|
||||||
|
}
|
||||||
|
|
||||||
QColor currentStrokeColor() const
|
QColor currentStrokeColor() const
|
||||||
{
|
{
|
||||||
if (m_dummyPainter.pen().brush().style() == Qt::NoBrush ||
|
if (m_dummyPainter.pen().brush().style() == Qt::NoBrush ||
|
||||||
|
@ -606,6 +611,8 @@ void QSvgVisitorImpl::visitTextNode(const QSvgText *node)
|
||||||
if (info.grad.type() == QGradient::NoGradient && styleResolver->currentFillGradient() != nullptr)
|
if (info.grad.type() == QGradient::NoGradient && styleResolver->currentFillGradient() != nullptr)
|
||||||
info.grad = styleResolver->applyOpacityToGradient(*styleResolver->currentFillGradient(), styleResolver->currentFillOpacity());
|
info.grad = styleResolver->applyOpacityToGradient(*styleResolver->currentFillGradient(), styleResolver->currentFillOpacity());
|
||||||
|
|
||||||
|
info.fillTransform = styleResolver->currentFillTransform();
|
||||||
|
|
||||||
m_generator->generatePath(info);
|
m_generator->generatePath(info);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -819,6 +826,7 @@ void QSvgVisitorImpl::handlePathNode(const QSvgNode *node, const QPainterPath &p
|
||||||
info.strokeStyle.color = styleResolver->currentStrokeColor();
|
info.strokeStyle.color = styleResolver->currentStrokeColor();
|
||||||
if (styleResolver->currentFillGradient() != nullptr)
|
if (styleResolver->currentFillGradient() != nullptr)
|
||||||
info.grad = styleResolver->applyOpacityToGradient(*styleResolver->currentFillGradient(), styleResolver->currentFillOpacity());
|
info.grad = styleResolver->applyOpacityToGradient(*styleResolver->currentFillGradient(), styleResolver->currentFillOpacity());
|
||||||
|
info.fillTransform = styleResolver->currentFillTransform();
|
||||||
|
|
||||||
m_generator->generatePath(info);
|
m_generator->generatePath(info);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
<svg viewBox="0 0 380 800" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<radialGradient
|
||||||
|
id="gradient1"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
cx="100"
|
||||||
|
cy="100"
|
||||||
|
r="100"
|
||||||
|
fx="100"
|
||||||
|
fy="100"
|
||||||
|
gradientTransform="translate(100 0)">
|
||||||
|
<stop offset="0%" stop-color="darkblue" />
|
||||||
|
<stop offset="50%" stop-color="skyblue" />
|
||||||
|
<stop offset="100%" stop-color="darkblue" />
|
||||||
|
</radialGradient>
|
||||||
|
<radialGradient
|
||||||
|
id="gradient2"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
cx="100"
|
||||||
|
cy="100"
|
||||||
|
r="100"
|
||||||
|
fx="100"
|
||||||
|
fy="100"
|
||||||
|
gradientTransform="scale(2 1)">
|
||||||
|
<stop offset="0%" stop-color="darkblue" />
|
||||||
|
<stop offset="50%" stop-color="skyblue" />
|
||||||
|
<stop offset="100%" stop-color="darkblue" />
|
||||||
|
</radialGradient>
|
||||||
|
<radialGradient
|
||||||
|
id="gradient3"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
cx="100"
|
||||||
|
cy="100"
|
||||||
|
r="100"
|
||||||
|
fx="100"
|
||||||
|
fy="100"
|
||||||
|
gradientTransform="skewX(40)">
|
||||||
|
<stop offset="0%" stop-color="darkblue" />
|
||||||
|
<stop offset="50%" stop-color="skyblue" />
|
||||||
|
<stop offset="100%" stop-color="darkblue" />
|
||||||
|
</radialGradient>
|
||||||
|
|
||||||
|
<rect x="0" y="0" width="300" height="100" fill="url(#gradient1)" />
|
||||||
|
<text font-size="124" x="0" y="200" stroke="black" fill="url(#gradient1)">XLAT</text>
|
||||||
|
|
||||||
|
<g transform="translate(0 250)">
|
||||||
|
<rect x="0" y="0" width="300" height="100" fill="url(#gradient2)" />
|
||||||
|
<text font-size="124" x="0" y="200" stroke="black" fill="url(#gradient2)">SCAL</text>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<g transform="translate(0 500)">
|
||||||
|
<rect x="0" y="0" width="300" height="100" fill="url(#gradient3)" />
|
||||||
|
<text font-size="124" x="0" y="200" stroke="black" fill="url(#gradient3)">SKEW</text>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
<g font-family="Arial" font-size="92" transform="translate(50 0)">
|
||||||
|
<text x="0" y="100" stroke="black" fill="url(#gradient1)">TEST</text>
|
||||||
|
</g>
|
||||||
|
-->
|
||||||
|
</svg>
|
||||||
|
|
||||||
|
|
After Width: | Height: | Size: 1.8 KiB |
|
@ -0,0 +1,25 @@
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.VectorImage
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: topLevelItem
|
||||||
|
width: 800
|
||||||
|
height: 800
|
||||||
|
|
||||||
|
ListModel {
|
||||||
|
id: renderers
|
||||||
|
ListElement { renderer: VectorImage.GeometryRenderer }
|
||||||
|
ListElement { renderer: VectorImage.CurveRenderer }
|
||||||
|
}
|
||||||
|
|
||||||
|
Row {
|
||||||
|
Repeater {
|
||||||
|
model: renderers
|
||||||
|
|
||||||
|
VectorImage {
|
||||||
|
source: "../shared/svg/gradientxform.svg"
|
||||||
|
preferredRendererType: renderer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue