bump product version to 4.1.6.2
[LibreOffice.git] / forms / source / component / imgprod.cxx
blobf2d7273585a0303784339206606c29775e544502
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 .
21 #include "imgprod.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 <com/sun/star/io/XInputStream.hpp>
30 #include "svtools/imageresourceaccess.hxx"
31 #include <comphelper/processfactory.hxx>
33 // --------------------
34 // - ImgProdLockBytes -
35 // --------------------
37 class ImgProdLockBytes : public SvLockBytes
39 ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > xStmRef;
40 ::com::sun::star::uno::Sequence<sal_Int8> maSeq;
42 ImgProdLockBytes() {};
44 public:
46 ImgProdLockBytes( SvStream* pStm, sal_Bool bOwner );
47 ImgProdLockBytes( ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > & rStreamRef );
48 virtual ~ImgProdLockBytes();
50 virtual ErrCode ReadAt( sal_Size nPos, void* pBuffer, sal_Size nCount, sal_Size* pRead ) const;
51 virtual ErrCode WriteAt( sal_Size nPos, const void* pBuffer, sal_Size nCount, sal_Size* pWritten );
52 virtual ErrCode Flush() const;
53 virtual ErrCode SetSize( sal_Size nSize );
54 virtual ErrCode Stat( SvLockBytesStat*, SvLockBytesStatFlag ) const;
57 // ------------------------------------------------------------------------
59 ImgProdLockBytes::ImgProdLockBytes( SvStream* pStm, sal_Bool bOwner ) :
60 SvLockBytes( pStm, bOwner )
64 // ------------------------------------------------------------------------
66 ImgProdLockBytes::ImgProdLockBytes( ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > & rStmRef ) :
67 xStmRef( rStmRef )
69 if( xStmRef.is() )
71 const sal_uInt32 nBytesToRead = 65535;
72 sal_uInt32 nRead;
76 ::com::sun::star::uno::Sequence< sal_Int8 > aReadSeq;
78 nRead = xStmRef->readSomeBytes( aReadSeq, nBytesToRead );
80 if( nRead )
82 const sal_uInt32 nOldLength = maSeq.getLength();
83 maSeq.realloc( nOldLength + nRead );
84 memcpy( maSeq.getArray() + nOldLength, aReadSeq.getConstArray(), aReadSeq.getLength() );
87 while( nBytesToRead == nRead );
91 // ------------------------------------------------------------------------
93 ImgProdLockBytes::~ImgProdLockBytes()
97 // ------------------------------------------------------------------------
99 ErrCode ImgProdLockBytes::ReadAt( sal_Size nPos, void* pBuffer, sal_Size nCount, sal_Size* pRead ) const
101 if( GetStream() )
103 ( (SvStream*) GetStream() )->ResetError();
104 const ErrCode nErr = SvLockBytes::ReadAt( nPos, pBuffer, nCount, pRead );
105 ( (SvStream*) GetStream() )->ResetError();
106 return nErr;
108 else
110 const sal_Size nSeqLen = maSeq.getLength();
111 ErrCode nErr = ERRCODE_NONE;
113 if( nPos < nSeqLen )
115 if( ( nPos + nCount ) > nSeqLen )
116 nCount = nSeqLen - nPos;
118 memcpy( pBuffer, maSeq.getConstArray() + nPos, nCount );
119 *pRead = nCount;
121 else
122 *pRead = 0UL;
124 return nErr;
128 // ------------------------------------------------------------------------
130 ErrCode ImgProdLockBytes::WriteAt( sal_Size nPos, const void* pBuffer, sal_Size nCount, sal_Size* pWritten )
132 if( GetStream() )
133 return SvLockBytes::WriteAt( nPos, pBuffer, nCount, pWritten );
134 else
136 DBG_ASSERT( xStmRef.is(), "ImgProdLockBytes::WriteAt: xInputStream has no reference..." );
137 return ERRCODE_IO_CANTWRITE;
141 // ------------------------------------------------------------------------
143 ErrCode ImgProdLockBytes::Flush() const
145 return ERRCODE_NONE;
148 // ------------------------------------------------------------------------
150 ErrCode ImgProdLockBytes::SetSize( sal_Size nSize )
152 if( GetStream() )
153 return SvLockBytes::SetSize( nSize );
154 else
156 OSL_FAIL( "ImgProdLockBytes::SetSize not supported for xInputStream..." );
157 return ERRCODE_IO_CANTWRITE;
161 // ------------------------------------------------------------------------
163 ErrCode ImgProdLockBytes::Stat( SvLockBytesStat* pStat, SvLockBytesStatFlag eFlag ) const
165 if( GetStream() )
166 return SvLockBytes::Stat( pStat, eFlag );
167 else
169 DBG_ASSERT( xStmRef.is(), "ImgProdLockBytes::Stat: xInputStream has no reference..." );
170 pStat->nSize = maSeq.getLength();
171 return ERRCODE_NONE;
175 // -----------------
176 // - ImageProducer -
177 // -----------------
179 ImageProducer::ImageProducer() :
180 mpStm ( NULL ),
181 mbConsInit ( sal_False )
183 mpGraphic = new Graphic;
186 // ------------------------------------------------------------
188 ImageProducer::~ImageProducer()
190 delete mpGraphic;
191 mpGraphic = NULL;
193 delete mpStm;
194 mpStm = NULL;
197 // ------------------------------------------------------------
199 // ::com::sun::star::uno::XInterface
200 ::com::sun::star::uno::Any ImageProducer::queryInterface( const ::com::sun::star::uno::Type & rType ) throw(::com::sun::star::uno::RuntimeException)
202 ::com::sun::star::uno::Any aRet = ::cppu::queryInterface( rType,
203 (static_cast< ::com::sun::star::lang::XInitialization* >(this)),
204 (static_cast< ::com::sun::star::awt::XImageProducer* >(this)) );
205 return (aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType ));
208 // ------------------------------------------------------------
210 void ImageProducer::addConsumer( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageConsumer >& rxConsumer ) throw(::com::sun::star::uno::RuntimeException)
212 DBG_ASSERT( rxConsumer.is(), "::AddConsumer(...): No consumer referenced!" );
213 if( rxConsumer.is() )
214 maConsList.push_back( new ::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageConsumer > ( rxConsumer ));
217 // ------------------------------------------------------------
219 void ImageProducer::removeConsumer( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageConsumer >& rxConsumer ) throw(::com::sun::star::uno::RuntimeException)
221 ConsumerList_t::reverse_iterator riter = std::find(maConsList.rbegin(),maConsList.rend(),rxConsumer);
223 if (riter != maConsList.rend())
224 maConsList.erase(riter.base()-1);
227 // ------------------------------------------------------------
229 void ImageProducer::SetImage( const OUString& rPath )
231 maURL = rPath;
232 mpGraphic->Clear();
233 mbConsInit = sal_False;
234 delete mpStm;
236 if ( ::svt::GraphicAccess::isSupportedURL( maURL ) )
238 mpStm = ::svt::GraphicAccess::getImageStream( ::comphelper::getProcessComponentContext(), maURL );
240 else if( !maURL.isEmpty() )
242 SvStream* pIStm = ::utl::UcbStreamHelper::CreateStream( maURL, STREAM_STD_READ );
243 mpStm = pIStm ? new SvStream( new ImgProdLockBytes( pIStm, sal_True ) ) : NULL;
245 else
246 mpStm = NULL;
249 // ------------------------------------------------------------
251 void ImageProducer::SetImage( SvStream& rStm )
253 maURL = OUString();
254 mpGraphic->Clear();
255 mbConsInit = sal_False;
257 delete mpStm;
258 mpStm = new SvStream( new ImgProdLockBytes( &rStm, sal_False ) );
261 // ------------------------------------------------------------
263 void ImageProducer::setImage( ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > & rInputStmRef )
265 maURL = OUString();
266 mpGraphic->Clear();
267 mbConsInit = sal_False;
268 delete mpStm;
270 if( rInputStmRef.is() )
271 mpStm = new SvStream( new ImgProdLockBytes( rInputStmRef ) );
272 else
273 mpStm = NULL;
276 // ------------------------------------------------------------
278 void ImageProducer::NewDataAvailable()
280 if( ( GRAPHIC_NONE == mpGraphic->GetType() ) || mpGraphic->GetContext() )
281 startProduction();
284 // ------------------------------------------------------------
286 void ImageProducer::startProduction() throw(::com::sun::star::uno::RuntimeException)
288 if( !maConsList.empty() || maDoneHdl.IsSet() )
290 bool bNotifyEmptyGraphics = false;
292 // valid stream or filled graphic? => update consumers
293 if( mpStm || ( mpGraphic->GetType() != GRAPHIC_NONE ) )
295 // if we already have a graphic, we don't have to import again;
296 // graphic is cleared if a new Stream is set
297 if( ( mpGraphic->GetType() == GRAPHIC_NONE ) || mpGraphic->GetContext() )
299 if ( ImplImportGraphic( *mpGraphic ) && maDoneHdl.IsSet() )
300 maDoneHdl.Call( mpGraphic );
303 if( mpGraphic->GetType() != GRAPHIC_NONE )
304 ImplUpdateData( *mpGraphic );
305 else
306 bNotifyEmptyGraphics = true;
308 else
309 bNotifyEmptyGraphics = true;
311 if ( bNotifyEmptyGraphics )
313 // reset image
314 // create temporary list to hold interfaces
315 ConsumerList_t aTmp = maConsList;
317 // iterate through interfaces
318 for( ConsumerList_t::iterator iter = aTmp.begin(); iter != aTmp.end(); ++iter )
320 (*iter)->init( 0, 0 );
321 (*iter)->complete( ::com::sun::star::awt::ImageStatus::IMAGESTATUS_STATICIMAGEDONE, this );
324 if ( maDoneHdl.IsSet() )
325 maDoneHdl.Call( NULL );
330 // ------------------------------------------------------------
332 sal_Bool ImageProducer::ImplImportGraphic( Graphic& rGraphic )
334 if( ERRCODE_IO_PENDING == mpStm->GetError() )
335 mpStm->ResetError();
337 mpStm->Seek( 0UL );
339 sal_Bool bRet = GraphicConverter::Import( *mpStm, rGraphic ) == ERRCODE_NONE;
341 if( ERRCODE_IO_PENDING == mpStm->GetError() )
342 mpStm->ResetError();
344 return bRet;
347 // ------------------------------------------------------------
349 void ImageProducer::ImplUpdateData( const Graphic& rGraphic )
351 ImplInitConsumer( rGraphic );
353 if( mbConsInit && !maConsList.empty() )
355 // create temporary list to hold interfaces
356 ConsumerList_t aTmp = maConsList;
358 ImplUpdateConsumer( rGraphic );
359 mbConsInit = sal_False;
361 // iterate through interfaces
362 for( ConsumerList_t::iterator iter = aTmp.begin(); iter != aTmp.end(); ++iter )
363 (*iter)->complete( ::com::sun::star::awt::ImageStatus::IMAGESTATUS_STATICIMAGEDONE, this );
367 // ------------------------------------------------------------
369 void ImageProducer::ImplInitConsumer( const Graphic& rGraphic )
371 Bitmap aBmp( rGraphic.GetBitmapEx().GetBitmap() );
372 BitmapReadAccess* pBmpAcc = aBmp.AcquireReadAccess();
374 if( pBmpAcc )
376 sal_uInt16 nPalCount = 0;
377 sal_uInt32 nRMask = 0;
378 sal_uInt32 nGMask = 0;
379 sal_uInt32 nBMask = 0;
380 sal_uInt32 nAMask = 0;
381 ::com::sun::star::uno::Sequence< sal_Int32 > aRGBPal;
383 if( pBmpAcc->HasPalette() )
385 nPalCount = pBmpAcc->GetPaletteEntryCount();
387 if( nPalCount )
389 aRGBPal = ::com::sun::star::uno::Sequence< sal_Int32 >( nPalCount + 1 );
391 sal_Int32* pTmp = aRGBPal.getArray();
393 for( sal_uInt32 i = 0; i < nPalCount; i++, pTmp++ )
395 const BitmapColor& rCol = pBmpAcc->GetPaletteColor( (sal_uInt16) i );
397 *pTmp = ( (sal_Int32) rCol.GetRed() ) << (sal_Int32)(24L);
398 *pTmp |= ( (sal_Int32) rCol.GetGreen() ) << (sal_Int32)(16L);
399 *pTmp |= ( (sal_Int32) rCol.GetBlue() ) << (sal_Int32)(8L);
400 *pTmp |= (sal_Int32)(0x000000ffL);
403 if( rGraphic.IsTransparent() )
405 // append transparent entry
406 *pTmp = (sal_Int32)(0xffffff00L);
407 mnTransIndex = nPalCount;
408 nPalCount++;
410 else
411 mnTransIndex = 0;
415 else
417 nRMask = 0xff000000UL;
418 nGMask = 0x00ff0000UL;
419 nBMask = 0x0000ff00UL;
420 nAMask = 0x000000ffUL;
423 // create temporary list to hold interfaces
424 ConsumerList_t aTmp = maConsList;
426 // iterate through interfaces
427 for( ConsumerList_t::iterator iter = aTmp.begin(); iter != aTmp.end(); ++iter)
429 (*iter)->init( pBmpAcc->Width(), pBmpAcc->Height() );
430 (*iter)->setColorModel( pBmpAcc->GetBitCount(),aRGBPal, nRMask, nGMask, nBMask, nAMask );
433 aBmp.ReleaseAccess( pBmpAcc );
434 mbConsInit = sal_True;
438 // ------------------------------------------------------------
440 void ImageProducer::ImplUpdateConsumer( const Graphic& rGraphic )
442 BitmapEx aBmpEx( rGraphic.GetBitmapEx() );
443 Bitmap aBmp( aBmpEx.GetBitmap() );
444 BitmapReadAccess* pBmpAcc = aBmp.AcquireReadAccess();
446 if( pBmpAcc )
448 Bitmap aMask( aBmpEx.GetMask() );
449 BitmapReadAccess* pMskAcc = !!aMask ? aMask.AcquireReadAccess() : NULL;
450 const long nWidth = pBmpAcc->Width();
451 const long nHeight = pBmpAcc->Height();
452 const long nStartX = 0L;
453 const long nEndX = nWidth - 1L;
454 const long nStartY = 0L;
455 const long nEndY = nHeight - 1L;
456 const long nPartWidth = nEndX - nStartX + 1;
457 const long nPartHeight = nEndY - nStartY + 1;
459 if( !pMskAcc )
461 aMask = Bitmap( aBmp.GetSizePixel(), 1 );
462 aMask.Erase( COL_BLACK );
463 pMskAcc = aMask.AcquireReadAccess();
466 // create temporary list to hold interfaces
467 ConsumerList_t aTmp = maConsList;
469 if( pBmpAcc->HasPalette() )
471 const BitmapColor aWhite( pMskAcc->GetBestMatchingColor( Color( COL_WHITE ) ) );
473 if( mnTransIndex < 256 )
475 ::com::sun::star::uno::Sequence<sal_Int8> aData( nPartWidth * nPartHeight );
476 sal_Int8* pTmp = aData.getArray();
478 for( long nY = nStartY; nY <= nEndY; nY++ )
480 for( long nX = nStartX; nX <= nEndX; nX++ )
482 if( pMskAcc->GetPixel( nY, nX ) == aWhite )
483 *pTmp++ = sal::static_int_cast< sal_Int8 >(
484 mnTransIndex );
485 else
486 *pTmp++ = pBmpAcc->GetPixel( nY, nX ).GetIndex();
490 // iterate through interfaces
491 for (ConsumerList_t::iterator iter = aTmp.begin(); iter != aTmp.end(); ++iter)
492 (*iter)->setPixelsByBytes( nStartX, nStartY, nPartWidth, nPartHeight, aData, 0UL, nPartWidth );
494 else
496 ::com::sun::star::uno::Sequence<sal_Int32> aData( nPartWidth * nPartHeight );
497 sal_Int32* pTmp = aData.getArray();
499 for( long nY = nStartY; nY <= nEndY; nY++ )
501 for( long nX = nStartX; nX <= nEndX; nX++ )
503 if( pMskAcc->GetPixel( nY, nX ) == aWhite )
504 *pTmp++ = mnTransIndex;
505 else
506 *pTmp++ = pBmpAcc->GetPixel( nY, nX ).GetIndex();
510 // iterate through interfaces
511 for (ConsumerList_t::iterator iter = aTmp.begin(); iter != aTmp.end(); ++iter)
512 (*iter)->setPixelsByLongs( nStartX, nStartY, nPartWidth, nPartHeight, aData, 0UL, nPartWidth );
515 else
517 ::com::sun::star::uno::Sequence<sal_Int32> aData( nPartWidth * nPartHeight );
518 const BitmapColor aWhite( pMskAcc->GetBestMatchingColor( Color( COL_WHITE ) ) );
519 sal_Int32* pTmp = aData.getArray();
521 for( long nY = nStartY; nY <= nEndY; nY++ )
523 for( long nX = nStartX; nX <= nEndX; nX++, pTmp++ )
525 const BitmapColor aCol( pBmpAcc->GetPixel( nY, nX ) );
527 *pTmp = ( (sal_Int32) aCol.GetRed() ) << (sal_Int32)(24L);
528 *pTmp |= ( (sal_Int32) aCol.GetGreen() ) << (sal_Int32)(16L);
529 *pTmp |= ( (sal_Int32) aCol.GetBlue() ) << (sal_Int32)(8L);
531 if( pMskAcc->GetPixel( nY, nX ) != aWhite )
532 *pTmp |= 0x000000ffUL;
536 // iterate through interfaces
537 for (ConsumerList_t::iterator iter = aTmp.begin(); iter != aTmp.end(); ++iter)
538 (*iter)->setPixelsByLongs( nStartX, nStartY, nPartWidth, nPartHeight, aData, 0UL, nPartWidth );
541 aBmp.ReleaseAccess( pBmpAcc );
542 aMask.ReleaseAccess( pMskAcc );
546 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)
548 if ( aArguments.getLength() == 1 )
550 ::com::sun::star::uno::Any aArg = aArguments.getConstArray()[0];
551 OUString aURL;
552 if ( aArg >>= aURL )
554 SetImage( aURL );
559 namespace frm
561 ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >
562 SAL_CALL ImageProducer_CreateInstance(
563 const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& )
565 return ::com::sun::star::uno::Reference < ::com::sun::star::uno::XInterface >(
566 ( ::cppu::OWeakObject* ) new ImageProducer );
568 } // namespace frm
570 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */