1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxClientDC class
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
13 About pens, brushes, and the autoSetting flag:
15 Under X, pens and brushes control some of the same X drawing parameters.
16 Therefore, it is impossible to independently maintain the current pen and the
17 current brush. Also, some settings depend on the current logical function. The
18 m_currentFill, etc. instance variables remember state across the brush and
21 Since pens are used more than brushes, the autoSetting flag is used to
22 indicate that a brush was recently used, and SetPen must be called to
23 reinstall the current pen's parameters. If autoSetting includes 0x2, then the
24 pens color may need to be set based on XOR.
26 There is, unfortunately, some confusion between setting the current pen/brush
27 and actually installing the brush/pen parameters. Both functionalies are
28 perform by SetPen and SetBrush. C'est la vie.
31 // ============================================================================
33 // ============================================================================
35 // ----------------------------------------------------------------------------
37 // ----------------------------------------------------------------------------
40 #pragma implementation "dcclient.h"
43 #include "wx/dcclient.h"
44 #include "wx/dcmemory.h"
45 #include "wx/window.h"
53 #include "wx/motif/private.h"
62 static Pixmap bdiag
, cdiag
, fdiag
, cross
, horiz
, verti
;
64 // ----------------------------------------------------------------------------
66 // ----------------------------------------------------------------------------
68 #define RAD2DEG 57.2957795131
70 // Fudge factor (VZ: what??)
73 // ----------------------------------------------------------------------------
75 // ----------------------------------------------------------------------------
77 #if !USE_SHARED_LIBRARY
78 IMPLEMENT_DYNAMIC_CLASS(wxClientDC
, wxWindowDC
)
79 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC
, wxWindowDC
)
80 IMPLEMENT_DYNAMIC_CLASS(wxWindowDC
, wxDC
)
83 // ----------------------------------------------------------------------------
85 // ----------------------------------------------------------------------------
87 static void XCopyRemote(Display
*src_display
, Display
*dest_display
,
88 Drawable src
, Drawable dest
,
91 unsigned int w
, unsigned int h
,
93 bool more
, XImage
**cache
);
95 // ============================================================================
97 // ============================================================================
99 // ----------------------------------------------------------------------------
101 // ----------------------------------------------------------------------------
103 wxWindowDC::wxWindowDC()
106 m_gcBacking
= (WXGC
) 0;
108 m_backgroundPixel
= -1;
109 m_currentPenWidth
= 1;
110 m_currentPenJoin
= -1;
111 m_currentPenDashCount
= -1;
112 m_currentPenDash
= (char*) NULL
;
115 // m_currentBkMode = wxTRANSPARENT;
116 m_colour
= wxColourDisplay();
117 m_display
= (WXDisplay
*) NULL
;
118 m_currentRegion
= (WXRegion
) 0;
119 m_userRegion
= (WXRegion
) 0;
120 m_pixmap
= (WXPixmap
) 0;
122 m_oldFont
= (WXFont
) 0;
125 wxWindowDC::wxWindowDC( wxWindow
*window
)
127 wxASSERT_MSG( (window
!= (wxWindow
*) NULL
), "You must pass a valid wxWindow to wxWindowDC/wxClientDC/wxPaintDC constructor." );
131 m_gcBacking
= (WXGC
) 0;
132 m_backgroundPixel
= -1;
133 m_currentPenWidth
= 1;
134 m_currentPenJoin
= -1;
135 m_currentPenDashCount
= -1;
136 m_currentPenDash
= (char*) NULL
;
139 // m_currentBkMode = wxTRANSPARENT;
140 m_colour
= wxColourDisplay();
141 m_currentRegion
= (WXRegion
) 0;
142 m_userRegion
= (WXRegion
) 0;
146 m_display
= window
->GetXDisplay();
147 m_pixmap
= window
->GetXWindow();
148 Display
* display
= (Display
*) m_display
;
150 XSetWindowColormap (display
, (Pixmap
) m_pixmap
, (Colormap
) wxTheApp
->GetMainColormap(m_display
));
153 gcvalues
.foreground
= BlackPixel (display
, DefaultScreen (display
));
154 gcvalues
.background
= WhitePixel (display
, DefaultScreen (display
));
155 gcvalues
.graphics_exposures
= False
;
156 gcvalues
.line_width
= 1;
157 m_gc
= (WXGC
) XCreateGC (display
, RootWindow (display
, DefaultScreen (display
)),
158 GCForeground
| GCBackground
| GCGraphicsExposures
| GCLineWidth
,
161 if (m_window
->GetBackingPixmap())
163 m_gcBacking
= (WXGC
) XCreateGC (display
, RootWindow (display
,
164 DefaultScreen (display
)),
165 GCForeground
| GCBackground
| GCGraphicsExposures
| GCLineWidth
,
169 m_backgroundPixel
= (int) gcvalues
.background
;
171 // Get the current Font so we can set it back later
173 XGetGCValues((Display
*) m_display
, (GC
) m_gc
, GCFont
, &valReturn
);
174 m_oldFont
= (WXFont
) valReturn
.font
;
176 SetBackground(wxBrush(m_window
->GetBackgroundColour(), wxSOLID
));
179 wxWindowDC::~wxWindowDC()
181 if (m_gc
&& (m_oldFont
!= (WXFont
) 0) && ((long) m_oldFont
!= -1))
183 XSetFont ((Display
*) m_display
, (GC
) m_gc
, (Font
) m_oldFont
);
185 if (m_window
&& m_window
->GetBackingPixmap())
186 XSetFont ((Display
*) m_display
,(GC
) m_gcBacking
, (Font
) m_oldFont
);
190 XFreeGC ((Display
*) m_display
, (GC
) m_gc
);
194 XFreeGC ((Display
*) m_display
, (GC
) m_gcBacking
);
195 m_gcBacking
= (WXGC
) 0;
198 XDestroyRegion ((Region
) m_currentRegion
);
199 m_currentRegion
= (WXRegion
) 0;
202 XDestroyRegion ((Region
) m_userRegion
);
203 m_userRegion
= (WXRegion
) 0;
206 void wxWindowDC::DoFloodFill( long WXUNUSED(x1
), long WXUNUSED(y1
),
207 const wxColour
& WXUNUSED(col
), int WXUNUSED(style
) )
209 wxFAIL_MSG("not implemented");
212 bool wxWindowDC::DoGetPixel( long WXUNUSED(x1
), long WXUNUSED(y1
), wxColour
*WXUNUSED(col
) ) const
214 wxFAIL_MSG("not implemented");
219 void wxWindowDC::DoDrawLine( long x1
, long y1
, long x2
, long y2
)
221 wxCHECK_RET( Ok(), "invalid dc" );
223 int x1d
, y1d
, x2d
, y2d
;
225 // FreeGetPixelCache();
235 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, x1d
, y1d
, x2d
, y2d
);
237 if (m_window
&& m_window
->GetBackingPixmap())
238 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
239 XLOG2DEV_2(x1
), YLOG2DEV_2(y1
),
240 XLOG2DEV_2(x2
), YLOG2DEV_2(y2
));
242 CalcBoundingBox(x1
, y1
);
243 CalcBoundingBox(x2
, y2
);
246 void wxWindowDC::DoCrossHair( long x
, long y
)
248 wxCHECK_RET( Ok(), "invalid dc" );
253 int xx
= XLOG2DEV (x
);
254 int yy
= YLOG2DEV (y
);
256 wxDisplaySize (&ww
, &hh
);
257 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, 0, yy
,
259 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xx
, 0,
262 if (m_window
&& m_window
->GetBackingPixmap())
266 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
269 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
275 void wxWindowDC::DoDrawArc( long x1
, long y1
, long x2
, long y2
, long xc
, long yc
)
277 wxCHECK_RET( Ok(), "invalid dc" );
279 // FreeGetPixelCache();
281 int xx1
= XLOG2DEV (x1
);
282 int yy1
= YLOG2DEV (y1
);
283 int xx2
= XLOG2DEV (x2
);
284 int yy2
= YLOG2DEV (y2
);
285 int xxc
= XLOG2DEV (xc
);
286 int yyc
= YLOG2DEV (yc
);
287 int xxc_2
= XLOG2DEV_2 (xc
);
288 int yyc_2
= YLOG2DEV_2 (yc
);
292 double radius
= sqrt (dx
* dx
+ dy
* dy
);
293 long r
= (long) radius
;
295 double radius1
, radius2
;
297 if (xx1
== xx2
&& yy1
== yy2
)
302 else if (radius
== 0.0)
303 radius1
= radius2
= 0.0;
312 radius1
= -atan2 ((double) (yy1
- yyc
), (double) (xx1
- xxc
)) * 360.0 / (2 * M_PI
);
320 radius2
= -atan2 ((double) (yy2
- yyc
), (double) (xx2
- xxc
)) * 360.0 / (2 * M_PI
);
324 int alpha1
= (int) radius1
;
325 int alpha2
= (int) (radius2
- radius1
);
328 while (alpha2
> 360 * 64)
331 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
334 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) (GC
) m_gc
,
335 xxc
- r
, yyc
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
337 if (m_window
&& m_window
->GetBackingPixmap())
338 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
339 xxc_2
- r
, yyc_2
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
343 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
347 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
348 xxc
- r
, yyc
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
350 if (m_window
&& m_window
->GetBackingPixmap())
351 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
352 xxc_2
- r
, yyc_2
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
354 CalcBoundingBox (x1
, y1
);
355 CalcBoundingBox (x2
, y2
);
358 void wxWindowDC::DoDrawEllipticArc( long x
, long y
, long width
, long height
, double sa
, double ea
)
360 wxCHECK_RET( Ok(), "invalid dc" );
366 wd
= XLOG2DEVREL(width
);
367 hd
= YLOG2DEVREL(height
);
369 if (sa
>=360 || sa
<=-360) sa
=sa
-int(sa
/360)*360;
370 if (ea
>=360 || ea
<=-360) ea
=ea
-int(ea
/360)*360;
371 int start
= int(sa
*64);
372 int end
= int(ea
*64);
373 if (start
<0) start
+=360*64;
374 if (end
<0) end
+=360*64;
375 if (end
>start
) end
-=start
;
376 else end
+=360*64-start
;
378 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
380 m_autoSetting
= TRUE
; // must be reset
383 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, start
, end
);
385 if (m_window
&& m_window
->GetBackingPixmap())
386 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
387 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),wd
,hd
,start
,end
);
390 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
394 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, start
,end
);
395 if (m_window
&& m_window
->GetBackingPixmap())
396 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
397 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),wd
,hd
,start
,end
);
399 CalcBoundingBox (x
, y
);
400 CalcBoundingBox (x
+ width
, y
+ height
);
403 void wxWindowDC::DoDrawPoint( long x
, long y
)
405 wxCHECK_RET( Ok(), "invalid dc" );
407 // FreeGetPixelCache();
409 if (m_pen
.Ok() && m_autoSetting
)
412 XDrawPoint ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
));
413 if (m_window
&& m_window
->GetBackingPixmap())
414 XDrawPoint ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, XLOG2DEV_2 (x
), YLOG2DEV_2 (y
));
416 CalcBoundingBox (x
, y
);
419 void wxWindowDC::DoDrawLines( int n
, wxPoint points
[], long xoffset
, long yoffset
)
421 wxCHECK_RET( Ok(), "invalid dc" );
423 // FreeGetPixelCache();
425 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
430 XPoint
*xpoints
= new XPoint
[n
];
433 for (i
= 0; i
< n
; i
++)
435 xpoints
[i
].x
= XLOG2DEV (points
[i
].x
+ xoffset
);
436 xpoints
[i
].y
= YLOG2DEV (points
[i
].y
+ yoffset
);
438 XDrawLines ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xpoints
, n
, 0);
440 if (m_window
&& m_window
->GetBackingPixmap())
442 for (i
= 0; i
< n
; i
++)
444 xpoints
[i
].x
= XLOG2DEV_2 (points
[i
].x
+ xoffset
);
445 xpoints
[i
].y
= YLOG2DEV_2 (points
[i
].y
+ yoffset
);
447 XDrawLines ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, xpoints
, n
, 0);
453 void wxWindowDC::DoDrawPolygon( int n
, wxPoint points
[],
454 long xoffset
, long yoffset
, int fillStyle
)
456 wxCHECK_RET( Ok(), "invalid dc" );
458 // FreeGetPixelCache();
460 XPoint
*xpoints1
= new XPoint
[n
+ 1];
461 XPoint
*xpoints2
= new XPoint
[n
+ 1];
463 for (i
= 0; i
< n
; i
++)
465 xpoints1
[i
].x
= XLOG2DEV (points
[i
].x
+ xoffset
);
466 xpoints1
[i
].y
= YLOG2DEV (points
[i
].y
+ yoffset
);
467 xpoints2
[i
].x
= XLOG2DEV_2 (points
[i
].x
+ xoffset
);
468 xpoints2
[i
].y
= YLOG2DEV_2 (points
[i
].y
+ yoffset
);
469 CalcBoundingBox (points
[i
].x
+ xoffset
, points
[i
].y
+ yoffset
);
472 // Close figure for XDrawLines (not needed for XFillPolygon)
473 xpoints1
[i
].x
= xpoints1
[0].x
;
474 xpoints1
[i
].y
= xpoints1
[0].y
;
475 xpoints2
[i
].x
= xpoints2
[0].x
;
476 xpoints2
[i
].y
= xpoints2
[0].y
;
478 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
481 XSetFillRule ((Display
*) m_display
, (GC
) m_gc
, fillStyle
== wxODDEVEN_RULE
? EvenOddRule
: WindingRule
);
482 XFillPolygon ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xpoints1
, n
, Complex
, 0);
483 XSetFillRule ((Display
*) m_display
, (GC
) m_gc
, EvenOddRule
); // default mode
484 if (m_window
&& m_window
->GetBackingPixmap())
486 XSetFillRule ((Display
*) m_display
,(GC
) m_gcBacking
,
487 fillStyle
== wxODDEVEN_RULE
? EvenOddRule
: WindingRule
);
488 XFillPolygon ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, xpoints2
, n
, Complex
, 0);
489 XSetFillRule ((Display
*) m_display
,(GC
) m_gcBacking
, EvenOddRule
); // default mode
493 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
497 XDrawLines ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xpoints1
, n
+ 1, 0);
499 if (m_window
&& m_window
->GetBackingPixmap())
500 XDrawLines ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, xpoints2
, n
+ 1, 0);
507 void wxWindowDC::DoDrawRectangle( long x
, long y
, long width
, long height
)
509 wxCHECK_RET( Ok(), "invalid dc" );
511 // FreeGetPixelCache();
513 int xd
, yd
, wfd
, hfd
, wd
, hd
;
517 wfd
= XLOG2DEVREL(width
);
519 hfd
= YLOG2DEVREL(height
);
522 if (wfd
== 0 || hfd
== 0) return;
523 if (wd
< 0) { wd
= - wd
; xd
= xd
- wd
; }
524 if (hd
< 0) { hd
= - hd
; yd
= yd
- hd
; }
526 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
529 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wfd
, hfd
);
531 if (m_window
&& m_window
->GetBackingPixmap())
532 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
533 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
537 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
541 XDrawRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
);
543 if (m_window
&& m_window
->GetBackingPixmap())
544 XDrawRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
545 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
548 CalcBoundingBox (x
, y
);
549 CalcBoundingBox (x
+ width
, y
+ height
);
552 void wxWindowDC::DoDrawRoundedRectangle( long x
, long y
, long width
, long height
, double radius
)
554 wxCHECK_RET( Ok(), "invalid dc" );
556 // FreeGetPixelCache();
558 // If radius is negative, it's a proportion of the smaller dimension.
560 if (radius
< 0.0) radius
= - radius
* ((width
< height
) ? width
: height
);
562 int xd
= XLOG2DEV (x
);
563 int yd
= YLOG2DEV (y
);
564 int rd
= XLOG2DEVREL ((long) radius
);
565 int wd
= XLOG2DEVREL (width
) - WX_GC_CF
;
566 int hd
= YLOG2DEVREL (height
) - WX_GC_CF
;
571 // If radius is zero use DrawRectangle() instead to avoid
572 // X drawing errors with small radii
575 DrawRectangle( x
, y
, width
, height
);
579 // Draw nothing if transformed w or h is 0
580 if (wd
== 0 || hd
== 0) return;
582 // CMB: adjust size if outline is drawn otherwise the result is
583 // 1 pixel too wide and high
584 if (m_pen
.GetStyle() != wxTRANSPARENT
)
590 // CMB: ensure dd is not larger than rectangle otherwise we
591 // get an hour glass shape
592 if (rw_d
> wd
) rw_d
= wd
;
593 if (rw_d
> hd
) rw_d
= hd
;
596 // For backing pixmap
597 int xd2
= XLOG2DEV_2 (x
);
598 int yd2
= YLOG2DEV_2 (y
);
599 int rd2
= XLOG2DEVREL ((long) radius
);
600 int wd2
= XLOG2DEVREL (width
) ;
601 int hd2
= YLOG2DEVREL (height
) ;
606 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
610 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ rd
, yd
,
612 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ rd
,
615 // Arcs start from 3 o'clock, positive angles anticlockwise
617 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
,
618 rw_d
, rh_d
, 90 * 64, 90 * 64);
620 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
, yd
,
621 // rw_d, rh_d, 0, 90 * 64);
622 rw_d
, rh_d
, 0, 91 * 64);
624 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
,
626 // rw_d, rh_d, 270 * 64, 90 * 64);
627 rw_d
, rh_d
, 269 * 64, 92 * 64);
629 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ hd
- rh_d
,
630 rw_d
, rh_d
, 180 * 64, 90 * 64);
632 if (m_window
&& m_window
->GetBackingPixmap())
634 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
635 xd2
+ rd2
, yd2
, wd2
- rw_d2
, hd2
);
636 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
637 xd2
, yd2
+ rd2
, wd2
, hd2
- rh_d2
);
639 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
640 xd2
, yd2
, rw_d2
, rh_d2
, 90 * 64, 90 * 64);
641 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
642 xd2
+ wd2
- rw_d2
, yd2
,
643 // rw_d2, rh_d2, 0, 90 * 64);
644 rw_d2
, rh_d2
, 0, 91 * 64);
645 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
648 // rw_d2, rh_d2, 270 * 64, 90 * 64);
649 rw_d2
, rh_d2
, 269 * 64, 92 * 64);
650 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
651 xd2
, yd2
+ hd2
- rh_d2
,
652 rw_d2
, rh_d2
, 180 * 64, 90 * 64);
656 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
659 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ rd
, yd
,
660 xd
+ wd
- rd
+ 1, yd
);
661 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ rd
, yd
+ hd
,
662 xd
+ wd
- rd
, yd
+ hd
);
664 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ rd
,
666 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
, yd
+ rd
,
667 xd
+ wd
, yd
+ hd
- rd
+ 1);
668 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
,
669 rw_d
, rh_d
, 90 * 64, 90 * 64);
670 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
, yd
,
671 // rw_d, rh_d, 0, 90 * 64);
672 rw_d
, rh_d
, 0, 91 * 64);
673 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
,
675 rw_d
, rh_d
, 269 * 64, 92 * 64);
676 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ hd
- rh_d
,
677 rw_d
, rh_d
, 180 * 64, 90 * 64);
679 if (m_window
&& m_window
->GetBackingPixmap())
681 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
683 xd2
+ wd2
- rd2
+ 1, yd2
);
684 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
685 xd2
+ rd2
, yd2
+ hd2
,
686 xd2
+ wd2
- rd2
, yd2
+ hd2
);
688 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
690 xd2
, yd2
+ hd2
- rd2
);
691 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
692 xd2
+ wd2
, yd2
+ rd2
,
693 xd2
+ wd2
, yd2
+ hd2
- rd2
+ 1);
694 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
696 rw_d2
, rh_d2
, 90 * 64, 90 * 64);
697 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
698 xd2
+ wd2
- rw_d2
, yd2
,
699 // rw_d2, rh_d2, 0, 90 * 64);
700 rw_d2
, rh_d2
, 0, 91 * 64);
701 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
704 rw_d2
, rh_d2
, 269 * 64, 92 * 64);
705 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
706 xd2
, yd2
+ hd2
- rh_d2
,
707 rw_d2
, rh_d2
, 180 * 64, 90 * 64);
710 CalcBoundingBox (x
, y
);
711 CalcBoundingBox (x
+ width
, y
+ height
);
716 void wxWindowDC::DoDrawEllipse( long x
, long y
, long width
, long height
)
718 wxCHECK_RET( Ok(), "invalid dc" );
720 // Check for negative width and height
733 // FreeGetPixelCache();
735 static const int angle
= 23040;
741 wd
= XLOG2DEVREL(width
) ;
742 hd
= YLOG2DEVREL(height
) ;
744 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
747 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, 0, angle
);
748 if (m_window
&& m_window
->GetBackingPixmap())
749 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
750 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
751 XLOG2DEVREL (width
) - WX_GC_CF
,
752 YLOG2DEVREL (height
) - WX_GC_CF
, 0, angle
);
755 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
759 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, 0, angle
);
760 if (m_window
&& m_window
->GetBackingPixmap())
761 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
762 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
763 XLOG2DEVREL (width
) - WX_GC_CF
,
764 YLOG2DEVREL (height
) - WX_GC_CF
, 0, angle
);
766 CalcBoundingBox (x
, y
);
767 CalcBoundingBox (x
+ width
, y
+ height
);
771 bool wxWindowDC::CanDrawBitmap() const
773 wxCHECK_MSG( Ok(), FALSE
, "invalid dc" );
779 void wxWindowDC::DoDrawIcon( const wxIcon
&icon
, long x
, long y
)
781 // FreeGetPixelCache();
783 // Be sure that foreground pixels (1) of
784 // the Icon will be painted with pen colour. [m_pen.SetColour()]
785 // Background pixels (0) will be painted with
786 // last selected background color. [::SetBackground]
787 if (m_pen
.Ok() && m_autoSetting
)
791 Pixmap iconPixmap
= (Pixmap
) icon
.GetPixmap();
792 width
= icon
.GetWidth();
793 height
= icon
.GetHeight();
794 if (icon
.GetDisplay() == m_display
)
796 if (icon
.GetDepth() <= 1)
798 XCopyPlane ((Display
*) m_display
, iconPixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
800 (int) XLOG2DEV (x
), (int) YLOG2DEV (y
), 1);
804 XCopyArea ((Display
*) m_display
, iconPixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
806 (int) XLOG2DEV (x
), (int) YLOG2DEV (y
));
810 if (m_window
&& m_window
->GetBackingPixmap())
812 if (icon
.GetDepth() <= 1)
814 XCopyPlane ((Display
*) m_display
, iconPixmap
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
815 0, 0, width
, height
, (int) XLOG2DEV_2 (x
), (int) YLOG2DEV_2 (y
), 1);
819 XCopyArea ((Display
*) m_display
, iconPixmap
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
821 (int) XLOG2DEV_2 (x
), (int) YLOG2DEV_2 (y
));
824 } else { /* Remote copy (different (Display*) m_displays) */
825 XImage
*cache
= NULL
;
826 if (m_window
&& m_window
->GetBackingPixmap())
827 XCopyRemote((Display
*) icon
.GetDisplay(), (Display
*) m_display
, iconPixmap
, (Pixmap
) m_window
->GetBackingPixmap(),
828 (GC
) m_gcBacking
, 0, 0, width
, height
,
829 (int) XLOG2DEV_2 (x
), (int) YLOG2DEV_2 (y
), TRUE
, &cache
);
830 XCopyRemote((Display
*) icon
.GetDisplay(), (Display
*) m_display
, iconPixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
832 (int) XLOG2DEV (x
), (int) YLOG2DEV (y
), FALSE
, &cache
);
834 CalcBoundingBox (x
, y
);
838 // TODO: use scaled Blit e.g. as per John Price's implementation in Contrib/Utilities
839 bool wxWindowDC::DoBlit( long xdest
, long ydest
, long width
, long height
,
840 wxDC
*source
, long xsrc
, long ysrc
, int rop
, bool useMask
)
842 wxCHECK_MSG( Ok(), FALSE
, "invalid dc" );
844 wxWindowDC
* sourceDC
= wxDynamicCast(source
, wxWindowDC
);
846 wxASSERT_MSG( sourceDC
, "Blit source DC must be wxWindowDC or derived class." );
848 // FreeGetPixelCache();
850 // Be sure that foreground pixels (1) of the Icon will be painted with pen
851 // colour. [m_pen.SetColour()] Background pixels (0) will be painted with
852 // last selected background color. [::SetBackground]
853 if (m_pen
.Ok() && m_autoSetting
)
856 // Do bitmap scaling if necessary
858 wxBitmap
*scaledBitmap
= (wxBitmap
*) NULL
;
859 Pixmap sourcePixmap
= (Pixmap
) NULL
;
860 double scaleX
, scaleY
;
861 GetUserScale(& scaleX
, & scaleY
);
863 // Sorry, can't scale masks just yet
864 if (!useMask
&& (scaleX
!= 1.0 || scaleY
!= 1.0) && sourceDC
->IsKindOf(CLASSINFO(wxMemoryDC
)))
866 wxMemoryDC
* memDC
= (wxMemoryDC
*) sourceDC
;
867 wxBitmap
& bitmap
= memDC
->GetBitmap();
869 wxASSERT_MSG( (bitmap
.Ok()), "Bad source bitmap in wxWindowDC::Blit");
871 wxImage
image(bitmap
);
874 sourcePixmap
= (Pixmap
) bitmap
.GetPixmap();
878 int scaledW
= (int) (bitmap
.GetWidth() * scaleX
);
879 int scaledH
= (int) (bitmap
.GetHeight() * scaleY
);
881 image
= image
.Scale(scaledW
, scaledH
);
882 scaledBitmap
= new wxBitmap(image
.ConvertToBitmap());
883 sourcePixmap
= (Pixmap
) scaledBitmap
->GetPixmap();
887 sourcePixmap
= (Pixmap
) sourceDC
->m_pixmap
;
889 if (m_pixmap
&& sourcePixmap
)
892 int orig
= m_logicalFunction
;
894 SetLogicalFunction (rop
);
896 if (m_display
!= sourceDC
->m_display
)
898 XImage
*cache
= NULL
;
900 if (m_window
&& m_window
->GetBackingPixmap())
901 XCopyRemote((Display
*) sourceDC
->m_display
, (Display
*) m_display
,
902 (Pixmap
) sourcePixmap
, (Pixmap
) m_window
->GetBackingPixmap(),
904 source
->LogicalToDeviceX (xsrc
),
905 source
->LogicalToDeviceY (ysrc
),
906 source
->LogicalToDeviceXRel(width
),
907 source
->LogicalToDeviceYRel(height
),
908 XLOG2DEV_2 (xdest
), YLOG2DEV_2 (ydest
),
911 if ( useMask
&& source
->IsKindOf(CLASSINFO(wxMemoryDC
)) )
913 wxMemoryDC
*memDC
= (wxMemoryDC
*)source
;
914 wxBitmap
& sel
= memDC
->GetBitmap();
915 if ( sel
.Ok() && sel
.GetMask() && sel
.GetMask()->GetPixmap() )
917 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) sel
.GetMask()->GetPixmap());
918 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, XLOG2DEV (xdest
), YLOG2DEV (ydest
));
922 XCopyRemote((Display
*) sourceDC
->m_display
, (Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
923 source
->LogicalToDeviceX (xsrc
),
924 source
->LogicalToDeviceY (ysrc
),
925 source
->LogicalToDeviceXRel(width
),
926 source
->LogicalToDeviceYRel(height
),
927 XLOG2DEV (xdest
), YLOG2DEV (ydest
),
932 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
933 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, 0, 0);
938 if (m_window
&& m_window
->GetBackingPixmap())
940 // +++ MARKUS (mho@comnets.rwth-aachen): error on blitting bitmaps with depth 1
941 if (source
->IsKindOf(CLASSINFO(wxMemoryDC
)) && ((wxMemoryDC
*) source
)->GetBitmap().GetDepth() == 1)
943 XCopyPlane ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
944 source
->LogicalToDeviceX (xsrc
),
945 source
->LogicalToDeviceY (ysrc
),
946 source
->LogicalToDeviceXRel(width
),
947 source
->LogicalToDeviceYRel(height
),
948 XLOG2DEV_2 (xdest
), YLOG2DEV_2 (ydest
), 1);
952 XCopyArea ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
953 source
->LogicalToDeviceX (xsrc
),
954 source
->LogicalToDeviceY (ysrc
),
955 source
->LogicalToDeviceXRel(width
),
956 source
->LogicalToDeviceYRel(height
),
957 XLOG2DEV_2 (xdest
), YLOG2DEV_2 (ydest
));
960 if ( useMask
&& source
->IsKindOf(CLASSINFO(wxMemoryDC
)) )
962 wxMemoryDC
*memDC
= (wxMemoryDC
*)source
;
963 wxBitmap
& sel
= memDC
->GetBitmap();
964 if ( sel
.Ok() && sel
.GetMask() && sel
.GetMask()->GetPixmap() )
966 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) sel
.GetMask()->GetPixmap());
967 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, XLOG2DEV (xdest
), YLOG2DEV (ydest
));
971 // Check if we're copying from a mono bitmap
972 if (source
->IsKindOf(CLASSINFO(wxMemoryDC
)) &&
973 ((wxMemoryDC
*)source
)->GetBitmap().Ok() && (((wxMemoryDC
*)source
)->GetBitmap().GetDepth () == 1))
975 XCopyPlane ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
976 source
->LogicalToDeviceX (xsrc
),
977 source
->LogicalToDeviceY (ysrc
),
978 source
->LogicalToDeviceXRel(width
),
979 source
->LogicalToDeviceYRel(height
),
980 XLOG2DEV (xdest
), YLOG2DEV (ydest
), 1);
984 XCopyArea ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
985 source
->LogicalToDeviceX (xsrc
),
986 source
->LogicalToDeviceY (ysrc
),
987 source
->LogicalToDeviceXRel(width
),
988 source
->LogicalToDeviceYRel(height
),
989 XLOG2DEV (xdest
), YLOG2DEV (ydest
));
994 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
995 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, 0, 0);
998 } /* Remote/local (Display*) m_display */
999 CalcBoundingBox (xdest
, ydest
);
1000 CalcBoundingBox (xdest
+ width
, ydest
+ height
);
1002 SetLogicalFunction(orig
);
1004 if (scaledBitmap
) delete scaledBitmap
;
1008 if (scaledBitmap
) delete scaledBitmap
;
1013 void wxWindowDC::DoDrawText( const wxString
&text
, long x
, long y
)
1015 wxCHECK_RET( Ok(), "invalid dc" );
1017 // Since X draws from the baseline of the text, must add the text height
1023 slen
= strlen(text
);
1027 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1028 int direction
, descent
;
1029 XCharStruct overall_return
;
1032 (void)XTextExtents16((XFontStruct
*) pFontStruct
, (XChar2b
*)(const char*) text
, slen
, &direction
,
1033 &ascent
, &descent
, &overall_return
);
1036 (void)XTextExtents((XFontStruct
*) pFontStruct
, (char*) (const char*) text
, slen
, &direction
,
1037 &ascent
, &descent
, &overall_return
);
1039 cx
= overall_return
.width
;
1040 cy
= ascent
+ descent
;
1043 // First draw a rectangle representing the text background, if a text
1044 // background is specified
1045 if (m_textBackgroundColour
.Ok () && (m_backgroundMode
!= wxTRANSPARENT
))
1047 wxColour oldPenColour
= m_currentColour
;
1048 m_currentColour
= m_textBackgroundColour
;
1049 bool sameColour
= (oldPenColour
.Ok () && m_textBackgroundColour
.Ok () &&
1050 (oldPenColour
.Red () == m_textBackgroundColour
.Red ()) &&
1051 (oldPenColour
.Blue () == m_textBackgroundColour
.Blue ()) &&
1052 (oldPenColour
.Green () == m_textBackgroundColour
.Green ()));
1054 // This separation of the big && test required for gcc2.7/HP UX 9.02
1055 // or pixel value can be corrupted!
1056 sameColour
= (sameColour
&&
1057 (oldPenColour
.GetPixel() == m_textBackgroundColour
.GetPixel()));
1059 if (!sameColour
|| !GetOptimization())
1061 int pixel
= m_textBackgroundColour
.AllocColour(m_display
);
1062 m_currentColour
= m_textBackgroundColour
;
1064 // Set the GC to the required colour
1067 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1068 if (m_window
&& m_window
->GetBackingPixmap())
1069 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1073 m_textBackgroundColour
= oldPenColour
;
1075 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
), cx
, cy
);
1076 if (m_window
&& m_window
->GetBackingPixmap())
1077 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
1078 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
), cx
, cy
);
1081 // Now set the text foreground and draw the text
1082 if (m_textForegroundColour
.Ok ())
1084 wxColour oldPenColour
= m_currentColour
;
1085 m_currentColour
= m_textForegroundColour
;
1086 bool sameColour
= (oldPenColour
.Ok () && m_currentColour
.Ok () &&
1087 (oldPenColour
.Red () == m_currentColour
.Red ()) &&
1088 (oldPenColour
.Blue () == m_currentColour
.Blue ()) &&
1089 (oldPenColour
.Green () == m_currentColour
.Green ()) &&
1090 (oldPenColour
.GetPixel() == m_currentColour
.GetPixel()));
1092 if (!sameColour
|| !GetOptimization())
1095 if (!m_colour
) // Mono display
1097 // Unless foreground is really white, draw it in black
1098 unsigned char red
= m_textForegroundColour
.Red ();
1099 unsigned char blue
= m_textForegroundColour
.Blue ();
1100 unsigned char green
= m_textForegroundColour
.Green ();
1101 if (red
== (unsigned char) 255 && blue
== (unsigned char) 255
1102 && green
== (unsigned char) 255)
1104 m_currentColour
= *wxWHITE
;
1105 pixel
= (int) WhitePixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1106 m_currentColour
.SetPixel(pixel
);
1107 m_textForegroundColour
.SetPixel(pixel
);
1111 m_currentColour
= *wxBLACK
;
1112 pixel
= (int) BlackPixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1113 m_currentColour
.SetPixel(pixel
);
1114 m_textForegroundColour
.SetPixel(pixel
);
1119 pixel
= m_textForegroundColour
.AllocColour((Display
*) m_display
);
1120 m_currentColour
.SetPixel(pixel
);
1123 // Set the GC to the required colour
1126 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1127 if (m_window
&& m_window
->GetBackingPixmap())
1128 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1132 m_textForegroundColour
= oldPenColour
;
1135 // We need to add the ascent, not the whole height, since X draws at the
1136 // point above the descender.
1139 XDrawString16((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
) + ascent
,
1140 (XChar2b
*)(char*) (const char*) text
, slen
);
1143 XDrawString((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
) + ascent
, text
, slen
);
1145 if (m_window
&& m_window
->GetBackingPixmap()) {
1148 XDrawString16((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
1149 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
) + ascent
,
1150 (XChar2b
*)(char*) (const char*) text
, slen
);
1153 XDrawString((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
1154 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
) + ascent
, (char*) (const char*) text
, slen
);
1158 GetTextExtent (text
, &w
, &h
);
1159 CalcBoundingBox (x
+ w
, y
+ h
);
1160 CalcBoundingBox (x
, y
);
1163 bool wxWindowDC::CanGetTextExtent() const
1168 void wxWindowDC::GetTextExtent( const wxString
&string
, long *width
, long *height
,
1169 long *descent
, long *externalLeading
,
1170 wxFont
*font
) const
1172 wxCHECK_RET( Ok(), "invalid dc" );
1174 wxFont
* theFont
= font
;
1176 theFont
= (wxFont
*)&m_font
; // const_cast
1180 // TODO: this should be an error log function
1181 wxFAIL_MSG("set a valid font before calling GetTextExtent!");
1183 if (width
) *width
= -1;
1184 if (height
) *height
= -1;
1188 WXFontStructPtr pFontStruct
= theFont
->GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1190 int direction
, ascent
, descent2
;
1191 XCharStruct overall
;
1196 slen
= str16len(string
);
1199 slen
= strlen(string
);
1203 XTextExtents16((XFontStruct
*) pFontStruct
, (XChar2b
*) (char*) (const char*) string
, slen
, &direction
,
1204 &ascent
, &descent2
, &overall
);
1207 XTextExtents((XFontStruct
*) pFontStruct
, (char*) (const char*) string
, slen
, &direction
,
1208 &ascent
, &descent2
, &overall
);
1210 if (width
) *width
= XDEV2LOGREL (overall
.width
);
1211 if (height
) *height
= YDEV2LOGREL (ascent
+ descent2
);
1213 *descent
= descent2
;
1214 if (externalLeading
)
1215 *externalLeading
= 0;
1218 long wxWindowDC::GetCharWidth() const
1220 wxCHECK_MSG( Ok(), 0, "invalid dc" );
1221 wxCHECK_MSG( m_font
.Ok(), 0, "invalid font" );
1223 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
* m_logicalScaleY
, m_display
);
1225 int direction
, ascent
, descent
;
1226 XCharStruct overall
;
1227 XTextExtents ((XFontStruct
*) pFontStruct
, "x", 1, &direction
, &ascent
,
1228 &descent
, &overall
);
1229 return XDEV2LOGREL(overall
.width
);
1232 long wxWindowDC::GetCharHeight() const
1234 wxCHECK_MSG( Ok(), 0, "invalid dc" );
1235 wxCHECK_MSG( m_font
.Ok(), 0, "invalid font" );
1237 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1239 int direction
, ascent
, descent
;
1240 XCharStruct overall
;
1241 XTextExtents ((XFontStruct
*) pFontStruct
, "x", 1, &direction
, &ascent
,
1242 &descent
, &overall
);
1243 // return XDEV2LOGREL(overall.ascent + overall.descent);
1244 return XDEV2LOGREL(ascent
+ descent
);
1247 void wxWindowDC::Clear()
1249 wxCHECK_RET( Ok(), "invalid dc" );
1254 m_window
->GetSize(&w
, &h
);
1256 if (m_window
&& m_window
->GetBackingPixmap())
1258 w
= m_window
->GetPixmapWidth();
1259 h
= m_window
->GetPixmapHeight();
1264 if (this->IsKindOf(CLASSINFO(wxMemoryDC
)))
1266 wxMemoryDC
* memDC
= (wxMemoryDC
*) this;
1267 w
= memDC
->GetBitmap().GetWidth();
1268 h
= memDC
->GetBitmap().GetHeight();
1274 wxBrush saveBrush
= m_brush
;
1275 SetBrush (m_backgroundBrush
);
1277 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, 0, 0, w
, h
);
1279 if (m_window
&& m_window
->GetBackingPixmap())
1280 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, 0, 0, w
, h
);
1282 m_brush
= saveBrush
;
1285 void wxWindowDC::Clear(const wxRect
& rect
)
1287 wxCHECK_RET( Ok(), "invalid dc" );
1289 int x
= rect
.x
; int y
= rect
.y
;
1290 int w
= rect
.width
; int h
= rect
.height
;
1292 wxBrush saveBrush
= m_brush
;
1293 SetBrush (m_backgroundBrush
);
1295 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, x
, y
, w
, h
);
1297 if (m_window
&& m_window
->GetBackingPixmap())
1298 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, x
, y
, w
, h
);
1300 m_brush
= saveBrush
;
1303 void wxWindowDC::SetFont( const wxFont
&font
)
1305 wxCHECK_RET( Ok(), "invalid dc" );
1311 if ((m_oldFont
!= (WXFont
) 0) && ((long) m_oldFont
!= -1))
1313 XSetFont ((Display
*) m_display
, (GC
) m_gc
, (Font
) m_oldFont
);
1315 if (m_window
&& m_window
->GetBackingPixmap())
1316 XSetFont ((Display
*) m_display
,(GC
) m_gcBacking
, (Font
) m_oldFont
);
1321 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1323 Font fontId
= ((XFontStruct
*)pFontStruct
)->fid
;
1324 XSetFont ((Display
*) m_display
, (GC
) m_gc
, fontId
);
1326 if (m_window
&& m_window
->GetBackingPixmap())
1327 XSetFont ((Display
*) m_display
,(GC
) m_gcBacking
, fontId
);
1330 void wxWindowDC::SetPen( const wxPen
&pen
)
1332 wxCHECK_RET( Ok(), "invalid dc" );
1338 wxBitmap oldStipple
= m_currentStipple
;
1339 int oldStyle
= m_currentStyle
;
1340 int oldFill
= m_currentFill
;
1341 int old_pen_width
= m_currentPenWidth
;
1342 int old_pen_join
= m_currentPenJoin
;
1343 int old_pen_cap
= m_currentPenCap
;
1344 int old_pen_nb_dash
= m_currentPenDashCount
;
1345 char *old_pen_dash
= m_currentPenDash
;
1347 wxColour oldPenColour
= m_currentColour
;
1348 m_currentColour
= m_pen
.GetColour ();
1349 m_currentStyle
= m_pen
.GetStyle ();
1350 m_currentFill
= m_pen
.GetStyle (); // TODO?
1351 m_currentPenWidth
= m_pen
.GetWidth ();
1352 m_currentPenJoin
= m_pen
.GetJoin ();
1353 m_currentPenCap
= m_pen
.GetCap ();
1354 m_currentPenDashCount
= m_pen
.GetDashCount();
1355 m_currentPenDash
= m_pen
.GetDash();
1357 if (m_currentStyle
== wxSTIPPLE
)
1358 m_currentStipple
= * m_pen
.GetStipple ();
1360 bool sameStyle
= (oldStyle
== m_currentStyle
&&
1361 oldFill
== m_currentFill
&&
1362 old_pen_join
== m_currentPenJoin
&&
1363 old_pen_cap
== m_currentPenCap
&&
1364 old_pen_nb_dash
== m_currentPenDashCount
&&
1365 old_pen_dash
== m_currentPenDash
&&
1366 old_pen_width
== m_currentPenWidth
);
1368 bool sameColour
= (oldPenColour
.Ok () &&
1369 (oldPenColour
.Red () == m_currentColour
.Red ()) &&
1370 (oldPenColour
.Blue () == m_currentColour
.Blue ()) &&
1371 (oldPenColour
.Green () == m_currentColour
.Green ()) &&
1372 (oldPenColour
.GetPixel() == m_currentColour
.GetPixel()));
1374 if (!sameStyle
|| !GetOptimization())
1376 int scaled_width
= (int) XLOG2DEVREL (m_pen
.GetWidth ());
1377 if (scaled_width
< 0)
1383 const static char dotted
[] = {2, 5};
1384 const static char short_dashed
[] = {4, 4};
1385 const static char long_dashed
[] = {4, 8};
1386 const static char dotted_dashed
[] = {6, 6, 2, 6};
1388 // We express dash pattern in pen width unit, so we are
1389 // independent of zoom factor and so on...
1391 const char *req_dash
;
1393 switch (m_pen
.GetStyle ())
1396 req_nb_dash
= m_currentPenDashCount
;
1397 req_dash
= m_currentPenDash
;
1398 style
= LineOnOffDash
;
1403 style
= LineOnOffDash
;
1407 req_dash
= short_dashed
;
1408 style
= LineOnOffDash
;
1412 req_dash
= long_dashed
;
1413 style
= LineOnOffDash
;
1417 req_dash
= dotted_dashed
;
1418 style
= LineOnOffDash
;
1429 if (req_dash
&& req_nb_dash
)
1431 char *real_req_dash
= new char[req_nb_dash
];
1434 int factor
= scaled_width
== 0 ? 1 : scaled_width
;
1435 for (int i
= 0; i
< req_nb_dash
; i
++)
1436 real_req_dash
[i
] = req_dash
[i
] * factor
;
1437 XSetDashes ((Display
*) m_display
, (GC
) m_gc
, 0, real_req_dash
, req_nb_dash
);
1439 if (m_window
&& m_window
->GetBackingPixmap())
1440 XSetDashes ((Display
*) m_display
,(GC
) m_gcBacking
, 0, real_req_dash
, req_nb_dash
);
1441 delete[]real_req_dash
;
1445 // No Memory. We use non-scaled dash pattern...
1446 XSetDashes ((Display
*) m_display
, (GC
) m_gc
, 0, req_dash
, req_nb_dash
);
1448 if (m_window
&& m_window
->GetBackingPixmap())
1449 XSetDashes ((Display
*) m_display
,(GC
) m_gcBacking
, 0, req_dash
, req_nb_dash
);
1453 switch (m_pen
.GetCap ())
1455 case wxCAP_PROJECTING
:
1456 cap
= CapProjecting
;
1463 cap
= (scaled_width
<= 1) ? CapNotLast
: CapRound
;
1467 switch (m_pen
.GetJoin ())
1481 XSetLineAttributes ((Display
*) m_display
, (GC
) m_gc
, scaled_width
, style
, cap
, join
);
1483 if (m_window
&& m_window
->GetBackingPixmap())
1484 XSetLineAttributes ((Display
*) m_display
,(GC
) m_gcBacking
, scaled_width
, style
, cap
, join
);
1487 if (IS_HATCH(m_currentFill
) && ((m_currentFill
!= oldFill
) || !GetOptimization()))
1491 oldStipple
= wxNullBitmap
; // For later reset!!
1493 switch (m_currentFill
)
1495 case wxBDIAGONAL_HATCH
:
1496 if (bdiag
== (Pixmap
) 0)
1497 bdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1498 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1499 bdiag_bits
, bdiag_width
, bdiag_height
);
1502 case wxFDIAGONAL_HATCH
:
1503 if (fdiag
== (Pixmap
) 0)
1504 fdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1505 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1506 fdiag_bits
, fdiag_width
, fdiag_height
);
1510 if (cross
== (Pixmap
) 0)
1511 cross
= XCreateBitmapFromData ((Display
*) m_display
,
1512 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1513 cross_bits
, cross_width
, cross_height
);
1516 case wxHORIZONTAL_HATCH
:
1517 if (horiz
== (Pixmap
) 0)
1518 horiz
= XCreateBitmapFromData ((Display
*) m_display
,
1519 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1520 horiz_bits
, horiz_width
, horiz_height
);
1523 case wxVERTICAL_HATCH
:
1524 if (verti
== (Pixmap
) 0)
1525 verti
= XCreateBitmapFromData ((Display
*) m_display
,
1526 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1527 verti_bits
, verti_width
, verti_height
);
1530 case wxCROSSDIAG_HATCH
:
1532 if (cdiag
== (Pixmap
) 0)
1533 cdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1534 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1535 cdiag_bits
, cdiag_width
, cdiag_height
);
1539 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, myStipple
);
1541 if (m_window
&& m_window
->GetBackingPixmap())
1542 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, myStipple
);
1544 else if (m_currentStipple
.Ok()
1545 && ((m_currentStipple
!= oldStipple
) || !GetOptimization()))
1547 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) m_currentStipple
.GetPixmap());
1549 if (m_window
&& m_window
->GetBackingPixmap())
1550 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, (Pixmap
) m_currentStipple
.GetPixmap());
1553 if ((m_currentFill
!= oldFill
) || !GetOptimization())
1557 if (m_currentFill
== wxSTIPPLE
)
1558 fill_style
= FillStippled
;
1559 else if (IS_HATCH (m_currentFill
))
1560 fill_style
= FillStippled
;
1562 fill_style
= FillSolid
;
1563 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, fill_style
);
1564 if (m_window
&& m_window
->GetBackingPixmap())
1565 XSetFillStyle ((Display
*) m_display
,(GC
) m_gcBacking
, fill_style
);
1568 // must test m_logicalFunction, because it involves background!
1569 if (!sameColour
|| !GetOptimization()
1570 || ((m_logicalFunction
== wxXOR
) || (m_autoSetting
& 0x2)))
1573 if (m_pen
.GetStyle () == wxTRANSPARENT
)
1574 pixel
= m_backgroundPixel
;
1577 unsigned char red
= m_pen
.GetColour ().Red ();
1578 unsigned char blue
= m_pen
.GetColour ().Blue ();
1579 unsigned char green
= m_pen
.GetColour ().Green ();
1580 if (red
== (unsigned char) 255 && blue
== (unsigned char) 255
1581 && green
== (unsigned char) 255)
1583 pixel
= (int) WhitePixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1584 m_currentColour
= *wxWHITE
;
1585 m_pen
.GetColour().SetPixel(pixel
);
1586 m_currentColour
.SetPixel(pixel
);
1590 pixel
= (int) BlackPixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1591 m_currentColour
= *wxBLACK
;
1592 m_pen
.GetColour().SetPixel(pixel
);
1597 pixel
= m_pen
.GetColour ().AllocColour(m_display
);
1598 m_currentColour
.SetPixel(pixel
);
1601 // Finally, set the GC to the required colour
1604 if (m_logicalFunction
== wxXOR
)
1607 XGetGCValues ((Display
*) m_display
, (GC
) m_gc
, GCBackground
, &values
);
1608 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
^ values
.background
);
1609 if (m_window
&& m_window
->GetBackingPixmap())
1610 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
^ values
.background
);
1614 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1615 if (m_window
&& m_window
->GetBackingPixmap())
1616 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1621 m_pen
.GetColour().SetPixel(oldPenColour
.GetPixel());
1626 void wxWindowDC::SetBrush( const wxBrush
&brush
)
1628 wxCHECK_RET( Ok(), "invalid dc" );
1632 if (!m_brush
.Ok() || m_brush
.GetStyle () == wxTRANSPARENT
)
1635 int oldFill
= m_currentFill
;
1636 wxBitmap oldStipple
= m_currentStipple
;
1638 m_autoSetting
|= 0x1;
1640 m_currentFill
= m_brush
.GetStyle ();
1641 if (m_currentFill
== wxSTIPPLE
)
1642 m_currentStipple
= * m_brush
.GetStipple ();
1644 wxColour
oldBrushColour(m_currentColour
);
1645 m_currentColour
= m_brush
.GetColour ();
1647 bool sameColour
= (oldBrushColour
.Ok () &&
1648 (oldBrushColour
.Red () == m_currentColour
.Red ()) &&
1649 (oldBrushColour
.Blue () == m_currentColour
.Blue ()) &&
1650 (oldBrushColour
.Green () == m_currentColour
.Green ()) &&
1651 (oldBrushColour
.GetPixel() == m_currentColour
.GetPixel()));
1653 if ((oldFill
!= m_brush
.GetStyle ()) || !GetOptimization())
1655 switch (brush
.GetStyle ())
1659 case wxBDIAGONAL_HATCH
:
1660 case wxCROSSDIAG_HATCH
:
1661 case wxFDIAGONAL_HATCH
:
1663 case wxHORIZONTAL_HATCH
:
1664 case wxVERTICAL_HATCH
:
1667 // Chris Breeze 23/07/97: use background mode to determine whether
1668 // fill style should be solid or transparent
1669 int style
= (m_backgroundMode
== wxSOLID
? FillOpaqueStippled
: FillStippled
);
1670 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, style
);
1671 if (m_window
&& m_window
->GetBackingPixmap())
1672 XSetFillStyle ((Display
*) m_display
,(GC
) m_gcBacking
, style
);
1677 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, FillSolid
);
1678 if (m_window
&& m_window
->GetBackingPixmap())
1679 XSetFillStyle ((Display
*) m_display
,(GC
) m_gcBacking
, FillSolid
);
1683 if (IS_HATCH(m_currentFill
) && ((m_currentFill
!= oldFill
) || !GetOptimization()))
1687 switch (m_currentFill
)
1689 case wxBDIAGONAL_HATCH
:
1690 if (bdiag
== (Pixmap
) 0)
1691 bdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1692 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1693 bdiag_bits
, bdiag_width
, bdiag_height
);
1696 case wxFDIAGONAL_HATCH
:
1697 if (fdiag
== (Pixmap
) 0)
1698 fdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1699 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1700 fdiag_bits
, fdiag_width
, fdiag_height
);
1704 if (cross
== (Pixmap
) 0)
1705 cross
= XCreateBitmapFromData ((Display
*) m_display
,
1706 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1707 cross_bits
, cross_width
, cross_height
);
1710 case wxHORIZONTAL_HATCH
:
1711 if (horiz
== (Pixmap
) 0)
1712 horiz
= XCreateBitmapFromData ((Display
*) m_display
,
1713 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1714 horiz_bits
, horiz_width
, horiz_height
);
1717 case wxVERTICAL_HATCH
:
1718 if (verti
== (Pixmap
) 0)
1719 verti
= XCreateBitmapFromData ((Display
*) m_display
,
1720 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1721 verti_bits
, verti_width
, verti_height
);
1724 case wxCROSSDIAG_HATCH
:
1726 if (cdiag
== (Pixmap
) 0)
1727 cdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1728 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1729 cdiag_bits
, cdiag_width
, cdiag_height
);
1733 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, myStipple
);
1735 if (m_window
&& m_window
->GetBackingPixmap())
1736 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, myStipple
);
1738 // X can forget the stipple value when resizing a window (apparently)
1739 // so always set the stipple.
1740 else if (m_currentStipple
.Ok()) // && m_currentStipple != oldStipple)
1742 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) m_currentStipple
.GetPixmap());
1743 if (m_window
&& m_window
->GetBackingPixmap())
1744 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, (Pixmap
) m_currentStipple
.GetPixmap());
1747 // must test m_logicalFunction, because it involves background!
1748 if (!sameColour
|| !GetOptimization() || m_logicalFunction
== wxXOR
)
1753 // Policy - on a monochrome screen, all brushes are white,
1754 // except when they're REALLY black!!!
1755 unsigned char red
= m_brush
.GetColour ().Red ();
1756 unsigned char blue
= m_brush
.GetColour ().Blue ();
1757 unsigned char green
= m_brush
.GetColour ().Green ();
1759 if (red
== (unsigned char) 0 && blue
== (unsigned char) 0
1760 && green
== (unsigned char) 0)
1762 pixel
= (int) BlackPixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1763 m_currentColour
= *wxBLACK
;
1764 m_brush
.GetColour().SetPixel(pixel
);
1765 m_currentColour
.SetPixel(pixel
);
1769 pixel
= (int) WhitePixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1770 m_currentColour
= *wxWHITE
;
1771 m_brush
.GetColour().SetPixel(pixel
);
1772 m_currentColour
.SetPixel(pixel
);
1775 // N.B. comment out the above line and uncomment the following lines
1776 // if you want non-white colours to be black on a monochrome display.
1778 if (red == (unsigned char )255 && blue == (unsigned char)255
1779 && green == (unsigned char)255)
1780 pixel = (int)WhitePixel((Display*) m_display, DefaultScreen((Display*) m_display));
1782 pixel = (int)BlackPixel((Display*) m_display, DefaultScreen((Display*) m_display));
1785 else if (m_brush
.GetStyle () != wxTRANSPARENT
)
1787 pixel
= m_brush
.GetColour().AllocColour(m_display
);
1788 m_currentColour
.SetPixel(pixel
);
1792 // Finally, set the GC to the required colour
1793 if (m_logicalFunction
== wxXOR
)
1796 XGetGCValues ((Display
*) m_display
, (GC
) m_gc
, GCBackground
, &values
);
1797 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
^ values
.background
);
1798 if (m_window
&& m_window
->GetBackingPixmap())
1799 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
^ values
.background
);
1803 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1804 if (m_window
&& m_window
->GetBackingPixmap())
1805 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1810 m_brush
.GetColour().SetPixel(oldBrushColour
.GetPixel());
1813 void wxWindowDC::SetBackground( const wxBrush
&brush
)
1815 wxCHECK_RET( Ok(), "invalid dc" );
1817 m_backgroundBrush
= brush
;
1819 if (!m_backgroundBrush
.Ok())
1822 int pixel
= m_backgroundBrush
.GetColour().AllocColour(m_display
);
1824 // New behaviour, 10/2/99: setting the background brush of a DC
1825 // doesn't affect the window background colour.
1827 // XSetWindowBackground doesn't work for non-Window pixmaps
1828 if (!this->IsKindOf(CLASSINFO(wxMemoryDC)))
1829 XSetWindowBackground ((Display*) m_display, (Pixmap) m_pixmap, pixel);
1832 // Necessary for ::DrawIcon, which use fg/bg pixel or the GC.
1833 // And Blit,... (Any fct that use XCopyPlane, in fact.)
1834 XSetBackground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1835 if (m_window
&& m_window
->GetBackingPixmap())
1836 XSetBackground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1839 void wxWindowDC::SetLogicalFunction( int function
)
1841 wxCHECK_RET( Ok(), "invalid dc" );
1846 if (m_logicalFunction
== function
)
1852 x_function
= GXclear
;
1858 x_function
= GXinvert
;
1861 x_function
= GXorReverse
;
1864 x_function
= GXandReverse
;
1873 x_function
= GXandInverted
;
1876 x_function
= GXnoop
;
1882 x_function
= GXequiv
;
1885 x_function
= GXcopyInverted
;
1888 x_function
= GXorInverted
;
1891 x_function
= GXnand
;
1898 x_function
= GXcopy
;
1902 XSetFunction((Display
*) m_display
, (GC
) m_gc
, x_function
);
1903 if (m_window
&& m_window
->GetBackingPixmap())
1904 XSetFunction((Display
*) m_display
, (GC
) m_gcBacking
, x_function
);
1906 if ((m_logicalFunction
== wxXOR
) != (function
== wxXOR
))
1907 /* MATTHEW: [9] Need to redo pen simply */
1908 m_autoSetting
|= 0x2;
1910 m_logicalFunction
= function
;
1914 void wxWindowDC::SetTextForeground( const wxColour
&col
)
1916 wxCHECK_RET( Ok(), "invalid dc" );
1918 if (m_textForegroundColour
== col
)
1921 m_textForegroundColour
= col
;
1925 void wxWindowDC::SetTextBackground( const wxColour
&col
)
1927 wxCHECK_RET( Ok(), "invalid dc" );
1929 if (m_textBackgroundColour
== col
)
1932 m_textBackgroundColour
= col
;
1933 if (!m_textBackgroundColour
.Ok())
1937 void wxWindowDC::SetBackgroundMode( int mode
)
1939 m_backgroundMode
= mode
;
1942 void wxWindowDC::SetPalette( const wxPalette
& palette
)
1947 /* Use GetXColormap */
1948 XSetWindowColormap ((Display
*) m_display
, (Window
) m_window
->GetXWindow(),
1949 (Colormap
) palette
.GetXColormap());
1951 /* Use wxGetMainColormap */
1952 XSetWindowColormap ((Display
*) m_display
, (Window
) m_window
->GetXWindow(),
1953 (Colormap
) wxTheApp
->GetMainColormap(m_display
));
1958 void wxWindowDC::SetDCClipping()
1960 // m_userRegion is the region set by calling SetClippingRegion
1962 if (m_currentRegion
)
1963 XDestroyRegion ((Region
) m_currentRegion
);
1965 // We need to take into account
1966 // clipping imposed on a window by a repaint.
1967 // We'll combine it with the user region. But for now,
1968 // just use the currently-defined user clipping region.
1969 if (m_userRegion
|| (m_window
&& m_window
->GetUpdateRegion().Ok()) )
1970 m_currentRegion
= (WXRegion
) XCreateRegion ();
1972 m_currentRegion
= (WXRegion
) NULL
;
1974 if ((m_window
&& m_window
->GetUpdateRegion().Ok()) && m_userRegion
)
1975 XIntersectRegion ((Region
) m_window
->GetUpdateRegion().GetXRegion(), (Region
) m_userRegion
, (Region
) m_currentRegion
);
1976 else if (m_userRegion
)
1977 XIntersectRegion ((Region
) m_userRegion
, (Region
) m_userRegion
, (Region
) m_currentRegion
);
1978 else if (m_window
&& m_window
->GetUpdateRegion().Ok())
1979 XIntersectRegion ((Region
) m_window
->GetUpdateRegion().GetXRegion(), (Region
) m_window
->GetUpdateRegion().GetXRegion(),
1980 (Region
) m_currentRegion
);
1982 if (m_currentRegion
)
1984 XSetRegion ((Display
*) m_display
, (GC
) m_gc
, (Region
) m_currentRegion
);
1988 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
1993 void wxWindowDC::DoSetClippingRegion( long x
, long y
, long width
, long height
)
1995 wxDC::DoSetClippingRegion( x
, y
, width
, height
);
1998 XDestroyRegion ((Region
) m_userRegion
);
1999 m_userRegion
= (WXRegion
) XCreateRegion ();
2003 r
.width
= XLOG2DEVREL(width
);
2004 r
.height
= YLOG2DEVREL(height
);
2005 XUnionRectWithRegion (&r
, (Region
) m_userRegion
, (Region
) m_userRegion
);
2009 // Needs to work differently for Pixmap: without this,
2010 // there's a nasty (Display*) m_display bug. 8/12/94
2011 if (m_window
&& m_window
->GetBackingPixmap())
2013 XRectangle rects
[1];
2014 rects
[0].x
= XLOG2DEV_2(x
);
2015 rects
[0].y
= YLOG2DEV_2(y
);
2016 rects
[0].width
= XLOG2DEVREL(width
);
2017 rects
[0].height
= YLOG2DEVREL(height
);
2018 XSetClipRectangles((Display
*) m_display
, (GC
) m_gcBacking
, 0, 0, rects
, 1, Unsorted
);
2022 void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion
& region
)
2024 wxRect box
= region
.GetBox();
2026 wxDC::DoSetClippingRegion( box
.x
, box
.y
, box
.width
, box
.height
);
2029 XDestroyRegion ((Region
) m_userRegion
);
2030 m_userRegion
= (WXRegion
) XCreateRegion ();
2032 XUnionRegion((Region
) m_userRegion
, (Region
) region
.GetXRegion(), (Region
) m_userRegion
);
2036 // Needs to work differently for Pixmap: without this,
2037 // there's a nasty (Display*) m_display bug. 8/12/94
2038 if (m_window
&& m_window
->GetBackingPixmap())
2040 XRectangle rects
[1];
2041 rects
[0].x
= XLOG2DEV_2(box
.x
);
2042 rects
[0].y
= YLOG2DEV_2(box
.y
);
2043 rects
[0].width
= XLOG2DEVREL(box
.width
);
2044 rects
[0].height
= YLOG2DEVREL(box
.height
);
2045 XSetClipRectangles((Display
*) m_display
, (GC
) m_gcBacking
, 0, 0, rects
, 1, Unsorted
);
2050 void wxWindowDC::DestroyClippingRegion()
2052 wxDC::DestroyClippingRegion();
2055 XDestroyRegion ((Region
) m_userRegion
);
2056 m_userRegion
= NULL
;
2061 gc_val
.clip_mask
= None
;
2062 if (m_window
&& m_window
->GetBackingPixmap())
2063 XChangeGC((Display
*) m_display
, (GC
) m_gcBacking
, GCClipMask
, &gc_val
);
2066 // Resolution in pixels per logical inch
2067 wxSize
wxWindowDC::GetPPI() const
2069 return wxSize(100, 100);
2072 int wxWindowDC::GetDepth() const
2079 // ----------------------------------- spline code ----------------------------------------
2081 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
,
2082 double a3
, double b3
, double a4
, double b4
);
2083 void wx_clear_stack();
2084 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
, double *x3
,
2085 double *y3
, double *x4
, double *y4
);
2086 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
,
2087 double x4
, double y4
);
2088 static bool wx_spline_add_point(double x
, double y
);
2089 static void wx_spline_draw_point_array(wxDC
*dc
);
2091 wxList wx_spline_point_list
;
2093 #define half(z1, z2) ((z1+z2)/2.0)
2096 /* iterative version */
2098 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
, double a3
, double b3
, double a4
,
2101 register double xmid
, ymid
;
2102 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
2105 wx_spline_push(a1
, b1
, a2
, b2
, a3
, b3
, a4
, b4
);
2107 while (wx_spline_pop(&x1
, &y1
, &x2
, &y2
, &x3
, &y3
, &x4
, &y4
)) {
2108 xmid
= (double)half(x2
, x3
);
2109 ymid
= (double)half(y2
, y3
);
2110 if (fabs(x1
- xmid
) < THRESHOLD
&& fabs(y1
- ymid
) < THRESHOLD
&&
2111 fabs(xmid
- x4
) < THRESHOLD
&& fabs(ymid
- y4
) < THRESHOLD
) {
2112 wx_spline_add_point( x1
, y1
);
2113 wx_spline_add_point( xmid
, ymid
);
2115 wx_spline_push(xmid
, ymid
, (double)half(xmid
, x3
), (double)half(ymid
, y3
),
2116 (double)half(x3
, x4
), (double)half(y3
, y4
), x4
, y4
);
2117 wx_spline_push(x1
, y1
, (double)half(x1
, x2
), (double)half(y1
, y2
),
2118 (double)half(x2
, xmid
), (double)half(y2
, ymid
), xmid
, ymid
);
2123 /* utilities used by spline drawing routines */
2125 typedef struct wx_spline_stack_struct
{
2126 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
2129 #define SPLINE_STACK_DEPTH 20
2130 static Stack wx_spline_stack
[SPLINE_STACK_DEPTH
];
2131 static Stack
*wx_stack_top
;
2132 static int wx_stack_count
;
2134 void wx_clear_stack()
2136 wx_stack_top
= wx_spline_stack
;
2140 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
, double x4
, double y4
)
2142 wx_stack_top
->x1
= x1
;
2143 wx_stack_top
->y1
= y1
;
2144 wx_stack_top
->x2
= x2
;
2145 wx_stack_top
->y2
= y2
;
2146 wx_stack_top
->x3
= x3
;
2147 wx_stack_top
->y3
= y3
;
2148 wx_stack_top
->x4
= x4
;
2149 wx_stack_top
->y4
= y4
;
2154 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
,
2155 double *x3
, double *y3
, double *x4
, double *y4
)
2157 if (wx_stack_count
== 0)
2161 *x1
= wx_stack_top
->x1
;
2162 *y1
= wx_stack_top
->y1
;
2163 *x2
= wx_stack_top
->x2
;
2164 *y2
= wx_stack_top
->y2
;
2165 *x3
= wx_stack_top
->x3
;
2166 *y3
= wx_stack_top
->y3
;
2167 *x4
= wx_stack_top
->x4
;
2168 *y4
= wx_stack_top
->y4
;
2172 static bool wx_spline_add_point(double x
, double y
)
2174 wxPoint
*point
= new wxPoint
;
2177 wx_spline_point_list
.Append((wxObject
*)point
);
2181 static void wx_spline_draw_point_array(wxDC
*dc
)
2183 dc
->DrawLines(&wx_spline_point_list
, 0, 0 );
2184 wxNode
*node
= wx_spline_point_list
.First();
2187 wxPoint
*point
= (wxPoint
*)node
->Data();
2190 node
= wx_spline_point_list
.First();
2194 void wxWindowDC::DoDrawSpline( wxList
*points
)
2196 wxCHECK_RET( Ok(), _T("invalid window dc") );
2199 double cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
;
2200 double x1
, y1
, x2
, y2
;
2202 wxNode
*node
= points
->First();
2203 p
= (wxPoint
*)node
->Data();
2208 node
= node
->Next();
2209 p
= (wxPoint
*)node
->Data();
2213 cx1
= (double)((x1
+ x2
) / 2);
2214 cy1
= (double)((y1
+ y2
) / 2);
2215 cx2
= (double)((cx1
+ x2
) / 2);
2216 cy2
= (double)((cy1
+ y2
) / 2);
2218 wx_spline_add_point(x1
, y1
);
2220 while ((node
= node
->Next()) != NULL
)
2222 p
= (wxPoint
*)node
->Data();
2227 cx4
= (double)(x1
+ x2
) / 2;
2228 cy4
= (double)(y1
+ y2
) / 2;
2229 cx3
= (double)(x1
+ cx4
) / 2;
2230 cy3
= (double)(y1
+ cy4
) / 2;
2232 wx_quadratic_spline(cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
);
2236 cx2
= (double)(cx1
+ x2
) / 2;
2237 cy2
= (double)(cy1
+ y2
) / 2;
2240 wx_spline_add_point( cx1
, cy1
);
2241 wx_spline_add_point( x2
, y2
);
2243 wx_spline_draw_point_array( this );
2246 #endif // wxUSE_SPLINE
2250 // ----------------------------------------------------------------------------
2252 // ----------------------------------------------------------------------------
2254 wxPaintDC::wxPaintDC(wxWindow
* win
) : wxWindowDC(win
)
2256 wxRegion
* region
= NULL
;
2258 // Combine all the update rects into a region
2259 const wxRectList
& updateRects(win
->GetUpdateRects());
2260 if ( updateRects
.GetCount() != 0 )
2262 for ( wxRectList::Node
*node
= updateRects
.GetFirst();
2264 node
= node
->GetNext() )
2266 wxRect
* rect
= node
->GetData();
2269 region
= new wxRegion(*rect
);
2271 // TODO: is this correct? In SetDCClipping above,
2272 // XIntersectRegion is used to combine paint and user
2273 // regions. XIntersectRegion appears to work in that case...
2274 region
->Union(*rect
);
2280 win
->GetClientSize(&cw
, &ch
);
2281 region
= new wxRegion(wxRect(0, 0, cw
, ch
));
2284 win
->SetUpdateRegion(*region
);
2286 // Set the clipping region. Any user-defined region will be combined with this
2287 // one in SetDCClipping.
2288 XSetRegion ((Display
*) m_display
, (GC
) m_gc
, (Region
) region
->GetXRegion());
2293 wxPaintDC::~wxPaintDC()
2295 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
2297 m_window
->ClearUpdateRegion();
2300 // ----------------------------------------------------------------------------
2301 // private functions
2302 // ----------------------------------------------------------------------------
2305 Used when copying between drawables on different (Display*) m_displays. Not
2306 very fast, but better than giving up.
2309 static void XCopyRemote(Display
*src_display
, Display
*dest_display
,
2310 Drawable src
, Drawable dest
,
2313 unsigned int w
, unsigned int h
,
2314 int destx
, int desty
,
2315 bool more
, XImage
**cache
)
2317 XImage
*image
, *destimage
;
2318 Colormap destcm
, srccm
;
2319 static const int CACHE_SIZE
= 256;
2322 unsigned long cachesrc
[CACHE_SIZE
], cachedest
[CACHE_SIZE
];
2323 int k
, cache_pos
, all_cache
;
2325 if (!cache
|| !*cache
)
2326 image
= XGetImage(src_display
, src
, srcx
, srcy
, w
, h
, AllPlanes
, ZPixmap
);
2330 destimage
= XGetImage(dest_display
, dest
, destx
, desty
, w
, h
, AllPlanes
, ZPixmap
);
2332 srccm
= (Colormap
) wxTheApp
->GetMainColormap((WXDisplay
*) src_display
);
2333 destcm
= (Colormap
) wxTheApp
->GetMainColormap((WXDisplay
*) dest_display
);
2338 for (i
= 0; i
< w
; i
++)
2339 for (j
= 0; j
< h
; j
++) {
2340 unsigned long pixel
;
2343 pixel
= XGetPixel(image
, i
, j
);
2344 for (k
= cache_pos
; k
--; )
2345 if (cachesrc
[k
] == pixel
) {
2346 pixel
= cachedest
[k
];
2350 for (k
= CACHE_SIZE
; k
-- > cache_pos
; )
2351 if (cachesrc
[k
] == pixel
) {
2352 pixel
= cachedest
[k
];
2356 cachesrc
[cache_pos
] = xcol
.pixel
= pixel
;
2357 XQueryColor(src_display
, srccm
, &xcol
);
2358 if (!XAllocColor(dest_display
, destcm
, &xcol
))
2360 cachedest
[cache_pos
] = pixel
= xcol
.pixel
;
2362 if (++cache_pos
>= CACHE_SIZE
) {
2368 XPutPixel(destimage
, i
, j
, pixel
);
2371 XPutImage(dest_display
, dest
, destgc
, destimage
, 0, 0, destx
, desty
, w
, h
);
2372 XDestroyImage(destimage
);
2377 XDestroyImage(image
);
2382 /* Helper function for 16-bit fonts */
2383 static int str16len(const char *s
)
2387 while (s
[0] && s
[1]) {