Merge branch 'master' of github.com:airbnb/lottie-web
diff --git a/player/js/effects/TransformEffect.js b/player/js/effects/TransformEffect.js
index d4bcc0d..2536ce5 100644
--- a/player/js/effects/TransformEffect.js
+++ b/player/js/effects/TransformEffect.js
@@ -21,8 +21,9 @@
var effectElements = this.effectsManager.effectElements;
var anchor = effectElements[0].p.v;
var position = effectElements[1].p.v;
+ var isUniformScale = effectElements[2].p.v === 1;
var scaleHeight = effectElements[3].p.v;
- var scaleWidth = effectElements[4].p.v;
+ var scaleWidth = isUniformScale ? scaleHeight : effectElements[4].p.v;
var skew = effectElements[5].p.v;
var skewAxis = effectElements[6].p.v;
var rotation = effectElements[7].p.v;
diff --git a/player/js/elements/helpers/TransformElement.js b/player/js/elements/helpers/TransformElement.js
index cbb2391..bc27023 100644
--- a/player/js/elements/helpers/TransformElement.js
+++ b/player/js/elements/helpers/TransformElement.js
@@ -70,7 +70,8 @@
if (this.localTransforms[i]._mdf) {
this.finalTransform._localMatMdf = true;
}
- if (this.localTransforms[i]._opMdf) {
+ if (this.localTransforms[i]._opMdf && !this.finalTransform._opMdf) {
+ this.finalTransform.localOpacity = this.finalTransform.mProp.o.v;
this.finalTransform._opMdf = true;
}
i += 1;
diff --git a/player/js/utils/FontManager.js b/player/js/utils/FontManager.js
index 4f749fb..6477bcc 100644
--- a/player/js/utils/FontManager.js
+++ b/player/js/utils/FontManager.js
@@ -18,6 +18,15 @@
2367, 2368, 2369, 2370, 2371, 2372, 2373, 2374, 2375, 2376, 2377, 2378, 2379,
2380, 2381, 2382, 2383, 2387, 2388, 2389, 2390, 2391, 2402, 2403]);
+ var BLACK_FLAG_CODE_POINT = 127988;
+ var CANCEL_TAG_CODE_POINT = 917631;
+ var A_TAG_CODE_POINT = 917601;
+ var Z_TAG_CODE_POINT = 917626;
+ var VARIATION_SELECTOR_16_CODE_POINT = 65039;
+ var ZERO_WIDTH_JOINER_CODE_POINT = 8205;
+ var REGIONAL_CHARACTER_A_CODE_POINT = 127462;
+ var REGIONAL_CHARACTER_Z_CODE_POINT = 127487;
+
var surrogateModifiers = [
'd83cdffb',
'd83cdffc',
@@ -26,8 +35,6 @@
'd83cdfff',
];
- var zeroWidthJoiner = [65039, 8205];
-
function trimFontOptions(font) {
var familyArray = font.split(',');
var i;
@@ -296,18 +303,20 @@
function measureText(char, fontName, size) {
var fontData = this.getFontByName(fontName);
- var index = char.charCodeAt(0);
- if (!fontData.cache[index + 1]) {
+ // Using the char instead of char.charCodeAt(0)
+ // to avoid collisions between equal chars
+ var index = char;
+ if (!fontData.cache[index]) {
var tHelper = fontData.helper;
if (char === ' ') {
var doubleSize = tHelper.measureText('|' + char + '|');
var singleSize = tHelper.measureText('||');
- fontData.cache[index + 1] = (doubleSize - singleSize) / 100;
+ fontData.cache[index] = (doubleSize - singleSize) / 100;
} else {
- fontData.cache[index + 1] = tHelper.measureText(char) / 100;
+ fontData.cache[index] = tHelper.measureText(char) / 100;
}
}
- return fontData.cache[index + 1] * size;
+ return fontData.cache[index] * size;
}
function getFontByName(name) {
@@ -322,22 +331,77 @@
return this.fonts[0];
}
+ function getCodePoint(string) {
+ var codePoint = 0;
+ var first = string.charCodeAt(0);
+ if (first >= 0xD800 && first <= 0xDBFF) {
+ var second = string.charCodeAt(1);
+ if (second >= 0xDC00 && second <= 0xDFFF) {
+ codePoint = (first - 0xD800) * 0x400 + second - 0xDC00 + 0x10000;
+ }
+ }
+ return codePoint;
+ }
+
+ // Skin tone modifiers
function isModifier(firstCharCode, secondCharCode) {
var sum = firstCharCode.toString(16) + secondCharCode.toString(16);
return surrogateModifiers.indexOf(sum) !== -1;
}
- function isZeroWidthJoiner(firstCharCode, secondCharCode) {
- if (!secondCharCode) {
- return firstCharCode === zeroWidthJoiner[1];
+ function isZeroWidthJoiner(charCode) {
+ return charCode === ZERO_WIDTH_JOINER_CODE_POINT;
+ }
+
+ // This codepoint may change the appearance of the preceding character.
+ // If that is a symbol, dingbat or emoji, U+FE0F forces it to be rendered
+ // as a colorful image as compared to a monochrome text variant.
+ function isVariationSelector(charCode) {
+ return charCode === VARIATION_SELECTOR_16_CODE_POINT;
+ }
+
+ // The regional indicator symbols are a set of 26 alphabetic Unicode
+ /// characters (A–Z) intended to be used to encode ISO 3166-1 alpha-2
+ // two-letter country codes in a way that allows optional special treatment.
+ function isRegionalCode(string) {
+ var codePoint = getCodePoint(string);
+ if (codePoint >= REGIONAL_CHARACTER_A_CODE_POINT && codePoint <= REGIONAL_CHARACTER_Z_CODE_POINT) {
+ return true;
}
- return firstCharCode === zeroWidthJoiner[0] && secondCharCode === zeroWidthJoiner[1];
+ return false;
+ }
+
+ // Some Emoji implementations represent combinations of
+ // two “regional indicator” letters as a single flag symbol.
+ function isFlagEmoji(string) {
+ return isRegionalCode(string.substr(0, 2)) && isRegionalCode(string.substr(2, 2));
}
function isCombinedCharacter(char) {
return combinedCharacters.indexOf(char) !== -1;
}
+ // Regional flags start with a BLACK_FLAG_CODE_POINT
+ // folowed by 5 chars in the TAG range
+ // and end with a CANCEL_TAG_CODE_POINT
+ function isRegionalFlag(text, index) {
+ var codePoint = getCodePoint(text.substr(index, 2));
+ if (codePoint !== BLACK_FLAG_CODE_POINT) {
+ return false;
+ }
+ var count = 0;
+ index += 2;
+ while (count < 5) {
+ codePoint = getCodePoint(text.substr(index, 2));
+ if (codePoint < A_TAG_CODE_POINT || codePoint > Z_TAG_CODE_POINT) {
+ return false;
+ }
+ count += 1;
+ index += 2;
+ }
+ return getCodePoint(text.substr(index, 2)) === CANCEL_TAG_CODE_POINT;
+ }
+
function setIsLoaded() {
this.isLoaded = true;
}
@@ -354,7 +418,12 @@
};
Font.isModifier = isModifier;
Font.isZeroWidthJoiner = isZeroWidthJoiner;
+ Font.isFlagEmoji = isFlagEmoji;
+ Font.isRegionalCode = isRegionalCode;
Font.isCombinedCharacter = isCombinedCharacter;
+ Font.isRegionalFlag = isRegionalFlag;
+ Font.isVariationSelector = isVariationSelector;
+ Font.BLACK_FLAG_CODE_POINT = BLACK_FLAG_CODE_POINT;
var fontPrototype = {
addChars: addChars,
diff --git a/player/js/utils/expressions/ExpressionManager.js b/player/js/utils/expressions/ExpressionManager.js
index 20acb03..121763e 100644
--- a/player/js/utils/expressions/ExpressionManager.js
+++ b/player/js/utils/expressions/ExpressionManager.js
@@ -34,12 +34,12 @@
}
function isNumerable(tOfV, v) {
- return tOfV === 'number' || tOfV === 'boolean' || tOfV === 'string' || v instanceof Number;
+ return tOfV === 'number' || v instanceof Number || tOfV === 'boolean' || tOfV === 'string';
}
function $bm_neg(a) {
var tOfA = typeof a;
- if (tOfA === 'number' || tOfA === 'boolean' || a instanceof Number) {
+ if (tOfA === 'number' || a instanceof Number || tOfA === 'boolean') {
return -a;
}
if ($bm_isInstanceOfArray(a)) {
@@ -64,10 +64,7 @@
function sum(a, b) {
var tOfA = typeof a;
var tOfB = typeof b;
- if (tOfA === 'string' || tOfB === 'string') {
- return a + b;
- }
- if (isNumerable(tOfA, a) && isNumerable(tOfB, b)) {
+ if ((isNumerable(tOfA, a) && isNumerable(tOfB, b)) || tOfA === 'string' || tOfB === 'string') {
return a + b;
}
if ($bm_isInstanceOfArray(a) && isNumerable(tOfB, b)) {
diff --git a/player/js/utils/text/TextProperty.js b/player/js/utils/text/TextProperty.js
index 1b188f0..a26ddf6 100644
--- a/player/js/utils/text/TextProperty.js
+++ b/player/js/utils/text/TextProperty.js
@@ -153,39 +153,49 @@
var charCode;
var secondCharCode;
var shouldCombine = false;
+ var shouldCombineNext = false;
+ var currentChars = '';
while (i < len) {
+ shouldCombine = shouldCombineNext;
+ shouldCombineNext = false;
charCode = text.charCodeAt(i);
+ currentChars = text.charAt(i);
if (FontManager.isCombinedCharacter(charCode)) {
- charactersArray[charactersArray.length - 1] += text.charAt(i);
+ shouldCombine = true;
+ // It's a potential surrogate pair (this is the High surrogate)
} else if (charCode >= 0xD800 && charCode <= 0xDBFF) {
- secondCharCode = text.charCodeAt(i + 1);
- if (secondCharCode >= 0xDC00 && secondCharCode <= 0xDFFF) {
- if (shouldCombine || FontManager.isModifier(charCode, secondCharCode)) {
- charactersArray[charactersArray.length - 1] += text.substr(i, 2);
- shouldCombine = false;
- } else {
- charactersArray.push(text.substr(i, 2));
- }
- i += 1;
+ if (FontManager.isRegionalFlag(text, i)) {
+ currentChars = text.substr(i, 14);
} else {
- charactersArray.push(text.charAt(i));
+ secondCharCode = text.charCodeAt(i + 1);
+ // It's a surrogate pair (this is the Low surrogate)
+ if (secondCharCode >= 0xDC00 && secondCharCode <= 0xDFFF) {
+ if (FontManager.isModifier(charCode, secondCharCode)) {
+ currentChars = text.substr(i, 2);
+ shouldCombine = true;
+ } else if (FontManager.isFlagEmoji(text.substr(i, 4))) {
+ currentChars = text.substr(i, 4);
+ } else {
+ currentChars = text.substr(i, 2);
+ }
+ }
}
} else if (charCode > 0xDBFF) {
secondCharCode = text.charCodeAt(i + 1);
- if (FontManager.isZeroWidthJoiner(charCode, secondCharCode)) {
+ if (FontManager.isVariationSelector(charCode)) {
shouldCombine = true;
- charactersArray[charactersArray.length - 1] += text.substr(i, 2);
- i += 1;
- } else {
- charactersArray.push(text.charAt(i));
}
} else if (FontManager.isZeroWidthJoiner(charCode)) {
- charactersArray[charactersArray.length - 1] += text.charAt(i);
shouldCombine = true;
- } else {
- charactersArray.push(text.charAt(i));
+ shouldCombineNext = true;
}
- i += 1;
+ if (shouldCombine) {
+ charactersArray[charactersArray.length - 1] += currentChars;
+ shouldCombine = false;
+ } else {
+ charactersArray.push(currentChars);
+ }
+ i += currentChars.length;
}
return charactersArray;
};