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
DrawBorder(tools::Rectangle aBorderRect)32 void OutputDevice::DrawBorder(tools::Rectangle aBorderRect)
33 {
34 sal_uInt16 nPixel = static_cast<sal_uInt16>(PixelToLogic(Size(1, 1)).Width());
35
36 aBorderRect.AdjustLeft(nPixel);
37 aBorderRect.AdjustTop(nPixel);
38
39 SetLineColor(COL_LIGHTGRAY);
40 DrawRect(aBorderRect);
41
42 aBorderRect.AdjustLeft(-nPixel);
43 aBorderRect.AdjustTop(-nPixel);
44 aBorderRect.AdjustRight(-nPixel);
45 aBorderRect.AdjustBottom(-nPixel);
46 SetLineColor(COL_GRAY);
47
48 DrawRect(aBorderRect);
49 }
50
DrawRect(const tools::Rectangle & rRect)51 void OutputDevice::DrawRect( const tools::Rectangle& rRect )
52 {
53 assert(!is_double_buffered_window());
54
55 if ( mpMetaFile )
56 mpMetaFile->AddAction( new MetaRectAction( rRect ) );
57
58 if ( !IsDeviceOutputNecessary() || (!mbLineColor && !mbFillColor) || ImplIsRecordLayout() )
59 return;
60
61 tools::Rectangle aRect( ImplLogicToDevicePixel( rRect ) );
62
63 if ( aRect.IsEmpty() )
64 return;
65
66 aRect.Justify();
67
68 if ( !mpGraphics && !AcquireGraphics() )
69 return;
70 assert(mpGraphics);
71
72 if ( mbInitClipRegion )
73 InitClipRegion();
74
75 if ( mbOutputClipped )
76 return;
77
78 if ( mbInitLineColor )
79 InitLineColor();
80
81 if ( mbInitFillColor )
82 InitFillColor();
83
84 mpGraphics->DrawRect( aRect.Left(), aRect.Top(), aRect.GetWidth(), aRect.GetHeight(), *this );
85
86 if( mpAlphaVDev )
87 mpAlphaVDev->DrawRect( rRect );
88 }
89
DrawRect(const tools::Rectangle & rRect,sal_uLong nHorzRound,sal_uLong nVertRound)90 void OutputDevice::DrawRect( const tools::Rectangle& rRect,
91 sal_uLong nHorzRound, sal_uLong nVertRound )
92 {
93 assert(!is_double_buffered_window());
94
95 if ( mpMetaFile )
96 mpMetaFile->AddAction( new MetaRoundRectAction( rRect, nHorzRound, nVertRound ) );
97
98 if ( !IsDeviceOutputNecessary() || (!mbLineColor && !mbFillColor) || ImplIsRecordLayout() )
99 return;
100
101 const tools::Rectangle aRect( ImplLogicToDevicePixel( rRect ) );
102
103 if ( aRect.IsEmpty() )
104 return;
105
106 nHorzRound = ImplLogicWidthToDevicePixel( nHorzRound );
107 nVertRound = ImplLogicHeightToDevicePixel( nVertRound );
108
109 // we need a graphics
110 if ( !mpGraphics && !AcquireGraphics() )
111 return;
112 assert(mpGraphics);
113
114 if ( mbInitClipRegion )
115 InitClipRegion();
116
117 if ( mbOutputClipped )
118 return;
119
120 if ( mbInitLineColor )
121 InitLineColor();
122
123 if ( mbInitFillColor )
124 InitFillColor();
125
126 if ( !nHorzRound && !nVertRound )
127 {
128 mpGraphics->DrawRect( aRect.Left(), aRect.Top(), aRect.GetWidth(), aRect.GetHeight(), *this );
129 }
130 else
131 {
132 tools::Polygon aRoundRectPoly( aRect, nHorzRound, nVertRound );
133
134 if ( aRoundRectPoly.GetSize() >= 2 )
135 {
136 Point* pPtAry = aRoundRectPoly.GetPointAry();
137
138 if ( !mbFillColor )
139 mpGraphics->DrawPolyLine( aRoundRectPoly.GetSize(), pPtAry, *this );
140 else
141 mpGraphics->DrawPolygon( aRoundRectPoly.GetSize(), pPtAry, *this );
142 }
143 }
144
145 if( mpAlphaVDev )
146 mpAlphaVDev->DrawRect( rRect, nHorzRound, nVertRound );
147 }
148
Invert(const tools::Rectangle & rRect,InvertFlags nFlags)149 void OutputDevice::Invert( const tools::Rectangle& rRect, InvertFlags nFlags )
150 {
151 assert(!is_double_buffered_window());
152 if ( !IsDeviceOutputNecessary() )
153 return;
154
155 tools::Rectangle aRect( ImplLogicToDevicePixel( rRect ) );
156
157 if ( aRect.IsEmpty() )
158 return;
159 aRect.Justify();
160
161 // we need a graphics
162 if ( !mpGraphics && !AcquireGraphics() )
163 return;
164 assert(mpGraphics);
165
166 if ( mbInitClipRegion )
167 InitClipRegion();
168
169 if ( mbOutputClipped )
170 return;
171
172 SalInvert nSalFlags = SalInvert::NONE;
173 if ( nFlags & InvertFlags::N50 )
174 nSalFlags |= SalInvert::N50;
175 if ( nFlags & InvertFlags::TrackFrame )
176 nSalFlags |= SalInvert::TrackFrame;
177 mpGraphics->Invert( aRect.Left(), aRect.Top(), aRect.GetWidth(), aRect.GetHeight(), nSalFlags, *this );
178 }
179
Invert(const tools::Polygon & rPoly,InvertFlags nFlags)180 void OutputDevice::Invert( const tools::Polygon& rPoly, InvertFlags nFlags )
181 {
182 assert(!is_double_buffered_window());
183 if ( !IsDeviceOutputNecessary() )
184 return;
185
186 sal_uInt16 nPoints = rPoly.GetSize();
187
188 if ( nPoints < 2 )
189 return;
190
191 tools::Polygon aPoly( ImplLogicToDevicePixel( rPoly ) );
192
193 // we need a graphics
194 if ( !mpGraphics && !AcquireGraphics() )
195 return;
196 assert(mpGraphics);
197
198 if ( mbInitClipRegion )
199 InitClipRegion();
200
201 if ( mbOutputClipped )
202 return;
203
204 SalInvert nSalFlags = SalInvert::NONE;
205 if ( nFlags & InvertFlags::N50 )
206 nSalFlags |= SalInvert::N50;
207 if ( nFlags & InvertFlags::TrackFrame )
208 nSalFlags |= SalInvert::TrackFrame;
209 const Point* pPtAry = aPoly.GetConstPointAry();
210 mpGraphics->Invert( nPoints, pPtAry, nSalFlags, *this );
211 }
212
DrawCheckered(const Point & rPos,const Size & rSize,sal_uInt32 nLen,Color aStart,Color aEnd)213 void OutputDevice::DrawCheckered(const Point& rPos, const Size& rSize, sal_uInt32 nLen, Color aStart, Color aEnd)
214 {
215 assert(!is_double_buffered_window());
216
217 const sal_uInt32 nMaxX(rPos.X() + rSize.Width());
218 const sal_uInt32 nMaxY(rPos.Y() + rSize.Height());
219
220 Push(PushFlags::LINECOLOR|PushFlags::FILLCOLOR);
221 SetLineColor();
222
223 for(sal_uInt32 x(0), nX(rPos.X()); nX < nMaxX; x++, nX += nLen)
224 {
225 const sal_uInt32 nRight(std::min(nMaxX, nX + nLen));
226
227 for(sal_uInt32 y(0), nY(rPos.Y()); nY < nMaxY; y++, nY += nLen)
228 {
229 const sal_uInt32 nBottom(std::min(nMaxY, nY + nLen));
230
231 SetFillColor(((x & 0x0001) ^ (y & 0x0001)) ? aStart : aEnd);
232 DrawRect(tools::Rectangle(nX, nY, nRight, nBottom));
233 }
234 }
235
236 Pop();
237 }
238
DrawGrid(const tools::Rectangle & rRect,const Size & rDist,DrawGridFlags nFlags)239 void OutputDevice::DrawGrid( const tools::Rectangle& rRect, const Size& rDist, DrawGridFlags nFlags )
240 {
241 assert(!is_double_buffered_window());
242
243 tools::Rectangle aDstRect( PixelToLogic( Point() ), GetOutputSize() );
244 aDstRect.Intersection( rRect );
245
246 if( aDstRect.IsEmpty() || ImplIsRecordLayout() )
247 return;
248
249 if( !mpGraphics && !AcquireGraphics() )
250 return;
251 assert(mpGraphics);
252
253 if( mbInitClipRegion )
254 InitClipRegion();
255
256 if( mbOutputClipped )
257 return;
258
259 const tools::Long nDistX = std::max( rDist.Width(), tools::Long(1) );
260 const tools::Long nDistY = std::max( rDist.Height(), tools::Long(1) );
261 tools::Long nX = ( rRect.Left() >= aDstRect.Left() ) ? rRect.Left() : ( rRect.Left() + ( ( aDstRect.Left() - rRect.Left() ) / nDistX ) * nDistX );
262 tools::Long nY = ( rRect.Top() >= aDstRect.Top() ) ? rRect.Top() : ( rRect.Top() + ( ( aDstRect.Top() - rRect.Top() ) / nDistY ) * nDistY );
263 const tools::Long nRight = aDstRect.Right();
264 const tools::Long nBottom = aDstRect.Bottom();
265 const tools::Long nStartX = ImplLogicXToDevicePixel( nX );
266 const tools::Long nEndX = ImplLogicXToDevicePixel( nRight );
267 const tools::Long nStartY = ImplLogicYToDevicePixel( nY );
268 const tools::Long nEndY = ImplLogicYToDevicePixel( nBottom );
269 tools::Long nHorzCount = 0;
270 tools::Long nVertCount = 0;
271
272 std::vector< sal_Int32 > aVertBuf;
273 std::vector< sal_Int32 > aHorzBuf;
274
275 if( ( nFlags & DrawGridFlags::Dots ) || ( nFlags & DrawGridFlags::HorzLines ) )
276 {
277 aVertBuf.resize( aDstRect.GetHeight() / nDistY + 2 );
278 aVertBuf[ nVertCount++ ] = nStartY;
279 while( ( nY += nDistY ) <= nBottom )
280 {
281 aVertBuf[ nVertCount++ ] = ImplLogicYToDevicePixel( nY );
282 }
283 }
284
285 if( ( nFlags & DrawGridFlags::Dots ) || ( nFlags & DrawGridFlags::VertLines ) )
286 {
287 aHorzBuf.resize( aDstRect.GetWidth() / nDistX + 2 );
288 aHorzBuf[ nHorzCount++ ] = nStartX;
289 while( ( nX += nDistX ) <= nRight )
290 {
291 aHorzBuf[ nHorzCount++ ] = ImplLogicXToDevicePixel( nX );
292 }
293 }
294
295 if( mbInitLineColor )
296 InitLineColor();
297
298 if( mbInitFillColor )
299 InitFillColor();
300
301 const bool bOldMap = mbMap;
302 EnableMapMode( false );
303
304 if( nFlags & DrawGridFlags::Dots )
305 {
306 for( tools::Long i = 0; i < nVertCount; i++ )
307 {
308 for( tools::Long j = 0, Y = aVertBuf[ i ]; j < nHorzCount; j++ )
309 {
310 mpGraphics->DrawPixel( aHorzBuf[ j ], Y, *this );
311 }
312 }
313 }
314 else
315 {
316 if( nFlags & DrawGridFlags::HorzLines )
317 {
318 for( tools::Long i = 0; i < nVertCount; i++ )
319 {
320 nY = aVertBuf[ i ];
321 mpGraphics->DrawLine( nStartX, nY, nEndX, nY, *this );
322 }
323 }
324
325 if( nFlags & DrawGridFlags::VertLines )
326 {
327 for( tools::Long i = 0; i < nHorzCount; i++ )
328 {
329 nX = aHorzBuf[ i ];
330 mpGraphics->DrawLine( nX, nStartY, nX, nEndY, *this );
331 }
332 }
333 }
334
335 EnableMapMode( bOldMap );
336
337 if( mpAlphaVDev )
338 mpAlphaVDev->DrawGrid( rRect, rDist, nFlags );
339 }
340
AdjustTwoRect(SalTwoRect & rTwoRect,const Size & rSizePix)341 BmpMirrorFlags AdjustTwoRect( SalTwoRect& rTwoRect, const Size& rSizePix )
342 {
343 BmpMirrorFlags nMirrFlags = BmpMirrorFlags::NONE;
344
345 if ( rTwoRect.mnDestWidth < 0 )
346 {
347 rTwoRect.mnSrcX = rSizePix.Width() - rTwoRect.mnSrcX - rTwoRect.mnSrcWidth;
348 rTwoRect.mnDestWidth = -rTwoRect.mnDestWidth;
349 rTwoRect.mnDestX -= rTwoRect.mnDestWidth-1;
350 nMirrFlags |= BmpMirrorFlags::Horizontal;
351 }
352
353 if ( rTwoRect.mnDestHeight < 0 )
354 {
355 rTwoRect.mnSrcY = rSizePix.Height() - rTwoRect.mnSrcY - rTwoRect.mnSrcHeight;
356 rTwoRect.mnDestHeight = -rTwoRect.mnDestHeight;
357 rTwoRect.mnDestY -= rTwoRect.mnDestHeight-1;
358 nMirrFlags |= BmpMirrorFlags::Vertical;
359 }
360
361 if( ( rTwoRect.mnSrcX < 0 ) || ( rTwoRect.mnSrcX >= rSizePix.Width() ) ||
362 ( rTwoRect.mnSrcY < 0 ) || ( rTwoRect.mnSrcY >= rSizePix.Height() ) ||
363 ( ( rTwoRect.mnSrcX + rTwoRect.mnSrcWidth ) > rSizePix.Width() ) ||
364 ( ( rTwoRect.mnSrcY + rTwoRect.mnSrcHeight ) > rSizePix.Height() ) )
365 {
366 const tools::Rectangle aSourceRect( Point( rTwoRect.mnSrcX, rTwoRect.mnSrcY ),
367 Size( rTwoRect.mnSrcWidth, rTwoRect.mnSrcHeight ) );
368 tools::Rectangle aCropRect( aSourceRect );
369
370 aCropRect.Intersection( tools::Rectangle( Point(), rSizePix ) );
371
372 if( aCropRect.IsEmpty() )
373 {
374 rTwoRect.mnSrcWidth = rTwoRect.mnSrcHeight = rTwoRect.mnDestWidth = rTwoRect.mnDestHeight = 0;
375 }
376 else
377 {
378 const double fFactorX = ( rTwoRect.mnSrcWidth > 1 ) ? static_cast<double>( rTwoRect.mnDestWidth - 1 ) / ( rTwoRect.mnSrcWidth - 1 ) : 0.0;
379 const double fFactorY = ( rTwoRect.mnSrcHeight > 1 ) ? static_cast<double>( rTwoRect.mnDestHeight - 1 ) / ( rTwoRect.mnSrcHeight - 1 ) : 0.0;
380
381 const tools::Long nDstX1 = rTwoRect.mnDestX + FRound( fFactorX * ( aCropRect.Left() - rTwoRect.mnSrcX ) );
382 const tools::Long nDstY1 = rTwoRect.mnDestY + FRound( fFactorY * ( aCropRect.Top() - rTwoRect.mnSrcY ) );
383 const tools::Long nDstX2 = rTwoRect.mnDestX + FRound( fFactorX * ( aCropRect.Right() - rTwoRect.mnSrcX ) );
384 const tools::Long nDstY2 = rTwoRect.mnDestY + FRound( fFactorY * ( aCropRect.Bottom() - rTwoRect.mnSrcY ) );
385
386 rTwoRect.mnSrcX = aCropRect.Left();
387 rTwoRect.mnSrcY = aCropRect.Top();
388 rTwoRect.mnSrcWidth = aCropRect.GetWidth();
389 rTwoRect.mnSrcHeight = aCropRect.GetHeight();
390 rTwoRect.mnDestX = nDstX1;
391 rTwoRect.mnDestY = nDstY1;
392 rTwoRect.mnDestWidth = nDstX2 - nDstX1 + 1;
393 rTwoRect.mnDestHeight = nDstY2 - nDstY1 + 1;
394 }
395 }
396
397 return nMirrFlags;
398 }
399
AdjustTwoRect(SalTwoRect & rTwoRect,const tools::Rectangle & rValidSrcRect)400 void AdjustTwoRect( SalTwoRect& rTwoRect, const tools::Rectangle& rValidSrcRect )
401 {
402 if( !(( rTwoRect.mnSrcX < rValidSrcRect.Left() ) || ( rTwoRect.mnSrcX >= rValidSrcRect.Right() ) ||
403 ( rTwoRect.mnSrcY < rValidSrcRect.Top() ) || ( rTwoRect.mnSrcY >= rValidSrcRect.Bottom() ) ||
404 ( ( rTwoRect.mnSrcX + rTwoRect.mnSrcWidth ) > rValidSrcRect.Right() ) ||
405 ( ( rTwoRect.mnSrcY + rTwoRect.mnSrcHeight ) > rValidSrcRect.Bottom() )) )
406 return;
407
408 const tools::Rectangle aSourceRect( Point( rTwoRect.mnSrcX, rTwoRect.mnSrcY ),
409 Size( rTwoRect.mnSrcWidth, rTwoRect.mnSrcHeight ) );
410 tools::Rectangle aCropRect( aSourceRect );
411
412 aCropRect.Intersection( rValidSrcRect );
413
414 if( aCropRect.IsEmpty() )
415 {
416 rTwoRect.mnSrcWidth = rTwoRect.mnSrcHeight = rTwoRect.mnDestWidth = rTwoRect.mnDestHeight = 0;
417 }
418 else
419 {
420 const double fFactorX = ( rTwoRect.mnSrcWidth > 1 ) ? static_cast<double>( rTwoRect.mnDestWidth - 1 ) / ( rTwoRect.mnSrcWidth - 1 ) : 0.0;
421 const double fFactorY = ( rTwoRect.mnSrcHeight > 1 ) ? static_cast<double>( rTwoRect.mnDestHeight - 1 ) / ( rTwoRect.mnSrcHeight - 1 ) : 0.0;
422
423 const tools::Long nDstX1 = rTwoRect.mnDestX + FRound( fFactorX * ( aCropRect.Left() - rTwoRect.mnSrcX ) );
424 const tools::Long nDstY1 = rTwoRect.mnDestY + FRound( fFactorY * ( aCropRect.Top() - rTwoRect.mnSrcY ) );
425 const tools::Long nDstX2 = rTwoRect.mnDestX + FRound( fFactorX * ( aCropRect.Right() - rTwoRect.mnSrcX ) );
426 const tools::Long nDstY2 = rTwoRect.mnDestY + FRound( fFactorY * ( aCropRect.Bottom() - rTwoRect.mnSrcY ) );
427
428 rTwoRect.mnSrcX = aCropRect.Left();
429 rTwoRect.mnSrcY = aCropRect.Top();
430 rTwoRect.mnSrcWidth = aCropRect.GetWidth();
431 rTwoRect.mnSrcHeight = aCropRect.GetHeight();
432 rTwoRect.mnDestX = nDstX1;
433 rTwoRect.mnDestY = nDstY1;
434 rTwoRect.mnDestWidth = nDstX2 - nDstX1 + 1;
435 rTwoRect.mnDestHeight = nDstY2 - nDstY1 + 1;
436 }
437 }
438
439 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
440