Related: tdf#149971 avmedia: add doc model and render for crop of media objects
It is possible to provide an explicit preview of media objects since
commit 8fa1d453c94cdbb03dac646fb8db2ebd1a0e84bd (Related: tdf#149971
svx: support explicitly provided snapshots for media shapes,
2022-08-24), however they can't be cropped.
This means that media shapes from PPTX with cropping show unexpected
content and can also have a buggy aspect ratio.
Extend avmedia::MediaItem to store cropping and take it into account
when returning the preview bitmap in SdrMediaObj::getSnapshot(). PPTX
import works out of the box, as oox/ already tried to set a cropping
property on the media shape.
This is just the preview, the cropping of the video itself is not yet
implemented.
(cherry picked from commit b6f0fd6a2f459ead2268e07bfd86db7e303b323f)
Conflicts:
svx/source/unodraw/unoprov.cxx
Change-Id: I8db3e0dcf252613d56eb0e6139adf097e53b15cc
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/138963
Tested-by: Jenkins
Reviewed-by: Sarper Akdemir <sarper.akdemir@collabora.com>
diff --git a/avmedia/source/framework/mediaitem.cxx b/avmedia/source/framework/mediaitem.cxx
index 0a53cf5..ac8c09b 100644
--- a/avmedia/source/framework/mediaitem.cxx
+++ b/avmedia/source/framework/mediaitem.cxx
@@ -30,6 +30,7 @@
#include <com/sun/star/uri/UriReferenceFactory.hpp>
#include <com/sun/star/uri/XUriReference.hpp>
#include <com/sun/star/uri/XUriReferenceFactory.hpp>
#include <com/sun/star/text/GraphicCrop.hpp>
#include <sal/log.hxx>
@@ -64,6 +65,7 @@ struct MediaItem::Impl
bool m_bMute;
css::media::ZoomLevel m_eZoom;
Graphic m_aGraphic;
text::GraphicCrop m_aCrop;
explicit Impl(AVMediaSetMask nMaskSet)
: m_nMaskSet( nMaskSet )
@@ -107,6 +109,7 @@ bool MediaItem::operator==( const SfxPoolItem& rItem ) const
&& m_pImpl->m_Referer == rOther.m_pImpl->m_Referer
&& m_pImpl->m_sMimeType == rOther.m_pImpl->m_sMimeType
&& m_pImpl->m_aGraphic == rOther.m_pImpl->m_aGraphic
&& m_pImpl->m_aCrop == rOther.m_pImpl->m_aCrop
&& m_pImpl->m_eState == rOther.m_pImpl->m_eState
&& m_pImpl->m_fDuration == rOther.m_pImpl->m_fDuration
&& m_pImpl->m_fTime == rOther.m_pImpl->m_fTime
@@ -193,6 +196,9 @@ bool MediaItem::merge(const MediaItem& rMediaItem)
if (nMaskSet & AVMediaSetMask::GRAPHIC)
bChanged |= setGraphic(rMediaItem.getGraphic());
if (nMaskSet & AVMediaSetMask::CROP)
bChanged |= setCrop(rMediaItem.getCrop());
if( AVMediaSetMask::STATE & nMaskSet )
bChanged |= setState( rMediaItem.getState() );
@@ -275,6 +281,17 @@ bool MediaItem::setGraphic(const Graphic& rGraphic)
const Graphic & MediaItem::getGraphic() const { return m_pImpl->m_aGraphic; }
bool MediaItem::setCrop(const text::GraphicCrop& rCrop)
{
m_pImpl->m_nMaskSet |= AVMediaSetMask::CROP;
bool bChanged = rCrop != m_pImpl->m_aCrop;
if (bChanged)
m_pImpl->m_aCrop = rCrop;
return bChanged;
}
const text::GraphicCrop& MediaItem::getCrop() const { return m_pImpl->m_aCrop; }
bool MediaItem::setState(MediaState eState)
{
m_pImpl->m_nMaskSet |= AVMediaSetMask::STATE;
diff --git a/include/avmedia/mediaitem.hxx b/include/avmedia/mediaitem.hxx
index 5d033b7..bbb5e06 100644
--- a/include/avmedia/mediaitem.hxx
+++ b/include/avmedia/mediaitem.hxx
@@ -33,6 +33,7 @@ namespace com::sun::star::embed { class XStorage; }
namespace com::sun::star::frame { class XModel; }
namespace com::sun::star::io { class XInputStream; }
namespace com::sun::star::io { class XStream; }
namespace com::sun::star::text { struct GraphicCrop; }
class Graphic;
enum class AVMediaSetMask
@@ -48,11 +49,12 @@ enum class AVMediaSetMask
URL = 0x080,
MIME_TYPE = 0x100,
GRAPHIC = 0x200,
ALL = 0x3ff,
CROP = 0x400,
ALL = 0x7ff,
};
namespace o3tl
{
template<> struct typed_flags<AVMediaSetMask> : is_typed_flags<AVMediaSetMask, 0x3ff> {};
template<> struct typed_flags<AVMediaSetMask> : is_typed_flags<AVMediaSetMask, 0x7ff> {};
}
@@ -120,6 +122,8 @@ public:
OUString getMimeType() const;
bool setGraphic(const Graphic& rGraphic);
const Graphic & getGraphic() const;
bool setCrop(const css::text::GraphicCrop& rCrop);
const css::text::GraphicCrop& getCrop() const;
const OUString& getTempURL() const;
const OUString& getReferer() const;
diff --git a/svx/qa/unit/data/video-snapshot.pptx b/svx/qa/unit/data/video-snapshot.pptx
index 9a0ec9e..a212f10 100644
--- a/svx/qa/unit/data/video-snapshot.pptx
+++ b/svx/qa/unit/data/video-snapshot.pptx
Binary files differ
diff --git a/svx/qa/unit/svdraw.cxx b/svx/qa/unit/svdraw.cxx
index 1bb9a6d..a2bee4a 100644
--- a/svx/qa/unit/svdraw.cxx
+++ b/svx/qa/unit/svdraw.cxx
@@ -505,6 +505,12 @@ CPPUNIT_TEST_FIXTURE(SvdrawTest, testVideoSnapshot)
// i.e. the preview was black, not red; since we seeked 3 secs into the video, while PowerPoint
// doesn't do that.
CPPUNIT_ASSERT_EQUAL(Color(0xff, 0x0, 0x0), rBitmap.GetPixelColor(0, 0));
// Without the accompanying fix in place, this test would have failed with:
// - Expected: 321
// - Actual : 640
// i.e. ~25% crop from left and right should result in half width, but it was not reduced.
CPPUNIT_ASSERT_EQUAL(static_cast<tools::Long>(321), rBitmap.GetSizePixel().getWidth());
}
}
diff --git a/svx/source/svdraw/svdomedia.cxx b/svx/source/svdraw/svdomedia.cxx
index de813b9..46a35c2d 100644
--- a/svx/source/svdraw/svdomedia.cxx
+++ b/svx/source/svdraw/svdomedia.cxx
@@ -21,6 +21,8 @@
#include <svx/svdomedia.hxx>
#include <com/sun/star/text/GraphicCrop.hpp>
#include <rtl/ustring.hxx>
#include <sal/log.hxx>
@@ -154,6 +156,20 @@ uno::Reference< graphic::XGraphic > const & SdrMediaObj::getSnapshot() const
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();
@@ -363,6 +379,11 @@ void SdrMediaObj::mediaPropertiesChanged( const ::avmedia::MediaItem& rNewProper
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() ))
{
diff --git a/svx/source/unodraw/unoprov.cxx b/svx/source/unodraw/unoprov.cxx
index 68bdde6..9936a4d 100644
--- a/svx/source/unodraw/unoprov.cxx
+++ b/svx/source/unodraw/unoprov.cxx
@@ -736,6 +736,7 @@ static SfxItemPropertyMapEntry const * ImplGetSvxMediaShapePropertyMap()
{ 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},
{ UNO_NAME_GRAPHOBJ_GRAPHIC, OWN_ATTR_VALUE_GRAPHIC , cppu::UnoType<css::graphic::XGraphic>::get(), 0, 0},
{ UNO_NAME_GRAPHIC_GRAPHICCROP, SDRATTR_GRAFCROP , cppu::UnoType<css::text::GraphicCrop>::get(), 0, 0},
{ u"", 0, css::uno::Type(), 0, 0 }
};
diff --git a/svx/source/unodraw/unoshap4.cxx b/svx/source/unodraw/unoshap4.cxx
index 2635074..4aabe59 100644
--- a/svx/source/unodraw/unoshap4.cxx
+++ b/svx/source/unodraw/unoshap4.cxx
@@ -783,7 +783,8 @@ bool SvxMediaShape::setPropertyValueImpl( const OUString& rName, const SfxItemPr
if( ((pProperty->nWID >= OWN_ATTR_MEDIA_URL) && (pProperty->nWID <= OWN_ATTR_MEDIA_ZOOM))
|| (pProperty->nWID == OWN_ATTR_MEDIA_STREAM)
|| (pProperty->nWID == OWN_ATTR_MEDIA_MIMETYPE)
|| (pProperty->nWID == OWN_ATTR_VALUE_GRAPHIC))
|| (pProperty->nWID == OWN_ATTR_VALUE_GRAPHIC)
|| (pProperty->nWID == SDRATTR_GRAFCROP))
{
#if HAVE_FEATURE_AVMEDIA
SdrMediaObj* pMedia = static_cast< SdrMediaObj* >( GetSdrObject() );
@@ -888,6 +889,19 @@ bool SvxMediaShape::setPropertyValueImpl( const OUString& rName, const SfxItemPr
#endif
break;
case SDRATTR_GRAFCROP:
#if HAVE_FEATURE_AVMEDIA
{
text::GraphicCrop aCrop;
if (rValue >>= aCrop)
{
bOk = true;
aItem.setCrop(aCrop);
}
}
#endif
break;
case OWN_ATTR_MEDIA_STREAM:
#if HAVE_FEATURE_AVMEDIA
try
@@ -946,7 +960,8 @@ bool SvxMediaShape::getPropertyValueImpl( const OUString& rName, const SfxItemPr
|| (pProperty->nWID == OWN_ATTR_MEDIA_TEMPFILEURL)
|| (pProperty->nWID == OWN_ATTR_MEDIA_MIMETYPE)
|| (pProperty->nWID == OWN_ATTR_FALLBACK_GRAPHIC)
|| (pProperty->nWID == OWN_ATTR_VALUE_GRAPHIC))
|| (pProperty->nWID == OWN_ATTR_VALUE_GRAPHIC)
|| (pProperty->nWID == SDRATTR_GRAFCROP))
{
SdrMediaObj* pMedia = static_cast< SdrMediaObj* >( GetSdrObject() );
#if HAVE_FEATURE_AVMEDIA
@@ -1031,6 +1046,15 @@ bool SvxMediaShape::getPropertyValueImpl( const OUString& rName, const SfxItemPr
#endif
break;
case SDRATTR_GRAFCROP:
#if HAVE_FEATURE_AVMEDIA
{
text::GraphicCrop aCrop = aItem.getCrop();
rValue <<= aCrop;
}
#endif
break;
case OWN_ATTR_FALLBACK_GRAPHIC:
rValue <<= pMedia->getSnapshot();
break;