Kaydet (Commit) ced59c16 authored tarafından Armin Le Grand's avatar Armin Le Grand Kaydeden (comit) Thorsten Behrens

RotateFlyFrameFix: Add RotCenter info to ODF export

Since the WriterFlyFrames are implicitly rotated around
their center in the Writer UI this has to be added to the
transformation in ODF expressing this. The saved data
now contains the shape data in svg:x/y/width/height statements
(and thus back-compatible AFAP) and a draw:transform statement
(that is to be applied to the defined shape) containing the
rotation around the object's center.

Change-Id: Iccfc70924364f1d58995fce180bce9b6e7643ff4
Reviewed-on: https://gerrit.libreoffice.org/47719Tested-by: 's avatarJenkins <ci@libreoffice.org>
Reviewed-by: 's avatarThorsten Behrens <Thorsten.Behrens@CIB.de>
üst cba1c400
...@@ -64,6 +64,11 @@ namespace xmloff ...@@ -64,6 +64,11 @@ namespace xmloff
} }
namespace basegfx
{
class B2DPoint;
}
enum class TextPNS enum class TextPNS
{ {
ODF, ODF,
...@@ -253,6 +258,7 @@ protected: ...@@ -253,6 +258,7 @@ protected:
XMLShapeExportFlags addTextFrameAttributes( XMLShapeExportFlags addTextFrameAttributes(
const css::uno::Reference< css::beans::XPropertySet >& rPropSet, const css::uno::Reference< css::beans::XPropertySet >& rPropSet,
bool bShape, bool bShape,
basegfx::B2DPoint* pCenter = nullptr,
OUString *pMinHeightValue = nullptr, OUString *pMinHeightValue = nullptr,
OUString *pMinWidthValue = nullptr ); OUString *pMinWidthValue = nullptr );
......
...@@ -990,7 +990,7 @@ XMLTextFrameContext_Impl::XMLTextFrameContext_Impl( ...@@ -990,7 +990,7 @@ XMLTextFrameContext_Impl::XMLTextFrameContext_Impl(
SdXMLImExTransform2D aSdXMLImExTransform2D; SdXMLImExTransform2D aSdXMLImExTransform2D;
basegfx::B2DHomMatrix aFullTransform; basegfx::B2DHomMatrix aFullTransform;
// use SdXMLImExTransform2D to convert to transformation // Use SdXMLImExTransform2D to convert to transformation
// Note: using GetTwipUnitConverter instead of GetMM100UnitConverter may be needed, // Note: using GetTwipUnitConverter instead of GetMM100UnitConverter may be needed,
// but is not generally available (as it should be, a 'current' UnitConverter should // but is not generally available (as it should be, a 'current' UnitConverter should
// be available at GetExport() - and maybe was once). May have to be addressed as soon // be available at GetExport() - and maybe was once). May have to be addressed as soon
...@@ -1002,13 +1002,22 @@ XMLTextFrameContext_Impl::XMLTextFrameContext_Impl( ...@@ -1002,13 +1002,22 @@ XMLTextFrameContext_Impl::XMLTextFrameContext_Impl(
{ {
const basegfx::utils::B2DHomMatrixBufferedDecompose aDecomposedTransform(aFullTransform); const basegfx::utils::B2DHomMatrixBufferedDecompose aDecomposedTransform(aFullTransform);
// currently we *only* use rotation, so warn if *any* of the other transform parts is used // currently we *only* use rotation (and translation indirectly), so warn if *any*
// of the other transform parts is used
SAL_WARN_IF(!basegfx::fTools::equal(1.0, aDecomposedTransform.getScale().getX()), "xmloff.text", "draw:transform uses scaleX" ); SAL_WARN_IF(!basegfx::fTools::equal(1.0, aDecomposedTransform.getScale().getX()), "xmloff.text", "draw:transform uses scaleX" );
SAL_WARN_IF(!basegfx::fTools::equal(1.0, aDecomposedTransform.getScale().getY()), "xmloff.text", "draw:transform uses scaleY" ); SAL_WARN_IF(!basegfx::fTools::equal(1.0, aDecomposedTransform.getScale().getY()), "xmloff.text", "draw:transform uses scaleY" );
SAL_WARN_IF(!basegfx::fTools::equalZero(aDecomposedTransform.getTranslate().getX()), "xmloff.text", "draw:transform uses translateX" );
SAL_WARN_IF(!basegfx::fTools::equalZero(aDecomposedTransform.getTranslate().getY()), "xmloff.text", "draw:transform uses translateY" );
SAL_WARN_IF(!basegfx::fTools::equalZero(aDecomposedTransform.getShearX()), "xmloff.text", "draw:transform uses shearX" ); SAL_WARN_IF(!basegfx::fTools::equalZero(aDecomposedTransform.getShearX()), "xmloff.text", "draw:transform uses shearX" );
// Translation comes from the translate to RotCenter, rot and BackTranslate.
// This means that it represents the translation between unrotated TopLeft
// and rotated TopLeft. This may be checked here now, but currently we only
// use rotation around center and assume that this *was* a rotation around
// center. The check would compare the object's center with the RotCenter
// that can be extracted from the transformation in aFullTransform.
// The definition contains implicitely the RotationCenter absolute
// to the scaled and translated object, so this may be used if needed (see
// _exportTextGraphic how the -trans/rot/trans is composed)
if(!basegfx::fTools::equalZero(aDecomposedTransform.getRotate())) if(!basegfx::fTools::equalZero(aDecomposedTransform.getRotate()))
{ {
// rotation is used, set it. Convert from deg to 10th degree integer // rotation is used, set it. Convert from deg to 10th degree integer
......
...@@ -2529,8 +2529,9 @@ static bool lcl_txtpara_isBoundAsChar( ...@@ -2529,8 +2529,9 @@ static bool lcl_txtpara_isBoundAsChar(
XMLShapeExportFlags XMLTextParagraphExport::addTextFrameAttributes( XMLShapeExportFlags XMLTextParagraphExport::addTextFrameAttributes(
const Reference < XPropertySet >& rPropSet, const Reference < XPropertySet >& rPropSet,
bool bShape, bool bShape,
OUString *pMinHeightValue, basegfx::B2DPoint* pCenter,
OUString *pMinWidthValue) OUString* pMinHeightValue,
OUString* pMinWidthValue)
{ {
XMLShapeExportFlags nShapeFeatures = SEF_DEFAULT; XMLShapeExportFlags nShapeFeatures = SEF_DEFAULT;
...@@ -2592,6 +2593,11 @@ XMLShapeExportFlags XMLTextParagraphExport::addTextFrameAttributes( ...@@ -2592,6 +2593,11 @@ XMLShapeExportFlags XMLTextParagraphExport::addTextFrameAttributes(
sValue, nPos ); sValue, nPos );
GetExport().AddAttribute( XML_NAMESPACE_SVG, XML_X, GetExport().AddAttribute( XML_NAMESPACE_SVG, XML_X,
sValue.makeStringAndClear() ); sValue.makeStringAndClear() );
if(nullptr != pCenter)
{
// add left edge to Center
pCenter->setX(pCenter->getX() + nPos);
}
} }
} }
else if( TextContentAnchorType_AS_CHARACTER == eAnchor ) else if( TextContentAnchorType_AS_CHARACTER == eAnchor )
...@@ -2610,6 +2616,11 @@ XMLShapeExportFlags XMLTextParagraphExport::addTextFrameAttributes( ...@@ -2610,6 +2616,11 @@ XMLShapeExportFlags XMLTextParagraphExport::addTextFrameAttributes(
sValue, nPos ); sValue, nPos );
GetExport().AddAttribute( XML_NAMESPACE_SVG, XML_Y, GetExport().AddAttribute( XML_NAMESPACE_SVG, XML_Y,
sValue.makeStringAndClear() ); sValue.makeStringAndClear() );
if(nullptr != pCenter)
{
// add top edge to Center
pCenter->setY(pCenter->getY() + nPos);
}
} }
if( bShape ) if( bShape )
nShapeFeatures = (nShapeFeatures & ~XMLShapeExportFlags::Y); nShapeFeatures = (nShapeFeatures & ~XMLShapeExportFlags::Y);
...@@ -2641,8 +2652,15 @@ XMLShapeExportFlags XMLTextParagraphExport::addTextFrameAttributes( ...@@ -2641,8 +2652,15 @@ XMLShapeExportFlags XMLTextParagraphExport::addTextFrameAttributes(
} }
} }
else else
{
GetExport().AddAttribute( XML_NAMESPACE_SVG, XML_WIDTH, GetExport().AddAttribute( XML_NAMESPACE_SVG, XML_WIDTH,
sValue.makeStringAndClear() ); sValue.makeStringAndClear() );
if(nullptr != pCenter)
{
// add half width to Center
pCenter->setX(pCenter->getX() + (0.5 * nWidth));
}
}
} }
bool bSyncWidth = false; bool bSyncWidth = false;
if( xPropSetInfo->hasPropertyByName( sIsSyncWidthToHeight ) ) if( xPropSetInfo->hasPropertyByName( sIsSyncWidthToHeight ) )
...@@ -2693,10 +2711,19 @@ XMLShapeExportFlags XMLTextParagraphExport::addTextFrameAttributes( ...@@ -2693,10 +2711,19 @@ XMLShapeExportFlags XMLTextParagraphExport::addTextFrameAttributes(
nHeight ); nHeight );
if( SizeType::FIX != nSizeType && 0==nRelHeight && !bSyncHeight && if( SizeType::FIX != nSizeType && 0==nRelHeight && !bSyncHeight &&
pMinHeightValue ) pMinHeightValue )
{
*pMinHeightValue = sValue.makeStringAndClear(); *pMinHeightValue = sValue.makeStringAndClear();
}
else else
{
GetExport().AddAttribute( XML_NAMESPACE_SVG, XML_HEIGHT, GetExport().AddAttribute( XML_NAMESPACE_SVG, XML_HEIGHT,
sValue.makeStringAndClear() ); sValue.makeStringAndClear() );
if(nullptr != pCenter)
{
// add half height to Center
pCenter->setY(pCenter->getY() + (0.5 * nHeight));
}
}
} }
if( bSyncHeight ) if( bSyncHeight )
{ {
...@@ -2869,7 +2896,7 @@ void XMLTextParagraphExport::_exportTextFrame( ...@@ -2869,7 +2896,7 @@ void XMLTextParagraphExport::_exportTextFrame(
if( !sAutoStyle.isEmpty() ) if( !sAutoStyle.isEmpty() )
GetExport().AddAttribute( XML_NAMESPACE_DRAW, XML_STYLE_NAME, GetExport().AddAttribute( XML_NAMESPACE_DRAW, XML_STYLE_NAME,
GetExport().EncodeStyleName( sAutoStyle ) ); GetExport().EncodeStyleName( sAutoStyle ) );
addTextFrameAttributes(rPropSet, false, &aMinHeightValue, &sMinWidthValue); addTextFrameAttributes(rPropSet, false, nullptr, &aMinHeightValue, &sMinWidthValue);
SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_DRAW, SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_DRAW,
XML_FRAME, false, true ); XML_FRAME, false, true );
...@@ -3029,12 +3056,19 @@ void XMLTextParagraphExport::_exportTextGraphic( ...@@ -3029,12 +3056,19 @@ void XMLTextParagraphExport::_exportTextGraphic(
if( !sAutoStyle.isEmpty() ) if( !sAutoStyle.isEmpty() )
GetExport().AddAttribute( XML_NAMESPACE_DRAW, XML_STYLE_NAME, GetExport().AddAttribute( XML_NAMESPACE_DRAW, XML_STYLE_NAME,
GetExport().EncodeStyleName( sAutoStyle ) ); GetExport().EncodeStyleName( sAutoStyle ) );
addTextFrameAttributes( rPropSet, false );
// check if we need to use svg:transform
sal_Int16 nRotation(0);
rPropSet->getPropertyValue( sGraphicRotation ) >>= nRotation;
const bool bUseRotation(0 != nRotation);
basegfx::B2DPoint aCenter(0.0, 0.0);
// add TextFrame attributes like svg:x/y/width/height, also get back
// object's center point if rotation is used and has to be exported
addTextFrameAttributes(rPropSet, false, bUseRotation ? &aCenter : nullptr);
// svg:transform // svg:transform
sal_Int16 nVal = 0; if(bUseRotation)
rPropSet->getPropertyValue( sGraphicRotation ) >>= nVal;
if( nVal != 0 )
{ {
// RotateFlyFrameFix: im/export full 'draw:transform' using existing tooling. // RotateFlyFrameFix: im/export full 'draw:transform' using existing tooling.
// Currently only rotation is used, but combinations with 'draw:transform' // Currently only rotation is used, but combinations with 'draw:transform'
...@@ -3047,10 +3081,17 @@ void XMLTextParagraphExport::_exportTextGraphic( ...@@ -3047,10 +3081,17 @@ void XMLTextParagraphExport::_exportTextGraphic(
// we have a right-handed coordinate system, so need to correct this by mirroring // we have a right-handed coordinate system, so need to correct this by mirroring
// the rotation to get the correct transformation. See also case XML_TOK_TEXT_FRAME_TRANSFORM // the rotation to get the correct transformation. See also case XML_TOK_TEXT_FRAME_TRANSFORM
// in XMLTextFrameContext_Impl::XMLTextFrameContext_Impl and #i78696# // in XMLTextFrameContext_Impl::XMLTextFrameContext_Impl and #i78696#
const double fRotate(static_cast< double >(-nVal) * (M_PI/1800.0)); const double fRotate(static_cast< double >(-nRotation) * (M_PI/1800.0));
// transform to rotation center which is the object's center
aSdXMLImExTransform2D.AddTranslate(-aCenter);
// add rotation itself
aSdXMLImExTransform2D.AddRotate(fRotate); aSdXMLImExTransform2D.AddRotate(fRotate);
// back-transform after rotation
aSdXMLImExTransform2D.AddTranslate(aCenter);
// Note: using GetTwipUnitConverter instead of GetMM100UnitConverter may be needed, // Note: using GetTwipUnitConverter instead of GetMM100UnitConverter may be needed,
// but is not generally available (as it should be, a 'current' UnitConverter should // but is not generally available (as it should be, a 'current' UnitConverter should
// be available at GetExport() - and maybe was once). May have to be addressed as soon // be available at GetExport() - and maybe was once). May have to be addressed as soon
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment