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 .
23 #include <xml/imagesdocumenthandler.hxx>
25 #include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp>
26 #include <com/sun/star/xml/sax/SAXException.hpp>
28 #include <vcl/svapp.hxx>
29 #include <vcl/toolbox.hxx>
30 #include <rtl/ustrbuf.hxx>
32 #include <comphelper/attributelist.hxx>
34 using namespace ::com::sun::star::uno
;
35 using namespace ::com::sun::star::xml::sax
;
37 #define ELEMENT_IMAGECONTAINER "imagescontainer"
38 #define ELEMENT_IMAGES "images"
39 #define ELEMENT_ENTRY "entry"
40 #define ELEMENT_EXTERNALIMAGES "externalimages"
41 #define ELEMENT_EXTERNALENTRY "externalentry"
43 #define ELEMENT_NS_IMAGESCONTAINER "image:imagescontainer"
44 #define ELEMENT_NS_IMAGES "image:images"
45 #define ELEMENT_NS_ENTRY "image:entry"
47 #define ATTRIBUTE_HREF "href"
48 #define ATTRIBUTE_MASKCOLOR "maskcolor"
49 #define ATTRIBUTE_COMMAND "command"
50 #define ATTRIBUTE_BITMAPINDEX "bitmap-index"
51 #define ATTRIBUTE_MASKURL "maskurl"
52 #define ATTRIBUTE_MASKMODE "maskmode"
53 #define ATTRIBUTE_HIGHCONTRASTURL "highcontrasturl"
54 #define ATTRIBUTE_HIGHCONTRASTMASKURL "highcontrastmaskurl"
55 #define ATTRIBUTE_TYPE_CDATA "CDATA"
57 #define ATTRIBUTE_XMLNS_IMAGE "xmlns:image"
58 #define ATTRIBUTE_XMLNS_XLINK "xmlns:xlink"
60 #define ATTRIBUTE_XLINK_TYPE "xlink:type"
61 #define ATTRIBUTE_XLINK_TYPE_VALUE "simple"
63 #define XMLNS_IMAGE "http://openoffice.org/2001/image"
64 #define XMLNS_XLINK "http://www.w3.org/1999/xlink"
65 #define XMLNS_IMAGE_PREFIX "image:"
67 #define XMLNS_FILTER_SEPARATOR "^"
69 #define IMAGES_DOCTYPE "<!DOCTYPE image:imagecontainer PUBLIC \"-//OpenOffice.org//DTD OfficeDocument 1.0//EN\" \"image.dtd\">"
74 struct ImageXMLEntryProperty
76 OReadImagesDocumentHandler::Image_XML_Namespace nNamespace
;
80 ImageXMLEntryProperty
const ImagesEntries
[OReadImagesDocumentHandler::IMG_XML_ENTRY_COUNT
] =
82 { OReadImagesDocumentHandler::IMG_NS_IMAGE
, ELEMENT_IMAGECONTAINER
},
83 { OReadImagesDocumentHandler::IMG_NS_IMAGE
, ELEMENT_IMAGES
},
84 { OReadImagesDocumentHandler::IMG_NS_IMAGE
, ELEMENT_ENTRY
},
85 { OReadImagesDocumentHandler::IMG_NS_IMAGE
, ELEMENT_EXTERNALIMAGES
},
86 { OReadImagesDocumentHandler::IMG_NS_IMAGE
, ELEMENT_EXTERNALENTRY
},
87 { OReadImagesDocumentHandler::IMG_NS_XLINK
, ATTRIBUTE_HREF
},
88 { OReadImagesDocumentHandler::IMG_NS_IMAGE
, ATTRIBUTE_MASKCOLOR
},
89 { OReadImagesDocumentHandler::IMG_NS_IMAGE
, ATTRIBUTE_COMMAND
},
90 { OReadImagesDocumentHandler::IMG_NS_IMAGE
, ATTRIBUTE_BITMAPINDEX
},
91 { OReadImagesDocumentHandler::IMG_NS_IMAGE
, ATTRIBUTE_MASKURL
},
92 { OReadImagesDocumentHandler::IMG_NS_IMAGE
, ATTRIBUTE_MASKMODE
},
93 { OReadImagesDocumentHandler::IMG_NS_IMAGE
, ATTRIBUTE_HIGHCONTRASTURL
},
94 { OReadImagesDocumentHandler::IMG_NS_IMAGE
, ATTRIBUTE_HIGHCONTRASTMASKURL
}
97 OReadImagesDocumentHandler::OReadImagesDocumentHandler( ImageItemDescriptorList
& rItems
) :
98 m_rImageList( rItems
)
100 // create hash map to speed up lookup
101 for ( int i
= 0; i
< int(IMG_XML_ENTRY_COUNT
); i
++ )
103 OUStringBuffer
temp( 20 );
105 if ( ImagesEntries
[i
].nNamespace
== IMG_NS_IMAGE
)
106 temp
.append( XMLNS_IMAGE
);
108 temp
.append( XMLNS_XLINK
);
110 temp
.append( XMLNS_FILTER_SEPARATOR
);
111 temp
.appendAscii( ImagesEntries
[i
].aEntryName
);
112 m_aImageMap
.emplace( temp
.makeStringAndClear(), static_cast<Image_XML_Entry
>(i
) );
116 m_bImageContainerStartFound
= false;
117 m_bImageContainerEndFound
= false;
118 m_bImagesStartFound
= false;
121 OReadImagesDocumentHandler::~OReadImagesDocumentHandler()
126 void SAL_CALL
OReadImagesDocumentHandler::startDocument()
130 void SAL_CALL
OReadImagesDocumentHandler::endDocument()
134 if (m_bImageContainerStartFound
!= m_bImageContainerEndFound
)
136 OUString aErrorMessage
= getErrorLineString() + "No matching start or end element 'image:imagecontainer' found!";
137 throw SAXException( aErrorMessage
, Reference
< XInterface
>(), Any() );
141 void SAL_CALL
OReadImagesDocumentHandler::startElement(
142 const OUString
& aName
, const Reference
< XAttributeList
> &xAttribs
)
146 ImageHashMap::const_iterator pImageEntry
= m_aImageMap
.find( aName
);
147 if ( pImageEntry
!= m_aImageMap
.end() )
149 switch ( pImageEntry
->second
)
151 case IMG_ELEMENT_IMAGECONTAINER
:
153 // image:imagecontainer element (container element for all further image elements)
154 if ( m_bImageContainerStartFound
)
156 OUString aErrorMessage
= getErrorLineString() + "Element 'image:imagecontainer' cannot be embedded into 'image:imagecontainer'!";
157 throw SAXException( aErrorMessage
, Reference
< XInterface
>(), Any() );
160 m_bImageContainerStartFound
= true;
164 case IMG_ELEMENT_IMAGES
:
166 if ( !m_bImageContainerStartFound
)
168 OUString aErrorMessage
= getErrorLineString() + "Element 'image:images' must be embedded into element 'image:imagecontainer'!";
169 throw SAXException( aErrorMessage
, Reference
< XInterface
>(), Any() );
172 if ( m_bImagesStartFound
)
174 OUString aErrorMessage
= getErrorLineString() + "Element 'image:images' cannot be embedded into 'image:images'!";
175 throw SAXException( aErrorMessage
, Reference
< XInterface
>(), Any() );
178 m_bImagesStartFound
= true;
182 case IMG_ELEMENT_ENTRY
:
184 // Check that image:entry is embedded into image:images!
185 if ( !m_bImagesStartFound
)
187 OUString aErrorMessage
= getErrorLineString() + "Element 'image:entry' must be embedded into element 'image:images'!";
188 throw SAXException( aErrorMessage
, Reference
< XInterface
>(), Any() );
191 // Create new image item descriptor
192 ImageItemDescriptor aItem
;
194 // Read attributes for this image definition
195 for ( sal_Int16 n
= 0; n
< xAttribs
->getLength(); n
++ )
197 pImageEntry
= m_aImageMap
.find( xAttribs
->getNameByIndex( n
) );
198 if ( pImageEntry
!= m_aImageMap
.end() )
200 switch ( pImageEntry
->second
)
202 case IMG_ATTRIBUTE_COMMAND
:
204 aItem
.aCommandURL
= xAttribs
->getValueByIndex( n
);
214 // Check required attribute "command"
215 if ( aItem
.aCommandURL
.isEmpty() )
217 OUString aErrorMessage
= getErrorLineString() + "Required attribute 'image:command' must have a value!";
218 throw SAXException( aErrorMessage
, Reference
< XInterface
>(), Any() );
221 m_rImageList
.push_back( aItem
);
231 void SAL_CALL
OReadImagesDocumentHandler::endElement(const OUString
& aName
)
235 ImageHashMap::const_iterator pImageEntry
= m_aImageMap
.find( aName
);
236 if ( pImageEntry
!= m_aImageMap
.end() )
238 switch ( pImageEntry
->second
)
240 case IMG_ELEMENT_IMAGECONTAINER
:
242 m_bImageContainerEndFound
= true;
246 case IMG_ELEMENT_IMAGES
:
248 m_bImagesStartFound
= false;
257 void SAL_CALL
OReadImagesDocumentHandler::characters(const OUString
&)
261 void SAL_CALL
OReadImagesDocumentHandler::ignorableWhitespace(const OUString
&)
265 void SAL_CALL
OReadImagesDocumentHandler::processingInstruction(
266 const OUString
& /*aTarget*/, const OUString
& /*aData*/ )
270 void SAL_CALL
OReadImagesDocumentHandler::setDocumentLocator(
271 const Reference
< XLocator
> &xLocator
)
274 m_xLocator
= xLocator
;
277 OUString
OReadImagesDocumentHandler::getErrorLineString()
280 if ( m_xLocator
.is() )
282 OUStringBuffer
buffer("Line: ");
283 buffer
.append(m_xLocator
->getLineNumber());
284 buffer
.append(" - ");
285 return buffer
.makeStringAndClear();
291 // OWriteImagesDocumentHandler
293 OWriteImagesDocumentHandler::OWriteImagesDocumentHandler(
294 const ImageItemDescriptorList
& rItems
,
295 Reference
< XDocumentHandler
> const & rWriteDocumentHandler
) :
296 m_rImageItemList( rItems
),
297 m_xWriteDocumentHandler( rWriteDocumentHandler
)
299 ::comphelper::AttributeList
* pList
= new ::comphelper::AttributeList
;
300 m_xEmptyList
.set( static_cast<XAttributeList
*>(pList
), UNO_QUERY
);
301 m_aAttributeType
= ATTRIBUTE_TYPE_CDATA
;
302 m_aXMLImageNS
= XMLNS_IMAGE_PREFIX
;
303 m_aAttributeXlinkType
= ATTRIBUTE_XLINK_TYPE
;
304 m_aAttributeValueSimple
= ATTRIBUTE_XLINK_TYPE_VALUE
;
307 OWriteImagesDocumentHandler::~OWriteImagesDocumentHandler()
311 void OWriteImagesDocumentHandler::WriteImagesDocument()
315 m_xWriteDocumentHandler
->startDocument();
317 // write DOCTYPE line!
318 Reference
< XExtendedDocumentHandler
> xExtendedDocHandler( m_xWriteDocumentHandler
, UNO_QUERY
);
319 if ( xExtendedDocHandler
.is() )
321 xExtendedDocHandler
->unknown( IMAGES_DOCTYPE
);
322 m_xWriteDocumentHandler
->ignorableWhitespace( OUString() );
325 rtl::Reference
<::comphelper::AttributeList
> pList
= new ::comphelper::AttributeList
;
327 pList
->AddAttribute( ATTRIBUTE_XMLNS_IMAGE
,
331 pList
->AddAttribute( ATTRIBUTE_XMLNS_XLINK
,
335 m_xWriteDocumentHandler
->startElement( ELEMENT_NS_IMAGESCONTAINER
, pList
.get() );
336 m_xWriteDocumentHandler
->ignorableWhitespace( OUString() );
338 WriteImageList( &m_rImageItemList
);
340 m_xWriteDocumentHandler
->ignorableWhitespace( OUString() );
341 m_xWriteDocumentHandler
->endElement( ELEMENT_NS_IMAGESCONTAINER
);
342 m_xWriteDocumentHandler
->ignorableWhitespace( OUString() );
343 m_xWriteDocumentHandler
->endDocument();
346 // protected member functions
348 void OWriteImagesDocumentHandler::WriteImageList( const ImageItemDescriptorList
* pImageList
)
350 ::comphelper::AttributeList
* pList
= new ::comphelper::AttributeList
;
351 Reference
< XAttributeList
> xList( static_cast<XAttributeList
*>(pList
) , UNO_QUERY
);
353 // save required attributes
354 pList
->AddAttribute( m_aAttributeXlinkType
,
356 m_aAttributeValueSimple
);
358 m_xWriteDocumentHandler
->startElement( ELEMENT_NS_IMAGES
, xList
);
359 m_xWriteDocumentHandler
->ignorableWhitespace( OUString() );
361 for (const ImageItemDescriptor
& i
: *pImageList
)
364 m_xWriteDocumentHandler
->endElement( ELEMENT_NS_IMAGES
);
365 m_xWriteDocumentHandler
->ignorableWhitespace( OUString() );
368 void OWriteImagesDocumentHandler::WriteImage( const ImageItemDescriptor
* pImage
)
370 ::comphelper::AttributeList
* pList
= new ::comphelper::AttributeList
;
371 Reference
< XAttributeList
> xList( static_cast<XAttributeList
*>(pList
) , UNO_QUERY
);
373 pList
->AddAttribute( m_aXMLImageNS
+ ATTRIBUTE_COMMAND
,
375 pImage
->aCommandURL
);
377 m_xWriteDocumentHandler
->startElement( ELEMENT_NS_ENTRY
, xList
);
378 m_xWriteDocumentHandler
->ignorableWhitespace( OUString() );
380 m_xWriteDocumentHandler
->endElement( ELEMENT_NS_ENTRY
);
381 m_xWriteDocumentHandler
->ignorableWhitespace( OUString() );
384 } // namespace framework
386 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */