1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20 #include <iostream>
21 #include <stdio.h>
22 #include "WW8TableInfo.hxx"
23 #include <fmtfsize.hxx>
24 #include "attributeoutputbase.hxx"
25 #include <swtable.hxx>
26 #include <frmfmt.hxx>
27 #include <pam.hxx>
28 #include <dbgoutsw.hxx>
29 #include <sal/log.hxx>
30 #include <osl/diagnose.h>
31
32 namespace ww8
33 {
34
WW8TableNodeInfoInner(WW8TableNodeInfo * pParent)35 WW8TableNodeInfoInner::WW8TableNodeInfoInner(WW8TableNodeInfo * pParent)
36 : mpParent(pParent)
37 , mnDepth(0)
38 , mnCell(0)
39 , mnRow(0)
40 , mnShadowsBefore(0)
41 , mnShadowsAfter(0)
42 , mbEndOfLine(false)
43 , mbFinalEndOfLine(false)
44 , mbEndOfCell(false)
45 , mbFirstInTable(false)
46 , mbVertMerge(false)
47 , mpTableBox(nullptr)
48 , mpTable(nullptr)
49 {
50 }
51
~WW8TableNodeInfoInner()52 WW8TableNodeInfoInner::~WW8TableNodeInfoInner()
53 {
54 }
55
setDepth(sal_uInt32 nDepth)56 void WW8TableNodeInfoInner::setDepth(sal_uInt32 nDepth)
57 {
58 mnDepth = nDepth;
59 }
60
setCell(sal_uInt32 nCell)61 void WW8TableNodeInfoInner::setCell(sal_uInt32 nCell)
62 {
63 mnCell = nCell;
64 }
65
setRow(sal_uInt32 nRow)66 void WW8TableNodeInfoInner::setRow(sal_uInt32 nRow)
67 {
68 mnRow = nRow;
69 }
70
setShadowsBefore(sal_uInt32 nShadowsBefore)71 void WW8TableNodeInfoInner::setShadowsBefore(sal_uInt32 nShadowsBefore)
72 {
73 mnShadowsBefore = nShadowsBefore;
74 }
75
setShadowsAfter(sal_uInt32 nShadowsAfter)76 void WW8TableNodeInfoInner::setShadowsAfter(sal_uInt32 nShadowsAfter)
77 {
78 mnShadowsAfter = nShadowsAfter;
79 }
80
setEndOfLine(bool bEndOfLine)81 void WW8TableNodeInfoInner::setEndOfLine(bool bEndOfLine)
82 {
83 mbEndOfLine = bEndOfLine;
84 }
85
setFinalEndOfLine(bool bFinalEndOfLine)86 void WW8TableNodeInfoInner::setFinalEndOfLine(bool bFinalEndOfLine)
87 {
88 mbFinalEndOfLine = bFinalEndOfLine;
89 }
90
setEndOfCell(bool bEndOfCell)91 void WW8TableNodeInfoInner::setEndOfCell(bool bEndOfCell)
92 {
93 mbEndOfCell = bEndOfCell;
94 }
95
setFirstInTable(bool bFirstInTable)96 void WW8TableNodeInfoInner::setFirstInTable(bool bFirstInTable)
97 {
98 mbFirstInTable = bFirstInTable;
99 }
100
setVertMerge(bool bVertMerge)101 void WW8TableNodeInfoInner::setVertMerge(bool bVertMerge)
102
103 {
104 mbVertMerge = bVertMerge;
105 }
106
setTableBox(const SwTableBox * pTableBox)107 void WW8TableNodeInfoInner::setTableBox(const SwTableBox * pTableBox)
108 {
109 mpTableBox = pTableBox;
110 }
111
setTable(const SwTable * pTable)112 void WW8TableNodeInfoInner::setTable(const SwTable * pTable)
113 {
114 mpTable = pTable;
115 }
116
setRect(const SwRect & rRect)117 void WW8TableNodeInfoInner::setRect(const SwRect & rRect)
118 {
119 maRect = rRect;
120 }
121
getNode() const122 const SwNode * WW8TableNodeInfoInner::getNode() const
123 {
124 const SwNode * pResult = nullptr;
125
126 if (mpParent != nullptr)
127 pResult = mpParent->getNode();
128
129 return pResult;
130 }
131
getTableBoxesOfRow() const132 TableBoxVectorPtr WW8TableNodeInfoInner::getTableBoxesOfRow() const
133 {
134 TableBoxVectorPtr pResult = std::make_shared<TableBoxVector>();
135
136 WW8TableCellGrid::Pointer_t pCellGrid =
137 mpParent->getParent()->getCellGridForTable(getTable(), false);
138
139 if (!pCellGrid)
140 {
141 const SwTableLine * pTabLine = getTableBox()->GetUpper();
142 const SwTableBoxes & rTableBoxes = pTabLine->GetTabBoxes();
143
144 sal_uInt8 nBoxes = rTableBoxes.size();
145 if (nBoxes > MAXTABLECELLS)
146 nBoxes = MAXTABLECELLS;
147 for ( sal_uInt8 n = 0; n < nBoxes; n++ )
148 {
149 pResult->push_back(rTableBoxes[n]);
150 }
151 }
152 else
153 pResult = pCellGrid->getTableBoxesOfRow(this);
154
155 return pResult;
156 }
157
getGridColsOfRow(AttributeOutputBase & rBase,bool calculateColumnsFromAllRows)158 GridColsPtr WW8TableNodeInfoInner::getGridColsOfRow(AttributeOutputBase & rBase, bool calculateColumnsFromAllRows)
159 {
160 GridColsPtr pResult = std::make_shared<GridCols>();
161 WidthsPtr pWidths;
162
163 // Check which columns should be checked - only the current row,
164 // or all the rows together
165 if (calculateColumnsFromAllRows)
166 {
167 // Calculate the width of all the columns based on ALL the rows.
168 // The difference is that this kind of draws vertical lines,
169 // so that if the rows look like this:
170 //
171 // ------------------------
172 // | | |
173 // ------------------------
174 // | | |
175 // ------------------------
176 // | | |
177 // ------------------------
178
179 // then the actual column widths will be broken down like this:
180 //
181 // ------------------------
182 // | | | | |
183 // ------------------------
184
185 // See the example at
186 // http://officeopenxml.com/WPtableGrid.php
187 // Under "Word 2007 Example"
188 pWidths = getColumnWidthsBasedOnAllRows();
189 }
190 else
191 {
192 // Calculate the width of all the columns based on the current row
193 pWidths = getWidthsOfRow();
194 }
195
196 const SwFrameFormat *pFormat = getTable()->GetFrameFormat();
197 OSL_ENSURE(pFormat,"Impossible");
198 if (!pFormat)
199 return pResult;
200
201 const SwFormatFrameSize &rSize = pFormat->GetFrameSize();
202 tools::ULong nTableSz = static_cast<tools::ULong>(rSize.GetWidth());
203
204 tools::Long nPageSize = 0;
205 bool bRelBoxSize = false;
206
207 rBase.GetTablePageSize( this, nPageSize, bRelBoxSize );
208
209 SwTwips nSz = 0;
210 for (const auto& rWidth : *pWidths)
211 {
212 nSz += rWidth;
213 SwTwips nCalc = nSz;
214 if ( bRelBoxSize )
215 nCalc = ( nCalc * nPageSize ) / nTableSz;
216
217 pResult->push_back( nCalc );
218 }
219
220 return pResult;
221 }
222
getColumnWidthsBasedOnAllRows() const223 WidthsPtr WW8TableNodeInfoInner::getColumnWidthsBasedOnAllRows() const
224 {
225 WidthsPtr pWidths;
226
227 WW8TableCellGrid::Pointer_t pCellGrid =
228 mpParent->getParent()->getCellGridForTable(getTable(), false);
229
230 if (!pCellGrid)
231 {
232 const SwTable * pTable = getTable();
233 const SwTableLines& rTableLines = pTable->GetTabLines();
234 const size_t nNumOfLines = rTableLines.size();
235
236 // Go over all the rows - and for each row - calculate where
237 // there is a separator between columns
238 WidthsPtr pSeparators = std::make_shared<Widths>();
239 for ( size_t nLineIndex = 0; nLineIndex < nNumOfLines; ++nLineIndex )
240 {
241 const SwTableLine *pCurrentLine = rTableLines[nLineIndex];
242 const SwTableBoxes & rTabBoxes = pCurrentLine->GetTabBoxes();
243 size_t nBoxes = rTabBoxes.size();
244 if (nBoxes > MAXTABLECELLS)
245 nBoxes = MAXTABLECELLS;
246
247 sal_uInt32 nSeparatorPosition = 0;
248 for (size_t nBoxIndex = 0; nBoxIndex < nBoxes; ++nBoxIndex)
249 {
250 const SwFrameFormat* pBoxFormat = rTabBoxes[ nBoxIndex ]->GetFrameFormat();
251 const SwFormatFrameSize& rLSz = pBoxFormat->GetFrameSize();
252 nSeparatorPosition += rLSz.GetWidth();
253 pSeparators->push_back(nSeparatorPosition);
254 }
255 }
256
257 // Sort the separator positions and remove any duplicates
258 std::sort(pSeparators->begin(), pSeparators->end());
259 std::vector<sal_uInt32>::iterator it = std::unique(pSeparators->begin(), pSeparators->end());
260 pSeparators->erase(it, pSeparators->end());
261
262 // Calculate the widths based on the position of the unique & sorted
263 // column separators
264 pWidths = std::make_shared<Widths>();
265 sal_uInt32 nPreviousWidth = 0;
266 for (const sal_uInt32 nCurrentWidth : *pSeparators)
267 {
268 pWidths->push_back(nCurrentWidth - nPreviousWidth);
269 nPreviousWidth = nCurrentWidth;
270 }
271 }
272 else
273 {
274 pWidths = pCellGrid->getWidthsOfRow(this);
275 }
276
277 return pWidths;
278 }
279
getWidthsOfRow() const280 WidthsPtr WW8TableNodeInfoInner::getWidthsOfRow() const
281 {
282 WidthsPtr pWidths;
283
284 WW8TableCellGrid::Pointer_t pCellGrid =
285 mpParent->getParent()->getCellGridForTable(getTable(), false);
286
287 if (!pCellGrid)
288 {
289 const SwTableBox * pTabBox = getTableBox();
290 const SwTableLine * pTabLine = pTabBox->GetUpper();
291 const SwTableBoxes & rTabBoxes = pTabLine->GetTabBoxes();
292
293 pWidths = std::make_shared<Widths>();
294 // number of cell written
295 sal_uInt32 nBoxes = rTabBoxes.size();
296 if (nBoxes > MAXTABLECELLS)
297 nBoxes = MAXTABLECELLS;
298
299 for (sal_uInt32 n = 0; n < nBoxes; n++)
300 {
301 const SwFrameFormat* pBoxFormat = rTabBoxes[ n ]->GetFrameFormat();
302 const SwFormatFrameSize& rLSz = pBoxFormat->GetFrameSize();
303
304 pWidths->push_back(rLSz.GetWidth());
305 }
306 }
307 else
308 pWidths = pCellGrid->getWidthsOfRow(this);
309
310 return pWidths;
311 }
312
getRowSpansOfRow() const313 RowSpansPtr WW8TableNodeInfoInner::getRowSpansOfRow() const
314 {
315 RowSpansPtr pResult = std::make_shared<RowSpans>();
316
317 WW8TableCellGrid::Pointer_t pCellGrid =
318 mpParent->getParent()->getCellGridForTable(getTable(), false);
319
320 if (!pCellGrid)
321 {
322 const SwTableBox * pTabBox = getTableBox();
323 const SwTableLine * pTabLine = pTabBox->GetUpper();
324 const SwTableBoxes & rTabBoxes = pTabLine->GetTabBoxes();
325
326 sal_uInt32 nBoxes = rTabBoxes.size();
327 if (nBoxes > MAXTABLECELLS)
328 nBoxes = MAXTABLECELLS;
329
330 for (sal_uInt32 n = 0; n < nBoxes; ++n)
331 {
332 pResult->push_back(rTabBoxes[n]->getRowSpan());
333 }
334 }
335 else
336 pResult = pCellGrid->getRowSpansOfRow(this);
337
338 return pResult;
339 }
340
341
342 #ifdef DBG_UTIL
toString() const343 std::string WW8TableNodeInfoInner::toString() const
344 {
345 static char buffer[256];
346 snprintf(buffer, sizeof(buffer),
347 "<tableinner depth=\"%" SAL_PRIuUINT32 "\""
348 " cell=\"%" SAL_PRIuUINT32 "\""
349 " row=\"%" SAL_PRIuUINT32 "\""
350 " endOfCell=\"%s\""
351 " endOfLine=\"%s\""
352 " shadowsBefore=\"%" SAL_PRIuUINT32 "\""
353 " shadowsAfter=\"%" SAL_PRIuUINT32 "\""
354 " vertMerge=\"%s\"/>",
355 mnDepth, mnCell, mnRow,
356 mbEndOfCell ? "yes" : "no",
357 mbEndOfLine ? "yes" : "no",
358 mnShadowsBefore,
359 mnShadowsAfter,
360 mbVertMerge ? "yes" : "no");
361
362 return std::string(buffer);
363 }
364 #endif
365
WW8TableNodeInfo(WW8TableInfo * pParent,const SwNode * pNode)366 WW8TableNodeInfo::WW8TableNodeInfo(WW8TableInfo * pParent,
367 const SwNode * pNode)
368 : mpParent(pParent),
369 mnDepth(0),
370 mpNode(pNode),
371 mpNext(nullptr),
372 mpNextNode(nullptr)
373 {
374 }
375
~WW8TableNodeInfo()376 WW8TableNodeInfo::~WW8TableNodeInfo()
377 {
378 }
379
380 #ifdef DBG_UTIL
toString() const381 std::string WW8TableNodeInfo::toString() const
382 {
383 static char buffer[1024];
384 snprintf(buffer, sizeof(buffer),
385 "<tableNodeInfo p=\"%p\" depth=\"%" SAL_PRIuUINT32 "\">"
386 ,this, getDepth());
387
388 std::string sResult(buffer);
389
390 for (const auto& rInner : mInners)
391 {
392 WW8TableNodeInfoInner::Pointer_t pInner = rInner.second;
393 sResult += pInner->toString();
394 }
395 sResult += dbg_out(*mpNode);
396 sResult += "</tableNodeInfo>";
397
398 return sResult;
399 }
400 #endif
401
setDepth(sal_uInt32 nDepth)402 void WW8TableNodeInfo::setDepth(sal_uInt32 nDepth)
403 {
404 mnDepth = nDepth;
405
406 Inners_t::iterator aIt = mInners.find(mnDepth);
407
408 if (aIt == mInners.end())
409 mInners[mnDepth] = std::make_shared<ww8::WW8TableNodeInfoInner>(this);
410
411 mInners[mnDepth]->setDepth(mnDepth);
412 }
413
setEndOfLine(bool bEndOfLine)414 void WW8TableNodeInfo::setEndOfLine(bool bEndOfLine)
415 {
416 WW8TableNodeInfoInner::Pointer_t pInner = getInnerForDepth(mnDepth);
417 pInner->setEndOfLine(bEndOfLine);
418
419 #ifdef DBG_UTIL
420 SAL_INFO( "sw.ww8", "<endOfLine depth=\"" << mnDepth << "\">" << toString() << "</endOfLine>" );
421 #endif
422 }
423
setEndOfCell(bool bEndOfCell)424 void WW8TableNodeInfo::setEndOfCell(bool bEndOfCell)
425 {
426 WW8TableNodeInfoInner::Pointer_t pInner = getInnerForDepth(mnDepth);
427 pInner->setEndOfCell(bEndOfCell);
428
429 #ifdef DBG_UTIL
430 SAL_INFO( "sw.ww8", "<endOfCell depth=\"" << mnDepth << "\">" << toString() << "</endOfCell>" );
431 #endif
432 }
433
setFirstInTable(bool bFirstInTable)434 void WW8TableNodeInfo::setFirstInTable(bool bFirstInTable)
435 {
436 WW8TableNodeInfoInner::Pointer_t pInner = getInnerForDepth(mnDepth);
437
438 pInner->setFirstInTable(bFirstInTable);
439
440 #ifdef DBG_UTIL
441 SAL_INFO( "sw.ww8", "<firstInTable depth=\"" << mnDepth << "\">" << toString() << "</firstInTable>" );
442 #endif
443 }
444
setVertMerge(bool bVertMerge)445 void WW8TableNodeInfo::setVertMerge(bool bVertMerge)
446 {
447 WW8TableNodeInfoInner::Pointer_t pInner = getInnerForDepth(mnDepth);
448
449 pInner->setVertMerge(bVertMerge);
450
451 #ifdef DBG_UTIL
452 SAL_INFO( "sw.ww8", "<vertMerge depth=\"" << mnDepth << "\">" << toString() << "</vertMerge>" );
453 #endif
454 }
455
setTableBox(const SwTableBox * pTableBox)456 void WW8TableNodeInfo::setTableBox(const SwTableBox * pTableBox)
457 {
458 getInnerForDepth(mnDepth)->setTableBox(pTableBox);
459 }
460
setTable(const SwTable * pTable)461 void WW8TableNodeInfo::setTable(const SwTable * pTable)
462 {
463 getInnerForDepth(mnDepth)->setTable(pTable);
464 }
465
setNext(WW8TableNodeInfo * pNext)466 void WW8TableNodeInfo::setNext(WW8TableNodeInfo * pNext)
467 {
468 mpNext = pNext;
469
470 #ifdef DBG_UTIL
471 SAL_INFO( "sw.ww8", "<setnext><from>" << toString() << "</from><to>" << pNext->toString() << "</to></setnext>" );
472 #endif
473 }
474
setNextNode(const SwNode * pNode)475 void WW8TableNodeInfo::setNextNode(const SwNode * pNode)
476 {
477 mpNextNode = pNode;
478 }
479
setRect(const SwRect & rRect)480 void WW8TableNodeInfo::setRect(const SwRect & rRect)
481 {
482 getInnerForDepth(mnDepth)->setRect(rRect);
483 }
484
setCell(sal_uInt32 nCell)485 void WW8TableNodeInfo::setCell(sal_uInt32 nCell)
486 {
487 getInnerForDepth(mnDepth)->setCell(nCell);
488 }
489
setRow(sal_uInt32 nRow)490 void WW8TableNodeInfo::setRow(sal_uInt32 nRow)
491 {
492 getInnerForDepth(mnDepth)->setRow(nRow);
493 }
494
setShadowsBefore(sal_uInt32 nShadowsBefore)495 void WW8TableNodeInfo::setShadowsBefore(sal_uInt32 nShadowsBefore)
496 {
497 getInnerForDepth(mnDepth)->setShadowsBefore(nShadowsBefore);
498 }
499
setShadowsAfter(sal_uInt32 nShadowsAfter)500 void WW8TableNodeInfo::setShadowsAfter(sal_uInt32 nShadowsAfter)
501 {
502 getInnerForDepth(mnDepth)->setShadowsAfter(nShadowsAfter);
503 }
504
505
getDepth() const506 sal_uInt32 WW8TableNodeInfo::getDepth() const
507 {
508 if (!mInners.empty())
509 return mInners.begin()->second->getDepth();
510
511 return mnDepth;
512 }
513
514
getTableBox() const515 const SwTableBox * WW8TableNodeInfo::getTableBox() const
516 {
517 return getInnerForDepth(mnDepth)->getTableBox();
518 }
519
getCell() const520 sal_uInt32 WW8TableNodeInfo::getCell() const
521 {
522 return getInnerForDepth(mnDepth)->getCell();
523 }
524
getRow() const525 sal_uInt32 WW8TableNodeInfo::getRow() const
526 {
527 return getInnerForDepth(mnDepth)->getRow();
528 }
529
getFirstInner() const530 WW8TableNodeInfoInner::Pointer_t WW8TableNodeInfo::getFirstInner() const
531 {
532 WW8TableNodeInfoInner::Pointer_t pResult;
533
534 if (!mInners.empty())
535 pResult = mInners.begin()->second;
536
537 return pResult;
538 }
539
getInnerForDepth(sal_uInt32 nDepth) const540 WW8TableNodeInfoInner::Pointer_t WW8TableNodeInfo::getInnerForDepth(sal_uInt32 nDepth) const
541 {
542 WW8TableNodeInfoInner::Pointer_t pResult;
543
544 Inners_t::const_iterator aIt = mInners.find(nDepth);
545 if (aIt != mInners.end())
546 {
547 pResult = aIt->second;
548 }
549
550 return pResult;
551 }
552
WW8TableInfo()553 WW8TableInfo::WW8TableInfo()
554 {
555 }
556
~WW8TableInfo()557 WW8TableInfo::~WW8TableInfo()
558 {
559 }
560
561 WW8TableNodeInfo *
processSwTableByLayout(const SwTable * pTable,RowEndInners_t & rLastRowEnds)562 WW8TableInfo::processSwTableByLayout(const SwTable * pTable, RowEndInners_t &rLastRowEnds)
563 {
564 SwTableCellInfo aTableCellInfo(pTable);
565
566 while (aTableCellInfo.getNext())
567 {
568 SwRect aRect = aTableCellInfo.getRect();
569
570 SAL_INFO( "sw.ww8", "<CellFrame>" );
571 SAL_INFO( "sw.ww8", "<rect top=\"" << aRect.Top() << "\" bottom=\"" << aRect.Bottom()
572 << "\" left=\"" << aRect.Left() << "\" right=\"" << aRect.Right() << "\"/>" );
573 const SwTableBox * pTableBox = aTableCellInfo.getTableBox();
574 const SwStartNode * pSttNd = pTableBox->GetSttNd();
575
576 if (pSttNd != nullptr)
577 {
578 SwPaM aPam(*pSttNd, 0);
579
580 bool bDone = false;
581 do
582 {
583 SwNode & rNode = aPam.GetPoint()->nNode.GetNode();
584
585 insertTableNodeInfo(&rNode, pTable, pTableBox, 0, 0, 1, & aRect);
586
587 if (rNode.IsEndNode())
588 {
589 SwEndNode * pEndNode = rNode.GetEndNode();
590 SwStartNode * pTmpSttNd = pEndNode->StartOfSectionNode();
591
592 if (pTmpSttNd == pSttNd)
593 bDone = true;
594 }
595
596 aPam.GetPoint()->nNode++;
597 }
598 while (!bDone);
599 }
600
601 SAL_INFO( "sw.ww8", "</CellFrame>" );
602 }
603
604 return reorderByLayout(pTable, rLastRowEnds);
605 }
606
processSwTable(const SwTable * pTable)607 void WW8TableInfo::processSwTable(const SwTable * pTable)
608 {
609 SAL_INFO( "sw.ww8", "<processSwTable>" );
610
611 WW8TableNodeInfo * pPrev = nullptr;
612 RowEndInners_t aLastRowEnds;
613
614 if (pTable->IsTableComplex() && pTable->HasLayout())
615 {
616 pPrev = processSwTableByLayout(pTable, aLastRowEnds);
617 #ifdef DBG_UTIL
618 SAL_INFO( "sw.ww8", getCellGridForTable(pTable)->toString());
619 #endif
620 }
621 else
622 {
623 const SwTableLines & rLines = pTable->GetTabLines();
624
625 for (size_t n = 0; n < rLines.size(); ++n)
626 {
627 const SwTableLine * pLine = rLines[n];
628
629 pPrev = processTableLine(pTable, pLine, static_cast<sal_uInt32>(n), 1, pPrev, aLastRowEnds);
630 }
631
632 }
633
634 if (pPrev)
635 {
636 SwTableNode * pTableNode = pTable->GetTableNode();
637 SwEndNode * pEndNode = pTableNode->EndOfSectionNode();
638 pPrev->setNextNode(pEndNode);
639 assert(!aLastRowEnds.empty());
640 for (auto &a : aLastRowEnds)
641 {
642 assert(a.second->isEndOfLine());
643 a.second->setFinalEndOfLine(true);
644 }
645 }
646 SAL_INFO( "sw.ww8", "</processSwTable>" );
647 }
648
649 WW8TableNodeInfo *
processTableLine(const SwTable * pTable,const SwTableLine * pTableLine,sal_uInt32 nRow,sal_uInt32 nDepth,WW8TableNodeInfo * pPrev,RowEndInners_t & rLastRowEnds)650 WW8TableInfo::processTableLine(const SwTable * pTable,
651 const SwTableLine * pTableLine,
652 sal_uInt32 nRow,
653 sal_uInt32 nDepth,
654 WW8TableNodeInfo * pPrev,
655 RowEndInners_t &rLastRowEnds)
656 {
657 SAL_INFO( "sw.ww8", "<processTableLine row=\"" << nRow << "\" depth=\"" << nDepth << "\">" );
658
659 const SwTableBoxes & rBoxes = pTableLine->GetTabBoxes();
660
661 for (size_t n = 0; n < rBoxes.size(); ++n)
662 {
663 const SwTableBox * pBox = rBoxes[n];
664
665 pPrev = processTableBox(pTable, pBox, nRow, static_cast<sal_uInt32>(n), nDepth, n == rBoxes.size() - 1, pPrev, rLastRowEnds);
666 }
667
668 SAL_INFO( "sw.ww8", "</processTableLine>" );
669
670 return pPrev;
671 }
672
673 WW8TableNodeInfo::Pointer_t
processTableBoxLines(const SwTableBox * pBox,const SwTable * pTable,const SwTableBox * pBoxToSet,sal_uInt32 nRow,sal_uInt32 nCell,sal_uInt32 nDepth)674 WW8TableInfo::processTableBoxLines(const SwTableBox * pBox,
675 const SwTable * pTable,
676 const SwTableBox * pBoxToSet,
677 sal_uInt32 nRow,
678 sal_uInt32 nCell,
679 sal_uInt32 nDepth)
680 {
681 SAL_INFO( "sw.ww8", "<processTableBoxLines depth=\"" << nDepth << "\" row=\"" << nRow
682 << "\" cell=\"" << nCell << "\">" );
683
684 const SwTableLines & rLines = pBox->GetTabLines();
685 WW8TableNodeInfo::Pointer_t pNodeInfo;
686
687 if (!rLines.empty())
688 {
689 for (size_t n = 0; n < rLines.size(); ++n)
690 {
691 const SwTableLine * pLine = rLines[n];
692 const SwTableBoxes & rBoxes = pLine->GetTabBoxes();
693
694 for (size_t nBox = 0; nBox < rBoxes.size(); ++nBox)
695 pNodeInfo = processTableBoxLines(rBoxes[nBox], pTable, pBoxToSet, nRow, nCell, nDepth);
696 }
697 }
698 else
699 {
700 const SwStartNode * pSttNd = pBox->GetSttNd();
701 const SwEndNode * pEndNd = pSttNd->EndOfSectionNode();
702 SwPaM aPaM(*pSttNd, 0);
703 SwPaM aEndPaM(*pEndNd, 0);
704
705 bool bDone = false;
706 while (!bDone)
707 {
708 SwNode & rNode = aPaM.GetPoint()->nNode.GetNode();
709
710 pNodeInfo = insertTableNodeInfo(&rNode, pTable, pBoxToSet, nRow, nCell, nDepth);
711
712 if (aPaM.GetPoint()->nNode == aEndPaM.GetPoint()->nNode)
713 bDone = true;
714 else
715 aPaM.GetPoint()->nNode++;
716 }
717 }
718
719 SAL_INFO( "sw.ww8", "</processTableBoxLines>" );
720
721 return pNodeInfo;
722 }
723
updateFinalEndOfLine(RowEndInners_t & rLastRowEnds,WW8TableNodeInfo const * pEndOfCellInfo)724 static void updateFinalEndOfLine(RowEndInners_t &rLastRowEnds, WW8TableNodeInfo const * pEndOfCellInfo)
725 {
726 sal_Int32 nDepth = pEndOfCellInfo->getDepth();
727 WW8TableNodeInfoInner::Pointer_t pInner = pEndOfCellInfo->getInnerForDepth(nDepth);
728
729 auto aIt = rLastRowEnds.find(nDepth);
730 if (aIt == rLastRowEnds.end() || (pInner->getRow() > aIt->second->getRow()))
731 rLastRowEnds[nDepth] = pInner.get();
732 }
733
734 WW8TableNodeInfo *
processTableBox(const SwTable * pTable,const SwTableBox * pBox,sal_uInt32 nRow,sal_uInt32 nCell,sal_uInt32 nDepth,bool bEndOfLine,WW8TableNodeInfo * pPrev,RowEndInners_t & rLastRowEnds)735 WW8TableInfo::processTableBox(const SwTable * pTable,
736 const SwTableBox * pBox,
737 sal_uInt32 nRow,
738 sal_uInt32 nCell,
739 sal_uInt32 nDepth,
740 bool bEndOfLine,
741 WW8TableNodeInfo * pPrev,
742 RowEndInners_t &rLastRowEnds)
743 {
744 SAL_INFO( "sw.ww8", "<processTableBox row=\"" << nRow << "\" cell=\"" << nCell
745 << "\" depth=\"" << nDepth << "\">" );
746
747 WW8TableNodeInfo::Pointer_t pNodeInfo;
748 const SwTableLines & rLines = pBox->GetTabLines();
749 const SwStartNode * pSttNd = pBox->GetSttNd();
750 WW8TableNodeInfo::Pointer_t pEndOfCellInfo;
751
752 if (!rLines.empty())
753 {
754 pNodeInfo = processTableBoxLines(pBox, pTable, pBox, nRow, nCell, nDepth);
755 pNodeInfo->setEndOfCell(true);
756 if (bEndOfLine)
757 {
758 pNodeInfo->setEndOfLine(true);
759 updateFinalEndOfLine(rLastRowEnds, pNodeInfo.get());
760 }
761
762 for (size_t n = 0; n < rLines.size(); n++)
763 {
764 const SwTableLine * pLine = rLines[n];
765
766 pPrev = processTableLine(pTable, pLine, n, 1, pPrev, rLastRowEnds);
767 }
768 }
769 else
770 {
771 SwPaM aPaM(*pSttNd, 0);
772
773 bool bDone = false;
774 sal_uInt32 nDepthInsideCell = 0;
775
776 do
777 {
778 SwNode & rNode = aPaM.GetPoint()->nNode.GetNode();
779
780 if (rNode.IsStartNode())
781 {
782 if (nDepthInsideCell > 0)
783 pEndOfCellInfo.reset();
784
785 nDepthInsideCell++;
786 }
787
788 pNodeInfo = insertTableNodeInfo(&rNode, pTable, pBox, nRow, nCell, nDepth);
789
790 if (pPrev)
791 pPrev->setNext(pNodeInfo.get());
792
793 pPrev = pNodeInfo.get();
794
795 if (nDepthInsideCell == 1 && rNode.IsTextNode())
796 pEndOfCellInfo = pNodeInfo;
797
798 if (rNode.IsEndNode())
799 {
800 nDepthInsideCell--;
801
802 if (nDepthInsideCell == 0 && !pEndOfCellInfo)
803 pEndOfCellInfo = pNodeInfo;
804
805 SwEndNode * pEndNode = rNode.GetEndNode( );
806 SwStartNode * pTmpSttNd = pEndNode->StartOfSectionNode();
807 if (pTmpSttNd == pSttNd)
808 bDone = true;
809 }
810
811 aPaM.GetPoint()->nNode++;
812 }
813 while (!bDone);
814
815 if (pEndOfCellInfo)
816 {
817 pEndOfCellInfo->setEndOfCell(true);
818
819 if (bEndOfLine)
820 {
821 pEndOfCellInfo->setEndOfLine(true);
822 updateFinalEndOfLine(rLastRowEnds, pEndOfCellInfo.get());
823 }
824 }
825 }
826
827 SAL_INFO( "sw.ww8", "</processTableBox>" );
828
829 return pPrev;
830 }
831
insertTableNodeInfo(const SwNode * pNode,const SwTable * pTable,const SwTableBox * pTableBox,sal_uInt32 nRow,sal_uInt32 nCell,sal_uInt32 nDepth,SwRect const * pRect)832 WW8TableNodeInfo::Pointer_t WW8TableInfo::insertTableNodeInfo
833 (const SwNode * pNode,
834 const SwTable * pTable,
835 const SwTableBox * pTableBox,
836 sal_uInt32 nRow,
837 sal_uInt32 nCell,
838 sal_uInt32 nDepth,
839 SwRect const * pRect)
840 {
841 WW8TableNodeInfo::Pointer_t pNodeInfo = getTableNodeInfo(pNode);
842
843 if (!pNodeInfo)
844 {
845 pNodeInfo =
846 std::make_shared<ww8::WW8TableNodeInfo>(this, pNode);
847 mMap.emplace(pNode, pNodeInfo);
848 }
849
850 pNodeInfo->setDepth(nDepth + pNodeInfo->getDepth());
851
852 pNodeInfo->setTable(pTable);
853 pNodeInfo->setTableBox(pTableBox);
854
855 pNodeInfo->setCell(nCell);
856 pNodeInfo->setRow(nRow);
857
858 if (pNode->IsTextNode())
859 {
860 FirstInTableMap_t::const_iterator aIt = mFirstInTableMap.find(pTable);
861 if (aIt == mFirstInTableMap.end())
862 {
863 mFirstInTableMap[pTable] = pNode;
864 pNodeInfo->setFirstInTable(true);
865 }
866 }
867
868 if (pRect)
869 {
870 WW8TableCellGrid::Pointer_t pCellGrid = getCellGridForTable(pTable);
871
872 pCellGrid->insert(*pRect, pNodeInfo.get());
873 pNodeInfo->setRect(*pRect);
874 }
875
876 #ifdef DBG_UTIL
877 SAL_INFO( "sw.ww8", pNodeInfo->toString());
878 #endif
879 return pNodeInfo;
880 }
881
getCellGridForTable(const SwTable * pTable,bool bCreate)882 WW8TableCellGrid::Pointer_t WW8TableInfo::getCellGridForTable
883 (const SwTable * pTable, bool bCreate)
884 {
885 WW8TableCellGrid::Pointer_t pResult;
886 CellGridMap_t::iterator aIt = mCellGridMap.find(pTable);
887
888 if (aIt == mCellGridMap.end())
889 {
890 if (bCreate)
891 {
892 pResult = std::make_shared<ww8::WW8TableCellGrid>();
893 mCellGridMap[pTable] = pResult;
894 }
895 }
896 else
897 pResult = mCellGridMap[pTable];
898
899 return pResult;
900 }
901
getTableNodeInfo(const SwNode * pNode)902 WW8TableNodeInfo::Pointer_t WW8TableInfo::getTableNodeInfo
903 (const SwNode * pNode)
904 {
905 WW8TableNodeInfo::Pointer_t pResult;
906 Map_t::iterator aIt = mMap.find(pNode);
907
908 if (aIt != mMap.end())
909 pResult = (*aIt).second;
910
911 return pResult;
912 }
913
getNextNode(const SwNode * pNode)914 const SwNode * WW8TableInfo::getNextNode(const SwNode * pNode)
915 {
916 const SwNode * pResult = nullptr;
917
918 WW8TableNodeInfo::Pointer_t pNodeInfo = getTableNodeInfo(pNode);
919
920 if (pNodeInfo)
921 {
922 WW8TableNodeInfo * pNextInfo = pNodeInfo->getNext();
923
924 if (pNextInfo != nullptr)
925 pResult = pNextInfo->getNode();
926 else
927 {
928 const SwNode * pNextNode = pNodeInfo->getNextNode();
929
930 if (pNextNode != nullptr)
931 pResult = pNextNode;
932 }
933 }
934
935 return pResult;
936 }
937
operator <(const WW8TableNodeInfo & rInfo) const938 bool WW8TableNodeInfo::operator < (const WW8TableNodeInfo & rInfo) const
939 {
940 bool bRet = false;
941
942 if (rInfo.mpNode != nullptr)
943 {
944 if (mpNode == nullptr)
945 {
946 bRet = true;
947 }
948 else
949 {
950 if (mpNode->GetIndex() < rInfo.mpNode->GetIndex())
951 bRet = true;
952 }
953 }
954
955 return bRet;
956 }
957
operator <(const CellInfo & aCellInfo) const958 bool CellInfo::operator < (const CellInfo & aCellInfo) const
959 {
960 bool aRet = false;
961
962 if (top() < aCellInfo.top())
963 aRet = true;
964 else if (top() == aCellInfo.top())
965 {
966 if (left() < aCellInfo.left())
967 aRet = true;
968 else if (left() == aCellInfo.left())
969 {
970 if (width() < aCellInfo.width())
971 aRet = true;
972 else if (width() == aCellInfo.width())
973 {
974 if (height() < aCellInfo.height())
975 aRet = true;
976 else if (height() == aCellInfo.height())
977 {
978 if (aCellInfo.getTableNodeInfo())
979 {
980 if (m_pNodeInfo == nullptr)
981 aRet = true;
982 else
983 {
984 aRet = *m_pNodeInfo < *aCellInfo.getTableNodeInfo();
985 }
986 }
987 }
988 }
989 }
990 }
991
992 return aRet;
993 }
994
995 #ifdef DBG_UTIL
toString() const996 std::string CellInfo::toString() const
997 {
998 static char sBuffer[256];
999
1000 snprintf(sBuffer, sizeof(sBuffer),
1001 "<cellinfo left=\"%" SAL_PRIdINT64 "\""
1002 " right=\"%" SAL_PRIdINT64 "\""
1003 " top=\"%" SAL_PRIdINT64 "\""
1004 " bottom=\"%" SAL_PRIdINT64 "\""
1005 " node=\"%p\"/>",
1006 sal_Int64(left()),
1007 sal_Int64(right()),
1008 sal_Int64(top()),
1009 sal_Int64(bottom()),
1010 m_pNodeInfo);
1011
1012 return sBuffer;
1013 }
1014 #endif
1015
reorderByLayout(const SwTable * pTable,RowEndInners_t & rLastRowEnds)1016 WW8TableNodeInfo * WW8TableInfo::reorderByLayout(const SwTable * pTable, RowEndInners_t &rLastRowEnds)
1017 {
1018 WW8TableCellGrid::Pointer_t pCellGrid = getCellGridForTable(pTable);
1019
1020 #ifdef DBG_UTIL
1021 SAL_INFO( "sw.ww8", pCellGrid->toString());
1022 #endif
1023
1024 pCellGrid->addShadowCells();
1025 return pCellGrid->connectCells(rLastRowEnds);
1026 }
1027
WW8TableCellGrid()1028 WW8TableCellGrid::WW8TableCellGrid()
1029 {
1030 }
1031
~WW8TableCellGrid()1032 WW8TableCellGrid::~WW8TableCellGrid()
1033 {
1034 }
1035
getRow(tools::Long nTop,bool bCreate)1036 WW8TableCellGridRow::Pointer_t WW8TableCellGrid::getRow(tools::Long nTop, bool bCreate)
1037 {
1038 WW8TableCellGridRow::Pointer_t pResult;
1039
1040 RowTops_t::iterator aIt = m_aRowTops.find(nTop);
1041
1042 if (aIt == m_aRowTops.end())
1043 {
1044 if (bCreate)
1045 {
1046 pResult = std::make_shared<ww8::WW8TableCellGridRow>();
1047 m_aRows[nTop] = pResult;
1048 m_aRowTops.insert(nTop);
1049 }
1050 }
1051 else
1052 pResult = m_aRows[nTop];
1053
1054 return pResult;
1055 }
1056
getRowTopsBegin() const1057 WW8TableCellGrid::RowTops_t::const_iterator WW8TableCellGrid::getRowTopsBegin() const
1058 {
1059 return m_aRowTops.begin();
1060 }
1061
getRowTopsEnd() const1062 WW8TableCellGrid::RowTops_t::const_iterator WW8TableCellGrid::getRowTopsEnd() const
1063 {
1064 return m_aRowTops.end();
1065 }
1066
getCellsBegin(tools::Long nTop)1067 CellInfoMultiSet::const_iterator WW8TableCellGrid::getCellsBegin(tools::Long nTop)
1068 {
1069 return getRow(nTop)->begin();
1070 }
1071
getCellsEnd(tools::Long nTop)1072 CellInfoMultiSet::const_iterator WW8TableCellGrid::getCellsEnd(tools::Long nTop)
1073 {
1074 return getRow(nTop)->end();
1075 }
1076
insert(const SwRect & rRect,WW8TableNodeInfo * pNodeInfo,const tools::ULong * pFormatFrameWidth)1077 void WW8TableCellGrid::insert(const SwRect & rRect,
1078 WW8TableNodeInfo * pNodeInfo,
1079 const tools::ULong * pFormatFrameWidth)
1080 {
1081 CellInfo aCellInfo(rRect, pNodeInfo);
1082
1083 if (pFormatFrameWidth != nullptr)
1084 aCellInfo.setFormatFrameWidth(*pFormatFrameWidth);
1085
1086 WW8TableCellGridRow::Pointer_t pRow = getRow(rRect.Top());
1087 pRow->insert(aCellInfo);
1088 }
1089
addShadowCells()1090 void WW8TableCellGrid::addShadowCells()
1091 {
1092 SAL_INFO( "sw.ww8", "<addShadowCells>" );
1093
1094 RowTops_t::const_iterator aTopsIt = getRowTopsBegin();
1095
1096 while (aTopsIt != getRowTopsEnd())
1097 {
1098 CellInfoMultiSet::const_iterator aCellIt = getCellsBegin(*aTopsIt);
1099 CellInfoMultiSet::const_iterator aCellEndIt = getCellsEnd(*aTopsIt);
1100
1101 RowSpansPtr pRowSpans = std::make_shared<RowSpans>();
1102
1103 bool bBeginningOfCell = true;
1104 bool bVertMerge = false;
1105 SwRect aRect = aCellIt->getRect();
1106 sal_Int32 nRowSpan = 1;
1107 while (aCellIt != aCellEndIt)
1108 {
1109 WW8TableNodeInfo * pNodeInfo = aCellIt->getTableNodeInfo();
1110
1111 if (bBeginningOfCell)
1112 {
1113 RowTops_t::const_iterator aRowSpanIt(aTopsIt);
1114 ++aRowSpanIt;
1115
1116 if (aRowSpanIt != getRowTopsEnd() &&
1117 *aRowSpanIt < aCellIt->bottom())
1118 {
1119 aRect.Top(*aRowSpanIt);
1120 tools::ULong nFormatFrameWidth = aCellIt->getFormatFrameWidth();
1121 insert(aRect, nullptr, &nFormatFrameWidth);
1122
1123 bVertMerge = true;
1124 }
1125 else
1126 bVertMerge = false;
1127
1128 nRowSpan = 1;
1129 while (aRowSpanIt != getRowTopsEnd() &&
1130 *aRowSpanIt < aCellIt->bottom())
1131 {
1132 ++aRowSpanIt;
1133 nRowSpan++;
1134 }
1135
1136 if (pNodeInfo)
1137 pRowSpans->push_back(nRowSpan);
1138 else
1139 pRowSpans->push_back(-nRowSpan);
1140 }
1141
1142 if (pNodeInfo)
1143 {
1144 pNodeInfo->setVertMerge(bVertMerge);
1145 }
1146
1147 ++aCellIt;
1148 if (aCellIt != aCellEndIt)
1149 {
1150 bBeginningOfCell = (aRect.Left() != aCellIt->left());
1151 aRect = aCellIt->getRect();
1152 }
1153 }
1154
1155 WW8TableCellGridRow::Pointer_t pRow = getRow(*aTopsIt);
1156 if (pRow)
1157 pRow->setRowSpans(pRowSpans);
1158
1159 ++aTopsIt;
1160 }
1161 SAL_INFO( "sw.ww8", "</addShadowCells>" );
1162 }
1163
connectCells(RowEndInners_t & rLastRowEnds)1164 WW8TableNodeInfo * WW8TableCellGrid::connectCells(RowEndInners_t &rLastRowEnds)
1165 {
1166 RowTops_t::const_iterator aTopsIt = getRowTopsBegin();
1167 sal_uInt32 nRow = 0;
1168 WW8TableNodeInfo * pLastNodeInfo = nullptr;
1169
1170 while (aTopsIt != getRowTopsEnd())
1171 {
1172 CellInfoMultiSet::const_iterator aCellIt = getCellsBegin(*aTopsIt);
1173 CellInfoMultiSet::const_iterator aCellEndIt = getCellsEnd(*aTopsIt);
1174 GridColsPtr pWidths = std::make_shared<Widths>();
1175 TableBoxVectorPtr pTableBoxes = std::make_shared<TableBoxVector>();
1176
1177 sal_uInt32 nShadows = 0;
1178 sal_uInt32 nCell = 0;
1179 bool bBeginningOfCell = true;
1180 WW8TableNodeInfo * pEndOfCellInfo = nullptr;
1181 sal_uInt32 nDepthInCell = 0;
1182 while (aCellIt != aCellEndIt)
1183 {
1184 tools::Long nCellX = aCellIt->left();
1185 WW8TableNodeInfo * pNodeInfo = aCellIt->getTableNodeInfo();
1186 if (pNodeInfo)
1187 {
1188 const SwNode * pNode = pNodeInfo->getNode();
1189
1190 if (pNode->IsStartNode())
1191 {
1192 nDepthInCell++;
1193 pEndOfCellInfo = nullptr;
1194 }
1195
1196 if (nDepthInCell == 1 && pNode->IsTextNode())
1197 pEndOfCellInfo = pNodeInfo;
1198
1199 pNodeInfo->setShadowsBefore(nShadows);
1200 pNodeInfo->setCell(nCell);
1201 pNodeInfo->setRow(nRow);
1202 if (pLastNodeInfo)
1203 {
1204 pLastNodeInfo->setNext(pNodeInfo);
1205 pLastNodeInfo->setNextNode(pNode);
1206 }
1207 pLastNodeInfo = pNodeInfo;
1208 nShadows = 0;
1209
1210 if (pNode->IsEndNode())
1211 {
1212 nDepthInCell--;
1213
1214 if (nDepthInCell == 0 && !pEndOfCellInfo)
1215 pEndOfCellInfo = pNodeInfo;
1216 }
1217 }
1218 else
1219 {
1220 nShadows++;
1221 }
1222
1223 if (bBeginningOfCell)
1224 {
1225 pWidths->push_back(aCellIt->getFormatFrameWidth());
1226
1227 if (pNodeInfo)
1228 pTableBoxes->push_back(pNodeInfo->getTableBox());
1229 else
1230 pTableBoxes->push_back(nullptr);
1231 }
1232
1233 ++aCellIt;
1234 bBeginningOfCell = false;
1235
1236 if (aCellIt != aCellEndIt && aCellIt->left() != nCellX)
1237 {
1238 nCell++;
1239 bBeginningOfCell = true;
1240
1241 if (pEndOfCellInfo)
1242 {
1243 pEndOfCellInfo->setEndOfCell(true);
1244 }
1245
1246 pEndOfCellInfo = nullptr;
1247 }
1248 }
1249
1250 pLastNodeInfo->setShadowsAfter(nShadows);
1251
1252 if (!pEndOfCellInfo)
1253 {
1254 pEndOfCellInfo = pLastNodeInfo;
1255 }
1256
1257 pEndOfCellInfo->setEndOfCell(true);
1258 pLastNodeInfo->setEndOfLine(true);
1259 updateFinalEndOfLine(rLastRowEnds, pLastNodeInfo);
1260
1261 WW8TableCellGridRow::Pointer_t pRow(getRow(*aTopsIt));
1262 pRow->setTableBoxVector(pTableBoxes);
1263 pRow->setWidths(pWidths);
1264
1265 ++aTopsIt;
1266 nRow++;
1267 }
1268
1269 return pLastNodeInfo;
1270 }
1271
1272 #ifdef DBG_UTIL
toString()1273 std::string WW8TableCellGrid::toString()
1274 {
1275 std::string sResult = "<WW8TableCellGrid>";
1276
1277 RowTops_t::const_iterator aTopsIt = getRowTopsBegin();
1278 static char sBuffer[1024];
1279 while (aTopsIt != getRowTopsEnd())
1280 {
1281 sprintf(sBuffer, "<row y=\"%" SAL_PRIdINT64 "\">", sal_Int64(*aTopsIt));
1282 sResult += sBuffer;
1283
1284 CellInfoMultiSet::const_iterator aCellIt = getCellsBegin(*aTopsIt);
1285 CellInfoMultiSet::const_iterator aCellsEnd = getCellsEnd(*aTopsIt);
1286
1287 while (aCellIt != aCellsEnd)
1288 {
1289 snprintf(sBuffer, sizeof(sBuffer), "<cellInfo top=\"%" SAL_PRIdINT64 "\" bottom=\"%" SAL_PRIdINT64 "\" left=\"%" SAL_PRIdINT64 "\" right=\"%" SAL_PRIdINT64 "\">",
1290 sal_Int64(aCellIt->top()), sal_Int64(aCellIt->bottom()), sal_Int64(aCellIt->left()), sal_Int64(aCellIt->right()));
1291 sResult += sBuffer;
1292
1293 WW8TableNodeInfo * pInfo = aCellIt->getTableNodeInfo();
1294 if (pInfo)
1295 sResult += pInfo->toString();
1296 else
1297 sResult += "<shadow/>\n";
1298
1299 sResult += "</cellInfo>\n";
1300 ++aCellIt;
1301 }
1302
1303 WW8TableCellGridRow::Pointer_t pRow = getRow(*aTopsIt);
1304 WidthsPtr pWidths = pRow->getWidths();
1305 if (pWidths != nullptr)
1306 {
1307 sResult += "<widths>";
1308
1309 Widths::const_iterator aItEnd = pWidths->end();
1310 for (Widths::const_iterator aIt = pWidths->begin();
1311 aIt != aItEnd;
1312 ++aIt)
1313 {
1314 if (aIt != pWidths->begin())
1315 sResult += ", ";
1316
1317 snprintf(sBuffer, sizeof(sBuffer), "%" SAL_PRIxUINT32 "", *aIt);
1318 sResult += sBuffer;
1319 }
1320
1321 sResult += "</widths>";
1322 }
1323
1324 RowSpansPtr pRowSpans = pRow->getRowSpans();
1325 if (pRowSpans)
1326 {
1327 sResult += "<rowspans>";
1328
1329 RowSpans::const_iterator aItEnd = pRowSpans->end();
1330 for (RowSpans::const_iterator aIt = pRowSpans->begin();
1331 aIt != aItEnd;
1332 ++aIt)
1333 {
1334 if (aIt != pRowSpans->begin())
1335 sResult += ", ";
1336
1337 snprintf(sBuffer, sizeof(sBuffer), "%" SAL_PRIxUINT32 "", *aIt);
1338 sResult += sBuffer;
1339 }
1340
1341 sResult += "</rowspans>";
1342 }
1343
1344 sResult += "</row>\n";
1345 ++aTopsIt;
1346 }
1347
1348 sResult += "</WW8TableCellGrid>\n";
1349
1350 return sResult;
1351 }
1352 #endif
1353
getTableBoxesOfRow(WW8TableNodeInfoInner const * pNodeInfoInner)1354 TableBoxVectorPtr WW8TableCellGrid::getTableBoxesOfRow
1355 (WW8TableNodeInfoInner const * pNodeInfoInner)
1356 {
1357 TableBoxVectorPtr pResult;
1358 WW8TableCellGridRow::Pointer_t pRow =
1359 getRow(pNodeInfoInner->getRect().Top(), false);
1360
1361 if (pRow)
1362 {
1363 pResult = pRow->getTableBoxVector();
1364 }
1365
1366 return pResult;
1367 }
1368
getWidthsOfRow(WW8TableNodeInfoInner const * pNodeInfoInner)1369 WidthsPtr WW8TableCellGrid::getWidthsOfRow
1370 (WW8TableNodeInfoInner const * pNodeInfoInner)
1371 {
1372 GridColsPtr pResult;
1373
1374 WW8TableCellGridRow::Pointer_t pRow =
1375 getRow(pNodeInfoInner->getRect().Top(), false);
1376
1377 if (pRow)
1378 {
1379 pResult = pRow->getWidths();
1380 }
1381
1382 return pResult;
1383 }
1384
getRowSpansOfRow(WW8TableNodeInfoInner const * pNodeInfoInner)1385 RowSpansPtr WW8TableCellGrid::getRowSpansOfRow
1386 (WW8TableNodeInfoInner const * pNodeInfoInner)
1387 {
1388 RowSpansPtr pResult;
1389
1390 WW8TableCellGridRow::Pointer_t pRow =
1391 getRow(pNodeInfoInner->getRect().Top(), false);
1392
1393 if (pRow)
1394 {
1395 pResult = pRow->getRowSpans();
1396 }
1397
1398 return pResult;
1399 }
1400
WW8TableCellGridRow()1401 WW8TableCellGridRow::WW8TableCellGridRow()
1402 : m_pCellInfos(std::make_shared<CellInfoMultiSet>())
1403 {
1404 }
1405
~WW8TableCellGridRow()1406 WW8TableCellGridRow::~WW8TableCellGridRow()
1407 {
1408 }
1409
insert(const CellInfo & rCellInfo)1410 void WW8TableCellGridRow::insert(const CellInfo & rCellInfo)
1411 {
1412 m_pCellInfos->insert(rCellInfo);
1413
1414 #ifdef DBG_UTIL
1415 SAL_INFO( "sw.ww8", "<gridRowInsert>" << rCellInfo.toString() << "</gridRowInsert>" );
1416 #endif
1417 }
1418
begin() const1419 CellInfoMultiSet::const_iterator WW8TableCellGridRow::begin() const
1420 {
1421 return m_pCellInfos->begin();
1422 }
1423
end() const1424 CellInfoMultiSet::const_iterator WW8TableCellGridRow::end() const
1425 {
1426 return m_pCellInfos->end();
1427 }
1428
setTableBoxVector(TableBoxVectorPtr const & pTableBoxVector)1429 void WW8TableCellGridRow::setTableBoxVector(TableBoxVectorPtr const & pTableBoxVector)
1430 {
1431 if (pTableBoxVector->size() > MAXTABLECELLS)
1432 pTableBoxVector->resize(MAXTABLECELLS);
1433 m_pTableBoxVector = pTableBoxVector;
1434 }
1435
setWidths(WidthsPtr const & pWidths)1436 void WW8TableCellGridRow::setWidths(WidthsPtr const & pWidths)
1437 {
1438 m_pWidths = pWidths;
1439 }
1440
setRowSpans(RowSpansPtr const & pRowSpans)1441 void WW8TableCellGridRow::setRowSpans(RowSpansPtr const & pRowSpans)
1442 {
1443 m_pRowSpans = pRowSpans;
1444 }
1445
1446
CellInfo(const SwRect & aRect,WW8TableNodeInfo * pNodeInfo)1447 CellInfo::CellInfo(const SwRect & aRect, WW8TableNodeInfo * pNodeInfo)
1448 : m_aRect(aRect), m_pNodeInfo(pNodeInfo), m_nFormatFrameWidth(0)
1449 {
1450 if (pNodeInfo != nullptr)
1451 {
1452 const SwTableBox * pBox = pNodeInfo->getTableBox();
1453 const SwFrameFormat * pFrameFormat = pBox->GetFrameFormat();
1454 const SwFormatFrameSize & rSize = pFrameFormat->GetFrameSize();
1455
1456 m_nFormatFrameWidth = rSize.GetWidth();
1457 }
1458 }
1459
1460 }
1461
1462 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1463