1 /////////////////////////////////////////////////////////////////////////////
4 // Author: Robert Roebling
6 // Copyright: (c) 1998 Robert Roebling
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
10 // For compilers that support precompilation, includes "wx.h".
11 #include "wx/wxprec.h"
18 //----------------------------------------------------------------------------
20 //----------------------------------------------------------------------------
22 wxDCFactory
*wxDCFactory::m_factory
= NULL
;
24 void wxDCFactory::SetDCFactory( wxDCFactory
*factory
)
26 if (wxDCFactory::m_factory
)
27 delete wxDCFactory::m_factory
;
29 wxDCFactory::m_factory
= factory
;
32 wxDCFactory
*wxDCFactory::GetFactory()
34 if (!wxDCFactory::m_factory
)
35 wxDCFactory::m_factory
= new wxNativeDCFactory
;
37 return wxDCFactory::m_factory
;
40 //-----------------------------------------------------------------------------
42 //-----------------------------------------------------------------------------
44 wxImplDC
* wxNativeDCFactory::CreateWindowDC( wxWindow
*window
)
46 #if defined(__WXMSW__)
47 return new wxWindowsWindowImplDC( window
);
48 #elif defined(__WXGTK20__)
49 return new wxGTKWindowImplDC( window
);
50 #elif defined(__WXGTK__)
51 return new wxGTKWindowImplDC( window
);
52 #elif defined(__WXMAC__)
53 return new wxMacWindowImplDC( window
);
54 #elif defined(__WXCOCOA__)
55 return new wxCocoaWindowImplDC( window
);
56 #elif defined(__WXMOTIF__)
57 return new wxMotifWindowImplDC( window
);
58 #elif defined(__WXX11__)
59 return new wxX11WindowImplDC( window
);
60 #elif defined(__WXMGL__)
61 return new wxMGLWindowImplDC( window
);
62 #elif defined(__WXDFB__)
63 return new wxDFBWindowImplDC( window
);
64 #elif defined(__WXPM__)
65 return new wxPMWindowImplDC( window
);
66 #elif defined(__PALMOS__)
67 return new wxPalmWindowImplDC( window
);
71 wxImplDC
* wxNativeDCFactory::CreateClientDC( wxWindow
*window
)
73 #if defined(__WXMSW__)
74 return new wxWindowsClientImplDC( window
);
75 #elif defined(__WXGTK20__)
76 return new wxGTKClientImplDC( window
);
77 #elif defined(__WXGTK__)
78 return new wxGTKClientImplDC( window
);
79 #elif defined(__WXMAC__)
80 return new wxMacClientImplDC( window
);
81 #elif defined(__WXCOCOA__)
82 return new wxCocoaClientImplDC( window
);
83 #elif defined(__WXMOTIF__)
84 return new wxMotifClientImplDC( window
);
85 #elif defined(__WXX11__)
86 return new wxX11ClientImplDC( window
);
87 #elif defined(__WXMGL__)
88 return new wxMGLClientImplDC( window
);
89 #elif defined(__WXDFB__)
90 return new wxDFBClientImplDC( window
);
91 #elif defined(__WXPM__)
92 return new wxPMClientImplDC( window
);
93 #elif defined(__PALMOS__)
94 return new wxPalmClientImplDC( window
);
98 wxImplDC
* wxNativeDCFactory::CreatePaintDC( wxWindow
*window
)
100 #if defined(__WXMSW__)
101 return new wxWindowsPaintImplDC( window
);
102 #elif defined(__WXGTK20__)
103 return new wxGTKPaintImplDC( window
);
104 #elif defined(__WXGTK__)
105 return new wxGTKPaintImplDC( window
);
106 #elif defined(__WXMAC__)
107 return new wxMacPaintImplDC( window
);
108 #elif defined(__WXCOCOA__)
109 return new wxCocoaPaintImplDC( window
);
110 #elif defined(__WXMOTIF__)
111 return new wxMotifPaintImplDC( window
);
112 #elif defined(__WXX11__)
113 return new wxX11PaintImplDC( window
);
114 #elif defined(__WXMGL__)
115 return new wxMGLPaintImplDC( window
);
116 #elif defined(__WXDFB__)
117 return new wxDFBPaintImplDC( window
);
118 #elif defined(__WXPM__)
119 return new wxPMPaintImplDC( window
);
120 #elif defined(__PALMOS__)
121 return new wxPalmPaintImplDC( window
);
125 wxImplDC
* wxNativeDCFactory::CreateMemoryDC()
127 #if defined(__WXMSW__)
128 return new wxWindowsMemoryImplDC();
129 #elif defined(__WXGTK20__)
130 return new wxGTKMemoryImplDC();
131 #elif defined(__WXGTK__)
132 return new wxGTKMemoryImplDC();
133 #elif defined(__WXMAC__)
134 return new wxMacMemoryImplDC();
135 #elif defined(__WXCOCOA__)
136 return new wxCocoaMemoryImplDC();
137 #elif defined(__WXMOTIF__)
138 return new wxMotifMemoryImplDC();
139 #elif defined(__WXX11__)
140 return new wxX11MemoryImplDC();
141 #elif defined(__WXMGL__)
142 return new wxMGLMemoryImplDC();
143 #elif defined(__WXDFB__)
144 return new wxDFBMemoryImplDC();
145 #elif defined(__WXPM__)
146 return new wxPMMemoryImplDC();
147 #elif defined(__PALMOS__)
148 return new wxPalmMemoryImplDC();
152 wxImplDC
* wxNativeDCFactory::CreateMemoryDC( wxBitmap
&bitmap
)
154 #if defined(__WXMSW__)
155 return new wxWindowsMemoryImplDC( bitmap
);
156 #elif defined(__WXGTK20__)
157 return new wxGTKMemoryImplDC( bitmap
);
158 #elif defined(__WXGTK__)
159 return new wxGTKMemoryImplDC( bitmap
);
160 #elif defined(__WXMAC__)
161 return new wxMacMemoryImplDC( bitmap
);
162 #elif defined(__WXCOCOA__)
163 return new wxCocoaMemoryImplDC( bitmap
);
164 #elif defined(__WXMOTIF__)
165 return new wxMotifMemoryImplDC( bitmap
);
166 #elif defined(__WXX11__)
167 return new wxX11MemoryImplDC( bitmap
);
168 #elif defined(__WXMGL__)
169 return new wxMGLMemoryImplDC( bitmap
);
170 #elif defined(__WXDFB__)
171 return new wxDFBMemoryImplDC( bitmap
);
172 #elif defined(__WXPM__)
173 return new wxPMMemoryImplDC( bitmap
);
174 #elif defined(__PALMOS__)
175 return new wxPalmMemoryImplDC( bitmap
);
179 wxImplDC
* wxNativeDCFactory::CreateMemoryDC( wxDC
*dc
)
181 #if defined(__WXMSW__)
182 return new wxWindowsMemoryImplDC( dc
);
183 #elif defined(__WXGTK20__)
184 return new wxGTKMemoryImplDC( dc
);
185 #elif defined(__WXGTK__)
186 return new wxGTKMemoryImplDC( dc
);
187 #elif defined(__WXMAC__)
188 return new wxMacMemoryImplDC( dc
);
189 #elif defined(__WXCOCOA__)
190 return new wxCocoaMemoryImplDC( dc
);
191 #elif defined(__WXMOTIF__)
192 return new wxMotifMemoryImplDC( dc
);
193 #elif defined(__WXX11__)
194 return new wxX11MemoryImplDC( dc
);
195 #elif defined(__WXMGL__)
196 return new wxMGLMemoryImplDC( dc
);
197 #elif defined(__WXDFB__)
198 return new wxDFBMemoryImplDC( dc
);
199 #elif defined(__WXPM__)
200 return new wxPMMemoryImplDC( dc
);
201 #elif defined(__PALMOS__)
202 return new wxPalmMemoryImplDC( dc
);
206 //-----------------------------------------------------------------------------
208 //-----------------------------------------------------------------------------
210 IMPLEMENT_ABSTRACT_CLASS(wxImplDC
, wxObject
)
212 wxImplDC::wxImplDC( wxDC
*owner
)
213 : m_colour(wxColourDisplay())
217 , m_isBBoxValid(false)
218 , m_logicalOriginX(0), m_logicalOriginY(0)
219 , m_deviceOriginX(0), m_deviceOriginY(0)
220 , m_deviceLocalOriginX(0), m_deviceLocalOriginY(0)
221 , m_logicalScaleX(1.0), m_logicalScaleY(1.0)
222 , m_userScaleX(1.0), m_userScaleY(1.0)
223 , m_scaleX(1.0), m_scaleY(1.0)
224 , m_signX(1), m_signY(1)
225 , m_minX(0), m_minY(0), m_maxX(0), m_maxY(0)
226 , m_clipX1(0), m_clipY1(0), m_clipX2(0), m_clipY2(0)
227 , m_logicalFunction(wxCOPY
)
228 , m_backgroundMode(wxTRANSPARENT
)
229 , m_mappingMode(wxMM_TEXT
)
232 , m_backgroundBrush(*wxTRANSPARENT_BRUSH
)
233 , m_textForegroundColour(*wxBLACK
)
234 , m_textBackgroundColour(*wxWHITE
)
238 , m_hasCustomPalette(false)
239 #endif // wxUSE_PALETTE
243 m_mm_to_pix_x
= (double)wxGetDisplaySize().GetWidth() /
244 (double)wxGetDisplaySizeMM().GetWidth();
245 m_mm_to_pix_y
= (double)wxGetDisplaySize().GetHeight() /
246 (double)wxGetDisplaySizeMM().GetHeight();
252 wxImplDC::~wxImplDC()
256 #if WXWIN_COMPATIBILITY_2_8
257 // for compatibility with the old code when wxCoord was long everywhere
258 void wxImplDC::GetTextExtent(const wxString
& string
,
261 long *externalLeading
,
262 const wxFont
*theFont
) const
264 wxCoord x2
, y2
, descent2
, externalLeading2
;
265 DoGetTextExtent(string
, &x2
, &y2
,
266 &descent2
, &externalLeading2
,
274 if ( externalLeading
)
275 *externalLeading
= externalLeading2
;
278 void wxImplDC::GetLogicalOrigin(long *x
, long *y
) const
281 DoGetLogicalOrigin(&x2
, &y2
);
288 void wxImplDC::GetDeviceOrigin(long *x
, long *y
) const
291 DoGetDeviceOrigin(&x2
, &y2
);
298 void wxImplDC::GetClippingBox(long *x
, long *y
, long *w
, long *h
) const
301 DoGetClippingBox(&xx
, &yy
, &ww
, &hh
);
307 #endif // WXWIN_COMPATIBILITY_2_8
311 // ----------------------------------------------------------------------------
312 // coordinate conversions and transforms
313 // ----------------------------------------------------------------------------
315 wxCoord
wxImplDC::DeviceToLogicalX(wxCoord x
) const
317 return wxRound((double)(x
- m_deviceOriginX
- m_deviceLocalOriginX
) / m_scaleX
) * m_signX
+ m_logicalOriginX
;
320 wxCoord
wxImplDC::DeviceToLogicalY(wxCoord y
) const
322 return wxRound((double)(y
- m_deviceOriginY
- m_deviceLocalOriginY
) / m_scaleY
) * m_signY
+ m_logicalOriginY
;
325 wxCoord
wxImplDC::DeviceToLogicalXRel(wxCoord x
) const
327 return wxRound((double)(x
) / m_scaleX
);
330 wxCoord
wxImplDC::DeviceToLogicalYRel(wxCoord y
) const
332 return wxRound((double)(y
) / m_scaleY
);
335 wxCoord
wxImplDC::LogicalToDeviceX(wxCoord x
) const
337 return wxRound((double)(x
- m_logicalOriginX
) * m_scaleX
) * m_signX
+ m_deviceOriginX
+ m_deviceLocalOriginX
;
340 wxCoord
wxImplDC::LogicalToDeviceY(wxCoord y
) const
342 return wxRound((double)(y
- m_logicalOriginY
) * m_scaleY
) * m_signY
+ m_deviceOriginY
+ m_deviceLocalOriginY
;
345 wxCoord
wxImplDC::LogicalToDeviceXRel(wxCoord x
) const
347 return wxRound((double)(x
) * m_scaleX
);
350 wxCoord
wxImplDC::LogicalToDeviceYRel(wxCoord y
) const
352 return wxRound((double)(y
) * m_scaleY
);
355 void wxImplDC::ComputeScaleAndOrigin()
357 m_scaleX
= m_logicalScaleX
* m_userScaleX
;
358 m_scaleY
= m_logicalScaleY
* m_userScaleY
;
361 void wxImplDC::SetMapMode( int mode
)
366 SetLogicalScale( twips2mm
*m_mm_to_pix_x
, twips2mm
*m_mm_to_pix_y
);
369 SetLogicalScale( pt2mm
*m_mm_to_pix_x
, pt2mm
*m_mm_to_pix_y
);
372 SetLogicalScale( m_mm_to_pix_x
, m_mm_to_pix_y
);
375 SetLogicalScale( m_mm_to_pix_x
/10.0, m_mm_to_pix_y
/10.0 );
379 SetLogicalScale( 1.0, 1.0 );
382 m_mappingMode
= mode
;
385 void wxImplDC::SetUserScale( double x
, double y
)
387 // allow negative ? -> no
390 ComputeScaleAndOrigin();
393 void wxImplDC::SetLogicalScale( double x
, double y
)
398 ComputeScaleAndOrigin();
401 void wxImplDC::SetLogicalOrigin( wxCoord x
, wxCoord y
)
403 m_logicalOriginX
= x
* m_signX
;
404 m_logicalOriginY
= y
* m_signY
;
405 ComputeScaleAndOrigin();
408 void wxImplDC::SetDeviceOrigin( wxCoord x
, wxCoord y
)
412 ComputeScaleAndOrigin();
415 void wxImplDC::SetDeviceLocalOrigin( wxCoord x
, wxCoord y
)
417 m_deviceLocalOriginX
= x
;
418 m_deviceLocalOriginY
= y
;
419 ComputeScaleAndOrigin();
422 void wxImplDC::SetAxisOrientation( bool xLeftRight
, bool yBottomUp
)
424 // only wxPostScripDC has m_signX = -1, we override SetAxisOrientation there
425 m_signX
= (xLeftRight
? 1 : -1);
426 m_signY
= (yBottomUp
? -1 : 1);
427 ComputeScaleAndOrigin();
431 // Each element of the widths array will be the width of the string up to and
432 // including the corresponding character in text. This is the generic
433 // implementation, the port-specific classes should do this with native APIs
434 // if available and if faster. Note: pango_layout_index_to_pos is much slower
435 // than calling GetTextExtent!!
442 FontWidthCache() : m_scaleX(1), m_widths(NULL
) { }
443 ~FontWidthCache() { delete []m_widths
; }
448 m_widths
= new int[FWC_SIZE
];
450 memset(m_widths
, 0, sizeof(int)*FWC_SIZE
);
458 static FontWidthCache s_fontWidthCache
;
460 bool wxImplDC::DoGetPartialTextExtents(const wxString
& text
, wxArrayInt
& widths
) const
464 const size_t len
= text
.length();
468 // reset the cache if font or horizontal scale have changed
469 if ( !s_fontWidthCache
.m_widths
||
470 !wxIsSameDouble(s_fontWidthCache
.m_scaleX
, m_scaleX
) ||
471 (s_fontWidthCache
.m_font
!= GetFont()) )
473 s_fontWidthCache
.Reset();
474 s_fontWidthCache
.m_font
= GetFont();
475 s_fontWidthCache
.m_scaleX
= m_scaleX
;
478 // Calculate the position of each character based on the widths of
479 // the previous characters
481 for ( size_t i
= 0; i
< len
; i
++ )
483 const wxChar c
= text
[i
];
484 unsigned int c_int
= (unsigned int)c
;
486 if ((c_int
< FWC_SIZE
) && (s_fontWidthCache
.m_widths
[c_int
] != 0))
488 w
= s_fontWidthCache
.m_widths
[c_int
];
492 GetTextExtent(c
, &w
, &h
);
493 if (c_int
< FWC_SIZE
)
494 s_fontWidthCache
.m_widths
[c_int
] = w
;
498 widths
[i
] = totalWidth
;
504 void wxImplDC::GetMultiLineTextExtent(const wxString
& text
,
508 const wxFont
*font
) const
510 wxCoord widthTextMax
= 0, widthLine
,
511 heightTextTotal
= 0, heightLineDefault
= 0, heightLine
= 0;
514 for ( const wxChar
*pc
= text
; ; pc
++ )
516 if ( *pc
== _T('\n') || *pc
== _T('\0') )
518 if ( curLine
.empty() )
520 // we can't use GetTextExtent - it will return 0 for both width
521 // and height and an empty line should count in height
524 // assume that this line has the same height as the previous
526 if ( !heightLineDefault
)
527 heightLineDefault
= heightLine
;
529 if ( !heightLineDefault
)
531 // but we don't know it yet - choose something reasonable
532 DoGetTextExtent(_T("W"), NULL
, &heightLineDefault
,
536 heightTextTotal
+= heightLineDefault
;
540 DoGetTextExtent(curLine
, &widthLine
, &heightLine
,
542 if ( widthLine
> widthTextMax
)
543 widthTextMax
= widthLine
;
544 heightTextTotal
+= heightLine
;
547 if ( *pc
== _T('\n') )
566 *y
= heightTextTotal
;
571 void wxImplDC::DoDrawCheckMark(wxCoord x1
, wxCoord y1
,
572 wxCoord width
, wxCoord height
)
574 wxCHECK_RET( Ok(), wxT("invalid window dc") );
576 wxCoord x2
= x1
+ width
,
579 // the pen width is calibrated to give 3 for width == height == 10
580 wxDCPenChanger
pen(m_owner
, wxPen(GetTextForeground(), (width
+ height
+ 1)/7));
582 // we're drawing a scaled version of wx/generic/tick.xpm here
583 wxCoord x3
= x1
+ (4*width
) / 10, // x of the tick bottom
584 y3
= y1
+ height
/ 2; // y of the left tick branch
585 DoDrawLine(x1
, y3
, x3
, y2
);
586 DoDrawLine(x3
, y2
, x2
, y1
);
588 CalcBoundingBox(x1
, y1
);
589 CalcBoundingBox(x2
, y2
);
593 wxImplDC::DoStretchBlit(wxCoord xdest
, wxCoord ydest
,
594 wxCoord dstWidth
, wxCoord dstHeight
,
596 wxCoord xsrc
, wxCoord ysrc
,
597 wxCoord srcWidth
, wxCoord srcHeight
,
603 wxCHECK_MSG( srcWidth
&& srcHeight
&& dstWidth
&& dstHeight
, false,
604 _T("invalid blit size") );
606 // emulate the stretching by modifying the DC scale
607 double xscale
= (double)srcWidth
/dstWidth
,
608 yscale
= (double)srcHeight
/dstHeight
;
610 double xscaleOld
, yscaleOld
;
611 GetUserScale(&xscaleOld
, &yscaleOld
);
612 SetUserScale(xscaleOld
/xscale
, yscaleOld
/yscale
);
614 bool rc
= DoBlit(wxCoord(xdest
*xscale
), wxCoord(ydest
*yscale
),
615 wxCoord(dstWidth
*xscale
), wxCoord(dstHeight
*yscale
),
617 xsrc
, ysrc
, rop
, useMask
, xsrcMask
, ysrcMask
);
619 SetUserScale(xscaleOld
, yscaleOld
);
624 void wxImplDC::DrawLines(const wxList
*list
, wxCoord xoffset
, wxCoord yoffset
)
626 int n
= list
->GetCount();
627 wxPoint
*points
= new wxPoint
[n
];
630 for ( wxList::compatibility_iterator node
= list
->GetFirst(); node
; node
= node
->GetNext(), i
++ )
632 wxPoint
*point
= (wxPoint
*)node
->GetData();
633 points
[i
].x
= point
->x
;
634 points
[i
].y
= point
->y
;
637 DoDrawLines(n
, points
, xoffset
, yoffset
);
642 void wxImplDC::DrawPolygon(const wxList
*list
,
643 wxCoord xoffset
, wxCoord yoffset
,
646 int n
= list
->GetCount();
647 wxPoint
*points
= new wxPoint
[n
];
650 for ( wxList::compatibility_iterator node
= list
->GetFirst(); node
; node
= node
->GetNext(), i
++ )
652 wxPoint
*point
= (wxPoint
*)node
->GetData();
653 points
[i
].x
= point
->x
;
654 points
[i
].y
= point
->y
;
657 DoDrawPolygon(n
, points
, xoffset
, yoffset
, fillStyle
);
663 wxImplDC::DoDrawPolyPolygon(int n
,
666 wxCoord xoffset
, wxCoord yoffset
,
671 DoDrawPolygon(count
[0], points
, xoffset
, yoffset
, fillStyle
);
679 for (i
= j
= lastOfs
= 0; i
< n
; i
++)
684 pts
= new wxPoint
[j
+n
-1];
685 for (i
= 0; i
< j
; i
++)
687 for (i
= 2; i
<= n
; i
++)
689 lastOfs
-= count
[n
-i
];
690 pts
[j
++] = pts
[lastOfs
];
694 SetPen(wxPen(*wxBLACK
, 0, wxTRANSPARENT
));
695 DoDrawPolygon(j
, pts
, xoffset
, yoffset
, fillStyle
);
697 for (i
= j
= 0; i
< n
; i
++)
699 DoDrawLines(count
[i
], pts
+j
, xoffset
, yoffset
);
707 // TODO: this API needs fixing (wxPointList, why (!const) "wxList *"?)
708 void wxImplDC::DrawSpline(wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
, wxCoord x3
, wxCoord y3
)
712 wxPoint
*point1
= new wxPoint
;
713 point1
->x
= x1
; point1
->y
= y1
;
714 point_list
.Append((wxObject
*)point1
);
716 wxPoint
*point2
= new wxPoint
;
717 point2
->x
= x2
; point2
->y
= y2
;
718 point_list
.Append((wxObject
*)point2
);
720 wxPoint
*point3
= new wxPoint
;
721 point3
->x
= x3
; point3
->y
= y3
;
722 point_list
.Append((wxObject
*)point3
);
724 DrawSpline(&point_list
);
726 for( wxList::compatibility_iterator node
= point_list
.GetFirst(); node
; node
= node
->GetNext() )
728 wxPoint
*p
= (wxPoint
*)node
->GetData();
733 void wxImplDC::DrawSpline(int n
, wxPoint points
[])
736 for (int i
=0; i
< n
; i
++)
738 list
.Append((wxObject
*)&points
[i
]);
744 // ----------------------------------- spline code ----------------------------------------
746 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
,
747 double a3
, double b3
, double a4
, double b4
);
748 void wx_clear_stack();
749 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
, double *x3
,
750 double *y3
, double *x4
, double *y4
);
751 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
,
752 double x4
, double y4
);
753 static bool wx_spline_add_point(double x
, double y
);
754 static void wx_spline_draw_point_array(wxDCBase
*dc
);
756 wxList wx_spline_point_list
;
758 #define half(z1, z2) ((z1+z2)/2.0)
761 /* iterative version */
763 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
, double a3
, double b3
, double a4
,
766 register double xmid
, ymid
;
767 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
770 wx_spline_push(a1
, b1
, a2
, b2
, a3
, b3
, a4
, b4
);
772 while (wx_spline_pop(&x1
, &y1
, &x2
, &y2
, &x3
, &y3
, &x4
, &y4
)) {
773 xmid
= (double)half(x2
, x3
);
774 ymid
= (double)half(y2
, y3
);
775 if (fabs(x1
- xmid
) < THRESHOLD
&& fabs(y1
- ymid
) < THRESHOLD
&&
776 fabs(xmid
- x4
) < THRESHOLD
&& fabs(ymid
- y4
) < THRESHOLD
) {
777 wx_spline_add_point( x1
, y1
);
778 wx_spline_add_point( xmid
, ymid
);
780 wx_spline_push(xmid
, ymid
, (double)half(xmid
, x3
), (double)half(ymid
, y3
),
781 (double)half(x3
, x4
), (double)half(y3
, y4
), x4
, y4
);
782 wx_spline_push(x1
, y1
, (double)half(x1
, x2
), (double)half(y1
, y2
),
783 (double)half(x2
, xmid
), (double)half(y2
, ymid
), xmid
, ymid
);
788 /* utilities used by spline drawing routines */
790 typedef struct wx_spline_stack_struct
{
791 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
794 #define SPLINE_STACK_DEPTH 20
795 static Stack wx_spline_stack
[SPLINE_STACK_DEPTH
];
796 static Stack
*wx_stack_top
;
797 static int wx_stack_count
;
799 void wx_clear_stack()
801 wx_stack_top
= wx_spline_stack
;
805 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
, double x4
, double y4
)
807 wx_stack_top
->x1
= x1
;
808 wx_stack_top
->y1
= y1
;
809 wx_stack_top
->x2
= x2
;
810 wx_stack_top
->y2
= y2
;
811 wx_stack_top
->x3
= x3
;
812 wx_stack_top
->y3
= y3
;
813 wx_stack_top
->x4
= x4
;
814 wx_stack_top
->y4
= y4
;
819 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
,
820 double *x3
, double *y3
, double *x4
, double *y4
)
822 if (wx_stack_count
== 0)
826 *x1
= wx_stack_top
->x1
;
827 *y1
= wx_stack_top
->y1
;
828 *x2
= wx_stack_top
->x2
;
829 *y2
= wx_stack_top
->y2
;
830 *x3
= wx_stack_top
->x3
;
831 *y3
= wx_stack_top
->y3
;
832 *x4
= wx_stack_top
->x4
;
833 *y4
= wx_stack_top
->y4
;
837 static bool wx_spline_add_point(double x
, double y
)
839 wxPoint
*point
= new wxPoint
;
842 wx_spline_point_list
.Append((wxObject
*)point
);
846 static void wx_spline_draw_point_array(wxDC
*dc
)
848 dc
->DrawLines(&wx_spline_point_list
, 0, 0 );
849 wxList::compatibility_iterator node
= wx_spline_point_list
.GetFirst();
852 wxPoint
*point
= (wxPoint
*)node
->GetData();
854 wx_spline_point_list
.Erase(node
);
855 node
= wx_spline_point_list
.GetFirst();
859 void wxImplDC::DoDrawSpline( wxList
*points
)
861 wxCHECK_RET( Ok(), wxT("invalid window dc") );
864 double cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
;
865 double x1
, y1
, x2
, y2
;
867 wxList::compatibility_iterator node
= points
->GetFirst();
872 p
= (wxPoint
*)node
->GetData();
877 node
= node
->GetNext();
878 p
= (wxPoint
*)node
->GetData();
882 cx1
= (double)((x1
+ x2
) / 2);
883 cy1
= (double)((y1
+ y2
) / 2);
884 cx2
= (double)((cx1
+ x2
) / 2);
885 cy2
= (double)((cy1
+ y2
) / 2);
887 wx_spline_add_point(x1
, y1
);
889 while ((node
= node
->GetNext())
895 p
= (wxPoint
*)node
->GetData();
900 cx4
= (double)(x1
+ x2
) / 2;
901 cy4
= (double)(y1
+ y2
) / 2;
902 cx3
= (double)(x1
+ cx4
) / 2;
903 cy3
= (double)(y1
+ cy4
) / 2;
905 wx_quadratic_spline(cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
);
909 cx2
= (double)(cx1
+ x2
) / 2;
910 cy2
= (double)(cy1
+ y2
) / 2;
913 wx_spline_add_point( cx1
, cy1
);
914 wx_spline_add_point( x2
, y2
);
916 wx_spline_draw_point_array( m_owner
);
919 #endif // wxUSE_SPLINES
922 void wxImplDC::DrawLabel(const wxString
& text
,
923 const wxBitmap
& bitmap
,
927 wxRect
*rectBounding
)
929 // find the text position
930 wxCoord widthText
, heightText
, heightLine
;
931 GetMultiLineTextExtent(text
, &widthText
, &heightText
, &heightLine
);
933 wxCoord width
, height
;
936 width
= widthText
+ bitmap
.GetWidth();
937 height
= bitmap
.GetHeight();
946 if ( alignment
& wxALIGN_RIGHT
)
948 x
= rect
.GetRight() - width
;
950 else if ( alignment
& wxALIGN_CENTRE_HORIZONTAL
)
952 x
= (rect
.GetLeft() + rect
.GetRight() + 1 - width
) / 2;
954 else // alignment & wxALIGN_LEFT
959 if ( alignment
& wxALIGN_BOTTOM
)
961 y
= rect
.GetBottom() - height
;
963 else if ( alignment
& wxALIGN_CENTRE_VERTICAL
)
965 y
= (rect
.GetTop() + rect
.GetBottom() + 1 - height
) / 2;
967 else // alignment & wxALIGN_TOP
972 // draw the bitmap first
978 DoDrawBitmap(bitmap
, x
, y
, true /* use mask */);
980 wxCoord offset
= bitmap
.GetWidth() + 4;
984 y
+= (height
- heightText
) / 2;
987 // we will draw the underscore under the accel char later
988 wxCoord startUnderscore
= 0,
992 // split the string into lines and draw each of them separately
994 for ( wxString::const_iterator pc
= text
.begin(); ; ++pc
)
996 if ( *pc
== _T('\n') || pc
== text
.end() )
998 int xRealStart
= x
; // init it here to avoid compielr warnings
1000 if ( !curLine
.empty() )
1002 // NB: can't test for !(alignment & wxALIGN_LEFT) because
1003 // wxALIGN_LEFT is 0
1004 if ( alignment
& (wxALIGN_RIGHT
| wxALIGN_CENTRE_HORIZONTAL
) )
1007 m_owner
->GetTextExtent(curLine
, &widthLine
, NULL
);
1009 if ( alignment
& wxALIGN_RIGHT
)
1011 xRealStart
+= width
- widthLine
;
1013 else // if ( alignment & wxALIGN_CENTRE_HORIZONTAL )
1015 xRealStart
+= (width
- widthLine
) / 2;
1018 //else: left aligned, nothing to do
1020 DoDrawText(curLine
, xRealStart
, y
);
1025 // do we have underscore in this line? we can check yUnderscore
1026 // because it is set below to just y + heightLine if we do
1027 if ( y
== yUnderscore
)
1029 // adjust the horz positions to account for the shift
1030 startUnderscore
+= xRealStart
;
1031 endUnderscore
+= xRealStart
;
1034 if ( pc
== text
.end() )
1039 else // not end of line
1041 if ( pc
- text
.begin() == indexAccel
)
1043 // remeber to draw underscore here
1044 GetTextExtent(curLine
, &startUnderscore
, NULL
);
1046 GetTextExtent(curLine
, &endUnderscore
, NULL
);
1048 yUnderscore
= y
+ heightLine
;
1057 // draw the underscore if found
1058 if ( startUnderscore
!= endUnderscore
)
1060 // it should be of the same colour as text
1061 SetPen(wxPen(GetTextForeground(), 0, wxSOLID
));
1065 DoDrawLine(startUnderscore
, yUnderscore
, endUnderscore
, yUnderscore
);
1068 // return bounding rect if requested
1071 *rectBounding
= wxRect(x
, y
- heightText
, widthText
, heightText
);
1074 CalcBoundingBox(x0
, y0
);
1075 CalcBoundingBox(x0
+ width0
, y0
+ height
);
1079 void wxImplDC::DoGradientFillLinear(const wxRect
& rect
,
1080 const wxColour
& initialColour
,
1081 const wxColour
& destColour
,
1082 wxDirection nDirection
)
1085 wxPen oldPen
= m_pen
;
1086 wxBrush oldBrush
= m_brush
;
1088 wxUint8 nR1
= initialColour
.Red();
1089 wxUint8 nG1
= initialColour
.Green();
1090 wxUint8 nB1
= initialColour
.Blue();
1091 wxUint8 nR2
= destColour
.Red();
1092 wxUint8 nG2
= destColour
.Green();
1093 wxUint8 nB2
= destColour
.Blue();
1096 if ( nDirection
== wxEAST
|| nDirection
== wxWEST
)
1098 wxInt32 x
= rect
.GetWidth();
1099 wxInt32 w
= x
; // width of area to shade
1100 wxInt32 xDelta
= w
/256; // height of one shade bend
1108 nR
= nR1
- (nR1
-nR2
)*(w
-x
)/w
;
1110 nR
= nR1
+ (nR2
-nR1
)*(w
-x
)/w
;
1113 nG
= nG1
- (nG1
-nG2
)*(w
-x
)/w
;
1115 nG
= nG1
+ (nG2
-nG1
)*(w
-x
)/w
;
1118 nB
= nB1
- (nB1
-nB2
)*(w
-x
)/w
;
1120 nB
= nB1
+ (nB2
-nB1
)*(w
-x
)/w
;
1122 wxColour
colour(nR
,nG
,nB
);
1123 SetPen(wxPen(colour
, 1, wxSOLID
));
1124 SetBrush(wxBrush(colour
));
1125 if(nDirection
== wxEAST
)
1126 DoDrawRectangle(rect
.GetRight()-x
-xDelta
, rect
.GetTop(),
1127 xDelta
, rect
.GetHeight());
1128 else //nDirection == wxWEST
1129 DoDrawRectangle(rect
.GetLeft()+x
, rect
.GetTop(),
1130 xDelta
, rect
.GetHeight());
1133 else // nDirection == wxNORTH || nDirection == wxSOUTH
1135 wxInt32 y
= rect
.GetHeight();
1136 wxInt32 w
= y
; // height of area to shade
1137 wxInt32 yDelta
= w
/255; // height of one shade bend
1145 nR
= nR1
- (nR1
-nR2
)*(w
-y
)/w
;
1147 nR
= nR1
+ (nR2
-nR1
)*(w
-y
)/w
;
1150 nG
= nG1
- (nG1
-nG2
)*(w
-y
)/w
;
1152 nG
= nG1
+ (nG2
-nG1
)*(w
-y
)/w
;
1155 nB
= nB1
- (nB1
-nB2
)*(w
-y
)/w
;
1157 nB
= nB1
+ (nB2
-nB1
)*(w
-y
)/w
;
1159 wxColour
colour(nR
,nG
,nB
);
1160 SetPen(wxPen(colour
, 1, wxSOLID
));
1161 SetBrush(wxBrush(colour
));
1162 if(nDirection
== wxNORTH
)
1163 DoDrawRectangle(rect
.GetLeft(), rect
.GetTop()+y
,
1164 rect
.GetWidth(), yDelta
);
1165 else //nDirection == wxSOUTH
1166 DoDrawRectangle(rect
.GetLeft(), rect
.GetBottom()-y
-yDelta
,
1167 rect
.GetWidth(), yDelta
);
1175 void wxImplDC::DoGradientFillConcentric(const wxRect
& rect
,
1176 const wxColour
& initialColour
,
1177 const wxColour
& destColour
,
1178 const wxPoint
& circleCenter
)
1180 //save the old pen color
1181 wxColour oldPenColour
= m_pen
.GetColour();
1183 wxUint8 nR1
= destColour
.Red();
1184 wxUint8 nG1
= destColour
.Green();
1185 wxUint8 nB1
= destColour
.Blue();
1186 wxUint8 nR2
= initialColour
.Red();
1187 wxUint8 nG2
= initialColour
.Green();
1188 wxUint8 nB2
= initialColour
.Blue();
1193 wxInt32 cx
= rect
.GetWidth() / 2;
1194 wxInt32 cy
= rect
.GetHeight() / 2;
1202 wxInt32 nCircleOffX
= circleCenter
.x
- (rect
.GetWidth() / 2);
1203 wxInt32 nCircleOffY
= circleCenter
.y
- (rect
.GetHeight() / 2);
1205 for ( wxInt32 x
= 0; x
< rect
.GetWidth(); x
++ )
1207 for ( wxInt32 y
= 0; y
< rect
.GetHeight(); y
++ )
1209 //get color difference
1210 wxInt32 nGradient
= ((nRadius
-
1212 pow((double)(x
- cx
- nCircleOffX
), 2) +
1213 pow((double)(y
- cy
- nCircleOffY
), 2)
1214 )) * 100) / nRadius
;
1216 //normalize Gradient
1221 nR
= (wxUint8
)(nR1
+ ((nR2
- nR1
) * nGradient
/ 100));
1222 nG
= (wxUint8
)(nG1
+ ((nG2
- nG1
) * nGradient
/ 100));
1223 nB
= (wxUint8
)(nB1
+ ((nB2
- nB1
) * nGradient
/ 100));
1226 m_pen
.SetColour(wxColour(nR
,nG
,nB
));
1227 DoDrawPoint(wxPoint(x
+ rect
.GetLeft(), y
+ rect
.GetTop()));
1230 //return old pen color
1231 m_pen
.SetColour(oldPenColour
);
1234 //-----------------------------------------------------------------------------
1236 //-----------------------------------------------------------------------------
1238 IMPLEMENT_ABSTRACT_CLASS(wxDC
, wxObject
)
1240 #if WXWIN_COMPATIBILITY_2_8
1241 // for compatibility with the old code when wxCoord was long everywhere
1242 void wxDC::GetTextExtent(const wxString
& string
,
1245 long *externalLeading
,
1246 const wxFont
*theFont
) const
1248 wxCoord x2
, y2
, descent2
, externalLeading2
;
1249 m_pimpl
->DoGetTextExtent(string
, &x2
, &y2
,
1250 &descent2
, &externalLeading2
,
1257 *descent
= descent2
;
1258 if ( externalLeading
)
1259 *externalLeading
= externalLeading2
;
1262 void wxDC::GetLogicalOrigin(long *x
, long *y
) const
1265 m_pimpl
->DoGetLogicalOrigin(&x2
, &y2
);
1272 void wxDC::GetDeviceOrigin(long *x
, long *y
) const
1275 m_pimpl
->DoGetDeviceOrigin(&x2
, &y2
);
1282 void wxDC::GetClippingBox(long *x
, long *y
, long *w
, long *h
) const
1284 wxCoord xx
,yy
,ww
,hh
;
1285 m_pimpl
->DoGetClippingBox(&xx
, &yy
, &ww
, &hh
);
1292 #endif // WXWIN_COMPATIBILITY_2_8
1295 #endif // wxUSE_NEW_DC
1297 //-----------------------------------------------------------------------------
1299 //-----------------------------------------------------------------------------
1301 IMPLEMENT_ABSTRACT_CLASS(wxDC
, wxDCBase
)
1307 m_pen
= *wxBLACK_PEN
;
1308 m_font
= *wxNORMAL_FONT
;
1309 m_brush
= *wxWHITE_BRUSH
;
1312 void wxDC::DoSetClippingRegion( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
1317 m_clipX2
= x
+ width
;
1318 m_clipY2
= y
+ height
;
1321 // ---------------------------------------------------------------------------
1322 // get DC capabilities
1323 // ---------------------------------------------------------------------------
1325 void wxDC::DoGetSizeMM( int* width
, int* height
) const
1330 if (width
) *width
= int( double(w
) / (m_userScaleX
*m_mm_to_pix_x
) );
1331 if (height
) *height
= int( double(h
) / (m_userScaleY
*m_mm_to_pix_y
) );
1334 // Resolution in pixels per logical inch
1335 wxSize
wxDC::GetPPI() const
1337 // TODO (should probably be pure virtual)
1338 return wxSize(0, 0);