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 "salinst.hxx"
24 #include "PhysicalFontCollection.hxx"
27 #include <vcl/ITiledRenderable.hxx>
32 ITiledRenderable::~ITiledRenderable()
38 using namespace ::com::sun::star::uno
;
40 bool VirtualDevice::AcquireGraphics() const
47 mbInitLineColor
= true;
48 mbInitFillColor
= true;
50 mbInitTextColor
= true;
51 mbInitClipRegion
= true;
53 ImplSVData
* pSVData
= ImplGetSVData();
57 mpGraphics
= mpVirDev
->AcquireGraphics();
58 // if needed retry after releasing least recently used virtual device graphics
61 if ( !pSVData
->maGDIData
.mpLastVirGraphics
)
63 pSVData
->maGDIData
.mpLastVirGraphics
->ReleaseGraphics();
64 mpGraphics
= mpVirDev
->AcquireGraphics();
66 // update global LRU list of virtual device graphics
69 mpNextGraphics
= pSVData
->maGDIData
.mpFirstVirGraphics
;
70 pSVData
->maGDIData
.mpFirstVirGraphics
= const_cast<VirtualDevice
*>(this);
72 mpNextGraphics
->mpPrevGraphics
= const_cast<VirtualDevice
*>(this);
73 if ( !pSVData
->maGDIData
.mpLastVirGraphics
)
74 pSVData
->maGDIData
.mpLastVirGraphics
= const_cast<VirtualDevice
*>(this);
80 mpGraphics
->SetXORMode( (RasterOp::Invert
== meRasterOp
) || (RasterOp::Xor
== meRasterOp
) );
81 mpGraphics
->setAntiAliasB2DDraw(bool(mnAntialiasing
& AntialiasingFlags::EnableB2dDraw
));
84 return mpGraphics
!= nullptr;
87 void VirtualDevice::ReleaseGraphics( bool bRelease
)
94 // release the fonts of the physically released graphics device
98 ImplSVData
* pSVData
= ImplGetSVData();
100 VirtualDevice
* pVirDev
= this;
103 pVirDev
->mpVirDev
->ReleaseGraphics( mpGraphics
);
104 // remove from global LRU list of virtual device graphics
105 if ( mpPrevGraphics
)
106 mpPrevGraphics
->mpNextGraphics
= mpNextGraphics
;
108 pSVData
->maGDIData
.mpFirstVirGraphics
= mpNextGraphics
;
109 if ( mpNextGraphics
)
110 mpNextGraphics
->mpPrevGraphics
= mpPrevGraphics
;
112 pSVData
->maGDIData
.mpLastVirGraphics
= mpPrevGraphics
;
114 mpGraphics
= nullptr;
115 mpPrevGraphics
= nullptr;
116 mpNextGraphics
= nullptr;
119 void VirtualDevice::ImplInitVirDev( const OutputDevice
* pOutDev
,
120 long nDX
, long nDY
, DeviceFormat eFormat
, const SystemGraphicsData
*pData
)
122 SAL_INFO( "vcl.virdev", "ImplInitVirDev(" << nDX
<< "," << nDY
<< "," << static_cast<int>(eFormat
) << ")" );
124 bool bErase
= nDX
> 0 && nDY
> 0;
132 ImplSVData
* pSVData
= ImplGetSVData();
135 pOutDev
= ImplGetDefaultWindow();
139 SalGraphics
* pGraphics
;
140 if ( !pOutDev
->mpGraphics
)
141 (void)pOutDev
->AcquireGraphics();
142 pGraphics
= pOutDev
->mpGraphics
;
144 mpVirDev
= pSVData
->mpDefInst
->CreateVirtualDevice(pGraphics
, nDX
, nDY
, eFormat
, pData
);
149 // do not abort but throw an exception, may be the current thread terminates anyway (plugin-scenario)
150 throw css::uno::RuntimeException(
151 "Could not create system bitmap!",
152 css::uno::Reference
< css::uno::XInterface
>() );
158 case DeviceFormat::BITMASK
:
162 mnBitCount
= pOutDev
->GetBitCount();
168 meAlphaFormat
= DeviceFormat::NONE
;
170 if (meFormat
== DeviceFormat::BITMASK
)
171 SetAntialiasing( AntialiasingFlags::DisableText
);
173 if ( pOutDev
->GetOutDevType() == OUTDEV_PRINTER
)
174 mbScreenComp
= false;
175 else if ( pOutDev
->GetOutDevType() == OUTDEV_VIRDEV
)
176 mbScreenComp
= static_cast<const VirtualDevice
*>(pOutDev
)->mbScreenComp
;
178 meOutDevType
= OUTDEV_VIRDEV
;
180 mpFontCollection
= pSVData
->maGDIData
.mpScreenFontList
;
181 mpFontCache
= pSVData
->maGDIData
.mpScreenFontCache
;
182 mnDPIX
= pOutDev
->mnDPIX
;
183 mnDPIY
= pOutDev
->mnDPIY
;
184 mnDPIScalePercentage
= pOutDev
->mnDPIScalePercentage
;
185 maFont
= pOutDev
->maFont
;
187 if( maTextColor
!= pOutDev
->maTextColor
)
189 maTextColor
= pOutDev
->maTextColor
;
190 mbInitTextColor
= true;
193 // virtual devices have white background by default
194 SetBackground( Wallpaper( Color( COL_WHITE
) ) );
196 // #i59283# don't erase user-provided surface
197 if( !pData
&& bErase
)
200 // register VirDev in the list
201 mpNext
= pSVData
->maGDIData
.mpFirstVirDev
;
204 mpNext
->mpPrev
= this;
206 pSVData
->maGDIData
.mpLastVirDev
= this;
207 pSVData
->maGDIData
.mpFirstVirDev
= this;
210 VirtualDevice::VirtualDevice(DeviceFormat eFormat
)
211 : mpVirDev( nullptr ),
212 meRefDevMode( RefDevMode::NONE
),
213 mbForceZeroExtleadBug( false )
215 SAL_INFO( "vcl.virdev", "VirtualDevice::VirtualDevice( " << static_cast<int>(eFormat
) << " )" );
217 ImplInitVirDev(Application::GetDefaultDevice(), 0, 0, eFormat
);
220 VirtualDevice::VirtualDevice(const OutputDevice
& rCompDev
, DeviceFormat eFormat
)
221 : mpVirDev( nullptr ),
222 meRefDevMode( RefDevMode::NONE
),
223 mbForceZeroExtleadBug( false )
225 SAL_INFO( "vcl.virdev", "VirtualDevice::VirtualDevice( " << static_cast<int>(eFormat
) << " )" );
227 ImplInitVirDev(&rCompDev
, 0, 0, eFormat
);
230 VirtualDevice::VirtualDevice(const OutputDevice
& rCompDev
, DeviceFormat eFormat
, DeviceFormat eAlphaFormat
)
231 : mpVirDev( nullptr )
232 , meRefDevMode( RefDevMode::NONE
)
233 , mbForceZeroExtleadBug( false )
235 SAL_INFO( "vcl.virdev",
236 "VirtualDevice::VirtualDevice( " << static_cast<int>(eFormat
) << ", " << static_cast<int>(eAlphaFormat
) << " )" );
238 ImplInitVirDev(&rCompDev
, 0, 0, eFormat
);
240 // Enable alpha channel
241 meAlphaFormat
= eAlphaFormat
;
244 VirtualDevice::VirtualDevice(const SystemGraphicsData
*pData
, const Size
&rSize
,
245 DeviceFormat eFormat
)
246 : mpVirDev( nullptr ),
247 meRefDevMode( RefDevMode::NONE
),
248 mbForceZeroExtleadBug( false )
250 SAL_INFO( "vcl.virdev", "VirtualDevice::VirtualDevice( " << static_cast<int>(eFormat
) << " )" );
252 ImplInitVirDev(Application::GetDefaultDevice(), rSize
.Width(), rSize
.Height(),
256 VirtualDevice::~VirtualDevice()
258 SAL_INFO( "vcl.virdev", "VirtualDevice::~VirtualDevice()" );
262 void VirtualDevice::dispose()
264 SAL_INFO( "vcl.virdev", "VirtualDevice::dispose()" );
266 ImplSVData
* pSVData
= ImplGetSVData();
272 // remove this VirtualDevice from the double-linked global list
274 mpPrev
->mpNext
= mpNext
;
276 pSVData
->maGDIData
.mpFirstVirDev
= mpNext
;
279 mpNext
->mpPrev
= mpPrev
;
281 pSVData
->maGDIData
.mpLastVirDev
= mpPrev
;
283 OutputDevice::dispose();
286 bool VirtualDevice::InnerImplSetOutputSizePixel( const Size
& rNewSize
, bool bErase
,
287 sal_uInt8
*const pBuffer
)
289 SAL_INFO( "vcl.virdev",
290 "VirtualDevice::InnerImplSetOutputSizePixel( " << rNewSize
.Width() << ", "
291 << rNewSize
.Height() << ", " << int(bErase
) << " )" );
295 else if ( rNewSize
== GetOutputSizePixel() )
299 // Yeah, so trying to re-use a VirtualDevice but this time using a
300 // pre-allocated buffer won't work. Big deal.
305 long nNewWidth
= rNewSize
.Width(), nNewHeight
= rNewSize
.Height();
310 if ( nNewHeight
< 1 )
316 bRet
= mpVirDev
->SetSizeUsingBuffer( nNewWidth
, nNewHeight
, pBuffer
);
318 bRet
= mpVirDev
->SetSize( nNewWidth
, nNewHeight
);
322 mnOutWidth
= rNewSize
.Width();
323 mnOutHeight
= rNewSize
.Height();
329 SalVirtualDevice
* pNewVirDev
;
330 ImplSVData
* pSVData
= ImplGetSVData();
332 // we need a graphics
335 if ( !AcquireGraphics() )
339 pNewVirDev
= pSVData
->mpDefInst
->CreateVirtualDevice(mpGraphics
, nNewWidth
, nNewHeight
, meFormat
);
342 SalGraphics
* pGraphics
= pNewVirDev
->AcquireGraphics();
347 if ( mnOutWidth
< nNewWidth
)
351 if ( mnOutHeight
< nNewHeight
)
352 nHeight
= mnOutHeight
;
354 nHeight
= nNewHeight
;
355 SalTwoRect
aPosAry(0, 0, nWidth
, nHeight
, 0, 0, nWidth
, nHeight
);
356 pGraphics
->CopyBits( aPosAry
, mpGraphics
, this, this );
357 pNewVirDev
->ReleaseGraphics( pGraphics
);
360 mpVirDev
= pNewVirDev
;
361 mnOutWidth
= rNewSize
.Width();
362 mnOutHeight
= rNewSize
.Height();
378 // #i32109#: Fill opaque areas correctly (without relying on
379 // fill/linecolor state)
380 void VirtualDevice::ImplFillOpaqueRectangle( const tools::Rectangle
& rRect
)
382 // Set line and fill color to black (->opaque),
383 // fill rect with that (linecolor, too, because of
384 // those pesky missing pixel problems)
385 Push( PushFlags::LINECOLOR
| PushFlags::FILLCOLOR
);
386 SetLineColor( COL_BLACK
);
387 SetFillColor( COL_BLACK
);
392 bool VirtualDevice::ImplSetOutputSizePixel( const Size
& rNewSize
, bool bErase
,
393 sal_uInt8
*const pBuffer
)
395 if( InnerImplSetOutputSizePixel(rNewSize
, bErase
, pBuffer
) )
397 if (meAlphaFormat
!= DeviceFormat::NONE
)
399 // #110958# Setup alpha bitmap
400 if(mpAlphaVDev
&& mpAlphaVDev
->GetOutputSizePixel() != rNewSize
)
402 mpAlphaVDev
.disposeAndClear();
407 mpAlphaVDev
= VclPtr
<VirtualDevice
>::Create(*this, meAlphaFormat
);
408 mpAlphaVDev
->InnerImplSetOutputSizePixel(rNewSize
, bErase
, nullptr);
411 // TODO: copy full outdev state to new one, here. Also needed in outdev2.cxx:DrawOutDev
412 if( GetLineColor() != Color( COL_TRANSPARENT
) )
413 mpAlphaVDev
->SetLineColor( COL_BLACK
);
415 if( GetFillColor() != Color( COL_TRANSPARENT
) )
416 mpAlphaVDev
->SetFillColor( COL_BLACK
);
418 mpAlphaVDev
->SetMapMode( GetMapMode() );
427 void VirtualDevice::EnableRTL( bool bEnable
)
429 // virdevs default to not mirroring, they will only be set to mirroring
430 // under rare circumstances in the UI, eg the valueset control
431 // because each virdev has its own SalGraphics we can safely switch the SalGraphics here
433 if( AcquireGraphics() )
434 mpGraphics
->SetLayout( bEnable
? SalLayoutFlags::BiDiRtl
: SalLayoutFlags::NONE
);
436 OutputDevice::EnableRTL(bEnable
);
439 bool VirtualDevice::SetOutputSizePixel( const Size
& rNewSize
, bool bErase
)
441 return ImplSetOutputSizePixel(rNewSize
, bErase
, nullptr);
444 bool VirtualDevice::SetOutputSizePixelScaleOffsetAndBuffer(
445 const Size
& rNewSize
, const Fraction
& rScale
, const Point
& rNewOffset
,
446 sal_uInt8
*const pBuffer
)
449 MapMode mm
= GetMapMode();
450 mm
.SetOrigin( rNewOffset
);
451 mm
.SetScaleX( rScale
);
452 mm
.SetScaleY( rScale
);
455 return ImplSetOutputSizePixel(rNewSize
, true, pBuffer
);
458 void VirtualDevice::SetReferenceDevice( RefDevMode i_eRefDevMode
)
460 sal_Int32 nDPIX
= 600, nDPIY
= 600;
461 switch( i_eRefDevMode
)
463 case RefDevMode::NONE
:
465 SAL_WARN( "vcl.virdev", "VDev::SetRefDev illegal argument!" );
467 case RefDevMode::Dpi600
:
470 case RefDevMode::MSO1
:
471 nDPIX
= nDPIY
= 6*1440;
473 case RefDevMode::PDF1
:
477 ImplSetReferenceDevice( i_eRefDevMode
, nDPIX
, nDPIY
);
480 void VirtualDevice::SetReferenceDevice( sal_Int32 i_nDPIX
, sal_Int32 i_nDPIY
)
482 ImplSetReferenceDevice( RefDevMode::Custom
, i_nDPIX
, i_nDPIY
);
485 void VirtualDevice::ImplSetReferenceDevice( RefDevMode i_eRefDevMode
, sal_Int32 i_nDPIX
, sal_Int32 i_nDPIY
)
489 mnDPIScalePercentage
= 100;
491 EnableOutput( false ); // prevent output on reference device
492 mbScreenComp
= false;
494 // invalidate currently selected fonts
498 // avoid adjusting font lists when already in refdev mode
499 RefDevMode nOldRefDevMode
= meRefDevMode
;
500 meRefDevMode
= i_eRefDevMode
;
501 if( nOldRefDevMode
!= RefDevMode::NONE
)
504 // the reference device should have only scalable fonts
505 // => clean up the original font lists before getting new ones
506 if ( mpFontInstance
)
508 mpFontCache
->Release( mpFontInstance
);
509 mpFontInstance
= nullptr;
511 if ( mpDeviceFontList
)
513 delete mpDeviceFontList
;
514 mpDeviceFontList
= nullptr;
516 if ( mpDeviceFontSizeList
)
518 delete mpDeviceFontSizeList
;
519 mpDeviceFontSizeList
= nullptr;
522 // preserve global font lists
523 ImplSVData
* pSVData
= ImplGetSVData();
524 if( mpFontCollection
&& (mpFontCollection
!= pSVData
->maGDIData
.mpScreenFontList
) )
525 delete mpFontCollection
;
526 if( mpFontCache
&& (mpFontCache
!= pSVData
->maGDIData
.mpScreenFontCache
) )
529 // get font list with scalable fonts only
531 mpFontCollection
= pSVData
->maGDIData
.mpScreenFontList
->Clone();
533 // prepare to use new font lists
534 mpFontCache
= new ImplFontCache();
537 sal_uInt16
VirtualDevice::GetBitCount() const
542 bool VirtualDevice::UsePolyPolygonForComplexGradient()
547 void VirtualDevice::Compat_ZeroExtleadBug()
549 mbForceZeroExtleadBug
= true;
552 long VirtualDevice::GetFontExtLeading() const
555 // backwards compatible line metrics after fixing #i60945#
556 if ( mbForceZeroExtleadBug
)
560 return mpFontInstance
->mxFontMetric
->GetExternalLeading();
563 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */