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"
52 #pragma message disable nosimpint
56 #pragma message enable nosimpint
59 #include "wx/motif/private.h"
62 #include <float.h> // for M_PI
72 static Pixmap bdiag
, cdiag
, fdiag
, cross
, horiz
, verti
;
74 // ----------------------------------------------------------------------------
76 // ----------------------------------------------------------------------------
78 // Fudge factor (VZ: what??)
81 // ----------------------------------------------------------------------------
83 // ----------------------------------------------------------------------------
85 IMPLEMENT_DYNAMIC_CLASS(wxClientDC
, wxWindowDC
)
86 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC
, wxWindowDC
)
87 IMPLEMENT_DYNAMIC_CLASS(wxWindowDC
, wxDC
)
89 // ----------------------------------------------------------------------------
91 // ----------------------------------------------------------------------------
93 static void XCopyRemote(Display
*src_display
, Display
*dest_display
,
94 Drawable src
, Drawable dest
,
97 unsigned int w
, unsigned int h
,
99 bool more
, XImage
**cache
);
101 // ============================================================================
103 // ============================================================================
106 * compare two doubles and return the larger rounded
109 static int roundmax(double a
, double b
)
111 return (int)((a
> b
? a
: b
) + 0.5);
115 * compare two doubles and return the smaller rounded
118 static int roundmin(double a
, double b
)
120 return (int)((a
< b
? a
: b
) - 0.5);
124 // ----------------------------------------------------------------------------
126 // ----------------------------------------------------------------------------
128 wxWindowDC::wxWindowDC()
131 m_gcBacking
= (WXGC
) 0;
133 m_backgroundPixel
= -1;
134 m_currentPenWidth
= 1;
135 m_currentPenJoin
= -1;
136 m_currentPenDashCount
= -1;
137 m_currentPenDash
= (char*) NULL
;
140 // m_currentBkMode = wxTRANSPARENT;
141 m_colour
= wxColourDisplay();
142 m_display
= (WXDisplay
*) NULL
;
143 m_currentRegion
= (WXRegion
) 0;
144 m_userRegion
= (WXRegion
) 0;
145 m_pixmap
= (WXPixmap
) 0;
147 m_oldFont
= (WXFont
) 0;
150 wxWindowDC::wxWindowDC( wxWindow
*window
)
152 wxASSERT_MSG( (window
!= (wxWindow
*) NULL
), "You must pass a valid wxWindow to wxWindowDC/wxClientDC/wxPaintDC constructor." );
155 m_font
= window
->GetFont();
157 m_gcBacking
= (WXGC
) 0;
158 m_backgroundPixel
= -1;
159 m_currentPenWidth
= 1;
160 m_currentPenJoin
= -1;
161 m_currentPenDashCount
= -1;
162 m_currentPenDash
= (char*) NULL
;
165 // m_currentBkMode = wxTRANSPARENT;
166 m_colour
= wxColourDisplay();
167 m_currentRegion
= (WXRegion
) 0;
168 m_userRegion
= (WXRegion
) 0;
172 m_display
= window
->GetXDisplay();
173 m_pixmap
= window
->GetXWindow();
174 Display
* display
= (Display
*) m_display
;
176 XSetWindowColormap (display
, (Pixmap
) m_pixmap
, (Colormap
) wxTheApp
->GetMainColormap(m_display
));
179 gcvalues
.foreground
= BlackPixel (display
, DefaultScreen (display
));
180 gcvalues
.background
= WhitePixel (display
, DefaultScreen (display
));
181 gcvalues
.graphics_exposures
= False
;
182 gcvalues
.line_width
= 1;
183 m_gc
= (WXGC
) XCreateGC (display
, RootWindow (display
, DefaultScreen (display
)),
184 GCForeground
| GCBackground
| GCGraphicsExposures
| GCLineWidth
,
187 if (m_window
->GetBackingPixmap())
189 m_gcBacking
= (WXGC
) XCreateGC (display
, RootWindow (display
,
190 DefaultScreen (display
)),
191 GCForeground
| GCBackground
| GCGraphicsExposures
| GCLineWidth
,
195 m_backgroundPixel
= (int) gcvalues
.background
;
197 // Get the current Font so we can set it back later
199 XGetGCValues((Display
*) m_display
, (GC
) m_gc
, GCFont
, &valReturn
);
200 m_oldFont
= (WXFont
) valReturn
.font
;
202 SetBackground(wxBrush(m_window
->GetBackgroundColour(), wxSOLID
));
205 wxWindowDC::~wxWindowDC()
207 if (m_gc
&& (m_oldFont
!= (WXFont
) 0) && ((long) m_oldFont
!= -1))
209 XSetFont ((Display
*) m_display
, (GC
) m_gc
, (Font
) m_oldFont
);
211 if (m_window
&& m_window
->GetBackingPixmap())
212 XSetFont ((Display
*) m_display
,(GC
) m_gcBacking
, (Font
) m_oldFont
);
216 XFreeGC ((Display
*) m_display
, (GC
) m_gc
);
220 XFreeGC ((Display
*) m_display
, (GC
) m_gcBacking
);
221 m_gcBacking
= (WXGC
) 0;
224 XDestroyRegion ((Region
) m_currentRegion
);
225 m_currentRegion
= (WXRegion
) 0;
228 XDestroyRegion ((Region
) m_userRegion
);
229 m_userRegion
= (WXRegion
) 0;
232 void wxWindowDC::DoFloodFill( wxCoord
WXUNUSED(x1
), wxCoord
WXUNUSED(y1
),
233 const wxColour
& WXUNUSED(col
), int WXUNUSED(style
) )
235 wxFAIL_MSG("not implemented");
238 bool wxWindowDC::DoGetPixel( wxCoord x1
, wxCoord y1
, wxColour
*col
) const
240 // Generic (and therefore rather inefficient) method.
241 // Could be improved.
243 wxBitmap
bitmap(1, 1);
244 memdc
.SelectObject(bitmap
);
245 memdc
.Blit(0, 0, 1, 1, (wxDC
*) this, x1
, y1
);
246 memdc
.SelectObject(wxNullBitmap
);
247 wxImage
image(bitmap
);
248 col
->Set(image
.GetRed(0, 0), image
.GetGreen(0, 0), image
.GetBlue(0, 0));
252 void wxWindowDC::DoDrawLine( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
)
254 wxCHECK_RET( Ok(), "invalid dc" );
256 int x1d
, y1d
, x2d
, y2d
;
258 // FreeGetPixelCache();
268 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, x1d
, y1d
, x2d
, y2d
);
270 if (m_window
&& m_window
->GetBackingPixmap())
271 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
272 XLOG2DEV_2(x1
), YLOG2DEV_2(y1
),
273 XLOG2DEV_2(x2
), YLOG2DEV_2(y2
));
275 CalcBoundingBox(x1
, y1
);
276 CalcBoundingBox(x2
, y2
);
279 void wxWindowDC::DoCrossHair( wxCoord x
, wxCoord y
)
281 wxCHECK_RET( Ok(), "invalid dc" );
286 int xx
= XLOG2DEV (x
);
287 int yy
= YLOG2DEV (y
);
289 wxDisplaySize (&ww
, &hh
);
290 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, 0, yy
,
292 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xx
, 0,
295 if (m_window
&& m_window
->GetBackingPixmap())
299 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
302 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
308 void wxWindowDC::DoDrawArc( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
, wxCoord xc
, wxCoord yc
)
310 wxCHECK_RET( Ok(), "invalid dc" );
312 // FreeGetPixelCache();
314 int xx1
= XLOG2DEV (x1
);
315 int yy1
= YLOG2DEV (y1
);
316 int xx2
= XLOG2DEV (x2
);
317 int yy2
= YLOG2DEV (y2
);
318 int xxc
= XLOG2DEV (xc
);
319 int yyc
= YLOG2DEV (yc
);
320 int xxc_2
= XLOG2DEV_2 (xc
);
321 int yyc_2
= YLOG2DEV_2 (yc
);
323 wxCoord dx
= xx1
- xxc
;
324 wxCoord dy
= yy1
- yyc
;
325 double radius
= sqrt (dx
* dx
+ dy
* dy
);
326 wxCoord r
= (wxCoord
) radius
;
328 double radius1
, radius2
;
330 if (xx1
== xx2
&& yy1
== yy2
)
335 else if (radius
== 0.0)
336 radius1
= radius2
= 0.0;
345 radius1
= -atan2 ((double) (yy1
- yyc
), (double) (xx1
- xxc
)) * 360.0 / (2 * M_PI
);
353 radius2
= -atan2 ((double) (yy2
- yyc
), (double) (xx2
- xxc
)) * 360.0 / (2 * M_PI
);
357 int alpha1
= (int) radius1
;
358 int alpha2
= (int) (radius2
- radius1
);
361 while (alpha2
> 360 * 64)
364 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
367 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) (GC
) m_gc
,
368 xxc
- r
, yyc
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
370 if (m_window
&& m_window
->GetBackingPixmap())
371 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
372 xxc_2
- r
, yyc_2
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
376 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
380 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
381 xxc
- r
, yyc
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
383 if (m_window
&& m_window
->GetBackingPixmap())
384 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
385 xxc_2
- r
, yyc_2
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
387 CalcBoundingBox (x1
, y1
);
388 CalcBoundingBox (x2
, y2
);
391 void wxWindowDC::DoDrawEllipticArc( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double sa
, double ea
)
393 wxCHECK_RET( Ok(), "invalid dc" );
399 wd
= XLOG2DEVREL(width
);
400 hd
= YLOG2DEVREL(height
);
402 if (sa
>=360 || sa
<=-360) sa
=sa
-int(sa
/360)*360;
403 if (ea
>=360 || ea
<=-360) ea
=ea
-int(ea
/360)*360;
404 int start
= int(sa
*64);
405 int end
= int(ea
*64);
406 if (start
<0) start
+=360*64;
407 if (end
<0) end
+=360*64;
408 if (end
>start
) end
-=start
;
409 else end
+=360*64-start
;
411 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
413 m_autoSetting
= TRUE
; // must be reset
416 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, start
, end
);
418 if (m_window
&& m_window
->GetBackingPixmap())
419 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
420 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),wd
,hd
,start
,end
);
423 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
427 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, start
,end
);
428 if (m_window
&& m_window
->GetBackingPixmap())
429 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
430 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),wd
,hd
,start
,end
);
432 CalcBoundingBox (x
, y
);
433 CalcBoundingBox (x
+ width
, y
+ height
);
436 void wxWindowDC::DoDrawPoint( wxCoord x
, wxCoord y
)
438 wxCHECK_RET( Ok(), "invalid dc" );
440 // FreeGetPixelCache();
442 if (m_pen
.Ok() && m_autoSetting
)
445 XDrawPoint ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
));
446 if (m_window
&& m_window
->GetBackingPixmap())
447 XDrawPoint ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, XLOG2DEV_2 (x
), YLOG2DEV_2 (y
));
449 CalcBoundingBox (x
, y
);
452 void wxWindowDC::DoDrawLines( int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
)
454 wxCHECK_RET( Ok(), "invalid dc" );
456 // FreeGetPixelCache();
458 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
463 XPoint
*xpoints
= new XPoint
[n
];
466 for (i
= 0; i
< n
; i
++)
468 xpoints
[i
].x
= XLOG2DEV (points
[i
].x
+ xoffset
);
469 xpoints
[i
].y
= YLOG2DEV (points
[i
].y
+ yoffset
);
471 XDrawLines ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xpoints
, n
, 0);
473 if (m_window
&& m_window
->GetBackingPixmap())
475 for (i
= 0; i
< n
; i
++)
477 xpoints
[i
].x
= XLOG2DEV_2 (points
[i
].x
+ xoffset
);
478 xpoints
[i
].y
= YLOG2DEV_2 (points
[i
].y
+ yoffset
);
480 XDrawLines ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, xpoints
, n
, 0);
486 void wxWindowDC::DoDrawPolygon( int n
, wxPoint points
[],
487 wxCoord xoffset
, wxCoord yoffset
, int fillStyle
)
489 wxCHECK_RET( Ok(), "invalid dc" );
491 // FreeGetPixelCache();
493 XPoint
*xpoints1
= new XPoint
[n
+ 1];
494 XPoint
*xpoints2
= new XPoint
[n
+ 1];
496 for (i
= 0; i
< n
; i
++)
498 xpoints1
[i
].x
= XLOG2DEV (points
[i
].x
+ xoffset
);
499 xpoints1
[i
].y
= YLOG2DEV (points
[i
].y
+ yoffset
);
500 xpoints2
[i
].x
= XLOG2DEV_2 (points
[i
].x
+ xoffset
);
501 xpoints2
[i
].y
= YLOG2DEV_2 (points
[i
].y
+ yoffset
);
502 CalcBoundingBox (points
[i
].x
+ xoffset
, points
[i
].y
+ yoffset
);
505 // Close figure for XDrawLines (not needed for XFillPolygon)
506 xpoints1
[i
].x
= xpoints1
[0].x
;
507 xpoints1
[i
].y
= xpoints1
[0].y
;
508 xpoints2
[i
].x
= xpoints2
[0].x
;
509 xpoints2
[i
].y
= xpoints2
[0].y
;
511 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
514 XSetFillRule ((Display
*) m_display
, (GC
) m_gc
, fillStyle
== wxODDEVEN_RULE
? EvenOddRule
: WindingRule
);
515 XFillPolygon ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xpoints1
, n
, Complex
, 0);
516 XSetFillRule ((Display
*) m_display
, (GC
) m_gc
, EvenOddRule
); // default mode
517 if (m_window
&& m_window
->GetBackingPixmap())
519 XSetFillRule ((Display
*) m_display
,(GC
) m_gcBacking
,
520 fillStyle
== wxODDEVEN_RULE
? EvenOddRule
: WindingRule
);
521 XFillPolygon ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, xpoints2
, n
, Complex
, 0);
522 XSetFillRule ((Display
*) m_display
,(GC
) m_gcBacking
, EvenOddRule
); // default mode
526 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
530 XDrawLines ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xpoints1
, n
+ 1, 0);
532 if (m_window
&& m_window
->GetBackingPixmap())
533 XDrawLines ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, xpoints2
, n
+ 1, 0);
540 void wxWindowDC::DoDrawRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
542 wxCHECK_RET( Ok(), "invalid dc" );
544 // FreeGetPixelCache();
546 int xd
, yd
, wfd
, hfd
, wd
, hd
;
550 wfd
= XLOG2DEVREL(width
);
552 hfd
= YLOG2DEVREL(height
);
555 if (wfd
== 0 || hfd
== 0) return;
556 if (wd
< 0) { wd
= - wd
; xd
= xd
- wd
; }
557 if (hd
< 0) { hd
= - hd
; yd
= yd
- hd
; }
559 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
562 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wfd
, hfd
);
564 if (m_window
&& m_window
->GetBackingPixmap())
565 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
566 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
570 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
574 XDrawRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
);
576 if (m_window
&& m_window
->GetBackingPixmap())
577 XDrawRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
578 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
581 CalcBoundingBox (x
, y
);
582 CalcBoundingBox (x
+ width
, y
+ height
);
585 void wxWindowDC::DoDrawRoundedRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double radius
)
587 wxCHECK_RET( Ok(), "invalid dc" );
589 // FreeGetPixelCache();
591 // If radius is negative, it's a proportion of the smaller dimension.
593 if (radius
< 0.0) radius
= - radius
* ((width
< height
) ? width
: height
);
595 int xd
= XLOG2DEV (x
);
596 int yd
= YLOG2DEV (y
);
597 int rd
= XLOG2DEVREL ((long) radius
);
598 int wd
= XLOG2DEVREL (width
) - WX_GC_CF
;
599 int hd
= YLOG2DEVREL (height
) - WX_GC_CF
;
604 // If radius is zero use DrawRectangle() instead to avoid
605 // X drawing errors with small radii
608 DrawRectangle( x
, y
, width
, height
);
612 // Draw nothing if transformed w or h is 0
613 if (wd
== 0 || hd
== 0) return;
615 // CMB: adjust size if outline is drawn otherwise the result is
616 // 1 pixel too wide and high
617 if (m_pen
.GetStyle() != wxTRANSPARENT
)
623 // CMB: ensure dd is not larger than rectangle otherwise we
624 // get an hour glass shape
625 if (rw_d
> wd
) rw_d
= wd
;
626 if (rw_d
> hd
) rw_d
= hd
;
629 // For backing pixmap
630 int xd2
= XLOG2DEV_2 (x
);
631 int yd2
= YLOG2DEV_2 (y
);
632 int rd2
= XLOG2DEVREL ((long) radius
);
633 int wd2
= XLOG2DEVREL (width
) ;
634 int hd2
= YLOG2DEVREL (height
) ;
639 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
643 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ rd
, yd
,
645 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ rd
,
648 // Arcs start from 3 o'clock, positive angles anticlockwise
650 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
,
651 rw_d
, rh_d
, 90 * 64, 90 * 64);
653 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
, yd
,
654 // rw_d, rh_d, 0, 90 * 64);
655 rw_d
, rh_d
, 0, 91 * 64);
657 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
,
659 // rw_d, rh_d, 270 * 64, 90 * 64);
660 rw_d
, rh_d
, 269 * 64, 92 * 64);
662 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ hd
- rh_d
,
663 rw_d
, rh_d
, 180 * 64, 90 * 64);
665 if (m_window
&& m_window
->GetBackingPixmap())
667 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
668 xd2
+ rd2
, yd2
, wd2
- rw_d2
, hd2
);
669 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
670 xd2
, yd2
+ rd2
, wd2
, hd2
- rh_d2
);
672 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
673 xd2
, yd2
, rw_d2
, rh_d2
, 90 * 64, 90 * 64);
674 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
675 xd2
+ wd2
- rw_d2
, yd2
,
676 // rw_d2, rh_d2, 0, 90 * 64);
677 rw_d2
, rh_d2
, 0, 91 * 64);
678 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
681 // rw_d2, rh_d2, 270 * 64, 90 * 64);
682 rw_d2
, rh_d2
, 269 * 64, 92 * 64);
683 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
684 xd2
, yd2
+ hd2
- rh_d2
,
685 rw_d2
, rh_d2
, 180 * 64, 90 * 64);
689 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
692 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ rd
, yd
,
693 xd
+ wd
- rd
+ 1, yd
);
694 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ rd
, yd
+ hd
,
695 xd
+ wd
- rd
, yd
+ hd
);
697 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ rd
,
699 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
, yd
+ rd
,
700 xd
+ wd
, yd
+ hd
- rd
+ 1);
701 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
,
702 rw_d
, rh_d
, 90 * 64, 90 * 64);
703 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
, yd
,
704 // rw_d, rh_d, 0, 90 * 64);
705 rw_d
, rh_d
, 0, 91 * 64);
706 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
,
708 rw_d
, rh_d
, 269 * 64, 92 * 64);
709 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ hd
- rh_d
,
710 rw_d
, rh_d
, 180 * 64, 90 * 64);
712 if (m_window
&& m_window
->GetBackingPixmap())
714 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
716 xd2
+ wd2
- rd2
+ 1, yd2
);
717 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
718 xd2
+ rd2
, yd2
+ hd2
,
719 xd2
+ wd2
- rd2
, yd2
+ hd2
);
721 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
723 xd2
, yd2
+ hd2
- rd2
);
724 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
725 xd2
+ wd2
, yd2
+ rd2
,
726 xd2
+ wd2
, yd2
+ hd2
- rd2
+ 1);
727 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
729 rw_d2
, rh_d2
, 90 * 64, 90 * 64);
730 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
731 xd2
+ wd2
- rw_d2
, yd2
,
732 // rw_d2, rh_d2, 0, 90 * 64);
733 rw_d2
, rh_d2
, 0, 91 * 64);
734 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
737 rw_d2
, rh_d2
, 269 * 64, 92 * 64);
738 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
739 xd2
, yd2
+ hd2
- rh_d2
,
740 rw_d2
, rh_d2
, 180 * 64, 90 * 64);
743 CalcBoundingBox (x
, y
);
744 CalcBoundingBox (x
+ width
, y
+ height
);
749 void wxWindowDC::DoDrawEllipse( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
751 wxCHECK_RET( Ok(), "invalid dc" );
753 // Check for negative width and height
766 // FreeGetPixelCache();
768 static const int angle
= 23040;
774 wd
= XLOG2DEVREL(width
) ;
775 hd
= YLOG2DEVREL(height
) ;
777 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
780 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, 0, angle
);
781 if (m_window
&& m_window
->GetBackingPixmap())
782 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
783 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
784 XLOG2DEVREL (width
) - WX_GC_CF
,
785 YLOG2DEVREL (height
) - WX_GC_CF
, 0, angle
);
788 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
792 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, 0, angle
);
793 if (m_window
&& m_window
->GetBackingPixmap())
794 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
795 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
796 XLOG2DEVREL (width
) - WX_GC_CF
,
797 YLOG2DEVREL (height
) - WX_GC_CF
, 0, angle
);
799 CalcBoundingBox (x
, y
);
800 CalcBoundingBox (x
+ width
, y
+ height
);
804 bool wxWindowDC::CanDrawBitmap() const
806 wxCHECK_MSG( Ok(), FALSE
, "invalid dc" );
812 void wxWindowDC::DoDrawIcon( const wxIcon
&icon
, wxCoord x
, wxCoord y
)
814 // FreeGetPixelCache();
816 // Be sure that foreground pixels (1) of
817 // the Icon will be painted with pen colour. [m_pen.SetColour()]
818 // Background pixels (0) will be painted with
819 // last selected background color. [::SetBackground]
820 if (m_pen
.Ok() && m_autoSetting
)
824 Pixmap iconPixmap
= (Pixmap
) icon
.GetPixmap();
825 width
= icon
.GetWidth();
826 height
= icon
.GetHeight();
827 if (icon
.GetDisplay() == m_display
)
829 if (icon
.GetDepth() <= 1)
831 XCopyPlane ((Display
*) m_display
, iconPixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
833 (int) XLOG2DEV (x
), (int) YLOG2DEV (y
), 1);
837 XCopyArea ((Display
*) m_display
, iconPixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
839 (int) XLOG2DEV (x
), (int) YLOG2DEV (y
));
843 if (m_window
&& m_window
->GetBackingPixmap())
845 if (icon
.GetDepth() <= 1)
847 XCopyPlane ((Display
*) m_display
, iconPixmap
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
848 0, 0, width
, height
, (int) XLOG2DEV_2 (x
), (int) YLOG2DEV_2 (y
), 1);
852 XCopyArea ((Display
*) m_display
, iconPixmap
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
854 (int) XLOG2DEV_2 (x
), (int) YLOG2DEV_2 (y
));
857 } else { /* Remote copy (different (Display*) m_displays) */
858 XImage
*cache
= NULL
;
859 if (m_window
&& m_window
->GetBackingPixmap())
860 XCopyRemote((Display
*) icon
.GetDisplay(), (Display
*) m_display
, iconPixmap
, (Pixmap
) m_window
->GetBackingPixmap(),
861 (GC
) m_gcBacking
, 0, 0, width
, height
,
862 (int) XLOG2DEV_2 (x
), (int) YLOG2DEV_2 (y
), TRUE
, &cache
);
863 XCopyRemote((Display
*) icon
.GetDisplay(), (Display
*) m_display
, iconPixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
865 (int) XLOG2DEV (x
), (int) YLOG2DEV (y
), FALSE
, &cache
);
867 CalcBoundingBox (x
, y
);
871 // TODO: use scaled Blit e.g. as per John Price's implementation in Contrib/Utilities
872 bool wxWindowDC::DoBlit( wxCoord xdest
, wxCoord ydest
, wxCoord width
, wxCoord height
,
873 wxDC
*source
, wxCoord xsrc
, wxCoord ysrc
, int rop
, bool useMask
)
875 wxCHECK_MSG( Ok(), FALSE
, "invalid dc" );
877 wxWindowDC
* sourceDC
= wxDynamicCast(source
, wxWindowDC
);
879 wxASSERT_MSG( sourceDC
, "Blit source DC must be wxWindowDC or derived class." );
881 // FreeGetPixelCache();
883 // Be sure that foreground pixels (1) of the Icon will be painted with pen
884 // colour. [m_pen.SetColour()] Background pixels (0) will be painted with
885 // last selected background color. [::SetBackground]
886 if (m_pen
.Ok() && m_autoSetting
)
889 // Do bitmap scaling if necessary
891 wxBitmap
*scaledBitmap
= (wxBitmap
*) NULL
;
892 Pixmap sourcePixmap
= (Pixmap
) NULL
;
893 double scaleX
, scaleY
;
894 GetUserScale(& scaleX
, & scaleY
);
896 // Sorry, can't scale masks just yet
897 if (!useMask
&& (scaleX
!= 1.0 || scaleY
!= 1.0) && sourceDC
->IsKindOf(CLASSINFO(wxMemoryDC
)))
899 wxMemoryDC
* memDC
= (wxMemoryDC
*) sourceDC
;
900 wxBitmap
& bitmap
= memDC
->GetBitmap();
902 wxASSERT_MSG( (bitmap
.Ok()), "Bad source bitmap in wxWindowDC::Blit");
904 wxImage
image(bitmap
);
907 sourcePixmap
= (Pixmap
) bitmap
.GetPixmap();
911 int scaledW
= (int) (bitmap
.GetWidth() * scaleX
);
912 int scaledH
= (int) (bitmap
.GetHeight() * scaleY
);
914 image
= image
.Scale(scaledW
, scaledH
);
915 scaledBitmap
= new wxBitmap(image
.ConvertToBitmap());
916 sourcePixmap
= (Pixmap
) scaledBitmap
->GetPixmap();
920 sourcePixmap
= (Pixmap
) sourceDC
->m_pixmap
;
922 if (m_pixmap
&& sourcePixmap
)
925 int orig
= m_logicalFunction
;
927 SetLogicalFunction (rop
);
929 if (m_display
!= sourceDC
->m_display
)
931 XImage
*cache
= NULL
;
933 if (m_window
&& m_window
->GetBackingPixmap())
934 XCopyRemote((Display
*) sourceDC
->m_display
, (Display
*) m_display
,
935 (Pixmap
) sourcePixmap
, (Pixmap
) m_window
->GetBackingPixmap(),
937 source
->LogicalToDeviceX (xsrc
),
938 source
->LogicalToDeviceY (ysrc
),
939 source
->LogicalToDeviceXRel(width
),
940 source
->LogicalToDeviceYRel(height
),
941 XLOG2DEV_2 (xdest
), YLOG2DEV_2 (ydest
),
944 if ( useMask
&& source
->IsKindOf(CLASSINFO(wxMemoryDC
)) )
946 wxMemoryDC
*memDC
= (wxMemoryDC
*)source
;
947 wxBitmap
& sel
= memDC
->GetBitmap();
948 if ( sel
.Ok() && sel
.GetMask() && sel
.GetMask()->GetPixmap() )
950 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) sel
.GetMask()->GetPixmap());
951 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, XLOG2DEV (xdest
), YLOG2DEV (ydest
));
955 XCopyRemote((Display
*) sourceDC
->m_display
, (Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
956 source
->LogicalToDeviceX (xsrc
),
957 source
->LogicalToDeviceY (ysrc
),
958 source
->LogicalToDeviceXRel(width
),
959 source
->LogicalToDeviceYRel(height
),
960 XLOG2DEV (xdest
), YLOG2DEV (ydest
),
965 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
966 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, 0, 0);
971 if (m_window
&& m_window
->GetBackingPixmap())
973 // +++ MARKUS (mho@comnets.rwth-aachen): error on blitting bitmaps with depth 1
974 if (source
->IsKindOf(CLASSINFO(wxMemoryDC
)) && ((wxMemoryDC
*) source
)->GetBitmap().GetDepth() == 1)
976 XCopyPlane ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
977 source
->LogicalToDeviceX (xsrc
),
978 source
->LogicalToDeviceY (ysrc
),
979 source
->LogicalToDeviceXRel(width
),
980 source
->LogicalToDeviceYRel(height
),
981 XLOG2DEV_2 (xdest
), YLOG2DEV_2 (ydest
), 1);
985 XCopyArea ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
986 source
->LogicalToDeviceX (xsrc
),
987 source
->LogicalToDeviceY (ysrc
),
988 source
->LogicalToDeviceXRel(width
),
989 source
->LogicalToDeviceYRel(height
),
990 XLOG2DEV_2 (xdest
), YLOG2DEV_2 (ydest
));
993 if ( useMask
&& source
->IsKindOf(CLASSINFO(wxMemoryDC
)) )
995 wxMemoryDC
*memDC
= (wxMemoryDC
*)source
;
996 wxBitmap
& sel
= memDC
->GetBitmap();
997 if ( sel
.Ok() && sel
.GetMask() && sel
.GetMask()->GetPixmap() )
999 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) sel
.GetMask()->GetPixmap());
1000 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, XLOG2DEV (xdest
), YLOG2DEV (ydest
));
1004 // Check if we're copying from a mono bitmap
1005 if (source
->IsKindOf(CLASSINFO(wxMemoryDC
)) &&
1006 ((wxMemoryDC
*)source
)->GetBitmap().Ok() && (((wxMemoryDC
*)source
)->GetBitmap().GetDepth () == 1))
1008 XCopyPlane ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
1009 source
->LogicalToDeviceX (xsrc
),
1010 source
->LogicalToDeviceY (ysrc
),
1011 source
->LogicalToDeviceXRel(width
),
1012 source
->LogicalToDeviceYRel(height
),
1013 XLOG2DEV (xdest
), YLOG2DEV (ydest
), 1);
1017 XCopyArea ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
1018 source
->LogicalToDeviceX (xsrc
),
1019 source
->LogicalToDeviceY (ysrc
),
1020 source
->LogicalToDeviceXRel(width
),
1021 source
->LogicalToDeviceYRel(height
),
1022 XLOG2DEV (xdest
), YLOG2DEV (ydest
));
1027 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
1028 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, 0, 0);
1031 } /* Remote/local (Display*) m_display */
1032 CalcBoundingBox (xdest
, ydest
);
1033 CalcBoundingBox (xdest
+ width
, ydest
+ height
);
1035 SetLogicalFunction(orig
);
1037 if (scaledBitmap
) delete scaledBitmap
;
1041 if (scaledBitmap
) delete scaledBitmap
;
1046 void wxWindowDC::DoDrawText( const wxString
&text
, wxCoord x
, wxCoord y
)
1048 wxCHECK_RET( Ok(), "invalid dc" );
1050 // Since X draws from the baseline of the text, must add the text height
1056 slen
= strlen(text
);
1060 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1061 int direction
, descent
;
1062 XCharStruct overall_return
;
1065 (void)XTextExtents16((XFontStruct
*) pFontStruct
, (XChar2b
*)(const char*) text
, slen
, &direction
,
1066 &ascent
, &descent
, &overall_return
);
1069 (void)XTextExtents((XFontStruct
*) pFontStruct
, (char*) (const char*) text
, slen
, &direction
,
1070 &ascent
, &descent
, &overall_return
);
1072 cx
= overall_return
.width
;
1073 cy
= ascent
+ descent
;
1076 // First draw a rectangle representing the text background, if a text
1077 // background is specified
1078 if (m_textBackgroundColour
.Ok () && (m_backgroundMode
!= wxTRANSPARENT
))
1080 wxColour oldPenColour
= m_currentColour
;
1081 m_currentColour
= m_textBackgroundColour
;
1082 bool sameColour
= (oldPenColour
.Ok () && m_textBackgroundColour
.Ok () &&
1083 (oldPenColour
.Red () == m_textBackgroundColour
.Red ()) &&
1084 (oldPenColour
.Blue () == m_textBackgroundColour
.Blue ()) &&
1085 (oldPenColour
.Green () == m_textBackgroundColour
.Green ()));
1087 // This separation of the big && test required for gcc2.7/HP UX 9.02
1088 // or pixel value can be corrupted!
1089 sameColour
= (sameColour
&&
1090 (oldPenColour
.GetPixel() == m_textBackgroundColour
.GetPixel()));
1092 if (!sameColour
|| !GetOptimization())
1094 int pixel
= m_textBackgroundColour
.AllocColour(m_display
);
1095 m_currentColour
= m_textBackgroundColour
;
1097 // Set the GC to the required colour
1100 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1101 if (m_window
&& m_window
->GetBackingPixmap())
1102 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1106 m_textBackgroundColour
= oldPenColour
;
1108 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
), cx
, cy
);
1109 if (m_window
&& m_window
->GetBackingPixmap())
1110 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
1111 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
), cx
, cy
);
1114 // Now set the text foreground and draw the text
1115 if (m_textForegroundColour
.Ok ())
1117 wxColour oldPenColour
= m_currentColour
;
1118 m_currentColour
= m_textForegroundColour
;
1119 bool sameColour
= (oldPenColour
.Ok () && m_currentColour
.Ok () &&
1120 (oldPenColour
.Red () == m_currentColour
.Red ()) &&
1121 (oldPenColour
.Blue () == m_currentColour
.Blue ()) &&
1122 (oldPenColour
.Green () == m_currentColour
.Green ()) &&
1123 (oldPenColour
.GetPixel() == m_currentColour
.GetPixel()));
1125 if (!sameColour
|| !GetOptimization())
1128 if (!m_colour
) // Mono display
1130 // Unless foreground is really white, draw it in black
1131 unsigned char red
= m_textForegroundColour
.Red ();
1132 unsigned char blue
= m_textForegroundColour
.Blue ();
1133 unsigned char green
= m_textForegroundColour
.Green ();
1134 if (red
== (unsigned char) 255 && blue
== (unsigned char) 255
1135 && green
== (unsigned char) 255)
1137 m_currentColour
= *wxWHITE
;
1138 pixel
= (int) WhitePixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1139 m_currentColour
.SetPixel(pixel
);
1140 m_textForegroundColour
.SetPixel(pixel
);
1144 m_currentColour
= *wxBLACK
;
1145 pixel
= (int) BlackPixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1146 m_currentColour
.SetPixel(pixel
);
1147 m_textForegroundColour
.SetPixel(pixel
);
1152 pixel
= m_textForegroundColour
.AllocColour((Display
*) m_display
);
1153 m_currentColour
.SetPixel(pixel
);
1156 // Set the GC to the required colour
1159 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1160 if (m_window
&& m_window
->GetBackingPixmap())
1161 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1165 m_textForegroundColour
= oldPenColour
;
1168 // We need to add the ascent, not the whole height, since X draws at the
1169 // point above the descender.
1172 XDrawString16((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
) + ascent
,
1173 (XChar2b
*)(char*) (const char*) text
, slen
);
1176 XDrawString((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
) + ascent
, text
, slen
);
1178 if (m_window
&& m_window
->GetBackingPixmap()) {
1181 XDrawString16((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
1182 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
) + ascent
,
1183 (XChar2b
*)(char*) (const char*) text
, slen
);
1186 XDrawString((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
1187 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
) + ascent
, (char*) (const char*) text
, slen
);
1191 GetTextExtent (text
, &w
, &h
);
1192 CalcBoundingBox (x
+ w
, y
+ h
);
1193 CalcBoundingBox (x
, y
);
1196 void wxWindowDC::DoDrawRotatedText( const wxString
&text
, wxCoord x
, wxCoord y
, double angle
)
1200 DrawText(text
, x
, y
);
1204 wxCHECK_RET( Ok(), "invalid dc" );
1206 // Since X draws from the baseline of the text, must add the text height
1212 slen
= strlen(text
);
1216 // Calculate text extent.
1217 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1218 int direction
, descent
;
1219 XCharStruct overall_return
;
1222 (void)XTextExtents16((XFontStruct
*) pFontStruct
, (XChar2b
*)(const char*) text
, slen
, &direction
,
1223 &ascent
, &descent
, &overall_return
);
1226 (void)XTextExtents((XFontStruct
*) pFontStruct
, (char*) (const char*) text
, slen
, &direction
,
1227 &ascent
, &descent
, &overall_return
);
1229 cx
= overall_return
.width
;
1230 cy
= ascent
+ descent
;
1233 wxBitmap
src(cx
, cy
);
1235 dc
.SelectObject(src
);
1236 dc
.SetFont(GetFont());
1237 dc
.SetBackground(*wxWHITE_BRUSH
);
1238 dc
.SetBrush(*wxBLACK_BRUSH
);
1240 dc
.DrawText(text
, 0, 0);
1241 dc
.SetFont(wxNullFont
);
1243 // Calculate the size of the rotated bounding box.
1244 double dx
= cos(angle
/ 180.0 * M_PI
);
1245 double dy
= sin(angle
/ 180.0 * M_PI
);
1246 double x4
= -cy
* dy
;
1247 double y4
= cy
* dx
;
1248 double x3
= cx
* dx
;
1249 double y3
= cx
* dy
;
1250 double x2
= x3
+ x4
;
1251 double y2
= y3
+ y4
;
1255 // Create image from the source bitmap after writing the text into it.
1258 int minx
= roundmin(0, roundmin(x4
, roundmin(x2
, x3
)));
1259 int miny
= roundmin(0, roundmin(y4
, roundmin(y2
, y3
)));
1260 int maxx
= roundmax(0, roundmax(x4
, roundmax(x2
, x3
)));
1261 int maxy
= roundmax(0, roundmax(y4
, roundmax(y2
, y3
)));
1263 // This rotates counterclockwise around the top left corner.
1264 for (int rx
= minx
; rx
< maxx
; rx
++)
1266 for (int ry
= miny
; ry
< maxy
; ry
++)
1268 // transform dest coords to source coords
1269 int sx
= (int) (rx
* dx
+ ry
* dy
+ 0.5);
1270 int sy
= (int) (ry
* dx
- rx
* dy
+ 0.5);
1271 if (sx
>= 0 && sx
< cx
&& sy
>= 0 && sy
< cy
)
1273 // draw black pixels, ignore white ones (i.e. transparent b/g)
1274 if (image
.GetRed(sx
, sy
) == 0)
1276 DrawPoint((wxCoord
) (x1
+ maxx
- rx
), (wxCoord
) (cy
+ y1
- ry
));
1281 //DrawPoint(x1 + maxx - rx, cy + y1 + maxy - ry);
1288 // First draw a rectangle representing the text background, if a text
1289 // background is specified
1290 if (m_textBackgroundColour
.Ok () && (m_backgroundMode
!= wxTRANSPARENT
))
1292 wxColour oldPenColour
= m_currentColour
;
1293 m_currentColour
= m_textBackgroundColour
;
1294 bool sameColour
= (oldPenColour
.Ok () && m_textBackgroundColour
.Ok () &&
1295 (oldPenColour
.Red () == m_textBackgroundColour
.Red ()) &&
1296 (oldPenColour
.Blue () == m_textBackgroundColour
.Blue ()) &&
1297 (oldPenColour
.Green () == m_textBackgroundColour
.Green ()));
1299 // This separation of the big && test required for gcc2.7/HP UX 9.02
1300 // or pixel value can be corrupted!
1301 sameColour
= (sameColour
&&
1302 (oldPenColour
.GetPixel() == m_textBackgroundColour
.GetPixel()));
1304 if (!sameColour
|| !GetOptimization())
1306 int pixel
= m_textBackgroundColour
.AllocColour(m_display
);
1307 m_currentColour
= m_textBackgroundColour
;
1309 // Set the GC to the required colour
1312 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1313 if (m_window
&& m_window
->GetBackingPixmap())
1314 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1318 m_textBackgroundColour
= oldPenColour
;
1320 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
), cx
, cy
);
1321 if (m_window
&& m_window
->GetBackingPixmap())
1322 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
1323 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
), cx
, cy
);
1328 // XXX use pixmap size
1329 GetTextExtent (text
, &w
, &h
);
1330 CalcBoundingBox (x
+ w
, y
+ h
);
1331 CalcBoundingBox (x
, y
);
1334 bool wxWindowDC::CanGetTextExtent() const
1339 void wxWindowDC::DoGetTextExtent( const wxString
&string
, wxCoord
*width
, wxCoord
*height
,
1340 wxCoord
*descent
, wxCoord
*externalLeading
,
1341 wxFont
*font
) const
1343 wxCHECK_RET( Ok(), "invalid dc" );
1345 wxFont
* theFont
= font
;
1347 theFont
= (wxFont
*)&m_font
; // const_cast
1351 // TODO: this should be an error log function
1352 wxFAIL_MSG("set a valid font before calling GetTextExtent!");
1354 if (width
) *width
= -1;
1355 if (height
) *height
= -1;
1359 WXFontStructPtr pFontStruct
= theFont
->GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1361 int direction
, ascent
, descent2
;
1362 XCharStruct overall
;
1367 slen
= str16len(string
);
1370 slen
= strlen(string
);
1374 XTextExtents16((XFontStruct
*) pFontStruct
, (XChar2b
*) (char*) (const char*) string
, slen
, &direction
,
1375 &ascent
, &descent2
, &overall
);
1378 XTextExtents((XFontStruct
*) pFontStruct
, (char*) (const char*) string
, slen
, &direction
,
1379 &ascent
, &descent2
, &overall
);
1381 if (width
) *width
= XDEV2LOGREL (overall
.width
);
1382 if (height
) *height
= YDEV2LOGREL (ascent
+ descent2
);
1384 *descent
= descent2
;
1385 if (externalLeading
)
1386 *externalLeading
= 0;
1389 wxCoord
wxWindowDC::GetCharWidth() const
1391 wxCHECK_MSG( Ok(), 0, "invalid dc" );
1392 wxCHECK_MSG( m_font
.Ok(), 0, "invalid font" );
1394 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
* m_logicalScaleY
, m_display
);
1396 int direction
, ascent
, descent
;
1397 XCharStruct overall
;
1398 XTextExtents ((XFontStruct
*) pFontStruct
, "x", 1, &direction
, &ascent
,
1399 &descent
, &overall
);
1400 return XDEV2LOGREL(overall
.width
);
1403 wxCoord
wxWindowDC::GetCharHeight() const
1405 wxCHECK_MSG( Ok(), 0, "invalid dc" );
1406 wxCHECK_MSG( m_font
.Ok(), 0, "invalid font" );
1408 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1410 int direction
, ascent
, descent
;
1411 XCharStruct overall
;
1412 XTextExtents ((XFontStruct
*) pFontStruct
, "x", 1, &direction
, &ascent
,
1413 &descent
, &overall
);
1414 // return XDEV2LOGREL(overall.ascent + overall.descent);
1415 return XDEV2LOGREL(ascent
+ descent
);
1418 void wxWindowDC::Clear()
1420 wxCHECK_RET( Ok(), "invalid dc" );
1425 m_window
->GetSize(&w
, &h
);
1427 if (m_window
&& m_window
->GetBackingPixmap())
1429 w
= m_window
->GetPixmapWidth();
1430 h
= m_window
->GetPixmapHeight();
1435 if (this->IsKindOf(CLASSINFO(wxMemoryDC
)))
1437 wxMemoryDC
* memDC
= (wxMemoryDC
*) this;
1438 w
= memDC
->GetBitmap().GetWidth();
1439 h
= memDC
->GetBitmap().GetHeight();
1445 wxBrush saveBrush
= m_brush
;
1446 SetBrush (m_backgroundBrush
);
1448 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, 0, 0, w
, h
);
1450 if (m_window
&& m_window
->GetBackingPixmap())
1451 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, 0, 0, w
, h
);
1453 m_brush
= saveBrush
;
1456 void wxWindowDC::Clear(const wxRect
& rect
)
1458 wxCHECK_RET( Ok(), "invalid dc" );
1460 int x
= rect
.x
; int y
= rect
.y
;
1461 int w
= rect
.width
; int h
= rect
.height
;
1463 wxBrush saveBrush
= m_brush
;
1464 SetBrush (m_backgroundBrush
);
1466 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, x
, y
, w
, h
);
1468 if (m_window
&& m_window
->GetBackingPixmap())
1469 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, x
, y
, w
, h
);
1471 m_brush
= saveBrush
;
1474 void wxWindowDC::SetFont( const wxFont
&font
)
1476 wxCHECK_RET( Ok(), "invalid dc" );
1482 if ((m_oldFont
!= (WXFont
) 0) && ((wxCoord
) m_oldFont
!= -1))
1484 XSetFont ((Display
*) m_display
, (GC
) m_gc
, (Font
) m_oldFont
);
1486 if (m_window
&& m_window
->GetBackingPixmap())
1487 XSetFont ((Display
*) m_display
,(GC
) m_gcBacking
, (Font
) m_oldFont
);
1492 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1494 Font fontId
= ((XFontStruct
*)pFontStruct
)->fid
;
1495 XSetFont ((Display
*) m_display
, (GC
) m_gc
, fontId
);
1497 if (m_window
&& m_window
->GetBackingPixmap())
1498 XSetFont ((Display
*) m_display
,(GC
) m_gcBacking
, fontId
);
1501 void wxWindowDC::SetPen( const wxPen
&pen
)
1503 wxCHECK_RET( Ok(), "invalid dc" );
1509 wxBitmap oldStipple
= m_currentStipple
;
1510 int oldStyle
= m_currentStyle
;
1511 int oldFill
= m_currentFill
;
1512 int old_pen_width
= m_currentPenWidth
;
1513 int old_pen_join
= m_currentPenJoin
;
1514 int old_pen_cap
= m_currentPenCap
;
1515 int old_pen_nb_dash
= m_currentPenDashCount
;
1516 char *old_pen_dash
= m_currentPenDash
;
1518 wxColour oldPenColour
= m_currentColour
;
1519 m_currentColour
= m_pen
.GetColour ();
1520 m_currentStyle
= m_pen
.GetStyle ();
1521 m_currentFill
= m_pen
.GetStyle (); // TODO?
1522 m_currentPenWidth
= m_pen
.GetWidth ();
1523 m_currentPenJoin
= m_pen
.GetJoin ();
1524 m_currentPenCap
= m_pen
.GetCap ();
1525 m_currentPenDashCount
= m_pen
.GetDashCount();
1526 m_currentPenDash
= m_pen
.GetDash();
1528 if (m_currentStyle
== wxSTIPPLE
)
1529 m_currentStipple
= * m_pen
.GetStipple ();
1531 bool sameStyle
= (oldStyle
== m_currentStyle
&&
1532 oldFill
== m_currentFill
&&
1533 old_pen_join
== m_currentPenJoin
&&
1534 old_pen_cap
== m_currentPenCap
&&
1535 old_pen_nb_dash
== m_currentPenDashCount
&&
1536 old_pen_dash
== m_currentPenDash
&&
1537 old_pen_width
== m_currentPenWidth
);
1539 bool sameColour
= (oldPenColour
.Ok () &&
1540 (oldPenColour
.Red () == m_currentColour
.Red ()) &&
1541 (oldPenColour
.Blue () == m_currentColour
.Blue ()) &&
1542 (oldPenColour
.Green () == m_currentColour
.Green ()) &&
1543 (oldPenColour
.GetPixel() == m_currentColour
.GetPixel()));
1545 if (!sameStyle
|| !GetOptimization())
1547 int scaled_width
= (int) XLOG2DEVREL (m_pen
.GetWidth ());
1548 if (scaled_width
< 0)
1554 static const char dotted
[] = {2, 5};
1555 static const char short_dashed
[] = {4, 4};
1556 static const char long_dashed
[] = {4, 8};
1557 static const char dotted_dashed
[] = {6, 6, 2, 6};
1559 // We express dash pattern in pen width unit, so we are
1560 // independent of zoom factor and so on...
1562 const char *req_dash
;
1564 switch (m_pen
.GetStyle ())
1567 req_nb_dash
= m_currentPenDashCount
;
1568 req_dash
= m_currentPenDash
;
1569 style
= LineOnOffDash
;
1574 style
= LineOnOffDash
;
1578 req_dash
= short_dashed
;
1579 style
= LineOnOffDash
;
1583 req_dash
= long_dashed
;
1584 style
= LineOnOffDash
;
1588 req_dash
= dotted_dashed
;
1589 style
= LineOnOffDash
;
1600 if (req_dash
&& req_nb_dash
)
1602 char *real_req_dash
= new char[req_nb_dash
];
1605 int factor
= scaled_width
== 0 ? 1 : scaled_width
;
1606 for (int i
= 0; i
< req_nb_dash
; i
++)
1607 real_req_dash
[i
] = req_dash
[i
] * factor
;
1608 XSetDashes ((Display
*) m_display
, (GC
) m_gc
, 0, real_req_dash
, req_nb_dash
);
1610 if (m_window
&& m_window
->GetBackingPixmap())
1611 XSetDashes ((Display
*) m_display
,(GC
) m_gcBacking
, 0, real_req_dash
, req_nb_dash
);
1612 delete[]real_req_dash
;
1616 // No Memory. We use non-scaled dash pattern...
1617 XSetDashes ((Display
*) m_display
, (GC
) m_gc
, 0, req_dash
, req_nb_dash
);
1619 if (m_window
&& m_window
->GetBackingPixmap())
1620 XSetDashes ((Display
*) m_display
,(GC
) m_gcBacking
, 0, req_dash
, req_nb_dash
);
1624 switch (m_pen
.GetCap ())
1626 case wxCAP_PROJECTING
:
1627 cap
= CapProjecting
;
1634 cap
= (scaled_width
<= 1) ? CapNotLast
: CapRound
;
1638 switch (m_pen
.GetJoin ())
1652 XSetLineAttributes ((Display
*) m_display
, (GC
) m_gc
, scaled_width
, style
, cap
, join
);
1654 if (m_window
&& m_window
->GetBackingPixmap())
1655 XSetLineAttributes ((Display
*) m_display
,(GC
) m_gcBacking
, scaled_width
, style
, cap
, join
);
1658 if (IS_HATCH(m_currentFill
) && ((m_currentFill
!= oldFill
) || !GetOptimization()))
1662 oldStipple
= wxNullBitmap
; // For later reset!!
1664 switch (m_currentFill
)
1666 case wxBDIAGONAL_HATCH
:
1667 if (bdiag
== (Pixmap
) 0)
1668 bdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1669 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1670 bdiag_bits
, bdiag_width
, bdiag_height
);
1673 case wxFDIAGONAL_HATCH
:
1674 if (fdiag
== (Pixmap
) 0)
1675 fdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1676 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1677 fdiag_bits
, fdiag_width
, fdiag_height
);
1681 if (cross
== (Pixmap
) 0)
1682 cross
= XCreateBitmapFromData ((Display
*) m_display
,
1683 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1684 cross_bits
, cross_width
, cross_height
);
1687 case wxHORIZONTAL_HATCH
:
1688 if (horiz
== (Pixmap
) 0)
1689 horiz
= XCreateBitmapFromData ((Display
*) m_display
,
1690 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1691 horiz_bits
, horiz_width
, horiz_height
);
1694 case wxVERTICAL_HATCH
:
1695 if (verti
== (Pixmap
) 0)
1696 verti
= XCreateBitmapFromData ((Display
*) m_display
,
1697 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1698 verti_bits
, verti_width
, verti_height
);
1701 case wxCROSSDIAG_HATCH
:
1703 if (cdiag
== (Pixmap
) 0)
1704 cdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1705 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1706 cdiag_bits
, cdiag_width
, cdiag_height
);
1710 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, myStipple
);
1712 if (m_window
&& m_window
->GetBackingPixmap())
1713 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, myStipple
);
1715 else if (m_currentStipple
.Ok()
1716 && ((m_currentStipple
!= oldStipple
) || !GetOptimization()))
1718 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) m_currentStipple
.GetPixmap());
1720 if (m_window
&& m_window
->GetBackingPixmap())
1721 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, (Pixmap
) m_currentStipple
.GetPixmap());
1724 if ((m_currentFill
!= oldFill
) || !GetOptimization())
1728 if (m_currentFill
== wxSTIPPLE
)
1729 fill_style
= FillStippled
;
1730 else if (IS_HATCH (m_currentFill
))
1731 fill_style
= FillStippled
;
1733 fill_style
= FillSolid
;
1734 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, fill_style
);
1735 if (m_window
&& m_window
->GetBackingPixmap())
1736 XSetFillStyle ((Display
*) m_display
,(GC
) m_gcBacking
, fill_style
);
1739 // must test m_logicalFunction, because it involves background!
1740 if (!sameColour
|| !GetOptimization()
1741 || ((m_logicalFunction
== wxXOR
) || (m_autoSetting
& 0x2)))
1744 if (m_pen
.GetStyle () == wxTRANSPARENT
)
1745 pixel
= m_backgroundPixel
;
1748 unsigned char red
= m_pen
.GetColour ().Red ();
1749 unsigned char blue
= m_pen
.GetColour ().Blue ();
1750 unsigned char green
= m_pen
.GetColour ().Green ();
1751 if (red
== (unsigned char) 255 && blue
== (unsigned char) 255
1752 && green
== (unsigned char) 255)
1754 pixel
= (int) WhitePixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1755 m_currentColour
= *wxWHITE
;
1756 m_pen
.GetColour().SetPixel(pixel
);
1757 m_currentColour
.SetPixel(pixel
);
1761 pixel
= (int) BlackPixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1762 m_currentColour
= *wxBLACK
;
1763 m_pen
.GetColour().SetPixel(pixel
);
1768 pixel
= m_pen
.GetColour ().AllocColour(m_display
);
1769 m_currentColour
.SetPixel(pixel
);
1772 // Finally, set the GC to the required colour
1775 if (m_logicalFunction
== wxXOR
)
1778 XGetGCValues ((Display
*) m_display
, (GC
) m_gc
, GCBackground
, &values
);
1779 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
^ values
.background
);
1780 if (m_window
&& m_window
->GetBackingPixmap())
1781 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
^ values
.background
);
1785 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1786 if (m_window
&& m_window
->GetBackingPixmap())
1787 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1792 m_pen
.GetColour().SetPixel(oldPenColour
.GetPixel());
1797 void wxWindowDC::SetBrush( const wxBrush
&brush
)
1799 wxCHECK_RET( Ok(), "invalid dc" );
1803 if (!m_brush
.Ok() || m_brush
.GetStyle () == wxTRANSPARENT
)
1806 int oldFill
= m_currentFill
;
1807 wxBitmap oldStipple
= m_currentStipple
;
1809 m_autoSetting
|= 0x1;
1811 m_currentFill
= m_brush
.GetStyle ();
1812 if (m_currentFill
== wxSTIPPLE
)
1813 m_currentStipple
= * m_brush
.GetStipple ();
1815 wxColour
oldBrushColour(m_currentColour
);
1816 m_currentColour
= m_brush
.GetColour ();
1818 bool sameColour
= (oldBrushColour
.Ok () &&
1819 (oldBrushColour
.Red () == m_currentColour
.Red ()) &&
1820 (oldBrushColour
.Blue () == m_currentColour
.Blue ()) &&
1821 (oldBrushColour
.Green () == m_currentColour
.Green ()) &&
1822 (oldBrushColour
.GetPixel() == m_currentColour
.GetPixel()));
1824 if ((oldFill
!= m_brush
.GetStyle ()) || !GetOptimization())
1826 switch (brush
.GetStyle ())
1830 case wxBDIAGONAL_HATCH
:
1831 case wxCROSSDIAG_HATCH
:
1832 case wxFDIAGONAL_HATCH
:
1834 case wxHORIZONTAL_HATCH
:
1835 case wxVERTICAL_HATCH
:
1838 // Chris Breeze 23/07/97: use background mode to determine whether
1839 // fill style should be solid or transparent
1840 int style
= (m_backgroundMode
== wxSOLID
? FillOpaqueStippled
: FillStippled
);
1841 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, style
);
1842 if (m_window
&& m_window
->GetBackingPixmap())
1843 XSetFillStyle ((Display
*) m_display
,(GC
) m_gcBacking
, style
);
1848 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, FillSolid
);
1849 if (m_window
&& m_window
->GetBackingPixmap())
1850 XSetFillStyle ((Display
*) m_display
,(GC
) m_gcBacking
, FillSolid
);
1854 if (IS_HATCH(m_currentFill
) && ((m_currentFill
!= oldFill
) || !GetOptimization()))
1858 switch (m_currentFill
)
1860 case wxBDIAGONAL_HATCH
:
1861 if (bdiag
== (Pixmap
) 0)
1862 bdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1863 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1864 bdiag_bits
, bdiag_width
, bdiag_height
);
1867 case wxFDIAGONAL_HATCH
:
1868 if (fdiag
== (Pixmap
) 0)
1869 fdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1870 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1871 fdiag_bits
, fdiag_width
, fdiag_height
);
1875 if (cross
== (Pixmap
) 0)
1876 cross
= XCreateBitmapFromData ((Display
*) m_display
,
1877 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1878 cross_bits
, cross_width
, cross_height
);
1881 case wxHORIZONTAL_HATCH
:
1882 if (horiz
== (Pixmap
) 0)
1883 horiz
= XCreateBitmapFromData ((Display
*) m_display
,
1884 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1885 horiz_bits
, horiz_width
, horiz_height
);
1888 case wxVERTICAL_HATCH
:
1889 if (verti
== (Pixmap
) 0)
1890 verti
= XCreateBitmapFromData ((Display
*) m_display
,
1891 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1892 verti_bits
, verti_width
, verti_height
);
1895 case wxCROSSDIAG_HATCH
:
1897 if (cdiag
== (Pixmap
) 0)
1898 cdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1899 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1900 cdiag_bits
, cdiag_width
, cdiag_height
);
1904 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, myStipple
);
1906 if (m_window
&& m_window
->GetBackingPixmap())
1907 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, myStipple
);
1909 // X can forget the stipple value when resizing a window (apparently)
1910 // so always set the stipple.
1911 else if (m_currentStipple
.Ok()) // && m_currentStipple != oldStipple)
1913 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) m_currentStipple
.GetPixmap());
1914 if (m_window
&& m_window
->GetBackingPixmap())
1915 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, (Pixmap
) m_currentStipple
.GetPixmap());
1918 // must test m_logicalFunction, because it involves background!
1919 if (!sameColour
|| !GetOptimization() || m_logicalFunction
== wxXOR
)
1924 // Policy - on a monochrome screen, all brushes are white,
1925 // except when they're REALLY black!!!
1926 unsigned char red
= m_brush
.GetColour ().Red ();
1927 unsigned char blue
= m_brush
.GetColour ().Blue ();
1928 unsigned char green
= m_brush
.GetColour ().Green ();
1930 if (red
== (unsigned char) 0 && blue
== (unsigned char) 0
1931 && green
== (unsigned char) 0)
1933 pixel
= (int) BlackPixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1934 m_currentColour
= *wxBLACK
;
1935 m_brush
.GetColour().SetPixel(pixel
);
1936 m_currentColour
.SetPixel(pixel
);
1940 pixel
= (int) WhitePixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1941 m_currentColour
= *wxWHITE
;
1942 m_brush
.GetColour().SetPixel(pixel
);
1943 m_currentColour
.SetPixel(pixel
);
1946 // N.B. comment out the above line and uncomment the following lines
1947 // if you want non-white colours to be black on a monochrome display.
1949 if (red == (unsigned char )255 && blue == (unsigned char)255
1950 && green == (unsigned char)255)
1951 pixel = (int)WhitePixel((Display*) m_display, DefaultScreen((Display*) m_display));
1953 pixel = (int)BlackPixel((Display*) m_display, DefaultScreen((Display*) m_display));
1956 else if (m_brush
.GetStyle () != wxTRANSPARENT
)
1958 pixel
= m_brush
.GetColour().AllocColour(m_display
);
1959 m_currentColour
.SetPixel(pixel
);
1963 // Finally, set the GC to the required colour
1964 if (m_logicalFunction
== wxXOR
)
1967 XGetGCValues ((Display
*) m_display
, (GC
) m_gc
, GCBackground
, &values
);
1968 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
^ values
.background
);
1969 if (m_window
&& m_window
->GetBackingPixmap())
1970 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
^ values
.background
);
1974 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1975 if (m_window
&& m_window
->GetBackingPixmap())
1976 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1981 m_brush
.GetColour().SetPixel(oldBrushColour
.GetPixel());
1984 void wxWindowDC::SetBackground( const wxBrush
&brush
)
1986 wxCHECK_RET( Ok(), "invalid dc" );
1988 m_backgroundBrush
= brush
;
1990 if (!m_backgroundBrush
.Ok())
1993 int pixel
= m_backgroundBrush
.GetColour().AllocColour(m_display
);
1995 // New behaviour, 10/2/99: setting the background brush of a DC
1996 // doesn't affect the window background colour.
1998 // XSetWindowBackground doesn't work for non-Window pixmaps
1999 if (!this->IsKindOf(CLASSINFO(wxMemoryDC)))
2000 XSetWindowBackground ((Display*) m_display, (Pixmap) m_pixmap, pixel);
2003 // Necessary for ::DrawIcon, which use fg/bg pixel or the GC.
2004 // And Blit,... (Any fct that use XCopyPlane, in fact.)
2005 XSetBackground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
2006 if (m_window
&& m_window
->GetBackingPixmap())
2007 XSetBackground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
2010 void wxWindowDC::SetLogicalFunction( int function
)
2012 wxCHECK_RET( Ok(), "invalid dc" );
2017 if (m_logicalFunction
== function
)
2023 x_function
= GXclear
;
2029 x_function
= GXinvert
;
2032 x_function
= GXorReverse
;
2035 x_function
= GXandReverse
;
2044 x_function
= GXandInverted
;
2047 x_function
= GXnoop
;
2053 x_function
= GXequiv
;
2056 x_function
= GXcopyInverted
;
2059 x_function
= GXorInverted
;
2062 x_function
= GXnand
;
2069 x_function
= GXcopy
;
2073 XSetFunction((Display
*) m_display
, (GC
) m_gc
, x_function
);
2074 if (m_window
&& m_window
->GetBackingPixmap())
2075 XSetFunction((Display
*) m_display
, (GC
) m_gcBacking
, x_function
);
2077 if ((m_logicalFunction
== wxXOR
) != (function
== wxXOR
))
2078 /* MATTHEW: [9] Need to redo pen simply */
2079 m_autoSetting
|= 0x2;
2081 m_logicalFunction
= function
;
2085 void wxWindowDC::SetTextForeground( const wxColour
&col
)
2087 wxCHECK_RET( Ok(), "invalid dc" );
2089 if (m_textForegroundColour
== col
)
2092 m_textForegroundColour
= col
;
2096 void wxWindowDC::SetTextBackground( const wxColour
&col
)
2098 wxCHECK_RET( Ok(), "invalid dc" );
2100 if (m_textBackgroundColour
== col
)
2103 m_textBackgroundColour
= col
;
2104 if (!m_textBackgroundColour
.Ok())
2108 void wxWindowDC::SetBackgroundMode( int mode
)
2110 m_backgroundMode
= mode
;
2113 void wxWindowDC::SetPalette( const wxPalette
& palette
)
2118 /* Use GetXColormap */
2119 XSetWindowColormap ((Display
*) m_display
, (Window
) m_window
->GetXWindow(),
2120 (Colormap
) palette
.GetXColormap());
2122 /* Use wxGetMainColormap */
2123 XSetWindowColormap ((Display
*) m_display
, (Window
) m_window
->GetXWindow(),
2124 (Colormap
) wxTheApp
->GetMainColormap(m_display
));
2129 void wxWindowDC::SetDCClipping()
2131 // m_userRegion is the region set by calling SetClippingRegion
2133 if (m_currentRegion
)
2134 XDestroyRegion ((Region
) m_currentRegion
);
2136 // We need to take into account
2137 // clipping imposed on a window by a repaint.
2138 // We'll combine it with the user region. But for now,
2139 // just use the currently-defined user clipping region.
2140 if (m_userRegion
|| (m_window
&& m_window
->GetUpdateRegion().Ok()) )
2141 m_currentRegion
= (WXRegion
) XCreateRegion ();
2143 m_currentRegion
= (WXRegion
) NULL
;
2145 if ((m_window
&& m_window
->GetUpdateRegion().Ok()) && m_userRegion
)
2146 XIntersectRegion ((Region
) m_window
->GetUpdateRegion().GetXRegion(), (Region
) m_userRegion
, (Region
) m_currentRegion
);
2147 else if (m_userRegion
)
2148 XIntersectRegion ((Region
) m_userRegion
, (Region
) m_userRegion
, (Region
) m_currentRegion
);
2149 else if (m_window
&& m_window
->GetUpdateRegion().Ok())
2150 XIntersectRegion ((Region
) m_window
->GetUpdateRegion().GetXRegion(), (Region
) m_window
->GetUpdateRegion().GetXRegion(),
2151 (Region
) m_currentRegion
);
2153 if (m_currentRegion
)
2155 XSetRegion ((Display
*) m_display
, (GC
) m_gc
, (Region
) m_currentRegion
);
2159 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
2164 void wxWindowDC::DoSetClippingRegion( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
2166 wxDC::DoSetClippingRegion( x
, y
, width
, height
);
2169 XDestroyRegion ((Region
) m_userRegion
);
2170 m_userRegion
= (WXRegion
) XCreateRegion ();
2174 r
.width
= XLOG2DEVREL(width
);
2175 r
.height
= YLOG2DEVREL(height
);
2176 XUnionRectWithRegion (&r
, (Region
) m_userRegion
, (Region
) m_userRegion
);
2180 // Needs to work differently for Pixmap: without this,
2181 // there's a nasty (Display*) m_display bug. 8/12/94
2182 if (m_window
&& m_window
->GetBackingPixmap())
2184 XRectangle rects
[1];
2185 rects
[0].x
= XLOG2DEV_2(x
);
2186 rects
[0].y
= YLOG2DEV_2(y
);
2187 rects
[0].width
= XLOG2DEVREL(width
);
2188 rects
[0].height
= YLOG2DEVREL(height
);
2189 XSetClipRectangles((Display
*) m_display
, (GC
) m_gcBacking
, 0, 0, rects
, 1, Unsorted
);
2193 void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion
& region
)
2195 wxRect box
= region
.GetBox();
2197 wxDC::DoSetClippingRegion( box
.x
, box
.y
, box
.width
, box
.height
);
2200 XDestroyRegion ((Region
) m_userRegion
);
2201 m_userRegion
= (WXRegion
) XCreateRegion ();
2203 XUnionRegion((Region
) m_userRegion
, (Region
) region
.GetXRegion(), (Region
) m_userRegion
);
2207 // Needs to work differently for Pixmap: without this,
2208 // there's a nasty (Display*) m_display bug. 8/12/94
2209 if (m_window
&& m_window
->GetBackingPixmap())
2211 XRectangle rects
[1];
2212 rects
[0].x
= XLOG2DEV_2(box
.x
);
2213 rects
[0].y
= YLOG2DEV_2(box
.y
);
2214 rects
[0].width
= XLOG2DEVREL(box
.width
);
2215 rects
[0].height
= YLOG2DEVREL(box
.height
);
2216 XSetClipRectangles((Display
*) m_display
, (GC
) m_gcBacking
, 0, 0, rects
, 1, Unsorted
);
2221 void wxWindowDC::DestroyClippingRegion()
2223 wxDC::DestroyClippingRegion();
2226 XDestroyRegion ((Region
) m_userRegion
);
2227 m_userRegion
= NULL
;
2232 gc_val
.clip_mask
= None
;
2233 if (m_window
&& m_window
->GetBackingPixmap())
2234 XChangeGC((Display
*) m_display
, (GC
) m_gcBacking
, GCClipMask
, &gc_val
);
2237 // Resolution in pixels per logical inch
2238 wxSize
wxWindowDC::GetPPI() const
2240 return wxSize(100, 100);
2243 int wxWindowDC::GetDepth() const
2250 // ----------------------------------- spline code ----------------------------------------
2252 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
,
2253 double a3
, double b3
, double a4
, double b4
);
2254 void wx_clear_stack();
2255 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
, double *x3
,
2256 double *y3
, double *x4
, double *y4
);
2257 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
,
2258 double x4
, double y4
);
2259 static bool wx_spline_add_point(double x
, double y
);
2260 static void wx_spline_draw_point_array(wxDC
*dc
);
2262 wxList wx_spline_point_list
;
2264 #define half(z1, z2) ((z1+z2)/2.0)
2267 /* iterative version */
2269 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
, double a3
, double b3
, double a4
,
2272 register double xmid
, ymid
;
2273 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
2276 wx_spline_push(a1
, b1
, a2
, b2
, a3
, b3
, a4
, b4
);
2278 while (wx_spline_pop(&x1
, &y1
, &x2
, &y2
, &x3
, &y3
, &x4
, &y4
)) {
2279 xmid
= (double)half(x2
, x3
);
2280 ymid
= (double)half(y2
, y3
);
2281 if (fabs(x1
- xmid
) < THRESHOLD
&& fabs(y1
- ymid
) < THRESHOLD
&&
2282 fabs(xmid
- x4
) < THRESHOLD
&& fabs(ymid
- y4
) < THRESHOLD
) {
2283 wx_spline_add_point( x1
, y1
);
2284 wx_spline_add_point( xmid
, ymid
);
2286 wx_spline_push(xmid
, ymid
, (double)half(xmid
, x3
), (double)half(ymid
, y3
),
2287 (double)half(x3
, x4
), (double)half(y3
, y4
), x4
, y4
);
2288 wx_spline_push(x1
, y1
, (double)half(x1
, x2
), (double)half(y1
, y2
),
2289 (double)half(x2
, xmid
), (double)half(y2
, ymid
), xmid
, ymid
);
2294 /* utilities used by spline drawing routines */
2296 typedef struct wx_spline_stack_struct
{
2297 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
2300 #define SPLINE_STACK_DEPTH 20
2301 static Stack wx_spline_stack
[SPLINE_STACK_DEPTH
];
2302 static Stack
*wx_stack_top
;
2303 static int wx_stack_count
;
2305 void wx_clear_stack()
2307 wx_stack_top
= wx_spline_stack
;
2311 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
, double x4
, double y4
)
2313 wx_stack_top
->x1
= x1
;
2314 wx_stack_top
->y1
= y1
;
2315 wx_stack_top
->x2
= x2
;
2316 wx_stack_top
->y2
= y2
;
2317 wx_stack_top
->x3
= x3
;
2318 wx_stack_top
->y3
= y3
;
2319 wx_stack_top
->x4
= x4
;
2320 wx_stack_top
->y4
= y4
;
2325 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
,
2326 double *x3
, double *y3
, double *x4
, double *y4
)
2328 if (wx_stack_count
== 0)
2332 *x1
= wx_stack_top
->x1
;
2333 *y1
= wx_stack_top
->y1
;
2334 *x2
= wx_stack_top
->x2
;
2335 *y2
= wx_stack_top
->y2
;
2336 *x3
= wx_stack_top
->x3
;
2337 *y3
= wx_stack_top
->y3
;
2338 *x4
= wx_stack_top
->x4
;
2339 *y4
= wx_stack_top
->y4
;
2343 static bool wx_spline_add_point(double x
, double y
)
2345 wxPoint
*point
= new wxPoint
;
2348 wx_spline_point_list
.Append((wxObject
*)point
);
2352 static void wx_spline_draw_point_array(wxDC
*dc
)
2354 dc
->DrawLines(&wx_spline_point_list
, 0, 0 );
2355 wxNode
*node
= wx_spline_point_list
.First();
2358 wxPoint
*point
= (wxPoint
*)node
->Data();
2361 node
= wx_spline_point_list
.First();
2365 void wxWindowDC::DoDrawSpline( wxList
*points
)
2367 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2370 double cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
;
2371 double x1
, y1
, x2
, y2
;
2373 wxNode
*node
= points
->First();
2374 p
= (wxPoint
*)node
->Data();
2379 node
= node
->Next();
2380 p
= (wxPoint
*)node
->Data();
2384 cx1
= (double)((x1
+ x2
) / 2);
2385 cy1
= (double)((y1
+ y2
) / 2);
2386 cx2
= (double)((cx1
+ x2
) / 2);
2387 cy2
= (double)((cy1
+ y2
) / 2);
2389 wx_spline_add_point(x1
, y1
);
2391 while ((node
= node
->Next()) != NULL
)
2393 p
= (wxPoint
*)node
->Data();
2398 cx4
= (double)(x1
+ x2
) / 2;
2399 cy4
= (double)(y1
+ y2
) / 2;
2400 cx3
= (double)(x1
+ cx4
) / 2;
2401 cy3
= (double)(y1
+ cy4
) / 2;
2403 wx_quadratic_spline(cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
);
2407 cx2
= (double)(cx1
+ x2
) / 2;
2408 cy2
= (double)(cy1
+ y2
) / 2;
2411 wx_spline_add_point( cx1
, cy1
);
2412 wx_spline_add_point( x2
, y2
);
2414 wx_spline_draw_point_array( this );
2417 #endif // wxUSE_SPLINE
2421 // ----------------------------------------------------------------------------
2423 // ----------------------------------------------------------------------------
2425 wxPaintDC::wxPaintDC(wxWindow
* win
) : wxWindowDC(win
)
2427 wxRegion
* region
= NULL
;
2429 // Combine all the update rects into a region
2430 const wxRectList
& updateRects(win
->GetUpdateRects());
2431 if ( updateRects
.GetCount() != 0 )
2433 for ( wxRectList::Node
*node
= updateRects
.GetFirst();
2435 node
= node
->GetNext() )
2437 wxRect
* rect
= node
->GetData();
2440 region
= new wxRegion(*rect
);
2442 // TODO: is this correct? In SetDCClipping above,
2443 // XIntersectRegion is used to combine paint and user
2444 // regions. XIntersectRegion appears to work in that case...
2445 region
->Union(*rect
);
2451 win
->GetClientSize(&cw
, &ch
);
2452 region
= new wxRegion(wxRect(0, 0, cw
, ch
));
2455 win
->SetUpdateRegion(*region
);
2457 wxRegion
& theRegion(win
->GetUpdateRegion());
2458 theRegion
.SetRects(updateRects
); // We also store in terms of rects, for iteration to work.
2460 // Set the clipping region. Any user-defined region will be combined with this
2461 // one in SetDCClipping.
2462 XSetRegion ((Display
*) m_display
, (GC
) m_gc
, (Region
) region
->GetXRegion());
2467 wxPaintDC::~wxPaintDC()
2469 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
2471 m_window
->ClearUpdateRegion();
2474 // ----------------------------------------------------------------------------
2475 // private functions
2476 // ----------------------------------------------------------------------------
2479 Used when copying between drawables on different (Display*) m_displays. Not
2480 very fast, but better than giving up.
2483 static void XCopyRemote(Display
*src_display
, Display
*dest_display
,
2484 Drawable src
, Drawable dest
,
2487 unsigned int w
, unsigned int h
,
2488 int destx
, int desty
,
2489 bool more
, XImage
**cache
)
2491 XImage
*image
, *destimage
;
2492 Colormap destcm
, srccm
;
2493 static const int CACHE_SIZE
= 256;
2496 unsigned long cachesrc
[CACHE_SIZE
], cachedest
[CACHE_SIZE
];
2497 int k
, cache_pos
, all_cache
;
2499 if (!cache
|| !*cache
)
2500 image
= XGetImage(src_display
, src
, srcx
, srcy
, w
, h
, AllPlanes
, ZPixmap
);
2504 destimage
= XGetImage(dest_display
, dest
, destx
, desty
, w
, h
, AllPlanes
, ZPixmap
);
2506 srccm
= (Colormap
) wxTheApp
->GetMainColormap((WXDisplay
*) src_display
);
2507 destcm
= (Colormap
) wxTheApp
->GetMainColormap((WXDisplay
*) dest_display
);
2512 for (i
= 0; i
< w
; i
++)
2513 for (j
= 0; j
< h
; j
++) {
2514 unsigned long pixel
;
2517 pixel
= XGetPixel(image
, i
, j
);
2518 for (k
= cache_pos
; k
--; )
2519 if (cachesrc
[k
] == pixel
) {
2520 pixel
= cachedest
[k
];
2524 for (k
= CACHE_SIZE
; k
-- > cache_pos
; )
2525 if (cachesrc
[k
] == pixel
) {
2526 pixel
= cachedest
[k
];
2530 cachesrc
[cache_pos
] = xcol
.pixel
= pixel
;
2531 XQueryColor(src_display
, srccm
, &xcol
);
2532 if (!XAllocColor(dest_display
, destcm
, &xcol
))
2534 cachedest
[cache_pos
] = pixel
= xcol
.pixel
;
2536 if (++cache_pos
>= CACHE_SIZE
) {
2542 XPutPixel(destimage
, i
, j
, pixel
);
2545 XPutImage(dest_display
, dest
, destgc
, destimage
, 0, 0, destx
, desty
, w
, h
);
2546 XDestroyImage(destimage
);
2551 XDestroyImage(image
);
2556 /* Helper function for 16-bit fonts */
2557 static int str16len(const char *s
)
2561 while (s
[0] && s
[1]) {