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:
parent
273e73c896
commit
0df9ec782e
@ -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();
|
||||
};
|
||||
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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 );
|
||||
}
|
||||
|
@ -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")
|
||||
|
Loading…
x
Reference in New Issue
Block a user