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 <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 <dmapperLoggers.hxx>
35 :
36 : namespace writerfilter {
37 : namespace dmapper {
38 :
39 : using namespace ::com::sun::star;
40 : using namespace ::std;
41 :
42 :
43 3009 : DomainMapperTableManager::DomainMapperTableManager(bool bOOXML) :
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_bOOXML( bOOXML ),
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 3009 : m_pTablePropsHandler( new TablePropertiesHandler( bOOXML ) )
62 : {
63 3009 : m_pTablePropsHandler->SetTableManager( this );
64 :
65 : #ifdef DEBUG_DOMAINMAPPER
66 : #ifdef DEBUG_TABLE
67 : setTagLogger(dmapper_logger);
68 : #endif
69 : #endif
70 3009 : }
71 :
72 :
73 9027 : DomainMapperTableManager::~DomainMapperTableManager()
74 : {
75 3009 : if ( m_pTablePropsHandler )
76 3009 : delete m_pTablePropsHandler, m_pTablePropsHandler = NULL;
77 6018 : }
78 :
79 :
80 323658 : bool DomainMapperTableManager::sprm(Sprm & rSprm)
81 : {
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 323658 : bool bRet = DomainMapperTableManager_Base_t::sprm(rSprm);
89 323658 : if( !bRet )
90 : {
91 282688 : bRet = m_pTablePropsHandler->sprm( rSprm );
92 : }
93 :
94 323658 : if ( !bRet )
95 : {
96 268953 : bRet = true;
97 268953 : sal_uInt32 nSprmId = rSprm.getId();
98 268953 : Value::Pointer_t pValue = rSprm.getValue();
99 268953 : sal_Int32 nIntValue = ((pValue.get() != NULL) ? pValue->getInt() : 0);
100 268953 : switch ( nSprmId )
101 : {
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
106 : {
107 : //contains unit and value
108 2179 : writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
109 2179 : if( pProperties.get())
110 : { //contains attributes x2902 (LN_unit) and x17e2 (LN_trleft)
111 2179 : MeasureHandlerPtr pMeasureHandler( new MeasureHandler );
112 2179 : pProperties->resolve(*pMeasureHandler);
113 4358 : TablePropertyMapPtr pPropMap( new TablePropertyMap );
114 2179 : if( nSprmId == 0xf661 || nSprmId == sal_uInt32(NS_ooxml::LN_CT_TblPrBase_tblInd ))
115 : {
116 0 : pPropMap->setValue( TablePropertyMap::LEFT_MARGIN, pMeasureHandler->getMeasureValue() );
117 : }
118 : else
119 : {
120 2179 : m_nTableWidth = pMeasureHandler->getMeasureValue();
121 2179 : if( m_nTableWidth )
122 : {
123 914 : pPropMap->setValue( TablePropertyMap::TABLE_WIDTH_TYPE, text::SizeType::FIX );
124 914 : pPropMap->setValue( TablePropertyMap::TABLE_WIDTH, m_nTableWidth );
125 : }
126 1265 : else if( sal::static_int_cast<Id>(pMeasureHandler->getUnit()) == NS_ooxml::LN_Value_ST_TblWidth_pct )
127 : {
128 102 : sal_Int32 nPercent = pMeasureHandler->getValue() / 50;
129 102 : if(nPercent > 100)
130 0 : nPercent = 100;
131 102 : pPropMap->setValue( TablePropertyMap::TABLE_WIDTH_TYPE, text::SizeType::VARIABLE );
132 102 : pPropMap->setValue( TablePropertyMap::TABLE_WIDTH, nPercent );
133 : }
134 1163 : else if( sal::static_int_cast<Id>(pMeasureHandler->getUnit()) == NS_ooxml::LN_Value_ST_TblWidth_auto )
135 : {
136 : /*
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 value is 'auto', the table layout has to use 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.)
142 : */
143 1160 : bool bFixed = true;
144 1160 : sal_Int32 nRowFixedWidth = 0;
145 1160 : IntVectorPtr pCellWidths = getCurrentCellWidths();
146 : // Step 1. Check whether all cells have fixed widths in the given row of table.
147 4225 : for (std::vector<sal_Int32>::const_iterator aValIter = pCellWidths->begin(); aValIter != pCellWidths->end(); ++aValIter)
148 : {
149 3095 : if (*aValIter == -1)
150 : {
151 30 : bFixed = false;
152 30 : break;
153 : }
154 : // Sum the width of cells to find the total width of given row
155 3065 : nRowFixedWidth += (*aValIter);
156 : }
157 :
158 : // Check whether the total width of given row is compared with the maximum value of rows (m_nMaxFixedWidth).
159 1160 : if (bFixed )
160 : {
161 : // Check if total width
162 1130 : if (m_nMaxFixedWidth < nRowFixedWidth)
163 238 : m_nMaxFixedWidth = nRowFixedWidth;
164 :
165 1130 : pPropMap->setValue( TablePropertyMap::TABLE_WIDTH_TYPE, text::SizeType::FIX );
166 1130 : pPropMap->setValue( TablePropertyMap::TABLE_WIDTH, m_nMaxFixedWidth );
167 : }
168 : else
169 : {
170 : // Set the width type of table with 'Auto' and set the width value to 100(%)
171 30 : pPropMap->setValue( TablePropertyMap::TABLE_WIDTH_TYPE, text::SizeType::VARIABLE );
172 30 : pPropMap->setValue( TablePropertyMap::TABLE_WIDTH, 0 );
173 1160 : }
174 : }
175 2179 : m_bTableSizeTypeInserted = true;
176 : }
177 : #ifdef DEBUG_DOMAINMAPPER
178 : pPropMap->dumpXml( dmapper_logger );
179 : #endif
180 4358 : insertTableProps(pPropMap);
181 2179 : }
182 : }
183 2179 : 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 57 : if( nIntValue > 0 && m_nHeaderRepeat >= 0 )
189 : {
190 57 : ++m_nHeaderRepeat;
191 57 : TablePropertyMapPtr pPropMap( new TablePropertyMap );
192 57 : pPropMap->Insert( PROP_HEADER_ROW_COUNT, uno::makeAny( m_nHeaderRepeat ));
193 57 : insertTableProps(pPropMap);
194 : }
195 : else
196 0 : m_nHeaderRepeat = -1;
197 57 : if (nIntValue)
198 : {
199 : // Store the info that this is a header, we'll need that when we apply table styles.
200 57 : TablePropertyMapPtr pPropMap( new TablePropertyMap );
201 57 : pPropMap->Insert( PROP_TBL_HEADER, uno::makeAny(nIntValue));
202 57 : insertRowProps(pPropMap);
203 : }
204 57 : break;
205 : case 0xd608: // TDefTable
206 : {
207 0 : writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
208 0 : if( pProperties.get())
209 : {
210 0 : TDefTableHandlerPtr pTDefTableHandler( new TDefTableHandler(m_bOOXML) );
211 0 : pProperties->resolve( *pTDefTableHandler );
212 :
213 0 : TablePropertyMapPtr pRowPropMap( new TablePropertyMap );
214 0 : pRowPropMap->InsertProps(pTDefTableHandler->getRowProperties());
215 0 : insertRowProps( pRowPropMap );
216 0 : if( !m_nTableWidth )
217 : {
218 0 : m_nTableWidth= pTDefTableHandler->getTableWidth();
219 0 : if( m_nTableWidth )
220 : {
221 0 : TablePropertyMapPtr pPropMap( new TablePropertyMap );
222 0 : pPropMap->setValue( TablePropertyMap::TABLE_WIDTH, m_nTableWidth );
223 0 : insertTableProps(pPropMap);
224 : }
225 : }
226 0 : for( size_t nCell = 0; nCell < pTDefTableHandler->getCellCount(); ++nCell )
227 : {
228 0 : TablePropertyMapPtr pCellPropMap( new TablePropertyMap );
229 0 : pTDefTableHandler->fillCellProperties( nCell, pCellPropMap );
230 0 : cellPropsByCell( nCell, pCellPropMap );
231 0 : }
232 0 : }
233 : }
234 0 : break;
235 : case 0xD605: // sprmTTableBorders
236 : {
237 0 : writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
238 0 : if( pProperties.get())
239 : {
240 0 : BorderHandlerPtr pBorderHandler( new BorderHandler(m_bOOXML) );
241 0 : pProperties->resolve(*pBorderHandler);
242 0 : TablePropertyMapPtr pCellPropMap( new TablePropertyMap() );
243 0 : pCellPropMap->InsertProps(pBorderHandler->getProperties());
244 0 : cellPropsByCell( m_nCellBorderIndex, pCellPropMap );
245 0 : ++m_nCellBorderIndex;
246 0 : }
247 : }
248 0 : break;
249 : case 0xd632 : //sprmTNewSpacing
250 : case 0xd634 : //sprmTNewSpacing
251 : //TODO: sprms contain default (TNew) and actual border spacing of cells - not resolvable yet
252 0 : break;
253 : case 0xd613: //sprmTGridLineProps
254 : // TODO: needs a handler
255 : /*contains:
256 : GridLineProps">
257 : rtf:LINEPROPSTOP
258 : rtf:LINEPROPSLEFT
259 : rtf:LINEPROPSBOTTOM
260 : rtf:LINEPROPSRIGHT
261 : rtf:LINEPROPSHORIZONTAL
262 : rtf:LINEPROPSVERTICAL
263 : rtf:LINECOLOR
264 : rtf:LINEWIDTH
265 : rtf:LINETYPE
266 :
267 : */
268 0 : break;
269 : case 0x740a : //sprmTTlp
270 : //TODO: Table look specifier
271 0 : break;
272 : case 0x6816 : //unknown
273 : case 0x3466 : //unknown
274 : case 0x3615 : //unknown
275 : case 0x646b : //unknown - expandable sprm - see ww8scan.cxx
276 : case 0x7479 : //unknown
277 : case 0xf617 : //unknown
278 : case 0xf618 : //unknown
279 0 : bRet = false;
280 0 : break;
281 : case NS_ooxml::LN_CT_TblPrBase_tblStyle: //table style name
282 : {
283 1247 : m_sTableStyleName = pValue->getString();
284 1247 : TablePropertyMapPtr pPropMap( new TablePropertyMap );
285 1247 : pPropMap->Insert( META_PROP_TABLE_STYLE_NAME, uno::makeAny( m_sTableStyleName ));
286 1247 : insertTableProps(pPropMap);
287 : }
288 1247 : break;
289 : case NS_ooxml::LN_CT_TblGridBase_gridCol:
290 : {
291 7728 : if (nIntValue == -1)
292 85 : getCurrentGrid()->clear();
293 : else
294 7643 : getCurrentGrid()->push_back( ConversionHelper::convertTwipToMM100( nIntValue ) );
295 : }
296 7728 : break;
297 : case NS_ooxml::LN_CT_TcPrBase_vMerge : //vertical merge
298 : {
299 : // values can be: LN_Value_ST_Merge_restart, LN_Value_ST_Merge_continue, in reality the second one is a 0
300 129 : TablePropertyMapPtr pMergeProps( new TablePropertyMap );
301 129 : pMergeProps->Insert( PROP_VERTICAL_MERGE, uno::makeAny( bool( sal::static_int_cast<Id>(nIntValue) == NS_ooxml::LN_Value_ST_Merge_restart )) );
302 129 : cellProps( pMergeProps);
303 : }
304 129 : break;
305 : case NS_ooxml::LN_CT_TcPrBase_hMerge:
306 : {
307 : // values can be: LN_Value_ST_Merge_restart, LN_Value_ST_Merge_continue, in reality the second one is a 0
308 4 : TablePropertyMapPtr pMergeProps(new TablePropertyMap());
309 4 : pMergeProps->Insert(PROP_HORIZONTAL_MERGE, uno::makeAny(bool(sal::static_int_cast<Id>(nIntValue) == NS_ooxml::LN_Value_ST_Merge_restart)));
310 4 : cellProps(pMergeProps);
311 : }
312 4 : break;
313 : case NS_ooxml::LN_CT_TcPrBase_gridSpan: //number of grid positions spanned by this cell
314 : {
315 : #ifdef DEBUG_DOMAINMAPPER
316 : dmapper_logger->startElement("tablemanager.GridSpan");
317 : dmapper_logger->attribute("gridSpan", nIntValue);
318 : dmapper_logger->endElement();
319 : #endif
320 463 : m_nGridSpan = nIntValue;
321 : }
322 463 : break;
323 : case NS_ooxml::LN_CT_TblPrBase_tblLook:
324 : {
325 1606 : TablePropertyMapPtr pPropMap( new TablePropertyMap );
326 1606 : pPropMap->Insert( PROP_TBL_LOOK, uno::makeAny( nIntValue ));
327 1606 : insertTableProps(pPropMap);
328 : }
329 1606 : break;
330 : case NS_ooxml::LN_CT_TcPrBase_textDirection:
331 : {
332 133 : TablePropertyMapPtr pPropMap( new TablePropertyMap );
333 133 : bool bInsertCellProps = true;
334 133 : switch ( nIntValue )
335 : {
336 : case 1: // tbRl
337 : // Binary filter takes BiDirection into account ( but I have no idea about that here )
338 : // or even what it is. But... here's where to handle it if it becomes an issue
339 1 : pPropMap->Insert( PROP_FRM_DIRECTION, uno::makeAny( text::WritingMode2::TB_RL ));
340 : SAL_INFO( "writerfilter", "Have inserted textDirection " << nIntValue );
341 1 : break;
342 : case 3: // btLr
343 : {
344 : // We have to fake this text direction
345 31 : pPropMap->Insert( PROP_FRM_DIRECTION, uno::makeAny( text::WritingMode2::LR_TB ));
346 31 : pPropMap->Insert( PROP_CHAR_ROTATION, uno::makeAny( sal_Int16( 900 ) ));
347 : SAL_INFO( "writerfilter", "Have inserted textDirection " << nIntValue );
348 :
349 : // We're faking a text direction, so don't allow multiple lines.
350 31 : if (!getCellProps() || getCellProps()->find(PROP_VERTICAL_MERGE) == getCellProps()->end())
351 : {
352 : // Though in case there will be a vertical merge, don't do this, it hides text that is supposed to be visible.
353 12 : TablePropertyMapPtr pRowPropMap( new TablePropertyMap );
354 12 : pRowPropMap->Insert(PROP_SIZE_TYPE, uno::makeAny(text::SizeType::FIX));
355 12 : m_bRowSizeTypeInserted = true;
356 12 : insertRowProps(pRowPropMap);
357 : }
358 31 : m_bHasBtlrCell = true;
359 : }
360 31 : break;
361 : case 4: // lrTbV
362 0 : pPropMap->Insert( PROP_FRM_DIRECTION, uno::makeAny( text::WritingMode2::LR_TB ));
363 0 : break;
364 : case 5: // tbRlV
365 0 : pPropMap->Insert( PROP_FRM_DIRECTION, uno::makeAny( text::WritingMode2::TB_RL ));
366 0 : break;
367 : case 0: // lrTb
368 : case NS_ooxml::LN_Value_ST_TextDirection_tbLrV:
369 : default:
370 : // Ignore - we can't handle these
371 101 : bInsertCellProps = false;
372 101 : break;
373 : }
374 133 : if ( bInsertCellProps )
375 32 : cellProps( pPropMap );
376 133 : break;
377 : }
378 : case NS_ooxml::LN_CT_TcPrBase_tcW:
379 : {
380 : // Contains unit and value, but unit is not interesting for
381 : // us, later we'll just distribute these values in a
382 : // 0..10000 scale.
383 6445 : writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
384 6445 : if( pProperties.get())
385 : {
386 6445 : MeasureHandlerPtr pMeasureHandler(new MeasureHandler());
387 6445 : pProperties->resolve(*pMeasureHandler);
388 6445 : if (sal::static_int_cast<Id>(pMeasureHandler->getUnit()) == NS_ooxml::LN_Value_ST_TblWidth_auto)
389 117 : getCurrentCellWidths()->push_back(sal_Int32(-1));
390 : else
391 6328 : getCurrentCellWidths()->push_back(pMeasureHandler->getMeasureValue());
392 6445 : if (getTableDepthDifference() > 0)
393 298 : m_bPushCurrentWidth = true;
394 6445 : }
395 : }
396 6445 : break;
397 : case NS_ooxml::LN_CT_TrPrBase_cnfStyle:
398 241 : break; // the cnfStyle doesn't matter, instead the tblLook property is used to specify conditional styles that are to be used
399 : case NS_ooxml::LN_CT_PPrBase_cnfStyle:
400 : // TODO cnfStyle on a paragraph
401 1034 : break;
402 : case NS_ooxml::LN_CT_TcPrBase_cnfStyle:
403 259 : break; // the cnfStyle doesn't matter, instead the tblLook property is used to specify conditional styles that are to be used
404 : case NS_ooxml::LN_CT_TblPrBase_tblpPr:
405 : {
406 244 : writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
407 244 : if (pProperties.get())
408 : {
409 244 : TablePositionHandlerPtr pHandler = m_aTmpPosition.back();
410 244 : if ( !pHandler )
411 : {
412 244 : m_aTmpPosition.pop_back();
413 244 : pHandler.reset( new TablePositionHandler );
414 244 : m_aTmpPosition.push_back( pHandler );
415 : }
416 244 : pProperties->resolve(*m_aTmpPosition.back());
417 244 : }
418 : }
419 244 : break;
420 : case NS_ooxml::LN_CT_TrPrBase_gridBefore:
421 4 : m_nGridBefore = nIntValue;
422 4 : break;
423 : case NS_ooxml::LN_CT_TrPrBase_gridAfter:
424 9 : m_nGridAfter = nIntValue;
425 9 : break;
426 : default:
427 247171 : bRet = false;
428 :
429 : #ifdef DEBUG_DOMAINMAPPER
430 : dmapper_logger->element("unhandled");
431 : #endif
432 268953 : }
433 : }
434 323658 : return bRet;
435 : }
436 :
437 12118 : boost::shared_ptr< vector<sal_Int32> > DomainMapperTableManager::getCurrentGrid( )
438 : {
439 12118 : return m_aTableGrid.back( );
440 : }
441 :
442 8915 : boost::shared_ptr< vector< sal_Int32 > > DomainMapperTableManager::getCurrentSpans( )
443 : {
444 8915 : return m_aGridSpans.back( );
445 : }
446 :
447 9800 : boost::shared_ptr< vector< sal_Int32 > > DomainMapperTableManager::getCurrentCellWidths( )
448 : {
449 9800 : return m_aCellWidths.back( );
450 : }
451 :
452 3394 : const uno::Sequence<beans::PropertyValue> DomainMapperTableManager::getCurrentTablePosition( )
453 : {
454 3394 : if ( !m_aTablePositions.empty( ) && m_aTablePositions.back() )
455 31 : return m_aTablePositions.back( )->getTablePosition();
456 : else
457 3363 : return uno::Sequence< beans::PropertyValue >( 0 );
458 : }
459 :
460 3411 : void DomainMapperTableManager::startLevel( )
461 : {
462 3411 : DomainMapperTableManager_Base_t::startLevel( );
463 :
464 : // If requested, pop the value that was pushed too early.
465 3411 : boost::optional<sal_Int32> oCurrentWidth;
466 3411 : if (m_bPushCurrentWidth && !m_aCellWidths.empty() && !m_aCellWidths.back()->empty())
467 : {
468 285 : oCurrentWidth.reset(m_aCellWidths.back()->back());
469 285 : m_aCellWidths.back()->pop_back();
470 : }
471 :
472 6822 : IntVectorPtr pNewGrid( new vector<sal_Int32> );
473 6822 : IntVectorPtr pNewSpans( new vector<sal_Int32> );
474 6822 : IntVectorPtr pNewCellWidths( new vector<sal_Int32> );
475 6822 : TablePositionHandlerPtr pNewPositionHandler;
476 3411 : m_aTableGrid.push_back( pNewGrid );
477 3411 : m_aGridSpans.push_back( pNewSpans );
478 3411 : m_aCellWidths.push_back( pNewCellWidths );
479 3411 : m_aTablePositions.push_back( pNewPositionHandler );
480 :
481 6822 : TablePositionHandlerPtr pTmpPosition;
482 6822 : TablePropertyMapPtr pTmpProperties( new TablePropertyMap( ) );
483 3411 : m_aTmpPosition.push_back( pTmpPosition );
484 3411 : m_aTmpTableProperties.push_back( pTmpProperties );
485 3411 : m_nCell.push_back( 0 );
486 3411 : m_nTableWidth = 0;
487 3411 : m_nLayoutType = 0;
488 3411 : m_nMaxFixedWidth = 0;
489 :
490 : // And push it back to the right level.
491 3411 : if (oCurrentWidth)
492 3696 : m_aCellWidths.back()->push_back(*oCurrentWidth);
493 3411 : }
494 :
495 3394 : void DomainMapperTableManager::endLevel( )
496 : {
497 3394 : m_aTableGrid.pop_back( );
498 3394 : m_aGridSpans.pop_back( );
499 :
500 : // Do the same trick as in startLevel(): pop the value that was pushed too early.
501 3394 : boost::optional<sal_Int32> oCurrentWidth;
502 3394 : if (m_bPushCurrentWidth && !m_aCellWidths.empty() && !m_aCellWidths.back()->empty())
503 32 : oCurrentWidth.reset(m_aCellWidths.back()->back());
504 3394 : m_aCellWidths.pop_back( );
505 : // And push it back to the right level.
506 3394 : if (oCurrentWidth)
507 32 : m_aCellWidths.back()->push_back(*oCurrentWidth);
508 :
509 3394 : m_nCell.pop_back( );
510 3394 : m_nTableWidth = 0;
511 3394 : m_nLayoutType = 0;
512 3394 : m_nMaxFixedWidth = 0;
513 :
514 3394 : m_aTmpPosition.pop_back( );
515 3394 : m_aTmpTableProperties.pop_back( );
516 :
517 3394 : DomainMapperTableManager_Base_t::endLevel( );
518 : #ifdef DEBUG_DOMAINMAPPER
519 : dmapper_logger->startElement("dmappertablemanager.endLevel");
520 : PropertyMapPtr pProps = getTableProps();
521 : if (pProps.get() != NULL)
522 : getTableProps()->dumpXml( dmapper_logger );
523 :
524 : dmapper_logger->endElement();
525 : #endif
526 :
527 : // Pop back the table position after endLevel as it's used
528 : // in the endTable method called in endLevel.
529 3394 : m_aTablePositions.pop_back();
530 3394 : }
531 :
532 :
533 :
534 6720 : void DomainMapperTableManager::endOfCellAction()
535 : {
536 : #ifdef DEBUG_DOMAINMAPPER
537 : dmapper_logger->element("endOFCellAction");
538 : #endif
539 :
540 6720 : getCurrentSpans()->push_back(m_nGridSpan);
541 6720 : m_nGridSpan = 1;
542 6720 : ++m_nCell.back( );
543 6720 : }
544 :
545 :
546 2195 : void DomainMapperTableManager::endOfRowAction()
547 : {
548 : #ifdef DEBUG_DOMAINMAPPER
549 : dmapper_logger->startElement("endOfRowAction");
550 : #endif
551 :
552 : // Compare the table position with the previous ones. We may need to split
553 : // into two tables if those are different. We surely don't want to do anything
554 : // if we don't have any row yet.
555 2195 : TablePositionHandlerPtr pTmpPosition = m_aTmpPosition.back();
556 4390 : TablePropertyMapPtr pTmpTableProperties = m_aTmpTableProperties.back( );
557 4390 : TablePositionHandlerPtr pCurrentPosition = m_aTablePositions.back();
558 4603 : bool bSamePosition = ( pTmpPosition == pCurrentPosition ) ||
559 2686 : ( pTmpPosition && pCurrentPosition && *pTmpPosition == *pCurrentPosition );
560 2195 : if ( !bSamePosition && m_nRow > 0 )
561 : {
562 : // Save the grid infos to have them survive the end/start level
563 5 : IntVectorPtr pTmpTableGrid = m_aTableGrid.back();
564 10 : IntVectorPtr pTmpGridSpans = m_aGridSpans.back();
565 10 : IntVectorPtr pTmpCellWidths = m_aCellWidths.back();
566 :
567 : // endLevel and startLevel are taking care of the non finished row
568 : // to carry it over to the next table
569 5 : setKeepUnfinishedRow( true );
570 5 : endLevel();
571 5 : setKeepUnfinishedRow( false );
572 5 : startLevel();
573 :
574 5 : m_aTableGrid.pop_back();
575 5 : m_aGridSpans.pop_back();
576 5 : m_aCellWidths.pop_back();
577 5 : m_aTableGrid.push_back(pTmpTableGrid);
578 5 : m_aGridSpans.push_back(pTmpGridSpans);
579 10 : m_aCellWidths.push_back(pTmpCellWidths);
580 : }
581 :
582 : // Push the tmp position now that we compared it
583 2195 : m_aTablePositions.pop_back();
584 2195 : m_aTablePositions.push_back( pTmpPosition );
585 2195 : m_aTmpPosition.back().reset( );
586 :
587 :
588 4390 : IntVectorPtr pTableGrid = getCurrentGrid( );
589 4390 : IntVectorPtr pCellWidths = getCurrentCellWidths( );
590 2195 : if(!m_nTableWidth && pTableGrid->size())
591 : {
592 1272 : ::std::vector<sal_Int32>::const_iterator aCellIter = pTableGrid->begin();
593 :
594 : #ifdef DEBUG_DOMAINMAPPER
595 : dmapper_logger->startElement("tableWidth");
596 : #endif
597 :
598 6559 : while( aCellIter != pTableGrid->end() )
599 : {
600 : #ifdef DEBUG_DOMAINMAPPER
601 : dmapper_logger->startElement("col");
602 : dmapper_logger->attribute("width", *aCellIter);
603 : dmapper_logger->endElement();
604 : #endif
605 :
606 4015 : m_nTableWidth += *aCellIter++;
607 : }
608 :
609 1272 : if (m_nTableWidth > 0 && !m_bTableSizeTypeInserted)
610 : {
611 6 : TablePropertyMapPtr pPropMap( new TablePropertyMap );
612 6 : pPropMap->setValue( TablePropertyMap::TABLE_WIDTH, m_nTableWidth );
613 6 : insertTableProps(pPropMap);
614 : }
615 :
616 : #ifdef DEBUG_DOMAINMAPPER
617 : dmapper_logger->endElement();
618 : #endif
619 : }
620 :
621 4390 : IntVectorPtr pCurrentSpans = getCurrentSpans( );
622 2195 : if( pCurrentSpans->size() < m_nCell.back( ) )
623 : {
624 : //fill missing elements with '1'
625 0 : pCurrentSpans->insert( pCurrentSpans->end( ), m_nCell.back( ) - pCurrentSpans->size(), 1 );
626 : }
627 :
628 : #ifdef DEBUG_DOMAINMAPPER
629 : dmapper_logger->startElement("gridSpans");
630 : {
631 : ::std::vector<sal_Int32>::const_iterator aGridSpanIter = pCurrentSpans->begin();
632 : ::std::vector<sal_Int32>::const_iterator aGridSpanIterEnd = pCurrentSpans->end();
633 :
634 : while (aGridSpanIter != aGridSpanIterEnd)
635 : {
636 : dmapper_logger->startElement("gridSpan");
637 : dmapper_logger->attribute("span", *aGridSpanIter);
638 : dmapper_logger->endElement();
639 :
640 : ++aGridSpanIter;
641 : }
642 : }
643 : dmapper_logger->endElement();
644 : #endif
645 :
646 : //calculate number of used grids - it has to match the size of m_aTableGrid
647 2195 : size_t nGrids = 0;
648 2195 : ::std::vector<sal_Int32>::const_iterator aGridSpanIter = pCurrentSpans->begin();
649 8915 : for( ; aGridSpanIter != pCurrentSpans->end(); ++aGridSpanIter)
650 6720 : nGrids += *aGridSpanIter;
651 :
652 : // sj: the grid is having no units... they is containing only relative values.
653 : // a table with a grid of "1:2:1" looks identical as if the table is having
654 : // a grid of "20:40:20" and it doesn't have to do something with the tableWidth
655 : // -> so we have get the sum of each grid entry for the fullWidthRelative:
656 2195 : int nFullWidthRelative = 0;
657 9838 : for (unsigned int i = 0 ; i < (*pTableGrid.get()).size(); i++ )
658 7643 : nFullWidthRelative += (*pTableGrid.get())[ i ];
659 :
660 2195 : if( pTableGrid->size() == ( m_nGridBefore + nGrids + m_nGridAfter ) && m_nCell.back( ) > 0 )
661 : {
662 : /*
663 : * If table width property set earlier is smaller than the current table width,
664 : * then replace the TABLE_WIDTH property, set earlier.
665 : */
666 2173 : TablePropertyMapPtr propMap = m_aTmpTableProperties.back();
667 : sal_Int32 nTableWidth;
668 : sal_Int32 nTableWidthType;
669 2173 : propMap->getValue( TablePropertyMap::TABLE_WIDTH, nTableWidth );
670 2173 : propMap->getValue( TablePropertyMap::TABLE_WIDTH_TYPE, nTableWidthType );
671 2173 : if ((nTableWidthType == text::SizeType::FIX) && (nTableWidth < m_nTableWidth))
672 : {
673 26 : propMap->setValue( TablePropertyMap::TABLE_WIDTH, m_nTableWidth );
674 : }
675 2173 : if (nTableWidthType == text::SizeType::VARIABLE )
676 : {
677 131 : if(nTableWidth > 100 || nTableWidth <= 0)
678 : {
679 30 : propMap->setValue( TablePropertyMap::TABLE_WIDTH, m_nTableWidth);
680 30 : propMap->setValue( TablePropertyMap::TABLE_WIDTH_TYPE, text::SizeType::FIX);
681 : }
682 : }
683 4346 : uno::Sequence< text::TableColumnSeparator > aSeparators( m_nCell.back( ) - 1 );
684 2173 : text::TableColumnSeparator* pSeparators = aSeparators.getArray();
685 2173 : sal_Int16 nLastRelPos = 0;
686 2173 : sal_uInt32 nBorderGridIndex = m_nGridBefore;
687 :
688 2173 : ::std::vector< sal_Int32 >::const_iterator aSpansIter = pCurrentSpans->begin( );
689 6681 : for( sal_uInt32 nBorder = 0; nBorder < m_nCell.back( ) - 1; ++nBorder )
690 : {
691 4508 : double fGridWidth = 0.;
692 9447 : for ( sal_Int32 nGridCount = *aSpansIter; nGridCount > 0; --nGridCount )
693 4939 : fGridWidth += (*pTableGrid.get())[nBorderGridIndex++];
694 :
695 : sal_Int16 nRelPos =
696 4508 : sal::static_int_cast< sal_Int16 >((fGridWidth * 10000) / nFullWidthRelative);
697 :
698 4508 : pSeparators[nBorder].Position = nRelPos + nLastRelPos;
699 4508 : pSeparators[nBorder].IsVisible = sal_True;
700 4508 : nLastRelPos = nLastRelPos + nRelPos;
701 4508 : ++aSpansIter;
702 : }
703 4346 : TablePropertyMapPtr pPropMap( new TablePropertyMap );
704 2173 : pPropMap->Insert( PROP_TABLE_COLUMN_SEPARATORS, uno::makeAny( aSeparators ) );
705 :
706 : #ifdef DEBUG_DOMAINMAPPER
707 : dmapper_logger->startElement("rowProperties");
708 : pPropMap->dumpXml( dmapper_logger );
709 : dmapper_logger->endElement();
710 : #endif
711 4346 : insertRowProps(pPropMap);
712 : }
713 41 : else if ( pCellWidths->size() > 0 &&
714 10 : ( m_nLayoutType == NS_ooxml::LN_Value_wordprocessingml_ST_TblLayout_fixed
715 8 : || pCellWidths->size() == ( m_nGridBefore + nGrids + m_nGridAfter ) )
716 : )
717 : {
718 : // If we're here, then the number of cells does not equal to the amount
719 : // defined by the grid, even after taking care of
720 : // gridSpan/gridBefore/gridAfter. Handle this by ignoring the grid and
721 : // providing the separators based on the provided cell widths, as long
722 : // as we have a fixed layout;
723 : // On the other hand even if the layout is not fixed, but the cell widths
724 : // provided equal the total number of cells, and there are no after/before cells
725 : // then use the cell widths to calculate the column separators.
726 9 : uno::Sequence< text::TableColumnSeparator > aSeparators(pCellWidths->size() - 1);
727 9 : text::TableColumnSeparator* pSeparators = aSeparators.getArray();
728 9 : sal_Int16 nSum = 0;
729 9 : sal_uInt32 nPos = 0;
730 : // Avoid divide by zero (if there's no grid, position using cell widths).
731 9 : if( nFullWidthRelative == 0 )
732 0 : for (sal_uInt32 i = 0; i < pCellWidths->size(); ++i)
733 0 : nFullWidthRelative += (*pCellWidths.get())[i];
734 :
735 19 : for (sal_uInt32 i = 0; i < pCellWidths->size() - 1; ++i)
736 : {
737 10 : nSum += (*pCellWidths.get())[i];
738 10 : pSeparators[nPos].Position = (nSum * 10000) / nFullWidthRelative; // Relative position
739 10 : pSeparators[nPos].IsVisible = sal_True;
740 10 : nPos++;
741 : }
742 :
743 18 : TablePropertyMapPtr pPropMap( new TablePropertyMap );
744 9 : pPropMap->Insert( PROP_TABLE_COLUMN_SEPARATORS, uno::makeAny( aSeparators ) );
745 : #ifdef DEBUG_DOMAINMAPPER
746 : dmapper_logger->startElement("rowProperties");
747 : pPropMap->dumpXml( dmapper_logger );
748 : dmapper_logger->endElement();
749 : #endif
750 18 : insertRowProps(pPropMap);
751 : }
752 :
753 : // Now that potentially opened table is closed, save the table properties
754 2195 : DomainMapperTableManager_Base_t::insertTableProps( pTmpTableProperties );
755 :
756 2195 : m_aTmpTableProperties.pop_back();
757 4390 : TablePropertyMapPtr pEmptyTableProps( new TablePropertyMap() );
758 2195 : m_aTmpTableProperties.push_back( pEmptyTableProps );
759 :
760 2195 : ++m_nRow;
761 2195 : m_nCell.back( ) = 0;
762 2195 : m_nCellBorderIndex = 0;
763 2195 : getCurrentGrid()->clear();
764 2195 : pCurrentSpans->clear();
765 2195 : pCellWidths->clear();
766 :
767 2195 : m_nGridBefore = m_nGridAfter = 0;
768 2195 : m_bRowSizeTypeInserted = false;
769 2195 : m_bHasBtlrCell = false;
770 4390 : m_bTableSizeTypeInserted = false;
771 :
772 : #ifdef DEBUG_DOMAINMAPPER
773 : dmapper_logger->endElement();
774 : #endif
775 2195 : }
776 :
777 :
778 3394 : void DomainMapperTableManager::clearData()
779 : {
780 3394 : m_nRow = m_nCellBorderIndex = m_nHeaderRepeat = m_nTableWidth = m_nLayoutType = 0;
781 3394 : m_sTableStyleName = OUString();
782 3394 : m_pTableStyleTextProperies.reset();
783 3394 : }
784 :
785 :
786 : }}
787 :
788 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|