1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
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
{
40 using namespace ::com::sun::star
;
41 using namespace ::std
;
44 DomainMapperTableManager::DomainMapperTableManager(bool bOOXML
) :
50 m_nCellBorderIndex(0),
55 m_aTmpTableProperties(),
56 m_bPushCurrentWidth(false),
57 m_bRowSizeTypeInserted(false),
58 m_bTableSizeTypeInserted(false),
61 m_pTablePropsHandler( new TablePropertiesHandler( bOOXML
) )
63 m_pTablePropsHandler
->SetTableManager( this );
65 #ifdef DEBUG_DOMAINMAPPER
67 setTagLogger(dmapper_logger
);
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();
88 bool bRet
= DomainMapperTableManager_Base_t::sprm(rSprm
);
91 bRet
= m_pTablePropsHandler
->sprm( rSprm
);
97 sal_uInt32 nSprmId
= rSprm
.getId();
98 Value::Pointer_t pValue
= rSprm
.getValue();
99 sal_Int32 nIntValue
= ((pValue
.get() != NULL
) ? pValue
->getInt() : 0);
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() );
120 m_nTableWidth
= pMeasureHandler
->getMeasureValue();
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;
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.)
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
)
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).
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
);
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
);
180 insertTableProps(pPropMap
);
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 )
191 TablePropertyMapPtr
pPropMap( new TablePropertyMap
);
192 pPropMap
->Insert( PROP_HEADER_ROW_COUNT
, false, uno::makeAny( m_nHeaderRepeat
));
193 insertTableProps(pPropMap
);
196 m_nHeaderRepeat
= -1;
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
);
211 m_nTableWidth
= pTDefTableHandler
->getTableWidth();
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
);
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
;
242 case 0xd632 : //sprmTNewSpacing
243 case 0xd634 : //sprmTNewSpacing
244 //TODO: sprms contain default (TNew) and actual border spacing of cells - not resolvable yet
246 case 0xd613: //sprmTGridLineProps
247 // TODO: needs a handler
254 rtf:LINEPROPSHORIZONTAL
255 rtf:LINEPROPSVERTICAL
262 case 0x740a : //sprmTTlp
263 //TODO: Table look specifier
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
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
);
282 case NS_ooxml::LN_CT_TblGridBase_gridCol
:
285 getCurrentGrid()->clear();
287 getCurrentGrid()->push_back( ConversionHelper::convertTwipToMM100( nIntValue
) );
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
);
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
);
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();
313 m_nGridSpan
= nIntValue
;
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
);
323 case NS_ooxml::LN_CT_TcPrBase_textDirection
:
325 TablePropertyMapPtr
pPropMap( new TablePropertyMap
);
326 bool bInsertCellProps
= true;
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
);
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
);
350 pPropMap
->Insert( PROP_FRM_DIRECTION
, false, uno::makeAny( text::WritingMode2::LR_TB
));
353 pPropMap
->Insert( PROP_FRM_DIRECTION
, false, uno::makeAny( text::WritingMode2::TB_RL
));
356 case NS_ooxml::LN_Value_ST_TextDirection_tbLrV
:
358 // Ignore - we can't handle these
359 bInsertCellProps
= false;
362 if ( bInsertCellProps
)
363 cellProps( pPropMap
);
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
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));
379 getCurrentCellWidths()->push_back(pMeasureHandler
->getMeasureValue());
380 if (getTableDepthDifference() > 0)
381 m_bPushCurrentWidth
= true;
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
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();
400 m_aTmpPosition
.pop_back();
401 pHandler
.reset( new TablePositionHandler
);
402 m_aTmpPosition
.push_back( pHandler
);
404 pProperties
->resolve(*m_aTmpPosition
.back());
408 case NS_ooxml::LN_CT_TrPrBase_gridBefore
:
409 m_nGridBefore
= nIntValue
;
411 case NS_ooxml::LN_CT_TrPrBase_gridAfter
:
412 m_nGridAfter
= nIntValue
;
417 #ifdef DEBUG_DOMAINMAPPER
418 dmapper_logger
->element("unhandled");
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();
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 );
476 m_nMaxFixedWidth
= 0;
478 // And push it back to the right level.
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.
495 m_aCellWidths
.back()->push_back(*oCurrentWidth
);
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();
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");
528 getCurrentSpans()->push_back(m_nGridSpan
);
534 void DomainMapperTableManager::endOfRowAction()
536 #ifdef DEBUG_DOMAINMAPPER
537 dmapper_logger
->startElement("endOfRowAction");
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 );
559 setKeepUnfinishedRow( false );
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");
586 while( aCellIter
!= pTableGrid
->end() )
588 #ifdef DEBUG_DOMAINMAPPER
589 dmapper_logger
->startElement("col");
590 dmapper_logger
->attribute("width", *aCellIter
);
591 dmapper_logger
->endElement();
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();
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();
631 dmapper_logger
->endElement();
634 //calculate number of used grids - it has to match the size of m_aTableGrid
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
++];
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
;
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();
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();
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
;
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();
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
);
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();
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
)
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
);
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(
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: */