1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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"
22 #include <osl/diagnose.h>
23 #include <tools/debug.hxx>
25 #include <vcl/BitmapReadAccess.hxx>
26 #include <vcl/cvtgrf.hxx>
27 #include <vcl/svapp.hxx>
28 #include <unotools/ucbstreamhelper.hxx>
29 #include <cppuhelper/queryinterface.hxx>
30 #include <cppuhelper/supportsservice.hxx>
31 #include <com/sun/star/awt/ImageStatus.hpp>
32 #include <com/sun/star/io/XInputStream.hpp>
34 #include <svtools/imageresourceaccess.hxx>
35 #include <comphelper/processfactory.hxx>
38 ImageProducer::ImageProducer()
46 ImageProducer::~ImageProducer()
52 css::uno::Any
ImageProducer::queryInterface( const css::uno::Type
& rType
)
54 css::uno::Any aRet
= ::cppu::queryInterface( rType
,
55 static_cast< css::lang::XInitialization
* >(this),
56 static_cast< css::lang::XServiceInfo
* >(this),
57 static_cast< css::awt::XImageProducer
* >(this) );
58 return (aRet
.hasValue() ? aRet
: OWeakObject::queryInterface( rType
));
62 void ImageProducer::addConsumer( const css::uno::Reference
< css::awt::XImageConsumer
>& rxConsumer
)
64 DBG_ASSERT( rxConsumer
.is(), "::AddConsumer(...): No consumer referenced!" );
66 maConsList
.push_back( rxConsumer
);
70 void ImageProducer::removeConsumer( const css::uno::Reference
< css::awt::XImageConsumer
>& rxConsumer
)
72 ConsumerList_t::reverse_iterator riter
= std::find(maConsList
.rbegin(),maConsList
.rend(),rxConsumer
);
74 if (riter
!= maConsList
.rend())
75 maConsList
.erase(riter
.base()-1);
79 void ImageProducer::SetImage( const OUString
& rPath
)
84 mxOwnedStream
.reset();
87 if ( ::svt::GraphicAccess::isSupportedURL( maURL
) )
89 mxOwnedStream
= ::svt::GraphicAccess::getImageStream( ::comphelper::getProcessComponentContext(), maURL
);
90 mpStm
= mxOwnedStream
.get();
92 else if( !maURL
.isEmpty() )
94 mxOwnedStream
= ::utl::UcbStreamHelper::CreateStream( maURL
, StreamMode::STD_READ
);
95 mpStm
= mxOwnedStream
.get();
100 void ImageProducer::SetImage( SvStream
& rStm
)
105 mxOwnedStream
.reset();
110 void ImageProducer::setImage( css::uno::Reference
< css::io::XInputStream
> const & rInputStmRef
)
115 mxOwnedStream
.reset();
118 if( rInputStmRef
.is() )
120 mxOwnedStream
= utl::UcbStreamHelper::CreateStream( rInputStmRef
);
121 mpStm
= mxOwnedStream
.get();
126 void ImageProducer::NewDataAvailable()
128 if (GraphicType::NONE
== moGraphic
->GetType())
133 void ImageProducer::startProduction()
135 if( maConsList
.empty() && !maDoneHdl
.IsSet() )
138 bool bNotifyEmptyGraphics
= false;
140 // valid stream or filled graphic? => update consumers
141 if (mpStm
|| moGraphic
->GetType() != GraphicType::NONE
)
143 // if we already have a graphic, we don't have to import again;
144 // graphic is cleared if a new Stream is set
145 if (moGraphic
->GetType() == GraphicType::NONE
)
147 if ( ImplImportGraphic( *moGraphic
) )
148 maDoneHdl
.Call( &*moGraphic
);
151 if( moGraphic
->GetType() != GraphicType::NONE
)
152 ImplUpdateData( *moGraphic
);
154 bNotifyEmptyGraphics
= true;
157 bNotifyEmptyGraphics
= true;
159 if ( !bNotifyEmptyGraphics
)
163 // create temporary list to hold interfaces
164 ConsumerList_t aTmp
= maConsList
;
166 // iterate through interfaces
167 for (auto const& elem
: aTmp
)
170 elem
->complete( css::awt::ImageStatus::IMAGESTATUS_STATICIMAGEDONE
, this );
173 maDoneHdl
.Call( nullptr );
177 bool ImageProducer::ImplImportGraphic( Graphic
& rGraphic
)
182 if( ERRCODE_IO_PENDING
== mpStm
->GetError() )
187 bool bRet
= GraphicConverter::Import( *mpStm
, rGraphic
) == ERRCODE_NONE
;
189 if( ERRCODE_IO_PENDING
== mpStm
->GetError() )
196 void ImageProducer::ImplUpdateData( const Graphic
& rGraphic
)
198 ImplInitConsumer( rGraphic
);
200 if( mbConsInit
&& !maConsList
.empty() )
202 // create temporary list to hold interfaces
203 ConsumerList_t aTmp
= maConsList
;
205 ImplUpdateConsumer( rGraphic
);
208 // iterate through interfaces
209 for (auto const& elem
: aTmp
)
210 elem
->complete( css::awt::ImageStatus::IMAGESTATUS_STATICIMAGEDONE
, this );
215 void ImageProducer::ImplInitConsumer( const Graphic
& rGraphic
)
217 sal_uInt32 nRMask
= 0;
218 sal_uInt32 nGMask
= 0;
219 sal_uInt32 nBMask
= 0;
220 sal_uInt32 nAMask
= 0;
221 sal_uInt32 nWidth
= 0;
222 sal_uInt32 nHeight
= 0;
223 sal_uInt8 nBitCount
= 0;
224 css::uno::Sequence
< sal_Int32
> aRGBPal
;
225 rGraphic
.GetBitmapEx().GetColorModel(aRGBPal
, nRMask
, nGMask
, nBMask
, nAMask
, mnTransIndex
, nWidth
, nHeight
, nBitCount
);
227 // create temporary list to hold interfaces
228 ConsumerList_t aTmp
= maConsList
;
230 // iterate through interfaces
231 for (auto const& elem
: aTmp
)
233 elem
->init( nWidth
, nHeight
);
234 elem
->setColorModel( nBitCount
,aRGBPal
, nRMask
, nGMask
, nBMask
, nAMask
);
241 void ImageProducer::ImplUpdateConsumer( const Graphic
& rGraphic
)
243 BitmapEx
aBmpEx( rGraphic
.GetBitmapEx() );
244 const Bitmap
& aBmp( aBmpEx
.GetBitmap() );
245 BitmapScopedReadAccess
pBmpAcc(aBmp
);
250 AlphaMask
aMask( aBmpEx
.GetAlphaMask() );
251 BitmapScopedReadAccess pMskAcc
;
252 if (!aMask
.IsEmpty())
254 const tools::Long nWidth
= pBmpAcc
->Width();
255 const tools::Long nHeight
= pBmpAcc
->Height();
256 const tools::Long nStartX
= 0;
257 const tools::Long nEndX
= nWidth
- 1;
258 const tools::Long nStartY
= 0;
259 const tools::Long nEndY
= nHeight
- 1;
260 const tools::Long nPartWidth
= nEndX
- nStartX
+ 1;
261 const tools::Long nPartHeight
= nEndY
- nStartY
+ 1;
265 aMask
= AlphaMask(aBmp
.GetSizePixel());
270 // create temporary list to hold interfaces
271 ConsumerList_t aTmp
= maConsList
;
273 if( pBmpAcc
->HasPalette() )
275 const BitmapColor
aWhite( pMskAcc
->GetBestMatchingColor( COL_ALPHA_TRANSPARENT
) );
277 if( mnTransIndex
< 256 )
279 css::uno::Sequence
<sal_Int8
> aData( nPartWidth
* nPartHeight
);
280 sal_Int8
* pTmp
= aData
.getArray();
282 for( tools::Long nY
= nStartY
; nY
<= nEndY
; nY
++ )
284 Scanline pScanlineMask
= pMskAcc
->GetScanline( nY
);
285 Scanline pScanline
= pBmpAcc
->GetScanline( nY
);
286 for( tools::Long nX
= nStartX
; nX
<= nEndX
; nX
++ )
288 if( pMskAcc
->GetPixelFromData( pScanlineMask
, nX
) == aWhite
)
289 *pTmp
++ = sal::static_int_cast
< sal_Int8
>(
292 *pTmp
++ = pBmpAcc
->GetPixelFromData( pScanline
, nX
).GetIndex();
296 // iterate through interfaces
297 for (auto const& elem
: aTmp
)
298 elem
->setPixelsByBytes( nStartX
, nStartY
, nPartWidth
, nPartHeight
, aData
, 0UL, nPartWidth
);
302 css::uno::Sequence
<sal_Int32
> aData( nPartWidth
* nPartHeight
);
303 sal_Int32
* pTmp
= aData
.getArray();
305 for( tools::Long nY
= nStartY
; nY
<= nEndY
; nY
++ )
307 Scanline pScanlineMask
= pMskAcc
->GetScanline( nY
);
308 Scanline pScanline
= pBmpAcc
->GetScanline( nY
);
309 for( tools::Long nX
= nStartX
; nX
<= nEndX
; nX
++ )
311 if( pMskAcc
->GetPixelFromData( pScanlineMask
, nX
) == aWhite
)
312 *pTmp
++ = mnTransIndex
;
314 *pTmp
++ = pBmpAcc
->GetPixelFromData( pScanline
, nX
).GetIndex();
318 // iterate through interfaces
319 for (auto const& elem
: aTmp
)
320 elem
->setPixelsByLongs( nStartX
, nStartY
, nPartWidth
, nPartHeight
, aData
, 0UL, nPartWidth
);
325 css::uno::Sequence
<sal_Int32
> aData( nPartWidth
* nPartHeight
);
326 const BitmapColor
aWhite( pMskAcc
->GetBestMatchingColor( COL_WHITE
) );
327 sal_Int32
* pTmp
= aData
.getArray();
329 for( tools::Long nY
= nStartY
; nY
<= nEndY
; nY
++ )
331 Scanline pScanlineMask
= pMskAcc
->GetScanline( nY
);
332 Scanline pScanline
= pBmpAcc
->GetScanline( nY
);
333 for( tools::Long nX
= nStartX
; nX
<= nEndX
; nX
++, pTmp
++ )
335 const BitmapColor
aCol( pBmpAcc
->GetPixelFromData( pScanline
, nX
) );
337 *pTmp
= static_cast<sal_Int32
>(aCol
.GetRed()) << 24;
338 *pTmp
|= static_cast<sal_Int32
>(aCol
.GetGreen()) << 16;
339 *pTmp
|= static_cast<sal_Int32
>(aCol
.GetBlue()) << 8;
341 if( pMskAcc
->GetPixelFromData( pScanlineMask
, nX
) != aWhite
)
342 *pTmp
|= 0x000000ffUL
;
346 // iterate through interfaces
347 for (auto const& elem
: aTmp
)
348 elem
->setPixelsByLongs( nStartX
, nStartY
, nPartWidth
, nPartHeight
, aData
, 0UL, nPartWidth
);
353 void ImageProducer::initialize( const css::uno::Sequence
< css::uno::Any
>& aArguments
)
355 if ( aArguments
.getLength() == 1 )
357 css::uno::Any aArg
= aArguments
.getConstArray()[0];
366 OUString
ImageProducer::getImplementationName() {
367 return u
"com.sun.star.form.ImageProducer"_ustr
;
370 sal_Bool
ImageProducer::supportsService(OUString
const & ServiceName
) {
371 return cppu::supportsService(this, ServiceName
);
374 css::uno::Sequence
<OUString
> ImageProducer::getSupportedServiceNames() {
375 return {u
"com.sun.star.awt.ImageProducer"_ustr
};
379 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
380 com_sun_star_form_ImageProducer_get_implementation(css::uno::XComponentContext
*,
381 css::uno::Sequence
<css::uno::Any
> const &)
383 return cppu::acquire(new ImageProducer());
386 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */