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 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_xmloff.hxx"
26 #include "PageMasterExportPropMapper.hxx"
27 #include <xmloff/xmltoken.hxx>
28 #include <comphelper/types.hxx>
29 #include <com/sun/star/table/BorderLine.hpp>
30 #include <xmloff/PageMasterStyleMap.hxx>
31 #include <tools/debug.hxx>
32 #include <rtl/ustrbuf.hxx>
33 #include <comphelper/extract.hxx>
34 
35 using namespace ::com::sun::star;
36 using namespace ::com::sun::star::uno;
37 using namespace ::com::sun::star::beans;
38 using namespace ::comphelper;
39 using namespace ::xmloff::token;
40 
41 
42 //______________________________________________________________________________
43 
44 inline sal_Bool lcl_HasSameLineWidth( const table::BorderLine& rLine1, const table::BorderLine& rLine2 )
45 {
46 	return	(rLine1.InnerLineWidth == rLine2.InnerLineWidth) &&
47 			(rLine1.OuterLineWidth == rLine2.OuterLineWidth) &&
48 			(rLine1.LineDistance == rLine2.LineDistance);
49 }
50 
51 inline sal_Bool operator==( const table::BorderLine& rLine1, const table::BorderLine& rLine2 )
52 {
53 	return	(rLine1.Color == rLine2.Color) &&
54 			lcl_HasSameLineWidth( rLine1, rLine2 );
55 }
56 
57 inline void lcl_RemoveState( XMLPropertyState* pState )
58 {
59 	pState->mnIndex = -1;
60 	pState->maValue.clear();
61 }
62 
63 void lcl_RemoveStateIfZero16( XMLPropertyState* pState )
64 {
65 	sal_Int16	nValue = sal_Int16();
66 	if( (pState->maValue >>= nValue) && !nValue )
67 		lcl_RemoveState( pState );
68 }
69 
70 void lcl_AddState(::std::vector< XMLPropertyState >& rPropState, sal_Int32 nIndex, const rtl::OUString& rProperty, uno::Reference< beans::XPropertySet >& xProps)
71 {
72     if(::cppu::any2bool(xProps->getPropertyValue(rProperty)))
73         rPropState.push_back(XMLPropertyState (nIndex, cppu::bool2any(sal_True)));
74 }
75 
76 //______________________________________________________________________________
77 // helper struct to handle equal XMLPropertyState's for page, header and footer
78 
79 struct XMLPropertyStateBuffer
80 {
81     XMLPropertyState*       pPMMarginAll;
82     XMLPropertyState*       pPMMarginTop;
83     XMLPropertyState*       pPMMarginBottom;
84     XMLPropertyState*       pPMMarginLeft;
85     XMLPropertyState*       pPMMarginRight;
86 
87 	XMLPropertyState*		pPMBorderAll;
88 	XMLPropertyState*		pPMBorderTop;
89 	XMLPropertyState*		pPMBorderBottom;
90 	XMLPropertyState*		pPMBorderLeft;
91 	XMLPropertyState*		pPMBorderRight;
92 
93 	XMLPropertyState*		pPMBorderWidthAll;
94 	XMLPropertyState*		pPMBorderWidthTop;
95 	XMLPropertyState*		pPMBorderWidthBottom;
96 	XMLPropertyState*		pPMBorderWidthLeft;
97 	XMLPropertyState*		pPMBorderWidthRight;
98 
99 	XMLPropertyState*		pPMPaddingAll;
100 	XMLPropertyState*		pPMPaddingTop;
101 	XMLPropertyState*		pPMPaddingBottom;
102 	XMLPropertyState*		pPMPaddingLeft;
103 	XMLPropertyState*		pPMPaddingRight;
104 
105 							XMLPropertyStateBuffer();
106 	void					ContextFilter( ::std::vector< XMLPropertyState >& rPropState );
107 };
108 
109 XMLPropertyStateBuffer::XMLPropertyStateBuffer()
110     :   pPMMarginAll( NULL )
111     ,   pPMMarginTop( NULL )
112     ,   pPMMarginBottom( NULL )
113     ,   pPMMarginLeft( NULL )
114     ,   pPMMarginRight( NULL )
115     ,
116 		pPMBorderAll( NULL ),
117 		pPMBorderTop( NULL ),
118 		pPMBorderBottom( NULL ),
119 		pPMBorderLeft( NULL ),
120 		pPMBorderRight( NULL ),
121 
122 		pPMBorderWidthAll( NULL ),
123 		pPMBorderWidthTop( NULL ),
124 		pPMBorderWidthBottom( NULL ),
125 		pPMBorderWidthLeft( NULL ),
126 		pPMBorderWidthRight( NULL ),
127 
128 		pPMPaddingAll( NULL ),
129 		pPMPaddingTop( NULL ),
130 		pPMPaddingBottom( NULL ),
131 		pPMPaddingLeft( NULL ),
132 		pPMPaddingRight( NULL )
133 {
134 }
135 
136 void XMLPropertyStateBuffer::ContextFilter( ::std::vector< XMLPropertyState >& )
137 {
138     if (pPMMarginAll)
139     {
140         lcl_RemoveState(pPMMarginAll); // #i117696# do not write fo:margin
141     }
142 
143 	if( pPMBorderAll )
144 	{
145 		if( pPMBorderTop && pPMBorderBottom && pPMBorderLeft && pPMBorderRight )
146 		{
147 			table::BorderLine aLineTop, aLineBottom, aLineLeft, aLineRight;
148 
149 			pPMBorderTop->maValue >>= aLineTop;
150 			pPMBorderBottom->maValue >>= aLineBottom;
151 			pPMBorderLeft->maValue >>= aLineLeft;
152 			pPMBorderRight->maValue >>= aLineRight;
153 
154 			if( (aLineTop == aLineBottom) && (aLineBottom == aLineLeft) && (aLineLeft == aLineRight) )
155 			{
156 				lcl_RemoveState( pPMBorderTop );
157 				lcl_RemoveState( pPMBorderBottom );
158 				lcl_RemoveState( pPMBorderLeft );
159 				lcl_RemoveState( pPMBorderRight );
160 			}
161 			else
162 				lcl_RemoveState( pPMBorderAll );
163 		}
164 		else
165 			lcl_RemoveState( pPMBorderAll );
166 	}
167 
168 	if( pPMBorderWidthAll )
169 	{
170 		if( pPMBorderWidthTop && pPMBorderWidthBottom && pPMBorderWidthLeft && pPMBorderWidthRight )
171 		{
172 			table::BorderLine aLineTop, aLineBottom, aLineLeft, aLineRight;
173 
174 			pPMBorderWidthTop->maValue >>= aLineTop;
175 			pPMBorderWidthBottom->maValue >>= aLineBottom;
176 			pPMBorderWidthLeft->maValue >>= aLineLeft;
177 			pPMBorderWidthRight->maValue >>= aLineRight;
178 
179 			if( lcl_HasSameLineWidth( aLineTop, aLineBottom ) &&
180 				lcl_HasSameLineWidth( aLineBottom, aLineLeft ) &&
181 				lcl_HasSameLineWidth( aLineLeft, aLineRight ) )
182 			{
183 				lcl_RemoveState( pPMBorderWidthTop );
184 				lcl_RemoveState( pPMBorderWidthBottom );
185 				lcl_RemoveState( pPMBorderWidthLeft );
186 				lcl_RemoveState( pPMBorderWidthRight );
187 			}
188 			else
189 				lcl_RemoveState( pPMBorderWidthAll );
190 		}
191 		else
192 			lcl_RemoveState( pPMBorderWidthAll );
193 	}
194 
195 	if( pPMPaddingAll )
196 	{
197 		if( pPMPaddingTop && pPMPaddingBottom && pPMPaddingLeft && pPMPaddingRight )
198 		{
199 			sal_Int32 nTop = 0, nBottom = 0, nLeft = 0, nRight = 0;
200 
201 			pPMPaddingTop->maValue >>= nTop;
202 			pPMPaddingBottom->maValue >>= nBottom;
203 			pPMPaddingLeft->maValue >>= nLeft;
204 			pPMPaddingRight->maValue >>= nRight;
205 
206 			if( (nTop == nBottom) && (nBottom == nLeft) && (nLeft == nRight) )
207 			{
208 				lcl_RemoveState( pPMPaddingTop );
209 				lcl_RemoveState( pPMPaddingBottom );
210 				lcl_RemoveState( pPMPaddingLeft );
211 				lcl_RemoveState( pPMPaddingRight );
212 			}
213 			else
214 				lcl_RemoveState( pPMPaddingAll );
215 		}
216 		else
217 			lcl_RemoveState( pPMPaddingAll );
218 	}
219 }
220 
221 //______________________________________________________________________________
222 
223 XMLPageMasterExportPropMapper::XMLPageMasterExportPropMapper(
224 		const UniReference< XMLPropertySetMapper >& rMapper,
225 		SvXMLExport& rExport ) :
226 	SvXMLExportPropertyMapper( rMapper ),
227 	aBackgroundImageExport( rExport ),
228 	aTextColumnsExport( rExport ),
229 	aFootnoteSeparatorExport( rExport )
230 {
231 }
232 
233 XMLPageMasterExportPropMapper::~XMLPageMasterExportPropMapper()
234 {
235 }
236 
237 void XMLPageMasterExportPropMapper::handleElementItem(
238         SvXMLExport&,
239 		const XMLPropertyState& rProperty,
240 		sal_uInt16 /*nFlags*/,
241 		const ::std::vector< XMLPropertyState >* pProperties,
242 		sal_uInt32 nIdx ) const
243 {
244 	XMLPageMasterExportPropMapper* pThis = (XMLPageMasterExportPropMapper*) this;
245 
246 	sal_uInt32 nContextId = getPropertySetMapper()->GetEntryContextId( rProperty.mnIndex );
247 	switch( nContextId )
248 	{
249 		case CTF_PM_GRAPHICURL:
250 		case CTF_PM_HEADERGRAPHICURL:
251 		case CTF_PM_FOOTERGRAPHICURL:
252 			{
253 				DBG_ASSERT( pProperties && (nIdx >= 2), "property vector missing" );
254 				sal_Int32 nPos;
255 				sal_Int32 nFilter;
256 				switch( nContextId  )
257 				{
258 				case CTF_PM_GRAPHICURL:
259 					nPos = CTF_PM_GRAPHICPOSITION;
260 					nFilter = CTF_PM_GRAPHICFILTER;
261 					break;
262 				case CTF_PM_HEADERGRAPHICURL:
263 					nPos = CTF_PM_HEADERGRAPHICPOSITION;
264 					nFilter = CTF_PM_HEADERGRAPHICFILTER;
265 					break;
266 				case CTF_PM_FOOTERGRAPHICURL:
267 					nPos = CTF_PM_FOOTERGRAPHICPOSITION;
268 					nFilter = CTF_PM_FOOTERGRAPHICFILTER;
269 					break;
270 				default:
271 					nPos = 0;  // TODO What values should this be?
272 					nFilter = 0;
273 				}
274 				const Any*	pPos	= NULL;
275 				const Any*	pFilter	= NULL;
276 				if( pProperties && (nIdx >= 2) )
277 				{
278 					const XMLPropertyState& rPos = (*pProperties)[nIdx - 2];
279 					DBG_ASSERT( getPropertySetMapper()->GetEntryContextId( rPos.mnIndex ) == nPos,
280 								"invalid property map: pos expected" );
281 					if( getPropertySetMapper()->GetEntryContextId( rPos.mnIndex ) == nPos )
282 						pPos = &rPos.maValue;
283 
284 					const XMLPropertyState& rFilter = (*pProperties)[nIdx - 1];
285 					DBG_ASSERT( getPropertySetMapper()->GetEntryContextId( rFilter.mnIndex ) == nFilter,
286 								"invalid property map: filter expected" );
287 					if( getPropertySetMapper()->GetEntryContextId( rFilter.mnIndex ) == nFilter )
288 						pFilter = &rFilter.maValue;
289 				}
290 				sal_uInt32 nPropIndex = rProperty.mnIndex;
291 				pThis->aBackgroundImageExport.exportXML( rProperty.maValue, pPos, pFilter, NULL,
292 					getPropertySetMapper()->GetEntryNameSpace( nPropIndex ),
293 					getPropertySetMapper()->GetEntryXMLName( nPropIndex ) );
294 			}
295 			break;
296 		case CTF_PM_TEXTCOLUMNS:
297 			pThis->aTextColumnsExport.exportXML( rProperty.maValue );
298 			break;
299 		case CTF_PM_FTN_LINE_WEIGTH:
300 			pThis->aFootnoteSeparatorExport.exportXML( pProperties, nIdx,
301 													   getPropertySetMapper());
302 			break;
303 	}
304 }
305 
306 void XMLPageMasterExportPropMapper::handleSpecialItem(
307 		SvXMLAttributeList&,
308 		const XMLPropertyState&,
309 		const SvXMLUnitConverter&,
310 		const SvXMLNamespaceMap&,
311 		const ::std::vector< XMLPropertyState >*,
312 		sal_uInt32 /*nIdx*/) const
313 {
314 }
315 
316 void XMLPageMasterExportPropMapper::ContextFilter(
317 		::std::vector< XMLPropertyState >& rPropState,
318 		Reference< XPropertySet > rPropSet ) const
319 {
320 	XMLPropertyStateBuffer	aPageBuffer;
321 	XMLPropertyStateBuffer	aHeaderBuffer;
322 	XMLPropertyStateBuffer	aFooterBuffer;
323 
324 	XMLPropertyState*		pPMHeaderHeight		= NULL;
325 	XMLPropertyState*		pPMHeaderMinHeight	= NULL;
326 	XMLPropertyState*		pPMHeaderDynamic	= NULL;
327 
328 	XMLPropertyState*		pPMFooterHeight		= NULL;
329 	XMLPropertyState*		pPMFooterMinHeight	= NULL;
330 	XMLPropertyState*		pPMFooterDynamic	= NULL;
331 
332 	XMLPropertyState*		pPMScaleTo			= NULL;
333 	XMLPropertyState*		pPMScaleToPages		= NULL;
334 	XMLPropertyState*		pPMScaleToX 		= NULL;
335 	XMLPropertyState*		pPMScaleToY	    	= NULL;
336 	XMLPropertyState*		pPMStandardMode    	= NULL;
337 	XMLPropertyState*		pPMGridBaseWidth   	= NULL;
338 	XMLPropertyState*		pPMGridSnapToChars 	= NULL;
339 
340     XMLPropertyState*       pPrint              = NULL;
341 
342     UniReference < XMLPropertySetMapper > aPropMapper(getPropertySetMapper());
343 
344 	for( ::std::vector< XMLPropertyState >::iterator aIter = rPropState.begin(); aIter != rPropState.end(); ++aIter )
345 	{
346         XMLPropertyState *pProp = &(*aIter);
347 		sal_Int16 nContextId	= aPropMapper->GetEntryContextId( pProp->mnIndex );
348 		sal_Int16 nFlag			= nContextId & CTF_PM_FLAGMASK;
349 		sal_Int16 nSimpleId		= nContextId & (~CTF_PM_FLAGMASK | XML_PM_CTF_START);
350         sal_Int16 nPrintId      = nContextId & CTF_PM_PRINTMASK;
351 
352 		XMLPropertyStateBuffer* pBuffer;
353 		switch( nFlag )
354 		{
355 			case CTF_PM_HEADERFLAG:			pBuffer = &aHeaderBuffer;	break;
356 			case CTF_PM_FOOTERFLAG:			pBuffer = &aFooterBuffer;	break;
357 			default:						pBuffer = &aPageBuffer;		break;
358 		}
359 
360 		switch( nSimpleId )
361 		{
362             case CTF_PM_MARGINALL:          pBuffer->pPMMarginAll           = pProp;    break;
363             case CTF_PM_MARGINTOP:          pBuffer->pPMMarginTop           = pProp;    break;
364             case CTF_PM_MARGINBOTTOM:       pBuffer->pPMMarginBottom        = pProp;    break;
365             case CTF_PM_MARGINLEFT:         pBuffer->pPMMarginLeft          = pProp;    break;
366             case CTF_PM_MARGINRIGHT:        pBuffer->pPMMarginRight         = pProp;    break;
367 			case CTF_PM_BORDERALL:			pBuffer->pPMBorderAll			= pProp;	break;
368 			case CTF_PM_BORDERTOP:			pBuffer->pPMBorderTop			= pProp;	break;
369 			case CTF_PM_BORDERBOTTOM:		pBuffer->pPMBorderBottom		= pProp;	break;
370 			case CTF_PM_BORDERLEFT:			pBuffer->pPMBorderLeft			= pProp;	break;
371 			case CTF_PM_BORDERRIGHT:		pBuffer->pPMBorderRight			= pProp;	break;
372 			case CTF_PM_BORDERWIDTHALL:		pBuffer->pPMBorderWidthAll		= pProp;	break;
373 			case CTF_PM_BORDERWIDTHTOP:		pBuffer->pPMBorderWidthTop		= pProp;	break;
374 			case CTF_PM_BORDERWIDTHBOTTOM:	pBuffer->pPMBorderWidthBottom	= pProp;	break;
375 			case CTF_PM_BORDERWIDTHLEFT:	pBuffer->pPMBorderWidthLeft		= pProp;	break;
376 			case CTF_PM_BORDERWIDTHRIGHT:	pBuffer->pPMBorderWidthRight	= pProp;	break;
377 			case CTF_PM_PADDINGALL:			pBuffer->pPMPaddingAll			= pProp;	break;
378 			case CTF_PM_PADDINGTOP:			pBuffer->pPMPaddingTop			= pProp;	break;
379 			case CTF_PM_PADDINGBOTTOM:		pBuffer->pPMPaddingBottom		= pProp;	break;
380 			case CTF_PM_PADDINGLEFT:		pBuffer->pPMPaddingLeft			= pProp;	break;
381 			case CTF_PM_PADDINGRIGHT:		pBuffer->pPMPaddingRight		= pProp;	break;
382 		}
383 
384 		switch( nContextId )
385 		{
386 			case CTF_PM_HEADERHEIGHT:		pPMHeaderHeight		= pProp;	break;
387 			case CTF_PM_HEADERMINHEIGHT:	pPMHeaderMinHeight	= pProp;	break;
388 			case CTF_PM_HEADERDYNAMIC:		pPMHeaderDynamic	= pProp;	break;
389 			case CTF_PM_FOOTERHEIGHT:		pPMFooterHeight		= pProp;	break;
390 			case CTF_PM_FOOTERMINHEIGHT:	pPMFooterMinHeight	= pProp;	break;
391 			case CTF_PM_FOOTERDYNAMIC:		pPMFooterDynamic	= pProp;	break;
392 			case CTF_PM_SCALETO:			pPMScaleTo			= pProp;	break;
393 			case CTF_PM_SCALETOPAGES:		pPMScaleToPages		= pProp;	break;
394             case CTF_PM_SCALETOX:   		pPMScaleToX 		= pProp;	break;
395             case CTF_PM_SCALETOY:   		pPMScaleToY 		= pProp;	break;
396             case CTF_PM_STANDARD_MODE:		pPMStandardMode		= pProp;	break;
397             case CTP_PM_GRID_BASE_WIDTH:		pPMGridBaseWidth	= pProp;	break;
398             case CTP_PM_GRID_SNAP_TO_CHARS:		pPMGridSnapToChars	= pProp;	break;
399 		}
400         if (nPrintId == CTF_PM_PRINTMASK)
401         {
402             pPrint = pProp;
403             lcl_RemoveState(pPrint);
404         }
405 	}
406 
407 	if( pPMStandardMode && !getBOOL(pPMStandardMode->maValue) )
408 	{
409 		lcl_RemoveState(pPMStandardMode);
410 		if( pPMGridBaseWidth )
411 			lcl_RemoveState(pPMGridBaseWidth);
412 		if( pPMGridSnapToChars )
413 			lcl_RemoveState(pPMGridSnapToChars);
414 	}
415 
416 	if( pPMGridBaseWidth && pPMStandardMode )
417 		lcl_RemoveState(pPMStandardMode);
418 
419 	aPageBuffer.ContextFilter( rPropState );
420 	aHeaderBuffer.ContextFilter( rPropState );
421 	aFooterBuffer.ContextFilter( rPropState );
422 
423 	if( pPMHeaderHeight && (!pPMHeaderDynamic || (pPMHeaderDynamic && getBOOL( pPMHeaderDynamic->maValue ))) )
424 		lcl_RemoveState( pPMHeaderHeight );
425 	if( pPMHeaderMinHeight && pPMHeaderDynamic && !getBOOL( pPMHeaderDynamic->maValue ) )
426 		lcl_RemoveState( pPMHeaderMinHeight );
427 	if( pPMHeaderDynamic )
428 		lcl_RemoveState( pPMHeaderDynamic );
429 
430 	if( pPMFooterHeight && (!pPMFooterDynamic || (pPMFooterDynamic && getBOOL( pPMFooterDynamic->maValue ))) )
431 		lcl_RemoveState( pPMFooterHeight );
432 	if( pPMFooterMinHeight && pPMFooterDynamic && !getBOOL( pPMFooterDynamic->maValue ) )
433 		lcl_RemoveState( pPMFooterMinHeight );
434 	if( pPMFooterDynamic )
435 		lcl_RemoveState( pPMFooterDynamic );
436 
437 	if( pPMScaleTo )
438 		lcl_RemoveStateIfZero16( pPMScaleTo );
439 	if( pPMScaleToPages )
440 		lcl_RemoveStateIfZero16( pPMScaleToPages );
441 	if( pPMScaleToX )
442 		lcl_RemoveStateIfZero16( pPMScaleToX );
443 	if( pPMScaleToY )
444 		lcl_RemoveStateIfZero16( pPMScaleToY );
445 
446     if (pPrint)
447     {
448         lcl_AddState(rPropState, aPropMapper->FindEntryIndex(CTF_PM_PRINT_ANNOTATIONS), rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("PrintAnnotations")), rPropSet);
449         lcl_AddState(rPropState, aPropMapper->FindEntryIndex(CTF_PM_PRINT_CHARTS), rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("PrintCharts")), rPropSet);
450         lcl_AddState(rPropState, aPropMapper->FindEntryIndex(CTF_PM_PRINT_DRAWING), rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("PrintDrawing")), rPropSet);
451         lcl_AddState(rPropState, aPropMapper->FindEntryIndex(CTF_PM_PRINT_FORMULAS), rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("PrintFormulas")), rPropSet);
452         lcl_AddState(rPropState, aPropMapper->FindEntryIndex(CTF_PM_PRINT_GRID), rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("PrintGrid")), rPropSet);
453         lcl_AddState(rPropState, aPropMapper->FindEntryIndex(CTF_PM_PRINT_HEADERS), rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("PrintHeaders")), rPropSet);
454         lcl_AddState(rPropState, aPropMapper->FindEntryIndex(CTF_PM_PRINT_OBJECTS), rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("PrintObjects")), rPropSet);
455         lcl_AddState(rPropState, aPropMapper->FindEntryIndex(CTF_PM_PRINT_ZEROVALUES), rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("PrintZeroValues")), rPropSet);
456     }
457 
458 	SvXMLExportPropertyMapper::ContextFilter(rPropState,rPropSet);
459 }
460 
461