1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
23 #include <com/sun/star/graphic/XGraphic.hpp>
25 #include <tools/debug.hxx>
26 #include <sal/log.hxx>
27 #include <sax/tools/converter.hxx>
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>
36 #include <xmloff/XMLBase64ImportContext.hxx>
37 #include <XMLBackgroundImageContext.hxx>
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
;
46 const SvXMLEnumMapEntry
<GraphicLocation
> psXML_BrushHoriPos
[] =
48 { XML_LEFT
, GraphicLocation_LEFT_MIDDLE
},
49 { XML_RIGHT
, GraphicLocation_RIGHT_MIDDLE
},
50 { XML_TOKEN_INVALID
, GraphicLocation(0) }
53 const SvXMLEnumMapEntry
<GraphicLocation
> psXML_BrushVertPos
[] =
55 { XML_TOP
, GraphicLocation_MIDDLE_TOP
},
56 { XML_BOTTOM
, GraphicLocation_MIDDLE_BOTTOM
},
57 { XML_TOKEN_INVALID
, GraphicLocation(0) }
60 static void lcl_xmlbic_MergeHoriPos( GraphicLocation
& ePos
,
61 GraphicLocation eHori
)
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" );
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
);
80 case GraphicLocation_LEFT_MIDDLE
:
81 case GraphicLocation_MIDDLE_MIDDLE
:
82 case GraphicLocation_RIGHT_MIDDLE
:
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
);
100 static void lcl_xmlbic_MergeVertPos( GraphicLocation
& ePos
,
101 GraphicLocation eVert
)
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" );
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
);
120 case GraphicLocation_MIDDLE_TOP
:
121 case GraphicLocation_MIDDLE_MIDDLE
:
122 case GraphicLocation_MIDDLE_BOTTOM
:
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
);
141 void XMLBackgroundImageContext::ProcessAttrs(
142 const Reference
< xml::sax::XFastAttributeList
>& xAttrList
)
144 ePos
= GraphicLocation_NONE
;
146 for (auto &aIter
: sax_fastparser::castToFastAttributeList(xAttrList
))
148 switch( aIter
.getToken() )
150 case XML_ELEMENT(XLINK
, XML_HREF
):
151 m_sURL
= aIter
.toString();
152 if( GraphicLocation_NONE
== ePos
)
153 ePos
= GraphicLocation_TILED
;
155 case XML_ELEMENT(XLINK
, XML_TYPE
):
156 case XML_ELEMENT(XLINK
, XML_ACTUATE
):
157 case XML_ELEMENT(XLINK
, XML_SHOW
):
159 case XML_ELEMENT(STYLE
, XML_POSITION
):
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;
167 while( bOK
&& aTokenEnum
.getNextToken( aToken
) )
169 GraphicLocation nTmpGraphicLocation
;
174 else if( std::u16string_view::npos
!= aToken
.find( '%' ) )
177 if (::sax::Converter::convertPercent( nPrc
, aToken
))
182 ? GraphicLocation_LEFT_TOP
183 : (nPrc
< 75 ? GraphicLocation_MIDDLE_MIDDLE
184 : GraphicLocation_RIGHT_BOTTOM
);
190 ? GraphicLocation_LEFT_TOP
191 : (nPrc
< 75 ? GraphicLocation_LEFT_MIDDLE
192 : GraphicLocation_LEFT_BOTTOM
);
193 lcl_xmlbic_MergeVertPos( eNewPos
, eTmp
);
203 else if( IsXMLToken( aToken
, XML_CENTER
) )
206 lcl_xmlbic_MergeVertPos( eNewPos
,
207 GraphicLocation_MIDDLE_MIDDLE
);
209 lcl_xmlbic_MergeHoriPos( eNewPos
,
210 GraphicLocation_MIDDLE_MIDDLE
);
212 eNewPos
= GraphicLocation_MIDDLE_MIDDLE
;
214 else if( SvXMLUnitConverter::convertEnum( nTmpGraphicLocation
, aToken
,
215 psXML_BrushHoriPos
) )
218 lcl_xmlbic_MergeHoriPos( eNewPos
, nTmpGraphicLocation
);
220 eNewPos
= nTmpGraphicLocation
;
225 else if( SvXMLUnitConverter::convertEnum( nTmpGraphicLocation
, aToken
,
226 psXML_BrushVertPos
) )
229 lcl_xmlbic_MergeVertPos( eNewPos
, nTmpGraphicLocation
);
231 eNewPos
= nTmpGraphicLocation
;
242 bOK
&= GraphicLocation_NONE
!= eNewPos
;
247 case XML_ELEMENT(STYLE
, XML_REPEAT
):
249 GraphicLocation nPos
= GraphicLocation_NONE
;
250 static const SvXMLEnumMapEntry
<GraphicLocation
> psXML_BrushRepeat
[] =
252 { XML_REPEAT
, GraphicLocation_TILED
},
253 { XML_BACKGROUND_NO_REPEAT
, GraphicLocation_MIDDLE_MIDDLE
},
254 { XML_STRETCH
, GraphicLocation_AREA
},
255 { XML_TOKEN_INVALID
, GraphicLocation(0) }
257 if( SvXMLUnitConverter::convertEnum( nPos
, aIter
.toView(),
258 psXML_BrushRepeat
) )
260 if( GraphicLocation_MIDDLE_MIDDLE
!= nPos
||
261 GraphicLocation_NONE
== ePos
||
262 GraphicLocation_AREA
== ePos
||
263 GraphicLocation_TILED
== ePos
)
268 case XML_ELEMENT(STYLE
, XML_FILTER_NAME
):
269 sFilter
= aIter
.toString();
271 case XML_ELEMENT(DRAW
, XML_OPACITY
):
274 // convert from percent and clip
275 if (::sax::Converter::convertPercent( nTmp
, aIter
.toView() ))
277 if( (nTmp
>= 0) && (nTmp
<= 100) )
278 nTransparency
= static_cast<sal_Int8
>( 100-nTmp
);
283 XMLOFF_WARN_UNKNOWN("xmloff", aIter
);
289 XMLBackgroundImageContext::XMLBackgroundImageContext(
290 SvXMLImport
& rImport
, sal_Int32 nElement
,
291 const Reference
< xml::sax::XFastAttributeList
> & xAttrList
,
292 const XMLPropertyState
& rProp
,
294 sal_Int32 nFilterIdx
,
295 sal_Int32 nTransparencyIdx
,
296 sal_Int32 nBitmapModeIdx
,
297 ::std::vector
< XMLPropertyState
> &rProps
) :
298 XMLElementPropertyContext( rImport
, nElement
, rProp
, rProps
),
300 m_nBitmapModeIdx(nBitmapModeIdx
),
301 aFilterProp( nFilterIdx
),
302 aTransparencyProp( nTransparencyIdx
),
305 ProcessAttrs( xAttrList
);
308 XMLBackgroundImageContext::~XMLBackgroundImageContext()
312 css::uno::Reference
< css::xml::sax::XFastContextHandler
> XMLBackgroundImageContext::createFastChildContext(
314 const css::uno::Reference
< css::xml::sax::XFastAttributeList
>& /*xAttrList*/ )
316 if( nElement
== XML_ELEMENT(OFFICE
, xmloff::token::XML_BINARY_DATA
) )
318 if( m_sURL
.isEmpty() && !m_xBase64Stream
.is() )
320 m_xBase64Stream
= GetImport().GetStreamForGraphicObjectURLFromBase64();
321 if( m_xBase64Stream
.is() )
322 return new XMLBase64ImportContext( GetImport(), m_xBase64Stream
);
325 XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement
);
329 void XMLBackgroundImageContext::endFastElement(sal_Int32 nElement
)
331 uno::Reference
<graphic::XGraphic
> xGraphic
;
332 if (!m_sURL
.isEmpty())
334 xGraphic
= GetImport().loadGraphicByURL(m_sURL
);
336 else if (m_xBase64Stream
.is())
338 xGraphic
= GetImport().loadGraphicFromBase64(m_xBase64Stream
);
339 m_xBase64Stream
= nullptr;
343 ePos
= GraphicLocation_NONE
;
344 else if (GraphicLocation_NONE
== ePos
)
345 ePos
= GraphicLocation_TILED
;
348 aProp
.maValue
<<= xGraphic
;
349 aPosProp
.maValue
<<= ePos
;
350 aFilterProp
.maValue
<<= sFilter
;
351 aTransparencyProp
.maValue
<<= nTransparency
;
354 XMLElementPropertyContext::endFastElement(nElement
);
356 if( -1 != aPosProp
.mnIndex
)
358 // See if a FillBitmapMode property is already set, in that case
359 // BackGraphicLocation will be ignored.
361 if (m_nBitmapModeIdx
!= -1)
363 for (XMLPropertyState
& rProperty
: rProperties
)
365 if (rProperty
.mnIndex
== m_nBitmapModeIdx
)
369 // Found, so map the old property to the new one.
372 case GraphicLocation_TILED
:
373 rProperty
.maValue
<<= drawing::BitmapMode_REPEAT
;
375 case GraphicLocation_AREA
:
376 rProperty
.maValue
<<= drawing::BitmapMode_STRETCH
;
378 case GraphicLocation_MIDDLE_MIDDLE
:
379 rProperty
.maValue
<<= drawing::BitmapMode_NO_REPEAT
;
389 rProperties
.push_back( aPosProp
);
391 if( -1 != aFilterProp
.mnIndex
)
392 rProperties
.push_back( aFilterProp
);
393 if( -1 != aTransparencyProp
.mnIndex
)
394 rProperties
.push_back( aTransparencyProp
);
397 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */