LCOV - code coverage report
Current view: top level - svx/source/svdraw - svdomedia.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 130 225 57.8 %
Date: 2015-06-13 12:38:46 Functions: 25 36 69.4 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       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/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      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 .
      18             :  */
      19             : 
      20             : #include <config_features.h>
      21             : 
      22             : #include <svx/svdomedia.hxx>
      23             : 
      24             : #include <rtl/ustring.hxx>
      25             : #include <osl/file.hxx>
      26             : 
      27             : #include <com/sun/star/document/XStorageBasedDocument.hpp>
      28             : #include <com/sun/star/embed/XStorage.hpp>
      29             : 
      30             : #include <ucbhelper/content.hxx>
      31             : #include <comphelper/processfactory.hxx>
      32             : #include <comphelper/storagehelper.hxx>
      33             : 
      34             : #include <vcl/svapp.hxx>
      35             : 
      36             : #include <svx/svdmodel.hxx>
      37             : #include "svdglob.hxx"
      38             : #include "svx/svdstr.hrc"
      39             : #include <svx/sdr/contact/viewcontactofsdrmediaobj.hxx>
      40             : #include <avmedia/mediawindow.hxx>
      41             : 
      42             : // For handling of glTF models
      43             : #include <unotools/tempfile.hxx>
      44             : #include <unotools/localfilehelper.hxx>
      45             : #include <tools/urlobj.hxx>
      46             : 
      47             : using namespace ::com::sun::star;
      48             : 
      49             : 
      50             : // - SdrMediaObj -
      51             : 
      52             : // Note: the temp file is read only, until it is deleted!
      53             : // It may be shared between multiple documents in case of copy/paste,
      54             : // hence the shared_ptr.
      55             : struct MediaTempFile
      56             : {
      57             :     OUString const m_TempFileURL;
      58             :     OUString const m_TempDirURL; // yet another hack, for the glTF models
      59           6 :     MediaTempFile(OUString const& rURL, OUString const& rDirURL)
      60           6 :         : m_TempFileURL(rURL), m_TempDirURL(rDirURL)
      61           6 :     {}
      62           6 :     ~MediaTempFile()
      63           6 :     {
      64           6 :         ::osl::File::remove(m_TempFileURL);
      65           6 :         if (!m_TempDirURL.isEmpty())
      66             :         {
      67           2 :             ::utl::removeTree(m_TempDirURL);
      68             :         }
      69           6 :     }
      70             : };
      71             : 
      72          14 : struct SdrMediaObj::Impl
      73             : {
      74             :     ::avmedia::MediaItem                  m_MediaProperties;
      75             :     ::boost::shared_ptr< MediaTempFile >  m_pTempFile;
      76             :     uno::Reference< graphic::XGraphic >   m_xCachedSnapshot;
      77             :     OUString m_LastFailedPkgURL;
      78             : };
      79             : 
      80         308 : TYPEINIT1( SdrMediaObj, SdrRectObj );
      81             : 
      82             : 
      83             : 
      84           7 : SdrMediaObj::SdrMediaObj()
      85             :     : SdrRectObj()
      86           7 :     , m_xImpl( new Impl() )
      87             : {
      88           7 : }
      89             : 
      90           0 : SdrMediaObj::SdrMediaObj( const Rectangle& rRect )
      91             :     : SdrRectObj( rRect )
      92           0 :     , m_xImpl( new Impl() )
      93             : {
      94           0 : }
      95             : 
      96          14 : SdrMediaObj::~SdrMediaObj()
      97             : {
      98          14 : }
      99             : 
     100           0 : bool SdrMediaObj::HasTextEdit() const
     101             : {
     102           0 :     return false;
     103             : }
     104             : 
     105           7 : sdr::contact::ViewContact* SdrMediaObj::CreateObjectSpecificViewContact()
     106             : {
     107           7 :     return new sdr::contact::ViewContactOfSdrMediaObj( *this );
     108             : }
     109             : 
     110           0 : void SdrMediaObj::TakeObjInfo( SdrObjTransformInfoRec& rInfo ) const
     111             : {
     112           0 :     rInfo.bSelectAllowed = true;
     113           0 :     rInfo.bMoveAllowed = true;
     114           0 :     rInfo.bResizeFreeAllowed = true;
     115           0 :     rInfo.bResizePropAllowed = true;
     116           0 :     rInfo.bRotateFreeAllowed = false;
     117           0 :     rInfo.bRotate90Allowed = false;
     118           0 :     rInfo.bMirrorFreeAllowed = false;
     119           0 :     rInfo.bMirror45Allowed = false;
     120           0 :     rInfo.bMirror90Allowed = false;
     121           0 :     rInfo.bTransparenceAllowed = false;
     122           0 :     rInfo.bGradientAllowed = false;
     123           0 :     rInfo.bShearAllowed = false;
     124           0 :     rInfo.bEdgeRadiusAllowed = false;
     125           0 :     rInfo.bNoOrthoDesired = false;
     126           0 :     rInfo.bNoContortion = false;
     127           0 :     rInfo.bCanConvToPath = false;
     128           0 :     rInfo.bCanConvToPoly = false;
     129           0 :     rInfo.bCanConvToContour = false;
     130           0 :     rInfo.bCanConvToPathLineToArea = false;
     131           0 :     rInfo.bCanConvToPolyLineToArea = false;
     132           0 : }
     133             : 
     134          80 : sal_uInt16 SdrMediaObj::GetObjIdentifier() const
     135             : {
     136          80 :     return sal_uInt16( OBJ_MEDIA );
     137             : }
     138             : 
     139           4 : OUString SdrMediaObj::TakeObjNameSingul() const
     140             : {
     141           4 :     OUStringBuffer sName(ImpGetResStr(STR_ObjNameSingulMEDIA));
     142             : 
     143           8 :     OUString aName(GetName());
     144             : 
     145           4 :     if (!aName.isEmpty())
     146             :     {
     147           0 :         sName.append(' ');
     148           0 :         sName.append('\'');
     149           0 :         sName.append(aName);
     150           0 :         sName.append('\'');
     151             :     }
     152             : 
     153           8 :     return sName.makeStringAndClear();
     154             : }
     155             : 
     156           0 : OUString SdrMediaObj::TakeObjNamePlural() const
     157             : {
     158           0 :     return ImpGetResStr(STR_ObjNamePluralMEDIA);
     159             : }
     160             : 
     161           0 : SdrMediaObj* SdrMediaObj::Clone() const
     162             : {
     163           0 :     return CloneHelper< SdrMediaObj >();
     164             : }
     165             : 
     166           0 : SdrMediaObj& SdrMediaObj::operator=(const SdrMediaObj& rObj)
     167             : {
     168           0 :     if( this == &rObj )
     169           0 :         return *this;
     170           0 :     SdrRectObj::operator=( rObj );
     171             : 
     172           0 :     m_xImpl->m_pTempFile = rObj.m_xImpl->m_pTempFile; // before props
     173           0 :     setMediaProperties( rObj.getMediaProperties() );
     174           0 :     m_xImpl->m_xCachedSnapshot = rObj.m_xImpl->m_xCachedSnapshot;
     175           0 :     return *this;
     176             : }
     177             : 
     178           1 : const uno::Reference< graphic::XGraphic > SdrMediaObj::getSnapshot() const
     179             : {
     180           1 :     if( !m_xImpl->m_xCachedSnapshot.is() )
     181             :     {
     182           1 :         OUString aRealURL = m_xImpl->m_MediaProperties.getTempURL();
     183           1 :         if( aRealURL.isEmpty() )
     184           0 :             aRealURL = m_xImpl->m_MediaProperties.getURL();
     185           1 :         m_xImpl->m_xCachedSnapshot = avmedia::MediaWindow::grabFrame( aRealURL, m_xImpl->m_MediaProperties.getReferer(), m_xImpl->m_MediaProperties.getMimeType());
     186             :     }
     187           1 :     return m_xImpl->m_xCachedSnapshot;
     188             : }
     189             : 
     190           0 : void SdrMediaObj::AdjustToMaxRect( const Rectangle& rMaxRect, bool bShrinkOnly /* = false */ )
     191             : {
     192           0 :     Size aSize( Application::GetDefaultDevice()->PixelToLogic( getPreferredSize(), MAP_100TH_MM ) );
     193           0 :     Size aMaxSize( rMaxRect.GetSize() );
     194             : 
     195           0 :     if( aSize.Height() != 0 && aSize.Width() != 0 )
     196             :     {
     197           0 :         Point aPos( rMaxRect.TopLeft() );
     198             : 
     199             :         // if graphic is too large, fit it to the page
     200           0 :         if ( (!bShrinkOnly                          ||
     201           0 :              ( aSize.Height() > aMaxSize.Height() ) ||
     202           0 :              ( aSize.Width()  > aMaxSize.Width()  ) )&&
     203           0 :              aSize.Height() && aMaxSize.Height() )
     204             :         {
     205           0 :             float fGrfWH =  (float)aSize.Width() /
     206           0 :                             (float)aSize.Height();
     207           0 :             float fWinWH =  (float)aMaxSize.Width() /
     208           0 :                             (float)aMaxSize.Height();
     209             : 
     210             :             // scale graphic to page size
     211           0 :             if ( fGrfWH < fWinWH )
     212             :             {
     213           0 :                 aSize.Width() = (long)(aMaxSize.Height() * fGrfWH);
     214           0 :                 aSize.Height()= aMaxSize.Height();
     215             :             }
     216           0 :             else if ( fGrfWH > 0.F )
     217             :             {
     218           0 :                 aSize.Width() = aMaxSize.Width();
     219           0 :                 aSize.Height()= (long)(aMaxSize.Width() / fGrfWH);
     220             :             }
     221             : 
     222           0 :             aPos = rMaxRect.Center();
     223             :         }
     224             : 
     225           0 :         if( bShrinkOnly )
     226           0 :             aPos = maRect.TopLeft();
     227             : 
     228           0 :         aPos.X() -= aSize.Width() / 2;
     229           0 :         aPos.Y() -= aSize.Height() / 2;
     230           0 :         SetLogicRect( Rectangle( aPos, aSize ) );
     231             :     }
     232           0 : }
     233             : 
     234           0 : void SdrMediaObj::setURL( const OUString& rURL, const OUString& rReferer, const OUString& rMimeType )
     235             : {
     236           0 :     ::avmedia::MediaItem aURLItem;
     237           0 :     if( !rMimeType.isEmpty() )
     238           0 :         m_xImpl->m_MediaProperties.setMimeType(rMimeType);
     239           0 :     aURLItem.setURL( rURL, "", rReferer );
     240           0 :     setMediaProperties( aURLItem );
     241           0 : }
     242             : 
     243           7 : const OUString& SdrMediaObj::getURL() const
     244             : {
     245           7 :     return m_xImpl->m_MediaProperties.getURL();
     246             : }
     247             : 
     248          46 : void SdrMediaObj::setMediaProperties( const ::avmedia::MediaItem& rState )
     249             : {
     250          46 :     mediaPropertiesChanged( rState );
     251          46 :     static_cast< sdr::contact::ViewContactOfSdrMediaObj& >( GetViewContact() ).executeMediaItem( getMediaProperties() );
     252          46 : }
     253             : 
     254          67 : const ::avmedia::MediaItem& SdrMediaObj::getMediaProperties() const
     255             : {
     256          67 :     return m_xImpl->m_MediaProperties;
     257             : }
     258             : 
     259           0 : Size SdrMediaObj::getPreferredSize() const
     260             : {
     261           0 :     return static_cast< sdr::contact::ViewContactOfSdrMediaObj& >( GetViewContact() ).getPreferredSize();
     262             : }
     263             : 
     264           2 : uno::Reference<io::XInputStream> SdrMediaObj::GetInputStream()
     265             : {
     266           2 :     if (!m_xImpl->m_pTempFile)
     267             :     {
     268             :         SAL_WARN("svx", "this is only intended for embedded media");
     269           0 :         return 0;
     270             :     }
     271           2 :     ucbhelper::Content tempFile(m_xImpl->m_pTempFile->m_TempFileURL,
     272             :                 uno::Reference<ucb::XCommandEnvironment>(),
     273           4 :                 comphelper::getProcessComponentContext());
     274           2 :     return tempFile.openStream();
     275             : }
     276             : 
     277             : #if HAVE_FEATURE_GLTF
     278           2 : static bool lcl_HandleJsonPackageURL(
     279             :     const OUString& rURL,
     280             :     SdrModel* const pModel,
     281             :     OUString& o_rTempFileURL,
     282             :     OUString& o_rTempDirURL)
     283             : {
     284             :     // Create a temporary folder which will contain all files of glTF model
     285           2 :     o_rTempDirURL = ::utl::TempFile(NULL, true).GetURL();
     286             : 
     287           2 :     const sal_uInt16 nPackageLength = OString("vnd.sun.star.Package:").getLength();
     288           2 :     const OUString sUrlPath = rURL.copy(nPackageLength,rURL.lastIndexOf("/")-nPackageLength);
     289             :     try
     290             :     {
     291             :         // Base storage:
     292             :         uno::Reference<document::XStorageBasedDocument> const xSBD(
     293           2 :             pModel->getUnoModel(), uno::UNO_QUERY_THROW);
     294             :         const uno::Reference<embed::XStorage> xStorage(
     295           4 :             xSBD->getDocumentStorage(), uno::UNO_QUERY_THROW);
     296             : 
     297             :         // Model source
     298           4 :         ::comphelper::LifecycleProxy proxy;
     299             :         const uno::Reference<embed::XStorage> xModelStorage(
     300             :             ::comphelper::OStorageHelper::GetStorageAtPath(xStorage, sUrlPath,
     301           4 :                 embed::ElementModes::READ, proxy));
     302             : 
     303             :         // Copy all files of glTF model from storage to the temp folder
     304           4 :         uno::Reference< container::XNameAccess > xNameAccess( xModelStorage, uno::UNO_QUERY );
     305           4 :         const uno::Sequence< OUString > aFilenames = xNameAccess->getElementNames();
     306          12 :         for( sal_Int32 nFileIndex = 0; nFileIndex < aFilenames.getLength(); ++nFileIndex )
     307             :         {
     308             :             // Generate temp file path
     309          10 :             const OUString& rFilename = aFilenames[nFileIndex];
     310          10 :             INetURLObject aUrlObj(o_rTempDirURL);
     311          10 :             aUrlObj.insertName(rFilename);
     312          20 :             const OUString sFilepath = aUrlObj.GetMainURL( INetURLObject::NO_DECODE );
     313             : 
     314             :             // Media URL will point at json file
     315          10 :             if( rFilename.endsWith(".json") )
     316           2 :                 o_rTempFileURL = sFilepath;
     317             : 
     318             :             // Create temp file and fill it from storage
     319             :             ::ucbhelper::Content aTargetContent(sFilepath,
     320          20 :                 uno::Reference<ucb::XCommandEnvironment>(), comphelper::getProcessComponentContext());
     321             : 
     322             :             uno::Reference<io::XStream> const xStream(
     323          20 :                 xModelStorage->openStreamElement(rFilename,embed::ElementModes::READ), uno::UNO_SET_THROW);
     324             :             uno::Reference<io::XInputStream> const xInputStream(
     325          20 :                 xStream->getInputStream(), uno::UNO_SET_THROW);
     326             : 
     327          10 :             aTargetContent.writeStream(xInputStream,true);
     328          12 :         }
     329             : 
     330             :     }
     331           0 :     catch (uno::Exception const& e)
     332             :     {
     333             :         SAL_INFO("svx", "exception while copying glTF related files to temp directory '" << e.Message << "'");
     334             :     }
     335           2 :     return true;
     336             : }
     337             : #endif
     338             : 
     339           4 : static bool lcl_CopyToTempFile(
     340             :         uno::Reference<io::XInputStream> const& xInStream,
     341             :         OUString & o_rTempFileURL)
     342             : {
     343           4 :     OUString tempFileURL;
     344             :     ::osl::FileBase::RC const err =
     345           4 :         ::osl::FileBase::createTempFile(0, 0, & tempFileURL);
     346           4 :     if (::osl::FileBase::E_None != err)
     347             :     {
     348             :         SAL_INFO("svx", "cannot create temp file");
     349           0 :         return false;
     350             :     }
     351             : 
     352             :     try
     353             :     {
     354             :         ::ucbhelper::Content tempContent(tempFileURL,
     355             :                 uno::Reference<ucb::XCommandEnvironment>(),
     356           4 :                 comphelper::getProcessComponentContext());
     357           4 :         tempContent.writeStream(xInStream, true); // copy stream to file
     358             :     }
     359           0 :     catch (uno::Exception const& e)
     360             :     {
     361             :         SAL_WARN("svx", "exception: '" << e.Message << "'");
     362           0 :         return false;
     363             :     }
     364           4 :     o_rTempFileURL = tempFileURL;
     365           4 :     return true;
     366             : }
     367             : 
     368           2 : void SdrMediaObj::SetInputStream(uno::Reference<io::XInputStream> const& xStream)
     369             : {
     370           2 :     if (m_xImpl->m_pTempFile || m_xImpl->m_LastFailedPkgURL.isEmpty())
     371             :     {
     372             :         SAL_WARN("svx", "this is only intended for embedded media");
     373           0 :         return;
     374             :     }
     375           2 :     OUString tempFileURL;
     376           2 :     bool const bSuccess = lcl_CopyToTempFile(xStream, tempFileURL);
     377           2 :     if (bSuccess)
     378             :     {
     379           2 :         m_xImpl->m_pTempFile.reset(new MediaTempFile(tempFileURL, ""));
     380           2 :         m_xImpl->m_MediaProperties.setURL(
     381           4 :             m_xImpl->m_LastFailedPkgURL, tempFileURL, "");
     382             :     }
     383           2 :     m_xImpl->m_LastFailedPkgURL.clear(); // once only
     384             : }
     385             : 
     386             : /// copy a stream from XStorage to temp file
     387           5 : static bool lcl_HandlePackageURL(
     388             :         OUString const & rURL,
     389             :         SdrModel *const pModel,
     390             :         OUString & o_rTempFileURL)
     391             : {
     392           5 :     if (!pModel)
     393             :     {
     394             :         SAL_WARN("svx", "no model");
     395           0 :         return false;
     396             :     }
     397           5 :     ::comphelper::LifecycleProxy sourceProxy;
     398          10 :     uno::Reference<io::XInputStream> xInStream;
     399             :     try {
     400           5 :         xInStream = pModel->GetDocumentStream(rURL, sourceProxy);
     401             :     }
     402           0 :     catch (container::NoSuchElementException const&)
     403             :     {
     404             :         SAL_INFO("svx", "not found: '" << OUString(rURL) << "'");
     405           0 :         return false;
     406             :     }
     407           0 :     catch (uno::Exception const& e)
     408             :     {
     409             :         SAL_WARN("svx", "exception: '" << e.Message << "'");
     410           0 :         return false;
     411             :     }
     412           5 :     if (!xInStream.is())
     413             :     {
     414             :         SAL_WARN("svx", "no stream?");
     415           3 :         return false;
     416             :     }
     417           7 :     return lcl_CopyToTempFile(xInStream, o_rTempFileURL);
     418             : }
     419             : 
     420          46 : void SdrMediaObj::mediaPropertiesChanged( const ::avmedia::MediaItem& rNewProperties )
     421             : {
     422          46 :     bool bBroadcastChanged = false;
     423          46 :     const AVMediaSetMask nMaskSet = rNewProperties.getMaskSet();
     424             : 
     425             :     // use only a subset of MediaItem properties for own own properties
     426          46 :     if( AVMediaSetMask::MIME_TYPE & nMaskSet )
     427           5 :         m_xImpl->m_MediaProperties.setMimeType( rNewProperties.getMimeType() );
     428             : 
     429          99 :     if( ( AVMediaSetMask::URL & nMaskSet ) &&
     430          53 :         ( rNewProperties.getURL() != getURL() ))
     431             :     {
     432           7 :         m_xImpl->m_xCachedSnapshot.clear();
     433           7 :         OUString const url(rNewProperties.getURL());
     434           7 :         if (url.startsWithIgnoreAsciiCase("vnd.sun.star.Package:"))
     435             :         {
     436          14 :             if (   !m_xImpl->m_pTempFile
     437           7 :                 || (m_xImpl->m_pTempFile->m_TempFileURL !=
     438           0 :                                 rNewProperties.getTempURL()))
     439             :             {
     440           7 :                 OUString tempFileURL;
     441          14 :                 OUString tempDirURL;
     442             :                 bool bSuccess;
     443             : #if HAVE_FEATURE_GLTF
     444           7 :                 if( url.endsWith(".json") )
     445           2 :                     bSuccess = lcl_HandleJsonPackageURL(url, GetModel(), tempFileURL, tempDirURL);
     446             :                 else
     447             : #endif
     448           5 :                     bSuccess = lcl_HandlePackageURL(url, GetModel(), tempFileURL);
     449           7 :                 if (bSuccess)
     450             :                 {
     451           4 :                     m_xImpl->m_pTempFile.reset(
     452           8 :                             new MediaTempFile(tempFileURL, tempDirURL));
     453           4 :                     m_xImpl->m_MediaProperties.setURL(url, tempFileURL, "");
     454             :                 }
     455             :                 else // this case is for Clone via operator=
     456             :                 {
     457           3 :                     m_xImpl->m_pTempFile.reset();
     458           3 :                     m_xImpl->m_MediaProperties.setURL("", "", "");
     459             :                     // UGLY: oox import also gets here, because unlike ODF
     460             :                     // getDocumentStorage() is not the imported file...
     461           3 :                     m_xImpl->m_LastFailedPkgURL = url;
     462           7 :                 }
     463             :             }
     464             :             else
     465             :             {
     466           0 :                 m_xImpl->m_MediaProperties.setURL(url,
     467           0 :                         rNewProperties.getTempURL(), "");
     468             :             }
     469             :         }
     470             :         else
     471             :         {
     472           0 :             m_xImpl->m_pTempFile.reset();
     473           0 :             m_xImpl->m_MediaProperties.setURL(url, "", rNewProperties.getReferer());
     474             :         }
     475           7 :         bBroadcastChanged = true;
     476             :     }
     477             : 
     478          46 :     if( AVMediaSetMask::LOOP & nMaskSet )
     479          10 :         m_xImpl->m_MediaProperties.setLoop( rNewProperties.isLoop() );
     480             : 
     481          46 :     if( AVMediaSetMask::MUTE & nMaskSet )
     482          10 :         m_xImpl->m_MediaProperties.setMute( rNewProperties.isMute() );
     483             : 
     484          46 :     if( AVMediaSetMask::VOLUMEDB & nMaskSet )
     485          10 :         m_xImpl->m_MediaProperties.setVolumeDB( rNewProperties.getVolumeDB() );
     486             : 
     487          46 :     if( AVMediaSetMask::ZOOM & nMaskSet )
     488           4 :         m_xImpl->m_MediaProperties.setZoom( rNewProperties.getZoom() );
     489             : 
     490          46 :     if( bBroadcastChanged )
     491             :     {
     492           7 :         SetChanged();
     493           7 :         BroadcastObjectChange();
     494             :     }
     495         481 : }
     496             : 
     497             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11