|
29 | 29 | #include "mlt_animation.h" |
30 | 30 | #include "mlt_properties.h" |
31 | 31 |
|
| 32 | +#include <ctype.h> |
32 | 33 | #include <float.h> |
33 | 34 | #include <locale.h> |
34 | 35 | #include <math.h> |
@@ -2106,18 +2107,94 @@ mlt_properties mlt_property_get_properties(mlt_property self) |
2106 | 2107 | return properties; |
2107 | 2108 | } |
2108 | 2109 |
|
| 2110 | +static int is_keyframe_type_marker(char c) |
| 2111 | +{ |
| 2112 | + switch (c) { |
| 2113 | + case '|': |
| 2114 | + case '!': |
| 2115 | + case '~': |
| 2116 | + case '$': |
| 2117 | + case '-': |
| 2118 | + return 1; |
| 2119 | + default: |
| 2120 | + return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'D'); |
| 2121 | + } |
| 2122 | +} |
| 2123 | + |
| 2124 | +static int is_keyframe_token(const char *begin, const char *end) |
| 2125 | +{ |
| 2126 | + while (begin < end && isspace((unsigned char) *begin)) |
| 2127 | + ++begin; |
| 2128 | + while (end > begin && isspace((unsigned char) end[-1])) |
| 2129 | + --end; |
| 2130 | + if (begin >= end) |
| 2131 | + return 0; |
| 2132 | + |
| 2133 | + if (end - begin > 1 && is_keyframe_type_marker(end[-1])) |
| 2134 | + --end; |
| 2135 | + |
| 2136 | + int has_digit = 0; |
| 2137 | + int trailing_unit_seen = 0; |
| 2138 | + for (const char *p = begin; p < end; ++p) { |
| 2139 | + unsigned char c = (unsigned char) *p; |
| 2140 | + if (isdigit(c)) { |
| 2141 | + has_digit = 1; |
| 2142 | + continue; |
| 2143 | + } |
| 2144 | + if (c == ':' || c == '.' || c == ',' || c == '-' || c == '+') |
| 2145 | + continue; |
| 2146 | + if (isalpha(c) && p == end - 1 && !trailing_unit_seen && has_digit) { |
| 2147 | + trailing_unit_seen = 1; |
| 2148 | + continue; |
| 2149 | + } |
| 2150 | + return 0; |
| 2151 | + } |
| 2152 | + return has_digit; |
| 2153 | +} |
| 2154 | + |
2109 | 2155 | /** Check if a property is animated. |
2110 | 2156 | * |
2111 | 2157 | * This is not a thread-safe function because it is used internally by |
2112 | 2158 | * mlt_property_s under a lock. However, external callers should protect it. |
| 2159 | + * |
| 2160 | + * A property counts as animated when it already has an animation object or |
| 2161 | + * when its serialized string contains at least one unquoted keyframe item of |
| 2162 | + * the form key=value, where key looks like a frame or time token. This also |
| 2163 | + * accepts the optional single-character keyframe-type marker that serialized |
| 2164 | + * animations place immediately before '='. |
| 2165 | + * |
| 2166 | + * This intentionally does not treat every '=' as animation syntax. Plain |
| 2167 | + * strings may legitimately contain '=' or ';' characters, and those continue |
| 2168 | + * to work as ordinary string values. Quoted string payloads inside animation |
| 2169 | + * strings also continue to work: text between double quotes is ignored while |
| 2170 | + * scanning for separators, matching the documented requirement to quote string |
| 2171 | + * values that contain animation delimiters. |
| 2172 | + * |
2113 | 2173 | * \public \memberof mlt_property_s |
2114 | 2174 | * \param self a property |
2115 | 2175 | * \return true if the property is animated |
2116 | 2176 | */ |
2117 | 2177 |
|
2118 | 2178 | int mlt_property_is_anim(mlt_property self) |
2119 | 2179 | { |
2120 | | - return self->animation || (self->prop_string && strchr(self->prop_string, '=')); |
| 2180 | + if (self->animation) |
| 2181 | + return 1; |
| 2182 | + if (!self->prop_string) |
| 2183 | + return 0; |
| 2184 | + |
| 2185 | + const char *token_start = self->prop_string; |
| 2186 | + int in_quotes = 0; |
| 2187 | + for (const char *p = self->prop_string; *p; ++p) { |
| 2188 | + if (*p == '"' && (p == self->prop_string || p[-1] != '\\')) { |
| 2189 | + in_quotes = !in_quotes; |
| 2190 | + continue; |
| 2191 | + } |
| 2192 | + if (!in_quotes && *p == '=') |
| 2193 | + return is_keyframe_token(token_start, p); |
| 2194 | + if (!in_quotes && *p == ';') |
| 2195 | + token_start = p + 1; |
| 2196 | + } |
| 2197 | + return 0; |
2121 | 2198 | } |
2122 | 2199 |
|
2123 | 2200 | /** Check if a property is a color. |
|
0 commit comments