1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
22 #include "WW8TableInfo.hxx"
23 #include <fmtfsize.hxx>
24 #include "attributeoutputbase.hxx"
25 #include <swtable.hxx>
28 #include <dbgoutsw.hxx>
29 #include <sal/log.hxx>
30 #include <osl/diagnose.h>
31 #include <rtl/string.hxx>
36 WW8TableNodeInfoInner::WW8TableNodeInfoInner(WW8TableNodeInfo
* pParent
)
44 , mbFinalEndOfLine(false)
46 , mbFirstInTable(false)
53 void WW8TableNodeInfoInner::setDepth(sal_uInt32 nDepth
)
58 void WW8TableNodeInfoInner::setCell(sal_uInt32 nCell
)
63 void WW8TableNodeInfoInner::setRow(sal_uInt32 nRow
)
68 void WW8TableNodeInfoInner::setShadowsBefore(sal_uInt32 nShadowsBefore
)
70 mnShadowsBefore
= nShadowsBefore
;
73 void WW8TableNodeInfoInner::setShadowsAfter(sal_uInt32 nShadowsAfter
)
75 mnShadowsAfter
= nShadowsAfter
;
78 void WW8TableNodeInfoInner::setEndOfLine(bool bEndOfLine
)
80 mbEndOfLine
= bEndOfLine
;
83 void WW8TableNodeInfoInner::setFinalEndOfLine(bool bFinalEndOfLine
)
85 mbFinalEndOfLine
= bFinalEndOfLine
;
88 void WW8TableNodeInfoInner::setEndOfCell(bool bEndOfCell
)
90 mbEndOfCell
= bEndOfCell
;
93 void WW8TableNodeInfoInner::setFirstInTable(bool bFirstInTable
)
95 mbFirstInTable
= bFirstInTable
;
98 void WW8TableNodeInfoInner::setVertMerge(bool bVertMerge
)
101 mbVertMerge
= bVertMerge
;
104 void WW8TableNodeInfoInner::setTableBox(const SwTableBox
* pTableBox
)
106 mpTableBox
= pTableBox
;
109 void WW8TableNodeInfoInner::setTable(const SwTable
* pTable
)
114 void WW8TableNodeInfoInner::setRect(const SwRect
& rRect
)
119 const SwNode
* WW8TableNodeInfoInner::getNode() const
121 const SwNode
* pResult
= nullptr;
123 if (mpParent
!= nullptr)
124 pResult
= mpParent
->getNode();
129 TableBoxVectorPtr
WW8TableNodeInfoInner::getTableBoxesOfRow() const
131 TableBoxVectorPtr pResult
= std::make_shared
<TableBoxVector
>();
133 WW8TableCellGrid::Pointer_t pCellGrid
=
134 mpParent
->getParent()->getCellGridForTable(getTable(), false);
138 const SwTableLine
* pTabLine
= getTableBox()->GetUpper();
139 const SwTableBoxes
& rTableBoxes
= pTabLine
->GetTabBoxes();
141 sal_uInt8 nBoxes
= rTableBoxes
.size();
142 if (nBoxes
> MAXTABLECELLS
)
143 nBoxes
= MAXTABLECELLS
;
144 for ( sal_uInt8 n
= 0; n
< nBoxes
; n
++ )
146 pResult
->push_back(rTableBoxes
[n
]);
150 pResult
= pCellGrid
->getTableBoxesOfRow(this);
155 GridColsPtr
WW8TableNodeInfoInner::getGridColsOfRow(AttributeOutputBase
& rBase
, bool calculateColumnsFromAllRows
)
157 GridColsPtr pResult
= std::make_shared
<GridCols
>();
160 // Check which columns should be checked - only the current row,
161 // or all the rows together
162 if (calculateColumnsFromAllRows
)
164 // Calculate the width of all the columns based on ALL the rows.
165 // The difference is that this kind of draws vertical lines,
166 // so that if the rows look like this:
168 // ------------------------
170 // ------------------------
172 // ------------------------
174 // ------------------------
176 // then the actual column widths will be broken down like this:
178 // ------------------------
180 // ------------------------
182 // See the example at
183 // http://officeopenxml.com/WPtableGrid.php
184 // Under "Word 2007 Example"
185 pWidths
= getColumnWidthsBasedOnAllRows();
189 // Calculate the width of all the columns based on the current row
190 pWidths
= getWidthsOfRow();
193 const SwFrameFormat
*pFormat
= getTable()->GetFrameFormat();
194 OSL_ENSURE(pFormat
,"Impossible");
198 const SwFormatFrameSize
&rSize
= pFormat
->GetFrameSize();
199 tools::ULong nTableSz
= static_cast<tools::ULong
>(rSize
.GetWidth());
201 tools::Long nPageSize
= 0;
202 bool bRelBoxSize
= false;
204 rBase
.GetTablePageSize( this, nPageSize
, bRelBoxSize
);
207 for (const auto& rWidth
: *pWidths
)
212 nCalc
= ( nCalc
* nPageSize
) / nTableSz
;
214 pResult
->push_back( nCalc
);
220 WidthsPtr
WW8TableNodeInfoInner::getColumnWidthsBasedOnAllRows() const
224 WW8TableCellGrid::Pointer_t pCellGrid
=
225 mpParent
->getParent()->getCellGridForTable(getTable(), false);
229 const SwTable
* pTable
= getTable();
230 const SwTableLines
& rTableLines
= pTable
->GetTabLines();
231 const size_t nNumOfLines
= rTableLines
.size();
233 // Go over all the rows - and for each row - calculate where
234 // there is a separator between columns
235 WidthsPtr pSeparators
= std::make_shared
<Widths
>();
236 for ( size_t nLineIndex
= 0; nLineIndex
< nNumOfLines
; ++nLineIndex
)
238 const SwTableLine
*pCurrentLine
= rTableLines
[nLineIndex
];
239 const SwTableBoxes
& rTabBoxes
= pCurrentLine
->GetTabBoxes();
240 size_t nBoxes
= rTabBoxes
.size();
241 if (nBoxes
> MAXTABLECELLS
)
242 nBoxes
= MAXTABLECELLS
;
244 sal_uInt32 nSeparatorPosition
= 0;
245 for (size_t nBoxIndex
= 0; nBoxIndex
< nBoxes
; ++nBoxIndex
)
247 const SwFrameFormat
* pBoxFormat
= rTabBoxes
[ nBoxIndex
]->GetFrameFormat();
248 const SwFormatFrameSize
& rLSz
= pBoxFormat
->GetFrameSize();
249 nSeparatorPosition
+= rLSz
.GetWidth();
250 pSeparators
->push_back(nSeparatorPosition
);
254 // Sort the separator positions and remove any duplicates
255 std::sort(pSeparators
->begin(), pSeparators
->end());
256 std::vector
<sal_uInt32
>::iterator it
= std::unique(pSeparators
->begin(), pSeparators
->end());
257 pSeparators
->erase(it
, pSeparators
->end());
259 // Calculate the widths based on the position of the unique & sorted
261 pWidths
= std::make_shared
<Widths
>();
262 sal_uInt32 nPreviousWidth
= 0;
263 for (const sal_uInt32 nCurrentWidth
: *pSeparators
)
265 pWidths
->push_back(nCurrentWidth
- nPreviousWidth
);
266 nPreviousWidth
= nCurrentWidth
;
271 pWidths
= pCellGrid
->getWidthsOfRow(this);
277 WidthsPtr
WW8TableNodeInfoInner::getWidthsOfRow() const
281 WW8TableCellGrid::Pointer_t pCellGrid
=
282 mpParent
->getParent()->getCellGridForTable(getTable(), false);
286 const SwTableBox
* pTabBox
= getTableBox();
287 const SwTableLine
* pTabLine
= pTabBox
->GetUpper();
288 const SwTableBoxes
& rTabBoxes
= pTabLine
->GetTabBoxes();
290 pWidths
= std::make_shared
<Widths
>();
291 // number of cell written
292 sal_uInt32 nBoxes
= rTabBoxes
.size();
293 if (nBoxes
> MAXTABLECELLS
)
294 nBoxes
= MAXTABLECELLS
;
296 for (sal_uInt32 n
= 0; n
< nBoxes
; n
++)
298 const SwFrameFormat
* pBoxFormat
= rTabBoxes
[ n
]->GetFrameFormat();
299 const SwFormatFrameSize
& rLSz
= pBoxFormat
->GetFrameSize();
301 pWidths
->push_back(rLSz
.GetWidth());
305 pWidths
= pCellGrid
->getWidthsOfRow(this);
310 RowSpansPtr
WW8TableNodeInfoInner::getRowSpansOfRow() const
312 RowSpansPtr pResult
= std::make_shared
<RowSpans
>();
314 WW8TableCellGrid::Pointer_t pCellGrid
=
315 mpParent
->getParent()->getCellGridForTable(getTable(), false);
319 const SwTableBox
* pTabBox
= getTableBox();
320 const SwTableLine
* pTabLine
= pTabBox
->GetUpper();
321 const SwTableBoxes
& rTabBoxes
= pTabLine
->GetTabBoxes();
323 sal_uInt32 nBoxes
= rTabBoxes
.size();
324 if (nBoxes
> MAXTABLECELLS
)
325 nBoxes
= MAXTABLECELLS
;
327 for (sal_uInt32 n
= 0; n
< nBoxes
; ++n
)
329 pResult
->push_back(rTabBoxes
[n
]->getRowSpan());
333 pResult
= pCellGrid
->getRowSpansOfRow(this);
340 std::string
WW8TableNodeInfoInner::toString() const
342 static char buffer
[256];
343 snprintf(buffer
, sizeof(buffer
),
344 "<tableinner depth=\"%" SAL_PRIuUINT32
"\""
345 " cell=\"%" SAL_PRIuUINT32
"\""
346 " row=\"%" SAL_PRIuUINT32
"\""
349 " shadowsBefore=\"%" SAL_PRIuUINT32
"\""
350 " shadowsAfter=\"%" SAL_PRIuUINT32
"\""
351 " vertMerge=\"%s\"/>",
352 mnDepth
, mnCell
, mnRow
,
353 mbEndOfCell
? "yes" : "no",
354 mbEndOfLine
? "yes" : "no",
357 mbVertMerge
? "yes" : "no");
359 return std::string(buffer
);
363 WW8TableNodeInfo::WW8TableNodeInfo(WW8TableInfo
* pParent
,
364 const SwNode
* pNode
)
373 WW8TableNodeInfo::~WW8TableNodeInfo()
378 std::string
WW8TableNodeInfo::toString() const
380 static char buffer
[1024];
381 snprintf(buffer
, sizeof(buffer
),
382 "<tableNodeInfo p=\"%p\" depth=\"%" SAL_PRIuUINT32
"\">"
385 std::string
sResult(buffer
);
387 for (const auto& rInner
: mInners
)
389 WW8TableNodeInfoInner::Pointer_t pInner
= rInner
.second
;
390 sResult
+= pInner
->toString();
392 sResult
+= dbg_out(*mpNode
);
393 sResult
+= "</tableNodeInfo>";
399 void WW8TableNodeInfo::setDepth(sal_uInt32 nDepth
)
403 Inners_t::iterator aIt
= mInners
.find(mnDepth
);
405 if (aIt
== mInners
.end())
406 mInners
[mnDepth
] = std::make_shared
<ww8::WW8TableNodeInfoInner
>(this);
408 mInners
[mnDepth
]->setDepth(mnDepth
);
411 void WW8TableNodeInfo::setEndOfLine(bool bEndOfLine
)
413 WW8TableNodeInfoInner::Pointer_t pInner
= getInnerForDepth(mnDepth
);
414 pInner
->setEndOfLine(bEndOfLine
);
417 SAL_INFO( "sw.ww8", "<endOfLine depth=\"" << mnDepth
<< "\">" << toString() << "</endOfLine>" );
421 void WW8TableNodeInfo::setEndOfCell(bool bEndOfCell
)
423 WW8TableNodeInfoInner::Pointer_t pInner
= getInnerForDepth(mnDepth
);
424 pInner
->setEndOfCell(bEndOfCell
);
427 SAL_INFO( "sw.ww8", "<endOfCell depth=\"" << mnDepth
<< "\">" << toString() << "</endOfCell>" );
431 void WW8TableNodeInfo::setFirstInTable(bool bFirstInTable
)
433 WW8TableNodeInfoInner::Pointer_t pInner
= getInnerForDepth(mnDepth
);
435 pInner
->setFirstInTable(bFirstInTable
);
438 SAL_INFO( "sw.ww8", "<firstInTable depth=\"" << mnDepth
<< "\">" << toString() << "</firstInTable>" );
442 void WW8TableNodeInfo::setVertMerge(bool bVertMerge
)
444 WW8TableNodeInfoInner::Pointer_t pInner
= getInnerForDepth(mnDepth
);
446 pInner
->setVertMerge(bVertMerge
);
449 SAL_INFO( "sw.ww8", "<vertMerge depth=\"" << mnDepth
<< "\">" << toString() << "</vertMerge>" );
453 void WW8TableNodeInfo::setTableBox(const SwTableBox
* pTableBox
)
455 getInnerForDepth(mnDepth
)->setTableBox(pTableBox
);
458 void WW8TableNodeInfo::setTable(const SwTable
* pTable
)
460 getInnerForDepth(mnDepth
)->setTable(pTable
);
463 void WW8TableNodeInfo::setNext(WW8TableNodeInfo
* pNext
)
468 SAL_INFO( "sw.ww8", "<setnext><from>" << toString() << "</from><to>" << pNext
->toString() << "</to></setnext>" );
472 void WW8TableNodeInfo::setNextNode(const SwNode
* pNode
)
477 void WW8TableNodeInfo::setRect(const SwRect
& rRect
)
479 getInnerForDepth(mnDepth
)->setRect(rRect
);
482 void WW8TableNodeInfo::setCell(sal_uInt32 nCell
)
484 getInnerForDepth(mnDepth
)->setCell(nCell
);
487 void WW8TableNodeInfo::setRow(sal_uInt32 nRow
)
489 getInnerForDepth(mnDepth
)->setRow(nRow
);
492 void WW8TableNodeInfo::setShadowsBefore(sal_uInt32 nShadowsBefore
)
494 getInnerForDepth(mnDepth
)->setShadowsBefore(nShadowsBefore
);
497 void WW8TableNodeInfo::setShadowsAfter(sal_uInt32 nShadowsAfter
)
499 getInnerForDepth(mnDepth
)->setShadowsAfter(nShadowsAfter
);
503 sal_uInt32
WW8TableNodeInfo::getDepth() const
505 if (!mInners
.empty())
506 return mInners
.begin()->second
->getDepth();
512 const SwTableBox
* WW8TableNodeInfo::getTableBox() const
514 return getInnerForDepth(mnDepth
)->getTableBox();
517 sal_uInt32
WW8TableNodeInfo::getCell() const
519 return getInnerForDepth(mnDepth
)->getCell();
522 sal_uInt32
WW8TableNodeInfo::getRow() const
524 return getInnerForDepth(mnDepth
)->getRow();
527 WW8TableNodeInfoInner::Pointer_t
WW8TableNodeInfo::getFirstInner() const
529 WW8TableNodeInfoInner::Pointer_t pResult
;
531 if (!mInners
.empty())
532 pResult
= mInners
.begin()->second
;
537 WW8TableNodeInfoInner::Pointer_t
WW8TableNodeInfo::getInnerForDepth(sal_uInt32 nDepth
) const
539 WW8TableNodeInfoInner::Pointer_t pResult
;
541 Inners_t::const_iterator aIt
= mInners
.find(nDepth
);
542 if (aIt
!= mInners
.end())
544 pResult
= aIt
->second
;
550 WW8TableInfo::WW8TableInfo()
554 WW8TableInfo::~WW8TableInfo()
559 WW8TableInfo::processSwTableByLayout(const SwTable
* pTable
, RowEndInners_t
&rLastRowEnds
)
561 SwTableCellInfo
aTableCellInfo(pTable
);
563 while (aTableCellInfo
.getNext())
565 SwRect aRect
= aTableCellInfo
.getRect();
567 SAL_INFO( "sw.ww8", "<CellFrame>" );
568 SAL_INFO( "sw.ww8", "<rect top=\"" << aRect
.Top() << "\" bottom=\"" << aRect
.Bottom()
569 << "\" left=\"" << aRect
.Left() << "\" right=\"" << aRect
.Right() << "\"/>" );
570 const SwTableBox
* pTableBox
= aTableCellInfo
.getTableBox();
571 const SwStartNode
* pSttNd
= pTableBox
->GetSttNd();
573 if (pSttNd
!= nullptr)
575 SwPaM
aPam(*pSttNd
, 0);
580 SwNode
& rNode
= aPam
.GetPoint()->GetNode();
582 insertTableNodeInfo(&rNode
, pTable
, pTableBox
, 0, 0, 1, & aRect
);
584 if (rNode
.IsEndNode())
586 SwEndNode
* pEndNode
= rNode
.GetEndNode();
587 SwStartNode
* pTmpSttNd
= pEndNode
->StartOfSectionNode();
589 if (pTmpSttNd
== pSttNd
)
593 aPam
.GetPoint()->Adjust(SwNodeOffset(1));
598 SAL_INFO( "sw.ww8", "</CellFrame>" );
601 return reorderByLayout(pTable
, rLastRowEnds
);
604 void WW8TableInfo::processSwTable(const SwTable
* pTable
)
606 SAL_INFO( "sw.ww8", "<processSwTable>" );
608 WW8TableNodeInfo
* pPrev
= nullptr;
609 RowEndInners_t aLastRowEnds
;
611 if (pTable
->IsTableComplex() && pTable
->HasLayout())
613 pPrev
= processSwTableByLayout(pTable
, aLastRowEnds
);
615 SAL_INFO( "sw.ww8", getCellGridForTable(pTable
)->toString());
620 const SwTableLines
& rLines
= pTable
->GetTabLines();
622 for (size_t n
= 0; n
< rLines
.size(); ++n
)
624 const SwTableLine
* pLine
= rLines
[n
];
626 pPrev
= processTableLine(pTable
, pLine
, static_cast<sal_uInt32
>(n
), 1, pPrev
, aLastRowEnds
);
633 SwTableNode
* pTableNode
= pTable
->GetTableNode();
634 SwEndNode
* pEndNode
= pTableNode
->EndOfSectionNode();
635 pPrev
->setNextNode(pEndNode
);
636 assert(!aLastRowEnds
.empty());
637 for (auto &a
: aLastRowEnds
)
639 assert(a
.second
->isEndOfLine());
640 a
.second
->setFinalEndOfLine(true);
643 SAL_INFO( "sw.ww8", "</processSwTable>" );
647 WW8TableInfo::processTableLine(const SwTable
* pTable
,
648 const SwTableLine
* pTableLine
,
651 WW8TableNodeInfo
* pPrev
,
652 RowEndInners_t
&rLastRowEnds
)
654 SAL_INFO( "sw.ww8", "<processTableLine row=\"" << nRow
<< "\" depth=\"" << nDepth
<< "\">" );
656 const SwTableBoxes
& rBoxes
= pTableLine
->GetTabBoxes();
658 for (size_t n
= 0; n
< rBoxes
.size(); ++n
)
660 const SwTableBox
* pBox
= rBoxes
[n
];
662 pPrev
= processTableBox(pTable
, pBox
, nRow
, static_cast<sal_uInt32
>(n
), nDepth
, n
== rBoxes
.size() - 1, pPrev
, rLastRowEnds
);
665 SAL_INFO( "sw.ww8", "</processTableLine>" );
670 WW8TableNodeInfo::Pointer_t
671 WW8TableInfo::processTableBoxLines(const SwTableBox
* pBox
,
672 const SwTable
* pTable
,
673 const SwTableBox
* pBoxToSet
,
678 SAL_INFO( "sw.ww8", "<processTableBoxLines depth=\"" << nDepth
<< "\" row=\"" << nRow
679 << "\" cell=\"" << nCell
<< "\">" );
681 const SwTableLines
& rLines
= pBox
->GetTabLines();
682 WW8TableNodeInfo::Pointer_t pNodeInfo
;
686 for (size_t n
= 0; n
< rLines
.size(); ++n
)
688 const SwTableLine
* pLine
= rLines
[n
];
689 const SwTableBoxes
& rBoxes
= pLine
->GetTabBoxes();
691 for (size_t nBox
= 0; nBox
< rBoxes
.size(); ++nBox
)
692 pNodeInfo
= processTableBoxLines(rBoxes
[nBox
], pTable
, pBoxToSet
, nRow
, nCell
, nDepth
);
697 const SwStartNode
* pSttNd
= pBox
->GetSttNd();
698 const SwEndNode
* pEndNd
= pSttNd
->EndOfSectionNode();
699 SwPaM
aPaM(*pSttNd
, 0);
700 SwPaM
aEndPaM(*pEndNd
, 0);
705 SwNode
& rNode
= aPaM
.GetPoint()->GetNode();
707 pNodeInfo
= insertTableNodeInfo(&rNode
, pTable
, pBoxToSet
, nRow
, nCell
, nDepth
);
709 if (aPaM
.GetPoint()->GetNode() == aEndPaM
.GetPoint()->GetNode())
712 aPaM
.GetPoint()->Adjust(SwNodeOffset(1));
716 SAL_INFO( "sw.ww8", "</processTableBoxLines>" );
721 static void updateFinalEndOfLine(RowEndInners_t
&rLastRowEnds
, WW8TableNodeInfo
const * pEndOfCellInfo
)
723 sal_Int32 nDepth
= pEndOfCellInfo
->getDepth();
724 WW8TableNodeInfoInner::Pointer_t pInner
= pEndOfCellInfo
->getInnerForDepth(nDepth
);
726 auto aIt
= rLastRowEnds
.find(nDepth
);
727 if (aIt
== rLastRowEnds
.end() || (pInner
->getRow() > aIt
->second
->getRow()))
728 rLastRowEnds
[nDepth
] = pInner
.get();
732 WW8TableInfo::processTableBox(const SwTable
* pTable
,
733 const SwTableBox
* pBox
,
738 WW8TableNodeInfo
* pPrev
,
739 RowEndInners_t
&rLastRowEnds
)
741 SAL_INFO( "sw.ww8", "<processTableBox row=\"" << nRow
<< "\" cell=\"" << nCell
742 << "\" depth=\"" << nDepth
<< "\">" );
744 WW8TableNodeInfo::Pointer_t pNodeInfo
;
745 const SwTableLines
& rLines
= pBox
->GetTabLines();
746 const SwStartNode
* pSttNd
= pBox
->GetSttNd();
747 WW8TableNodeInfo::Pointer_t pEndOfCellInfo
;
751 pNodeInfo
= processTableBoxLines(pBox
, pTable
, pBox
, nRow
, nCell
, nDepth
);
752 pNodeInfo
->setEndOfCell(true);
755 pNodeInfo
->setEndOfLine(true);
756 updateFinalEndOfLine(rLastRowEnds
, pNodeInfo
.get());
759 for (size_t n
= 0; n
< rLines
.size(); n
++)
761 const SwTableLine
* pLine
= rLines
[n
];
763 pPrev
= processTableLine(pTable
, pLine
, n
, 1, pPrev
, rLastRowEnds
);
768 SwPaM
aPaM(*pSttNd
, 0);
771 sal_uInt32 nDepthInsideCell
= 0;
775 SwNode
& rNode
= aPaM
.GetPoint()->GetNode();
777 if (rNode
.IsStartNode())
779 if (nDepthInsideCell
> 0)
780 pEndOfCellInfo
.reset();
785 pNodeInfo
= insertTableNodeInfo(&rNode
, pTable
, pBox
, nRow
, nCell
, nDepth
);
788 pPrev
->setNext(pNodeInfo
.get());
790 pPrev
= pNodeInfo
.get();
792 if (nDepthInsideCell
== 1 && rNode
.IsTextNode())
793 pEndOfCellInfo
= pNodeInfo
;
795 if (rNode
.IsEndNode())
799 if (nDepthInsideCell
== 0 && !pEndOfCellInfo
)
800 pEndOfCellInfo
= pNodeInfo
;
802 SwEndNode
* pEndNode
= rNode
.GetEndNode( );
803 SwStartNode
* pTmpSttNd
= pEndNode
->StartOfSectionNode();
804 if (pTmpSttNd
== pSttNd
)
808 aPaM
.GetPoint()->Adjust(SwNodeOffset(1));
814 pEndOfCellInfo
->setEndOfCell(true);
818 pEndOfCellInfo
->setEndOfLine(true);
819 updateFinalEndOfLine(rLastRowEnds
, pEndOfCellInfo
.get());
824 SAL_INFO( "sw.ww8", "</processTableBox>" );
829 WW8TableNodeInfo::Pointer_t
WW8TableInfo::insertTableNodeInfo
830 (const SwNode
* pNode
,
831 const SwTable
* pTable
,
832 const SwTableBox
* pTableBox
,
836 SwRect
const * pRect
)
838 WW8TableNodeInfo::Pointer_t pNodeInfo
= getTableNodeInfo(pNode
);
843 std::make_shared
<ww8::WW8TableNodeInfo
>(this, pNode
);
844 mMap
.emplace(pNode
, pNodeInfo
);
847 pNodeInfo
->setDepth(nDepth
+ pNodeInfo
->getDepth());
849 pNodeInfo
->setTable(pTable
);
850 pNodeInfo
->setTableBox(pTableBox
);
852 pNodeInfo
->setCell(nCell
);
853 pNodeInfo
->setRow(nRow
);
855 if (pNode
->IsTextNode())
857 FirstInTableMap_t::const_iterator aIt
= mFirstInTableMap
.find(pTable
);
858 if (aIt
== mFirstInTableMap
.end())
860 mFirstInTableMap
[pTable
] = pNode
;
861 pNodeInfo
->setFirstInTable(true);
867 WW8TableCellGrid::Pointer_t pCellGrid
= getCellGridForTable(pTable
);
869 pCellGrid
->insert(*pRect
, pNodeInfo
.get());
870 pNodeInfo
->setRect(*pRect
);
874 SAL_INFO( "sw.ww8", pNodeInfo
->toString());
879 WW8TableCellGrid::Pointer_t
WW8TableInfo::getCellGridForTable
880 (const SwTable
* pTable
, bool bCreate
)
882 WW8TableCellGrid::Pointer_t pResult
;
883 CellGridMap_t::iterator aIt
= mCellGridMap
.find(pTable
);
885 if (aIt
== mCellGridMap
.end())
889 pResult
= std::make_shared
<ww8::WW8TableCellGrid
>();
890 mCellGridMap
[pTable
] = pResult
;
894 pResult
= mCellGridMap
[pTable
];
899 WW8TableNodeInfo::Pointer_t
WW8TableInfo::getTableNodeInfo
900 (const SwNode
* pNode
)
902 WW8TableNodeInfo::Pointer_t pResult
;
903 Map_t::iterator aIt
= mMap
.find(pNode
);
905 if (aIt
!= mMap
.end())
906 pResult
= (*aIt
).second
;
911 const SwNode
* WW8TableInfo::getNextNode(const SwNode
* pNode
)
913 const SwNode
* pResult
= nullptr;
915 WW8TableNodeInfo::Pointer_t pNodeInfo
= getTableNodeInfo(pNode
);
919 WW8TableNodeInfo
* pNextInfo
= pNodeInfo
->getNext();
921 if (pNextInfo
!= nullptr)
922 pResult
= pNextInfo
->getNode();
925 const SwNode
* pNextNode
= pNodeInfo
->getNextNode();
927 if (pNextNode
!= nullptr)
935 bool WW8TableNodeInfo::operator < (const WW8TableNodeInfo
& rInfo
) const
939 if (rInfo
.mpNode
!= nullptr)
941 if (mpNode
== nullptr)
947 if (mpNode
->GetIndex() < rInfo
.mpNode
->GetIndex())
955 bool CellInfo::operator < (const CellInfo
& aCellInfo
) const
959 if (top() < aCellInfo
.top())
961 else if (top() == aCellInfo
.top())
963 if (left() < aCellInfo
.left())
965 else if (left() == aCellInfo
.left())
967 if (width() < aCellInfo
.width())
969 else if (width() == aCellInfo
.width())
971 if (height() < aCellInfo
.height())
973 else if (height() == aCellInfo
.height())
975 if (aCellInfo
.getTableNodeInfo())
977 if (m_pNodeInfo
== nullptr)
981 aRet
= *m_pNodeInfo
< *aCellInfo
.getTableNodeInfo();
993 std::string
CellInfo::toString() const
995 static char sBuffer
[256];
997 snprintf(sBuffer
, sizeof(sBuffer
),
998 "<cellinfo left=\"%" SAL_PRIdINT64
"\""
999 " right=\"%" SAL_PRIdINT64
"\""
1000 " top=\"%" SAL_PRIdINT64
"\""
1001 " bottom=\"%" SAL_PRIdINT64
"\""
1006 sal_Int64(bottom()),
1013 WW8TableNodeInfo
* WW8TableInfo::reorderByLayout(const SwTable
* pTable
, RowEndInners_t
&rLastRowEnds
)
1015 WW8TableCellGrid::Pointer_t pCellGrid
= getCellGridForTable(pTable
);
1018 SAL_INFO( "sw.ww8", pCellGrid
->toString());
1021 pCellGrid
->addShadowCells();
1022 return pCellGrid
->connectCells(rLastRowEnds
);
1025 WW8TableCellGrid::WW8TableCellGrid()
1029 WW8TableCellGrid::~WW8TableCellGrid()
1033 WW8TableCellGridRow::Pointer_t
WW8TableCellGrid::getRow(tools::Long nTop
, bool bCreate
)
1035 WW8TableCellGridRow::Pointer_t pResult
;
1037 RowTops_t::iterator aIt
= m_aRowTops
.find(nTop
);
1039 if (aIt
== m_aRowTops
.end())
1043 pResult
= std::make_shared
<ww8::WW8TableCellGridRow
>();
1044 m_aRows
[nTop
] = pResult
;
1045 m_aRowTops
.insert(nTop
);
1049 pResult
= m_aRows
[nTop
];
1054 WW8TableCellGrid::RowTops_t::const_iterator
WW8TableCellGrid::getRowTopsBegin() const
1056 return m_aRowTops
.begin();
1059 WW8TableCellGrid::RowTops_t::const_iterator
WW8TableCellGrid::getRowTopsEnd() const
1061 return m_aRowTops
.end();
1064 CellInfoMultiSet::const_iterator
WW8TableCellGrid::getCellsBegin(tools::Long nTop
)
1066 return getRow(nTop
)->begin();
1069 CellInfoMultiSet::const_iterator
WW8TableCellGrid::getCellsEnd(tools::Long nTop
)
1071 return getRow(nTop
)->end();
1074 void WW8TableCellGrid::insert(const SwRect
& rRect
,
1075 WW8TableNodeInfo
* pNodeInfo
,
1076 const tools::ULong
* pFormatFrameWidth
)
1078 CellInfo
aCellInfo(rRect
, pNodeInfo
);
1080 if (pFormatFrameWidth
!= nullptr)
1081 aCellInfo
.setFormatFrameWidth(*pFormatFrameWidth
);
1083 WW8TableCellGridRow::Pointer_t pRow
= getRow(rRect
.Top());
1084 pRow
->insert(aCellInfo
);
1087 void WW8TableCellGrid::addShadowCells()
1089 SAL_INFO( "sw.ww8", "<addShadowCells>" );
1091 RowTops_t::const_iterator aTopsIt
= getRowTopsBegin();
1093 while (aTopsIt
!= getRowTopsEnd())
1095 CellInfoMultiSet::const_iterator aCellIt
= getCellsBegin(*aTopsIt
);
1096 CellInfoMultiSet::const_iterator aCellEndIt
= getCellsEnd(*aTopsIt
);
1098 RowSpansPtr pRowSpans
= std::make_shared
<RowSpans
>();
1100 bool bBeginningOfCell
= true;
1101 bool bVertMerge
= false;
1102 SwRect aRect
= aCellIt
->getRect();
1103 sal_Int32 nRowSpan
= 1;
1104 while (aCellIt
!= aCellEndIt
)
1106 WW8TableNodeInfo
* pNodeInfo
= aCellIt
->getTableNodeInfo();
1108 if (bBeginningOfCell
)
1110 RowTops_t::const_iterator
aRowSpanIt(aTopsIt
);
1113 if (aRowSpanIt
!= getRowTopsEnd() &&
1114 *aRowSpanIt
< aCellIt
->bottom())
1116 aRect
.Top(*aRowSpanIt
);
1117 tools::ULong nFormatFrameWidth
= aCellIt
->getFormatFrameWidth();
1118 insert(aRect
, nullptr, &nFormatFrameWidth
);
1126 while (aRowSpanIt
!= getRowTopsEnd() &&
1127 *aRowSpanIt
< aCellIt
->bottom())
1134 pRowSpans
->push_back(nRowSpan
);
1136 pRowSpans
->push_back(-nRowSpan
);
1141 pNodeInfo
->setVertMerge(bVertMerge
);
1145 if (aCellIt
!= aCellEndIt
)
1147 bBeginningOfCell
= (aRect
.Left() != aCellIt
->left());
1148 aRect
= aCellIt
->getRect();
1152 WW8TableCellGridRow::Pointer_t pRow
= getRow(*aTopsIt
);
1154 pRow
->setRowSpans(pRowSpans
);
1158 SAL_INFO( "sw.ww8", "</addShadowCells>" );
1161 WW8TableNodeInfo
* WW8TableCellGrid::connectCells(RowEndInners_t
&rLastRowEnds
)
1163 RowTops_t::const_iterator aTopsIt
= getRowTopsBegin();
1164 sal_uInt32 nRow
= 0;
1165 WW8TableNodeInfo
* pLastNodeInfo
= nullptr;
1167 while (aTopsIt
!= getRowTopsEnd())
1169 CellInfoMultiSet::const_iterator aCellIt
= getCellsBegin(*aTopsIt
);
1170 CellInfoMultiSet::const_iterator aCellEndIt
= getCellsEnd(*aTopsIt
);
1171 GridColsPtr pWidths
= std::make_shared
<Widths
>();
1172 TableBoxVectorPtr pTableBoxes
= std::make_shared
<TableBoxVector
>();
1174 sal_uInt32 nShadows
= 0;
1175 sal_uInt32 nCell
= 0;
1176 bool bBeginningOfCell
= true;
1177 WW8TableNodeInfo
* pEndOfCellInfo
= nullptr;
1178 sal_uInt32 nDepthInCell
= 0;
1179 while (aCellIt
!= aCellEndIt
)
1181 tools::Long nCellX
= aCellIt
->left();
1182 WW8TableNodeInfo
* pNodeInfo
= aCellIt
->getTableNodeInfo();
1185 const SwNode
* pNode
= pNodeInfo
->getNode();
1187 if (pNode
->IsStartNode())
1190 pEndOfCellInfo
= nullptr;
1193 if (nDepthInCell
== 1 && pNode
->IsTextNode())
1194 pEndOfCellInfo
= pNodeInfo
;
1196 pNodeInfo
->setShadowsBefore(nShadows
);
1197 pNodeInfo
->setCell(nCell
);
1198 pNodeInfo
->setRow(nRow
);
1201 pLastNodeInfo
->setNext(pNodeInfo
);
1202 pLastNodeInfo
->setNextNode(pNode
);
1204 pLastNodeInfo
= pNodeInfo
;
1207 if (pNode
->IsEndNode())
1209 assert(nDepthInCell
> 0 && "otherwise overflow");
1212 if (nDepthInCell
== 0 && !pEndOfCellInfo
)
1213 pEndOfCellInfo
= pNodeInfo
;
1221 if (bBeginningOfCell
)
1223 pWidths
->push_back(aCellIt
->getFormatFrameWidth());
1226 pTableBoxes
->push_back(pNodeInfo
->getTableBox());
1228 pTableBoxes
->push_back(nullptr);
1232 bBeginningOfCell
= false;
1234 if (aCellIt
!= aCellEndIt
&& aCellIt
->left() != nCellX
)
1237 bBeginningOfCell
= true;
1241 pEndOfCellInfo
->setEndOfCell(true);
1244 pEndOfCellInfo
= nullptr;
1248 pLastNodeInfo
->setShadowsAfter(nShadows
);
1250 if (!pEndOfCellInfo
)
1252 pEndOfCellInfo
= pLastNodeInfo
;
1255 pEndOfCellInfo
->setEndOfCell(true);
1256 pLastNodeInfo
->setEndOfLine(true);
1257 updateFinalEndOfLine(rLastRowEnds
, pLastNodeInfo
);
1259 WW8TableCellGridRow::Pointer_t
pRow(getRow(*aTopsIt
));
1260 pRow
->setTableBoxVector(pTableBoxes
);
1261 pRow
->setWidths(pWidths
);
1267 return pLastNodeInfo
;
1271 std::string
WW8TableCellGrid::toString()
1273 std::string sResult
= "<WW8TableCellGrid>";
1275 RowTops_t::const_iterator aTopsIt
= getRowTopsBegin();
1276 static char sBuffer
[1024];
1277 while (aTopsIt
!= getRowTopsEnd())
1279 sResult
+= "<row y=\"";
1280 sResult
+= OString::number(*aTopsIt
);
1283 CellInfoMultiSet::const_iterator aCellIt
= getCellsBegin(*aTopsIt
);
1284 CellInfoMultiSet::const_iterator aCellsEnd
= getCellsEnd(*aTopsIt
);
1286 while (aCellIt
!= aCellsEnd
)
1288 snprintf(sBuffer
, sizeof(sBuffer
), "<cellInfo top=\"%" SAL_PRIdINT64
"\" bottom=\"%" SAL_PRIdINT64
"\" left=\"%" SAL_PRIdINT64
"\" right=\"%" SAL_PRIdINT64
"\">",
1289 sal_Int64(aCellIt
->top()), sal_Int64(aCellIt
->bottom()), sal_Int64(aCellIt
->left()), sal_Int64(aCellIt
->right()));
1292 WW8TableNodeInfo
* pInfo
= aCellIt
->getTableNodeInfo();
1294 sResult
+= pInfo
->toString();
1296 sResult
+= "<shadow/>\n";
1298 sResult
+= "</cellInfo>\n";
1302 WW8TableCellGridRow::Pointer_t pRow
= getRow(*aTopsIt
);
1303 WidthsPtr pWidths
= pRow
->getWidths();
1304 if (pWidths
!= nullptr)
1306 sResult
+= "<widths>";
1308 Widths::const_iterator aItEnd
= pWidths
->end();
1309 for (Widths::const_iterator aIt
= pWidths
->begin();
1313 if (aIt
!= pWidths
->begin())
1316 snprintf(sBuffer
, sizeof(sBuffer
), "%" SAL_PRIxUINT32
"", *aIt
);
1320 sResult
+= "</widths>";
1323 RowSpansPtr pRowSpans
= pRow
->getRowSpans();
1326 sResult
+= "<rowspans>";
1328 RowSpans::const_iterator aItEnd
= pRowSpans
->end();
1329 for (RowSpans::const_iterator aIt
= pRowSpans
->begin();
1333 if (aIt
!= pRowSpans
->begin())
1336 snprintf(sBuffer
, sizeof(sBuffer
), "%" SAL_PRIxUINT32
"", *aIt
);
1340 sResult
+= "</rowspans>";
1343 sResult
+= "</row>\n";
1347 sResult
+= "</WW8TableCellGrid>\n";
1353 TableBoxVectorPtr
WW8TableCellGrid::getTableBoxesOfRow
1354 (WW8TableNodeInfoInner
const * pNodeInfoInner
)
1356 TableBoxVectorPtr pResult
;
1357 WW8TableCellGridRow::Pointer_t pRow
=
1358 getRow(pNodeInfoInner
->getRect().Top(), false);
1362 pResult
= pRow
->getTableBoxVector();
1368 WidthsPtr
WW8TableCellGrid::getWidthsOfRow
1369 (WW8TableNodeInfoInner
const * pNodeInfoInner
)
1371 GridColsPtr pResult
;
1373 WW8TableCellGridRow::Pointer_t pRow
=
1374 getRow(pNodeInfoInner
->getRect().Top(), false);
1378 pResult
= pRow
->getWidths();
1384 RowSpansPtr
WW8TableCellGrid::getRowSpansOfRow
1385 (WW8TableNodeInfoInner
const * pNodeInfoInner
)
1387 RowSpansPtr pResult
;
1389 WW8TableCellGridRow::Pointer_t pRow
=
1390 getRow(pNodeInfoInner
->getRect().Top(), false);
1394 pResult
= pRow
->getRowSpans();
1400 WW8TableCellGridRow::WW8TableCellGridRow()
1401 : m_pCellInfos(std::make_shared
<CellInfoMultiSet
>())
1405 WW8TableCellGridRow::~WW8TableCellGridRow()
1409 void WW8TableCellGridRow::insert(const CellInfo
& rCellInfo
)
1411 m_pCellInfos
->insert(rCellInfo
);
1414 SAL_INFO( "sw.ww8", "<gridRowInsert>" << rCellInfo
.toString() << "</gridRowInsert>" );
1418 CellInfoMultiSet::const_iterator
WW8TableCellGridRow::begin() const
1420 return m_pCellInfos
->begin();
1423 CellInfoMultiSet::const_iterator
WW8TableCellGridRow::end() const
1425 return m_pCellInfos
->end();
1428 void WW8TableCellGridRow::setTableBoxVector(TableBoxVectorPtr
const & pTableBoxVector
)
1430 if (pTableBoxVector
->size() > MAXTABLECELLS
)
1431 pTableBoxVector
->resize(MAXTABLECELLS
);
1432 m_pTableBoxVector
= pTableBoxVector
;
1435 void WW8TableCellGridRow::setWidths(WidthsPtr
const & pWidths
)
1437 m_pWidths
= pWidths
;
1440 void WW8TableCellGridRow::setRowSpans(RowSpansPtr
const & pRowSpans
)
1442 m_pRowSpans
= pRowSpans
;
1446 CellInfo::CellInfo(const SwRect
& aRect
, WW8TableNodeInfo
* pNodeInfo
)
1447 : m_aRect(aRect
), m_pNodeInfo(pNodeInfo
), m_nFormatFrameWidth(0)
1449 if (pNodeInfo
!= nullptr)
1451 const SwTableBox
* pBox
= pNodeInfo
->getTableBox();
1452 const SwFrameFormat
* pFrameFormat
= pBox
->GetFrameFormat();
1453 const SwFormatFrameSize
& rSize
= pFrameFormat
->GetFrameSize();
1455 m_nFormatFrameWidth
= rSize
.GetWidth();
1461 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */