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
This commit is contained in:
@@ -51,13 +51,17 @@ struct Shape3DProperties
|
|||||||
OptValue< sal_Int32 > mnLightRigDirection;
|
OptValue< sal_Int32 > mnLightRigDirection;
|
||||||
OptValue< sal_Int32 > mnLightRigType;
|
OptValue< sal_Int32 > mnLightRigType;
|
||||||
RotationProperties maCameraRotation;
|
RotationProperties maCameraRotation;
|
||||||
|
RotationProperties maLightRigRotation;
|
||||||
|
|
||||||
/** Overwrites all members that are explicitly set in rSourceProps. */
|
/** Overwrites all members that are explicitly set in rSourceProps. */
|
||||||
void assignUsed( const Shape3DProperties& rSourceProps );
|
void assignUsed( const Shape3DProperties& rSourceProps );
|
||||||
|
|
||||||
OUString getCameraPrstName( sal_Int32 nElement );
|
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 > getCameraAttributes();
|
||||||
|
css::uno::Sequence< css::beans::PropertyValue > getLightRigAttributes();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@@ -58,8 +58,9 @@ ContextHandlerRef Scene3DPropertiesContext::onCreateContext( sal_Int32 aElementT
|
|||||||
case A_TOKEN( lightRig ):
|
case A_TOKEN( lightRig ):
|
||||||
mr3DProperties.mnLightRigDirection = rAttribs.getToken( XML_dir, XML_none );
|
mr3DProperties.mnLightRigDirection = rAttribs.getToken( XML_dir, XML_none );
|
||||||
mr3DProperties.mnLightRigType = rAttribs.getToken( XML_rig, 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( backdrop ):
|
||||||
case A_TOKEN( extLst ):
|
case A_TOKEN( extLst ):
|
||||||
return 0; // TODO: later (backdrop is not supported by core anyway)
|
return 0; // TODO: later (backdrop is not supported by core anyway)
|
||||||
|
@@ -939,8 +939,14 @@ Reference< XShape > Shape::createAndInsert(
|
|||||||
|
|
||||||
// add 3D effects if any
|
// add 3D effects if any
|
||||||
Sequence< PropertyValue > aCamera3DEffects = get3DProperties().getCameraAttributes();
|
Sequence< PropertyValue > aCamera3DEffects = get3DProperties().getCameraAttributes();
|
||||||
if( aCamera3DEffects.getLength() > 0 )
|
Sequence< PropertyValue > aLightRig3DEffects = get3DProperties().getLightRigAttributes();
|
||||||
putPropertyToGrabBag( "3DEffectProperties", Any( aCamera3DEffects ) );
|
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,
|
// These can have a custom geometry, so position should be set here,
|
||||||
|
@@ -118,6 +118,59 @@ OUString Shape3DProperties::getCameraPrstName( sal_Int32 nElement )
|
|||||||
return OUString();
|
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 > Shape3DProperties::getCameraAttributes()
|
||||||
{
|
{
|
||||||
css::uno::Sequence<css::beans::PropertyValue> aSeq(6);
|
css::uno::Sequence<css::beans::PropertyValue> aSeq(6);
|
||||||
@@ -162,6 +215,44 @@ css::uno::Sequence< css::beans::PropertyValue > Shape3DProperties::getCameraAttr
|
|||||||
return aSeq;
|
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
|
} // namespace drawingml
|
||||||
|
@@ -2277,15 +2277,23 @@ void DrawingML::WriteShape3DEffects( Reference< XPropertySet > xPropSet )
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// extract the relevant properties from the grab bag
|
// extract the relevant properties from the grab bag
|
||||||
Sequence< PropertyValue > aGrabBag, aEffectProps;
|
Sequence< PropertyValue > aGrabBag, aEffectProps, aLightRigProps;
|
||||||
mAny >>= aGrabBag;
|
mAny >>= aGrabBag;
|
||||||
for( sal_Int32 i=0; i < aGrabBag.getLength(); ++i )
|
for( sal_Int32 i=0; i < aGrabBag.getLength(); ++i )
|
||||||
if( aGrabBag[i].Name == "3DEffectProperties" )
|
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;
|
break;
|
||||||
}
|
}
|
||||||
if( aEffectProps.getLength() == 0 )
|
if( aEffectProps.getLength() == 0 && aLightRigProps.getLength() == 0 )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
bool bCameraRotationPresent = false;
|
bool bCameraRotationPresent = false;
|
||||||
@@ -2328,8 +2336,43 @@ 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 );
|
mpFS->startElementNS( XML_a, XML_scene3d, FSEND );
|
||||||
|
|
||||||
|
if( aEffectProps.getLength() > 0 )
|
||||||
|
{
|
||||||
sax_fastparser::XFastAttributeListRef xAttrList( aCameraAttrList );
|
sax_fastparser::XFastAttributeListRef xAttrList( aCameraAttrList );
|
||||||
mpFS->startElementNS( XML_a, XML_camera, xAttrList );
|
mpFS->startElementNS( XML_a, XML_camera, xAttrList );
|
||||||
if( bCameraRotationPresent )
|
if( bCameraRotationPresent )
|
||||||
@@ -2338,7 +2381,23 @@ void DrawingML::WriteShape3DEffects( Reference< XPropertySet > xPropSet )
|
|||||||
mpFS->singleElementNS( XML_a, XML_rot, xRotAttrList );
|
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 );
|
||||||
|
|
||||||
|
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
|
// 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->singleElementNS( XML_a, XML_lightRig, XML_rig, "threePt", XML_dir, "t", FSEND );
|
||||||
|
|
||||||
|
@@ -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",
|
"wp:anchor/a:graphic/a:graphicData/wps:wsp/wps:spPr/a:scene3d/a:camera/a:rot",
|
||||||
"rev", "12900001");
|
"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
|
// second shape
|
||||||
assertXPath(pXmlDoc, "/w:document/w:body/w:p[2]/w:r/mc:AlternateContent/mc:Choice/w:drawing/"
|
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",
|
"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/"
|
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",
|
"wp:anchor/a:graphic/a:graphicData/wps:wsp/wps:spPr/a:scene3d/a:camera/a:rot",
|
||||||
0);
|
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")
|
DECLARE_OOXMLEXPORT_TEST(fdo77719, "fdo77719.docx")
|
||||||
|
Reference in New Issue
Block a user