summaryrefslogtreecommitdiff
path: root/vcl/source/gdi/rendergraphicrasterizer.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'vcl/source/gdi/rendergraphicrasterizer.cxx')
-rw-r--r--vcl/source/gdi/rendergraphicrasterizer.cxx400
1 files changed, 400 insertions, 0 deletions
diff --git a/vcl/source/gdi/rendergraphicrasterizer.cxx b/vcl/source/gdi/rendergraphicrasterizer.cxx
new file mode 100644
index 000000000000..29c9863335b3
--- /dev/null
+++ b/vcl/source/gdi/rendergraphicrasterizer.cxx
@@ -0,0 +1,400 @@
+/*************************************************************************
+ *
+ * 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 <vcl/rendergraphicrasterizer.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/wrkwin.hxx>
+#include <vcl/virdev.hxx>
+#include <vcl/unohelp.hxx>
+#include <vcl/bmpacc.hxx>
+#include <vcl/graph.hxx>
+#include <tools/stream.hxx>
+#include <comphelper/processfactory.hxx>
+#include <unotools/streamwrap.hxx>
+
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+
+#define VCL_SERVICENAME_RASTERIZER_SVG "com.sun.star.graphic.GraphicRasterizer_RSVG"
+
+using namespace com::sun::star;
+
+namespace vcl
+{
+// ---------------------------------------------------------
+// - maximum extent in pixel for graphics to be rasterized -
+// ---------------------------------------------------------
+
+static const sal_uInt32 nRasterizerDefaultExtent = 4096;
+
+// ---------------------------
+// - RenderGraphicRasterizer -
+// ---------------------------
+
+RenderGraphicRasterizer::RenderGraphicRasterizer( const RenderGraphic& rRenderGraphic ) :
+ maRenderGraphic( rRenderGraphic ),
+ mfRotateAngle( 0.0 ),
+ mfShearAngleX( 0.0 ),
+ mfShearAngleY( 0.0 )
+{
+}
+
+// -------------------------------------------------------------------------
+
+RenderGraphicRasterizer::RenderGraphicRasterizer( const RenderGraphicRasterizer& rRenderGraphicRasterizer ) :
+ maRenderGraphic( rRenderGraphicRasterizer.maRenderGraphic ),
+ mxRasterizer( rRenderGraphicRasterizer.mxRasterizer ),
+ maBitmapEx( rRenderGraphicRasterizer.maBitmapEx ),
+ maDefaultSizePixel( rRenderGraphicRasterizer.maDefaultSizePixel ),
+ mfRotateAngle( rRenderGraphicRasterizer.mfRotateAngle ),
+ mfShearAngleX( rRenderGraphicRasterizer.mfShearAngleX ),
+ mfShearAngleY( rRenderGraphicRasterizer.mfShearAngleY )
+{
+}
+
+// -------------------------------------------------------------------------
+
+RenderGraphicRasterizer::~RenderGraphicRasterizer()
+{
+}
+
+// -------------------------------------------------------------------------
+
+RenderGraphicRasterizer& RenderGraphicRasterizer::operator=(
+ const RenderGraphicRasterizer& rRenderGraphicRasterizer )
+{
+ maRenderGraphic = rRenderGraphicRasterizer.maRenderGraphic;
+ maBitmapEx = rRenderGraphicRasterizer.maBitmapEx;
+ maDefaultSizePixel = rRenderGraphicRasterizer.maDefaultSizePixel;
+ mfRotateAngle = rRenderGraphicRasterizer.mfRotateAngle;
+ mfShearAngleX = rRenderGraphicRasterizer.mfShearAngleX;
+ mfShearAngleY = rRenderGraphicRasterizer.mfShearAngleY;
+ mxRasterizer = rRenderGraphicRasterizer.mxRasterizer;
+
+ return( *this );
+}
+
+// -------------------------------------------------------------------------
+
+const Size& RenderGraphicRasterizer::GetDefaultSizePixel() const
+{
+ const_cast< RenderGraphicRasterizer* >( this )->InitializeRasterizer();
+
+ return( maDefaultSizePixel );
+}
+
+// -------------------------------------------------------------------------
+
+BitmapEx RenderGraphicRasterizer::GetReplacement() const
+{
+ BitmapEx aRet( Rasterize( GetDefaultSizePixel() ) );
+
+ aRet.SetPrefSize( GetPrefSize() );
+ aRet.SetPrefMapMode( GetPrefMapMode() );
+
+ return( aRet );
+}
+
+// -------------------------------------------------------------------------
+
+Size RenderGraphicRasterizer::GetPrefSize() const
+{
+ const Size aSizePixel( GetDefaultSizePixel() );
+ std::auto_ptr< VirtualDevice > apCompVDev;
+ OutputDevice* pCompDev = NULL;
+
+#ifndef NO_GETAPPWINDOW
+ pCompDev = Application::GetAppWindow();
+#endif
+
+ if( !pCompDev )
+ {
+ apCompVDev.reset( new VirtualDevice );
+ pCompDev = apCompVDev.get();
+ }
+
+ return( pCompDev->PixelToLogic( aSizePixel, GetPrefMapMode() ) );
+}
+
+// -------------------------------------------------------------------------
+
+MapMode RenderGraphicRasterizer::GetPrefMapMode() const
+{
+ return( MapMode( MAP_100TH_MM ) );
+}
+
+// -------------------------------------------------------------------------
+
+const BitmapEx& RenderGraphicRasterizer::Rasterize( const Size& rSizePixel,
+ double fRotateAngle,
+ double fShearAngleX,
+ double fShearAngleY,
+ sal_uInt32 nMaxExtent ) const
+{
+ const bool bRasterize = !maRenderGraphic.IsEmpty() &&
+ rSizePixel.Width() && rSizePixel.Height() &&
+ ( maBitmapEx.IsEmpty() ||
+ ( rSizePixel != maBitmapEx.GetSizePixel() ) ||
+ ( fRotateAngle != mfRotateAngle ) ||
+ ( fShearAngleX != mfShearAngleX ) ||
+ ( fShearAngleY != mfShearAngleY ) );
+
+ if( bRasterize )
+ {
+ const_cast< RenderGraphicRasterizer* >( this )->InitializeRasterizer();
+
+ if( mxRasterizer.is() )
+ {
+ sal_uInt32 nWidth = labs( rSizePixel.Width() );
+ sal_uInt32 nHeight = labs( rSizePixel.Height() );
+
+ // limiting the extent of the rastered bitmap
+ if( VCL_RASTERIZER_UNLIMITED_EXTENT != nMaxExtent )
+ {
+ if( VCL_RASTERIZER_DEFAULT_EXTENT == nMaxExtent )
+ {
+ nMaxExtent = nRasterizerDefaultExtent;
+ }
+
+ if( ( nWidth > nMaxExtent ) || ( nHeight > nMaxExtent ) )
+ {
+ const double fScale = static_cast< double >( nMaxExtent ) / ::std::max( nWidth, nHeight );
+
+ nWidth = FRound( nWidth * fScale );
+ nHeight = FRound( nHeight * fScale );
+ }
+ }
+
+ if( !ImplRasterizeFromCache( const_cast< RenderGraphicRasterizer& >( *this ),
+ Size( nWidth, nHeight ), fRotateAngle, fShearAngleX, fShearAngleY ) )
+ {
+ try
+ {
+ const uno::Sequence< beans::PropertyValue > aPropertySeq;
+ const Graphic aRasteredGraphic( mxRasterizer->rasterize( nWidth,
+ nHeight,
+ fRotateAngle,
+ fShearAngleX,
+ fShearAngleY,
+ aPropertySeq ) );
+
+ maBitmapEx = aRasteredGraphic.GetBitmapEx();
+ mfRotateAngle = fRotateAngle;
+ mfShearAngleX = fShearAngleX;
+ mfShearAngleY = fShearAngleY;
+
+ ImplUpdateCache( *this );
+
+// OSL_TRACE( "Wanted: %d x %d / Got: %d x %d", rSizePixel.Width(), rSizePixel.Height(), maBitmapEx.GetSizePixel().Width(), maBitmapEx.GetSizePixel().Height() );
+ }
+ catch( ... )
+ {
+ OSL_TRACE( "caught exception during rasterization" );
+ }
+ }
+ }
+ }
+
+ return( maBitmapEx );
+}
+
+// -------------------------------------------------------------------------
+
+void RenderGraphicRasterizer::InitializeRasterizer()
+{
+ if( !mxRasterizer.is() && !ImplInitializeFromCache( *this ) )
+ {
+ uno::Reference< lang::XMultiServiceFactory > xFactory( ::comphelper::getProcessServiceFactory() );
+
+ maDefaultSizePixel.Width() = maDefaultSizePixel.Height() = 0;
+
+ if( !maRenderGraphic.IsEmpty() )
+ {
+ rtl::OUString aServiceName;
+
+ if( 0 == maRenderGraphic.GetGraphicDataMimeType().compareToAscii( "image/svg+xml" ) )
+ {
+ aServiceName = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( VCL_SERVICENAME_RASTERIZER_SVG ) );
+ }
+
+ if( aServiceName.getLength() )
+ {
+ mxRasterizer.set( xFactory->createInstance( aServiceName ), uno::UNO_QUERY );
+
+ if( mxRasterizer.is() )
+ {
+ std::auto_ptr< VirtualDevice > apCompVDev;
+ OutputDevice* pCompDev = NULL;
+
+#ifndef NO_GETAPPWINDOW
+ pCompDev = Application::GetAppWindow();
+#endif
+
+ if( !pCompDev )
+ {
+ apCompVDev.reset( new VirtualDevice );
+ pCompDev = apCompVDev.get();
+ }
+
+ const Size aDPI( pCompDev->LogicToPixel( Size( 1, 1 ), MAP_INCH ) );
+ awt::Size aSizePixel;
+ SvMemoryStream aMemStm( maRenderGraphic.GetGraphicData().get(),
+ maRenderGraphic.GetGraphicDataLength(),
+ STREAM_READ );
+
+ uno::Reference< io::XInputStream > xIStm( new utl::OSeekableInputStreamWrapper( aMemStm ) );
+
+ try
+ {
+ if( !xIStm.is() || !mxRasterizer->initializeData( xIStm, aDPI.Width(), aDPI.Height(), aSizePixel ) )
+ {
+ mxRasterizer.clear();
+ }
+ else
+ {
+ maDefaultSizePixel.Width() = aSizePixel.Width;
+ maDefaultSizePixel.Height() = aSizePixel.Height;
+ }
+ }
+ catch( ... )
+ {
+ OSL_TRACE( "caught exception during initialization of SVG rasterizer component" );
+ mxRasterizer.clear();
+ }
+ }
+ }
+ }
+ }
+}
+
+// ------------------------------------------------------------------------------
+
+RenderGraphicRasterizer::RenderGraphicRasterizerCache& RenderGraphicRasterizer::ImplGetCache()
+{
+ static RenderGraphicRasterizerCache* pCache = NULL;
+
+ if( !pCache )
+ {
+ pCache = new RenderGraphicRasterizerCache;
+ }
+
+ return( *pCache );
+}
+
+// ------------------------------------------------------------------------------
+
+bool RenderGraphicRasterizer::ImplInitializeFromCache( RenderGraphicRasterizer& rRasterizer )
+{
+ RenderGraphicRasterizerCache& rCache = ImplGetCache();
+ bool bRet = false;
+
+ for( sal_uInt32 i = 0; i < rCache.size(); ++i )
+ {
+ const RenderGraphicRasterizer* pCheck = &rCache[ i ];
+
+ if( pCheck && pCheck->mxRasterizer.is() && ( pCheck->maRenderGraphic == rRasterizer.maRenderGraphic ) )
+ {
+// OSL_TRACE( "Hit RenderGraphicRasterizer cache for initialization" );
+
+ rRasterizer.mxRasterizer = pCheck->mxRasterizer;
+ rRasterizer.maDefaultSizePixel = pCheck->maDefaultSizePixel;
+
+ // put found Rasterizer at begin of deque
+ const RenderGraphicRasterizer aFound( rCache[ i ] );
+
+ rCache.erase( rCache.begin() + i );
+ rCache.push_front( aFound );
+
+
+ bRet = true;
+ }
+ }
+
+ return( bRet );
+}
+
+// ------------------------------------------------------------------------------
+
+bool RenderGraphicRasterizer::ImplRasterizeFromCache( RenderGraphicRasterizer& rRasterizer,
+ const Size& rSizePixel,
+ double fRotateAngle,
+ double fShearAngleX,
+ double fShearAngleY )
+{
+ RenderGraphicRasterizerCache& rCache = ImplGetCache();
+ bool bRet = false;
+
+ for( sal_uInt32 i = 0; i < rCache.size(); ++i )
+ {
+ const RenderGraphicRasterizer& rCheck = rCache[ i ];
+
+ if( rCheck.mxRasterizer.is() && rRasterizer.mxRasterizer.is() &&
+ ( ( rCheck.mxRasterizer == rRasterizer.mxRasterizer ) ||
+ ( rRasterizer.maRenderGraphic == rCheck.maRenderGraphic ) ) &&
+ ( rCheck.maBitmapEx.GetSizePixel() == rSizePixel ) &&
+ ( rCheck.mfRotateAngle == fRotateAngle ) &&
+ ( rCheck.mfShearAngleX == fShearAngleX ) &&
+ ( rCheck.mfShearAngleY == fShearAngleY ) )
+ {
+// OSL_TRACE( "Hit RenderGraphicRasterizer cache for rasterizing" );
+
+ rRasterizer.maBitmapEx = rCheck.maBitmapEx;
+ rRasterizer.mfRotateAngle = fRotateAngle;
+ rRasterizer.mfShearAngleX = fShearAngleX;
+ rRasterizer.mfShearAngleY = fShearAngleY;
+
+ // put found Rasterizer at begin of deque
+ const RenderGraphicRasterizer aFound( rCache[ i ] );
+
+ rCache.erase( rCache.begin() + i );
+ rCache.push_front( aFound );
+
+ bRet = true;
+ }
+ }
+
+ return( bRet );
+}
+
+// ------------------------------------------------------------------------------
+
+void RenderGraphicRasterizer::ImplUpdateCache( const RenderGraphicRasterizer& rRasterizer )
+{
+ RenderGraphicRasterizerCache& rCache = ImplGetCache();
+ const sal_uInt32 nMaxCacheSize = 8;
+
+ if( rCache.size() < nMaxCacheSize )
+ {
+ rCache.push_front( rRasterizer );
+ }
+ else
+ {
+ rCache.pop_back();
+ rCache.push_front( rRasterizer );
+ }
+}
+
+} // VCL