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 .
23 #include "WW8TableInfo.hxx"
24 #include "fmtfsize.hxx"
25 #include "attributeoutputbase.hxx"
26 #include "swtable.hxx"
30 #include "dbgoutsw.hxx"
35 WW8TableNodeInfoInner::WW8TableNodeInfoInner(WW8TableNodeInfo
* pParent
)
43 , mbFinalEndOfLine(false)
45 , mbFirstInTable(false)
52 WW8TableNodeInfoInner::~WW8TableNodeInfoInner()
56 void WW8TableNodeInfoInner::setDepth(sal_uInt32 nDepth
)
61 void WW8TableNodeInfoInner::setCell(sal_uInt32 nCell
)
66 void WW8TableNodeInfoInner::setRow(sal_uInt32 nRow
)
71 void WW8TableNodeInfoInner::setShadowsBefore(sal_uInt32 nShadowsBefore
)
73 mnShadowsBefore
= nShadowsBefore
;
76 void WW8TableNodeInfoInner::setShadowsAfter(sal_uInt32 nShadowsAfter
)
78 mnShadowsAfter
= nShadowsAfter
;
81 void WW8TableNodeInfoInner::setEndOfLine(bool bEndOfLine
)
83 mbEndOfLine
= bEndOfLine
;
86 void WW8TableNodeInfoInner::setFinalEndOfLine(bool bFinalEndOfLine
)
88 mbFinalEndOfLine
= bFinalEndOfLine
;
91 void WW8TableNodeInfoInner::setEndOfCell(bool bEndOfCell
)
93 mbEndOfCell
= bEndOfCell
;
96 void WW8TableNodeInfoInner::setFirstInTable(bool bFirstInTable
)
98 mbFirstInTable
= bFirstInTable
;
101 void WW8TableNodeInfoInner::setVertMerge(bool bVertMerge
)
104 mbVertMerge
= bVertMerge
;
107 void WW8TableNodeInfoInner::setTableBox(const SwTableBox
* pTableBox
)
109 mpTableBox
= pTableBox
;
112 void WW8TableNodeInfoInner::setTable(const SwTable
* pTable
)
117 void WW8TableNodeInfoInner::setRect(const SwRect
& rRect
)
123 const SwNode
* WW8TableNodeInfoInner::getNode() const
125 const SwNode
* pResult
= nullptr;
127 if (mpParent
!= nullptr)
128 pResult
= mpParent
->getNode();
133 TableBoxVectorPtr
WW8TableNodeInfoInner::getTableBoxesOfRow()
135 TableBoxVectorPtr
pResult(new TableBoxVector
);
137 WW8TableCellGrid::Pointer_t pCellGrid
=
138 mpParent
->getParent()->getCellGridForTable(getTable(), false);
140 if (pCellGrid
.get() == nullptr)
142 const SwTableLine
* pTabLine
= getTableBox()->GetUpper();
143 const SwTableBoxes
& rTableBoxes
= pTabLine
->GetTabBoxes();
145 sal_uInt8 nBoxes
= rTableBoxes
.size();
146 if (nBoxes
> MAXTABLECELLS
)
147 nBoxes
= MAXTABLECELLS
;
148 for ( sal_uInt8 n
= 0; n
< nBoxes
; n
++ )
150 pResult
->push_back(rTableBoxes
[n
]);
154 pResult
= pCellGrid
->getTableBoxesOfRow(this);
159 GridColsPtr
WW8TableNodeInfoInner::getGridColsOfRow(AttributeOutputBase
& rBase
, bool calculateColumnsFromAllRows
)
161 GridColsPtr
pResult(new GridCols
);
164 // Check which columns should be checked - only the current row,
165 // or all the rows together
166 if (calculateColumnsFromAllRows
)
168 // Calculate the width of all the columns based on ALL the rows.
169 // The difference is that this kind of draws vertical lines,
170 // so that if the rows look like this:
172 // ------------------------
174 // ------------------------
176 // ------------------------
178 // ------------------------
180 // then the actual column widths will be broken down like this:
182 // ------------------------
184 // ------------------------
186 // See the example at
187 // http://officeopenxml.com/WPtableGrid.php
188 // Under "Word 2007 Example"
189 pWidths
= getColumnWidthsBasedOnAllRows();
193 // Calculate the width of all the columns based on the current row
194 pWidths
= getWidthsOfRow();
197 const SwFrameFormat
*pFormat
= getTable()->GetFrameFormat();
198 OSL_ENSURE(pFormat
,"Impossible");
202 const SwFormatFrameSize
&rSize
= pFormat
->GetFrameSize();
203 unsigned long nTableSz
= static_cast<unsigned long>(rSize
.GetWidth());
206 bool bRelBoxSize
= false;
208 rBase
.GetTablePageSize( this, nPageSize
, bRelBoxSize
);
211 Widths::const_iterator aWidthsEnd
= pWidths
->end();
212 for ( Widths::const_iterator aIt
= pWidths
->begin();
219 nCalc
= ( nCalc
* nPageSize
) / nTableSz
;
221 pResult
->push_back( nCalc
);
227 WidthsPtr
WW8TableNodeInfoInner::getColumnWidthsBasedOnAllRows()
231 WW8TableCellGrid::Pointer_t pCellGrid
=
232 mpParent
->getParent()->getCellGridForTable(getTable(), false);
234 if (pCellGrid
.get() == nullptr)
236 const SwTable
* pTable
= getTable();
237 const SwTableLines
& rTableLines
= pTable
->GetTabLines();
238 const size_t nNumOfLines
= rTableLines
.size();
240 // Go over all the rows - and for each row - calculate where
241 // there is a separator between columns
242 WidthsPtr
pSeparators(new Widths
);
243 for ( size_t nLineIndex
= 0; nLineIndex
< nNumOfLines
; ++nLineIndex
)
245 const SwTableLine
*pCurrentLine
= rTableLines
[nLineIndex
];
246 const SwTableBoxes
& rTabBoxes
= pCurrentLine
->GetTabBoxes();
247 size_t nBoxes
= rTabBoxes
.size();
248 if (nBoxes
> MAXTABLECELLS
)
249 nBoxes
= MAXTABLECELLS
;
251 sal_uInt32 nSeparatorPosition
= 0;
252 for (size_t nBoxIndex
= 0; nBoxIndex
< nBoxes
; ++nBoxIndex
)
254 const SwFrameFormat
* pBoxFormat
= rTabBoxes
[ nBoxIndex
]->GetFrameFormat();
255 const SwFormatFrameSize
& rLSz
= pBoxFormat
->GetFrameSize();
256 nSeparatorPosition
+= rLSz
.GetWidth();
257 pSeparators
->push_back(nSeparatorPosition
);
261 // Sort the separator positions and remove any duplicates
262 std::sort(pSeparators
->begin(), pSeparators
->end());
263 std::vector
<sal_uInt32
>::iterator it
= std::unique(pSeparators
->begin(), pSeparators
->end());
264 pSeparators
->erase(it
, pSeparators
->end());
266 // Calculate the widths based on the position of the unique & sorted
268 pWidths
= std::make_shared
<Widths
>();
269 sal_uInt32 nPreviousWidth
= 0;
270 Widths::const_iterator aItEnd2
= pSeparators
->end();
271 for (Widths::const_iterator aIt2
= pSeparators
->begin(); aIt2
!= aItEnd2
; ++aIt2
)
273 sal_uInt32 nCurrentWidth
= *aIt2
;
274 pWidths
->push_back(nCurrentWidth
- nPreviousWidth
);
275 nPreviousWidth
= nCurrentWidth
;
280 pWidths
= pCellGrid
->getWidthsOfRow(this);
286 WidthsPtr
WW8TableNodeInfoInner::getWidthsOfRow()
290 WW8TableCellGrid::Pointer_t pCellGrid
=
291 mpParent
->getParent()->getCellGridForTable(getTable(), false);
293 if (pCellGrid
.get() == nullptr)
295 const SwTableBox
* pTabBox
= getTableBox();
296 const SwTableLine
* pTabLine
= pTabBox
->GetUpper();
297 const SwTableBoxes
& rTabBoxes
= pTabLine
->GetTabBoxes();
299 pWidths
= std::make_shared
<Widths
>();
300 // number of cell written
301 sal_uInt32 nBoxes
= rTabBoxes
.size();
302 if (nBoxes
> MAXTABLECELLS
)
303 nBoxes
= MAXTABLECELLS
;
305 for (sal_uInt32 n
= 0; n
< nBoxes
; n
++)
307 const SwFrameFormat
* pBoxFormat
= rTabBoxes
[ n
]->GetFrameFormat();
308 const SwFormatFrameSize
& rLSz
= pBoxFormat
->GetFrameSize();
310 pWidths
->push_back(rLSz
.GetWidth());
314 pWidths
= pCellGrid
->getWidthsOfRow(this);
319 RowSpansPtr
WW8TableNodeInfoInner::getRowSpansOfRow()
321 RowSpansPtr
pResult(new RowSpans
);
323 WW8TableCellGrid::Pointer_t pCellGrid
=
324 mpParent
->getParent()->getCellGridForTable(getTable(), false);
326 if (pCellGrid
.get() == nullptr)
328 const SwTableBox
* pTabBox
= getTableBox();
329 const SwTableLine
* pTabLine
= pTabBox
->GetUpper();
330 const SwTableBoxes
& rTabBoxes
= pTabLine
->GetTabBoxes();
332 sal_uInt32 nBoxes
= rTabBoxes
.size();
333 if (nBoxes
> MAXTABLECELLS
)
334 nBoxes
= MAXTABLECELLS
;
336 for (sal_uInt32 n
= 0; n
< nBoxes
; ++n
)
338 pResult
->push_back(rTabBoxes
[n
]->getRowSpan());
342 pResult
= pCellGrid
->getRowSpansOfRow(this);
349 std::string
WW8TableNodeInfoInner::toString() const
351 static char buffer
[256];
352 snprintf(buffer
, sizeof(buffer
),
353 "<tableinner depth=\"%" SAL_PRIuUINT32
"\""
354 " cell=\"%" SAL_PRIuUINT32
"\""
355 " row=\"%" SAL_PRIuUINT32
"\""
358 " shadowsBefore=\"%" SAL_PRIuUINT32
"\""
359 " shadowsAfter=\"%" SAL_PRIuUINT32
"\""
360 " vertMerge=\"%s\"/>",
361 mnDepth
, mnCell
, mnRow
,
362 mbEndOfCell
? "yes" : "no",
363 mbEndOfLine
? "yes" : "no",
366 mbVertMerge
? "yes" : "no");
368 return std::string(buffer
);
372 WW8TableNodeInfo::WW8TableNodeInfo(WW8TableInfo
* pParent
,
373 const SwNode
* pNode
)
382 WW8TableNodeInfo::~WW8TableNodeInfo()
387 std::string
WW8TableNodeInfo::toString() const
389 static char buffer
[1024];
390 snprintf(buffer
, sizeof(buffer
),
391 "<tableNodeInfo p=\"%p\" depth=\"%" SAL_PRIuUINT32
"\">"
394 std::string
sResult(buffer
);
396 Inners_t::const_iterator
aIt(mInners
.begin());
397 Inners_t::const_iterator
aEnd(mInners
.end());
401 WW8TableNodeInfoInner::Pointer_t pInner
= aIt
->second
;
402 sResult
+= pInner
->toString();
406 sResult
+= dbg_out(*mpNode
);
407 sResult
+= "</tableNodeInfo>";
413 void WW8TableNodeInfo::setDepth(sal_uInt32 nDepth
)
417 Inners_t::iterator aIt
= mInners
.find(mnDepth
);
419 if (aIt
== mInners
.end())
420 mInners
[mnDepth
] = std::make_shared
<ww8::WW8TableNodeInfoInner
>(this);
422 mInners
[mnDepth
]->setDepth(mnDepth
);
425 void WW8TableNodeInfo::setEndOfLine(bool bEndOfLine
)
427 WW8TableNodeInfoInner::Pointer_t pInner
= getInnerForDepth(mnDepth
);
428 pInner
->setEndOfLine(bEndOfLine
);
431 SAL_INFO( "sw.ww8", "<endOfLine depth=\"" << mnDepth
<< "\">" << toString() << "</endOfLine>" );
435 void WW8TableNodeInfo::setEndOfCell(bool bEndOfCell
)
437 WW8TableNodeInfoInner::Pointer_t pInner
= getInnerForDepth(mnDepth
);
438 pInner
->setEndOfCell(bEndOfCell
);
441 SAL_INFO( "sw.ww8", "<endOfCell depth=\"" << mnDepth
<< "\">" << toString() << "</endOfCell>" );
445 void WW8TableNodeInfo::setFirstInTable(bool bFirstInTable
)
447 WW8TableNodeInfoInner::Pointer_t pInner
= getInnerForDepth(mnDepth
);
449 pInner
->setFirstInTable(bFirstInTable
);
452 SAL_INFO( "sw.ww8", "<firstInTable depth=\"" << mnDepth
<< "\">" << toString() << "</firstInTable>" );
456 void WW8TableNodeInfo::setVertMerge(bool bVertMerge
)
458 WW8TableNodeInfoInner::Pointer_t pInner
= getInnerForDepth(mnDepth
);
460 pInner
->setVertMerge(bVertMerge
);
463 SAL_INFO( "sw.ww8", "<vertMerge depth=\"" << mnDepth
<< "\">" << toString() << "</vertMerge>" );
467 void WW8TableNodeInfo::setTableBox(const SwTableBox
* pTableBox
)
469 getInnerForDepth(mnDepth
)->setTableBox(pTableBox
);
472 void WW8TableNodeInfo::setTable(const SwTable
* pTable
)
474 getInnerForDepth(mnDepth
)->setTable(pTable
);
477 void WW8TableNodeInfo::setNext(WW8TableNodeInfo
* pNext
)
482 SAL_INFO( "sw.ww8", "<setnext><from>" << toString() << "</from><to>" << pNext
->toString() << "</to></setnext>" );
486 void WW8TableNodeInfo::setNextNode(const SwNode
* pNode
)
491 void WW8TableNodeInfo::setRect(const SwRect
& rRect
)
493 getInnerForDepth(mnDepth
)->setRect(rRect
);
496 void WW8TableNodeInfo::setCell(sal_uInt32 nCell
)
498 getInnerForDepth(mnDepth
)->setCell(nCell
);
501 void WW8TableNodeInfo::setRow(sal_uInt32 nRow
)
503 getInnerForDepth(mnDepth
)->setRow(nRow
);
506 void WW8TableNodeInfo::setShadowsBefore(sal_uInt32 nShadowsBefore
)
508 getInnerForDepth(mnDepth
)->setShadowsBefore(nShadowsBefore
);
511 void WW8TableNodeInfo::setShadowsAfter(sal_uInt32 nShadowsAfter
)
513 getInnerForDepth(mnDepth
)->setShadowsAfter(nShadowsAfter
);
517 sal_uInt32
WW8TableNodeInfo::getDepth() const
519 if (!mInners
.empty())
520 return mInners
.begin()->second
->getDepth();
526 const SwTableBox
* WW8TableNodeInfo::getTableBox() const
528 return getInnerForDepth(mnDepth
)->getTableBox();
531 sal_uInt32
WW8TableNodeInfo::getCell() const
533 return getInnerForDepth(mnDepth
)->getCell();
536 sal_uInt32
WW8TableNodeInfo::getRow() const
538 return getInnerForDepth(mnDepth
)->getRow();
541 const WW8TableNodeInfoInner::Pointer_t
WW8TableNodeInfo::getFirstInner() const
543 WW8TableNodeInfoInner::Pointer_t pResult
;
545 if (!mInners
.empty())
546 pResult
= mInners
.begin()->second
;
551 const WW8TableNodeInfoInner::Pointer_t
WW8TableNodeInfo::getInnerForDepth(sal_uInt32 nDepth
) const
553 WW8TableNodeInfoInner::Pointer_t pResult
;
555 Inners_t::const_iterator aIt
= mInners
.find(nDepth
);
556 if (aIt
!= mInners
.end())
558 pResult
= aIt
->second
;
564 WW8TableInfo::WW8TableInfo()
568 WW8TableInfo::~WW8TableInfo()
573 WW8TableInfo::processSwTableByLayout(const SwTable
* pTable
, RowEndInners_t
&rLastRowEnds
)
575 SwTableCellInfo
aTableCellInfo(pTable
);
577 while (aTableCellInfo
.getNext())
579 SwRect aRect
= aTableCellInfo
.getRect();
581 SAL_INFO( "sw.ww8", "<CellFrame>" );
582 SAL_INFO( "sw.ww8", "<rect top=\"" << aRect
.Top() << "\" bottom=\"" << aRect
.Bottom()
583 << "\" left=\"" << aRect
.Left() << "\" right=\"" << aRect
.Right() << "\"/>" );
584 const SwTableBox
* pTableBox
= aTableCellInfo
.getTableBox();
585 const SwStartNode
* pSttNd
= pTableBox
->GetSttNd();
587 if (pSttNd
!= nullptr)
589 SwPaM
aPam(*pSttNd
, 0);
594 SwNode
& rNode
= aPam
.GetPoint()->nNode
.GetNode();
596 insertTableNodeInfo(&rNode
, pTable
, pTableBox
, 0, 0, 1, & aRect
);
598 if (rNode
.IsEndNode())
600 SwEndNode
* pEndNode
= rNode
.GetEndNode();
601 SwStartNode
* pTmpSttNd
= pEndNode
->StartOfSectionNode();
603 if (pTmpSttNd
== pSttNd
)
607 aPam
.GetPoint()->nNode
++;
612 SAL_INFO( "sw.ww8", "</CellFrame>" );
615 return reorderByLayout(pTable
, rLastRowEnds
);
618 void WW8TableInfo::processSwTable(const SwTable
* pTable
)
620 SAL_INFO( "sw.ww8", "<processSwTable>" );
622 WW8TableNodeInfo
* pPrev
= nullptr;
623 RowEndInners_t aLastRowEnds
;
625 if (pTable
->IsTableComplex() && pTable
->HasLayout())
627 pPrev
= processSwTableByLayout(pTable
, aLastRowEnds
);
629 SAL_INFO( "sw.ww8", getCellGridForTable(pTable
)->toString());
634 const SwTableLines
& rLines
= pTable
->GetTabLines();
636 for (size_t n
= 0; n
< rLines
.size(); ++n
)
638 const SwTableLine
* pLine
= rLines
[n
];
640 pPrev
= processTableLine(pTable
, pLine
, static_cast<sal_uInt32
>(n
), 1, pPrev
, aLastRowEnds
);
647 SwTableNode
* pTableNode
= pTable
->GetTableNode();
648 SwEndNode
* pEndNode
= pTableNode
->EndOfSectionNode();
649 pPrev
->setNextNode(pEndNode
);
650 assert(!aLastRowEnds
.empty());
651 for (auto &a
: aLastRowEnds
)
653 assert(a
.second
->isEndOfLine());
654 a
.second
->setFinalEndOfLine(true);
657 SAL_INFO( "sw.ww8", "</processSwTable>" );
661 WW8TableInfo::processTableLine(const SwTable
* pTable
,
662 const SwTableLine
* pTableLine
,
665 WW8TableNodeInfo
* pPrev
,
666 RowEndInners_t
&rLastRowEnds
)
668 SAL_INFO( "sw.ww8", "<processTableLine row=\"" << nRow
<< "\" depth=\"" << nDepth
<< "\">" );
670 const SwTableBoxes
& rBoxes
= pTableLine
->GetTabBoxes();
672 WW8TableNodeInfo::Pointer_t pTextNodeInfo
;
674 for (size_t n
= 0; n
< rBoxes
.size(); ++n
)
676 const SwTableBox
* pBox
= rBoxes
[n
];
678 pPrev
= processTableBox(pTable
, pBox
, nRow
, static_cast<sal_uInt32
>(n
), nDepth
, n
== rBoxes
.size() - 1, pPrev
, rLastRowEnds
);
681 SAL_INFO( "sw.ww8", "</processTableLine>" );
686 WW8TableNodeInfo::Pointer_t
687 WW8TableInfo::processTableBoxLines(const SwTableBox
* pBox
,
688 const SwTable
* pTable
,
689 const SwTableBox
* pBoxToSet
,
694 SAL_INFO( "sw.ww8", "<processTableBoxLines depth=\"" << nDepth
<< "\" row=\"" << nRow
695 << "\" cell=\"" << nCell
<< "\">" );
697 const SwTableLines
& rLines
= pBox
->GetTabLines();
698 WW8TableNodeInfo::Pointer_t pNodeInfo
;
702 for (size_t n
= 0; n
< rLines
.size(); ++n
)
704 const SwTableLine
* pLine
= rLines
[n
];
705 const SwTableBoxes
& rBoxes
= pLine
->GetTabBoxes();
707 for (size_t nBox
= 0; nBox
< rBoxes
.size(); ++nBox
)
708 pNodeInfo
= processTableBoxLines(rBoxes
[nBox
], pTable
, pBoxToSet
, nRow
, nCell
, nDepth
);
713 const SwStartNode
* pSttNd
= pBox
->GetSttNd();
714 const SwEndNode
* pEndNd
= pSttNd
->EndOfSectionNode();
715 SwPaM
aPaM(*pSttNd
, 0);
716 SwPaM
aEndPaM(*pEndNd
, 0);
721 SwNode
& rNode
= aPaM
.GetPoint()->nNode
.GetNode();
723 pNodeInfo
= insertTableNodeInfo(&rNode
, pTable
, pBoxToSet
, nRow
, nCell
, nDepth
);
725 if (aPaM
.GetPoint()->nNode
== aEndPaM
.GetPoint()->nNode
)
728 aPaM
.GetPoint()->nNode
++;
732 SAL_INFO( "sw.ww8", "</processTableBoxLines>" );
737 void updateFinalEndOfLine(RowEndInners_t
&rLastRowEnds
, WW8TableNodeInfo
* pEndOfCellInfo
)
739 sal_Int32 nDepth
= pEndOfCellInfo
->getDepth();
740 WW8TableNodeInfoInner::Pointer_t pInner
= pEndOfCellInfo
->getInnerForDepth(nDepth
);
742 auto aIt
= rLastRowEnds
.find(nDepth
);
743 if (aIt
== rLastRowEnds
.end() || (pInner
->getRow() > aIt
->second
->getRow()))
744 rLastRowEnds
[nDepth
] = pInner
.get();
748 WW8TableInfo::processTableBox(const SwTable
* pTable
,
749 const SwTableBox
* pBox
,
754 WW8TableNodeInfo
* pPrev
,
755 RowEndInners_t
&rLastRowEnds
)
757 SAL_INFO( "sw.ww8", "<processTableBox row=\"" << nRow
<< "\" cell=\"" << nCell
758 << "\" depth=\"" << nDepth
<< "\">" );
760 WW8TableNodeInfo::Pointer_t pNodeInfo
;
761 const SwTableLines
& rLines
= pBox
->GetTabLines();
762 const SwStartNode
* pSttNd
= pBox
->GetSttNd();
763 WW8TableNodeInfo::Pointer_t pEndOfCellInfo
;
767 pNodeInfo
= processTableBoxLines(pBox
, pTable
, pBox
, nRow
, nCell
, nDepth
);
768 pNodeInfo
->setEndOfCell(true);
771 pNodeInfo
->setEndOfLine(true);
772 updateFinalEndOfLine(rLastRowEnds
, pNodeInfo
.get());
775 for (size_t n
= 0; n
< rLines
.size(); n
++)
777 const SwTableLine
* pLine
= rLines
[n
];
779 pPrev
= processTableLine(pTable
, pLine
, n
, 1, pPrev
, rLastRowEnds
);
784 SwPaM
aPaM(*pSttNd
, 0);
787 sal_uInt32 nDepthInsideCell
= 0;
791 SwNode
& rNode
= aPaM
.GetPoint()->nNode
.GetNode();
793 if (rNode
.IsStartNode())
795 if (nDepthInsideCell
> 0)
796 pEndOfCellInfo
.reset();
801 pNodeInfo
= insertTableNodeInfo(&rNode
, pTable
, pBox
, nRow
, nCell
, nDepth
);
804 pPrev
->setNext(pNodeInfo
.get());
806 pPrev
= pNodeInfo
.get();
808 if (nDepthInsideCell
== 1 && rNode
.IsTextNode())
809 pEndOfCellInfo
= pNodeInfo
;
811 if (rNode
.IsEndNode())
815 if (nDepthInsideCell
== 0 && !pEndOfCellInfo
)
816 pEndOfCellInfo
= pNodeInfo
;
818 SwEndNode
* pEndNode
= rNode
.GetEndNode( );
819 SwStartNode
* pTmpSttNd
= pEndNode
->StartOfSectionNode();
820 if (pTmpSttNd
== pSttNd
)
824 aPaM
.GetPoint()->nNode
++;
828 if (pEndOfCellInfo
.get() != nullptr)
830 pEndOfCellInfo
->setEndOfCell(true);
834 pEndOfCellInfo
->setEndOfLine(true);
835 updateFinalEndOfLine(rLastRowEnds
, pEndOfCellInfo
.get());
840 SAL_INFO( "sw.ww8", "</processTableBox>" );
845 WW8TableNodeInfo::Pointer_t
WW8TableInfo::insertTableNodeInfo
846 (const SwNode
* pNode
,
847 const SwTable
* pTable
,
848 const SwTableBox
* pTableBox
,
854 WW8TableNodeInfo::Pointer_t pNodeInfo
= getTableNodeInfo(pNode
);
856 if (pNodeInfo
.get() == nullptr)
859 std::make_shared
<ww8::WW8TableNodeInfo
>(this, pNode
);
860 mMap
.insert(Map_t::value_type(pNode
, pNodeInfo
));
863 pNodeInfo
->setDepth(nDepth
+ pNodeInfo
->getDepth());
865 pNodeInfo
->setTable(pTable
);
866 pNodeInfo
->setTableBox(pTableBox
);
868 pNodeInfo
->setCell(nCell
);
869 pNodeInfo
->setRow(nRow
);
871 if (pNode
->IsTextNode())
873 FirstInTableMap_t::const_iterator aIt
= mFirstInTableMap
.find(pTable
);
874 if (aIt
== mFirstInTableMap
.end())
876 mFirstInTableMap
[pTable
] = pNode
;
877 pNodeInfo
->setFirstInTable(true);
883 WW8TableCellGrid::Pointer_t pCellGrid
= getCellGridForTable(pTable
);
885 pCellGrid
->insert(*pRect
, pNodeInfo
.get());
886 pNodeInfo
->setRect(*pRect
);
890 SAL_INFO( "sw.ww8", pNodeInfo
->toString());
895 WW8TableCellGrid::Pointer_t
WW8TableInfo::getCellGridForTable
896 (const SwTable
* pTable
, bool bCreate
)
898 WW8TableCellGrid::Pointer_t pResult
;
899 CellGridMap_t::iterator aIt
= mCellGridMap
.find(pTable
);
901 if (aIt
== mCellGridMap
.end())
905 pResult
= std::make_shared
<ww8::WW8TableCellGrid
>();
906 mCellGridMap
[pTable
] = pResult
;
910 pResult
= mCellGridMap
[pTable
];
915 WW8TableNodeInfo::Pointer_t
WW8TableInfo::getTableNodeInfo
916 (const SwNode
* pNode
)
918 WW8TableNodeInfo::Pointer_t pResult
;
919 Map_t::iterator aIt
= mMap
.find(pNode
);
921 if (aIt
!= mMap
.end())
922 pResult
= (*aIt
).second
;
927 const SwNode
* WW8TableInfo::getNextNode(const SwNode
* pNode
)
929 const SwNode
* pResult
= nullptr;
931 WW8TableNodeInfo::Pointer_t pNodeInfo
= getTableNodeInfo(pNode
);
933 if (pNodeInfo
.get() != nullptr)
935 WW8TableNodeInfo
* pNextInfo
= pNodeInfo
->getNext();
937 if (pNextInfo
!= nullptr)
938 pResult
= pNextInfo
->getNode();
941 const SwNode
* pNextNode
= pNodeInfo
->getNextNode();
943 if (pNextNode
!= nullptr)
951 bool WW8TableNodeInfo::operator < (const WW8TableNodeInfo
& rInfo
) const
955 if (rInfo
.mpNode
!= nullptr)
957 if (mpNode
== nullptr)
963 if (mpNode
->GetIndex() < rInfo
.mpNode
->GetIndex())
971 bool CellInfo::operator < (const CellInfo
& aCellInfo
) const
975 if (top() < aCellInfo
.top())
977 else if (top() == aCellInfo
.top())
979 if (left() < aCellInfo
.left())
981 else if (left() == aCellInfo
.left())
983 if (width() < aCellInfo
.width())
985 else if (width() == aCellInfo
.width())
987 if (height() < aCellInfo
.height())
989 else if (height() == aCellInfo
.height())
991 if (aCellInfo
.getTableNodeInfo())
993 if (m_pNodeInfo
== nullptr)
997 aRet
= *m_pNodeInfo
< *aCellInfo
.getTableNodeInfo();
1009 std::string
CellInfo::toString() const
1011 static char sBuffer
[256];
1013 snprintf(sBuffer
, sizeof(sBuffer
),
1014 "<cellinfo left=\"%ld\""
1029 WW8TableNodeInfo
* WW8TableInfo::reorderByLayout(const SwTable
* pTable
, RowEndInners_t
&rLastRowEnds
)
1031 WW8TableCellGrid::Pointer_t pCellGrid
= getCellGridForTable(pTable
);
1034 SAL_INFO( "sw.ww8", pCellGrid
->toString());
1037 pCellGrid
->addShadowCells();
1038 return pCellGrid
->connectCells(rLastRowEnds
);
1041 WW8TableCellGrid::WW8TableCellGrid()
1045 WW8TableCellGrid::~WW8TableCellGrid()
1049 WW8TableCellGridRow::Pointer_t
WW8TableCellGrid::getRow(long nTop
, bool bCreate
)
1051 WW8TableCellGridRow::Pointer_t pResult
;
1053 RowTops_t::iterator aIt
= m_aRowTops
.find(nTop
);
1055 if (aIt
== m_aRowTops
.end())
1059 pResult
= std::make_shared
<ww8::WW8TableCellGridRow
>();
1060 m_aRows
[nTop
] = pResult
;
1061 m_aRowTops
.insert(nTop
);
1065 pResult
= m_aRows
[nTop
];
1070 WW8TableCellGrid::RowTops_t::const_iterator
WW8TableCellGrid::getRowTopsBegin() const
1072 return m_aRowTops
.begin();
1075 WW8TableCellGrid::RowTops_t::const_iterator
WW8TableCellGrid::getRowTopsEnd() const
1077 return m_aRowTops
.end();
1080 CellInfoMultiSet::const_iterator
WW8TableCellGrid::getCellsBegin(long nTop
)
1082 return getRow(nTop
)->begin();
1085 CellInfoMultiSet::const_iterator
WW8TableCellGrid::getCellsEnd(long nTop
)
1087 return getRow(nTop
)->end();
1090 void WW8TableCellGrid::insert(const SwRect
& rRect
,
1091 WW8TableNodeInfo
* pNodeInfo
,
1092 unsigned long * pFormatFrameWidth
)
1094 CellInfo
aCellInfo(rRect
, pNodeInfo
);
1096 if (pFormatFrameWidth
!= nullptr)
1097 aCellInfo
.setFormatFrameWidth(*pFormatFrameWidth
);
1099 WW8TableCellGridRow::Pointer_t pRow
= getRow(rRect
.Top());
1100 pRow
->insert(aCellInfo
);
1103 void WW8TableCellGrid::addShadowCells()
1105 SAL_INFO( "sw.ww8", "<addShadowCells>" );
1107 RowTops_t::const_iterator aTopsIt
= getRowTopsBegin();
1109 while (aTopsIt
!= getRowTopsEnd())
1112 long nTop
= *aTopsIt
;
1115 CellInfoMultiSet::const_iterator aCellIt
= getCellsBegin(*aTopsIt
);
1116 CellInfoMultiSet::const_iterator aCellEndIt
= getCellsEnd(*aTopsIt
);
1118 RowSpansPtr
pRowSpans(new RowSpans
);
1120 bool bBeginningOfCell
= true;
1121 bool bVertMerge
= false;
1122 SwRect aRect
= aCellIt
->getRect();
1124 while (aCellIt
!= aCellEndIt
)
1126 WW8TableNodeInfo
* pNodeInfo
= aCellIt
->getTableNodeInfo();
1128 if (bBeginningOfCell
)
1130 RowTops_t::const_iterator
aRowSpanIt(aTopsIt
);
1133 if (aRowSpanIt
!= getRowTopsEnd() &&
1134 *aRowSpanIt
< aCellIt
->bottom())
1136 aRect
.Top(*aRowSpanIt
);
1137 unsigned long nFormatFrameWidth
= aCellIt
->getFormatFrameWidth();
1138 insert(aRect
, nullptr, &nFormatFrameWidth
);
1146 while (aRowSpanIt
!= getRowTopsEnd() &&
1147 *aRowSpanIt
< aCellIt
->bottom())
1154 pRowSpans
->push_back(nRowSpan
);
1156 pRowSpans
->push_back(-nRowSpan
);
1161 pNodeInfo
->setVertMerge(bVertMerge
);
1165 if (aCellIt
!= aCellEndIt
)
1167 bBeginningOfCell
= (aRect
.Left() != aCellIt
->left());
1168 aRect
= aCellIt
->getRect();
1172 WW8TableCellGridRow::Pointer_t pRow
= getRow(*aTopsIt
);
1173 if (pRow
.get() != nullptr)
1174 pRow
->setRowSpans(pRowSpans
);
1178 SAL_INFO( "sw.ww8", "</addShadowCells>" );
1181 WW8TableNodeInfo
* WW8TableCellGrid::connectCells(RowEndInners_t
&rLastRowEnds
)
1183 RowTops_t::const_iterator aTopsIt
= getRowTopsBegin();
1184 sal_uInt32 nRow
= 0;
1185 WW8TableNodeInfo
* pLastNodeInfo
= nullptr;
1187 while (aTopsIt
!= getRowTopsEnd())
1189 CellInfoMultiSet::const_iterator aCellIt
= getCellsBegin(*aTopsIt
);
1190 CellInfoMultiSet::const_iterator aCellEndIt
= getCellsEnd(*aTopsIt
);
1191 GridColsPtr
pWidths(new Widths
);
1192 TableBoxVectorPtr
pTableBoxes(new TableBoxVector
);
1194 sal_uInt32 nShadows
= 0;
1195 sal_uInt32 nCell
= 0;
1196 bool bBeginningOfCell
= true;
1197 WW8TableNodeInfo
* pEndOfCellInfo
= nullptr;
1198 sal_uInt32 nDepthInCell
= 0;
1199 while (aCellIt
!= aCellEndIt
)
1201 long nCellX
= aCellIt
->left();
1202 WW8TableNodeInfo
* pNodeInfo
= aCellIt
->getTableNodeInfo();
1205 const SwNode
* pNode
= pNodeInfo
->getNode();
1207 if (pNode
->IsStartNode())
1210 pEndOfCellInfo
= nullptr;
1213 if (nDepthInCell
== 1 && pNode
->IsTextNode())
1214 pEndOfCellInfo
= pNodeInfo
;
1216 pNodeInfo
->setShadowsBefore(nShadows
);
1217 pNodeInfo
->setCell(nCell
);
1218 pNodeInfo
->setRow(nRow
);
1221 pLastNodeInfo
->setNext(pNodeInfo
);
1222 pLastNodeInfo
->setNextNode(pNode
);
1224 pLastNodeInfo
= pNodeInfo
;
1227 if (pNode
->IsEndNode())
1231 if (nDepthInCell
== 0 && !pEndOfCellInfo
)
1232 pEndOfCellInfo
= pNodeInfo
;
1240 if (bBeginningOfCell
)
1242 pWidths
->push_back(aCellIt
->getFormatFrameWidth());
1245 pTableBoxes
->push_back(pNodeInfo
->getTableBox());
1247 pTableBoxes
->push_back(nullptr);
1251 bBeginningOfCell
= false;
1253 if (aCellIt
!= aCellEndIt
&& aCellIt
->left() != nCellX
)
1256 bBeginningOfCell
= true;
1260 pEndOfCellInfo
->setEndOfCell(true);
1263 pEndOfCellInfo
= nullptr;
1267 pLastNodeInfo
->setShadowsAfter(nShadows
);
1269 if (!pEndOfCellInfo
)
1271 pEndOfCellInfo
= pLastNodeInfo
;
1274 pEndOfCellInfo
->setEndOfCell(true);
1275 pLastNodeInfo
->setEndOfLine(true);
1276 updateFinalEndOfLine(rLastRowEnds
, pLastNodeInfo
);
1278 WW8TableCellGridRow::Pointer_t
pRow(getRow(*aTopsIt
));
1279 pRow
->setTableBoxVector(pTableBoxes
);
1280 pRow
->setWidths(pWidths
);
1286 return pLastNodeInfo
;
1290 std::string
WW8TableCellGrid::toString()
1292 std::string sResult
= "<WW8TableCellGrid>";
1294 RowTops_t::const_iterator aTopsIt
= getRowTopsBegin();
1295 static char sBuffer
[1024];
1296 while (aTopsIt
!= getRowTopsEnd())
1298 sprintf(sBuffer
, "<row y=\"%ld\">", *aTopsIt
);
1301 CellInfoMultiSet::const_iterator aCellIt
= getCellsBegin(*aTopsIt
);
1302 CellInfoMultiSet::const_iterator aCellsEnd
= getCellsEnd(*aTopsIt
);
1304 while (aCellIt
!= aCellsEnd
)
1306 snprintf(sBuffer
, sizeof(sBuffer
), "<cellInfo top=\"%ld\" bottom=\"%ld\" left=\"%ld\" right=\"%ld\">",
1307 aCellIt
->top(), aCellIt
->bottom(), aCellIt
->left(), aCellIt
->right());
1310 WW8TableNodeInfo
* pInfo
= aCellIt
->getTableNodeInfo();
1312 sResult
+= pInfo
->toString();
1314 sResult
+= "<shadow/>\n";
1316 sResult
+= "</cellInfo>\n";
1320 WW8TableCellGridRow::Pointer_t pRow
= getRow(*aTopsIt
);
1321 WidthsPtr pWidths
= pRow
->getWidths();
1322 if (pWidths
!= nullptr)
1324 sResult
+= "<widths>";
1326 Widths::const_iterator aItEnd
= pWidths
->end();
1327 for (Widths::const_iterator aIt
= pWidths
->begin();
1331 if (aIt
!= pWidths
->begin())
1334 snprintf(sBuffer
, sizeof(sBuffer
), "%" SAL_PRIxUINT32
"", *aIt
);
1338 sResult
+= "</widths>";
1341 RowSpansPtr pRowSpans
= pRow
->getRowSpans();
1342 if (pRowSpans
.get() != nullptr)
1344 sResult
+= "<rowspans>";
1346 RowSpans::const_iterator aItEnd
= pRowSpans
->end();
1347 for (RowSpans::const_iterator aIt
= pRowSpans
->begin();
1351 if (aIt
!= pRowSpans
->begin())
1354 snprintf(sBuffer
, sizeof(sBuffer
), "%" SAL_PRIxUINT32
"", *aIt
);
1358 sResult
+= "</rowspans>";
1361 sResult
+= "</row>\n";
1365 sResult
+= "</WW8TableCellGrid>\n";
1371 TableBoxVectorPtr
WW8TableCellGrid::getTableBoxesOfRow
1372 (WW8TableNodeInfoInner
* pNodeInfoInner
)
1374 TableBoxVectorPtr pResult
;
1375 WW8TableCellGridRow::Pointer_t pRow
=
1376 getRow(pNodeInfoInner
->getRect().Top(), false);
1378 if (pRow
.get() != nullptr)
1380 pResult
= pRow
->getTableBoxVector();
1386 WidthsPtr
WW8TableCellGrid::getWidthsOfRow
1387 (WW8TableNodeInfoInner
* pNodeInfoInner
)
1389 GridColsPtr pResult
;
1391 WW8TableCellGridRow::Pointer_t pRow
=
1392 getRow(pNodeInfoInner
->getRect().Top(), false);
1394 if (pRow
.get() != nullptr)
1396 pResult
= pRow
->getWidths();
1402 RowSpansPtr
WW8TableCellGrid::getRowSpansOfRow
1403 (WW8TableNodeInfoInner
* pNodeInfoInner
)
1405 RowSpansPtr pResult
;
1407 WW8TableCellGridRow::Pointer_t pRow
=
1408 getRow(pNodeInfoInner
->getRect().Top(), false);
1410 if (pRow
.get() != nullptr)
1412 pResult
= pRow
->getRowSpans();
1418 WW8TableCellGridRow::WW8TableCellGridRow()
1419 : m_pCellInfos(new CellInfoMultiSet
)
1423 WW8TableCellGridRow::~WW8TableCellGridRow()
1427 void WW8TableCellGridRow::insert(const CellInfo
& rCellInfo
)
1429 m_pCellInfos
->insert(rCellInfo
);
1432 SAL_INFO( "sw.ww8", "<gridRowInsert>" << rCellInfo
.toString() << "</gridRowInsert>" );
1436 CellInfoMultiSet::const_iterator
WW8TableCellGridRow::begin() const
1438 return m_pCellInfos
->begin();
1441 CellInfoMultiSet::const_iterator
WW8TableCellGridRow::end() const
1443 return m_pCellInfos
->end();
1446 void WW8TableCellGridRow::setTableBoxVector(TableBoxVectorPtr
const & pTableBoxVector
)
1448 if (pTableBoxVector
->size() > MAXTABLECELLS
)
1449 pTableBoxVector
->resize(MAXTABLECELLS
);
1450 m_pTableBoxVector
= pTableBoxVector
;
1453 void WW8TableCellGridRow::setWidths(WidthsPtr
const & pWidths
)
1455 m_pWidths
= pWidths
;
1458 void WW8TableCellGridRow::setRowSpans(RowSpansPtr
const & pRowSpans
)
1460 m_pRowSpans
= pRowSpans
;
1464 CellInfo::CellInfo(const SwRect
& aRect
, WW8TableNodeInfo
* pNodeInfo
)
1465 : m_aRect(aRect
), m_pNodeInfo(pNodeInfo
), m_nFormatFrameWidth(0)
1467 if (pNodeInfo
!= nullptr)
1469 const SwTableBox
* pBox
= pNodeInfo
->getTableBox();
1470 const SwFrameFormat
* pFrameFormat
= pBox
->GetFrameFormat();
1471 const SwFormatFrameSize
& rSize
= pFrameFormat
->GetFrameSize();
1473 m_nFormatFrameWidth
= rSize
.GetWidth();
1479 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */