xref: /trunk/main/desktop/source/splash/splash.cxx (revision 2722cedd)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_desktop.hxx"
26 
27 #include <introbmpnames.hxx>
28 #include "splash.hxx"
29 #include <stdio.h>
30 #include <unotools/bootstrap.hxx>
31 #include <vos/process.hxx>
32 #include <tools/urlobj.hxx>
33 #include <tools/stream.hxx>
34 #include <sfx2/sfx.hrc>
35 #include <vcl/svapp.hxx>
36 #include <vcl/salnativewidgets.hxx>
37 
38 #include <com/sun/star/registry/XRegistryKey.hpp>
39 #include <rtl/bootstrap.hxx>
40 #include <rtl/logfile.hxx>
41 #include <rtl/ustrbuf.hxx>
42 #include <rtl/math.hxx>
43 #include <vcl/graph.hxx>
44 #include <svtools/filter.hxx>
45 
46 #define NOT_LOADED  ((long)-1)
47 
48 using namespace ::rtl;
49 using namespace ::com::sun::star::registry;
50 
51 namespace desktop
52 {
53 
54 SplashScreen::SplashScreen(const Reference< XMultiServiceFactory >& rSMgr)
55     : IntroWindow()
56     , _vdev(*((IntroWindow*)this))
57     , _cProgressFrameColor(sal::static_int_cast< ColorData >(NOT_LOADED))
58     , _cProgressBarColor(sal::static_int_cast< ColorData >(NOT_LOADED))
59     , _bNativeProgress(true)
60 	, _iMax(100)
61 	, _iProgress(0)
62     , _eBitmapMode(BM_DEFAULTMODE)
63 	, _bPaintBitmap(sal_True)
64 	, _bPaintProgress(sal_False)
65     , _bShowLogo(sal_True)
66     , _bFullScreenSplash(sal_False)
67     , _bProgressEnd(sal_False)
68     , _tlx(NOT_LOADED)
69     , _tly(NOT_LOADED)
70     , _barwidth(NOT_LOADED)
71     , _barheight(NOT_LOADED)
72     , _barspace(2)
73     , _fXPos(-1.0)
74     , _fYPos(-1.0)
75     , _fWidth(-1.0)
76     , _fHeight(-1.0)
77     , _xoffset(12)
78 	, _yoffset(18)
79 {
80 	_rFactory = rSMgr;
81 
82     loadConfig();
83 }
84 
85 SplashScreen::~SplashScreen()
86 {
87 	Application::RemoveEventListener(
88 		LINK( this, SplashScreen, AppEventListenerHdl ) );
89 	Hide();
90 
91 }
92 
93 void SAL_CALL SplashScreen::start(const OUString&, sal_Int32 nRange)
94 	throw (RuntimeException)
95 {
96     _iMax = nRange;
97     if (_bVisible) {
98         _bProgressEnd = sal_False;
99         ::vos::OGuard aSolarGuard( Application::GetSolarMutex() );
100         if ( _eBitmapMode == BM_FULLSCREEN )
101             ShowFullScreenMode( sal_True );
102         Show();
103         Paint(Rectangle());
104         Flush();
105     }
106 }
107 
108 void SAL_CALL SplashScreen::end()
109 	throw (RuntimeException)
110 {
111     _iProgress = _iMax;
112     if (_bVisible )
113     {
114         if ( _eBitmapMode == BM_FULLSCREEN )
115             EndFullScreenMode();
116         Hide();
117     }
118     _bProgressEnd = sal_True;
119 }
120 
121 void SAL_CALL SplashScreen::reset()
122 	throw (RuntimeException)
123 {
124     _iProgress = 0;
125     if (_bVisible && !_bProgressEnd )
126     {
127         if ( _eBitmapMode == BM_FULLSCREEN )
128             ShowFullScreenMode( sal_True );
129         Show();
130         updateStatus();
131     }
132 }
133 
134 void SAL_CALL SplashScreen::setText(const OUString& rText)
135 	throw (RuntimeException)
136 {
137     ::vos::OGuard aSolarGuard( Application::GetSolarMutex() );
138     if ( _sProgressText != rText )
139     {
140         _sProgressText = rText;
141 
142         if (_bVisible && !_bProgressEnd)
143         {
144             if ( _eBitmapMode == BM_FULLSCREEN )
145                 ShowFullScreenMode( sal_True );
146             Show();
147             updateStatus();
148         }
149     }
150 }
151 
152 void SAL_CALL SplashScreen::setValue(sal_Int32 nValue)
153 	throw (RuntimeException)
154 {
155     RTL_LOGFILE_CONTEXT( aLog, "::SplashScreen::setValue (lo119109)" );
156     RTL_LOGFILE_CONTEXT_TRACE1( aLog, "value=%d", nValue );
157 
158     ::vos::OGuard aSolarGuard( Application::GetSolarMutex() );
159     if (_bVisible && !_bProgressEnd) {
160         if ( _eBitmapMode == BM_FULLSCREEN )
161             ShowFullScreenMode( sal_True );
162         Show();
163         if (nValue >= _iMax) _iProgress = _iMax;
164 	else _iProgress = nValue;
165 	updateStatus();
166     }
167 }
168 
169 // XInitialize
170 void SAL_CALL
171 SplashScreen::initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any>& aArguments )
172 	throw (RuntimeException)
173 {
174 	::osl::ClearableMutexGuard	aGuard(	_aMutex );
175 	if (aArguments.getLength() > 0)
176     {
177         aArguments[0] >>= _bVisible;
178         if (aArguments.getLength() > 1 )
179             aArguments[1] >>= _sAppName;
180 
181         // start to determine bitmap and all other required value
182         initBitmap();
183 	    Size aSize = _aIntroBmp.GetSizePixel();
184 	    SetOutputSizePixel( aSize );
185         _vdev.SetOutputSizePixel( aSize );
186 	    _height = aSize.Height();
187 	    _width = aSize.Width();
188         if (_width > 500)
189         {
190             Point xtopleft(212,216);
191             if ( NOT_LOADED == _tlx || NOT_LOADED == _tly )
192             {
193                 _tlx = xtopleft.X();    // top-left x
194                 _tly = xtopleft.Y();    // top-left y
195             }
196             if ( NOT_LOADED == _barwidth )
197                 _barwidth = 263;
198             if ( NOT_LOADED == _barheight )
199                 _barheight = 8;
200             if (( _eBitmapMode == BM_FULLSCREEN ) &&
201                 _bFullScreenSplash )
202             {
203                 if( ( _fXPos >= 0.0 ) && ( _fYPos >= 0.0 ))
204                 {
205                     _tlx = sal_Int32( double( aSize.Width() ) * _fXPos );
206                     _tly = sal_Int32( double( aSize.Height() ) * _fYPos );
207                 }
208                 if ( _fWidth >= 0.0 )
209                     _barwidth  = sal_Int32( double( aSize.Width() ) * _fWidth );
210                 if ( _fHeight >= 0.0 )
211                     _barheight = sal_Int32( double( aSize.Width() ) * _fHeight );
212             }
213         }
214         else
215         {
216             if ( NOT_LOADED == _barwidth )
217                 _barwidth  = _width - (2 * _xoffset);
218             if ( NOT_LOADED == _barheight )
219                 _barheight = 6;
220             if ( NOT_LOADED == _tlx || NOT_LOADED == _tly )
221             {
222                 _tlx = _xoffset;           // top-left x
223                 _tly = _height - _yoffset; // top-left y
224             }
225         }
226 
227         if ( sal::static_int_cast< ColorData >(NOT_LOADED) ==
228              _cProgressFrameColor.GetColor() )
229             _cProgressFrameColor = Color( COL_LIGHTGRAY );
230 
231         if ( sal::static_int_cast< ColorData >(NOT_LOADED) ==
232              _cProgressBarColor.GetColor() )
233         {
234             // progress bar: new color only for big bitmap format
235             if ( _width > 500 )
236                 _cProgressBarColor = Color( 157, 202, 18 );
237             else
238                 _cProgressBarColor = Color( COL_BLUE );
239         }
240 
241         Application::AddEventListener(
242 		    LINK( this, SplashScreen, AppEventListenerHdl ) );
243 
244         SetBackgroundBitmap( _aIntroBmp );
245     }
246 }
247 
248 void SplashScreen::updateStatus()
249 {
250 	if (!_bVisible || _bProgressEnd) return;
251 	if (!_bPaintProgress) _bPaintProgress = sal_True;
252 	//_bPaintBitmap=sal_False;
253 	Paint(Rectangle());
254 	//_bPaintBitmap=sal_True;
255     Flush();
256 }
257 
258 // internal private methods
259 IMPL_LINK( SplashScreen, AppEventListenerHdl, VclWindowEvent *, inEvent )
260 {
261 	if ( inEvent != 0 )
262 	{
263         // Paint( Rectangle() );
264 		switch ( inEvent->GetId() )
265 		{
266 			case VCLEVENT_WINDOW_SHOW:
267 				Paint( Rectangle() );
268 				break;
269 			default:
270 				break;
271 		}
272 	}
273 	return 0;
274 }
275 
276 // Read keys from edition/edition.ini or soffice{.ini|rc}:
277 OUString implReadBootstrapKey( const OUString& _rKey )
278 {
279     OUString sValue(
280         rtl::OUString(
281             RTL_CONSTASCII_USTRINGPARAM(
282                 "${.override:${BRAND_BASE_DIR}/program/edition/edition.ini:")) +
283         _rKey + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("}")));
284     rtl::Bootstrap::expandMacros(sValue);
285     return sValue;
286 }
287 
288 void SplashScreen::loadConfig()
289 {
290     _bShowLogo = !implReadBootstrapKey(
291         rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Logo"))).
292         equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("0"));
293 
294     OUString sProgressFrameColor = implReadBootstrapKey(
295         OUString( RTL_CONSTASCII_USTRINGPARAM( "ProgressFrameColor" ) ) );
296     OUString sProgressBarColor = implReadBootstrapKey(
297         OUString( RTL_CONSTASCII_USTRINGPARAM( "ProgressBarColor" ) ) );
298     OUString sSize = implReadBootstrapKey(
299         OUString( RTL_CONSTASCII_USTRINGPARAM( "ProgressSize" ) ) );
300     OUString sPosition = implReadBootstrapKey(
301         OUString( RTL_CONSTASCII_USTRINGPARAM( "ProgressPosition" ) ) );
302     OUString sFullScreenSplash = implReadBootstrapKey(
303         OUString( RTL_CONSTASCII_USTRINGPARAM( "FullScreenSplash" ) ) );
304     OUString sNativeProgress = implReadBootstrapKey(
305         OUString( RTL_CONSTASCII_USTRINGPARAM( "NativeProgress" ) ) );
306 
307 
308     // Determine full screen splash mode
309     _bFullScreenSplash = (( sFullScreenSplash.getLength() > 0 ) &&
310                           ( !sFullScreenSplash.equalsAsciiL( "0", 1 )));
311 
312     // Try to retrieve the relative values for the progress bar. The current
313     // schema uses the screen ratio to retrieve the associated values.
314     if ( _bFullScreenSplash )
315         determineProgressRatioValues( _fXPos, _fYPos, _fWidth, _fHeight );
316 
317     if ( sProgressFrameColor.getLength() )
318     {
319         sal_uInt8 nRed = 0;
320         sal_uInt8 nGreen = 0;
321         sal_uInt8 nBlue = 0;
322         sal_Int32 idx = 0;
323         sal_Int32 temp = sProgressFrameColor.getToken( 0, ',', idx ).toInt32();
324         if ( idx != -1 )
325         {
326             nRed = static_cast< sal_uInt8 >( temp );
327             temp = sProgressFrameColor.getToken( 0, ',', idx ).toInt32();
328         }
329         if ( idx != -1 )
330         {
331             nGreen = static_cast< sal_uInt8 >( temp );
332             nBlue = static_cast< sal_uInt8 >( sProgressFrameColor.getToken( 0, ',', idx ).toInt32() );
333             _cProgressFrameColor = Color( nRed, nGreen, nBlue );
334         }
335     }
336 
337     if ( sProgressBarColor.getLength() )
338     {
339         sal_uInt8 nRed = 0;
340         sal_uInt8 nGreen = 0;
341         sal_uInt8 nBlue = 0;
342         sal_Int32 idx = 0;
343         sal_Int32 temp = sProgressBarColor.getToken( 0, ',', idx ).toInt32();
344         if ( idx != -1 )
345         {
346             nRed = static_cast< sal_uInt8 >( temp );
347             temp = sProgressBarColor.getToken( 0, ',', idx ).toInt32();
348         }
349         if ( idx != -1 )
350         {
351             nGreen = static_cast< sal_uInt8 >( temp );
352             nBlue = static_cast< sal_uInt8 >( sProgressBarColor.getToken( 0, ',', idx ).toInt32() );
353             _cProgressBarColor = Color( nRed, nGreen, nBlue );
354         }
355     }
356 
357     if( sNativeProgress.getLength() )
358     {
359         _bNativeProgress = sNativeProgress.toBoolean();
360     }
361 
362     if ( sSize.getLength() )
363     {
364         sal_Int32 idx = 0;
365         sal_Int32 temp = sSize.getToken( 0, ',', idx ).toInt32();
366         if ( idx != -1 )
367         {
368             _barwidth = temp;
369             _barheight = sSize.getToken( 0, ',', idx ).toInt32();
370         }
371     }
372 
373     if ( _barheight >= 10 )
374         _barspace = 3;  // more space between frame and bar
375 
376     if ( sPosition.getLength() )
377     {
378         sal_Int32 idx = 0;
379         sal_Int32 temp = sPosition.getToken( 0, ',', idx ).toInt32();
380         if ( idx != -1 )
381         {
382             _tlx = temp;
383             _tly = sPosition.getToken( 0, ',', idx ).toInt32();
384         }
385     }
386 }
387 
388 void SplashScreen::initBitmap()
389 {
390     if ( _bShowLogo )
391     {
392         OUString sExecutePath;
393         ::rtl::Bootstrap::get(
394             OUString( RTL_CONSTASCII_USTRINGPARAM( "BRAND_BASE_DIR" ) ),
395             sExecutePath );
396         sExecutePath += OUString( RTL_CONSTASCII_USTRINGPARAM( "/program/" ) );
397 
398         bool haveBitmap = false;
399 
400         // Try all bitmaps in INTRO_BITMAP_NAMES
401         sal_Int32 nIndex = 0;
402         OUString  aIntroBitmapFiles( RTL_CONSTASCII_USTRINGPARAM( INTRO_BITMAP_STRINGLIST ));
403         do
404         {
405             haveBitmap = loadBitmap( sExecutePath, aIntroBitmapFiles.getToken( 0, ',', nIndex ) );
406         }
407         while ( !haveBitmap && ( nIndex >= 0 ) );
408 
409         if (!haveBitmap) {
410             rtl::OUString edition(
411                 rtl::OUString(
412                     RTL_CONSTASCII_USTRINGPARAM(
413                         "${BRAND_BASE_DIR}/program/edition")));
414             rtl::Bootstrap::expandMacros(edition);
415             haveBitmap = findBitmap(edition);
416         }
417         if (!haveBitmap) {
418             findBitmap(sExecutePath);
419         }
420     }
421 }
422 
423 bool SplashScreen::loadBitmap(
424     rtl::OUString const & path, const rtl::OUString &rBmpFileName )
425 {
426     if ( rBmpFileName.getLength() == 0 )
427         return false;
428 
429     INetURLObject aObj( path, INET_PROT_FILE );
430     aObj.insertName( rBmpFileName );
431 
432     SvFileStream aStrm( aObj.PathToFileName(), STREAM_STD_READ );
433     if ( !aStrm.GetError() )
434     {
435         // Use graphic class to also support more graphic formats (bmp,png,...)
436         Graphic aGraphic;
437 
438         GraphicFilter* pGF = GraphicFilter::GetGraphicFilter();
439         pGF->ImportGraphic( aGraphic, String(), aStrm, GRFILTER_FORMAT_DONTKNOW );
440 
441         // Default case, we load the intro bitmap from a seperate file
442         // (e.g. staroffice_intro.bmp or starsuite_intro.bmp)
443         _aIntroBmp = aGraphic.GetBitmapEx();
444         return true;
445     }
446 
447     return false;
448 }
449 
450 bool SplashScreen::findBitmap(rtl::OUString const & path) {
451     bool haveBitmap = false;
452     if ( _bFullScreenSplash )
453     {
454         haveBitmap = findScreenBitmap(path);
455         if ( haveBitmap )
456             _eBitmapMode = BM_FULLSCREEN;
457         else
458             haveBitmap = findAppBitmap(path);
459     }
460     if ( !haveBitmap )
461     {
462         haveBitmap = loadBitmap(
463             path, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("intro.png")));
464         if ( !haveBitmap )
465             haveBitmap = loadBitmap(
466                 path, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("intro.bmp")));
467     }
468 
469     return haveBitmap;
470 }
471 
472 bool SplashScreen::findScreenBitmap(rtl::OUString const & path)
473 {
474     sal_Int32 nWidth( 0 );
475     sal_Int32 nHeight( 0 );
476 
477     // determine desktop resolution
478     sal_uInt32 nCount = Application::GetScreenCount();
479     if ( nCount > 0 )
480     {
481         // retrieve size from first screen
482         Rectangle aScreenArea = Application::GetScreenPosSizePixel((unsigned int)0);
483         nWidth  = aScreenArea.GetWidth();
484         nHeight = aScreenArea.GetHeight();
485     }
486 
487     // create file name from screen resolution information
488     OUStringBuffer aStrBuf( 128 );
489     aStrBuf.appendAscii( "intro_" );
490     if ( _sAppName.getLength() > 0 )
491     {
492         aStrBuf.append( _sAppName );
493         aStrBuf.appendAscii( "_" );
494     }
495     aStrBuf.append( OUString::valueOf( nWidth ));
496     aStrBuf.appendAscii( "x" );
497     aStrBuf.append( OUString::valueOf( nHeight ));
498 
499     OUString aRootIntroFileName = aStrBuf.makeStringAndClear();
500     OUString aBmpFileName       = aRootIntroFileName + OUString::createFromAscii(".png");
501 
502     bool haveBitmap = loadBitmap( path, aBmpFileName );
503     if ( !haveBitmap )
504     {
505         aBmpFileName = aRootIntroFileName + OUString::createFromAscii(".bmp");
506         haveBitmap   = loadBitmap( path, aBmpFileName );
507     }
508 
509     if ( !haveBitmap )
510     {
511         aStrBuf.appendAscii( "intro_" );
512         aStrBuf.appendAscii( "_" );
513         aStrBuf.append( OUString::valueOf( nWidth ));
514         aStrBuf.appendAscii( "x" );
515         aStrBuf.append( OUString::valueOf( nHeight ));
516 
517         aRootIntroFileName = aStrBuf.makeStringAndClear();
518         aBmpFileName = aRootIntroFileName + OUString::createFromAscii(".png");
519 
520         haveBitmap = loadBitmap( path, aBmpFileName );
521         if ( !haveBitmap )
522         {
523             aBmpFileName = aRootIntroFileName + OUString::createFromAscii(".bmp");
524             haveBitmap   = loadBitmap( path, aBmpFileName );
525         }
526     }
527     return haveBitmap;
528 }
529 
530 bool SplashScreen::findAppBitmap(rtl::OUString const & path)
531 {
532     bool haveBitmap = false;
533 
534     if ( _sAppName.getLength() > 0 )
535     {
536         OUStringBuffer aStrBuf( 128 );
537         aStrBuf.appendAscii( "intro_" );
538         aStrBuf.appendAscii( "_" );
539         aStrBuf.append( _sAppName );
540 
541         OUString aRootIntroFileName = aStrBuf.makeStringAndClear();
542 
543         OUString aBmpFileName = aRootIntroFileName + OUString::createFromAscii( ".png" );
544         haveBitmap = loadBitmap( path, aBmpFileName );
545         if ( !haveBitmap )
546         {
547             aBmpFileName = aRootIntroFileName + OUString::createFromAscii( ".bmp" );
548             haveBitmap = loadBitmap( path, aBmpFileName );
549         }
550     }
551     return haveBitmap;
552 }
553 
554 void SplashScreen::determineProgressRatioValues(
555     double& rXRelPos, double& rYRelPos,
556     double& rRelWidth, double& rRelHeight )
557 {
558     sal_Int32 nWidth( 0 );
559     sal_Int32 nHeight( 0 );
560     sal_Int32 nScreenRatio( 0 );
561 
562     // determine desktop resolution
563     sal_uInt32 nCount = Application::GetScreenCount();
564     if ( nCount > 0 )
565     {
566         // retrieve size from first screen
567         Rectangle aScreenArea = Application::GetScreenPosSizePixel((unsigned int)0);
568         nWidth  = aScreenArea.GetWidth();
569         nHeight = aScreenArea.GetHeight();
570         nScreenRatio  = sal_Int32( math::round( double( nWidth ) / double( nHeight ), 2 ) * 100 );
571     }
572 
573     char szFullScreenProgressRatio[] = "FullScreenProgressRatio0";
574     char szFullScreenProgressPos[]   = "FullScreenProgressPos0";
575     char szFullScreenProgressSize[]  = "FullScreenProgressSize0";
576     for ( sal_Int32 i = 0; i <= 9; i++ )
577     {
578         char cNum = '0' + char( i );
579         szFullScreenProgressRatio[23] = cNum;
580         szFullScreenProgressPos[21]   = cNum;
581         szFullScreenProgressSize[22]  = cNum;
582 
583         OUString sFullScreenProgressRatio = implReadBootstrapKey(
584             OUString::createFromAscii( szFullScreenProgressRatio ) );
585 
586         if ( sFullScreenProgressRatio.getLength() > 0 )
587         {
588             double fRatio = sFullScreenProgressRatio.toDouble();
589             sal_Int32 nRatio = sal_Int32( math::round( fRatio, 2 ) * 100 );
590             if ( nRatio == nScreenRatio )
591             {
592                 OUString sFullScreenProgressPos = implReadBootstrapKey(
593                     OUString::createFromAscii( szFullScreenProgressPos ) );
594                 OUString sFullScreenProgressSize = implReadBootstrapKey(
595                     OUString::createFromAscii( szFullScreenProgressSize ) );
596 
597                 if ( sFullScreenProgressPos.getLength() )
598                 {
599                     sal_Int32 idx = 0;
600                     double temp = sFullScreenProgressPos.getToken( 0, ',', idx ).toDouble();
601                     if ( idx != -1 )
602                     {
603                         rXRelPos = temp;
604                         rYRelPos = sFullScreenProgressPos.getToken( 0, ',', idx ).toDouble();
605                     }
606                 }
607 
608                 if ( sFullScreenProgressSize.getLength() )
609                 {
610                     sal_Int32 idx = 0;
611                     double temp = sFullScreenProgressSize.getToken( 0, ',', idx ).toDouble();
612                     if ( idx != -1 )
613                     {
614                         rRelWidth  = temp;
615                         rRelHeight = sFullScreenProgressSize.getToken( 0, ',', idx ).toDouble();
616                     }
617                 }
618             }
619         }
620         else
621             break;
622     }
623 }
624 
625 void SplashScreen::Paint( const Rectangle&)
626 {
627 	if(!_bVisible) return;
628 
629     //native drawing
630     sal_Bool bNativeOK = sal_False;
631 
632     // in case of native controls we need to draw directly to the window
633     if( _bNativeProgress && IsNativeControlSupported( CTRL_INTROPROGRESS, PART_ENTIRE_CONTROL ) )
634     {
635         DrawBitmapEx( Point(), _aIntroBmp );
636 
637         ImplControlValue aValue( _iProgress * _barwidth / _iMax);
638         Rectangle aDrawRect( Point(_tlx, _tly), Size( _barwidth, _barheight ) );
639         Rectangle aNativeControlRegion, aNativeContentRegion;
640 
641         if( GetNativeControlRegion( CTRL_INTROPROGRESS, PART_ENTIRE_CONTROL, aDrawRect,
642                                              CTRL_STATE_ENABLED, aValue, rtl::OUString(),
643                                              aNativeControlRegion, aNativeContentRegion ) )
644         {
645               long nProgressHeight = aNativeControlRegion.GetHeight();
646               aDrawRect.Top() -= (nProgressHeight - _barheight)/2;
647               aDrawRect.Bottom() += (nProgressHeight - _barheight)/2;
648         }
649 
650         if( (bNativeOK = DrawNativeControl( CTRL_INTROPROGRESS, PART_ENTIRE_CONTROL, aDrawRect,
651                                             CTRL_STATE_ENABLED, aValue, _sProgressText )) != sal_False )
652         {
653             return;
654         }
655     }
656     //non native drawing
657 	// draw bitmap
658 	if (_bPaintBitmap)
659 		_vdev.DrawBitmapEx( Point(), _aIntroBmp );
660 
661 	if (_bPaintProgress) {
662 		// draw progress...
663 		long length = (_iProgress * _barwidth / _iMax) - (2 * _barspace);
664 		if (length < 0) length = 0;
665 
666 		// border
667 		_vdev.SetFillColor();
668 		_vdev.SetLineColor( _cProgressFrameColor );
669 		_vdev.DrawRect(Rectangle(_tlx, _tly, _tlx+_barwidth, _tly+_barheight));
670 		_vdev.SetFillColor( _cProgressBarColor );
671 		_vdev.SetLineColor();
672 		_vdev.DrawRect(Rectangle(_tlx+_barspace, _tly+_barspace, _tlx+_barspace+length, _tly+_barheight-_barspace));
673         _vdev.DrawText( Rectangle(_tlx, _tly+_barheight+5, _tlx+_barwidth, _tly+_barheight+5+20), _sProgressText, TEXT_DRAW_CENTER );
674 	}
675     Size aSize =  GetOutputSizePixel();
676     Size bSize =  _vdev.GetOutputSizePixel();
677     //_vdev.Flush();
678     //_vdev.DrawOutDev(Point(), GetOutputSize(), Point(), GetOutputSize(), *((IntroWindow*)this) );
679     DrawOutDev(Point(), GetOutputSizePixel(), Point(), _vdev.GetOutputSizePixel(), _vdev );
680 	//Flush();
681 }
682 
683 
684 // get service instance...
685 SplashScreen *SplashScreen::_pINSTANCE = NULL;
686 osl::Mutex SplashScreen::_aMutex;
687 
688 Reference< XInterface > SplashScreen::getInstance(const Reference< XMultiServiceFactory >& rSMgr)
689 {
690 	if ( _pINSTANCE == 0 )
691 	{
692 		osl::MutexGuard guard(_aMutex);
693 		if (_pINSTANCE == 0)
694 			return (XComponent*)new SplashScreen(rSMgr);
695 	}
696 
697 	return (XComponent*)0;
698 }
699 
700 // static service info...
701 const char* SplashScreen::interfaces[] =
702 {
703     "com.sun.star.task.XStartusIndicator",
704     "com.sun.star.lang.XInitialization",
705     NULL,
706 };
707 const sal_Char *SplashScreen::serviceName = "com.sun.star.office.SplashScreen";
708 const sal_Char *SplashScreen::implementationName = "com.sun.star.office.comp.SplashScreen";
709 const sal_Char *SplashScreen::supportedServiceNames[] = {"com.sun.star.office.SplashScreen", NULL};
710 
711 }
712