]> git.saurik.com Git - wxWidgets.git/blame - src/common/dcbase.cpp
fixing unicode compile
[wxWidgets.git] / src / common / dcbase.cpp
CommitLineData
dbe94982 1/////////////////////////////////////////////////////////////////////////////
06052f3f 2// Name: src/common/dcbase.cpp
1e6feb95
VZ
3// Purpose: generic methods of the wxDC Class
4// Author: Vadim Zeitlin
dbe94982
BM
5// Modified by:
6// Created: 05/25/99
7// RCS-ID: $Id$
77ffb593 8// Copyright: (c) wxWidgets team
65571936 9// Licence: wxWindows licence
dbe94982
BM
10/////////////////////////////////////////////////////////////////////////////
11
1e6feb95
VZ
12// ============================================================================
13// declarations
14// ============================================================================
15
1e6feb95
VZ
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
dbe94982
BM
20// For compilers that support precompilation, includes "wx.h".
21#include "wx/wxprec.h"
22
23#ifdef __BORLANDC__
bd1e9c12 24 #pragma hdrstop
dbe94982
BM
25#endif
26
dbe94982 27#include "wx/dc.h"
ab171e95
RR
28#include "wx/dcclient.h"
29#include "wx/dcmemory.h"
30#include "wx/dcscreen.h"
4f37154e 31#include "wx/dcprint.h"
4f37154e 32#include "wx/prntbase.h"
18680f86
WS
33
34#ifndef WX_PRECOMP
35 #include "wx/math.h"
f2498c4e 36 #include "wx/module.h"
18680f86 37#endif
dbe94982 38
888dde65 39#ifdef __WXMSW__
f2498c4e
VZ
40 #include "wx/msw/dcclient.h"
41 #include "wx/msw/dcmemory.h"
42 #include "wx/msw/dcscreen.h"
888dde65 43#endif
2970ae54 44
888dde65 45#ifdef __WXGTK__
f2498c4e
VZ
46 #include "wx/gtk/dcclient.h"
47 #include "wx/gtk/dcmemory.h"
48 #include "wx/gtk/dcscreen.h"
888dde65
RR
49#endif
50
51#ifdef __WXMAC__
f2498c4e
VZ
52 #include "wx/mac/dcclient.h"
53 #include "wx/mac/dcmemory.h"
54 #include "wx/mac/dcscreen.h"
888dde65 55#endif
2970ae54 56
938156b2
DE
57#ifdef __WXCOCOA__
58 #include "wx/cocoa/dcclient.h"
59 #include "wx/cocoa/dcmemory.h"
60 #include "wx/cocoa/dcscreen.h"
61#endif
62
e6514d0e 63#ifdef __WXX11__
f2498c4e
VZ
64 #include "wx/x11/dcclient.h"
65 #include "wx/x11/dcmemory.h"
66 #include "wx/x11/dcscreen.h"
e6514d0e
RR
67#endif
68
2970ae54
RR
69//----------------------------------------------------------------------------
70// wxDCFactory
71//----------------------------------------------------------------------------
72
73wxDCFactory *wxDCFactory::m_factory = NULL;
74
f2498c4e 75void wxDCFactory::Set(wxDCFactory *factory)
2970ae54 76{
f2498c4e 77 delete m_factory;
2970ae54 78
f2498c4e 79 m_factory = factory;
2970ae54
RR
80}
81
f0875501 82wxDCFactory *wxDCFactory::Get()
2970ae54 83{
f2498c4e
VZ
84 if ( !m_factory )
85 m_factory = new wxNativeDCFactory;
2970ae54 86
f2498c4e 87 return m_factory;
2970ae54
RR
88}
89
f2498c4e
VZ
90class wxDCFactoryCleanupModule : public wxModule
91{
92public:
93 virtual bool OnInit() { return true; }
94 virtual void OnExit() { wxDCFactory::Set(NULL); }
95
96private:
97 DECLARE_DYNAMIC_CLASS(wxDCFactoryCleanupModule)
98};
99
100IMPLEMENT_DYNAMIC_CLASS(wxDCFactoryCleanupModule, wxModule)
101
2970ae54
RR
102//-----------------------------------------------------------------------------
103// wxNativeDCFactory
104//-----------------------------------------------------------------------------
105
888dde65 106wxDCImpl* wxNativeDCFactory::CreateWindowDC( wxWindowDC *owner )
f0875501 107{
888dde65 108 return new wxWindowDCImpl( owner );
2970ae54
RR
109}
110
888dde65 111wxDCImpl* wxNativeDCFactory::CreateWindowDC( wxWindowDC *owner, wxWindow *window )
f0875501 112{
888dde65 113 return new wxWindowDCImpl( owner, window );
2970ae54
RR
114}
115
888dde65
RR
116wxDCImpl* wxNativeDCFactory::CreateClientDC( wxClientDC *owner )
117{
118 return new wxClientDCImpl( owner );
2970ae54
RR
119}
120
888dde65
RR
121wxDCImpl* wxNativeDCFactory::CreateClientDC( wxClientDC *owner, wxWindow *window )
122{
123 return new wxClientDCImpl( owner, window );
2970ae54
RR
124}
125
888dde65
RR
126wxDCImpl* wxNativeDCFactory::CreatePaintDC( wxPaintDC *owner )
127{
128 return new wxPaintDCImpl( owner );
2970ae54
RR
129}
130
888dde65
RR
131wxDCImpl* wxNativeDCFactory::CreatePaintDC( wxPaintDC *owner, wxWindow *window )
132{
133 return new wxPaintDCImpl( owner, window );
2970ae54
RR
134}
135
888dde65
RR
136wxDCImpl* wxNativeDCFactory::CreateMemoryDC( wxMemoryDC *owner )
137{
138 return new wxMemoryDCImpl( owner );
2970ae54
RR
139}
140
888dde65
RR
141wxDCImpl* wxNativeDCFactory::CreateMemoryDC( wxMemoryDC *owner, wxBitmap &bitmap )
142{
143 return new wxMemoryDCImpl( owner, bitmap );
2970ae54
RR
144}
145
888dde65
RR
146wxDCImpl* wxNativeDCFactory::CreateMemoryDC( wxMemoryDC *owner, wxDC *dc )
147{
148 return new wxMemoryDCImpl( owner, dc );
ab171e95
RR
149}
150
888dde65
RR
151wxDCImpl* wxNativeDCFactory::CreateScreenDC( wxScreenDC *owner )
152{
153 return new wxScreenDCImpl( owner );
2970ae54
RR
154}
155
6b4f4d47 156#if wxUSE_PRINTING_ARCHITECTURE
888dde65 157wxDCImpl *wxNativeDCFactory::CreatePrinterDC( wxPrinterDC *owner, const wxPrintData &data )
c8ddadff 158{
4f37154e 159 wxPrintFactory *factory = wxPrintFactory::GetFactory();
888dde65 160 return factory->CreatePrinterDCImpl( owner, data );
c8ddadff 161}
6b4f4d47 162#endif
c8ddadff 163
2970ae54
RR
164//-----------------------------------------------------------------------------
165// wxWindowDC
166//-----------------------------------------------------------------------------
167
f0875501 168IMPLEMENT_ABSTRACT_CLASS(wxWindowDC, wxDC)
2970ae54 169
f0875501
VZ
170wxWindowDC::wxWindowDC(wxWindow *win)
171 : wxDC(wxDCFactory::Get()->CreateWindowDC(this, win))
2970ae54 172{
2970ae54
RR
173}
174
175//-----------------------------------------------------------------------------
176// wxClientDC
177//-----------------------------------------------------------------------------
178
f0875501 179IMPLEMENT_ABSTRACT_CLASS(wxClientDC, wxWindowDC)
2970ae54 180
f0875501
VZ
181wxClientDC::wxClientDC(wxWindow *win)
182 : wxWindowDC(wxDCFactory::Get()->CreateClientDC(this, win))
2970ae54 183{
2970ae54
RR
184}
185
2970ae54
RR
186//-----------------------------------------------------------------------------
187// wxMemoryDC
188//-----------------------------------------------------------------------------
189
190IMPLEMENT_DYNAMIC_CLASS(wxMemoryDC, wxDC)
191
192wxMemoryDC::wxMemoryDC()
f0875501 193 : wxDC(wxDCFactory::Get()->CreateMemoryDC(this))
2970ae54 194{
2970ae54
RR
195}
196
f0875501
VZ
197wxMemoryDC::wxMemoryDC(wxBitmap& bitmap)
198 : wxDC(wxDCFactory::Get()->CreateMemoryDC(this, bitmap))
2970ae54 199{
2970ae54
RR
200}
201
f0875501
VZ
202wxMemoryDC::wxMemoryDC(wxDC *dc)
203 : wxDC(wxDCFactory::Get()->CreateMemoryDC(this, dc))
2970ae54 204{
ab171e95
RR
205}
206
207void wxMemoryDC::SelectObject(wxBitmap& bmp)
208{
209 // make sure that the given wxBitmap is not sharing its data with other
210 // wxBitmap instances as its contents will be modified by any drawing
211 // operation done on this DC
212 if (bmp.IsOk())
213 bmp.UnShare();
214
4f37154e 215 GetImpl()->DoSelect(bmp);
ab171e95
RR
216}
217
218void wxMemoryDC::SelectObjectAsSource(const wxBitmap& bmp)
219{
4f37154e 220 GetImpl()->DoSelect(bmp);
2970ae54 221}
ab171e95
RR
222
223const wxBitmap& wxMemoryDC::GetSelectedBitmap() const
224{
4f37154e 225 return GetImpl()->GetSelectedBitmap();
ab171e95
RR
226}
227
228wxBitmap& wxMemoryDC::GetSelectedBitmap()
229{
4f37154e 230 return GetImpl()->GetSelectedBitmap();
ab171e95
RR
231}
232
f0875501 233
2970ae54
RR
234//-----------------------------------------------------------------------------
235// wxPaintDC
236//-----------------------------------------------------------------------------
237
f0875501 238IMPLEMENT_ABSTRACT_CLASS(wxPaintDC, wxClientDC)
2970ae54 239
f0875501
VZ
240wxPaintDC::wxPaintDC(wxWindow *win)
241 : wxClientDC(wxDCFactory::Get()->CreatePaintDC(this, win))
2970ae54 242{
2970ae54
RR
243}
244
ab171e95
RR
245//-----------------------------------------------------------------------------
246// wxScreenDC
247//-----------------------------------------------------------------------------
248
249IMPLEMENT_DYNAMIC_CLASS(wxScreenDC, wxWindowDC)
250
251wxScreenDC::wxScreenDC()
f0875501 252 : wxDC(wxDCFactory::Get()->CreateScreenDC(this))
ab171e95 253{
2970ae54
RR
254}
255
4f37154e
RR
256//-----------------------------------------------------------------------------
257// wxPrinterDC
258//-----------------------------------------------------------------------------
259
6b4f4d47
RR
260#if wxUSE_PRINTING_ARCHITECTURE
261
4f37154e
RR
262IMPLEMENT_DYNAMIC_CLASS(wxPrinterDC, wxDC)
263
264wxPrinterDC::wxPrinterDC()
f0875501 265 : wxDC(wxDCFactory::Get()->CreatePrinterDC(this, wxPrintData()))
4f37154e 266{
4f37154e
RR
267}
268
f0875501
VZ
269wxPrinterDC::wxPrinterDC(const wxPrintData& data)
270 : wxDC(wxDCFactory::Get()->CreatePrinterDC(this, data))
38dd8ed4
RR
271{
272}
273
274wxRect wxPrinterDC::GetPaperRect()
275{
276 return GetImpl()->GetPaperRect();
277}
278
279int wxPrinterDC::GetResolution()
280{
281 return GetImpl()->GetResolution();
282}
283
f0875501 284#endif // wxUSE_PRINTING_ARCHITECTURE
38dd8ed4 285
2970ae54 286//-----------------------------------------------------------------------------
888dde65 287// wxDCImpl
2970ae54
RR
288//-----------------------------------------------------------------------------
289
888dde65 290IMPLEMENT_ABSTRACT_CLASS(wxDCImpl, wxObject)
2970ae54 291
888dde65
RR
292wxDCImpl::wxDCImpl( wxDC *owner )
293 : m_window(NULL)
294 , m_colour(wxColourDisplay())
2970ae54
RR
295 , m_ok(true)
296 , m_clipping(false)
297 , m_isInteractive(0)
298 , m_isBBoxValid(false)
299 , m_logicalOriginX(0), m_logicalOriginY(0)
300 , m_deviceOriginX(0), m_deviceOriginY(0)
301 , m_deviceLocalOriginX(0), m_deviceLocalOriginY(0)
302 , m_logicalScaleX(1.0), m_logicalScaleY(1.0)
303 , m_userScaleX(1.0), m_userScaleY(1.0)
304 , m_scaleX(1.0), m_scaleY(1.0)
305 , m_signX(1), m_signY(1)
306 , m_minX(0), m_minY(0), m_maxX(0), m_maxY(0)
307 , m_clipX1(0), m_clipY1(0), m_clipX2(0), m_clipY2(0)
308 , m_logicalFunction(wxCOPY)
309 , m_backgroundMode(wxTRANSPARENT)
310 , m_mappingMode(wxMM_TEXT)
311 , m_pen()
312 , m_brush()
313 , m_backgroundBrush(*wxTRANSPARENT_BRUSH)
314 , m_textForegroundColour(*wxBLACK)
315 , m_textBackgroundColour(*wxWHITE)
316 , m_font()
317#if wxUSE_PALETTE
318 , m_palette()
319 , m_hasCustomPalette(false)
320#endif // wxUSE_PALETTE
321{
322 m_owner = owner;
323
324 m_mm_to_pix_x = (double)wxGetDisplaySize().GetWidth() /
325 (double)wxGetDisplaySizeMM().GetWidth();
326 m_mm_to_pix_y = (double)wxGetDisplaySize().GetHeight() /
327 (double)wxGetDisplaySizeMM().GetHeight();
f0875501 328
2970ae54
RR
329 ResetBoundingBox();
330 ResetClipping();
331}
332
888dde65 333wxDCImpl::~wxDCImpl()
2970ae54
RR
334{
335}
336
2970ae54
RR
337// ----------------------------------------------------------------------------
338// coordinate conversions and transforms
339// ----------------------------------------------------------------------------
340
888dde65 341wxCoord wxDCImpl::DeviceToLogicalX(wxCoord x) const
2970ae54
RR
342{
343 return wxRound((double)(x - m_deviceOriginX - m_deviceLocalOriginX) / m_scaleX) * m_signX + m_logicalOriginX;
344}
345
888dde65 346wxCoord wxDCImpl::DeviceToLogicalY(wxCoord y) const
2970ae54
RR
347{
348 return wxRound((double)(y - m_deviceOriginY - m_deviceLocalOriginY) / m_scaleY) * m_signY + m_logicalOriginY;
349}
350
888dde65 351wxCoord wxDCImpl::DeviceToLogicalXRel(wxCoord x) const
2970ae54
RR
352{
353 return wxRound((double)(x) / m_scaleX);
354}
355
888dde65 356wxCoord wxDCImpl::DeviceToLogicalYRel(wxCoord y) const
2970ae54
RR
357{
358 return wxRound((double)(y) / m_scaleY);
359}
360
888dde65 361wxCoord wxDCImpl::LogicalToDeviceX(wxCoord x) const
2970ae54 362{
02255e07 363 return wxRound((double)(x - m_logicalOriginX) * m_scaleX) * m_signX + m_deviceOriginX * m_signY + m_deviceLocalOriginX;
2970ae54
RR
364}
365
888dde65 366wxCoord wxDCImpl::LogicalToDeviceY(wxCoord y) const
2970ae54 367{
02255e07 368 return wxRound((double)(y - m_logicalOriginY) * m_scaleY) * m_signY + m_deviceOriginY * m_signY + m_deviceLocalOriginY;
2970ae54
RR
369}
370
888dde65 371wxCoord wxDCImpl::LogicalToDeviceXRel(wxCoord x) const
2970ae54
RR
372{
373 return wxRound((double)(x) * m_scaleX);
374}
375
888dde65 376wxCoord wxDCImpl::LogicalToDeviceYRel(wxCoord y) const
2970ae54
RR
377{
378 return wxRound((double)(y) * m_scaleY);
379}
380
888dde65 381void wxDCImpl::ComputeScaleAndOrigin()
2970ae54
RR
382{
383 m_scaleX = m_logicalScaleX * m_userScaleX;
384 m_scaleY = m_logicalScaleY * m_userScaleY;
385}
386
888dde65 387void wxDCImpl::SetMapMode( int mode )
2970ae54
RR
388{
389 switch (mode)
390 {
391 case wxMM_TWIPS:
392 SetLogicalScale( twips2mm*m_mm_to_pix_x, twips2mm*m_mm_to_pix_y );
393 break;
394 case wxMM_POINTS:
395 SetLogicalScale( pt2mm*m_mm_to_pix_x, pt2mm*m_mm_to_pix_y );
396 break;
397 case wxMM_METRIC:
398 SetLogicalScale( m_mm_to_pix_x, m_mm_to_pix_y );
399 break;
400 case wxMM_LOMETRIC:
401 SetLogicalScale( m_mm_to_pix_x/10.0, m_mm_to_pix_y/10.0 );
402 break;
403 default:
404 case wxMM_TEXT:
405 SetLogicalScale( 1.0, 1.0 );
406 break;
407 }
408 m_mappingMode = mode;
409}
410
888dde65 411void wxDCImpl::SetUserScale( double x, double y )
2970ae54
RR
412{
413 // allow negative ? -> no
414 m_userScaleX = x;
415 m_userScaleY = y;
416 ComputeScaleAndOrigin();
417}
418
888dde65 419void wxDCImpl::SetLogicalScale( double x, double y )
2970ae54
RR
420{
421 // allow negative ?
422 m_logicalScaleX = x;
423 m_logicalScaleY = y;
424 ComputeScaleAndOrigin();
425}
426
888dde65 427void wxDCImpl::SetLogicalOrigin( wxCoord x, wxCoord y )
2970ae54
RR
428{
429 m_logicalOriginX = x * m_signX;
430 m_logicalOriginY = y * m_signY;
431 ComputeScaleAndOrigin();
432}
433
888dde65 434void wxDCImpl::SetDeviceOrigin( wxCoord x, wxCoord y )
2970ae54
RR
435{
436 m_deviceOriginX = x;
437 m_deviceOriginY = y;
438 ComputeScaleAndOrigin();
439}
440
888dde65 441void wxDCImpl::SetDeviceLocalOrigin( wxCoord x, wxCoord y )
2970ae54
RR
442{
443 m_deviceLocalOriginX = x;
444 m_deviceLocalOriginY = y;
445 ComputeScaleAndOrigin();
446}
447
888dde65 448void wxDCImpl::SetAxisOrientation( bool xLeftRight, bool yBottomUp )
2970ae54
RR
449{
450 // only wxPostScripDC has m_signX = -1, we override SetAxisOrientation there
02255e07 451 // wxWidgets 2.9: no longer override it
2970ae54
RR
452 m_signX = (xLeftRight ? 1 : -1);
453 m_signY = (yBottomUp ? -1 : 1);
454 ComputeScaleAndOrigin();
455}
456
457
458// Each element of the widths array will be the width of the string up to and
459// including the corresponding character in text. This is the generic
460// implementation, the port-specific classes should do this with native APIs
461// if available and if faster. Note: pango_layout_index_to_pos is much slower
462// than calling GetTextExtent!!
463
464#define FWC_SIZE 256
465
466class FontWidthCache
467{
468public:
469 FontWidthCache() : m_scaleX(1), m_widths(NULL) { }
470 ~FontWidthCache() { delete []m_widths; }
471
472 void Reset()
473 {
474 if (!m_widths)
475 m_widths = new int[FWC_SIZE];
476
477 memset(m_widths, 0, sizeof(int)*FWC_SIZE);
478 }
479
480 wxFont m_font;
481 double m_scaleX;
482 int *m_widths;
483};
484
485static FontWidthCache s_fontWidthCache;
486
888dde65 487bool wxDCImpl::DoGetPartialTextExtents(const wxString& text, wxArrayInt& widths) const
2970ae54
RR
488{
489 int totalWidth = 0;
490
491 const size_t len = text.length();
492 widths.Empty();
493 widths.Add(0, len);
494
495 // reset the cache if font or horizontal scale have changed
496 if ( !s_fontWidthCache.m_widths ||
497 !wxIsSameDouble(s_fontWidthCache.m_scaleX, m_scaleX) ||
498 (s_fontWidthCache.m_font != GetFont()) )
499 {
500 s_fontWidthCache.Reset();
501 s_fontWidthCache.m_font = GetFont();
502 s_fontWidthCache.m_scaleX = m_scaleX;
503 }
504
505 // Calculate the position of each character based on the widths of
506 // the previous characters
507 int w, h;
508 for ( size_t i = 0; i < len; i++ )
509 {
510 const wxChar c = text[i];
511 unsigned int c_int = (unsigned int)c;
512
513 if ((c_int < FWC_SIZE) && (s_fontWidthCache.m_widths[c_int] != 0))
514 {
515 w = s_fontWidthCache.m_widths[c_int];
516 }
517 else
518 {
ab171e95 519 DoGetTextExtent(c, &w, &h);
2970ae54
RR
520 if (c_int < FWC_SIZE)
521 s_fontWidthCache.m_widths[c_int] = w;
522 }
523
524 totalWidth += w;
525 widths[i] = totalWidth;
526 }
527
528 return true;
529}
530
888dde65 531void wxDCImpl::GetMultiLineTextExtent(const wxString& text,
2970ae54
RR
532 wxCoord *x,
533 wxCoord *y,
534 wxCoord *h,
535 const wxFont *font) const
536{
537 wxCoord widthTextMax = 0, widthLine,
538 heightTextTotal = 0, heightLineDefault = 0, heightLine = 0;
539
540 wxString curLine;
4f37154e 541 for ( wxString::const_iterator pc = text.begin(); ; ++pc )
2970ae54 542 {
4f37154e 543 if ( pc == text.end() || *pc == _T('\n') )
2970ae54
RR
544 {
545 if ( curLine.empty() )
546 {
547 // we can't use GetTextExtent - it will return 0 for both width
548 // and height and an empty line should count in height
549 // calculation
550
551 // assume that this line has the same height as the previous
552 // one
553 if ( !heightLineDefault )
554 heightLineDefault = heightLine;
555
556 if ( !heightLineDefault )
557 {
558 // but we don't know it yet - choose something reasonable
559 DoGetTextExtent(_T("W"), NULL, &heightLineDefault,
560 NULL, NULL, font);
561 }
562
563 heightTextTotal += heightLineDefault;
564 }
565 else
566 {
567 DoGetTextExtent(curLine, &widthLine, &heightLine,
568 NULL, NULL, font);
569 if ( widthLine > widthTextMax )
570 widthTextMax = widthLine;
571 heightTextTotal += heightLine;
572 }
573
4f37154e 574 if ( pc == text.end() )
2970ae54 575 {
4f37154e 576 break;
2970ae54 577 }
4f37154e 578 else // '\n'
2970ae54 579 {
4f37154e 580 curLine.clear();
2970ae54
RR
581 }
582 }
583 else
584 {
585 curLine += *pc;
586 }
587 }
588
589 if ( x )
590 *x = widthTextMax;
591 if ( y )
592 *y = heightTextTotal;
593 if ( h )
594 *h = heightLine;
595}
596
888dde65 597void wxDCImpl::DoDrawCheckMark(wxCoord x1, wxCoord y1,
2970ae54
RR
598 wxCoord width, wxCoord height)
599{
ab171e95 600 wxCHECK_RET( IsOk(), wxT("invalid window dc") );
2970ae54
RR
601
602 wxCoord x2 = x1 + width,
603 y2 = y1 + height;
604
605 // the pen width is calibrated to give 3 for width == height == 10
ab171e95 606 wxDCPenChanger pen( *m_owner, wxPen(GetTextForeground(), (width + height + 1)/7));
2970ae54
RR
607
608 // we're drawing a scaled version of wx/generic/tick.xpm here
609 wxCoord x3 = x1 + (4*width) / 10, // x of the tick bottom
610 y3 = y1 + height / 2; // y of the left tick branch
611 DoDrawLine(x1, y3, x3, y2);
612 DoDrawLine(x3, y2, x2, y1);
613
614 CalcBoundingBox(x1, y1);
615 CalcBoundingBox(x2, y2);
616}
617
618bool
888dde65 619wxDCImpl::DoStretchBlit(wxCoord xdest, wxCoord ydest,
2970ae54
RR
620 wxCoord dstWidth, wxCoord dstHeight,
621 wxDC *source,
622 wxCoord xsrc, wxCoord ysrc,
623 wxCoord srcWidth, wxCoord srcHeight,
624 int rop,
625 bool useMask,
626 wxCoord xsrcMask,
627 wxCoord ysrcMask)
628{
629 wxCHECK_MSG( srcWidth && srcHeight && dstWidth && dstHeight, false,
630 _T("invalid blit size") );
631
632 // emulate the stretching by modifying the DC scale
633 double xscale = (double)srcWidth/dstWidth,
634 yscale = (double)srcHeight/dstHeight;
635
636 double xscaleOld, yscaleOld;
637 GetUserScale(&xscaleOld, &yscaleOld);
638 SetUserScale(xscaleOld/xscale, yscaleOld/yscale);
639
640 bool rc = DoBlit(wxCoord(xdest*xscale), wxCoord(ydest*yscale),
641 wxCoord(dstWidth*xscale), wxCoord(dstHeight*yscale),
642 source,
643 xsrc, ysrc, rop, useMask, xsrcMask, ysrcMask);
644
645 SetUserScale(xscaleOld, yscaleOld);
646
647 return rc;
648}
649
888dde65 650void wxDCImpl::DrawLines(const wxPointList *list, wxCoord xoffset, wxCoord yoffset)
2970ae54
RR
651{
652 int n = list->GetCount();
653 wxPoint *points = new wxPoint[n];
654
655 int i = 0;
b0d7707b 656 for ( wxPointList::compatibility_iterator node = list->GetFirst(); node; node = node->GetNext(), i++ )
2970ae54 657 {
b0d7707b 658 wxPoint *point = node->GetData();
2970ae54
RR
659 points[i].x = point->x;
660 points[i].y = point->y;
661 }
662
663 DoDrawLines(n, points, xoffset, yoffset);
664
665 delete [] points;
666}
667
888dde65 668void wxDCImpl::DrawPolygon(const wxPointList *list,
2970ae54
RR
669 wxCoord xoffset, wxCoord yoffset,
670 int fillStyle)
671{
672 int n = list->GetCount();
673 wxPoint *points = new wxPoint[n];
674
675 int i = 0;
b0d7707b 676 for ( wxPointList::compatibility_iterator node = list->GetFirst(); node; node = node->GetNext(), i++ )
2970ae54 677 {
b0d7707b 678 wxPoint *point = node->GetData();
2970ae54
RR
679 points[i].x = point->x;
680 points[i].y = point->y;
681 }
682
683 DoDrawPolygon(n, points, xoffset, yoffset, fillStyle);
684
685 delete [] points;
686}
687
688void
888dde65 689wxDCImpl::DoDrawPolyPolygon(int n,
2970ae54
RR
690 int count[],
691 wxPoint points[],
692 wxCoord xoffset, wxCoord yoffset,
693 int fillStyle)
694{
695 if ( n == 1 )
696 {
697 DoDrawPolygon(count[0], points, xoffset, yoffset, fillStyle);
698 return;
699 }
700
701 int i, j, lastOfs;
702 wxPoint* pts;
703 wxPen pen;
704
705 for (i = j = lastOfs = 0; i < n; i++)
706 {
707 lastOfs = j;
708 j += count[i];
709 }
710 pts = new wxPoint[j+n-1];
711 for (i = 0; i < j; i++)
712 pts[i] = points[i];
713 for (i = 2; i <= n; i++)
714 {
715 lastOfs -= count[n-i];
716 pts[j++] = pts[lastOfs];
717 }
718
719 pen = GetPen();
720 SetPen(wxPen(*wxBLACK, 0, wxTRANSPARENT));
721 DoDrawPolygon(j, pts, xoffset, yoffset, fillStyle);
722 SetPen(pen);
723 for (i = j = 0; i < n; i++)
724 {
725 DoDrawLines(count[i], pts+j, xoffset, yoffset);
726 j += count[i];
727 }
728 delete[] pts;
729}
730
731#if wxUSE_SPLINES
732
888dde65 733void wxDCImpl::DoDrawSpline(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2, wxCoord x3, wxCoord y3)
2970ae54 734{
b0d7707b 735 wxPointList point_list;
2970ae54
RR
736
737 wxPoint *point1 = new wxPoint;
738 point1->x = x1; point1->y = y1;
b0d7707b 739 point_list.Append( point1 );
2970ae54
RR
740
741 wxPoint *point2 = new wxPoint;
742 point2->x = x2; point2->y = y2;
b0d7707b 743 point_list.Append( point2 );
2970ae54
RR
744
745 wxPoint *point3 = new wxPoint;
746 point3->x = x3; point3->y = y3;
b0d7707b 747 point_list.Append( point3 );
2970ae54 748
ab171e95 749 DoDrawSpline(&point_list);
2970ae54 750
b0d7707b 751 for( wxPointList::compatibility_iterator node = point_list.GetFirst(); node; node = node->GetNext() )
2970ae54 752 {
b0d7707b 753 wxPoint *p = node->GetData();
2970ae54
RR
754 delete p;
755 }
756}
757
888dde65 758void wxDCImpl::DoDrawSpline(int n, wxPoint points[])
2970ae54 759{
b0d7707b 760 wxPointList list;
2970ae54 761 for (int i =0; i < n; i++)
b0d7707b 762 list.Append( &points[i] );
2970ae54 763
ab171e95 764 DoDrawSpline(&list);
2970ae54
RR
765}
766
767// ----------------------------------- spline code ----------------------------------------
768
769void wx_quadratic_spline(double a1, double b1, double a2, double b2,
770 double a3, double b3, double a4, double b4);
771void wx_clear_stack();
772int wx_spline_pop(double *x1, double *y1, double *x2, double *y2, double *x3,
773 double *y3, double *x4, double *y4);
774void wx_spline_push(double x1, double y1, double x2, double y2, double x3, double y3,
775 double x4, double y4);
776static bool wx_spline_add_point(double x, double y);
ab171e95 777static void wx_spline_draw_point_array(wxDC *dc);
2970ae54 778
b0d7707b 779wxPointList wx_spline_point_list;
2970ae54
RR
780
781#define half(z1, z2) ((z1+z2)/2.0)
782#define THRESHOLD 5
783
784/* iterative version */
785
786void wx_quadratic_spline(double a1, double b1, double a2, double b2, double a3, double b3, double a4,
787 double b4)
788{
789 register double xmid, ymid;
790 double x1, y1, x2, y2, x3, y3, x4, y4;
791
792 wx_clear_stack();
793 wx_spline_push(a1, b1, a2, b2, a3, b3, a4, b4);
794
795 while (wx_spline_pop(&x1, &y1, &x2, &y2, &x3, &y3, &x4, &y4)) {
796 xmid = (double)half(x2, x3);
797 ymid = (double)half(y2, y3);
798 if (fabs(x1 - xmid) < THRESHOLD && fabs(y1 - ymid) < THRESHOLD &&
799 fabs(xmid - x4) < THRESHOLD && fabs(ymid - y4) < THRESHOLD) {
800 wx_spline_add_point( x1, y1 );
801 wx_spline_add_point( xmid, ymid );
802 } else {
803 wx_spline_push(xmid, ymid, (double)half(xmid, x3), (double)half(ymid, y3),
804 (double)half(x3, x4), (double)half(y3, y4), x4, y4);
805 wx_spline_push(x1, y1, (double)half(x1, x2), (double)half(y1, y2),
806 (double)half(x2, xmid), (double)half(y2, ymid), xmid, ymid);
807 }
808 }
809}
810
811/* utilities used by spline drawing routines */
812
813typedef struct wx_spline_stack_struct {
814 double x1, y1, x2, y2, x3, y3, x4, y4;
815} Stack;
816
817#define SPLINE_STACK_DEPTH 20
818static Stack wx_spline_stack[SPLINE_STACK_DEPTH];
819static Stack *wx_stack_top;
820static int wx_stack_count;
821
822void wx_clear_stack()
823{
824 wx_stack_top = wx_spline_stack;
825 wx_stack_count = 0;
826}
827
828void wx_spline_push(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4)
829{
830 wx_stack_top->x1 = x1;
831 wx_stack_top->y1 = y1;
832 wx_stack_top->x2 = x2;
833 wx_stack_top->y2 = y2;
834 wx_stack_top->x3 = x3;
835 wx_stack_top->y3 = y3;
836 wx_stack_top->x4 = x4;
837 wx_stack_top->y4 = y4;
838 wx_stack_top++;
839 wx_stack_count++;
840}
841
842int wx_spline_pop(double *x1, double *y1, double *x2, double *y2,
843 double *x3, double *y3, double *x4, double *y4)
844{
845 if (wx_stack_count == 0)
846 return (0);
847 wx_stack_top--;
848 wx_stack_count--;
849 *x1 = wx_stack_top->x1;
850 *y1 = wx_stack_top->y1;
851 *x2 = wx_stack_top->x2;
852 *y2 = wx_stack_top->y2;
853 *x3 = wx_stack_top->x3;
854 *y3 = wx_stack_top->y3;
855 *x4 = wx_stack_top->x4;
856 *y4 = wx_stack_top->y4;
857 return (1);
858}
859
860static bool wx_spline_add_point(double x, double y)
861{
b0d7707b
RR
862 wxPoint *point = new wxPoint( wxRound(x), wxRound(y) );
863 wx_spline_point_list.Append(point );
864 return true;
2970ae54
RR
865}
866
867static void wx_spline_draw_point_array(wxDC *dc)
868{
4f37154e 869 dc->DrawLines(&wx_spline_point_list, 0, 0 );
b0d7707b
RR
870 wxPointList::compatibility_iterator node = wx_spline_point_list.GetFirst();
871 while (node)
872 {
873 wxPoint *point = node->GetData();
874 delete point;
875 wx_spline_point_list.Erase(node);
876 node = wx_spline_point_list.GetFirst();
877 }
2970ae54
RR
878}
879
888dde65 880void wxDCImpl::DoDrawSpline( const wxPointList *points )
2970ae54 881{
ab171e95 882 wxCHECK_RET( IsOk(), wxT("invalid window dc") );
2970ae54
RR
883
884 wxPoint *p;
885 double cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4;
886 double x1, y1, x2, y2;
887
b0d7707b 888 wxPointList::compatibility_iterator node = points->GetFirst();
2970ae54
RR
889 if (!node)
890 // empty list
891 return;
892
893 p = (wxPoint *)node->GetData();
894
895 x1 = p->x;
896 y1 = p->y;
897
898 node = node->GetNext();
b0d7707b 899 p = node->GetData();
2970ae54
RR
900
901 x2 = p->x;
902 y2 = p->y;
903 cx1 = (double)((x1 + x2) / 2);
904 cy1 = (double)((y1 + y2) / 2);
905 cx2 = (double)((cx1 + x2) / 2);
906 cy2 = (double)((cy1 + y2) / 2);
907
908 wx_spline_add_point(x1, y1);
909
910 while ((node = node->GetNext())
911#if !wxUSE_STL
912 != NULL
913#endif // !wxUSE_STL
914 )
915 {
b0d7707b 916 p = node->GetData();
2970ae54
RR
917 x1 = x2;
918 y1 = y2;
919 x2 = p->x;
920 y2 = p->y;
921 cx4 = (double)(x1 + x2) / 2;
922 cy4 = (double)(y1 + y2) / 2;
923 cx3 = (double)(x1 + cx4) / 2;
924 cy3 = (double)(y1 + cy4) / 2;
925
926 wx_quadratic_spline(cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4);
927
928 cx1 = cx4;
929 cy1 = cy4;
930 cx2 = (double)(cx1 + x2) / 2;
931 cy2 = (double)(cy1 + y2) / 2;
932 }
933
934 wx_spline_add_point( cx1, cy1 );
935 wx_spline_add_point( x2, y2 );
936
937 wx_spline_draw_point_array( m_owner );
938}
939
940#endif // wxUSE_SPLINES
941
942
2970ae54 943
888dde65 944void wxDCImpl::DoGradientFillLinear(const wxRect& rect,
2970ae54
RR
945 const wxColour& initialColour,
946 const wxColour& destColour,
947 wxDirection nDirection)
948{
949 // save old pen
950 wxPen oldPen = m_pen;
951 wxBrush oldBrush = m_brush;
952
953 wxUint8 nR1 = initialColour.Red();
954 wxUint8 nG1 = initialColour.Green();
955 wxUint8 nB1 = initialColour.Blue();
956 wxUint8 nR2 = destColour.Red();
957 wxUint8 nG2 = destColour.Green();
958 wxUint8 nB2 = destColour.Blue();
959 wxUint8 nR, nG, nB;
960
961 if ( nDirection == wxEAST || nDirection == wxWEST )
962 {
963 wxInt32 x = rect.GetWidth();
964 wxInt32 w = x; // width of area to shade
965 wxInt32 xDelta = w/256; // height of one shade bend
966 if (xDelta < 1)
967 xDelta = 1;
968
969 while (x >= xDelta)
970 {
971 x -= xDelta;
972 if (nR1 > nR2)
973 nR = nR1 - (nR1-nR2)*(w-x)/w;
974 else
975 nR = nR1 + (nR2-nR1)*(w-x)/w;
976
977 if (nG1 > nG2)
978 nG = nG1 - (nG1-nG2)*(w-x)/w;
979 else
980 nG = nG1 + (nG2-nG1)*(w-x)/w;
981
982 if (nB1 > nB2)
983 nB = nB1 - (nB1-nB2)*(w-x)/w;
984 else
985 nB = nB1 + (nB2-nB1)*(w-x)/w;
986
987 wxColour colour(nR,nG,nB);
988 SetPen(wxPen(colour, 1, wxSOLID));
989 SetBrush(wxBrush(colour));
990 if(nDirection == wxEAST)
5f77ee3b 991 DoDrawRectangle(rect.GetRight()-x-xDelta+1, rect.GetTop(),
2970ae54
RR
992 xDelta, rect.GetHeight());
993 else //nDirection == wxWEST
994 DoDrawRectangle(rect.GetLeft()+x, rect.GetTop(),
995 xDelta, rect.GetHeight());
996 }
997 }
998 else // nDirection == wxNORTH || nDirection == wxSOUTH
999 {
1000 wxInt32 y = rect.GetHeight();
1001 wxInt32 w = y; // height of area to shade
1002 wxInt32 yDelta = w/255; // height of one shade bend
1003 if (yDelta < 1)
1004 yDelta = 1;
1005
1006 while (y > 0)
1007 {
1008 y -= yDelta;
1009 if (nR1 > nR2)
1010 nR = nR1 - (nR1-nR2)*(w-y)/w;
1011 else
1012 nR = nR1 + (nR2-nR1)*(w-y)/w;
1013
1014 if (nG1 > nG2)
1015 nG = nG1 - (nG1-nG2)*(w-y)/w;
1016 else
1017 nG = nG1 + (nG2-nG1)*(w-y)/w;
1018
1019 if (nB1 > nB2)
1020 nB = nB1 - (nB1-nB2)*(w-y)/w;
1021 else
1022 nB = nB1 + (nB2-nB1)*(w-y)/w;
1023
1024 wxColour colour(nR,nG,nB);
1025 SetPen(wxPen(colour, 1, wxSOLID));
1026 SetBrush(wxBrush(colour));
1027 if(nDirection == wxNORTH)
1028 DoDrawRectangle(rect.GetLeft(), rect.GetTop()+y,
1029 rect.GetWidth(), yDelta);
1030 else //nDirection == wxSOUTH
5f77ee3b 1031 DoDrawRectangle(rect.GetLeft(), rect.GetBottom()-y-yDelta+1,
2970ae54
RR
1032 rect.GetWidth(), yDelta);
1033 }
1034 }
1035
1036 SetPen(oldPen);
1037 SetBrush(oldBrush);
1038}
1039
888dde65 1040void wxDCImpl::DoGradientFillConcentric(const wxRect& rect,
2970ae54
RR
1041 const wxColour& initialColour,
1042 const wxColour& destColour,
1043 const wxPoint& circleCenter)
1044{
1045 //save the old pen color
1046 wxColour oldPenColour = m_pen.GetColour();
1047
1048 wxUint8 nR1 = destColour.Red();
1049 wxUint8 nG1 = destColour.Green();
1050 wxUint8 nB1 = destColour.Blue();
1051 wxUint8 nR2 = initialColour.Red();
1052 wxUint8 nG2 = initialColour.Green();
1053 wxUint8 nB2 = initialColour.Blue();
1054 wxUint8 nR, nG, nB;
1055
1056
1057 //Radius
1058 wxInt32 cx = rect.GetWidth() / 2;
1059 wxInt32 cy = rect.GetHeight() / 2;
1060 wxInt32 nRadius;
1061 if (cx < cy)
1062 nRadius = cx;
1063 else
1064 nRadius = cy;
1065
1066 //Offset of circle
1067 wxInt32 nCircleOffX = circleCenter.x - (rect.GetWidth() / 2);
1068 wxInt32 nCircleOffY = circleCenter.y - (rect.GetHeight() / 2);
1069
1070 for ( wxInt32 x = 0; x < rect.GetWidth(); x++ )
1071 {
1072 for ( wxInt32 y = 0; y < rect.GetHeight(); y++ )
1073 {
1074 //get color difference
1075 wxInt32 nGradient = ((nRadius -
1076 (wxInt32)sqrt(
1077 pow((double)(x - cx - nCircleOffX), 2) +
1078 pow((double)(y - cy - nCircleOffY), 2)
1079 )) * 100) / nRadius;
1080
1081 //normalize Gradient
1082 if (nGradient < 0 )
1083 nGradient = 0;
1084
1085 //get dest colors
1086 nR = (wxUint8)(nR1 + ((nR2 - nR1) * nGradient / 100));
1087 nG = (wxUint8)(nG1 + ((nG2 - nG1) * nGradient / 100));
1088 nB = (wxUint8)(nB1 + ((nB2 - nB1) * nGradient / 100));
1089
1090 //set the pixel
1091 m_pen.SetColour(wxColour(nR,nG,nB));
ab171e95 1092 DoDrawPoint(x + rect.GetLeft(), y + rect.GetTop());
2970ae54
RR
1093 }
1094 }
1095 //return old pen color
1096 m_pen.SetColour(oldPenColour);
1097}
1098
1099//-----------------------------------------------------------------------------
1100// wxDC
1101//-----------------------------------------------------------------------------
1102
1103IMPLEMENT_ABSTRACT_CLASS(wxDC, wxObject)
1104
ab171e95
RR
1105void wxDC::DrawLabel(const wxString& text,
1106 const wxBitmap& bitmap,
1107 const wxRect& rect,
1108 int alignment,
1109 int indexAccel,
1110 wxRect *rectBounding)
1111{
1112 // find the text position
1113 wxCoord widthText, heightText, heightLine;
1114 GetMultiLineTextExtent(text, &widthText, &heightText, &heightLine);
1115
1116 wxCoord width, height;
1117 if ( bitmap.Ok() )
1118 {
1119 width = widthText + bitmap.GetWidth();
1120 height = bitmap.GetHeight();
1121 }
1122 else // no bitmap
1123 {
1124 width = widthText;
1125 height = heightText;
1126 }
1127
1128 wxCoord x, y;
1129 if ( alignment & wxALIGN_RIGHT )
1130 {
1131 x = rect.GetRight() - width;
1132 }
1133 else if ( alignment & wxALIGN_CENTRE_HORIZONTAL )
1134 {
1135 x = (rect.GetLeft() + rect.GetRight() + 1 - width) / 2;
1136 }
1137 else // alignment & wxALIGN_LEFT
1138 {
1139 x = rect.GetLeft();
1140 }
1141
1142 if ( alignment & wxALIGN_BOTTOM )
1143 {
1144 y = rect.GetBottom() - height;
1145 }
1146 else if ( alignment & wxALIGN_CENTRE_VERTICAL )
1147 {
1148 y = (rect.GetTop() + rect.GetBottom() + 1 - height) / 2;
1149 }
1150 else // alignment & wxALIGN_TOP
1151 {
1152 y = rect.GetTop();
1153 }
1154
1155 // draw the bitmap first
1156 wxCoord x0 = x,
1157 y0 = y,
1158 width0 = width;
1159 if ( bitmap.Ok() )
1160 {
1161 DrawBitmap(bitmap, x, y, true /* use mask */);
1162
1163 wxCoord offset = bitmap.GetWidth() + 4;
1164 x += offset;
1165 width -= offset;
1166
1167 y += (height - heightText) / 2;
1168 }
1169
1170 // we will draw the underscore under the accel char later
1171 wxCoord startUnderscore = 0,
1172 endUnderscore = 0,
1173 yUnderscore = 0;
1174
1175 // split the string into lines and draw each of them separately
1176 wxString curLine;
1177 for ( wxString::const_iterator pc = text.begin(); ; ++pc )
1178 {
1179 if ( *pc == _T('\n') || pc == text.end() )
1180 {
1181 int xRealStart = x; // init it here to avoid compielr warnings
1182
1183 if ( !curLine.empty() )
1184 {
1185 // NB: can't test for !(alignment & wxALIGN_LEFT) because
1186 // wxALIGN_LEFT is 0
1187 if ( alignment & (wxALIGN_RIGHT | wxALIGN_CENTRE_HORIZONTAL) )
1188 {
1189 wxCoord widthLine;
1190 GetTextExtent(curLine, &widthLine, NULL);
1191
1192 if ( alignment & wxALIGN_RIGHT )
1193 {
1194 xRealStart += width - widthLine;
1195 }
1196 else // if ( alignment & wxALIGN_CENTRE_HORIZONTAL )
1197 {
1198 xRealStart += (width - widthLine) / 2;
1199 }
1200 }
1201 //else: left aligned, nothing to do
1202
1203 DrawText(curLine, xRealStart, y);
1204 }
1205
1206 y += heightLine;
1207
1208 // do we have underscore in this line? we can check yUnderscore
1209 // because it is set below to just y + heightLine if we do
1210 if ( y == yUnderscore )
1211 {
1212 // adjust the horz positions to account for the shift
1213 startUnderscore += xRealStart;
1214 endUnderscore += xRealStart;
1215 }
1216
1217 if ( pc == text.end() )
1218 break;
1219
1220 curLine.clear();
1221 }
1222 else // not end of line
1223 {
1224 if ( pc - text.begin() == indexAccel )
1225 {
1226 // remeber to draw underscore here
1227 GetTextExtent(curLine, &startUnderscore, NULL);
1228 curLine += *pc;
1229 GetTextExtent(curLine, &endUnderscore, NULL);
1230
1231 yUnderscore = y + heightLine;
1232 }
1233 else
1234 {
1235 curLine += *pc;
1236 }
1237 }
1238 }
1239
1240 // draw the underscore if found
1241 if ( startUnderscore != endUnderscore )
1242 {
1243 // it should be of the same colour as text
1244 SetPen(wxPen(GetTextForeground(), 0, wxSOLID));
1245
1246 yUnderscore--;
1247
1248 DrawLine(startUnderscore, yUnderscore, endUnderscore, yUnderscore);
1249 }
1250
1251 // return bounding rect if requested
1252 if ( rectBounding )
1253 {
1254 *rectBounding = wxRect(x, y - heightText, widthText, heightText);
1255 }
1256
1257 CalcBoundingBox(x0, y0);
1258 CalcBoundingBox(x0 + width0, y0 + height);
1259}
1260
2970ae54
RR
1261#if WXWIN_COMPATIBILITY_2_8
1262 // for compatibility with the old code when wxCoord was long everywhere
1263void wxDC::GetTextExtent(const wxString& string,
1264 long *x, long *y,
1265 long *descent,
1266 long *externalLeading,
1267 const wxFont *theFont) const
1268 {
1269 wxCoord x2, y2, descent2, externalLeading2;
1270 m_pimpl->DoGetTextExtent(string, &x2, &y2,
1271 &descent2, &externalLeading2,
1272 theFont);
1273 if ( x )
1274 *x = x2;
1275 if ( y )
1276 *y = y2;
1277 if ( descent )
1278 *descent = descent2;
1279 if ( externalLeading )
1280 *externalLeading = externalLeading2;
1281 }
1282
f0875501 1283void wxDC::GetLogicalOrigin(long *x, long *y) const
2970ae54
RR
1284 {
1285 wxCoord x2, y2;
1286 m_pimpl->DoGetLogicalOrigin(&x2, &y2);
1287 if ( x )
1288 *x = x2;
1289 if ( y )
1290 *y = y2;
1291 }
1292
f0875501 1293void wxDC::GetDeviceOrigin(long *x, long *y) const
2970ae54
RR
1294 {
1295 wxCoord x2, y2;
1296 m_pimpl->DoGetDeviceOrigin(&x2, &y2);
1297 if ( x )
1298 *x = x2;
1299 if ( y )
1300 *y = y2;
f0875501
VZ
1301 }
1302
1303void wxDC::GetClippingBox(long *x, long *y, long *w, long *h) const
2970ae54
RR
1304 {
1305 wxCoord xx,yy,ww,hh;
1306 m_pimpl->DoGetClippingBox(&xx, &yy, &ww, &hh);
1307 if (x) *x = xx;
1308 if (y) *y = yy;
1309 if (w) *w = ww;
1310 if (h) *h = hh;
f0875501
VZ
1311 }
1312
2970ae54 1313#endif // WXWIN_COMPATIBILITY_2_8