summaryrefslogtreecommitdiff
path: root/sc/source/filter/xml/xmlexprt.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sc/source/filter/xml/xmlexprt.cxx')
-rw-r--r--sc/source/filter/xml/xmlexprt.cxx180
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);