[Libreoffice-commits] .: Branch 'feature/svg-export' - 3 commits - filter/source

Libreoffice Gerrit user logerrit at kemper.freedesktop.org
Mon Aug 20 12:18:35 PDT 2012


 filter/source/svg/presentation_engine.js |  826 ++++++++++++++++++++++++++++++-
 filter/source/svg/svgexport.cxx          |  560 +++++++++++++--------
 filter/source/svg/svgfilter.hxx          |   60 --
 filter/source/svg/svgwriter.cxx          |  527 ++++++++++++-------
 filter/source/svg/svgwriter.hxx          |   19 
 5 files changed, 1547 insertions(+), 445 deletions(-)

New commits:
commit 031cfa7e8d02580f5ab61dbc769a9447de293b1b
Author: Marco Cecchetti <mrcekets at gmail.com>
Date:   Mon Aug 20 20:22:09 2012 +0200

    some improvement in making text animation compatible with text selection

diff --git a/filter/source/svg/presentation_engine.js b/filter/source/svg/presentation_engine.js
index e3132d3..7d98d5d 100644
--- a/filter/source/svg/presentation_engine.js
+++ b/filter/source/svg/presentation_engine.js
@@ -2130,11 +2130,7 @@ initHyperlinks : function()
                     {
                         var sId = aHyperlinkIdSet[j];
                         //log( 'initHyperlinks: j=' + j + ' id: <' + sId + '>' );
-                        var aHyperlinkElem = document.getElementById( sId );
-                        if( aHyperlinkElem )
-                        {
-                            aHyperlinkSet[ sId ] = new HyperlinkElement( sId, aHyperlinkElem, this.aSlideAnimationsHandler.aEventMultiplexer );
-                        }
+                        aHyperlinkSet[ sId ] = new HyperlinkElement( sId, this.aSlideAnimationsHandler.aEventMultiplexer );
                     }
                 }
             }
@@ -8904,6 +8900,8 @@ function AnimatedElement( aElement )
         log( 'AnimatedElement constructor: element is not valid' );
     }
 
+    this.aSlideShowContext = null;
+
     this.aBaseElement = aElement.cloneNode( true );
     this.aActiveElement = aElement;
     this.sElementId = this.aActiveElement.getAttribute( 'id' );
@@ -9023,8 +9021,14 @@ AnimatedElement.prototype.setToElement = function( aElement )
     return true;
 };
 
-AnimatedElement.prototype.notifySlideStart = function()
+AnimatedElement.prototype.notifySlideStart = function( aSlideShowContext )
 {
+    if( !aSlideShowContext )
+    {
+        log( 'AnimatedElement.notifySlideStart: slideshow context is not valid' );
+    }
+    this.aSlideShowContext = aSlideShowContext;
+
     var aClone = this.aBaseElement.cloneNode( true );
     this.aActiveElement.parentNode.replaceChild( aClone, this.aActiveElement );
     this.aActiveElement = aClone;
@@ -9033,6 +9037,11 @@ AnimatedElement.prototype.notifySlideStart = function()
     this.DBG( '.notifySlideStart invoked' );
 };
 
+AnimatedElement.prototype.notifySlideEnd = function()
+{
+    // empty body
+};
+
 AnimatedElement.prototype.notifyAnimationStart = function()
 {
     // empty body
@@ -9458,7 +9467,7 @@ AnimatedElement.prototype.DBG = function( sMessage, nTime )
 };
 
 // ------------------------------------------------------------------------------------------ //
-function AnimatedTextElement( aElement )
+function AnimatedTextElement( aElement, aEventMultiplexer )
 {
     var theDocument = document;
 
@@ -9493,6 +9502,11 @@ function AnimatedTextElement( aElement )
     // Clone paragraph element <tspan>
     var aParagraphElement = aElement.cloneNode( true );
 
+    // We create a group element for wrapping bullets, bitmaps
+    // and text decoration
+    this.aGraphicGroupElement = theDocument.createElementNS( NSS['svg'], 'g' );
+    this.aGraphicGroupElement.setAttribute( 'class', 'GraphicGroup' );
+
     // In case we are dealing with a list item that utilizes a bullet char
     // we need to clone the related bullet char too.
     var aBulletCharClone = null;
@@ -9557,7 +9571,8 @@ function AnimatedTextElement( aElement )
 
     // Change clone element id.
     this.sParagraphId = sId = aParagraphElement.getAttribute( 'id' );
-    aParagraphElement.setAttribute( 'id', sId +'.a' );
+    aParagraphElement.removeAttribute( 'id' );
+    aAnimatableElement.setAttribute( 'id', sId +'.a' );
     if( aBulletCharClone )
         aBulletCharClone.removeAttribute( 'id' );
     for( i = 0; i < aBitmapCloneSet.length; ++i )
@@ -9566,56 +9581,48 @@ function AnimatedTextElement( aElement )
             aBitmapCloneSet[i].removeAttribute( 'id' );
     }
 
-    // Hide original text paragraph.
+    // Set up visibility
     var sVisibilityAttr = aElement.getAttribute( 'visibility' );
-    if( sVisibilityAttr === 'hidden' )
-    {
-        aAnimatableElement.setAttribute( 'visibility', 'hidden' );
-        this.eInitialVisibility = HIDDEN;
-    }
-    else
-    {
-        aElement.setAttribute( 'visibility', 'hidden' );
-        this.eInitialVisibility = VISIBLE;
-    }
+    if( !sVisibilityAttr )
+        sVisibilityAttr = 'inherit';
+    aAnimatableElement.setAttribute( 'visibility', sVisibilityAttr );
     aParagraphElement.setAttribute( 'visibility', 'inherit' );
-    if( aBulletCharClone )
-        aBulletCharClone.setAttribute( 'visibility', 'inherit' );
+    this.aGraphicGroupElement.setAttribute( 'visibility', 'inherit' );
     if( aBulletCharElem )
         aBulletCharElem.setAttribute( 'visibility', 'hidden' );
-
     for( i = 0; i < aBitmapCloneSet.length; ++i )
     {
         if( aBitmapElemSet[i] )
             aBitmapElemSet[i].setAttribute( 'visibility', 'hidden' );
-        if( aBitmapCloneSet[i] )
-            aBitmapCloneSet[i].setAttribute( 'visibility', 'inherit' );
     }
 
-
     // Append each element to its parent.
     // <g class='AnimatedElements'>
     //   <g>
     //     <text>
     //       <tspan class='TextParagraph'> ... </tspan>
     //     </text>
-    //     [<g class='BulletChar'>...</g>]
-    //     [<g class='EmbeddedBitmap'>...</g>]
-    //     .
-    //     .
-    //     [<g class='EmbeddedBitmap'>...</g>]
+    //     <g class='GraphicGroup'>
+    //       [<g class='BulletChar'>...</g>]
+    //       [<g class='EmbeddedBitmap'>...</g>]
+    //       .
+    //       .
+    //       [<g class='EmbeddedBitmap'>...</g>]
+    //     </g>
     //   </g>
     // </g>
 
     aTextElement.appendChild( aParagraphElement );
     aAnimatableElement.appendChild( aTextElement );
+
     if( aBulletCharClone )
-        aAnimatableElement.appendChild( aBulletCharClone );
+        this.aGraphicGroupElement.appendChild( aBulletCharClone );
     for( i = 0; i < aBitmapCloneSet.length; ++i )
     {
         if( aBitmapCloneSet[i] )
-            aAnimatableElement.appendChild( aBitmapCloneSet[i] );
+            this.aGraphicGroupElement.appendChild( aBitmapCloneSet[i] );
     }
+    aAnimatableElement.appendChild( this.aGraphicGroupElement );
     aAnimatedElementGroup.appendChild( aAnimatableElement );
 
     this.aParentTextElement = aElement.parentNode;
@@ -9623,32 +9630,81 @@ function AnimatedTextElement( aElement )
     this.aAnimatedElementGroup = aAnimatedElementGroup;
     this.nRunningAnimations = 0;
 
-    AnimatedTextElement.superclass.constructor.call( this, aAnimatableElement );
+    // we collect all hyperlink ids
+    this.aHyperlinkIdSet = new Array();
+    var aHyperlinkElementSet = getElementsByClassName( this.aParagraphElement, 'UrlField' );
+    var i = 0;
+    var sHyperlinkId;
+    for( ; i < aHyperlinkElementSet.length; ++i )
+    {
+        sHyperlinkId = aHyperlinkElementSet[i].getAttribute( 'id' );
+        if( sHyperlinkId )
+           this.aHyperlinkIdSet.push( sHyperlinkId );
+        else
+            log( 'error: AnimatedTextElement constructor: hyperlink element has no id' );
+    }
+
+
+    AnimatedTextElement.superclass.constructor.call( this, aAnimatableElement, aEventMultiplexer );
 
 }
 extend( AnimatedTextElement, AnimatedElement );
 
-/*
-AnimatedTextElement.prototype.notifySlideStart = function()
-{
-    var aClone = this.aBaseElement.cloneNode( true );
-    this.aActiveElement.parentNode.replaceChild( aClone, this.aActiveElement );
-    this.aActiveElement = aClone;
 
-    var aAnimatedParagraphElement = this.aActiveElement.firstElementChild.firstElementChild;
-    if( aAnimatedParagraphElement )
+AnimatedTextElement.prototype.setToElement = function( aElement )
+{
+    var bRet = AnimatedTextElement.superclass.setToElement.call( this, aElement );
+    if( bRet )
     {
-        var aParagraphElement = aAnimatedParagraphElement.cloneNode( true );
-        aParagraphElement.setAttribute( 'id', this.sParagraphId );
-        aParagraphElement.setAttribute( 'visibility', aVisibilityAttributeValue[ this.eInitialVisibility  ] );
-        this.aParentTextElement.replaceChild( aParagraphElement, this.aParagraphElement  );
-        this.aParagraphElement = aParagraphElement;
+        this.aGraphicGroupElement = getElementByClassName( this.aActiveElement, 'GraphicGroup' );
     }
-    this.aActiveElement.setAttribute( 'visibility', 'hidden' );
+    return ( bRet && this.aGraphicGroupElement );
+};
 
+AnimatedTextElement.prototype.notifySlideStart = function( aSlideShowContext )
+{
+    log( 'AnimatedTextElement.notifySlideStart' );
+    AnimatedTextElement.superclass.notifySlideStart.call( this, aSlideShowContext );
+    this.aGraphicGroupElement = getElementByClassName( this.aActiveElement, 'GraphicGroup' );
+    this.restoreBaseTextParagraph();
+};
 
-    this.initElement();
-    this.DBG( '.notifySlideStart invoked' );
+AnimatedTextElement.prototype.notifySlideEnd = function()
+{
+    log( 'AnimatedTextElement.notifySlideEnd' );
+    this.aGraphicGroupElement.setAttribute( 'visibility', 'inherit' );
+};
+
+AnimatedTextElement.prototype.restoreBaseTextParagraph = function()
+{
+    var aActiveParagraphElement = this.aActiveElement.firstElementChild.firstElementChild;
+    if( aActiveParagraphElement )
+    {
+        var sVisibilityAttr = this.aActiveElement.getAttribute( 'visibility' );
+        if( !sVisibilityAttr || ( sVisibilityAttr === 'visible' ) )
+            sVisibilityAttr = 'inherit';
+        if( sVisibilityAttr === 'inherit' )
+            this.aGraphicGroupElement.setAttribute( 'visibility', 'visible' );
+        else
+            this.aGraphicGroupElement.setAttribute( 'visibility', 'hidden' );
+
+        var aParagraphClone = aActiveParagraphElement.cloneNode( true );
+        aParagraphClone.setAttribute( 'id', this.sParagraphId );
+        aParagraphClone.setAttribute( 'visibility', sVisibilityAttr );
+        this.aParentTextElement.replaceChild( aParagraphClone, this.aParagraphElement );
+        this.aParagraphElement = aParagraphClone;
+
+
+        var aEventMultiplexer = this.aSlideShowContext.aEventMultiplexer;
+        var aHyperlinkIdSet = this.aHyperlinkIdSet;
+        var aHyperlinkElementSet = getElementsByClassName( this.aParagraphElement, 'UrlField' );
+        var i = 0;
+        for( ; i < aHyperlinkIdSet.length; ++i )
+        {
+            aEventMultiplexer.notifyElementChangedEvent( aHyperlinkIdSet[i], aHyperlinkElementSet[i] );
+        }
+    }
+    this.aActiveElement.setAttribute( 'visibility', 'hidden' );
 };
 
 AnimatedTextElement.prototype.notifyAnimationStart = function()
@@ -9656,8 +9712,12 @@ AnimatedTextElement.prototype.notifyAnimationStart = function()
     log( 'AnimatedTextElement.notifyAnimationStart' );
     if( this.nRunningAnimations === 0 )
     {
+        var sVisibilityAttr = this.aParagraphElement.getAttribute( 'visibility' );
+        if( !sVisibilityAttr )
+            sVisibilityAttr = 'inherit';
+        this.aActiveElement.setAttribute( 'visibility', sVisibilityAttr );
+        this.aGraphicGroupElement.setAttribute( 'visibility', 'inherit' );
         this.aParagraphElement.setAttribute( 'visibility', 'hidden' );
-        this.aActiveElement.setAttribute( 'visibility', aVisibilityAttributeValue[ this.eInitialVisibility  ] );
     }
     ++this.nRunningAnimations;
 };
@@ -9668,20 +9728,29 @@ AnimatedTextElement.prototype.notifyAnimationEnd = function()
     --this.nRunningAnimations;
     if( this.nRunningAnimations === 0 )
     {
-        var sVisibilityAttr = this.aActiveElement.getAttribute( 'visibility' );
-        var aAnimatedParagraphElement = this.aActiveElement.firstElementChild.firstElementChild;
-        if( aAnimatedParagraphElement )
-        {
-            var aParagraphElement = aAnimatedParagraphElement.cloneNode( true );
-            aParagraphElement.setAttribute( 'visibility', sVisibilityAttr );
-            aParagraphElement.setAttribute( 'id', this.sParagraphId );
-            this.aParentTextElement.replaceChild( aParagraphElement, this.aParagraphElement  );
-            this.aParagraphElement = aParagraphElement;
-        }
-        this.aActiveElement.setAttribute( 'visibility', 'hidden' );
+        this.restoreBaseTextParagraph();
     }
 };
-*/
+
+AnimatedTextElement.prototype.saveState = function( nAnimationNodeId )
+{
+    if( this.nRunningAnimations === 0 )
+    {
+        var sVisibilityAttr = this.aParagraphElement.getAttribute( 'visibility' );
+        this.aActiveElement.setAttribute( 'visibility', sVisibilityAttr );
+        this.aGraphicGroupElement.setAttribute( 'visibility', 'inherit' );
+    }
+    AnimatedTextElement.superclass.saveState.call( this, nAnimationNodeId );
+};
+
+AnimatedTextElement.prototype.restoreState = function( nAnimationNodeId )
+{
+    var bRet = AnimatedTextElement.superclass.restoreState.call( this, nAnimationNodeId );
+    if( bRet )
+        this.restoreBaseTextParagraph();
+    return bRet;
+};
+
 
 
 // ------------------------------------------------------------------------------------------ //
@@ -10406,17 +10475,17 @@ SourceEventElement.prototype.setDefaultCursor = function()
 
 // ------------------------------------------------------------------------------------------ //
 
-function HyperlinkElement( sId, aElement, aEventMultiplexer )
+function HyperlinkElement( sId, aEventMultiplexer )
 {
+    var aElement = document.getElementById( sId );
     if( !aElement )
     {
-        log( 'error: HyperlinkElement: passed element is not valid' );
+        log( 'error: HyperlinkElement: no element with id: <' + sId + '> found' );
         return;
     }
     if( !aEventMultiplexer )
     {
-        log( 'error: HyperlinkElement: passed event multiplexer is not valid' );
-        return;
+        log( 'AnimatedElement constructor: event multiplexer is not valid' );
     }
 
     this.sId = sId;
@@ -10436,11 +10505,14 @@ function HyperlinkElement( sId, aElement, aEventMultiplexer )
             }
         }
 
+        this.aEventMultiplexer.registerElementChangedHandler( this.sId, bind2( HyperlinkElement.prototype.onElementChanged, this) );
         this.aEventMultiplexer.registerMouseClickHandler( this, 1100 );
 
         this.bIsPointerOver = false;
-        this.aElement.addEventListener( 'mouseover', bind2( HyperlinkElement.prototype.onMouseEnter, this), false );
-        this.aElement.addEventListener( 'mouseout', bind2( HyperlinkElement.prototype.onMouseLeave, this), false );
+        this.mouseEnterHandler = bind2( HyperlinkElement.prototype.onMouseEnter, this);
+        this.mouseLeaveHandler = bind2( HyperlinkElement.prototype.onMouseLeave, this);
+        this.aElement.addEventListener( 'mouseover', this.mouseEnterHandler, false );
+        this.aElement.addEventListener( 'mouseout', this.mouseLeaveHandler, false );
     }
     else
     {
@@ -10448,6 +10520,25 @@ function HyperlinkElement( sId, aElement, aEventMultiplexer )
     }
 }
 
+HyperlinkElement.prototype.onElementChanged = function( aElement )
+{
+    //var aElement = document.getElementById( this.sId );
+    if( !aElement )
+    {
+        log( 'error: HyperlinkElement: passed element is not valid' );
+        return;
+    }
+
+    if( this.sURL )
+    {
+        this.aElement.removeEventListener( 'mouseover', this.mouseEnterHandler, false );
+        this.aElement.removeEventListener( 'mouseout', this.mouseLeaveHandler, false );
+        this.aElement = aElement;
+        this.aElement.addEventListener( 'mouseover', this.mouseEnterHandler, false );
+        this.aElement.addEventListener( 'mouseout', this.mouseLeaveHandler, false );
+    }
+};
+
 HyperlinkElement.prototype.onMouseEnter = function()
 {
     this.bIsPointerOver = true;
@@ -10607,6 +10698,7 @@ function EventMultiplexer( aTimerEventQueue )
     this.aRewindRunningInteractiveEffectEventSet = new Object();
     this.aRewindEndedInteractiveEffectEventSet = new Object();
     this.aRewindedEffectHandlerSet = new Object();
+    this.aElementChangedHandlerSet = new Object();
 }
 
 EventMultiplexer.CURR_UNIQUE_ID = 0;
@@ -10787,6 +10879,18 @@ EventMultiplexer.prototype.notifyRewindedEffectEvent = function( aNotifierId )
     }
 };
 
+EventMultiplexer.prototype.registerElementChangedHandler = function( aNotifierId, aHandler )
+{
+    this.aElementChangedHandlerSet[ aNotifierId ] = aHandler;
+}
+
+EventMultiplexer.prototype.notifyElementChangedEvent = function( aNotifierId, aElement )
+{
+    if( this.aElementChangedHandlerSet[ aNotifierId ] )
+    {
+        (this.aElementChangedHandlerSet[ aNotifierId ])( aElement );
+    }
+};
 
 EventMultiplexer.DEBUG = aEventMultiplexerDebugPrinter.isEnabled();
 
@@ -12427,7 +12531,7 @@ SlideShow.prototype.notifyNextEffectEnd = function()
     this.aStartedEffectList[ this.aStartedEffectIndexMap[ -1 ] ].end();
 };
 
-SlideShow.prototype.notifySlideStart = function( nSlideIndex )
+SlideShow.prototype.notifySlideStart = function( nNewSlideIndex, nOldSlideIndex )
 {
     this.nCurrentEffect = 0;
     this.bIsRewinding = false;
@@ -12438,10 +12542,18 @@ SlideShow.prototype.notifySlideStart = function( nSlideIndex )
     this.aStartedEffectIndexMap = new Object();
     this.aStartedEffectIndexMap[ -1 ] = undefined;
 
+    var aAnimatedElementMap;
+    var sId;
+    if( nOldSlideIndex !== undefined )
+    {
+        aAnimatedElementMap = theMetaDoc.aMetaSlideSet[nOldSlideIndex].aSlideAnimationsHandler.aAnimatedElementMap;
+        for( sId in aAnimatedElementMap )
+            aAnimatedElementMap[ sId ].notifySlideEnd();
+    }
 
-    var aAnimatedElementMap = theMetaDoc.aMetaSlideSet[nSlideIndex].aSlideAnimationsHandler.aAnimatedElementMap;
-    for( var sId in aAnimatedElementMap )
-        aAnimatedElementMap[ sId ].notifySlideStart();
+    aAnimatedElementMap = theMetaDoc.aMetaSlideSet[nNewSlideIndex].aSlideAnimationsHandler.aAnimatedElementMap;
+    for( sId in aAnimatedElementMap )
+        aAnimatedElementMap[ sId ].notifySlideStart( this.aContext );
 };
 
 SlideShow.prototype.notifyTransitionEnd = function( nSlideIndex )
@@ -12792,7 +12904,7 @@ SlideShow.prototype.displaySlide = function( nNewSlide, bSkipSlideTransition )
         }
     }
 
-    this.notifySlideStart( nNewSlide );
+    this.notifySlideStart( nNewSlide, nOldSlide );
 
     if( this.isEnabled() && !bSkipSlideTransition  )
     {
diff --git a/filter/source/svg/svgexport.cxx b/filter/source/svg/svgexport.cxx
index 38cad60..8f8d727 100644
--- a/filter/source/svg/svgexport.cxx
+++ b/filter/source/svg/svgexport.cxx
@@ -1749,6 +1749,42 @@ sal_Bool SVGFilter::implExportShape( const Reference< XShape >& rxShape )
                 {   // for text field shapes we set up text-adjust attributes
                     // and set visibility to hidden
                     OUString aShapeClass = implGetClassFromShape( rxShape );
+
+
+
+                    {
+//                        Reference< XPropertySetInfo > xPropSetInfo = xShapePropSet->getPropertySetInfo();
+//                        Sequence< Property > aPropSeq = xPropSetInfo->getProperties();
+//                        sal_Int32 nLength = aPropSeq.getLength();
+//                        OUString sGraphicPropList;
+//                        for( sal_Int32 i = 0; i < nLength; ++i )
+//                        {
+//                            sGraphicPropList += aPropSeq[i].Name;
+//                            sGraphicPropList += B2UCONST( ": " );
+//                            sGraphicPropList += aPropSeq[i].Type.getTypeName();
+//                            sGraphicPropList += B2UCONST( "; " );
+//                        }
+//                        mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "class", B2UCONST( "Graphic" ) );
+//                        mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "property-list", sGraphicPropList );
+//                        SvXMLElementExport aExp2( *mpSVGExport, XML_NAMESPACE_NONE, "desc", sal_True, sal_True );
+
+//                        if( xPropSetInfo->hasPropertyByName( B2UCONST( "GraphicURL" ) ) )
+//                        {
+//                            OUString sGraphicURL;
+//                            if( xShapePropSet->getPropertyValue( B2UCONST( "GraphicURL" ) ) >>= sGraphicURL )
+//                            {
+//                                if( !sGraphicURL.isEmpty() )
+//                                {
+//                                    mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "class", B2UCONST( "GraphicURL" ) );
+//                                    mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "xlink:ref", sGraphicURL );
+//                                    SvXMLElementExport aExp2( *mpSVGExport, XML_NAMESPACE_NONE, "desc", sal_True, sal_True );
+//                                }
+//                            }
+//                        }
+                    }
+
+
+
                     if( mbPresentation )
                     {
                         sal_Bool bIsPageNumber  = ( aShapeClass == "Slide_Number" );
diff --git a/filter/source/svg/svgfilter.hxx b/filter/source/svg/svgfilter.hxx
index acb0ac0..8459f11 100644
--- a/filter/source/svg/svgfilter.hxx
+++ b/filter/source/svg/svgfilter.hxx
@@ -29,6 +29,7 @@
 #ifndef SVGFILTER_HXX
 #define SVGFILTER_HXX
 
+#include <com/sun/star/uno/Type.hxx>
 #include <com/sun/star/animations/XAnimationNodeSupplier.hpp>
 #include <com/sun/star/drawing/XMasterPageTarget.hpp>
 #include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
diff --git a/filter/source/svg/svgwriter.cxx b/filter/source/svg/svgwriter.cxx
index 2575bfe..d13ac78 100644
--- a/filter/source/svg/svgwriter.cxx
+++ b/filter/source/svg/svgwriter.cxx
@@ -1171,6 +1171,10 @@ sal_Bool SVGTextWriter::nextTextPortion()
                         sInfo += sFieldName;
                         sInfo += B2UCONST( "; " );
 
+                        sInfo += B2UCONST( "content: " );
+                        sInfo += xTextField->getPresentation( /* show command: */ sal_False );
+                        sInfo += B2UCONST( "; " );
+
                         if( sFieldName.equalsAscii( "DateTime" ) || sFieldName.equalsAscii( "Header" )
                                 || sFieldName.equalsAscii( "Footer" ) || sFieldName.equalsAscii( "PageNumber" ) )
                         {
@@ -1562,6 +1566,14 @@ void SVGTextWriter::writeTextPortion( const Point& rPos,
                     else
                     {
                         sContent = mrCurrentTextPortion->getString();
+                        if( mbIsURLField && sContent.isEmpty() )
+                        {
+                            Reference < XPropertySet > xPropSet( mrCurrentTextPortion, UNO_QUERY );
+                            Reference < XTextField > xTextField( xPropSet->getPropertyValue( B2UCONST( "TextField" ) ), UNO_QUERY );
+                            sContent = xTextField->getPresentation( /* show command: */ sal_False );
+                            if( sContent.isEmpty() )
+                                OSL_FAIL( "SVGTextWriter::writeTextPortion: content of URL TextField is empty." );
+                        }
                         mnLeftTextPortionLength = sContent.getLength();
                     }
                 }
@@ -1769,6 +1781,7 @@ void SVGTextWriter::implWriteTextPortion( const Point& rPos,
     }
     else if( mbIsURLField && !msUrl.isEmpty() )
     {
+        mrExport.AddAttribute( XML_NAMESPACE_NONE, "class", B2UCONST( "UrlField" ) );
         mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrXLinkHRef, msUrl );
         mbIsURLField = sal_False;
     }
commit 0c967e15b9c6253067cb04e9299852899adf1f38
Author: Marco Cecchetti <mrcekets at gmail.com>
Date:   Sat Aug 18 19:25:17 2012 +0200

    Handled META_BMPSCALE_ACTION, supported hyperlinks, text selection support.
    
    The implCreateObjectFromShape method of the SVGFilter class has been modified in order
    to handling bitmap meta actions of type META_BMPSCALE_ACTION for each bitmap
    embedded into a text shape.
    
    The implCreateObjectFromShape method of the SVGFilter class has been modified in order
    to avoid to generate an id for empty text shapes.
    
    The MetaSlide class has two new methods for collecting text shapes from the text shape
    exported index and hyperlinks. A new HyperlinkElement class has been designed for
    handling text portion with an attached URL. The routine handling mouse click has been
    modified in order to interacting with the EventMultiplexer instance belonging to the current
    slide even when no animations are exported. All that let us supporting both web links and
    local links to slide belonging to the current document.
    
    The routine handling mouse click has been modified in order to avoid to start the next effect
    or switch to the next slide when there is a text fragment selected.
    
    Now when the user selects text or performs a right click in order to copy the selected text no
    further action is executed by the presentation engine. When the left mouse button is clicked
    the previous selection is discarded but still no further action is performed by the presentation
    engine.
    
    The implCreateObjectFromShape method of the SVGFilter class has been modified in order
    to avoid of adding to the group of embedded bitmaps those bitmap belonging to XShape
    object convertible to XText but that does not contain any text shape meta comment action.
    Now a meta bitmap action is handled by the SVGTextWriter class only if the action is between
    a meta comment action of type XTEXT_PAINTSHAPE_BEGIN and a meta comment action of
    type XTEXT_PAINTSHAPE_END.
    
    The writeBitmapPlaceholder and implWriteEmbeddedBitmaps methods of the SVGTextWriter
    class have been modified in order to change the way the id of the <use> elements that
    reference a bitmap is created. That has been needed because when two <use> element
    referencing the same bitmap and embedded into two different text shapes but placed at the
    same position (e.g. for instance when they belong to different slide)  they got the same id.
    Now the id is built by prepending the meta bitmap action checksum with the text shape id
    followed by a dot.

diff --git a/filter/source/svg/presentation_engine.js b/filter/source/svg/presentation_engine.js
index 35a4998..e3132d3 100644
--- a/filter/source/svg/presentation_engine.js
+++ b/filter/source/svg/presentation_engine.js
@@ -316,6 +316,72 @@ function mouseHandlerDispatch( aEvt, anAction )
 document.onmouseup = function( aEvt ) { return mouseHandlerDispatch( aEvt, MOUSE_UP ); };
 //document.onmousemove = function( aEvt ) { return mouseHandlerDispatch( aEvt, MOUSE_MOVE ); };
 
+
+/** mouseClickHelper
+ *
+ * @return {Object}
+ *   a mouse click handler
+ */
+function mouseClickHelper( aEvt )
+{
+    // In case text is selected we stay on the current slide.
+    // Anyway if we are dealing with Firefox there is an issue:
+    // Firefox supports a naive way of selecting svg text, if you click
+    // on text the current selection is set to the whole text fragment
+    // wrapped by the related <tspan> element.
+    // That means until you click on text you never move to the next slide.
+    // In order to avoid this case we do not test the status of current
+    // selection, when the presentation is running on a mozilla browser.
+    if( !Detect.isMozilla )
+    {
+        var aWindowObject = document.defaultView;
+        if( aWindowObject )
+        {
+            var aTextSelection = aWindowObject.getSelection();
+            var sSelectedText =  aTextSelection.toString();
+            if( sSelectedText )
+            {
+                log( 'text selection: ' + sSelectedText );
+                if( sLastSelectedText !== sSelectedText )
+                {
+                    bTextHasBeenSelected = true;
+                    sLastSelectedText = sSelectedText;
+                }
+                else
+                {
+                    bTextHasBeenSelected = false;
+                }
+                return null;
+            }
+            else if( bTextHasBeenSelected )
+            {
+                bTextHasBeenSelected = false;
+                sLastSelectedText = '';
+                return null;
+            }
+        }
+        else
+        {
+            log( 'error: HyperlinkElement.handleClick: invalid window object.' );
+        }
+    }
+
+    var aSlideAnimationsHandler = theMetaDoc.aMetaSlideSet[nCurSlide].aSlideAnimationsHandler;
+    if( aSlideAnimationsHandler )
+    {
+        var aCurrentEventMultiplexer = aSlideAnimationsHandler.aEventMultiplexer;
+        if( aCurrentEventMultiplexer )
+        {
+            if( aCurrentEventMultiplexer.hasRegisteredMouseClickHandlers() )
+            {
+                return aCurrentEventMultiplexer.notifyMouseClick( aEvt );
+            }
+        }
+    }
+    return slideOnMouseUp( aEvt );
+}
+
+
 /** Function to supply the default mouse handler dictionary.
  *
  *  @returns default mouse handler dictionary
@@ -329,10 +395,11 @@ function getDefaultMouseHandlerDictionary()
 
     // slide mode
     mouseHandlerDict[SLIDE_MODE][MOUSE_UP]
+        = mouseClickHelper;
         //= function( aEvt ) { return slideOnMouseDown( aEvt ); };
-        = function( aEvt ) { return ( aSlideShow.aEventMultiplexer ) ?
-                                        aSlideShow.aEventMultiplexer.notifyMouseClick( aEvt )
-                                        : slideOnMouseUp( aEvt ); };
+//        = function( aEvt ) { return ( aSlideShow.aEventMultiplexer ) ?
+//                                        aSlideShow.aEventMultiplexer.notifyMouseClick( aEvt )
+//                                        : slideOnMouseUp( aEvt ); };
 
     mouseHandlerDict[SLIDE_MODE][MOUSE_WHEEL]
         = function( aEvt ) { return slideOnMouseWheel( aEvt ); };
@@ -615,6 +682,152 @@ PathTools.arcAsBezier = function( last, rx, ry, xRotg, large, sweep, x, y )
 };
 
 
+function has( name )
+{
+    return has.cache[name];
+}
+
+has.cache = {};
+
+has.add = function( name, test )
+{
+    has.cache[name] = test;
+};
+
+function configureDetectionTools()
+{
+    if( !navigator )
+    {
+        log( 'error: configureDetectionTools: configuration failed' );
+        return null;
+    }
+
+    var n = navigator,
+    dua = n.userAgent,
+    dav = n.appVersion,
+    tv = parseFloat(dav);
+
+    has.add('air', dua.indexOf('AdobeAIR') >= 0),
+    has.add('khtml', dav.indexOf('Konqueror') >= 0 ? tv : undefined);
+    has.add('webkit', parseFloat(dua.split('WebKit/')[1]) || undefined);
+    has.add('chrome', parseFloat(dua.split('Chrome/')[1]) || undefined);
+    has.add('safari', dav.indexOf('Safari')>=0 && !has('chrome') ? parseFloat(dav.split('Version/')[1]) : undefined);
+    has.add('mac', dav.indexOf('Macintosh') >= 0);
+    has.add('quirks', document.compatMode == 'BackCompat');
+    has.add('ios', /iPhone|iPod|iPad/.test(dua));
+    has.add('android', parseFloat(dua.split('Android ')[1]) || undefined);
+
+    if(!has('webkit')){
+        // Opera
+        if(dua.indexOf('Opera') >= 0){
+            // see http://dev.opera.com/articles/view/opera-ua-string-changes and http://www.useragentstring.com/pages/Opera/
+            // 9.8 has both styles; <9.8, 9.9 only old style
+            has.add('opera', tv >= 9.8 ? parseFloat(dua.split('Version/')[1]) || tv : tv);
+        }
+
+        // Mozilla and firefox
+        if(dua.indexOf('Gecko') >= 0 && !has('khtml') && !has('webkit')){
+            has.add('mozilla', tv);
+        }
+        if(has('mozilla')){
+            //We really need to get away from this. Consider a sane isGecko approach for the future.
+            has.add('ff', parseFloat(dua.split('Firefox/')[1] || dua.split('Minefield/')[1]) || undefined);
+        }
+
+        // IE
+        if(document.all && !has('opera')){
+            var isIE = parseFloat(dav.split('MSIE ')[1]) || undefined;
+
+            //In cases where the page has an HTTP header or META tag with
+            //X-UA-Compatible, then it is in emulation mode.
+            //Make sure isIE reflects the desired version.
+            //document.documentMode of 5 means quirks mode.
+            //Only switch the value if documentMode's major version
+            //is different from isIE's major version.
+            var mode = document.documentMode;
+            if(mode && mode != 5 && Math.floor(isIE) != mode){
+                isIE = mode;
+            }
+
+            has.add('ie', isIE);
+        }
+
+        // Wii
+        has.add('wii', typeof opera != 'undefined' && opera.wiiremote);
+    }
+
+    var detect =
+    {
+		// isFF: Number|undefined
+		//		Version as a Number if client is FireFox. undefined otherwise. Corresponds to
+		//		major detected FireFox version (1.5, 2, 3, etc.)
+		isFF: has('ff'),
+
+		// isIE: Number|undefined
+		//		Version as a Number if client is MSIE(PC). undefined otherwise. Corresponds to
+		//		major detected IE version (6, 7, 8, etc.)
+		isIE: has('ie'),
+
+		// isKhtml: Number|undefined
+		//		Version as a Number if client is a KHTML browser. undefined otherwise. Corresponds to major
+		//		detected version.
+		isKhtml: has('khtml'),
+
+		// isWebKit: Number|undefined
+		//		Version as a Number if client is a WebKit-derived browser (Konqueror,
+		//		Safari, Chrome, etc.). undefined otherwise.
+		isWebKit: has('webkit'),
+
+		// isMozilla: Number|undefined
+		//		Version as a Number if client is a Mozilla-based browser (Firefox,
+		//		SeaMonkey). undefined otherwise. Corresponds to major detected version.
+		isMozilla: has('mozilla'),
+		// isMoz: Number|undefined
+		//		Version as a Number if client is a Mozilla-based browser (Firefox,
+		//		SeaMonkey). undefined otherwise. Corresponds to major detected version.
+		isMoz: has('mozilla'),
+
+		// isOpera: Number|undefined
+		//		Version as a Number if client is Opera. undefined otherwise. Corresponds to
+		//		major detected version.
+		isOpera: has('opera'),
+
+		// isSafari: Number|undefined
+		//		Version as a Number if client is Safari or iPhone. undefined otherwise.
+		isSafari: has('safari'),
+
+		// isChrome: Number|undefined
+		//		Version as a Number if client is Chrome browser. undefined otherwise.
+		isChrome: has('chrome'),
+
+		// isMac: Boolean
+		//		True if the client runs on Mac
+		isMac: has('mac'),
+
+		// isIos: Boolean
+		//		True if client is iPhone, iPod, or iPad
+		isIos: has('ios'),
+
+		// isAndroid: Number|undefined
+		//		Version as a Number if client is android browser. undefined otherwise.
+		isAndroid: has('android'),
+
+		// isWii: Boolean
+		//		True if client is Wii
+		isWii: has('wii'),
+
+		// isQuirks: Boolean
+		//		Page is in quirks mode.
+		isQuirks: has('quirks'),
+
+		// isAir: Boolean
+		//		True if client is Adobe Air
+		isAir: has('air')
+    };
+    return detect;
+}
+
+
 
 /*****
  * @dojoend
@@ -937,6 +1150,24 @@ function PriorityQueue( aCompareFunc )
     this.aCompareFunc = aCompareFunc;
 }
 
+PriorityQueue.prototype.clone = function()
+{
+    var aCopy = new PriorityQueue( this.aCompareFunc );
+    var src = this.aSequence;
+    var dest = [];
+    var i, l;
+    for( i = 0, l = src.length; i < l; ++i )
+    {
+        if( i in src )
+        {
+            dest.push( src[i] );
+        }
+    }
+    aCopy.aSequence = dest;
+
+    return aCopy;
+};
+
 PriorityQueue.prototype.top = function()
 {
     return this.aSequence[0];
@@ -1171,11 +1402,15 @@ var INDEX_COLUMNS_DEFAULT = 3;
 var INDEX_OFFSET = 0;
 
 // Initialization.
+var Detect = configureDetectionTools();
 var theMetaDoc;
 var theSlideIndexPage;
 var currentMode = SLIDE_MODE;
 var processingEffect = false;
 var nCurSlide = undefined;
+var bTextHasBeenSelected = false;
+var sLastSelectedText = '';
+
 
 // Initialize char and key code dictionaries.
 var charCodeDictionary = getDefaultCharCodeDictionary();
@@ -1240,6 +1475,7 @@ function instantiate( TemplateClass, BaseType )
     return TemplateClass.instanceSet[ nSize ].instance;
 }
 
+
 // ------------------------------------------------------------------------------------------ //
 /**********************************
  ** Helper functions and classes **
@@ -1284,11 +1520,19 @@ function warning( bCondition, sMessage )
 function getNSAttribute( sNSPrefix, aElem, sAttrName )
 {
     if( !aElem ) return null;
-    if( aElem.hasAttributeNS( NSS[sNSPrefix], sAttrName ) )
+    if( 'getAttributeNS' in aElem )
     {
         return aElem.getAttributeNS( NSS[sNSPrefix], sAttrName );
     }
-    return null;
+    else
+    {
+        return aElem.getAttribute( sNSPrefix + ':' + sAttrName );
+    }
+//    if( aElem.hasAttributeNS( NSS[sNSPrefix], sAttrName ) )
+//    {
+//        return aElem.getAttributeNS( NSS[sNSPrefix], sAttrName );
+//    }
+//    return null;
 }
 
 function getOOOAttribute( aElem, sAttrName )
@@ -1691,6 +1935,12 @@ function MetaSlide( sMetaSlideId, aMetaDoc )
     if( false && this.aSlideAnimationsHandler.aRootNode )
         log( this.aSlideAnimationsHandler.aRootNode.info( true ) );
 
+    // We collect text shapes included in this slide .
+    this.aTextShapeSet = this.collectTextShapes();
+
+    // We initialize hyperlinks
+    this.aHyperlinkSet = this.initHyperlinks();
+
 }
 
 MetaSlide.prototype =
@@ -1821,6 +2071,78 @@ initFixedTextFieldContentProvider : function( aOOOAttribute )
     return this.theMetaDoc.aTextFieldContentProviderSet[ nIndex ];
 },
 
+collectTextShapes : function()
+{
+    var aTextShapeSet = new Array();
+    var aTextShapeIndexElem = getElementByClassName( document, 'TextShapeIndex' );
+    if( aTextShapeIndexElem )
+    {
+        var aIndexEntryList = getElementChildren( aTextShapeIndexElem );
+        var i;
+        for( i = 0; i < aIndexEntryList.length; ++i )
+        {
+            var sSlideId = getOOOAttribute( aIndexEntryList[i], 'slide' );
+            if( sSlideId === this.slideId )
+            {
+                var sTextShapeIds = getOOOAttribute( aIndexEntryList[i], 'id-list' );
+                if( sTextShapeIds )
+                {
+                    //log( 'slide id: ' + this.slideId + ' text shape id list: ' + sTextShapeIds );
+                    var aTextShapeIdSet =  sTextShapeIds.split( ' ' );
+                    var j;
+                    for( j = 0; j < aTextShapeIdSet.length; ++j )
+                    {
+                        var aTextShapeElem = document.getElementById( aTextShapeIdSet[j] );
+                        if( aTextShapeElem )
+                        {
+                            aTextShapeSet.push( aTextShapeElem );
+                        }
+                        else
+                        {
+                            log( 'warning: MetaSlide.collectTextShapes: text shape with id <' + aTextShapeIdSet[j] + '> is not valid.'  );
+                        }
+                    }
+                }
+                break;
+            }
+        }
+    }
+    return aTextShapeSet;
+},
+
+initHyperlinks : function()
+{
+    var aHyperlinkSet = new Object();
+    var i;
+    for( i = 0; i < this.aTextShapeSet.length; ++i )
+    {
+        if( this.aTextShapeSet[i] )
+        {
+            var aHyperlinkIdList = getElementByClassName( this.aTextShapeSet[i], 'HyperlinkIdList' );
+            if( aHyperlinkIdList )
+            {
+                var sHyperlinkIds = aHyperlinkIdList.textContent;
+                if( sHyperlinkIds )
+                {
+                    var aHyperlinkIdSet = sHyperlinkIds.trim().split( ' ' );
+                    var j;
+                    for( j = 0; j < aHyperlinkIdSet.length; ++j )
+                    {
+                        var sId = aHyperlinkIdSet[j];
+                        //log( 'initHyperlinks: j=' + j + ' id: <' + sId + '>' );
+                        var aHyperlinkElem = document.getElementById( sId );
+                        if( aHyperlinkElem )
+                        {
+                            aHyperlinkSet[ sId ] = new HyperlinkElement( sId, aHyperlinkElem, this.aSlideAnimationsHandler.aEventMultiplexer );
+                        }
+                    }
+                }
+            }
+        }
+    }
+    return aHyperlinkSet;
+},
+
 getSlideAnimationsRoot : function()
 {
     return this.theMetaDoc.aSlideAnimationsMap[ this.slideId ];
@@ -9208,6 +9530,7 @@ function AnimatedTextElement( aElement )
         }
     }
 
+    // In case there are embedded bitmaps we need to clone them
     var aBitmapElemSet = new Array();
     var aBitmapCloneSet = new Array();
     var aBitmapPlaceholderSet = getElementsByClassName( aElement, 'BitmapPlaceholder' );
@@ -9260,6 +9583,7 @@ function AnimatedTextElement( aElement )
         aBulletCharClone.setAttribute( 'visibility', 'inherit' );
     if( aBulletCharElem )
         aBulletCharElem.setAttribute( 'visibility', 'hidden' );
+
     for( i = 0; i < aBitmapCloneSet.length; ++i )
     {
         if( aBitmapElemSet[i] )
@@ -10080,6 +10404,102 @@ SourceEventElement.prototype.setDefaultCursor = function()
     this.aElement.setAttribute( 'style', 'cursor: default' );
 };
 
+// ------------------------------------------------------------------------------------------ //
+
+function HyperlinkElement( sId, aElement, aEventMultiplexer )
+{
+    if( !aElement )
+    {
+        log( 'error: HyperlinkElement: passed element is not valid' );
+        return;
+    }
+    if( !aEventMultiplexer )
+    {
+        log( 'error: HyperlinkElement: passed event multiplexer is not valid' );
+        return;
+    }
+
+    this.sId = sId;
+    this.aElement = aElement;
+    this.aEventMultiplexer = aEventMultiplexer;
+    this.nTargetSlideIndex = undefined;
+
+    this.sURL = getNSAttribute( 'xlink', this.aElement, 'href' );
+    if( this.sURL )
+    {
+        if( this.sURL[0] === '#' )
+        {
+            if( this.sURL.substr(1, 5) === 'Slide' )
+            {
+                var sSlideIndex = this.sURL.split( ' ' )[1];
+                this.nTargetSlideIndex = parseInt( sSlideIndex ) - 1;
+            }
+        }
+
+        this.aEventMultiplexer.registerMouseClickHandler( this, 1100 );
+
+        this.bIsPointerOver = false;
+        this.aElement.addEventListener( 'mouseover', bind2( HyperlinkElement.prototype.onMouseEnter, this), false );
+        this.aElement.addEventListener( 'mouseout', bind2( HyperlinkElement.prototype.onMouseLeave, this), false );
+    }
+    else
+    {
+        log( 'warning: HyperlinkElement(' + this.sId + '): url is empty' );
+    }
+}
+
+HyperlinkElement.prototype.onMouseEnter = function()
+{
+    this.bIsPointerOver = true;
+    this.setPointerCursor();
+};
+
+HyperlinkElement.prototype.onMouseLeave = function()
+{
+    this.bIsPointerOver = false;
+    this.setDefaultCursor();
+};
+
+HyperlinkElement.prototype.handleClick = function( aMouseEvent )
+{
+    if( !this.bIsPointerOver ) return false;
+
+    //log( 'hyperlink: ' + this.sURL );
+
+    if( this.nTargetSlideIndex !== undefined )
+    {
+        aSlideShow.displaySlide( this.nTargetSlideIndex, true );
+    }
+    else
+    {
+        var aWindowObject = document.defaultView;
+        if( aWindowObject )
+        {
+            aWindowObject.open( this.sURL, this.sId );
+        }
+        else
+        {
+            log( 'error: HyperlinkElement.handleClick: invalid window object.' );
+        }
+    }
+
+
+    return true;
+};
+
+HyperlinkElement.prototype.setPointerCursor = function()
+{
+    if( this.bClickHandled )
+        return;
+
+    this.aElement.setAttribute( 'style', 'cursor: pointer' );
+};
+
+HyperlinkElement.prototype.setDefaultCursor = function()
+{
+    this.aElement.setAttribute( 'style', 'cursor: default' );
+};
+
 
 // ------------------------------------------------------------------------------------------ //
 function InteractiveAnimationSequence( nId )
@@ -10171,9 +10591,11 @@ PriorityEntry.compare = function( aLhsEntry, aRhsEntry )
     return ( aLhsEntry.nPriority < aRhsEntry.nPriority );
 };
 
+
 // ------------------------------------------------------------------------------------------ //
 function EventMultiplexer( aTimerEventQueue )
 {
+    this.nId = EventMultiplexer.getUniqueId();
     this.aTimerEventQueue = aTimerEventQueue;
     this.aEventMap = new Object();
     this.aSkipEffectEndHandlerSet = new Array();
@@ -10187,6 +10609,25 @@ function EventMultiplexer( aTimerEventQueue )
     this.aRewindedEffectHandlerSet = new Object();
 }
 
+EventMultiplexer.CURR_UNIQUE_ID = 0;
+
+EventMultiplexer.getUniqueId = function()
+{
+    ++EventMultiplexer.CURR_UNIQUE_ID;
+    return EventMultiplexer.CURR_UNIQUE_ID;
+};
+
+EventMultiplexer.prototype.getId = function()
+{
+    return this.nId;
+}
+
+EventMultiplexer.prototype.hasRegisteredMouseClickHandlers = function()
+{
+    var nSize = this.aMouseClickHandlerSet.size();
+    return ( nSize > 0 );
+}
+
 EventMultiplexer.prototype.registerMouseClickHandler = function( aHandler, nPriority )
 {
     var aHandlerEntry = new PriorityEntry( aHandler, nPriority );
@@ -10195,11 +10636,11 @@ EventMultiplexer.prototype.registerMouseClickHandler = function( aHandler, nPrio
 
 EventMultiplexer.prototype.notifyMouseClick = function( aMouseEvent )
 {
-    var aMouseClickHandlerSet = this.aMouseClickHandlerSet;
-    var nSize = aMouseClickHandlerSet.size();
-    for( var i = 0; i < nSize; ++i )
+    var aMouseClickHandlerSet = this.aMouseClickHandlerSet.clone();
+    while( !aMouseClickHandlerSet.isEmpty() )
     {
-        var aHandlerEntry = aMouseClickHandlerSet.aSequence[i];
+        var aHandlerEntry = aMouseClickHandlerSet.top();
+        aMouseClickHandlerSet.pop();
         if( aHandlerEntry.aValue.handleClick( aMouseEvent ) )
             break;
     }
diff --git a/filter/source/svg/svgexport.cxx b/filter/source/svg/svgexport.cxx
index 038b2db..38cad60 100644
--- a/filter/source/svg/svgexport.cxx
+++ b/filter/source/svg/svgexport.cxx
@@ -455,6 +455,102 @@ sal_Bool ObjectRepresentation::operator==( const ObjectRepresentation& rPresenta
             ( *mpMtf == *rPresentation.mpMtf ) );
 }
 
+// -----------------------------------------------------------------------------
+
+sal_uLong GetBitmapChecksum( const MetaAction* pAction )
+{
+    sal_uLong nChecksum = 0;
+    const sal_uInt16 nType = pAction->GetType();
+
+    switch( nType )
+    {
+        case( META_BMPSCALE_ACTION ):
+        {
+            const MetaBmpScaleAction* pA = (const MetaBmpScaleAction*) pAction;
+            if( pA  )
+                nChecksum = pA->GetBitmap().GetChecksum();
+            else
+                OSL_FAIL( "GetBitmapChecksum: MetaBmpScaleAction pointer is null." );
+        }
+        break;
+        case( META_BMPEXSCALE_ACTION ):
+        {
+            const MetaBmpExScaleAction* pA = (const MetaBmpExScaleAction*) pAction;
+            if( pA )
+                nChecksum = pA->GetBitmapEx().GetChecksum();
+            else
+                OSL_FAIL( "GetBitmapChecksum: MetaBmpExScaleAction pointer is null." );
+        }
+        break;
+    }
+    return nChecksum;
+}
+// -----------------------------------------------------------------------------
+
+void MetaBitmapActionGetPoint( const MetaAction* pAction, Point& rPt )
+{
+    const sal_uInt16 nType = pAction->GetType();
+    switch( nType )
+    {
+        case( META_BMPSCALE_ACTION ):
+        {
+            const MetaBmpScaleAction* pA = (const MetaBmpScaleAction*) pAction;
+            if( pA  )
+                rPt = pA->GetPoint();
+            else
+                OSL_FAIL( "MetaBitmapActionGetPoint: MetaBmpScaleAction pointer is null." );
+        }
+        break;
+        case( META_BMPEXSCALE_ACTION ):
+        {
+            const MetaBmpExScaleAction* pA = (const MetaBmpExScaleAction*) pAction;
+            if( pA )
+                rPt = pA->GetPoint();
+            else
+                OSL_FAIL( "MetaBitmapActionGetPoint: MetaBmpExScaleAction pointer is null." );
+        }
+        break;
+    }
+
+}
+
+// -----------------------------------------------------------------------------
+
+size_t HashBitmap::operator()( const ObjectRepresentation& rObjRep ) const
+{
+    const GDIMetaFile& aMtf = rObjRep.GetRepresentation();
+    if( aMtf.GetActionSize() == 1 )
+    {
+        return static_cast< size_t >( GetBitmapChecksum( aMtf.GetAction( 0 ) ) );
+    }
+    else
+    {
+        OSL_FAIL( "HashBitmap: metafile should have a single action." );
+        return 0;
+    }
+}
+
+// -----------------------------------------------------------------------------
+
+bool EqualityBitmap::operator()( const ObjectRepresentation& rObjRep1,
+                                     const ObjectRepresentation& rObjRep2 ) const
+{
+    const GDIMetaFile& aMtf1 = rObjRep1.GetRepresentation();
+    const GDIMetaFile& aMtf2 = rObjRep2.GetRepresentation();
+    if( aMtf1.GetActionSize() == 1 && aMtf2.GetActionSize() == 1 )
+    {
+        sal_uLong nChecksum1 = GetBitmapChecksum( aMtf1.GetAction( 0 ) );
+        sal_uLong nChecksum2 = GetBitmapChecksum( aMtf2.GetAction( 0 ) );
+        return ( nChecksum1 == nChecksum2 );
+    }
+    else
+    {
+        OSL_FAIL( "EqualityBitmap: metafile should have a single action." );
+        return false;
+    }
+}
+
+
 // -------------
 // - SVGFilter -
 // -------------
@@ -1245,10 +1341,10 @@ sal_Bool SVGFilter::implExportTextEmbeddedBitmaps()
 
         if( aMtf.GetActionSize() == 1 )
         {
-            MetaBmpExScaleAction* pAction = (MetaBmpExScaleAction*) aMtf.GetAction( 0 );
+            MetaAction* pAction = aMtf.GetAction( 0 );
             if( pAction )
             {
-                sal_uLong nId = pAction->GetBitmapEx().GetChecksum();
+                sal_uLong nId = GetBitmapChecksum( pAction );
                 sId = B2UCONST( "bitmap(" );
                 sId += OUString::valueOf( (sal_Int64)nId );
                 sId += B2UCONST( ")" );
@@ -1263,7 +1359,8 @@ sal_Bool SVGFilter::implExportTextEmbeddedBitmaps()
                     const Point aTopLeft;
                     const Size  aSize( aBoundRect.Width, aBoundRect.Height );
 
-                    const Point aPt = pAction->GetPoint();
+                    Point aPt;
+                    MetaBitmapActionGetPoint( pAction, aPt );
                     // The image must be exported with x, y attribute set to 0,
                     // on the contrary when referenced by a <use> element,
                     // specifying the wanted position, they will result
@@ -1726,7 +1823,7 @@ sal_Bool SVGFilter::implExportShape( const Reference< XShape >& rxShape )
                     if( !rShapeId.isEmpty() )
                     {
                         mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", rShapeId );
-                        //mpSVGExport->AddAttributeIdLegacy( XML_NAMESPACE_DRAW, rShapeId );
+
                     }
 
                     const GDIMetaFile* pEmbeddedBitmapsMtf = NULL;
@@ -1736,8 +1833,6 @@ sal_Bool SVGFilter::implExportShape( const Reference< XShape >& rxShape )
                     }
 
                     {
-//                        Reference< XText > xText( rxShape, UNO_QUERY );
-//                        mpSVGWriter->bIsTextShape = xText.is();
                         SvXMLElementExport aExp2( *mpSVGExport, XML_NAMESPACE_NONE, "g", sal_True, sal_True );
                         mpSVGWriter->WriteMetaFile( aTopLeft, aSize, rMtf,
                                                     SVGWRITER_WRITE_ALL,
@@ -1869,54 +1964,83 @@ sal_Bool SVGFilter::implCreateObjectsFromShape( const Reference< XDrawPage > & r
                 }
                 else
                 {
-                    Reference< XText > xText( rxShape, UNO_QUERY );
-                    sal_Bool bIsTextShape = xText.is();
-
-                    if( !mpSVGExport->IsUsePositionedCharacters() && bIsTextShape )
+                    if( aGraphic.GetGDIMetaFile().GetActionSize() )
                     {
+                        Reference< XText > xText( rxShape, UNO_QUERY );
+                        sal_Bool bIsTextShape = xText.is();
 
-                        // We create a map of text shape ids.
-                        implRegisterInterface( rxShape );
-                        Reference< XInterface > xRef( rxShape, UNO_QUERY );
-                        const OUString& rShapeId = implGetValidIDFromInterface( xRef );
-                        if( !rShapeId.isEmpty() )
+                        if( !mpSVGExport->IsUsePositionedCharacters() && bIsTextShape )
                         {
-                            mTextShapeIdListMap[rxPage] += rShapeId;
-                            mTextShapeIdListMap[rxPage] += B2UCONST( " " );
-                        }
-
-                        // We create a set of bitmaps embedded into text shape.
-                        GDIMetaFile aMtf;
-                        const Point    aNullPt;
-                        const Size    aSize( pObj->GetCurrentBoundRect().GetSize() );
-                        MetaAction*   pAction;
-                        const GDIMetaFile& rMtf = aGraphic.GetGDIMetaFile();
-                        sal_uLong nCount = rMtf.GetActionSize();
-                        for( sal_uLong nCurAction = 0; nCurAction < nCount; ++nCurAction )
-                        {
-                            pAction = rMtf.GetAction( nCurAction );
-                            const sal_uInt16    nType = pAction->GetType();
+                            Reference< XPropertySet >   xShapePropSet( rxShape, UNO_QUERY );
 
-                            if( nType == META_BMPEXSCALE_ACTION )
+                            if( xShapePropSet.is() )
                             {
-                                GDIMetaFile aEmbeddedBitmapMtf;
-                                pAction->Duplicate();
-                                aEmbeddedBitmapMtf.AddAction( pAction );
-                                aEmbeddedBitmapMtf.SetPrefSize( aSize );
-                                aEmbeddedBitmapMtf.SetPrefMapMode( MAP_100TH_MM );
-                                mEmbeddedBitmapActionSet.insert( ObjectRepresentation( rxShape, aEmbeddedBitmapMtf ) );
-                                pAction->Duplicate();
-                                aMtf.AddAction( pAction );
+                                sal_Bool bHideObj = sal_False;
+
+                                if( mbPresentation )
+                                {
+                                    xShapePropSet->getPropertyValue( B2UCONST( "IsEmptyPresentationObject" ) )  >>= bHideObj;
+                                }
+
+                                if( !bHideObj )
+                                {
+                                    // We create a map of text shape ids.
+                                    implRegisterInterface( rxShape );
+                                    Reference< XInterface > xRef( rxShape, UNO_QUERY );
+                                    const OUString& rShapeId = implGetValidIDFromInterface( xRef );
+                                    if( !rShapeId.isEmpty() )
+                                    {
+                                        mTextShapeIdListMap[rxPage] += rShapeId;
+                                        mTextShapeIdListMap[rxPage] += B2UCONST( " " );
+                                    }
+
+                                    // We create a set of bitmaps embedded into text shape.
+                                    GDIMetaFile   aMtf;
+                                    const Point   aNullPt;
+                                    const Size    aSize( pObj->GetCurrentBoundRect().GetSize() );
+                                    MetaAction*   pAction;
+                                    sal_Bool bIsTextShapeStarted = sal_False;
+                                    const GDIMetaFile& rMtf = aGraphic.GetGDIMetaFile();
+                                    sal_uLong nCount = rMtf.GetActionSize();
+                                    for( sal_uLong nCurAction = 0; nCurAction < nCount; ++nCurAction )
+                                    {
+                                        pAction = rMtf.GetAction( nCurAction );
+                                        const sal_uInt16    nType = pAction->GetType();
+
+                                        if( nType == META_COMMENT_ACTION )
+                                        {
+                                            const MetaCommentAction* pA = (const MetaCommentAction*) pAction;
+                                            if( ( pA->GetComment().equalsIgnoreAsciiCaseL(RTL_CONSTASCII_STRINGPARAM("XTEXT_PAINTSHAPE_BEGIN")) ) )
+                                            {
+                                                bIsTextShapeStarted = sal_True;
+                                            }
+                                            else if( ( pA->GetComment().equalsIgnoreAsciiCaseL( RTL_CONSTASCII_STRINGPARAM( "XTEXT_PAINTSHAPE_END" ) ) ) )
+                                            {
+                                                bIsTextShapeStarted = sal_False;
+                                            }
+                                        }
+                                        if( bIsTextShapeStarted && ( nType == META_BMPSCALE_ACTION  || nType == META_BMPEXSCALE_ACTION ) )
+                                        {
+                                            GDIMetaFile aEmbeddedBitmapMtf;
+                                            pAction->Duplicate();
+                                            aEmbeddedBitmapMtf.AddAction( pAction );
+                                            aEmbeddedBitmapMtf.SetPrefSize( aSize );
+                                            aEmbeddedBitmapMtf.SetPrefMapMode( MAP_100TH_MM );
+                                            mEmbeddedBitmapActionSet.insert( ObjectRepresentation( rxShape, aEmbeddedBitmapMtf ) );
+                                            pAction->Duplicate();
+                                            aMtf.AddAction( pAction );
+                                        }
+                                    }
+                                    aMtf.SetPrefSize( aSize );
+                                    aMtf.SetPrefMapMode( MAP_100TH_MM );
+                                    mEmbeddedBitmapActionMap[ rxShape ] = ObjectRepresentation( rxShape, aMtf );
+                                }
                             }
                         }
-                        aMtf.SetPrefSize( aSize );
-                        aMtf.SetPrefMapMode( MAP_100TH_MM );
-                        mEmbeddedBitmapActionMap[ rxShape ] = ObjectRepresentation( rxShape, aMtf );
                     }
-
                     (*mpObjects)[ rxShape ] = ObjectRepresentation( rxShape, aGraphic.GetGDIMetaFile() );
+                    bRet = sal_True;
                 }
-                bRet = sal_True;
             }
         }
     }
diff --git a/filter/source/svg/svgfilter.hxx b/filter/source/svg/svgfilter.hxx
index 1dba3d9..acb0ac0 100644
--- a/filter/source/svg/svgfilter.hxx
+++ b/filter/source/svg/svgfilter.hxx
@@ -236,67 +236,22 @@ struct HashUChar
 };
 
 // ---------------------------
-// - HashBmpExScale -
+// - HashBitmap -
 // ---------------------------
 
-struct HashBmpExScale
+struct HashBitmap
 {
-    size_t operator()( const ObjectRepresentation& rObjRep ) const
-    {
-        const GDIMetaFile& aMtf = rObjRep.GetRepresentation();
-        if( aMtf.GetActionSize() == 1 )
-        {
-            const MetaBmpExScaleAction* pAction = (const MetaBmpExScaleAction*) aMtf.GetAction( 0 );
-            if( pAction )
-            {
-                return static_cast< size_t >( pAction->GetBitmapEx().GetChecksum() );
-            }
-            else
-            {
-                OSL_FAIL( "HashBmpExScale: metafile should have MetaBmpExScaleAction only." );
-                return 0;
-            }
-        }
-        else
-        {
-            OSL_FAIL( "HashBmpExScale: metafile should have a single action." );
-            return 0;
-        }
-    }
+    size_t operator()( const ObjectRepresentation& rObjRep ) const;
 };
 
 // ---------------------------
-// - EqualityBmpExScale -
+// - EqualityBitmap -
 // ---------------------------
 
-struct EqualityBmpExScale
+struct EqualityBitmap
 {
     bool operator()( const ObjectRepresentation& rObjRep1,
-                     const ObjectRepresentation& rObjRep2 ) const
-    {
-        const GDIMetaFile& aMtf1 = rObjRep1.GetRepresentation();
-        const GDIMetaFile& aMtf2 = rObjRep2.GetRepresentation();
-        if( aMtf1.GetActionSize() == 1 && aMtf2.GetActionSize() == 1 )
-        {
-            const MetaBmpExScaleAction* pA1 = (const MetaBmpExScaleAction*) aMtf1.GetAction( 0 );
-            const MetaBmpExScaleAction* pA2 = (const MetaBmpExScaleAction*) aMtf2.GetAction( 0 );
-            if( pA1 && pA2 )
-            {
-                return ( pA1->GetBitmapEx().GetChecksum() == pA2->GetBitmapEx().GetChecksum() );
-            }
-            else
-            {
-                OSL_FAIL( "EqualityBmpExScale: metafile should have MetaBmpExScaleAction only." );
-                return false;
-            }
-        }
-        else
-        {
-            OSL_FAIL( "EqualityBmpExScale: metafile should have a single action." );
-            return false;
-        }
-
-    }
+                     const ObjectRepresentation& rObjRep2 ) const;
 };
 
 
@@ -325,7 +280,7 @@ public:
 
     typedef ::boost::unordered_map< Reference< XInterface >, ::rtl::OUString, HashReferenceXInterface >         UOStringMap;
 
-    typedef ::boost::unordered_set< ObjectRepresentation, HashBmpExScale, EqualityBmpExScale >                  MetaBitmapActionSet;
+    typedef ::boost::unordered_set< ObjectRepresentation, HashBitmap, EqualityBitmap >                  MetaBitmapActionSet;
 
 private:
 
diff --git a/filter/source/svg/svgwriter.cxx b/filter/source/svg/svgwriter.cxx
index ca3f539..2575bfe 100644
--- a/filter/source/svg/svgwriter.cxx
+++ b/filter/source/svg/svgwriter.cxx
@@ -455,7 +455,9 @@ SVGTextWriter::SVGTextWriter( SVGExport& rExport, SVGFontExport& rFontExport )
         mrFontExport( rFontExport ),
         mpContext( NULL ),
         mpVDev( NULL ),
+        mbIsTextShapeStarted( sal_False ),
         mrTextShape(),
+        msShapeId(),
         mrParagraphEnumeration(),
         mrCurrentTextParagraph(),
         mrTextPortionEnumeration(),
@@ -576,10 +578,10 @@ sal_Bool SVGTextWriter::implGetTextPosition<MetaTextRectAction>( const MetaActio
 
 // -----------------------------------------------------------------------------
 
-template<>
-sal_Bool SVGTextWriter::implGetTextPosition<MetaBmpExScaleAction>( const MetaAction* pAction, Point& raPos, sal_Bool& rbEmpty )
+template< typename SubType >
+sal_Bool SVGTextWriter::implGetTextPositionFromBitmap( const MetaAction* pAction, Point& raPos, sal_Bool& rbEmpty )
 {
-    const MetaBmpExScaleAction* pA = (const MetaBmpExScaleAction*) pAction;
+    const SubType* pA = (const SubType*) pAction;
     raPos = pA->GetPoint();
     rbEmpty = sal_False;
     return sal_True;
@@ -640,9 +642,15 @@ sal_Int32 SVGTextWriter::setTextPosition( const GDIMetaFile& rMtf, sal_uLong& nC
             }
             break;
 
+            case( META_BMPSCALE_ACTION ):
+            {
+                bConfigured = implGetTextPositionFromBitmap<MetaBmpScaleAction>( pAction, aPos, bEmpty );
+            }
+            break;
+
             case( META_BMPEXSCALE_ACTION ):
             {
-                bConfigured = implGetTextPosition<MetaBmpExScaleAction>( pAction, aPos, bEmpty );
+                bConfigured = implGetTextPositionFromBitmap<MetaBmpExScaleAction>( pAction, aPos, bEmpty );
             }
             break;
 
@@ -911,6 +919,9 @@ sal_Bool SVGTextWriter::createParagraphEnumeration()
 {
     if( mrTextShape.is() )
     {
+        Reference< XInterface > xRef( mrTextShape, UNO_QUERY );
+        msShapeId = implGetValidIDFromInterface( xRef );
+
         Reference< XEnumerationAccess > xEnumerationAccess( mrTextShape, UNO_QUERY_THROW );
         Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_QUERY_THROW );
         if( xEnumeration.is() )
@@ -1219,6 +1230,7 @@ void SVGTextWriter::startTextShape()
     }
 
     {
+        mbIsTextShapeStarted = sal_True;
         maParentFont = Font();
         mrExport.AddAttribute( XML_NAMESPACE_NONE, "class", B2UCONST( "TextShape" ) );
         mpTextShapeElem = new SvXMLElementExport( mrExport, XML_NAMESPACE_NONE, aXMLElemText, sal_True, mbIWS );
@@ -1242,6 +1254,7 @@ void SVGTextWriter::endTextShape()
         delete mpTextShapeElem;
         mpTextShapeElem = NULL;
     }
+    mbIsTextShapeStarted = sal_False;
     // these need to be invoked after the <text> element has been closed
     implExportHyperlinkIds();
     implWriteBulletChars();
@@ -1336,7 +1349,7 @@ void SVGTextWriter::implExportHyperlinkIds()
     if( !msHyperlinkIdList.isEmpty() )
     {
         mrExport.AddAttribute( XML_NAMESPACE_NONE, "class", B2UCONST( "HyperlinkIdList" ) );
-        SvXMLElementExport aDescElem( mrExport, XML_NAMESPACE_NONE, "desc", sal_True, sal_True );
+        SvXMLElementExport aDescElem( mrExport, XML_NAMESPACE_NONE, "desc", sal_True, sal_False );
         mrExport.GetDocHandler()->characters( msHyperlinkIdList.trim() );
         msHyperlinkIdList = OUString();
     }
@@ -1413,7 +1426,8 @@ void SVGTextWriter::implWriteBulletChars()
 
 // -----------------------------------------------------------------------------
 
-void SVGTextWriter::writeBitmapPlaceholder( const MetaBmpExScaleAction* pAction )
+template< typename MetaBitmapActionType >
+void SVGTextWriter::writeBitmapPlaceholder( const MetaBitmapActionType* pAction )
 {
     // text position element
     const Point& rPos = pAction->GetPoint();
@@ -1429,6 +1443,8 @@ void SVGTextWriter::writeBitmapPlaceholder( const MetaBmpExScaleAction* pAction
     // bitmap placeholder element
     sal_uLong nId = SVGActionWriter::GetChecksum( pAction );
     OUString sId = B2UCONST( "bitmap-placeholder(" );
+    sId += msShapeId;
+    sId += B2UCONST( "." );
     sId += OUString::valueOf( (sal_Int64)nId );
     sId += B2UCONST( ")" );
 
@@ -1452,17 +1468,43 @@ void SVGTextWriter::implWriteEmbeddedBitmaps()
         const GDIMetaFile& rMtf = *mpTextEmbeddedBitmapMtf;
 
         OUString sId, sRefId;
-        sal_uLong nId;
+        sal_uLong nId, nChecksum;
+        Point aPt;
+        Size  aSz;
         sal_uLong nCount = rMtf.GetActionSize();
         for( sal_uLong nCurAction = 0; nCurAction < nCount; nCurAction++ )
         {
-            MetaBmpExScaleAction* pAction = (MetaBmpExScaleAction*) rMtf.GetAction( nCurAction );
+
+            const MetaAction* pAction = rMtf.GetAction( nCurAction );
+            const sal_uInt16 nType = pAction->GetType();
+
+            switch( nType )
+            {
+                case( META_BMPSCALE_ACTION ):
+                {
+                    const MetaBmpScaleAction* pA = (const MetaBmpScaleAction*) pAction;
+                    nChecksum = pA->GetBitmap().GetChecksum();
+                    aPt = pA->GetPoint();
+                    aSz = pA->GetSize();
+                }
+                break;
+                case( META_BMPEXSCALE_ACTION ):
+                {
+                    const MetaBmpExScaleAction* pA = (const MetaBmpExScaleAction*) pAction;
+                    nChecksum = pA->GetBitmapEx().GetChecksum();
+                    aPt = pA->GetPoint();
+                    aSz = pA->GetSize();
+                }
+                break;
+            }
 
             // <g id="?" > (used by animations)
             {
                 // embedded bitmap id
                 nId = SVGActionWriter::GetChecksum( pAction );
                 sId = B2UCONST( "embedded-bitmap(" );
+                sId += msShapeId;
+                sId += B2UCONST( "." );
                 sId += OUString::valueOf( (sal_Int64)nId );
                 sId += B2UCONST( ")" );
                 mrExport.AddAttribute( XML_NAMESPACE_NONE, "id", sId );
@@ -1473,20 +1515,17 @@ void SVGTextWriter::implWriteEmbeddedBitmaps()
                 // <use x="?" y="?" xlink:ref="?" >
                 {
                     // referenced bitmap template
-                    nId = pAction->GetBitmapEx().GetChecksum();
                     sRefId = B2UCONST( "#bitmap(" );
-                    sRefId += OUString::valueOf( (sal_Int64)nId );
+                    sRefId += OUString::valueOf( (sal_Int64)nChecksum );
                     sRefId += B2UCONST( ")" );
 
-                    const Point& rPt = pAction->GetPoint();
-                    const Size&  rSz = pAction->GetSize();
-                    Point aPt;
-                    Size  aSz;
-                    implMap( rPt, aPt );
-                    implMap( rSz, aSz );
+                    Point aPoint;
+                    Size  aSize;
+                    implMap( aPt, aPoint );
+                    implMap( aSz, aSize );
 
-                    mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrX, OUString::valueOf( aPt.X() ) );
-                    mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrY, OUString::valueOf( aPt.Y() ) );
+                    mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrX, OUString::valueOf( aPoint.X() ) );
+                    mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrY, OUString::valueOf( aPoint.Y() ) );
                     mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrXLinkHRef, sRefId );
 
                     SvXMLElementExport aRefElem( mrExport, XML_NAMESPACE_NONE, "use", sal_True, sal_True );
@@ -1906,31 +1945,13 @@ PolyPolygon& SVGActionWriter::ImplMap( const PolyPolygon& rPolyPoly, PolyPolygon
 
 // -----------------------------------------------------------------------------
 
-sal_uLong SVGActionWriter::GetChecksum( const MetaBmpExScaleAction* pAct )
+sal_uLong SVGActionWriter::GetChecksum( const MetaAction* pAction )
 {
-    sal_uLong           nCrc = 0;
-    SVBT16              aBT16;
-    SVBT32              aBT32;
-
-    ShortToSVBT16( pAct->GetType(), aBT16 );
-    nCrc = rtl_crc32( nCrc, aBT16, 2 );
-
-    UInt32ToSVBT32( pAct->GetBitmapEx().GetChecksum(), aBT32 );
-    nCrc = rtl_crc32( nCrc, aBT32, 4 );
-
-    UInt32ToSVBT32( pAct->GetPoint().X(), aBT32 );
-    nCrc = rtl_crc32( nCrc, aBT32, 4 );
-
-    UInt32ToSVBT32( pAct->GetPoint().Y(), aBT32 );
-    nCrc = rtl_crc32( nCrc, aBT32, 4 );
-
-    UInt32ToSVBT32( pAct->GetSize().Width(), aBT32 );
-    nCrc = rtl_crc32( nCrc, aBT32, 4 );
-
-    UInt32ToSVBT32( pAct->GetSize().Height(), aBT32 );
-    nCrc = rtl_crc32( nCrc, aBT32, 4 );
-
-    return nCrc;
+    GDIMetaFile aMtf;
+    MetaAction* pA = (MetaAction*)pAction;
+    pA->Duplicate();
+    aMtf.AddAction( pA );
+    return aMtf.GetChecksum();
 }
 
 // -----------------------------------------------------------------------------
@@ -2749,11 +2770,12 @@ void SVGActionWriter::ImplWriteActions( const GDIMetaFile& rMtf,
     if( mnInnerMtfCount )
         nWriteFlags |= SVGWRITER_NO_SHAPE_COMMENTS;
 
+
+    bool bIsTextShape = false;
     if( !mrExport.IsUsePositionedCharacters() && pxShape
             && Reference< XText >( *pxShape, UNO_QUERY ).is() )
     {
-        Reference< XText > xText( *pxShape, UNO_QUERY );
-        maTextWriter.setTextShape( xText, pTextEmbeddedBitmapMtf );
+        bIsTextShape = true;
     }
 
     mbIsPlacehlolderShape = false;
@@ -2769,7 +2791,7 @@ void SVGActionWriter::ImplWriteActions( const GDIMetaFile& rMtf,
         const MetaAction*   pAction = rMtf.GetAction( nCurAction );
         const sal_uInt16        nType = pAction->GetType();
 
-        if( maTextWriter.getTextShape().is() )
+        if( bIsTextShape )
         {
             try
             {
@@ -3225,6 +3247,12 @@ void SVGActionWriter::ImplWriteActions( const GDIMetaFile& rMtf,
                 {
                     if( ( pA->GetComment().equalsIgnoreAsciiCaseL( RTL_CONSTASCII_STRINGPARAM( "XTEXT_PAINTSHAPE_BEGIN" ) ) ) )
                     {
+                        if( pxShape )
+                        {
+                            Reference< XText > xText( *pxShape, UNO_QUERY );
+                            if( xText.is() )
+                                maTextWriter.setTextShape( xText, pTextEmbeddedBitmapMtf );
+                        }
                         maTextWriter.createParagraphEnumeration();
                         {
                             // nTextFound == -1 => no text found
@@ -3343,9 +3371,17 @@ void SVGActionWriter::ImplWriteActions( const GDIMetaFile& rMtf,
                 {
                     const MetaBmpScaleAction* pA = (const MetaBmpScaleAction*) pAction;
 
-                    ImplWriteBmp( pA->GetBitmap(),
-                                  pA->GetPoint(), pA->GetSize(),
-                                  Point(), pA->GetBitmap().GetSizePixel() );
+                    // Bitmaps embedded into text shapes are collected and exported elsewhere.
+                    if( maTextWriter.isTextShapeStarted() )
+                    {
+                        maTextWriter.writeBitmapPlaceholder( pA );
+                    }
+                    else
+                    {
+                        ImplWriteBmp( pA->GetBitmap(),
+                                      pA->GetPoint(), pA->GetSize(),
+                                      Point(), pA->GetBitmap().GetSizePixel() );
+                    }
                 }
             }
             break;
@@ -3383,7 +3419,7 @@ void SVGActionWriter::ImplWriteActions( const GDIMetaFile& rMtf,
                     const MetaBmpExScaleAction* pA = (const MetaBmpExScaleAction*) pAction;
 
                     // Bitmaps embedded into text shapes are collected and exported elsewhere.
-                    if( maTextWriter.getTextShape().is() )
+                    if( maTextWriter.isTextShapeStarted() )
                     {
                         maTextWriter.writeBitmapPlaceholder( pA );
                     }
diff --git a/filter/source/svg/svgwriter.hxx b/filter/source/svg/svgwriter.hxx
index 125c5ef..7f79f6f 100644
--- a/filter/source/svg/svgwriter.hxx
+++ b/filter/source/svg/svgwriter.hxx
@@ -204,7 +204,9 @@ class SVGTextWriter
     SVGFontExport&                              mrFontExport;
     SVGAttributeWriter*                         mpContext;
     VirtualDevice*                              mpVDev;
+    sal_Bool                                    mbIsTextShapeStarted;
     Reference<XText>                            mrTextShape;
+    ::rtl::OUString                             msShapeId;
     Reference<XEnumeration>                     mrParagraphEnumeration;
     Reference<XTextContent>                     mrCurrentTextParagraph;
     Reference<XEnumeration>                     mrTextPortionEnumeration;
@@ -244,6 +246,7 @@ class SVGTextWriter
     sal_Bool nextParagraph();
     sal_Bool nextTextPortion();
 
+    sal_Bool isTextShapeStarted() { return mbIsTextShapeStarted; }
     void startTextShape();
     void endTextShape();
     void startTextParagraph();
@@ -252,7 +255,8 @@ class SVGTextWriter
     void endTextPosition();
     void implExportHyperlinkIds();
     void implWriteBulletChars();
-    void writeBitmapPlaceholder( const MetaBmpExScaleAction* pAction );
+    template< typename MetaBitmapActionType >
+    void writeBitmapPlaceholder( const MetaBitmapActionType* pAction );
     void implWriteEmbeddedBitmaps();
     void writeTextPortion( const Point& rPos, const String& rText,
                            sal_Bool bApplyMapping = sal_True );
@@ -295,8 +299,12 @@ class SVGTextWriter
     void implMap( const Point& rPt, Point& rDstPt ) const;
     void implSetCurrentFont();
     void implSetFontFamily();
+
     template< typename SubType >
     sal_Bool implGetTextPosition( const MetaAction* pAction, Point& raPos, sal_Bool& bEmpty );
+    template< typename SubType >
+    sal_Bool implGetTextPositionFromBitmap( const MetaAction* pAction, Point& raPos, sal_Bool& rbEmpty );
+
     void implRegisterInterface( const Reference< XInterface >& rxIf );
     const ::rtl::OUString & implGetValidIDFromInterface( const Reference< XInterface >& rxIf );
 
@@ -390,7 +398,7 @@ private:
 public:
 
     static ::rtl::OUString  GetPathString( const PolyPolygon& rPolyPoly, sal_Bool bLine );
-    static sal_uLong        GetChecksum( const MetaBmpExScaleAction* pAct );
+    static sal_uLong        GetChecksum( const MetaAction* pAction );
 
 public:
 
@@ -404,7 +412,6 @@ public:
                                            const ::rtl::OUString* pElementId = NULL,
                                            const Reference< XShape >* pXShape = NULL,
                                            const GDIMetaFile* pTextEmbeddedBitmapMtf = NULL );
-    sal_Bool bIsTextShape;
 };
 
 #endif
commit 76876021482d8c2d9bc43f4ae3c352fc613103c9
Author: Marco Cecchetti <mrcekets at gmail.com>
Date:   Wed Aug 15 22:32:42 2012 +0200

    Now MasterPage text fields work, list items are detected correctly,  some effect work on text.
    
    Date/Time, Footer and Page Number text fields are displayed correctly again.
    
    Fixed several bugs related to synchronization of the two iterations on both meta comment
    actions and text paragraphs/text portions enumerations. At present list items inside a table
    or an OLE object are not exported correctly.
    
    Enabled support for animating text paragraph. Both entrance and exit effects work on text
    shapes, on the contrary there is not yet support for emphasis effects such as changing font
    color and font properties. At present it is possible to apply an effect to the whole paragraph
    only, no support is provided for by word or by character effect variants. Another weak point
    of current implementation is that if you try to select a fragment of a text shape and in your
    selection is included an animatable paragraph the selection is not correct.

diff --git a/filter/source/svg/presentation_engine.js b/filter/source/svg/presentation_engine.js
index 88d8de0..35a4998 100644
--- a/filter/source/svg/presentation_engine.js
+++ b/filter/source/svg/presentation_engine.js
@@ -1098,6 +1098,7 @@ var aPresentationClipPathId = 'presentation_clip_path';
 var aOOOAttrNumberOfSlides = 'number-of-slides';
 var aOOOAttrStartSlideNumber= 'start-slide-number';
 var aOOOAttrNumberingType = 'page-numbering-type';
+var aOOOAttrListItemNumberingType= 'numbering-type';
 
 var aOOOAttrSlide = 'slide';
 var aOOOAttrMaster = 'master';
@@ -5680,6 +5681,7 @@ function AnimationBaseNode( aAnimElem, aParentNode, aNodeContext )
     this.sClassName = 'AnimationBaseNode';
     this.bIsContainer = false;
     this.aTargetElement = null;
+    this.bIsTargetTextElement = false
     this.aAnimatedElement = null;
     this.aActivity = null;
 
@@ -5708,6 +5710,10 @@ AnimationBaseNode.prototype.parseElement = function()
         log( 'AnimationBaseNode.parseElement: target element not found: ' + sTargetElementAttr );
     }
 
+    // sub-item attribute for text animated element
+    var sSubItemAttr = aAnimElem.getAttribute( 'sub-item' );
+    this.bIsTargetTextElement = ( sSubItemAttr && ( sSubItemAttr === 'text' ) );
+
     // additive attribute
     var sAdditiveAttr = aAnimElem.getAttribute( 'additive' );
     if( sAdditiveAttr && aAddittiveModeInMap[sAdditiveAttr] )
@@ -5737,8 +5743,16 @@ AnimationBaseNode.prototype.parseElement = function()
         // create animated element
         if( !this.aNodeContext.aAnimatedElementMap[ sTargetElementAttr ] )
         {
-            this.aNodeContext.aAnimatedElementMap[ sTargetElementAttr ]
+            if( this.bIsTargetTextElement )
+            {
+                this.aNodeContext.aAnimatedElementMap[ sTargetElementAttr ]
+                    = new AnimatedTextElement( this.aTargetElement );
+            }
+            else
+            {
+                this.aNodeContext.aAnimatedElementMap[ sTargetElementAttr ]
                     = new AnimatedElement( this.aTargetElement );
+            }
         }
         this.aAnimatedElement = this.aNodeContext.aAnimatedElementMap[ sTargetElementAttr ];
 
@@ -7386,6 +7400,7 @@ ClippingAnimation.prototype.end = function()
     {
         this.aAnimatableElement.cleanClipPath();
         this.bAnimationStarted = false;
+        this.aAnimatableElement.notifyAnimationEnd();
     }
 };
 
@@ -7440,7 +7455,10 @@ GenericAnimation.prototype.start = function( aAnimatableElement )
 GenericAnimation.prototype.end = function()
 {
     if( this.bAnimationStarted )
+    {
         this.bAnimationStarted = false;
+        this.aAnimatableElement.notifyAnimationEnd();
+    }
 };
 
 GenericAnimation.prototype.perform = function( aValue )
@@ -9117,6 +9135,229 @@ AnimatedElement.prototype.DBG = function( sMessage, nTime )
     aAnimatedElementDebugPrinter.print( 'AnimatedElement(' + this.getId() + ')' + sMessage, nTime );
 };
 
+// ------------------------------------------------------------------------------------------ //
+function AnimatedTextElement( aElement )
+{
+    var theDocument = document;
+
+    var sTextType = aElement.getAttribute( 'class' );
+    var bIsListItem = ( sTextType === 'ListItem' );
+    if( ( sTextType !== 'TextParagraph' ) && !bIsListItem )
+    {
+        log( 'AnimatedTextElement: passed element is not a paragraph.' );
+        return;
+    }
+    var aTextShapeElement = aElement.parentNode;
+    sTextType = aTextShapeElement.getAttribute( 'class' );
+    if( sTextType !== 'TextShape' )
+    {
+        log( 'AnimatedTextElement: element parent is not a text shape.' );
+        return;
+    }
+    var aTextShapeGroup = aTextShapeElement.parentNode;
+    // We search for the helper group element used for inserting
+    // the element copy to be animated; if it doesn't exist we create it.
+    var aAnimatedElementGroup = getElementByClassName( aTextShapeGroup, 'AnimatedElements' );
+    if( !aAnimatedElementGroup )
+    {
+        aAnimatedElementGroup = theDocument.createElementNS( NSS['svg'], 'g' );
+        aAnimatedElementGroup.setAttribute( 'class', 'AnimatedElements' );
+        aTextShapeGroup.appendChild( aAnimatedElementGroup );
+    }
+
+    // Create element used on animating
+    var aAnimatableElement = theDocument.createElementNS( NSS['svg'], 'g' );
+    var aTextElement = theDocument.createElementNS( NSS['svg'], 'text' );
+    // Clone paragraph element <tspan>
+    var aParagraphElement = aElement.cloneNode( true );
+
+    // In case we are dealing with a list item that utilizes a bullet char
+    // we need to clone the related bullet char too.
+    var aBulletCharClone = null;
+    var aBulletCharElem = null;
+    var bIsBulletCharStyle =
+        ( aElement.getAttributeNS( NSS['ooo'], aOOOAttrListItemNumberingType ) === 'bullet-style' );
+    if( bIsBulletCharStyle )
+    {
+        var aBulletCharGroupElem = getElementByClassName( aTextShapeGroup, 'BulletChars' );
+        if( aBulletCharGroupElem )
+        {
+            var aBulletPlaceholderElem = getElementByClassName( aElement.firstElementChild, 'BulletPlaceholder' );
+            if( aBulletPlaceholderElem )
+            {
+                var sId = aBulletPlaceholderElem.getAttribute( 'id' );
+                sId = 'bullet-char(' + sId + ')';
+                aBulletCharElem = theDocument.getElementById( sId );
+                if( aBulletCharElem )
+                {
+                    aBulletCharClone = aBulletCharElem.cloneNode( true );
+                }
+                else
+                {
+                    log( 'AnimatedTextElement: ' + sId + ' not found.' );
+                }
+            }
+            else
+            {
+                log( 'AnimatedTextElement: no bullet placeholder found' );
+            }
+        }
+        else
+        {
+            log( 'AnimatedTextElement: no bullet char group found' );
+        }
+    }
+
+    var aBitmapElemSet = new Array();
+    var aBitmapCloneSet = new Array();
+    var aBitmapPlaceholderSet = getElementsByClassName( aElement, 'BitmapPlaceholder' );
+    if( aBitmapPlaceholderSet )
+    {
+        var i;
+        for( i = 0; i < aBitmapPlaceholderSet.length; ++i )
+        {
+            sId = aBitmapPlaceholderSet[i].getAttribute( 'id' );
+            var sBitmapChecksum = sId.substring( 'bitmap-placeholder'.length + 1, sId.length - 1 );
+            sId = 'embedded-bitmap(' + sBitmapChecksum + ')';
+            aBitmapElemSet[i] = theDocument.getElementById( sId );
+            if( aBitmapElemSet[i] )
+            {
+                aBitmapCloneSet[i] = aBitmapElemSet[i].cloneNode( true );
+            }
+            else
+            {
+                log( 'AnimatedTextElement: ' + sId + ' not found.' );
+            }
+        }
+    }
+
+
+    // Change clone element id.
+    this.sParagraphId = sId = aParagraphElement.getAttribute( 'id' );
+    aParagraphElement.setAttribute( 'id', sId +'.a' );
+    if( aBulletCharClone )
+        aBulletCharClone.removeAttribute( 'id' );
+    for( i = 0; i < aBitmapCloneSet.length; ++i )
+    {
+        if( aBitmapCloneSet[i] )
+            aBitmapCloneSet[i].removeAttribute( 'id' );
+    }
+
+    // Hide original text paragraph.
+    var sVisibilityAttr = aElement.getAttribute( 'visibility' );
+    if( sVisibilityAttr === 'hidden' )
+    {
+        aAnimatableElement.setAttribute( 'visibility', 'hidden' );
+        this.eInitialVisibility = HIDDEN;
+    }
+    else
+    {
+        aElement.setAttribute( 'visibility', 'hidden' );
+        this.eInitialVisibility = VISIBLE;
+    }
+    aParagraphElement.setAttribute( 'visibility', 'inherit' );
+    if( aBulletCharClone )
+        aBulletCharClone.setAttribute( 'visibility', 'inherit' );
+    if( aBulletCharElem )
+        aBulletCharElem.setAttribute( 'visibility', 'hidden' );
+    for( i = 0; i < aBitmapCloneSet.length; ++i )
+    {
+        if( aBitmapElemSet[i] )
+            aBitmapElemSet[i].setAttribute( 'visibility', 'hidden' );
+        if( aBitmapCloneSet[i] )
+            aBitmapCloneSet[i].setAttribute( 'visibility', 'inherit' );
+    }
+
+
+    // Append each element to its parent.
+    // <g class='AnimatedElements'>
+    //   <g>
+    //     <text>
+    //       <tspan class='TextParagraph'> ... </tspan>
+    //     </text>
+    //     [<g class='BulletChar'>...</g>]
+    //     [<g class='EmbeddedBitmap'>...</g>]
+    //     .
+    //     .
+    //     [<g class='EmbeddedBitmap'>...</g>]
+    //   </g>
+    // </g>
+
+    aTextElement.appendChild( aParagraphElement );
+    aAnimatableElement.appendChild( aTextElement );
+    if( aBulletCharClone )
+        aAnimatableElement.appendChild( aBulletCharClone );
+    for( i = 0; i < aBitmapCloneSet.length; ++i )
+    {
+        if( aBitmapCloneSet[i] )
+            aAnimatableElement.appendChild( aBitmapCloneSet[i] );
+    }
+    aAnimatedElementGroup.appendChild( aAnimatableElement );
+
+    this.aParentTextElement = aElement.parentNode;
+    this.aParagraphElement = aElement;
+    this.aAnimatedElementGroup = aAnimatedElementGroup;
+    this.nRunningAnimations = 0;
+
+    AnimatedTextElement.superclass.constructor.call( this, aAnimatableElement );
+
+}
+extend( AnimatedTextElement, AnimatedElement );
+
+/*
+AnimatedTextElement.prototype.notifySlideStart = function()
+{
+    var aClone = this.aBaseElement.cloneNode( true );
+    this.aActiveElement.parentNode.replaceChild( aClone, this.aActiveElement );
+    this.aActiveElement = aClone;
+
+    var aAnimatedParagraphElement = this.aActiveElement.firstElementChild.firstElementChild;
+    if( aAnimatedParagraphElement )
+    {
+        var aParagraphElement = aAnimatedParagraphElement.cloneNode( true );
+        aParagraphElement.setAttribute( 'id', this.sParagraphId );
+        aParagraphElement.setAttribute( 'visibility', aVisibilityAttributeValue[ this.eInitialVisibility  ] );
+        this.aParentTextElement.replaceChild( aParagraphElement, this.aParagraphElement  );
+        this.aParagraphElement = aParagraphElement;
+    }
+    this.aActiveElement.setAttribute( 'visibility', 'hidden' );
+
+
+    this.initElement();
+    this.DBG( '.notifySlideStart invoked' );
+};
+
+AnimatedTextElement.prototype.notifyAnimationStart = function()
+{
+    log( 'AnimatedTextElement.notifyAnimationStart' );
+    if( this.nRunningAnimations === 0 )
+    {
+        this.aParagraphElement.setAttribute( 'visibility', 'hidden' );
+        this.aActiveElement.setAttribute( 'visibility', aVisibilityAttributeValue[ this.eInitialVisibility  ] );
+    }
+    ++this.nRunningAnimations;
+};
+
+AnimatedTextElement.prototype.notifyAnimationEnd = function()
+{
+    log( 'AnimatedTextElement.notifyAnimationEnd' );
+    --this.nRunningAnimations;
+    if( this.nRunningAnimations === 0 )
+    {
+        var sVisibilityAttr = this.aActiveElement.getAttribute( 'visibility' );
+        var aAnimatedParagraphElement = this.aActiveElement.firstElementChild.firstElementChild;
+        if( aAnimatedParagraphElement )
+        {
+            var aParagraphElement = aAnimatedParagraphElement.cloneNode( true );
+            aParagraphElement.setAttribute( 'visibility', sVisibilityAttr );
+            aParagraphElement.setAttribute( 'id', this.sParagraphId );
+            this.aParentTextElement.replaceChild( aParagraphElement, this.aParagraphElement  );
+            this.aParagraphElement = aParagraphElement;
+        }
+        this.aActiveElement.setAttribute( 'visibility', 'hidden' );
+    }
+};
+*/
 
 
 // ------------------------------------------------------------------------------------------ //
diff --git a/filter/source/svg/svgexport.cxx b/filter/source/svg/svgexport.cxx
index ae2d6dc..038b2db 100644
--- a/filter/source/svg/svgexport.cxx
+++ b/filter/source/svg/svgexport.cxx
@@ -1057,10 +1057,14 @@ sal_Bool SVGFilter::implGenerateMetaData()
                     sElemId += OUString::valueOf( i );
                     mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", sElemId );
                     aFieldSet[i]->elementExport( mpSVGExport );
-
-                    aFieldSet[i]->growCharSet( mTextFieldCharSets );
                 }
-
+                if( mpSVGExport->IsEmbedFonts() && mpSVGExport->IsUsePositionedCharacters() )
+                {
+                    for( sal_Int32 i = 0, nSize = aFieldSet.size(); i < nSize; ++i )
+                    {
+                        aFieldSet[i]->growCharSet( mTextFieldCharSets );
+                    }
+                }
             }
             // text fields are used only for generating meta info so we don't need them anymore
             for( sal_uInt32 i = 0; i < aFieldSet.size(); ++i )
@@ -2018,170 +2022,184 @@ OUString SVGFilter::implGetInterfaceName( const Reference< XInterface >& rxIf )
 
 IMPL_LINK( SVGFilter, CalcFieldHdl, EditFieldInfo*, pInfo )
 {
-    sal_Bool       bFieldProcessed = sal_False;
+    sal_Bool bFieldProcessed = sal_False;
+
     if( pInfo && mbPresentation )
     {
         bFieldProcessed = true;
         OUString   aRepresentation = B2UCONST("");
         if( !mbSinglePage )
         {
-            // to notify to the SVGActionWriter::ImplWriteText method
-            // that we are dealing with a placeholder shape
-            aRepresentation = sPlaceholderTag;
-
-            if( !mCreateOjectsCurrentMasterPage.is() )
+            if( mpSVGExport->IsEmbedFonts() && mpSVGExport->IsUsePositionedCharacters() )
             {
-                OSL_FAIL( "error: !mCreateOjectsCurrentMasterPage.is()" );
-                return 0;
-            }
-            sal_Bool bHasCharSetMap = !( mTextFieldCharSets.find( mCreateOjectsCurrentMasterPage ) == mTextFieldCharSets.end() );
+                // to notify to the SVGActionWriter::ImplWriteText method
+                // that we are dealing with a placeholder shape
+                aRepresentation = sPlaceholderTag;
 
-            static const ::rtl::OUString aHeaderId( B2UCONST( aOOOAttrHeaderField ) );
-            static const ::rtl::OUString aFooterId( B2UCONST( aOOOAttrFooterField ) );
-            static const ::rtl::OUString aDateTimeId( B2UCONST( aOOOAttrDateTimeField ) );
-            static const ::rtl::OUString aVariableDateTimeId( B2UCONST( aOOOAttrDateTimeField ) + B2UCONST( "-variable" ) );
+                if( !mCreateOjectsCurrentMasterPage.is() )
+                {
+                    OSL_FAIL( "error: !mCreateOjectsCurrentMasterPage.is()" );
+                    return 0;
+                }
+                sal_Bool bHasCharSetMap = !( mTextFieldCharSets.find( mCreateOjectsCurrentMasterPage ) == mTextFieldCharSets.end() );
 
-            const UCharSet * pCharSet = NULL;
-            UCharSetMap * pCharSetMap = NULL;
-            if( bHasCharSetMap )
-            {
-                pCharSetMap = &( mTextFieldCharSets[ mCreateOjectsCurrentMasterPage ] );
-            }
-            const SvxFieldData* pField = pInfo->GetField().GetField();
-            if( bHasCharSetMap && ( pField->GetClassId() == text::textfield::Type::PRESENTATION_HEADER ) && ( pCharSetMap->find( aHeaderId ) != pCharSetMap->end() ) )
-            {
-                pCharSet = &( (*pCharSetMap)[ aHeaderId ] );
-            }
-            else if( bHasCharSetMap && ( pField->GetClassId() == text::textfield::Type::PRESENTATION_FOOTER ) && ( pCharSetMap->find( aFooterId ) != pCharSetMap->end() ) )
-            {
-                pCharSet = &( (*pCharSetMap)[ aFooterId ] );
-            }
-            else if( pField->GetClassId() == text::textfield::Type::PRESENTATION_DATE_TIME )
-            {
-                if( bHasCharSetMap && ( pCharSetMap->find( aDateTimeId ) != pCharSetMap->end() ) )
+                static const ::rtl::OUString aHeaderId( B2UCONST( aOOOAttrHeaderField ) );
+                static const ::rtl::OUString aFooterId( B2UCONST( aOOOAttrFooterField ) );
+                static const ::rtl::OUString aDateTimeId( B2UCONST( aOOOAttrDateTimeField ) );
+                static const ::rtl::OUString aVariableDateTimeId( B2UCONST( aOOOAttrDateTimeField ) + B2UCONST( "-variable" ) );
+
+                const UCharSet * pCharSet = NULL;
+                UCharSetMap * pCharSetMap = NULL;
+                if( bHasCharSetMap )
+                {
+                    pCharSetMap = &( mTextFieldCharSets[ mCreateOjectsCurrentMasterPage ] );
+                }
+                const SvxFieldData* pField = pInfo->GetField().GetField();
+                if( bHasCharSetMap && ( pField->GetClassId() == text::textfield::Type::PRESENTATION_HEADER ) && ( pCharSetMap->find( aHeaderId ) != pCharSetMap->end() ) )
+                {
+                    pCharSet = &( (*pCharSetMap)[ aHeaderId ] );
+                }
+                else if( bHasCharSetMap && ( pField->GetClassId() == text::textfield::Type::PRESENTATION_FOOTER ) && ( pCharSetMap->find( aFooterId ) != pCharSetMap->end() ) )
                 {
-                    pCharSet = &( (*pCharSetMap)[ aDateTimeId ] );
+                    pCharSet = &( (*pCharSetMap)[ aFooterId ] );
                 }
-                if( bHasCharSetMap && ( pCharSetMap->find( aVariableDateTimeId ) != pCharSetMap->end() ) && !(*pCharSetMap)[ aVariableDateTimeId ].empty() )
+                else if( pField->GetClassId() == text::textfield::Type::PRESENTATION_DATE_TIME )
                 {
-                    SvxDateFormat eDateFormat = SVXDATEFORMAT_B, eCurDateFormat;
-                    const UCharSet & aCharSet = (*pCharSetMap)[ aVariableDateTimeId ];
-                    UCharSet::const_iterator aChar = aCharSet.begin();
-                    // we look for the most verbose date format
-                    for( ; aChar != aCharSet.end(); ++aChar )
+                    if( bHasCharSetMap && ( pCharSetMap->find( aDateTimeId ) != pCharSetMap->end() ) )
                     {
-                        eCurDateFormat = (SvxDateFormat)( (int)( *aChar ) & 0x0f );
-                        switch( eDateFormat )
+                        pCharSet = &( (*pCharSetMap)[ aDateTimeId ] );
+                    }
+                    if( bHasCharSetMap && ( pCharSetMap->find( aVariableDateTimeId ) != pCharSetMap->end() ) && !(*pCharSetMap)[ aVariableDateTimeId ].empty() )
+                    {
+                        SvxDateFormat eDateFormat = SVXDATEFORMAT_B, eCurDateFormat;
+                        const UCharSet & aCharSet = (*pCharSetMap)[ aVariableDateTimeId ];
+                        UCharSet::const_iterator aChar = aCharSet.begin();
+                        // we look for the most verbose date format
+                        for( ; aChar != aCharSet.end(); ++aChar )
                         {
-                            case SVXDATEFORMAT_STDSMALL: ;
-                            case SVXDATEFORMAT_A: ;     // 13.02.96
-                            case SVXDATEFORMAT_B:       // 13.02.1996
-                                switch( eCurDateFormat )
-                                {
-                                    case SVXDATEFORMAT_C: ;     // 13.Feb 1996
-                                    case SVXDATEFORMAT_D:       // 13.February 1996
-                                    case SVXDATEFORMAT_E: ;     // Tue, 13.February 1996
-                                    case SVXDATEFORMAT_STDBIG: ;
-                                    case SVXDATEFORMAT_F:       // Tuesday, 13.February 1996
-                                        eDateFormat = eCurDateFormat;
-                                        break;
-                                    default:
-                                        break;
-                                }
-                            case SVXDATEFORMAT_C: ;     // 13.Feb 1996
-                            case SVXDATEFORMAT_D:       // 13.February 1996
-                                switch( eCurDateFormat )
-                                {
-                                    case SVXDATEFORMAT_E: ;     // Tue, 13.February 1996
-                                    case SVXDATEFORMAT_STDBIG: ;
-                                    case SVXDATEFORMAT_F:       // Tuesday, 13.February 1996
-                                        eDateFormat = eCurDateFormat;
-                                        break;
-                                    default:
-                                        break;
-                                }
-                                break;
-                            default:
-                                break;
+                            eCurDateFormat = (SvxDateFormat)( (int)( *aChar ) & 0x0f );
+                            switch( eDateFormat )
+                            {
+                                case SVXDATEFORMAT_STDSMALL: ;
+                                case SVXDATEFORMAT_A: ;     // 13.02.96
+                                case SVXDATEFORMAT_B:       // 13.02.1996
+                                    switch( eCurDateFormat )
+                                    {
+                                        case SVXDATEFORMAT_C: ;     // 13.Feb 1996
+                                        case SVXDATEFORMAT_D:       // 13.February 1996
+                                        case SVXDATEFORMAT_E: ;     // Tue, 13.February 1996
+                                        case SVXDATEFORMAT_STDBIG: ;
+                                        case SVXDATEFORMAT_F:       // Tuesday, 13.February 1996
+                                            eDateFormat = eCurDateFormat;
+                                            break;
+                                        default:
+                                            break;
+                                    }
+                                case SVXDATEFORMAT_C: ;     // 13.Feb 1996
+                                case SVXDATEFORMAT_D:       // 13.February 1996
+                                    switch( eCurDateFormat )

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list