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 .
20 #include <tools/urlobj.hxx>
21 #include <com/sun/star/document/XGraphicStorageHandler.hpp>
22 #include <com/sun/star/embed/ElementModes.hpp>
23 #include <com/sun/star/container/XNameContainer.hpp>
24 #include <com/sun/star/xml/sax/XDocumentHandler.hpp>
25 #include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp>
26 #include <com/sun/star/drawing/LineDash.hpp>
27 #include <com/sun/star/awt/Gradient.hpp>
28 #include <com/sun/star/awt/XBitmap.hpp>
29 #include <com/sun/star/drawing/Hatch.hpp>
30 #include <com/sun/star/io/XSeekable.hpp>
31 #include <comphelper/processfactory.hxx>
32 #include <comphelper/storagehelper.hxx>
33 #include <sax/tools/converter.hxx>
34 #include <sfx2/docfile.hxx>
35 #include <xmloff/xmlnamespace.hxx>
36 #include <xmloff/namespacemap.hxx>
38 #include <xmloff/xmltoken.hxx>
39 #include <xmloff/DashStyle.hxx>
40 #include <xmloff/GradientStyle.hxx>
41 #include <xmloff/HatchStyle.hxx>
42 #include <xmloff/ImageStyle.hxx>
43 #include <xmloff/MarkerStyle.hxx>
44 #include <xmloff/xmlictxt.hxx>
45 #include <svx/xmlgrhlp.hxx>
46 #include <xmloff/attrlist.hxx>
48 #include <xmlxtimp.hxx>
49 #include <tools/diagnose_ex.h>
51 using namespace com::sun::star
;
52 using namespace com::sun::star::container
;
53 using namespace com::sun::star::document
;
54 using namespace com::sun::star::uno
;
55 using namespace com::sun::star::awt
;
56 using namespace com::sun::star::lang
;
57 using namespace com::sun::star::xml::sax
;
58 using namespace ::xmloff::token
;
63 enum class SvxXMLTableImportContextEnum
{ Color
, Marker
, Dash
, Hatch
, Gradient
, Bitmap
};
65 class SvxXMLTableImportContext
: public SvXMLImportContext
68 SvxXMLTableImportContext( SvXMLImport
& rImport
, SvxXMLTableImportContextEnum eContext
, const uno::Reference
< XNameContainer
>& xTable
,
71 virtual css::uno::Reference
< css::xml::sax::XFastContextHandler
> SAL_CALL
72 createFastChildContext(sal_Int32 Element
,
73 const css::uno::Reference
< css::xml::sax::XFastAttributeList
> & Attribs
) override
;
76 static void importColor( const uno::Reference
< XFastAttributeList
>& xAttrList
, Any
& rAny
, OUString
& rName
);
77 void importMarker( const uno::Reference
< XFastAttributeList
>& xAttrList
, Any
& rAny
, OUString
& rName
);
78 void importDash( const uno::Reference
< XFastAttributeList
>& xAttrList
, Any
& rAny
, OUString
& rName
);
79 void importHatch( const uno::Reference
< XFastAttributeList
>& xAttrList
, Any
& rAny
, OUString
& rName
);
80 void importGradient( const uno::Reference
< XFastAttributeList
>& xAttrList
, Any
& rAny
, OUString
& rName
);
81 void importBitmap( const uno::Reference
< XFastAttributeList
>& xAttrList
, Any
& rAny
, OUString
& rName
);
84 uno::Reference
< XNameContainer
> mxTable
;
85 SvxXMLTableImportContextEnum meContext
;
91 SvxXMLTableImportContext::SvxXMLTableImportContext( SvXMLImport
& rImport
, SvxXMLTableImportContextEnum eContext
, const uno::Reference
< XNameContainer
>& xTable
, bool bOOoFormat
)
92 : SvXMLImportContext( rImport
), mxTable( xTable
), meContext( eContext
),
93 mbOOoFormat( bOOoFormat
)
97 css::uno::Reference
< css::xml::sax::XFastContextHandler
>
98 SvxXMLTableImportContext::createFastChildContext(sal_Int32 nElement
,
99 const css::uno::Reference
< css::xml::sax::XFastAttributeList
> & rAttrList
)
101 if( !(IsTokenInNamespace(nElement
, XML_NAMESPACE_DRAW
) ||
102 IsTokenInNamespace(nElement
, XML_NAMESPACE_DRAW_OOO
) ))
105 std::vector
<std::pair
<sal_Int32
, OString
>> aTmpAttrList
;
106 for (auto& aIter
: sax_fastparser::castToFastAttributeList( rAttrList
))
107 aTmpAttrList
.push_back({aIter
.getToken(), OString(aIter
.toCString())});
109 (SvxXMLTableImportContextEnum::Dash
== meContext
|| SvxXMLTableImportContextEnum::Hatch
== meContext
||
110 SvxXMLTableImportContextEnum::Bitmap
== meContext
) )
112 for( auto & aIter
: aTmpAttrList
)
114 sal_Int32 aLocalAttr
= aIter
.first
& TOKEN_MASK
;
115 if( aIter
.first
== XML_ELEMENT(XLINK
, XML_HREF
) &&
116 SvxXMLTableImportContextEnum::Bitmap
== meContext
)
118 OString rValue
= aIter
.second
;
119 if( !rValue
.isEmpty() && '#' == rValue
[0] )
120 rValue
= rValue
.copy( 1 );
122 else if( (IsTokenInNamespace(aIter
.first
, XML_NAMESPACE_DRAW
) || IsTokenInNamespace(aIter
.first
, XML_NAMESPACE_DRAW_OOO
)) &&
123 ( ( SvxXMLTableImportContextEnum::Dash
== meContext
&&
124 ( aLocalAttr
== XML_DOTS1_LENGTH
||
125 aLocalAttr
== XML_DOTS2_LENGTH
||
126 aLocalAttr
== XML_DISTANCE
) ) ||
127 ( SvxXMLTableImportContextEnum::Hatch
== meContext
&&
128 ( aLocalAttr
== XML_DISTANCE
) ) ) )
130 OString
& rValue
= aIter
.second
;
131 sal_Int32 nPos
= rValue
.getLength();
132 while( nPos
&& rValue
[nPos
-1] <= ' ' )
135 ('c'==rValue
[nPos
-2] || 'C'==rValue
[nPos
-2]) &&
136 ('h'==rValue
[nPos
-1] || 'H'==rValue
[nPos
-1]) )
138 rValue
= rValue
.copy( 0, nPos
-2 );
145 rtl::Reference
<sax_fastparser::FastAttributeList
> xFastList
= new sax_fastparser::FastAttributeList(nullptr);
146 for (auto& aIter
: aTmpAttrList
)
147 xFastList
->add(aIter
.first
, aIter
.second
);
154 case SvxXMLTableImportContextEnum::Color
:
155 importColor( xFastList
.get(), aAny
, aName
);
157 case SvxXMLTableImportContextEnum::Marker
:
158 importMarker( xFastList
.get(), aAny
, aName
);
160 case SvxXMLTableImportContextEnum::Dash
:
161 importDash( xFastList
.get(), aAny
, aName
);
163 case SvxXMLTableImportContextEnum::Hatch
:
164 importHatch( xFastList
.get(), aAny
, aName
);
166 case SvxXMLTableImportContextEnum::Gradient
:
167 importGradient( xFastList
.get(), aAny
, aName
);
169 case SvxXMLTableImportContextEnum::Bitmap
:
170 importBitmap( xFastList
.get(), aAny
, aName
);
174 if( !aName
.isEmpty() && aAny
.hasValue() )
176 if( mxTable
->hasByName( aName
) )
178 mxTable
->replaceByName( aName
, aAny
);
182 mxTable
->insertByName( aName
, aAny
);
186 catch (const uno::Exception
&)
188 DBG_UNHANDLED_EXCEPTION("svx");
190 return new SvXMLImportContext( GetImport() );
193 void SvxXMLTableImportContext::importColor( const uno::Reference
< XFastAttributeList
>& xAttrList
, Any
& rAny
, OUString
& rName
)
195 for (auto& aIter
: sax_fastparser::castToFastAttributeList( xAttrList
))
197 switch (aIter
.getToken())
199 case XML_ELEMENT(DRAW
, XML_NAME
):
200 case XML_ELEMENT(DRAW_OOO
, XML_NAME
):
201 rName
= aIter
.toString();
203 case XML_ELEMENT(DRAW
, XML_COLOR
):
204 case XML_ELEMENT(DRAW_OOO
, XML_COLOR
):
207 ::sax::Converter::convertColor(nColor
, aIter
.toString());
212 XMLOFF_WARN_UNKNOWN("xmloff", aIter
);
217 void SvxXMLTableImportContext::importMarker( const uno::Reference
< XFastAttributeList
>& xAttrList
, Any
& rAny
, OUString
& rName
)
221 XMLMarkerStyleImport
aMarkerStyle( GetImport() );
222 aMarkerStyle
.importXML( xAttrList
, rAny
, rName
);
224 catch (const Exception
&)
226 TOOLS_WARN_EXCEPTION("svx", "");
230 void SvxXMLTableImportContext::importDash( const uno::Reference
< XFastAttributeList
>& xAttrList
, Any
& rAny
, OUString
& rName
)
234 XMLDashStyleImport
aDashStyle( GetImport() );
235 aDashStyle
.importXML( xAttrList
, rAny
, rName
);
237 catch (const Exception
&)
239 TOOLS_WARN_EXCEPTION("svx", "");
243 void SvxXMLTableImportContext::importHatch( const uno::Reference
< XFastAttributeList
>& xAttrList
, Any
& rAny
, OUString
& rName
)
247 XMLHatchStyleImport
aHatchStyle( GetImport() );
248 aHatchStyle
.importXML( xAttrList
, rAny
, rName
);
250 catch (const Exception
&)
252 TOOLS_WARN_EXCEPTION("svx", "");
256 void SvxXMLTableImportContext::importGradient( const uno::Reference
< XFastAttributeList
>& xAttrList
, Any
& rAny
, OUString
& rName
)
260 XMLGradientStyleImport
aGradientStyle( GetImport() );
261 aGradientStyle
.importXML( xAttrList
, rAny
, rName
);
263 catch (const Exception
&)
265 TOOLS_WARN_EXCEPTION("svx", "");
269 void SvxXMLTableImportContext::importBitmap( const uno::Reference
< XFastAttributeList
>& xAttrList
, Any
& rAny
, OUString
& rName
)
273 uno::Any aGraphicAny
;
274 XMLImageStyle::importXML(xAttrList
, aGraphicAny
, rName
, GetImport());
275 if (aGraphicAny
.has
<uno::Reference
<graphic::XGraphic
>>())
277 auto xGraphic
= aGraphicAny
.get
<uno::Reference
<graphic::XGraphic
>>();
278 uno::Reference
<awt::XBitmap
> xBitmap(xGraphic
, uno::UNO_QUERY
);
283 catch (const Exception
&)
285 TOOLS_WARN_EXCEPTION("svx", "");
290 SvxXMLXTableImport::SvxXMLXTableImport(
291 const css::uno::Reference
< css::uno::XComponentContext
>& rContext
,
292 const uno::Reference
< XNameContainer
> & rTable
,
293 uno::Reference
<XGraphicStorageHandler
> const & xGraphicStorageHandler
)
294 : SvXMLImport(rContext
, "", SvXMLImportFlags::NONE
),
297 SetGraphicStorageHandler(xGraphicStorageHandler
);
299 GetNamespaceMap().Add( GetXMLToken(XML_NP_OOO
), GetXMLToken(XML_N_OOO
), XML_NAMESPACE_OOO
);
300 GetNamespaceMap().Add( GetXMLToken(XML_NP_OFFICE
), GetXMLToken(XML_N_OFFICE
), XML_NAMESPACE_OFFICE
);
301 GetNamespaceMap().Add( GetXMLToken(XML_NP_DRAW
), GetXMLToken(XML_N_DRAW
), XML_NAMESPACE_DRAW
);
302 GetNamespaceMap().Add( GetXMLToken(XML_NP_XLINK
), GetXMLToken(XML_N_XLINK
), XML_NAMESPACE_XLINK
);
304 GetNamespaceMap().Add( "__ooo", GetXMLToken(XML_N_OOO
), XML_NAMESPACE_OOO
);
305 GetNamespaceMap().Add( "__xlink", GetXMLToken(XML_N_XLINK
), XML_NAMESPACE_XLINK
);
307 // OOo namespaces for reading OOo 1.1 files
308 GetNamespaceMap().Add( "___office",
309 GetXMLToken(XML_N_OFFICE_OOO
),
310 XML_NAMESPACE_OFFICE
);
311 GetNamespaceMap().Add( "___draw",
312 GetXMLToken(XML_N_DRAW_OOO
),
313 XML_NAMESPACE_DRAW
);
316 SvxXMLXTableImport::~SvxXMLXTableImport() throw ()
320 static void openStorageStream( xml::sax::InputSource
*pParserInput
,
321 rtl::Reference
<SvXMLGraphicHelper
>& rxGraphicHelper
,
322 const uno::Reference
< embed::XStorage
>& xStorage
)
324 uno::Reference
< io::XStream
> xIStm( xStorage
->openStreamElement( "Content.xml", embed::ElementModes::READ
), uno::UNO_SET_THROW
);
325 pParserInput
->aInputStream
= xIStm
->getInputStream();
326 rxGraphicHelper
= SvXMLGraphicHelper::Create( xStorage
, SvXMLGraphicHelperMode::Read
);
329 bool SvxXMLXTableImport::load( const OUString
&rPath
, const OUString
&rReferer
,
330 const uno::Reference
< embed::XStorage
> &xStorage
,
331 const uno::Reference
< XNameContainer
>& xTable
,
332 bool *bOptLoadedFromStorage
) throw()
335 rtl::Reference
<SvXMLGraphicHelper
> xGraphicHelper
;
337 INetURLObject
aURLObj( rPath
);
338 bool bUseStorage
= aURLObj
.GetProtocol() == INetProtocol::NotValid
; // a relative path
342 uno::Reference
<uno::XComponentContext
> xContext( ::comphelper::getProcessComponentContext() );
344 xml::sax::InputSource aParserInput
;
345 comphelper::LifecycleProxy aNasty
;
347 if( !bUseStorage
|| !xStorage
.is() )
349 SfxMedium
aMedium( rPath
, rReferer
, StreamMode::READ
| StreamMode::NOCREATE
);
350 aParserInput
.sSystemId
= aMedium
.GetName();
352 if( aMedium
.IsStorage() )
354 uno::Reference
< embed::XStorage
> xMediumStorage( aMedium
.GetStorage( false ), uno::UNO_SET_THROW
);
355 openStorageStream( &aParserInput
, xGraphicHelper
, xMediumStorage
);
358 aParserInput
.aInputStream
= aMedium
.GetInputStream();
360 else // relative URL into a storage
362 uno::Reference
< embed::XStorage
> xSubStorage
;
365 xSubStorage
= comphelper::OStorageHelper::GetStorageAtPath(
366 xStorage
, rPath
, embed::ElementModes::READ
, aNasty
);
368 catch (const uno::Exception
&)
371 if( xSubStorage
.is() )
372 openStorageStream( &aParserInput
, xGraphicHelper
, xSubStorage
);
375 css::uno::Reference
< css::io::XStream
> xStream
= comphelper::OStorageHelper::GetStreamAtPath(
376 xStorage
, rPath
, embed::ElementModes::READ
, aNasty
);
379 aParserInput
.aInputStream
= xStream
->getInputStream();
381 if( bOptLoadedFromStorage
)
382 *bOptLoadedFromStorage
= true;
385 uno::Reference
<XGraphicStorageHandler
> xGraphicStorageHandler
;
386 if (xGraphicHelper
.is())
387 xGraphicStorageHandler
= xGraphicHelper
.get();
391 uno::Reference
< io::XSeekable
> xSeek( aParserInput
.aInputStream
, uno::UNO_QUERY_THROW
);
394 catch (const uno::Exception
&)
398 rtl::Reference
<SvxXMLXTableImport
> xImport(new SvxXMLXTableImport(xContext
, xTable
, xGraphicStorageHandler
));
399 xImport
->parseStream( aParserInput
);
402 xGraphicHelper
->dispose();
406 // thrown each time you load a document with property tables that are not
407 // on the current machine. FIXME: would be better to check a file exists
408 // before importing ...
415 SvXMLImportContext
*SvxXMLXTableImport::CreateFastContext( sal_Int32 nElement
,
416 const ::css::uno::Reference
< ::css::xml::sax::XFastAttributeList
>& /*xAttrList*/ )
418 if( IsTokenInNamespace(nElement
, XML_NAMESPACE_OOO
) ||
419 IsTokenInNamespace(nElement
, XML_NAMESPACE_OFFICE
) ||
420 IsTokenInNamespace(nElement
, XML_NAMESPACE_OFFICE_OOO
) )
422 bool bOOoFormat
= IsTokenInNamespace(nElement
, XML_NAMESPACE_OFFICE
) ||
423 IsTokenInNamespace(nElement
, XML_NAMESPACE_OFFICE_OOO
);
424 Type aType
= mrTable
->getElementType();
425 sal_Int32 nToken
= nElement
& TOKEN_MASK
;
427 if ( nToken
== XML_COLOR_TABLE
)
429 if( aType
== ::cppu::UnoType
<sal_Int32
>::get() )
430 return new SvxXMLTableImportContext( *this, SvxXMLTableImportContextEnum::Color
, mrTable
, bOOoFormat
);
432 else if ( nToken
== XML_MARKER_TABLE
)
434 if( aType
== cppu::UnoType
<drawing::PolyPolygonBezierCoords
>::get())
435 return new SvxXMLTableImportContext( *this, SvxXMLTableImportContextEnum::Marker
, mrTable
, bOOoFormat
);
437 else if ( nToken
== XML_DASH_TABLE
)
439 if( aType
== cppu::UnoType
<drawing::LineDash
>::get())
440 return new SvxXMLTableImportContext( *this, SvxXMLTableImportContextEnum::Dash
, mrTable
, bOOoFormat
);
442 else if ( nToken
== XML_HATCH_TABLE
)
444 if( aType
== cppu::UnoType
<drawing::Hatch
>::get())
445 return new SvxXMLTableImportContext( *this, SvxXMLTableImportContextEnum::Hatch
, mrTable
, bOOoFormat
);
447 else if ( nToken
== XML_GRADIENT_TABLE
)
449 if( aType
== cppu::UnoType
<awt::Gradient
>::get())
450 return new SvxXMLTableImportContext( *this, SvxXMLTableImportContextEnum::Gradient
, mrTable
, bOOoFormat
);
452 else if ( nToken
== XML_BITMAP_TABLE
)
454 if( aType
== ::cppu::UnoType
<awt::XBitmap
>::get())
455 return new SvxXMLTableImportContext( *this, SvxXMLTableImportContextEnum::Bitmap
, mrTable
, bOOoFormat
);
462 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */