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