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:
parent
1b922da415
commit
c6ff03f37a
@ -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");
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user