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/QueueInfo.hxx>
27 #include <vcl/event.hxx>
28 #include <vcl/virdev.hxx>
29 #include <vcl/print.hxx>
31 #include <comphelper/processfactory.hxx>
33 #include <salinst.hxx>
36 #include <salptype.hxx>
42 #include <PhysicalFontCollection.hxx>
45 #include <com/sun/star/beans/XPropertySet.hpp>
46 #include <com/sun/star/configuration/theDefaultProvider.hpp>
47 #include <com/sun/star/container/XNameAccess.hpp>
48 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
49 #include <com/sun/star/uno/Sequence.h>
51 int nImplSysDialog
= 0;
55 Paper
ImplGetPaperFormat( tools::Long nWidth100thMM
, tools::Long nHeight100thMM
)
57 PaperInfo
aInfo(nWidth100thMM
, nHeight100thMM
);
59 return aInfo
.getPaper();
62 const PaperInfo
& ImplGetEmptyPaper()
64 static PaperInfo
aInfo(PAPER_USER
);
69 void ImplUpdateJobSetupPaper( JobSetup
& rJobSetup
)
71 const ImplJobSetup
& rConstData
= rJobSetup
.ImplGetConstData();
73 if ( !rConstData
.GetPaperWidth() || !rConstData
.GetPaperHeight() )
75 if ( rConstData
.GetPaperFormat() != PAPER_USER
)
77 PaperInfo
aInfo(rConstData
.GetPaperFormat());
79 ImplJobSetup
& rData
= rJobSetup
.ImplGetData();
80 rData
.SetPaperWidth( aInfo
.getWidth() );
81 rData
.SetPaperHeight( aInfo
.getHeight() );
84 else if ( rConstData
.GetPaperFormat() == PAPER_USER
)
86 Paper ePaper
= ImplGetPaperFormat( rConstData
.GetPaperWidth(), rConstData
.GetPaperHeight() );
87 if ( ePaper
!= PAPER_USER
)
88 rJobSetup
.ImplGetData().SetPaperFormat(ePaper
);
93 PrinterOptions::PrinterOptions() :
94 mbReduceTransparency( false ),
95 meReducedTransparencyMode( PrinterTransparencyMode::Auto
),
96 mbReduceGradients( false ),
97 meReducedGradientsMode( PrinterGradientMode::Stripes
),
98 mnReducedGradientStepCount( 64 ),
99 mbReduceBitmaps( false ),
100 meReducedBitmapMode( PrinterBitmapMode::Normal
),
101 mnReducedBitmapResolution( 200 ),
102 mbReducedBitmapsIncludeTransparency( true ),
103 mbConvertToGreyscales( false ),
104 mbPDFAsStandardPrintJobFormat( false )
108 void PrinterOptions::ReadFromConfig( bool i_bFile
)
110 bool bSuccess
= false;
111 // save old state in case something goes wrong
112 PrinterOptions
aOldValues( *this );
114 // get the configuration service
115 css::uno::Reference
< css::lang::XMultiServiceFactory
> xConfigProvider
;
116 css::uno::Reference
< css::container::XNameAccess
> xConfigAccess
;
119 // get service provider
120 css::uno::Reference
< css::uno::XComponentContext
> xContext( comphelper::getProcessComponentContext() );
121 // create configuration hierarchical access name
124 xConfigProvider
= css::configuration::theDefaultProvider::get( xContext
);
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" );
133 xConfigProvider
->createInstanceWithArguments(
134 "com.sun.star.configuration.ConfigurationAccess", { css::uno::Any(aVal
) } ),
135 css::uno::UNO_QUERY
);
136 if( xConfigAccess
.is() )
138 css::uno::Reference
< css::beans::XPropertySet
> xSet( xConfigAccess
, css::uno::UNO_QUERY
);
141 sal_Int32 nValue
= 0;
143 if( xSet
->getPropertyValue("ReduceTransparency") >>= bValue
)
144 SetReduceTransparency( bValue
);
145 if( xSet
->getPropertyValue("ReducedTransparencyMode") >>= nValue
)
146 SetReducedTransparencyMode( static_cast<PrinterTransparencyMode
>(nValue
) );
147 if( xSet
->getPropertyValue("ReduceGradients") >>= bValue
)
148 SetReduceGradients( bValue
);
149 if( xSet
->getPropertyValue("ReducedGradientMode") >>= nValue
)
150 SetReducedGradientMode( static_cast<PrinterGradientMode
>(nValue
) );
151 if( xSet
->getPropertyValue("ReducedGradientStepCount") >>= nValue
)
152 SetReducedGradientStepCount( static_cast<sal_uInt16
>(nValue
) );
153 if( xSet
->getPropertyValue("ReduceBitmaps") >>= bValue
)
154 SetReduceBitmaps( bValue
);
155 if( xSet
->getPropertyValue("ReducedBitmapMode") >>= nValue
)
156 SetReducedBitmapMode( static_cast<PrinterBitmapMode
>(nValue
) );
157 if( xSet
->getPropertyValue("ReducedBitmapResolution") >>= nValue
)
158 SetReducedBitmapResolution( static_cast<sal_uInt16
>(nValue
) );
159 if( xSet
->getPropertyValue("ReducedBitmapIncludesTransparency") >>= bValue
)
160 SetReducedBitmapIncludesTransparency( bValue
);
161 if( xSet
->getPropertyValue("ConvertToGreyscales") >>= bValue
)
162 SetConvertToGreyscales( bValue
);
163 if( xSet
->getPropertyValue("PDFAsStandardPrintJobFormat") >>= bValue
)
164 SetPDFAsStandardPrintJobFormat( bValue
);
170 catch( const css::uno::Exception
& )
174 catch( const css::lang::WrappedTargetException
& )
182 void Printer::ImplPrintTransparent( const Bitmap
& rBmp
, const Bitmap
& rMask
,
183 const Point
& rDestPt
, const Size
& rDestSize
,
184 const Point
& rSrcPtPixel
, const Size
& rSrcSizePixel
)
186 Point
aDestPt( LogicToPixel( rDestPt
) );
187 Size
aDestSz( LogicToPixel( rDestSize
) );
188 tools::Rectangle
aSrcRect( rSrcPtPixel
, rSrcSizePixel
);
192 if( rBmp
.IsEmpty() || !aSrcRect
.GetWidth() || !aSrcRect
.GetHeight() || !aDestSz
.Width() || !aDestSz
.Height() )
195 Bitmap
aPaint( rBmp
), aMask( rMask
);
196 BmpMirrorFlags nMirrFlags
= BmpMirrorFlags::NONE
;
198 if (aMask
.getPixelFormat() > vcl::PixelFormat::N1_BPP
)
199 aMask
.Convert( BmpConversion::N1BitThreshold
);
201 // mirrored horizontally
202 if( aDestSz
.Width() < 0 )
204 aDestSz
.setWidth( -aDestSz
.Width() );
205 aDestPt
.AdjustX( -( aDestSz
.Width() - 1 ) );
206 nMirrFlags
|= BmpMirrorFlags::Horizontal
;
209 // mirrored vertically
210 if( aDestSz
.Height() < 0 )
212 aDestSz
.setHeight( -aDestSz
.Height() );
213 aDestPt
.AdjustY( -( aDestSz
.Height() - 1 ) );
214 nMirrFlags
|= BmpMirrorFlags::Vertical
;
218 if( aSrcRect
!= tools::Rectangle( Point(), aPaint
.GetSizePixel() ) )
220 aPaint
.Crop( aSrcRect
);
221 aMask
.Crop( aSrcRect
);
224 // destination mirrored
225 if( nMirrFlags
!= BmpMirrorFlags::NONE
)
227 aPaint
.Mirror( nMirrFlags
);
228 aMask
.Mirror( nMirrFlags
);
231 // we always want to have a mask
232 if( aMask
.IsEmpty() )
234 aMask
= Bitmap(aSrcRect
.GetSize(), vcl::PixelFormat::N1_BPP
);
235 aMask
.Erase( COL_BLACK
);
239 const tools::Long nSrcWidth
= aSrcRect
.GetWidth(), nSrcHeight
= aSrcRect
.GetHeight();
240 tools::Long nX
, nY
; // , nWorkX, nWorkY, nWorkWidth, nWorkHeight;
241 std::unique_ptr
<tools::Long
[]> pMapX(new tools::Long
[ nSrcWidth
+ 1 ]);
242 std::unique_ptr
<tools::Long
[]> pMapY(new tools::Long
[ nSrcHeight
+ 1 ]);
243 const bool bOldMap
= mbMap
;
247 // create forward mapping tables
248 for( nX
= 0; nX
<= nSrcWidth
; nX
++ )
249 pMapX
[ nX
] = aDestPt
.X() + FRound( static_cast<double>(aDestSz
.Width()) * nX
/ nSrcWidth
);
251 for( nY
= 0; nY
<= nSrcHeight
; nY
++ )
252 pMapY
[ nY
] = aDestPt
.Y() + FRound( static_cast<double>(aDestSz
.Height()) * nY
/ nSrcHeight
);
254 // walk through all rectangles of mask
255 const vcl::Region
aWorkRgn(aMask
.CreateRegion(COL_BLACK
, tools::Rectangle(Point(), aMask
.GetSizePixel())));
256 RectangleVector aRectangles
;
257 aWorkRgn
.GetRegionRectangles(aRectangles
);
259 for (auto const& rectangle
: aRectangles
)
261 const Point
aMapPt(pMapX
[rectangle
.Left()], pMapY
[rectangle
.Top()]);
262 const Size
aMapSz( pMapX
[rectangle
.Right() + 1] - aMapPt
.X(), // pMapX[L + W] -> L + ((R - L) + 1) -> R + 1
263 pMapY
[rectangle
.Bottom() + 1] - aMapPt
.Y()); // same for Y
264 Bitmap
aBandBmp(aPaint
);
266 aBandBmp
.Crop(rectangle
);
267 DrawBitmap(aMapPt
, aMapSz
, Point(), aBandBmp
.GetSizePixel(), aBandBmp
);
274 bool Printer::DrawTransformBitmapExDirect(
275 const basegfx::B2DHomMatrix
& /*aFullTransform*/,
276 const BitmapEx
& /*rBitmapEx*/,
279 // printers can't draw bitmaps directly
283 bool Printer::TransformAndReduceBitmapExToTargetRange(
284 const basegfx::B2DHomMatrix
& /*aFullTransform*/,
285 basegfx::B2DRange
& /*aVisibleRange*/,
286 double& /*fMaximumArea*/)
288 // deliberately do nothing - you can't reduce the
289 // target range for a printer at all
293 void Printer::DrawDeviceBitmap( const Point
& rDestPt
, const Size
& rDestSize
,
294 const Point
& rSrcPtPixel
, const Size
& rSrcSizePixel
,
297 if( rBmpEx
.IsAlpha() )
299 // #107169# For true alpha bitmaps, no longer masking the
300 // bitmap, but perform a full alpha blend against a white
302 Bitmap
aBmp( rBmpEx
.GetBitmap() );
303 aBmp
.Blend( rBmpEx
.GetAlpha(), COL_WHITE
);
304 DrawBitmap( rDestPt
, rDestSize
, rSrcPtPixel
, rSrcSizePixel
, aBmp
);
308 Bitmap
aBmp( rBmpEx
.GetBitmap() );
309 ImplPrintTransparent( aBmp
, Bitmap(), rDestPt
, rDestSize
, rSrcPtPixel
, rSrcSizePixel
);
313 void Printer::EmulateDrawTransparent ( const tools::PolyPolygon
& rPolyPoly
,
314 sal_uInt16 nTransparencePercent
)
316 // #110958# Disable alpha VDev, we perform the necessary
317 VirtualDevice
* pOldAlphaVDev
= mpAlphaVDev
;
319 // operation explicitly further below.
321 mpAlphaVDev
= nullptr;
323 GDIMetaFile
* pOldMetaFile
= mpMetaFile
;
324 mpMetaFile
= nullptr;
326 mpMetaFile
= pOldMetaFile
;
328 // #110958# Restore disabled alpha VDev
329 mpAlphaVDev
= pOldAlphaVDev
;
331 tools::Rectangle
aPolyRect( LogicToPixel( rPolyPoly
).GetBoundRect() );
332 const Size
aDPISize( LogicToPixel(Size(1, 1), MapMode(MapUnit::MapInch
)) );
333 const tools::Long nBaseExtent
= std::max
<tools::Long
>( FRound( aDPISize
.Width() / 300. ), 1 );
335 const sal_uInt16 nTrans
= ( nTransparencePercent
< 13 ) ? 0 :
336 ( nTransparencePercent
< 38 ) ? 25 :
337 ( nTransparencePercent
< 63 ) ? 50 :
338 ( nTransparencePercent
< 88 ) ? 75 : 100;
342 case 25: nMove
= nBaseExtent
* 3; break;
343 case 50: nMove
= nBaseExtent
* 4; break;
344 case 75: nMove
= nBaseExtent
* 6; break;
346 // #i112959# very transparent (88 < nTransparencePercent <= 99)
347 case 100: nMove
= nBaseExtent
* 8; break;
349 // #i112959# not transparent (nTransparencePercent < 13)
350 default: nMove
= 0; break;
353 Push( PushFlags::CLIPREGION
| PushFlags::LINECOLOR
);
354 IntersectClipRegion(vcl::Region(rPolyPoly
));
355 SetLineColor( GetFillColor() );
356 const bool bOldMap
= mbMap
;
357 EnableMapMode( false );
361 tools::Rectangle
aRect( aPolyRect
.TopLeft(), Size( aPolyRect
.GetWidth(), nBaseExtent
) );
362 while( aRect
.Top() <= aPolyRect
.Bottom() )
365 aRect
.Move( 0, nMove
);
368 aRect
= tools::Rectangle( aPolyRect
.TopLeft(), Size( nBaseExtent
, aPolyRect
.GetHeight() ) );
369 while( aRect
.Left() <= aPolyRect
.Right() )
372 aRect
.Move( nMove
, 0 );
377 // #i112959# if not transparent, draw full rectangle in clip region
378 DrawRect( aPolyRect
);
381 EnableMapMode( bOldMap
);
384 mpMetaFile
= pOldMetaFile
;
386 // #110958# Restore disabled alpha VDev
387 mpAlphaVDev
= pOldAlphaVDev
;
390 void Printer::DrawOutDev( const Point
& /*rDestPt*/, const Size
& /*rDestSize*/,
391 const Point
& /*rSrcPt*/, const Size
& /*rSrcSize*/ )
393 SAL_WARN( "vcl.gdi", "Don't use OutputDevice::DrawOutDev(...) with printer devices!" );
396 void Printer::DrawOutDev( const Point
& /*rDestPt*/, const Size
& /*rDestSize*/,
397 const Point
& /*rSrcPt*/, const Size
& /*rSrcSize*/,
398 const OutputDevice
& /*rOutDev*/ )
400 SAL_WARN( "vcl.gdi", "Don't use OutputDevice::DrawOutDev(...) with printer devices!" );
403 void Printer::CopyArea( const Point
& /*rDestPt*/,
404 const Point
& /*rSrcPt*/, const Size
& /*rSrcSize*/,
405 bool /*bWindowInvalidate*/ )
407 SAL_WARN( "vcl.gdi", "Don't use OutputDevice::CopyArea(...) with printer devices!" );
410 tools::Rectangle
Printer::GetBackgroundComponentBounds() const
412 Point aPageOffset
= Point( 0, 0 ) - this->GetPageOffsetPixel();
413 Size aSize
= this->GetPaperSizePixel();
414 return tools::Rectangle( aPageOffset
, aSize
);
417 void Printer::SetPrinterOptions( const PrinterOptions
& i_rOptions
)
419 *mpPrinterOptions
= i_rOptions
;
422 bool Printer::HasMirroredGraphics() const
424 // due to a "hotfix" for AOO bug i55719, this needs to return false
428 SalPrinterQueueInfo::SalPrinterQueueInfo()
430 mnStatus
= PrintQueueFlags::NONE
;
431 mnJobs
= QUEUE_JOBS_DONTKNOW
;
434 SalPrinterQueueInfo::~SalPrinterQueueInfo()
438 ImplPrnQueueList::~ImplPrnQueueList()
442 void ImplPrnQueueList::Add( std::unique_ptr
<SalPrinterQueueInfo
> pData
)
444 std::unordered_map
< OUString
, sal_Int32
>::iterator it
=
445 m_aNameToIndex
.find( pData
->maPrinterName
);
446 if( it
== m_aNameToIndex
.end() )
448 m_aNameToIndex
[ pData
->maPrinterName
] = m_aQueueInfos
.size();
449 m_aPrinterList
.push_back( pData
->maPrinterName
);
450 m_aQueueInfos
.push_back( ImplPrnQueueData() );
451 m_aQueueInfos
.back().mpQueueInfo
= nullptr;
452 m_aQueueInfos
.back().mpSalQueueInfo
= std::move(pData
);
454 else // this should not happen, but ...
456 ImplPrnQueueData
& rData
= m_aQueueInfos
[ it
->second
];
457 rData
.mpQueueInfo
.reset();
458 rData
.mpSalQueueInfo
= std::move(pData
);
462 ImplPrnQueueData
* ImplPrnQueueList::Get( const OUString
& rPrinter
)
464 ImplPrnQueueData
* pData
= nullptr;
465 std::unordered_map
<OUString
,sal_Int32
>::iterator it
=
466 m_aNameToIndex
.find( rPrinter
);
467 if( it
!= m_aNameToIndex
.end() )
468 pData
= &m_aQueueInfos
[it
->second
];
472 static void ImplInitPrnQueueList()
474 ImplSVData
* pSVData
= ImplGetSVData();
476 pSVData
->maGDIData
.mpPrinterQueueList
.reset(new ImplPrnQueueList
);
478 static const char* pEnv
= getenv( "SAL_DISABLE_PRINTERLIST" );
479 if( !pEnv
|| !*pEnv
)
480 pSVData
->mpDefInst
->GetPrinterQueueInfo( pSVData
->maGDIData
.mpPrinterQueueList
.get() );
483 void ImplDeletePrnQueueList()
485 ImplSVData
* pSVData
= ImplGetSVData();
486 pSVData
->maGDIData
.mpPrinterQueueList
.reset();
489 const std::vector
<OUString
>& Printer::GetPrinterQueues()
491 ImplSVData
* pSVData
= ImplGetSVData();
492 if ( !pSVData
->maGDIData
.mpPrinterQueueList
)
493 ImplInitPrnQueueList();
494 return pSVData
->maGDIData
.mpPrinterQueueList
->m_aPrinterList
;
497 const QueueInfo
* Printer::GetQueueInfo( const OUString
& rPrinterName
, bool bStatusUpdate
)
499 ImplSVData
* pSVData
= ImplGetSVData();
501 if ( !pSVData
->maGDIData
.mpPrinterQueueList
)
502 ImplInitPrnQueueList();
504 if ( !pSVData
->maGDIData
.mpPrinterQueueList
)
507 ImplPrnQueueData
* pInfo
= pSVData
->maGDIData
.mpPrinterQueueList
->Get( rPrinterName
);
510 if( !pInfo
->mpQueueInfo
|| bStatusUpdate
)
511 pSVData
->mpDefInst
->GetPrinterQueueState( pInfo
->mpSalQueueInfo
.get() );
513 if ( !pInfo
->mpQueueInfo
)
514 pInfo
->mpQueueInfo
.reset(new QueueInfo
);
516 pInfo
->mpQueueInfo
->maPrinterName
= pInfo
->mpSalQueueInfo
->maPrinterName
;
517 pInfo
->mpQueueInfo
->maDriver
= pInfo
->mpSalQueueInfo
->maDriver
;
518 pInfo
->mpQueueInfo
->maLocation
= pInfo
->mpSalQueueInfo
->maLocation
;
519 pInfo
->mpQueueInfo
->maComment
= pInfo
->mpSalQueueInfo
->maComment
;
520 pInfo
->mpQueueInfo
->mnStatus
= pInfo
->mpSalQueueInfo
->mnStatus
;
521 pInfo
->mpQueueInfo
->mnJobs
= pInfo
->mpSalQueueInfo
->mnJobs
;
522 return pInfo
->mpQueueInfo
.get();
527 OUString
Printer::GetDefaultPrinterName()
529 static const char* pEnv
= getenv( "SAL_DISABLE_DEFAULTPRINTER" );
530 if( !pEnv
|| !*pEnv
)
532 ImplSVData
* pSVData
= ImplGetSVData();
534 return pSVData
->mpDefInst
->GetDefaultPrinter();
539 void Printer::ImplInitData()
542 mbDefPrinter
= false;
543 mnError
= ERRCODE_NONE
;
546 mbCollateCopy
= false;
550 mbInPrintPage
= false;
551 mbNewJobSetup
= false;
552 mbSinglePrintJobs
= false;
553 mpInfoPrinter
= nullptr;
555 mpDisplayDev
= nullptr;
556 mpPrinterOptions
.reset(new PrinterOptions
);
558 // Add printer to the list
559 ImplSVData
* pSVData
= ImplGetSVData();
560 mpNext
= pSVData
->maGDIData
.mpFirstPrinter
;
563 mpNext
->mpPrev
= this;
564 pSVData
->maGDIData
.mpFirstPrinter
= this;
567 bool Printer::AcquireGraphics() const
569 DBG_TESTSOLARMUTEX();
574 mbInitLineColor
= true;
575 mbInitFillColor
= true;
577 mbInitTextColor
= true;
578 mbInitClipRegion
= true;
580 ImplSVData
* pSVData
= ImplGetSVData();
583 mpGraphics
= mpJobGraphics
;
584 else if ( mpDisplayDev
)
586 const VirtualDevice
* pVirDev
= mpDisplayDev
;
587 mpGraphics
= pVirDev
->mpVirDev
->AcquireGraphics();
588 // if needed retry after releasing least recently used virtual device graphics
589 while ( !mpGraphics
)
591 if ( !pSVData
->maGDIData
.mpLastVirGraphics
)
593 pSVData
->maGDIData
.mpLastVirGraphics
->ReleaseGraphics();
594 mpGraphics
= pVirDev
->mpVirDev
->AcquireGraphics();
596 // update global LRU list of virtual device graphics
599 mpNextGraphics
= pSVData
->maGDIData
.mpFirstVirGraphics
;
600 pSVData
->maGDIData
.mpFirstVirGraphics
= const_cast<Printer
*>(this);
601 if ( mpNextGraphics
)
602 mpNextGraphics
->mpPrevGraphics
= const_cast<Printer
*>(this);
603 if ( !pSVData
->maGDIData
.mpLastVirGraphics
)
604 pSVData
->maGDIData
.mpLastVirGraphics
= const_cast<Printer
*>(this);
609 mpGraphics
= mpInfoPrinter
->AcquireGraphics();
610 // if needed retry after releasing least recently used printer graphics
611 while ( !mpGraphics
)
613 if ( !pSVData
->maGDIData
.mpLastPrnGraphics
)
615 pSVData
->maGDIData
.mpLastPrnGraphics
->ReleaseGraphics();
616 mpGraphics
= mpInfoPrinter
->AcquireGraphics();
618 // update global LRU list of printer graphics
621 mpNextGraphics
= pSVData
->maGDIData
.mpFirstPrnGraphics
;
622 pSVData
->maGDIData
.mpFirstPrnGraphics
= const_cast<Printer
*>(this);
623 if ( mpNextGraphics
)
624 mpNextGraphics
->mpPrevGraphics
= const_cast<Printer
*>(this);
625 if ( !pSVData
->maGDIData
.mpLastPrnGraphics
)
626 pSVData
->maGDIData
.mpLastPrnGraphics
= const_cast<Printer
*>(this);
632 mpGraphics
->SetXORMode( (RasterOp::Invert
== meRasterOp
) || (RasterOp::Xor
== meRasterOp
), RasterOp::Invert
== meRasterOp
);
633 mpGraphics
->setAntiAlias(bool(mnAntialiasing
& AntialiasingFlags::Enable
));
636 return mpGraphics
!= nullptr;
639 void Printer::ImplReleaseFonts()
642 // HACK to fix an urgent P1 printing issue fast
643 // WinSalPrinter does not respect GetGraphics/ReleaseGraphics conventions
644 // so Printer::mpGraphics often points to a dead WinSalGraphics
645 // TODO: fix WinSalPrinter's GetGraphics/ReleaseGraphics handling
646 mpGraphics
->ReleaseFonts();
651 mpFontInstance
.clear();
652 mpDeviceFontList
.reset();
653 mpDeviceFontSizeList
.reset();
656 void Printer::ReleaseGraphics( bool bRelease
)
658 DBG_TESTSOLARMUTEX();
663 // release the fonts of the physically released graphics device
667 ImplSVData
* pSVData
= ImplGetSVData();
669 Printer
* pPrinter
= this;
671 if ( !pPrinter
->mpJobGraphics
)
673 if ( pPrinter
->mpDisplayDev
)
675 VirtualDevice
* pVirDev
= pPrinter
->mpDisplayDev
;
677 pVirDev
->mpVirDev
->ReleaseGraphics( mpGraphics
);
678 // remove from global LRU list of virtual device graphics
679 if ( mpPrevGraphics
)
680 mpPrevGraphics
->mpNextGraphics
= mpNextGraphics
;
682 pSVData
->maGDIData
.mpFirstVirGraphics
= mpNextGraphics
;
683 if ( mpNextGraphics
)
684 mpNextGraphics
->mpPrevGraphics
= mpPrevGraphics
;
686 pSVData
->maGDIData
.mpLastVirGraphics
= mpPrevGraphics
;
691 pPrinter
->mpInfoPrinter
->ReleaseGraphics( mpGraphics
);
692 // remove from global LRU list of printer graphics
693 if ( mpPrevGraphics
)
694 mpPrevGraphics
->mpNextGraphics
= mpNextGraphics
;
696 pSVData
->maGDIData
.mpFirstPrnGraphics
= static_cast<Printer
*>(mpNextGraphics
.get());
697 if ( mpNextGraphics
)
698 mpNextGraphics
->mpPrevGraphics
= mpPrevGraphics
;
700 pSVData
->maGDIData
.mpLastPrnGraphics
= static_cast<Printer
*>(mpPrevGraphics
.get());
704 mpGraphics
= nullptr;
705 mpPrevGraphics
= nullptr;
706 mpNextGraphics
= nullptr;
709 void Printer::ImplInit( SalPrinterQueueInfo
* pInfo
)
711 ImplSVData
* pSVData
= ImplGetSVData();
712 // #i74084# update info for this specific SalPrinterQueueInfo
713 pSVData
->mpDefInst
->GetPrinterQueueState( pInfo
);
715 // Test whether the driver actually matches the JobSetup
716 ImplJobSetup
& rData
= maJobSetup
.ImplGetData();
717 if ( rData
.GetDriverData() )
719 if ( rData
.GetPrinterName() != pInfo
->maPrinterName
||
720 rData
.GetDriver() != pInfo
->maDriver
)
722 std::free( const_cast<sal_uInt8
*>(rData
.GetDriverData()) );
723 rData
.SetDriverData(nullptr);
724 rData
.SetDriverDataLen(0);
728 // Remember printer name
729 maPrinterName
= pInfo
->maPrinterName
;
730 maDriver
= pInfo
->maDriver
;
732 // Add printer name to JobSetup
733 rData
.SetPrinterName( maPrinterName
);
734 rData
.SetDriver( maDriver
);
736 mpInfoPrinter
= pSVData
->mpDefInst
->CreateInfoPrinter( pInfo
, &rData
);
738 mpJobGraphics
= nullptr;
739 ImplUpdateJobSetupPaper( maJobSetup
);
741 if ( !mpInfoPrinter
)
747 // we need a graphics
748 if ( !AcquireGraphics() )
755 ImplUpdatePageData();
756 mxFontCollection
= std::make_shared
<PhysicalFontCollection
>();
757 mxFontCache
= std::make_shared
<ImplFontCache
>();
758 mpGraphics
->GetDevFontList(mxFontCollection
.get());
761 void Printer::ImplInitDisplay()
763 ImplSVData
* pSVData
= ImplGetSVData();
765 mpInfoPrinter
= nullptr;
767 mpJobGraphics
= nullptr;
769 mpDisplayDev
= VclPtr
<VirtualDevice
>::Create();
770 mxFontCollection
= pSVData
->maGDIData
.mxScreenFontList
;
771 mxFontCache
= pSVData
->maGDIData
.mxScreenFontCache
;
772 mnDPIX
= mpDisplayDev
->mnDPIX
;
773 mnDPIY
= mpDisplayDev
->mnDPIY
;
776 void Printer::DrawDeviceMask( const Bitmap
& rMask
, const Color
& rMaskColor
,
777 const Point
& rDestPt
, const Size
& rDestSize
,
778 const Point
& rSrcPtPixel
, const Size
& rSrcSizePixel
)
780 Point
aDestPt( LogicToPixel( rDestPt
) );
781 Size
aDestSz( LogicToPixel( rDestSize
) );
782 tools::Rectangle
aSrcRect( rSrcPtPixel
, rSrcSizePixel
);
786 if( !(!rMask
.IsEmpty() && aSrcRect
.GetWidth() && aSrcRect
.GetHeight() && aDestSz
.Width() && aDestSz
.Height()) )
789 Bitmap
aMask( rMask
);
790 BmpMirrorFlags nMirrFlags
= BmpMirrorFlags::NONE
;
792 if (aMask
.getPixelFormat() > vcl::PixelFormat::N1_BPP
)
793 aMask
.Convert( BmpConversion::N1BitThreshold
);
795 // mirrored horizontally
796 if( aDestSz
.Width() < 0 )
798 aDestSz
.setWidth( -aDestSz
.Width() );
799 aDestPt
.AdjustX( -( aDestSz
.Width() - 1 ) );
800 nMirrFlags
|= BmpMirrorFlags::Horizontal
;
803 // mirrored vertically
804 if( aDestSz
.Height() < 0 )
806 aDestSz
.setHeight( -aDestSz
.Height() );
807 aDestPt
.AdjustY( -( aDestSz
.Height() - 1 ) );
808 nMirrFlags
|= BmpMirrorFlags::Vertical
;
812 if( aSrcRect
!= tools::Rectangle( Point(), aMask
.GetSizePixel() ) )
813 aMask
.Crop( aSrcRect
);
815 // destination mirrored
816 if( nMirrFlags
!= BmpMirrorFlags::NONE
)
817 aMask
.Mirror( nMirrFlags
);
820 const tools::Long nSrcWidth
= aSrcRect
.GetWidth(), nSrcHeight
= aSrcRect
.GetHeight();
821 tools::Long nX
, nY
; //, nWorkX, nWorkY, nWorkWidth, nWorkHeight;
822 std::unique_ptr
<tools::Long
[]> pMapX( new tools::Long
[ nSrcWidth
+ 1 ] );
823 std::unique_ptr
<tools::Long
[]> pMapY( new tools::Long
[ nSrcHeight
+ 1 ] );
824 GDIMetaFile
* pOldMetaFile
= mpMetaFile
;
825 const bool bOldMap
= mbMap
;
827 mpMetaFile
= nullptr;
829 Push( PushFlags::FILLCOLOR
| PushFlags::LINECOLOR
);
830 SetLineColor( rMaskColor
);
831 SetFillColor( rMaskColor
);
835 // create forward mapping tables
836 for( nX
= 0; nX
<= nSrcWidth
; nX
++ )
837 pMapX
[ nX
] = aDestPt
.X() + FRound( static_cast<double>(aDestSz
.Width()) * nX
/ nSrcWidth
);
839 for( nY
= 0; nY
<= nSrcHeight
; nY
++ )
840 pMapY
[ nY
] = aDestPt
.Y() + FRound( static_cast<double>(aDestSz
.Height()) * nY
/ nSrcHeight
);
842 // walk through all rectangles of mask
843 const vcl::Region
aWorkRgn(aMask
.CreateRegion(COL_BLACK
, tools::Rectangle(Point(), aMask
.GetSizePixel())));
844 RectangleVector aRectangles
;
845 aWorkRgn
.GetRegionRectangles(aRectangles
);
847 for (auto const& rectangle
: aRectangles
)
849 const Point
aMapPt(pMapX
[rectangle
.Left()], pMapY
[rectangle
.Top()]);
851 pMapX
[rectangle
.Right() + 1] - aMapPt
.X(), // pMapX[L + W] -> L + ((R - L) + 1) -> R + 1
852 pMapY
[rectangle
.Bottom() + 1] - aMapPt
.Y()); // same for Y
854 DrawRect(tools::Rectangle(aMapPt
, aMapSz
));
859 mpMetaFile
= pOldMetaFile
;
862 SalPrinterQueueInfo
* Printer::ImplGetQueueInfo( const OUString
& rPrinterName
,
863 const OUString
* pDriver
)
865 ImplSVData
* pSVData
= ImplGetSVData();
866 if ( !pSVData
->maGDIData
.mpPrinterQueueList
)
867 ImplInitPrnQueueList();
869 ImplPrnQueueList
* pPrnList
= pSVData
->maGDIData
.mpPrinterQueueList
.get();
870 if ( pPrnList
&& !pPrnList
->m_aQueueInfos
.empty() )
872 // first search for the printer name directly
873 ImplPrnQueueData
* pInfo
= pPrnList
->Get( rPrinterName
);
875 return pInfo
->mpSalQueueInfo
.get();
877 // then search case insensitive
878 for(const ImplPrnQueueData
& rQueueInfo
: pPrnList
->m_aQueueInfos
)
880 if( rQueueInfo
.mpSalQueueInfo
->maPrinterName
.equalsIgnoreAsciiCase( rPrinterName
) )
881 return rQueueInfo
.mpSalQueueInfo
.get();
884 // then search for driver name
887 for(const ImplPrnQueueData
& rQueueInfo
: pPrnList
->m_aQueueInfos
)
889 if( rQueueInfo
.mpSalQueueInfo
->maDriver
== *pDriver
)
890 return rQueueInfo
.mpSalQueueInfo
.get();
894 // then the default printer
895 pInfo
= pPrnList
->Get( GetDefaultPrinterName() );
897 return pInfo
->mpSalQueueInfo
.get();
899 // last chance: the first available printer
900 return pPrnList
->m_aQueueInfos
[0].mpSalQueueInfo
.get();
906 void Printer::ImplUpdatePageData()
908 // we need a graphics
909 if ( !AcquireGraphics() )
912 mpGraphics
->GetResolution( mnDPIX
, mnDPIY
);
913 mpInfoPrinter
->GetPageInfo( &maJobSetup
.ImplGetConstData(),
914 mnOutWidth
, mnOutHeight
,
919 void Printer::ImplUpdateFontList()
921 ImplUpdateFontData();
924 tools::Long
Printer::GetGradientStepCount( tools::Long nMinRect
)
926 // use display-equivalent step size calculation
927 tools::Long nInc
= (nMinRect
< 800) ? 10 : 20;
933 : OutputDevice(OUTDEV_PRINTER
)
936 SalPrinterQueueInfo
* pInfo
= ImplGetQueueInfo( GetDefaultPrinterName(), nullptr );
940 if ( !IsDisplayPrinter() )
947 Printer::Printer( const JobSetup
& rJobSetup
)
948 : OutputDevice(OUTDEV_PRINTER
)
949 , maJobSetup(rJobSetup
)
952 const ImplJobSetup
& rConstData
= rJobSetup
.ImplGetConstData();
953 OUString aDriver
= rConstData
.GetDriver();
954 SalPrinterQueueInfo
* pInfo
= ImplGetQueueInfo( rConstData
.GetPrinterName(),
959 SetJobSetup( rJobSetup
);
964 maJobSetup
= JobSetup();
968 Printer::Printer( const QueueInfo
& rQueueInfo
)
969 : OutputDevice(OUTDEV_PRINTER
)
972 SalPrinterQueueInfo
* pInfo
= ImplGetQueueInfo( rQueueInfo
.GetPrinterName(),
973 &rQueueInfo
.GetDriver() );
980 Printer::Printer( const OUString
& rPrinterName
)
981 : OutputDevice(OUTDEV_PRINTER
)
984 SalPrinterQueueInfo
* pInfo
= ImplGetQueueInfo( rPrinterName
, nullptr );
996 void Printer::dispose()
998 SAL_WARN_IF( IsPrinting(), "vcl.gdi", "Printer::~Printer() - Job is printing" );
999 SAL_WARN_IF( IsJobActive(), "vcl.gdi", "Printer::~Printer() - Job is active" );
1001 mpPrinterOptions
.reset();
1004 if ( mpInfoPrinter
)
1005 ImplGetSVData()->mpDefInst
->DestroyInfoPrinter( mpInfoPrinter
);
1007 mpDisplayDev
.disposeAndClear();
1010 // OutputDevice Dtor is trying the same thing; that why we need to set
1011 // the FontEntry to NULL here
1012 // TODO: consolidate duplicate cleanup by Printer and OutputDevice
1013 mpFontInstance
.clear();
1014 mpDeviceFontList
.reset();
1015 mpDeviceFontSizeList
.reset();
1016 mxFontCache
.reset();
1017 // font list deleted by OutputDevice dtor
1020 // Add printer from the list
1021 ImplSVData
* pSVData
= ImplGetSVData();
1023 mpPrev
->mpNext
= mpNext
;
1025 pSVData
->maGDIData
.mpFirstPrinter
= mpNext
;
1027 mpNext
->mpPrev
= mpPrev
;
1031 OutputDevice::dispose();
1034 Size
Printer::GetButtonBorderSize()
1036 Size
aBrdSize(LogicToPixel(Size(20, 20), MapMode(MapUnit::Map100thMM
)));
1038 if (!aBrdSize
.Width())
1039 aBrdSize
.setWidth(1);
1041 if (!aBrdSize
.Height())
1042 aBrdSize
.setHeight(1);
1047 sal_uInt32
Printer::GetCapabilities( PrinterCapType nType
) const
1049 if ( IsDisplayPrinter() )
1053 return mpInfoPrinter
->GetCapabilities( &maJobSetup
.ImplGetConstData(), nType
);
1058 bool Printer::HasSupport( PrinterSupport eFeature
) const
1062 case PrinterSupport::SetOrientation
:
1063 return GetCapabilities( PrinterCapType::SetOrientation
) != 0;
1064 case PrinterSupport::SetPaperSize
:
1065 return GetCapabilities( PrinterCapType::SetPaperSize
) != 0;
1066 case PrinterSupport::SetPaper
:
1067 return GetCapabilities( PrinterCapType::SetPaper
) != 0;
1068 case PrinterSupport::CollateCopy
:
1069 return (GetCapabilities( PrinterCapType::CollateCopies
) != 0);
1070 case PrinterSupport::SetupDialog
:
1071 return GetCapabilities( PrinterCapType::SupportDialog
) != 0;
1077 bool Printer::SetJobSetup( const JobSetup
& rSetup
)
1079 if ( IsDisplayPrinter() || mbInPrintPage
)
1082 JobSetup aJobSetup
= rSetup
;
1085 if ( mpInfoPrinter
->SetPrinterData( &aJobSetup
.ImplGetData() ) )
1087 ImplUpdateJobSetupPaper( aJobSetup
);
1088 mbNewJobSetup
= true;
1089 maJobSetup
= aJobSetup
;
1090 ImplUpdatePageData();
1091 ImplUpdateFontList();
1098 bool Printer::Setup(weld::Window
* pWindow
, PrinterSetupMode eMode
)
1100 if ( IsDisplayPrinter() )
1103 if ( IsJobActive() || IsPrinting() )
1106 JobSetup aJobSetup
= maJobSetup
;
1107 ImplJobSetup
& rData
= aJobSetup
.ImplGetData();
1108 rData
.SetPrinterSetupMode( eMode
);
1109 // TODO: orig page size
1113 vcl::Window
* pDefWin
= ImplGetDefaultWindow();
1114 pWindow
= pDefWin
? pDefWin
->GetFrameWeld() : nullptr;
1120 ImplSVData
* pSVData
= ImplGetSVData();
1121 pSVData
->maAppData
.mnModalMode
++;
1123 bool bSetup
= mpInfoPrinter
->Setup(pWindow
, &rData
);
1124 pSVData
->maAppData
.mnModalMode
--;
1128 ImplUpdateJobSetupPaper( aJobSetup
);
1129 mbNewJobSetup
= true;
1130 maJobSetup
= aJobSetup
;
1131 ImplUpdatePageData();
1132 ImplUpdateFontList();
1138 bool Printer::SetPrinterProps( const Printer
* pPrinter
)
1140 if ( IsJobActive() || IsPrinting() )
1143 ImplSVData
* pSVData
= ImplGetSVData();
1145 mbDefPrinter
= pPrinter
->mbDefPrinter
;
1146 maPrintFile
= pPrinter
->maPrintFile
;
1147 mbPrintFile
= pPrinter
->mbPrintFile
;
1148 mnCopyCount
= pPrinter
->mnCopyCount
;
1149 mbCollateCopy
= pPrinter
->mbCollateCopy
;
1150 mnPageQueueSize
= pPrinter
->mnPageQueueSize
;
1151 *mpPrinterOptions
= *pPrinter
->mpPrinterOptions
;
1153 if ( pPrinter
->IsDisplayPrinter() )
1155 // Destroy old printer
1156 if ( !IsDisplayPrinter() )
1159 pSVData
->mpDefInst
->DestroyInfoPrinter( mpInfoPrinter
);
1160 mpFontInstance
.clear();
1161 mpDeviceFontList
.reset();
1162 mpDeviceFontSizeList
.reset();
1163 // clean up font list
1164 mxFontCache
.reset();
1165 mxFontCollection
.reset();
1169 mpInfoPrinter
= nullptr;
1172 // Construct new printer
1177 // Destroy old printer?
1178 if ( GetName() != pPrinter
->GetName() )
1183 mpDisplayDev
.disposeAndClear();
1187 pSVData
->mpDefInst
->DestroyInfoPrinter( mpInfoPrinter
);
1189 mpFontInstance
.clear();
1190 mpDeviceFontList
.reset();
1191 mpDeviceFontSizeList
.reset();
1192 mxFontCache
.reset();
1193 mxFontCollection
.reset();
1196 mpInfoPrinter
= nullptr;
1199 // Construct new printer
1200 OUString aDriver
= pPrinter
->GetDriverName();
1201 SalPrinterQueueInfo
* pInfo
= ImplGetQueueInfo( pPrinter
->GetName(), &aDriver
);
1205 SetJobSetup( pPrinter
->GetJobSetup() );
1211 SetJobSetup( pPrinter
->GetJobSetup() );
1216 bool Printer::SetOrientation( Orientation eOrientation
)
1218 if ( mbInPrintPage
)
1221 if ( maJobSetup
.ImplGetConstData().GetOrientation() != eOrientation
)
1223 JobSetup aJobSetup
= maJobSetup
;
1224 ImplJobSetup
& rData
= aJobSetup
.ImplGetData();
1226 rData
.SetOrientation(eOrientation
);
1228 if ( IsDisplayPrinter() )
1230 mbNewJobSetup
= true;
1231 maJobSetup
= aJobSetup
;
1236 if ( mpInfoPrinter
->SetData( JobSetFlags::ORIENTATION
, &rData
) )
1238 ImplUpdateJobSetupPaper( aJobSetup
);
1239 mbNewJobSetup
= true;
1240 maJobSetup
= aJobSetup
;
1241 ImplUpdatePageData();
1242 ImplUpdateFontList();
1252 Orientation
Printer::GetOrientation() const
1254 return maJobSetup
.ImplGetConstData().GetOrientation();
1257 bool Printer::SetPaperBin( sal_uInt16 nPaperBin
)
1259 if ( mbInPrintPage
)
1262 if ( maJobSetup
.ImplGetConstData().GetPaperBin() != nPaperBin
&&
1263 nPaperBin
< GetPaperBinCount() )
1265 JobSetup aJobSetup
= maJobSetup
;
1266 ImplJobSetup
& rData
= aJobSetup
.ImplGetData();
1267 rData
.SetPaperBin(nPaperBin
);
1269 if ( IsDisplayPrinter() )
1271 mbNewJobSetup
= true;
1272 maJobSetup
= aJobSetup
;
1277 if ( mpInfoPrinter
->SetData( JobSetFlags::PAPERBIN
, &rData
) )
1279 ImplUpdateJobSetupPaper( aJobSetup
);
1280 mbNewJobSetup
= true;
1281 maJobSetup
= aJobSetup
;
1282 ImplUpdatePageData();
1283 ImplUpdateFontList();
1293 sal_uInt16
Printer::GetPaperBin() const
1295 return maJobSetup
.ImplGetConstData().GetPaperBin();
1298 bool Printer::GetPrinterSettingsPreferred() const
1300 return maJobSetup
.ImplGetConstData().GetPapersizeFromSetup();
1303 // dear loplugins, DO NOT REMOVE this code
1304 // it will be used in follow-up commits
1305 void Printer::SetPrinterSettingsPreferred( bool bPaperSizeFromSetup
)
1307 if ( maJobSetup
.ImplGetConstData().GetPapersizeFromSetup() != bPaperSizeFromSetup
)
1309 JobSetup aJobSetup
= maJobSetup
;
1310 ImplJobSetup
& rData
= aJobSetup
.ImplGetData();
1311 rData
.SetPapersizeFromSetup(bPaperSizeFromSetup
);
1313 mbNewJobSetup
= true;
1314 maJobSetup
= aJobSetup
;
1318 // Map user paper format to an available printer paper format
1319 void Printer::ImplFindPaperFormatForUserSize( JobSetup
& aJobSetup
)
1321 ImplJobSetup
& rData
= aJobSetup
.ImplGetData();
1323 // The angle that a landscape page will be turned counterclockwise wrt to portrait.
1324 int nLandscapeAngle
= mpInfoPrinter
? mpInfoPrinter
->GetLandscapeAngle( &maJobSetup
.ImplGetConstData() ) : 900;
1325 int nPaperCount
= GetPaperInfoCount();
1326 PaperInfo
aInfo(rData
.GetPaperWidth(), rData
.GetPaperHeight());
1328 // Compare all paper formats and get the appropriate one
1329 for ( int i
= 0; i
< nPaperCount
; i
++ )
1331 const PaperInfo
& rPaperInfo
= GetPaperInfo( i
);
1333 if ( aInfo
.sloppyEqual(rPaperInfo
) )
1335 rData
.SetPaperFormat(
1336 ImplGetPaperFormat( rPaperInfo
.getWidth(),
1337 rPaperInfo
.getHeight() ));
1338 rData
.SetOrientation( Orientation::Portrait
);
1343 // If the printer supports landscape orientation, check paper sizes again
1344 // with landscape orientation. This is necessary as a printer driver provides
1345 // all paper sizes with portrait orientation only!!
1346 if ( !(rData
.GetPaperFormat() == PAPER_USER
&&
1347 nLandscapeAngle
!= 0 &&
1348 HasSupport( PrinterSupport::SetOrientation
)))
1351 const tools::Long nRotatedWidth
= rData
.GetPaperHeight();
1352 const tools::Long nRotatedHeight
= rData
.GetPaperWidth();
1353 PaperInfo
aRotatedInfo(nRotatedWidth
, nRotatedHeight
);
1355 for ( int i
= 0; i
< nPaperCount
; i
++ )
1357 const PaperInfo
& rPaperInfo
= GetPaperInfo( i
);
1359 if ( aRotatedInfo
.sloppyEqual( rPaperInfo
) )
1361 rData
.SetPaperFormat(
1362 ImplGetPaperFormat( rPaperInfo
.getWidth(),
1363 rPaperInfo
.getHeight() ));
1364 rData
.SetOrientation( Orientation::Landscape
);
1370 void Printer::SetPaper( Paper ePaper
)
1372 if ( mbInPrintPage
)
1375 if ( maJobSetup
.ImplGetConstData().GetPaperFormat() == ePaper
)
1378 JobSetup aJobSetup
= maJobSetup
;
1379 ImplJobSetup
& rData
= aJobSetup
.ImplGetData();
1381 rData
.SetPaperFormat( ePaper
);
1382 if ( ePaper
!= PAPER_USER
)
1384 PaperInfo
aInfo(ePaper
);
1385 rData
.SetPaperWidth( aInfo
.getWidth() );
1386 rData
.SetPaperHeight( aInfo
.getHeight() );
1389 if ( IsDisplayPrinter() )
1391 mbNewJobSetup
= true;
1392 maJobSetup
= aJobSetup
;
1397 if ( ePaper
== PAPER_USER
)
1398 ImplFindPaperFormatForUserSize( aJobSetup
);
1399 if ( mpInfoPrinter
->SetData( JobSetFlags::PAPERSIZE
| JobSetFlags::ORIENTATION
, &rData
))
1401 ImplUpdateJobSetupPaper( aJobSetup
);
1402 mbNewJobSetup
= true;
1403 maJobSetup
= aJobSetup
;
1404 ImplUpdatePageData();
1405 ImplUpdateFontList();
1409 bool Printer::SetPaperSizeUser( const Size
& rSize
)
1411 if ( mbInPrintPage
)
1414 const Size aPixSize
= LogicToPixel( rSize
);
1415 const Size aPageSize
= PixelToLogic(aPixSize
, MapMode(MapUnit::Map100thMM
));
1416 bool bNeedToChange(maJobSetup
.ImplGetConstData().GetPaperWidth() != aPageSize
.Width() ||
1417 maJobSetup
.ImplGetConstData().GetPaperHeight() != aPageSize
.Height());
1421 // #i122984# only need to change when Paper is different from PAPER_USER and
1422 // the mapped Paper which will created below in the call to ImplFindPaperFormatForUserSize
1423 // and will replace maJobSetup.ImplGetConstData()->GetPaperFormat(). This leads to
1424 // unnecessary JobSetups, e.g. when printing a multi-page fax, but also with
1426 const Paper aPaper
= ImplGetPaperFormat(aPageSize
.Width(), aPageSize
.Height());
1428 bNeedToChange
= maJobSetup
.ImplGetConstData().GetPaperFormat() != PAPER_USER
&&
1429 maJobSetup
.ImplGetConstData().GetPaperFormat() != aPaper
;
1434 JobSetup aJobSetup
= maJobSetup
;
1435 ImplJobSetup
& rData
= aJobSetup
.ImplGetData();
1436 rData
.SetPaperFormat( PAPER_USER
);
1437 rData
.SetPaperWidth( aPageSize
.Width() );
1438 rData
.SetPaperHeight( aPageSize
.Height() );
1440 if ( IsDisplayPrinter() )
1442 mbNewJobSetup
= true;
1443 maJobSetup
= aJobSetup
;
1448 ImplFindPaperFormatForUserSize( aJobSetup
);
1450 // Changing the paper size can also change the orientation!
1451 if ( mpInfoPrinter
->SetData( JobSetFlags::PAPERSIZE
| JobSetFlags::ORIENTATION
, &rData
))
1453 ImplUpdateJobSetupPaper( aJobSetup
);
1454 mbNewJobSetup
= true;
1455 maJobSetup
= aJobSetup
;
1456 ImplUpdatePageData();
1457 ImplUpdateFontList();
1467 int Printer::GetPaperInfoCount() const
1469 if( ! mpInfoPrinter
)
1471 if( ! mpInfoPrinter
->m_bPapersInit
)
1472 mpInfoPrinter
->InitPaperFormats( &maJobSetup
.ImplGetConstData() );
1473 return mpInfoPrinter
->m_aPaperFormats
.size();
1476 OUString
Printer::GetPaperName( Paper ePaper
)
1478 ImplSVData
* pSVData
= ImplGetSVData();
1479 if( pSVData
->maPaperNames
.empty() )
1481 static const int PaperIndex
[] =
1483 PAPER_A0
, PAPER_A1
, PAPER_A2
, PAPER_A3
, PAPER_A4
, PAPER_A5
, PAPER_B4_ISO
, PAPER_B5_ISO
,
1484 PAPER_LETTER
, PAPER_LEGAL
, PAPER_TABLOID
, PAPER_USER
, PAPER_B6_ISO
, PAPER_ENV_C4
, PAPER_ENV_C5
,
1485 PAPER_ENV_C6
, PAPER_ENV_C65
, PAPER_ENV_DL
, PAPER_SLIDE_DIA
, PAPER_SCREEN_4_3
, PAPER_C
, PAPER_D
,
1486 PAPER_E
, PAPER_EXECUTIVE
, PAPER_FANFOLD_LEGAL_DE
, PAPER_ENV_MONARCH
, PAPER_ENV_PERSONAL
, PAPER_ENV_9
,
1487 PAPER_ENV_10
, PAPER_ENV_11
, PAPER_ENV_12
, PAPER_KAI16
, PAPER_KAI32
, PAPER_KAI32BIG
, PAPER_B4_JIS
,
1488 PAPER_B5_JIS
, PAPER_B6_JIS
, PAPER_LEDGER
, PAPER_STATEMENT
, PAPER_QUARTO
, PAPER_10x14
, PAPER_ENV_14
,
1489 PAPER_ENV_C3
, PAPER_ENV_ITALY
, PAPER_FANFOLD_US
, PAPER_FANFOLD_DE
, PAPER_POSTCARD_JP
, PAPER_9x11
,
1490 PAPER_10x11
, PAPER_15x11
, PAPER_ENV_INVITE
, PAPER_A_PLUS
, PAPER_B_PLUS
, PAPER_LETTER_PLUS
, PAPER_A4_PLUS
,
1491 PAPER_DOUBLEPOSTCARD_JP
, PAPER_A6
, PAPER_12x11
, PAPER_A7
, PAPER_A8
, PAPER_A9
, PAPER_A10
, PAPER_B0_ISO
,
1492 PAPER_B1_ISO
, PAPER_B2_ISO
, PAPER_B3_ISO
, PAPER_B7_ISO
, PAPER_B8_ISO
, PAPER_B9_ISO
, PAPER_B10_ISO
,
1493 PAPER_ENV_C2
, PAPER_ENV_C7
, PAPER_ENV_C8
, PAPER_ARCHA
, PAPER_ARCHB
, PAPER_ARCHC
, PAPER_ARCHD
,
1494 PAPER_ARCHE
, PAPER_SCREEN_16_9
, PAPER_SCREEN_16_10
, PAPER_16K_195x270
, PAPER_16K_197x273
1496 assert(SAL_N_ELEMENTS(PaperIndex
) == SAL_N_ELEMENTS(RID_STR_PAPERNAMES
) && "localized paper name count wrong");
1497 for (size_t i
= 0; i
< SAL_N_ELEMENTS(PaperIndex
); ++i
)
1498 pSVData
->maPaperNames
[PaperIndex
[i
]] = VclResId(RID_STR_PAPERNAMES
[i
]);
1501 std::unordered_map
<int,OUString
>::const_iterator it
= pSVData
->maPaperNames
.find( static_cast<int>(ePaper
) );
1502 return (it
!= pSVData
->maPaperNames
.end()) ? it
->second
: OUString();
1505 const PaperInfo
& Printer::GetPaperInfo( int nPaper
) const
1507 if( ! mpInfoPrinter
)
1508 return ImplGetEmptyPaper();
1509 if( ! mpInfoPrinter
->m_bPapersInit
)
1510 mpInfoPrinter
->InitPaperFormats( &maJobSetup
.ImplGetConstData() );
1511 if( mpInfoPrinter
->m_aPaperFormats
.empty() || nPaper
< 0 || nPaper
>= int(mpInfoPrinter
->m_aPaperFormats
.size()) )
1512 return ImplGetEmptyPaper();
1513 return mpInfoPrinter
->m_aPaperFormats
[nPaper
];
1516 Size
Printer::GetPaperSize( int nPaper
)
1518 PaperInfo aInfo
= GetPaperInfo( nPaper
);
1519 return PixelToLogic( Size( aInfo
.getWidth(), aInfo
.getHeight() ) );
1522 void Printer::SetDuplexMode( DuplexMode eDuplex
)
1524 if ( mbInPrintPage
)
1527 if ( maJobSetup
.ImplGetConstData().GetDuplexMode() == eDuplex
)
1530 JobSetup aJobSetup
= maJobSetup
;
1531 ImplJobSetup
& rData
= aJobSetup
.ImplGetData();
1533 rData
.SetDuplexMode( eDuplex
);
1535 if ( IsDisplayPrinter() )
1537 mbNewJobSetup
= true;
1538 maJobSetup
= aJobSetup
;
1543 if ( mpInfoPrinter
->SetData( JobSetFlags::DUPLEXMODE
, &rData
) )
1545 ImplUpdateJobSetupPaper( aJobSetup
);
1546 mbNewJobSetup
= true;
1547 maJobSetup
= aJobSetup
;
1548 ImplUpdatePageData();
1549 ImplUpdateFontList();
1553 DuplexMode
Printer::GetDuplexMode() const
1555 return maJobSetup
.ImplGetConstData().GetDuplexMode();
1558 Paper
Printer::GetPaper() const
1560 return maJobSetup
.ImplGetConstData().GetPaperFormat();
1563 sal_uInt16
Printer::GetPaperBinCount() const
1565 if ( IsDisplayPrinter() )
1568 return mpInfoPrinter
->GetPaperBinCount( &maJobSetup
.ImplGetConstData() );
1571 OUString
Printer::GetPaperBinName( sal_uInt16 nPaperBin
) const
1573 if ( IsDisplayPrinter() )
1576 if ( nPaperBin
< GetPaperBinCount() )
1577 return mpInfoPrinter
->GetPaperBinName( &maJobSetup
.ImplGetConstData(), nPaperBin
);
1582 void Printer::SetCopyCount( sal_uInt16 nCopy
, bool bCollate
)
1584 mnCopyCount
= nCopy
;
1585 mbCollateCopy
= bCollate
;
1588 ErrCode
Printer::ImplSalPrinterErrorCodeToVCL( SalPrinterError nError
)
1593 case SalPrinterError::NONE
:
1594 nVCLError
= ERRCODE_NONE
;
1596 case SalPrinterError::Abort
:
1597 nVCLError
= PRINTER_ABORT
;
1600 nVCLError
= PRINTER_GENERALERROR
;
1607 void Printer::EndJob()
1609 if ( !IsJobActive() )
1612 SAL_WARN_IF( mbInPrintPage
, "vcl.gdi", "Printer::EndJob() - StartPage() without EndPage() called" );
1614 mbJobActive
= false;
1622 mbDevOutput
= false;
1623 mpPrinter
->EndJob();
1628 void Printer::ImplStartPage()
1630 if ( !IsJobActive() )
1636 SalGraphics
* pGraphics
= mpPrinter
->StartPage( &maJobSetup
.ImplGetData(),
1641 mpJobGraphics
= pGraphics
;
1645 // PrintJob not aborted ???
1646 if ( IsJobActive() )
1647 mbInPrintPage
= true;
1650 void Printer::ImplEndPage()
1652 if ( !IsJobActive() )
1655 mbInPrintPage
= false;
1659 mpPrinter
->EndPage();
1661 mbDevOutput
= false;
1663 mpJobGraphics
= nullptr;
1664 mbNewJobSetup
= false;
1668 void Printer::updatePrinters()
1670 ImplSVData
* pSVData
= ImplGetSVData();
1671 ImplPrnQueueList
* pPrnList
= pSVData
->maGDIData
.mpPrinterQueueList
.get();
1676 std::unique_ptr
<ImplPrnQueueList
> pNewList(new ImplPrnQueueList
);
1677 pSVData
->mpDefInst
->GetPrinterQueueInfo( pNewList
.get() );
1679 bool bChanged
= pPrnList
->m_aQueueInfos
.size() != pNewList
->m_aQueueInfos
.size();
1680 for( decltype(pPrnList
->m_aQueueInfos
)::size_type i
= 0; ! bChanged
&& i
< pPrnList
->m_aQueueInfos
.size(); i
++ )
1682 ImplPrnQueueData
& rInfo
= pPrnList
->m_aQueueInfos
[i
];
1683 ImplPrnQueueData
& rNewInfo
= pNewList
->m_aQueueInfos
[i
];
1684 if( ! rInfo
.mpSalQueueInfo
|| ! rNewInfo
.mpSalQueueInfo
|| // sanity check
1685 rInfo
.mpSalQueueInfo
->maPrinterName
!= rNewInfo
.mpSalQueueInfo
->maPrinterName
)
1693 ImplDeletePrnQueueList();
1694 pSVData
->maGDIData
.mpPrinterQueueList
= std::move(pNewList
);
1696 Application
* pApp
= GetpApp();
1699 DataChangedEvent
aDCEvt( DataChangedEventType::PRINTER
);
1700 Application::ImplCallEventListenersApplicationDataChanged(&aDCEvt
);
1701 Application::NotifyAllWindows( aDCEvt
);
1705 bool Printer::UsePolyPolygonForComplexGradient()
1710 void Printer::ClipAndDrawGradientMetafile ( const Gradient
&rGradient
, const tools::PolyPolygon
&rPolyPoly
)
1712 const tools::Rectangle
aBoundRect( rPolyPoly
.GetBoundRect() );
1714 Push( PushFlags::CLIPREGION
);
1715 IntersectClipRegion(vcl::Region(rPolyPoly
));
1716 DrawGradient( aBoundRect
, rGradient
);
1720 void Printer::SetFontOrientation( LogicalFontInstance
* const pFontEntry
) const
1722 pFontEntry
->mnOrientation
= pFontEntry
->mxFontMetric
->GetOrientation();
1725 vcl::Region
Printer::ClipToDeviceBounds(vcl::Region aRegion
) const
1730 Bitmap
Printer::GetBitmap( const Point
& rSrcPt
, const Size
& rSize
) const
1732 SAL_WARN("vcl.gdi", "GetBitmap(): This should never be called on by a Printer instance");
1734 return OutputDevice::GetBitmap( rSrcPt
, rSize
);
1737 css::awt::DeviceInfo
Printer::GetDeviceInfo() const
1739 Size aDevSz
= GetPaperSizePixel();
1740 css::awt::DeviceInfo aInfo
= GetCommonDeviceInfo(aDevSz
);
1741 Size aOutSz
= GetOutputSizePixel();
1742 Point aOffset
= GetPageOffset();
1743 aInfo
.LeftInset
= aOffset
.X();
1744 aInfo
.TopInset
= aOffset
.Y();
1745 aInfo
.RightInset
= aDevSz
.Width() - aOutSz
.Width() - aOffset
.X();
1746 aInfo
.BottomInset
= aDevSz
.Height() - aOutSz
.Height() - aOffset
.Y();
1747 aInfo
.Capabilities
= 0;
1752 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */