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/io/XActiveDataControl.hpp>
24 #include <com/sun/star/io/XActiveDataSource.hpp>
25 #include <com/sun/star/xml/sax/Parser.hpp>
26 #include <com/sun/star/container/XNameContainer.hpp>
27 #include <com/sun/star/xml/sax/XDocumentHandler.hpp>
28 #include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp>
29 #include <com/sun/star/drawing/LineDash.hpp>
30 #include <com/sun/star/awt/Gradient.hpp>
31 #include <com/sun/star/awt/XBitmap.hpp>
32 #include <com/sun/star/drawing/Hatch.hpp>
33 #include <com/sun/star/io/XOutputStream.hpp>
34 #include <com/sun/star/io/XSeekable.hpp>
35 #include <comphelper/processfactory.hxx>
36 #include <comphelper/storagehelper.hxx>
37 #include <unotools/streamwrap.hxx>
38 #include <rtl/ustrbuf.hxx>
39 #include <sax/tools/converter.hxx>
40 #include <sfx2/docfile.hxx>
41 #include <xmloff/xmlnmspe.hxx>
42 #include <xmloff/nmspmap.hxx>
44 #include <xmloff/xmltoken.hxx>
45 #include <xmloff/xmlmetae.hxx>
46 #include <xmloff/DashStyle.hxx>
47 #include <xmloff/GradientStyle.hxx>
48 #include <xmloff/HatchStyle.hxx>
49 #include <xmloff/ImageStyle.hxx>
50 #include <xmloff/MarkerStyle.hxx>
51 #include <xmloff/xmlictxt.hxx>
52 #include <svx/xmlgrhlp.hxx>
53 #include <xmloff/attrlist.hxx>
55 #include <xmlxtimp.hxx>
59 using namespace com::sun::star
;
60 using namespace com::sun::star::container
;
61 using namespace com::sun::star::document
;
62 using namespace com::sun::star::uno
;
63 using namespace com::sun::star::awt
;
64 using namespace com::sun::star::lang
;
65 using namespace com::sun::star::xml::sax
;
66 using namespace ::xmloff::token
;
69 enum class SvxXMLTableImportContextEnum
{ Color
, Marker
, Dash
, Hatch
, Gradient
, Bitmap
};
72 class SvxXMLTableImportContext
: public SvXMLImportContext
75 SvxXMLTableImportContext( SvXMLImport
& rImport
, sal_uInt16 nPrfx
, const OUString
& rLName
, SvxXMLTableImportContextEnum eContext
, const uno::Reference
< XNameContainer
>& xTable
,
78 virtual SvXMLImportContextRef
CreateChildContext( sal_uInt16 nPrefix
, const OUString
& rLocalName
, const uno::Reference
< XAttributeList
>& xAttrList
) override
;
81 void importColor( const uno::Reference
< XAttributeList
>& xAttrList
, Any
& rAny
, OUString
& rName
);
82 void importMarker( const uno::Reference
< XAttributeList
>& xAttrList
, Any
& rAny
, OUString
& rName
);
83 void importDash( const uno::Reference
< XAttributeList
>& xAttrList
, Any
& rAny
, OUString
& rName
);
84 void importHatch( const uno::Reference
< XAttributeList
>& xAttrList
, Any
& rAny
, OUString
& rName
);
85 void importGradient( const uno::Reference
< XAttributeList
>& xAttrList
, Any
& rAny
, OUString
& rName
);
86 void importBitmap( const uno::Reference
< XAttributeList
>& xAttrList
, Any
& rAny
, OUString
& rName
);
89 uno::Reference
< XNameContainer
> mxTable
;
90 SvxXMLTableImportContextEnum
const meContext
;
91 bool const mbOOoFormat
;
95 SvxXMLTableImportContext::SvxXMLTableImportContext( SvXMLImport
& rImport
, sal_uInt16 nPrfx
, const OUString
& rLName
, SvxXMLTableImportContextEnum eContext
, const uno::Reference
< XNameContainer
>& xTable
, bool bOOoFormat
)
96 : SvXMLImportContext( rImport
, nPrfx
, rLName
), mxTable( xTable
), meContext( eContext
),
97 mbOOoFormat( bOOoFormat
)
101 SvXMLImportContextRef
SvxXMLTableImportContext::CreateChildContext( sal_uInt16 nPrefix
, const OUString
& rLocalName
, const uno::Reference
< XAttributeList
>& rAttrList
)
103 if( XML_NAMESPACE_DRAW
== nPrefix
)
105 uno::Reference
< XAttributeList
> xAttrList( rAttrList
);
107 (SvxXMLTableImportContextEnum::Dash
== meContext
|| SvxXMLTableImportContextEnum::Hatch
== meContext
||
108 SvxXMLTableImportContextEnum::Bitmap
== meContext
) )
110 SvXMLAttributeList
*pAttrList
= new SvXMLAttributeList( rAttrList
);
111 xAttrList
= pAttrList
;
112 sal_Int16 nAttrCount
= xAttrList
.is() ? xAttrList
->getLength() : 0;
113 for( sal_Int16 i
=0; i
< nAttrCount
; i
++ )
115 const OUString
& rAttrName
= xAttrList
->getNameByIndex( i
);
117 sal_uInt16 nPrefix_
=
118 GetImport().GetNamespaceMap().GetKeyByAttrName( rAttrName
,
120 if( XML_NAMESPACE_XLINK
== nPrefix_
&&
121 SvxXMLTableImportContextEnum::Bitmap
== meContext
&&
122 IsXMLToken( aLocalName
, XML_HREF
) )
124 const OUString rValue
= xAttrList
->getValueByIndex( i
);
125 if( !rValue
.isEmpty() && '#' == rValue
[0] )
126 pAttrList
->SetValueByIndex( i
, rValue
.copy( 1 ) );
128 else if( XML_NAMESPACE_DRAW
== nPrefix_
&&
129 ( ( SvxXMLTableImportContextEnum::Dash
== meContext
&&
130 (IsXMLToken( aLocalName
, XML_DOTS1_LENGTH
) ||
131 IsXMLToken( aLocalName
, XML_DOTS2_LENGTH
) ||
132 IsXMLToken( aLocalName
, XML_DISTANCE
)) ) ||
133 ( SvxXMLTableImportContextEnum::Hatch
== meContext
&&
134 IsXMLToken( aLocalName
, XML_HATCH_DISTANCE
) ) ) )
136 const OUString rValue
= xAttrList
->getValueByIndex( i
);
137 sal_Int32 nPos
= rValue
.getLength();
138 while( nPos
&& rValue
[nPos
-1] <= ' ' )
141 ('c'==rValue
[nPos
-2] || 'C'==rValue
[nPos
-2]) &&
142 ('h'==rValue
[nPos
-1] || 'H'==rValue
[nPos
-1]) )
144 pAttrList
->SetValueByIndex( i
, rValue
.copy( 0, nPos
-2 ) );
156 case SvxXMLTableImportContextEnum::Color
:
157 importColor( xAttrList
, aAny
, aName
);
159 case SvxXMLTableImportContextEnum::Marker
:
160 importMarker( xAttrList
, aAny
, aName
);
162 case SvxXMLTableImportContextEnum::Dash
:
163 importDash( xAttrList
, aAny
, aName
);
165 case SvxXMLTableImportContextEnum::Hatch
:
166 importHatch( xAttrList
, aAny
, aName
);
168 case SvxXMLTableImportContextEnum::Gradient
:
169 importGradient( xAttrList
, aAny
, aName
);
171 case SvxXMLTableImportContextEnum::Bitmap
:
172 importBitmap( xAttrList
, aAny
, aName
);
176 if( !aName
.isEmpty() && aAny
.hasValue() )
178 if( mxTable
->hasByName( aName
) )
180 mxTable
->replaceByName( aName
, aAny
);
184 mxTable
->insertByName( aName
, aAny
);
188 catch (const uno::Exception
&)
193 return new SvXMLImportContext( GetImport(), nPrefix
, rLocalName
);
196 void SvxXMLTableImportContext::importColor( const uno::Reference
< XAttributeList
>& xAttrList
, Any
& rAny
, OUString
& rName
)
198 const sal_Int16 nAttrCount
= xAttrList
.is() ? xAttrList
->getLength() : 0;
199 for( sal_Int16 i
=0; i
< nAttrCount
; i
++ )
201 const OUString
& rFullAttrName
= xAttrList
->getNameByIndex( i
);
203 sal_uInt16 nPrefix
= GetImport().GetNamespaceMap().GetKeyByAttrName( rFullAttrName
, &aLocalName
);
206 if( XML_NAMESPACE_DRAW
== nPrefix
)
208 if( aLocalName
== GetXMLToken(XML_NAME
) )
210 rName
= xAttrList
->getValueByIndex( i
);
212 else if( aLocalName
== GetXMLToken(XML_COLOR
) )
215 ::sax::Converter::convertColor(nColor
,
216 xAttrList
->getValueByIndex( i
));
223 void SvxXMLTableImportContext::importMarker( const uno::Reference
< XAttributeList
>& xAttrList
, Any
& rAny
, OUString
& rName
)
227 XMLMarkerStyleImport
aMarkerStyle( GetImport() );
228 aMarkerStyle
.importXML( xAttrList
, rAny
, rName
);
230 catch (const Exception
&)
232 OSL_FAIL("SvxXMLTableImportContext::importMarker(), exception caught!");
236 void SvxXMLTableImportContext::importDash( const uno::Reference
< XAttributeList
>& xAttrList
, Any
& rAny
, OUString
& rName
)
240 XMLDashStyleImport
aDashStyle( GetImport() );
241 aDashStyle
.importXML( xAttrList
, rAny
, rName
);
243 catch (const Exception
&)
245 OSL_FAIL("SvxXMLTableImportContext::importDash(), exception caught!");
249 void SvxXMLTableImportContext::importHatch( const uno::Reference
< XAttributeList
>& xAttrList
, Any
& rAny
, OUString
& rName
)
253 XMLHatchStyleImport
aHatchStyle( GetImport() );
254 aHatchStyle
.importXML( xAttrList
, rAny
, rName
);
256 catch (const Exception
&)
258 OSL_FAIL("SvxXMLTableImportContext::importHatch(), exception caught!");
262 void SvxXMLTableImportContext::importGradient( const uno::Reference
< XAttributeList
>& xAttrList
, Any
& rAny
, OUString
& rName
)
266 XMLGradientStyleImport
aGradientStyle( GetImport() );
267 aGradientStyle
.importXML( xAttrList
, rAny
, rName
);
269 catch (const Exception
&)
271 OSL_FAIL("SvxXMLTableImportContext::importGradient(), exception caught!");
275 void SvxXMLTableImportContext::importBitmap( const uno::Reference
< XAttributeList
>& xAttrList
, Any
& rAny
, OUString
& rName
)
279 uno::Any aGraphicAny
;
280 XMLImageStyle::importXML(xAttrList
, aGraphicAny
, rName
, GetImport());
281 if (aGraphicAny
.has
<uno::Reference
<graphic::XGraphic
>>())
283 auto xGraphic
= aGraphicAny
.get
<uno::Reference
<graphic::XGraphic
>>();
284 uno::Reference
<awt::XBitmap
> xBitmap(xGraphic
, uno::UNO_QUERY
);
289 catch (const Exception
&)
291 OSL_FAIL("SvxXMLTableImportContext::importBitmap(), exception caught!");
296 SvxXMLXTableImport::SvxXMLXTableImport(
297 const css::uno::Reference
< css::uno::XComponentContext
>& rContext
,
298 const uno::Reference
< XNameContainer
> & rTable
,
299 uno::Reference
<XGraphicStorageHandler
> const & xGraphicStorageHandler
)
300 : SvXMLImport(rContext
, "", SvXMLImportFlags::NONE
),
303 SetGraphicStorageHandler(xGraphicStorageHandler
);
305 GetNamespaceMap().Add( "__ooo", GetXMLToken(XML_N_OOO
), XML_NAMESPACE_OOO
);
306 GetNamespaceMap().Add( "__office", GetXMLToken(XML_N_OFFICE
), XML_NAMESPACE_OFFICE
);
307 GetNamespaceMap().Add( "__draw", GetXMLToken(XML_N_DRAW
), XML_NAMESPACE_DRAW
);
308 GetNamespaceMap().Add( "__xlink", GetXMLToken(XML_N_XLINK
), XML_NAMESPACE_XLINK
);
310 // OOo namespaces for reading OOo 1.1 files
311 GetNamespaceMap().Add( "___office",
312 GetXMLToken(XML_N_OFFICE_OOO
),
313 XML_NAMESPACE_OFFICE
);
314 GetNamespaceMap().Add( "___draw",
315 GetXMLToken(XML_N_DRAW_OOO
),
316 XML_NAMESPACE_DRAW
);
319 SvxXMLXTableImport::~SvxXMLXTableImport() throw ()
323 static void openStorageStream( xml::sax::InputSource
*pParserInput
,
324 rtl::Reference
<SvXMLGraphicHelper
>& rxGraphicHelper
,
325 const uno::Reference
< embed::XStorage
>& xStorage
)
327 uno::Reference
< io::XStream
> xIStm( xStorage
->openStreamElement( "Content.xml", embed::ElementModes::READ
), uno::UNO_QUERY_THROW
);
328 pParserInput
->aInputStream
= xIStm
->getInputStream();
329 rxGraphicHelper
= SvXMLGraphicHelper::Create( xStorage
, SvXMLGraphicHelperMode::Read
);
332 bool SvxXMLXTableImport::load( const OUString
&rPath
, const OUString
&rReferer
,
333 const uno::Reference
< embed::XStorage
> &xStorage
,
334 const uno::Reference
< XNameContainer
>& xTable
,
335 bool *bOptLoadedFromStorage
) throw()
338 rtl::Reference
<SvXMLGraphicHelper
> xGraphicHelper
;
340 INetURLObject
aURLObj( rPath
);
341 bool bUseStorage
= aURLObj
.GetProtocol() == INetProtocol::NotValid
; // a relative path
345 uno::Reference
<uno::XComponentContext
> xContext( ::comphelper::getProcessComponentContext() );
347 uno::Reference
< xml::sax::XParser
> xParser
= xml::sax::Parser::create( xContext
);
349 xml::sax::InputSource aParserInput
;
350 comphelper::LifecycleProxy aNasty
;
352 if( !bUseStorage
|| !xStorage
.is() )
354 SfxMedium
aMedium( rPath
, rReferer
, StreamMode::READ
| StreamMode::NOCREATE
);
355 aParserInput
.sSystemId
= aMedium
.GetName();
357 if( aMedium
.IsStorage() )
359 uno::Reference
< embed::XStorage
> xMediumStorage( aMedium
.GetStorage( false ), uno::UNO_QUERY_THROW
);
360 openStorageStream( &aParserInput
, xGraphicHelper
, xMediumStorage
);
363 aParserInput
.aInputStream
= aMedium
.GetInputStream();
365 else // relative URL into a storage
367 uno::Reference
< embed::XStorage
> xSubStorage
;
370 xSubStorage
= comphelper::OStorageHelper::GetStorageAtPath(
371 xStorage
, rPath
, embed::ElementModes::READ
, aNasty
);
373 catch (const uno::Exception
&)
376 if( xSubStorage
.is() )
377 openStorageStream( &aParserInput
, xGraphicHelper
, xSubStorage
);
380 css::uno::Reference
< css::io::XStream
> xStream
;
381 xStream
= comphelper::OStorageHelper::GetStreamAtPath(
382 xStorage
, rPath
, embed::ElementModes::READ
, aNasty
);
385 aParserInput
.aInputStream
= xStream
->getInputStream();
387 if( bOptLoadedFromStorage
)
388 *bOptLoadedFromStorage
= true;
391 uno::Reference
<XGraphicStorageHandler
> xGraphicStorageHandler
;
392 if (xGraphicHelper
.is())
393 xGraphicStorageHandler
= xGraphicHelper
.get();
397 uno::Reference
< io::XSeekable
> xSeek( aParserInput
.aInputStream
, uno::UNO_QUERY_THROW
);
400 catch (const uno::Exception
&)
404 uno::Reference
<XDocumentHandler
> xHandler(new SvxXMLXTableImport(xContext
, xTable
, xGraphicStorageHandler
));
405 xParser
->setDocumentHandler( xHandler
);
406 xParser
->parseStream( aParserInput
);
409 xGraphicHelper
->dispose();
413 // thrown each time you load a document with property tables that are not
414 // on the current machine. FIXME: would be better to check a file exists
415 // before importing ...
422 SvXMLImportContext
*SvxXMLXTableImport::CreateDocumentContext(
423 sal_uInt16
const nPrefix
, const OUString
& rLocalName
,
424 const uno::Reference
< XAttributeList
>& /*xAttrList*/)
426 if( XML_NAMESPACE_OOO
== nPrefix
||
427 XML_NAMESPACE_OFFICE
== nPrefix
)
429 bool bOOoFormat
= (XML_NAMESPACE_OFFICE
== nPrefix
);
430 Type aType
= mrTable
->getElementType();
432 if ( rLocalName
== "color-table" )
434 if( aType
== ::cppu::UnoType
<sal_Int32
>::get() )
435 return new SvxXMLTableImportContext( *this, nPrefix
, rLocalName
, SvxXMLTableImportContextEnum::Color
, mrTable
, bOOoFormat
);
437 else if ( rLocalName
== "marker-table" )
439 if( aType
== cppu::UnoType
<drawing::PolyPolygonBezierCoords
>::get())
440 return new SvxXMLTableImportContext( *this, nPrefix
, rLocalName
, SvxXMLTableImportContextEnum::Marker
, mrTable
, bOOoFormat
);
442 else if ( rLocalName
== "dash-table" )
444 if( aType
== cppu::UnoType
<drawing::LineDash
>::get())
445 return new SvxXMLTableImportContext( *this, nPrefix
, rLocalName
, SvxXMLTableImportContextEnum::Dash
, mrTable
, bOOoFormat
);
447 else if ( rLocalName
== "hatch-table" )
449 if( aType
== cppu::UnoType
<drawing::Hatch
>::get())
450 return new SvxXMLTableImportContext( *this, nPrefix
, rLocalName
, SvxXMLTableImportContextEnum::Hatch
, mrTable
, bOOoFormat
);
452 else if ( rLocalName
== "gradient-table" )
454 if( aType
== cppu::UnoType
<awt::Gradient
>::get())
455 return new SvxXMLTableImportContext( *this, nPrefix
, rLocalName
, SvxXMLTableImportContextEnum::Gradient
, mrTable
, bOOoFormat
);
457 else if ( rLocalName
== "bitmap-table" )
459 if( aType
== ::cppu::UnoType
<awt::XBitmap
>::get())
460 return new SvxXMLTableImportContext( *this, nPrefix
, rLocalName
, SvxXMLTableImportContextEnum::Bitmap
, mrTable
, bOOoFormat
);
464 return new SvXMLImportContext( *this, nPrefix
, rLocalName
);
467 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */