avmedia/source/framework/mediaitem.cxx |   17 +++++++++++++++++
 include/avmedia/mediaitem.hxx          |    8 ++++++--
 svx/qa/unit/data/video-snapshot.pptx   |binary
 svx/qa/unit/svdraw.cxx                 |    6 ++++++
 svx/source/svdraw/svdomedia.cxx        |   21 +++++++++++++++++++++
 svx/source/unodraw/unoprov.cxx         |    1 +
 svx/source/unodraw/unoshap4.cxx        |   28 ++++++++++++++++++++++++++--
 7 files changed, 77 insertions(+), 4 deletions(-)

New commits:
commit b6f0fd6a2f459ead2268e07bfd86db7e303b323f
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Thu Aug 25 14:01:43 2022 +0200
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Thu Aug 25 15:41:34 2022 +0200

    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.
    
    Change-Id: I8db3e0dcf252613d56eb0e6139adf097e53b15cc
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/138808
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>
    Tested-by: Jenkins

diff --git a/avmedia/source/framework/mediaitem.cxx 
b/avmedia/source/framework/mediaitem.cxx
index 49b400084128..77b28918f545 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 5d033b7efba1..bbb5e06e49b1 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 9a0ec9ebd867..a212f105200f 100644
Binary files a/svx/qa/unit/data/video-snapshot.pptx and 
b/svx/qa/unit/data/video-snapshot.pptx differ
diff --git a/svx/qa/unit/svdraw.cxx b/svx/qa/unit/svdraw.cxx
index 1bb9a6dab4db..a2bee4a8d30d 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 15a0e1179098..1dd55f057991 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 faebaf224213..074d584566db 100644
--- a/svx/source/unodraw/unoprov.cxx
+++ b/svx/source/unodraw/unoprov.cxx
@@ -713,6 +713,7 @@ static o3tl::span<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},
     };
 
     return aMediaShapePropertyMap_Impl;
diff --git a/svx/source/unodraw/unoshap4.cxx b/svx/source/unodraw/unoshap4.cxx
index aee99b3841d3..482efb826117 100644
--- a/svx/source/unodraw/unoshap4.cxx
+++ b/svx/source/unodraw/unoshap4.cxx
@@ -784,7 +784,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() );
@@ -889,6 +890,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
@@ -947,7 +961,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
@@ -1032,6 +1047,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;

Reply via email to