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