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/dcbuffer.h" // for IMPLEMENT_DYNAMIC_CLASS
41 //----------------------------------------------------------------------------
43 //----------------------------------------------------------------------------
45 wxDCFactory
*wxDCFactory::m_factory
= NULL
;
47 void wxDCFactory::SetDCFactory( wxDCFactory
*factory
)
49 if (wxDCFactory::m_factory
)
50 delete wxDCFactory::m_factory
;
52 wxDCFactory::m_factory
= factory
;
55 wxDCFactory
*wxDCFactory::GetFactory()
57 if (!wxDCFactory::m_factory
)
58 wxDCFactory::m_factory
= new wxNativeDCFactory
;
60 return wxDCFactory::m_factory
;
63 //-----------------------------------------------------------------------------
65 //-----------------------------------------------------------------------------
67 wxImplDC
* wxNativeDCFactory::CreateWindowDC( wxWindowDC
*owner
)
69 #if defined(__WXMSW__)
70 return new wxWindowsWindowImplDC( owner
);
71 #elif defined(__WXGTK20__)
72 return new wxGTKWindowImplDC( owner
);
73 #elif defined(__WXGTK__)
74 return new wxGTKWindowImplDC( owner
);
75 #elif defined(__WXMAC__)
76 return new wxMacWindowImplDC( owner
);
77 #elif defined(__WXCOCOA__)
78 return new wxCocoaWindowImplDC( owner
);
79 #elif defined(__WXMOTIF__)
80 return new wxMotifWindowImplDC( owner
);
81 #elif defined(__WXX11__)
82 return new wxX11WindowImplDC( owner
);
83 #elif defined(__WXMGL__)
84 return new wxMGLWindowImplDC( owner
);
85 #elif defined(__WXDFB__)
86 return new wxDFBWindowImplDC( owner
);
87 #elif defined(__WXPM__)
88 return new wxPMWindowImplDC( owner
);
89 #elif defined(__PALMOS__)
90 return new wxPalmWindowImplDC( owner
);
94 wxImplDC
* wxNativeDCFactory::CreateWindowDC( wxWindowDC
*owner
, wxWindow
*window
)
96 #if defined(__WXMSW__)
97 return new wxWindowsWindowImplDC( owner
, window
);
98 #elif defined(__WXGTK20__)
99 return new wxGTKWindowImplDC( owner
, window
);
100 #elif defined(__WXGTK__)
101 return new wxGTKWindowImplDC( owner
, window
);
102 #elif defined(__WXMAC__)
103 return new wxMacWindowImplDC( owner
, window
);
104 #elif defined(__WXCOCOA__)
105 return new wxCocoaWindowImplDC( owner
, window
);
106 #elif defined(__WXMOTIF__)
107 return new wxMotifWindowImplDC( owner
, window
);
108 #elif defined(__WXX11__)
109 return new wxX11WindowImplDC( owner
, window
);
110 #elif defined(__WXMGL__)
111 return new wxMGLWindowImplDC( owner
, window
);
112 #elif defined(__WXDFB__)
113 return new wxDFBWindowImplDC( owner
, window
);
114 #elif defined(__WXPM__)
115 return new wxPMWindowImplDC( owner
, window
);
116 #elif defined(__PALMOS__)
117 return new wxPalmWindowImplDC( owner
, window
);
121 wxImplDC
* wxNativeDCFactory::CreateClientDC( wxClientDC
*owner
)
123 #if defined(__WXMSW__)
124 return new wxWindowsClientImplDC( owner
);
125 #elif defined(__WXGTK20__)
126 return new wxGTKClientImplDC( owner
);
127 #elif defined(__WXGTK__)
128 return new wxGTKClientImplDC( owner
);
129 #elif defined(__WXMAC__)
130 return new wxMacClientImplDC( owner
);
131 #elif defined(__WXCOCOA__)
132 return new wxCocoaClientImplDC( owner
);
133 #elif defined(__WXMOTIF__)
134 return new wxMotifClientImplDC( owner
);
135 #elif defined(__WXX11__)
136 return new wxX11ClientImplDC( owner
);
137 #elif defined(__WXMGL__)
138 return new wxMGLClientImplDC( owner
);
139 #elif defined(__WXDFB__)
140 return new wxDFBClientImplDC( owner
);
141 #elif defined(__WXPM__)
142 return new wxPMClientImplDC( owner
);
143 #elif defined(__PALMOS__)
144 return new wxPalmClientImplDC( owner
);
148 wxImplDC
* wxNativeDCFactory::CreateClientDC( wxClientDC
*owner
, wxWindow
*window
)
150 #if defined(__WXMSW__)
151 return new wxWindowsClientImplDC( owner
, window
);
152 #elif defined(__WXGTK20__)
153 return new wxGTKClientImplDC( owner
, window
);
154 #elif defined(__WXGTK__)
155 return new wxGTKClientImplDC( owner
, window
);
156 #elif defined(__WXMAC__)
157 return new wxMacClientImplDC( owner
, window
);
158 #elif defined(__WXCOCOA__)
159 return new wxCocoaClientImplDC( owner
, window
);
160 #elif defined(__WXMOTIF__)
161 return new wxMotifClientImplDC( owner
, window
);
162 #elif defined(__WXX11__)
163 return new wxX11ClientImplDC( owner
, window
);
164 #elif defined(__WXMGL__)
165 return new wxMGLClientImplDC( owner
, window
);
166 #elif defined(__WXDFB__)
167 return new wxDFBClientImplDC( owner
, window
);
168 #elif defined(__WXPM__)
169 return new wxPMClientImplDC( owner
, window
);
170 #elif defined(__PALMOS__)
171 return new wxPalmClientImplDC( owner
, window
);
175 wxImplDC
* wxNativeDCFactory::CreatePaintDC( wxPaintDC
*owner
)
177 #if defined(__WXMSW__)
178 return new wxWindowsPaintImplDC( owner
);
179 #elif defined(__WXGTK20__)
180 return new wxGTKPaintImplDC( owner
);
181 #elif defined(__WXGTK__)
182 return new wxGTKPaintImplDC( owner
);
183 #elif defined(__WXMAC__)
184 return new wxMacPaintImplDC( owner
);
185 #elif defined(__WXCOCOA__)
186 return new wxCocoaPaintImplDC( owner
);
187 #elif defined(__WXMOTIF__)
188 return new wxMotifPaintImplDC( owner
);
189 #elif defined(__WXX11__)
190 return new wxX11PaintImplDC( owner
);
191 #elif defined(__WXMGL__)
192 return new wxMGLPaintImplDC( owner
);
193 #elif defined(__WXDFB__)
194 return new wxDFBPaintImplDC( owner
);
195 #elif defined(__WXPM__)
196 return new wxPMPaintImplDC( owner
);
197 #elif defined(__PALMOS__)
198 return new wxPalmPaintImplDC( owner
);
202 wxImplDC
* wxNativeDCFactory::CreatePaintDC( wxPaintDC
*owner
, wxWindow
*window
)
204 #if defined(__WXMSW__)
205 return new wxWindowsPaintImplDC( owner
, window
);
206 #elif defined(__WXGTK20__)
207 return new wxGTKPaintImplDC( owner
, window
);
208 #elif defined(__WXGTK__)
209 return new wxGTKPaintImplDC( owner
, window
);
210 #elif defined(__WXMAC__)
211 return new wxMacPaintImplDC( owner
, window
);
212 #elif defined(__WXCOCOA__)
213 return new wxCocoaPaintImplDC( owner
, window
);
214 #elif defined(__WXMOTIF__)
215 return new wxMotifPaintImplDC( owner
, window
);
216 #elif defined(__WXX11__)
217 return new wxX11PaintImplDC( owner
, window
);
218 #elif defined(__WXMGL__)
219 return new wxMGLPaintImplDC( owner
, window
);
220 #elif defined(__WXDFB__)
221 return new wxDFBPaintImplDC( owner
, window
);
222 #elif defined(__WXPM__)
223 return new wxPMPaintImplDC( owner
, window
);
224 #elif defined(__PALMOS__)
225 return new wxPalmPaintImplDC( owner
, window
);
229 wxImplDC
* wxNativeDCFactory::CreateMemoryDC( wxMemoryDC
*owner
)
231 #if defined(__WXMSW__)
232 return new wxWindowsMemoryImplDC( owner
);
233 #elif defined(__WXGTK20__)
234 return new wxGTKMemoryImplDC( owner
);
235 #elif defined(__WXGTK__)
236 return new wxGTKMemoryImplDC( owner
);
237 #elif defined(__WXMAC__)
238 return new wxMacMemoryImplDC( owner
);
239 #elif defined(__WXCOCOA__)
240 return new wxCocoaMemoryImplDC( owner
);
241 #elif defined(__WXMOTIF__)
242 return new wxMotifMemoryImplDC( owner
);
243 #elif defined(__WXX11__)
244 return new wxX11MemoryImplDC( owner
);
245 #elif defined(__WXMGL__)
246 return new wxMGLMemoryImplDC( owner
);
247 #elif defined(__WXDFB__)
248 return new wxDFBMemoryImplDC( owner
);
249 #elif defined(__WXPM__)
250 return new wxPMMemoryImplDC( owner
);
251 #elif defined(__PALMOS__)
252 return new wxPalmMemoryImplDC( owner
);
256 wxImplDC
* wxNativeDCFactory::CreateMemoryDC( wxMemoryDC
*owner
, wxBitmap
&bitmap
)
258 #if defined(__WXMSW__)
259 return new wxWindowsMemoryImplDC( owner
, bitmap
);
260 #elif defined(__WXGTK20__)
261 return new wxGTKMemoryImplDC( owner
, bitmap
);
262 #elif defined(__WXGTK__)
263 return new wxGTKMemoryImplDC( owner
, bitmap
);
264 #elif defined(__WXMAC__)
265 return new wxMacMemoryImplDC( owner
, bitmap
);
266 #elif defined(__WXCOCOA__)
267 return new wxCocoaMemoryImplDC( owner
, bitmap
);
268 #elif defined(__WXMOTIF__)
269 return new wxMotifMemoryImplDC( owner
, bitmap
);
270 #elif defined(__WXX11__)
271 return new wxX11MemoryImplDC( owner
, bitmap
);
272 #elif defined(__WXMGL__)
273 return new wxMGLMemoryImplDC( owner
, bitmap
);
274 #elif defined(__WXDFB__)
275 return new wxDFBMemoryImplDC( owner
, bitmap
);
276 #elif defined(__WXPM__)
277 return new wxPMMemoryImplDC( owner
, bitmap
);
278 #elif defined(__PALMOS__)
279 return new wxPalmMemoryImplDC( owner
, bitmap
);
283 wxImplDC
* wxNativeDCFactory::CreateMemoryDC( wxMemoryDC
*owner
, wxDC
*dc
)
285 #if defined(__WXMSW__)
286 return new wxWindowsMemoryImplDC( owner
, dc
);
287 #elif defined(__WXGTK20__)
288 return new wxGTKMemoryImplDC( owner
, dc
);
289 #elif defined(__WXGTK__)
290 return new wxGTKMemoryImplDC( owner
, dc
);
291 #elif defined(__WXMAC__)
292 return new wxMacMemoryImplDC( owner
, dc
);
293 #elif defined(__WXCOCOA__)
294 return new wxCocoaMemoryImplDC( owner
, dc
);
295 #elif defined(__WXMOTIF__)
296 return new wxMotifMemoryImplDC( owner
, dc
);
297 #elif defined(__WXX11__)
298 return new wxX11MemoryImplDC( owner
, dc
);
299 #elif defined(__WXMGL__)
300 return new wxMGLMemoryImplDC( owner
, dc
);
301 #elif defined(__WXDFB__)
302 return new wxDFBMemoryImplDC( owner
, dc
);
303 #elif defined(__WXPM__)
304 return new wxPMMemoryImplDC( owner
, dc
);
305 #elif defined(__PALMOS__)
306 return new wxPalmMemoryImplDC( owner
, dc
);
310 wxImplDC
* wxNativeDCFactory::CreateScreenDC( wxScreenDC
*owner
)
312 #if defined(__WXMSW__)
313 return new wxWindowsScreenImplDC( owner
);
314 #elif defined(__WXGTK20__)
315 return new wxGTKScreenImplDC( owner
);
316 #elif defined(__WXGTK__)
317 return new wxGTKScreenImplDC( owner
);
318 #elif defined(__WXMAC__)
319 return new wxMacScreenImplDC( owner
);
320 #elif defined(__WXCOCOA__)
321 return new wxCocoaScreenImplDC( owner
);
322 #elif defined(__WXMOTIF__)
323 return new wxMotifScreenImplDC( owner
);
324 #elif defined(__WXX11__)
325 return new wxX11ScreenImplDC( owner
);
326 #elif defined(__WXMGL__)
327 return new wxMGLScreenImplDC( owner
);
328 #elif defined(__WXDFB__)
329 return new wxDFBScreenImplDC( owner
);
330 #elif defined(__WXPM__)
331 return new wxPMScreenImplDC( owner
);
332 #elif defined(__PALMOS__)
333 return new wxPalmScreenImplDC( owner
);
337 //-----------------------------------------------------------------------------
339 //-----------------------------------------------------------------------------
341 IMPLEMENT_DYNAMIC_CLASS(wxWindowDC
, wxDC
)
343 wxWindowDC::wxWindowDC()
345 wxDCFactory
*factory
= wxDCFactory::GetFactory();
346 m_pimpl
= factory
->CreateWindowDC( this );
349 wxWindowDC::wxWindowDC( wxWindow
*win
)
351 wxDCFactory
*factory
= wxDCFactory::GetFactory();
352 m_pimpl
= factory
->CreateWindowDC( this, win
);
355 //-----------------------------------------------------------------------------
357 //-----------------------------------------------------------------------------
359 IMPLEMENT_DYNAMIC_CLASS(wxClientDC
, wxDC
)
361 wxClientDC::wxClientDC()
363 wxDCFactory
*factory
= wxDCFactory::GetFactory();
364 m_pimpl
= factory
->CreateClientDC( this );
367 wxClientDC::wxClientDC( wxWindow
*win
)
369 wxDCFactory
*factory
= wxDCFactory::GetFactory();
370 m_pimpl
= factory
->CreateClientDC( this, win
);
373 //-----------------------------------------------------------------------------
375 //-----------------------------------------------------------------------------
377 IMPLEMENT_DYNAMIC_CLASS(wxMemoryDC
, wxDC
)
379 wxMemoryDC::wxMemoryDC()
381 wxDCFactory
*factory
= wxDCFactory::GetFactory();
382 m_pimpl
= factory
->CreateMemoryDC( this );
385 wxMemoryDC::wxMemoryDC( wxBitmap
& bitmap
)
387 wxDCFactory
*factory
= wxDCFactory::GetFactory();
388 m_pimpl
= factory
->CreateMemoryDC( this, bitmap
);
391 wxMemoryDC::wxMemoryDC( wxDC
*dc
)
393 wxDCFactory
*factory
= wxDCFactory::GetFactory();
394 m_pimpl
= factory
->CreateMemoryDC( this, dc
);
397 void wxMemoryDC::SelectObject(wxBitmap
& bmp
)
399 // make sure that the given wxBitmap is not sharing its data with other
400 // wxBitmap instances as its contents will be modified by any drawing
401 // operation done on this DC
406 wxGTKMemoryImplDC
*mem_pimpl
= wxDynamicCast( m_pimpl
, wxGTKMemoryImplDC
);
411 mem_pimpl
->DoSelect(bmp
);
414 void wxMemoryDC::SelectObjectAsSource(const wxBitmap
& bmp
)
417 wxGTKMemoryImplDC
*mem_pimpl
= wxDynamicCast( m_pimpl
, wxGTKMemoryImplDC
);
421 mem_pimpl
->DoSelect(bmp
);
424 const wxBitmap
& wxMemoryDC::GetSelectedBitmap() const
427 wxGTKMemoryImplDC
*mem_pimpl
= wxDynamicCast( m_pimpl
, wxGTKMemoryImplDC
);
432 return mem_pimpl
->DoGetSelectedBitmap();
437 wxBitmap
& wxMemoryDC::GetSelectedBitmap()
440 wxGTKMemoryImplDC
*mem_pimpl
= wxDynamicCast( m_pimpl
, wxGTKMemoryImplDC
);
446 return mem_pimpl
->DoGetSelectedBitmap();
452 //-----------------------------------------------------------------------------
454 //-----------------------------------------------------------------------------
456 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC
, wxDC
)
458 wxPaintDC::wxPaintDC()
460 wxDCFactory
*factory
= wxDCFactory::GetFactory();
461 m_pimpl
= factory
->CreatePaintDC( this );
464 wxPaintDC::wxPaintDC( wxWindow
*win
)
466 wxDCFactory
*factory
= wxDCFactory::GetFactory();
467 m_pimpl
= factory
->CreatePaintDC( this, win
);
470 //-----------------------------------------------------------------------------
472 //-----------------------------------------------------------------------------
474 IMPLEMENT_DYNAMIC_CLASS(wxScreenDC
, wxWindowDC
)
476 wxScreenDC::wxScreenDC()
478 wxDCFactory
*factory
= wxDCFactory::GetFactory();
479 m_pimpl
= factory
->CreateScreenDC( this );
482 //-----------------------------------------------------------------------------
484 //-----------------------------------------------------------------------------
486 IMPLEMENT_ABSTRACT_CLASS(wxImplDC
, wxObject
)
488 wxImplDC::wxImplDC( wxDC
*owner
)
489 : m_colour(wxColourDisplay())
493 , m_isBBoxValid(false)
494 , m_logicalOriginX(0), m_logicalOriginY(0)
495 , m_deviceOriginX(0), m_deviceOriginY(0)
496 , m_deviceLocalOriginX(0), m_deviceLocalOriginY(0)
497 , m_logicalScaleX(1.0), m_logicalScaleY(1.0)
498 , m_userScaleX(1.0), m_userScaleY(1.0)
499 , m_scaleX(1.0), m_scaleY(1.0)
500 , m_signX(1), m_signY(1)
501 , m_minX(0), m_minY(0), m_maxX(0), m_maxY(0)
502 , m_clipX1(0), m_clipY1(0), m_clipX2(0), m_clipY2(0)
503 , m_logicalFunction(wxCOPY
)
504 , m_backgroundMode(wxTRANSPARENT
)
505 , m_mappingMode(wxMM_TEXT
)
508 , m_backgroundBrush(*wxTRANSPARENT_BRUSH
)
509 , m_textForegroundColour(*wxBLACK
)
510 , m_textBackgroundColour(*wxWHITE
)
514 , m_hasCustomPalette(false)
515 #endif // wxUSE_PALETTE
519 m_mm_to_pix_x
= (double)wxGetDisplaySize().GetWidth() /
520 (double)wxGetDisplaySizeMM().GetWidth();
521 m_mm_to_pix_y
= (double)wxGetDisplaySize().GetHeight() /
522 (double)wxGetDisplaySizeMM().GetHeight();
528 wxImplDC::~wxImplDC()
532 // ----------------------------------------------------------------------------
533 // coordinate conversions and transforms
534 // ----------------------------------------------------------------------------
536 wxCoord
wxImplDC::DeviceToLogicalX(wxCoord x
) const
538 return wxRound((double)(x
- m_deviceOriginX
- m_deviceLocalOriginX
) / m_scaleX
) * m_signX
+ m_logicalOriginX
;
541 wxCoord
wxImplDC::DeviceToLogicalY(wxCoord y
) const
543 return wxRound((double)(y
- m_deviceOriginY
- m_deviceLocalOriginY
) / m_scaleY
) * m_signY
+ m_logicalOriginY
;
546 wxCoord
wxImplDC::DeviceToLogicalXRel(wxCoord x
) const
548 return wxRound((double)(x
) / m_scaleX
);
551 wxCoord
wxImplDC::DeviceToLogicalYRel(wxCoord y
) const
553 return wxRound((double)(y
) / m_scaleY
);
556 wxCoord
wxImplDC::LogicalToDeviceX(wxCoord x
) const
558 return wxRound((double)(x
- m_logicalOriginX
) * m_scaleX
) * m_signX
+ m_deviceOriginX
* m_signY
+ m_deviceLocalOriginX
;
561 wxCoord
wxImplDC::LogicalToDeviceY(wxCoord y
) const
563 return wxRound((double)(y
- m_logicalOriginY
) * m_scaleY
) * m_signY
+ m_deviceOriginY
* m_signY
+ m_deviceLocalOriginY
;
566 wxCoord
wxImplDC::LogicalToDeviceXRel(wxCoord x
) const
568 return wxRound((double)(x
) * m_scaleX
);
571 wxCoord
wxImplDC::LogicalToDeviceYRel(wxCoord y
) const
573 return wxRound((double)(y
) * m_scaleY
);
576 void wxImplDC::ComputeScaleAndOrigin()
578 m_scaleX
= m_logicalScaleX
* m_userScaleX
;
579 m_scaleY
= m_logicalScaleY
* m_userScaleY
;
582 void wxImplDC::SetMapMode( int mode
)
587 SetLogicalScale( twips2mm
*m_mm_to_pix_x
, twips2mm
*m_mm_to_pix_y
);
590 SetLogicalScale( pt2mm
*m_mm_to_pix_x
, pt2mm
*m_mm_to_pix_y
);
593 SetLogicalScale( m_mm_to_pix_x
, m_mm_to_pix_y
);
596 SetLogicalScale( m_mm_to_pix_x
/10.0, m_mm_to_pix_y
/10.0 );
600 SetLogicalScale( 1.0, 1.0 );
603 m_mappingMode
= mode
;
606 void wxImplDC::SetUserScale( double x
, double y
)
608 // allow negative ? -> no
611 ComputeScaleAndOrigin();
614 void wxImplDC::SetLogicalScale( double x
, double y
)
619 ComputeScaleAndOrigin();
622 void wxImplDC::SetLogicalOrigin( wxCoord x
, wxCoord y
)
624 m_logicalOriginX
= x
* m_signX
;
625 m_logicalOriginY
= y
* m_signY
;
626 ComputeScaleAndOrigin();
629 void wxImplDC::SetDeviceOrigin( wxCoord x
, wxCoord y
)
633 ComputeScaleAndOrigin();
636 void wxImplDC::SetDeviceLocalOrigin( wxCoord x
, wxCoord y
)
638 m_deviceLocalOriginX
= x
;
639 m_deviceLocalOriginY
= y
;
640 ComputeScaleAndOrigin();
643 void wxImplDC::SetAxisOrientation( bool xLeftRight
, bool yBottomUp
)
645 // only wxPostScripDC has m_signX = -1, we override SetAxisOrientation there
646 // wxWidgets 2.9: no longer override it
647 m_signX
= (xLeftRight
? 1 : -1);
648 m_signY
= (yBottomUp
? -1 : 1);
649 ComputeScaleAndOrigin();
653 // Each element of the widths array will be the width of the string up to and
654 // including the corresponding character in text. This is the generic
655 // implementation, the port-specific classes should do this with native APIs
656 // if available and if faster. Note: pango_layout_index_to_pos is much slower
657 // than calling GetTextExtent!!
664 FontWidthCache() : m_scaleX(1), m_widths(NULL
) { }
665 ~FontWidthCache() { delete []m_widths
; }
670 m_widths
= new int[FWC_SIZE
];
672 memset(m_widths
, 0, sizeof(int)*FWC_SIZE
);
680 static FontWidthCache s_fontWidthCache
;
682 bool wxImplDC::DoGetPartialTextExtents(const wxString
& text
, wxArrayInt
& widths
) const
686 const size_t len
= text
.length();
690 // reset the cache if font or horizontal scale have changed
691 if ( !s_fontWidthCache
.m_widths
||
692 !wxIsSameDouble(s_fontWidthCache
.m_scaleX
, m_scaleX
) ||
693 (s_fontWidthCache
.m_font
!= GetFont()) )
695 s_fontWidthCache
.Reset();
696 s_fontWidthCache
.m_font
= GetFont();
697 s_fontWidthCache
.m_scaleX
= m_scaleX
;
700 // Calculate the position of each character based on the widths of
701 // the previous characters
703 for ( size_t i
= 0; i
< len
; i
++ )
705 const wxChar c
= text
[i
];
706 unsigned int c_int
= (unsigned int)c
;
708 if ((c_int
< FWC_SIZE
) && (s_fontWidthCache
.m_widths
[c_int
] != 0))
710 w
= s_fontWidthCache
.m_widths
[c_int
];
714 DoGetTextExtent(c
, &w
, &h
);
715 if (c_int
< FWC_SIZE
)
716 s_fontWidthCache
.m_widths
[c_int
] = w
;
720 widths
[i
] = totalWidth
;
726 void wxImplDC::GetMultiLineTextExtent(const wxString
& text
,
730 const wxFont
*font
) const
732 wxCoord widthTextMax
= 0, widthLine
,
733 heightTextTotal
= 0, heightLineDefault
= 0, heightLine
= 0;
736 for ( const wxChar
*pc
= text
; ; pc
++ )
738 if ( *pc
== _T('\n') || *pc
== _T('\0') )
740 if ( curLine
.empty() )
742 // we can't use GetTextExtent - it will return 0 for both width
743 // and height and an empty line should count in height
746 // assume that this line has the same height as the previous
748 if ( !heightLineDefault
)
749 heightLineDefault
= heightLine
;
751 if ( !heightLineDefault
)
753 // but we don't know it yet - choose something reasonable
754 DoGetTextExtent(_T("W"), NULL
, &heightLineDefault
,
758 heightTextTotal
+= heightLineDefault
;
762 DoGetTextExtent(curLine
, &widthLine
, &heightLine
,
764 if ( widthLine
> widthTextMax
)
765 widthTextMax
= widthLine
;
766 heightTextTotal
+= heightLine
;
769 if ( *pc
== _T('\n') )
788 *y
= heightTextTotal
;
793 void wxImplDC::DoDrawCheckMark(wxCoord x1
, wxCoord y1
,
794 wxCoord width
, wxCoord height
)
796 wxCHECK_RET( IsOk(), wxT("invalid window dc") );
798 wxCoord x2
= x1
+ width
,
801 // the pen width is calibrated to give 3 for width == height == 10
802 wxDCPenChanger
pen( *m_owner
, wxPen(GetTextForeground(), (width
+ height
+ 1)/7));
804 // we're drawing a scaled version of wx/generic/tick.xpm here
805 wxCoord x3
= x1
+ (4*width
) / 10, // x of the tick bottom
806 y3
= y1
+ height
/ 2; // y of the left tick branch
807 DoDrawLine(x1
, y3
, x3
, y2
);
808 DoDrawLine(x3
, y2
, x2
, y1
);
810 CalcBoundingBox(x1
, y1
);
811 CalcBoundingBox(x2
, y2
);
815 wxImplDC::DoStretchBlit(wxCoord xdest
, wxCoord ydest
,
816 wxCoord dstWidth
, wxCoord dstHeight
,
818 wxCoord xsrc
, wxCoord ysrc
,
819 wxCoord srcWidth
, wxCoord srcHeight
,
825 wxCHECK_MSG( srcWidth
&& srcHeight
&& dstWidth
&& dstHeight
, false,
826 _T("invalid blit size") );
828 // emulate the stretching by modifying the DC scale
829 double xscale
= (double)srcWidth
/dstWidth
,
830 yscale
= (double)srcHeight
/dstHeight
;
832 double xscaleOld
, yscaleOld
;
833 GetUserScale(&xscaleOld
, &yscaleOld
);
834 SetUserScale(xscaleOld
/xscale
, yscaleOld
/yscale
);
836 bool rc
= DoBlit(wxCoord(xdest
*xscale
), wxCoord(ydest
*yscale
),
837 wxCoord(dstWidth
*xscale
), wxCoord(dstHeight
*yscale
),
839 xsrc
, ysrc
, rop
, useMask
, xsrcMask
, ysrcMask
);
841 SetUserScale(xscaleOld
, yscaleOld
);
846 void wxImplDC::DrawLines(const wxPointList
*list
, wxCoord xoffset
, wxCoord yoffset
)
848 int n
= list
->GetCount();
849 wxPoint
*points
= new wxPoint
[n
];
852 for ( wxPointList::compatibility_iterator node
= list
->GetFirst(); node
; node
= node
->GetNext(), i
++ )
854 wxPoint
*point
= node
->GetData();
855 points
[i
].x
= point
->x
;
856 points
[i
].y
= point
->y
;
859 DoDrawLines(n
, points
, xoffset
, yoffset
);
864 void wxImplDC::DrawPolygon(const wxPointList
*list
,
865 wxCoord xoffset
, wxCoord yoffset
,
868 int n
= list
->GetCount();
869 wxPoint
*points
= new wxPoint
[n
];
872 for ( wxPointList::compatibility_iterator node
= list
->GetFirst(); node
; node
= node
->GetNext(), i
++ )
874 wxPoint
*point
= node
->GetData();
875 points
[i
].x
= point
->x
;
876 points
[i
].y
= point
->y
;
879 DoDrawPolygon(n
, points
, xoffset
, yoffset
, fillStyle
);
885 wxImplDC::DoDrawPolyPolygon(int n
,
888 wxCoord xoffset
, wxCoord yoffset
,
893 DoDrawPolygon(count
[0], points
, xoffset
, yoffset
, fillStyle
);
901 for (i
= j
= lastOfs
= 0; i
< n
; i
++)
906 pts
= new wxPoint
[j
+n
-1];
907 for (i
= 0; i
< j
; i
++)
909 for (i
= 2; i
<= n
; i
++)
911 lastOfs
-= count
[n
-i
];
912 pts
[j
++] = pts
[lastOfs
];
916 SetPen(wxPen(*wxBLACK
, 0, wxTRANSPARENT
));
917 DoDrawPolygon(j
, pts
, xoffset
, yoffset
, fillStyle
);
919 for (i
= j
= 0; i
< n
; i
++)
921 DoDrawLines(count
[i
], pts
+j
, xoffset
, yoffset
);
929 void wxImplDC::DoDrawSpline(wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
, wxCoord x3
, wxCoord y3
)
931 wxPointList point_list
;
933 wxPoint
*point1
= new wxPoint
;
934 point1
->x
= x1
; point1
->y
= y1
;
935 point_list
.Append( point1
);
937 wxPoint
*point2
= new wxPoint
;
938 point2
->x
= x2
; point2
->y
= y2
;
939 point_list
.Append( point2
);
941 wxPoint
*point3
= new wxPoint
;
942 point3
->x
= x3
; point3
->y
= y3
;
943 point_list
.Append( point3
);
945 DoDrawSpline(&point_list
);
947 for( wxPointList::compatibility_iterator node
= point_list
.GetFirst(); node
; node
= node
->GetNext() )
949 wxPoint
*p
= node
->GetData();
954 void wxImplDC::DoDrawSpline(int n
, wxPoint points
[])
957 for (int i
=0; i
< n
; i
++)
958 list
.Append( &points
[i
] );
963 // ----------------------------------- spline code ----------------------------------------
965 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
,
966 double a3
, double b3
, double a4
, double b4
);
967 void wx_clear_stack();
968 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
, double *x3
,
969 double *y3
, double *x4
, double *y4
);
970 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
,
971 double x4
, double y4
);
972 static bool wx_spline_add_point(double x
, double y
);
973 static void wx_spline_draw_point_array(wxDC
*dc
);
975 wxPointList wx_spline_point_list
;
977 #define half(z1, z2) ((z1+z2)/2.0)
980 /* iterative version */
982 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
, double a3
, double b3
, double a4
,
985 register double xmid
, ymid
;
986 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
989 wx_spline_push(a1
, b1
, a2
, b2
, a3
, b3
, a4
, b4
);
991 while (wx_spline_pop(&x1
, &y1
, &x2
, &y2
, &x3
, &y3
, &x4
, &y4
)) {
992 xmid
= (double)half(x2
, x3
);
993 ymid
= (double)half(y2
, y3
);
994 if (fabs(x1
- xmid
) < THRESHOLD
&& fabs(y1
- ymid
) < THRESHOLD
&&
995 fabs(xmid
- x4
) < THRESHOLD
&& fabs(ymid
- y4
) < THRESHOLD
) {
996 wx_spline_add_point( x1
, y1
);
997 wx_spline_add_point( xmid
, ymid
);
999 wx_spline_push(xmid
, ymid
, (double)half(xmid
, x3
), (double)half(ymid
, y3
),
1000 (double)half(x3
, x4
), (double)half(y3
, y4
), x4
, y4
);
1001 wx_spline_push(x1
, y1
, (double)half(x1
, x2
), (double)half(y1
, y2
),
1002 (double)half(x2
, xmid
), (double)half(y2
, ymid
), xmid
, ymid
);
1007 /* utilities used by spline drawing routines */
1009 typedef struct wx_spline_stack_struct
{
1010 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
1013 #define SPLINE_STACK_DEPTH 20
1014 static Stack wx_spline_stack
[SPLINE_STACK_DEPTH
];
1015 static Stack
*wx_stack_top
;
1016 static int wx_stack_count
;
1018 void wx_clear_stack()
1020 wx_stack_top
= wx_spline_stack
;
1024 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
, double x4
, double y4
)
1026 wx_stack_top
->x1
= x1
;
1027 wx_stack_top
->y1
= y1
;
1028 wx_stack_top
->x2
= x2
;
1029 wx_stack_top
->y2
= y2
;
1030 wx_stack_top
->x3
= x3
;
1031 wx_stack_top
->y3
= y3
;
1032 wx_stack_top
->x4
= x4
;
1033 wx_stack_top
->y4
= y4
;
1038 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
,
1039 double *x3
, double *y3
, double *x4
, double *y4
)
1041 if (wx_stack_count
== 0)
1045 *x1
= wx_stack_top
->x1
;
1046 *y1
= wx_stack_top
->y1
;
1047 *x2
= wx_stack_top
->x2
;
1048 *y2
= wx_stack_top
->y2
;
1049 *x3
= wx_stack_top
->x3
;
1050 *y3
= wx_stack_top
->y3
;
1051 *x4
= wx_stack_top
->x4
;
1052 *y4
= wx_stack_top
->y4
;
1056 static bool wx_spline_add_point(double x
, double y
)
1058 wxPoint
*point
= new wxPoint( wxRound(x
), wxRound(y
) );
1059 wx_spline_point_list
.Append(point
);
1063 static void wx_spline_draw_point_array(wxDC
*dc
)
1065 wxPointList::compatibility_iterator node
= wx_spline_point_list
.GetFirst();
1068 wxPoint
*point
= node
->GetData();
1070 wx_spline_point_list
.Erase(node
);
1071 node
= wx_spline_point_list
.GetFirst();
1075 void wxImplDC::DoDrawSpline( const wxPointList
*points
)
1077 wxCHECK_RET( IsOk(), wxT("invalid window dc") );
1080 double cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
;
1081 double x1
, y1
, x2
, y2
;
1083 wxPointList::compatibility_iterator node
= points
->GetFirst();
1088 p
= (wxPoint
*)node
->GetData();
1093 node
= node
->GetNext();
1094 p
= node
->GetData();
1098 cx1
= (double)((x1
+ x2
) / 2);
1099 cy1
= (double)((y1
+ y2
) / 2);
1100 cx2
= (double)((cx1
+ x2
) / 2);
1101 cy2
= (double)((cy1
+ y2
) / 2);
1103 wx_spline_add_point(x1
, y1
);
1105 while ((node
= node
->GetNext())
1108 #endif // !wxUSE_STL
1111 p
= node
->GetData();
1116 cx4
= (double)(x1
+ x2
) / 2;
1117 cy4
= (double)(y1
+ y2
) / 2;
1118 cx3
= (double)(x1
+ cx4
) / 2;
1119 cy3
= (double)(y1
+ cy4
) / 2;
1121 wx_quadratic_spline(cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
);
1125 cx2
= (double)(cx1
+ x2
) / 2;
1126 cy2
= (double)(cy1
+ y2
) / 2;
1129 wx_spline_add_point( cx1
, cy1
);
1130 wx_spline_add_point( x2
, y2
);
1132 wx_spline_draw_point_array( m_owner
);
1135 #endif // wxUSE_SPLINES
1139 void wxImplDC::DoGradientFillLinear(const wxRect
& rect
,
1140 const wxColour
& initialColour
,
1141 const wxColour
& destColour
,
1142 wxDirection nDirection
)
1145 wxPen oldPen
= m_pen
;
1146 wxBrush oldBrush
= m_brush
;
1148 wxUint8 nR1
= initialColour
.Red();
1149 wxUint8 nG1
= initialColour
.Green();
1150 wxUint8 nB1
= initialColour
.Blue();
1151 wxUint8 nR2
= destColour
.Red();
1152 wxUint8 nG2
= destColour
.Green();
1153 wxUint8 nB2
= destColour
.Blue();
1156 if ( nDirection
== wxEAST
|| nDirection
== wxWEST
)
1158 wxInt32 x
= rect
.GetWidth();
1159 wxInt32 w
= x
; // width of area to shade
1160 wxInt32 xDelta
= w
/256; // height of one shade bend
1168 nR
= nR1
- (nR1
-nR2
)*(w
-x
)/w
;
1170 nR
= nR1
+ (nR2
-nR1
)*(w
-x
)/w
;
1173 nG
= nG1
- (nG1
-nG2
)*(w
-x
)/w
;
1175 nG
= nG1
+ (nG2
-nG1
)*(w
-x
)/w
;
1178 nB
= nB1
- (nB1
-nB2
)*(w
-x
)/w
;
1180 nB
= nB1
+ (nB2
-nB1
)*(w
-x
)/w
;
1182 wxColour
colour(nR
,nG
,nB
);
1183 SetPen(wxPen(colour
, 1, wxSOLID
));
1184 SetBrush(wxBrush(colour
));
1185 if(nDirection
== wxEAST
)
1186 DoDrawRectangle(rect
.GetRight()-x
-xDelta
+1, rect
.GetTop(),
1187 xDelta
, rect
.GetHeight());
1188 else //nDirection == wxWEST
1189 DoDrawRectangle(rect
.GetLeft()+x
, rect
.GetTop(),
1190 xDelta
, rect
.GetHeight());
1193 else // nDirection == wxNORTH || nDirection == wxSOUTH
1195 wxInt32 y
= rect
.GetHeight();
1196 wxInt32 w
= y
; // height of area to shade
1197 wxInt32 yDelta
= w
/255; // height of one shade bend
1205 nR
= nR1
- (nR1
-nR2
)*(w
-y
)/w
;
1207 nR
= nR1
+ (nR2
-nR1
)*(w
-y
)/w
;
1210 nG
= nG1
- (nG1
-nG2
)*(w
-y
)/w
;
1212 nG
= nG1
+ (nG2
-nG1
)*(w
-y
)/w
;
1215 nB
= nB1
- (nB1
-nB2
)*(w
-y
)/w
;
1217 nB
= nB1
+ (nB2
-nB1
)*(w
-y
)/w
;
1219 wxColour
colour(nR
,nG
,nB
);
1220 SetPen(wxPen(colour
, 1, wxSOLID
));
1221 SetBrush(wxBrush(colour
));
1222 if(nDirection
== wxNORTH
)
1223 DoDrawRectangle(rect
.GetLeft(), rect
.GetTop()+y
,
1224 rect
.GetWidth(), yDelta
);
1225 else //nDirection == wxSOUTH
1226 DoDrawRectangle(rect
.GetLeft(), rect
.GetBottom()-y
-yDelta
+1,
1227 rect
.GetWidth(), yDelta
);
1235 void wxImplDC::DoGradientFillConcentric(const wxRect
& rect
,
1236 const wxColour
& initialColour
,
1237 const wxColour
& destColour
,
1238 const wxPoint
& circleCenter
)
1240 //save the old pen color
1241 wxColour oldPenColour
= m_pen
.GetColour();
1243 wxUint8 nR1
= destColour
.Red();
1244 wxUint8 nG1
= destColour
.Green();
1245 wxUint8 nB1
= destColour
.Blue();
1246 wxUint8 nR2
= initialColour
.Red();
1247 wxUint8 nG2
= initialColour
.Green();
1248 wxUint8 nB2
= initialColour
.Blue();
1253 wxInt32 cx
= rect
.GetWidth() / 2;
1254 wxInt32 cy
= rect
.GetHeight() / 2;
1262 wxInt32 nCircleOffX
= circleCenter
.x
- (rect
.GetWidth() / 2);
1263 wxInt32 nCircleOffY
= circleCenter
.y
- (rect
.GetHeight() / 2);
1265 for ( wxInt32 x
= 0; x
< rect
.GetWidth(); x
++ )
1267 for ( wxInt32 y
= 0; y
< rect
.GetHeight(); y
++ )
1269 //get color difference
1270 wxInt32 nGradient
= ((nRadius
-
1272 pow((double)(x
- cx
- nCircleOffX
), 2) +
1273 pow((double)(y
- cy
- nCircleOffY
), 2)
1274 )) * 100) / nRadius
;
1276 //normalize Gradient
1281 nR
= (wxUint8
)(nR1
+ ((nR2
- nR1
) * nGradient
/ 100));
1282 nG
= (wxUint8
)(nG1
+ ((nG2
- nG1
) * nGradient
/ 100));
1283 nB
= (wxUint8
)(nB1
+ ((nB2
- nB1
) * nGradient
/ 100));
1286 m_pen
.SetColour(wxColour(nR
,nG
,nB
));
1287 DoDrawPoint(x
+ rect
.GetLeft(), y
+ rect
.GetTop());
1290 //return old pen color
1291 m_pen
.SetColour(oldPenColour
);
1294 //-----------------------------------------------------------------------------
1296 //-----------------------------------------------------------------------------
1298 IMPLEMENT_ABSTRACT_CLASS(wxDC
, wxObject
)
1300 void wxDC::DrawLabel(const wxString
& text
,
1301 const wxBitmap
& bitmap
,
1305 wxRect
*rectBounding
)
1307 // find the text position
1308 wxCoord widthText
, heightText
, heightLine
;
1309 GetMultiLineTextExtent(text
, &widthText
, &heightText
, &heightLine
);
1311 wxCoord width
, height
;
1314 width
= widthText
+ bitmap
.GetWidth();
1315 height
= bitmap
.GetHeight();
1320 height
= heightText
;
1324 if ( alignment
& wxALIGN_RIGHT
)
1326 x
= rect
.GetRight() - width
;
1328 else if ( alignment
& wxALIGN_CENTRE_HORIZONTAL
)
1330 x
= (rect
.GetLeft() + rect
.GetRight() + 1 - width
) / 2;
1332 else // alignment & wxALIGN_LEFT
1337 if ( alignment
& wxALIGN_BOTTOM
)
1339 y
= rect
.GetBottom() - height
;
1341 else if ( alignment
& wxALIGN_CENTRE_VERTICAL
)
1343 y
= (rect
.GetTop() + rect
.GetBottom() + 1 - height
) / 2;
1345 else // alignment & wxALIGN_TOP
1350 // draw the bitmap first
1356 DrawBitmap(bitmap
, x
, y
, true /* use mask */);
1358 wxCoord offset
= bitmap
.GetWidth() + 4;
1362 y
+= (height
- heightText
) / 2;
1365 // we will draw the underscore under the accel char later
1366 wxCoord startUnderscore
= 0,
1370 // split the string into lines and draw each of them separately
1372 for ( wxString::const_iterator pc
= text
.begin(); ; ++pc
)
1374 if ( *pc
== _T('\n') || pc
== text
.end() )
1376 int xRealStart
= x
; // init it here to avoid compielr warnings
1378 if ( !curLine
.empty() )
1380 // NB: can't test for !(alignment & wxALIGN_LEFT) because
1381 // wxALIGN_LEFT is 0
1382 if ( alignment
& (wxALIGN_RIGHT
| wxALIGN_CENTRE_HORIZONTAL
) )
1385 GetTextExtent(curLine
, &widthLine
, NULL
);
1387 if ( alignment
& wxALIGN_RIGHT
)
1389 xRealStart
+= width
- widthLine
;
1391 else // if ( alignment & wxALIGN_CENTRE_HORIZONTAL )
1393 xRealStart
+= (width
- widthLine
) / 2;
1396 //else: left aligned, nothing to do
1398 DrawText(curLine
, xRealStart
, y
);
1403 // do we have underscore in this line? we can check yUnderscore
1404 // because it is set below to just y + heightLine if we do
1405 if ( y
== yUnderscore
)
1407 // adjust the horz positions to account for the shift
1408 startUnderscore
+= xRealStart
;
1409 endUnderscore
+= xRealStart
;
1412 if ( pc
== text
.end() )
1417 else // not end of line
1419 if ( pc
- text
.begin() == indexAccel
)
1421 // remeber to draw underscore here
1422 GetTextExtent(curLine
, &startUnderscore
, NULL
);
1424 GetTextExtent(curLine
, &endUnderscore
, NULL
);
1426 yUnderscore
= y
+ heightLine
;
1435 // draw the underscore if found
1436 if ( startUnderscore
!= endUnderscore
)
1438 // it should be of the same colour as text
1439 SetPen(wxPen(GetTextForeground(), 0, wxSOLID
));
1443 DrawLine(startUnderscore
, yUnderscore
, endUnderscore
, yUnderscore
);
1446 // return bounding rect if requested
1449 *rectBounding
= wxRect(x
, y
- heightText
, widthText
, heightText
);
1452 CalcBoundingBox(x0
, y0
);
1453 CalcBoundingBox(x0
+ width0
, y0
+ height
);
1456 #if WXWIN_COMPATIBILITY_2_8
1457 // for compatibility with the old code when wxCoord was long everywhere
1458 void wxDC::GetTextExtent(const wxString
& string
,
1461 long *externalLeading
,
1462 const wxFont
*theFont
) const
1464 wxCoord x2
, y2
, descent2
, externalLeading2
;
1465 m_pimpl
->DoGetTextExtent(string
, &x2
, &y2
,
1466 &descent2
, &externalLeading2
,
1473 *descent
= descent2
;
1474 if ( externalLeading
)
1475 *externalLeading
= externalLeading2
;
1478 void wxDC::GetLogicalOrigin(long *x
, long *y
) const
1481 m_pimpl
->DoGetLogicalOrigin(&x2
, &y2
);
1488 void wxDC::GetDeviceOrigin(long *x
, long *y
) const
1491 m_pimpl
->DoGetDeviceOrigin(&x2
, &y2
);
1498 void wxDC::GetClippingBox(long *x
, long *y
, long *w
, long *h
) const
1500 wxCoord xx
,yy
,ww
,hh
;
1501 m_pimpl
->DoGetClippingBox(&xx
, &yy
, &ww
, &hh
);
1508 #endif // WXWIN_COMPATIBILITY_2_8
1511 #else // wxUSE_NEW_DC
1514 // bool wxDCBase::sm_cacheing = false;
1516 IMPLEMENT_ABSTRACT_CLASS(wxDCBase
, wxObject
)
1518 // ============================================================================
1520 // ============================================================================
1522 IMPLEMENT_DYNAMIC_CLASS(wxBufferedDC
, wxMemoryDC
)
1523 IMPLEMENT_ABSTRACT_CLASS(wxBufferedPaintDC
, wxBufferedDC
)
1525 wxDCBase::wxDCBase()
1526 : m_colour(wxColourDisplay())
1529 , m_isInteractive(0)
1530 , m_isBBoxValid(false)
1531 , m_logicalOriginX(0), m_logicalOriginY(0)
1532 , m_deviceOriginX(0), m_deviceOriginY(0)
1533 , m_deviceLocalOriginX(0), m_deviceLocalOriginY(0)
1534 , m_logicalScaleX(1.0), m_logicalScaleY(1.0)
1535 , m_userScaleX(1.0), m_userScaleY(1.0)
1536 , m_scaleX(1.0), m_scaleY(1.0)
1537 , m_signX(1), m_signY(1)
1538 , m_minX(0), m_minY(0), m_maxX(0), m_maxY(0)
1539 , m_clipX1(0), m_clipY1(0), m_clipX2(0), m_clipY2(0)
1540 , m_logicalFunction(wxCOPY
)
1541 , m_backgroundMode(wxTRANSPARENT
)
1542 , m_mappingMode(wxMM_TEXT
)
1545 , m_backgroundBrush(*wxTRANSPARENT_BRUSH
)
1546 , m_textForegroundColour(*wxBLACK
)
1547 , m_textBackgroundColour(*wxWHITE
)
1551 , m_hasCustomPalette(false)
1552 #endif // wxUSE_PALETTE
1554 m_mm_to_pix_x
= (double)wxGetDisplaySize().GetWidth() /
1555 (double)wxGetDisplaySizeMM().GetWidth();
1556 m_mm_to_pix_y
= (double)wxGetDisplaySize().GetHeight() /
1557 (double)wxGetDisplaySizeMM().GetHeight();
1563 wxDCBase::~wxDCBase()
1567 #if WXWIN_COMPATIBILITY_2_6
1568 void wxDCBase::BeginDrawing()
1572 void wxDCBase::EndDrawing()
1575 #endif // WXWIN_COMPATIBILITY_2_6
1577 #if WXWIN_COMPATIBILITY_2_8
1578 // for compatibility with the old code when wxCoord was long everywhere
1579 void wxDCBase::GetTextExtent(const wxString
& string
,
1582 long *externalLeading
,
1583 const wxFont
*theFont
) const
1585 wxCoord x2
, y2
, descent2
, externalLeading2
;
1586 DoGetTextExtent(string
, &x2
, &y2
,
1587 &descent2
, &externalLeading2
,
1594 *descent
= descent2
;
1595 if ( externalLeading
)
1596 *externalLeading
= externalLeading2
;
1599 void wxDCBase::GetLogicalOrigin(long *x
, long *y
) const
1602 DoGetLogicalOrigin(&x2
, &y2
);
1609 void wxDCBase::GetDeviceOrigin(long *x
, long *y
) const
1612 DoGetDeviceOrigin(&x2
, &y2
);
1619 void wxDCBase::GetClippingBox(long *x
, long *y
, long *w
, long *h
) const
1621 wxCoord xx
,yy
,ww
,hh
;
1622 DoGetClippingBox(&xx
, &yy
, &ww
, &hh
);
1628 #endif // WXWIN_COMPATIBILITY_2_8
1632 // ----------------------------------------------------------------------------
1633 // coordinate conversions and transforms
1634 // ----------------------------------------------------------------------------
1636 wxCoord
wxDCBase::DeviceToLogicalX(wxCoord x
) const
1638 return wxRound((double)(x
- m_deviceOriginX
- m_deviceLocalOriginX
) / m_scaleX
) * m_signX
+ m_logicalOriginX
;
1641 wxCoord
wxDCBase::DeviceToLogicalY(wxCoord y
) const
1643 return wxRound((double)(y
- m_deviceOriginY
- m_deviceLocalOriginY
) / m_scaleY
) * m_signY
+ m_logicalOriginY
;
1646 wxCoord
wxDCBase::DeviceToLogicalXRel(wxCoord x
) const
1648 return wxRound((double)(x
) / m_scaleX
);
1651 wxCoord
wxDCBase::DeviceToLogicalYRel(wxCoord y
) const
1653 return wxRound((double)(y
) / m_scaleY
);
1656 wxCoord
wxDCBase::LogicalToDeviceX(wxCoord x
) const
1658 return wxRound((double)(x
- m_logicalOriginX
) * m_scaleX
) * m_signX
+ m_deviceOriginX
+ m_deviceLocalOriginX
;
1661 wxCoord
wxDCBase::LogicalToDeviceY(wxCoord y
) const
1663 return wxRound((double)(y
- m_logicalOriginY
) * m_scaleY
) * m_signY
+ m_deviceOriginY
+ m_deviceLocalOriginY
;
1666 wxCoord
wxDCBase::LogicalToDeviceXRel(wxCoord x
) const
1668 return wxRound((double)(x
) * m_scaleX
);
1671 wxCoord
wxDCBase::LogicalToDeviceYRel(wxCoord y
) const
1673 return wxRound((double)(y
) * m_scaleY
);
1676 void wxDCBase::ComputeScaleAndOrigin()
1678 m_scaleX
= m_logicalScaleX
* m_userScaleX
;
1679 m_scaleY
= m_logicalScaleY
* m_userScaleY
;
1682 void wxDCBase::SetMapMode( int mode
)
1687 SetLogicalScale( twips2mm
*m_mm_to_pix_x
, twips2mm
*m_mm_to_pix_y
);
1690 SetLogicalScale( pt2mm
*m_mm_to_pix_x
, pt2mm
*m_mm_to_pix_y
);
1693 SetLogicalScale( m_mm_to_pix_x
, m_mm_to_pix_y
);
1696 SetLogicalScale( m_mm_to_pix_x
/10.0, m_mm_to_pix_y
/10.0 );
1700 SetLogicalScale( 1.0, 1.0 );
1703 m_mappingMode
= mode
;
1706 void wxDCBase::SetUserScale( double x
, double y
)
1708 // allow negative ? -> no
1711 ComputeScaleAndOrigin();
1714 void wxDCBase::SetLogicalScale( double x
, double y
)
1717 m_logicalScaleX
= x
;
1718 m_logicalScaleY
= y
;
1719 ComputeScaleAndOrigin();
1722 void wxDCBase::SetLogicalOrigin( wxCoord x
, wxCoord y
)
1724 m_logicalOriginX
= x
* m_signX
;
1725 m_logicalOriginY
= y
* m_signY
;
1726 ComputeScaleAndOrigin();
1729 void wxDCBase::SetDeviceOrigin( wxCoord x
, wxCoord y
)
1731 m_deviceOriginX
= x
;
1732 m_deviceOriginY
= y
;
1733 ComputeScaleAndOrigin();
1736 void wxDCBase::SetDeviceLocalOrigin( wxCoord x
, wxCoord y
)
1738 m_deviceLocalOriginX
= x
;
1739 m_deviceLocalOriginY
= y
;
1740 ComputeScaleAndOrigin();
1743 void wxDCBase::SetAxisOrientation( bool xLeftRight
, bool yBottomUp
)
1745 // only wxPostScripDC has m_signX = -1, we override SetAxisOrientation there
1746 // wxWidgets 2.9: no longer override it
1747 m_signX
= (xLeftRight
? 1 : -1);
1748 m_signY
= (yBottomUp
? -1 : 1);
1749 ComputeScaleAndOrigin();
1752 // ----------------------------------------------------------------------------
1754 // ----------------------------------------------------------------------------
1756 void wxDCBase::DoDrawCheckMark(wxCoord x1
, wxCoord y1
,
1757 wxCoord width
, wxCoord height
)
1759 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1761 wxCoord x2
= x1
+ width
,
1764 // the pen width is calibrated to give 3 for width == height == 10
1765 wxDCPenChanger
pen((wxDC
&)*this,
1766 wxPen(GetTextForeground(), (width
+ height
+ 1)/7));
1768 // we're drawing a scaled version of wx/generic/tick.xpm here
1769 wxCoord x3
= x1
+ (4*width
) / 10, // x of the tick bottom
1770 y3
= y1
+ height
/ 2; // y of the left tick branch
1771 DoDrawLine(x1
, y3
, x3
, y2
);
1772 DoDrawLine(x3
, y2
, x2
, y1
);
1774 CalcBoundingBox(x1
, y1
);
1775 CalcBoundingBox(x2
, y2
);
1778 // ----------------------------------------------------------------------------
1779 // stubs for functions not implemented in all ports
1780 // ----------------------------------------------------------------------------
1783 wxDCBase::DoStretchBlit(wxCoord xdest
, wxCoord ydest
,
1784 wxCoord dstWidth
, wxCoord dstHeight
,
1786 wxCoord xsrc
, wxCoord ysrc
,
1787 wxCoord srcWidth
, wxCoord srcHeight
,
1793 wxCHECK_MSG( srcWidth
&& srcHeight
&& dstWidth
&& dstHeight
, false,
1794 _T("invalid blit size") );
1796 // emulate the stretching by modifying the DC scale
1797 double xscale
= (double)srcWidth
/dstWidth
,
1798 yscale
= (double)srcHeight
/dstHeight
;
1800 double xscaleOld
, yscaleOld
;
1801 GetUserScale(&xscaleOld
, &yscaleOld
);
1802 SetUserScale(xscaleOld
/xscale
, yscaleOld
/yscale
);
1804 bool rc
= DoBlit(wxCoord(xdest
*xscale
), wxCoord(ydest
*yscale
),
1805 wxCoord(dstWidth
*xscale
), wxCoord(dstHeight
*yscale
),
1807 xsrc
, ysrc
, rop
, useMask
, xsrcMask
, ysrcMask
);
1809 SetUserScale(xscaleOld
, yscaleOld
);
1814 // ----------------------------------------------------------------------------
1816 // ----------------------------------------------------------------------------
1818 void wxDCBase::DrawLines(const wxPointList
*list
, wxCoord xoffset
, wxCoord yoffset
)
1820 unsigned int n
= list
->GetCount();
1821 wxPoint
*points
= new wxPoint
[n
];
1824 wxPointList::compatibility_iterator node
;
1825 for ( node
= list
->GetFirst(); node
; node
= node
->GetNext(), i
++ )
1827 wxPoint
*point
= node
->GetData();
1828 points
[i
].x
= point
->x
;
1829 points
[i
].y
= point
->y
;
1832 DoDrawLines(n
, points
, xoffset
, yoffset
);
1837 #if WXWIN_COMPATIBILITY_2_8
1838 void wxDCBase::DrawLines(const wxList
*list
, wxCoord xoffset
, wxCoord yoffset
)
1840 unsigned int n
= list
->GetCount();
1841 wxPoint
*points
= new wxPoint
[n
];
1844 wxObjectList::compatibility_iterator node
;
1845 for ( node
= list
->GetFirst(); node
; node
= node
->GetNext(), i
++ )
1847 wxPoint
*point
= (wxPoint
*) node
->GetData();
1848 points
[i
].x
= point
->x
;
1849 points
[i
].y
= point
->y
;
1852 DoDrawLines(n
, points
, xoffset
, yoffset
);
1856 #endif // WXWIN_COMPATIBILITY_2_8
1859 void wxDCBase::DrawPolygon(const wxPointList
*list
,
1860 wxCoord xoffset
, wxCoord yoffset
,
1863 unsigned int n
= list
->GetCount();
1864 wxPoint
*points
= new wxPoint
[n
];
1867 wxPointList::compatibility_iterator node
;
1868 for ( node
= list
->GetFirst(); node
; node
= node
->GetNext(), i
++ )
1870 wxPoint
*point
= node
->GetData();
1871 points
[i
].x
= point
->x
;
1872 points
[i
].y
= point
->y
;
1875 DoDrawPolygon(n
, points
, xoffset
, yoffset
, fillStyle
);
1881 #if WXWIN_COMPATIBILITY_2_8
1882 void wxDCBase::DrawPolygon(const wxList
*list
,
1883 wxCoord xoffset
, wxCoord yoffset
,
1886 unsigned int n
= list
->GetCount();
1887 wxPoint
*points
= new wxPoint
[n
];
1890 wxObjectList::compatibility_iterator node
;
1891 for ( node
= list
->GetFirst(); node
; node
= node
->GetNext(), i
++ )
1893 wxPoint
*point
= (wxPoint
*) node
->GetData();
1894 points
[i
].x
= point
->x
;
1895 points
[i
].y
= point
->y
;
1898 DoDrawPolygon(n
, points
, xoffset
, yoffset
, fillStyle
);
1902 #endif // WXWIN_COMPATIBILITY_2_8
1905 wxDCBase::DoDrawPolyPolygon(int n
,
1908 wxCoord xoffset
, wxCoord yoffset
,
1913 DoDrawPolygon(count
[0], points
, xoffset
, yoffset
, fillStyle
);
1921 for (i
= j
= lastOfs
= 0; i
< n
; i
++)
1926 pts
= new wxPoint
[j
+n
-1];
1927 for (i
= 0; i
< j
; i
++)
1929 for (i
= 2; i
<= n
; i
++)
1931 lastOfs
-= count
[n
-i
];
1932 pts
[j
++] = pts
[lastOfs
];
1936 SetPen(wxPen(*wxBLACK
, 0, wxTRANSPARENT
));
1937 DoDrawPolygon(j
, pts
, xoffset
, yoffset
, fillStyle
);
1939 for (i
= j
= 0; i
< n
; i
++)
1941 DoDrawLines(count
[i
], pts
+j
, xoffset
, yoffset
);
1947 // ----------------------------------------------------------------------------
1949 // ----------------------------------------------------------------------------
1953 void wxDCBase::DrawSpline(wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
, wxCoord x3
, wxCoord y3
)
1955 wxPointList point_list
;
1957 wxPoint
*point1
= new wxPoint
;
1958 point1
->x
= x1
; point1
->y
= y1
;
1959 point_list
.Append( point1
);
1961 wxPoint
*point2
= new wxPoint
;
1962 point2
->x
= x2
; point2
->y
= y2
;
1963 point_list
.Append( point2
);
1965 wxPoint
*point3
= new wxPoint
;
1966 point3
->x
= x3
; point3
->y
= y3
;
1967 point_list
.Append( point3
);
1969 DrawSpline(&point_list
);
1971 for( wxPointList::compatibility_iterator node
= point_list
.GetFirst(); node
; node
= node
->GetNext() )
1973 wxPoint
*p
= node
->GetData();
1978 void wxDCBase::DrawSpline(int n
, wxPoint points
[])
1981 for (int i
=0; i
< n
; i
++)
1982 list
.Append( &points
[i
] );
1987 // ----------------------------------- spline code ----------------------------------------
1989 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
,
1990 double a3
, double b3
, double a4
, double b4
);
1991 void wx_clear_stack();
1992 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
, double *x3
,
1993 double *y3
, double *x4
, double *y4
);
1994 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
,
1995 double x4
, double y4
);
1996 static bool wx_spline_add_point(double x
, double y
);
1997 static void wx_spline_draw_point_array(wxDCBase
*dc
);
1999 wxPointList wx_spline_point_list
;
2001 #define half(z1, z2) ((z1+z2)/2.0)
2004 /* iterative version */
2006 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
, double a3
, double b3
, double a4
,
2009 register double xmid
, ymid
;
2010 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
2013 wx_spline_push(a1
, b1
, a2
, b2
, a3
, b3
, a4
, b4
);
2015 while (wx_spline_pop(&x1
, &y1
, &x2
, &y2
, &x3
, &y3
, &x4
, &y4
)) {
2016 xmid
= (double)half(x2
, x3
);
2017 ymid
= (double)half(y2
, y3
);
2018 if (fabs(x1
- xmid
) < THRESHOLD
&& fabs(y1
- ymid
) < THRESHOLD
&&
2019 fabs(xmid
- x4
) < THRESHOLD
&& fabs(ymid
- y4
) < THRESHOLD
) {
2020 wx_spline_add_point( x1
, y1
);
2021 wx_spline_add_point( xmid
, ymid
);
2023 wx_spline_push(xmid
, ymid
, (double)half(xmid
, x3
), (double)half(ymid
, y3
),
2024 (double)half(x3
, x4
), (double)half(y3
, y4
), x4
, y4
);
2025 wx_spline_push(x1
, y1
, (double)half(x1
, x2
), (double)half(y1
, y2
),
2026 (double)half(x2
, xmid
), (double)half(y2
, ymid
), xmid
, ymid
);
2031 /* utilities used by spline drawing routines */
2033 typedef struct wx_spline_stack_struct
{
2034 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
2037 #define SPLINE_STACK_DEPTH 20
2038 static Stack wx_spline_stack
[SPLINE_STACK_DEPTH
];
2039 static Stack
*wx_stack_top
;
2040 static int wx_stack_count
;
2042 void wx_clear_stack()
2044 wx_stack_top
= wx_spline_stack
;
2048 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
, double x4
, double y4
)
2050 wx_stack_top
->x1
= x1
;
2051 wx_stack_top
->y1
= y1
;
2052 wx_stack_top
->x2
= x2
;
2053 wx_stack_top
->y2
= y2
;
2054 wx_stack_top
->x3
= x3
;
2055 wx_stack_top
->y3
= y3
;
2056 wx_stack_top
->x4
= x4
;
2057 wx_stack_top
->y4
= y4
;
2062 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
,
2063 double *x3
, double *y3
, double *x4
, double *y4
)
2065 if (wx_stack_count
== 0)
2069 *x1
= wx_stack_top
->x1
;
2070 *y1
= wx_stack_top
->y1
;
2071 *x2
= wx_stack_top
->x2
;
2072 *y2
= wx_stack_top
->y2
;
2073 *x3
= wx_stack_top
->x3
;
2074 *y3
= wx_stack_top
->y3
;
2075 *x4
= wx_stack_top
->x4
;
2076 *y4
= wx_stack_top
->y4
;
2080 static bool wx_spline_add_point(double x
, double y
)
2082 wxPoint
*point
= new wxPoint( wxRound(x
), wxRound(y
) );
2083 wx_spline_point_list
.Append( point
);
2087 static void wx_spline_draw_point_array(wxDCBase
*dc
)
2089 dc
->DrawLines(&wx_spline_point_list
, 0, 0 );
2090 wxPointList::compatibility_iterator node
= wx_spline_point_list
.GetFirst();
2093 wxPoint
*point
= node
->GetData();
2095 wx_spline_point_list
.Erase(node
);
2096 node
= wx_spline_point_list
.GetFirst();
2100 #if WXWIN_COMPATIBILITY_2_8
2101 void wxDCBase::DrawSpline(const wxList
*points
)
2104 wxObjectList::compatibility_iterator node
= points
->GetFirst();
2107 list
.Append( (wxPoint
*) node
->GetData() );
2108 node
= node
->GetNext();
2110 DoDrawSpline( &list
);
2112 #endif // WXWIN_COMPATIBILITY_2_8
2114 void wxDCBase::DoDrawSpline( const wxPointList
*points
)
2116 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2119 double cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
;
2120 double x1
, y1
, x2
, y2
;
2122 wxPointList::compatibility_iterator node
= points
->GetFirst();
2127 p
= node
->GetData();
2132 node
= node
->GetNext();
2133 p
= node
->GetData();
2137 cx1
= (double)((x1
+ x2
) / 2);
2138 cy1
= (double)((y1
+ y2
) / 2);
2139 cx2
= (double)((cx1
+ x2
) / 2);
2140 cy2
= (double)((cy1
+ y2
) / 2);
2142 wx_spline_add_point(x1
, y1
);
2144 while ((node
= node
->GetNext())
2147 #endif // !wxUSE_STL
2150 p
= node
->GetData();
2155 cx4
= (double)(x1
+ x2
) / 2;
2156 cy4
= (double)(y1
+ y2
) / 2;
2157 cx3
= (double)(x1
+ cx4
) / 2;
2158 cy3
= (double)(y1
+ cy4
) / 2;
2160 wx_quadratic_spline(cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
);
2164 cx2
= (double)(cx1
+ x2
) / 2;
2165 cy2
= (double)(cy1
+ y2
) / 2;
2168 wx_spline_add_point( cx1
, cy1
);
2169 wx_spline_add_point( x2
, y2
);
2171 wx_spline_draw_point_array( this );
2174 #endif // wxUSE_SPLINES
2176 // ----------------------------------------------------------------------------
2177 // Partial Text Extents
2178 // ----------------------------------------------------------------------------
2181 // Each element of the widths array will be the width of the string up to and
2182 // including the corresponding character in text. This is the generic
2183 // implementation, the port-specific classes should do this with native APIs
2184 // if available and if faster. Note: pango_layout_index_to_pos is much slower
2185 // than calling GetTextExtent!!
2187 #define FWC_SIZE 256
2189 class FontWidthCache
2192 FontWidthCache() : m_scaleX(1), m_widths(NULL
) { }
2193 ~FontWidthCache() { delete []m_widths
; }
2198 m_widths
= new int[FWC_SIZE
];
2200 memset(m_widths
, 0, sizeof(int)*FWC_SIZE
);
2208 static FontWidthCache s_fontWidthCache
;
2210 bool wxDCBase::DoGetPartialTextExtents(const wxString
& text
, wxArrayInt
& widths
) const
2214 const size_t len
= text
.length();
2218 // reset the cache if font or horizontal scale have changed
2219 if ( !s_fontWidthCache
.m_widths
||
2220 !wxIsSameDouble(s_fontWidthCache
.m_scaleX
, m_scaleX
) ||
2221 (s_fontWidthCache
.m_font
!= GetFont()) )
2223 s_fontWidthCache
.Reset();
2224 s_fontWidthCache
.m_font
= GetFont();
2225 s_fontWidthCache
.m_scaleX
= m_scaleX
;
2228 // Calculate the position of each character based on the widths of
2229 // the previous characters
2231 for ( size_t i
= 0; i
< len
; i
++ )
2233 const wxChar c
= text
[i
];
2234 unsigned int c_int
= (unsigned int)c
;
2236 if ((c_int
< FWC_SIZE
) && (s_fontWidthCache
.m_widths
[c_int
] != 0))
2238 w
= s_fontWidthCache
.m_widths
[c_int
];
2242 GetTextExtent(c
, &w
, &h
);
2243 if (c_int
< FWC_SIZE
)
2244 s_fontWidthCache
.m_widths
[c_int
] = w
;
2248 widths
[i
] = totalWidth
;
2255 // ----------------------------------------------------------------------------
2256 // enhanced text drawing
2257 // ----------------------------------------------------------------------------
2259 void wxDCBase::GetMultiLineTextExtent(const wxString
& text
,
2263 const wxFont
*font
) const
2265 wxCoord widthTextMax
= 0, widthLine
,
2266 heightTextTotal
= 0, heightLineDefault
= 0, heightLine
= 0;
2269 for ( wxString::const_iterator pc
= text
.begin(); ; ++pc
)
2271 if ( pc
== text
.end() || *pc
== _T('\n') )
2273 if ( curLine
.empty() )
2275 // we can't use GetTextExtent - it will return 0 for both width
2276 // and height and an empty line should count in height
2279 // assume that this line has the same height as the previous
2281 if ( !heightLineDefault
)
2282 heightLineDefault
= heightLine
;
2284 if ( !heightLineDefault
)
2286 // but we don't know it yet - choose something reasonable
2287 GetTextExtent(_T("W"), NULL
, &heightLineDefault
,
2291 heightTextTotal
+= heightLineDefault
;
2295 GetTextExtent(curLine
, &widthLine
, &heightLine
,
2297 if ( widthLine
> widthTextMax
)
2298 widthTextMax
= widthLine
;
2299 heightTextTotal
+= heightLine
;
2302 if ( pc
== text
.end() )
2320 *y
= heightTextTotal
;
2325 void wxDCBase::DrawLabel(const wxString
& text
,
2326 const wxBitmap
& bitmap
,
2330 wxRect
*rectBounding
)
2332 // find the text position
2333 wxCoord widthText
, heightText
, heightLine
;
2334 GetMultiLineTextExtent(text
, &widthText
, &heightText
, &heightLine
);
2336 wxCoord width
, height
;
2339 width
= widthText
+ bitmap
.GetWidth();
2340 height
= bitmap
.GetHeight();
2345 height
= heightText
;
2349 if ( alignment
& wxALIGN_RIGHT
)
2351 x
= rect
.GetRight() - width
;
2353 else if ( alignment
& wxALIGN_CENTRE_HORIZONTAL
)
2355 x
= (rect
.GetLeft() + rect
.GetRight() + 1 - width
) / 2;
2357 else // alignment & wxALIGN_LEFT
2362 if ( alignment
& wxALIGN_BOTTOM
)
2364 y
= rect
.GetBottom() - height
;
2366 else if ( alignment
& wxALIGN_CENTRE_VERTICAL
)
2368 y
= (rect
.GetTop() + rect
.GetBottom() + 1 - height
) / 2;
2370 else // alignment & wxALIGN_TOP
2375 // draw the bitmap first
2381 DrawBitmap(bitmap
, x
, y
, true /* use mask */);
2383 wxCoord offset
= bitmap
.GetWidth() + 4;
2387 y
+= (height
- heightText
) / 2;
2390 // we will draw the underscore under the accel char later
2391 wxCoord startUnderscore
= 0,
2395 // split the string into lines and draw each of them separately
2397 for ( wxString::const_iterator pc
= text
.begin(); ; ++pc
)
2399 if ( pc
== text
.end() || *pc
== _T('\n') )
2401 int xRealStart
= x
; // init it here to avoid compielr warnings
2403 if ( !curLine
.empty() )
2405 // NB: can't test for !(alignment & wxALIGN_LEFT) because
2406 // wxALIGN_LEFT is 0
2407 if ( alignment
& (wxALIGN_RIGHT
| wxALIGN_CENTRE_HORIZONTAL
) )
2410 GetTextExtent(curLine
, &widthLine
, NULL
);
2412 if ( alignment
& wxALIGN_RIGHT
)
2414 xRealStart
+= width
- widthLine
;
2416 else // if ( alignment & wxALIGN_CENTRE_HORIZONTAL )
2418 xRealStart
+= (width
- widthLine
) / 2;
2421 //else: left aligned, nothing to do
2423 DrawText(curLine
, xRealStart
, y
);
2428 // do we have underscore in this line? we can check yUnderscore
2429 // because it is set below to just y + heightLine if we do
2430 if ( y
== yUnderscore
)
2432 // adjust the horz positions to account for the shift
2433 startUnderscore
+= xRealStart
;
2434 endUnderscore
+= xRealStart
;
2437 if ( pc
== text
.end() )
2442 else // not end of line
2444 if ( pc
- text
.begin() == indexAccel
)
2446 // remeber to draw underscore here
2447 GetTextExtent(curLine
, &startUnderscore
, NULL
);
2449 GetTextExtent(curLine
, &endUnderscore
, NULL
);
2451 yUnderscore
= y
+ heightLine
;
2460 // draw the underscore if found
2461 if ( startUnderscore
!= endUnderscore
)
2463 // it should be of the same colour as text
2464 SetPen(wxPen(GetTextForeground(), 0, wxSOLID
));
2468 DrawLine(startUnderscore
, yUnderscore
, endUnderscore
, yUnderscore
);
2471 // return bounding rect if requested
2474 *rectBounding
= wxRect(x
, y
- heightText
, widthText
, heightText
);
2477 CalcBoundingBox(x0
, y0
);
2478 CalcBoundingBox(x0
+ width0
, y0
+ height
);
2482 void wxDCBase::DoGradientFillLinear(const wxRect
& rect
,
2483 const wxColour
& initialColour
,
2484 const wxColour
& destColour
,
2485 wxDirection nDirection
)
2488 wxPen oldPen
= m_pen
;
2489 wxBrush oldBrush
= m_brush
;
2491 wxUint8 nR1
= initialColour
.Red();
2492 wxUint8 nG1
= initialColour
.Green();
2493 wxUint8 nB1
= initialColour
.Blue();
2494 wxUint8 nR2
= destColour
.Red();
2495 wxUint8 nG2
= destColour
.Green();
2496 wxUint8 nB2
= destColour
.Blue();
2499 if ( nDirection
== wxEAST
|| nDirection
== wxWEST
)
2501 wxInt32 x
= rect
.GetWidth();
2502 wxInt32 w
= x
; // width of area to shade
2503 wxInt32 xDelta
= w
/256; // height of one shade bend
2511 nR
= nR1
- (nR1
-nR2
)*(w
-x
)/w
;
2513 nR
= nR1
+ (nR2
-nR1
)*(w
-x
)/w
;
2516 nG
= nG1
- (nG1
-nG2
)*(w
-x
)/w
;
2518 nG
= nG1
+ (nG2
-nG1
)*(w
-x
)/w
;
2521 nB
= nB1
- (nB1
-nB2
)*(w
-x
)/w
;
2523 nB
= nB1
+ (nB2
-nB1
)*(w
-x
)/w
;
2525 wxColour
colour(nR
,nG
,nB
);
2526 SetPen(wxPen(colour
, 1, wxSOLID
));
2527 SetBrush(wxBrush(colour
));
2528 if(nDirection
== wxEAST
)
2529 DrawRectangle(rect
.GetRight()-x
-xDelta
+1, rect
.GetTop(),
2530 xDelta
, rect
.GetHeight());
2531 else //nDirection == wxWEST
2532 DrawRectangle(rect
.GetLeft()+x
, rect
.GetTop(),
2533 xDelta
, rect
.GetHeight());
2536 else // nDirection == wxNORTH || nDirection == wxSOUTH
2538 wxInt32 y
= rect
.GetHeight();
2539 wxInt32 w
= y
; // height of area to shade
2540 wxInt32 yDelta
= w
/255; // height of one shade bend
2548 nR
= nR1
- (nR1
-nR2
)*(w
-y
)/w
;
2550 nR
= nR1
+ (nR2
-nR1
)*(w
-y
)/w
;
2553 nG
= nG1
- (nG1
-nG2
)*(w
-y
)/w
;
2555 nG
= nG1
+ (nG2
-nG1
)*(w
-y
)/w
;
2558 nB
= nB1
- (nB1
-nB2
)*(w
-y
)/w
;
2560 nB
= nB1
+ (nB2
-nB1
)*(w
-y
)/w
;
2562 wxColour
colour(nR
,nG
,nB
);
2563 SetPen(wxPen(colour
, 1, wxSOLID
));
2564 SetBrush(wxBrush(colour
));
2565 if(nDirection
== wxNORTH
)
2566 DrawRectangle(rect
.GetLeft(), rect
.GetTop()+y
,
2567 rect
.GetWidth(), yDelta
);
2568 else //nDirection == wxSOUTH
2569 DrawRectangle(rect
.GetLeft(), rect
.GetBottom()-y
-yDelta
+1,
2570 rect
.GetWidth(), yDelta
);
2578 void wxDCBase::DoGradientFillConcentric(const wxRect
& rect
,
2579 const wxColour
& initialColour
,
2580 const wxColour
& destColour
,
2581 const wxPoint
& circleCenter
)
2583 //save the old pen color
2584 wxColour oldPenColour
= m_pen
.GetColour();
2586 wxUint8 nR1
= destColour
.Red();
2587 wxUint8 nG1
= destColour
.Green();
2588 wxUint8 nB1
= destColour
.Blue();
2589 wxUint8 nR2
= initialColour
.Red();
2590 wxUint8 nG2
= initialColour
.Green();
2591 wxUint8 nB2
= initialColour
.Blue();
2596 wxInt32 cx
= rect
.GetWidth() / 2;
2597 wxInt32 cy
= rect
.GetHeight() / 2;
2605 wxInt32 nCircleOffX
= circleCenter
.x
- (rect
.GetWidth() / 2);
2606 wxInt32 nCircleOffY
= circleCenter
.y
- (rect
.GetHeight() / 2);
2608 for ( wxInt32 x
= 0; x
< rect
.GetWidth(); x
++ )
2610 for ( wxInt32 y
= 0; y
< rect
.GetHeight(); y
++ )
2612 //get color difference
2613 wxInt32 nGradient
= ((nRadius
-
2615 pow((double)(x
- cx
- nCircleOffX
), 2) +
2616 pow((double)(y
- cy
- nCircleOffY
), 2)
2617 )) * 100) / nRadius
;
2619 //normalize Gradient
2624 nR
= (wxUint8
)(nR1
+ ((nR2
- nR1
) * nGradient
/ 100));
2625 nG
= (wxUint8
)(nG1
+ ((nG2
- nG1
) * nGradient
/ 100));
2626 nB
= (wxUint8
)(nB1
+ ((nB2
- nB1
) * nGradient
/ 100));
2629 m_pen
.SetColour(wxColour(nR
,nG
,nB
));
2630 DrawPoint(wxPoint(x
+ rect
.GetLeft(), y
+ rect
.GetTop()));
2633 //return old pen color
2634 m_pen
.SetColour(oldPenColour
);
2638 Notes for wxWidgets DrawEllipticArcRot(...)
2640 wxDCBase::DrawEllipticArcRot(...) draws a rotated elliptic arc or an ellipse.
2641 It uses wxDCBase::CalculateEllipticPoints(...) and wxDCBase::Rotate(...),
2644 All methods are generic, so they can be implemented in wxDCBase.
2645 DoDrawEllipticArcRot(...) is virtual, so it can be called from deeper
2646 methods like (WinCE) wxDC::DoDrawArc(...).
2648 CalculateEllipticPoints(...) fills a given list of wxPoints with some points
2649 of an elliptic arc. The algorithm is pixel-based: In every row (in flat
2650 parts) or every column (in steep parts) only one pixel is calculated.
2651 Trigonometric calculation (sin, cos, tan, atan) is only done if the
2652 starting angle is not equal to the ending angle. The calculation of the
2653 pixels is done using simple arithmetic only and should perform not too
2654 bad even on devices without floating point processor. I didn't test this yet.
2656 Rotate(...) rotates a list of point pixel-based, you will see rounding errors.
2657 For instance: an ellipse rotated 180 degrees is drawn
2658 slightly different from the original.
2660 The points are then moved to an array and used to draw a polyline and/or polygon
2661 (with center added, the pie).
2662 The result looks quite similar to the native ellipse, only e few pixels differ.
2664 The performance on a desktop system (Athlon 1800, WinXP) is about 7 times
2665 slower as DrawEllipse(...), which calls the native API.
2666 An rotated ellipse outside the clipping region takes nearly the same time,
2667 while an native ellipse outside takes nearly no time to draw.
2669 If you draw an arc with this new method, you will see the starting and ending angles
2670 are calculated properly.
2671 If you use DrawEllipticArc(...), you will see they are only correct for circles
2672 and not properly calculated for ellipses.
2675 p.lenhard@t-online.de
2679 void wxDCBase::DoDrawEllipticArcRot( wxCoord x
, wxCoord y
,
2680 wxCoord w
, wxCoord h
,
2681 double sa
, double ea
, double angle
)
2685 CalculateEllipticPoints( &list
, x
, y
, w
, h
, sa
, ea
);
2686 Rotate( &list
, angle
, wxPoint( x
+w
/2, y
+h
/2 ) );
2688 // Add center (for polygon/pie)
2689 list
.Append( new wxPoint( x
+w
/2, y
+h
/2 ) );
2691 // copy list into array and delete list elements
2692 int n
= list
.GetCount();
2693 wxPoint
*points
= new wxPoint
[n
];
2695 wxPointList::compatibility_iterator node
;
2696 for ( node
= list
.GetFirst(); node
; node
= node
->GetNext(), i
++ )
2698 wxPoint
*point
= node
->GetData();
2699 points
[i
].x
= point
->x
;
2700 points
[i
].y
= point
->y
;
2704 // first draw the pie without pen, if necessary
2705 if( GetBrush() != *wxTRANSPARENT_BRUSH
)
2707 wxPen
tempPen( GetPen() );
2708 SetPen( *wxTRANSPARENT_PEN
);
2709 DoDrawPolygon( n
, points
, 0, 0 );
2713 // then draw the arc without brush, if necessary
2714 if( GetPen() != *wxTRANSPARENT_PEN
)
2717 DoDrawLines( n
-1, points
, 0, 0 );
2722 } // DrawEllipticArcRot
2724 void wxDCBase::Rotate( wxPointList
* points
, double angle
, wxPoint center
)
2729 double dSinA
= -sin(angle
*2.0*pi
/360.0);
2730 double dCosA
= cos(angle
*2.0*pi
/360.0);
2731 wxPointList::compatibility_iterator node
;
2732 for ( node
= points
->GetFirst(); node
; node
= node
->GetNext() )
2734 wxPoint
* point
= node
->GetData();
2736 // transform coordinates, if necessary
2737 if( center
.x
) point
->x
-= center
.x
;
2738 if( center
.y
) point
->y
-= center
.y
;
2740 // calculate rotation, rounding simply by implicit cast to integer
2741 int xTemp
= point
->x
* dCosA
- point
->y
* dSinA
;
2742 point
->y
= point
->x
* dSinA
+ point
->y
* dCosA
;
2745 // back transform coordinates, if necessary
2746 if( center
.x
) point
->x
+= center
.x
;
2747 if( center
.y
) point
->y
+= center
.y
;
2752 void wxDCBase::CalculateEllipticPoints( wxPointList
* points
,
2753 wxCoord xStart
, wxCoord yStart
,
2754 wxCoord w
, wxCoord h
,
2755 double sa
, double ea
)
2766 bool bUseAngles
= false;
2772 // decrement 1 pixel if ellipse is smaller than 2*a, 2*b
2774 if( 2*a
== w
) decrX
= 1;
2776 if( 2*b
== h
) decrY
= 1;
2778 wxCoord xCenter
= xStart
+ a
;
2779 wxCoord yCenter
= yStart
+ b
;
2780 // calculate data for start and end, if necessary
2784 // normalisation of angles
2785 while( sa
<0 ) sa
+= 360;
2786 while( ea
<0 ) ea
+= 360;
2787 while( sa
>=360 ) sa
-= 360;
2788 while( ea
>=360 ) ea
-= 360;
2789 // calculate quadrant numbers
2790 if( sa
> 270 ) sq
= 3;
2791 else if( sa
> 180 ) sq
= 2;
2792 else if( sa
> 90 ) sq
= 1;
2793 if( ea
> 270 ) eq
= 3;
2794 else if( ea
> 180 ) eq
= 2;
2795 else if( ea
> 90 ) eq
= 1;
2796 sar
= sa
* pi
/ 180.0;
2797 ear
= ea
* pi
/ 180.0;
2798 // correct angle circle -> ellipse
2799 sar
= atan( -a
/(double)b
* tan( sar
) );
2800 if ( sq
== 1 || sq
== 2 ) sar
+= pi
;
2801 ear
= atan( -a
/(double)b
* tan( ear
) );
2802 if ( eq
== 1 || eq
== 2 ) ear
+= pi
;
2803 // coordinates of points
2804 xsa
= xCenter
+ a
* cos( sar
);
2805 if( sq
== 0 || sq
== 3 ) xsa
-= decrX
;
2806 ysa
= yCenter
+ b
* sin( sar
);
2807 if( sq
== 2 || sq
== 3 ) ysa
-= decrY
;
2808 xea
= xCenter
+ a
* cos( ear
);
2809 if( eq
== 0 || eq
== 3 ) xea
-= decrX
;
2810 yea
= yCenter
+ b
* sin( ear
);
2811 if( eq
== 2 || eq
== 3 ) yea
-= decrY
;
2813 // calculate c1 = b^2, c2 = b^2/a^2 with a = w/2, b = h/2
2815 double c2
= 2.0 / w
;
2824 // Lists for quadrant 1 to 4
2825 wxPointList pointsarray
[4];
2826 // Calculate points for first quadrant and set in all quadrants
2827 for( x
= 0; x
<= a
; ++x
)
2832 bool bNewPoint
= false;
2833 while( y2
> c1
- c2
* x2
&& y
> 0 )
2839 // old y now to big: set point with old y, old x
2840 if( bNewPoint
&& x
>1)
2843 // remove points on the same line
2844 pointsarray
[0].Insert( new wxPoint( xCenter
+ x1
- decrX
, yCenter
- y_old
) );
2845 pointsarray
[1].Append( new wxPoint( xCenter
- x1
, yCenter
- y_old
) );
2846 pointsarray
[2].Insert( new wxPoint( xCenter
- x1
, yCenter
+ y_old
- decrY
) );
2847 pointsarray
[3].Append( new wxPoint( xCenter
+ x1
- decrX
, yCenter
+ y_old
- decrY
) );
2849 } // calculate point
2851 // Starting and/or ending points for the quadrants, first quadrant gets both.
2852 pointsarray
[0].Insert( new wxPoint( xCenter
+ a
- decrX
, yCenter
) );
2853 pointsarray
[0].Append( new wxPoint( xCenter
, yCenter
- b
) );
2854 pointsarray
[1].Append( new wxPoint( xCenter
- a
, yCenter
) );
2855 pointsarray
[2].Append( new wxPoint( xCenter
, yCenter
+ b
- decrY
) );
2856 pointsarray
[3].Append( new wxPoint( xCenter
+ a
- decrX
, yCenter
) );
2858 // copy quadrants in original list
2861 // Copy the right part of the points in the lists
2862 // and delete the wxPoints, because they do not leave this method.
2863 points
->Append( new wxPoint( xsa
, ysa
) );
2865 bool bStarted
= false;
2866 bool bReady
= false;
2867 bool bForceTurn
= ( sq
== eq
&& sa
> ea
);
2870 wxPointList::compatibility_iterator node
;
2871 for( node
= pointsarray
[q
].GetFirst(); node
; node
= node
->GetNext() )
2873 // once: go to starting point in start quadrant
2876 node
->GetData()->x
< xsa
+1 && q
<= 1
2878 node
->GetData()->x
> xsa
-1 && q
>= 2
2885 // copy point, if not at ending point
2888 if( q
!= eq
|| bForceTurn
2890 ( (wxPoint
*) node
->GetData() )->x
> xea
+1 && q
<= 1
2892 ( (wxPoint
*) node
->GetData() )->x
< xea
-1 && q
>= 2
2896 wxPoint
* pPoint
= new wxPoint( *(node
->GetData()) );
2897 points
->Append( pPoint
);
2899 else if( q
== eq
&& !bForceTurn
|| node
->GetData()->x
== xea
)
2909 } // while not bReady
2910 points
->Append( new wxPoint( xea
, yea
) );
2913 for( q
= 0; q
< 4; ++q
)
2915 wxPointList::compatibility_iterator node
;
2916 for( node
= pointsarray
[q
].GetFirst(); node
; node
= node
->GetNext() )
2918 wxPoint
*p
= node
->GetData();
2925 wxPointList::compatibility_iterator node
;
2926 // copy whole ellipse, wxPoints will be deleted outside
2927 for( node
= pointsarray
[0].GetFirst(); node
; node
= node
->GetNext() )
2929 wxPoint
*p
= node
->GetData();
2930 points
->Append( p
);
2932 for( node
= pointsarray
[1].GetFirst(); node
; node
= node
->GetNext() )
2934 wxPoint
*p
= node
->GetData();
2935 points
->Append( p
);
2937 for( node
= pointsarray
[2].GetFirst(); node
; node
= node
->GetNext() )
2939 wxPoint
*p
= node
->GetData();
2940 points
->Append( p
);
2942 for( node
= pointsarray
[3].GetFirst(); node
; node
= node
->GetNext() )
2944 wxPoint
*p
= node
->GetData();
2945 points
->Append( p
);
2948 } // CalculateEllipticPoints
2950 #endif // __WXWINCE__
2952 #endif // wxUSE_NEW_DC