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 .
22 #include <sal/types.h>
24 #include <tools/poly.hxx>
25 #include <tools/helpers.hxx>
27 #include <vcl/outdev.hxx>
28 #include <vcl/virdev.hxx>
29 #include <vcl/window.hxx>
33 void OutputDevice::DrawRect( const Rectangle
& rRect
)
35 assert(!is_double_buffered_window());
38 mpMetaFile
->AddAction( new MetaRectAction( rRect
) );
40 if ( !IsDeviceOutputNecessary() || (!mbLineColor
&& !mbFillColor
) || ImplIsRecordLayout() )
43 Rectangle
aRect( ImplLogicToDevicePixel( rRect
) );
45 if ( aRect
.IsEmpty() )
50 if ( !mpGraphics
&& !AcquireGraphics() )
53 if ( mbInitClipRegion
)
56 if ( mbOutputClipped
)
59 if ( mbInitLineColor
)
62 if ( mbInitFillColor
)
65 mpGraphics
->DrawRect( aRect
.Left(), aRect
.Top(), aRect
.GetWidth(), aRect
.GetHeight(), this );
68 mpAlphaVDev
->DrawRect( rRect
);
71 void OutputDevice::DrawRect( const Rectangle
& rRect
,
72 sal_uLong nHorzRound
, sal_uLong nVertRound
)
74 assert(!is_double_buffered_window());
77 mpMetaFile
->AddAction( new MetaRoundRectAction( rRect
, nHorzRound
, nVertRound
) );
79 if ( !IsDeviceOutputNecessary() || (!mbLineColor
&& !mbFillColor
) || ImplIsRecordLayout() )
82 const Rectangle
aRect( ImplLogicToDevicePixel( rRect
) );
84 if ( aRect
.IsEmpty() )
87 nHorzRound
= ImplLogicWidthToDevicePixel( nHorzRound
);
88 nVertRound
= ImplLogicHeightToDevicePixel( nVertRound
);
93 if ( !AcquireGraphics() )
97 if ( mbInitClipRegion
)
100 if ( mbOutputClipped
)
103 if ( mbInitLineColor
)
106 if ( mbInitFillColor
)
109 if ( !nHorzRound
&& !nVertRound
)
111 mpGraphics
->DrawRect( aRect
.Left(), aRect
.Top(), aRect
.GetWidth(), aRect
.GetHeight(), this );
115 const Polygon
aRoundRectPoly( aRect
, nHorzRound
, nVertRound
);
117 if ( aRoundRectPoly
.GetSize() >= 2 )
119 const SalPoint
* pPtAry
= reinterpret_cast<const SalPoint
*>(aRoundRectPoly
.GetConstPointAry());
122 mpGraphics
->DrawPolyLine( aRoundRectPoly
.GetSize(), pPtAry
, this );
124 mpGraphics
->DrawPolygon( aRoundRectPoly
.GetSize(), pPtAry
, this );
129 mpAlphaVDev
->DrawRect( rRect
, nHorzRound
, nVertRound
);
132 void OutputDevice::Invert( const Rectangle
& rRect
, sal_uInt16 nFlags
)
134 assert(!is_double_buffered_window());
135 if ( !IsDeviceOutputNecessary() )
138 Rectangle
aRect( ImplLogicToDevicePixel( rRect
) );
140 if ( aRect
.IsEmpty() )
144 // we need a graphics
147 if ( !AcquireGraphics() )
151 if ( mbInitClipRegion
)
154 if ( mbOutputClipped
)
157 SalInvert nSalFlags
= 0;
158 if ( nFlags
& INVERT_HIGHLIGHT
)
159 nSalFlags
|= SAL_INVERT_HIGHLIGHT
;
160 if ( nFlags
& INVERT_50
)
161 nSalFlags
|= SAL_INVERT_50
;
162 mpGraphics
->Invert( aRect
.Left(), aRect
.Top(), aRect
.GetWidth(), aRect
.GetHeight(), nSalFlags
, this );
165 void OutputDevice::Invert( const Polygon
& rPoly
, sal_uInt16 nFlags
)
167 assert(!is_double_buffered_window());
168 if ( !IsDeviceOutputNecessary() )
171 sal_uInt16 nPoints
= rPoly
.GetSize();
176 Polygon
aPoly( ImplLogicToDevicePixel( rPoly
) );
178 // we need a graphics
181 if ( !AcquireGraphics() )
185 if ( mbInitClipRegion
)
188 if ( mbOutputClipped
)
191 SalInvert nSalFlags
= 0;
192 if ( nFlags
& INVERT_HIGHLIGHT
)
193 nSalFlags
|= SAL_INVERT_HIGHLIGHT
;
194 if ( nFlags
& INVERT_50
)
195 nSalFlags
|= SAL_INVERT_50
;
196 const SalPoint
* pPtAry
= reinterpret_cast<const SalPoint
*>(aPoly
.GetConstPointAry());
197 mpGraphics
->Invert( nPoints
, pPtAry
, nSalFlags
, this );
200 void OutputDevice::DrawCheckered(const Point
& rPos
, const Size
& rSize
, sal_uInt32 nLen
, Color aStart
, Color aEnd
)
202 assert(!is_double_buffered_window());
204 const sal_uInt32
nMaxX(rPos
.X() + rSize
.Width());
205 const sal_uInt32
nMaxY(rPos
.Y() + rSize
.Height());
207 Push(PushFlags::LINECOLOR
|PushFlags::FILLCOLOR
);
210 for(sal_uInt32
x(0), nX(rPos
.X()); nX
< nMaxX
; x
++, nX
+= nLen
)
212 const sal_uInt32
nRight(std::min(nMaxX
, nX
+ nLen
));
214 for(sal_uInt32
y(0), nY(rPos
.Y()); nY
< nMaxY
; y
++, nY
+= nLen
)
216 const sal_uInt32
nBottom(std::min(nMaxY
, nY
+ nLen
));
218 SetFillColor((x
& 0x0001) ^ (y
& 0x0001) ? aStart
: aEnd
);
219 DrawRect(Rectangle(nX
, nY
, nRight
, nBottom
));
226 void OutputDevice::DrawGrid( const Rectangle
& rRect
, const Size
& rDist
, DrawGridFlags nFlags
)
228 assert(!is_double_buffered_window());
230 Rectangle
aDstRect( PixelToLogic( Point() ), GetOutputSize() );
231 aDstRect
.Intersection( rRect
);
233 if( aDstRect
.IsEmpty() || ImplIsRecordLayout() )
236 if( !mpGraphics
&& !AcquireGraphics() )
239 if( mbInitClipRegion
)
242 if( mbOutputClipped
)
245 const long nDistX
= std::max( rDist
.Width(), 1L );
246 const long nDistY
= std::max( rDist
.Height(), 1L );
247 long nX
= ( rRect
.Left() >= aDstRect
.Left() ) ? rRect
.Left() : ( rRect
.Left() + ( ( aDstRect
.Left() - rRect
.Left() ) / nDistX
) * nDistX
);
248 long nY
= ( rRect
.Top() >= aDstRect
.Top() ) ? rRect
.Top() : ( rRect
.Top() + ( ( aDstRect
.Top() - rRect
.Top() ) / nDistY
) * nDistY
);
249 const long nRight
= aDstRect
.Right();
250 const long nBottom
= aDstRect
.Bottom();
251 const long nStartX
= ImplLogicXToDevicePixel( nX
);
252 const long nEndX
= ImplLogicXToDevicePixel( nRight
);
253 const long nStartY
= ImplLogicYToDevicePixel( nY
);
254 const long nEndY
= ImplLogicYToDevicePixel( nBottom
);
255 long nHorzCount
= 0L;
256 long nVertCount
= 0L;
258 css::uno::Sequence
< sal_Int32
> aVertBuf
;
259 css::uno::Sequence
< sal_Int32
> aHorzBuf
;
261 if( ( nFlags
& DrawGridFlags::Dots
) || ( nFlags
& DrawGridFlags::HorzLines
) )
263 aVertBuf
.realloc( aDstRect
.GetHeight() / nDistY
+ 2L );
264 aVertBuf
[ nVertCount
++ ] = nStartY
;
265 while( ( nY
+= nDistY
) <= nBottom
)
267 aVertBuf
[ nVertCount
++ ] = ImplLogicYToDevicePixel( nY
);
271 if( ( nFlags
& DrawGridFlags::Dots
) || ( nFlags
& DrawGridFlags::VertLines
) )
273 aHorzBuf
.realloc( aDstRect
.GetWidth() / nDistX
+ 2L );
274 aHorzBuf
[ nHorzCount
++ ] = nStartX
;
275 while( ( nX
+= nDistX
) <= nRight
)
277 aHorzBuf
[ nHorzCount
++ ] = ImplLogicXToDevicePixel( nX
);
281 if( mbInitLineColor
)
284 if( mbInitFillColor
)
287 const bool bOldMap
= mbMap
;
288 EnableMapMode( false );
290 if( nFlags
& DrawGridFlags::Dots
)
292 for( long i
= 0L; i
< nVertCount
; i
++ )
294 for( long j
= 0L, Y
= aVertBuf
[ i
]; j
< nHorzCount
; j
++ )
296 mpGraphics
->DrawPixel( aHorzBuf
[ j
], Y
, this );
302 if( nFlags
& DrawGridFlags::HorzLines
)
304 for( long i
= 0L; i
< nVertCount
; i
++ )
307 mpGraphics
->DrawLine( nStartX
, nY
, nEndX
, nY
, this );
311 if( nFlags
& DrawGridFlags::VertLines
)
313 for( long i
= 0L; i
< nHorzCount
; i
++ )
316 mpGraphics
->DrawLine( nX
, nStartY
, nX
, nEndY
, this );
321 EnableMapMode( bOldMap
);
324 mpAlphaVDev
->DrawGrid( rRect
, rDist
, nFlags
);
327 BmpMirrorFlags
AdjustTwoRect( SalTwoRect
& rTwoRect
, const Size
& rSizePix
)
329 BmpMirrorFlags nMirrFlags
= BmpMirrorFlags::NONE
;
331 if ( rTwoRect
.mnDestWidth
< 0 )
333 rTwoRect
.mnSrcX
= rSizePix
.Width() - rTwoRect
.mnSrcX
- rTwoRect
.mnSrcWidth
;
334 rTwoRect
.mnDestWidth
= -rTwoRect
.mnDestWidth
;
335 rTwoRect
.mnDestX
-= rTwoRect
.mnDestWidth
-1;
336 nMirrFlags
|= BmpMirrorFlags::Horizontal
;
339 if ( rTwoRect
.mnDestHeight
< 0 )
341 rTwoRect
.mnSrcY
= rSizePix
.Height() - rTwoRect
.mnSrcY
- rTwoRect
.mnSrcHeight
;
342 rTwoRect
.mnDestHeight
= -rTwoRect
.mnDestHeight
;
343 rTwoRect
.mnDestY
-= rTwoRect
.mnDestHeight
-1;
344 nMirrFlags
|= BmpMirrorFlags::Vertical
;
347 if( ( rTwoRect
.mnSrcX
< 0 ) || ( rTwoRect
.mnSrcX
>= rSizePix
.Width() ) ||
348 ( rTwoRect
.mnSrcY
< 0 ) || ( rTwoRect
.mnSrcY
>= rSizePix
.Height() ) ||
349 ( ( rTwoRect
.mnSrcX
+ rTwoRect
.mnSrcWidth
) > rSizePix
.Width() ) ||
350 ( ( rTwoRect
.mnSrcY
+ rTwoRect
.mnSrcHeight
) > rSizePix
.Height() ) )
352 const Rectangle
aSourceRect( Point( rTwoRect
.mnSrcX
, rTwoRect
.mnSrcY
),
353 Size( rTwoRect
.mnSrcWidth
, rTwoRect
.mnSrcHeight
) );
354 Rectangle
aCropRect( aSourceRect
);
356 aCropRect
.Intersection( Rectangle( Point(), rSizePix
) );
358 if( aCropRect
.IsEmpty() )
360 rTwoRect
.mnSrcWidth
= rTwoRect
.mnSrcHeight
= rTwoRect
.mnDestWidth
= rTwoRect
.mnDestHeight
= 0;
364 const double fFactorX
= ( rTwoRect
.mnSrcWidth
> 1 ) ? (double) ( rTwoRect
.mnDestWidth
- 1 ) / ( rTwoRect
.mnSrcWidth
- 1 ) : 0.0;
365 const double fFactorY
= ( rTwoRect
.mnSrcHeight
> 1 ) ? (double) ( rTwoRect
.mnDestHeight
- 1 ) / ( rTwoRect
.mnSrcHeight
- 1 ) : 0.0;
367 const long nDstX1
= rTwoRect
.mnDestX
+ FRound( fFactorX
* ( aCropRect
.Left() - rTwoRect
.mnSrcX
) );
368 const long nDstY1
= rTwoRect
.mnDestY
+ FRound( fFactorY
* ( aCropRect
.Top() - rTwoRect
.mnSrcY
) );
369 const long nDstX2
= rTwoRect
.mnDestX
+ FRound( fFactorX
* ( aCropRect
.Right() - rTwoRect
.mnSrcX
) );
370 const long nDstY2
= rTwoRect
.mnDestY
+ FRound( fFactorY
* ( aCropRect
.Bottom() - rTwoRect
.mnSrcY
) );
372 rTwoRect
.mnSrcX
= aCropRect
.Left();
373 rTwoRect
.mnSrcY
= aCropRect
.Top();
374 rTwoRect
.mnSrcWidth
= aCropRect
.GetWidth();
375 rTwoRect
.mnSrcHeight
= aCropRect
.GetHeight();
376 rTwoRect
.mnDestX
= nDstX1
;
377 rTwoRect
.mnDestY
= nDstY1
;
378 rTwoRect
.mnDestWidth
= nDstX2
- nDstX1
+ 1;
379 rTwoRect
.mnDestHeight
= nDstY2
- nDstY1
+ 1;
386 void AdjustTwoRect( SalTwoRect
& rTwoRect
, const Rectangle
& rValidSrcRect
)
388 if( ( rTwoRect
.mnSrcX
< rValidSrcRect
.Left() ) || ( rTwoRect
.mnSrcX
>= rValidSrcRect
.Right() ) ||
389 ( rTwoRect
.mnSrcY
< rValidSrcRect
.Top() ) || ( rTwoRect
.mnSrcY
>= rValidSrcRect
.Bottom() ) ||
390 ( ( rTwoRect
.mnSrcX
+ rTwoRect
.mnSrcWidth
) > rValidSrcRect
.Right() ) ||
391 ( ( rTwoRect
.mnSrcY
+ rTwoRect
.mnSrcHeight
) > rValidSrcRect
.Bottom() ) )
393 const Rectangle
aSourceRect( Point( rTwoRect
.mnSrcX
, rTwoRect
.mnSrcY
),
394 Size( rTwoRect
.mnSrcWidth
, rTwoRect
.mnSrcHeight
) );
395 Rectangle
aCropRect( aSourceRect
);
397 aCropRect
.Intersection( rValidSrcRect
);
399 if( aCropRect
.IsEmpty() )
401 rTwoRect
.mnSrcWidth
= rTwoRect
.mnSrcHeight
= rTwoRect
.mnDestWidth
= rTwoRect
.mnDestHeight
= 0;
405 const double fFactorX
= ( rTwoRect
.mnSrcWidth
> 1 ) ? (double) ( rTwoRect
.mnDestWidth
- 1 ) / ( rTwoRect
.mnSrcWidth
- 1 ) : 0.0;
406 const double fFactorY
= ( rTwoRect
.mnSrcHeight
> 1 ) ? (double) ( rTwoRect
.mnDestHeight
- 1 ) / ( rTwoRect
.mnSrcHeight
- 1 ) : 0.0;
408 const long nDstX1
= rTwoRect
.mnDestX
+ FRound( fFactorX
* ( aCropRect
.Left() - rTwoRect
.mnSrcX
) );
409 const long nDstY1
= rTwoRect
.mnDestY
+ FRound( fFactorY
* ( aCropRect
.Top() - rTwoRect
.mnSrcY
) );
410 const long nDstX2
= rTwoRect
.mnDestX
+ FRound( fFactorX
* ( aCropRect
.Right() - rTwoRect
.mnSrcX
) );
411 const long nDstY2
= rTwoRect
.mnDestY
+ FRound( fFactorY
* ( aCropRect
.Bottom() - rTwoRect
.mnSrcY
) );
413 rTwoRect
.mnSrcX
= aCropRect
.Left();
414 rTwoRect
.mnSrcY
= aCropRect
.Top();
415 rTwoRect
.mnSrcWidth
= aCropRect
.GetWidth();
416 rTwoRect
.mnSrcHeight
= aCropRect
.GetHeight();
417 rTwoRect
.mnDestX
= nDstX1
;
418 rTwoRect
.mnDestY
= nDstY1
;
419 rTwoRect
.mnDestWidth
= nDstX2
- nDstX1
+ 1;
420 rTwoRect
.mnDestHeight
= nDstY2
- nDstY1
+ 1;
425 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */