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 .
21 #include <tools/debug.hxx>
23 #include <vcl/settings.hxx>
24 #include <vcl/svapp.hxx>
25 #include <vcl/wrkwin.hxx>
26 #include <vcl/virdev.hxx>
28 #include <salinst.hxx>
30 #include <salframe.hxx>
35 using namespace ::com::sun::star::uno
;
37 // =======================================================================
39 void VirtualDevice::ImplInitVirDev( const OutputDevice
* pOutDev
,
40 long nDX
, long nDY
, sal_uInt16 nBitCount
, const SystemGraphicsData
*pData
)
42 SAL_INFO( "vcl.virdev", "ImplInitVirDev(" << nDX
<< "," << nDY
<< "," << nBitCount
<< ")" );
50 ImplSVData
* pSVData
= ImplGetSVData();
53 pOutDev
= ImplGetDefaultWindow();
57 SalGraphics
* pGraphics
;
58 if ( !pOutDev
->mpGraphics
)
59 ((OutputDevice
*)pOutDev
)->ImplGetGraphics();
60 pGraphics
= pOutDev
->mpGraphics
;
62 mpVirDev
= pSVData
->mpDefInst
->CreateVirtualDevice( pGraphics
, nDX
, nDY
, nBitCount
, pData
);
67 // do not abort but throw an exception, may be the current thread terminates anyway (plugin-scenario)
68 throw ::com::sun::star::uno::RuntimeException(
69 OUString( "Could not create system bitmap!" ),
70 ::com::sun::star::uno::Reference
< ::com::sun::star::uno::XInterface
>() );
71 //GetpApp()->Exception( EXC_SYSOBJNOTCREATED );
74 mnBitCount
= ( nBitCount
? nBitCount
: pOutDev
->GetBitCount() );
77 mbScreenComp
= sal_True
;
80 // #i59315# init vdev size from system object, when passed a
81 // SystemGraphicsData. Otherwise, output size will always
82 // incorrectly stay at (1,1)
83 if( pData
&& mpVirDev
)
84 mpVirDev
->GetSize(mnOutWidth
,mnOutHeight
);
87 SetAntialiasing( ANTIALIASING_DISABLE_TEXT
);
89 if ( pOutDev
->GetOutDevType() == OUTDEV_PRINTER
)
90 mbScreenComp
= sal_False
;
91 else if ( pOutDev
->GetOutDevType() == OUTDEV_VIRDEV
)
92 mbScreenComp
= ((VirtualDevice
*)pOutDev
)->mbScreenComp
;
94 meOutDevType
= OUTDEV_VIRDEV
;
95 mbDevOutput
= sal_True
;
96 mpFontList
= pSVData
->maGDIData
.mpScreenFontList
;
97 mpFontCache
= pSVData
->maGDIData
.mpScreenFontCache
;
98 mnDPIX
= pOutDev
->mnDPIX
;
99 mnDPIY
= pOutDev
->mnDPIY
;
100 maFont
= pOutDev
->maFont
;
102 if( maTextColor
!= pOutDev
->maTextColor
)
104 maTextColor
= pOutDev
->maTextColor
;
105 mbInitTextColor
= true;
108 // Virtuelle Devices haben defaultmaessig einen weissen Hintergrund
109 SetBackground( Wallpaper( Color( COL_WHITE
) ) );
111 // #i59283# don't erase user-provided surface
115 // VirDev in Liste eintragen
116 mpNext
= pSVData
->maGDIData
.mpFirstVirDev
;
119 mpNext
->mpPrev
= this;
121 pSVData
->maGDIData
.mpLastVirDev
= this;
122 pSVData
->maGDIData
.mpFirstVirDev
= this;
125 // -----------------------------------------------------------------------
127 VirtualDevice::VirtualDevice( sal_uInt16 nBitCount
)
129 meRefDevMode( REFDEV_NONE
)
131 SAL_WARN_IF( (nBitCount
> 1 && nBitCount
!= 8), "vcl.gdi",
132 "VirtualDevice::VirtualDevice(): Only 0, 1 or 8 allowed for BitCount" );
133 SAL_INFO( "vcl.gdi", "VirtualDevice::VirtualDevice( " << nBitCount
<< " )" );
135 ImplInitVirDev( Application::GetDefaultDevice(), 1, 1, nBitCount
);
138 // -----------------------------------------------------------------------
140 VirtualDevice::VirtualDevice( const OutputDevice
& rCompDev
, sal_uInt16 nBitCount
)
142 meRefDevMode( REFDEV_NONE
)
144 SAL_WARN_IF( nBitCount
> 1, "vcl.gdi",
145 "VirtualDevice::VirtualDevice(): Only 0 or 1 is for BitCount allowed" );
146 SAL_INFO( "vcl.gdi", "VirtualDevice::VirtualDevice( " << nBitCount
<< " )" );
148 ImplInitVirDev( &rCompDev
, 1, 1, nBitCount
);
151 // -----------------------------------------------------------------------
153 VirtualDevice::VirtualDevice( const OutputDevice
& rCompDev
, sal_uInt16 nBitCount
, sal_uInt16 nAlphaBitCount
)
155 meRefDevMode( REFDEV_NONE
)
157 SAL_WARN_IF( nBitCount
> 1, "vcl.gdi",
158 "VirtualDevice::VirtualDevice(): Only 0 or 1 is for BitCount allowed" );
160 "VirtualDevice::VirtualDevice( " << nBitCount
<< ", " << nAlphaBitCount
<< " )" );
162 ImplInitVirDev( &rCompDev
, 1, 1, nBitCount
);
164 // Enable alpha channel
165 mnAlphaDepth
= sal::static_int_cast
<sal_Int8
>(nAlphaBitCount
);
168 // -----------------------------------------------------------------------
170 VirtualDevice::VirtualDevice( const SystemGraphicsData
*pData
, sal_uInt16 nBitCount
)
172 meRefDevMode( REFDEV_NONE
)
174 SAL_INFO( "vcl.gdi", "VirtualDevice::VirtualDevice( " << nBitCount
<< " )" );
176 ImplInitVirDev( Application::GetDefaultDevice(), 1, 1, nBitCount
, pData
);
179 // -----------------------------------------------------------------------
181 VirtualDevice::~VirtualDevice()
183 SAL_INFO( "vcl.gdi", "VirtualDevice::~VirtualDevice()" );
185 ImplSVData
* pSVData
= ImplGetSVData();
187 ImplReleaseGraphics();
190 pSVData
->mpDefInst
->DestroyVirtualDevice( mpVirDev
);
192 // remove this VirtualDevice from the double-linked global list
194 mpPrev
->mpNext
= mpNext
;
196 pSVData
->maGDIData
.mpFirstVirDev
= mpNext
;
199 mpNext
->mpPrev
= mpPrev
;
201 pSVData
->maGDIData
.mpLastVirDev
= mpPrev
;
204 // -----------------------------------------------------------------------
206 sal_Bool
VirtualDevice::InnerImplSetOutputSizePixel( const Size
& rNewSize
, sal_Bool bErase
, const basebmp::RawMemorySharedArray
&pBuffer
)
209 "VirtualDevice::InnerImplSetOutputSizePixel( " << rNewSize
.Width() << ", "
210 << rNewSize
.Height() << ", " << int(bErase
) << " )" );
214 else if ( rNewSize
== GetOutputSizePixel() )
218 // Yeah, so trying to re-use a VirtualDevice but this time using a
219 // pre-allocated buffer won't work. Big deal.
224 long nNewWidth
= rNewSize
.Width(), nNewHeight
= rNewSize
.Height();
229 if ( nNewHeight
< 1 )
235 bRet
= mpVirDev
->SetSizeUsingBuffer( nNewWidth
, nNewHeight
, pBuffer
);
237 bRet
= mpVirDev
->SetSize( nNewWidth
, nNewHeight
);
241 mnOutWidth
= rNewSize
.Width();
242 mnOutHeight
= rNewSize
.Height();
248 SalVirtualDevice
* pNewVirDev
;
249 ImplSVData
* pSVData
= ImplGetSVData();
251 // we need a graphics
254 if ( !ImplGetGraphics() )
258 pNewVirDev
= pSVData
->mpDefInst
->CreateVirtualDevice( mpGraphics
, nNewWidth
, nNewHeight
, mnBitCount
);
261 SalGraphics
* pGraphics
= pNewVirDev
->GetGraphics();
267 if ( mnOutWidth
< nNewWidth
)
271 if ( mnOutHeight
< nNewHeight
)
272 nHeight
= mnOutHeight
;
274 nHeight
= nNewHeight
;
277 aPosAry
.mnSrcWidth
= nWidth
;
278 aPosAry
.mnSrcHeight
= nHeight
;
281 aPosAry
.mnDestWidth
= nWidth
;
282 aPosAry
.mnDestHeight
= nHeight
;
284 pGraphics
->CopyBits( &aPosAry
, mpGraphics
, this, this );
285 pNewVirDev
->ReleaseGraphics( pGraphics
);
286 ImplReleaseGraphics();
287 pSVData
->mpDefInst
->DestroyVirtualDevice( mpVirDev
);
288 mpVirDev
= pNewVirDev
;
289 mnOutWidth
= rNewSize
.Width();
290 mnOutHeight
= rNewSize
.Height();
296 pSVData
->mpDefInst
->DestroyVirtualDevice( pNewVirDev
);
306 // -----------------------------------------------------------------------
308 // #i32109#: Fill opaque areas correctly (without relying on
309 // fill/linecolor state)
310 void VirtualDevice::ImplFillOpaqueRectangle( const Rectangle
& rRect
)
312 // Set line and fill color to black (->opaque),
313 // fill rect with that (linecolor, too, because of
314 // those pesky missing pixel problems)
315 Push( PUSH_LINECOLOR
| PUSH_FILLCOLOR
);
316 SetLineColor( COL_BLACK
);
317 SetFillColor( COL_BLACK
);
322 // -----------------------------------------------------------------------
324 sal_Bool
VirtualDevice::ImplSetOutputSizePixel( const Size
& rNewSize
, sal_Bool bErase
, const basebmp::RawMemorySharedArray
&pBuffer
)
326 if( InnerImplSetOutputSizePixel(rNewSize
, bErase
, pBuffer
) )
328 if( mnAlphaDepth
!= -1 )
330 // #110958# Setup alpha bitmap
331 if(mpAlphaVDev
&& mpAlphaVDev
->GetOutputSizePixel() != rNewSize
)
339 mpAlphaVDev
= new VirtualDevice( *this, mnAlphaDepth
);
340 mpAlphaVDev
->InnerImplSetOutputSizePixel(rNewSize
, bErase
, basebmp::RawMemorySharedArray() );
343 // TODO: copy full outdev state to new one, here. Also needed in outdev2.cxx:DrawOutDev
344 if( GetLineColor() != Color( COL_TRANSPARENT
) )
345 mpAlphaVDev
->SetLineColor( COL_BLACK
);
347 if( GetFillColor() != Color( COL_TRANSPARENT
) )
348 mpAlphaVDev
->SetFillColor( COL_BLACK
);
350 mpAlphaVDev
->SetMapMode( GetMapMode() );
359 sal_Bool
VirtualDevice::SetOutputSizePixel( const Size
& rNewSize
, sal_Bool bErase
)
361 return ImplSetOutputSizePixel( rNewSize
, bErase
, basebmp::RawMemorySharedArray() );
364 sal_Bool
VirtualDevice::SetOutputSizePixelScaleOffsetAndBuffer( const Size
& rNewSize
, const Fraction
& rScale
, const Point
& rNewOffset
, const basebmp::RawMemorySharedArray
&pBuffer
)
367 MapMode mm
= GetMapMode();
368 mm
.SetOrigin( rNewOffset
);
369 mm
.SetScaleX( rScale
);
370 mm
.SetScaleY( rScale
);
373 return ImplSetOutputSizePixel( rNewSize
, sal_True
, pBuffer
);
376 // -----------------------------------------------------------------------
378 void VirtualDevice::SetReferenceDevice( RefDevMode i_eRefDevMode
)
380 sal_Int32 nDPIX
= 600, nDPIY
= 600;
381 switch( i_eRefDevMode
)
385 DBG_ASSERT( sal_False
, "VDev::SetRefDev illegal argument!" );
390 case REFDEV_MODE_MSO1
:
391 nDPIX
= nDPIY
= 6*1440;
393 case REFDEV_MODE_PDF1
:
397 ImplSetReferenceDevice( i_eRefDevMode
, nDPIX
, nDPIY
);
400 void VirtualDevice::SetReferenceDevice( sal_Int32 i_nDPIX
, sal_Int32 i_nDPIY
)
402 ImplSetReferenceDevice( REFDEV_CUSTOM
, i_nDPIX
, i_nDPIY
);
405 void VirtualDevice::ImplSetReferenceDevice( RefDevMode i_eRefDevMode
, sal_Int32 i_nDPIX
, sal_Int32 i_nDPIY
)
410 EnableOutput( sal_False
); // prevent output on reference device
411 mbScreenComp
= sal_False
;
413 // invalidate currently selected fonts
414 mbInitFont
= sal_True
;
415 mbNewFont
= sal_True
;
417 // avoid adjusting font lists when already in refdev mode
418 sal_uInt8 nOldRefDevMode
= meRefDevMode
;
419 sal_uInt8 nOldCompatFlag
= (sal_uInt8
)meRefDevMode
& REFDEV_FORCE_ZERO_EXTLEAD
;
420 meRefDevMode
= (sal_uInt8
)(i_eRefDevMode
| nOldCompatFlag
);
421 if( (nOldRefDevMode
^ nOldCompatFlag
) != REFDEV_NONE
)
424 // the reference device should have only scalable fonts
425 // => clean up the original font lists before getting new ones
428 mpFontCache
->Release( mpFontEntry
);
431 if ( mpGetDevFontList
)
433 delete mpGetDevFontList
;
434 mpGetDevFontList
= NULL
;
436 if ( mpGetDevSizeList
)
438 delete mpGetDevSizeList
;
439 mpGetDevSizeList
= NULL
;
442 // preserve global font lists
443 ImplSVData
* pSVData
= ImplGetSVData();
444 if( mpFontList
&& (mpFontList
!= pSVData
->maGDIData
.mpScreenFontList
) )
446 if( mpFontCache
&& (mpFontCache
!= pSVData
->maGDIData
.mpScreenFontCache
) )
449 // get font list with scalable fonts only
451 mpFontList
= pSVData
->maGDIData
.mpScreenFontList
->Clone( true, false );
453 // prepare to use new font lists
454 mpFontCache
= new ImplFontCache( false );
457 // -----------------------------------------------------------------------
459 void VirtualDevice::Compat_ZeroExtleadBug()
461 meRefDevMode
= (sal_uInt8
)meRefDevMode
| REFDEV_FORCE_ZERO_EXTLEAD
;
464 // -----------------------------------------------------------------------
466 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */