LCOV - code coverage report
Current view: top level - writerfilter/source/dmapper - DomainMapperTableManager.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 337 350 96.3 %
Date: 2015-06-13 12:38:46 Functions: 17 17 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : #include <boost/optional.hpp>
      20             : #include <DomainMapperTableManager.hxx>
      21             : #include <BorderHandler.hxx>
      22             : #include <CellColorHandler.hxx>
      23             : #include <CellMarginHandler.hxx>
      24             : #include <ConversionHelper.hxx>
      25             : #include <MeasureHandler.hxx>
      26             : #include <TDefTableHandler.hxx>
      27             : #include <com/sun/star/text/HoriOrientation.hpp>
      28             : #include <com/sun/star/text/SizeType.hpp>
      29             : #include <com/sun/star/text/TableColumnSeparator.hpp>
      30             : #include <com/sun/star/text/VertOrientation.hpp>
      31             : #include <com/sun/star/text/WritingMode2.hpp>
      32             : #include <o3tl/numeric.hxx>
      33             : #include <ooxml/resourceids.hxx>
      34             : #include <DomainMapper.hxx>
      35             : #include <rtl/math.hxx>
      36             : 
      37             : namespace writerfilter {
      38             : namespace dmapper {
      39             : 
      40             : using namespace ::com::sun::star;
      41             : using namespace ::std;
      42             : 
      43        4834 : DomainMapperTableManager::DomainMapperTableManager() :
      44             :     m_nRow(0),
      45             :     m_nCell(),
      46             :     m_nGridSpan(1),
      47             :     m_nGridBefore(0),
      48             :     m_nGridAfter(0),
      49             :     m_nCellBorderIndex(0),
      50             :     m_nHeaderRepeat(0),
      51             :     m_nTableWidth(0),
      52             :     m_bIsInShape(false),
      53             :     m_aTmpPosition(),
      54             :     m_aTmpTableProperties(),
      55             :     m_bPushCurrentWidth(false),
      56             :     m_bRowSizeTypeInserted(false),
      57             :     m_bHasBtlrCell(false),
      58             :     m_bTableSizeTypeInserted(false),
      59             :     m_nLayoutType(0),
      60             :     m_nMaxFixedWidth(0),
      61        4834 :     m_pTablePropsHandler(new TablePropertiesHandler())
      62             : {
      63        4834 :     m_pTablePropsHandler->SetTableManager( this );
      64        4834 : }
      65             : 
      66             : 
      67       14502 : DomainMapperTableManager::~DomainMapperTableManager()
      68             : {
      69        4834 :     if ( m_pTablePropsHandler )
      70        4834 :         delete m_pTablePropsHandler, m_pTablePropsHandler = nullptr;
      71        9668 : }
      72             : 
      73      394081 : bool DomainMapperTableManager::attribute(Id nName, Value& rValue)
      74             : {
      75      394081 :     bool bRet = true;
      76             : 
      77      394081 :     switch (nName)
      78             :     {
      79             :     case NS_ooxml::LN_CT_TblLook_val:
      80             :     {
      81        2583 :         TablePropertyMapPtr pPropMap(new TablePropertyMap());
      82        2583 :         pPropMap->Insert(PROP_TBL_LOOK, uno::makeAny<sal_Int32>(rValue.getInt()));
      83        2583 :         insertTableProps(pPropMap);
      84        2583 :         m_aTableLook["val"] = uno::makeAny<sal_Int32>(rValue.getInt());
      85             :     }
      86        2583 :     break;
      87             :     case NS_ooxml::LN_CT_TblLook_noVBand:
      88        2140 :         m_aTableLook["noVBand"] = uno::makeAny<sal_Int32>(rValue.getInt());
      89        2140 :     break;
      90             :     case NS_ooxml::LN_CT_TblLook_noHBand:
      91        2140 :         m_aTableLook["noHBand"] = uno::makeAny<sal_Int32>(rValue.getInt());
      92        2140 :     break;
      93             :     case NS_ooxml::LN_CT_TblLook_lastColumn:
      94        2140 :         m_aTableLook["lastColumn"] = uno::makeAny<sal_Int32>(rValue.getInt());
      95        2140 :     break;
      96             :     case NS_ooxml::LN_CT_TblLook_lastRow:
      97        2140 :         m_aTableLook["lastRow"] = uno::makeAny<sal_Int32>(rValue.getInt());
      98        2140 :     break;
      99             :     case NS_ooxml::LN_CT_TblLook_firstColumn:
     100        2140 :         m_aTableLook["firstColumn"] = uno::makeAny<sal_Int32>(rValue.getInt());
     101        2140 :     break;
     102             :     case NS_ooxml::LN_CT_TblLook_firstRow:
     103        2140 :         m_aTableLook["firstRow"] = uno::makeAny<sal_Int32>(rValue.getInt());
     104        2140 :     break;
     105             :     default:
     106      378658 :         bRet = false;
     107             :     }
     108             : 
     109      394081 :     return bRet;
     110             : }
     111             : 
     112        2583 : void DomainMapperTableManager::finishTableLook()
     113             : {
     114        2583 :     TablePropertyMapPtr pPropMap(new TablePropertyMap());
     115        2583 :     pPropMap->Insert(META_PROP_TABLE_LOOK, uno::makeAny(m_aTableLook.getAsConstPropertyValueList()));
     116        2583 :     m_aTableLook.clear();
     117        2583 :     insertTableProps(pPropMap);
     118        2583 : }
     119             : 
     120      487564 : bool DomainMapperTableManager::sprm(Sprm & rSprm)
     121             : {
     122             : #ifdef DEBUG_WRITERFILTER
     123             :     TagLogger::getInstance().startElement("tablemanager.sprm");
     124             :     string sSprm = rSprm.toString();
     125             :     TagLogger::getInstance().chars(sSprm);
     126             :     TagLogger::getInstance().endElement();
     127             : #endif
     128      487564 :     bool bRet = TableManager::sprm(rSprm);
     129      487564 :     if( !bRet )
     130             :     {
     131      435197 :         bRet = m_pTablePropsHandler->sprm( rSprm );
     132             :     }
     133             : 
     134      487564 :     if ( !bRet )
     135             :     {
     136      415107 :         bRet = true;
     137      415107 :         sal_uInt32 nSprmId = rSprm.getId();
     138      415107 :         Value::Pointer_t pValue = rSprm.getValue();
     139      415107 :         sal_Int32 nIntValue = ((pValue.get() != nullptr) ? pValue->getInt() : 0);
     140      415107 :         switch ( nSprmId )
     141             :         {
     142             :             case NS_ooxml::LN_CT_TblPrBase_tblW:
     143             :             case NS_ooxml::LN_CT_TblPrBase_tblInd:
     144             :             {
     145             :                 //contains unit and value
     146        2944 :                 writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
     147        2944 :                 if( pProperties.get())
     148             :                 {
     149        2944 :                     MeasureHandlerPtr pMeasureHandler( new MeasureHandler );
     150        2944 :                     pProperties->resolve(*pMeasureHandler);
     151        5888 :                     TablePropertyMapPtr pPropMap( new TablePropertyMap );
     152        2944 :                     if (nSprmId == sal_uInt32(NS_ooxml::LN_CT_TblPrBase_tblInd))
     153             :                     {
     154           0 :                         pPropMap->setValue( TablePropertyMap::LEFT_MARGIN, pMeasureHandler->getMeasureValue() );
     155             :                     }
     156             :                     else
     157             :                     {
     158        2944 :                         m_nTableWidth = pMeasureHandler->getMeasureValue();
     159        2944 :                         if( m_nTableWidth )
     160             :                         {
     161        1969 :                             pPropMap->setValue( TablePropertyMap::TABLE_WIDTH_TYPE, text::SizeType::FIX );
     162        1969 :                             pPropMap->setValue( TablePropertyMap::TABLE_WIDTH, m_nTableWidth );
     163             :                         }
     164         975 :                         else if( sal::static_int_cast<Id>(pMeasureHandler->getUnit()) == NS_ooxml::LN_Value_ST_TblWidth_pct )
     165             :                         {
     166         171 :                             sal_Int32 nPercent = pMeasureHandler->getValue() / 50;
     167         171 :                             if(nPercent > 100)
     168           1 :                                 nPercent = 100;
     169         171 :                             pPropMap->setValue( TablePropertyMap::TABLE_WIDTH_TYPE, text::SizeType::VARIABLE );
     170         171 :                             pPropMap->setValue( TablePropertyMap::TABLE_WIDTH, nPercent );
     171             :                         }
     172         804 :                         else if( sal::static_int_cast<Id>(pMeasureHandler->getUnit()) == NS_ooxml::LN_Value_ST_TblWidth_auto )
     173             :                         {
     174             :                             /*
     175             :                             This attribute specifies the width type of table. This is used as part of the table layout
     176             :                             algorithm specified by the tblLayout element.(See 17.4.64 and 17.4.65 of the ISO/IEC 29500-1:2011.)
     177             :                             If this value is 'auto', the table layout has to use the preferred widths on the table items to generate
     178             :                             the final sizing of the table, but then must use the contents of each cell to determine final column widths.
     179             :                             (See 17.18.87 of the ISO/IEC 29500-1:2011.)
     180             :                             */
     181         801 :                             bool bFixed = true;
     182         801 :                             sal_Int32 nRowFixedWidth = 0;
     183         801 :                             IntVectorPtr pCellWidths = getCurrentCellWidths();
     184             :                             // Step 1. Check whether all cells have fixed widths in the given row of table.
     185        2877 :                             for (std::vector<sal_Int32>::const_iterator aValIter = pCellWidths->begin(); aValIter != pCellWidths->end(); ++aValIter)
     186             :                             {
     187        2108 :                                 if (*aValIter == -1)
     188             :                                 {
     189          32 :                                     bFixed = false;
     190          32 :                                     break;
     191             :                                 }
     192             :                                 // Sum the width of cells to find the total width of given row
     193        2076 :                                 nRowFixedWidth += (*aValIter);
     194             :                             }
     195             : 
     196             :                             // Check whether the total width of given row is compared with the maximum value of rows (m_nMaxFixedWidth).
     197         801 :                             if (!bFixed)
     198             :                             {
     199             :                                 // Set the width type of table with 'Auto' and set the width value to 100(%)
     200          32 :                                 pPropMap->setValue( TablePropertyMap::TABLE_WIDTH_TYPE, text::SizeType::VARIABLE );
     201          32 :                                 pPropMap->setValue( TablePropertyMap::TABLE_WIDTH, 0 );
     202         801 :                             }
     203             :                         }
     204        2944 :                         m_bTableSizeTypeInserted = true;
     205             :                     }
     206             : #ifdef DEBUG_WRITERFILTER
     207             :                     pPropMap->dumpXml();
     208             : #endif
     209        5888 :                     insertTableProps(pPropMap);
     210        2944 :                 }
     211             :             }
     212        2944 :             break;
     213             :             case NS_ooxml::LN_CT_TrPrBase_tblHeader:
     214             :                 // if nIntValue == 1 then the row is a repeated header line
     215             :                 // to prevent later rows from increasing the repeating m_nHeaderRepeat is set to NULL when repeating stops
     216          99 :                 if( nIntValue > 0 && m_nHeaderRepeat >= 0 )
     217             :                 {
     218          99 :                     ++m_nHeaderRepeat;
     219          99 :                     TablePropertyMapPtr pPropMap( new TablePropertyMap );
     220          99 :                     pPropMap->Insert( PROP_HEADER_ROW_COUNT, uno::makeAny( m_nHeaderRepeat ));
     221          99 :                     insertTableProps(pPropMap);
     222             :                 }
     223             :                 else
     224           0 :                     m_nHeaderRepeat = -1;
     225          99 :                 if (nIntValue)
     226             :                 {
     227             :                     // Store the info that this is a header, we'll need that when we apply table styles.
     228          99 :                     TablePropertyMapPtr pPropMap( new TablePropertyMap );
     229          99 :                     pPropMap->Insert( PROP_TBL_HEADER, uno::makeAny(nIntValue));
     230          99 :                     insertRowProps(pPropMap);
     231             :                 }
     232          99 :             break;
     233             :             case NS_ooxml::LN_CT_TblPrBase_tblStyle: //table style name
     234             :             {
     235        1412 :                 m_sTableStyleName = pValue->getString();
     236        1412 :                 TablePropertyMapPtr pPropMap( new TablePropertyMap );
     237        1412 :                 pPropMap->Insert( META_PROP_TABLE_STYLE_NAME, uno::makeAny( m_sTableStyleName ));
     238        1412 :                 insertTableProps(pPropMap);
     239             :             }
     240        1412 :             break;
     241             :             case NS_ooxml::LN_CT_TblGridBase_gridCol:
     242             :             {
     243        8925 :                 if (nIntValue == -1)
     244         135 :                     getCurrentGrid()->clear();
     245             :                 else
     246        8790 :                     getCurrentGrid()->push_back( ConversionHelper::convertTwipToMM100( nIntValue ) );
     247             :             }
     248        8925 :             break;
     249             :             case NS_ooxml::LN_CT_TcPrBase_vMerge : //vertical merge
     250             :             {
     251             :                 // values can be: LN_Value_ST_Merge_restart, LN_Value_ST_Merge_continue, in reality the second one is a 0
     252         145 :                 TablePropertyMapPtr pMergeProps( new TablePropertyMap );
     253         145 :                 pMergeProps->Insert( PROP_VERTICAL_MERGE, uno::makeAny( bool( sal::static_int_cast<Id>(nIntValue) == NS_ooxml::LN_Value_ST_Merge_restart )) );
     254         145 :                 cellProps( pMergeProps);
     255             :             }
     256         145 :             break;
     257             :             case NS_ooxml::LN_CT_TcPrBase_hMerge:
     258             :             {
     259             :                 // values can be: LN_Value_ST_Merge_restart, LN_Value_ST_Merge_continue, in reality the second one is a 0
     260           4 :                 TablePropertyMapPtr pMergeProps(new TablePropertyMap());
     261           4 :                 pMergeProps->Insert(PROP_HORIZONTAL_MERGE, uno::makeAny(bool(sal::static_int_cast<Id>(nIntValue) == NS_ooxml::LN_Value_ST_Merge_restart)));
     262           4 :                 cellProps(pMergeProps);
     263             :             }
     264           4 :             break;
     265             :             case NS_ooxml::LN_CT_TcPrBase_gridSpan: //number of grid positions spanned by this cell
     266             :             {
     267             : #ifdef DEBUG_WRITERFILTER
     268             :                 TagLogger::getInstance().startElement("tablemanager.GridSpan");
     269             :                 TagLogger::getInstance().attribute("gridSpan", nIntValue);
     270             :                 TagLogger::getInstance().endElement();
     271             : #endif
     272         290 :                 m_nGridSpan = nIntValue;
     273             :             }
     274         290 :             break;
     275             :             case NS_ooxml::LN_CT_TcPrBase_textDirection:
     276             :             {
     277         178 :                 TablePropertyMapPtr pPropMap( new TablePropertyMap );
     278             : 
     279             :                 // Remember the cell direction, so later in
     280             :                 // DomainMapperTableHandler::endTableGetCellProperties() can we
     281             :                 // handle the combination of the cell direction and paragraph
     282             :                 // alignment as necessary.
     283         178 :                 pPropMap->Insert(PROP_CELL_DIRECTION, uno::Any(sal_Int32(nIntValue)));
     284             : 
     285         178 :                 bool bInsertCellProps = true;
     286         178 :                 switch ( nIntValue )
     287             :                 {
     288             :                     case NS_ooxml::LN_Value_ST_TextDirection_tbRl:
     289             :                     // Binary filter takes BiDirection into account ( but I have no idea about that here )
     290             :                     // or even what it is. But... here's where to handle it if it becomes an issue
     291           2 :                         pPropMap->Insert( PROP_FRM_DIRECTION, uno::makeAny( text::WritingMode2::TB_RL ));
     292             :                         SAL_INFO( "writerfilter", "Have inserted textDirection " << nIntValue );
     293           2 :                         break;
     294             :                     case NS_ooxml::LN_Value_ST_TextDirection_btLr:
     295             :                         {
     296             :                         // We have to fake this text direction
     297          32 :                          pPropMap->Insert( PROP_FRM_DIRECTION, uno::makeAny( text::WritingMode2::LR_TB ));
     298          32 :                          pPropMap->Insert( PROP_CHAR_ROTATION, uno::makeAny( sal_Int16( 900 ) ));
     299             :                         SAL_INFO( "writerfilter", "Have inserted textDirection " << nIntValue );
     300             : 
     301             :                         // We're faking a text direction, so don't allow multiple lines.
     302          32 :                         if (!getCellProps() || !getCellProps()->isSet(PROP_VERTICAL_MERGE))
     303             :                         {
     304             :                             // Though in case there will be a vertical merge, don't do this, it hides text that is supposed to be visible.
     305          12 :                             m_bRowSizeTypeInserted = true;
     306             :                         }
     307          32 :                         m_bHasBtlrCell = true;
     308             :                         }
     309          32 :                         break;
     310             :                     case NS_ooxml::LN_Value_ST_TextDirection_lrTbV:
     311           0 :                         pPropMap->Insert( PROP_FRM_DIRECTION, uno::makeAny( text::WritingMode2::LR_TB ));
     312           0 :                         break;
     313             :                     case NS_ooxml::LN_Value_ST_TextDirection_tbRlV:
     314           0 :                         pPropMap->Insert( PROP_FRM_DIRECTION, uno::makeAny( text::WritingMode2::TB_RL ));
     315           0 :                         break;
     316             :                     case NS_ooxml::LN_Value_ST_TextDirection_lrTb:
     317             :                     case NS_ooxml::LN_Value_ST_TextDirection_tbLrV:
     318             :                     default:
     319             :                        // Ignore - we can't handle these
     320         144 :                        bInsertCellProps = false;
     321         144 :                        break;
     322             :                 }
     323         178 :                 if ( bInsertCellProps )
     324          34 :                     cellProps( pPropMap );
     325         178 :                 break;
     326             :             }
     327             :             case NS_ooxml::LN_CT_TcPrBase_tcW:
     328             :                 {
     329             :                     // Contains unit and value, but unit is not interesting for
     330             :                     // us, later we'll just distribute these values in a
     331             :                     // 0..10000 scale.
     332        7929 :                     writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
     333        7929 :                     if( pProperties.get())
     334             :                     {
     335        7929 :                         MeasureHandlerPtr pMeasureHandler(new MeasureHandler());
     336        7929 :                         pProperties->resolve(*pMeasureHandler);
     337        7929 :                         if (sal::static_int_cast<Id>(pMeasureHandler->getUnit()) == NS_ooxml::LN_Value_ST_TblWidth_auto)
     338         118 :                             getCurrentCellWidths()->push_back(sal_Int32(-1));
     339             :                         else
     340        7811 :                             getCurrentCellWidths()->push_back(pMeasureHandler->getMeasureValue());
     341        7929 :                         if (getTableDepthDifference() > 0)
     342         474 :                             m_bPushCurrentWidth = true;
     343        7929 :                     }
     344             :                 }
     345        7929 :                 break;
     346             :             case NS_ooxml::LN_CT_TblPrBase_tblpPr:
     347             :                 {
     348         304 :                     writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
     349             :                     // Ignore <w:tblpPr> in shape text, those tables should be always non-floating ones.
     350         304 :                     if (!m_bIsInShape && pProperties.get())
     351             :                     {
     352         269 :                         TablePositionHandlerPtr pHandler = m_aTmpPosition.back();
     353         269 :                         if ( !pHandler )
     354             :                         {
     355         269 :                             m_aTmpPosition.pop_back();
     356         269 :                             pHandler.reset( new TablePositionHandler );
     357         269 :                             m_aTmpPosition.push_back( pHandler );
     358             :                         }
     359         269 :                         pProperties->resolve(*m_aTmpPosition.back());
     360         304 :                     }
     361             :                 }
     362         304 :                 break;
     363             :             case NS_ooxml::LN_CT_TrPrBase_gridBefore:
     364           0 :                 m_nGridBefore = nIntValue;
     365           0 :                 break;
     366             :             case NS_ooxml::LN_CT_TrPrBase_gridAfter:
     367           9 :                 m_nGridAfter = nIntValue;
     368           9 :                 break;
     369             :             case NS_ooxml::LN_CT_TblPrBase_tblCaption:
     370             :                 // To-Do: Not yet preserved
     371          12 :                 break;
     372             :             case NS_ooxml::LN_CT_TblPrBase_tblDescription:
     373             :                 // To-Do: Not yet preserved
     374           0 :                 break;
     375             :             case NS_ooxml::LN_CT_TrPrBase_tblCellSpacing:
     376             :                 // To-Do: Not yet preserved
     377          80 :                 break;
     378             :             case NS_ooxml::LN_CT_TblPrBase_tblCellSpacing:
     379             :                 // To-Do: Not yet preserved
     380         105 :                 break;
     381             :             case NS_ooxml::LN_CT_TblPrBase_bidiVisual:
     382             :             {
     383          96 :                 TablePropertyMapPtr pPropMap(new TablePropertyMap());
     384          96 :                 pPropMap->Insert(PROP_WRITING_MODE, uno::makeAny(nIntValue ? text::WritingMode2::RL_TB : text::WritingMode2::LR_TB));
     385          96 :                 insertTableProps(pPropMap);
     386          96 :                 break;
     387             :             }
     388             :             default:
     389      392575 :                 bRet = false;
     390             : 
     391             : #ifdef DEBUG_WRITERFILTER
     392             :                 TagLogger::getInstance().element("unhandled");
     393             : #endif
     394      415107 :         }
     395             :     }
     396      487564 :     return bRet;
     397             : }
     398             : 
     399       14881 : std::shared_ptr< vector<sal_Int32> > DomainMapperTableManager::getCurrentGrid( )
     400             : {
     401       14881 :     return m_aTableGrid.back( );
     402             : }
     403             : 
     404       11321 : std::shared_ptr< vector< sal_Int32 > > DomainMapperTableManager::getCurrentSpans( )
     405             : {
     406       11321 :     return m_aGridSpans.back( );
     407             : }
     408             : 
     409       11708 : std::shared_ptr< vector< sal_Int32 > > DomainMapperTableManager::getCurrentCellWidths( )
     410             : {
     411       11708 :     return m_aCellWidths.back( );
     412             : }
     413             : 
     414        5437 : const uno::Sequence<beans::PropertyValue> DomainMapperTableManager::getCurrentTablePosition( )
     415             : {
     416        5437 :     if ( !m_aTablePositions.empty( ) && m_aTablePositions.back() )
     417          43 :         return m_aTablePositions.back( )->getTablePosition();
     418             :     else
     419        5394 :         return uno::Sequence< beans::PropertyValue >( 0 );
     420             : }
     421             : 
     422         665 : TablePositionHandler* DomainMapperTableManager::getCurrentTableRealPosition()
     423             : {
     424         665 :     if ( !m_aTablePositions.empty( ) && m_aTablePositions.back() )
     425          86 :         return (m_aTablePositions.back( )).get();
     426             :     else
     427         579 :         return nullptr;
     428             : }
     429             : 
     430        1408 : void DomainMapperTableManager::setIsInShape(bool bIsInShape)
     431             : {
     432        1408 :     m_bIsInShape = bIsInShape;
     433        1408 : }
     434             : 
     435        5471 : void DomainMapperTableManager::startLevel( )
     436             : {
     437        5471 :     TableManager::startLevel( );
     438             : 
     439             :     // If requested, pop the value that was pushed too early.
     440        5471 :     boost::optional<sal_Int32> oCurrentWidth;
     441        5471 :     if (m_bPushCurrentWidth && !m_aCellWidths.empty() && !m_aCellWidths.back()->empty())
     442             :     {
     443         450 :         oCurrentWidth.reset(m_aCellWidths.back()->back());
     444         450 :         m_aCellWidths.back()->pop_back();
     445             :     }
     446             : 
     447       10942 :     IntVectorPtr pNewGrid( new vector<sal_Int32> );
     448       10942 :     IntVectorPtr pNewSpans( new vector<sal_Int32> );
     449       10942 :     IntVectorPtr pNewCellWidths( new vector<sal_Int32> );
     450       10942 :     TablePositionHandlerPtr pNewPositionHandler;
     451        5471 :     m_aTableGrid.push_back( pNewGrid );
     452        5471 :     m_aGridSpans.push_back( pNewSpans );
     453        5471 :     m_aCellWidths.push_back( pNewCellWidths );
     454        5471 :     m_aTablePositions.push_back( pNewPositionHandler );
     455             : 
     456       10942 :     TablePositionHandlerPtr pTmpPosition;
     457       10942 :     TablePropertyMapPtr pTmpProperties( new TablePropertyMap( ) );
     458        5471 :     m_aTmpPosition.push_back( pTmpPosition );
     459        5471 :     m_aTmpTableProperties.push_back( pTmpProperties );
     460        5471 :     m_nCell.push_back( 0 );
     461        5471 :     m_nTableWidth = 0;
     462        5471 :     m_nLayoutType = 0;
     463        5471 :     m_nMaxFixedWidth = 0;
     464             : 
     465             :     // And push it back to the right level.
     466        5471 :     if (oCurrentWidth)
     467        5921 :         m_aCellWidths.back()->push_back(*oCurrentWidth);
     468        5471 : }
     469             : 
     470        5439 : void DomainMapperTableManager::endLevel( )
     471             : {
     472        5439 :     m_aTableGrid.pop_back( );
     473        5439 :     m_aGridSpans.pop_back( );
     474             : 
     475             :     // Do the same trick as in startLevel(): pop the value that was pushed too early.
     476        5439 :     boost::optional<sal_Int32> oCurrentWidth;
     477        5439 :     if (m_bPushCurrentWidth && !m_aCellWidths.empty() && !m_aCellWidths.back()->empty())
     478          43 :         oCurrentWidth.reset(m_aCellWidths.back()->back());
     479        5439 :     m_aCellWidths.pop_back( );
     480             :     // And push it back to the right level.
     481        5439 :     if (oCurrentWidth && !m_aCellWidths.empty() && !m_aCellWidths.back()->empty())
     482          14 :         m_aCellWidths.back()->push_back(*oCurrentWidth);
     483             : 
     484        5439 :     m_nCell.pop_back( );
     485        5439 :     m_nTableWidth = 0;
     486        5439 :     m_nLayoutType = 0;
     487        5439 :     m_nMaxFixedWidth = 0;
     488             : 
     489        5439 :     m_aTmpPosition.pop_back( );
     490        5439 :     m_aTmpTableProperties.pop_back( );
     491             : 
     492        5439 :     TableManager::endLevel( );
     493             : #ifdef DEBUG_WRITERFILTER
     494             :     TagLogger::getInstance().startElement("dmappertablemanager.endLevel");
     495             :     PropertyMapPtr pProps = getTableProps();
     496             :     if (pProps.get() != nullptr)
     497             :         getTableProps()->dumpXml();
     498             : 
     499             :     TagLogger::getInstance().endElement();
     500             : #endif
     501             : 
     502             :     // Pop back the table position after endLevel as it's used
     503             :     // in the endTable method called in endLevel.
     504        5439 :     m_aTablePositions.pop_back();
     505        5439 : }
     506             : 
     507        8343 : void DomainMapperTableManager::endOfCellAction()
     508             : {
     509             : #ifdef DEBUG_WRITERFILTER
     510             :     TagLogger::getInstance().element("endOFCellAction");
     511             : #endif
     512             : 
     513        8343 :     getCurrentSpans()->push_back(m_nGridSpan);
     514        8343 :     m_nGridSpan = 1;
     515        8343 :     ++m_nCell.back( );
     516        8343 : }
     517             : 
     518        2978 : void DomainMapperTableManager::endOfRowAction()
     519             : {
     520             : #ifdef DEBUG_WRITERFILTER
     521             :     TagLogger::getInstance().startElement("endOfRowAction");
     522             : #endif
     523             : 
     524             :     // Compare the table position with the previous ones. We may need to split
     525             :     // into two tables if those are different. We surely don't want to do anything
     526             :     // if we don't have any row yet.
     527        2978 :     TablePositionHandlerPtr pTmpPosition = m_aTmpPosition.back();
     528        5956 :     TablePropertyMapPtr pTmpTableProperties = m_aTmpTableProperties.back( );
     529        5956 :     TablePositionHandlerPtr pCurrentPosition = m_aTablePositions.back();
     530        6182 :     bool bSamePosition = ( pTmpPosition == pCurrentPosition ) ||
     531        3517 :                          ( pTmpPosition && pCurrentPosition && *pTmpPosition == *pCurrentPosition );
     532        2978 :     if ( !bSamePosition && m_nRow > 0 )
     533             :     {
     534             :         // Save the grid infos to have them survive the end/start level
     535           5 :         IntVectorPtr pTmpTableGrid = m_aTableGrid.back();
     536          10 :         IntVectorPtr pTmpGridSpans = m_aGridSpans.back();
     537          10 :         IntVectorPtr pTmpCellWidths = m_aCellWidths.back();
     538             : 
     539             :         // endLevel and startLevel are taking care of the non finished row
     540             :         // to carry it over to the next table
     541           5 :         setKeepUnfinishedRow( true );
     542           5 :         endLevel();
     543           5 :         setKeepUnfinishedRow( false );
     544           5 :         startLevel();
     545             : 
     546           5 :         m_aTableGrid.pop_back();
     547           5 :         m_aGridSpans.pop_back();
     548           5 :         m_aCellWidths.pop_back();
     549           5 :         m_aTableGrid.push_back(pTmpTableGrid);
     550           5 :         m_aGridSpans.push_back(pTmpGridSpans);
     551          10 :         m_aCellWidths.push_back(pTmpCellWidths);
     552             :     }
     553             : 
     554             :     // Push the tmp position now that we compared it
     555        2978 :     m_aTablePositions.pop_back();
     556        2978 :     m_aTablePositions.push_back( pTmpPosition );
     557        2978 :     m_aTmpPosition.back().reset( );
     558             : 
     559             : 
     560        5956 :     IntVectorPtr pTableGrid = getCurrentGrid( );
     561        5956 :     IntVectorPtr pCellWidths = getCurrentCellWidths( );
     562        2978 :     if(!m_nTableWidth && pTableGrid->size())
     563             :     {
     564         985 :         ::std::vector<sal_Int32>::const_iterator aCellIter = pTableGrid->begin();
     565             : 
     566             : #ifdef DEBUG_WRITERFILTER
     567             :         TagLogger::getInstance().startElement("tableWidth");
     568             : #endif
     569             : 
     570        4813 :         while( aCellIter != pTableGrid->end() )
     571             :         {
     572             : #ifdef DEBUG_WRITERFILTER
     573             :             TagLogger::getInstance().startElement("col");
     574             :             TagLogger::getInstance().attribute("width", *aCellIter);
     575             :             TagLogger::getInstance().endElement();
     576             : #endif
     577             : 
     578        2843 :              m_nTableWidth += *aCellIter++;
     579             :         }
     580             : 
     581         985 :         if (m_nTableWidth > 0 && !m_bTableSizeTypeInserted)
     582             :         {
     583           8 :             TablePropertyMapPtr pPropMap( new TablePropertyMap );
     584           8 :             pPropMap->setValue( TablePropertyMap::TABLE_WIDTH, m_nTableWidth );
     585           8 :             insertTableProps(pPropMap);
     586             :         }
     587             : 
     588             : #ifdef DEBUG_WRITERFILTER
     589             :         TagLogger::getInstance().endElement();
     590             : #endif
     591             :     }
     592             : 
     593        5956 :     IntVectorPtr pCurrentSpans = getCurrentSpans( );
     594        2978 :     if( pCurrentSpans->size() < m_nCell.back( ) )
     595             :     {
     596             :         //fill missing elements with '1'
     597           0 :         pCurrentSpans->insert( pCurrentSpans->end( ), m_nCell.back( ) - pCurrentSpans->size(), 1 );
     598             :     }
     599             : 
     600             : #ifdef DEBUG_WRITERFILTER
     601             :     TagLogger::getInstance().startElement("gridSpans");
     602             :     {
     603             :         ::std::vector<sal_Int32>::const_iterator aGridSpanIter = pCurrentSpans->begin();
     604             :         ::std::vector<sal_Int32>::const_iterator aGridSpanIterEnd = pCurrentSpans->end();
     605             : 
     606             :         while (aGridSpanIter != aGridSpanIterEnd)
     607             :         {
     608             :             TagLogger::getInstance().startElement("gridSpan");
     609             :             TagLogger::getInstance().attribute("span", *aGridSpanIter);
     610             :             TagLogger::getInstance().endElement();
     611             : 
     612             :             ++aGridSpanIter;
     613             :         }
     614             :     }
     615             :     TagLogger::getInstance().endElement();
     616             : #endif
     617             : 
     618             :     //calculate number of used grids - it has to match the size of m_aTableGrid
     619        2978 :     size_t nGrids = 0;
     620        2978 :     ::std::vector<sal_Int32>::const_iterator aGridSpanIter = pCurrentSpans->begin();
     621       11321 :     for( ; aGridSpanIter != pCurrentSpans->end(); ++aGridSpanIter)
     622        8343 :         nGrids += *aGridSpanIter;
     623             : 
     624             :     // sj: the grid is having no units... they is containing only relative values.
     625             :     // a table with a grid of "1:2:1" looks identical as if the table is having
     626             :     // a grid of "20:40:20" and it doesn't have to do something with the tableWidth
     627             :     // -> so we have get the sum of each grid entry for the fullWidthRelative:
     628        2978 :     int nFullWidthRelative = 0;
     629       11767 :     for (size_t i = 0 ; i < (*pTableGrid.get()).size(); i++ )
     630        8789 :         nFullWidthRelative += (*pTableGrid.get())[ i ];
     631             : 
     632        2978 :     if( pTableGrid->size() == ( m_nGridBefore + nGrids + m_nGridAfter ) && m_nCell.back( ) > 0 )
     633             :     {
     634             :         /*
     635             :          * If table width property set earlier is smaller than the current table width,
     636             :          * then replace the TABLE_WIDTH property, set earlier.
     637             :          */
     638        2911 :         TablePropertyMapPtr propMap = m_aTmpTableProperties.back();
     639        2911 :         sal_Int32 nTableWidth(0);
     640        2911 :         sal_Int32 nTableWidthType(text::SizeType::VARIABLE);
     641        2911 :         propMap->getValue( TablePropertyMap::TABLE_WIDTH, nTableWidth );
     642        2911 :         propMap->getValue( TablePropertyMap::TABLE_WIDTH_TYPE, nTableWidthType );
     643        2911 :         if ((nTableWidthType == text::SizeType::FIX) && (nTableWidth < m_nTableWidth))
     644             :         {
     645           0 :             propMap->setValue( TablePropertyMap::TABLE_WIDTH, m_nTableWidth );
     646             :         }
     647        2911 :         if (nTableWidthType == text::SizeType::VARIABLE )
     648             :         {
     649         998 :             if(nTableWidth > 100 || nTableWidth <= 0)
     650             :             {
     651         829 :                 propMap->setValue( TablePropertyMap::TABLE_WIDTH, m_nTableWidth);
     652         829 :                 propMap->setValue( TablePropertyMap::TABLE_WIDTH_TYPE, text::SizeType::FIX);
     653             :             }
     654             :         }
     655        5822 :         uno::Sequence< text::TableColumnSeparator > aSeparators( m_nCell.back( ) - 1 );
     656        2911 :         text::TableColumnSeparator* pSeparators = aSeparators.getArray();
     657        2911 :         sal_Int16 nLastRelPos = 0;
     658        2911 :         sal_uInt32 nBorderGridIndex = m_nGridBefore;
     659             : 
     660        2911 :         size_t nWidthsBound =  m_nCell.back( ) - 1;
     661        2911 :         if (nWidthsBound)
     662             :         {
     663        2524 :             if (nFullWidthRelative == 0)
     664           0 :                 throw o3tl::divide_by_zero();
     665             : 
     666        2524 :             ::std::vector< sal_Int32 >::const_iterator aSpansIter = pCurrentSpans->begin( );
     667        7792 :             for( size_t nBorder = 0; nBorder < nWidthsBound; ++nBorder )
     668             :             {
     669        5268 :                 double fGridWidth = 0.;
     670       10667 :                 for ( sal_Int32 nGridCount = *aSpansIter; nGridCount > 0; --nGridCount )
     671        5399 :                     fGridWidth += (*pTableGrid.get())[nBorderGridIndex++];
     672             : 
     673        5268 :                 sal_Int16 nRelPos = rtl::math::round((fGridWidth * 10000) / nFullWidthRelative);
     674             : 
     675        5268 :                 pSeparators[nBorder].Position =  nRelPos + nLastRelPos;
     676        5268 :                 pSeparators[nBorder].IsVisible = sal_True;
     677        5268 :                 nLastRelPos = nLastRelPos + nRelPos;
     678        5268 :                 ++aSpansIter;
     679             :             }
     680             :         }
     681        5822 :         TablePropertyMapPtr pPropMap( new TablePropertyMap );
     682        2911 :         pPropMap->Insert( PROP_TABLE_COLUMN_SEPARATORS, uno::makeAny( aSeparators ) );
     683             : 
     684             : #ifdef DEBUG_WRITERFILTER
     685             :         TagLogger::getInstance().startElement("rowProperties");
     686             :         pPropMap->dumpXml();
     687             :         TagLogger::getInstance().endElement();
     688             : #endif
     689        5822 :         insertRowProps(pPropMap);
     690             :     }
     691         138 :     else if ( pCellWidths->size() > 0 &&
     692          51 :                ( m_nLayoutType == NS_ooxml::LN_Value_doc_ST_TblLayout_fixed
     693          49 :                  || pCellWidths->size() == ( m_nGridBefore + nGrids + m_nGridAfter ) )
     694             :              )
     695             :     {
     696             :         // If we're here, then the number of cells does not equal to the amount
     697             :         // defined by the grid, even after taking care of
     698             :         // gridSpan/gridBefore/gridAfter. Handle this by ignoring the grid and
     699             :         // providing the separators based on the provided cell widths, as long
     700             :         // as we have a fixed layout;
     701             :         // On the other hand even if the layout is not fixed, but the cell widths
     702             :         // provided equal the total number of cells, and there are no after/before cells
     703             :         // then use the cell widths to calculate the column separators.
     704          20 :         uno::Sequence< text::TableColumnSeparator > aSeparators(pCellWidths->size() - 1);
     705          20 :         text::TableColumnSeparator* pSeparators = aSeparators.getArray();
     706          20 :         sal_Int16 nSum = 0;
     707          20 :         sal_uInt32 nPos = 0;
     708             :         // Avoid divide by zero (if there's no grid, position using cell widths).
     709          20 :         if( nFullWidthRelative == 0 )
     710           2 :             for (size_t i = 0; i < pCellWidths->size(); ++i)
     711           1 :                 nFullWidthRelative += (*pCellWidths.get())[i];
     712             : 
     713          20 :         size_t nWidthsBound = pCellWidths->size() - 1;
     714          20 :         if (nWidthsBound)
     715             :         {
     716          16 :             if (nFullWidthRelative == 0)
     717           0 :                 throw o3tl::divide_by_zero();
     718             : 
     719          38 :             for (size_t i = 0; i < nWidthsBound; ++i)
     720             :             {
     721          22 :                 nSum += (*pCellWidths.get())[i];
     722          22 :                 pSeparators[nPos].Position = (nSum * 10000) / nFullWidthRelative; // Relative position
     723          22 :                 pSeparators[nPos].IsVisible = sal_True;
     724          22 :                 nPos++;
     725             :             }
     726             :         }
     727             : 
     728          40 :         TablePropertyMapPtr pPropMap( new TablePropertyMap );
     729          20 :         pPropMap->Insert( PROP_TABLE_COLUMN_SEPARATORS, uno::makeAny( aSeparators ) );
     730             : #ifdef DEBUG_WRITERFILTER
     731             :         TagLogger::getInstance().startElement("rowProperties");
     732             :         pPropMap->dumpXml();
     733             :         TagLogger::getInstance().endElement();
     734             : #endif
     735          40 :         insertRowProps(pPropMap);
     736             :     }
     737             : 
     738             :     // Now that potentially opened table is closed, save the table properties
     739        2978 :     TableManager::insertTableProps( pTmpTableProperties );
     740             : 
     741        2978 :     m_aTmpTableProperties.pop_back();
     742        5956 :     TablePropertyMapPtr pEmptyTableProps( new TablePropertyMap() );
     743        2978 :     m_aTmpTableProperties.push_back( pEmptyTableProps );
     744             : 
     745        2978 :     ++m_nRow;
     746        2978 :     m_nCell.back( ) = 0;
     747        2978 :     m_nCellBorderIndex = 0;
     748        2978 :     getCurrentGrid()->clear();
     749        2978 :     pCurrentSpans->clear();
     750        2978 :     pCellWidths->clear();
     751             : 
     752        2978 :     m_nGridBefore = m_nGridAfter = 0;
     753        2978 :     m_bRowSizeTypeInserted = false;
     754        2978 :     m_bHasBtlrCell = false;
     755        5956 :     m_bTableSizeTypeInserted = false;
     756             : 
     757             : #ifdef DEBUG_WRITERFILTER
     758             :     TagLogger::getInstance().endElement();
     759             : #endif
     760        2978 : }
     761             : 
     762        5439 : void DomainMapperTableManager::clearData()
     763             : {
     764        5439 :     m_nRow = m_nCellBorderIndex = m_nHeaderRepeat = m_nTableWidth = m_nLayoutType = 0;
     765        5439 :     m_sTableStyleName.clear();
     766        5439 :     m_pTableStyleTextProperies.reset();
     767        5439 : }
     768             : 
     769             : }}
     770             : 
     771             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11