[Libreoffice-commits] core.git: 7 commits - avmedia/Library_avmedia.mk avmedia/source external/boost include/avmedia include/sal sd/source svx/source xmloff/source

Zolnai Tamás tamas.zolnai at collabora.com
Wed Apr 2 03:23:58 PDT 2014


 avmedia/Library_avmedia.mk                       |    1 
 avmedia/source/framework/mediaitem.cxx           |   11 -
 avmedia/source/framework/modeltools.cxx          |  198 +++++++++++++++++++++++
 external/boost/UnpackedTarball_boost.mk          |    1 
 external/boost/boost.jsonparser.warnings.patch.0 |   58 ++++++
 external/boost/boost.libcdr.warnings.patch.1     |   97 -----------
 include/avmedia/mediaitem.hxx                    |    5 
 include/avmedia/modeltools.hxx                   |   22 ++
 include/sal/log-areas.dox                        |    6 
 sd/source/ui/func/fuinsert.cxx                   |    4 
 sd/source/ui/inc/View.hxx                        |    7 
 sd/source/ui/view/sdview4.cxx                    |   34 +++
 svx/source/svdraw/svdomedia.cxx                  |   70 +++++++-
 xmloff/source/draw/shapeexport.cxx               |   64 +++++++
 xmloff/source/draw/ximpshap.cxx                  |    3 
 15 files changed, 466 insertions(+), 115 deletions(-)

New commits:
commit e341ea3863bd19a2884083d2957273cc3572f989
Author: Zolnai Tamás <tamas.zolnai at collabora.com>
Date:   Tue Apr 1 19:22:52 2014 +0200

    ODF import of glTF 3D models
    
    Change-Id: I42f7bc63c1f75592ab628407b40d40536e58f18c

diff --git a/xmloff/source/draw/ximpshap.cxx b/xmloff/source/draw/ximpshap.cxx
index df6b191..aefffce 100644
--- a/xmloff/source/draw/ximpshap.cxx
+++ b/xmloff/source/draw/ximpshap.cxx
@@ -3062,7 +3062,8 @@ void SdXMLPluginShapeContext::StartElement( const ::com::sun::star::uno::Referen
 
         if( nPrefix == XML_NAMESPACE_DRAW && IsXMLToken( aLocalName, XML_MIME_TYPE ) )
         {
-            if( xAttrList->getValueByIndex( n ).equalsAscii( "application/vnd.sun.star.media" ) )
+            if( xAttrList->getValueByIndex( n ).equalsAscii( "application/vnd.sun.star.media" ) ||
+                xAttrList->getValueByIndex( n ).equalsAscii( "application/vnd.gltf+json" ))
                 mbMedia = true;
 
             // leave this loop
commit f7a5ed9b4b34264252be48488cf23c052a2276c2
Author: Zolnai Tamás <tamas.zolnai at collabora.com>
Date:   Wed Apr 2 11:58:11 2014 +0200

    Store glTF related files in a temp folder which URL can be given to the player
    
    media::XPlayer is constructed by media::XManager with
    only one URL parameter.
    
    Change-Id: I3693bce5386ea7f75fa7d9f1a7d744f90440d62b

diff --git a/svx/source/svdraw/svdomedia.cxx b/svx/source/svdraw/svdomedia.cxx
index 24199a9..e60b446 100644
--- a/svx/source/svdraw/svdomedia.cxx
+++ b/svx/source/svdraw/svdomedia.cxx
@@ -38,7 +38,9 @@
 #include <svx/sdr/contact/viewcontactofsdrmediaobj.hxx>
 #include <avmedia/mediawindow.hxx>
 
-
+// For handling of glTF models
+#include <unotools/tempfile.hxx>
+#include <tools/urlobj.hxx>
 
 using namespace ::com::sun::star;
 
@@ -294,6 +296,65 @@ uno::Reference<io::XInputStream> SdrMediaObj::GetInputStream()
     return tempFile.openStream();
 }
 
+static bool lcl_HandleJsonPackageURL(
+    const OUString& rURL,
+    SdrModel* const pModel,
+    OUString& o_rTempFileURL)
+{
+    // Create a temporary folder which will contain all files of glTF model
+    const OUString sTempFolder = ::utl::TempFile( NULL, true ).GetURL();
+
+    const sal_uInt16 nPackageLength = OString("vnd.sun.star.Package:").getLength();
+    const OUString sUrlPath = rURL.copy(nPackageLength,rURL.lastIndexOf("/")-nPackageLength);
+    try
+    {
+        // Base storage:
+        uno::Reference<document::XStorageBasedDocument> const xSBD(
+            pModel->getUnoModel(), uno::UNO_QUERY_THROW);
+        const uno::Reference<embed::XStorage> xStorage(
+            xSBD->getDocumentStorage(), uno::UNO_QUERY_THROW);
+
+        // Model source
+        ::comphelper::LifecycleProxy proxy;
+        const uno::Reference<embed::XStorage> xModelStorage(
+            ::comphelper::OStorageHelper::GetStorageAtPath(xStorage, sUrlPath,
+                embed::ElementModes::READ, proxy));
+
+        // Copy all files of glTF model from storage to the temp folder
+        uno::Reference< container::XNameAccess > xNameAccess( xModelStorage, uno::UNO_QUERY );
+        const uno::Sequence< OUString > aFilenames = xNameAccess->getElementNames();
+        for( sal_Int32 nFileIndex = 0; nFileIndex < aFilenames.getLength(); ++nFileIndex )
+        {
+            // Generate temp file path
+            const OUString& rFilename = aFilenames[nFileIndex];
+            INetURLObject aUrlObj(sTempFolder);
+            aUrlObj.insertName(rFilename);
+            const OUString sFilepath = aUrlObj.GetMainURL( INetURLObject::NO_DECODE );
+
+            // Media URL will point at json file
+            if( rFilename.endsWith(".json") )
+                o_rTempFileURL = sFilepath;
+
+            // Create temp file and fill it from storage
+            ::ucbhelper::Content aTargetContent(sFilepath,
+                uno::Reference<ucb::XCommandEnvironment>(), comphelper::getProcessComponentContext());
+
+            uno::Reference<io::XStream> const xStream(
+                xModelStorage->openStreamElement(rFilename,embed::ElementModes::READ), uno::UNO_SET_THROW);
+            uno::Reference<io::XInputStream> const xInputStream(
+                xStream->getInputStream(), uno::UNO_SET_THROW);
+
+            aTargetContent.writeStream(xInputStream,true);
+        }
+
+    }
+    catch (uno::Exception const& e)
+    {
+        SAL_INFO("svx", "exception while copying glTF related files to temp directory '" << e.Message << "'");
+    }
+    return true;
+}
+
 /// copy a stream from XStorage to temp file
 static bool lcl_HandlePackageURL(
         OUString const & rURL,
@@ -369,8 +430,11 @@ void SdrMediaObj::mediaPropertiesChanged( const ::avmedia::MediaItem& rNewProper
                                 rNewProperties.getTempURL()))
             {
                 OUString tempFileURL;
-                bool const bSuccess = lcl_HandlePackageURL(
-                    url, GetModel(), tempFileURL);
+                bool bSuccess;
+                if( url.endsWith(".json") )
+                    bSuccess = lcl_HandleJsonPackageURL(url, GetModel(), tempFileURL);
+                else
+                    bSuccess = lcl_HandlePackageURL( url, GetModel(), tempFileURL);
                 if (bSuccess)
                 {
                     m_pImpl->m_pTempFile.reset(new MediaTempFile(tempFileURL));
commit 9220939537bf1041b2cb3b119c2156ba1f432632
Author: Zolnai Tamás <tamas.zolnai at collabora.com>
Date:   Tue Apr 1 19:14:16 2014 +0200

    Use "Insert" instead of "Open" in title of 3D Model insertion file dialog
    
    Change-Id: Ibb6a7df3bf25f7006b71deeebd5abb842a628a46

diff --git a/sd/source/ui/func/fuinsert.cxx b/sd/source/ui/func/fuinsert.cxx
index 7e0a025..6146ba7 100644
--- a/sd/source/ui/func/fuinsert.cxx
+++ b/sd/source/ui/func/fuinsert.cxx
@@ -776,7 +776,7 @@ void FuInsert3DModel::DoExecute( SfxRequest& )
 {
     sfx2::FileDialogHelper aDlg( ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE, 0 );
 
-    aDlg.SetTitle( "Open 3DModel" );
+    aDlg.SetTitle( "Insert 3D Model" );
     aDlg.AddFilter( "GL Transmission Format", "*.json" );
     aDlg.AddFilter( "All files", "*.*"  );
 
commit f388519b2cc6cfcabf2ec51955d06717e7f6b46b
Author: Zolnai Tamás <tamas.zolnai at collabora.com>
Date:   Wed Apr 2 11:59:42 2014 +0200

    ODF export of glTF 3D models
    
    Change-Id: Iea06ea7359b859144df338e1e22675e05bf4a2d7

diff --git a/xmloff/source/draw/shapeexport.cxx b/xmloff/source/draw/shapeexport.cxx
index eaa06d3..3a24c71 100644
--- a/xmloff/source/draw/shapeexport.cxx
+++ b/xmloff/source/draw/shapeexport.cxx
@@ -78,6 +78,7 @@
 #include <com/sun/star/style/XStyle.hpp>
 #include <com/sun/star/table/XColumnRowRange.hpp>
 #include <com/sun/star/text/XText.hpp>
+#include <com/sun/star/document/XStorageBasedDocument.hpp>
 
 #include <comphelper/classids.hxx>
 #include <comphelper/processfactory.hxx>
@@ -91,6 +92,7 @@
 #include <tools/debug.hxx>
 #include <tools/globname.hxx>
 #include <tools/helpers.hxx>
+#include <tools/urlobj.hxx>
 
 #include <xmloff/contextid.hxx>
 #include <xmloff/families.hxx>
@@ -3155,6 +3157,63 @@ lcl_StoreMediaAndGetURL(SvXMLExport & rExport,
     }
 }
 
+static void lcl_StoreJsonExternals(
+    SvXMLExport& rExport, const OUString& rURL)
+{
+    OUString sUrlPath;
+    if (rURL.startsWithIgnoreAsciiCase("vnd.sun.star.Package:", &sUrlPath))
+    {
+        sUrlPath = sUrlPath.copy(0,sUrlPath.lastIndexOf("/"));
+        try
+        {
+            // Base storage
+            uno::Reference<document::XStorageBasedDocument> const xSBD(
+                rExport.GetModel(), uno::UNO_QUERY_THROW);
+            const uno::Reference<embed::XStorage> xStorage(
+                xSBD->getDocumentStorage(), uno::UNO_QUERY_THROW);
+
+            // Model source
+            ::comphelper::LifecycleProxy proxy;
+            const uno::Reference<embed::XStorage> xModelStorage(
+                ::comphelper::OStorageHelper::GetStorageAtPath(xStorage, sUrlPath,
+                    embed::ElementModes::READ, proxy));
+
+            // Target storage
+            uno::Reference<embed::XStorage> const xTarget(
+                    rExport.GetTargetStorage(), uno::UNO_QUERY_THROW);
+
+            // Target of all models
+            const uno::Reference<embed::XStorage> xModelsTarget(
+                xTarget->openStorageElement(sUrlPath.copy(0,sUrlPath.lastIndexOf("/")), embed::ElementModes::WRITE));
+
+            // Target of current model
+            const uno::Reference<embed::XStorage> xModelTarget(
+                xModelsTarget->openStorageElement(sUrlPath.copy(sUrlPath.lastIndexOf("/")+1), embed::ElementModes::WRITE));
+
+            xModelStorage->copyToStorage(xModelTarget);
+
+            uno::Reference<embed::XTransactedObject> const xTransaction(xModelsTarget, uno::UNO_QUERY);
+            if (xTransaction.is())
+            {
+                xTransaction->commit();
+            }
+        }
+        catch (uno::Exception const& e)
+        {
+            SAL_INFO("xmloff", "exception while storing embedded model: '" << e.Message << "'");
+        }
+    }
+}
+
+static OUString lcl_GetMimeType(const OUString& aMediaURL)
+{
+    // TODO: Find a better way to find out the mime type, maybe via propset
+    if( aMediaURL.endsWith(".json") )
+        return OUString("application/vnd.gltf+json");
+    else
+        return OUString("application/vnd.sun.star.media");
+}
+
 void XMLShapeExport::ImpExportMediaShape(
     const uno::Reference< drawing::XShape >& xShape,
     XmlShapeType eShapeType, sal_Int32 nFeatures, com::sun::star::awt::Point* pRefPoint)
@@ -3177,13 +3236,16 @@ void XMLShapeExport::ImpExportMediaShape(
         xPropSet->getPropertyValue("MediaURL") >>= aMediaURL;
         OUString const persistentURL =
             lcl_StoreMediaAndGetURL(GetExport(), xPropSet, aMediaURL);
+        if( aMediaURL.endsWith(".json") )
+            lcl_StoreJsonExternals(GetExport(), aMediaURL);
+
         mrExport.AddAttribute ( XML_NAMESPACE_XLINK, XML_HREF, persistentURL );
         mrExport.AddAttribute ( XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE );
         mrExport.AddAttribute ( XML_NAMESPACE_XLINK, XML_SHOW, XML_EMBED );
         mrExport.AddAttribute ( XML_NAMESPACE_XLINK, XML_ACTUATE, XML_ONLOAD );
 
         // export mime-type
-        mrExport.AddAttribute( XML_NAMESPACE_DRAW, XML_MIME_TYPE, OUString(  "application/vnd.sun.star.media"  ) );
+        mrExport.AddAttribute( XML_NAMESPACE_DRAW, XML_MIME_TYPE, lcl_GetMimeType(aMediaURL) );
 
         // write plugin
         SvXMLElementExport aOBJ(mrExport, XML_NAMESPACE_DRAW, XML_PLUGIN, !( nFeatures & SEF_EXPORT_NO_WS ), true);
commit 414ff5650a810be807fed61ded1b9d6a23aa720b
Author: Zolnai Tamás <tamas.zolnai at collabora.com>
Date:   Wed Apr 2 11:41:59 2014 +0200

    Avoid Wsahdow warnings related to boost json parser
    
    Problematic variable: separator -> separator_
    
    Change-Id: Ia4e1b1543f61b03e029e1bc4151ec58334e8df57

diff --git a/external/boost/UnpackedTarball_boost.mk b/external/boost/UnpackedTarball_boost.mk
index d73ee50..b3ffa7e 100644
--- a/external/boost/UnpackedTarball_boost.mk
+++ b/external/boost/UnpackedTarball_boost.mk
@@ -49,6 +49,7 @@ boost_patches += boost.wuninitialized.patch
 boost_patches += boost.wdeprecated-auto_ptr.patch.0
 #https://svn.boost.org/trac/boost/ticket/9397
 boost_patches += boost.9397.warnings.patch.0
+boost_patches += boost.jsonparser.warnings.patch.0
 
 $(eval $(call gb_UnpackedTarball_UnpackedTarball,boost))
 
diff --git a/external/boost/boost.jsonparser.warnings.patch.0 b/external/boost/boost.jsonparser.warnings.patch.0
new file mode 100644
index 0000000..4a71b3b
--- /dev/null
+++ b/external/boost/boost.jsonparser.warnings.patch.0
@@ -0,0 +1,58 @@
+--- boost/property_tree/string_path.hpp
++++ boost/property_tree/string_path.hpp
+@@ -88,14 +88,14 @@ namespace boost { namespace property_tree
+         typedef typename String::value_type char_type;
+
+         /// Create an empty path.
+-        explicit string_path(char_type separator = char_type('.'));
++        explicit string_path(char_type separator_ = char_type('.'));
+         /// Create a path by parsing the given string.
+         /// @param value A sequence, possibly with separators, that describes
+         ///              the path, e.g. "one.two.three".
+         /// @param separator The separator used in parsing. Defaults to '.'.
+         /// @param tr The translator used by this path to convert the individual
+         ///           parts to keys.
+-        string_path(const String &value, char_type separator = char_type('.'),
++        string_path(const String &value, char_type separator_ = char_type('.'),
+                     Translator tr = Translator());
+         /// Create a path by parsing the given string.
+         /// @param value A zero-terminated array of values. Only use if zero-
+@@ -106,7 +106,7 @@ namespace boost { namespace property_tree
+         /// @param tr The translator used by this path to convert the individual
+         ///           parts to keys.
+         string_path(const char_type *value,
+-                    char_type separator = char_type('.'),
++                    char_type separator_ = char_type('.'),
+                     Translator tr = Translator());
+
+         // Default copying doesn't do the right thing with the iterator
+@@ -162,23 +162,23 @@ namespace boost { namespace property_tree
+     };
+
+     template <typename String, typename Translator> inline
+-    string_path<String, Translator>::string_path(char_type separator)
+-        : m_separator(separator), m_start(m_value.begin())
++    string_path<String, Translator>::string_path(char_type separator_)
++        : m_separator(separator_), m_start(m_value.begin())
+     {}
+
+     template <typename String, typename Translator> inline
+     string_path<String, Translator>::string_path(const String &value,
+-                                                 char_type separator,
++                                                 char_type separator_,
+                                                  Translator tr)
+-        : m_value(value), m_separator(separator),
++        : m_value(value), m_separator(separator_),
+           m_tr(tr), m_start(m_value.begin())
+     {}
+
+     template <typename String, typename Translator> inline
+     string_path<String, Translator>::string_path(const char_type *value,
+-                                                 char_type separator,
++                                                 char_type separator_,
+                                                  Translator tr)
+-        : m_value(value), m_separator(separator),
++        : m_value(value), m_separator(separator_),
+           m_tr(tr), m_start(m_value.begin())
+     {}
+
commit c3986c90e329af98520bda1ad11ecf6d059d50e1
Author: Zolnai Tamás <tamas.zolnai at collabora.com>
Date:   Wed Apr 2 11:40:45 2014 +0200

    These changes are not needed any more
    
    Moreover these line causes the same Wshadow warning
    which was the reason of adding them.
    
    Change-Id: I6b5793b66db26720626b7924d59e9283168f8abe

diff --git a/external/boost/boost.libcdr.warnings.patch.1 b/external/boost/boost.libcdr.warnings.patch.1
index 22888c4..12a7ea2 100644
--- a/external/boost/boost.libcdr.warnings.patch.1
+++ b/external/boost/boost.libcdr.warnings.patch.1
@@ -1,100 +1,3 @@
---- boost/boost/multi_index/detail/index_matcher.hpp	2008-07-03 18:51:53.000000000 +0200
-+++ boost/boost/multi_index/detail/index_matcher.hpp	2013-05-17 15:30:12.539099597 +0200
-@@ -132,17 +132,17 @@
-         entries(),entries()+size_,
-         entry(node),entry::less_by_node()); /* localize entry */
-     ent->ordered=false;
--    std::size_t n=ent->pos;                 /* get its position */
-+    std::size_t n_=ent->pos;                 /* get its position */
- 
-     entry dummy(0);
--    dummy.pile_top=n;
-+    dummy.pile_top=n_;
- 
-     entry* pile_ent=                        /* find the first available pile */
-       std::lower_bound(                     /* to stack the entry            */
-         entries(),entries()+num_piles,
-         dummy,entry::less_by_pile_top());
- 
--    pile_ent->pile_top=n;                   /* stack the entry */
-+    pile_ent->pile_top=n_;                   /* stack the entry */
-     pile_ent->pile_top_entry=ent;        
- 
-     /* if not the first pile, link entry to top of the preceding pile */
-@@ -164,7 +164,7 @@
-        */
- 
-       entry* ent=entries()[num_piles-1].pile_top_entry;
--      for(std::size_t n=num_piles;n--;){
-+      for(std::size_t n_=num_piles;n_--;){
-         ent->ordered=true;
-         ent=ent->previous;
-       }
---- boost/boost/multi_index/ordered_index.hpp	2010-07-25 12:44:55.000000000 +0200
-+++ boost/boost/multi_index/ordered_index.hpp	2013-05-17 15:33:42.785182819 +0200
-@@ -436,9 +436,9 @@
- 
-   template<typename CompatibleKey,typename CompatibleCompare>
-   iterator find(
--    const CompatibleKey& x,const CompatibleCompare& comp)const
-+    const CompatibleKey& x,const CompatibleCompare& comp_)const
-   {
--    return make_iterator(ordered_index_find(root(),header(),key,x,comp));
-+    return make_iterator(ordered_index_find(root(),header(),key,x,comp_));
-   }
- 
-   template<typename CompatibleKey>
-@@ -448,9 +448,9 @@
-   }
- 
-   template<typename CompatibleKey,typename CompatibleCompare>
--  size_type count(const CompatibleKey& x,const CompatibleCompare& comp)const
-+  size_type count(const CompatibleKey& x,const CompatibleCompare& comp_)const
-   {
--    std::pair<iterator,iterator> p=equal_range(x,comp);
-+    std::pair<iterator,iterator> p=equal_range(x,comp_);
-     size_type n=std::distance(p.first,p.second);
-     return n;
-   }
-@@ -464,10 +464,10 @@
- 
-   template<typename CompatibleKey,typename CompatibleCompare>
-   iterator lower_bound(
--    const CompatibleKey& x,const CompatibleCompare& comp)const
-+    const CompatibleKey& x,const CompatibleCompare& comp_)const
-   {
-     return make_iterator(
--      ordered_index_lower_bound(root(),header(),key,x,comp));
-+      ordered_index_lower_bound(root(),header(),key,x,comp_));
-   }
- 
-   template<typename CompatibleKey>
-@@ -479,10 +479,10 @@
- 
-   template<typename CompatibleKey,typename CompatibleCompare>
-   iterator upper_bound(
--    const CompatibleKey& x,const CompatibleCompare& comp)const
-+    const CompatibleKey& x,const CompatibleCompare& comp_)const
-   {
-     return make_iterator(
--      ordered_index_upper_bound(root(),header(),key,x,comp));
-+      ordered_index_upper_bound(root(),header(),key,x,comp_));
-   }
- 
-   template<typename CompatibleKey>
-@@ -497,10 +497,10 @@
- 
-   template<typename CompatibleKey,typename CompatibleCompare>
-   std::pair<iterator,iterator> equal_range(
--    const CompatibleKey& x,const CompatibleCompare& comp)const
-+    const CompatibleKey& x,const CompatibleCompare& comp_)const
-   {
-     std::pair<node_type*,node_type*> p=
--      ordered_index_equal_range(root(),header(),key,x,comp);
-+      ordered_index_equal_range(root(),header(),key,x,comp_);
-     return std::pair<iterator,iterator>(
-       make_iterator(p.first),make_iterator(p.second));
-   }
 --- boost/boost/multi_index/sequenced_index.hpp	2008-07-03 18:51:53.000000000 +0200
 +++ boost/boost/multi_index/sequenced_index.hpp	2013-05-17 15:44:15.265289335 +0200
 @@ -346,7 +346,7 @@
commit edb4c11b074e486a4fc071ea94c9c4a1c83e84a3
Author: Zolnai Tamás <tamas.zolnai at collabora.com>
Date:   Wed Apr 2 11:34:03 2014 +0200

    glTF 3D model embedding: Embed all external resources of *.json file
    
    Store them under /Model/<json_file_name_without_extension>/
    modeltools: functions for handling 3D models inside avmedia
    
    Change-Id: Ia2bdad6064db372e1c946b6ab02c434545d1ed45

diff --git a/avmedia/Library_avmedia.mk b/avmedia/Library_avmedia.mk
index 3c723f1..9352227 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 b9ab635..32f6f04 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 0000000..10da986
--- /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 97a63a9..c512e26 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 0000000..db9fc13
--- /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 2d712a6..f8a2967 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
 
+ at section avmedia
+
+ at li @c avmedia
+ at li @c avmedia.model - 3D models
+
 @section other
 
 @li @c accessibility
- at 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 c1706fc..7e0a025 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 526298a..85936ed 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 7229da7..770d292 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 )
         {


More information about the Libreoffice-commits mailing list