1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <sal/types.h>
21 #include <sal/log.hxx>
22 
23 #include <tools/helpers.hxx>
24 #include <tools/debug.hxx>
25 
26 #include <vcl/QueueInfo.hxx>
27 #include <vcl/event.hxx>
28 #include <vcl/virdev.hxx>
29 #include <vcl/print.hxx>
30 
31 #include <comphelper/processfactory.hxx>
32 
33 #include <salinst.hxx>
34 #include <salvd.hxx>
35 #include <salgdi.hxx>
36 #include <salptype.hxx>
37 #include <salprn.hxx>
38 #include <svdata.hxx>
39 #include <print.hrc>
40 #include <jobset.h>
41 #include <outdev.h>
42 #include <PhysicalFontCollection.hxx>
43 #include <print.h>
44 
45 #include <com/sun/star/beans/XPropertySet.hpp>
46 #include <com/sun/star/configuration/theDefaultProvider.hpp>
47 #include <com/sun/star/container/XNameAccess.hpp>
48 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
49 #include <com/sun/star/uno/Sequence.h>
50 
51 int nImplSysDialog = 0;
52 
53 namespace
54 {
ImplGetPaperFormat(tools::Long nWidth100thMM,tools::Long nHeight100thMM)55     Paper ImplGetPaperFormat( tools::Long nWidth100thMM, tools::Long nHeight100thMM )
56     {
57         PaperInfo aInfo(nWidth100thMM, nHeight100thMM);
58         aInfo.doSloppyFit();
59         return aInfo.getPaper();
60     }
61 
ImplGetEmptyPaper()62     const PaperInfo& ImplGetEmptyPaper()
63     {
64         static PaperInfo aInfo(PAPER_USER);
65         return aInfo;
66     }
67 }
68 
ImplUpdateJobSetupPaper(JobSetup & rJobSetup)69 void ImplUpdateJobSetupPaper( JobSetup& rJobSetup )
70 {
71     const ImplJobSetup& rConstData = rJobSetup.ImplGetConstData();
72 
73     if ( !rConstData.GetPaperWidth() || !rConstData.GetPaperHeight() )
74     {
75         if ( rConstData.GetPaperFormat() != PAPER_USER )
76         {
77             PaperInfo aInfo(rConstData.GetPaperFormat());
78 
79             ImplJobSetup& rData = rJobSetup.ImplGetData();
80             rData.SetPaperWidth( aInfo.getWidth() );
81             rData.SetPaperHeight( aInfo.getHeight() );
82         }
83     }
84     else if ( rConstData.GetPaperFormat() == PAPER_USER )
85     {
86         Paper ePaper = ImplGetPaperFormat( rConstData.GetPaperWidth(), rConstData.GetPaperHeight() );
87         if ( ePaper != PAPER_USER )
88             rJobSetup.ImplGetData().SetPaperFormat(ePaper);
89     }
90 }
91 
92 // PrinterOptions
PrinterOptions()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 )
105 {
106 }
107 
ReadFromConfig(bool i_bFile)108 void PrinterOptions::ReadFromConfig( bool i_bFile )
109 {
110     bool bSuccess = false;
111     // save old state in case something goes wrong
112     PrinterOptions aOldValues( *this );
113 
114     // get the configuration service
115     css::uno::Reference< css::lang::XMultiServiceFactory > xConfigProvider;
116     css::uno::Reference< css::container::XNameAccess > xConfigAccess;
117     try
118     {
119         // get service provider
120         css::uno::Reference< css::uno::XComponentContext > xContext( comphelper::getProcessComponentContext() );
121         // create configuration hierarchical access name
122         try
123         {
124             xConfigProvider = css::configuration::theDefaultProvider::get( xContext );
125 
126             css::beans::PropertyValue aVal;
127             aVal.Name = "nodepath";
128             if( i_bFile )
129                 aVal.Value <<= OUString( "/org.openoffice.Office.Common/Print/Option/File" );
130             else
131                 aVal.Value <<= OUString( "/org.openoffice.Office.Common/Print/Option/Printer" );
132             xConfigAccess.set(
133                     xConfigProvider->createInstanceWithArguments(
134                         "com.sun.star.configuration.ConfigurationAccess", { css::uno::Any(aVal) } ),
135                         css::uno::UNO_QUERY );
136             if( xConfigAccess.is() )
137             {
138                 css::uno::Reference< css::beans::XPropertySet > xSet( xConfigAccess, css::uno::UNO_QUERY );
139                 if( xSet.is() )
140                 {
141                     sal_Int32 nValue = 0;
142                     bool  bValue = false;
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 );
165 
166                     bSuccess = true;
167                 }
168             }
169         }
170         catch( const css::uno::Exception& )
171         {
172         }
173     }
174     catch( const css::lang::WrappedTargetException& )
175     {
176     }
177 
178     if( ! bSuccess )
179         *this = aOldValues;
180 }
181 
ImplPrintTransparent(const Bitmap & rBmp,const Bitmap & rMask,const Point & rDestPt,const Size & rDestSize,const Point & rSrcPtPixel,const Size & rSrcSizePixel)182 void Printer::ImplPrintTransparent( const Bitmap& rBmp, const Bitmap& rMask,
183                                          const Point& rDestPt, const Size& rDestSize,
184                                          const Point& rSrcPtPixel, const Size& rSrcSizePixel )
185 {
186     Point       aDestPt( LogicToPixel( rDestPt ) );
187     Size        aDestSz( LogicToPixel( rDestSize ) );
188     tools::Rectangle   aSrcRect( rSrcPtPixel, rSrcSizePixel );
189 
190     aSrcRect.Justify();
191 
192     if( rBmp.IsEmpty() || !aSrcRect.GetWidth() || !aSrcRect.GetHeight() || !aDestSz.Width() || !aDestSz.Height() )
193         return;
194 
195     Bitmap  aPaint( rBmp ), aMask( rMask );
196     BmpMirrorFlags nMirrFlags = BmpMirrorFlags::NONE;
197 
198     if (aMask.getPixelFormat() > vcl::PixelFormat::N1_BPP)
199         aMask.Convert( BmpConversion::N1BitThreshold );
200 
201     // mirrored horizontally
202     if( aDestSz.Width() < 0 )
203     {
204         aDestSz.setWidth( -aDestSz.Width() );
205         aDestPt.AdjustX( -( aDestSz.Width() - 1 ) );
206         nMirrFlags |= BmpMirrorFlags::Horizontal;
207     }
208 
209     // mirrored vertically
210     if( aDestSz.Height() < 0 )
211     {
212         aDestSz.setHeight( -aDestSz.Height() );
213         aDestPt.AdjustY( -( aDestSz.Height() - 1 ) );
214         nMirrFlags |= BmpMirrorFlags::Vertical;
215     }
216 
217     // source cropped?
218     if( aSrcRect != tools::Rectangle( Point(), aPaint.GetSizePixel() ) )
219     {
220         aPaint.Crop( aSrcRect );
221         aMask.Crop( aSrcRect );
222     }
223 
224     // destination mirrored
225     if( nMirrFlags != BmpMirrorFlags::NONE )
226     {
227         aPaint.Mirror( nMirrFlags );
228         aMask.Mirror( nMirrFlags );
229     }
230 
231     // we always want to have a mask
232     if( aMask.IsEmpty() )
233     {
234         aMask = Bitmap(aSrcRect.GetSize(), vcl::PixelFormat::N1_BPP);
235         aMask.Erase( COL_BLACK );
236     }
237 
238     // do painting
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;
244 
245     mbMap = false;
246 
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 );
250 
251     for( nY = 0; nY <= nSrcHeight; nY++ )
252         pMapY[ nY ] = aDestPt.Y() + FRound( static_cast<double>(aDestSz.Height()) * nY / nSrcHeight );
253 
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);
258 
259     for (auto const& rectangle : aRectangles)
260     {
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);
265 
266         aBandBmp.Crop(rectangle);
267         DrawBitmap(aMapPt, aMapSz, Point(), aBandBmp.GetSizePixel(), aBandBmp);
268     }
269 
270     mbMap = bOldMap;
271 
272 }
273 
DrawTransformBitmapExDirect(const basegfx::B2DHomMatrix &,const BitmapEx &,double)274 bool Printer::DrawTransformBitmapExDirect(
275     const basegfx::B2DHomMatrix& /*aFullTransform*/,
276     const BitmapEx& /*rBitmapEx*/,
277     double /*fAlpha*/)
278 {
279     // printers can't draw bitmaps directly
280     return false;
281 }
282 
TransformAndReduceBitmapExToTargetRange(const basegfx::B2DHomMatrix &,basegfx::B2DRange &,double &)283 bool Printer::TransformAndReduceBitmapExToTargetRange(
284     const basegfx::B2DHomMatrix& /*aFullTransform*/,
285     basegfx::B2DRange& /*aVisibleRange*/,
286     double& /*fMaximumArea*/)
287 {
288     // deliberately do nothing - you can't reduce the
289     // target range for a printer at all
290     return true;
291 }
292 
DrawDeviceBitmap(const Point & rDestPt,const Size & rDestSize,const Point & rSrcPtPixel,const Size & rSrcSizePixel,BitmapEx & rBmpEx)293 void Printer::DrawDeviceBitmap( const Point& rDestPt, const Size& rDestSize,
294                                 const Point& rSrcPtPixel, const Size& rSrcSizePixel,
295                                 BitmapEx& rBmpEx )
296 {
297     if( rBmpEx.IsAlpha() )
298     {
299         // #107169# For true alpha bitmaps, no longer masking the
300         // bitmap, but perform a full alpha blend against a white
301         // background here.
302         Bitmap aBmp( rBmpEx.GetBitmap() );
303         aBmp.Blend( rBmpEx.GetAlpha(), COL_WHITE );
304         DrawBitmap( rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel, aBmp );
305     }
306     else
307     {
308         Bitmap aBmp( rBmpEx.GetBitmap() );
309         ImplPrintTransparent( aBmp, Bitmap(), rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel );
310     }
311 }
312 
EmulateDrawTransparent(const tools::PolyPolygon & rPolyPoly,sal_uInt16 nTransparencePercent)313 void Printer::EmulateDrawTransparent ( const tools::PolyPolygon& rPolyPoly,
314                                        sal_uInt16 nTransparencePercent )
315 {
316     // #110958# Disable alpha VDev, we perform the necessary
317     VirtualDevice* pOldAlphaVDev = mpAlphaVDev;
318 
319     // operation explicitly further below.
320     if( mpAlphaVDev )
321         mpAlphaVDev = nullptr;
322 
323     GDIMetaFile* pOldMetaFile = mpMetaFile;
324     mpMetaFile = nullptr;
325 
326     mpMetaFile = pOldMetaFile;
327 
328     // #110958# Restore disabled alpha VDev
329     mpAlphaVDev = pOldAlphaVDev;
330 
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 );
334     tools::Long            nMove;
335     const sal_uInt16    nTrans = ( nTransparencePercent < 13 ) ? 0 :
336         ( nTransparencePercent < 38 ) ? 25 :
337         ( nTransparencePercent < 63 ) ? 50 :
338         ( nTransparencePercent < 88 ) ? 75 : 100;
339 
340     switch( nTrans )
341     {
342         case 25: nMove = nBaseExtent * 3; break;
343         case 50: nMove = nBaseExtent * 4; break;
344         case 75: nMove = nBaseExtent * 6; break;
345 
346             // #i112959#  very transparent (88 < nTransparencePercent <= 99)
347         case 100: nMove = nBaseExtent * 8; break;
348 
349             // #i112959# not transparent (nTransparencePercent < 13)
350         default:    nMove = 0; break;
351     }
352 
353     Push( PushFlags::CLIPREGION | PushFlags::LINECOLOR );
354     IntersectClipRegion(vcl::Region(rPolyPoly));
355     SetLineColor( GetFillColor() );
356     const bool bOldMap = mbMap;
357     EnableMapMode( false );
358 
359     if(nMove)
360     {
361         tools::Rectangle aRect( aPolyRect.TopLeft(), Size( aPolyRect.GetWidth(), nBaseExtent ) );
362         while( aRect.Top() <= aPolyRect.Bottom() )
363         {
364             DrawRect( aRect );
365             aRect.Move( 0, nMove );
366         }
367 
368         aRect = tools::Rectangle( aPolyRect.TopLeft(), Size( nBaseExtent, aPolyRect.GetHeight() ) );
369         while( aRect.Left() <= aPolyRect.Right() )
370         {
371             DrawRect( aRect );
372             aRect.Move( nMove, 0 );
373         }
374     }
375     else
376     {
377         // #i112959# if not transparent, draw full rectangle in clip region
378         DrawRect( aPolyRect );
379     }
380 
381     EnableMapMode( bOldMap );
382     Pop();
383 
384     mpMetaFile = pOldMetaFile;
385 
386     // #110958# Restore disabled alpha VDev
387     mpAlphaVDev = pOldAlphaVDev;
388 }
389 
DrawOutDev(const Point &,const Size &,const Point &,const Size &)390 void Printer::DrawOutDev( const Point& /*rDestPt*/, const Size& /*rDestSize*/,
391                                const Point& /*rSrcPt*/,  const Size& /*rSrcSize*/ )
392 {
393     SAL_WARN( "vcl.gdi", "Don't use OutputDevice::DrawOutDev(...) with printer devices!" );
394 }
395 
DrawOutDev(const Point &,const Size &,const Point &,const Size &,const OutputDevice &)396 void Printer::DrawOutDev( const Point& /*rDestPt*/, const Size& /*rDestSize*/,
397                                const Point& /*rSrcPt*/,  const Size& /*rSrcSize*/,
398                                const OutputDevice& /*rOutDev*/ )
399 {
400     SAL_WARN( "vcl.gdi", "Don't use OutputDevice::DrawOutDev(...) with printer devices!" );
401 }
402 
CopyArea(const Point &,const Point &,const Size &,bool)403 void Printer::CopyArea( const Point& /*rDestPt*/,
404                         const Point& /*rSrcPt*/,  const Size& /*rSrcSize*/,
405                         bool /*bWindowInvalidate*/ )
406 {
407     SAL_WARN( "vcl.gdi", "Don't use OutputDevice::CopyArea(...) with printer devices!" );
408 }
409 
GetBackgroundComponentBounds() const410 tools::Rectangle Printer::GetBackgroundComponentBounds() const
411 {
412     Point aPageOffset = Point( 0, 0 ) - this->GetPageOffsetPixel();
413     Size aSize  = this->GetPaperSizePixel();
414     return tools::Rectangle( aPageOffset, aSize );
415 }
416 
SetPrinterOptions(const PrinterOptions & i_rOptions)417 void Printer::SetPrinterOptions( const PrinterOptions& i_rOptions )
418 {
419     *mpPrinterOptions = i_rOptions;
420 }
421 
HasMirroredGraphics() const422 bool Printer::HasMirroredGraphics() const
423 {
424     // due to a "hotfix" for AOO bug i55719, this needs to return false
425     return false;
426 }
427 
SalPrinterQueueInfo()428 SalPrinterQueueInfo::SalPrinterQueueInfo()
429 {
430     mnStatus    = PrintQueueFlags::NONE;
431     mnJobs      = QUEUE_JOBS_DONTKNOW;
432 }
433 
~SalPrinterQueueInfo()434 SalPrinterQueueInfo::~SalPrinterQueueInfo()
435 {
436 }
437 
~ImplPrnQueueList()438 ImplPrnQueueList::~ImplPrnQueueList()
439 {
440 }
441 
Add(std::unique_ptr<SalPrinterQueueInfo> pData)442 void ImplPrnQueueList::Add( std::unique_ptr<SalPrinterQueueInfo> pData )
443 {
444     std::unordered_map< OUString, sal_Int32 >::iterator it =
445         m_aNameToIndex.find( pData->maPrinterName );
446     if( it == m_aNameToIndex.end() )
447     {
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);
453     }
454     else // this should not happen, but ...
455     {
456         ImplPrnQueueData& rData = m_aQueueInfos[ it->second ];
457         rData.mpQueueInfo.reset();
458         rData.mpSalQueueInfo = std::move(pData);
459     }
460 }
461 
Get(const OUString & rPrinter)462 ImplPrnQueueData* ImplPrnQueueList::Get( const OUString& rPrinter )
463 {
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];
469     return pData;
470 }
471 
ImplInitPrnQueueList()472 static void ImplInitPrnQueueList()
473 {
474     ImplSVData* pSVData = ImplGetSVData();
475 
476     pSVData->maGDIData.mpPrinterQueueList.reset(new ImplPrnQueueList);
477 
478     static const char* pEnv = getenv( "SAL_DISABLE_PRINTERLIST" );
479     if( !pEnv || !*pEnv )
480         pSVData->mpDefInst->GetPrinterQueueInfo( pSVData->maGDIData.mpPrinterQueueList.get() );
481 }
482 
ImplDeletePrnQueueList()483 void ImplDeletePrnQueueList()
484 {
485     ImplSVData*         pSVData = ImplGetSVData();
486     pSVData->maGDIData.mpPrinterQueueList.reset();
487 }
488 
GetPrinterQueues()489 const std::vector<OUString>& Printer::GetPrinterQueues()
490 {
491     ImplSVData* pSVData = ImplGetSVData();
492     if ( !pSVData->maGDIData.mpPrinterQueueList )
493         ImplInitPrnQueueList();
494     return pSVData->maGDIData.mpPrinterQueueList->m_aPrinterList;
495 }
496 
GetQueueInfo(const OUString & rPrinterName,bool bStatusUpdate)497 const QueueInfo* Printer::GetQueueInfo( const OUString& rPrinterName, bool bStatusUpdate )
498 {
499     ImplSVData* pSVData = ImplGetSVData();
500 
501     if ( !pSVData->maGDIData.mpPrinterQueueList )
502         ImplInitPrnQueueList();
503 
504     if ( !pSVData->maGDIData.mpPrinterQueueList )
505         return nullptr;
506 
507     ImplPrnQueueData* pInfo = pSVData->maGDIData.mpPrinterQueueList->Get( rPrinterName );
508     if( pInfo )
509     {
510         if( !pInfo->mpQueueInfo || bStatusUpdate )
511             pSVData->mpDefInst->GetPrinterQueueState( pInfo->mpSalQueueInfo.get() );
512 
513         if ( !pInfo->mpQueueInfo )
514             pInfo->mpQueueInfo.reset(new QueueInfo);
515 
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();
523     }
524     return nullptr;
525 }
526 
GetDefaultPrinterName()527 OUString Printer::GetDefaultPrinterName()
528 {
529     static const char* pEnv = getenv( "SAL_DISABLE_DEFAULTPRINTER" );
530     if( !pEnv || !*pEnv )
531     {
532         ImplSVData* pSVData = ImplGetSVData();
533 
534         return pSVData->mpDefInst->GetDefaultPrinter();
535     }
536     return OUString();
537 }
538 
ImplInitData()539 void Printer::ImplInitData()
540 {
541     mbDevOutput         = false;
542     mbDefPrinter        = false;
543     mnError             = ERRCODE_NONE;
544     mnPageQueueSize     = 0;
545     mnCopyCount         = 1;
546     mbCollateCopy       = false;
547     mbPrinting          = false;
548     mbJobActive         = false;
549     mbPrintFile         = false;
550     mbInPrintPage       = false;
551     mbNewJobSetup       = false;
552     mbSinglePrintJobs   = false;
553     mpInfoPrinter       = nullptr;
554     mpPrinter           = nullptr;
555     mpDisplayDev        = nullptr;
556     mpPrinterOptions.reset(new PrinterOptions);
557 
558     // Add printer to the list
559     ImplSVData* pSVData = ImplGetSVData();
560     mpNext = pSVData->maGDIData.mpFirstPrinter;
561     mpPrev = nullptr;
562     if ( mpNext )
563         mpNext->mpPrev = this;
564     pSVData->maGDIData.mpFirstPrinter = this;
565 }
566 
AcquireGraphics() const567 bool Printer::AcquireGraphics() const
568 {
569     DBG_TESTSOLARMUTEX();
570 
571     if ( mpGraphics )
572         return true;
573 
574     mbInitLineColor     = true;
575     mbInitFillColor     = true;
576     mbInitFont          = true;
577     mbInitTextColor     = true;
578     mbInitClipRegion    = true;
579 
580     ImplSVData* pSVData = ImplGetSVData();
581 
582     if ( mpJobGraphics )
583         mpGraphics = mpJobGraphics;
584     else if ( mpDisplayDev )
585     {
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 )
590         {
591             if ( !pSVData->maGDIData.mpLastVirGraphics )
592                 break;
593             pSVData->maGDIData.mpLastVirGraphics->ReleaseGraphics();
594             mpGraphics = pVirDev->mpVirDev->AcquireGraphics();
595         }
596         // update global LRU list of virtual device graphics
597         if ( mpGraphics )
598         {
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);
605         }
606     }
607     else
608     {
609         mpGraphics = mpInfoPrinter->AcquireGraphics();
610         // if needed retry after releasing least recently used printer graphics
611         while ( !mpGraphics )
612         {
613             if ( !pSVData->maGDIData.mpLastPrnGraphics )
614                 break;
615             pSVData->maGDIData.mpLastPrnGraphics->ReleaseGraphics();
616             mpGraphics = mpInfoPrinter->AcquireGraphics();
617         }
618         // update global LRU list of printer graphics
619         if ( mpGraphics )
620         {
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);
627         }
628     }
629 
630     if ( mpGraphics )
631     {
632         mpGraphics->SetXORMode( (RasterOp::Invert == meRasterOp) || (RasterOp::Xor == meRasterOp), RasterOp::Invert == meRasterOp );
633         mpGraphics->setAntiAlias(bool(mnAntialiasing & AntialiasingFlags::Enable));
634     }
635 
636     return mpGraphics != nullptr;
637 }
638 
ImplReleaseFonts()639 void Printer::ImplReleaseFonts()
640 {
641 #ifdef UNX
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();
647 #endif
648     mbNewFont = true;
649     mbInitFont = true;
650 
651     mpFontInstance.clear();
652     mpDeviceFontList.reset();
653     mpDeviceFontSizeList.reset();
654 }
655 
ReleaseGraphics(bool bRelease)656 void Printer::ReleaseGraphics( bool bRelease )
657 {
658     DBG_TESTSOLARMUTEX();
659 
660     if ( !mpGraphics )
661         return;
662 
663     // release the fonts of the physically released graphics device
664     if( bRelease )
665         ImplReleaseFonts();
666 
667     ImplSVData* pSVData = ImplGetSVData();
668 
669     Printer* pPrinter = this;
670 
671     if ( !pPrinter->mpJobGraphics )
672     {
673         if ( pPrinter->mpDisplayDev )
674         {
675             VirtualDevice* pVirDev = pPrinter->mpDisplayDev;
676             if ( bRelease )
677                 pVirDev->mpVirDev->ReleaseGraphics( mpGraphics );
678             // remove from global LRU list of virtual device graphics
679             if ( mpPrevGraphics )
680                 mpPrevGraphics->mpNextGraphics = mpNextGraphics;
681             else
682                 pSVData->maGDIData.mpFirstVirGraphics = mpNextGraphics;
683             if ( mpNextGraphics )
684                 mpNextGraphics->mpPrevGraphics = mpPrevGraphics;
685             else
686                 pSVData->maGDIData.mpLastVirGraphics = mpPrevGraphics;
687         }
688         else
689         {
690             if ( bRelease )
691                 pPrinter->mpInfoPrinter->ReleaseGraphics( mpGraphics );
692             // remove from global LRU list of printer graphics
693             if ( mpPrevGraphics )
694                 mpPrevGraphics->mpNextGraphics = mpNextGraphics;
695             else
696                 pSVData->maGDIData.mpFirstPrnGraphics = static_cast<Printer*>(mpNextGraphics.get());
697             if ( mpNextGraphics )
698                 mpNextGraphics->mpPrevGraphics = mpPrevGraphics;
699             else
700                 pSVData->maGDIData.mpLastPrnGraphics = static_cast<Printer*>(mpPrevGraphics.get());
701         }
702     }
703 
704     mpGraphics      = nullptr;
705     mpPrevGraphics  = nullptr;
706     mpNextGraphics  = nullptr;
707 }
708 
ImplInit(SalPrinterQueueInfo * pInfo)709 void Printer::ImplInit( SalPrinterQueueInfo* pInfo )
710 {
711     ImplSVData* pSVData = ImplGetSVData();
712     // #i74084# update info for this specific SalPrinterQueueInfo
713     pSVData->mpDefInst->GetPrinterQueueState( pInfo );
714 
715     // Test whether the driver actually matches the JobSetup
716     ImplJobSetup& rData = maJobSetup.ImplGetData();
717     if ( rData.GetDriverData() )
718     {
719         if ( rData.GetPrinterName() != pInfo->maPrinterName ||
720              rData.GetDriver() != pInfo->maDriver )
721         {
722             std::free( const_cast<sal_uInt8*>(rData.GetDriverData()) );
723             rData.SetDriverData(nullptr);
724             rData.SetDriverDataLen(0);
725         }
726     }
727 
728     // Remember printer name
729     maPrinterName = pInfo->maPrinterName;
730     maDriver = pInfo->maDriver;
731 
732     // Add printer name to JobSetup
733     rData.SetPrinterName( maPrinterName );
734     rData.SetDriver( maDriver );
735 
736     mpInfoPrinter   = pSVData->mpDefInst->CreateInfoPrinter( pInfo, &rData );
737     mpPrinter       = nullptr;
738     mpJobGraphics   = nullptr;
739     ImplUpdateJobSetupPaper( maJobSetup );
740 
741     if ( !mpInfoPrinter )
742     {
743         ImplInitDisplay();
744         return;
745     }
746 
747     // we need a graphics
748     if ( !AcquireGraphics() )
749     {
750         ImplInitDisplay();
751         return;
752     }
753 
754     // Init data
755     ImplUpdatePageData();
756     mxFontCollection = std::make_shared<PhysicalFontCollection>();
757     mxFontCache = std::make_shared<ImplFontCache>();
758     mpGraphics->GetDevFontList(mxFontCollection.get());
759 }
760 
ImplInitDisplay()761 void Printer::ImplInitDisplay()
762 {
763     ImplSVData* pSVData = ImplGetSVData();
764 
765     mpInfoPrinter       = nullptr;
766     mpPrinter           = nullptr;
767     mpJobGraphics       = nullptr;
768 
769     mpDisplayDev = VclPtr<VirtualDevice>::Create();
770     mxFontCollection    = pSVData->maGDIData.mxScreenFontList;
771     mxFontCache         = pSVData->maGDIData.mxScreenFontCache;
772     mnDPIX              = mpDisplayDev->mnDPIX;
773     mnDPIY              = mpDisplayDev->mnDPIY;
774 }
775 
DrawDeviceMask(const Bitmap & rMask,const Color & rMaskColor,const Point & rDestPt,const Size & rDestSize,const Point & rSrcPtPixel,const Size & rSrcSizePixel)776 void Printer::DrawDeviceMask( const Bitmap& rMask, const Color& rMaskColor,
777                          const Point& rDestPt, const Size& rDestSize,
778                          const Point& rSrcPtPixel, const Size& rSrcSizePixel )
779 {
780     Point       aDestPt( LogicToPixel( rDestPt ) );
781     Size        aDestSz( LogicToPixel( rDestSize ) );
782     tools::Rectangle   aSrcRect( rSrcPtPixel, rSrcSizePixel );
783 
784     aSrcRect.Justify();
785 
786     if( !(!rMask.IsEmpty() && aSrcRect.GetWidth() && aSrcRect.GetHeight() && aDestSz.Width() && aDestSz.Height()) )
787         return;
788 
789     Bitmap  aMask( rMask );
790     BmpMirrorFlags nMirrFlags = BmpMirrorFlags::NONE;
791 
792     if (aMask.getPixelFormat() > vcl::PixelFormat::N1_BPP)
793         aMask.Convert( BmpConversion::N1BitThreshold );
794 
795     // mirrored horizontally
796     if( aDestSz.Width() < 0 )
797     {
798         aDestSz.setWidth( -aDestSz.Width() );
799         aDestPt.AdjustX( -( aDestSz.Width() - 1 ) );
800         nMirrFlags |= BmpMirrorFlags::Horizontal;
801     }
802 
803     // mirrored vertically
804     if( aDestSz.Height() < 0 )
805     {
806         aDestSz.setHeight( -aDestSz.Height() );
807         aDestPt.AdjustY( -( aDestSz.Height() - 1 ) );
808         nMirrFlags |= BmpMirrorFlags::Vertical;
809     }
810 
811     // source cropped?
812     if( aSrcRect != tools::Rectangle( Point(), aMask.GetSizePixel() ) )
813         aMask.Crop( aSrcRect );
814 
815     // destination mirrored
816     if( nMirrFlags != BmpMirrorFlags::NONE)
817         aMask.Mirror( nMirrFlags );
818 
819     // do painting
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;
826 
827     mpMetaFile = nullptr;
828     mbMap = false;
829     Push( PushFlags::FILLCOLOR | PushFlags::LINECOLOR );
830     SetLineColor( rMaskColor );
831     SetFillColor( rMaskColor );
832     InitLineColor();
833     InitFillColor();
834 
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 );
838 
839     for( nY = 0; nY <= nSrcHeight; nY++ )
840         pMapY[ nY ] = aDestPt.Y() + FRound( static_cast<double>(aDestSz.Height()) * nY / nSrcHeight );
841 
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);
846 
847     for (auto const& rectangle : aRectangles)
848     {
849         const Point aMapPt(pMapX[rectangle.Left()], pMapY[rectangle.Top()]);
850         const Size aMapSz(
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
853 
854         DrawRect(tools::Rectangle(aMapPt, aMapSz));
855     }
856 
857     Pop();
858     mbMap = bOldMap;
859     mpMetaFile = pOldMetaFile;
860 }
861 
ImplGetQueueInfo(const OUString & rPrinterName,const OUString * pDriver)862 SalPrinterQueueInfo* Printer::ImplGetQueueInfo( const OUString& rPrinterName,
863                                                 const OUString* pDriver )
864 {
865     ImplSVData* pSVData = ImplGetSVData();
866     if ( !pSVData->maGDIData.mpPrinterQueueList )
867         ImplInitPrnQueueList();
868 
869     ImplPrnQueueList* pPrnList = pSVData->maGDIData.mpPrinterQueueList.get();
870     if ( pPrnList && !pPrnList->m_aQueueInfos.empty() )
871     {
872         // first search for the printer name directly
873         ImplPrnQueueData* pInfo = pPrnList->Get( rPrinterName );
874         if( pInfo )
875             return pInfo->mpSalQueueInfo.get();
876 
877         // then search case insensitive
878         for(const ImplPrnQueueData & rQueueInfo : pPrnList->m_aQueueInfos)
879         {
880             if( rQueueInfo.mpSalQueueInfo->maPrinterName.equalsIgnoreAsciiCase( rPrinterName ) )
881                 return rQueueInfo.mpSalQueueInfo.get();
882         }
883 
884         // then search for driver name
885         if ( pDriver )
886         {
887             for(const ImplPrnQueueData & rQueueInfo : pPrnList->m_aQueueInfos)
888             {
889                 if( rQueueInfo.mpSalQueueInfo->maDriver == *pDriver )
890                     return rQueueInfo.mpSalQueueInfo.get();
891             }
892         }
893 
894         // then the default printer
895         pInfo = pPrnList->Get( GetDefaultPrinterName() );
896         if( pInfo )
897             return pInfo->mpSalQueueInfo.get();
898 
899         // last chance: the first available printer
900         return pPrnList->m_aQueueInfos[0].mpSalQueueInfo.get();
901     }
902 
903     return nullptr;
904 }
905 
ImplUpdatePageData()906 void Printer::ImplUpdatePageData()
907 {
908     // we need a graphics
909     if ( !AcquireGraphics() )
910         return;
911 
912     mpGraphics->GetResolution( mnDPIX, mnDPIY );
913     mpInfoPrinter->GetPageInfo( &maJobSetup.ImplGetConstData(),
914                                 mnOutWidth, mnOutHeight,
915                                 maPageOffset,
916                                 maPaperSize );
917 }
918 
ImplUpdateFontList()919 void Printer::ImplUpdateFontList()
920 {
921     ImplUpdateFontData();
922 }
923 
GetGradientStepCount(tools::Long nMinRect)924 tools::Long Printer::GetGradientStepCount( tools::Long nMinRect )
925 {
926     // use display-equivalent step size calculation
927     tools::Long nInc = (nMinRect < 800) ? 10 : 20;
928 
929     return nInc;
930 }
931 
Printer()932 Printer::Printer()
933     : OutputDevice(OUTDEV_PRINTER)
934 {
935     ImplInitData();
936     SalPrinterQueueInfo* pInfo = ImplGetQueueInfo( GetDefaultPrinterName(), nullptr );
937     if ( pInfo )
938     {
939         ImplInit( pInfo );
940         if ( !IsDisplayPrinter() )
941             mbDefPrinter = true;
942     }
943     else
944         ImplInitDisplay();
945 }
946 
Printer(const JobSetup & rJobSetup)947 Printer::Printer( const JobSetup& rJobSetup )
948     : OutputDevice(OUTDEV_PRINTER)
949     , maJobSetup(rJobSetup)
950 {
951     ImplInitData();
952     const ImplJobSetup& rConstData = rJobSetup.ImplGetConstData();
953     OUString aDriver = rConstData.GetDriver();
954     SalPrinterQueueInfo* pInfo = ImplGetQueueInfo( rConstData.GetPrinterName(),
955                                                    &aDriver );
956     if ( pInfo )
957     {
958         ImplInit( pInfo );
959         SetJobSetup( rJobSetup );
960     }
961     else
962     {
963         ImplInitDisplay();
964         maJobSetup = JobSetup();
965     }
966 }
967 
Printer(const QueueInfo & rQueueInfo)968 Printer::Printer( const QueueInfo& rQueueInfo )
969     : OutputDevice(OUTDEV_PRINTER)
970 {
971     ImplInitData();
972     SalPrinterQueueInfo* pInfo = ImplGetQueueInfo( rQueueInfo.GetPrinterName(),
973                                                    &rQueueInfo.GetDriver() );
974     if ( pInfo )
975         ImplInit( pInfo );
976     else
977         ImplInitDisplay();
978 }
979 
Printer(const OUString & rPrinterName)980 Printer::Printer( const OUString& rPrinterName )
981     : OutputDevice(OUTDEV_PRINTER)
982 {
983     ImplInitData();
984     SalPrinterQueueInfo* pInfo = ImplGetQueueInfo( rPrinterName, nullptr );
985     if ( pInfo )
986         ImplInit( pInfo );
987     else
988         ImplInitDisplay();
989 }
990 
~Printer()991 Printer::~Printer()
992 {
993     disposeOnce();
994 }
995 
dispose()996 void Printer::dispose()
997 {
998     SAL_WARN_IF( IsPrinting(), "vcl.gdi", "Printer::~Printer() - Job is printing" );
999     SAL_WARN_IF( IsJobActive(), "vcl.gdi", "Printer::~Printer() - Job is active" );
1000 
1001     mpPrinterOptions.reset();
1002 
1003     ReleaseGraphics();
1004     if ( mpInfoPrinter )
1005         ImplGetSVData()->mpDefInst->DestroyInfoPrinter( mpInfoPrinter );
1006     if ( mpDisplayDev )
1007         mpDisplayDev.disposeAndClear();
1008     else
1009     {
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
1018     }
1019 
1020     // Add printer from the list
1021     ImplSVData* pSVData = ImplGetSVData();
1022     if ( mpPrev )
1023         mpPrev->mpNext = mpNext;
1024     else
1025         pSVData->maGDIData.mpFirstPrinter = mpNext;
1026     if ( mpNext )
1027         mpNext->mpPrev = mpPrev;
1028 
1029     mpPrev.clear();
1030     mpNext.clear();
1031     OutputDevice::dispose();
1032 }
1033 
GetButtonBorderSize()1034 Size Printer::GetButtonBorderSize()
1035 {
1036     Size aBrdSize(LogicToPixel(Size(20, 20), MapMode(MapUnit::Map100thMM)));
1037 
1038     if (!aBrdSize.Width())
1039         aBrdSize.setWidth(1);
1040 
1041     if (!aBrdSize.Height())
1042         aBrdSize.setHeight(1);
1043 
1044     return aBrdSize;
1045 }
1046 
GetCapabilities(PrinterCapType nType) const1047 sal_uInt32 Printer::GetCapabilities( PrinterCapType nType ) const
1048 {
1049     if ( IsDisplayPrinter() )
1050         return 0;
1051 
1052     if( mpInfoPrinter )
1053         return mpInfoPrinter->GetCapabilities( &maJobSetup.ImplGetConstData(), nType );
1054     else
1055         return 0;
1056 }
1057 
HasSupport(PrinterSupport eFeature) const1058 bool Printer::HasSupport( PrinterSupport eFeature ) const
1059 {
1060     switch ( eFeature )
1061     {
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;
1072     }
1073 
1074     return true;
1075 }
1076 
SetJobSetup(const JobSetup & rSetup)1077 bool Printer::SetJobSetup( const JobSetup& rSetup )
1078 {
1079     if ( IsDisplayPrinter() || mbInPrintPage )
1080         return false;
1081 
1082     JobSetup aJobSetup = rSetup;
1083 
1084     ReleaseGraphics();
1085     if ( mpInfoPrinter->SetPrinterData( &aJobSetup.ImplGetData() ) )
1086     {
1087         ImplUpdateJobSetupPaper( aJobSetup );
1088         mbNewJobSetup = true;
1089         maJobSetup = aJobSetup;
1090         ImplUpdatePageData();
1091         ImplUpdateFontList();
1092         return true;
1093     }
1094 
1095     return false;
1096 }
1097 
Setup(weld::Window * pWindow,PrinterSetupMode eMode)1098 bool Printer::Setup(weld::Window* pWindow, PrinterSetupMode eMode)
1099 {
1100     if ( IsDisplayPrinter() )
1101         return false;
1102 
1103     if ( IsJobActive() || IsPrinting() )
1104         return false;
1105 
1106     JobSetup aJobSetup = maJobSetup;
1107     ImplJobSetup& rData = aJobSetup.ImplGetData();
1108     rData.SetPrinterSetupMode( eMode );
1109     // TODO: orig page size
1110 
1111     if (!pWindow)
1112     {
1113         vcl::Window* pDefWin = ImplGetDefaultWindow();
1114         pWindow = pDefWin ? pDefWin->GetFrameWeld() : nullptr;
1115     }
1116     if( !pWindow )
1117         return false;
1118 
1119     ReleaseGraphics();
1120     ImplSVData* pSVData = ImplGetSVData();
1121     pSVData->maAppData.mnModalMode++;
1122     nImplSysDialog++;
1123     bool bSetup = mpInfoPrinter->Setup(pWindow, &rData);
1124     pSVData->maAppData.mnModalMode--;
1125     nImplSysDialog--;
1126     if ( bSetup )
1127     {
1128         ImplUpdateJobSetupPaper( aJobSetup );
1129         mbNewJobSetup = true;
1130         maJobSetup = aJobSetup;
1131         ImplUpdatePageData();
1132         ImplUpdateFontList();
1133         return true;
1134     }
1135     return false;
1136 }
1137 
SetPrinterProps(const Printer * pPrinter)1138 bool Printer::SetPrinterProps( const Printer* pPrinter )
1139 {
1140     if ( IsJobActive() || IsPrinting() )
1141         return false;
1142 
1143     ImplSVData* pSVData = ImplGetSVData();
1144 
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;
1152 
1153     if ( pPrinter->IsDisplayPrinter() )
1154     {
1155         // Destroy old printer
1156         if ( !IsDisplayPrinter() )
1157         {
1158             ReleaseGraphics();
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();
1166 
1167             mbInitFont = true;
1168             mbNewFont = true;
1169             mpInfoPrinter = nullptr;
1170         }
1171 
1172         // Construct new printer
1173         ImplInitDisplay();
1174         return true;
1175     }
1176 
1177     // Destroy old printer?
1178     if ( GetName() != pPrinter->GetName() )
1179     {
1180         ReleaseGraphics();
1181         if ( mpDisplayDev )
1182         {
1183             mpDisplayDev.disposeAndClear();
1184         }
1185         else
1186         {
1187             pSVData->mpDefInst->DestroyInfoPrinter( mpInfoPrinter );
1188 
1189             mpFontInstance.clear();
1190             mpDeviceFontList.reset();
1191             mpDeviceFontSizeList.reset();
1192             mxFontCache.reset();
1193             mxFontCollection.reset();
1194             mbInitFont = true;
1195             mbNewFont = true;
1196             mpInfoPrinter = nullptr;
1197         }
1198 
1199         // Construct new printer
1200         OUString aDriver = pPrinter->GetDriverName();
1201         SalPrinterQueueInfo* pInfo = ImplGetQueueInfo( pPrinter->GetName(), &aDriver );
1202         if ( pInfo )
1203         {
1204             ImplInit( pInfo );
1205             SetJobSetup( pPrinter->GetJobSetup() );
1206         }
1207         else
1208             ImplInitDisplay();
1209     }
1210     else
1211         SetJobSetup( pPrinter->GetJobSetup() );
1212 
1213     return false;
1214 }
1215 
SetOrientation(Orientation eOrientation)1216 bool Printer::SetOrientation( Orientation eOrientation )
1217 {
1218     if ( mbInPrintPage )
1219         return false;
1220 
1221     if ( maJobSetup.ImplGetConstData().GetOrientation() != eOrientation )
1222     {
1223         JobSetup      aJobSetup = maJobSetup;
1224         ImplJobSetup& rData = aJobSetup.ImplGetData();
1225 
1226         rData.SetOrientation(eOrientation);
1227 
1228         if ( IsDisplayPrinter() )
1229         {
1230             mbNewJobSetup = true;
1231             maJobSetup = aJobSetup;
1232             return true;
1233         }
1234 
1235         ReleaseGraphics();
1236         if ( mpInfoPrinter->SetData( JobSetFlags::ORIENTATION, &rData ) )
1237         {
1238             ImplUpdateJobSetupPaper( aJobSetup );
1239             mbNewJobSetup = true;
1240             maJobSetup = aJobSetup;
1241             ImplUpdatePageData();
1242             ImplUpdateFontList();
1243             return true;
1244         }
1245         else
1246             return false;
1247     }
1248 
1249     return true;
1250 }
1251 
GetOrientation() const1252 Orientation Printer::GetOrientation() const
1253 {
1254     return maJobSetup.ImplGetConstData().GetOrientation();
1255 }
1256 
SetPaperBin(sal_uInt16 nPaperBin)1257 bool Printer::SetPaperBin( sal_uInt16 nPaperBin )
1258 {
1259     if ( mbInPrintPage )
1260         return false;
1261 
1262     if ( maJobSetup.ImplGetConstData().GetPaperBin() != nPaperBin &&
1263          nPaperBin < GetPaperBinCount() )
1264     {
1265         JobSetup      aJobSetup = maJobSetup;
1266         ImplJobSetup& rData = aJobSetup.ImplGetData();
1267         rData.SetPaperBin(nPaperBin);
1268 
1269         if ( IsDisplayPrinter() )
1270         {
1271             mbNewJobSetup = true;
1272             maJobSetup = aJobSetup;
1273             return true;
1274         }
1275 
1276         ReleaseGraphics();
1277         if ( mpInfoPrinter->SetData( JobSetFlags::PAPERBIN, &rData ) )
1278         {
1279             ImplUpdateJobSetupPaper( aJobSetup );
1280             mbNewJobSetup = true;
1281             maJobSetup = aJobSetup;
1282             ImplUpdatePageData();
1283             ImplUpdateFontList();
1284             return true;
1285         }
1286         else
1287             return false;
1288     }
1289 
1290     return true;
1291 }
1292 
GetPaperBin() const1293 sal_uInt16 Printer::GetPaperBin() const
1294 {
1295     return maJobSetup.ImplGetConstData().GetPaperBin();
1296 }
1297 
GetPrinterSettingsPreferred() const1298 bool Printer::GetPrinterSettingsPreferred() const
1299 {
1300     return maJobSetup.ImplGetConstData().GetPapersizeFromSetup();
1301 }
1302 
1303 // dear loplugins, DO NOT REMOVE this code
1304 // it will be used in follow-up commits
SetPrinterSettingsPreferred(bool bPaperSizeFromSetup)1305 void Printer::SetPrinterSettingsPreferred( bool bPaperSizeFromSetup)
1306 {
1307     if ( maJobSetup.ImplGetConstData().GetPapersizeFromSetup() != bPaperSizeFromSetup )
1308     {
1309         JobSetup      aJobSetup = maJobSetup;
1310         ImplJobSetup& rData = aJobSetup.ImplGetData();
1311         rData.SetPapersizeFromSetup(bPaperSizeFromSetup);
1312 
1313         mbNewJobSetup = true;
1314         maJobSetup = aJobSetup;
1315     }
1316 }
1317 
1318 // Map user paper format to an available printer paper format
ImplFindPaperFormatForUserSize(JobSetup & aJobSetup)1319 void Printer::ImplFindPaperFormatForUserSize( JobSetup& aJobSetup )
1320 {
1321     ImplJobSetup& rData = aJobSetup.ImplGetData();
1322 
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());
1327 
1328     // Compare all paper formats and get the appropriate one
1329     for ( int i = 0; i < nPaperCount; i++ )
1330     {
1331         const PaperInfo& rPaperInfo = GetPaperInfo( i );
1332 
1333         if ( aInfo.sloppyEqual(rPaperInfo) )
1334         {
1335             rData.SetPaperFormat(
1336                 ImplGetPaperFormat( rPaperInfo.getWidth(),
1337                     rPaperInfo.getHeight() ));
1338             rData.SetOrientation( Orientation::Portrait );
1339             return;
1340         }
1341     }
1342 
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 )))
1349         return;
1350 
1351     const tools::Long nRotatedWidth = rData.GetPaperHeight();
1352     const tools::Long nRotatedHeight = rData.GetPaperWidth();
1353     PaperInfo aRotatedInfo(nRotatedWidth, nRotatedHeight);
1354 
1355     for ( int i = 0; i < nPaperCount; i++ )
1356     {
1357         const PaperInfo& rPaperInfo = GetPaperInfo( i );
1358 
1359         if ( aRotatedInfo.sloppyEqual( rPaperInfo ) )
1360         {
1361             rData.SetPaperFormat(
1362                 ImplGetPaperFormat( rPaperInfo.getWidth(),
1363                     rPaperInfo.getHeight() ));
1364             rData.SetOrientation( Orientation::Landscape );
1365             return;
1366         }
1367     }
1368 }
1369 
SetPaper(Paper ePaper)1370 void Printer::SetPaper( Paper ePaper )
1371 {
1372     if ( mbInPrintPage )
1373         return;
1374 
1375     if ( maJobSetup.ImplGetConstData().GetPaperFormat() == ePaper )
1376         return;
1377 
1378     JobSetup      aJobSetup = maJobSetup;
1379     ImplJobSetup& rData = aJobSetup.ImplGetData();
1380 
1381     rData.SetPaperFormat( ePaper );
1382     if ( ePaper != PAPER_USER )
1383     {
1384         PaperInfo aInfo(ePaper);
1385         rData.SetPaperWidth( aInfo.getWidth() );
1386         rData.SetPaperHeight( aInfo.getHeight() );
1387     }
1388 
1389     if ( IsDisplayPrinter() )
1390     {
1391         mbNewJobSetup = true;
1392         maJobSetup = aJobSetup;
1393         return;
1394     }
1395 
1396     ReleaseGraphics();
1397     if ( ePaper == PAPER_USER )
1398         ImplFindPaperFormatForUserSize( aJobSetup );
1399     if ( mpInfoPrinter->SetData( JobSetFlags::PAPERSIZE | JobSetFlags::ORIENTATION, &rData ))
1400     {
1401         ImplUpdateJobSetupPaper( aJobSetup );
1402         mbNewJobSetup = true;
1403         maJobSetup = aJobSetup;
1404         ImplUpdatePageData();
1405         ImplUpdateFontList();
1406     }
1407 }
1408 
SetPaperSizeUser(const Size & rSize)1409 bool Printer::SetPaperSizeUser( const Size& rSize )
1410 {
1411     if ( mbInPrintPage )
1412         return false;
1413 
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());
1418 
1419     if(!bNeedToChange)
1420     {
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
1425         // normal print
1426         const Paper aPaper = ImplGetPaperFormat(aPageSize.Width(), aPageSize.Height());
1427 
1428         bNeedToChange = maJobSetup.ImplGetConstData().GetPaperFormat() != PAPER_USER &&
1429             maJobSetup.ImplGetConstData().GetPaperFormat() != aPaper;
1430     }
1431 
1432     if(bNeedToChange)
1433     {
1434         JobSetup      aJobSetup = maJobSetup;
1435         ImplJobSetup& rData = aJobSetup.ImplGetData();
1436         rData.SetPaperFormat( PAPER_USER );
1437         rData.SetPaperWidth( aPageSize.Width() );
1438         rData.SetPaperHeight( aPageSize.Height() );
1439 
1440         if ( IsDisplayPrinter() )
1441         {
1442             mbNewJobSetup = true;
1443             maJobSetup = aJobSetup;
1444             return true;
1445         }
1446 
1447         ReleaseGraphics();
1448         ImplFindPaperFormatForUserSize( aJobSetup );
1449 
1450         // Changing the paper size can also change the orientation!
1451         if ( mpInfoPrinter->SetData( JobSetFlags::PAPERSIZE | JobSetFlags::ORIENTATION, &rData ))
1452         {
1453             ImplUpdateJobSetupPaper( aJobSetup );
1454             mbNewJobSetup = true;
1455             maJobSetup = aJobSetup;
1456             ImplUpdatePageData();
1457             ImplUpdateFontList();
1458             return true;
1459         }
1460         else
1461             return false;
1462     }
1463 
1464     return true;
1465 }
1466 
GetPaperInfoCount() const1467 int Printer::GetPaperInfoCount() const
1468 {
1469     if( ! mpInfoPrinter )
1470         return 0;
1471     if( ! mpInfoPrinter->m_bPapersInit )
1472         mpInfoPrinter->InitPaperFormats( &maJobSetup.ImplGetConstData() );
1473     return mpInfoPrinter->m_aPaperFormats.size();
1474 }
1475 
GetPaperName(Paper ePaper)1476 OUString Printer::GetPaperName( Paper ePaper )
1477 {
1478     ImplSVData* pSVData = ImplGetSVData();
1479     if( pSVData->maPaperNames.empty() )
1480     {
1481         static const int PaperIndex[] =
1482         {
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
1495         };
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]);
1499     }
1500 
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();
1503 }
1504 
GetPaperInfo(int nPaper) const1505 const PaperInfo& Printer::GetPaperInfo( int nPaper ) const
1506 {
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];
1514 }
1515 
GetPaperSize(int nPaper)1516 Size Printer::GetPaperSize( int nPaper )
1517 {
1518     PaperInfo aInfo = GetPaperInfo( nPaper );
1519     return PixelToLogic( Size( aInfo.getWidth(), aInfo.getHeight() ) );
1520 }
1521 
SetDuplexMode(DuplexMode eDuplex)1522 void Printer::SetDuplexMode( DuplexMode eDuplex )
1523 {
1524     if ( mbInPrintPage )
1525         return;
1526 
1527     if ( maJobSetup.ImplGetConstData().GetDuplexMode() == eDuplex )
1528         return;
1529 
1530     JobSetup      aJobSetup = maJobSetup;
1531     ImplJobSetup& rData = aJobSetup.ImplGetData();
1532 
1533     rData.SetDuplexMode( eDuplex );
1534 
1535     if ( IsDisplayPrinter() )
1536     {
1537         mbNewJobSetup = true;
1538         maJobSetup = aJobSetup;
1539         return;
1540     }
1541 
1542     ReleaseGraphics();
1543     if ( mpInfoPrinter->SetData( JobSetFlags::DUPLEXMODE, &rData ) )
1544     {
1545         ImplUpdateJobSetupPaper( aJobSetup );
1546         mbNewJobSetup = true;
1547         maJobSetup = aJobSetup;
1548         ImplUpdatePageData();
1549         ImplUpdateFontList();
1550     }
1551 }
1552 
GetDuplexMode() const1553 DuplexMode Printer::GetDuplexMode() const
1554 {
1555     return maJobSetup.ImplGetConstData().GetDuplexMode();
1556 }
1557 
GetPaper() const1558 Paper Printer::GetPaper() const
1559 {
1560     return maJobSetup.ImplGetConstData().GetPaperFormat();
1561 }
1562 
GetPaperBinCount() const1563 sal_uInt16 Printer::GetPaperBinCount() const
1564 {
1565     if ( IsDisplayPrinter() )
1566         return 0;
1567 
1568     return mpInfoPrinter->GetPaperBinCount( &maJobSetup.ImplGetConstData() );
1569 }
1570 
GetPaperBinName(sal_uInt16 nPaperBin) const1571 OUString Printer::GetPaperBinName( sal_uInt16 nPaperBin ) const
1572 {
1573     if ( IsDisplayPrinter() )
1574         return OUString();
1575 
1576     if ( nPaperBin < GetPaperBinCount() )
1577         return mpInfoPrinter->GetPaperBinName( &maJobSetup.ImplGetConstData(), nPaperBin );
1578     else
1579         return OUString();
1580 }
1581 
SetCopyCount(sal_uInt16 nCopy,bool bCollate)1582 void Printer::SetCopyCount( sal_uInt16 nCopy, bool bCollate )
1583 {
1584     mnCopyCount = nCopy;
1585     mbCollateCopy = bCollate;
1586 }
1587 
ImplSalPrinterErrorCodeToVCL(SalPrinterError nError)1588 ErrCode Printer::ImplSalPrinterErrorCodeToVCL( SalPrinterError nError )
1589 {
1590     ErrCode nVCLError;
1591     switch ( nError )
1592     {
1593         case SalPrinterError::NONE:
1594             nVCLError = ERRCODE_NONE;
1595             break;
1596         case SalPrinterError::Abort:
1597             nVCLError = PRINTER_ABORT;
1598             break;
1599         default:
1600             nVCLError = PRINTER_GENERALERROR;
1601             break;
1602     }
1603 
1604     return nVCLError;
1605 }
1606 
EndJob()1607 void Printer::EndJob()
1608 {
1609     if ( !IsJobActive() )
1610         return;
1611 
1612     SAL_WARN_IF( mbInPrintPage, "vcl.gdi", "Printer::EndJob() - StartPage() without EndPage() called" );
1613 
1614     mbJobActive = false;
1615 
1616     if ( mpPrinter )
1617     {
1618         ReleaseGraphics();
1619 
1620         mbPrinting      = false;
1621 
1622         mbDevOutput = false;
1623         mpPrinter->EndJob();
1624         mpPrinter.reset();
1625     }
1626 }
1627 
ImplStartPage()1628 void Printer::ImplStartPage()
1629 {
1630     if ( !IsJobActive() )
1631         return;
1632 
1633     if ( !mpPrinter )
1634         return;
1635 
1636     SalGraphics* pGraphics = mpPrinter->StartPage( &maJobSetup.ImplGetData(),
1637                                                    mbNewJobSetup );
1638     if ( pGraphics )
1639     {
1640         ReleaseGraphics();
1641         mpJobGraphics = pGraphics;
1642     }
1643     mbDevOutput = true;
1644 
1645     // PrintJob not aborted ???
1646     if ( IsJobActive() )
1647         mbInPrintPage = true;
1648 }
1649 
ImplEndPage()1650 void Printer::ImplEndPage()
1651 {
1652     if ( !IsJobActive() )
1653         return;
1654 
1655     mbInPrintPage = false;
1656 
1657     if ( mpPrinter )
1658     {
1659         mpPrinter->EndPage();
1660         ReleaseGraphics();
1661         mbDevOutput = false;
1662 
1663         mpJobGraphics = nullptr;
1664         mbNewJobSetup = false;
1665     }
1666 }
1667 
updatePrinters()1668 void Printer::updatePrinters()
1669 {
1670     ImplSVData*         pSVData = ImplGetSVData();
1671     ImplPrnQueueList*   pPrnList = pSVData->maGDIData.mpPrinterQueueList.get();
1672 
1673     if ( !pPrnList )
1674         return;
1675 
1676     std::unique_ptr<ImplPrnQueueList> pNewList(new ImplPrnQueueList);
1677     pSVData->mpDefInst->GetPrinterQueueInfo( pNewList.get() );
1678 
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++ )
1681     {
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 )
1686         {
1687             bChanged = true;
1688         }
1689     }
1690     if( !bChanged )
1691         return;
1692 
1693     ImplDeletePrnQueueList();
1694     pSVData->maGDIData.mpPrinterQueueList = std::move(pNewList);
1695 
1696     Application* pApp = GetpApp();
1697     if( pApp )
1698     {
1699         DataChangedEvent aDCEvt( DataChangedEventType::PRINTER );
1700         Application::ImplCallEventListenersApplicationDataChanged(&aDCEvt);
1701         Application::NotifyAllWindows( aDCEvt );
1702     }
1703 }
1704 
UsePolyPolygonForComplexGradient()1705 bool Printer::UsePolyPolygonForComplexGradient()
1706 {
1707     return true;
1708 }
1709 
ClipAndDrawGradientMetafile(const Gradient & rGradient,const tools::PolyPolygon & rPolyPoly)1710 void Printer::ClipAndDrawGradientMetafile ( const Gradient &rGradient, const tools::PolyPolygon &rPolyPoly )
1711 {
1712     const tools::Rectangle aBoundRect( rPolyPoly.GetBoundRect() );
1713 
1714     Push( PushFlags::CLIPREGION );
1715     IntersectClipRegion(vcl::Region(rPolyPoly));
1716     DrawGradient( aBoundRect, rGradient );
1717     Pop();
1718 }
1719 
SetFontOrientation(LogicalFontInstance * const pFontEntry) const1720 void Printer::SetFontOrientation( LogicalFontInstance* const pFontEntry ) const
1721 {
1722     pFontEntry->mnOrientation = pFontEntry->mxFontMetric->GetOrientation();
1723 }
1724 
ClipToDeviceBounds(vcl::Region aRegion) const1725 vcl::Region Printer::ClipToDeviceBounds(vcl::Region aRegion) const
1726 {
1727     return aRegion;
1728 }
1729 
GetBitmap(const Point & rSrcPt,const Size & rSize) const1730 Bitmap Printer::GetBitmap( const Point& rSrcPt, const Size& rSize ) const
1731 {
1732     SAL_WARN("vcl.gdi", "GetBitmap(): This should never be called on by a Printer instance");
1733 
1734     return OutputDevice::GetBitmap( rSrcPt, rSize );
1735 }
1736 
GetDeviceInfo() const1737 css::awt::DeviceInfo Printer::GetDeviceInfo() const
1738 {
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;
1748 
1749     return aInfo;
1750 }
1751 
1752 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1753