| function TextAnimatorProperty(textData, renderType, elem) { |
| this._isFirstFrame = true; |
| this._hasMaskedPath = false; |
| this._frameId = -1; |
| this._textData = textData; |
| this._renderType = renderType; |
| this._elem = elem; |
| this._animatorsData = createSizedArray(this._textData.a.length); |
| this._pathData = {}; |
| this._moreOptions = { |
| alignment: {}, |
| }; |
| this.renderedLetters = []; |
| this.lettersChangedFlag = false; |
| this.initDynamicPropertyContainer(elem); |
| } |
| |
| TextAnimatorProperty.prototype.searchProperties = function () { |
| var i, |
| len = this._textData.a.length, |
| animatorProps; |
| var getProp = PropertyFactory.getProp; |
| for (i = 0; i < len; i += 1) { |
| animatorProps = this._textData.a[i]; |
| this._animatorsData[i] = new TextAnimatorDataProperty(this._elem, animatorProps, this); |
| } |
| if (this._textData.p && 'm' in this._textData.p) { |
| this._pathData = { |
| f: getProp(this._elem, this._textData.p.f, 0, 0, this), |
| l: getProp(this._elem, this._textData.p.l, 0, 0, this), |
| r: this._textData.p.r, |
| m: this._elem.maskManager.getMaskProperty(this._textData.p.m), |
| }; |
| this._hasMaskedPath = true; |
| } else { |
| this._hasMaskedPath = false; |
| } |
| this._moreOptions.alignment = getProp(this._elem, this._textData.m.a, 1, 0, this); |
| }; |
| |
| TextAnimatorProperty.prototype.getMeasures = function (documentData, lettersChangedFlag) { |
| this.lettersChangedFlag = lettersChangedFlag; |
| if (!this._mdf && !this._isFirstFrame && !lettersChangedFlag && (!this._hasMaskedPath || !this._pathData.m._mdf)) { |
| return; |
| } |
| this._isFirstFrame = false; |
| var alignment = this._moreOptions.alignment.v; |
| var animators = this._animatorsData; |
| var textData = this._textData; |
| var matrixHelper = this.mHelper; |
| var renderType = this._renderType; |
| var renderedLettersCount = this.renderedLetters.length; |
| var data = this.data; |
| var xPos, |
| yPos; |
| var i, |
| len; |
| var letters = documentData.l, |
| pathInfo, |
| currentLength, |
| currentPoint, |
| segmentLength, |
| flag, |
| pointInd, |
| segmentInd, |
| prevPoint, |
| points, |
| segments, |
| partialLength, |
| totalLength, |
| perc, |
| tanAngle, |
| mask; |
| if (this._hasMaskedPath) { |
| mask = this._pathData.m; |
| if (!this._pathData.n || this._pathData._mdf) { |
| var paths = mask.v; |
| if (this._pathData.r) { |
| paths = paths.reverse(); |
| } |
| // TODO: release bezier data cached from previous pathInfo: this._pathData.pi |
| pathInfo = { |
| tLength: 0, |
| segments: [], |
| }; |
| len = paths._length - 1; |
| var bezierData; |
| totalLength = 0; |
| for (i = 0; i < len; i += 1) { |
| bezierData = bez.buildBezierData(paths.v[i], |
| paths.v[i + 1], |
| [paths.o[i][0] - paths.v[i][0], paths.o[i][1] - paths.v[i][1]], |
| [paths.i[i + 1][0] - paths.v[i + 1][0], paths.i[i + 1][1] - paths.v[i + 1][1]]); |
| pathInfo.tLength += bezierData.segmentLength; |
| pathInfo.segments.push(bezierData); |
| totalLength += bezierData.segmentLength; |
| } |
| i = len; |
| if (mask.v.c) { |
| bezierData = bez.buildBezierData(paths.v[i], |
| paths.v[0], |
| [paths.o[i][0] - paths.v[i][0], paths.o[i][1] - paths.v[i][1]], |
| [paths.i[0][0] - paths.v[0][0], paths.i[0][1] - paths.v[0][1]]); |
| pathInfo.tLength += bezierData.segmentLength; |
| pathInfo.segments.push(bezierData); |
| totalLength += bezierData.segmentLength; |
| } |
| this._pathData.pi = pathInfo; |
| } |
| pathInfo = this._pathData.pi; |
| |
| currentLength = this._pathData.f.v; |
| segmentInd = 0; |
| pointInd = 1; |
| segmentLength = 0; |
| flag = true; |
| segments = pathInfo.segments; |
| if (currentLength < 0 && mask.v.c) { |
| if (pathInfo.tLength < Math.abs(currentLength)) { |
| currentLength = -Math.abs(currentLength) % pathInfo.tLength; |
| } |
| segmentInd = segments.length - 1; |
| points = segments[segmentInd].points; |
| pointInd = points.length - 1; |
| while (currentLength < 0) { |
| currentLength += points[pointInd].partialLength; |
| pointInd -= 1; |
| if (pointInd < 0) { |
| segmentInd -= 1; |
| points = segments[segmentInd].points; |
| pointInd = points.length - 1; |
| } |
| } |
| } |
| points = segments[segmentInd].points; |
| prevPoint = points[pointInd - 1]; |
| currentPoint = points[pointInd]; |
| partialLength = currentPoint.partialLength; |
| } |
| |
| len = letters.length; |
| xPos = 0; |
| yPos = 0; |
| var yOff = documentData.finalSize * 1.2 * 0.714; |
| var firstLine = true; |
| var animatorProps, |
| animatorSelector; |
| var j, |
| jLen; |
| var letterValue; |
| |
| jLen = animators.length; |
| var lastLetter; |
| |
| var mult, |
| ind = -1, |
| offf, |
| xPathPos, |
| yPathPos; |
| var initPathPos = currentLength, |
| initSegmentInd = segmentInd, |
| initPointInd = pointInd, |
| currentLine = -1; |
| var elemOpacity; |
| var sc, |
| sw, |
| fc, |
| k; |
| var lineLength = 0; |
| var letterSw, |
| letterSc, |
| letterFc, |
| letterM = '', |
| letterP = this.defaultPropsArray, |
| letterO; |
| |
| // |
| if (documentData.j === 2 || documentData.j === 1) { |
| var animatorJustifyOffset = 0; |
| var animatorFirstCharOffset = 0; |
| var justifyOffsetMult = documentData.j === 2 ? -0.5 : -1; |
| var lastIndex = 0; |
| var isNewLine = true; |
| |
| for (i = 0; i < len; i += 1) { |
| if (letters[i].n) { |
| if (animatorJustifyOffset) { |
| animatorJustifyOffset += animatorFirstCharOffset; |
| } |
| while (lastIndex < i) { |
| letters[lastIndex].animatorJustifyOffset = animatorJustifyOffset; |
| lastIndex += 1; |
| } |
| animatorJustifyOffset = 0; |
| isNewLine = true; |
| } else { |
| for (j = 0; j < jLen; j += 1) { |
| animatorProps = animators[j].a; |
| if (animatorProps.t.propType) { |
| if (isNewLine && documentData.j === 2) { |
| animatorFirstCharOffset += animatorProps.t.v * justifyOffsetMult; |
| } |
| animatorSelector = animators[j].s; |
| mult = animatorSelector.getMult(letters[i].anIndexes[j], textData.a[j].s.totalChars); |
| if (mult.length) { |
| animatorJustifyOffset += animatorProps.t.v * mult[0] * justifyOffsetMult; |
| } else { |
| animatorJustifyOffset += animatorProps.t.v * mult * justifyOffsetMult; |
| } |
| } |
| } |
| isNewLine = false; |
| } |
| } |
| if (animatorJustifyOffset) { |
| animatorJustifyOffset += animatorFirstCharOffset; |
| } |
| while (lastIndex < i) { |
| letters[lastIndex].animatorJustifyOffset = animatorJustifyOffset; |
| lastIndex += 1; |
| } |
| } |
| // |
| |
| for (i = 0; i < len; i += 1) { |
| matrixHelper.reset(); |
| elemOpacity = 1; |
| if (letters[i].n) { |
| xPos = 0; |
| yPos += documentData.yOffset; |
| yPos += firstLine ? 1 : 0; |
| currentLength = initPathPos; |
| firstLine = false; |
| lineLength = 0; |
| if (this._hasMaskedPath) { |
| segmentInd = initSegmentInd; |
| pointInd = initPointInd; |
| points = segments[segmentInd].points; |
| prevPoint = points[pointInd - 1]; |
| currentPoint = points[pointInd]; |
| partialLength = currentPoint.partialLength; |
| segmentLength = 0; |
| } |
| letterO = letterSw = letterFc = letterM = ''; |
| letterP = this.defaultPropsArray; |
| } else { |
| if (this._hasMaskedPath) { |
| if (currentLine !== letters[i].line) { |
| switch (documentData.j) { |
| case 1: |
| currentLength += totalLength - documentData.lineWidths[letters[i].line]; |
| break; |
| case 2: |
| currentLength += (totalLength - documentData.lineWidths[letters[i].line]) / 2; |
| break; |
| default: |
| break; |
| } |
| currentLine = letters[i].line; |
| } |
| if (ind !== letters[i].ind) { |
| if (letters[ind]) { |
| currentLength += letters[ind].extra; |
| } |
| currentLength += letters[i].an / 2; |
| ind = letters[i].ind; |
| } |
| currentLength += (alignment[0] * letters[i].an) * .005; |
| var animatorOffset = 0; |
| for (j = 0; j < jLen; j += 1) { |
| animatorProps = animators[j].a; |
| if (animatorProps.p.propType) { |
| animatorSelector = animators[j].s; |
| mult = animatorSelector.getMult(letters[i].anIndexes[j], textData.a[j].s.totalChars); |
| if (mult.length) { |
| animatorOffset += animatorProps.p.v[0] * mult[0]; |
| } else { |
| animatorOffset += animatorProps.p.v[0] * mult; |
| } |
| } |
| if (animatorProps.a.propType) { |
| animatorSelector = animators[j].s; |
| mult = animatorSelector.getMult(letters[i].anIndexes[j], textData.a[j].s.totalChars); |
| if (mult.length) { |
| animatorOffset += animatorProps.a.v[0] * mult[0]; |
| } else { |
| animatorOffset += animatorProps.a.v[0] * mult; |
| } |
| } |
| } |
| flag = true; |
| while (flag) { |
| if (segmentLength + partialLength >= currentLength + animatorOffset || !points) { |
| perc = (currentLength + animatorOffset - segmentLength) / currentPoint.partialLength; |
| xPathPos = prevPoint.point[0] + (currentPoint.point[0] - prevPoint.point[0]) * perc; |
| yPathPos = prevPoint.point[1] + (currentPoint.point[1] - prevPoint.point[1]) * perc; |
| matrixHelper.translate((-alignment[0] * letters[i].an) * .005, -(alignment[1] * yOff) * .01); |
| flag = false; |
| } else if (points) { |
| segmentLength += currentPoint.partialLength; |
| pointInd += 1; |
| if (pointInd >= points.length) { |
| pointInd = 0; |
| segmentInd += 1; |
| if (!segments[segmentInd]) { |
| if (mask.v.c) { |
| pointInd = 0; |
| segmentInd = 0; |
| points = segments[segmentInd].points; |
| } else { |
| segmentLength -= currentPoint.partialLength; |
| points = null; |
| } |
| } else { |
| points = segments[segmentInd].points; |
| } |
| } |
| if (points) { |
| prevPoint = currentPoint; |
| currentPoint = points[pointInd]; |
| partialLength = currentPoint.partialLength; |
| } |
| } |
| } |
| offf = letters[i].an / 2 - letters[i].add; |
| matrixHelper.translate(-offf, 0, 0); |
| } else { |
| offf = letters[i].an / 2 - letters[i].add; |
| matrixHelper.translate(-offf, 0, 0); |
| |
| // Grouping alignment |
| matrixHelper.translate((-alignment[0] * letters[i].an) * .005, (-alignment[1] * yOff) * .01, 0); |
| } |
| |
| lineLength += letters[i].l / 2; |
| for (j = 0; j < jLen; j += 1) { |
| animatorProps = animators[j].a; |
| if (animatorProps.t.propType) { |
| animatorSelector = animators[j].s; |
| mult = animatorSelector.getMult(letters[i].anIndexes[j], textData.a[j].s.totalChars); |
| // This condition is to prevent applying tracking to first character in each line. Might be better to use a boolean "isNewLine" |
| if (xPos !== 0 || documentData.j !== 0) { |
| if (this._hasMaskedPath) { |
| if (mult.length) { |
| currentLength += animatorProps.t.v * mult[0]; |
| } else { |
| currentLength += animatorProps.t.v * mult; |
| } |
| } else if (mult.length) { |
| xPos += animatorProps.t.v * mult[0]; |
| } else { |
| xPos += animatorProps.t.v * mult; |
| } |
| } |
| } |
| } |
| lineLength += letters[i].l / 2; |
| if (documentData.strokeWidthAnim) { |
| sw = documentData.sw || 0; |
| } |
| if (documentData.strokeColorAnim) { |
| if (documentData.sc) { |
| sc = [documentData.sc[0], documentData.sc[1], documentData.sc[2]]; |
| } else { |
| sc = [0, 0, 0]; |
| } |
| } |
| if (documentData.fillColorAnim && documentData.fc) { |
| fc = [documentData.fc[0], documentData.fc[1], documentData.fc[2]]; |
| } |
| for (j = 0; j < jLen; j += 1) { |
| animatorProps = animators[j].a; |
| if (animatorProps.a.propType) { |
| animatorSelector = animators[j].s; |
| mult = animatorSelector.getMult(letters[i].anIndexes[j], textData.a[j].s.totalChars); |
| |
| if (mult.length) { |
| matrixHelper.translate(-animatorProps.a.v[0] * mult[0], -animatorProps.a.v[1] * mult[1], animatorProps.a.v[2] * mult[2]); |
| } else { |
| matrixHelper.translate(-animatorProps.a.v[0] * mult, -animatorProps.a.v[1] * mult, animatorProps.a.v[2] * mult); |
| } |
| } |
| } |
| for (j = 0; j < jLen; j += 1) { |
| animatorProps = animators[j].a; |
| if (animatorProps.s.propType) { |
| animatorSelector = animators[j].s; |
| mult = animatorSelector.getMult(letters[i].anIndexes[j], textData.a[j].s.totalChars); |
| if (mult.length) { |
| matrixHelper.scale(1 + ((animatorProps.s.v[0] - 1) * mult[0]), 1 + ((animatorProps.s.v[1] - 1) * mult[1]), 1); |
| } else { |
| matrixHelper.scale(1 + ((animatorProps.s.v[0] - 1) * mult), 1 + ((animatorProps.s.v[1] - 1) * mult), 1); |
| } |
| } |
| } |
| for (j = 0; j < jLen; j += 1) { |
| animatorProps = animators[j].a; |
| animatorSelector = animators[j].s; |
| mult = animatorSelector.getMult(letters[i].anIndexes[j], textData.a[j].s.totalChars); |
| if (animatorProps.sk.propType) { |
| if (mult.length) { |
| matrixHelper.skewFromAxis(-animatorProps.sk.v * mult[0], animatorProps.sa.v * mult[1]); |
| } else { |
| matrixHelper.skewFromAxis(-animatorProps.sk.v * mult, animatorProps.sa.v * mult); |
| } |
| } |
| if (animatorProps.r.propType) { |
| if (mult.length) { |
| matrixHelper.rotateZ(-animatorProps.r.v * mult[2]); |
| } else { |
| matrixHelper.rotateZ(-animatorProps.r.v * mult); |
| } |
| } |
| if (animatorProps.ry.propType) { |
| if (mult.length) { |
| matrixHelper.rotateY(animatorProps.ry.v * mult[1]); |
| } else { |
| matrixHelper.rotateY(animatorProps.ry.v * mult); |
| } |
| } |
| if (animatorProps.rx.propType) { |
| if (mult.length) { |
| matrixHelper.rotateX(animatorProps.rx.v * mult[0]); |
| } else { |
| matrixHelper.rotateX(animatorProps.rx.v * mult); |
| } |
| } |
| if (animatorProps.o.propType) { |
| if (mult.length) { |
| elemOpacity += ((animatorProps.o.v) * mult[0] - elemOpacity) * mult[0]; |
| } else { |
| elemOpacity += ((animatorProps.o.v) * mult - elemOpacity) * mult; |
| } |
| } |
| if (documentData.strokeWidthAnim && animatorProps.sw.propType) { |
| if (mult.length) { |
| sw += animatorProps.sw.v * mult[0]; |
| } else { |
| sw += animatorProps.sw.v * mult; |
| } |
| } |
| if (documentData.strokeColorAnim && animatorProps.sc.propType) { |
| for (k = 0; k < 3; k += 1) { |
| if (mult.length) { |
| sc[k] += (animatorProps.sc.v[k] - sc[k]) * mult[0]; |
| } else { |
| sc[k] += (animatorProps.sc.v[k] - sc[k]) * mult; |
| } |
| } |
| } |
| if (documentData.fillColorAnim && documentData.fc) { |
| if (animatorProps.fc.propType) { |
| for (k = 0; k < 3; k += 1) { |
| if (mult.length) { |
| fc[k] += (animatorProps.fc.v[k] - fc[k]) * mult[0]; |
| } else { |
| fc[k] += (animatorProps.fc.v[k] - fc[k]) * mult; |
| } |
| } |
| } |
| if (animatorProps.fh.propType) { |
| if (mult.length) { |
| fc = addHueToRGB(fc, animatorProps.fh.v * mult[0]); |
| } else { |
| fc = addHueToRGB(fc, animatorProps.fh.v * mult); |
| } |
| } |
| if (animatorProps.fs.propType) { |
| if (mult.length) { |
| fc = addSaturationToRGB(fc, animatorProps.fs.v * mult[0]); |
| } else { |
| fc = addSaturationToRGB(fc, animatorProps.fs.v * mult); |
| } |
| } |
| if (animatorProps.fb.propType) { |
| if (mult.length) { |
| fc = addBrightnessToRGB(fc, animatorProps.fb.v * mult[0]); |
| } else { |
| fc = addBrightnessToRGB(fc, animatorProps.fb.v * mult); |
| } |
| } |
| } |
| } |
| |
| for (j = 0; j < jLen; j += 1) { |
| animatorProps = animators[j].a; |
| |
| if (animatorProps.p.propType) { |
| animatorSelector = animators[j].s; |
| mult = animatorSelector.getMult(letters[i].anIndexes[j], textData.a[j].s.totalChars); |
| if (this._hasMaskedPath) { |
| if (mult.length) { |
| matrixHelper.translate(0, animatorProps.p.v[1] * mult[0], -animatorProps.p.v[2] * mult[1]); |
| } else { |
| matrixHelper.translate(0, animatorProps.p.v[1] * mult, -animatorProps.p.v[2] * mult); |
| } |
| } else if (mult.length) { |
| matrixHelper.translate(animatorProps.p.v[0] * mult[0], animatorProps.p.v[1] * mult[1], -animatorProps.p.v[2] * mult[2]); |
| } else { |
| matrixHelper.translate(animatorProps.p.v[0] * mult, animatorProps.p.v[1] * mult, -animatorProps.p.v[2] * mult); |
| } |
| } |
| } |
| if (documentData.strokeWidthAnim) { |
| letterSw = sw < 0 ? 0 : sw; |
| } |
| if (documentData.strokeColorAnim) { |
| letterSc = 'rgb(' + Math.round(sc[0] * 255) + ',' + Math.round(sc[1] * 255) + ',' + Math.round(sc[2] * 255) + ')'; |
| } |
| if (documentData.fillColorAnim && documentData.fc) { |
| letterFc = 'rgb(' + Math.round(fc[0] * 255) + ',' + Math.round(fc[1] * 255) + ',' + Math.round(fc[2] * 255) + ')'; |
| } |
| |
| if (this._hasMaskedPath) { |
| matrixHelper.translate(0, -documentData.ls); |
| |
| matrixHelper.translate(0, (alignment[1] * yOff) * .01 + yPos, 0); |
| if (textData.p.p) { |
| tanAngle = (currentPoint.point[1] - prevPoint.point[1]) / (currentPoint.point[0] - prevPoint.point[0]); |
| var rot = (Math.atan(tanAngle) * 180) / Math.PI; |
| if (currentPoint.point[0] < prevPoint.point[0]) { |
| rot += 180; |
| } |
| matrixHelper.rotate((-rot * Math.PI) / 180); |
| } |
| matrixHelper.translate(xPathPos, yPathPos, 0); |
| currentLength -= (alignment[0] * letters[i].an) * .005; |
| if (letters[i + 1] && ind !== letters[i + 1].ind) { |
| currentLength += letters[i].an / 2; |
| currentLength += (documentData.tr * .001) * documentData.finalSize; |
| } |
| } else { |
| matrixHelper.translate(xPos, yPos, 0); |
| |
| if (documentData.ps) { |
| // matrixHelper.translate(documentData.ps[0],documentData.ps[1],0); |
| matrixHelper.translate(documentData.ps[0], documentData.ps[1] + documentData.ascent, 0); |
| } |
| switch (documentData.j) { |
| case 1: |
| matrixHelper.translate(letters[i].animatorJustifyOffset + documentData.justifyOffset + (documentData.boxWidth - documentData.lineWidths[letters[i].line]), 0, 0); |
| break; |
| case 2: |
| matrixHelper.translate(letters[i].animatorJustifyOffset + documentData.justifyOffset + (documentData.boxWidth - documentData.lineWidths[letters[i].line]) / 2, 0, 0); |
| break; |
| default: |
| break; |
| } |
| matrixHelper.translate(0, -documentData.ls); |
| matrixHelper.translate(offf, 0, 0); |
| matrixHelper.translate((alignment[0] * letters[i].an) * .005, (alignment[1] * yOff) * .01, 0); |
| xPos += letters[i].l + (documentData.tr * .001) * documentData.finalSize; |
| } |
| if (renderType === 'html') { |
| letterM = matrixHelper.toCSS(); |
| } else if (renderType === 'svg') { |
| letterM = matrixHelper.to2dCSS(); |
| } else { |
| letterP = [matrixHelper.props[0], matrixHelper.props[1], matrixHelper.props[2], matrixHelper.props[3], matrixHelper.props[4], matrixHelper.props[5], matrixHelper.props[6], matrixHelper.props[7], matrixHelper.props[8], matrixHelper.props[9], matrixHelper.props[10], matrixHelper.props[11], matrixHelper.props[12], matrixHelper.props[13], matrixHelper.props[14], matrixHelper.props[15]]; |
| } |
| letterO = elemOpacity; |
| } |
| |
| if (renderedLettersCount <= i) { |
| letterValue = new LetterProps(letterO, letterSw, letterSc, letterFc, letterM, letterP); |
| this.renderedLetters.push(letterValue); |
| renderedLettersCount += 1; |
| this.lettersChangedFlag = true; |
| } else { |
| letterValue = this.renderedLetters[i]; |
| this.lettersChangedFlag = letterValue.update(letterO, letterSw, letterSc, letterFc, letterM, letterP) || this.lettersChangedFlag; |
| } |
| } |
| }; |
| |
| TextAnimatorProperty.prototype.getValue = function () { |
| if (this._elem.globalData.frameId === this._frameId) { |
| return; |
| } |
| this._frameId = this._elem.globalData.frameId; |
| this.iterateDynamicProperties(); |
| }; |
| |
| TextAnimatorProperty.prototype.mHelper = new Matrix(); |
| TextAnimatorProperty.prototype.defaultPropsArray = []; |
| extendPrototype([DynamicPropertyContainer], TextAnimatorProperty); |