Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 :
21 : #include "imgprod.hxx"
22 :
23 : #include <vcl/bmpacc.hxx>
24 : #include <vcl/cvtgrf.hxx>
25 : #include <vcl/svapp.hxx>
26 : #include <unotools/ucbstreamhelper.hxx>
27 : #include <svtools/filter.hxx>
28 : #include <com/sun/star/io/XInputStream.hpp>
29 :
30 : #include "svtools/imageresourceaccess.hxx"
31 : #include <comphelper/processfactory.hxx>
32 :
33 : // --------------------
34 : // - ImgProdLockBytes -
35 : // --------------------
36 :
37 : class ImgProdLockBytes : public SvLockBytes
38 : {
39 : ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > xStmRef;
40 : ::com::sun::star::uno::Sequence<sal_Int8> maSeq;
41 :
42 : ImgProdLockBytes() {};
43 :
44 : public:
45 :
46 : ImgProdLockBytes( SvStream* pStm, sal_Bool bOwner );
47 : ImgProdLockBytes( ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > & rStreamRef );
48 : virtual ~ImgProdLockBytes();
49 :
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;
55 : };
56 :
57 : // ------------------------------------------------------------------------
58 :
59 0 : ImgProdLockBytes::ImgProdLockBytes( SvStream* pStm, sal_Bool bOwner ) :
60 0 : SvLockBytes( pStm, bOwner )
61 : {
62 0 : }
63 :
64 : // ------------------------------------------------------------------------
65 :
66 0 : ImgProdLockBytes::ImgProdLockBytes( ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > & rStmRef ) :
67 0 : xStmRef( rStmRef )
68 : {
69 0 : if( xStmRef.is() )
70 : {
71 0 : const sal_uInt32 nBytesToRead = 65535;
72 : sal_uInt32 nRead;
73 :
74 0 : do
75 : {
76 0 : ::com::sun::star::uno::Sequence< sal_Int8 > aReadSeq;
77 :
78 0 : nRead = xStmRef->readSomeBytes( aReadSeq, nBytesToRead );
79 :
80 0 : if( nRead )
81 : {
82 0 : const sal_uInt32 nOldLength = maSeq.getLength();
83 0 : maSeq.realloc( nOldLength + nRead );
84 0 : memcpy( maSeq.getArray() + nOldLength, aReadSeq.getConstArray(), aReadSeq.getLength() );
85 0 : }
86 : }
87 : while( nBytesToRead == nRead );
88 : }
89 0 : }
90 :
91 : // ------------------------------------------------------------------------
92 :
93 0 : ImgProdLockBytes::~ImgProdLockBytes()
94 : {
95 0 : }
96 :
97 : // ------------------------------------------------------------------------
98 :
99 0 : ErrCode ImgProdLockBytes::ReadAt( sal_Size nPos, void* pBuffer, sal_Size nCount, sal_Size* pRead ) const
100 : {
101 0 : if( GetStream() )
102 : {
103 0 : ( (SvStream*) GetStream() )->ResetError();
104 0 : const ErrCode nErr = SvLockBytes::ReadAt( nPos, pBuffer, nCount, pRead );
105 0 : ( (SvStream*) GetStream() )->ResetError();
106 0 : return nErr;
107 : }
108 : else
109 : {
110 0 : const sal_Size nSeqLen = maSeq.getLength();
111 0 : ErrCode nErr = ERRCODE_NONE;
112 :
113 0 : if( nPos < nSeqLen )
114 : {
115 0 : if( ( nPos + nCount ) > nSeqLen )
116 0 : nCount = nSeqLen - nPos;
117 :
118 0 : memcpy( pBuffer, maSeq.getConstArray() + nPos, nCount );
119 0 : *pRead = nCount;
120 : }
121 : else
122 0 : *pRead = 0UL;
123 :
124 0 : return nErr;
125 : }
126 : }
127 :
128 : // ------------------------------------------------------------------------
129 :
130 0 : ErrCode ImgProdLockBytes::WriteAt( sal_Size nPos, const void* pBuffer, sal_Size nCount, sal_Size* pWritten )
131 : {
132 0 : if( GetStream() )
133 0 : return SvLockBytes::WriteAt( nPos, pBuffer, nCount, pWritten );
134 : else
135 : {
136 : DBG_ASSERT( xStmRef.is(), "ImgProdLockBytes::WriteAt: xInputStream has no reference..." );
137 0 : return ERRCODE_IO_CANTWRITE;
138 : }
139 : }
140 :
141 : // ------------------------------------------------------------------------
142 :
143 0 : ErrCode ImgProdLockBytes::Flush() const
144 : {
145 0 : return ERRCODE_NONE;
146 : }
147 :
148 : // ------------------------------------------------------------------------
149 :
150 0 : ErrCode ImgProdLockBytes::SetSize( sal_Size nSize )
151 : {
152 0 : if( GetStream() )
153 0 : return SvLockBytes::SetSize( nSize );
154 : else
155 : {
156 : OSL_FAIL( "ImgProdLockBytes::SetSize not supported for xInputStream..." );
157 0 : return ERRCODE_IO_CANTWRITE;
158 : }
159 : }
160 :
161 : // ------------------------------------------------------------------------
162 :
163 0 : ErrCode ImgProdLockBytes::Stat( SvLockBytesStat* pStat, SvLockBytesStatFlag eFlag ) const
164 : {
165 0 : if( GetStream() )
166 0 : return SvLockBytes::Stat( pStat, eFlag );
167 : else
168 : {
169 : DBG_ASSERT( xStmRef.is(), "ImgProdLockBytes::Stat: xInputStream has no reference..." );
170 0 : pStat->nSize = maSeq.getLength();
171 0 : return ERRCODE_NONE;
172 : }
173 : }
174 :
175 : // -----------------
176 : // - ImageProducer -
177 : // -----------------
178 :
179 3 : ImageProducer::ImageProducer() :
180 : mpStm ( NULL ),
181 3 : mbConsInit ( sal_False )
182 : {
183 3 : mpGraphic = new Graphic;
184 : DBG_ASSERT( Application::GetFilterHdl().IsSet(), "ImageProducer::ImageProducer(): No filter handler set" );
185 3 : }
186 :
187 : // ------------------------------------------------------------
188 :
189 9 : ImageProducer::~ImageProducer()
190 : {
191 3 : delete mpGraphic;
192 3 : mpGraphic = NULL;
193 :
194 3 : delete mpStm;
195 3 : mpStm = NULL;
196 6 : }
197 :
198 : // ------------------------------------------------------------
199 :
200 : // ::com::sun::star::uno::XInterface
201 0 : ::com::sun::star::uno::Any ImageProducer::queryInterface( const ::com::sun::star::uno::Type & rType ) throw(::com::sun::star::uno::RuntimeException)
202 : {
203 : ::com::sun::star::uno::Any aRet = ::cppu::queryInterface( rType,
204 : (static_cast< ::com::sun::star::lang::XInitialization* >(this)),
205 0 : (static_cast< ::com::sun::star::awt::XImageProducer* >(this)) );
206 0 : return (aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType ));
207 : }
208 :
209 : // ------------------------------------------------------------
210 :
211 0 : void ImageProducer::addConsumer( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageConsumer >& rxConsumer ) throw(::com::sun::star::uno::RuntimeException)
212 : {
213 : DBG_ASSERT( rxConsumer.is(), "::AddConsumer(...): No consumer referenced!" );
214 0 : if( rxConsumer.is() )
215 0 : maConsList.push_back( new ::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageConsumer > ( rxConsumer ));
216 0 : }
217 :
218 : // ------------------------------------------------------------
219 :
220 0 : void ImageProducer::removeConsumer( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageConsumer >& rxConsumer ) throw(::com::sun::star::uno::RuntimeException)
221 : {
222 0 : ConsumerList_t::reverse_iterator riter = std::find(maConsList.rbegin(),maConsList.rend(),rxConsumer);
223 :
224 0 : if (riter != maConsList.rend())
225 0 : maConsList.erase(riter.base()-1);
226 0 : }
227 :
228 : // ------------------------------------------------------------
229 :
230 0 : void ImageProducer::SetImage( const ::rtl::OUString& rPath )
231 : {
232 0 : maURL = rPath;
233 0 : mpGraphic->Clear();
234 0 : mbConsInit = sal_False;
235 0 : delete mpStm;
236 :
237 0 : if ( ::svt::GraphicAccess::isSupportedURL( maURL ) )
238 : {
239 0 : mpStm = ::svt::GraphicAccess::getImageStream( ::comphelper::getProcessServiceFactory(), maURL );
240 : }
241 0 : else if( !maURL.isEmpty() )
242 : {
243 0 : SvStream* pIStm = ::utl::UcbStreamHelper::CreateStream( maURL, STREAM_STD_READ );
244 0 : mpStm = pIStm ? new SvStream( new ImgProdLockBytes( pIStm, sal_True ) ) : NULL;
245 : }
246 : else
247 0 : mpStm = NULL;
248 0 : }
249 :
250 : // ------------------------------------------------------------
251 :
252 0 : void ImageProducer::SetImage( SvStream& rStm )
253 : {
254 0 : maURL = ::rtl::OUString();
255 0 : mpGraphic->Clear();
256 0 : mbConsInit = sal_False;
257 :
258 0 : delete mpStm;
259 0 : mpStm = new SvStream( new ImgProdLockBytes( &rStm, sal_False ) );
260 0 : }
261 :
262 : // ------------------------------------------------------------
263 :
264 0 : void ImageProducer::setImage( ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > & rInputStmRef )
265 : {
266 0 : maURL = ::rtl::OUString();
267 0 : mpGraphic->Clear();
268 0 : mbConsInit = sal_False;
269 0 : delete mpStm;
270 :
271 0 : if( rInputStmRef.is() )
272 0 : mpStm = new SvStream( new ImgProdLockBytes( rInputStmRef ) );
273 : else
274 0 : mpStm = NULL;
275 0 : }
276 :
277 : // ------------------------------------------------------------
278 :
279 0 : void ImageProducer::NewDataAvailable()
280 : {
281 0 : if( ( GRAPHIC_NONE == mpGraphic->GetType() ) || mpGraphic->GetContext() )
282 0 : startProduction();
283 0 : }
284 :
285 : // ------------------------------------------------------------
286 :
287 0 : void ImageProducer::startProduction() throw(::com::sun::star::uno::RuntimeException)
288 : {
289 0 : if( !maConsList.empty() || maDoneHdl.IsSet() )
290 : {
291 0 : bool bNotifyEmptyGraphics = false;
292 :
293 : // valid stream or filled graphic? => update consumers
294 0 : if( mpStm || ( mpGraphic->GetType() != GRAPHIC_NONE ) )
295 : {
296 : // if we already have a graphic, we don't have to import again;
297 : // graphic is cleared if a new Stream is set
298 0 : if( ( mpGraphic->GetType() == GRAPHIC_NONE ) || mpGraphic->GetContext() )
299 : {
300 0 : if ( ImplImportGraphic( *mpGraphic ) && maDoneHdl.IsSet() )
301 0 : maDoneHdl.Call( mpGraphic );
302 : }
303 :
304 0 : if( mpGraphic->GetType() != GRAPHIC_NONE )
305 0 : ImplUpdateData( *mpGraphic );
306 : else
307 0 : bNotifyEmptyGraphics = true;
308 : }
309 : else
310 0 : bNotifyEmptyGraphics = true;
311 :
312 0 : if ( bNotifyEmptyGraphics )
313 : {
314 : // reset image
315 : // create temporary list to hold interfaces
316 0 : ConsumerList_t aTmp = maConsList;
317 :
318 : // iterate through interfaces
319 0 : for( ConsumerList_t::iterator iter = aTmp.begin(); iter != aTmp.end(); ++iter )
320 : {
321 0 : (*iter)->init( 0, 0 );
322 0 : (*iter)->complete( ::com::sun::star::awt::ImageStatus::IMAGESTATUS_STATICIMAGEDONE, this );
323 : }
324 :
325 0 : if ( maDoneHdl.IsSet() )
326 0 : maDoneHdl.Call( NULL );
327 : }
328 : }
329 0 : }
330 :
331 : // ------------------------------------------------------------
332 :
333 0 : sal_Bool ImageProducer::ImplImportGraphic( Graphic& rGraphic )
334 : {
335 0 : if( ERRCODE_IO_PENDING == mpStm->GetError() )
336 0 : mpStm->ResetError();
337 :
338 0 : mpStm->Seek( 0UL );
339 :
340 0 : sal_Bool bRet = GraphicConverter::Import( *mpStm, rGraphic ) == ERRCODE_NONE;
341 :
342 0 : if( ERRCODE_IO_PENDING == mpStm->GetError() )
343 0 : mpStm->ResetError();
344 :
345 0 : return bRet;
346 : }
347 :
348 : // ------------------------------------------------------------
349 :
350 0 : void ImageProducer::ImplUpdateData( const Graphic& rGraphic )
351 : {
352 0 : ImplInitConsumer( rGraphic );
353 :
354 0 : if( mbConsInit && !maConsList.empty() )
355 : {
356 : // create temporary list to hold interfaces
357 0 : ConsumerList_t aTmp = maConsList;
358 :
359 0 : ImplUpdateConsumer( rGraphic );
360 0 : mbConsInit = sal_False;
361 :
362 : // iterate through interfaces
363 0 : for( ConsumerList_t::iterator iter = aTmp.begin(); iter != aTmp.end(); ++iter )
364 0 : (*iter)->complete( ::com::sun::star::awt::ImageStatus::IMAGESTATUS_STATICIMAGEDONE, this );
365 : }
366 0 : }
367 :
368 : // ------------------------------------------------------------
369 :
370 0 : void ImageProducer::ImplInitConsumer( const Graphic& rGraphic )
371 : {
372 0 : Bitmap aBmp( rGraphic.GetBitmapEx().GetBitmap() );
373 0 : BitmapReadAccess* pBmpAcc = aBmp.AcquireReadAccess();
374 :
375 0 : if( pBmpAcc )
376 : {
377 0 : sal_uInt16 nPalCount = 0;
378 0 : sal_uInt32 nRMask = 0;
379 0 : sal_uInt32 nGMask = 0;
380 0 : sal_uInt32 nBMask = 0;
381 0 : sal_uInt32 nAMask = 0;
382 0 : ::com::sun::star::uno::Sequence< sal_Int32 > aRGBPal;
383 :
384 0 : if( pBmpAcc->HasPalette() )
385 : {
386 0 : nPalCount = pBmpAcc->GetPaletteEntryCount();
387 :
388 0 : if( nPalCount )
389 : {
390 0 : aRGBPal = ::com::sun::star::uno::Sequence< sal_Int32 >( nPalCount + 1 );
391 :
392 0 : sal_Int32* pTmp = aRGBPal.getArray();
393 :
394 0 : for( sal_uInt32 i = 0; i < nPalCount; i++, pTmp++ )
395 : {
396 0 : const BitmapColor& rCol = pBmpAcc->GetPaletteColor( (sal_uInt16) i );
397 :
398 0 : *pTmp = ( (sal_Int32) rCol.GetRed() ) << (sal_Int32)(24L);
399 0 : *pTmp |= ( (sal_Int32) rCol.GetGreen() ) << (sal_Int32)(16L);
400 0 : *pTmp |= ( (sal_Int32) rCol.GetBlue() ) << (sal_Int32)(8L);
401 0 : *pTmp |= (sal_Int32)(0x000000ffL);
402 : }
403 :
404 0 : if( rGraphic.IsTransparent() )
405 : {
406 : // append transparent entry
407 0 : *pTmp = (sal_Int32)(0xffffff00L);
408 0 : mnTransIndex = nPalCount;
409 0 : nPalCount++;
410 : }
411 : else
412 0 : mnTransIndex = 0;
413 :
414 : }
415 : }
416 : else
417 : {
418 0 : nRMask = 0xff000000UL;
419 0 : nGMask = 0x00ff0000UL;
420 0 : nBMask = 0x0000ff00UL;
421 0 : nAMask = 0x000000ffUL;
422 : }
423 :
424 : // create temporary list to hold interfaces
425 0 : ConsumerList_t aTmp = maConsList;
426 :
427 : // iterate through interfaces
428 0 : for( ConsumerList_t::iterator iter = aTmp.begin(); iter != aTmp.end(); ++iter)
429 : {
430 0 : (*iter)->init( pBmpAcc->Width(), pBmpAcc->Height() );
431 0 : (*iter)->setColorModel( pBmpAcc->GetBitCount(),aRGBPal, nRMask, nGMask, nBMask, nAMask );
432 : }
433 :
434 0 : aBmp.ReleaseAccess( pBmpAcc );
435 0 : mbConsInit = sal_True;
436 0 : }
437 0 : }
438 :
439 : // ------------------------------------------------------------
440 :
441 0 : void ImageProducer::ImplUpdateConsumer( const Graphic& rGraphic )
442 : {
443 0 : BitmapEx aBmpEx( rGraphic.GetBitmapEx() );
444 0 : Bitmap aBmp( aBmpEx.GetBitmap() );
445 0 : BitmapReadAccess* pBmpAcc = aBmp.AcquireReadAccess();
446 :
447 0 : if( pBmpAcc )
448 : {
449 0 : Bitmap aMask( aBmpEx.GetMask() );
450 0 : BitmapReadAccess* pMskAcc = !!aMask ? aMask.AcquireReadAccess() : NULL;
451 0 : const long nWidth = pBmpAcc->Width();
452 0 : const long nHeight = pBmpAcc->Height();
453 0 : const long nStartX = 0L;
454 0 : const long nEndX = nWidth - 1L;
455 0 : const long nStartY = 0L;
456 0 : const long nEndY = nHeight - 1L;
457 0 : const long nPartWidth = nEndX - nStartX + 1;
458 0 : const long nPartHeight = nEndY - nStartY + 1;
459 :
460 0 : if( !pMskAcc )
461 : {
462 0 : aMask = Bitmap( aBmp.GetSizePixel(), 1 );
463 0 : aMask.Erase( COL_BLACK );
464 0 : pMskAcc = aMask.AcquireReadAccess();
465 : }
466 :
467 : // create temporary list to hold interfaces
468 0 : ConsumerList_t aTmp = maConsList;
469 :
470 0 : if( pBmpAcc->HasPalette() )
471 : {
472 0 : const BitmapColor aWhite( pMskAcc->GetBestMatchingColor( Color( COL_WHITE ) ) );
473 :
474 0 : if( mnTransIndex < 256 )
475 : {
476 0 : ::com::sun::star::uno::Sequence<sal_Int8> aData( nPartWidth * nPartHeight );
477 0 : sal_Int8* pTmp = aData.getArray();
478 :
479 0 : for( long nY = nStartY; nY <= nEndY; nY++ )
480 : {
481 0 : for( long nX = nStartX; nX <= nEndX; nX++ )
482 : {
483 0 : if( pMskAcc->GetPixel( nY, nX ) == aWhite )
484 : *pTmp++ = sal::static_int_cast< sal_Int8 >(
485 0 : mnTransIndex );
486 : else
487 0 : *pTmp++ = pBmpAcc->GetPixel( nY, nX ).GetIndex();
488 : }
489 : }
490 :
491 : // iterate through interfaces
492 0 : for (ConsumerList_t::iterator iter = aTmp.begin(); iter != aTmp.end(); ++iter)
493 0 : (*iter)->setPixelsByBytes( nStartX, nStartY, nPartWidth, nPartHeight, aData, 0UL, nPartWidth );
494 : }
495 : else
496 : {
497 0 : ::com::sun::star::uno::Sequence<sal_Int32> aData( nPartWidth * nPartHeight );
498 0 : sal_Int32* pTmp = aData.getArray();
499 :
500 0 : for( long nY = nStartY; nY <= nEndY; nY++ )
501 : {
502 0 : for( long nX = nStartX; nX <= nEndX; nX++ )
503 : {
504 0 : if( pMskAcc->GetPixel( nY, nX ) == aWhite )
505 0 : *pTmp++ = mnTransIndex;
506 : else
507 0 : *pTmp++ = pBmpAcc->GetPixel( nY, nX ).GetIndex();
508 : }
509 : }
510 :
511 : // iterate through interfaces
512 0 : for (ConsumerList_t::iterator iter = aTmp.begin(); iter != aTmp.end(); ++iter)
513 0 : (*iter)->setPixelsByLongs( nStartX, nStartY, nPartWidth, nPartHeight, aData, 0UL, nPartWidth );
514 0 : }
515 : }
516 : else
517 : {
518 0 : ::com::sun::star::uno::Sequence<sal_Int32> aData( nPartWidth * nPartHeight );
519 0 : const BitmapColor aWhite( pMskAcc->GetBestMatchingColor( Color( COL_WHITE ) ) );
520 0 : sal_Int32* pTmp = aData.getArray();
521 :
522 0 : for( long nY = nStartY; nY <= nEndY; nY++ )
523 : {
524 0 : for( long nX = nStartX; nX <= nEndX; nX++, pTmp++ )
525 : {
526 0 : const BitmapColor aCol( pBmpAcc->GetPixel( nY, nX ) );
527 :
528 0 : *pTmp = ( (sal_Int32) aCol.GetRed() ) << (sal_Int32)(24L);
529 0 : *pTmp |= ( (sal_Int32) aCol.GetGreen() ) << (sal_Int32)(16L);
530 0 : *pTmp |= ( (sal_Int32) aCol.GetBlue() ) << (sal_Int32)(8L);
531 :
532 0 : if( pMskAcc->GetPixel( nY, nX ) != aWhite )
533 0 : *pTmp |= 0x000000ffUL;
534 0 : }
535 : }
536 :
537 : // iterate through interfaces
538 0 : for (ConsumerList_t::iterator iter = aTmp.begin(); iter != aTmp.end(); ++iter)
539 0 : (*iter)->setPixelsByLongs( nStartX, nStartY, nPartWidth, nPartHeight, aData, 0UL, nPartWidth );
540 : }
541 :
542 0 : aBmp.ReleaseAccess( pBmpAcc );
543 0 : aMask.ReleaseAccess( pMskAcc );
544 0 : }
545 0 : }
546 :
547 0 : 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 : {
549 0 : if ( aArguments.getLength() == 1 )
550 : {
551 0 : ::com::sun::star::uno::Any aArg = aArguments.getConstArray()[0];
552 0 : rtl::OUString aURL;
553 0 : if ( aArg >>= aURL )
554 : {
555 0 : SetImage( aURL );
556 0 : }
557 : }
558 0 : }
559 :
560 : namespace frm
561 : {
562 : ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >
563 0 : SAL_CALL ImageProducer_CreateInstance(
564 : const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& )
565 : {
566 : return ::com::sun::star::uno::Reference < ::com::sun::star::uno::XInterface >(
567 0 : ( ::cppu::OWeakObject* ) new ImageProducer );
568 : }
569 : } // namespace frm
570 :
571 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|