/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "EPUBExportFilter.hxx" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "exp/xmlimp.hxx" #include "EPUBPackage.hxx" using namespace com::sun::star; namespace writerperfect { EPUBExportFilter::EPUBExportFilter(uno::Reference xContext) : mxContext(std::move(xContext)) { } sal_Int32 EPUBExportFilter::GetDefaultVersion() { return 30; } sal_Int32 EPUBExportFilter::GetDefaultSplitMethod() { return libepubgen::EPUB_SPLIT_METHOD_HEADING; } sal_Int32 EPUBExportFilter::GetDefaultLayoutMethod() { return libepubgen::EPUB_LAYOUT_METHOD_REFLOWABLE; } sal_Bool EPUBExportFilter::filter(const uno::Sequence& rDescriptor) { sal_Int32 nVersion = EPUBExportFilter::GetDefaultVersion(); sal_Int32 nSplitMethod = EPUBExportFilter::GetDefaultSplitMethod(); sal_Int32 nLayoutMethod = EPUBExportFilter::GetDefaultLayoutMethod(); uno::Sequence aFilterData; OUString aFilterOptions; for (const auto& rProp : rDescriptor) { if (rProp.Name == "FilterData") rProp.Value >>= aFilterData; else if (rProp.Name == "FilterOptions") rProp.Value >>= aFilterOptions; } if (aFilterOptions == "layout=fixed") nLayoutMethod = libepubgen::EPUB_LAYOUT_METHOD_FIXED; for (const auto& rProp : std::as_const(aFilterData)) { if (rProp.Name == "EPUBVersion") rProp.Value >>= nVersion; else if (rProp.Name == "EPUBSplitMethod") rProp.Value >>= nSplitMethod; else if (rProp.Name == "EPUBLayoutMethod") rProp.Value >>= nLayoutMethod; } // Build the export filter chain: the package has direct access to the ZIP // file, the flat ODF filter has access to the doc model, everything else // is in-between. EPUBPackage aPackage(mxContext, rDescriptor); libepubgen::EPUBTextGenerator aGenerator(&aPackage, nVersion); aGenerator.setOption(libepubgen::EPUB_GENERATOR_OPTION_SPLIT, nSplitMethod); aGenerator.setOption(libepubgen::EPUB_GENERATOR_OPTION_LAYOUT, nLayoutMethod); OUString aSourceURL; uno::Reference xSourceModel(mxSourceDocument, uno::UNO_QUERY); if (xSourceModel.is()) aSourceURL = xSourceModel->getURL(); std::vector aPageMetafiles; if (nLayoutMethod == libepubgen::EPUB_LAYOUT_METHOD_FIXED) CreateMetafiles(aPageMetafiles); uno::Reference xExportHandler( new exp::XMLImport(mxContext, aGenerator, aSourceURL, rDescriptor, aPageMetafiles)); uno::Reference xInitialization( mxContext->getServiceManager()->createInstanceWithContext( "com.sun.star.comp.Writer.XMLOasisExporter", mxContext), uno::UNO_QUERY); // A subset of parameters are passed in as a property set. static comphelper::PropertyMapEntry const aInfoMap[] = { { OUString("BaseURI"), 0, cppu::UnoType::get(), beans::PropertyAttribute::MAYBEVOID, 0 } }; uno::Reference xInfoSet( comphelper::GenericPropertySet_CreateInstance(new comphelper::PropertySetInfo(aInfoMap))); xInfoSet->setPropertyValue("BaseURI", uno::Any(aSourceURL)); xInitialization->initialize({ uno::Any(xExportHandler), uno::Any(xInfoSet) }); uno::Reference xExporter(xInitialization, uno::UNO_QUERY); xExporter->setSourceDocument(mxSourceDocument); uno::Reference xFilter(xInitialization, uno::UNO_QUERY); return xFilter->filter(rDescriptor); } void EPUBExportFilter::CreateMetafiles(std::vector& rPageMetafiles) { DocumentToGraphicRenderer aRenderer(mxSourceDocument, /*bSelectionOnly=*/false); uno::Reference xModel(mxSourceDocument, uno::UNO_QUERY); if (!xModel.is()) return; uno::Reference xTextViewCursorSupplier( xModel->getCurrentController(), uno::UNO_QUERY); if (!xTextViewCursorSupplier.is()) return; uno::Reference xCursor(xTextViewCursorSupplier->getViewCursor(), uno::UNO_QUERY); if (!xCursor.is()) return; xCursor->jumpToLastPage(); sal_Int16 nPages = xCursor->getPage(); for (sal_Int16 nPage = 1; nPage <= nPages; ++nPage) { Size aDocumentSizePixel = aRenderer.getDocumentSizeInPixels(nPage); Size aLogic = aRenderer.getDocumentSizeIn100mm(nPage); // Get the CSS pixel size of the page (mm100 -> pixel using 96 DPI, independent from system DPI). Size aCss(static_cast(aLogic.getWidth()) / 26.4583, static_cast(aLogic.getHeight()) / 26.4583); Graphic aGraphic = aRenderer.renderToGraphic(nPage, aDocumentSizePixel, aCss, COL_WHITE, /*bExtOutDevData=*/true); auto& rGDIMetaFile = const_cast(aGraphic.GetGDIMetaFile()); // Set preferred map unit and size on the metafile, so the SVG size // will be correct in MM. MapMode aMapMode; aMapMode.SetMapUnit(MapUnit::Map100thMM); rGDIMetaFile.SetPrefMapMode(aMapMode); rGDIMetaFile.SetPrefSize(aLogic); SvMemoryStream aMemoryStream; SvmWriter aWriter(aMemoryStream); aWriter.Write(rGDIMetaFile); uno::Sequence aSequence(static_cast(aMemoryStream.GetData()), aMemoryStream.Tell()); exp::FixedLayoutPage aPage; aPage.aMetafile = aSequence; aPage.aCssPixels = aCss; aPage.aChapterNames = aRenderer.getChapterNames(); rPageMetafiles.push_back(aPage); } } void EPUBExportFilter::cancel() {} void EPUBExportFilter::setSourceDocument(const uno::Reference& xDocument) { mxSourceDocument = xDocument; } OUString EPUBExportFilter::getImplementationName() { return "com.sun.star.comp.Writer.EPUBExportFilter"; } sal_Bool EPUBExportFilter::supportsService(const OUString& rServiceName) { return cppu::supportsService(this, rServiceName); } uno::Sequence EPUBExportFilter::getSupportedServiceNames() { uno::Sequence aRet = { OUString("com.sun.star.document.ExportFilter") }; return aRet; } extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface* com_sun_star_comp_Writer_EPUBExportFilter_get_implementation( uno::XComponentContext* pContext, uno::Sequence const& /*rSeq*/) { return cppu::acquire(new EPUBExportFilter(pContext)); } } // namespace writerperfect /* vim:set shiftwidth=4 softtabstop=4 expandtab: */