Line data Source code
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 :
21 : #include <tools/debug.hxx>
22 :
23 : #include <vcl/settings.hxx>
24 : #include <vcl/svapp.hxx>
25 : #include <vcl/wrkwin.hxx>
26 : #include <vcl/virdev.hxx>
27 :
28 : #include <salinst.hxx>
29 : #include <salgdi.hxx>
30 : #include <salframe.hxx>
31 : #include <salvd.hxx>
32 : #include <outdev.h>
33 : #include <svdata.hxx>
34 :
35 : using namespace ::com::sun::star::uno;
36 :
37 : // =======================================================================
38 :
39 15162 : void VirtualDevice::ImplInitVirDev( const OutputDevice* pOutDev,
40 : long nDX, long nDY, sal_uInt16 nBitCount, const SystemGraphicsData *pData )
41 : {
42 15162 : if ( nDX < 1 )
43 0 : nDX = 1;
44 :
45 15162 : if ( nDY < 1 )
46 0 : nDY = 1;
47 :
48 15162 : ImplSVData* pSVData = ImplGetSVData();
49 :
50 15162 : if ( !pOutDev )
51 0 : pOutDev = ImplGetDefaultWindow();
52 15162 : if( !pOutDev )
53 15162 : return;
54 :
55 : SalGraphics* pGraphics;
56 15162 : if ( !pOutDev->mpGraphics )
57 2052 : ((OutputDevice*)pOutDev)->ImplGetGraphics();
58 15162 : pGraphics = pOutDev->mpGraphics;
59 15162 : if ( pGraphics )
60 15162 : mpVirDev = pSVData->mpDefInst->CreateVirtualDevice( pGraphics, nDX, nDY, nBitCount, pData );
61 : else
62 0 : mpVirDev = NULL;
63 15162 : if ( !mpVirDev )
64 : {
65 : // do not abort but throw an exception, may be the current thread terminates anyway (plugin-scenario)
66 : throw ::com::sun::star::uno::RuntimeException(
67 : OUString( RTL_CONSTASCII_USTRINGPARAM( "Could not create system bitmap!" ) ),
68 0 : ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() );
69 : //GetpApp()->Exception( EXC_SYSOBJNOTCREATED );
70 : }
71 :
72 15162 : mnBitCount = ( nBitCount ? nBitCount : pOutDev->GetBitCount() );
73 15162 : mnOutWidth = nDX;
74 15162 : mnOutHeight = nDY;
75 15162 : mbScreenComp = sal_True;
76 15162 : mnAlphaDepth = -1;
77 :
78 : // #i59315# init vdev size from system object, when passed a
79 : // SystemGraphicsData. Otherwise, output size will always
80 : // incorrectly stay at (1,1)
81 15162 : if( pData && mpVirDev )
82 0 : mpVirDev->GetSize(mnOutWidth,mnOutHeight);
83 :
84 15162 : if( mnBitCount < 8 )
85 837 : SetAntialiasing( ANTIALIASING_DISABLE_TEXT );
86 :
87 15162 : if ( pOutDev->GetOutDevType() == OUTDEV_PRINTER )
88 0 : mbScreenComp = sal_False;
89 15162 : else if ( pOutDev->GetOutDevType() == OUTDEV_VIRDEV )
90 90 : mbScreenComp = ((VirtualDevice*)pOutDev)->mbScreenComp;
91 :
92 15162 : meOutDevType = OUTDEV_VIRDEV;
93 15162 : mbDevOutput = sal_True;
94 15162 : mpFontList = pSVData->maGDIData.mpScreenFontList;
95 15162 : mpFontCache = pSVData->maGDIData.mpScreenFontCache;
96 15162 : mnDPIX = pOutDev->mnDPIX;
97 15162 : mnDPIY = pOutDev->mnDPIY;
98 15162 : maFont = pOutDev->maFont;
99 :
100 15162 : if( maTextColor != pOutDev->maTextColor )
101 : {
102 0 : maTextColor = pOutDev->maTextColor;
103 0 : mbInitTextColor = true;
104 : }
105 :
106 : // Virtuelle Devices haben defaultmaessig einen weissen Hintergrund
107 15162 : SetBackground( Wallpaper( Color( COL_WHITE ) ) );
108 :
109 : // #i59283# don't erase user-provided surface
110 15162 : if( !pData )
111 15162 : Erase();
112 :
113 : // VirDev in Liste eintragen
114 15162 : mpNext = pSVData->maGDIData.mpFirstVirDev;
115 15162 : mpPrev = NULL;
116 15162 : if ( mpNext )
117 14964 : mpNext->mpPrev = this;
118 : else
119 198 : pSVData->maGDIData.mpLastVirDev = this;
120 15162 : pSVData->maGDIData.mpFirstVirDev = this;
121 : }
122 :
123 : // -----------------------------------------------------------------------
124 :
125 12927 : VirtualDevice::VirtualDevice( sal_uInt16 nBitCount )
126 : : mpVirDev( NULL ),
127 12927 : meRefDevMode( REFDEV_NONE )
128 : {
129 : SAL_WARN_IF( nBitCount > 1, "vcl.gdi",
130 : "VirtualDevice::VirtualDevice(): Only 0 or 1 is for BitCount allowed" );
131 : SAL_INFO( "vcl.gdi", "VirtualDevice::VirtualDevice( " << nBitCount << " )" );
132 :
133 12927 : ImplInitVirDev( Application::GetDefaultDevice(), 1, 1, nBitCount );
134 12927 : }
135 :
136 : // -----------------------------------------------------------------------
137 :
138 2231 : VirtualDevice::VirtualDevice( const OutputDevice& rCompDev, sal_uInt16 nBitCount )
139 : : mpVirDev( NULL ),
140 2231 : meRefDevMode( REFDEV_NONE )
141 : {
142 : SAL_WARN_IF( nBitCount > 1, "vcl.gdi",
143 : "VirtualDevice::VirtualDevice(): Only 0 or 1 is for BitCount allowed" );
144 : SAL_INFO( "vcl.gdi", "VirtualDevice::VirtualDevice( " << nBitCount << " )" );
145 :
146 2231 : ImplInitVirDev( &rCompDev, 1, 1, nBitCount );
147 2231 : }
148 :
149 : // -----------------------------------------------------------------------
150 :
151 4 : VirtualDevice::VirtualDevice( const OutputDevice& rCompDev, sal_uInt16 nBitCount, sal_uInt16 nAlphaBitCount )
152 : : mpVirDev( NULL ),
153 4 : meRefDevMode( REFDEV_NONE )
154 : {
155 : SAL_WARN_IF( nBitCount > 1, "vcl.gdi",
156 : "VirtualDevice::VirtualDevice(): Only 0 or 1 is for BitCount allowed" );
157 : SAL_INFO( "vcl.gdi",
158 : "VirtualDevice::VirtualDevice( " << nBitCount << ", " << nAlphaBitCount << " )" );
159 :
160 4 : ImplInitVirDev( &rCompDev, 1, 1, nBitCount );
161 :
162 : // Enable alpha channel
163 4 : mnAlphaDepth = sal::static_int_cast<sal_Int8>(nAlphaBitCount);
164 4 : }
165 :
166 : // -----------------------------------------------------------------------
167 :
168 0 : VirtualDevice::VirtualDevice( const SystemGraphicsData *pData, sal_uInt16 nBitCount )
169 : : mpVirDev( NULL ),
170 0 : meRefDevMode( REFDEV_NONE )
171 : {
172 : SAL_INFO( "vcl.gdi", "VirtualDevice::VirtualDevice( " << nBitCount << " )" );
173 :
174 0 : ImplInitVirDev( Application::GetDefaultDevice(), 1, 1, nBitCount, pData );
175 0 : }
176 :
177 : // -----------------------------------------------------------------------
178 :
179 28005 : VirtualDevice::~VirtualDevice()
180 : {
181 : SAL_INFO( "vcl.gdi", "VirtualDevice::~VirtualDevice()" );
182 :
183 12490 : ImplSVData* pSVData = ImplGetSVData();
184 :
185 12490 : ImplReleaseGraphics();
186 :
187 12490 : if ( mpVirDev )
188 12490 : pSVData->mpDefInst->DestroyVirtualDevice( mpVirDev );
189 :
190 : // remove this VirtualDevice from the double-linked global list
191 12490 : if( mpPrev )
192 1734 : mpPrev->mpNext = mpNext;
193 : else
194 10756 : pSVData->maGDIData.mpFirstVirDev = mpNext;
195 :
196 12490 : if( mpNext )
197 12257 : mpNext->mpPrev = mpPrev;
198 : else
199 233 : pSVData->maGDIData.mpLastVirDev = mpPrev;
200 15515 : }
201 :
202 : // -----------------------------------------------------------------------
203 :
204 2129 : sal_Bool VirtualDevice::InnerImplSetOutputSizePixel( const Size& rNewSize, sal_Bool bErase, const basebmp::RawMemorySharedArray &pBuffer )
205 : {
206 : SAL_INFO( "vcl.gdi",
207 : "VirtualDevice::InnerImplSetOutputSizePixel( " << rNewSize.Width() << ", "
208 : << rNewSize.Height() << ", " << bErase << " )" );
209 :
210 2129 : if ( !mpVirDev )
211 0 : return sal_False;
212 2129 : else if ( rNewSize == GetOutputSizePixel() )
213 : {
214 6 : if ( bErase )
215 6 : Erase();
216 : // Yeah, so trying to re-use a VirtualDevice but this time using a
217 : // pre-allocated buffer won't work. Big deal.
218 6 : return sal_True;
219 : }
220 :
221 : sal_Bool bRet;
222 2123 : long nNewWidth = rNewSize.Width(), nNewHeight = rNewSize.Height();
223 :
224 2123 : if ( nNewWidth < 1 )
225 4 : nNewWidth = 1;
226 :
227 2123 : if ( nNewHeight < 1 )
228 4 : nNewHeight = 1;
229 :
230 2123 : if ( bErase )
231 : {
232 1791 : if ( pBuffer )
233 0 : bRet = mpVirDev->SetSizeUsingBuffer( nNewWidth, nNewHeight, pBuffer );
234 : else
235 1791 : bRet = mpVirDev->SetSize( nNewWidth, nNewHeight );
236 :
237 1791 : if ( bRet )
238 : {
239 1791 : mnOutWidth = rNewSize.Width();
240 1791 : mnOutHeight = rNewSize.Height();
241 1791 : Erase();
242 : }
243 : }
244 : else
245 : {
246 : SalVirtualDevice* pNewVirDev;
247 332 : ImplSVData* pSVData = ImplGetSVData();
248 :
249 : // we need a graphics
250 332 : if ( !mpGraphics )
251 : {
252 0 : if ( !ImplGetGraphics() )
253 0 : return sal_False;
254 : }
255 :
256 332 : pNewVirDev = pSVData->mpDefInst->CreateVirtualDevice( mpGraphics, nNewWidth, nNewHeight, mnBitCount );
257 332 : if ( pNewVirDev )
258 : {
259 332 : SalGraphics* pGraphics = pNewVirDev->GetGraphics();
260 332 : if ( pGraphics )
261 : {
262 : SalTwoRect aPosAry;
263 : long nWidth;
264 : long nHeight;
265 332 : if ( mnOutWidth < nNewWidth )
266 328 : nWidth = mnOutWidth;
267 : else
268 4 : nWidth = nNewWidth;
269 332 : if ( mnOutHeight < nNewHeight )
270 328 : nHeight = mnOutHeight;
271 : else
272 4 : nHeight = nNewHeight;
273 332 : aPosAry.mnSrcX = 0;
274 332 : aPosAry.mnSrcY = 0;
275 332 : aPosAry.mnSrcWidth = nWidth;
276 332 : aPosAry.mnSrcHeight = nHeight;
277 332 : aPosAry.mnDestX = 0;
278 332 : aPosAry.mnDestY = 0;
279 332 : aPosAry.mnDestWidth = nWidth;
280 332 : aPosAry.mnDestHeight = nHeight;
281 :
282 332 : pGraphics->CopyBits( &aPosAry, mpGraphics, this, this );
283 332 : pNewVirDev->ReleaseGraphics( pGraphics );
284 332 : ImplReleaseGraphics();
285 332 : pSVData->mpDefInst->DestroyVirtualDevice( mpVirDev );
286 332 : mpVirDev = pNewVirDev;
287 332 : mnOutWidth = rNewSize.Width();
288 332 : mnOutHeight = rNewSize.Height();
289 332 : bRet = sal_True;
290 : }
291 : else
292 : {
293 0 : bRet = sal_False;
294 0 : pSVData->mpDefInst->DestroyVirtualDevice( pNewVirDev );
295 : }
296 : }
297 : else
298 0 : bRet = sal_False;
299 : }
300 :
301 2123 : return bRet;
302 : }
303 :
304 : // -----------------------------------------------------------------------
305 :
306 : // #i32109#: Fill opaque areas correctly (without relying on
307 : // fill/linecolor state)
308 0 : void VirtualDevice::ImplFillOpaqueRectangle( const Rectangle& rRect )
309 : {
310 : // Set line and fill color to black (->opaque),
311 : // fill rect with that (linecolor, too, because of
312 : // those pesky missing pixel problems)
313 0 : Push( PUSH_LINECOLOR | PUSH_FILLCOLOR );
314 0 : SetLineColor( COL_BLACK );
315 0 : SetFillColor( COL_BLACK );
316 0 : DrawRect( rRect );
317 0 : Pop();
318 0 : }
319 :
320 : // -----------------------------------------------------------------------
321 :
322 2125 : sal_Bool VirtualDevice::ImplSetOutputSizePixel( const Size& rNewSize, sal_Bool bErase, const basebmp::RawMemorySharedArray &pBuffer )
323 : {
324 2125 : if( InnerImplSetOutputSizePixel(rNewSize, bErase, pBuffer) )
325 : {
326 2125 : if( mnAlphaDepth != -1 )
327 : {
328 : // #110958# Setup alpha bitmap
329 4 : if(mpAlphaVDev && mpAlphaVDev->GetOutputSizePixel() != rNewSize)
330 : {
331 0 : delete mpAlphaVDev;
332 0 : mpAlphaVDev = 0L;
333 : }
334 :
335 4 : if( !mpAlphaVDev )
336 : {
337 4 : mpAlphaVDev = new VirtualDevice( *this, mnAlphaDepth );
338 4 : mpAlphaVDev->InnerImplSetOutputSizePixel(rNewSize, bErase, basebmp::RawMemorySharedArray() );
339 : }
340 :
341 : // TODO: copy full outdev state to new one, here. Also needed in outdev2.cxx:DrawOutDev
342 4 : if( GetLineColor() != Color( COL_TRANSPARENT ) )
343 4 : mpAlphaVDev->SetLineColor( COL_BLACK );
344 :
345 4 : if( GetFillColor() != Color( COL_TRANSPARENT ) )
346 4 : mpAlphaVDev->SetFillColor( COL_BLACK );
347 :
348 4 : mpAlphaVDev->SetMapMode( GetMapMode() );
349 : }
350 :
351 2125 : return sal_True;
352 : }
353 :
354 0 : return sal_False;
355 : }
356 :
357 2125 : sal_Bool VirtualDevice::SetOutputSizePixel( const Size& rNewSize, sal_Bool bErase )
358 : {
359 2125 : return ImplSetOutputSizePixel( rNewSize, bErase, basebmp::RawMemorySharedArray() );
360 : }
361 :
362 0 : sal_Bool VirtualDevice::SetOutputSizePixelScaleOffsetAndBuffer( const Size& rNewSize, const Fraction& rScale, const Point& rNewOffset, const basebmp::RawMemorySharedArray &pBuffer )
363 : {
364 0 : if (pBuffer) {
365 0 : MapMode mm = GetMapMode();
366 0 : mm.SetOrigin( rNewOffset );
367 0 : mm.SetScaleX( rScale );
368 0 : mm.SetScaleY( rScale );
369 0 : SetMapMode( mm );
370 : }
371 0 : return ImplSetOutputSizePixel( rNewSize, sal_True, pBuffer);
372 : }
373 :
374 : // -----------------------------------------------------------------------
375 :
376 758 : void VirtualDevice::SetReferenceDevice( RefDevMode i_eRefDevMode )
377 : {
378 758 : sal_Int32 nDPIX = 600, nDPIY = 600;
379 758 : switch( i_eRefDevMode )
380 : {
381 : case REFDEV_NONE:
382 : default:
383 : DBG_ASSERT( sal_False, "VDev::SetRefDev illegal argument!" );
384 0 : break;
385 : case REFDEV_MODE06:
386 6 : nDPIX = nDPIY = 600;
387 6 : break;
388 : case REFDEV_MODE_MSO1:
389 752 : nDPIX = nDPIY = 6*1440;
390 752 : break;
391 : case REFDEV_MODE_PDF1:
392 0 : nDPIX = nDPIY = 720;
393 0 : break;
394 : }
395 758 : ImplSetReferenceDevice( i_eRefDevMode, nDPIX, nDPIY );
396 758 : }
397 :
398 0 : void VirtualDevice::SetReferenceDevice( sal_Int32 i_nDPIX, sal_Int32 i_nDPIY )
399 : {
400 0 : ImplSetReferenceDevice( REFDEV_CUSTOM, i_nDPIX, i_nDPIY );
401 0 : }
402 :
403 758 : void VirtualDevice::ImplSetReferenceDevice( RefDevMode i_eRefDevMode, sal_Int32 i_nDPIX, sal_Int32 i_nDPIY )
404 : {
405 758 : mnDPIX = i_nDPIX;
406 758 : mnDPIY = i_nDPIY;
407 :
408 758 : EnableOutput( sal_False ); // prevent output on reference device
409 758 : mbScreenComp = sal_False;
410 :
411 : // invalidate currently selected fonts
412 758 : mbInitFont = sal_True;
413 758 : mbNewFont = sal_True;
414 :
415 : // avoid adjusting font lists when already in refdev mode
416 758 : sal_uInt8 nOldRefDevMode = meRefDevMode;
417 758 : sal_uInt8 nOldCompatFlag = (sal_uInt8)meRefDevMode & REFDEV_FORCE_ZERO_EXTLEAD;
418 758 : meRefDevMode = (sal_uInt8)(i_eRefDevMode | nOldCompatFlag);
419 758 : if( (nOldRefDevMode ^ nOldCompatFlag) != REFDEV_NONE )
420 758 : return;
421 :
422 : // the reference device should have only scalable fonts
423 : // => clean up the original font lists before getting new ones
424 758 : if ( mpFontEntry )
425 : {
426 0 : mpFontCache->Release( mpFontEntry );
427 0 : mpFontEntry = NULL;
428 : }
429 758 : if ( mpGetDevFontList )
430 : {
431 0 : delete mpGetDevFontList;
432 0 : mpGetDevFontList = NULL;
433 : }
434 758 : if ( mpGetDevSizeList )
435 : {
436 0 : delete mpGetDevSizeList;
437 0 : mpGetDevSizeList = NULL;
438 : }
439 :
440 : // preserve global font lists
441 758 : ImplSVData* pSVData = ImplGetSVData();
442 758 : if( mpFontList && (mpFontList != pSVData->maGDIData.mpScreenFontList) )
443 0 : delete mpFontList;
444 758 : if( mpFontCache && (mpFontCache != pSVData->maGDIData.mpScreenFontCache) )
445 0 : delete mpFontCache;
446 :
447 : // get font list with scalable fonts only
448 758 : ImplGetGraphics();
449 758 : mpFontList = pSVData->maGDIData.mpScreenFontList->Clone( true, false );
450 :
451 : // prepare to use new font lists
452 758 : mpFontCache = new ImplFontCache( false );
453 : }
454 :
455 : // -----------------------------------------------------------------------
456 :
457 0 : void VirtualDevice::Compat_ZeroExtleadBug()
458 : {
459 0 : meRefDevMode = (sal_uInt8)meRefDevMode | REFDEV_FORCE_ZERO_EXTLEAD;
460 0 : }
461 :
462 : // -----------------------------------------------------------------------
463 :
464 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|