1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxClientDC class
8 // Copyright: (c) AUTHOR
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation "dcclient.h"
16 #include "wx/dcclient.h"
17 #include "wx/dcmemory.h"
18 #include "wx/region.h"
21 //-----------------------------------------------------------------------------
23 //-----------------------------------------------------------------------------
25 #define RAD2DEG 57.2957795131
27 //-----------------------------------------------------------------------------
29 //-----------------------------------------------------------------------------
31 #if !USE_SHARED_LIBRARY
32 IMPLEMENT_DYNAMIC_CLASS(wxWindowDC
, wxDC
)
33 IMPLEMENT_DYNAMIC_CLASS(wxClientDC
, wxWindowDC
)
34 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC
, wxWindowDC
)
41 wxWindowDC::wxWindowDC(void)
45 wxWindowDC::wxWindowDC( wxWindow
*window
)
49 wxWindowDC::~wxWindowDC(void)
53 void wxWindowDC::FloodFill( long WXUNUSED(x1
), long WXUNUSED(y1
),
54 const wxColour
& WXUNUSED(col
), int WXUNUSED(style
) )
58 bool wxWindowDC::GetPixel( long WXUNUSED(x1
), long WXUNUSED(y1
), wxColour
*WXUNUSED(col
) ) const
63 void wxWindowDC::DrawLine( long x1
, long y1
, long x2
, long y2
)
69 void wxWindowDC::CrossHair( long x
, long y
)
75 void wxWindowDC::DrawArc( long x1
, long y1
, long x2
, long y2
, long xc
, long yc
)
79 long xx1
= XLOG2DEV(x1
);
80 long yy1
= YLOG2DEV(y1
);
81 long xx2
= XLOG2DEV(x2
);
82 long yy2
= YLOG2DEV(y2
);
83 long xxc
= XLOG2DEV((long)xc
);
84 long yyc
= YLOG2DEV((long)yc
);
85 double dx
= xx1
- xxc
;
86 double dy
= yy1
- yyc
;
87 double radius
= sqrt(dx
*dx
+dy
*dy
);
88 long r
= (long)radius
;
89 double radius1
, radius2
;
91 if (xx1
== xx2
&& yy1
== yy2
)
99 radius1
= radius2
= 0.0;
103 radius1
= (xx1
- xxc
== 0) ?
104 (yy1
- yyc
< 0) ? 90.0 : -90.0 :
105 -atan2(double(yy1
-yyc
), double(xx1
-xxc
)) * RAD2DEG
;
106 radius2
= (xx2
- xxc
== 0) ?
107 (yy2
- yyc
< 0) ? 90.0 : -90.0 :
108 -atan2(double(yy2
-yyc
), double(xx2
-xxc
)) * RAD2DEG
;
110 long alpha1
= long(radius1
* 64.0);
111 long alpha2
= long((radius2
- radius1
) * 64.0);
112 while (alpha2
<= 0) alpha2
+= 360*64;
113 while (alpha1
> 360*64) alpha1
-= 360*64;
115 if (m_brush
.GetStyle() != wxTRANSPARENT
) {};
117 if (m_pen
.GetStyle() != wxTRANSPARENT
) {};
121 void wxWindowDC::DrawEllipticArc( long x
, long y
, long width
, long height
, double sa
, double ea
)
125 long xx
= XLOG2DEV(x
);
126 long yy
= YLOG2DEV(y
);
127 long ww
= m_signX
* XLOG2DEVREL(width
);
128 long hh
= m_signY
* YLOG2DEVREL(height
);
130 // CMB: handle -ve width and/or height
131 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
132 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
134 long start
= long(sa
* 64.0);
135 long end
= long(ea
* 64.0);
136 if (m_brush
.GetStyle() != wxTRANSPARENT
) {};
138 if (m_pen
.GetStyle() != wxTRANSPARENT
) {};
141 void wxWindowDC::DrawPoint( long x
, long y
)
145 if (m_pen
.GetStyle() != wxTRANSPARENT
) {};
148 void wxWindowDC::DrawLines( int n
, wxPoint points
[], long xoffset
, long yoffset
)
152 if (m_pen
.GetStyle() == wxTRANSPARENT
) return;
154 for (int i
= 0; i
< n
-1; i
++)
156 long x1
= XLOG2DEV(points
[i
].x
+ xoffset
);
157 long x2
= XLOG2DEV(points
[i
+1].x
+ xoffset
);
158 long y1
= YLOG2DEV(points
[i
].y
+ yoffset
); // oh, what a waste
159 long y2
= YLOG2DEV(points
[i
+1].y
+ yoffset
);
163 void wxWindowDC::DrawLines( wxList
*points
, long xoffset
, long yoffset
)
167 if (m_pen
.GetStyle() == wxTRANSPARENT
) return;
169 wxNode
*node
= points
->First();
172 wxPoint
*point
= (wxPoint
*)node
->Data();
173 wxPoint
*npoint
= (wxPoint
*)node
->Next()->Data();
174 long x1
= XLOG2DEV(point
->x
+ xoffset
);
175 long x2
= XLOG2DEV(npoint
->x
+ xoffset
);
176 long y1
= YLOG2DEV(point
->y
+ yoffset
); // and again...
177 long y2
= YLOG2DEV(npoint
->y
+ yoffset
);
182 void wxWindowDC::DrawPolygon( int WXUNUSED(n
), wxPoint
WXUNUSED(points
)[],
183 long WXUNUSED(xoffset
), long WXUNUSED(yoffset
), int WXUNUSED(fillStyle
) )
188 void wxWindowDC::DrawPolygon( wxList
*WXUNUSED(lines
), long WXUNUSED(xoffset
),
189 long WXUNUSED(yoffset
), int WXUNUSED(fillStyle
) )
194 void wxWindowDC::DrawRectangle( long x
, long y
, long width
, long height
)
198 long xx
= XLOG2DEV(x
);
199 long yy
= YLOG2DEV(y
);
200 long ww
= m_signX
* XLOG2DEVREL(width
);
201 long hh
= m_signY
* YLOG2DEVREL(height
);
203 // CMB: draw nothing if transformed w or h is 0
204 if (ww
== 0 || hh
== 0) return;
206 // CMB: handle -ve width and/or height
207 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
208 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
210 if (m_brush
.GetStyle() != wxTRANSPARENT
) {};
212 if (m_pen
.GetStyle() != wxTRANSPARENT
) {};
215 void wxWindowDC::DrawRoundedRectangle( long x
, long y
, long width
, long height
, double radius
)
219 if (radius
< 0.0) radius
= - radius
* ((width
< height
) ? width
: height
);
221 long xx
= XLOG2DEV(x
);
222 long yy
= YLOG2DEV(y
);
223 long ww
= m_signX
* XLOG2DEVREL(width
);
224 long hh
= m_signY
* YLOG2DEVREL(height
);
225 long rr
= XLOG2DEVREL((long)radius
);
227 // CMB: handle -ve width and/or height
228 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
229 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
231 // CMB: if radius is zero use DrawRectangle() instead to avoid
232 // X drawing errors with small radii
235 DrawRectangle( x
, y
, width
, height
);
239 // CMB: draw nothing if transformed w or h is 0
240 if (ww
== 0 || hh
== 0) return;
242 // CMB: adjust size if outline is drawn otherwise the result is
243 // 1 pixel too wide and high
244 if (m_pen
.GetStyle() != wxTRANSPARENT
)
250 // CMB: ensure dd is not larger than rectangle otherwise we
251 // get an hour glass shape
253 if (dd
> ww
) dd
= ww
;
254 if (dd
> hh
) dd
= hh
;
257 if (m_brush
.GetStyle() != wxTRANSPARENT
)
261 if (m_pen
.GetStyle() != wxTRANSPARENT
)
266 void wxWindowDC::DrawEllipse( long x
, long y
, long width
, long height
)
270 long xx
= XLOG2DEV(x
);
271 long yy
= YLOG2DEV(y
);
272 long ww
= m_signX
* XLOG2DEVREL(width
);
273 long hh
= m_signY
* YLOG2DEVREL(height
);
275 // CMB: handle -ve width and/or height
276 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
277 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
279 if (m_brush
.GetStyle() != wxTRANSPARENT
) {};
281 if (m_pen
.GetStyle() != wxTRANSPARENT
) {};
284 bool wxWindowDC::CanDrawBitmap(void) const
289 void wxWindowDC::DrawIcon( const wxIcon
&icon
, long x
, long y
, bool useMask
)
293 if (!icon
.Ok()) return;
295 int xx
= XLOG2DEV(x
);
296 int yy
= YLOG2DEV(y
);
300 bool wxWindowDC::Blit( long xdest
, long ydest
, long width
, long height
,
301 wxDC
*source
, long xsrc
, long ysrc
, int WXUNUSED(logical_func
), bool WXUNUSED(useMask
) )
303 if (!Ok()) return FALSE
;
305 // CMB 20/5/98: add blitting of bitmaps
306 if (source
->IsKindOf(CLASSINFO(wxMemoryDC
)))
308 wxMemoryDC
* srcDC
= (wxMemoryDC
*)source
;
310 GdkBitmap* bmap = srcDC->m_selected.GetBitmap();
317 source->DeviceToLogicalX(xsrc), source->DeviceToLogicalY(ysrc),
318 XLOG2DEV(xdest), YLOG2DEV(ydest),
319 source->DeviceToLogicalXRel(width), source->DeviceToLogicalYRel(height)
329 void wxWindowDC::DrawText( const wxString
&text
, long x
, long y
, bool
338 bool wxWindowDC::CanGetTextExtent(void) const
343 void wxWindowDC::GetTextExtent( const wxString
&string
, long *width
, long *height
,
344 long *WXUNUSED(descent
), long *WXUNUSED(externalLeading
),
345 wxFont
*WXUNUSED(theFont
), bool WXUNUSED(use16
) )
351 long wxWindowDC::GetCharWidth(void)
357 long wxWindowDC::GetCharHeight(void)
363 void wxWindowDC::Clear(void)
369 void wxWindowDC::SetFont( const wxFont
&font
)
376 void wxWindowDC::SetPen( const wxPen
&pen
)
380 if (m_pen
== pen
) return;
384 if (!m_pen
.Ok()) return;
387 void wxWindowDC::SetBrush( const wxBrush
&brush
)
391 if (m_brush
== brush
) return;
395 if (!m_brush
.Ok()) return;
399 void wxWindowDC::SetBackground( const wxBrush
&brush
)
403 if (m_backgroundBrush
== brush
) return;
405 m_backgroundBrush
= brush
;
407 if (!m_backgroundBrush
.Ok()) return;
411 void wxWindowDC::SetLogicalFunction( int function
)
413 if (m_logicalFunction
== function
) return;
416 void wxWindowDC::SetTextForeground( const wxColour
&col
)
420 if (m_textForegroundColour
== col
) return;
422 m_textForegroundColour
= col
;
423 if (!m_textForegroundColour
.Ok()) return;
426 void wxWindowDC::SetTextBackground( const wxColour
&col
)
430 if (m_textBackgroundColour
== col
) return;
432 m_textBackgroundColour
= col
;
433 if (!m_textBackgroundColour
.Ok()) return;
436 void wxWindowDC::SetBackgroundMode( int mode
)
438 m_backgroundMode
= mode
;
440 if (m_brush
.GetStyle() != wxSOLID
&& m_brush
.GetStyle() != wxTRANSPARENT
)
445 void wxWindowDC::SetPalette( const wxPalette
& WXUNUSED(palette
) )
449 void wxWindowDC::SetClippingRegion( long x
, long y
, long width
, long height
)
451 wxDC::SetClippingRegion( x
, y
, width
, height
);
457 void wxWindowDC::SetClippingRegion( const wxRegion
& region
)
459 wxRect box
= region
.GetBox();
461 wxDC::SetClippingRegion( box
.x
, box
.y
, box
.width
, box
.height
);
466 void wxWindowDC::DestroyClippingRegion(void)
468 wxDC::DestroyClippingRegion();
472 // ----------------------------------- spline code ----------------------------------------
474 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
,
475 double a3
, double b3
, double a4
, double b4
);
476 void wx_clear_stack(void);
477 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
, double *x3
,
478 double *y3
, double *x4
, double *y4
);
479 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
,
480 double x4
, double y4
);
481 static bool wx_spline_add_point(double x
, double y
);
482 static void wx_spline_draw_point_array(wxDC
*dc
);
484 wxList wx_spline_point_list
;
486 #define half(z1, z2) ((z1+z2)/2.0)
489 /* iterative version */
491 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
, double a3
, double b3
, double a4
,
494 register double xmid
, ymid
;
495 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
498 wx_spline_push(a1
, b1
, a2
, b2
, a3
, b3
, a4
, b4
);
500 while (wx_spline_pop(&x1
, &y1
, &x2
, &y2
, &x3
, &y3
, &x4
, &y4
)) {
501 xmid
= (double)half(x2
, x3
);
502 ymid
= (double)half(y2
, y3
);
503 if (fabs(x1
- xmid
) < THRESHOLD
&& fabs(y1
- ymid
) < THRESHOLD
&&
504 fabs(xmid
- x4
) < THRESHOLD
&& fabs(ymid
- y4
) < THRESHOLD
) {
505 wx_spline_add_point( x1
, y1
);
506 wx_spline_add_point( xmid
, ymid
);
508 wx_spline_push(xmid
, ymid
, (double)half(xmid
, x3
), (double)half(ymid
, y3
),
509 (double)half(x3
, x4
), (double)half(y3
, y4
), x4
, y4
);
510 wx_spline_push(x1
, y1
, (double)half(x1
, x2
), (double)half(y1
, y2
),
511 (double)half(x2
, xmid
), (double)half(y2
, ymid
), xmid
, ymid
);
516 /* utilities used by spline drawing routines */
518 typedef struct wx_spline_stack_struct
{
519 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
522 #define SPLINE_STACK_DEPTH 20
523 static Stack wx_spline_stack
[SPLINE_STACK_DEPTH
];
524 static Stack
*wx_stack_top
;
525 static int wx_stack_count
;
527 void wx_clear_stack(void)
529 wx_stack_top
= wx_spline_stack
;
533 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
, double x4
, double y4
)
535 wx_stack_top
->x1
= x1
;
536 wx_stack_top
->y1
= y1
;
537 wx_stack_top
->x2
= x2
;
538 wx_stack_top
->y2
= y2
;
539 wx_stack_top
->x3
= x3
;
540 wx_stack_top
->y3
= y3
;
541 wx_stack_top
->x4
= x4
;
542 wx_stack_top
->y4
= y4
;
547 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
,
548 double *x3
, double *y3
, double *x4
, double *y4
)
550 if (wx_stack_count
== 0)
554 *x1
= wx_stack_top
->x1
;
555 *y1
= wx_stack_top
->y1
;
556 *x2
= wx_stack_top
->x2
;
557 *y2
= wx_stack_top
->y2
;
558 *x3
= wx_stack_top
->x3
;
559 *y3
= wx_stack_top
->y3
;
560 *x4
= wx_stack_top
->x4
;
561 *y4
= wx_stack_top
->y4
;
565 static bool wx_spline_add_point(double x
, double y
)
567 wxPoint
*point
= new wxPoint
;
570 wx_spline_point_list
.Append((wxObject
*)point
);
574 static void wx_spline_draw_point_array(wxDC
*dc
)
576 dc
->DrawLines(&wx_spline_point_list
, 0, 0 );
577 wxNode
*node
= wx_spline_point_list
.First();
580 wxPoint
*point
= (wxPoint
*)node
->Data();
583 node
= wx_spline_point_list
.First();
587 void wxWindowDC::DrawSpline( wxList
*points
)
590 double cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
;
591 double x1
, y1
, x2
, y2
;
593 wxNode
*node
= points
->First();
594 p
= (wxPoint
*)node
->Data();
600 p
= (wxPoint
*)node
->Data();
604 cx1
= (double)((x1
+ x2
) / 2);
605 cy1
= (double)((y1
+ y2
) / 2);
606 cx2
= (double)((cx1
+ x2
) / 2);
607 cy2
= (double)((cy1
+ y2
) / 2);
609 wx_spline_add_point(x1
, y1
);
611 while ((node
= node
->Next()) != NULL
)
613 p
= (wxPoint
*)node
->Data();
618 cx4
= (double)(x1
+ x2
) / 2;
619 cy4
= (double)(y1
+ y2
) / 2;
620 cx3
= (double)(x1
+ cx4
) / 2;
621 cy3
= (double)(y1
+ cy4
) / 2;
623 wx_quadratic_spline(cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
);
627 cx2
= (double)(cx1
+ x2
) / 2;
628 cy2
= (double)(cy1
+ y2
) / 2;
631 wx_spline_add_point( cx1
, cy1
);
632 wx_spline_add_point( x2
, y2
);
634 wx_spline_draw_point_array( this );