Bug Summary

File:home/maarten/src/libreoffice/core/include/rtl/ref.hxx
Warning:line 123, column 13
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 print.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/gdi/print.cxx

/home/maarten/src/libreoffice/core/vcl/source/gdi/print.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 <sal/types.h>
21#include <sal/log.hxx>
22
23#include <tools/helpers.hxx>
24#include <tools/debug.hxx>
25
26#include <vcl/QueueInfo.hxx>
27#include <vcl/event.hxx>
28#include <vcl/virdev.hxx>
29#include <vcl/print.hxx>
30
31#include <comphelper/processfactory.hxx>
32
33#include <salinst.hxx>
34#include <salvd.hxx>
35#include <salgdi.hxx>
36#include <salptype.hxx>
37#include <salprn.hxx>
38#include <svdata.hxx>
39#include <print.hrc>
40#include <jobset.h>
41#include <outdev.h>
42#include <PhysicalFontCollection.hxx>
43#include <print.h>
44
45#include <com/sun/star/beans/XPropertySet.hpp>
46#include <com/sun/star/configuration/theDefaultProvider.hpp>
47#include <com/sun/star/container/XNameAccess.hpp>
48#include <com/sun/star/lang/XMultiServiceFactory.hpp>
49#include <com/sun/star/uno/Sequence.h>
50
51int nImplSysDialog = 0;
52
53namespace
54{
55 Paper ImplGetPaperFormat( long nWidth100thMM, long nHeight100thMM )
56 {
57 PaperInfo aInfo(nWidth100thMM, nHeight100thMM);
58 aInfo.doSloppyFit();
59 return aInfo.getPaper();
60 }
61
62 const PaperInfo& ImplGetEmptyPaper()
63 {
64 static PaperInfo aInfo(PAPER_USER);
65 return aInfo;
66 }
67}
68
69void ImplUpdateJobSetupPaper( JobSetup& rJobSetup )
70{
71 const ImplJobSetup& rConstData = rJobSetup.ImplGetConstData();
72
73 if ( !rConstData.GetPaperWidth() || !rConstData.GetPaperHeight() )
74 {
75 if ( rConstData.GetPaperFormat() != PAPER_USER )
76 {
77 PaperInfo aInfo(rConstData.GetPaperFormat());
78
79 ImplJobSetup& rData = rJobSetup.ImplGetData();
80 rData.SetPaperWidth( aInfo.getWidth() );
81 rData.SetPaperHeight( aInfo.getHeight() );
82 }
83 }
84 else if ( rConstData.GetPaperFormat() == PAPER_USER )
85 {
86 Paper ePaper = ImplGetPaperFormat( rConstData.GetPaperWidth(), rConstData.GetPaperHeight() );
87 if ( ePaper != PAPER_USER )
88 rJobSetup.ImplGetData().SetPaperFormat(ePaper);
89 }
90}
91
92// PrinterOptions
93PrinterOptions::PrinterOptions() :
94 mbReduceTransparency( false ),
95 meReducedTransparencyMode( PrinterTransparencyMode::Auto ),
96 mbReduceGradients( false ),
97 meReducedGradientsMode( PrinterGradientMode::Stripes ),
98 mnReducedGradientStepCount( 64 ),
99 mbReduceBitmaps( false ),
100 meReducedBitmapMode( PrinterBitmapMode::Normal ),
101 mnReducedBitmapResolution( 200 ),
102 mbReducedBitmapsIncludeTransparency( true ),
103 mbConvertToGreyscales( false ),
104 mbPDFAsStandardPrintJobFormat( false )
105{
106}
107
108void PrinterOptions::ReadFromConfig( bool i_bFile )
109{
110 bool bSuccess = false;
111 // save old state in case something goes wrong
112 PrinterOptions aOldValues( *this );
113
114 // get the configuration service
115 css::uno::Reference< css::lang::XMultiServiceFactory > xConfigProvider;
116 css::uno::Reference< css::container::XNameAccess > xConfigAccess;
117 try
118 {
119 // get service provider
120 css::uno::Reference< css::uno::XComponentContext > xContext( comphelper::getProcessComponentContext() );
121 // create configuration hierarchical access name
122 try
123 {
124 xConfigProvider = css::configuration::theDefaultProvider::get( xContext );
125
126 css::uno::Sequence< css::uno::Any > aArgs(1);
127 css::beans::PropertyValue aVal;
128 aVal.Name = "nodepath";
129 if( i_bFile )
130 aVal.Value <<= OUString( "/org.openoffice.Office.Common/Print/Option/File" );
131 else
132 aVal.Value <<= OUString( "/org.openoffice.Office.Common/Print/Option/Printer" );
133 aArgs.getArray()[0] <<= aVal;
134 xConfigAccess.set(
135 xConfigProvider->createInstanceWithArguments(
136 "com.sun.star.configuration.ConfigurationAccess", aArgs ),
137 css::uno::UNO_QUERY );
138 if( xConfigAccess.is() )
139 {
140 css::uno::Reference< css::beans::XPropertySet > xSet( xConfigAccess, css::uno::UNO_QUERY );
141 if( xSet.is() )
142 {
143 sal_Int32 nValue = 0;
144 bool bValue = false;
145 if( xSet->getPropertyValue("ReduceTransparency") >>= bValue )
146 SetReduceTransparency( bValue );
147 if( xSet->getPropertyValue("ReducedTransparencyMode") >>= nValue )
148 SetReducedTransparencyMode( static_cast<PrinterTransparencyMode>(nValue) );
149 if( xSet->getPropertyValue("ReduceGradients") >>= bValue )
150 SetReduceGradients( bValue );
151 if( xSet->getPropertyValue("ReducedGradientMode") >>= nValue )
152 SetReducedGradientMode( static_cast<PrinterGradientMode>(nValue) );
153 if( xSet->getPropertyValue("ReducedGradientStepCount") >>= nValue )
154 SetReducedGradientStepCount( static_cast<sal_uInt16>(nValue) );
155 if( xSet->getPropertyValue("ReduceBitmaps") >>= bValue )
156 SetReduceBitmaps( bValue );
157 if( xSet->getPropertyValue("ReducedBitmapMode") >>= nValue )
158 SetReducedBitmapMode( static_cast<PrinterBitmapMode>(nValue) );
159 if( xSet->getPropertyValue("ReducedBitmapResolution") >>= nValue )
160 SetReducedBitmapResolution( static_cast<sal_uInt16>(nValue) );
161 if( xSet->getPropertyValue("ReducedBitmapIncludesTransparency") >>= bValue )
162 SetReducedBitmapIncludesTransparency( bValue );
163 if( xSet->getPropertyValue("ConvertToGreyscales") >>= bValue )
164 SetConvertToGreyscales( bValue );
165 if( xSet->getPropertyValue("PDFAsStandardPrintJobFormat") >>= bValue )
166 SetPDFAsStandardPrintJobFormat( bValue );
167
168 bSuccess = true;
169 }
170 }
171 }
172 catch( const css::uno::Exception& )
173 {
174 }
175 }
176 catch( const css::lang::WrappedTargetException& )
177 {
178 }
179
180 if( ! bSuccess )
181 *this = aOldValues;
182}
183
184bool Printer::DrawTransformBitmapExDirect(
185 const basegfx::B2DHomMatrix& /*aFullTransform*/,
186 const BitmapEx& /*rBitmapEx*/)
187{
188 // printers can't draw bitmaps directly
189 return false;
190}
191
192bool Printer::TransformAndReduceBitmapExToTargetRange(
193 const basegfx::B2DHomMatrix& /*aFullTransform*/,
194 basegfx::B2DRange& /*aVisibleRange*/,
195 double& /*fMaximumArea*/)
196{
197 // deliberately do nothing - you can't reduce the
198 // target range for a printer at all
199 return true;
200}
201
202void Printer::DrawDeviceBitmap( const Point& rDestPt, const Size& rDestSize,
203 const Point& rSrcPtPixel, const Size& rSrcSizePixel,
204 BitmapEx& rBmpEx )
205{
206 if( rBmpEx.IsAlpha() )
207 {
208 // #107169# For true alpha bitmaps, no longer masking the
209 // bitmap, but perform a full alpha blend against a white
210 // background here.
211 Bitmap aBmp( rBmpEx.GetBitmap() );
212 aBmp.Blend( rBmpEx.GetAlpha(), COL_WHITE );
213 DrawBitmap( rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel, aBmp );
214 }
215 else
216 {
217 Bitmap aBmp( rBmpEx.GetBitmap() ), aMask( rBmpEx.GetMask() );
218 aBmp.Replace( aMask, COL_WHITE );
219 ImplPrintTransparent( aBmp, aMask, rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel );
220 }
221}
222
223void Printer::EmulateDrawTransparent ( const tools::PolyPolygon& rPolyPoly,
224 sal_uInt16 nTransparencePercent )
225{
226 // #110958# Disable alpha VDev, we perform the necessary
227 VirtualDevice* pOldAlphaVDev = mpAlphaVDev;
228
229 // operation explicitly further below.
230 if( mpAlphaVDev )
1
Taking true branch
231 mpAlphaVDev = nullptr;
2
Calling 'VclPtr::operator='
12
Returning; memory was released
232
233 GDIMetaFile* pOldMetaFile = mpMetaFile;
234 mpMetaFile = nullptr;
235
236 mpMetaFile = pOldMetaFile;
237
238 // #110958# Restore disabled alpha VDev
239 mpAlphaVDev = pOldAlphaVDev;
13
Calling 'VclPtr::operator='
240
241 tools::Rectangle aPolyRect( LogicToPixel( rPolyPoly ).GetBoundRect() );
242 const Size aDPISize( LogicToPixel(Size(1, 1), MapMode(MapUnit::MapInch)) );
243 const long nBaseExtent = std::max( FRound( aDPISize.Width() / 300. ), 1L );
244 long nMove;
245 const sal_uInt16 nTrans = ( nTransparencePercent < 13 ) ? 0 :
246 ( nTransparencePercent < 38 ) ? 25 :
247 ( nTransparencePercent < 63 ) ? 50 :
248 ( nTransparencePercent < 88 ) ? 75 : 100;
249
250 switch( nTrans )
251 {
252 case 25: nMove = nBaseExtent * 3; break;
253 case 50: nMove = nBaseExtent * 4; break;
254 case 75: nMove = nBaseExtent * 6; break;
255
256 // #i112959# very transparent (88 < nTransparencePercent <= 99)
257 case 100: nMove = nBaseExtent * 8; break;
258
259 // #i112959# not transparent (nTransparencePercent < 13)
260 default: nMove = 0; break;
261 }
262
263 Push( PushFlags::CLIPREGION | PushFlags::LINECOLOR );
264 IntersectClipRegion(vcl::Region(rPolyPoly));
265 SetLineColor( GetFillColor() );
266 const bool bOldMap = mbMap;
267 EnableMapMode( false );
268
269 if(nMove)
270 {
271 tools::Rectangle aRect( aPolyRect.TopLeft(), Size( aPolyRect.GetWidth(), nBaseExtent ) );
272 while( aRect.Top() <= aPolyRect.Bottom() )
273 {
274 DrawRect( aRect );
275 aRect.Move( 0, nMove );
276 }
277
278 aRect = tools::Rectangle( aPolyRect.TopLeft(), Size( nBaseExtent, aPolyRect.GetHeight() ) );
279 while( aRect.Left() <= aPolyRect.Right() )
280 {
281 DrawRect( aRect );
282 aRect.Move( nMove, 0 );
283 }
284 }
285 else
286 {
287 // #i112959# if not transparent, draw full rectangle in clip region
288 DrawRect( aPolyRect );
289 }
290
291 EnableMapMode( bOldMap );
292 Pop();
293
294 mpMetaFile = pOldMetaFile;
295
296 // #110958# Restore disabled alpha VDev
297 mpAlphaVDev = pOldAlphaVDev;
298}
299
300void Printer::DrawOutDev( const Point& /*rDestPt*/, const Size& /*rDestSize*/,
301 const Point& /*rSrcPt*/, const Size& /*rSrcSize*/ )
302{
303 SAL_WARN( "vcl.gdi", "Don't use OutputDevice::DrawOutDev(...) with printer devices!" )do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "vcl.gdi")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "Don't use OutputDevice::DrawOutDev(...) with printer devices!"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"
), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/print.cxx"
":" "303" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "Don't use OutputDevice::DrawOutDev(...) with printer devices!"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "Don't use OutputDevice::DrawOutDev(...) with printer devices!"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"
), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/print.cxx"
":" "303" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "Don't use OutputDevice::DrawOutDev(...) with printer devices!"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"
), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/print.cxx"
":" "303" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "Don't use OutputDevice::DrawOutDev(...) with printer devices!"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "Don't use OutputDevice::DrawOutDev(...) with printer devices!"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"
), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/print.cxx"
":" "303" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
304}
305
306void Printer::DrawOutDev( const Point& /*rDestPt*/, const Size& /*rDestSize*/,
307 const Point& /*rSrcPt*/, const Size& /*rSrcSize*/,
308 const OutputDevice& /*rOutDev*/ )
309{
310 SAL_WARN( "vcl.gdi", "Don't use OutputDevice::DrawOutDev(...) with printer devices!" )do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "vcl.gdi")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "Don't use OutputDevice::DrawOutDev(...) with printer devices!"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"
), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/print.cxx"
":" "310" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "Don't use OutputDevice::DrawOutDev(...) with printer devices!"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "Don't use OutputDevice::DrawOutDev(...) with printer devices!"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"
), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/print.cxx"
":" "310" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "Don't use OutputDevice::DrawOutDev(...) with printer devices!"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"
), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/print.cxx"
":" "310" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "Don't use OutputDevice::DrawOutDev(...) with printer devices!"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "Don't use OutputDevice::DrawOutDev(...) with printer devices!"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"
), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/print.cxx"
":" "310" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
311}
312
313void Printer::CopyArea( const Point& /*rDestPt*/,
314 const Point& /*rSrcPt*/, const Size& /*rSrcSize*/,
315 bool /*bWindowInvalidate*/ )
316{
317 SAL_WARN( "vcl.gdi", "Don't use OutputDevice::CopyArea(...) with printer devices!" )do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "vcl.gdi")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "Don't use OutputDevice::CopyArea(...) with printer devices!"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"
), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/print.cxx"
":" "317" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "Don't use OutputDevice::CopyArea(...) with printer devices!"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "Don't use OutputDevice::CopyArea(...) with printer devices!"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"
), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/print.cxx"
":" "317" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "Don't use OutputDevice::CopyArea(...) with printer devices!"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"
), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/print.cxx"
":" "317" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "Don't use OutputDevice::CopyArea(...) with printer devices!"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "Don't use OutputDevice::CopyArea(...) with printer devices!"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"
), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/print.cxx"
":" "317" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
318}
319
320tools::Rectangle Printer::GetBackgroundComponentBounds() const
321{
322 Point aPageOffset = Point( 0, 0 ) - this->GetPageOffsetPixel();
323 Size aSize = this->GetPaperSizePixel();
324 return tools::Rectangle( aPageOffset, aSize );
325}
326
327void Printer::SetPrinterOptions( const PrinterOptions& i_rOptions )
328{
329 *mpPrinterOptions = i_rOptions;
330}
331
332bool Printer::HasMirroredGraphics() const
333{
334 // due to a "hotfix" for AOO bug i55719, this needs to return false
335 return false;
336}
337
338SalPrinterQueueInfo::SalPrinterQueueInfo()
339{
340 mnStatus = PrintQueueFlags::NONE;
341 mnJobs = QUEUE_JOBS_DONTKNOW;
342}
343
344SalPrinterQueueInfo::~SalPrinterQueueInfo()
345{
346}
347
348ImplPrnQueueList::~ImplPrnQueueList()
349{
350}
351
352void ImplPrnQueueList::Add( std::unique_ptr<SalPrinterQueueInfo> pData )
353{
354 std::unordered_map< OUString, sal_Int32 >::iterator it =
355 m_aNameToIndex.find( pData->maPrinterName );
356 if( it == m_aNameToIndex.end() )
357 {
358 m_aNameToIndex[ pData->maPrinterName ] = m_aQueueInfos.size();
359 m_aPrinterList.push_back( pData->maPrinterName );
360 m_aQueueInfos.push_back( ImplPrnQueueData() );
361 m_aQueueInfos.back().mpQueueInfo = nullptr;
362 m_aQueueInfos.back().mpSalQueueInfo = std::move(pData);
363 }
364 else // this should not happen, but ...
365 {
366 ImplPrnQueueData& rData = m_aQueueInfos[ it->second ];
367 rData.mpQueueInfo.reset();
368 rData.mpSalQueueInfo = std::move(pData);
369 }
370}
371
372ImplPrnQueueData* ImplPrnQueueList::Get( const OUString& rPrinter )
373{
374 ImplPrnQueueData* pData = nullptr;
375 std::unordered_map<OUString,sal_Int32>::iterator it =
376 m_aNameToIndex.find( rPrinter );
377 if( it != m_aNameToIndex.end() )
378 pData = &m_aQueueInfos[it->second];
379 return pData;
380}
381
382static void ImplInitPrnQueueList()
383{
384 ImplSVData* pSVData = ImplGetSVData();
385
386 pSVData->maGDIData.mpPrinterQueueList.reset(new ImplPrnQueueList);
387
388 static const char* pEnv = getenv( "SAL_DISABLE_PRINTERLIST" );
389 if( !pEnv || !*pEnv )
390 pSVData->mpDefInst->GetPrinterQueueInfo( pSVData->maGDIData.mpPrinterQueueList.get() );
391}
392
393void ImplDeletePrnQueueList()
394{
395 ImplSVData* pSVData = ImplGetSVData();
396 pSVData->maGDIData.mpPrinterQueueList.reset();
397}
398
399const std::vector<OUString>& Printer::GetPrinterQueues()
400{
401 ImplSVData* pSVData = ImplGetSVData();
402 if ( !pSVData->maGDIData.mpPrinterQueueList )
403 ImplInitPrnQueueList();
404 return pSVData->maGDIData.mpPrinterQueueList->m_aPrinterList;
405}
406
407const QueueInfo* Printer::GetQueueInfo( const OUString& rPrinterName, bool bStatusUpdate )
408{
409 ImplSVData* pSVData = ImplGetSVData();
410
411 if ( !pSVData->maGDIData.mpPrinterQueueList )
412 ImplInitPrnQueueList();
413
414 if ( !pSVData->maGDIData.mpPrinterQueueList )
415 return nullptr;
416
417 ImplPrnQueueData* pInfo = pSVData->maGDIData.mpPrinterQueueList->Get( rPrinterName );
418 if( pInfo )
419 {
420 if( !pInfo->mpQueueInfo || bStatusUpdate )
421 pSVData->mpDefInst->GetPrinterQueueState( pInfo->mpSalQueueInfo.get() );
422
423 if ( !pInfo->mpQueueInfo )
424 pInfo->mpQueueInfo.reset(new QueueInfo);
425
426 pInfo->mpQueueInfo->maPrinterName = pInfo->mpSalQueueInfo->maPrinterName;
427 pInfo->mpQueueInfo->maDriver = pInfo->mpSalQueueInfo->maDriver;
428 pInfo->mpQueueInfo->maLocation = pInfo->mpSalQueueInfo->maLocation;
429 pInfo->mpQueueInfo->maComment = pInfo->mpSalQueueInfo->maComment;
430 pInfo->mpQueueInfo->mnStatus = pInfo->mpSalQueueInfo->mnStatus;
431 pInfo->mpQueueInfo->mnJobs = pInfo->mpSalQueueInfo->mnJobs;
432 return pInfo->mpQueueInfo.get();
433 }
434 return nullptr;
435}
436
437OUString Printer::GetDefaultPrinterName()
438{
439 static const char* pEnv = getenv( "SAL_DISABLE_DEFAULTPRINTER" );
440 if( !pEnv || !*pEnv )
441 {
442 ImplSVData* pSVData = ImplGetSVData();
443
444 return pSVData->mpDefInst->GetDefaultPrinter();
445 }
446 return OUString();
447}
448
449void Printer::ImplInitData()
450{
451 mbDevOutput = false;
452 mbDefPrinter = false;
453 mnError = ERRCODE_NONEErrCode(0);
454 mnPageQueueSize = 0;
455 mnCopyCount = 1;
456 mbCollateCopy = false;
457 mbPrinting = false;
458 mbJobActive = false;
459 mbPrintFile = false;
460 mbInPrintPage = false;
461 mbNewJobSetup = false;
462 mpInfoPrinter = nullptr;
463 mpPrinter = nullptr;
464 mpDisplayDev = nullptr;
465 mpPrinterOptions.reset(new PrinterOptions);
466
467 // Add printer to the list
468 ImplSVData* pSVData = ImplGetSVData();
469 mpNext = pSVData->maGDIData.mpFirstPrinter;
470 mpPrev = nullptr;
471 if ( mpNext )
472 mpNext->mpPrev = this;
473 pSVData->maGDIData.mpFirstPrinter = this;
474}
475
476bool Printer::AcquireGraphics() const
477{
478 DBG_TESTSOLARMUTEX()do { DbgTestSolarMutex(); } while(false);
479
480 if ( mpGraphics )
481 return true;
482
483 mbInitLineColor = true;
484 mbInitFillColor = true;
485 mbInitFont = true;
486 mbInitTextColor = true;
487 mbInitClipRegion = true;
488
489 ImplSVData* pSVData = ImplGetSVData();
490
491 if ( mpJobGraphics )
492 mpGraphics = mpJobGraphics;
493 else if ( mpDisplayDev )
494 {
495 const VirtualDevice* pVirDev = mpDisplayDev;
496 mpGraphics = pVirDev->mpVirDev->AcquireGraphics();
497 // if needed retry after releasing least recently used virtual device graphics
498 while ( !mpGraphics )
499 {
500 if ( !pSVData->maGDIData.mpLastVirGraphics )
501 break;
502 pSVData->maGDIData.mpLastVirGraphics->ReleaseGraphics();
503 mpGraphics = pVirDev->mpVirDev->AcquireGraphics();
504 }
505 // update global LRU list of virtual device graphics
506 if ( mpGraphics )
507 {
508 mpNextGraphics = pSVData->maGDIData.mpFirstVirGraphics;
509 pSVData->maGDIData.mpFirstVirGraphics = const_cast<Printer*>(this);
510 if ( mpNextGraphics )
511 mpNextGraphics->mpPrevGraphics = const_cast<Printer*>(this);
512 if ( !pSVData->maGDIData.mpLastVirGraphics )
513 pSVData->maGDIData.mpLastVirGraphics = const_cast<Printer*>(this);
514 }
515 }
516 else
517 {
518 mpGraphics = mpInfoPrinter->AcquireGraphics();
519 // if needed retry after releasing least recently used printer graphics
520 while ( !mpGraphics )
521 {
522 if ( !pSVData->maGDIData.mpLastPrnGraphics )
523 break;
524 pSVData->maGDIData.mpLastPrnGraphics->ReleaseGraphics();
525 mpGraphics = mpInfoPrinter->AcquireGraphics();
526 }
527 // update global LRU list of printer graphics
528 if ( mpGraphics )
529 {
530 mpNextGraphics = pSVData->maGDIData.mpFirstPrnGraphics;
531 pSVData->maGDIData.mpFirstPrnGraphics = const_cast<Printer*>(this);
532 if ( mpNextGraphics )
533 mpNextGraphics->mpPrevGraphics = const_cast<Printer*>(this);
534 if ( !pSVData->maGDIData.mpLastPrnGraphics )
535 pSVData->maGDIData.mpLastPrnGraphics = const_cast<Printer*>(this);
536 }
537 }
538
539 if ( mpGraphics )
540 {
541 mpGraphics->SetXORMode( (RasterOp::Invert == meRasterOp) || (RasterOp::Xor == meRasterOp), RasterOp::Invert == meRasterOp );
542 mpGraphics->setAntiAlias(bool(mnAntialiasing & AntialiasingFlags::Enable));
543 }
544
545 return mpGraphics != nullptr;
546}
547
548void Printer::ImplReleaseFonts()
549{
550#ifdef UNX1
551 // HACK to fix an urgent P1 printing issue fast
552 // WinSalPrinter does not respect GetGraphics/ReleaseGraphics conventions
553 // so Printer::mpGraphics often points to a dead WinSalGraphics
554 // TODO: fix WinSalPrinter's GetGraphics/ReleaseGraphics handling
555 mpGraphics->ReleaseFonts();
556#endif
557 mbNewFont = true;
558 mbInitFont = true;
559
560 mpFontInstance.clear();
561 mpDeviceFontList.reset();
562 mpDeviceFontSizeList.reset();
563}
564
565void Printer::ReleaseGraphics( bool bRelease )
566{
567 DBG_TESTSOLARMUTEX()do { DbgTestSolarMutex(); } while(false);
568
569 if ( !mpGraphics )
570 return;
571
572 // release the fonts of the physically released graphics device
573 if( bRelease )
574 ImplReleaseFonts();
575
576 ImplSVData* pSVData = ImplGetSVData();
577
578 Printer* pPrinter = this;
579
580 if ( !pPrinter->mpJobGraphics )
581 {
582 if ( pPrinter->mpDisplayDev )
583 {
584 VirtualDevice* pVirDev = pPrinter->mpDisplayDev;
585 if ( bRelease )
586 pVirDev->mpVirDev->ReleaseGraphics( mpGraphics );
587 // remove from global LRU list of virtual device graphics
588 if ( mpPrevGraphics )
589 mpPrevGraphics->mpNextGraphics = mpNextGraphics;
590 else
591 pSVData->maGDIData.mpFirstVirGraphics = mpNextGraphics;
592 if ( mpNextGraphics )
593 mpNextGraphics->mpPrevGraphics = mpPrevGraphics;
594 else
595 pSVData->maGDIData.mpLastVirGraphics = mpPrevGraphics;
596 }
597 else
598 {
599 if ( bRelease )
600 pPrinter->mpInfoPrinter->ReleaseGraphics( mpGraphics );
601 // remove from global LRU list of printer graphics
602 if ( mpPrevGraphics )
603 mpPrevGraphics->mpNextGraphics = mpNextGraphics;
604 else
605 pSVData->maGDIData.mpFirstPrnGraphics = mpNextGraphics;
606 if ( mpNextGraphics )
607 mpNextGraphics->mpPrevGraphics = mpPrevGraphics;
608 else
609 pSVData->maGDIData.mpLastPrnGraphics = mpPrevGraphics;
610 }
611 }
612
613 mpGraphics = nullptr;
614 mpPrevGraphics = nullptr;
615 mpNextGraphics = nullptr;
616}
617
618void Printer::ImplInit( SalPrinterQueueInfo* pInfo )
619{
620 ImplSVData* pSVData = ImplGetSVData();
621 // #i74084# update info for this specific SalPrinterQueueInfo
622 pSVData->mpDefInst->GetPrinterQueueState( pInfo );
623
624 // Test whether the driver actually matches the JobSetup
625 ImplJobSetup& rData = maJobSetup.ImplGetData();
626 if ( rData.GetDriverData() )
627 {
628 if ( rData.GetPrinterName() != pInfo->maPrinterName ||
629 rData.GetDriver() != pInfo->maDriver )
630 {
631 std::free( const_cast<sal_uInt8*>(rData.GetDriverData()) );
632 rData.SetDriverData(nullptr);
633 rData.SetDriverDataLen(0);
634 }
635 }
636
637 // Remember printer name
638 maPrinterName = pInfo->maPrinterName;
639 maDriver = pInfo->maDriver;
640
641 // Add printer name to JobSetup
642 rData.SetPrinterName( maPrinterName );
643 rData.SetDriver( maDriver );
644
645 mpInfoPrinter = pSVData->mpDefInst->CreateInfoPrinter( pInfo, &rData );
646 mpPrinter = nullptr;
647 mpJobGraphics = nullptr;
648 ImplUpdateJobSetupPaper( maJobSetup );
649
650 if ( !mpInfoPrinter )
651 {
652 ImplInitDisplay();
653 return;
654 }
655
656 // we need a graphics
657 if ( !AcquireGraphics() )
658 {
659 ImplInitDisplay();
660 return;
661 }
662
663 // Init data
664 ImplUpdatePageData();
665 mxFontCollection = std::make_shared<PhysicalFontCollection>();
666 mxFontCache = std::make_shared<ImplFontCache>();
667 mpGraphics->GetDevFontList(mxFontCollection.get());
668}
669
670void Printer::ImplInitDisplay()
671{
672 ImplSVData* pSVData = ImplGetSVData();
673
674 mpInfoPrinter = nullptr;
675 mpPrinter = nullptr;
676 mpJobGraphics = nullptr;
677
678 mpDisplayDev = VclPtr<VirtualDevice>::Create();
679 mxFontCollection = pSVData->maGDIData.mxScreenFontList;
680 mxFontCache = pSVData->maGDIData.mxScreenFontCache;
681 mnDPIX = mpDisplayDev->mnDPIX;
682 mnDPIY = mpDisplayDev->mnDPIY;
683}
684
685void Printer::DrawDeviceMask( const Bitmap& rMask, const Color& rMaskColor,
686 const Point& rDestPt, const Size& rDestSize,
687 const Point& rSrcPtPixel, const Size& rSrcSizePixel )
688{
689 Point aDestPt( LogicToPixel( rDestPt ) );
690 Size aDestSz( LogicToPixel( rDestSize ) );
691 tools::Rectangle aSrcRect( rSrcPtPixel, rSrcSizePixel );
692
693 aSrcRect.Justify();
694
695 if( !(!rMask.IsEmpty() && aSrcRect.GetWidth() && aSrcRect.GetHeight() && aDestSz.Width() && aDestSz.Height()) )
696 return;
697
698 Bitmap aMask( rMask );
699 BmpMirrorFlags nMirrFlags = BmpMirrorFlags::NONE;
700
701 if( aMask.GetBitCount() > 1 )
702 aMask.Convert( BmpConversion::N1BitThreshold );
703
704 // mirrored horizontically
705 if( aDestSz.Width() < 0 )
706 {
707 aDestSz.setWidth( -aDestSz.Width() );
708 aDestPt.AdjustX( -( aDestSz.Width() - 1 ) );
709 nMirrFlags |= BmpMirrorFlags::Horizontal;
710 }
711
712 // mirrored vertically
713 if( aDestSz.Height() < 0 )
714 {
715 aDestSz.setHeight( -aDestSz.Height() );
716 aDestPt.AdjustY( -( aDestSz.Height() - 1 ) );
717 nMirrFlags |= BmpMirrorFlags::Vertical;
718 }
719
720 // source cropped?
721 if( aSrcRect != tools::Rectangle( Point(), aMask.GetSizePixel() ) )
722 aMask.Crop( aSrcRect );
723
724 // destination mirrored
725 if( nMirrFlags != BmpMirrorFlags::NONE)
726 aMask.Mirror( nMirrFlags );
727
728 // do painting
729 const long nSrcWidth = aSrcRect.GetWidth(), nSrcHeight = aSrcRect.GetHeight();
730 long nX, nY; //, nWorkX, nWorkY, nWorkWidth, nWorkHeight;
731 std::unique_ptr<long[]> pMapX( new long[ nSrcWidth + 1 ] );
732 std::unique_ptr<long[]> pMapY( new long[ nSrcHeight + 1 ] );
733 GDIMetaFile* pOldMetaFile = mpMetaFile;
734 const bool bOldMap = mbMap;
735
736 mpMetaFile = nullptr;
737 mbMap = false;
738 Push( PushFlags::FILLCOLOR | PushFlags::LINECOLOR );
739 SetLineColor( rMaskColor );
740 SetFillColor( rMaskColor );
741 InitLineColor();
742 InitFillColor();
743
744 // create forward mapping tables
745 for( nX = 0; nX <= nSrcWidth; nX++ )
746 pMapX[ nX ] = aDestPt.X() + FRound( static_cast<double>(aDestSz.Width()) * nX / nSrcWidth );
747
748 for( nY = 0; nY <= nSrcHeight; nY++ )
749 pMapY[ nY ] = aDestPt.Y() + FRound( static_cast<double>(aDestSz.Height()) * nY / nSrcHeight );
750
751 // walk through all rectangles of mask
752 const vcl::Region aWorkRgn(aMask.CreateRegion(COL_BLACK, tools::Rectangle(Point(), aMask.GetSizePixel())));
753 RectangleVector aRectangles;
754 aWorkRgn.GetRegionRectangles(aRectangles);
755
756 for (auto const& rectangle : aRectangles)
757 {
758 const Point aMapPt(pMapX[rectangle.Left()], pMapY[rectangle.Top()]);
759 const Size aMapSz(
760 pMapX[rectangle.Right() + 1] - aMapPt.X(), // pMapX[L + W] -> L + ((R - L) + 1) -> R + 1
761 pMapY[rectangle.Bottom() + 1] - aMapPt.Y()); // same for Y
762
763 DrawRect(tools::Rectangle(aMapPt, aMapSz));
764 }
765
766 Pop();
767 mbMap = bOldMap;
768 mpMetaFile = pOldMetaFile;
769}
770
771SalPrinterQueueInfo* Printer::ImplGetQueueInfo( const OUString& rPrinterName,
772 const OUString* pDriver )
773{
774 ImplSVData* pSVData = ImplGetSVData();
775 if ( !pSVData->maGDIData.mpPrinterQueueList )
776 ImplInitPrnQueueList();
777
778 ImplPrnQueueList* pPrnList = pSVData->maGDIData.mpPrinterQueueList.get();
779 if ( pPrnList && !pPrnList->m_aQueueInfos.empty() )
780 {
781 // first search for the printer name directly
782 ImplPrnQueueData* pInfo = pPrnList->Get( rPrinterName );
783 if( pInfo )
784 return pInfo->mpSalQueueInfo.get();
785
786 // then search case insensitive
787 for(const ImplPrnQueueData & rQueueInfo : pPrnList->m_aQueueInfos)
788 {
789 if( rQueueInfo.mpSalQueueInfo->maPrinterName.equalsIgnoreAsciiCase( rPrinterName ) )
790 return rQueueInfo.mpSalQueueInfo.get();
791 }
792
793 // then search for driver name
794 if ( pDriver )
795 {
796 for(const ImplPrnQueueData & rQueueInfo : pPrnList->m_aQueueInfos)
797 {
798 if( rQueueInfo.mpSalQueueInfo->maDriver == *pDriver )
799 return rQueueInfo.mpSalQueueInfo.get();
800 }
801 }
802
803 // then the default printer
804 pInfo = pPrnList->Get( GetDefaultPrinterName() );
805 if( pInfo )
806 return pInfo->mpSalQueueInfo.get();
807
808 // last chance: the first available printer
809 return pPrnList->m_aQueueInfos[0].mpSalQueueInfo.get();
810 }
811
812 return nullptr;
813}
814
815void Printer::ImplUpdatePageData()
816{
817 // we need a graphics
818 if ( !AcquireGraphics() )
819 return;
820
821 mpGraphics->GetResolution( mnDPIX, mnDPIY );
822 mpInfoPrinter->GetPageInfo( &maJobSetup.ImplGetConstData(),
823 mnOutWidth, mnOutHeight,
824 maPageOffset,
825 maPaperSize );
826}
827
828void Printer::ImplUpdateFontList()
829{
830 ImplUpdateFontData();
831}
832
833long Printer::GetGradientStepCount( long nMinRect )
834{
835 // use display-equivalent step size calculation
836 long nInc = (nMinRect < 800) ? 10 : 20;
837
838 return nInc;
839}
840
841Printer::Printer()
842 : OutputDevice(OUTDEV_PRINTER)
843{
844 ImplInitData();
845 SalPrinterQueueInfo* pInfo = ImplGetQueueInfo( GetDefaultPrinterName(), nullptr );
846 if ( pInfo )
847 {
848 ImplInit( pInfo );
849 if ( !IsDisplayPrinter() )
850 mbDefPrinter = true;
851 }
852 else
853 ImplInitDisplay();
854}
855
856Printer::Printer( const JobSetup& rJobSetup )
857 : OutputDevice(OUTDEV_PRINTER)
858 , maJobSetup(rJobSetup)
859{
860 ImplInitData();
861 const ImplJobSetup& rConstData = rJobSetup.ImplGetConstData();
862 OUString aDriver = rConstData.GetDriver();
863 SalPrinterQueueInfo* pInfo = ImplGetQueueInfo( rConstData.GetPrinterName(),
864 &aDriver );
865 if ( pInfo )
866 {
867 ImplInit( pInfo );
868 SetJobSetup( rJobSetup );
869 }
870 else
871 {
872 ImplInitDisplay();
873 maJobSetup = JobSetup();
874 }
875}
876
877Printer::Printer( const QueueInfo& rQueueInfo )
878 : OutputDevice(OUTDEV_PRINTER)
879{
880 ImplInitData();
881 SalPrinterQueueInfo* pInfo = ImplGetQueueInfo( rQueueInfo.GetPrinterName(),
882 &rQueueInfo.GetDriver() );
883 if ( pInfo )
884 ImplInit( pInfo );
885 else
886 ImplInitDisplay();
887}
888
889Printer::Printer( const OUString& rPrinterName )
890 : OutputDevice(OUTDEV_PRINTER)
891{
892 ImplInitData();
893 SalPrinterQueueInfo* pInfo = ImplGetQueueInfo( rPrinterName, nullptr );
894 if ( pInfo )
895 ImplInit( pInfo );
896 else
897 ImplInitDisplay();
898}
899
900Printer::~Printer()
901{
902 disposeOnce();
903}
904
905void Printer::dispose()
906{
907 SAL_WARN_IF( IsPrinting(), "vcl.gdi", "Printer::~Printer() - Job is printing" )do { if (true && (IsPrinting())) { switch (sal_detail_log_report
(::SAL_DETAIL_LOG_LEVEL_WARN, "vcl.gdi")) { case SAL_DETAIL_LOG_ACTION_IGNORE
: break; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail
::getResult( ::sal::detail::StreamStart() << "Printer::~Printer() - Job is printing"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"
), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/print.cxx"
":" "907" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "Printer::~Printer() - Job is printing"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "Printer::~Printer() - Job is printing"; ::sal::detail
::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/print.cxx"
":" "907" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "Printer::~Printer() - Job is printing") == 1) { ::
sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"), (
"/home/maarten/src/libreoffice/core/vcl/source/gdi/print.cxx"
":" "907" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "Printer::~Printer() - Job is printing"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "Printer::~Printer() - Job is printing"; ::sal::detail
::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/print.cxx"
":" "907" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
908 SAL_WARN_IF( IsJobActive(), "vcl.gdi", "Printer::~Printer() - Job is active" )do { if (true && (IsJobActive())) { switch (sal_detail_log_report
(::SAL_DETAIL_LOG_LEVEL_WARN, "vcl.gdi")) { case SAL_DETAIL_LOG_ACTION_IGNORE
: break; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail
::getResult( ::sal::detail::StreamStart() << "Printer::~Printer() - Job is active"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"
), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/print.cxx"
":" "908" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "Printer::~Printer() - Job is active")
, 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "Printer::~Printer() - Job is active"; ::sal::detail
::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/print.cxx"
":" "908" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "Printer::~Printer() - Job is active") == 1) { ::
sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"), (
"/home/maarten/src/libreoffice/core/vcl/source/gdi/print.cxx"
":" "908" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "Printer::~Printer() - Job is active")
, 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "Printer::~Printer() - Job is active"; ::sal::detail
::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/print.cxx"
":" "908" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
909
910 mpPrinterOptions.reset();
911
912 ReleaseGraphics();
913 if ( mpInfoPrinter )
914 ImplGetSVData()->mpDefInst->DestroyInfoPrinter( mpInfoPrinter );
915 if ( mpDisplayDev )
916 mpDisplayDev.disposeAndClear();
917 else
918 {
919 // OutputDevice Dtor is trying the same thing; that why we need to set
920 // the FontEntry to NULL here
921 // TODO: consolidate duplicate cleanup by Printer and OutputDevice
922 mpFontInstance.clear();
923 mpDeviceFontList.reset();
924 mpDeviceFontSizeList.reset();
925 mxFontCache.reset();
926 // font list deleted by OutputDevice dtor
927 }
928
929 // Add printer from the list
930 ImplSVData* pSVData = ImplGetSVData();
931 if ( mpPrev )
932 mpPrev->mpNext = mpNext;
933 else
934 pSVData->maGDIData.mpFirstPrinter = mpNext;
935 if ( mpNext )
936 mpNext->mpPrev = mpPrev;
937
938 mpPrev.clear();
939 mpNext.clear();
940 OutputDevice::dispose();
941}
942
943Size Printer::GetButtonBorderSize()
944{
945 Size aBrdSize(LogicToPixel(Size(20, 20), MapMode(MapUnit::Map100thMM)));
946
947 if (!aBrdSize.Width())
948 aBrdSize.setWidth(1);
949
950 if (!aBrdSize.Height())
951 aBrdSize.setHeight(1);
952
953 return aBrdSize;
954}
955
956sal_uInt32 Printer::GetCapabilities( PrinterCapType nType ) const
957{
958 if ( IsDisplayPrinter() )
959 return 0;
960
961 if( mpInfoPrinter )
962 return mpInfoPrinter->GetCapabilities( &maJobSetup.ImplGetConstData(), nType );
963 else
964 return 0;
965}
966
967bool Printer::HasSupport( PrinterSupport eFeature ) const
968{
969 switch ( eFeature )
970 {
971 case PrinterSupport::SetOrientation:
972 return GetCapabilities( PrinterCapType::SetOrientation ) != 0;
973 case PrinterSupport::SetPaperSize:
974 return GetCapabilities( PrinterCapType::SetPaperSize ) != 0;
975 case PrinterSupport::SetPaper:
976 return GetCapabilities( PrinterCapType::SetPaper ) != 0;
977 case PrinterSupport::CollateCopy:
978 return (GetCapabilities( PrinterCapType::CollateCopies ) != 0);
979 case PrinterSupport::SetupDialog:
980 return GetCapabilities( PrinterCapType::SupportDialog ) != 0;
981 }
982
983 return true;
984}
985
986bool Printer::SetJobSetup( const JobSetup& rSetup )
987{
988 if ( IsDisplayPrinter() || mbInPrintPage )
989 return false;
990
991 JobSetup aJobSetup = rSetup;
992
993 ReleaseGraphics();
994 if ( mpInfoPrinter->SetPrinterData( &aJobSetup.ImplGetData() ) )
995 {
996 ImplUpdateJobSetupPaper( aJobSetup );
997 mbNewJobSetup = true;
998 maJobSetup = aJobSetup;
999 ImplUpdatePageData();
1000 ImplUpdateFontList();
1001 return true;
1002 }
1003
1004 return false;
1005}
1006
1007bool Printer::Setup(weld::Window* pWindow, PrinterSetupMode eMode)
1008{
1009 if ( IsDisplayPrinter() )
1010 return false;
1011
1012 if ( IsJobActive() || IsPrinting() )
1013 return false;
1014
1015 JobSetup aJobSetup = maJobSetup;
1016 ImplJobSetup& rData = aJobSetup.ImplGetData();
1017 rData.SetPrinterSetupMode( eMode );
1018 // TODO: orig page size
1019
1020 if (!pWindow)
1021 {
1022 vcl::Window* pDefWin = ImplGetDefaultWindow();
1023 pWindow = pDefWin ? pDefWin->GetFrameWeld() : nullptr;
1024 }
1025 if( !pWindow )
1026 return false;
1027
1028 ReleaseGraphics();
1029 ImplSVData* pSVData = ImplGetSVData();
1030 pSVData->maAppData.mnModalMode++;
1031 nImplSysDialog++;
1032 bool bSetup = mpInfoPrinter->Setup(pWindow, &rData);
1033 pSVData->maAppData.mnModalMode--;
1034 nImplSysDialog--;
1035 if ( bSetup )
1036 {
1037 ImplUpdateJobSetupPaper( aJobSetup );
1038 mbNewJobSetup = true;
1039 maJobSetup = aJobSetup;
1040 ImplUpdatePageData();
1041 ImplUpdateFontList();
1042 return true;
1043 }
1044 return false;
1045}
1046
1047bool Printer::SetPrinterProps( const Printer* pPrinter )
1048{
1049 if ( IsJobActive() || IsPrinting() )
1050 return false;
1051
1052 ImplSVData* pSVData = ImplGetSVData();
1053
1054 mbDefPrinter = pPrinter->mbDefPrinter;
1055 maPrintFile = pPrinter->maPrintFile;
1056 mbPrintFile = pPrinter->mbPrintFile;
1057 mnCopyCount = pPrinter->mnCopyCount;
1058 mbCollateCopy = pPrinter->mbCollateCopy;
1059 mnPageQueueSize = pPrinter->mnPageQueueSize;
1060 *mpPrinterOptions = *pPrinter->mpPrinterOptions;
1061
1062 if ( pPrinter->IsDisplayPrinter() )
1063 {
1064 // Destroy old printer
1065 if ( !IsDisplayPrinter() )
1066 {
1067 ReleaseGraphics();
1068 pSVData->mpDefInst->DestroyInfoPrinter( mpInfoPrinter );
1069 mpFontInstance.clear();
1070 mpDeviceFontList.reset();
1071 mpDeviceFontSizeList.reset();
1072 // clean up font list
1073 mxFontCache.reset();
1074 mxFontCollection.reset();
1075
1076 mbInitFont = true;
1077 mbNewFont = true;
1078 mpInfoPrinter = nullptr;
1079 }
1080
1081 // Construct new printer
1082 ImplInitDisplay();
1083 return true;
1084 }
1085
1086 // Destroy old printer?
1087 if ( GetName() != pPrinter->GetName() )
1088 {
1089 ReleaseGraphics();
1090 if ( mpDisplayDev )
1091 {
1092 mpDisplayDev.disposeAndClear();
1093 }
1094 else
1095 {
1096 pSVData->mpDefInst->DestroyInfoPrinter( mpInfoPrinter );
1097
1098 mpFontInstance.clear();
1099 mpDeviceFontList.reset();
1100 mpDeviceFontSizeList.reset();
1101 mxFontCache.reset();
1102 mxFontCollection.reset();
1103 mbInitFont = true;
1104 mbNewFont = true;
1105 mpInfoPrinter = nullptr;
1106 }
1107
1108 // Construct new printer
1109 OUString aDriver = pPrinter->GetDriverName();
1110 SalPrinterQueueInfo* pInfo = ImplGetQueueInfo( pPrinter->GetName(), &aDriver );
1111 if ( pInfo )
1112 {
1113 ImplInit( pInfo );
1114 SetJobSetup( pPrinter->GetJobSetup() );
1115 }
1116 else
1117 ImplInitDisplay();
1118 }
1119 else
1120 SetJobSetup( pPrinter->GetJobSetup() );
1121
1122 return false;
1123}
1124
1125bool Printer::SetOrientation( Orientation eOrientation )
1126{
1127 if ( mbInPrintPage )
1128 return false;
1129
1130 if ( maJobSetup.ImplGetConstData().GetOrientation() != eOrientation )
1131 {
1132 JobSetup aJobSetup = maJobSetup;
1133 ImplJobSetup& rData = aJobSetup.ImplGetData();
1134
1135 rData.SetOrientation(eOrientation);
1136
1137 if ( IsDisplayPrinter() )
1138 {
1139 mbNewJobSetup = true;
1140 maJobSetup = aJobSetup;
1141 return true;
1142 }
1143
1144 ReleaseGraphics();
1145 if ( mpInfoPrinter->SetData( JobSetFlags::ORIENTATION, &rData ) )
1146 {
1147 ImplUpdateJobSetupPaper( aJobSetup );
1148 mbNewJobSetup = true;
1149 maJobSetup = aJobSetup;
1150 ImplUpdatePageData();
1151 ImplUpdateFontList();
1152 return true;
1153 }
1154 else
1155 return false;
1156 }
1157
1158 return true;
1159}
1160
1161Orientation Printer::GetOrientation() const
1162{
1163 return maJobSetup.ImplGetConstData().GetOrientation();
1164}
1165
1166bool Printer::SetPaperBin( sal_uInt16 nPaperBin )
1167{
1168 if ( mbInPrintPage )
1169 return false;
1170
1171 if ( maJobSetup.ImplGetConstData().GetPaperBin() != nPaperBin &&
1172 nPaperBin < GetPaperBinCount() )
1173 {
1174 JobSetup aJobSetup = maJobSetup;
1175 ImplJobSetup& rData = aJobSetup.ImplGetData();
1176 rData.SetPaperBin(nPaperBin);
1177
1178 if ( IsDisplayPrinter() )
1179 {
1180 mbNewJobSetup = true;
1181 maJobSetup = aJobSetup;
1182 return true;
1183 }
1184
1185 ReleaseGraphics();
1186 if ( mpInfoPrinter->SetData( JobSetFlags::PAPERBIN, &rData ) )
1187 {
1188 ImplUpdateJobSetupPaper( aJobSetup );
1189 mbNewJobSetup = true;
1190 maJobSetup = aJobSetup;
1191 ImplUpdatePageData();
1192 ImplUpdateFontList();
1193 return true;
1194 }
1195 else
1196 return false;
1197 }
1198
1199 return true;
1200}
1201
1202sal_uInt16 Printer::GetPaperBin() const
1203{
1204 return maJobSetup.ImplGetConstData().GetPaperBin();
1205}
1206
1207bool Printer::GetPrinterSettingsPreferred() const
1208{
1209 return maJobSetup.ImplGetConstData().GetPapersizeFromSetup();
1210}
1211
1212// dear loplugins, DO NOT REMOVE this code
1213// it will be used in follow-up commits
1214void Printer::SetPrinterSettingsPreferred( bool bPaperSizeFromSetup)
1215{
1216 if ( maJobSetup.ImplGetConstData().GetPapersizeFromSetup() != bPaperSizeFromSetup )
1217 {
1218 JobSetup aJobSetup = maJobSetup;
1219 ImplJobSetup& rData = aJobSetup.ImplGetData();
1220 rData.SetPapersizeFromSetup(bPaperSizeFromSetup);
1221
1222 mbNewJobSetup = true;
1223 maJobSetup = aJobSetup;
1224 }
1225}
1226
1227// Map user paper format to an available printer paper format
1228void Printer::ImplFindPaperFormatForUserSize( JobSetup& aJobSetup )
1229{
1230 ImplJobSetup& rData = aJobSetup.ImplGetData();
1231
1232 // The angle that a landscape page will be turned counterclockwise wrt to portrait.
1233 int nLandscapeAngle = mpInfoPrinter ? mpInfoPrinter->GetLandscapeAngle( &maJobSetup.ImplGetConstData() ) : 900;
1234 int nPaperCount = GetPaperInfoCount();
1235 PaperInfo aInfo(rData.GetPaperWidth(), rData.GetPaperHeight());
1236
1237 // Compare all paper formats and get the appropriate one
1238 for ( int i = 0; i < nPaperCount; i++ )
1239 {
1240 const PaperInfo& rPaperInfo = GetPaperInfo( i );
1241
1242 if ( aInfo.sloppyEqual(rPaperInfo) )
1243 {
1244 rData.SetPaperFormat(
1245 ImplGetPaperFormat( rPaperInfo.getWidth(),
1246 rPaperInfo.getHeight() ));
1247 rData.SetOrientation( Orientation::Portrait );
1248 return;
1249 }
1250 }
1251
1252 // If the printer supports landscape orientation, check paper sizes again
1253 // with landscape orientation. This is necessary as a printer driver provides
1254 // all paper sizes with portrait orientation only!!
1255 if ( !(rData.GetPaperFormat() == PAPER_USER &&
1256 nLandscapeAngle != 0 &&
1257 HasSupport( PrinterSupport::SetOrientation )))
1258 return;
1259
1260 const long nRotatedWidth = rData.GetPaperHeight();
1261 const long nRotatedHeight = rData.GetPaperWidth();
1262 PaperInfo aRotatedInfo(nRotatedWidth, nRotatedHeight);
1263
1264 for ( int i = 0; i < nPaperCount; i++ )
1265 {
1266 const PaperInfo& rPaperInfo = GetPaperInfo( i );
1267
1268 if ( aRotatedInfo.sloppyEqual( rPaperInfo ) )
1269 {
1270 rData.SetPaperFormat(
1271 ImplGetPaperFormat( rPaperInfo.getWidth(),
1272 rPaperInfo.getHeight() ));
1273 rData.SetOrientation( Orientation::Landscape );
1274 return;
1275 }
1276 }
1277}
1278
1279void Printer::SetPaper( Paper ePaper )
1280{
1281 if ( mbInPrintPage )
1282 return;
1283
1284 if ( maJobSetup.ImplGetConstData().GetPaperFormat() == ePaper )
1285 return;
1286
1287 JobSetup aJobSetup = maJobSetup;
1288 ImplJobSetup& rData = aJobSetup.ImplGetData();
1289
1290 rData.SetPaperFormat( ePaper );
1291 if ( ePaper != PAPER_USER )
1292 {
1293 PaperInfo aInfo(ePaper);
1294 rData.SetPaperWidth( aInfo.getWidth() );
1295 rData.SetPaperHeight( aInfo.getHeight() );
1296 }
1297
1298 if ( IsDisplayPrinter() )
1299 {
1300 mbNewJobSetup = true;
1301 maJobSetup = aJobSetup;
1302 return;
1303 }
1304
1305 ReleaseGraphics();
1306 if ( ePaper == PAPER_USER )
1307 ImplFindPaperFormatForUserSize( aJobSetup );
1308 if ( mpInfoPrinter->SetData( JobSetFlags::PAPERSIZE | JobSetFlags::ORIENTATION, &rData ))
1309 {
1310 ImplUpdateJobSetupPaper( aJobSetup );
1311 mbNewJobSetup = true;
1312 maJobSetup = aJobSetup;
1313 ImplUpdatePageData();
1314 ImplUpdateFontList();
1315 }
1316}
1317
1318bool Printer::SetPaperSizeUser( const Size& rSize )
1319{
1320 if ( mbInPrintPage )
1321 return false;
1322
1323 const Size aPixSize = LogicToPixel( rSize );
1324 const Size aPageSize = PixelToLogic(aPixSize, MapMode(MapUnit::Map100thMM));
1325 bool bNeedToChange(maJobSetup.ImplGetConstData().GetPaperWidth() != aPageSize.Width() ||
1326 maJobSetup.ImplGetConstData().GetPaperHeight() != aPageSize.Height());
1327
1328 if(!bNeedToChange)
1329 {
1330 // #i122984# only need to change when Paper is different from PAPER_USER and
1331 // the mapped Paper which will created below in the call to ImplFindPaperFormatForUserSize
1332 // and will replace maJobSetup.ImplGetConstData()->GetPaperFormat(). This leads to
1333 // unnecessary JobSetups, e.g. when printing a multi-page fax, but also with
1334 // normal print
1335 const Paper aPaper = ImplGetPaperFormat(aPageSize.Width(), aPageSize.Height());
1336
1337 bNeedToChange = maJobSetup.ImplGetConstData().GetPaperFormat() != PAPER_USER &&
1338 maJobSetup.ImplGetConstData().GetPaperFormat() != aPaper;
1339 }
1340
1341 if(bNeedToChange)
1342 {
1343 JobSetup aJobSetup = maJobSetup;
1344 ImplJobSetup& rData = aJobSetup.ImplGetData();
1345 rData.SetPaperFormat( PAPER_USER );
1346 rData.SetPaperWidth( aPageSize.Width() );
1347 rData.SetPaperHeight( aPageSize.Height() );
1348
1349 if ( IsDisplayPrinter() )
1350 {
1351 mbNewJobSetup = true;
1352 maJobSetup = aJobSetup;
1353 return true;
1354 }
1355
1356 ReleaseGraphics();
1357 ImplFindPaperFormatForUserSize( aJobSetup );
1358
1359 // Changing the paper size can also change the orientation!
1360 if ( mpInfoPrinter->SetData( JobSetFlags::PAPERSIZE | JobSetFlags::ORIENTATION, &rData ))
1361 {
1362 ImplUpdateJobSetupPaper( aJobSetup );
1363 mbNewJobSetup = true;
1364 maJobSetup = aJobSetup;
1365 ImplUpdatePageData();
1366 ImplUpdateFontList();
1367 return true;
1368 }
1369 else
1370 return false;
1371 }
1372
1373 return true;
1374}
1375
1376int Printer::GetPaperInfoCount() const
1377{
1378 if( ! mpInfoPrinter )
1379 return 0;
1380 if( ! mpInfoPrinter->m_bPapersInit )
1381 mpInfoPrinter->InitPaperFormats( &maJobSetup.ImplGetConstData() );
1382 return mpInfoPrinter->m_aPaperFormats.size();
1383}
1384
1385OUString Printer::GetPaperName( Paper ePaper )
1386{
1387 ImplSVData* pSVData = ImplGetSVData();
1388 if( pSVData->maPaperNames.empty() )
1389 {
1390 static const int PaperIndex[] =
1391 {
1392 PAPER_A0, PAPER_A1, PAPER_A2, PAPER_A3, PAPER_A4, PAPER_A5, PAPER_B4_ISO, PAPER_B5_ISO,
1393 PAPER_LETTER, PAPER_LEGAL, PAPER_TABLOID, PAPER_USER, PAPER_B6_ISO, PAPER_ENV_C4, PAPER_ENV_C5,
1394 PAPER_ENV_C6, PAPER_ENV_C65, PAPER_ENV_DL, PAPER_SLIDE_DIA, PAPER_SCREEN_4_3, PAPER_C, PAPER_D,
1395 PAPER_E, PAPER_EXECUTIVE, PAPER_FANFOLD_LEGAL_DE, PAPER_ENV_MONARCH, PAPER_ENV_PERSONAL, PAPER_ENV_9,
1396 PAPER_ENV_10, PAPER_ENV_11, PAPER_ENV_12, PAPER_KAI16, PAPER_KAI32, PAPER_KAI32BIG, PAPER_B4_JIS,
1397 PAPER_B5_JIS, PAPER_B6_JIS, PAPER_LEDGER, PAPER_STATEMENT, PAPER_QUARTO, PAPER_10x14, PAPER_ENV_14,
1398 PAPER_ENV_C3, PAPER_ENV_ITALY, PAPER_FANFOLD_US, PAPER_FANFOLD_DE, PAPER_POSTCARD_JP, PAPER_9x11,
1399 PAPER_10x11, PAPER_15x11, PAPER_ENV_INVITE, PAPER_A_PLUS, PAPER_B_PLUS, PAPER_LETTER_PLUS, PAPER_A4_PLUS,
1400 PAPER_DOUBLEPOSTCARD_JP, PAPER_A6, PAPER_12x11, PAPER_A7, PAPER_A8, PAPER_A9, PAPER_A10, PAPER_B0_ISO,
1401 PAPER_B1_ISO, PAPER_B2_ISO, PAPER_B3_ISO, PAPER_B7_ISO, PAPER_B8_ISO, PAPER_B9_ISO, PAPER_B10_ISO,
1402 PAPER_ENV_C2, PAPER_ENV_C7, PAPER_ENV_C8, PAPER_ARCHA, PAPER_ARCHB, PAPER_ARCHC, PAPER_ARCHD,
1403 PAPER_ARCHE, PAPER_SCREEN_16_9, PAPER_SCREEN_16_10, PAPER_16K_195x270, PAPER_16K_197x273
1404 };
1405 assert(SAL_N_ELEMENTS(PaperIndex) == SAL_N_ELEMENTS(RID_STR_PAPERNAMES) && "localized paper name count wrong")(static_cast <bool> ((sizeof(sal_n_array_size(PaperIndex
))) == (sizeof(sal_n_array_size(RID_STR_PAPERNAMES))) &&
"localized paper name count wrong") ? void (0) : __assert_fail
("SAL_N_ELEMENTS(PaperIndex) == SAL_N_ELEMENTS(RID_STR_PAPERNAMES) && \"localized paper name count wrong\""
, "/home/maarten/src/libreoffice/core/vcl/source/gdi/print.cxx"
, 1405, __extension__ __PRETTY_FUNCTION__))
;
1406 for (size_t i = 0; i < SAL_N_ELEMENTS(PaperIndex)(sizeof(sal_n_array_size(PaperIndex))); ++i)
1407 pSVData->maPaperNames[PaperIndex[i]] = VclResId(RID_STR_PAPERNAMES[i]);
1408 }
1409
1410 std::unordered_map<int,OUString>::const_iterator it = pSVData->maPaperNames.find( static_cast<int>(ePaper) );
1411 return (it != pSVData->maPaperNames.end()) ? it->second : OUString();
1412}
1413
1414const PaperInfo& Printer::GetPaperInfo( int nPaper ) const
1415{
1416 if( ! mpInfoPrinter )
1417 return ImplGetEmptyPaper();
1418 if( ! mpInfoPrinter->m_bPapersInit )
1419 mpInfoPrinter->InitPaperFormats( &maJobSetup.ImplGetConstData() );
1420 if( mpInfoPrinter->m_aPaperFormats.empty() || nPaper < 0 || nPaper >= int(mpInfoPrinter->m_aPaperFormats.size()) )
1421 return ImplGetEmptyPaper();
1422 return mpInfoPrinter->m_aPaperFormats[nPaper];
1423}
1424
1425Size Printer::GetPaperSize( int nPaper )
1426{
1427 PaperInfo aInfo = GetPaperInfo( nPaper );
1428 return PixelToLogic( Size( aInfo.getWidth(), aInfo.getHeight() ) );
1429}
1430
1431void Printer::SetDuplexMode( DuplexMode eDuplex )
1432{
1433 if ( mbInPrintPage )
1434 return;
1435
1436 if ( maJobSetup.ImplGetConstData().GetDuplexMode() == eDuplex )
1437 return;
1438
1439 JobSetup aJobSetup = maJobSetup;
1440 ImplJobSetup& rData = aJobSetup.ImplGetData();
1441
1442 rData.SetDuplexMode( eDuplex );
1443
1444 if ( IsDisplayPrinter() )
1445 {
1446 mbNewJobSetup = true;
1447 maJobSetup = aJobSetup;
1448 return;
1449 }
1450
1451 ReleaseGraphics();
1452 if ( mpInfoPrinter->SetData( JobSetFlags::DUPLEXMODE, &rData ) )
1453 {
1454 ImplUpdateJobSetupPaper( aJobSetup );
1455 mbNewJobSetup = true;
1456 maJobSetup = aJobSetup;
1457 ImplUpdatePageData();
1458 ImplUpdateFontList();
1459 }
1460}
1461
1462DuplexMode Printer::GetDuplexMode() const
1463{
1464 return maJobSetup.ImplGetConstData().GetDuplexMode();
1465}
1466
1467Paper Printer::GetPaper() const
1468{
1469 return maJobSetup.ImplGetConstData().GetPaperFormat();
1470}
1471
1472sal_uInt16 Printer::GetPaperBinCount() const
1473{
1474 if ( IsDisplayPrinter() )
1475 return 0;
1476
1477 return mpInfoPrinter->GetPaperBinCount( &maJobSetup.ImplGetConstData() );
1478}
1479
1480OUString Printer::GetPaperBinName( sal_uInt16 nPaperBin ) const
1481{
1482 if ( IsDisplayPrinter() )
1483 return OUString();
1484
1485 if ( nPaperBin < GetPaperBinCount() )
1486 return mpInfoPrinter->GetPaperBinName( &maJobSetup.ImplGetConstData(), nPaperBin );
1487 else
1488 return OUString();
1489}
1490
1491void Printer::SetCopyCount( sal_uInt16 nCopy, bool bCollate )
1492{
1493 mnCopyCount = nCopy;
1494 mbCollateCopy = bCollate;
1495}
1496
1497ErrCode Printer::ImplSalPrinterErrorCodeToVCL( SalPrinterError nError )
1498{
1499 ErrCode nVCLError;
1500 switch ( nError )
1501 {
1502 case SalPrinterError::NONE:
1503 nVCLError = ERRCODE_NONEErrCode(0);
1504 break;
1505 case SalPrinterError::Abort:
1506 nVCLError = PRINTER_ABORTErrCode( ErrCodeArea::Io, ErrCodeClass::Abort, 27 );
1507 break;
1508 default:
1509 nVCLError = PRINTER_GENERALERRORErrCode( ErrCodeArea::Io, ErrCodeClass::General, 13 );
1510 break;
1511 }
1512
1513 return nVCLError;
1514}
1515
1516void Printer::EndJob()
1517{
1518 if ( !IsJobActive() )
1519 return;
1520
1521 SAL_WARN_IF( mbInPrintPage, "vcl.gdi", "Printer::EndJob() - StartPage() without EndPage() called" )do { if (true && (mbInPrintPage)) { switch (sal_detail_log_report
(::SAL_DETAIL_LOG_LEVEL_WARN, "vcl.gdi")) { case SAL_DETAIL_LOG_ACTION_IGNORE
: break; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail
::getResult( ::sal::detail::StreamStart() << "Printer::EndJob() - StartPage() without EndPage() called"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"
), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/print.cxx"
":" "1521" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "Printer::EndJob() - StartPage() without EndPage() called"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "Printer::EndJob() - StartPage() without EndPage() called"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"
), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/print.cxx"
":" "1521" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "Printer::EndJob() - StartPage() without EndPage() called"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"
), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/print.cxx"
":" "1521" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "Printer::EndJob() - StartPage() without EndPage() called"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "Printer::EndJob() - StartPage() without EndPage() called"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"
), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/print.cxx"
":" "1521" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
1522
1523 mbJobActive = false;
1524
1525 if ( mpPrinter )
1526 {
1527 ReleaseGraphics();
1528
1529 mbPrinting = false;
1530
1531 mbDevOutput = false;
1532 mpPrinter->EndJob();
1533 mpPrinter.reset();
1534 }
1535}
1536
1537void Printer::ImplStartPage()
1538{
1539 if ( !IsJobActive() )
1540 return;
1541
1542 if ( !mpPrinter )
1543 return;
1544
1545 SalGraphics* pGraphics = mpPrinter->StartPage( &maJobSetup.ImplGetData(),
1546 mbNewJobSetup );
1547 if ( pGraphics )
1548 {
1549 ReleaseGraphics();
1550 mpJobGraphics = pGraphics;
1551 }
1552 mbDevOutput = true;
1553
1554 // PrintJob not aborted ???
1555 if ( IsJobActive() )
1556 mbInPrintPage = true;
1557}
1558
1559void Printer::ImplEndPage()
1560{
1561 if ( !IsJobActive() )
1562 return;
1563
1564 mbInPrintPage = false;
1565
1566 if ( mpPrinter )
1567 {
1568 mpPrinter->EndPage();
1569 ReleaseGraphics();
1570 mbDevOutput = false;
1571
1572 mpJobGraphics = nullptr;
1573 mbNewJobSetup = false;
1574 }
1575}
1576
1577void Printer::updatePrinters()
1578{
1579 ImplSVData* pSVData = ImplGetSVData();
1580 ImplPrnQueueList* pPrnList = pSVData->maGDIData.mpPrinterQueueList.get();
1581
1582 if ( !pPrnList )
1583 return;
1584
1585 std::unique_ptr<ImplPrnQueueList> pNewList(new ImplPrnQueueList);
1586 pSVData->mpDefInst->GetPrinterQueueInfo( pNewList.get() );
1587
1588 bool bChanged = pPrnList->m_aQueueInfos.size() != pNewList->m_aQueueInfos.size();
1589 for( decltype(pPrnList->m_aQueueInfos)::size_type i = 0; ! bChanged && i < pPrnList->m_aQueueInfos.size(); i++ )
1590 {
1591 ImplPrnQueueData& rInfo = pPrnList->m_aQueueInfos[i];
1592 ImplPrnQueueData& rNewInfo = pNewList->m_aQueueInfos[i];
1593 if( ! rInfo.mpSalQueueInfo || ! rNewInfo.mpSalQueueInfo || // sanity check
1594 rInfo.mpSalQueueInfo->maPrinterName != rNewInfo.mpSalQueueInfo->maPrinterName )
1595 {
1596 bChanged = true;
1597 }
1598 }
1599 if( !bChanged )
1600 return;
1601
1602 ImplDeletePrnQueueList();
1603 pSVData->maGDIData.mpPrinterQueueList = std::move(pNewList);
1604
1605 Application* pApp = GetpApp();
1606 if( pApp )
1607 {
1608 DataChangedEvent aDCEvt( DataChangedEventType::PRINTER );
1609 Application::ImplCallEventListenersApplicationDataChanged(&aDCEvt);
1610 Application::NotifyAllWindows( aDCEvt );
1611 }
1612}
1613
1614bool Printer::UsePolyPolygonForComplexGradient()
1615{
1616 return true;
1617}
1618
1619void Printer::ClipAndDrawGradientMetafile ( const Gradient &rGradient, const tools::PolyPolygon &rPolyPoly )
1620{
1621 const tools::Rectangle aBoundRect( rPolyPoly.GetBoundRect() );
1622
1623 Push( PushFlags::CLIPREGION );
1624 IntersectClipRegion(vcl::Region(rPolyPoly));
1625 DrawGradient( aBoundRect, rGradient );
1626 Pop();
1627}
1628
1629void Printer::SetFontOrientation( LogicalFontInstance* const pFontEntry ) const
1630{
1631 pFontEntry->mnOrientation = pFontEntry->mxFontMetric->GetOrientation();
1632}
1633
1634vcl::Region Printer::ClipToDeviceBounds(vcl::Region aRegion) const
1635{
1636 return aRegion;
1637}
1638
1639Bitmap Printer::GetBitmap( const Point& rSrcPt, const Size& rSize ) const
1640{
1641 SAL_WARN("vcl.gdi", "GetBitmap(): This should never be called on by a Printer instance")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "vcl.gdi")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "GetBitmap(): This should never be called on by a Printer instance"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"
), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/print.cxx"
":" "1641" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "GetBitmap(): This should never be called on by a Printer instance"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "GetBitmap(): This should never be called on by a Printer instance"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"
), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/print.cxx"
":" "1641" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "GetBitmap(): This should never be called on by a Printer instance"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"
), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/print.cxx"
":" "1641" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "GetBitmap(): This should never be called on by a Printer instance"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "GetBitmap(): This should never be called on by a Printer instance"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"
), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/print.cxx"
":" "1641" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
1642
1643 return OutputDevice::GetBitmap( rSrcPt, rSize );
1644}
1645
1646/* 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);
3
Calling 'Reference::set'
11
Returning; memory was released
14
Calling 'Reference::set'
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 ;-)
205 if (aTmp.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();
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 )
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
3.1
'pBody' is null
14.1
'pBody' is non-null
3.1
'pBody' is null
14.1
'pBody' is non-null
3.1
'pBody' is null
14.1
'pBody' is non-null
3.1
'pBody' is null
14.1
'pBody' is non-null
)
4
Taking false branch
15
Taking true branch
123 pBody->acquire();
16
Use of memory after it is freed
124 reference_type * const pOld = m_pBody;
125 m_pBody = pBody;
126 if (pOld
4.1
'pOld' is non-null
4.1
'pOld' is non-null
4.1
'pOld' is non-null
4.1
'pOld' is non-null
)
5
Taking true branch
127 pOld->release();
6
Calling 'VclReferenceBase::release'
10
Returning; memory was released
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)
177 {
178 reference_type * const pOld = m_pBody;
179 m_pBody = NULL__null;
180 pOld->release();
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;
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)
7
Assuming the condition is true
8
Taking true branch
40 delete this;
9
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