Bump version to 4.1-6
[LibreOffice.git] / writerfilter / source / dmapper / DomainMapperTableManager.cxx
blobc2c0728b4815f1edec51e521bf40d08e54b175ea
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
19 #include <boost/optional.hpp>
20 #include <DomainMapperTableManager.hxx>
21 #include <resourcemodel/WW8ResourceModel.hxx>
22 #include <BorderHandler.hxx>
23 #include <CellColorHandler.hxx>
24 #include <CellMarginHandler.hxx>
25 #include <ConversionHelper.hxx>
26 #include <MeasureHandler.hxx>
27 #include <TDefTableHandler.hxx>
28 #include <com/sun/star/text/HoriOrientation.hpp>
29 #include <com/sun/star/text/SizeType.hpp>
30 #include <com/sun/star/text/TableColumnSeparator.hpp>
31 #include <com/sun/star/text/VertOrientation.hpp>
32 #include <com/sun/star/text/WritingMode2.hpp>
33 #include <ooxml/resourceids.hxx>
34 #include <doctok/sprmids.hxx>
35 #include <dmapperLoggers.hxx>
37 namespace writerfilter {
38 namespace dmapper {
40 using namespace ::com::sun::star;
41 using namespace ::std;
44 DomainMapperTableManager::DomainMapperTableManager(bool bOOXML) :
45 m_nRow(0),
46 m_nCell(),
47 m_nGridSpan(1),
48 m_nGridBefore(0),
49 m_nGridAfter(0),
50 m_nCellBorderIndex(0),
51 m_nHeaderRepeat(0),
52 m_nTableWidth(0),
53 m_bOOXML( bOOXML ),
54 m_aTmpPosition(),
55 m_aTmpTableProperties(),
56 m_bPushCurrentWidth(false),
57 m_bRowSizeTypeInserted(false),
58 m_bTableSizeTypeInserted(false),
59 m_nLayoutType(0),
60 m_nMaxFixedWidth(0),
61 m_pTablePropsHandler( new TablePropertiesHandler( bOOXML ) )
63 m_pTablePropsHandler->SetTableManager( this );
65 #ifdef DEBUG_DOMAINMAPPER
66 #ifdef DEBUG_TABLE
67 setTagLogger(dmapper_logger);
68 #endif
69 #endif
73 DomainMapperTableManager::~DomainMapperTableManager()
75 if ( m_pTablePropsHandler )
76 delete m_pTablePropsHandler, m_pTablePropsHandler = NULL;
80 bool DomainMapperTableManager::sprm(Sprm & rSprm)
82 #ifdef DEBUG_DOMAINMAPPER
83 dmapper_logger->startElement("tablemanager.sprm");
84 string sSprm = rSprm.toString();
85 dmapper_logger->chars(sSprm);
86 dmapper_logger->endElement();
87 #endif
88 bool bRet = DomainMapperTableManager_Base_t::sprm(rSprm);
89 if( !bRet )
91 bRet = m_pTablePropsHandler->sprm( rSprm );
94 if ( !bRet )
96 bRet = true;
97 sal_uInt32 nSprmId = rSprm.getId();
98 Value::Pointer_t pValue = rSprm.getValue();
99 sal_Int32 nIntValue = ((pValue.get() != NULL) ? pValue->getInt() : 0);
100 switch ( nSprmId )
102 case 0xf661: //sprmTTRLeft left table indent
103 case 0xf614: // sprmTTPreferredWidth - preferred table width
104 case NS_ooxml::LN_CT_TblPrBase_tblW: //90722;
105 case NS_ooxml::LN_CT_TblPrBase_tblInd: //90725
107 //contains unit and value
108 writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
109 if( pProperties.get())
110 { //contains attributes x2902 (LN_unit) and x17e2 (LN_trleft)
111 MeasureHandlerPtr pMeasureHandler( new MeasureHandler );
112 pProperties->resolve(*pMeasureHandler);
113 TablePropertyMapPtr pPropMap( new TablePropertyMap );
114 if( nSprmId == 0xf661 || nSprmId == sal_uInt32(NS_ooxml::LN_CT_TblPrBase_tblInd ))
116 pPropMap->setValue( TablePropertyMap::LEFT_MARGIN, pMeasureHandler->getMeasureValue() );
118 else
120 m_nTableWidth = pMeasureHandler->getMeasureValue();
121 if( m_nTableWidth )
123 pPropMap->setValue( TablePropertyMap::TABLE_WIDTH_TYPE, text::SizeType::FIX );
124 pPropMap->setValue( TablePropertyMap::TABLE_WIDTH, m_nTableWidth );
126 else if( sal::static_int_cast<Id>(pMeasureHandler->getUnit()) == NS_ooxml::LN_Value_ST_TblWidth_pct )
128 sal_Int32 nPercent = pMeasureHandler->getValue() / 50;
129 if(nPercent > 100)
130 nPercent = 100;
131 pPropMap->setValue( TablePropertyMap::TABLE_WIDTH_TYPE, text::SizeType::VARIABLE );
132 pPropMap->setValue( TablePropertyMap::TABLE_WIDTH, nPercent );
134 else if( sal::static_int_cast<Id>(pMeasureHandler->getUnit()) == NS_ooxml::LN_Value_ST_TblWidth_auto )
137 This attribute specifies the width type of table. This is used as part of the table layout
138 algorithm specified by the tblLayout element.(See 17.4.64 and 17.4.65 of the ISO/IEC 29500-1:2011.)
139 If this valus is 'auto', the table layout has to uses the preferred widths on the table items to generate
140 the final sizing of the table, but then must use the contents of each cell to determine final column widths.
141 (See 17.18.87 of the ISO/IEC 29500-1:2011.)
143 bool bFixed = true;
144 sal_Int32 nRowFixedWidth = 0;
145 IntVectorPtr pCellWidths = getCurrentCellWidths();
146 // Step 1. Check whether all cells hava fixed widths in the given row of table.
147 for (std::vector<sal_Int32>::const_iterator aValIter = pCellWidths->begin(); aValIter != pCellWidths->end(); ++aValIter)
149 if (*aValIter == -1)
151 bFixed = false;
152 break;
154 // Sum the width of cells to find the total width of given row
155 nRowFixedWidth += (*aValIter);
158 // Check whether the total width of given row is compared with the maximum value of rows (m_nMaxFixedWidth).
159 if (bFixed )
161 // Check if total width
162 if (m_nMaxFixedWidth < nRowFixedWidth)
163 m_nMaxFixedWidth = nRowFixedWidth;
165 pPropMap->setValue( TablePropertyMap::TABLE_WIDTH_TYPE, text::SizeType::FIX );
166 pPropMap->setValue( TablePropertyMap::TABLE_WIDTH, m_nMaxFixedWidth );
168 else
170 // Set the width type of table with 'Auto' and set the width value to 100(%)
171 pPropMap->setValue( TablePropertyMap::TABLE_WIDTH_TYPE, text::SizeType::VARIABLE );
172 pPropMap->setValue( TablePropertyMap::TABLE_WIDTH, 100 );
175 m_bTableSizeTypeInserted = true;
177 #ifdef DEBUG_DOMAINMAPPER
178 pPropMap->dumpXml( dmapper_logger );
179 #endif
180 insertTableProps(pPropMap);
183 break;
184 case 0x3404:// sprmTTableHeader
185 case NS_ooxml::LN_CT_TrPrBase_tblHeader: //90704
186 // if nIntValue == 1 then the row is a repeated header line
187 // to prevent later rows from increasing the repeating m_nHeaderRepeat is set to NULL when repeating stops
188 if( nIntValue > 0 && m_nHeaderRepeat >= 0 )
190 ++m_nHeaderRepeat;
191 TablePropertyMapPtr pPropMap( new TablePropertyMap );
192 pPropMap->Insert( PROP_HEADER_ROW_COUNT, false, uno::makeAny( m_nHeaderRepeat ));
193 insertTableProps(pPropMap);
195 else
196 m_nHeaderRepeat = -1;
197 break;
198 case 0xd608: // TDefTable
200 writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
201 if( pProperties.get())
203 TDefTableHandlerPtr pTDefTableHandler( new TDefTableHandler(m_bOOXML) );
204 pProperties->resolve( *pTDefTableHandler );
206 TablePropertyMapPtr pRowPropMap( new TablePropertyMap );
207 pRowPropMap->InsertProps(pTDefTableHandler->getRowProperties());
208 insertRowProps( pRowPropMap );
209 if( !m_nTableWidth )
211 m_nTableWidth= pTDefTableHandler->getTableWidth();
212 if( m_nTableWidth )
214 TablePropertyMapPtr pPropMap( new TablePropertyMap );
215 pPropMap->setValue( TablePropertyMap::TABLE_WIDTH, m_nTableWidth );
216 insertTableProps(pPropMap);
219 for( size_t nCell = 0; nCell < pTDefTableHandler->getCellCount(); ++nCell )
221 TablePropertyMapPtr pCellPropMap( new TablePropertyMap );
222 pTDefTableHandler->fillCellProperties( nCell, pCellPropMap );
223 cellPropsByCell( nCell, pCellPropMap );
227 break;
228 case 0xD605: // sprmTTableBorders
230 writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
231 if( pProperties.get())
233 BorderHandlerPtr pBorderHandler( new BorderHandler(m_bOOXML) );
234 pProperties->resolve(*pBorderHandler);
235 TablePropertyMapPtr pCellPropMap( new TablePropertyMap() );
236 pCellPropMap->InsertProps(pBorderHandler->getProperties());
237 cellPropsByCell( m_nCellBorderIndex, pCellPropMap );
238 ++m_nCellBorderIndex;
241 break;
242 case 0xd632 : //sprmTNewSpacing
243 case 0xd634 : //sprmTNewSpacing
244 //TODO: sprms contain default (TNew) and actual border spacing of cells - not resolvable yet
245 break;
246 case 0xd613: //sprmTGridLineProps
247 // TODO: needs a handler
248 /*contains:
249 GridLineProps">
250 rtf:LINEPROPSTOP
251 rtf:LINEPROPSLEFT
252 rtf:LINEPROPSBOTTOM
253 rtf:LINEPROPSRIGHT
254 rtf:LINEPROPSHORIZONTAL
255 rtf:LINEPROPSVERTICAL
256 rtf:LINECOLOR
257 rtf:LINEWIDTH
258 rtf:LINETYPE
261 break;
262 case 0x740a : //sprmTTlp
263 //TODO: Table look specifier
264 break;
265 case 0x6816 : //unknown
266 case 0x3466 : //unknown
267 case 0x3615 : //unknown
268 case 0x646b : //unknown - expandable sprm - see ww8scan.cxx
269 case 0x7479 : //unknown
270 case 0xf617 : //unknown
271 case 0xf618 : //unknown
272 bRet = false;
273 break;
274 case NS_ooxml::LN_CT_TblPrBase_tblStyle: //table style name
276 m_sTableStyleName = pValue->getString();
277 TablePropertyMapPtr pPropMap( new TablePropertyMap );
278 pPropMap->Insert( META_PROP_TABLE_STYLE_NAME, false, uno::makeAny( m_sTableStyleName ));
279 insertTableProps(pPropMap);
281 break;
282 case NS_ooxml::LN_CT_TblGridBase_gridCol:
284 if (nIntValue == -1)
285 getCurrentGrid()->clear();
286 else
287 getCurrentGrid()->push_back( ConversionHelper::convertTwipToMM100( nIntValue ) );
289 break;
290 case NS_ooxml::LN_CT_TcPrBase_vMerge : //vertical merge
292 // values can be: LN_Value_ST_Merge_restart, LN_Value_ST_Merge_continue, in reality the second one is a 0
293 TablePropertyMapPtr pMergeProps( new TablePropertyMap );
294 pMergeProps->Insert( PROP_VERTICAL_MERGE, false, uno::makeAny( bool( sal::static_int_cast<Id>(nIntValue) == NS_ooxml::LN_Value_ST_Merge_restart )) );
295 cellProps( pMergeProps);
297 break;
298 case NS_ooxml::LN_CT_TcPrBase_hMerge:
300 // values can be: LN_Value_ST_Merge_restart, LN_Value_ST_Merge_continue, in reality the second one is a 0
301 TablePropertyMapPtr pMergeProps(new TablePropertyMap());
302 pMergeProps->Insert(PROP_HORIZONTAL_MERGE, false, uno::makeAny(bool(sal::static_int_cast<Id>(nIntValue) == NS_ooxml::LN_Value_ST_Merge_restart)));
303 cellProps(pMergeProps);
305 break;
306 case NS_ooxml::LN_CT_TcPrBase_gridSpan: //number of grid positions spanned by this cell
308 #ifdef DEBUG_DOMAINMAPPER
309 dmapper_logger->startElement("tablemanager.GridSpan");
310 dmapper_logger->attribute("gridSpan", nIntValue);
311 dmapper_logger->endElement();
312 #endif
313 m_nGridSpan = nIntValue;
315 break;
316 case NS_ooxml::LN_CT_TblPrBase_tblLook:
318 TablePropertyMapPtr pPropMap( new TablePropertyMap );
319 pPropMap->Insert( PROP_TBL_LOOK, false, uno::makeAny( nIntValue ));
320 insertTableProps(pPropMap);
322 break;
323 case NS_ooxml::LN_CT_TcPrBase_textDirection:
325 TablePropertyMapPtr pPropMap( new TablePropertyMap );
326 bool bInsertCellProps = true;
327 switch ( nIntValue )
329 case 1: // tbRl
330 // Binary filter takes BiDirection into account ( but I have no idea about that here )
331 // or even what it is. But... here's where to handle it if it becomes an issue
332 pPropMap->Insert( PROP_FRM_DIRECTION, false, uno::makeAny( text::WritingMode2::TB_RL ));
333 SAL_INFO( "writerfilter", "Have inserted textDirection " << nIntValue );
334 break;
335 case 3: // btLr
337 // We have to fake this text direction
338 pPropMap->Insert( PROP_FRM_DIRECTION, false, uno::makeAny( text::WritingMode2::LR_TB ));
339 pPropMap->Insert( PROP_CHAR_ROTATION, false, uno::makeAny( sal_Int16( 900 ) ));
340 SAL_INFO( "writerfilter", "Have inserted textDirection " << nIntValue );
342 // We're faking a text direction, so don't allow multiple lines.
343 TablePropertyMapPtr pRowPropMap( new TablePropertyMap );
344 pRowPropMap->Insert(PROP_SIZE_TYPE, false, uno::makeAny(text::SizeType::FIX));
345 m_bRowSizeTypeInserted = true;
346 insertRowProps(pRowPropMap);
348 break;
349 case 4: // lrTbV
350 pPropMap->Insert( PROP_FRM_DIRECTION, false, uno::makeAny( text::WritingMode2::LR_TB ));
351 break;
352 case 5: // tbRlV
353 pPropMap->Insert( PROP_FRM_DIRECTION, false, uno::makeAny( text::WritingMode2::TB_RL ));
354 break;
355 case 0: // lrTb
356 case NS_ooxml::LN_Value_ST_TextDirection_tbLrV:
357 default:
358 // Ignore - we can't handle these
359 bInsertCellProps = false;
360 break;
362 if ( bInsertCellProps )
363 cellProps( pPropMap );
364 break;
366 case NS_ooxml::LN_CT_TcPrBase_tcW:
368 // Contains unit and value, but unit is not interesting for
369 // us, later we'll just distribute these values in a
370 // 0..10000 scale.
371 writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
372 if( pProperties.get())
374 MeasureHandlerPtr pMeasureHandler(new MeasureHandler());
375 pProperties->resolve(*pMeasureHandler);
376 if (sal::static_int_cast<Id>(pMeasureHandler->getUnit()) == NS_ooxml::LN_Value_ST_TblWidth_auto)
377 getCurrentCellWidths()->push_back(sal_Int32(-1));
378 else
379 getCurrentCellWidths()->push_back(pMeasureHandler->getMeasureValue());
380 if (getTableDepthDifference() > 0)
381 m_bPushCurrentWidth = true;
384 break;
385 case NS_ooxml::LN_CT_TrPrBase_cnfStyle:
386 break; // the cnfStyle doesn't matter, instead the tblLook property is used to specify conditional styles that are to be used
387 case NS_ooxml::LN_CT_PPrBase_cnfStyle:
388 // TODO cnfStyle on a paragraph
389 break;
390 case NS_ooxml::LN_CT_TcPrBase_cnfStyle:
391 break; // the cnfStyle doesn't matter, instead the tblLook property is used to specify conditional styles that are to be used
392 case NS_ooxml::LN_CT_TblPrBase_tblpPr:
394 writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
395 if (pProperties.get())
397 TablePositionHandlerPtr pHandler = m_aTmpPosition.back();
398 if ( !pHandler )
400 m_aTmpPosition.pop_back();
401 pHandler.reset( new TablePositionHandler );
402 m_aTmpPosition.push_back( pHandler );
404 pProperties->resolve(*m_aTmpPosition.back());
407 break;
408 case NS_ooxml::LN_CT_TrPrBase_gridBefore:
409 m_nGridBefore = nIntValue;
410 break;
411 case NS_ooxml::LN_CT_TrPrBase_gridAfter:
412 m_nGridAfter = nIntValue;
413 break;
414 default:
415 bRet = false;
417 #ifdef DEBUG_DOMAINMAPPER
418 dmapper_logger->element("unhandled");
419 #endif
422 return bRet;
425 boost::shared_ptr< vector<sal_Int32> > DomainMapperTableManager::getCurrentGrid( )
427 return m_aTableGrid.back( );
430 boost::shared_ptr< vector< sal_Int32 > > DomainMapperTableManager::getCurrentSpans( )
432 return m_aGridSpans.back( );
435 boost::shared_ptr< vector< sal_Int32 > > DomainMapperTableManager::getCurrentCellWidths( )
437 return m_aCellWidths.back( );
440 const uno::Sequence<beans::PropertyValue> DomainMapperTableManager::getCurrentTablePosition( )
442 if ( !m_aTablePositions.empty( ) && m_aTablePositions.back() )
443 return m_aTablePositions.back( )->getTablePosition();
444 else
445 return uno::Sequence< beans::PropertyValue >( 0 );
448 void DomainMapperTableManager::startLevel( )
450 DomainMapperTableManager_Base_t::startLevel( );
452 // If requested, pop the value that was pushed too early.
453 boost::optional<sal_Int32> oCurrentWidth;
454 if (m_bPushCurrentWidth && !m_aCellWidths.empty() && !m_aCellWidths.back()->empty())
456 oCurrentWidth.reset(m_aCellWidths.back()->back());
457 m_aCellWidths.back()->pop_back();
460 IntVectorPtr pNewGrid( new vector<sal_Int32> );
461 IntVectorPtr pNewSpans( new vector<sal_Int32> );
462 IntVectorPtr pNewCellWidths( new vector<sal_Int32> );
463 TablePositionHandlerPtr pNewPositionHandler;
464 m_aTableGrid.push_back( pNewGrid );
465 m_aGridSpans.push_back( pNewSpans );
466 m_aCellWidths.push_back( pNewCellWidths );
467 m_aTablePositions.push_back( pNewPositionHandler );
469 TablePositionHandlerPtr pTmpPosition;
470 TablePropertyMapPtr pTmpProperties( new TablePropertyMap( ) );
471 m_aTmpPosition.push_back( pTmpPosition );
472 m_aTmpTableProperties.push_back( pTmpProperties );
473 m_nCell.push_back( 0 );
474 m_nTableWidth = 0;
475 m_nLayoutType = 0;
476 m_nMaxFixedWidth = 0;
478 // And push it back to the right level.
479 if (oCurrentWidth)
480 m_aCellWidths.back()->push_back(*oCurrentWidth);
483 void DomainMapperTableManager::endLevel( )
485 m_aTableGrid.pop_back( );
486 m_aGridSpans.pop_back( );
488 // Do the same trick as in startLevel(): pop the value that was pushed too early.
489 boost::optional<sal_Int32> oCurrentWidth;
490 if (m_bPushCurrentWidth && !m_aCellWidths.empty() && !m_aCellWidths.back()->empty())
491 oCurrentWidth.reset(m_aCellWidths.back()->back());
492 m_aCellWidths.pop_back( );
493 // And push it back to the right level.
494 if (oCurrentWidth)
495 m_aCellWidths.back()->push_back(*oCurrentWidth);
497 m_nCell.pop_back( );
498 m_nTableWidth = 0;
499 m_nLayoutType = 0;
500 m_nMaxFixedWidth = 0;
502 m_aTmpPosition.pop_back( );
503 m_aTmpTableProperties.pop_back( );
505 DomainMapperTableManager_Base_t::endLevel( );
506 #ifdef DEBUG_DOMAINMAPPER
507 dmapper_logger->startElement("dmappertablemanager.endLevel");
508 PropertyMapPtr pProps = getTableProps();
509 if (pProps.get() != NULL)
510 getTableProps()->dumpXml( dmapper_logger );
512 dmapper_logger->endElement();
513 #endif
515 // Pop back the table position after endLevel as it's used
516 // in the endTable method called in endLevel.
517 m_aTablePositions.pop_back();
522 void DomainMapperTableManager::endOfCellAction()
524 #ifdef DEBUG_DOMAINMAPPER
525 dmapper_logger->element("endOFCellAction");
526 #endif
528 getCurrentSpans()->push_back(m_nGridSpan);
529 m_nGridSpan = 1;
530 ++m_nCell.back( );
534 void DomainMapperTableManager::endOfRowAction()
536 #ifdef DEBUG_DOMAINMAPPER
537 dmapper_logger->startElement("endOfRowAction");
538 #endif
540 // Compare the table position with the previous ones. We may need to split
541 // into two tables if those are different. We surely don't want to do anything
542 // if we don't have any row yet.
543 TablePositionHandlerPtr pTmpPosition = m_aTmpPosition.back();
544 TablePropertyMapPtr pTmpTableProperties = m_aTmpTableProperties.back( );
545 TablePositionHandlerPtr pCurrentPosition = m_aTablePositions.back();
546 bool bSamePosition = ( pTmpPosition == pCurrentPosition ) ||
547 ( pTmpPosition && pCurrentPosition && *pTmpPosition == *pCurrentPosition );
548 if ( !bSamePosition && m_nRow > 0 )
550 // Save the grid infos to have them survive the end/start level
551 IntVectorPtr pTmpTableGrid = m_aTableGrid.back();
552 IntVectorPtr pTmpGridSpans = m_aGridSpans.back();
553 IntVectorPtr pTmpCellWidths = m_aCellWidths.back();
555 // endLevel and startLevel are taking care of the non finished row
556 // to carry it over to the next table
557 setKeepUnfinishedRow( true );
558 endLevel();
559 setKeepUnfinishedRow( false );
560 startLevel();
562 m_aTableGrid.pop_back();
563 m_aGridSpans.pop_back();
564 m_aCellWidths.pop_back();
565 m_aTableGrid.push_back(pTmpTableGrid);
566 m_aGridSpans.push_back(pTmpGridSpans);
567 m_aCellWidths.push_back(pTmpCellWidths);
570 // Push the tmp position now that we compared it
571 m_aTablePositions.pop_back();
572 m_aTablePositions.push_back( pTmpPosition );
573 m_aTmpPosition.back().reset( );
576 IntVectorPtr pTableGrid = getCurrentGrid( );
577 IntVectorPtr pCellWidths = getCurrentCellWidths( );
578 if(!m_nTableWidth && pTableGrid->size())
580 ::std::vector<sal_Int32>::const_iterator aCellIter = pTableGrid->begin();
582 #ifdef DEBUG_DOMAINMAPPER
583 dmapper_logger->startElement("tableWidth");
584 #endif
586 while( aCellIter != pTableGrid->end() )
588 #ifdef DEBUG_DOMAINMAPPER
589 dmapper_logger->startElement("col");
590 dmapper_logger->attribute("width", *aCellIter);
591 dmapper_logger->endElement();
592 #endif
594 m_nTableWidth += *aCellIter++;
597 if (m_nTableWidth > 0 && !m_bTableSizeTypeInserted)
599 TablePropertyMapPtr pPropMap( new TablePropertyMap );
600 pPropMap->setValue( TablePropertyMap::TABLE_WIDTH, m_nTableWidth );
601 insertTableProps(pPropMap);
604 #ifdef DEBUG_DOMAINMAPPER
605 dmapper_logger->endElement();
606 #endif
609 IntVectorPtr pCurrentSpans = getCurrentSpans( );
610 if( pCurrentSpans->size() < m_nCell.back( ) )
612 //fill missing elements with '1'
613 pCurrentSpans->insert( pCurrentSpans->end( ), m_nCell.back( ) - pCurrentSpans->size(), 1 );
616 #ifdef DEBUG_DOMAINMAPPER
617 dmapper_logger->startElement("gridSpans");
619 ::std::vector<sal_Int32>::const_iterator aGridSpanIter = pCurrentSpans->begin();
620 ::std::vector<sal_Int32>::const_iterator aGridSpanIterEnd = pCurrentSpans->end();
622 while (aGridSpanIter != aGridSpanIterEnd)
624 dmapper_logger->startElement("gridSpan");
625 dmapper_logger->attribute("span", *aGridSpanIter);
626 dmapper_logger->endElement();
628 ++aGridSpanIter;
631 dmapper_logger->endElement();
632 #endif
634 //calculate number of used grids - it has to match the size of m_aTableGrid
635 size_t nGrids = 0;
636 ::std::vector<sal_Int32>::const_iterator aGridSpanIter = pCurrentSpans->begin();
637 for( ; aGridSpanIter != pCurrentSpans->end(); ++aGridSpanIter)
638 nGrids += *aGridSpanIter;
640 // sj: the grid is having no units... they is containing only relative values.
641 // a table with a grid of "1:2:1" looks identical as if the table is having
642 // a grid of "20:40:20" and it doesn't have to do something with the tableWidth
643 // -> so we have get the sum of each grid entry for the fullWidthRelative:
644 int nFullWidthRelative = 0;
645 for (unsigned int i = 0 ; i < (*pTableGrid.get()).size(); i++ )
646 nFullWidthRelative += (*pTableGrid.get())[ i ];
648 if( pTableGrid->size() == ( m_nGridBefore + nGrids + m_nGridAfter ) && m_nCell.back( ) > 0 )
650 uno::Sequence< text::TableColumnSeparator > aSeparators( m_nCell.back( ) - 1 );
651 text::TableColumnSeparator* pSeparators = aSeparators.getArray();
652 sal_Int16 nLastRelPos = 0;
653 sal_uInt32 nBorderGridIndex = m_nGridBefore;
655 ::std::vector< sal_Int32 >::const_iterator aSpansIter = pCurrentSpans->begin( );
656 for( sal_uInt32 nBorder = 0; nBorder < m_nCell.back( ) - 1; ++nBorder )
658 double fGridWidth = 0.;
659 for ( sal_Int32 nGridCount = *aSpansIter; nGridCount > 0; --nGridCount )
660 fGridWidth += (*pTableGrid.get())[nBorderGridIndex++];
662 sal_Int16 nRelPos =
663 sal::static_int_cast< sal_Int16 >((fGridWidth * 10000) / nFullWidthRelative);
665 pSeparators[nBorder].Position = nRelPos + nLastRelPos;
666 pSeparators[nBorder].IsVisible = sal_True;
667 nLastRelPos = nLastRelPos + nRelPos;
668 ++aSpansIter;
670 TablePropertyMapPtr pPropMap( new TablePropertyMap );
671 pPropMap->Insert( PROP_TABLE_COLUMN_SEPARATORS, false, uno::makeAny( aSeparators ) );
673 #ifdef DEBUG_DOMAINMAPPER
674 dmapper_logger->startElement("rowProperties");
675 pPropMap->dumpXml( dmapper_logger );
676 dmapper_logger->endElement();
677 #endif
678 insertRowProps(pPropMap);
680 else if (pCellWidths->size() > 0 && m_nLayoutType == NS_ooxml::LN_Value_wordprocessingml_ST_TblLayout_fixed)
682 // If we're here, then the number of cells does not equal to the amount
683 // defined by the grid, even after taking care of
684 // gridSpan/gridBefore/gridAfter. Handle this by ignoring the grid and
685 // providing the separators based on the provided cell widths, as long
686 // as we have a fixed layout.
687 uno::Sequence< text::TableColumnSeparator > aSeparators(pCellWidths->size() - 1);
688 text::TableColumnSeparator* pSeparators = aSeparators.getArray();
689 sal_Int16 nSum = 0;
690 sal_uInt32 nPos = 0;
691 // Avoid divide by zero (if there's no grid, position using cell widths).
692 if( nFullWidthRelative == 0 )
693 for (sal_uInt32 i = 0; i < pCellWidths->size(); ++i)
694 nFullWidthRelative += (*pCellWidths.get())[i];
696 for (sal_uInt32 i = 0; i < pCellWidths->size() - 1; ++i)
698 nSum += (*pCellWidths.get())[i];
699 pSeparators[nPos].Position = (nSum * 10000) / nFullWidthRelative; // Relative position
700 pSeparators[nPos].IsVisible = sal_True;
701 nPos++;
704 TablePropertyMapPtr pPropMap( new TablePropertyMap );
705 pPropMap->Insert( PROP_TABLE_COLUMN_SEPARATORS, false, uno::makeAny( aSeparators ) );
706 #ifdef DEBUG_DOMAINMAPPER
707 dmapper_logger->startElement("rowProperties");
708 pPropMap->dumpXml( dmapper_logger );
709 dmapper_logger->endElement();
710 #endif
711 insertRowProps(pPropMap);
714 // Now that potentially opened table is closed, save the table properties
715 DomainMapperTableManager_Base_t::insertTableProps( pTmpTableProperties );
717 m_aTmpTableProperties.pop_back();
718 TablePropertyMapPtr pEmptyTableProps( new TablePropertyMap() );
719 m_aTmpTableProperties.push_back( pEmptyTableProps );
721 ++m_nRow;
722 m_nCell.back( ) = 0;
723 m_nCellBorderIndex = 0;
724 getCurrentGrid()->clear();
725 pCurrentSpans->clear();
726 pCellWidths->clear();
728 m_nGridBefore = m_nGridAfter = 0;
729 m_bRowSizeTypeInserted = false;
730 m_bTableSizeTypeInserted = false;
732 #ifdef DEBUG_DOMAINMAPPER
733 dmapper_logger->endElement();
734 #endif
738 void DomainMapperTableManager::clearData()
740 m_nRow = m_nCellBorderIndex = m_nHeaderRepeat = m_nTableWidth = m_nLayoutType = 0;
741 m_sTableStyleName = OUString();
742 m_pTableStyleTextProperies.reset();
746 void lcl_CopyTextProperties(PropertyMapPtr pToFill,
747 const StyleSheetEntry* pStyleSheetEntry, StyleSheetTablePtr pStyleSheetTable)
749 if( !pStyleSheetEntry )
750 return;
751 //fill base style properties first, recursively
752 if( !pStyleSheetEntry->sBaseStyleIdentifier.isEmpty())
754 const StyleSheetEntryPtr pParentStyleSheet =
755 pStyleSheetTable->FindStyleSheetByISTD(pStyleSheetEntry->sBaseStyleIdentifier);
756 OSL_ENSURE( pParentStyleSheet, "table style not found" );
757 lcl_CopyTextProperties( pToFill, pParentStyleSheet.get( ), pStyleSheetTable);
760 PropertyMap::const_iterator aPropIter = pStyleSheetEntry->pProperties->begin();
761 while(aPropIter != pStyleSheetEntry->pProperties->end())
763 //copy all text properties form the table style to the current run attributes
764 if( aPropIter->first.bIsTextProperty )
765 pToFill->insert(*aPropIter);
766 ++aPropIter;
769 void DomainMapperTableManager::CopyTextProperties(PropertyMapPtr pContext, StyleSheetTablePtr pStyleSheetTable)
771 if( !m_pTableStyleTextProperies.get())
773 m_pTableStyleTextProperies.reset( new PropertyMap );
774 const StyleSheetEntryPtr pStyleSheetEntry = pStyleSheetTable->FindStyleSheetByISTD(
775 m_sTableStyleName);
776 OSL_ENSURE( pStyleSheetEntry, "table style not found" );
777 lcl_CopyTextProperties(m_pTableStyleTextProperies, pStyleSheetEntry.get( ), pStyleSheetTable);
779 pContext->InsertProps(m_pTableStyleTextProperies);
785 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */