462 lines
14 KiB
Plaintext
462 lines
14 KiB
Plaintext
|
import {
|
||
|
initialDefaultFrame,
|
||
|
} from '../../main';
|
||
|
import getFontProperties from '../getFontProperties';
|
||
|
import FontManager from '../FontManager';
|
||
|
|
||
|
function TextProperty(elem, data) {
|
||
|
this._frameId = initialDefaultFrame;
|
||
|
this.pv = '';
|
||
|
this.v = '';
|
||
|
this.kf = false;
|
||
|
this._isFirstFrame = true;
|
||
|
this._mdf = false;
|
||
|
if (data.d && data.d.sid) {
|
||
|
data.d = elem.globalData.slotManager.getProp(data.d);
|
||
|
}
|
||
|
this.data = data;
|
||
|
this.elem = elem;
|
||
|
this.comp = this.elem.comp;
|
||
|
this.keysIndex = 0;
|
||
|
this.canResize = false;
|
||
|
this.minimumFontSize = 1;
|
||
|
this.effectsSequence = [];
|
||
|
this.currentData = {
|
||
|
ascent: 0,
|
||
|
boxWidth: this.defaultBoxWidth,
|
||
|
f: '',
|
||
|
fStyle: '',
|
||
|
fWeight: '',
|
||
|
fc: '',
|
||
|
j: '',
|
||
|
justifyOffset: '',
|
||
|
l: [],
|
||
|
lh: 0,
|
||
|
lineWidths: [],
|
||
|
ls: '',
|
||
|
of: '',
|
||
|
s: '',
|
||
|
sc: '',
|
||
|
sw: 0,
|
||
|
t: 0,
|
||
|
tr: 0,
|
||
|
sz: 0,
|
||
|
ps: null,
|
||
|
fillColorAnim: false,
|
||
|
strokeColorAnim: false,
|
||
|
strokeWidthAnim: false,
|
||
|
yOffset: 0,
|
||
|
finalSize: 0,
|
||
|
finalText: [],
|
||
|
finalLineHeight: 0,
|
||
|
__complete: false,
|
||
|
|
||
|
};
|
||
|
this.copyData(this.currentData, this.data.d.k[0].s);
|
||
|
|
||
|
if (!this.searchProperty()) {
|
||
|
this.completeTextData(this.currentData);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
TextProperty.prototype.defaultBoxWidth = [0, 0];
|
||
|
|
||
|
TextProperty.prototype.copyData = function (obj, data) {
|
||
|
for (var s in data) {
|
||
|
if (Object.prototype.hasOwnProperty.call(data, s)) {
|
||
|
obj[s] = data[s];
|
||
|
}
|
||
|
}
|
||
|
return obj;
|
||
|
};
|
||
|
|
||
|
TextProperty.prototype.setCurrentData = function (data) {
|
||
|
if (!data.__complete) {
|
||
|
this.completeTextData(data);
|
||
|
}
|
||
|
this.currentData = data;
|
||
|
this.currentData.boxWidth = this.currentData.boxWidth || this.defaultBoxWidth;
|
||
|
this._mdf = true;
|
||
|
};
|
||
|
|
||
|
TextProperty.prototype.searchProperty = function () {
|
||
|
return this.searchKeyframes();
|
||
|
};
|
||
|
|
||
|
TextProperty.prototype.searchKeyframes = function () {
|
||
|
this.kf = this.data.d.k.length > 1;
|
||
|
if (this.kf) {
|
||
|
this.addEffect(this.getKeyframeValue.bind(this));
|
||
|
}
|
||
|
return this.kf;
|
||
|
};
|
||
|
|
||
|
TextProperty.prototype.addEffect = function (effectFunction) {
|
||
|
this.effectsSequence.push(effectFunction);
|
||
|
this.elem.addDynamicProperty(this);
|
||
|
};
|
||
|
|
||
|
TextProperty.prototype.getValue = function (_finalValue) {
|
||
|
if ((this.elem.globalData.frameId === this.frameId || !this.effectsSequence.length) && !_finalValue) {
|
||
|
return;
|
||
|
}
|
||
|
this.currentData.t = this.data.d.k[this.keysIndex].s.t;
|
||
|
var currentValue = this.currentData;
|
||
|
var currentIndex = this.keysIndex;
|
||
|
if (this.lock) {
|
||
|
this.setCurrentData(this.currentData);
|
||
|
return;
|
||
|
}
|
||
|
this.lock = true;
|
||
|
this._mdf = false;
|
||
|
var i; var
|
||
|
len = this.effectsSequence.length;
|
||
|
var finalValue = _finalValue || this.data.d.k[this.keysIndex].s;
|
||
|
for (i = 0; i < len; i += 1) {
|
||
|
// Checking if index changed to prevent creating a new object every time the expression updates.
|
||
|
if (currentIndex !== this.keysIndex) {
|
||
|
finalValue = this.effectsSequence[i](finalValue, finalValue.t);
|
||
|
} else {
|
||
|
finalValue = this.effectsSequence[i](this.currentData, finalValue.t);
|
||
|
}
|
||
|
}
|
||
|
if (currentValue !== finalValue) {
|
||
|
this.setCurrentData(finalValue);
|
||
|
}
|
||
|
this.v = this.currentData;
|
||
|
this.pv = this.v;
|
||
|
this.lock = false;
|
||
|
this.frameId = this.elem.globalData.frameId;
|
||
|
};
|
||
|
|
||
|
TextProperty.prototype.getKeyframeValue = function () {
|
||
|
var textKeys = this.data.d.k;
|
||
|
var frameNum = this.elem.comp.renderedFrame;
|
||
|
var i = 0; var
|
||
|
len = textKeys.length;
|
||
|
while (i <= len - 1) {
|
||
|
if (i === len - 1 || textKeys[i + 1].t > frameNum) {
|
||
|
break;
|
||
|
}
|
||
|
i += 1;
|
||
|
}
|
||
|
if (this.keysIndex !== i) {
|
||
|
this.keysIndex = i;
|
||
|
}
|
||
|
return this.data.d.k[this.keysIndex].s;
|
||
|
};
|
||
|
|
||
|
TextProperty.prototype.buildFinalText = function (text) {
|
||
|
var charactersArray = [];
|
||
|
var i = 0;
|
||
|
var len = text.length;
|
||
|
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)) {
|
||
|
shouldCombine = true;
|
||
|
// It's a potential surrogate pair (this is the High surrogate)
|
||
|
} else if (charCode >= 0xD800 && charCode <= 0xDBFF) {
|
||
|
if (FontManager.isRegionalFlag(text, i)) {
|
||
|
currentChars = text.substr(i, 14);
|
||
|
} else {
|
||
|
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.isVariationSelector(charCode)) {
|
||
|
shouldCombine = true;
|
||
|
}
|
||
|
} else if (FontManager.isZeroWidthJoiner(charCode)) {
|
||
|
shouldCombine = true;
|
||
|
shouldCombineNext = true;
|
||
|
}
|
||
|
if (shouldCombine) {
|
||
|
charactersArray[charactersArray.length - 1] += currentChars;
|
||
|
shouldCombine = false;
|
||
|
} else {
|
||
|
charactersArray.push(currentChars);
|
||
|
}
|
||
|
i += currentChars.length;
|
||
|
}
|
||
|
return charactersArray;
|
||
|
};
|
||
|
|
||
|
TextProperty.prototype.completeTextData = function (documentData) {
|
||
|
documentData.__complete = true;
|
||
|
var fontManager = this.elem.globalData.fontManager;
|
||
|
var data = this.data;
|
||
|
var letters = [];
|
||
|
var i; var
|
||
|
len;
|
||
|
var newLineFlag; var index = 0; var
|
||
|
val;
|
||
|
var anchorGrouping = data.m.g;
|
||
|
var currentSize = 0; var currentPos = 0; var currentLine = 0; var
|
||
|
lineWidths = [];
|
||
|
var lineWidth = 0;
|
||
|
var maxLineWidth = 0;
|
||
|
var j; var
|
||
|
jLen;
|
||
|
var fontData = fontManager.getFontByName(documentData.f);
|
||
|
var charData; var
|
||
|
cLength = 0;
|
||
|
|
||
|
var fontProps = getFontProperties(fontData);
|
||
|
documentData.fWeight = fontProps.weight;
|
||
|
documentData.fStyle = fontProps.style;
|
||
|
documentData.finalSize = documentData.s;
|
||
|
documentData.finalText = this.buildFinalText(documentData.t);
|
||
|
len = documentData.finalText.length;
|
||
|
documentData.finalLineHeight = documentData.lh;
|
||
|
var trackingOffset = (documentData.tr / 1000) * documentData.finalSize;
|
||
|
var charCode;
|
||
|
if (documentData.sz) {
|
||
|
var flag = true;
|
||
|
var boxWidth = documentData.sz[0];
|
||
|
var boxHeight = documentData.sz[1];
|
||
|
var currentHeight; var
|
||
|
finalText;
|
||
|
while (flag) {
|
||
|
finalText = this.buildFinalText(documentData.t);
|
||
|
currentHeight = 0;
|
||
|
lineWidth = 0;
|
||
|
len = finalText.length;
|
||
|
trackingOffset = (documentData.tr / 1000) * documentData.finalSize;
|
||
|
var lastSpaceIndex = -1;
|
||
|
for (i = 0; i < len; i += 1) {
|
||
|
charCode = finalText[i].charCodeAt(0);
|
||
|
newLineFlag = false;
|
||
|
if (finalText[i] === ' ') {
|
||
|
lastSpaceIndex = i;
|
||
|
} else if (charCode === 13 || charCode === 3) {
|
||
|
lineWidth = 0;
|
||
|
newLineFlag = true;
|
||
|
currentHeight += documentData.finalLineHeight || documentData.finalSize * 1.2;
|
||
|
}
|
||
|
if (fontManager.chars) {
|
||
|
charData = fontManager.getCharData(finalText[i], fontData.fStyle, fontData.fFamily);
|
||
|
cLength = newLineFlag ? 0 : (charData.w * documentData.finalSize) / 100;
|
||
|
} else {
|
||
|
// tCanvasHelper.font = documentData.s + 'px '+ fontData.fFamily;
|
||
|
cLength = fontManager.measureText(finalText[i], documentData.f, documentData.finalSize);
|
||
|
}
|
||
|
if (lineWidth + cLength > boxWidth && finalText[i] !== ' ') {
|
||
|
if (lastSpaceIndex === -1) {
|
||
|
len += 1;
|
||
|
} else {
|
||
|
i = lastSpaceIndex;
|
||
|
}
|
||
|
currentHeight += documentData.finalLineHeight || documentData.finalSize * 1.2;
|
||
|
finalText.splice(i, lastSpaceIndex === i ? 1 : 0, '\r');
|
||
|
// finalText = finalText.substr(0,i) + "\r" + finalText.substr(i === lastSpaceIndex ? i + 1 : i);
|
||
|
lastSpaceIndex = -1;
|
||
|
lineWidth = 0;
|
||
|
} else {
|
||
|
lineWidth += cLength;
|
||
|
lineWidth += trackingOffset;
|
||
|
}
|
||
|
}
|
||
|
currentHeight += (fontData.ascent * documentData.finalSize) / 100;
|
||
|
if (this.canResize && documentData.finalSize > this.minimumFontSize && boxHeight < currentHeight) {
|
||
|
documentData.finalSize -= 1;
|
||
|
documentData.finalLineHeight = (documentData.finalSize * documentData.lh) / documentData.s;
|
||
|
} else {
|
||
|
documentData.finalText = finalText;
|
||
|
len = documentData.finalText.length;
|
||
|
flag = false;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
lineWidth = -trackingOffset;
|
||
|
cLength = 0;
|
||
|
var uncollapsedSpaces = 0;
|
||
|
var currentChar;
|
||
|
for (i = 0; i < len; i += 1) {
|
||
|
newLineFlag = false;
|
||
|
currentChar = documentData.finalText[i];
|
||
|
charCode = currentChar.charCodeAt(0);
|
||
|
if (charCode === 13 || charCode === 3) {
|
||
|
uncollapsedSpaces = 0;
|
||
|
lineWidths.push(lineWidth);
|
||
|
maxLineWidth = lineWidth > maxLineWidth ? lineWidth : maxLineWidth;
|
||
|
lineWidth = -2 * trackingOffset;
|
||
|
val = '';
|
||
|
newLineFlag = true;
|
||
|
currentLine += 1;
|
||
|
} else {
|
||
|
val = currentChar;
|
||
|
}
|
||
|
if (fontManager.chars) {
|
||
|
charData = fontManager.getCharData(currentChar, fontData.fStyle, fontManager.getFontByName(documentData.f).fFamily);
|
||
|
cLength = newLineFlag ? 0 : (charData.w * documentData.finalSize) / 100;
|
||
|
} else {
|
||
|
// var charWidth = fontManager.measureText(val, documentData.f, documentData.finalSize);
|
||
|
// tCanvasHelper.font = documentData.finalSize + 'px '+ fontManager.getFontByName(documentData.f).fFamily;
|
||
|
cLength = fontManager.measureText(val, documentData.f, documentData.finalSize);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
if (currentChar === ' ') {
|
||
|
uncollapsedSpaces += cLength + trackingOffset;
|
||
|
} else {
|
||
|
lineWidth += cLength + trackingOffset + uncollapsedSpaces;
|
||
|
uncollapsedSpaces = 0;
|
||
|
}
|
||
|
letters.push({
|
||
|
l: cLength, an: cLength, add: currentSize, n: newLineFlag, anIndexes: [], val: val, line: currentLine, animatorJustifyOffset: 0,
|
||
|
});
|
||
|
if (anchorGrouping == 2) { // eslint-disable-line eqeqeq
|
||
|
currentSize += cLength;
|
||
|
if (val === '' || val === ' ' || i === len - 1) {
|
||
|
if (val === '' || val === ' ') {
|
||
|
currentSize -= cLength;
|
||
|
}
|
||
|
while (currentPos <= i) {
|
||
|
letters[currentPos].an = currentSize;
|
||
|
letters[currentPos].ind = index;
|
||
|
letters[currentPos].extra = cLength;
|
||
|
currentPos += 1;
|
||
|
}
|
||
|
index += 1;
|
||
|
currentSize = 0;
|
||
|
}
|
||
|
} else if (anchorGrouping == 3) { // eslint-disable-line eqeqeq
|
||
|
currentSize += cLength;
|
||
|
if (val === '' || i === len - 1) {
|
||
|
if (val === '') {
|
||
|
currentSize -= cLength;
|
||
|
}
|
||
|
while (currentPos <= i) {
|
||
|
letters[currentPos].an = currentSize;
|
||
|
letters[currentPos].ind = index;
|
||
|
letters[currentPos].extra = cLength;
|
||
|
currentPos += 1;
|
||
|
}
|
||
|
currentSize = 0;
|
||
|
index += 1;
|
||
|
}
|
||
|
} else {
|
||
|
letters[index].ind = index;
|
||
|
letters[index].extra = 0;
|
||
|
index += 1;
|
||
|
}
|
||
|
}
|
||
|
documentData.l = letters;
|
||
|
maxLineWidth = lineWidth > maxLineWidth ? lineWidth : maxLineWidth;
|
||
|
lineWidths.push(lineWidth);
|
||
|
if (documentData.sz) {
|
||
|
documentData.boxWidth = documentData.sz[0];
|
||
|
documentData.justifyOffset = 0;
|
||
|
} else {
|
||
|
documentData.boxWidth = maxLineWidth;
|
||
|
switch (documentData.j) {
|
||
|
case 1:
|
||
|
documentData.justifyOffset = -documentData.boxWidth;
|
||
|
break;
|
||
|
case 2:
|
||
|
documentData.justifyOffset = -documentData.boxWidth / 2;
|
||
|
break;
|
||
|
default:
|
||
|
documentData.justifyOffset = 0;
|
||
|
}
|
||
|
}
|
||
|
documentData.lineWidths = lineWidths;
|
||
|
|
||
|
var animators = data.a; var animatorData; var
|
||
|
letterData;
|
||
|
jLen = animators.length;
|
||
|
var based; var ind; var
|
||
|
indexes = [];
|
||
|
for (j = 0; j < jLen; j += 1) {
|
||
|
animatorData = animators[j];
|
||
|
if (animatorData.a.sc) {
|
||
|
documentData.strokeColorAnim = true;
|
||
|
}
|
||
|
if (animatorData.a.sw) {
|
||
|
documentData.strokeWidthAnim = true;
|
||
|
}
|
||
|
if (animatorData.a.fc || animatorData.a.fh || animatorData.a.fs || animatorData.a.fb) {
|
||
|
documentData.fillColorAnim = true;
|
||
|
}
|
||
|
ind = 0;
|
||
|
based = animatorData.s.b;
|
||
|
for (i = 0; i < len; i += 1) {
|
||
|
letterData = letters[i];
|
||
|
letterData.anIndexes[j] = ind;
|
||
|
if ((based == 1 && letterData.val !== '') || (based == 2 && letterData.val !== '' && letterData.val !== ' ') || (based == 3 && (letterData.n || letterData.val == ' ' || i == len - 1)) || (based == 4 && (letterData.n || i == len - 1))) { // eslint-disable-line eqeqeq
|
||
|
if (animatorData.s.rn === 1) {
|
||
|
indexes.push(ind);
|
||
|
}
|
||
|
ind += 1;
|
||
|
}
|
||
|
}
|
||
|
data.a[j].s.totalChars = ind;
|
||
|
var currentInd = -1; var
|
||
|
newInd;
|
||
|
if (animatorData.s.rn === 1) {
|
||
|
for (i = 0; i < len; i += 1) {
|
||
|
letterData = letters[i];
|
||
|
if (currentInd != letterData.anIndexes[j]) { // eslint-disable-line eqeqeq
|
||
|
currentInd = letterData.anIndexes[j];
|
||
|
newInd = indexes.splice(Math.floor(Math.random() * indexes.length), 1)[0];
|
||
|
}
|
||
|
letterData.anIndexes[j] = newInd;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
documentData.yOffset = documentData.finalLineHeight || documentData.finalSize * 1.2;
|
||
|
documentData.ls = documentData.ls || 0;
|
||
|
documentData.ascent = (fontData.ascent * documentData.finalSize) / 100;
|
||
|
};
|
||
|
|
||
|
TextProperty.prototype.updateDocumentData = function (newData, index) {
|
||
|
index = index === undefined ? this.keysIndex : index;
|
||
|
var dData = this.copyData({}, this.data.d.k[index].s);
|
||
|
dData = this.copyData(dData, newData);
|
||
|
this.data.d.k[index].s = dData;
|
||
|
this.recalculate(index);
|
||
|
this.setCurrentData(dData);
|
||
|
this.elem.addDynamicProperty(this);
|
||
|
};
|
||
|
|
||
|
TextProperty.prototype.recalculate = function (index) {
|
||
|
var dData = this.data.d.k[index].s;
|
||
|
dData.__complete = false;
|
||
|
this.keysIndex = 0;
|
||
|
this._isFirstFrame = true;
|
||
|
this.getValue(dData);
|
||
|
};
|
||
|
|
||
|
TextProperty.prototype.canResizeFont = function (_canResize) {
|
||
|
this.canResize = _canResize;
|
||
|
this.recalculate(this.keysIndex);
|
||
|
this.elem.addDynamicProperty(this);
|
||
|
};
|
||
|
|
||
|
TextProperty.prototype.setMinimumFontSize = function (_fontValue) {
|
||
|
this.minimumFontSize = Math.floor(_fontValue) || 1;
|
||
|
this.recalculate(this.keysIndex);
|
||
|
this.elem.addDynamicProperty(this);
|
||
|
};
|
||
|
|
||
|
export default TextProperty;
|