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 <jaragu...@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 <jaragu...@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 <jaragu...@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")
_______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits