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 //-----------------------------------------------------------------------------
45 // temporary implementation of the missing GDK function
46 //-----------------------------------------------------------------------------
48 #include "gdk/gdkprivate.h"
50 void gdk_draw_bitmap (GdkDrawable
*drawable
,
60 GdkWindowPrivate
*drawable_private
;
61 GdkWindowPrivate
*src_private
;
62 GdkGCPrivate
*gc_private
;
64 g_return_if_fail (drawable
!= NULL
);
65 g_return_if_fail (src
!= NULL
);
66 g_return_if_fail (gc
!= NULL
);
68 drawable_private
= (GdkWindowPrivate
*) drawable
;
69 src_private
= (GdkWindowPrivate
*) src
;
70 if (drawable_private
->destroyed
|| src_private
->destroyed
)
73 gc_private
= (GdkGCPrivate
*) gc
;
75 if (width
== -1) width
= src_private
->width
;
76 if (height
== -1) height
= src_private
->height
;
78 XCopyPlane( drawable_private
->xdisplay
,
80 drawable_private
->xwindow
,
89 * compare two doubles and return the larger rounded
92 static int roundmax(double a
, double b
)
94 return (int)((a
> b
? a
: b
) + 0.5);
98 * compare two doubles and return the smaller rounded
101 static int roundmin(double a
, double b
)
103 return (int)((a
< b
? a
: b
) - 0.5);
107 //-----------------------------------------------------------------------------
109 //-----------------------------------------------------------------------------
111 IMPLEMENT_DYNAMIC_CLASS(wxWindowDC
, wxDC
)
113 wxWindowDC::wxWindowDC()
115 m_penGC
= (GdkGC
*) NULL
;
116 m_brushGC
= (GdkGC
*) NULL
;
117 m_textGC
= (GdkGC
*) NULL
;
118 m_bgGC
= (GdkGC
*) NULL
;
119 m_cmap
= (GdkColormap
*) NULL
;
121 m_owner
= (wxWindow
*)NULL
;
124 wxWindowDC::wxWindowDC( wxWindow
*window
)
126 m_penGC
= (GdkGC
*) NULL
;
127 m_brushGC
= (GdkGC
*) NULL
;
128 m_textGC
= (GdkGC
*) NULL
;
129 m_bgGC
= (GdkGC
*) NULL
;
130 m_cmap
= (GdkColormap
*) NULL
;
131 m_owner
= (wxWindow
*)NULL
;
133 m_font
= window
->GetFont();
135 wxASSERT_MSG( window
, wxT("DC needs a window") );
137 GtkWidget
*widget
= window
->m_wxwindow
;
139 wxASSERT_MSG( widget
, wxT("DC needs a widget") );
141 GtkPizza
*pizza
= GTK_PIZZA( widget
);
142 m_window
= pizza
->bin_window
;
147 /* don't report problems */
153 if (window
->m_wxwindow
)
154 m_cmap
= gtk_widget_get_colormap( window
->m_wxwindow
);
156 m_cmap
= gtk_widget_get_colormap( window
->m_widget
);
160 /* this must be done after SetUpDC, bacause SetUpDC calls the
161 repective SetBrush, SetPen, SetBackground etc functions
162 to set up the DC. SetBackground call m_owner->SetBackground
163 and this might not be desired as the standard dc background
164 is white whereas a window might assume gray to be the
165 standard (as e.g. wxStatusBar) */
170 wxWindowDC::~wxWindowDC()
175 void wxWindowDC::DoFloodFill( wxCoord
WXUNUSED(x
), wxCoord
WXUNUSED(y
),
176 const wxColour
&WXUNUSED(col
), int WXUNUSED(style
) )
178 wxFAIL_MSG( wxT("wxWindowDC::DoFloodFill not implemented") );
181 bool wxWindowDC::DoGetPixel( wxCoord
WXUNUSED(x1
), wxCoord
WXUNUSED(y1
), wxColour
*WXUNUSED(col
) ) const
183 wxFAIL_MSG( wxT("wxWindowDC::DoGetPixel not implemented") );
187 void wxWindowDC::DoDrawLine( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
)
189 wxCHECK_RET( Ok(), wxT("invalid window dc") );
191 if (m_pen
.GetStyle() != wxTRANSPARENT
)
194 gdk_draw_line( m_window
, m_penGC
, XLOG2DEV(x1
), YLOG2DEV(y1
), XLOG2DEV(x2
), YLOG2DEV(y2
) );
196 CalcBoundingBox(x1
, y1
);
197 CalcBoundingBox(x2
, y2
);
201 void wxWindowDC::DoCrossHair( wxCoord x
, wxCoord y
)
203 wxCHECK_RET( Ok(), wxT("invalid window dc") );
205 if (m_pen
.GetStyle() != wxTRANSPARENT
)
210 wxCoord xx
= XLOG2DEV(x
);
211 wxCoord yy
= YLOG2DEV(y
);
214 gdk_draw_line( m_window
, m_penGC
, 0, yy
, XLOG2DEVREL(w
), yy
);
215 gdk_draw_line( m_window
, m_penGC
, xx
, 0, xx
, YLOG2DEVREL(h
) );
220 void wxWindowDC::DoDrawArc( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
,
221 wxCoord xc
, wxCoord yc
)
223 wxCHECK_RET( Ok(), wxT("invalid window dc") );
225 wxCoord xx1
= XLOG2DEV(x1
);
226 wxCoord yy1
= YLOG2DEV(y1
);
227 wxCoord xx2
= XLOG2DEV(x2
);
228 wxCoord yy2
= YLOG2DEV(y2
);
229 wxCoord xxc
= XLOG2DEV(xc
);
230 wxCoord yyc
= YLOG2DEV(yc
);
231 double dx
= xx1
- xxc
;
232 double dy
= yy1
- yyc
;
233 double radius
= sqrt((double)(dx
*dx
+dy
*dy
));
234 wxCoord r
= (wxCoord
)radius
;
235 double radius1
, radius2
;
237 if (xx1
== xx2
&& yy1
== yy2
)
245 radius1
= radius2
= 0.0;
249 radius1
= (xx1
- xxc
== 0) ?
250 (yy1
- yyc
< 0) ? 90.0 : -90.0 :
251 -atan2(double(yy1
-yyc
), double(xx1
-xxc
)) * RAD2DEG
;
252 radius2
= (xx2
- xxc
== 0) ?
253 (yy2
- yyc
< 0) ? 90.0 : -90.0 :
254 -atan2(double(yy2
-yyc
), double(xx2
-xxc
)) * RAD2DEG
;
256 wxCoord alpha1
= wxCoord(radius1
* 64.0);
257 wxCoord alpha2
= wxCoord((radius2
- radius1
) * 64.0);
258 while (alpha2
<= 0) alpha2
+= 360*64;
259 while (alpha1
> 360*64) alpha1
-= 360*64;
263 if (m_brush
.GetStyle() != wxTRANSPARENT
)
264 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
266 if (m_pen
.GetStyle() != wxTRANSPARENT
)
267 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
270 CalcBoundingBox (x1
, y1
);
271 CalcBoundingBox (x2
, y2
);
274 void wxWindowDC::DoDrawEllipticArc( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double sa
, double ea
)
276 wxCHECK_RET( Ok(), wxT("invalid window dc") );
278 wxCoord xx
= XLOG2DEV(x
);
279 wxCoord yy
= YLOG2DEV(y
);
280 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
281 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
283 // CMB: handle -ve width and/or height
284 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
285 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
289 wxCoord start
= wxCoord(sa
* 64.0);
290 wxCoord end
= wxCoord(ea
* 64.0);
292 if (m_brush
.GetStyle() != wxTRANSPARENT
)
293 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end
);
295 if (m_pen
.GetStyle() != wxTRANSPARENT
)
296 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
, hh
, start
, end
);
299 CalcBoundingBox (x
, y
);
300 CalcBoundingBox (x
+ width
, y
+ height
);
303 void wxWindowDC::DoDrawPoint( wxCoord x
, wxCoord y
)
305 wxCHECK_RET( Ok(), wxT("invalid window dc") );
307 if ((m_pen
.GetStyle() != wxTRANSPARENT
) && m_window
)
308 gdk_draw_point( m_window
, m_penGC
, XLOG2DEV(x
), YLOG2DEV(y
) );
310 CalcBoundingBox (x
, y
);
313 void wxWindowDC::DoDrawLines( int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
)
315 wxCHECK_RET( Ok(), wxT("invalid window dc") );
317 if (m_pen
.GetStyle() == wxTRANSPARENT
) return;
320 CalcBoundingBox( points
[0].x
+ xoffset
, points
[0].y
+ yoffset
);
322 for (int i
= 0; i
< n
-1; i
++)
324 wxCoord x1
= XLOG2DEV(points
[i
].x
+ xoffset
);
325 wxCoord x2
= XLOG2DEV(points
[i
+1].x
+ xoffset
);
326 wxCoord y1
= YLOG2DEV(points
[i
].y
+ yoffset
); // oh, what a waste
327 wxCoord y2
= YLOG2DEV(points
[i
+1].y
+ yoffset
);
330 gdk_draw_line( m_window
, m_penGC
, x1
, y1
, x2
, y2
);
332 CalcBoundingBox( points
[i
+1].x
+ xoffset
, points
[i
+1].y
+ yoffset
);
336 void wxWindowDC::DoDrawPolygon( int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
, int WXUNUSED(fillStyle
) )
338 wxCHECK_RET( Ok(), wxT("invalid window dc") );
342 GdkPoint
*gdkpoints
= new GdkPoint
[n
+1];
344 for (i
= 0 ; i
< n
; i
++)
346 gdkpoints
[i
].x
= XLOG2DEV(points
[i
].x
+ xoffset
);
347 gdkpoints
[i
].y
= YLOG2DEV(points
[i
].y
+ yoffset
);
349 CalcBoundingBox( points
[i
].x
+ xoffset
, points
[i
].y
+ yoffset
);
352 if ((m_brush
.GetStyle() != wxTRANSPARENT
) && m_window
)
353 gdk_draw_polygon (m_window
, m_brushGC
, TRUE
, gdkpoints
, n
);
357 if ((m_pen
.GetStyle() != wxTRANSPARENT
) && m_window
)
359 for (i
= 0 ; i
< n
; i
++)
361 gdk_draw_line( m_window
, m_penGC
,
364 gdkpoints
[(i
+1)%n
].x
,
365 gdkpoints
[(i
+1)%n
].y
);
372 void wxWindowDC::DoDrawRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
374 wxCHECK_RET( Ok(), wxT("invalid window dc") );
376 wxCoord xx
= XLOG2DEV(x
);
377 wxCoord yy
= YLOG2DEV(y
);
378 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
379 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
381 // CMB: draw nothing if transformed w or h is 0
382 if (ww
== 0 || hh
== 0) return;
384 // CMB: handle -ve width and/or height
385 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
386 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
390 if (m_brush
.GetStyle() != wxTRANSPARENT
)
391 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
);
393 if (m_pen
.GetStyle() != wxTRANSPARENT
)
394 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 wxWindowDC::DoDrawRoundedRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double radius
)
403 wxCHECK_RET( Ok(), wxT("invalid window dc") );
405 if (radius
< 0.0) radius
= - radius
* ((width
< height
) ? width
: height
);
407 wxCoord xx
= XLOG2DEV(x
);
408 wxCoord yy
= YLOG2DEV(y
);
409 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
410 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
411 wxCoord rr
= XLOG2DEVREL((wxCoord
)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
)
438 // CMB: ensure dd is not larger than rectangle otherwise we
439 // get an hour glass shape
441 if (dd
> ww
) dd
= ww
;
442 if (dd
> hh
) dd
= hh
;
445 if (m_brush
.GetStyle() != wxTRANSPARENT
)
447 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh
);
448 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 );
449 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
450 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
451 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
452 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
455 if (m_pen
.GetStyle() != wxTRANSPARENT
)
457 gdk_draw_line( m_window
, m_penGC
, xx
+rr
, yy
, xx
+ww
-rr
, yy
);
458 gdk_draw_line( m_window
, m_penGC
, xx
+rr
, yy
+hh
, xx
+ww
-rr
, yy
+hh
);
459 gdk_draw_line( m_window
, m_penGC
, xx
, yy
+rr
, xx
, yy
+hh
-rr
);
460 gdk_draw_line( m_window
, m_penGC
, xx
+ww
, yy
+rr
, xx
+ww
, yy
+hh
-rr
);
461 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
462 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
463 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
464 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
468 // this ignores the radius
469 CalcBoundingBox( x
, y
);
470 CalcBoundingBox( x
+ width
, y
+ height
);
473 void wxWindowDC::DoDrawEllipse( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
475 wxCHECK_RET( Ok(), wxT("invalid window dc") );
477 wxCoord xx
= XLOG2DEV(x
);
478 wxCoord yy
= YLOG2DEV(y
);
479 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
480 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
482 // CMB: handle -ve width and/or height
483 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
484 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
488 if (m_brush
.GetStyle() != wxTRANSPARENT
)
489 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 );
491 if (m_pen
.GetStyle() != wxTRANSPARENT
)
492 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
, hh
, 0, 360*64 );
495 CalcBoundingBox( x
- width
, y
- height
);
496 CalcBoundingBox( x
+ width
, y
+ height
);
499 void wxWindowDC::DoDrawIcon( const wxIcon
&icon
, wxCoord x
, wxCoord y
)
501 // VZ: egcs 1.0.3 refuses to compile this without cast, no idea why
502 DoDrawBitmap( (const wxBitmap
&)icon
, x
, y
, (bool)TRUE
);
505 void wxWindowDC::DoDrawBitmap( const wxBitmap
&bitmap
,
506 wxCoord x
, wxCoord y
,
509 wxCHECK_RET( Ok(), wxT("invalid window dc") );
511 wxCHECK_RET( bitmap
.Ok(), wxT("invalid bitmap") );
513 /* scale/translate size and position */
515 int xx
= XLOG2DEV(x
);
516 int yy
= YLOG2DEV(y
);
518 int w
= bitmap
.GetWidth();
519 int h
= bitmap
.GetHeight();
521 CalcBoundingBox( x
, y
);
522 CalcBoundingBox( x
+ w
, y
+ h
);
524 if (!m_window
) return;
526 int ww
= XLOG2DEVREL(w
);
527 int hh
= YLOG2DEVREL(h
);
529 /* scale bitmap if required */
533 if ((w
!= ww
) || (h
!= hh
))
535 wxImage
image( bitmap
);
536 image
= image
.Scale( ww
, hh
);
538 use_bitmap
= image
.ConvertToBitmap();
545 /* apply mask if any */
547 GdkBitmap
*mask
= (GdkBitmap
*) NULL
;
548 if (use_bitmap
.GetMask()) mask
= use_bitmap
.GetMask()->GetBitmap();
552 gdk_gc_set_clip_mask( m_penGC
, mask
);
553 gdk_gc_set_clip_origin( m_penGC
, xx
, yy
);
556 /* draw XPixmap or XBitmap, depending on what the wxBitmap contains */
558 GdkPixmap
*pm
= use_bitmap
.GetPixmap();
561 gdk_draw_pixmap( m_window
, m_penGC
, pm
, 0, 0, xx
, yy
, -1, -1 );
565 GdkBitmap
*bm
= use_bitmap
.GetBitmap();
568 gdk_draw_bitmap( m_window
, m_penGC
, bm
, 0, 0, xx
, yy
, -1, -1 );
572 /* remove mask again if any */
576 gdk_gc_set_clip_mask( m_penGC
, (GdkBitmap
*) NULL
);
577 gdk_gc_set_clip_origin( m_penGC
, 0, 0 );
581 bool wxWindowDC::DoBlit( wxCoord xdest
, wxCoord ydest
, wxCoord width
, wxCoord height
,
582 wxDC
*source
, wxCoord xsrc
, wxCoord ysrc
,
583 int logical_func
, bool useMask
)
585 /* this is the nth try to get this utterly useless function to
586 work. it now completely ignores the scaling or translation
587 of the source dc, but scales correctly on the target dc and
588 knows about possible mask information in a memory dc. */
590 wxCHECK_MSG( Ok(), FALSE
, wxT("invalid window dc") );
592 wxCHECK_MSG( source
, FALSE
, wxT("invalid source dc") );
594 if (!m_window
) return FALSE
;
596 wxClientDC
*srcDC
= (wxClientDC
*)source
;
597 wxMemoryDC
*memDC
= (wxMemoryDC
*)source
;
599 bool use_bitmap_method
= FALSE
;
601 if (srcDC
->m_isMemDC
)
603 if (!memDC
->m_selected
.Ok()) return FALSE
;
605 /* we use the "XCopyArea" way to copy a memory dc into
606 y different window if the memory dc BOTH
607 a) doesn't have any mask or its mask isn't used
611 if (useMask
&& (memDC
->m_selected
.GetMask()))
613 /* we HAVE TO use the direct way for memory dcs
614 that have mask since the XCopyArea doesn't know
616 use_bitmap_method
= TRUE
;
618 else if (memDC
->m_selected
.GetDepth() == 1)
620 /* we HAVE TO use the direct way for memory dcs
621 that are bitmaps because XCopyArea doesn't cope
622 with different bit depths */
623 use_bitmap_method
= TRUE
;
625 else if ((xsrc
== 0) && (ysrc
== 0) &&
626 (width
== memDC
->m_selected
.GetWidth()) &&
627 (height
== memDC
->m_selected
.GetHeight()))
629 /* we SHOULD use the direct way if all of the bitmap
630 in the memory dc is copied in which case XCopyArea
631 wouldn't be able able to boost performace by reducing
632 the area to be scaled */
633 use_bitmap_method
= TRUE
;
637 use_bitmap_method
= FALSE
;
641 CalcBoundingBox( xdest
, ydest
);
642 CalcBoundingBox( xdest
+ width
, ydest
+ height
);
644 int old_logical_func
= m_logicalFunction
;
645 SetLogicalFunction( logical_func
);
647 if (use_bitmap_method
)
649 /* scale/translate bitmap size */
651 wxCoord bm_width
= memDC
->m_selected
.GetWidth();
652 wxCoord bm_height
= memDC
->m_selected
.GetHeight();
654 wxCoord bm_ww
= XLOG2DEVREL( bm_width
);
655 wxCoord bm_hh
= YLOG2DEVREL( bm_height
);
657 /* scale bitmap if required */
661 if ((bm_width
!= bm_ww
) || (bm_height
!= bm_hh
))
663 wxImage
image( memDC
->m_selected
);
664 image
= image
.Scale( bm_ww
, bm_hh
);
666 use_bitmap
= image
.ConvertToBitmap();
670 use_bitmap
= memDC
->m_selected
;
673 /* scale/translate size and position */
675 wxCoord xx
= XLOG2DEV(xdest
);
676 wxCoord yy
= YLOG2DEV(ydest
);
678 wxCoord ww
= XLOG2DEVREL(width
);
679 wxCoord hh
= YLOG2DEVREL(height
);
681 /* apply mask if any */
683 GdkBitmap
*mask
= (GdkBitmap
*) NULL
;
684 if (use_bitmap
.GetMask()) mask
= use_bitmap
.GetMask()->GetBitmap();
688 gdk_gc_set_clip_mask( m_penGC
, mask
);
689 gdk_gc_set_clip_origin( m_penGC
, xx
, yy
);
692 /* draw XPixmap or XBitmap, depending on what the wxBitmap contains */
694 GdkPixmap
*pm
= use_bitmap
.GetPixmap();
697 gdk_draw_pixmap( m_window
, m_penGC
, pm
, xsrc
, ysrc
, xx
, yy
, ww
, hh
);
701 GdkBitmap
*bm
= use_bitmap
.GetBitmap();
704 /* we use the textGC here because blitting a bitmap is done
705 using the current text colour */
706 gdk_draw_bitmap( m_window
, m_textGC
, bm
, xsrc
, ysrc
, xx
, yy
, ww
, hh
);
710 /* remove mask again if any */
714 gdk_gc_set_clip_mask( m_penGC
, (GdkBitmap
*) NULL
);
715 gdk_gc_set_clip_origin( m_penGC
, 0, 0 );
718 else /* use_bitmap_method */
720 /* scale/translate size and position */
722 wxCoord xx
= XLOG2DEV(xdest
);
723 wxCoord yy
= YLOG2DEV(ydest
);
725 wxCoord ww
= XLOG2DEVREL(width
);
726 wxCoord hh
= YLOG2DEVREL(height
);
728 if ((width
!= ww
) || (height
!= hh
))
730 /* draw source window into a bitmap as we cannot scale
731 a window in contrast to a bitmap. this would actually
732 work with memory dcs as well, but we'd lose the mask
733 information and waste one step in this process since
734 a memory already has a bitmap. all this is slightly
735 inefficient as we could take an XImage directly from
736 an X window, but we'd then also have to care that
737 the window is not outside the screen (in which case
738 we'd get a BadMatch or what not).
739 Is a double XGetImage and combined XGetPixel and
740 XPutPixel really faster? I'm not sure. look at wxXt
741 for a different implementation of the same problem. */
743 wxBitmap
bitmap( width
, height
);
744 gdk_window_copy_area( bitmap
.GetPixmap(), m_penGC
, 0, 0,
746 xsrc
, ysrc
, width
, height
);
750 wxImage
image( bitmap
);
751 image
= image
.Scale( ww
, hh
);
753 /* convert to bitmap */
755 bitmap
= image
.ConvertToBitmap();
757 /* draw scaled bitmap */
759 gdk_draw_pixmap( m_window
, m_penGC
, bitmap
.GetPixmap(), 0, 0, xx
, yy
, -1, -1 );
764 /* no scaling and not a memory dc with a mask either */
766 gdk_window_copy_area( m_window
, m_penGC
, xx
, yy
,
768 xsrc
, ysrc
, width
, height
);
772 SetLogicalFunction( old_logical_func
);
776 void wxWindowDC::DoDrawText( const wxString
&text
, wxCoord x
, wxCoord y
)
778 wxCHECK_RET( Ok(), wxT("invalid window dc") );
780 if (!m_window
) return;
782 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
784 wxCHECK_RET( font
, wxT("invalid font") );
789 /* CMB 21/5/98: draw text background if mode is wxSOLID */
790 if (m_backgroundMode
== wxSOLID
)
792 wxCoord width
= gdk_string_width( font
, text
.mbc_str() );
793 wxCoord height
= font
->ascent
+ font
->descent
;
794 gdk_gc_set_foreground( m_textGC
, m_textBackgroundColour
.GetColor() );
795 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, x
, y
, width
, height
);
796 gdk_gc_set_foreground( m_textGC
, m_textForegroundColour
.GetColor() );
798 gdk_draw_string( m_window
, font
, m_textGC
, x
, y
+ font
->ascent
, text
.mbc_str() );
800 /* CMB 17/7/98: simple underline: ignores scaling and underlying
801 X font's XA_UNDERLINE_POSITION and XA_UNDERLINE_THICKNESS
802 properties (see wxXt implementation) */
803 if (m_font
.GetUnderlined())
805 long width
= gdk_string_width( font
, text
.mbc_str() );
806 long ul_y
= y
+ font
->ascent
;
807 if (font
->descent
> 0) ul_y
++;
808 gdk_draw_line( m_window
, m_textGC
, x
, ul_y
, x
+ width
, ul_y
);
812 GetTextExtent (text
, &w
, &h
);
813 CalcBoundingBox (x
+ w
, y
+ h
);
814 CalcBoundingBox (x
, y
);
817 void wxWindowDC::DoDrawRotatedText( const wxString
&text
, wxCoord x
, wxCoord y
, double angle
)
821 DrawText(text
, x
, y
);
825 wxCHECK_RET( Ok(), wxT("invalid window dc") );
827 if (!m_window
) return;
829 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
831 wxCHECK_RET( font
, wxT("invalid font") );
836 int cx
= gdk_string_width( font
, text
.mbc_str() );
837 int cy
= font
->ascent
+ font
->descent
;
839 wxBitmap
src(cx
, cy
);
841 dc
.SelectObject(src
);
842 dc
.SetFont(GetFont());
843 dc
.SetBackground(*wxWHITE_BRUSH
);
844 dc
.SetBrush(*wxBLACK_BRUSH
);
846 dc
.DrawText(text
, 0, 0);
847 dc
.SetFont(wxNullFont
);
849 // Calculate the size of the rotated bounding box.
850 double dx
= cos(angle
/ 180.0 * M_PI
);
851 double dy
= sin(angle
/ 180.0 * M_PI
);
852 double x4
= -cy
* dy
;
861 // Create image from the source bitmap after writing the text into it.
864 int minx
= roundmin(0, roundmin(x4
, roundmin(x2
, x3
)));
865 int miny
= roundmin(0, roundmin(y4
, roundmin(y2
, y3
)));
866 int maxx
= roundmax(0, roundmax(x4
, roundmax(x2
, x3
)));
867 int maxy
= roundmax(0, roundmax(y4
, roundmax(y2
, y3
)));
869 // This rotates counterclockwise around the top left corner.
870 for (int rx
= minx
; rx
< maxx
; rx
++)
872 for (int ry
= miny
; ry
< maxy
; ry
++)
874 // transform dest coords to source coords
875 int sx
= (int) (rx
* dx
+ ry
* dy
+ 0.5);
876 int sy
= (int) (ry
* dx
- rx
* dy
+ 0.5);
877 if (sx
>= 0 && sx
< cx
&& sy
>= 0 && sy
< cy
)
879 // draw black pixels, ignore white ones (i.e. transparent b/g)
880 if (image
.GetRed(sx
, sy
) == 0)
882 DrawPoint(x1
+ maxx
- rx
, cy
+ y1
- ry
);
887 //DrawPoint(x1 + maxx - rx, cy + y1 + maxy - ry);
893 // TODO call CalcBoundingBox()
896 void wxWindowDC::DoGetTextExtent(const wxString
&string
,
897 wxCoord
*width
, wxCoord
*height
,
898 wxCoord
*descent
, wxCoord
*externalLeading
,
899 wxFont
*theFont
) const
901 wxFont fontToUse
= m_font
;
902 if (theFont
) fontToUse
= *theFont
;
904 GdkFont
*font
= fontToUse
.GetInternalFont( m_scaleY
);
905 if (width
) (*width
) = wxCoord(gdk_string_width( font
, string
.mbc_str() ) / m_scaleX
);
906 if (height
) (*height
) = wxCoord((font
->ascent
+ font
->descent
) / m_scaleY
);
907 if (descent
) (*descent
) = wxCoord(font
->descent
/ m_scaleY
);
908 if (externalLeading
) (*externalLeading
) = 0; // ??
911 wxCoord
wxWindowDC::GetCharWidth() const
913 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
914 wxCHECK_MSG( font
, -1, wxT("invalid font") );
916 return wxCoord(gdk_string_width( font
, "H" ) / m_scaleX
);
919 wxCoord
wxWindowDC::GetCharHeight() const
921 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
922 wxCHECK_MSG( font
, -1, wxT("invalid font") );
924 return wxCoord((font
->ascent
+ font
->descent
) / m_scaleY
);
927 void wxWindowDC::Clear()
929 wxCHECK_RET( Ok(), wxT("invalid window dc") );
931 if (!m_window
) return;
933 /* - we either are a memory dc or have a window as the
934 owner. anything else shouldn't happen.
935 - we don't use gdk_window_clear() as we don't set
936 the window's background colour anymore. it is too
937 much pain to keep the DC's and the window's back-
938 ground colour in synch. */
943 m_owner
->GetSize( &width
, &height
);
944 gdk_draw_rectangle( m_window
, m_bgGC
, TRUE
, 0, 0, width
, height
);
951 GetSize( &width
, &height
);
952 gdk_draw_rectangle( m_window
, m_bgGC
, TRUE
, 0, 0, width
, height
);
957 void wxWindowDC::SetFont( const wxFont
&font
)
962 void wxWindowDC::SetPen( const wxPen
&pen
)
964 wxCHECK_RET( Ok(), wxT("invalid window dc") );
966 if (m_pen
== pen
) return;
970 if (!m_pen
.Ok()) return;
972 if (!m_window
) return;
974 gint width
= m_pen
.GetWidth();
977 // CMB: if width is non-zero scale it with the dc
982 // X doesn't allow different width in x and y and so we take
985 ( fabs((double) XLOG2DEVREL(width
)) +
986 fabs((double) YLOG2DEVREL(width
)) ) / 2.0;
990 static const char dotted
[] = {1, 1};
991 static const char short_dashed
[] = {2, 2};
992 static const char wxCoord_dashed
[] = {2, 4};
993 static const char dotted_dashed
[] = {3, 3, 1, 3};
995 // We express dash pattern in pen width unit, so we are
996 // independent of zoom factor and so on...
998 const char *req_dash
;
1000 GdkLineStyle lineStyle
= GDK_LINE_SOLID
;
1001 switch (m_pen
.GetStyle())
1005 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1006 req_nb_dash
= m_pen
.GetDashCount();
1007 req_dash
= m_pen
.GetDash();
1012 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1019 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1021 req_dash
= wxCoord_dashed
;
1026 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1028 req_dash
= short_dashed
;
1033 // lineStyle = GDK_LINE_DOUBLE_DASH;
1034 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1036 req_dash
= dotted_dashed
;
1045 lineStyle
= GDK_LINE_SOLID
;
1046 req_dash
= (wxDash
*)NULL
;
1052 #if (GTK_MINOR_VERSION > 0)
1053 if (req_dash
&& req_nb_dash
)
1055 char *real_req_dash
= new char[req_nb_dash
];
1058 for (int i
= 0; i
< req_nb_dash
; i
++)
1059 real_req_dash
[i
] = req_dash
[i
] * width
;
1060 gdk_gc_set_dashes( m_penGC
, 0, real_req_dash
, req_nb_dash
);
1061 delete[] real_req_dash
;
1065 // No Memory. We use non-scaled dash pattern...
1066 gdk_gc_set_dashes( m_penGC
, 0, (char*)req_dash
, req_nb_dash
);
1071 GdkCapStyle capStyle
= GDK_CAP_ROUND
;
1072 switch (m_pen
.GetCap())
1074 case wxCAP_ROUND
: { capStyle
= (width
<= 1) ? GDK_CAP_NOT_LAST
: GDK_CAP_ROUND
; break; }
1075 case wxCAP_PROJECTING
: { capStyle
= GDK_CAP_PROJECTING
; break; }
1076 case wxCAP_BUTT
: { capStyle
= GDK_CAP_BUTT
; break; }
1079 GdkJoinStyle joinStyle
= GDK_JOIN_ROUND
;
1080 switch (m_pen
.GetJoin())
1082 case wxJOIN_BEVEL
: { joinStyle
= GDK_JOIN_BEVEL
; break; }
1083 case wxJOIN_ROUND
: { joinStyle
= GDK_JOIN_ROUND
; break; }
1084 case wxJOIN_MITER
: { joinStyle
= GDK_JOIN_MITER
; break; }
1087 gdk_gc_set_line_attributes( m_penGC
, width
, lineStyle
, capStyle
, joinStyle
);
1089 m_pen
.GetColour().CalcPixel( m_cmap
);
1090 gdk_gc_set_foreground( m_penGC
, m_pen
.GetColour().GetColor() );
1093 void wxWindowDC::SetBrush( const wxBrush
&brush
)
1095 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1097 if (m_brush
== brush
) return;
1101 if (!m_brush
.Ok()) return;
1103 if (!m_window
) return;
1105 m_brush
.GetColour().CalcPixel( m_cmap
);
1106 gdk_gc_set_foreground( m_brushGC
, m_brush
.GetColour().GetColor() );
1108 gdk_gc_set_fill( m_brushGC
, GDK_SOLID
);
1110 if ((m_brush
.GetStyle() == wxSTIPPLE
) && (m_brush
.GetStipple()->Ok()))
1112 if (m_brush
.GetStipple()->GetPixmap())
1114 gdk_gc_set_fill( m_brushGC
, GDK_TILED
);
1115 gdk_gc_set_tile( m_brushGC
, m_brush
.GetStipple()->GetPixmap() );
1119 gdk_gc_set_fill( m_brushGC
, GDK_STIPPLED
);
1120 gdk_gc_set_stipple( m_brushGC
, m_brush
.GetStipple()->GetBitmap() );
1124 if (IS_HATCH(m_brush
.GetStyle()))
1126 gdk_gc_set_fill( m_brushGC
, GDK_STIPPLED
);
1127 int num
= m_brush
.GetStyle() - wxBDIAGONAL_HATCH
;
1128 gdk_gc_set_stipple( m_brushGC
, hatches
[num
] );
1132 void wxWindowDC::SetBackground( const wxBrush
&brush
)
1134 /* CMB 21/7/98: Added SetBackground. Sets background brush
1135 * for Clear() and bg colour for shapes filled with cross-hatch brush */
1137 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1139 if (m_backgroundBrush
== brush
) return;
1141 m_backgroundBrush
= brush
;
1143 if (!m_backgroundBrush
.Ok()) return;
1145 if (!m_window
) return;
1147 m_backgroundBrush
.GetColour().CalcPixel( m_cmap
);
1148 gdk_gc_set_background( m_brushGC
, m_backgroundBrush
.GetColour().GetColor() );
1149 gdk_gc_set_background( m_penGC
, m_backgroundBrush
.GetColour().GetColor() );
1150 gdk_gc_set_background( m_bgGC
, m_backgroundBrush
.GetColour().GetColor() );
1151 gdk_gc_set_foreground( m_bgGC
, m_backgroundBrush
.GetColour().GetColor() );
1153 gdk_gc_set_fill( m_bgGC
, GDK_SOLID
);
1155 if ((m_backgroundBrush
.GetStyle() == wxSTIPPLE
) && (m_backgroundBrush
.GetStipple()->Ok()))
1157 if (m_backgroundBrush
.GetStipple()->GetPixmap())
1159 gdk_gc_set_fill( m_bgGC
, GDK_TILED
);
1160 gdk_gc_set_tile( m_bgGC
, m_backgroundBrush
.GetStipple()->GetPixmap() );
1164 gdk_gc_set_fill( m_bgGC
, GDK_STIPPLED
);
1165 gdk_gc_set_stipple( m_bgGC
, m_backgroundBrush
.GetStipple()->GetBitmap() );
1169 if (IS_HATCH(m_backgroundBrush
.GetStyle()))
1171 gdk_gc_set_fill( m_bgGC
, GDK_STIPPLED
);
1172 int num
= m_backgroundBrush
.GetStyle() - wxBDIAGONAL_HATCH
;
1173 gdk_gc_set_stipple( m_bgGC
, hatches
[num
] );
1177 void wxWindowDC::SetLogicalFunction( int function
)
1179 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1181 if (m_logicalFunction
== function
) return;
1183 GdkFunction mode
= GDK_COPY
;
1186 case wxXOR
: mode
= GDK_XOR
; break;
1187 case wxINVERT
: mode
= GDK_INVERT
; break;
1188 #if (GTK_MINOR_VERSION > 0)
1189 case wxOR_REVERSE
: mode
= GDK_OR_REVERSE
; break;
1190 case wxAND_REVERSE
: mode
= GDK_AND_REVERSE
; break;
1191 case wxCLEAR
: mode
= GDK_CLEAR
; break;
1192 case wxSET
: mode
= GDK_SET
; break;
1193 case wxOR_INVERT
: mode
= GDK_OR_INVERT
; break;
1195 case wxAND
: mode
= GDK_AND
; break;
1197 case wxOR
: mode
= GDK_OR
; break;
1198 case wxEQUIV
: mode
= GDK_EQUIV
; break;
1199 case wxNAND
: mode
= GDK_NAND
; break;
1200 case wxAND_INVERT
: mode
= GDK_AND_INVERT
; break;
1201 case wxCOPY
: mode
= GDK_COPY
; break;
1202 case wxNO_OP
: mode
= GDK_NOOP
; break;
1203 case wxSRC_INVERT
: mode
= GDK_COPY_INVERT
; break;
1207 wxFAIL_MSG( wxT("unsupported logical function") );
1212 m_logicalFunction
= function
;
1214 if (!m_window
) return;
1216 gdk_gc_set_function( m_penGC
, mode
);
1217 gdk_gc_set_function( m_brushGC
, mode
);
1218 gdk_gc_set_function( m_textGC
, mode
);
1221 void wxWindowDC::SetTextForeground( const wxColour
&col
)
1223 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1225 if (m_textForegroundColour
== col
) return;
1227 m_textForegroundColour
= col
;
1228 if (!m_textForegroundColour
.Ok()) return;
1230 if (!m_window
) return;
1232 m_textForegroundColour
.CalcPixel( m_cmap
);
1233 gdk_gc_set_foreground( m_textGC
, m_textForegroundColour
.GetColor() );
1236 void wxWindowDC::SetTextBackground( const wxColour
&col
)
1238 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1240 if (m_textBackgroundColour
== col
) return;
1242 m_textBackgroundColour
= col
;
1243 if (!m_textBackgroundColour
.Ok()) return;
1245 if (!m_window
) return;
1247 m_textBackgroundColour
.CalcPixel( m_cmap
);
1248 gdk_gc_set_background( m_textGC
, m_textBackgroundColour
.GetColor() );
1251 void wxWindowDC::SetBackgroundMode( int mode
)
1253 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1255 m_backgroundMode
= mode
;
1257 if (!m_window
) return;
1259 // CMB 21/7/98: fill style of cross-hatch brushes is affected by
1260 // transparent/solid background mode
1262 if (m_brush
.GetStyle() != wxSOLID
&& m_brush
.GetStyle() != wxTRANSPARENT
)
1264 gdk_gc_set_fill( m_brushGC
,
1265 (m_backgroundMode
== wxTRANSPARENT
) ? GDK_STIPPLED
: GDK_OPAQUE_STIPPLED
);
1269 void wxWindowDC::SetPalette( const wxPalette
& WXUNUSED(palette
) )
1271 wxFAIL_MSG( wxT("wxWindowDC::SetPalette not implemented") );
1274 void wxWindowDC::DoSetClippingRegion( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
1276 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1278 wxDC::DoSetClippingRegion( x
, y
, width
, height
);
1280 if (!m_window
) return;
1283 rect
.x
= XLOG2DEV(x
);
1284 rect
.y
= YLOG2DEV(y
);
1285 rect
.width
= XLOG2DEVREL(width
);
1286 rect
.height
= YLOG2DEVREL(height
);
1287 gdk_gc_set_clip_rectangle( m_penGC
, &rect
);
1288 gdk_gc_set_clip_rectangle( m_brushGC
, &rect
);
1289 gdk_gc_set_clip_rectangle( m_textGC
, &rect
);
1290 gdk_gc_set_clip_rectangle( m_bgGC
, &rect
);
1293 void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion
®ion
)
1295 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1299 DestroyClippingRegion();
1303 if (!m_window
) return;
1305 gdk_gc_set_clip_region( m_penGC
, region
.GetRegion() );
1306 gdk_gc_set_clip_region( m_brushGC
, region
.GetRegion() );
1307 gdk_gc_set_clip_region( m_textGC
, region
.GetRegion() );
1308 gdk_gc_set_clip_region( m_bgGC
, region
.GetRegion() );
1311 void wxWindowDC::DestroyClippingRegion()
1313 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1315 wxDC::DestroyClippingRegion();
1317 if (!m_window
) return;
1319 gdk_gc_set_clip_rectangle( m_penGC
, (GdkRectangle
*) NULL
);
1320 gdk_gc_set_clip_rectangle( m_brushGC
, (GdkRectangle
*) NULL
);
1321 gdk_gc_set_clip_rectangle( m_textGC
, (GdkRectangle
*) NULL
);
1322 gdk_gc_set_clip_rectangle( m_bgGC
, (GdkRectangle
*) NULL
);
1325 void wxWindowDC::SetUpDC()
1329 m_logicalFunction
= wxCOPY
;
1330 m_penGC
= gdk_gc_new( m_window
);
1331 m_brushGC
= gdk_gc_new( m_window
);
1332 m_textGC
= gdk_gc_new( m_window
);
1333 m_bgGC
= gdk_gc_new( m_window
);
1335 wxColour
tmp_col( m_textForegroundColour
);
1336 m_textForegroundColour
= wxNullColour
;
1337 SetTextForeground( tmp_col
);
1338 tmp_col
= m_textBackgroundColour
;
1339 m_textBackgroundColour
= wxNullColour
;
1340 SetTextBackground( tmp_col
);
1342 wxPen
tmp_pen( m_pen
);
1346 wxFont
tmp_font( m_font
);
1347 m_font
= wxNullFont
;
1348 SetFont( tmp_font
);
1350 wxBrush
tmp_brush( m_brush
);
1351 m_brush
= wxNullBrush
;
1352 SetBrush( tmp_brush
);
1355 tmp_brush = m_backgroundBrush;
1356 m_backgroundBrush = wxNullBrush;
1357 SetBackground( tmp_brush );
1359 tmp_brush
= m_backgroundBrush
;
1360 m_backgroundBrush
= wxNullBrush
;
1361 SetBackground( *wxWHITE_BRUSH
);
1362 m_backgroundBrush
= tmp_brush
;
1366 hatch_bitmap
= hatches
;
1367 hatch_bitmap
[0] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, bdiag_bits
, bdiag_width
, bdiag_height
);
1368 hatch_bitmap
[1] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, cdiag_bits
, cdiag_width
, cdiag_height
);
1369 hatch_bitmap
[2] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, fdiag_bits
, fdiag_width
, fdiag_height
);
1370 hatch_bitmap
[3] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, cross_bits
, cross_width
, cross_height
);
1371 hatch_bitmap
[4] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, horiz_bits
, horiz_width
, horiz_height
);
1372 hatch_bitmap
[5] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, verti_bits
, verti_width
, verti_height
);
1376 void wxWindowDC::Destroy()
1378 if (m_penGC
) gdk_gc_unref( m_penGC
);
1379 m_penGC
= (GdkGC
*) NULL
;
1380 if (m_brushGC
) gdk_gc_unref( m_brushGC
);
1381 m_brushGC
= (GdkGC
*) NULL
;
1382 if (m_textGC
) gdk_gc_unref( m_textGC
);
1383 m_textGC
= (GdkGC
*) NULL
;
1384 if (m_bgGC
) gdk_gc_unref( m_bgGC
);
1385 m_bgGC
= (GdkGC
*) NULL
;
1388 void wxWindowDC::ComputeScaleAndOrigin()
1390 /* CMB: copy scale to see if it changes */
1391 double origScaleX
= m_scaleX
;
1392 double origScaleY
= m_scaleY
;
1394 wxDC::ComputeScaleAndOrigin();
1396 /* CMB: if scale has changed call SetPen to recalulate the line width */
1397 if ((m_scaleX
!= origScaleX
|| m_scaleY
!= origScaleY
) &&
1400 /* this is a bit artificial, but we need to force wxDC to think
1401 the pen has changed */
1408 // Resolution in pixels per logical inch
1409 wxSize
wxWindowDC::GetPPI() const
1411 return wxSize(100, 100);
1414 int wxWindowDC::GetDepth() const
1416 wxFAIL_MSG(wxT("not implemented"));
1422 // ----------------------------------- spline code ----------------------------------------
1424 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
,
1425 double a3
, double b3
, double a4
, double b4
);
1426 void wx_clear_stack();
1427 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
, double *x3
,
1428 double *y3
, double *x4
, double *y4
);
1429 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
,
1430 double x4
, double y4
);
1431 static bool wx_spline_add_point(double x
, double y
);
1432 static void wx_spline_draw_point_array(wxDC
*dc
);
1434 wxList wx_spline_point_list
;
1436 #define half(z1, z2) ((z1+z2)/2.0)
1439 /* iterative version */
1441 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
, double a3
, double b3
, double a4
,
1444 register double xmid
, ymid
;
1445 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
1448 wx_spline_push(a1
, b1
, a2
, b2
, a3
, b3
, a4
, b4
);
1450 while (wx_spline_pop(&x1
, &y1
, &x2
, &y2
, &x3
, &y3
, &x4
, &y4
)) {
1451 xmid
= (double)half(x2
, x3
);
1452 ymid
= (double)half(y2
, y3
);
1453 if (fabs(x1
- xmid
) < THRESHOLD
&& fabs(y1
- ymid
) < THRESHOLD
&&
1454 fabs(xmid
- x4
) < THRESHOLD
&& fabs(ymid
- y4
) < THRESHOLD
) {
1455 wx_spline_add_point( x1
, y1
);
1456 wx_spline_add_point( xmid
, ymid
);
1458 wx_spline_push(xmid
, ymid
, (double)half(xmid
, x3
), (double)half(ymid
, y3
),
1459 (double)half(x3
, x4
), (double)half(y3
, y4
), x4
, y4
);
1460 wx_spline_push(x1
, y1
, (double)half(x1
, x2
), (double)half(y1
, y2
),
1461 (double)half(x2
, xmid
), (double)half(y2
, ymid
), xmid
, ymid
);
1466 /* utilities used by spline drawing routines */
1468 typedef struct wx_spline_stack_struct
{
1469 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
1472 #define SPLINE_STACK_DEPTH 20
1473 static Stack wx_spline_stack
[SPLINE_STACK_DEPTH
];
1474 static Stack
*wx_stack_top
;
1475 static int wx_stack_count
;
1477 void wx_clear_stack()
1479 wx_stack_top
= wx_spline_stack
;
1483 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
, double x4
, double y4
)
1485 wx_stack_top
->x1
= x1
;
1486 wx_stack_top
->y1
= y1
;
1487 wx_stack_top
->x2
= x2
;
1488 wx_stack_top
->y2
= y2
;
1489 wx_stack_top
->x3
= x3
;
1490 wx_stack_top
->y3
= y3
;
1491 wx_stack_top
->x4
= x4
;
1492 wx_stack_top
->y4
= y4
;
1497 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
,
1498 double *x3
, double *y3
, double *x4
, double *y4
)
1500 if (wx_stack_count
== 0)
1504 *x1
= wx_stack_top
->x1
;
1505 *y1
= wx_stack_top
->y1
;
1506 *x2
= wx_stack_top
->x2
;
1507 *y2
= wx_stack_top
->y2
;
1508 *x3
= wx_stack_top
->x3
;
1509 *y3
= wx_stack_top
->y3
;
1510 *x4
= wx_stack_top
->x4
;
1511 *y4
= wx_stack_top
->y4
;
1515 static bool wx_spline_add_point(double x
, double y
)
1517 wxPoint
*point
= new wxPoint
;
1520 wx_spline_point_list
.Append((wxObject
*)point
);
1524 static void wx_spline_draw_point_array(wxDC
*dc
)
1526 dc
->DrawLines(&wx_spline_point_list
, 0, 0 );
1527 wxNode
*node
= wx_spline_point_list
.First();
1530 wxPoint
*point
= (wxPoint
*)node
->Data();
1533 node
= wx_spline_point_list
.First();
1537 void wxWindowDC::DoDrawSpline( wxList
*points
)
1539 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1542 double cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
;
1543 double x1
, y1
, x2
, y2
;
1545 wxNode
*node
= points
->First();
1546 p
= (wxPoint
*)node
->Data();
1551 node
= node
->Next();
1552 p
= (wxPoint
*)node
->Data();
1556 cx1
= (double)((x1
+ x2
) / 2);
1557 cy1
= (double)((y1
+ y2
) / 2);
1558 cx2
= (double)((cx1
+ x2
) / 2);
1559 cy2
= (double)((cy1
+ y2
) / 2);
1561 wx_spline_add_point(x1
, y1
);
1563 while ((node
= node
->Next()) != NULL
)
1565 p
= (wxPoint
*)node
->Data();
1570 cx4
= (double)(x1
+ x2
) / 2;
1571 cy4
= (double)(y1
+ y2
) / 2;
1572 cx3
= (double)(x1
+ cx4
) / 2;
1573 cy3
= (double)(y1
+ cy4
) / 2;
1575 wx_quadratic_spline(cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
);
1579 cx2
= (double)(cx1
+ x2
) / 2;
1580 cy2
= (double)(cy1
+ y2
) / 2;
1583 wx_spline_add_point( cx1
, cy1
);
1584 wx_spline_add_point( x2
, y2
);
1586 wx_spline_draw_point_array( this );
1589 #endif // wxUSE_SPLINE
1591 //-----------------------------------------------------------------------------
1593 //-----------------------------------------------------------------------------
1595 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC
,wxWindowDC
)
1597 wxPaintDC::wxPaintDC()
1602 wxPaintDC::wxPaintDC( wxWindow
*win
)
1607 //-----------------------------------------------------------------------------
1609 //-----------------------------------------------------------------------------
1611 IMPLEMENT_DYNAMIC_CLASS(wxClientDC
,wxWindowDC
)
1613 wxClientDC::wxClientDC()
1618 wxClientDC::wxClientDC( wxWindow
*win
)