6#include <QtSvg/private/qsvganimatedproperty_p.h>
7#include <QtSvg/private/qsvgutils_p.h>
8#include <QtGui/private/qmath_p.h>
15 QStringView numStr = str.trimmed();
17 if (numStr.isEmpty()) {
24 if (numStr.endsWith(QLatin1String(
"deg"))) {
27 }
else if (numStr.endsWith(QLatin1String(
"grad"))) {
31 }
else if (numStr.endsWith(QLatin1String(
"rad"))) {
33 unitFactor = 180.0 / Q_PI;
34 }
else if (numStr.endsWith(QLatin1String(
"turn"))) {
42 return QSvgUtils::toDouble(numStr, ok) * unitFactor;
47 auto sortFunction = [](QCss::AnimationRule::AnimationRuleSet r1, QCss::AnimationRule::AnimationRuleSet r2) {
48 return r1.keyFrame < r2.keyFrame;
51 QList<QCss::AnimationRule> animationRules = sheet.animationRules;
52 for (QCss::AnimationRule rule : animationRules) {
53 std::sort(rule.ruleSets.begin(), rule.ruleSets.end(), sortFunction);
54 m_animations[rule.animName] = rule;
58QSvgCssAnimation *
QSvgCssHandler::createAnimation(
const QString &name)
60 if (!m_animations.contains(name))
63 QCss::AnimationRule animationRule = m_animations[name];
64 QHash<QString, QSvgAbstractAnimatedProperty*> animatedProperies;
65 QSvgCssAnimation *animation =
new QSvgCssAnimation;
67 for (
const auto &ruleSet : std::as_const(animationRule.ruleSets)) {
68 for (QCss::Declaration decl : ruleSet.declarations) {
69 if (decl.d->property == QStringLiteral(
"fill") || decl.d->property == QStringLiteral(
"stroke")) {
70 QSvgAnimatedPropertyColor *prop =
nullptr;
71 if (!animatedProperies.contains(decl.d->property))
72 animatedProperies[decl.d->property] = QSvgAbstractAnimatedProperty::createAnimatedProperty(decl.d->property);
73 prop =
static_cast<QSvgAnimatedPropertyColor *>(animatedProperies[decl.d->property]);
74 prop->appendKeyFrame(ruleSet.keyFrame);
75 updateColorProperty(decl, prop);
76 }
else if (decl.d->property == QStringLiteral(
"transform")) {
77 QSvgAnimatedPropertyTransform *prop =
nullptr;
78 if (!animatedProperies.contains(decl.d->property))
79 animatedProperies[decl.d->property] = QSvgAbstractAnimatedProperty::createAnimatedProperty(decl.d->property);
80 prop =
static_cast<QSvgAnimatedPropertyTransform *>(animatedProperies[decl.d->property]);
81 prop->appendKeyFrame(ruleSet.keyFrame);
82 updateTransformProperty(decl, prop);
83 }
else if (decl.d->property == QStringLiteral(
"fill-opacity") || decl.d->property == QStringLiteral(
"stroke-opacity")
84 || decl.d->property == QStringLiteral(
"opacity")) {
85 QSvgAnimatedPropertyFloat *prop =
nullptr;
86 if (!animatedProperies.contains(decl.d->property))
87 animatedProperies[decl.d->property] = QSvgAbstractAnimatedProperty::createAnimatedProperty(decl.d->property);
88 prop =
static_cast<QSvgAnimatedPropertyFloat *>(animatedProperies[decl.d->property]);
89 prop->appendKeyFrame(ruleSet.keyFrame);
90 QString opacity = decl.d->values.first().toString();
91 prop->appendValue(opacity.toDouble());
96 for (
auto it = animatedProperies.begin(); it != animatedProperies.end(); it++)
97 animation->appendProperty(it.value());
102void QSvgCssHandler::updateColorProperty(
const QCss::Declaration &decl, QSvgAnimatedPropertyColor *property)
104 QString colorStr = decl.d->values.first().toString();
105 QColor color = QColor::fromString(colorStr);
106 property->appendColor(color);
109void QSvgCssHandler::updateTransformProperty(
const QCss::Declaration &decl, QSvgAnimatedPropertyTransform *property)
111 for (QCss::Value val : decl.d->values) {
112 if (val.type == QCss::Value::Function) {
113 QStringList lst = val.variant.toStringList();
114 QStringView transformType = lst[0];
115 QStringList args = lst[1].split(QStringLiteral(
","), Qt::SkipEmptyParts);
116 if (transformType == QStringLiteral(
"scale")) {
117 qreal scale0 = QSvgUtils::toDouble(args[0].trimmed());
118 qreal scale1 = QSvgUtils::toDouble(args[1].trimmed());
119 property->appendScale(QPointF(scale0, scale1));
120 }
else if (transformType == QStringLiteral(
"translate")) {
121 QSvgUtils::LengthType type;
122 qreal translate0 = QSvgUtils::parseLength(args[0], &type);
123 translate0 = QSvgUtils::convertToPixels(translate0,
false, type);
124 qreal translate1 = QSvgUtils::parseLength(args[1], &type);
125 translate1 = QSvgUtils::convertToPixels(translate1,
false, type);
126 property->appendTranslation(QPointF(translate0, translate1));
127 }
else if (transformType == QStringLiteral(
"rotate")) {
128 qreal rotationAngle = qsvg_parseAngle(args[0]);
129 property->appendRotation(rotationAngle);
130 property->appendCenterOfRotation(QPointF(0, 0));
131 }
else if (transformType == QStringLiteral(
"skew")) {
132 qreal skew0 = qsvg_parseAngle(args[0]);
133 qreal skew1 = qsvg_parseAngle(args[1]);
134 property->appendSkew(QPointF(skew0, skew1));
135 }
else if (transformType == QStringLiteral(
"matrix")) {
136 QSvgUtils::LengthType type;
137 qreal translate0 = QSvgUtils::parseLength(args[4], &type);
138 translate0 = QSvgUtils::convertToPixels(translate0,
false, type);
139 qreal translate1 = QSvgUtils::parseLength(args[5], &type);
140 translate1 = QSvgUtils::convertToPixels(translate1,
false, type);
141 qreal scale0 = QSvgUtils::toDouble(args[0].trimmed());
142 qreal scale1 = QSvgUtils::toDouble(args[3].trimmed());
143 qreal skew0 = QSvgUtils::toDouble((args[1].trimmed()));
144 qreal skew1 = QSvgUtils::toDouble((args[2].trimmed()));
145 property->appendSkew(QPointF(skew0, skew1));
146 property->appendTranslation(QPointF(translate0, translate1));
147 property->appendScale(QPointF(scale0, scale1));
void collectAnimations(const QCss::StyleSheet &sheet)
static QT_BEGIN_NAMESPACE qreal qsvg_parseAngle(QStringView str, bool *ok=nullptr)