1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <sal/types.h>
21 #include <tools/poly.hxx>
22 #include <tools/helpers.hxx>
24 #include <vcl/metaact.hxx>
25 #include <vcl/virdev.hxx>
31 void OutputDevice::DrawBorder(tools::Rectangle aBorderRect
)
33 sal_uInt16 nPixel
= static_cast<sal_uInt16
>(PixelToLogic(Size(1, 1)).Width());
35 aBorderRect
.AdjustLeft(nPixel
);
36 aBorderRect
.AdjustTop(nPixel
);
38 SetLineColor(COL_LIGHTGRAY
);
39 DrawRect(aBorderRect
);
41 aBorderRect
.AdjustLeft(-nPixel
);
42 aBorderRect
.AdjustTop(-nPixel
);
43 aBorderRect
.AdjustRight(-nPixel
);
44 aBorderRect
.AdjustBottom(-nPixel
);
45 SetLineColor(COL_GRAY
);
47 DrawRect(aBorderRect
);
50 void OutputDevice::DrawRect( const tools::Rectangle
& rRect
)
52 assert(!is_double_buffered_window());
55 mpMetaFile
->AddAction( new MetaRectAction( rRect
) );
57 if ( !IsDeviceOutputNecessary() || (!mbLineColor
&& !mbFillColor
) || ImplIsRecordLayout() )
60 tools::Rectangle
aRect( ImplLogicToDevicePixel( rRect
) );
62 if ( aRect
.IsEmpty() )
67 if ( !mpGraphics
&& !AcquireGraphics() )
71 if ( mbInitClipRegion
)
74 if ( mbOutputClipped
)
77 if ( mbInitLineColor
)
80 if ( mbInitFillColor
)
83 mpGraphics
->DrawRect( aRect
.Left(), aRect
.Top(), aRect
.GetWidth(), aRect
.GetHeight(), *this );
86 mpAlphaVDev
->DrawRect( rRect
);
89 void OutputDevice::DrawRect( const tools::Rectangle
& rRect
,
90 sal_uLong nHorzRound
, sal_uLong nVertRound
)
92 assert(!is_double_buffered_window());
95 mpMetaFile
->AddAction( new MetaRoundRectAction( rRect
, nHorzRound
, nVertRound
) );
97 if ( !IsDeviceOutputNecessary() || (!mbLineColor
&& !mbFillColor
) || ImplIsRecordLayout() )
100 const tools::Rectangle
aRect( ImplLogicToDevicePixel( rRect
) );
102 if ( aRect
.IsEmpty() )
105 nHorzRound
= ImplLogicWidthToDevicePixel( nHorzRound
);
106 nVertRound
= ImplLogicHeightToDevicePixel( nVertRound
);
108 // we need a graphics
109 if ( !mpGraphics
&& !AcquireGraphics() )
113 if ( mbInitClipRegion
)
116 if ( mbOutputClipped
)
119 if ( mbInitLineColor
)
122 if ( mbInitFillColor
)
125 if ( !nHorzRound
&& !nVertRound
)
127 mpGraphics
->DrawRect( aRect
.Left(), aRect
.Top(), aRect
.GetWidth(), aRect
.GetHeight(), *this );
131 tools::Polygon
aRoundRectPoly( aRect
, nHorzRound
, nVertRound
);
133 if ( aRoundRectPoly
.GetSize() >= 2 )
135 Point
* pPtAry
= aRoundRectPoly
.GetPointAry();
138 mpGraphics
->DrawPolyLine( aRoundRectPoly
.GetSize(), pPtAry
, *this );
140 mpGraphics
->DrawPolygon( aRoundRectPoly
.GetSize(), pPtAry
, *this );
145 mpAlphaVDev
->DrawRect( rRect
, nHorzRound
, nVertRound
);
148 void OutputDevice::Invert( const tools::Rectangle
& rRect
, InvertFlags nFlags
)
150 assert(!is_double_buffered_window());
151 if ( !IsDeviceOutputNecessary() )
154 tools::Rectangle
aRect( ImplLogicToDevicePixel( rRect
) );
156 if ( aRect
.IsEmpty() )
160 // we need a graphics
161 if ( !mpGraphics
&& !AcquireGraphics() )
165 if ( mbInitClipRegion
)
168 if ( mbOutputClipped
)
171 SalInvert nSalFlags
= SalInvert::NONE
;
172 if ( nFlags
& InvertFlags::N50
)
173 nSalFlags
|= SalInvert::N50
;
174 if ( nFlags
& InvertFlags::TrackFrame
)
175 nSalFlags
|= SalInvert::TrackFrame
;
176 mpGraphics
->Invert( aRect
.Left(), aRect
.Top(), aRect
.GetWidth(), aRect
.GetHeight(), nSalFlags
, *this );
179 void OutputDevice::Invert( const tools::Polygon
& rPoly
, InvertFlags nFlags
)
181 assert(!is_double_buffered_window());
182 if ( !IsDeviceOutputNecessary() )
185 sal_uInt16 nPoints
= rPoly
.GetSize();
190 tools::Polygon
aPoly( ImplLogicToDevicePixel( rPoly
) );
192 // we need a graphics
193 if ( !mpGraphics
&& !AcquireGraphics() )
197 if ( mbInitClipRegion
)
200 if ( mbOutputClipped
)
203 SalInvert nSalFlags
= SalInvert::NONE
;
204 if ( nFlags
& InvertFlags::N50
)
205 nSalFlags
|= SalInvert::N50
;
206 if ( nFlags
& InvertFlags::TrackFrame
)
207 nSalFlags
|= SalInvert::TrackFrame
;
208 const Point
* pPtAry
= aPoly
.GetConstPointAry();
209 mpGraphics
->Invert( nPoints
, pPtAry
, nSalFlags
, *this );
212 void OutputDevice::DrawCheckered(const Point
& rPos
, const Size
& rSize
, sal_uInt32 nLen
, Color aStart
, Color aEnd
)
214 assert(!is_double_buffered_window());
216 const sal_uInt32
nMaxX(rPos
.X() + rSize
.Width());
217 const sal_uInt32
nMaxY(rPos
.Y() + rSize
.Height());
219 Push(vcl::PushFlags::LINECOLOR
|vcl::PushFlags::FILLCOLOR
);
222 for(sal_uInt32
x(0), nX(rPos
.X()); nX
< nMaxX
; x
++, nX
+= nLen
)
224 const sal_uInt32
nRight(std::min(nMaxX
, nX
+ nLen
));
226 for(sal_uInt32
y(0), nY(rPos
.Y()); nY
< nMaxY
; y
++, nY
+= nLen
)
228 const sal_uInt32
nBottom(std::min(nMaxY
, nY
+ nLen
));
230 SetFillColor(((x
& 0x0001) ^ (y
& 0x0001)) ? aStart
: aEnd
);
231 DrawRect(tools::Rectangle(nX
, nY
, nRight
, nBottom
));
238 void OutputDevice::DrawGrid( const tools::Rectangle
& rRect
, const Size
& rDist
, DrawGridFlags nFlags
)
240 assert(!is_double_buffered_window());
242 tools::Rectangle
aDstRect( PixelToLogic( Point() ), GetOutputSize() );
243 aDstRect
.Intersection( rRect
);
245 if( aDstRect
.IsEmpty() || ImplIsRecordLayout() )
248 if( !mpGraphics
&& !AcquireGraphics() )
252 if( mbInitClipRegion
)
255 if( mbOutputClipped
)
258 const tools::Long nDistX
= std::max( rDist
.Width(), tools::Long(1) );
259 const tools::Long nDistY
= std::max( rDist
.Height(), tools::Long(1) );
260 tools::Long nX
= ( rRect
.Left() >= aDstRect
.Left() ) ? rRect
.Left() : ( rRect
.Left() + ( ( aDstRect
.Left() - rRect
.Left() ) / nDistX
) * nDistX
);
261 tools::Long nY
= ( rRect
.Top() >= aDstRect
.Top() ) ? rRect
.Top() : ( rRect
.Top() + ( ( aDstRect
.Top() - rRect
.Top() ) / nDistY
) * nDistY
);
262 const tools::Long nRight
= aDstRect
.Right();
263 const tools::Long nBottom
= aDstRect
.Bottom();
264 const tools::Long nStartX
= ImplLogicXToDevicePixel( nX
);
265 const tools::Long nEndX
= ImplLogicXToDevicePixel( nRight
);
266 const tools::Long nStartY
= ImplLogicYToDevicePixel( nY
);
267 const tools::Long nEndY
= ImplLogicYToDevicePixel( nBottom
);
268 tools::Long nHorzCount
= 0;
269 tools::Long nVertCount
= 0;
271 std::vector
< sal_Int32
> aVertBuf
;
272 std::vector
< sal_Int32
> aHorzBuf
;
274 if( ( nFlags
& DrawGridFlags::Dots
) || ( nFlags
& DrawGridFlags::HorzLines
) )
276 aVertBuf
.resize( aDstRect
.GetHeight() / nDistY
+ 2 );
277 aVertBuf
[ nVertCount
++ ] = nStartY
;
278 while( ( nY
+= nDistY
) <= nBottom
)
280 aVertBuf
[ nVertCount
++ ] = ImplLogicYToDevicePixel( nY
);
284 if( ( nFlags
& DrawGridFlags::Dots
) || ( nFlags
& DrawGridFlags::VertLines
) )
286 aHorzBuf
.resize( aDstRect
.GetWidth() / nDistX
+ 2 );
287 aHorzBuf
[ nHorzCount
++ ] = nStartX
;
288 while( ( nX
+= nDistX
) <= nRight
)
290 aHorzBuf
[ nHorzCount
++ ] = ImplLogicXToDevicePixel( nX
);
294 if( mbInitLineColor
)
297 if( mbInitFillColor
)
300 const bool bOldMap
= mbMap
;
301 EnableMapMode( false );
303 if( nFlags
& DrawGridFlags::Dots
)
305 for( tools::Long i
= 0; i
< nVertCount
; i
++ )
307 for( tools::Long j
= 0, Y
= aVertBuf
[ i
]; j
< nHorzCount
; j
++ )
309 mpGraphics
->DrawPixel( aHorzBuf
[ j
], Y
, *this );
315 if( nFlags
& DrawGridFlags::HorzLines
)
317 for( tools::Long i
= 0; i
< nVertCount
; i
++ )
320 mpGraphics
->DrawLine( nStartX
, nY
, nEndX
, nY
, *this );
324 if( nFlags
& DrawGridFlags::VertLines
)
326 for( tools::Long i
= 0; i
< nHorzCount
; i
++ )
329 mpGraphics
->DrawLine( nX
, nStartY
, nX
, nEndY
, *this );
334 EnableMapMode( bOldMap
);
337 mpAlphaVDev
->DrawGrid( rRect
, rDist
, nFlags
);
340 BmpMirrorFlags
AdjustTwoRect( SalTwoRect
& rTwoRect
, const Size
& rSizePix
)
342 BmpMirrorFlags nMirrFlags
= BmpMirrorFlags::NONE
;
344 if ( rTwoRect
.mnDestWidth
< 0 )
346 rTwoRect
.mnSrcX
= rSizePix
.Width() - rTwoRect
.mnSrcX
- rTwoRect
.mnSrcWidth
;
347 rTwoRect
.mnDestWidth
= -rTwoRect
.mnDestWidth
;
348 rTwoRect
.mnDestX
-= rTwoRect
.mnDestWidth
-1;
349 nMirrFlags
|= BmpMirrorFlags::Horizontal
;
352 if ( rTwoRect
.mnDestHeight
< 0 )
354 rTwoRect
.mnSrcY
= rSizePix
.Height() - rTwoRect
.mnSrcY
- rTwoRect
.mnSrcHeight
;
355 rTwoRect
.mnDestHeight
= -rTwoRect
.mnDestHeight
;
356 rTwoRect
.mnDestY
-= rTwoRect
.mnDestHeight
-1;
357 nMirrFlags
|= BmpMirrorFlags::Vertical
;
360 if( ( rTwoRect
.mnSrcX
< 0 ) || ( rTwoRect
.mnSrcX
>= rSizePix
.Width() ) ||
361 ( rTwoRect
.mnSrcY
< 0 ) || ( rTwoRect
.mnSrcY
>= rSizePix
.Height() ) ||
362 ( ( rTwoRect
.mnSrcX
+ rTwoRect
.mnSrcWidth
) > rSizePix
.Width() ) ||
363 ( ( rTwoRect
.mnSrcY
+ rTwoRect
.mnSrcHeight
) > rSizePix
.Height() ) )
365 const tools::Rectangle
aSourceRect( Point( rTwoRect
.mnSrcX
, rTwoRect
.mnSrcY
),
366 Size( rTwoRect
.mnSrcWidth
, rTwoRect
.mnSrcHeight
) );
367 tools::Rectangle
aCropRect( aSourceRect
);
369 aCropRect
.Intersection( tools::Rectangle( Point(), rSizePix
) );
371 if( aCropRect
.IsEmpty() )
373 rTwoRect
.mnSrcWidth
= rTwoRect
.mnSrcHeight
= rTwoRect
.mnDestWidth
= rTwoRect
.mnDestHeight
= 0;
377 const double fFactorX
= ( rTwoRect
.mnSrcWidth
> 1 ) ? static_cast<double>( rTwoRect
.mnDestWidth
- 1 ) / ( rTwoRect
.mnSrcWidth
- 1 ) : 0.0;
378 const double fFactorY
= ( rTwoRect
.mnSrcHeight
> 1 ) ? static_cast<double>( rTwoRect
.mnDestHeight
- 1 ) / ( rTwoRect
.mnSrcHeight
- 1 ) : 0.0;
380 const tools::Long nDstX1
= rTwoRect
.mnDestX
+ basegfx::fround
<tools::Long
>( fFactorX
* ( aCropRect
.Left() - rTwoRect
.mnSrcX
) );
381 const tools::Long nDstY1
= rTwoRect
.mnDestY
+ basegfx::fround
<tools::Long
>( fFactorY
* ( aCropRect
.Top() - rTwoRect
.mnSrcY
) );
382 const tools::Long nDstX2
= rTwoRect
.mnDestX
+ basegfx::fround
<tools::Long
>( fFactorX
* ( aCropRect
.Right() - rTwoRect
.mnSrcX
) );
383 const tools::Long nDstY2
= rTwoRect
.mnDestY
+ basegfx::fround
<tools::Long
>( fFactorY
* ( aCropRect
.Bottom() - rTwoRect
.mnSrcY
) );
385 rTwoRect
.mnSrcX
= aCropRect
.Left();
386 rTwoRect
.mnSrcY
= aCropRect
.Top();
387 rTwoRect
.mnSrcWidth
= aCropRect
.GetWidth();
388 rTwoRect
.mnSrcHeight
= aCropRect
.GetHeight();
389 rTwoRect
.mnDestX
= nDstX1
;
390 rTwoRect
.mnDestY
= nDstY1
;
391 rTwoRect
.mnDestWidth
= nDstX2
- nDstX1
+ 1;
392 rTwoRect
.mnDestHeight
= nDstY2
- nDstY1
+ 1;
399 void AdjustTwoRect( SalTwoRect
& rTwoRect
, const tools::Rectangle
& rValidSrcRect
)
401 if( !(( rTwoRect
.mnSrcX
< rValidSrcRect
.Left() ) || ( rTwoRect
.mnSrcX
>= rValidSrcRect
.Right() ) ||
402 ( rTwoRect
.mnSrcY
< rValidSrcRect
.Top() ) || ( rTwoRect
.mnSrcY
>= rValidSrcRect
.Bottom() ) ||
403 ( ( rTwoRect
.mnSrcX
+ rTwoRect
.mnSrcWidth
) > rValidSrcRect
.Right() ) ||
404 ( ( rTwoRect
.mnSrcY
+ rTwoRect
.mnSrcHeight
) > rValidSrcRect
.Bottom() )) )
407 const tools::Rectangle
aSourceRect( Point( rTwoRect
.mnSrcX
, rTwoRect
.mnSrcY
),
408 Size( rTwoRect
.mnSrcWidth
, rTwoRect
.mnSrcHeight
) );
409 tools::Rectangle
aCropRect( aSourceRect
);
411 aCropRect
.Intersection( rValidSrcRect
);
413 if( aCropRect
.IsEmpty() )
415 rTwoRect
.mnSrcWidth
= rTwoRect
.mnSrcHeight
= rTwoRect
.mnDestWidth
= rTwoRect
.mnDestHeight
= 0;
419 const double fFactorX
= ( rTwoRect
.mnSrcWidth
> 1 ) ? static_cast<double>( rTwoRect
.mnDestWidth
- 1 ) / ( rTwoRect
.mnSrcWidth
- 1 ) : 0.0;
420 const double fFactorY
= ( rTwoRect
.mnSrcHeight
> 1 ) ? static_cast<double>( rTwoRect
.mnDestHeight
- 1 ) / ( rTwoRect
.mnSrcHeight
- 1 ) : 0.0;
422 const tools::Long nDstX1
= rTwoRect
.mnDestX
+ basegfx::fround
<tools::Long
>( fFactorX
* ( aCropRect
.Left() - rTwoRect
.mnSrcX
) );
423 const tools::Long nDstY1
= rTwoRect
.mnDestY
+ basegfx::fround
<tools::Long
>( fFactorY
* ( aCropRect
.Top() - rTwoRect
.mnSrcY
) );
424 const tools::Long nDstX2
= rTwoRect
.mnDestX
+ basegfx::fround
<tools::Long
>( fFactorX
* ( aCropRect
.Right() - rTwoRect
.mnSrcX
) );
425 const tools::Long nDstY2
= rTwoRect
.mnDestY
+ basegfx::fround
<tools::Long
>( fFactorY
* ( aCropRect
.Bottom() - rTwoRect
.mnSrcY
) );
427 rTwoRect
.mnSrcX
= aCropRect
.Left();
428 rTwoRect
.mnSrcY
= aCropRect
.Top();
429 rTwoRect
.mnSrcWidth
= aCropRect
.GetWidth();
430 rTwoRect
.mnSrcHeight
= aCropRect
.GetHeight();
431 rTwoRect
.mnDestX
= nDstX1
;
432 rTwoRect
.mnDestY
= nDstY1
;
433 rTwoRect
.mnDestWidth
= nDstX2
- nDstX1
+ 1;
434 rTwoRect
.mnDestHeight
= nDstY2
- nDstY1
+ 1;
438 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */