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 6800 : void VirtualDevice::ImplInitVirDev( const OutputDevice* pOutDev,
40 : long nDX, long nDY, sal_uInt16 nBitCount, const SystemGraphicsData *pData )
41 : {
42 6800 : if ( nDX < 1 )
43 0 : nDX = 1;
44 :
45 6800 : if ( nDY < 1 )
46 0 : nDY = 1;
47 :
48 6800 : ImplSVData* pSVData = ImplGetSVData();
49 :
50 6800 : if ( !pOutDev )
51 0 : pOutDev = ImplGetDefaultWindow();
52 6800 : if( !pOutDev )
53 6800 : return;
54 :
55 : SalGraphics* pGraphics;
56 6800 : if ( !pOutDev->mpGraphics )
57 970 : ((OutputDevice*)pOutDev)->ImplGetGraphics();
58 6800 : pGraphics = pOutDev->mpGraphics;
59 6800 : if ( pGraphics )
60 6800 : mpVirDev = pSVData->mpDefInst->CreateVirtualDevice( pGraphics, nDX, nDY, nBitCount, pData );
61 : else
62 0 : mpVirDev = NULL;
63 6800 : 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 6800 : mnBitCount = ( nBitCount ? nBitCount : pOutDev->GetBitCount() );
73 6800 : mnOutWidth = nDX;
74 6800 : mnOutHeight = nDY;
75 6800 : mbScreenComp = sal_True;
76 6800 : 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 6800 : if( pData && mpVirDev )
82 0 : mpVirDev->GetSize(mnOutWidth,mnOutHeight);
83 :
84 6800 : if( mnBitCount < 8 )
85 395 : SetAntialiasing( ANTIALIASING_DISABLE_TEXT );
86 :
87 6800 : if ( pOutDev->GetOutDevType() == OUTDEV_PRINTER )
88 0 : mbScreenComp = sal_False;
89 6800 : else if ( pOutDev->GetOutDevType() == OUTDEV_VIRDEV )
90 41 : mbScreenComp = ((VirtualDevice*)pOutDev)->mbScreenComp;
91 :
92 6800 : meOutDevType = OUTDEV_VIRDEV;
93 6800 : mbDevOutput = sal_True;
94 6800 : mpFontList = pSVData->maGDIData.mpScreenFontList;
95 6800 : mpFontCache = pSVData->maGDIData.mpScreenFontCache;
96 6800 : mnDPIX = pOutDev->mnDPIX;
97 6800 : mnDPIY = pOutDev->mnDPIY;
98 6800 : maFont = pOutDev->maFont;
99 :
100 6800 : 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 6800 : SetBackground( Wallpaper( Color( COL_WHITE ) ) );
108 :
109 : // #i59283# don't erase user-provided surface
110 6800 : if( !pData )
111 6800 : Erase();
112 :
113 : // VirDev in Liste eintragen
114 6800 : mpNext = pSVData->maGDIData.mpFirstVirDev;
115 6800 : mpPrev = NULL;
116 6800 : if ( mpNext )
117 6727 : mpNext->mpPrev = this;
118 : else
119 73 : pSVData->maGDIData.mpLastVirDev = this;
120 6800 : pSVData->maGDIData.mpFirstVirDev = this;
121 : }
122 :
123 : // -----------------------------------------------------------------------
124 :
125 5797 : VirtualDevice::VirtualDevice( sal_uInt16 nBitCount )
126 : : mpVirDev( NULL ),
127 5797 : 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 5797 : ImplInitVirDev( Application::GetDefaultDevice(), 1, 1, nBitCount );
134 5797 : }
135 :
136 : // -----------------------------------------------------------------------
137 :
138 1003 : VirtualDevice::VirtualDevice( const OutputDevice& rCompDev, sal_uInt16 nBitCount )
139 : : mpVirDev( NULL ),
140 1003 : 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 1003 : ImplInitVirDev( &rCompDev, 1, 1, nBitCount );
147 1003 : }
148 :
149 : // -----------------------------------------------------------------------
150 :
151 0 : VirtualDevice::VirtualDevice( const OutputDevice& rCompDev, sal_uInt16 nBitCount, sal_uInt16 nAlphaBitCount )
152 : : mpVirDev( NULL ),
153 0 : 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 0 : ImplInitVirDev( &rCompDev, 1, 1, nBitCount );
161 :
162 : // Enable alpha channel
163 0 : mnAlphaDepth = sal::static_int_cast<sal_Int8>(nAlphaBitCount);
164 0 : }
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 12800 : VirtualDevice::~VirtualDevice()
180 : {
181 : SAL_INFO( "vcl.gdi", "VirtualDevice::~VirtualDevice()" );
182 :
183 5689 : ImplSVData* pSVData = ImplGetSVData();
184 :
185 5689 : ImplReleaseGraphics();
186 :
187 5689 : if ( mpVirDev )
188 5689 : pSVData->mpDefInst->DestroyVirtualDevice( mpVirDev );
189 :
190 : // remove this VirtualDevice from the double-linked global list
191 5689 : if( mpPrev )
192 821 : mpPrev->mpNext = mpNext;
193 : else
194 4868 : pSVData->maGDIData.mpFirstVirDev = mpNext;
195 :
196 5689 : if( mpNext )
197 5610 : mpNext->mpPrev = mpPrev;
198 : else
199 79 : pSVData->maGDIData.mpLastVirDev = mpPrev;
200 7111 : }
201 :
202 : // -----------------------------------------------------------------------
203 :
204 928 : 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 928 : if ( !mpVirDev )
211 0 : return sal_False;
212 928 : else if ( rNewSize == GetOutputSizePixel() )
213 : {
214 0 : if ( bErase )
215 0 : 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 0 : return sal_True;
219 : }
220 :
221 : sal_Bool bRet;
222 928 : long nNewWidth = rNewSize.Width(), nNewHeight = rNewSize.Height();
223 :
224 928 : if ( nNewWidth < 1 )
225 2 : nNewWidth = 1;
226 :
227 928 : if ( nNewHeight < 1 )
228 2 : nNewHeight = 1;
229 :
230 928 : if ( bErase )
231 : {
232 797 : if ( pBuffer )
233 0 : bRet = mpVirDev->SetSizeUsingBuffer( nNewWidth, nNewHeight, pBuffer );
234 : else
235 797 : bRet = mpVirDev->SetSize( nNewWidth, nNewHeight );
236 :
237 797 : if ( bRet )
238 : {
239 797 : mnOutWidth = rNewSize.Width();
240 797 : mnOutHeight = rNewSize.Height();
241 797 : Erase();
242 : }
243 : }
244 : else
245 : {
246 : SalVirtualDevice* pNewVirDev;
247 131 : ImplSVData* pSVData = ImplGetSVData();
248 :
249 : // we need a graphics
250 131 : if ( !mpGraphics )
251 : {
252 0 : if ( !ImplGetGraphics() )
253 0 : return sal_False;
254 : }
255 :
256 131 : pNewVirDev = pSVData->mpDefInst->CreateVirtualDevice( mpGraphics, nNewWidth, nNewHeight, mnBitCount );
257 131 : if ( pNewVirDev )
258 : {
259 131 : SalGraphics* pGraphics = pNewVirDev->GetGraphics();
260 131 : if ( pGraphics )
261 : {
262 : SalTwoRect aPosAry;
263 : long nWidth;
264 : long nHeight;
265 131 : if ( mnOutWidth < nNewWidth )
266 129 : nWidth = mnOutWidth;
267 : else
268 2 : nWidth = nNewWidth;
269 131 : if ( mnOutHeight < nNewHeight )
270 129 : nHeight = mnOutHeight;
271 : else
272 2 : nHeight = nNewHeight;
273 131 : aPosAry.mnSrcX = 0;
274 131 : aPosAry.mnSrcY = 0;
275 131 : aPosAry.mnSrcWidth = nWidth;
276 131 : aPosAry.mnSrcHeight = nHeight;
277 131 : aPosAry.mnDestX = 0;
278 131 : aPosAry.mnDestY = 0;
279 131 : aPosAry.mnDestWidth = nWidth;
280 131 : aPosAry.mnDestHeight = nHeight;
281 :
282 131 : pGraphics->CopyBits( &aPosAry, mpGraphics, this, this );
283 131 : pNewVirDev->ReleaseGraphics( pGraphics );
284 131 : ImplReleaseGraphics();
285 131 : pSVData->mpDefInst->DestroyVirtualDevice( mpVirDev );
286 131 : mpVirDev = pNewVirDev;
287 131 : mnOutWidth = rNewSize.Width();
288 131 : mnOutHeight = rNewSize.Height();
289 131 : 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 928 : 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 928 : sal_Bool VirtualDevice::ImplSetOutputSizePixel( const Size& rNewSize, sal_Bool bErase, const basebmp::RawMemorySharedArray &pBuffer )
323 : {
324 928 : if( InnerImplSetOutputSizePixel(rNewSize, bErase, pBuffer) )
325 : {
326 928 : if( mnAlphaDepth != -1 )
327 : {
328 : // #110958# Setup alpha bitmap
329 0 : if(mpAlphaVDev && mpAlphaVDev->GetOutputSizePixel() != rNewSize)
330 : {
331 0 : delete mpAlphaVDev;
332 0 : mpAlphaVDev = 0L;
333 : }
334 :
335 0 : if( !mpAlphaVDev )
336 : {
337 0 : mpAlphaVDev = new VirtualDevice( *this, mnAlphaDepth );
338 0 : 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 0 : if( GetLineColor() != Color( COL_TRANSPARENT ) )
343 0 : mpAlphaVDev->SetLineColor( COL_BLACK );
344 :
345 0 : if( GetFillColor() != Color( COL_TRANSPARENT ) )
346 0 : mpAlphaVDev->SetFillColor( COL_BLACK );
347 :
348 0 : mpAlphaVDev->SetMapMode( GetMapMode() );
349 : }
350 :
351 928 : return sal_True;
352 : }
353 :
354 0 : return sal_False;
355 : }
356 :
357 928 : sal_Bool VirtualDevice::SetOutputSizePixel( const Size& rNewSize, sal_Bool bErase )
358 : {
359 928 : 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 362 : void VirtualDevice::SetReferenceDevice( RefDevMode i_eRefDevMode )
377 : {
378 362 : sal_Int32 nDPIX = 600, nDPIY = 600;
379 362 : 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 3 : nDPIX = nDPIY = 600;
387 3 : break;
388 : case REFDEV_MODE_MSO1:
389 359 : nDPIX = nDPIY = 6*1440;
390 359 : break;
391 : case REFDEV_MODE_PDF1:
392 0 : nDPIX = nDPIY = 720;
393 0 : break;
394 : }
395 362 : ImplSetReferenceDevice( i_eRefDevMode, nDPIX, nDPIY );
396 362 : }
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 362 : void VirtualDevice::ImplSetReferenceDevice( RefDevMode i_eRefDevMode, sal_Int32 i_nDPIX, sal_Int32 i_nDPIY )
404 : {
405 362 : mnDPIX = i_nDPIX;
406 362 : mnDPIY = i_nDPIY;
407 :
408 362 : EnableOutput( sal_False ); // prevent output on reference device
409 362 : mbScreenComp = sal_False;
410 :
411 : // invalidate currently selected fonts
412 362 : mbInitFont = sal_True;
413 362 : mbNewFont = sal_True;
414 :
415 : // avoid adjusting font lists when already in refdev mode
416 362 : sal_uInt8 nOldRefDevMode = meRefDevMode;
417 362 : sal_uInt8 nOldCompatFlag = (sal_uInt8)meRefDevMode & REFDEV_FORCE_ZERO_EXTLEAD;
418 362 : meRefDevMode = (sal_uInt8)(i_eRefDevMode | nOldCompatFlag);
419 362 : if( (nOldRefDevMode ^ nOldCompatFlag) != REFDEV_NONE )
420 362 : return;
421 :
422 : // the reference device should have only scalable fonts
423 : // => clean up the original font lists before getting new ones
424 362 : if ( mpFontEntry )
425 : {
426 0 : mpFontCache->Release( mpFontEntry );
427 0 : mpFontEntry = NULL;
428 : }
429 362 : if ( mpGetDevFontList )
430 : {
431 0 : delete mpGetDevFontList;
432 0 : mpGetDevFontList = NULL;
433 : }
434 362 : if ( mpGetDevSizeList )
435 : {
436 0 : delete mpGetDevSizeList;
437 0 : mpGetDevSizeList = NULL;
438 : }
439 :
440 : // preserve global font lists
441 362 : ImplSVData* pSVData = ImplGetSVData();
442 362 : if( mpFontList && (mpFontList != pSVData->maGDIData.mpScreenFontList) )
443 0 : delete mpFontList;
444 362 : if( mpFontCache && (mpFontCache != pSVData->maGDIData.mpScreenFontCache) )
445 0 : delete mpFontCache;
446 :
447 : // get font list with scalable fonts only
448 362 : ImplGetGraphics();
449 362 : mpFontList = pSVData->maGDIData.mpScreenFontList->Clone( true, false );
450 :
451 : // prepare to use new font lists
452 362 : 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: */
|