1 /////////////////////////////////////////////////////////////////////////////
4 // Author: Robert Roebling
6 // Copyright: (c) 1998 Robert Roebling, Markus Holzem, Chris Breeze
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
11 #pragma implementation "dcclient.h"
14 #include "wx/dcclient.h"
15 #include "wx/dcmemory.h"
18 //-----------------------------------------------------------------------------
20 //-----------------------------------------------------------------------------
30 static GdkPixmap
*hatches
[num_hatches
];
31 static GdkPixmap
**hatch_bitmap
= (GdkPixmap
**) NULL
;
33 //-----------------------------------------------------------------------------
35 //-----------------------------------------------------------------------------
37 #define RAD2DEG 57.2957795131
39 //-----------------------------------------------------------------------------
40 // temporary implementation of the missing GDK function
41 //-----------------------------------------------------------------------------
42 #include "gdk/gdkprivate.h"
43 void gdk_draw_bitmap (GdkDrawable
*drawable
,
53 GdkWindowPrivate
*drawable_private
;
54 GdkWindowPrivate
*src_private
;
55 GdkGCPrivate
*gc_private
;
57 g_return_if_fail (drawable
!= NULL
);
58 g_return_if_fail (src
!= NULL
);
59 g_return_if_fail (gc
!= NULL
);
61 drawable_private
= (GdkWindowPrivate
*) drawable
;
62 src_private
= (GdkWindowPrivate
*) src
;
63 if (drawable_private
->destroyed
|| src_private
->destroyed
)
66 gc_private
= (GdkGCPrivate
*) gc
;
68 if (width
== -1) width
= src_private
->width
;
69 if (height
== -1) height
= src_private
->height
;
71 XCopyPlane( drawable_private
->xdisplay
,
73 drawable_private
->xwindow
,
81 //-----------------------------------------------------------------------------
83 //-----------------------------------------------------------------------------
85 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC
,wxDC
)
87 wxPaintDC::wxPaintDC(void)
89 m_penGC
= (GdkGC
*) NULL
;
90 m_brushGC
= (GdkGC
*) NULL
;
91 m_textGC
= (GdkGC
*) NULL
;
92 m_bgGC
= (GdkGC
*) NULL
;
93 m_cmap
= (GdkColormap
*) NULL
;
97 wxPaintDC::wxPaintDC( wxWindow
*window
)
99 m_penGC
= (GdkGC
*) NULL
;
100 m_brushGC
= (GdkGC
*) NULL
;
101 m_textGC
= (GdkGC
*) NULL
;
102 m_bgGC
= (GdkGC
*) NULL
;
103 m_cmap
= (GdkColormap
*) NULL
;
106 GtkWidget
*widget
= window
->m_wxwindow
;
108 m_window
= widget
->window
;
109 if (!m_window
) return;
110 if (window
->m_wxwindow
)
111 m_cmap
= gtk_widget_get_colormap( window
->m_wxwindow
);
113 m_cmap
= gtk_widget_get_colormap( window
->m_widget
);
120 wxPaintDC::~wxPaintDC(void)
125 void wxPaintDC::FloodFill( long WXUNUSED(x1
), long WXUNUSED(y1
),
126 wxColour
*WXUNUSED(col
), int WXUNUSED(style
) )
128 wxFAIL_MSG( "wxPaintDC::FloodFill not implemented" );
131 bool wxPaintDC::GetPixel( long WXUNUSED(x1
), long WXUNUSED(y1
), wxColour
*WXUNUSED(col
) ) const
133 wxFAIL_MSG( "wxPaintDC::GetPixel not implemented" );
137 void wxPaintDC::DrawLine( long x1
, long y1
, long x2
, long y2
)
141 if (m_pen
.GetStyle() != wxTRANSPARENT
)
143 gdk_draw_line( m_window
, m_penGC
,
144 XLOG2DEV(x1
), YLOG2DEV(y1
), XLOG2DEV(x2
), YLOG2DEV(y2
) );
147 CalcBoundingBox(x1
, y1
);
148 CalcBoundingBox(x2
, y2
);
151 void wxPaintDC::CrossHair( long x
, long y
)
155 if (m_pen
.GetStyle() != wxTRANSPARENT
)
160 long xx
= XLOG2DEV(x
);
161 long yy
= YLOG2DEV(y
);
162 gdk_draw_line( m_window
, m_penGC
, 0, yy
, XLOG2DEVREL(w
), yy
);
163 gdk_draw_line( m_window
, m_penGC
, xx
, 0, xx
, YLOG2DEVREL(h
) );
167 void wxPaintDC::DrawArc( long x1
, long y1
, long x2
, long y2
, double xc
, double yc
)
171 long xx1
= XLOG2DEV(x1
);
172 long yy1
= YLOG2DEV(y1
);
173 long xx2
= XLOG2DEV(x2
);
174 long yy2
= YLOG2DEV(y2
);
175 long xxc
= XLOG2DEV((long)xc
);
176 long yyc
= YLOG2DEV((long)yc
);
177 double dx
= xx1
- xxc
;
178 double dy
= yy1
- yyc
;
179 double radius
= sqrt(dx
*dx
+dy
*dy
);
180 long r
= (long)radius
;
181 double radius1
, radius2
;
183 if (xx1
== xx2
&& yy1
== yy2
)
191 radius1
= radius2
= 0.0;
195 radius1
= (xx1
- xxc
== 0) ?
196 (yy1
- yyc
< 0) ? 90.0 : -90.0 :
197 -atan2(double(yy1
-yyc
), double(xx1
-xxc
)) * RAD2DEG
;
198 radius2
= (xx2
- xxc
== 0) ?
199 (yy2
- yyc
< 0) ? 90.0 : -90.0 :
200 -atan2(double(yy2
-yyc
), double(xx2
-xxc
)) * RAD2DEG
;
202 long alpha1
= long(radius1
* 64.0);
203 long alpha2
= long((radius2
- radius1
) * 64.0);
204 while (alpha2
<= 0) alpha2
+= 360*64;
205 while (alpha1
> 360*64) alpha1
-= 360*64;
207 if (m_brush
.GetStyle() != wxTRANSPARENT
)
208 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
210 if (m_pen
.GetStyle() != wxTRANSPARENT
)
211 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
213 CalcBoundingBox (x1
, y1
);
214 CalcBoundingBox (x2
, y2
);
217 void wxPaintDC::DrawEllipticArc( long x
, long y
, long width
, long height
, double sa
, double ea
)
221 long xx
= XLOG2DEV(x
);
222 long yy
= YLOG2DEV(y
);
223 long ww
= m_signX
* XLOG2DEVREL(width
);
224 long hh
= m_signY
* YLOG2DEVREL(height
);
226 // CMB: handle -ve width and/or height
227 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
228 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
230 long start
= long(sa
* 64.0);
231 long end
= long(ea
* 64.0);
232 if (m_brush
.GetStyle() != wxTRANSPARENT
)
233 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end
);
235 if (m_pen
.GetStyle() != wxTRANSPARENT
)
236 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
, hh
, start
, end
);
238 CalcBoundingBox (x
, y
);
239 CalcBoundingBox (x
+ width
, y
+ height
);
242 void wxPaintDC::DrawPoint( long x
, long y
)
246 if (m_pen
.GetStyle() != wxTRANSPARENT
)
247 gdk_draw_point( m_window
, m_penGC
, XLOG2DEV(x
), YLOG2DEV(y
) );
249 CalcBoundingBox (x
, y
);
252 void wxPaintDC::DrawLines( int n
, wxPoint points
[], long xoffset
, long yoffset
)
256 if (m_pen
.GetStyle() == wxTRANSPARENT
) return;
259 CalcBoundingBox( points
[0].x
+ xoffset
, points
[0].y
+ yoffset
);
261 for (int i
= 0; i
< n
-1; i
++)
263 long x1
= XLOG2DEV(points
[i
].x
+ xoffset
);
264 long x2
= XLOG2DEV(points
[i
+1].x
+ xoffset
);
265 long y1
= YLOG2DEV(points
[i
].y
+ yoffset
); // oh, what a waste
266 long y2
= YLOG2DEV(points
[i
+1].y
+ yoffset
);
267 gdk_draw_line( m_window
, m_penGC
, x1
, y1
, x2
, y2
);
269 CalcBoundingBox( points
[i
+1].x
+ xoffset
, points
[i
+1].y
+ yoffset
);
273 void wxPaintDC::DrawLines( wxList
*points
, long xoffset
, long yoffset
)
277 if (m_pen
.GetStyle() == wxTRANSPARENT
) return;
279 wxNode
*node
= points
->First();
282 wxPoint
*pt
= (wxPoint
*)node
->Data();
283 CalcBoundingBox( pt
->x
+ xoffset
, pt
->y
+ yoffset
);
287 wxPoint
*point
= (wxPoint
*)node
->Data();
288 wxPoint
*npoint
= (wxPoint
*)node
->Next()->Data();
289 long x1
= XLOG2DEV(point
->x
+ xoffset
);
290 long x2
= XLOG2DEV(npoint
->x
+ xoffset
);
291 long y1
= YLOG2DEV(point
->y
+ yoffset
); // and a waste again...
292 long y2
= YLOG2DEV(npoint
->y
+ yoffset
);
293 gdk_draw_line( m_window
, m_penGC
, x1
, y1
, x2
, y2
);
296 CalcBoundingBox( npoint
->x
+ xoffset
, npoint
->y
+ yoffset
);
300 void wxPaintDC::DrawPolygon( int n
, wxPoint points
[], long xoffset
, long yoffset
, int WXUNUSED(fillStyle
) )
306 GdkPoint
*gdkpoints
= new GdkPoint
[n
+1];
308 for (i
= 0 ; i
< n
; i
++)
310 gdkpoints
[i
].x
= XLOG2DEV(points
[i
].x
+ xoffset
);
311 gdkpoints
[i
].y
= YLOG2DEV(points
[i
].y
+ yoffset
);
313 CalcBoundingBox( points
[i
].x
+ xoffset
, points
[i
].y
+ yoffset
);
316 if (m_brush
.GetStyle() != wxTRANSPARENT
)
317 gdk_draw_polygon (m_window
, m_brushGC
, TRUE
, gdkpoints
, n
);
321 if (m_pen
.GetStyle() != wxTRANSPARENT
)
322 for (i
= 0 ; i
< n
; i
++)
324 gdk_draw_line( m_window
, m_penGC
,
327 gdkpoints
[(i
+1)%n
].x
,
328 gdkpoints
[(i
+1)%n
].y
);
334 void wxPaintDC::DrawPolygon( wxList
*lines
, long xoffset
, long yoffset
, int WXUNUSED(fillStyle
))
338 int n
= lines
->Number();
341 GdkPoint
*gdkpoints
= new GdkPoint
[n
];
342 wxNode
*node
= lines
->First();
346 wxPoint
*p
= (wxPoint
*) node
->Data();
347 gdkpoints
[cnt
].x
= XLOG2DEV(p
->x
+ xoffset
);
348 gdkpoints
[cnt
].y
= YLOG2DEV(p
->y
+ yoffset
);
352 CalcBoundingBox( p
->x
+ xoffset
, p
->y
+ yoffset
);
355 if (m_brush
.GetStyle() != wxTRANSPARENT
)
356 gdk_draw_polygon (m_window
, m_brushGC
, TRUE
, gdkpoints
, n
);
360 if (m_pen
.GetStyle() != wxTRANSPARENT
)
363 for (i
= 0 ; i
< n
; i
++)
365 gdk_draw_line( m_window
, m_penGC
,
368 gdkpoints
[(i
+1)%n
].x
,
369 gdkpoints
[(i
+1)%n
].y
);
375 void wxPaintDC::DrawRectangle( long x
, long y
, long width
, long height
)
379 long xx
= XLOG2DEV(x
);
380 long yy
= YLOG2DEV(y
);
381 long ww
= m_signX
* XLOG2DEVREL(width
);
382 long hh
= m_signY
* YLOG2DEVREL(height
);
384 // CMB: draw nothing if transformed w or h is 0
385 if (ww
== 0 || hh
== 0) return;
387 // CMB: handle -ve width and/or height
388 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
389 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
391 if (m_brush
.GetStyle() != wxTRANSPARENT
)
392 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
);
394 if (m_pen
.GetStyle() != wxTRANSPARENT
)
395 gdk_draw_rectangle( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
-1, hh
-1 );
397 CalcBoundingBox( x
, y
);
398 CalcBoundingBox( x
+ width
, y
+ height
);
401 void wxPaintDC::DrawRoundedRectangle( long x
, long y
, long width
, long height
, double radius
)
405 if (radius
< 0.0) radius
= - radius
* ((width
< height
) ? width
: height
);
407 long xx
= XLOG2DEV(x
);
408 long yy
= YLOG2DEV(y
);
409 long ww
= m_signX
* XLOG2DEVREL(width
);
410 long hh
= m_signY
* YLOG2DEVREL(height
);
411 long rr
= XLOG2DEVREL((long)radius
);
413 // CMB: handle -ve width and/or height
414 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
415 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
417 // CMB: if radius is zero use DrawRectangle() instead to avoid
418 // X drawing errors with small radii
421 DrawRectangle( x
, y
, width
, height
);
425 // CMB: draw nothing if transformed w or h is 0
426 if (ww
== 0 || hh
== 0) return;
428 // CMB: adjust size if outline is drawn otherwise the result is
429 // 1 pixel too wide and high
430 if (m_pen
.GetStyle() != wxTRANSPARENT
)
436 // CMB: ensure dd is not larger than rectangle otherwise we
437 // get an hour glass shape
439 if (dd
> ww
) dd
= ww
;
440 if (dd
> hh
) dd
= hh
;
443 if (m_brush
.GetStyle() != wxTRANSPARENT
)
445 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh
);
446 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 );
447 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
448 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
449 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
450 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
453 if (m_pen
.GetStyle() != wxTRANSPARENT
)
455 gdk_draw_line( m_window
, m_penGC
, xx
+rr
, yy
, xx
+ww
-rr
, yy
);
456 gdk_draw_line( m_window
, m_penGC
, xx
+rr
, yy
+hh
, xx
+ww
-rr
, yy
+hh
);
457 gdk_draw_line( m_window
, m_penGC
, xx
, yy
+rr
, xx
, yy
+hh
-rr
);
458 gdk_draw_line( m_window
, m_penGC
, xx
+ww
, yy
+rr
, xx
+ww
, yy
+hh
-rr
);
459 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
460 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
461 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
462 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
465 // this ignores the radius
466 CalcBoundingBox( x
, y
);
467 CalcBoundingBox( x
+ width
, y
+ height
);
470 void wxPaintDC::DrawEllipse( long x
, long y
, long width
, long height
)
474 long xx
= XLOG2DEV(x
);
475 long yy
= YLOG2DEV(y
);
476 long ww
= m_signX
* XLOG2DEVREL(width
);
477 long hh
= m_signY
* YLOG2DEVREL(height
);
479 // CMB: handle -ve width and/or height
480 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
481 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
483 if (m_brush
.GetStyle() != wxTRANSPARENT
)
484 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 );
486 if (m_pen
.GetStyle() != wxTRANSPARENT
)
487 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
, hh
, 0, 360*64 );
489 CalcBoundingBox( x
, y
);
490 CalcBoundingBox( x
+ width
, y
+ height
);
493 bool wxPaintDC::CanDrawBitmap(void) const
498 void wxPaintDC::DrawIcon( const wxIcon
&icon
, long x
, long y
, bool useMask
)
502 if (!icon
.Ok()) return;
504 int xx
= XLOG2DEV(x
);
505 int yy
= YLOG2DEV(y
);
507 GdkBitmap
*mask
= (GdkBitmap
*) NULL
;
508 if (icon
.GetMask()) mask
= icon
.GetMask()->GetBitmap();
512 gdk_gc_set_clip_mask( m_penGC
, mask
);
513 gdk_gc_set_clip_origin( m_penGC
, xx
, yy
);
516 GdkPixmap
*pm
= icon
.GetPixmap();
517 gdk_draw_pixmap( m_window
, m_penGC
, pm
, 0, 0, xx
, yy
, -1, -1 );
521 gdk_gc_set_clip_mask( m_penGC
, (GdkBitmap
*) NULL
);
522 gdk_gc_set_clip_origin( m_penGC
, 0, 0 );
525 CalcBoundingBox( x
, y
);
526 int width
= icon
.GetWidth();
527 int height
= icon
.GetHeight();
528 CalcBoundingBox( x
+ width
, y
+ height
);
531 bool wxPaintDC::Blit( long xdest
, long ydest
, long width
, long height
,
532 wxDC
*source
, long xsrc
, long ysrc
, int WXUNUSED(logical_func
), bool useMask
)
534 if (!Ok()) return FALSE
;
536 CalcBoundingBox( xdest
, ydest
);
537 CalcBoundingBox( xdest
+ width
, ydest
+ height
);
539 wxClientDC
*csrc
= (wxClientDC
*)source
;
543 wxMemoryDC
* srcDC
= (wxMemoryDC
*)source
;
544 GdkPixmap
* pmap
= srcDC
->m_selected
.GetPixmap();
547 long xx
= XLOG2DEV(xdest
);
548 long yy
= YLOG2DEV(ydest
);
550 GdkBitmap
*mask
= (GdkBitmap
*) NULL
;
551 if (srcDC
->m_selected
.GetMask()) mask
= srcDC
->m_selected
.GetMask()->GetBitmap();
555 gdk_gc_set_clip_mask( m_textGC
, mask
);
556 gdk_gc_set_clip_origin( m_textGC
, xx
, yy
);
559 gdk_draw_pixmap( m_window
, m_textGC
, pmap
,
560 source
->DeviceToLogicalX(xsrc
),
561 source
->DeviceToLogicalY(ysrc
),
564 source
->DeviceToLogicalXRel(width
),
565 source
->DeviceToLogicalYRel(height
) );
569 gdk_gc_set_clip_mask( m_textGC
, (GdkBitmap
*) NULL
);
570 gdk_gc_set_clip_origin( m_textGC
, 0, 0 );
576 GdkBitmap
* bmap
= srcDC
->m_selected
.GetBitmap();
579 long xx
= XLOG2DEV(xdest
);
580 long yy
= YLOG2DEV(ydest
);
582 GdkBitmap
*mask
= (GdkBitmap
*) NULL
;
583 if (srcDC
->m_selected
.GetMask()) mask
= srcDC
->m_selected
.GetMask()->GetBitmap();
587 gdk_gc_set_clip_mask( m_textGC
, mask
);
588 gdk_gc_set_clip_origin( m_textGC
, xx
, yy
);
591 gdk_draw_bitmap( m_window
, m_textGC
, bmap
,
592 source
->DeviceToLogicalX(xsrc
),
593 source
->DeviceToLogicalY(ysrc
),
596 source
->DeviceToLogicalXRel(width
),
597 source
->DeviceToLogicalYRel(height
) );
601 gdk_gc_set_clip_mask( m_textGC
, (GdkBitmap
*) NULL
);
602 gdk_gc_set_clip_origin( m_textGC
, 0, 0 );
609 gdk_window_copy_area ( m_window
, m_textGC
,
610 XLOG2DEV(xdest
), YLOG2DEV(ydest
),
612 source
->DeviceToLogicalX(xsrc
),
613 source
->DeviceToLogicalY(ysrc
),
614 source
->DeviceToLogicalXRel(width
),
615 source
->DeviceToLogicalYRel(height
) );
618 gdk_window_copy_area ( m_window, m_textGC,
619 XLOG2DEV(xdest), YLOG2DEV(ydest),
628 void wxPaintDC::DrawText( const wxString
&text
, long x
, long y
, bool WXUNUSED(use16
) )
632 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
637 // CMB 21/5/98: draw text background if mode is wxSOLID
638 if (m_backgroundMode
== wxSOLID
)
640 long width
= gdk_string_width( font
, text
);
641 long height
= font
->ascent
+ font
->descent
;
642 gdk_gc_set_foreground( m_textGC
, m_textBackgroundColour
.GetColor() );
643 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, x
, y
, width
, height
);
644 gdk_gc_set_foreground( m_textGC
, m_textForegroundColour
.GetColor() );
646 gdk_draw_string( m_window
, font
, m_textGC
, x
, y
+ font
->ascent
, text
);
648 // CMB 17/7/98: simple underline: ignores scaling and underlying
649 // X font's XA_UNDERLINE_POSITION and XA_UNDERLINE_THICKNESS
650 // properties (see wxXt implementation)
651 if (m_font
.GetUnderlined())
653 long width
= gdk_string_width( font
, text
);
654 long ul_y
= y
+ font
->ascent
;
655 if (font
->descent
> 0) ul_y
++;
656 gdk_draw_line( m_window
, m_textGC
, x
, ul_y
, x
+ width
, ul_y
);
660 GetTextExtent (text
, &w
, &h
);
661 CalcBoundingBox (x
+ w
, y
+ h
);
662 CalcBoundingBox (x
, y
);
665 bool wxPaintDC::CanGetTextExtent(void) const
670 void wxPaintDC::GetTextExtent( const wxString
&string
, long *width
, long *height
,
671 long *descent
, long *externalLeading
,
672 wxFont
*theFont
, bool WXUNUSED(use16
) )
676 wxFont fontToUse
= m_font
;
677 if (theFont
) fontToUse
= *theFont
;
679 GdkFont
*font
= fontToUse
.GetInternalFont( m_scaleY
);
680 if (width
) (*width
) = long(gdk_string_width( font
, string
) / m_scaleX
);
681 if (height
) (*height
) = long((font
->ascent
+ font
->descent
) / m_scaleY
);
682 if (descent
) (*descent
) = long(font
->descent
/ m_scaleY
);
683 if (externalLeading
) (*externalLeading
) = 0; // ??
686 long wxPaintDC::GetCharWidth(void)
690 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
691 return long(gdk_string_width( font
, "H" ) / m_scaleX
);
694 long wxPaintDC::GetCharHeight(void)
698 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
699 return long((font
->ascent
+ font
->descent
) / m_scaleY
);
702 void wxPaintDC::Clear(void)
708 gdk_window_clear( m_window
);
713 GetSize( &width
, &height
);
714 gdk_draw_rectangle( m_window
, m_bgGC
, TRUE
, 0, 0, width
, height
);
718 void wxPaintDC::SetFont( const wxFont
&font
)
725 void wxPaintDC::SetPen( const wxPen
&pen
)
729 if (m_pen
== pen
) return;
733 if (!m_pen
.Ok()) return;
735 gint width
= m_pen
.GetWidth();
736 // CMB: if width is non-zero scale it with the dc
743 // X doesn't allow different width in x and y and so we take
745 double w
= 0.5 + (abs(XLOG2DEVREL(width
)) + abs(YLOG2DEVREL(width
))) / 2.0;
749 GdkLineStyle lineStyle
= GDK_LINE_SOLID
;
750 switch (m_pen
.GetStyle())
752 case wxSOLID
: { lineStyle
= GDK_LINE_SOLID
; break; }
753 case wxDOT
: { lineStyle
= GDK_LINE_ON_OFF_DASH
; break; }
754 case wxLONG_DASH
: { lineStyle
= GDK_LINE_ON_OFF_DASH
; break; }
755 case wxSHORT_DASH
: { lineStyle
= GDK_LINE_ON_OFF_DASH
; break; }
756 case wxDOT_DASH
: { lineStyle
= GDK_LINE_DOUBLE_DASH
; break; }
759 GdkCapStyle capStyle
= GDK_CAP_ROUND
;
760 switch (m_pen
.GetCap())
762 case wxCAP_ROUND
: { capStyle
= (width
<= 1) ? GDK_CAP_NOT_LAST
: GDK_CAP_ROUND
; break; }
763 case wxCAP_PROJECTING
: { capStyle
= GDK_CAP_PROJECTING
; break; }
764 case wxCAP_BUTT
: { capStyle
= GDK_CAP_BUTT
; break; }
767 GdkJoinStyle joinStyle
= GDK_JOIN_ROUND
;
768 switch (m_pen
.GetJoin())
770 case wxJOIN_BEVEL
: { joinStyle
= GDK_JOIN_BEVEL
; break; }
771 case wxJOIN_ROUND
: { joinStyle
= GDK_JOIN_ROUND
; break; }
772 case wxJOIN_MITER
: { joinStyle
= GDK_JOIN_MITER
; break; }
775 gdk_gc_set_line_attributes( m_penGC
, width
, lineStyle
, capStyle
, joinStyle
);
777 m_pen
.GetColour().CalcPixel( m_cmap
);
778 gdk_gc_set_foreground( m_penGC
, m_pen
.GetColour().GetColor() );
781 void wxPaintDC::SetBrush( const wxBrush
&brush
)
785 if (m_brush
== brush
) return;
789 if (!m_brush
.Ok()) return;
791 m_brush
.GetColour().CalcPixel( m_cmap
);
792 gdk_gc_set_foreground( m_brushGC
, m_brush
.GetColour().GetColor() );
794 GdkFill fillStyle
= GDK_SOLID
;
795 switch (m_brush
.GetStyle())
801 fillStyle
= GDK_STIPPLED
;
804 gdk_gc_set_fill( m_brushGC
, fillStyle
);
806 if (m_brush
.GetStyle() == wxSTIPPLE
)
808 gdk_gc_set_stipple( m_brushGC
, m_brush
.GetStipple()->GetPixmap() );
811 if (IS_HATCH(m_brush
.GetStyle()))
813 int num
= m_brush
.GetStyle() - wxBDIAGONAL_HATCH
;
814 gdk_gc_set_stipple( m_brushGC
, hatches
[num
] );
818 // CMB 21/7/98: Added SetBackground. Sets background brush
819 // for Clear() and bg colour for shapes filled with cross-hatch brush
820 void wxPaintDC::SetBackground( const wxBrush
&brush
)
824 if (m_backgroundBrush
== brush
) return;
826 m_backgroundBrush
= brush
;
828 if (!m_backgroundBrush
.Ok()) return;
830 m_backgroundBrush
.GetColour().CalcPixel( m_cmap
);
831 gdk_gc_set_background( m_brushGC
, m_backgroundBrush
.GetColour().GetColor() );
832 gdk_gc_set_foreground( m_bgGC
, m_backgroundBrush
.GetColour().GetColor() );
834 GdkFill fillStyle
= GDK_SOLID
;
835 switch (m_backgroundBrush
.GetStyle())
841 fillStyle
= GDK_STIPPLED
;
844 gdk_gc_set_fill( m_bgGC
, fillStyle
);
846 if (m_backgroundBrush
.GetStyle() == wxSTIPPLE
)
848 gdk_gc_set_stipple( m_bgGC
, m_backgroundBrush
.GetStipple()->GetPixmap() );
851 if (IS_HATCH(m_backgroundBrush
.GetStyle()))
853 int num
= m_backgroundBrush
.GetStyle() - wxBDIAGONAL_HATCH
;
854 gdk_gc_set_stipple( m_bgGC
, hatches
[num
] );
858 void wxPaintDC::SetLogicalFunction( int function
)
860 if (m_logicalFunction
== function
) return;
861 GdkFunction mode
= GDK_COPY
;
864 case wxXOR
: mode
= GDK_INVERT
; break;
865 case wxINVERT
: mode
= GDK_INVERT
; break;
868 m_logicalFunction
= function
;
869 gdk_gc_set_function( m_penGC
, mode
);
870 gdk_gc_set_function( m_brushGC
, mode
);
873 void wxPaintDC::SetTextForeground( const wxColour
&col
)
877 if (m_textForegroundColour
== col
) return;
879 m_textForegroundColour
= col
;
880 if (!m_textForegroundColour
.Ok()) return;
882 m_textForegroundColour
.CalcPixel( m_cmap
);
883 gdk_gc_set_foreground( m_textGC
, m_textForegroundColour
.GetColor() );
886 void wxPaintDC::SetTextBackground( const wxColour
&col
)
890 if (m_textBackgroundColour
== col
) return;
892 m_textBackgroundColour
= col
;
893 if (!m_textBackgroundColour
.Ok()) return;
895 m_textBackgroundColour
.CalcPixel( m_cmap
);
896 gdk_gc_set_background( m_textGC
, m_textBackgroundColour
.GetColor() );
899 void wxPaintDC::SetBackgroundMode( int mode
)
901 m_backgroundMode
= mode
;
903 // CMB 21/7/98: fill style of cross-hatch brushes is affected by
904 // transparent/solid background mode
905 if (m_brush
.GetStyle() != wxSOLID
&& m_brush
.GetStyle() != wxTRANSPARENT
)
907 gdk_gc_set_fill( m_brushGC
,
908 (m_backgroundMode
== wxTRANSPARENT
) ? GDK_STIPPLED
: GDK_OPAQUE_STIPPLED
);
912 void wxPaintDC::SetPalette( const wxPalette
& WXUNUSED(palette
) )
916 void wxPaintDC::SetClippingRegion( long x
, long y
, long width
, long height
)
918 wxDC::SetClippingRegion( x
, y
, width
, height
);
921 rect
.x
= XLOG2DEV(x
);
922 rect
.y
= YLOG2DEV(y
);
923 rect
.width
= XLOG2DEVREL(width
);
924 rect
.height
= YLOG2DEVREL(height
);
925 gdk_gc_set_clip_rectangle( m_penGC
, &rect
);
926 gdk_gc_set_clip_rectangle( m_brushGC
, &rect
);
927 gdk_gc_set_clip_rectangle( m_textGC
, &rect
);
928 gdk_gc_set_clip_rectangle( m_bgGC
, &rect
);
931 void wxPaintDC::DestroyClippingRegion(void)
933 wxDC::DestroyClippingRegion();
935 gdk_gc_set_clip_rectangle( m_penGC
, (GdkRectangle
*) NULL
);
936 gdk_gc_set_clip_rectangle( m_brushGC
, (GdkRectangle
*) NULL
);
937 gdk_gc_set_clip_rectangle( m_textGC
, (GdkRectangle
*) NULL
);
938 gdk_gc_set_clip_rectangle( m_bgGC
, (GdkRectangle
*) NULL
);
941 void wxPaintDC::SetUpDC(void)
945 m_logicalFunction
= wxCOPY
;
946 m_penGC
= gdk_gc_new( m_window
);
947 m_brushGC
= gdk_gc_new( m_window
);
948 m_textGC
= gdk_gc_new( m_window
);
949 m_bgGC
= gdk_gc_new( m_window
);
950 SetTextForeground( m_textForegroundColour
);
951 SetTextBackground( m_textBackgroundColour
);
956 gdk_gc_set_background( m_penGC
, wxWHITE
->GetColor() );
960 hatch_bitmap
= hatches
;
961 hatch_bitmap
[0] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, bdiag_bits
, bdiag_width
, bdiag_height
);
962 hatch_bitmap
[1] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, cdiag_bits
, cdiag_width
, cdiag_height
);
963 hatch_bitmap
[2] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, fdiag_bits
, fdiag_width
, fdiag_height
);
964 hatch_bitmap
[3] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, cross_bits
, cross_width
, cross_height
);
965 hatch_bitmap
[4] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, horiz_bits
, horiz_width
, horiz_height
);
966 hatch_bitmap
[5] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, verti_bits
, verti_width
, verti_height
);
970 void wxPaintDC::Destroy(void)
972 if (m_penGC
) gdk_gc_unref( m_penGC
);
973 m_penGC
= (GdkGC
*) NULL
;
974 if (m_brushGC
) gdk_gc_unref( m_brushGC
);
975 m_brushGC
= (GdkGC
*) NULL
;
976 if (m_textGC
) gdk_gc_unref( m_textGC
);
977 m_textGC
= (GdkGC
*) NULL
;
978 if (m_bgGC
) gdk_gc_unref( m_bgGC
);
979 m_bgGC
= (GdkGC
*) NULL
;
982 GdkWindow
*wxPaintDC::GetWindow(void)
987 // ----------------------------------- spline code ----------------------------------------
989 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
,
990 double a3
, double b3
, double a4
, double b4
);
991 void wx_clear_stack(void);
992 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
, double *x3
,
993 double *y3
, double *x4
, double *y4
);
994 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
,
995 double x4
, double y4
);
996 static bool wx_spline_add_point(double x
, double y
);
997 static void wx_spline_draw_point_array(wxDC
*dc
);
999 wxList wx_spline_point_list
;
1001 #define half(z1, z2) ((z1+z2)/2.0)
1004 /* iterative version */
1006 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
, double a3
, double b3
, double a4
,
1009 register double xmid
, ymid
;
1010 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
1013 wx_spline_push(a1
, b1
, a2
, b2
, a3
, b3
, a4
, b4
);
1015 while (wx_spline_pop(&x1
, &y1
, &x2
, &y2
, &x3
, &y3
, &x4
, &y4
)) {
1016 xmid
= (double)half(x2
, x3
);
1017 ymid
= (double)half(y2
, y3
);
1018 if (fabs(x1
- xmid
) < THRESHOLD
&& fabs(y1
- ymid
) < THRESHOLD
&&
1019 fabs(xmid
- x4
) < THRESHOLD
&& fabs(ymid
- y4
) < THRESHOLD
) {
1020 wx_spline_add_point( x1
, y1
);
1021 wx_spline_add_point( xmid
, ymid
);
1023 wx_spline_push(xmid
, ymid
, (double)half(xmid
, x3
), (double)half(ymid
, y3
),
1024 (double)half(x3
, x4
), (double)half(y3
, y4
), x4
, y4
);
1025 wx_spline_push(x1
, y1
, (double)half(x1
, x2
), (double)half(y1
, y2
),
1026 (double)half(x2
, xmid
), (double)half(y2
, ymid
), xmid
, ymid
);
1031 /* utilities used by spline drawing routines */
1033 typedef struct wx_spline_stack_struct
{
1034 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
1037 #define SPLINE_STACK_DEPTH 20
1038 static Stack wx_spline_stack
[SPLINE_STACK_DEPTH
];
1039 static Stack
*wx_stack_top
;
1040 static int wx_stack_count
;
1042 void wx_clear_stack(void)
1044 wx_stack_top
= wx_spline_stack
;
1048 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
, double x4
, double y4
)
1050 wx_stack_top
->x1
= x1
;
1051 wx_stack_top
->y1
= y1
;
1052 wx_stack_top
->x2
= x2
;
1053 wx_stack_top
->y2
= y2
;
1054 wx_stack_top
->x3
= x3
;
1055 wx_stack_top
->y3
= y3
;
1056 wx_stack_top
->x4
= x4
;
1057 wx_stack_top
->y4
= y4
;
1062 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
,
1063 double *x3
, double *y3
, double *x4
, double *y4
)
1065 if (wx_stack_count
== 0)
1069 *x1
= wx_stack_top
->x1
;
1070 *y1
= wx_stack_top
->y1
;
1071 *x2
= wx_stack_top
->x2
;
1072 *y2
= wx_stack_top
->y2
;
1073 *x3
= wx_stack_top
->x3
;
1074 *y3
= wx_stack_top
->y3
;
1075 *x4
= wx_stack_top
->x4
;
1076 *y4
= wx_stack_top
->y4
;
1080 static bool wx_spline_add_point(double x
, double y
)
1082 wxPoint
*point
= new wxPoint
;
1085 wx_spline_point_list
.Append((wxObject
*)point
);
1089 static void wx_spline_draw_point_array(wxDC
*dc
)
1091 dc
->DrawLines(&wx_spline_point_list
, 0, 0 );
1092 wxNode
*node
= wx_spline_point_list
.First();
1095 wxPoint
*point
= (wxPoint
*)node
->Data();
1098 node
= wx_spline_point_list
.First();
1102 void wxPaintDC::DrawSpline( wxList
*points
)
1105 double cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
;
1106 double x1
, y1
, x2
, y2
;
1108 wxNode
*node
= points
->First();
1109 p
= (wxPoint
*)node
->Data();
1114 node
= node
->Next();
1115 p
= (wxPoint
*)node
->Data();
1119 cx1
= (double)((x1
+ x2
) / 2);
1120 cy1
= (double)((y1
+ y2
) / 2);
1121 cx2
= (double)((cx1
+ x2
) / 2);
1122 cy2
= (double)((cy1
+ y2
) / 2);
1124 wx_spline_add_point(x1
, y1
);
1126 while ((node
= node
->Next()) != NULL
)
1128 p
= (wxPoint
*)node
->Data();
1133 cx4
= (double)(x1
+ x2
) / 2;
1134 cy4
= (double)(y1
+ y2
) / 2;
1135 cx3
= (double)(x1
+ cx4
) / 2;
1136 cy3
= (double)(y1
+ cy4
) / 2;
1138 wx_quadratic_spline(cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
);
1142 cx2
= (double)(cx1
+ x2
) / 2;
1143 cy2
= (double)(cy1
+ y2
) / 2;
1146 wx_spline_add_point( cx1
, cy1
);
1147 wx_spline_add_point( x2
, y2
);
1149 wx_spline_draw_point_array( this );