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>
22 #include <tools/resary.hxx>
23 #include <tools/helpers.hxx>
25 #include <vcl/virdev.hxx>
26 #include <vcl/print.hxx>
28 #include <comphelper/processfactory.hxx>
30 #include "salinst.hxx"
33 #include "salptype.hxx"
39 #include "PhysicalFontCollection.hxx"
42 #include "com/sun/star/beans/XPropertySet.hpp"
43 #include "com/sun/star/configuration/theDefaultProvider.hpp"
44 #include "com/sun/star/container/XNameAccess.hpp"
45 #include "com/sun/star/lang/XMultiServiceFactory.hpp"
46 #include "com/sun/star/uno/Sequence.h"
48 int nImplSysDialog
= 0;
52 Paper
ImplGetPaperFormat( long nWidth100thMM
, long nHeight100thMM
)
54 PaperInfo
aInfo(nWidth100thMM
, nHeight100thMM
);
56 return aInfo
.getPaper();
59 const PaperInfo
& ImplGetEmptyPaper()
61 static PaperInfo
aInfo(PAPER_USER
);
66 void ImplUpdateJobSetupPaper( JobSetup
& rJobSetup
)
68 const ImplJobSetup
& rConstData
= rJobSetup
.ImplGetConstData();
70 if ( !rConstData
.GetPaperWidth() || !rConstData
.GetPaperHeight() )
72 if ( rConstData
.GetPaperFormat() != PAPER_USER
)
74 PaperInfo
aInfo(rConstData
.GetPaperFormat());
76 ImplJobSetup
& rData
= rJobSetup
.ImplGetData();
77 rData
.SetPaperWidth( aInfo
.getWidth() );
78 rData
.SetPaperHeight( aInfo
.getHeight() );
81 else if ( rConstData
.GetPaperFormat() == PAPER_USER
)
83 Paper ePaper
= ImplGetPaperFormat( rConstData
.GetPaperWidth(), rConstData
.GetPaperHeight() );
84 if ( ePaper
!= PAPER_USER
)
85 rJobSetup
.ImplGetData().SetPaperFormat(ePaper
);
90 PrinterOptions::PrinterOptions() :
91 mbReduceTransparency( false ),
92 meReducedTransparencyMode( PrinterTransparencyMode::Auto
),
93 mbReduceGradients( false ),
94 meReducedGradientsMode( PrinterGradientMode::Stripes
),
95 mnReducedGradientStepCount( 64 ),
96 mbReduceBitmaps( false ),
97 meReducedBitmapMode( PrinterBitmapMode::Normal
),
98 mnReducedBitmapResolution( 200 ),
99 mbReducedBitmapsIncludeTransparency( true ),
100 mbConvertToGreyscales( false ),
101 mbPDFAsStandardPrintJobFormat( false )
105 PrinterOptions::~PrinterOptions()
109 bool PrinterOptions::ReadFromConfig( bool i_bFile
)
111 bool bSuccess
= false;
112 // save old state in case something goes wrong
113 PrinterOptions
aOldValues( *this );
115 // get the configuration service
116 css::uno::Reference
< css::lang::XMultiServiceFactory
> xConfigProvider
;
117 css::uno::Reference
< css::container::XNameAccess
> xConfigAccess
;
120 // get service provider
121 css::uno::Reference
< css::uno::XComponentContext
> xContext( comphelper::getProcessComponentContext() );
122 // create configuration hierarchical access name
125 xConfigProvider
= css::configuration::theDefaultProvider::get( xContext
);
127 css::uno::Sequence
< css::uno::Any
> aArgs(1);
128 css::beans::PropertyValue aVal
;
129 aVal
.Name
= "nodepath";
131 aVal
.Value
<<= OUString( "/org.openoffice.Office.Common/Print/Option/File" );
133 aVal
.Value
<<= OUString( "/org.openoffice.Office.Common/Print/Option/Printer" );
134 aArgs
.getArray()[0] <<= aVal
;
136 xConfigProvider
->createInstanceWithArguments(
137 "com.sun.star.configuration.ConfigurationAccess", aArgs
),
138 css::uno::UNO_QUERY
);
139 if( xConfigAccess
.is() )
141 css::uno::Reference
< css::beans::XPropertySet
> xSet( xConfigAccess
, css::uno::UNO_QUERY
);
144 sal_Int32 nValue
= 0;
146 if( xSet
->getPropertyValue("ReduceTransparency") >>= bValue
)
147 SetReduceTransparency( bValue
);
148 if( xSet
->getPropertyValue("ReducedTransparencyMode") >>= nValue
)
149 SetReducedTransparencyMode( (PrinterTransparencyMode
)nValue
);
150 if( xSet
->getPropertyValue("ReduceGradients") >>= bValue
)
151 SetReduceGradients( bValue
);
152 if( xSet
->getPropertyValue("ReducedGradientMode") >>= nValue
)
153 SetReducedGradientMode( (PrinterGradientMode
)nValue
);
154 if( xSet
->getPropertyValue("ReducedGradientStepCount") >>= nValue
)
155 SetReducedGradientStepCount( (sal_uInt16
)nValue
);
156 if( xSet
->getPropertyValue("ReduceBitmaps") >>= bValue
)
157 SetReduceBitmaps( bValue
);
158 if( xSet
->getPropertyValue("ReducedBitmapMode") >>= nValue
)
159 SetReducedBitmapMode( (PrinterBitmapMode
)nValue
);
160 if( xSet
->getPropertyValue("ReducedBitmapResolution") >>= nValue
)
161 SetReducedBitmapResolution( (sal_uInt16
)nValue
);
162 if( xSet
->getPropertyValue("ReducedBitmapIncludesTransparency") >>= bValue
)
163 SetReducedBitmapIncludesTransparency( bValue
);
164 if( xSet
->getPropertyValue("ConvertToGreyscales") >>= bValue
)
165 SetConvertToGreyscales( bValue
);
166 if( xSet
->getPropertyValue("PDFAsStandardPrintJobFormat") >>= bValue
)
167 SetPDFAsStandardPrintJobFormat( bValue
);
173 catch( const css::uno::Exception
& )
177 catch( const css::lang::WrappedTargetException
& )
186 bool Printer::DrawTransformBitmapExDirect(
187 const basegfx::B2DHomMatrix
& /*aFullTransform*/,
188 const BitmapEx
& /*rBitmapEx*/)
190 // printers can't draw bitmaps directly
194 bool Printer::TransformAndReduceBitmapExToTargetRange(
195 const basegfx::B2DHomMatrix
& /*aFullTransform*/,
196 basegfx::B2DRange
& /*aVisibleRange*/,
197 double& /*fMaximumArea*/)
199 // deliberately do nothing - you can't reduce the
200 // target range for a printer at all
204 void Printer::DrawDeviceBitmap( const Point
& rDestPt
, const Size
& rDestSize
,
205 const Point
& rSrcPtPixel
, const Size
& rSrcSizePixel
,
208 if( rBmpEx
.IsAlpha() )
210 // #107169# For true alpha bitmaps, no longer masking the
211 // bitmap, but perform a full alpha blend against a white
213 Bitmap
aBmp( rBmpEx
.GetBitmap() );
214 aBmp
.Blend( rBmpEx
.GetAlpha(), Color( COL_WHITE
) );
215 DrawBitmap( rDestPt
, rDestSize
, rSrcPtPixel
, rSrcSizePixel
, aBmp
);
219 Bitmap
aBmp( rBmpEx
.GetBitmap() ), aMask( rBmpEx
.GetMask() );
220 aBmp
.Replace( aMask
, Color( COL_WHITE
) );
221 ImplPrintTransparent( aBmp
, aMask
, rDestPt
, rDestSize
, rSrcPtPixel
, rSrcSizePixel
);
225 void Printer::EmulateDrawTransparent ( const tools::PolyPolygon
& rPolyPoly
,
226 sal_uInt16 nTransparencePercent
)
228 // #110958# Disable alpha VDev, we perform the necessary
229 VirtualDevice
* pOldAlphaVDev
= mpAlphaVDev
;
231 // operation explicitly further below.
233 mpAlphaVDev
= nullptr;
235 GDIMetaFile
* pOldMetaFile
= mpMetaFile
;
236 mpMetaFile
= nullptr;
238 mpMetaFile
= pOldMetaFile
;
240 // #110958# Restore disabled alpha VDev
241 mpAlphaVDev
= pOldAlphaVDev
;
243 tools::Rectangle
aPolyRect( LogicToPixel( rPolyPoly
).GetBoundRect() );
244 const Size
aDPISize( LogicToPixel( Size( 1, 1 ), MapUnit::MapInch
) );
245 const long nBaseExtent
= std::max( FRound( aDPISize
.Width() / 300. ), 1L );
247 const sal_uInt16 nTrans
= ( nTransparencePercent
< 13 ) ? 0 :
248 ( nTransparencePercent
< 38 ) ? 25 :
249 ( nTransparencePercent
< 63 ) ? 50 :
250 ( nTransparencePercent
< 88 ) ? 75 : 100;
254 case 25: nMove
= nBaseExtent
* 3; break;
255 case 50: nMove
= nBaseExtent
* 4; break;
256 case 75: nMove
= nBaseExtent
* 6; break;
258 // #i112959# very transparent (88 < nTransparencePercent <= 99)
259 case 100: nMove
= nBaseExtent
* 8; break;
261 // #i112959# not transparent (nTransparencePercent < 13)
262 default: nMove
= 0; break;
265 Push( PushFlags::CLIPREGION
| PushFlags::LINECOLOR
);
266 IntersectClipRegion(vcl::Region(rPolyPoly
));
267 SetLineColor( GetFillColor() );
268 const bool bOldMap
= mbMap
;
269 EnableMapMode( false );
273 tools::Rectangle
aRect( aPolyRect
.TopLeft(), Size( aPolyRect
.GetWidth(), nBaseExtent
) );
274 while( aRect
.Top() <= aPolyRect
.Bottom() )
277 aRect
.Move( 0, nMove
);
280 aRect
= tools::Rectangle( aPolyRect
.TopLeft(), Size( nBaseExtent
, aPolyRect
.GetHeight() ) );
281 while( aRect
.Left() <= aPolyRect
.Right() )
284 aRect
.Move( nMove
, 0 );
289 // #i112959# if not transparent, draw full rectangle in clip region
290 DrawRect( aPolyRect
);
293 EnableMapMode( bOldMap
);
296 mpMetaFile
= pOldMetaFile
;
298 // #110958# Restore disabled alpha VDev
299 mpAlphaVDev
= pOldAlphaVDev
;
302 void Printer::DrawOutDev( const Point
& /*rDestPt*/, const Size
& /*rDestSize*/,
303 const Point
& /*rSrcPt*/, const Size
& /*rSrcSize*/ )
305 SAL_WARN( "vcl.gdi", "Don't use OutputDevice::DrawOutDev(...) with printer devices!" );
308 void Printer::DrawOutDev( const Point
& /*rDestPt*/, const Size
& /*rDestSize*/,
309 const Point
& /*rSrcPt*/, const Size
& /*rSrcSize*/,
310 const OutputDevice
& /*rOutDev*/ )
312 SAL_WARN( "vcl.gdi", "Don't use OutputDevice::DrawOutDev(...) with printer devices!" );
315 void Printer::CopyArea( const Point
& /*rDestPt*/,
316 const Point
& /*rSrcPt*/, const Size
& /*rSrcSize*/,
317 bool /*bWindowInvalidate*/ )
319 SAL_WARN( "vcl.gdi", "Don't use OutputDevice::CopyArea(...) with printer devices!" );
322 void Printer::SetPrinterOptions( const PrinterOptions
& i_rOptions
)
324 *mpPrinterOptions
= i_rOptions
;
327 bool Printer::HasMirroredGraphics() const
329 // due to a "hotfix" for AOO bug i55719, this needs to return false
334 QueueInfo::QueueInfo()
336 mnStatus
= PrintQueueFlags::NONE
;
340 QueueInfo::QueueInfo( const QueueInfo
& rInfo
) :
341 maPrinterName( rInfo
.maPrinterName
),
342 maDriver( rInfo
.maDriver
),
343 maLocation( rInfo
.maLocation
),
344 maComment( rInfo
.maComment
),
345 mnStatus( rInfo
.mnStatus
),
346 mnJobs( rInfo
.mnJobs
)
350 QueueInfo::~QueueInfo()
354 SalPrinterQueueInfo::SalPrinterQueueInfo()
356 mnStatus
= PrintQueueFlags::NONE
;
357 mnJobs
= QUEUE_JOBS_DONTKNOW
;
361 SalPrinterQueueInfo::~SalPrinterQueueInfo()
365 ImplPrnQueueList::~ImplPrnQueueList()
367 ImplSVData
* pSVData
= ImplGetSVData();
368 for(ImplPrnQueueData
& rQueueInfo
: m_aQueueInfos
)
370 delete rQueueInfo
.mpQueueInfo
;
371 pSVData
->mpDefInst
->DeletePrinterQueueInfo( rQueueInfo
.mpSalQueueInfo
);
375 void ImplPrnQueueList::Add( SalPrinterQueueInfo
* pData
)
377 std::unordered_map
< OUString
, sal_Int32
, OUStringHash
>::iterator it
=
378 m_aNameToIndex
.find( pData
->maPrinterName
);
379 if( it
== m_aNameToIndex
.end() )
381 m_aNameToIndex
[ pData
->maPrinterName
] = m_aQueueInfos
.size();
382 m_aQueueInfos
.push_back( ImplPrnQueueData() );
383 m_aQueueInfos
.back().mpQueueInfo
= nullptr;
384 m_aQueueInfos
.back().mpSalQueueInfo
= pData
;
385 m_aPrinterList
.push_back( pData
->maPrinterName
);
387 else // this should not happen, but ...
389 ImplPrnQueueData
& rData
= m_aQueueInfos
[ it
->second
];
390 delete rData
.mpQueueInfo
;
391 rData
.mpQueueInfo
= nullptr;
392 ImplGetSVData()->mpDefInst
->DeletePrinterQueueInfo( rData
.mpSalQueueInfo
);
393 rData
.mpSalQueueInfo
= pData
;
397 ImplPrnQueueData
* ImplPrnQueueList::Get( const OUString
& rPrinter
)
399 ImplPrnQueueData
* pData
= nullptr;
400 std::unordered_map
<OUString
,sal_Int32
,OUStringHash
>::iterator it
=
401 m_aNameToIndex
.find( rPrinter
);
402 if( it
!= m_aNameToIndex
.end() )
403 pData
= &m_aQueueInfos
[it
->second
];
407 static void ImplInitPrnQueueList()
409 ImplSVData
* pSVData
= ImplGetSVData();
411 pSVData
->maGDIData
.mpPrinterQueueList
= new ImplPrnQueueList
;
413 static const char* pEnv
= getenv( "SAL_DISABLE_PRINTERLIST" );
414 if( !pEnv
|| !*pEnv
)
415 pSVData
->mpDefInst
->GetPrinterQueueInfo( pSVData
->maGDIData
.mpPrinterQueueList
);
418 void ImplDeletePrnQueueList()
420 ImplSVData
* pSVData
= ImplGetSVData();
421 ImplPrnQueueList
* pPrnList
= pSVData
->maGDIData
.mpPrinterQueueList
;
426 pSVData
->maGDIData
.mpPrinterQueueList
= nullptr;
430 const std::vector
<OUString
>& Printer::GetPrinterQueues()
432 ImplSVData
* pSVData
= ImplGetSVData();
433 if ( !pSVData
->maGDIData
.mpPrinterQueueList
)
434 ImplInitPrnQueueList();
435 return pSVData
->maGDIData
.mpPrinterQueueList
->m_aPrinterList
;
438 const QueueInfo
* Printer::GetQueueInfo( const OUString
& rPrinterName
, bool bStatusUpdate
)
440 ImplSVData
* pSVData
= ImplGetSVData();
442 if ( !pSVData
->maGDIData
.mpPrinterQueueList
)
443 ImplInitPrnQueueList();
445 if ( !pSVData
->maGDIData
.mpPrinterQueueList
)
448 ImplPrnQueueData
* pInfo
= pSVData
->maGDIData
.mpPrinterQueueList
->Get( rPrinterName
);
451 if( !pInfo
->mpQueueInfo
|| bStatusUpdate
)
452 pSVData
->mpDefInst
->GetPrinterQueueState( pInfo
->mpSalQueueInfo
);
454 if ( !pInfo
->mpQueueInfo
)
455 pInfo
->mpQueueInfo
= new QueueInfo
;
457 pInfo
->mpQueueInfo
->maPrinterName
= pInfo
->mpSalQueueInfo
->maPrinterName
;
458 pInfo
->mpQueueInfo
->maDriver
= pInfo
->mpSalQueueInfo
->maDriver
;
459 pInfo
->mpQueueInfo
->maLocation
= pInfo
->mpSalQueueInfo
->maLocation
;
460 pInfo
->mpQueueInfo
->maComment
= pInfo
->mpSalQueueInfo
->maComment
;
461 pInfo
->mpQueueInfo
->mnStatus
= pInfo
->mpSalQueueInfo
->mnStatus
;
462 pInfo
->mpQueueInfo
->mnJobs
= pInfo
->mpSalQueueInfo
->mnJobs
;
463 return pInfo
->mpQueueInfo
;
468 OUString
Printer::GetDefaultPrinterName()
470 static const char* pEnv
= getenv( "SAL_DISABLE_DEFAULTPRINTER" );
471 if( !pEnv
|| !*pEnv
)
473 ImplSVData
* pSVData
= ImplGetSVData();
475 return pSVData
->mpDefInst
->GetDefaultPrinter();
480 void Printer::ImplInitData()
483 meOutDevType
= OUTDEV_PRINTER
;
484 mbDefPrinter
= false;
490 mbCollateCopy
= false;
494 mbInPrintPage
= false;
495 mbNewJobSetup
= false;
496 mpInfoPrinter
= nullptr;
498 mpDisplayDev
= nullptr;
499 mpPrinterOptions
= new PrinterOptions
;
501 // Add printer to the list
502 ImplSVData
* pSVData
= ImplGetSVData();
503 mpNext
= pSVData
->maGDIData
.mpFirstPrinter
;
506 mpNext
->mpPrev
= this;
508 pSVData
->maGDIData
.mpLastPrinter
= this;
509 pSVData
->maGDIData
.mpFirstPrinter
= this;
512 bool Printer::AcquireGraphics() const
514 DBG_TESTSOLARMUTEX();
519 mbInitLineColor
= true;
520 mbInitFillColor
= true;
522 mbInitTextColor
= true;
523 mbInitClipRegion
= true;
525 ImplSVData
* pSVData
= ImplGetSVData();
528 mpGraphics
= mpJobGraphics
;
529 else if ( mpDisplayDev
)
531 const VirtualDevice
* pVirDev
= mpDisplayDev
;
532 mpGraphics
= pVirDev
->mpVirDev
->AcquireGraphics();
533 // if needed retry after releasing least recently used virtual device graphics
534 while ( !mpGraphics
)
536 if ( !pSVData
->maGDIData
.mpLastVirGraphics
)
538 pSVData
->maGDIData
.mpLastVirGraphics
->ReleaseGraphics();
539 mpGraphics
= pVirDev
->mpVirDev
->AcquireGraphics();
541 // update global LRU list of virtual device graphics
544 mpNextGraphics
= pSVData
->maGDIData
.mpFirstVirGraphics
;
545 pSVData
->maGDIData
.mpFirstVirGraphics
= const_cast<Printer
*>(this);
546 if ( mpNextGraphics
)
547 mpNextGraphics
->mpPrevGraphics
= const_cast<Printer
*>(this);
548 if ( !pSVData
->maGDIData
.mpLastVirGraphics
)
549 pSVData
->maGDIData
.mpLastVirGraphics
= const_cast<Printer
*>(this);
554 mpGraphics
= mpInfoPrinter
->AcquireGraphics();
555 // if needed retry after releasing least recently used printer graphics
556 while ( !mpGraphics
)
558 if ( !pSVData
->maGDIData
.mpLastPrnGraphics
)
560 pSVData
->maGDIData
.mpLastPrnGraphics
->ReleaseGraphics();
561 mpGraphics
= mpInfoPrinter
->AcquireGraphics();
563 // update global LRU list of printer graphics
566 mpNextGraphics
= pSVData
->maGDIData
.mpFirstPrnGraphics
;
567 pSVData
->maGDIData
.mpFirstPrnGraphics
= const_cast<Printer
*>(this);
568 if ( mpNextGraphics
)
569 mpNextGraphics
->mpPrevGraphics
= const_cast<Printer
*>(this);
570 if ( !pSVData
->maGDIData
.mpLastPrnGraphics
)
571 pSVData
->maGDIData
.mpLastPrnGraphics
= const_cast<Printer
*>(this);
577 mpGraphics
->SetXORMode( (RasterOp::Invert
== meRasterOp
) || (RasterOp::Xor
== meRasterOp
) );
578 mpGraphics
->setAntiAliasB2DDraw(bool(mnAntialiasing
& AntialiasingFlags::EnableB2dDraw
));
581 return mpGraphics
!= nullptr;
584 void Printer::ImplReleaseFonts()
587 // HACK to fix an urgent P1 printing issue fast
588 // WinSalPrinter does not respect GetGraphics/ReleaseGraphics conventions
589 // so Printer::mpGraphics often points to a dead WinSalGraphics
590 // TODO: fix WinSalPrinter's GetGraphics/ReleaseGraphics handling
591 mpGraphics
->ReleaseFonts();
596 if ( mpFontInstance
)
598 mpFontCache
->Release( mpFontInstance
);
599 mpFontInstance
= nullptr;
602 if ( mpDeviceFontList
)
604 delete mpDeviceFontList
;
605 mpDeviceFontList
= nullptr;
608 if ( mpDeviceFontSizeList
)
610 delete mpDeviceFontSizeList
;
611 mpDeviceFontSizeList
= nullptr;
615 void Printer::ReleaseGraphics( bool bRelease
)
617 DBG_TESTSOLARMUTEX();
622 // release the fonts of the physically released graphics device
626 ImplSVData
* pSVData
= ImplGetSVData();
628 Printer
* pPrinter
= this;
630 if ( !pPrinter
->mpJobGraphics
)
632 if ( pPrinter
->mpDisplayDev
)
634 VirtualDevice
* pVirDev
= pPrinter
->mpDisplayDev
;
636 pVirDev
->mpVirDev
->ReleaseGraphics( mpGraphics
);
637 // remove from global LRU list of virtual device graphics
638 if ( mpPrevGraphics
)
639 mpPrevGraphics
->mpNextGraphics
= mpNextGraphics
;
641 pSVData
->maGDIData
.mpFirstVirGraphics
= mpNextGraphics
;
642 if ( mpNextGraphics
)
643 mpNextGraphics
->mpPrevGraphics
= mpPrevGraphics
;
645 pSVData
->maGDIData
.mpLastVirGraphics
= mpPrevGraphics
;
650 pPrinter
->mpInfoPrinter
->ReleaseGraphics( mpGraphics
);
651 // remove from global LRU list of printer graphics
652 if ( mpPrevGraphics
)
653 mpPrevGraphics
->mpNextGraphics
= mpNextGraphics
;
655 pSVData
->maGDIData
.mpFirstPrnGraphics
= mpNextGraphics
;
656 if ( mpNextGraphics
)
657 mpNextGraphics
->mpPrevGraphics
= mpPrevGraphics
;
659 pSVData
->maGDIData
.mpLastPrnGraphics
= mpPrevGraphics
;
663 mpGraphics
= nullptr;
664 mpPrevGraphics
= nullptr;
665 mpNextGraphics
= nullptr;
668 void Printer::ImplInit( SalPrinterQueueInfo
* pInfo
)
670 ImplSVData
* pSVData
= ImplGetSVData();
671 // #i74084# update info for this specific SalPrinterQueueInfo
672 pSVData
->mpDefInst
->GetPrinterQueueState( pInfo
);
674 // Test whether the driver actually matches the JobSetup
675 ImplJobSetup
& rData
= maJobSetup
.ImplGetData();
676 if ( rData
.GetDriverData() )
678 if ( rData
.GetPrinterName() != pInfo
->maPrinterName
||
679 rData
.GetDriver() != pInfo
->maDriver
)
681 rtl_freeMemory( const_cast<sal_uInt8
*>(rData
.GetDriverData()) );
682 rData
.SetDriverData(nullptr);
683 rData
.SetDriverDataLen(0);
687 // Remember printer name
688 maPrinterName
= pInfo
->maPrinterName
;
689 maDriver
= pInfo
->maDriver
;
691 // Add printer name to JobSetup
692 rData
.SetPrinterName( maPrinterName
);
693 rData
.SetDriver( maDriver
);
695 mpInfoPrinter
= pSVData
->mpDefInst
->CreateInfoPrinter( pInfo
, &rData
);
697 mpJobGraphics
= nullptr;
698 ImplUpdateJobSetupPaper( maJobSetup
);
700 if ( !mpInfoPrinter
)
706 // we need a graphics
707 if ( !AcquireGraphics() )
714 ImplUpdatePageData();
715 mpFontCollection
= new PhysicalFontCollection();
716 mpFontCache
= new ImplFontCache();
717 mpGraphics
->GetDevFontList( mpFontCollection
);
720 void Printer::ImplInitDisplay()
722 ImplSVData
* pSVData
= ImplGetSVData();
724 mpInfoPrinter
= nullptr;
726 mpJobGraphics
= nullptr;
728 mpDisplayDev
= VclPtr
<VirtualDevice
>::Create();
729 mpFontCollection
= pSVData
->maGDIData
.mpScreenFontList
;
730 mpFontCache
= pSVData
->maGDIData
.mpScreenFontCache
;
731 mnDPIX
= mpDisplayDev
->mnDPIX
;
732 mnDPIY
= mpDisplayDev
->mnDPIY
;
735 void Printer::DrawDeviceMask( const Bitmap
& rMask
, const Color
& rMaskColor
,
736 const Point
& rDestPt
, const Size
& rDestSize
,
737 const Point
& rSrcPtPixel
, const Size
& rSrcSizePixel
)
740 Point
aDestPt( LogicToPixel( rDestPt
) );
741 Size
aDestSz( LogicToPixel( rDestSize
) );
742 tools::Rectangle
aSrcRect( rSrcPtPixel
, rSrcSizePixel
);
746 if( !rMask
.IsEmpty() && aSrcRect
.GetWidth() && aSrcRect
.GetHeight() && aDestSz
.Width() && aDestSz
.Height() )
748 Bitmap
aMask( rMask
);
749 BmpMirrorFlags nMirrFlags
= BmpMirrorFlags::NONE
;
751 if( aMask
.GetBitCount() > 1 )
752 aMask
.Convert( BmpConversion::N1BitThreshold
);
754 // mirrored horizontically
755 if( aDestSz
.Width() < 0 )
757 aDestSz
.Width() = -aDestSz
.Width();
758 aDestPt
.X() -= ( aDestSz
.Width() - 1 );
759 nMirrFlags
|= BmpMirrorFlags::Horizontal
;
762 // mirrored vertically
763 if( aDestSz
.Height() < 0 )
765 aDestSz
.Height() = -aDestSz
.Height();
766 aDestPt
.Y() -= ( aDestSz
.Height() - 1 );
767 nMirrFlags
|= BmpMirrorFlags::Vertical
;
771 if( aSrcRect
!= tools::Rectangle( aPt
, aMask
.GetSizePixel() ) )
772 aMask
.Crop( aSrcRect
);
774 // destination mirrored
775 if( nMirrFlags
!= BmpMirrorFlags::NONE
)
776 aMask
.Mirror( nMirrFlags
);
779 const long nSrcWidth
= aSrcRect
.GetWidth(), nSrcHeight
= aSrcRect
.GetHeight();
780 long nX
, nY
; //, nWorkX, nWorkY, nWorkWidth, nWorkHeight;
781 long* pMapX
= new long[ nSrcWidth
+ 1 ];
782 long* pMapY
= new long[ nSrcHeight
+ 1 ];
783 GDIMetaFile
* pOldMetaFile
= mpMetaFile
;
784 const bool bOldMap
= mbMap
;
786 mpMetaFile
= nullptr;
788 Push( PushFlags::FILLCOLOR
| PushFlags::LINECOLOR
);
789 SetLineColor( rMaskColor
);
790 SetFillColor( rMaskColor
);
794 // create forward mapping tables
795 for( nX
= 0; nX
<= nSrcWidth
; nX
++ )
796 pMapX
[ nX
] = aDestPt
.X() + FRound( (double) aDestSz
.Width() * nX
/ nSrcWidth
);
798 for( nY
= 0; nY
<= nSrcHeight
; nY
++ )
799 pMapY
[ nY
] = aDestPt
.Y() + FRound( (double) aDestSz
.Height() * nY
/ nSrcHeight
);
801 // walk through all rectangles of mask
802 const vcl::Region
aWorkRgn(aMask
.CreateRegion(COL_BLACK
, tools::Rectangle(Point(), aMask
.GetSizePixel())));
803 RectangleVector aRectangles
;
804 aWorkRgn
.GetRegionRectangles(aRectangles
);
806 for(RectangleVector::const_iterator
aRectIter(aRectangles
.begin()); aRectIter
!= aRectangles
.end(); ++aRectIter
)
808 const Point
aMapPt(pMapX
[aRectIter
->Left()], pMapY
[aRectIter
->Top()]);
810 pMapX
[aRectIter
->Right() + 1] - aMapPt
.X(), // pMapX[L + W] -> L + ((R - L) + 1) -> R + 1
811 pMapY
[aRectIter
->Bottom() + 1] - aMapPt
.Y()); // same for Y
813 DrawRect(tools::Rectangle(aMapPt
, aMapSz
));
820 mpMetaFile
= pOldMetaFile
;
824 SalPrinterQueueInfo
* Printer::ImplGetQueueInfo( const OUString
& rPrinterName
,
825 const OUString
* pDriver
)
827 ImplSVData
* pSVData
= ImplGetSVData();
828 if ( !pSVData
->maGDIData
.mpPrinterQueueList
)
829 ImplInitPrnQueueList();
831 ImplPrnQueueList
* pPrnList
= pSVData
->maGDIData
.mpPrinterQueueList
;
832 if ( pPrnList
&& pPrnList
->m_aQueueInfos
.size() )
834 // first search for the printer name directly
835 ImplPrnQueueData
* pInfo
= pPrnList
->Get( rPrinterName
);
837 return pInfo
->mpSalQueueInfo
;
839 // then search case insensitive
840 for(ImplPrnQueueData
& rQueueInfo
: pPrnList
->m_aQueueInfos
)
842 if( rQueueInfo
.mpSalQueueInfo
->maPrinterName
.equalsIgnoreAsciiCase( rPrinterName
) )
843 return rQueueInfo
.mpSalQueueInfo
;
846 // then search for driver name
849 for(ImplPrnQueueData
& rQueueInfo
: pPrnList
->m_aQueueInfos
)
851 if( rQueueInfo
.mpSalQueueInfo
->maDriver
== *pDriver
)
852 return rQueueInfo
.mpSalQueueInfo
;
856 // then the default printer
857 pInfo
= pPrnList
->Get( GetDefaultPrinterName() );
859 return pInfo
->mpSalQueueInfo
;
861 // last chance: the first available printer
862 return pPrnList
->m_aQueueInfos
[0].mpSalQueueInfo
;
868 void Printer::ImplUpdatePageData()
870 // we need a graphics
871 if ( !AcquireGraphics() )
874 mpGraphics
->GetResolution( mnDPIX
, mnDPIY
);
875 mpInfoPrinter
->GetPageInfo( &maJobSetup
.ImplGetConstData(),
876 mnOutWidth
, mnOutHeight
,
877 maPageOffset
.X(), maPageOffset
.Y(),
878 maPaperSize
.Width(), maPaperSize
.Height() );
881 void Printer::ImplUpdateFontList()
883 ImplUpdateFontData();
886 long Printer::GetGradientStepCount( long nMinRect
)
888 // use display-equivalent step size calculation
889 long nInc
= (nMinRect
< 800) ? 10 : 20;
897 SalPrinterQueueInfo
* pInfo
= ImplGetQueueInfo( GetDefaultPrinterName(), nullptr );
901 if ( !IsDisplayPrinter() )
908 Printer::Printer( const JobSetup
& rJobSetup
) :
909 maJobSetup( rJobSetup
)
912 const ImplJobSetup
& rConstData
= rJobSetup
.ImplGetConstData();
913 OUString aDriver
= rConstData
.GetDriver();
914 SalPrinterQueueInfo
* pInfo
= ImplGetQueueInfo( rConstData
.GetPrinterName(),
919 SetJobSetup( rJobSetup
);
924 maJobSetup
= JobSetup();
928 Printer::Printer( const QueueInfo
& rQueueInfo
)
931 SalPrinterQueueInfo
* pInfo
= ImplGetQueueInfo( rQueueInfo
.GetPrinterName(),
932 &rQueueInfo
.GetDriver() );
939 Printer::Printer( const OUString
& rPrinterName
)
942 SalPrinterQueueInfo
* pInfo
= ImplGetQueueInfo( rPrinterName
, nullptr );
954 void Printer::dispose()
956 SAL_WARN_IF( IsPrinting(), "vcl.gdi", "Printer::~Printer() - Job is printing" );
957 SAL_WARN_IF( IsJobActive(), "vcl.gdi", "Printer::~Printer() - Job is active" );
959 delete mpPrinterOptions
;
960 mpPrinterOptions
= nullptr;
964 ImplGetSVData()->mpDefInst
->DestroyInfoPrinter( mpInfoPrinter
);
966 mpDisplayDev
.disposeAndClear();
969 // OutputDevice Dtor is trying the same thing; that why we need to set
970 // the FontEntry to NULL here
971 // TODO: consolidate duplicate cleanup by Printer and OutputDevice
972 if ( mpFontInstance
)
974 mpFontCache
->Release( mpFontInstance
);
975 mpFontInstance
= nullptr;
977 if ( mpDeviceFontList
)
979 delete mpDeviceFontList
;
980 mpDeviceFontList
= nullptr;
982 if ( mpDeviceFontSizeList
)
984 delete mpDeviceFontSizeList
;
985 mpDeviceFontSizeList
= nullptr;
988 mpFontCache
= nullptr;
989 // font list deleted by OutputDevice dtor
992 // Add printer from the list
993 ImplSVData
* pSVData
= ImplGetSVData();
995 mpPrev
->mpNext
= mpNext
;
997 pSVData
->maGDIData
.mpFirstPrinter
= mpNext
;
999 mpNext
->mpPrev
= mpPrev
;
1001 pSVData
->maGDIData
.mpLastPrinter
= mpPrev
;
1005 OutputDevice::dispose();
1008 sal_uInt32
Printer::GetCapabilities( PrinterCapType nType
) const
1010 if ( IsDisplayPrinter() )
1014 return mpInfoPrinter
->GetCapabilities( &maJobSetup
.ImplGetConstData(), nType
);
1019 bool Printer::HasSupport( PrinterSupport eFeature
) const
1023 case PrinterSupport::SetOrientation
:
1024 return GetCapabilities( PrinterCapType::SetOrientation
) != 0;
1025 case PrinterSupport::SetPaperSize
:
1026 return GetCapabilities( PrinterCapType::SetPaperSize
) != 0;
1027 case PrinterSupport::SetPaper
:
1028 return GetCapabilities( PrinterCapType::SetPaper
) != 0;
1029 case PrinterSupport::CollateCopy
:
1030 return (GetCapabilities( PrinterCapType::CollateCopies
) != 0);
1031 case PrinterSupport::SetupDialog
:
1032 return GetCapabilities( PrinterCapType::SupportDialog
) != 0;
1038 bool Printer::SetJobSetup( const JobSetup
& rSetup
)
1040 if ( IsDisplayPrinter() || mbInPrintPage
)
1043 JobSetup aJobSetup
= rSetup
;
1046 if ( mpInfoPrinter
->SetPrinterData( &aJobSetup
.ImplGetData() ) )
1048 ImplUpdateJobSetupPaper( aJobSetup
);
1049 mbNewJobSetup
= true;
1050 maJobSetup
= aJobSetup
;
1051 ImplUpdatePageData();
1052 ImplUpdateFontList();
1059 bool Printer::Setup( vcl::Window
* pWindow
, bool bPapersizeFromSetup
)
1061 if ( IsDisplayPrinter() )
1064 if ( IsJobActive() || IsPrinting() )
1067 JobSetup aJobSetup
= maJobSetup
;
1068 ImplJobSetup
& rData
= aJobSetup
.ImplGetData();
1069 rData
.SetPapersizeFromSetup( bPapersizeFromSetup
);
1072 pWindow
= ImplGetDefaultWindow();
1076 pFrame
= pWindow
->ImplGetFrame();
1078 ImplSVData
* pSVData
= ImplGetSVData();
1079 pSVData
->maAppData
.mnModalMode
++;
1081 bool bSetup
= mpInfoPrinter
->Setup( pFrame
, &rData
);
1082 pSVData
->maAppData
.mnModalMode
--;
1086 ImplUpdateJobSetupPaper( aJobSetup
);
1087 mbNewJobSetup
= true;
1088 maJobSetup
= aJobSetup
;
1089 ImplUpdatePageData();
1090 ImplUpdateFontList();
1096 bool Printer::SetPrinterProps( const Printer
* pPrinter
)
1098 if ( IsJobActive() || IsPrinting() )
1101 ImplSVData
* pSVData
= ImplGetSVData();
1103 mbDefPrinter
= pPrinter
->mbDefPrinter
;
1104 maPrintFile
= pPrinter
->maPrintFile
;
1105 mbPrintFile
= pPrinter
->mbPrintFile
;
1106 mnCopyCount
= pPrinter
->mnCopyCount
;
1107 mbCollateCopy
= pPrinter
->mbCollateCopy
;
1108 mnPageQueueSize
= pPrinter
->mnPageQueueSize
;
1109 *mpPrinterOptions
= *pPrinter
->mpPrinterOptions
;
1111 if ( pPrinter
->IsDisplayPrinter() )
1113 // Destroy old printer
1114 if ( !IsDisplayPrinter() )
1117 pSVData
->mpDefInst
->DestroyInfoPrinter( mpInfoPrinter
);
1118 if ( mpFontInstance
)
1120 mpFontCache
->Release( mpFontInstance
);
1121 mpFontInstance
= nullptr;
1123 if ( mpDeviceFontList
)
1125 delete mpDeviceFontList
;
1126 mpDeviceFontList
= nullptr;
1128 if ( mpDeviceFontSizeList
)
1130 delete mpDeviceFontSizeList
;
1131 mpDeviceFontSizeList
= nullptr;
1133 // clean up font list
1135 delete mpFontCollection
;
1136 mpFontCache
= nullptr;
1137 mpFontCollection
= nullptr;
1141 mpInfoPrinter
= nullptr;
1144 // Construct new printer
1149 // Destroy old printer?
1150 if ( GetName() != pPrinter
->GetName() )
1155 mpDisplayDev
.disposeAndClear();
1159 pSVData
->mpDefInst
->DestroyInfoPrinter( mpInfoPrinter
);
1161 if ( mpFontInstance
)
1163 mpFontCache
->Release( mpFontInstance
);
1164 mpFontInstance
= nullptr;
1166 if ( mpDeviceFontList
)
1168 delete mpDeviceFontList
;
1169 mpDeviceFontList
= nullptr;
1171 if ( mpDeviceFontSizeList
)
1173 delete mpDeviceFontSizeList
;
1174 mpDeviceFontSizeList
= nullptr;
1177 delete mpFontCollection
;
1178 mpFontCache
= nullptr;
1179 mpFontCollection
= nullptr;
1182 mpInfoPrinter
= nullptr;
1185 // Construct new printer
1186 OUString aDriver
= pPrinter
->GetDriverName();
1187 SalPrinterQueueInfo
* pInfo
= ImplGetQueueInfo( pPrinter
->GetName(), &aDriver
);
1191 SetJobSetup( pPrinter
->GetJobSetup() );
1197 SetJobSetup( pPrinter
->GetJobSetup() );
1202 bool Printer::SetOrientation( Orientation eOrientation
)
1204 if ( mbInPrintPage
)
1207 if ( maJobSetup
.ImplGetConstData().GetOrientation() != eOrientation
)
1209 JobSetup aJobSetup
= maJobSetup
;
1210 ImplJobSetup
& rData
= aJobSetup
.ImplGetData();
1212 rData
.SetOrientation(eOrientation
);
1214 if ( IsDisplayPrinter() )
1216 mbNewJobSetup
= true;
1217 maJobSetup
= aJobSetup
;
1222 if ( mpInfoPrinter
->SetData( JobSetFlags::ORIENTATION
, &rData
) )
1224 ImplUpdateJobSetupPaper( aJobSetup
);
1225 mbNewJobSetup
= true;
1226 maJobSetup
= aJobSetup
;
1227 ImplUpdatePageData();
1228 ImplUpdateFontList();
1238 Orientation
Printer::GetOrientation() const
1240 return maJobSetup
.ImplGetConstData().GetOrientation();
1243 bool Printer::SetPaperBin( sal_uInt16 nPaperBin
)
1245 if ( mbInPrintPage
)
1248 if ( maJobSetup
.ImplGetConstData().GetPaperBin() != nPaperBin
&&
1249 nPaperBin
< GetPaperBinCount() )
1251 JobSetup aJobSetup
= maJobSetup
;
1252 ImplJobSetup
& rData
= aJobSetup
.ImplGetData();
1253 rData
.SetPaperBin(nPaperBin
);
1255 if ( IsDisplayPrinter() )
1257 mbNewJobSetup
= true;
1258 maJobSetup
= aJobSetup
;
1263 if ( mpInfoPrinter
->SetData( JobSetFlags::PAPERBIN
, &rData
) )
1265 ImplUpdateJobSetupPaper( aJobSetup
);
1266 mbNewJobSetup
= true;
1267 maJobSetup
= aJobSetup
;
1268 ImplUpdatePageData();
1269 ImplUpdateFontList();
1279 sal_uInt16
Printer::GetPaperBin() const
1281 return maJobSetup
.ImplGetConstData().GetPaperBin();
1284 // Map user paper format to a available printer paper formats
1285 void Printer::ImplFindPaperFormatForUserSize( JobSetup
& aJobSetup
, bool bMatchNearest
)
1287 ImplJobSetup
& rData
= aJobSetup
.ImplGetData();
1289 // The angle that a landscape page will be turned counterclockwise wrt to portrait.
1290 int nLandscapeAngle
= mpInfoPrinter
? mpInfoPrinter
->GetLandscapeAngle( &maJobSetup
.ImplGetConstData() ) : 900;
1292 int nPaperCount
= GetPaperInfoCount();
1293 bool bFound
= false;
1295 PaperInfo
aInfo(rData
.GetPaperWidth(), rData
.GetPaperHeight());
1297 // Compare all paper formats and get the appropriate one
1298 for ( int i
= 0; i
< nPaperCount
; i
++ )
1300 const PaperInfo
& rPaperInfo
= GetPaperInfo( i
);
1302 if ( aInfo
.sloppyEqual(rPaperInfo
) )
1304 rData
.SetPaperFormat(
1305 ImplGetPaperFormat( rPaperInfo
.getWidth(),
1306 rPaperInfo
.getHeight() ));
1307 rData
.SetOrientation( Orientation::Portrait
);
1313 // If the printer supports landscape orientation, check paper sizes again
1314 // with landscape orientation. This is necessary as a printer driver provides
1315 // all paper sizes with portrait orientation only!!
1316 if ( rData
.GetPaperFormat() == PAPER_USER
&&
1317 nLandscapeAngle
!= 0 &&
1318 HasSupport( PrinterSupport::SetOrientation
))
1320 const long nRotatedWidth
= rData
.GetPaperHeight();
1321 const long nRotatedHeight
= rData
.GetPaperWidth();
1322 PaperInfo
aRotatedInfo(nRotatedWidth
, nRotatedHeight
);
1324 for ( int i
= 0; i
< nPaperCount
; i
++ )
1326 const PaperInfo
& rPaperInfo
= GetPaperInfo( i
);
1328 if ( aRotatedInfo
.sloppyEqual( rPaperInfo
) )
1330 rData
.SetPaperFormat(
1331 ImplGetPaperFormat( rPaperInfo
.getWidth(),
1332 rPaperInfo
.getHeight() ));
1333 rData
.SetOrientation( Orientation::Landscape
);
1340 if( ! bFound
&& bMatchNearest
)
1342 sal_Int64 nBestMatch
= SAL_MAX_INT64
;
1344 Orientation eBestOrientation
= Orientation::Portrait
;
1345 for( int i
= 0; i
< nPaperCount
; i
++ )
1347 const PaperInfo
& rPaperInfo
= GetPaperInfo( i
);
1349 // check portrait match
1350 sal_Int64 nDX
= rData
.GetPaperWidth() - rPaperInfo
.getWidth();
1351 sal_Int64 nDY
= rData
.GetPaperHeight() - rPaperInfo
.getHeight();
1352 sal_Int64 nMatch
= nDX
*nDX
+ nDY
*nDY
;
1353 if( nMatch
< nBestMatch
)
1355 nBestMatch
= nMatch
;
1357 eBestOrientation
= Orientation::Portrait
;
1360 // check landscape match
1361 nDX
= rData
.GetPaperWidth() - rPaperInfo
.getHeight();
1362 nDY
= rData
.GetPaperHeight() - rPaperInfo
.getWidth();
1363 nMatch
= nDX
*nDX
+ nDY
*nDY
;
1364 if( nMatch
< nBestMatch
)
1366 nBestMatch
= nMatch
;
1368 eBestOrientation
= Orientation::Landscape
;
1371 const PaperInfo
& rBestInfo
= GetPaperInfo( nBestIndex
);
1372 rData
.SetPaperFormat(
1373 ImplGetPaperFormat( rBestInfo
.getWidth(),
1374 rBestInfo
.getHeight() ));
1375 rData
.SetOrientation(eBestOrientation
);
1379 bool Printer::SetPaper( Paper ePaper
)
1381 if ( mbInPrintPage
)
1384 if ( maJobSetup
.ImplGetConstData().GetPaperFormat() != ePaper
)
1386 JobSetup aJobSetup
= maJobSetup
;
1387 ImplJobSetup
& rData
= aJobSetup
.ImplGetData();
1389 rData
.SetPaperFormat( ePaper
);
1390 if ( ePaper
!= PAPER_USER
)
1392 PaperInfo
aInfo(ePaper
);
1393 rData
.SetPaperWidth( aInfo
.getWidth() );
1394 rData
.SetPaperHeight( aInfo
.getHeight() );
1397 if ( IsDisplayPrinter() )
1399 mbNewJobSetup
= true;
1400 maJobSetup
= aJobSetup
;
1405 if ( ePaper
== PAPER_USER
)
1406 ImplFindPaperFormatForUserSize( aJobSetup
, false );
1407 if ( mpInfoPrinter
->SetData( JobSetFlags::PAPERSIZE
| JobSetFlags::ORIENTATION
, &rData
))
1409 ImplUpdateJobSetupPaper( aJobSetup
);
1410 mbNewJobSetup
= true;
1411 maJobSetup
= aJobSetup
;
1412 ImplUpdatePageData();
1413 ImplUpdateFontList();
1423 bool Printer::SetPaperSizeUser( const Size
& rSize
)
1425 return SetPaperSizeUser( rSize
, false );
1428 bool Printer::SetPaperSizeUser( const Size
& rSize
, bool bMatchNearest
)
1430 if ( mbInPrintPage
)
1433 const Size aPixSize
= LogicToPixel( rSize
);
1434 const Size aPageSize
= PixelToLogic( aPixSize
, MapUnit::Map100thMM
);
1435 bool bNeedToChange(maJobSetup
.ImplGetConstData().GetPaperWidth() != aPageSize
.Width() ||
1436 maJobSetup
.ImplGetConstData().GetPaperHeight() != aPageSize
.Height());
1440 // #i122984# only need to change when Paper is different from PAPER_USER and
1441 // the mapped Paper which will created below in the call to ImplFindPaperFormatForUserSize
1442 // and will replace maJobSetup.ImplGetConstData()->GetPaperFormat(). This leads to
1443 // unnecessary JobSetups, e.g. when printing a multi-page fax, but also with
1445 const Paper aPaper
= ImplGetPaperFormat(aPageSize
.Width(), aPageSize
.Height());
1447 bNeedToChange
= maJobSetup
.ImplGetConstData().GetPaperFormat() != PAPER_USER
&&
1448 maJobSetup
.ImplGetConstData().GetPaperFormat() != aPaper
;
1453 JobSetup aJobSetup
= maJobSetup
;
1454 ImplJobSetup
& rData
= aJobSetup
.ImplGetData();
1455 rData
.SetPaperFormat( PAPER_USER
);
1456 rData
.SetPaperWidth( aPageSize
.Width() );
1457 rData
.SetPaperHeight( aPageSize
.Height() );
1459 if ( IsDisplayPrinter() )
1461 mbNewJobSetup
= true;
1462 maJobSetup
= aJobSetup
;
1467 ImplFindPaperFormatForUserSize( aJobSetup
, bMatchNearest
);
1469 // Changing the paper size can also change the orientation!
1470 if ( mpInfoPrinter
->SetData( JobSetFlags::PAPERSIZE
| JobSetFlags::ORIENTATION
, &rData
))
1472 ImplUpdateJobSetupPaper( aJobSetup
);
1473 mbNewJobSetup
= true;
1474 maJobSetup
= aJobSetup
;
1475 ImplUpdatePageData();
1476 ImplUpdateFontList();
1486 int Printer::GetPaperInfoCount() const
1488 if( ! mpInfoPrinter
)
1490 if( ! mpInfoPrinter
->m_bPapersInit
)
1491 mpInfoPrinter
->InitPaperFormats( &maJobSetup
.ImplGetConstData() );
1492 return mpInfoPrinter
->m_aPaperFormats
.size();
1495 OUString
Printer::GetPaperName( Paper ePaper
)
1497 ImplSVData
* pSVData
= ImplGetSVData();
1498 if( ! pSVData
->mpPaperNames
)
1500 pSVData
->mpPaperNames
= new std::unordered_map
< int, OUString
>;
1501 if( ImplGetResMgr() )
1503 ResStringArray
aPaperStrings( VclResId( RID_STR_PAPERNAMES
) );
1504 static const int PaperIndex
[] =
1506 PAPER_A0
, PAPER_A1
, PAPER_A2
, PAPER_A3
, PAPER_A4
, PAPER_A5
,
1507 PAPER_B4_ISO
, PAPER_B5_ISO
, PAPER_LETTER
, PAPER_LEGAL
, PAPER_TABLOID
,
1508 PAPER_USER
, PAPER_B6_ISO
, PAPER_ENV_C4
, PAPER_ENV_C5
, PAPER_ENV_C6
, PAPER_ENV_C65
,
1509 PAPER_ENV_DL
, PAPER_SLIDE_DIA
, PAPER_C
, PAPER_D
, PAPER_E
,
1510 PAPER_EXECUTIVE
, PAPER_FANFOLD_LEGAL_DE
, PAPER_ENV_MONARCH
, PAPER_ENV_PERSONAL
,
1511 PAPER_ENV_9
, PAPER_ENV_10
, PAPER_ENV_11
, PAPER_ENV_12
, PAPER_KAI16
,
1512 PAPER_KAI32
, PAPER_KAI32BIG
, PAPER_B4_JIS
, PAPER_B5_JIS
, PAPER_B6_JIS
,
1515 OSL_ENSURE( sal_uInt32(SAL_N_ELEMENTS(PaperIndex
)) == aPaperStrings
.Count(), "localized paper name count wrong" );
1516 for( int i
= 0; i
< int(SAL_N_ELEMENTS(PaperIndex
)); i
++ )
1517 (*pSVData
->mpPaperNames
)[PaperIndex
[i
]] = aPaperStrings
.GetString(i
);
1521 std::unordered_map
<int,OUString
>::const_iterator it
= pSVData
->mpPaperNames
->find( (int)ePaper
);
1522 return (it
!= pSVData
->mpPaperNames
->end()) ? it
->second
: OUString();
1525 OUString
Printer::GetPaperName() const
1527 Size aPageSize
= PixelToLogic( GetPaperSizePixel(), MapUnit::Map100thMM
);
1528 Paper ePaper
= ImplGetPaperFormat( aPageSize
.Width(), aPageSize
.Height() );
1529 if( ePaper
== PAPER_USER
)
1530 ePaper
= ImplGetPaperFormat( aPageSize
.Height(), aPageSize
.Width() );
1531 return (ePaper
!= PAPER_USER
) ? GetPaperName( ePaper
) : OUString();
1534 const PaperInfo
& Printer::GetPaperInfo( int nPaper
) const
1536 if( ! mpInfoPrinter
)
1537 return ImplGetEmptyPaper();
1538 if( ! mpInfoPrinter
->m_bPapersInit
)
1539 mpInfoPrinter
->InitPaperFormats( &maJobSetup
.ImplGetConstData() );
1540 if( mpInfoPrinter
->m_aPaperFormats
.empty() || nPaper
< 0 || nPaper
>= int(mpInfoPrinter
->m_aPaperFormats
.size()) )
1541 return ImplGetEmptyPaper();
1542 return mpInfoPrinter
->m_aPaperFormats
[nPaper
];
1545 bool Printer::SetDuplexMode( DuplexMode eDuplex
)
1547 if ( mbInPrintPage
)
1550 if ( maJobSetup
.ImplGetConstData().GetDuplexMode() != eDuplex
)
1552 JobSetup aJobSetup
= maJobSetup
;
1553 ImplJobSetup
& rData
= aJobSetup
.ImplGetData();
1555 rData
.SetDuplexMode( eDuplex
);
1557 if ( IsDisplayPrinter() )
1559 mbNewJobSetup
= true;
1560 maJobSetup
= aJobSetup
;
1565 if ( mpInfoPrinter
->SetData( JobSetFlags::DUPLEXMODE
, &rData
) )
1567 ImplUpdateJobSetupPaper( aJobSetup
);
1568 mbNewJobSetup
= true;
1569 maJobSetup
= aJobSetup
;
1570 ImplUpdatePageData();
1571 ImplUpdateFontList();
1581 Paper
Printer::GetPaper() const
1583 return maJobSetup
.ImplGetConstData().GetPaperFormat();
1586 sal_uInt16
Printer::GetPaperBinCount() const
1588 if ( IsDisplayPrinter() )
1591 return mpInfoPrinter
->GetPaperBinCount( &maJobSetup
.ImplGetConstData() );
1594 OUString
Printer::GetPaperBinName( sal_uInt16 nPaperBin
) const
1596 if ( IsDisplayPrinter() )
1599 if ( nPaperBin
< GetPaperBinCount() )
1600 return mpInfoPrinter
->GetPaperBinName( &maJobSetup
.ImplGetConstData(), nPaperBin
);
1605 bool Printer::SetCopyCount( sal_uInt16 nCopy
, bool bCollate
)
1607 mnCopyCount
= nCopy
;
1608 mbCollateCopy
= bCollate
;
1612 sal_uLong
Printer::ImplSalPrinterErrorCodeToVCL( sal_uLong nError
)
1614 sal_uLong nVCLError
;
1618 nVCLError
= PRINTER_OK
;
1620 case SAL_PRINTER_ERROR_ABORT
:
1621 nVCLError
= PRINTER_ABORT
;
1624 nVCLError
= PRINTER_GENERALERROR
;
1631 bool Printer::EndJob()
1634 if ( !IsJobActive() )
1637 SAL_WARN_IF( mbInPrintPage
, "vcl.gdi", "Printer::EndJob() - StartPage() without EndPage() called" );
1639 mbJobActive
= false;
1651 mbDevOutput
= false;
1652 bRet
= mpPrinter
->EndJob();
1653 // FIXME: Do not destroy the printer asynchronously as Win95
1654 // can't handle destroying a printer object and printing
1656 ImplGetSVData()->mpDefInst
->DestroyPrinter( mpPrinter
);
1657 mpPrinter
= nullptr;
1663 void Printer::ImplStartPage()
1665 if ( !IsJobActive() )
1670 SalGraphics
* pGraphics
= mpPrinter
->StartPage( &maJobSetup
.ImplGetData(),
1675 mpJobGraphics
= pGraphics
;
1679 // PrintJob not aborted ???
1680 if ( IsJobActive() )
1682 mbInPrintPage
= true;
1689 void Printer::ImplEndPage()
1691 if ( !IsJobActive() )
1694 mbInPrintPage
= false;
1698 mpPrinter
->EndPage();
1700 mbDevOutput
= false;
1702 mpJobGraphics
= nullptr;
1703 mbNewJobSetup
= false;
1707 void Printer::updatePrinters()
1709 ImplSVData
* pSVData
= ImplGetSVData();
1710 ImplPrnQueueList
* pPrnList
= pSVData
->maGDIData
.mpPrinterQueueList
;
1714 ImplPrnQueueList
* pNewList
= new ImplPrnQueueList
;
1715 pSVData
->mpDefInst
->GetPrinterQueueInfo( pNewList
);
1717 bool bChanged
= pPrnList
->m_aQueueInfos
.size() != pNewList
->m_aQueueInfos
.size();
1718 for( decltype(pPrnList
->m_aQueueInfos
)::size_type i
= 0; ! bChanged
&& i
< pPrnList
->m_aQueueInfos
.size(); i
++ )
1720 ImplPrnQueueData
& rInfo
= pPrnList
->m_aQueueInfos
[i
];
1721 ImplPrnQueueData
& rNewInfo
= pNewList
->m_aQueueInfos
[i
];
1722 if( ! rInfo
.mpSalQueueInfo
|| ! rNewInfo
.mpSalQueueInfo
|| // sanity check
1723 rInfo
.mpSalQueueInfo
->maPrinterName
!= rNewInfo
.mpSalQueueInfo
->maPrinterName
)
1730 ImplDeletePrnQueueList();
1731 pSVData
->maGDIData
.mpPrinterQueueList
= pNewList
;
1733 Application
* pApp
= GetpApp();
1736 DataChangedEvent
aDCEvt( DataChangedEventType::PRINTER
);
1737 Application::NotifyAllWindows( aDCEvt
);
1745 bool Printer::UsePolyPolygonForComplexGradient()
1750 void Printer::ClipAndDrawGradientMetafile ( const Gradient
&rGradient
, const tools::PolyPolygon
&rPolyPoly
)
1752 const tools::Rectangle
aBoundRect( rPolyPoly
.GetBoundRect() );
1754 Push( PushFlags::CLIPREGION
);
1755 IntersectClipRegion(vcl::Region(rPolyPoly
));
1756 DrawGradient( aBoundRect
, rGradient
);
1760 void Printer::InitFont() const
1762 DBG_TESTSOLARMUTEX();
1764 if (!mpFontInstance
)
1769 // select font in the device layers
1770 mpGraphics
->SetFont( &(mpFontInstance
->maFontSelData
), 0 );
1775 void Printer::SetFontOrientation( LogicalFontInstance
* const pFontEntry
) const
1777 pFontEntry
->mnOrientation
= pFontEntry
->mxFontMetric
->GetOrientation();
1780 Bitmap
Printer::GetBitmap( const Point
& rSrcPt
, const Size
& rSize
) const
1782 SAL_WARN("vcl.gdi", "GetBitmap(): This should never be called on by a Printer instance");
1784 return OutputDevice::GetBitmap( rSrcPt
, rSize
);
1787 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */