summaryrefslogtreecommitdiffstats
path: root/filter/source/svg/presentation_engine.js
diff options
context:
space:
mode:
Diffstat (limited to 'filter/source/svg/presentation_engine.js')
-rw-r--r--filter/source/svg/presentation_engine.js487
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 )