bump product version to 5.0.4.1
[LibreOffice.git] / xmloff / source / style / XMLBackgroundImageContext.cxx
bloba0ee84b2b7ded07941cc0928c72598e6648809c7
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include <com/sun/star/io/XOutputStream.hpp>
22 #include <com/sun/star/drawing/BitmapMode.hpp>
24 #include <tools/debug.hxx>
26 #include <sax/tools/converter.hxx>
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"
38 using namespace ::com::sun::star;
39 using namespace ::com::sun::star::uno;
40 using namespace ::com::sun::star::style;
41 using namespace ::com::sun::star::io;
42 using namespace ::xmloff::token;
44 enum SvXMLTokenMapAttrs
46 XML_TOK_BGIMG_HREF,
47 XML_TOK_BGIMG_TYPE,
48 XML_TOK_BGIMG_ACTUATE,
49 XML_TOK_BGIMG_SHOW,
50 XML_TOK_BGIMG_POSITION,
51 XML_TOK_BGIMG_REPEAT,
52 XML_TOK_BGIMG_FILTER,
53 XML_TOK_BGIMG_OPACITY,
54 XML_TOK_NGIMG_END=XML_TOK_UNKNOWN
56 static const SvXMLTokenMapEntry* lcl_getBGImgAttributesAttrTokenMap()
58 static const SvXMLTokenMapEntry aBGImgAttributesAttrTokenMap[] =
60 { XML_NAMESPACE_XLINK, XML_HREF, XML_TOK_BGIMG_HREF },
61 { XML_NAMESPACE_XLINK, XML_TYPE, XML_TOK_BGIMG_TYPE },
62 { XML_NAMESPACE_XLINK, XML_ACTUATE, XML_TOK_BGIMG_ACTUATE },
63 { XML_NAMESPACE_XLINK, XML_SHOW, XML_TOK_BGIMG_SHOW },
64 { XML_NAMESPACE_STYLE, XML_POSITION, XML_TOK_BGIMG_POSITION },
65 { XML_NAMESPACE_STYLE, XML_REPEAT, XML_TOK_BGIMG_REPEAT },
66 { XML_NAMESPACE_STYLE, XML_FILTER_NAME, XML_TOK_BGIMG_FILTER },
67 { XML_NAMESPACE_DRAW, XML_OPACITY, XML_TOK_BGIMG_OPACITY },
68 XML_TOKEN_MAP_END
70 return aBGImgAttributesAttrTokenMap;
75 static const SvXMLEnumMapEntry psXML_BrushHoriPos[] =
77 { XML_LEFT, GraphicLocation_LEFT_MIDDLE },
78 { XML_RIGHT, GraphicLocation_RIGHT_MIDDLE },
79 { XML_TOKEN_INVALID, 0 }
82 static const SvXMLEnumMapEntry psXML_BrushVertPos[] =
84 { XML_TOP, GraphicLocation_MIDDLE_TOP },
85 { XML_BOTTOM, GraphicLocation_MIDDLE_BOTTOM },
86 { XML_TOKEN_INVALID, 0 }
89 static void lcl_xmlbic_MergeHoriPos( GraphicLocation& ePos,
90 GraphicLocation eHori )
92 DBG_ASSERT( GraphicLocation_LEFT_MIDDLE==eHori ||
93 GraphicLocation_MIDDLE_MIDDLE==eHori ||
94 GraphicLocation_RIGHT_MIDDLE==eHori,
95 "lcl_xmlbic_MergeHoriPos: vertical pos must be middle" );
97 switch( ePos )
99 case GraphicLocation_LEFT_TOP:
100 case GraphicLocation_MIDDLE_TOP:
101 case GraphicLocation_RIGHT_TOP:
102 ePos = GraphicLocation_LEFT_MIDDLE==eHori
103 ? GraphicLocation_LEFT_TOP
104 : (GraphicLocation_MIDDLE_MIDDLE==eHori
105 ? GraphicLocation_MIDDLE_TOP
106 : GraphicLocation_RIGHT_TOP);
107 break;
109 case GraphicLocation_LEFT_MIDDLE:
110 case GraphicLocation_MIDDLE_MIDDLE:
111 case GraphicLocation_RIGHT_MIDDLE:
112 ePos = eHori;
113 break;
115 case GraphicLocation_LEFT_BOTTOM:
116 case GraphicLocation_MIDDLE_BOTTOM:
117 case GraphicLocation_RIGHT_BOTTOM:
118 ePos = GraphicLocation_LEFT_MIDDLE==eHori
119 ? GraphicLocation_LEFT_BOTTOM
120 : (GraphicLocation_MIDDLE_MIDDLE==eHori
121 ? GraphicLocation_MIDDLE_BOTTOM
122 : GraphicLocation_RIGHT_BOTTOM);
123 break;
124 default:
125 break;
129 static void lcl_xmlbic_MergeVertPos( GraphicLocation& ePos,
130 GraphicLocation eVert )
132 DBG_ASSERT( GraphicLocation_MIDDLE_TOP==eVert ||
133 GraphicLocation_MIDDLE_MIDDLE==eVert ||
134 GraphicLocation_MIDDLE_BOTTOM==eVert,
135 "lcl_xmlbic_MergeVertPos: horizontal pos must be middle" );
137 switch( ePos )
139 case GraphicLocation_LEFT_TOP:
140 case GraphicLocation_LEFT_MIDDLE:
141 case GraphicLocation_LEFT_BOTTOM:
142 ePos = GraphicLocation_MIDDLE_TOP==eVert
143 ? GraphicLocation_LEFT_TOP
144 : (GraphicLocation_MIDDLE_MIDDLE==eVert
145 ? GraphicLocation_LEFT_MIDDLE
146 : GraphicLocation_LEFT_BOTTOM);
147 break;
149 case GraphicLocation_MIDDLE_TOP:
150 case GraphicLocation_MIDDLE_MIDDLE:
151 case GraphicLocation_MIDDLE_BOTTOM:
152 ePos = eVert;
153 break;
155 case GraphicLocation_RIGHT_TOP:
156 case GraphicLocation_RIGHT_MIDDLE:
157 case GraphicLocation_RIGHT_BOTTOM:
158 ePos = GraphicLocation_MIDDLE_TOP==eVert
159 ? GraphicLocation_RIGHT_TOP
160 : (GraphicLocation_MIDDLE_MIDDLE==eVert
161 ? GraphicLocation_RIGHT_MIDDLE
162 : GraphicLocation_RIGHT_BOTTOM);
163 break;
164 default:
165 break;
169 TYPEINIT1( XMLBackgroundImageContext, XMLElementPropertyContext );
171 void XMLBackgroundImageContext::ProcessAttrs(
172 const Reference< xml::sax::XAttributeList >& xAttrList )
174 SvXMLTokenMap aTokenMap( lcl_getBGImgAttributesAttrTokenMap() );
176 ePos = GraphicLocation_NONE;
178 sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
179 for( sal_Int16 i=0; i < nAttrCount; i++ )
181 const OUString& rAttrName = xAttrList->getNameByIndex( i );
182 OUString aLocalName;
183 sal_uInt16 nPrefix =
184 GetImport().GetNamespaceMap().GetKeyByAttrName( rAttrName,
185 &aLocalName );
186 const OUString& rValue = xAttrList->getValueByIndex( i );
188 switch( aTokenMap.Get( nPrefix, aLocalName ) )
190 case XML_TOK_BGIMG_HREF:
191 sURL = rValue;
192 if( GraphicLocation_NONE == ePos )
193 ePos = GraphicLocation_TILED;
194 break;
195 case XML_TOK_BGIMG_TYPE:
196 case XML_TOK_BGIMG_ACTUATE:
197 case XML_TOK_BGIMG_SHOW:
198 break;
199 case XML_TOK_BGIMG_POSITION:
201 GraphicLocation eNewPos = GraphicLocation_NONE, eTmp;
202 sal_uInt16 nTmp;
203 SvXMLTokenEnumerator aTokenEnum( rValue );
204 OUString aToken;
205 bool bHori = false, bVert = false;
206 bool bOK = true;
207 while( bOK && aTokenEnum.getNextToken( aToken ) )
209 if( bHori && bVert )
211 bOK = false;
213 else if( -1 != aToken.indexOf( '%' ) )
215 sal_Int32 nPrc = 50;
216 if (::sax::Converter::convertPercent( nPrc, aToken ))
218 if( !bHori )
220 eNewPos = nPrc < 25
221 ? GraphicLocation_LEFT_TOP
222 : (nPrc < 75 ? GraphicLocation_MIDDLE_MIDDLE
223 : GraphicLocation_RIGHT_BOTTOM);
224 bHori = true;
226 else
228 eTmp = nPrc < 25
229 ? GraphicLocation_LEFT_TOP
230 : (nPrc < 75 ? GraphicLocation_LEFT_MIDDLE
231 : GraphicLocation_LEFT_BOTTOM);
232 lcl_xmlbic_MergeVertPos( eNewPos, eTmp );
233 bVert = true;
236 else
238 // wrong percentage
239 bOK = false;
242 else if( IsXMLToken( aToken, XML_CENTER ) )
244 if( bHori )
245 lcl_xmlbic_MergeVertPos( eNewPos,
246 GraphicLocation_MIDDLE_MIDDLE );
247 else if ( bVert )
248 lcl_xmlbic_MergeHoriPos( eNewPos,
249 GraphicLocation_MIDDLE_MIDDLE );
250 else
251 eNewPos = GraphicLocation_MIDDLE_MIDDLE;
253 else if( SvXMLUnitConverter::convertEnum( nTmp, aToken,
254 psXML_BrushHoriPos ) )
256 if( bVert )
257 lcl_xmlbic_MergeHoriPos( eNewPos,
258 (GraphicLocation)nTmp );
259 else if( !bHori )
260 eNewPos = (GraphicLocation)nTmp;
261 else
262 bOK = false;
263 bHori = true;
265 else if( SvXMLUnitConverter::convertEnum( nTmp, aToken,
266 psXML_BrushVertPos ) )
268 if( bHori )
269 lcl_xmlbic_MergeVertPos( eNewPos,
270 (GraphicLocation)nTmp );
271 else if( !bVert )
272 eNewPos = (GraphicLocation)nTmp;
273 else
274 bOK = false;
275 bVert = true;
277 else
279 bOK = false;
283 bOK &= GraphicLocation_NONE != eNewPos;
284 if( bOK )
285 ePos = eNewPos;
287 break;
288 case XML_TOK_BGIMG_REPEAT:
290 sal_uInt16 nPos = GraphicLocation_NONE;
291 static const SvXMLEnumMapEntry psXML_BrushRepeat[] =
293 { XML_BACKGROUND_REPEAT, GraphicLocation_TILED },
294 { XML_BACKGROUND_NO_REPEAT, GraphicLocation_MIDDLE_MIDDLE },
295 { XML_BACKGROUND_STRETCH, GraphicLocation_AREA },
296 { XML_TOKEN_INVALID, 0 }
298 if( SvXMLUnitConverter::convertEnum( nPos, rValue,
299 psXML_BrushRepeat ) )
301 if( GraphicLocation_MIDDLE_MIDDLE != nPos ||
302 GraphicLocation_NONE == ePos ||
303 GraphicLocation_AREA == ePos ||
304 GraphicLocation_TILED == ePos )
305 ePos = (GraphicLocation)nPos;
308 break;
309 case XML_TOK_BGIMG_FILTER:
310 sFilter = rValue;
311 break;
312 case XML_TOK_BGIMG_OPACITY:
314 sal_Int32 nTmp;
315 // convert from percent and clip
316 if (::sax::Converter::convertPercent( nTmp, rValue ))
318 if( (nTmp >= 0) && (nTmp <= 100) )
319 nTransparency = static_cast<sal_Int8>( 100-nTmp );
322 break;
328 XMLBackgroundImageContext::XMLBackgroundImageContext(
329 SvXMLImport& rImport, sal_uInt16 nPrfx,
330 const OUString& rLName,
331 const Reference< xml::sax::XAttributeList > & xAttrList,
332 const XMLPropertyState& rProp,
333 sal_Int32 nPosIdx,
334 sal_Int32 nFilterIdx,
335 sal_Int32 nTransparencyIdx,
336 sal_Int32 nBitmapModeIdx,
337 ::std::vector< XMLPropertyState > &rProps ) :
338 XMLElementPropertyContext( rImport, nPrfx, rLName, rProp, rProps ),
339 aPosProp( nPosIdx ),
340 m_nBitmapModeIdx(nBitmapModeIdx),
341 aFilterProp( nFilterIdx ),
342 aTransparencyProp( nTransparencyIdx ),
343 nTransparency( 0 )
345 ProcessAttrs( xAttrList );
348 XMLBackgroundImageContext::~XMLBackgroundImageContext()
352 SvXMLImportContext *XMLBackgroundImageContext::CreateChildContext(
353 sal_uInt16 nPrefix, const OUString& rLocalName,
354 const Reference< xml::sax::XAttributeList > & xAttrList )
356 SvXMLImportContext *pContext = NULL;
357 if( (XML_NAMESPACE_OFFICE == nPrefix) &&
358 xmloff::token::IsXMLToken( rLocalName,
359 xmloff::token::XML_BINARY_DATA ) )
361 if( sURL.isEmpty() && !xBase64Stream.is() )
363 xBase64Stream = GetImport().GetStreamForGraphicObjectURLFromBase64();
364 if( xBase64Stream.is() )
365 pContext = new XMLBase64ImportContext( GetImport(), nPrefix,
366 rLocalName, xAttrList,
367 xBase64Stream );
370 if( !pContext )
372 pContext = new SvXMLImportContext( GetImport(), nPrefix, rLocalName );
375 return pContext;
378 void XMLBackgroundImageContext::EndElement()
380 if( !sURL.isEmpty() )
382 sURL = GetImport().ResolveGraphicObjectURL( sURL, false );
384 else if( xBase64Stream.is() )
386 sURL = GetImport().ResolveGraphicObjectURLFromBase64( xBase64Stream );
387 xBase64Stream = 0;
390 if( sURL.isEmpty() )
391 ePos = GraphicLocation_NONE;
392 else if( GraphicLocation_NONE == ePos )
393 ePos = GraphicLocation_TILED;
395 if (!sURL.isEmpty())
396 aProp.maValue <<= sURL;
397 aPosProp.maValue <<= ePos;
398 aFilterProp.maValue <<= sFilter;
399 aTransparencyProp.maValue <<= nTransparency;
401 SetInsert( true );
402 XMLElementPropertyContext::EndElement();
404 if( -1 != aPosProp.mnIndex )
406 // See if a FillBitmapMode property is already set, in that case
407 // BackGraphicLocation will be ignored.
408 bool bFound = false;
409 if (m_nBitmapModeIdx != -1)
411 for (XMLPropertyState& rProperty : rProperties)
413 if (rProperty.mnIndex == m_nBitmapModeIdx)
415 bFound = true;
417 // Found, so map the old property to the new one.
418 switch (ePos)
420 case GraphicLocation_TILED:
421 rProperty.maValue <<= drawing::BitmapMode_REPEAT;
422 break;
423 case GraphicLocation_AREA:
424 rProperty.maValue <<= drawing::BitmapMode_STRETCH;
425 break;
426 case GraphicLocation_MIDDLE_MIDDLE:
427 rProperty.maValue <<= drawing::BitmapMode_NO_REPEAT;
428 break;
429 default:
430 break;
432 break;
436 if (!bFound)
437 rProperties.push_back( aPosProp );
439 if( -1 != aFilterProp.mnIndex )
440 rProperties.push_back( aFilterProp );
441 if( -1 != aTransparencyProp.mnIndex )
442 rProperties.push_back( aTransparencyProp );
445 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */