diff options
Diffstat (limited to 'filter/source/svg/presentation_engine.js')
-rw-r--r-- | filter/source/svg/presentation_engine.js | 487 |
1 files changed, 425 insertions, 62 deletions
diff --git a/filter/source/svg/presentation_engine.js b/filter/source/svg/presentation_engine.js index 636fc3a50d37..fa42b89b2f8e 100644 --- a/filter/source/svg/presentation_engine.js +++ b/filter/source/svg/presentation_engine.js @@ -763,7 +763,7 @@ function getDistance(p1, p2, props) { var x = p2[props[0]] - p1[props[0]], y = p2[props[1]] - p1[props[1]]; - return Math.sqrt((x * x) + (y * y)); + return Math.hypot(x, y); } /** @@ -2756,6 +2756,56 @@ function getElementsByProperty( node, name ) return elements; } +// User can hide / show the presentation content. +// For that purpose, we change the background color of root node to either black or white. +// To set it back to its original color (for showing the content back), we should have the initial background color saved somewhere to read back. +// There may be no initial color at all, so the initial value of the saved initial is undefined. +var rootNodeInitialBackgroundColor = undefined; + +function changeRootNodeBackgroundTo(color) { + if (rootNodeInitialBackgroundColor === undefined) + rootNodeInitialBackgroundColor = ROOT_NODE.style.backgroundColor; + + if (color === 'initial') + ROOT_NODE.style.backgroundColor = rootNodeInitialBackgroundColor; + else + ROOT_NODE.style.backgroundColor = color; +} + +var isContentHidden = false; +var contentInitialVisibilityValues = null; + +function getInitialVisibilityValues() { + var list = ROOT_NODE.querySelectorAll('g'); + contentInitialVisibilityValues = []; + for (var i = 0; i < list.length; i++) { + var temp = {}; + temp.object = list[i]; + temp.visibility = list[i].style.visibility; + contentInitialVisibilityValues.push(temp); + } +} + +function hideShowContent(color) { + if (contentInitialVisibilityValues === null) + getInitialVisibilityValues(); + + if (isContentHidden) { + for (var i = 0; i < contentInitialVisibilityValues.length; i++) + contentInitialVisibilityValues[i].object.style.visibility = contentInitialVisibilityValues[i].visibility; + + changeRootNodeBackgroundTo('initial'); + isContentHidden = false; + } + else { + for (var i = 0; i < contentInitialVisibilityValues.length; i++) + contentInitialVisibilityValues[i].object.style.visibility = 'hidden'; + + changeRootNodeBackgroundTo(color); + isContentHidden = true; + } +} + /** Event handler for key press. * * @param aEvt the event @@ -2765,7 +2815,7 @@ function onKeyDown( aEvt ) if ( !aEvt ) aEvt = window.event; - var code = aEvt.keyCode || aEvt.charCode; + var code = aEvt.keyCode || aEvt.charCode || aEvt.code; // console.log('===> onKeyDown: ' + code); @@ -2788,6 +2838,20 @@ function onKeyDown( aEvt ) // console.log(' now: ' + code); } + else if (code === P_KEY) { + aEvt.preventDefault(); + if (ROOT_NODE.style.cursor === 'pointer') + ROOT_NODE.style.cursor = 'default'; + else + ROOT_NODE.style.cursor = 'pointer'; + } + else if (code === W_KEY) { + hideShowContent('white'); + } + else if (code === B_KEY) { + hideShowContent('black'); + } + if( !processingEffect && keyCodeDictionary[currentMode] && keyCodeDictionary[currentMode][code] ) { @@ -4464,13 +4528,13 @@ var aOOOAttrTextAdjust = 'text-adjust'; // element class names var aClipPathGroupClassName = 'ClipPathGroup'; var aPageClassName = 'Page'; -var aSlideNumberClassName = 'Slide_Number'; -var aDateTimeClassName = 'Date/Time'; +var aSlideNumberClassName = 'PageNumber'; +var aDateTimeClassName = 'DateTime'; var aFooterClassName = 'Footer'; var aHeaderClassName = 'Header'; var aDateClassName = 'Date'; var aTimeClassName = 'Time'; -var aSlideNameClassName='SlideName'; +var aSlideNameClassName='PageName'; // Creating a namespace dictionary. var NSS = {}; @@ -4505,7 +4569,10 @@ var END_KEY = 35; // end keycode var ENTER_KEY = 13; var SPACE_KEY = 32; var ESCAPE_KEY = 27; +var B_KEY = 66; +var P_KEY = 80; var Q_KEY = 81; +var W_KEY = 87; // Visibility Values var HIDDEN = 0; @@ -4785,15 +4852,6 @@ function getRandomInt( nMax ) return Math.floor( Math.random() * nMax ); } -function isTextFieldElement( aElement ) // eslint-disable-line no-unused-vars -{ - var sClassName = aElement.getAttribute( 'class' ); - return ( sClassName === aSlideNumberClassName ) || - ( sClassName === aFooterClassName ) || - ( sClassName === aHeaderClassName ) || - ( sClassName === aDateTimeClassName ); -} - /********************* ** Debug Utilities ** @@ -5192,10 +5250,11 @@ initPlaceholderElements : function() for( ; i < aPlaceholderList.length; ++i ) { var aPlaceholderElem = aPlaceholderList[i]; - var sContent = aPlaceholderElem.textContent; - if( sContent === '<date>' ) + var sClass = aPlaceholderElem.getAttribute('class'); + var sFieldType = sClass.split(' ')[1]; + if( sFieldType === aDateClassName) aPlaceholderElem.textContent = new Date().toLocaleDateString(); - else if( sContent === '<time>' ) + else if( sFieldType === aTimeClassName ) aPlaceholderElem.textContent = new Date().toLocaleTimeString(); } }, @@ -5376,24 +5435,43 @@ getSlideAnimationsRoot : function() }; // end MetaSlide prototype -function getTextFieldType ( elem ) +function removeRedundantParagraphFromTextFieldShape( aObject ) { + var aTextElem = getElementByClassName( aObject, 'SVGTextShape' ); + if( aTextElem ) + { + var aPlaceholderElement = getElementsByClassName(aTextElem, 'PlaceholderText'); + if( aPlaceholderElement ) + { + var aTextParagraphSet = getElementsByClassName(aTextElem, 'TextParagraph'); + // When the text field width is too small, the placeholder text spans several lines. + // We remove all text lines but the first one which is used as a placeholder. + // This is a workaround but it should work in the majority of cases. + // A complete solution needs to support svg text wrapping. + if( aTextParagraphSet.length > 1 ) + { + var i = aTextParagraphSet.length; + while( i > 1 ) + { + aTextElem.removeChild(aTextParagraphSet[i - 1]); + --i; + } + } + } + } +} + +function getTextFieldType ( elem ) { var sFieldType = null; var sClass = elem.getAttribute('class'); - if( sClass == 'TextShape' ) + if( sClass === 'TextShape' ) { - var aPlaceholderElement = getElementByClassName( elem, 'PlaceholderText' ); - if (aPlaceholderElement) + var aPlaceholderElement = getElementByClassName(elem, 'PlaceholderText'); + if( aPlaceholderElement ) { - var sContent = aPlaceholderElement.textContent - if (sContent === '<number>') - sFieldType = aSlideNumberClassName; - else if (sContent === '<date>') - sFieldType = aDateClassName; - else if (sContent === '<time>') - sFieldType = aTimeClassName; - else if (sContent === '<slide-name>') - sFieldType = aSlideNameClassName; + var sClassAttr = aPlaceholderElement.getAttribute('class'); + var classes = sClassAttr.split(' '); + sFieldType = classes[1]; } } return sFieldType; @@ -5401,8 +5479,8 @@ function getTextFieldType ( elem ) function isTextFieldByClassName ( sClassName ) { - return sClassName === aDateTimeClassName || sClassName === aFooterClassName - || sClassName === aHeaderClassName || sClassName.indexOf( aSlideNumberClassName ) == 0 + return sClassName.indexOf( aDateTimeClassName ) == 0 || sClassName.indexOf( aFooterClassName ) == 0 + || sClassName.indexOf( aHeaderClassName ) == 0 || sClassName.indexOf( aSlideNumberClassName ) == 0 || sClassName.indexOf( aDateClassName ) == 0 || sClassName.indexOf( aTimeClassName ) == 0 || sClassName.indexOf( aSlideNameClassName ) == 0; } @@ -5421,7 +5499,7 @@ function isTextFieldByClassName ( sClassName ) * background image * </g> * <g class='BackgroundObjects'> - * <g class='Date/Time'> + * <g class='DateTime'> * date/time placeholder * </g> * <g class='Header'> @@ -5430,7 +5508,7 @@ function isTextFieldByClassName ( sClassName ) * <g class='Footer'> * footer placeholder * </g> - * <g class='Slide_Number'> + * <g class='PageNumber'> * slide number placeholder * </g> * shapes @@ -5487,6 +5565,7 @@ function MasterPage( sMasterPageId, aMetaSlide ) for( ; i < aBackgroundObjectList.length; ++i ) { var aObject = aBackgroundObjectList[i]; + removeRedundantParagraphFromTextFieldShape( aObject ); sClass = null; var sFieldType = getTextFieldType( aObject ); if( sFieldType && aObject.firstElementChild ) @@ -5501,6 +5580,12 @@ function MasterPage( sMasterPageId, aMetaSlide ) if( !sClass ) { sClass = aBackgroundObjectList[i].getAttribute('class'); + if( sClass === aDateTimeClassName || sClass === aFooterClassName + || sClass === aHeaderClassName || sClass === aSlideNumberClassName) + { + sClass += '.Default'; + aObject.setAttribute('class', sClass); + } } if( !sClass || !isTextFieldByClassName( sClass ) ) { @@ -5707,10 +5792,10 @@ PlaceholderShape.prototype.init = function() * <use class='Background'> // reference to master page background element * <g class='BackgroundObjects'> * <use class='BackgroundObjectSubGroup'> // reference to the group of shapes on the master page that are below text fields - * <g class='Slide_Number'> // a cloned element + * <g class='PageNumber'> // a cloned element * ... * </g> - * <use class='Date/Time'> // reference to a clone + * <use class='DateTime'> // reference to a clone * <use class='Footer'> * <use class='Header'> * <use class='BackgroundObjectSubGroup'> // reference to the group of shapes on the master page that are above text fields @@ -5834,7 +5919,7 @@ MasterPageView.prototype.createElement = function() // The cloned element is appended directly to the field group element // since there is no slide number field content shared between two slide // (because the slide number of two slide is always different). - var nIsPageNumberVisible = sId === aSlideNumberClassName ? this.aMetaSlide.nIsPageNumberVisible : true; + var nIsPageNumberVisible = sId === (aSlideNumberClassName + '.Default') ? this.aMetaSlide.nIsPageNumberVisible : true; if( aPlaceholderShapeSet[sId] && aPlaceholderShapeSet[sId].isValid() && nIsPageNumberVisible && @@ -5845,44 +5930,47 @@ MasterPageView.prototype.createElement = function() aTextFieldContentProviderSet[aSlideNumberClassName] ); aSlideNumberFieldHandler.update( this.aMetaSlide.nSlideNumber ); aSlideNumberFieldHandler.appendTo( this.aBackgroundObjectsElement ); - if ( sId === aSlideNumberClassName ) + if ( sId === aSlideNumberClassName + '.Default' ) this.aSlideNumberFieldHandler = aSlideNumberFieldHandler; } } - else if( sId === aDateTimeClassName ) + else if( sId === aDateTimeClassName + '.Default' ) { - // Date/Time field + // DateTime field if( this.aMetaSlide.nIsDateTimeVisible ) { this.aDateTimeFieldHandler = - this.initTextFieldHandler( aDateTimeClassName, aPlaceholderShapeSet, + this.initTextFieldHandler( sId, aPlaceholderShapeSet, aTextFieldContentProviderSet, aDefsElement, aTextFieldHandlerSet, sMasterSlideId ); } } - else if( sId === aFooterClassName ) + else if( sId === aFooterClassName + '.Default' ) { // Footer Field if( this.aMetaSlide.nIsFooterVisible ) { this.aFooterFieldHandler = - this.initTextFieldHandler( aFooterClassName, aPlaceholderShapeSet, + this.initTextFieldHandler( sId, aPlaceholderShapeSet, aTextFieldContentProviderSet, aDefsElement, aTextFieldHandlerSet, sMasterSlideId ); } } - else if( sId === aHeaderClassName ) + else if( sId === aHeaderClassName + '.Default' ) { // Header Field if( this.aMetaSlide.nIsHeaderVisible ) { this.aHeaderFieldHandler = - this.initTextFieldHandler( aHeaderClassName, aPlaceholderShapeSet, + this.initTextFieldHandler( sId, aPlaceholderShapeSet, aTextFieldContentProviderSet, aDefsElement, aTextFieldHandlerSet, sMasterSlideId ); } } - else if( sId.indexOf( aDateClassName ) == 0 + else if( sId.indexOf( aDateTimeClassName ) == 0 + || sId.indexOf( aFooterClassName ) == 0 + || sId.indexOf( aHeaderClassName ) == 0 + || sId.indexOf( aDateClassName ) == 0 || sId.indexOf( aTimeClassName ) == 0 || sId.indexOf( aSlideNameClassName ) == 0 ) { @@ -5922,21 +6010,21 @@ MasterPageView.prototype.initTextFieldHandler = if( aPlaceholderShape && aPlaceholderShape.isValid() && aTextFieldContentProvider ) { - var sTextFieldContentProviderId = aTextFieldContentProvider.sId; + var sTextFiedHandlerKey = aTextFieldContentProvider.sId + '.' + sId; // We create only one single TextFieldHandler object (and so one only // text field clone) per master slide and text content. - if ( !aTextFieldHandlerSet[ sMasterSlideId ][ sTextFieldContentProviderId ] ) + if ( !aTextFieldHandlerSet[ sMasterSlideId ][ sTextFiedHandlerKey ] ) { - aTextFieldHandlerSet[ sMasterSlideId ][ sTextFieldContentProviderId ] = + aTextFieldHandlerSet[ sMasterSlideId ][ sTextFiedHandlerKey ] = new TextFieldHandler( aPlaceholderShape, aTextFieldContentProvider ); - aTextFieldHandler = aTextFieldHandlerSet[ sMasterSlideId ][ sTextFieldContentProviderId ]; + aTextFieldHandler = aTextFieldHandlerSet[ sMasterSlideId ][ sTextFiedHandlerKey ]; aTextFieldHandler.update(); aTextFieldHandler.appendTo( aDefsElement ); } else { - aTextFieldHandler = aTextFieldHandlerSet[ sMasterSlideId ][ sTextFieldContentProviderId ]; + aTextFieldHandler = aTextFieldHandlerSet[ sMasterSlideId ][ sTextFiedHandlerKey ]; } sRefId = aTextFieldHandler.sId; } @@ -7033,6 +7121,8 @@ function matrixToString( aSVGMatrix ) // eslint-disable-next-line no-unused-vars function numberParser( sValue ) { + if( typeof sValue !== 'string' ) + return undefined; if( sValue === '.' ) return undefined; var reFloatNumber = /^[+-]?[0-9]*[.]?[0-9]*$/; @@ -7045,6 +7135,9 @@ function numberParser( sValue ) function booleanParser( sValue ) { + if( typeof sValue !== 'string' ) + return undefined; + sValue = sValue.toLowerCase(); if( sValue === 'true' ) return true; @@ -7056,6 +7149,9 @@ function booleanParser( sValue ) function colorParser( sValue ) { + if( typeof sValue !== 'string' ) + return undefined; + // The following 3 color functions are used in evaluating sValue string // so don't remove them. @@ -7989,6 +8085,7 @@ var ENUM_PROPERTY = 2; var COLOR_PROPERTY = 3; var STRING_PROPERTY = 4; var BOOL_PROPERTY = 5; +var TUPLE_NUMBER_PROPERTY = 6; var aValueTypeOutMap = [ 'unknown', 'number', 'enum', 'color', 'string', 'boolean' ]; @@ -8006,6 +8103,14 @@ var aAttributeMap = 'get': 'getOpacity', 'set': 'setOpacity' }, + 'scale': { 'type': TUPLE_NUMBER_PROPERTY, + 'get': 'getSize', + 'set': 'setSize' }, + + 'translate': { 'type': TUPLE_NUMBER_PROPERTY, + 'get': 'getPos', + 'set': 'setPos' }, + 'rotate': { 'type': NUMBER_PROPERTY, 'get': 'getRotationAngle', 'set': 'setRotationAngle' }, @@ -11574,6 +11679,70 @@ PropertyAnimationNode.prototype.createActivity = function() +function isValidTransformation( sType ) +{ + return ( sType === 'translate' || sType === 'scale' || sType === 'rotate' + || sType === 'skewX' || sType === 'skewY' ); +} + +function AnimationTransformNode( aAnimElem, aParentNode, aNodeContext ) +{ + AnimationTransformNode.superclass.constructor.call( this, aAnimElem, aParentNode, aNodeContext ); + + this.sClassName = 'AnimationTransformNode'; +} +extend( AnimationTransformNode, AnimationBaseNode3 ); + + +AnimationTransformNode.prototype.parseElement = function() +{ + var bRet = AnimationTransformNode.superclass.parseElement.call(this); + + var aAnimElem = this.aElement; + + // transformation type + var sTransformType = aAnimElem.getAttribute( 'svg:type' ); + if( !isValidTransformation( sTransformType ) ) + { + this.eCurrentState = INVALID_NODE; + log( 'AnimationTransformNode.parseElement: transformation type not found: ' + sTransformType ); + } + else + { + this.sAttributeName = sTransformType; + } + + return bRet; +} + +AnimationTransformNode.prototype.createActivity = function() +{ + var aActivityParamSet = this.fillActivityParams(); + var aAnimation; + + if( this.getAttributeName() === 'scale' || this.getAttributeName() === 'translate' ) + { + aAnimation = createPairPropertyAnimation( this.getAttributeName(), + this.getAnimatedElement(), + this.aNodeContext.aSlideWidth, + this.aNodeContext.aSlideHeight ); + + } + else + { + aAnimation = createPropertyAnimation( this.getAttributeName(), + this.getAnimatedElement(), + this.aNodeContext.aSlideWidth, + this.aNodeContext.aSlideHeight ); + } + + var aInterpolator = null; // createActivity will compute it; + return createActivity( aActivityParamSet, this, aAnimation, aInterpolator ); +}; + + + + function AnimationSetNode( aAnimElem, aParentNode, aNodeContext ) { AnimationSetNode.superclass.constructor.call( this, aAnimElem, aParentNode, aNodeContext ); @@ -11872,10 +12041,8 @@ function createAnimationNode( aElement, aParentNode, aNodeContext ) aCreatedNode = new AnimationColorNode( aElement, aParentNode, aNodeContext ); break; case ANIMATION_NODE_ANIMATETRANSFORM: - //aCreatedNode = new AnimationTransformNode( aElement, aParentNode, aNodeContext ); - //break; - log( 'createAnimationNode: ANIMATETRANSFORM not implemented' ); - return null; + aCreatedNode = new AnimationTransformNode( aElement, aParentNode, aNodeContext ); + break; case ANIMATION_NODE_TRANSITIONFILTER: aCreatedNode = new AnimationTransitionFilterNode( aElement, aParentNode, aNodeContext ); break; @@ -11998,6 +12165,41 @@ function createPropertyAnimation( sAttrName, aAnimatedElement, nWidth, nHeight ) +function createPairPropertyAnimation( sTransformType, aAnimatedElement, nWidth, nHeight ) +{ + var aFunctorSet = aAttributeMap[ sTransformType ]; + var sGetValueMethod = aFunctorSet.get; + var sSetValueMethod = aFunctorSet.set; + + var aDefaultValue = []; + var aSizeReference = []; + if( sTransformType === 'scale' ) + { + aDefaultValue[0] = aSizeReference[0] = aAnimatedElement.getBaseBBox().width; + aDefaultValue[1] = aSizeReference[1] = aAnimatedElement.getBaseBBox().height; + } + else if( sTransformType === 'translate' ) + { + aDefaultValue[0] = aAnimatedElement.getBaseCenterX(); + aDefaultValue[1] = aAnimatedElement.getBaseCenterY(); + aSizeReference[0] = nWidth; + aSizeReference[1] = nHeight; + } + else + { + log( 'createPairPropertyAnimation: transform type is not handled' ); + return null; + } + + return new TupleAnimation( bind( aAnimatedElement, aAnimatedElement[ sGetValueMethod ] ), + bind( aAnimatedElement, aAnimatedElement[ sSetValueMethod ] ), + aDefaultValue, + aSizeReference ); +} + + + + /** createShapeTransition * * @param aActivityParamSet @@ -12197,6 +12399,45 @@ GenericAnimation.prototype.getUnderlyingValue = function() +function TupleAnimation( aGetValueFunc, aSetValueFunc, aDefaultValue, aReferenceSize ) +{ + TupleAnimation.superclass.constructor.call( this, aGetValueFunc, aSetValueFunc ); + assert( aDefaultValue && aReferenceSize, + 'TupleAnimation constructor: default value functor and/or reference size are not valid' ); + + this.aDefaultValue = aDefaultValue; + this.aReferenceSize = aReferenceSize; +} +extend( TupleAnimation, GenericAnimation ); + +TupleAnimation.prototype.perform = function( aNormValue ) +{ + assert(aNormValue.length === this.aReferenceSize.length); + + var aValue = []; + for( var i = 0; i < aNormValue.length; ++i ) + { + aValue.push( aNormValue[i] * this.aReferenceSize[i] ); + } + + this.aSetValueFunc( aValue ); +}; + +TupleAnimation.prototype.getUnderlyingValue = function() +{ + var aValue = this.aGetValueFunc(); + assert(aValue.length === this.aReferenceSize.length); + + var aNormValue = []; + for( var i = 0; i < aValue.length; ++i ) + { + aNormValue.push( aValue[i] / this.aReferenceSize[i] ); + } + + return aNormValue; +}; + + function HSLAnimationWrapper( aColorAnimation ) { @@ -14514,6 +14755,11 @@ AnimatedElement.prototype.getY = function() return this.nCenterY; }; +AnimatedElement.prototype.getPos = function() +{ + return [this.getX(), this.getY()]; +}; + AnimatedElement.prototype.getWidth = function() { return this.nScaleFactorX * this.getBaseBBox().width; @@ -14524,6 +14770,11 @@ AnimatedElement.prototype.getHeight = function() return this.nScaleFactorY * this.getBaseBBox().height; }; +AnimatedElement.prototype.getSize = function() +{ + return [this.getWidth(), this.getHeight()]; +}; + AnimatedElement.prototype.updateTransformAttribute = function() { this.aTransformAttrList = this.aActiveElement.transform.baseVal; @@ -14553,12 +14804,27 @@ AnimatedElement.prototype.setY = function( nNewCenterY ) this.nCenterY = nNewCenterY; }; +AnimatedElement.prototype.setPos = function( aNewPos ) +{ + var nNewCenterX = aNewPos[0]; + var nNewCenterY = aNewPos[1]; + + if( nNewCenterX === this.nCenterX && nNewCenterY === this.nCenterY ) return; + + this.aTransformAttrList = this.aActiveElement.transform.baseVal; + this.aTransformAttr = this.aTransformAttrList.getItem( 0 ); + this.aTMatrix = this.aTransformAttr.matrix.translate( nNewCenterX - this.nCenterX, nNewCenterY - this.nCenterY ); + this.aTransformAttr.setMatrix( this.aTMatrix ); + this.nCenterX = nNewCenterX; + this.nCenterY = nNewCenterY; +}; + AnimatedElement.prototype.setWidth = function( nNewWidth ) { ANIMDBG.print( 'AnimatedElement.setWidth: nNewWidth = ' + nNewWidth ); if( nNewWidth < 0 ) { - log('AnimatedElement(' + this.getId() + ').setWidth: negative height!'); + log('AnimatedElement(' + this.getId() + ').setWidth: negative width!'); nNewWidth = 0; } @@ -14603,6 +14869,43 @@ AnimatedElement.prototype.setHeight = function( nNewHeight ) this.nScaleFactorY = nScaleFactorY; }; +AnimatedElement.prototype.setSize= function( aNewSize ) +{ + var nNewWidth = aNewSize[0]; + var nNewHeight = aNewSize[1]; + ANIMDBG.print( 'AnimatedElement.setSize: = [' + nNewWidth + ',' + nNewHeight + ']'); + if( nNewWidth < 0 ) + { + log('AnimatedElement(' + this.getId() + ').setSize: negative width!'); + nNewWidth = 0; + } + if( nNewHeight < 0 ) + { + log('AnimatedElement(' + this.getId() + ').setSize: negative height!'); + nNewHeight = 0; + } + + var nBaseWidth = this.getBaseBBox().width; + var nScaleFactorX = nNewWidth / nBaseWidth; + if( nScaleFactorX < 1e-5 ) nScaleFactorX = 1e-5; + + var nBaseHeight = this.getBaseBBox().height; + var nScaleFactorY = nNewHeight / nBaseHeight; + if( nScaleFactorY < 1e-5 ) nScaleFactorY = 1e-5; + + if( nScaleFactorX == this.nScaleFactorX && nScaleFactorY == this.nScaleFactorY ) return; + + this.aTMatrix = document.documentElement.createSVGMatrix() + .translate( this.nCenterX, this.nCenterY ) + .rotate(this.nRotationAngle) + .scaleNonUniform( nScaleFactorX, nScaleFactorY ) + .translate( -this.nBaseCenterX, -this.nBaseCenterY ); + this.updateTransformAttribute(); + + this.nScaleFactorX = nScaleFactorX; + this.nScaleFactorY = nScaleFactorY; +}; + AnimatedElement.prototype.getOpacity = function() { return this.aActiveElement.getAttribute( 'opacity' ); @@ -14807,7 +15110,7 @@ function AnimatedTextElement( aElement, aEventMultiplexer ) if( aBulletPlaceholderElem ) { var sId = aBulletPlaceholderElem.getAttribute( 'id' ); - sId = 'bullet-char(' + sId + ')'; + sId = 'bullet-char-' + sId; aBulletCharElem = theDocument.getElementById( sId ); if( aBulletCharElem ) { @@ -16336,6 +16639,17 @@ aInterpolatorHandler.aLerpFunctorMap[ CALC_MODE_LINEAR ][ COLOR_PROPERTY ][ COLO }; }; +aInterpolatorHandler.aLerpFunctorMap[ CALC_MODE_LINEAR ][ TUPLE_NUMBER_PROPERTY ] = + function ( aFrom, aTo, nT ) + { + var aRes = []; + for( var i = 0; i < aFrom.length; ++i ) + { + aRes.push( ( 1.0 - nT )* aFrom[i] + nT * aTo[i] ); + } + return aRes; + }; + @@ -16503,6 +16817,36 @@ aOperatorSetMap[ STRING_PROPERTY ] = aOperatorSetMap[ ENUM_PROPERTY ]; // bool operators aOperatorSetMap[ BOOL_PROPERTY ] = aOperatorSetMap[ ENUM_PROPERTY ]; +// tuple number operators +aOperatorSetMap[ TUPLE_NUMBER_PROPERTY ] = {}; + +aOperatorSetMap[ TUPLE_NUMBER_PROPERTY ].equal = function( a, b ) +{ + assert( a.length === b.length, 'Tuples length mismatch.' ); + return ( a.toString() === b.toString() ); +}; + +aOperatorSetMap[ TUPLE_NUMBER_PROPERTY ].add = function( a, b ) +{ + assert( a.length === b.length, 'Tuples length mismatch.' ); + var r = []; + for( var i = 0; i < a.length; ++i ) + { + r.push(a[i] + b[i]); + } + return r; +}; + +aOperatorSetMap[ TUPLE_NUMBER_PROPERTY ].scale = function( k, v ) +{ + var r = []; + for( var i = 0; i < v.length; ++i ) + { + r.push(k * v[i]); + } + return r; +}; + @@ -17912,6 +18256,22 @@ function extractAttributeValues( eValueType, aValueList, aValueSet, aBBox, nSlid aValueList.push( aValue ); } break; + case TUPLE_NUMBER_PROPERTY : + for( i = 0; i < aValueSet.length; ++i ) + { + if( typeof aValueSet[i] === 'string' ) + { + var aTuple = aValueSet[i].split(','); + aValue = []; + evalValuesAttribute(aValue, aTuple, aBBox, nSlideWidth, nSlideHeight); + aValueList.push(aValue); + } + else + { + aValueList.push( undefined ); + } + } + break; default: log( 'createValueListActivity: unexpected value type: ' + eValueType ); } @@ -17934,9 +18294,12 @@ function evalValuesAttribute( aValueList, aValueSet, aBBox, nSlideWidth, nSlideH for( var i = 0; i < aValueSet.length; ++i ) { var sValue = aValueSet[i]; - sValue = sValue.replace(reMath, 'Math.$&'); - sValue = sValue.replace(/pi(?!\w)/g, 'Math.PI'); - sValue = sValue.replace(/e(?!\w)/g, 'Math.E'); + if(sValue) + { + sValue = sValue.replace(reMath, 'Math.$&'); + sValue = sValue.replace(/pi(?!\w)/g, 'Math.PI'); + sValue = sValue.replace(/e(?!\w)/g, 'Math.E'); + } var aValue = eval( sValue ); aValueList.push( aValue ); } @@ -18622,8 +18985,8 @@ SlideShow.prototype.exitSlideShowInApp = function() { if (window.webkit !== undefined && window.webkit.messageHandlers !== undefined && - window.webkit.messageHandlers.lool !== undefined) - window.webkit.messageHandlers.lool.postMessage('EXITSLIDESHOW', '*'); + window.webkit.messageHandlers.lok !== undefined) + window.webkit.messageHandlers.lok.postMessage('EXITSLIDESHOW', '*'); } SlideShow.prototype.displaySlide = function( nNewSlide, bSkipSlideTransition ) |