LibreOffice Module xmloff (master)  1
XMLBackgroundImageContext.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
20 
21 #include <com/sun/star/io/XOutputStream.hpp>
22 #include <com/sun/star/drawing/BitmapMode.hpp>
23 #include <com/sun/star/graphic/XGraphic.hpp>
24 
25 #include <tools/debug.hxx>
26 
27 #include <sax/tools/converter.hxx>
28 
29 #include <xmloff/xmltkmap.hxx>
30 #include <xmloff/xmluconv.hxx>
31 #include <xmloff/xmlnmspe.hxx>
32 #include <xmloff/xmltoken.hxx>
33 #include <xmloff/xmlimp.hxx>
34 #include <xmloff/nmspmap.hxx>
35 #include <xmloff/xmlement.hxx>
38 
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 namespace {
47 
49 {
50  XML_TOK_BGIMG_HREF,
51  XML_TOK_BGIMG_TYPE,
52  XML_TOK_BGIMG_ACTUATE,
53  XML_TOK_BGIMG_SHOW,
54  XML_TOK_BGIMG_POSITION,
55  XML_TOK_BGIMG_REPEAT,
56  XML_TOK_BGIMG_FILTER,
57  XML_TOK_BGIMG_OPACITY
58 };
59 
60 }
61 
63 {
64  { XML_NAMESPACE_XLINK, XML_HREF, XML_TOK_BGIMG_HREF },
65  { XML_NAMESPACE_XLINK, XML_TYPE, XML_TOK_BGIMG_TYPE },
66  { XML_NAMESPACE_XLINK, XML_ACTUATE, XML_TOK_BGIMG_ACTUATE },
67  { XML_NAMESPACE_XLINK, XML_SHOW, XML_TOK_BGIMG_SHOW },
68  { XML_NAMESPACE_STYLE, XML_POSITION, XML_TOK_BGIMG_POSITION },
69  { XML_NAMESPACE_STYLE, XML_REPEAT, XML_TOK_BGIMG_REPEAT },
70  { XML_NAMESPACE_STYLE, XML_FILTER_NAME, XML_TOK_BGIMG_FILTER },
71  { XML_NAMESPACE_DRAW, XML_OPACITY, XML_TOK_BGIMG_OPACITY },
73 };
74 
75 
77 {
78  { XML_LEFT, GraphicLocation_LEFT_MIDDLE },
79  { XML_RIGHT, GraphicLocation_RIGHT_MIDDLE },
80  { XML_TOKEN_INVALID, GraphicLocation(0) }
81 };
82 
84 {
85  { XML_TOP, GraphicLocation_MIDDLE_TOP },
86  { XML_BOTTOM, GraphicLocation_MIDDLE_BOTTOM },
87  { XML_TOKEN_INVALID, GraphicLocation(0) }
88 };
89 
90 static void lcl_xmlbic_MergeHoriPos( GraphicLocation& ePos,
91  GraphicLocation eHori )
92 {
93  DBG_ASSERT( GraphicLocation_LEFT_MIDDLE==eHori ||
94  GraphicLocation_MIDDLE_MIDDLE==eHori ||
95  GraphicLocation_RIGHT_MIDDLE==eHori,
96  "lcl_xmlbic_MergeHoriPos: vertical pos must be middle" );
97 
98  switch( ePos )
99  {
100  case GraphicLocation_LEFT_TOP:
101  case GraphicLocation_MIDDLE_TOP:
102  case GraphicLocation_RIGHT_TOP:
103  ePos = GraphicLocation_LEFT_MIDDLE==eHori
104  ? GraphicLocation_LEFT_TOP
105  : (GraphicLocation_MIDDLE_MIDDLE==eHori
106  ? GraphicLocation_MIDDLE_TOP
107  : GraphicLocation_RIGHT_TOP);
108  break;
109 
110  case GraphicLocation_LEFT_MIDDLE:
111  case GraphicLocation_MIDDLE_MIDDLE:
112  case GraphicLocation_RIGHT_MIDDLE:
113  ePos = eHori;
114  break;
115 
116  case GraphicLocation_LEFT_BOTTOM:
117  case GraphicLocation_MIDDLE_BOTTOM:
118  case GraphicLocation_RIGHT_BOTTOM:
119  ePos = GraphicLocation_LEFT_MIDDLE==eHori
120  ? GraphicLocation_LEFT_BOTTOM
121  : (GraphicLocation_MIDDLE_MIDDLE==eHori
122  ? GraphicLocation_MIDDLE_BOTTOM
123  : GraphicLocation_RIGHT_BOTTOM);
124  break;
125  default:
126  break;
127  }
128 }
129 
130 static void lcl_xmlbic_MergeVertPos( GraphicLocation& ePos,
131  GraphicLocation eVert )
132 {
133  DBG_ASSERT( GraphicLocation_MIDDLE_TOP==eVert ||
134  GraphicLocation_MIDDLE_MIDDLE==eVert ||
135  GraphicLocation_MIDDLE_BOTTOM==eVert,
136  "lcl_xmlbic_MergeVertPos: horizontal pos must be middle" );
137 
138  switch( ePos )
139  {
140  case GraphicLocation_LEFT_TOP:
141  case GraphicLocation_LEFT_MIDDLE:
142  case GraphicLocation_LEFT_BOTTOM:
143  ePos = GraphicLocation_MIDDLE_TOP==eVert
144  ? GraphicLocation_LEFT_TOP
145  : (GraphicLocation_MIDDLE_MIDDLE==eVert
146  ? GraphicLocation_LEFT_MIDDLE
147  : GraphicLocation_LEFT_BOTTOM);
148  break;
149 
150  case GraphicLocation_MIDDLE_TOP:
151  case GraphicLocation_MIDDLE_MIDDLE:
152  case GraphicLocation_MIDDLE_BOTTOM:
153  ePos = eVert;
154  break;
155 
156  case GraphicLocation_RIGHT_TOP:
157  case GraphicLocation_RIGHT_MIDDLE:
158  case GraphicLocation_RIGHT_BOTTOM:
159  ePos = GraphicLocation_MIDDLE_TOP==eVert
160  ? GraphicLocation_RIGHT_TOP
161  : (GraphicLocation_MIDDLE_MIDDLE==eVert
162  ? GraphicLocation_RIGHT_MIDDLE
163  : GraphicLocation_RIGHT_BOTTOM);
164  break;
165  default:
166  break;
167  }
168 }
169 
170 
172  const Reference< xml::sax::XAttributeList >& xAttrList )
173 {
174  static const SvXMLTokenMap aTokenMap( aBGImgAttributesAttrTokenMap );
175 
176  ePos = GraphicLocation_NONE;
177 
178  sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
179  for( sal_Int16 i=0; i < nAttrCount; i++ )
180  {
181  const OUString& rAttrName = xAttrList->getNameByIndex( i );
182  OUString aLocalName;
183  sal_uInt16 nPrefix =
185  &aLocalName );
186  const OUString& rValue = xAttrList->getValueByIndex( i );
187 
188  switch( aTokenMap.Get( nPrefix, aLocalName ) )
189  {
190  case XML_TOK_BGIMG_HREF:
191  m_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:
200  {
201  GraphicLocation eNewPos = GraphicLocation_NONE, eTmp;
202  SvXMLTokenEnumerator aTokenEnum( rValue );
203  OUString aToken;
204  bool bHori = false, bVert = false;
205  bool bOK = true;
206  while( bOK && aTokenEnum.getNextToken( aToken ) )
207  {
208  GraphicLocation nTmpGraphicLocation;
209  if( bHori && bVert )
210  {
211  bOK = false;
212  }
213  else if( -1 != aToken.indexOf( '%' ) )
214  {
215  sal_Int32 nPrc = 50;
216  if (::sax::Converter::convertPercent( nPrc, aToken ))
217  {
218  if( !bHori )
219  {
220  eNewPos = nPrc < 25
221  ? GraphicLocation_LEFT_TOP
222  : (nPrc < 75 ? GraphicLocation_MIDDLE_MIDDLE
223  : GraphicLocation_RIGHT_BOTTOM);
224  bHori = true;
225  }
226  else
227  {
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;
234  }
235  }
236  else
237  {
238  // wrong percentage
239  bOK = false;
240  }
241  }
242  else if( IsXMLToken( aToken, XML_CENTER ) )
243  {
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;
252  }
253  else if( SvXMLUnitConverter::convertEnum( nTmpGraphicLocation, aToken,
254  psXML_BrushHoriPos ) )
255  {
256  if( bVert )
257  lcl_xmlbic_MergeHoriPos( eNewPos, nTmpGraphicLocation );
258  else if( !bHori )
259  eNewPos = nTmpGraphicLocation;
260  else
261  bOK = false;
262  bHori = true;
263  }
264  else if( SvXMLUnitConverter::convertEnum( nTmpGraphicLocation, aToken,
265  psXML_BrushVertPos ) )
266  {
267  if( bHori )
268  lcl_xmlbic_MergeVertPos( eNewPos, nTmpGraphicLocation );
269  else if( !bVert )
270  eNewPos = nTmpGraphicLocation;
271  else
272  bOK = false;
273  bVert = true;
274  }
275  else
276  {
277  bOK = false;
278  }
279  }
280 
281  bOK &= GraphicLocation_NONE != eNewPos;
282  if( bOK )
283  ePos = eNewPos;
284  }
285  break;
286  case XML_TOK_BGIMG_REPEAT:
287  {
288  GraphicLocation nPos = GraphicLocation_NONE;
290  {
291  { XML_REPEAT, GraphicLocation_TILED },
292  { XML_BACKGROUND_NO_REPEAT, GraphicLocation_MIDDLE_MIDDLE },
293  { XML_STRETCH, GraphicLocation_AREA },
294  { XML_TOKEN_INVALID, GraphicLocation(0) }
295  };
296  if( SvXMLUnitConverter::convertEnum( nPos, rValue,
297  psXML_BrushRepeat ) )
298  {
299  if( GraphicLocation_MIDDLE_MIDDLE != nPos ||
300  GraphicLocation_NONE == ePos ||
301  GraphicLocation_AREA == ePos ||
302  GraphicLocation_TILED == ePos )
303  ePos = nPos;
304  }
305  }
306  break;
307  case XML_TOK_BGIMG_FILTER:
308  sFilter = rValue;
309  break;
310  case XML_TOK_BGIMG_OPACITY:
311  {
312  sal_Int32 nTmp;
313  // convert from percent and clip
314  if (::sax::Converter::convertPercent( nTmp, rValue ))
315  {
316  if( (nTmp >= 0) && (nTmp <= 100) )
317  nTransparency = static_cast<sal_Int8>( 100-nTmp );
318  }
319  }
320  break;
321  }
322  }
323 
324 }
325 
327  SvXMLImport& rImport, sal_uInt16 nPrfx,
328  const OUString& rLName,
329  const Reference< xml::sax::XAttributeList > & xAttrList,
330  const XMLPropertyState& rProp,
331  sal_Int32 nPosIdx,
332  sal_Int32 nFilterIdx,
333  sal_Int32 nTransparencyIdx,
334  sal_Int32 nBitmapModeIdx,
335  ::std::vector< XMLPropertyState > &rProps ) :
336  XMLElementPropertyContext( rImport, nPrfx, rLName, rProp, rProps ),
337  aPosProp( nPosIdx ),
338  m_nBitmapModeIdx(nBitmapModeIdx),
339  aFilterProp( nFilterIdx ),
340  aTransparencyProp( nTransparencyIdx ),
341  nTransparency( 0 )
342 {
343  ProcessAttrs( xAttrList );
344 }
345 
347 {
348 }
349 
351  sal_uInt16 nPrefix, const OUString& rLocalName,
352  const Reference< xml::sax::XAttributeList > & xAttrList )
353 {
354  SvXMLImportContext *pContext = nullptr;
355  if( (XML_NAMESPACE_OFFICE == nPrefix) &&
356  xmloff::token::IsXMLToken( rLocalName,
358  {
359  if( m_sURL.isEmpty() && !m_xBase64Stream.is() )
360  {
362  if( m_xBase64Stream.is() )
363  pContext = new XMLBase64ImportContext( GetImport(), nPrefix,
364  rLocalName, xAttrList,
365  m_xBase64Stream );
366  }
367  }
368 
369  return pContext;
370 }
371 
373 {
374  uno::Reference<graphic::XGraphic> xGraphic;
375  if (!m_sURL.isEmpty())
376  {
377  xGraphic = GetImport().loadGraphicByURL(m_sURL);
378  }
379  else if (m_xBase64Stream.is())
380  {
382  m_xBase64Stream = nullptr;
383  }
384 
385  if (!xGraphic.is())
386  ePos = GraphicLocation_NONE;
387  else if (GraphicLocation_NONE == ePos)
388  ePos = GraphicLocation_TILED;
389 
390  if (xGraphic.is())
391  aProp.maValue <<= xGraphic;
392  aPosProp.maValue <<= ePos;
395 
396  SetInsert( true );
398 
399  if( -1 != aPosProp.mnIndex )
400  {
401  // See if a FillBitmapMode property is already set, in that case
402  // BackGraphicLocation will be ignored.
403  bool bFound = false;
404  if (m_nBitmapModeIdx != -1)
405  {
406  for (XMLPropertyState& rProperty : rProperties)
407  {
408  if (rProperty.mnIndex == m_nBitmapModeIdx)
409  {
410  bFound = true;
411 
412  // Found, so map the old property to the new one.
413  switch (ePos)
414  {
415  case GraphicLocation_TILED:
416  rProperty.maValue <<= drawing::BitmapMode_REPEAT;
417  break;
418  case GraphicLocation_AREA:
419  rProperty.maValue <<= drawing::BitmapMode_STRETCH;
420  break;
421  case GraphicLocation_MIDDLE_MIDDLE:
422  rProperty.maValue <<= drawing::BitmapMode_NO_REPEAT;
423  break;
424  default:
425  break;
426  }
427  break;
428  }
429  }
430  }
431  if (!bFound)
432  rProperties.push_back( aPosProp );
433  }
434  if( -1 != aFilterProp.mnIndex )
435  rProperties.push_back( aFilterProp );
436  if( -1 != aTransparencyProp.mnIndex )
437  rProperties.push_back( aTransparencyProp );
438 }
439 
440 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
bool IsXMLToken(const OUString &rString, enum XMLTokenEnum eToken)
compare eToken to the string
Definition: xmltoken.cxx:3422
constexpr sal_uInt16 XML_NAMESPACE_STYLE
Definition: xmlnmspe.hxx:30
css::uno::Reference< css::graphic::XGraphic > loadGraphicFromBase64(css::uno::Reference< css::io::XOutputStream > const &rxOutputStream)
Definition: xmlimp.cxx:1378
static XMLTokenEnum const aTokenMap[]
Definition: Oasis2OOo.cxx:1145
static bool convertEnum(EnumT &rEnum, const OUString &rValue, const SvXMLEnumMapEntry< EnumT > *pMap)
convert string to enum using given enum map, if the enum is not found in the map, this method will re...
Definition: xmluconv.hxx:128
signed char sal_Int8
SvXMLTokenMapAttrs
SvXMLImport & GetImport()
Definition: xmlictxt.hxx:62
XMLBackgroundImageContext(SvXMLImport &rImport, sal_uInt16 nPrfx, const OUString &rLName, const css::uno::Reference< css::xml::sax::XAttributeList > &xAttrList, const XMLPropertyState &rProp, sal_Int32 nPosIdx, sal_Int32 nFilterIdx, sal_Int32 nTransparencyIdx, sal_Int32 nBitmapModeIdx,::std::vector< XMLPropertyState > &rProps)
sal_Int32 mnIndex
Definition: maptype.hxx:106
SvXMLNamespaceMap & GetNamespaceMap()
Definition: xmlimp.hxx:397
css::uno::Reference< css::graphic::XGraphic > loadGraphicByURL(OUString const &rURL)
Definition: xmlimp.cxx:1356
bool getNextToken(OUString &rToken)
Definition: xmluconv.cxx:449
sal_uInt16 GetKeyByAttrName(const OUString &rAttrName, OUString *pPrefix, OUString *pLocalName, OUString *pNamespace) const
Definition: nmspmap.cxx:437
#define XML_TOKEN_MAP_END
Definition: xmltkmap.hxx:33
css::uno::Any const & rValue
Definition: ImageStyle.hxx:38
css::uno::Reference< css::io::XOutputStream > GetStreamForGraphicObjectURLFromBase64() const
Definition: xmlimp.cxx:1390
static const SvXMLEnumMapEntry< GraphicLocation > psXML_BrushVertPos[]
constexpr sal_uInt16 XML_NAMESPACE_DRAW
Definition: xmlnmspe.hxx:33
css::uno::Reference< css::io::XOutputStream > m_xBase64Stream
#define DBG_ASSERT(sCon, aError)
int i
static const SvXMLTokenMapEntry aBGImgAttributesAttrTokenMap[]
static void lcl_xmlbic_MergeHoriPos(GraphicLocation &ePos, GraphicLocation eHori)
sal_uInt16 Get(sal_uInt16 nPrefix, const OUString &rLName) const
Definition: xmltkmap.cxx:93
::std::vector< XMLPropertyState > & rProperties
This class deliberately does not support XWeak, to improve performance when loading large documents...
Definition: xmlictxt.hxx:44
constexpr sal_uInt16 XML_NAMESPACE_XLINK
Definition: xmlnmspe.hxx:35
Map an XMLTokenEnum to an enum value.
Definition: ximpshap.hxx:40
css::uno::Any maValue
Definition: maptype.hxx:107
Handling of tokens in XML:
Smart struct to transport an Any with an index to the appropriate property-name.
Definition: maptype.hxx:104
static const SvXMLEnumMapEntry< GraphicLocation > psXML_BrushHoriPos[]
void ProcessAttrs(const css::uno::Reference< css::xml::sax::XAttributeList > &xAttrList)
SvXMLImportContextRef CreateChildContext(sal_uInt16 nPrefix, const OUString &rLocalName, const css::uno::Reference< css::xml::sax::XAttributeList > &xAttrList) override
Create a children element context.
static void lcl_xmlbic_MergeVertPos(GraphicLocation &ePos, GraphicLocation eVert)
virtual void EndElement() override
EndElement is called before a context will be destructed, but after an elements context has been pars...
css::style::GraphicLocation ePos
Reference< XGraphic > xGraphic
sal_uInt16 nPos
virtual void EndElement() override
EndElement is called before a context will be destructed, but after an elements context has been pars...
constexpr sal_uInt16 XML_NAMESPACE_OFFICE
Definition: xmlnmspe.hxx:29
static bool convertPercent(sal_Int32 &rValue, const OUString &rString)
const struct SvXMLEnumMapEntry< SvxGraphicPosition > psXML_BrushRepeat[]