Update git submodules
[LibreOffice.git] / forms / source / component / imgprod.cxx
blob7ea05d743ac1bd2ac9517c67cfe99e1d3e0fb7ca
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"
22 #include <osl/diagnose.h>
23 #include <tools/debug.hxx>
24 #include <utility>
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()
39 : mpStm(nullptr)
40 , mnTransIndex(0)
41 , mbConsInit(false)
43 moGraphic.emplace();
46 ImageProducer::~ImageProducer()
51 // XInterface
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!" );
65 if( rxConsumer.is() )
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 )
81 maURL = rPath;
82 moGraphic->Clear();
83 mbConsInit = false;
84 mxOwnedStream.reset();
85 mpStm = nullptr;
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 )
102 maURL.clear();
103 moGraphic->Clear();
104 mbConsInit = false;
105 mxOwnedStream.reset();
106 mpStm = &rStm;
110 void ImageProducer::setImage( css::uno::Reference< css::io::XInputStream > const & rInputStmRef )
112 maURL.clear();
113 moGraphic->Clear();
114 mbConsInit = false;
115 mxOwnedStream.reset();
116 mpStm = nullptr;
118 if( rInputStmRef.is() )
120 mxOwnedStream = utl::UcbStreamHelper::CreateStream( rInputStmRef );
121 mpStm = mxOwnedStream.get();
126 void ImageProducer::NewDataAvailable()
128 if (GraphicType::NONE == moGraphic->GetType())
129 startProduction();
133 void ImageProducer::startProduction()
135 if( maConsList.empty() && !maDoneHdl.IsSet() )
136 return;
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 );
153 else
154 bNotifyEmptyGraphics = true;
156 else
157 bNotifyEmptyGraphics = true;
159 if ( !bNotifyEmptyGraphics )
160 return;
162 // reset image
163 // create temporary list to hold interfaces
164 ConsumerList_t aTmp = maConsList;
166 // iterate through interfaces
167 for (auto const& elem : aTmp)
169 elem->init( 0, 0 );
170 elem->complete( css::awt::ImageStatus::IMAGESTATUS_STATICIMAGEDONE, this );
173 maDoneHdl.Call( nullptr );
177 bool ImageProducer::ImplImportGraphic( Graphic& rGraphic )
179 if (!mpStm)
180 return false;
182 if( ERRCODE_IO_PENDING == mpStm->GetError() )
183 mpStm->ResetError();
185 mpStm->Seek( 0 );
187 bool bRet = GraphicConverter::Import( *mpStm, rGraphic ) == ERRCODE_NONE;
189 if( ERRCODE_IO_PENDING == mpStm->GetError() )
190 mpStm->ResetError();
192 return bRet;
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 );
206 mbConsInit = false;
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 );
237 mbConsInit = true;
241 void ImageProducer::ImplUpdateConsumer( const Graphic& rGraphic )
243 BitmapEx aBmpEx( rGraphic.GetBitmapEx() );
244 const Bitmap& aBmp( aBmpEx.GetBitmap() );
245 BitmapScopedReadAccess pBmpAcc(aBmp);
247 if( !pBmpAcc )
248 return;
250 AlphaMask aMask( aBmpEx.GetAlphaMask() );
251 BitmapScopedReadAccess pMskAcc;
252 if (!aMask.IsEmpty())
253 pMskAcc = aMask;
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;
263 if( !pMskAcc )
265 aMask = AlphaMask(aBmp.GetSizePixel());
266 aMask.Erase( 0 );
267 pMskAcc = aMask;
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 >(
290 mnTransIndex );
291 else
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 );
300 else
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;
313 else
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 );
323 else
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];
358 OUString aURL;
359 if ( aArg >>= aURL )
361 SetImage( aURL );
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: */