1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxClientDC class
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation "dcclient.h"
16 #include "wx/dcclient.h"
17 #include "wx/dcmemory.h"
18 #include "wx/window.h"
23 #include "wx/motif/private.h"
25 //-----------------------------------------------------------------------------
27 //-----------------------------------------------------------------------------
29 #define RAD2DEG 57.2957795131
31 //-----------------------------------------------------------------------------
33 //-----------------------------------------------------------------------------
35 #if !USE_SHARED_LIBRARY
36 //IMPLEMENT_DYNAMIC_CLASS(wxClientDC, wxDC)
37 //IMPLEMENT_DYNAMIC_CLASS(wxWindowDC, wxDC)
38 IMPLEMENT_DYNAMIC_CLASS(wxWindowDC
, wxDC
)
42 wxWindowDC
::wxWindowDC(void)
45 m_gcBacking
= (WXGC
) 0;
47 m_backgroundPixel
= -1;
48 m_currentPenWidth
= 1;
49 m_currentPenJoin
= -1;
50 m_currentPenDashCount
= -1;
51 m_currentPenDash
= (char*) NULL
;
54 m_currentBkMode
= wxTRANSPARENT
;
55 m_colour
= wxColourDisplay();
56 m_display
= (WXDisplay
*) NULL
;
57 m_clippingRegion
= (WXRegion
) 0;
60 wxWindowDC
::wxWindowDC( wxWindow
*window
)
64 m_gcBacking
= (WXGC
) 0;
66 m_backgroundPixel
= -1;
67 m_currentPenWidth
= 1;
68 m_currentPenJoin
= -1;
69 m_currentPenDashCount
= -1;
70 m_currentPenDash
= (char*) NULL
;
73 m_currentBkMode
= wxTRANSPARENT
;
74 m_colour
= wxColourDisplay();
75 m_display
= window
->GetXDisplay();
76 m_clippingRegion
= (WXRegion
) 0;
80 wxWindowDC
::~wxWindowDC(void)
83 XFreeGC ((Display
*) m_display
, (GC
) m_gc
);
87 XFreeGC ((Display
*) m_display
, (GC
) m_gcBacking
);
88 m_gcBacking
= (WXGC
) 0;
91 XDestroyRegion ((Region
) m_clippingRegion
);
92 m_clippingRegion
= (WXRegion
) 0;
95 void wxWindowDC
::FloodFill( long WXUNUSED(x1
), long WXUNUSED(y1
),
96 wxColour
* WXUNUSED(col
), int WXUNUSED(style
) )
100 bool wxWindowDC
::GetPixel( long WXUNUSED(x1
), long WXUNUSED(y1
), wxColour
*WXUNUSED(col
) ) const
105 void wxWindowDC
::DrawLine( long x1
, long y1
, long x2
, long y2
)
109 int x1d
, y1d
, x2d
, y2d
;
111 /* MATTHEW: [7] Implement GetPixel */
119 if (current_pen
&& autoSetting
)
120 SetPen (current_pen
);
121 XDrawLine (display
, pixmap
, gc
, x1d
, y1d
, x2d
, y2d
);
123 if (canvas
&& canvas
->is_retained
)
124 XDrawLine (display
, canvas
->backingPixmap
, gcBacking
,
125 XLOG2DEV_2(x1
), YLOG2DEV_2(y1
),
126 XLOG2DEV_2(x2
), YLOG2DEV_2(y2
));
128 CalcBoundingBox(x1
, y1
);
129 CalcBoundingBox(x2
, y2
);
133 void wxWindowDC
::CrossHair( long x
, long y
)
139 void wxWindowDC
::DrawArc( long x1
, long y1
, long x2
, long y2
, long xc
, long yc
)
143 long xx1
= XLOG2DEV(x1
);
144 long yy1
= YLOG2DEV(y1
);
145 long xx2
= XLOG2DEV(x2
);
146 long yy2
= YLOG2DEV(y2
);
147 long xxc
= XLOG2DEV((long)xc
);
148 long yyc
= YLOG2DEV((long)yc
);
149 double dx
= xx1
- xxc
;
150 double dy
= yy1
- yyc
;
151 double radius
= sqrt(dx
*dx
+dy
*dy
);
152 long r
= (long)radius
;
153 double radius1
, radius2
;
155 if (xx1
== xx2
&& yy1
== yy2
)
163 radius1
= radius2
= 0.0;
167 radius1
= (xx1
- xxc
== 0) ?
168 (yy1
- yyc
< 0) ?
90.0 : -90.0 :
169 -atan2(double(yy1
-yyc
), double(xx1
-xxc
)) * RAD2DEG
;
170 radius2
= (xx2
- xxc
== 0) ?
171 (yy2
- yyc
< 0) ?
90.0 : -90.0 :
172 -atan2(double(yy2
-yyc
), double(xx2
-xxc
)) * RAD2DEG
;
174 long alpha1
= long(radius1
* 64.0);
175 long alpha2
= long((radius2
- radius1
) * 64.0);
176 while (alpha2
<= 0) alpha2
+= 360*64;
177 while (alpha1
> 360*64) alpha1
-= 360*64;
179 if (m_brush
.GetStyle() != wxTRANSPARENT
) {};
181 if (m_pen
.GetStyle() != wxTRANSPARENT
) {};
185 void wxWindowDC
::DrawEllipticArc( long x
, long y
, long width
, long height
, double sa
, double ea
)
189 long xx
= XLOG2DEV(x
);
190 long yy
= YLOG2DEV(y
);
191 long ww
= m_signX
* XLOG2DEVREL(width
);
192 long hh
= m_signY
* YLOG2DEVREL(height
);
194 // CMB: handle -ve width and/or height
195 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
196 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
198 long start
= long(sa
* 64.0);
199 long end
= long(ea
* 64.0);
200 if (m_brush
.GetStyle() != wxTRANSPARENT
) {};
202 if (m_pen
.GetStyle() != wxTRANSPARENT
) {};
205 void wxWindowDC
::DrawPoint( long x
, long y
)
209 if (m_pen
.GetStyle() != wxTRANSPARENT
) {};
212 void wxWindowDC
::DrawLines( int n
, wxPoint points
[], long xoffset
, long yoffset
)
216 if (m_pen
.GetStyle() == wxTRANSPARENT
) return;
218 for (int i
= 0; i
< n
-1; i
++)
220 long x1
= XLOG2DEV(points
[i
].x
+ xoffset
);
221 long x2
= XLOG2DEV(points
[i
+1].x
+ xoffset
);
222 long y1
= YLOG2DEV(points
[i
].y
+ yoffset
); // oh, what a waste
223 long y2
= YLOG2DEV(points
[i
+1].y
+ yoffset
);
227 void wxWindowDC
::DrawLines( wxList
*points
, long xoffset
, long yoffset
)
231 if (m_pen
.GetStyle() == wxTRANSPARENT
) return;
233 wxNode
*node
= points
->First();
236 wxPoint
*point
= (wxPoint
*)node
->Data();
237 wxPoint
*npoint
= (wxPoint
*)node
->Next()->Data();
238 long x1
= XLOG2DEV(point
->x
+ xoffset
);
239 long x2
= XLOG2DEV(npoint
->x
+ xoffset
);
240 long y1
= YLOG2DEV(point
->y
+ yoffset
); // and again...
241 long y2
= YLOG2DEV(npoint
->y
+ yoffset
);
246 void wxWindowDC
::DrawPolygon( int WXUNUSED(n
), wxPoint
WXUNUSED(points
)[],
247 long WXUNUSED(xoffset
), long WXUNUSED(yoffset
), int WXUNUSED(fillStyle
) )
252 void wxWindowDC
::DrawPolygon( wxList
*WXUNUSED(lines
), long WXUNUSED(xoffset
),
253 long WXUNUSED(yoffset
), int WXUNUSED(fillStyle
) )
258 void wxWindowDC
::DrawRectangle( long x
, long y
, long width
, long height
)
262 long xx
= XLOG2DEV(x
);
263 long yy
= YLOG2DEV(y
);
264 long ww
= m_signX
* XLOG2DEVREL(width
);
265 long hh
= m_signY
* YLOG2DEVREL(height
);
267 // CMB: draw nothing if transformed w or h is 0
268 if (ww
== 0 || hh
== 0) return;
270 // CMB: handle -ve width and/or height
271 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
272 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
274 if (m_brush
.GetStyle() != wxTRANSPARENT
) {};
276 if (m_pen
.GetStyle() != wxTRANSPARENT
) {};
279 void wxWindowDC
::DrawRoundedRectangle( long x
, long y
, long width
, long height
, double radius
)
283 if (radius
< 0.0) radius
= - radius
* ((width
< height
) ? width
: height
);
285 long xx
= XLOG2DEV(x
);
286 long yy
= YLOG2DEV(y
);
287 long ww
= m_signX
* XLOG2DEVREL(width
);
288 long hh
= m_signY
* YLOG2DEVREL(height
);
289 long rr
= XLOG2DEVREL((long)radius
);
291 // CMB: handle -ve width and/or height
292 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
293 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
295 // CMB: if radius is zero use DrawRectangle() instead to avoid
296 // X drawing errors with small radii
299 DrawRectangle( x
, y
, width
, height
);
303 // CMB: draw nothing if transformed w or h is 0
304 if (ww
== 0 || hh
== 0) return;
306 // CMB: adjust size if outline is drawn otherwise the result is
307 // 1 pixel too wide and high
308 if (m_pen
.GetStyle() != wxTRANSPARENT
)
314 // CMB: ensure dd is not larger than rectangle otherwise we
315 // get an hour glass shape
317 if (dd
> ww
) dd
= ww
;
318 if (dd
> hh
) dd
= hh
;
321 if (m_brush
.GetStyle() != wxTRANSPARENT
)
325 if (m_pen
.GetStyle() != wxTRANSPARENT
)
330 void wxWindowDC
::DrawEllipse( long x
, long y
, long width
, long height
)
334 long xx
= XLOG2DEV(x
);
335 long yy
= YLOG2DEV(y
);
336 long ww
= m_signX
* XLOG2DEVREL(width
);
337 long hh
= m_signY
* YLOG2DEVREL(height
);
339 // CMB: handle -ve width and/or height
340 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
341 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
343 if (m_brush
.GetStyle() != wxTRANSPARENT
) {};
345 if (m_pen
.GetStyle() != wxTRANSPARENT
) {};
348 bool wxWindowDC
::CanDrawBitmap(void) const
353 void wxWindowDC
::DrawIcon( const wxIcon
&icon
, long x
, long y
, bool useMask
)
357 if (!icon
.Ok()) return;
359 int xx
= XLOG2DEV(x
);
360 int yy
= YLOG2DEV(y
);
364 bool wxWindowDC
::Blit( long xdest
, long ydest
, long width
, long height
,
365 wxDC
*source
, long xsrc
, long ysrc
, int WXUNUSED(logical_func
), bool WXUNUSED(useMask
) )
367 if (!Ok()) return FALSE
;
369 // CMB 20/5/98: add blitting of bitmaps
370 if (source
->IsKindOf(CLASSINFO(wxMemoryDC
)))
372 wxMemoryDC
* srcDC
= (wxMemoryDC
*)source
;
374 GdkBitmap* bmap = srcDC->m_selected.GetBitmap();
381 source->DeviceToLogicalX(xsrc), source->DeviceToLogicalY(ysrc),
382 XLOG2DEV(xdest), YLOG2DEV(ydest),
383 source->DeviceToLogicalXRel(width), source->DeviceToLogicalYRel(height)
393 void wxWindowDC
::DrawText( const wxString
&text
, long x
, long y
, bool
402 bool wxWindowDC
::CanGetTextExtent(void) const
407 void wxWindowDC
::GetTextExtent( const wxString
&string
, long *width
, long *height
,
408 long *WXUNUSED(descent
), long *WXUNUSED(externalLeading
),
409 wxFont
*WXUNUSED(theFont
), bool WXUNUSED(use16
) )
415 long wxWindowDC
::GetCharWidth(void)
421 long wxWindowDC
::GetCharHeight(void)
427 void wxWindowDC
::Clear(void)
433 void wxWindowDC
::SetFont( const wxFont
&font
)
440 void wxWindowDC
::SetPen( const wxPen
&pen
)
444 if (m_pen
== pen
) return;
448 if (!m_pen
.Ok()) return;
451 void wxWindowDC
::SetBrush( const wxBrush
&brush
)
455 if (m_brush
== brush
) return;
459 if (!m_brush
.Ok()) return;
463 void wxWindowDC
::SetBackground( const wxBrush
&brush
)
467 if (m_backgroundBrush
== brush
) return;
469 m_backgroundBrush
= brush
;
471 if (!m_backgroundBrush
.Ok()) return;
475 void wxWindowDC
::SetLogicalFunction( int function
)
477 if (m_logicalFunction
== function
) return;
480 void wxWindowDC
::SetTextForeground( const wxColour
&col
)
484 if (m_textForegroundColour
== col
) return;
486 m_textForegroundColour
= col
;
487 if (!m_textForegroundColour
.Ok()) return;
490 void wxWindowDC
::SetTextBackground( const wxColour
&col
)
494 if (m_textBackgroundColour
== col
) return;
496 m_textBackgroundColour
= col
;
497 if (!m_textBackgroundColour
.Ok()) return;
500 void wxWindowDC
::SetBackgroundMode( int mode
)
502 m_backgroundMode
= mode
;
504 if (m_brush
.GetStyle() != wxSOLID
&& m_brush
.GetStyle() != wxTRANSPARENT
)
509 void wxWindowDC
::SetPalette( const wxPalette
& WXUNUSED(palette
) )
513 void wxWindowDC
::SetClippingRegion( long x
, long y
, long width
, long height
)
515 wxDC
::SetClippingRegion( x
, y
, width
, height
);
519 void wxWindowDC
::DestroyClippingRegion(void)
521 wxDC
::DestroyClippingRegion();
525 // ----------------------------------- spline code ----------------------------------------
527 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
,
528 double a3
, double b3
, double a4
, double b4
);
529 void wx_clear_stack(void);
530 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
, double *x3
,
531 double *y3
, double *x4
, double *y4
);
532 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
,
533 double x4
, double y4
);
534 static bool wx_spline_add_point(double x
, double y
);
535 static void wx_spline_draw_point_array(wxDC
*dc
);
537 wxList wx_spline_point_list
;
539 #define half(z1, z2) ((z1+z2)/2.0)
542 /* iterative version */
544 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
, double a3
, double b3
, double a4
,
547 register double xmid
, ymid
;
548 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
551 wx_spline_push(a1
, b1
, a2
, b2
, a3
, b3
, a4
, b4
);
553 while (wx_spline_pop(&x1
, &y1
, &x2
, &y2
, &x3
, &y3
, &x4
, &y4
)) {
554 xmid
= (double)half(x2
, x3
);
555 ymid
= (double)half(y2
, y3
);
556 if (fabs(x1
- xmid
) < THRESHOLD
&& fabs(y1
- ymid
) < THRESHOLD
&&
557 fabs(xmid
- x4
) < THRESHOLD
&& fabs(ymid
- y4
) < THRESHOLD
) {
558 wx_spline_add_point( x1
, y1
);
559 wx_spline_add_point( xmid
, ymid
);
561 wx_spline_push(xmid
, ymid
, (double)half(xmid
, x3
), (double)half(ymid
, y3
),
562 (double)half(x3
, x4
), (double)half(y3
, y4
), x4
, y4
);
563 wx_spline_push(x1
, y1
, (double)half(x1
, x2
), (double)half(y1
, y2
),
564 (double)half(x2
, xmid
), (double)half(y2
, ymid
), xmid
, ymid
);
569 /* utilities used by spline drawing routines */
571 typedef struct wx_spline_stack_struct
{
572 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
575 #define SPLINE_STACK_DEPTH 20
576 static Stack wx_spline_stack
[SPLINE_STACK_DEPTH
];
577 static Stack
*wx_stack_top
;
578 static int wx_stack_count
;
580 void wx_clear_stack(void)
582 wx_stack_top
= wx_spline_stack
;
586 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
, double x4
, double y4
)
588 wx_stack_top
->x1
= x1
;
589 wx_stack_top
->y1
= y1
;
590 wx_stack_top
->x2
= x2
;
591 wx_stack_top
->y2
= y2
;
592 wx_stack_top
->x3
= x3
;
593 wx_stack_top
->y3
= y3
;
594 wx_stack_top
->x4
= x4
;
595 wx_stack_top
->y4
= y4
;
600 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
,
601 double *x3
, double *y3
, double *x4
, double *y4
)
603 if (wx_stack_count
== 0)
607 *x1
= wx_stack_top
->x1
;
608 *y1
= wx_stack_top
->y1
;
609 *x2
= wx_stack_top
->x2
;
610 *y2
= wx_stack_top
->y2
;
611 *x3
= wx_stack_top
->x3
;
612 *y3
= wx_stack_top
->y3
;
613 *x4
= wx_stack_top
->x4
;
614 *y4
= wx_stack_top
->y4
;
618 static bool wx_spline_add_point(double x
, double y
)
620 wxPoint
*point
= new wxPoint
;
623 wx_spline_point_list
.Append((wxObject
*)point
);
627 static void wx_spline_draw_point_array(wxDC
*dc
)
629 dc
->DrawLines(&wx_spline_point_list
, 0, 0 );
630 wxNode
*node
= wx_spline_point_list
.First();
633 wxPoint
*point
= (wxPoint
*)node
->Data();
636 node
= wx_spline_point_list
.First();
640 void wxWindowDC
::DrawOpenSpline( wxList
*points
)
643 double cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
;
644 double x1
, y1
, x2
, y2
;
646 wxNode
*node
= points
->First();
647 p
= (wxPoint
*)node
->Data();
653 p
= (wxPoint
*)node
->Data();
657 cx1
= (double)((x1
+ x2
) / 2);
658 cy1
= (double)((y1
+ y2
) / 2);
659 cx2
= (double)((cx1
+ x2
) / 2);
660 cy2
= (double)((cy1
+ y2
) / 2);
662 wx_spline_add_point(x1
, y1
);
664 while ((node
= node
->Next()) != NULL
)
666 p
= (wxPoint
*)node
->Data();
671 cx4
= (double)(x1
+ x2
) / 2;
672 cy4
= (double)(y1
+ y2
) / 2;
673 cx3
= (double)(x1
+ cx4
) / 2;
674 cy3
= (double)(y1
+ cy4
) / 2;
676 wx_quadratic_spline(cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
);
680 cx2
= (double)(cx1
+ x2
) / 2;
681 cy2
= (double)(cy1
+ y2
) / 2;
684 wx_spline_add_point( cx1
, cy1
);
685 wx_spline_add_point( x2
, y2
);
687 wx_spline_draw_point_array( this );