xref: /trunk/main/xmloff/source/style/XMLBackgroundImageContext.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_xmloff.hxx"
30 #include <tools/debug.hxx>
31 #include <com/sun/star/io/XOutputStream.hpp>
32 #include <xmloff/xmltkmap.hxx>
33 #include <xmloff/xmluconv.hxx>
34 #include "xmloff/xmlnmspe.hxx"
35 #include <xmloff/xmltoken.hxx>
36 #include <xmloff/xmlimp.hxx>
37 #include <xmloff/nmspmap.hxx>
38 #include <xmloff/XMLBase64ImportContext.hxx>
39 #include "XMLBackgroundImageContext.hxx"
40 
41 using ::rtl::OUString;
42 using ::rtl::OUStringBuffer;
43 
44 using namespace ::com::sun::star;
45 using namespace ::com::sun::star::uno;
46 using namespace ::com::sun::star::style;
47 using namespace ::com::sun::star::io;
48 using namespace ::xmloff::token;
49 
50 enum SvXMLTokenMapAttrs
51 {
52     XML_TOK_BGIMG_HREF,
53     XML_TOK_BGIMG_TYPE,
54     XML_TOK_BGIMG_ACTUATE,
55     XML_TOK_BGIMG_SHOW,
56     XML_TOK_BGIMG_POSITION,
57     XML_TOK_BGIMG_REPEAT,
58     XML_TOK_BGIMG_FILTER,
59     XML_TOK_BGIMG_OPACITY,
60     XML_TOK_NGIMG_END=XML_TOK_UNKNOWN
61 };
62 const SvXMLTokenMapEntry* lcl_getBGImgAttributesAttrTokenMap()
63 {
64     static __FAR_DATA SvXMLTokenMapEntry aBGImgAttributesAttrTokenMap[] =
65     {
66         { XML_NAMESPACE_XLINK, XML_HREF,        XML_TOK_BGIMG_HREF      },
67         { XML_NAMESPACE_XLINK, XML_TYPE,        XML_TOK_BGIMG_TYPE      },
68         { XML_NAMESPACE_XLINK, XML_ACTUATE,     XML_TOK_BGIMG_ACTUATE   },
69         { XML_NAMESPACE_XLINK, XML_SHOW,        XML_TOK_BGIMG_SHOW      },
70         { XML_NAMESPACE_STYLE, XML_POSITION,    XML_TOK_BGIMG_POSITION  },
71         { XML_NAMESPACE_STYLE, XML_REPEAT,      XML_TOK_BGIMG_REPEAT    },
72         { XML_NAMESPACE_STYLE, XML_FILTER_NAME, XML_TOK_BGIMG_FILTER    },
73         { XML_NAMESPACE_DRAW,  XML_OPACITY,     XML_TOK_BGIMG_OPACITY   },
74         XML_TOKEN_MAP_END
75     };
76     return aBGImgAttributesAttrTokenMap;
77 }
78 
79 
80 
81 SvXMLEnumMapEntry psXML_BrushHoriPos[] =
82 {
83     { XML_LEFT,         GraphicLocation_LEFT_MIDDLE },
84     { XML_RIGHT,        GraphicLocation_RIGHT_MIDDLE    },
85     { XML_TOKEN_INVALID,                    0           }
86 };
87 
88 SvXMLEnumMapEntry psXML_BrushVertPos[] =
89 {
90     { XML_TOP,          GraphicLocation_MIDDLE_TOP  },
91     { XML_BOTTOM,       GraphicLocation_MIDDLE_BOTTOM   },
92     { XML_TOKEN_INVALID,                    0           }
93 };
94 
95 void lcl_xmlbic_MergeHoriPos( GraphicLocation& ePos,
96                                    GraphicLocation eHori )
97 {
98     DBG_ASSERT( GraphicLocation_LEFT_MIDDLE==eHori ||
99                 GraphicLocation_MIDDLE_MIDDLE==eHori ||
100                 GraphicLocation_RIGHT_MIDDLE==eHori,
101                 "lcl_xmlbic_MergeHoriPos: vertical pos must be middle" );
102 
103     switch( ePos )
104     {
105     case GraphicLocation_LEFT_TOP:
106     case GraphicLocation_MIDDLE_TOP:
107     case GraphicLocation_RIGHT_TOP:
108         ePos = GraphicLocation_LEFT_MIDDLE==eHori
109                 ? GraphicLocation_LEFT_TOP
110                 : (GraphicLocation_MIDDLE_MIDDLE==eHori
111                         ? GraphicLocation_MIDDLE_TOP
112                         : GraphicLocation_RIGHT_TOP);
113         break;
114 
115     case GraphicLocation_LEFT_MIDDLE:
116     case GraphicLocation_MIDDLE_MIDDLE:
117     case GraphicLocation_RIGHT_MIDDLE:
118         ePos = eHori;
119         break;
120 
121     case GraphicLocation_LEFT_BOTTOM:
122     case GraphicLocation_MIDDLE_BOTTOM:
123     case GraphicLocation_RIGHT_BOTTOM:
124         ePos = GraphicLocation_LEFT_MIDDLE==eHori
125                 ? GraphicLocation_LEFT_BOTTOM
126                 : (GraphicLocation_MIDDLE_MIDDLE==eHori
127                         ? GraphicLocation_MIDDLE_BOTTOM
128                         : GraphicLocation_RIGHT_BOTTOM);
129         break;
130     default:
131         break;
132     }
133 }
134 
135 void lcl_xmlbic_MergeVertPos( GraphicLocation& ePos,
136                                               GraphicLocation eVert )
137 {
138     DBG_ASSERT( GraphicLocation_MIDDLE_TOP==eVert ||
139                 GraphicLocation_MIDDLE_MIDDLE==eVert ||
140                 GraphicLocation_MIDDLE_BOTTOM==eVert,
141                 "lcl_xmlbic_MergeVertPos: horizontal pos must be middle" );
142 
143     switch( ePos )
144     {
145     case GraphicLocation_LEFT_TOP:
146     case GraphicLocation_LEFT_MIDDLE:
147     case GraphicLocation_LEFT_BOTTOM:
148         ePos = GraphicLocation_MIDDLE_TOP==eVert
149                 ? GraphicLocation_LEFT_TOP
150                 : (GraphicLocation_MIDDLE_MIDDLE==eVert
151                         ? GraphicLocation_LEFT_MIDDLE
152                         : GraphicLocation_LEFT_BOTTOM);
153         ePos = eVert;
154         break;
155 
156     case GraphicLocation_MIDDLE_TOP:
157     case GraphicLocation_MIDDLE_MIDDLE:
158     case GraphicLocation_MIDDLE_BOTTOM:
159         ePos = eVert;
160         break;
161 
162     case GraphicLocation_RIGHT_TOP:
163     case GraphicLocation_RIGHT_MIDDLE:
164     case GraphicLocation_RIGHT_BOTTOM:
165         ePos = GraphicLocation_MIDDLE_TOP==eVert
166                 ? GraphicLocation_RIGHT_TOP
167                 : (GraphicLocation_MIDDLE_MIDDLE==eVert
168                         ? GraphicLocation_RIGHT_MIDDLE
169                         : GraphicLocation_RIGHT_BOTTOM);
170         break;
171     default:
172         break;
173     }
174 }
175 
176 TYPEINIT1( XMLBackgroundImageContext, XMLElementPropertyContext );
177 
178 void XMLBackgroundImageContext::ProcessAttrs(
179         const Reference< xml::sax::XAttributeList >& xAttrList )
180 {
181     SvXMLTokenMap aTokenMap( lcl_getBGImgAttributesAttrTokenMap() );
182 
183     ePos = GraphicLocation_NONE;
184 
185     sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
186     for( sal_Int16 i=0; i < nAttrCount; i++ )
187     {
188         const OUString& rAttrName = xAttrList->getNameByIndex( i );
189         OUString aLocalName;
190         sal_uInt16 nPrefix =
191             GetImport().GetNamespaceMap().GetKeyByAttrName( rAttrName,
192                                                             &aLocalName );
193         const OUString& rValue = xAttrList->getValueByIndex( i );
194 
195         switch( aTokenMap.Get( nPrefix, aLocalName ) )
196         {
197         case XML_TOK_BGIMG_HREF:
198             sURL = rValue;
199             if( GraphicLocation_NONE == ePos )
200                 ePos = GraphicLocation_TILED;
201             break;
202         case XML_TOK_BGIMG_TYPE:
203         case XML_TOK_BGIMG_ACTUATE:
204         case XML_TOK_BGIMG_SHOW:
205             break;
206         case XML_TOK_BGIMG_POSITION:
207             {
208                 GraphicLocation eNewPos = GraphicLocation_NONE, eTmp;
209                 sal_uInt16 nTmp;
210                 SvXMLTokenEnumerator aTokenEnum( rValue );
211                 OUString aToken;
212                 sal_Bool bHori = sal_False, bVert = sal_False;
213                 sal_Bool bOK = sal_True;
214                 while( bOK && aTokenEnum.getNextToken( aToken ) )
215                 {
216                     if( bHori && bVert )
217                     {
218                         bOK = sal_False;
219                     }
220                     else if( -1 != aToken.indexOf( sal_Unicode('%') ) )
221                     {
222                         sal_Int32 nPrc = 50;
223                         if( SvXMLUnitConverter::convertPercent( nPrc, aToken ) )
224                         {
225                             if( !bHori )
226                             {
227                                 eNewPos = nPrc < 25
228                                     ? GraphicLocation_LEFT_TOP
229                                     : (nPrc < 75 ? GraphicLocation_MIDDLE_MIDDLE
230                                                 : GraphicLocation_RIGHT_BOTTOM);
231                                 bHori = sal_True;
232                             }
233                             else
234                             {
235                                 eTmp = nPrc < 25
236                                     ? GraphicLocation_LEFT_TOP
237                                     : (nPrc < 75 ? GraphicLocation_LEFT_MIDDLE
238                                                  : GraphicLocation_LEFT_BOTTOM);
239                                 lcl_xmlbic_MergeVertPos( eNewPos, eTmp );
240                                 bVert = sal_True;
241                             }
242                         }
243                         else
244                         {
245                             // wrong percentage
246                             bOK = sal_False;
247                         }
248                     }
249                     else if( IsXMLToken( aToken, XML_CENTER ) )
250                     {
251                         if( bHori )
252                             lcl_xmlbic_MergeVertPos( eNewPos,
253                                           GraphicLocation_MIDDLE_MIDDLE );
254                         else if ( bVert )
255                             lcl_xmlbic_MergeHoriPos( eNewPos,
256                                           GraphicLocation_MIDDLE_MIDDLE );
257                         else
258                             eNewPos = GraphicLocation_MIDDLE_MIDDLE;
259                     }
260                     else if( SvXMLUnitConverter::convertEnum( nTmp, aToken,
261                                                          psXML_BrushHoriPos ) )
262                     {
263                         if( bVert )
264                             lcl_xmlbic_MergeHoriPos( eNewPos,
265                                         (GraphicLocation)nTmp );
266                         else if( !bHori )
267                             eNewPos = (GraphicLocation)nTmp;
268                         else
269                             bOK = sal_False;
270                         bHori = sal_True;
271                     }
272                     else if( SvXMLUnitConverter::convertEnum( nTmp, aToken,
273                                                          psXML_BrushVertPos ) )
274                     {
275                         if( bHori )
276                             lcl_xmlbic_MergeVertPos( eNewPos,
277                                             (GraphicLocation)nTmp );
278                         else if( !bVert )
279                             eNewPos = (GraphicLocation)nTmp;
280                         else
281                             bOK = sal_False;
282                         bVert = sal_True;
283                     }
284                     else
285                     {
286                         bOK = sal_False;
287                     }
288                 }
289 
290                 bOK &= GraphicLocation_NONE != eNewPos;
291                 if( bOK )
292                     ePos = eNewPos;
293             }
294             break;
295         case XML_TOK_BGIMG_REPEAT:
296             {
297                 sal_uInt16 nPos = GraphicLocation_NONE;
298                 static SvXMLEnumMapEntry psXML_BrushRepeat[] =
299                 {
300                     { XML_BACKGROUND_REPEAT,        GraphicLocation_TILED   },
301                     { XML_BACKGROUND_NO_REPEAT,     GraphicLocation_MIDDLE_MIDDLE       },
302                     { XML_BACKGROUND_STRETCH,       GraphicLocation_AREA    },
303                     { XML_TOKEN_INVALID,            0           }
304                 };
305                 if( SvXMLUnitConverter::convertEnum( nPos, rValue,
306                                                 psXML_BrushRepeat ) )
307                 {
308                     if( GraphicLocation_MIDDLE_MIDDLE != nPos ||
309                         GraphicLocation_NONE == ePos ||
310                         GraphicLocation_AREA == ePos ||
311                         GraphicLocation_TILED == ePos )
312                         ePos = (GraphicLocation)nPos;
313                 }
314             }
315             break;
316         case XML_TOK_BGIMG_FILTER:
317             sFilter = rValue;
318             break;
319         case XML_TOK_BGIMG_OPACITY:
320             {
321                 sal_Int32 nTmp;
322                 // convert from percent and clip
323                 if( SvXMLUnitConverter::convertPercent( nTmp, rValue ) )
324                 {
325                     if( (nTmp >= 0) && (nTmp <= 100) )
326                         nTransparency = static_cast<sal_Int8>( 100-nTmp );
327                 }
328             }
329             break;
330         }
331     }
332 
333 }
334 
335 XMLBackgroundImageContext::XMLBackgroundImageContext(
336         SvXMLImport& rImport, sal_uInt16 nPrfx,
337         const OUString& rLName,
338         const Reference< xml::sax::XAttributeList > & xAttrList,
339         const XMLPropertyState& rProp,
340         sal_Int32 nPosIdx,
341         sal_Int32 nFilterIdx,
342         sal_Int32 nTransparencyIdx,
343         ::std::vector< XMLPropertyState > &rProps ) :
344     XMLElementPropertyContext( rImport, nPrfx, rLName, rProp, rProps ),
345     aPosProp( nPosIdx ),
346     aFilterProp( nFilterIdx ),
347     aTransparencyProp( nTransparencyIdx ),
348     nTransparency( 0 )
349 {
350     ProcessAttrs( xAttrList );
351 }
352 
353 XMLBackgroundImageContext::~XMLBackgroundImageContext()
354 {
355 }
356 
357 SvXMLImportContext *XMLBackgroundImageContext::CreateChildContext(
358         sal_uInt16 nPrefix, const OUString& rLocalName,
359         const Reference< xml::sax::XAttributeList > & xAttrList )
360 {
361     SvXMLImportContext *pContext = NULL;
362     if( (XML_NAMESPACE_OFFICE == nPrefix) &&
363         xmloff::token::IsXMLToken( rLocalName,
364                                         xmloff::token::XML_BINARY_DATA ) )
365     {
366         if( !sURL.getLength() && !xBase64Stream.is() )
367         {
368             xBase64Stream = GetImport().GetStreamForGraphicObjectURLFromBase64();
369             if( xBase64Stream.is() )
370                 pContext = new XMLBase64ImportContext( GetImport(), nPrefix,
371                                                     rLocalName, xAttrList,
372                                                     xBase64Stream );
373         }
374     }
375     if( !pContext )
376     {
377         pContext = new SvXMLImportContext( GetImport(), nPrefix, rLocalName );
378     }
379 
380     return pContext;
381 }
382 
383 void XMLBackgroundImageContext::EndElement()
384 {
385     if( sURL.getLength() )
386     {
387         sURL = GetImport().ResolveGraphicObjectURL( sURL, sal_False );
388     }
389     else if( xBase64Stream.is() )
390     {
391         sURL = GetImport().ResolveGraphicObjectURLFromBase64( xBase64Stream );
392         xBase64Stream = 0;
393     }
394 
395     if( !sURL.getLength() )
396         ePos = GraphicLocation_NONE;
397     else if( GraphicLocation_NONE == ePos )
398         ePos = GraphicLocation_TILED;
399 
400     aProp.maValue <<= sURL;
401     aPosProp.maValue <<= ePos;
402     aFilterProp.maValue <<= sFilter;
403     aTransparencyProp.maValue <<= nTransparency;
404 
405     SetInsert( sal_True );
406     XMLElementPropertyContext::EndElement();
407 
408     if( -1 != aPosProp.mnIndex )
409         rProperties.push_back( aPosProp );
410     if( -1 != aFilterProp.mnIndex )
411         rProperties.push_back( aFilterProp );
412     if( -1 != aTransparencyProp.mnIndex )
413         rProperties.push_back( aTransparencyProp );
414 }
415