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
WXUNUSED(x1
), wxCoord
WXUNUSED(y1
), wxColour
*WXUNUSED(col
) ) const
240 wxFAIL_MSG("not implemented");
245 void wxWindowDC::DoDrawLine( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
)
247 wxCHECK_RET( Ok(), "invalid dc" );
249 int x1d
, y1d
, x2d
, y2d
;
251 // FreeGetPixelCache();
261 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, x1d
, y1d
, x2d
, y2d
);
263 if (m_window
&& m_window
->GetBackingPixmap())
264 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
265 XLOG2DEV_2(x1
), YLOG2DEV_2(y1
),
266 XLOG2DEV_2(x2
), YLOG2DEV_2(y2
));
268 CalcBoundingBox(x1
, y1
);
269 CalcBoundingBox(x2
, y2
);
272 void wxWindowDC::DoCrossHair( wxCoord x
, wxCoord y
)
274 wxCHECK_RET( Ok(), "invalid dc" );
279 int xx
= XLOG2DEV (x
);
280 int yy
= YLOG2DEV (y
);
282 wxDisplaySize (&ww
, &hh
);
283 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, 0, yy
,
285 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xx
, 0,
288 if (m_window
&& m_window
->GetBackingPixmap())
292 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
295 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
301 void wxWindowDC::DoDrawArc( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
, wxCoord xc
, wxCoord yc
)
303 wxCHECK_RET( Ok(), "invalid dc" );
305 // FreeGetPixelCache();
307 int xx1
= XLOG2DEV (x1
);
308 int yy1
= YLOG2DEV (y1
);
309 int xx2
= XLOG2DEV (x2
);
310 int yy2
= YLOG2DEV (y2
);
311 int xxc
= XLOG2DEV (xc
);
312 int yyc
= YLOG2DEV (yc
);
313 int xxc_2
= XLOG2DEV_2 (xc
);
314 int yyc_2
= YLOG2DEV_2 (yc
);
316 wxCoord dx
= xx1
- xxc
;
317 wxCoord dy
= yy1
- yyc
;
318 double radius
= sqrt (dx
* dx
+ dy
* dy
);
319 wxCoord r
= (wxCoord
) radius
;
321 double radius1
, radius2
;
323 if (xx1
== xx2
&& yy1
== yy2
)
328 else if (radius
== 0.0)
329 radius1
= radius2
= 0.0;
338 radius1
= -atan2 ((double) (yy1
- yyc
), (double) (xx1
- xxc
)) * 360.0 / (2 * M_PI
);
346 radius2
= -atan2 ((double) (yy2
- yyc
), (double) (xx2
- xxc
)) * 360.0 / (2 * M_PI
);
350 int alpha1
= (int) radius1
;
351 int alpha2
= (int) (radius2
- radius1
);
354 while (alpha2
> 360 * 64)
357 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
360 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) (GC
) m_gc
,
361 xxc
- r
, yyc
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
363 if (m_window
&& m_window
->GetBackingPixmap())
364 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
365 xxc_2
- r
, yyc_2
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
369 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
373 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
374 xxc
- r
, yyc
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
376 if (m_window
&& m_window
->GetBackingPixmap())
377 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
378 xxc_2
- r
, yyc_2
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
380 CalcBoundingBox (x1
, y1
);
381 CalcBoundingBox (x2
, y2
);
384 void wxWindowDC::DoDrawEllipticArc( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double sa
, double ea
)
386 wxCHECK_RET( Ok(), "invalid dc" );
392 wd
= XLOG2DEVREL(width
);
393 hd
= YLOG2DEVREL(height
);
395 if (sa
>=360 || sa
<=-360) sa
=sa
-int(sa
/360)*360;
396 if (ea
>=360 || ea
<=-360) ea
=ea
-int(ea
/360)*360;
397 int start
= int(sa
*64);
398 int end
= int(ea
*64);
399 if (start
<0) start
+=360*64;
400 if (end
<0) end
+=360*64;
401 if (end
>start
) end
-=start
;
402 else end
+=360*64-start
;
404 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
406 m_autoSetting
= TRUE
; // must be reset
409 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, start
, end
);
411 if (m_window
&& m_window
->GetBackingPixmap())
412 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
413 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),wd
,hd
,start
,end
);
416 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
420 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, start
,end
);
421 if (m_window
&& m_window
->GetBackingPixmap())
422 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
423 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),wd
,hd
,start
,end
);
425 CalcBoundingBox (x
, y
);
426 CalcBoundingBox (x
+ width
, y
+ height
);
429 void wxWindowDC::DoDrawPoint( wxCoord x
, wxCoord y
)
431 wxCHECK_RET( Ok(), "invalid dc" );
433 // FreeGetPixelCache();
435 if (m_pen
.Ok() && m_autoSetting
)
438 XDrawPoint ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
));
439 if (m_window
&& m_window
->GetBackingPixmap())
440 XDrawPoint ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, XLOG2DEV_2 (x
), YLOG2DEV_2 (y
));
442 CalcBoundingBox (x
, y
);
445 void wxWindowDC::DoDrawLines( int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
)
447 wxCHECK_RET( Ok(), "invalid dc" );
449 // FreeGetPixelCache();
451 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
456 XPoint
*xpoints
= new XPoint
[n
];
459 for (i
= 0; i
< n
; i
++)
461 xpoints
[i
].x
= XLOG2DEV (points
[i
].x
+ xoffset
);
462 xpoints
[i
].y
= YLOG2DEV (points
[i
].y
+ yoffset
);
464 XDrawLines ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xpoints
, n
, 0);
466 if (m_window
&& m_window
->GetBackingPixmap())
468 for (i
= 0; i
< n
; i
++)
470 xpoints
[i
].x
= XLOG2DEV_2 (points
[i
].x
+ xoffset
);
471 xpoints
[i
].y
= YLOG2DEV_2 (points
[i
].y
+ yoffset
);
473 XDrawLines ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, xpoints
, n
, 0);
479 void wxWindowDC::DoDrawPolygon( int n
, wxPoint points
[],
480 wxCoord xoffset
, wxCoord yoffset
, int fillStyle
)
482 wxCHECK_RET( Ok(), "invalid dc" );
484 // FreeGetPixelCache();
486 XPoint
*xpoints1
= new XPoint
[n
+ 1];
487 XPoint
*xpoints2
= new XPoint
[n
+ 1];
489 for (i
= 0; i
< n
; i
++)
491 xpoints1
[i
].x
= XLOG2DEV (points
[i
].x
+ xoffset
);
492 xpoints1
[i
].y
= YLOG2DEV (points
[i
].y
+ yoffset
);
493 xpoints2
[i
].x
= XLOG2DEV_2 (points
[i
].x
+ xoffset
);
494 xpoints2
[i
].y
= YLOG2DEV_2 (points
[i
].y
+ yoffset
);
495 CalcBoundingBox (points
[i
].x
+ xoffset
, points
[i
].y
+ yoffset
);
498 // Close figure for XDrawLines (not needed for XFillPolygon)
499 xpoints1
[i
].x
= xpoints1
[0].x
;
500 xpoints1
[i
].y
= xpoints1
[0].y
;
501 xpoints2
[i
].x
= xpoints2
[0].x
;
502 xpoints2
[i
].y
= xpoints2
[0].y
;
504 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
507 XSetFillRule ((Display
*) m_display
, (GC
) m_gc
, fillStyle
== wxODDEVEN_RULE
? EvenOddRule
: WindingRule
);
508 XFillPolygon ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xpoints1
, n
, Complex
, 0);
509 XSetFillRule ((Display
*) m_display
, (GC
) m_gc
, EvenOddRule
); // default mode
510 if (m_window
&& m_window
->GetBackingPixmap())
512 XSetFillRule ((Display
*) m_display
,(GC
) m_gcBacking
,
513 fillStyle
== wxODDEVEN_RULE
? EvenOddRule
: WindingRule
);
514 XFillPolygon ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, xpoints2
, n
, Complex
, 0);
515 XSetFillRule ((Display
*) m_display
,(GC
) m_gcBacking
, EvenOddRule
); // default mode
519 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
523 XDrawLines ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xpoints1
, n
+ 1, 0);
525 if (m_window
&& m_window
->GetBackingPixmap())
526 XDrawLines ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, xpoints2
, n
+ 1, 0);
533 void wxWindowDC::DoDrawRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
535 wxCHECK_RET( Ok(), "invalid dc" );
537 // FreeGetPixelCache();
539 int xd
, yd
, wfd
, hfd
, wd
, hd
;
543 wfd
= XLOG2DEVREL(width
);
545 hfd
= YLOG2DEVREL(height
);
548 if (wfd
== 0 || hfd
== 0) return;
549 if (wd
< 0) { wd
= - wd
; xd
= xd
- wd
; }
550 if (hd
< 0) { hd
= - hd
; yd
= yd
- hd
; }
552 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
555 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wfd
, hfd
);
557 if (m_window
&& m_window
->GetBackingPixmap())
558 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
559 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
563 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
567 XDrawRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
);
569 if (m_window
&& m_window
->GetBackingPixmap())
570 XDrawRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
571 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
574 CalcBoundingBox (x
, y
);
575 CalcBoundingBox (x
+ width
, y
+ height
);
578 void wxWindowDC::DoDrawRoundedRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double radius
)
580 wxCHECK_RET( Ok(), "invalid dc" );
582 // FreeGetPixelCache();
584 // If radius is negative, it's a proportion of the smaller dimension.
586 if (radius
< 0.0) radius
= - radius
* ((width
< height
) ? width
: height
);
588 int xd
= XLOG2DEV (x
);
589 int yd
= YLOG2DEV (y
);
590 int rd
= XLOG2DEVREL ((long) radius
);
591 int wd
= XLOG2DEVREL (width
) - WX_GC_CF
;
592 int hd
= YLOG2DEVREL (height
) - WX_GC_CF
;
597 // If radius is zero use DrawRectangle() instead to avoid
598 // X drawing errors with small radii
601 DrawRectangle( x
, y
, width
, height
);
605 // Draw nothing if transformed w or h is 0
606 if (wd
== 0 || hd
== 0) return;
608 // CMB: adjust size if outline is drawn otherwise the result is
609 // 1 pixel too wide and high
610 if (m_pen
.GetStyle() != wxTRANSPARENT
)
616 // CMB: ensure dd is not larger than rectangle otherwise we
617 // get an hour glass shape
618 if (rw_d
> wd
) rw_d
= wd
;
619 if (rw_d
> hd
) rw_d
= hd
;
622 // For backing pixmap
623 int xd2
= XLOG2DEV_2 (x
);
624 int yd2
= YLOG2DEV_2 (y
);
625 int rd2
= XLOG2DEVREL ((long) radius
);
626 int wd2
= XLOG2DEVREL (width
) ;
627 int hd2
= YLOG2DEVREL (height
) ;
632 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
636 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ rd
, yd
,
638 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ rd
,
641 // Arcs start from 3 o'clock, positive angles anticlockwise
643 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
,
644 rw_d
, rh_d
, 90 * 64, 90 * 64);
646 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
, yd
,
647 // rw_d, rh_d, 0, 90 * 64);
648 rw_d
, rh_d
, 0, 91 * 64);
650 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
,
652 // rw_d, rh_d, 270 * 64, 90 * 64);
653 rw_d
, rh_d
, 269 * 64, 92 * 64);
655 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ hd
- rh_d
,
656 rw_d
, rh_d
, 180 * 64, 90 * 64);
658 if (m_window
&& m_window
->GetBackingPixmap())
660 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
661 xd2
+ rd2
, yd2
, wd2
- rw_d2
, hd2
);
662 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
663 xd2
, yd2
+ rd2
, wd2
, hd2
- rh_d2
);
665 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
666 xd2
, yd2
, rw_d2
, rh_d2
, 90 * 64, 90 * 64);
667 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
668 xd2
+ wd2
- rw_d2
, yd2
,
669 // rw_d2, rh_d2, 0, 90 * 64);
670 rw_d2
, rh_d2
, 0, 91 * 64);
671 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
674 // rw_d2, rh_d2, 270 * 64, 90 * 64);
675 rw_d2
, rh_d2
, 269 * 64, 92 * 64);
676 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
677 xd2
, yd2
+ hd2
- rh_d2
,
678 rw_d2
, rh_d2
, 180 * 64, 90 * 64);
682 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
685 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ rd
, yd
,
686 xd
+ wd
- rd
+ 1, yd
);
687 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ rd
, yd
+ hd
,
688 xd
+ wd
- rd
, yd
+ hd
);
690 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ rd
,
692 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
, yd
+ rd
,
693 xd
+ wd
, yd
+ hd
- rd
+ 1);
694 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
,
695 rw_d
, rh_d
, 90 * 64, 90 * 64);
696 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
, yd
,
697 // rw_d, rh_d, 0, 90 * 64);
698 rw_d
, rh_d
, 0, 91 * 64);
699 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
,
701 rw_d
, rh_d
, 269 * 64, 92 * 64);
702 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ hd
- rh_d
,
703 rw_d
, rh_d
, 180 * 64, 90 * 64);
705 if (m_window
&& m_window
->GetBackingPixmap())
707 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
709 xd2
+ wd2
- rd2
+ 1, yd2
);
710 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
711 xd2
+ rd2
, yd2
+ hd2
,
712 xd2
+ wd2
- rd2
, yd2
+ hd2
);
714 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
716 xd2
, yd2
+ hd2
- rd2
);
717 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
718 xd2
+ wd2
, yd2
+ rd2
,
719 xd2
+ wd2
, yd2
+ hd2
- rd2
+ 1);
720 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
722 rw_d2
, rh_d2
, 90 * 64, 90 * 64);
723 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
724 xd2
+ wd2
- rw_d2
, yd2
,
725 // rw_d2, rh_d2, 0, 90 * 64);
726 rw_d2
, rh_d2
, 0, 91 * 64);
727 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
730 rw_d2
, rh_d2
, 269 * 64, 92 * 64);
731 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
732 xd2
, yd2
+ hd2
- rh_d2
,
733 rw_d2
, rh_d2
, 180 * 64, 90 * 64);
736 CalcBoundingBox (x
, y
);
737 CalcBoundingBox (x
+ width
, y
+ height
);
742 void wxWindowDC::DoDrawEllipse( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
744 wxCHECK_RET( Ok(), "invalid dc" );
746 // Check for negative width and height
759 // FreeGetPixelCache();
761 static const int angle
= 23040;
767 wd
= XLOG2DEVREL(width
) ;
768 hd
= YLOG2DEVREL(height
) ;
770 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
773 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, 0, angle
);
774 if (m_window
&& m_window
->GetBackingPixmap())
775 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
776 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
777 XLOG2DEVREL (width
) - WX_GC_CF
,
778 YLOG2DEVREL (height
) - WX_GC_CF
, 0, angle
);
781 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
785 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, 0, angle
);
786 if (m_window
&& m_window
->GetBackingPixmap())
787 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
788 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
789 XLOG2DEVREL (width
) - WX_GC_CF
,
790 YLOG2DEVREL (height
) - WX_GC_CF
, 0, angle
);
792 CalcBoundingBox (x
, y
);
793 CalcBoundingBox (x
+ width
, y
+ height
);
797 bool wxWindowDC::CanDrawBitmap() const
799 wxCHECK_MSG( Ok(), FALSE
, "invalid dc" );
805 void wxWindowDC::DoDrawIcon( const wxIcon
&icon
, wxCoord x
, wxCoord y
)
807 // FreeGetPixelCache();
809 // Be sure that foreground pixels (1) of
810 // the Icon will be painted with pen colour. [m_pen.SetColour()]
811 // Background pixels (0) will be painted with
812 // last selected background color. [::SetBackground]
813 if (m_pen
.Ok() && m_autoSetting
)
817 Pixmap iconPixmap
= (Pixmap
) icon
.GetPixmap();
818 width
= icon
.GetWidth();
819 height
= icon
.GetHeight();
820 if (icon
.GetDisplay() == m_display
)
822 if (icon
.GetDepth() <= 1)
824 XCopyPlane ((Display
*) m_display
, iconPixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
826 (int) XLOG2DEV (x
), (int) YLOG2DEV (y
), 1);
830 XCopyArea ((Display
*) m_display
, iconPixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
832 (int) XLOG2DEV (x
), (int) YLOG2DEV (y
));
836 if (m_window
&& m_window
->GetBackingPixmap())
838 if (icon
.GetDepth() <= 1)
840 XCopyPlane ((Display
*) m_display
, iconPixmap
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
841 0, 0, width
, height
, (int) XLOG2DEV_2 (x
), (int) YLOG2DEV_2 (y
), 1);
845 XCopyArea ((Display
*) m_display
, iconPixmap
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
847 (int) XLOG2DEV_2 (x
), (int) YLOG2DEV_2 (y
));
850 } else { /* Remote copy (different (Display*) m_displays) */
851 XImage
*cache
= NULL
;
852 if (m_window
&& m_window
->GetBackingPixmap())
853 XCopyRemote((Display
*) icon
.GetDisplay(), (Display
*) m_display
, iconPixmap
, (Pixmap
) m_window
->GetBackingPixmap(),
854 (GC
) m_gcBacking
, 0, 0, width
, height
,
855 (int) XLOG2DEV_2 (x
), (int) YLOG2DEV_2 (y
), TRUE
, &cache
);
856 XCopyRemote((Display
*) icon
.GetDisplay(), (Display
*) m_display
, iconPixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
858 (int) XLOG2DEV (x
), (int) YLOG2DEV (y
), FALSE
, &cache
);
860 CalcBoundingBox (x
, y
);
864 // TODO: use scaled Blit e.g. as per John Price's implementation in Contrib/Utilities
865 bool wxWindowDC::DoBlit( wxCoord xdest
, wxCoord ydest
, wxCoord width
, wxCoord height
,
866 wxDC
*source
, wxCoord xsrc
, wxCoord ysrc
, int rop
, bool useMask
)
868 wxCHECK_MSG( Ok(), FALSE
, "invalid dc" );
870 wxWindowDC
* sourceDC
= wxDynamicCast(source
, wxWindowDC
);
872 wxASSERT_MSG( sourceDC
, "Blit source DC must be wxWindowDC or derived class." );
874 // FreeGetPixelCache();
876 // Be sure that foreground pixels (1) of the Icon will be painted with pen
877 // colour. [m_pen.SetColour()] Background pixels (0) will be painted with
878 // last selected background color. [::SetBackground]
879 if (m_pen
.Ok() && m_autoSetting
)
882 // Do bitmap scaling if necessary
884 wxBitmap
*scaledBitmap
= (wxBitmap
*) NULL
;
885 Pixmap sourcePixmap
= (Pixmap
) NULL
;
886 double scaleX
, scaleY
;
887 GetUserScale(& scaleX
, & scaleY
);
889 // Sorry, can't scale masks just yet
890 if (!useMask
&& (scaleX
!= 1.0 || scaleY
!= 1.0) && sourceDC
->IsKindOf(CLASSINFO(wxMemoryDC
)))
892 wxMemoryDC
* memDC
= (wxMemoryDC
*) sourceDC
;
893 wxBitmap
& bitmap
= memDC
->GetBitmap();
895 wxASSERT_MSG( (bitmap
.Ok()), "Bad source bitmap in wxWindowDC::Blit");
897 wxImage
image(bitmap
);
900 sourcePixmap
= (Pixmap
) bitmap
.GetPixmap();
904 int scaledW
= (int) (bitmap
.GetWidth() * scaleX
);
905 int scaledH
= (int) (bitmap
.GetHeight() * scaleY
);
907 image
= image
.Scale(scaledW
, scaledH
);
908 scaledBitmap
= new wxBitmap(image
.ConvertToBitmap());
909 sourcePixmap
= (Pixmap
) scaledBitmap
->GetPixmap();
913 sourcePixmap
= (Pixmap
) sourceDC
->m_pixmap
;
915 if (m_pixmap
&& sourcePixmap
)
918 int orig
= m_logicalFunction
;
920 SetLogicalFunction (rop
);
922 if (m_display
!= sourceDC
->m_display
)
924 XImage
*cache
= NULL
;
926 if (m_window
&& m_window
->GetBackingPixmap())
927 XCopyRemote((Display
*) sourceDC
->m_display
, (Display
*) m_display
,
928 (Pixmap
) sourcePixmap
, (Pixmap
) m_window
->GetBackingPixmap(),
930 source
->LogicalToDeviceX (xsrc
),
931 source
->LogicalToDeviceY (ysrc
),
932 source
->LogicalToDeviceXRel(width
),
933 source
->LogicalToDeviceYRel(height
),
934 XLOG2DEV_2 (xdest
), YLOG2DEV_2 (ydest
),
937 if ( useMask
&& source
->IsKindOf(CLASSINFO(wxMemoryDC
)) )
939 wxMemoryDC
*memDC
= (wxMemoryDC
*)source
;
940 wxBitmap
& sel
= memDC
->GetBitmap();
941 if ( sel
.Ok() && sel
.GetMask() && sel
.GetMask()->GetPixmap() )
943 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) sel
.GetMask()->GetPixmap());
944 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, XLOG2DEV (xdest
), YLOG2DEV (ydest
));
948 XCopyRemote((Display
*) sourceDC
->m_display
, (Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
949 source
->LogicalToDeviceX (xsrc
),
950 source
->LogicalToDeviceY (ysrc
),
951 source
->LogicalToDeviceXRel(width
),
952 source
->LogicalToDeviceYRel(height
),
953 XLOG2DEV (xdest
), YLOG2DEV (ydest
),
958 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
959 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, 0, 0);
964 if (m_window
&& m_window
->GetBackingPixmap())
966 // +++ MARKUS (mho@comnets.rwth-aachen): error on blitting bitmaps with depth 1
967 if (source
->IsKindOf(CLASSINFO(wxMemoryDC
)) && ((wxMemoryDC
*) source
)->GetBitmap().GetDepth() == 1)
969 XCopyPlane ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
970 source
->LogicalToDeviceX (xsrc
),
971 source
->LogicalToDeviceY (ysrc
),
972 source
->LogicalToDeviceXRel(width
),
973 source
->LogicalToDeviceYRel(height
),
974 XLOG2DEV_2 (xdest
), YLOG2DEV_2 (ydest
), 1);
978 XCopyArea ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
979 source
->LogicalToDeviceX (xsrc
),
980 source
->LogicalToDeviceY (ysrc
),
981 source
->LogicalToDeviceXRel(width
),
982 source
->LogicalToDeviceYRel(height
),
983 XLOG2DEV_2 (xdest
), YLOG2DEV_2 (ydest
));
986 if ( useMask
&& source
->IsKindOf(CLASSINFO(wxMemoryDC
)) )
988 wxMemoryDC
*memDC
= (wxMemoryDC
*)source
;
989 wxBitmap
& sel
= memDC
->GetBitmap();
990 if ( sel
.Ok() && sel
.GetMask() && sel
.GetMask()->GetPixmap() )
992 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) sel
.GetMask()->GetPixmap());
993 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, XLOG2DEV (xdest
), YLOG2DEV (ydest
));
997 // Check if we're copying from a mono bitmap
998 if (source
->IsKindOf(CLASSINFO(wxMemoryDC
)) &&
999 ((wxMemoryDC
*)source
)->GetBitmap().Ok() && (((wxMemoryDC
*)source
)->GetBitmap().GetDepth () == 1))
1001 XCopyPlane ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
1002 source
->LogicalToDeviceX (xsrc
),
1003 source
->LogicalToDeviceY (ysrc
),
1004 source
->LogicalToDeviceXRel(width
),
1005 source
->LogicalToDeviceYRel(height
),
1006 XLOG2DEV (xdest
), YLOG2DEV (ydest
), 1);
1010 XCopyArea ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
1011 source
->LogicalToDeviceX (xsrc
),
1012 source
->LogicalToDeviceY (ysrc
),
1013 source
->LogicalToDeviceXRel(width
),
1014 source
->LogicalToDeviceYRel(height
),
1015 XLOG2DEV (xdest
), YLOG2DEV (ydest
));
1020 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
1021 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, 0, 0);
1024 } /* Remote/local (Display*) m_display */
1025 CalcBoundingBox (xdest
, ydest
);
1026 CalcBoundingBox (xdest
+ width
, ydest
+ height
);
1028 SetLogicalFunction(orig
);
1030 if (scaledBitmap
) delete scaledBitmap
;
1034 if (scaledBitmap
) delete scaledBitmap
;
1039 void wxWindowDC::DoDrawText( const wxString
&text
, wxCoord x
, wxCoord y
)
1041 wxCHECK_RET( Ok(), "invalid dc" );
1043 // Since X draws from the baseline of the text, must add the text height
1049 slen
= strlen(text
);
1053 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1054 int direction
, descent
;
1055 XCharStruct overall_return
;
1058 (void)XTextExtents16((XFontStruct
*) pFontStruct
, (XChar2b
*)(const char*) text
, slen
, &direction
,
1059 &ascent
, &descent
, &overall_return
);
1062 (void)XTextExtents((XFontStruct
*) pFontStruct
, (char*) (const char*) text
, slen
, &direction
,
1063 &ascent
, &descent
, &overall_return
);
1065 cx
= overall_return
.width
;
1066 cy
= ascent
+ descent
;
1069 // First draw a rectangle representing the text background, if a text
1070 // background is specified
1071 if (m_textBackgroundColour
.Ok () && (m_backgroundMode
!= wxTRANSPARENT
))
1073 wxColour oldPenColour
= m_currentColour
;
1074 m_currentColour
= m_textBackgroundColour
;
1075 bool sameColour
= (oldPenColour
.Ok () && m_textBackgroundColour
.Ok () &&
1076 (oldPenColour
.Red () == m_textBackgroundColour
.Red ()) &&
1077 (oldPenColour
.Blue () == m_textBackgroundColour
.Blue ()) &&
1078 (oldPenColour
.Green () == m_textBackgroundColour
.Green ()));
1080 // This separation of the big && test required for gcc2.7/HP UX 9.02
1081 // or pixel value can be corrupted!
1082 sameColour
= (sameColour
&&
1083 (oldPenColour
.GetPixel() == m_textBackgroundColour
.GetPixel()));
1085 if (!sameColour
|| !GetOptimization())
1087 int pixel
= m_textBackgroundColour
.AllocColour(m_display
);
1088 m_currentColour
= m_textBackgroundColour
;
1090 // Set the GC to the required colour
1093 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1094 if (m_window
&& m_window
->GetBackingPixmap())
1095 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1099 m_textBackgroundColour
= oldPenColour
;
1101 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
), cx
, cy
);
1102 if (m_window
&& m_window
->GetBackingPixmap())
1103 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
1104 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
), cx
, cy
);
1107 // Now set the text foreground and draw the text
1108 if (m_textForegroundColour
.Ok ())
1110 wxColour oldPenColour
= m_currentColour
;
1111 m_currentColour
= m_textForegroundColour
;
1112 bool sameColour
= (oldPenColour
.Ok () && m_currentColour
.Ok () &&
1113 (oldPenColour
.Red () == m_currentColour
.Red ()) &&
1114 (oldPenColour
.Blue () == m_currentColour
.Blue ()) &&
1115 (oldPenColour
.Green () == m_currentColour
.Green ()) &&
1116 (oldPenColour
.GetPixel() == m_currentColour
.GetPixel()));
1118 if (!sameColour
|| !GetOptimization())
1121 if (!m_colour
) // Mono display
1123 // Unless foreground is really white, draw it in black
1124 unsigned char red
= m_textForegroundColour
.Red ();
1125 unsigned char blue
= m_textForegroundColour
.Blue ();
1126 unsigned char green
= m_textForegroundColour
.Green ();
1127 if (red
== (unsigned char) 255 && blue
== (unsigned char) 255
1128 && green
== (unsigned char) 255)
1130 m_currentColour
= *wxWHITE
;
1131 pixel
= (int) WhitePixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1132 m_currentColour
.SetPixel(pixel
);
1133 m_textForegroundColour
.SetPixel(pixel
);
1137 m_currentColour
= *wxBLACK
;
1138 pixel
= (int) BlackPixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1139 m_currentColour
.SetPixel(pixel
);
1140 m_textForegroundColour
.SetPixel(pixel
);
1145 pixel
= m_textForegroundColour
.AllocColour((Display
*) m_display
);
1146 m_currentColour
.SetPixel(pixel
);
1149 // Set the GC to the required colour
1152 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1153 if (m_window
&& m_window
->GetBackingPixmap())
1154 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1158 m_textForegroundColour
= oldPenColour
;
1161 // We need to add the ascent, not the whole height, since X draws at the
1162 // point above the descender.
1165 XDrawString16((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
) + ascent
,
1166 (XChar2b
*)(char*) (const char*) text
, slen
);
1169 XDrawString((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
) + ascent
, text
, slen
);
1171 if (m_window
&& m_window
->GetBackingPixmap()) {
1174 XDrawString16((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
1175 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
) + ascent
,
1176 (XChar2b
*)(char*) (const char*) text
, slen
);
1179 XDrawString((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
1180 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
) + ascent
, (char*) (const char*) text
, slen
);
1184 GetTextExtent (text
, &w
, &h
);
1185 CalcBoundingBox (x
+ w
, y
+ h
);
1186 CalcBoundingBox (x
, y
);
1189 void wxWindowDC::DoDrawRotatedText( const wxString
&text
, wxCoord x
, wxCoord y
, double angle
)
1193 DrawText(text
, x
, y
);
1197 wxCHECK_RET( Ok(), "invalid dc" );
1199 // Since X draws from the baseline of the text, must add the text height
1205 slen
= strlen(text
);
1209 // Calculate text extent.
1210 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1211 int direction
, descent
;
1212 XCharStruct overall_return
;
1215 (void)XTextExtents16((XFontStruct
*) pFontStruct
, (XChar2b
*)(const char*) text
, slen
, &direction
,
1216 &ascent
, &descent
, &overall_return
);
1219 (void)XTextExtents((XFontStruct
*) pFontStruct
, (char*) (const char*) text
, slen
, &direction
,
1220 &ascent
, &descent
, &overall_return
);
1222 cx
= overall_return
.width
;
1223 cy
= ascent
+ descent
;
1226 wxBitmap
src(cx
, cy
);
1228 dc
.SelectObject(src
);
1229 dc
.SetFont(GetFont());
1230 dc
.SetBackground(*wxWHITE_BRUSH
);
1231 dc
.SetBrush(*wxBLACK_BRUSH
);
1233 dc
.DrawText(text
, 0, 0);
1234 dc
.SetFont(wxNullFont
);
1236 // Calculate the size of the rotated bounding box.
1237 double dx
= cos(angle
/ 180.0 * M_PI
);
1238 double dy
= sin(angle
/ 180.0 * M_PI
);
1239 double x4
= -cy
* dy
;
1240 double y4
= cy
* dx
;
1241 double x3
= cx
* dx
;
1242 double y3
= cx
* dy
;
1243 double x2
= x3
+ x4
;
1244 double y2
= y3
+ y4
;
1248 // Create image from the source bitmap after writing the text into it.
1251 int minx
= roundmin(0, roundmin(x4
, roundmin(x2
, x3
)));
1252 int miny
= roundmin(0, roundmin(y4
, roundmin(y2
, y3
)));
1253 int maxx
= roundmax(0, roundmax(x4
, roundmax(x2
, x3
)));
1254 int maxy
= roundmax(0, roundmax(y4
, roundmax(y2
, y3
)));
1256 // This rotates counterclockwise around the top left corner.
1257 for (int rx
= minx
; rx
< maxx
; rx
++)
1259 for (int ry
= miny
; ry
< maxy
; ry
++)
1261 // transform dest coords to source coords
1262 int sx
= (int) (rx
* dx
+ ry
* dy
+ 0.5);
1263 int sy
= (int) (ry
* dx
- rx
* dy
+ 0.5);
1264 if (sx
>= 0 && sx
< cx
&& sy
>= 0 && sy
< cy
)
1266 // draw black pixels, ignore white ones (i.e. transparent b/g)
1267 if (image
.GetRed(sx
, sy
) == 0)
1269 DrawPoint(x1
+ maxx
- rx
, cy
+ y1
- ry
);
1274 //DrawPoint(x1 + maxx - rx, cy + y1 + maxy - ry);
1281 // First draw a rectangle representing the text background, if a text
1282 // background is specified
1283 if (m_textBackgroundColour
.Ok () && (m_backgroundMode
!= wxTRANSPARENT
))
1285 wxColour oldPenColour
= m_currentColour
;
1286 m_currentColour
= m_textBackgroundColour
;
1287 bool sameColour
= (oldPenColour
.Ok () && m_textBackgroundColour
.Ok () &&
1288 (oldPenColour
.Red () == m_textBackgroundColour
.Red ()) &&
1289 (oldPenColour
.Blue () == m_textBackgroundColour
.Blue ()) &&
1290 (oldPenColour
.Green () == m_textBackgroundColour
.Green ()));
1292 // This separation of the big && test required for gcc2.7/HP UX 9.02
1293 // or pixel value can be corrupted!
1294 sameColour
= (sameColour
&&
1295 (oldPenColour
.GetPixel() == m_textBackgroundColour
.GetPixel()));
1297 if (!sameColour
|| !GetOptimization())
1299 int pixel
= m_textBackgroundColour
.AllocColour(m_display
);
1300 m_currentColour
= m_textBackgroundColour
;
1302 // Set the GC to the required colour
1305 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1306 if (m_window
&& m_window
->GetBackingPixmap())
1307 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1311 m_textBackgroundColour
= oldPenColour
;
1313 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
), cx
, cy
);
1314 if (m_window
&& m_window
->GetBackingPixmap())
1315 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
1316 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
), cx
, cy
);
1321 // XXX use pixmap size
1322 GetTextExtent (text
, &w
, &h
);
1323 CalcBoundingBox (x
+ w
, y
+ h
);
1324 CalcBoundingBox (x
, y
);
1327 bool wxWindowDC::CanGetTextExtent() const
1332 void wxWindowDC::DoGetTextExtent( const wxString
&string
, wxCoord
*width
, wxCoord
*height
,
1333 wxCoord
*descent
, wxCoord
*externalLeading
,
1334 wxFont
*font
) const
1336 wxCHECK_RET( Ok(), "invalid dc" );
1338 wxFont
* theFont
= font
;
1340 theFont
= (wxFont
*)&m_font
; // const_cast
1344 // TODO: this should be an error log function
1345 wxFAIL_MSG("set a valid font before calling GetTextExtent!");
1347 if (width
) *width
= -1;
1348 if (height
) *height
= -1;
1352 WXFontStructPtr pFontStruct
= theFont
->GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1354 int direction
, ascent
, descent2
;
1355 XCharStruct overall
;
1360 slen
= str16len(string
);
1363 slen
= strlen(string
);
1367 XTextExtents16((XFontStruct
*) pFontStruct
, (XChar2b
*) (char*) (const char*) string
, slen
, &direction
,
1368 &ascent
, &descent2
, &overall
);
1371 XTextExtents((XFontStruct
*) pFontStruct
, (char*) (const char*) string
, slen
, &direction
,
1372 &ascent
, &descent2
, &overall
);
1374 if (width
) *width
= XDEV2LOGREL (overall
.width
);
1375 if (height
) *height
= YDEV2LOGREL (ascent
+ descent2
);
1377 *descent
= descent2
;
1378 if (externalLeading
)
1379 *externalLeading
= 0;
1382 wxCoord
wxWindowDC::GetCharWidth() const
1384 wxCHECK_MSG( Ok(), 0, "invalid dc" );
1385 wxCHECK_MSG( m_font
.Ok(), 0, "invalid font" );
1387 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
* m_logicalScaleY
, m_display
);
1389 int direction
, ascent
, descent
;
1390 XCharStruct overall
;
1391 XTextExtents ((XFontStruct
*) pFontStruct
, "x", 1, &direction
, &ascent
,
1392 &descent
, &overall
);
1393 return XDEV2LOGREL(overall
.width
);
1396 wxCoord
wxWindowDC::GetCharHeight() const
1398 wxCHECK_MSG( Ok(), 0, "invalid dc" );
1399 wxCHECK_MSG( m_font
.Ok(), 0, "invalid font" );
1401 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1403 int direction
, ascent
, descent
;
1404 XCharStruct overall
;
1405 XTextExtents ((XFontStruct
*) pFontStruct
, "x", 1, &direction
, &ascent
,
1406 &descent
, &overall
);
1407 // return XDEV2LOGREL(overall.ascent + overall.descent);
1408 return XDEV2LOGREL(ascent
+ descent
);
1411 void wxWindowDC::Clear()
1413 wxCHECK_RET( Ok(), "invalid dc" );
1418 m_window
->GetSize(&w
, &h
);
1420 if (m_window
&& m_window
->GetBackingPixmap())
1422 w
= m_window
->GetPixmapWidth();
1423 h
= m_window
->GetPixmapHeight();
1428 if (this->IsKindOf(CLASSINFO(wxMemoryDC
)))
1430 wxMemoryDC
* memDC
= (wxMemoryDC
*) this;
1431 w
= memDC
->GetBitmap().GetWidth();
1432 h
= memDC
->GetBitmap().GetHeight();
1438 wxBrush saveBrush
= m_brush
;
1439 SetBrush (m_backgroundBrush
);
1441 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, 0, 0, w
, h
);
1443 if (m_window
&& m_window
->GetBackingPixmap())
1444 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, 0, 0, w
, h
);
1446 m_brush
= saveBrush
;
1449 void wxWindowDC::Clear(const wxRect
& rect
)
1451 wxCHECK_RET( Ok(), "invalid dc" );
1453 int x
= rect
.x
; int y
= rect
.y
;
1454 int w
= rect
.width
; int h
= rect
.height
;
1456 wxBrush saveBrush
= m_brush
;
1457 SetBrush (m_backgroundBrush
);
1459 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, x
, y
, w
, h
);
1461 if (m_window
&& m_window
->GetBackingPixmap())
1462 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, x
, y
, w
, h
);
1464 m_brush
= saveBrush
;
1467 void wxWindowDC::SetFont( const wxFont
&font
)
1469 wxCHECK_RET( Ok(), "invalid dc" );
1475 if ((m_oldFont
!= (WXFont
) 0) && ((wxCoord
) m_oldFont
!= -1))
1477 XSetFont ((Display
*) m_display
, (GC
) m_gc
, (Font
) m_oldFont
);
1479 if (m_window
&& m_window
->GetBackingPixmap())
1480 XSetFont ((Display
*) m_display
,(GC
) m_gcBacking
, (Font
) m_oldFont
);
1485 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1487 Font fontId
= ((XFontStruct
*)pFontStruct
)->fid
;
1488 XSetFont ((Display
*) m_display
, (GC
) m_gc
, fontId
);
1490 if (m_window
&& m_window
->GetBackingPixmap())
1491 XSetFont ((Display
*) m_display
,(GC
) m_gcBacking
, fontId
);
1494 void wxWindowDC::SetPen( const wxPen
&pen
)
1496 wxCHECK_RET( Ok(), "invalid dc" );
1502 wxBitmap oldStipple
= m_currentStipple
;
1503 int oldStyle
= m_currentStyle
;
1504 int oldFill
= m_currentFill
;
1505 int old_pen_width
= m_currentPenWidth
;
1506 int old_pen_join
= m_currentPenJoin
;
1507 int old_pen_cap
= m_currentPenCap
;
1508 int old_pen_nb_dash
= m_currentPenDashCount
;
1509 char *old_pen_dash
= m_currentPenDash
;
1511 wxColour oldPenColour
= m_currentColour
;
1512 m_currentColour
= m_pen
.GetColour ();
1513 m_currentStyle
= m_pen
.GetStyle ();
1514 m_currentFill
= m_pen
.GetStyle (); // TODO?
1515 m_currentPenWidth
= m_pen
.GetWidth ();
1516 m_currentPenJoin
= m_pen
.GetJoin ();
1517 m_currentPenCap
= m_pen
.GetCap ();
1518 m_currentPenDashCount
= m_pen
.GetDashCount();
1519 m_currentPenDash
= m_pen
.GetDash();
1521 if (m_currentStyle
== wxSTIPPLE
)
1522 m_currentStipple
= * m_pen
.GetStipple ();
1524 bool sameStyle
= (oldStyle
== m_currentStyle
&&
1525 oldFill
== m_currentFill
&&
1526 old_pen_join
== m_currentPenJoin
&&
1527 old_pen_cap
== m_currentPenCap
&&
1528 old_pen_nb_dash
== m_currentPenDashCount
&&
1529 old_pen_dash
== m_currentPenDash
&&
1530 old_pen_width
== m_currentPenWidth
);
1532 bool sameColour
= (oldPenColour
.Ok () &&
1533 (oldPenColour
.Red () == m_currentColour
.Red ()) &&
1534 (oldPenColour
.Blue () == m_currentColour
.Blue ()) &&
1535 (oldPenColour
.Green () == m_currentColour
.Green ()) &&
1536 (oldPenColour
.GetPixel() == m_currentColour
.GetPixel()));
1538 if (!sameStyle
|| !GetOptimization())
1540 int scaled_width
= (int) XLOG2DEVREL (m_pen
.GetWidth ());
1541 if (scaled_width
< 0)
1547 static const char dotted
[] = {2, 5};
1548 static const char short_dashed
[] = {4, 4};
1549 static const char long_dashed
[] = {4, 8};
1550 static const char dotted_dashed
[] = {6, 6, 2, 6};
1552 // We express dash pattern in pen width unit, so we are
1553 // independent of zoom factor and so on...
1555 const char *req_dash
;
1557 switch (m_pen
.GetStyle ())
1560 req_nb_dash
= m_currentPenDashCount
;
1561 req_dash
= m_currentPenDash
;
1562 style
= LineOnOffDash
;
1567 style
= LineOnOffDash
;
1571 req_dash
= short_dashed
;
1572 style
= LineOnOffDash
;
1576 req_dash
= long_dashed
;
1577 style
= LineOnOffDash
;
1581 req_dash
= dotted_dashed
;
1582 style
= LineOnOffDash
;
1593 if (req_dash
&& req_nb_dash
)
1595 char *real_req_dash
= new char[req_nb_dash
];
1598 int factor
= scaled_width
== 0 ? 1 : scaled_width
;
1599 for (int i
= 0; i
< req_nb_dash
; i
++)
1600 real_req_dash
[i
] = req_dash
[i
] * factor
;
1601 XSetDashes ((Display
*) m_display
, (GC
) m_gc
, 0, real_req_dash
, req_nb_dash
);
1603 if (m_window
&& m_window
->GetBackingPixmap())
1604 XSetDashes ((Display
*) m_display
,(GC
) m_gcBacking
, 0, real_req_dash
, req_nb_dash
);
1605 delete[]real_req_dash
;
1609 // No Memory. We use non-scaled dash pattern...
1610 XSetDashes ((Display
*) m_display
, (GC
) m_gc
, 0, req_dash
, req_nb_dash
);
1612 if (m_window
&& m_window
->GetBackingPixmap())
1613 XSetDashes ((Display
*) m_display
,(GC
) m_gcBacking
, 0, req_dash
, req_nb_dash
);
1617 switch (m_pen
.GetCap ())
1619 case wxCAP_PROJECTING
:
1620 cap
= CapProjecting
;
1627 cap
= (scaled_width
<= 1) ? CapNotLast
: CapRound
;
1631 switch (m_pen
.GetJoin ())
1645 XSetLineAttributes ((Display
*) m_display
, (GC
) m_gc
, scaled_width
, style
, cap
, join
);
1647 if (m_window
&& m_window
->GetBackingPixmap())
1648 XSetLineAttributes ((Display
*) m_display
,(GC
) m_gcBacking
, scaled_width
, style
, cap
, join
);
1651 if (IS_HATCH(m_currentFill
) && ((m_currentFill
!= oldFill
) || !GetOptimization()))
1655 oldStipple
= wxNullBitmap
; // For later reset!!
1657 switch (m_currentFill
)
1659 case wxBDIAGONAL_HATCH
:
1660 if (bdiag
== (Pixmap
) 0)
1661 bdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1662 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1663 bdiag_bits
, bdiag_width
, bdiag_height
);
1666 case wxFDIAGONAL_HATCH
:
1667 if (fdiag
== (Pixmap
) 0)
1668 fdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1669 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1670 fdiag_bits
, fdiag_width
, fdiag_height
);
1674 if (cross
== (Pixmap
) 0)
1675 cross
= XCreateBitmapFromData ((Display
*) m_display
,
1676 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1677 cross_bits
, cross_width
, cross_height
);
1680 case wxHORIZONTAL_HATCH
:
1681 if (horiz
== (Pixmap
) 0)
1682 horiz
= XCreateBitmapFromData ((Display
*) m_display
,
1683 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1684 horiz_bits
, horiz_width
, horiz_height
);
1687 case wxVERTICAL_HATCH
:
1688 if (verti
== (Pixmap
) 0)
1689 verti
= XCreateBitmapFromData ((Display
*) m_display
,
1690 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1691 verti_bits
, verti_width
, verti_height
);
1694 case wxCROSSDIAG_HATCH
:
1696 if (cdiag
== (Pixmap
) 0)
1697 cdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1698 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1699 cdiag_bits
, cdiag_width
, cdiag_height
);
1703 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, myStipple
);
1705 if (m_window
&& m_window
->GetBackingPixmap())
1706 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, myStipple
);
1708 else if (m_currentStipple
.Ok()
1709 && ((m_currentStipple
!= oldStipple
) || !GetOptimization()))
1711 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) m_currentStipple
.GetPixmap());
1713 if (m_window
&& m_window
->GetBackingPixmap())
1714 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, (Pixmap
) m_currentStipple
.GetPixmap());
1717 if ((m_currentFill
!= oldFill
) || !GetOptimization())
1721 if (m_currentFill
== wxSTIPPLE
)
1722 fill_style
= FillStippled
;
1723 else if (IS_HATCH (m_currentFill
))
1724 fill_style
= FillStippled
;
1726 fill_style
= FillSolid
;
1727 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, fill_style
);
1728 if (m_window
&& m_window
->GetBackingPixmap())
1729 XSetFillStyle ((Display
*) m_display
,(GC
) m_gcBacking
, fill_style
);
1732 // must test m_logicalFunction, because it involves background!
1733 if (!sameColour
|| !GetOptimization()
1734 || ((m_logicalFunction
== wxXOR
) || (m_autoSetting
& 0x2)))
1737 if (m_pen
.GetStyle () == wxTRANSPARENT
)
1738 pixel
= m_backgroundPixel
;
1741 unsigned char red
= m_pen
.GetColour ().Red ();
1742 unsigned char blue
= m_pen
.GetColour ().Blue ();
1743 unsigned char green
= m_pen
.GetColour ().Green ();
1744 if (red
== (unsigned char) 255 && blue
== (unsigned char) 255
1745 && green
== (unsigned char) 255)
1747 pixel
= (int) WhitePixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1748 m_currentColour
= *wxWHITE
;
1749 m_pen
.GetColour().SetPixel(pixel
);
1750 m_currentColour
.SetPixel(pixel
);
1754 pixel
= (int) BlackPixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1755 m_currentColour
= *wxBLACK
;
1756 m_pen
.GetColour().SetPixel(pixel
);
1761 pixel
= m_pen
.GetColour ().AllocColour(m_display
);
1762 m_currentColour
.SetPixel(pixel
);
1765 // Finally, set the GC to the required colour
1768 if (m_logicalFunction
== wxXOR
)
1771 XGetGCValues ((Display
*) m_display
, (GC
) m_gc
, GCBackground
, &values
);
1772 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
^ values
.background
);
1773 if (m_window
&& m_window
->GetBackingPixmap())
1774 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
^ values
.background
);
1778 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1779 if (m_window
&& m_window
->GetBackingPixmap())
1780 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1785 m_pen
.GetColour().SetPixel(oldPenColour
.GetPixel());
1790 void wxWindowDC::SetBrush( const wxBrush
&brush
)
1792 wxCHECK_RET( Ok(), "invalid dc" );
1796 if (!m_brush
.Ok() || m_brush
.GetStyle () == wxTRANSPARENT
)
1799 int oldFill
= m_currentFill
;
1800 wxBitmap oldStipple
= m_currentStipple
;
1802 m_autoSetting
|= 0x1;
1804 m_currentFill
= m_brush
.GetStyle ();
1805 if (m_currentFill
== wxSTIPPLE
)
1806 m_currentStipple
= * m_brush
.GetStipple ();
1808 wxColour
oldBrushColour(m_currentColour
);
1809 m_currentColour
= m_brush
.GetColour ();
1811 bool sameColour
= (oldBrushColour
.Ok () &&
1812 (oldBrushColour
.Red () == m_currentColour
.Red ()) &&
1813 (oldBrushColour
.Blue () == m_currentColour
.Blue ()) &&
1814 (oldBrushColour
.Green () == m_currentColour
.Green ()) &&
1815 (oldBrushColour
.GetPixel() == m_currentColour
.GetPixel()));
1817 if ((oldFill
!= m_brush
.GetStyle ()) || !GetOptimization())
1819 switch (brush
.GetStyle ())
1823 case wxBDIAGONAL_HATCH
:
1824 case wxCROSSDIAG_HATCH
:
1825 case wxFDIAGONAL_HATCH
:
1827 case wxHORIZONTAL_HATCH
:
1828 case wxVERTICAL_HATCH
:
1831 // Chris Breeze 23/07/97: use background mode to determine whether
1832 // fill style should be solid or transparent
1833 int style
= (m_backgroundMode
== wxSOLID
? FillOpaqueStippled
: FillStippled
);
1834 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, style
);
1835 if (m_window
&& m_window
->GetBackingPixmap())
1836 XSetFillStyle ((Display
*) m_display
,(GC
) m_gcBacking
, style
);
1841 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, FillSolid
);
1842 if (m_window
&& m_window
->GetBackingPixmap())
1843 XSetFillStyle ((Display
*) m_display
,(GC
) m_gcBacking
, FillSolid
);
1847 if (IS_HATCH(m_currentFill
) && ((m_currentFill
!= oldFill
) || !GetOptimization()))
1851 switch (m_currentFill
)
1853 case wxBDIAGONAL_HATCH
:
1854 if (bdiag
== (Pixmap
) 0)
1855 bdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1856 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1857 bdiag_bits
, bdiag_width
, bdiag_height
);
1860 case wxFDIAGONAL_HATCH
:
1861 if (fdiag
== (Pixmap
) 0)
1862 fdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1863 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1864 fdiag_bits
, fdiag_width
, fdiag_height
);
1868 if (cross
== (Pixmap
) 0)
1869 cross
= XCreateBitmapFromData ((Display
*) m_display
,
1870 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1871 cross_bits
, cross_width
, cross_height
);
1874 case wxHORIZONTAL_HATCH
:
1875 if (horiz
== (Pixmap
) 0)
1876 horiz
= XCreateBitmapFromData ((Display
*) m_display
,
1877 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1878 horiz_bits
, horiz_width
, horiz_height
);
1881 case wxVERTICAL_HATCH
:
1882 if (verti
== (Pixmap
) 0)
1883 verti
= XCreateBitmapFromData ((Display
*) m_display
,
1884 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1885 verti_bits
, verti_width
, verti_height
);
1888 case wxCROSSDIAG_HATCH
:
1890 if (cdiag
== (Pixmap
) 0)
1891 cdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1892 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1893 cdiag_bits
, cdiag_width
, cdiag_height
);
1897 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, myStipple
);
1899 if (m_window
&& m_window
->GetBackingPixmap())
1900 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, myStipple
);
1902 // X can forget the stipple value when resizing a window (apparently)
1903 // so always set the stipple.
1904 else if (m_currentStipple
.Ok()) // && m_currentStipple != oldStipple)
1906 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) m_currentStipple
.GetPixmap());
1907 if (m_window
&& m_window
->GetBackingPixmap())
1908 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, (Pixmap
) m_currentStipple
.GetPixmap());
1911 // must test m_logicalFunction, because it involves background!
1912 if (!sameColour
|| !GetOptimization() || m_logicalFunction
== wxXOR
)
1917 // Policy - on a monochrome screen, all brushes are white,
1918 // except when they're REALLY black!!!
1919 unsigned char red
= m_brush
.GetColour ().Red ();
1920 unsigned char blue
= m_brush
.GetColour ().Blue ();
1921 unsigned char green
= m_brush
.GetColour ().Green ();
1923 if (red
== (unsigned char) 0 && blue
== (unsigned char) 0
1924 && green
== (unsigned char) 0)
1926 pixel
= (int) BlackPixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1927 m_currentColour
= *wxBLACK
;
1928 m_brush
.GetColour().SetPixel(pixel
);
1929 m_currentColour
.SetPixel(pixel
);
1933 pixel
= (int) WhitePixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1934 m_currentColour
= *wxWHITE
;
1935 m_brush
.GetColour().SetPixel(pixel
);
1936 m_currentColour
.SetPixel(pixel
);
1939 // N.B. comment out the above line and uncomment the following lines
1940 // if you want non-white colours to be black on a monochrome display.
1942 if (red == (unsigned char )255 && blue == (unsigned char)255
1943 && green == (unsigned char)255)
1944 pixel = (int)WhitePixel((Display*) m_display, DefaultScreen((Display*) m_display));
1946 pixel = (int)BlackPixel((Display*) m_display, DefaultScreen((Display*) m_display));
1949 else if (m_brush
.GetStyle () != wxTRANSPARENT
)
1951 pixel
= m_brush
.GetColour().AllocColour(m_display
);
1952 m_currentColour
.SetPixel(pixel
);
1956 // Finally, set the GC to the required colour
1957 if (m_logicalFunction
== wxXOR
)
1960 XGetGCValues ((Display
*) m_display
, (GC
) m_gc
, GCBackground
, &values
);
1961 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
^ values
.background
);
1962 if (m_window
&& m_window
->GetBackingPixmap())
1963 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
^ values
.background
);
1967 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1968 if (m_window
&& m_window
->GetBackingPixmap())
1969 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1974 m_brush
.GetColour().SetPixel(oldBrushColour
.GetPixel());
1977 void wxWindowDC::SetBackground( const wxBrush
&brush
)
1979 wxCHECK_RET( Ok(), "invalid dc" );
1981 m_backgroundBrush
= brush
;
1983 if (!m_backgroundBrush
.Ok())
1986 int pixel
= m_backgroundBrush
.GetColour().AllocColour(m_display
);
1988 // New behaviour, 10/2/99: setting the background brush of a DC
1989 // doesn't affect the window background colour.
1991 // XSetWindowBackground doesn't work for non-Window pixmaps
1992 if (!this->IsKindOf(CLASSINFO(wxMemoryDC)))
1993 XSetWindowBackground ((Display*) m_display, (Pixmap) m_pixmap, pixel);
1996 // Necessary for ::DrawIcon, which use fg/bg pixel or the GC.
1997 // And Blit,... (Any fct that use XCopyPlane, in fact.)
1998 XSetBackground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1999 if (m_window
&& m_window
->GetBackingPixmap())
2000 XSetBackground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
2003 void wxWindowDC::SetLogicalFunction( int function
)
2005 wxCHECK_RET( Ok(), "invalid dc" );
2010 if (m_logicalFunction
== function
)
2016 x_function
= GXclear
;
2022 x_function
= GXinvert
;
2025 x_function
= GXorReverse
;
2028 x_function
= GXandReverse
;
2037 x_function
= GXandInverted
;
2040 x_function
= GXnoop
;
2046 x_function
= GXequiv
;
2049 x_function
= GXcopyInverted
;
2052 x_function
= GXorInverted
;
2055 x_function
= GXnand
;
2062 x_function
= GXcopy
;
2066 XSetFunction((Display
*) m_display
, (GC
) m_gc
, x_function
);
2067 if (m_window
&& m_window
->GetBackingPixmap())
2068 XSetFunction((Display
*) m_display
, (GC
) m_gcBacking
, x_function
);
2070 if ((m_logicalFunction
== wxXOR
) != (function
== wxXOR
))
2071 /* MATTHEW: [9] Need to redo pen simply */
2072 m_autoSetting
|= 0x2;
2074 m_logicalFunction
= function
;
2078 void wxWindowDC::SetTextForeground( const wxColour
&col
)
2080 wxCHECK_RET( Ok(), "invalid dc" );
2082 if (m_textForegroundColour
== col
)
2085 m_textForegroundColour
= col
;
2089 void wxWindowDC::SetTextBackground( const wxColour
&col
)
2091 wxCHECK_RET( Ok(), "invalid dc" );
2093 if (m_textBackgroundColour
== col
)
2096 m_textBackgroundColour
= col
;
2097 if (!m_textBackgroundColour
.Ok())
2101 void wxWindowDC::SetBackgroundMode( int mode
)
2103 m_backgroundMode
= mode
;
2106 void wxWindowDC::SetPalette( const wxPalette
& palette
)
2111 /* Use GetXColormap */
2112 XSetWindowColormap ((Display
*) m_display
, (Window
) m_window
->GetXWindow(),
2113 (Colormap
) palette
.GetXColormap());
2115 /* Use wxGetMainColormap */
2116 XSetWindowColormap ((Display
*) m_display
, (Window
) m_window
->GetXWindow(),
2117 (Colormap
) wxTheApp
->GetMainColormap(m_display
));
2122 void wxWindowDC::SetDCClipping()
2124 // m_userRegion is the region set by calling SetClippingRegion
2126 if (m_currentRegion
)
2127 XDestroyRegion ((Region
) m_currentRegion
);
2129 // We need to take into account
2130 // clipping imposed on a window by a repaint.
2131 // We'll combine it with the user region. But for now,
2132 // just use the currently-defined user clipping region.
2133 if (m_userRegion
|| (m_window
&& m_window
->GetUpdateRegion().Ok()) )
2134 m_currentRegion
= (WXRegion
) XCreateRegion ();
2136 m_currentRegion
= (WXRegion
) NULL
;
2138 if ((m_window
&& m_window
->GetUpdateRegion().Ok()) && m_userRegion
)
2139 XIntersectRegion ((Region
) m_window
->GetUpdateRegion().GetXRegion(), (Region
) m_userRegion
, (Region
) m_currentRegion
);
2140 else if (m_userRegion
)
2141 XIntersectRegion ((Region
) m_userRegion
, (Region
) m_userRegion
, (Region
) m_currentRegion
);
2142 else if (m_window
&& m_window
->GetUpdateRegion().Ok())
2143 XIntersectRegion ((Region
) m_window
->GetUpdateRegion().GetXRegion(), (Region
) m_window
->GetUpdateRegion().GetXRegion(),
2144 (Region
) m_currentRegion
);
2146 if (m_currentRegion
)
2148 XSetRegion ((Display
*) m_display
, (GC
) m_gc
, (Region
) m_currentRegion
);
2152 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
2157 void wxWindowDC::DoSetClippingRegion( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
2159 wxDC::DoSetClippingRegion( x
, y
, width
, height
);
2162 XDestroyRegion ((Region
) m_userRegion
);
2163 m_userRegion
= (WXRegion
) XCreateRegion ();
2167 r
.width
= XLOG2DEVREL(width
);
2168 r
.height
= YLOG2DEVREL(height
);
2169 XUnionRectWithRegion (&r
, (Region
) m_userRegion
, (Region
) m_userRegion
);
2173 // Needs to work differently for Pixmap: without this,
2174 // there's a nasty (Display*) m_display bug. 8/12/94
2175 if (m_window
&& m_window
->GetBackingPixmap())
2177 XRectangle rects
[1];
2178 rects
[0].x
= XLOG2DEV_2(x
);
2179 rects
[0].y
= YLOG2DEV_2(y
);
2180 rects
[0].width
= XLOG2DEVREL(width
);
2181 rects
[0].height
= YLOG2DEVREL(height
);
2182 XSetClipRectangles((Display
*) m_display
, (GC
) m_gcBacking
, 0, 0, rects
, 1, Unsorted
);
2186 void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion
& region
)
2188 wxRect box
= region
.GetBox();
2190 wxDC::DoSetClippingRegion( box
.x
, box
.y
, box
.width
, box
.height
);
2193 XDestroyRegion ((Region
) m_userRegion
);
2194 m_userRegion
= (WXRegion
) XCreateRegion ();
2196 XUnionRegion((Region
) m_userRegion
, (Region
) region
.GetXRegion(), (Region
) m_userRegion
);
2200 // Needs to work differently for Pixmap: without this,
2201 // there's a nasty (Display*) m_display bug. 8/12/94
2202 if (m_window
&& m_window
->GetBackingPixmap())
2204 XRectangle rects
[1];
2205 rects
[0].x
= XLOG2DEV_2(box
.x
);
2206 rects
[0].y
= YLOG2DEV_2(box
.y
);
2207 rects
[0].width
= XLOG2DEVREL(box
.width
);
2208 rects
[0].height
= YLOG2DEVREL(box
.height
);
2209 XSetClipRectangles((Display
*) m_display
, (GC
) m_gcBacking
, 0, 0, rects
, 1, Unsorted
);
2214 void wxWindowDC::DestroyClippingRegion()
2216 wxDC::DestroyClippingRegion();
2219 XDestroyRegion ((Region
) m_userRegion
);
2220 m_userRegion
= NULL
;
2225 gc_val
.clip_mask
= None
;
2226 if (m_window
&& m_window
->GetBackingPixmap())
2227 XChangeGC((Display
*) m_display
, (GC
) m_gcBacking
, GCClipMask
, &gc_val
);
2230 // Resolution in pixels per logical inch
2231 wxSize
wxWindowDC::GetPPI() const
2233 return wxSize(100, 100);
2236 int wxWindowDC::GetDepth() const
2243 // ----------------------------------- spline code ----------------------------------------
2245 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
,
2246 double a3
, double b3
, double a4
, double b4
);
2247 void wx_clear_stack();
2248 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
, double *x3
,
2249 double *y3
, double *x4
, double *y4
);
2250 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
,
2251 double x4
, double y4
);
2252 static bool wx_spline_add_point(double x
, double y
);
2253 static void wx_spline_draw_point_array(wxDC
*dc
);
2255 wxList wx_spline_point_list
;
2257 #define half(z1, z2) ((z1+z2)/2.0)
2260 /* iterative version */
2262 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
, double a3
, double b3
, double a4
,
2265 register double xmid
, ymid
;
2266 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
2269 wx_spline_push(a1
, b1
, a2
, b2
, a3
, b3
, a4
, b4
);
2271 while (wx_spline_pop(&x1
, &y1
, &x2
, &y2
, &x3
, &y3
, &x4
, &y4
)) {
2272 xmid
= (double)half(x2
, x3
);
2273 ymid
= (double)half(y2
, y3
);
2274 if (fabs(x1
- xmid
) < THRESHOLD
&& fabs(y1
- ymid
) < THRESHOLD
&&
2275 fabs(xmid
- x4
) < THRESHOLD
&& fabs(ymid
- y4
) < THRESHOLD
) {
2276 wx_spline_add_point( x1
, y1
);
2277 wx_spline_add_point( xmid
, ymid
);
2279 wx_spline_push(xmid
, ymid
, (double)half(xmid
, x3
), (double)half(ymid
, y3
),
2280 (double)half(x3
, x4
), (double)half(y3
, y4
), x4
, y4
);
2281 wx_spline_push(x1
, y1
, (double)half(x1
, x2
), (double)half(y1
, y2
),
2282 (double)half(x2
, xmid
), (double)half(y2
, ymid
), xmid
, ymid
);
2287 /* utilities used by spline drawing routines */
2289 typedef struct wx_spline_stack_struct
{
2290 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
2293 #define SPLINE_STACK_DEPTH 20
2294 static Stack wx_spline_stack
[SPLINE_STACK_DEPTH
];
2295 static Stack
*wx_stack_top
;
2296 static int wx_stack_count
;
2298 void wx_clear_stack()
2300 wx_stack_top
= wx_spline_stack
;
2304 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
, double x4
, double y4
)
2306 wx_stack_top
->x1
= x1
;
2307 wx_stack_top
->y1
= y1
;
2308 wx_stack_top
->x2
= x2
;
2309 wx_stack_top
->y2
= y2
;
2310 wx_stack_top
->x3
= x3
;
2311 wx_stack_top
->y3
= y3
;
2312 wx_stack_top
->x4
= x4
;
2313 wx_stack_top
->y4
= y4
;
2318 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
,
2319 double *x3
, double *y3
, double *x4
, double *y4
)
2321 if (wx_stack_count
== 0)
2325 *x1
= wx_stack_top
->x1
;
2326 *y1
= wx_stack_top
->y1
;
2327 *x2
= wx_stack_top
->x2
;
2328 *y2
= wx_stack_top
->y2
;
2329 *x3
= wx_stack_top
->x3
;
2330 *y3
= wx_stack_top
->y3
;
2331 *x4
= wx_stack_top
->x4
;
2332 *y4
= wx_stack_top
->y4
;
2336 static bool wx_spline_add_point(double x
, double y
)
2338 wxPoint
*point
= new wxPoint
;
2341 wx_spline_point_list
.Append((wxObject
*)point
);
2345 static void wx_spline_draw_point_array(wxDC
*dc
)
2347 dc
->DrawLines(&wx_spline_point_list
, 0, 0 );
2348 wxNode
*node
= wx_spline_point_list
.First();
2351 wxPoint
*point
= (wxPoint
*)node
->Data();
2354 node
= wx_spline_point_list
.First();
2358 void wxWindowDC::DoDrawSpline( wxList
*points
)
2360 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2363 double cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
;
2364 double x1
, y1
, x2
, y2
;
2366 wxNode
*node
= points
->First();
2367 p
= (wxPoint
*)node
->Data();
2372 node
= node
->Next();
2373 p
= (wxPoint
*)node
->Data();
2377 cx1
= (double)((x1
+ x2
) / 2);
2378 cy1
= (double)((y1
+ y2
) / 2);
2379 cx2
= (double)((cx1
+ x2
) / 2);
2380 cy2
= (double)((cy1
+ y2
) / 2);
2382 wx_spline_add_point(x1
, y1
);
2384 while ((node
= node
->Next()) != NULL
)
2386 p
= (wxPoint
*)node
->Data();
2391 cx4
= (double)(x1
+ x2
) / 2;
2392 cy4
= (double)(y1
+ y2
) / 2;
2393 cx3
= (double)(x1
+ cx4
) / 2;
2394 cy3
= (double)(y1
+ cy4
) / 2;
2396 wx_quadratic_spline(cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
);
2400 cx2
= (double)(cx1
+ x2
) / 2;
2401 cy2
= (double)(cy1
+ y2
) / 2;
2404 wx_spline_add_point( cx1
, cy1
);
2405 wx_spline_add_point( x2
, y2
);
2407 wx_spline_draw_point_array( this );
2410 #endif // wxUSE_SPLINE
2414 // ----------------------------------------------------------------------------
2416 // ----------------------------------------------------------------------------
2418 wxPaintDC::wxPaintDC(wxWindow
* win
) : wxWindowDC(win
)
2420 wxRegion
* region
= NULL
;
2422 // Combine all the update rects into a region
2423 const wxRectList
& updateRects(win
->GetUpdateRects());
2424 if ( updateRects
.GetCount() != 0 )
2426 for ( wxRectList::Node
*node
= updateRects
.GetFirst();
2428 node
= node
->GetNext() )
2430 wxRect
* rect
= node
->GetData();
2433 region
= new wxRegion(*rect
);
2435 // TODO: is this correct? In SetDCClipping above,
2436 // XIntersectRegion is used to combine paint and user
2437 // regions. XIntersectRegion appears to work in that case...
2438 region
->Union(*rect
);
2444 win
->GetClientSize(&cw
, &ch
);
2445 region
= new wxRegion(wxRect(0, 0, cw
, ch
));
2448 win
->SetUpdateRegion(*region
);
2450 wxRegion
& theRegion(win
->GetUpdateRegion());
2451 theRegion
.SetRects(updateRects
); // We also store in terms of rects, for iteration to work.
2453 // Set the clipping region. Any user-defined region will be combined with this
2454 // one in SetDCClipping.
2455 XSetRegion ((Display
*) m_display
, (GC
) m_gc
, (Region
) region
->GetXRegion());
2460 wxPaintDC::~wxPaintDC()
2462 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
2464 m_window
->ClearUpdateRegion();
2467 // ----------------------------------------------------------------------------
2468 // private functions
2469 // ----------------------------------------------------------------------------
2472 Used when copying between drawables on different (Display*) m_displays. Not
2473 very fast, but better than giving up.
2476 static void XCopyRemote(Display
*src_display
, Display
*dest_display
,
2477 Drawable src
, Drawable dest
,
2480 unsigned int w
, unsigned int h
,
2481 int destx
, int desty
,
2482 bool more
, XImage
**cache
)
2484 XImage
*image
, *destimage
;
2485 Colormap destcm
, srccm
;
2486 static const int CACHE_SIZE
= 256;
2489 unsigned long cachesrc
[CACHE_SIZE
], cachedest
[CACHE_SIZE
];
2490 int k
, cache_pos
, all_cache
;
2492 if (!cache
|| !*cache
)
2493 image
= XGetImage(src_display
, src
, srcx
, srcy
, w
, h
, AllPlanes
, ZPixmap
);
2497 destimage
= XGetImage(dest_display
, dest
, destx
, desty
, w
, h
, AllPlanes
, ZPixmap
);
2499 srccm
= (Colormap
) wxTheApp
->GetMainColormap((WXDisplay
*) src_display
);
2500 destcm
= (Colormap
) wxTheApp
->GetMainColormap((WXDisplay
*) dest_display
);
2505 for (i
= 0; i
< w
; i
++)
2506 for (j
= 0; j
< h
; j
++) {
2507 unsigned long pixel
;
2510 pixel
= XGetPixel(image
, i
, j
);
2511 for (k
= cache_pos
; k
--; )
2512 if (cachesrc
[k
] == pixel
) {
2513 pixel
= cachedest
[k
];
2517 for (k
= CACHE_SIZE
; k
-- > cache_pos
; )
2518 if (cachesrc
[k
] == pixel
) {
2519 pixel
= cachedest
[k
];
2523 cachesrc
[cache_pos
] = xcol
.pixel
= pixel
;
2524 XQueryColor(src_display
, srccm
, &xcol
);
2525 if (!XAllocColor(dest_display
, destcm
, &xcol
))
2527 cachedest
[cache_pos
] = pixel
= xcol
.pixel
;
2529 if (++cache_pos
>= CACHE_SIZE
) {
2535 XPutPixel(destimage
, i
, j
, pixel
);
2538 XPutImage(dest_display
, dest
, destgc
, destimage
, 0, 0, destx
, desty
, w
, h
);
2539 XDestroyImage(destimage
);
2544 XDestroyImage(image
);
2549 /* Helper function for 16-bit fonts */
2550 static int str16len(const char *s
)
2554 while (s
[0] && s
[1]) {