From a851d1706e5cbd868f9a509ed03ac589a198d21f Mon Sep 17 00:00:00 2001 From: Mira Grudzinska Date: Mon, 21 Oct 2024 21:36:23 +0700 Subject: [PATCH] lottie: fix transformations in text range selector Since the translate API was used while text updating, the subsequent range selector transformations gets overwritten when updating the shape (scale and rotate, adding another translation will persist). This caused unexpected results. Fixed by using the transform API when additional transformations are needed - also fixes applying more than one range selector. --- src/loaders/lottie/tvgLottieBuilder.cpp | 63 ++++++++++++++----------- src/renderer/tvgPaint.h | 2 +- 2 files changed, 36 insertions(+), 29 deletions(-) diff --git a/src/loaders/lottie/tvgLottieBuilder.cpp b/src/loaders/lottie/tvgLottieBuilder.cpp index 4b43ff0d..af59fb44 100644 --- a/src/loaders/lottie/tvgLottieBuilder.cpp +++ b/src/loaders/lottie/tvgLottieBuilder.cpp @@ -1060,43 +1060,50 @@ void LottieBuilder::updateText(LottieLayer* layer, float frameNo) shape->stroke(doc.stroke.color.rgb[0], doc.stroke.color.rgb[1], doc.stroke.color.rgb[2]); } - //text range process - for (auto s = text->ranges.begin(); s < text->ranges.end(); ++s) { - float start, end; - (*s)->range(frameNo, float(totalChars), start, end); + if (!text->ranges.empty()) { + Point scaling = {1.0f, 1.0f}; + auto rotation = 0.0f; + auto translation = cursor; - auto basedIdx = idx; - if ((*s)->based == LottieTextRange::Based::CharsExcludingSpaces) basedIdx = idx - space; - else if ((*s)->based == LottieTextRange::Based::Words) basedIdx = line + space; - else if ((*s)->based == LottieTextRange::Based::Lines) basedIdx = line; + //text range process + for (auto s = text->ranges.begin(); s < text->ranges.end(); ++s) { + float start, end; + (*s)->range(frameNo, float(totalChars), start, end); - if (basedIdx < start || basedIdx >= end) continue; - auto matrix = shape->transform(); + auto basedIdx = idx; + if ((*s)->based == LottieTextRange::Based::CharsExcludingSpaces) basedIdx = idx - space; + else if ((*s)->based == LottieTextRange::Based::Words) basedIdx = line + space; + else if ((*s)->based == LottieTextRange::Based::Lines) basedIdx = line; - shape->opacity((*s)->style.opacity(frameNo)); + if (basedIdx < start || basedIdx >= end) continue; - auto color = (*s)->style.fillColor(frameNo); - shape->fill(color.rgb[0], color.rgb[1], color.rgb[2], (*s)->style.fillOpacity(frameNo)); + translation = translation + (*s)->style.position(frameNo); + auto temp = (*s)->style.scale(frameNo); + scaling.x *= temp.x * 0.01f; + scaling.y *= temp.y * 0.01f; + rotation += (*s)->style.rotation(frameNo); - rotate(&matrix, (*s)->style.rotation(frameNo)); + shape->opacity((*s)->style.opacity(frameNo)); - auto glyphScale = (*s)->style.scale(frameNo) * 0.01f; - tvg::scale(&matrix, glyphScale.x, glyphScale.y); + auto color = (*s)->style.fillColor(frameNo); + shape->fill(color.rgb[0], color.rgb[1], color.rgb[2], (*s)->style.fillOpacity(frameNo)); - auto position = (*s)->style.position(frameNo); - translate(&matrix, position.x, position.y); + if (doc.stroke.render) { + auto strokeColor = (*s)->style.strokeColor(frameNo); + shape->stroke((*s)->style.strokeWidth(frameNo) / scale); + shape->stroke(strokeColor.rgb[0], strokeColor.rgb[1], strokeColor.rgb[2], (*s)->style.strokeOpacity(frameNo)); + } + cursor.x += (*s)->style.letterSpacing(frameNo); - shape->transform(matrix); - - if (doc.stroke.render) { - auto strokeColor = (*s)->style.strokeColor(frameNo); - shape->stroke((*s)->style.strokeWidth(frameNo) / scale); - shape->stroke(strokeColor.rgb[0], strokeColor.rgb[1], strokeColor.rgb[2], (*s)->style.strokeOpacity(frameNo)); + auto spacing = (*s)->style.lineSpacing(frameNo); + if (spacing > lineSpacing) lineSpacing = spacing; } - cursor.x += (*s)->style.letterSpacing(frameNo); - - auto spacing = (*s)->style.lineSpacing(frameNo); - if (spacing > lineSpacing) lineSpacing = spacing; + Matrix matrix; + identity(&matrix); + translate(&matrix, translation.x, translation.y); + tvg::scale(&matrix, scaling.x, scaling.y); + rotate(&matrix, rotation); + shape->transform(matrix); } scene->push(cast(shape)); diff --git a/src/renderer/tvgPaint.h b/src/renderer/tvgPaint.h index e623c6ae..b44af1aa 100644 --- a/src/renderer/tvgPaint.h +++ b/src/renderer/tvgPaint.h @@ -107,7 +107,7 @@ namespace tvg bool transform(const Matrix& m) { - tr.m = m; + if (&tr.m != &m) tr.m = m; tr.overriding = true; renderFlag |= RenderUpdateFlag::Transform;