1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/dcbase.cpp
3 // Purpose: generic methods of the wxDC Class
4 // Author: Vadim Zeitlin
8 // Copyright: (c) wxWidgets team
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
28 #include "wx/dcclient.h"
29 #include "wx/dcmemory.h"
30 #include "wx/dcscreen.h"
31 #include "wx/dcprint.h"
32 #include "wx/prntbase.h"
33 #include "wx/scopeguard.h"
37 #include "wx/module.h"
41 #include "wx/msw/dcclient.h"
42 #include "wx/msw/dcmemory.h"
43 #include "wx/msw/dcscreen.h"
47 #include "wx/gtk/dcclient.h"
48 #include "wx/gtk/dcmemory.h"
49 #include "wx/gtk/dcscreen.h"
50 #elif defined(__WXGTK__)
51 #include "wx/gtk1/dcclient.h"
52 #include "wx/gtk1/dcmemory.h"
53 #include "wx/gtk1/dcscreen.h"
57 #include "wx/osx/dcclient.h"
58 #include "wx/osx/dcmemory.h"
59 #include "wx/osx/dcscreen.h"
63 #include "wx/os2/dcclient.h"
64 #include "wx/os2/dcmemory.h"
65 #include "wx/os2/dcscreen.h"
69 #include "wx/cocoa/dcclient.h"
70 #include "wx/cocoa/dcmemory.h"
71 #include "wx/cocoa/dcscreen.h"
75 #include "wx/motif/dcclient.h"
76 #include "wx/motif/dcmemory.h"
77 #include "wx/motif/dcscreen.h"
81 #include "wx/x11/dcclient.h"
82 #include "wx/x11/dcmemory.h"
83 #include "wx/x11/dcscreen.h"
87 #include "wx/dfb/dcclient.h"
88 #include "wx/dfb/dcmemory.h"
89 #include "wx/dfb/dcscreen.h"
93 #include "wx/palmos/dcclient.h"
94 #include "wx/palmos/dcmemory.h"
95 #include "wx/palmos/dcscreen.h"
98 //----------------------------------------------------------------------------
100 //----------------------------------------------------------------------------
102 wxDCFactory
*wxDCFactory::m_factory
= NULL
;
104 void wxDCFactory::Set(wxDCFactory
*factory
)
111 wxDCFactory
*wxDCFactory::Get()
114 m_factory
= new wxNativeDCFactory
;
119 class wxDCFactoryCleanupModule
: public wxModule
122 virtual bool OnInit() { return true; }
123 virtual void OnExit() { wxDCFactory::Set(NULL
); }
126 DECLARE_DYNAMIC_CLASS(wxDCFactoryCleanupModule
)
129 IMPLEMENT_DYNAMIC_CLASS(wxDCFactoryCleanupModule
, wxModule
)
131 //-----------------------------------------------------------------------------
133 //-----------------------------------------------------------------------------
135 wxDCImpl
* wxNativeDCFactory::CreateWindowDC( wxWindowDC
*owner
, wxWindow
*window
)
137 wxDCImpl
* const impl
= new wxWindowDCImpl( owner
, window
);
138 impl
->InheritAttributes(window
);
142 wxDCImpl
* wxNativeDCFactory::CreateClientDC( wxClientDC
*owner
, wxWindow
*window
)
144 wxDCImpl
* const impl
= new wxClientDCImpl( owner
, window
);
145 impl
->InheritAttributes(window
);
149 wxDCImpl
* wxNativeDCFactory::CreatePaintDC( wxPaintDC
*owner
, wxWindow
*window
)
151 wxDCImpl
* const impl
= new wxPaintDCImpl( owner
, window
);
152 impl
->InheritAttributes(window
);
156 wxDCImpl
* wxNativeDCFactory::CreateMemoryDC( wxMemoryDC
*owner
)
158 return new wxMemoryDCImpl( owner
);
161 wxDCImpl
* wxNativeDCFactory::CreateMemoryDC(wxMemoryDC
*owner
, wxBitmap
& bitmap
)
163 // the bitmap may be modified when it's selected into a memory DC so make
164 // sure changing this bitmap doesn't affect any other shallow copies of it
165 // (see wxMemoryDC::SelectObject())
167 // notice that we don't provide any ctor equivalent to SelectObjectAsSource
168 // method because this should be rarely needed and easy to work around by
169 // using the default ctor and calling SelectObjectAsSource itself
173 return new wxMemoryDCImpl(owner
, bitmap
);
176 wxDCImpl
* wxNativeDCFactory::CreateMemoryDC( wxMemoryDC
*owner
, wxDC
*dc
)
178 return new wxMemoryDCImpl( owner
, dc
);
181 wxDCImpl
* wxNativeDCFactory::CreateScreenDC( wxScreenDC
*owner
)
183 return new wxScreenDCImpl( owner
);
186 #if wxUSE_PRINTING_ARCHITECTURE
187 wxDCImpl
*wxNativeDCFactory::CreatePrinterDC( wxPrinterDC
*owner
, const wxPrintData
&data
)
189 wxPrintFactory
*factory
= wxPrintFactory::GetFactory();
190 return factory
->CreatePrinterDCImpl( owner
, data
);
194 //-----------------------------------------------------------------------------
196 //-----------------------------------------------------------------------------
198 IMPLEMENT_ABSTRACT_CLASS(wxWindowDC
, wxDC
)
200 wxWindowDC::wxWindowDC(wxWindow
*win
)
201 : wxDC(wxDCFactory::Get()->CreateWindowDC(this, win
))
205 //-----------------------------------------------------------------------------
207 //-----------------------------------------------------------------------------
209 IMPLEMENT_ABSTRACT_CLASS(wxClientDC
, wxWindowDC
)
211 wxClientDC::wxClientDC(wxWindow
*win
)
212 : wxWindowDC(wxDCFactory::Get()->CreateClientDC(this, win
))
216 //-----------------------------------------------------------------------------
218 //-----------------------------------------------------------------------------
220 IMPLEMENT_DYNAMIC_CLASS(wxMemoryDC
, wxDC
)
222 wxMemoryDC::wxMemoryDC()
223 : wxDC(wxDCFactory::Get()->CreateMemoryDC(this))
227 wxMemoryDC::wxMemoryDC(wxBitmap
& bitmap
)
228 : wxDC(wxDCFactory::Get()->CreateMemoryDC(this, bitmap
))
232 wxMemoryDC::wxMemoryDC(wxDC
*dc
)
233 : wxDC(wxDCFactory::Get()->CreateMemoryDC(this, dc
))
237 void wxMemoryDC::SelectObject(wxBitmap
& bmp
)
239 // make sure that the given wxBitmap is not sharing its data with other
240 // wxBitmap instances as its contents will be modified by any drawing
241 // operation done on this DC
245 GetImpl()->DoSelect(bmp
);
248 void wxMemoryDC::SelectObjectAsSource(const wxBitmap
& bmp
)
250 GetImpl()->DoSelect(bmp
);
253 const wxBitmap
& wxMemoryDC::GetSelectedBitmap() const
255 return GetImpl()->GetSelectedBitmap();
258 wxBitmap
& wxMemoryDC::GetSelectedBitmap()
260 return GetImpl()->GetSelectedBitmap();
264 //-----------------------------------------------------------------------------
266 //-----------------------------------------------------------------------------
268 IMPLEMENT_ABSTRACT_CLASS(wxPaintDC
, wxClientDC
)
270 wxPaintDC::wxPaintDC(wxWindow
*win
)
271 : wxClientDC(wxDCFactory::Get()->CreatePaintDC(this, win
))
275 //-----------------------------------------------------------------------------
277 //-----------------------------------------------------------------------------
279 IMPLEMENT_DYNAMIC_CLASS(wxScreenDC
, wxWindowDC
)
281 wxScreenDC::wxScreenDC()
282 : wxDC(wxDCFactory::Get()->CreateScreenDC(this))
286 //-----------------------------------------------------------------------------
288 //-----------------------------------------------------------------------------
290 #if wxUSE_PRINTING_ARCHITECTURE
292 IMPLEMENT_DYNAMIC_CLASS(wxPrinterDC
, wxDC
)
294 wxPrinterDC::wxPrinterDC()
295 : wxDC(wxDCFactory::Get()->CreatePrinterDC(this, wxPrintData()))
299 wxPrinterDC::wxPrinterDC(const wxPrintData
& data
)
300 : wxDC(wxDCFactory::Get()->CreatePrinterDC(this, data
))
304 wxRect
wxPrinterDC::GetPaperRect() const
306 return GetImpl()->GetPaperRect();
309 int wxPrinterDC::GetResolution() const
311 return GetImpl()->GetResolution();
314 #endif // wxUSE_PRINTING_ARCHITECTURE
316 //-----------------------------------------------------------------------------
318 //-----------------------------------------------------------------------------
320 IMPLEMENT_ABSTRACT_CLASS(wxDCImpl
, wxObject
)
322 wxDCImpl::wxDCImpl( wxDC
*owner
)
324 , m_colour(wxColourDisplay())
328 , m_isBBoxValid(false)
329 , m_logicalOriginX(0), m_logicalOriginY(0)
330 , m_deviceOriginX(0), m_deviceOriginY(0)
331 , m_deviceLocalOriginX(0), m_deviceLocalOriginY(0)
332 , m_logicalScaleX(1.0), m_logicalScaleY(1.0)
333 , m_userScaleX(1.0), m_userScaleY(1.0)
334 , m_scaleX(1.0), m_scaleY(1.0)
335 , m_signX(1), m_signY(1)
336 , m_minX(0), m_minY(0), m_maxX(0), m_maxY(0)
337 , m_clipX1(0), m_clipY1(0), m_clipX2(0), m_clipY2(0)
338 , m_logicalFunction(wxCOPY
)
339 , m_backgroundMode(wxBRUSHSTYLE_TRANSPARENT
)
340 , m_mappingMode(wxMM_TEXT
)
343 , m_backgroundBrush()
344 , m_textForegroundColour(*wxBLACK
)
345 , m_textBackgroundColour(*wxWHITE
)
349 , m_hasCustomPalette(false)
350 #endif // wxUSE_PALETTE
354 m_mm_to_pix_x
= (double)wxGetDisplaySize().GetWidth() /
355 (double)wxGetDisplaySizeMM().GetWidth();
356 m_mm_to_pix_y
= (double)wxGetDisplaySize().GetHeight() /
357 (double)wxGetDisplaySizeMM().GetHeight();
363 wxDCImpl::~wxDCImpl()
367 // ----------------------------------------------------------------------------
368 // coordinate conversions and transforms
369 // ----------------------------------------------------------------------------
371 wxCoord
wxDCImpl::DeviceToLogicalX(wxCoord x
) const
373 return wxRound( (double)((x
- m_deviceOriginX
- m_deviceLocalOriginX
) * m_signX
) / m_scaleX
) + m_logicalOriginX
;
376 wxCoord
wxDCImpl::DeviceToLogicalY(wxCoord y
) const
378 return wxRound( (double)((y
- m_deviceOriginY
- m_deviceLocalOriginY
) * m_signY
) / m_scaleY
) + m_logicalOriginY
;
381 wxCoord
wxDCImpl::DeviceToLogicalXRel(wxCoord x
) const
383 return wxRound((double)(x
) / m_scaleX
);
386 wxCoord
wxDCImpl::DeviceToLogicalYRel(wxCoord y
) const
388 return wxRound((double)(y
) / m_scaleY
);
391 wxCoord
wxDCImpl::LogicalToDeviceX(wxCoord x
) const
393 return wxRound( (double)((x
- m_logicalOriginX
) * m_signX
) * m_scaleX
) + m_deviceOriginX
+ m_deviceLocalOriginX
;
396 wxCoord
wxDCImpl::LogicalToDeviceY(wxCoord y
) const
398 return wxRound( (double)((y
- m_logicalOriginY
) * m_signY
) * m_scaleY
) + m_deviceOriginY
+ m_deviceLocalOriginY
;
401 wxCoord
wxDCImpl::LogicalToDeviceXRel(wxCoord x
) const
403 return wxRound((double)(x
) * m_scaleX
);
406 wxCoord
wxDCImpl::LogicalToDeviceYRel(wxCoord y
) const
408 return wxRound((double)(y
) * m_scaleY
);
411 void wxDCImpl::ComputeScaleAndOrigin()
413 m_scaleX
= m_logicalScaleX
* m_userScaleX
;
414 m_scaleY
= m_logicalScaleY
* m_userScaleY
;
417 void wxDCImpl::SetMapMode( wxMappingMode mode
)
422 SetLogicalScale( twips2mm
*m_mm_to_pix_x
, twips2mm
*m_mm_to_pix_y
);
425 SetLogicalScale( pt2mm
*m_mm_to_pix_x
, pt2mm
*m_mm_to_pix_y
);
428 SetLogicalScale( m_mm_to_pix_x
, m_mm_to_pix_y
);
431 SetLogicalScale( m_mm_to_pix_x
/10.0, m_mm_to_pix_y
/10.0 );
435 SetLogicalScale( 1.0, 1.0 );
438 m_mappingMode
= mode
;
441 void wxDCImpl::SetUserScale( double x
, double y
)
443 // allow negative ? -> no
446 ComputeScaleAndOrigin();
449 void wxDCImpl::SetLogicalScale( double x
, double y
)
454 ComputeScaleAndOrigin();
457 void wxDCImpl::SetLogicalOrigin( wxCoord x
, wxCoord y
)
459 m_logicalOriginX
= x
* m_signX
;
460 m_logicalOriginY
= y
* m_signY
;
461 ComputeScaleAndOrigin();
464 void wxDCImpl::SetDeviceOrigin( wxCoord x
, wxCoord y
)
468 ComputeScaleAndOrigin();
471 void wxDCImpl::SetDeviceLocalOrigin( wxCoord x
, wxCoord y
)
473 m_deviceLocalOriginX
= x
;
474 m_deviceLocalOriginY
= y
;
475 ComputeScaleAndOrigin();
478 void wxDCImpl::SetAxisOrientation( bool xLeftRight
, bool yBottomUp
)
480 // only wxPostScripDC has m_signX = -1, we override SetAxisOrientation there
481 // wxWidgets 2.9: no longer override it
482 m_signX
= (xLeftRight
? 1 : -1);
483 m_signY
= (yBottomUp
? -1 : 1);
484 ComputeScaleAndOrigin();
488 // Each element of the widths array will be the width of the string up to and
489 // including the corresponding character in text. This is the generic
490 // implementation, the port-specific classes should do this with native APIs
491 // if available and if faster. Note: pango_layout_index_to_pos is much slower
492 // than calling GetTextExtent!!
499 FontWidthCache() : m_scaleX(1), m_widths(NULL
) { }
500 ~FontWidthCache() { delete []m_widths
; }
505 m_widths
= new int[FWC_SIZE
];
507 memset(m_widths
, 0, sizeof(int)*FWC_SIZE
);
515 static FontWidthCache s_fontWidthCache
;
517 bool wxDCImpl::DoGetPartialTextExtents(const wxString
& text
, wxArrayInt
& widths
) const
521 const size_t len
= text
.length();
525 // reset the cache if font or horizontal scale have changed
526 if ( !s_fontWidthCache
.m_widths
||
527 !wxIsSameDouble(s_fontWidthCache
.m_scaleX
, m_scaleX
) ||
528 (s_fontWidthCache
.m_font
!= GetFont()) )
530 s_fontWidthCache
.Reset();
531 s_fontWidthCache
.m_font
= GetFont();
532 s_fontWidthCache
.m_scaleX
= m_scaleX
;
535 // Calculate the position of each character based on the widths of
536 // the previous characters
538 for ( size_t i
= 0; i
< len
; i
++ )
540 const wxChar c
= text
[i
];
541 unsigned int c_int
= (unsigned int)c
;
543 if ((c_int
< FWC_SIZE
) && (s_fontWidthCache
.m_widths
[c_int
] != 0))
545 w
= s_fontWidthCache
.m_widths
[c_int
];
549 DoGetTextExtent(c
, &w
, &h
);
550 if (c_int
< FWC_SIZE
)
551 s_fontWidthCache
.m_widths
[c_int
] = w
;
555 widths
[i
] = totalWidth
;
561 void wxDCImpl::GetMultiLineTextExtent(const wxString
& text
,
565 const wxFont
*font
) const
567 wxCoord widthTextMax
= 0, widthLine
,
568 heightTextTotal
= 0, heightLineDefault
= 0, heightLine
= 0;
571 for ( wxString::const_iterator pc
= text
.begin(); ; ++pc
)
573 if ( pc
== text
.end() || *pc
== wxT('\n') )
575 if ( curLine
.empty() )
577 // we can't use GetTextExtent - it will return 0 for both width
578 // and height and an empty line should count in height
581 // assume that this line has the same height as the previous
583 if ( !heightLineDefault
)
584 heightLineDefault
= heightLine
;
586 if ( !heightLineDefault
)
588 // but we don't know it yet - choose something reasonable
589 DoGetTextExtent(wxT("W"), NULL
, &heightLineDefault
,
593 heightTextTotal
+= heightLineDefault
;
597 DoGetTextExtent(curLine
, &widthLine
, &heightLine
,
599 if ( widthLine
> widthTextMax
)
600 widthTextMax
= widthLine
;
601 heightTextTotal
+= heightLine
;
604 if ( pc
== text
.end() )
622 *y
= heightTextTotal
;
627 void wxDCImpl::DoDrawCheckMark(wxCoord x1
, wxCoord y1
,
628 wxCoord width
, wxCoord height
)
630 wxCHECK_RET( IsOk(), wxT("invalid window dc") );
632 wxCoord x2
= x1
+ width
,
635 // the pen width is calibrated to give 3 for width == height == 10
636 wxDCPenChanger
pen( *m_owner
, wxPen(GetTextForeground(), (width
+ height
+ 1)/7));
638 // we're drawing a scaled version of wx/generic/tick.xpm here
639 wxCoord x3
= x1
+ (4*width
) / 10, // x of the tick bottom
640 y3
= y1
+ height
/ 2; // y of the left tick branch
641 DoDrawLine(x1
, y3
, x3
, y2
);
642 DoDrawLine(x3
, y2
, x2
, y1
);
644 CalcBoundingBox(x1
, y1
);
645 CalcBoundingBox(x2
, y2
);
649 wxDCImpl::DoStretchBlit(wxCoord xdest
, wxCoord ydest
,
650 wxCoord dstWidth
, wxCoord dstHeight
,
652 wxCoord xsrc
, wxCoord ysrc
,
653 wxCoord srcWidth
, wxCoord srcHeight
,
654 wxRasterOperationMode rop
,
659 wxCHECK_MSG( srcWidth
&& srcHeight
&& dstWidth
&& dstHeight
, false,
660 wxT("invalid blit size") );
662 // emulate the stretching by modifying the DC scale
663 double xscale
= (double)srcWidth
/dstWidth
,
664 yscale
= (double)srcHeight
/dstHeight
;
666 double xscaleOld
, yscaleOld
;
667 GetUserScale(&xscaleOld
, &yscaleOld
);
668 SetUserScale(xscaleOld
/xscale
, yscaleOld
/yscale
);
670 bool rc
= DoBlit(wxCoord(xdest
*xscale
), wxCoord(ydest
*yscale
),
671 wxCoord(dstWidth
*xscale
), wxCoord(dstHeight
*yscale
),
673 xsrc
, ysrc
, rop
, useMask
, xsrcMask
, ysrcMask
);
675 SetUserScale(xscaleOld
, yscaleOld
);
680 void wxDCImpl::DrawLines(const wxPointList
*list
, wxCoord xoffset
, wxCoord yoffset
)
682 int n
= list
->GetCount();
683 wxPoint
*points
= new wxPoint
[n
];
686 for ( wxPointList::compatibility_iterator node
= list
->GetFirst(); node
; node
= node
->GetNext(), i
++ )
688 wxPoint
*point
= node
->GetData();
689 points
[i
].x
= point
->x
;
690 points
[i
].y
= point
->y
;
693 DoDrawLines(n
, points
, xoffset
, yoffset
);
698 void wxDCImpl::DrawPolygon(const wxPointList
*list
,
699 wxCoord xoffset
, wxCoord yoffset
,
700 wxPolygonFillMode fillStyle
)
702 int n
= list
->GetCount();
703 wxPoint
*points
= new wxPoint
[n
];
706 for ( wxPointList::compatibility_iterator node
= list
->GetFirst(); node
; node
= node
->GetNext(), i
++ )
708 wxPoint
*point
= node
->GetData();
709 points
[i
].x
= point
->x
;
710 points
[i
].y
= point
->y
;
713 DoDrawPolygon(n
, points
, xoffset
, yoffset
, fillStyle
);
719 wxDCImpl::DoDrawPolyPolygon(int n
,
722 wxCoord xoffset
, wxCoord yoffset
,
723 wxPolygonFillMode fillStyle
)
727 DoDrawPolygon(count
[0], points
, xoffset
, yoffset
, fillStyle
);
735 for (i
= j
= lastOfs
= 0; i
< n
; i
++)
740 pts
= new wxPoint
[j
+n
-1];
741 for (i
= 0; i
< j
; i
++)
743 for (i
= 2; i
<= n
; i
++)
745 lastOfs
-= count
[n
-i
];
746 pts
[j
++] = pts
[lastOfs
];
750 SetPen(wxPen(*wxBLACK
, 0, wxPENSTYLE_TRANSPARENT
));
751 DoDrawPolygon(j
, pts
, xoffset
, yoffset
, fillStyle
);
753 for (i
= j
= 0; i
< n
; i
++)
755 DoDrawLines(count
[i
], pts
+j
, xoffset
, yoffset
);
763 void wxDCImpl::DrawSpline(wxCoord x1
, wxCoord y1
,
764 wxCoord x2
, wxCoord y2
,
765 wxCoord x3
, wxCoord y3
)
767 wxPoint points
[] = { wxPoint(x1
, y1
), wxPoint(x2
, y2
), wxPoint(x3
, y3
) };
768 DrawSpline(WXSIZEOF(points
), points
);
771 void wxDCImpl::DrawSpline(int n
, wxPoint points
[])
774 for ( int i
= 0; i
< n
; i
++ )
775 list
.Append(&points
[i
]);
780 // ----------------------------------- spline code ----------------------------------------
782 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
,
783 double a3
, double b3
, double a4
, double b4
);
784 void wx_clear_stack();
785 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
, double *x3
,
786 double *y3
, double *x4
, double *y4
);
787 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
,
788 double x4
, double y4
);
789 static bool wx_spline_add_point(double x
, double y
);
790 static void wx_spline_draw_point_array(wxDC
*dc
);
792 static wxPointList wx_spline_point_list
;
794 #define half(z1, z2) ((z1+z2)/2.0)
797 /* iterative version */
799 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
, double a3
, double b3
, double a4
,
802 register double xmid
, ymid
;
803 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
806 wx_spline_push(a1
, b1
, a2
, b2
, a3
, b3
, a4
, b4
);
808 while (wx_spline_pop(&x1
, &y1
, &x2
, &y2
, &x3
, &y3
, &x4
, &y4
)) {
809 xmid
= (double)half(x2
, x3
);
810 ymid
= (double)half(y2
, y3
);
811 if (fabs(x1
- xmid
) < THRESHOLD
&& fabs(y1
- ymid
) < THRESHOLD
&&
812 fabs(xmid
- x4
) < THRESHOLD
&& fabs(ymid
- y4
) < THRESHOLD
) {
813 wx_spline_add_point( x1
, y1
);
814 wx_spline_add_point( xmid
, ymid
);
816 wx_spline_push(xmid
, ymid
, (double)half(xmid
, x3
), (double)half(ymid
, y3
),
817 (double)half(x3
, x4
), (double)half(y3
, y4
), x4
, y4
);
818 wx_spline_push(x1
, y1
, (double)half(x1
, x2
), (double)half(y1
, y2
),
819 (double)half(x2
, xmid
), (double)half(y2
, ymid
), xmid
, ymid
);
824 /* utilities used by spline drawing routines */
826 typedef struct wx_spline_stack_struct
{
827 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
830 #define SPLINE_STACK_DEPTH 20
831 static Stack wx_spline_stack
[SPLINE_STACK_DEPTH
];
832 static Stack
*wx_stack_top
;
833 static int wx_stack_count
;
835 void wx_clear_stack()
837 wx_stack_top
= wx_spline_stack
;
841 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
, double x4
, double y4
)
843 wx_stack_top
->x1
= x1
;
844 wx_stack_top
->y1
= y1
;
845 wx_stack_top
->x2
= x2
;
846 wx_stack_top
->y2
= y2
;
847 wx_stack_top
->x3
= x3
;
848 wx_stack_top
->y3
= y3
;
849 wx_stack_top
->x4
= x4
;
850 wx_stack_top
->y4
= y4
;
855 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
,
856 double *x3
, double *y3
, double *x4
, double *y4
)
858 if (wx_stack_count
== 0)
862 *x1
= wx_stack_top
->x1
;
863 *y1
= wx_stack_top
->y1
;
864 *x2
= wx_stack_top
->x2
;
865 *y2
= wx_stack_top
->y2
;
866 *x3
= wx_stack_top
->x3
;
867 *y3
= wx_stack_top
->y3
;
868 *x4
= wx_stack_top
->x4
;
869 *y4
= wx_stack_top
->y4
;
873 static bool wx_spline_add_point(double x
, double y
)
875 wxPoint
*point
= new wxPoint( wxRound(x
), wxRound(y
) );
876 wx_spline_point_list
.Append(point
);
880 static void wx_spline_draw_point_array(wxDC
*dc
)
882 dc
->DrawLines(&wx_spline_point_list
, 0, 0 );
883 wxPointList::compatibility_iterator node
= wx_spline_point_list
.GetFirst();
886 wxPoint
*point
= node
->GetData();
888 wx_spline_point_list
.Erase(node
);
889 node
= wx_spline_point_list
.GetFirst();
893 void wxDCImpl::DoDrawSpline( const wxPointList
*points
)
895 wxCHECK_RET( IsOk(), wxT("invalid window dc") );
898 double cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
;
899 double x1
, y1
, x2
, y2
;
901 wxPointList::compatibility_iterator node
= points
->GetFirst();
906 p
= (wxPoint
*)node
->GetData();
911 node
= node
->GetNext();
916 cx1
= (double)((x1
+ x2
) / 2);
917 cy1
= (double)((y1
+ y2
) / 2);
918 cx2
= (double)((cx1
+ x2
) / 2);
919 cy2
= (double)((cy1
+ y2
) / 2);
921 wx_spline_add_point(x1
, y1
);
923 while ((node
= node
->GetNext())
934 cx4
= (double)(x1
+ x2
) / 2;
935 cy4
= (double)(y1
+ y2
) / 2;
936 cx3
= (double)(x1
+ cx4
) / 2;
937 cy3
= (double)(y1
+ cy4
) / 2;
939 wx_quadratic_spline(cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
);
943 cx2
= (double)(cx1
+ x2
) / 2;
944 cy2
= (double)(cy1
+ y2
) / 2;
947 wx_spline_add_point( cx1
, cy1
);
948 wx_spline_add_point( x2
, y2
);
950 wx_spline_draw_point_array( m_owner
);
953 #endif // wxUSE_SPLINES
957 void wxDCImpl::DoGradientFillLinear(const wxRect
& rect
,
958 const wxColour
& initialColour
,
959 const wxColour
& destColour
,
960 wxDirection nDirection
)
963 wxPen oldPen
= m_pen
;
964 wxBrush oldBrush
= m_brush
;
966 wxUint8 nR1
= initialColour
.Red();
967 wxUint8 nG1
= initialColour
.Green();
968 wxUint8 nB1
= initialColour
.Blue();
969 wxUint8 nR2
= destColour
.Red();
970 wxUint8 nG2
= destColour
.Green();
971 wxUint8 nB2
= destColour
.Blue();
974 if ( nDirection
== wxEAST
|| nDirection
== wxWEST
)
976 wxInt32 x
= rect
.GetWidth();
977 wxInt32 w
= x
; // width of area to shade
978 wxInt32 xDelta
= w
/256; // height of one shade bend
986 nR
= nR1
- (nR1
-nR2
)*(w
-x
)/w
;
988 nR
= nR1
+ (nR2
-nR1
)*(w
-x
)/w
;
991 nG
= nG1
- (nG1
-nG2
)*(w
-x
)/w
;
993 nG
= nG1
+ (nG2
-nG1
)*(w
-x
)/w
;
996 nB
= nB1
- (nB1
-nB2
)*(w
-x
)/w
;
998 nB
= nB1
+ (nB2
-nB1
)*(w
-x
)/w
;
1000 wxColour
colour(nR
,nG
,nB
);
1001 SetPen(wxPen(colour
, 1, wxPENSTYLE_SOLID
));
1002 SetBrush(wxBrush(colour
));
1003 if(nDirection
== wxEAST
)
1004 DoDrawRectangle(rect
.GetRight()-x
-xDelta
+1, rect
.GetTop(),
1005 xDelta
, rect
.GetHeight());
1006 else //nDirection == wxWEST
1007 DoDrawRectangle(rect
.GetLeft()+x
, rect
.GetTop(),
1008 xDelta
, rect
.GetHeight());
1011 else // nDirection == wxNORTH || nDirection == wxSOUTH
1013 wxInt32 y
= rect
.GetHeight();
1014 wxInt32 w
= y
; // height of area to shade
1015 wxInt32 yDelta
= w
/255; // height of one shade bend
1023 nR
= nR1
- (nR1
-nR2
)*(w
-y
)/w
;
1025 nR
= nR1
+ (nR2
-nR1
)*(w
-y
)/w
;
1028 nG
= nG1
- (nG1
-nG2
)*(w
-y
)/w
;
1030 nG
= nG1
+ (nG2
-nG1
)*(w
-y
)/w
;
1033 nB
= nB1
- (nB1
-nB2
)*(w
-y
)/w
;
1035 nB
= nB1
+ (nB2
-nB1
)*(w
-y
)/w
;
1037 wxColour
colour(nR
,nG
,nB
);
1038 SetPen(wxPen(colour
, 1, wxPENSTYLE_SOLID
));
1039 SetBrush(wxBrush(colour
));
1040 if(nDirection
== wxNORTH
)
1041 DoDrawRectangle(rect
.GetLeft(), rect
.GetTop()+y
,
1042 rect
.GetWidth(), yDelta
);
1043 else //nDirection == wxSOUTH
1044 DoDrawRectangle(rect
.GetLeft(), rect
.GetBottom()-y
-yDelta
+1,
1045 rect
.GetWidth(), yDelta
);
1053 void wxDCImpl::DoGradientFillConcentric(const wxRect
& rect
,
1054 const wxColour
& initialColour
,
1055 const wxColour
& destColour
,
1056 const wxPoint
& circleCenter
)
1058 // save the old pen and ensure it is restored on exit
1059 const wxPen penOrig
= m_pen
;
1060 wxON_BLOCK_EXIT_SET(m_pen
, penOrig
);
1062 wxUint8 nR1
= destColour
.Red();
1063 wxUint8 nG1
= destColour
.Green();
1064 wxUint8 nB1
= destColour
.Blue();
1065 wxUint8 nR2
= initialColour
.Red();
1066 wxUint8 nG2
= initialColour
.Green();
1067 wxUint8 nB2
= initialColour
.Blue();
1072 wxInt32 cx
= rect
.GetWidth() / 2;
1073 wxInt32 cy
= rect
.GetHeight() / 2;
1081 wxInt32 nCircleOffX
= circleCenter
.x
- (rect
.GetWidth() / 2);
1082 wxInt32 nCircleOffY
= circleCenter
.y
- (rect
.GetHeight() / 2);
1084 for ( wxInt32 x
= 0; x
< rect
.GetWidth(); x
++ )
1086 for ( wxInt32 y
= 0; y
< rect
.GetHeight(); y
++ )
1088 //get color difference
1089 wxInt32 nGradient
= ((nRadius
-
1091 pow((double)(x
- cx
- nCircleOffX
), 2) +
1092 pow((double)(y
- cy
- nCircleOffY
), 2)
1093 )) * 100) / nRadius
;
1095 //normalize Gradient
1100 nR
= (wxUint8
)(nR1
+ ((nR2
- nR1
) * nGradient
/ 100));
1101 nG
= (wxUint8
)(nG1
+ ((nG2
- nG1
) * nGradient
/ 100));
1102 nB
= (wxUint8
)(nB1
+ ((nB2
- nB1
) * nGradient
/ 100));
1105 m_pen
= wxColour(nR
,nG
,nB
);
1106 DoDrawPoint(x
+ rect
.GetLeft(), y
+ rect
.GetTop());
1111 void wxDCImpl::InheritAttributes(wxWindow
*win
)
1113 wxCHECK_RET( win
, "window can't be NULL" );
1115 SetFont(win
->GetFont());
1116 SetTextForeground(win
->GetForegroundColour());
1117 SetTextBackground(win
->GetBackgroundColour());
1118 SetBackground(win
->GetBackgroundColour());
1119 SetLayoutDirection(win
->GetLayoutDirection());
1122 //-----------------------------------------------------------------------------
1124 //-----------------------------------------------------------------------------
1126 IMPLEMENT_ABSTRACT_CLASS(wxDC
, wxObject
)
1128 void wxDC::CopyAttributes(const wxDC
& dc
)
1130 SetFont(dc
.GetFont());
1131 SetTextForeground(dc
.GetTextForeground());
1132 SetTextBackground(dc
.GetTextBackground());
1133 SetBackground(dc
.GetBackground());
1134 SetLayoutDirection(dc
.GetLayoutDirection());
1137 void wxDC::DrawLabel(const wxString
& text
,
1138 const wxBitmap
& bitmap
,
1142 wxRect
*rectBounding
)
1144 // find the text position
1145 wxCoord widthText
, heightText
, heightLine
;
1146 GetMultiLineTextExtent(text
, &widthText
, &heightText
, &heightLine
);
1148 wxCoord width
, height
;
1151 width
= widthText
+ bitmap
.GetWidth();
1152 height
= bitmap
.GetHeight();
1157 height
= heightText
;
1161 if ( alignment
& wxALIGN_RIGHT
)
1163 x
= rect
.GetRight() - width
;
1165 else if ( alignment
& wxALIGN_CENTRE_HORIZONTAL
)
1167 x
= (rect
.GetLeft() + rect
.GetRight() + 1 - width
) / 2;
1169 else // alignment & wxALIGN_LEFT
1174 if ( alignment
& wxALIGN_BOTTOM
)
1176 y
= rect
.GetBottom() - height
;
1178 else if ( alignment
& wxALIGN_CENTRE_VERTICAL
)
1180 y
= (rect
.GetTop() + rect
.GetBottom() + 1 - height
) / 2;
1182 else // alignment & wxALIGN_TOP
1187 // draw the bitmap first
1193 DrawBitmap(bitmap
, x
, y
, true /* use mask */);
1195 wxCoord offset
= bitmap
.GetWidth() + 4;
1199 y
+= (height
- heightText
) / 2;
1202 // we will draw the underscore under the accel char later
1203 wxCoord startUnderscore
= 0,
1207 // split the string into lines and draw each of them separately
1209 // NB: while wxDC::DrawText() on some platforms supports drawing multi-line
1210 // strings natively, this is not the case for all of them, notably not
1211 // wxMSW which uses this function for multi-line texts, so we may only
1212 // call DrawText() for single-line strings from here to avoid infinite
1215 for ( wxString::const_iterator pc
= text
.begin(); ; ++pc
)
1217 if ( pc
== text
.end() || *pc
== '\n' )
1219 int xRealStart
= x
; // init it here to avoid compielr warnings
1221 if ( !curLine
.empty() )
1223 // NB: can't test for !(alignment & wxALIGN_LEFT) because
1224 // wxALIGN_LEFT is 0
1225 if ( alignment
& (wxALIGN_RIGHT
| wxALIGN_CENTRE_HORIZONTAL
) )
1228 GetTextExtent(curLine
, &widthLine
, NULL
);
1230 if ( alignment
& wxALIGN_RIGHT
)
1232 xRealStart
+= width
- widthLine
;
1234 else // if ( alignment & wxALIGN_CENTRE_HORIZONTAL )
1236 xRealStart
+= (width
- widthLine
) / 2;
1239 //else: left aligned, nothing to do
1241 DrawText(curLine
, xRealStart
, y
);
1246 // do we have underscore in this line? we can check yUnderscore
1247 // because it is set below to just y + heightLine if we do
1248 if ( y
== yUnderscore
)
1250 // adjust the horz positions to account for the shift
1251 startUnderscore
+= xRealStart
;
1252 endUnderscore
+= xRealStart
;
1255 if ( pc
== text
.end() )
1260 else // not end of line
1262 if ( pc
- text
.begin() == indexAccel
)
1264 // remeber to draw underscore here
1265 GetTextExtent(curLine
, &startUnderscore
, NULL
);
1267 GetTextExtent(curLine
, &endUnderscore
, NULL
);
1269 yUnderscore
= y
+ heightLine
;
1278 // draw the underscore if found
1279 if ( startUnderscore
!= endUnderscore
)
1281 // it should be of the same colour as text
1282 SetPen(wxPen(GetTextForeground(), 0, wxPENSTYLE_SOLID
));
1286 DrawLine(startUnderscore
, yUnderscore
, endUnderscore
, yUnderscore
);
1289 // return bounding rect if requested
1292 *rectBounding
= wxRect(x
, y
- heightText
, widthText
, heightText
);
1295 CalcBoundingBox(x0
, y0
);
1296 CalcBoundingBox(x0
+ width0
, y0
+ height
);
1299 #if WXWIN_COMPATIBILITY_2_8
1300 // for compatibility with the old code when wxCoord was long everywhere
1301 void wxDC::GetTextExtent(const wxString
& string
,
1304 long *externalLeading
,
1305 const wxFont
*theFont
) const
1307 wxCoord x2
, y2
, descent2
, externalLeading2
;
1308 m_pimpl
->DoGetTextExtent(string
, &x2
, &y2
,
1309 &descent2
, &externalLeading2
,
1316 *descent
= descent2
;
1317 if ( externalLeading
)
1318 *externalLeading
= externalLeading2
;
1321 void wxDC::GetLogicalOrigin(long *x
, long *y
) const
1324 m_pimpl
->DoGetLogicalOrigin(&x2
, &y2
);
1331 void wxDC::GetDeviceOrigin(long *x
, long *y
) const
1334 m_pimpl
->DoGetDeviceOrigin(&x2
, &y2
);
1341 void wxDC::GetClippingBox(long *x
, long *y
, long *w
, long *h
) const
1343 wxCoord xx
,yy
,ww
,hh
;
1344 m_pimpl
->DoGetClippingBox(&xx
, &yy
, &ww
, &hh
);
1351 void wxDC::DrawObject(wxDrawObject
* drawobject
)
1353 drawobject
->Draw(*this);
1354 CalcBoundingBox(drawobject
->MinX(),drawobject
->MinY());
1355 CalcBoundingBox(drawobject
->MaxX(),drawobject
->MaxY());
1358 #endif // WXWIN_COMPATIBILITY_2_8
1361 Notes for wxWidgets DrawEllipticArcRot(...)
1363 wxDCBase::DrawEllipticArcRot(...) draws a rotated elliptic arc or an ellipse.
1364 It uses wxDCBase::CalculateEllipticPoints(...) and wxDCBase::Rotate(...),
1367 All methods are generic, so they can be implemented in wxDCBase.
1368 DoDrawEllipticArcRot(...) is virtual, so it can be called from deeper
1369 methods like (WinCE) wxDC::DoDrawArc(...).
1371 CalculateEllipticPoints(...) fills a given list of wxPoints with some points
1372 of an elliptic arc. The algorithm is pixel-based: In every row (in flat
1373 parts) or every column (in steep parts) only one pixel is calculated.
1374 Trigonometric calculation (sin, cos, tan, atan) is only done if the
1375 starting angle is not equal to the ending angle. The calculation of the
1376 pixels is done using simple arithmetic only and should perform not too
1377 bad even on devices without floating point processor. I didn't test this yet.
1379 Rotate(...) rotates a list of point pixel-based, you will see rounding errors.
1380 For instance: an ellipse rotated 180 degrees is drawn
1381 slightly different from the original.
1383 The points are then moved to an array and used to draw a polyline and/or polygon
1384 (with center added, the pie).
1385 The result looks quite similar to the native ellipse, only e few pixels differ.
1387 The performance on a desktop system (Athlon 1800, WinXP) is about 7 times
1388 slower as DrawEllipse(...), which calls the native API.
1389 An rotated ellipse outside the clipping region takes nearly the same time,
1390 while an native ellipse outside takes nearly no time to draw.
1392 If you draw an arc with this new method, you will see the starting and ending angles
1393 are calculated properly.
1394 If you use DrawEllipticArc(...), you will see they are only correct for circles
1395 and not properly calculated for ellipses.
1398 p.lenhard@t-online.de
1402 void wxDCImpl::DoDrawEllipticArcRot( wxCoord x
, wxCoord y
,
1403 wxCoord w
, wxCoord h
,
1404 double sa
, double ea
, double angle
)
1408 CalculateEllipticPoints( &list
, x
, y
, w
, h
, sa
, ea
);
1409 Rotate( &list
, angle
, wxPoint( x
+w
/2, y
+h
/2 ) );
1411 // Add center (for polygon/pie)
1412 list
.Append( new wxPoint( x
+w
/2, y
+h
/2 ) );
1414 // copy list into array and delete list elements
1415 int n
= list
.GetCount();
1416 wxPoint
*points
= new wxPoint
[n
];
1418 wxPointList::compatibility_iterator node
;
1419 for ( node
= list
.GetFirst(); node
; node
= node
->GetNext(), i
++ )
1421 wxPoint
*point
= node
->GetData();
1422 points
[i
].x
= point
->x
;
1423 points
[i
].y
= point
->y
;
1427 // first draw the pie without pen, if necessary
1428 if( GetBrush() != *wxTRANSPARENT_BRUSH
)
1430 wxPen
tempPen( GetPen() );
1431 SetPen( *wxTRANSPARENT_PEN
);
1432 DoDrawPolygon( n
, points
, 0, 0 );
1436 // then draw the arc without brush, if necessary
1437 if( GetPen() != *wxTRANSPARENT_PEN
)
1440 DoDrawLines( n
-1, points
, 0, 0 );
1445 } // DrawEllipticArcRot
1447 void wxDCImpl::Rotate( wxPointList
* points
, double angle
, wxPoint center
)
1452 double dSinA
= -sin(angle
*2.0*pi
/360.0);
1453 double dCosA
= cos(angle
*2.0*pi
/360.0);
1454 wxPointList::compatibility_iterator node
;
1455 for ( node
= points
->GetFirst(); node
; node
= node
->GetNext() )
1457 wxPoint
* point
= node
->GetData();
1459 // transform coordinates, if necessary
1460 if( center
.x
) point
->x
-= center
.x
;
1461 if( center
.y
) point
->y
-= center
.y
;
1463 // calculate rotation, rounding simply by implicit cast to integer
1464 int xTemp
= point
->x
* dCosA
- point
->y
* dSinA
;
1465 point
->y
= point
->x
* dSinA
+ point
->y
* dCosA
;
1468 // back transform coordinates, if necessary
1469 if( center
.x
) point
->x
+= center
.x
;
1470 if( center
.y
) point
->y
+= center
.y
;
1475 void wxDCImpl::CalculateEllipticPoints( wxPointList
* points
,
1476 wxCoord xStart
, wxCoord yStart
,
1477 wxCoord w
, wxCoord h
,
1478 double sa
, double ea
)
1489 bool bUseAngles
= false;
1495 // decrement 1 pixel if ellipse is smaller than 2*a, 2*b
1497 if( 2*a
== w
) decrX
= 1;
1499 if( 2*b
== h
) decrY
= 1;
1501 wxCoord xCenter
= xStart
+ a
;
1502 wxCoord yCenter
= yStart
+ b
;
1503 // calculate data for start and end, if necessary
1507 // normalisation of angles
1508 while( sa
<0 ) sa
+= 360;
1509 while( ea
<0 ) ea
+= 360;
1510 while( sa
>=360 ) sa
-= 360;
1511 while( ea
>=360 ) ea
-= 360;
1512 // calculate quadrant numbers
1513 if( sa
> 270 ) sq
= 3;
1514 else if( sa
> 180 ) sq
= 2;
1515 else if( sa
> 90 ) sq
= 1;
1516 if( ea
> 270 ) eq
= 3;
1517 else if( ea
> 180 ) eq
= 2;
1518 else if( ea
> 90 ) eq
= 1;
1519 sar
= sa
* pi
/ 180.0;
1520 ear
= ea
* pi
/ 180.0;
1521 // correct angle circle -> ellipse
1522 sar
= atan( -a
/(double)b
* tan( sar
) );
1523 if ( sq
== 1 || sq
== 2 ) sar
+= pi
;
1524 ear
= atan( -a
/(double)b
* tan( ear
) );
1525 if ( eq
== 1 || eq
== 2 ) ear
+= pi
;
1526 // coordinates of points
1527 xsa
= xCenter
+ a
* cos( sar
);
1528 if( sq
== 0 || sq
== 3 ) xsa
-= decrX
;
1529 ysa
= yCenter
+ b
* sin( sar
);
1530 if( sq
== 2 || sq
== 3 ) ysa
-= decrY
;
1531 xea
= xCenter
+ a
* cos( ear
);
1532 if( eq
== 0 || eq
== 3 ) xea
-= decrX
;
1533 yea
= yCenter
+ b
* sin( ear
);
1534 if( eq
== 2 || eq
== 3 ) yea
-= decrY
;
1536 // calculate c1 = b^2, c2 = b^2/a^2 with a = w/2, b = h/2
1538 double c2
= 2.0 / w
;
1547 // Lists for quadrant 1 to 4
1548 wxPointList pointsarray
[4];
1549 // Calculate points for first quadrant and set in all quadrants
1550 for( x
= 0; x
<= a
; ++x
)
1555 bool bNewPoint
= false;
1556 while( y2
> c1
- c2
* x2
&& y
> 0 )
1562 // old y now to big: set point with old y, old x
1563 if( bNewPoint
&& x
>1)
1566 // remove points on the same line
1567 pointsarray
[0].Insert( new wxPoint( xCenter
+ x1
- decrX
, yCenter
- y_old
) );
1568 pointsarray
[1].Append( new wxPoint( xCenter
- x1
, yCenter
- y_old
) );
1569 pointsarray
[2].Insert( new wxPoint( xCenter
- x1
, yCenter
+ y_old
- decrY
) );
1570 pointsarray
[3].Append( new wxPoint( xCenter
+ x1
- decrX
, yCenter
+ y_old
- decrY
) );
1572 } // calculate point
1574 // Starting and/or ending points for the quadrants, first quadrant gets both.
1575 pointsarray
[0].Insert( new wxPoint( xCenter
+ a
- decrX
, yCenter
) );
1576 pointsarray
[0].Append( new wxPoint( xCenter
, yCenter
- b
) );
1577 pointsarray
[1].Append( new wxPoint( xCenter
- a
, yCenter
) );
1578 pointsarray
[2].Append( new wxPoint( xCenter
, yCenter
+ b
- decrY
) );
1579 pointsarray
[3].Append( new wxPoint( xCenter
+ a
- decrX
, yCenter
) );
1581 // copy quadrants in original list
1584 // Copy the right part of the points in the lists
1585 // and delete the wxPoints, because they do not leave this method.
1586 points
->Append( new wxPoint( xsa
, ysa
) );
1588 bool bStarted
= false;
1589 bool bReady
= false;
1590 bool bForceTurn
= ( sq
== eq
&& sa
> ea
);
1593 wxPointList::compatibility_iterator node
;
1594 for( node
= pointsarray
[q
].GetFirst(); node
; node
= node
->GetNext() )
1596 // once: go to starting point in start quadrant
1599 node
->GetData()->x
< xsa
+1 && q
<= 1
1601 node
->GetData()->x
> xsa
-1 && q
>= 2
1608 // copy point, if not at ending point
1611 if( q
!= eq
|| bForceTurn
1613 ( (wxPoint
*) node
->GetData() )->x
> xea
+1 && q
<= 1
1615 ( (wxPoint
*) node
->GetData() )->x
< xea
-1 && q
>= 2
1619 wxPoint
* pPoint
= new wxPoint( *(node
->GetData()) );
1620 points
->Append( pPoint
);
1622 else if( q
== eq
&& !bForceTurn
|| node
->GetData()->x
== xea
)
1632 } // while not bReady
1633 points
->Append( new wxPoint( xea
, yea
) );
1636 for( q
= 0; q
< 4; ++q
)
1638 wxPointList::compatibility_iterator node
;
1639 for( node
= pointsarray
[q
].GetFirst(); node
; node
= node
->GetNext() )
1641 wxPoint
*p
= node
->GetData();
1648 wxPointList::compatibility_iterator node
;
1649 // copy whole ellipse, wxPoints will be deleted outside
1650 for( node
= pointsarray
[0].GetFirst(); node
; node
= node
->GetNext() )
1652 wxPoint
*p
= node
->GetData();
1653 points
->Append( p
);
1655 for( node
= pointsarray
[1].GetFirst(); node
; node
= node
->GetNext() )
1657 wxPoint
*p
= node
->GetData();
1658 points
->Append( p
);
1660 for( node
= pointsarray
[2].GetFirst(); node
; node
= node
->GetNext() )
1662 wxPoint
*p
= node
->GetData();
1663 points
->Append( p
);
1665 for( node
= pointsarray
[3].GetFirst(); node
; node
= node
->GetNext() )
1667 wxPoint
*p
= node
->GetData();
1668 points
->Append( p
);
1671 } // CalculateEllipticPoints
1673 #endif // __WXWINCE__
1675 float wxDCImpl::GetFontPointSizeAdjustment(float dpi
)
1677 // wxMSW has long-standing bug where wxFont point size is interpreted as
1678 // "pixel size corresponding to given point size *on screen*". In other
1679 // words, on a typical 600dpi printer and a typical 96dpi screen, fonts
1680 // are ~6 times smaller when printing. Unfortunately, this bug is so severe
1681 // that *all* printing code has to account for it and consequently, other
1682 // ports need to emulate this bug too:
1683 const wxSize screenPPI
= wxGetDisplayPPI();
1684 return float(screenPPI
.y
) / dpi
;