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