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 : #include <vcl/outdev.hxx>
21 : #include <vcl/virdev.hxx>
22 : #include <vcl/window.hxx>
23 :
24 : #include <wall2.hxx>
25 :
26 24158 : void OutputDevice::DrawWallpaper( const Rectangle& rRect,
27 : const Wallpaper& rWallpaper )
28 : {
29 24158 : assert_if_double_buffered_window();
30 :
31 24158 : if ( mpMetaFile )
32 3757 : mpMetaFile->AddAction( new MetaWallpaperAction( rRect, rWallpaper ) );
33 :
34 24158 : if ( !IsDeviceOutputNecessary() || ImplIsRecordLayout() )
35 24158 : return;
36 :
37 24158 : if ( rWallpaper.GetStyle() != WALLPAPER_NULL )
38 : {
39 24011 : Rectangle aRect = LogicToPixel( rRect );
40 24011 : aRect.Justify();
41 :
42 24011 : if ( !aRect.IsEmpty() )
43 : {
44 47958 : DrawWallpaper( aRect.Left(), aRect.Top(), aRect.GetWidth(), aRect.GetHeight(),
45 71937 : rWallpaper );
46 : }
47 : }
48 :
49 24158 : if( mpAlphaVDev )
50 3757 : mpAlphaVDev->DrawWallpaper( rRect, rWallpaper );
51 : }
52 :
53 364819 : void OutputDevice::DrawWallpaper( long nX, long nY,
54 : long nWidth, long nHeight,
55 : const Wallpaper& rWallpaper )
56 : {
57 364819 : assert_if_double_buffered_window();
58 :
59 364819 : if( rWallpaper.IsBitmap() )
60 2 : DrawBitmapWallpaper( nX, nY, nWidth, nHeight, rWallpaper );
61 364817 : else if( rWallpaper.IsGradient() )
62 1227 : DrawGradientWallpaper( nX, nY, nWidth, nHeight, rWallpaper );
63 : else
64 363590 : DrawColorWallpaper( nX, nY, nWidth, nHeight, rWallpaper );
65 364819 : }
66 :
67 363595 : void OutputDevice::DrawColorWallpaper( long nX, long nY,
68 : long nWidth, long nHeight,
69 : const Wallpaper& rWallpaper )
70 : {
71 363595 : assert_if_double_buffered_window();
72 :
73 : // draw wallpaper without border
74 363595 : Color aOldLineColor = GetLineColor();
75 363595 : Color aOldFillColor = GetFillColor();
76 363595 : SetLineColor();
77 363595 : SetFillColor( rWallpaper.GetColor() );
78 :
79 363595 : bool bMap = mbMap;
80 363595 : EnableMapMode( false );
81 363595 : DrawRect( Rectangle( Point( nX, nY ), Size( nWidth, nHeight ) ) );
82 363595 : SetLineColor( aOldLineColor );
83 363595 : SetFillColor( aOldFillColor );
84 363595 : EnableMapMode( bMap );
85 363595 : }
86 :
87 242085 : void OutputDevice::Erase()
88 : {
89 242085 : if ( !IsDeviceOutputNecessary() || ImplIsRecordLayout() )
90 242085 : return;
91 :
92 242085 : if ( mbBackground )
93 : {
94 242046 : RasterOp eRasterOp = GetRasterOp();
95 242046 : if ( eRasterOp != ROP_OVERPAINT )
96 0 : SetRasterOp( ROP_OVERPAINT );
97 242046 : DrawWallpaper( 0, 0, mnOutWidth, mnOutHeight, maBackground );
98 242046 : if ( eRasterOp != ROP_OVERPAINT )
99 0 : SetRasterOp( eRasterOp );
100 : }
101 :
102 242085 : if( mpAlphaVDev )
103 20 : mpAlphaVDev->Erase();
104 : }
105 :
106 2 : void OutputDevice::DrawBitmapWallpaper( long nX, long nY,
107 : long nWidth, long nHeight,
108 : const Wallpaper& rWallpaper )
109 : {
110 2 : assert_if_double_buffered_window();
111 :
112 2 : BitmapEx aBmpEx;
113 2 : const BitmapEx* pCached = rWallpaper.ImplGetImpWallpaper()->ImplGetCachedBitmap();
114 2 : Point aPos;
115 2 : Size aSize;
116 2 : GDIMetaFile* pOldMetaFile = mpMetaFile;
117 2 : const WallpaperStyle eStyle = rWallpaper.GetStyle();
118 2 : const bool bOldMap = mbMap;
119 2 : bool bDrawn = false;
120 2 : bool bDrawGradientBackground = false;
121 2 : bool bDrawColorBackground = false;
122 :
123 2 : if( pCached )
124 1 : aBmpEx = *pCached;
125 : else
126 1 : aBmpEx = rWallpaper.GetBitmap();
127 :
128 2 : const long nBmpWidth = aBmpEx.GetSizePixel().Width();
129 2 : const long nBmpHeight = aBmpEx.GetSizePixel().Height();
130 2 : const bool bTransparent = aBmpEx.IsTransparent();
131 :
132 : // draw background
133 2 : if( bTransparent )
134 : {
135 1 : if( rWallpaper.IsGradient() )
136 0 : bDrawGradientBackground = true;
137 : else
138 : {
139 1 : if( !pCached && !rWallpaper.GetColor().GetTransparency() )
140 : {
141 1 : ScopedVclPtrInstance< VirtualDevice > aVDev( *this );
142 1 : aVDev->SetBackground( rWallpaper.GetColor() );
143 1 : aVDev->SetOutputSizePixel( Size( nBmpWidth, nBmpHeight ) );
144 1 : aVDev->DrawBitmapEx( Point(), aBmpEx );
145 1 : aBmpEx = aVDev->GetBitmap( Point(), aVDev->GetOutputSizePixel() );
146 : }
147 :
148 1 : bDrawColorBackground = true;
149 : }
150 : }
151 1 : else if( eStyle != WALLPAPER_TILE && eStyle != WALLPAPER_SCALE )
152 : {
153 1 : if( rWallpaper.IsGradient() )
154 0 : bDrawGradientBackground = true;
155 : else
156 1 : bDrawColorBackground = true;
157 : }
158 :
159 : // background of bitmap?
160 2 : if( bDrawGradientBackground )
161 0 : DrawGradientWallpaper( nX, nY, nWidth, nHeight, rWallpaper );
162 2 : else if( bDrawColorBackground && bTransparent )
163 : {
164 1 : DrawColorWallpaper( nX, nY, nWidth, nHeight, rWallpaper );
165 1 : bDrawColorBackground = false;
166 : }
167 :
168 : // calc pos and size
169 2 : if( rWallpaper.IsRect() )
170 : {
171 0 : const Rectangle aBound( LogicToPixel( rWallpaper.GetRect() ) );
172 0 : aPos = aBound.TopLeft();
173 0 : aSize = aBound.GetSize();
174 : }
175 : else
176 : {
177 2 : aPos = Point( 0, 0 );
178 2 : aSize = Size( mnOutWidth, mnOutHeight );
179 : }
180 :
181 2 : mpMetaFile = NULL;
182 2 : EnableMapMode( false );
183 2 : Push( PushFlags::CLIPREGION );
184 2 : IntersectClipRegion( Rectangle( Point( nX, nY ), Size( nWidth, nHeight ) ) );
185 :
186 2 : switch( eStyle )
187 : {
188 : case( WALLPAPER_SCALE ):
189 0 : if( !pCached || ( pCached->GetSizePixel() != aSize ) )
190 : {
191 0 : if( pCached )
192 0 : rWallpaper.ImplGetImpWallpaper()->ImplReleaseCachedBitmap();
193 :
194 0 : aBmpEx = rWallpaper.GetBitmap();
195 0 : aBmpEx.Scale( aSize );
196 0 : aBmpEx = BitmapEx( aBmpEx.GetBitmap().CreateDisplayBitmap( this ), aBmpEx.GetMask() );
197 : }
198 0 : break;
199 :
200 : case( WALLPAPER_TOPLEFT ):
201 0 : break;
202 :
203 : case( WALLPAPER_TOP ):
204 0 : aPos.X() += ( aSize.Width() - nBmpWidth ) >> 1;
205 0 : break;
206 :
207 : case( WALLPAPER_TOPRIGHT ):
208 0 : aPos.X() += ( aSize.Width() - nBmpWidth );
209 0 : break;
210 :
211 : case( WALLPAPER_LEFT ):
212 0 : aPos.Y() += ( aSize.Height() - nBmpHeight ) >> 1;
213 0 : break;
214 :
215 : case( WALLPAPER_CENTER ):
216 0 : aPos.X() += ( aSize.Width() - nBmpWidth ) >> 1;
217 0 : aPos.Y() += ( aSize.Height() - nBmpHeight ) >> 1;
218 0 : break;
219 :
220 : case( WALLPAPER_RIGHT ):
221 0 : aPos.X() += ( aSize.Width() - nBmpWidth );
222 0 : aPos.Y() += ( aSize.Height() - nBmpHeight ) >> 1;
223 0 : break;
224 :
225 : case( WALLPAPER_BOTTOMLEFT ):
226 0 : aPos.Y() += ( aSize.Height() - nBmpHeight );
227 0 : break;
228 :
229 : case( WALLPAPER_BOTTOM ):
230 0 : aPos.X() += ( aSize.Width() - nBmpWidth ) >> 1;
231 0 : aPos.Y() += ( aSize.Height() - nBmpHeight );
232 0 : break;
233 :
234 : case( WALLPAPER_BOTTOMRIGHT ):
235 2 : aPos.X() += ( aSize.Width() - nBmpWidth );
236 2 : aPos.Y() += ( aSize.Height() - nBmpHeight );
237 2 : break;
238 :
239 : default:
240 : {
241 0 : const long nRight = nX + nWidth - 1L;
242 0 : const long nBottom = nY + nHeight - 1L;
243 : long nFirstX;
244 : long nFirstY;
245 :
246 0 : if( eStyle == WALLPAPER_TILE )
247 : {
248 0 : nFirstX = aPos.X();
249 0 : nFirstY = aPos.Y();
250 : }
251 : else
252 : {
253 0 : nFirstX = aPos.X() + ( ( aSize.Width() - nBmpWidth ) >> 1 );
254 0 : nFirstY = aPos.Y() + ( ( aSize.Height() - nBmpHeight ) >> 1 );
255 : }
256 :
257 0 : const long nOffX = ( nFirstX - nX ) % nBmpWidth;
258 0 : const long nOffY = ( nFirstY - nY ) % nBmpHeight;
259 0 : long nStartX = nX + nOffX;
260 0 : long nStartY = nY + nOffY;
261 :
262 0 : if( nOffX > 0L )
263 0 : nStartX -= nBmpWidth;
264 :
265 0 : if( nOffY > 0L )
266 0 : nStartY -= nBmpHeight;
267 :
268 0 : for( long nBmpY = nStartY; nBmpY <= nBottom; nBmpY += nBmpHeight )
269 : {
270 0 : for( long nBmpX = nStartX; nBmpX <= nRight; nBmpX += nBmpWidth )
271 : {
272 0 : DrawBitmapEx( Point( nBmpX, nBmpY ), aBmpEx );
273 : }
274 : }
275 0 : bDrawn = true;
276 : }
277 0 : break;
278 : }
279 :
280 2 : if( !bDrawn )
281 : {
282 : // optimized for non-transparent bitmaps
283 2 : if( bDrawColorBackground )
284 : {
285 1 : const Size aBmpSize( aBmpEx.GetSizePixel() );
286 1 : const Point aTmpPoint;
287 1 : const Rectangle aOutRect( aTmpPoint, GetOutputSizePixel() );
288 1 : const Rectangle aColRect( Point( nX, nY ), Size( nWidth, nHeight ) );
289 1 : Rectangle aWorkRect;
290 :
291 1 : aWorkRect = Rectangle( 0, 0, aOutRect.Right(), aPos.Y() - 1L );
292 1 : aWorkRect.Justify();
293 1 : aWorkRect.Intersection( aColRect );
294 1 : if( !aWorkRect.IsEmpty() )
295 : {
296 2 : DrawColorWallpaper( aWorkRect.Left(), aWorkRect.Top(),
297 : aWorkRect.GetWidth(), aWorkRect.GetHeight(),
298 3 : rWallpaper );
299 : }
300 :
301 1 : aWorkRect = Rectangle( 0, aPos.Y(), aPos.X() - 1L, aPos.Y() + aBmpSize.Height() - 1L );
302 1 : aWorkRect.Justify();
303 1 : aWorkRect.Intersection( aColRect );
304 1 : if( !aWorkRect.IsEmpty() )
305 : {
306 2 : DrawColorWallpaper( aWorkRect.Left(), aWorkRect.Top(),
307 : aWorkRect.GetWidth(), aWorkRect.GetHeight(),
308 3 : rWallpaper );
309 : }
310 :
311 3 : aWorkRect = Rectangle( aPos.X() + aBmpSize.Width(), aPos.Y(),
312 4 : aOutRect.Right(), aPos.Y() + aBmpSize.Height() - 1L );
313 1 : aWorkRect.Justify();
314 1 : aWorkRect.Intersection( aColRect );
315 1 : if( !aWorkRect.IsEmpty() )
316 : {
317 2 : DrawColorWallpaper( aWorkRect.Left(), aWorkRect.Top(),
318 : aWorkRect.GetWidth(), aWorkRect.GetHeight(),
319 3 : rWallpaper );
320 : }
321 :
322 2 : aWorkRect = Rectangle( 0, aPos.Y() + aBmpSize.Height(),
323 3 : aOutRect.Right(), aOutRect.Bottom() );
324 1 : aWorkRect.Justify();
325 1 : aWorkRect.Intersection( aColRect );
326 1 : if( !aWorkRect.IsEmpty() )
327 : {
328 2 : DrawColorWallpaper( aWorkRect.Left(), aWorkRect.Top(),
329 : aWorkRect.GetWidth(), aWorkRect.GetHeight(),
330 3 : rWallpaper );
331 : }
332 : }
333 :
334 2 : DrawBitmapEx( aPos, aBmpEx );
335 : }
336 :
337 2 : rWallpaper.ImplGetImpWallpaper()->ImplSetCachedBitmap( aBmpEx );
338 :
339 2 : Pop();
340 2 : EnableMapMode( bOldMap );
341 2 : mpMetaFile = pOldMetaFile;
342 2 : }
343 :
344 1227 : void OutputDevice::DrawGradientWallpaper( long nX, long nY,
345 : long nWidth, long nHeight,
346 : const Wallpaper& rWallpaper )
347 : {
348 1227 : assert_if_double_buffered_window();
349 :
350 1227 : Rectangle aBound;
351 1227 : GDIMetaFile* pOldMetaFile = mpMetaFile;
352 1227 : const bool bOldMap = mbMap;
353 :
354 1227 : aBound = Rectangle( Point( nX, nY ), Size( nWidth, nHeight ) );
355 :
356 1227 : mpMetaFile = NULL;
357 1227 : EnableMapMode( false );
358 1227 : Push( PushFlags::CLIPREGION );
359 1227 : IntersectClipRegion( Rectangle( Point( nX, nY ), Size( nWidth, nHeight ) ) );
360 :
361 1227 : DrawGradient( aBound, rWallpaper.GetGradient() );
362 :
363 1227 : Pop();
364 1227 : EnableMapMode( bOldMap );
365 1227 : mpMetaFile = pOldMetaFile;
366 1227 : }
367 :
368 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|