tdf#131098 docx export: write fill property of graphic
[LibreOffice.git] / lotuswordpro / source / filter / lwptablelayout.cxx
blob90fb18c7ba6786ff5d232bed39aa30c3ea742663
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * The Contents of this file are made available subject to the terms of
5 * either of the following licenses
7 * - GNU Lesser General Public License Version 2.1
8 * - Sun Industry Standards Source License Version 1.1
10 * Sun Microsystems Inc., October, 2000
12 * GNU Lesser General Public License Version 2.1
13 * =============================================
14 * Copyright 2000 by Sun Microsystems, Inc.
15 * 901 San Antonio Road, Palo Alto, CA 94303, USA
17 * This library is free software; you can redistribute it and/or
18 * modify it under the terms of the GNU Lesser General Public
19 * License version 2.1, as published by the Free Software Foundation.
21 * This library is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 * Lesser General Public License for more details.
26 * You should have received a copy of the GNU Lesser General Public
27 * License along with this library; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
29 * MA 02111-1307 USA
32 * Sun Industry Standards Source License Version 1.1
33 * =================================================
34 * The contents of this file are subject to the Sun Industry Standards
35 * Source License Version 1.1 (the "License"); You may not use this file
36 * except in compliance with the License. You may obtain a copy of the
37 * License at http://www.openoffice.org/license.html.
39 * Software provided under this License is provided on an "AS IS" basis,
40 * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
41 * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
42 * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
43 * See the License for the specific provisions governing your rights and
44 * obligations concerning the Software.
46 * The Initial Developer of the Original Code is: IBM Corporation
48 * Copyright: 2008 by IBM Corporation
50 * All Rights Reserved.
52 * Contributor(s): _______________________________________
55 ************************************************************************/
56 /**
57 * @file
58 * For LWP filter architecture prototype - table layouts
61 #include <lwpglobalmgr.hxx>
62 #include "lwptablelayout.hxx"
63 #include <lwpfoundry.hxx>
64 #include "lwpholder.hxx"
65 #include "lwptable.hxx"
66 #include "lwptblcell.hxx"
67 #include "lwprowlayout.hxx"
68 #include <lwpfilehdr.hxx>
70 #include <xfilter/xfstylemanager.hxx>
71 #include <xfilter/xftablestyle.hxx>
72 #include <xfilter/xfrow.hxx>
73 #include <xfilter/xfrowstyle.hxx>
74 #include <xfilter/xfcell.hxx>
75 #include <xfilter/xfcolstyle.hxx>
76 #include <xfilter/xfframestyle.hxx>
77 #include <xfilter/xfframe.hxx>
78 #include <xfilter/xffloatframe.hxx>
79 #include "lwpframelayout.hxx"
80 #include <xfilter/xfnumberstyle.hxx>
81 #include <xfilter/xfparastyle.hxx>
82 #include <o3tl/sorted_vector.hxx>
83 #include <sal/log.hxx>
84 #include <comphelper/configuration.hxx>
86 #include <algorithm>
87 #include <memory>
89 LwpSuperTableLayout::LwpSuperTableLayout(LwpObjectHeader const &objHdr, LwpSvStream* pStrm)
90 : LwpPlacableLayout(objHdr, pStrm)
92 m_pFrame.reset(new LwpFrame(this) );
95 LwpSuperTableLayout::~LwpSuperTableLayout()
98 /**
99 * @short Read super table layout record
101 void LwpSuperTableLayout::Read()
103 LwpPlacableLayout::Read();
104 m_pObjStrm->SkipExtra();
108 * @short Get child table layout
109 * @return pointer to table layout
111 LwpTableLayout* LwpSuperTableLayout::GetTableLayout()
113 LwpObjectID *pID = &GetChildTail();
115 o3tl::sorted_vector<LwpObjectID*> aSeen;
116 while (pID && !pID->IsNull())
118 bool bAlreadySeen = !aSeen.insert(pID).second;
119 if (bAlreadySeen)
120 throw std::runtime_error("loop in conversion");
122 LwpLayout* pLayout = dynamic_cast<LwpLayout*>(pID->obj().get());
123 if (!pLayout)
124 break;
125 if (pLayout->GetLayoutType() == LWP_TABLE_LAYOUT)
126 return dynamic_cast<LwpTableLayout *>(pLayout);
127 pID = &pLayout->GetPrevious();
130 return nullptr;
134 * @short Get effective heading table layout, the one just before table layout is the only one which is effective
135 * @return LwpTableHeadingLayout* - pointer to table heading layout
137 LwpTableHeadingLayout* LwpSuperTableLayout::GetTableHeadingLayout()
139 LwpObjectID *pID = &GetChildTail();
141 o3tl::sorted_vector<LwpObjectID*> aSeen;
142 while (pID && !pID->IsNull())
144 bool bAlreadySeen = !aSeen.insert(pID).second;
145 if (bAlreadySeen)
146 throw std::runtime_error("loop in conversion");
148 LwpLayout * pLayout = dynamic_cast<LwpLayout *>(pID->obj().get());
149 if (!pLayout)
150 break;
151 if (pLayout->GetLayoutType() == LWP_TABLE_HEADING_LAYOUT)
152 return dynamic_cast<LwpTableHeadingLayout *>(pLayout);
153 pID = &pLayout->GetPrevious();
156 return nullptr;
160 * @short Register super table layout style
162 void LwpSuperTableLayout::RegisterNewStyle()
164 // if this layout is style of real table entry
165 LwpTableLayout* pTableLayout = GetTableLayout();
166 if (pTableLayout != nullptr)
168 pTableLayout->SetFoundry(m_pFoundry);
169 pTableLayout->RegisterStyle();
173 * @short Judge whether table size is according to content, borrowed from Word Pro code
174 * @param
175 * @return sal_Bool
177 bool LwpSuperTableLayout::IsSizeRightToContent()
179 /* Only "with paragraph above" tables can size right to content. */
180 if (GetRelativeType() == LwpLayoutRelativityGuts::LAY_INLINE_NEWLINE)
181 return LwpPlacableLayout::IsSizeRightToContent();
183 return false;
186 * @short Judge whether table is justifiable, borrowed from Word Pro code
187 * @param
188 * @return sal_Bool
190 bool LwpSuperTableLayout::IsJustifiable()
192 return (GetRelativeType() != LwpLayoutRelativityGuts::LAY_INLINE_NEWLINE || IsSizeRightToContent());
195 * @short Get width of frame outside table
196 * @param pTableStyle - pointer of XFTableStyle
197 * @return double - table width
199 double LwpSuperTableLayout::GetWidth()
201 double dWidth = GetTableWidth();
202 double dLeft = GetMarginsValue(MARGIN_LEFT);
203 double dRight = GetMarginsValue(MARGIN_RIGHT);
205 return (dWidth + dLeft + dRight);
208 * @short Get width of table
209 * @param pTableStyle - pointer of XFTableStyle
210 * @return double - table width
212 double LwpSuperTableLayout::GetTableWidth()
214 sal_Int32 nWidth = 0;
215 if(!IsJustifiable() || ((nWidth = LwpMiddleLayout::GetMinimumWidth()) <= 0))
217 LwpTableLayout* pTableLayout = GetTableLayout();
218 if(!pTableLayout)
220 SAL_WARN("lwp", "missing table layout, early return");
221 return 0;
223 LwpTable *pTable = pTableLayout->GetTable();
224 if(!pTable)
226 SAL_WARN("lwp", "missing table, early return");
227 return 0;
229 double dDefaultWidth = pTable->GetWidth();
230 sal_uInt16 nCol = pTable->GetColumn();
232 double dWidth = 0;
234 for(sal_uInt16 i =0; i< nCol; i++)
236 LwpObjectID *pColumnID = &pTableLayout->GetColumnLayoutHead();
237 LwpColumnLayout * pColumnLayout = dynamic_cast<LwpColumnLayout *>(pColumnID->obj().get());
238 double dColumnWidth = dDefaultWidth;
239 o3tl::sorted_vector<LwpColumnLayout*> aSeen;
240 while (pColumnLayout)
242 bool bAlreadySeen = !aSeen.insert(pColumnLayout).second;
243 if (bAlreadySeen)
244 throw std::runtime_error("loop in conversion");
245 if(pColumnLayout->GetColumnID() == i)
247 dColumnWidth = pColumnLayout->GetWidth();
248 break;
250 pColumnID = &pColumnLayout->GetNext();
251 pColumnLayout = dynamic_cast<LwpColumnLayout *>(pColumnID->obj().get());
253 dWidth += dColumnWidth;
256 return dWidth;
259 double dLeft = GetMarginsValue(MARGIN_LEFT);
260 double dRight = GetMarginsValue(MARGIN_RIGHT);
261 return LwpTools::ConvertFromUnits(nWidth) - dLeft - dRight;
265 * @short Apply shadow to table
266 * @param pTableStyle - pointer of XFTableStyle
267 * @return
269 void LwpSuperTableLayout::ApplyShadow(XFTableStyle *pTableStyle)
271 // use shadow property of supertable
272 std::unique_ptr<XFShadow> pXFShadow(GetXFShadow());
273 if(pXFShadow)
275 pTableStyle->SetShadow(pXFShadow->GetPosition(), pXFShadow->GetOffset(), pXFShadow->GetColor());
279 * @short Apply pattern fill to table style
280 * @param pTableStyle - pointer of XFTableStyle
281 * @return
283 void LwpSuperTableLayout::ApplyPatternFill(XFTableStyle* pTableStyle)
285 std::unique_ptr<XFBGImage> xXFBGImage(GetFillPattern());
286 if (xXFBGImage)
288 pTableStyle->SetBackImage(xXFBGImage);
293 * @short Apply background to table style
294 * @param pTableStyle - pointer of XFTableStyle
295 * @return
297 void LwpSuperTableLayout::ApplyBackGround(XFTableStyle* pTableStyle)
299 if (IsPatternFill())
301 ApplyPatternFill(pTableStyle);
303 else
305 ApplyBackColor(pTableStyle);
309 * @short Apply back color to table
310 * @param pTableStyle - pointer of XFTableStyle
311 * @return
313 void LwpSuperTableLayout::ApplyBackColor(XFTableStyle *pTableStyle)
315 LwpColor* pColor = GetBackColor();
316 if(pColor && pColor->IsValidColor())
318 XFColor aColor(pColor->To24Color());
319 pTableStyle->SetBackColor(aColor);
323 * @short Apply watermark to table
324 * @param pTableStyle - pointer of XFTableStyle
325 * @return
327 void LwpSuperTableLayout::ApplyWatermark(XFTableStyle *pTableStyle)
329 std::unique_ptr<XFBGImage> xBGImage(GetXFBGImage());
330 if (xBGImage)
332 pTableStyle->SetBackImage(xBGImage);
336 * @short Apply alignment to table
337 * @param pTableStyle - pointer of XFTableStyle
338 * @return
340 void LwpSuperTableLayout::ApplyAlignment(XFTableStyle * pTableStyle)
342 LwpPoint aPoint;
343 if (LwpLayoutGeometry* pGeometry = GetGeometry())
344 aPoint = pGeometry->GetOrigin();
345 double dXOffset = LwpTools::ConvertFromUnits(aPoint.GetX());
347 // add left padding to alignment distance
348 double dLeft = GetMarginsValue(MARGIN_LEFT);
350 pTableStyle->SetAlign(enumXFAlignStart, dXOffset+ dLeft);
353 * @short Add table to container
354 * @param pCont - pointer of container
355 * @return pCont
357 void LwpSuperTableLayout::XFConvert(XFContentContainer* pCont)
359 if ( LwpLayoutRelativityGuts::LAY_INLINE_NEWLINE == GetRelativeType()
360 && (!GetContainerLayout().is() || !GetContainerLayout()->IsCell()) )
362 LwpTableLayout * pTableLayout = GetTableLayout();
363 if (pTableLayout)
365 pTableLayout->XFConvert(pCont);
368 else if(IsRelativeAnchored())
370 //anchor to paragraph except "with paragraph above"
371 XFConvertFrame(pCont);
373 else if(m_pFrame)
375 //anchor to page, frame, cell
376 m_pFrame->XFConvert(pCont);
380 * @short convert frame which anchor to page
381 * @param
382 * @return
384 void LwpSuperTableLayout::XFConvertFrame(XFContentContainer* pCont, sal_Int32 nStart, sal_Int32 nEnd, bool bAll)
386 if(!m_pFrame)
387 return;
389 rtl::Reference<XFFrame> xXFFrame;
390 if(nEnd < nStart)
392 xXFFrame.set(new XFFrame);
394 else
396 xXFFrame.set(new XFFloatFrame(nStart, nEnd, bAll));
399 m_pFrame->Parse(xXFFrame.get(), static_cast<sal_uInt16>(nStart));
400 //parse table, and add table to frame
401 LwpTableLayout * pTableLayout = GetTableLayout();
402 if (pTableLayout)
404 pTableLayout->XFConvert(xXFFrame.get());
406 //add frame to the container
407 pCont->Add(xXFFrame.get());
411 * @short register frame style
412 * @param
413 * @return
415 void LwpSuperTableLayout::RegisterFrameStyle()
417 std::unique_ptr<XFFrameStyle> xFrameStyle(new XFFrameStyle);
418 m_pFrame->RegisterStyle(xFrameStyle);
421 LwpTableLayout::LwpTableLayout(LwpObjectHeader const &objHdr, LwpSvStream* pStrm)
422 : LwpLayout(objHdr, pStrm)
423 , m_nRows(0)
424 , m_nCols(0)
425 , m_pDefaultCellLayout(nullptr)
426 , m_bConverted(false)
431 * @short Get neighbour cell by specifying ROW+COL
432 * @param nRow
433 * @param nCol
434 * @return LwpCellLayout *
436 LwpCellLayout * LwpTableLayout::GetCellByRowCol(sal_uInt16 nRow, sal_uInt16 nCol)
438 if (nRow >= m_nRows || nCol >= m_nCols)
439 return nullptr;
441 return m_WordProCellsMap[static_cast<size_t>(nRow)*m_nCols + nCol];
445 * @short traverse all table cells
446 * @param
447 * @param
448 * @param
450 void LwpTableLayout::TraverseTable()
452 sal_uInt32 nCount = m_nRows*m_nCols;
454 // new cell map nRow*nCOl and initialize
455 m_WordProCellsMap.insert(m_WordProCellsMap.end(), nCount, m_pDefaultCellLayout);
457 // set value
458 LwpObjectID* pRowID = &GetChildHead();
459 LwpRowLayout * pRowLayout = dynamic_cast<LwpRowLayout *>(pRowID->obj().get());
460 o3tl::sorted_vector<LwpRowLayout*> aSeen;
461 while (pRowLayout)
463 bool bAlreadySeen = !aSeen.insert(pRowLayout).second;
464 if (bAlreadySeen)
465 throw std::runtime_error("loop in conversion");
467 pRowLayout->SetRowMap();
469 // for 's analysis job
470 m_RowsMap[pRowLayout->GetRowID()] = pRowLayout;
471 pRowLayout->CollectMergeInfo();
472 // end for 's analysis
474 pRowID = &pRowLayout->GetNext();
475 pRowLayout = dynamic_cast<LwpRowLayout *>(pRowID->obj().get());
480 * @short search the cell map
481 * @param nRow - row id (0 based)
482 * @param nRow - row id (0 based)
483 * @return LwpObjectID * - pointer to cell story object ID
485 LwpObjectID * LwpTableLayout::SearchCellStoryMap(sal_uInt16 nRow, sal_uInt16 nCol)
487 if (nRow >= m_nRows || nCol >= m_nCols )
489 return nullptr;
492 LwpCellLayout * pCell = GetCellByRowCol(nRow, nCol);
493 if (pCell)
495 // maybe connected cell layout
496 // maybe default cell layout
497 if (nRow != pCell->GetRowID() || nCol != pCell->GetColID())
499 return nullptr;
501 return &pCell->GetContent();
504 return nullptr;
508 * @short Get parent super table layout of table layout
509 * @return LwpSuperTableLayout * - pointer of parent super table layout
511 LwpSuperTableLayout * LwpTableLayout::GetSuperTableLayout()
513 return dynamic_cast<LwpSuperTableLayout *>(GetParent().obj().get());
516 * @short Get table pointer
517 * @return LwpTable * - content table pointer
519 LwpTable * LwpTableLayout::GetTable()
521 return dynamic_cast<LwpTable *>(m_Content.obj().get());
524 * @short Get column style name by column ID
525 * @param sal_uInt16 -- col id(0 based)
526 * @return OUString - name of column style
528 OUString LwpTableLayout::GetColumnWidth(sal_uInt16 nCol)
530 if (nCol >= m_nCols)
532 assert(false);
533 return m_DefaultColumnStyleName;
536 LwpColumnLayout * pCol = m_aColumns[nCol];
537 if (pCol)
539 return pCol->GetStyleName();
542 return m_DefaultColumnStyleName;
545 * @short analyze all columns to get whole table width and width of all columns
546 * @short and register all column styles
547 * @param none
549 void LwpTableLayout::RegisterColumns()
551 LwpTable* pTable = GetTable();
552 if (!pTable)
553 throw std::range_error("corrupt LwpTableLayout");
555 LwpSuperTableLayout* pSuper = GetSuperTableLayout();
556 if (!pSuper)
557 throw std::range_error("corrupt LwpTableLayout");
559 sal_uInt16 nCols = m_nCols;
561 m_aColumns.resize(nCols);
562 std::unique_ptr<bool[]> pWidthCalculated( new bool[nCols] );
563 for(sal_uInt16 i=0;i<nCols; i++)
565 pWidthCalculated[i] = false;
566 m_aColumns[i] = nullptr;
569 double dDefaultColumn = pTable->GetWidth();
570 sal_uInt16 nJustifiableColumn = nCols;
572 double dTableWidth = pSuper->GetTableWidth();
574 // Get total width of justifiable columns
575 // NOTICE: all default columns are regarded as justifiable columns
576 LwpObjectID* pColumnID = &GetColumnLayoutHead();
577 LwpColumnLayout * pColumnLayout = dynamic_cast<LwpColumnLayout *>(pColumnID->obj().get());
578 o3tl::sorted_vector<LwpColumnLayout*> aSeen;
579 while (pColumnLayout)
581 bool bAlreadySeen = !aSeen.insert(pColumnLayout).second;
582 if (bAlreadySeen)
583 throw std::runtime_error("loop in conversion");
585 auto nColId = pColumnLayout->GetColumnID();
586 if (nColId >= nCols)
588 throw std::range_error("corrupt LwpTableLayout");
590 m_aColumns[nColId] = pColumnLayout;
591 if (!pColumnLayout->IsJustifiable())
593 pWidthCalculated[nColId] = true;
594 dTableWidth -= pColumnLayout->GetWidth();
595 nJustifiableColumn --;
598 pColumnID = &pColumnLayout->GetNext();
599 pColumnLayout = dynamic_cast<LwpColumnLayout *>(pColumnID->obj().get());
602 // if all columns are not justifiable, the rightmost column will be changed to justifiable
603 if (nJustifiableColumn == 0 && nCols != 0)
605 nJustifiableColumn ++;
606 if (m_aColumns[nCols - 1])
608 pWidthCalculated[nCols-1] = false;
609 dTableWidth += m_aColumns[nCols-1]->GetWidth();
611 else
613 // this can't happen
614 dTableWidth = dDefaultColumn;
615 assert(false);
619 // justifiable columns will share the remain width averagely
620 dDefaultColumn = nJustifiableColumn ? dTableWidth/nJustifiableColumn : 0;
622 // register default column style
623 std::unique_ptr<XFColStyle> xColStyle(new XFColStyle);
624 xColStyle->SetWidth(static_cast<float>(dDefaultColumn));
626 XFStyleManager* pXFStyleManager = LwpGlobalMgr::GetInstance()->GetXFStyleManager();
627 m_DefaultColumnStyleName = pXFStyleManager->AddStyle(std::move(xColStyle)).m_pStyle->GetStyleName();
629 // register existed column style
630 sal_uInt16 i=0;
631 for( i=0;i<nCols; i++)
633 if (m_aColumns[i])
635 m_aColumns[i]->SetFoundry(m_pFoundry);
636 if(!pWidthCalculated[i])
638 // justifiable ----register style with calculated value
639 m_aColumns[i]->SetStyleName(m_DefaultColumnStyleName);
641 else
643 // not justifiable ---- register style with original value
644 m_aColumns[i]->RegisterStyle(m_aColumns[i]->GetWidth());
650 * @short register all row styles
651 * @param none
653 void LwpTableLayout::RegisterRows()
655 LwpTable * pTable = GetTable();
656 if (pTable == nullptr)
658 assert(false);
659 return;
662 // register default row style
663 std::unique_ptr<XFRowStyle> xRowStyle(new XFRowStyle);
664 if (m_nDirection & 0x0030)
666 xRowStyle->SetMinRowHeight(static_cast<float>(pTable->GetHeight()));
668 else
670 xRowStyle->SetRowHeight(static_cast<float>(pTable->GetHeight()));
672 XFStyleManager* pXFStyleManager = LwpGlobalMgr::GetInstance()->GetXFStyleManager();
673 m_DefaultRowStyleName = pXFStyleManager->AddStyle(std::move(xRowStyle)).m_pStyle->GetStyleName();
675 // register style of rows
676 LwpObjectID * pRowID = &GetChildHead();
677 LwpRowLayout * pRowLayout = dynamic_cast<LwpRowLayout *>(pRowID->obj().get());
678 while (pRowLayout)
680 pRowLayout->SetFoundry(m_pFoundry);
681 pRowLayout->RegisterStyle();
683 pRowID = &pRowLayout->GetNext();
684 pRowLayout = dynamic_cast<LwpRowLayout *>(pRowID->obj().get());
688 * @short register table style, if needed, including frame style
689 * @param none
691 void LwpTableLayout::RegisterStyle()
693 // get super table layout
694 LwpSuperTableLayout * pSuper = GetSuperTableLayout();
695 if (!pSuper)
696 return;
698 // get table
699 LwpTable * pTable = GetTable();
700 if (pTable == nullptr)
702 SAL_WARN("lwp", "missing table, early return");
703 return;
706 // get row/column number of this table
707 m_nRows = pTable->GetRow();
708 m_nCols = pTable->GetColumn();
709 //http://www.danielsays.com/ss-gallery-win1x2x3x-lotus-word-pro-96.html
710 //tables with up to 255 rows and 8192 columns
711 //the row limit tallies with the casting of m_nCols to an unsigned char
712 //elsewhere
713 if (m_nRows > MAX_NUM_ROWS)
714 throw std::runtime_error("max legal row exceeded");
715 if (m_nCols > MAX_NUM_COLS)
716 throw std::runtime_error("max legal column exceeded");
718 // get default cell layout of current table
719 LwpObjectID& rID= pTable->GetDefaultCellStyle();
720 m_pDefaultCellLayout = dynamic_cast<LwpCellLayout *>(rID.obj().get());
722 // register columns styles
723 RegisterColumns();
725 // register style of whole table
726 std::unique_ptr<XFTableStyle> xTableStyle(new XFTableStyle);
728 sal_uInt8 nType = pSuper->GetRelativeType();
729 // If the table is not "with paragraph above" placement, create an frame style
730 // by supertable layout
731 if ( LwpLayoutRelativityGuts::LAY_INLINE_NEWLINE == nType
732 && (!pSuper->GetContainerLayout().is() || !pSuper->GetContainerLayout()->IsCell()) )
734 //with para above
735 pSuper->ApplyBackGround(xTableStyle.get());
736 pSuper->ApplyWatermark(xTableStyle.get());
737 pSuper->ApplyShadow(xTableStyle.get());
738 pSuper->ApplyAlignment(xTableStyle.get());
739 xTableStyle->SetWidth(pSuper->GetTableWidth());
741 else
743 pSuper->RegisterFrameStyle();
744 xTableStyle->SetAlign(enumXFAlignCenter);
745 xTableStyle->SetWidth(pSuper->GetTableWidth());
747 XFStyleManager* pXFStyleManager = LwpGlobalMgr::GetInstance()->GetXFStyleManager();
748 m_StyleName = pXFStyleManager->AddStyle(std::move(xTableStyle)).m_pStyle->GetStyleName();
750 //convert to OO table now and register row style traverse
751 TraverseTable();
753 SplitConflictCells();
755 // Register rows layouts, it must be after SplitConflictCells
756 RegisterRows();
758 // Parse table
759 ParseTable();
761 // the old code doesn't check if the LwpFoundry pointer is NULL,
762 // so the NULL pointer cause sodc freeze. Add code to check the pointer.
763 if (GetFoundry())
764 PutCellVals(GetFoundry(), pTable->GetObjectID());
767 * @short read table layout
768 * @param none
770 void LwpTableLayout::ParseTable()
772 // get super table layout
773 LwpSuperTableLayout* pSuper = GetSuperTableLayout();
774 if (!pSuper)
776 throw std::runtime_error("missing super table");
779 if (m_pXFTable)
781 throw std::runtime_error("this table is already parsed");
784 // set name of object
785 m_pXFTable.set(new XFTable);
787 m_pXFTable->SetTableName(pSuper->GetName().str());
788 // set table style
789 m_pXFTable->SetStyleName(m_StyleName);
791 sal_uInt16 nRow = m_nRows;
792 sal_uInt8 nCol = static_cast<sal_uInt8>(m_nCols);
794 sal_uInt16 nContentRow = 0;
796 //process header rows
797 LwpTableHeadingLayout* pTableHeading;
798 pTableHeading = pSuper->GetTableHeadingLayout();
799 if (pTableHeading)
801 sal_uInt16 nStartHeadRow;
802 sal_uInt16 nEndHeadRow;
803 pTableHeading->GetStartEndRow(nStartHeadRow,nEndHeadRow);
804 if (nStartHeadRow == 0)
806 if (comphelper::IsFuzzing() && nEndHeadRow - nStartHeadRow > 128)
808 SAL_WARN("lwp", "truncating HeadingRow for fuzzing performance");
809 nEndHeadRow = nStartHeadRow + 128;
811 nContentRow = ConvertHeadingRow(m_pXFTable,nStartHeadRow,nEndHeadRow+1);
815 ConvertTable(m_pXFTable, nContentRow, nRow, 0, nCol);
819 * @short read table layout
820 * @param none
822 void LwpTableLayout::Read()
824 LwpLayout::Read();
826 // before layout hierarchy rework!
827 if(LwpFileHeader::m_nFileRevision < 0x000b)
829 assert(false);
831 m_ColumnLayout.ReadIndexed(m_pObjStrm.get());
833 m_pObjStrm->SkipExtra();
837 * @short Convert table
838 * @param
839 * @return pCont - container which will contain table
841 void LwpTableLayout::XFConvert(XFContentContainer* pCont)
843 if (!m_pXFTable)
844 return;
845 if (m_bConverted)
846 throw std::runtime_error("already added to a container");
847 pCont->Add(m_pXFTable.get());
848 m_bConverted = true;
852 * @short convert heading row
853 * @param pXFTable - pointer of table
854 * @param nStartRow - start heading row ID
855 * @param nEndRow - end heading row ID
857 sal_uInt16 LwpTableLayout::ConvertHeadingRow(
858 rtl::Reference<XFTable> const & pXFTable, sal_uInt16 nStartHeadRow, sal_uInt16 nEndHeadRow)
860 sal_uInt16 nContentRow;
861 LwpTable* pTable = GetTable();
862 assert(pTable);
863 sal_uInt8 nCol = static_cast<sal_uInt8>(pTable->GetColumn());
864 rtl::Reference<XFTable> pTmpTable( new XFTable );
866 ConvertTable(pTmpTable,nStartHeadRow,nEndHeadRow,0,nCol);
868 sal_uInt16 nRowNum = pTmpTable->GetRowCount();
869 std::vector<sal_uInt8> CellMark(nRowNum);
871 if (nRowNum == 1)
873 XFRow* pXFRow = pTmpTable->GetRow(1);
874 pXFTable->AddHeaderRow(pXFRow);
875 pTmpTable->RemoveRow(1);
876 nContentRow = nEndHeadRow;
878 else
880 sal_uInt8 nFirstColSpann = 1;
881 const bool bFindFlag = FindSplitColMark(pTmpTable.get(), CellMark, nFirstColSpann);
883 if (bFindFlag)//split to 2 cells
885 SplitRowToCells(pTmpTable.get(), pXFTable, nFirstColSpann, CellMark.data());
886 nContentRow = nEndHeadRow;
888 else//can not split,the first row will be the heading row,the rest will be content row
890 XFRow* pXFRow = pTmpTable->GetRow(1);
891 pXFTable->AddHeaderRow(pXFRow);
892 pTmpTable->RemoveRow(1);
893 auto iter = m_RowsMap.find(0);
894 if (iter == m_RowsMap.end())
896 SAL_WARN("lwp", "row 0 is unknown");
897 nContentRow = 0;
899 else
900 nContentRow = iter->second->GetCurMaxSpannedRows(0,nCol);
903 return nContentRow;
906 void LwpTableLayout::SplitRowToCells(XFTable* pTmpTable, rtl::Reference<XFTable> const & pXFTable,
907 sal_uInt8 nFirstColSpann,const sal_uInt8* pCellMark)
909 sal_uInt16 i;
910 sal_uInt16 nRowNum = pTmpTable->GetRowCount();
911 LwpTable* pTable = GetTable();
912 assert(pTable);
913 sal_uInt8 nCol = static_cast<sal_uInt8>(pTable->GetColumn());
915 rtl::Reference<XFRow> xXFRow(new XFRow);
917 //register style for heading row
918 double fHeight = 0;
919 std::unique_ptr<XFRowStyle> xRowStyle(new XFRowStyle);
920 XFRow* pRow = pTmpTable->GetRow(1);
921 if (!pRow)
922 throw std::runtime_error("missing row");
923 OUString styleName = pRow->GetStyleName();
925 // get settings of the row and assign them to new row style
926 XFStyleManager* pXFStyleManager = LwpGlobalMgr::GetInstance()->GetXFStyleManager();
927 XFRowStyle *pTempRowStyle = static_cast<XFRowStyle*>(pXFStyleManager->FindStyle(styleName));
928 if (pTempRowStyle)
929 *xRowStyle = *pTempRowStyle;
931 for (i=1;i<=nRowNum;i++)
933 styleName = pTmpTable->GetRow(i)->GetStyleName();
934 if (XFRowStyle* pRowStyle = static_cast<XFRowStyle*>(pXFStyleManager->FindStyle(styleName)))
935 fHeight+=pRowStyle->GetRowHeight();
937 if (m_nDirection & 0x0030)
939 xRowStyle->SetMinRowHeight(static_cast<float>(fHeight));
941 else
943 xRowStyle->SetRowHeight(static_cast<float>(fHeight));
945 xXFRow->SetStyleName(pXFStyleManager->AddStyle(std::move(xRowStyle)).m_pStyle->GetStyleName());
947 //construct heading row
948 rtl::Reference<XFCell> xXFCell1(new XFCell);
949 rtl::Reference<XFCell> xXFCell2(new XFCell);
950 rtl::Reference<XFTable> xSubTable1(new XFTable);
951 rtl::Reference<XFTable> xSubTable2(new XFTable);
952 rtl::Reference<XFCell> xNewCell;
954 for (i=1;i<=nRowNum;i++)
956 XFRow* pOldRow = pTmpTable->GetRow(i);
957 rtl::Reference<XFRow> xNewRow(new XFRow);
958 xNewRow->SetStyleName(pOldRow->GetStyleName());
959 for (sal_uInt8 j=1;j<=pCellMark[i];j++)
961 xNewCell = pOldRow->GetCell(j);
962 xNewRow->AddCell(xNewCell);
964 xSubTable1->AddRow(xNewRow);
966 ConvertColumn(xSubTable1, 0, nFirstColSpann);//add column info
968 xXFCell1->Add(xSubTable1.get());
969 xXFCell1->SetColumnSpaned(nFirstColSpann);
970 xXFRow->AddCell(xXFCell1);
972 for (i=1;i<=nRowNum;i++)
974 XFRow* pOldRow = pTmpTable->GetRow(i);
975 rtl::Reference<XFRow> xNewRow(new XFRow);
976 xNewRow->SetStyleName(pOldRow->GetStyleName());
977 for(sal_Int32 j=pCellMark[i]+1;j<=pOldRow->GetCellCount();j++)
979 xNewCell = pOldRow->GetCell(j);
980 xNewRow->AddCell(xNewCell);
982 xSubTable2->AddRow(xNewRow);
985 ConvertColumn(xSubTable2, nFirstColSpann, nCol);//add column info
986 xXFCell2->Add(xSubTable2.get());
987 xXFCell2->SetColumnSpaned(nCol-nFirstColSpann);
988 xXFRow->AddCell(xXFCell2);
990 pXFTable->AddHeaderRow(xXFRow.get());
992 //remove tmp table
993 for (i=1;i<=nRowNum;i++)
995 pTmpTable->RemoveRow(i);
1000 * @short find if the heading rows can be split to 2 cells
1001 * @param pXFTable - pointer of tmp XFtable
1002 * @param CellMark - pointer of cell mark array
1004 bool LwpTableLayout::FindSplitColMark(XFTable* pXFTable, std::vector<sal_uInt8>& rCellMark,
1005 sal_uInt8& nMaxColSpan)
1007 sal_uInt16 nRowNum = pXFTable->GetRowCount();
1008 sal_uInt8 nColNum = static_cast<sal_uInt8>(pXFTable->GetColumnCount());
1009 sal_uInt8 nCount;
1010 sal_uInt8 nColSpan;
1011 bool bFindFlag = false;
1012 XFRow* pTmpRow;
1014 for(sal_uInt8 i=1;i<=nColNum;i++)
1016 sal_uInt16 nRowLoop;
1018 //find current max column span
1019 nMaxColSpan = 1;
1020 for (nRowLoop=1;nRowLoop<=nRowNum;nRowLoop++)
1022 nColSpan = 0;
1023 for(sal_uInt8 nCellLoop=1; nCellLoop<i+1; nCellLoop++)
1025 pTmpRow = pXFTable->GetRow(nRowLoop);
1026 XFCell* pCell = pTmpRow->GetCell(nCellLoop);
1027 if (pCell)
1028 nColSpan += static_cast<sal_uInt8>(pCell->GetColSpaned());
1029 else
1030 return false;
1032 if (nColSpan > nMaxColSpan)
1033 nMaxColSpan = nColSpan;
1034 rCellMark.at(nRowLoop) = 0;//reset all cell mark to zero
1037 //find if other row has the same column
1038 for (nRowLoop=1;nRowLoop<=nRowNum;nRowLoop++)
1040 pTmpRow = pXFTable->GetRow(nRowLoop);
1041 nCount = 0;
1042 sal_Int32 nCellMark = 0;
1043 for (sal_Int32 nCellLoop=1; nCellLoop<=pTmpRow->GetCellCount(); nCellLoop++)
1045 if (nCount>nMaxColSpan)
1046 break;
1047 nCount+= static_cast<sal_uInt8>(pTmpRow->GetCell(nCellLoop)->GetColSpaned());
1048 if (nCount == nMaxColSpan)
1050 nCellMark = nCellLoop;
1051 break;
1054 if (nCellMark == 0)
1055 break;
1056 else
1057 rCellMark.at(nRowLoop) = nCellMark;
1059 for(nRowLoop=1;nRowLoop<=nRowNum;nRowLoop++)//check if all ==0,break
1061 if (rCellMark.at(nRowLoop) == 0)
1062 break;
1064 if (nRowLoop == nRowNum+1)
1066 bFindFlag = true;
1067 return bFindFlag;
1071 return bFindFlag;
1074 static bool operator==(const TableConvertAttempt& a, const TableConvertAttempt& b)
1076 return a.mnStartRow == b.mnStartRow &&
1077 a.mnEndRow == b.mnEndRow &&
1078 a.mnStartCol== b.mnStartCol &&
1079 a.mnEndCol == b.mnEndCol;
1083 * @short convert word pro table to SODC table
1084 * @param pXFTable - pointer of table
1085 * @param nStartRow - start row ID
1086 * @param nEndRow - end row ID
1087 * @param nStartCol - start column ID
1088 * @param nEndCol - end column ID
1090 void LwpTableLayout::ConvertTable(rtl::Reference<XFTable> const & pXFTable, sal_uInt16 nStartRow,
1091 sal_uInt16 nEndRow,sal_uInt8 nStartCol,sal_uInt8 nEndCol)
1093 TableConvertAttempt aConversionAttempt(nStartRow, nEndRow, nStartCol, nEndCol);
1094 auto itr = std::find(m_aConvertingStack.begin(), m_aConvertingStack.end(), aConversionAttempt);
1095 if (itr != m_aConvertingStack.end())
1097 SAL_WARN("lwp", "already trying to convert this range");
1098 return;
1101 m_aConvertingStack.push_back(aConversionAttempt);
1103 //out put column info TO BE CHANGED
1104 ConvertColumn(pXFTable,nStartCol,nEndCol);
1106 std::map<sal_uInt16,LwpRowLayout*>::iterator iter;
1108 for (sal_uInt16 i=nStartRow; i<nEndRow;)
1110 iter = m_RowsMap.find(i);
1111 if (iter == m_RowsMap.end())
1113 ConvertDefaultRow(pXFTable,nStartCol,nEndCol,i);
1114 i++;
1116 else
1118 LwpRowLayout* pRow = iter->second;
1119 if (pRow->GetCurMaxSpannedRows(nStartCol,nEndCol) == 1)
1121 pRow->ConvertCommonRow(pXFTable,nStartCol,nEndCol);
1122 i++;
1124 else
1126 pRow->ConvertRow(pXFTable,nStartCol,nEndCol);
1127 i += pRow->GetCurMaxSpannedRows(nStartCol,nEndCol);
1132 m_aConvertingStack.pop_back();
1136 * @short apply numeric value and formula to cell
1137 * @param pFoundry - pointer of foundry
1138 * @param aTableID - table ID
1140 void LwpTableLayout::PutCellVals(LwpFoundry* pFoundry, LwpObjectID aTableID)
1143 // The old code doesn't check if the LwpFoundry pointer is NULL, so the NULL
1144 // pointer cause sodc frozen. Add code to check the pointer.
1145 if( !pFoundry ) return;
1147 try{
1149 LwpDLVListHeadHolder* pHolder = dynamic_cast<LwpDLVListHeadHolder*>(pFoundry->GetNumberManager().GetTableRangeID().obj().get());
1151 LwpTableRange* pTableRange = pHolder ? dynamic_cast<LwpTableRange*>(pHolder->GetHeadID().obj().get()) : nullptr;
1153 //Look up the table
1154 o3tl::sorted_vector<LwpTableRange*> aTableSeen;
1155 while (pTableRange)
1157 bool bAlreadySeenTable = !aTableSeen.insert(pTableRange).second;
1158 if (bAlreadySeenTable)
1159 throw std::runtime_error("loop in conversion");
1160 LwpObjectID aID = pTableRange->GetTableID();
1161 if (aID == aTableID)
1163 break;
1165 pTableRange = pTableRange->GetNext();
1168 if (!pTableRange)
1169 return;
1171 LwpCellRange* pRange = dynamic_cast<LwpCellRange*>(pTableRange->GetCellRangeID().obj().get());
1172 if (!pRange)
1173 return;
1175 LwpFolder* pFolder = dynamic_cast<LwpFolder*>(pRange->GetFolderID().obj().get());
1176 if (!pFolder)
1177 return;
1179 LwpObjectID aRowListID = pFolder->GetChildHeadID();
1180 LwpRowList* pRowList = dynamic_cast<LwpRowList*>(aRowListID.obj().get());
1182 //loop the rowlist
1183 o3tl::sorted_vector<LwpRowList*> aOuterSeen;
1184 while (pRowList)
1186 bool bAlreadySeenOuter = !aOuterSeen.insert(pRowList).second;
1187 if (bAlreadySeenOuter)
1188 throw std::runtime_error("loop in conversion");
1189 sal_uInt16 nRowID = pRowList->GetRowID();
1191 LwpCellList* pCellList = dynamic_cast<LwpCellList*>(pRowList->GetChildHeadID().obj().get());
1192 //loop the cellList
1193 o3tl::sorted_vector<LwpCellList*> aSeen;
1194 while (pCellList)
1196 bool bAlreadySeen = !aSeen.insert(pCellList).second;
1197 if (bAlreadySeen)
1198 throw std::runtime_error("loop in conversion");
1200 {//put cell
1201 sal_uInt16 nColID = pCellList->GetColumnID();
1203 XFCell* pCell = GetCellsMap(nRowID,static_cast<sal_uInt8>(nColID));
1204 if (!pCell)
1206 throw std::runtime_error("Hidden cell would not be in cellsmap");
1209 pCellList->Convert(pCell, this);
1211 //process paragraph
1212 PostProcessParagraph(pCell, nRowID, nColID);
1215 pCellList = dynamic_cast<LwpCellList*>(pCellList->GetNextID().obj().get());
1218 pRowList = dynamic_cast<LwpRowList*>(pRowList->GetNextID().obj().get());
1221 }catch (...) {
1222 SAL_WARN("lwp", "bad PutCellVals");
1227 * @short 1. set number right alignment to right if number 2. remove tab added before if number
1228 * @param pCell - cell which to be process
1229 * @param nRowID - row number in Word Pro file
1230 * @param nColID - column number in Word Pro file
1232 void LwpTableLayout::PostProcessParagraph(XFCell *pCell, sal_uInt16 nRowID, sal_uInt16 nColID)
1234 // if number right, set alignment to right
1235 LwpCellLayout * pCellLayout = GetCellByRowCol(nRowID, nColID);
1236 if(!pCellLayout)
1237 return;
1239 rtl::Reference<XFContent> first(
1240 pCell->FindFirstContent(enumXFContentPara));
1241 XFParagraph * pXFPara = static_cast<XFParagraph*>(first.get());
1242 if (!pXFPara)
1243 return;
1244 XFColor aNullColor;
1246 OUString sNumfmt = pCellLayout->GetNumfmtName();
1247 bool bColorMod = false;
1248 XFNumberStyle* pNumStyle = nullptr;
1249 XFStyleManager* pXFStyleManager = LwpGlobalMgr::GetInstance()->GetXFStyleManager();
1250 if (!sNumfmt.isEmpty())
1252 pNumStyle = static_cast<XFNumberStyle*>(pXFStyleManager->FindStyle(sNumfmt));
1253 XFColor aColor = pNumStyle->GetColor();
1254 if ( aColor != aNullColor )
1255 bColorMod = true;//end
1258 XFParaStyle * pStyle = pXFStyleManager->FindParaStyle(pXFPara->GetStyleName());
1259 if (!((pStyle && pStyle->GetNumberRight()) || bColorMod))
1260 return;
1262 std::unique_ptr<XFParaStyle> xOverStyle(new XFParaStyle);
1264 if (pStyle)
1266 *xOverStyle = *pStyle;
1268 if (pStyle->GetNumberRight())
1269 xOverStyle->SetAlignType(enumXFAlignEnd);
1272 if (bColorMod)
1274 rtl::Reference<XFFont> xFont = xOverStyle->GetFont();
1275 if (xFont.is())
1277 XFColor aColor = xFont->GetColor();
1278 if (aColor == aNullColor)
1280 rtl::Reference<XFFont> pNewFont(new XFFont);
1281 aColor = pNumStyle->GetColor();
1282 pNewFont->SetColor(aColor);
1283 xOverStyle->SetFont(pNewFont);
1288 xOverStyle->SetStyleName(u""_ustr);
1289 OUString StyleName
1290 = pXFStyleManager->AddStyle(std::move(xOverStyle)).m_pStyle->GetStyleName();
1292 pXFPara->SetStyleName(StyleName);
1296 * @short Parse all cols of table
1297 * @param pXFTable - pointer to created XFTable
1299 void LwpTableLayout::ConvertColumn(rtl::Reference<XFTable> const & pXFTable, sal_uInt8 nStartCol, sal_uInt8 nEndCol)
1301 LwpTable * pTable = GetTable();
1302 if (!pTable)
1304 assert(false);
1305 return;
1308 for (sal_uInt32 iLoop = 0; iLoop < static_cast<sal_uInt32>(nEndCol)-nStartCol; ++iLoop)
1310 // add row to table
1311 LwpObjectID *pColID = &GetColumnLayoutHead();
1312 LwpColumnLayout * pColumnLayout = dynamic_cast<LwpColumnLayout *>(pColID->obj().get());
1313 while (pColumnLayout)
1315 if (pColumnLayout->GetColumnID() == (iLoop+nStartCol))
1317 pXFTable->SetColumnStyle(iLoop+1, pColumnLayout->GetStyleName());
1318 break;
1320 pColID = &pColumnLayout->GetNext();
1321 pColumnLayout = dynamic_cast<LwpColumnLayout *>(pColID->obj().get());
1323 if (!pColumnLayout)
1325 pXFTable->SetColumnStyle(iLoop+1, m_DefaultColumnStyleName);
1330 * @short split conflict merged cells
1332 void LwpTableLayout::SplitConflictCells()
1334 LwpTable * pTable = GetTable();
1335 if (!pTable)
1336 return;
1337 sal_uInt16 nCol = pTable->GetColumn();
1338 sal_uInt16 nRow = pTable->GetRow();
1340 sal_uInt16 nEffectRows;
1341 std::map<sal_uInt16,LwpRowLayout*>::iterator iter1;
1342 std::map<sal_uInt16,LwpRowLayout*>::iterator iter2;
1343 LwpRowLayout* pRowLayout;
1344 LwpRowLayout* pEffectRow;
1346 for (sal_uInt16 i=0; i<nRow; )
1348 iter1 = m_RowsMap.find(i);
1349 if (iter1 == m_RowsMap.end())//default rows
1351 i++;
1352 continue;
1354 pRowLayout= iter1->second;
1355 if (!pRowLayout->GetMergeCellFlag())
1357 i++;
1358 continue;
1360 else
1362 nEffectRows = i + pRowLayout->GetCurMaxSpannedRows(0,static_cast<sal_uInt8>(nCol));
1364 for (sal_uInt16 j = i+1; j<nEffectRows; j++)
1366 iter2 = m_RowsMap.find(j);
1367 if (iter2 == m_RowsMap.end())
1368 continue;
1369 pEffectRow = iter2->second;
1370 if (!pEffectRow->GetMergeCellFlag())
1371 continue;
1372 else
1373 pEffectRow->SetCellSplit(nEffectRows);
1375 i = nEffectRows;
1377 }//end for
1381 * @short add default row which are missing in the file
1382 * @param pXFTable - pointer to new created table
1383 * @param nStartCol - starting column
1384 * @param nEndCol - end column
1385 * @return pXFTable
1387 void LwpTableLayout::ConvertDefaultRow(rtl::Reference<XFTable> const & pXFTable, sal_uInt8 nStartCol,
1388 sal_uInt8 nEndCol, sal_uInt16 nRowID)
1390 // current row doesn't exist in the file
1391 rtl::Reference<XFRow> xRow(new XFRow);
1392 xRow->SetStyleName(m_DefaultRowStyleName);
1394 for (sal_uInt16 j =0;j < nEndCol-nStartCol; j++)
1396 // if table has default cell layout, use it to ConvertCell
1397 // otherwise use blank cell
1398 rtl::Reference<XFCell> xCell;
1399 if (m_pDefaultCellLayout)
1401 LwpTable* pTable = GetTable();
1402 assert(pTable);
1403 xCell = m_pDefaultCellLayout->DoConvertCell(
1404 pTable->GetObjectID(),nRowID,j+nStartCol);
1406 else
1408 xCell.set(new XFCell);
1410 xRow->AddCell(xCell);
1413 pXFTable->AddRow(xRow);
1417 * @short set cell map info
1418 * @param pXFCell - pointer to xfcell
1419 * @param nRow - row id
1420 * @param nCol - column id
1422 void LwpTableLayout::SetCellsMap(sal_uInt16 nRow1, sal_uInt8 nCol1,
1423 sal_uInt16 nRow2, sal_uInt8 nCol2, XFCell* pXFCell)
1425 m_CellsMap.insert({{nRow1, nCol1}, {nRow2, nCol2}}, pXFCell);
1429 * @short get cell map info
1430 * @param nRow - row id
1431 * @param nCol - column id
1432 * @return pXFCell
1434 XFCell* LwpTableLayout::GetCellsMap(sal_uInt16 nRow, sal_uInt8 nCol)
1436 auto results = m_CellsMap.search({{nRow, nCol}, {nRow, nCol}}, rt_type::search_type::overlap);
1437 if (results.begin() == results.end())
1438 return nullptr;
1439 // return the last thing inserted for this position
1440 return std::prev(results.end())->GetCell();
1443 * @descr Get row layout by row id
1444 * @param nRow - row id
1446 LwpRowLayout* LwpTableLayout::GetRowLayout(sal_uInt16 nRow)
1448 LwpObjectID *pRowID = &GetChildHead();
1449 LwpRowLayout * pRowLayout = dynamic_cast<LwpRowLayout *>(pRowID->obj().get());
1450 while (pRowLayout)
1452 if(pRowLayout->GetRowID() == nRow)
1453 return pRowLayout;
1455 pRowID = &pRowLayout->GetNext();
1456 pRowLayout = dynamic_cast<LwpRowLayout *>(pRowID->obj().get());
1458 return nullptr;
1461 //add end by
1462 LwpColumnLayout::LwpColumnLayout(LwpObjectHeader const &objHdr, LwpSvStream* pStrm)
1463 : LwpVirtualLayout(objHdr, pStrm)
1464 , ccolid(0)
1465 , cwidth(0)
1468 LwpColumnLayout::~LwpColumnLayout()
1470 void LwpColumnLayout::Read()
1472 LwpObjectStream* pStrm = m_pObjStrm.get();
1474 LwpVirtualLayout::Read();
1476 sal_uInt16 colid;
1478 colid = pStrm->QuickReaduInt16(); // forced to lushort
1479 ccolid = static_cast<sal_uInt8>(colid);
1480 cwidth = pStrm->QuickReadInt32();
1482 pStrm->SkipExtra();
1485 void LwpColumnLayout::RegisterStyle(double dCalculatedWidth)
1487 std::unique_ptr<XFColStyle> xColStyle(new XFColStyle);
1488 xColStyle->SetWidth(static_cast<float>(dCalculatedWidth));
1489 XFStyleManager* pXFStyleManager = LwpGlobalMgr::GetInstance()->GetXFStyleManager();
1490 m_StyleName = pXFStyleManager->AddStyle(std::move(xColStyle)).m_pStyle->GetStyleName();
1493 LwpTableHeadingLayout::LwpTableHeadingLayout(LwpObjectHeader const &objHdr, LwpSvStream* pStrm)
1494 : LwpTableLayout(objHdr, pStrm)
1495 , cStartRow(0)
1496 , cEndRow(0)
1499 LwpTableHeadingLayout::~LwpTableHeadingLayout()
1502 * @short read table heading layout
1503 * @param
1504 * @return
1506 void LwpTableHeadingLayout::Read()
1508 LwpTableLayout::Read();
1510 cStartRow = m_pObjStrm->QuickReaduInt16();
1511 cEndRow = m_pObjStrm->QuickReaduInt16();
1513 m_pObjStrm->SkipExtra();
1517 * @short get start and end row number of table heading
1518 * @param
1519 * @return *pStartRow - starting row number
1520 * @return *pEndRow - end row number
1522 void LwpTableHeadingLayout::GetStartEndRow(sal_uInt16& nStartRow, sal_uInt16& nEndRow)
1524 nStartRow = cStartRow;
1525 nEndRow = cEndRow;
1528 LwpSuperParallelColumnLayout::LwpSuperParallelColumnLayout(LwpObjectHeader const &objHdr, LwpSvStream* pStrm):LwpSuperTableLayout(objHdr, pStrm)
1531 LwpSuperParallelColumnLayout::~LwpSuperParallelColumnLayout()
1534 void LwpSuperParallelColumnLayout::Read()
1536 LwpSuperTableLayout::Read();
1537 m_pObjStrm->SkipExtra();
1541 LwpSuperGlossaryLayout::LwpSuperGlossaryLayout(LwpObjectHeader const &objHdr, LwpSvStream* pStrm):LwpSuperTableLayout(objHdr, pStrm)
1545 LwpSuperGlossaryLayout::~LwpSuperGlossaryLayout()
1549 void LwpSuperGlossaryLayout::Read()
1551 LwpSuperTableLayout::Read();
1552 m_pObjStrm->SkipExtra();
1555 LwpParallelColumnsLayout::LwpParallelColumnsLayout(LwpObjectHeader const &objHdr, LwpSvStream* pStrm):LwpTableLayout(objHdr, pStrm)
1559 LwpParallelColumnsLayout::~LwpParallelColumnsLayout()
1563 void LwpParallelColumnsLayout::Read()
1565 LwpTableLayout::Read();
1566 m_pObjStrm->SkipExtra();
1569 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */