]> git.saurik.com Git - wxWidgets.git/blame - src/msw/dc.cpp
Fixed HRGN leak in DoSetClippingRegion
[wxWidgets.git] / src / msw / dc.cpp
CommitLineData
2bda0e17
KB
1/////////////////////////////////////////////////////////////////////////////
2// Name: dc.cpp
3// Purpose: wxDC class
4// Author: Julian Smart
5// Modified by:
6// Created: 01/02/97
7// RCS-ID: $Id$
8// Copyright: (c) Julian Smart and Markus Holzem
fd3f686c 9// Licence: wxWindows licence
2bda0e17
KB
10/////////////////////////////////////////////////////////////////////////////
11
a23fd0e1
VZ
12// ===========================================================================
13// declarations
14// ===========================================================================
15
16// ---------------------------------------------------------------------------
17// headers
18// ---------------------------------------------------------------------------
19
2bda0e17 20#ifdef __GNUG__
a23fd0e1 21 #pragma implementation "dc.h"
2bda0e17
KB
22#endif
23
24// For compilers that support precompilation, includes "wx.h".
25#include "wx/wxprec.h"
26
27#ifdef __BORLANDC__
a23fd0e1 28 #pragma hdrstop
2bda0e17
KB
29#endif
30
31#ifndef WX_PRECOMP
4286a5b5 32 #include "wx/window.h"
a23fd0e1
VZ
33 #include "wx/dc.h"
34 #include "wx/utils.h"
35 #include "wx/dialog.h"
36 #include "wx/app.h"
37 #include "wx/bitmap.h"
38 #include "wx/dcmemory.h"
0c589ad0 39 #include "wx/log.h"
4286a5b5 40 #include "wx/icon.h"
2bda0e17
KB
41#endif
42
840bb342 43#include "wx/settings.h"
2bda0e17 44#include "wx/dcprint.h"
2bda0e17
KB
45
46#include <string.h>
47#include <math.h>
2bda0e17 48
a58a12e9
VZ
49#include "wx/msw/private.h" // needs to be before #include <commdlg.h>
50
47d67540 51#if wxUSE_COMMON_DIALOGS
a23fd0e1 52 #include <commdlg.h>
2bda0e17
KB
53#endif
54
55#ifndef __WIN32__
a23fd0e1 56 #include <print.h>
2bda0e17
KB
57#endif
58
5acb7b3e 59IMPLEMENT_ABSTRACT_CLASS(wxDC, wxDCBase)
2bda0e17 60
a23fd0e1
VZ
61// ---------------------------------------------------------------------------
62// constants
63// ---------------------------------------------------------------------------
64
42e69d6b
VZ
65static const int VIEWPORT_EXTENT = 1000;
66
67static const int MM_POINTS = 9;
68static const int MM_METRIC = 10;
a23fd0e1 69
4314ec48
VZ
70// usually this is defined in math.h
71#ifndef M_PI
72 static const double M_PI = 3.14159265358979323846;
73#endif // M_PI
74
4aff28fc
VZ
75// ROPs which don't have standard names (see "Ternary Raster Operations" in the
76// MSDN docs for how this and other numbers in wxDC::Blit() are obtained)
77#define DSTCOPY 0x00AA0029 // a.k.a. NOP operation
78
4314ec48
VZ
79// ---------------------------------------------------------------------------
80// private functions
81// ---------------------------------------------------------------------------
82
83// convert degrees to radians
84static inline double DegToRad(double deg) { return (deg * M_PI) / 180.0; }
85
f6bcfd97
BP
86// ----------------------------------------------------------------------------
87// private classes
88// ----------------------------------------------------------------------------
89
90// instead of duplicating the same code which sets and then restores text
91// colours in each wxDC method working with wxSTIPPLE_MASK_OPAQUE brushes,
92// encapsulate this in a small helper class
93
94// wxColourChanger: changes the text colours in the ctor if required and
95// restores them in the dtor
96class wxColourChanger
97{
98public:
99 wxColourChanger(wxDC& dc);
100 ~wxColourChanger();
101
102private:
103 wxDC& m_dc;
104
105 COLORREF m_colFgOld, m_colBgOld;
106
107 bool m_changed;
108};
109
a23fd0e1
VZ
110// ===========================================================================
111// implementation
112// ===========================================================================
113
f6bcfd97
BP
114// ----------------------------------------------------------------------------
115// wxColourChanger
116// ----------------------------------------------------------------------------
117
118wxColourChanger::wxColourChanger(wxDC& dc) : m_dc(dc)
119{
120 if ( dc.GetBrush().GetStyle() == wxSTIPPLE_MASK_OPAQUE )
121 {
122 HDC hdc = GetHdcOf(dc);
123 m_colFgOld = ::GetTextColor(hdc);
124 m_colBgOld = ::GetBkColor(hdc);
125
126 // note that Windows convention is opposite to wxWindows one, this is
127 // why text colour becomes the background one and vice versa
128 const wxColour& colFg = dc.GetTextForeground();
129 if ( colFg.Ok() )
130 {
131 ::SetBkColor(hdc, colFg.GetPixel());
132 }
133
134 const wxColour& colBg = dc.GetTextBackground();
135 if ( colBg.Ok() )
136 {
137 ::SetTextColor(hdc, colBg.GetPixel());
138 }
139
140 SetBkMode(hdc,
141 dc.GetBackgroundMode() == wxTRANSPARENT ? TRANSPARENT
142 : OPAQUE);
143
144 // flag which telsl us to undo changes in the dtor
145 m_changed = TRUE;
146 }
147 else
148 {
149 // nothing done, nothing to undo
150 m_changed = FALSE;
151 }
152}
153
154wxColourChanger::~wxColourChanger()
155{
156 if ( m_changed )
157 {
158 // restore the colours we changed
159 HDC hdc = GetHdcOf(m_dc);
160
161 ::SetBkMode(hdc, TRANSPARENT);
162 ::SetTextColor(hdc, m_colFgOld);
163 ::SetBkColor(hdc, m_colBgOld);
164 }
165}
166
a23fd0e1
VZ
167// ---------------------------------------------------------------------------
168// wxDC
169// ---------------------------------------------------------------------------
2bda0e17
KB
170
171// Default constructor
a23fd0e1 172wxDC::wxDC()
2bda0e17 173{
7bcb11d3 174 m_canvas = NULL;
a23fd0e1 175
7bcb11d3
JS
176 m_oldBitmap = 0;
177 m_oldPen = 0;
178 m_oldBrush = 0;
179 m_oldFont = 0;
180 m_oldPalette = 0;
a23fd0e1 181
7bcb11d3
JS
182 m_bOwnsDC = FALSE;
183 m_hDC = 0;
a23fd0e1 184
7bcb11d3
JS
185 m_windowExtX = VIEWPORT_EXTENT;
186 m_windowExtY = VIEWPORT_EXTENT;
2bda0e17
KB
187}
188
189
a23fd0e1 190wxDC::~wxDC()
2bda0e17 191{
7ba4fbeb
VZ
192 if ( m_hDC != 0 )
193 {
7bcb11d3 194 SelectOldObjects(m_hDC);
7ba4fbeb
VZ
195
196 // if we own the HDC, we delete it, otherwise we just release it
197
198 if ( m_bOwnsDC )
199 {
200 ::DeleteDC(GetHdc());
7bcb11d3 201 }
7ba4fbeb
VZ
202 else // we don't own our HDC
203 {
db400410
JS
204 if (m_canvas)
205 {
206 ::ReleaseDC(GetHwndOf(m_canvas), GetHdc());
207 }
208 else
209 {
210 // Must have been a wxScreenDC
211 ::ReleaseDC((HWND) NULL, GetHdc());
212 }
7ba4fbeb
VZ
213 }
214 }
2bda0e17
KB
215}
216
217// This will select current objects out of the DC,
218// which is what you have to do before deleting the
219// DC.
220void wxDC::SelectOldObjects(WXHDC dc)
221{
7bcb11d3 222 if (dc)
2bda0e17 223 {
7bcb11d3
JS
224 if (m_oldBitmap)
225 {
226 ::SelectObject((HDC) dc, (HBITMAP) m_oldBitmap);
227 if (m_selectedBitmap.Ok())
228 {
229 m_selectedBitmap.SetSelectedInto(NULL);
230 }
231 }
a23fd0e1 232 m_oldBitmap = 0;
7bcb11d3
JS
233 if (m_oldPen)
234 {
235 ::SelectObject((HDC) dc, (HPEN) m_oldPen);
236 }
a23fd0e1 237 m_oldPen = 0;
7bcb11d3
JS
238 if (m_oldBrush)
239 {
240 ::SelectObject((HDC) dc, (HBRUSH) m_oldBrush);
241 }
a23fd0e1 242 m_oldBrush = 0;
7bcb11d3
JS
243 if (m_oldFont)
244 {
245 ::SelectObject((HDC) dc, (HFONT) m_oldFont);
246 }
a23fd0e1 247 m_oldFont = 0;
7bcb11d3
JS
248 if (m_oldPalette)
249 {
250 ::SelectPalette((HDC) dc, (HPALETTE) m_oldPalette, TRUE);
251 }
a23fd0e1 252 m_oldPalette = 0;
2bda0e17 253 }
a23fd0e1
VZ
254
255 m_brush = wxNullBrush;
7bcb11d3
JS
256 m_pen = wxNullPen;
257 m_palette = wxNullPalette;
258 m_font = wxNullFont;
259 m_backgroundBrush = wxNullBrush;
260 m_selectedBitmap = wxNullBitmap;
2bda0e17
KB
261}
262
a23fd0e1
VZ
263// ---------------------------------------------------------------------------
264// clipping
265// ---------------------------------------------------------------------------
266
1e6feb95
VZ
267void wxDC::UpdateClipBox()
268{
269 RECT rect;
270 GetClipBox(GetHdc(), &rect);
271
272 m_clipX1 = (wxCoord) XDEV2LOG(rect.left);
273 m_clipY1 = (wxCoord) YDEV2LOG(rect.top);
274 m_clipX2 = (wxCoord) XDEV2LOG(rect.right);
275 m_clipY2 = (wxCoord) YDEV2LOG(rect.bottom);
f547e9bb
RL
276}
277
c4218a74 278void wxDC::DoSetClippingRegion(wxCoord x, wxCoord y, wxCoord w, wxCoord h)
2bda0e17 279{
7bcb11d3 280 m_clipping = TRUE;
40a89076 281
c4218a74
VZ
282 // the region coords are always the device ones, so do the translation
283 // manually
1e6feb95
VZ
284 //
285 // FIXME: possible +/-1 error here, to check!
c4218a74
VZ
286 HRGN hrgn = ::CreateRectRgn(LogicalToDeviceX(x),
287 LogicalToDeviceY(y),
288 LogicalToDeviceX(x + w),
289 LogicalToDeviceY(y + h));
40a89076
VZ
290 if ( !hrgn )
291 {
292 wxLogLastError(_T("CreateRectRgn"));
293 }
294 else
295 {
296 if ( ::SelectClipRgn(GetHdc(), hrgn) == ERROR )
297 {
298 wxLogLastError(_T("SelectClipRgn"));
299 }
7ecf5ac7 300 DeleteObject(hrgn);
40a89076 301
1e6feb95 302 UpdateClipBox();
40a89076 303 }
2bda0e17
KB
304}
305
a23fd0e1 306void wxDC::DoSetClippingRegionAsRegion(const wxRegion& region)
a724d789 307{
1e6feb95 308 wxCHECK_RET( GetHrgnOf(region), wxT("invalid clipping region") );
a23fd0e1 309
7bcb11d3 310 m_clipping = TRUE;
a23fd0e1 311
1e6d9499 312#ifdef __WIN16__
1e6feb95
VZ
313 SelectClipRgn(GetHdc(), GetHrgnOf(region));
314#else // Win32
315 ExtSelectClipRgn(GetHdc(), GetHrgnOf(region), RGN_AND);
316#endif // Win16/32
a724d789 317
1e6feb95 318 UpdateClipBox();
2bda0e17
KB
319}
320
a23fd0e1 321void wxDC::DestroyClippingRegion()
2bda0e17 322{
7bcb11d3
JS
323 if (m_clipping && m_hDC)
324 {
325 // TODO: this should restore the previous clipping region,
326 // so that OnPaint processing works correctly, and the update clipping region
327 // doesn't get destroyed after the first DestroyClippingRegion.
328 HRGN rgn = CreateRectRgn(0, 0, 32000, 32000);
a23fd0e1 329 SelectClipRgn(GetHdc(), rgn);
7bcb11d3
JS
330 DeleteObject(rgn);
331 }
1e6feb95 332
7bcb11d3 333 m_clipping = FALSE;
2bda0e17
KB
334}
335
a23fd0e1
VZ
336// ---------------------------------------------------------------------------
337// query capabilities
338// ---------------------------------------------------------------------------
339
340bool wxDC::CanDrawBitmap() const
2bda0e17 341{
7bcb11d3 342 return TRUE;
2bda0e17
KB
343}
344
a23fd0e1 345bool wxDC::CanGetTextExtent() const
2bda0e17 346{
04ef50df
JS
347#ifdef __WXMICROWIN__
348 // TODO Extend MicroWindows' GetDeviceCaps function
349 return TRUE;
350#else
7bcb11d3 351 // What sort of display is it?
a23fd0e1
VZ
352 int technology = ::GetDeviceCaps(GetHdc(), TECHNOLOGY);
353
354 return (technology == DT_RASDISPLAY) || (technology == DT_RASPRINTER);
04ef50df 355#endif
2bda0e17
KB
356}
357
a23fd0e1 358int wxDC::GetDepth() const
2bda0e17 359{
a23fd0e1 360 return (int)::GetDeviceCaps(GetHdc(), BITSPIXEL);
2bda0e17
KB
361}
362
a23fd0e1
VZ
363// ---------------------------------------------------------------------------
364// drawing
365// ---------------------------------------------------------------------------
366
367void wxDC::Clear()
2bda0e17 368{
7bcb11d3 369 RECT rect;
2506aab6
VZ
370 if ( m_canvas )
371 {
7bcb11d3 372 GetClientRect((HWND) m_canvas->GetHWND(), &rect);
2506aab6
VZ
373 }
374 else
7bcb11d3 375 {
eaeb6a3c
JS
376 // No, I think we should simply ignore this if printing on e.g.
377 // a printer DC.
378 // wxCHECK_RET( m_selectedBitmap.Ok(), wxT("this DC can't be cleared") );
379 if (!m_selectedBitmap.Ok())
380 return;
2506aab6 381
7bcb11d3
JS
382 rect.left = 0; rect.top = 0;
383 rect.right = m_selectedBitmap.GetWidth();
384 rect.bottom = m_selectedBitmap.GetHeight();
385 }
2506aab6 386
a23fd0e1
VZ
387 (void) ::SetMapMode(GetHdc(), MM_TEXT);
388
389 DWORD colour = GetBkColor(GetHdc());
7bcb11d3 390 HBRUSH brush = CreateSolidBrush(colour);
a23fd0e1 391 FillRect(GetHdc(), &rect, brush);
7bcb11d3 392 DeleteObject(brush);
a23fd0e1
VZ
393
394 ::SetMapMode(GetHdc(), MM_ANISOTROPIC);
395 ::SetViewportExtEx(GetHdc(), VIEWPORT_EXTENT, VIEWPORT_EXTENT, NULL);
396 ::SetWindowExtEx(GetHdc(), m_windowExtX, m_windowExtY, NULL);
397 ::SetViewportOrgEx(GetHdc(), (int)m_deviceOriginX, (int)m_deviceOriginY, NULL);
398 ::SetWindowOrgEx(GetHdc(), (int)m_logicalOriginX, (int)m_logicalOriginY, NULL);
399}
400
72cdf4c9 401void wxDC::DoFloodFill(wxCoord x, wxCoord y, const wxColour& col, int style)
a23fd0e1 402{
0bafad0c
VZ
403 if ( !::ExtFloodFill(GetHdc(), XLOG2DEV(x), YLOG2DEV(y),
404 col.GetPixel(),
405 style == wxFLOOD_SURFACE ? FLOODFILLSURFACE
406 : FLOODFILLBORDER) )
407 {
408 // quoting from the MSDN docs:
409 //
410 // Following are some of the reasons this function might fail:
411 //
412 // * The filling could not be completed.
413 // * The specified point has the boundary color specified by the
414 // crColor parameter (if FLOODFILLBORDER was requested).
415 // * The specified point does not have the color specified by
416 // crColor (if FLOODFILLSURFACE was requested)
417 // * The point is outside the clipping region that is, it is not
418 // visible on the device.
419 //
f6bcfd97 420 wxLogLastError(wxT("ExtFloodFill"));
0bafad0c 421 }
a23fd0e1 422
7bcb11d3 423 CalcBoundingBox(x, y);
2bda0e17
KB
424}
425
72cdf4c9 426bool wxDC::DoGetPixel(wxCoord x, wxCoord y, wxColour *col) const
2bda0e17 427{
f6bcfd97
BP
428 wxCHECK_MSG( col, FALSE, _T("NULL colour parameter in wxDC::GetPixel") );
429
7bcb11d3 430 // get the color of the pixel
a23fd0e1 431 COLORREF pixelcolor = ::GetPixel(GetHdc(), XLOG2DEV(x), YLOG2DEV(y));
0bafad0c 432
f6bcfd97 433 wxRGBToColour(*col, pixelcolor);
dc1efb1d
JS
434
435 return TRUE;
2bda0e17
KB
436}
437
72cdf4c9 438void wxDC::DoCrossHair(wxCoord x, wxCoord y)
a23fd0e1 439{
72cdf4c9
VZ
440 wxCoord x1 = x-VIEWPORT_EXTENT;
441 wxCoord y1 = y-VIEWPORT_EXTENT;
442 wxCoord x2 = x+VIEWPORT_EXTENT;
443 wxCoord y2 = y+VIEWPORT_EXTENT;
a23fd0e1
VZ
444
445 (void)MoveToEx(GetHdc(), XLOG2DEV(x1), YLOG2DEV(y), NULL);
446 (void)LineTo(GetHdc(), XLOG2DEV(x2), YLOG2DEV(y));
447
448 (void)MoveToEx(GetHdc(), XLOG2DEV(x), YLOG2DEV(y1), NULL);
449 (void)LineTo(GetHdc(), XLOG2DEV(x), YLOG2DEV(y2));
450
7bcb11d3
JS
451 CalcBoundingBox(x1, y1);
452 CalcBoundingBox(x2, y2);
2bda0e17
KB
453}
454
72cdf4c9 455void wxDC::DoDrawLine(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2)
2bda0e17 456{
a23fd0e1
VZ
457 (void)MoveToEx(GetHdc(), XLOG2DEV(x1), YLOG2DEV(y1), NULL);
458 (void)LineTo(GetHdc(), XLOG2DEV(x2), YLOG2DEV(y2));
459
058939fc
JS
460 // Normalization: Windows doesn't draw the last point of the line.
461 // But apparently neither does GTK+, so we take it out again.
462// (void)LineTo(GetHdc(), XLOG2DEV(x2) + 1, YLOG2DEV(y2));
a23fd0e1 463
7bcb11d3
JS
464 CalcBoundingBox(x1, y1);
465 CalcBoundingBox(x2, y2);
2bda0e17
KB
466}
467
f6bcfd97
BP
468// Draws an arc of a circle, centred on (xc, yc), with starting point (x1, y1)
469// and ending at (x2, y2)
470void wxDC::DoDrawArc(wxCoord x1, wxCoord y1,
471 wxCoord x2, wxCoord y2,
472 wxCoord xc, wxCoord yc)
2bda0e17 473{
f6bcfd97 474 wxColourChanger cc(*this); // needed for wxSTIPPLE_MASK_OPAQUE handling
2d8a5cb1 475
f6bcfd97
BP
476 double dx = xc - x1;
477 double dy = yc - y1;
478 double radius = (double)sqrt(dx*dx+dy*dy);
479 wxCoord r = (wxCoord)radius;
2d8a5cb1 480
f6bcfd97
BP
481 // treat the special case of full circle separately
482 if ( x1 == x2 && y1 == y2 )
7bcb11d3 483 {
f6bcfd97 484 DrawEllipse(xc - r, yc - r, 2*r, 2*r);
a23fd0e1 485 return;
7bcb11d3 486 }
a23fd0e1 487
72cdf4c9
VZ
488 wxCoord xx1 = XLOG2DEV(x1);
489 wxCoord yy1 = YLOG2DEV(y1);
490 wxCoord xx2 = XLOG2DEV(x2);
491 wxCoord yy2 = YLOG2DEV(y2);
492 wxCoord xxc = XLOG2DEV(xc);
493 wxCoord yyc = YLOG2DEV(yc);
494 wxCoord ray = (wxCoord) sqrt(double((xxc-xx1)*(xxc-xx1)+(yyc-yy1)*(yyc-yy1)));
a23fd0e1 495
72cdf4c9
VZ
496 wxCoord xxx1 = (wxCoord) (xxc-ray);
497 wxCoord yyy1 = (wxCoord) (yyc-ray);
498 wxCoord xxx2 = (wxCoord) (xxc+ray);
499 wxCoord yyy2 = (wxCoord) (yyc+ray);
f6bcfd97
BP
500
501 if ( m_brush.Ok() && m_brush.GetStyle() != wxTRANSPARENT )
7bcb11d3
JS
502 {
503 // Have to add 1 to bottom-right corner of rectangle
504 // to make semi-circles look right (crooked line otherwise).
505 // Unfortunately this is not a reliable method, depends
506 // on the size of shape.
507 // TODO: figure out why this happens!
f6bcfd97 508 Pie(GetHdc(),xxx1,yyy1,xxx2+1,yyy2+1, xx1,yy1,xx2,yy2);
7bcb11d3
JS
509 }
510 else
2d8a5cb1 511 {
f6bcfd97 512 Arc(GetHdc(),xxx1,yyy1,xxx2,yyy2, xx1,yy1,xx2,yy2);
2d8a5cb1 513 }
f6bcfd97
BP
514
515 CalcBoundingBox(xc - r, yc - r);
516 CalcBoundingBox(xc + r, yc + r);
2bda0e17
KB
517}
518
cd9da200
VZ
519void wxDC::DoDrawCheckMark(wxCoord x1, wxCoord y1,
520 wxCoord width, wxCoord height)
521{
522 wxCoord x2 = x1 + width,
523 y2 = y1 + height;
524
04ef50df 525#if defined(__WIN32__) && !defined(__SC__) && !defined(__WXMICROWIN__)
cd9da200
VZ
526 RECT rect;
527 rect.left = x1;
528 rect.top = y1;
529 rect.right = x2;
530 rect.bottom = y2;
531
532 DrawFrameControl(GetHdc(), &rect, DFC_MENU, DFCS_MENUCHECK);
533#else // Win16
534 // In WIN16, draw a cross
535 HPEN blackPen = ::CreatePen(PS_SOLID, 1, RGB(0, 0, 0));
536 HPEN whiteBrush = (HPEN)::GetStockObject(WHITE_BRUSH);
e06b9569
JS
537 HPEN hPenOld = (HPEN)::SelectObject(GetHdc(), blackPen);
538 HPEN hBrushOld = (HPEN)::SelectObject(GetHdc(), whiteBrush);
cd9da200
VZ
539 ::SetROP2(GetHdc(), R2_COPYPEN);
540 Rectangle(GetHdc(), x1, y1, x2, y2);
8cb172b4 541 MoveToEx(GetHdc(), x1, y1, NULL);
cd9da200 542 LineTo(GetHdc(), x2, y2);
8cb172b4 543 MoveToEx(GetHdc(), x2, y1, NULL);
cd9da200
VZ
544 LineTo(GetHdc(), x1, y2);
545 ::SelectObject(GetHdc(), hPenOld);
546 ::SelectObject(GetHdc(), hBrushOld);
547 ::DeleteObject(blackPen);
548#endif // Win32/16
549
550 CalcBoundingBox(x1, y1);
551 CalcBoundingBox(x2, y2);
552}
553
72cdf4c9 554void wxDC::DoDrawPoint(wxCoord x, wxCoord y)
2bda0e17 555{
7bcb11d3
JS
556 COLORREF color = 0x00ffffff;
557 if (m_pen.Ok())
558 {
a23fd0e1 559 color = m_pen.GetColour().GetPixel();
7bcb11d3 560 }
a23fd0e1
VZ
561
562 SetPixel(GetHdc(), XLOG2DEV(x), YLOG2DEV(y), color);
563
7bcb11d3 564 CalcBoundingBox(x, y);
2bda0e17
KB
565}
566
72cdf4c9 567void wxDC::DoDrawPolygon(int n, wxPoint points[], wxCoord xoffset, wxCoord yoffset,int fillStyle)
2bda0e17 568{
f6bcfd97 569 wxColourChanger cc(*this); // needed for wxSTIPPLE_MASK_OPAQUE handling
de2d2cdc 570
7bcb11d3
JS
571 // Do things less efficiently if we have offsets
572 if (xoffset != 0 || yoffset != 0)
6a6c0a8b 573 {
7bcb11d3
JS
574 POINT *cpoints = new POINT[n];
575 int i;
576 for (i = 0; i < n; i++)
577 {
578 cpoints[i].x = (int)(points[i].x + xoffset);
579 cpoints[i].y = (int)(points[i].y + yoffset);
a23fd0e1 580
7bcb11d3
JS
581 CalcBoundingBox(cpoints[i].x, cpoints[i].y);
582 }
a23fd0e1
VZ
583 int prev = SetPolyFillMode(GetHdc(),fillStyle==wxODDEVEN_RULE?ALTERNATE:WINDING);
584 (void)Polygon(GetHdc(), cpoints, n);
585 SetPolyFillMode(GetHdc(),prev);
7bcb11d3
JS
586 delete[] cpoints;
587 }
588 else
589 {
590 int i;
591 for (i = 0; i < n; i++)
592 CalcBoundingBox(points[i].x, points[i].y);
a23fd0e1
VZ
593
594 int prev = SetPolyFillMode(GetHdc(),fillStyle==wxODDEVEN_RULE?ALTERNATE:WINDING);
595 (void)Polygon(GetHdc(), (POINT*) points, n);
596 SetPolyFillMode(GetHdc(),prev);
6a6c0a8b 597 }
2bda0e17
KB
598}
599
72cdf4c9 600void wxDC::DoDrawLines(int n, wxPoint points[], wxCoord xoffset, wxCoord yoffset)
2bda0e17 601{
7bcb11d3
JS
602 // Do things less efficiently if we have offsets
603 if (xoffset != 0 || yoffset != 0)
6a6c0a8b 604 {
7bcb11d3
JS
605 POINT *cpoints = new POINT[n];
606 int i;
607 for (i = 0; i < n; i++)
608 {
609 cpoints[i].x = (int)(points[i].x + xoffset);
610 cpoints[i].y = (int)(points[i].y + yoffset);
a23fd0e1 611
7bcb11d3
JS
612 CalcBoundingBox(cpoints[i].x, cpoints[i].y);
613 }
a23fd0e1 614 (void)Polyline(GetHdc(), cpoints, n);
7bcb11d3
JS
615 delete[] cpoints;
616 }
617 else
618 {
619 int i;
620 for (i = 0; i < n; i++)
621 CalcBoundingBox(points[i].x, points[i].y);
a23fd0e1
VZ
622
623 (void)Polyline(GetHdc(), (POINT*) points, n);
6a6c0a8b 624 }
2bda0e17
KB
625}
626
72cdf4c9 627void wxDC::DoDrawRectangle(wxCoord x, wxCoord y, wxCoord width, wxCoord height)
2bda0e17 628{
f6bcfd97 629 wxColourChanger cc(*this); // needed for wxSTIPPLE_MASK_OPAQUE handling
de2d2cdc 630
72cdf4c9
VZ
631 wxCoord x2 = x + width;
632 wxCoord y2 = y + height;
a23fd0e1 633
5456b916 634 if ((m_logicalFunction == wxCOPY) && (m_pen.GetStyle() == wxTRANSPARENT))
0bafad0c 635 {
7299b1b2 636 RECT rect;
5456b916
RR
637 rect.left = XLOG2DEV(x);
638 rect.top = YLOG2DEV(y);
639 rect.right = XLOG2DEV(x2);
7299b1b2
RD
640 rect.bottom = YLOG2DEV(y2);
641 (void)FillRect(GetHdc(), &rect, (HBRUSH)m_brush.GetResourceHandle() );
5456b916
RR
642 }
643 else
644 {
645 // Windows draws the filled rectangles without outline (i.e. drawn with a
646 // transparent pen) one pixel smaller in both directions and we want them
f6bcfd97 647 // to have the same size regardless of which pen is used - adjust
5456b916
RR
648
649