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