]> git.saurik.com Git - wxWidgets.git/blame - src/msw/dc.cpp
Removed erroneous copyright names and corrected licence spelling
[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
0cbff120 43#include "wx/sysopt.h"
2bda0e17 44#include "wx/dcprint.h"
aef94d68 45#include "wx/module.h"
acf8e3d2 46#include "wx/dynload.h"
2bda0e17
KB
47
48#include <string.h>
49#include <math.h>
2bda0e17 50
a58a12e9
VZ
51#include "wx/msw/private.h" // needs to be before #include <commdlg.h>
52
c67d6888 53#if wxUSE_COMMON_DIALOGS && !defined(__WXMICROWIN__)
a23fd0e1 54 #include <commdlg.h>
2bda0e17
KB
55#endif
56
57#ifndef __WIN32__
a23fd0e1 58 #include <print.h>
2bda0e17
KB
59#endif
60
3bce6687
JS
61/* Quaternary raster codes */
62#ifndef MAKEROP4
63#define MAKEROP4(fore,back) (DWORD)((((back) << 8) & 0xFF000000) | (fore))
64#endif
65
5acb7b3e 66IMPLEMENT_ABSTRACT_CLASS(wxDC, wxDCBase)
2bda0e17 67
a23fd0e1
VZ
68// ---------------------------------------------------------------------------
69// constants
70// ---------------------------------------------------------------------------
71
42e69d6b
VZ
72static const int VIEWPORT_EXTENT = 1000;
73
74static const int MM_POINTS = 9;
75static const int MM_METRIC = 10;
a23fd0e1 76
4314ec48
VZ
77// usually this is defined in math.h
78#ifndef M_PI
79 static const double M_PI = 3.14159265358979323846;
80#endif // M_PI
81
4aff28fc
VZ
82// ROPs which don't have standard names (see "Ternary Raster Operations" in the
83// MSDN docs for how this and other numbers in wxDC::Blit() are obtained)
84#define DSTCOPY 0x00AA0029 // a.k.a. NOP operation
85
1e2081a1
VZ
86// ----------------------------------------------------------------------------
87// macros for logical <-> device coords conversion
88// ----------------------------------------------------------------------------
89
90/*
91 We currently let Windows do all the translations itself so these macros are
92 not really needed (any more) but keep them to enhance readability of the
93 code by allowing to see where are the logical and where are the device
94 coordinates used.
95 */
96
97// logical to device
98#define XLOG2DEV(x) (x)
99#define YLOG2DEV(y) (y)
100
101// device to logical
102#define XDEV2LOG(x) (x)
103#define YDEV2LOG(y) (y)
104
4314ec48
VZ
105// ---------------------------------------------------------------------------
106// private functions
107// ---------------------------------------------------------------------------
108
109// convert degrees to radians
110static inline double DegToRad(double deg) { return (deg * M_PI) / 180.0; }
111
f6bcfd97
BP
112// ----------------------------------------------------------------------------
113// private classes
114// ----------------------------------------------------------------------------
115
116// instead of duplicating the same code which sets and then restores text
117// colours in each wxDC method working with wxSTIPPLE_MASK_OPAQUE brushes,
118// encapsulate this in a small helper class
119
120// wxColourChanger: changes the text colours in the ctor if required and
121// restores them in the dtor
122class wxColourChanger
123{
124public:
125 wxColourChanger(wxDC& dc);
126 ~wxColourChanger();
127
128private:
129 wxDC& m_dc;
130
131 COLORREF m_colFgOld, m_colBgOld;
132
133 bool m_changed;
134};
135
f178ab7e
VZ
136// this class saves the old stretch blit mode during its life time
137class StretchBltModeChanger
138{
139public:
140 StretchBltModeChanger(HDC hdc, int mode)
141 : m_hdc(hdc)
142 {
143 m_modeOld = ::SetStretchBltMode(m_hdc, mode);
144 if ( !m_modeOld )
145 wxLogLastError(_T("SetStretchBltMode"));
146 }
147
148 ~StretchBltModeChanger()
149 {
150 if ( !::SetStretchBltMode(m_hdc, m_modeOld) )
151 wxLogLastError(_T("SetStretchBltMode"));
152 }
153
154private:
155 const HDC m_hdc;
156
157 int m_modeOld;
158};
159
a23fd0e1
VZ
160// ===========================================================================
161// implementation
162// ===========================================================================
163
f6bcfd97
BP
164// ----------------------------------------------------------------------------
165// wxColourChanger
166// ----------------------------------------------------------------------------
167
168wxColourChanger::wxColourChanger(wxDC& dc) : m_dc(dc)
169{
cafbad8f
VZ
170 const wxBrush& brush = dc.GetBrush();
171 if ( brush.Ok() && brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE )
f6bcfd97
BP
172 {
173 HDC hdc = GetHdcOf(dc);
174 m_colFgOld = ::GetTextColor(hdc);
175 m_colBgOld = ::GetBkColor(hdc);
176
177 // note that Windows convention is opposite to wxWindows one, this is
178 // why text colour becomes the background one and vice versa
179 const wxColour& colFg = dc.GetTextForeground();
180 if ( colFg.Ok() )
181 {
182 ::SetBkColor(hdc, colFg.GetPixel());
183 }
184
185 const wxColour& colBg = dc.GetTextBackground();
186 if ( colBg.Ok() )
187 {
188 ::SetTextColor(hdc, colBg.GetPixel());
189 }
190
191 SetBkMode(hdc,
192 dc.GetBackgroundMode() == wxTRANSPARENT ? TRANSPARENT
193 : OPAQUE);
194
195 // flag which telsl us to undo changes in the dtor
196 m_changed = TRUE;
197 }
198 else
199 {
200 // nothing done, nothing to undo
201 m_changed = FALSE;
202 }
203}
204
205wxColourChanger::~wxColourChanger()
206{
207 if ( m_changed )
208 {
209 // restore the colours we changed
210 HDC hdc = GetHdcOf(m_dc);
211
212 ::SetBkMode(hdc, TRANSPARENT);
213 ::SetTextColor(hdc, m_colFgOld);
214 ::SetBkColor(hdc, m_colBgOld);
215 }
216}
217
a23fd0e1
VZ
218// ---------------------------------------------------------------------------
219// wxDC
220// ---------------------------------------------------------------------------
2bda0e17
KB
221
222// Default constructor
a23fd0e1 223wxDC::wxDC()
2bda0e17 224{
7bcb11d3 225 m_canvas = NULL;
a23fd0e1 226
7bcb11d3
JS
227 m_oldBitmap = 0;
228 m_oldPen = 0;
229 m_oldBrush = 0;
230 m_oldFont = 0;
d275c7eb 231#if wxUSE_PALETTE
7bcb11d3 232 m_oldPalette = 0;
d275c7eb 233#endif // wxUSE_PALETTE
a23fd0e1 234
7bcb11d3
JS
235 m_bOwnsDC = FALSE;
236 m_hDC = 0;
2bda0e17
KB
237}
238
a23fd0e1 239wxDC::~wxDC()
2bda0e17 240{
7ba4fbeb
VZ
241 if ( m_hDC != 0 )
242 {
7bcb11d3 243 SelectOldObjects(m_hDC);
7ba4fbeb
VZ
244
245 // if we own the HDC, we delete it, otherwise we just release it
246
247 if ( m_bOwnsDC )
248 {
249 ::DeleteDC(GetHdc());
7bcb11d3 250 }
7ba4fbeb
VZ
251 else // we don't own our HDC
252 {
db400410
JS
253 if (m_canvas)
254 {
255 ::ReleaseDC(GetHwndOf(m_canvas), GetHdc());
256 }
257 else
258 {
259 // Must have been a wxScreenDC
260 ::ReleaseDC((HWND) NULL, GetHdc());
261 }
7ba4fbeb
VZ
262 }
263 }
2bda0e17
KB
264}
265
266// This will select current objects out of the DC,
267// which is what you have to do before deleting the
268// DC.
269void wxDC::SelectOldObjects(WXHDC dc)
270{
7bcb11d3 271 if (dc)
2bda0e17 272 {
7bcb11d3
JS
273 if (m_oldBitmap)
274 {
275 ::SelectObject((HDC) dc, (HBITMAP) m_oldBitmap);
3ca22d5e 276#ifdef __WXDEBUG__
7bcb11d3
JS
277 if (m_selectedBitmap.Ok())
278 {
279 m_selectedBitmap.SetSelectedInto(NULL);
280 }
3ca22d5e 281#endif
7bcb11d3 282 }
a23fd0e1 283 m_oldBitmap = 0;
7bcb11d3
JS
284 if (m_oldPen)
285 {
286 ::SelectObject((HDC) dc, (HPEN) m_oldPen);
287 }
a23fd0e1 288 m_oldPen = 0;
7bcb11d3
JS
289 if (m_oldBrush)
290 {
291 ::SelectObject((HDC) dc, (HBRUSH) m_oldBrush);
292 }
a23fd0e1 293 m_oldBrush = 0;
7bcb11d3
JS
294 if (m_oldFont)
295 {
296 ::SelectObject((HDC) dc, (HFONT) m_oldFont);
297 }
a23fd0e1 298 m_oldFont = 0;
d275c7eb
VZ
299
300#if wxUSE_PALETTE
7bcb11d3
JS
301 if (m_oldPalette)
302 {
19193a2c 303 ::SelectPalette((HDC) dc, (HPALETTE) m_oldPalette, FALSE);
7bcb11d3 304 }
a23fd0e1 305 m_oldPalette = 0;
d275c7eb 306#endif // wxUSE_PALETTE
2bda0e17 307 }
a23fd0e1
VZ
308
309 m_brush = wxNullBrush;
7bcb11d3 310 m_pen = wxNullPen;
d275c7eb 311#if wxUSE_PALETTE
7bcb11d3 312 m_palette = wxNullPalette;
d275c7eb 313#endif // wxUSE_PALETTE
7bcb11d3
JS
314 m_font = wxNullFont;
315 m_backgroundBrush = wxNullBrush;
316 m_selectedBitmap = wxNullBitmap;
2bda0e17
KB
317}
318
a23fd0e1
VZ
319// ---------------------------------------------------------------------------
320// clipping
321// ---------------------------------------------------------------------------
322
1e6feb95
VZ
323void wxDC::UpdateClipBox()
324{
5adad466
JS
325#ifdef __WXMICROWIN__
326 if (!GetHDC()) return;
327#endif
d275c7eb 328
1e6feb95 329 RECT rect;
5230934a 330 ::GetClipBox(GetHdc(), &rect);
1e6feb95
VZ
331
332 m_clipX1 = (wxCoord) XDEV2LOG(rect.left);
333 m_clipY1 = (wxCoord) YDEV2LOG(rect.top);
334 m_clipX2 = (wxCoord) XDEV2LOG(rect.right);
335 m_clipY2 = (wxCoord) YDEV2LOG(rect.bottom);
f547e9bb
RL
336}
337
5230934a
VZ
338// common part of DoSetClippingRegion() and DoSetClippingRegionAsRegion()
339void wxDC::SetClippingHrgn(WXHRGN hrgn)
2bda0e17 340{
5230934a
VZ
341 wxCHECK_RET( hrgn, wxT("invalid clipping region") );
342
5adad466 343#ifdef __WXMICROWIN__
5230934a
VZ
344 if (!GetHdc()) return;
345#endif // __WXMICROWIN__
346
347 // note that we combine the new clipping region with the existing one: this
348 // is compatible with what the other ports do and is the documented
349 // behaviour now (starting with 2.3.3)
350#ifdef __WIN16__
351 RECT rectClip;
352 if ( !::GetClipBox(GetHdc(), &rectClip) )
353 return;
354
355 HRGN hrgnDest = ::CreateRectRgn(0, 0, 0, 0);
356 HRGN hrgnClipOld = ::CreateRectRgn(rectClip.left, rectClip.top,
357 rectClip.right, rectClip.bottom);
358
359 if ( ::CombineRgn(hrgnDest, hrgnClipOld, (HRGN)hrgn, RGN_AND) != ERROR )
360 {
361 ::SelectClipRgn(GetHdc(), hrgnDest);
362 }
363
364 ::DeleteObject(hrgnClipOld);
365 ::DeleteObject(hrgnDest);
366#else // Win32
367 if ( ::ExtSelectClipRgn(GetHdc(), (HRGN)hrgn, RGN_AND) == ERROR )
368 {
369 wxLogLastError(_T("ExtSelectClipRgn"));
370
371 return;
372 }
373#endif // Win16/32
d275c7eb 374
7bcb11d3 375 m_clipping = TRUE;
40a89076 376
5230934a
VZ
377 UpdateClipBox();
378}
379
380void wxDC::DoSetClippingRegion(wxCoord x, wxCoord y, wxCoord w, wxCoord h)
381{
c4218a74
VZ
382 // the region coords are always the device ones, so do the translation
383 // manually
1e6feb95
VZ
384 //
385 // FIXME: possible +/-1 error here, to check!
c4218a74
VZ
386 HRGN hrgn = ::CreateRectRgn(LogicalToDeviceX(x),
387 LogicalToDeviceY(y),
388 LogicalToDeviceX(x + w),
389 LogicalToDeviceY(y + h));
40a89076
VZ
390 if ( !hrgn )
391 {
392 wxLogLastError(_T("CreateRectRgn"));
393 }
394 else
395 {
5230934a 396 SetClippingHrgn((WXHRGN)hrgn);
40a89076 397
5230934a 398 ::DeleteObject(hrgn);
40a89076 399 }
2bda0e17
KB
400}
401
a23fd0e1 402void wxDC::DoSetClippingRegionAsRegion(const wxRegion& region)
a724d789 403{
5230934a 404 SetClippingHrgn(region.GetHRGN());
2bda0e17
KB
405}
406
a23fd0e1 407void wxDC::DestroyClippingRegion()
2bda0e17 408{
5adad466
JS
409#ifdef __WXMICROWIN__
410 if (!GetHDC()) return;
411#endif
d275c7eb 412
7bcb11d3
JS
413 if (m_clipping && m_hDC)
414 {
415 // TODO: this should restore the previous clipping region,
5230934a
VZ
416 // so that OnPaint processing works correctly, and the update
417 // clipping region doesn't get destroyed after the first
418 // DestroyClippingRegion.
7bcb11d3 419 HRGN rgn = CreateRectRgn(0, 0, 32000, 32000);
5230934a
VZ
420 ::SelectClipRgn(GetHdc(), rgn);
421 ::DeleteObject(rgn);
7bcb11d3 422 }
1e6feb95 423
7bcb11d3 424 m_clipping = FALSE;
2bda0e17
KB
425}
426
a23fd0e1
VZ
427// ---------------------------------------------------------------------------
428// query capabilities
429// ---------------------------------------------------------------------------
430
431bool wxDC::CanDrawBitmap() const
2bda0e17 432{
7bcb11d3 433 return TRUE;
2bda0e17
KB
434}
435
a23fd0e1 436bool wxDC::CanGetTextExtent() const
2bda0e17 437{
04ef50df
JS
438#ifdef __WXMICROWIN__
439 // TODO Extend MicroWindows' GetDeviceCaps function
440 return TRUE;
441#else
7bcb11d3 442 // What sort of display is it?
a23fd0e1
VZ
443 int technology = ::GetDeviceCaps(GetHdc(), TECHNOLOGY);
444
445 return (technology == DT_RASDISPLAY) || (technology == DT_RASPRINTER);
04ef50df 446#endif
2bda0e17
KB
447}
448
a23fd0e1 449int wxDC::GetDepth() const
2bda0e17 450{
5adad466
JS
451#ifdef __WXMICROWIN__
452 if (!GetHDC()) return 16;
453#endif
d275c7eb 454
a23fd0e1 455 return (int)::GetDeviceCaps(GetHdc(), BITSPIXEL);
2bda0e17
KB
456}
457
a23fd0e1
VZ
458// ---------------------------------------------------------------------------
459// drawing
460// ---------------------------------------------------------------------------
461
462void wxDC::Clear()
2bda0e17 463{
5adad466
JS
464#ifdef __WXMICROWIN__
465 if (!GetHDC()) return;
466#endif
d275c7eb 467
7bcb11d3 468 RECT rect;
2506aab6
VZ
469 if ( m_canvas )
470 {
7bcb11d3 471 GetClientRect((HWND) m_canvas->GetHWND(), &rect);
2506aab6
VZ
472 }
473 else
7bcb11d3 474 {
eaeb6a3c
JS
475 // No, I think we should simply ignore this if printing on e.g.
476 // a printer DC.
477 // wxCHECK_RET( m_selectedBitmap.Ok(), wxT("this DC can't be cleared") );
478 if (!m_selectedBitmap.Ok())
479 return;
2506aab6 480
7bcb11d3
JS
481 rect.left = 0; rect.top = 0;
482 rect.right = m_selectedBitmap.GetWidth();
483 rect.bottom = m_selectedBitmap.GetHeight();
484 }
2506aab6 485
a23fd0e1
VZ
486 (void) ::SetMapMode(GetHdc(), MM_TEXT);
487
1e2081a1
VZ
488 DWORD colour = ::GetBkColor(GetHdc());
489 HBRUSH brush = ::CreateSolidBrush(colour);
490 ::FillRect(GetHdc(), &rect, brush);
491 ::DeleteObject(brush);
492
493 int width = DeviceToLogicalXRel(VIEWPORT_EXTENT)*m_signX,
494 height = DeviceToLogicalYRel(VIEWPORT_EXTENT)*m_signY;
a23fd0e1
VZ
495
496 ::SetMapMode(GetHdc(), MM_ANISOTROPIC);
497 ::SetViewportExtEx(GetHdc(), VIEWPORT_EXTENT, VIEWPORT_EXTENT, NULL);
1e2081a1 498 ::SetWindowExtEx(GetHdc(), width, height, NULL);
a23fd0e1
VZ
499 ::SetViewportOrgEx(GetHdc(), (int)m_deviceOriginX, (int)m_deviceOriginY, NULL);
500 ::SetWindowOrgEx(GetHdc(), (int)m_logicalOriginX, (int)m_logicalOriginY, NULL);
501}
502
387ebd3e 503bool wxDC::DoFloodFill(wxCoord x, wxCoord y, const wxColour& col, int style)
a23fd0e1 504{
5adad466 505#ifdef __WXMICROWIN__
387ebd3e 506 if (!GetHDC()) return FALSE;
5adad466 507#endif
d275c7eb 508
387ebd3e 509 bool success = (0 != ::ExtFloodFill(GetHdc(), XLOG2DEV(x), YLOG2DEV(y),
0bafad0c
VZ
510 col.GetPixel(),
511 style == wxFLOOD_SURFACE ? FLOODFILLSURFACE
387ebd3e
JS
512 : FLOODFILLBORDER) ) ;
513 if (!success)
0bafad0c
VZ
514 {
515 // quoting from the MSDN docs:
516 //
517 // Following are some of the reasons this function might fail:
518 //
519 // * The filling could not be completed.
520 // * The specified point has the boundary color specified by the
521 // crColor parameter (if FLOODFILLBORDER was requested).
522 // * The specified point does not have the color specified by
523 // crColor (if FLOODFILLSURFACE was requested)
524 // * The point is outside the clipping region that is, it is not
525 // visible on the device.
526 //
f6bcfd97 527 wxLogLastError(wxT("ExtFloodFill"));
0bafad0c 528 }
a23fd0e1 529
7bcb11d3 530 CalcBoundingBox(x, y);
387ebd3e
JS
531
532 return success;
2bda0e17
KB
533}
534
72cdf4c9 535bool wxDC::DoGetPixel(wxCoord x, wxCoord y, wxColour *col) const
2bda0e17 536{
5adad466
JS
537#ifdef __WXMICROWIN__
538 if (!GetHDC()) return FALSE;
539#endif
d275c7eb 540
f6bcfd97
BP
541 wxCHECK_MSG( col, FALSE, _T("NULL colour parameter in wxDC::GetPixel") );
542
7bcb11d3 543 // get the color of the pixel
a23fd0e1 544 COLORREF pixelcolor = ::GetPixel(GetHdc(), XLOG2DEV(x), YLOG2DEV(y));
0bafad0c 545
f6bcfd97 546 wxRGBToColour(*col, pixelcolor);
dc1efb1d
JS
547
548 return TRUE;
2bda0e17
KB
549}
550
72cdf4c9 551void wxDC::DoCrossHair(wxCoord x, wxCoord y)
a23fd0e1 552{
5adad466
JS
553#ifdef __WXMICROWIN__
554 if (!GetHDC()) return;
555#endif
d275c7eb 556
72cdf4c9
VZ
557 wxCoord x1 = x-VIEWPORT_EXTENT;
558 wxCoord y1 = y-VIEWPORT_EXTENT;
559 wxCoord x2 = x+VIEWPORT_EXTENT;
560 wxCoord y2 = y+VIEWPORT_EXTENT;
a23fd0e1
VZ
561
562 (void)MoveToEx(GetHdc(), XLOG2DEV(x1), YLOG2DEV(y), NULL);
563 (void)LineTo(GetHdc(), XLOG2DEV(x2), YLOG2DEV(y));
564
565 (void)MoveToEx(GetHdc(), XLOG2DEV(x), YLOG2DEV(y1), NULL);
566 (void)LineTo(GetHdc(), XLOG2DEV(x), YLOG2DEV(y2));
567
7bcb11d3
JS
568 CalcBoundingBox(x1, y1);
569 CalcBoundingBox(x2, y2);
2bda0e17
KB
570}
571
72cdf4c9 572void wxDC::DoDrawLine(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2)
2bda0e17 573{
5adad466
JS
574#ifdef __WXMICROWIN__
575 if (!GetHDC()) return;
576#endif
d275c7eb 577
a23fd0e1
VZ
578 (void)MoveToEx(GetHdc(), XLOG2DEV(x1), YLOG2DEV(y1), NULL);
579 (void)LineTo(GetHdc(), XLOG2DEV(x2), YLOG2DEV(y2));
580
7bcb11d3
JS
581 CalcBoundingBox(x1, y1);
582 CalcBoundingBox(x2, y2);
2bda0e17
KB
583}
584
f6bcfd97
BP
585// Draws an arc of a circle, centred on (xc, yc), with starting point (x1, y1)
586// and ending at (x2, y2)
587void wxDC::DoDrawArc(wxCoord x1, wxCoord y1,
588 wxCoord x2, wxCoord y2,
589 wxCoord xc, wxCoord yc)
2bda0e17 590{
5adad466
JS
591#ifdef __WXMICROWIN__
592 if (!GetHDC()) return;
593#endif
d275c7eb 594
f6bcfd97 595 wxColourChanger cc(*this); // needed for wxSTIPPLE_MASK_OPAQUE handling
2d8a5cb1 596
f6bcfd97
BP
597 double dx = xc - x1;
598 double dy = yc - y1;
599 double radius = (double)sqrt(dx*dx+dy*dy);
600 wxCoord r = (wxCoord)radius;
2d8a5cb1 601
f6bcfd97
BP
602 // treat the special case of full circle separately
603 if ( x1 == x2 && y1 == y2 )
7bcb11d3 604 {
f6bcfd97 605 DrawEllipse(xc - r, yc - r, 2*r, 2*r);
a23fd0e1 606 return;
7bcb11d3 607 }
a23fd0e1 608
72cdf4c9
VZ
609 wxCoord xx1 = XLOG2DEV(x1);
610 wxCoord yy1 = YLOG2DEV(y1);
611 wxCoord xx2 = XLOG2DEV(x2);
612 wxCoord yy2 = YLOG2DEV(y2);
613 wxCoord xxc = XLOG2DEV(xc);
614 wxCoord yyc = YLOG2DEV(yc);
615 wxCoord ray = (wxCoord) sqrt(double((xxc-xx1)*(xxc-xx1)+(yyc-yy1)*(yyc-yy1)));
a23fd0e1 616
72cdf4c9
VZ
617 wxCoord xxx1 = (wxCoord) (xxc-ray);
618 wxCoord yyy1 = (wxCoord) (yyc-ray);
619 wxCoord xxx2 = (wxCoord) (xxc+ray);
620 wxCoord yyy2 = (wxCoord) (yyc+ray);
f6bcfd97
BP
621
622 if ( m_brush.Ok() && m_brush.GetStyle() != wxTRANSPARENT )
7bcb11d3
JS
623 {
624 // Have to add 1 to bottom-right corner of rectangle
625 // to make semi-circles look right (crooked line otherwise).
626 // Unfortunately this is not a reliable method, depends
627 // on the size of shape.
628 // TODO: figure out why this happens!
f6bcfd97 629 Pie(GetHdc(),xxx1,yyy1,xxx2+1,yyy2+1, xx1,yy1,xx2,yy2);
7bcb11d3
JS
630 }
631 else
2d8a5cb1 632 {
f6bcfd97 633 Arc(GetHdc(),xxx1,yyy1,xxx2,yyy2, xx1,yy1,xx2,yy2);
2d8a5cb1 634 }
f6bcfd97
BP
635
636 CalcBoundingBox(xc - r, yc - r);
637 CalcBoundingBox(xc + r, yc + r);
2bda0e17
KB
638}
639
cd9da200
VZ
640void wxDC::DoDrawCheckMark(wxCoord x1, wxCoord y1,
641 wxCoord width, wxCoord height)
642{
5adad466
JS
643#ifdef __WXMICROWIN__
644 if (!GetHDC()) return;
645#endif
d275c7eb 646
cd9da200
VZ
647 wxCoord x2 = x1 + width,
648 y2 = y1 + height;
649
04ef50df 650#if defined(__WIN32__) && !defined(__SC__) && !defined(__WXMICROWIN__)
cd9da200
VZ
651 RECT rect;
652 rect.left = x1;
653 rect.top = y1;
654 rect.right = x2;
655 rect.bottom = y2;
656
657 DrawFrameControl(GetHdc(), &rect, DFC_MENU, DFCS_MENUCHECK);
658#else // Win16
659 // In WIN16, draw a cross
660 HPEN blackPen = ::CreatePen(PS_SOLID, 1, RGB(0, 0, 0));
661 HPEN whiteBrush = (HPEN)::GetStockObject(WHITE_BRUSH);
e06b9569
JS
662 HPEN hPenOld = (HPEN)::SelectObject(GetHdc(), blackPen);
663 HPEN hBrushOld = (HPEN)::SelectObject(GetHdc(), whiteBrush);
cd9da200
VZ
664 ::SetROP2(GetHdc(), R2_COPYPEN);
665 Rectangle(GetHdc(), x1, y1, x2, y2);
8cb172b4 666 MoveToEx(GetHdc(), x1, y1, NULL);
cd9da200 667 LineTo(GetHdc(), x2, y2);
8cb172b4 668 MoveToEx(GetHdc(), x2, y1, NULL);
cd9da200
VZ
669 LineTo(GetHdc(), x1, y2);
670 ::SelectObject(GetHdc(), hPenOld);
671 ::SelectObject(GetHdc(), hBrushOld);
672 ::DeleteObject(blackPen);
673#endif // Win32/16
674
675 CalcBoundingBox(x1, y1);
676 CalcBoundingBox(x2, y2);
677}
678
72cdf4c9 679void wxDC::DoDrawPoint(wxCoord x, wxCoord y)
2bda0e17 680{
5adad466
JS
681#ifdef __WXMICROWIN__
682 if (!GetHDC()) return;
683#endif
d275c7eb 684
7bcb11d3
JS
685 COLORREF color = 0x00ffffff;
686 if (m_pen.Ok())
687 {
a23fd0e1 688 color = m_pen.GetColour().GetPixel();
7bcb11d3 689 }
a23fd0e1
VZ
690
691 SetPixel(GetHdc(), XLOG2DEV(x), YLOG2DEV(y), color);
692
7bcb11d3 693 CalcBoundingBox(x, y);
2bda0e17
KB
694}
695
72cdf4c9 696void wxDC::DoDrawPolygon(int n, wxPoint points[], wxCoord xoffset, wxCoord yoffset,int fillStyle)
2bda0e17 697{
5adad466
JS
698#ifdef __WXMICROWIN__
699 if (!GetHDC()) return;
700#endif
d275c7eb 701
f6bcfd97 702 wxColourChanger cc(*this); // needed for wxSTIPPLE_MASK_OPAQUE handling
de2d2cdc 703
7bcb11d3
JS
704 // Do things less efficiently if we have offsets
705 if (xoffset != 0 || yoffset != 0)
6a6c0a8b 706 {
7bcb11d3
JS
707 POINT *cpoints = new POINT[n];
708 int i;
709 for (i = 0; i < n; i++)
710 {
711 cpoints[i].x = (int)(points[i].x + xoffset);
712 cpoints[i].y = (int)(points[i].y + yoffset);
a23fd0e1 713
7bcb11d3
JS
714 CalcBoundingBox(cpoints[i].x, cpoints[i].y);
715 }
a23fd0e1
VZ
716 int prev = SetPolyFillMode(GetHdc(),fillStyle==wxODDEVEN_RULE?ALTERNATE:WINDING);
717 (void)Polygon(GetHdc(), cpoints, n);
718 SetPolyFillMode(GetHdc(),prev);
7bcb11d3
JS
719 delete[] cpoints;
720 }
721 else
722 {
723 int i;
724 for (i = 0; i < n; i++)
725 CalcBoundingBox(points[i].x, points[i].y);
a23fd0e1
VZ
726
727 int prev = SetPolyFillMode(GetHdc(),fillStyle==wxODDEVEN_RULE?ALTERNATE:WINDING);
728 (void)Polygon(GetHdc(), (POINT*) points, n);
729 SetPolyFillMode(GetHdc(),prev);
6a6c0a8b 730 }
2bda0e17
KB
731}
732
72cdf4c9 733void wxDC::DoDrawLines(int n, wxPoint points[], wxCoord xoffset, wxCoord yoffset)
2bda0e17 734{
5adad466
JS
735#ifdef __WXMICROWIN__
736 if (!GetHDC()) return;
737#endif
d275c7eb 738
7bcb11d3
JS
739 // Do things less efficiently if we have offsets
740 if (xoffset != 0 || yoffset != 0)
6a6c0a8b 741 {
7bcb11d3
JS
742 POINT *cpoints = new POINT[n];
743 int i;
744 for (i = 0; i < n; i++)
745 {
746 cpoints[i].x = (int)(points[i].x + xoffset);
747 cpoints[i].y = (int)(points[i].y + yoffset);
a23fd0e1 748
7bcb11d3
JS
749 CalcBoundingBox(cpoints[i].x, cpoints[i].y);
750 }
a23fd0e1 751 (void)Polyline(GetHdc(), cpoints, n);
7bcb11d3
JS
752 delete[] cpoints;
753 }
754 else
755 {
756 int i;
757 for (i = 0; i < n; i++)
758 CalcBoundingBox(points[i].x, points[i].y);
a23fd0e1
VZ
759
760 (void)Polyline(GetHdc(), (POINT*) points, n);
6a6c0a8b 761 }
2bda0e17
KB
762}
763
72cdf4c9 764void wxDC::DoDrawRectangle(wxCoord x, wxCoord y, wxCoord width, wxCoord height)
2bda0e17 765{
5adad466
JS
766#ifdef __WXMICROWIN__
767 if (!GetHDC()) return;
768#endif
d275c7eb 769
f6bcfd97 770 wxColourChanger cc(*this); // needed for wxSTIPPLE_MASK_OPAQUE handling
de2d2cdc 771
72cdf4c9
VZ
772 wxCoord x2 = x + width;
773 wxCoord y2 = y + height;
a23fd0e1 774
5456b916 775 if ((m_logicalFunction == wxCOPY) && (m_pen.GetStyle() == wxTRANSPARENT))
0bafad0c 776 {
7299b1b2 777 RECT rect;
5456b916
RR
778 rect.left = XLOG2DEV(x);
779 rect.top = YLOG2DEV(y);
780 rect.right = XLOG2DEV(x2);
7299b1b2
RD
781 rect.bottom = YLOG2DEV(y2);
782 (void)FillRect(GetHdc(), &rect, (HBRUSH)m_brush.GetResourceHandle() );
5456b916
RR
783 }
784 else
785 {
786 // Windows draws the filled rectangles without outline (i.e. drawn with a
787 // transparent pen) one pixel smaller in both directions and we want them
f6bcfd97 788 // to have the same size regardless of which pen is used - adjust
5456b916
RR
789
790