tdf#131098 docx export: write fill property of graphic
[LibreOffice.git] / lotuswordpro / source / filter / lwprowlayout.cxx
blobde06c6b98aed7dc52d02af900a5b7b6470b16352
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 - row layouts
61 #include "lwprowlayout.hxx"
62 #include "lwptable.hxx"
63 #include <lwpglobalmgr.hxx>
64 #include <xfilter/xfstylemanager.hxx>
65 #include <xfilter/xfrow.hxx>
66 #include <xfilter/xfrowstyle.hxx>
67 #include <xfilter/xftable.hxx>
68 #include <xfilter/xfcell.hxx>
69 #include <o3tl/sorted_vector.hxx>
71 LwpRowLayout::LwpRowLayout(LwpObjectHeader const &objHdr, LwpSvStream* pStrm)
72 : LwpVirtualLayout(objHdr, pStrm)
73 , crowid(0)
74 , cheight(0)
75 , cLeaderDotCount(0)
76 , cLeaderDotY(0)
77 , cRowFlags(0)
79 m_ConnCellList.clear();
82 LwpRowLayout::~LwpRowLayout()
85 /**
86 * @short register row style
87 * @param
88 * @param
89 * @param
90 * @return
92 void LwpRowLayout::SetRowMap()
94 LwpObjectID *pCellID= &GetChildHead();
95 LwpCellLayout * pCellLayout = dynamic_cast<LwpCellLayout *>(pCellID->obj().get());
97 o3tl::sorted_vector<LwpCellLayout*> aSeen;
98 while(pCellLayout)
100 bool bAlreadySeen = !aSeen.insert(pCellLayout).second;
101 if (bAlreadySeen)
102 throw std::runtime_error("loop in conversion");
104 pCellLayout->SetCellMap();
106 pCellID = &pCellLayout->GetNext();
107 pCellLayout = dynamic_cast<LwpCellLayout *>(pCellID->obj().get());
111 * @short register row style
112 * @param
113 * @param
114 * @param
115 * @return
117 void LwpRowLayout::RegisterStyle()
119 // register row style
120 std::unique_ptr<XFRowStyle> pRowStyle(new XFRowStyle());
122 if (m_nDirection & 0x0030)
124 pRowStyle->SetMinRowHeight(LwpTools::ConvertFromUnits(cheight));
126 else
128 pRowStyle->SetRowHeight(LwpTools::ConvertFromUnits(cheight));
130 XFStyleManager* pXFStyleManager = LwpGlobalMgr::GetInstance()->GetXFStyleManager();
131 m_StyleName = pXFStyleManager->AddStyle(std::move(pRowStyle)).m_pStyle->GetStyleName();
133 LwpTableLayout* pTableLayout = GetParentTableLayout();
134 if (pTableLayout)
136 pTableLayout->GetTable();
138 // register cells' style
139 LwpObjectID *pCellID= &GetChildHead();
140 LwpCellLayout * pCellLayout = dynamic_cast<LwpCellLayout *>(pCellID->obj().get());
142 o3tl::sorted_vector<LwpCellLayout*> aSeen;
143 while (pCellLayout)
145 bool bAlreadySeen = !aSeen.insert(pCellLayout).second;
146 if (bAlreadySeen)
147 throw std::runtime_error("loop in conversion");
149 pCellLayout->SetFoundry(m_pFoundry);
150 pCellLayout->RegisterStyle();
151 pCellID = &pCellLayout->GetNext();
152 pCellLayout = dynamic_cast<LwpCellLayout *>(pCellID->obj().get());
157 * @short register row style
158 * @param
159 * @param
160 * @param
161 * @return
163 void LwpRowLayout::Read()
165 #define MAXUNIT (0x7fffffffL) // Highest positive UNIT value
166 LwpObjectStream* pStrm = m_pObjStrm.get();
168 LwpVirtualLayout::Read();
170 //skip CLiteLayout data;
171 LwpAtomHolder ContentClass;
172 ContentClass.Read(pStrm);
173 pStrm->SkipExtra();
175 // Row layout content
176 crowid = pStrm->QuickReaduInt16();
177 cheight = pStrm->QuickReadInt32();
178 cLeaderDotCount = static_cast<sal_uInt8>(pStrm->QuickReaduInt16()); // was written as lushort.
179 cLeaderDotY = MAXUNIT; // Sentinel meaning "not calculated yet"
180 cRowFlags = static_cast<sal_uInt8>(pStrm->QuickReaduInt16()); // was written as lushort.
182 pStrm->SkipExtra();
186 * @short Parse rows with connect cell
187 * @param pXFTable - pointer to created XFTable
189 void LwpRowLayout::ConvertRow(rtl::Reference<XFTable> const & pXFTable,sal_uInt8 nStartCol,sal_uInt8 nEndCol)
191 LwpTableLayout* pTableLayout = GetParentTableLayout();
192 if (!pTableLayout)
193 throw std::runtime_error("missing TableLayout");
194 LwpTable* pTable = pTableLayout->GetTable();
195 if (!pTable)
196 throw std::runtime_error("missing Table");
198 //calculate the connected cell position
199 sal_Int32 nMarkConnCell = FindMarkConnCell(nStartCol,nEndCol);
201 //if there is no connected cell
202 if (nMarkConnCell == -1)
204 ConvertCommonRow(pXFTable,nStartCol,nEndCol);
205 return;
208 //register connect row style
209 sal_uInt16 nRowMark = crowid + GetCurMaxSpannedRows(nStartCol,nEndCol);
210 rtl::Reference<XFRow> xXFRow(new XFRow);
211 RegisterCurRowStyle(xXFRow.get(), nRowMark);
213 //if there is connected cell
214 for (sal_uInt8 i=nStartCol; i<nEndCol; )
216 rtl::Reference<XFCell> xXFCell;
217 sal_uInt8 nColMark;
219 if (nMarkConnCell == -1)
220 nColMark = nEndCol;
221 else
222 nColMark = m_ConnCellList[nMarkConnCell]->GetColID();
224 if (nColMark > i)//create subtable
226 xXFCell.set(new XFCell);
227 xXFCell->SetColumnSpaned(nColMark-i);
228 rtl::Reference<XFTable> xSubTable(new XFTable);
229 pTableLayout->ConvertTable(xSubTable,crowid,nRowMark,i,nColMark);
230 xXFCell->Add(xSubTable.get());
231 i = nColMark;
233 else
235 sal_uInt8 nColID = m_ConnCellList[nMarkConnCell]->GetColID()
236 +m_ConnCellList[nMarkConnCell]->GetNumcols()-1;
237 xXFCell = m_ConnCellList[nMarkConnCell]->DoConvertCell(
238 pTable->GetObjectID(),
239 crowid+m_ConnCellList[nMarkConnCell]->GetNumrows()-1,
240 m_ConnCellList[nMarkConnCell]->GetColID());
242 //set all cell in this merge cell to cellsmap
243 pTableLayout->SetCellsMap(crowid, i, nRowMark - 1, nColID, xXFCell.get());
245 i += m_ConnCellList[nMarkConnCell]->GetNumcols();
246 nMarkConnCell = FindNextMarkConnCell(static_cast<sal_uInt16>(nMarkConnCell),nEndCol);
249 if (xXFCell)
250 xXFRow->AddCell(xXFCell);
252 pXFTable->AddRow(xXFRow);
256 * @short register row style in SODC table
257 * @param pXFRow - pointer of row
258 * @param nRowMark - spanned row number
260 void LwpRowLayout::RegisterCurRowStyle(XFRow* pXFRow,sal_uInt16 nRowMark)
262 XFStyleManager* pXFStyleManager = LwpGlobalMgr::GetInstance()->GetXFStyleManager();
263 XFRowStyle* pRowStyle = static_cast<XFRowStyle*>(pXFStyleManager->FindStyle(m_StyleName));
264 if (!pRowStyle)
265 return;
266 double fHeight = pRowStyle->GetRowHeight();
268 std::unique_ptr<XFRowStyle> pNewStyle(new XFRowStyle);
269 *pNewStyle = *pRowStyle;
270 LwpTableLayout* pTableLayout = GetParentTableLayout();
271 if (!pTableLayout)
273 return;
275 std::map<sal_uInt16,LwpRowLayout*> RowsMap = pTableLayout->GetRowsMap();
277 for (sal_uInt16 i=crowid+1; i<nRowMark;i++)
279 std::map<sal_uInt16,LwpRowLayout*>::iterator iter = RowsMap.find(i);
280 if (iter == RowsMap.end())
282 pRowStyle = static_cast<XFRowStyle*>(
283 pXFStyleManager->FindStyle(pTableLayout->GetDefaultRowStyleName()));
285 else
287 pRowStyle = static_cast<XFRowStyle*>(
288 pXFStyleManager->FindStyle(iter->second->GetStyleName()));
290 if (!pRowStyle)
291 throw std::runtime_error("missing RowStyle");
292 fHeight += pRowStyle->GetRowHeight();
295 if (m_nDirection & 0x0030)
297 pNewStyle->SetMinRowHeight(static_cast<float>(fHeight));
299 else
301 pNewStyle->SetRowHeight(static_cast<float>(fHeight));
304 pXFRow->SetStyleName(pXFStyleManager->AddStyle(std::move(pNewStyle)).m_pStyle->GetStyleName());
308 * @short find max merge cell in a given column range
309 * @param nStartCol - start column ID
310 * @param nEndCol - end column ID
312 sal_Int32 LwpRowLayout::FindMarkConnCell(sal_uInt8 nStartCol,sal_uInt8 nEndCol)
314 if (m_ConnCellList.empty())
315 return -1;
317 sal_uInt16 nSpannRows = 1;
318 sal_Int32 nMarkConnCell = -1;
320 for (size_t i=0;i<m_ConnCellList.size();i++)
322 if (m_ConnCellList[i]->GetColID()>=nEndCol)
323 break;
324 if (m_ConnCellList[i]->GetColID()>=nStartCol)
326 if (m_ConnCellList[i]->GetNumrows()>nSpannRows)
328 nSpannRows = m_ConnCellList[i]->GetNumrows();
329 nMarkConnCell = i;
333 return nMarkConnCell;
337 * @short find next merge cell with the same spanned row number with current merge cell
338 * @param nStartCol - start column ID
339 * @param nEndCol - end column ID
341 sal_Int32 LwpRowLayout::FindNextMarkConnCell(sal_uInt16 nMarkConnCell,sal_uInt8 nEndCol)
343 sal_uInt16 nMaxRows = m_ConnCellList[nMarkConnCell]->GetNumrows();
345 for (size_t i=nMarkConnCell+1;i<m_ConnCellList.size();i++)
347 if (m_ConnCellList[i]->GetColID()>=nEndCol)
348 break;
349 if (m_ConnCellList[i]->GetNumrows() == nMaxRows)
351 return i;
354 return -1;
357 * @short get max spanned row numbers in a given column range
358 * @param nStartCol - start column ID
359 * @param nEndCol - end column ID
361 sal_uInt16 LwpRowLayout::GetCurMaxSpannedRows(sal_uInt8 nStartCol,sal_uInt8 nEndCol)
363 sal_Int32 nMarkConnCell = FindMarkConnCell(nStartCol,nEndCol);
364 if (nMarkConnCell == -1)
365 return 1;
366 else
367 return m_ConnCellList[nMarkConnCell]->GetNumrows();
370 * @short convert row with rowlayout,but no merge cells
371 * @param pXFTable - pointer of table
372 * @param nStartCol - start column ID
373 * @param nEndCol - end column ID
375 void LwpRowLayout::ConvertCommonRow(rtl::Reference<XFTable> const & pXFTable, sal_uInt8 nStartCol, sal_uInt8 nEndCol)
377 LwpTableLayout* pTableLayout = GetParentTableLayout();
378 if (!pTableLayout)
379 return;
380 LwpTable* pTable = pTableLayout->GetTable();
381 if (!pTable)
382 return;
384 rtl::Reference<XFRow> xRow(new XFRow);
385 xRow->SetStyleName(m_StyleName);
387 sal_uInt8 nCellStartCol,nCellEndCol;
389 for (sal_uInt16 i = nStartCol; i < nEndCol; i++)
391 // add row to table
392 LwpObjectID *pCellID= &GetChildHead();
393 LwpCellLayout * pCellLayout = dynamic_cast<LwpCellLayout *>(pCellID->obj().get());
394 nCellStartCol = i;//mark the begin position of cell
395 nCellEndCol = i;//mark the end position of cell
396 rtl::Reference<XFCell> xCell;
397 while(pCellLayout)
399 if (pCellLayout->GetColID() == i)
401 if (pCellLayout->GetLayoutType() == LWP_CONNECTED_CELL_LAYOUT)
403 LwpConnectedCellLayout* pConnCell = static_cast<LwpConnectedCellLayout*>(pCellLayout);
404 auto nNumCols = pConnCell->GetNumcols();
405 if (!nNumCols)
406 throw std::runtime_error("loop in conversion");
407 auto nNewEndCol = i + nNumCols - 1;
408 if (nNewEndCol > std::numeric_limits<sal_uInt8>::max())
409 throw std::range_error("column index too large");
410 nCellEndCol = nNewEndCol;
411 i = nCellEndCol;
413 xCell = pCellLayout->DoConvertCell(pTable->GetObjectID(),crowid,i);
414 break;
416 pCellID = &pCellLayout->GetNext();
417 pCellLayout = dynamic_cast<LwpCellLayout *>(pCellID->obj().get());
419 if (!pCellLayout)
421 // if table has default cell layout, use it to ConvertCell
422 // otherwise use blank cell
423 LwpCellLayout * pDefaultCell = pTableLayout->GetDefaultCellLayout();
424 if (pDefaultCell)
426 xCell = pDefaultCell->DoConvertCell(
427 pTable->GetObjectID(),crowid, i);
429 else
431 xCell.set(new XFCell);
434 xRow->AddCell(xCell);
436 pTableLayout->SetCellsMap(crowid, nCellStartCol, crowid, nCellEndCol, xCell.get()); //set to cellsmap
439 pXFTable->AddRow(xRow);
442 * @short collect merge cell info when register row styles
444 void LwpRowLayout::CollectMergeInfo()
446 LwpObjectID *pCellID= &GetChildHead();
447 LwpCellLayout * pCellLayout = dynamic_cast<LwpCellLayout *>(pCellID->obj().get());
449 while(pCellLayout)
451 if (pCellLayout->GetLayoutType() == LWP_CONNECTED_CELL_LAYOUT)
453 LwpConnectedCellLayout* pConnCell = static_cast<LwpConnectedCellLayout*>(pCellLayout);
454 m_ConnCellList.push_back(pConnCell);
456 pCellID = &pCellLayout->GetNext();
457 pCellLayout = dynamic_cast<LwpCellLayout *>(pCellID->obj().get());
461 * @short split merge cells in this row
462 * @param nEffectRows - max spanned number of previous row
464 void LwpRowLayout::SetCellSplit(sal_uInt16 nEffectRows)
466 for (LwpConnectedCellLayout* pConnCell : m_ConnCellList)
468 sal_uInt16 nRowSpan;
469 if (o3tl::checked_add(pConnCell->GetRowID(), pConnCell->GetNumrows(), nRowSpan))
470 throw std::range_error("bad span");
471 if (nRowSpan > nEffectRows)
473 if (o3tl::checked_sub(nEffectRows, pConnCell->GetRowID(), nRowSpan))
474 throw std::range_error("bad span");
475 pConnCell->SetNumrows(nRowSpan);
480 * @short check if the row has merge cell
482 bool LwpRowLayout::GetMergeCellFlag() const
484 return !m_ConnCellList.empty();
487 LwpRowHeadingLayout::LwpRowHeadingLayout(LwpObjectHeader const &objHdr, LwpSvStream* pStrm)
488 : LwpRowLayout(objHdr, pStrm)
491 LwpRowHeadingLayout::~LwpRowHeadingLayout()
493 void LwpRowHeadingLayout::Read()
495 LwpRowLayout::Read();
497 cRowLayout.ReadIndexed(m_pObjStrm.get());
498 m_pObjStrm->SkipExtra();
501 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */