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 #include <sal/log.hxx>
27 #include <sax/tools/converter.hxx>
28 
29 #include <xmloff/xmltkmap.hxx>
30 #include <xmloff/xmluconv.hxx>
31 #include <xmloff/xmlnamespace.hxx>
32 #include <xmloff/xmltoken.hxx>
33 #include <xmloff/xmlimp.hxx>
34 #include <xmloff/namespacemap.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::XFastAttributeList >& xAttrList )
173 {
174  ePos = GraphicLocation_NONE;
175 
176  for (auto &aIter : sax_fastparser::castToFastAttributeList(xAttrList))
177  {
178  const OUString sValue = aIter.toString();
179 
180  switch( aIter.getToken() )
181  {
182  case XML_ELEMENT(XLINK, XML_HREF):
183  m_sURL = sValue;
184  if( GraphicLocation_NONE == ePos )
185  ePos = GraphicLocation_TILED;
186  break;
187  case XML_ELEMENT(XLINK, XML_TYPE):
188  case XML_ELEMENT(XLINK, XML_ACTUATE):
189  case XML_ELEMENT(XLINK, XML_SHOW):
190  break;
192  {
193  GraphicLocation eNewPos = GraphicLocation_NONE, eTmp;
194  SvXMLTokenEnumerator aTokenEnum( sValue );
195  OUString aToken;
196  bool bHori = false, bVert = false;
197  bool bOK = true;
198  while( bOK && aTokenEnum.getNextToken( aToken ) )
199  {
200  GraphicLocation nTmpGraphicLocation;
201  if( bHori && bVert )
202  {
203  bOK = false;
204  }
205  else if( -1 != aToken.indexOf( '%' ) )
206  {
207  sal_Int32 nPrc = 50;
208  if (::sax::Converter::convertPercent( nPrc, aToken ))
209  {
210  if( !bHori )
211  {
212  eNewPos = nPrc < 25
213  ? GraphicLocation_LEFT_TOP
214  : (nPrc < 75 ? GraphicLocation_MIDDLE_MIDDLE
215  : GraphicLocation_RIGHT_BOTTOM);
216  bHori = true;
217  }
218  else
219  {
220  eTmp = nPrc < 25
221  ? GraphicLocation_LEFT_TOP
222  : (nPrc < 75 ? GraphicLocation_LEFT_MIDDLE
223  : GraphicLocation_LEFT_BOTTOM);
224  lcl_xmlbic_MergeVertPos( eNewPos, eTmp );
225  bVert = true;
226  }
227  }
228  else
229  {
230  // wrong percentage
231  bOK = false;
232  }
233  }
234  else if( IsXMLToken( aToken, XML_CENTER ) )
235  {
236  if( bHori )
237  lcl_xmlbic_MergeVertPos( eNewPos,
238  GraphicLocation_MIDDLE_MIDDLE );
239  else if ( bVert )
240  lcl_xmlbic_MergeHoriPos( eNewPos,
241  GraphicLocation_MIDDLE_MIDDLE );
242  else
243  eNewPos = GraphicLocation_MIDDLE_MIDDLE;
244  }
245  else if( SvXMLUnitConverter::convertEnum( nTmpGraphicLocation, aToken,
246  psXML_BrushHoriPos ) )
247  {
248  if( bVert )
249  lcl_xmlbic_MergeHoriPos( eNewPos, nTmpGraphicLocation );
250  else if( !bHori )
251  eNewPos = nTmpGraphicLocation;
252  else
253  bOK = false;
254  bHori = true;
255  }
256  else if( SvXMLUnitConverter::convertEnum( nTmpGraphicLocation, aToken,
257  psXML_BrushVertPos ) )
258  {
259  if( bHori )
260  lcl_xmlbic_MergeVertPos( eNewPos, nTmpGraphicLocation );
261  else if( !bVert )
262  eNewPos = nTmpGraphicLocation;
263  else
264  bOK = false;
265  bVert = true;
266  }
267  else
268  {
269  bOK = false;
270  }
271  }
272 
273  bOK &= GraphicLocation_NONE != eNewPos;
274  if( bOK )
275  ePos = eNewPos;
276  }
277  break;
279  {
280  GraphicLocation nPos = GraphicLocation_NONE;
282  {
283  { XML_REPEAT, GraphicLocation_TILED },
284  { XML_BACKGROUND_NO_REPEAT, GraphicLocation_MIDDLE_MIDDLE },
285  { XML_STRETCH, GraphicLocation_AREA },
286  { XML_TOKEN_INVALID, GraphicLocation(0) }
287  };
288  if( SvXMLUnitConverter::convertEnum( nPos, sValue,
289  psXML_BrushRepeat ) )
290  {
291  if( GraphicLocation_MIDDLE_MIDDLE != nPos ||
292  GraphicLocation_NONE == ePos ||
293  GraphicLocation_AREA == ePos ||
294  GraphicLocation_TILED == ePos )
295  ePos = nPos;
296  }
297  }
298  break;
300  sFilter = sValue;
301  break;
303  {
304  sal_Int32 nTmp;
305  // convert from percent and clip
306  if (::sax::Converter::convertPercent( nTmp, sValue ))
307  {
308  if( (nTmp >= 0) && (nTmp <= 100) )
309  nTransparency = static_cast<sal_Int8>( 100-nTmp );
310  }
311  }
312  break;
313  default:
314  SAL_WARN("xmloff", "unknown attribute " << SvXMLImport::getPrefixAndNameFromToken(aIter.getToken()) << "=" << sValue);
315  }
316  }
317 
318 }
319 
321  SvXMLImport& rImport, sal_Int32 nElement,
322  const Reference< xml::sax::XFastAttributeList > & xAttrList,
323  const XMLPropertyState& rProp,
324  sal_Int32 nPosIdx,
325  sal_Int32 nFilterIdx,
326  sal_Int32 nTransparencyIdx,
327  sal_Int32 nBitmapModeIdx,
328  ::std::vector< XMLPropertyState > &rProps ) :
329  XMLElementPropertyContext( rImport, nElement, rProp, rProps ),
330  aPosProp( nPosIdx ),
331  m_nBitmapModeIdx(nBitmapModeIdx),
332  aFilterProp( nFilterIdx ),
333  aTransparencyProp( nTransparencyIdx ),
334  nTransparency( 0 )
335 {
336  ProcessAttrs( xAttrList );
337 }
338 
340 {
341 }
342 
343 css::uno::Reference< css::xml::sax::XFastContextHandler > XMLBackgroundImageContext::createFastChildContext(
344  sal_Int32 nElement,
345  const css::uno::Reference< css::xml::sax::XFastAttributeList >& /*xAttrList*/ )
346 {
348  {
349  if( m_sURL.isEmpty() && !m_xBase64Stream.is() )
350  {
352  if( m_xBase64Stream.is() )
354  }
355  }
356  SAL_WARN("xmloff", "unknown element " << SvXMLImport::getPrefixAndNameFromToken(nElement));
357  return nullptr;
358 }
359 
361 {
362  uno::Reference<graphic::XGraphic> xGraphic;
363  if (!m_sURL.isEmpty())
364  {
365  xGraphic = GetImport().loadGraphicByURL(m_sURL);
366  }
367  else if (m_xBase64Stream.is())
368  {
370  m_xBase64Stream = nullptr;
371  }
372 
373  if (!xGraphic.is())
374  ePos = GraphicLocation_NONE;
375  else if (GraphicLocation_NONE == ePos)
376  ePos = GraphicLocation_TILED;
377 
378  if (xGraphic.is())
379  aProp.maValue <<= xGraphic;
380  aPosProp.maValue <<= ePos;
383 
384  SetInsert( true );
386 
387  if( -1 != aPosProp.mnIndex )
388  {
389  // See if a FillBitmapMode property is already set, in that case
390  // BackGraphicLocation will be ignored.
391  bool bFound = false;
392  if (m_nBitmapModeIdx != -1)
393  {
394  for (XMLPropertyState& rProperty : rProperties)
395  {
396  if (rProperty.mnIndex == m_nBitmapModeIdx)
397  {
398  bFound = true;
399 
400  // Found, so map the old property to the new one.
401  switch (ePos)
402  {
403  case GraphicLocation_TILED:
404  rProperty.maValue <<= drawing::BitmapMode_REPEAT;
405  break;
406  case GraphicLocation_AREA:
407  rProperty.maValue <<= drawing::BitmapMode_STRETCH;
408  break;
409  case GraphicLocation_MIDDLE_MIDDLE:
410  rProperty.maValue <<= drawing::BitmapMode_NO_REPEAT;
411  break;
412  default:
413  break;
414  }
415  break;
416  }
417  }
418  }
419  if (!bFound)
420  rProperties.push_back( aPosProp );
421  }
422  if( -1 != aFilterProp.mnIndex )
423  rProperties.push_back( aFilterProp );
424  if( -1 != aTransparencyProp.mnIndex )
425  rProperties.push_back( aTransparencyProp );
426 }
427 
428 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
bool IsXMLToken(const OUString &rString, enum XMLTokenEnum eToken)
compare eToken to the string
Definition: xmltoken.cxx:3434
css::uno::Reference< css::graphic::XGraphic > loadGraphicFromBase64(css::uno::Reference< css::io::XOutputStream > const &rxOutputStream)
Definition: xmlimp.cxx:1381
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
constexpr sal_uInt16 XML_NAMESPACE_XLINK
sal_Int32 mnIndex
Definition: maptype.hxx:124
FastAttributeList & castToFastAttributeList(const css::uno::Reference< css::xml::sax::XFastAttributeList > &xAttrList)
css::uno::Reference< css::graphic::XGraphic > loadGraphicByURL(OUString const &rURL)
Definition: xmlimp.cxx:1359
bool getNextToken(OUString &rToken)
Definition: xmluconv.cxx:449
virtual void SAL_CALL endFastElement(sal_Int32 nElement) override
#define XML_TOKEN_MAP_END
Definition: xmltkmap.hxx:33
DRAW
static OUString getPrefixAndNameFromToken(sal_Int32 nToken)
Definition: xmlimp.cxx:2025
constexpr sal_uInt16 XML_NAMESPACE_DRAW
css::uno::Reference< css::io::XOutputStream > GetStreamForGraphicObjectURLFromBase64() const
Definition: xmlimp.cxx:1393
const SvXMLEnumMapEntry< GraphicLocation > psXML_BrushVertPos[]
css::uno::Reference< css::io::XOutputStream > m_xBase64Stream
#define DBG_ASSERT(sCon, aError)
const SvXMLTokenMapEntry aBGImgAttributesAttrTokenMap[]
static void lcl_xmlbic_MergeHoriPos(GraphicLocation &ePos, GraphicLocation eHori)
virtual void SAL_CALL endFastElement(sal_Int32 nElement) override
::std::vector< XMLPropertyState > & rProperties
void ProcessAttrs(const css::uno::Reference< css::xml::sax::XFastAttributeList > &xAttrList)
Map an XMLTokenEnum to an enum value.
Definition: ximpshap.hxx:40
css::uno::Any maValue
Definition: maptype.hxx:125
XMLBackgroundImageContext(SvXMLImport &rImport, sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList > &xAttrList, const XMLPropertyState &rProp, sal_Int32 nPosIdx, sal_Int32 nFilterIdx, sal_Int32 nTransparencyIdx, sal_Int32 nBitmapModeIdx,::std::vector< XMLPropertyState > &rProps)
Handling of tokens in XML:
#define XML_ELEMENT(prefix, name)
Definition: xmlimp.hxx:94
Smart struct to transport an Any with an index to the appropriate property-name.
Definition: maptype.hxx:122
virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList > &AttrList) override
const SvXMLEnumMapEntry< GraphicLocation > psXML_BrushHoriPos[]
#define SAL_WARN(area, stream)
static void lcl_xmlbic_MergeVertPos(GraphicLocation &ePos, GraphicLocation eVert)
css::style::GraphicLocation ePos
Reference< XGraphic > xGraphic
constexpr sal_uInt16 XML_NAMESPACE_STYLE
sal_uInt16 nPos
static bool convertPercent(sal_Int32 &rValue, const OUString &rString)
const struct SvXMLEnumMapEntry< SvxGraphicPosition > psXML_BrushRepeat[]