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