diff options
-rw-r--r-- | avmedia/Library_avmedia.mk | 1 | ||||
-rw-r--r-- | avmedia/source/framework/mediaitem.cxx | 11 | ||||
-rw-r--r-- | avmedia/source/framework/modeltools.cxx | 198 | ||||
-rw-r--r-- | include/avmedia/mediaitem.hxx | 5 | ||||
-rw-r--r-- | include/avmedia/modeltools.hxx | 22 | ||||
-rw-r--r-- | include/sal/log-areas.dox | 6 | ||||
-rw-r--r-- | sd/source/ui/func/fuinsert.cxx | 2 | ||||
-rw-r--r-- | sd/source/ui/inc/View.hxx | 7 | ||||
-rw-r--r-- | sd/source/ui/view/sdview4.cxx | 34 |
9 files changed, 274 insertions, 12 deletions
diff --git a/avmedia/Library_avmedia.mk b/avmedia/Library_avmedia.mk index 3c723f19e0e7..935222798313 100644 --- a/avmedia/Library_avmedia.mk +++ b/avmedia/Library_avmedia.mk @@ -47,6 +47,7 @@ $(eval $(call gb_Library_add_exception_objects,avmedia,\ avmedia/source/framework/mediamisc \ avmedia/source/framework/mediaplayer \ avmedia/source/framework/mediatoolbox \ + avmedia/source/framework/modeltools \ avmedia/source/framework/soundhandler \ avmedia/source/viewer/mediaevent_impl \ avmedia/source/viewer/mediawindow \ diff --git a/avmedia/source/framework/mediaitem.cxx b/avmedia/source/framework/mediaitem.cxx index b9ab635cdc72..32f6f043ca0e 100644 --- a/avmedia/source/framework/mediaitem.cxx +++ b/avmedia/source/framework/mediaitem.cxx @@ -23,7 +23,6 @@ #include <com/sun/star/beans/XPropertySet.hpp> #include <com/sun/star/embed/ElementModes.hpp> -#include <com/sun/star/embed/XStorage.hpp> #include <com/sun/star/embed/XTransactedObject.hpp> #include <com/sun/star/document/XStorageBasedDocument.hpp> #include <com/sun/star/ucb/XCommandEnvironment.hpp> @@ -313,7 +312,7 @@ void MediaItem::setZoom( ::com::sun::star::media::ZoomLevel eZoom ) return m_pImpl->m_eZoom; } -static OUString lcl_GetFilename(OUString const& rSourceURL) +OUString GetFilename(OUString const& rSourceURL) { uno::Reference<uri::XUriReferenceFactory> const xUriFactory( uri::UriReferenceFactory::create( @@ -337,8 +336,8 @@ static OUString lcl_GetFilename(OUString const& rSourceURL) return filename; } -static uno::Reference<io::XStream> -lcl_CreateStream(uno::Reference<embed::XStorage> const& xStorage, +uno::Reference<io::XStream> +CreateStream(uno::Reference<embed::XStorage> const& xStorage, OUString const& rFilename) { OUString filename(rFilename); @@ -397,10 +396,10 @@ bool EmbedMedia(uno::Reference<frame::XModel> const& xModel, uno::Reference<embed::XStorage> const xSubStorage( xStorage->openStorageElement(media, embed::ElementModes::WRITE)); - OUString filename(lcl_GetFilename(rSourceURL)); + OUString filename(GetFilename(rSourceURL)); uno::Reference<io::XStream> const xStream( - lcl_CreateStream(xSubStorage, filename), uno::UNO_SET_THROW); + CreateStream(xSubStorage, filename), uno::UNO_SET_THROW); uno::Reference<io::XOutputStream> const xOutStream( xStream->getOutputStream(), uno::UNO_SET_THROW); diff --git a/avmedia/source/framework/modeltools.cxx b/avmedia/source/framework/modeltools.cxx new file mode 100644 index 000000000000..10da986cd803 --- /dev/null +++ b/avmedia/source/framework/modeltools.cxx @@ -0,0 +1,198 @@ +/* -*- 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 <avmedia/modeltools.hxx> +#include <avmedia/mediaitem.hxx> + +#include <com/sun/star/embed/ElementModes.hpp> +#include <com/sun/star/embed/XTransactedObject.hpp> +#include <com/sun/star/document/XStorageBasedDocument.hpp> +#include <com/sun/star/embed/XStorage.hpp> +#include <osl/file.hxx> +#include <comphelper/processfactory.hxx> +#include <tools/urlobj.hxx> +#include <ucbhelper/content.hxx> + +#include <boost/property_tree/ptree.hpp> +#include <boost/property_tree/json_parser.hpp> +#include <boost/foreach.hpp> + +#include <string> +#include <vector> + +using namespace ::com::sun::star; +using namespace boost::property_tree; + +namespace avmedia { + +static void lcl_EmbedExternals(const OUString& rSourceURL, uno::Reference<embed::XStorage> xSubStorage, ::ucbhelper::Content& rContent) +{ + // Create a temp file with which json parser can work. + OUString sTempFileURL; + const ::osl::FileBase::RC aErr = + ::osl::FileBase::createTempFile(0, 0, &sTempFileURL); + if (::osl::FileBase::E_None != aErr) + { + SAL_WARN("avmedia.model", "cannot create temp file"); + return; + } + try + { + // Write json content to the temp file + ::ucbhelper::Content aTempContent(sTempFileURL, + uno::Reference<ucb::XCommandEnvironment>(), + comphelper::getProcessComponentContext()); + aTempContent.writeStream(rContent.openStream(), true); + } + catch (uno::Exception const& e) + { + SAL_WARN("avmedia.model", "exception: '" << e.Message << "'"); + return; + } + + // Convert URL to a file path for loading + const INetURLObject aURLObj(sTempFileURL); + std::string sUrl = OUStringToOString( aURLObj.getFSysPath(INetURLObject::FSYS_DETECT), RTL_TEXTENCODING_UTF8 ).getStr(); + + // Parse json, read externals' URI and modify this relative URI's so they remain valid in the new context. + std::vector<std::string> vExternals; + ptree aTree; + try + { + json_parser::read_json( sUrl, aTree ); + + // Buffers for geometry and animations + BOOST_FOREACH(ptree::value_type &rVal,aTree.get_child("buffers")) + { + const std::string sBufferUri(rVal.second.get<std::string>("path")); + vExternals.push_back(sBufferUri); + // Change path: make it contain only a file name + aTree.put("buffers." + rVal.first + ".path.",sBufferUri.substr(sBufferUri.find_last_of('/')+1)); + } + // Images for textures + BOOST_FOREACH(ptree::value_type &rVal,aTree.get_child("images")) + { + const std::string sImageUri(rVal.second.get<std::string>("path")); + vExternals.push_back(sImageUri); + // Change path: make it contain only a file name + aTree.put("images." + rVal.first + ".path.",sImageUri.substr(sImageUri.find_last_of('/')+1)); + } + // Shaders (contains names only) + BOOST_FOREACH(ptree::value_type &rVal,aTree.get_child("programs")) + { + vExternals.push_back(rVal.second.get<std::string>("fragmentShader") + ".glsl"); + vExternals.push_back(rVal.second.get<std::string>("vertexShader") + ".glsl"); + } + + // Write out modified json + json_parser::write_json( sUrl, aTree ); + } + catch ( boost::exception const& ) + { + SAL_WARN("avmedia.model", "failed to parse json file"); + return; + } + + // Reload json with modified path to external resources + rContent = ::ucbhelper::Content("file://" + OUString::createFromAscii(sUrl.c_str()), + uno::Reference<ucb::XCommandEnvironment>(), + comphelper::getProcessComponentContext()); + + // Store all external files next to the json file + for( std::vector<std::string>::iterator aCIter = vExternals.begin(); aCIter != vExternals.end(); ++aCIter ) + { + const OUString sAbsURL = INetURLObject::GetAbsURL(rSourceURL,OUString::createFromAscii(aCIter->c_str())); + + ::ucbhelper::Content aContent(sAbsURL, + uno::Reference<ucb::XCommandEnvironment>(), + comphelper::getProcessComponentContext()); + + uno::Reference<io::XStream> const xStream( + CreateStream(xSubStorage, GetFilename(sAbsURL)), uno::UNO_SET_THROW); + uno::Reference<io::XOutputStream> const xOutStream( + xStream->getOutputStream(), uno::UNO_SET_THROW); + + if (!aContent.openStream(xOutStream)) + { + SAL_WARN("avmedia.model", "openStream to storage failed"); + return; + } + } +} + +bool Embed3DModel( const uno::Reference<frame::XModel>& xModel, + const OUString& rSourceURL, OUString& o_rEmbeddedURL) +{ + try + { + ::ucbhelper::Content aSourceContent(rSourceURL, + uno::Reference<ucb::XCommandEnvironment>(), + comphelper::getProcessComponentContext()); + + // Base storage + uno::Reference<document::XStorageBasedDocument> const xSBD(xModel, + uno::UNO_QUERY_THROW); + uno::Reference<embed::XStorage> const xStorage( + xSBD->getDocumentStorage(), uno::UNO_QUERY_THROW); + + // Model storage + const OUString sModel("Model"); + uno::Reference<embed::XStorage> const xModelStorage( + xStorage->openStorageElement(sModel, embed::ElementModes::WRITE)); + + // Own storage of the corresponding model + const OUString sFilename(GetFilename(rSourceURL)); + const OUString sGLTFDir(sFilename.copy(0,sFilename.lastIndexOf('.'))); + uno::Reference<embed::XStorage> const xSubStorage( + xModelStorage->openStorageElement(sGLTFDir, embed::ElementModes::WRITE)); + + // Embed external resources + lcl_EmbedExternals(rSourceURL, xSubStorage, aSourceContent); + + // Save model file (.json) + uno::Reference<io::XStream> const xStream( + CreateStream(xSubStorage, sFilename), uno::UNO_SET_THROW); + uno::Reference<io::XOutputStream> const xOutStream( + xStream->getOutputStream(), uno::UNO_SET_THROW); + + if (!aSourceContent.openStream(xOutStream)) + { + SAL_INFO("avmedia.model", "openStream to storage failed"); + return false; + } + + const uno::Reference<embed::XTransactedObject> xSubTransaction(xSubStorage, uno::UNO_QUERY); + if (xSubTransaction.is()) + { + xSubTransaction->commit(); + } + const uno::Reference<embed::XTransactedObject> xModelTransaction(xModelStorage, uno::UNO_QUERY); + if (xModelTransaction.is()) + { + xModelTransaction->commit(); + } + const uno::Reference<embed::XTransactedObject> xTransaction(xStorage, uno::UNO_QUERY); + if (xTransaction.is()) + { + xTransaction->commit(); + } + + o_rEmbeddedURL = "vnd.sun.star.Package:" + sModel + "/" + sGLTFDir + "/" + sFilename; + return true; + } + catch (uno::Exception const&) + { + SAL_WARN("avmedia.model", "Exception while trying to embed model"); + } + return false; +} + +} // namespace avemdia + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/avmedia/mediaitem.hxx b/include/avmedia/mediaitem.hxx index 97a63a961597..c512e2654eb9 100644 --- a/include/avmedia/mediaitem.hxx +++ b/include/avmedia/mediaitem.hxx @@ -26,6 +26,7 @@ #include <svl/poolitem.hxx> #include <com/sun/star/media/ZoomLevel.hpp> #include <com/sun/star/frame/XModel.hpp> +#include <com/sun/star/embed/XStorage.hpp> #include <avmedia/avmediadllapi.h> #define AVMEDIA_SETMASK_NONE ((sal_uInt32)(0x00000000)) @@ -128,6 +129,10 @@ bool AVMEDIA_DLLPUBLIC EmbedMedia( OUString const& rSourceURL, OUString & o_rEmbeddedURL); +OUString GetFilename(OUString const& rSourceURL); + +::com::sun::star::uno::Reference<::com::sun::star::io::XStream> CreateStream( + ::com::sun::star::uno::Reference<::com::sun::star::embed::XStorage> const& xStorage, OUString const& rFilename); } #endif diff --git a/include/avmedia/modeltools.hxx b/include/avmedia/modeltools.hxx new file mode 100644 index 000000000000..db9fc139f3f5 --- /dev/null +++ b/include/avmedia/modeltools.hxx @@ -0,0 +1,22 @@ +/* -*- 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 <rtl/ustring.hxx> +#include <com/sun/star/frame/XModel.hpp> +#include <avmedia/avmediadllapi.h> + +namespace avmedia { + +bool AVMEDIA_DLLPUBLIC Embed3DModel( + const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel>& xModel, + const OUString& rSourceURL, OUString& o_rEmbeddedURL); + +} // namespace avemdia + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/sal/log-areas.dox b/include/sal/log-areas.dox index 2d712a6be3d7..f8a29673e095 100644 --- a/include/sal/log-areas.dox +++ b/include/sal/log-areas.dox @@ -448,10 +448,14 @@ certain functionality. @li @c svx @li @c svx.fmcmop +@section avmedia + +@li @c avmedia +@li @c avmedia.model - 3D models + @section other @li @c accessibility -@li @c avmedia @li @c basebmp @li @c binaryurp @li @c configmgr diff --git a/sd/source/ui/func/fuinsert.cxx b/sd/source/ui/func/fuinsert.cxx index c1706fc298cf..7e0a0255986f 100644 --- a/sd/source/ui/func/fuinsert.cxx +++ b/sd/source/ui/func/fuinsert.cxx @@ -805,7 +805,7 @@ void FuInsert3DModel::DoExecute( SfxRequest& ) aPos.Y() -= aSize.Height() >> 1; } - mpView->InsertMediaURL( sURL, nAction, aPos, aSize, false ) ; + mpView->Insert3DModelURL( sURL, nAction, aPos, aSize, false ) ; if( mpWindow ) mpWindow->LeaveWait(); diff --git a/sd/source/ui/inc/View.hxx b/sd/source/ui/inc/View.hxx index 526298a0aec0..85936ed89196 100644 --- a/sd/source/ui/inc/View.hxx +++ b/sd/source/ui/inc/View.hxx @@ -145,6 +145,13 @@ public: const Point& rPos, const Size& rSize, bool const bLink ); + SdrMediaObj* Insert3DModelURL( const OUString& rModelURL, sal_Int8& rAction, + const Point& rPos, const Size& rSize, + bool const bLink ); + + SdrMediaObj* InsertMediaObj( const OUString& rURL, sal_Int8& rAction, + const Point& rPos, const Size& rSize ); + bool PasteRTFTable( SotStorageStreamRef xStm, SdrPage* pPage, sal_uLong nPasteOptions ); sal_Bool IsPresObjSelected(sal_Bool bOnPage=sal_True, sal_Bool bOnMasterPage=sal_True, sal_Bool bCheckPresObjListOnly=sal_False, sal_Bool bCheckLayoutOnly=sal_False) const; diff --git a/sd/source/ui/view/sdview4.cxx b/sd/source/ui/view/sdview4.cxx index 7229da7458d9..770d2928c340 100644 --- a/sd/source/ui/view/sdview4.cxx +++ b/sd/source/ui/view/sdview4.cxx @@ -35,6 +35,7 @@ #include <sot/storage.hxx> #include <sfx2/app.hxx> #include <avmedia/mediawindow.hxx> +#include <avmedia/modeltools.hxx> #include <svtools/ehdl.hxx> #include <svtools/sfxecode.hxx> #include <vcl/graphicfilter.hxx> @@ -268,8 +269,6 @@ SdrGrafObj* View::InsertGraphic( const Graphic& rGraphic, sal_Int8& rAction, return pNewGrafObj; } - - SdrMediaObj* View::InsertMediaURL( const OUString& rMediaURL, sal_Int8& rAction, const Point& rPos, const Size& rSize, bool const bLink ) @@ -287,6 +286,33 @@ SdrMediaObj* View::InsertMediaURL( const OUString& rMediaURL, sal_Int8& rAction, if (!bRet) { return 0; } } + return InsertMediaObj( realURL, rAction, rPos, rSize ); +} + +SdrMediaObj* View::Insert3DModelURL( + const OUString& rModelURL, sal_Int8& rAction, + const Point& rPos, const Size& rSize, + bool const bLink ) +{ + OUString sRealURL; + if (bLink) + { + sRealURL = rModelURL; + } + else + { + uno::Reference<frame::XModel> const xModel( + GetDoc().GetObjectShell()->GetModel()); + bool const bRet = ::avmedia::Embed3DModel(xModel, rModelURL, sRealURL); + if (!bRet) { return 0; } + } + + return InsertMediaObj( sRealURL, rAction, rPos, rSize ); +} + +SdrMediaObj* View::InsertMediaObj( const OUString& rMediaURL, sal_Int8& rAction, + const Point& rPos, const Size& rSize ) +{ SdrEndTextEdit(); mnAction = rAction; @@ -309,7 +335,7 @@ SdrMediaObj* View::InsertMediaURL( const OUString& rMediaURL, sal_Int8& rAction, if( mnAction == DND_ACTION_LINK && pPickObj && pPV && pPickObj->ISA( SdrMediaObj ) ) { pNewMediaObj = static_cast< SdrMediaObj* >( pPickObj->Clone() ); - pNewMediaObj->setURL( realURL, ""/*TODO?*/ ); + pNewMediaObj->setURL( rMediaURL, ""/*TODO?*/ ); BegUndo(SD_RESSTR(STR_UNDO_DRAGDROP)); ReplaceObjectAtView(pPickObj, *pPV, pNewMediaObj); @@ -345,7 +371,7 @@ SdrMediaObj* View::InsertMediaURL( const OUString& rMediaURL, sal_Int8& rAction, if (sh != 0 && sh->HasName()) { referer = sh->GetMedium()->GetName(); } - pNewMediaObj->setURL( realURL, referer ); + pNewMediaObj->setURL( rMediaURL, referer ); if( pPickObj ) { |