739e20ac58
Change-Id: I654e71e56d60bf629625df09eb93b21c9ef670e8
895 lines
34 KiB
C++
895 lines
34 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/*************************************************************************
|
|
*
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* Copyright 2000, 2010 Oracle and/or its affiliates.
|
|
*
|
|
* OpenOffice.org - a multi-platform office productivity suite
|
|
*
|
|
* This file is part of OpenOffice.org.
|
|
*
|
|
* OpenOffice.org is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Lesser General Public License version 3
|
|
* only, as published by the Free Software Foundation.
|
|
*
|
|
* OpenOffice.org is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Lesser General Public License version 3 for more details
|
|
* (a copy is included in the LICENSE file that accompanied this code).
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
* version 3 along with OpenOffice.org. If not, see
|
|
* <http://www.openoffice.org/license.html>
|
|
* for a copy of the LGPLv3 License.
|
|
*
|
|
************************************************************************/
|
|
|
|
|
|
#include <osl/mutex.hxx>
|
|
#include <vcl/svapp.hxx>
|
|
#include <vcl/image.hxx>
|
|
#include <vcl/metaact.hxx>
|
|
#include <vcl/msgbox.hxx>
|
|
#include <vcl/imagerepository.hxx>
|
|
#include <tools/rcid.h>
|
|
#include <tools/resid.hxx>
|
|
#include <tools/resmgr.hxx>
|
|
#include <unotools/ucbstreamhelper.hxx>
|
|
#include <svtools/filter.hxx>
|
|
#include <svtools/wmf.hxx>
|
|
#include <svl/solar.hrc>
|
|
#include <vcl/virdev.hxx>
|
|
#include <com/sun/star/io/XStream.hpp>
|
|
#include <com/sun/star/text/GraphicCrop.hpp>
|
|
#include <comphelper/servicehelper.hxx>
|
|
|
|
#include "descriptor.hxx"
|
|
#include "graphic.hxx"
|
|
#include <svtools/grfmgr.hxx>
|
|
#include "provider.hxx"
|
|
|
|
using namespace com::sun::star;
|
|
|
|
namespace unographic {
|
|
|
|
#define UNO_NAME_GRAPHOBJ_URLPREFIX "vnd.sun.star.GraphicObject:"
|
|
|
|
// -------------------
|
|
// - GraphicProvider -
|
|
// -------------------
|
|
|
|
uno::Reference< uno::XInterface > SAL_CALL GraphicProvider_CreateInstance( const uno::Reference< lang::XMultiServiceFactory >& )
|
|
{
|
|
return (static_cast< ::cppu::OWeakObject* >(new GraphicProvider ));
|
|
}
|
|
|
|
GraphicProvider::GraphicProvider()
|
|
{
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------
|
|
|
|
GraphicProvider::~GraphicProvider()
|
|
{
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------
|
|
|
|
::rtl::OUString GraphicProvider::getImplementationName_Static()
|
|
throw()
|
|
{
|
|
return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.graphic.GraphicProvider" ) );
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------
|
|
|
|
uno::Sequence< ::rtl::OUString > GraphicProvider::getSupportedServiceNames_Static()
|
|
throw()
|
|
{
|
|
uno::Sequence< ::rtl::OUString > aSeq( 1 );
|
|
|
|
aSeq.getArray()[ 0 ] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.graphic.GraphicProvider" ) );
|
|
|
|
return aSeq;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------
|
|
|
|
::rtl::OUString SAL_CALL GraphicProvider::getImplementationName()
|
|
throw( uno::RuntimeException )
|
|
{
|
|
return getImplementationName_Static();
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------
|
|
|
|
sal_Bool SAL_CALL GraphicProvider::supportsService( const ::rtl::OUString& ServiceName )
|
|
throw( uno::RuntimeException )
|
|
{
|
|
uno::Sequence< ::rtl::OUString > aSNL( getSupportedServiceNames() );
|
|
const ::rtl::OUString* pArray = aSNL.getConstArray();
|
|
|
|
for( int i = 0; i < aSNL.getLength(); i++ )
|
|
if( pArray[i] == ServiceName )
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------
|
|
|
|
uno::Sequence< ::rtl::OUString > SAL_CALL GraphicProvider::getSupportedServiceNames()
|
|
throw( uno::RuntimeException )
|
|
{
|
|
return getSupportedServiceNames_Static();
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------
|
|
|
|
uno::Sequence< uno::Type > SAL_CALL GraphicProvider::getTypes()
|
|
throw(uno::RuntimeException)
|
|
{
|
|
uno::Sequence< uno::Type > aTypes( 3 );
|
|
uno::Type* pTypes = aTypes.getArray();
|
|
|
|
*pTypes++ = ::getCppuType((const uno::Reference< lang::XServiceInfo>*)0);
|
|
*pTypes++ = ::getCppuType((const uno::Reference< lang::XTypeProvider>*)0);
|
|
*pTypes++ = ::getCppuType((const uno::Reference< graphic::XGraphicProvider>*)0);
|
|
|
|
return aTypes;
|
|
}
|
|
|
|
namespace
|
|
{
|
|
class theGraphicProviderUnoTunnelId : public rtl::Static< UnoTunnelIdInit, theGraphicProviderUnoTunnelId > {};
|
|
}
|
|
|
|
uno::Sequence< sal_Int8 > SAL_CALL GraphicProvider::getImplementationId()
|
|
throw(uno::RuntimeException)
|
|
{
|
|
return theGraphicProviderUnoTunnelId::get().getSeq();
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------
|
|
|
|
uno::Reference< ::graphic::XGraphic > GraphicProvider::implLoadGraphicObject( const ::rtl::OUString& rResourceURL ) const
|
|
{
|
|
uno::Reference< ::graphic::XGraphic > xRet;
|
|
if( rResourceURL.compareToAscii( UNO_NAME_GRAPHOBJ_URLPREFIX, RTL_CONSTASCII_LENGTH( UNO_NAME_GRAPHOBJ_URLPREFIX ) ) == 0 )
|
|
{
|
|
// graphic manager url
|
|
String aTmpStr( rResourceURL.copy( sizeof( UNO_NAME_GRAPHOBJ_URLPREFIX ) - 1 ) );
|
|
rtl::OString aUniqueID(rtl::OUStringToOString(aTmpStr,
|
|
RTL_TEXTENCODING_UTF8));
|
|
GraphicObject aGrafObj(aUniqueID);
|
|
// I don't call aGrafObj.GetXGraphic because it will call us back
|
|
// into implLoadMemory ( with "private:memorygraphic" test )
|
|
::unographic::Graphic* pUnoGraphic = new ::unographic::Graphic;
|
|
pUnoGraphic->init( aGrafObj.GetGraphic() );
|
|
xRet = pUnoGraphic;
|
|
}
|
|
return xRet;
|
|
}
|
|
|
|
uno::Reference< ::graphic::XGraphic > GraphicProvider::implLoadMemory( const ::rtl::OUString& rResourceURL ) const
|
|
{
|
|
uno::Reference< ::graphic::XGraphic > xRet;
|
|
sal_Int32 nIndex = 0;
|
|
|
|
if( ( 0 == rResourceURL.getToken( 0, '/', nIndex ).compareToAscii( "private:memorygraphic" ) ) )
|
|
{
|
|
sal_Int64 nGraphicAddress = rResourceURL.getToken( 0, '/', nIndex ).toInt64();
|
|
|
|
if( nGraphicAddress )
|
|
{
|
|
::unographic::Graphic* pUnoGraphic = new ::unographic::Graphic;
|
|
|
|
pUnoGraphic->init( *reinterpret_cast< ::Graphic* >( nGraphicAddress ) );
|
|
xRet = pUnoGraphic;
|
|
}
|
|
}
|
|
|
|
return xRet;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------
|
|
|
|
uno::Reference< ::graphic::XGraphic > GraphicProvider::implLoadRepositoryImage( const ::rtl::OUString& rResourceURL ) const
|
|
{
|
|
uno::Reference< ::graphic::XGraphic > xRet;
|
|
sal_Int32 nIndex = 0;
|
|
|
|
if( ( 0 == rResourceURL.getToken( 0, '/', nIndex ).compareToAscii( "private:graphicrepository" ) ) )
|
|
{
|
|
String sPathName( rResourceURL.copy( nIndex ) );
|
|
BitmapEx aBitmap;
|
|
if ( ::vcl::ImageRepository::loadImage( sPathName, aBitmap, false ) )
|
|
{
|
|
Image aImage( aBitmap );
|
|
xRet = aImage.GetXGraphic();
|
|
}
|
|
}
|
|
return xRet;
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------------------------------
|
|
|
|
uno::Reference< ::graphic::XGraphic > GraphicProvider::implLoadStandardImage( const ::rtl::OUString& rResourceURL ) const
|
|
{
|
|
uno::Reference< ::graphic::XGraphic > xRet;
|
|
sal_Int32 nIndex = 0;
|
|
|
|
if( ( 0 == rResourceURL.getToken( 0, '/', nIndex ).compareToAscii( "private:standardimage" ) ) )
|
|
{
|
|
rtl::OUString sImageName( rResourceURL.copy( nIndex ) );
|
|
if ( sImageName == "info" )
|
|
{
|
|
xRet = InfoBox::GetStandardImage().GetXGraphic();
|
|
}
|
|
else if ( sImageName == "warning" )
|
|
{
|
|
xRet = WarningBox::GetStandardImage().GetXGraphic();
|
|
}
|
|
else if ( sImageName == "error" )
|
|
{
|
|
xRet = ErrorBox::GetStandardImage().GetXGraphic();
|
|
}
|
|
else if ( sImageName == "query" )
|
|
{
|
|
xRet = QueryBox::GetStandardImage().GetXGraphic();
|
|
}
|
|
}
|
|
return xRet;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------
|
|
|
|
uno::Reference< ::graphic::XGraphic > GraphicProvider::implLoadBitmap( const uno::Reference< awt::XBitmap >& xBtm ) const
|
|
{
|
|
uno::Reference< ::graphic::XGraphic > xRet;
|
|
uno::Sequence< sal_Int8 > aBmpSeq( xBtm->getDIB() );
|
|
uno::Sequence< sal_Int8 > aMaskSeq( xBtm->getMaskDIB() );
|
|
SvMemoryStream aBmpStream( aBmpSeq.getArray(), aBmpSeq.getLength(), STREAM_READ );
|
|
Bitmap aBmp;
|
|
aBmpStream >> aBmp;
|
|
|
|
BitmapEx aBmpEx;
|
|
|
|
if( aMaskSeq.getLength() )
|
|
{
|
|
SvMemoryStream aMaskStream( aMaskSeq.getArray(), aMaskSeq.getLength(), STREAM_READ );
|
|
Bitmap aMask;
|
|
aMaskStream >> aMask;
|
|
aBmpEx = BitmapEx( aBmp, aMask );
|
|
}
|
|
else
|
|
aBmpEx = BitmapEx( aBmp );
|
|
|
|
if( !aBmpEx.IsEmpty() )
|
|
{
|
|
::unographic::Graphic* pUnoGraphic = new ::unographic::Graphic;
|
|
|
|
pUnoGraphic->init( aBmpEx );
|
|
xRet = pUnoGraphic;
|
|
}
|
|
return xRet;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------
|
|
|
|
uno::Reference< ::graphic::XGraphic > GraphicProvider::implLoadResource( const ::rtl::OUString& rResourceURL ) const
|
|
{
|
|
uno::Reference< ::graphic::XGraphic > xRet;
|
|
sal_Int32 nIndex = 0;
|
|
|
|
if( ( 0 == rResourceURL.getToken( 0, '/', nIndex ).compareToAscii( "private:resource" ) ) )
|
|
{
|
|
rtl::OString aResMgrName(rtl::OUStringToOString(
|
|
rResourceURL.getToken(0, '/', nIndex), RTL_TEXTENCODING_ASCII_US));
|
|
|
|
ResMgr* pResMgr = ResMgr::CreateResMgr( aResMgrName.getStr(), Application::GetSettings().GetUILocale() );
|
|
|
|
if( pResMgr )
|
|
{
|
|
const ::rtl::OUString aResourceType( rResourceURL.getToken( 0, '/', nIndex ) );
|
|
const ResId aResId( rResourceURL.getToken( 0, '/', nIndex ).toInt32(), *pResMgr );
|
|
|
|
if( !aResourceType.isEmpty() )
|
|
{
|
|
BitmapEx aBmpEx;
|
|
|
|
if( ( 0 == aResourceType.compareToAscii( "bitmap" ) ) ||
|
|
( 0 == aResourceType.compareToAscii( "bitmapex" ) ) )
|
|
{
|
|
aResId.SetRT( RSC_BITMAP );
|
|
|
|
if( pResMgr->IsAvailable( aResId ) )
|
|
{
|
|
aBmpEx = BitmapEx( aResId );
|
|
}
|
|
}
|
|
else if( 0 == aResourceType.compareToAscii( "image" ) )
|
|
{
|
|
aResId.SetRT( RSC_IMAGE );
|
|
|
|
if( pResMgr->IsAvailable( aResId ) )
|
|
{
|
|
const Image aImage( aResId );
|
|
aBmpEx = aImage.GetBitmapEx();
|
|
}
|
|
}
|
|
else if( 0 == aResourceType.compareToAscii( "imagelist" ) )
|
|
{
|
|
aResId.SetRT( RSC_IMAGELIST );
|
|
|
|
if( pResMgr->IsAvailable( aResId ) )
|
|
{
|
|
const ImageList aImageList( aResId );
|
|
sal_Int32 nImageId = ( nIndex > -1 ) ? rResourceURL.getToken( 0, '/', nIndex ).toInt32() : 0;
|
|
|
|
if( 0 < nImageId )
|
|
{
|
|
const Image aImage( aImageList.GetImage( sal::static_int_cast< sal_uInt16 >(nImageId) ) );
|
|
aBmpEx = aImage.GetBitmapEx();
|
|
}
|
|
else
|
|
{
|
|
aBmpEx = aImageList.GetAsHorizontalStrip();
|
|
}
|
|
}
|
|
}
|
|
|
|
if( !aBmpEx.IsEmpty() )
|
|
{
|
|
::unographic::Graphic* pUnoGraphic = new ::unographic::Graphic;
|
|
|
|
pUnoGraphic->init( aBmpEx );
|
|
xRet = pUnoGraphic;
|
|
}
|
|
}
|
|
|
|
delete pResMgr;
|
|
}
|
|
}
|
|
|
|
return xRet;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------
|
|
|
|
uno::Reference< beans::XPropertySet > SAL_CALL GraphicProvider::queryGraphicDescriptor( const uno::Sequence< beans::PropertyValue >& rMediaProperties )
|
|
throw ( io::IOException, lang::IllegalArgumentException, lang::WrappedTargetException, uno::RuntimeException)
|
|
{
|
|
uno::Reference< beans::XPropertySet > xRet;
|
|
|
|
::rtl::OUString aURL;
|
|
uno::Reference< io::XInputStream > xIStm;
|
|
uno::Reference< awt::XBitmap >xBtm;
|
|
|
|
for( sal_Int32 i = 0; ( i < rMediaProperties.getLength() ) && !xRet.is(); ++i )
|
|
{
|
|
const ::rtl::OUString aName( rMediaProperties[ i ].Name );
|
|
const uno::Any aValue( rMediaProperties[ i ].Value );
|
|
|
|
if( COMPARE_EQUAL == aName.compareToAscii( "URL" ) )
|
|
{
|
|
aValue >>= aURL;
|
|
}
|
|
else if( COMPARE_EQUAL == aName.compareToAscii( "InputStream" ) )
|
|
{
|
|
aValue >>= xIStm;
|
|
}
|
|
else if( COMPARE_EQUAL == aName.compareToAscii( "Bitmap" ) )
|
|
{
|
|
aValue >>= xBtm;
|
|
}
|
|
}
|
|
|
|
if( xIStm.is() )
|
|
{
|
|
GraphicDescriptor* pDescriptor = new GraphicDescriptor;
|
|
pDescriptor->init( xIStm, aURL );
|
|
xRet = pDescriptor;
|
|
}
|
|
else if( !aURL.isEmpty() )
|
|
{
|
|
uno::Reference< ::graphic::XGraphic > xGraphic( implLoadMemory( aURL ) );
|
|
if( !xGraphic.is() )
|
|
xGraphic = implLoadResource( aURL );
|
|
if( !xGraphic.is() )
|
|
xGraphic = implLoadGraphicObject( aURL );
|
|
|
|
if ( !xGraphic.is() )
|
|
xGraphic = implLoadRepositoryImage( aURL );
|
|
|
|
if ( !xGraphic.is() )
|
|
xGraphic = implLoadStandardImage( aURL );
|
|
|
|
if( xGraphic.is() )
|
|
{
|
|
xRet = uno::Reference< beans::XPropertySet >( xGraphic, uno::UNO_QUERY );
|
|
}
|
|
else
|
|
{
|
|
GraphicDescriptor* pDescriptor = new GraphicDescriptor;
|
|
pDescriptor->init( aURL );
|
|
xRet = pDescriptor;
|
|
}
|
|
}
|
|
else if( xBtm.is() )
|
|
{
|
|
uno::Reference< ::graphic::XGraphic > xGraphic( implLoadBitmap( xBtm ) );
|
|
if( xGraphic.is() )
|
|
xRet = uno::Reference< beans::XPropertySet >( xGraphic, uno::UNO_QUERY );
|
|
}
|
|
|
|
return xRet;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------
|
|
|
|
uno::Reference< ::graphic::XGraphic > SAL_CALL GraphicProvider::queryGraphic( const uno::Sequence< ::beans::PropertyValue >& rMediaProperties )
|
|
throw ( io::IOException, lang::IllegalArgumentException, lang::WrappedTargetException, uno::RuntimeException)
|
|
{
|
|
uno::Reference< ::graphic::XGraphic > xRet;
|
|
String aPath;
|
|
SvStream* pIStm = NULL;
|
|
|
|
uno::Reference< io::XInputStream > xIStm;
|
|
uno::Reference< awt::XBitmap >xBtm;
|
|
|
|
uno::Sequence< ::beans::PropertyValue > aFilterData;
|
|
|
|
for( sal_Int32 i = 0; ( i < rMediaProperties.getLength() ) && !pIStm && !xRet.is(); ++i )
|
|
{
|
|
const ::rtl::OUString aName( rMediaProperties[ i ].Name );
|
|
const uno::Any aValue( rMediaProperties[ i ].Value );
|
|
|
|
if( COMPARE_EQUAL == aName.compareToAscii( "URL" ) )
|
|
{
|
|
::rtl::OUString aURL;
|
|
aValue >>= aURL;
|
|
aPath = aURL;
|
|
}
|
|
else if( COMPARE_EQUAL == aName.compareToAscii( "InputStream" ) )
|
|
{
|
|
aValue >>= xIStm;
|
|
}
|
|
else if( COMPARE_EQUAL == aName.compareToAscii( "Bitmap" ) )
|
|
{
|
|
aValue >>= xBtm;
|
|
}
|
|
else if( COMPARE_EQUAL == aName.compareToAscii( "FilterData" ) )
|
|
{
|
|
aValue >>= aFilterData;
|
|
}
|
|
}
|
|
|
|
// Check for the goal width and height if they are defined
|
|
sal_uInt16 nExtWidth = 0;
|
|
sal_uInt16 nExtHeight = 0;
|
|
sal_uInt16 nExtMapMode = 0;
|
|
for( sal_Int32 i = 0; i < aFilterData.getLength(); ++i )
|
|
{
|
|
const ::rtl::OUString aName( aFilterData[ i ].Name );
|
|
const uno::Any aValue( aFilterData[ i ].Value );
|
|
|
|
if( COMPARE_EQUAL == aName.compareToAscii( "ExternalWidth" ) )
|
|
{
|
|
aValue >>= nExtWidth;
|
|
}
|
|
else if( COMPARE_EQUAL == aName.compareToAscii( "ExternalHeight" ) )
|
|
{
|
|
aValue >>= nExtHeight;
|
|
}
|
|
else if( COMPARE_EQUAL == aName.compareToAscii( "ExternalMapMode" ) )
|
|
{
|
|
aValue >>= nExtMapMode;
|
|
}
|
|
}
|
|
|
|
if( xIStm.is() )
|
|
{
|
|
pIStm = ::utl::UcbStreamHelper::CreateStream( xIStm );
|
|
}
|
|
else if( aPath.Len() )
|
|
{
|
|
xRet = implLoadMemory( aPath );
|
|
|
|
if( !xRet.is() )
|
|
xRet = implLoadGraphicObject( aPath );
|
|
|
|
if( !xRet.is() )
|
|
xRet = implLoadResource( aPath );
|
|
|
|
if ( !xRet.is() )
|
|
xRet = implLoadRepositoryImage( aPath );
|
|
|
|
if ( !xRet.is() )
|
|
xRet = implLoadStandardImage( aPath );
|
|
|
|
if( !xRet.is() )
|
|
pIStm = ::utl::UcbStreamHelper::CreateStream( aPath, STREAM_READ );
|
|
}
|
|
else if( xBtm.is() )
|
|
{
|
|
xRet = implLoadBitmap( xBtm );
|
|
}
|
|
|
|
if( pIStm )
|
|
{
|
|
::GraphicFilter& rFilter = ::GraphicFilter::GetGraphicFilter();
|
|
|
|
{
|
|
::Graphic aVCLGraphic;
|
|
|
|
// Define APM Header if goal height and width are defined
|
|
WMF_EXTERNALHEADER aExtHeader;
|
|
aExtHeader.xExt = nExtWidth;
|
|
aExtHeader.yExt = nExtHeight;
|
|
aExtHeader.mapMode = nExtMapMode;
|
|
WMF_EXTERNALHEADER *pExtHeader = NULL;
|
|
if ( nExtMapMode > 0 )
|
|
pExtHeader = &aExtHeader;
|
|
|
|
if( ( rFilter.ImportGraphic( aVCLGraphic, aPath, *pIStm,
|
|
GRFILTER_FORMAT_DONTKNOW, NULL, 0, pExtHeader ) == GRFILTER_OK ) &&
|
|
( aVCLGraphic.GetType() != GRAPHIC_NONE ) )
|
|
{
|
|
::unographic::Graphic* pUnoGraphic = new ::unographic::Graphic;
|
|
|
|
pUnoGraphic->init( aVCLGraphic );
|
|
xRet = pUnoGraphic;
|
|
}
|
|
}
|
|
|
|
delete pIStm;
|
|
}
|
|
|
|
return xRet;
|
|
}
|
|
|
|
void ImplCalculateCropRect( ::Graphic& rGraphic, const text::GraphicCrop& rGraphicCropLogic, Rectangle& rGraphicCropPixel )
|
|
{
|
|
if ( rGraphicCropLogic.Left || rGraphicCropLogic.Top || rGraphicCropLogic.Right || rGraphicCropLogic.Bottom )
|
|
{
|
|
Size aSourceSizePixel( rGraphic.GetSizePixel() );
|
|
if ( aSourceSizePixel.Width() && aSourceSizePixel.Height() )
|
|
{
|
|
if ( rGraphicCropLogic.Left || rGraphicCropLogic.Top || rGraphicCropLogic.Right || rGraphicCropLogic.Bottom )
|
|
{
|
|
Size aSize100thMM( 0, 0 );
|
|
if( rGraphic.GetPrefMapMode().GetMapUnit() != MAP_PIXEL )
|
|
{
|
|
aSize100thMM = OutputDevice::LogicToLogic( rGraphic.GetPrefSize(), rGraphic.GetPrefMapMode(), MAP_100TH_MM );
|
|
}
|
|
else
|
|
{
|
|
aSize100thMM = Application::GetDefaultDevice()->PixelToLogic( rGraphic.GetPrefSize(), MAP_100TH_MM );
|
|
}
|
|
if ( aSize100thMM.Width() && aSize100thMM.Height() )
|
|
{
|
|
double fSourceSizePixelWidth = static_cast<double>(aSourceSizePixel.Width());
|
|
double fSourceSizePixelHeight= static_cast<double>(aSourceSizePixel.Height());
|
|
rGraphicCropPixel.Left() = static_cast< sal_Int32 >((fSourceSizePixelWidth * rGraphicCropLogic.Left ) / aSize100thMM.Width());
|
|
rGraphicCropPixel.Top() = static_cast< sal_Int32 >((fSourceSizePixelHeight * rGraphicCropLogic.Top ) / aSize100thMM.Height());
|
|
rGraphicCropPixel.Right() = static_cast< sal_Int32 >(( fSourceSizePixelWidth * ( aSize100thMM.Width() - rGraphicCropLogic.Right ) ) / aSize100thMM.Width() );
|
|
rGraphicCropPixel.Bottom() = static_cast< sal_Int32 >(( fSourceSizePixelHeight * ( aSize100thMM.Height() - rGraphicCropLogic.Bottom ) ) / aSize100thMM.Height() );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void ImplApplyBitmapScaling( ::Graphic& rGraphic, sal_Int32 nPixelWidth, sal_Int32 nPixelHeight )
|
|
{
|
|
if ( nPixelWidth && nPixelHeight )
|
|
{
|
|
BitmapEx aBmpEx( rGraphic.GetBitmapEx() );
|
|
MapMode aPrefMapMode( aBmpEx.GetPrefMapMode() );
|
|
Size aPrefSize( aBmpEx.GetPrefSize() );
|
|
aBmpEx.Scale( Size( nPixelWidth, nPixelHeight ) );
|
|
aBmpEx.SetPrefMapMode( aPrefMapMode );
|
|
aBmpEx.SetPrefSize( aPrefSize );
|
|
rGraphic = aBmpEx;
|
|
}
|
|
}
|
|
|
|
void ImplApplyBitmapResolution( ::Graphic& rGraphic, sal_Int32 nImageResolution, const Size& rVisiblePixelSize, const awt::Size& rLogicalSize )
|
|
{
|
|
if ( nImageResolution && rLogicalSize.Width && rLogicalSize.Height )
|
|
{
|
|
const double fImageResolution = static_cast<double>( nImageResolution );
|
|
const double fSourceDPIX = ( static_cast<double>(rVisiblePixelSize.Width()) * 2540.0 ) / static_cast<double>(rLogicalSize.Width);
|
|
const double fSourceDPIY = ( static_cast<double>(rVisiblePixelSize.Height()) * 2540.0 ) / static_cast<double>(rLogicalSize.Height);
|
|
const sal_Int32 nSourcePixelWidth( rGraphic.GetSizePixel().Width() );
|
|
const sal_Int32 nSourcePixelHeight( rGraphic.GetSizePixel().Height() );
|
|
const double fSourcePixelWidth = static_cast<double>( nSourcePixelWidth );
|
|
const double fSourcePixelHeight= static_cast<double>( nSourcePixelHeight );
|
|
|
|
sal_Int32 nDestPixelWidth = nSourcePixelWidth;
|
|
sal_Int32 nDestPixelHeight = nSourcePixelHeight;
|
|
|
|
// check, if the bitmap DPI exceeds the maximum DPI
|
|
if( fSourceDPIX > fImageResolution )
|
|
{
|
|
nDestPixelWidth = static_cast<sal_Int32>(( fSourcePixelWidth * fImageResolution ) / fSourceDPIX);
|
|
if ( !nDestPixelWidth || ( nDestPixelWidth > nSourcePixelWidth ) )
|
|
nDestPixelWidth = nSourcePixelWidth;
|
|
}
|
|
if ( fSourceDPIY > fImageResolution )
|
|
{
|
|
nDestPixelHeight= static_cast<sal_Int32>(( fSourcePixelHeight* fImageResolution ) / fSourceDPIY);
|
|
if ( !nDestPixelHeight || ( nDestPixelHeight > nSourcePixelHeight ) )
|
|
nDestPixelHeight = nSourcePixelHeight;
|
|
}
|
|
if ( ( nDestPixelWidth != nSourcePixelWidth ) || ( nDestPixelHeight != nSourcePixelHeight ) )
|
|
ImplApplyBitmapScaling( rGraphic, nDestPixelWidth, nDestPixelHeight );
|
|
}
|
|
}
|
|
|
|
void ImplApplyFilterData( ::Graphic& rGraphic, uno::Sequence< beans::PropertyValue >& rFilterData )
|
|
{
|
|
/* this method applies following attributes to the graphic, in the first step the
|
|
cropping area (logical size in 100thmm) is applied, in the second step the resolution
|
|
is applied, in the third step the graphic is scaled to the corresponding pixelsize.
|
|
if a parameter value is zero or not available the corresponding step will be skipped */
|
|
|
|
sal_Int32 nPixelWidth = 0;
|
|
sal_Int32 nPixelHeight= 0;
|
|
sal_Int32 nImageResolution = 0;
|
|
awt::Size aLogicalSize( 0, 0 );
|
|
text::GraphicCrop aCropLogic( 0, 0, 0, 0 );
|
|
sal_Bool bRemoveCropArea = sal_True;
|
|
|
|
for( sal_Int32 i = 0; i < rFilterData.getLength(); ++i )
|
|
{
|
|
const ::rtl::OUString aName( rFilterData[ i ].Name );
|
|
const uno::Any aValue( rFilterData[ i ].Value );
|
|
|
|
if( COMPARE_EQUAL == aName.compareToAscii( "PixelWidth" ) )
|
|
aValue >>= nPixelWidth;
|
|
else if( COMPARE_EQUAL == aName.compareToAscii( "PixelHeight" ) )
|
|
aValue >>= nPixelHeight;
|
|
else if( COMPARE_EQUAL == aName.compareToAscii( "LogicalSize" ) )
|
|
aValue >>= aLogicalSize;
|
|
else if (COMPARE_EQUAL == aName.compareToAscii( "GraphicCropLogic" ) )
|
|
aValue >>= aCropLogic;
|
|
else if (COMPARE_EQUAL == aName.compareToAscii( "RemoveCropArea" ) )
|
|
aValue >>= bRemoveCropArea;
|
|
else if (COMPARE_EQUAL == aName.compareToAscii( "ImageResolution" ) )
|
|
aValue >>= nImageResolution;
|
|
}
|
|
if ( rGraphic.GetType() == GRAPHIC_BITMAP )
|
|
{
|
|
Rectangle aCropPixel( Point( 0, 0 ), rGraphic.GetSizePixel() );
|
|
ImplCalculateCropRect( rGraphic, aCropLogic, aCropPixel );
|
|
if ( bRemoveCropArea )
|
|
{
|
|
BitmapEx aBmpEx( rGraphic.GetBitmapEx() );
|
|
aBmpEx.Crop( aCropPixel );
|
|
rGraphic = aBmpEx;
|
|
}
|
|
Size aVisiblePixelSize( bRemoveCropArea ? rGraphic.GetSizePixel() : aCropPixel.GetSize() );
|
|
ImplApplyBitmapResolution( rGraphic, nImageResolution, aVisiblePixelSize, aLogicalSize );
|
|
ImplApplyBitmapScaling( rGraphic, nPixelWidth, nPixelHeight );
|
|
}
|
|
else if ( ( rGraphic.GetType() == GRAPHIC_GDIMETAFILE ) && nImageResolution )
|
|
{
|
|
VirtualDevice aDummyVDev;
|
|
GDIMetaFile aMtf( rGraphic.GetGDIMetaFile() );
|
|
Size aMtfSize( aDummyVDev.LogicToLogic( aMtf.GetPrefSize(), aMtf.GetPrefMapMode(), MAP_100TH_MM ) );
|
|
if ( aMtfSize.Width() && aMtfSize.Height() )
|
|
{
|
|
MapMode aNewMapMode( MAP_100TH_MM );
|
|
aNewMapMode.SetScaleX( static_cast< double >( aLogicalSize.Width ) / static_cast< double >( aMtfSize.Width() ) );
|
|
aNewMapMode.SetScaleY( static_cast< double >( aLogicalSize.Height ) / static_cast< double >( aMtfSize.Height() ) );
|
|
aDummyVDev.EnableOutput( sal_False );
|
|
aDummyVDev.SetMapMode( aNewMapMode );
|
|
|
|
for( size_t i = 0, nObjCount = aMtf.GetActionSize(); i < nObjCount; i++ )
|
|
{
|
|
MetaAction* pAction = aMtf.GetAction( i );
|
|
switch( pAction->GetType() )
|
|
{
|
|
// only optimizing common bitmap actions:
|
|
case( META_MAPMODE_ACTION ):
|
|
{
|
|
const_cast< MetaAction* >( pAction )->Execute( &aDummyVDev );
|
|
break;
|
|
}
|
|
case( META_PUSH_ACTION ):
|
|
{
|
|
const MetaPushAction* pA = (const MetaPushAction*)pAction;
|
|
aDummyVDev.Push( pA->GetFlags() );
|
|
break;
|
|
}
|
|
case( META_POP_ACTION ):
|
|
{
|
|
aDummyVDev.Pop();
|
|
break;
|
|
}
|
|
case( META_BMPSCALE_ACTION ):
|
|
case( META_BMPEXSCALE_ACTION ):
|
|
{
|
|
BitmapEx aBmpEx;
|
|
Point aPos;
|
|
Size aSize;
|
|
if ( pAction->GetType() == META_BMPSCALE_ACTION )
|
|
{
|
|
MetaBmpScaleAction* pScaleAction = dynamic_cast< MetaBmpScaleAction* >( pAction );
|
|
aBmpEx = pScaleAction->GetBitmap();
|
|
aPos = pScaleAction->GetPoint();
|
|
aSize = pScaleAction->GetSize();
|
|
}
|
|
else
|
|
{
|
|
MetaBmpExScaleAction* pScaleAction = dynamic_cast< MetaBmpExScaleAction* >( pAction );
|
|
aBmpEx = pScaleAction->GetBitmapEx();
|
|
aPos = pScaleAction->GetPoint();
|
|
aSize = pScaleAction->GetSize();
|
|
}
|
|
::Graphic aGraphic( aBmpEx );
|
|
const Size aSize100thmm( aDummyVDev.LogicToPixel( aSize ) );
|
|
Size aSize100thmm2( aDummyVDev.PixelToLogic( aSize100thmm, MAP_100TH_MM ) );
|
|
|
|
ImplApplyBitmapResolution( aGraphic, nImageResolution,
|
|
aGraphic.GetSizePixel(), awt::Size( aSize100thmm2.Width(), aSize100thmm2.Height() ) );
|
|
|
|
MetaAction* pNewAction;
|
|
if ( pAction->GetType() == META_BMPSCALE_ACTION )
|
|
pNewAction = new MetaBmpScaleAction ( aPos, aSize, aGraphic.GetBitmap() );
|
|
else
|
|
pNewAction = new MetaBmpExScaleAction( aPos, aSize, aGraphic.GetBitmapEx() );
|
|
|
|
aMtf.ReplaceAction( pNewAction, i );
|
|
pAction->Delete();
|
|
break;
|
|
}
|
|
default:
|
|
case( META_BMP_ACTION ):
|
|
case( META_BMPSCALEPART_ACTION ):
|
|
case( META_BMPEX_ACTION ):
|
|
case( META_BMPEXSCALEPART_ACTION ):
|
|
case( META_MASK_ACTION ):
|
|
case( META_MASKSCALE_ACTION ):
|
|
break;
|
|
}
|
|
}
|
|
rGraphic = aMtf;
|
|
}
|
|
}
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------
|
|
|
|
void SAL_CALL GraphicProvider::storeGraphic( const uno::Reference< ::graphic::XGraphic >& rxGraphic, const uno::Sequence< beans::PropertyValue >& rMediaProperties )
|
|
throw ( io::IOException, lang::IllegalArgumentException, lang::WrappedTargetException, uno::RuntimeException)
|
|
{
|
|
SvStream* pOStm = NULL;
|
|
String aPath;
|
|
sal_Int32 i;
|
|
|
|
for( i = 0; ( i < rMediaProperties.getLength() ) && !pOStm; ++i )
|
|
{
|
|
const ::rtl::OUString aName( rMediaProperties[ i ].Name );
|
|
const uno::Any aValue( rMediaProperties[ i ].Value );
|
|
|
|
if( COMPARE_EQUAL == aName.compareToAscii( "URL" ) )
|
|
{
|
|
::rtl::OUString aURL;
|
|
|
|
aValue >>= aURL;
|
|
pOStm = ::utl::UcbStreamHelper::CreateStream( aURL, STREAM_WRITE | STREAM_TRUNC );
|
|
aPath = aURL;
|
|
}
|
|
else if( COMPARE_EQUAL == aName.compareToAscii( "OutputStream" ) )
|
|
{
|
|
uno::Reference< io::XStream > xOStm;
|
|
|
|
aValue >>= xOStm;
|
|
|
|
if( xOStm.is() )
|
|
pOStm = ::utl::UcbStreamHelper::CreateStream( xOStm );
|
|
}
|
|
}
|
|
|
|
if( pOStm )
|
|
{
|
|
uno::Sequence< beans::PropertyValue > aFilterDataSeq;
|
|
const char* pFilterShortName = NULL;
|
|
|
|
for( i = 0; i < rMediaProperties.getLength(); ++i )
|
|
{
|
|
const ::rtl::OUString aName( rMediaProperties[ i ].Name );
|
|
const uno::Any aValue( rMediaProperties[ i ].Value );
|
|
|
|
if( COMPARE_EQUAL == aName.compareToAscii( "FilterData" ) )
|
|
{
|
|
aValue >>= aFilterDataSeq;
|
|
}
|
|
else if( COMPARE_EQUAL == aName.compareToAscii( "MimeType" ) )
|
|
{
|
|
::rtl::OUString aMimeType;
|
|
|
|
aValue >>= aMimeType;
|
|
|
|
if( COMPARE_EQUAL == aMimeType.compareToAscii( MIMETYPE_BMP ) )
|
|
pFilterShortName = "bmp";
|
|
else if( COMPARE_EQUAL == aMimeType.compareToAscii( MIMETYPE_EPS ) )
|
|
pFilterShortName = "eps";
|
|
else if( COMPARE_EQUAL == aMimeType.compareToAscii( MIMETYPE_GIF ) )
|
|
pFilterShortName = "gif";
|
|
else if( COMPARE_EQUAL == aMimeType.compareToAscii( MIMETYPE_JPG ) )
|
|
pFilterShortName = "jpg";
|
|
else if( COMPARE_EQUAL == aMimeType.compareToAscii( MIMETYPE_MET ) )
|
|
pFilterShortName = "met";
|
|
else if( COMPARE_EQUAL == aMimeType.compareToAscii( MIMETYPE_PNG ) )
|
|
pFilterShortName = "png";
|
|
else if( COMPARE_EQUAL == aMimeType.compareToAscii( MIMETYPE_PCT ) )
|
|
pFilterShortName = "pct";
|
|
else if( COMPARE_EQUAL == aMimeType.compareToAscii( MIMETYPE_PBM ) )
|
|
pFilterShortName = "pbm";
|
|
else if( COMPARE_EQUAL == aMimeType.compareToAscii( MIMETYPE_PGM ) )
|
|
pFilterShortName = "pgm";
|
|
else if( COMPARE_EQUAL == aMimeType.compareToAscii( MIMETYPE_PPM ) )
|
|
pFilterShortName = "ppm";
|
|
else if( COMPARE_EQUAL == aMimeType.compareToAscii( MIMETYPE_RAS ) )
|
|
pFilterShortName = "ras";
|
|
else if( COMPARE_EQUAL == aMimeType.compareToAscii( MIMETYPE_SVM ) )
|
|
pFilterShortName = "svm";
|
|
else if( COMPARE_EQUAL == aMimeType.compareToAscii( MIMETYPE_TIF ) )
|
|
pFilterShortName = "tif";
|
|
else if( COMPARE_EQUAL == aMimeType.compareToAscii( MIMETYPE_EMF ) )
|
|
pFilterShortName = "emf";
|
|
else if( COMPARE_EQUAL == aMimeType.compareToAscii( MIMETYPE_WMF ) )
|
|
pFilterShortName = "wmf";
|
|
else if( COMPARE_EQUAL == aMimeType.compareToAscii( MIMETYPE_XPM ) )
|
|
pFilterShortName = "xpm";
|
|
else if( COMPARE_EQUAL == aMimeType.compareToAscii( MIMETYPE_SVG ) )
|
|
pFilterShortName = "svg";
|
|
else if( COMPARE_EQUAL == aMimeType.compareToAscii( MIMETYPE_VCLGRAPHIC ) )
|
|
pFilterShortName = MIMETYPE_VCLGRAPHIC;
|
|
}
|
|
}
|
|
|
|
if( pFilterShortName )
|
|
{
|
|
::GraphicFilter& rFilter = ::GraphicFilter::GetGraphicFilter();
|
|
|
|
{
|
|
const uno::Reference< XInterface > xIFace( rxGraphic, uno::UNO_QUERY );
|
|
const ::Graphic* pGraphic = ::unographic::Graphic::getImplementation( xIFace );
|
|
|
|
if( pGraphic && ( pGraphic->GetType() != GRAPHIC_NONE ) )
|
|
{
|
|
::Graphic aGraphic( *pGraphic );
|
|
ImplApplyFilterData( aGraphic, aFilterDataSeq );
|
|
|
|
/* sj: using a temporary memory stream, because some graphic filters are seeking behind
|
|
stream end (which leads to an invalid argument exception then). */
|
|
SvMemoryStream aMemStrm;
|
|
aMemStrm.SetVersion( SOFFICE_FILEFORMAT_CURRENT );
|
|
if( 0 == strcmp( pFilterShortName, MIMETYPE_VCLGRAPHIC ) )
|
|
aMemStrm << aGraphic;
|
|
else
|
|
{
|
|
rFilter.ExportGraphic( aGraphic, aPath, aMemStrm,
|
|
rFilter.GetExportFormatNumberForShortName( ::rtl::OUString::createFromAscii( pFilterShortName ) ),
|
|
( aFilterDataSeq.getLength() ? &aFilterDataSeq : NULL ) );
|
|
}
|
|
aMemStrm.Seek( STREAM_SEEK_TO_END );
|
|
pOStm->Write( aMemStrm.GetData(), aMemStrm.Tell() );
|
|
}
|
|
}
|
|
}
|
|
delete pOStm;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|