Bug Summary

File:home/maarten/src/libreoffice/core/include/rtl/ref.hxx
Warning:line 192, column 9
Use of memory after it is freed

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name UnoGraphicProvider.cxx -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/11.0.0 -isystem /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/glm -isystem /usr/include/glib-2.0 -isystem /usr/lib64/glib-2.0/include -isystem /usr/include/libmount -isystem /usr/include/blkid -isystem /usr/include/cairo -isystem /usr/include/glib-2.0 -isystem /usr/lib64/glib-2.0/include -isystem /usr/include/pixman-1 -isystem /usr/include/freetype2 -isystem /usr/include/libpng16 -isystem /usr/include/libxml2 -isystem /usr/include/freetype2 -isystem /usr/include/libpng16 -isystem /usr/include/dbus-1.0 -isystem /usr/lib64/dbus-1.0/include -isystem /usr/include/freetype2 -isystem /usr/include/libpng16 -D BOOST_ERROR_CODE_HEADER_ONLY -D BOOST_SYSTEM_NO_DEPRECATED -D CPPU_ENV=gcc3 -D LINUX -D OSL_DEBUG_LEVEL=1 -D SAL_LOG_INFO -D SAL_LOG_WARN -D UNIX -D UNX -D X86_64 -D _PTHREADS -D _REENTRANT -D VCL_DLLIMPLEMENTATION -D DLLIMPLEMENTATION_UITEST -D CUI_DLL_NAME="libcuilo.so" -D DESKTOP_DETECTOR_DLL_NAME="libdesktop_detectorlo.so" -D TK_DLL_NAME="libtklo.so" -D SYSTEM_ZLIB -D GLM_FORCE_CTOR_INIT -D SK_USER_CONFIG_HEADER=</home/maarten/src/libreoffice/core/config_host/config_skia.h> -D SKIA_DLL -D ENABLE_CUPS -D HAVE_VALGRIND_HEADERS -D EXCEPTIONS_ON -D LIBO_INTERNAL_ONLY -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/epoxy/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/skia/include/core -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/skia/include/effects -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/skia/include/gpu -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/skia/include/config -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/skia/include/ports -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/skia/include/third_party/vulkan -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/skia/tools/gpu -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/skia -I /home/maarten/src/libreoffice/core/external/skia/inc/ -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/mdds/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/lcms2/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/i18n -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/common -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/harfbuzz/src -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/graphite/include -I /home/maarten/src/libreoffice/core/external/boost/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/boost -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/pdfium -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/pdfium/public -D COMPONENT_BUILD -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/libpng -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/libjpeg-turbo -I /home/maarten/src/libreoffice/core/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include/linux -I /home/maarten/src/libreoffice/core/config_host -I /home/maarten/src/libreoffice/core/vcl/inc -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/udkapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/offapi/normal -I /home/maarten/src/libreoffice/core/workdir/CustomTarget/officecfg/registry -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libxml2 -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10 -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/x86_64-redhat-linux -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/11.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O0 -Wno-missing-braces -std=c++17 -fdeprecated-macro -fdebug-compilation-dir /home/maarten/src/libreoffice/core -ferror-limit 19 -fvisibility hidden -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -debug-info-kind=constructor -analyzer-output=html -faddrsig -o /home/maarten/tmp/wis/scan-build-libreoffice/output/report/2020-10-07-141433-9725-1 -x c++ /home/maarten/src/libreoffice/core/vcl/source/graphic/UnoGraphicProvider.cxx

/home/maarten/src/libreoffice/core/vcl/source/graphic/UnoGraphicProvider.cxx

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#include <vcl/svapp.hxx>
21#include <vcl/image.hxx>
22#include <vcl/metaact.hxx>
23#include <imagerepository.hxx>
24#include <tools/fract.hxx>
25#include <unotools/ucbstreamhelper.hxx>
26#include <vcl/graphicfilter.hxx>
27#include <vcl/stdtext.hxx>
28#include <vcl/wmfexternal.hxx>
29#include <vcl/virdev.hxx>
30#include <com/sun/star/awt/XBitmap.hpp>
31#include <com/sun/star/graphic/XGraphicProvider2.hpp>
32#include <com/sun/star/io/XStream.hpp>
33#include <com/sun/star/lang/XServiceInfo.hpp>
34#include <com/sun/star/text/GraphicCrop.hpp>
35#include <com/sun/star/uno/XComponentContext.hpp>
36#include <comphelper/fileformat.h>
37#include <comphelper/servicehelper.hxx>
38#include <cppuhelper/implbase.hxx>
39#include <cppuhelper/supportsservice.hxx>
40#include <sal/log.hxx>
41
42#include <graphic/UnoGraphicDescriptor.hxx>
43#include <graphic/UnoGraphic.hxx>
44#include <rtl/ref.hxx>
45#include <vcl/dibtools.hxx>
46#include <comphelper/sequence.hxx>
47#include <memory>
48
49using namespace com::sun::star;
50
51namespace {
52
53class GraphicProvider : public ::cppu::WeakImplHelper< css::graphic::XGraphicProvider2,
54 css::lang::XServiceInfo >
55{
56public:
57
58 GraphicProvider();
59
60protected:
61
62 // XServiceInfo
63 virtual OUString SAL_CALL getImplementationName() override;
64 virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
65 virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
66
67 // XTypeProvider
68 virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes( ) override;
69 virtual css::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId( ) override;
70
71 // XGraphicProvider
72 virtual css::uno::Reference< css::beans::XPropertySet > SAL_CALL queryGraphicDescriptor( const css::uno::Sequence< css::beans::PropertyValue >& MediaProperties ) override;
73 virtual css::uno::Reference< css::graphic::XGraphic > SAL_CALL queryGraphic( const css::uno::Sequence< css::beans::PropertyValue >& MediaProperties ) override;
74 virtual void SAL_CALL storeGraphic( const css::uno::Reference< css::graphic::XGraphic >& Graphic, const css::uno::Sequence< css::beans::PropertyValue >& MediaProperties ) override;
75
76 // XGraphicProvider2
77 uno::Sequence< uno::Reference<graphic::XGraphic> > SAL_CALL queryGraphics(const uno::Sequence< uno::Sequence<beans::PropertyValue> >& MediaPropertiesSeq ) override;
78
79private:
80
81 static css::uno::Reference< css::graphic::XGraphic > implLoadMemory( const OUString& rResourceURL );
82 static css::uno::Reference< css::graphic::XGraphic > implLoadRepositoryImage( const OUString& rResourceURL );
83 static css::uno::Reference< css::graphic::XGraphic > implLoadBitmap( const css::uno::Reference< css::awt::XBitmap >& rBitmap );
84 static css::uno::Reference< css::graphic::XGraphic > implLoadStandardImage( const OUString& rResourceURL );
85};
86
87GraphicProvider::GraphicProvider()
88{
89}
90
91OUString SAL_CALL GraphicProvider::getImplementationName()
92{
93 return "com.sun.star.comp.graphic.GraphicProvider";
94}
95
96sal_Bool SAL_CALL GraphicProvider::supportsService( const OUString& ServiceName )
97{
98 return cppu::supportsService( this, ServiceName );
99}
100
101uno::Sequence< OUString > SAL_CALL GraphicProvider::getSupportedServiceNames()
102{
103 uno::Sequence<OUString> aSeq { "com.sun.star.graphic.GraphicProvider" };
104 return aSeq;
105}
106
107uno::Sequence< uno::Type > SAL_CALL GraphicProvider::getTypes()
108{
109 static const uno::Sequence< uno::Type > aTypes {
110 cppu::UnoType<lang::XServiceInfo>::get(),
111 cppu::UnoType<lang::XTypeProvider>::get(),
112 cppu::UnoType<graphic::XGraphicProvider>::get()
113 };
114 return aTypes;
115}
116
117uno::Sequence< sal_Int8 > SAL_CALL GraphicProvider::getImplementationId()
118{
119 return css::uno::Sequence<sal_Int8>();
120}
121
122uno::Reference< ::graphic::XGraphic > GraphicProvider::implLoadMemory( const OUString& rResourceURL )
123{
124 uno::Reference< ::graphic::XGraphic > xRet;
125 sal_Int32 nIndex = 0;
126
127 if( rResourceURL.getToken( 0, '/', nIndex ) == "private:memorygraphic" )
128 {
129 sal_Int64 nGraphicAddress = rResourceURL.getToken( 0, '/', nIndex ).toInt64();
130
131 if( nGraphicAddress )
132 {
133 ::unographic::Graphic* pUnoGraphic = new ::unographic::Graphic;
134
135 pUnoGraphic->init( *reinterpret_cast< ::Graphic* >( nGraphicAddress ) );
136 xRet = pUnoGraphic;
137 }
138 }
139
140 return xRet;
141}
142
143
144uno::Reference< ::graphic::XGraphic > GraphicProvider::implLoadRepositoryImage( const OUString& rResourceURL )
145{
146 uno::Reference< ::graphic::XGraphic > xRet;
147
148 OUString sPathName;
149 if( rResourceURL.startsWith("private:graphicrepository/", &sPathName) )
150 {
151 BitmapEx aBitmap;
152 if ( vcl::ImageRepository::loadImage( sPathName, aBitmap ) )
153 {
154 xRet = Graphic(aBitmap).GetXGraphic();
155 }
156 }
157 return xRet;
158}
159
160
161uno::Reference< ::graphic::XGraphic > GraphicProvider::implLoadStandardImage( const OUString& rResourceURL )
162{
163 uno::Reference< ::graphic::XGraphic > xRet;
164
165 OUString sImageName;
166 if( rResourceURL.startsWith("private:standardimage/", &sImageName) )
167 {
168 if ( sImageName == "info" )
169 {
170 xRet = Graphic(GetStandardInfoBoxImage().GetBitmapEx()).GetXGraphic();
171 }
172 else if ( sImageName == "warning" )
173 {
174 xRet = Graphic(GetStandardWarningBoxImage().GetBitmapEx()).GetXGraphic();
175 }
176 else if ( sImageName == "error" )
177 {
178 xRet = Graphic(GetStandardErrorBoxImage().GetBitmapEx()).GetXGraphic();
179 }
180 else if ( sImageName == "query" )
181 {
182 xRet = Graphic(GetStandardQueryBoxImage().GetBitmapEx()).GetXGraphic();
183 }
184 }
185 return xRet;
186}
187
188
189uno::Reference< ::graphic::XGraphic > GraphicProvider::implLoadBitmap( const uno::Reference< awt::XBitmap >& xBtm )
190{
191 uno::Reference< ::graphic::XGraphic > xRet;
192 uno::Sequence< sal_Int8 > aBmpSeq( xBtm->getDIB() );
193 uno::Sequence< sal_Int8 > aMaskSeq( xBtm->getMaskDIB() );
194 SvMemoryStream aBmpStream( aBmpSeq.getArray(), aBmpSeq.getLength(), StreamMode::READ );
195 Bitmap aBmp;
196 BitmapEx aBmpEx;
197
198 ReadDIB(aBmp, aBmpStream, true);
199
200 if( aMaskSeq.hasElements() )
201 {
202 SvMemoryStream aMaskStream( aMaskSeq.getArray(), aMaskSeq.getLength(), StreamMode::READ );
203 Bitmap aMask;
204
205 ReadDIB(aMask, aMaskStream, true);
206 aBmpEx = BitmapEx( aBmp, aMask );
207 }
208 else
209 aBmpEx = BitmapEx( aBmp );
210
211 if( !aBmpEx.IsEmpty() )
212 {
213 ::unographic::Graphic* pUnoGraphic = new ::unographic::Graphic;
214
215 pUnoGraphic->init( aBmpEx );
216 xRet = pUnoGraphic;
217 }
218 return xRet;
219}
220
221uno::Reference< beans::XPropertySet > SAL_CALL GraphicProvider::queryGraphicDescriptor( const uno::Sequence< beans::PropertyValue >& rMediaProperties )
222{
223 uno::Reference< beans::XPropertySet > xRet;
224
225 OUString aURL;
226 uno::Reference< io::XInputStream > xIStm;
227 uno::Reference< awt::XBitmap >xBtm;
228
229 for( const auto& rMediaProperty : rMediaProperties )
230 {
231 if (xRet.is())
232 break;
233
234 const OUString aName( rMediaProperty.Name );
235 const uno::Any aValue( rMediaProperty.Value );
236
237 if (aName == "URL")
238 {
239 aValue >>= aURL;
240 }
241 else if (aName == "InputStream")
242 {
243 aValue >>= xIStm;
244 }
245 else if (aName == "Bitmap")
246 {
247 aValue >>= xBtm;
248 }
249 }
250
251 SolarMutexGuard g;
252
253 if( xIStm.is() )
254 {
255 unographic::GraphicDescriptor* pDescriptor = new unographic::GraphicDescriptor;
256 pDescriptor->init( xIStm, aURL );
257 xRet = pDescriptor;
258 }
259 else if( !aURL.isEmpty() )
260 {
261 uno::Reference< ::graphic::XGraphic > xGraphic( implLoadMemory( aURL ) );
262
263 if ( !xGraphic.is() )
264 xGraphic = implLoadRepositoryImage( aURL );
265
266 if ( !xGraphic.is() )
267 xGraphic = implLoadStandardImage( aURL );
268
269 if( xGraphic.is() )
270 {
271 xRet.set( xGraphic, uno::UNO_QUERY );
272 }
273 else
274 {
275 unographic::GraphicDescriptor* pDescriptor = new unographic::GraphicDescriptor;
276 pDescriptor->init( aURL );
277 xRet = pDescriptor;
278 }
279 }
280 else if( xBtm.is() )
281 {
282 uno::Reference< ::graphic::XGraphic > xGraphic( implLoadBitmap( xBtm ) );
283 if( xGraphic.is() )
284 xRet.set( xGraphic, uno::UNO_QUERY );
285 }
286
287 return xRet;
288}
289
290
291uno::Reference< ::graphic::XGraphic > SAL_CALL GraphicProvider::queryGraphic( const uno::Sequence< ::beans::PropertyValue >& rMediaProperties )
292{
293 uno::Reference< ::graphic::XGraphic > xRet;
294 OUString aPath;
295
296 uno::Reference< io::XInputStream > xIStm;
297 uno::Reference< awt::XBitmap >xBtm;
298
299 uno::Sequence< ::beans::PropertyValue > aFilterData;
300
301 bool bLazyRead = false;
302 bool bLoadAsLink = false;
303
304 for (const auto& rMediaProperty : rMediaProperties)
305 {
306 if (xRet.is())
307 break;
308
309 const OUString aName( rMediaProperty.Name );
310 const uno::Any aValue( rMediaProperty.Value );
311
312 if (aName == "URL")
313 {
314 OUString aURL;
315 aValue >>= aURL;
316 aPath = aURL;
317 }
318 else if (aName == "InputStream")
319 {
320 aValue >>= xIStm;
321 }
322 else if (aName == "Bitmap")
323 {
324 aValue >>= xBtm;
325 }
326 else if (aName == "FilterData")
327 {
328 aValue >>= aFilterData;
329 }
330 else if (aName == "LazyRead")
331 {
332 aValue >>= bLazyRead;
333 }
334 else if (aName == "LoadAsLink")
335 {
336 aValue >>= bLoadAsLink;
337 }
338 }
339
340 // Check for the goal width and height if they are defined
341 sal_uInt16 nExtWidth = 0;
342 sal_uInt16 nExtHeight = 0;
343 sal_uInt16 nExtMapMode = 0;
344 for( const auto& rProp : std::as_const(aFilterData) )
345 {
346 const OUString aName( rProp.Name );
347 const uno::Any aValue( rProp.Value );
348
349 if (aName == "ExternalWidth")
350 {
351 aValue >>= nExtWidth;
352 }
353 else if (aName == "ExternalHeight")
354 {
355 aValue >>= nExtHeight;
356 }
357 else if (aName == "ExternalMapMode")
358 {
359 aValue >>= nExtMapMode;
360 }
361 }
362
363 SolarMutexGuard g;
364
365 std::unique_ptr<SvStream> pIStm;
366
367 if( xIStm.is() )
368 {
369 pIStm = ::utl::UcbStreamHelper::CreateStream( xIStm );
370 }
371 else if( !aPath.isEmpty() )
372 {
373 xRet = implLoadMemory( aPath );
374
375 if ( !xRet.is() )
376 xRet = implLoadRepositoryImage( aPath );
377
378 if ( !xRet.is() )
379 xRet = implLoadStandardImage( aPath );
380
381 if( !xRet.is() )
382 pIStm = ::utl::UcbStreamHelper::CreateStream( aPath, StreamMode::READ );
383 }
384 else if( xBtm.is() )
385 {
386 xRet = implLoadBitmap( xBtm );
387 }
388
389 if( pIStm )
390 {
391 ::GraphicFilter& rFilter = ::GraphicFilter::GetGraphicFilter();
392
393 {
394 Graphic aVCLGraphic;
395
396 // Define APM Header if goal height and width are defined
397 WmfExternal aExtHeader;
398 aExtHeader.xExt = nExtWidth;
399 aExtHeader.yExt = nExtHeight;
400 aExtHeader.mapMode = nExtMapMode;
401 WmfExternal *pExtHeader = nullptr;
402 if ( nExtMapMode > 0 )
403 {
404 pExtHeader = &aExtHeader;
405 bLazyRead = false;
406 }
407
408 ErrCode error = ERRCODE_NONEErrCode(0);
409 if (bLazyRead)
410 {
411 Graphic aGraphic = rFilter.ImportUnloadedGraphic(*pIStm);
412 if (!aGraphic.IsNone())
413 aVCLGraphic = aGraphic;
414 }
415 if (aVCLGraphic.IsNone())
416 error = rFilter.ImportGraphic(aVCLGraphic, aPath, *pIStm, GRFILTER_FORMAT_DONTKNOW(sal_uInt16(0xFFFF)),
417 nullptr, GraphicFilterImportFlags::NONE, pExtHeader);
418
419 if( (error == ERRCODE_NONEErrCode(0) ) &&
420 ( aVCLGraphic.GetType() != GraphicType::NONE ) )
421 {
422 if (!aPath.isEmpty() && bLoadAsLink)
423 aVCLGraphic.setOriginURL(aPath);
424
425 ::unographic::Graphic* pUnoGraphic = new ::unographic::Graphic;
426
427 pUnoGraphic->init( aVCLGraphic );
428 xRet = pUnoGraphic;
429 }
430 else{
431 SAL_WARN("svtools", "Could not create graphic: " << error)do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "svtools")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "Could not create graphic: "
<< error) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("svtools"), ("/home/maarten/src/libreoffice/core/vcl/source/graphic/UnoGraphicProvider.cxx"
":" "431" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "Could not create graphic: " << error
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "Could not create graphic: " << error; ::sal::
detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("svtools"), ("/home/maarten/src/libreoffice/core/vcl/source/graphic/UnoGraphicProvider.cxx"
":" "431" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "Could not create graphic: " << error) == 1
) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("svtools"
), ("/home/maarten/src/libreoffice/core/vcl/source/graphic/UnoGraphicProvider.cxx"
":" "431" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "Could not create graphic: " << error
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "Could not create graphic: " << error; ::sal::
detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("svtools"), ("/home/maarten/src/libreoffice/core/vcl/source/graphic/UnoGraphicProvider.cxx"
":" "431" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
432 }
433 }
434 }
435
436 return xRet;
437}
438
439uno::Sequence< uno::Reference<graphic::XGraphic> > SAL_CALL GraphicProvider::queryGraphics(const uno::Sequence< uno::Sequence<beans::PropertyValue> >& rMediaPropertiesSeq)
440{
441 SolarMutexGuard aGuard;
442
443 // Turn properties into streams.
444 std::vector< std::unique_ptr<SvStream> > aStreams;
445 for (const auto& rMediaProperties : rMediaPropertiesSeq)
446 {
447 std::unique_ptr<SvStream> pStream;
448 uno::Reference<io::XInputStream> xStream;
449
450 auto pProp = std::find_if(rMediaProperties.begin(), rMediaProperties.end(),
451 [](const beans::PropertyValue& rProp) { return rProp.Name == "InputStream"; });
452 if (pProp != rMediaProperties.end())
453 {
454 pProp->Value >>= xStream;
455 if (xStream.is())
456 pStream = utl::UcbStreamHelper::CreateStream(xStream);
457 }
458
459 aStreams.push_back(std::move(pStream));
460 }
461
462 // Import: streams to graphics.
463 std::vector< std::shared_ptr<Graphic> > aGraphics;
464 GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
465 rFilter.ImportGraphics(aGraphics, std::move(aStreams));
466
467 // Returning: graphics to UNO objects.
468 std::vector< uno::Reference<graphic::XGraphic> > aRet;
469 for (const auto& pGraphic : aGraphics)
470 {
471 uno::Reference<graphic::XGraphic> xGraphic;
472
473 if (pGraphic)
474 {
475 auto pUnoGraphic = new unographic::Graphic();
476 pUnoGraphic->init(*pGraphic);
477 xGraphic = pUnoGraphic;
478 }
479
480 aRet.push_back(xGraphic);
481 }
482
483 return comphelper::containerToSequence(aRet);
484}
485
486void ImplCalculateCropRect( ::Graphic const & rGraphic, const text::GraphicCrop& rGraphicCropLogic, tools::Rectangle& rGraphicCropPixel )
487{
488 if ( !(rGraphicCropLogic.Left || rGraphicCropLogic.Top || rGraphicCropLogic.Right || rGraphicCropLogic.Bottom) )
489 return;
490
491 Size aSourceSizePixel( rGraphic.GetSizePixel() );
492 if ( !(aSourceSizePixel.Width() && aSourceSizePixel.Height()) )
493 return;
494
495 if ( !(rGraphicCropLogic.Left || rGraphicCropLogic.Top || rGraphicCropLogic.Right || rGraphicCropLogic.Bottom) )
496 return;
497
498 Size aSize100thMM( 0, 0 );
499 if( rGraphic.GetPrefMapMode().GetMapUnit() != MapUnit::MapPixel )
500 {
501 aSize100thMM = OutputDevice::LogicToLogic(rGraphic.GetPrefSize(), rGraphic.GetPrefMapMode(), MapMode(MapUnit::Map100thMM));
502 }
503 else
504 {
505 aSize100thMM = Application::GetDefaultDevice()->PixelToLogic(rGraphic.GetPrefSize(), MapMode(MapUnit::Map100thMM));
506 }
507 if ( aSize100thMM.Width() && aSize100thMM.Height() )
508 {
509 double fSourceSizePixelWidth = static_cast<double>(aSourceSizePixel.Width());
510 double fSourceSizePixelHeight= static_cast<double>(aSourceSizePixel.Height());
511 rGraphicCropPixel.SetLeft( static_cast< sal_Int32 >((fSourceSizePixelWidth * rGraphicCropLogic.Left ) / aSize100thMM.Width()) );
512 rGraphicCropPixel.SetTop( static_cast< sal_Int32 >((fSourceSizePixelHeight * rGraphicCropLogic.Top ) / aSize100thMM.Height()) );
513 rGraphicCropPixel.SetRight( static_cast< sal_Int32 >(( fSourceSizePixelWidth * ( aSize100thMM.Width() - rGraphicCropLogic.Right ) ) / aSize100thMM.Width() ) );
514 rGraphicCropPixel.SetBottom( static_cast< sal_Int32 >(( fSourceSizePixelHeight * ( aSize100thMM.Height() - rGraphicCropLogic.Bottom ) ) / aSize100thMM.Height() ) );
515 }
516}
517
518void ImplApplyBitmapScaling( ::Graphic& rGraphic, sal_Int32 nPixelWidth, sal_Int32 nPixelHeight )
519{
520 if ( nPixelWidth && nPixelHeight )
521 {
522 BitmapEx aBmpEx( rGraphic.GetBitmapEx() );
523 MapMode aPrefMapMode( aBmpEx.GetPrefMapMode() );
524 Size aPrefSize( aBmpEx.GetPrefSize() );
525 aBmpEx.Scale( Size( nPixelWidth, nPixelHeight ) );
526 aBmpEx.SetPrefMapMode( aPrefMapMode );
527 aBmpEx.SetPrefSize( aPrefSize );
528 rGraphic = aBmpEx;
529 }
530}
531
532void ImplApplyBitmapResolution( ::Graphic& rGraphic, sal_Int32 nImageResolution, const Size& rVisiblePixelSize, const awt::Size& rLogicalSize )
533{
534 if ( !(nImageResolution && rLogicalSize.Width && rLogicalSize.Height) )
535 return;
536
537 const double fImageResolution = static_cast<double>( nImageResolution );
538 const double fSourceDPIX = ( static_cast<double>(rVisiblePixelSize.Width()) * 2540.0 ) / static_cast<double>(rLogicalSize.Width);
539 const double fSourceDPIY = ( static_cast<double>(rVisiblePixelSize.Height()) * 2540.0 ) / static_cast<double>(rLogicalSize.Height);
540 const sal_Int32 nSourcePixelWidth( rGraphic.GetSizePixel().Width() );
541 const sal_Int32 nSourcePixelHeight( rGraphic.GetSizePixel().Height() );
542 const double fSourcePixelWidth = static_cast<double>( nSourcePixelWidth );
543 const double fSourcePixelHeight= static_cast<double>( nSourcePixelHeight );
544
545 sal_Int32 nDestPixelWidth = nSourcePixelWidth;
546 sal_Int32 nDestPixelHeight = nSourcePixelHeight;
547
548 // check, if the bitmap DPI exceeds the maximum DPI
549 if( fSourceDPIX > fImageResolution )
550 {
551 nDestPixelWidth = static_cast<sal_Int32>(( fSourcePixelWidth * fImageResolution ) / fSourceDPIX);
552 if ( !nDestPixelWidth || ( nDestPixelWidth > nSourcePixelWidth ) )
553 nDestPixelWidth = nSourcePixelWidth;
554 }
555 if ( fSourceDPIY > fImageResolution )
556 {
557 nDestPixelHeight= static_cast<sal_Int32>(( fSourcePixelHeight* fImageResolution ) / fSourceDPIY);
558 if ( !nDestPixelHeight || ( nDestPixelHeight > nSourcePixelHeight ) )
559 nDestPixelHeight = nSourcePixelHeight;
560 }
561 if ( ( nDestPixelWidth != nSourcePixelWidth ) || ( nDestPixelHeight != nSourcePixelHeight ) )
562 ImplApplyBitmapScaling( rGraphic, nDestPixelWidth, nDestPixelHeight );
563}
564
565void ImplApplyFilterData( ::Graphic& rGraphic, const uno::Sequence< beans::PropertyValue >& rFilterData )
566{
567 /* this method applies following attributes to the graphic, in the first step the
568 cropping area (logical size in 100thmm) is applied, in the second step the resolution
569 is applied, in the third step the graphic is scaled to the corresponding pixelsize.
570 if a parameter value is zero or not available the corresponding step will be skipped */
571
572 sal_Int32 nPixelWidth = 0;
573 sal_Int32 nPixelHeight= 0;
574 sal_Int32 nImageResolution = 0;
575 awt::Size aLogicalSize( 0, 0 );
576 text::GraphicCrop aCropLogic( 0, 0, 0, 0 );
577 bool bRemoveCropArea = true;
578
579 for( const auto& rProp : rFilterData )
1
Assuming '__begin1' is not equal to '__end1'
580 {
581 const OUString aName( rProp.Name );
582 const uno::Any aValue( rProp.Value );
583
584 if (aName == "PixelWidth")
2
Assuming the condition is true
3
Taking true branch
4
Taking false branch
585 aValue >>= nPixelWidth;
586 else if (aName == "PixelHeight")
5
Taking false branch
587 aValue >>= nPixelHeight;
588 else if (aName == "LogicalSize")
6
Taking false branch
589 aValue >>= aLogicalSize;
590 else if (aName == "GraphicCropLogic")
7
Taking false branch
591 aValue >>= aCropLogic;
592 else if (aName == "RemoveCropArea")
8
Taking false branch
593 aValue >>= bRemoveCropArea;
594 else if (aName == "ImageResolution")
9
Assuming the condition is true
10
Taking true branch
595 aValue >>= nImageResolution;
596 }
597 if ( rGraphic.GetType() == GraphicType::Bitmap )
11
Assuming the condition is false
12
Taking false branch
598 {
599 if(rGraphic.getVectorGraphicData())
600 {
601 // embedded Vector Graphic Data, no need to scale. Also no method to apply crop data currently
602 }
603 else
604 {
605 tools::Rectangle aCropPixel( Point( 0, 0 ), rGraphic.GetSizePixel() );
606 ImplCalculateCropRect( rGraphic, aCropLogic, aCropPixel );
607 if ( bRemoveCropArea )
608 {
609 BitmapEx aBmpEx( rGraphic.GetBitmapEx() );
610 aBmpEx.Crop( aCropPixel );
611 rGraphic = aBmpEx;
612 }
613 Size aVisiblePixelSize( bRemoveCropArea ? rGraphic.GetSizePixel() : aCropPixel.GetSize() );
614 ImplApplyBitmapResolution( rGraphic, nImageResolution, aVisiblePixelSize, aLogicalSize );
615 ImplApplyBitmapScaling( rGraphic, nPixelWidth, nPixelHeight );
616 }
617 }
618 else if ( ( rGraphic.GetType() == GraphicType::GdiMetafile ) && nImageResolution )
13
Assuming the condition is true
14
Assuming 'nImageResolution' is not equal to 0
15
Taking true branch
619 {
620 ScopedVclPtrInstance< VirtualDevice > aDummyVDev;
16
Calling default constructor for 'ScopedVclPtrInstance<VirtualDevice>'
18
Returning from default constructor for 'ScopedVclPtrInstance<VirtualDevice>'
621 GDIMetaFile aMtf( rGraphic.GetGDIMetaFile() );
622 Size aMtfSize( OutputDevice::LogicToLogic(aMtf.GetPrefSize(), aMtf.GetPrefMapMode(), MapMode(MapUnit::Map100thMM)) );
623 if ( aMtfSize.Width() && aMtfSize.Height() )
19
Assuming the condition is false
624 {
625 MapMode aNewMapMode( MapUnit::Map100thMM );
626 aNewMapMode.SetScaleX( Fraction( aLogicalSize.Width, aMtfSize.Width() ) );
627 aNewMapMode.SetScaleY( Fraction( aLogicalSize.Height, aMtfSize.Height() ) );
628 aDummyVDev->EnableOutput( false );
629 aDummyVDev->SetMapMode( aNewMapMode );
630
631 for( size_t i = 0, nObjCount = aMtf.GetActionSize(); i < nObjCount; i++ )
632 {
633 MetaAction* pAction = aMtf.GetAction( i );
634 switch( pAction->GetType() )
635 {
636 // only optimizing common bitmap actions:
637 case MetaActionType::MAPMODE:
638 {
639 pAction->Execute( aDummyVDev.get() );
640 break;
641 }
642 case MetaActionType::PUSH:
643 {
644 const MetaPushAction* pA = static_cast<const MetaPushAction*>(pAction);
645 aDummyVDev->Push( pA->GetFlags() );
646 break;
647 }
648 case MetaActionType::POP:
649 {
650 aDummyVDev->Pop();
651 break;
652 }
653 case MetaActionType::BMPSCALE:
654 case MetaActionType::BMPEXSCALE:
655 {
656 BitmapEx aBmpEx;
657 Point aPos;
658 Size aSize;
659 if ( pAction->GetType() == MetaActionType::BMPSCALE )
660 {
661 MetaBmpScaleAction* pScaleAction = dynamic_cast< MetaBmpScaleAction* >( pAction );
662 assert(pScaleAction)(static_cast <bool> (pScaleAction) ? void (0) : __assert_fail
("pScaleAction", "/home/maarten/src/libreoffice/core/vcl/source/graphic/UnoGraphicProvider.cxx"
, 662, __extension__ __PRETTY_FUNCTION__))
;
663 aBmpEx = pScaleAction->GetBitmap();
664 aPos = pScaleAction->GetPoint();
665 aSize = pScaleAction->GetSize();
666 }
667 else
668 {
669 MetaBmpExScaleAction* pScaleAction = dynamic_cast< MetaBmpExScaleAction* >( pAction );
670 assert(pScaleAction)(static_cast <bool> (pScaleAction) ? void (0) : __assert_fail
("pScaleAction", "/home/maarten/src/libreoffice/core/vcl/source/graphic/UnoGraphicProvider.cxx"
, 670, __extension__ __PRETTY_FUNCTION__))
;
671 aBmpEx = pScaleAction->GetBitmapEx();
672 aPos = pScaleAction->GetPoint();
673 aSize = pScaleAction->GetSize();
674 }
675 ::Graphic aGraphic( aBmpEx );
676 const Size aSize100thmm( aDummyVDev->LogicToPixel( aSize ) );
677 Size aSize100thmm2( aDummyVDev->PixelToLogic(aSize100thmm, MapMode(MapUnit::Map100thMM)) );
678
679 ImplApplyBitmapResolution( aGraphic, nImageResolution,
680 aGraphic.GetSizePixel(), awt::Size( aSize100thmm2.Width(), aSize100thmm2.Height() ) );
681
682 rtl::Reference<MetaAction> pNewAction = new MetaBmpExScaleAction( aPos, aSize, aGraphic.GetBitmapEx() );
683 aMtf.ReplaceAction( pNewAction, i );
684 break;
685 }
686 default:
687 case MetaActionType::BMP:
688 case MetaActionType::BMPSCALEPART:
689 case MetaActionType::BMPEX:
690 case MetaActionType::BMPEXSCALEPART:
691 case MetaActionType::MASK:
692 case MetaActionType::MASKSCALE:
693 break;
694 }
695 }
696 rGraphic = aMtf;
697 }
698 }
20
Calling implicit destructor for 'ScopedVclPtrInstance<VirtualDevice>'
21
Calling '~ScopedVclPtr'
699}
700
701
702void SAL_CALL GraphicProvider::storeGraphic( const uno::Reference< ::graphic::XGraphic >& rxGraphic, const uno::Sequence< beans::PropertyValue >& rMediaProperties )
703{
704 SolarMutexGuard g;
705
706 std::unique_ptr<SvStream> pOStm;
707 OUString aPath;
708
709 for( const auto& rMediaProperty : rMediaProperties )
710 {
711 const OUString aName( rMediaProperty.Name );
712 const uno::Any aValue( rMediaProperty.Value );
713
714 if (aName == "URL")
715 {
716 OUString aURL;
717
718 aValue >>= aURL;
719 pOStm = ::utl::UcbStreamHelper::CreateStream( aURL, StreamMode::WRITE | StreamMode::TRUNC );
720 aPath = aURL;
721 }
722 else if (aName == "OutputStream")
723 {
724 uno::Reference< io::XStream > xOStm;
725
726 aValue >>= xOStm;
727
728 if( xOStm.is() )
729 pOStm = ::utl::UcbStreamHelper::CreateStream( xOStm );
730 }
731
732 if( pOStm )
733 break;
734 }
735
736 if( !pOStm )
737 return;
738
739 uno::Sequence< beans::PropertyValue > aFilterDataSeq;
740 const char* pFilterShortName = nullptr;
741
742 for( const auto& rMediaProperty : rMediaProperties )
743 {
744 const OUString aName( rMediaProperty.Name );
745 const uno::Any aValue( rMediaProperty.Value );
746
747 if (aName == "FilterData")
748 {
749 aValue >>= aFilterDataSeq;
750 }
751 else if (aName == "MimeType")
752 {
753 OUString aMimeType;
754
755 aValue >>= aMimeType;
756
757 if (aMimeType == MIMETYPE_BMP"image/x-MS-bmp")
758 pFilterShortName = "bmp";
759 else if (aMimeType == MIMETYPE_EPS"image/x-eps")
760 pFilterShortName = "eps";
761 else if (aMimeType == MIMETYPE_GIF"image/gif")
762 pFilterShortName = "gif";
763 else if (aMimeType == MIMETYPE_JPG"image/jpeg")
764 pFilterShortName = "jpg";
765 else if (aMimeType == MIMETYPE_MET"image/x-met")
766 pFilterShortName = "met";
767 else if (aMimeType == MIMETYPE_PNG"image/png")
768 pFilterShortName = "png";
769 else if (aMimeType == MIMETYPE_PCT"image/x-pict")
770 pFilterShortName = "pct";
771 else if (aMimeType == MIMETYPE_PBM"image/x-portable-bitmap")
772 pFilterShortName = "pbm";
773 else if (aMimeType == MIMETYPE_PGM"image/x-portable-graymap")
774 pFilterShortName = "pgm";
775 else if (aMimeType == MIMETYPE_PPM"image/x-portable-pixmap")
776 pFilterShortName = "ppm";
777 else if (aMimeType == MIMETYPE_RAS"image/x-cmu-raster")
778 pFilterShortName = "ras";
779 else if (aMimeType == MIMETYPE_SVM"image/x-svm")
780 pFilterShortName = "svm";
781 else if (aMimeType == MIMETYPE_TIF"image/tiff")
782 pFilterShortName = "tif";
783 else if (aMimeType == MIMETYPE_EMF"image/x-emf")
784 pFilterShortName = "emf";
785 else if (aMimeType == MIMETYPE_WMF"image/x-wmf")
786 pFilterShortName = "wmf";
787 else if (aMimeType == MIMETYPE_XPM"image/x-xpixmap")
788 pFilterShortName = "xpm";
789 else if (aMimeType == MIMETYPE_SVG"image/svg+xml")
790 pFilterShortName = "svg";
791 else if (aMimeType == MIMETYPE_VCLGRAPHIC"image/x-vclgraphic")
792 pFilterShortName = MIMETYPE_VCLGRAPHIC"image/x-vclgraphic";
793 }
794 }
795
796 if( !pFilterShortName )
797 return;
798
799 ::GraphicFilter& rFilter = ::GraphicFilter::GetGraphicFilter();
800
801 {
802 const uno::Reference< XInterface > xIFace( rxGraphic, uno::UNO_QUERY );
803 const ::Graphic* pGraphic = comphelper::getUnoTunnelImplementation<::Graphic>( xIFace );
804
805 if( pGraphic && ( pGraphic->GetType() != GraphicType::NONE ) )
806 {
807 ::Graphic aGraphic( *pGraphic );
808 ImplApplyFilterData( aGraphic, aFilterDataSeq );
809
810 /* sj: using a temporary memory stream, because some graphic filters are seeking behind
811 stream end (which leads to an invalid argument exception then). */
812 SvMemoryStream aMemStrm;
813 aMemStrm.SetVersion( SOFFICE_FILEFORMAT_CURRENT6800 );
814 if( 0 == strcmp( pFilterShortName, MIMETYPE_VCLGRAPHIC"image/x-vclgraphic" ) )
815 WriteGraphic( aMemStrm, aGraphic );
816 else
817 {
818 rFilter.ExportGraphic( aGraphic, aPath, aMemStrm,
819 rFilter.GetExportFormatNumberForShortName( OUString::createFromAscii( pFilterShortName ) ),
820 ( aFilterDataSeq.hasElements() ? &aFilterDataSeq : nullptr ) );
821 }
822 pOStm->WriteBytes( aMemStrm.GetData(), aMemStrm.TellEnd() );
823 }
824 }
825}
826
827}
828
829extern "C" SAL_DLLPUBLIC_EXPORT__attribute__ ((visibility("default"))) css::uno::XInterface *
830com_sun_star_comp_graphic_GraphicProvider_get_implementation(
831 css::uno::XComponentContext *,
832 css::uno::Sequence<css::uno::Any> const &)
833{
834 return cppu::acquire(new GraphicProvider);
835}
836
837/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx

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#ifndef INCLUDED_VCL_PTR_HXX
21#define INCLUDED_VCL_PTR_HXX
22
23#include <sal/config.h>
24
25#include <rtl/ref.hxx>
26
27#include <utility>
28#include <type_traits>
29
30#ifdef DBG_UTIL
31#ifndef _WIN32
32#include <vcl/vclmain.hxx>
33#endif
34#endif
35
36class VclReferenceBase;
37
38namespace vcl::detail {
39
40template<typename>
41constexpr bool isIncompleteOrDerivedFromVclReferenceBase(...) { return true; }
42
43template<typename T> constexpr bool isIncompleteOrDerivedFromVclReferenceBase(
44 int (*)[sizeof(T)])
45{ return std::is_base_of<VclReferenceBase, T>::value; }
46
47} // namespace vcl::detail
48
49/**
50 * A thin wrapper around rtl::Reference to implement the acquire and dispose semantics we want for references to vcl::Window subclasses.
51 *
52 * For more details on the design please see vcl/README.lifecycle
53 *
54 * @param reference_type must be a subclass of vcl::Window
55 */
56template <class reference_type>
57class VclPtr
58{
59 static_assert(
60 vcl::detail::isIncompleteOrDerivedFromVclReferenceBase<reference_type>(
61 nullptr),
62 "template argument type must be derived from VclReferenceBase");
63
64 ::rtl::Reference<reference_type> m_rInnerRef;
65
66public:
67 /** Constructor...
68 */
69 VclPtr()
70 : m_rInnerRef()
71 {}
72
73 /** Constructor...
74 */
75 VclPtr (reference_type * pBody)
76 : m_rInnerRef(pBody)
77 {}
78
79 /** Constructor... that doesn't take a ref.
80 */
81 VclPtr (reference_type * pBody, __sal_NoAcquire)
82 : m_rInnerRef(pBody, SAL_NO_ACQUIRE)
83 {}
84
85 /** Up-casting conversion constructor: Copies interface reference.
86
87 Does not work for up-casts to ambiguous bases. For the special case of
88 up-casting to Reference< XInterface >, see the corresponding conversion
89 operator.
90
91 @param rRef another reference
92 */
93 template< class derived_type >
94 VclPtr(
95 const VclPtr< derived_type > & rRef,
96 typename std::enable_if<
97 std::is_base_of<reference_type, derived_type>::value, int>::type
98 = 0 )
99 : m_rInnerRef( static_cast<reference_type*>(rRef) )
100 {
101 }
102
103#if defined(DBG_UTIL) && !defined(_WIN32)
104 virtual ~VclPtr()
105 {
106 assert(m_rInnerRef.get() == nullptr || vclmain::isAlive())(static_cast <bool> (m_rInnerRef.get() == nullptr || vclmain
::isAlive()) ? void (0) : __assert_fail ("m_rInnerRef.get() == nullptr || vclmain::isAlive()"
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 106, __extension__ __PRETTY_FUNCTION__))
;
107 // We can be one of the intermediate counts, but if we are the last
108 // VclPtr keeping this object alive, then something forgot to call dispose().
109 assert((!m_rInnerRef.get() || m_rInnerRef->isDisposed() || m_rInnerRef->getRefCount() > 1)(static_cast <bool> ((!m_rInnerRef.get() || m_rInnerRef
->isDisposed() || m_rInnerRef->getRefCount() > 1) &&
"someone forgot to call dispose()") ? void (0) : __assert_fail
("(!m_rInnerRef.get() || m_rInnerRef->isDisposed() || m_rInnerRef->getRefCount() > 1) && \"someone forgot to call dispose()\""
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 110, __extension__ __PRETTY_FUNCTION__))
110 && "someone forgot to call dispose()")(static_cast <bool> ((!m_rInnerRef.get() || m_rInnerRef
->isDisposed() || m_rInnerRef->getRefCount() > 1) &&
"someone forgot to call dispose()") ? void (0) : __assert_fail
("(!m_rInnerRef.get() || m_rInnerRef->isDisposed() || m_rInnerRef->getRefCount() > 1) && \"someone forgot to call dispose()\""
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 110, __extension__ __PRETTY_FUNCTION__))
;
111 }
112 VclPtr(VclPtr const &) = default;
113 VclPtr(VclPtr &&) = default;
114 VclPtr & operator =(VclPtr const &) = default;
115 VclPtr & operator =(VclPtr &&) = default;
116#endif
117
118 /**
119 * A construction helper for VclPtr. Since VclPtr types are created
120 * with a reference-count of one - to help fit into the existing
121 * code-flow; this helps us to construct them easily.
122 *
123 * For more details on the design please see vcl/README.lifecycle
124 *
125 * @tparam reference_type must be a subclass of vcl::Window
126 */
127 template<typename... Arg> [[nodiscard]] static VclPtr< reference_type > Create(Arg &&... arg)
128 {
129 return VclPtr< reference_type >( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE );
130 }
131
132 /** Probably most common used: handle->someBodyOp().
133 */
134 reference_type * operator->() const
135 {
136 return m_rInnerRef.get();
137 }
138
139 /** Get the body. Can be used instead of operator->().
140 I.e. handle->someBodyOp() and handle.get()->someBodyOp()
141 are the same.
142 */
143 reference_type * get() const
144 {
145 return m_rInnerRef.get();
146 }
147
148 void set(reference_type *pBody)
149 {
150 m_rInnerRef.set(pBody);
151 }
152
153 void reset(reference_type *pBody)
154 {
155 m_rInnerRef.set(pBody);
156 }
157
158 /** Up-casting copy assignment operator.
159
160 Does not work for up-casts to ambiguous bases.
161
162 @param rRef another reference
163 */
164 template<typename derived_type>
165 typename std::enable_if<
166 std::is_base_of<reference_type, derived_type>::value,
167 VclPtr &>::type
168 operator =(VclPtr<derived_type> const & rRef)
169 {
170 m_rInnerRef.set(rRef.get());
171 return *this;
172 }
173
174 VclPtr & operator =(reference_type * pBody)
175 {
176 m_rInnerRef.set(pBody);
177 return *this;
178 }
179
180 operator reference_type * () const
181 {
182 return m_rInnerRef.get();
183 }
184
185 explicit operator bool () const
186 {
187 return m_rInnerRef.get() != nullptr;
188 }
189
190 void clear()
191 {
192 m_rInnerRef.clear();
193 }
194
195 void reset()
196 {
197 m_rInnerRef.clear();
198 }
199
200 void disposeAndClear()
201 {
202 // hold it alive for the lifetime of this method
203 ::rtl::Reference<reference_type> aTmp(m_rInnerRef);
204 m_rInnerRef.clear(); // we should use some 'swap' method ideally ;-)
23
Calling 'Reference::clear'
30
Returning; memory was released
205 if (aTmp.get()) {
31
Calling 'Reference::get'
206 aTmp->disposeOnce();
207 }
208 }
209
210 /** Needed to place VclPtr's into STL collection.
211 */
212 bool operator< (const VclPtr<reference_type> & handle) const
213 {
214 return (m_rInnerRef < handle.m_rInnerRef);
215 }
216}; // class VclPtr
217
218template<typename T1, typename T2>
219inline bool operator ==(VclPtr<T1> const & p1, VclPtr<T2> const & p2) {
220 return p1.get() == p2.get();
221}
222
223template<typename T> inline bool operator ==(VclPtr<T> const & p1, T const * p2)
224{
225 return p1.get() == p2;
226}
227
228template<typename T> inline bool operator ==(VclPtr<T> const & p1, T * p2) {
229 return p1.get() == p2;
230}
231
232template<typename T> inline bool operator ==(T const * p1, VclPtr<T> const & p2)
233{
234 return p1 == p2.get();
235}
236
237template<typename T> inline bool operator ==(T * p1, VclPtr<T> const & p2) {
238 return p1 == p2.get();
239}
240
241template<typename T1, typename T2>
242inline bool operator !=(VclPtr<T1> const & p1, VclPtr<T2> const & p2) {
243 return !(p1 == p2);
244}
245
246template<typename T> inline bool operator !=(VclPtr<T> const & p1, T const * p2)
247{
248 return !(p1 == p2);
249}
250
251template<typename T> inline bool operator !=(VclPtr<T> const & p1, T * p2) {
252 return !(p1 == p2);
253}
254
255template<typename T> inline bool operator !=(T const * p1, VclPtr<T> const & p2)
256{
257 return !(p1 == p2);
258}
259
260template<typename T> inline bool operator !=(T * p1, VclPtr<T> const & p2) {
261 return !(p1 == p2);
262}
263
264/**
265 * A construction helper for a temporary VclPtr. Since VclPtr types
266 * are created with a reference-count of one - to help fit into
267 * the existing code-flow; this helps us to construct them easily.
268 * see also VclPtr::Create and ScopedVclPtr
269 *
270 * For more details on the design please see vcl/README.lifecycle
271 *
272 * @param reference_type must be a subclass of vcl::Window
273 */
274template <class reference_type>
275class SAL_WARN_UNUSED__attribute__((warn_unused)) VclPtrInstance final : public VclPtr<reference_type>
276{
277public:
278 template<typename... Arg> VclPtrInstance(Arg &&... arg)
279 : VclPtr<reference_type>( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE )
280 {
281 }
282
283 /**
284 * Override and disallow this, to prevent people accidentally calling it and actually
285 * getting VclPtr::Create and getting a naked VclPtr<> instance
286 */
287 template<typename... Arg> static VclPtrInstance< reference_type > Create(Arg &&... ) = delete;
288};
289
290template <class reference_type>
291class ScopedVclPtr : public VclPtr<reference_type>
292{
293public:
294 /** Constructor...
295 */
296 ScopedVclPtr()
297 : VclPtr<reference_type>()
298 {}
299
300 /** Constructor
301 */
302 ScopedVclPtr (reference_type * pBody)
303 : VclPtr<reference_type>(pBody)
304 {}
305
306 /** Copy constructor...
307 */
308 ScopedVclPtr (const VclPtr<reference_type> & handle)
309 : VclPtr<reference_type>(handle)
310 {}
311
312 /**
313 Assignment that releases the last reference.
314 */
315 void disposeAndReset(reference_type *pBody)
316 {
317 if (pBody != this->get()) {
318 VclPtr<reference_type>::disposeAndClear();
319 VclPtr<reference_type>::set(pBody);
320 }
321 }
322
323 /**
324 Assignment that releases the last reference.
325 */
326 ScopedVclPtr<reference_type>& operator = (reference_type * pBody)
327 {
328 disposeAndReset(pBody);
329 return *this;
330 }
331
332 /** Up-casting conversion constructor: Copies interface reference.
333
334 Does not work for up-casts to ambiguous bases. For the special case of
335 up-casting to Reference< XInterface >, see the corresponding conversion
336 operator.
337
338 @param rRef another reference
339 */
340 template< class derived_type >
341 ScopedVclPtr(
342 const VclPtr< derived_type > & rRef,
343 typename std::enable_if<
344 std::is_base_of<reference_type, derived_type>::value, int>::type
345 = 0 )
346 : VclPtr<reference_type>( rRef )
347 {
348 }
349
350 /** Up-casting assignment operator.
351
352 Does not work for up-casts to ambiguous bases.
353
354 @param rRef another VclPtr
355 */
356 template<typename derived_type>
357 typename std::enable_if<
358 std::is_base_of<reference_type, derived_type>::value,
359 ScopedVclPtr &>::type
360 operator =(VclPtr<derived_type> const & rRef)
361 {
362 disposeAndReset(rRef.get());
363 return *this;
364 }
365
366 /**
367 * Override and disallow this, to prevent people accidentally calling it and actually
368 * getting VclPtr::Create and getting a naked VclPtr<> instance
369 */
370 template<typename... Arg> static ScopedVclPtr< reference_type > Create(Arg &&... ) = delete;
371
372 ~ScopedVclPtr()
373 {
374 VclPtr<reference_type>::disposeAndClear();
22
Calling 'VclPtr::disposeAndClear'
375 assert(VclPtr<reference_type>::get() == nullptr)(static_cast <bool> (VclPtr<reference_type>::get(
) == nullptr) ? void (0) : __assert_fail ("VclPtr<reference_type>::get() == nullptr"
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 375, __extension__ __PRETTY_FUNCTION__))
; // make sure there are no lingering references
376 }
377
378private:
379 // Most likely we don't want this default copy-constructor.
380 ScopedVclPtr (const ScopedVclPtr<reference_type> &) = delete;
381 // And certainly we don't want a default assignment operator.
382 ScopedVclPtr<reference_type>& operator = (const ScopedVclPtr<reference_type> &) = delete;
383 // And disallow reset as that doesn't call disposeAndClear on the original reference
384 void reset() = delete;
385 void reset(reference_type *pBody) = delete;
386
387protected:
388 ScopedVclPtr (reference_type * pBody, __sal_NoAcquire)
389 : VclPtr<reference_type>(pBody, SAL_NO_ACQUIRE)
390 {}
391};
392
393/**
394 * A construction helper for ScopedVclPtr. Since VclPtr types are created
395 * with a reference-count of one - to help fit into the existing
396 * code-flow; this helps us to construct them easily.
397 *
398 * For more details on the design please see vcl/README.lifecycle
399 *
400 * @param reference_type must be a subclass of vcl::Window
401 */
402#if defined _MSC_VER
403#pragma warning(push)
404#pragma warning(disable: 4521) // " multiple copy constructors specified"
405#endif
406template <class reference_type>
407class SAL_WARN_UNUSED__attribute__((warn_unused)) ScopedVclPtrInstance final : public ScopedVclPtr<reference_type>
408{
409public:
410 template<typename... Arg> ScopedVclPtrInstance(Arg &&... arg)
411 : ScopedVclPtr<reference_type>( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE )
17
Memory is allocated
412 {
413 }
414
415 /**
416 * Override and disallow this, to prevent people accidentally calling it and actually
417 * getting VclPtr::Create and getting a naked VclPtr<> instance
418 */
419 template<typename... Arg> static ScopedVclPtrInstance< reference_type > Create(Arg &&...) = delete;
420
421private:
422 // Prevent the above perfect forwarding ctor from hijacking (accidental)
423 // attempts at ScopedVclPtrInstance copy construction (where the hijacking
424 // would typically lead to somewhat obscure error messages); both non-const
425 // and const variants are needed here, as the ScopedVclPtr base class has a
426 // const--variant copy ctor, so the implicitly declared copy ctor for
427 // ScopedVclPtrInstance would also be the const variant, so non-const copy
428 // construction attempts would be hijacked by the perfect forwarding ctor;
429 // but if we only declared a non-const variant here, the const variant would
430 // no longer be implicitly declared (as there would already be an explicitly
431 // declared copy ctor), so const copy construction attempts would then be
432 // hijacked by the perfect forwarding ctor:
433 ScopedVclPtrInstance(ScopedVclPtrInstance &) = delete;
434 ScopedVclPtrInstance(ScopedVclPtrInstance const &) = delete;
435};
436#if defined _MSC_VER
437#pragma warning(pop)
438#endif
439
440#endif // INCLUDED_VCL_PTR_HXX
441
442/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/include/rtl/ref.hxx

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#ifndef INCLUDED_RTL_REF_HXX
21#define INCLUDED_RTL_REF_HXX
22
23#include "sal/config.h"
24
25#include <cassert>
26#include <cstddef>
27#include <functional>
28#ifdef LIBO_INTERNAL_ONLY1
29#include <type_traits>
30#endif
31
32#include "sal/types.h"
33
34namespace rtl
35{
36
37/** Template reference class for reference type.
38*/
39template <class reference_type>
40class Reference
41{
42 /** The <b>reference_type</b> body pointer.
43 */
44 reference_type * m_pBody;
45
46
47public:
48 /** Constructor...
49 */
50 Reference()
51 : m_pBody (NULL__null)
52 {}
53
54
55 /** Constructor...
56 */
57 Reference (reference_type * pBody, __sal_NoAcquire)
58 : m_pBody (pBody)
59 {
60 }
61
62 /** Constructor...
63 */
64 Reference (reference_type * pBody)
65 : m_pBody (pBody)
66 {
67 if (m_pBody)
68 m_pBody->acquire();
69 }
70
71 /** Copy constructor...
72 */
73 Reference (const Reference<reference_type> & handle)
74 : m_pBody (handle.m_pBody)
75 {
76 if (m_pBody)
77 m_pBody->acquire();
78 }
79
80#ifdef LIBO_INTERNAL_ONLY1
81 /** Move constructor...
82 */
83 Reference (Reference<reference_type> && handle) noexcept
84 : m_pBody (handle.m_pBody)
85 {
86 handle.m_pBody = nullptr;
87 }
88#endif
89
90#if defined LIBO_INTERNAL_ONLY1
91 /** Up-casting conversion constructor: Copies interface reference.
92
93 Does not work for up-casts to ambiguous bases.
94
95 @param rRef another reference
96 */
97 template< class derived_type >
98 inline Reference(
99 const Reference< derived_type > & rRef,
100 std::enable_if_t<std::is_base_of_v<reference_type, derived_type>, int> = 0 )
101 : m_pBody (rRef.get())
102 {
103 if (m_pBody)
104 m_pBody->acquire();
105 }
106#endif
107
108 /** Destructor...
109 */
110 ~Reference() COVERITY_NOEXCEPT_FALSE
111 {
112 if (m_pBody)
113 m_pBody->release();
114 }
115
116 /** Set...
117 Similar to assignment.
118 */
119 Reference<reference_type> &
120 SAL_CALL set (reference_type * pBody)
121 {
122 if (pBody)
123 pBody->acquire();
124 reference_type * const pOld = m_pBody;
125 m_pBody = pBody;
126 if (pOld)
127 pOld->release();
128 return *this;
129 }
130
131 /** Assignment.
132 Unbinds this instance from its body (if bound) and
133 bind it to the body represented by the handle.
134 */
135 Reference<reference_type> &
136 SAL_CALL operator= (const Reference<reference_type> & handle)
137 {
138 return set( handle.m_pBody );
139 }
140
141#ifdef LIBO_INTERNAL_ONLY1
142 /** Assignment.
143 * Unbinds this instance from its body (if bound),
144 * bind it to the body represented by the handle, and
145 * set the body represented by the handle to nullptr.
146 */
147 Reference<reference_type> &
148 operator= (Reference<reference_type> && handle)
149 {
150 // self-movement guts ourself
151 if (m_pBody)
152 m_pBody->release();
153 m_pBody = handle.m_pBody;
154 handle.m_pBody = nullptr;
155 return *this;
156 }
157#endif
158
159 /** Assignment...
160 */
161 Reference<reference_type> &
162 SAL_CALL operator= (reference_type * pBody)
163 {
164 return set( pBody );
165 }
166
167 /** Unbind the body from this handle.
168 Note that for a handle representing a large body,
169 "handle.clear().set(new body());" _might_
170 perform a little bit better than "handle.set(new body());",
171 since in the second case two large objects exist in memory
172 (the old body and the new body).
173 */
174 Reference<reference_type> & SAL_CALL clear()
175 {
176 if (m_pBody
23.1
Field 'm_pBody' is non-null
23.1
Field 'm_pBody' is non-null
23.1
Field 'm_pBody' is non-null
23.1
Field 'm_pBody' is non-null
)
24
Taking true branch
177 {
178 reference_type * const pOld = m_pBody;
179 m_pBody = NULL__null;
180 pOld->release();
25
Calling 'VclReferenceBase::release'
29
Returning; memory was released
181 }
182 return *this;
183 }
184
185
186 /** Get the body. Can be used instead of operator->().
187 I.e. handle->someBodyOp() and handle.get()->someBodyOp()
188 are the same.
189 */
190 reference_type * SAL_CALL get() const
191 {
192 return m_pBody;
32
Use of memory after it is freed
193 }
194
195
196 /** Probably most common used: handle->someBodyOp().
197 */
198 reference_type * SAL_CALL operator->() const
199 {
200 assert(m_pBody != NULL)(static_cast <bool> (m_pBody != __null) ? void (0) : __assert_fail
("m_pBody != NULL", "/home/maarten/src/libreoffice/core/include/rtl/ref.hxx"
, 200, __extension__ __PRETTY_FUNCTION__))
;
201 return m_pBody;
202 }
203
204
205 /** Allows (*handle).someBodyOp().
206 */
207 reference_type & SAL_CALL operator*() const
208 {
209 assert(m_pBody != NULL)(static_cast <bool> (m_pBody != __null) ? void (0) : __assert_fail
("m_pBody != NULL", "/home/maarten/src/libreoffice/core/include/rtl/ref.hxx"
, 209, __extension__ __PRETTY_FUNCTION__))
;
210 return *m_pBody;
211 }
212
213
214 /** Returns True if the handle does point to a valid body.
215 */
216 bool SAL_CALL is() const
217 {
218 return (m_pBody != NULL__null);
219 }
220
221#if defined LIBO_INTERNAL_ONLY1
222 /** Returns True if the handle does point to a valid body.
223 */
224 explicit operator bool() const
225 {
226 return is();
227 }
228#endif
229
230 /** Returns True if this points to pBody.
231 */
232 bool SAL_CALL operator== (const reference_type * pBody) const
233 {
234 return (m_pBody == pBody);
235 }
236
237
238 /** Returns True if handle points to the same body.
239 */
240 bool
241 SAL_CALL operator== (const Reference<reference_type> & handle) const
242 {
243 return (m_pBody == handle.m_pBody);
244 }
245
246
247 /** Needed to place References into STL collection.
248 */
249 bool
250 SAL_CALL operator!= (const Reference<reference_type> & handle) const
251 {
252 return (m_pBody != handle.m_pBody);
253 }
254
255
256 /** Needed to place References into STL collection.
257 */
258 bool
259 SAL_CALL operator< (const Reference<reference_type> & handle) const
260 {
261 return (m_pBody < handle.m_pBody);
262 }
263
264
265 /** Needed to place References into STL collection.
266 */
267 bool
268 SAL_CALL operator> (const Reference<reference_type> & handle) const
269 {
270 return (m_pBody > handle.m_pBody);
271 }
272};
273
274} // namespace rtl
275
276#if defined LIBO_INTERNAL_ONLY1
277namespace std
278{
279
280/// @cond INTERNAL
281/**
282 Make rtl::Reference hashable by default for use in STL containers.
283
284 @since LibreOffice 6.3
285*/
286template<typename T>
287struct hash<::rtl::Reference<T>>
288{
289 std::size_t operator()(::rtl::Reference<T> const & s) const
290 { return std::size_t(s.get()); }
291};
292/// @endcond
293
294}
295
296#endif
297
298#endif /* ! INCLUDED_RTL_REF_HXX */
299
300/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/include/vcl/vclreferencebase.hxx

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#ifndef INCLUDED_VCL_Reference_HXX
20#define INCLUDED_VCL_Reference_HXX
21
22#include <vcl/dllapi.h>
23#include <osl/interlck.h>
24
25class VCL_DLLPUBLIC__attribute__ ((visibility("default"))) VclReferenceBase
26{
27 mutable oslInterlockedCount mnRefCnt;
28
29 template<typename T> friend class VclPtr;
30
31public:
32 void acquire() const
33 {
34 osl_atomic_increment(&mnRefCnt)__sync_add_and_fetch((&mnRefCnt), 1);
35 }
36
37 void release() const
38 {
39 if (osl_atomic_decrement(&mnRefCnt)__sync_sub_and_fetch((&mnRefCnt), 1) == 0)
26
Assuming the condition is true
27
Taking true branch
40 delete this;
28
Memory is released
41 }
42#ifdef DBG_UTIL
43#ifndef _WIN32
44 sal_Int32 getRefCount() const { return mnRefCnt; }
45#endif
46#endif
47
48
49private:
50 VclReferenceBase(const VclReferenceBase&) = delete;
51 VclReferenceBase& operator=(const VclReferenceBase&) = delete;
52
53 bool mbDisposed : 1;
54
55protected:
56 VclReferenceBase();
57protected:
58 virtual ~VclReferenceBase();
59
60protected:
61 virtual void dispose();
62
63public:
64 void disposeOnce();
65 bool isDisposed() const { return mbDisposed; }
66
67};
68#endif