| function TextProperty(elem, data) { |
| this._frameId = initialDefaultFrame; |
| this.pv = ''; |
| this.v = ''; |
| this.kf = false; |
| this._isFirstFrame = true; |
| this._mdf = false; |
| 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 (data.hasOwnProperty(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 multipliedValue; |
| var i, 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.pv = this.v = this.currentData; |
| this.lock = false; |
| this.frameId = this.elem.globalData.frameId; |
| }; |
| |
| TextProperty.prototype.getKeyframeValue = function () { |
| var textKeys = this.data.d.k, textDocumentData; |
| var frameNum = this.elem.comp.renderedFrame; |
| var i = 0, len = textKeys.length; |
| while (i <= len - 1) { |
| textDocumentData = textKeys[i].s; |
| 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 combinedCharacters = FontManager.getCombinedCharacterCodes(); |
| var charactersArray = []; |
| var i = 0, len = text.length; |
| var charCode; |
| while (i < len) { |
| charCode = text.charCodeAt(i); |
| if (combinedCharacters.indexOf(charCode) !== -1) { |
| charactersArray[charactersArray.length - 1] += text.charAt(i); |
| } else { |
| if (charCode >= 0xD800 && charCode <= 0xDBFF) { |
| charCode = text.charCodeAt(i + 1); |
| if (charCode >= 0xDC00 && charCode <= 0xDFFF) { |
| charactersArray.push(text.substr(i, 2)); |
| ++i; |
| } else { |
| charactersArray.push(text.charAt(i)); |
| } |
| } else { |
| charactersArray.push(text.charAt(i)); |
| } |
| } |
| i += 1; |
| } |
| return charactersArray; |
| }; |
| |
| TextProperty.prototype.completeTextData = function (documentData) { |
| documentData.__complete = true; |
| var fontManager = this.elem.globalData.fontManager; |
| var data = this.data; |
| var letters = []; |
| var i, len; |
| var newLineFlag, index = 0, val; |
| var anchorGrouping = data.m.g; |
| var currentSize = 0, currentPos = 0, currentLine = 0, lineWidths = []; |
| var lineWidth = 0; |
| var maxLineWidth = 0; |
| var j, jLen; |
| var fontData = fontManager.getFontByName(documentData.f); |
| var charData, cLength = 0; |
| var styles = fontData.fStyle ? fontData.fStyle.split(' ') : []; |
| |
| var fWeight = 'normal', fStyle = 'normal'; |
| len = styles.length; |
| var styleName; |
| for (i = 0; i < len; i += 1) { |
| styleName = styles[i].toLowerCase(); |
| switch (styleName) { |
| case 'italic': |
| fStyle = 'italic'; |
| break; |
| case 'bold': |
| fWeight = '700'; |
| break; |
| case 'black': |
| fWeight = '900'; |
| break; |
| case 'medium': |
| fWeight = '500'; |
| break; |
| case 'regular': |
| case 'normal': |
| fWeight = '400'; |
| break; |
| case 'light': |
| case 'thin': |
| fWeight = '200'; |
| break; |
| } |
| } |
| documentData.fWeight = fontData.fWeight || fWeight; |
| documentData.fStyle = fStyle; |
| 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, 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) { |
| 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) { |
| 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, animatorData, letterData; |
| jLen = animators.length; |
| var based, ind, 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))) { |
| if (animatorData.s.rn === 1) { |
| indexes.push(ind); |
| } |
| ind += 1; |
| } |
| } |
| data.a[j].s.totalChars = ind; |
| var currentInd = -1, newInd; |
| if (animatorData.s.rn === 1) { |
| for (i = 0; i < len; i += 1) { |
| letterData = letters[i]; |
| if (currentInd != letterData.anIndexes[j]) { |
| 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.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); |
| }; |