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/config.h>
22 #include <sal/types.h>
23 #include <sal/log.hxx>
24 #include <comphelper/processfactory.hxx>
25 #include <o3tl/safeint.hxx>
26 #include <tools/debug.hxx>
27 #include <tools/helpers.hxx>
29 #include <vcl/QueueInfo.hxx>
30 #include <vcl/event.hxx>
31 #include <vcl/virdev.hxx>
32 #include <vcl/print.hxx>
33 #include <vcl/printer/Options.hxx>
37 #include <ImplOutDevData.hxx>
38 #include <font/PhysicalFontCollection.hxx>
39 #include <font/PhysicalFontFaceCollection.hxx>
40 #include <font/fontsubstitution.hxx>
41 #include <impfontcache.hxx>
44 #include <salinst.hxx>
46 #include <salptype.hxx>
50 #include <com/sun/star/beans/XPropertySet.hpp>
51 #include <com/sun/star/configuration/theDefaultProvider.hpp>
52 #include <com/sun/star/container/XNameAccess.hpp>
53 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
54 #include <com/sun/star/uno/Sequence.h>
56 int nImplSysDialog
= 0;
60 Paper
ImplGetPaperFormat( tools::Long nWidth100thMM
, tools::Long nHeight100thMM
)
62 PaperInfo
aInfo(nWidth100thMM
, nHeight100thMM
);
64 return aInfo
.getPaper();
67 const PaperInfo
& ImplGetEmptyPaper()
69 static PaperInfo
aInfo(PAPER_USER
);
74 void ImplUpdateJobSetupPaper( JobSetup
& rJobSetup
)
76 const ImplJobSetup
& rConstData
= rJobSetup
.ImplGetConstData();
78 if ( !rConstData
.GetPaperWidth() || !rConstData
.GetPaperHeight() )
80 if ( rConstData
.GetPaperFormat() != PAPER_USER
)
82 PaperInfo
aInfo(rConstData
.GetPaperFormat());
84 ImplJobSetup
& rData
= rJobSetup
.ImplGetData();
85 rData
.SetPaperWidth( aInfo
.getWidth() );
86 rData
.SetPaperHeight( aInfo
.getHeight() );
89 else if ( rConstData
.GetPaperFormat() == PAPER_USER
)
91 Paper ePaper
= ImplGetPaperFormat( rConstData
.GetPaperWidth(), rConstData
.GetPaperHeight() );
92 if ( ePaper
!= PAPER_USER
)
93 rJobSetup
.ImplGetData().SetPaperFormat(ePaper
);
97 void Printer::ImplPrintTransparent( const Bitmap
& rBmp
,
98 const Point
& rDestPt
, const Size
& rDestSize
,
99 const Point
& rSrcPtPixel
, const Size
& rSrcSizePixel
)
101 Point
aDestPt( LogicToPixel( rDestPt
) );
102 Size
aDestSz( LogicToPixel( rDestSize
) );
103 tools::Rectangle
aSrcRect( rSrcPtPixel
, rSrcSizePixel
);
105 aSrcRect
.Normalize();
107 if( rBmp
.IsEmpty() || !aSrcRect
.GetWidth() || !aSrcRect
.GetHeight() || !aDestSz
.Width() || !aDestSz
.Height() )
110 Bitmap
aPaint( rBmp
);
111 BmpMirrorFlags nMirrFlags
= BmpMirrorFlags::NONE
;
113 // mirrored horizontally
114 if( aDestSz
.Width() < 0 )
116 aDestSz
.setWidth( -aDestSz
.Width() );
117 aDestPt
.AdjustX( -( aDestSz
.Width() - 1 ) );
118 nMirrFlags
|= BmpMirrorFlags::Horizontal
;
121 // mirrored vertically
122 if( aDestSz
.Height() < 0 )
124 aDestSz
.setHeight( -aDestSz
.Height() );
125 aDestPt
.AdjustY( -( aDestSz
.Height() - 1 ) );
126 nMirrFlags
|= BmpMirrorFlags::Vertical
;
130 if( aSrcRect
!= tools::Rectangle( Point(), aPaint
.GetSizePixel() ) )
132 aPaint
.Crop( aSrcRect
);
135 // destination mirrored
136 if( nMirrFlags
!= BmpMirrorFlags::NONE
)
138 aPaint
.Mirror( nMirrFlags
);
141 // we always want to have a mask
142 AlphaMask
aAlphaMask(aSrcRect
.GetSize());
143 aAlphaMask
.Erase( 0 );
146 const tools::Long nSrcWidth
= aSrcRect
.GetWidth(), nSrcHeight
= aSrcRect
.GetHeight();
147 tools::Long nX
, nY
; // , nWorkX, nWorkY, nWorkWidth, nWorkHeight;
148 std::unique_ptr
<tools::Long
[]> pMapX(new tools::Long
[ nSrcWidth
+ 1 ]);
149 std::unique_ptr
<tools::Long
[]> pMapY(new tools::Long
[ nSrcHeight
+ 1 ]);
150 const bool bOldMap
= mbMap
;
154 // create forward mapping tables
155 for( nX
= 0; nX
<= nSrcWidth
; nX
++ )
156 pMapX
[ nX
] = aDestPt
.X() + basegfx::fround
<tools::Long
>( static_cast<double>(aDestSz
.Width()) * nX
/ nSrcWidth
);
158 for( nY
= 0; nY
<= nSrcHeight
; nY
++ )
159 pMapY
[ nY
] = aDestPt
.Y() + basegfx::fround
<tools::Long
>( static_cast<double>(aDestSz
.Height()) * nY
/ nSrcHeight
);
161 tools::Rectangle rectangle
{ Point(0,0), aSrcRect
.GetSize() };
162 const Point
aMapPt(pMapX
[rectangle
.Left()], pMapY
[rectangle
.Top()]);
163 const Size
aMapSz( pMapX
[rectangle
.Right() + 1] - aMapPt
.X(), // pMapX[L + W] -> L + ((R - L) + 1) -> R + 1
164 pMapY
[rectangle
.Bottom() + 1] - aMapPt
.Y()); // same for Y
165 Bitmap
aBandBmp(aPaint
);
167 DrawBitmap(aMapPt
, aMapSz
, Point(), aBandBmp
.GetSizePixel(), aBandBmp
);
172 bool Printer::DrawTransformBitmapExDirect(
173 const basegfx::B2DHomMatrix
& /*aFullTransform*/,
174 const BitmapEx
& /*rBitmapEx*/,
177 // printers can't draw bitmaps directly
181 bool Printer::TransformAndReduceBitmapExToTargetRange(
182 const basegfx::B2DHomMatrix
& /*aFullTransform*/,
183 basegfx::B2DRange
& /*aVisibleRange*/,
184 double& /*fMaximumArea*/)
186 // deliberately do nothing - you can't reduce the
187 // target range for a printer at all
191 void Printer::DrawDeviceBitmapEx( const Point
& rDestPt
, const Size
& rDestSize
,
192 const Point
& rSrcPtPixel
, const Size
& rSrcSizePixel
,
195 if( rBmpEx
.IsAlpha() )
197 // #107169# For true alpha bitmaps, no longer masking the
198 // bitmap, but perform a full alpha blend against a white
200 Bitmap
aBmp( rBmpEx
.GetBitmap() );
201 aBmp
.Blend( rBmpEx
.GetAlphaMask(), COL_WHITE
);
202 DrawBitmap( rDestPt
, rDestSize
, rSrcPtPixel
, rSrcSizePixel
, aBmp
);
206 const Bitmap
& aBmp( rBmpEx
.GetBitmap() );
207 ImplPrintTransparent( aBmp
, rDestPt
, rDestSize
, rSrcPtPixel
, rSrcSizePixel
);
211 void Printer::EmulateDrawTransparent ( const tools::PolyPolygon
& rPolyPoly
,
212 sal_uInt16 nTransparencePercent
)
214 // #110958# Disable alpha VDev, we perform the necessary
215 VirtualDevice
* pOldAlphaVDev
= mpAlphaVDev
;
217 // operation explicitly further below.
219 mpAlphaVDev
= nullptr;
221 GDIMetaFile
* pOldMetaFile
= mpMetaFile
;
222 mpMetaFile
= nullptr;
224 tools::Rectangle
aPolyRect( LogicToPixel( rPolyPoly
).GetBoundRect() );
225 const Size
aDPISize( LogicToPixel(Size(1, 1), MapMode(MapUnit::MapInch
)) );
226 const tools::Long nBaseExtent
= std::max
<tools::Long
>( basegfx::fround
<tools::Long
>( aDPISize
.Width() / 300. ), 1 );
228 const sal_uInt16 nTrans
= ( nTransparencePercent
< 13 ) ? 0 :
229 ( nTransparencePercent
< 38 ) ? 25 :
230 ( nTransparencePercent
< 63 ) ? 50 :
231 ( nTransparencePercent
< 88 ) ? 75 : 100;
235 case 25: nMove
= nBaseExtent
* 3; break;
236 case 50: nMove
= nBaseExtent
* 4; break;
237 case 75: nMove
= nBaseExtent
* 6; break;
239 // #i112959# very transparent (88 < nTransparencePercent <= 99)
240 case 100: nMove
= nBaseExtent
* 8; break;
242 // #i112959# not transparent (nTransparencePercent < 13)
243 default: nMove
= 0; break;
246 Push( vcl::PushFlags::CLIPREGION
| vcl::PushFlags::LINECOLOR
);
247 IntersectClipRegion(vcl::Region(rPolyPoly
));
248 SetLineColor( GetFillColor() );
249 const bool bOldMap
= mbMap
;
250 EnableMapMode( false );
254 tools::Rectangle
aRect( aPolyRect
.TopLeft(), Size( aPolyRect
.GetWidth(), nBaseExtent
) );
255 while( aRect
.Top() <= aPolyRect
.Bottom() )
258 aRect
.Move( 0, nMove
);
261 aRect
= tools::Rectangle( aPolyRect
.TopLeft(), Size( nBaseExtent
, aPolyRect
.GetHeight() ) );
262 while( aRect
.Left() <= aPolyRect
.Right() )
265 aRect
.Move( nMove
, 0 );
270 // #i112959# if not transparent, draw full rectangle in clip region
271 DrawRect( aPolyRect
);
274 EnableMapMode( bOldMap
);
277 mpMetaFile
= pOldMetaFile
;
279 // #110958# Restore disabled alpha VDev
280 mpAlphaVDev
= pOldAlphaVDev
;
283 void Printer::DrawOutDev( const Point
& /*rDestPt*/, const Size
& /*rDestSize*/,
284 const Point
& /*rSrcPt*/, const Size
& /*rSrcSize*/ )
286 SAL_WARN( "vcl.gdi", "Don't use OutputDevice::DrawOutDev(...) with printer devices!" );
289 void Printer::DrawOutDev( const Point
& /*rDestPt*/, const Size
& /*rDestSize*/,
290 const Point
& /*rSrcPt*/, const Size
& /*rSrcSize*/,
291 const OutputDevice
& /*rOutDev*/ )
293 SAL_WARN( "vcl.gdi", "Don't use OutputDevice::DrawOutDev(...) with printer devices!" );
296 void Printer::CopyArea( const Point
& /*rDestPt*/,
297 const Point
& /*rSrcPt*/, const Size
& /*rSrcSize*/,
298 bool /*bWindowInvalidate*/ )
300 SAL_WARN( "vcl.gdi", "Don't use OutputDevice::CopyArea(...) with printer devices!" );
303 tools::Rectangle
Printer::GetBackgroundComponentBounds() const
305 Point aPageOffset
= Point( 0, 0 ) - this->GetPageOffsetPixel();
306 Size aSize
= this->GetPaperSizePixel();
307 return tools::Rectangle( aPageOffset
, aSize
);
310 void Printer::SetPrinterOptions( const vcl::printer::Options
& i_rOptions
)
312 *mpPrinterOptions
= i_rOptions
;
315 bool Printer::HasMirroredGraphics() const
317 // due to a "hotfix" for AOO bug i55719, this needs to return false
321 SalPrinterQueueInfo::SalPrinterQueueInfo()
323 mnStatus
= PrintQueueFlags::NONE
;
324 mnJobs
= QUEUE_JOBS_DONTKNOW
;
327 SalPrinterQueueInfo::~SalPrinterQueueInfo()
331 ImplPrnQueueList::~ImplPrnQueueList()
335 void ImplPrnQueueList::Add( std::unique_ptr
<SalPrinterQueueInfo
> pData
)
337 std::unordered_map
< OUString
, sal_Int32
>::iterator it
=
338 m_aNameToIndex
.find( pData
->maPrinterName
);
339 if( it
== m_aNameToIndex
.end() )
341 m_aNameToIndex
[ pData
->maPrinterName
] = m_aQueueInfos
.size();
342 m_aPrinterList
.push_back( pData
->maPrinterName
);
343 m_aQueueInfos
.push_back( ImplPrnQueueData() );
344 m_aQueueInfos
.back().mpQueueInfo
= nullptr;
345 m_aQueueInfos
.back().mpSalQueueInfo
= std::move(pData
);
347 else // this should not happen, but ...
349 ImplPrnQueueData
& rData
= m_aQueueInfos
[ it
->second
];
350 rData
.mpQueueInfo
.reset();
351 rData
.mpSalQueueInfo
= std::move(pData
);
355 ImplPrnQueueData
* ImplPrnQueueList::Get( const OUString
& rPrinter
)
357 ImplPrnQueueData
* pData
= nullptr;
358 std::unordered_map
<OUString
,sal_Int32
>::iterator it
=
359 m_aNameToIndex
.find( rPrinter
);
360 if( it
!= m_aNameToIndex
.end() )
361 pData
= &m_aQueueInfos
[it
->second
];
365 static void ImplInitPrnQueueList()
367 ImplSVData
* pSVData
= ImplGetSVData();
369 pSVData
->maGDIData
.mpPrinterQueueList
.reset(new ImplPrnQueueList
);
371 static const char* pEnv
= getenv( "SAL_DISABLE_PRINTERLIST" );
372 if( !pEnv
|| !*pEnv
)
373 pSVData
->mpDefInst
->GetPrinterQueueInfo( pSVData
->maGDIData
.mpPrinterQueueList
.get() );
376 void ImplDeletePrnQueueList()
378 ImplSVData
* pSVData
= ImplGetSVData();
379 pSVData
->maGDIData
.mpPrinterQueueList
.reset();
382 const std::vector
<OUString
>& Printer::GetPrinterQueues()
384 ImplSVData
* pSVData
= ImplGetSVData();
385 if ( !pSVData
->maGDIData
.mpPrinterQueueList
)
386 ImplInitPrnQueueList();
387 assert(pSVData
->maGDIData
.mpPrinterQueueList
&& "mpPrinterQueueList exists by now");
388 return pSVData
->maGDIData
.mpPrinterQueueList
->m_aPrinterList
;
391 const QueueInfo
* Printer::GetQueueInfo( const OUString
& rPrinterName
, bool bStatusUpdate
)
393 ImplSVData
* pSVData
= ImplGetSVData();
395 if ( !pSVData
->maGDIData
.mpPrinterQueueList
)
396 ImplInitPrnQueueList();
398 if ( !pSVData
->maGDIData
.mpPrinterQueueList
)
401 ImplPrnQueueData
* pInfo
= pSVData
->maGDIData
.mpPrinterQueueList
->Get( rPrinterName
);
404 if( !pInfo
->mpQueueInfo
|| bStatusUpdate
)
405 pSVData
->mpDefInst
->GetPrinterQueueState( pInfo
->mpSalQueueInfo
.get() );
407 if ( !pInfo
->mpQueueInfo
)
408 pInfo
->mpQueueInfo
.reset(new QueueInfo
);
410 pInfo
->mpQueueInfo
->maPrinterName
= pInfo
->mpSalQueueInfo
->maPrinterName
;
411 pInfo
->mpQueueInfo
->maDriver
= pInfo
->mpSalQueueInfo
->maDriver
;
412 pInfo
->mpQueueInfo
->maLocation
= pInfo
->mpSalQueueInfo
->maLocation
;
413 pInfo
->mpQueueInfo
->maComment
= pInfo
->mpSalQueueInfo
->maComment
;
414 pInfo
->mpQueueInfo
->mnStatus
= pInfo
->mpSalQueueInfo
->mnStatus
;
415 pInfo
->mpQueueInfo
->mnJobs
= pInfo
->mpSalQueueInfo
->mnJobs
;
416 return pInfo
->mpQueueInfo
.get();
421 OUString
Printer::GetDefaultPrinterName()
423 static const char* pEnv
= getenv( "SAL_DISABLE_DEFAULTPRINTER" );
424 if( !pEnv
|| !*pEnv
)
426 ImplSVData
* pSVData
= ImplGetSVData();
428 return pSVData
->mpDefInst
->GetDefaultPrinter();
433 void Printer::ImplInitData()
436 mbDefPrinter
= false;
437 mnError
= ERRCODE_NONE
;
440 mbCollateCopy
= false;
444 mbInPrintPage
= false;
445 mbNewJobSetup
= false;
446 mbSinglePrintJobs
= false;
447 mbUsePrintSetting
= false;
448 mbResetPrintArea
= false;
449 mpInfoPrinter
= nullptr;
451 mpDisplayDev
= nullptr;
452 mpPrinterOptions
.reset(new vcl::printer::Options
);
454 // Add printer to the list
455 ImplSVData
* pSVData
= ImplGetSVData();
456 mpNext
= pSVData
->maGDIData
.mpFirstPrinter
;
459 mpNext
->mpPrev
= this;
460 pSVData
->maGDIData
.mpFirstPrinter
= this;
463 bool Printer::AcquireGraphics() const
465 DBG_TESTSOLARMUTEX();
470 mbInitLineColor
= true;
471 mbInitFillColor
= true;
473 mbInitTextColor
= true;
474 mbInitClipRegion
= true;
476 ImplSVData
* pSVData
= ImplGetSVData();
479 mpGraphics
= mpJobGraphics
;
480 else if ( mpDisplayDev
)
482 const VirtualDevice
* pVirDev
= mpDisplayDev
;
483 mpGraphics
= pVirDev
->mpVirDev
->AcquireGraphics();
484 // if needed retry after releasing least recently used virtual device graphics
485 while ( !mpGraphics
)
487 if ( !pSVData
->maGDIData
.mpLastVirGraphics
)
489 pSVData
->maGDIData
.mpLastVirGraphics
->ReleaseGraphics();
490 mpGraphics
= pVirDev
->mpVirDev
->AcquireGraphics();
492 // update global LRU list of virtual device graphics
495 mpNextGraphics
= pSVData
->maGDIData
.mpFirstVirGraphics
;
496 pSVData
->maGDIData
.mpFirstVirGraphics
= const_cast<Printer
*>(this);
497 if ( mpNextGraphics
)
498 mpNextGraphics
->mpPrevGraphics
= const_cast<Printer
*>(this);
499 if ( !pSVData
->maGDIData
.mpLastVirGraphics
)
500 pSVData
->maGDIData
.mpLastVirGraphics
= const_cast<Printer
*>(this);
505 mpGraphics
= mpInfoPrinter
->AcquireGraphics();
506 // if needed retry after releasing least recently used printer graphics
507 while ( !mpGraphics
)
509 if ( !pSVData
->maGDIData
.mpLastPrnGraphics
)
511 pSVData
->maGDIData
.mpLastPrnGraphics
->ReleaseGraphics();
512 mpGraphics
= mpInfoPrinter
->AcquireGraphics();
514 // update global LRU list of printer graphics
517 mpNextGraphics
= pSVData
->maGDIData
.mpFirstPrnGraphics
;
518 pSVData
->maGDIData
.mpFirstPrnGraphics
= const_cast<Printer
*>(this);
519 if ( mpNextGraphics
)
520 mpNextGraphics
->mpPrevGraphics
= const_cast<Printer
*>(this);
521 if ( !pSVData
->maGDIData
.mpLastPrnGraphics
)
522 pSVData
->maGDIData
.mpLastPrnGraphics
= const_cast<Printer
*>(this);
528 mpGraphics
->SetXORMode( (RasterOp::Invert
== meRasterOp
) || (RasterOp::Xor
== meRasterOp
), RasterOp::Invert
== meRasterOp
);
529 mpGraphics
->setAntiAlias(bool(mnAntialiasing
& AntialiasingFlags::Enable
));
532 return mpGraphics
!= nullptr;
535 void Printer::ImplReleaseFonts()
537 mpGraphics
->ReleaseFonts();
541 mpFontInstance
.clear();
542 mpFontFaceCollection
.reset();
545 void Printer::ImplReleaseGraphics(bool bRelease
)
547 DBG_TESTSOLARMUTEX();
552 // release the fonts of the physically released graphics device
556 ImplSVData
* pSVData
= ImplGetSVData();
558 Printer
* pPrinter
= this;
560 if ( !pPrinter
->mpJobGraphics
)
562 if ( pPrinter
->mpDisplayDev
)
564 VirtualDevice
* pVirDev
= pPrinter
->mpDisplayDev
;
566 pVirDev
->mpVirDev
->ReleaseGraphics( mpGraphics
);
567 // remove from global LRU list of virtual device graphics
568 if ( mpPrevGraphics
)
569 mpPrevGraphics
->mpNextGraphics
= mpNextGraphics
;
571 pSVData
->maGDIData
.mpFirstVirGraphics
= mpNextGraphics
;
572 if ( mpNextGraphics
)
573 mpNextGraphics
->mpPrevGraphics
= mpPrevGraphics
;
575 pSVData
->maGDIData
.mpLastVirGraphics
= mpPrevGraphics
;
580 pPrinter
->mpInfoPrinter
->ReleaseGraphics( mpGraphics
);
581 // remove from global LRU list of printer graphics
582 if ( mpPrevGraphics
)
583 mpPrevGraphics
->mpNextGraphics
= mpNextGraphics
;
585 pSVData
->maGDIData
.mpFirstPrnGraphics
= static_cast<Printer
*>(mpNextGraphics
.get());
586 if ( mpNextGraphics
)
587 mpNextGraphics
->mpPrevGraphics
= mpPrevGraphics
;
589 pSVData
->maGDIData
.mpLastPrnGraphics
= static_cast<Printer
*>(mpPrevGraphics
.get());
593 mpGraphics
= nullptr;
594 mpPrevGraphics
= nullptr;
595 mpNextGraphics
= nullptr;
598 void Printer::ReleaseGraphics(bool bRelease
)
600 ImplReleaseGraphics(bRelease
);
603 void Printer::ImplInit( SalPrinterQueueInfo
* pInfo
)
605 ImplSVData
* pSVData
= ImplGetSVData();
606 // #i74084# update info for this specific SalPrinterQueueInfo
607 pSVData
->mpDefInst
->GetPrinterQueueState( pInfo
);
609 // Test whether the driver actually matches the JobSetup
610 ImplJobSetup
& rData
= maJobSetup
.ImplGetData();
611 if ( rData
.GetDriverData() )
613 if ( rData
.GetPrinterName() != pInfo
->maPrinterName
||
614 rData
.GetDriver() != pInfo
->maDriver
)
616 rData
.SetDriverData(nullptr, 0);
620 // Remember printer name
621 maPrinterName
= pInfo
->maPrinterName
;
622 maDriver
= pInfo
->maDriver
;
624 // Add printer name to JobSetup
625 rData
.SetPrinterName( maPrinterName
);
626 rData
.SetDriver( maDriver
);
628 mpInfoPrinter
= pSVData
->mpDefInst
->CreateInfoPrinter( pInfo
, &rData
);
630 mpJobGraphics
= nullptr;
631 ImplUpdateJobSetupPaper( maJobSetup
);
633 if ( !mpInfoPrinter
)
639 // we need a graphics
640 if ( !AcquireGraphics() )
647 ImplUpdatePageData();
648 mxFontCollection
= std::make_shared
<vcl::font::PhysicalFontCollection
>();
649 mxFontCache
= std::make_shared
<ImplFontCache
>();
650 mpGraphics
->GetDevFontList(mxFontCollection
.get());
653 void Printer::ImplInitDisplay()
655 ImplSVData
* pSVData
= ImplGetSVData();
657 mpInfoPrinter
= nullptr;
659 mpJobGraphics
= nullptr;
661 mpDisplayDev
= VclPtr
<VirtualDevice
>::Create();
662 mxFontCollection
= pSVData
->maGDIData
.mxScreenFontList
;
663 mxFontCache
= pSVData
->maGDIData
.mxScreenFontCache
;
664 mnDPIX
= mpDisplayDev
->mnDPIX
;
665 mnDPIY
= mpDisplayDev
->mnDPIY
;
668 void Printer::DrawDeviceMask( const Bitmap
& rMask
, const Color
& rMaskColor
,
669 const Point
& rDestPt
, const Size
& rDestSize
,
670 const Point
& rSrcPtPixel
, const Size
& rSrcSizePixel
)
672 Point
aDestPt( LogicToPixel( rDestPt
) );
673 Size
aDestSz( LogicToPixel( rDestSize
) );
674 tools::Rectangle
aSrcRect( rSrcPtPixel
, rSrcSizePixel
);
676 aSrcRect
.Normalize();
678 if( !(!rMask
.IsEmpty() && aSrcRect
.GetWidth() && aSrcRect
.GetHeight() && aDestSz
.Width() && aDestSz
.Height()) )
681 Bitmap
aMask( rMask
);
682 BmpMirrorFlags nMirrFlags
= BmpMirrorFlags::NONE
;
684 if (aMask
.getPixelFormat() >= vcl::PixelFormat::N8_BPP
)
685 aMask
.Convert( BmpConversion::N1BitThreshold
);
687 // mirrored horizontally
688 if( aDestSz
.Width() < 0 )
690 aDestSz
.setWidth( -aDestSz
.Width() );
691 aDestPt
.AdjustX( -( aDestSz
.Width() - 1 ) );
692 nMirrFlags
|= BmpMirrorFlags::Horizontal
;
695 // mirrored vertically
696 if( aDestSz
.Height() < 0 )
698 aDestSz
.setHeight( -aDestSz
.Height() );
699 aDestPt
.AdjustY( -( aDestSz
.Height() - 1 ) );
700 nMirrFlags
|= BmpMirrorFlags::Vertical
;
704 if( aSrcRect
!= tools::Rectangle( Point(), aMask
.GetSizePixel() ) )
705 aMask
.Crop( aSrcRect
);
707 // destination mirrored
708 if( nMirrFlags
!= BmpMirrorFlags::NONE
)
709 aMask
.Mirror( nMirrFlags
);
712 const tools::Long nSrcWidth
= aSrcRect
.GetWidth(), nSrcHeight
= aSrcRect
.GetHeight();
713 tools::Long nX
, nY
; //, nWorkX, nWorkY, nWorkWidth, nWorkHeight;
714 std::unique_ptr
<tools::Long
[]> pMapX( new tools::Long
[ nSrcWidth
+ 1 ] );
715 std::unique_ptr
<tools::Long
[]> pMapY( new tools::Long
[ nSrcHeight
+ 1 ] );
716 GDIMetaFile
* pOldMetaFile
= mpMetaFile
;
717 const bool bOldMap
= mbMap
;
719 mpMetaFile
= nullptr;
721 Push( vcl::PushFlags::FILLCOLOR
| vcl::PushFlags::LINECOLOR
);
722 SetLineColor( rMaskColor
);
723 SetFillColor( rMaskColor
);
727 // create forward mapping tables
728 for( nX
= 0; nX
<= nSrcWidth
; nX
++ )
729 pMapX
[ nX
] = aDestPt
.X() + basegfx::fround
<tools::Long
>( static_cast<double>(aDestSz
.Width()) * nX
/ nSrcWidth
);
731 for( nY
= 0; nY
<= nSrcHeight
; nY
++ )
732 pMapY
[ nY
] = aDestPt
.Y() + basegfx::fround
<tools::Long
>( static_cast<double>(aDestSz
.Height()) * nY
/ nSrcHeight
);
734 // walk through all rectangles of mask
735 const vcl::Region
aWorkRgn(aMask
.CreateRegion(COL_BLACK
, tools::Rectangle(Point(), aMask
.GetSizePixel())));
736 RectangleVector aRectangles
;
737 aWorkRgn
.GetRegionRectangles(aRectangles
);
739 for (auto const& rectangle
: aRectangles
)
741 const Point
aMapPt(pMapX
[rectangle
.Left()], pMapY
[rectangle
.Top()]);
743 pMapX
[rectangle
.Right() + 1] - aMapPt
.X(), // pMapX[L + W] -> L + ((R - L) + 1) -> R + 1
744 pMapY
[rectangle
.Bottom() + 1] - aMapPt
.Y()); // same for Y
746 DrawRect(tools::Rectangle(aMapPt
, aMapSz
));
751 mpMetaFile
= pOldMetaFile
;
754 SalPrinterQueueInfo
* Printer::ImplGetQueueInfo( const OUString
& rPrinterName
,
755 const OUString
* pDriver
)
757 ImplSVData
* pSVData
= ImplGetSVData();
758 if ( !pSVData
->maGDIData
.mpPrinterQueueList
)
759 ImplInitPrnQueueList();
761 ImplPrnQueueList
* pPrnList
= pSVData
->maGDIData
.mpPrinterQueueList
.get();
762 if ( pPrnList
&& !pPrnList
->m_aQueueInfos
.empty() )
764 // first search for the printer name directly
765 ImplPrnQueueData
* pInfo
= pPrnList
->Get( rPrinterName
);
767 return pInfo
->mpSalQueueInfo
.get();
769 // then search case insensitive
770 for(const ImplPrnQueueData
& rQueueInfo
: pPrnList
->m_aQueueInfos
)
772 if( rQueueInfo
.mpSalQueueInfo
->maPrinterName
.equalsIgnoreAsciiCase( rPrinterName
) )
773 return rQueueInfo
.mpSalQueueInfo
.get();
776 // then search for driver name
779 for(const ImplPrnQueueData
& rQueueInfo
: pPrnList
->m_aQueueInfos
)
781 if( rQueueInfo
.mpSalQueueInfo
->maDriver
== *pDriver
)
782 return rQueueInfo
.mpSalQueueInfo
.get();
786 // then the default printer
787 pInfo
= pPrnList
->Get( GetDefaultPrinterName() );
789 return pInfo
->mpSalQueueInfo
.get();
791 // last chance: the first available printer
792 return pPrnList
->m_aQueueInfos
[0].mpSalQueueInfo
.get();
798 void Printer::ImplUpdatePageData()
800 // we need a graphics
801 if ( !AcquireGraphics() )
804 mpGraphics
->GetResolution( mnDPIX
, mnDPIY
);
805 mpInfoPrinter
->GetPageInfo( &maJobSetup
.ImplGetConstData(),
806 mnOutWidth
, mnOutHeight
,
811 void Printer::ImplUpdateFontList()
813 ImplUpdateFontData();
816 tools::Long
Printer::GetGradientStepCount( tools::Long nMinRect
)
818 // use display-equivalent step size calculation
819 tools::Long nInc
= (nMinRect
< 800) ? 10 : 20;
825 : OutputDevice(OUTDEV_PRINTER
)
828 SalPrinterQueueInfo
* pInfo
= ImplGetQueueInfo( GetDefaultPrinterName(), nullptr );
832 if ( !IsDisplayPrinter() )
839 Printer::Printer( const JobSetup
& rJobSetup
)
840 : OutputDevice(OUTDEV_PRINTER
)
841 , maJobSetup(rJobSetup
)
844 const ImplJobSetup
& rConstData
= rJobSetup
.ImplGetConstData();
845 const OUString
& aDriver
= rConstData
.GetDriver();
846 SalPrinterQueueInfo
* pInfo
= ImplGetQueueInfo( rConstData
.GetPrinterName(),
851 SetJobSetup( rJobSetup
);
856 maJobSetup
= JobSetup();
860 Printer::Printer( const QueueInfo
& rQueueInfo
)
861 : OutputDevice(OUTDEV_PRINTER
)
864 SalPrinterQueueInfo
* pInfo
= ImplGetQueueInfo( rQueueInfo
.GetPrinterName(),
865 &rQueueInfo
.GetDriver() );
872 Printer::Printer( const OUString
& rPrinterName
)
873 : OutputDevice(OUTDEV_PRINTER
)
876 SalPrinterQueueInfo
* pInfo
= ImplGetQueueInfo( rPrinterName
, nullptr );
888 void Printer::dispose()
890 SAL_WARN_IF( IsPrinting(), "vcl.gdi", "Printer::~Printer() - Job is printing" );
891 SAL_WARN_IF( IsJobActive(), "vcl.gdi", "Printer::~Printer() - Job is active" );
893 mpPrinterOptions
.reset();
895 ImplReleaseGraphics();
897 ImplGetSVData()->mpDefInst
->DestroyInfoPrinter( mpInfoPrinter
);
899 mpDisplayDev
.disposeAndClear();
902 // OutputDevice Dtor is trying the same thing; that why we need to set
903 // the FontEntry to NULL here
904 // TODO: consolidate duplicate cleanup by Printer and OutputDevice
905 mpFontInstance
.clear();
906 mpFontFaceCollection
.reset();
908 // font list deleted by OutputDevice dtor
911 // Add printer from the list
912 ImplSVData
* pSVData
= ImplGetSVData();
914 mpPrev
->mpNext
= mpNext
;
916 pSVData
->maGDIData
.mpFirstPrinter
= mpNext
;
918 mpNext
->mpPrev
= mpPrev
;
922 OutputDevice::dispose();
925 Size
Printer::GetButtonBorderSize()
927 Size
aBrdSize(LogicToPixel(Size(20, 20), MapMode(MapUnit::Map100thMM
)));
929 if (!aBrdSize
.Width())
930 aBrdSize
.setWidth(1);
932 if (!aBrdSize
.Height())
933 aBrdSize
.setHeight(1);
938 sal_uInt32
Printer::GetCapabilities( PrinterCapType nType
) const
940 if ( IsDisplayPrinter() )
944 return mpInfoPrinter
->GetCapabilities( &maJobSetup
.ImplGetConstData(), nType
);
949 bool Printer::HasSupport( PrinterSupport eFeature
) const
953 case PrinterSupport::SetOrientation
:
954 return GetCapabilities( PrinterCapType::SetOrientation
) != 0;
955 case PrinterSupport::SetPaperSize
:
956 return GetCapabilities( PrinterCapType::SetPaperSize
) != 0;
957 case PrinterSupport::SetPaper
:
958 return GetCapabilities( PrinterCapType::SetPaper
) != 0;
959 case PrinterSupport::CollateCopy
:
960 return (GetCapabilities( PrinterCapType::CollateCopies
) != 0);
961 case PrinterSupport::SetupDialog
:
962 return GetCapabilities( PrinterCapType::SupportDialog
) != 0;
968 bool Printer::SetJobSetup( const JobSetup
& rSetup
)
970 if ( IsDisplayPrinter() || mbInPrintPage
)
973 JobSetup aJobSetup
= rSetup
;
976 if ( mpInfoPrinter
->SetPrinterData( &aJobSetup
.ImplGetData() ) )
978 ImplUpdateJobSetupPaper( aJobSetup
);
979 mbNewJobSetup
= true;
980 maJobSetup
= std::move(aJobSetup
);
981 ImplUpdatePageData();
982 ImplUpdateFontList();
989 bool Printer::Setup(weld::Window
* pWindow
, PrinterSetupMode eMode
)
991 if ( IsDisplayPrinter() )
994 if ( IsJobActive() || IsPrinting() )
997 JobSetup aJobSetup
= maJobSetup
;
998 ImplJobSetup
& rData
= aJobSetup
.ImplGetData();
999 rData
.SetPrinterSetupMode( eMode
);
1000 // TODO: orig page size
1004 vcl::Window
* pDefWin
= ImplGetDefaultWindow();
1005 pWindow
= pDefWin
? pDefWin
->GetFrameWeld() : nullptr;
1011 ImplSVData
* pSVData
= ImplGetSVData();
1012 pSVData
->maAppData
.mnModalMode
++;
1014 bool bSetup
= mpInfoPrinter
->Setup(pWindow
, &rData
);
1015 pSVData
->maAppData
.mnModalMode
--;
1019 ImplUpdateJobSetupPaper( aJobSetup
);
1020 mbNewJobSetup
= true;
1021 maJobSetup
= std::move(aJobSetup
);
1022 ImplUpdatePageData();
1023 ImplUpdateFontList();
1029 bool Printer::SetPrinterProps( const Printer
* pPrinter
)
1031 if ( IsJobActive() || IsPrinting() )
1034 ImplSVData
* pSVData
= ImplGetSVData();
1036 mbDefPrinter
= pPrinter
->mbDefPrinter
;
1037 maPrintFile
= pPrinter
->maPrintFile
;
1038 mbPrintFile
= pPrinter
->mbPrintFile
;
1039 mnCopyCount
= pPrinter
->mnCopyCount
;
1040 mbCollateCopy
= pPrinter
->mbCollateCopy
;
1041 mnPageQueueSize
= pPrinter
->mnPageQueueSize
;
1042 *mpPrinterOptions
= *pPrinter
->mpPrinterOptions
;
1044 if ( pPrinter
->IsDisplayPrinter() )
1046 // Destroy old printer
1047 if ( !IsDisplayPrinter() )
1050 pSVData
->mpDefInst
->DestroyInfoPrinter( mpInfoPrinter
);
1051 mpFontInstance
.clear();
1052 mpFontFaceCollection
.reset();
1053 // clean up font list
1054 mxFontCache
.reset();
1055 mxFontCollection
.reset();
1059 mpInfoPrinter
= nullptr;
1062 // Construct new printer
1067 // Destroy old printer?
1068 if ( GetName() != pPrinter
->GetName() )
1073 mpDisplayDev
.disposeAndClear();
1077 pSVData
->mpDefInst
->DestroyInfoPrinter( mpInfoPrinter
);
1079 mpFontInstance
.clear();
1080 mpFontFaceCollection
.reset();
1081 mxFontCache
.reset();
1082 mxFontCollection
.reset();
1085 mpInfoPrinter
= nullptr;
1088 // Construct new printer
1089 const OUString
& aDriver
= pPrinter
->GetDriverName();
1090 SalPrinterQueueInfo
* pInfo
= ImplGetQueueInfo( pPrinter
->GetName(), &aDriver
);
1094 SetJobSetup( pPrinter
->GetJobSetup() );
1100 SetJobSetup( pPrinter
->GetJobSetup() );
1105 bool Printer::SetOrientation( Orientation eOrientation
)
1107 if ( mbInPrintPage
)
1110 if ( maJobSetup
.ImplGetConstData().GetOrientation() != eOrientation
)
1112 JobSetup aJobSetup
= maJobSetup
;
1113 ImplJobSetup
& rData
= aJobSetup
.ImplGetData();
1115 rData
.SetOrientation(eOrientation
);
1117 if ( IsDisplayPrinter() )
1119 mbNewJobSetup
= true;
1120 maJobSetup
= aJobSetup
;
1125 if ( mpInfoPrinter
->SetData( JobSetFlags::ORIENTATION
, &rData
) )
1127 ImplUpdateJobSetupPaper( aJobSetup
);
1128 mbNewJobSetup
= true;
1129 maJobSetup
= std::move(aJobSetup
);
1130 ImplUpdatePageData();
1131 ImplUpdateFontList();
1141 Orientation
Printer::GetOrientation() const
1143 return maJobSetup
.ImplGetConstData().GetOrientation();
1146 bool Printer::SetPaperBin( sal_uInt16 nPaperBin
)
1148 if ( mbInPrintPage
)
1151 if ( maJobSetup
.ImplGetConstData().GetPaperBin() != nPaperBin
&&
1152 nPaperBin
< GetPaperBinCount() )
1154 JobSetup aJobSetup
= maJobSetup
;
1155 ImplJobSetup
& rData
= aJobSetup
.ImplGetData();
1156 rData
.SetPaperBin(nPaperBin
);
1158 if ( IsDisplayPrinter() )
1160 mbNewJobSetup
= true;
1161 maJobSetup
= aJobSetup
;
1166 if ( mpInfoPrinter
->SetData( JobSetFlags::PAPERBIN
, &rData
) )
1168 ImplUpdateJobSetupPaper( aJobSetup
);
1169 mbNewJobSetup
= true;
1170 maJobSetup
= std::move(aJobSetup
);
1171 ImplUpdatePageData();
1172 ImplUpdateFontList();
1182 sal_uInt16
Printer::GetPaperBin() const
1184 return maJobSetup
.ImplGetConstData().GetPaperBin();
1187 bool Printer::GetPrinterSettingsPreferred() const
1189 return maJobSetup
.ImplGetConstData().GetPapersizeFromSetup();
1192 // dear loplugins, DO NOT REMOVE this code
1193 // it will be used in follow-up commits
1194 void Printer::SetPrinterSettingsPreferred( bool bPaperSizeFromSetup
)
1196 if ( maJobSetup
.ImplGetConstData().GetPapersizeFromSetup() != bPaperSizeFromSetup
)
1198 JobSetup aJobSetup
= maJobSetup
;
1199 ImplJobSetup
& rData
= aJobSetup
.ImplGetData();
1200 rData
.SetPapersizeFromSetup(bPaperSizeFromSetup
);
1202 mbNewJobSetup
= true;
1203 maJobSetup
= std::move(aJobSetup
);
1207 // Map user paper format to an available printer paper format
1208 void Printer::ImplFindPaperFormatForUserSize( JobSetup
& aJobSetup
)
1210 ImplJobSetup
& rData
= aJobSetup
.ImplGetData();
1212 // The angle that a landscape page will be turned counterclockwise wrt to portrait.
1213 int nLandscapeAngle
= mpInfoPrinter
? mpInfoPrinter
->GetLandscapeAngle( &maJobSetup
.ImplGetConstData() ) : 900;
1214 int nPaperCount
= GetPaperInfoCount();
1215 PaperInfo
aInfo(rData
.GetPaperWidth(), rData
.GetPaperHeight());
1217 // Compare all paper formats and get the appropriate one
1218 for ( int i
= 0; i
< nPaperCount
; i
++ )
1220 const PaperInfo
& rPaperInfo
= GetPaperInfo( i
);
1222 if ( aInfo
.sloppyEqual(rPaperInfo
) )
1224 rData
.SetPaperFormat(
1225 ImplGetPaperFormat( rPaperInfo
.getWidth(),
1226 rPaperInfo
.getHeight() ));
1227 rData
.SetOrientation( Orientation::Portrait
);
1232 // If the printer supports landscape orientation, check paper sizes again
1233 // with landscape orientation. This is necessary as a printer driver provides
1234 // all paper sizes with portrait orientation only!!
1235 if ( !(rData
.GetPaperFormat() == PAPER_USER
&&
1236 nLandscapeAngle
!= 0 &&
1237 HasSupport( PrinterSupport::SetOrientation
)))
1240 const tools::Long nRotatedWidth
= rData
.GetPaperHeight();
1241 const tools::Long nRotatedHeight
= rData
.GetPaperWidth();
1242 PaperInfo
aRotatedInfo(nRotatedWidth
, nRotatedHeight
);
1244 for ( int i
= 0; i
< nPaperCount
; i
++ )
1246 const PaperInfo
& rPaperInfo
= GetPaperInfo( i
);
1248 if ( aRotatedInfo
.sloppyEqual( rPaperInfo
) )
1250 rData
.SetPaperFormat(
1251 ImplGetPaperFormat( rPaperInfo
.getWidth(),
1252 rPaperInfo
.getHeight() ));
1253 rData
.SetOrientation( Orientation::Landscape
);
1259 void Printer::SetPaper( Paper ePaper
)
1261 if ( mbInPrintPage
)
1264 if ( maJobSetup
.ImplGetConstData().GetPaperFormat() == ePaper
)
1267 JobSetup aJobSetup
= maJobSetup
;
1268 ImplJobSetup
& rData
= aJobSetup
.ImplGetData();
1270 rData
.SetPaperFormat( ePaper
);
1271 if ( ePaper
!= PAPER_USER
)
1273 PaperInfo
aInfo(ePaper
);
1274 rData
.SetPaperWidth( aInfo
.getWidth() );
1275 rData
.SetPaperHeight( aInfo
.getHeight() );
1278 if ( IsDisplayPrinter() )
1280 mbNewJobSetup
= true;
1281 maJobSetup
= aJobSetup
;
1286 if ( ePaper
== PAPER_USER
)
1287 ImplFindPaperFormatForUserSize( aJobSetup
);
1288 if ( mpInfoPrinter
->SetData( JobSetFlags::PAPERSIZE
| JobSetFlags::ORIENTATION
, &rData
))
1290 ImplUpdateJobSetupPaper( aJobSetup
);
1291 mbNewJobSetup
= true;
1292 maJobSetup
= std::move(aJobSetup
);
1293 ImplUpdatePageData();
1294 ImplUpdateFontList();
1298 bool Printer::SetPaperSizeUser( const Size
& rSize
)
1300 if ( mbInPrintPage
)
1303 const Size aPixSize
= LogicToPixel( rSize
);
1304 const Size aPageSize
= PixelToLogic(aPixSize
, MapMode(MapUnit::Map100thMM
));
1305 bool bNeedToChange(maJobSetup
.ImplGetConstData().GetPaperWidth() != aPageSize
.Width() ||
1306 maJobSetup
.ImplGetConstData().GetPaperHeight() != aPageSize
.Height());
1310 // #i122984# only need to change when Paper is different from PAPER_USER and
1311 // the mapped Paper which will created below in the call to ImplFindPaperFormatForUserSize
1312 // and will replace maJobSetup.ImplGetConstData()->GetPaperFormat(). This leads to
1313 // unnecessary JobSetups, e.g. when printing a multi-page fax, but also with
1315 const Paper aPaper
= ImplGetPaperFormat(aPageSize
.Width(), aPageSize
.Height());
1317 bNeedToChange
= maJobSetup
.ImplGetConstData().GetPaperFormat() != PAPER_USER
&&
1318 maJobSetup
.ImplGetConstData().GetPaperFormat() != aPaper
;
1322 Size aPaperSize
= GetPaperSizePixel();
1323 bNeedToChange
= (aPageSize
.Width() < aPageSize
.Height()
1324 && aPaperSize
.Width() > aPaperSize
.Height())
1325 || (aPageSize
.Width() > aPageSize
.Height()
1326 && aPaperSize
.Width() < aPaperSize
.Height());
1332 JobSetup aJobSetup
= maJobSetup
;
1333 ImplJobSetup
& rData
= aJobSetup
.ImplGetData();
1334 rData
.SetPaperFormat( PAPER_USER
);
1335 rData
.SetPaperWidth( aPageSize
.Width() );
1336 rData
.SetPaperHeight( aPageSize
.Height() );
1337 rData
.SetOrientation( Orientation::Portrait
);
1339 if ( IsDisplayPrinter() )
1341 mbNewJobSetup
= true;
1342 maJobSetup
= std::move(aJobSetup
);
1347 ImplFindPaperFormatForUserSize( aJobSetup
);
1349 // Changing the paper size can also change the orientation!
1350 if ( mpInfoPrinter
->SetData( JobSetFlags::PAPERSIZE
| JobSetFlags::ORIENTATION
, &rData
))
1352 ImplUpdateJobSetupPaper( aJobSetup
);
1353 mbNewJobSetup
= true;
1354 maJobSetup
= std::move(aJobSetup
);
1355 ImplUpdatePageData();
1356 ImplUpdateFontList();
1366 int Printer::GetPaperInfoCount() const
1368 if( ! mpInfoPrinter
)
1370 if( ! mpInfoPrinter
->m_bPapersInit
)
1371 mpInfoPrinter
->InitPaperFormats( &maJobSetup
.ImplGetConstData() );
1372 return mpInfoPrinter
->m_aPaperFormats
.size();
1375 OUString
Printer::GetPaperName( Paper ePaper
)
1377 ImplSVData
* pSVData
= ImplGetSVData();
1378 if( pSVData
->maPaperNames
.empty() )
1380 // This array must (probably) match exactly the enum Paper in <i18nutil/paper.hxx>
1381 static const int PaperIndex
[] =
1383 PAPER_A0
, PAPER_A1
, PAPER_A2
, PAPER_A3
, PAPER_A4
, PAPER_A5
, PAPER_B4_ISO
, PAPER_B5_ISO
,
1384 PAPER_LETTER
, PAPER_LEGAL
, PAPER_TABLOID
, PAPER_USER
, PAPER_B6_ISO
, PAPER_ENV_C4
, PAPER_ENV_C5
,
1385 PAPER_ENV_C6
, PAPER_ENV_C65
, PAPER_ENV_DL
, PAPER_SLIDE_DIA
, PAPER_SCREEN_4_3
, PAPER_C
, PAPER_D
,
1386 PAPER_E
, PAPER_EXECUTIVE
, PAPER_FANFOLD_LEGAL_DE
, PAPER_ENV_MONARCH
, PAPER_ENV_PERSONAL
, PAPER_ENV_9
,
1387 PAPER_ENV_10
, PAPER_ENV_11
, PAPER_ENV_12
, PAPER_KAI16
, PAPER_KAI32
, PAPER_KAI32BIG
, PAPER_B4_JIS
,
1388 PAPER_B5_JIS
, PAPER_B6_JIS
, PAPER_LEDGER
, PAPER_STATEMENT
, PAPER_QUARTO
, PAPER_10x14
, PAPER_ENV_14
,
1389 PAPER_ENV_C3
, PAPER_ENV_ITALY
, PAPER_FANFOLD_US
, PAPER_FANFOLD_DE
, PAPER_POSTCARD_JP
, PAPER_9x11
,
1390 PAPER_10x11
, PAPER_15x11
, PAPER_ENV_INVITE
, PAPER_A_PLUS
, PAPER_B_PLUS
, PAPER_LETTER_PLUS
, PAPER_A4_PLUS
,
1391 PAPER_DOUBLEPOSTCARD_JP
, PAPER_A6
, PAPER_12x11
, PAPER_A7
, PAPER_A8
, PAPER_A9
, PAPER_A10
, PAPER_B0_ISO
,
1392 PAPER_B1_ISO
, PAPER_B2_ISO
, PAPER_B3_ISO
, PAPER_B7_ISO
, PAPER_B8_ISO
, PAPER_B9_ISO
, PAPER_B10_ISO
,
1393 PAPER_ENV_C2
, PAPER_ENV_C7
, PAPER_ENV_C8
, PAPER_ARCHA
, PAPER_ARCHB
, PAPER_ARCHC
, PAPER_ARCHD
,
1394 PAPER_ARCHE
, PAPER_SCREEN_16_9
, PAPER_SCREEN_16_10
, PAPER_16K_195x270
, PAPER_16K_197x273
,
1395 PAPER_WIDESCREEN
, PAPER_ONSCREENSHOW_4_3
, PAPER_ONSCREENSHOW_16_9
, PAPER_ONSCREENSHOW_16_10
1397 static_assert(SAL_N_ELEMENTS(PaperIndex
) == SAL_N_ELEMENTS(RID_STR_PAPERNAMES
), "localized paper name count wrong");
1398 for (size_t i
= 0; i
< SAL_N_ELEMENTS(PaperIndex
); ++i
)
1399 pSVData
->maPaperNames
[PaperIndex
[i
]] = VclResId(RID_STR_PAPERNAMES
[i
]);
1402 std::unordered_map
<int,OUString
>::const_iterator it
= pSVData
->maPaperNames
.find( static_cast<int>(ePaper
) );
1403 return (it
!= pSVData
->maPaperNames
.end()) ? it
->second
: OUString();
1406 const PaperInfo
& Printer::GetPaperInfo( int nPaper
) const
1408 if( ! mpInfoPrinter
)
1409 return ImplGetEmptyPaper();
1410 if( ! mpInfoPrinter
->m_bPapersInit
)
1411 mpInfoPrinter
->InitPaperFormats( &maJobSetup
.ImplGetConstData() );
1412 if( mpInfoPrinter
->m_aPaperFormats
.empty() || nPaper
< 0 || o3tl::make_unsigned(nPaper
) >= mpInfoPrinter
->m_aPaperFormats
.size() )
1413 return ImplGetEmptyPaper();
1414 return mpInfoPrinter
->m_aPaperFormats
[nPaper
];
1417 Size
Printer::GetPaperSize( int nPaper
) const
1419 PaperInfo aInfo
= GetPaperInfo( nPaper
);
1420 return PixelToLogic( Size( aInfo
.getWidth(), aInfo
.getHeight() ) );
1423 void Printer::SetDuplexMode( DuplexMode eDuplex
)
1425 if ( mbInPrintPage
)
1428 if ( maJobSetup
.ImplGetConstData().GetDuplexMode() == eDuplex
)
1431 JobSetup aJobSetup
= maJobSetup
;
1432 ImplJobSetup
& rData
= aJobSetup
.ImplGetData();
1434 rData
.SetDuplexMode( eDuplex
);
1436 if ( IsDisplayPrinter() )
1438 mbNewJobSetup
= true;
1439 maJobSetup
= aJobSetup
;
1444 if ( mpInfoPrinter
->SetData( JobSetFlags::DUPLEXMODE
, &rData
) )
1446 ImplUpdateJobSetupPaper( aJobSetup
);
1447 mbNewJobSetup
= true;
1448 maJobSetup
= std::move(aJobSetup
);
1449 ImplUpdatePageData();
1450 ImplUpdateFontList();
1454 DuplexMode
Printer::GetDuplexMode() const
1456 return maJobSetup
.ImplGetConstData().GetDuplexMode();
1459 Paper
Printer::GetPaper() const
1461 return maJobSetup
.ImplGetConstData().GetPaperFormat();
1464 Size
Printer::GetSizeOfPaper() const
1466 return Size(maJobSetup
.ImplGetConstData().GetPaperWidth(), maJobSetup
.ImplGetConstData().GetPaperHeight());
1469 sal_uInt16
Printer::GetPaperBinCount() const
1471 if ( IsDisplayPrinter() )
1474 return mpInfoPrinter
->GetPaperBinCount( &maJobSetup
.ImplGetConstData() );
1477 OUString
Printer::GetPaperBinName( sal_uInt16 nPaperBin
) const
1479 if ( IsDisplayPrinter() )
1482 if ( nPaperBin
< GetPaperBinCount() )
1483 return mpInfoPrinter
->GetPaperBinName( &maJobSetup
.ImplGetConstData(), nPaperBin
);
1488 sal_uInt16
Printer::GetPaperBinBySourceIndex(sal_uInt16 nPaperSource
) const
1490 if ( IsDisplayPrinter() )
1493 return mpInfoPrinter
->GetPaperBinBySourceIndex( &maJobSetup
.ImplGetConstData(), nPaperSource
);
1496 sal_uInt16
Printer::GetSourceIndexByPaperBin(sal_uInt16 nPaperBin
) const
1498 if (IsDisplayPrinter())
1501 return mpInfoPrinter
->GetSourceIndexByPaperBin( &maJobSetup
.ImplGetConstData(), nPaperBin
);
1504 void Printer::SetCopyCount( sal_uInt16 nCopy
, bool bCollate
)
1506 mnCopyCount
= nCopy
;
1507 mbCollateCopy
= bCollate
;
1510 ErrCode
Printer::ImplSalPrinterErrorCodeToVCL( SalPrinterError nError
)
1515 case SalPrinterError::NONE
:
1516 nVCLError
= ERRCODE_NONE
;
1518 case SalPrinterError::Abort
:
1519 nVCLError
= PRINTER_ABORT
;
1522 nVCLError
= PRINTER_GENERALERROR
;
1529 void Printer::EndJob()
1531 if ( !IsJobActive() )
1534 SAL_WARN_IF( mbInPrintPage
, "vcl.gdi", "Printer::EndJob() - StartPage() without EndPage() called" );
1536 mbJobActive
= false;
1544 mbDevOutput
= false;
1545 mpPrinter
->EndJob();
1550 void Printer::ImplStartPage()
1552 if ( !IsJobActive() )
1558 SalGraphics
* pGraphics
= mpPrinter
->StartPage( &maJobSetup
.ImplGetData(),
1563 mpJobGraphics
= pGraphics
;
1567 // PrintJob not aborted ???
1568 if ( IsJobActive() )
1569 mbInPrintPage
= true;
1572 void Printer::ImplEndPage()
1574 if ( !IsJobActive() )
1577 mbInPrintPage
= false;
1582 mpPrinter
->EndPage();
1583 mbDevOutput
= false;
1585 mpJobGraphics
= nullptr;
1586 mbNewJobSetup
= false;
1590 void Printer::updatePrinters()
1592 ImplSVData
* pSVData
= ImplGetSVData();
1593 ImplPrnQueueList
* pPrnList
= pSVData
->maGDIData
.mpPrinterQueueList
.get();
1598 std::unique_ptr
<ImplPrnQueueList
> pNewList(new ImplPrnQueueList
);
1599 pSVData
->mpDefInst
->GetPrinterQueueInfo( pNewList
.get() );
1601 bool bChanged
= pPrnList
->m_aQueueInfos
.size() != pNewList
->m_aQueueInfos
.size();
1602 for( decltype(pPrnList
->m_aQueueInfos
)::size_type i
= 0; ! bChanged
&& i
< pPrnList
->m_aQueueInfos
.size(); i
++ )
1604 ImplPrnQueueData
& rInfo
= pPrnList
->m_aQueueInfos
[i
];
1605 ImplPrnQueueData
& rNewInfo
= pNewList
->m_aQueueInfos
[i
];
1606 if( ! rInfo
.mpSalQueueInfo
|| ! rNewInfo
.mpSalQueueInfo
|| // sanity check
1607 rInfo
.mpSalQueueInfo
->maPrinterName
!= rNewInfo
.mpSalQueueInfo
->maPrinterName
)
1615 ImplDeletePrnQueueList();
1616 pSVData
->maGDIData
.mpPrinterQueueList
= std::move(pNewList
);
1618 Application
* pApp
= GetpApp();
1621 DataChangedEvent
aDCEvt( DataChangedEventType::PRINTER
);
1622 Application::ImplCallEventListenersApplicationDataChanged(&aDCEvt
);
1623 Application::NotifyAllWindows( aDCEvt
);
1627 bool Printer::UsePolyPolygonForComplexGradient()
1632 void Printer::ClipAndDrawGradientMetafile ( const Gradient
&rGradient
, const tools::PolyPolygon
&rPolyPoly
)
1634 const tools::Rectangle
aBoundRect( rPolyPoly
.GetBoundRect() );
1636 Push( vcl::PushFlags::CLIPREGION
);
1637 IntersectClipRegion(vcl::Region(rPolyPoly
));
1638 DrawGradient( aBoundRect
, rGradient
);
1642 void Printer::SetFontOrientation( LogicalFontInstance
* const pFontEntry
) const
1644 pFontEntry
->mnOrientation
= pFontEntry
->mxFontMetric
->GetOrientation();
1647 vcl::Region
Printer::ClipToDeviceBounds(vcl::Region aRegion
) const
1652 Bitmap
Printer::GetBitmap( const Point
& rSrcPt
, const Size
& rSize
) const
1654 SAL_WARN("vcl.gdi", "GetBitmap(): This should never be called on by a Printer instance");
1656 return OutputDevice::GetBitmap( rSrcPt
, rSize
);
1659 css::awt::DeviceInfo
Printer::GetDeviceInfo() const
1661 Size aDevSz
= GetPaperSizePixel();
1662 css::awt::DeviceInfo aInfo
= GetCommonDeviceInfo(aDevSz
);
1663 Size aOutSz
= GetOutputSizePixel();
1664 Point aOffset
= GetPageOffset();
1665 aInfo
.LeftInset
= aOffset
.X();
1666 aInfo
.TopInset
= aOffset
.Y();
1667 aInfo
.RightInset
= aDevSz
.Width() - aOutSz
.Width() - aOffset
.X();
1668 aInfo
.BottomInset
= aDevSz
.Height() - aOutSz
.Height() - aOffset
.Y();
1669 aInfo
.Capabilities
= 0;
1674 void Printer::SetWaveLineColors(Color
const& rColor
, tools::Long
)
1676 if (mbLineColor
|| mbInitLineColor
)
1678 mpGraphics
->SetLineColor();
1679 mbInitLineColor
= true;
1682 mpGraphics
->SetFillColor(rColor
);
1683 mbInitFillColor
= true;
1686 Size
Printer::GetWaveLineSize(tools::Long nLineWidth
) const
1688 // FIXME - do we have a bug here? If the linewidth is 0, then we will return
1689 // Size(0, 0) - is this correct?
1690 return Size(nLineWidth
, ((nLineWidth
*mnDPIX
)+(mnDPIY
/2))/mnDPIY
);
1693 void Printer::SetSystemTextColor(SystemTextColorFlags
, bool)
1695 SetTextColor(COL_BLACK
);
1698 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */