[Libreoffice-commits] core.git: Branch 'distro/collabora/cp-5.0' - 3 commits - filter/source sd/qa

Marco Cecchetti marco.cecchetti at collabora.com
Mon Dec 14 12:53:19 PST 2015


 filter/source/svg/presentation_engine.js |  238 ++++++++++++++++++++++++++++---
 filter/source/svg/svgexport.cxx          |   49 ++++--
 sd/qa/unit/SVGExportTests.cxx            |   18 +-
 3 files changed, 268 insertions(+), 37 deletions(-)

New commits:
commit 21e52eab685c8639eef9b607e817ca893107d8bd
Author: Marco Cecchetti <marco.cecchetti at collabora.com>
Date:   Mon Dec 14 17:20:31 2015 +0100

    svg export: borders of leaving slide are not covered by the entering one
    
    Change-Id: I4b7422eb77edd39a2c6bd427aa8c10d62b1e370d

diff --git a/filter/source/svg/presentation_engine.js b/filter/source/svg/presentation_engine.js
index 83b979f..66509c6 100644
--- a/filter/source/svg/presentation_engine.js
+++ b/filter/source/svg/presentation_engine.js
@@ -735,6 +735,7 @@ var aOOOElemMetaSlides = 'ooo:meta_slides';
 var aOOOElemMetaSlide = 'ooo:meta_slide';
 var aOOOElemTextField = 'ooo:text_field';
 var aPresentationClipPathId = 'presentation_clip_path';
+var aPresentationClipPathShrinkId = 'presentation_clip_path_shrink';
 
 // ooo attributes
 var aOOOAttrNumberOfSlides = 'number-of-slides';
@@ -1948,8 +1949,12 @@ MasterPageView.prototype.createElement = function()
     // 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) );
+    var nWidthExt = WIDTH / 1000;
+    var nHeightExt = HEIGHT / 1000;
+    aWhiteRect.setAttribute( 'x', String( -nWidthExt / 2 ) );
+    aWhiteRect.setAttribute( 'y', String( -nHeightExt / 2 ) );
+    aWhiteRect.setAttribute( 'width', String( WIDTH + nWidthExt ) );
+    aWhiteRect.setAttribute( 'height', String( HEIGHT + nHeightExt ) );
     aWhiteRect.setAttribute( 'fill', '#FFFFFF' );
     aMasterPageViewElement.appendChild( aWhiteRect );
 
@@ -12413,7 +12418,16 @@ SlideShow.prototype.notifySlideStart = function( nNewSlideIndex, nOldSlideIndex
 
 SlideShow.prototype.notifyTransitionEnd = function( nSlideIndex )
 {
-    theMetaDoc.setCurrentSlide( nSlideIndex );
+    // reset the presentation clip path on the leaving slide
+    // to the standard one when transition ends
+    if( theMetaDoc.getCurrentSlide() )
+    {
+        var sRef = 'url(#' + aPresentationClipPathId + ')';
+        theMetaDoc.getCurrentSlide().slideElement.setAttribute('clip-path', sRef);
+    }
+
+    theMetaDoc.setCurrentSlide(nSlideIndex);
+
     if( this.aSlideViewElement )
     {
         theMetaDoc.getCurrentSlide().aVisibilityStatusElement.parentNode.removeChild( this.aSlideViewElement );
@@ -12790,6 +12804,11 @@ SlideShow.prototype.displaySlide = function( nNewSlide, bSkipSlideTransition )
             var aSlideTransitionHandler = aNewMetaSlide.aTransitionHandler;
             if( aSlideTransitionHandler && aSlideTransitionHandler.isValid() )
             {
+                // clipPath element used for the leaving slide in order
+                // to avoid that slide borders are visible during transition
+                var sRef = 'url(#' + aPresentationClipPathShrinkId + ')';
+                aOldMetaSlide.slideElement.setAttribute( 'clip-path', sRef );
+
                 // when we switch from the last to the first slide we need to hide the last slide
                 // or nobody will see the transition, hence we create a view of the last slide and
                 // we place it before the first slide
@@ -12800,6 +12819,7 @@ SlideShow.prototype.displaySlide = function( nNewSlide, bSkipSlideTransition )
                     aNewMetaSlide.aVisibilityStatusElement.parentNode.insertBefore( this.aSlideViewElement, aNewMetaSlide.aVisibilityStatusElement );
                     aOldMetaSlide.hide();
                 }
+
                 var aLeavingSlide = aOldMetaSlide;
                 var aEnteringSlide = aNewMetaSlide;
                 var aTransitionEndEvent = makeEvent( bind2( this.notifyTransitionEnd, this, nNewSlide ) );
diff --git a/filter/source/svg/svgexport.cxx b/filter/source/svg/svgexport.cxx
index c4b2d7e..e9b29dc 100644
--- a/filter/source/svg/svgexport.cxx
+++ b/filter/source/svg/svgexport.cxx
@@ -845,6 +845,22 @@ bool SVGFilter::implExportDocument()
                 SvXMLElementExport aRectElem( *mpSVGExport, XML_NAMESPACE_NONE, "rect", true, true );
             }
         }
+        // Create a ClipPath element applied to the leaving slide in order
+        // to avoid that slide borders are visible during transition
+        {
+            mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", "presentation_clip_path_shrink" );
+            mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "clipPathUnits", "userSpaceOnUse" );
+            SvXMLElementExport aClipPathElem( *mpSVGExport, XML_NAMESPACE_NONE, "clipPath", true, true );
+            {
+                sal_Int32 nDocWidthExt = nDocWidth / 500;
+                sal_Int32 nDocHeightExt = nDocHeight / 500;
+                mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "x", OUString::number( nDocX + nDocWidthExt / 2 ) );
+                mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "y", OUString::number( nDocY + nDocHeightExt / 2) );
+                mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "width", OUString::number( nDocWidth - nDocWidthExt ) );
+                mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "height", OUString::number( nDocHeight - nDocHeightExt ) );
+                SvXMLElementExport aRectElem( *mpSVGExport, XML_NAMESPACE_NONE, "rect", true, true );
+            }
+        }
     }
 
     if( implLookForFirstVisiblePage() )  // OK! We found at least one visible page.
diff --git a/sd/qa/unit/SVGExportTests.cxx b/sd/qa/unit/SVGExportTests.cxx
index cd4259c..7dec2c6 100644
--- a/sd/qa/unit/SVGExportTests.cxx
+++ b/sd/qa/unit/SVGExportTests.cxx
@@ -100,15 +100,15 @@ public:
 
         assertXPath(svgDoc, MAKE_PATH_STRING( /SVG_SVG ), 1);
         assertXPath(svgDoc, MAKE_PATH_STRING( /SVG_SVG/SVG_G[2] ), "class", "SlideGroup");
-        assertXPath(svgDoc, MAKE_PATH_STRING( /SVG_SVG/SVG_G[2]/SVG_G/SVG_G ), "class", "Slide");
-        assertXPath(svgDoc, MAKE_PATH_STRING( /SVG_SVG/SVG_G[2]/SVG_G/SVG_G/SVG_G/SVG_G[1] ), "class", "TitleText");
-        assertXPath(svgDoc, MAKE_PATH_STRING( /SVG_SVG/SVG_G[2]/SVG_G/SVG_G/SVG_G/SVG_G[1]/SVG_G/SVG_TEXT ), "class", "TextShape");
-        assertXPath(svgDoc, MAKE_PATH_STRING( /SVG_SVG/SVG_G[2]/SVG_G/SVG_G/SVG_G/SVG_G[1]/SVG_G/SVG_TEXT/SVG_TSPAN ), "class", "TextParagraph");
-        assertXPath(svgDoc, MAKE_PATH_STRING( /SVG_SVG/SVG_G[2]/SVG_G/SVG_G/SVG_G/SVG_G[1]/SVG_G/SVG_TEXT/SVG_TSPAN ), "text-decoration", "underline");
-
-        assertXPath(svgDoc, MAKE_PATH_STRING( /SVG_SVG/SVG_G[2]/SVG_G/SVG_G/SVG_G/SVG_G[2]/SVG_G/SVG_TEXT ), "class", "TextShape");
-        assertXPath(svgDoc, MAKE_PATH_STRING( /SVG_SVG/SVG_G[2]/SVG_G/SVG_G/SVG_G/SVG_G[2]/SVG_G/SVG_TEXT/SVG_TSPAN ), "class", "TextParagraph");
-        assertXPath(svgDoc, MAKE_PATH_STRING( /SVG_SVG/SVG_G[2]/SVG_G/SVG_G/SVG_G/SVG_G[2]/SVG_G/SVG_TEXT/SVG_TSPAN ), "text-decoration", "line-through");
+        assertXPath(svgDoc, MAKE_PATH_STRING( /SVG_SVG/SVG_G[2]/SVG_G/SVG_G/SVG_G ), "class", "Slide");
+        assertXPath(svgDoc, MAKE_PATH_STRING( /SVG_SVG/SVG_G[2]/SVG_G/SVG_G/SVG_G/SVG_G/SVG_G[1] ), "class", "TitleText");
+        assertXPath(svgDoc, MAKE_PATH_STRING( /SVG_SVG/SVG_G[2]/SVG_G/SVG_G/SVG_G/SVG_G/SVG_G[1]/SVG_G/SVG_TEXT ), "class", "TextShape");
+        assertXPath(svgDoc, MAKE_PATH_STRING( /SVG_SVG/SVG_G[2]/SVG_G/SVG_G/SVG_G/SVG_G/SVG_G[1]/SVG_G/SVG_TEXT/SVG_TSPAN ), "class", "TextParagraph");
+        assertXPath(svgDoc, MAKE_PATH_STRING( /SVG_SVG/SVG_G[2]/SVG_G/SVG_G/SVG_G/SVG_G/SVG_G[1]/SVG_G/SVG_TEXT/SVG_TSPAN ), "text-decoration", "underline");
+
+        assertXPath(svgDoc, MAKE_PATH_STRING( /SVG_SVG/SVG_G[2]/SVG_G/SVG_G/SVG_G/SVG_G/SVG_G[2]/SVG_G/SVG_TEXT ), "class", "TextShape");
+        assertXPath(svgDoc, MAKE_PATH_STRING( /SVG_SVG/SVG_G[2]/SVG_G/SVG_G/SVG_G/SVG_G/SVG_G[2]/SVG_G/SVG_TEXT/SVG_TSPAN ), "class", "TextParagraph");
+        assertXPath(svgDoc, MAKE_PATH_STRING( /SVG_SVG/SVG_G[2]/SVG_G/SVG_G/SVG_G/SVG_G/SVG_G[2]/SVG_G/SVG_TEXT/SVG_TSPAN ), "text-decoration", "line-through");
     }
 
     CPPUNIT_TEST_SUITE(SdSVGFilterTest);
commit e546411f954cd493f027e67b2f2740445fa26ea9
Author: Marco Cecchetti <marco.cecchetti at collabora.com>
Date:   Mon Dec 14 14:21:45 2015 +0100

    svg export: transition not displayed when switching from last to first slide
    
    Some transition, such as those involving clipping, is not displayed when
    switching from last to first slide. That is due to the fact that the
    leaving slide (the last one) is over the entering slide (the first one).
    
    The issue has been solved by hiding the last slide and placing a view to
    it (svg:use) behind the first slide.
    
    Change-Id: Iac1d23a1b9834c301b8ae511ea3f81397e5a4229

diff --git a/filter/source/svg/presentation_engine.js b/filter/source/svg/presentation_engine.js
index c1e4645..83b979f 100644
--- a/filter/source/svg/presentation_engine.js
+++ b/filter/source/svg/presentation_engine.js
@@ -1218,7 +1218,7 @@ function MetaDocument()
     this.aMasterPageSet = new Object();
     this.aTextFieldHandlerSet = new Object();
     this.aTextFieldContentProviderSet = new Array();
-    this.aSlideNumberProvider =  new SlideNumberProvider( this.nStartSlideNumber + 1, this.sPageNumberingType );
+    this.aSlideNumberProvider = new SlideNumberProvider( this.nStartSlideNumber + 1, this.sPageNumberingType );
 
     // We create a map with key an id and value the svg element containing
     // the animations performed on the slide with such an id.
@@ -1336,7 +1336,8 @@ function MetaSlide( sMetaSlideId, aMetaDoc )
     else
         this.nSlideNumber= -1;
 
-    // Each slide element is wrapped by a <g> element that is responsible for
+    // Each slide element is double wrapped by <g> elements.
+    // The outer <g> element is responsible for
     // the slide element visibility. In fact the visibility attribute has
     // to be set on the parent of the slide element and not directly on
     // the slide element. The reason is that in index mode each slide
@@ -1351,7 +1352,14 @@ function MetaSlide( sMetaSlideId, aMetaDoc )
     // The workaround of setting up the visibility attribute on the slide
     // parent element let us to make visible a slide in a <use> element
     // even if the slide parent element visibility is set to 'hidden'.
-    this.aVisibilityStatusElement = this.slideElement.parentNode;
+    // The inner <g> element is used in order to append some element
+    // before or after the slide, operation that can be needed for some
+    // slide transition (e.g. fade through black). In this way we can
+    // create a view of both the slide and the appended elements that turns out
+    // to be useful for handling transition from the last to the first slide.
+    this.aContainerElement = this.slideElement.parentNode;
+    this.slideContainerId = this.aContainerElement.getAttribute( 'id' );
+    this.aVisibilityStatusElement = this.aContainerElement.parentNode;
 
     // We get a reference to the draw page element, where all shapes specific
     // of this slide live.
@@ -8503,7 +8511,7 @@ function AnimatedSlide( aMetaSlide )
 
     this.aMetaSlide = aMetaSlide;
     this.aSlideElement = this.aMetaSlide.slideElement;
-    this.sSlideId =  this.aMetaSlide.slideId;
+    this.sSlideId = this.aMetaSlide.slideId;
 
     this.aUsedAttributeSet = new Array();
 
@@ -8628,7 +8636,7 @@ AnimatedSlide.prototype.insertBefore = function( aElement )
 {
     if( aElement )
     {
-         this.aSlideElement.parentNode.insertBefore( aElement, this.aSlideElement );
+        this.aSlideElement.parentNode.insertBefore( aElement, this.aSlideElement );
     }
 };
 
@@ -8656,7 +8664,7 @@ AnimatedSlide.prototype.removeElement = function( aElement )
 {
     if( aElement )
     {
-         this.aSlideElement.parentNode.removeChild( aElement );
+        this.aSlideElement.parentNode.removeChild( aElement );
     }
 };
 
@@ -12406,6 +12414,11 @@ SlideShow.prototype.notifySlideStart = function( nNewSlideIndex, nOldSlideIndex
 SlideShow.prototype.notifyTransitionEnd = function( nSlideIndex )
 {
     theMetaDoc.setCurrentSlide( nSlideIndex );
+    if( this.aSlideViewElement )
+    {
+        theMetaDoc.getCurrentSlide().aVisibilityStatusElement.parentNode.removeChild( this.aSlideViewElement );
+        this.aSlideViewElement = null;
+    }
     if( this.isEnabled() )
     {
         // clear all queues
@@ -12777,6 +12790,16 @@ SlideShow.prototype.displaySlide = function( nNewSlide, bSkipSlideTransition )
             var aSlideTransitionHandler = aNewMetaSlide.aTransitionHandler;
             if( aSlideTransitionHandler && aSlideTransitionHandler.isValid() )
             {
+                // when we switch from the last to the first slide we need to hide the last slide
+                // or nobody will see the transition, hence we create a view of the last slide and
+                // we place it before the first slide
+                if( nOldSlide > nNewSlide )
+                {
+                    this.aSlideViewElement = document.createElementNS( NSS['svg'], 'use' );
+                    setNSAttribute( 'xlink', this.aSlideViewElement, 'href', '#' + aOldMetaSlide.slideContainerId );
+                    aNewMetaSlide.aVisibilityStatusElement.parentNode.insertBefore( this.aSlideViewElement, aNewMetaSlide.aVisibilityStatusElement );
+                    aOldMetaSlide.hide();
+                }
                 var aLeavingSlide = aOldMetaSlide;
                 var aEnteringSlide = aNewMetaSlide;
                 var aTransitionEndEvent = makeEvent( bind2( this.notifyTransitionEnd, this, nNewSlide ) );
diff --git a/filter/source/svg/svgexport.cxx b/filter/source/svg/svgexport.cxx
index 83bb22b..c4b2d7e 100644
--- a/filter/source/svg/svgexport.cxx
+++ b/filter/source/svg/svgexport.cxx
@@ -1601,23 +1601,34 @@ bool SVGFilter::implExportDrawPages( const SVGFilter::XDrawPageSequence & rxPage
             }
             SvXMLElementExport aGElement( *mpSVGExport, XML_NAMESPACE_NONE, "g", true, true );
 
+
             {
-                // add id attribute
+                // Insert a further inner the <g> open tag for handling elements
+                // inserted before or after a slide: that is used for some
+                // when swithing from the last to the first slide.
                 const OUString & sPageId = implGetValidIDFromInterface( rxPages[i] );
-                mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", sPageId );
+                OUString sContainerId = "container-";
+                sContainerId += sPageId;
+                mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", sContainerId );
+                SvXMLElementExport aContainerExp( *mpSVGExport, XML_NAMESPACE_NONE, "g", true, true );
 
-                mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "class", "Slide" );
+                {
+                    // add id attribute
+                    mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", sPageId );
 
-                // Adding a clip path to each exported slide , so in case
-                // bitmaps or other elements exceed the slide margins, they are
-                // trimmed, even when they are shown inside a thumbnail view.
-                OUString sClipPathAttrValue = "url(#" + msClipPathId + ")";
-                mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "clip-path", sClipPathAttrValue );
+                    mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "class", "Slide" );
 
-                SvXMLElementExport aSlideElement( *mpSVGExport, XML_NAMESPACE_NONE, "g", true, true );
+                    // Adding a clip path to each exported slide , so in case
+                    // bitmaps or other elements exceed the slide margins, they are
+                    // trimmed, even when they are shown inside a thumbnail view.
+                    OUString sClipPathAttrValue = "url(#" + msClipPathId + ")";
+                    mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "clip-path", sClipPathAttrValue );
 
-                bRet = implExportPage( sPageId, rxPages[i], xShapes, false /* is not a master page */ ) || bRet;
-            }
+                    SvXMLElementExport aSlideElement( *mpSVGExport, XML_NAMESPACE_NONE, "g", true, true );
+
+                    bRet = implExportPage( sPageId, rxPages[i], xShapes, false /* is not a master page */ ) || bRet;
+                }
+            } // append the </g> closing tag related to inserted elements
         } // append the </g> closing tag related to the svg element handling the slide visibility
     }
 
commit b42ae0c72d1d8dabfe5fe4be671919420e504e1c
Author: Marco Cecchetti <marco.cecchetti at collabora.com>
Date:   Fri Dec 11 16:29:38 2015 +0100

    svg export: added support for random bar and dissolve transitions
    
    Change-Id: Ib5e303599b04b031d7eefed56603bce0d1e1e570

diff --git a/filter/source/svg/presentation_engine.js b/filter/source/svg/presentation_engine.js
index c1cc82b..c1e4645 100644
--- a/filter/source/svg/presentation_engine.js
+++ b/filter/source/svg/presentation_engine.js
@@ -1077,6 +1077,17 @@ function getSafeIndex( nIndex, nMin, nMax )
         return nIndex;
 }
 
+/** getRandomInt
+ *
+ * @param nMax
+ * @returns {number}
+ *   an integer in [0,nMax[
+ */
+function getRandomInt( nMax )
+{
+    return Math.floor( Math.random() * nMax );
+}
+
 function isTextFieldElement( aElement )
 {
     var sClassName = aElement.getAttribute( 'class' );
@@ -3627,7 +3638,7 @@ SVGPathElement.prototype.changeOrientation = function()
     var aMovePathSeg = this.createSVGPathSegMovetoAbs( nCurrentX, nCurrentY );
     aPathSegList.insertItemBefore( aMovePathSeg, 0 );
 
-}
+};
 
 /** matrixTransform and changeOrientation
  *  We implement these methods for each path segment type still present
@@ -4120,11 +4131,13 @@ BOXWIPE_TRANSITION          = 2;
 FOURBOXWIPE_TRANSITION      = 3;
 ELLIPSEWIPE_TRANSITION      = 4; // 17
 CLOCKWIPE_TRANSITION        = 5; // 22
-PINWHEELWIPE_TRANSITION     = 6;  // 23
+PINWHEELWIPE_TRANSITION     = 6; // 23
 PUSHWIPE_TRANSITION         = 7; // 35
 SLIDEWIPE_TRANSITION        = 8; // 36
 FADE_TRANSITION             = 9; // 37
-CHECKERBOARDWIPE_TRANSITION = 10; // 39
+RANDOMBARWIPE_TRANSITION    = 10 // 38
+CHECKERBOARDWIPE_TRANSITION = 11; // 39
+DISSOLVE_TRANSITION         = 12; // 40
 
 aTransitionTypeInMap = {
     'barWipe'           : BARWIPE_TRANSITION,
@@ -4136,12 +4149,14 @@ aTransitionTypeInMap = {
     'pushWipe'          : PUSHWIPE_TRANSITION,
     'slideWipe'         : SLIDEWIPE_TRANSITION,
     'fade'              : FADE_TRANSITION,
-    'checkerBoardWipe'  : CHECKERBOARDWIPE_TRANSITION
+    'randomBarWipe'     : RANDOMBARWIPE_TRANSITION,
+    'checkerBoardWipe'  : CHECKERBOARDWIPE_TRANSITION,
+    'dissolve'          : DISSOLVE_TRANSITION
 };
 
 aTransitionTypeOutMap = [ '', 'barWipe', 'boxWipe', 'fourBoxWipe', 'ellipseWipe',
                           'clockWipe', 'pinWheelWipe', 'pushWipe', 'slideWipe',
-                          'fade', 'checkerBoardWipe' ];
+                          'fade', 'randomBarWipe', 'checkerBoardWipe', 'dissolve' ];
 
 
 // Transition Subtypes
@@ -4175,6 +4190,7 @@ ONEBLADE_TRANS_SUBTYPE              = 26; // 107
 ACROSS_TRANS_SUBTYPE                = 27;
 
 aTransitionSubtypeInMap = {
+    'default'           : DEFAULT_TRANS_SUBTYPE,
     'leftToRight'       : LEFTTORIGHT_TRANS_SUBTYPE,
     'topToBottom'       : TOPTOBOTTOM_TRANS_SUBTYPE,
     'cornersIn'         : CORNERSIN_TRANS_SUBTYPE,
@@ -4444,6 +4460,29 @@ aTransitionInfoTable[FADE_TRANSITION][FADEOVERCOLOR_TRANS_SUBTYPE] =
     'scaleIsotropically' : false
 };
 
+
+aTransitionInfoTable[RANDOMBARWIPE_TRANSITION] = {};
+aTransitionInfoTable[RANDOMBARWIPE_TRANSITION][VERTICAL_TRANS_SUBTYPE] =
+{
+    'class' : TRANSITION_CLIP_POLYPOLYGON,
+    'rotationAngle' : 90.0,
+    'scaleX' : 1.0,
+    'scaleY' : 1.0,
+    'reverseMethod' : REVERSEMETHOD_IGNORE,
+    'outInvertsSweep' : true,
+    'scaleIsotropically' : false
+};
+aTransitionInfoTable[RANDOMBARWIPE_TRANSITION][HORIZONTAL_TRANS_SUBTYPE] =
+{
+    'class' : TRANSITION_CLIP_POLYPOLYGON,
+    'rotationAngle' : 0.0,
+    'scaleX' : 1.0,
+    'scaleY' : 1.0,
+    'reverseMethod' : REVERSEMETHOD_IGNORE,
+    'outInvertsSweep' : true,
+    'scaleIsotropically' : false
+};
+
 aTransitionInfoTable[CHECKERBOARDWIPE_TRANSITION] = {};
 aTransitionInfoTable[CHECKERBOARDWIPE_TRANSITION][DOWN_TRANS_SUBTYPE] =
 {
@@ -4466,6 +4505,18 @@ aTransitionInfoTable[CHECKERBOARDWIPE_TRANSITION][ACROSS_TRANS_SUBTYPE] =
     'scaleIsotropically' : false
 };
 
+aTransitionInfoTable[DISSOLVE_TRANSITION] = {};
+aTransitionInfoTable[DISSOLVE_TRANSITION][DEFAULT_TRANS_SUBTYPE] =
+{
+    'class' : TRANSITION_CLIP_POLYPOLYGON,
+    'rotationAngle' : 0.0,
+    'scaleX' : 1.0,
+    'scaleY' : 1.0,
+    'reverseMethod' : REVERSEMETHOD_IGNORE,
+    'outInvertsSweep' : true,
+    'scaleIsotropically' : true
+};
+
 
 // Transition tables
 
@@ -5615,7 +5666,7 @@ function AnimationBaseNode( aAnimElem, aParentNode, aNodeContext )
     this.sClassName = 'AnimationBaseNode';
     this.bIsContainer = false;
     this.aTargetElement = null;
-    this.bIsTargetTextElement = false
+    this.bIsTargetTextElement = false;
     this.aAnimatedElement = null;
     this.aActivity = null;
 
@@ -6974,7 +7025,9 @@ AnimationTransitionFilterNode.prototype.parseElement = function()
     // subtype attribute
     this.eTransitionSubType = undefined;
     var sSubTypeAttr = aAnimElem.getAttributeNS( NSS['smil'], 'subtype' );
-    if( sSubTypeAttr && aTransitionSubtypeInMap[ sSubTypeAttr ] )
+    if( sSubTypeAttr === null )
+        sSubTypeAttr = 'default';
+    if( sSubTypeAttr && ( aTransitionSubtypeInMap[ sSubTypeAttr ] !== undefined  ) )
     {
         this.eTransitionSubType = aTransitionSubtypeInMap[ sSubTypeAttr ];
     }
@@ -8016,8 +8069,12 @@ function createClipPolyPolygon( nType, nSubtype )
                     return null;
             }
             return new PinWheelWipePath( nBlades );
+        case RANDOMBARWIPE_TRANSITION:
+            return new RandomWipePath( 128, true /* bars */ );
         case CHECKERBOARDWIPE_TRANSITION:
             return new CheckerBoardWipePath( 10 );
+        case DISSOLVE_TRANSITION:
+            return new RandomWipePath( 16 * 16, false /* dissolve */ );
     }
 }
 
@@ -8032,6 +8089,14 @@ function createUnitSquarePath()
     return aPath;
 }
 
+function createEmptyPath()
+{
+    var aPath = document.createElementNS( NSS['svg'], 'path' );
+    var sD = 'M 0 0 L 0 0';
+    aPath.setAttribute( 'd', sD );
+    return aPath;
+}
+
 function pruneScaleValue( nVal )
 {
     if( nVal < 0.0 )
@@ -8329,6 +8394,100 @@ CheckerBoardWipePath.prototype.perform = function( nT )
 
 
 
+/** Class RandomWipePath
+ *
+ *  @param nElements
+ *     The number of bars or cells to be used.
+ *  @param bRandomBars
+ *     true: generates a horizontal random bar wipe
+ *     false: generates a dissolve wipe
+ */
+function RandomWipePath( nElements, bRandomBars )
+{
+    this.nElements = nElements;
+    this.aBasePath = createUnitSquarePath();
+    this.aPositionArray = new Array( nElements );
+    this.aClipPath = createEmptyPath();
+    this.nAlreadyAppendedElements = 0;
+
+    if( bRandomBars ) // random bar wipe
+    {
+        var fEdgeLength = 1.0 / nElements;
+        var nPos;
+        for( nPos = 0; nPos < nElements; ++nPos )
+        {
+            this.aPositionArray[nPos] = { x: 0.0, y: pruneScaleValue( nPos * fEdgeLength ) }
+        }
+        var aTransform = SVGIdentityMatrix.scaleNonUniform( 1.0, pruneScaleValue( fEdgeLength ) );
+    }
+    else // dissolve wipe
+    {
+        var nSqrtElements = Math.round( Math.sqrt( nElements ) );
+        var fEdgeLength = 1.0 / nSqrtElements;
+        var nPos;
+        for( nPos = 0; nPos < nElements; ++nPos )
+        {
+            this.aPositionArray[nPos] = {
+                x: pruneScaleValue( ( nPos % nSqrtElements ) * fEdgeLength ),
+                y: pruneScaleValue( ( nPos / nSqrtElements ) * fEdgeLength ) }
+        }
+        var aTransform = SVGIdentityMatrix.scale( pruneScaleValue( fEdgeLength ) );
+    }
+    this.aBasePath.matrixTransform( aTransform );
+
+    var nPos1, nPos2;
+    var tmp;
+    for( nPos1 = nElements - 1; nPos1 > 0; --nPos1 )
+    {
+        nPos2 = getRandomInt( nPos1 + 1 );
+        tmp = this.aPositionArray[nPos1];
+        this.aPositionArray[nPos1] = this.aPositionArray[nPos2];
+        this.aPositionArray[nPos2] = tmp;
+    }
+}
+
+/** perform
+ *
+ *  @param nT
+ *      A parameter in [0,1] representing the width of the generated bars or squares.
+ *  @return {SVGPathElement}
+ *      A svg <path> element representing a multi bars or a multi squared cells.
+ */
+RandomWipePath.prototype.perform = function( nT )
+{
+    var aPolyPath = createEmptyPath();
+    var aPoint;
+    var aPath;
+    var aTransform;
+    var nElements = Math.round( nT * this.nElements );
+    if( nElements === 0 )
+    {
+        return aPolyPath;
+    }
+    // check if we need to reset the clip path
+    if( this.nAlreadyAppendedElements >= nElements )
+    {
+        this.nAlreadyAppendedElements = 0;
+        this.aClipPath = createEmptyPath();
+    }
+    var nPos;
+    for( nPos = this.nAlreadyAppendedElements; nPos < nElements; ++nPos )
+    {
+        aPoint = this.aPositionArray[nPos];
+        aPath = this.aBasePath.cloneNode( true );
+        aTransform = SVGIdentityMatrix.translate( aPoint.x, aPoint.y );
+        aPath.matrixTransform( aTransform );
+        aPolyPath.appendPath( aPath );
+    }
+
+    this.nAlreadyAppendedElements = nElements;
+    this.aClipPath.appendPath( aPolyPath );
+
+    return this.aClipPath.cloneNode( true );
+};
+
+
+
 /** Class AnimatedSlide
  *  This class handle a slide element during a slide transition.
  *
@@ -9603,7 +9762,9 @@ SlideTransition.prototype.parseElement = function()
     // subtype attribute
     this.eTransitionSubType = undefined;
     var sSubTypeAttr = aAnimElem.getAttributeNS( NSS['smil'], 'subtype' );
-    if( sSubTypeAttr && aTransitionSubtypeInMap[ sSubTypeAttr ] )
+    if( sSubTypeAttr === null )
+        sSubTypeAttr = 'default';
+    if( sSubTypeAttr && ( aTransitionSubtypeInMap[ sSubTypeAttr ] !== undefined ) )
     {
         this.eTransitionSubType = aTransitionSubtypeInMap[ sSubTypeAttr ];
         this.bIsValid = true;


More information about the Libreoffice-commits mailing list