avmedia: add doc model for bitmap fill of slide narrations
This allows specifying a custom bitmap for a media shape. It's mostly useful for audio-only streams where the additional bitmap may be e.g. a speaker icon to indicate this a narration. Change-Id: I21c1b492ac09b631cf6e3ec8120be8b82c01c26d Reviewed-on: https://gerrit.libreoffice.org/c/core/+/109763 Reviewed-by: Miklos Vajna <vmiklos@collabora.com> Tested-by: Jenkins
This commit is contained in:
@@ -40,6 +40,7 @@
|
|||||||
#include <mediamisc.hxx>
|
#include <mediamisc.hxx>
|
||||||
#include <osl/file.hxx>
|
#include <osl/file.hxx>
|
||||||
#include <tools/diagnose_ex.h>
|
#include <tools/diagnose_ex.h>
|
||||||
|
#include <vcl/graph.hxx>
|
||||||
|
|
||||||
using namespace ::com::sun::star;
|
using namespace ::com::sun::star;
|
||||||
|
|
||||||
@@ -62,6 +63,7 @@ struct MediaItem::Impl
|
|||||||
bool m_bLoop;
|
bool m_bLoop;
|
||||||
bool m_bMute;
|
bool m_bMute;
|
||||||
css::media::ZoomLevel m_eZoom;
|
css::media::ZoomLevel m_eZoom;
|
||||||
|
Graphic m_aGraphic;
|
||||||
|
|
||||||
explicit Impl(AVMediaSetMask nMaskSet)
|
explicit Impl(AVMediaSetMask nMaskSet)
|
||||||
: m_nMaskSet( nMaskSet )
|
: m_nMaskSet( nMaskSet )
|
||||||
@@ -104,6 +106,7 @@ bool MediaItem::operator==( const SfxPoolItem& rItem ) const
|
|||||||
&& m_pImpl->m_URL == rOther.m_pImpl->m_URL
|
&& m_pImpl->m_URL == rOther.m_pImpl->m_URL
|
||||||
&& m_pImpl->m_Referer == rOther.m_pImpl->m_Referer
|
&& m_pImpl->m_Referer == rOther.m_pImpl->m_Referer
|
||||||
&& m_pImpl->m_sMimeType == rOther.m_pImpl->m_sMimeType
|
&& m_pImpl->m_sMimeType == rOther.m_pImpl->m_sMimeType
|
||||||
|
&& m_pImpl->m_aGraphic == rOther.m_pImpl->m_aGraphic
|
||||||
&& m_pImpl->m_eState == rOther.m_pImpl->m_eState
|
&& m_pImpl->m_eState == rOther.m_pImpl->m_eState
|
||||||
&& m_pImpl->m_fDuration == rOther.m_pImpl->m_fDuration
|
&& m_pImpl->m_fDuration == rOther.m_pImpl->m_fDuration
|
||||||
&& m_pImpl->m_fTime == rOther.m_pImpl->m_fTime
|
&& m_pImpl->m_fTime == rOther.m_pImpl->m_fTime
|
||||||
@@ -188,6 +191,9 @@ void MediaItem::merge( const MediaItem& rMediaItem )
|
|||||||
if( AVMediaSetMask::MIME_TYPE & nMaskSet )
|
if( AVMediaSetMask::MIME_TYPE & nMaskSet )
|
||||||
setMimeType( rMediaItem.getMimeType() );
|
setMimeType( rMediaItem.getMimeType() );
|
||||||
|
|
||||||
|
if (nMaskSet & AVMediaSetMask::GRAPHIC)
|
||||||
|
setGraphic(rMediaItem.getGraphic());
|
||||||
|
|
||||||
if( AVMediaSetMask::STATE & nMaskSet )
|
if( AVMediaSetMask::STATE & nMaskSet )
|
||||||
setState( rMediaItem.getState() );
|
setState( rMediaItem.getState() );
|
||||||
|
|
||||||
@@ -256,6 +262,13 @@ OUString MediaItem::getMimeType() const
|
|||||||
return !m_pImpl->m_sMimeType.isEmpty() ? m_pImpl->m_sMimeType : AVMEDIA_MIMETYPE_COMMON;
|
return !m_pImpl->m_sMimeType.isEmpty() ? m_pImpl->m_sMimeType : AVMEDIA_MIMETYPE_COMMON;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MediaItem::setGraphic(const Graphic& rGraphic)
|
||||||
|
{
|
||||||
|
m_pImpl->m_nMaskSet |= AVMediaSetMask::GRAPHIC;
|
||||||
|
m_pImpl->m_aGraphic = rGraphic;
|
||||||
|
}
|
||||||
|
|
||||||
|
Graphic MediaItem::getGraphic() const { return m_pImpl->m_aGraphic; }
|
||||||
|
|
||||||
void MediaItem::setState( MediaState eState )
|
void MediaItem::setState( MediaState eState )
|
||||||
{
|
{
|
||||||
|
@@ -32,6 +32,7 @@ namespace com::sun::star::embed { class XStorage; }
|
|||||||
namespace com::sun::star::frame { class XModel; }
|
namespace com::sun::star::frame { class XModel; }
|
||||||
namespace com::sun::star::io { class XInputStream; }
|
namespace com::sun::star::io { class XInputStream; }
|
||||||
namespace com::sun::star::io { class XStream; }
|
namespace com::sun::star::io { class XStream; }
|
||||||
|
class Graphic;
|
||||||
|
|
||||||
enum class AVMediaSetMask
|
enum class AVMediaSetMask
|
||||||
{
|
{
|
||||||
@@ -45,11 +46,12 @@ enum class AVMediaSetMask
|
|||||||
ZOOM = 0x040,
|
ZOOM = 0x040,
|
||||||
URL = 0x080,
|
URL = 0x080,
|
||||||
MIME_TYPE = 0x100,
|
MIME_TYPE = 0x100,
|
||||||
ALL = 0x1ff,
|
GRAPHIC = 0x200,
|
||||||
|
ALL = 0x3ff,
|
||||||
};
|
};
|
||||||
namespace o3tl
|
namespace o3tl
|
||||||
{
|
{
|
||||||
template<> struct typed_flags<AVMediaSetMask> : is_typed_flags<AVMediaSetMask, 0x1ff> {};
|
template<> struct typed_flags<AVMediaSetMask> : is_typed_flags<AVMediaSetMask, 0x3ff> {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -115,6 +117,8 @@ public:
|
|||||||
|
|
||||||
void setMimeType( const OUString& rMimeType );
|
void setMimeType( const OUString& rMimeType );
|
||||||
OUString getMimeType() const;
|
OUString getMimeType() const;
|
||||||
|
void setGraphic(const Graphic& rGraphic);
|
||||||
|
Graphic getGraphic() const;
|
||||||
const OUString& getTempURL() const;
|
const OUString& getTempURL() const;
|
||||||
|
|
||||||
const OUString& getReferer() const;
|
const OUString& getReferer() const;
|
||||||
|
@@ -53,6 +53,8 @@
|
|||||||
|
|
||||||
#include <svx/svdotable.hxx>
|
#include <svx/svdotable.hxx>
|
||||||
#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
|
#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
|
||||||
|
#include <rtl/uri.hxx>
|
||||||
|
#include <vcl/pngread.hxx>
|
||||||
|
|
||||||
using namespace css;
|
using namespace css;
|
||||||
|
|
||||||
@@ -1313,6 +1315,27 @@ void SdOOXMLExportTest1::testNarrationMimeType()
|
|||||||
assertXPath(pXmlDoc,
|
assertXPath(pXmlDoc,
|
||||||
"/ContentType:Types/ContentType:Override[@PartName='/ppt/media/media1.m4a']",
|
"/ContentType:Types/ContentType:Override[@PartName='/ppt/media/media1.m4a']",
|
||||||
"ContentType", "audio/mp4");
|
"ContentType", "audio/mp4");
|
||||||
|
|
||||||
|
// Check if the bitmap of the media shape is exported correctly.
|
||||||
|
xmlDocUniquePtr pSlideDoc = parseExport(aTempFile, "ppt/slides/slide1.xml");
|
||||||
|
OUString aImageId = getXPath(pSlideDoc, "/p:sld/p:cSld/p:spTree/p:pic/p:blipFill/a:blip", "embed");
|
||||||
|
xmlDocUniquePtr pRelsDoc = parseExport(aTempFile, "ppt/slides/_rels/slide1.xml.rels");
|
||||||
|
OUString aImagePath = "/rels:Relationships/rels:Relationship[@Id='" + aImageId + "']";
|
||||||
|
// Something like ../media/image2.png.
|
||||||
|
OUString aImageStreamName = getXPath(pRelsDoc, aImagePath.toUtf8(), "Target");
|
||||||
|
OUString aImageAbsName = rtl::Uri::convertRelToAbs("file:///ppt/slides/", aImageStreamName);
|
||||||
|
// Something like ppt/media/image2.png.
|
||||||
|
OUString aImageRelName;
|
||||||
|
CPPUNIT_ASSERT(aImageAbsName.startsWith("file:///", &aImageRelName));
|
||||||
|
std::unique_ptr<SvStream> pImageStream = parseExportStream(aTempFile, aImageRelName);
|
||||||
|
vcl::PNGReader aReader(*pImageStream);
|
||||||
|
BitmapEx aBitmapEx = aReader.Read();
|
||||||
|
// Without the accompanying fix in place, this test would have failed with:
|
||||||
|
// - Expected: 256
|
||||||
|
// - Actual : 120
|
||||||
|
// i.e. the bitmap of the narration was lost, some default placeholder was exported instead.
|
||||||
|
CPPUNIT_ASSERT_EQUAL(static_cast<tools::Long>(256), aBitmapEx.GetSizePixel().Height());
|
||||||
|
|
||||||
xDocShRef->DoClose();
|
xDocShRef->DoClose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -330,6 +330,11 @@ void SdrMediaObj::mediaPropertiesChanged( const ::avmedia::MediaItem& rNewProper
|
|||||||
if( AVMediaSetMask::MIME_TYPE & nMaskSet )
|
if( AVMediaSetMask::MIME_TYPE & nMaskSet )
|
||||||
m_xImpl->m_MediaProperties.setMimeType( rNewProperties.getMimeType() );
|
m_xImpl->m_MediaProperties.setMimeType( rNewProperties.getMimeType() );
|
||||||
|
|
||||||
|
if (nMaskSet & AVMediaSetMask::GRAPHIC)
|
||||||
|
{
|
||||||
|
m_xImpl->m_MediaProperties.setGraphic(rNewProperties.getGraphic());
|
||||||
|
}
|
||||||
|
|
||||||
if( ( AVMediaSetMask::URL & nMaskSet ) &&
|
if( ( AVMediaSetMask::URL & nMaskSet ) &&
|
||||||
( rNewProperties.getURL() != getURL() ))
|
( rNewProperties.getURL() != getURL() ))
|
||||||
{
|
{
|
||||||
|
@@ -729,6 +729,7 @@ static SfxItemPropertyMapEntry const * ImplGetSvxMediaShapePropertyMap()
|
|||||||
{u"PrivateTempFileURL", OWN_ATTR_MEDIA_TEMPFILEURL, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::READONLY, 0},
|
{u"PrivateTempFileURL", OWN_ATTR_MEDIA_TEMPFILEURL, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::READONLY, 0},
|
||||||
{ u"MediaMimeType", OWN_ATTR_MEDIA_MIMETYPE, cppu::UnoType<OUString>::get(), 0, 0},
|
{ u"MediaMimeType", OWN_ATTR_MEDIA_MIMETYPE, cppu::UnoType<OUString>::get(), 0, 0},
|
||||||
{ u"FallbackGraphic", OWN_ATTR_FALLBACK_GRAPHIC, cppu::UnoType<css::graphic::XGraphic>::get(), css::beans::PropertyAttribute::READONLY, 0},
|
{ u"FallbackGraphic", OWN_ATTR_FALLBACK_GRAPHIC, cppu::UnoType<css::graphic::XGraphic>::get(), css::beans::PropertyAttribute::READONLY, 0},
|
||||||
|
{ u"" UNO_NAME_GRAPHOBJ_GRAPHIC, OWN_ATTR_VALUE_GRAPHIC , cppu::UnoType<css::graphic::XGraphic>::get(), 0, 0},
|
||||||
{ u"", 0, css::uno::Type(), 0, 0 }
|
{ u"", 0, css::uno::Type(), 0, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -779,7 +779,8 @@ bool SvxMediaShape::setPropertyValueImpl( const OUString& rName, const SfxItemPr
|
|||||||
{
|
{
|
||||||
if( ((pProperty->nWID >= OWN_ATTR_MEDIA_URL) && (pProperty->nWID <= OWN_ATTR_MEDIA_ZOOM))
|
if( ((pProperty->nWID >= OWN_ATTR_MEDIA_URL) && (pProperty->nWID <= OWN_ATTR_MEDIA_ZOOM))
|
||||||
|| (pProperty->nWID == OWN_ATTR_MEDIA_STREAM)
|
|| (pProperty->nWID == OWN_ATTR_MEDIA_STREAM)
|
||||||
|| (pProperty->nWID == OWN_ATTR_MEDIA_MIMETYPE) )
|
|| (pProperty->nWID == OWN_ATTR_MEDIA_MIMETYPE)
|
||||||
|
|| (pProperty->nWID == OWN_ATTR_VALUE_GRAPHIC))
|
||||||
{
|
{
|
||||||
SdrMediaObj* pMedia = static_cast< SdrMediaObj* >( GetSdrObject() );
|
SdrMediaObj* pMedia = static_cast< SdrMediaObj* >( GetSdrObject() );
|
||||||
::avmedia::MediaItem aItem;
|
::avmedia::MediaItem aItem;
|
||||||
@@ -869,6 +870,19 @@ bool SvxMediaShape::setPropertyValueImpl( const OUString& rName, const SfxItemPr
|
|||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case OWN_ATTR_VALUE_GRAPHIC:
|
||||||
|
#if HAVE_FEATURE_AVMEDIA
|
||||||
|
{
|
||||||
|
uno::Reference<graphic::XGraphic> xGraphic(rValue, uno::UNO_QUERY);
|
||||||
|
if (xGraphic.is())
|
||||||
|
{
|
||||||
|
bOk = true;
|
||||||
|
aItem.setGraphic(Graphic(xGraphic));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
|
||||||
case OWN_ATTR_MEDIA_STREAM:
|
case OWN_ATTR_MEDIA_STREAM:
|
||||||
#if HAVE_FEATURE_AVMEDIA
|
#if HAVE_FEATURE_AVMEDIA
|
||||||
try
|
try
|
||||||
@@ -924,7 +938,8 @@ bool SvxMediaShape::getPropertyValueImpl( const OUString& rName, const SfxItemPr
|
|||||||
|| (pProperty->nWID == OWN_ATTR_MEDIA_STREAM)
|
|| (pProperty->nWID == OWN_ATTR_MEDIA_STREAM)
|
||||||
|| (pProperty->nWID == OWN_ATTR_MEDIA_TEMPFILEURL)
|
|| (pProperty->nWID == OWN_ATTR_MEDIA_TEMPFILEURL)
|
||||||
|| (pProperty->nWID == OWN_ATTR_MEDIA_MIMETYPE)
|
|| (pProperty->nWID == OWN_ATTR_MEDIA_MIMETYPE)
|
||||||
|| (pProperty->nWID == OWN_ATTR_FALLBACK_GRAPHIC))
|
|| (pProperty->nWID == OWN_ATTR_FALLBACK_GRAPHIC)
|
||||||
|
|| (pProperty->nWID == OWN_ATTR_VALUE_GRAPHIC))
|
||||||
{
|
{
|
||||||
SdrMediaObj* pMedia = static_cast< SdrMediaObj* >( GetSdrObject() );
|
SdrMediaObj* pMedia = static_cast< SdrMediaObj* >( GetSdrObject() );
|
||||||
const ::avmedia::MediaItem aItem( pMedia->getMediaProperties() );
|
const ::avmedia::MediaItem aItem( pMedia->getMediaProperties() );
|
||||||
@@ -995,6 +1010,18 @@ bool SvxMediaShape::getPropertyValueImpl( const OUString& rName, const SfxItemPr
|
|||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case OWN_ATTR_VALUE_GRAPHIC:
|
||||||
|
#if HAVE_FEATURE_AVMEDIA
|
||||||
|
{
|
||||||
|
Graphic aGraphic = aItem.getGraphic();
|
||||||
|
if (!aGraphic.IsNone())
|
||||||
|
{
|
||||||
|
rValue <<= aGraphic.GetXGraphic();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
|
||||||
case OWN_ATTR_FALLBACK_GRAPHIC:
|
case OWN_ATTR_FALLBACK_GRAPHIC:
|
||||||
rValue <<= pMedia->getSnapshot();
|
rValue <<= pMedia->getSnapshot();
|
||||||
break;
|
break;
|
||||||
|
Reference in New Issue
Block a user