16#include <initializer_list>
17#include <unordered_map>
19#include <com/sun/star/svg/XSVGWriter.hpp>
20#include <com/sun/star/uri/UriReferenceFactory.hpp>
21#include <com/sun/star/xml/sax/InputSource.hpp>
22#include <com/sun/star/xml/sax/Parser.hpp>
23#include <com/sun/star/xml/sax/Writer.hpp>
44OUString GetMimeType(
const OUString& rExtension)
46 static const std::unordered_map<OUString, OUString> vMimeTypes = {
47 {
"gif",
"image/gif" },
48 {
"jpg",
"image/jpeg" },
49 {
"png",
"image/png" },
50 {
"svg",
"image/svg+xml" },
53 auto it = vMimeTypes.find(rExtension);
54 return it == vMimeTypes.end() ? OUString() : it->second;
58OUString FindMediaDir(
const OUString& rDocumentBaseURL,
64 auto pProp = std::find_if(
65 rFilterData.begin(), rFilterData.end(),
66 [](
const beans::PropertyValue& rProp) { return rProp.Name ==
"RVNGMediaDir"; });
67 if (pProp != rFilterData.end())
68 pProp->Value >>= aMediaDir;
70 if (!aMediaDir.isEmpty())
71 return aMediaDir +
"/";
77 aMediaDir = rtl::Uri::convertRelToAbs(rDocumentBaseURL,
aURL.GetBase()) +
"/";
79 catch (
const rtl::MalformedUriException&)
87OUString FindCoverImage(
const OUString& rDocumentBaseURL, OUString& rMimeType,
93 auto pProp = std::find_if(
94 rFilterData.begin(), rFilterData.end(),
95 [](
const beans::PropertyValue& rProp) { return rProp.Name ==
"RVNGCoverImage"; });
96 if (pProp != rFilterData.end())
97 pProp->Value >>= aRet;
102 rMimeType = GetMimeType(aRetURL.GetFileExtension());
107 if (rDocumentBaseURL.isEmpty())
110 static const std::initializer_list<std::u16string_view> vExtensions
111 = {
u"gif",
u"jpg",
u"png",
u"svg" };
113 OUString aMediaDir = FindMediaDir(rDocumentBaseURL, rFilterData);
114 for (
const auto& rExtension : vExtensions)
116 aRet = aMediaDir +
"cover." + rExtension;
120 if (aStream.IsOpen())
122 rMimeType = GetMimeType(OUString(rExtension));
136 const OUString& rDocumentBaseURL,
138 librevenge::RVNGPropertyList& rMetaData)
142 for (
const auto& rProp : rFilterData)
144 if (rProp.Name ==
"RVNGIdentifier")
146 rProp.Value >>= aValue;
147 if (!aValue.isEmpty())
148 rMetaData.insert(
"dc:identifier", aValue.toUtf8().getStr());
150 else if (rProp.Name ==
"RVNGTitle")
152 rProp.Value >>= aValue;
153 if (!aValue.isEmpty())
154 rMetaData.insert(
"dc:title", aValue.toUtf8().getStr());
156 else if (rProp.Name ==
"RVNGInitialCreator")
158 rProp.Value >>= aValue;
159 if (!aValue.isEmpty())
160 rMetaData.insert(
"meta:initial-creator", aValue.toUtf8().getStr());
162 else if (rProp.Name ==
"RVNGLanguage")
164 rProp.Value >>= aValue;
165 if (!aValue.isEmpty())
166 rMetaData.insert(
"dc:language", aValue.toUtf8().getStr());
168 else if (rProp.Name ==
"RVNGDate")
170 rProp.Value >>= aValue;
171 if (!aValue.isEmpty())
172 rMetaData.insert(
"dc:date", aValue.toUtf8().getStr());
177 if (rDocumentBaseURL.isEmpty())
180 OUString aMediaDir = FindMediaDir(rDocumentBaseURL, rFilterData);
181 OUString
aURL = aMediaDir +
"metadata.xmp";
183 if (!aStream.IsOpen())
186 xml::sax::InputSource aInputSource;
188 aInputSource.aInputStream =
xStream;
191 xParser->setDocumentHandler(xXMP);
194 xParser->parseStream(aInputSource);
196 catch (
const uno::Exception&)
204class XMLBodyContext :
public XMLImportContext
207 XMLBodyContext(XMLImport& rImport);
210 CreateChildContext(
const OUString& rName,
215XMLBodyContext::XMLBodyContext(XMLImport& rImport)
216 : XMLImportContext(rImport)
221XMLBodyContext::CreateChildContext(
const OUString& rName,
224 if (rName ==
"office:text")
225 return new XMLBodyContentContext(GetImport());
232class XMLOfficeDocContext :
public XMLImportContext
235 XMLOfficeDocContext(XMLImport& rImport);
238 CreateChildContext(
const OUString& rName,
242 void HandleFixedLayoutPage(
const FixedLayoutPage& rPage,
bool bFirst);
246XMLOfficeDocContext::XMLOfficeDocContext(XMLImport& rImport)
247 : XMLImportContext(rImport)
254 if (rName ==
"office:meta")
255 return new XMLMetaDocumentContext(GetImport());
256 if (rName ==
"office:automatic-styles")
257 return new XMLStylesContext(GetImport(), XMLStylesContext::StyleType_AUTOMATIC);
258 if (rName ==
"office:styles")
259 return new XMLStylesContext(GetImport(), XMLStylesContext::StyleType_NONE);
260 if (rName ==
"office:master-styles")
261 return new XMLStylesContext(GetImport(), XMLStylesContext::StyleType_NONE);
262 if (rName ==
"office:font-face-decls")
263 return new XMLFontFaceDeclsContext(GetImport());
264 if (rName ==
"office:body")
266 if (GetImport().GetPageMetafiles().empty())
267 return new XMLBodyContext(GetImport());
272 for (
const auto& rPage : GetImport().GetPageMetafiles())
274 HandleFixedLayoutPage(rPage, bFirst);
282void XMLOfficeDocContext::HandleFixedLayoutPage(
const FixedLayoutPage& rPage,
bool bFirst)
286 if (!xSaxWriter.is())
293 xCtx->getServiceManager()->createInstanceWithArgumentsAndContext(
294 "com.sun.star.svg.SVGWriter", aArguments, xCtx),
296 if (!xSVGWriter.is())
302 xSVGWriter->write(xSaxWriter, rPage.aMetafile);
305 librevenge::RVNGPropertyList aPageProperties;
307 double fWidth = rPage.aCssPixels.getWidth();
309 aPageProperties.insert(
"fo:page-width", fWidth);
310 double fHeight = rPage.aCssPixels.getHeight();
312 aPageProperties.insert(
"fo:page-height", fHeight);
314 if (!rPage.aChapterNames.empty())
317 librevenge::RVNGPropertyListVector aChapterNames;
318 for (
const auto& rName : rPage.aChapterNames)
320 librevenge::RVNGPropertyList aChapter;
321 aChapter.insert(
"librevenge:name", rName.toUtf8().getStr());
322 aChapterNames.append(aChapter);
324 aPageProperties.insert(
"librevenge:chapter-names", aChapterNames);
327 GetImport().GetGenerator().openPageSpan(aPageProperties);
328 librevenge::RVNGPropertyList aParagraphProperties;
332 aParagraphProperties.insert(
"fo:break-before",
"page");
333 GetImport().GetGenerator().openParagraph(aParagraphProperties);
334 librevenge::RVNGPropertyList aImageProperties;
335 aImageProperties.insert(
"librevenge:mime-type",
"image/svg+xml");
336 librevenge::RVNGBinaryData aBinaryData;
337 aBinaryData.append(
static_cast<const unsigned char*
>(aMemoryStream.
GetData()),
339 aImageProperties.insert(
"office:binary-data", aBinaryData);
340 GetImport().GetGenerator().insertBinaryObject(aImageProperties);
341 GetImport().GetGenerator().closeParagraph();
342 GetImport().GetGenerator().closePageSpan();
346 librevenge::RVNGTextInterface& rGenerator,
const OUString& rURL,
348 const std::vector<FixedLayoutPage>& rPageMetafiles)
349 : mrGenerator(rGenerator)
351 , mbIsInPageSpan(false)
352 , mrPageMetafiles(rPageMetafiles)
355 auto pDescriptor = std::find_if(
356 rDescriptor.begin(), rDescriptor.end(),
357 [](
const beans::PropertyValue& rProp) { return rProp.Name ==
"FilterData"; });
358 if (pDescriptor != rDescriptor.end())
359 pDescriptor->Value >>= aFilterData;
364 OUString aCoverImage = FindCoverImage(rURL,
aMimeType, aFilterData);
365 if (!aCoverImage.isEmpty())
367 librevenge::RVNGBinaryData aBinaryData;
371 aBinaryData.append(
static_cast<const unsigned char*
>(aMemoryStream.
GetData()),
373 librevenge::RVNGPropertyList aCoverImageProperties;
374 aCoverImageProperties.insert(
"office:binary-data", aBinaryData);
375 aCoverImageProperties.insert(
"librevenge:mime-type",
aMimeType.toUtf8().getStr());
394bool FileURLExists(
const OUString& rURL)
397 return aStream.IsOpen();
408 catch (
const uno::Exception&)
412 bool bAbsolute =
true;
414 bAbsolute = xUriRef->isAbsolute();
421 if (!FileURLExists(aAbs))
426 if (!FileURLExists(aAbs))
432 librevenge::RVNGBinaryData aBinaryData;
435 aBinaryData.append(
static_cast<const unsigned char*
>(aMemoryStream.
GetData()),
437 rPropList.insert(
"office:binary-data", aBinaryData);
441 rPropList.insert(
"librevenge:mime-type",
aMimeType.toUtf8().getStr());
457 if (rName ==
u"office:document")
458 return new XMLOfficeDocContext(*
this);
552 xContext =
maContexts.top()->CreateChildContext(rName, xAttribs);
558 xContext->startElement(rName, xAttribs);
588 OUString sMasterPageName;
589 OUString sLayoutName;
591 if (rPropertyList[
"style:master-page-name"])
592 sMasterPageName = OStringToOUString(
593 rPropertyList[
"style:master-page-name"]->getStr().cstr(), RTL_TEXTENCODING_UTF8);
595 sMasterPageName =
"Standard";
597 if (sMasterPageName.getLength())
599 librevenge::RVNGPropertyList& rMasterPage =
GetMasterStyles()[sMasterPageName];
600 if (rMasterPage[
"style:page-layout-name"])
602 sLayoutName = OStringToOUString(rMasterPage[
"style:page-layout-name"]->getStr().cstr(),
603 RTL_TEXTENCODING_UTF8);
607 if (sLayoutName.getLength())
609 librevenge::RVNGPropertyList& rPageLayout =
GetPageLayouts()[sLayoutName];
OUString GetFileExtension() const
SvStream & WriteStream(SvStream &rStream)
void SAL_CALL endDocument() override
std::map< OUString, librevenge::RVNGPropertyList > maAutomaticGraphicStyles
const css::uno::Reference< css::uno::XComponentContext > & mxContext
std::map< OUString, librevenge::RVNGPropertyList > maParagraphStyles
void HandlePageSpan(const librevenge::RVNGPropertyList &rPropertyList)
std::map< OUString, librevenge::RVNGPropertyList > & GetParagraphStyles()
std::map< OUString, librevenge::RVNGPropertyList > maRowStyles
std::map< OUString, librevenge::RVNGPropertyList > maTextStyles
std::map< OUString, librevenge::RVNGPropertyList > maAutomaticRowStyles
std::map< OUString, librevenge::RVNGPropertyList > & GetPageLayouts()
void SAL_CALL startElement(const OUString &rName, const css::uno::Reference< css::xml::sax::XAttributeList > &xAttribs) override
css::uno::Reference< css::uri::XUriReferenceFactory > mxUriReferenceFactory
std::map< OUString, librevenge::RVNGPropertyList > & GetTextStyles()
std::map< OUString, librevenge::RVNGPropertyList > & GetCellStyles()
rtl::Reference< XMLImportContext > CreateContext(std::u16string_view rName, const css::uno::Reference< css::xml::sax::XAttributeList > &xAttribs)
std::map< OUString, librevenge::RVNGPropertyList > & GetColumnStyles()
std::map< OUString, librevenge::RVNGPropertyList > & GetAutomaticRowStyles()
std::map< OUString, librevenge::RVNGPropertyList > maCellStyles
const librevenge::RVNGPropertyList & GetMetaData() const
std::map< OUString, librevenge::RVNGPropertyList > & GetAutomaticTableStyles()
std::map< OUString, librevenge::RVNGPropertyList > & GetAutomaticParagraphStyles()
std::map< OUString, librevenge::RVNGPropertyList > maColumnStyles
std::map< OUString, librevenge::RVNGPropertyList > & GetTableStyles()
std::map< OUString, librevenge::RVNGPropertyList > & GetAutomaticColumnStyles()
const css::uno::Reference< css::uno::XComponentContext > & GetComponentContext() const
const std::vector< FixedLayoutPage > & GetPageMetafiles() const
const std::vector< FixedLayoutPage > & mrPageMetafiles
void SAL_CALL ignorableWhitespace(const OUString &rWhitespaces) override
std::map< OUString, librevenge::RVNGPropertyList > maAutomaticColumnStyles
std::map< OUString, librevenge::RVNGPropertyList > & GetGraphicStyles()
librevenge::RVNGPropertyList maMetaData
Author, date, etc – overwrites what would be from the document out of the box.
void SAL_CALL startDocument() override
std::map< OUString, librevenge::RVNGPropertyList > maAutomaticParagraphStyles
std::map< OUString, librevenge::RVNGPropertyList > & GetMasterStyles()
void SAL_CALL setDocumentLocator(const css::uno::Reference< css::xml::sax::XLocator > &xLocator) override
std::map< OUString, librevenge::RVNGPropertyList > & GetRowStyles()
std::map< OUString, librevenge::RVNGPropertyList > maAutomaticCellStyles
std::map< OUString, librevenge::RVNGPropertyList > & GetAutomaticCellStyles()
librevenge::RVNGTextInterface & mrGenerator
bool GetIsInPageSpan() const
std::map< OUString, librevenge::RVNGPropertyList > maTableStyles
std::map< OUString, librevenge::RVNGPropertyList > & GetAutomaticTextStyles()
PopupState FillPopupData(const OUString &rURL, librevenge::RVNGPropertyList &rPropList)
std::map< OUString, librevenge::RVNGPropertyList > & GetAutomaticGraphicStyles()
std::map< OUString, librevenge::RVNGPropertyList > maAutomaticTextStyles
std::map< OUString, librevenge::RVNGPropertyList > maPageLayouts
void SAL_CALL processingInstruction(const OUString &rTarget, const OUString &rData) override
std::map< OUString, librevenge::RVNGPropertyList > maMasterStyles
void SAL_CALL characters(const OUString &rChars) override
void SAL_CALL endElement(const OUString &rName) override
std::map< OUString, librevenge::RVNGPropertyList > maGraphicStyles
std::stack< rtl::Reference< XMLImportContext > > maContexts
librevenge::RVNGPropertyListVector maCoverImages
std::map< OUString, librevenge::RVNGPropertyList > maAutomaticTableStyles
const librevenge::RVNGPropertyListVector & GetCoverImages() const
librevenge::RVNGTextInterface & GetGenerator() const
#define DBG_UNHANDLED_EXCEPTION(...)
Sequence< PropertyValue > aArguments
css::beans::PropertyValue makePropertyValue(const OUString &rName, T &&rValue)
PopupState
States describing the result of a link -> popup conversion.
@ Consumed
The relative link was converted to a popup.
@ NotConsumed
The absolute link was not handled.
@ Ignore
The relative link is invalid and should be ignored.
const sal_Unicode *const aMimeType[]