diff options
Diffstat (limited to 'sc/source/filter/xml/xmlexprt.cxx')
-rw-r--r-- | sc/source/filter/xml/xmlexprt.cxx | 180 |
1 files changed, 140 insertions, 40 deletions
diff --git a/sc/source/filter/xml/xmlexprt.cxx b/sc/source/filter/xml/xmlexprt.cxx index 6df4093cc8eb..3aeefa2a3c51 100644 --- a/sc/source/filter/xml/xmlexprt.cxx +++ b/sc/source/filter/xml/xmlexprt.cxx @@ -114,6 +114,7 @@ #include <svx/unoshape.hxx> #include <comphelper/base64.hxx> #include <comphelper/extract.hxx> +#include <svx/svdoashp.hxx> #include <svx/svdobj.hxx> #include <svx/svdocapt.hxx> #include <vcl/svapp.hxx> @@ -736,7 +737,9 @@ void ScXMLExport::WriteSingleColumn(const sal_Int32 nRepeatColumns, const sal_In const sal_Int32 nIndex, const bool bIsAutoStyle, const bool bIsVisible) { CheckAttrList(); - AddAttribute(sAttrStyleName, pColumnStyles->GetStyleNameByIndex(nStyleIndex)); + // tdf#138466 + if (nStyleIndex != -1) + AddAttribute(sAttrStyleName, pColumnStyles->GetStyleNameByIndex(nStyleIndex)); if (!bIsVisible) AddAttribute(XML_NAMESPACE_TABLE, XML_VISIBILITY, XML_COLLAPSE); if (nRepeatColumns > 1) @@ -869,9 +872,7 @@ void ScXMLExport::ExportColumns(const sal_Int32 nTable, const ScRange& aColumnHe nColsRepeated = 1; } } - // tdf#138466 - if (nPrevIndex != -1) - WriteColumn(nPrevColumn, nColsRepeated, nPrevIndex, bPrevIsVisible); + WriteColumn(nPrevColumn, nColsRepeated, nPrevIndex, bPrevIsVisible); if (!bIsClosed) CloseHeaderColumn(); if (pGroupColumns->IsGroupEnd(nColumn - 1)) @@ -1350,7 +1351,9 @@ void ScXMLExport::WriteRowStartTag( const sal_Int32 nIndex, const sal_Int32 nEqualRows, bool bHidden, bool bFiltered) { - AddAttribute(sAttrStyleName, pRowStyles->GetStyleNameByIndex(nIndex)); + // tdf#143940 + if (nIndex != -1) + AddAttribute(sAttrStyleName, pRowStyles->GetStyleNameByIndex(nIndex)); if (bHidden) { if (bFiltered) @@ -2000,7 +2003,7 @@ void ScXMLExport::AddStyleFromCells(const uno::Reference<beans::XPropertySet>& x OUString sStyleName; sal_Int32 nNumberFormat(-1); sal_Int32 nValidationIndex(-1); - std::vector< XMLPropertyState > aPropStates(xCellStylesExportPropertySetMapper->Filter( xProperties )); + std::vector<XMLPropertyState> aPropStates(xCellStylesExportPropertySetMapper->Filter(*this, xProperties)); std::vector< XMLPropertyState >::iterator aItr(aPropStates.begin()); std::vector< XMLPropertyState >::iterator aEndItr(aPropStates.end()); sal_Int32 nCount(0); @@ -2134,7 +2137,7 @@ void ScXMLExport::AddStyleFromCells(const uno::Reference<beans::XPropertySet>& x void ScXMLExport::AddStyleFromColumn(const uno::Reference<beans::XPropertySet>& xColumnProperties, const OUString* pOldName, sal_Int32& rIndex, bool& rIsVisible) { - std::vector<XMLPropertyState> aPropStates(xColumnStylesExportPropertySetMapper->Filter(xColumnProperties)); + std::vector<XMLPropertyState> aPropStates(xColumnStylesExportPropertySetMapper->Filter(*this, xColumnProperties)); if(aPropStates.empty()) return; @@ -2171,7 +2174,7 @@ void ScXMLExport::AddStyleFromColumn(const uno::Reference<beans::XPropertySet>& void ScXMLExport::AddStyleFromRow(const uno::Reference<beans::XPropertySet>& xRowProperties, const OUString* pOldName, sal_Int32& rIndex) { - std::vector<XMLPropertyState> aPropStates(xRowStylesExportPropertySetMapper->Filter(xRowProperties)); + std::vector<XMLPropertyState> aPropStates(xRowStylesExportPropertySetMapper->Filter(*this, xRowProperties)); if(aPropStates.empty()) return; @@ -2319,7 +2322,7 @@ void ScXMLExport::collectAutoStyles() uno::Reference<beans::XPropertySet> xTableProperties(xIndex->getByIndex(nTable), uno::UNO_QUERY); if (xTableProperties.is()) { - std::vector<XMLPropertyState> aPropStates(xTableStylesExportPropertySetMapper->Filter(xTableProperties)); + std::vector<XMLPropertyState> aPropStates(xTableStylesExportPropertySetMapper->Filter(*this, xTableProperties)); OUString sName( rTableEntry.maName ); GetAutoStylePool()->AddNamed(sName, XmlStyleFamily::TABLE_TABLE, OUString(), aPropStates); GetAutoStylePool()->RegisterName(XmlStyleFamily::TABLE_TABLE, sName); @@ -2353,7 +2356,7 @@ void ScXMLExport::collectAutoStyles() { if ( !rNoteEntry.maStyleName.isEmpty() ) { - std::vector<XMLPropertyState> aPropStates(xShapeMapper->Filter(xShapeProperties)); + std::vector<XMLPropertyState> aPropStates(xShapeMapper->Filter(*this, xShapeProperties)); OUString sName( rNoteEntry.maStyleName ); GetAutoStylePool()->AddNamed(sName, XmlStyleFamily::SD_GRAPHICS_ID, OUString(), aPropStates); GetAutoStylePool()->RegisterName(XmlStyleFamily::SD_GRAPHICS_ID, sName); @@ -2361,7 +2364,7 @@ void ScXMLExport::collectAutoStyles() if ( !rNoteEntry.maTextStyle.isEmpty() ) { std::vector<XMLPropertyState> aPropStates( - GetTextParagraphExport()->GetParagraphPropertyMapper()->Filter(xShapeProperties)); + GetTextParagraphExport()->GetParagraphPropertyMapper()->Filter(*this, xShapeProperties)); OUString sName( rNoteEntry.maTextStyle ); GetAutoStylePool()->AddNamed(sName, XmlStyleFamily::TEXT_PARAGRAPH, OUString(), aPropStates); GetAutoStylePool()->RegisterName(XmlStyleFamily::TEXT_PARAGRAPH, sName); @@ -2393,7 +2396,7 @@ void ScXMLExport::collectAutoStyles() lcl_GetEnumerated( xCellText, rNoteParaEntry.maSelection.nStartPara ), uno::UNO_QUERY ); if ( xParaProp.is() ) { - std::vector<XMLPropertyState> aPropStates(xParaPropMapper->Filter(xParaProp)); + std::vector<XMLPropertyState> aPropStates(xParaPropMapper->Filter(*this, xParaProp)); OUString sName( rNoteParaEntry.maName ); GetAutoStylePool()->AddNamed(sName, XmlStyleFamily::TEXT_PARAGRAPH, OUString(), aPropStates); GetAutoStylePool()->RegisterName(XmlStyleFamily::TEXT_PARAGRAPH, sName); @@ -2426,7 +2429,7 @@ void ScXMLExport::collectAutoStyles() { pCursor->SetSelection( rNoteTextEntry.maSelection ); - std::vector<XMLPropertyState> aPropStates(xTextPropMapper->Filter(xCursorProp)); + std::vector<XMLPropertyState> aPropStates(xTextPropMapper->Filter(*this, xCursorProp)); OUString sName( rNoteTextEntry.maName ); GetAutoStylePool()->AddNamed(sName, XmlStyleFamily::TEXT_TEXT, OUString(), aPropStates); GetAutoStylePool()->RegisterName(XmlStyleFamily::TEXT_TEXT, sName); @@ -2467,7 +2470,7 @@ void ScXMLExport::collectAutoStyles() continue; pCursor->SetSelection( rTextEntry.maSelection ); - std::vector<XMLPropertyState> aPropStates(xTextPropMapper->Filter(xCursorProp)); + std::vector<XMLPropertyState> aPropStates(xTextPropMapper->Filter(*this, xCursorProp)); OUString sName( rTextEntry.maName ); GetAutoStylePool()->AddNamed(sName, XmlStyleFamily::TEXT_TEXT, OUString(), aPropStates); GetAutoStylePool()->RegisterName(XmlStyleFamily::TEXT_TEXT, sName); @@ -2497,7 +2500,7 @@ void ScXMLExport::collectAutoStyles() uno::Reference<beans::XPropertySet> xTableProperties(xTable, uno::UNO_QUERY); if (xTableProperties.is()) { - std::vector<XMLPropertyState> aPropStates(xTableStylesExportPropertySetMapper->Filter(xTableProperties)); + std::vector<XMLPropertyState> aPropStates(xTableStylesExportPropertySetMapper->Filter(*this, xTableProperties)); if(!aPropStates.empty()) { OUString sName; @@ -3476,43 +3479,106 @@ void ScXMLExport::WriteShapes(const ScMyCell& rMyCell) if( !(rMyCell.bHasShape && !rMyCell.aShapeList.empty() && pDoc) ) return; - tools::Rectangle aRectFull = pDoc->GetMMRect( + // Reference point to turn absolute coordinates in reference point + offset. That happens in most + // cases in XMLShapeExport::ImpExportNewTrans_DecomposeAndRefPoint, which gets the absolute + // coordinates as translation from matrix in property "Transformation". For cell anchored shapes + // the reference point is left-top (in LTR mode) of that cell, which contains the shape. + tools::Rectangle aCellRectFull = pDoc->GetMMRect( rMyCell.maCellAddress.Col(), rMyCell.maCellAddress.Row(), rMyCell.maCellAddress.Col(), rMyCell.maCellAddress.Row(), rMyCell.maCellAddress.Tab(), false /*bHiddenAsZero*/); - tools::Rectangle aRectReduced = pDoc->GetMMRect( - rMyCell.maCellAddress.Col(), rMyCell.maCellAddress.Row(), rMyCell.maCellAddress.Col(), - rMyCell.maCellAddress.Row(), rMyCell.maCellAddress.Tab(), true /*bHiddenAsZero*/); - - // Reference point awt::Point aPoint; bool bNegativePage = pDoc->IsNegativePage(rMyCell.maCellAddress.Tab()); if (bNegativePage) - aPoint.X = aRectFull.Right(); + aPoint.X = aCellRectFull.Right(); else - aPoint.X = aRectFull.Left(); - aPoint.Y = aRectFull.Top(); + aPoint.X = aCellRectFull.Left(); + aPoint.Y = aCellRectFull.Top(); for (const auto& rShape : rMyCell.aShapeList) { if (rShape.xShape.is()) { + // The current object geometry is based on bHiddenAsZero=true, but ODF file format + // needs it as if there were no hidden rows or columns. We manipulate the geometry + // accordingly for writing xml markup and restore geometry later. bool bNeedsRestore = false; SdrObject* pObj = GetSdrObjectFromXShape(rShape.xShape); + // Remember original geometry SdrObjGeoData* pGeoData = nullptr; if (pObj) pGeoData = pObj->GetGeoData(); - if (pObj && aRectFull != aRectReduced) + // Hiding row or column affects the shape based on its snap rect. So we need start and + // end cell address of snap rect. In case of a transformed shape, it is not in rMyCell. + ScAddress aSnapStartAddress = rMyCell.maCellAddress; + ScDrawObjData* pObjData = nullptr; + bool bIsShapeTransformed = false; + if (pObj) + { + pObjData = ScDrawLayer::GetObjData(pObj); + bIsShapeTransformed = pObj->GetRotateAngle() != 0 || pObj->GetShearAngle() != 0; + } + if (bIsShapeTransformed && pObjData) + aSnapStartAddress = pObjData->maStart; + + // In case rows or columns are hidden above or before the snap rect, move the shape to the + // position it would have, if these rows and columns are visible. + tools::Rectangle aRectFull = pDoc->GetMMRect( + aSnapStartAddress.Col(), aSnapStartAddress.Row(), aSnapStartAddress.Col(), + aSnapStartAddress.Row(), aSnapStartAddress.Tab(), false /*bHiddenAsZero*/); + tools::Rectangle aRectReduced = pDoc->GetMMRect( + aSnapStartAddress.Col(), aSnapStartAddress.Row(), aSnapStartAddress.Col(), + aSnapStartAddress.Row(), aSnapStartAddress.Tab(), true /*bHiddenAsZero*/); + const tools::Long nLeftDiff(aRectFull.Left() - aRectReduced.Left()); + const tools::Long nTopDiff(aRectFull.Top() - aRectReduced.Top()); + if (pObj && (abs(nLeftDiff) > 1 || abs(nTopDiff) > 1)) { - // There are hidden rows or columns above or before the start cell. - // The current object geometry is based on bHiddenAsZero=true, but ODF file format - // needs it as if there were no hidden rows or columns. - // We shift the object and restore it later. bNeedsRestore = true; - pObj->NbcMove(Size(aRectFull.Left() - aRectReduced.Left(), - aRectFull.Top() - aRectReduced.Top())); + pObj->NbcMove(Size(nLeftDiff, nTopDiff)); + } + + // tdf#137033 In case the shape is anchored "To Cell (resize with cell)" hiding rows or + // columns inside the snap rect has not only changed size of the shape but rotate and shear + // angle too. We resize the shape to full size. That will recover the original angles too. + if (rShape.bResizeWithCell && pObjData && pObj) + { + // Get original size from anchor + const Point aSnapStartOffset = pObjData->maStartOffset; + // In case of 'resize with cell' maEnd and maEndOffset should be valid. + const ScAddress aSnapEndAddress(pObjData->maEnd); + const Point aSnapEndOffset = pObjData->maEndOffset; + const tools::Rectangle aStartCellRect = pDoc->GetMMRect( + aSnapStartAddress.Col(), aSnapStartAddress.Row(), aSnapStartAddress.Col(), + aSnapStartAddress.Row(), aSnapStartAddress.Tab(), false /*bHiddenAsZero*/); + const tools::Rectangle aEndCellRect = pDoc->GetMMRect( + aSnapEndAddress.Col(), aSnapEndAddress.Row(), aSnapEndAddress.Col(), + aSnapEndAddress.Row(), aSnapEndAddress.Tab(), false /*bHiddenAsZero*/); + if (bNegativePage) + { + aRectFull.SetLeft(aEndCellRect.Right() - aSnapEndOffset.X()); + aRectFull.SetRight(aStartCellRect.Right() - aSnapStartOffset.X()); + } + else + { + aRectFull.SetLeft(aStartCellRect.Left() + aSnapStartOffset.X()); + aRectFull.SetRight(aEndCellRect.Left() + aSnapEndOffset.X()); + } + aRectFull.SetTop(aStartCellRect.Top() + aSnapStartOffset.Y()); + aRectFull.SetBottom(aEndCellRect.Top() + aSnapEndOffset.Y()); + aRectReduced = pObjData->getShapeRect(); + if(abs(aRectFull.getWidth() - aRectReduced.getWidth()) > 1 + || abs(aRectFull.getHeight() - aRectReduced.getHeight()) > 1) + { + bNeedsRestore = true; + Fraction aScaleWidth(aRectFull.getWidth(), aRectReduced.getWidth()); + if (!aScaleWidth.IsValid()) + aScaleWidth = Fraction(1.0); + Fraction aScaleHeight(aRectFull.getHeight(), aRectReduced.getHeight()); + if (!aScaleHeight.IsValid()) + aScaleHeight = Fraction(1.0); + pObj->NbcResize(pObj->GetRelativePos(), aScaleWidth, aScaleHeight); + } } - // ToDo: Adapt object skew and rotation to bHiddenAsZero=false, tdf#137033 // We only write the end address if we want the shape to resize with the cell if ( rShape.bResizeWithCell && @@ -3530,9 +3596,31 @@ void ScXMLExport::WriteShapes(const ScMyCell& rMyCell) AddAttribute(XML_NAMESPACE_TABLE, XML_END_Y, sBuffer.makeStringAndClear()); } - if (bNegativePage) - aPoint.X = 2 * rShape.xShape->getPosition().X + rShape.xShape->getSize().Width - - aPoint.X; + // Correct above calculated reference point for some cases: + // a) For a RTL-sheet translate from matrix is not suitable, because the shape + // from xml (which is always LTR) is not mirrored to negative page but shifted. + // b) In case of horizontal mirrored, 'resize with cell' anchored custom shape, translate + // has wrong values. FixMe: Why is translate wrong? + // c) Measure lines do not use transformation matrix but use start and end point directly. + ScDrawObjData* pNRObjData = nullptr; + if (pObj && bNegativePage + && rShape.xShape->getShapeType() == "com.sun.star.drawing.MeasureShape") + { + // invers of shift when import + tools::Rectangle aSnapRect = pObj->GetSnapRect(); + aPoint.X = aSnapRect.Left() + aSnapRect.Right() - aPoint.X; + } + else if (pObj && (pNRObjData = ScDrawLayer::GetNonRotatedObjData(pObj)) + && ((rShape.bResizeWithCell && pObj->GetObjIdentifier() == OBJ_CUSTOMSHAPE + && static_cast<SdrObjCustomShape*>(pObj)->IsMirroredX()) + || bNegativePage)) + { + //In these cases we set reference Point = matrix translate - startOffset. + awt::Point aMatrixTranslate = rShape.xShape->getPosition(); + aPoint.X = aMatrixTranslate.X - pNRObjData->maStartOffset.X(); + aPoint.Y = aMatrixTranslate.Y - pNRObjData->maStartOffset.Y(); + } + ExportShape(rShape.xShape, &aPoint); // Restore object geometry @@ -3556,11 +3644,23 @@ void ScXMLExport::WriteTableShapes() { if (pDoc->IsNegativePage(static_cast<SCTAB>(nCurrentTable))) { - awt::Point aPoint(rxShape->getPosition()); - awt::Size aSize(rxShape->getSize()); - aPoint.X += aPoint.X + aSize.Width; - aPoint.Y = 0; - ExportShape(rxShape, &aPoint); + // RTL-mirroring refers to snap rectangle, not to logic rectangle, therefore cannot use + // getPosition() and getSize(), but need property "FrameRect" from rxShape or + // GetSnapRect() from associated SdrObject. + uno::Reference<beans::XPropertySet> xShapeProp(rxShape, uno::UNO_QUERY); + awt::Rectangle aFrameRect; + if (xShapeProp.is() && (xShapeProp->getPropertyValue("FrameRect") >>= aFrameRect)) + { + // file format uses shape in LTR mode. newLeft = - oldRight = - (oldLeft + width). + // newTranslate = oldTranslate - refPoint, oldTranslate from transformation matrix, + // calculated in XMLShapeExport::exportShape common for all modules. + // oldTranslate.X = oldLeft ==> refPoint.X = 2 * oldLeft + width + awt::Point aRefPoint; + aRefPoint.X = 2 * aFrameRect.X + aFrameRect.Width - 1; + aRefPoint.Y = 0; + ExportShape(rxShape, &aRefPoint); + } + // else should not happen } else ExportShape(rxShape, nullptr); |