avmedia: implement video crop support in the ODP filter

And also import/export the video preview as well. The naming follows the
style used for table shape previews.

The preview is important, since the cropping is relative to the bitmap's
preferred logic size.

Change-Id: I6115284c1f4cf342b3296cd0ac3beb70a809fd1b
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/138959
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
Tested-by: Jenkins
This commit is contained in:
Miklos Vajna 2022-08-29 09:23:22 +02:00
parent 690458889f
commit cbc6e67d3c
7 changed files with 146 additions and 2 deletions

View File

@ -858,6 +858,8 @@ private:
// override these for special property handling in subcasses. Return true if property is handled
virtual bool setPropertyValueImpl( const OUString& rName, const SfxItemPropertyMapEntry* pProperty, const css::uno::Any& rValue ) override;
virtual bool getPropertyValueImpl( const OUString& rName, const SfxItemPropertyMapEntry* pProperty, css::uno::Any& rValue ) override;
bool getPropertyStateImpl(const SfxItemPropertyMapEntry* pProperty,
css::beans::PropertyState& rState) override;
OUString referer_;
};

View File

@ -1071,4 +1071,29 @@ bool SvxMediaShape::getPropertyValueImpl( const OUString& rName, const SfxItemPr
}
}
bool SvxMediaShape::getPropertyStateImpl(const SfxItemPropertyMapEntry* pProperty,
css::beans::PropertyState& rState)
{
#if HAVE_FEATURE_AVMEDIA
if (pProperty->nWID == SDRATTR_GRAFCROP)
{
auto pMedia = static_cast<SdrMediaObj*>(GetSdrObject());
const avmedia::MediaItem& rItem = pMedia->getMediaProperties();
const text::GraphicCrop& rCrop = rItem.getCrop();
if (rCrop.Bottom > 0 || rCrop.Left > 0 || rCrop.Right > 0 || rCrop.Top > 0)
{
// The media has a crop, expose it to UNO-based export filters.
rState = beans::PropertyState_DIRECT_VALUE;
}
else
{
rState = beans::PropertyState_AMBIGUOUS_VALUE;
}
return true;
}
#endif
return SvxShape::getPropertyStateImpl(pProperty, rState);
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

View File

@ -28,6 +28,9 @@ $(eval $(call gb_CppunitTest_use_libraries,xmloff_draw, \
test \
unotest \
utl \
avmedia \
svxcore \
vcl \
))
$(eval $(call gb_CppunitTest_use_sdk_api,xmloff_draw))

Binary file not shown.

View File

@ -24,6 +24,7 @@
#include <com/sun/star/util/Color.hpp>
#include <com/sun/star/text/XTextRange.hpp>
#include <com/sun/star/text/XTextTable.hpp>
#include <com/sun/star/text/GraphicCrop.hpp>
#include <comphelper/propertyvalue.hxx>
#include <comphelper/sequence.hxx>
@ -31,6 +32,9 @@
#include <unotools/tempfile.hxx>
#include <unotools/ucbstreamhelper.hxx>
#include <unotools/saveopt.hxx>
#include <svx/unopage.hxx>
#include <svx/svdpage.hxx>
#include <svx/svdomedia.hxx>
using namespace ::com::sun::star;
@ -173,6 +177,52 @@ CPPUNIT_TEST_FIXTURE(XmloffDrawTest, testThemeExport)
assertXPath(pXmlDoc, "//style:master-page/loext:theme/loext:color-table/loext:color", 12);
}
CPPUNIT_TEST_FIXTURE(XmloffDrawTest, testVideoSnapshot)
{
// Execute ODP import:
OUString aURL = m_directories.getURLFromSrc(u"xmloff/qa/unit/data/video-snapshot.odp");
getComponent() = loadFromDesktop(aURL, "com.sun.star.presentation.PresentationDocument");
uno::Reference<drawing::XDrawPagesSupplier> xDrawPagesSupplier(getComponent(),
uno::UNO_QUERY_THROW);
CPPUNIT_ASSERT(xDrawPagesSupplier.is());
uno::Reference<drawing::XDrawPages> xDrawPages(xDrawPagesSupplier->getDrawPages());
uno::Reference<drawing::XDrawPage> xDrawPage(xDrawPages->getByIndex(0), uno::UNO_QUERY_THROW);
CPPUNIT_ASSERT(xDrawPage.is());
auto pUnoPage = dynamic_cast<SvxDrawPage*>(xDrawPage.get());
SdrPage* pSdrPage = pUnoPage->GetSdrPage();
auto pMedia = dynamic_cast<SdrMediaObj*>(pSdrPage->GetObj(0));
// Check that the preview was imported:
const avmedia::MediaItem& rItem = pMedia->getMediaProperties();
const Graphic& rGraphic = rItem.getGraphic();
CPPUNIT_ASSERT(!rGraphic.IsNone());
// Check that the crop was imported:
const text::GraphicCrop& rCrop = rItem.getCrop();
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), rCrop.Top);
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), rCrop.Bottom);
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1356), rCrop.Left);
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1356), rCrop.Right);
// Execute ODP export:
utl::TempFile aTempFile;
save("impress8", aTempFile);
std::unique_ptr<SvStream> pStream = parseExportStream(aTempFile, "content.xml");
xmlDocUniquePtr pXmlDoc = parseXmlStream(pStream.get());
// Check that the preview was exported:
// Without the accompanying fix in place, this test would have failed with:
// - Expected: 1
// - Actual : 0
// - XPath '//draw:frame[@draw:style-name='gr1']/draw:image' number of nodes is incorrect
// i.e. the preview wasn't exported to ODP.
assertXPath(pXmlDoc, "//draw:frame[@draw:style-name='gr1']/draw:image", "href",
"Pictures/MediaPreview1.png");
// Check that the crop was exported:
assertXPath(pXmlDoc, "//style:style[@style:name='gr1']/style:graphic-properties", "clip",
"rect(0cm, 1.356cm, 0cm, 1.356cm)");
}
CPPUNIT_TEST_FIXTURE(XmloffDrawTest, testThemeImport)
{
// Given a document that has a master page with a theme associated:

View File

@ -103,6 +103,7 @@
#include <tools/globname.hxx>
#include <tools/helpers.hxx>
#include <comphelper/diagnose_ex.hxx>
#include <vcl/graph.hxx>
#include <xmloff/contextid.hxx>
#include <xmloff/families.hxx>
@ -3400,7 +3401,7 @@ void XMLShapeExport::ImpExportMediaShape(
mrExport.AddAttribute( XML_NAMESPACE_DRAW, XML_MIME_TYPE, sMimeType );
// write plugin
SvXMLElementExport aPluginOBJ(mrExport, XML_NAMESPACE_DRAW, XML_PLUGIN, !( nFeatures & XMLShapeExportFlags::NO_WS ), true);
auto pPluginOBJ = std::make_unique<SvXMLElementExport>(mrExport, XML_NAMESPACE_DRAW, XML_PLUGIN, !( nFeatures & XMLShapeExportFlags::NO_WS ), true);
// export parameters
const OUString aFalseStr( "false" ), aTrueStr( "true" );
@ -3450,6 +3451,57 @@ void XMLShapeExport::ImpExportMediaShape(
delete new SvXMLElementExport( mrExport, XML_NAMESPACE_DRAW, XML_PARAM, false, true );
}
pPluginOBJ.reset();
uno::Reference<graphic::XGraphic> xGraphic;
xPropSet->getPropertyValue("Graphic") >>= xGraphic;
Graphic aGraphic(xGraphic);
if (!aGraphic.IsNone())
{
// The media has a preview, export it.
uno::Reference<embed::XStorage> xPictureStorage;
uno::Reference<embed::XStorage> xStorage;
uno::Reference<io::XStream> xPictureStream;
OUString sPictureName;
xStorage.set(GetExport().GetTargetStorage(), uno::UNO_SET_THROW);
xPictureStorage.set(
xStorage->openStorageElement("Pictures", embed::ElementModes::READWRITE),
uno::UNO_SET_THROW);
sal_Int32 nIndex = 0;
while (true)
{
sPictureName = "MediaPreview" + OUString::number(++nIndex) + ".png";
if (!xPictureStorage->hasByName(sPictureName))
{
break;
}
}
xPictureStream.set(
xPictureStorage->openStreamElement(sPictureName, ::embed::ElementModes::READWRITE),
uno::UNO_SET_THROW);
uno::Reference<uno::XComponentContext> xContext = GetExport().getComponentContext();
uno::Reference<graphic::XGraphicProvider> xProvider(
graphic::GraphicProvider::create(xContext));
uno::Sequence<beans::PropertyValue> aArgs{
comphelper::makePropertyValue("MimeType", OUString("image/png")),
comphelper::makePropertyValue("OutputStream", xPictureStream->getOutputStream())
};
xProvider->storeGraphic(xGraphic, aArgs);
if (xPictureStorage.is())
{
uno::Reference<embed::XTransactedObject> xTrans(xPictureStorage, uno::UNO_QUERY);
if (xTrans.is())
xTrans->commit();
}
OUString sURL = "Pictures/" + sPictureName;
mrExport.AddAttribute(XML_NAMESPACE_XLINK, XML_HREF, sURL);
mrExport.AddAttribute(XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE);
mrExport.AddAttribute(XML_NAMESPACE_XLINK, XML_SHOW, XML_EMBED);
mrExport.AddAttribute(XML_NAMESPACE_XLINK, XML_ACTUATE, XML_ONLOAD);
SvXMLElementExport aImageElem(GetExport(), XML_NAMESPACE_DRAW, XML_IMAGE, false, true);
}
}
void XMLShapeExport::ImpExport3DSceneShape( const uno::Reference< drawing::XShape >& xShape, XMLShapeExportFlags nFeatures, awt::Point* pRefPoint)

View File

@ -2918,6 +2918,12 @@ void SdXMLPluginShapeContext::startFastElement (sal_Int32 /*nElement*/,
if( !mxShape.is() )
return;
if (mbMedia)
{
// The media may have a crop, apply it.
SetStyle(/*bSupportsStyle=*/false);
}
SetLayer();
if(bIsPresShape)
@ -3312,6 +3318,7 @@ css::uno::Reference< css::xml::sax::XFastContextHandler > SdXMLFrameShapeContext
pShapeContext->setHyperlink( msHyperlink );
auto nToken = nElement & TOKEN_MASK;
bool bMedia = false;
// Ignore gltf model if necessary and so the fallback image will be imported
if( nToken == XML_PLUGIN )
{
@ -3321,10 +3328,15 @@ css::uno::Reference< css::xml::sax::XFastContextHandler > SdXMLFrameShapeContext
mxImplContext = nullptr;
return new SvXMLImportContext(GetImport());
}
else if (pPluginContext && pPluginContext->getMimeType() == "application/vnd.sun.star.media")
{
// The media may have a preview, import it.
bMedia = true;
}
}
mxImplContext = xContext;
mbSupportsReplacement = (nToken == XML_OBJECT ) || (nToken == XML_OBJECT_OLE);
mbSupportsReplacement = (nToken == XML_OBJECT ) || (nToken == XML_OBJECT_OLE) || bMedia;
setSupportsMultipleContents(nToken == XML_IMAGE);
if(getSupportsMultipleContents() && dynamic_cast< SdXMLGraphicObjectShapeContext* >(xContext.get()))