From c31270abc1605a9de505f4753f1192520fd4130d Mon Sep 17 00:00:00 2001 From: Miklos Vajna Date: Mon, 19 Nov 2012 12:41:39 +0100 Subject: n#780645 DOCX import: add support for fixed column width In general, DOCX tables provide a grid for the table, then use spans in case different number of cells are used in different rows. In this case, the cell width is ignored, as the wished width can be counted from the grid and span values. However, it's also valid to simply provide more cells then the amount defined by the grid, and in this case the cell width should decide the final width of the cells. This commit adds support for this later case. (cherry picked from commit ad913681c0e0cdaaa706329f518f59ee54b86d43) Conflicts: writerfilter/source/dmapper/DomainMapperTableManager.cxx Change-Id: I0dd6c1f0c06f81c2afa00489b7ad1f33ff300a7c --- writerfilter/inc/resourcemodel/TableManager.hxx | 5 ++ .../source/dmapper/DomainMapperTableManager.cxx | 68 +++++++++++++++++++++- .../source/dmapper/DomainMapperTableManager.hxx | 5 ++ 3 files changed, 77 insertions(+), 1 deletion(-) diff --git a/writerfilter/inc/resourcemodel/TableManager.hxx b/writerfilter/inc/resourcemodel/TableManager.hxx index 651cf40d796c..72b575a97b5e 100644 --- a/writerfilter/inc/resourcemodel/TableManager.hxx +++ b/writerfilter/inc/resourcemodel/TableManager.hxx @@ -475,6 +475,11 @@ protected: */ sal_uInt32 getTableDepthNew() { return mnTableDepthNew; } + /** + Return the current table difference, i.e. 1 if we are in the first cell of a new table, etc. + */ + sal_uInt32 getTableDepthDifference() { return mnTableDepthNew - mnTableDepth; } + /** Action to be carried out at the end of the last paragraph of a cell. diff --git a/writerfilter/source/dmapper/DomainMapperTableManager.cxx b/writerfilter/source/dmapper/DomainMapperTableManager.cxx index 62d70bba60b3..50f0cb0d42af 100644 --- a/writerfilter/source/dmapper/DomainMapperTableManager.cxx +++ b/writerfilter/source/dmapper/DomainMapperTableManager.cxx @@ -25,6 +25,7 @@ * for a copy of the LGPLv3 License. * ************************************************************************/ +#include #include #include #include @@ -60,6 +61,7 @@ DomainMapperTableManager::DomainMapperTableManager(bool bOOXML, bool bImplicitMe m_nTableWidth(0), m_bOOXML( bOOXML ), m_bImplicitMerges(bImplicitMerges), + m_bPushCurrentWidth(false), m_pTablePropsHandler( new TablePropertiesHandler( bOOXML ) ) { m_pTablePropsHandler->SetTableManager( this ); @@ -291,7 +293,21 @@ bool DomainMapperTableManager::sprm(Sprm & rSprm) break; } case NS_ooxml::LN_CT_TcPrBase_tcW: - break; //fixed column width is not supported + { + // Contains unit and value, but unit is not interesting for + // us, later we'll just distribute these values in a + // 0..10000 scale. + writerfilter::Reference::Pointer_t pProperties = rSprm.getProps(); + if( pProperties.get()) + { + MeasureHandlerPtr pMeasureHandler(new MeasureHandler()); + pProperties->resolve(*pMeasureHandler); + getCurrentCellWidths()->push_back(pMeasureHandler->getMeasureValue()); + if (getTableDepthDifference() > 0) + m_bPushCurrentWidth = true; + } + } + break; case NS_ooxml::LN_CT_TrPrBase_cnfStyle: { TablePropertyMapPtr pProps( new TablePropertyMap ); @@ -347,6 +363,11 @@ boost::shared_ptr< vector< sal_Int32 > > DomainMapperTableManager::getCurrentSpa return m_aGridSpans.back( ); } +boost::shared_ptr< vector< sal_Int32 > > DomainMapperTableManager::getCurrentCellWidths( ) +{ + return m_aCellWidths.back( ); +} + const rtl::OUString& DomainMapperTableManager::getTableVertAnchor() const { return m_sTableVertAnchor; @@ -356,18 +377,33 @@ void DomainMapperTableManager::startLevel( ) { DomainMapperTableManager_Base_t::startLevel( ); + // If requested, pop the value that was pushed too early. + boost::optional oCurrentWidth; + if (m_bPushCurrentWidth && !m_aCellWidths.empty() && !m_aCellWidths.back()->empty()) + { + oCurrentWidth.reset(m_aCellWidths.back()->back()); + m_aCellWidths.back()->pop_back(); + } + IntVectorPtr pNewGrid( new vector ); IntVectorPtr pNewSpans( new vector ); + IntVectorPtr pNewCellWidths( new vector ); m_aTableGrid.push_back( pNewGrid ); m_aGridSpans.push_back( pNewSpans ); + m_aCellWidths.push_back( pNewCellWidths ); m_nCell.push_back( 0 ); m_nTableWidth = 0; + + // And push it back to the right level. + if (oCurrentWidth) + m_aCellWidths.back()->push_back(*oCurrentWidth); } void DomainMapperTableManager::endLevel( ) { m_aTableGrid.pop_back( ); m_aGridSpans.pop_back( ); + m_aCellWidths.pop_back( ); m_nCell.pop_back( ); m_nTableWidth = 0; @@ -403,6 +439,7 @@ void DomainMapperTableManager::endOfRowAction() #endif IntVectorPtr pTableGrid = getCurrentGrid( ); + IntVectorPtr pCellWidths = getCurrentCellWidths( ); if(!m_nTableWidth && pTableGrid->size()) { ::std::vector::const_iterator aCellIter = pTableGrid->begin(); @@ -532,11 +569,40 @@ void DomainMapperTableManager::endOfRowAction() #endif insertRowProps(pPropMap); } + else if (pCellWidths->size() > 0) + { + // If we're here, then the number of cells does not equal to the amount + // defined by the grid, even after taking care of + // gridSpan/gridBefore/gridAfter. Handle this by ignoring the grid and + // providing the separators based on the provided cell widths. + uno::Sequence< text::TableColumnSeparator > aSeparators(pCellWidths->size() - 1); + text::TableColumnSeparator* pSeparators = aSeparators.getArray(); + sal_Int16 nSum = 0; + sal_uInt32 nPos = 0; + + for (sal_uInt32 i = 0; i < pCellWidths->size() - 1; ++i) + { + nSum += (*pCellWidths.get())[i]; + pSeparators[nPos].Position = nSum * nFullWidthRelative / nFullWidth; + pSeparators[nPos].IsVisible = sal_True; + nPos++; + } + + TablePropertyMapPtr pPropMap( new TablePropertyMap ); + pPropMap->Insert( PROP_TABLE_COLUMN_SEPARATORS, false, uno::makeAny( aSeparators ) ); +#ifdef DEBUG_DOMAINMAPPER + dmapper_logger->startElement("rowProperties"); + pPropMap->dumpXml( dmapper_logger ); + dmapper_logger->endElement(); +#endif + insertRowProps(pPropMap); + } ++m_nRow; m_nCell.back( ) = 0; m_nCellBorderIndex = 0; pCurrentSpans->clear(); + pCellWidths->clear(); m_nGridBefore = m_nGridAfter = 0; diff --git a/writerfilter/source/dmapper/DomainMapperTableManager.hxx b/writerfilter/source/dmapper/DomainMapperTableManager.hxx index 2c346fb9a86b..64a06c2bbdcc 100644 --- a/writerfilter/source/dmapper/DomainMapperTableManager.hxx +++ b/writerfilter/source/dmapper/DomainMapperTableManager.hxx @@ -59,6 +59,10 @@ class DomainMapperTableManager : public DomainMapperTableManager_Base_t ::std::vector< IntVectorPtr > m_aTableGrid; ::std::vector< IntVectorPtr > m_aGridSpans; + /// If this is true, then we pushed a width before the next level started, and that should be carried over when starting the next level. + bool m_bPushCurrentWidth; + /// Individual table cell width values, used only in case the number of cells doesn't match the table grid. + ::std::vector< IntVectorPtr > m_aCellWidths; TablePropertiesHandler *m_pTablePropsHandler; PropertyMapPtr m_pStyleProps; @@ -84,6 +88,7 @@ public: IntVectorPtr getCurrentGrid( ); IntVectorPtr getCurrentSpans( ); + IntVectorPtr getCurrentCellWidths( ); const ::rtl::OUString& getTableStyleName() const { return m_sTableStyleName; } const rtl::OUString& getTableVertAnchor() const; -- cgit v1.2.3