[Libreoffice-commits] .: 9 commits - filter/source
Marco Cecchetti
mcecchetti at kemper.freedesktop.org
Fri Jun 15 01:30:29 PDT 2012
filter/source/svg/js2hxx.py | 7
filter/source/svg/presentation_engine.js | 4830 +++++++++++++++++++++++++------
filter/source/svg/svgexport.cxx | 373 +-
filter/source/svg/svgfilter.hxx | 14
4 files changed, 4262 insertions(+), 962 deletions(-)
New commits:
commit a7bd0355844f5bc4a3717df059ecfa5743b041fe
Author: Marco Cecchetti <mrcekets at gmail.com>
Date: Sat Jun 9 19:55:50 2012 +0200
Fixed a bug related to text fields introduced on the last commit.
diff --git a/filter/source/svg/presentation_engine.js b/filter/source/svg/presentation_engine.js
index 73e0bf7..1ce3e16 100644
--- a/filter/source/svg/presentation_engine.js
+++ b/filter/source/svg/presentation_engine.js
@@ -1952,10 +1952,6 @@ PlaceholderShape.prototype.init = function()
var aTextFieldElement = getElementByClassName( this.masterPage.backgroundObjects, this.className );
if( aTextFieldElement )
{
- var sVisibility = aTextFieldElement.getAttribute( 'visibility' );
- if( sVisibility == 'hidden' )
- return;
-
var aPlaceholderElement = getElementByClassName( aTextFieldElement, 'PlaceholderText' );
if( aPlaceholderElement )
{
@@ -2131,7 +2127,8 @@ MasterPageView.prototype.createElement = function()
// (because the slide number of two slide is always different).
if( aPlaceholderShapeSet[aSlideNumberClassName] &&
aPlaceholderShapeSet[aSlideNumberClassName].isValid() &&
- this.aMetaSlide.nIsPageNumberVisible )
+ this.aMetaSlide.nIsPageNumberVisible &&
+ aTextFieldContentProviderSet[aSlideNumberClassName] )
{
this.aSlideNumberFieldHandler =
new SlideNumberFieldHandler( aPlaceholderShapeSet[aSlideNumberClassName],
@@ -2188,7 +2185,8 @@ function( sClassName, aPlaceholderShapeSet, aTextFieldContentProviderSet,
{
var aTextFieldHandler = null;
if( aPlaceholderShapeSet[sClassName] &&
- aPlaceholderShapeSet[sClassName].isValid() )
+ aPlaceholderShapeSet[sClassName].isValid()
+ && aTextFieldContentProviderSet[sClassName] )
{
var sTextFieldContentProviderId = aTextFieldContentProviderSet[sClassName].sId;
// We create only one single TextFieldHandler object (and so one only
commit 61360495ac22065c5de08f55ec6dd8144a25b1aa
Author: Marco Cecchetti <mrcekets at gmail.com>
Date: Sat Jun 9 17:43:28 2012 +0200
Provided support for clipping-based shape transitions (barnWipe,
fourBoxWipe, ellipseWipe, pinWheelWipe). Basic support for reverse
method by subtraction.
Ported or implemented the following classes or functions:
createShapeTransition, ClippingAnimation.
Extended the following SVG DOM classes: SVGPathElement (prependPath
method).
Modified and added new methods to: AnimatedElement, ClippingFunctor,
EllipseWipePath, FourBoxWipePath.
diff --git a/filter/source/svg/presentation_engine.js b/filter/source/svg/presentation_engine.js
index 0b09ffe..73e0bf7 100644
--- a/filter/source/svg/presentation_engine.js
+++ b/filter/source/svg/presentation_engine.js
@@ -395,7 +395,7 @@ function indexSetPageSlide( nIndex )
/***** **********************************************************************
*
- * The "New" BSD License:
+ * The 'New' BSD License:
* **********************
* Copyright (c) 2005-2012, The Dojo Foundation
* All rights reserved.
@@ -412,7 +412,7 @@ function indexSetPageSlide( nIndex )
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
@@ -1669,8 +1669,8 @@ function MetaSlide( sMetaSlideId, aMetaDoc )
if( this.bHasTransition )
{
this.aTransitionHandler = new SlideTransition( this.getSlideAnimationsRoot(), this.slideId );
- if( this.aTransitionHandler.isValid() )
- log( this.aTransitionHandler.info() );
+ //if( this.aTransitionHandler.isValid() )
+ // log( this.aTransitionHandler.info() );
}
// We initialize the SlideAnimationsHandler object
@@ -1952,6 +1952,10 @@ PlaceholderShape.prototype.init = function()
var aTextFieldElement = getElementByClassName( this.masterPage.backgroundObjects, this.className );
if( aTextFieldElement )
{
+ var sVisibility = aTextFieldElement.getAttribute( 'visibility' );
+ if( sVisibility == 'hidden' )
+ return;
+
var aPlaceholderElement = getElementByClassName( aTextFieldElement, 'PlaceholderText' );
if( aPlaceholderElement )
{
@@ -3641,6 +3645,25 @@ SVGMatrix.prototype.setToRotationAroundPoint = function( nX, nY, nAngle )
* SVGPath extensions
**********************************************************************************************/
+/** SVGPathElement.prependPath
+ * Merge the two path together by inserting the passed path before this one.
+ *
+ * @param aPath
+ * An object of type SVGPathElement to be prepended.
+ */
+SVGPathElement.prototype.prependPath = function( aPath )
+{
+ var sPathData = aPath.getAttribute( 'd' );
+ sPathData += ( ' ' + this.getAttribute( 'd' ) );
+ this.setAttribute( 'd', sPathData );
+};
+
+/** SVGPathElement.appendPath
+ * Merge the two path together by inserting the passed path after this one.
+ *
+ * @param aPath
+ * An object of type SVGPathElement to be appended.
+ */
SVGPathElement.prototype.appendPath = function( aPath )
{
var sPathData = this.getAttribute( 'd' );
@@ -6590,15 +6613,11 @@ AnimationTransitionFilterNode.prototype.createActivity = function()
{
var aActivityParamSet = this.fillActivityParams();
- var aAnimation = createPropertyAnimation( 'opacity',
- this.getAnimatedElement(),
- this.aNodeContext.aSlideWidth,
- this.aNodeContext.aSlideHeight );
-
- var eDirection = this.getTransitionMode() ? FORWARD : BACKWARD;
-
- return new SimpleActivity( aActivityParamSet, aAnimation, eDirection );
-
+ return createShapeTransition( aActivityParamSet,
+ this.getAnimatedElement(),
+ this.aNodeContext.aSlideWidth,
+ this.aNodeContext.aSlideHeight,
+ this );
};
AnimationTransitionFilterNode.prototype.parseElement = function()
@@ -6863,6 +6882,152 @@ function createPropertyAnimation( sAttrName, aAnimatedElement, nWidth, nHeight )
// ------------------------------------------------------------------------------------------ //
+/** createShapeTransition
+ *
+ * @param aActivityParamSet
+ * The set of property for the activity to be created.
+ * @param aAnimatedElement
+ * The element to be animated.
+ * @param nSlideWidth
+ * The width of a slide.
+ * @param nSlideHeight
+ * The height of a slide.
+ * @param aAnimatedTransitionFilterNode
+ * An instance of the AnimationFilterNode that invoked this function.
+ * @return {SimpleActivity}
+ * A simple activity handling a shape transition.
+ */
+function createShapeTransition( aActivityParamSet, aAnimatedElement,
+ nSlideWidth, nSlideHeight,
+ aAnimatedTransitionFilterNode )
+{
+ if( !aAnimatedTransitionFilterNode )
+ {
+ log( 'createShapeTransition: the animated transition filter node is not valid.' );
+ return null;
+ }
+ var eTransitionType = aAnimatedTransitionFilterNode.getTransitionType();
+ var eTransitionSubType = aAnimatedTransitionFilterNode.getTransitionSubType();
+ var bDirectionForward = ! aAnimatedTransitionFilterNode.getReverseDirection();
+ var bModeIn = ( aAnimatedTransitionFilterNode.getTransitionMode() == FORWARD );
+
+ var aTransitionInfo = aTransitionInfoTable[eTransitionType][eTransitionSubType];
+ var eTransitionClass = aTransitionInfo['class'];
+
+ switch( eTransitionClass )
+ {
+ default:
+ case TRANSITION_INVALID:
+ log( 'createShapeTransition: transition class: TRANSITION_INVALID' );
+ return null;
+
+ case TRANSITION_CLIP_POLYPOLYGON:
+ var aParametricPolyPolygon
+ = createClipPolyPolygon( eTransitionType, eTransitionSubType );
+ var aClippingAnimation
+ = new ClippingAnimation( aParametricPolyPolygon, aTransitionInfo,
+ bDirectionForward, bModeIn );
+ return new SimpleActivity( aActivityParamSet, aClippingAnimation, true );
+
+ case TRANSITION_SPECIAL:
+ switch( eTransitionType )
+ {
+ // no special transition filter provided
+ // we map everything to crossfade
+ default:
+ var aAnimation
+ = createPropertyAnimation( 'opacity',
+ aAnimatedElement,
+ nSlideWidth,
+ nSlideHeight );
+ return new SimpleActivity( aActivityParamSet, aAnimation, bModeIn );
+ }
+ }
+
+}
+
+
+
+// ------------------------------------------------------------------------------------------ //
+/** Class ClippingAnimation
+ * This class performs a shape transition where the effect is achieved by
+ * clipping the shape to be animated with a parametric path.
+ *
+ * @param aParametricPolyPolygon
+ * An object handling a <path> element that depends on a parameter.
+ * @param aTransitionInfo
+ * The set of parameters defining the shape transition to be performed.
+ * @param bDirectionForward
+ * The direction the shape transition has to be performed.
+ * @param bModeIn
+ * If true the element to be animated becomes more visible as the transition
+ * progress else it becomes less visible.
+ */
+function ClippingAnimation( aParametricPolyPolygon, aTransitionInfo,
+ bDirectionForward, bModeIn )
+{
+ this.aClippingFunctor = new ClippingFunctor( aParametricPolyPolygon,
+ aTransitionInfo,
+ bDirectionForward, bModeIn );
+ this.bAnimationStarted = false;
+}
+
+/** start
+ * This method notifies to the element involved in the transition that
+ * the animation is starting and creates the <clipPath> element used for
+ * the transition.
+ *
+ * @param aAnimatableElement
+ * The element to be animated.
+ */
+ClippingAnimation.prototype.start = function( aAnimatableElement )
+{
+ assert( aAnimatableElement,
+ 'ClippingAnimation.start: animatable element is not valid' );
+ this.aAnimatableElement = aAnimatableElement;
+ this.aAnimatableElement.initClipPath();
+ this.aAnimatableElement.notifyAnimationStart();
+
+ if( !this.bAnimationStarted )
+ this.bAnimationStarted = true;
+
+};
+
+/** end
+ * The transition clean up is performed here.
+ */
+ClippingAnimation.prototype.end = function()
+{
+ if( this.bAnimationStarted )
+ {
+ this.aAnimatableElement.cleanClipPath();
+ this.bAnimationStarted = false;
+ }
+};
+
+/** perform
+ * This method set the position of the element to be animated according to
+ * the passed time value.
+ *
+ * @param nValue
+ * The time parameter.
+ */
+ClippingAnimation.prototype.perform = function( nValue )
+{
+ var nWidth = this.aAnimatableElement.aClippingBBox.width;
+ var nHeight = this.aAnimatableElement.aClippingBBox.height;
+ var aPolyPolygonElement = this.aClippingFunctor.perform( nValue, nWidth, nHeight );
+ this.aAnimatableElement.setClipPath( aPolyPolygonElement );
+};
+
+ClippingAnimation.prototype.getUnderlyingValue = function()
+{
+ return 0.0;
+};
+
+
+
+// ------------------------------------------------------------------------------------------ //
function GenericAnimation( aGetValueFunc, aSetValueFunc, aGetModifier, aSetModifier )
{
assert( aGetValueFunc && aSetValueFunc,
@@ -6968,7 +7133,7 @@ SlideChangeBase.prototype.start = function()
return;
};
-/** start
+/** end
* The transition clean up is performed here.
*/
SlideChangeBase.prototype.end = function()
@@ -7408,6 +7573,11 @@ function ClippingFunctor( aParametricPolyPolygon, aTransitionInfo,
}
}
+// This path is used when the direction is the reverse one and
+// the reverse method type is the subtraction type.
+ClippingFunctor.aBoundingPath = document.createElementNS( NSS['svg'], 'path' );
+ClippingFunctor.aBoundingPath.setAttribute( 'd', 'M -1 -1 L 2 -1 L 2 2 L -1 2 L -1 -1' );
+
/** perform
*
* @param nT
@@ -7429,7 +7599,8 @@ ClippingFunctor.prototype.perform = function( nT, nWidth, nHeight )
if( this.bSubtractPolygon )
{
-
+ aClipPoly.changeOrientation();
+ aClipPoly.prependPath( ClippingFunctor.aBoundingPath );
}
var aMatrix;
@@ -7635,7 +7806,11 @@ FourBoxWipePath.prototype.perform = function( nT )
aSquare.changeOrientation();
aPolyPath.appendPath( aSquare );
+ // Remind: operations are applied in inverse order
aMatrix = SVGIdentityMatrix.translate( 0.5, 0.5 );
+ // We enlarge a bit the clip path so we avoid that in reverse direction
+ // some thin line of the border stroke is visible.
+ aMatrix = aMatrix.scale( 1.1 );
aPolyPath.matrixTransform( aMatrix );
return aPolyPath;
@@ -7656,32 +7831,16 @@ function EllipseWipePath( eSubtype )
{
this.eSubtype = eSubtype;
- var sPathData;
-
- switch( eSubtype )
- {
- case DEFAULT_TRANS_SUBTYPE:
- case CIRCLE_TRANS_SUBTYPE:
- // precomputed circle( 0.5, 0.5, SQRT2 / 2 )
- sPathData = 'M 0.5 -0.207107 ' +
- 'C 0.687536 -0.207107 0.867392 -0.132608 1 0 ' +
- 'C 1.13261 0.132608 1.20711 0.312464 1.20711 0.5 ' +
- 'C 1.20711 0.687536 1.13261 0.867392 1 1 ' +
- 'C 0.867392 1.13261 0.687536 1.20711 0.5 1.20711 ' +
- 'C 0.312464 1.20711 0.132608 1.13261 0 1 ' +
- 'C -0.132608 0.867392 -0.207107 0.687536 -0.207107 0.5 ' +
- 'C -0.207107 0.312464 -0.132608 0.132608 0 0 ' +
- 'C 0.132608 -0.132608 0.312464 -0.207107 0.5 -0.207107';
- break;
- case VERTICAL_TRANS_SUBTYPE:
- sPathData = '';
- break;
- case HORIZONTAL_TRANS_SUBTYPE:
- sPathData = '';
- break;
- default:
- log( 'EllipseWipePath: unknown subtype: ' + eSubtype );
- }
+ // precomputed circle( 0.5, 0.5, SQRT2 / 2 )
+ var sPathData = 'M 0.5 -0.207107 ' +
+ 'C 0.687536 -0.207107 0.867392 -0.132608 1 0 ' +
+ 'C 1.13261 0.132608 1.20711 0.312464 1.20711 0.5 ' +
+ 'C 1.20711 0.687536 1.13261 0.867392 1 1 ' +
+ 'C 0.867392 1.13261 0.687536 1.20711 0.5 1.20711 ' +
+ 'C 0.312464 1.20711 0.132608 1.13261 0 1 ' +
+ 'C -0.132608 0.867392 -0.207107 0.687536 -0.207107 0.5 ' +
+ 'C -0.207107 0.312464 -0.132608 0.132608 0 0 ' +
+ 'C 0.132608 -0.132608 0.312464 -0.207107 0.5 -0.207107';
this.aBasePath = document.createElementNS( NSS['svg'], 'path' );
this.aBasePath.setAttribute( 'd', sPathData );
@@ -7867,7 +8026,7 @@ AnimatedSlide.prototype.initClipPath = function()
var sId = 'clip-path-' + this.sSlideId;
this.aClipPathElement.setAttribute( 'id', sId );
- //this.aClipPathElement.setAttribute( 'clipPathUnits', 'userSpaceOnUse' );
+ this.aClipPathElement.setAttribute( 'clipPathUnits', 'userSpaceOnUse' );
// We create and append a placeholder content.
this.aClipPathContent = document.createElementNS( NSS['svg'], 'path' );
@@ -8021,6 +8180,7 @@ function AnimatedElement( aElement )
this.aActiveElement = aElement;
this.initElement();
+ this.sElementId = this.aActiveElement.getAttribute( 'id' );
this.aBaseBBox = this.aActiveElement.getBBox();
this.nBaseCenterX = this.aBaseBBox.x + this.aBaseBBox.width / 2;
@@ -8030,6 +8190,9 @@ function AnimatedElement( aElement )
this.nScaleFactorX = 1.0;
this.nScaleFactorY = 1.0;
+ this.aClipPathElement = null;
+ this.aClipPathContent = null;
+
this.aPreviousElement = null;
this.aElementArray = new Array();
this.nCurrentState = 0;
@@ -8050,6 +8213,58 @@ AnimatedElement.prototype.initElement = function()
this.aActiveElement.setAttribute( 'transform', makeMatrixString( 1, 0, 0, 1, 0, 0 ) );
};
+/** initClipPath
+ * Create a new clip path element and append it to the clip path def group.
+ * Moreover the created <clipPath> element is referenced by the handled
+ * animated element.
+ *
+ */
+AnimatedElement.prototype.initClipPath = function()
+{
+ // We create the clip path element.
+ this.aClipPathElement = document.createElementNS( NSS['svg'], 'clipPath' );
+
+ var sId = 'clip-path-' + this.sElementId;
+ this.aClipPathElement.setAttribute( 'id', sId );
+ this.aClipPathElement.setAttribute( 'clipPathUnits', 'userSpaceOnUse' );
+
+ // We create and append a placeholder content.
+ this.aClipPathContent = document.createElementNS( NSS['svg'], 'path' );
+ this.aClippingBBox = this.getBBoxWithStroke();
+ var nWidth = this.aClippingBBox.width;
+ var nHeight = this.aClippingBBox.height;
+ var sPathData = 'M ' + this.aClippingBBox.x + ' ' + this.aClippingBBox.y +
+ ' h ' + nWidth + ' v ' + nHeight + ' h -' + nWidth + ' z';
+ this.aClipPathContent.setAttribute( 'd', sPathData );
+ this.aClipPathElement.appendChild( this.aClipPathContent );
+
+ // We insert it into the svg document.
+ var aClipPathGroup = theMetaDoc.aClipPathGroup;
+ aClipPathGroup.appendChild( this.aClipPathElement );
+
+ // Finally we set the reference to the created clip path.
+ var sRef = 'url(#' + sId + ')';
+ this.aActiveElement.setAttribute( 'clip-path', sRef );
+};
+
+/** cleanClipPath
+ * Removes the related <clipPath> element from the <defs> group,
+ * and remove the 'clip-path' attribute from the animated element.
+ *
+ */
+AnimatedElement.prototype.cleanClipPath = function()
+{
+ this.aActiveElement.removeAttribute( 'clip-path' );
+
+ if( this.aClipPathElement )
+ {
+ var aClipPathGroup = theMetaDoc.aClipPathGroup;
+ aClipPathGroup.removeChild( this.aClipPathElement );
+ this.aClipPathElement = null;
+ this.aClipPathContent = null;
+ }
+};
+
AnimatedElement.prototype.getId = function()
{
return this.aActiveElement.getAttribute( 'id' );
@@ -8173,6 +8388,76 @@ AnimatedElement.prototype.getBBox = function()
return this.aActiveElement.parentNode.getBBox();
};
+AnimatedElement.prototype.getBBoxWithStroke = function()
+{
+ var aBBox = this.aActiveElement.parentNode.getBBox();
+
+ var aChildrenSet = this.aActiveElement.childNodes;
+
+ var sStroke, sStrokeWidth;
+ var nStrokeWidth = 0;
+ var i;
+ for( i = 0; i < aChildrenSet.length; ++i )
+ {
+ if( ! aChildrenSet[i].getAttribute )
+ continue;
+
+ sStroke = aChildrenSet[i].getAttribute( 'stroke' );
+ if( sStroke && sStroke != 'none' )
+ {
+ sStrokeWidth = aChildrenSet[i].getAttribute( 'stroke-width' );
+ var nSW = parseFloat( sStrokeWidth );
+ if( nSW > nStrokeWidth )
+ nStrokeWidth = nSW;
+ }
+ }
+
+ if( nStrokeWidth == 0 )
+ {
+ sStrokeWidth = ROOT_NODE.getAttribute( 'stroke-width' );
+ nStrokeWidth = parseFloat( sStrokeWidth );
+ }
+ if( nStrokeWidth != 0 )
+ {
+ // It is hard to clip properly the stroke so we try to enlarge
+ // the resulting bounding box even more.
+ nStrokeWidth *= 1.1;
+ var nHalfStrokeWidth = nStrokeWidth / 2;
+ var nDoubleStrokeWidth = nStrokeWidth * 2;
+
+ // Note: IE10 don't let modify the values of a element BBox.
+ var aEBBox = document.documentElement.createSVGRect();
+ aEBBox.x = aBBox.x - nHalfStrokeWidth;
+ aEBBox.y = aBBox.y - nHalfStrokeWidth;
+ aEBBox.width = aBBox.width + nDoubleStrokeWidth;
+ aEBBox.height = aBBox.height + nDoubleStrokeWidth;
+ aBBox = aEBBox;
+ }
+ return aBBox;
+};
+
+/** setClipPath
+ * Replace the current content of the <clipPath> element with the one
+ * passed through the parameter.
+ *
+ * @param aClipPathContent
+ * A <g> element representing a <path> element used for clipping.
+ */
+AnimatedElement.prototype.setClipPath = function( aClipPathContent )
+{
+ if( this.aClipPathContent )
+ {
+ // We need to translate the clip path to the top left corner of
+ // the element bounding box.
+ var aTranslation = SVGIdentityMatrix.translate( this.aClippingBBox.x,
+ this.aClippingBBox.y);
+ aClipPathContent.matrixTransform( aTranslation );
+ var sPathData = aClipPathContent.getAttribute( 'd' );
+ this.aClipPathContent.setAttribute( 'd', sPathData );
+ }
+};
+
+
AnimatedElement.prototype.getX = function()
{
return this.nCenterX;
commit 6016a685482aaa7e2ef80b31ee5196238665face
Author: Marco Cecchetti <mrcekets at gmail.com>
Date: Wed Jun 6 19:19:44 2012 +0200
Enabled support for clipping-based slide transitions (barnWipe,
fourBoxWipe, ellipseWipe, pinWheelWipe).
Ported or implemented the following classes or functions:
ClippedSlideChange, PathTools.normalizePath, ClippingFunctor,
createClipPolyPolygon, BarWipePath, FourBoxWipePath,
PathTools.createPathFromEllipse, EllipseWipePath, PinWheelWipePath.
Extended the following SVG DOM classes: SVGMatrix, SVGPathElement,
SVGPathSegMovetoAbs, SVGPathSegLinetoAbs, SVGPathSegCurvetoQuadraticAbs,
SVGPathSegCurvetoCubicAbs.
Modified and added new methods to: MetaDocument, AnimatedSlide,
SlideTransition, TransitionInfoTable.
diff --git a/filter/source/svg/presentation_engine.js b/filter/source/svg/presentation_engine.js
index 7b17623..0b09ffe 100644
--- a/filter/source/svg/presentation_engine.js
+++ b/filter/source/svg/presentation_engine.js
@@ -390,6 +390,463 @@ function indexSetPageSlide( nIndex )
* @licstart
*
* The following is the license notice for the part of JavaScript code of this
+ * page included between the '@dojostart' and the '@dojoend' notes.
+ */
+
+/***** **********************************************************************
+ *
+ * The "New" BSD License:
+ * **********************
+ * Copyright (c) 2005-2012, The Dojo Foundation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the Dojo Foundation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+
+/*****
+ * @licend
+ *
+ * The above is the license notice for the part of JavaScript code of this
+ * page included between the '@dojostart' and the '@dojoend' notes.
+ */
+
+
+
+/*****
+ * @dojostart
+ *
+ * The following code is a derivative work of some part of the dojox.gfx library.
+ * @source http://svn.dojotoolkit.org/src/dojox/trunk/gfx/arc.js
+ */
+
+
+function degToRad( degree )
+{
+ return (Math.PI * degree / 180);
+}
+
+function radToDeg( radiant )
+{
+ return (180 * radiant / Math.PI);
+}
+
+
+var PathTools = new Object();
+
+
+PathTools.unitArcAsBezier = function( alpha )
+{
+ // summary: return a start point, 1st and 2nd control points, and an end point of
+ // a an arc, which is reflected on the x axis
+ // alpha: Number
+ // angle in radians, the arc will be 2 * angle size
+ var cosa = Math.cos(alpha);
+ var sina = Math.sin(alpha);
+ var p2 = {x: cosa + (4 / 3) * (1 - cosa), y: sina - (4 / 3) * cosa * (1 - cosa) / sina};
+
+ return { // Object
+ s: {x: cosa, y: -sina},
+ c1: {x: p2.x, y: -p2.y},
+ c2: p2,
+ e: {x: cosa, y: sina}
+ };
+};
+
+PathTools.arcAsBezier = function( last, rx, ry, xRotg, large, sweep, x, y )
+{
+ // summary: calculates an arc as a series of Bezier curves
+ // given the last point and a standard set of SVG arc parameters,
+ // it returns an array of arrays of parameters to form a series of
+ // absolute Bezier curves.
+ // last: Object
+ // a point-like object as a start of the arc
+ // rx: Number
+ // a horizontal radius for the virtual ellipse
+ // ry: Number
+ // a vertical radius for the virtual ellipse
+ // xRotg: Number
+ // a rotation of an x axis of the virtual ellipse in degrees
+ // large: Boolean
+ // which part of the ellipse will be used (the larger arc if true)
+ // sweep: Boolean
+ // direction of the arc (CW if true)
+ // x: Number
+ // the x coordinate of the end point of the arc
+ // y: Number
+ // the y coordinate of the end point of the arc
+
+ // constants
+ var twoPI = 2 * Math.PI, pi4 = Math.PI / 4, pi8 = Math.PI / 8,
+ pi48 = pi4 + pi8, curvePI4 = PathTools.unitArcAsBezier(pi8);
+
+ // calculate parameters
+ large = Boolean(large);
+ sweep = Boolean(sweep);
+
+ var xRot = degToRad( xRotg );
+ var rx2 = rx * rx, ry2 = ry * ry;
+ var m = document.documentElement.createSVGMatrix();
+ m = m.rotate(-xRotg);
+ var p = document.documentElement.createSVGPoint();
+ p.x = (last.x - x) / 2; p.y = (last.y - y) / 2;
+ var pa = p.matrixTransform( m );
+
+ var pax2 = pa.x * pa.x, pay2 = pa.y * pa.y;
+ var c1 = Math.sqrt((rx2 * ry2 - rx2 * pay2 - ry2 * pax2) / (rx2 * pay2 + ry2 * pax2));
+
+ if( isNaN(c1) ) { c1 = 0; }
+
+ var ca = {
+ x: c1 * rx * pa.y / ry,
+ y: -c1 * ry * pa.x / rx
+ };
+
+ if( large == sweep )
+ {
+ ca = {x: -ca.x, y: -ca.y};
+ }
+
+ // the center
+ m = document.documentElement.createSVGMatrix();
+ m = m.translate( (last.x + x) / 2, (last.y + y) / 2 ).rotate( xRotg );
+ p.x = ca.x; p.y = ca.y;
+ var c = p.matrixTransform( m );
+
+ // calculate the elliptic transformation
+ m = document.documentElement.createSVGMatrix();
+ var elliptic_transform = m.translate( c.x, c.y ).rotate( xRotg ).scaleNonUniform( rx, ry );
+
+ // start, end, and size of our arc
+ var inversed = elliptic_transform.inverse();
+ p.x = last.x; p.y = last.y;
+ var sp = p.matrixTransform( inversed );
+ p.x = x; p.y = y;
+ var ep = p.matrixTransform( inversed );
+ var startAngle = Math.atan2(sp.y, sp.x);
+ var endAngle = Math.atan2(ep.y, ep.x);
+ var theta = startAngle - endAngle; // size of our arc in radians
+
+ if( sweep ) { theta = -theta; }
+ if( theta < 0 )
+ {
+ theta += twoPI;
+ }
+ else if( theta > twoPI )
+ {
+ theta -= twoPI;
+ }
+
+ // draw curve chunks
+ var alpha = pi8, curve = curvePI4;
+ var step = sweep ? alpha : -alpha;
+ var result = [];
+
+ var aPathElement = document.createElementNS( NSS['svg'], 'path' );
+
+ for(var angle = theta; angle > 0; angle -= pi4)
+ {
+ if( angle < pi48 )
+ {
+ alpha = angle / 2;
+ curve = PathTools.unitArcAsBezier(alpha);
+ step = sweep ? alpha : -alpha;
+ angle = 0; // stop the loop
+ }
+ var c2, e;
+ var M = elliptic_transform.rotate( radToDeg( startAngle + step ) );
+
+ if( sweep )
+ {
+ p.x = curve.c1.x; p.y = curve.c1.y;
+ c1 = p.matrixTransform( M );
+ p.x = curve.c2.x; p.y = curve.c2.y;
+ c2 = p.matrixTransform( M );
+ p.x = curve.e.x; p.y = curve.e.y;
+ e = p.matrixTransform( M );
+ }
+ else
+ {
+ p.x = curve.c2.x; p.y = curve.c2.y;
+ c1 = p.matrixTransform( M );
+ p.x = curve.c1.x; p.y = curve.c1.y;
+ c2 = p.matrixTransform( M );
+ p.x = curve.s.x; p.y = curve.s.y;
+ e = p.matrixTransform( M );
+ }
+
+ // draw the curve
+ var aCubicBezierSeg = aPathElement.createSVGPathSegCurvetoCubicAbs( e.x, e.y, c1.x, c1.y, c2.x, c2.y );
+ result.push( aCubicBezierSeg );
+
+ startAngle += 2 * step;
+ }
+ return result; // Array
+};
+
+
+
+/*****
+ * @dojoend
+ *
+ * The above code is a derivative work of some part of the dojox.gfx library.
+ * @source http://svn.dojotoolkit.org/src/dojox/trunk/gfx/arc.js
+ */
+
+
+
+
+/** normalizePath
+ *
+ * @param sPath
+ * A string representing a svg <path> element list of commands.
+ * @return {String}
+ * A string representing the same svg <path> passed as input defined by
+ * using only the following commands: M, L, Q, C.
+ */
+PathTools.normalizePath = function( sPath )
+{
+ var PATHSEG_CLOSEPATH = 1;
+ var PATHSEG_MOVETO_ABS = 2;
+ var PATHSEG_MOVETO_REL = 3;
+ var PATHSEG_LINETO_ABS = 4;
+ var PATHSEG_LINETO_REL = 5;
+ var PATHSEG_CURVETO_CUBIC_ABS = 6;
+ var PATHSEG_CURVETO_CUBIC_REL = 7;
+ var PATHSEG_CURVETO_QUADRATIC_ABS = 8;
+ var PATHSEG_CURVETO_QUADRATIC_REL = 9;
+ var PATHSEG_ARC_ABS = 10;
+ var PATHSEG_ARC_REL = 11;
+ var PATHSEG_LINETO_HORIZONTAL_ABS = 12;
+ var PATHSEG_LINETO_HORIZONTAL_REL = 13;
+ var PATHSEG_LINETO_VERTICAL_ABS = 14;
+ var PATHSEG_LINETO_VERTICAL_REL = 15;
+ var PATHSEG_CURVETO_CUBIC_SMOOTH_ABS = 16;
+ var PATHSEG_CURVETO_CUBIC_SMOOTH_REL = 17;
+ var PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS = 18;
+ var PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL = 19;
+
+ var aPath = document.createElementNS( NSS['svg'], 'path' );
+ aPath.setAttribute( 'd', sPath );
+ var aPathSegList = aPath.pathSegList;
+ if( !aPathSegList )
+ {
+ log( 'normalizePath: no path segment list supported, abort.' );
+ return '';
+ }
+ var nSize = aPathSegList.numberOfItems;
+
+ var aPreviousPathSeg = null;
+ var nCurrentX = 0;
+ var nCurrentY = 0;
+ var nInitialX = 0;
+ var nInitialY = 0;
+ var aPathSeg = null;
+ var aAbsPathSeg = null;
+
+ var i;
+ for( i = 0; i < nSize; ++i )
+ {
+
+ aPathSeg = aPathSegList.getItem( i );
+ switch( aPathSeg.pathSegType )
+ {
+ case PATHSEG_CLOSEPATH:
+ aAbsPathSeg = aPath.createSVGPathSegLinetoAbs( nInitialX, nInitialY );
+ aPathSegList.replaceItem( aAbsPathSeg, i );
+ break;
+ case PATHSEG_MOVETO_ABS:
+ nInitialX = aPathSeg.x;
+ nInitialY = aPathSeg.y;
+ break;
+ case PATHSEG_MOVETO_REL:
+ nCurrentX += aPathSeg.x;
+ nCurrentY += aPathSeg.y;
+ aAbsPathSeg = aPath.createSVGPathSegMovetoAbs( nCurrentX, nCurrentY );
+ aPathSegList.replaceItem( aAbsPathSeg, i );
+ nInitialX = nCurrentX;
+ nInitialY = nCurrentY;
+ break;
+ case PATHSEG_LINETO_ABS:
+ break;
+ case PATHSEG_LINETO_REL:
+ nCurrentX += aPathSeg.x;
+ nCurrentY += aPathSeg.y;
+ aAbsPathSeg = aPath.createSVGPathSegLinetoAbs( nCurrentX, nCurrentY );
+ aPathSegList.replaceItem( aAbsPathSeg, i );
+ break;
+ case PATHSEG_CURVETO_CUBIC_ABS:
+ break;
+ case PATHSEG_CURVETO_CUBIC_REL:
+ var nX1 = nCurrentX + aPathSeg.x1;
+ var nY1 = nCurrentY + aPathSeg.y1;
+ var nX2 = nCurrentX + aPathSeg.x2;
+ var nY2 = nCurrentY + aPathSeg.y2;
+ var nX = nCurrentX + aPathSeg.x;
+ var nY = nCurrentY + aPathSeg.y;
+ aAbsPathSeg = aPath.createSVGPathSegCurvetoCubicAbs( nX, nY, nX1, nY1, nX2, nY2 );
+ aPathSegList.replaceItem( aAbsPathSeg, i );
+ break;
+ case PATHSEG_CURVETO_QUADRATIC_ABS:
+ break;
+ case PATHSEG_CURVETO_QUADRATIC_REL:
+ nX1 = nCurrentX + aPathSeg.x1;
+ nY1 = nCurrentY + aPathSeg.y1;
+ nX = nCurrentX + aPathSeg.x;
+ nY = nCurrentY + aPathSeg.y;
+ aAbsPathSeg = aPath.createSVGPathSegCurvetoQuadraticAbs( nX, nY, nX1, nY1 );
+ aPathSegList.replaceItem( aAbsPathSeg, i );
+ break;
+ case PATHSEG_ARC_REL:
+ aPathSeg.x += nCurrentX;
+ aPathSeg.y += nCurrentY;
+ case PATHSEG_ARC_ABS:
+ var aCubicBezierSegList
+ = PathTools.arcAsBezier( { x: nCurrentX, y: nCurrentY },
+ aPathSeg.r1, aPathSeg.r2,
+ aPathSeg.angle,
+ aPathSeg.largeArcFlag,
+ aPathSeg.sweepFlag,
+ aPathSeg.x, aPathSeg.y );
+ var nLength = aCubicBezierSegList.length;
+ if( nLength > 0 )
+ {
+ var k;
+ for( k = 0; k < nLength; ++k )
+ {
+ aPathSegList.insertItemBefore( aCubicBezierSegList[k], i );
+ i += 1;
+ }
+ aPathSegList.removeItem( i );
+ i -= 1;
+ nSize += ( nLength - 1 );
+ }
+ break;
+ case PATHSEG_LINETO_HORIZONTAL_REL:
+ aPathSeg.x += nCurrentX;
+ // fall through intended
+ case PATHSEG_LINETO_HORIZONTAL_ABS:
+ aAbsPathSeg = aPath.createSVGPathSegLinetoAbs( aPathSeg.x, nCurrentY );
+ aPathSegList.replaceItem( aAbsPathSeg, i );
+ break;
+ case PATHSEG_LINETO_VERTICAL_REL:
+ aPathSeg.y += nCurrentY;
+ // fall through intended
+ case PATHSEG_LINETO_VERTICAL_ABS:
+ aAbsPathSeg = aPath.createSVGPathSegLinetoAbs( nCurrentX, aPathSeg.y );
+ aPathSegList.replaceItem( aAbsPathSeg, i );
+ break;
+ case PATHSEG_CURVETO_CUBIC_SMOOTH_REL:
+ aPathSeg.x += nCurrentX;
+ aPathSeg.y += nCurrentY;
+ aPathSeg.x2 += nCurrentX;
+ aPathSeg.y2 += nCurrentY;
+ // fall through intended
+ case PATHSEG_CURVETO_CUBIC_SMOOTH_ABS:
+ if( aPreviousPathSeg.pathSegType == PATHSEG_CURVETO_CUBIC_ABS )
+ {
+ nX1 = 2*nCurrentX - aPreviousPathSeg.x2;
+ nY1 = 2*nCurrentY - aPreviousPathSeg.y2;
+ }
+ else
+ {
+ nX1 = nCurrentX;
+ nY1 = nCurrentY;
+ }
+ aAbsPathSeg = aPath.createSVGPathSegCurvetoCubicAbs( aPathSeg.x, aPathSeg.y,
+ nX1, nY1,
+ aPathSeg.x2, aPathSeg.y2 );
+ aPathSegList.replaceItem( aAbsPathSeg, i );
+ break;
+ case PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL:
+ aPathSeg.x += nCurrentX;
+ aPathSeg.y += nCurrentY;
+ // fall through intended
+ case PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS:
+ if( aPreviousPathSeg.pathSegType == PATHSEG_CURVETO_QUADRATIC_ABS )
+ {
+ nX1 = 2*nCurrentX - aPreviousPathSeg.x1;
+ nY1 = 2*nCurrentY - aPreviousPathSeg.y1;
+ }
+ else
+ {
+ nX1 = nCurrentX;
+ nY1 = nCurrentY;
+ }
+ aAbsPathSeg = aPath.createSVGPathSegCurvetoQuadraticAbs( aPathSeg.x, aPathSeg.y, nX1, nY1 );
+ aPathSegList.replaceItem( aAbsPathSeg, i );
+ break;
+ default:
+ log( 'normalizePath: unknown path segment, index: ' + String(i) );
+ }
+ aPreviousPathSeg = aPathSegList.getItem( i );
+ nCurrentX = aPreviousPathSeg.x;
+ nCurrentY = aPreviousPathSeg.y;
+ }
+ return aPath.getAttribute( 'd' );
+};
+
+
+/** createPathFromEllipse
+ *
+ * @param nCX
+ * The ellipse center x coordinate.
+ * @param nCY
+ * The ellipse center y coordinate.
+ * @param nXRay
+ * The ellipse x-ray.
+ * @param nYRay
+ * The ellipse y-ray.
+ * @return {String}
+ * A string representing a list of path commands that approximate
+ * the ellipse.
+ */
+PathTools.createPathFromEllipse = function( nCX, nCY, nXRay, nYRay )
+{
+ var V1X = nCX, V1Y = nCY - nYRay;
+ var V2X = nCX + nXRay, V2Y = nCY;
+ var V3X = nCX, V3Y = nCY + nYRay;
+ var V4X = nCX - nXRay, V4Y = nCY;
+
+ var sPathData = 'M ' + V1X + ' ' + V1Y +
+ ' A ' + nXRay + ' ' + nYRay + ' 0 0 1 ' + V2X + ' ' + V2Y +
+ ' A ' + nXRay + ' ' + nYRay + ' 0 0 1 ' + V3X + ' ' + V3Y +
+ ' A ' + nXRay + ' ' + nYRay + ' 0 0 1 ' + V4X + ' ' + V4Y +
+ ' A ' + nXRay + ' ' + nYRay + ' 0 0 1 ' + V1X + ' ' + V1Y;
+
+ sPathData = PathTools.normalizePath( sPathData );
+ return sPathData;
+};
+
+
+
+
+/*****
+ * @licstart
+ *
+ * The following is the license notice for the part of JavaScript code of this
* page included between the '@stdlibstart' and the '@stdlibend' notes.
*/
@@ -627,6 +1084,7 @@ window.onload = init;
var aOOOElemMetaSlides = 'ooo:meta_slides';
var aOOOElemMetaSlide = 'ooo:meta_slide';
var aOOOElemTextField = 'ooo:text_field';
+var aPresentationClipPathId = 'presentation_clip_path';
// ooo attributes
var aOOOAttrNumberOfSlides = 'number-of-slides';
@@ -651,6 +1109,7 @@ var aOOOAttrDateTimeFormat = 'date-time-format';
var aOOOAttrTextAdjust = 'text-adjust';
// element class names
+var aClipPathGroupClassName = 'ClipPathGroup';
var aPageClassName = 'Page';
var aSlideNumberClassName = 'Slide_Number';
var aDateTimeClassName = 'Date/Time';
@@ -1031,6 +1490,15 @@ function MetaDocument()
// - the numbering type used in the presentation, default type is arabic.
this.sPageNumberingType = aMetaDocElem.getAttributeNS( NSS['ooo'], aOOOAttrNumberingType ) || 'arabic';
+ // The <defs> element used for wrapping <clipPath>.
+ this.aClipPathGroup = getElementByClassName( ROOT_NODE, aClipPathGroupClassName );
+ assert( this.aClipPathGroup, 'MetaDocument: the clip path group element is not valid.');
+
+ // The <clipPath> element used to clip all slides.
+ this.aPresentationClipPath = document.getElementById( aPresentationClipPathId );
+ assert( this.aPresentationClipPath,
+ 'MetaDocument: the presentation clip path element element is not valid.');
+
// The collections for handling properties of each slide, svg elements
// related to master pages and content and properties of text fields.
this.aMetaSlideSet = new Array();
@@ -3145,6 +3613,250 @@ HSLColor.interpolate = function( aFrom, aTo, nT, bCCW )
+/**********************************************************************************************
+ * SVGMatrix extensions
+ **********************************************************************************************/
+
+SVGIdentityMatrix = document.documentElement.createSVGMatrix();
+
+SVGMatrix.prototype.setToIdentity = function()
+{
+ this.a = this.d = 1;
+ this.b = this.c = this.d = this.e = 0;
+};
+
+SVGMatrix.prototype.setToRotationAroundPoint = function( nX, nY, nAngle )
+{
+ nAngle = degToRad( nAngle );
+ var nSin = Math.sin( nAngle );
+ var nCos = Math.cos( nAngle );
+
+ this.a = nCos; this.c = -nSin; this.e = nX * (1 - nCos) + nY * nSin;
+ this.b = nSin; this.d = nCos; this.f = nY * (1 - nCos) - nX * nSin;
+};
+
+
+
+/**********************************************************************************************
+ * SVGPath extensions
+ **********************************************************************************************/
+
+SVGPathElement.prototype.appendPath = function( aPath )
+{
+ var sPathData = this.getAttribute( 'd' );
+ sPathData += ( ' ' + aPath.getAttribute( 'd' ) );
+ this.setAttribute( 'd', sPathData );
+};
+
+/** SVGPathElement.matrixTransform
+ * Apply the transformation defined by the passed matrix to the referenced
+ * svg <path> element.
+ * After the transformation 'this' element is modified in order to reference
+ * the transformed path.
+ *
+ * @param aSVGMatrix
+ * An SVGMatrix instance.
+ */
+SVGPathElement.prototype.matrixTransform = function( aSVGMatrix )
+{
+ var aPathSegList = this.pathSegList;
+ var nLength = aPathSegList.numberOfItems;
+ var i;
+ for( i = 0; i < nLength; ++i )
+ {
+ aPathSegList.getItem( i ).matrixTransform( aSVGMatrix );
+ }
+};
+
+/** SVGPathElement.changeOrientation
+ * Invert the path orientation by inverting the path command list.
+ *
+ */
+SVGPathElement.prototype.changeOrientation = function()
+{
+ var aPathSegList = this.pathSegList;
+ var nLength = aPathSegList.numberOfItems;
+ if( nLength == 0 ) return;
+
+ var nCurrentX = 0;
+ var nCurrentY = 0;
+
+ var aPathSeg = aPathSegList.getItem( 0 );
+ if( aPathSeg.pathSegTypeAsLetter == 'M' )
+ {
+ nCurrentX = aPathSeg.x;
+ nCurrentY = aPathSeg.y;
+ aPathSegList.removeItem( 0 );
+ --nLength;
+ }
+
+ var i;
+ for( i = 0; i < nLength; ++i )
+ {
+ aPathSeg = aPathSegList.getItem( i );
+ var aPoint = aPathSeg.changeOrientation( nCurrentX, nCurrentY );
+ nCurrentX = aPoint.x;
+ nCurrentY = aPoint.y;
+ }
+
+
+ for( i = nLength - 2; i >= 0; --i )
+ {
+ aPathSeg = aPathSegList.removeItem( i );
+ aPathSegList.appendItem( aPathSeg );
+ }
+
+ var aMovePathSeg = this.createSVGPathSegMovetoAbs( nCurrentX, nCurrentY );
+ aPathSegList.insertItemBefore( aMovePathSeg, 0 );
+
+}
+
+/** matrixTransform and changeOrientation
+ * We implement these methods for each path segment type still present
+ * after the path normalization (M, L, Q, C).
+ *
+ * Note: Opera doesn't have any SVGPathSeg* class and rises an error.
+ * We exploit this fact for providing a different implementation.
+ */
+try
+{ // Firefox, Google Chrome, Internet Explorer, Safari.
+
+ SVGPathSegMovetoAbs.prototype.matrixTransform = function( aSVGMatrix )
+ {
+ SVGPathMatrixTransform( this, aSVGMatrix );
+ };
+
+ SVGPathSegLinetoAbs.prototype.matrixTransform = function( aSVGMatrix )
+ {
+ SVGPathMatrixTransform( this, aSVGMatrix );
+ };
+
+ SVGPathSegCurvetoQuadraticAbs.prototype.matrixTransform = function( aSVGMatrix )
+ {
+ SVGPathMatrixTransform( this, aSVGMatrix );
+ var nX = this.x1;
+ this.x1 = aSVGMatrix.a * nX + aSVGMatrix.c * this.y1 + aSVGMatrix.e;
+ this.y1 = aSVGMatrix.b * nX + aSVGMatrix.d * this.y1 + aSVGMatrix.f;
+ };
+
+ SVGPathSegCurvetoCubicAbs.prototype.matrixTransform = function( aSVGMatrix )
+ {
+ SVGPathMatrixTransform( this, aSVGMatrix );
+ var nX = this.x1;
+ this.x1 = aSVGMatrix.a * nX + aSVGMatrix.c * this.y1 + aSVGMatrix.e;
+ this.y1 = aSVGMatrix.b * nX + aSVGMatrix.d * this.y1 + aSVGMatrix.f;
+ nX = this.x2;
+ this.x2 = aSVGMatrix.a * nX + aSVGMatrix.c * this.y2 + aSVGMatrix.e;
+ this.y2 = aSVGMatrix.b * nX + aSVGMatrix.d * this.y2 + aSVGMatrix.f;
+ };
+
+
+ SVGPathSegMovetoAbs.prototype.changeOrientation = function( nCurrentX, nCurrentY )
+ {
+ var aPoint = { x: this.x, y: this.y };
+ this.x = nCurrentX;
+ this.y = nCurrentY;
+ return aPoint;
+ };
+
+ SVGPathSegLinetoAbs.prototype.changeOrientation = function( nCurrentX, nCurrentY )
+ {
+ var aPoint = { x: this.x, y: this.y };
+ this.x = nCurrentX;
+ this.y = nCurrentY;
+ return aPoint;
+ };
+
+ SVGPathSegCurvetoQuadraticAbs.prototype.changeOrientation = function( nCurrentX, nCurrentY )
+ {
+ var aPoint = { x: this.x, y: this.y };
+ this.x = nCurrentX;
+ this.y = nCurrentY;
+ return aPoint;
+ };
+
+ SVGPathSegCurvetoCubicAbs.prototype.changeOrientation = function( nCurrentX, nCurrentY )
+ {
+ var aPoint = { x: this.x, y: this.y };
+ this.x = nCurrentX;
+ this.y = nCurrentY;
+ var nX = this.x1;
+ this.x1 = this.x2;
+ this.x2 = nX;
+ var nY = this.y1;
+ this.y1 = this.y2;
+ this.y2 = nY;
+ return aPoint;
+ };
+
+}
+catch( e )
+{ // Opera
+
+ if( e.name == 'ReferenceError' )
+ {
+ SVGPathSeg.prototype.matrixTransform = function( aSVGMatrix )
+ {
+ var nX;
+ switch( this.pathSegTypeAsLetter )
+ {
+ case 'C':
+ nX = this.x2;
+ this.x2 = aSVGMatrix.a * nX + aSVGMatrix.c * this.y2 + aSVGMatrix.e;
+ this.y2 = aSVGMatrix.b * nX + aSVGMatrix.d * this.y2 + aSVGMatrix.f;
+ // fall through intended
+ case 'Q':
+ nX = this.x1;
+ this.x1 = aSVGMatrix.a * nX + aSVGMatrix.c * this.y1 + aSVGMatrix.e;
+ this.y1 = aSVGMatrix.b * nX + aSVGMatrix.d * this.y1 + aSVGMatrix.f;
+ // fall through intended
+ case 'M':
+ case 'L':
+ SVGPathMatrixTransform( this, aSVGMatrix );
+ break;
+ default:
+ log( 'SVGPathSeg.matrixTransform: unexpected path segment type: '
+ + this.pathSegTypeAsLetter );
+ }
+ };
+
+ SVGPathSeg.prototype.changeOrientation = function( nCurrentX, nCurrentY )
+ {
+ switch( this.pathSegTypeAsLetter )
+ {
+ case 'C':
+ var nX = this.x1;
+ this.x1 = this.x2;
+ this.x2 = nX;
+ var nY = this.y1;
+ this.y1 = this.y2;
+ this.y2 = nY;
+ // fall through intended
+ case 'M':
+ case 'L':
+ case 'Q':
+ var aPoint = { x: this.x, y: this.y };
+ this.x = nCurrentX;
+ this.y = nCurrentY;
+ return aPoint;
+ default:
+ log( 'SVGPathSeg.changeOrientation: unexpected path segment type: '
+ + this.pathSegTypeAsLetter );
+ return null;
+ }
+ }
+ }
+ else throw e;
+}
+
+function SVGPathMatrixTransform( aPath, aSVGMatrix )
+{
+ var nX = aPath.x;
+ aPath.x = aSVGMatrix.a * nX + aSVGMatrix.c * aPath.y + aSVGMatrix.e;
+ aPath.y = aSVGMatrix.b * nX + aSVGMatrix.d * aPath.y + aSVGMatrix.f;
+}
+
+
/**********************************************************************************************
* AnimationNode Class Hierarchy
@@ -3431,36 +4143,75 @@ aTransitionClassOutMap = ['invalid', 'clip polypolygon', 'special'];
// Transition Types
BARWIPE_TRANSITION = 1;
-PUSHWIPE_TRANSITION = 2; // 35
-SLIDEWIPE_TRANSITION = 3; // 36
-FADE_TRANSITION = 4; // 37
+BOXWIPE_TRANSITION = 2;
+FOURBOXWIPE_TRANSITION = 3;
+ELLIPSEWIPE_TRANSITION = 4; // 17
+CLOCKWIPE_TRANSITION = 5; // 22
+PINWHEELWIPE_TRANSITION = 6 // 23
+PUSHWIPE_TRANSITION = 7; // 35
+SLIDEWIPE_TRANSITION = 8; // 36
+FADE_TRANSITION = 9; // 37
aTransitionTypeInMap = {
'barWipe' : BARWIPE_TRANSITION,
+ 'boxWipe' : BOXWIPE_TRANSITION,
+ 'fourBoxWipe' : FOURBOXWIPE_TRANSITION,
+ 'ellipseWipe' : ELLIPSEWIPE_TRANSITION,
+ 'clockWipe' : CLOCKWIPE_TRANSITION,
+ 'pinWheelWipe' : PINWHEELWIPE_TRANSITION,
'pushWipe' : PUSHWIPE_TRANSITION,
'slideWipe' : SLIDEWIPE_TRANSITION,
'fade' : FADE_TRANSITION
};
-aTransitionTypeOutMap = [ '', 'barWipe', 'pushWipe', 'slideWipe', 'fade' ];
+aTransitionTypeOutMap = [ '', 'barWipe', 'boxWipe', 'fourBoxWipe', 'ellipseWipe',
+ 'clockWipe', 'pinWheelWipe', 'pushWipe', 'slideWipe',
+ 'fade' ];
// Transition Subtypes
DEFAULT_TRANS_SUBTYPE = 0;
LEFTTORIGHT_TRANS_SUBTYPE = 1;
TOPTOBOTTOM_TRANS_SUBTYPE = 2;
-FROMLEFT_TRANS_SUBTYPE = 3; // 97
-FROMTOP_TRANS_SUBTYPE = 4;
-FROMRIGHT_TRANS_SUBTYPE = 5;
-FROMBOTTOM_TRANS_SUBTYPE = 6
-CROSSFADE_TRANS_SUBTYPE = 7;
-FADETOCOLOR_TRANS_SUBTYPE = 8;
-FADEFROMCOLOR_TRANS_SUBTYPE = 9;
-FADEOVERCOLOR_TRANS_SUBTYPE = 10; // 104
+CORNERSIN_TRANS_SUBTYPE = 3; // 11
+CORNERSOUT_TRANS_SUBTYPE = 4;
+VERTICAL_TRANS_SUBTYPE = 5;
+HORIZONTAL_TRANS_SUBTYPE = 6; // 14
+CIRCLE_TRANS_SUBTYPE = 7; // 27
+CLOCKWISETWELVE_TRANS_SUBTYPE = 8; // 33
+CLOCKWISETHREE_TRANS_SUBTYPE = 9;
+CLOCKWISESIX_TRANS_SUBTYPE = 10;
+CLOCKWISENINE_TRANS_SUBTYPE = 11;
+TWOBLADEVERTICAL_TRANS_SUBTYPE = 12;
+TWOBLADEHORIZONTAL_TRANS_SUBTYPE = 13;
+FOURBLADE_TRANS_SUBTYPE = 14; // 39
+FROMLEFT_TRANS_SUBTYPE = 15; // 97
+FROMTOP_TRANS_SUBTYPE = 16;
+FROMRIGHT_TRANS_SUBTYPE = 17;
+FROMBOTTOM_TRANS_SUBTYPE = 18;
+CROSSFADE_TRANS_SUBTYPE = 19;
+FADETOCOLOR_TRANS_SUBTYPE = 20;
+FADEFROMCOLOR_TRANS_SUBTYPE = 21;
+FADEOVERCOLOR_TRANS_SUBTYPE = 22;
+THREEBLADE_TRANS_SUBTYPE = 23;
+EIGHTBLADE_TRANS_SUBTYPE = 24;
+ONEBLADE_TRANS_SUBTYPE = 25; // 107
aTransitionSubtypeInMap = {
'leftToRight' : LEFTTORIGHT_TRANS_SUBTYPE,
'topToBottom' : TOPTOBOTTOM_TRANS_SUBTYPE,
+ 'cornersIn' : CORNERSIN_TRANS_SUBTYPE,
+ 'cornersOut' : CORNERSOUT_TRANS_SUBTYPE,
+ 'vertical' : VERTICAL_TRANS_SUBTYPE,
+ 'horizontal' : HORIZONTAL_TRANS_SUBTYPE,
+ 'circle' : CIRCLE_TRANS_SUBTYPE,
+ 'clockwiseTwelve' : CLOCKWISETWELVE_TRANS_SUBTYPE,
+ 'clockwiseThree' : CLOCKWISETHREE_TRANS_SUBTYPE,
+ 'clockwiseSix' : CLOCKWISESIX_TRANS_SUBTYPE,
+ 'clockwiseNine' : CLOCKWISENINE_TRANS_SUBTYPE,
+ 'twoBladeVertical' : TWOBLADEVERTICAL_TRANS_SUBTYPE,
+ 'twoBladeHorizontal': TWOBLADEHORIZONTAL_TRANS_SUBTYPE,
+ 'fourBlade' : FOURBLADE_TRANS_SUBTYPE,
'fromLeft' : FROMLEFT_TRANS_SUBTYPE,
'fromTop' : FROMTOP_TRANS_SUBTYPE,
'fromRight' : FROMRIGHT_TRANS_SUBTYPE,
@@ -3468,12 +4219,19 @@ aTransitionSubtypeInMap = {
'crossfade' : CROSSFADE_TRANS_SUBTYPE,
'fadeToColor' : FADETOCOLOR_TRANS_SUBTYPE,
'fadeFromColor' : FADEFROMCOLOR_TRANS_SUBTYPE,
- 'fadeOverColor' : FADEOVERCOLOR_TRANS_SUBTYPE
+ 'fadeOverColor' : FADEOVERCOLOR_TRANS_SUBTYPE,
+ 'threeBlade' : THREEBLADE_TRANS_SUBTYPE,
+ 'eightBlade' : EIGHTBLADE_TRANS_SUBTYPE,
+ 'oneBlade' : ONEBLADE_TRANS_SUBTYPE
};
-aTransitionSubtypeOutMap = [ 'default', 'leftToRight', 'topToBottom', 'fromLeft',
- 'fromTop', 'fromRight', 'fromBottom', 'crossfade',
- 'fadeToColor', 'fadeFromColor', 'fadeOverColor' ];
+aTransitionSubtypeOutMap = [ 'default', 'leftToRight', 'topToBottom', 'cornersIn',
+ 'cornersOut', 'vertical', 'horizontal', 'circle',
+ 'clockwiseTwelve', 'clockwiseThree', 'clockwiseSix',
+ 'clockwiseNine', 'twoBladeVertical', 'twoBladeHorizontal',
+ 'fourBlade', 'fromLeft', 'fromTop', 'fromRight',
+ 'fromBottom', 'crossfade', 'fadeToColor', 'fadeFromColor',
+ 'fadeOverColor', 'threeBlade', 'eightBlade', 'oneBlade' ];
// Transition Modes
@@ -3548,6 +4306,119 @@ aTransitionInfoTable[BARWIPE_TRANSITION][TOPTOBOTTOM_TRANS_SUBTYPE] =
'scaleIsotropically' : false
};
+aTransitionInfoTable[FOURBOXWIPE_TRANSITION] = {};
+aTransitionInfoTable[FOURBOXWIPE_TRANSITION][CORNERSIN_TRANS_SUBTYPE] =
+aTransitionInfoTable[FOURBOXWIPE_TRANSITION][CORNERSOUT_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 0.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ 'outInvertsSweep' : true,
+ 'scaleIsotropically' : false
+};
+
+aTransitionInfoTable[ELLIPSEWIPE_TRANSITION] = {};
+aTransitionInfoTable[ELLIPSEWIPE_TRANSITION][CIRCLE_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 0.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ 'outInvertsSweep' : true,
+ 'scaleIsotropically' : true
+};
+aTransitionInfoTable[ELLIPSEWIPE_TRANSITION][HORIZONTAL_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 0.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ 'outInvertsSweep' : true,
+ 'scaleIsotropically' : false
+};
+aTransitionInfoTable[ELLIPSEWIPE_TRANSITION][VERTICAL_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 90.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ 'outInvertsSweep' : true,
+ 'scaleIsotropically' : false
+};
+
+aTransitionInfoTable[CLOCKWIPE_TRANSITION] = {};
+aTransitionInfoTable[CLOCKWIPE_TRANSITION][CLOCKWISETWELVE_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 0.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_FLIP_X,
+ 'outInvertsSweep' : true,
+ 'scaleIsotropically' : false
+};
+aTransitionInfoTable[CLOCKWIPE_TRANSITION][CLOCKWISETHREE_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 90.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_FLIP_Y,
+ 'outInvertsSweep' : true,
+ 'scaleIsotropically' : false
+};
+aTransitionInfoTable[CLOCKWIPE_TRANSITION][CLOCKWISESIX_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 180.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_FLIP_X,
+ 'outInvertsSweep' : true,
+ 'scaleIsotropically' : false
+};
+aTransitionInfoTable[CLOCKWIPE_TRANSITION][CLOCKWISENINE_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 270.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_FLIP_Y,
+ 'outInvertsSweep' : true,
+ 'scaleIsotropically' : false
+};
+
+aTransitionInfoTable[PINWHEELWIPE_TRANSITION] = {};
+aTransitionInfoTable[PINWHEELWIPE_TRANSITION][ONEBLADE_TRANS_SUBTYPE] =
+aTransitionInfoTable[PINWHEELWIPE_TRANSITION][TWOBLADEVERTICAL_TRANS_SUBTYPE] =
+aTransitionInfoTable[PINWHEELWIPE_TRANSITION][THREEBLADE_TRANS_SUBTYPE] =
+aTransitionInfoTable[PINWHEELWIPE_TRANSITION][FOURBLADE_TRANS_SUBTYPE] =
+aTransitionInfoTable[PINWHEELWIPE_TRANSITION][EIGHTBLADE_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 0.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_FLIP_X,
+ 'outInvertsSweep' : true,
+ 'scaleIsotropically' : true
+};
+aTransitionInfoTable[PINWHEELWIPE_TRANSITION][TWOBLADEHORIZONTAL_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : -90.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_FLIP_Y,
+ 'outInvertsSweep' : true,
+ 'scaleIsotropically' : true
+};
+
aTransitionInfoTable[PUSHWIPE_TRANSITION] = {};
aTransitionInfoTable[PUSHWIPE_TRANSITION][FROMLEFT_TRANS_SUBTYPE] =
aTransitionInfoTable[PUSHWIPE_TRANSITION][FROMTOP_TRANS_SUBTYPE] =
@@ -6369,6 +7240,540 @@ MovingSlideChange.prototype.performOut = function( nT )
// ------------------------------------------------------------------------------------------ //
+/** Class ClippedSlideChange
+ * This class performs a slide transition where the entering slide wipes
+ * the leaving one out. The wipe effect is achieved by clipping the entering
+ * slide with a parametric path.
+ *
+ * @param aLeavingSlide
+ * An object of type AnimatedSlide handling the leaving slide.
+ * @param aEnteringSlide
+ * An object of type AnimatedSlide handling the entering slide.
+ * @param aParametricPolyPolygon
+ * An object handling a <path> element that depends on a parameter.
+ * @param aTransitionInfo
+ * The set of parameters defining the slide transition to be performed.
+ * @param bIsDirectionForward
+ * The direction the slide transition has to be performed.
+ */
+function ClippedSlideChange( aLeavingSlide, aEnteringSlide, aParametricPolyPolygon,
+ aTransitionInfo, bIsDirectionForward )
+{
+ ClippedSlideChange.superclass.constructor.call( this, aLeavingSlide, aEnteringSlide );
+
+ var bIsModeIn = true;
+ this.aClippingFunctor= new ClippingFunctor( aParametricPolyPolygon, aTransitionInfo,
+ bIsDirectionForward, bIsModeIn );
+}
+extend( ClippedSlideChange, SlideChangeBase );
+
+/** start
+ * This method notifies to the slides involved in the transition the attributes
+ * appended to the slide elements for performing the animation.
+ * Moreover it sets the entering slide in the initial state and makes the slide
+ * visible.
+ */
+ClippedSlideChange.prototype.start = function()
+{
+ ClippedSlideChange.superclass.start.call( this );
+ this.aEnteringSlide.notifyUsedAttribute( 'clip-path' );;
+ this.performIn( 0 );
+ this.aEnteringSlide.show();
+};
+
+/** performIn
+ * This method set the position of the entering slide according to the passed
+ * time value.
+ *
+ * @param nT
+ * The time parameter.
+ */
+ClippedSlideChange.prototype.performIn = function( nT )
+{
+ var nWidth = this.aEnteringSlide.getWidth();
+ var nHeight = this.aEnteringSlide.getHeight();
+ var aPolyPolygonElement = this.aClippingFunctor.perform( nT, nWidth, nHeight );
+ this.aEnteringSlide.setClipPath( aPolyPolygonElement );
+};
+
+ClippedSlideChange.prototype.performOut = function( nT )
+{
+ // empty body
+};
+
+
+
+// ------------------------------------------------------------------------------------------ //
+/** Class ClippingFunctor
+ * This class is responsible for computing the <path> used for clipping
+ * the entering slide in a polypolygon clipping slide transition or the
+ * animated shape in a transition filter effect.
+ *
+ * @param aParametricPolyPolygon
+ * An object that handle a <path> element defined in the [0,1]x[0,1]
+ * unit square and that depends on a parameter.
+ * @param aTransitionInfo
+ * The set of parameters defining the slide transition to be performed.
+ * @param bIsDirectionForward
+ * The direction the slide transition has to be performed.
+ * @param bIsModeIn
+ * The direction the filter effect has to be performed
+ */
+function ClippingFunctor( aParametricPolyPolygon, aTransitionInfo,
+ bIsDirectionForward, bIsModeIn)
+{
+ this.aParametricPolyPolygon = aParametricPolyPolygon;
+ this.aStaticTransformation = null;
+ this.bForwardParameterSweep = true;
+ this.bSubtractPolygon = false;
+ this.bScaleIsotropically = aTransitionInfo.scaleIsotropically;
+ this.bFlip = false;
+
+ assert( this.aParametricPolyPolygon,
+ 'ClippingFunctor: parametric polygon is not valid' );
+
+ if( aTransitionInfo.rotationAngle != 0.0 ||
+ aTransitionInfo.scaleX != 1.0 || aTransitionInfo.scaleY != 1.0 )
+ {
+ // note: operations must be defined in reverse order.
+ this.aStaticTransformation = SVGIdentityMatrix.translate( 0.5, 0.5 );
+ if( aTransitionInfo.scaleX != 1.0 || aTransitionInfo.scaleY != 1.0 )
+ this.aStaticTransformation
+ = this.aStaticTransformation.scaleNonUniform( aTransitionInfo.scaleX,
+ aTransitionInfo.scaleY );
+ if( aTransitionInfo.rotationAngle != 0.0 )
+ this.aStaticTransformation
+ = this.aStaticTransformation.rotate( aTransitionInfo.rotationAngle );
+ this.aStaticTransformation = this.aStaticTransformation.translate( -0.5, -0.5 );
+ }
+ else
+ {
+ this.aStaticTransformation = document.documentElement.createSVGMatrix();
+ }
+
+ if( !bIsDirectionForward )
+ {
+ var aMatrix = null;
+ switch( aTransitionInfo.reverseMethod )
+ {
+ default:
+ log( 'ClippingFunctor: unexpected reverse method.' )
+ break;
+ case REVERSEMETHOD_IGNORE:
+ break;
+ case REVERSEMETHOD_INVERT_SWEEP:
+ this.bForwardParameterSweep = !this.bForwardParameterSweep;
+ break;
+ case REVERSEMETHOD_SUBTRACT_POLYGON:
+ this.bSubtractPolygon = !this.bSubtractPolygon;
+ break;
+ case REVERSEMETHOD_SUBTRACT_AND_INVERT:
+ this.bForwardParameterSweep = !this.bForwardParameterSweep;
+ this.bSubtractPolygon = !this.bSubtractPolygon;
+ break;
+ case REVERSEMETHOD_ROTATE_180:
+ aMatrix = document.documentElement.createSVGMatrix();
+ aMatrix.setToRotationAroundPoint( 0.5, 0.5, 180 );
+ this.aStaticTransformation = aMatrix.multiply( this.aStaticTransformation );
+ break;
+ case REVERSEMETHOD_FLIP_X:
+ aMatrix = document.documentElement.createSVGMatrix();
+ // |-1 0 1 |
+ // | 0 1 0 |
+ aMatrix.a = -1; aMatrix.e = 1.0;
+ this.aStaticTransformation = aMatrix.multiply( this.aStaticTransformation );
+ this.bFlip = true;
+ break;
+ case REVERSEMETHOD_FLIP_Y:
+ aMatrix = document.documentElement.createSVGMatrix();
+ // | 1 0 0 |
+ // | 0 -1 1 |
+ aMatrix.d = -1; aMatrix.f = 1.0;
+ this.aStaticTransformation = aMatrix.multiply( this.aStaticTransformation );
+ this.bFlip = true;
+ break;
+ }
+ }
+
+ if( !bIsModeIn )
+ {
+ if( aTransitionInfo.outInvertsSweep )
+ {
+ this.bForwardParameterSweep = !this.bForwardParameterSweep;
+ }
+ else
+ {
+ this.bSubtractPolygon = !this.bSubtractPolygon;
+ }
+ }
+}
+
+/** perform
+ *
+ * @param nT
+ * A parameter in [0,1] representing normalized time.
+ * @param nWidth
+ * The width of the bounding box of the slide/shape to be clipped.
+ * @param nHeight
+ * The height of the bounding box of the slide/shape to be clipped.
+ * @return {SVGPathElement}
+ * A svg <path> element representing the path to be used for the clipping
+ * operation.
+ */
+ClippingFunctor.prototype.perform = function( nT, nWidth, nHeight )
+{
+ var aClipPoly = this.aParametricPolyPolygon.perform( this.bForwardParameterSweep ? nT : (1 - nT) );
+
+ if( this.bFlip )
+ aClipPoly.changeOrientation();
+
+ if( this.bSubtractPolygon )
+ {
+
+ }
+
+ var aMatrix;
+ if( this.bScaleIsotropically )
+ {
+ var nScaleFactor = Math.max( nWidth, nHeight );
+ // translate( scale( aStaticTransformation() ) )
+ // note: operations must be defined in reverse order.
+ aMatrix = SVGIdentityMatrix.translate( -( nScaleFactor - nWidth ) / 2.0,
+ -( nScaleFactor - nHeight ) / 2.0 );
+ aMatrix = aMatrix.scale( nScaleFactor );
+ aMatrix = aMatrix.multiply( this.aStaticTransformation );
+ }
+ else
+ {
+ aMatrix = SVGIdentityMatrix.scaleNonUniform( nWidth, nHeight );
+ aMatrix = aMatrix.multiply( this.aStaticTransformation );
+ }
+
+ aClipPoly.matrixTransform( aMatrix );
+
+ return aClipPoly;
+};
+
+
+
+// ------------------------------------------------------------------------------------------ //
+/** createClipPolyPolygon
+ *
+ * @param nType
+ * An enumerator representing the transition type.
+ * @param nSubtype
+ * An enumerator representing the transition subtype.
+ * @return
+ * An object that handles a parametric <path> element.
+ */
+function createClipPolyPolygon( nType, nSubtype )
+{
+ switch( nType )
+ {
+ default:
+ log( 'createClipPolyPolygon: unknown transition type: ' + nType );
+ return null;
+ case BARWIPE_TRANSITION:
+ return new BarWipePath( 1 );
+ case FOURBOXWIPE_TRANSITION:
+ return new FourBoxWipePath( nSubtype === CORNERSOUT_TRANS_SUBTYPE );
+ case ELLIPSEWIPE_TRANSITION:
+ return new EllipseWipePath( nSubtype );
+ case PINWHEELWIPE_TRANSITION:
+ var nBlades;
+ switch( nSubtype )
+ {
+ case ONEBLADE_TRANS_SUBTYPE:
+ nBlades = 1;
+ break;
+ case DEFAULT_TRANS_SUBTYPE:
+ case TWOBLADEVERTICAL_TRANS_SUBTYPE:
+ nBlades = 2;
+ break;
+ case TWOBLADEHORIZONTAL_TRANS_SUBTYPE:
+ nBlades = 2;
+ break;
+ case THREEBLADE_TRANS_SUBTYPE:
+ nBlades = 3;
+ break;
+ case FOURBLADE_TRANS_SUBTYPE:
+ nBlades = 4;
+ break;
+ case EIGHTBLADE_TRANS_SUBTYPE:
+ nBlades = 8;
+ break;
+ default:
+ log( 'createClipPolyPolygon: unknown subtype: ' + nSubtype );
+ return null;
+ }
+ return new PinWheelWipePath( nBlades );
+ }
+}
+
+
+
+// ------------------------------------------------------------------------------------------ //
+function createUnitSquarePath()
+{
+ var aPath = document.createElementNS( NSS['svg'], 'path' );
+ var sD = 'M 0 0 L 1 0 L 1 1 L 0 1 L 0 0';
+ aPath.setAttribute( 'd', sD );
+ return aPath;
+}
+
+function pruneScaleValue( nVal )
+{
+ if( nVal < 0.0 )
+ return (nVal < -0.00001 ? nVal : -0.00001);
+ else
+ return (nVal > 0.00001 ? nVal : 0.00001);
+}
+
+// ------------------------------------------------------------------------------------------ //
+/** Class BarWipePath
+ * This class handles a <path> element that defines a unit square and
+ * transforms it accordingly to a parameter in the [0,1] range for performing
+ * a left to right barWipe transition.
+ *
+ * @param nBars
+ * The number of bars to be generated.
+ */
+function BarWipePath( nBars /* nBars > 1: blinds effect */ )
+{
+ this.nBars = nBars;
+ if( this.nBars === undefined || this.nBars < 1 )
+ this.nBars = 1;
+ this.aBasePath = createUnitSquarePath();
+}
+
+/** perform
+ *
+ * @param nT
+ * A parameter in [0,1] representing the width of the generated bars.
+ * @return {SVGPathElement}
+ * A svg <path> element representing a multi-bars.
+ */
+BarWipePath.prototype.perform = function( nT )
+{
+
+ var aMatrix = SVGIdentityMatrix.scaleNonUniform( pruneScaleValue( nT / this.nBars ), 1.0 );
+
+ var aPolyPath = this.aBasePath.cloneNode( true );
+ aPolyPath.matrixTransform( aMatrix );
+
+ if( this.nBars > 1 )
+ {
+ var i;
+ var aTransform;
+ var aPath;
+ for( i = this.nBars - 1; i > 0; --i )
+ {
+ aTransform = SVGIdentityMatrix.translate( i / this.nBars, 0.0 );
+ aTransform = aTransform.multiply( aMatrix );
+ aPath = this.aBasePath.cloneNode( true );
+ aPath.matrixTransform( aTransform );
+ aPolyPath.appendPath( aPath );
+ }
+ }
+ return aPolyPath;
+};
+
+
+
+// ------------------------------------------------------------------------------------------ //
+/** Class FourBoxWipePath
+ * This class handles a path made up by four squares and is utilized for
+ * performing fourBoxWipe transitions.
+ *
+ * @param bCornersOut
+ * If true the transition subtype is cornersOut else is cornersIn.
+ */
+function FourBoxWipePath( bCornersOut )
+{
+ this.bCornersOut = bCornersOut;
+ this.aBasePath = createUnitSquarePath();
+}
+
+FourBoxWipePath.prototype.perform = function( nT )
+{
+ var aMatrix;
+ var d = pruneScaleValue( nT / 2.0 );
+
+ if( this.bCornersOut )
+ {
+ aMatrix = SVGIdentityMatrix.translate( -0.25, -0.25 ).scale( d ).translate( -0.5, -0.5 );
+ }
+ else
+ {
+ aMatrix = SVGIdentityMatrix.translate( -0.5, -0.5 ).scale( d );
+ }
+
+
+ var aTransform = aMatrix;
+ // top left
+ var aSquare = this.aBasePath.cloneNode( true );
+ aSquare.matrixTransform( aTransform );
+ var aPolyPath = aSquare;
+ // bottom left, flip on x-axis:
+ aMatrix = SVGIdentityMatrix.flipY();
+ aTransform = aMatrix.multiply( aTransform );
+ aSquare = this.aBasePath.cloneNode( true );
+ aSquare.matrixTransform( aTransform );
+ aSquare.changeOrientation();
+ aPolyPath.appendPath( aSquare );
+ // bottom right, flip on y-axis:
+ aMatrix = SVGIdentityMatrix.flipX();
+ aTransform = aMatrix.multiply( aTransform );
+ aSquare = this.aBasePath.cloneNode( true );
+ aSquare.matrixTransform( aTransform );
+ aPolyPath.appendPath( aSquare );
+ // top right, flip on x-axis:
+ aMatrix = SVGIdentityMatrix.flipY();
+ aTransform = aMatrix.multiply( aTransform );
+ aSquare = this.aBasePath.cloneNode( true );
+ aSquare.matrixTransform( aTransform );
+ aSquare.changeOrientation();
+ aPolyPath.appendPath( aSquare );
+
+ aMatrix = SVGIdentityMatrix.translate( 0.5, 0.5 );
+ aPolyPath.matrixTransform( aMatrix );
+
+ return aPolyPath;
+};
+
+
+
+// ------------------------------------------------------------------------------------------ //
+/** Class EllipseWipePath
+ * This class handles a parametric ellipse represented by a path made up of
+ * cubic Bezier curve segments that helps in performing the ellipseWipe
+ * transition.
+ *
+ * @param eSubtype
+ * The transition subtype.
+ */
+function EllipseWipePath( eSubtype )
+{
+ this.eSubtype = eSubtype;
+
+ var sPathData;
+
+ switch( eSubtype )
+ {
+ case DEFAULT_TRANS_SUBTYPE:
+ case CIRCLE_TRANS_SUBTYPE:
+ // precomputed circle( 0.5, 0.5, SQRT2 / 2 )
+ sPathData = 'M 0.5 -0.207107 ' +
+ 'C 0.687536 -0.207107 0.867392 -0.132608 1 0 ' +
+ 'C 1.13261 0.132608 1.20711 0.312464 1.20711 0.5 ' +
+ 'C 1.20711 0.687536 1.13261 0.867392 1 1 ' +
+ 'C 0.867392 1.13261 0.687536 1.20711 0.5 1.20711 ' +
+ 'C 0.312464 1.20711 0.132608 1.13261 0 1 ' +
+ 'C -0.132608 0.867392 -0.207107 0.687536 -0.207107 0.5 ' +
+ 'C -0.207107 0.312464 -0.132608 0.132608 0 0 ' +
+ 'C 0.132608 -0.132608 0.312464 -0.207107 0.5 -0.207107';
+ break;
+ case VERTICAL_TRANS_SUBTYPE:
+ sPathData = '';
+ break;
+ case HORIZONTAL_TRANS_SUBTYPE:
+ sPathData = '';
+ break;
+ default:
+ log( 'EllipseWipePath: unknown subtype: ' + eSubtype );
+ }
+
+ this.aBasePath = document.createElementNS( NSS['svg'], 'path' );
+ this.aBasePath.setAttribute( 'd', sPathData );
+}
+
+EllipseWipePath.prototype.perform = function( nT )
+{
+
+ var aTransform = SVGIdentityMatrix.translate( 0.5, 0.5 ).scale( nT ).translate( -0.5, -0.5 );
+ var aEllipse = this.aBasePath.cloneNode( true );
+ aEllipse.matrixTransform( aTransform );
+
+ return aEllipse;
+};
+
+
+
+// ------------------------------------------------------------------------------------------ //
+/** Class PinWheelWipePath
+ * This class handles a parametric poly-path that is used for performing
+ * a spinWheelWipe transition.
+ *
+ * @param nBlades
+ * Number of blades generated by the transition.
+ */
+function PinWheelWipePath( nBlades )
+{
+ this.nBlades = nBlades;
+ if( !this.nBlades || this.nBlades < 1 )
+ this.nBlades = 1;
+}
+
+PinWheelWipePath.calcCenteredClock = function( nT, nE )
+{
+ var nMAX_EDGE = 2;
+
+ var aTransform = SVGIdentityMatrix.rotate( nT * 360 );
+
+ var aPoint = document.documentElement.createSVGPoint();
+ aPoint.y = -nMAX_EDGE;
+ aPoint = aPoint.matrixTransform( aTransform );
+
+ var sPathData = 'M ' + aPoint.x + ' ' + aPoint.y + ' ';
+ if( nT >= 0.875 )
+ // L -e -e
+ sPathData += 'L ' + '-' + nE + ' -' + nE + ' ';
+ if( nT >= 0.625 )
+ // L -e e
+ sPathData += 'L ' + '-' + nE + ' ' + nE + ' ';
+ if( nT >= 0.375 )
+ // L e e
+ sPathData += 'L ' + nE + ' ' + nE + ' ';
+ if( nT >= 0.125 )
+ // L e -e
+ sPathData += 'L ' + nE + ' -' + nE + ' ';
+
+ // L 0 -e
+ sPathData += 'L 0 -' + nE + ' ';
+ sPathData += 'L 0 0 ';
+ // Z
+ sPathData += 'L ' + aPoint.x + ' ' + aPoint.y;
+
+ var aPath = document.createElementNS( NSS['svg'], 'path' );
+ aPath.setAttribute( 'd', sPathData );
+ return aPath;
+};
+
+PinWheelWipePath.prototype.perform = function( nT )
+{
+ var aBasePath = PinWheelWipePath.calcCenteredClock( nT / this.nBlades,
+ 2.0 /* max edge when rotating */ );
+
+ var aPolyPath = aBasePath.cloneNode( true );
+ var aPath;
+ var aRotation;
+ var i;
+ for( i = this.nBlades - 1; i > 0; --i )
+ {
+ aRotation = SVGIdentityMatrix.rotate( (i * 360) / this.nBlades );
+ aPath = aBasePath.cloneNode( true );
+ aPath.matrixTransform( aRotation );
+ aPolyPath.appendPath( aPath );
+ }
+
+ var aTransform = SVGIdentityMatrix.translate( 0.5, 0.5 ).scale( 0.5 );
+ aPolyPath.matrixTransform( aTransform );
+
+ return aPolyPath;
+};
+
+
+// ------------------------------------------------------------------------------------------ //
/** Class AnimatedSlide
* This class handle a slide element during a slide transition.
*
@@ -6384,8 +7789,13 @@ function AnimatedSlide( aMetaSlide )
this.aMetaSlide = aMetaSlide;
this.aSlideElement = this.aMetaSlide.slideElement;
+ this.sSlideId = this.aMetaSlide.slideId;
this.aUsedAttributeSet = new Array();
+
+ this.aClipPathElement = null;
+ this.aClipPathContent = null;
+ this.bIsClipped = false;
}
/** show
@@ -6413,7 +7823,15 @@ AnimatedSlide.prototype.hide = function()
*/
AnimatedSlide.prototype.notifyUsedAttribute = function( sName )
{
- this.aUsedAttributeSet.push( sName );
+ if( sName == 'clip-path' )
+ {
+ this.initClipPath();
+ this.bIsClipped = true;
+ }
+ else
+ {
+ this.aUsedAttributeSet.push( sName );
+ }
};
/** reset
@@ -6422,6 +7840,12 @@ AnimatedSlide.prototype.notifyUsedAttribute = function( sName )
*/
AnimatedSlide.prototype.reset = function()
{
+ if( this.bIsClipped )
+ {
+ this.cleanClipPath();
+ this.bIsClipped = false;
+ }
+
var i;
for( i = 0; i < this.aUsedAttributeSet.length; ++i )
{
@@ -6431,6 +7855,55 @@ AnimatedSlide.prototype.reset = function()
this.aUsedAttributeSet = new Array();
};
+/** initClipPath
+ * Create a new clip path element and append it to the clip path def group.
+ * Moreover the created <clipPath> element is referenced by the handled slide
+ * element.
+ */
+AnimatedSlide.prototype.initClipPath = function()
+{
+ // We create the clip path element.
+ this.aClipPathElement = document.createElementNS( NSS['svg'], 'clipPath' );
+
+ var sId = 'clip-path-' + this.sSlideId;
+ this.aClipPathElement.setAttribute( 'id', sId );
+ //this.aClipPathElement.setAttribute( 'clipPathUnits', 'userSpaceOnUse' );
+
+ // We create and append a placeholder content.
+ this.aClipPathContent = document.createElementNS( NSS['svg'], 'path' );
+ var sPathData = 'M 0 0 h ' + WIDTH + ' v ' + HEIGHT + ' h -' + WIDTH + ' z';
+ this.aClipPathContent.setAttribute( 'd', sPathData );
+ this.aClipPathElement.appendChild( this.aClipPathContent );
+
+ // We insert it into the svg document.
+ var aClipPathGroup = theMetaDoc.aClipPathGroup;
+ aClipPathGroup.appendChild( this.aClipPathElement );
+
+ // Finally we set the reference to the created clip path.
+ // We set it on the parent element because a slide element already
+ // owns a clip path attribute.
+ var sRef = 'url(#' + sId + ')';
+ this.aSlideElement.parentNode.setAttribute( 'clip-path', sRef );
+};
+
+/** cleanClipPath
+ * Removes the related <clipPath> element from the <defs> group,
+ * and remove the 'clip-path' attribute from the slide element.
+ *
+ */
+AnimatedSlide.prototype.cleanClipPath = function()
+{
+ this.aSlideElement.parentNode.removeAttribute( 'clip-path' );
+
+ if( this.aClipPathElement )
+ {
+ var aClipPathGroup = theMetaDoc.aClipPathGroup;
+ aClipPathGroup.removeChild( this.aClipPathElement );
+ this.aClipPathElement = null;
+ this.aClipPathContent = null;
+ }
+};
+
/** insertBefore
* Insert an svg element before the handled slide element.
*
@@ -6459,7 +7932,7 @@ AnimatedSlide.prototype.appendElement = function( aElement )
}
};
-/** appendElement
+/** removeElement
* Remove an svg element.
*
* @param aElement
@@ -6517,6 +7990,25 @@ AnimatedSlide.prototype.translate = function( nDx, nDy )
this.aSlideElement.setAttribute( 'transform', sTransformAttr );
};
+/** setClipPath
+ * Replace the current content of the <clipPath> element with the one
+ * passed through the parameter.
+ *
+ * @param aClipPathContent
+ * A <g> element representing a <path> element used for clipping.
+ */
+AnimatedSlide.prototype.setClipPath = function( aClipPathContent )
+{
+ // Earlier we used to replace the current <path> element with the passed one,
+ // anyway that does not work in IE9, so we replace the 'd' attribute, only.
+ if( this.aClipPathContent )
+ {
+// this.aClipPathElement.replaceChild( aClipPathContent, this.aClipPathContent );
+// this.aClipPathContent = aClipPathContent;
+ var sPathData = aClipPathContent.getAttribute( 'd' );
+ this.aClipPathContent.setAttribute( 'd', sPathData );
+ }
+};
// ------------------------------------------------------------------------------------------ //
@@ -7009,7 +8501,10 @@ SlideTransition.prototype.createSlideTransition = function( aLeavingSlide, aEnte
return null;
case TRANSITION_CLIP_POLYPOLYGON:
- return null;
+ var aParametricPolyPolygon
+ = createClipPolyPolygon( this.eTransitionType, this.eTransitionSubType );
+ return new ClippedSlideChange( aLeavingSlide, aEnteringSlide, aParametricPolyPolygon,
+ aTransitionInfo, this.isDirectionForward() );
case TRANSITION_SPECIAL:
switch( this.eTransitionType )
@@ -7136,12 +8631,6 @@ SlideTransition.prototype.parseElement = function()
if( sDirectionAttr == 'reverse' )
this.bReverseDirection = true;
- // mode attribute:
- this.eTransitionMode = TRANSITION_MODE_IN;
- var sModeAttr = aAnimElem.getAttribute( 'mode' );
- if( sModeAttr === 'out' )
- this.eTransitionMode = TRANSITION_MODE_OUT;
-
// fade color
this.sFadeColor = null;
if( this.eTransitionType == FADE_TRANSITION &&
@@ -7202,9 +8691,9 @@ SlideTransition.prototype.getFadeColor = function()
return this.sFadeColor;
};
-SlideTransition.prototype.getReverseDirection = function()
+SlideTransition.prototype.isDirectionForward = function()
{
- return this.bReverseDirection;
+ return !this.bReverseDirection;
};
SlideTransition.prototype.getDuration = function()
@@ -7228,7 +8717,7 @@ SlideTransition.prototype.info = function()
sInfo += '; subtype: ' + aTransitionSubtypeOutMap[ this.getTransitionSubType() ];
// transition direction
- if( this.getReverseDirection() )
+ if( !this.isDirectionForward() )
sInfo += '; direction: reverse';
// transition mode
@@ -9155,8 +10644,6 @@ SlideShow.prototype.notifyTransitionEnd = function( nSlideIndex )
// clear all queues
this.dispose();
- this.notifySlideStart( nSlideIndex );
-
theMetaDoc.getCurrentSlide().aSlideAnimationsHandler.start();
this.update();
}
@@ -9228,6 +10715,8 @@ SlideShow.prototype.displaySlide = function( nNewSlide, bSkipSlideTransition )
}
}
+ this.notifySlideStart( nNewSlide );
+
if( this.isEnabled() && !bSkipSlideTransition )
{
// create slide transition and add to activity queue
@@ -9279,7 +10768,7 @@ SlideShow.prototype.displaySlide = function( nNewSlide, bSkipSlideTransition )
SlideShow.prototype.update = function()
{
this.aTimer.holdTimer();
- var suspendHandle = ROOT_NODE.suspendRedraw( PREFERRED_FRAME_RATE * 1000 );
+ //var suspendHandle = ROOT_NODE.suspendRedraw( PREFERRED_FRAME_RATE * 1000 );
// process queues
this.aTimerEventQueue.process();
@@ -9289,8 +10778,8 @@ SlideShow.prototype.update = function()
this.aActivityQueue.processDequeued();
- ROOT_NODE.unsuspendRedraw(suspendHandle);
- ROOT_NODE.forceRedraw();
+ //ROOT_NODE.unsuspendRedraw(suspendHandle);
+ //ROOT_NODE.forceRedraw();
this.aTimer.releaseTimer();
var bActivitiesLeft = ( ! this.aActivityQueue.isEmpty() );
diff --git a/filter/source/svg/svgexport.cxx b/filter/source/svg/svgexport.cxx
index 3d04812..bcb2e29 100644
--- a/filter/source/svg/svgexport.cxx
+++ b/filter/source/svg/svgexport.cxx
@@ -748,6 +748,7 @@ sal_Bool SVGFilter::implExportDocument()
// Create a ClipPath element that will be used for cutting bitmaps and other elements that could exceed the page margins.
{
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "class", B2UCONST( "ClipPathGroup" ) );
SvXMLElementExport aDefsElem( *mpSVGExport, XML_NAMESPACE_NONE, "defs", sal_True, sal_True );
{
mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", msClipPathId );
commit a962bffa18e81032423e1c5c7065125d27caa163
Author: Marco Cecchetti <mrcekets at gmail.com>
Date: Thu May 31 21:45:13 2012 +0200
Enabled support for fade, slide wipe and push wipe slide transitions.
Ported or implemented the following classes: SlideTransition,
AnimatedSlide, SlideChangeBase, FadingSlideChange,
FadingOverColorSlideChange, MovingSlideChange.
Modified and added new methods to: MetaSlide, SlideShow.
diff --git a/filter/source/svg/presentation_engine.js b/filter/source/svg/presentation_engine.js
index 53ab747..7b17623 100644
--- a/filter/source/svg/presentation_engine.js
+++ b/filter/source/svg/presentation_engine.js
@@ -635,6 +635,7 @@ var aOOOAttrNumberingType = 'page-numbering-type';
var aOOOAttrSlide = 'slide';
var aOOOAttrMaster = 'master';
+var aOOOAttrHasTransition = 'has-transition';
var aOOOAttrBackgroundVisibility = 'background-visibility';
var aOOOAttrMasterObjectsVisibility = 'master-objects-visibility';
var aOOOAttrPageNumberVisibility = 'page-number-visibility';
@@ -1194,6 +1195,16 @@ function MetaSlide( sMetaSlideId, aMetaDoc )
this.aTextFieldContentProviderSet[aFooterClassName] = this.initFixedTextFieldContentProvider( aOOOAttrFooterField );
this.aTextFieldContentProviderSet[aHeaderClassName] = this.initFixedTextFieldContentProvider( aOOOAttrHeaderField );
+ // We look for slide transition.
+ this.aTransitionHandler = null;
+ this.bHasTransition = this.initHasTransition() || true;
+ if( this.bHasTransition )
+ {
+ this.aTransitionHandler = new SlideTransition( this.getSlideAnimationsRoot(), this.slideId );
+ if( this.aTransitionHandler.isValid() )
+ log( this.aTransitionHandler.info() );
+ }
+
// We initialize the SlideAnimationsHandler object
this.aSlideAnimationsHandler = new SlideAnimations( aSlideShow.getContext() );
this.aSlideAnimationsHandler.importAnimations( this.getSlideAnimationsRoot() );
@@ -1210,7 +1221,8 @@ MetaSlide.prototype =
/*** public methods ***/
/** show
- * Set the visibility property of the slide to 'inherit'.
+ * Set the visibility property of the slide to 'inherit'
+ * and update the master page view.
*/
show : function()
{
@@ -1261,6 +1273,12 @@ initMasterPage : function()
return this.theMetaDoc.aMasterPageSet[ sMasterPageId ];
},
+initHasTransition : function()
+{
+ var sHasTransition = this.element.getAttributeNS( NSS['ooo'], aOOOAttrHasTransition );
+ return ( sHasTransition === 'true' );
+},
+
initVisibilityProperty : function( aVisibilityAttribute, nDefaultValue )
{
var nVisibility = nDefaultValue;
@@ -1596,6 +1614,15 @@ MasterPageView.prototype.createElement = function()
'MasterPageView.createElement: failed to create a master page view element.' );
aMasterPageViewElement.setAttribute( 'class', 'MasterPageView' );
+ // we place a white rect below any else element
+ // that is also a workaround for some kind of slide transition
+ // when the master page is empty
+ var aWhiteRect = theDocument.createElementNS( NSS['svg'], 'rect' );
+ aWhiteRect.setAttribute( 'width', String( WIDTH ) );
+ aWhiteRect.setAttribute( 'height', String( HEIGHT) );
+ aWhiteRect.setAttribute( 'fill', '#FFFFFF' );
+ aMasterPageViewElement.appendChild( aWhiteRect );
+
// init the Background element
if( this.aMetaSlide.nIsBackgroundVisible )
{
@@ -2491,7 +2518,7 @@ function dispatchEffects(dir)
function skipEffects(dir)
{
// TODO to be implemented
- switchSlide(dir);
+ switchSlide(dir, true);
}
function switchSlide( nOffset, bSkipTransition )
@@ -2616,6 +2643,67 @@ function bind( aObject, aMethod )
};
}
+function bind2( aFunction )
+{
+ var aBoundArgList = arguments;
+
+ var aResultFunction = null;
+
+ switch( aBoundArgList.length )
+ {
+ case 1: aResultFunction = function()
+ {
+ return aFunction.call( arguments[0], arguments[1],
+ arguments[2], arguments[3],
+ arguments[4] );
+ };
+ break;
+ case 2: aResultFunction = function()
+ {
+ return aFunction.call( aBoundArgList[1], arguments[0],
+ arguments[1], arguments[2],
+ arguments[3] );
+ };
+ break;
+ case 3: aResultFunction = function()
+ {
+ return aFunction.call( aBoundArgList[1], aBoundArgList[2],
+ arguments[0], arguments[1],
+ arguments[2] );
+ };
+ break;
+ case 4: aResultFunction = function()
+ {
+ return aFunction.call( aBoundArgList[1], aBoundArgList[2],
+ aBoundArgList[3], arguments[0],
+ arguments[1] );
+ };
+ break;
+ case 5: aResultFunction = function()
+ {
+ return aFunction.call( aBoundArgList[1], aBoundArgList[2],
+ aBoundArgList[3], aBoundArgList[4],
+ arguments[0] );
+ };
+ break;
+ default:
+ log( 'bind2: arity not handled.' );
+ }
+
+ return aResultFunction;
+}
+
+//function concat3( s1, s2, s3 )
+//{
+// log( s1 + s2 + s3 );
+//}
+//
+//var bound1 = bind2( concat3, 'Qui' );
+//bound1( 'Quo', 'Qua' );
+//
+//var bound2 = bind2( concat3, 'Qui', 'Quo' );
+//bound2( 'Qua' );
+
function getCurrentSystemTime()
{
return ( new Date() ).getTime();
@@ -3333,31 +3421,59 @@ var aAttributeMap =
};
+// Transition Classes
+TRANSITION_INVALID = 0; // Invalid type
+TRANSITION_CLIP_POLYPOLYGON = 1; // Transition expressed by parametric clip polygon
+TRANSITION_SPECIAL = 2; // Transition expressed by hand-crafted function
+
+aTransitionClassOutMap = ['invalid', 'clip polypolygon', 'special'];
+
+
// Transition Types
BARWIPE_TRANSITION = 1;
-FADE_TRANSITION = 2; // 37
+PUSHWIPE_TRANSITION = 2; // 35
+SLIDEWIPE_TRANSITION = 3; // 36
+FADE_TRANSITION = 4; // 37
aTransitionTypeInMap = {
'barWipe' : BARWIPE_TRANSITION,
+ 'pushWipe' : PUSHWIPE_TRANSITION,
+ 'slideWipe' : SLIDEWIPE_TRANSITION,
'fade' : FADE_TRANSITION
};
-aTransitionTypeOutMap = [ '', 'barWipe', 'fade' ];
+aTransitionTypeOutMap = [ '', 'barWipe', 'pushWipe', 'slideWipe', 'fade' ];
// Transition Subtypes
DEFAULT_TRANS_SUBTYPE = 0;
LEFTTORIGHT_TRANS_SUBTYPE = 1;
TOPTOBOTTOM_TRANS_SUBTYPE = 2;
-CROSSFADE_TRANS_SUBTYPE = 3; // 101
+FROMLEFT_TRANS_SUBTYPE = 3; // 97
+FROMTOP_TRANS_SUBTYPE = 4;
+FROMRIGHT_TRANS_SUBTYPE = 5;
+FROMBOTTOM_TRANS_SUBTYPE = 6
+CROSSFADE_TRANS_SUBTYPE = 7;
+FADETOCOLOR_TRANS_SUBTYPE = 8;
+FADEFROMCOLOR_TRANS_SUBTYPE = 9;
+FADEOVERCOLOR_TRANS_SUBTYPE = 10; // 104
aTransitionSubtypeInMap = {
'leftToRight' : LEFTTORIGHT_TRANS_SUBTYPE,
'topToBottom' : TOPTOBOTTOM_TRANS_SUBTYPE,
- 'crossfade' : CROSSFADE_TRANS_SUBTYPE
+ 'fromLeft' : FROMLEFT_TRANS_SUBTYPE,
+ 'fromTop' : FROMTOP_TRANS_SUBTYPE,
+ 'fromRight' : FROMRIGHT_TRANS_SUBTYPE,
+ 'fromBottom' : FROMBOTTOM_TRANS_SUBTYPE,
+ 'crossfade' : CROSSFADE_TRANS_SUBTYPE,
+ 'fadeToColor' : FADETOCOLOR_TRANS_SUBTYPE,
+ 'fadeFromColor' : FADEFROMCOLOR_TRANS_SUBTYPE,
+ 'fadeOverColor' : FADEOVERCOLOR_TRANS_SUBTYPE
};
-aTransitionSubtypeOutMap = [ 'default', 'leftToRight', 'topToBottom', 'crossfade' ];
+aTransitionSubtypeOutMap = [ 'default', 'leftToRight', 'topToBottom', 'fromLeft',
+ 'fromTop', 'fromRight', 'fromBottom', 'crossfade',
+ 'fadeToColor', 'fadeFromColor', 'fadeOverColor' ];
// Transition Modes
@@ -3368,6 +3484,116 @@ aTransitionModeInMap = { 'out': TRANSITION_MODE_OUT, 'in': TRANSITION_MODE_IN };
aTransitionModeOutMap = [ 'out', 'in' ];
+// Transition Reverse Methods
+
+// Ignore direction attribute altogether.
+// (If it has no sensible meaning for this transition.)
+REVERSEMETHOD_IGNORE = 0;
+// Revert by changing the direction of the parameter sweep.
+// (From 1->0 instead of 0->1)
+REVERSEMETHOD_INVERT_SWEEP = 1;
+// Revert by subtracting the generated polygon from the target bound rect.
+REVERSEMETHOD_SUBTRACT_POLYGON = 2;
+// Combination of REVERSEMETHOD_INVERT_SWEEP and REVERSEMETHOD_SUBTRACT_POLYGON.
+REVERSEMETHOD_SUBTRACT_AND_INVERT = 3;
+// Reverse by rotating polygon 180 degrees.
+REVERSEMETHOD_ROTATE_180 = 4;
+// Reverse by flipping polygon at the y axis.
+REVERSEMETHOD_FLIP_X = 5;
+// Reverse by flipping polygon at the x axis.
+REVERSEMETHOD_FLIP_Y = 6;
+
+aReverseMethodOutMap = ['ignore', 'invert sweep', 'subtract polygon',
+ 'subtract and invert', 'rotate 180', 'flip x', 'flip y'];
+
+// ------------------------------------------------------------------------------------------ //
+// Transition filter info table
+
+var aTransitionInfoTable = {};
+
+// type: fake transition
+aTransitionInfoTable[0] = {};
+// subtype: default
+aTransitionInfoTable[0][0] =
+{
+ 'class' : TRANSITION_INVALID,
+ 'rotationAngle' : 0.0,
+ 'scaleX' : 0.0,
+ 'scaleY' : 0.0,
+ 'reverseMethod' : REVERSEMETHOD_IGNORE,
+ 'outInvertsSweep' : false,
+ 'scaleIsotropically' : false
+};
+
+
+aTransitionInfoTable[BARWIPE_TRANSITION] = {};
+aTransitionInfoTable[BARWIPE_TRANSITION][LEFTTORIGHT_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 0.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_FLIP_X,
+ 'outInvertsSweep' : false,
+ 'scaleIsotropically' : false
+};
+aTransitionInfoTable[BARWIPE_TRANSITION][TOPTOBOTTOM_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 90.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_FLIP_Y,
+ 'outInvertsSweep' : false,
+ 'scaleIsotropically' : false
+};
+
+aTransitionInfoTable[PUSHWIPE_TRANSITION] = {};
+aTransitionInfoTable[PUSHWIPE_TRANSITION][FROMLEFT_TRANS_SUBTYPE] =
+aTransitionInfoTable[PUSHWIPE_TRANSITION][FROMTOP_TRANS_SUBTYPE] =
+aTransitionInfoTable[PUSHWIPE_TRANSITION][FROMRIGHT_TRANS_SUBTYPE] =
+aTransitionInfoTable[PUSHWIPE_TRANSITION][FROMBOTTOM_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_SPECIAL,
+ 'rotationAngle' : 0.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_IGNORE,
+ 'outInvertsSweep' : true,
+ 'scaleIsotropically' : false
+};
+
+aTransitionInfoTable[SLIDEWIPE_TRANSITION] = {};
+aTransitionInfoTable[SLIDEWIPE_TRANSITION][FROMLEFT_TRANS_SUBTYPE] =
+aTransitionInfoTable[SLIDEWIPE_TRANSITION][FROMTOP_TRANS_SUBTYPE] =
+aTransitionInfoTable[SLIDEWIPE_TRANSITION][FROMRIGHT_TRANS_SUBTYPE] =
+aTransitionInfoTable[SLIDEWIPE_TRANSITION][FROMBOTTOM_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_SPECIAL,
+ 'rotationAngle' : 0.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_IGNORE,
+ 'outInvertsSweep' : true,
+ 'scaleIsotropically' : false
+};
+
+aTransitionInfoTable[FADE_TRANSITION] = {};
+aTransitionInfoTable[FADE_TRANSITION][CROSSFADE_TRANS_SUBTYPE] =
+aTransitionInfoTable[FADE_TRANSITION][FADETOCOLOR_TRANS_SUBTYPE] =
+aTransitionInfoTable[FADE_TRANSITION][FADEFROMCOLOR_TRANS_SUBTYPE] =
+aTransitionInfoTable[FADE_TRANSITION][FADEOVERCOLOR_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_SPECIAL,
+ 'rotationAngle' : 0.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_IGNORE,
+ 'outInvertsSweep' : true,
+ 'scaleIsotropically' : false
+};
+
+
// ------------------------------------------------------------------------------------------ //
// Transition tables
@@ -5847,6 +6073,453 @@ HSLAnimationWrapper.prototype.getUnderlyingValue = function()
// ------------------------------------------------------------------------------------------ //
+/** Class SlideChangeBase
+ * The base abstract class of classes performing slide transitions.
+ *
+ * @param aLeavingSlide
+ * An object of type AnimatedSlide handling the leaving slide.
+ * @param aEnteringSlide
+ * An object of type AnimatedSlide handling the entering slide.
+ */
+function SlideChangeBase(aLeavingSlide, aEnteringSlide)
+{
+ this.aLeavingSlide = aLeavingSlide;
+ this.aEnteringSlide = aEnteringSlide;
+ this.bIsFinished = false;
+}
+
+/** start
+ * The transition initialization is performed here.
+ */
+SlideChangeBase.prototype.start = function()
+{
+ if( this.bIsFinished )
+ return;
+};
+
+/** start
+ * The transition clean up is performed here.
+ */
+SlideChangeBase.prototype.end = function()
+{
+ if( this.bIsFinished )
+ return;
+
+ this.aLeavingSlide.hide();
+ this.aEnteringSlide.reset();
+ this.aLeavingSlide.reset();
+
+ this.bIsFinished = true;
+};
+
+/** perform
+ * This method is responsible for performing the slide transition.
+ *
+ * @param nValue
+ * The time parameter.
+ * @return {Boolean}
+ * If the transition is performed returns tue else returns false.
+ */
+SlideChangeBase.prototype.perform = function( nValue )
+{
+ if( this.bIsFinished ) return false;
+
+ if( this.aLeavingSlide )
+ this.performOut( nValue );
+
+ if( this.aEnteringSlide )
+ this.performIn( nValue );
+
+ return true;
+};
+
+SlideChangeBase.prototype.getUnderlyingValue = function()
+{
+ return 0.0;
+};
+
+SlideChangeBase.prototype.performIn = function( nValue )
+{
+ log( 'SlideChangeBase.performIn: abstract method called' );
+};
+
+SlideChangeBase.prototype.performOut = function( nValue )
+{
+ log( 'SlideChangeBase.performOut: abstract method called' );
+};
+
+
+
+// ------------------------------------------------------------------------------------------ //
+/** Class FadingSlideChange
... etc. - the rest is truncated
More information about the Libreoffice-commits
mailing list