LibreOffice Module vcl (master)  1
rect.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 <sal/types.h>
23 
24 #include <tools/poly.hxx>
25 #include <tools/helpers.hxx>
26 #include <vcl/metaact.hxx>
27 #include <vcl/outdev.hxx>
28 #include <vcl/virdev.hxx>
29 
30 #include <salgdi.hxx>
31 
33 {
34  assert(!is_double_buffered_window());
35 
36  if ( mpMetaFile )
37  mpMetaFile->AddAction( new MetaRectAction( rRect ) );
38 
40  return;
41 
42  tools::Rectangle aRect( ImplLogicToDevicePixel( rRect ) );
43 
44  if ( aRect.IsEmpty() )
45  return;
46 
47  aRect.Justify();
48 
49  if ( !mpGraphics && !AcquireGraphics() )
50  return;
51 
52  if ( mbInitClipRegion )
54 
55  if ( mbOutputClipped )
56  return;
57 
58  if ( mbInitLineColor )
59  InitLineColor();
60 
61  if ( mbInitFillColor )
62  InitFillColor();
63 
64  mpGraphics->DrawRect( aRect.Left(), aRect.Top(), aRect.GetWidth(), aRect.GetHeight(), this );
65 
66  if( mpAlphaVDev )
67  mpAlphaVDev->DrawRect( rRect );
68 }
69 
71  sal_uLong nHorzRound, sal_uLong nVertRound )
72 {
73  assert(!is_double_buffered_window());
74 
75  if ( mpMetaFile )
76  mpMetaFile->AddAction( new MetaRoundRectAction( rRect, nHorzRound, nVertRound ) );
77 
79  return;
80 
81  const tools::Rectangle aRect( ImplLogicToDevicePixel( rRect ) );
82 
83  if ( aRect.IsEmpty() )
84  return;
85 
86  nHorzRound = ImplLogicWidthToDevicePixel( nHorzRound );
87  nVertRound = ImplLogicHeightToDevicePixel( nVertRound );
88 
89  // we need a graphics
90  if ( !mpGraphics && !AcquireGraphics() )
91  return;
92 
93  if ( mbInitClipRegion )
95 
96  if ( mbOutputClipped )
97  return;
98 
99  if ( mbInitLineColor )
100  InitLineColor();
101 
102  if ( mbInitFillColor )
103  InitFillColor();
104 
105  if ( !nHorzRound && !nVertRound )
106  {
107  mpGraphics->DrawRect( aRect.Left(), aRect.Top(), aRect.GetWidth(), aRect.GetHeight(), this );
108  }
109  else
110  {
111  tools::Polygon aRoundRectPoly( aRect, nHorzRound, nVertRound );
112 
113  if ( aRoundRectPoly.GetSize() >= 2 )
114  {
115  SalPoint* pPtAry = reinterpret_cast<SalPoint*>(aRoundRectPoly.GetPointAry());
116 
117  if ( !mbFillColor )
118  mpGraphics->DrawPolyLine( aRoundRectPoly.GetSize(), pPtAry, this );
119  else
120  mpGraphics->DrawPolygon( aRoundRectPoly.GetSize(), pPtAry, this );
121  }
122  }
123 
124  if( mpAlphaVDev )
125  mpAlphaVDev->DrawRect( rRect, nHorzRound, nVertRound );
126 }
127 
129 {
130  assert(!is_double_buffered_window());
131  if ( !IsDeviceOutputNecessary() )
132  return;
133 
134  tools::Rectangle aRect( ImplLogicToDevicePixel( rRect ) );
135 
136  if ( aRect.IsEmpty() )
137  return;
138  aRect.Justify();
139 
140  // we need a graphics
141  if ( !mpGraphics && !AcquireGraphics() )
142  return;
143 
144  if ( mbInitClipRegion )
145  InitClipRegion();
146 
147  if ( mbOutputClipped )
148  return;
149 
150  SalInvert nSalFlags = SalInvert::NONE;
151  if ( nFlags & InvertFlags::N50 )
152  nSalFlags |= SalInvert::N50;
153  if ( nFlags & InvertFlags::TrackFrame )
154  nSalFlags |= SalInvert::TrackFrame;
155  mpGraphics->Invert( aRect.Left(), aRect.Top(), aRect.GetWidth(), aRect.GetHeight(), nSalFlags, this );
156 }
157 
158 void OutputDevice::Invert( const tools::Polygon& rPoly, InvertFlags nFlags )
159 {
160  assert(!is_double_buffered_window());
161  if ( !IsDeviceOutputNecessary() )
162  return;
163 
164  sal_uInt16 nPoints = rPoly.GetSize();
165 
166  if ( nPoints < 2 )
167  return;
168 
169  tools::Polygon aPoly( ImplLogicToDevicePixel( rPoly ) );
170 
171  // we need a graphics
172  if ( !mpGraphics && !AcquireGraphics() )
173  return;
174 
175  if ( mbInitClipRegion )
176  InitClipRegion();
177 
178  if ( mbOutputClipped )
179  return;
180 
181  SalInvert nSalFlags = SalInvert::NONE;
182  if ( nFlags & InvertFlags::N50 )
183  nSalFlags |= SalInvert::N50;
184  if ( nFlags & InvertFlags::TrackFrame )
185  nSalFlags |= SalInvert::TrackFrame;
186  const SalPoint* pPtAry = reinterpret_cast<const SalPoint*>(aPoly.GetConstPointAry());
187  mpGraphics->Invert( nPoints, pPtAry, nSalFlags, this );
188 }
189 
190 void OutputDevice::DrawCheckered(const Point& rPos, const Size& rSize, sal_uInt32 nLen, Color aStart, Color aEnd)
191 {
192  assert(!is_double_buffered_window());
193 
194  const sal_uInt32 nMaxX(rPos.X() + rSize.Width());
195  const sal_uInt32 nMaxY(rPos.Y() + rSize.Height());
196 
198  SetLineColor();
199 
200  for(sal_uInt32 x(0), nX(rPos.X()); nX < nMaxX; x++, nX += nLen)
201  {
202  const sal_uInt32 nRight(std::min(nMaxX, nX + nLen));
203 
204  for(sal_uInt32 y(0), nY(rPos.Y()); nY < nMaxY; y++, nY += nLen)
205  {
206  const sal_uInt32 nBottom(std::min(nMaxY, nY + nLen));
207 
208  SetFillColor(((x & 0x0001) ^ (y & 0x0001)) ? aStart : aEnd);
209  DrawRect(tools::Rectangle(nX, nY, nRight, nBottom));
210  }
211  }
212 
213  Pop();
214 }
215 
216 void OutputDevice::DrawGrid( const tools::Rectangle& rRect, const Size& rDist, DrawGridFlags nFlags )
217 {
218  assert(!is_double_buffered_window());
219 
220  tools::Rectangle aDstRect( PixelToLogic( Point() ), GetOutputSize() );
221  aDstRect.Intersection( rRect );
222  // FIXME: seems we have an off-by-one around the border
223  // here with the cairo / svp backend at least.
224  aDstRect.AdjustRight(1);
225  aDstRect.AdjustBottom(1);
226 
227  if( aDstRect.IsEmpty() || ImplIsRecordLayout() )
228  return;
229 
230  if( !mpGraphics && !AcquireGraphics() )
231  return;
232 
233  if( mbInitClipRegion )
234  InitClipRegion();
235 
236  if( mbOutputClipped )
237  return;
238 
239  const long nDistX = std::max( rDist.Width(), 1L );
240  const long nDistY = std::max( rDist.Height(), 1L );
241  long nX = ( rRect.Left() >= aDstRect.Left() ) ? rRect.Left() : ( rRect.Left() + ( ( aDstRect.Left() - rRect.Left() ) / nDistX ) * nDistX );
242  long nY = ( rRect.Top() >= aDstRect.Top() ) ? rRect.Top() : ( rRect.Top() + ( ( aDstRect.Top() - rRect.Top() ) / nDistY ) * nDistY );
243  const long nRight = aDstRect.Right();
244  const long nBottom = aDstRect.Bottom();
245  const long nStartX = ImplLogicXToDevicePixel( nX );
246  const long nEndX = ImplLogicXToDevicePixel( nRight );
247  const long nStartY = ImplLogicYToDevicePixel( nY );
248  const long nEndY = ImplLogicYToDevicePixel( nBottom );
249  long nHorzCount = 0;
250  long nVertCount = 0;
251 
252  std::vector< sal_Int32 > aVertBuf;
253  std::vector< sal_Int32 > aHorzBuf;
254 
255  if( ( nFlags & DrawGridFlags::Dots ) || ( nFlags & DrawGridFlags::HorzLines ) )
256  {
257  aVertBuf.resize( aDstRect.GetHeight() / nDistY + 2 );
258  aVertBuf[ nVertCount++ ] = nStartY;
259  while( ( nY += nDistY ) <= nBottom )
260  {
261  aVertBuf[ nVertCount++ ] = ImplLogicYToDevicePixel( nY );
262  }
263  }
264 
265  if( ( nFlags & DrawGridFlags::Dots ) || ( nFlags & DrawGridFlags::VertLines ) )
266  {
267  aHorzBuf.resize( aDstRect.GetWidth() / nDistX + 2 );
268  aHorzBuf[ nHorzCount++ ] = nStartX;
269  while( ( nX += nDistX ) <= nRight )
270  {
271  aHorzBuf[ nHorzCount++ ] = ImplLogicXToDevicePixel( nX );
272  }
273  }
274 
275  if( mbInitLineColor )
276  InitLineColor();
277 
278  if( mbInitFillColor )
279  InitFillColor();
280 
281  const bool bOldMap = mbMap;
282  EnableMapMode( false );
283 
284  if( nFlags & DrawGridFlags::Dots )
285  {
286  for( long i = 0; i < nVertCount; i++ )
287  {
288  for( long j = 0, Y = aVertBuf[ i ]; j < nHorzCount; j++ )
289  {
290  mpGraphics->DrawPixel( aHorzBuf[ j ], Y, this );
291  }
292  }
293  }
294  else
295  {
296  if( nFlags & DrawGridFlags::HorzLines )
297  {
298  for( long i = 0; i < nVertCount; i++ )
299  {
300  nY = aVertBuf[ i ];
301  mpGraphics->DrawLine( nStartX, nY, nEndX, nY, this );
302  }
303  }
304 
305  if( nFlags & DrawGridFlags::VertLines )
306  {
307  for( long i = 0; i < nHorzCount; i++ )
308  {
309  nX = aHorzBuf[ i ];
310  mpGraphics->DrawLine( nX, nStartY, nX, nEndY, this );
311  }
312  }
313  }
314 
315  EnableMapMode( bOldMap );
316 
317  if( mpAlphaVDev )
318  mpAlphaVDev->DrawGrid( rRect, rDist, nFlags );
319 }
320 
321 BmpMirrorFlags AdjustTwoRect( SalTwoRect& rTwoRect, const Size& rSizePix )
322 {
324 
325  if ( rTwoRect.mnDestWidth < 0 )
326  {
327  rTwoRect.mnSrcX = rSizePix.Width() - rTwoRect.mnSrcX - rTwoRect.mnSrcWidth;
328  rTwoRect.mnDestWidth = -rTwoRect.mnDestWidth;
329  rTwoRect.mnDestX -= rTwoRect.mnDestWidth-1;
330  nMirrFlags |= BmpMirrorFlags::Horizontal;
331  }
332 
333  if ( rTwoRect.mnDestHeight < 0 )
334  {
335  rTwoRect.mnSrcY = rSizePix.Height() - rTwoRect.mnSrcY - rTwoRect.mnSrcHeight;
336  rTwoRect.mnDestHeight = -rTwoRect.mnDestHeight;
337  rTwoRect.mnDestY -= rTwoRect.mnDestHeight-1;
338  nMirrFlags |= BmpMirrorFlags::Vertical;
339  }
340 
341  if( ( rTwoRect.mnSrcX < 0 ) || ( rTwoRect.mnSrcX >= rSizePix.Width() ) ||
342  ( rTwoRect.mnSrcY < 0 ) || ( rTwoRect.mnSrcY >= rSizePix.Height() ) ||
343  ( ( rTwoRect.mnSrcX + rTwoRect.mnSrcWidth ) > rSizePix.Width() ) ||
344  ( ( rTwoRect.mnSrcY + rTwoRect.mnSrcHeight ) > rSizePix.Height() ) )
345  {
346  const tools::Rectangle aSourceRect( Point( rTwoRect.mnSrcX, rTwoRect.mnSrcY ),
347  Size( rTwoRect.mnSrcWidth, rTwoRect.mnSrcHeight ) );
348  tools::Rectangle aCropRect( aSourceRect );
349 
350  aCropRect.Intersection( tools::Rectangle( Point(), rSizePix ) );
351 
352  if( aCropRect.IsEmpty() )
353  {
354  rTwoRect.mnSrcWidth = rTwoRect.mnSrcHeight = rTwoRect.mnDestWidth = rTwoRect.mnDestHeight = 0;
355  }
356  else
357  {
358  const double fFactorX = ( rTwoRect.mnSrcWidth > 1 ) ? static_cast<double>( rTwoRect.mnDestWidth - 1 ) / ( rTwoRect.mnSrcWidth - 1 ) : 0.0;
359  const double fFactorY = ( rTwoRect.mnSrcHeight > 1 ) ? static_cast<double>( rTwoRect.mnDestHeight - 1 ) / ( rTwoRect.mnSrcHeight - 1 ) : 0.0;
360 
361  const long nDstX1 = rTwoRect.mnDestX + FRound( fFactorX * ( aCropRect.Left() - rTwoRect.mnSrcX ) );
362  const long nDstY1 = rTwoRect.mnDestY + FRound( fFactorY * ( aCropRect.Top() - rTwoRect.mnSrcY ) );
363  const long nDstX2 = rTwoRect.mnDestX + FRound( fFactorX * ( aCropRect.Right() - rTwoRect.mnSrcX ) );
364  const long nDstY2 = rTwoRect.mnDestY + FRound( fFactorY * ( aCropRect.Bottom() - rTwoRect.mnSrcY ) );
365 
366  rTwoRect.mnSrcX = aCropRect.Left();
367  rTwoRect.mnSrcY = aCropRect.Top();
368  rTwoRect.mnSrcWidth = aCropRect.GetWidth();
369  rTwoRect.mnSrcHeight = aCropRect.GetHeight();
370  rTwoRect.mnDestX = nDstX1;
371  rTwoRect.mnDestY = nDstY1;
372  rTwoRect.mnDestWidth = nDstX2 - nDstX1 + 1;
373  rTwoRect.mnDestHeight = nDstY2 - nDstY1 + 1;
374  }
375  }
376 
377  return nMirrFlags;
378 }
379 
380 void AdjustTwoRect( SalTwoRect& rTwoRect, const tools::Rectangle& rValidSrcRect )
381 {
382  if( ( rTwoRect.mnSrcX < rValidSrcRect.Left() ) || ( rTwoRect.mnSrcX >= rValidSrcRect.Right() ) ||
383  ( rTwoRect.mnSrcY < rValidSrcRect.Top() ) || ( rTwoRect.mnSrcY >= rValidSrcRect.Bottom() ) ||
384  ( ( rTwoRect.mnSrcX + rTwoRect.mnSrcWidth ) > rValidSrcRect.Right() ) ||
385  ( ( rTwoRect.mnSrcY + rTwoRect.mnSrcHeight ) > rValidSrcRect.Bottom() ) )
386  {
387  const tools::Rectangle aSourceRect( Point( rTwoRect.mnSrcX, rTwoRect.mnSrcY ),
388  Size( rTwoRect.mnSrcWidth, rTwoRect.mnSrcHeight ) );
389  tools::Rectangle aCropRect( aSourceRect );
390 
391  aCropRect.Intersection( rValidSrcRect );
392 
393  if( aCropRect.IsEmpty() )
394  {
395  rTwoRect.mnSrcWidth = rTwoRect.mnSrcHeight = rTwoRect.mnDestWidth = rTwoRect.mnDestHeight = 0;
396  }
397  else
398  {
399  const double fFactorX = ( rTwoRect.mnSrcWidth > 1 ) ? static_cast<double>( rTwoRect.mnDestWidth - 1 ) / ( rTwoRect.mnSrcWidth - 1 ) : 0.0;
400  const double fFactorY = ( rTwoRect.mnSrcHeight > 1 ) ? static_cast<double>( rTwoRect.mnDestHeight - 1 ) / ( rTwoRect.mnSrcHeight - 1 ) : 0.0;
401 
402  const long nDstX1 = rTwoRect.mnDestX + FRound( fFactorX * ( aCropRect.Left() - rTwoRect.mnSrcX ) );
403  const long nDstY1 = rTwoRect.mnDestY + FRound( fFactorY * ( aCropRect.Top() - rTwoRect.mnSrcY ) );
404  const long nDstX2 = rTwoRect.mnDestX + FRound( fFactorX * ( aCropRect.Right() - rTwoRect.mnSrcX ) );
405  const long nDstY2 = rTwoRect.mnDestY + FRound( fFactorY * ( aCropRect.Bottom() - rTwoRect.mnSrcY ) );
406 
407  rTwoRect.mnSrcX = aCropRect.Left();
408  rTwoRect.mnSrcY = aCropRect.Top();
409  rTwoRect.mnSrcWidth = aCropRect.GetWidth();
410  rTwoRect.mnSrcHeight = aCropRect.GetHeight();
411  rTwoRect.mnDestX = nDstX1;
412  rTwoRect.mnDestY = nDstY1;
413  rTwoRect.mnDestWidth = nDstX2 - nDstX1 + 1;
414  rTwoRect.mnDestHeight = nDstY2 - nDstY1 + 1;
415  }
416  }
417 }
418 
419 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
long Width() const
long mnSrcWidth
Definition: salgtype.hxx:52
long GetWidth() const
long GetHeight() const
SAL_DLLPRIVATE bool ImplIsRecordLayout() const
Definition: outdev.cxx:657
long mnSrcHeight
Definition: salgtype.hxx:53
tools::Rectangle & Intersection(const tools::Rectangle &rRect)
long FRound(double fVal)
long Height() const
sal_uIntPtr sal_uLong
BmpMirrorFlags AdjustTwoRect(SalTwoRect &rTwoRect, const Size &rSizePix)
Definition: rect.cxx:321
bool mbOutputClipped
Definition: outdev.hxx:381
SAL_DLLPRIVATE bool is_double_buffered_window() const
long mnDestWidth
Definition: salgtype.hxx:56
long mnSrcX
Definition: salgtype.hxx:50
void EnableMapMode(bool bEnable=true)
Definition: map.cxx:647
bool mbMap
Definition: outdev.hxx:376
void DrawRect(long nX, long nY, long nWidth, long nHeight, const OutputDevice *pOutDev)
float x
long AdjustBottom(long nVertMoveDelta)
bool IsEmpty() const
SAL_DLLPRIVATE void InitLineColor()
long mnDestY
Definition: salgtype.hxx:55
void Invert(const tools::Rectangle &rRect, InvertFlags nFlags=InvertFlags::NONE)
Definition: rect.cxx:128
long Right() const
long Top() const
SAL_DLLPRIVATE long ImplLogicXToDevicePixel(long nX) const
Convert a logical X coordinate to a device pixel's X coordinate.
Definition: map.cxx:410
void DrawRect(const tools::Rectangle &rRect)
Definition: rect.cxx:32
void DrawPolyLine(sal_uInt32 nPoints, SalPoint const *pPtAry, const OutputDevice *pOutDev)
float y
void DrawPolygon(sal_uInt32 nPoints, const SalPoint *pPtAry, const OutputDevice *pOutDev)
SalGraphics * mpGraphics
Graphics context to draw on.
Definition: outdev.hxx:316
void SetLineColor()
SAL_DLLPRIVATE void InitFillColor()
SAL_DLLPRIVATE long ImplLogicYToDevicePixel(long nY) const
Convert a logical Y coordinate to a device pixel's Y coordinate.
Definition: map.cxx:420
Point * GetPointAry()
const Point * GetConstPointAry() const
virtual bool AcquireGraphics() const =0
Acquire a graphics device that the output device uses to draw on.
int i
Size GetOutputSize() const
Definition: outdev.hxx:450
bool mbInitLineColor
Definition: outdev.hxx:384
void SetFillColor()
long Bottom() const
BmpMirrorFlags
Definition: bitmap.hxx:36
SalInvert
Definition: salgtype.hxx:84
bool mbLineColor
Definition: outdev.hxx:382
sal_uInt16 GetSize() const
DrawGridFlags
Definition: outdev.hxx:187
long X() const
void DrawPixel(long nX, long nY, const OutputDevice *pOutDev)
#define Y
long mnSrcY
Definition: salgtype.hxx:51
Point PixelToLogic(const Point &rDevicePt) const
Definition: map.cxx:1185
bool mbFillColor
Definition: outdev.hxx:383
VclPtr< VirtualDevice > mpAlphaVDev
Definition: outdev.hxx:331
long AdjustRight(long nHorzMoveDelta)
void Invert(long nX, long nY, long nWidth, long nHeight, SalInvert nFlags, const OutputDevice *pOutDev)
long mnDestX
Definition: salgtype.hxx:54
void AddAction(const rtl::Reference< MetaAction > &pAction)
Definition: gdimtf.cxx:540
bool mbInitClipRegion
Definition: outdev.hxx:388
void DrawGrid(const tools::Rectangle &rRect, const Size &rDist, DrawGridFlags nFlags)
Definition: rect.cxx:216
virtual void InitClipRegion()
InvertFlags
Definition: outdev.hxx:267
SAL_DLLPRIVATE long ImplLogicWidthToDevicePixel(long nWidth) const
Convert a logical width to a width in units of device pixels.
Definition: map.cxx:430
long Left() const
void DrawCheckered(const Point &rPos, const Size &rSize, sal_uInt32 nLen=8, Color aStart=COL_WHITE, Color aEnd=COL_BLACK)
Fill the given rectangle with checkered rectangles of size nLen x nLen using the colors aStart and aE...
Definition: rect.cxx:190
bool mbInitFillColor
Definition: outdev.hxx:385
SAL_DLLPRIVATE long ImplLogicHeightToDevicePixel(long nHeight) const
Convert a logical height to a height in units of device pixels.
Definition: map.cxx:440
SAL_DLLPRIVATE tools::Rectangle ImplLogicToDevicePixel(const tools::Rectangle &rLogicRect) const
Convert a logical rectangle to a rectangle in physical device pixel units.
Definition: map.cxx:504
long mnDestHeight
Definition: salgtype.hxx:57
void DrawLine(long nX1, long nY1, long nX2, long nY2, const OutputDevice *pOutDev)
bool IsDeviceOutputNecessary() const
Definition: outdev.hxx:589
void Push(PushFlags nFlags=PushFlags::ALL)
Definition: outdevstate.cxx:60
long Y() const
GDIMetaFile * mpMetaFile
Definition: outdev.hxx:319