1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sal/types.h>
21 #include <sal/log.hxx>
23 #include <tools/helpers.hxx>
24 #include <tools/debug.hxx>
26 #include <vcl/event.hxx>
27 #include <vcl/virdev.hxx>
28 #include <vcl/print.hxx>
30 #include <comphelper/processfactory.hxx>
32 #include <salinst.hxx>
35 #include <salptype.hxx>
41 #include <PhysicalFontCollection.hxx>
44 #include <com/sun/star/beans/XPropertySet.hpp>
45 #include <com/sun/star/configuration/theDefaultProvider.hpp>
46 #include <com/sun/star/container/XNameAccess.hpp>
47 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
48 #include <com/sun/star/uno/Sequence.h>
50 int nImplSysDialog
= 0;
54 Paper
ImplGetPaperFormat( long nWidth100thMM
, long nHeight100thMM
)
56 PaperInfo
aInfo(nWidth100thMM
, nHeight100thMM
);
58 return aInfo
.getPaper();
61 const PaperInfo
& ImplGetEmptyPaper()
63 static PaperInfo
aInfo(PAPER_USER
);
68 void ImplUpdateJobSetupPaper( JobSetup
& rJobSetup
)
70 const ImplJobSetup
& rConstData
= rJobSetup
.ImplGetConstData();
72 if ( !rConstData
.GetPaperWidth() || !rConstData
.GetPaperHeight() )
74 if ( rConstData
.GetPaperFormat() != PAPER_USER
)
76 PaperInfo
aInfo(rConstData
.GetPaperFormat());
78 ImplJobSetup
& rData
= rJobSetup
.ImplGetData();
79 rData
.SetPaperWidth( aInfo
.getWidth() );
80 rData
.SetPaperHeight( aInfo
.getHeight() );
83 else if ( rConstData
.GetPaperFormat() == PAPER_USER
)
85 Paper ePaper
= ImplGetPaperFormat( rConstData
.GetPaperWidth(), rConstData
.GetPaperHeight() );
86 if ( ePaper
!= PAPER_USER
)
87 rJobSetup
.ImplGetData().SetPaperFormat(ePaper
);
92 PrinterOptions::PrinterOptions() :
93 mbReduceTransparency( false ),
94 meReducedTransparencyMode( PrinterTransparencyMode::Auto
),
95 mbReduceGradients( false ),
96 meReducedGradientsMode( PrinterGradientMode::Stripes
),
97 mnReducedGradientStepCount( 64 ),
98 mbReduceBitmaps( false ),
99 meReducedBitmapMode( PrinterBitmapMode::Normal
),
100 mnReducedBitmapResolution( 200 ),
101 mbReducedBitmapsIncludeTransparency( true ),
102 mbConvertToGreyscales( false ),
103 mbPDFAsStandardPrintJobFormat( false )
107 void PrinterOptions::ReadFromConfig( bool i_bFile
)
109 bool bSuccess
= false;
110 // save old state in case something goes wrong
111 PrinterOptions
aOldValues( *this );
113 // get the configuration service
114 css::uno::Reference
< css::lang::XMultiServiceFactory
> xConfigProvider
;
115 css::uno::Reference
< css::container::XNameAccess
> xConfigAccess
;
118 // get service provider
119 css::uno::Reference
< css::uno::XComponentContext
> xContext( comphelper::getProcessComponentContext() );
120 // create configuration hierarchical access name
123 xConfigProvider
= css::configuration::theDefaultProvider::get( xContext
);
125 css::uno::Sequence
< css::uno::Any
> aArgs(1);
126 css::beans::PropertyValue aVal
;
127 aVal
.Name
= "nodepath";
129 aVal
.Value
<<= OUString( "/org.openoffice.Office.Common/Print/Option/File" );
131 aVal
.Value
<<= OUString( "/org.openoffice.Office.Common/Print/Option/Printer" );
132 aArgs
.getArray()[0] <<= aVal
;
134 xConfigProvider
->createInstanceWithArguments(
135 "com.sun.star.configuration.ConfigurationAccess", aArgs
),
136 css::uno::UNO_QUERY
);
137 if( xConfigAccess
.is() )
139 css::uno::Reference
< css::beans::XPropertySet
> xSet( xConfigAccess
, css::uno::UNO_QUERY
);
142 sal_Int32 nValue
= 0;
144 if( xSet
->getPropertyValue("ReduceTransparency") >>= bValue
)
145 SetReduceTransparency( bValue
);
146 if( xSet
->getPropertyValue("ReducedTransparencyMode") >>= nValue
)
147 SetReducedTransparencyMode( static_cast<PrinterTransparencyMode
>(nValue
) );
148 if( xSet
->getPropertyValue("ReduceGradients") >>= bValue
)
149 SetReduceGradients( bValue
);
150 if( xSet
->getPropertyValue("ReducedGradientMode") >>= nValue
)
151 SetReducedGradientMode( static_cast<PrinterGradientMode
>(nValue
) );
152 if( xSet
->getPropertyValue("ReducedGradientStepCount") >>= nValue
)
153 SetReducedGradientStepCount( static_cast<sal_uInt16
>(nValue
) );
154 if( xSet
->getPropertyValue("ReduceBitmaps") >>= bValue
)
155 SetReduceBitmaps( bValue
);
156 if( xSet
->getPropertyValue("ReducedBitmapMode") >>= nValue
)
157 SetReducedBitmapMode( static_cast<PrinterBitmapMode
>(nValue
) );
158 if( xSet
->getPropertyValue("ReducedBitmapResolution") >>= nValue
)
159 SetReducedBitmapResolution( static_cast<sal_uInt16
>(nValue
) );
160 if( xSet
->getPropertyValue("ReducedBitmapIncludesTransparency") >>= bValue
)
161 SetReducedBitmapIncludesTransparency( bValue
);
162 if( xSet
->getPropertyValue("ConvertToGreyscales") >>= bValue
)
163 SetConvertToGreyscales( bValue
);
164 if( xSet
->getPropertyValue("PDFAsStandardPrintJobFormat") >>= bValue
)
165 SetPDFAsStandardPrintJobFormat( bValue
);
171 catch( const css::uno::Exception
& )
175 catch( const css::lang::WrappedTargetException
& )
183 bool Printer::DrawTransformBitmapExDirect(
184 const basegfx::B2DHomMatrix
& /*aFullTransform*/,
185 const BitmapEx
& /*rBitmapEx*/)
187 // printers can't draw bitmaps directly
191 bool Printer::TransformAndReduceBitmapExToTargetRange(
192 const basegfx::B2DHomMatrix
& /*aFullTransform*/,
193 basegfx::B2DRange
& /*aVisibleRange*/,
194 double& /*fMaximumArea*/)
196 // deliberately do nothing - you can't reduce the
197 // target range for a printer at all
201 void Printer::DrawDeviceBitmap( const Point
& rDestPt
, const Size
& rDestSize
,
202 const Point
& rSrcPtPixel
, const Size
& rSrcSizePixel
,
205 if( rBmpEx
.IsAlpha() )
207 // #107169# For true alpha bitmaps, no longer masking the
208 // bitmap, but perform a full alpha blend against a white
210 Bitmap
aBmp( rBmpEx
.GetBitmap() );
211 aBmp
.Blend( rBmpEx
.GetAlpha(), COL_WHITE
);
212 DrawBitmap( rDestPt
, rDestSize
, rSrcPtPixel
, rSrcSizePixel
, aBmp
);
216 Bitmap
aBmp( rBmpEx
.GetBitmap() ), aMask( rBmpEx
.GetMask() );
217 aBmp
.Replace( aMask
, COL_WHITE
);
218 ImplPrintTransparent( aBmp
, aMask
, rDestPt
, rDestSize
, rSrcPtPixel
, rSrcSizePixel
);
222 void Printer::EmulateDrawTransparent ( const tools::PolyPolygon
& rPolyPoly
,
223 sal_uInt16 nTransparencePercent
)
225 // #110958# Disable alpha VDev, we perform the necessary
226 VirtualDevice
* pOldAlphaVDev
= mpAlphaVDev
;
228 // operation explicitly further below.
230 mpAlphaVDev
= nullptr;
232 GDIMetaFile
* pOldMetaFile
= mpMetaFile
;
233 mpMetaFile
= nullptr;
235 mpMetaFile
= pOldMetaFile
;
237 // #110958# Restore disabled alpha VDev
238 mpAlphaVDev
= pOldAlphaVDev
;
240 tools::Rectangle
aPolyRect( LogicToPixel( rPolyPoly
).GetBoundRect() );
241 const Size
aDPISize( LogicToPixel(Size(1, 1), MapMode(MapUnit::MapInch
)) );
242 const long nBaseExtent
= std::max( FRound( aDPISize
.Width() / 300. ), 1L );
244 const sal_uInt16 nTrans
= ( nTransparencePercent
< 13 ) ? 0 :
245 ( nTransparencePercent
< 38 ) ? 25 :
246 ( nTransparencePercent
< 63 ) ? 50 :
247 ( nTransparencePercent
< 88 ) ? 75 : 100;
251 case 25: nMove
= nBaseExtent
* 3; break;
252 case 50: nMove
= nBaseExtent
* 4; break;
253 case 75: nMove
= nBaseExtent
* 6; break;
255 // #i112959# very transparent (88 < nTransparencePercent <= 99)
256 case 100: nMove
= nBaseExtent
* 8; break;
258 // #i112959# not transparent (nTransparencePercent < 13)
259 default: nMove
= 0; break;
262 Push( PushFlags::CLIPREGION
| PushFlags::LINECOLOR
);
263 IntersectClipRegion(vcl::Region(rPolyPoly
));
264 SetLineColor( GetFillColor() );
265 const bool bOldMap
= mbMap
;
266 EnableMapMode( false );
270 tools::Rectangle
aRect( aPolyRect
.TopLeft(), Size( aPolyRect
.GetWidth(), nBaseExtent
) );
271 while( aRect
.Top() <= aPolyRect
.Bottom() )
274 aRect
.Move( 0, nMove
);
277 aRect
= tools::Rectangle( aPolyRect
.TopLeft(), Size( nBaseExtent
, aPolyRect
.GetHeight() ) );
278 while( aRect
.Left() <= aPolyRect
.Right() )
281 aRect
.Move( nMove
, 0 );
286 // #i112959# if not transparent, draw full rectangle in clip region
287 DrawRect( aPolyRect
);
290 EnableMapMode( bOldMap
);
293 mpMetaFile
= pOldMetaFile
;
295 // #110958# Restore disabled alpha VDev
296 mpAlphaVDev
= pOldAlphaVDev
;
299 void Printer::DrawOutDev( const Point
& /*rDestPt*/, const Size
& /*rDestSize*/,
300 const Point
& /*rSrcPt*/, const Size
& /*rSrcSize*/ )
302 SAL_WARN( "vcl.gdi", "Don't use OutputDevice::DrawOutDev(...) with printer devices!" );
305 void Printer::DrawOutDev( const Point
& /*rDestPt*/, const Size
& /*rDestSize*/,
306 const Point
& /*rSrcPt*/, const Size
& /*rSrcSize*/,
307 const OutputDevice
& /*rOutDev*/ )
309 SAL_WARN( "vcl.gdi", "Don't use OutputDevice::DrawOutDev(...) with printer devices!" );
312 void Printer::CopyArea( const Point
& /*rDestPt*/,
313 const Point
& /*rSrcPt*/, const Size
& /*rSrcSize*/,
314 bool /*bWindowInvalidate*/ )
316 SAL_WARN( "vcl.gdi", "Don't use OutputDevice::CopyArea(...) with printer devices!" );
319 void Printer::SetPrinterOptions( const PrinterOptions
& i_rOptions
)
321 *mpPrinterOptions
= i_rOptions
;
324 bool Printer::HasMirroredGraphics() const
326 // due to a "hotfix" for AOO bug i55719, this needs to return false
331 QueueInfo::QueueInfo()
333 mnStatus
= PrintQueueFlags::NONE
;
337 SalPrinterQueueInfo::SalPrinterQueueInfo()
339 mnStatus
= PrintQueueFlags::NONE
;
340 mnJobs
= QUEUE_JOBS_DONTKNOW
;
343 SalPrinterQueueInfo::~SalPrinterQueueInfo()
347 ImplPrnQueueList::~ImplPrnQueueList()
351 void ImplPrnQueueList::Add( std::unique_ptr
<SalPrinterQueueInfo
> pData
)
353 std::unordered_map
< OUString
, sal_Int32
>::iterator it
=
354 m_aNameToIndex
.find( pData
->maPrinterName
);
355 if( it
== m_aNameToIndex
.end() )
357 m_aNameToIndex
[ pData
->maPrinterName
] = m_aQueueInfos
.size();
358 m_aPrinterList
.push_back( pData
->maPrinterName
);
359 m_aQueueInfos
.push_back( ImplPrnQueueData() );
360 m_aQueueInfos
.back().mpQueueInfo
= nullptr;
361 m_aQueueInfos
.back().mpSalQueueInfo
= std::move(pData
);
363 else // this should not happen, but ...
365 ImplPrnQueueData
& rData
= m_aQueueInfos
[ it
->second
];
366 rData
.mpQueueInfo
.reset();
367 rData
.mpSalQueueInfo
= std::move(pData
);
371 ImplPrnQueueData
* ImplPrnQueueList::Get( const OUString
& rPrinter
)
373 ImplPrnQueueData
* pData
= nullptr;
374 std::unordered_map
<OUString
,sal_Int32
>::iterator it
=
375 m_aNameToIndex
.find( rPrinter
);
376 if( it
!= m_aNameToIndex
.end() )
377 pData
= &m_aQueueInfos
[it
->second
];
381 static void ImplInitPrnQueueList()
383 ImplSVData
* pSVData
= ImplGetSVData();
385 pSVData
->maGDIData
.mpPrinterQueueList
.reset(new ImplPrnQueueList
);
387 static const char* pEnv
= getenv( "SAL_DISABLE_PRINTERLIST" );
388 if( !pEnv
|| !*pEnv
)
389 pSVData
->mpDefInst
->GetPrinterQueueInfo( pSVData
->maGDIData
.mpPrinterQueueList
.get() );
392 void ImplDeletePrnQueueList()
394 ImplSVData
* pSVData
= ImplGetSVData();
395 pSVData
->maGDIData
.mpPrinterQueueList
.reset();
398 const std::vector
<OUString
>& Printer::GetPrinterQueues()
400 ImplSVData
* pSVData
= ImplGetSVData();
401 if ( !pSVData
->maGDIData
.mpPrinterQueueList
)
402 ImplInitPrnQueueList();
403 return pSVData
->maGDIData
.mpPrinterQueueList
->m_aPrinterList
;
406 const QueueInfo
* Printer::GetQueueInfo( const OUString
& rPrinterName
, bool bStatusUpdate
)
408 ImplSVData
* pSVData
= ImplGetSVData();
410 if ( !pSVData
->maGDIData
.mpPrinterQueueList
)
411 ImplInitPrnQueueList();
413 if ( !pSVData
->maGDIData
.mpPrinterQueueList
)
416 ImplPrnQueueData
* pInfo
= pSVData
->maGDIData
.mpPrinterQueueList
->Get( rPrinterName
);
419 if( !pInfo
->mpQueueInfo
|| bStatusUpdate
)
420 pSVData
->mpDefInst
->GetPrinterQueueState( pInfo
->mpSalQueueInfo
.get() );
422 if ( !pInfo
->mpQueueInfo
)
423 pInfo
->mpQueueInfo
.reset(new QueueInfo
);
425 pInfo
->mpQueueInfo
->maPrinterName
= pInfo
->mpSalQueueInfo
->maPrinterName
;
426 pInfo
->mpQueueInfo
->maDriver
= pInfo
->mpSalQueueInfo
->maDriver
;
427 pInfo
->mpQueueInfo
->maLocation
= pInfo
->mpSalQueueInfo
->maLocation
;
428 pInfo
->mpQueueInfo
->maComment
= pInfo
->mpSalQueueInfo
->maComment
;
429 pInfo
->mpQueueInfo
->mnStatus
= pInfo
->mpSalQueueInfo
->mnStatus
;
430 pInfo
->mpQueueInfo
->mnJobs
= pInfo
->mpSalQueueInfo
->mnJobs
;
431 return pInfo
->mpQueueInfo
.get();
436 OUString
Printer::GetDefaultPrinterName()
438 static const char* pEnv
= getenv( "SAL_DISABLE_DEFAULTPRINTER" );
439 if( !pEnv
|| !*pEnv
)
441 ImplSVData
* pSVData
= ImplGetSVData();
443 return pSVData
->mpDefInst
->GetDefaultPrinter();
448 void Printer::ImplInitData()
451 mbDefPrinter
= false;
452 mnError
= ERRCODE_NONE
;
455 mbCollateCopy
= false;
459 mbInPrintPage
= false;
460 mbNewJobSetup
= false;
461 mpInfoPrinter
= nullptr;
463 mpDisplayDev
= nullptr;
464 mpPrinterOptions
.reset(new PrinterOptions
);
466 // Add printer to the list
467 ImplSVData
* pSVData
= ImplGetSVData();
468 mpNext
= pSVData
->maGDIData
.mpFirstPrinter
;
471 mpNext
->mpPrev
= this;
472 pSVData
->maGDIData
.mpFirstPrinter
= this;
475 bool Printer::AcquireGraphics() const
477 DBG_TESTSOLARMUTEX();
482 mbInitLineColor
= true;
483 mbInitFillColor
= true;
485 mbInitTextColor
= true;
486 mbInitClipRegion
= true;
488 ImplSVData
* pSVData
= ImplGetSVData();
491 mpGraphics
= mpJobGraphics
;
492 else if ( mpDisplayDev
)
494 const VirtualDevice
* pVirDev
= mpDisplayDev
;
495 mpGraphics
= pVirDev
->mpVirDev
->AcquireGraphics();
496 // if needed retry after releasing least recently used virtual device graphics
497 while ( !mpGraphics
)
499 if ( !pSVData
->maGDIData
.mpLastVirGraphics
)
501 pSVData
->maGDIData
.mpLastVirGraphics
->ReleaseGraphics();
502 mpGraphics
= pVirDev
->mpVirDev
->AcquireGraphics();
504 // update global LRU list of virtual device graphics
507 mpNextGraphics
= pSVData
->maGDIData
.mpFirstVirGraphics
;
508 pSVData
->maGDIData
.mpFirstVirGraphics
= const_cast<Printer
*>(this);
509 if ( mpNextGraphics
)
510 mpNextGraphics
->mpPrevGraphics
= const_cast<Printer
*>(this);
511 if ( !pSVData
->maGDIData
.mpLastVirGraphics
)
512 pSVData
->maGDIData
.mpLastVirGraphics
= const_cast<Printer
*>(this);
517 mpGraphics
= mpInfoPrinter
->AcquireGraphics();
518 // if needed retry after releasing least recently used printer graphics
519 while ( !mpGraphics
)
521 if ( !pSVData
->maGDIData
.mpLastPrnGraphics
)
523 pSVData
->maGDIData
.mpLastPrnGraphics
->ReleaseGraphics();
524 mpGraphics
= mpInfoPrinter
->AcquireGraphics();
526 // update global LRU list of printer graphics
529 mpNextGraphics
= pSVData
->maGDIData
.mpFirstPrnGraphics
;
530 pSVData
->maGDIData
.mpFirstPrnGraphics
= const_cast<Printer
*>(this);
531 if ( mpNextGraphics
)
532 mpNextGraphics
->mpPrevGraphics
= const_cast<Printer
*>(this);
533 if ( !pSVData
->maGDIData
.mpLastPrnGraphics
)
534 pSVData
->maGDIData
.mpLastPrnGraphics
= const_cast<Printer
*>(this);
540 mpGraphics
->SetXORMode( (RasterOp::Invert
== meRasterOp
) || (RasterOp::Xor
== meRasterOp
), RasterOp::Invert
== meRasterOp
);
541 mpGraphics
->setAntiAliasB2DDraw(bool(mnAntialiasing
& AntialiasingFlags::EnableB2dDraw
));
544 return mpGraphics
!= nullptr;
547 void Printer::ImplReleaseFonts()
550 // HACK to fix an urgent P1 printing issue fast
551 // WinSalPrinter does not respect GetGraphics/ReleaseGraphics conventions
552 // so Printer::mpGraphics often points to a dead WinSalGraphics
553 // TODO: fix WinSalPrinter's GetGraphics/ReleaseGraphics handling
554 mpGraphics
->ReleaseFonts();
559 mpFontInstance
.clear();
560 mpDeviceFontList
.reset();
561 mpDeviceFontSizeList
.reset();
564 void Printer::ReleaseGraphics( bool bRelease
)
566 DBG_TESTSOLARMUTEX();
571 // release the fonts of the physically released graphics device
575 ImplSVData
* pSVData
= ImplGetSVData();
577 Printer
* pPrinter
= this;
579 if ( !pPrinter
->mpJobGraphics
)
581 if ( pPrinter
->mpDisplayDev
)
583 VirtualDevice
* pVirDev
= pPrinter
->mpDisplayDev
;
585 pVirDev
->mpVirDev
->ReleaseGraphics( mpGraphics
);
586 // remove from global LRU list of virtual device graphics
587 if ( mpPrevGraphics
)
588 mpPrevGraphics
->mpNextGraphics
= mpNextGraphics
;
590 pSVData
->maGDIData
.mpFirstVirGraphics
= mpNextGraphics
;
591 if ( mpNextGraphics
)
592 mpNextGraphics
->mpPrevGraphics
= mpPrevGraphics
;
594 pSVData
->maGDIData
.mpLastVirGraphics
= mpPrevGraphics
;
599 pPrinter
->mpInfoPrinter
->ReleaseGraphics( mpGraphics
);
600 // remove from global LRU list of printer graphics
601 if ( mpPrevGraphics
)
602 mpPrevGraphics
->mpNextGraphics
= mpNextGraphics
;
604 pSVData
->maGDIData
.mpFirstPrnGraphics
= mpNextGraphics
;
605 if ( mpNextGraphics
)
606 mpNextGraphics
->mpPrevGraphics
= mpPrevGraphics
;
608 pSVData
->maGDIData
.mpLastPrnGraphics
= mpPrevGraphics
;
612 mpGraphics
= nullptr;
613 mpPrevGraphics
= nullptr;
614 mpNextGraphics
= nullptr;
617 void Printer::ImplInit( SalPrinterQueueInfo
* pInfo
)
619 ImplSVData
* pSVData
= ImplGetSVData();
620 // #i74084# update info for this specific SalPrinterQueueInfo
621 pSVData
->mpDefInst
->GetPrinterQueueState( pInfo
);
623 // Test whether the driver actually matches the JobSetup
624 ImplJobSetup
& rData
= maJobSetup
.ImplGetData();
625 if ( rData
.GetDriverData() )
627 if ( rData
.GetPrinterName() != pInfo
->maPrinterName
||
628 rData
.GetDriver() != pInfo
->maDriver
)
630 std::free( const_cast<sal_uInt8
*>(rData
.GetDriverData()) );
631 rData
.SetDriverData(nullptr);
632 rData
.SetDriverDataLen(0);
636 // Remember printer name
637 maPrinterName
= pInfo
->maPrinterName
;
638 maDriver
= pInfo
->maDriver
;
640 // Add printer name to JobSetup
641 rData
.SetPrinterName( maPrinterName
);
642 rData
.SetDriver( maDriver
);
644 mpInfoPrinter
= pSVData
->mpDefInst
->CreateInfoPrinter( pInfo
, &rData
);
646 mpJobGraphics
= nullptr;
647 ImplUpdateJobSetupPaper( maJobSetup
);
649 if ( !mpInfoPrinter
)
655 // we need a graphics
656 if ( !AcquireGraphics() )
663 ImplUpdatePageData();
664 mxFontCollection
.reset(new PhysicalFontCollection
);
665 mxFontCache
.reset(new ImplFontCache
);
666 mpGraphics
->GetDevFontList(mxFontCollection
.get());
669 void Printer::ImplInitDisplay()
671 ImplSVData
* pSVData
= ImplGetSVData();
673 mpInfoPrinter
= nullptr;
675 mpJobGraphics
= nullptr;
677 mpDisplayDev
= VclPtr
<VirtualDevice
>::Create();
678 mxFontCollection
= pSVData
->maGDIData
.mxScreenFontList
;
679 mxFontCache
= pSVData
->maGDIData
.mxScreenFontCache
;
680 mnDPIX
= mpDisplayDev
->mnDPIX
;
681 mnDPIY
= mpDisplayDev
->mnDPIY
;
684 void Printer::DrawDeviceMask( const Bitmap
& rMask
, const Color
& rMaskColor
,
685 const Point
& rDestPt
, const Size
& rDestSize
,
686 const Point
& rSrcPtPixel
, const Size
& rSrcSizePixel
)
688 Point
aDestPt( LogicToPixel( rDestPt
) );
689 Size
aDestSz( LogicToPixel( rDestSize
) );
690 tools::Rectangle
aSrcRect( rSrcPtPixel
, rSrcSizePixel
);
694 if( !(!rMask
.IsEmpty() && aSrcRect
.GetWidth() && aSrcRect
.GetHeight() && aDestSz
.Width() && aDestSz
.Height()) )
697 Bitmap
aMask( rMask
);
698 BmpMirrorFlags nMirrFlags
= BmpMirrorFlags::NONE
;
700 if( aMask
.GetBitCount() > 1 )
701 aMask
.Convert( BmpConversion::N1BitThreshold
);
703 // mirrored horizontically
704 if( aDestSz
.Width() < 0 )
706 aDestSz
.setWidth( -aDestSz
.Width() );
707 aDestPt
.AdjustX( -( aDestSz
.Width() - 1 ) );
708 nMirrFlags
|= BmpMirrorFlags::Horizontal
;
711 // mirrored vertically
712 if( aDestSz
.Height() < 0 )
714 aDestSz
.setHeight( -aDestSz
.Height() );
715 aDestPt
.AdjustY( -( aDestSz
.Height() - 1 ) );
716 nMirrFlags
|= BmpMirrorFlags::Vertical
;
720 if( aSrcRect
!= tools::Rectangle( Point(), aMask
.GetSizePixel() ) )
721 aMask
.Crop( aSrcRect
);
723 // destination mirrored
724 if( nMirrFlags
!= BmpMirrorFlags::NONE
)
725 aMask
.Mirror( nMirrFlags
);
728 const long nSrcWidth
= aSrcRect
.GetWidth(), nSrcHeight
= aSrcRect
.GetHeight();
729 long nX
, nY
; //, nWorkX, nWorkY, nWorkWidth, nWorkHeight;
730 std::unique_ptr
<long[]> pMapX( new long[ nSrcWidth
+ 1 ] );
731 std::unique_ptr
<long[]> pMapY( new long[ nSrcHeight
+ 1 ] );
732 GDIMetaFile
* pOldMetaFile
= mpMetaFile
;
733 const bool bOldMap
= mbMap
;
735 mpMetaFile
= nullptr;
737 Push( PushFlags::FILLCOLOR
| PushFlags::LINECOLOR
);
738 SetLineColor( rMaskColor
);
739 SetFillColor( rMaskColor
);
743 // create forward mapping tables
744 for( nX
= 0; nX
<= nSrcWidth
; nX
++ )
745 pMapX
[ nX
] = aDestPt
.X() + FRound( static_cast<double>(aDestSz
.Width()) * nX
/ nSrcWidth
);
747 for( nY
= 0; nY
<= nSrcHeight
; nY
++ )
748 pMapY
[ nY
] = aDestPt
.Y() + FRound( static_cast<double>(aDestSz
.Height()) * nY
/ nSrcHeight
);
750 // walk through all rectangles of mask
751 const vcl::Region
aWorkRgn(aMask
.CreateRegion(COL_BLACK
, tools::Rectangle(Point(), aMask
.GetSizePixel())));
752 RectangleVector aRectangles
;
753 aWorkRgn
.GetRegionRectangles(aRectangles
);
755 for (auto const& rectangle
: aRectangles
)
757 const Point
aMapPt(pMapX
[rectangle
.Left()], pMapY
[rectangle
.Top()]);
759 pMapX
[rectangle
.Right() + 1] - aMapPt
.X(), // pMapX[L + W] -> L + ((R - L) + 1) -> R + 1
760 pMapY
[rectangle
.Bottom() + 1] - aMapPt
.Y()); // same for Y
762 DrawRect(tools::Rectangle(aMapPt
, aMapSz
));
767 mpMetaFile
= pOldMetaFile
;
770 SalPrinterQueueInfo
* Printer::ImplGetQueueInfo( const OUString
& rPrinterName
,
771 const OUString
* pDriver
)
773 ImplSVData
* pSVData
= ImplGetSVData();
774 if ( !pSVData
->maGDIData
.mpPrinterQueueList
)
775 ImplInitPrnQueueList();
777 ImplPrnQueueList
* pPrnList
= pSVData
->maGDIData
.mpPrinterQueueList
.get();
778 if ( pPrnList
&& !pPrnList
->m_aQueueInfos
.empty() )
780 // first search for the printer name directly
781 ImplPrnQueueData
* pInfo
= pPrnList
->Get( rPrinterName
);
783 return pInfo
->mpSalQueueInfo
.get();
785 // then search case insensitive
786 for(const ImplPrnQueueData
& rQueueInfo
: pPrnList
->m_aQueueInfos
)
788 if( rQueueInfo
.mpSalQueueInfo
->maPrinterName
.equalsIgnoreAsciiCase( rPrinterName
) )
789 return rQueueInfo
.mpSalQueueInfo
.get();
792 // then search for driver name
795 for(const ImplPrnQueueData
& rQueueInfo
: pPrnList
->m_aQueueInfos
)
797 if( rQueueInfo
.mpSalQueueInfo
->maDriver
== *pDriver
)
798 return rQueueInfo
.mpSalQueueInfo
.get();
802 // then the default printer
803 pInfo
= pPrnList
->Get( GetDefaultPrinterName() );
805 return pInfo
->mpSalQueueInfo
.get();
807 // last chance: the first available printer
808 return pPrnList
->m_aQueueInfos
[0].mpSalQueueInfo
.get();
814 void Printer::ImplUpdatePageData()
816 // we need a graphics
817 if ( !AcquireGraphics() )
820 mpGraphics
->GetResolution( mnDPIX
, mnDPIY
);
821 mpInfoPrinter
->GetPageInfo( &maJobSetup
.ImplGetConstData(),
822 mnOutWidth
, mnOutHeight
,
827 void Printer::ImplUpdateFontList()
829 ImplUpdateFontData();
832 long Printer::GetGradientStepCount( long nMinRect
)
834 // use display-equivalent step size calculation
835 long nInc
= (nMinRect
< 800) ? 10 : 20;
841 : OutputDevice(OUTDEV_PRINTER
)
844 SalPrinterQueueInfo
* pInfo
= ImplGetQueueInfo( GetDefaultPrinterName(), nullptr );
848 if ( !IsDisplayPrinter() )
855 Printer::Printer( const JobSetup
& rJobSetup
)
856 : OutputDevice(OUTDEV_PRINTER
)
857 , maJobSetup(rJobSetup
)
860 const ImplJobSetup
& rConstData
= rJobSetup
.ImplGetConstData();
861 OUString aDriver
= rConstData
.GetDriver();
862 SalPrinterQueueInfo
* pInfo
= ImplGetQueueInfo( rConstData
.GetPrinterName(),
867 SetJobSetup( rJobSetup
);
872 maJobSetup
= JobSetup();
876 Printer::Printer( const QueueInfo
& rQueueInfo
)
877 : OutputDevice(OUTDEV_PRINTER
)
880 SalPrinterQueueInfo
* pInfo
= ImplGetQueueInfo( rQueueInfo
.GetPrinterName(),
881 &rQueueInfo
.GetDriver() );
888 Printer::Printer( const OUString
& rPrinterName
)
889 : OutputDevice(OUTDEV_PRINTER
)
892 SalPrinterQueueInfo
* pInfo
= ImplGetQueueInfo( rPrinterName
, nullptr );
904 void Printer::dispose()
906 SAL_WARN_IF( IsPrinting(), "vcl.gdi", "Printer::~Printer() - Job is printing" );
907 SAL_WARN_IF( IsJobActive(), "vcl.gdi", "Printer::~Printer() - Job is active" );
909 mpPrinterOptions
.reset();
913 ImplGetSVData()->mpDefInst
->DestroyInfoPrinter( mpInfoPrinter
);
915 mpDisplayDev
.disposeAndClear();
918 // OutputDevice Dtor is trying the same thing; that why we need to set
919 // the FontEntry to NULL here
920 // TODO: consolidate duplicate cleanup by Printer and OutputDevice
921 mpFontInstance
.clear();
922 mpDeviceFontList
.reset();
923 mpDeviceFontSizeList
.reset();
925 // font list deleted by OutputDevice dtor
928 // Add printer from the list
929 ImplSVData
* pSVData
= ImplGetSVData();
931 mpPrev
->mpNext
= mpNext
;
933 pSVData
->maGDIData
.mpFirstPrinter
= mpNext
;
935 mpNext
->mpPrev
= mpPrev
;
939 OutputDevice::dispose();
942 sal_uInt32
Printer::GetCapabilities( PrinterCapType nType
) const
944 if ( IsDisplayPrinter() )
948 return mpInfoPrinter
->GetCapabilities( &maJobSetup
.ImplGetConstData(), nType
);
953 bool Printer::HasSupport( PrinterSupport eFeature
) const
957 case PrinterSupport::SetOrientation
:
958 return GetCapabilities( PrinterCapType::SetOrientation
) != 0;
959 case PrinterSupport::SetPaperSize
:
960 return GetCapabilities( PrinterCapType::SetPaperSize
) != 0;
961 case PrinterSupport::SetPaper
:
962 return GetCapabilities( PrinterCapType::SetPaper
) != 0;
963 case PrinterSupport::CollateCopy
:
964 return (GetCapabilities( PrinterCapType::CollateCopies
) != 0);
965 case PrinterSupport::SetupDialog
:
966 return GetCapabilities( PrinterCapType::SupportDialog
) != 0;
972 bool Printer::SetJobSetup( const JobSetup
& rSetup
)
974 if ( IsDisplayPrinter() || mbInPrintPage
)
977 JobSetup aJobSetup
= rSetup
;
980 if ( mpInfoPrinter
->SetPrinterData( &aJobSetup
.ImplGetData() ) )
982 ImplUpdateJobSetupPaper( aJobSetup
);
983 mbNewJobSetup
= true;
984 maJobSetup
= aJobSetup
;
985 ImplUpdatePageData();
986 ImplUpdateFontList();
993 bool Printer::Setup(weld::Window
* pWindow
, PrinterSetupMode eMode
)
995 if ( IsDisplayPrinter() )
998 if ( IsJobActive() || IsPrinting() )
1001 JobSetup aJobSetup
= maJobSetup
;
1002 ImplJobSetup
& rData
= aJobSetup
.ImplGetData();
1003 rData
.SetPrinterSetupMode( eMode
);
1004 // TODO: orig page size
1008 vcl::Window
* pDefWin
= ImplGetDefaultWindow();
1009 pWindow
= pDefWin
? pDefWin
->GetFrameWeld() : nullptr;
1015 ImplSVData
* pSVData
= ImplGetSVData();
1016 pSVData
->maAppData
.mnModalMode
++;
1018 bool bSetup
= mpInfoPrinter
->Setup(pWindow
, &rData
);
1019 pSVData
->maAppData
.mnModalMode
--;
1023 ImplUpdateJobSetupPaper( aJobSetup
);
1024 mbNewJobSetup
= true;
1025 maJobSetup
= aJobSetup
;
1026 ImplUpdatePageData();
1027 ImplUpdateFontList();
1033 bool Printer::SetPrinterProps( const Printer
* pPrinter
)
1035 if ( IsJobActive() || IsPrinting() )
1038 ImplSVData
* pSVData
= ImplGetSVData();
1040 mbDefPrinter
= pPrinter
->mbDefPrinter
;
1041 maPrintFile
= pPrinter
->maPrintFile
;
1042 mbPrintFile
= pPrinter
->mbPrintFile
;
1043 mnCopyCount
= pPrinter
->mnCopyCount
;
1044 mbCollateCopy
= pPrinter
->mbCollateCopy
;
1045 mnPageQueueSize
= pPrinter
->mnPageQueueSize
;
1046 *mpPrinterOptions
= *pPrinter
->mpPrinterOptions
;
1048 if ( pPrinter
->IsDisplayPrinter() )
1050 // Destroy old printer
1051 if ( !IsDisplayPrinter() )
1054 pSVData
->mpDefInst
->DestroyInfoPrinter( mpInfoPrinter
);
1055 mpFontInstance
.clear();
1056 mpDeviceFontList
.reset();
1057 mpDeviceFontSizeList
.reset();
1058 // clean up font list
1059 mxFontCache
.reset();
1060 mxFontCollection
.reset();
1064 mpInfoPrinter
= nullptr;
1067 // Construct new printer
1072 // Destroy old printer?
1073 if ( GetName() != pPrinter
->GetName() )
1078 mpDisplayDev
.disposeAndClear();
1082 pSVData
->mpDefInst
->DestroyInfoPrinter( mpInfoPrinter
);
1084 mpFontInstance
.clear();
1085 mpDeviceFontList
.reset();
1086 mpDeviceFontSizeList
.reset();
1087 mxFontCache
.reset();
1088 mxFontCollection
.reset();
1091 mpInfoPrinter
= nullptr;
1094 // Construct new printer
1095 OUString aDriver
= pPrinter
->GetDriverName();
1096 SalPrinterQueueInfo
* pInfo
= ImplGetQueueInfo( pPrinter
->GetName(), &aDriver
);
1100 SetJobSetup( pPrinter
->GetJobSetup() );
1106 SetJobSetup( pPrinter
->GetJobSetup() );
1111 bool Printer::SetOrientation( Orientation eOrientation
)
1113 if ( mbInPrintPage
)
1116 if ( maJobSetup
.ImplGetConstData().GetOrientation() != eOrientation
)
1118 JobSetup aJobSetup
= maJobSetup
;
1119 ImplJobSetup
& rData
= aJobSetup
.ImplGetData();
1121 rData
.SetOrientation(eOrientation
);
1123 if ( IsDisplayPrinter() )
1125 mbNewJobSetup
= true;
1126 maJobSetup
= aJobSetup
;
1131 if ( mpInfoPrinter
->SetData( JobSetFlags::ORIENTATION
, &rData
) )
1133 ImplUpdateJobSetupPaper( aJobSetup
);
1134 mbNewJobSetup
= true;
1135 maJobSetup
= aJobSetup
;
1136 ImplUpdatePageData();
1137 ImplUpdateFontList();
1147 Orientation
Printer::GetOrientation() const
1149 return maJobSetup
.ImplGetConstData().GetOrientation();
1152 bool Printer::SetPaperBin( sal_uInt16 nPaperBin
)
1154 if ( mbInPrintPage
)
1157 if ( maJobSetup
.ImplGetConstData().GetPaperBin() != nPaperBin
&&
1158 nPaperBin
< GetPaperBinCount() )
1160 JobSetup aJobSetup
= maJobSetup
;
1161 ImplJobSetup
& rData
= aJobSetup
.ImplGetData();
1162 rData
.SetPaperBin(nPaperBin
);
1164 if ( IsDisplayPrinter() )
1166 mbNewJobSetup
= true;
1167 maJobSetup
= aJobSetup
;
1172 if ( mpInfoPrinter
->SetData( JobSetFlags::PAPERBIN
, &rData
) )
1174 ImplUpdateJobSetupPaper( aJobSetup
);
1175 mbNewJobSetup
= true;
1176 maJobSetup
= aJobSetup
;
1177 ImplUpdatePageData();
1178 ImplUpdateFontList();
1188 sal_uInt16
Printer::GetPaperBin() const
1190 return maJobSetup
.ImplGetConstData().GetPaperBin();
1193 bool Printer::GetPrinterSettingsPreferred() const
1195 return maJobSetup
.ImplGetConstData().GetPapersizeFromSetup();
1198 // dear loplugins, DO NOT REMOVE this code
1199 // it will be used in follow-up commits
1200 void Printer::SetPrinterSettingsPreferred( bool bPaperSizeFromSetup
)
1202 if ( maJobSetup
.ImplGetConstData().GetPapersizeFromSetup() != bPaperSizeFromSetup
)
1204 JobSetup aJobSetup
= maJobSetup
;
1205 ImplJobSetup
& rData
= aJobSetup
.ImplGetData();
1206 rData
.SetPapersizeFromSetup(bPaperSizeFromSetup
);
1208 mbNewJobSetup
= true;
1209 maJobSetup
= aJobSetup
;
1213 // Map user paper format to an available printer paper format
1214 void Printer::ImplFindPaperFormatForUserSize( JobSetup
& aJobSetup
, bool bMatchNearest
)
1216 ImplJobSetup
& rData
= aJobSetup
.ImplGetData();
1218 // The angle that a landscape page will be turned counterclockwise wrt to portrait.
1219 int nLandscapeAngle
= mpInfoPrinter
? mpInfoPrinter
->GetLandscapeAngle( &maJobSetup
.ImplGetConstData() ) : 900;
1221 int nPaperCount
= GetPaperInfoCount();
1222 bool bFound
= false;
1224 PaperInfo
aInfo(rData
.GetPaperWidth(), rData
.GetPaperHeight());
1226 // Compare all paper formats and get the appropriate one
1227 for ( int i
= 0; i
< nPaperCount
; i
++ )
1229 const PaperInfo
& rPaperInfo
= GetPaperInfo( i
);
1231 if ( aInfo
.sloppyEqual(rPaperInfo
) )
1233 rData
.SetPaperFormat(
1234 ImplGetPaperFormat( rPaperInfo
.getWidth(),
1235 rPaperInfo
.getHeight() ));
1236 rData
.SetOrientation( Orientation::Portrait
);
1242 // If the printer supports landscape orientation, check paper sizes again
1243 // with landscape orientation. This is necessary as a printer driver provides
1244 // all paper sizes with portrait orientation only!!
1245 if ( rData
.GetPaperFormat() == PAPER_USER
&&
1246 nLandscapeAngle
!= 0 &&
1247 HasSupport( PrinterSupport::SetOrientation
))
1249 const long nRotatedWidth
= rData
.GetPaperHeight();
1250 const long nRotatedHeight
= rData
.GetPaperWidth();
1251 PaperInfo
aRotatedInfo(nRotatedWidth
, nRotatedHeight
);
1253 for ( int i
= 0; i
< nPaperCount
; i
++ )
1255 const PaperInfo
& rPaperInfo
= GetPaperInfo( i
);
1257 if ( aRotatedInfo
.sloppyEqual( rPaperInfo
) )
1259 rData
.SetPaperFormat(
1260 ImplGetPaperFormat( rPaperInfo
.getWidth(),
1261 rPaperInfo
.getHeight() ));
1262 rData
.SetOrientation( Orientation::Landscape
);
1269 if( ! bFound
&& bMatchNearest
)
1271 sal_Int64 nBestMatch
= SAL_MAX_INT64
;
1273 Orientation eBestOrientation
= Orientation::Portrait
;
1274 for( int i
= 0; i
< nPaperCount
; i
++ )
1276 const PaperInfo
& rPaperInfo
= GetPaperInfo( i
);
1278 // check portrait match
1279 sal_Int64 nDX
= rData
.GetPaperWidth() - rPaperInfo
.getWidth();
1280 sal_Int64 nDY
= rData
.GetPaperHeight() - rPaperInfo
.getHeight();
1281 sal_Int64 nMatch
= nDX
*nDX
+ nDY
*nDY
;
1282 if( nMatch
< nBestMatch
)
1284 nBestMatch
= nMatch
;
1286 eBestOrientation
= Orientation::Portrait
;
1289 // check landscape match
1290 nDX
= rData
.GetPaperWidth() - rPaperInfo
.getHeight();
1291 nDY
= rData
.GetPaperHeight() - rPaperInfo
.getWidth();
1292 nMatch
= nDX
*nDX
+ nDY
*nDY
;
1293 if( nMatch
< nBestMatch
)
1295 nBestMatch
= nMatch
;
1297 eBestOrientation
= Orientation::Landscape
;
1300 const PaperInfo
& rBestInfo
= GetPaperInfo( nBestIndex
);
1301 rData
.SetPaperFormat(
1302 ImplGetPaperFormat( rBestInfo
.getWidth(),
1303 rBestInfo
.getHeight() ));
1304 rData
.SetOrientation(eBestOrientation
);
1308 void Printer::SetPaper( Paper ePaper
)
1310 if ( mbInPrintPage
)
1313 if ( maJobSetup
.ImplGetConstData().GetPaperFormat() != ePaper
)
1315 JobSetup aJobSetup
= maJobSetup
;
1316 ImplJobSetup
& rData
= aJobSetup
.ImplGetData();
1318 rData
.SetPaperFormat( ePaper
);
1319 if ( ePaper
!= PAPER_USER
)
1321 PaperInfo
aInfo(ePaper
);
1322 rData
.SetPaperWidth( aInfo
.getWidth() );
1323 rData
.SetPaperHeight( aInfo
.getHeight() );
1326 if ( IsDisplayPrinter() )
1328 mbNewJobSetup
= true;
1329 maJobSetup
= aJobSetup
;
1334 if ( ePaper
== PAPER_USER
)
1335 ImplFindPaperFormatForUserSize( aJobSetup
, false );
1336 if ( mpInfoPrinter
->SetData( JobSetFlags::PAPERSIZE
| JobSetFlags::ORIENTATION
, &rData
))
1338 ImplUpdateJobSetupPaper( aJobSetup
);
1339 mbNewJobSetup
= true;
1340 maJobSetup
= aJobSetup
;
1341 ImplUpdatePageData();
1342 ImplUpdateFontList();
1347 bool Printer::SetPaperSizeUser( const Size
& rSize
)
1349 return SetPaperSizeUser( rSize
, false );
1352 bool Printer::SetPaperSizeUser( const Size
& rSize
, bool bMatchNearest
)
1354 if ( mbInPrintPage
)
1357 const Size aPixSize
= LogicToPixel( rSize
);
1358 const Size aPageSize
= PixelToLogic(aPixSize
, MapMode(MapUnit::Map100thMM
));
1359 bool bNeedToChange(maJobSetup
.ImplGetConstData().GetPaperWidth() != aPageSize
.Width() ||
1360 maJobSetup
.ImplGetConstData().GetPaperHeight() != aPageSize
.Height());
1364 // #i122984# only need to change when Paper is different from PAPER_USER and
1365 // the mapped Paper which will created below in the call to ImplFindPaperFormatForUserSize
1366 // and will replace maJobSetup.ImplGetConstData()->GetPaperFormat(). This leads to
1367 // unnecessary JobSetups, e.g. when printing a multi-page fax, but also with
1369 const Paper aPaper
= ImplGetPaperFormat(aPageSize
.Width(), aPageSize
.Height());
1371 bNeedToChange
= maJobSetup
.ImplGetConstData().GetPaperFormat() != PAPER_USER
&&
1372 maJobSetup
.ImplGetConstData().GetPaperFormat() != aPaper
;
1377 JobSetup aJobSetup
= maJobSetup
;
1378 ImplJobSetup
& rData
= aJobSetup
.ImplGetData();
1379 rData
.SetPaperFormat( PAPER_USER
);
1380 rData
.SetPaperWidth( aPageSize
.Width() );
1381 rData
.SetPaperHeight( aPageSize
.Height() );
1383 if ( IsDisplayPrinter() )
1385 mbNewJobSetup
= true;
1386 maJobSetup
= aJobSetup
;
1391 ImplFindPaperFormatForUserSize( aJobSetup
, bMatchNearest
);
1393 // Changing the paper size can also change the orientation!
1394 if ( mpInfoPrinter
->SetData( JobSetFlags::PAPERSIZE
| JobSetFlags::ORIENTATION
, &rData
))
1396 ImplUpdateJobSetupPaper( aJobSetup
);
1397 mbNewJobSetup
= true;
1398 maJobSetup
= aJobSetup
;
1399 ImplUpdatePageData();
1400 ImplUpdateFontList();
1410 int Printer::GetPaperInfoCount() const
1412 if( ! mpInfoPrinter
)
1414 if( ! mpInfoPrinter
->m_bPapersInit
)
1415 mpInfoPrinter
->InitPaperFormats( &maJobSetup
.ImplGetConstData() );
1416 return mpInfoPrinter
->m_aPaperFormats
.size();
1419 OUString
Printer::GetPaperName( Paper ePaper
)
1421 ImplSVData
* pSVData
= ImplGetSVData();
1422 if( pSVData
->maPaperNames
.empty() )
1424 static const int PaperIndex
[] =
1426 PAPER_A0
, PAPER_A1
, PAPER_A2
, PAPER_A3
, PAPER_A4
, PAPER_A5
, PAPER_B4_ISO
, PAPER_B5_ISO
,
1427 PAPER_LETTER
, PAPER_LEGAL
, PAPER_TABLOID
, PAPER_USER
, PAPER_B6_ISO
, PAPER_ENV_C4
, PAPER_ENV_C5
,
1428 PAPER_ENV_C6
, PAPER_ENV_C65
, PAPER_ENV_DL
, PAPER_SLIDE_DIA
, PAPER_SCREEN_4_3
, PAPER_C
, PAPER_D
,
1429 PAPER_E
, PAPER_EXECUTIVE
, PAPER_FANFOLD_LEGAL_DE
, PAPER_ENV_MONARCH
, PAPER_ENV_PERSONAL
, PAPER_ENV_9
,
1430 PAPER_ENV_10
, PAPER_ENV_11
, PAPER_ENV_12
, PAPER_KAI16
, PAPER_KAI32
, PAPER_KAI32BIG
, PAPER_B4_JIS
,
1431 PAPER_B5_JIS
, PAPER_B6_JIS
, PAPER_LEDGER
, PAPER_STATEMENT
, PAPER_QUARTO
, PAPER_10x14
, PAPER_ENV_14
,
1432 PAPER_ENV_C3
, PAPER_ENV_ITALY
, PAPER_FANFOLD_US
, PAPER_FANFOLD_DE
, PAPER_POSTCARD_JP
, PAPER_9x11
,
1433 PAPER_10x11
, PAPER_15x11
, PAPER_ENV_INVITE
, PAPER_A_PLUS
, PAPER_B_PLUS
, PAPER_LETTER_PLUS
, PAPER_A4_PLUS
,
1434 PAPER_DOUBLEPOSTCARD_JP
, PAPER_A6
, PAPER_12x11
, PAPER_A7
, PAPER_A8
, PAPER_A9
, PAPER_A10
, PAPER_B0_ISO
,
1435 PAPER_B1_ISO
, PAPER_B2_ISO
, PAPER_B3_ISO
, PAPER_B7_ISO
, PAPER_B8_ISO
, PAPER_B9_ISO
, PAPER_B10_ISO
,
1436 PAPER_ENV_C2
, PAPER_ENV_C7
, PAPER_ENV_C8
, PAPER_ARCHA
, PAPER_ARCHB
, PAPER_ARCHC
, PAPER_ARCHD
,
1437 PAPER_ARCHE
, PAPER_SCREEN_16_9
, PAPER_SCREEN_16_10
, PAPER_16K_195x270
, PAPER_16K_197x273
1439 assert(SAL_N_ELEMENTS(PaperIndex
) == SAL_N_ELEMENTS(RID_STR_PAPERNAMES
) && "localized paper name count wrong");
1440 for (size_t i
= 0; i
< SAL_N_ELEMENTS(PaperIndex
); ++i
)
1441 pSVData
->maPaperNames
[PaperIndex
[i
]] = VclResId(RID_STR_PAPERNAMES
[i
]);
1444 std::unordered_map
<int,OUString
>::const_iterator it
= pSVData
->maPaperNames
.find( static_cast<int>(ePaper
) );
1445 return (it
!= pSVData
->maPaperNames
.end()) ? it
->second
: OUString();
1448 const PaperInfo
& Printer::GetPaperInfo( int nPaper
) const
1450 if( ! mpInfoPrinter
)
1451 return ImplGetEmptyPaper();
1452 if( ! mpInfoPrinter
->m_bPapersInit
)
1453 mpInfoPrinter
->InitPaperFormats( &maJobSetup
.ImplGetConstData() );
1454 if( mpInfoPrinter
->m_aPaperFormats
.empty() || nPaper
< 0 || nPaper
>= int(mpInfoPrinter
->m_aPaperFormats
.size()) )
1455 return ImplGetEmptyPaper();
1456 return mpInfoPrinter
->m_aPaperFormats
[nPaper
];
1459 Size
Printer::GetPaperSize( int nPaper
)
1461 PaperInfo aInfo
= GetPaperInfo( nPaper
);
1462 return PixelToLogic( Size( aInfo
.getWidth(), aInfo
.getHeight() ) );
1465 void Printer::SetDuplexMode( DuplexMode eDuplex
)
1467 if ( mbInPrintPage
)
1470 if ( maJobSetup
.ImplGetConstData().GetDuplexMode() != eDuplex
)
1472 JobSetup aJobSetup
= maJobSetup
;
1473 ImplJobSetup
& rData
= aJobSetup
.ImplGetData();
1475 rData
.SetDuplexMode( eDuplex
);
1477 if ( IsDisplayPrinter() )
1479 mbNewJobSetup
= true;
1480 maJobSetup
= aJobSetup
;
1485 if ( mpInfoPrinter
->SetData( JobSetFlags::DUPLEXMODE
, &rData
) )
1487 ImplUpdateJobSetupPaper( aJobSetup
);
1488 mbNewJobSetup
= true;
1489 maJobSetup
= aJobSetup
;
1490 ImplUpdatePageData();
1491 ImplUpdateFontList();
1496 DuplexMode
Printer::GetDuplexMode() const
1498 return maJobSetup
.ImplGetConstData().GetDuplexMode();
1501 Paper
Printer::GetPaper() const
1503 return maJobSetup
.ImplGetConstData().GetPaperFormat();
1506 sal_uInt16
Printer::GetPaperBinCount() const
1508 if ( IsDisplayPrinter() )
1511 return mpInfoPrinter
->GetPaperBinCount( &maJobSetup
.ImplGetConstData() );
1514 OUString
Printer::GetPaperBinName( sal_uInt16 nPaperBin
) const
1516 if ( IsDisplayPrinter() )
1519 if ( nPaperBin
< GetPaperBinCount() )
1520 return mpInfoPrinter
->GetPaperBinName( &maJobSetup
.ImplGetConstData(), nPaperBin
);
1525 void Printer::SetCopyCount( sal_uInt16 nCopy
, bool bCollate
)
1527 mnCopyCount
= nCopy
;
1528 mbCollateCopy
= bCollate
;
1531 ErrCode
Printer::ImplSalPrinterErrorCodeToVCL( SalPrinterError nError
)
1536 case SalPrinterError::NONE
:
1537 nVCLError
= ERRCODE_NONE
;
1539 case SalPrinterError::Abort
:
1540 nVCLError
= PRINTER_ABORT
;
1543 nVCLError
= PRINTER_GENERALERROR
;
1550 void Printer::EndJob()
1552 if ( !IsJobActive() )
1555 SAL_WARN_IF( mbInPrintPage
, "vcl.gdi", "Printer::EndJob() - StartPage() without EndPage() called" );
1557 mbJobActive
= false;
1565 mbDevOutput
= false;
1566 mpPrinter
->EndJob();
1571 void Printer::ImplStartPage()
1573 if ( !IsJobActive() )
1578 SalGraphics
* pGraphics
= mpPrinter
->StartPage( &maJobSetup
.ImplGetData(),
1583 mpJobGraphics
= pGraphics
;
1587 // PrintJob not aborted ???
1588 if ( IsJobActive() )
1589 mbInPrintPage
= true;
1593 void Printer::ImplEndPage()
1595 if ( !IsJobActive() )
1598 mbInPrintPage
= false;
1602 mpPrinter
->EndPage();
1604 mbDevOutput
= false;
1606 mpJobGraphics
= nullptr;
1607 mbNewJobSetup
= false;
1611 void Printer::updatePrinters()
1613 ImplSVData
* pSVData
= ImplGetSVData();
1614 ImplPrnQueueList
* pPrnList
= pSVData
->maGDIData
.mpPrinterQueueList
.get();
1618 std::unique_ptr
<ImplPrnQueueList
> pNewList(new ImplPrnQueueList
);
1619 pSVData
->mpDefInst
->GetPrinterQueueInfo( pNewList
.get() );
1621 bool bChanged
= pPrnList
->m_aQueueInfos
.size() != pNewList
->m_aQueueInfos
.size();
1622 for( decltype(pPrnList
->m_aQueueInfos
)::size_type i
= 0; ! bChanged
&& i
< pPrnList
->m_aQueueInfos
.size(); i
++ )
1624 ImplPrnQueueData
& rInfo
= pPrnList
->m_aQueueInfos
[i
];
1625 ImplPrnQueueData
& rNewInfo
= pNewList
->m_aQueueInfos
[i
];
1626 if( ! rInfo
.mpSalQueueInfo
|| ! rNewInfo
.mpSalQueueInfo
|| // sanity check
1627 rInfo
.mpSalQueueInfo
->maPrinterName
!= rNewInfo
.mpSalQueueInfo
->maPrinterName
)
1634 ImplDeletePrnQueueList();
1635 pSVData
->maGDIData
.mpPrinterQueueList
= std::move(pNewList
);
1637 Application
* pApp
= GetpApp();
1640 DataChangedEvent
aDCEvt( DataChangedEventType::PRINTER
);
1641 Application::ImplCallEventListenersApplicationDataChanged(&aDCEvt
);
1642 Application::NotifyAllWindows( aDCEvt
);
1648 bool Printer::UsePolyPolygonForComplexGradient()
1653 void Printer::ClipAndDrawGradientMetafile ( const Gradient
&rGradient
, const tools::PolyPolygon
&rPolyPoly
)
1655 const tools::Rectangle
aBoundRect( rPolyPoly
.GetBoundRect() );
1657 Push( PushFlags::CLIPREGION
);
1658 IntersectClipRegion(vcl::Region(rPolyPoly
));
1659 DrawGradient( aBoundRect
, rGradient
);
1663 void Printer::SetFontOrientation( LogicalFontInstance
* const pFontEntry
) const
1665 pFontEntry
->mnOrientation
= pFontEntry
->mxFontMetric
->GetOrientation();
1668 vcl::Region
Printer::ClipToDeviceBounds(vcl::Region aRegion
) const
1673 Bitmap
Printer::GetBitmap( const Point
& rSrcPt
, const Size
& rSize
) const
1675 SAL_WARN("vcl.gdi", "GetBitmap(): This should never be called on by a Printer instance");
1677 return OutputDevice::GetBitmap( rSrcPt
, rSize
);
1680 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */