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"
17 #include "wx/gtk/win_gtk.h"
19 #include <math.h> // for floating-point functions
23 //-----------------------------------------------------------------------------
25 //-----------------------------------------------------------------------------
35 static GdkPixmap
*hatches
[num_hatches
];
36 static GdkPixmap
**hatch_bitmap
= (GdkPixmap
**) NULL
;
38 //-----------------------------------------------------------------------------
40 //-----------------------------------------------------------------------------
42 const double RAD2DEG
= 180.0 / M_PI
;
44 // ----------------------------------------------------------------------------
46 // ----------------------------------------------------------------------------
48 static inline double dmax(double a
, double b
) { return a
> b
? a
: b
; }
49 static inline double dmin(double a
, double b
) { return a
< b
? a
: b
; }
51 static inline double DegToRad(double deg
) { return (deg
* M_PI
) / 180.0; }
53 //-----------------------------------------------------------------------------
54 // temporary implementation of the missing GDK function
55 //-----------------------------------------------------------------------------
57 #include "gdk/gdkprivate.h"
59 void gdk_draw_bitmap (GdkDrawable
*drawable
,
69 GdkWindowPrivate
*drawable_private
;
70 GdkWindowPrivate
*src_private
;
71 GdkGCPrivate
*gc_private
;
73 g_return_if_fail (drawable
!= NULL
);
74 g_return_if_fail (src
!= NULL
);
75 g_return_if_fail (gc
!= NULL
);
77 drawable_private
= (GdkWindowPrivate
*) drawable
;
78 src_private
= (GdkWindowPrivate
*) src
;
79 if (drawable_private
->destroyed
|| src_private
->destroyed
)
82 gc_private
= (GdkGCPrivate
*) gc
;
84 if (width
== -1) width
= src_private
->width
;
85 if (height
== -1) height
= src_private
->height
;
87 XCopyPlane( drawable_private
->xdisplay
,
89 drawable_private
->xwindow
,
97 //-----------------------------------------------------------------------------
99 //-----------------------------------------------------------------------------
101 IMPLEMENT_DYNAMIC_CLASS(wxWindowDC
, wxDC
)
103 wxWindowDC::wxWindowDC()
105 m_penGC
= (GdkGC
*) NULL
;
106 m_brushGC
= (GdkGC
*) NULL
;
107 m_textGC
= (GdkGC
*) NULL
;
108 m_bgGC
= (GdkGC
*) NULL
;
109 m_cmap
= (GdkColormap
*) NULL
;
111 m_owner
= (wxWindow
*)NULL
;
114 wxWindowDC::wxWindowDC( wxWindow
*window
)
116 m_penGC
= (GdkGC
*) NULL
;
117 m_brushGC
= (GdkGC
*) NULL
;
118 m_textGC
= (GdkGC
*) NULL
;
119 m_bgGC
= (GdkGC
*) NULL
;
120 m_cmap
= (GdkColormap
*) NULL
;
121 m_owner
= (wxWindow
*)NULL
;
123 m_font
= window
->GetFont();
125 wxASSERT_MSG( window
, wxT("DC needs a window") );
127 GtkWidget
*widget
= window
->m_wxwindow
;
129 wxASSERT_MSG( widget
, wxT("DC needs a widget") );
131 GtkPizza
*pizza
= GTK_PIZZA( widget
);
132 m_window
= pizza
->bin_window
;
137 /* don't report problems */
143 if (window
->m_wxwindow
)
144 m_cmap
= gtk_widget_get_colormap( window
->m_wxwindow
);
146 m_cmap
= gtk_widget_get_colormap( window
->m_widget
);
150 /* this must be done after SetUpDC, bacause SetUpDC calls the
151 repective SetBrush, SetPen, SetBackground etc functions
152 to set up the DC. SetBackground call m_owner->SetBackground
153 and this might not be desired as the standard dc background
154 is white whereas a window might assume gray to be the
155 standard (as e.g. wxStatusBar) */
160 wxWindowDC::~wxWindowDC()
165 void wxWindowDC::DoFloodFill( wxCoord
WXUNUSED(x
), wxCoord
WXUNUSED(y
),
166 const wxColour
&WXUNUSED(col
), int WXUNUSED(style
) )
168 wxFAIL_MSG( wxT("wxWindowDC::DoFloodFill not implemented") );
171 bool wxWindowDC::DoGetPixel( wxCoord
WXUNUSED(x1
), wxCoord
WXUNUSED(y1
), wxColour
*WXUNUSED(col
) ) const
173 wxFAIL_MSG( wxT("wxWindowDC::DoGetPixel not implemented") );
177 void wxWindowDC::DoDrawLine( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
)
179 wxCHECK_RET( Ok(), wxT("invalid window dc") );
181 if (m_pen
.GetStyle() != wxTRANSPARENT
)
184 gdk_draw_line( m_window
, m_penGC
, XLOG2DEV(x1
), YLOG2DEV(y1
), XLOG2DEV(x2
), YLOG2DEV(y2
) );
186 CalcBoundingBox(x1
, y1
);
187 CalcBoundingBox(x2
, y2
);
191 void wxWindowDC::DoCrossHair( wxCoord x
, wxCoord y
)
193 wxCHECK_RET( Ok(), wxT("invalid window dc") );
195 if (m_pen
.GetStyle() != wxTRANSPARENT
)
200 wxCoord xx
= XLOG2DEV(x
);
201 wxCoord yy
= YLOG2DEV(y
);
204 gdk_draw_line( m_window
, m_penGC
, 0, yy
, XLOG2DEVREL(w
), yy
);
205 gdk_draw_line( m_window
, m_penGC
, xx
, 0, xx
, YLOG2DEVREL(h
) );
210 void wxWindowDC::DoDrawArc( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
,
211 wxCoord xc
, wxCoord yc
)
213 wxCHECK_RET( Ok(), wxT("invalid window dc") );
215 wxCoord xx1
= XLOG2DEV(x1
);
216 wxCoord yy1
= YLOG2DEV(y1
);
217 wxCoord xx2
= XLOG2DEV(x2
);
218 wxCoord yy2
= YLOG2DEV(y2
);
219 wxCoord xxc
= XLOG2DEV(xc
);
220 wxCoord yyc
= YLOG2DEV(yc
);
221 double dx
= xx1
- xxc
;
222 double dy
= yy1
- yyc
;
223 double radius
= sqrt((double)(dx
*dx
+dy
*dy
));
224 wxCoord r
= (wxCoord
)radius
;
225 double radius1
, radius2
;
227 if (xx1
== xx2
&& yy1
== yy2
)
235 radius1
= radius2
= 0.0;
239 radius1
= (xx1
- xxc
== 0) ?
240 (yy1
- yyc
< 0) ? 90.0 : -90.0 :
241 -atan2(double(yy1
-yyc
), double(xx1
-xxc
)) * RAD2DEG
;
242 radius2
= (xx2
- xxc
== 0) ?
243 (yy2
- yyc
< 0) ? 90.0 : -90.0 :
244 -atan2(double(yy2
-yyc
), double(xx2
-xxc
)) * RAD2DEG
;
246 wxCoord alpha1
= wxCoord(radius1
* 64.0);
247 wxCoord alpha2
= wxCoord((radius2
- radius1
) * 64.0);
248 while (alpha2
<= 0) alpha2
+= 360*64;
249 while (alpha1
> 360*64) alpha1
-= 360*64;
253 if (m_brush
.GetStyle() != wxTRANSPARENT
)
254 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
256 if (m_pen
.GetStyle() != wxTRANSPARENT
)
257 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
260 CalcBoundingBox (x1
, y1
);
261 CalcBoundingBox (x2
, y2
);
264 void wxWindowDC::DoDrawEllipticArc( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double sa
, double ea
)
266 wxCHECK_RET( Ok(), wxT("invalid window dc") );
268 wxCoord xx
= XLOG2DEV(x
);
269 wxCoord yy
= YLOG2DEV(y
);
270 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
271 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
273 // CMB: handle -ve width and/or height
274 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
275 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
279 wxCoord start
= wxCoord(sa
* 64.0);
280 wxCoord end
= wxCoord(ea
* 64.0);
282 if (m_brush
.GetStyle() != wxTRANSPARENT
)
283 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end
);
285 if (m_pen
.GetStyle() != wxTRANSPARENT
)
286 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
, hh
, start
, end
);
289 CalcBoundingBox (x
, y
);
290 CalcBoundingBox (x
+ width
, y
+ height
);
293 void wxWindowDC::DoDrawPoint( wxCoord x
, wxCoord y
)
295 wxCHECK_RET( Ok(), wxT("invalid window dc") );
297 if ((m_pen
.GetStyle() != wxTRANSPARENT
) && m_window
)
298 gdk_draw_point( m_window
, m_penGC
, XLOG2DEV(x
), YLOG2DEV(y
) );
300 CalcBoundingBox (x
, y
);
303 void wxWindowDC::DoDrawLines( int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
)
305 wxCHECK_RET( Ok(), wxT("invalid window dc") );
307 if (m_pen
.GetStyle() == wxTRANSPARENT
) return;
310 CalcBoundingBox( points
[0].x
+ xoffset
, points
[0].y
+ yoffset
);
312 for (int i
= 0; i
< n
-1; i
++)
314 wxCoord x1
= XLOG2DEV(points
[i
].x
+ xoffset
);
315 wxCoord x2
= XLOG2DEV(points
[i
+1].x
+ xoffset
);
316 wxCoord y1
= YLOG2DEV(points
[i
].y
+ yoffset
); // oh, what a waste
317 wxCoord y2
= YLOG2DEV(points
[i
+1].y
+ yoffset
);
320 gdk_draw_line( m_window
, m_penGC
, x1
, y1
, x2
, y2
);
322 CalcBoundingBox( points
[i
+1].x
+ xoffset
, points
[i
+1].y
+ yoffset
);
326 void wxWindowDC::DoDrawPolygon( int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
, int WXUNUSED(fillStyle
) )
328 wxCHECK_RET( Ok(), wxT("invalid window dc") );
332 GdkPoint
*gdkpoints
= new GdkPoint
[n
+1];
334 for (i
= 0 ; i
< n
; i
++)
336 gdkpoints
[i
].x
= XLOG2DEV(points
[i
].x
+ xoffset
);
337 gdkpoints
[i
].y
= YLOG2DEV(points
[i
].y
+ yoffset
);
339 CalcBoundingBox( points
[i
].x
+ xoffset
, points
[i
].y
+ yoffset
);
342 if ((m_brush
.GetStyle() != wxTRANSPARENT
) && m_window
)
343 gdk_draw_polygon (m_window
, m_brushGC
, TRUE
, gdkpoints
, n
);
347 if ((m_pen
.GetStyle() != wxTRANSPARENT
) && m_window
)
349 for (i
= 0 ; i
< n
; i
++)
351 gdk_draw_line( m_window
, m_penGC
,
354 gdkpoints
[(i
+1)%n
].x
,
355 gdkpoints
[(i
+1)%n
].y
);
362 void wxWindowDC::DoDrawRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
364 wxCHECK_RET( Ok(), wxT("invalid window dc") );
366 wxCoord xx
= XLOG2DEV(x
);
367 wxCoord yy
= YLOG2DEV(y
);
368 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
369 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
371 // CMB: draw nothing if transformed w or h is 0
372 if (ww
== 0 || hh
== 0) return;
374 // CMB: handle -ve width and/or height
375 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
376 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
380 if (m_brush
.GetStyle() != wxTRANSPARENT
)
381 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
);
383 if (m_pen
.GetStyle() != wxTRANSPARENT
)
384 gdk_draw_rectangle( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
-1, hh
-1 );
387 CalcBoundingBox( x
, y
);
388 CalcBoundingBox( x
+ width
, y
+ height
);
391 void wxWindowDC::DoDrawRoundedRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double radius
)
393 wxCHECK_RET( Ok(), wxT("invalid window dc") );
395 if (radius
< 0.0) radius
= - radius
* ((width
< height
) ? width
: height
);
397 wxCoord xx
= XLOG2DEV(x
);
398 wxCoord yy
= YLOG2DEV(y
);
399 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
400 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
401 wxCoord rr
= XLOG2DEVREL((wxCoord
)radius
);
403 // CMB: handle -ve width and/or height
404 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
405 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
407 // CMB: if radius is zero use DrawRectangle() instead to avoid
408 // X drawing errors with small radii
411 DrawRectangle( x
, y
, width
, height
);
415 // CMB: draw nothing if transformed w or h is 0
416 if (ww
== 0 || hh
== 0) return;
418 // CMB: adjust size if outline is drawn otherwise the result is
419 // 1 pixel too wide and high
420 if (m_pen
.GetStyle() != wxTRANSPARENT
)
428 // CMB: ensure dd is not larger than rectangle otherwise we
429 // get an hour glass shape
431 if (dd
> ww
) dd
= ww
;
432 if (dd
> hh
) dd
= hh
;
435 if (m_brush
.GetStyle() != wxTRANSPARENT
)
437 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh
);
438 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 );
439 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
440 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
441 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
442 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
445 if (m_pen
.GetStyle() != wxTRANSPARENT
)
447 gdk_draw_line( m_window
, m_penGC
, xx
+rr
, yy
, xx
+ww
-rr
, yy
);
448 gdk_draw_line( m_window
, m_penGC
, xx
+rr
, yy
+hh
, xx
+ww
-rr
, yy
+hh
);
449 gdk_draw_line( m_window
, m_penGC
, xx
, yy
+rr
, xx
, yy
+hh
-rr
);
450 gdk_draw_line( m_window
, m_penGC
, xx
+ww
, yy
+rr
, xx
+ww
, yy
+hh
-rr
);
451 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
452 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
453 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
454 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
458 // this ignores the radius
459 CalcBoundingBox( x
, y
);
460 CalcBoundingBox( x
+ width
, y
+ height
);
463 void wxWindowDC::DoDrawEllipse( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
465 wxCHECK_RET( Ok(), wxT("invalid window dc") );
467 wxCoord xx
= XLOG2DEV(x
);
468 wxCoord yy
= YLOG2DEV(y
);
469 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
470 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
472 // CMB: handle -ve width and/or height
473 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
474 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
478 if (m_brush
.GetStyle() != wxTRANSPARENT
)
479 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 );
481 if (m_pen
.GetStyle() != wxTRANSPARENT
)
482 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
, hh
, 0, 360*64 );
485 CalcBoundingBox( x
- width
, y
- height
);
486 CalcBoundingBox( x
+ width
, y
+ height
);
489 void wxWindowDC::DoDrawIcon( const wxIcon
&icon
, wxCoord x
, wxCoord y
)
491 // VZ: egcs 1.0.3 refuses to compile this without cast, no idea why
492 DoDrawBitmap( (const wxBitmap
&)icon
, x
, y
, (bool)TRUE
);
495 void wxWindowDC::DoDrawBitmap( const wxBitmap
&bitmap
,
496 wxCoord x
, wxCoord y
,
499 wxCHECK_RET( Ok(), wxT("invalid window dc") );
501 wxCHECK_RET( bitmap
.Ok(), wxT("invalid bitmap") );
503 bool is_mono
= (bitmap
.GetBitmap() != NULL
);
505 /* scale/translate size and position */
507 int xx
= XLOG2DEV(x
);
508 int yy
= YLOG2DEV(y
);
510 int w
= bitmap
.GetWidth();
511 int h
= bitmap
.GetHeight();
513 CalcBoundingBox( x
, y
);
514 CalcBoundingBox( x
+ w
, y
+ h
);
516 if (!m_window
) return;
518 int ww
= XLOG2DEVREL(w
);
519 int hh
= YLOG2DEVREL(h
);
521 /* scale bitmap if required */
525 if ((w
!= ww
) || (h
!= hh
))
527 wxImage
image( bitmap
);
528 image
.Rescale( ww
, hh
);
530 use_bitmap
= image
.ConvertToMonoBitmap(255,255,255);
532 use_bitmap
= image
.ConvertToBitmap();
539 /* apply mask if any */
541 GdkBitmap
*mask
= (GdkBitmap
*) NULL
;
542 if (use_bitmap
.GetMask()) mask
= use_bitmap
.GetMask()->GetBitmap();
548 gdk_gc_set_clip_mask( m_textGC
, mask
);
549 gdk_gc_set_clip_origin( m_textGC
, xx
, yy
);
553 gdk_gc_set_clip_mask( m_penGC
, mask
);
554 gdk_gc_set_clip_origin( m_penGC
, xx
, yy
);
558 /* Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For
559 drawing a mono-bitmap (XBitmap) we use the current text GC */
561 gdk_draw_bitmap( m_window
, m_textGC
, use_bitmap
.GetBitmap(), 0, 0, xx
, yy
, -1, -1 );
563 gdk_draw_pixmap( m_window
, m_penGC
, use_bitmap
.GetPixmap(), 0, 0, xx
, yy
, -1, -1 );
565 /* remove mask again if any */
571 gdk_gc_set_clip_mask( m_textGC
, (GdkBitmap
*) NULL
);
572 gdk_gc_set_clip_origin( m_textGC
, 0, 0 );
576 gdk_gc_set_clip_mask( m_penGC
, (GdkBitmap
*) NULL
);
577 gdk_gc_set_clip_origin( m_penGC
, 0, 0 );
582 bool wxWindowDC::DoBlit( wxCoord xdest
, wxCoord ydest
, wxCoord width
, wxCoord height
,
583 wxDC
*source
, wxCoord xsrc
, wxCoord ysrc
,
584 int logical_func
, bool useMask
)
586 /* this is the nth try to get this utterly useless function to
587 work. it now completely ignores the scaling or translation
588 of the source dc, but scales correctly on the target dc and
589 knows about possible mask information in a memory dc. */
591 wxCHECK_MSG( Ok(), FALSE
, wxT("invalid window dc") );
593 wxCHECK_MSG( source
, FALSE
, wxT("invalid source dc") );
595 if (!m_window
) return FALSE
;
597 wxClientDC
*srcDC
= (wxClientDC
*)source
;
598 wxMemoryDC
*memDC
= (wxMemoryDC
*)source
;
600 bool use_bitmap_method
= FALSE
;
601 bool is_mono
= FALSE
;
603 if (srcDC
->m_isMemDC
)
605 if (!memDC
->m_selected
.Ok()) return FALSE
;
607 /* we use the "XCopyArea" way to copy a memory dc into
608 y different window if the memory dc BOTH
609 a) doesn't have any mask or its mask isn't used
613 if (useMask
&& (memDC
->m_selected
.GetMask()))
615 /* we HAVE TO use the direct way for memory dcs
616 that have mask since the XCopyArea doesn't know
618 use_bitmap_method
= TRUE
;
620 else if (memDC
->m_selected
.GetDepth() == 1)
622 /* we HAVE TO use the direct way for memory dcs
623 that are bitmaps because XCopyArea doesn't cope
624 with different bit depths */
626 use_bitmap_method
= TRUE
;
628 else if ((xsrc
== 0) && (ysrc
== 0) &&
629 (width
== memDC
->m_selected
.GetWidth()) &&
630 (height
== memDC
->m_selected
.GetHeight()))
632 /* we SHOULD use the direct way if all of the bitmap
633 in the memory dc is copied in which case XCopyArea
634 wouldn't be able able to boost performace by reducing
635 the area to be scaled */
636 use_bitmap_method
= TRUE
;
640 use_bitmap_method
= FALSE
;
644 CalcBoundingBox( xdest
, ydest
);
645 CalcBoundingBox( xdest
+ width
, ydest
+ height
);
647 int old_logical_func
= m_logicalFunction
;
648 SetLogicalFunction( logical_func
);
650 if (use_bitmap_method
)
652 /* scale/translate bitmap size */
654 wxCoord bm_width
= memDC
->m_selected
.GetWidth();
655 wxCoord bm_height
= memDC
->m_selected
.GetHeight();
657 wxCoord bm_ww
= XLOG2DEVREL( bm_width
);
658 wxCoord bm_hh
= YLOG2DEVREL( bm_height
);
660 /* scale bitmap if required */
664 if ((bm_width
!= bm_ww
) || (bm_height
!= bm_hh
))
666 wxImage
image( memDC
->m_selected
);
667 image
= image
.Scale( bm_ww
, bm_hh
);
670 use_bitmap
= image
.ConvertToMonoBitmap(255,255,255);
672 use_bitmap
= image
.ConvertToBitmap();
676 use_bitmap
= memDC
->m_selected
;
679 /* scale/translate size and position */
681 wxCoord xx
= XLOG2DEV(xdest
);
682 wxCoord yy
= YLOG2DEV(ydest
);
684 wxCoord ww
= XLOG2DEVREL(width
);
685 wxCoord hh
= YLOG2DEVREL(height
);
687 /* apply mask if any */
689 GdkBitmap
*mask
= (GdkBitmap
*) NULL
;
690 if (use_bitmap
.GetMask()) mask
= use_bitmap
.GetMask()->GetBitmap();
696 gdk_gc_set_clip_mask( m_textGC
, mask
);
697 gdk_gc_set_clip_origin( m_textGC
, xx
, yy
);
701 gdk_gc_set_clip_mask( m_penGC
, mask
);
702 gdk_gc_set_clip_origin( m_penGC
, xx
, yy
);
706 /* Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For
707 drawing a mono-bitmap (XBitmap) we use the current text GC */
709 gdk_draw_bitmap( m_window
, m_textGC
, use_bitmap
.GetBitmap(), xsrc
, ysrc
, xx
, yy
, ww
, hh
);
711 gdk_draw_pixmap( m_window
, m_penGC
, use_bitmap
.GetPixmap(), xsrc
, ysrc
, xx
, yy
, ww
, hh
);
713 /* remove mask again if any */
719 gdk_gc_set_clip_mask( m_textGC
, (GdkBitmap
*) NULL
);
720 gdk_gc_set_clip_origin( m_textGC
, 0, 0 );
724 gdk_gc_set_clip_mask( m_penGC
, (GdkBitmap
*) NULL
);
725 gdk_gc_set_clip_origin( m_penGC
, 0, 0 );
729 else /* use_bitmap_method */
731 /* scale/translate size and position */
733 wxCoord xx
= XLOG2DEV(xdest
);
734 wxCoord yy
= YLOG2DEV(ydest
);
736 wxCoord ww
= XLOG2DEVREL(width
);
737 wxCoord hh
= YLOG2DEVREL(height
);
739 if ((width
!= ww
) || (height
!= hh
))
741 /* draw source window into a bitmap as we cannot scale
742 a window in contrast to a bitmap. this would actually
743 work with memory dcs as well, but we'd lose the mask
744 information and waste one step in this process since
745 a memory already has a bitmap. all this is slightly
746 inefficient as we could take an XImage directly from
747 an X window, but we'd then also have to care that
748 the window is not outside the screen (in which case
749 we'd get a BadMatch or what not).
750 Is a double XGetImage and combined XGetPixel and
751 XPutPixel really faster? I'm not sure. look at wxXt
752 for a different implementation of the same problem. */
754 wxBitmap
bitmap( width
, height
);
755 gdk_window_copy_area( bitmap
.GetPixmap(), m_penGC
, 0, 0,
757 xsrc
, ysrc
, width
, height
);
761 wxImage
image( bitmap
);
762 image
= image
.Scale( ww
, hh
);
764 /* convert to bitmap */
766 bitmap
= image
.ConvertToBitmap();
768 /* draw scaled bitmap */
770 gdk_draw_pixmap( m_window
, m_penGC
, bitmap
.GetPixmap(), 0, 0, xx
, yy
, -1, -1 );
775 /* no scaling and not a memory dc with a mask either */
777 gdk_window_copy_area( m_window
, m_penGC
, xx
, yy
,
779 xsrc
, ysrc
, width
, height
);
783 SetLogicalFunction( old_logical_func
);
787 void wxWindowDC::DoDrawText( const wxString
&text
, wxCoord x
, wxCoord y
)
789 wxCHECK_RET( Ok(), wxT("invalid window dc") );
791 if (!m_window
) return;
793 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
795 wxCHECK_RET( font
, wxT("invalid font") );
800 /* CMB 21/5/98: draw text background if mode is wxSOLID */
801 if (m_backgroundMode
== wxSOLID
)
803 wxCoord width
= gdk_string_width( font
, text
.mbc_str() );
804 wxCoord height
= font
->ascent
+ font
->descent
;
805 gdk_gc_set_foreground( m_textGC
, m_textBackgroundColour
.GetColor() );
806 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, x
, y
, width
, height
);
807 gdk_gc_set_foreground( m_textGC
, m_textForegroundColour
.GetColor() );
809 gdk_draw_string( m_window
, font
, m_textGC
, x
, y
+ font
->ascent
, text
.mbc_str() );
811 /* CMB 17/7/98: simple underline: ignores scaling and underlying
812 X font's XA_UNDERLINE_POSITION and XA_UNDERLINE_THICKNESS
813 properties (see wxXt implementation) */
814 if (m_font
.GetUnderlined())
816 wxCoord width
= gdk_string_width( font
, text
.mbc_str() );
817 wxCoord ul_y
= y
+ font
->ascent
;
818 if (font
->descent
> 0) ul_y
++;
819 gdk_draw_line( m_window
, m_textGC
, x
, ul_y
, x
+ width
, ul_y
);
823 GetTextExtent (text
, &w
, &h
);
824 CalcBoundingBox (x
+ w
, y
+ h
);
825 CalcBoundingBox (x
, y
);
828 void wxWindowDC::DoDrawRotatedText( const wxString
&text
, wxCoord x
, wxCoord y
, double angle
)
832 DrawText(text
, x
, y
);
836 wxCHECK_RET( Ok(), wxT("invalid window dc") );
838 if (!m_window
) return;
840 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
842 wxCHECK_RET( font
, wxT("invalid font") );
844 // the size of the text
845 wxCoord w
= gdk_string_width( font
, text
.mbc_str() );
846 wxCoord h
= font
->ascent
+ font
->descent
;
848 // draw the string normally
851 dc
.SelectObject(src
);
852 dc
.SetFont(GetFont());
853 dc
.SetBackground(*wxWHITE_BRUSH
);
854 dc
.SetBrush(*wxBLACK_BRUSH
);
856 dc
.DrawText(text
, 0, 0);
857 dc
.SetFont(wxNullFont
);
858 dc
.SelectObject(wxNullBitmap
);
860 // Calculate the size of the rotated bounding box.
861 double rad
= DegToRad(angle
);
862 double dx
= cos(rad
),
865 // the rectngle vertices are counted clockwise with the first one being at
866 // (0, 0) (or, rather, at (x, y))
868 y2
= -w
*dy
; // y axis points to the bottom, hence minus
875 wxCoord maxX
= (wxCoord
)(dmax(x2
, dmax(x3
, x4
)) + 0.5),
876 maxY
= (wxCoord
)(dmax(y2
, dmax(y3
, y4
)) + 0.5),
877 minX
= (wxCoord
)(dmin(x2
, dmin(x3
, x4
)) - 0.5),
878 minY
= (wxCoord
)(dmin(y2
, dmin(y3
, y4
)) - 0.5);
880 // prepare to blit-with-rotate the bitmap to the DC
883 GdkColor
*colText
= m_textForegroundColour
.GetColor(),
884 *colBack
= m_textBackgroundColour
.GetColor();
886 bool textColSet
= TRUE
;
888 unsigned char *data
= image
.GetData();
890 // paint pixel by pixel
891 for ( wxCoord srcX
= 0; srcX
< w
; srcX
++ )
893 for ( wxCoord srcY
= 0; srcY
< h
; srcY
++ )
895 // transform source coords to dest coords
896 double r
= sqrt(srcX
*srcX
+ srcY
*srcY
);
897 double angleOrig
= atan2(srcY
, srcX
) - rad
;
898 wxCoord dstX
= (wxCoord
)(r
*cos(angleOrig
) + 0.5),
899 dstY
= (wxCoord
)(r
*sin(angleOrig
) + 0.5);
902 bool textPixel
= data
[(srcY
*w
+ srcX
)*3] == 0;
903 if ( textPixel
|| (m_backgroundMode
== wxSOLID
) )
905 // change colour if needed
906 if ( textPixel
!= textColSet
)
908 gdk_gc_set_foreground( m_textGC
, textPixel
? colText
911 textColSet
= textPixel
;
914 // don't use DrawPoint() because it uses the current pen
915 // colour, and we don't need it here
916 gdk_draw_point( m_window
, m_textGC
,
917 XLOG2DEV(x
+ dstX
), YLOG2DEV(y
+ dstY
) );
922 // it would be better to draw with non underlined font and draw the line
923 // manually here (it would be more straight...)
925 if ( m_font
.GetUnderlined() )
927 gdk_draw_line( m_window
, m_textGC
,
928 XLOG2DEV(x
+ x4
), YLOG2DEV(y
+ y4
+ font
->descent
),
929 XLOG2DEV(x
+ x3
), YLOG2DEV(y
+ y3
+ font
->descent
));
933 // restore the font colour
934 gdk_gc_set_foreground( m_textGC
, colText
);
936 // update the bounding box
937 CalcBoundingBox(x
+ minX
, y
+ minY
);
938 CalcBoundingBox(x
+ maxX
, y
+ maxY
);
941 void wxWindowDC::DoGetTextExtent(const wxString
&string
,
942 wxCoord
*width
, wxCoord
*height
,
943 wxCoord
*descent
, wxCoord
*externalLeading
,
944 wxFont
*theFont
) const
946 wxFont fontToUse
= m_font
;
947 if (theFont
) fontToUse
= *theFont
;
949 GdkFont
*font
= fontToUse
.GetInternalFont( m_scaleY
);
950 if (width
) (*width
) = wxCoord(gdk_string_width( font
, string
.mbc_str() ) / m_scaleX
);
951 if (height
) (*height
) = wxCoord((font
->ascent
+ font
->descent
) / m_scaleY
);
952 if (descent
) (*descent
) = wxCoord(font
->descent
/ m_scaleY
);
953 if (externalLeading
) (*externalLeading
) = 0; // ??
956 wxCoord
wxWindowDC::GetCharWidth() const
958 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
959 wxCHECK_MSG( font
, -1, wxT("invalid font") );
961 return wxCoord(gdk_string_width( font
, "H" ) / m_scaleX
);
964 wxCoord
wxWindowDC::GetCharHeight() const
966 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
967 wxCHECK_MSG( font
, -1, wxT("invalid font") );
969 return wxCoord((font
->ascent
+ font
->descent
) / m_scaleY
);
972 void wxWindowDC::Clear()
974 wxCHECK_RET( Ok(), wxT("invalid window dc") );
976 if (!m_window
) return;
978 /* - we either are a memory dc or have a window as the
979 owner. anything else shouldn't happen.
980 - we don't use gdk_window_clear() as we don't set
981 the window's background colour anymore. it is too
982 much pain to keep the DC's and the window's back-
983 ground colour in synch. */
988 m_owner
->GetSize( &width
, &height
);
989 gdk_draw_rectangle( m_window
, m_bgGC
, TRUE
, 0, 0, width
, height
);
996 GetSize( &width
, &height
);
997 gdk_draw_rectangle( m_window
, m_bgGC
, TRUE
, 0, 0, width
, height
);
1002 void wxWindowDC::SetFont( const wxFont
&font
)
1007 void wxWindowDC::SetPen( const wxPen
&pen
)
1009 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1011 if (m_pen
== pen
) return;
1015 if (!m_pen
.Ok()) return;
1017 if (!m_window
) return;
1019 gint width
= m_pen
.GetWidth();
1022 // CMB: if width is non-zero scale it with the dc
1027 // X doesn't allow different width in x and y and so we take
1030 ( fabs((double) XLOG2DEVREL(width
)) +
1031 fabs((double) YLOG2DEVREL(width
)) ) / 2.0;
1035 static const char dotted
[] = {1, 1};
1036 static const char short_dashed
[] = {2, 2};
1037 static const char wxCoord_dashed
[] = {2, 4};
1038 static const char dotted_dashed
[] = {3, 3, 1, 3};
1040 // We express dash pattern in pen width unit, so we are
1041 // independent of zoom factor and so on...
1043 const char *req_dash
;
1045 GdkLineStyle lineStyle
= GDK_LINE_SOLID
;
1046 switch (m_pen
.GetStyle())
1050 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1051 req_nb_dash
= m_pen
.GetDashCount();
1052 req_dash
= m_pen
.GetDash();
1057 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1064 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1066 req_dash
= wxCoord_dashed
;
1071 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1073 req_dash
= short_dashed
;
1078 // lineStyle = GDK_LINE_DOUBLE_DASH;
1079 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1081 req_dash
= dotted_dashed
;
1090 lineStyle
= GDK_LINE_SOLID
;
1091 req_dash
= (wxDash
*)NULL
;
1097 #if (GTK_MINOR_VERSION > 0)
1098 if (req_dash
&& req_nb_dash
)
1100 char *real_req_dash
= new char[req_nb_dash
];
1103 for (int i
= 0; i
< req_nb_dash
; i
++)
1104 real_req_dash
[i
] = req_dash
[i
] * width
;
1105 gdk_gc_set_dashes( m_penGC
, 0, real_req_dash
, req_nb_dash
);
1106 delete[] real_req_dash
;
1110 // No Memory. We use non-scaled dash pattern...
1111 gdk_gc_set_dashes( m_penGC
, 0, (char*)req_dash
, req_nb_dash
);
1116 GdkCapStyle capStyle
= GDK_CAP_ROUND
;
1117 switch (m_pen
.GetCap())
1119 case wxCAP_ROUND
: { capStyle
= (width
<= 1) ? GDK_CAP_NOT_LAST
: GDK_CAP_ROUND
; break; }
1120 case wxCAP_PROJECTING
: { capStyle
= GDK_CAP_PROJECTING
; break; }
1121 case wxCAP_BUTT
: { capStyle
= GDK_CAP_BUTT
; break; }
1124 GdkJoinStyle joinStyle
= GDK_JOIN_ROUND
;
1125 switch (m_pen
.GetJoin())
1127 case wxJOIN_BEVEL
: { joinStyle
= GDK_JOIN_BEVEL
; break; }
1128 case wxJOIN_ROUND
: { joinStyle
= GDK_JOIN_ROUND
; break; }
1129 case wxJOIN_MITER
: { joinStyle
= GDK_JOIN_MITER
; break; }
1132 gdk_gc_set_line_attributes( m_penGC
, width
, lineStyle
, capStyle
, joinStyle
);
1134 m_pen
.GetColour().CalcPixel( m_cmap
);
1135 gdk_gc_set_foreground( m_penGC
, m_pen
.GetColour().GetColor() );
1138 void wxWindowDC::SetBrush( const wxBrush
&brush
)
1140 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1142 if (m_brush
== brush
) return;
1146 if (!m_brush
.Ok()) return;
1148 if (!m_window
) return;
1150 m_brush
.GetColour().CalcPixel( m_cmap
);
1151 gdk_gc_set_foreground( m_brushGC
, m_brush
.GetColour().GetColor() );
1153 gdk_gc_set_fill( m_brushGC
, GDK_SOLID
);
1155 if ((m_brush
.GetStyle() == wxSTIPPLE
) && (m_brush
.GetStipple()->Ok()))
1157 if (m_brush
.GetStipple()->GetPixmap())
1159 gdk_gc_set_fill( m_brushGC
, GDK_TILED
);
1160 gdk_gc_set_tile( m_brushGC
, m_brush
.GetStipple()->GetPixmap() );
1164 gdk_gc_set_fill( m_brushGC
, GDK_STIPPLED
);
1165 gdk_gc_set_stipple( m_brushGC
, m_brush
.GetStipple()->GetBitmap() );
1169 if (IS_HATCH(m_brush
.GetStyle()))
1171 gdk_gc_set_fill( m_brushGC
, GDK_STIPPLED
);
1172 int num
= m_brush
.GetStyle() - wxBDIAGONAL_HATCH
;
1173 gdk_gc_set_stipple( m_brushGC
, hatches
[num
] );
1177 void wxWindowDC::SetBackground( const wxBrush
&brush
)
1179 /* CMB 21/7/98: Added SetBackground. Sets background brush
1180 * for Clear() and bg colour for shapes filled with cross-hatch brush */
1182 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1184 if (m_backgroundBrush
== brush
) return;
1186 m_backgroundBrush
= brush
;
1188 if (!m_backgroundBrush
.Ok()) return;
1190 if (!m_window
) return;
1192 m_backgroundBrush
.GetColour().CalcPixel( m_cmap
);
1193 gdk_gc_set_background( m_brushGC
, m_backgroundBrush
.GetColour().GetColor() );
1194 gdk_gc_set_background( m_penGC
, m_backgroundBrush
.GetColour().GetColor() );
1195 gdk_gc_set_background( m_bgGC
, m_backgroundBrush
.GetColour().GetColor() );
1196 gdk_gc_set_foreground( m_bgGC
, m_backgroundBrush
.GetColour().GetColor() );
1198 gdk_gc_set_fill( m_bgGC
, GDK_SOLID
);
1200 if ((m_backgroundBrush
.GetStyle() == wxSTIPPLE
) && (m_backgroundBrush
.GetStipple()->Ok()))
1202 if (m_backgroundBrush
.GetStipple()->GetPixmap())
1204 gdk_gc_set_fill( m_bgGC
, GDK_TILED
);
1205 gdk_gc_set_tile( m_bgGC
, m_backgroundBrush
.GetStipple()->GetPixmap() );
1209 gdk_gc_set_fill( m_bgGC
, GDK_STIPPLED
);
1210 gdk_gc_set_stipple( m_bgGC
, m_backgroundBrush
.GetStipple()->GetBitmap() );
1214 if (IS_HATCH(m_backgroundBrush
.GetStyle()))
1216 gdk_gc_set_fill( m_bgGC
, GDK_STIPPLED
);
1217 int num
= m_backgroundBrush
.GetStyle() - wxBDIAGONAL_HATCH
;
1218 gdk_gc_set_stipple( m_bgGC
, hatches
[num
] );
1222 void wxWindowDC::SetLogicalFunction( int function
)
1224 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1226 if (m_logicalFunction
== function
) return;
1228 GdkFunction mode
= GDK_COPY
;
1231 case wxXOR
: mode
= GDK_XOR
; break;
1232 case wxINVERT
: mode
= GDK_INVERT
; break;
1233 #if (GTK_MINOR_VERSION > 0)
1234 case wxOR_REVERSE
: mode
= GDK_OR_REVERSE
; break;
1235 case wxAND_REVERSE
: mode
= GDK_AND_REVERSE
; break;
1236 case wxCLEAR
: mode
= GDK_CLEAR
; break;
1237 case wxSET
: mode
= GDK_SET
; break;
1238 case wxOR_INVERT
: mode
= GDK_OR_INVERT
; break;
1240 case wxAND
: mode
= GDK_AND
; break;
1242 case wxOR
: mode
= GDK_OR
; break;
1243 case wxEQUIV
: mode
= GDK_EQUIV
; break;
1244 case wxNAND
: mode
= GDK_NAND
; break;
1245 case wxAND_INVERT
: mode
= GDK_AND_INVERT
; break;
1246 case wxCOPY
: mode
= GDK_COPY
; break;
1247 case wxNO_OP
: mode
= GDK_NOOP
; break;
1248 case wxSRC_INVERT
: mode
= GDK_COPY_INVERT
; break;
1252 wxFAIL_MSG( wxT("unsupported logical function") );
1257 m_logicalFunction
= function
;
1259 if (!m_window
) return;
1261 gdk_gc_set_function( m_penGC
, mode
);
1262 gdk_gc_set_function( m_brushGC
, mode
);
1263 gdk_gc_set_function( m_textGC
, mode
);
1266 void wxWindowDC::SetTextForeground( const wxColour
&col
)
1268 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1270 if (m_textForegroundColour
== col
) return;
1272 m_textForegroundColour
= col
;
1273 if (!m_textForegroundColour
.Ok()) return;
1275 if (!m_window
) return;
1277 m_textForegroundColour
.CalcPixel( m_cmap
);
1278 gdk_gc_set_foreground( m_textGC
, m_textForegroundColour
.GetColor() );
1281 void wxWindowDC::SetTextBackground( const wxColour
&col
)
1283 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1285 if (m_textBackgroundColour
== col
) return;
1287 m_textBackgroundColour
= col
;
1288 if (!m_textBackgroundColour
.Ok()) return;
1290 if (!m_window
) return;
1292 m_textBackgroundColour
.CalcPixel( m_cmap
);
1293 gdk_gc_set_background( m_textGC
, m_textBackgroundColour
.GetColor() );
1296 void wxWindowDC::SetBackgroundMode( int mode
)
1298 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1300 m_backgroundMode
= mode
;
1302 if (!m_window
) return;
1304 // CMB 21/7/98: fill style of cross-hatch brushes is affected by
1305 // transparent/solid background mode
1307 if (m_brush
.GetStyle() != wxSOLID
&& m_brush
.GetStyle() != wxTRANSPARENT
)
1309 gdk_gc_set_fill( m_brushGC
,
1310 (m_backgroundMode
== wxTRANSPARENT
) ? GDK_STIPPLED
: GDK_OPAQUE_STIPPLED
);
1314 void wxWindowDC::SetPalette( const wxPalette
& WXUNUSED(palette
) )
1316 wxFAIL_MSG( wxT("wxWindowDC::SetPalette not implemented") );
1319 void wxWindowDC::DoSetClippingRegion( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
1321 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1323 wxDC::DoSetClippingRegion( x
, y
, width
, height
);
1325 if (!m_window
) return;
1328 rect
.x
= XLOG2DEV(x
);
1329 rect
.y
= YLOG2DEV(y
);
1330 rect
.width
= XLOG2DEVREL(width
);
1331 rect
.height
= YLOG2DEVREL(height
);
1332 gdk_gc_set_clip_rectangle( m_penGC
, &rect
);
1333 gdk_gc_set_clip_rectangle( m_brushGC
, &rect
);
1334 gdk_gc_set_clip_rectangle( m_textGC
, &rect
);
1335 gdk_gc_set_clip_rectangle( m_bgGC
, &rect
);
1338 void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion
®ion
)
1340 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1344 DestroyClippingRegion();
1348 if (!m_window
) return;
1350 gdk_gc_set_clip_region( m_penGC
, region
.GetRegion() );
1351 gdk_gc_set_clip_region( m_brushGC
, region
.GetRegion() );
1352 gdk_gc_set_clip_region( m_textGC
, region
.GetRegion() );
1353 gdk_gc_set_clip_region( m_bgGC
, region
.GetRegion() );
1356 void wxWindowDC::DestroyClippingRegion()
1358 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1360 wxDC::DestroyClippingRegion();
1362 if (!m_window
) return;
1364 gdk_gc_set_clip_rectangle( m_penGC
, (GdkRectangle
*) NULL
);
1365 gdk_gc_set_clip_rectangle( m_brushGC
, (GdkRectangle
*) NULL
);
1366 gdk_gc_set_clip_rectangle( m_textGC
, (GdkRectangle
*) NULL
);
1367 gdk_gc_set_clip_rectangle( m_bgGC
, (GdkRectangle
*) NULL
);
1370 void wxWindowDC::SetUpDC()
1374 m_logicalFunction
= wxCOPY
;
1375 m_penGC
= gdk_gc_new( m_window
);
1376 m_brushGC
= gdk_gc_new( m_window
);
1377 m_textGC
= gdk_gc_new( m_window
);
1378 m_bgGC
= gdk_gc_new( m_window
);
1380 wxColour
tmp_col( m_textForegroundColour
);
1381 m_textForegroundColour
= wxNullColour
;
1382 SetTextForeground( tmp_col
);
1383 tmp_col
= m_textBackgroundColour
;
1384 m_textBackgroundColour
= wxNullColour
;
1385 SetTextBackground( tmp_col
);
1387 wxPen
tmp_pen( m_pen
);
1391 wxFont
tmp_font( m_font
);
1392 m_font
= wxNullFont
;
1393 SetFont( tmp_font
);
1395 wxBrush
tmp_brush( m_brush
);
1396 m_brush
= wxNullBrush
;
1397 SetBrush( tmp_brush
);
1400 tmp_brush = m_backgroundBrush;
1401 m_backgroundBrush = wxNullBrush;
1402 SetBackground( tmp_brush );
1404 tmp_brush
= m_backgroundBrush
;
1405 m_backgroundBrush
= wxNullBrush
;
1406 SetBackground( *wxWHITE_BRUSH
);
1407 m_backgroundBrush
= tmp_brush
;
1411 hatch_bitmap
= hatches
;
1412 hatch_bitmap
[0] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, bdiag_bits
, bdiag_width
, bdiag_height
);
1413 hatch_bitmap
[1] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, cdiag_bits
, cdiag_width
, cdiag_height
);
1414 hatch_bitmap
[2] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, fdiag_bits
, fdiag_width
, fdiag_height
);
1415 hatch_bitmap
[3] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, cross_bits
, cross_width
, cross_height
);
1416 hatch_bitmap
[4] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, horiz_bits
, horiz_width
, horiz_height
);
1417 hatch_bitmap
[5] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, verti_bits
, verti_width
, verti_height
);
1421 void wxWindowDC::Destroy()
1423 if (m_penGC
) gdk_gc_unref( m_penGC
);
1424 m_penGC
= (GdkGC
*) NULL
;
1425 if (m_brushGC
) gdk_gc_unref( m_brushGC
);
1426 m_brushGC
= (GdkGC
*) NULL
;
1427 if (m_textGC
) gdk_gc_unref( m_textGC
);
1428 m_textGC
= (GdkGC
*) NULL
;
1429 if (m_bgGC
) gdk_gc_unref( m_bgGC
);
1430 m_bgGC
= (GdkGC
*) NULL
;
1433 void wxWindowDC::ComputeScaleAndOrigin()
1435 /* CMB: copy scale to see if it changes */
1436 double origScaleX
= m_scaleX
;
1437 double origScaleY
= m_scaleY
;
1439 wxDC::ComputeScaleAndOrigin();
1441 /* CMB: if scale has changed call SetPen to recalulate the line width */
1442 if ((m_scaleX
!= origScaleX
|| m_scaleY
!= origScaleY
) &&
1445 /* this is a bit artificial, but we need to force wxDC to think
1446 the pen has changed */
1453 // Resolution in pixels per logical inch
1454 wxSize
wxWindowDC::GetPPI() const
1456 return wxSize(100, 100);
1459 int wxWindowDC::GetDepth() const
1461 wxFAIL_MSG(wxT("not implemented"));
1467 // ----------------------------------- spline code ----------------------------------------
1469 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
,
1470 double a3
, double b3
, double a4
, double b4
);
1471 void wx_clear_stack();
1472 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
, double *x3
,
1473 double *y3
, double *x4
, double *y4
);
1474 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
,
1475 double x4
, double y4
);
1476 static bool wx_spline_add_point(double x
, double y
);
1477 static void wx_spline_draw_point_array(wxDC
*dc
);
1479 wxList wx_spline_point_list
;
1481 #define half(z1, z2) ((z1+z2)/2.0)
1484 /* iterative version */
1486 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
, double a3
, double b3
, double a4
,
1489 register double xmid
, ymid
;
1490 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
1493 wx_spline_push(a1
, b1
, a2
, b2
, a3
, b3
, a4
, b4
);
1495 while (wx_spline_pop(&x1
, &y1
, &x2
, &y2
, &x3
, &y3
, &x4
, &y4
)) {
1496 xmid
= (double)half(x2
, x3
);
1497 ymid
= (double)half(y2
, y3
);
1498 if (fabs(x1
- xmid
) < THRESHOLD
&& fabs(y1
- ymid
) < THRESHOLD
&&
1499 fabs(xmid
- x4
) < THRESHOLD
&& fabs(ymid
- y4
) < THRESHOLD
) {
1500 wx_spline_add_point( x1
, y1
);
1501 wx_spline_add_point( xmid
, ymid
);
1503 wx_spline_push(xmid
, ymid
, (double)half(xmid
, x3
), (double)half(ymid
, y3
),
1504 (double)half(x3
, x4
), (double)half(y3
, y4
), x4
, y4
);
1505 wx_spline_push(x1
, y1
, (double)half(x1
, x2
), (double)half(y1
, y2
),
1506 (double)half(x2
, xmid
), (double)half(y2
, ymid
), xmid
, ymid
);
1511 /* utilities used by spline drawing routines */
1513 typedef struct wx_spline_stack_struct
{
1514 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
1517 #define SPLINE_STACK_DEPTH 20
1518 static Stack wx_spline_stack
[SPLINE_STACK_DEPTH
];
1519 static Stack
*wx_stack_top
;
1520 static int wx_stack_count
;
1522 void wx_clear_stack()
1524 wx_stack_top
= wx_spline_stack
;
1528 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
, double x4
, double y4
)
1530 wx_stack_top
->x1
= x1
;
1531 wx_stack_top
->y1
= y1
;
1532 wx_stack_top
->x2
= x2
;
1533 wx_stack_top
->y2
= y2
;
1534 wx_stack_top
->x3
= x3
;
1535 wx_stack_top
->y3
= y3
;
1536 wx_stack_top
->x4
= x4
;
1537 wx_stack_top
->y4
= y4
;
1542 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
,
1543 double *x3
, double *y3
, double *x4
, double *y4
)
1545 if (wx_stack_count
== 0)
1549 *x1
= wx_stack_top
->x1
;
1550 *y1
= wx_stack_top
->y1
;
1551 *x2
= wx_stack_top
->x2
;
1552 *y2
= wx_stack_top
->y2
;
1553 *x3
= wx_stack_top
->x3
;
1554 *y3
= wx_stack_top
->y3
;
1555 *x4
= wx_stack_top
->x4
;
1556 *y4
= wx_stack_top
->y4
;
1560 static bool wx_spline_add_point(double x
, double y
)
1562 wxPoint
*point
= new wxPoint
;
1565 wx_spline_point_list
.Append((wxObject
*)point
);
1569 static void wx_spline_draw_point_array(wxDC
*dc
)
1571 dc
->DrawLines(&wx_spline_point_list
, 0, 0 );
1572 wxNode
*node
= wx_spline_point_list
.First();
1575 wxPoint
*point
= (wxPoint
*)node
->Data();
1578 node
= wx_spline_point_list
.First();
1582 void wxWindowDC::DoDrawSpline( wxList
*points
)
1584 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1587 double cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
;
1588 double x1
, y1
, x2
, y2
;
1590 wxNode
*node
= points
->First();
1591 p
= (wxPoint
*)node
->Data();
1596 node
= node
->Next();
1597 p
= (wxPoint
*)node
->Data();
1601 cx1
= (double)((x1
+ x2
) / 2);
1602 cy1
= (double)((y1
+ y2
) / 2);
1603 cx2
= (double)((cx1
+ x2
) / 2);
1604 cy2
= (double)((cy1
+ y2
) / 2);
1606 wx_spline_add_point(x1
, y1
);
1608 while ((node
= node
->Next()) != NULL
)
1610 p
= (wxPoint
*)node
->Data();
1615 cx4
= (double)(x1
+ x2
) / 2;
1616 cy4
= (double)(y1
+ y2
) / 2;
1617 cx3
= (double)(x1
+ cx4
) / 2;
1618 cy3
= (double)(y1
+ cy4
) / 2;
1620 wx_quadratic_spline(cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
);
1624 cx2
= (double)(cx1
+ x2
) / 2;
1625 cy2
= (double)(cy1
+ y2
) / 2;
1628 wx_spline_add_point( cx1
, cy1
);
1629 wx_spline_add_point( x2
, y2
);
1631 wx_spline_draw_point_array( this );
1634 #endif // wxUSE_SPLINE
1636 //-----------------------------------------------------------------------------
1638 //-----------------------------------------------------------------------------
1640 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC
,wxWindowDC
)
1642 wxPaintDC::wxPaintDC()
1647 wxPaintDC::wxPaintDC( wxWindow
*win
)
1652 //-----------------------------------------------------------------------------
1654 //-----------------------------------------------------------------------------
1656 IMPLEMENT_DYNAMIC_CLASS(wxClientDC
,wxWindowDC
)
1658 wxClientDC::wxClientDC()
1663 wxClientDC::wxClientDC( wxWindow
*win
)