25 static const QHash<QString, QSvgAbstractAnimatedProperty::Type> hash = {
26 { u"fill"_s, QSvgAbstractAnimatedProperty::Color },
27 { u"fill-opacity"_s, QSvgAbstractAnimatedProperty::Float },
28 { u"stroke-opacity"_s, QSvgAbstractAnimatedProperty::Float },
29 { u"stroke"_s, QSvgAbstractAnimatedProperty::Color },
30 { u"opacity"_s, QSvgAbstractAnimatedProperty::Float },
31 { u"transform"_s, QSvgAbstractAnimatedProperty::Transform },
32 { u"offset-distance"_s, QSvgAbstractAnimatedProperty::Float },
34 auto it = hash.find(name);
109QSvgAbstractAnimatedProperty *QSvgAbstractAnimatedProperty::createAnimatedProperty(
const QString &name)
111 const std::optional<Type> type = name2type(name);
114 qCDebug(lcSvgAnimatedProperty) <<
"Property : " << name <<
" is not animatable";
118 QSvgAbstractAnimatedProperty *prop =
nullptr;
121 case QSvgAbstractAnimatedProperty::Color:
122 prop =
new QSvgAnimatedPropertyColor(name);
124 case QSvgAbstractAnimatedProperty::Transform:
125 prop =
new QSvgAnimatedPropertyTransform(name);
127 case QSvgAbstractAnimatedProperty::Float:
128 prop =
new QSvgAnimatedPropertyFloat(name);
159void QSvgAnimatedPropertyColor::interpolate(uint index, qreal t)
const
161 QColor c1 = m_colors.at(index - 1);
162 QColor c2 = m_colors.at(index);
164 int alpha = q_lerp(c1.alpha(), c2.alpha(), t);
165 int red = q_lerp(c1.red(), c2.red(), t);
166 int green = q_lerp(c1.green(), c2.green(), t);
167 int blue = q_lerp(c1.blue(), c2.blue(), t);
169 m_interpolatedValue = QColor(red, green, blue, alpha);
195void QSvgAnimatedPropertyFloat::interpolate(uint index, qreal t)
const
197 if (index >= (uint)m_keyFrames.size()) {
198 qCWarning(lcSvgAnimatedProperty) <<
"Invalid index for key frames";
202 qreal float1 = m_values.at(index - 1);
203 qreal float2 = m_values.at(index);
205 m_interpolatedValue = q_lerp(float1, float2, t);
243void QSvgAnimatedPropertyTransform::interpolate(uint index, qreal t)
const
245 if (index >= (uint)m_keyFrames.size()) {
246 qCWarning(lcSvgAnimatedProperty) <<
"Invalid index for key frames";
250 if (!m_transformCount ||
251 ((m_components.size() / qsizetype(m_transformCount)) != m_keyFrames.size())) {
255 QTransform transform = QTransform();
257 qsizetype startIndex = (index - 1) * qsizetype(m_transformCount);
258 qsizetype endIndex = index * qsizetype(m_transformCount);
260 for (quint32 i = 0; i < m_transformCount; i++) {
261 TransformComponent tc1 = m_components.at(startIndex + i);
262 TransformComponent tc2 = m_components.at(endIndex + i);
263 if (tc1.type == tc2.type) {
264 if (tc1.type == TransformComponent::Translate) {
265 QPointF t1 = QPointF(tc1.values.at(0), tc1.values.at(1));
266 QPointF t2 = QPointF(tc2.values.at(0), tc2.values.at(1));
267 QPointF tr = pointInterpolator(t1, t2, t);
268 transform.translate(tr.x(), tr.y());
269 }
else if (tc1.type == TransformComponent::Scale) {
270 QPointF s1 = QPointF(tc1.values.at(0), tc1.values.at(1));
271 QPointF s2 = QPointF(tc2.values.at(0), tc2.values.at(1));
272 QPointF sr = pointInterpolator(s1, s2, t);
273 transform.scale(sr.x(), sr.y());
274 }
else if (tc1.type == TransformComponent::Rotate) {
275 QPointF cor1 = QPointF(tc1.values.at(1), tc1.values.at(2));
276 QPointF cor2 = QPointF(tc2.values.at(1), tc2.values.at(2));
277 QPointF corResult = pointInterpolator(cor1, cor2, t);
278 qreal angle1 = tc1.values.at(0);
279 qreal angle2 = tc2.values.at(0);
280 qreal angleResult = q_lerp(angle1, angle2, t);
281 transform.translate(corResult.x(), corResult.y());
282 transform.rotate(angleResult);
283 transform.translate(-corResult.x(), -corResult.y());
284 }
else if (tc1.type == TransformComponent::Skew) {
285 QPointF skew1 = QPointF(tc1.values.at(0), tc1.values.at(1));
286 QPointF skew2 = QPointF(tc2.values.at(0), tc2.values.at(1));
287 QPointF skewResult = pointInterpolator(skew1, skew2, t);
288 transform.shear(qTan(qDegreesToRadians(skewResult.x())),
289 qTan(qDegreesToRadians(skewResult.y())));
294 m_interpolatedValue = transform;