1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23 #include <DomainMapperTableManager.hxx>
24 #include <resourcemodel/WW8ResourceModel.hxx>
25 #include <BorderHandler.hxx>
26 #include <CellColorHandler.hxx>
27 #include <CellMarginHandler.hxx>
28 #include <ConversionHelper.hxx>
29 #include <MeasureHandler.hxx>
30 #include <TDefTableHandler.hxx>
31 #include <com/sun/star/text/HoriOrientation.hpp>
32 #include <com/sun/star/text/SizeType.hpp>
33 #include <com/sun/star/text/TableColumnSeparator.hpp>
34 #include <com/sun/star/text/VertOrientation.hpp>
35 #include <ooxml/resourceids.hxx>
36 #include <doctok/sprmids.hxx>
37 #include <dmapperLoggers.hxx>
38
39 namespace writerfilter {
40 namespace dmapper {
41
42 using namespace ::com::sun::star;
43 using namespace ::std;
44 /*-- 23.04.2007 14:57:49---------------------------------------------------
45
46 -----------------------------------------------------------------------*/
DomainMapperTableManager(bool bOOXML)47 DomainMapperTableManager::DomainMapperTableManager(bool bOOXML) :
48 m_nCellCounterForCurrentRow(),
49 m_nGridSpanOfCurrentCell( 1 ),
50 m_nCurrentCellBorderIndex(),
51 m_nCurrentHeaderRepeatCount(),
52 m_nTableWidthOfCurrentTable(),
53 m_bOOXML( bOOXML ),
54 m_pTablePropsHandler( new TablePropertiesHandler( bOOXML ) )
55 {
56 m_pTablePropsHandler->SetTableManager( this );
57
58 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
59 #ifdef DEBUG_TABLE
60 setTagLogger(dmapper_logger);
61 #endif
62 #endif
63 }
64 /*-- 23.04.2007 14:57:49---------------------------------------------------
65
66 -----------------------------------------------------------------------*/
~DomainMapperTableManager()67 DomainMapperTableManager::~DomainMapperTableManager()
68 {
69 delete m_pTablePropsHandler;
70 m_pTablePropsHandler = NULL;
71 }
72 /*-- 23.04.2007 15:25:37---------------------------------------------------
73
74 -----------------------------------------------------------------------*/
sprm(Sprm & rSprm)75 bool DomainMapperTableManager::sprm(Sprm & rSprm)
76 {
77 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
78 dmapper_logger->startElement("tablemanager.sprm");
79 string sSprm = rSprm.toString();
80 dmapper_logger->chars(sSprm);
81 dmapper_logger->endElement("tablemanager.sprm");
82 #endif
83 bool bRet = DomainMapperTableManager_Base_t::sprm(rSprm);
84
85 if( !bRet )
86 {
87 bRet = m_pTablePropsHandler->sprm( rSprm );
88 }
89
90 if ( !bRet )
91 {
92 bRet = true;
93 const sal_uInt32 nSprmId = rSprm.getId();
94 const Value::Pointer_t pValue = rSprm.getValue();
95 const sal_Int32 nIntValue = ((pValue.get() != NULL) ? pValue->getInt() : 0);
96 switch ( nSprmId )
97 {
98 case 0xf661: //sprmTTRLeft left table indent
99 /* WRITERFILTERSTATUS: done: 100, planned: 2, spent: 0 */
100
101 case 0xf614: // sprmTTPreferredWidth - preferred table width
102 /* WRITERFILTERSTATUS: done: 100, planned: 2, spent: 0 */
103
104 case NS_ooxml::LN_CT_TblPrBase_tblW: //90722;
105 /* WRITERFILTERSTATUS: done: 100, planned: 2, spent: 0 */
106
107 case NS_ooxml::LN_CT_TblPrBase_tblInd: //90725
108 /* WRITERFILTERSTATUS: done: 100, planned: 2, spent: 0 */
109 {
110 //contains unit and value
111 writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
112 if( pProperties.get())
113 { //contains attributes x2902 (LN_unit) and x17e2 (LN_trleft)
114 MeasureHandlerPtr pMeasureHandler( new MeasureHandler );
115 pProperties->resolve(*pMeasureHandler);
116 TablePropertyMapPtr pPropMap( new TablePropertyMap );
117 if( nSprmId == 0xf661 || nSprmId == sal_uInt32(NS_ooxml::LN_CT_TblPrBase_tblInd ))
118 {
119 pPropMap->setValue( TablePropertyMap::LEFT_MARGIN, pMeasureHandler->getMeasureValue() );
120 }
121 else
122 {
123 m_nTableWidthOfCurrentTable.top() = pMeasureHandler->getMeasureValue();
124 if( m_nTableWidthOfCurrentTable.top() > 0 )
125 pPropMap->setValue( TablePropertyMap::TABLE_WIDTH, m_nTableWidthOfCurrentTable.top() );
126 }
127 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
128 dmapper_logger->addTag(pPropMap->toTag());
129 #endif
130 insertTableProps(pPropMap);
131 }
132 }
133 break;
134
135 case 0x3404:// sprmTTableHeader
136 case NS_ooxml::LN_CT_TrPrBase_tblHeader:
137 /* WRITERFILTERSTATUS: done: 100, planned: 2, spent: 0 */
138 // if nIntValue == 1 then the row is a repeated header line
139 // to prevent later rows from increasing the repeating m_nHeaderRepeat is set to NULL when repeating stops
140 if( nIntValue > 0 && m_nCurrentHeaderRepeatCount.top() >= 0 )
141 {
142 ++(m_nCurrentHeaderRepeatCount.top());
143 TablePropertyMapPtr pPropMap( new TablePropertyMap );
144 pPropMap->Insert( PROP_HEADER_ROW_COUNT, false, uno::makeAny( m_nCurrentHeaderRepeatCount.top() ));
145 insertTableProps(pPropMap);
146 }
147 else
148 m_nCurrentHeaderRepeatCount.top() = -1;
149 break;
150
151 case 0xd608: // TDefTable
152 /* WRITERFILTERSTATUS: done: 100, planned: 2, spent: 0 */
153 {
154 writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
155 if( pProperties.get())
156 {
157 TDefTableHandlerPtr pTDefTableHandler( new TDefTableHandler(m_bOOXML) );
158 pProperties->resolve( *pTDefTableHandler );
159
160 TablePropertyMapPtr pRowPropMap( new TablePropertyMap );
161 pRowPropMap->insert( pTDefTableHandler->getRowProperties() );
162 insertRowProps( pRowPropMap );
163 if( m_nTableWidthOfCurrentTable.top() == 0 )
164 {
165 m_nTableWidthOfCurrentTable.top() = pTDefTableHandler->getTableWidth();
166 if( m_nTableWidthOfCurrentTable.top() > 0 )
167 {
168 TablePropertyMapPtr pPropMap( new TablePropertyMap );
169 pPropMap->setValue( TablePropertyMap::TABLE_WIDTH, m_nTableWidthOfCurrentTable.top() );
170 insertTableProps(pPropMap);
171 }
172 }
173 for( size_t nCell = 0; nCell < pTDefTableHandler->getCellCount(); ++nCell )
174 {
175 TablePropertyMapPtr pCellPropMap( new TablePropertyMap );
176 pTDefTableHandler->fillCellProperties( nCell, pCellPropMap );
177 cellPropsByCell( nCell, pCellPropMap );
178 }
179 }
180 }
181 break;
182
183 case 0xD605: // sprmTTableBorders
184 /* WRITERFILTERSTATUS: done: 100, planned: 2, spent: 0 */
185 {
186 writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
187 if( pProperties.get())
188 {
189 BorderHandlerPtr pBorderHandler( new BorderHandler(m_bOOXML) );
190 pProperties->resolve(*pBorderHandler);
191 TablePropertyMapPtr pCellPropMap( new TablePropertyMap() );
192 pCellPropMap->insert( pBorderHandler->getProperties() );
193 cellPropsByCell( m_nCurrentCellBorderIndex.top(), pCellPropMap );
194 ++(m_nCurrentCellBorderIndex.top());
195 }
196 }
197 break;
198
199 case 0xd632 : //sprmTNewSpacing
200 /* WRITERFILTERSTATUS: done: 0, planned: 2, spent: 0 */
201
202 case 0xd634 : //sprmTNewSpacing
203 /* WRITERFILTERSTATUS: done: 0, planned: 2, spent: 0 */
204 //TODO: sprms contain default (TNew) and actual border spacing of cells - not resolvable yet
205 break;
206
207 case 0xd613: //sprmTGridLineProps
208 /* WRITERFILTERSTATUS: done: 0, planned: 2, spent: 0 */
209 // TODO: needs a handler
210 /*contains:
211 GridLineProps">
212 rtf:LINEPROPSTOP
213 rtf:LINEPROPSLEFT
214 rtf:LINEPROPSBOTTOM
215 rtf:LINEPROPSRIGHT
216 rtf:LINEPROPSHORIZONTAL
217 rtf:LINEPROPSVERTICAL
218 rtf:LINECOLOR
219 rtf:LINEWIDTH
220 rtf:LINETYPE
221
222 */
223 break;
224
225 case 0x740a : //sprmTTlp
226 /* WRITERFILTERSTATUS: done: 0, planned: 2, spent: 0 */
227 //TODO: Table look specifier
228 break;
229
230 case 0x6816 : //unknown
231 case 0x3466 : //unknown
232 case 0x3615 : //unknown
233 case 0x646b : //unknown - expandable sprm - see ww8scan.cxx
234 case 0x7479 : //unknown
235 case 0xf617 : //unknown
236 case 0xf618 : //unknown
237 /* WRITERFILTERSTATUS: done: 100, planned: 2, spent: 0 */
238 bRet = false;
239 break;
240
241 case NS_ooxml::LN_CT_TblPrBase_tblStyle: //table style name
242 /* WRITERFILTERSTATUS: done: 100, planned: 2, spent: 0 */
243 {
244 TablePropertyMapPtr pPropMap( new TablePropertyMap );
245 pPropMap->Insert( META_PROP_TABLE_STYLE_NAME, false, uno::makeAny( pValue->getString() ));
246 insertTableProps(pPropMap);
247 }
248 break;
249
250 case NS_ooxml::LN_CT_TblGridBase_gridCol:
251 /* WRITERFILTERSTATUS: done: 100, planned: 2, spent: 0 */
252 {
253 getCurrentGrid()->push_back( ConversionHelper::convertTwipToMM100( nIntValue ) );
254 }
255 break;
256
257 case NS_ooxml::LN_CT_TcPrBase_vMerge : //vertical merge
258 /* WRITERFILTERSTATUS: done: 100, planned: 2, spent: 0 */
259 {
260 // values can be: LN_Value_ST_Merge_restart, LN_Value_ST_Merge_continue, in reality the second one is a 0
261 TablePropertyMapPtr pMergeProps( new TablePropertyMap );
262 pMergeProps->Insert( PROP_VERTICAL_MERGE, false, uno::makeAny( bool( sal::static_int_cast<Id>(nIntValue) == NS_ooxml::LN_Value_ST_Merge_restart )) );
263 cellProps( pMergeProps);
264 }
265 break;
266
267 case NS_ooxml::LN_CT_TcPrBase_gridSpan: //number of grid positions spanned by this cell
268 /* WRITERFILTERSTATUS: done: 100, planned: 2, spent: 0 */
269 {
270 #if DEBUG_DMAPPER_TABLE_HANDLER
271 dmapper_logger->startElement("tablemanager.GridSpan");
272 dmapper_logger->attribute("gridSpan", nIntValue);
273 dmapper_logger->endElement("tablemanager.GridSpan");
274 #endif
275 m_nGridSpanOfCurrentCell = nIntValue;
276 }
277 break;
278 case NS_ooxml::LN_CT_TblPrBase_tblLook:
279 /* WRITERFILTERSTATUS: done: 0, planned: 2, spent: 0 */
280 break; //todo: table look specifier
281
282 case NS_ooxml::LN_CT_TcPrBase_tcW:
283 /* WRITERFILTERSTATUS: done: 100, planned: 0.5, spent: 0 */
284 break; //fixed column width is not supported
285
286 case NS_ooxml::LN_CT_TrPrBase_cnfStyle:
287 /* WRITERFILTERSTATUS: done: 100, planned: 0.5, spent: 0 */
288 {
289 TablePropertyMapPtr pProps( new TablePropertyMap );
290 pProps->Insert( PROP_CNF_STYLE, true, uno::makeAny( pValue->getString( ) ) );
291 insertRowProps( pProps );
292 }
293 break;
294
295 case NS_ooxml::LN_CT_PPrBase_cnfStyle:
296 /* WRITERFILTERSTATUS: done: 0, planned: 0.5, spent: 0 */
297 // TODO cnfStyle on a paragraph
298 break;
299
300 case NS_ooxml::LN_CT_TcPrBase_cnfStyle:
301 /* WRITERFILTERSTATUS: done: 100, planned: 0.5, spent: 0 */
302 {
303 TablePropertyMapPtr pProps( new TablePropertyMap );
304 pProps->Insert( PROP_CNF_STYLE, true, uno::makeAny( pValue->getString( ) ) );
305 cellProps( pProps );
306 }
307 break;
308
309 default:
310 bRet = false;
311
312 #ifdef DEBUG_DOMAINMAPPER
313 dmapper_logger->element("TableManager.unhandled");
314 #endif
315 }
316 }
317 return bRet;
318 }
319
320
pushStackOfMembers()321 void DomainMapperTableManager::pushStackOfMembers()
322 {
323 m_nCellCounterForCurrentRow.push( 0 );
324 m_nCurrentCellBorderIndex.push( 0 );
325 m_nCurrentHeaderRepeatCount.push( 0 );
326 m_nTableWidthOfCurrentTable.push( 0 );
327
328 IntVectorPtr pNewGrid( new vector<sal_Int32> );
329 IntVectorPtr pNewSpans( new vector<sal_Int32> );
330 m_aTableGrid.push( pNewGrid );
331 m_aGridSpans.push( pNewSpans );
332 }
333
334
popStackOfMembers()335 void DomainMapperTableManager::popStackOfMembers()
336 {
337 if (!m_nCellCounterForCurrentRow.empty()) {
338 m_nCellCounterForCurrentRow.pop();
339 }
340 if (!m_nCurrentCellBorderIndex.empty()) {
341 m_nCurrentCellBorderIndex.pop();
342 }
343 if (!m_nCurrentHeaderRepeatCount.empty()) {
344 m_nCurrentHeaderRepeatCount.pop();
345 }
346 if (!m_nTableWidthOfCurrentTable.empty()) {
347 m_nTableWidthOfCurrentTable.pop();
348 }
349
350 if (!m_aTableGrid.empty()) {
351 m_aTableGrid.pop();
352 }
353 if (!m_aGridSpans.empty()) {
354 m_aGridSpans.pop();
355 }
356 }
357
358
getCurrentGrid()359 boost::shared_ptr< vector<sal_Int32> > DomainMapperTableManager::getCurrentGrid()
360 {
361 return m_aTableGrid.top();
362 }
363
getCurrentSpans()364 boost::shared_ptr< vector< sal_Int32 > > DomainMapperTableManager::getCurrentSpans()
365 {
366 return m_aGridSpans.top();
367 }
368
369
SetStyleProperties(PropertyMapPtr pProperties)370 void DomainMapperTableManager::SetStyleProperties(
371 PropertyMapPtr pProperties )
372 {
373 m_pStyleProps = pProperties;
374 if ( m_pStyleProps.get() )
375 {
376 pushStackOfMembers();
377 }
378 else
379 {
380 popStackOfMembers();
381 }
382 };
383
384
startLevel()385 void DomainMapperTableManager::startLevel()
386 {
387 DomainMapperTableManager_Base_t::startLevel();
388
389 pushStackOfMembers();
390 }
391
endLevel()392 void DomainMapperTableManager::endLevel()
393 {
394 popStackOfMembers();
395
396 DomainMapperTableManager_Base_t::endLevel();
397
398 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
399 dmapper_logger->startElement("dmappertablemanager.endLevel");
400 PropertyMapPtr pProps = getTableProps();
401 if (pProps.get() != NULL)
402 dmapper_logger->addTag(getTableProps()->toTag());
403
404 dmapper_logger->endElement("dmappertablemanager.endLevel");
405 #endif
406 }
407
408 /*-- 02.05.2007 14:36:26---------------------------------------------------
409
410 -----------------------------------------------------------------------*/
endOfCellAction()411 void DomainMapperTableManager::endOfCellAction()
412 {
413 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
414 dmapper_logger->element("endOFCellAction");
415 #endif
416
417 getCurrentSpans()->push_back( m_nGridSpanOfCurrentCell );
418 m_nGridSpanOfCurrentCell = 1;
419 ++(m_nCellCounterForCurrentRow.top());
420 }
421 /*-- 02.05.2007 14:36:26---------------------------------------------------
422
423 -----------------------------------------------------------------------*/
endOfRowAction()424 void DomainMapperTableManager::endOfRowAction()
425 {
426 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
427 dmapper_logger->startElement("endOfRowAction");
428 #endif
429
430 IntVectorPtr pTableGrid = getCurrentGrid( );
431 if( m_nTableWidthOfCurrentTable.top() == 0
432 && pTableGrid->size() > 0 )
433 {
434 ::std::vector<sal_Int32>::const_iterator aCellIter = pTableGrid->begin();
435
436 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
437 dmapper_logger->startElement("tableWidth");
438 #endif
439
440 while( aCellIter != pTableGrid->end() )
441 {
442 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
443 dmapper_logger->startElement("col");
444 dmapper_logger->attribute("width", *aCellIter);
445 dmapper_logger->endElement("col");
446 #endif
447
448 m_nTableWidthOfCurrentTable.top() += *aCellIter++;
449 }
450
451 if( m_nTableWidthOfCurrentTable.top() > 0)
452 {
453 TablePropertyMapPtr pPropMap( new TablePropertyMap );
454 pPropMap->setValue( TablePropertyMap::TABLE_WIDTH, m_nTableWidthOfCurrentTable.top() );
455 insertTableProps(pPropMap);
456 }
457
458 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
459 dmapper_logger->endElement("tableWidth");
460 #endif
461 }
462
463 IntVectorPtr pCurrentSpans = getCurrentSpans( );
464 if( pCurrentSpans->size() < m_nCellCounterForCurrentRow.top() )
465 {
466 //fill missing elements with '1'
467 pCurrentSpans->insert( pCurrentSpans->end( ), m_nCellCounterForCurrentRow.top() - pCurrentSpans->size(), 1 );
468 }
469
470 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
471 dmapper_logger->startElement("gridSpans");
472 {
473 ::std::vector<sal_Int32>::const_iterator aGridSpanIter = pCurrentSpans->begin();
474 ::std::vector<sal_Int32>::const_iterator aGridSpanIterEnd = pCurrentSpans->end();
475
476 while (aGridSpanIter != aGridSpanIterEnd)
477 {
478 dmapper_logger->startElement("gridSpan");
479 dmapper_logger->attribute("span", *aGridSpanIter);
480 dmapper_logger->endElement("gridSpan");
481
482 aGridSpanIter++;
483 }
484 }
485 dmapper_logger->endElement("gridSpans");
486 #endif
487
488 //calculate number of used grids - it has to match the size of m_aTableGrid
489 size_t nGrids = 0;
490 ::std::vector<sal_Int32>::const_iterator aGridSpanIter = pCurrentSpans->begin();
491 for( ; aGridSpanIter != pCurrentSpans->end(); ++aGridSpanIter)
492 nGrids += *aGridSpanIter;
493
494 if( pTableGrid->size() == nGrids )
495 {
496 //determine table width
497 double nFullWidth = m_nTableWidthOfCurrentTable.top();
498 //the positions have to be distibuted in a range of 10000
499 const double nFullWidthRelative = 10000.;
500 uno::Sequence< text::TableColumnSeparator > aSeparators( m_nCellCounterForCurrentRow.top() - 1 );
501 text::TableColumnSeparator* pSeparators = aSeparators.getArray();
502 sal_Int16 nLastRelPos = 0;
503 sal_uInt32 nBorderGridIndex = 0;
504
505 ::std::vector< sal_Int32 >::const_iterator aSpansIter = pCurrentSpans->begin( );
506 for( sal_uInt32 nBorder = 0; nBorder < m_nCellCounterForCurrentRow.top() - 1; ++nBorder )
507 {
508 sal_Int32 nGridCount = *aSpansIter;
509 double fGridWidth = 0.;
510 do
511 {
512 fGridWidth += (*pTableGrid.get())[nBorderGridIndex++];
513 }while( --nGridCount );
514
515 sal_Int16 nRelPos =
516 sal::static_int_cast< sal_Int16 >(fGridWidth * nFullWidthRelative / nFullWidth );
517
518 pSeparators[nBorder].Position = nRelPos + nLastRelPos;
519 pSeparators[nBorder].IsVisible = sal_True;
520 nLastRelPos = nLastRelPos + nRelPos;
521 aSpansIter++;
522 }
523 TablePropertyMapPtr pPropMap( new TablePropertyMap );
524 pPropMap->Insert( PROP_TABLE_COLUMN_SEPARATORS, false, uno::makeAny( aSeparators ) );
525
526 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
527 dmapper_logger->startElement("rowProperties");
528 dmapper_logger->addTag(pPropMap->toTag());
529 dmapper_logger->endElement("rowProperties");
530 #endif
531 insertRowProps(pPropMap);
532 }
533
534 m_nCellCounterForCurrentRow.top() = 0;
535 m_nCurrentCellBorderIndex.top() = 0;
536 pCurrentSpans->clear();
537
538 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
539 dmapper_logger->endElement("endOfRowAction");
540 #endif
541 }
542
543
544 }}
545