LibreOffice Module vcl (master)  1
wallpaper.cxx
Go to the documentation of this file.
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 <cassert>
21 
22 #include <vcl/gdimtf.hxx>
23 #include <vcl/metaact.hxx>
24 #include <vcl/outdev.hxx>
25 #include <vcl/virdev.hxx>
26 
28 {
29  return GetBackground().GetColor();
30 }
31 
33  const Wallpaper& rWallpaper )
34 {
35  assert(!is_double_buffered_window());
36 
37  if ( mpMetaFile )
38  mpMetaFile->AddAction( new MetaWallpaperAction( rRect, rWallpaper ) );
39 
41  return;
42 
43  if ( rWallpaper.GetStyle() != WallpaperStyle::NONE )
44  {
45  tools::Rectangle aRect = LogicToPixel( rRect );
46  aRect.Justify();
47 
48  if ( !aRect.IsEmpty() )
49  {
50  DrawWallpaper( aRect.Left(), aRect.Top(), aRect.GetWidth(), aRect.GetHeight(),
51  rWallpaper );
52  }
53  }
54 
55  if( mpAlphaVDev )
56  mpAlphaVDev->DrawWallpaper( rRect, rWallpaper );
57 }
58 
59 void OutputDevice::DrawWallpaper( long nX, long nY,
60  long nWidth, long nHeight,
61  const Wallpaper& rWallpaper )
62 {
63  assert(!is_double_buffered_window());
64 
65  if( rWallpaper.IsBitmap() )
66  DrawBitmapWallpaper( nX, nY, nWidth, nHeight, rWallpaper );
67  else if( rWallpaper.IsGradient() )
68  DrawGradientWallpaper( nX, nY, nWidth, nHeight, rWallpaper );
69  else
70  DrawColorWallpaper( nX, nY, nWidth, nHeight, rWallpaper );
71 }
72 
73 void OutputDevice::DrawColorWallpaper( long nX, long nY,
74  long nWidth, long nHeight,
75  const Wallpaper& rWallpaper )
76 {
77  assert(!is_double_buffered_window());
78 
79  // draw wallpaper without border
80  Color aOldLineColor = GetLineColor();
81  Color aOldFillColor = GetFillColor();
82  SetLineColor();
83  SetFillColor( rWallpaper.GetColor() );
84 
85  bool bMap = mbMap;
86  EnableMapMode( false );
87  DrawRect( tools::Rectangle( Point( nX, nY ), Size( nWidth, nHeight ) ) );
88  SetLineColor( aOldLineColor );
89  SetFillColor( aOldFillColor );
90  EnableMapMode( bMap );
91 }
92 
94 {
96  return;
97 
98  if ( mbBackground )
99  {
100  RasterOp eRasterOp = GetRasterOp();
101  if ( eRasterOp != RasterOp::OverPaint )
104  if ( eRasterOp != RasterOp::OverPaint )
105  SetRasterOp( eRasterOp );
106  }
107 
108  if( mpAlphaVDev )
109  mpAlphaVDev->Erase();
110 }
111 
112 void OutputDevice::DrawBitmapWallpaper( long nX, long nY,
113  long nWidth, long nHeight,
114  const Wallpaper& rWallpaper )
115 {
116  assert(!is_double_buffered_window());
117 
118  BitmapEx aBmpEx;
119  const BitmapEx* pCached = rWallpaper.ImplGetCachedBitmap();
120  Point aPos;
121  Size aSize;
122  GDIMetaFile* pOldMetaFile = mpMetaFile;
123  const WallpaperStyle eStyle = rWallpaper.GetStyle();
124  const bool bOldMap = mbMap;
125  bool bDrawn = false;
126  bool bDrawGradientBackground = false;
127  bool bDrawColorBackground = false;
128 
129  if( pCached )
130  aBmpEx = *pCached;
131  else
132  aBmpEx = rWallpaper.GetBitmap();
133 
134  const long nBmpWidth = aBmpEx.GetSizePixel().Width();
135  const long nBmpHeight = aBmpEx.GetSizePixel().Height();
136  const bool bTransparent = aBmpEx.IsTransparent();
137 
138  // draw background
139  if( bTransparent )
140  {
141  if( rWallpaper.IsGradient() )
142  bDrawGradientBackground = true;
143  else
144  {
145  if( !pCached && !rWallpaper.GetColor().GetTransparency() )
146  {
148  aVDev->SetBackground( rWallpaper.GetColor() );
149  aVDev->SetOutputSizePixel( Size( nBmpWidth, nBmpHeight ) );
150  aVDev->DrawBitmapEx( Point(), aBmpEx );
151  aBmpEx = aVDev->GetBitmapEx( Point(), aVDev->GetOutputSizePixel() );
152  }
153 
154  bDrawColorBackground = true;
155  }
156  }
157  else if( eStyle != WallpaperStyle::Tile && eStyle != WallpaperStyle::Scale )
158  {
159  if( rWallpaper.IsGradient() )
160  bDrawGradientBackground = true;
161  else
162  bDrawColorBackground = true;
163  }
164 
165  // background of bitmap?
166  if( bDrawGradientBackground )
167  DrawGradientWallpaper( nX, nY, nWidth, nHeight, rWallpaper );
168  else if( bDrawColorBackground && bTransparent )
169  {
170  DrawColorWallpaper( nX, nY, nWidth, nHeight, rWallpaper );
171  bDrawColorBackground = false;
172  }
173 
174  // calc pos and size
175  if( rWallpaper.IsRect() )
176  {
177  const tools::Rectangle aBound( LogicToPixel( rWallpaper.GetRect() ) );
178  aPos = aBound.TopLeft();
179  aSize = aBound.GetSize();
180  }
181  else
182  {
183  aPos = Point( 0, 0 );
184  aSize = Size( nWidth, nHeight );
185  }
186 
187  mpMetaFile = nullptr;
188  EnableMapMode( false );
190  IntersectClipRegion( tools::Rectangle( Point( nX, nY ), Size( nWidth, nHeight ) ) );
191 
192  switch( eStyle )
193  {
195  if( !pCached || ( pCached->GetSizePixel() != aSize ) )
196  {
197  if( pCached )
198  rWallpaper.ImplReleaseCachedBitmap();
199 
200  aBmpEx = rWallpaper.GetBitmap();
201  aBmpEx.Scale( aSize );
202  aBmpEx = BitmapEx( aBmpEx.GetBitmap().CreateDisplayBitmap( this ), aBmpEx.GetMask() );
203  }
204  break;
205 
207  break;
208 
209  case WallpaperStyle::Top:
210  aPos.AdjustX(( aSize.Width() - nBmpWidth ) >> 1 );
211  break;
212 
214  aPos.AdjustX( aSize.Width() - nBmpWidth);
215  break;
216 
218  aPos.AdjustY(( aSize.Height() - nBmpHeight ) >> 1 );
219  break;
220 
222  aPos.AdjustX(( aSize.Width() - nBmpWidth ) >> 1 );
223  aPos.AdjustY(( aSize.Height() - nBmpHeight ) >> 1 );
224  break;
225 
227  aPos.AdjustX(aSize.Width() - nBmpWidth);
228  aPos.AdjustY(( aSize.Height() - nBmpHeight ) >> 1 );
229  break;
230 
232  aPos.AdjustY( aSize.Height() - nBmpHeight );
233  break;
234 
236  aPos.AdjustX(( aSize.Width() - nBmpWidth ) >> 1 );
237  aPos.AdjustY( aSize.Height() - nBmpHeight );
238  break;
239 
241  aPos.AdjustX( aSize.Width() - nBmpWidth );
242  aPos.AdjustY( aSize.Height() - nBmpHeight );
243  break;
244 
245  default:
246  {
247  const long nRight = nX + nWidth - 1;
248  const long nBottom = nY + nHeight - 1;
249  long nFirstX;
250  long nFirstY;
251 
252  if( eStyle == WallpaperStyle::Tile )
253  {
254  nFirstX = aPos.X();
255  nFirstY = aPos.Y();
256  }
257  else
258  {
259  nFirstX = aPos.X() + ( ( aSize.Width() - nBmpWidth ) >> 1 );
260  nFirstY = aPos.Y() + ( ( aSize.Height() - nBmpHeight ) >> 1 );
261  }
262 
263  const long nOffX = ( nFirstX - nX ) % nBmpWidth;
264  const long nOffY = ( nFirstY - nY ) % nBmpHeight;
265  long nStartX = nX + nOffX;
266  long nStartY = nY + nOffY;
267 
268  if( nOffX > 0 )
269  nStartX -= nBmpWidth;
270 
271  if( nOffY > 0 )
272  nStartY -= nBmpHeight;
273 
274  for( long nBmpY = nStartY; nBmpY <= nBottom; nBmpY += nBmpHeight )
275  {
276  for( long nBmpX = nStartX; nBmpX <= nRight; nBmpX += nBmpWidth )
277  {
278  DrawBitmapEx( Point( nBmpX, nBmpY ), aBmpEx );
279  }
280  }
281  bDrawn = true;
282  }
283  break;
284  }
285 
286  if( !bDrawn )
287  {
288  // optimized for non-transparent bitmaps
289  if( bDrawColorBackground )
290  {
291  const Size aBmpSize( aBmpEx.GetSizePixel() );
292  const Point aTmpPoint;
293  const tools::Rectangle aOutRect( aTmpPoint, GetOutputSizePixel() );
294  const tools::Rectangle aColRect( Point( nX, nY ), Size( nWidth, nHeight ) );
295 
296  tools::Rectangle aWorkRect( 0, 0, aOutRect.Right(), aPos.Y() - 1 );
297  aWorkRect.Justify();
298  aWorkRect.Intersection( aColRect );
299  if( !aWorkRect.IsEmpty() )
300  {
301  DrawColorWallpaper( aWorkRect.Left(), aWorkRect.Top(),
302  aWorkRect.GetWidth(), aWorkRect.GetHeight(),
303  rWallpaper );
304  }
305 
306  aWorkRect = tools::Rectangle( 0, aPos.Y(), aPos.X() - 1, aPos.Y() + aBmpSize.Height() - 1 );
307  aWorkRect.Justify();
308  aWorkRect.Intersection( aColRect );
309  if( !aWorkRect.IsEmpty() )
310  {
311  DrawColorWallpaper( aWorkRect.Left(), aWorkRect.Top(),
312  aWorkRect.GetWidth(), aWorkRect.GetHeight(),
313  rWallpaper );
314  }
315 
316  aWorkRect = tools::Rectangle( aPos.X() + aBmpSize.Width(), aPos.Y(),
317  aOutRect.Right(), aPos.Y() + aBmpSize.Height() - 1 );
318  aWorkRect.Justify();
319  aWorkRect.Intersection( aColRect );
320  if( !aWorkRect.IsEmpty() )
321  {
322  DrawColorWallpaper( aWorkRect.Left(), aWorkRect.Top(),
323  aWorkRect.GetWidth(), aWorkRect.GetHeight(),
324  rWallpaper );
325  }
326 
327  aWorkRect = tools::Rectangle( 0, aPos.Y() + aBmpSize.Height(),
328  aOutRect.Right(), aOutRect.Bottom() );
329  aWorkRect.Justify();
330  aWorkRect.Intersection( aColRect );
331  if( !aWorkRect.IsEmpty() )
332  {
333  DrawColorWallpaper( aWorkRect.Left(), aWorkRect.Top(),
334  aWorkRect.GetWidth(), aWorkRect.GetHeight(),
335  rWallpaper );
336  }
337  }
338 
339  DrawBitmapEx( aPos, aBmpEx );
340  }
341 
342  rWallpaper.ImplSetCachedBitmap( aBmpEx );
343 
344  Pop();
345  EnableMapMode( bOldMap );
346  mpMetaFile = pOldMetaFile;
347 }
348 
349 void OutputDevice::DrawGradientWallpaper( long nX, long nY,
350  long nWidth, long nHeight,
351  const Wallpaper& rWallpaper )
352 {
353  assert(!is_double_buffered_window());
354 
355  tools::Rectangle aBound;
356  GDIMetaFile* pOldMetaFile = mpMetaFile;
357  const bool bOldMap = mbMap;
358 
359  aBound = tools::Rectangle( Point( nX, nY ), Size( nWidth, nHeight ) );
360 
361  mpMetaFile = nullptr;
362  EnableMapMode( false );
364  IntersectClipRegion( tools::Rectangle( Point( nX, nY ), Size( nWidth, nHeight ) ) );
365 
366  DrawGradient( aBound, rWallpaper.GetGradient() );
367 
368  Pop();
369  EnableMapMode( bOldMap );
370  mpMetaFile = pOldMetaFile;
371 }
372 
373 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Point TopLeft() const
long Width() const
Bitmap GetMask() const
Definition: bitmapex.cxx:258
long GetWidth() const
const Wallpaper & GetBackground() const
Definition: outdev.hxx:631
long GetHeight() const
SAL_DLLPRIVATE bool ImplIsRecordLayout() const
Definition: outdev.cxx:657
SAL_DLLPRIVATE void ImplReleaseCachedBitmap() const
Definition: wall.cxx:185
long AdjustX(long nHorzMove)
long Height() const
void DrawBitmapEx(const Point &rDestPt, const BitmapEx &rBitmapEx)
This is an overloaded member function, provided for convenience. It differs from the above function o...
bool Scale(const Size &rNewSize, BmpScaleFlag nScaleFlag=BmpScaleFlag::Default)
Scale the bitmap.
Definition: bitmapex.cxx:370
sal_uInt8 GetTransparency() const
SAL_DLLPRIVATE bool is_double_buffered_window() const
void IntersectClipRegion(const tools::Rectangle &rRect)
WallpaperStyle GetStyle() const
Definition: wall.cxx:214
void EnableMapMode(bool bEnable=true)
Definition: map.cxx:647
bool mbMap
Definition: outdev.hxx:376
void DrawWallpaper(const tools::Rectangle &rRect, const Wallpaper &rWallpaper)
Definition: wallpaper.cxx:32
bool IsEmpty() const
long Right() const
RasterOp
Definition: vclenum.hxx:191
bool mbBackground
Definition: outdev.hxx:378
long Top() const
SAL_DLLPRIVATE const BitmapEx * ImplGetCachedBitmap() const
Definition: wall.cxx:180
void DrawRect(const tools::Rectangle &rRect)
Definition: rect.cxx:32
Bitmap GetBitmap(const Color *pTransReplaceColor=nullptr) const
Definition: bitmapex.cxx:236
void SetLineColor()
tools::Rectangle GetRect() const
Definition: wall.cxx:309
Wallpaper maBackground
Definition: outdev.hxx:369
long AdjustY(long nVertMove)
void DrawGradientWallpaper(long nX, long nY, long nWidth, long nHeight, const Wallpaper &rWallpaper)
Definition: wallpaper.cxx:349
bool IsRect() const
Definition: wall.cxx:317
SAL_DLLPRIVATE void DrawColorWallpaper(long nX, long nY, long nWidth, long nHeight, const Wallpaper &rWallpaper)
Definition: wallpaper.cxx:73
const Color & GetColor() const
Definition: wall.cxx:199
void SetFillColor()
const Color & GetLineColor() const
Definition: outdev.hxx:618
virtual Color GetBackgroundColor() const
Definition: wallpaper.cxx:27
long Bottom() const
Size GetOutputSizePixel() const
Definition: outdev.hxx:441
bool IsTransparent() const
Definition: bitmapex.cxx:221
Bitmap CreateDisplayBitmap(OutputDevice *pDisplay)
long X() const
Size GetSize() const
Gradient GetGradient() const
Definition: wall.cxx:268
Point LogicToPixel(const Point &rLogicPt) const
Definition: map.cxx:940
VclPtr< VirtualDevice > mpAlphaVDev
Definition: outdev.hxx:331
BitmapEx GetBitmap() const
Definition: wall.cxx:242
bool IsGradient() const
Definition: wall.cxx:278
void Erase()
Definition: wallpaper.cxx:93
void AddAction(const rtl::Reference< MetaAction > &pAction)
Definition: gdimtf.cxx:539
WallpaperStyle
Definition: wall.hxx:32
void SetRasterOp(RasterOp eRasterOp)
SAL_DLLPRIVATE void DrawBitmapWallpaper(long nX, long nY, long nWidth, long nHeight, const Wallpaper &rWallpaper)
Definition: wallpaper.cxx:112
RasterOp GetRasterOp() const
Definition: outdev.hxx:604
long Left() const
bool IsBitmap() const
Definition: wall.cxx:250
long mnOutWidth
Definition: outdev.hxx:345
const Size & GetSizePixel() const
Definition: bitmapex.hxx:83
long mnOutHeight
Definition: outdev.hxx:346
bool IsDeviceOutputNecessary() const
Definition: outdev.hxx:589
void Push(PushFlags nFlags=PushFlags::ALL)
Definition: outdevstate.cxx:60
void DrawGradient(const tools::Rectangle &rRect, const Gradient &rGradient)
SAL_DLLPRIVATE void ImplSetCachedBitmap(BitmapEx &rBmp) const
Definition: wall.cxx:172
long Y() const
const Color & GetFillColor() const
Definition: outdev.hxx:623
GDIMetaFile * mpMetaFile
Definition: outdev.hxx:319