1 /////////////////////////////////////////////////////////////////////////////
2 // Name: gtk/dcclient.cpp
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/module.h"
19 #include "wx/gtk/win_gtk.h"
21 #include <math.h> // for floating-point functions
27 //-----------------------------------------------------------------------------
29 //-----------------------------------------------------------------------------
31 #define USE_PAINT_REGION 1
33 //-----------------------------------------------------------------------------
35 //-----------------------------------------------------------------------------
45 static GdkPixmap
*hatches
[num_hatches
];
46 static GdkPixmap
**hatch_bitmap
= (GdkPixmap
**) NULL
;
48 extern GtkWidget
*wxRootWindow
;
50 //-----------------------------------------------------------------------------
52 //-----------------------------------------------------------------------------
54 const double RAD2DEG
= 180.0 / M_PI
;
56 // ----------------------------------------------------------------------------
58 // ----------------------------------------------------------------------------
60 static inline double dmax(double a
, double b
) { return a
> b
? a
: b
; }
61 static inline double dmin(double a
, double b
) { return a
< b
? a
: b
; }
63 static inline double DegToRad(double deg
) { return (deg
* M_PI
) / 180.0; }
65 //-----------------------------------------------------------------------------
66 // temporary implementation of the missing GDK function
67 //-----------------------------------------------------------------------------
69 #include "gdk/gdkprivate.h"
71 void gdk_draw_bitmap (GdkDrawable
*drawable
,
81 GdkWindowPrivate
*drawable_private
;
82 GdkWindowPrivate
*src_private
;
83 GdkGCPrivate
*gc_private
;
85 g_return_if_fail (drawable
!= NULL
);
86 g_return_if_fail (src
!= NULL
);
87 g_return_if_fail (gc
!= NULL
);
89 drawable_private
= (GdkWindowPrivate
*) drawable
;
90 src_private
= (GdkWindowPrivate
*) src
;
91 if (drawable_private
->destroyed
|| src_private
->destroyed
)
94 gc_private
= (GdkGCPrivate
*) gc
;
96 if (width
== -1) width
= src_private
->width
;
97 if (height
== -1) height
= src_private
->height
;
99 XCopyPlane( drawable_private
->xdisplay
,
100 src_private
->xwindow
,
101 drawable_private
->xwindow
,
109 //-----------------------------------------------------------------------------
110 // Implement Pool of Graphic contexts. Creating them takes too much time.
111 //-----------------------------------------------------------------------------
113 #define GC_POOL_SIZE 200
135 static wxGC wxGCPool
[GC_POOL_SIZE
];
137 static void wxInitGCPool()
139 memset( wxGCPool
, 0, GC_POOL_SIZE
*sizeof(wxGC
) );
142 static void wxCleanUpGCPool()
144 for (int i
= 0; i
< GC_POOL_SIZE
; i
++)
146 if (wxGCPool
[i
].m_gc
)
147 gdk_gc_unref( wxGCPool
[i
].m_gc
);
151 static GdkGC
* wxGetPoolGC( GdkWindow
*window
, wxPoolGCType type
)
153 for (int i
= 0; i
< GC_POOL_SIZE
; i
++)
155 if (!wxGCPool
[i
].m_gc
)
157 wxGCPool
[i
].m_gc
= gdk_gc_new( window
);
158 gdk_gc_set_exposures( wxGCPool
[i
].m_gc
, FALSE
);
159 wxGCPool
[i
].m_type
= type
;
160 wxGCPool
[i
].m_used
= FALSE
;
162 if ((!wxGCPool
[i
].m_used
) && (wxGCPool
[i
].m_type
== type
))
164 wxGCPool
[i
].m_used
= TRUE
;
165 return wxGCPool
[i
].m_gc
;
169 wxFAIL_MSG( wxT("No GC available") );
171 return (GdkGC
*) NULL
;
174 static void wxFreePoolGC( GdkGC
*gc
)
176 for (int i
= 0; i
< GC_POOL_SIZE
; i
++)
178 if (wxGCPool
[i
].m_gc
== gc
)
180 wxGCPool
[i
].m_used
= FALSE
;
185 wxFAIL_MSG( wxT("Wrong GC") );
188 //-----------------------------------------------------------------------------
190 //-----------------------------------------------------------------------------
192 IMPLEMENT_DYNAMIC_CLASS(wxWindowDC
, wxDC
)
194 wxWindowDC::wxWindowDC()
196 m_penGC
= (GdkGC
*) NULL
;
197 m_brushGC
= (GdkGC
*) NULL
;
198 m_textGC
= (GdkGC
*) NULL
;
199 m_bgGC
= (GdkGC
*) NULL
;
200 m_cmap
= (GdkColormap
*) NULL
;
202 m_isScreenDC
= FALSE
;
203 m_owner
= (wxWindow
*)NULL
;
206 wxWindowDC::wxWindowDC( wxWindow
*window
)
208 m_penGC
= (GdkGC
*) NULL
;
209 m_brushGC
= (GdkGC
*) NULL
;
210 m_textGC
= (GdkGC
*) NULL
;
211 m_bgGC
= (GdkGC
*) NULL
;
212 m_cmap
= (GdkColormap
*) NULL
;
213 m_owner
= (wxWindow
*)NULL
;
215 m_isScreenDC
= FALSE
;
216 m_font
= window
->GetFont();
218 wxASSERT_MSG( window
, wxT("DC needs a window") );
220 GtkWidget
*widget
= window
->m_wxwindow
;
222 // some controls don't have m_wxwindow - like wxStaticBox, but the user
223 // code should still be able to create wxClientDCs for them, so we will
224 // use the parent window here then
227 window
= window
->GetParent();
228 widget
= window
->m_wxwindow
;
231 wxASSERT_MSG( widget
, wxT("DC needs a widget") );
233 GtkPizza
*pizza
= GTK_PIZZA( widget
);
234 m_window
= pizza
->bin_window
;
239 /* don't report problems */
245 m_cmap
= gtk_widget_get_colormap( widget
? widget
: window
->m_widget
);
249 /* this must be done after SetUpDC, bacause SetUpDC calls the
250 repective SetBrush, SetPen, SetBackground etc functions
251 to set up the DC. SetBackground call m_owner->SetBackground
252 and this might not be desired as the standard dc background
253 is white whereas a window might assume gray to be the
254 standard (as e.g. wxStatusBar) */
259 wxWindowDC::~wxWindowDC()
264 void wxWindowDC::SetUpDC()
268 wxASSERT_MSG( !m_penGC
, wxT("GCs already created") );
270 if (m_isMemDC
&& (((wxMemoryDC
*)this)->m_selected
.GetDepth() == 1))
272 m_penGC
= wxGetPoolGC( m_window
, wxPEN_MONO
);
273 m_brushGC
= wxGetPoolGC( m_window
, wxBRUSH_MONO
);
274 m_textGC
= wxGetPoolGC( m_window
, wxTEXT_MONO
);
275 m_bgGC
= wxGetPoolGC( m_window
, wxBG_MONO
);
279 m_penGC
= wxGetPoolGC( m_window
, wxPEN_COLOUR
);
280 m_brushGC
= wxGetPoolGC( m_window
, wxBRUSH_COLOUR
);
281 m_textGC
= wxGetPoolGC( m_window
, wxTEXT_COLOUR
);
282 m_bgGC
= wxGetPoolGC( m_window
, wxBG_COLOUR
);
285 /* background colour */
286 m_backgroundBrush
= *wxWHITE_BRUSH
;
287 m_backgroundBrush
.GetColour().CalcPixel( m_cmap
);
288 GdkColor
*bg_col
= m_backgroundBrush
.GetColour().GetColor();
291 m_textForegroundColour
.CalcPixel( m_cmap
);
292 gdk_gc_set_foreground( m_textGC
, m_textForegroundColour
.GetColor() );
294 m_textBackgroundColour
.CalcPixel( m_cmap
);
295 gdk_gc_set_background( m_textGC
, m_textBackgroundColour
.GetColor() );
297 gdk_gc_set_fill( m_textGC
, GDK_SOLID
);
300 m_pen
.GetColour().CalcPixel( m_cmap
);
301 gdk_gc_set_foreground( m_penGC
, m_pen
.GetColour().GetColor() );
302 gdk_gc_set_background( m_penGC
, bg_col
);
304 gdk_gc_set_line_attributes( m_penGC
, 0, GDK_LINE_SOLID
, GDK_CAP_NOT_LAST
, GDK_JOIN_ROUND
);
307 m_brush
.GetColour().CalcPixel( m_cmap
);
308 gdk_gc_set_foreground( m_brushGC
, m_brush
.GetColour().GetColor() );
309 gdk_gc_set_background( m_brushGC
, bg_col
);
311 gdk_gc_set_fill( m_brushGC
, GDK_SOLID
);
314 gdk_gc_set_background( m_bgGC
, bg_col
);
315 gdk_gc_set_foreground( m_bgGC
, bg_col
);
317 gdk_gc_set_fill( m_bgGC
, GDK_SOLID
);
320 gdk_gc_set_function( m_textGC
, GDK_COPY
);
321 gdk_gc_set_function( m_brushGC
, GDK_COPY
);
322 gdk_gc_set_function( m_penGC
, GDK_COPY
);
325 gdk_gc_set_clip_rectangle( m_penGC
, (GdkRectangle
*) NULL
);
326 gdk_gc_set_clip_rectangle( m_brushGC
, (GdkRectangle
*) NULL
);
327 gdk_gc_set_clip_rectangle( m_textGC
, (GdkRectangle
*) NULL
);
328 gdk_gc_set_clip_rectangle( m_bgGC
, (GdkRectangle
*) NULL
);
332 hatch_bitmap
= hatches
;
333 hatch_bitmap
[0] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, bdiag_bits
, bdiag_width
, bdiag_height
);
334 hatch_bitmap
[1] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, cdiag_bits
, cdiag_width
, cdiag_height
);
335 hatch_bitmap
[2] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, fdiag_bits
, fdiag_width
, fdiag_height
);
336 hatch_bitmap
[3] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, cross_bits
, cross_width
, cross_height
);
337 hatch_bitmap
[4] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, horiz_bits
, horiz_width
, horiz_height
);
338 hatch_bitmap
[5] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, verti_bits
, verti_width
, verti_height
);
342 void wxWindowDC::DoFloodFill( wxCoord
WXUNUSED(x
), wxCoord
WXUNUSED(y
),
343 const wxColour
&WXUNUSED(col
), int WXUNUSED(style
) )
345 wxFAIL_MSG( wxT("wxWindowDC::DoFloodFill not implemented") );
348 bool wxWindowDC::DoGetPixel( wxCoord x1
, wxCoord y1
, wxColour
*col
) const
350 // Generic (and therefore rather inefficient) method.
351 // Could be improved.
353 wxBitmap
bitmap(1, 1);
354 memdc
.SelectObject(bitmap
);
355 memdc
.Blit(0, 0, 1, 1, (wxDC
*) this, x1
, y1
);
356 memdc
.SelectObject(wxNullBitmap
);
357 wxImage
image(bitmap
);
358 col
->Set(image
.GetRed(0, 0), image
.GetGreen(0, 0), image
.GetBlue(0, 0));
362 void wxWindowDC::DoDrawLine( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
)
364 wxCHECK_RET( Ok(), wxT("invalid window dc") );
366 if (m_pen
.GetStyle() != wxTRANSPARENT
)
369 gdk_draw_line( m_window
, m_penGC
, XLOG2DEV(x1
), YLOG2DEV(y1
), XLOG2DEV(x2
), YLOG2DEV(y2
) );
371 CalcBoundingBox(x1
, y1
);
372 CalcBoundingBox(x2
, y2
);
376 void wxWindowDC::DoCrossHair( wxCoord x
, wxCoord y
)
378 wxCHECK_RET( Ok(), wxT("invalid window dc") );
380 if (m_pen
.GetStyle() != wxTRANSPARENT
)
385 wxCoord xx
= XLOG2DEV(x
);
386 wxCoord yy
= YLOG2DEV(y
);
389 gdk_draw_line( m_window
, m_penGC
, 0, yy
, XLOG2DEVREL(w
), yy
);
390 gdk_draw_line( m_window
, m_penGC
, xx
, 0, xx
, YLOG2DEVREL(h
) );
395 void wxWindowDC::DoDrawArc( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
,
396 wxCoord xc
, wxCoord yc
)
398 wxCHECK_RET( Ok(), wxT("invalid window dc") );
400 wxCoord xx1
= XLOG2DEV(x1
);
401 wxCoord yy1
= YLOG2DEV(y1
);
402 wxCoord xx2
= XLOG2DEV(x2
);
403 wxCoord yy2
= YLOG2DEV(y2
);
404 wxCoord xxc
= XLOG2DEV(xc
);
405 wxCoord yyc
= YLOG2DEV(yc
);
406 double dx
= xx1
- xxc
;
407 double dy
= yy1
- yyc
;
408 double radius
= sqrt((double)(dx
*dx
+dy
*dy
));
409 wxCoord r
= (wxCoord
)radius
;
410 double radius1
, radius2
;
412 if (xx1
== xx2
&& yy1
== yy2
)
420 radius1
= radius2
= 0.0;
424 radius1
= (xx1
- xxc
== 0) ?
425 (yy1
- yyc
< 0) ? 90.0 : -90.0 :
426 -atan2(double(yy1
-yyc
), double(xx1
-xxc
)) * RAD2DEG
;
427 radius2
= (xx2
- xxc
== 0) ?
428 (yy2
- yyc
< 0) ? 90.0 : -90.0 :
429 -atan2(double(yy2
-yyc
), double(xx2
-xxc
)) * RAD2DEG
;
431 wxCoord alpha1
= wxCoord(radius1
* 64.0);
432 wxCoord alpha2
= wxCoord((radius2
- radius1
) * 64.0);
433 while (alpha2
<= 0) alpha2
+= 360*64;
434 while (alpha1
> 360*64) alpha1
-= 360*64;
438 if (m_brush
.GetStyle() != wxTRANSPARENT
)
439 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
441 if (m_pen
.GetStyle() != wxTRANSPARENT
)
442 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
445 CalcBoundingBox (x1
, y1
);
446 CalcBoundingBox (x2
, y2
);
449 void wxWindowDC::DoDrawEllipticArc( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double sa
, double ea
)
451 wxCHECK_RET( Ok(), wxT("invalid window dc") );
453 wxCoord xx
= XLOG2DEV(x
);
454 wxCoord yy
= YLOG2DEV(y
);
455 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
456 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
458 // CMB: handle -ve width and/or height
459 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
460 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
464 wxCoord start
= wxCoord(sa
* 64.0);
465 wxCoord end
= wxCoord(ea
* 64.0);
467 if (m_brush
.GetStyle() != wxTRANSPARENT
)
468 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end
);
470 if (m_pen
.GetStyle() != wxTRANSPARENT
)
471 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
, hh
, start
, end
);
474 CalcBoundingBox (x
, y
);
475 CalcBoundingBox (x
+ width
, y
+ height
);
478 void wxWindowDC::DoDrawPoint( wxCoord x
, wxCoord y
)
480 wxCHECK_RET( Ok(), wxT("invalid window dc") );
482 if ((m_pen
.GetStyle() != wxTRANSPARENT
) && m_window
)
483 gdk_draw_point( m_window
, m_penGC
, XLOG2DEV(x
), YLOG2DEV(y
) );
485 CalcBoundingBox (x
, y
);
488 void wxWindowDC::DoDrawLines( int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
)
490 wxCHECK_RET( Ok(), wxT("invalid window dc") );
492 if (m_pen
.GetStyle() == wxTRANSPARENT
) return;
495 CalcBoundingBox( points
[0].x
+ xoffset
, points
[0].y
+ yoffset
);
497 for (int i
= 0; i
< n
-1; i
++)
499 wxCoord x1
= XLOG2DEV(points
[i
].x
+ xoffset
);
500 wxCoord x2
= XLOG2DEV(points
[i
+1].x
+ xoffset
);
501 wxCoord y1
= YLOG2DEV(points
[i
].y
+ yoffset
); // oh, what a waste
502 wxCoord y2
= YLOG2DEV(points
[i
+1].y
+ yoffset
);
505 gdk_draw_line( m_window
, m_penGC
, x1
, y1
, x2
, y2
);
507 CalcBoundingBox( points
[i
+1].x
+ xoffset
, points
[i
+1].y
+ yoffset
);
511 void wxWindowDC::DoDrawPolygon( int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
, int WXUNUSED(fillStyle
) )
513 wxCHECK_RET( Ok(), wxT("invalid window dc") );
517 GdkPoint
*gdkpoints
= new GdkPoint
[n
+1];
519 for (i
= 0 ; i
< n
; i
++)
521 gdkpoints
[i
].x
= XLOG2DEV(points
[i
].x
+ xoffset
);
522 gdkpoints
[i
].y
= YLOG2DEV(points
[i
].y
+ yoffset
);
524 CalcBoundingBox( points
[i
].x
+ xoffset
, points
[i
].y
+ yoffset
);
529 if (m_brush
.GetStyle() != wxTRANSPARENT
)
531 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
533 gdk_gc_set_ts_origin( m_textGC
,
534 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
535 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
536 gdk_draw_polygon( m_window
, m_textGC
, TRUE
, gdkpoints
, n
);
537 gdk_gc_set_ts_origin( m_textGC
, 0, 0 );
539 if (m_brush
.GetStyle() == wxSTIPPLE
)
541 gdk_gc_set_ts_origin( m_brushGC
,
542 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
543 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
544 gdk_draw_polygon( m_window
, m_brushGC
, TRUE
, gdkpoints
, n
);
545 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
549 gdk_draw_polygon( m_window
, m_brushGC
, TRUE
, gdkpoints
, n
);
553 if (m_pen
.GetStyle() != wxTRANSPARENT
)
555 for (i
= 0 ; i
< n
; i
++)
557 gdk_draw_line( m_window
, m_penGC
,
560 gdkpoints
[(i
+1)%n
].x
,
561 gdkpoints
[(i
+1)%n
].y
);
569 void wxWindowDC::DoDrawRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
571 wxCHECK_RET( Ok(), wxT("invalid window dc") );
573 wxCoord xx
= XLOG2DEV(x
);
574 wxCoord yy
= YLOG2DEV(y
);
575 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
576 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
578 // CMB: draw nothing if transformed w or h is 0
579 if (ww
== 0 || hh
== 0) return;
581 // CMB: handle -ve width and/or height
582 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
583 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
587 if (m_brush
.GetStyle() != wxTRANSPARENT
)
589 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
591 gdk_gc_set_ts_origin( m_textGC
,
592 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
593 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
594 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, xx
, yy
, ww
, hh
);
595 gdk_gc_set_ts_origin( m_textGC
, 0, 0 );
597 else if (m_brush
.GetStyle() == wxSTIPPLE
)
599 gdk_gc_set_ts_origin( m_brushGC
,
600 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
601 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
602 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
);
603 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
607 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
);
611 if (m_pen
.GetStyle() != wxTRANSPARENT
)
612 gdk_draw_rectangle( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
-1, hh
-1 );
615 CalcBoundingBox( x
, y
);
616 CalcBoundingBox( x
+ width
, y
+ height
);
619 void wxWindowDC::DoDrawRoundedRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double radius
)
621 wxCHECK_RET( Ok(), wxT("invalid window dc") );
623 if (radius
< 0.0) radius
= - radius
* ((width
< height
) ? width
: height
);
625 wxCoord xx
= XLOG2DEV(x
);
626 wxCoord yy
= YLOG2DEV(y
);
627 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
628 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
629 wxCoord rr
= XLOG2DEVREL((wxCoord
)radius
);
631 // CMB: handle -ve width and/or height
632 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
633 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
635 // CMB: if radius is zero use DrawRectangle() instead to avoid
636 // X drawing errors with small radii
639 DrawRectangle( x
, y
, width
, height
);
643 // CMB: draw nothing if transformed w or h is 0
644 if (ww
== 0 || hh
== 0) return;
646 // CMB: adjust size if outline is drawn otherwise the result is
647 // 1 pixel too wide and high
648 if (m_pen
.GetStyle() != wxTRANSPARENT
)
656 // CMB: ensure dd is not larger than rectangle otherwise we
657 // get an hour glass shape
659 if (dd
> ww
) dd
= ww
;
660 if (dd
> hh
) dd
= hh
;
663 if (m_brush
.GetStyle() != wxTRANSPARENT
)
665 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
667 gdk_gc_set_ts_origin( m_textGC
,
668 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
669 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
670 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh
);
671 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 );
672 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
673 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
674 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
675 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
676 gdk_gc_set_ts_origin( m_textGC
, 0, 0 );
678 else if (m_brush
.GetStyle() == wxSTIPPLE
)
680 gdk_gc_set_ts_origin( m_brushGC
,
681 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
682 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
683 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh
);
684 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 );
685 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
686 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
687 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
688 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
689 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
693 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh
);
694 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 );
695 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
696 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
697 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
698 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
702 if (m_pen
.GetStyle() != wxTRANSPARENT
)
704 gdk_draw_line( m_window
, m_penGC
, xx
+rr
, yy
, xx
+ww
-rr
, yy
);
705 gdk_draw_line( m_window
, m_penGC
, xx
+rr
, yy
+hh
, xx
+ww
-rr
, yy
+hh
);
706 gdk_draw_line( m_window
, m_penGC
, xx
, yy
+rr
, xx
, yy
+hh
-rr
);
707 gdk_draw_line( m_window
, m_penGC
, xx
+ww
, yy
+rr
, xx
+ww
, yy
+hh
-rr
);
708 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
709 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
710 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
711 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
715 // this ignores the radius
716 CalcBoundingBox( x
, y
);
717 CalcBoundingBox( x
+ width
, y
+ height
);
720 void wxWindowDC::DoDrawEllipse( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
722 wxCHECK_RET( Ok(), wxT("invalid window dc") );
724 wxCoord xx
= XLOG2DEV(x
);
725 wxCoord yy
= YLOG2DEV(y
);
726 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
727 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
729 // CMB: handle -ve width and/or height
730 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
731 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
735 if (m_brush
.GetStyle() != wxTRANSPARENT
)
737 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
739 gdk_gc_set_ts_origin( m_textGC
,
740 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
741 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
742 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 );
743 gdk_gc_set_ts_origin( m_textGC
, 0, 0 );
745 else if (m_brush
.GetStyle() == wxSTIPPLE
)
747 gdk_gc_set_ts_origin( m_brushGC
,
748 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
749 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
750 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 );
751 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
755 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 );
759 if (m_pen
.GetStyle() != wxTRANSPARENT
)
760 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
, hh
, 0, 360*64 );
763 CalcBoundingBox( x
- width
, y
- height
);
764 CalcBoundingBox( x
+ width
, y
+ height
);
767 void wxWindowDC::DoDrawIcon( const wxIcon
&icon
, wxCoord x
, wxCoord y
)
769 // VZ: egcs 1.0.3 refuses to compile this without cast, no idea why
770 DoDrawBitmap( (const wxBitmap
&)icon
, x
, y
, (bool)TRUE
);
773 void wxWindowDC::DoDrawBitmap( const wxBitmap
&bitmap
,
774 wxCoord x
, wxCoord y
,
777 wxCHECK_RET( Ok(), wxT("invalid window dc") );
779 wxCHECK_RET( bitmap
.Ok(), wxT("invalid bitmap") );
781 bool is_mono
= (bitmap
.GetBitmap() != NULL
);
783 /* scale/translate size and position */
784 int xx
= XLOG2DEV(x
);
785 int yy
= YLOG2DEV(y
);
787 int w
= bitmap
.GetWidth();
788 int h
= bitmap
.GetHeight();
790 CalcBoundingBox( x
, y
);
791 CalcBoundingBox( x
+ w
, y
+ h
);
793 if (!m_window
) return;
795 int ww
= XLOG2DEVREL(w
);
796 int hh
= YLOG2DEVREL(h
);
798 /* compare to current clipping region */
799 if (!m_currentClippingRegion
.IsNull())
801 wxRegion
tmp( xx
,yy
,ww
,hh
);
802 tmp
.Intersect( m_currentClippingRegion
);
807 /* scale bitmap if required */
809 if ((w
!= ww
) || (h
!= hh
))
811 wxImage
image( bitmap
);
812 image
.Rescale( ww
, hh
);
814 use_bitmap
= image
.ConvertToMonoBitmap(255,255,255);
816 use_bitmap
= image
.ConvertToBitmap();
823 /* apply mask if any */
824 GdkBitmap
*mask
= (GdkBitmap
*) NULL
;
825 if (use_bitmap
.GetMask()) mask
= use_bitmap
.GetMask()->GetBitmap();
829 GdkBitmap
*new_mask
= (GdkBitmap
*) NULL
;
830 if (!m_currentClippingRegion
.IsNull())
833 new_mask
= gdk_pixmap_new( wxRootWindow
->window
, ww
, hh
, 1 );
834 GdkGC
*gc
= gdk_gc_new( new_mask
);
836 gdk_gc_set_foreground( gc
, &col
);
837 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, ww
, hh
);
839 gdk_gc_set_background( gc
, &col
);
841 gdk_gc_set_foreground( gc
, &col
);
842 gdk_gc_set_clip_region( gc
, m_currentClippingRegion
.GetRegion() );
843 gdk_gc_set_clip_origin( gc
, -xx
, -yy
);
844 gdk_gc_set_fill( gc
, GDK_OPAQUE_STIPPLED
);
845 gdk_gc_set_stipple( gc
, mask
);
846 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, ww
, hh
);
853 gdk_gc_set_clip_mask( m_textGC
, new_mask
);
855 gdk_gc_set_clip_mask( m_textGC
, mask
);
856 gdk_gc_set_clip_origin( m_textGC
, xx
, yy
);
861 gdk_gc_set_clip_mask( m_penGC
, new_mask
);
863 gdk_gc_set_clip_mask( m_penGC
, mask
);
864 gdk_gc_set_clip_origin( m_penGC
, xx
, yy
);
867 gdk_bitmap_unref( new_mask
);
870 /* Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For
871 drawing a mono-bitmap (XBitmap) we use the current text GC */
873 gdk_draw_bitmap( m_window
, m_textGC
, use_bitmap
.GetBitmap(), 0, 0, xx
, yy
, -1, -1 );
875 gdk_draw_pixmap( m_window
, m_penGC
, use_bitmap
.GetPixmap(), 0, 0, xx
, yy
, -1, -1 );
877 /* remove mask again if any */
882 gdk_gc_set_clip_mask( m_textGC
, (GdkBitmap
*) NULL
);
883 gdk_gc_set_clip_origin( m_textGC
, 0, 0 );
884 if (!m_currentClippingRegion
.IsNull())
885 gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() );
889 gdk_gc_set_clip_mask( m_penGC
, (GdkBitmap
*) NULL
);
890 gdk_gc_set_clip_origin( m_penGC
, 0, 0 );
891 if (!m_currentClippingRegion
.IsNull())
892 gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() );
897 bool wxWindowDC::DoBlit( wxCoord xdest
, wxCoord ydest
, wxCoord width
, wxCoord height
,
898 wxDC
*source
, wxCoord xsrc
, wxCoord ysrc
,
899 int logical_func
, bool useMask
)
901 /* this is the nth try to get this utterly useless function to
902 work. it now completely ignores the scaling or translation
903 of the source dc, but scales correctly on the target dc and
904 knows about possible mask information in a memory dc. */
906 wxCHECK_MSG( Ok(), FALSE
, wxT("invalid window dc") );
908 wxCHECK_MSG( source
, FALSE
, wxT("invalid source dc") );
910 if (!m_window
) return FALSE
;
912 wxClientDC
*srcDC
= (wxClientDC
*)source
;
913 wxMemoryDC
*memDC
= (wxMemoryDC
*)source
;
915 bool use_bitmap_method
= FALSE
;
916 bool is_mono
= FALSE
;
918 if (srcDC
->m_isMemDC
)
920 if (!memDC
->m_selected
.Ok()) return FALSE
;
922 /* we use the "XCopyArea" way to copy a memory dc into
923 y different window if the memory dc BOTH
924 a) doesn't have any mask or its mask isn't used
928 if (useMask
&& (memDC
->m_selected
.GetMask()))
930 /* we HAVE TO use the direct way for memory dcs
931 that have mask since the XCopyArea doesn't know
933 use_bitmap_method
= TRUE
;
935 else if (memDC
->m_selected
.GetDepth() == 1)
937 /* we HAVE TO use the direct way for memory dcs
938 that are bitmaps because XCopyArea doesn't cope
939 with different bit depths */
941 use_bitmap_method
= TRUE
;
943 else if ((xsrc
== 0) && (ysrc
== 0) &&
944 (width
== memDC
->m_selected
.GetWidth()) &&
945 (height
== memDC
->m_selected
.GetHeight()))
947 /* we SHOULD use the direct way if all of the bitmap
948 in the memory dc is copied in which case XCopyArea
949 wouldn't be able able to boost performace by reducing
950 the area to be scaled */
951 use_bitmap_method
= TRUE
;
955 use_bitmap_method
= FALSE
;
959 CalcBoundingBox( xdest
, ydest
);
960 CalcBoundingBox( xdest
+ width
, ydest
+ height
);
962 /* scale/translate size and position */
963 wxCoord xx
= XLOG2DEV(xdest
);
964 wxCoord yy
= YLOG2DEV(ydest
);
966 wxCoord ww
= XLOG2DEVREL(width
);
967 wxCoord hh
= YLOG2DEVREL(height
);
969 /* compare to current clipping region */
970 if (!m_currentClippingRegion
.IsNull())
972 wxRegion
tmp( xx
,yy
,ww
,hh
);
973 tmp
.Intersect( m_currentClippingRegion
);
978 int old_logical_func
= m_logicalFunction
;
979 SetLogicalFunction( logical_func
);
981 if (use_bitmap_method
)
983 /* scale/translate bitmap size */
984 wxCoord bm_width
= memDC
->m_selected
.GetWidth();
985 wxCoord bm_height
= memDC
->m_selected
.GetHeight();
987 wxCoord bm_ww
= XLOG2DEVREL( bm_width
);
988 wxCoord bm_hh
= YLOG2DEVREL( bm_height
);
990 /* scale bitmap if required */
993 if ((bm_width
!= bm_ww
) || (bm_height
!= bm_hh
))
995 wxImage
image( memDC
->m_selected
);
996 image
= image
.Scale( bm_ww
, bm_hh
);
999 use_bitmap
= image
.ConvertToMonoBitmap(255,255,255);
1001 use_bitmap
= image
.ConvertToBitmap();
1005 use_bitmap
= memDC
->m_selected
;
1008 /* apply mask if any */
1009 GdkBitmap
*mask
= (GdkBitmap
*) NULL
;
1010 if (use_bitmap
.GetMask()) mask
= use_bitmap
.GetMask()->GetBitmap();
1012 if (useMask
&& mask
)
1014 GdkBitmap
*new_mask
= (GdkBitmap
*) NULL
;
1015 if (!m_currentClippingRegion
.IsNull())
1018 new_mask
= gdk_pixmap_new( wxRootWindow
->window
, bm_ww
, bm_hh
, 1 );
1019 GdkGC
*gc
= gdk_gc_new( new_mask
);
1021 gdk_gc_set_foreground( gc
, &col
);
1022 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, bm_ww
, bm_hh
);
1024 gdk_gc_set_background( gc
, &col
);
1026 gdk_gc_set_foreground( gc
, &col
);
1027 gdk_gc_set_clip_region( gc
, m_currentClippingRegion
.GetRegion() );
1028 gdk_gc_set_clip_origin( gc
, -xx
, -yy
);
1029 gdk_gc_set_fill( gc
, GDK_OPAQUE_STIPPLED
);
1030 gdk_gc_set_stipple( gc
, mask
);
1031 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, bm_ww
, bm_hh
);
1038 gdk_gc_set_clip_mask( m_textGC
, new_mask
);
1040 gdk_gc_set_clip_mask( m_textGC
, mask
);
1041 gdk_gc_set_clip_origin( m_textGC
, xx
, yy
);
1046 gdk_gc_set_clip_mask( m_penGC
, new_mask
);
1048 gdk_gc_set_clip_mask( m_penGC
, mask
);
1049 gdk_gc_set_clip_origin( m_penGC
, xx
, yy
);
1052 gdk_bitmap_unref( new_mask
);
1055 /* Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For
1056 drawing a mono-bitmap (XBitmap) we use the current text GC */
1059 gdk_draw_bitmap( m_window
, m_textGC
, use_bitmap
.GetBitmap(), xsrc
, ysrc
, xx
, yy
, ww
, hh
);
1061 gdk_draw_pixmap( m_window
, m_penGC
, use_bitmap
.GetPixmap(), xsrc
, ysrc
, xx
, yy
, ww
, hh
);
1063 /* remove mask again if any */
1064 if (useMask
&& mask
)
1068 gdk_gc_set_clip_mask( m_textGC
, (GdkBitmap
*) NULL
);
1069 gdk_gc_set_clip_origin( m_textGC
, 0, 0 );
1070 if (!m_currentClippingRegion
.IsNull())
1071 gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() );
1075 gdk_gc_set_clip_mask( m_penGC
, (GdkBitmap
*) NULL
);
1076 gdk_gc_set_clip_origin( m_penGC
, 0, 0 );
1077 if (!m_currentClippingRegion
.IsNull())
1078 gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() );
1082 else /* use_bitmap_method */
1084 if ((width
!= ww
) || (height
!= hh
))
1086 /* draw source window into a bitmap as we cannot scale
1087 a window in contrast to a bitmap. this would actually
1088 work with memory dcs as well, but we'd lose the mask
1089 information and waste one step in this process since
1090 a memory already has a bitmap. all this is slightly
1091 inefficient as we could take an XImage directly from
1092 an X window, but we'd then also have to care that
1093 the window is not outside the screen (in which case
1094 we'd get a BadMatch or what not).
1095 Is a double XGetImage and combined XGetPixel and
1096 XPutPixel really faster? I'm not sure. look at wxXt
1097 for a different implementation of the same problem. */
1099 wxBitmap
bitmap( width
, height
);
1101 /* copy including child window contents */
1102 gdk_gc_set_subwindow( m_penGC
, GDK_INCLUDE_INFERIORS
);
1103 gdk_window_copy_area( bitmap
.GetPixmap(), m_penGC
, 0, 0,
1105 xsrc
, ysrc
, width
, height
);
1106 gdk_gc_set_subwindow( m_penGC
, GDK_CLIP_BY_CHILDREN
);
1109 wxImage
image( bitmap
);
1110 image
= image
.Scale( ww
, hh
);
1112 /* convert to bitmap */
1113 bitmap
= image
.ConvertToBitmap();
1115 /* draw scaled bitmap */
1116 gdk_draw_pixmap( m_window
, m_penGC
, bitmap
.GetPixmap(), 0, 0, xx
, yy
, -1, -1 );
1121 /* No scaling and not a memory dc with a mask either */
1123 /* copy including child window contents */
1124 gdk_gc_set_subwindow( m_penGC
, GDK_INCLUDE_INFERIORS
);
1125 gdk_window_copy_area( m_window
, m_penGC
, xx
, yy
,
1127 xsrc
, ysrc
, width
, height
);
1128 gdk_gc_set_subwindow( m_penGC
, GDK_CLIP_BY_CHILDREN
);
1132 SetLogicalFunction( old_logical_func
);
1136 void wxWindowDC::DoDrawText( const wxString
&text
, wxCoord x
, wxCoord y
)
1138 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1140 if (!m_window
) return;
1142 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
1144 wxCHECK_RET( font
, wxT("invalid font") );
1149 /* CMB 21/5/98: draw text background if mode is wxSOLID */
1150 if (m_backgroundMode
== wxSOLID
)
1152 wxCoord width
= gdk_string_width( font
, text
.mbc_str() );
1153 wxCoord height
= font
->ascent
+ font
->descent
;
1154 gdk_gc_set_foreground( m_textGC
, m_textBackgroundColour
.GetColor() );
1155 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, x
, y
, width
, height
);
1156 gdk_gc_set_foreground( m_textGC
, m_textForegroundColour
.GetColor() );
1158 gdk_draw_string( m_window
, font
, m_textGC
, x
, y
+ font
->ascent
, text
.mbc_str() );
1160 /* CMB 17/7/98: simple underline: ignores scaling and underlying
1161 X font's XA_UNDERLINE_POSITION and XA_UNDERLINE_THICKNESS
1162 properties (see wxXt implementation) */
1163 if (m_font
.GetUnderlined())
1165 wxCoord width
= gdk_string_width( font
, text
.mbc_str() );
1166 wxCoord ul_y
= y
+ font
->ascent
;
1167 if (font
->descent
> 0) ul_y
++;
1168 gdk_draw_line( m_window
, m_textGC
, x
, ul_y
, x
+ width
, ul_y
);
1172 GetTextExtent (text
, &w
, &h
);
1173 CalcBoundingBox (x
+ w
, y
+ h
);
1174 CalcBoundingBox (x
, y
);
1177 void wxWindowDC::DoDrawRotatedText( const wxString
&text
, wxCoord x
, wxCoord y
, double angle
)
1181 DrawText(text
, x
, y
);
1185 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1187 if (!m_window
) return;
1189 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
1191 wxCHECK_RET( font
, wxT("invalid font") );
1193 // the size of the text
1194 wxCoord w
= gdk_string_width( font
, text
.mbc_str() );
1195 wxCoord h
= font
->ascent
+ font
->descent
;
1197 // draw the string normally
1200 dc
.SelectObject(src
);
1201 dc
.SetFont(GetFont());
1202 dc
.SetBackground(*wxWHITE_BRUSH
);
1203 dc
.SetBrush(*wxBLACK_BRUSH
);
1205 dc
.DrawText(text
, 0, 0);
1206 dc
.SetFont(wxNullFont
);
1207 dc
.SelectObject(wxNullBitmap
);
1209 // Calculate the size of the rotated bounding box.
1210 double rad
= DegToRad(angle
);
1211 double dx
= cos(rad
),
1214 // the rectngle vertices are counted clockwise with the first one being at
1215 // (0, 0) (or, rather, at (x, y))
1217 y2
= -w
*dy
; // y axis points to the bottom, hence minus
1220 double x3
= x4
+ x2
,
1224 wxCoord maxX
= (wxCoord
)(dmax(x2
, dmax(x3
, x4
)) + 0.5),
1225 maxY
= (wxCoord
)(dmax(y2
, dmax(y3
, y4
)) + 0.5),
1226 minX
= (wxCoord
)(dmin(x2
, dmin(x3
, x4
)) - 0.5),
1227 minY
= (wxCoord
)(dmin(y2
, dmin(y3
, y4
)) - 0.5);
1229 // prepare to blit-with-rotate the bitmap to the DC
1232 GdkColor
*colText
= m_textForegroundColour
.GetColor(),
1233 *colBack
= m_textBackgroundColour
.GetColor();
1235 bool textColSet
= TRUE
;
1237 unsigned char *data
= image
.GetData();
1239 // paint pixel by pixel
1240 for ( wxCoord srcX
= 0; srcX
< w
; srcX
++ )
1242 for ( wxCoord srcY
= 0; srcY
< h
; srcY
++ )
1244 // transform source coords to dest coords
1245 double r
= sqrt(srcX
*srcX
+ srcY
*srcY
);
1246 double angleOrig
= atan2(srcY
, srcX
) - rad
;
1247 wxCoord dstX
= (wxCoord
)(r
*cos(angleOrig
) + 0.5),
1248 dstY
= (wxCoord
)(r
*sin(angleOrig
) + 0.5);
1251 bool textPixel
= data
[(srcY
*w
+ srcX
)*3] == 0;
1252 if ( textPixel
|| (m_backgroundMode
== wxSOLID
) )
1254 // change colour if needed
1255 if ( textPixel
!= textColSet
)
1257 gdk_gc_set_foreground( m_textGC
, textPixel
? colText
1260 textColSet
= textPixel
;
1263 // don't use DrawPoint() because it uses the current pen
1264 // colour, and we don't need it here
1265 gdk_draw_point( m_window
, m_textGC
,
1266 XLOG2DEV(x
+ dstX
), YLOG2DEV(y
+ dstY
) );
1271 // it would be better to draw with non underlined font and draw the line
1272 // manually here (it would be more straight...)
1274 if ( m_font
.GetUnderlined() )
1276 gdk_draw_line( m_window
, m_textGC
,
1277 XLOG2DEV(x
+ x4
), YLOG2DEV(y
+ y4
+ font
->descent
),
1278 XLOG2DEV(x
+ x3
), YLOG2DEV(y
+ y3
+ font
->descent
));
1282 // restore the font colour
1283 gdk_gc_set_foreground( m_textGC
, colText
);
1285 // update the bounding box
1286 CalcBoundingBox(x
+ minX
, y
+ minY
);
1287 CalcBoundingBox(x
+ maxX
, y
+ maxY
);
1290 void wxWindowDC::DoGetTextExtent(const wxString
&string
,
1291 wxCoord
*width
, wxCoord
*height
,
1292 wxCoord
*descent
, wxCoord
*externalLeading
,
1293 wxFont
*theFont
) const
1295 wxFont fontToUse
= m_font
;
1296 if (theFont
) fontToUse
= *theFont
;
1298 GdkFont
*font
= fontToUse
.GetInternalFont( m_scaleY
);
1299 if (width
) (*width
) = wxCoord(gdk_string_width( font
, string
.mbc_str() ) / m_scaleX
);
1300 if (height
) (*height
) = wxCoord((font
->ascent
+ font
->descent
) / m_scaleY
);
1301 if (descent
) (*descent
) = wxCoord(font
->descent
/ m_scaleY
);
1302 if (externalLeading
) (*externalLeading
) = 0; // ??
1305 wxCoord
wxWindowDC::GetCharWidth() const
1307 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
1308 wxCHECK_MSG( font
, -1, wxT("invalid font") );
1310 return wxCoord(gdk_string_width( font
, "H" ) / m_scaleX
);
1313 wxCoord
wxWindowDC::GetCharHeight() const
1315 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
1316 wxCHECK_MSG( font
, -1, wxT("invalid font") );
1318 return wxCoord((font
->ascent
+ font
->descent
) / m_scaleY
);
1321 void wxWindowDC::Clear()
1323 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1325 if (!m_window
) return;
1327 /* - we either are a memory dc or have a window as the
1328 owner. anything else shouldn't happen.
1329 - we don't use gdk_window_clear() as we don't set
1330 the window's background colour anymore. it is too
1331 much pain to keep the DC's and the window's back-
1332 ground colour in synch. */
1337 m_owner
->GetSize( &width
, &height
);
1338 gdk_draw_rectangle( m_window
, m_bgGC
, TRUE
, 0, 0, width
, height
);
1345 GetSize( &width
, &height
);
1346 gdk_draw_rectangle( m_window
, m_bgGC
, TRUE
, 0, 0, width
, height
);
1351 void wxWindowDC::SetFont( const wxFont
&font
)
1356 void wxWindowDC::SetPen( const wxPen
&pen
)
1358 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1360 if (m_pen
== pen
) return;
1364 if (!m_pen
.Ok()) return;
1366 if (!m_window
) return;
1368 gint width
= m_pen
.GetWidth();
1371 // CMB: if width is non-zero scale it with the dc
1376 // X doesn't allow different width in x and y and so we take
1379 ( fabs((double) XLOG2DEVREL(width
)) +
1380 fabs((double) YLOG2DEVREL(width
)) ) / 2.0;
1384 static const char dotted
[] = {1, 1};
1385 static const char short_dashed
[] = {2, 2};
1386 static const char wxCoord_dashed
[] = {2, 4};
1387 static const char dotted_dashed
[] = {3, 3, 1, 3};
1389 // We express dash pattern in pen width unit, so we are
1390 // independent of zoom factor and so on...
1392 const char *req_dash
;
1394 GdkLineStyle lineStyle
= GDK_LINE_SOLID
;
1395 switch (m_pen
.GetStyle())
1399 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1400 req_nb_dash
= m_pen
.GetDashCount();
1401 req_dash
= m_pen
.GetDash();
1406 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1413 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1415 req_dash
= wxCoord_dashed
;
1420 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1422 req_dash
= short_dashed
;
1427 // lineStyle = GDK_LINE_DOUBLE_DASH;
1428 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1430 req_dash
= dotted_dashed
;
1435 case wxSTIPPLE_MASK_OPAQUE
:
1440 lineStyle
= GDK_LINE_SOLID
;
1441 req_dash
= (wxDash
*)NULL
;
1447 #if (GTK_MINOR_VERSION > 0)
1448 if (req_dash
&& req_nb_dash
)
1450 char *real_req_dash
= new char[req_nb_dash
];
1453 for (int i
= 0; i
< req_nb_dash
; i
++)
1454 real_req_dash
[i
] = req_dash
[i
] * width
;
1455 #if GTK_CHECK_VERSION(1,2,7)
1456 gdk_gc_set_dashes( m_penGC
, 0, (gint8
*) real_req_dash
,
1459 gdk_gc_set_dashes( m_penGC
, 0, real_req_dash
,
1462 delete[] real_req_dash
;
1466 // No Memory. We use non-scaled dash pattern...
1467 #if GTK_CHECK_VERSION(1,2,7)
1468 gdk_gc_set_dashes( m_penGC
, 0, (gint8
*)req_dash
, req_nb_dash
);
1470 gdk_gc_set_dashes( m_penGC
, 0, (char*)req_dash
, req_nb_dash
);
1476 GdkCapStyle capStyle
= GDK_CAP_ROUND
;
1477 switch (m_pen
.GetCap())
1479 case wxCAP_PROJECTING
: { capStyle
= GDK_CAP_PROJECTING
; break; }
1480 case wxCAP_BUTT
: { capStyle
= GDK_CAP_BUTT
; break; }
1487 capStyle
= GDK_CAP_NOT_LAST
;
1491 capStyle
= GDK_CAP_ROUND
;
1497 GdkJoinStyle joinStyle
= GDK_JOIN_ROUND
;
1498 switch (m_pen
.GetJoin())
1500 case wxJOIN_BEVEL
: { joinStyle
= GDK_JOIN_BEVEL
; break; }
1501 case wxJOIN_MITER
: { joinStyle
= GDK_JOIN_MITER
; break; }
1503 default: { joinStyle
= GDK_JOIN_ROUND
; break; }
1506 gdk_gc_set_line_attributes( m_penGC
, width
, lineStyle
, capStyle
, joinStyle
);
1508 m_pen
.GetColour().CalcPixel( m_cmap
);
1509 gdk_gc_set_foreground( m_penGC
, m_pen
.GetColour().GetColor() );
1512 void wxWindowDC::SetBrush( const wxBrush
&brush
)
1514 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1516 if (m_brush
== brush
) return;
1520 if (!m_brush
.Ok()) return;
1522 if (!m_window
) return;
1524 m_brush
.GetColour().CalcPixel( m_cmap
);
1525 gdk_gc_set_foreground( m_brushGC
, m_brush
.GetColour().GetColor() );
1527 gdk_gc_set_fill( m_brushGC
, GDK_SOLID
);
1529 if ((m_brush
.GetStyle() == wxSTIPPLE
) && (m_brush
.GetStipple()->Ok()))
1531 if (m_brush
.GetStipple()->GetPixmap())
1533 gdk_gc_set_fill( m_brushGC
, GDK_TILED
);
1534 gdk_gc_set_tile( m_brushGC
, m_brush
.GetStipple()->GetPixmap() );
1538 gdk_gc_set_fill( m_brushGC
, GDK_STIPPLED
);
1539 gdk_gc_set_stipple( m_brushGC
, m_brush
.GetStipple()->GetBitmap() );
1543 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
1545 gdk_gc_set_fill( m_textGC
, GDK_OPAQUE_STIPPLED
);
1546 gdk_gc_set_stipple( m_textGC
, m_brush
.GetStipple()->GetMask()->GetBitmap() );
1549 if (IS_HATCH(m_brush
.GetStyle()))
1551 gdk_gc_set_fill( m_brushGC
, GDK_STIPPLED
);
1552 int num
= m_brush
.GetStyle() - wxBDIAGONAL_HATCH
;
1553 gdk_gc_set_stipple( m_brushGC
, hatches
[num
] );
1557 void wxWindowDC::SetBackground( const wxBrush
&brush
)
1559 /* CMB 21/7/98: Added SetBackground. Sets background brush
1560 * for Clear() and bg colour for shapes filled with cross-hatch brush */
1562 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1564 if (m_backgroundBrush
== brush
) return;
1566 m_backgroundBrush
= brush
;
1568 if (!m_backgroundBrush
.Ok()) return;
1570 if (!m_window
) return;
1572 m_backgroundBrush
.GetColour().CalcPixel( m_cmap
);
1573 gdk_gc_set_background( m_brushGC
, m_backgroundBrush
.GetColour().GetColor() );
1574 gdk_gc_set_background( m_penGC
, m_backgroundBrush
.GetColour().GetColor() );
1575 gdk_gc_set_background( m_bgGC
, m_backgroundBrush
.GetColour().GetColor() );
1576 gdk_gc_set_foreground( m_bgGC
, m_backgroundBrush
.GetColour().GetColor() );
1578 gdk_gc_set_fill( m_bgGC
, GDK_SOLID
);
1580 if ((m_backgroundBrush
.GetStyle() == wxSTIPPLE
) && (m_backgroundBrush
.GetStipple()->Ok()))
1582 if (m_backgroundBrush
.GetStipple()->GetPixmap())
1584 gdk_gc_set_fill( m_bgGC
, GDK_TILED
);
1585 gdk_gc_set_tile( m_bgGC
, m_backgroundBrush
.GetStipple()->GetPixmap() );
1589 gdk_gc_set_fill( m_bgGC
, GDK_STIPPLED
);
1590 gdk_gc_set_stipple( m_bgGC
, m_backgroundBrush
.GetStipple()->GetBitmap() );
1594 if (IS_HATCH(m_backgroundBrush
.GetStyle()))
1596 gdk_gc_set_fill( m_bgGC
, GDK_STIPPLED
);
1597 int num
= m_backgroundBrush
.GetStyle() - wxBDIAGONAL_HATCH
;
1598 gdk_gc_set_stipple( m_bgGC
, hatches
[num
] );
1602 void wxWindowDC::SetLogicalFunction( int function
)
1604 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1606 if (m_logicalFunction
== function
)
1609 // VZ: shouldn't this be a CHECK?
1613 GdkFunction mode
= GDK_COPY
;
1616 case wxXOR
: mode
= GDK_XOR
; break;
1617 case wxINVERT
: mode
= GDK_INVERT
; break;
1618 #if (GTK_MINOR_VERSION > 0)
1619 case wxOR_REVERSE
: mode
= GDK_OR_REVERSE
; break;
1620 case wxAND_REVERSE
: mode
= GDK_AND_REVERSE
; break;
1621 case wxCLEAR
: mode
= GDK_CLEAR
; break;
1622 case wxSET
: mode
= GDK_SET
; break;
1623 case wxOR_INVERT
: mode
= GDK_OR_INVERT
; break;
1624 case wxAND
: mode
= GDK_AND
; break;
1625 case wxOR
: mode
= GDK_OR
; break;
1626 case wxEQUIV
: mode
= GDK_EQUIV
; break;
1627 case wxNAND
: mode
= GDK_NAND
; break;
1628 case wxAND_INVERT
: mode
= GDK_AND_INVERT
; break;
1629 case wxCOPY
: mode
= GDK_COPY
; break;
1630 case wxNO_OP
: mode
= GDK_NOOP
; break;
1631 case wxSRC_INVERT
: mode
= GDK_COPY_INVERT
; break;
1633 // unsupported by GTK
1634 case wxNOR
: mode
= GDK_COPY
; break;
1638 wxFAIL_MSG( wxT("unsupported logical function") );
1643 m_logicalFunction
= function
;
1645 gdk_gc_set_function( m_penGC
, mode
);
1646 gdk_gc_set_function( m_brushGC
, mode
);
1648 // to stay compatible with wxMSW, we don't apply ROPs to the text
1649 // operations (i.e. DrawText/DrawRotatedText).
1650 // True, but mono-bitmaps use the m_textGC and they use ROPs as well.
1651 gdk_gc_set_function( m_textGC
, mode
);
1654 void wxWindowDC::SetTextForeground( const wxColour
&col
)
1656 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1658 if (m_textForegroundColour
== col
) return;
1660 m_textForegroundColour
= col
;
1661 if (!m_textForegroundColour
.Ok()) return;
1663 if (!m_window
) return;
1665 m_textForegroundColour
.CalcPixel( m_cmap
);
1666 gdk_gc_set_foreground( m_textGC
, m_textForegroundColour
.GetColor() );
1669 void wxWindowDC::SetTextBackground( const wxColour
&col
)
1671 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1673 if (m_textBackgroundColour
== col
) return;
1675 m_textBackgroundColour
= col
;
1676 if (!m_textBackgroundColour
.Ok()) return;
1678 if (!m_window
) return;
1680 m_textBackgroundColour
.CalcPixel( m_cmap
);
1681 gdk_gc_set_background( m_textGC
, m_textBackgroundColour
.GetColor() );
1684 void wxWindowDC::SetBackgroundMode( int mode
)
1686 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1688 m_backgroundMode
= mode
;
1690 if (!m_window
) return;
1692 // CMB 21/7/98: fill style of cross-hatch brushes is affected by
1693 // transparent/solid background mode
1695 if (m_brush
.GetStyle() != wxSOLID
&& m_brush
.GetStyle() != wxTRANSPARENT
)
1697 gdk_gc_set_fill( m_brushGC
,
1698 (m_backgroundMode
== wxTRANSPARENT
) ? GDK_STIPPLED
: GDK_OPAQUE_STIPPLED
);
1702 void wxWindowDC::SetPalette( const wxPalette
& WXUNUSED(palette
) )
1704 wxFAIL_MSG( wxT("wxWindowDC::SetPalette not implemented") );
1707 void wxWindowDC::DoSetClippingRegion( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
1709 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1711 if (!m_window
) return;
1714 rect
.x
= XLOG2DEV(x
);
1715 rect
.y
= YLOG2DEV(y
);
1716 rect
.width
= XLOG2DEVREL(width
);
1717 rect
.height
= YLOG2DEVREL(height
);
1719 if (!m_currentClippingRegion
.IsNull())
1720 m_currentClippingRegion
.Intersect( rect
);
1722 m_currentClippingRegion
.Union( rect
);
1724 #if USE_PAINT_REGION
1725 if (!m_paintClippingRegion
.IsNull())
1726 m_currentClippingRegion
.Intersect( m_paintClippingRegion
);
1729 wxCoord xx
, yy
, ww
, hh
;
1730 m_currentClippingRegion
.GetBox( xx
, yy
, ww
, hh
);
1731 wxDC::DoSetClippingRegion( xx
, yy
, ww
, hh
);
1733 gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() );
1734 gdk_gc_set_clip_region( m_brushGC
, m_currentClippingRegion
.GetRegion() );
1735 gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() );
1736 gdk_gc_set_clip_region( m_bgGC
, m_currentClippingRegion
.GetRegion() );
1739 void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion
®ion
)
1741 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1745 DestroyClippingRegion();
1749 if (!m_window
) return;
1751 if (!m_currentClippingRegion
.IsNull())
1752 m_currentClippingRegion
.Intersect( region
);
1754 m_currentClippingRegion
.Union( region
);
1756 #if USE_PAINT_REGION
1757 if (!m_paintClippingRegion
.IsNull())
1758 m_currentClippingRegion
.Intersect( m_paintClippingRegion
);
1761 wxCoord xx
, yy
, ww
, hh
;
1762 m_currentClippingRegion
.GetBox( xx
, yy
, ww
, hh
);
1763 wxDC::DoSetClippingRegion( xx
, yy
, ww
, hh
);
1765 gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() );
1766 gdk_gc_set_clip_region( m_brushGC
, m_currentClippingRegion
.GetRegion() );
1767 gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() );
1768 gdk_gc_set_clip_region( m_bgGC
, m_currentClippingRegion
.GetRegion() );
1771 void wxWindowDC::DestroyClippingRegion()
1773 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1775 wxDC::DestroyClippingRegion();
1777 m_currentClippingRegion
.Clear();
1779 #if USE_PAINT_REGION
1780 if (!m_paintClippingRegion
.IsEmpty())
1781 m_currentClippingRegion
.Union( m_paintClippingRegion
);
1784 if (!m_window
) return;
1786 if (m_currentClippingRegion
.IsEmpty())
1788 gdk_gc_set_clip_rectangle( m_penGC
, (GdkRectangle
*) NULL
);
1789 gdk_gc_set_clip_rectangle( m_brushGC
, (GdkRectangle
*) NULL
);
1790 gdk_gc_set_clip_rectangle( m_textGC
, (GdkRectangle
*) NULL
);
1791 gdk_gc_set_clip_rectangle( m_bgGC
, (GdkRectangle
*) NULL
);
1795 gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() );
1796 gdk_gc_set_clip_region( m_brushGC
, m_currentClippingRegion
.GetRegion() );
1797 gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() );
1798 gdk_gc_set_clip_region( m_bgGC
, m_currentClippingRegion
.GetRegion() );
1802 void wxWindowDC::Destroy()
1804 if (m_penGC
) wxFreePoolGC( m_penGC
);
1805 m_penGC
= (GdkGC
*) NULL
;
1806 if (m_brushGC
) wxFreePoolGC( m_brushGC
);
1807 m_brushGC
= (GdkGC
*) NULL
;
1808 if (m_textGC
) wxFreePoolGC( m_textGC
);
1809 m_textGC
= (GdkGC
*) NULL
;
1810 if (m_bgGC
) wxFreePoolGC( m_bgGC
);
1811 m_bgGC
= (GdkGC
*) NULL
;
1814 void wxWindowDC::ComputeScaleAndOrigin()
1816 /* CMB: copy scale to see if it changes */
1817 double origScaleX
= m_scaleX
;
1818 double origScaleY
= m_scaleY
;
1820 wxDC::ComputeScaleAndOrigin();
1822 /* CMB: if scale has changed call SetPen to recalulate the line width */
1823 if ((m_scaleX
!= origScaleX
|| m_scaleY
!= origScaleY
) &&
1826 /* this is a bit artificial, but we need to force wxDC to think
1827 the pen has changed */
1834 // Resolution in pixels per logical inch
1835 wxSize
wxWindowDC::GetPPI() const
1837 return wxSize(100, 100);
1840 int wxWindowDC::GetDepth() const
1842 wxFAIL_MSG(wxT("not implemented"));
1848 // ----------------------------------- spline code ----------------------------------------
1850 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
,
1851 double a3
, double b3
, double a4
, double b4
);
1852 void wx_clear_stack();
1853 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
, double *x3
,
1854 double *y3
, double *x4
, double *y4
);
1855 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
,
1856 double x4
, double y4
);
1857 static bool wx_spline_add_point(double x
, double y
);
1858 static void wx_spline_draw_point_array(wxDC
*dc
);
1860 wxList wx_spline_point_list
;
1862 #define half(z1, z2) ((z1+z2)/2.0)
1865 /* iterative version */
1867 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
, double a3
, double b3
, double a4
,
1870 register double xmid
, ymid
;
1871 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
1874 wx_spline_push(a1
, b1
, a2
, b2
, a3
, b3
, a4
, b4
);
1876 while (wx_spline_pop(&x1
, &y1
, &x2
, &y2
, &x3
, &y3
, &x4
, &y4
)) {
1877 xmid
= (double)half(x2
, x3
);
1878 ymid
= (double)half(y2
, y3
);
1879 if (fabs(x1
- xmid
) < THRESHOLD
&& fabs(y1
- ymid
) < THRESHOLD
&&
1880 fabs(xmid
- x4
) < THRESHOLD
&& fabs(ymid
- y4
) < THRESHOLD
) {
1881 wx_spline_add_point( x1
, y1
);
1882 wx_spline_add_point( xmid
, ymid
);
1884 wx_spline_push(xmid
, ymid
, (double)half(xmid
, x3
), (double)half(ymid
, y3
),
1885 (double)half(x3
, x4
), (double)half(y3
, y4
), x4
, y4
);
1886 wx_spline_push(x1
, y1
, (double)half(x1
, x2
), (double)half(y1
, y2
),
1887 (double)half(x2
, xmid
), (double)half(y2
, ymid
), xmid
, ymid
);
1892 /* utilities used by spline drawing routines */
1894 typedef struct wx_spline_stack_struct
{
1895 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
1898 #define SPLINE_STACK_DEPTH 20
1899 static Stack wx_spline_stack
[SPLINE_STACK_DEPTH
];
1900 static Stack
*wx_stack_top
;
1901 static int wx_stack_count
;
1903 void wx_clear_stack()
1905 wx_stack_top
= wx_spline_stack
;
1909 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
, double x4
, double y4
)
1911 wx_stack_top
->x1
= x1
;
1912 wx_stack_top
->y1
= y1
;
1913 wx_stack_top
->x2
= x2
;
1914 wx_stack_top
->y2
= y2
;
1915 wx_stack_top
->x3
= x3
;
1916 wx_stack_top
->y3
= y3
;
1917 wx_stack_top
->x4
= x4
;
1918 wx_stack_top
->y4
= y4
;
1923 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
,
1924 double *x3
, double *y3
, double *x4
, double *y4
)
1926 if (wx_stack_count
== 0)
1930 *x1
= wx_stack_top
->x1
;
1931 *y1
= wx_stack_top
->y1
;
1932 *x2
= wx_stack_top
->x2
;
1933 *y2
= wx_stack_top
->y2
;
1934 *x3
= wx_stack_top
->x3
;
1935 *y3
= wx_stack_top
->y3
;
1936 *x4
= wx_stack_top
->x4
;
1937 *y4
= wx_stack_top
->y4
;
1941 static bool wx_spline_add_point(double x
, double y
)
1943 wxPoint
*point
= new wxPoint
;
1946 wx_spline_point_list
.Append((wxObject
*)point
);
1950 static void wx_spline_draw_point_array(wxDC
*dc
)
1952 dc
->DrawLines(&wx_spline_point_list
, 0, 0 );
1953 wxNode
*node
= wx_spline_point_list
.First();
1956 wxPoint
*point
= (wxPoint
*)node
->Data();
1959 node
= wx_spline_point_list
.First();
1963 void wxWindowDC::DoDrawSpline( wxList
*points
)
1965 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1968 double cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
;
1969 double x1
, y1
, x2
, y2
;
1971 wxNode
*node
= points
->First();
1972 p
= (wxPoint
*)node
->Data();
1977 node
= node
->Next();
1978 p
= (wxPoint
*)node
->Data();
1982 cx1
= (double)((x1
+ x2
) / 2);
1983 cy1
= (double)((y1
+ y2
) / 2);
1984 cx2
= (double)((cx1
+ x2
) / 2);
1985 cy2
= (double)((cy1
+ y2
) / 2);
1987 wx_spline_add_point(x1
, y1
);
1989 while ((node
= node
->Next()) != NULL
)
1991 p
= (wxPoint
*)node
->Data();
1996 cx4
= (double)(x1
+ x2
) / 2;
1997 cy4
= (double)(y1
+ y2
) / 2;
1998 cx3
= (double)(x1
+ cx4
) / 2;
1999 cy3
= (double)(y1
+ cy4
) / 2;
2001 wx_quadratic_spline(cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
);
2005 cx2
= (double)(cx1
+ x2
) / 2;
2006 cy2
= (double)(cy1
+ y2
) / 2;
2009 wx_spline_add_point( cx1
, cy1
);
2010 wx_spline_add_point( x2
, y2
);
2012 wx_spline_draw_point_array( this );
2015 #endif // wxUSE_SPLINE
2017 //-----------------------------------------------------------------------------
2019 //-----------------------------------------------------------------------------
2021 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC
,wxWindowDC
)
2023 wxPaintDC::wxPaintDC()
2028 wxPaintDC::wxPaintDC( wxWindow
*win
)
2031 #if USE_PAINT_REGION
2032 if (!win
->m_clipPaintRegion
)
2035 m_paintClippingRegion
= win
->GetUpdateRegion();
2036 m_currentClippingRegion
.Union( m_paintClippingRegion
);
2038 gdk_gc_set_clip_region( m_penGC
, m_paintClippingRegion
.GetRegion() );
2039 gdk_gc_set_clip_region( m_brushGC
, m_paintClippingRegion
.GetRegion() );
2040 gdk_gc_set_clip_region( m_textGC
, m_paintClippingRegion
.GetRegion() );
2041 gdk_gc_set_clip_region( m_bgGC
, m_paintClippingRegion
.GetRegion() );
2045 //-----------------------------------------------------------------------------
2047 //-----------------------------------------------------------------------------
2049 IMPLEMENT_DYNAMIC_CLASS(wxClientDC
,wxWindowDC
)
2051 wxClientDC::wxClientDC()
2056 wxClientDC::wxClientDC( wxWindow
*win
)
2061 // ----------------------------------------------------------------------------
2063 // ----------------------------------------------------------------------------
2065 class wxDCModule
: public wxModule
2072 DECLARE_DYNAMIC_CLASS(wxDCModule
)
2075 IMPLEMENT_DYNAMIC_CLASS(wxDCModule
, wxModule
)
2077 bool wxDCModule::OnInit()
2083 void wxDCModule::OnExit()