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 
223  if( aDstRect.IsEmpty() || ImplIsRecordLayout() )
224  return;
225 
226  if( !mpGraphics && !AcquireGraphics() )
227  return;
228 
229  if( mbInitClipRegion )
230  InitClipRegion();
231 
232  if( mbOutputClipped )
233  return;
234 
235  const long nDistX = std::max( rDist.Width(), 1L );
236  const long nDistY = std::max( rDist.Height(), 1L );
237  long nX = ( rRect.Left() >= aDstRect.Left() ) ? rRect.Left() : ( rRect.Left() + ( ( aDstRect.Left() - rRect.Left() ) / nDistX ) * nDistX );
238  long nY = ( rRect.Top() >= aDstRect.Top() ) ? rRect.Top() : ( rRect.Top() + ( ( aDstRect.Top() - rRect.Top() ) / nDistY ) * nDistY );
239  const long nRight = aDstRect.Right();
240  const long nBottom = aDstRect.Bottom();
241  const long nStartX = ImplLogicXToDevicePixel( nX );
242  const long nEndX = ImplLogicXToDevicePixel( nRight );
243  const long nStartY = ImplLogicYToDevicePixel( nY );
244  const long nEndY = ImplLogicYToDevicePixel( nBottom );
245  long nHorzCount = 0;
246  long nVertCount = 0;
247 
248  std::vector< sal_Int32 > aVertBuf;
249  std::vector< sal_Int32 > aHorzBuf;
250 
251  if( ( nFlags & DrawGridFlags::Dots ) || ( nFlags & DrawGridFlags::HorzLines ) )
252  {
253  aVertBuf.resize( aDstRect.GetHeight() / nDistY + 2 );
254  aVertBuf[ nVertCount++ ] = nStartY;
255  while( ( nY += nDistY ) <= nBottom )
256  {
257  aVertBuf[ nVertCount++ ] = ImplLogicYToDevicePixel( nY );
258  }
259  }
260 
261  if( ( nFlags & DrawGridFlags::Dots ) || ( nFlags & DrawGridFlags::VertLines ) )
262  {
263  aHorzBuf.resize( aDstRect.GetWidth() / nDistX + 2 );
264  aHorzBuf[ nHorzCount++ ] = nStartX;
265  while( ( nX += nDistX ) <= nRight )
266  {
267  aHorzBuf[ nHorzCount++ ] = ImplLogicXToDevicePixel( nX );
268  }
269  }
270 
271  if( mbInitLineColor )
272  InitLineColor();
273 
274  if( mbInitFillColor )
275  InitFillColor();
276 
277  const bool bOldMap = mbMap;
278  EnableMapMode( false );
279 
280  if( nFlags & DrawGridFlags::Dots )
281  {
282  for( long i = 0; i < nVertCount; i++ )
283  {
284  for( long j = 0, Y = aVertBuf[ i ]; j < nHorzCount; j++ )
285  {
286  mpGraphics->DrawPixel( aHorzBuf[ j ], Y, this );
287  }
288  }
289  }
290  else
291  {
292  if( nFlags & DrawGridFlags::HorzLines )
293  {
294  for( long i = 0; i < nVertCount; i++ )
295  {
296  nY = aVertBuf[ i ];
297  mpGraphics->DrawLine( nStartX, nY, nEndX, nY, this );
298  }
299  }
300 
301  if( nFlags & DrawGridFlags::VertLines )
302  {
303  for( long i = 0; i < nHorzCount; i++ )
304  {
305  nX = aHorzBuf[ i ];
306  mpGraphics->DrawLine( nX, nStartY, nX, nEndY, this );
307  }
308  }
309  }
310 
311  EnableMapMode( bOldMap );
312 
313  if( mpAlphaVDev )
314  mpAlphaVDev->DrawGrid( rRect, rDist, nFlags );
315 }
316 
317 BmpMirrorFlags AdjustTwoRect( SalTwoRect& rTwoRect, const Size& rSizePix )
318 {
320 
321  if ( rTwoRect.mnDestWidth < 0 )
322  {
323  rTwoRect.mnSrcX = rSizePix.Width() - rTwoRect.mnSrcX - rTwoRect.mnSrcWidth;
324  rTwoRect.mnDestWidth = -rTwoRect.mnDestWidth;
325  rTwoRect.mnDestX -= rTwoRect.mnDestWidth-1;
326  nMirrFlags |= BmpMirrorFlags::Horizontal;
327  }
328 
329  if ( rTwoRect.mnDestHeight < 0 )
330  {
331  rTwoRect.mnSrcY = rSizePix.Height() - rTwoRect.mnSrcY - rTwoRect.mnSrcHeight;
332  rTwoRect.mnDestHeight = -rTwoRect.mnDestHeight;
333  rTwoRect.mnDestY -= rTwoRect.mnDestHeight-1;
334  nMirrFlags |= BmpMirrorFlags::Vertical;
335  }
336 
337  if( ( rTwoRect.mnSrcX < 0 ) || ( rTwoRect.mnSrcX >= rSizePix.Width() ) ||
338  ( rTwoRect.mnSrcY < 0 ) || ( rTwoRect.mnSrcY >= rSizePix.Height() ) ||
339  ( ( rTwoRect.mnSrcX + rTwoRect.mnSrcWidth ) > rSizePix.Width() ) ||
340  ( ( rTwoRect.mnSrcY + rTwoRect.mnSrcHeight ) > rSizePix.Height() ) )
341  {
342  const tools::Rectangle aSourceRect( Point( rTwoRect.mnSrcX, rTwoRect.mnSrcY ),
343  Size( rTwoRect.mnSrcWidth, rTwoRect.mnSrcHeight ) );
344  tools::Rectangle aCropRect( aSourceRect );
345 
346  aCropRect.Intersection( tools::Rectangle( Point(), rSizePix ) );
347 
348  if( aCropRect.IsEmpty() )
349  {
350  rTwoRect.mnSrcWidth = rTwoRect.mnSrcHeight = rTwoRect.mnDestWidth = rTwoRect.mnDestHeight = 0;
351  }
352  else
353  {
354  const double fFactorX = ( rTwoRect.mnSrcWidth > 1 ) ? static_cast<double>( rTwoRect.mnDestWidth - 1 ) / ( rTwoRect.mnSrcWidth - 1 ) : 0.0;
355  const double fFactorY = ( rTwoRect.mnSrcHeight > 1 ) ? static_cast<double>( rTwoRect.mnDestHeight - 1 ) / ( rTwoRect.mnSrcHeight - 1 ) : 0.0;
356 
357  const long nDstX1 = rTwoRect.mnDestX + FRound( fFactorX * ( aCropRect.Left() - rTwoRect.mnSrcX ) );
358  const long nDstY1 = rTwoRect.mnDestY + FRound( fFactorY * ( aCropRect.Top() - rTwoRect.mnSrcY ) );
359  const long nDstX2 = rTwoRect.mnDestX + FRound( fFactorX * ( aCropRect.Right() - rTwoRect.mnSrcX ) );
360  const long nDstY2 = rTwoRect.mnDestY + FRound( fFactorY * ( aCropRect.Bottom() - rTwoRect.mnSrcY ) );
361 
362  rTwoRect.mnSrcX = aCropRect.Left();
363  rTwoRect.mnSrcY = aCropRect.Top();
364  rTwoRect.mnSrcWidth = aCropRect.GetWidth();
365  rTwoRect.mnSrcHeight = aCropRect.GetHeight();
366  rTwoRect.mnDestX = nDstX1;
367  rTwoRect.mnDestY = nDstY1;
368  rTwoRect.mnDestWidth = nDstX2 - nDstX1 + 1;
369  rTwoRect.mnDestHeight = nDstY2 - nDstY1 + 1;
370  }
371  }
372 
373  return nMirrFlags;
374 }
375 
376 void AdjustTwoRect( SalTwoRect& rTwoRect, const tools::Rectangle& rValidSrcRect )
377 {
378  if( ( rTwoRect.mnSrcX < rValidSrcRect.Left() ) || ( rTwoRect.mnSrcX >= rValidSrcRect.Right() ) ||
379  ( rTwoRect.mnSrcY < rValidSrcRect.Top() ) || ( rTwoRect.mnSrcY >= rValidSrcRect.Bottom() ) ||
380  ( ( rTwoRect.mnSrcX + rTwoRect.mnSrcWidth ) > rValidSrcRect.Right() ) ||
381  ( ( rTwoRect.mnSrcY + rTwoRect.mnSrcHeight ) > rValidSrcRect.Bottom() ) )
382  {
383  const tools::Rectangle aSourceRect( Point( rTwoRect.mnSrcX, rTwoRect.mnSrcY ),
384  Size( rTwoRect.mnSrcWidth, rTwoRect.mnSrcHeight ) );
385  tools::Rectangle aCropRect( aSourceRect );
386 
387  aCropRect.Intersection( rValidSrcRect );
388 
389  if( aCropRect.IsEmpty() )
390  {
391  rTwoRect.mnSrcWidth = rTwoRect.mnSrcHeight = rTwoRect.mnDestWidth = rTwoRect.mnDestHeight = 0;
392  }
393  else
394  {
395  const double fFactorX = ( rTwoRect.mnSrcWidth > 1 ) ? static_cast<double>( rTwoRect.mnDestWidth - 1 ) / ( rTwoRect.mnSrcWidth - 1 ) : 0.0;
396  const double fFactorY = ( rTwoRect.mnSrcHeight > 1 ) ? static_cast<double>( rTwoRect.mnDestHeight - 1 ) / ( rTwoRect.mnSrcHeight - 1 ) : 0.0;
397 
398  const long nDstX1 = rTwoRect.mnDestX + FRound( fFactorX * ( aCropRect.Left() - rTwoRect.mnSrcX ) );
399  const long nDstY1 = rTwoRect.mnDestY + FRound( fFactorY * ( aCropRect.Top() - rTwoRect.mnSrcY ) );
400  const long nDstX2 = rTwoRect.mnDestX + FRound( fFactorX * ( aCropRect.Right() - rTwoRect.mnSrcX ) );
401  const long nDstY2 = rTwoRect.mnDestY + FRound( fFactorY * ( aCropRect.Bottom() - rTwoRect.mnSrcY ) );
402 
403  rTwoRect.mnSrcX = aCropRect.Left();
404  rTwoRect.mnSrcY = aCropRect.Top();
405  rTwoRect.mnSrcWidth = aCropRect.GetWidth();
406  rTwoRect.mnSrcHeight = aCropRect.GetHeight();
407  rTwoRect.mnDestX = nDstX1;
408  rTwoRect.mnDestY = nDstY1;
409  rTwoRect.mnDestWidth = nDstX2 - nDstX1 + 1;
410  rTwoRect.mnDestHeight = nDstY2 - nDstY1 + 1;
411  }
412  }
413 }
414 
415 /* 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:317
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
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
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:539
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