fdo#70838: apply rotation transformations to DML anchor position

Used the same algorithm that we had for VML to update the position of
the DML anchor taking into account the rotation of the shape.

Complemented the unit test to check the values in the generated DML.

Change-Id: Ie0293c3cf4d1309fad58c0387f1589e69071fd9a
This commit is contained in:
Jacobo Aragunde Pérez 2014-03-22 13:16:52 +01:00
parent 1b922da415
commit c6ff03f37a
2 changed files with 82 additions and 2 deletions

View File

@ -490,6 +490,54 @@ DECLARE_OOXMLEXPORT_TEST(testFdo70838, "fdo70838.docx")
if (!pXmlDocument)
return;
// Check DML document
sal_Int32 aXPos[4], aYPos[4];
aXPos[0] = getXPathContent(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[1]/mc:Choice/w:drawing/wp:anchor/wp:positionH/wp:posOffset").toInt32();
aXPos[1] = getXPathContent(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[2]/mc:Choice/w:drawing/wp:anchor/wp:positionH/wp:posOffset").toInt32();
aXPos[2] = getXPathContent(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[3]/mc:Choice/w:drawing/wp:anchor/wp:positionH/wp:posOffset").toInt32();
aXPos[3] = getXPathContent(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[4]/mc:Choice/w:drawing/wp:anchor/wp:positionH/wp:posOffset").toInt32();
aYPos[0] = getXPathContent(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[1]/mc:Choice/w:drawing/wp:anchor/wp:positionV/wp:posOffset").toInt32();
aYPos[1] = getXPathContent(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[2]/mc:Choice/w:drawing/wp:anchor/wp:positionV/wp:posOffset").toInt32();
aYPos[2] = getXPathContent(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[3]/mc:Choice/w:drawing/wp:anchor/wp:positionV/wp:posOffset").toInt32();
aYPos[3] = getXPathContent(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[4]/mc:Choice/w:drawing/wp:anchor/wp:positionV/wp:posOffset").toInt32();
// TODO: compare values with a reference value extracted from the original document
// depends on fdo#75722
// certain degree of error is tolerated due to rounding in unit conversions
CPPUNIT_ASSERT(abs(aXPos[0] - aXPos[1]) < 1000);
CPPUNIT_ASSERT(abs(aXPos[1] - aXPos[2]) < 1000);
CPPUNIT_ASSERT(abs(aXPos[2] - aXPos[3]) < 1000);
CPPUNIT_ASSERT(abs(aYPos[0] - aYPos[1]) < 1000);
CPPUNIT_ASSERT(abs(aYPos[1] - aYPos[2]) < 1000);
CPPUNIT_ASSERT(abs(aYPos[2] - aYPos[3]) < 1000);
sal_Int32 aHSize[4], aVSize[4];
aHSize[0] = getXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[1]/mc:Choice/w:drawing/wp:anchor/wp:extent", "cx").toInt32();
aHSize[1] = getXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[2]/mc:Choice/w:drawing/wp:anchor/wp:extent", "cx").toInt32();
aHSize[2] = getXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[3]/mc:Choice/w:drawing/wp:anchor/wp:extent", "cx").toInt32();
aHSize[3] = getXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[4]/mc:Choice/w:drawing/wp:anchor/wp:extent", "cx").toInt32();
aVSize[0] = getXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[1]/mc:Choice/w:drawing/wp:anchor/wp:extent", "cy").toInt32();
aVSize[1] = getXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[2]/mc:Choice/w:drawing/wp:anchor/wp:extent", "cy").toInt32();
aVSize[2] = getXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[3]/mc:Choice/w:drawing/wp:anchor/wp:extent", "cy").toInt32();
aVSize[3] = getXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[4]/mc:Choice/w:drawing/wp:anchor/wp:extent", "cy").toInt32();
// certain degree of error is tolerated due to rounding in unit conversions
CPPUNIT_ASSERT(abs(3599280 - aHSize[0]) < 1000);
CPPUNIT_ASSERT(abs(3599280 - aHSize[1]) < 1000);
CPPUNIT_ASSERT(abs(3599280 - aHSize[2]) < 1000);
CPPUNIT_ASSERT(abs(3599280 - aHSize[3]) < 1000);
CPPUNIT_ASSERT(abs(1799640 - aVSize[0]) < 1000);
CPPUNIT_ASSERT(abs(1799640 - aVSize[1]) < 1000);
CPPUNIT_ASSERT(abs(1799640 - aVSize[2]) < 1000);
CPPUNIT_ASSERT(abs(1799640 - aVSize[3]) < 1000);
// Check VML document
// get styles of the four shapes
OUString aStyles[4];
aStyles[0] = getXPath( pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[1]/mc:Fallback/w:pict/v:rect", "style");

View File

@ -86,6 +86,35 @@ OUString lclGetAnchorIdFromGrabBag(const SdrObject* pObj)
return aResult;
}
void lclMovePositionWithRotation(awt::Point& aPos, sal_Int64 nRotation)
{
// code from ImplEESdrWriter::ImplFlipBoundingBox (filter/source/msfilter/eschesdo.cxx)
// TODO: refactor
if ( nRotation == 0 )
return;
if ( nRotation < 0 )
nRotation = ( 36000 + nRotation ) % 36000;
if ( nRotation % 18000 == 0 )
nRotation = 0;
while ( nRotation > 9000 )
nRotation = ( 18000 - ( nRotation % 18000 ) );
double fVal = (double) nRotation * F_PI18000;
double fCos = cos( fVal );
double fSin = sin( fVal );
double nWidthHalf = (double) aPos.X / 2;
double nHeightHalf = (double) aPos.Y / 2;
double nXDiff = fSin * nHeightHalf + fCos * nWidthHalf - nWidthHalf;
double nYDiff = fSin * nWidthHalf + fCos * nHeightHalf - nHeightHalf;
aPos.X += nXDiff;
aPos.Y += nYDiff;
}
}
ExportDataSaveRestore::ExportDataSaveRestore(DocxExport& rExport, sal_uLong nStt, sal_uLong nEnd, sw::Frame* pParentFrame)
@ -268,11 +297,14 @@ void DocxSdrExport::startDMLAnchorInline(const SwFrmFmt* pFrmFmt, const Size& rS
{
sax_fastparser::FastAttributeList* attrList = m_pImpl->m_pSerializer->createAttrList();
bool bOpaque = pFrmFmt->GetOpaque().GetValue();
awt::Point aPos(pFrmFmt->GetHoriOrient().GetPos(), pFrmFmt->GetVertOrient().GetPos());
const SdrObject* pObj = pFrmFmt->FindRealSdrObject();
if (pObj != NULL)
{
// SdrObjects know their layer, consider that instead of the frame format.
bOpaque = pObj->GetLayer() != pFrmFmt->GetDoc()->GetHellId() && pObj->GetLayer() != pFrmFmt->GetDoc()->GetInvisibleHellId();
lclMovePositionWithRotation(aPos, pObj->GetRotateAngle());
}
attrList->add(XML_behindDoc, bOpaque ? "0" : "1");
attrList->add(XML_distT, OString::number(TwipsToEMU(pULSpaceItem.GetUpper())).getStr());
@ -394,7 +426,7 @@ void DocxSdrExport::startDMLAnchorInline(const SwFrmFmt* pFrmFmt, const Size& rS
else
{
m_pImpl->m_pSerializer->startElementNS(XML_wp, XML_posOffset, FSEND);
m_pImpl->m_pSerializer->write(TwipsToEMU(pFrmFmt->GetHoriOrient().GetPos()));
m_pImpl->m_pSerializer->write(TwipsToEMU(aPos.X));
m_pImpl->m_pSerializer->endElementNS(XML_wp, XML_posOffset);
}
m_pImpl->m_pSerializer->endElementNS(XML_wp, XML_positionH);
@ -408,7 +440,7 @@ void DocxSdrExport::startDMLAnchorInline(const SwFrmFmt* pFrmFmt, const Size& rS
else
{
m_pImpl->m_pSerializer->startElementNS(XML_wp, XML_posOffset, FSEND);
m_pImpl->m_pSerializer->write(TwipsToEMU(pFrmFmt->GetVertOrient().GetPos()));
m_pImpl->m_pSerializer->write(TwipsToEMU(aPos.Y));
m_pImpl->m_pSerializer->endElementNS(XML_wp, XML_posOffset);
}
m_pImpl->m_pSerializer->endElementNS(XML_wp, XML_positionV);