Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/LibreOffice/svx/source/svdraw/   (Office von Apache Version 25.8.3.2©)  Datei vom 5.10.2025 mit Größe 14 kB image not shown  

Quelle  svdomedia.cxx   Sprache: C

 
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column:100 -*- */
/*
 * 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/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */


#include <config_features.h>

#include <svx/svdomedia.hxx>

#include <com/sun/star/text/GraphicCrop.hpp>

#include <rtl/ustring.hxx>
#include <sal/log.hxx>

#include <ucbhelper/content.hxx>
#include <comphelper/processfactory.hxx>
#include <comphelper/storagehelper.hxx>

#include <vcl/svapp.hxx>

#include <svx/svdmodel.hxx>
#include <svx/dialmgr.hxx>
#include <svx/strings.hrc>
#include <svx/sdr/contact/viewcontactofsdrmediaobj.hxx>
#include <avmedia/mediawindow.hxx>
#include <comphelper/diagnose_ex.hxx>

using namespace ::com::sun::star;


struct SdrMediaObj::Impl
{
    ::avmedia::MediaItem                  m_MediaProperties;
#if HAVE_FEATURE_AVMEDIA
    // Note: the temp file is read only, until it is deleted!
    // It may be shared between multiple documents in case of copy/paste,
    // hence the shared_ptr.
    std::shared_ptr< ::avmedia::MediaTempFile >  m_pTempFile;
#endif
    uno::Reference< graphic::XGraphic >   m_xCachedSnapshot;
    rtl::Reference<avmedia::PlayerListener> m_xPlayerListener;
    OUString m_LastFailedPkgURL;
};

SdrMediaObj::SdrMediaObj(SdrModel& rSdrModel)
:   SdrRectObj(rSdrModel)
    ,m_xImpl( new Impl )
{
}

SdrMediaObj::SdrMediaObj(SdrModel& rSdrModel, SdrMediaObj const & rSource)
:   SdrRectObj(rSdrModel, rSource)
    ,m_xImpl( new Impl )
{
#if HAVE_FEATURE_AVMEDIA
    m_xImpl->m_pTempFile = rSource.m_xImpl->m_pTempFile; // before props
#endif
    setMediaProperties( rSource.getMediaProperties() );
    m_xImpl->m_xCachedSnapshot = rSource.m_xImpl->m_xCachedSnapshot;
}

SdrMediaObj::SdrMediaObj(
    SdrModel& rSdrModel,
    const tools::Rectangle& rRect)
:   SdrRectObj(rSdrModel, rRect)
    ,m_xImpl( new Impl )
{
    osl_atomic_increment(&m_refCount);

    const bool bUndo(rSdrModel.IsUndoEnabled());
    rSdrModel.EnableUndo(false);
    MakeNameUnique();
    rSdrModel.EnableUndo(bUndo);

    osl_atomic_decrement(&m_refCount);
}

SdrMediaObj::~SdrMediaObj()
{
}

bool SdrMediaObj::HasTextEdit() const
{
    return false;
}

std::unique_ptr<sdr::contact::ViewContact> SdrMediaObj::CreateObjectSpecificViewContact()
{
    return std::make_unique<sdr::contact::ViewContactOfSdrMediaObj>( *this );
}

void SdrMediaObj::TakeObjInfo( SdrObjTransformInfoRec& rInfo ) const
{
    rInfo.bMoveAllowed = true;
    rInfo.bResizeFreeAllowed = true;
    rInfo.bResizePropAllowed = true;
    rInfo.bRotateFreeAllowed = false;
    rInfo.bRotate90Allowed = false;
    rInfo.bMirrorFreeAllowed = false;
    rInfo.bMirror45Allowed = false;
    rInfo.bMirror90Allowed = false;
    rInfo.bTransparenceAllowed = false;
    rInfo.bShearAllowed = false;
    rInfo.bEdgeRadiusAllowed = false;
    rInfo.bNoOrthoDesired = false;
    rInfo.bNoContortion = false;
    rInfo.bCanConvToPath = false;
    rInfo.bCanConvToPoly = false;
    rInfo.bCanConvToContour = false;
    rInfo.bCanConvToPathLineToArea = false;
    rInfo.bCanConvToPolyLineToArea = false;
}

SdrObjKind SdrMediaObj::GetObjIdentifier() const
{
    return SdrObjKind::Media;
}

OUString SdrMediaObj::TakeObjNameSingul() const
{
    OUString sName(SvxResId(STR_ObjNameSingulMEDIA));

    OUString aName(GetName());

    if (!aName.isEmpty())
        sName += " '" + aName + "'";

    return sName;
}

OUString SdrMediaObj::TakeObjNamePlural() const
{
    return SvxResId(STR_ObjNamePluralMEDIA);
}

rtl::Reference<SdrObject> SdrMediaObj::CloneSdrObject(SdrModel& rTargetModel) const
{
    return new SdrMediaObj(rTargetModel, *this);
}

uno::Reference< graphic::XGraphic > const & SdrMediaObj::getSnapshot() const
{
#if HAVE_FEATURE_AVMEDIA
    if( !m_xImpl->m_xCachedSnapshot.is() )
    {
        Graphic aGraphic = m_xImpl->m_MediaProperties.getGraphic();
        if (!aGraphic.IsNone())
        {
            Size aPref = aGraphic.GetPrefSize();
            Size aPixel = aGraphic.GetSizePixel();
            const text::GraphicCrop& rCrop = m_xImpl->m_MediaProperties.getCrop();
            if (rCrop.Bottom > 0 || rCrop.Left > 0 || rCrop.Right > 0 || rCrop.Top > 0)
            {
                tools::Long nLeft = aPixel.getWidth() * rCrop.Left / aPref.getWidth();
                tools::Long nTop = aPixel.getHeight() * rCrop.Top / aPref.getHeight();
                tools::Long nRight = aPixel.getWidth() * rCrop.Right / aPref.getWidth();
                tools::Long nBottom = aPixel.getHeight() * rCrop.Bottom / aPref.getHeight();
                BitmapEx aBitmapEx = aGraphic.GetBitmapEx();
                aBitmapEx.Crop({nLeft, nTop, aPixel.getWidth() - nRight, aPixel.getHeight() - nBottom});
                aGraphic = aBitmapEx;
            }

            // We have an explicit graphic for this media object, then go with that instead of
            // generating our own one.
            m_xImpl->m_xCachedSnapshot = aGraphic.GetXGraphic();
            return m_xImpl->m_xCachedSnapshot;
        }

        OUString aRealURL = m_xImpl->m_MediaProperties.getTempURL();
        if( aRealURL.isEmpty() )
            aRealURL = m_xImpl->m_MediaProperties.getURL();
        OUString sReferer = m_xImpl->m_MediaProperties.getReferer();
        OUString sMimeType = m_xImpl->m_MediaProperties.getMimeType();
        uno::Reference<graphic::XGraphic> xCachedSnapshot = m_xImpl->m_xCachedSnapshot;

        m_xImpl->m_xPlayerListener.set(new avmedia::PlayerListener(
            [this, xCachedSnapshot, aRealURL, sReferer, sMimeType](const css::uno::Reference<css::media::XPlayer>& rPlayer){
                SolarMutexGuard g;
                uno::Reference<graphic::XGraphic> xGraphic
                    = m_xImpl->m_MediaProperties.getGraphic().GetXGraphic();
                m_xImpl->m_xCachedSnapshot = avmedia::MediaWindow::grabFrame(rPlayer, xGraphic);
                ActionChanged();
            }));

        avmedia::MediaWindow::grabFrame(aRealURL, sReferer, sMimeType, m_xImpl->m_xPlayerListener);
    }
#endif
    return m_xImpl->m_xCachedSnapshot;
}

void SdrMediaObj::AdjustToMaxRect( const tools::Rectangle& rMaxRect, bool bShrinkOnly /* = false */ )
{
    Size aSize( Application::GetDefaultDevice()->PixelToLogic(
                    static_cast< sdr::contact::ViewContactOfSdrMediaObj& >( GetViewContact() ).getPreferredSize(),
                    MapMode(MapUnit::Map100thMM)) );
    Size aMaxSize( rMaxRect.GetSize() );

    if( aSize.IsEmpty() )
        return;

    Point aPos( rMaxRect.TopLeft() );

    // if graphic is too large, fit it to the page
    if ( (!bShrinkOnly                          ||
         ( aSize.Height() > aMaxSize.Height() ) ||
         ( aSize.Width()  > aMaxSize.Width()  ) )&&
         aSize.Height() && aMaxSize.Height() )
    {
        float fGrfWH =  static_cast<float>(aSize.Width()) /
                        static_cast<float>(aSize.Height());
        float fWinWH =  static_cast<float>(aMaxSize.Width()) /
                        static_cast<float>(aMaxSize.Height());

        // scale graphic to page size
        if ( fGrfWH < fWinWH )
        {
            aSize.setWidth( static_cast<tools::Long>(aMaxSize.Height() * fGrfWH) );
            aSize.setHeight( aMaxSize.Height() );
        }
        else if ( fGrfWH > 0.F )
        {
            aSize.setWidth( aMaxSize.Width() );
            aSize.setHeight( static_cast<tools::Long>(aMaxSize.Width() / fGrfWH) );
        }

        aPos = rMaxRect.Center();
    }

    if( bShrinkOnly )
        aPos = getRectangle().TopLeft();

    aPos.AdjustX( -(aSize.Width() / 2) );
    aPos.AdjustY( -(aSize.Height() / 2) );
    SetLogicRect( tools::Rectangle( aPos, aSize ) );
}

void SdrMediaObj::setURL(const OUString& rURL, const OUString& rReferer)
{
    ::avmedia::MediaItem aURLItem;
#if HAVE_FEATURE_AVMEDIA
    aURLItem.setURL( rURL, u""_ustr, rReferer );
#else
    (void) rURL;
    (void) rReferer;
#endif
    setMediaProperties( aURLItem );
}

const OUString& SdrMediaObj::getURL() const
{
#if HAVE_FEATURE_AVMEDIA
    return m_xImpl->m_MediaProperties.getURL();
#else
    static OUString ret;
    return ret;
#endif
}

const OUString& SdrMediaObj::getTempURL() const
{
#if HAVE_FEATURE_AVMEDIA
    return m_xImpl->m_MediaProperties.getTempURL();
#else
static OUString ret;
    return ret;
#endif
}

void SdrMediaObj::setMediaProperties( const ::avmedia::MediaItem& rState )
{
    mediaPropertiesChanged( rState );
    static_cast< sdr::contact::ViewContactOfSdrMediaObj& >( GetViewContact() ).executeMediaItem( getMediaProperties() );
}

const ::avmedia::MediaItem& SdrMediaObj::getMediaProperties() const
{
    return m_xImpl->m_MediaProperties;
}

uno::Reference<io::XInputStream> SdrMediaObj::GetInputStream() const
{
#if HAVE_FEATURE_AVMEDIA
    if (!m_xImpl->m_pTempFile)
    {
        SAL_WARN("svx""this is only intended for embedded media");
        return nullptr;
    }
    ucbhelper::Content tempFile(m_xImpl->m_pTempFile->m_TempFileURL,
                uno::Reference<ucb::XCommandEnvironment>(),
                comphelper::getProcessComponentContext());
    return tempFile.openStream();
#else
    return nullptr;
#endif
}

void SdrMediaObj::SetInputStream(uno::Reference<io::XInputStream> const& xStream)
{
#if !HAVE_FEATURE_AVMEDIA
    (void) xStream;
#else
    if (m_xImpl->m_pTempFile || m_xImpl->m_LastFailedPkgURL.isEmpty())
    {
        SAL_WARN("svx""this is only intended for embedded media");
        return;
    }

    OUString tempFileURL;
    const bool bSuccess(
        ::avmedia::CreateMediaTempFile(
            xStream,
            tempFileURL,
            u""));

    if (bSuccess)
    {
        m_xImpl->m_pTempFile = std::make_shared<::avmedia::MediaTempFile>(tempFileURL);
        m_xImpl->m_MediaProperties.setURL(
            m_xImpl->m_LastFailedPkgURL, tempFileURL, u""_ustr);
    }
    m_xImpl->m_LastFailedPkgURL.clear(); // once only
#endif
}

/// copy a stream from XStorage to temp file
#if HAVE_FEATURE_AVMEDIA
static bool lcl_HandlePackageURL(
    OUString const & rURL,
    const SdrModel& rModel,
    OUString & o_rTempFileURL)
{
    ::comphelper::LifecycleProxy sourceProxy;
    uno::Reference<io::XInputStream> xInStream;
    try {
        xInStream = rModel.GetDocumentStream(rURL, sourceProxy);
    }
    catch (container::NoSuchElementException const&)
    {
        SAL_INFO("svx""not found: '" << rURL << "'");
        return false;
    }
    catch (uno::Exception const&)
    {
        TOOLS_WARN_EXCEPTION("svx""");
        return false;
    }
    if (!xInStream.is())
    {
        SAL_WARN("svx""no stream?");
        return false;
    }
    // Make sure the temporary copy has the same file name extension as the original media file
    // (like .mp4). That seems to be important for some AVFoundation APIs. For random extension-less
    // file names, they don't seem to even bother looking inside the file.
    sal_Int32 nLastDot = rURL.lastIndexOf('.');
    sal_Int32 nLastSlash = rURL.lastIndexOf('/');
    OUString sDesiredExtension;
    if (nLastDot > nLastSlash && nLastDot+1 < rURL.getLength())
        sDesiredExtension = rURL.copy(nLastDot);
    return ::avmedia::CreateMediaTempFile(xInStream, o_rTempFileURL, sDesiredExtension);
}
#endif

void SdrMediaObj::mediaPropertiesChanged( const ::avmedia::MediaItem& rNewProperties )
{
    bool bBroadcastChanged = false;
#if HAVE_FEATURE_AVMEDIA
    const AVMediaSetMask nMaskSet = rNewProperties.getMaskSet();

    // use only a subset of MediaItem properties for own properties
    if( AVMediaSetMask::MIME_TYPE & nMaskSet )
        m_xImpl->m_MediaProperties.setMimeType( rNewProperties.getMimeType() );

    if (nMaskSet & AVMediaSetMask::GRAPHIC)
    {
        m_xImpl->m_MediaProperties.setGraphic(rNewProperties.getGraphic());
    }

    if (nMaskSet & AVMediaSetMask::CROP)
    {
        m_xImpl->m_MediaProperties.setCrop(rNewProperties.getCrop());
    }

    if( ( AVMediaSetMask::URL & nMaskSet ) &&
        ( rNewProperties.getURL() != getURL() ))
    {
        m_xImpl->m_xCachedSnapshot.clear();
        m_xImpl->m_xPlayerListener.clear();
        m_xImpl->m_MediaProperties.setFallbackURL( rNewProperties.getFallbackURL() );
        OUString const& url(rNewProperties.getURL());
        if (url.startsWithIgnoreAsciiCase("vnd.sun.star.Package:"))
        {
            if (   !m_xImpl->m_pTempFile
                || (m_xImpl->m_pTempFile->m_TempFileURL !=
                                rNewProperties.getTempURL()))
            {
                OUString tempFileURL;
                const bool bSuccess(
                    lcl_HandlePackageURL(
                        url,
                        getSdrModelFromSdrObject(),
                        tempFileURL));

                if (bSuccess)
                {
                    m_xImpl->m_pTempFile =
                            std::make_shared<::avmedia::MediaTempFile>(tempFileURL);
                    m_xImpl->m_MediaProperties.setURL(url, tempFileURL, u""_ustr);
                }
                else // this case is for Clone via operator=
                {
                    m_xImpl->m_pTempFile.reset();
                    m_xImpl->m_MediaProperties.setURL(u""_ustr, u""_ustr, u""_ustr);
                    // UGLY: oox import also gets here, because unlike ODF
                    // getDocumentStorage() is not the imported file...
                    m_xImpl->m_LastFailedPkgURL = url;
                }
            }
            else
            {
                m_xImpl->m_MediaProperties.setURL(url,
                        rNewProperties.getTempURL(), u""_ustr);
            }
        }
        else
        {
            m_xImpl->m_pTempFile.reset();
            m_xImpl->m_MediaProperties.setURL(url, u""_ustr, rNewProperties.getReferer());
        }
        bBroadcastChanged = true;
    }

    if( AVMediaSetMask::LOOP & nMaskSet )
        m_xImpl->m_MediaProperties.setLoop( rNewProperties.isLoop() );

    if( AVMediaSetMask::MUTE & nMaskSet )
        m_xImpl->m_MediaProperties.setMute( rNewProperties.isMute() );

    if( AVMediaSetMask::VOLUMEDB & nMaskSet )
        m_xImpl->m_MediaProperties.setVolumeDB( rNewProperties.getVolumeDB() );

    if( AVMediaSetMask::ZOOM & nMaskSet )
        m_xImpl->m_MediaProperties.setZoom( rNewProperties.getZoom() );
#else
    (void) rNewProperties;
#endif

    if( bBroadcastChanged )
    {
        SetChanged();
        BroadcastObjectChange();
    }
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Messung V0.5
C=95 H=94 G=94

¤ Dauer der Verarbeitung: 0.5 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.