[Libreoffice-commits] core.git: 3 commits - include/oox oox/source sw/qa

Jacobo Aragunde Pérez jaragunde at igalia.com
Fri May 9 05:12:24 PDT 2014


 include/oox/drawingml/scene3dcontext.hxx                        |   11 
 include/oox/drawingml/shape3dproperties.hxx                     |   21 +
 oox/source/drawingml/scene3dcontext.cxx                         |   43 ++
 oox/source/drawingml/shape.cxx                                  |   12 
 oox/source/drawingml/shape3dproperties.cxx                      |  176 ++++++++++
 oox/source/drawingml/shapepropertiescontext.cxx                 |    3 
 oox/source/export/drawingml.cxx                                 |  159 ++++++++-
 sw/qa/extras/ooxmlexport/data/shape-3d-effect-preservation.docx |binary
 sw/qa/extras/ooxmlexport/ooxmlsdrexport.cxx                     |   60 +++
 9 files changed, 467 insertions(+), 18 deletions(-)

New commits:
commit f6422b3dfcb00e451ef103127aace1856dc752a9
Author: Jacobo Aragunde Pérez <jaragunde at igalia.com>
Date:   Fri May 9 12:01:46 2014 +0200

    ooxml: Preserve shape 3d effects: top and bottom bevel
    
    Shapes 3D effects can specify top and bottom bevels like in the
    following example:
    
      <a:sp3d z="488950" extrusionH="63500" contourW="50800">
        <a:bevelT w="139700" h="88900" prst="cross"/>
        <a:bevelB h="88900" prst="relaxedInset"/>
      </a:sp3d>
    
    This patch preserves the a:bevel* tags and their attributes using the
    shape grab bag and modifies an existing unit test to add this check.
    
    Change-Id: I4762111e4d2f75ba2fd3721a126aa324a28a853c

diff --git a/include/oox/drawingml/scene3dcontext.hxx b/include/oox/drawingml/scene3dcontext.hxx
index e4b7a62..d016445 100644
--- a/include/oox/drawingml/scene3dcontext.hxx
+++ b/include/oox/drawingml/scene3dcontext.hxx
@@ -54,6 +54,8 @@ class Shape3DPropertiesContext : public ::oox::core::ContextHandler2
 public:
     Shape3DPropertiesContext( ::oox::core::ContextHandler2Helper& rParent, const ::oox::AttributeList& rAttribs, Shape3DProperties& r3DProperties ) throw();
 
+    ::oox::core::ContextHandlerRef onCreateContext( ::sal_Int32 Element, const ::oox::AttributeList& rAttribs ) SAL_OVERRIDE;
+
 private:
     Shape3DProperties& mr3DProperties;
 };
diff --git a/include/oox/drawingml/shape3dproperties.hxx b/include/oox/drawingml/shape3dproperties.hxx
index a66d46c..32e0f27 100644
--- a/include/oox/drawingml/shape3dproperties.hxx
+++ b/include/oox/drawingml/shape3dproperties.hxx
@@ -43,6 +43,13 @@ struct RotationProperties
     OptValue< sal_Int32 > mnRevolution;
 };
 
+struct BevelProperties
+{
+    OptValue< sal_Int32 > mnPreset;
+    OptValue< sal_Int32 > mnWidth;
+    OptValue< sal_Int32 > mnHeight;
+};
+
 struct Shape3DProperties
 {
     OptValue< sal_Int32 > mnPreset;
@@ -57,16 +64,21 @@ struct Shape3DProperties
     OptValue< sal_Int32 > mnContourW;
     OptValue< sal_Int32 > mnShapeZ;
 
+    OptValue< BevelProperties > maTopBevelProperties;
+    OptValue< BevelProperties > maBottomBevelProperties;
+
     /** Overwrites all members that are explicitly set in rSourceProps. */
     void                assignUsed( const Shape3DProperties& rSourceProps );
 
     OUString            getCameraPrstName( sal_Int32 nElement );
     OUString            getLightRigName( sal_Int32 nElement );
     OUString            getLightRigDirName( sal_Int32 nElement );
+    OUString            getBevelPresetTypeString( sal_Int32 nType );
 
     css::uno::Sequence< css::beans::PropertyValue > getCameraAttributes();
     css::uno::Sequence< css::beans::PropertyValue > getLightRigAttributes();
     css::uno::Sequence< css::beans::PropertyValue > getShape3DAttributes();
+    css::uno::Sequence< css::beans::PropertyValue > getBevelAttributes( BevelProperties rProps );
 };
 
 
diff --git a/oox/source/drawingml/scene3dcontext.cxx b/oox/source/drawingml/scene3dcontext.cxx
index bbae7ab..124a741 100644
--- a/oox/source/drawingml/scene3dcontext.cxx
+++ b/oox/source/drawingml/scene3dcontext.cxx
@@ -80,6 +80,32 @@ Shape3DPropertiesContext::Shape3DPropertiesContext( ContextHandler2Helper& rPare
         mr3DProperties.mnShapeZ = rAttribs.getInteger( XML_z, 0 );
 }
 
+ContextHandlerRef Shape3DPropertiesContext::onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs )
+{
+    switch( aElementToken )
+    {
+    case A_TOKEN( bevelT ):
+    case A_TOKEN( bevelB ):
+    {
+        BevelProperties aProps;
+        if( rAttribs.hasAttribute( XML_w ) )
+            aProps.mnWidth = rAttribs.getInteger( XML_w, 0 );
+        if( rAttribs.hasAttribute( XML_h ) )
+            aProps.mnHeight = rAttribs.getInteger( XML_h, 0 );
+        if( rAttribs.hasAttribute( XML_prst ) )
+            aProps.mnPreset = rAttribs.getToken( XML_prst, XML_none );
+
+        if( aElementToken == A_TOKEN( bevelT ) )
+            mr3DProperties.maTopBevelProperties.set( aProps );
+        else
+            mr3DProperties.maBottomBevelProperties.set( aProps );
+
+        break;
+    }
+    }
+    return 0;
+}
+
 Scene3DRotationPropertiesContext::Scene3DRotationPropertiesContext( ContextHandler2Helper& rParent, RotationProperties& rRotationProperties ) throw()
 : ContextHandler2( rParent )
 , mrRotationProperties( rRotationProperties )
diff --git a/oox/source/drawingml/shape3dproperties.cxx b/oox/source/drawingml/shape3dproperties.cxx
index 7da8a0b..28d9079 100644
--- a/oox/source/drawingml/shape3dproperties.cxx
+++ b/oox/source/drawingml/shape3dproperties.cxx
@@ -171,6 +171,27 @@ OUString Shape3DProperties::getLightRigDirName( sal_Int32 nElement )
     return OUString();
 }
 
+OUString Shape3DProperties::getBevelPresetTypeString( sal_Int32 nType )
+{
+    switch (nType)
+    {
+        case XML_relaxedInset:  return OUString("relaxedInset");
+        case XML_circle:        return OUString("circle");
+        case XML_slope:         return OUString("slope");
+        case XML_cross:         return OUString("cross");
+        case XML_angle:         return OUString("angle");
+        case XML_softRound:     return OUString("softRound");
+        case XML_convex:        return OUString("convex");
+        case XML_coolSlant:     return OUString("coolSlant");
+        case XML_divot:         return OUString("divot");
+        case XML_riblet:        return OUString("riblet");
+        case XML_hardEdge:      return OUString("hardEdge");
+        case XML_artDeco:       return OUString("artDeco");
+    }
+    SAL_WARN( "oox.drawingml", "Shape3DProperties::getBevelPresetTypeString - unexpected token" );
+    return OUString();
+}
+
 css::uno::Sequence< css::beans::PropertyValue > Shape3DProperties::getCameraAttributes()
 {
     css::uno::Sequence<css::beans::PropertyValue> aSeq(6);
@@ -253,10 +274,36 @@ css::uno::Sequence< css::beans::PropertyValue > Shape3DProperties::getLightRigAt
     return aSeq;
 }
 
-css::uno::Sequence< css::beans::PropertyValue > Shape3DProperties::getShape3DAttributes()
+css::uno::Sequence< css::beans::PropertyValue > Shape3DProperties::getBevelAttributes( BevelProperties rProps )
 {
     css::uno::Sequence<css::beans::PropertyValue> aSeq(3);
     sal_Int32 nSize = 0;
+    if( rProps.mnPreset.has() )
+    {
+        aSeq[nSize].Name = "prst";
+        aSeq[nSize].Value = css::uno::Any( getBevelPresetTypeString( rProps.mnPreset.use() ) );
+        nSize++;
+    }
+    if( rProps.mnWidth.has() )
+    {
+        aSeq[nSize].Name = "w";
+        aSeq[nSize].Value = css::uno::Any( rProps.mnWidth.use() );
+        nSize++;
+    }
+    if( rProps.mnHeight.has() )
+    {
+        aSeq[nSize].Name = "h";
+        aSeq[nSize].Value = css::uno::Any( rProps.mnHeight.use() );
+        nSize++;
+    }
+    aSeq.realloc( nSize );
+    return aSeq;
+}
+
+css::uno::Sequence< css::beans::PropertyValue > Shape3DProperties::getShape3DAttributes()
+{
+    css::uno::Sequence<css::beans::PropertyValue> aSeq(5);
+    sal_Int32 nSize = 0;
     if( mnExtrusionH.has() )
     {
         aSeq[nSize].Name = "extrusionH";
@@ -275,6 +322,18 @@ css::uno::Sequence< css::beans::PropertyValue > Shape3DProperties::getShape3DAtt
         aSeq[nSize].Value = css::uno::Any( mnShapeZ.use() );
         nSize++;
     }
+    if( maTopBevelProperties.has() )
+    {
+        aSeq[nSize].Name = "bevelT";
+        aSeq[nSize].Value = css::uno::Any( getBevelAttributes( maTopBevelProperties.use() ) );
+        nSize++;
+    }
+    if( maBottomBevelProperties.has() )
+    {
+        aSeq[nSize].Name = "bevelB";
+        aSeq[nSize].Value = css::uno::Any( getBevelAttributes( maBottomBevelProperties.use() ) );
+        nSize++;
+    }
     aSeq.realloc( nSize );
     return aSeq;
 }
diff --git a/oox/source/export/drawingml.cxx b/oox/source/export/drawingml.cxx
index 0b437db..90000a1 100644
--- a/oox/source/export/drawingml.cxx
+++ b/oox/source/export/drawingml.cxx
@@ -2408,6 +2408,9 @@ void DrawingML::WriteShape3DEffects( Reference< XPropertySet > xPropSet )
     if( aShape3DProps.getLength() == 0 )
         return;
 
+    bool bBevelTPresent = false, bBevelBPresent = false;
+    sax_fastparser::FastAttributeList *aBevelTAttrList = mpFS->createAttrList();
+    sax_fastparser::FastAttributeList *aBevelBAttrList = mpFS->createAttrList();
     sax_fastparser::FastAttributeList *aShape3DAttrList = mpFS->createAttrList();
     for( sal_Int32 i=0; i < aShape3DProps.getLength(); ++i )
     {
@@ -2423,10 +2426,59 @@ void DrawingML::WriteShape3DEffects( Reference< XPropertySet > xPropSet )
                 nToken = XML_z;
             aShape3DAttrList->add( nToken, OString::number( nVal ).getStr() );
         }
+        if( aShape3DProps[i].Name == "bevelT" || aShape3DProps[i].Name == "bevelB" )
+        {
+            Sequence< PropertyValue > aBevelProps;
+            aShape3DProps[i].Value >>= aBevelProps;
+            if ( aBevelProps.getLength() == 0 )
+                continue;
+
+            sax_fastparser::FastAttributeList *aBevelAttrList = NULL;
+            if( aShape3DProps[i].Name == "bevelT" )
+            {
+                bBevelTPresent = true;
+                aBevelAttrList = aBevelTAttrList;
+            }
+            else
+            {
+                bBevelBPresent = true;
+                aBevelAttrList = aBevelBAttrList;
+            }
+            for( sal_Int32 j=0; j < aBevelProps.getLength(); ++j )
+            {
+                if( aBevelProps[j].Name == "w" || aBevelProps[j].Name == "h" )
+                {
+                    sal_Int32 nVal = 0, nToken = XML_none;
+                    aBevelProps[j].Value >>= nVal;
+                    if( aBevelProps[j].Name == "w" )
+                        nToken = XML_w;
+                    else if( aBevelProps[j].Name == "h" )
+                        nToken = XML_h;
+                    aBevelAttrList->add( nToken, OString::number( nVal ).getStr() );
+                }
+                else  if( aBevelProps[j].Name == "prst" )
+                {
+                    OUString sVal;
+                    aBevelProps[j].Value >>= sVal;
+                    aBevelAttrList->add( XML_prst, OUStringToOString( sVal, RTL_TEXTENCODING_UTF8 ).getStr() );
+                }
+            }
+
+        }
     }
 
     sax_fastparser::XFastAttributeListRef xAttrList( aShape3DAttrList );
     mpFS->startElementNS( XML_a, XML_sp3d, xAttrList );
+    if( bBevelTPresent )
+    {
+        sax_fastparser::XFastAttributeListRef xBevelAttrList( aBevelTAttrList );
+        mpFS->singleElementNS( XML_a, XML_bevelT, xBevelAttrList );
+    }
+    if( bBevelBPresent )
+    {
+        sax_fastparser::XFastAttributeListRef xBevelAttrList( aBevelBAttrList );
+        mpFS->singleElementNS( XML_a, XML_bevelB, xBevelAttrList );
+    }
     mpFS->endElementNS( XML_a, XML_sp3d );
 }
 
diff --git a/sw/qa/extras/ooxmlexport/ooxmlsdrexport.cxx b/sw/qa/extras/ooxmlexport/ooxmlsdrexport.cxx
index d7bcf07..1bee43ea 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlsdrexport.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlsdrexport.cxx
@@ -1216,6 +1216,21 @@ DECLARE_OOXMLEXPORT_TEST(testShape3DEffectPreservation, "shape-3d-effect-preserv
     assertXPath(pXmlDoc, "/w:document/w:body/w:p[3]/w:r/mc:AlternateContent/mc:Choice/w:drawing/"
             "wp:anchor/a:graphic/a:graphicData/wps:wsp/wps:spPr/a:sp3d",
             "contourW", "50800");
+    assertXPath(pXmlDoc, "/w:document/w:body/w:p[3]/w:r/mc:AlternateContent/mc:Choice/w:drawing/"
+            "wp:anchor/a:graphic/a:graphicData/wps:wsp/wps:spPr/a:sp3d/a:bevelT",
+            "w", "139700");
+    assertXPath(pXmlDoc, "/w:document/w:body/w:p[3]/w:r/mc:AlternateContent/mc:Choice/w:drawing/"
+            "wp:anchor/a:graphic/a:graphicData/wps:wsp/wps:spPr/a:sp3d/a:bevelT",
+            "h", "88900");
+    assertXPath(pXmlDoc, "/w:document/w:body/w:p[3]/w:r/mc:AlternateContent/mc:Choice/w:drawing/"
+            "wp:anchor/a:graphic/a:graphicData/wps:wsp/wps:spPr/a:sp3d/a:bevelT",
+            "prst", "cross");
+    assertXPath(pXmlDoc, "/w:document/w:body/w:p[3]/w:r/mc:AlternateContent/mc:Choice/w:drawing/"
+            "wp:anchor/a:graphic/a:graphicData/wps:wsp/wps:spPr/a:sp3d/a:bevelB",
+            "h", "88900");
+    assertXPath(pXmlDoc, "/w:document/w:body/w:p[3]/w:r/mc:AlternateContent/mc:Choice/w:drawing/"
+            "wp:anchor/a:graphic/a:graphicData/wps:wsp/wps:spPr/a:sp3d/a:bevelB",
+            "prst", "relaxedInset");
 }
 
 DECLARE_OOXMLEXPORT_TEST(fdo77719, "fdo77719.docx")
commit 6566c218afec3cd8c4d36094777bc30b1970e9e4
Author: Jacobo Aragunde Pérez <jaragunde at igalia.com>
Date:   Thu May 8 14:25:10 2014 +0200

    ooxml: Preserve shape 3d effects: z, contour and extrusion
    
    Shapes can contain 3D effects like in the following example:
    
      <a:sp3d z="488950" extrusionH="63500" contourW="50800"/>
    
    This patch preserves the a:sp3d tag and its attributes using the shape
    grab bag and modifies an existing unit test to add this check.
    
    Change-Id: Ice3cae39c71784be0f6c7f2700b07c21a5e1fb6e

diff --git a/include/oox/drawingml/scene3dcontext.hxx b/include/oox/drawingml/scene3dcontext.hxx
index 82af76e..e4b7a62 100644
--- a/include/oox/drawingml/scene3dcontext.hxx
+++ b/include/oox/drawingml/scene3dcontext.hxx
@@ -49,6 +49,15 @@ private:
     Shape3DProperties& mr3DProperties;
 };
 
+class Shape3DPropertiesContext : public ::oox::core::ContextHandler2
+{
+public:
+    Shape3DPropertiesContext( ::oox::core::ContextHandler2Helper& rParent, const ::oox::AttributeList& rAttribs, Shape3DProperties& r3DProperties ) throw();
+
+private:
+    Shape3DProperties& mr3DProperties;
+};
+
 } }
 
 #endif // INCLUDED_OOX_DRAWINGML_SCENE3DCONTEXT_HXX
diff --git a/include/oox/drawingml/shape3dproperties.hxx b/include/oox/drawingml/shape3dproperties.hxx
index 2577e3f..a66d46c 100644
--- a/include/oox/drawingml/shape3dproperties.hxx
+++ b/include/oox/drawingml/shape3dproperties.hxx
@@ -53,6 +53,10 @@ struct Shape3DProperties
     RotationProperties maCameraRotation;
     RotationProperties maLightRigRotation;
 
+    OptValue< sal_Int32 > mnExtrusionH;
+    OptValue< sal_Int32 > mnContourW;
+    OptValue< sal_Int32 > mnShapeZ;
+
     /** Overwrites all members that are explicitly set in rSourceProps. */
     void                assignUsed( const Shape3DProperties& rSourceProps );
 
@@ -62,6 +66,7 @@ struct Shape3DProperties
 
     css::uno::Sequence< css::beans::PropertyValue > getCameraAttributes();
     css::uno::Sequence< css::beans::PropertyValue > getLightRigAttributes();
+    css::uno::Sequence< css::beans::PropertyValue > getShape3DAttributes();
 };
 
 
diff --git a/oox/source/drawingml/scene3dcontext.cxx b/oox/source/drawingml/scene3dcontext.cxx
index 7d95b73..bbae7ab 100644
--- a/oox/source/drawingml/scene3dcontext.cxx
+++ b/oox/source/drawingml/scene3dcontext.cxx
@@ -68,6 +68,18 @@ ContextHandlerRef Scene3DPropertiesContext::onCreateContext( sal_Int32 aElementT
     return 0;
 }
 
+Shape3DPropertiesContext::Shape3DPropertiesContext( ContextHandler2Helper& rParent, const AttributeList& rAttribs, Shape3DProperties& r3DProperties ) throw()
+: ContextHandler2( rParent )
+, mr3DProperties( r3DProperties )
+{
+    if( rAttribs.hasAttribute( XML_extrusionH ) )
+        mr3DProperties.mnExtrusionH = rAttribs.getInteger( XML_extrusionH, 0 );
+    if( rAttribs.hasAttribute( XML_contourW ) )
+        mr3DProperties.mnContourW = rAttribs.getInteger( XML_contourW, 0 );
+    if( rAttribs.hasAttribute( XML_z ) )
+        mr3DProperties.mnShapeZ = rAttribs.getInteger( XML_z, 0 );
+}
+
 Scene3DRotationPropertiesContext::Scene3DRotationPropertiesContext( ContextHandler2Helper& rParent, RotationProperties& rRotationProperties ) throw()
 : ContextHandler2( rParent )
 , mrRotationProperties( rRotationProperties )
diff --git a/oox/source/drawingml/shape.cxx b/oox/source/drawingml/shape.cxx
index 564f51b..da125cf 100644
--- a/oox/source/drawingml/shape.cxx
+++ b/oox/source/drawingml/shape.cxx
@@ -940,11 +940,13 @@ Reference< XShape > Shape::createAndInsert(
             // add 3D effects if any
             Sequence< PropertyValue > aCamera3DEffects = get3DProperties().getCameraAttributes();
             Sequence< PropertyValue > aLightRig3DEffects = get3DProperties().getLightRigAttributes();
+            Sequence< PropertyValue > aShape3DEffects = get3DProperties().getShape3DAttributes();
             if( aCamera3DEffects.getLength() > 0 || aLightRig3DEffects.getLength() > 0 )
             {
-                Sequence< PropertyValue > a3DEffectsGrabBag( 2 );
+                Sequence< PropertyValue > a3DEffectsGrabBag( 3 );
                 PUT_PROP( a3DEffectsGrabBag, 0, "Camera", Any( aCamera3DEffects ) );
                 PUT_PROP( a3DEffectsGrabBag, 1, "LightRig", Any( aLightRig3DEffects ) );
+                PUT_PROP( a3DEffectsGrabBag, 2, "Shape3D", Any( aShape3DEffects ) );
                 putPropertyToGrabBag( "3DEffectProperties", Any( a3DEffectsGrabBag ) );
             }
         }
diff --git a/oox/source/drawingml/shape3dproperties.cxx b/oox/source/drawingml/shape3dproperties.cxx
index 47346a9..7da8a0b 100644
--- a/oox/source/drawingml/shape3dproperties.cxx
+++ b/oox/source/drawingml/shape3dproperties.cxx
@@ -253,6 +253,32 @@ css::uno::Sequence< css::beans::PropertyValue > Shape3DProperties::getLightRigAt
     return aSeq;
 }
 
+css::uno::Sequence< css::beans::PropertyValue > Shape3DProperties::getShape3DAttributes()
+{
+    css::uno::Sequence<css::beans::PropertyValue> aSeq(3);
+    sal_Int32 nSize = 0;
+    if( mnExtrusionH.has() )
+    {
+        aSeq[nSize].Name = "extrusionH";
+        aSeq[nSize].Value = css::uno::Any( mnExtrusionH.use() );
+        nSize++;
+    }
+    if( mnContourW.has() )
+    {
+        aSeq[nSize].Name = "contourW";
+        aSeq[nSize].Value = css::uno::Any( mnContourW.use() );
+        nSize++;
+    }
+    if( mnShapeZ.has() )
+    {
+        aSeq[nSize].Name = "z";
+        aSeq[nSize].Value = css::uno::Any( mnShapeZ.use() );
+        nSize++;
+    }
+    aSeq.realloc( nSize );
+    return aSeq;
+}
+
 
 
 } // namespace drawingml
diff --git a/oox/source/drawingml/shapepropertiescontext.cxx b/oox/source/drawingml/shapepropertiescontext.cxx
index 0823e67..daf8731 100644
--- a/oox/source/drawingml/shapepropertiescontext.cxx
+++ b/oox/source/drawingml/shapepropertiescontext.cxx
@@ -99,8 +99,9 @@ ContextHandlerRef ShapePropertiesContext::onCreateContext( sal_Int32 aElementTok
         return new Scene3DPropertiesContext( *this, mrShape.get3DProperties() );
         break;
 
-    // todo
+    // todo not supported by core, only for preservation via grab bags
     case A_TOKEN( sp3d ):       // CT_Shape3D
+        return new Shape3DPropertiesContext( *this, rAttribs, mrShape.get3DProperties() );
         break;
     }
 
diff --git a/oox/source/export/drawingml.cxx b/oox/source/export/drawingml.cxx
index abe338b..0b437db 100644
--- a/oox/source/export/drawingml.cxx
+++ b/oox/source/export/drawingml.cxx
@@ -2277,7 +2277,7 @@ void DrawingML::WriteShape3DEffects( Reference< XPropertySet > xPropSet )
         return;
 
     // extract the relevant properties from the grab bag
-    Sequence< PropertyValue > aGrabBag, aEffectProps, aLightRigProps;
+    Sequence< PropertyValue > aGrabBag, aEffectProps, aLightRigProps, aShape3DProps;
     mAny >>= aGrabBag;
     for( sal_Int32 i=0; i < aGrabBag.getLength(); ++i )
         if( aGrabBag[i].Name == "3DEffectProperties" )
@@ -2290,10 +2290,12 @@ void DrawingML::WriteShape3DEffects( Reference< XPropertySet > xPropSet )
                     a3DEffectProps[j].Value >>= aEffectProps;
                 else if( a3DEffectProps[j].Name == "LightRig" )
                     a3DEffectProps[j].Value >>= aLightRigProps;
+                else if( a3DEffectProps[j].Name == "Shape3D" )
+                    a3DEffectProps[j].Value >>= aShape3DProps;
             }
             break;
         }
-    if( aEffectProps.getLength() == 0 && aLightRigProps.getLength() == 0 )
+    if( aEffectProps.getLength() == 0 && aLightRigProps.getLength() == 0 && aShape3DProps.getLength() == 0 )
         return;
 
     bool bCameraRotationPresent = false;
@@ -2402,6 +2404,30 @@ void DrawingML::WriteShape3DEffects( Reference< XPropertySet > xPropSet )
         mpFS->singleElementNS( XML_a, XML_lightRig, XML_rig, "threePt", XML_dir, "t", FSEND );
 
     mpFS->endElementNS( XML_a, XML_scene3d );
+
+    if( aShape3DProps.getLength() == 0 )
+        return;
+
+    sax_fastparser::FastAttributeList *aShape3DAttrList = mpFS->createAttrList();
+    for( sal_Int32 i=0; i < aShape3DProps.getLength(); ++i )
+    {
+        if( aShape3DProps[i].Name == "extrusionH" || aShape3DProps[i].Name == "contourW" || aShape3DProps[i].Name == "z" )
+        {
+            sal_Int32 nVal = 0, nToken = XML_none;
+            aShape3DProps[i].Value >>= nVal;
+            if( aShape3DProps[i].Name == "extrusionH" )
+                nToken = XML_extrusionH;
+            else if( aShape3DProps[i].Name == "contourW" )
+                nToken = XML_contourW;
+            else if( aShape3DProps[i].Name == "z" )
+                nToken = XML_z;
+            aShape3DAttrList->add( nToken, OString::number( nVal ).getStr() );
+        }
+    }
+
+    sax_fastparser::XFastAttributeListRef xAttrList( aShape3DAttrList );
+    mpFS->startElementNS( XML_a, XML_sp3d, xAttrList );
+    mpFS->endElementNS( XML_a, XML_sp3d );
 }
 
 }
diff --git a/sw/qa/extras/ooxmlexport/data/shape-3d-effect-preservation.docx b/sw/qa/extras/ooxmlexport/data/shape-3d-effect-preservation.docx
index ed41483..dd4a522 100644
Binary files a/sw/qa/extras/ooxmlexport/data/shape-3d-effect-preservation.docx and b/sw/qa/extras/ooxmlexport/data/shape-3d-effect-preservation.docx differ
diff --git a/sw/qa/extras/ooxmlexport/ooxmlsdrexport.cxx b/sw/qa/extras/ooxmlexport/ooxmlsdrexport.cxx
index 727aef9..d7bcf07 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlsdrexport.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlsdrexport.cxx
@@ -1151,7 +1151,7 @@ DECLARE_OOXMLEXPORT_TEST(testShape3DEffectPreservation, "shape-3d-effect-preserv
     if (!pXmlDoc)
        return;
 
-    // first shape
+    // first shape: extrusion and shift on z, rotated camera with zoom, rotated light rig
     assertXPath(pXmlDoc, "/w:document/w:body/w:p[1]/w:r/mc:AlternateContent/mc:Choice/w:drawing/"
             "wp:anchor/a:graphic/a:graphicData/wps:wsp/wps:spPr/a:scene3d/a:camera",
             "prst", "perspectiveRelaxedModerately");
@@ -1184,7 +1184,14 @@ DECLARE_OOXMLEXPORT_TEST(testShape3DEffectPreservation, "shape-3d-effect-preserv
             "wp:anchor/a:graphic/a:graphicData/wps:wsp/wps:spPr/a:scene3d/a:lightRig/a:rot",
             "rev", "4800000");
 
-    // second shape
+    assertXPath(pXmlDoc, "/w:document/w:body/w:p[1]/w:r/mc:AlternateContent/mc:Choice/w:drawing/"
+            "wp:anchor/a:graphic/a:graphicData/wps:wsp/wps:spPr/a:sp3d",
+            "extrusionH", "63500");
+    assertXPath(pXmlDoc, "/w:document/w:body/w:p[1]/w:r/mc:AlternateContent/mc:Choice/w:drawing/"
+            "wp:anchor/a:graphic/a:graphicData/wps:wsp/wps:spPr/a:sp3d",
+            "z", "488950");
+
+    // second shape: extrusion with theme color, no camera or light rotation
     assertXPath(pXmlDoc, "/w:document/w:body/w:p[2]/w:r/mc:AlternateContent/mc:Choice/w:drawing/"
             "wp:anchor/a:graphic/a:graphicData/wps:wsp/wps:spPr/a:scene3d/a:camera",
             "prst", "isometricLeftDown");
@@ -1200,6 +1207,15 @@ DECLARE_OOXMLEXPORT_TEST(testShape3DEffectPreservation, "shape-3d-effect-preserv
     assertXPath(pXmlDoc, "/w:document/w:body/w:p[2]/w:r/mc:AlternateContent/mc:Choice/w:drawing/"
             "wp:anchor/a:graphic/a:graphicData/wps:wsp/wps:spPr/a:scene3d/a:lightRig/a:rot",
             0);
+
+    assertXPath(pXmlDoc, "/w:document/w:body/w:p[2]/w:r/mc:AlternateContent/mc:Choice/w:drawing/"
+            "wp:anchor/a:graphic/a:graphicData/wps:wsp/wps:spPr/a:sp3d",
+            "extrusionH", "25400");
+
+    // third shape: colored countour and top and bottom bevel
+    assertXPath(pXmlDoc, "/w:document/w:body/w:p[3]/w:r/mc:AlternateContent/mc:Choice/w:drawing/"
+            "wp:anchor/a:graphic/a:graphicData/wps:wsp/wps:spPr/a:sp3d",
+            "contourW", "50800");
 }
 
 DECLARE_OOXMLEXPORT_TEST(fdo77719, "fdo77719.docx")
commit 0df9ec782efeb24c02f7c5baef53bf2fa75a4bc5
Author: Jacobo Aragunde Pérez <jaragunde at igalia.com>
Date:   Tue May 6 16:40:27 2014 +0200

    oox: preserve scene3d/lightRig effects on shapes.
    
    Shapes can contain 3D effects like in the following example:
    
      <a:scene3d>
        <a:camera prst="isometricLeftDown" zoom="150000"/>
        <a:lightRig rig="threePt" dir="t">
          <a:rot lat="0" lon="0" rev="4800000"/>
        </a:lightRig>
      </a:scene3d>
    
    This patch preserves the a:lightRig tag, its attributes and the child
    element a:rot using the shape grab bag. It also adds a unit test for
    this case.
    
    Change-Id: I66b6de3c2b5ef89223b10da54006e28113b8ba5f

diff --git a/include/oox/drawingml/shape3dproperties.hxx b/include/oox/drawingml/shape3dproperties.hxx
index efce9e0..2577e3f 100644
--- a/include/oox/drawingml/shape3dproperties.hxx
+++ b/include/oox/drawingml/shape3dproperties.hxx
@@ -51,13 +51,17 @@ struct Shape3DProperties
     OptValue< sal_Int32 > mnLightRigDirection;
     OptValue< sal_Int32 > mnLightRigType;
     RotationProperties maCameraRotation;
+    RotationProperties maLightRigRotation;
 
     /** Overwrites all members that are explicitly set in rSourceProps. */
     void                assignUsed( const Shape3DProperties& rSourceProps );
 
     OUString            getCameraPrstName( sal_Int32 nElement );
+    OUString            getLightRigName( sal_Int32 nElement );
+    OUString            getLightRigDirName( sal_Int32 nElement );
 
     css::uno::Sequence< css::beans::PropertyValue > getCameraAttributes();
+    css::uno::Sequence< css::beans::PropertyValue > getLightRigAttributes();
 };
 
 
diff --git a/oox/source/drawingml/scene3dcontext.cxx b/oox/source/drawingml/scene3dcontext.cxx
index 21c564c..7d95b73 100644
--- a/oox/source/drawingml/scene3dcontext.cxx
+++ b/oox/source/drawingml/scene3dcontext.cxx
@@ -58,8 +58,9 @@ ContextHandlerRef Scene3DPropertiesContext::onCreateContext( sal_Int32 aElementT
     case A_TOKEN( lightRig ):
         mr3DProperties.mnLightRigDirection = rAttribs.getToken( XML_dir, XML_none );
         mr3DProperties.mnLightRigType = rAttribs.getToken( XML_rig, XML_none );
-        // TODO: nested element XML_rot
-        break;
+
+        return new Scene3DRotationPropertiesContext( *this, mr3DProperties.maLightRigRotation );
+
     case A_TOKEN( backdrop ):
     case A_TOKEN( extLst ):
         return 0; // TODO: later (backdrop is not supported by core anyway)
diff --git a/oox/source/drawingml/shape.cxx b/oox/source/drawingml/shape.cxx
index a83fe49..564f51b 100644
--- a/oox/source/drawingml/shape.cxx
+++ b/oox/source/drawingml/shape.cxx
@@ -939,8 +939,14 @@ Reference< XShape > Shape::createAndInsert(
 
             // add 3D effects if any
             Sequence< PropertyValue > aCamera3DEffects = get3DProperties().getCameraAttributes();
-            if( aCamera3DEffects.getLength() > 0 )
-                putPropertyToGrabBag( "3DEffectProperties", Any( aCamera3DEffects ) );
+            Sequence< PropertyValue > aLightRig3DEffects = get3DProperties().getLightRigAttributes();
+            if( aCamera3DEffects.getLength() > 0 || aLightRig3DEffects.getLength() > 0 )
+            {
+                Sequence< PropertyValue > a3DEffectsGrabBag( 2 );
+                PUT_PROP( a3DEffectsGrabBag, 0, "Camera", Any( aCamera3DEffects ) );
+                PUT_PROP( a3DEffectsGrabBag, 1, "LightRig", Any( aLightRig3DEffects ) );
+                putPropertyToGrabBag( "3DEffectProperties", Any( a3DEffectsGrabBag ) );
+            }
         }
 
         // These can have a custom geometry, so position should be set here,
diff --git a/oox/source/drawingml/shape3dproperties.cxx b/oox/source/drawingml/shape3dproperties.cxx
index 853ed46..47346a9 100644
--- a/oox/source/drawingml/shape3dproperties.cxx
+++ b/oox/source/drawingml/shape3dproperties.cxx
@@ -118,6 +118,59 @@ OUString Shape3DProperties::getCameraPrstName( sal_Int32 nElement )
     return OUString();
 }
 
+OUString Shape3DProperties::getLightRigName( sal_Int32 nElement )
+{
+    switch( nElement )
+    {
+        case XML_legacyFlat1:       return OUString( "legacyFlat1" );
+        case XML_legacyFlat2:       return OUString( "legacyFlat2" );
+        case XML_legacyFlat3:       return OUString( "legacyFlat3" );
+        case XML_legacyFlat4:       return OUString( "legacyFlat4" );
+        case XML_legacyNormal1:     return OUString( "legacyNormal1" );
+        case XML_legacyNormal2:     return OUString( "legacyNormal2" );
+        case XML_legacyNormal3:     return OUString( "legacyNormal3" );
+        case XML_legacyNormal4:     return OUString( "legacyNormal4" );
+        case XML_legacyHarsh1:      return OUString( "legacyHarsh1" );
+        case XML_legacyHarsh2:      return OUString( "legacyHarsh2" );
+        case XML_legacyHarsh3:      return OUString( "legacyHarsh3" );
+        case XML_legacyHarsh4:      return OUString( "legacyHarsh4" );
+        case XML_threePt:           return OUString( "threePt" );
+        case XML_balanced:          return OUString( "balanced" );
+        case XML_soft:              return OUString( "soft" );
+        case XML_harsh:             return OUString( "harsh" );
+        case XML_flood:             return OUString( "flood" );
+        case XML_contrasting:       return OUString( "contrasting" );
+        case XML_morning:           return OUString( "morning" );
+        case XML_sunrise:           return OUString( "sunrise" );
+        case XML_sunset:            return OUString( "sunset" );
+        case XML_chilly:            return OUString( "chilly" );
+        case XML_freezing:          return OUString( "freezing" );
+        case XML_flat:              return OUString( "flat" );
+        case XML_twoPt:             return OUString( "twoPt" );
+        case XML_glow:              return OUString( "glow" );
+        case XML_brightRoom:        return OUString( "brightRoom" );
+    }
+    SAL_WARN( "oox.drawingml", "Shape3DProperties::getLightRigName - unexpected token" );
+    return OUString();
+}
+
+OUString Shape3DProperties::getLightRigDirName( sal_Int32 nElement )
+{
+    switch( nElement )
+    {
+        case XML_tl:    return OUString( "tl" );
+        case XML_t:     return OUString( "t" );
+        case XML_tr:    return OUString( "tr" );
+        case XML_l:     return OUString( "l" );
+        case XML_r:     return OUString( "r" );
+        case XML_bl:    return OUString( "bl" );
+        case XML_b:     return OUString( "b" );
+        case XML_br:    return OUString( "br" );
+    }
+    SAL_WARN( "oox.drawingml", "Shape3DProperties::getLightRigDirName - unexpected token" );
+    return OUString();
+}
+
 css::uno::Sequence< css::beans::PropertyValue > Shape3DProperties::getCameraAttributes()
 {
     css::uno::Sequence<css::beans::PropertyValue> aSeq(6);
@@ -162,6 +215,44 @@ css::uno::Sequence< css::beans::PropertyValue > Shape3DProperties::getCameraAttr
     return aSeq;
 }
 
+css::uno::Sequence< css::beans::PropertyValue > Shape3DProperties::getLightRigAttributes()
+{
+    css::uno::Sequence<css::beans::PropertyValue> aSeq(5);
+    sal_Int32 nSize = 0;
+    if( mnLightRigDirection.has() )
+    {
+        aSeq[nSize].Name = "dir";
+        aSeq[nSize].Value = css::uno::Any( getLightRigDirName( mnLightRigDirection.use() ) );
+        nSize++;
+    }
+    if( mnLightRigType.has() )
+    {
+        aSeq[nSize].Name = "rig";
+        aSeq[nSize].Value = css::uno::Any( getLightRigName( mnLightRigType.use() ) );
+        nSize++;
+    }
+    if( maLightRigRotation.mnLatitude.has() )
+    {
+        aSeq[nSize].Name = "rotLat";
+        aSeq[nSize].Value = css::uno::Any( maLightRigRotation.mnLatitude.use() );
+        nSize++;
+    }
+    if( maLightRigRotation.mnLongitude.has() )
+    {
+        aSeq[nSize].Name = "rotLon";
+        aSeq[nSize].Value = css::uno::Any( maLightRigRotation.mnLongitude.use() );
+        nSize++;
+    }
+    if( maLightRigRotation.mnRevolution.has() )
+    {
+        aSeq[nSize].Name = "rotRev";
+        aSeq[nSize].Value = css::uno::Any( maLightRigRotation.mnRevolution.use() );
+        nSize++;
+    }
+    aSeq.realloc( nSize );
+    return aSeq;
+}
+
 
 
 } // namespace drawingml
diff --git a/oox/source/export/drawingml.cxx b/oox/source/export/drawingml.cxx
index 5d08216..abe338b 100644
--- a/oox/source/export/drawingml.cxx
+++ b/oox/source/export/drawingml.cxx
@@ -2277,15 +2277,23 @@ void DrawingML::WriteShape3DEffects( Reference< XPropertySet > xPropSet )
         return;
 
     // extract the relevant properties from the grab bag
-    Sequence< PropertyValue > aGrabBag, aEffectProps;
+    Sequence< PropertyValue > aGrabBag, aEffectProps, aLightRigProps;
     mAny >>= aGrabBag;
     for( sal_Int32 i=0; i < aGrabBag.getLength(); ++i )
         if( aGrabBag[i].Name == "3DEffectProperties" )
         {
-            aGrabBag[i].Value >>= aEffectProps;
+            Sequence< PropertyValue > a3DEffectProps;
+            aGrabBag[i].Value >>= a3DEffectProps;
+            for( sal_Int32 j=0; j < a3DEffectProps.getLength(); ++j )
+            {
+                if( a3DEffectProps[j].Name == "Camera" )
+                    a3DEffectProps[j].Value >>= aEffectProps;
+                else if( a3DEffectProps[j].Name == "LightRig" )
+                    a3DEffectProps[j].Value >>= aLightRigProps;
+            }
             break;
         }
-    if( aEffectProps.getLength() == 0 )
+    if( aEffectProps.getLength() == 0 && aLightRigProps.getLength() == 0 )
         return;
 
     bool bCameraRotationPresent = false;
@@ -2328,19 +2336,70 @@ void DrawingML::WriteShape3DEffects( Reference< XPropertySet > xPropSet )
         }
     }
 
+    bool bLightRigRotationPresent = false;
+    sax_fastparser::FastAttributeList *aLightRigAttrList = mpFS->createAttrList();
+    sax_fastparser::FastAttributeList *aLightRigRotationAttrList = mpFS->createAttrList();
+    for( sal_Int32 i=0; i < aLightRigProps.getLength(); ++i )
+    {
+        if( aLightRigProps[i].Name == "rig" || aLightRigProps[i].Name == "dir" )
+        {
+            OUString sVal;
+            sal_Int32 nToken = XML_none;
+            aLightRigProps[i].Value >>= sVal;
+            if( aLightRigProps[i].Name == "rig" )
+                nToken = XML_rig;
+            else if( aLightRigProps[i].Name == "dir" )
+                nToken = XML_dir;
+            aLightRigAttrList->add( nToken, OUStringToOString( sVal, RTL_TEXTENCODING_UTF8 ).getStr() );
+        }
+        else if( aLightRigProps[i].Name == "rotLat" ||
+                aLightRigProps[i].Name == "rotLon" ||
+                aLightRigProps[i].Name == "rotRev" )
+        {
+            sal_Int32 nVal = 0, nToken = XML_none;
+            aLightRigProps[i].Value >>= nVal;
+            if( aLightRigProps[i].Name == "rotLat" )
+                nToken = XML_lat;
+            else if( aLightRigProps[i].Name == "rotLon" )
+                nToken = XML_lon;
+            else if( aLightRigProps[i].Name == "rotRev" )
+                nToken = XML_rev;
+            aLightRigRotationAttrList->add( nToken, OString::number( nVal ).getStr() );
+            bLightRigRotationPresent = true;
+        }
+    }
+
     mpFS->startElementNS( XML_a, XML_scene3d, FSEND );
 
-    sax_fastparser::XFastAttributeListRef xAttrList( aCameraAttrList );
-    mpFS->startElementNS( XML_a, XML_camera, xAttrList );
-    if( bCameraRotationPresent )
+    if( aEffectProps.getLength() > 0 )
     {
-        sax_fastparser::XFastAttributeListRef xRotAttrList( aCameraRotationAttrList );
-        mpFS->singleElementNS( XML_a, XML_rot, xRotAttrList );
+        sax_fastparser::XFastAttributeListRef xAttrList( aCameraAttrList );
+        mpFS->startElementNS( XML_a, XML_camera, xAttrList );
+        if( bCameraRotationPresent )
+        {
+            sax_fastparser::XFastAttributeListRef xRotAttrList( aCameraRotationAttrList );
+            mpFS->singleElementNS( XML_a, XML_rot, xRotAttrList );
+        }
+        mpFS->endElementNS( XML_a, XML_camera );
     }
-    mpFS->endElementNS( XML_a, XML_camera );
+    else
+        // a:camera with Word default values - Word won't open the document if this is not present
+        mpFS->singleElementNS( XML_a, XML_camera, XML_prst, "orthographicFront", FSEND );
 
-    // a:lightRig with Word default values - Word won't open the document if this is not present
-    mpFS->singleElementNS( XML_a, XML_lightRig, XML_rig, "threePt", XML_dir, "t", FSEND );
+    if( aEffectProps.getLength() > 0 )
+    {
+        sax_fastparser::XFastAttributeListRef xAttrList( aLightRigAttrList );
+        mpFS->startElementNS( XML_a, XML_lightRig, xAttrList );
+        if( bLightRigRotationPresent )
+        {
+            sax_fastparser::XFastAttributeListRef xRotAttrList( aLightRigRotationAttrList );
+            mpFS->singleElementNS( XML_a, XML_rot, xRotAttrList );
+        }
+        mpFS->endElementNS( XML_a, XML_lightRig );
+    }
+    else
+        // a:lightRig with Word default values - Word won't open the document if this is not present
+        mpFS->singleElementNS( XML_a, XML_lightRig, XML_rig, "threePt", XML_dir, "t", FSEND );
 
     mpFS->endElementNS( XML_a, XML_scene3d );
 }
diff --git a/sw/qa/extras/ooxmlexport/ooxmlsdrexport.cxx b/sw/qa/extras/ooxmlexport/ooxmlsdrexport.cxx
index e88d320..727aef9 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlsdrexport.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlsdrexport.cxx
@@ -1168,6 +1168,22 @@ DECLARE_OOXMLEXPORT_TEST(testShape3DEffectPreservation, "shape-3d-effect-preserv
             "wp:anchor/a:graphic/a:graphicData/wps:wsp/wps:spPr/a:scene3d/a:camera/a:rot",
             "rev", "12900001");
 
+    assertXPath(pXmlDoc, "/w:document/w:body/w:p[1]/w:r/mc:AlternateContent/mc:Choice/w:drawing/"
+            "wp:anchor/a:graphic/a:graphicData/wps:wsp/wps:spPr/a:scene3d/a:lightRig",
+            "rig", "threePt");
+    assertXPath(pXmlDoc, "/w:document/w:body/w:p[1]/w:r/mc:AlternateContent/mc:Choice/w:drawing/"
+            "wp:anchor/a:graphic/a:graphicData/wps:wsp/wps:spPr/a:scene3d/a:lightRig",
+            "dir", "t");
+    assertXPath(pXmlDoc, "/w:document/w:body/w:p[1]/w:r/mc:AlternateContent/mc:Choice/w:drawing/"
+            "wp:anchor/a:graphic/a:graphicData/wps:wsp/wps:spPr/a:scene3d/a:lightRig/a:rot",
+            "lat", "0");
+    assertXPath(pXmlDoc, "/w:document/w:body/w:p[1]/w:r/mc:AlternateContent/mc:Choice/w:drawing/"
+            "wp:anchor/a:graphic/a:graphicData/wps:wsp/wps:spPr/a:scene3d/a:lightRig/a:rot",
+            "lon", "0");
+    assertXPath(pXmlDoc, "/w:document/w:body/w:p[1]/w:r/mc:AlternateContent/mc:Choice/w:drawing/"
+            "wp:anchor/a:graphic/a:graphicData/wps:wsp/wps:spPr/a:scene3d/a:lightRig/a:rot",
+            "rev", "4800000");
+
     // second shape
     assertXPath(pXmlDoc, "/w:document/w:body/w:p[2]/w:r/mc:AlternateContent/mc:Choice/w:drawing/"
             "wp:anchor/a:graphic/a:graphicData/wps:wsp/wps:spPr/a:scene3d/a:camera",
@@ -1175,6 +1191,15 @@ DECLARE_OOXMLEXPORT_TEST(testShape3DEffectPreservation, "shape-3d-effect-preserv
     assertXPath(pXmlDoc, "/w:document/w:body/w:p[2]/w:r/mc:AlternateContent/mc:Choice/w:drawing/"
             "wp:anchor/a:graphic/a:graphicData/wps:wsp/wps:spPr/a:scene3d/a:camera/a:rot",
             0);
+    assertXPath(pXmlDoc, "/w:document/w:body/w:p[2]/w:r/mc:AlternateContent/mc:Choice/w:drawing/"
+            "wp:anchor/a:graphic/a:graphicData/wps:wsp/wps:spPr/a:scene3d/a:lightRig",
+            "rig", "threePt");
+    assertXPath(pXmlDoc, "/w:document/w:body/w:p[2]/w:r/mc:AlternateContent/mc:Choice/w:drawing/"
+            "wp:anchor/a:graphic/a:graphicData/wps:wsp/wps:spPr/a:scene3d/a:lightRig",
+            "dir", "t");
+    assertXPath(pXmlDoc, "/w:document/w:body/w:p[2]/w:r/mc:AlternateContent/mc:Choice/w:drawing/"
+            "wp:anchor/a:graphic/a:graphicData/wps:wsp/wps:spPr/a:scene3d/a:lightRig/a:rot",
+            0);
 }
 
 DECLARE_OOXMLEXPORT_TEST(fdo77719, "fdo77719.docx")


More information about the Libreoffice-commits mailing list