bump product version to 5.0.4.1
[LibreOffice.git] / forms / source / component / imgprod.cxx
blob913a0a7476787672afe75af163fc14fc545d3244
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "imgprod.hxx"
21 #include "services.hxx"
23 #include <vcl/bmpacc.hxx>
24 #include <vcl/cvtgrf.hxx>
25 #include <vcl/svapp.hxx>
26 #include <unotools/ucbstreamhelper.hxx>
27 #include <vcl/graphicfilter.hxx>
28 #include <cppuhelper/queryinterface.hxx>
29 #include <com/sun/star/io/XInputStream.hpp>
30 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
32 #include "svtools/imageresourceaccess.hxx"
33 #include <comphelper/processfactory.hxx>
35 // - ImgProdLockBytes -
38 class ImgProdLockBytes : public SvLockBytes
40 ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > xStmRef;
41 ::com::sun::star::uno::Sequence<sal_Int8> maSeq;
43 public:
45 ImgProdLockBytes( SvStream* pStm, bool bOwner );
46 ImgProdLockBytes( ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > & rStreamRef );
47 virtual ~ImgProdLockBytes();
49 virtual ErrCode ReadAt( sal_uInt64 nPos, void* pBuffer, sal_Size nCount, sal_Size * pRead ) const SAL_OVERRIDE;
50 virtual ErrCode WriteAt( sal_uInt64 nPos, const void* pBuffer, sal_Size nCount, sal_Size * pWritten ) SAL_OVERRIDE;
51 virtual ErrCode Flush() const SAL_OVERRIDE;
52 virtual ErrCode SetSize( sal_uInt64 nSize ) SAL_OVERRIDE;
53 virtual ErrCode Stat( SvLockBytesStat*, SvLockBytesStatFlag ) const SAL_OVERRIDE;
58 ImgProdLockBytes::ImgProdLockBytes( SvStream* pStm, bool bOwner ) :
59 SvLockBytes( pStm, bOwner )
65 ImgProdLockBytes::ImgProdLockBytes( ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > & rStmRef ) :
66 xStmRef( rStmRef )
68 if( xStmRef.is() )
70 const sal_uInt32 nBytesToRead = 65535;
71 sal_uInt32 nRead;
75 ::com::sun::star::uno::Sequence< sal_Int8 > aReadSeq;
77 nRead = xStmRef->readSomeBytes( aReadSeq, nBytesToRead );
79 if( nRead )
81 const sal_uInt32 nOldLength = maSeq.getLength();
82 maSeq.realloc( nOldLength + nRead );
83 memcpy( maSeq.getArray() + nOldLength, aReadSeq.getConstArray(), aReadSeq.getLength() );
86 while( nBytesToRead == nRead );
92 ImgProdLockBytes::~ImgProdLockBytes()
96 ErrCode ImgProdLockBytes::ReadAt(sal_uInt64 const nPos,
97 void* pBuffer, sal_Size nCount, sal_Size * pRead) const
99 if( GetStream() )
101 const_cast<SvStream*>(GetStream())->ResetError();
102 const ErrCode nErr = SvLockBytes::ReadAt( nPos, pBuffer, nCount, pRead );
103 const_cast<SvStream*>(GetStream())->ResetError();
104 return nErr;
106 else
108 const sal_Size nSeqLen = maSeq.getLength();
109 ErrCode nErr = ERRCODE_NONE;
111 if( nPos < nSeqLen )
113 if( ( nPos + nCount ) > nSeqLen )
114 nCount = nSeqLen - nPos;
116 memcpy( pBuffer, maSeq.getConstArray() + nPos, nCount );
117 *pRead = nCount;
119 else
120 *pRead = 0UL;
122 return nErr;
126 ErrCode ImgProdLockBytes::WriteAt(sal_uInt64 const nPos,
127 const void* pBuffer, sal_Size nCount, sal_Size * pWritten)
129 if( GetStream() )
130 return SvLockBytes::WriteAt( nPos, pBuffer, nCount, pWritten );
131 else
133 DBG_ASSERT( xStmRef.is(), "ImgProdLockBytes::WriteAt: xInputStream has no reference..." );
134 return ERRCODE_IO_CANTWRITE;
140 ErrCode ImgProdLockBytes::Flush() const
142 return ERRCODE_NONE;
147 ErrCode ImgProdLockBytes::SetSize(sal_uInt64 const nSize)
149 if( GetStream() )
150 return SvLockBytes::SetSize( nSize );
151 else
153 OSL_FAIL( "ImgProdLockBytes::SetSize not supported for xInputStream..." );
154 return ERRCODE_IO_CANTWRITE;
160 ErrCode ImgProdLockBytes::Stat( SvLockBytesStat* pStat, SvLockBytesStatFlag eFlag ) const
162 if( GetStream() )
163 return SvLockBytes::Stat( pStat, eFlag );
164 else
166 DBG_ASSERT( xStmRef.is(), "ImgProdLockBytes::Stat: xInputStream has no reference..." );
167 pStat->nSize = maSeq.getLength();
168 return ERRCODE_NONE;
172 // - ImageProducer -
173 ImageProducer::ImageProducer()
174 : mpStm(NULL)
175 , mnTransIndex(0)
176 , mbConsInit(false)
178 mpGraphic = new Graphic;
181 ImageProducer::~ImageProducer()
183 delete mpGraphic;
184 mpGraphic = NULL;
186 delete mpStm;
187 mpStm = NULL;
190 // ::com::sun::star::uno::XInterface
191 ::com::sun::star::uno::Any ImageProducer::queryInterface( const ::com::sun::star::uno::Type & rType ) throw(::com::sun::star::uno::RuntimeException, std::exception)
193 ::com::sun::star::uno::Any aRet = ::cppu::queryInterface( rType,
194 (static_cast< ::com::sun::star::lang::XInitialization* >(this)),
195 (static_cast< ::com::sun::star::awt::XImageProducer* >(this)) );
196 return (aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType ));
201 void ImageProducer::addConsumer( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageConsumer >& rxConsumer )
202 throw(::com::sun::star::uno::RuntimeException,
203 std::exception)
205 DBG_ASSERT( rxConsumer.is(), "::AddConsumer(...): No consumer referenced!" );
206 if( rxConsumer.is() )
207 maConsList.push_back( new ::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageConsumer > ( rxConsumer ));
212 void ImageProducer::removeConsumer( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageConsumer >& rxConsumer ) throw(::com::sun::star::uno::RuntimeException, std::exception)
214 ConsumerList_t::reverse_iterator riter = std::find(maConsList.rbegin(),maConsList.rend(),rxConsumer);
216 if (riter != maConsList.rend())
217 maConsList.erase(riter.base()-1);
222 void ImageProducer::SetImage( const OUString& rPath )
224 maURL = rPath;
225 mpGraphic->Clear();
226 mbConsInit = false;
227 delete mpStm;
229 if ( ::svt::GraphicAccess::isSupportedURL( maURL ) )
231 mpStm = ::svt::GraphicAccess::getImageStream( ::comphelper::getProcessComponentContext(), maURL );
233 else if( !maURL.isEmpty() )
235 SvStream* pIStm = ::utl::UcbStreamHelper::CreateStream( maURL, STREAM_STD_READ );
236 mpStm = pIStm ? new SvStream( new ImgProdLockBytes( pIStm, true ) ) : NULL;
238 else
239 mpStm = NULL;
244 void ImageProducer::SetImage( SvStream& rStm )
246 maURL.clear();
247 mpGraphic->Clear();
248 mbConsInit = false;
250 delete mpStm;
251 mpStm = new SvStream( new ImgProdLockBytes( &rStm, false ) );
256 void ImageProducer::setImage( ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > & rInputStmRef )
258 maURL.clear();
259 mpGraphic->Clear();
260 mbConsInit = false;
261 delete mpStm;
263 if( rInputStmRef.is() )
264 mpStm = new SvStream( new ImgProdLockBytes( rInputStmRef ) );
265 else
266 mpStm = NULL;
271 void ImageProducer::NewDataAvailable()
273 if( ( GRAPHIC_NONE == mpGraphic->GetType() ) || mpGraphic->GetContext() )
274 startProduction();
279 void ImageProducer::startProduction() throw(::com::sun::star::uno::RuntimeException, std::exception)
281 if( !maConsList.empty() || maDoneHdl.IsSet() )
283 bool bNotifyEmptyGraphics = false;
285 // valid stream or filled graphic? => update consumers
286 if( mpStm || ( mpGraphic->GetType() != GRAPHIC_NONE ) )
288 // if we already have a graphic, we don't have to import again;
289 // graphic is cleared if a new Stream is set
290 if( ( mpGraphic->GetType() == GRAPHIC_NONE ) || mpGraphic->GetContext() )
292 if ( ImplImportGraphic( *mpGraphic ) && maDoneHdl.IsSet() )
293 maDoneHdl.Call( mpGraphic );
296 if( mpGraphic->GetType() != GRAPHIC_NONE )
297 ImplUpdateData( *mpGraphic );
298 else
299 bNotifyEmptyGraphics = true;
301 else
302 bNotifyEmptyGraphics = true;
304 if ( bNotifyEmptyGraphics )
306 // reset image
307 // create temporary list to hold interfaces
308 ConsumerList_t aTmp = maConsList;
310 // iterate through interfaces
311 for( ConsumerList_t::iterator iter = aTmp.begin(); iter != aTmp.end(); ++iter )
313 (*iter)->init( 0, 0 );
314 (*iter)->complete( ::com::sun::star::awt::ImageStatus::IMAGESTATUS_STATICIMAGEDONE, this );
317 if ( maDoneHdl.IsSet() )
318 maDoneHdl.Call( NULL );
325 bool ImageProducer::ImplImportGraphic( Graphic& rGraphic )
327 if (!mpStm)
328 return false;
330 if( ERRCODE_IO_PENDING == mpStm->GetError() )
331 mpStm->ResetError();
333 mpStm->Seek( 0UL );
335 bool bRet = GraphicConverter::Import( *mpStm, rGraphic ) == ERRCODE_NONE;
337 if( ERRCODE_IO_PENDING == mpStm->GetError() )
338 mpStm->ResetError();
340 return bRet;
345 void ImageProducer::ImplUpdateData( const Graphic& rGraphic )
347 ImplInitConsumer( rGraphic );
349 if( mbConsInit && !maConsList.empty() )
351 // create temporary list to hold interfaces
352 ConsumerList_t aTmp = maConsList;
354 ImplUpdateConsumer( rGraphic );
355 mbConsInit = false;
357 // iterate through interfaces
358 for( ConsumerList_t::iterator iter = aTmp.begin(); iter != aTmp.end(); ++iter )
359 (*iter)->complete( ::com::sun::star::awt::ImageStatus::IMAGESTATUS_STATICIMAGEDONE, this );
365 void ImageProducer::ImplInitConsumer( const Graphic& rGraphic )
367 Bitmap aBmp( rGraphic.GetBitmapEx().GetBitmap() );
368 BitmapReadAccess* pBmpAcc = aBmp.AcquireReadAccess();
370 if( pBmpAcc )
372 sal_uInt16 nPalCount = 0;
373 sal_uInt32 nRMask = 0;
374 sal_uInt32 nGMask = 0;
375 sal_uInt32 nBMask = 0;
376 sal_uInt32 nAMask = 0;
377 ::com::sun::star::uno::Sequence< sal_Int32 > aRGBPal;
379 if( pBmpAcc->HasPalette() )
381 nPalCount = pBmpAcc->GetPaletteEntryCount();
383 if( nPalCount )
385 aRGBPal = ::com::sun::star::uno::Sequence< sal_Int32 >( nPalCount + 1 );
387 sal_Int32* pTmp = aRGBPal.getArray();
389 for( sal_uInt32 i = 0; i < nPalCount; i++, pTmp++ )
391 const BitmapColor& rCol = pBmpAcc->GetPaletteColor( (sal_uInt16) i );
393 *pTmp = ( (sal_Int32) rCol.GetRed() ) << (sal_Int32)(24L);
394 *pTmp |= ( (sal_Int32) rCol.GetGreen() ) << (sal_Int32)(16L);
395 *pTmp |= ( (sal_Int32) rCol.GetBlue() ) << (sal_Int32)(8L);
396 *pTmp |= (sal_Int32)(0x000000ffL);
399 if( rGraphic.IsTransparent() )
401 // append transparent entry
402 *pTmp = (sal_Int32)(0xffffff00L);
403 mnTransIndex = nPalCount;
404 nPalCount++;
406 else
407 mnTransIndex = 0;
411 else
413 nRMask = 0xff000000UL;
414 nGMask = 0x00ff0000UL;
415 nBMask = 0x0000ff00UL;
416 nAMask = 0x000000ffUL;
419 // create temporary list to hold interfaces
420 ConsumerList_t aTmp = maConsList;
422 // iterate through interfaces
423 for( ConsumerList_t::iterator iter = aTmp.begin(); iter != aTmp.end(); ++iter)
425 (*iter)->init( pBmpAcc->Width(), pBmpAcc->Height() );
426 (*iter)->setColorModel( pBmpAcc->GetBitCount(),aRGBPal, nRMask, nGMask, nBMask, nAMask );
429 Bitmap::ReleaseAccess( pBmpAcc );
430 mbConsInit = true;
436 void ImageProducer::ImplUpdateConsumer( const Graphic& rGraphic )
438 BitmapEx aBmpEx( rGraphic.GetBitmapEx() );
439 Bitmap aBmp( aBmpEx.GetBitmap() );
440 BitmapReadAccess* pBmpAcc = aBmp.AcquireReadAccess();
442 if( pBmpAcc )
444 Bitmap aMask( aBmpEx.GetMask() );
445 BitmapReadAccess* pMskAcc = !!aMask ? aMask.AcquireReadAccess() : NULL;
446 const long nWidth = pBmpAcc->Width();
447 const long nHeight = pBmpAcc->Height();
448 const long nStartX = 0L;
449 const long nEndX = nWidth - 1L;
450 const long nStartY = 0L;
451 const long nEndY = nHeight - 1L;
452 const long nPartWidth = nEndX - nStartX + 1;
453 const long nPartHeight = nEndY - nStartY + 1;
455 if( !pMskAcc )
457 aMask = Bitmap( aBmp.GetSizePixel(), 1 );
458 aMask.Erase( COL_BLACK );
459 pMskAcc = aMask.AcquireReadAccess();
462 // create temporary list to hold interfaces
463 ConsumerList_t aTmp = maConsList;
465 if( pBmpAcc->HasPalette() )
467 const BitmapColor aWhite( pMskAcc->GetBestMatchingColor( Color( COL_WHITE ) ) );
469 if( mnTransIndex < 256 )
471 ::com::sun::star::uno::Sequence<sal_Int8> aData( nPartWidth * nPartHeight );
472 sal_Int8* pTmp = aData.getArray();
474 for( long nY = nStartY; nY <= nEndY; nY++ )
476 for( long nX = nStartX; nX <= nEndX; nX++ )
478 if( pMskAcc->GetPixel( nY, nX ) == aWhite )
479 *pTmp++ = sal::static_int_cast< sal_Int8 >(
480 mnTransIndex );
481 else
482 *pTmp++ = pBmpAcc->GetPixel( nY, nX ).GetIndex();
486 // iterate through interfaces
487 for (ConsumerList_t::iterator iter = aTmp.begin(); iter != aTmp.end(); ++iter)
488 (*iter)->setPixelsByBytes( nStartX, nStartY, nPartWidth, nPartHeight, aData, 0UL, nPartWidth );
490 else
492 ::com::sun::star::uno::Sequence<sal_Int32> aData( nPartWidth * nPartHeight );
493 sal_Int32* pTmp = aData.getArray();
495 for( long nY = nStartY; nY <= nEndY; nY++ )
497 for( long nX = nStartX; nX <= nEndX; nX++ )
499 if( pMskAcc->GetPixel( nY, nX ) == aWhite )
500 *pTmp++ = mnTransIndex;
501 else
502 *pTmp++ = pBmpAcc->GetPixel( nY, nX ).GetIndex();
506 // iterate through interfaces
507 for (ConsumerList_t::iterator iter = aTmp.begin(); iter != aTmp.end(); ++iter)
508 (*iter)->setPixelsByLongs( nStartX, nStartY, nPartWidth, nPartHeight, aData, 0UL, nPartWidth );
511 else
513 ::com::sun::star::uno::Sequence<sal_Int32> aData( nPartWidth * nPartHeight );
514 const BitmapColor aWhite( pMskAcc->GetBestMatchingColor( Color( COL_WHITE ) ) );
515 sal_Int32* pTmp = aData.getArray();
517 for( long nY = nStartY; nY <= nEndY; nY++ )
519 for( long nX = nStartX; nX <= nEndX; nX++, pTmp++ )
521 const BitmapColor aCol( pBmpAcc->GetPixel( nY, nX ) );
523 *pTmp = ( (sal_Int32) aCol.GetRed() ) << (sal_Int32)(24L);
524 *pTmp |= ( (sal_Int32) aCol.GetGreen() ) << (sal_Int32)(16L);
525 *pTmp |= ( (sal_Int32) aCol.GetBlue() ) << (sal_Int32)(8L);
527 if( pMskAcc->GetPixel( nY, nX ) != aWhite )
528 *pTmp |= 0x000000ffUL;
532 // iterate through interfaces
533 for (ConsumerList_t::iterator iter = aTmp.begin(); iter != aTmp.end(); ++iter)
534 (*iter)->setPixelsByLongs( nStartX, nStartY, nPartWidth, nPartHeight, aData, 0UL, nPartWidth );
537 Bitmap::ReleaseAccess( pBmpAcc );
538 Bitmap::ReleaseAccess( pMskAcc );
542 void ImageProducer::initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments ) throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException, std::exception)
544 if ( aArguments.getLength() == 1 )
546 ::com::sun::star::uno::Any aArg = aArguments.getConstArray()[0];
547 OUString aURL;
548 if ( aArg >>= aURL )
550 SetImage( aURL );
555 extern "C" SAL_DLLPUBLIC_EXPORT ::com::sun::star::uno::XInterface* SAL_CALL
556 com_sun_star_form_ImageProducer_get_implementation(::com::sun::star::uno::XComponentContext*,
557 ::com::sun::star::uno::Sequence<css::uno::Any> const &)
559 return cppu::acquire(new ImageProducer());
562 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */