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 
47 {
48  { XML_LEFT, GraphicLocation_LEFT_MIDDLE },
49  { XML_RIGHT, GraphicLocation_RIGHT_MIDDLE },
50  { XML_TOKEN_INVALID, GraphicLocation(0) }
51 };
52 
54 {
55  { XML_TOP, GraphicLocation_MIDDLE_TOP },
56  { XML_BOTTOM, GraphicLocation_MIDDLE_BOTTOM },
57  { XML_TOKEN_INVALID, GraphicLocation(0) }
58 };
59 
60 static void lcl_xmlbic_MergeHoriPos( GraphicLocation& ePos,
61  GraphicLocation eHori )
62 {
63  DBG_ASSERT( GraphicLocation_LEFT_MIDDLE==eHori ||
64  GraphicLocation_MIDDLE_MIDDLE==eHori ||
65  GraphicLocation_RIGHT_MIDDLE==eHori,
66  "lcl_xmlbic_MergeHoriPos: vertical pos must be middle" );
67 
68  switch( ePos )
69  {
70  case GraphicLocation_LEFT_TOP:
71  case GraphicLocation_MIDDLE_TOP:
72  case GraphicLocation_RIGHT_TOP:
73  ePos = GraphicLocation_LEFT_MIDDLE==eHori
74  ? GraphicLocation_LEFT_TOP
75  : (GraphicLocation_MIDDLE_MIDDLE==eHori
76  ? GraphicLocation_MIDDLE_TOP
77  : GraphicLocation_RIGHT_TOP);
78  break;
79 
80  case GraphicLocation_LEFT_MIDDLE:
81  case GraphicLocation_MIDDLE_MIDDLE:
82  case GraphicLocation_RIGHT_MIDDLE:
83  ePos = eHori;
84  break;
85 
86  case GraphicLocation_LEFT_BOTTOM:
87  case GraphicLocation_MIDDLE_BOTTOM:
88  case GraphicLocation_RIGHT_BOTTOM:
89  ePos = GraphicLocation_LEFT_MIDDLE==eHori
90  ? GraphicLocation_LEFT_BOTTOM
91  : (GraphicLocation_MIDDLE_MIDDLE==eHori
92  ? GraphicLocation_MIDDLE_BOTTOM
93  : GraphicLocation_RIGHT_BOTTOM);
94  break;
95  default:
96  break;
97  }
98 }
99 
100 static void lcl_xmlbic_MergeVertPos( GraphicLocation& ePos,
101  GraphicLocation eVert )
102 {
103  DBG_ASSERT( GraphicLocation_MIDDLE_TOP==eVert ||
104  GraphicLocation_MIDDLE_MIDDLE==eVert ||
105  GraphicLocation_MIDDLE_BOTTOM==eVert,
106  "lcl_xmlbic_MergeVertPos: horizontal pos must be middle" );
107 
108  switch( ePos )
109  {
110  case GraphicLocation_LEFT_TOP:
111  case GraphicLocation_LEFT_MIDDLE:
112  case GraphicLocation_LEFT_BOTTOM:
113  ePos = GraphicLocation_MIDDLE_TOP==eVert
114  ? GraphicLocation_LEFT_TOP
115  : (GraphicLocation_MIDDLE_MIDDLE==eVert
116  ? GraphicLocation_LEFT_MIDDLE
117  : GraphicLocation_LEFT_BOTTOM);
118  break;
119 
120  case GraphicLocation_MIDDLE_TOP:
121  case GraphicLocation_MIDDLE_MIDDLE:
122  case GraphicLocation_MIDDLE_BOTTOM:
123  ePos = eVert;
124  break;
125 
126  case GraphicLocation_RIGHT_TOP:
127  case GraphicLocation_RIGHT_MIDDLE:
128  case GraphicLocation_RIGHT_BOTTOM:
129  ePos = GraphicLocation_MIDDLE_TOP==eVert
130  ? GraphicLocation_RIGHT_TOP
131  : (GraphicLocation_MIDDLE_MIDDLE==eVert
132  ? GraphicLocation_RIGHT_MIDDLE
133  : GraphicLocation_RIGHT_BOTTOM);
134  break;
135  default:
136  break;
137  }
138 }
139 
140 
142  const Reference< xml::sax::XFastAttributeList >& xAttrList )
143 {
144  ePos = GraphicLocation_NONE;
145 
146  for (auto &aIter : sax_fastparser::castToFastAttributeList(xAttrList))
147  {
148  switch( aIter.getToken() )
149  {
150  case XML_ELEMENT(XLINK, XML_HREF):
151  m_sURL = aIter.toString();
152  if( GraphicLocation_NONE == ePos )
153  ePos = GraphicLocation_TILED;
154  break;
155  case XML_ELEMENT(XLINK, XML_TYPE):
156  case XML_ELEMENT(XLINK, XML_ACTUATE):
157  case XML_ELEMENT(XLINK, XML_SHOW):
158  break;
160  {
161  GraphicLocation eNewPos = GraphicLocation_NONE, eTmp;
162  OUString sValue = aIter.toString();
163  SvXMLTokenEnumerator aTokenEnum( sValue );
164  std::u16string_view aToken;
165  bool bHori = false, bVert = false;
166  bool bOK = true;
167  while( bOK && aTokenEnum.getNextToken( aToken ) )
168  {
169  GraphicLocation nTmpGraphicLocation;
170  if( bHori && bVert )
171  {
172  bOK = false;
173  }
174  else if( std::u16string_view::npos != aToken.find( '%' ) )
175  {
176  sal_Int32 nPrc = 50;
177  if (::sax::Converter::convertPercent( nPrc, aToken ))
178  {
179  if( !bHori )
180  {
181  eNewPos = nPrc < 25
182  ? GraphicLocation_LEFT_TOP
183  : (nPrc < 75 ? GraphicLocation_MIDDLE_MIDDLE
184  : GraphicLocation_RIGHT_BOTTOM);
185  bHori = true;
186  }
187  else
188  {
189  eTmp = nPrc < 25
190  ? GraphicLocation_LEFT_TOP
191  : (nPrc < 75 ? GraphicLocation_LEFT_MIDDLE
192  : GraphicLocation_LEFT_BOTTOM);
193  lcl_xmlbic_MergeVertPos( eNewPos, eTmp );
194  bVert = true;
195  }
196  }
197  else
198  {
199  // wrong percentage
200  bOK = false;
201  }
202  }
203  else if( IsXMLToken( aToken, XML_CENTER ) )
204  {
205  if( bHori )
206  lcl_xmlbic_MergeVertPos( eNewPos,
207  GraphicLocation_MIDDLE_MIDDLE );
208  else if ( bVert )
209  lcl_xmlbic_MergeHoriPos( eNewPos,
210  GraphicLocation_MIDDLE_MIDDLE );
211  else
212  eNewPos = GraphicLocation_MIDDLE_MIDDLE;
213  }
214  else if( SvXMLUnitConverter::convertEnum( nTmpGraphicLocation, aToken,
215  psXML_BrushHoriPos ) )
216  {
217  if( bVert )
218  lcl_xmlbic_MergeHoriPos( eNewPos, nTmpGraphicLocation );
219  else if( !bHori )
220  eNewPos = nTmpGraphicLocation;
221  else
222  bOK = false;
223  bHori = true;
224  }
225  else if( SvXMLUnitConverter::convertEnum( nTmpGraphicLocation, aToken,
226  psXML_BrushVertPos ) )
227  {
228  if( bHori )
229  lcl_xmlbic_MergeVertPos( eNewPos, nTmpGraphicLocation );
230  else if( !bVert )
231  eNewPos = nTmpGraphicLocation;
232  else
233  bOK = false;
234  bVert = true;
235  }
236  else
237  {
238  bOK = false;
239  }
240  }
241 
242  bOK &= GraphicLocation_NONE != eNewPos;
243  if( bOK )
244  ePos = eNewPos;
245  }
246  break;
248  {
249  GraphicLocation nPos = GraphicLocation_NONE;
251  {
252  { XML_REPEAT, GraphicLocation_TILED },
253  { XML_BACKGROUND_NO_REPEAT, GraphicLocation_MIDDLE_MIDDLE },
254  { XML_STRETCH, GraphicLocation_AREA },
255  { XML_TOKEN_INVALID, GraphicLocation(0) }
256  };
257  if( SvXMLUnitConverter::convertEnum( nPos, aIter.toView(),
258  psXML_BrushRepeat ) )
259  {
260  if( GraphicLocation_MIDDLE_MIDDLE != nPos ||
261  GraphicLocation_NONE == ePos ||
262  GraphicLocation_AREA == ePos ||
263  GraphicLocation_TILED == ePos )
264  ePos = nPos;
265  }
266  }
267  break;
269  sFilter = aIter.toString();
270  break;
272  {
273  sal_Int32 nTmp;
274  // convert from percent and clip
275  if (::sax::Converter::convertPercent( nTmp, aIter.toView() ))
276  {
277  if( (nTmp >= 0) && (nTmp <= 100) )
278  nTransparency = static_cast<sal_Int8>( 100-nTmp );
279  }
280  }
281  break;
282  default:
283  XMLOFF_WARN_UNKNOWN("xmloff", aIter);
284  }
285  }
286 
287 }
288 
290  SvXMLImport& rImport, sal_Int32 nElement,
291  const Reference< xml::sax::XFastAttributeList > & xAttrList,
292  const XMLPropertyState& rProp,
293  sal_Int32 nPosIdx,
294  sal_Int32 nFilterIdx,
295  sal_Int32 nTransparencyIdx,
296  sal_Int32 nBitmapModeIdx,
297  ::std::vector< XMLPropertyState > &rProps ) :
298  XMLElementPropertyContext( rImport, nElement, rProp, rProps ),
299  aPosProp( nPosIdx ),
300  m_nBitmapModeIdx(nBitmapModeIdx),
301  aFilterProp( nFilterIdx ),
302  aTransparencyProp( nTransparencyIdx ),
303  nTransparency( 0 )
304 {
305  ProcessAttrs( xAttrList );
306 }
307 
309 {
310 }
311 
312 css::uno::Reference< css::xml::sax::XFastContextHandler > XMLBackgroundImageContext::createFastChildContext(
313  sal_Int32 nElement,
314  const css::uno::Reference< css::xml::sax::XFastAttributeList >& /*xAttrList*/ )
315 {
317  {
318  if( m_sURL.isEmpty() && !m_xBase64Stream.is() )
319  {
321  if( m_xBase64Stream.is() )
323  }
324  }
325  XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
326  return nullptr;
327 }
328 
330 {
331  uno::Reference<graphic::XGraphic> xGraphic;
332  if (!m_sURL.isEmpty())
333  {
334  xGraphic = GetImport().loadGraphicByURL(m_sURL);
335  }
336  else if (m_xBase64Stream.is())
337  {
339  m_xBase64Stream = nullptr;
340  }
341 
342  if (!xGraphic.is())
343  ePos = GraphicLocation_NONE;
344  else if (GraphicLocation_NONE == ePos)
345  ePos = GraphicLocation_TILED;
346 
347  if (xGraphic.is())
348  aProp.maValue <<= xGraphic;
349  aPosProp.maValue <<= ePos;
352 
353  SetInsert( true );
355 
356  if( -1 != aPosProp.mnIndex )
357  {
358  // See if a FillBitmapMode property is already set, in that case
359  // BackGraphicLocation will be ignored.
360  bool bFound = false;
361  if (m_nBitmapModeIdx != -1)
362  {
363  for (XMLPropertyState& rProperty : rProperties)
364  {
365  if (rProperty.mnIndex == m_nBitmapModeIdx)
366  {
367  bFound = true;
368 
369  // Found, so map the old property to the new one.
370  switch (ePos)
371  {
372  case GraphicLocation_TILED:
373  rProperty.maValue <<= drawing::BitmapMode_REPEAT;
374  break;
375  case GraphicLocation_AREA:
376  rProperty.maValue <<= drawing::BitmapMode_STRETCH;
377  break;
378  case GraphicLocation_MIDDLE_MIDDLE:
379  rProperty.maValue <<= drawing::BitmapMode_NO_REPEAT;
380  break;
381  default:
382  break;
383  }
384  break;
385  }
386  }
387  }
388  if (!bFound)
389  rProperties.push_back( aPosProp );
390  }
391  if( -1 != aFilterProp.mnIndex )
392  rProperties.push_back( aFilterProp );
393  if( -1 != aTransparencyProp.mnIndex )
394  rProperties.push_back( aTransparencyProp );
395 }
396 
397 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
css::uno::Reference< css::graphic::XGraphic > loadGraphicFromBase64(css::uno::Reference< css::io::XOutputStream > const &rxOutputStream)
Definition: xmlimp.cxx:1293
signed char sal_Int8
SvXMLImport & GetImport()
Definition: xmlictxt.hxx:59
sal_Int32 mnIndex
Definition: maptype.hxx:124
bool IsXMLToken(std::u16string_view rString, enum XMLTokenEnum eToken)
compare eToken to the string
Definition: xmltoken.cxx:3508
FastAttributeList & castToFastAttributeList(const css::uno::Reference< css::xml::sax::XFastAttributeList > &xAttrList)
css::uno::Reference< css::graphic::XGraphic > loadGraphicByURL(OUString const &rURL)
Definition: xmlimp.cxx:1271
virtual void SAL_CALL endFastElement(sal_Int32 nElement) override
endFastElement is called before a context will be destructed, but after an elements context has been ...
DRAW
#define XMLOFF_WARN_UNKNOWN(area, rIter)
Definition: xmlictxt.hxx:113
css::uno::Reference< css::io::XOutputStream > GetStreamForGraphicObjectURLFromBase64() const
Definition: xmlimp.cxx:1305
const SvXMLEnumMapEntry< GraphicLocation > psXML_BrushVertPos[]
css::uno::Reference< css::io::XOutputStream > m_xBase64Stream
#define DBG_ASSERT(sCon, aError)
bool getNextToken(std::u16string_view &rToken)
Definition: xmluconv.cxx:516
static void lcl_xmlbic_MergeHoriPos(GraphicLocation &ePos, GraphicLocation eHori)
virtual void SAL_CALL endFastElement(sal_Int32 nElement) override
endFastElement is called before a context will be destructed, but after an elements context has been ...
static bool convertPercent(sal_Int32 &rValue, std::u16string_view rString)
::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:39
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:97
Smart struct to transport an Any with an index to the appropriate property-name.
Definition: maptype.hxx:122
static bool convertEnum(EnumT &rEnum, std::u16string_view 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:145
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 XMLOFF_WARN_UNKNOWN_ELEMENT(area, token)
Definition: xmlictxt.hxx:119
static void lcl_xmlbic_MergeVertPos(GraphicLocation &ePos, GraphicLocation eVert)
css::style::GraphicLocation ePos
sal_uInt16 nPos
const struct SvXMLEnumMapEntry< SvxGraphicPosition > psXML_BrushRepeat[]