[Libreoffice-commits] core.git: Branch 'feature/cib_contract3753' - 70 commits - basic/qa basic/source config_host/config_qrcodegen.h.in config_host.mk.in configure.ac cui/source distro-configs/LibreOfficeOssFuzz.conf download.lst drawinglayer/source external/pdfium external/qrcodegen formula/source .gitreview include/oox include/sfx2 include/svtools include/svx include/unotools include/vcl include/xmloff lotuswordpro/source officecfg/registry oox/source readlicense_oo/license RepositoryExternal.mk sc/inc sc/qa sc/res sc/source sc/uiconfig sdext/source sd/qa sfx2/uiconfig solenv/flatpak-manifest.in svl/source svtools/source svx/source sw/CppunitTest_sw_core_crsr.mk sw/inc sw/Module_sw.mk sw/PythonTest_sw_python.mk sw/qa sw/source sw/uiconfig unotools/source vcl/inc vcl/Library_vcl.mk vcl/qa vcl/qt5 vcl/source vcl/unx writerfilter/source xmloff/source xmlsecurity/Library_xmlsecurity.mk xmlsecurity/qa xmlsecurity/source xmlsecurity/uiconfig xmlsecurity/workben
Michael Stahl (via logerrit)
logerrit at kemper.freedesktop.org
Mon Oct 5 12:16:16 UTC 2020
Rebased ref, commits from common ancestor:
commit f232ad20a020a85b1835cd6e3387113f629979b4
Author: Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Thu Oct 1 17:31:21 2020 +0200
Commit: Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Mon Oct 5 14:08:32 2020 +0200
sw: ODF import: convert the simplest sub-tables to rowspan tables
Before OOo 2.3, CWS swnewtable, Writer represented complex table
structures as sub-tables, i.e. <table:table table:is-sub-table="true">.
Try to convert these to the modern rowspan tables, which export to
non-ODF formats much easier.
There are some cases where the result is going to look different, or
where further work is required to adapt other things in the document;
leave these alone for now.
Change-Id: I6a6c497089ef886826484d2d723bf57c72f95b14
diff --git a/sw/inc/swtable.hxx b/sw/inc/swtable.hxx
index a373f561704f..b62c2567e2de 100644
--- a/sw/inc/swtable.hxx
+++ b/sw/inc/swtable.hxx
@@ -168,6 +168,7 @@ private:
void AdjustWidths( const long nOld, const long nNew );
void NewSetTabCols( Parm &rP, const SwTabCols &rNew, const SwTabCols &rOld,
const SwTableBox *pStart, bool bCurRowOnly );
+ void ConvertSubtableBox(sal_uInt16 const nRow, sal_uInt16 const nBox);
public:
@@ -340,6 +341,9 @@ public:
#endif
bool HasLayout() const;
+
+ bool CanConvertSubtables() const;
+ void ConvertSubtables();
};
/// SwTableLine is one table row in the document model.
diff --git a/sw/source/core/table/swnewtable.cxx b/sw/source/core/table/swnewtable.cxx
index 04a2509b1e37..892b31e807cc 100644
--- a/sw/source/core/table/swnewtable.cxx
+++ b/sw/source/core/table/swnewtable.cxx
@@ -21,6 +21,7 @@
#include <tblsel.hxx>
#include <tblrwcl.hxx>
#include <ndtxt.hxx>
+#include <ndole.hxx>
#include <node.hxx>
#include <UndoTable.hxx>
#include <pam.hxx>
@@ -30,8 +31,14 @@
#include <fmtfsize.hxx>
#include <doc.hxx>
#include <IDocumentUndoRedo.hxx>
+#include <IDocumentChartDataProviderAccess.hxx>
#include <IDocumentContentOperations.hxx>
+#include <IDocumentFieldsAccess.hxx>
#include <IDocumentLayoutAccess.hxx>
+#include <IDocumentMarkAccess.hxx>
+#include <IDocumentRedlineAccess.hxx>
+#include <fmtfld.hxx>
+#include <ftnidx.hxx>
#include <cstdlib>
#include <vector>
#include <set>
@@ -2089,6 +2096,286 @@ void SwTable::CleanUpBottomRowSpan( sal_uInt16 nDelLines )
}
}
+/**
+ This is kind of similar to InsertSpannedRow()/InsertRow() but that one would
+ recursively copy subtables, which would kind of defeat the purpose;
+ this function directly moves the subtable rows's cells into the newly
+ created rows. For the non-subtable boxes, covered-cells are created.
+
+ Outer row heights are adjusted to match the inner row heights, and the
+ last row's height is tweaked to ensure the sum of the heights is at least
+ the original outer row's minimal height.
+
+ Inner row backgrounds are copied to its cells, if they lack a background.
+
+ This currently can't handle more than 1 subtable in a row;
+ the inner rows of all subtables would need to be sorted by their height
+ to create the correct outer row structure, which is tricky and probably
+ requires a layout for the typical variable-height case.
+
+ */
+void SwTable::ConvertSubtableBox(sal_uInt16 const nRow, sal_uInt16 const nBox)
+{
+ SwDoc *const pDoc(GetFrameFormat()->GetDoc());
+ SwTableLine *const pSourceLine(GetTabLines()[nRow]);
+ SwTableBox *const pSubTableBox(pSourceLine->GetTabBoxes()[nBox]);
+ assert(!pSubTableBox->GetTabLines().empty());
+ // are relative (%) heights possible? apparently not
+ SwFormatFrameSize const outerSize(pSourceLine->GetFrameFormat()->GetFrameSize());
+ long minHeights(0);
+ {
+ SwFormatFrameSize const* pSize(nullptr);
+ SwFrameFormat const& rSubLineFormat(*pSubTableBox->GetTabLines()[0]->GetFrameFormat());
+ if (rSubLineFormat.GetItemState(RES_FRM_SIZE, true,
+ reinterpret_cast<SfxPoolItem const**>(&pSize)) == SfxItemState::SET)
+ { // for first row, apply height from inner row to outer row.
+ // in case the existing outer row height was larger than the entire
+ // subtable, the last inserted row needs to be tweaked (below)
+ pSourceLine->GetFrameFormat()->SetFormatAttr(*pSize);
+ if (pSize->GetHeightSizeType() != ATT_VAR_SIZE)
+ {
+ minHeights += pSize->GetHeight();
+ }
+ }
+ }
+ for (size_t i = 1; i < pSubTableBox->GetTabLines().size(); ++i)
+ {
+ SwTableLine *const pSubLine(pSubTableBox->GetTabLines()[i]);
+ SwTableLine *const pNewLine = new SwTableLine(
+ static_cast<SwTableLineFormat*>(pSourceLine->GetFrameFormat()),
+ pSourceLine->GetTabBoxes().size() - 1 + pSubLine->GetTabBoxes().size(),
+ nullptr);
+ SwFrameFormat const& rSubLineFormat(*pSubLine->GetFrameFormat());
+ SwFormatFrameSize const* pSize(nullptr);
+ if (rSubLineFormat.GetItemState(RES_FRM_SIZE, true,
+ reinterpret_cast<SfxPoolItem const**>(&pSize)) == SfxItemState::SET)
+ { // for rows 2..N, copy inner row height to outer row
+ pNewLine->ClaimFrameFormat();
+ pNewLine->GetFrameFormat()->SetFormatAttr(*pSize);
+ if (pSize->GetHeightSizeType() != ATT_VAR_SIZE)
+ {
+ minHeights += pSize->GetHeight();
+ }
+ }
+ // ensure the sum of the lines is at least as high as the outer line was
+ if (i == pSubTableBox->GetTabLines().size() - 1
+ && outerSize.GetHeightSizeType() != ATT_VAR_SIZE
+ && minHeights < outerSize.GetHeight())
+ {
+ SwFormatFrameSize lastSize(pNewLine->GetFrameFormat()->GetFrameSize());
+ lastSize.SetHeight(lastSize.GetHeight() + outerSize.GetHeight() - minHeights);
+ if (lastSize.GetHeightSizeType() == ATT_VAR_SIZE)
+ {
+ lastSize.SetHeightSizeType(ATT_MIN_SIZE);
+ }
+ pNewLine->GetFrameFormat()->SetFormatAttr(lastSize);
+ }
+ SfxPoolItem const* pRowBrush(nullptr);
+ rSubLineFormat.GetItemState(RES_BACKGROUND, true, &pRowBrush);
+ GetTabLines().insert(GetTabLines().begin() + nRow + i, pNewLine);
+ for (size_t j = 0; j < pSourceLine->GetTabBoxes().size(); ++j)
+ {
+ if (j == nBox)
+ {
+ for (size_t k = 0; k < pSubLine->GetTabBoxes().size(); ++k)
+ {
+ // move box k to new outer row
+ SwTableBox *const pSourceBox(pSubLine->GetTabBoxes()[k]);
+ assert(pSourceBox->getRowSpan() == 1);
+ // import filter (xmltbli.cxx) converts all box widths to absolute
+ assert(pSourceBox->GetFrameFormat()->GetFrameSize().GetWidthPercent() == 0);
+ ::InsTableBox(pDoc, GetTableNode(), pNewLine,
+ static_cast<SwTableBoxFormat*>(pSourceBox->GetFrameFormat()),
+ pSourceBox, j+k, 1);
+ // insert dummy text node...
+ pDoc->GetNodes().MakeTextNode(
+ SwNodeIndex(*pSourceBox->GetSttNd(), +1),
+ pDoc->GetDfltTextFormatColl());
+ SwNodeRange content(*pSourceBox->GetSttNd(), +2,
+ *pSourceBox->GetSttNd()->EndOfSectionNode());
+ SwTableBox *const pNewBox(pNewLine->GetTabBoxes()[j+k]);
+ SwNodeIndex insPos(*pNewBox->GetSttNd(), 1);
+ // MoveNodes would delete the box SwStartNode/SwEndNode
+ // without the dummy node
+#if 0
+ pDoc->GetNodes().MoveNodes(content, pDoc->GetNodes(), insPos, false);
+#else
+ pDoc->getIDocumentContentOperations().MoveNodeRange(content, insPos, SwMoveFlags::NO_DELFRMS);
+#endif
+ // delete the empty node that was bundled in the new box
+ pDoc->GetNodes().Delete(insPos);
+ if (pRowBrush)
+ {
+ SfxPoolItem const* pCellBrush(nullptr);
+ if (pNewBox->GetFrameFormat()->GetItemState(RES_BACKGROUND, true, &pCellBrush) != SfxItemState::SET)
+ { // set inner row background on inner cell
+ pNewBox->ClaimFrameFormat();
+ pNewBox->GetFrameFormat()->SetFormatAttr(*pRowBrush);
+ }
+ }
+ // assume that the borders can be left as they are, because
+ // lines don't have borders, only boxes do
+ }
+ }
+ else
+ {
+ // insert covered cell for box j
+ SwTableBox *const pSourceBox(pSourceLine->GetTabBoxes()[j]);
+ assert(pSourceBox->GetTabLines().empty()); // checked for that
+ sal_uInt16 const nInsPos(j < nBox ? j : j + pSubLine->GetTabBoxes().size() - 1);
+ ::InsTableBox(pDoc, GetTableNode(), pNewLine,
+ static_cast<SwTableBoxFormat*>(pSourceBox->GetFrameFormat()),
+ pSourceBox, nInsPos, 1);
+ // adjust row span:
+ // N rows in subtable, N-1 rows inserted:
+ // -1 -> -N ; -(N-1) ... -1
+ // -2 -> -(N+1) ; -N .. -2
+ // 1 -> N ; -(N-1) .. -1
+ // 2 -> N+1 ; -N .. -2
+ long newSourceRowSpan(pSourceBox->getRowSpan());
+ long newBoxRowSpan;
+ if (newSourceRowSpan < 0)
+ {
+ newSourceRowSpan -= pSubTableBox->GetTabLines().size() - 1;
+ newBoxRowSpan = newSourceRowSpan + i;
+ }
+ else
+ {
+ newSourceRowSpan += pSubTableBox->GetTabLines().size() - 1;
+ newBoxRowSpan = -(newSourceRowSpan - sal::static_int_cast<long>(i));
+ }
+ pNewLine->GetTabBoxes()[nInsPos]->setRowSpan(newBoxRowSpan);
+ if (i == pSubTableBox->GetTabLines().size() - 1)
+ { // only last iteration
+ pSourceBox->setRowSpan(newSourceRowSpan);
+ }
+ }
+ }
+ }
+ // delete inner rows 2..N
+ while (1 < pSubTableBox->GetTabLines().size())
+ {
+ // careful: the last box deletes pSubLine!
+ SwTableLine *const pSubLine(pSubTableBox->GetTabLines()[1]);
+ for (size_t j = pSubLine->GetTabBoxes().size(); 0 < j; --j)
+ {
+ SwTableBox *const pBox(pSubLine->GetTabBoxes()[0]);
+ DeleteBox_(*this, pBox, nullptr, false, false, nullptr);
+ }
+ }
+ // fix row spans in lines preceding nRow
+ lcl_ChangeRowSpan(*this, pSubTableBox->GetTabLines().size() - 1, nRow - 1, false);
+ // note: the first line of the inner table remains; caller will call
+ // GCLines() to remove it
+}
+
+bool SwTable::CanConvertSubtables() const
+{
+ for (SwTableLine const*const pLine : GetTabLines())
+ {
+ bool haveSubtable(false);
+ for (SwTableBox const*const pBox : pLine->GetTabBoxes())
+ {
+ if (pBox->IsFormulaOrValueBox() == RES_BOXATR_FORMULA)
+ {
+ return false; // no table box formulas yet
+ }
+ if (!pBox->GetTabLines().empty())
+ {
+ if (haveSubtable)
+ { // can't handle 2 subtable in a row yet
+ return false;
+ }
+ haveSubtable = true;
+ for (SwTableLine const*const pInnerLine : pBox->GetTabLines())
+ {
+ // bitmap row background will look different
+ SwFrameFormat const& rRowFormat(*pInnerLine->GetFrameFormat());
+ std::shared_ptr<SvxBrushItem> pBrush(rRowFormat.makeBackgroundBrushItem());
+ assert(pBrush);
+ if (pBrush->GetGraphicObject() != nullptr)
+ {
+ /* TODO: all cells could override this?
+ for (SwTableBox & rInnerBox : rInnerLine.GetTabBoxes())
+ */
+ if (1 < pInnerLine->GetTabBoxes().size()) // except if only 1 cell?
+ {
+ return false;
+ }
+ }
+ for (SwTableBox const*const pInnerBox : pInnerLine->GetTabBoxes())
+ {
+ if (!pInnerBox->GetTabLines().empty())
+ {
+ return false; // nested subtable :(
+ }
+ }
+ }
+ }
+ }
+ }
+ // note: fields that refer to table cells may be *outside* the table,
+ // so the entire document needs to be imported before checking here
+ // (same for table box formulas and charts)
+ SwDoc *const pDoc(GetFrameFormat()->GetDoc());
+ SwFieldType const*const pTableFields(
+ pDoc->getIDocumentFieldsAccess().GetFieldType(SwFieldIds::Table, "", false));
+ SwIterator<SwFormatField, SwFieldType> aIter(*pTableFields);
+ if (aIter.First() != nullptr)
+ {
+ return false; // no formulas in fields yet
+ }
+ if (pDoc->GetAttrPool().GetItemCount2(RES_BOXATR_FORMULA) != 0)
+ {
+ return false; // no table box formulas yet
+ }
+ OUString const tableName(GetFrameFormat()->GetName());
+ SwNodeIndex temp(*pDoc->GetNodes().GetEndOfAutotext().StartOfSectionNode(), +1);
+ while (SwStartNode const*const pStartNode = temp.GetNode().GetStartNode())
+ {
+ ++temp;
+ SwOLENode const*const pOLENode(temp.GetNode().GetOLENode());
+ if (pOLENode && tableName == pOLENode->GetChartTableName())
+ { // there are charts that refer to this table
+ // presumably such charts would need to be adapted somehow?
+ return false;
+ }
+ temp.Assign(*pStartNode->EndOfSectionNode(), +1);
+ }
+ return true;
+}
+
+void SwTable::ConvertSubtables()
+{
+ for (size_t i = 0; i < GetTabLines().size(); ++i)
+ {
+ SwTableLine *const pLine(GetTabLines()[i]);
+ for (size_t j = 0; j < pLine->GetTabBoxes().size(); ++j)
+ {
+ SwTableBox *const pBox(pLine->GetTabBoxes()[j]);
+ SwTableLines & rInnerLines(pBox->GetTabLines());
+ if (!rInnerLines.empty())
+ {
+ ConvertSubtableBox(i, j);
+ }
+ }
+ }
+ GCLines();
+ m_bNewModel = true;
+#if 0
+ // note: outline nodes (and ordinary lists) are sorted by MoveNodes() itself
+ // (this could change order inside table of contents, but that's a
+ // really esoteric use-case)
+ // nodes were moved - sort marks, redlines, footnotes
+ SwDoc *const pDoc(GetFrameFormat()->GetDoc());
+ pDoc->getIDocumentMarkAccess()->assureSortedMarkContainers();
+ pDoc->getIDocumentRedlineAccess().GetRedlineTable().Resort();
+ pDoc->GetFootnoteIdxs().UpdateAllFootnote();
+#endif
+ // assume that there aren't any node indexes to the deleted box start/end nodes
+ CHECK_TABLE( *this )
+}
+
#ifdef DBG_UTIL
struct RowSpanCheck
diff --git a/sw/source/filter/xml/xmlimp.cxx b/sw/source/filter/xml/xmlimp.cxx
index 75766a7f8a64..68a72af1cb2f 100644
--- a/sw/source/filter/xml/xmlimp.cxx
+++ b/sw/source/filter/xml/xmlimp.cxx
@@ -967,6 +967,22 @@ void SwXMLImport::endDocument()
}
}
+#if 1
+ if (!pDoc) { pDoc = SwImport::GetDocFromXMLImport(*this); }
+ for (sal_uLong i = 0; i < pDoc->GetNodes().Count(); ++i)
+ {
+ if (SwTableNode *const pTableNode = pDoc->GetNodes()[i]->GetTableNode())
+ {
+ if (!pTableNode->GetTable().IsNewModel()
+ && pTableNode->GetTable().CanConvertSubtables())
+ {
+ pTableNode->GetTable().ConvertSubtables();
+ }
+ }
+ // don't skip to the end; nested tables could have subtables too...
+ }
+#endif
+
// delegate to parent: takes care of error handling
SvXMLImport::endDocument();
ClearTextImport();
commit 4730243d6ab1393de5cf84a22b33cef57cdf6cd2
Author: Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Thu Oct 1 17:29:06 2020 +0200
Commit: Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Mon Oct 5 12:57:28 2020 +0200
sw: SwTable::GCLines(): don't throw away row background
If there's a row background, and a cell in the row doesn't override it,
apply the row background to the cell.
Change-Id: I37cd33249d3ab66c898c537e3bc6bab067d6f74b
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/103772
Tested-by: Jenkins
Reviewed-by: Michael Stahl <michael.stahl at cib.de>
(cherry picked from commit e65b1ba0033e1adaa4135539bb7b34b28cbedd7c)
diff --git a/sw/source/core/doc/gctable.cxx b/sw/source/core/doc/gctable.cxx
index 493ef4248c91..1d5a2a4eed25 100644
--- a/sw/source/core/doc/gctable.cxx
+++ b/sw/source/core/doc/gctable.cxx
@@ -351,6 +351,21 @@ static bool lcl_MergeGCBox(SwTableBox* pTableBox, GCLinePara* pPara)
for( auto pTabBox : pCpyLine->GetTabBoxes() )
pTabBox->SetUpper( pInsLine );
+ SfxPoolItem const* pRowBrush(nullptr);
+ pCpyLine->GetFrameFormat()->GetItemState(RES_BACKGROUND, true, &pRowBrush);
+ if (pRowBrush)
+ {
+ for (auto pBox : pCpyLine->GetTabBoxes())
+ {
+ SfxPoolItem const* pCellBrush(nullptr);
+ if (pBox->GetFrameFormat()->GetItemState(RES_BACKGROUND, true, &pCellBrush) != SfxItemState::SET)
+ { // set inner row background on inner cell
+ pBox->ClaimFrameFormat();
+ pBox->GetFrameFormat()->SetFormatAttr(*pRowBrush);
+ }
+ }
+ }
+
// remove the old box from its parent line
it = pInsLine->GetTabBoxes().erase( it );
// insert the nested line's boxes in its place
commit 3b7546e0c95b8253bf37e31577d8a0894e926dba
Author: Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Thu Oct 1 17:26:43 2020 +0200
Commit: Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Mon Oct 5 12:57:28 2020 +0200
sw: improve comments, dump rowspan to nodes.xml
Change-Id: Ifcd011f6d55ac534c449050d07009680dcd71d51
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/103771
Tested-by: Jenkins
Reviewed-by: Michael Stahl <michael.stahl at cib.de>
(cherry picked from commit 309868c32f00e5ca045f941deafb5216aad2538c)
diff --git a/sw/inc/swtable.hxx b/sw/inc/swtable.hxx
index a0deaf01e892..a373f561704f 100644
--- a/sw/inc/swtable.hxx
+++ b/sw/inc/swtable.hxx
@@ -310,7 +310,9 @@ public:
// Search in format for registered table.
static SwTable * FindTable( SwFrameFormat const*const pFormat );
- // Clean up structure a bit.
+ // Clean up structure of subtables a bit:
+ // convert row with 1 box with subtable; box with subtable with 1 row;
+ // by removing the subtable (both recursively)
void GCLines();
// Returns the table node via m_TabSortContentBoxes or pTableNode.
diff --git a/sw/inc/tblsel.hxx b/sw/inc/tblsel.hxx
index 0639db32f72e..cc353cc424bb 100644
--- a/sw/inc/tblsel.hxx
+++ b/sw/inc/tblsel.hxx
@@ -160,8 +160,8 @@ class FndBox_
FndLines_t m_Lines;
FndLine_* const m_pUpper;
- SwTableLine *m_pLineBefore; // For deleting/restoring the layout.
- SwTableLine *m_pLineBehind;
+ SwTableLine *m_pLineBefore; ///< For deleting/restoring the layout.
+ SwTableLine *m_pLineBehind; ///< For deleting/restoring the layout.
FndBox_(FndBox_ const&) = delete;
FndBox_& operator=(FndBox_ const&) = delete;
@@ -224,6 +224,10 @@ struct FndPara
: rBoxes(rPara.rBoxes), pFndLine(pFL), pFndBox(rPara.pFndBox) {}
};
+/** This creates a structure mirroring the SwTable structure that contains all
+ rows and non-leaf boxes (as pointers to SwTableBox/SwTableLine, not copies),
+ plus the leaf boxes that are selected by pFndPara->rBoxes
+ */
SW_DLLPUBLIC void ForEach_FndLineCopyCol(SwTableLines& rLines, FndPara* pFndPara );
#endif // INCLUDED_SW_INC_TBLSEL_HXX
diff --git a/sw/source/core/docnode/node.cxx b/sw/source/core/docnode/node.cxx
index 955e113f2768..61e8bd112d23 100644
--- a/sw/source/core/docnode/node.cxx
+++ b/sw/source/core/docnode/node.cxx
@@ -985,6 +985,8 @@ void SwStartNode::dumpAsXml(xmlTextWriterPtr pWriter) const
}
else if (GetStartNodeType() == SwTableBoxStartNode)
{
+ if (SwTableBox* pBox = GetTableBox())
+ xmlTextWriterWriteAttribute(pWriter, BAD_CAST("rowspan"), BAD_CAST(OString::number(pBox->getRowSpan()).getStr()));
xmlTextWriterStartElement(pWriter, BAD_CAST("attrset"));
if (SwTableBox* pBox = GetTableBox())
pBox->GetFrameFormat()->GetAttrSet().dumpAsXml(pWriter);
commit 3713675467393b451b8dd7c1a68ba430eaee24f2
Author: Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Fri Sep 18 11:47:56 2020 +0200
Commit: Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Fri Oct 2 16:39:09 2020 +0200
tdf#136620 tdf#136708 filter,oox,sw: fix export of 2 different wraps
This reverts commit 2cb90a5c87fe46737c8d840967d8836284f92ffd.
Revert the change to EscherPropertyContainer, which was completely
bogus, based on pre-existing bogus code in VMLExport::Commit().
The problem is that ESCHER_Wrap values are for wrapping text *inside* a
text box, which is "mso-wrap-style" in VML, whereas VML's w10:wrap
element defines how text wraps *around* a shape, doesn't exist as an
ESCHER property and is specific to Word formats.
Instead, export the w10:wrap element in VMLExport::EndShape().
This has 2 callers, WriteActiveXControl() and writeVMLDrawing().
Furthermore the value "none" wasn't written for WrapTextMode_THROUGH,
which caused the wrap element to be omitted in that case.
Change-Id: Id4a01fcb2ea73fa9bef4ee8769b5e0680e059f15
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/103009
Tested-by: Jenkins
Reviewed-by: Michael Stahl <michael.stahl at cib.de>
(cherry picked from commit fdc8590032b292dcb8152b328401e591fea642a4)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/103090
Reviewed-by: Caolán McNamara <caolanm at redhat.com>
(cherry picked from commit c54d697e2ac379d4b1a3ff5acb6f06bff30cadd6)
diff --git a/filter/source/msfilter/escherex.cxx b/filter/source/msfilter/escherex.cxx
index a2071237deb7..f04043e9156a 100644
--- a/filter/source/msfilter/escherex.cxx
+++ b/filter/source/msfilter/escherex.cxx
@@ -66,7 +66,6 @@
#include <com/sun/star/drawing/FlagSequence.hpp>
#include <com/sun/star/drawing/PolygonFlags.hpp>
#include <com/sun/star/text/WritingMode.hpp>
-#include <com/sun/star/text/WrapTextMode.hpp>
#include <com/sun/star/drawing/TextVerticalAdjust.hpp>
#include <com/sun/star/drawing/TextHorizontalAdjust.hpp>
#include <com/sun/star/drawing/EnhancedCustomShapeSegment.hpp>
@@ -700,10 +699,6 @@ void EscherPropertyContainer::CreateTextProperties(
bool bWordWrap ( false );
bool bAutoGrowSize ( false );
- uno::Any aTextWrap;
-
- EscherPropertyValueHelper::GetPropertyValue(aTextWrap, rXPropSet, "TextWrap", true);
-
if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, "TextWritingMode", true ) )
aAny >>= eWM;
if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, "TextVerticalAdjust", true ) )
@@ -842,21 +837,6 @@ void EscherPropertyContainer::CreateTextProperties(
nTextAttr |= 0x20002;
}
}
-
- if (aTextWrap.hasValue())
- { // explicit text wrap overrides whatever was inferred previously
- switch (aTextWrap.get<text::WrapTextMode>())
- {
- case text::WrapTextMode_THROUGH:
- eWrapMode = ESCHER_WrapNone;
- break;
- // in theory there are 3 more Escher_Wrap, but [MS-ODRAW] says they are useless
- default:
- eWrapMode = ESCHER_WrapSquare;
- break;
- }
- }
-
AddOpt( ESCHER_Prop_dxTextLeft, nLeft * 360 );
AddOpt( ESCHER_Prop_dxTextRight, nRight * 360 );
AddOpt( ESCHER_Prop_dyTextTop, nTop * 360 );
diff --git a/include/oox/export/vmlexport.hxx b/include/oox/export/vmlexport.hxx
index 7c2d3a62da6f..3736420756a6 100644
--- a/include/oox/export/vmlexport.hxx
+++ b/include/oox/export/vmlexport.hxx
@@ -80,8 +80,9 @@ class OOX_DLLPUBLIC VMLExport : public EscherEx
/// Parent exporter, used for text callback.
VMLTextExport* m_pTextExport;
- /// Anchoring.
+ /// Anchoring - Writer specific properties
sal_Int16 m_eHOri, m_eVOri, m_eHRel, m_eVRel;
+ std::unique_ptr<sax_fastparser::FastAttributeList> m_pWrapAttrList;
bool m_bInline; // css::text::TextContentAnchorType_AS_CHARACTER
/// The object we're exporting.
@@ -139,7 +140,9 @@ public:
/// Call this when you need to export the object as VML.
OString const & AddSdrObject( const SdrObject& rObj, sal_Int16 eHOri = -1,
sal_Int16 eVOri = -1, sal_Int16 eHRel = -1,
- sal_Int16 eVRel = -1, const bool bOOxmlExport = false );
+ sal_Int16 eVRel = -1,
+ std::unique_ptr<sax_fastparser::FastAttributeList> m_pWrapAttrList = nullptr,
+ const bool bOOxmlExport = false );
OString const & AddInlineSdrObject( const SdrObject& rObj, const bool bOOxmlExport );
virtual void AddSdrObjectVMLObject( const SdrObject& rObj) override;
static bool IsWaterMarkShape(const OUString& rStr);
diff --git a/oox/source/export/vmlexport.cxx b/oox/source/export/vmlexport.cxx
index ee93cf32bd27..2009d9ccf055 100644
--- a/oox/source/export/vmlexport.cxx
+++ b/oox/source/export/vmlexport.cxx
@@ -421,11 +421,15 @@ void VMLExport::Commit( EscherPropertyContainer& rProps, const tools::Rectangle&
case ESCHER_WrapSquare:
case ESCHER_WrapByPoints: pWrapType = "square"; break; // these two are equivalent according to the docu
case ESCHER_WrapNone: pWrapType = "none"; break;
- case ESCHER_WrapTopBottom: pWrapType = "topAndBottom"; break;
- case ESCHER_WrapThrough: pWrapType = "through"; break;
+ case ESCHER_WrapTopBottom:
+ case ESCHER_WrapThrough:
+ break; // last two are *undefined* in MS-ODRAW, don't exist in VML
}
if ( pWrapType )
- m_pSerializer->singleElementNS(XML_w10, XML_wrap, XML_type, pWrapType);
+ {
+ m_ShapeStyle.append(";mso-wrap-style:");
+ m_ShapeStyle.append(pWrapType);
+ }
}
bAlreadyWritten[ ESCHER_Prop_WrapText ] = true;
break;
@@ -1477,18 +1481,27 @@ void VMLExport::EndShape( sal_Int32 nShapeElement )
m_pSerializer->endElementNS(XML_v, XML_textbox);
}
+ if (m_pWrapAttrList)
+ {
+ sax_fastparser::XFastAttributeListRef const pWrapAttrList(m_pWrapAttrList.release());
+ m_pSerializer->singleElementNS(XML_w10, XML_wrap, pWrapAttrList);
+ }
+
// end of the shape
m_pSerializer->endElementNS( XML_v, nShapeElement );
}
}
-OString const & VMLExport::AddSdrObject( const SdrObject& rObj, sal_Int16 eHOri, sal_Int16 eVOri, sal_Int16 eHRel, sal_Int16 eVRel, const bool bOOxmlExport )
+OString const & VMLExport::AddSdrObject( const SdrObject& rObj, sal_Int16 eHOri, sal_Int16 eVOri, sal_Int16 eHRel, sal_Int16 eVRel,
+ std::unique_ptr<FastAttributeList> pWrapAttrList,
+ const bool bOOxmlExport )
{
m_pSdrObject = &rObj;
m_eHOri = eHOri;
m_eVOri = eVOri;
m_eHRel = eHRel;
m_eVRel = eVRel;
+ m_pWrapAttrList = std::move(pWrapAttrList);
m_bInline = false;
EscherEx::AddSdrObject(rObj, bOOxmlExport);
return m_sShapeId;
@@ -1501,6 +1514,7 @@ OString const & VMLExport::AddInlineSdrObject( const SdrObject& rObj, const bool
m_eVOri = -1;
m_eHRel = -1;
m_eVRel = -1;
+ m_pWrapAttrList.reset();
m_bInline = true;
EscherEx::AddSdrObject(rObj, bOOxmlExport);
return m_sShapeId;
diff --git a/sc/source/filter/xcl97/xcl97rec.cxx b/sc/source/filter/xcl97/xcl97rec.cxx
index 4a4656f57a94..58a4045cd7dd 100644
--- a/sc/source/filter/xcl97/xcl97rec.cxx
+++ b/sc/source/filter/xcl97/xcl97rec.cxx
@@ -59,6 +59,8 @@
#include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
#include <com/sun/star/chart2/XChartTypeContainer.hpp>
#include <com/sun/star/chart2/XChartDocument.hpp>
+
+#include <sax/fastattribs.hxx>
#include <oox/token/tokens.hxx>
#include <oox/token/namespaces.hxx>
#include <oox/token/relationship.hxx>
diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx
index 4256c8cf9cba..270ab6fe964f 100644
--- a/sw/source/filter/ww8/docxattributeoutput.cxx
+++ b/sw/source/filter/ww8/docxattributeoutput.cxx
@@ -5347,10 +5347,14 @@ void DocxAttributeOutput::WriteActiveXControl(const SdrObject* pObject, const Sw
{
const SwFormatHoriOrient& rHoriOri = rFrameFormat.GetHoriOrient();
const SwFormatVertOrient& rVertOri = rFrameFormat.GetVertOrient();
+ SwFormatSurround const& rSurround(rFrameFormat.GetSurround());
+ std::unique_ptr<sax_fastparser::FastAttributeList> pAttrList(docx::SurroundToVMLWrap(rSurround));
sShapeId = m_rExport.VMLExporter().AddSdrObject(*pObject,
rHoriOri.GetHoriOrient(), rVertOri.GetVertOrient(),
rHoriOri.GetRelationOrient(),
- rVertOri.GetRelationOrient(), true);
+ rVertOri.GetRelationOrient(),
+ std::move(pAttrList),
+ true);
}
// Restore default values
m_rExport.VMLExporter().SetSkipwzName(false);
@@ -8352,43 +8356,64 @@ void DocxAttributeOutput::FormatULSpace( const SvxULSpaceItem& rULSpace )
}
}
-void DocxAttributeOutput::FormatSurround( const SwFormatSurround& rSurround )
+namespace docx {
+
+std::unique_ptr<FastAttributeList> SurroundToVMLWrap(SwFormatSurround const& rSurround)
{
- if (m_rExport.SdrExporter().getTextFrameSyntax())
+ FastAttributeList * pAttrList(nullptr);
+ OString sType;
+ OString sSide;
+ switch (rSurround.GetSurround())
+ {
+ case css::text::WrapTextMode_NONE:
+ sType = "topAndBottom";
+ break;
+ case css::text::WrapTextMode_PARALLEL:
+ sType = "square";
+ break;
+ case css::text::WrapTextMode_DYNAMIC:
+ sType = "square";
+ sSide = "largest";
+ break;
+ case css::text::WrapTextMode_LEFT:
+ sType = "square";
+ sSide = "left";
+ break;
+ case css::text::WrapTextMode_RIGHT:
+ sType = "square";
+ sSide = "right";
+ break;
+ case css::text::WrapTextMode_THROUGH:
+ /* empty type and side means through */
+ default:
+ sType = "none";
+ break;
+ }
+ if (!sType.isEmpty() || !sSide.isEmpty())
{
- OString sType, sSide;
- switch (rSurround.GetSurround())
+ pAttrList = FastSerializerHelper::createAttrList();
+ if (!sType.isEmpty())
{
- case css::text::WrapTextMode_NONE:
- sType = "topAndBottom";
- break;
- case css::text::WrapTextMode_PARALLEL:
- sType = "square";
- break;
- case css::text::WrapTextMode_DYNAMIC:
- sType = "square";
- sSide = "largest";
- break;
- case css::text::WrapTextMode_LEFT:
- sType = "square";
- sSide = "left";
- break;
- case css::text::WrapTextMode_RIGHT:
- sType = "square";
- sSide = "right";
- break;
- case css::text::WrapTextMode_THROUGH:
- /* empty type and side means through */
- default:
- break;
+ pAttrList->add(XML_type, sType);
+ }
+ if (!sSide.isEmpty())
+ {
+ pAttrList->add(XML_side, sSide);
}
- if (!sType.isEmpty() || !sSide.isEmpty())
+ }
+ return std::unique_ptr<FastAttributeList>(pAttrList);
+}
+
+} // namespace docx
+
+void DocxAttributeOutput::FormatSurround( const SwFormatSurround& rSurround )
+{
+ if (m_rExport.SdrExporter().getTextFrameSyntax())
+ {
+ std::unique_ptr<FastAttributeList> pAttrList(docx::SurroundToVMLWrap(rSurround));
+ if (pAttrList)
{
- m_rExport.SdrExporter().setFlyWrapAttrList(FastSerializerHelper::createAttrList());
- if (!sType.isEmpty())
- m_rExport.SdrExporter().getFlyWrapAttrList()->add(XML_type, sType);
- if (!sSide.isEmpty())
- m_rExport.SdrExporter().getFlyWrapAttrList()->add(XML_side, sSide);
+ m_rExport.SdrExporter().setFlyWrapAttrList(pAttrList.release());
}
}
else if (m_rExport.SdrExporter().getDMLTextFrameSyntax())
diff --git a/sw/source/filter/ww8/docxattributeoutput.hxx b/sw/source/filter/ww8/docxattributeoutput.hxx
index 2b6e83dde2d6..b04ad82cff7e 100644
--- a/sw/source/filter/ww8/docxattributeoutput.hxx
+++ b/sw/source/filter/ww8/docxattributeoutput.hxx
@@ -1045,6 +1045,12 @@ struct DocxTableExportContext
~DocxTableExportContext() { m_rOutput.popFromTableExportContext(*this); }
};
+namespace docx {
+
+std::unique_ptr<sax_fastparser::FastAttributeList> SurroundToVMLWrap(SwFormatSurround const& rSurround);
+
+}
+
#endif // INCLUDED_SW_SOURCE_FILTER_WW8_DOCXATTRIBUTEOUTPUT_HXX
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/docxsdrexport.cxx b/sw/source/filter/ww8/docxsdrexport.cxx
index b86c64daeb24..a1f8b7b2f5be 100644
--- a/sw/source/filter/ww8/docxsdrexport.cxx
+++ b/sw/source/filter/ww8/docxsdrexport.cxx
@@ -827,9 +827,13 @@ void DocxSdrExport::writeVMLDrawing(const SdrObject* sdrObj, const SwFrameFormat
const SwFormatHoriOrient& rHoriOri = rFrameFormat.GetHoriOrient();
const SwFormatVertOrient& rVertOri = rFrameFormat.GetVertOrient();
+ SwFormatSurround const& rSurround(rFrameFormat.GetSurround());
+
+ std::unique_ptr<sax_fastparser::FastAttributeList> pAttrList(
+ docx::SurroundToVMLWrap(rSurround));
m_pImpl->getExport().VMLExporter().AddSdrObject(
*sdrObj, rHoriOri.GetHoriOrient(), rVertOri.GetVertOrient(), rHoriOri.GetRelationOrient(),
- rVertOri.GetRelationOrient(), true);
+ rVertOri.GetRelationOrient(), std::move(pAttrList), true);
m_pImpl->getSerializer()->endElementNS(XML_w, XML_pict);
}
commit 7dadf885b7598b13838ab3f18b87d12b8721a00d
Author: Samuel Mehrbrodt <Samuel.Mehrbrodt at cib.de>
AuthorDate: Thu Sep 10 09:45:08 2020 +0200
Commit: Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Fri Oct 2 16:39:08 2020 +0200
.gitreview: Update default branch
Change-Id: Ifcbcd3427508b468a9f1872b563c93760854becf
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/102364
Tested-by: Samuel Mehrbrodt <Samuel.Mehrbrodt at cib.de>
Reviewed-by: Samuel Mehrbrodt <Samuel.Mehrbrodt at cib.de>
diff --git a/.gitreview b/.gitreview
index 4cd7d22d9a83..2bbb2f4856f3 100644
--- a/.gitreview
+++ b/.gitreview
@@ -3,5 +3,4 @@ host=gerrit.libreoffice.org
port=29418
project=core
defaultremote=logerrit
-defaultbranch=libreoffice-6-4
-
+defaultbranch=feature/cib_contract3753
commit 05e5c6a5eac7700eada366e99e816d4a618bc556
Author: Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Wed Aug 26 17:08:00 2020 +0200
Commit: Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Fri Oct 2 16:39:08 2020 +0200
sw: DOCX export: don't export text frames as transparent
Writer paints text frames without fill still as opaque but nothing is
written in the DOCX file and Word by default treats DrawingML text frame
as transparent (the VML fallback is opaque though).
Change-Id: I0ce539ac8084c5047b4732abc5c199589ee369ee
diff --git a/sw/qa/extras/ooxmlexport/data/frame.fodt b/sw/qa/extras/ooxmlexport/data/frame.fodt
new file mode 100644
index 000000000000..c474b8de5e9e
--- /dev/null
+++ b/sw/qa/extras/ooxmlexport/data/frame.fodt
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<office:document xmlns:css3t="http://www.w3.org/TR/css3-text/" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rpt="http://openoffice.org/2005/report" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:d
r3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:grddl="http://www.w3.org/2003/g/data-view#" office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.text">
+ <office:font-face-decls>
+ <style:font-face style:name="Liberation Serif" svg:font-family="'Liberation Serif'" style:font-family-generic="roman" style:font-pitch="variable"/>
+ <style:font-face style:name="Lohit Devanagari" svg:font-family="'Lohit Devanagari'" style:font-family-generic="system" style:font-pitch="variable"/>
+ <style:font-face style:name="Source Han Serif CN" svg:font-family="'Source Han Serif CN'" style:font-family-generic="system" style:font-pitch="variable"/>
+ </office:font-face-decls>
+ <office:styles>
+ <style:default-style style:family="graphic">
+ <style:graphic-properties svg:stroke-color="#3465a4" draw:fill-color="#729fcf" fo:wrap-option="no-wrap" draw:shadow-offset-x="0.3cm" draw:shadow-offset-y="0.3cm" draw:start-line-spacing-horizontal="0.283cm" draw:start-line-spacing-vertical="0.283cm" draw:end-line-spacing-horizontal="0.283cm" draw:end-line-spacing-vertical="0.283cm" style:flow-with-text="false"/>
+ <style:paragraph-properties style:text-autospace="ideograph-alpha" style:line-break="strict" style:writing-mode="lr-tb" style:font-independent-line-spacing="false">
+ <style:tab-stops/>
+ </style:paragraph-properties>
+ <style:text-properties style:use-window-font-color="true" style:font-name="Liberation Serif" fo:font-size="12pt" fo:language="de" fo:country="DE" style:letter-kerning="true" style:font-name-asian="Source Han Serif CN" style:font-size-asian="10.5pt" style:language-asian="zh" style:country-asian="CN" style:font-name-complex="Lohit Devanagari" style:font-size-complex="12pt" style:language-complex="hi" style:country-complex="IN"/>
+ </style:default-style>
+ <style:default-style style:family="paragraph">
+ <style:paragraph-properties fo:orphans="2" fo:widows="2" fo:hyphenation-ladder-count="no-limit" style:text-autospace="ideograph-alpha" style:punctuation-wrap="hanging" style:line-break="strict" style:tab-stop-distance="1.251cm" style:writing-mode="page"/>
+ <style:text-properties style:use-window-font-color="true" style:font-name="Liberation Serif" fo:font-size="12pt" fo:language="de" fo:country="DE" style:letter-kerning="true" style:font-name-asian="Source Han Serif CN" style:font-size-asian="10.5pt" style:language-asian="zh" style:country-asian="CN" style:font-name-complex="Lohit Devanagari" style:font-size-complex="12pt" style:language-complex="hi" style:country-complex="IN" fo:hyphenate="false" fo:hyphenation-remain-char-count="2" fo:hyphenation-push-char-count="2"/>
+ </style:default-style>
+ <style:default-style style:family="table">
+ <style:table-properties table:border-model="collapsing"/>
+ </style:default-style>
+ <style:default-style style:family="table-row">
+ <style:table-row-properties fo:keep-together="auto"/>
+ </style:default-style>
+ <style:style style:name="Standard" style:family="paragraph" style:class="text"/>
+ <style:style style:name="Frame_20_contents" style:display-name="Frame contents" style:family="paragraph" style:parent-style-name="Standard" style:class="extra"/>
+ <style:style style:name="Frame" style:family="graphic">
+ <style:graphic-properties text:anchor-type="paragraph" svg:x="0cm" svg:y="0cm" fo:margin-left="0.201cm" fo:margin-right="0.201cm" fo:margin-top="0.201cm" fo:margin-bottom="0.201cm" style:wrap="parallel" style:number-wrapped-paragraphs="no-limit" style:wrap-contour="false" style:vertical-pos="top" style:vertical-rel="paragraph-content" style:horizontal-pos="center" style:horizontal-rel="paragraph-content" fo:padding="0.15cm" fo:border="0.06pt solid #000000"/>
+ </style:style>
+
+ <text:notes-configuration text:note-class="footnote" style:num-format="1" text:start-value="0" text:footnotes-position="page" text:start-numbering-at="document"/>
+ <text:notes-configuration text:note-class="endnote" style:num-format="i" text:start-value="0"/>
+ <text:linenumbering-configuration text:number-lines="false" text:offset="0.499cm" style:num-format="1" text:number-position="left" text:increment="5"/>
+ </office:styles>
+ <office:automatic-styles>
+ <style:style style:name="fr1" style:family="graphic" style:parent-style-name="Frame">
+ <style:graphic-properties style:wrap="run-through" style:number-wrapped-paragraphs="no-limit" style:vertical-pos="from-top" style:vertical-rel="paragraph" style:horizontal-pos="from-left" style:horizontal-rel="paragraph" draw:opacity="0%" draw:wrap-influence-on-position="once-concurrent"/>
+ </style:style>
+ <style:style style:name="fr2" style:family="graphic" style:parent-style-name="Frame">
+ <style:graphic-properties style:wrap="run-through" style:number-wrapped-paragraphs="no-limit" style:vertical-pos="from-top" style:vertical-rel="paragraph" style:horizontal-pos="from-left" style:horizontal-rel="paragraph" fo:background-color="#e8f2a1" draw:fill="solid" draw:fill-color="#e8f2a1" draw:wrap-influence-on-position="once-concurrent"/>
+ </style:style>
+ <style:style style:name="fr3" style:family="graphic" style:parent-style-name="Frame">
+ <style:graphic-properties style:run-through="foreground" style:wrap="run-through" style:number-wrapped-paragraphs="no-limit" style:vertical-pos="from-top" style:vertical-rel="paragraph" style:horizontal-pos="from-left" style:horizontal-rel="paragraph"/>
+ </style:style>
+ <style:page-layout style:name="pm1">
+ <style:page-layout-properties fo:page-width="21.001cm" fo:page-height="29.7cm" style:num-format="1" style:print-orientation="portrait" fo:margin-top="2cm" fo:margin-bottom="2cm" fo:margin-left="2cm" fo:margin-right="2cm" style:writing-mode="lr-tb" style:layout-grid-color="#c0c0c0" style:layout-grid-lines="20" style:layout-grid-base-height="0.706cm" style:layout-grid-ruby-height="0.353cm" style:layout-grid-mode="none" style:layout-grid-ruby-below="false" style:layout-grid-print="false" style:layout-grid-display="false" style:footnote-max-height="0cm">
+ <style:footnote-sep style:width="0.018cm" style:distance-before-sep="0.101cm" style:distance-after-sep="0.101cm" style:line-style="solid" style:adjustment="left" style:rel-width="25%" style:color="#000000"/>
+ </style:page-layout-properties>
+ <style:header-style/>
+ <style:footer-style/>
+ </style:page-layout>
+ </office:automatic-styles>
+ <office:master-styles>
+ <style:master-page style:name="Standard" style:page-layout-name="pm1"/>
+ </office:master-styles>
+ <office:body>
+ <office:text>
+ <text:p text:style-name="Standard"><draw:frame draw:style-name="fr3" draw:name="Frame1" text:anchor-type="paragraph" svg:x="0.87cm" svg:y="0cm" svg:width="2cm" draw:z-index="0">
+ <draw:text-box fo:min-height="0.499cm">
+ <text:p text:style-name="Frame_20_contents">opaque</text:p>
+ </draw:text-box>
+ </draw:frame><draw:frame draw:style-name="fr2" draw:name="Frame2" text:anchor-type="paragraph" svg:x="3.069cm" svg:y="0cm" svg:width="2cm" draw:z-index="1">
+ <draw:text-box fo:min-height="0.499cm">
+ <text:p text:style-name="Frame_20_contents">solid</text:p>
+ </draw:text-box>
+ </draw:frame><draw:frame draw:style-name="fr1" draw:name="Frame3" text:anchor-type="paragraph" svg:x="5.33cm" svg:y="0cm" svg:width="2.281cm" draw:z-index="2">
+ <draw:text-box fo:min-height="0.499cm">
+ <text:p text:style-name="Frame_20_contents">transparent</text:p>
+ </draw:text-box>
+ </draw:frame></text:p>
+ </office:text>
+ </office:body>
+</office:document>
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport6.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport6.cxx
index a8fe7ac73ea0..4318856bdae2 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport6.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport6.cxx
@@ -142,6 +142,29 @@ DECLARE_OOXMLEXPORT_TEST(testDMLSolidfillAlpha, "dml-solidfill-alpha.docx")
CPPUNIT_ASSERT_EQUAL(sal_Int16(20), getProperty<sal_Int16>(xShape, "FillTransparence"));
}
+DECLARE_OOXMLEXPORT_TEST(testDMLTextFrameNoFill, "frame.fodt")
+{
+ // Problem is that default text frame background is white in Writer and transparent in Word
+ uno::Reference<beans::XPropertySet> xShape1(getShape(1), uno::UNO_QUERY);
+// it is re-imported as solid
+// CPPUNIT_ASSERT_EQUAL(drawing::FillStyle_NONE, getProperty<drawing::FillStyle>(xShape1, "FillStyle"));
+ CPPUNIT_ASSERT_EQUAL(drawing::FillStyle_SOLID, getProperty<drawing::FillStyle>(xShape1, "FillStyle"));
+ CPPUNIT_ASSERT_EQUAL(sal_Int16(0), getProperty<sal_Int16>(xShape1, "FillTransparence"));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0xffffff), getProperty<sal_Int32>(xShape1, "FillColor"));
+
+ uno::Reference<beans::XPropertySet> xShape2(getShape(2), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(drawing::FillStyle_SOLID, getProperty<drawing::FillStyle>(xShape2, "FillStyle"));
+ CPPUNIT_ASSERT_EQUAL(sal_Int16(0), getProperty<sal_Int16>(xShape2, "FillTransparence"));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0xE8F2A1), getProperty<sal_Int32>(xShape2, "FillColor"));
+
+ uno::Reference<beans::XPropertySet> xShape3(getShape(3), uno::UNO_QUERY);
+// it is re-imported as solid
+// CPPUNIT_ASSERT_EQUAL(drawing::FillStyle_NONE, getProperty<drawing::FillStyle>(xShape3, "FillStyle"));
+ CPPUNIT_ASSERT_EQUAL(drawing::FillStyle_SOLID, getProperty<drawing::FillStyle>(xShape3, "FillStyle"));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0xffffff), getProperty<sal_Int32>(xShape3, "FillColor"));
+ CPPUNIT_ASSERT_EQUAL(sal_Int16(100), getProperty<sal_Int16>(xShape3, "FillTransparence"));
+}
+
DECLARE_OOXMLEXPORT_TEST(testDMLCustomGeometry, "dml-customgeometry-cubicbezier.docx")
{
diff --git a/sw/source/filter/ww8/attributeoutputbase.hxx b/sw/source/filter/ww8/attributeoutputbase.hxx
index 3d8daa633daa..38cd3f8893b3 100644
--- a/sw/source/filter/ww8/attributeoutputbase.hxx
+++ b/sw/source/filter/ww8/attributeoutputbase.hxx
@@ -668,6 +668,8 @@ public:
( ww8::WW8TableNodeInfoInner const * pTableTextNodeInfoInner,
long& rPageSize, bool& rRelBoxSize );
+ virtual void MaybeOutputBrushItem(SfxItemSet const&) { }
+
/// Exports the definition (image, size) of a single numbering picture bullet.
virtual void BulletDefinition(int /*nId*/, const Graphic& /*rGraphic*/, Size /*aSize*/) {}
diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx
index c03d971e8fdc..4256c8cf9cba 100644
--- a/sw/source/filter/ww8/docxattributeoutput.cxx
+++ b/sw/source/filter/ww8/docxattributeoutput.cxx
@@ -90,9 +90,11 @@
#include <editeng/editobj.hxx>
#include <editeng/keepitem.hxx>
#include <svx/xfillit0.hxx>
+#include <svx/xflclit.hxx>
#include <svx/xflgrit.hxx>
#include <svx/fmglob.hxx>
#include <svx/svdouno.hxx>
+#include <svx/unobrushitemhelper.hxx>
#include <svl/grabbagitem.hxx>
#include <sfx2/sfxbasemodel.hxx>
#include <tools/datetimeutils.hxx>
@@ -5822,6 +5824,27 @@ oox::drawingml::DrawingML& DocxAttributeOutput::GetDrawingML()
return m_rDrawingML;
}
+void DocxAttributeOutput::MaybeOutputBrushItem(SfxItemSet const& rSet)
+{
+ const XFillStyleItem* pXFillStyleItem(rSet.GetItem<XFillStyleItem>(XATTR_FILLSTYLE));
+
+ if ((pXFillStyleItem && pXFillStyleItem->GetValue() != drawing::FillStyle_NONE)
+ || !m_rExport.SdrExporter().getDMLTextFrameSyntax())
+ {
+ return;
+ }
+
+ // sw text frames are opaque by default, even with fill none!
+ std::unique_ptr<SfxItemSet> const pClone(rSet.Clone());
+ XFillColorItem const aColor(OUString(), COL_WHITE);
+ pClone->Put(aColor);
+ // call getSvxBrushItemForSolid - this also takes XFillTransparenceItem into account
+ XFillStyleItem const aSolid(drawing::FillStyle_SOLID);
+ pClone->Put(aSolid);
+ auto const pBrush(getSvxBrushItemFromSourceSet(*pClone, RES_BACKGROUND));
+ FormatBackground(*pBrush);
+}
+
/// Functor to do case-insensitive ordering of OUString instances.
struct OUStringIgnoreCase
{
@@ -8615,6 +8638,7 @@ void DocxAttributeOutput::FormatBox( const SvxBoxItem& rBox )
{
if (m_rExport.SdrExporter().getDMLTextFrameSyntax())
{
+ // ugh, exporting fill here is quite some hack... this OutputItemSet abstraction is quite leaky
// <a:gradFill> should be before <a:ln>.
const SfxPoolItem* pItem = GetExport().HasItem(XATTR_FILLSTYLE);
if (pItem)
diff --git a/sw/source/filter/ww8/docxattributeoutput.hxx b/sw/source/filter/ww8/docxattributeoutput.hxx
index a7733d62209b..2b6e83dde2d6 100644
--- a/sw/source/filter/ww8/docxattributeoutput.hxx
+++ b/sw/source/filter/ww8/docxattributeoutput.hxx
@@ -1013,6 +1013,7 @@ public:
virtual OUString FindRelId(BitmapChecksum nChecksum) override;
virtual void CacheRelId(BitmapChecksum nChecksum, const OUString& rRelId) override;
virtual oox::drawingml::DrawingML& GetDrawingML() override;
+ virtual void MaybeOutputBrushItem(SfxItemSet const&) override;
void BulletDefinition(int nId, const Graphic& rGraphic, Size aSize) override;
diff --git a/sw/source/filter/ww8/ww8atr.cxx b/sw/source/filter/ww8/ww8atr.cxx
index 87d6545d3391..b2c3b35d7ae1 100644
--- a/sw/source/filter/ww8/ww8atr.cxx
+++ b/sw/source/filter/ww8/ww8atr.cxx
@@ -332,6 +332,8 @@ void MSWordExportBase::OutputItemSet( const SfxItemSet& rSet, bool bPapFormat, b
ExportPoolItemsToCHP(aItems, nScript, nullptr);
if ( bPapFormat )
{
+ AttrOutput().MaybeOutputBrushItem(rSet);
+
for ( const auto& rItem : aItems )
{
pItem = rItem.second;
@@ -350,6 +352,13 @@ void MSWordExportBase::OutputItemSet( const SfxItemSet& rSet, bool bPapFormat, b
std::shared_ptr<SvxBrushItem> aBrush(getSvxBrushItemFromSourceSet(rSet, RES_BACKGROUND));
AttrOutput().OutputItem(*aBrush);
}
+#if 0
+ else
+ {
+ // note: *does not work* due to undocumented Word behavior: must be before a:ln element at least
+ AttrOutput().MaybeOutputBrushItem(rSet);
+ }
+#endif
}
m_pISet = nullptr; // for double attributes
}
commit 45a6300a4b6b268fce1bae884237dc2ce4d9bfe8
Author: Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Thu Aug 13 11:07:37 2020 +0200
Commit: Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Fri Oct 2 16:39:08 2020 +0200
sw: DOCX export: for soft-page-breaks, export continuous section breaks
When a section break is produced based on layout information such as
soft-page-break and follow page style, it's a bad idea to generate a
page break because the break may be in a different position in Word,
particularly if it was inside a fieldmark instruction.
It wouldn't work that well to ignore such page breaks in
MSWordExportBase::NeedTextNodeSplit() because then they would be created
when reaching the next node anyway, via FindPageDesc() fall-back to
layout.
Unfortunately this breaks the test tdf113849_evenAndOddHeaders.odt
which has a page style with follow-page-style on the first page; on
re-import from DOCX, the continuous section is now no longer converted
to a page break, so pages 2-3 have the wrong header/footers... this
seems impossible to fix in general in the import because it doesn't know
whether the continuous section break coincides with a layout page break.
Arguably this worked before mostly by accident? tdf#113849 isn't about
this afaics... Change the test file to have an explicit page break
there, which round-trips as intended. The real fix would be adding
continuous page style change to Writer i guess...
Change-Id: I00ffe3971607c148a7d5c13b89afb936718611c0
diff --git a/sw/qa/extras/ooxmlexport/data/tdf113849_evenAndOddHeaders.odt b/sw/qa/extras/ooxmlexport/data/tdf113849_evenAndOddHeaders.odt
index d9aa0ae23541..ae9b2af14ee7 100644
Binary files a/sw/qa/extras/ooxmlexport/data/tdf113849_evenAndOddHeaders.odt and b/sw/qa/extras/ooxmlexport/data/tdf113849_evenAndOddHeaders.odt differ
diff --git a/sw/source/filter/ww8/docxexport.cxx b/sw/source/filter/ww8/docxexport.cxx
index a212f4e5c9b8..74f06116484a 100644
--- a/sw/source/filter/ww8/docxexport.cxx
+++ b/sw/source/filter/ww8/docxexport.cxx
@@ -619,7 +619,8 @@ sal_uLong DocxExport::ReplaceCr( sal_uInt8 )
void DocxExport::PrepareNewPageDesc( const SfxItemSet* pSet,
const SwNode& rNd, const SwFormatPageDesc* pNewPgDescFormat,
- const SwPageDesc* pNewPgDesc )
+ const SwPageDesc* pNewPgDesc,
+ bool const bViaLayout)
{
// tell the attribute output that we are ready to write the section
// break [has to be output inside paragraph properties]
@@ -632,13 +633,12 @@ void DocxExport::PrepareNewPageDesc( const SfxItemSet* pSet,
if ( pNewPgDescFormat )
{
- m_pSections->AppendSection( *pNewPgDescFormat, rNd, pFormat, nLnNm );
+ m_pSections->AppendSection(*pNewPgDescFormat, rNd, pFormat, nLnNm, bViaLayout);
}
else if ( pNewPgDesc )
{
- m_pSections->AppendSection( pNewPgDesc, rNd, pFormat, nLnNm );
+ m_pSections->AppendSection(pNewPgDesc, rNd, pFormat, nLnNm, bViaLayout);
}
-
}
void DocxExport::InitStyles()
diff --git a/sw/source/filter/ww8/docxexport.hxx b/sw/source/filter/ww8/docxexport.hxx
index 00b908dc7efa..35e37a98ae39 100644
--- a/sw/source/filter/ww8/docxexport.hxx
+++ b/sw/source/filter/ww8/docxexport.hxx
@@ -218,7 +218,8 @@ protected:
virtual void PrepareNewPageDesc( const SfxItemSet* pSet,
const SwNode& rNd,
const SwFormatPageDesc* pNewPgDescFormat,
- const SwPageDesc* pNewPgDesc ) override;
+ const SwPageDesc* pNewPgDesc,
+ bool bViaLayout ) override;
private:
/// Setup pStyles and write styles.xml
diff --git a/sw/source/filter/ww8/rtfexport.cxx b/sw/source/filter/ww8/rtfexport.cxx
index 366cc18b3b0c..0e8733b48d63 100644
--- a/sw/source/filter/ww8/rtfexport.cxx
+++ b/sw/source/filter/ww8/rtfexport.cxx
@@ -948,7 +948,7 @@ ErrCode RtfExport::ExportDocument_Impl()
void RtfExport::PrepareNewPageDesc(const SfxItemSet* pSet, const SwNode& rNd,
const SwFormatPageDesc* pNewPgDescFormat,
- const SwPageDesc* pNewPgDesc)
+ const SwPageDesc* pNewPgDesc, bool const)
{
const SwSectionFormat* pFormat = GetSectionFormat(rNd);
const sal_uLong nLnNm = GetSectionLineNo(pSet, rNd);
diff --git a/sw/source/filter/ww8/rtfexport.hxx b/sw/source/filter/ww8/rtfexport.hxx
index 055aa50ff04e..527574ad701e 100644
--- a/sw/source/filter/ww8/rtfexport.hxx
+++ b/sw/source/filter/ww8/rtfexport.hxx
@@ -125,8 +125,8 @@ protected:
/// Get ready for a new section.
void PrepareNewPageDesc(const SfxItemSet* pSet, const SwNode& rNd,
- const SwFormatPageDesc* pNewPgDescFormat,
- const SwPageDesc* pNewPgDesc) override;
+ const SwFormatPageDesc* pNewPgDescFormat, const SwPageDesc* pNewPgDesc,
+ bool bViaLayout) override;
/// Return value indicates if an inherited outline numbering is suppressed.
bool DisallowInheritingOutlineNumbering(const SwFormat& rFormat) override;
diff --git a/sw/source/filter/ww8/wrtw8nds.cxx b/sw/source/filter/ww8/wrtw8nds.cxx
index 74783f3e7110..dc6abf17899e 100644
--- a/sw/source/filter/ww8/wrtw8nds.cxx
+++ b/sw/source/filter/ww8/wrtw8nds.cxx
@@ -2742,7 +2742,7 @@ void MSWordExportBase::OutputTextNode( SwTextNode& rNode )
// too.
const SwPageDesc* pNextPageDesc = m_pCurrentPageDesc->GetFollow();
assert(pNextPageDesc);
- PrepareNewPageDesc( rNode.GetpSwAttrSet(), rNode, nullptr , pNextPageDesc);
+ PrepareNewPageDesc( rNode.GetpSwAttrSet(), rNode, nullptr , pNextPageDesc, true);
}
}
else if (!bNeedParaSplit)
diff --git a/sw/source/filter/ww8/wrtw8sty.cxx b/sw/source/filter/ww8/wrtw8sty.cxx
index eb06b97195bb..e264d51a1ff2 100644
--- a/sw/source/filter/ww8/wrtw8sty.cxx
+++ b/sw/source/filter/ww8/wrtw8sty.cxx
@@ -1092,12 +1092,13 @@ const WW8_SepInfo* MSWordSections::CurrentSectionInfo()
}
void MSWordSections::AppendSection( const SwPageDesc* pPd,
- const SwSectionFormat* pSectionFormat, sal_uLong nLnNumRestartNo, bool bIsFirstParagraph )
+ const SwSectionFormat*const pSectionFormat, sal_uLong const nLnNumRestartNo,
+ bool const bIsFirstParagraph, bool const bIsContinuous)
{
if (HeaderFooterWritten()) {
return; // #i117955# prevent new sections in endnotes
}
- aSects.emplace_back( pPd, pSectionFormat, nLnNumRestartNo, boost::none, nullptr, bIsFirstParagraph );
+ aSects.emplace_back(pPd, pSectionFormat, nLnNumRestartNo, boost::none, nullptr, bIsFirstParagraph, bIsContinuous);
NeedsDocumentProtected( aSects.back() );
}
@@ -1112,13 +1113,14 @@ void WW8_WrPlcSepx::AppendSep( WW8_CP nStartCp, const SwPageDesc* pPd,
}
void MSWordSections::AppendSection( const SwFormatPageDesc& rPD,
- const SwNode& rNd, const SwSectionFormat* pSectionFormat, sal_uLong nLnNumRestartNo )
+ const SwNode& rNd, const SwSectionFormat*const pSectionFormat,
+ sal_uLong const nLnNumRestartNo, bool const bIsContinuous)
{
if (HeaderFooterWritten()) {
return; // #i117955# prevent new sections in endnotes
}
- WW8_SepInfo aI( rPD.GetPageDesc(), pSectionFormat, nLnNumRestartNo, rPD.GetNumOffset(), &rNd );
+ WW8_SepInfo aI(rPD.GetPageDesc(), pSectionFormat, nLnNumRestartNo, rPD.GetNumOffset(), &rNd, false, bIsContinuous);
aSects.push_back( aI );
NeedsDocumentProtected( aI );
@@ -1548,9 +1550,9 @@ void MSWordExportBase::SectionProperties( const WW8_SepInfo& rSepInfo, WW8_PdAtt
/* sprmSBkc, break code: 0 No break, 1 New column
2 New page, 3 Even page, 4 Odd page
*/
- sal_uInt8 nBreakCode = 2; // default start new page
+ sal_uInt8 nBreakCode = rSepInfo.isContinuous ? 0 : 2; // default start new page
bool bOutPgDscSet = true, bLeftRightPgChain = false, bOutputStyleItemSet = false;
- bool bEnsureHeaderFooterWritten = rSepInfo.pSectionFormat && rSepInfo.bIsFirstParagraph;
+ bool bEnsureHeaderFooterWritten = (rSepInfo.pSectionFormat && rSepInfo.bIsFirstParagraph) || rSepInfo.isContinuous;
const SwFrameFormat* pPdFormat = &pPd->GetMaster();
if ( rSepInfo.pSectionFormat )
{
diff --git a/sw/source/filter/ww8/wrtww8.hxx b/sw/source/filter/ww8/wrtww8.hxx
index 9356b87bd86f..43dce01a807c 100644
--- a/sw/source/filter/ww8/wrtww8.hxx
+++ b/sw/source/filter/ww8/wrtww8.hxx
@@ -181,13 +181,16 @@ struct WW8_SepInfo
sal_uLong const nLnNumRestartNo;
::boost::optional<sal_uInt16> const oPgRestartNo;
bool const bIsFirstParagraph;
+ bool isContinuous;
WW8_SepInfo( const SwPageDesc* pPD, const SwSectionFormat* pFormat,
sal_uLong nLnRestart, ::boost::optional<sal_uInt16> oPgRestart = boost::none,
- const SwNode* pNd = nullptr, bool bIsFirstPara = false )
+ const SwNode* pNd = nullptr, bool bIsFirstPara = false,
+ bool bIsContinuous = false)
: pPageDesc( pPD ), pSectionFormat( pFormat ), pPDNd( pNd ),
nLnNumRestartNo( nLnRestart ), oPgRestartNo( oPgRestart ),
bIsFirstParagraph( bIsFirstPara )
+ , isContinuous(bIsContinuous)
{}
bool IsProtected() const;
@@ -216,11 +219,13 @@ public:
void AppendSection( const SwPageDesc* pPd,
const SwSectionFormat* pSectionFormat,
sal_uLong nLnNumRestartNo,
- bool bIsFirstParagraph = false );
+ bool bIsFirstParagraph = false,
+ bool bIsContinuous = false);
void AppendSection( const SwFormatPageDesc& rPd,
const SwNode& rNd,
const SwSectionFormat* pSectionFormat,
- sal_uLong nLnNumRestartNo );
+ sal_uLong nLnNumRestartNo,
+ bool bIsContinuous = false);
/// Number of columns based on the most recent WW8_SepInfo.
sal_uInt16 CurrentNumberOfColumns( const SwDoc &rDoc ) const;
@@ -854,7 +859,8 @@ protected:
virtual void PrepareNewPageDesc( const SfxItemSet* pSet,
const SwNode& rNd,
const SwFormatPageDesc* pNewPgDescFormat,
- const SwPageDesc* pNewPgDesc ) = 0;
+ const SwPageDesc* pNewPgDesc,
+ bool bViaLayout ) = 0;
/// Return value indicates if an inherited outline numbering is suppressed.
virtual bool DisallowInheritingOutlineNumbering(const SwFormat &rFormat) = 0;
@@ -1121,7 +1127,8 @@ public:
virtual void PrepareNewPageDesc( const SfxItemSet* pSet,
const SwNode& rNd,
const SwFormatPageDesc* pNewPgDescFormat,
- const SwPageDesc* pNewPgDesc ) override;
+ const SwPageDesc* pNewPgDesc,
+ bool bViaLayout ) override;
static void Out_BorderLine(ww::bytes& rO, const ::editeng::SvxBorderLine* pLine,
sal_uInt16 nDist, sal_uInt16 nSprmNo, sal_uInt16 nSprmNoVer9,
diff --git a/sw/source/filter/ww8/ww8atr.cxx b/sw/source/filter/ww8/ww8atr.cxx
index 0b2c6527c0ea..87d6545d3391 100644
--- a/sw/source/filter/ww8/ww8atr.cxx
+++ b/sw/source/filter/ww8/ww8atr.cxx
@@ -457,7 +457,9 @@ void MSWordExportBase::OutputSectionBreaks( const SfxItemSet *pSet, const SwNode
//section.
bool bBreakSet = false;
- const SwPageDesc * pPageDesc = rNd.FindPageDesc();
+ size_t idx(0);
+ const SwPageDesc * pPageDesc = rNd.FindPageDesc(&idx);
+ bool isViaLayout(idx == rNd.GetIndex());
// Even if pAktPageDesc != pPageDesc ,it might be because of the different header & footer types.
if (m_pCurrentPageDesc != pPageDesc)
@@ -524,6 +526,7 @@ void MSWordExportBase::OutputSectionBreaks( const SfxItemSet *pSet, const SwNode
static_cast<const SwFormatPageDesc*>(pItem)->GetRegisteredIn() != nullptr)
{
bBreakSet = true;
+ assert(!isViaLayout);
bNewPageDesc = true;
pPgDesc = static_cast<const SwFormatPageDesc*>(pItem);
m_pCurrentPageDesc = pPgDesc->GetPageDesc();
@@ -551,6 +554,7 @@ void MSWordExportBase::OutputSectionBreaks( const SfxItemSet *pSet, const SwNode
}
}
bBreakSet = true;
+ isViaLayout = false;
if ( !bRemoveHardBreakInsideTable )
{
@@ -617,7 +621,7 @@ void MSWordExportBase::OutputSectionBreaks( const SfxItemSet *pSet, const SwNode
if ( bNewPageDesc && m_pCurrentPageDesc )
{
- PrepareNewPageDesc( pSet, rNd, pPgDesc, m_pCurrentPageDesc );
+ PrepareNewPageDesc(pSet, rNd, pPgDesc, m_pCurrentPageDesc, isViaLayout);
}
m_bBreakBefore = false;
m_bPrevTextNodeIsEmpty = isTextNodeEmpty ;
@@ -632,7 +636,7 @@ bool MSWordExportBase::OutputFollowPageDesc( const SfxItemSet* pSet, const SwTex
m_pCurrentPageDesc &&
m_pCurrentPageDesc != m_pCurrentPageDesc->GetFollow() )
{
- PrepareNewPageDesc( pSet, *pNd, nullptr, m_pCurrentPageDesc->GetFollow() );
+ PrepareNewPageDesc(pSet, *pNd, nullptr, m_pCurrentPageDesc->GetFollow(), true);
bRet = true;
}
@@ -670,7 +674,8 @@ sal_uLong MSWordExportBase::GetSectionLineNo( const SfxItemSet* pSet, const SwNo
void WW8Export::PrepareNewPageDesc( const SfxItemSet*pSet,
const SwNode& rNd,
const SwFormatPageDesc* pNewPgDescFormat,
- const SwPageDesc* pNewPgDesc )
+ const SwPageDesc* pNewPgDesc,
+ bool const )
{
// The PageDescs will only be inserted in WW8Writer::pSepx with the corresponding
// position by the occurrences of PageDesc attributes. The construction and
commit 4f1ed088c026d39df3e4c7b5609657b1f2496532
Author: Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Thu Aug 6 14:12:04 2020 +0200
Commit: Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Fri Oct 2 16:39:08 2020 +0200
sw: HACK to disble DrawingML export for rotated text shapes
Change-Id: I7542d0dd000b974ce490b9b81f3d85412e2409f2
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport.cxx
index 9a771a5f81b7..70b63e251495 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport.cxx
@@ -444,9 +444,11 @@ DECLARE_OOXMLEXPORT_TEST(testRot90Fliph, "rot90-fliph.docx")
// The problem was that a shape rotation of 90° got turned into 270° after roundtrip.
if (xmlDocPtr pXmlDoc = parseExport("word/document.xml"))
{
+#if 0
assertXPath(pXmlDoc, "//a:xfrm", "flipH", "1");
// This was 16200000 (270 * 60000).
assertXPath(pXmlDoc, "//a:xfrm", "rot", "5400000");
+#endif
}
}
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport15.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport15.cxx
index 1aa5f0fa631e..d5e067b98f07 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport15.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport15.cxx
@@ -38,6 +38,7 @@ DECLARE_OOXMLEXPORT_TEST(testAtPageShapeRelOrientation, "rotated_shape.fodt")
if (!pXmlDocument)
return;
+#if 0
assertXPathContent(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[1]/mc:Choice/w:drawing/wp:anchor"
"/wp:positionH/wp:posOffset", "-480060");
assertXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[1]/mc:Choice/w:drawing/wp:anchor"
@@ -56,13 +57,14 @@ DECLARE_OOXMLEXPORT_TEST(testAtPageShapeRelOrientation, "rotated_shape.fodt")
"/wp:positionV/wp:posOffset", "1080135");
assertXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/w:drawing/wp:anchor"
"/wp:positionV", "relativeFrom", "page");
+#endif
// now test text rotation -> VML writing direction
- assertXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[1]/mc:Fallback/w:pict/v:shape/v:textbox", "style", "mso-layout-flow-alt:bottom-to-top");
+ assertXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/w:pict/v:shape/v:textbox", "style", "mso-layout-flow-alt:bottom-to-top");
// text wrap -> VML
- assertXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[1]/mc:Fallback/w:pict/v:shape/w10:wrap", "type", "none");
+ assertXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/w:pict/v:shape/w10:wrap", "type", "none");
// vertical alignment -> VML
- OUString const style = getXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[1]/mc:Fallback/w:pict/v:shape", "style");
+ OUString const style = getXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/w:pict/v:shape", "style");
CPPUNIT_ASSERT(style.indexOf("v-text-anchor:middle") != -1);
}
diff --git a/sw/source/filter/ww8/docxsdrexport.cxx b/sw/source/filter/ww8/docxsdrexport.cxx
index 7cacc4eb3173..b86c64daeb24 100644
--- a/sw/source/filter/ww8/docxsdrexport.cxx
+++ b/sw/source/filter/ww8/docxsdrexport.cxx
@@ -16,6 +16,7 @@
#include <editeng/opaqitem.hxx>
#include <editeng/boxitem.hxx>
#include <svx/svdogrp.hxx>
+#include <svx/svdotext.hxx>
#include <oox/token/namespaces.hxx>
#include <textboxhelper.hxx>
#include <fmtanchr.hxx>
@@ -983,6 +984,24 @@ bool DocxSdrExport::Impl::isSupportedDMLShape(const uno::Reference<drawing::XSha
return true;
}
+bool lcl_isRotatedText(SdrObject const& rShape, uno::Reference<drawing::XShape> const& xShape)
+{
+ uno::Reference<beans::XPropertySet> const xProps(xShape, uno::UNO_QUERY);
+ sal_Int32 nRotateAngle = sal_Int32();
+ if (!dynamic_cast<SdrTextObj const*>(&rShape)
+ || !xProps->getPropertySetInfo()->hasPropertyByName("RotateAngle")
+ || !(xProps->getPropertyValue("RotateAngle") >>= nRotateAngle))
+ {
+ return false;
+ }
+ if (nRotateAngle == 9000) // is it enough, or should it be any angle != 0?
+ {
+ SAL_INFO("sw.ww8", "HACK: forcing rotated shape to VML only");
+ return true;
+ }
+ return false;
+}
+
void DocxSdrExport::writeDMLAndVMLDrawing(const SdrObject* sdrObj,
const SwFrameFormat& rFrameFormat, int nAnchorId)
{
@@ -1001,6 +1020,7 @@ void DocxSdrExport::writeDMLAndVMLDrawing(const SdrObject* sdrObj,
// In case we are already inside a DML block, then write the shape only as VML, turn out that's allowed to do.
// A common service created in util to check for VML shapes which are allowed to have textbox in content
if ((msfilter::util::HasTextBoxContent(eShapeType)) && Impl::isSupportedDMLShape(xShape)
+ && !lcl_isRotatedText(*sdrObj, xShape)
&& (!bDMLAndVMLDrawingOpen || lcl_isLockedCanvas(xShape))) // Locked canvas is OK inside DML
{
m_pImpl->getSerializer()->startElementNS(XML_mc, XML_AlternateContent);
commit ba6f89abde582424b9579c611a2dd36a701348e7
Author: Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Fri Aug 7 15:50:12 2020 +0200
Commit: Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Fri Oct 2 16:39:07 2020 +0200
oox: VML export: convert ESCHER_Prop_AnchorText to v-text-anchor
Change-Id: I903cac8d7b02138680613b5a1b6dab4b1c448158
diff --git a/oox/source/export/vmlexport.cxx b/oox/source/export/vmlexport.cxx
index 555796c47a9c..ee93cf32bd27 100644
--- a/oox/source/export/vmlexport.cxx
+++ b/oox/source/export/vmlexport.cxx
@@ -430,6 +430,47 @@ void VMLExport::Commit( EscherPropertyContainer& rProps, const tools::Rectangle&
bAlreadyWritten[ ESCHER_Prop_WrapText ] = true;
break;
+ case ESCHER_Prop_AnchorText: // 135
+ {
+ char const* pValue(nullptr);
+ switch (opt.nPropValue)
+ {
+ case ESCHER_AnchorTop:
+ pValue = "top";
+ break;
+ case ESCHER_AnchorMiddle:
+ pValue = "middle";
+ break;
+ case ESCHER_AnchorBottom:
+ pValue = "bottom";
+ break;
+ case ESCHER_AnchorTopCentered:
+ pValue = "top-center";
+ break;
+ case ESCHER_AnchorMiddleCentered:
+ pValue = "middle-center";
+ break;
+ case ESCHER_AnchorBottomCentered:
+ pValue = "bottom-center";
+ break;
+ case ESCHER_AnchorTopBaseline:
+ pValue = "top-baseline";
+ break;
+ case ESCHER_AnchorBottomBaseline:
+ pValue = "bottom-baseline";
+ break;
+ case ESCHER_AnchorTopCenteredBaseline:
+ pValue = "top-center-baseline";
+ break;
+ case ESCHER_AnchorBottomCenteredBaseline:
+ pValue = "bottom-center-baseline";
+ break;
+ }
+ m_ShapeStyle.append(";v-text-anchor:");
+ m_ShapeStyle.append(pValue);
+ }
+ break;
+
case ESCHER_Prop_txflTextFlow: // 136
{
// at least "bottom-to-top" only has an effect when it's on the v:textbox element, not on v:shape
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport15.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport15.cxx
index 7c317a0883e8..1aa5f0fa631e 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport15.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport15.cxx
@@ -61,7 +61,9 @@ DECLARE_OOXMLEXPORT_TEST(testAtPageShapeRelOrientation, "rotated_shape.fodt")
assertXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[1]/mc:Fallback/w:pict/v:shape/v:textbox", "style", "mso-layout-flow-alt:bottom-to-top");
// text wrap -> VML
assertXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[1]/mc:Fallback/w:pict/v:shape/w10:wrap", "type", "none");
-
+ // vertical alignment -> VML
+ OUString const style = getXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[1]/mc:Fallback/w:pict/v:shape", "style");
+ CPPUNIT_ASSERT(style.indexOf("v-text-anchor:middle") != -1);
}
DECLARE_OOXMLEXPORT_TEST(testTdf133334_followPgStyle, "tdf133334_followPgStyle.odt")
commit eb74a2ec72fd9c442792a006aee22f6489c1277d
Author: Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Fri Aug 7 15:45:25 2020 +0200
Commit: Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Fri Oct 2 16:39:07 2020 +0200
oox: VML export: produce bottom-to-top in a better way
Replace code added in 090c61eb93db4302d4565d5f11f7673190835fdb
with something that uses the already generated ESCHER property; this
lets a warning about the unhandled property disappear too.
Change-Id: Ieed83dd8e17e92eea9901124fce5e6da2a17196a
diff --git a/include/oox/export/vmlexport.hxx b/include/oox/export/vmlexport.hxx
index 83b5b91c0d41..7c2d3a62da6f 100644
--- a/include/oox/export/vmlexport.hxx
+++ b/include/oox/export/vmlexport.hxx
@@ -99,6 +99,9 @@ class OOX_DLLPUBLIC VMLExport : public EscherEx
/// Remember style, the most important shape attribute ;-)
OStringBuffer m_ShapeStyle;
+ /// style for textbox
+ OStringBuffer m_TextboxStyle;
+
/// Remember the generated shape id.
OString m_sShapeId;
diff --git a/oox/source/export/vmlexport.cxx b/oox/source/export/vmlexport.cxx
index 6fcc83a66da6..555796c47a9c 100644
--- a/oox/source/export/vmlexport.cxx
+++ b/oox/source/export/vmlexport.cxx
@@ -430,6 +430,28 @@ void VMLExport::Commit( EscherPropertyContainer& rProps, const tools::Rectangle&
bAlreadyWritten[ ESCHER_Prop_WrapText ] = true;
break;
+ case ESCHER_Prop_txflTextFlow: // 136
+ {
+ // at least "bottom-to-top" only has an effect when it's on the v:textbox element, not on v:shape
+ assert(m_TextboxStyle.isEmpty());
+ switch (opt.nPropValue)
+ {
+ case ESCHER_txflHorzN:
+ m_TextboxStyle.append("layout-flow:horizontal");
+ break;
+ case ESCHER_txflTtoBA:
+ m_TextboxStyle.append("layout-flow:vertical");
+ break;
+ case ESCHER_txflBtoT:
+ m_TextboxStyle.append("mso-layout-flow-alt:bottom-to-top");
+ break;
+ default:
+ assert(false); // unimplemented in escher export
+ break;
+ }
+ }
+ break;
+
// coordorigin
case ESCHER_Prop_geoLeft: // 320
case ESCHER_Prop_geoTop: // 321
@@ -1345,6 +1367,8 @@ sal_Int32 VMLExport::StartShape()
// start of the shape
m_pSerializer->startElementNS( XML_v, nShapeElement, XFastAttributeListRef( m_pShapeAttrList ) );
+ OString const textboxStyle(m_TextboxStyle.makeStringAndClear());
+
// now check if we have some editeng text (not associated textbox) and we have a text exporter registered
const SdrTextObj* pTxtObj = dynamic_cast<const SdrTextObj*>( m_pSdrObject );
if (pTxtObj && m_pTextExport && msfilter::util::HasTextBoxContent(m_nShapeType) && !IsWaterMarkShape(m_pSdrObject->GetName()) && !lcl_isTextBox(m_pSdrObject))
@@ -1369,19 +1393,11 @@ sal_Int32 VMLExport::StartShape()
if( pParaObj )
{
- uno::Reference<beans::XPropertySet> xPropertySet(const_cast<SdrObject*>(m_pSdrObject)->getUnoShape(), uno::UNO_QUERY);
sax_fastparser::FastAttributeList* pTextboxAttrList = FastSerializerHelper::createAttrList();
sax_fastparser::XFastAttributeListRef xTextboxAttrList(pTextboxAttrList);
- if (xPropertySet->getPropertySetInfo()->hasPropertyByName("RotateAngle"))
+ if (!textboxStyle.isEmpty())
{
- sal_Int32 nTextRotateAngle = sal_Int32();
- if (xPropertySet->getPropertyValue("RotateAngle") >>= nTextRotateAngle)
- {
- if (nTextRotateAngle == 9000)
- {
- pTextboxAttrList->add(XML_style, "mso-layout-flow-alt:bottom-to-top");
- }
- }
+ pTextboxAttrList->add(XML_style, textboxStyle);
}
// this is reached only in case some text is attached to the shape
commit e1489b5bc7c9bd534f049a448ab727d0009f1737
Author: Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Fri Aug 7 15:26:48 2020 +0200
Commit: Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Fri Oct 2 16:39:07 2020 +0200
filter: MSO export: convert TextWrap property to Escher_Wrap*
There's a paucity of working wrapping modes in Escher unfortunately.
Change-Id: Ibaf99c3249a6492dc129f9c9b5707778038f9a4c
diff --git a/filter/source/msfilter/escherex.cxx b/filter/source/msfilter/escherex.cxx
index f04043e9156a..a2071237deb7 100644
--- a/filter/source/msfilter/escherex.cxx
+++ b/filter/source/msfilter/escherex.cxx
@@ -66,6 +66,7 @@
#include <com/sun/star/drawing/FlagSequence.hpp>
#include <com/sun/star/drawing/PolygonFlags.hpp>
#include <com/sun/star/text/WritingMode.hpp>
+#include <com/sun/star/text/WrapTextMode.hpp>
#include <com/sun/star/drawing/TextVerticalAdjust.hpp>
#include <com/sun/star/drawing/TextHorizontalAdjust.hpp>
#include <com/sun/star/drawing/EnhancedCustomShapeSegment.hpp>
@@ -699,6 +700,10 @@ void EscherPropertyContainer::CreateTextProperties(
bool bWordWrap ( false );
bool bAutoGrowSize ( false );
+ uno::Any aTextWrap;
+
+ EscherPropertyValueHelper::GetPropertyValue(aTextWrap, rXPropSet, "TextWrap", true);
+
if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, "TextWritingMode", true ) )
aAny >>= eWM;
if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, "TextVerticalAdjust", true ) )
@@ -837,6 +842,21 @@ void EscherPropertyContainer::CreateTextProperties(
nTextAttr |= 0x20002;
}
}
+
+ if (aTextWrap.hasValue())
+ { // explicit text wrap overrides whatever was inferred previously
+ switch (aTextWrap.get<text::WrapTextMode>())
+ {
+ case text::WrapTextMode_THROUGH:
+ eWrapMode = ESCHER_WrapNone;
+ break;
+ // in theory there are 3 more Escher_Wrap, but [MS-ODRAW] says they are useless
+ default:
+ eWrapMode = ESCHER_WrapSquare;
+ break;
+ }
+ }
+
AddOpt( ESCHER_Prop_dxTextLeft, nLeft * 360 );
AddOpt( ESCHER_Prop_dxTextRight, nRight * 360 );
AddOpt( ESCHER_Prop_dyTextTop, nTop * 360 );
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport15.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport15.cxx
index 73c05ea83ca4..7c317a0883e8 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport15.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport15.cxx
@@ -59,6 +59,8 @@ DECLARE_OOXMLEXPORT_TEST(testAtPageShapeRelOrientation, "rotated_shape.fodt")
// now test text rotation -> VML writing direction
assertXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[1]/mc:Fallback/w:pict/v:shape/v:textbox", "style", "mso-layout-flow-alt:bottom-to-top");
+ // text wrap -> VML
+ assertXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[1]/mc:Fallback/w:pict/v:shape/w10:wrap", "type", "none");
}
commit 588f06a491f61f7c143c20136750500cc7c146c6
Author: Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Fri Aug 7 16:41:18 2020 +0200
Commit: Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Fri Oct 2 16:39:07 2020 +0200
sw: register w10 prefix
Change-Id: I1ca9c3c7c4f36b666ee7d17967b80fdaa7004874
diff --git a/sw/qa/inc/swmodeltestbase.hxx b/sw/qa/inc/swmodeltestbase.hxx
index 38f8e95a4a40..d62b92b58fc0 100644
--- a/sw/qa/inc/swmodeltestbase.hxx
+++ b/sw/qa/inc/swmodeltestbase.hxx
@@ -962,6 +962,7 @@ protected:
xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("a14"), BAD_CAST("http://schemas.microsoft.com/office/drawing/2010/main"));
xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("c"), BAD_CAST("http://schemas.openxmlformats.org/drawingml/2006/chart"));
xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("o"), BAD_CAST("urn:schemas-microsoft-com:office:office"));
+ xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("w10"), BAD_CAST("urn:schemas-microsoft-com:office:word"));
// odt
xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("office"), BAD_CAST("urn:oasis:names:tc:opendocument:xmlns:office:1.0"));
xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("style"), BAD_CAST("urn:oasis:names:tc:opendocument:xmlns:style:1.0"));
commit d8133f79ad3e32e2ca1df247391deabcc2be002f
Author: Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Thu Aug 6 14:11:38 2020 +0200
Commit: Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Fri Oct 2 16:39:06 2020 +0200
oox: VML export: for rotated text shape, produce bottom-to-top
This is for shapes that fail the lcl_isTextBox() check in
VMLExport::StartShape(), they can be rotated too but with a different
property than the "TextPreRotateAngle" that is used in
VMLExport::EndShape().
Change-Id: I530aae8b7138f47bae8434e205632f5f4adbb231
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/100249
Tested-by: Jenkins
Reviewed-by: Michael Stahl <michael.stahl at cib.de>
(cherry picked from commit 090c61eb93db4302d4565d5f11f7673190835fdb)
diff --git a/oox/source/export/vmlexport.cxx b/oox/source/export/vmlexport.cxx
index 98f3243e5461..6fcc83a66da6 100644
--- a/oox/source/export/vmlexport.cxx
+++ b/oox/source/export/vmlexport.cxx
@@ -1369,8 +1369,23 @@ sal_Int32 VMLExport::StartShape()
if( pParaObj )
{
+ uno::Reference<beans::XPropertySet> xPropertySet(const_cast<SdrObject*>(m_pSdrObject)->getUnoShape(), uno::UNO_QUERY);
+ sax_fastparser::FastAttributeList* pTextboxAttrList = FastSerializerHelper::createAttrList();
+ sax_fastparser::XFastAttributeListRef xTextboxAttrList(pTextboxAttrList);
+ if (xPropertySet->getPropertySetInfo()->hasPropertyByName("RotateAngle"))
+ {
+ sal_Int32 nTextRotateAngle = sal_Int32();
+ if (xPropertySet->getPropertyValue("RotateAngle") >>= nTextRotateAngle)
+ {
+ if (nTextRotateAngle == 9000)
+ {
+ pTextboxAttrList->add(XML_style, "mso-layout-flow-alt:bottom-to-top");
+ }
+ }
+ }
+
// this is reached only in case some text is attached to the shape
- m_pSerializer->startElementNS(XML_v, XML_textbox);
+ m_pSerializer->startElementNS(XML_v, XML_textbox, xTextboxAttrList);
m_pTextExport->WriteOutliner(*pParaObj);
m_pSerializer->endElementNS(XML_v, XML_textbox);
if( bOwnParaObj )
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport15.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport15.cxx
index 025cb033d476..73c05ea83ca4 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport15.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport15.cxx
@@ -56,6 +56,10 @@ DECLARE_OOXMLEXPORT_TEST(testAtPageShapeRelOrientation, "rotated_shape.fodt")
"/wp:positionV/wp:posOffset", "1080135");
assertXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/w:drawing/wp:anchor"
"/wp:positionV", "relativeFrom", "page");
+
+ // now test text rotation -> VML writing direction
+ assertXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[1]/mc:Fallback/w:pict/v:shape/v:textbox", "style", "mso-layout-flow-alt:bottom-to-top");
+
}
DECLARE_OOXMLEXPORT_TEST(testTdf133334_followPgStyle, "tdf133334_followPgStyle.odt")
commit 1272478cf48a79ede0d128a2609097053b3947cf
Author: Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Tue Aug 4 19:09:38 2020 +0200
Commit: Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Fri Oct 2 16:39:06 2020 +0200
tdf#135464 sw: avoid invalid combinations of HoriOrientRelation and FLY_AT_PAGE
... when using Anchor->To Page context menu.
For shapes, in SwDoc::ChgAnchor() and for sw flys in
SwDoc::SetFlyFrameAnchor().
Change-Id: I7d747b2558ef69df99636ea0fb0409deb461a79a
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/100131
Tested-by: Jenkins
Reviewed-by: Michael Stahl <michael.stahl at cib.de>
(cherry picked from commit 1de2b0d3234462b488db54d36ebc17e2b579b0f0)
diff --git a/sw/source/core/doc/docfly.cxx b/sw/source/core/doc/docfly.cxx
index 4451115905a8..cc3b858028c2 100644
--- a/sw/source/core/doc/docfly.cxx
+++ b/sw/source/core/doc/docfly.cxx
@@ -372,6 +372,7 @@ sal_Int8 SwDoc::SetFlyFrameAnchor( SwFrameFormat& rFormat, SfxItemSet& rSet, boo
pItem = nullptr;
SwFormatHoriOrient aOldH( rFormat.GetHoriOrient() );
+ bool bPutOldH(false);
if( text::HoriOrientation::NONE == aOldH.GetHoriOrient() && ( !pItem ||
aOldH.GetPos() == static_cast<const SwFormatHoriOrient*>(pItem)->GetPos() ))
@@ -386,6 +387,22 @@ sal_Int8 SwDoc::SetFlyFrameAnchor( SwFrameFormat& rFormat, SfxItemSet& rSet, boo
aOldH.SetRelationOrient( pH->GetRelationOrient() );
}
aOldH.SetPos( nPos );
+ bPutOldH = true;
+ }
+ if (nNew == RndStdIds::FLY_AT_PAGE)
+ {
+ sal_Int16 nRelOrient(pItem
+ ? static_cast<const SwFormatHoriOrient*>(pItem)->GetRelationOrient()
+ : aOldH.GetRelationOrient());
+ if (sw::GetAtPageRelOrientation(nRelOrient, false))
+ {
+ SAL_INFO("sw.ui", "fixing horizontal RelOrientation for at-page anchor");
+ aOldH.SetRelationOrient(nRelOrient);
+ bPutOldH = true;
+ }
+ }
+ if (bPutOldH)
+ {
rSet.Put( aOldH );
}
@@ -915,6 +932,17 @@ bool SwDoc::ChgAnchor( const SdrMarkList& _rMrkList,
// of attributes (method call <SetAttr(..)>) takes care of the
// invalidation of the object position.
SetAttr( aNewAnch, *pContact->GetFormat() );
+ if (aNewAnch.GetAnchorId() == RndStdIds::FLY_AT_PAGE)
+ {
+ SwFormatHoriOrient item(pContact->GetFormat()->GetHoriOrient());
+ sal_Int16 nRelOrient(item.GetRelationOrient());
+ if (sw::GetAtPageRelOrientation(nRelOrient, false))
+ {
+ SAL_INFO("sw.ui", "fixing horizontal RelOrientation for at-page anchor");
+ item.SetRelationOrient(text::RelOrientation::PAGE_FRAME);
+ SetAttr(item, *pContact->GetFormat());
+ }
+ }
if ( _bPosCorr )
{
// #i33313# - consider not connected 'virtual' drawing
diff --git a/sw/source/core/layout/anchoreddrawobject.cxx b/sw/source/core/layout/anchoreddrawobject.cxx
index 079468fdf062..f3813192c928 100644
--- a/sw/source/core/layout/anchoreddrawobject.cxx
+++ b/sw/source/core/layout/anchoreddrawobject.cxx
@@ -719,7 +719,10 @@ void SwAnchoredDrawObject::AdjustPositioningAttr( const SwFrame* _pNewAnchorFram
nVertRelPos = aObjRect.Top() - aAnchorPos.Y();
}
- GetFrameFormat().SetFormatAttr( SwFormatHoriOrient( nHoriRelPos, text::HoriOrientation::NONE, text::RelOrientation::FRAME ) );
+ GetFrameFormat().SetFormatAttr( SwFormatHoriOrient( nHoriRelPos, text::HoriOrientation::NONE,
+ GetFrameFormat().GetAnchor().GetAnchorId() == RndStdIds::FLY_AT_PAGE
+ ? text::RelOrientation::PAGE_FRAME
+ : text::RelOrientation::FRAME ) );
GetFrameFormat().SetFormatAttr( SwFormatVertOrient( nVertRelPos, text::VertOrientation::NONE, text::RelOrientation::FRAME ) );
}
commit b2510947725db91cb7bc8f6dba484ac6bb155280
Author: Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Tue Aug 4 18:56:08 2020 +0200
Commit: Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Fri Oct 2 16:39:02 2020 +0200
tdf#135464 sw: ODT->DOCX: fix positioning of at-page shapes and frames
Exporting at-page anchored flys to DOCX can result in wrong positions,
because DocxSdrExport::startDMLAnchorInline() converts
text::RelOrientation::FRAME to relativeFrom="column", i.e. the margin,
but sw displays it as relative to the page.
In fact at-page and FRAME is an invalid combination according to the
table in ODF 1.3, 20.298 style:horizontal-pos, the paragraph and
character relations are not valid for page-anchored flys.
Since there are lots of ODT files with this invalid combination, try to
fix it on import, in SwXFrame and SwXShape.
Funnily, SwXShape is attached before the properties are set, while
SwXFrame is attached after the properties are set.
The anchor frame for at-page is always a SwPageFrame.
Unfortunately there is a case where PRINT_AREA and PAGE_PRINT_AREA
differ, namely the CalcClipRect() only handles PRINT_AREA so it will
crop to the right margin with that but not with PAGE_PRINT_AREA,
so don't map this value.
Change-Id: I4d5f7f87d045ac4539b9170e55c34d4afe801f4d
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/100130
Tested-by: Jenkins
Reviewed-by: Michael Stahl <michael.stahl at cib.de>
(cherry picked from commit 12645900dece0a9aa0661fee796c27f672217977)
diff --git a/sw/inc/fmtornt.hxx b/sw/inc/fmtornt.hxx
index 24ffdc907e26..d0bea643f980 100644
--- a/sw/inc/fmtornt.hxx
+++ b/sw/inc/fmtornt.hxx
@@ -108,6 +108,12 @@ inline const SwFormatVertOrient &SwFormat::GetVertOrient(bool bInP) const
inline const SwFormatHoriOrient &SwFormat::GetHoriOrient(bool bInP) const
{ return m_aSet.GetHoriOrient(bInP); }
+namespace sw {
+
+ bool GetAtPageRelOrientation(sal_Int16 & rOrientation, bool const isIgnorePrintArea);
+
+}
+
#endif
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/qa/extras/ooxmlexport/data/rotated_shape.fodt b/sw/qa/extras/ooxmlexport/data/rotated_shape.fodt
new file mode 100644
index 000000000000..fce84f93e945
--- /dev/null
+++ b/sw/qa/extras/ooxmlexport/data/rotated_shape.fodt
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<office:document xmlns:officeooo="http://openoffice.org/2009/office" xmlns:css3t="http://www.w3.org/TR/css3-text/" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rpt="http://openoffice.org/2005/report" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns
:config:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="ur
n:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:xforms="http://www.w3.org/2002/xforms" office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.text">
+ <office:font-face-decls>
+ <style:font-face style:name="Times New Roman" svg:font-family="'Times New Roman'" style:font-family-generic="roman" style:font-pitch="variable"/>
+ <style:font-face style:name="Arial" svg:font-family="Arial" style:font-family-generic="swiss" style:font-pitch="variable"/>
+ <style:font-face style:name="Lucida Sans" svg:font-family="'Lucida Sans'" style:font-family-generic="system" style:font-pitch="variable"/>
+ <style:font-face style:name="NSimSun" svg:font-family="NSimSun" style:font-family-generic="system" style:font-pitch="variable"/>
+ </office:font-face-decls>
+ <office:styles>
+ <style:default-style style:family="graphic">
+ <style:graphic-properties svg:stroke-color="#3465a4" draw:fill-color="#729fcf" fo:wrap-option="no-wrap" draw:shadow-offset-x="0.3cm" draw:shadow-offset-y="0.3cm" draw:start-line-spacing-horizontal="0.283cm" draw:start-line-spacing-vertical="0.283cm" draw:end-line-spacing-horizontal="0.283cm" draw:end-line-spacing-vertical="0.283cm" style:flow-with-text="false"/>
+ <style:paragraph-properties style:text-autospace="ideograph-alpha" style:line-break="strict" style:font-independent-line-spacing="false">
+ <style:tab-stops/>
+ </style:paragraph-properties>
+ <style:text-properties style:use-window-font-color="true" loext:opacity="0%" style:font-name="Times New Roman" fo:font-size="12pt" fo:language="de" fo:country="DE" style:letter-kerning="true" style:font-name-asian="NSimSun" style:font-size-asian="10.5pt" style:language-asian="zh" style:country-asian="CN" style:font-name-complex="Lucida Sans" style:font-size-complex="12pt" style:language-complex="hi" style:country-complex="IN"/>
+ </style:default-style>
+ <style:default-style style:family="paragraph">
+ <style:paragraph-properties fo:orphans="2" fo:widows="2" fo:hyphenation-ladder-count="no-limit" style:text-autospace="ideograph-alpha" style:punctuation-wrap="hanging" style:line-break="strict" style:tab-stop-distance="1.251cm" style:writing-mode="page"/>
+ <style:text-properties style:use-window-font-color="true" loext:opacity="0%" style:font-name="Times New Roman" fo:font-size="12pt" fo:language="de" fo:country="DE" style:letter-kerning="true" style:font-name-asian="NSimSun" style:font-size-asian="10.5pt" style:language-asian="zh" style:country-asian="CN" style:font-name-complex="Lucida Sans" style:font-size-complex="12pt" style:language-complex="hi" style:country-complex="IN" fo:hyphenate="false" fo:hyphenation-remain-char-count="2" fo:hyphenation-push-char-count="2" loext:hyphenation-no-caps="false"/>
+ </style:default-style>
+ <style:default-style style:family="table">
+ <style:table-properties table:border-model="collapsing"/>
+ </style:default-style>
+ <style:default-style style:family="table-row">
+ <style:table-row-properties fo:keep-together="auto"/>
+ </style:default-style>
+ <style:style style:name="Standard" style:family="paragraph" style:class="text"/>
+ <text:notes-configuration text:note-class="footnote" style:num-format="1" text:start-value="0" text:footnotes-position="page" text:start-numbering-at="document"/>
+ <text:notes-configuration text:note-class="endnote" style:num-format="i" text:start-value="0"/>
... etc. - the rest is truncated
More information about the Libreoffice-commits
mailing list