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
16 parameters. Therefore, it is impossible to independently maintain
17 the current pen and the current brush. Also, some settings depend on
18 the current logical function. The m_currentFill, etc. instance
19 variables remember state across the brush and pen.
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 // ----------------------------------------------------------------------------
39 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
40 #pragma implementation "dcclient.h"
43 // For compilers that support precompilation, includes "wx.h".
44 #include "wx/wxprec.h"
46 #include "wx/dcclient.h"
47 #include "wx/dcmemory.h"
48 #include "wx/window.h"
55 #pragma message disable nosimpint
59 #pragma message enable nosimpint
62 #include "wx/motif/private.h"
65 #include <float.h> // for M_PI
75 static Pixmap bdiag
, cdiag
, fdiag
, cross
, horiz
, verti
;
77 // ----------------------------------------------------------------------------
79 // ----------------------------------------------------------------------------
81 // Fudge factor (VZ: what??)
84 // ----------------------------------------------------------------------------
86 // ----------------------------------------------------------------------------
88 IMPLEMENT_DYNAMIC_CLASS(wxClientDC
, wxWindowDC
)
89 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC
, wxWindowDC
)
90 IMPLEMENT_DYNAMIC_CLASS(wxWindowDC
, wxDC
)
93 // IS_HATCH exists for WXWIN_COMPATIBILITY_2_4 only
94 // but wxMotif needs it for its internals here
95 #define IS_HATCH(s) ((s)>=wxFIRST_HATCH && (s)<=wxLAST_HATCH)
98 // FIXME: left over after removal of wxDC::GetOptimization()
99 #define GET_OPTIMIZATION false
101 // ----------------------------------------------------------------------------
103 // ----------------------------------------------------------------------------
105 static void XCopyRemote(Display
*src_display
, Display
*dest_display
,
106 Drawable src
, Drawable dest
,
109 unsigned int w
, unsigned int h
,
110 int destx
, int desty
,
111 bool more
, XImage
**cache
);
113 // ============================================================================
115 // ============================================================================
118 * compare two doubles and return the larger rounded
121 static int roundmax(double a
, double b
)
123 return (int)((a
> b
? a
: b
) + 0.5);
127 * compare two doubles and return the smaller rounded
130 static int roundmin(double a
, double b
)
132 return (int)((a
< b
? a
: b
) - 0.5);
136 // ----------------------------------------------------------------------------
138 // ----------------------------------------------------------------------------
140 void wxWindowDC::Init()
143 m_gcBacking
= (WXGC
) 0;
145 m_backgroundPixel
= -1;
146 m_currentPenWidth
= 1;
147 m_currentPenJoin
= -1;
148 m_currentPenDashCount
= -1;
149 m_currentPenDash
= (wxX11Dash
*) NULL
;
152 m_colour
= wxColourDisplay();
153 m_display
= (WXDisplay
*) NULL
;
154 m_pixmap
= (WXPixmap
) 0;
156 m_oldFont
= (WXFont
) 0;
158 m_clipRegion
= (WXRegion
) 0;
161 wxWindowDC::wxWindowDC()
166 wxWindowDC::wxWindowDC( wxWindow
*window
)
168 wxASSERT_MSG( (window
!= (wxWindow
*) NULL
), "You must pass a valid wxWindow to wxWindowDC/wxClientDC/wxPaintDC constructor." );
173 m_font
= window
->GetFont();
176 m_display
= window
->GetXDisplay();
177 m_pixmap
= window
->GetXWindow();
178 Display
* display
= (Display
*) m_display
;
180 XSetWindowColormap (display
, (Pixmap
) m_pixmap
, (Colormap
) wxTheApp
->GetMainColormap(m_display
));
183 gcvalues
.foreground
= BlackPixel (display
, DefaultScreen (display
));
184 gcvalues
.background
= WhitePixel (display
, DefaultScreen (display
));
185 gcvalues
.graphics_exposures
= False
;
186 gcvalues
.subwindow_mode
= IncludeInferiors
;
187 gcvalues
.line_width
= 1;
188 m_gc
= (WXGC
) XCreateGC (display
, RootWindow (display
, DefaultScreen (display
)),
189 GCForeground
| GCBackground
| GCGraphicsExposures
| GCLineWidth
| GCSubwindowMode
,
192 if (m_window
->GetBackingPixmap())
194 m_gcBacking
= (WXGC
) XCreateGC (display
, RootWindow (display
,
195 DefaultScreen (display
)),
196 GCForeground
| GCBackground
| GCGraphicsExposures
| GCLineWidth
| GCSubwindowMode
,
200 m_backgroundPixel
= (int) gcvalues
.background
;
202 SetBackground(wxBrush(m_window
->GetBackgroundColour(), wxSOLID
));
205 wxWindowDC::~wxWindowDC()
208 XFreeGC ((Display
*) m_display
, (GC
) m_gc
);
212 XFreeGC ((Display
*) m_display
, (GC
) m_gcBacking
);
213 m_gcBacking
= (WXGC
) 0;
216 XDestroyRegion ((Region
) m_clipRegion
);
217 m_clipRegion
= (WXRegion
) 0;
220 extern bool wxDoFloodFill(wxDC
*dc
, wxCoord x
, wxCoord y
,
221 const wxColour
& col
, int style
);
223 bool wxWindowDC::DoFloodFill(wxCoord x
, wxCoord y
,
224 const wxColour
& col
, int style
)
226 return wxDoFloodFill(this, x
, y
, col
, style
);
229 bool wxWindowDC::DoGetPixel( wxCoord x1
, wxCoord y1
, wxColour
*col
) const
231 // Generic (and therefore rather inefficient) method.
232 // Could be improved.
234 wxBitmap
bitmap(1, 1);
235 memdc
.SelectObject(bitmap
);
236 memdc
.Blit(0, 0, 1, 1, (wxDC
*) this, x1
, y1
);
237 memdc
.SelectObject(wxNullBitmap
);
238 wxImage image
= bitmap
.ConvertToImage();
239 col
->Set(image
.GetRed(0, 0), image
.GetGreen(0, 0), image
.GetBlue(0, 0));
243 void wxWindowDC::DoDrawLine( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
)
245 wxCHECK_RET( Ok(), "invalid dc" );
247 int x1d
, y1d
, x2d
, y2d
;
257 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, x1d
, y1d
, x2d
, y2d
);
259 if (m_window
&& m_window
->GetBackingPixmap())
260 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
261 XLOG2DEV_2(x1
), YLOG2DEV_2(y1
),
262 XLOG2DEV_2(x2
), YLOG2DEV_2(y2
));
264 CalcBoundingBox(x1
, y1
);
265 CalcBoundingBox(x2
, y2
);
268 void wxWindowDC::DoCrossHair( wxCoord x
, wxCoord y
)
270 wxCHECK_RET( Ok(), "invalid dc" );
275 int xx
= XLOG2DEV (x
);
276 int yy
= YLOG2DEV (y
);
278 wxDisplaySize (&ww
, &hh
);
279 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, 0, yy
,
281 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xx
, 0,
284 if (m_window
&& m_window
->GetBackingPixmap())
288 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
291 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
297 void wxWindowDC::DoDrawArc( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
, wxCoord xc
, wxCoord yc
)
299 wxCHECK_RET( Ok(), "invalid dc" );
301 int xx1
= XLOG2DEV (x1
);
302 int yy1
= YLOG2DEV (y1
);
303 int xx2
= XLOG2DEV (x2
);
304 int yy2
= YLOG2DEV (y2
);
305 int xxc
= XLOG2DEV (xc
);
306 int yyc
= YLOG2DEV (yc
);
307 int xxc_2
= XLOG2DEV_2 (xc
);
308 int yyc_2
= YLOG2DEV_2 (yc
);
310 wxCoord dx
= xx1
- xxc
;
311 wxCoord dy
= yy1
- yyc
;
312 double radius
= sqrt ((double)(dx
* dx
+ dy
* dy
));
313 wxCoord r
= (wxCoord
) radius
;
315 double radius1
, radius2
;
317 if (xx1
== xx2
&& yy1
== yy2
)
322 else if (radius
== 0.0)
323 radius1
= radius2
= 0.0;
332 radius1
= -atan2 ((double) (yy1
- yyc
), (double) (xx1
- xxc
)) * 360.0 / (2 * M_PI
);
340 radius2
= -atan2 ((double) (yy2
- yyc
), (double) (xx2
- xxc
)) * 360.0 / (2 * M_PI
);
344 int alpha1
= (int) radius1
;
345 int alpha2
= (int) (radius2
- radius1
);
348 while (alpha2
> 360 * 64)
351 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
354 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) (GC
) m_gc
,
355 xxc
- r
, yyc
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
357 if (m_window
&& m_window
->GetBackingPixmap())
358 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
359 xxc_2
- r
, yyc_2
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
363 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
367 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
368 xxc
- r
, yyc
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
370 if (m_window
&& m_window
->GetBackingPixmap())
371 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
372 xxc_2
- r
, yyc_2
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
374 CalcBoundingBox (x1
, y1
);
375 CalcBoundingBox (x2
, y2
);
378 void wxWindowDC::DoDrawEllipticArc( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double sa
, double ea
)
380 wxCHECK_RET( Ok(), "invalid dc" );
386 wd
= XLOG2DEVREL(width
);
387 hd
= YLOG2DEVREL(height
);
389 if (sa
>=360 || sa
<=-360) sa
=sa
-int(sa
/360)*360;
390 if (ea
>=360 || ea
<=-360) ea
=ea
-int(ea
/360)*360;
391 int start
= int(sa
*64);
392 int end
= int(ea
*64);
393 if (start
<0) start
+=360*64;
394 if (end
<0) end
+=360*64;
395 if (end
>start
) end
-=start
;
396 else end
+=360*64-start
;
398 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
400 m_autoSetting
= true; // must be reset
403 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, start
, end
);
405 if (m_window
&& m_window
->GetBackingPixmap())
406 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
407 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),wd
,hd
,start
,end
);
410 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
414 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, start
,end
);
415 if (m_window
&& m_window
->GetBackingPixmap())
416 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
417 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),wd
,hd
,start
,end
);
419 CalcBoundingBox (x
, y
);
420 CalcBoundingBox (x
+ width
, y
+ height
);
423 void wxWindowDC::DoDrawPoint( wxCoord x
, wxCoord y
)
425 wxCHECK_RET( Ok(), "invalid dc" );
427 if (m_pen
.Ok() && m_autoSetting
)
430 XDrawPoint ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
));
431 if (m_window
&& m_window
->GetBackingPixmap())
432 XDrawPoint ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, XLOG2DEV_2 (x
), YLOG2DEV_2 (y
));
434 CalcBoundingBox (x
, y
);
437 void wxWindowDC::DoDrawLines( int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
)
439 wxCHECK_RET( Ok(), "invalid dc" );
441 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
446 XPoint
*xpoints
= new XPoint
[n
];
449 for (i
= 0; i
< n
; i
++)
451 xpoints
[i
].x
= XLOG2DEV (points
[i
].x
+ xoffset
);
452 xpoints
[i
].y
= YLOG2DEV (points
[i
].y
+ yoffset
);
454 XDrawLines ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xpoints
, n
, 0);
456 if (m_window
&& m_window
->GetBackingPixmap())
458 for (i
= 0; i
< n
; i
++)
460 xpoints
[i
].x
= XLOG2DEV_2 (points
[i
].x
+ xoffset
);
461 xpoints
[i
].y
= YLOG2DEV_2 (points
[i
].y
+ yoffset
);
463 XDrawLines ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, xpoints
, n
, 0);
469 void wxWindowDC::DoDrawPolygon( int n
, wxPoint points
[],
470 wxCoord xoffset
, wxCoord yoffset
, int fillStyle
)
472 wxCHECK_RET( Ok(), "invalid dc" );
474 XPoint
*xpoints1
= new XPoint
[n
+ 1];
475 XPoint
*xpoints2
= new XPoint
[n
+ 1];
477 for (i
= 0; i
< n
; i
++)
479 xpoints1
[i
].x
= XLOG2DEV (points
[i
].x
+ xoffset
);
480 xpoints1
[i
].y
= YLOG2DEV (points
[i
].y
+ yoffset
);
481 xpoints2
[i
].x
= XLOG2DEV_2 (points
[i
].x
+ xoffset
);
482 xpoints2
[i
].y
= YLOG2DEV_2 (points
[i
].y
+ yoffset
);
483 CalcBoundingBox (points
[i
].x
+ xoffset
, points
[i
].y
+ yoffset
);
486 // Close figure for XDrawLines (not needed for XFillPolygon)
487 xpoints1
[i
].x
= xpoints1
[0].x
;
488 xpoints1
[i
].y
= xpoints1
[0].y
;
489 xpoints2
[i
].x
= xpoints2
[0].x
;
490 xpoints2
[i
].y
= xpoints2
[0].y
;
492 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
495 XSetFillRule ((Display
*) m_display
, (GC
) m_gc
, fillStyle
== wxODDEVEN_RULE
? EvenOddRule
: WindingRule
);
496 XFillPolygon ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xpoints1
, n
, Complex
, 0);
497 XSetFillRule ((Display
*) m_display
, (GC
) m_gc
, EvenOddRule
); // default mode
498 if (m_window
&& m_window
->GetBackingPixmap())
500 XSetFillRule ((Display
*) m_display
,(GC
) m_gcBacking
,
501 fillStyle
== wxODDEVEN_RULE
? EvenOddRule
: WindingRule
);
502 XFillPolygon ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, xpoints2
, n
, Complex
, 0);
503 XSetFillRule ((Display
*) m_display
,(GC
) m_gcBacking
, EvenOddRule
); // default mode
507 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
511 XDrawLines ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xpoints1
, n
+ 1, 0);
513 if (m_window
&& m_window
->GetBackingPixmap())
514 XDrawLines ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, xpoints2
, n
+ 1, 0);
521 void wxWindowDC::DoDrawRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
523 wxCHECK_RET( Ok(), "invalid dc" );
525 int xd
, yd
, wfd
, hfd
, wd
, hd
;
529 wfd
= XLOG2DEVREL(width
);
531 hfd
= YLOG2DEVREL(height
);
534 if (wfd
== 0 || hfd
== 0) return;
535 if (wd
< 0) { wd
= - wd
; xd
= xd
- wd
; }
536 if (hd
< 0) { hd
= - hd
; yd
= yd
- hd
; }
538 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
541 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wfd
, hfd
);
543 if (m_window
&& m_window
->GetBackingPixmap())
544 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
545 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
549 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
553 XDrawRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
);
555 if (m_window
&& m_window
->GetBackingPixmap())
556 XDrawRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
557 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
560 CalcBoundingBox (x
, y
);
561 CalcBoundingBox (x
+ width
, y
+ height
);
564 void wxWindowDC::DoDrawRoundedRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double radius
)
566 wxCHECK_RET( Ok(), "invalid dc" );
568 // If radius is negative, it's a proportion of the smaller dimension.
570 if (radius
< 0.0) radius
= - radius
* ((width
< height
) ? width
: height
);
572 int xd
= XLOG2DEV (x
);
573 int yd
= YLOG2DEV (y
);
574 int rd
= XLOG2DEVREL ((long) radius
);
575 int wd
= XLOG2DEVREL (width
) - WX_GC_CF
;
576 int hd
= YLOG2DEVREL (height
) - WX_GC_CF
;
581 // If radius is zero use DrawRectangle() instead to avoid
582 // X drawing errors with small radii
585 DrawRectangle( x
, y
, width
, height
);
589 // Draw nothing if transformed w or h is 0
590 if (wd
== 0 || hd
== 0) return;
592 // CMB: adjust size if outline is drawn otherwise the result is
593 // 1 pixel too wide and high
594 if (m_pen
.GetStyle() != wxTRANSPARENT
)
600 // CMB: ensure dd is not larger than rectangle otherwise we
601 // get an hour glass shape
602 if (rw_d
> wd
) rw_d
= wd
;
603 if (rw_d
> hd
) rw_d
= hd
;
606 // For backing pixmap
607 int xd2
= XLOG2DEV_2 (x
);
608 int yd2
= YLOG2DEV_2 (y
);
609 int rd2
= XLOG2DEVREL ((long) radius
);
610 int wd2
= XLOG2DEVREL (width
) ;
611 int hd2
= YLOG2DEVREL (height
) ;
616 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
620 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ rd
, yd
,
622 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ rd
,
625 // Arcs start from 3 o'clock, positive angles anticlockwise
627 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
,
628 rw_d
, rh_d
, 90 * 64, 90 * 64);
630 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
, yd
,
631 // rw_d, rh_d, 0, 90 * 64);
632 rw_d
, rh_d
, 0, 91 * 64);
634 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
,
636 // rw_d, rh_d, 270 * 64, 90 * 64);
637 rw_d
, rh_d
, 269 * 64, 92 * 64);
639 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ hd
- rh_d
,
640 rw_d
, rh_d
, 180 * 64, 90 * 64);
642 if (m_window
&& m_window
->GetBackingPixmap())
644 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
645 xd2
+ rd2
, yd2
, wd2
- rw_d2
, hd2
);
646 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
647 xd2
, yd2
+ rd2
, wd2
, hd2
- rh_d2
);
649 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
650 xd2
, yd2
, rw_d2
, rh_d2
, 90 * 64, 90 * 64);
651 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
652 xd2
+ wd2
- rw_d2
, yd2
,
653 // rw_d2, rh_d2, 0, 90 * 64);
654 rw_d2
, rh_d2
, 0, 91 * 64);
655 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
658 // rw_d2, rh_d2, 270 * 64, 90 * 64);
659 rw_d2
, rh_d2
, 269 * 64, 92 * 64);
660 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
661 xd2
, yd2
+ hd2
- rh_d2
,
662 rw_d2
, rh_d2
, 180 * 64, 90 * 64);
666 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
669 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ rd
, yd
,
670 xd
+ wd
- rd
+ 1, yd
);
671 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ rd
, yd
+ hd
,
672 xd
+ wd
- rd
, yd
+ hd
);
674 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ rd
,
676 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
, yd
+ rd
,
677 xd
+ wd
, yd
+ hd
- rd
+ 1);
678 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
,
679 rw_d
, rh_d
, 90 * 64, 90 * 64);
680 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
, yd
,
681 // rw_d, rh_d, 0, 90 * 64);
682 rw_d
, rh_d
, 0, 91 * 64);
683 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
,
685 rw_d
, rh_d
, 269 * 64, 92 * 64);
686 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ hd
- rh_d
,
687 rw_d
, rh_d
, 180 * 64, 90 * 64);
689 if (m_window
&& m_window
->GetBackingPixmap())
691 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
693 xd2
+ wd2
- rd2
+ 1, yd2
);
694 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
695 xd2
+ rd2
, yd2
+ hd2
,
696 xd2
+ wd2
- rd2
, yd2
+ hd2
);
698 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
700 xd2
, yd2
+ hd2
- rd2
);
701 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
702 xd2
+ wd2
, yd2
+ rd2
,
703 xd2
+ wd2
, yd2
+ hd2
- rd2
+ 1);
704 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
706 rw_d2
, rh_d2
, 90 * 64, 90 * 64);
707 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
708 xd2
+ wd2
- rw_d2
, yd2
,
709 // rw_d2, rh_d2, 0, 90 * 64);
710 rw_d2
, rh_d2
, 0, 91 * 64);
711 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
714 rw_d2
, rh_d2
, 269 * 64, 92 * 64);
715 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
716 xd2
, yd2
+ hd2
- rh_d2
,
717 rw_d2
, rh_d2
, 180 * 64, 90 * 64);
720 CalcBoundingBox (x
, y
);
721 CalcBoundingBox (x
+ width
, y
+ height
);
724 void wxWindowDC::DoDrawEllipse( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
726 wxCHECK_RET( Ok(), "invalid dc" );
728 // Check for negative width and height
741 static const int angle
= 23040;
747 wd
= XLOG2DEVREL(width
) ;
748 hd
= YLOG2DEVREL(height
) ;
750 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
753 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, 0, angle
);
754 if (m_window
&& m_window
->GetBackingPixmap())
755 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
756 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
757 XLOG2DEVREL (width
) - WX_GC_CF
,
758 YLOG2DEVREL (height
) - WX_GC_CF
, 0, angle
);
761 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
765 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, 0, angle
);
766 if (m_window
&& m_window
->GetBackingPixmap())
767 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
768 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
769 XLOG2DEVREL (width
) - WX_GC_CF
,
770 YLOG2DEVREL (height
) - WX_GC_CF
, 0, angle
);
772 CalcBoundingBox (x
, y
);
773 CalcBoundingBox (x
+ width
, y
+ height
);
777 bool wxWindowDC::CanDrawBitmap() const
779 wxCHECK_MSG( Ok(), false, "invalid dc" );
784 // TODO: use scaled Blit e.g. as per John Price's implementation
785 // in Contrib/Utilities
786 bool wxWindowDC::DoBlit( wxCoord xdest
, wxCoord ydest
,
787 wxCoord width
, wxCoord height
,
788 wxDC
*source
, wxCoord xsrc
, wxCoord ysrc
,
789 int rop
, bool useMask
,
790 wxCoord xsrcMask
, wxCoord ysrcMask
)
792 wxCHECK_MSG( Ok(), false, "invalid dc" );
794 wxWindowDC
* sourceDC
= wxDynamicCast(source
, wxWindowDC
);
796 wxASSERT_MSG( sourceDC
, "Blit source DC must be wxWindowDC or derived class." );
798 // Be sure that foreground pixels (1) of the Icon will be painted with
799 // foreground colour. [m_textForegroundColour] Background pixels (0)
800 // will be painted with backgound colour (m_textBackgroundColour)
801 // Using ::SetPen is horribly slow, so avoid doing it
802 int oldBackgroundPixel
= -1;
803 int oldForegroundPixel
= -1;
805 if (m_textBackgroundColour
.Ok())
807 oldBackgroundPixel
= m_backgroundPixel
;
808 int pixel
= m_textBackgroundColour
.AllocColour(m_display
);
810 XSetBackground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
811 if (m_window
&& m_window
->GetBackingPixmap())
812 XSetBackground ((Display
*) m_display
,(GC
) m_gcBacking
,
815 if (m_textForegroundColour
.Ok())
817 oldForegroundPixel
= m_currentColour
.GetPixel();
819 if( m_textForegroundColour
.GetPixel() <= -1 )
820 CalculatePixel( m_textForegroundColour
,
821 m_textForegroundColour
, true);
823 int pixel
= m_textForegroundColour
.GetPixel();
825 SetForegroundPixelWithLogicalFunction(pixel
);
828 // Do bitmap scaling if necessary
830 wxBitmap
*scaledBitmap
= (wxBitmap
*) NULL
;
831 Pixmap sourcePixmap
= (Pixmap
) NULL
;
832 double scaleX
, scaleY
;
833 GetUserScale(& scaleX
, & scaleY
);
836 /* TODO: use the mask origin when drawing transparently */
837 if (xsrcMask
== -1 && ysrcMask
== -1)
839 xsrcMask
= xsrc
; ysrcMask
= ysrc
;
842 // Sorry, can't scale masks just yet
843 if (!useMask
&& (scaleX
!= 1.0 || scaleY
!= 1.0) && sourceDC
->IsKindOf(CLASSINFO(wxMemoryDC
)))
845 wxMemoryDC
* memDC
= (wxMemoryDC
*) sourceDC
;
846 wxBitmap
& bitmap
= memDC
->GetBitmap();
848 wxASSERT_MSG( (bitmap
.Ok()), "Bad source bitmap in wxWindowDC::Blit");
850 wxImage image
= bitmap
.ConvertToImage();
853 sourcePixmap
= (Pixmap
) bitmap
.GetDrawable();
857 int scaledW
= (int) (bitmap
.GetWidth() * scaleX
);
858 int scaledH
= (int) (bitmap
.GetHeight() * scaleY
);
860 image
= image
.Scale(scaledW
, scaledH
);
861 scaledBitmap
= new wxBitmap(image
);
862 sourcePixmap
= (Pixmap
) scaledBitmap
->GetDrawable();
866 sourcePixmap
= (Pixmap
) sourceDC
->m_pixmap
;
868 if (m_pixmap
&& sourcePixmap
)
871 int orig
= m_logicalFunction
;
873 SetLogicalFunction (rop
);
875 if (m_display
!= sourceDC
->m_display
)
877 XImage
*cache
= NULL
;
879 if (m_window
&& m_window
->GetBackingPixmap())
880 XCopyRemote((Display
*) sourceDC
->m_display
, (Display
*) m_display
,
881 (Pixmap
) sourcePixmap
, (Pixmap
) m_window
->GetBackingPixmap(),
883 source
->LogicalToDeviceX (xsrc
),
884 source
->LogicalToDeviceY (ysrc
),
885 source
->LogicalToDeviceXRel(width
),
886 source
->LogicalToDeviceYRel(height
),
887 XLOG2DEV_2 (xdest
), YLOG2DEV_2 (ydest
),
890 if ( useMask
&& source
->IsKindOf(CLASSINFO(wxMemoryDC
)) )
892 wxMemoryDC
*memDC
= (wxMemoryDC
*)source
;
893 wxBitmap
& sel
= memDC
->GetBitmap();
894 if ( sel
.Ok() && sel
.GetMask() && sel
.GetMask()->GetBitmap() )
896 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) sel
.GetMask()->GetBitmap());
897 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, XLOG2DEV (xdest
), YLOG2DEV (ydest
));
901 XCopyRemote((Display
*) sourceDC
->m_display
, (Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
902 source
->LogicalToDeviceX (xsrc
),
903 source
->LogicalToDeviceY (ysrc
),
904 source
->LogicalToDeviceXRel(width
),
905 source
->LogicalToDeviceYRel(height
),
906 XLOG2DEV (xdest
), YLOG2DEV (ydest
),
912 XSetRegion ((Display
*) m_display
, (GC
) m_gc
,
913 (Region
) m_clipRegion
);
915 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
917 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, 0, 0);
921 { //XGCValues values;
922 //XGetGCValues((Display*)m_display, (GC)m_gc, GCForeground, &values);
924 if (m_window
&& m_window
->GetBackingPixmap())
926 // +++ MARKUS (mho@comnets.rwth-aachen): error on blitting bitmaps with depth 1
927 if (source
->IsKindOf(CLASSINFO(wxMemoryDC
)) && ((wxMemoryDC
*) source
)->GetBitmap().GetDepth() == 1)
929 XCopyPlane ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
930 source
->LogicalToDeviceX (xsrc
),
931 source
->LogicalToDeviceY (ysrc
),
932 source
->LogicalToDeviceXRel(width
),
933 source
->LogicalToDeviceYRel(height
),
934 XLOG2DEV_2 (xdest
), YLOG2DEV_2 (ydest
), 1);
938 XCopyArea ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
939 source
->LogicalToDeviceX (xsrc
),
940 source
->LogicalToDeviceY (ysrc
),
941 source
->LogicalToDeviceXRel(width
),
942 source
->LogicalToDeviceYRel(height
),
943 XLOG2DEV_2 (xdest
), YLOG2DEV_2 (ydest
));
946 if ( useMask
&& source
->IsKindOf(CLASSINFO(wxMemoryDC
)) )
948 wxMemoryDC
*memDC
= (wxMemoryDC
*)source
;
949 wxBitmap
& sel
= memDC
->GetBitmap();
950 if ( sel
.Ok() && sel
.GetMask() && sel
.GetMask()->GetBitmap() )
952 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) sel
.GetMask()->GetBitmap());
953 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, XLOG2DEV (xdest
), YLOG2DEV (ydest
));
957 // Check if we're copying from a mono bitmap
958 if (source
->IsKindOf(CLASSINFO(wxMemoryDC
)) &&
959 ((wxMemoryDC
*)source
)->GetBitmap().Ok() && (((wxMemoryDC
*)source
)->GetBitmap().GetDepth () == 1))
961 XCopyPlane ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
962 source
->LogicalToDeviceX (xsrc
),
963 source
->LogicalToDeviceY (ysrc
),
964 source
->LogicalToDeviceXRel(width
),
965 source
->LogicalToDeviceYRel(height
),
966 XLOG2DEV (xdest
), YLOG2DEV (ydest
), 1);
970 XCopyArea ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
971 source
->LogicalToDeviceX (xsrc
),
972 source
->LogicalToDeviceY (ysrc
),
973 source
->LogicalToDeviceXRel(width
),
974 source
->LogicalToDeviceYRel(height
),
975 XLOG2DEV (xdest
), YLOG2DEV (ydest
));
981 XSetRegion ((Display
*) m_display
, (GC
) m_gc
,
982 (Region
) m_clipRegion
);
984 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
986 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, 0, 0);
989 } /* Remote/local (Display*) m_display */
990 CalcBoundingBox (xdest
, ydest
);
991 CalcBoundingBox (xdest
+ width
, ydest
+ height
);
993 SetLogicalFunction(orig
);
997 if (scaledBitmap
) delete scaledBitmap
;
999 if (oldBackgroundPixel
> -1)
1001 XSetBackground ((Display
*) m_display
, (GC
) m_gc
, oldBackgroundPixel
);
1002 if (m_window
&& m_window
->GetBackingPixmap())
1003 XSetBackground ((Display
*) m_display
,(GC
) m_gcBacking
,
1004 oldBackgroundPixel
);
1006 if (oldForegroundPixel
> -1)
1008 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, oldForegroundPixel
);
1009 if (m_window
&& m_window
->GetBackingPixmap())
1010 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
,
1011 oldForegroundPixel
);
1017 void wxWindowDC::DoDrawText( const wxString
&text
, wxCoord x
, wxCoord y
)
1019 wxCHECK_RET( Ok(), "invalid dc" );
1021 // Since X draws from the baseline of the text, must add the text height
1025 int slen
= text
.length();
1027 // Set FillStyle, otherwise X will use current stipple!
1028 XGCValues gcV
, gcBackingV
;
1030 XGetGCValues ((Display
*) m_display
, (GC
)m_gc
, GCFillStyle
, &gcV
);
1031 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, FillSolid
);
1032 if (m_window
&& m_window
->GetBackingPixmap())
1034 XGetGCValues ((Display
*) m_display
, (GC
)m_gcBacking
, GCFillStyle
,
1036 XSetFillStyle ((Display
*) m_display
, (GC
) m_gcBacking
, FillSolid
);
1040 wxGetTextExtent (m_display
, m_font
, m_userScaleY
* m_logicalScaleY
,
1041 text
, &cx
, &cy
, &ascent
, NULL
);
1043 // First draw a rectangle representing the text background, if a text
1044 // background is specified
1045 if (m_textBackgroundColour
.Ok () && (m_backgroundMode
!= wxTRANSPARENT
))
1047 wxColour oldPenColour
= m_currentColour
;
1048 m_currentColour
= m_textBackgroundColour
;
1049 bool sameColour
= (oldPenColour
.Ok () && m_textBackgroundColour
.Ok () &&
1050 (oldPenColour
.Red () == m_textBackgroundColour
.Red ()) &&
1051 (oldPenColour
.Blue () == m_textBackgroundColour
.Blue ()) &&
1052 (oldPenColour
.Green () == m_textBackgroundColour
.Green ()));
1054 // This separation of the big && test required for gcc2.7/HP UX 9.02
1055 // or pixel value can be corrupted!
1056 sameColour
= (sameColour
&&
1057 (oldPenColour
.GetPixel() == m_textBackgroundColour
.GetPixel()));
1059 if (!sameColour
|| !GET_OPTIMIZATION
)
1061 int pixel
= m_textBackgroundColour
.AllocColour(m_display
);
1062 m_currentColour
= m_textBackgroundColour
;
1064 // Set the GC to the required colour
1067 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1068 if (m_window
&& m_window
->GetBackingPixmap())
1069 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1073 m_textBackgroundColour
= oldPenColour
;
1075 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
), cx
, cy
);
1076 if (m_window
&& m_window
->GetBackingPixmap())
1077 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
1078 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
), cx
, cy
);
1081 // Now set the text foreground and draw the text
1082 if (m_textForegroundColour
.Ok ())
1084 wxColour oldPenColour
= m_currentColour
;
1085 m_currentColour
= m_textForegroundColour
;
1086 bool sameColour
= (oldPenColour
.Ok () && m_currentColour
.Ok () &&
1087 (oldPenColour
.Red () == m_currentColour
.Red ()) &&
1088 (oldPenColour
.Blue () == m_currentColour
.Blue ()) &&
1089 (oldPenColour
.Green () == m_currentColour
.Green ()) &&
1090 (oldPenColour
.GetPixel() == m_currentColour
.GetPixel()));
1092 if (!sameColour
|| !GET_OPTIMIZATION
)
1094 int pixel
= CalculatePixel(m_textForegroundColour
,
1095 m_currentColour
, false);
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_textForegroundColour
= oldPenColour
;
1109 // We need to add the ascent, not the whole height, since X draws at the
1110 // point above the descender.
1113 XDrawString16((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
) + ascent
,
1114 (XChar2b
*)(char*) (const char*) text
, slen
);
1117 #if wxMOTIF_NEW_FONT_HANDLING
1118 XFontSet fset
= (XFontSet
) m_font
.GetFontSet (m_userScaleY
* m_logicalScaleY
, m_display
);
1119 XmbDrawString((Display
*) m_display
, (Pixmap
) m_pixmap
, fset
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
) + ascent
, text
, slen
);
1121 XDrawString((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
) + ascent
, text
, slen
);
1124 if (m_window
&& m_window
->GetBackingPixmap()) {
1127 XDrawString16((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
1128 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
) + ascent
,
1129 (XChar2b
*)(char*) (const char*) text
, slen
);
1132 #if wxMOTIF_NEW_FONT_HANDLING
1133 XmbDrawString((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), fset
, (GC
) m_gcBacking
,
1134 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
) + ascent
,
1135 wxConstCast(text
.c_str(), char), slen
);
1137 XDrawString((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
1138 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
) + ascent
,
1139 wxConstCast(text
.c_str(), char), slen
);
1143 // restore fill style
1144 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, gcV
.fill_style
);
1145 if (m_window
&& m_window
->GetBackingPixmap())
1146 XSetFillStyle ((Display
*) m_display
, (GC
) m_gcBacking
,
1147 gcBackingV
.fill_style
);
1150 GetTextExtent (text
, &w
, &h
);
1151 CalcBoundingBox (x
+ w
, y
+ h
);
1152 CalcBoundingBox (x
, y
);
1155 void wxWindowDC::DoDrawRotatedText( const wxString
&text
, wxCoord x
, wxCoord y
,
1160 DrawText(text
, x
, y
);
1164 wxCHECK_RET( Ok(), "invalid dc" );
1166 int oldBackgroundPixel
= -1;
1167 int oldForegroundPixel
= -1;
1168 int foregroundPixel
= -1;
1169 int backgroundPixel
= -1;
1171 if (m_textBackgroundColour
.Ok())
1173 oldBackgroundPixel
= m_backgroundPixel
;
1174 backgroundPixel
= m_textBackgroundColour
.AllocColour(m_display
);
1176 if (m_textForegroundColour
.Ok())
1178 oldForegroundPixel
= m_currentColour
.GetPixel();
1180 if( m_textForegroundColour
.GetPixel() <= -1 )
1181 CalculatePixel( m_textForegroundColour
,
1182 m_textForegroundColour
, true);
1184 foregroundPixel
= m_textForegroundColour
.GetPixel();
1187 // Since X draws from the baseline of the text, must add the text height
1193 wxGetTextExtent (m_display
, m_font
, m_userScaleY
* m_logicalScaleY
,
1194 text
, &cx
, &cy
, &ascent
, NULL
);
1196 wxBitmap
src(cx
, cy
);
1198 dc
.SelectObject(src
);
1199 dc
.SetFont(GetFont());
1200 dc
.SetBackground(*wxWHITE_BRUSH
);
1201 dc
.SetBrush(*wxBLACK_BRUSH
);
1203 dc
.DrawText(text
, 0, 0);
1204 dc
.SetFont(wxNullFont
);
1206 // Calculate the size of the rotated bounding box.
1207 double dx
= cos(angle
/ 180.0 * M_PI
);
1208 double dy
= sin(angle
/ 180.0 * M_PI
);
1209 double x4
= cy
* dy
;
1210 double y4
= cy
* dx
;
1211 double x3
= cx
* dx
;
1212 double y3
= -cx
* dy
;
1213 double x2
= x3
+ x4
;
1214 double y2
= y3
+ y4
;
1218 // Create image from the source bitmap after writing the text into it.
1219 wxImage image
= src
.ConvertToImage();
1221 int minx
= roundmin(0, roundmin(x4
, roundmin(x2
, x3
)));
1222 int miny
= roundmin(0, roundmin(y4
, roundmin(y2
, y3
)));
1223 int maxx
= roundmax(0, roundmax(x4
, roundmax(x2
, x3
)));
1224 int maxy
= roundmax(0, roundmax(y4
, roundmax(y2
, y3
)));
1226 bool lastFore
= false, lastBack
= false;
1228 // This rotates counterclockwise around the top left corner.
1229 for (int rx
= minx
; rx
< maxx
; rx
++)
1231 for (int ry
= miny
; ry
< maxy
; ry
++)
1233 // transform dest coords to source coords
1234 int sx
= (int) (rx
* dx
- ry
* dy
+ 0.5);
1235 int sy
= - (int) (-ry
* dx
- rx
* dy
+ 0.5);
1236 if (sx
>= 0 && sx
< cx
&& sy
>= 0 && sy
< cy
)
1238 bool textPixel
= image
.GetRed(sx
, sy
) == 0;
1240 if (!textPixel
&& m_backgroundMode
!= wxSOLID
)
1243 wxCoord ox
= (wxCoord
) (x1
+ rx
),
1244 oy
= (wxCoord
) (y1
+ ry
);
1245 // draw black pixels, ignore white ones (i.e. transparent b/g)
1246 if (textPixel
&& !lastFore
)
1248 XSetForeground ((Display
*) m_display
, (GC
) m_gc
,
1253 else if (!textPixel
&& !lastBack
)
1255 XSetForeground ((Display
*) m_display
, (GC
) m_gc
,
1261 XDrawPoint ((Display
*) m_display
, (Pixmap
) m_pixmap
,
1262 (GC
) m_gc
, XLOG2DEV (ox
), YLOG2DEV (oy
));
1263 if (m_window
&& m_window
->GetBackingPixmap())
1264 XDrawPoint ((Display
*) m_display
,
1265 (Pixmap
) m_window
->GetBackingPixmap(),
1267 XLOG2DEV_2 (ox
), YLOG2DEV_2 (oy
));
1272 if (oldBackgroundPixel
> -1)
1274 XSetBackground ((Display
*) m_display
, (GC
) m_gc
, oldBackgroundPixel
);
1275 if (m_window
&& m_window
->GetBackingPixmap())
1276 XSetBackground ((Display
*) m_display
,(GC
) m_gcBacking
,
1277 oldBackgroundPixel
);
1279 if (oldForegroundPixel
> -1)
1281 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, oldForegroundPixel
);
1282 if (m_window
&& m_window
->GetBackingPixmap())
1283 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
,
1284 oldForegroundPixel
);
1287 CalcBoundingBox (minx
, miny
);
1288 CalcBoundingBox (maxx
, maxy
);
1291 bool wxWindowDC::CanGetTextExtent() const
1296 void wxWindowDC::DoGetTextExtent( const wxString
&string
, wxCoord
*width
, wxCoord
*height
,
1297 wxCoord
*descent
, wxCoord
*externalLeading
,
1298 wxFont
*font
) const
1300 wxCHECK_RET( Ok(), "invalid dc" );
1302 const wxFont
* theFont
= font
? font
: &m_font
;
1306 // TODO: this should be an error log function
1307 wxFAIL_MSG("set a valid font before calling GetTextExtent!");
1309 if (width
) *width
= -1;
1310 if (height
) *height
= -1;
1314 wxGetTextExtent(m_display
, *theFont
, m_userScaleY
* m_logicalScaleY
,
1315 string
, width
, height
, NULL
, descent
);
1317 if (width
) *width
= XDEV2LOGREL (*width
);
1318 if (height
) *height
= YDEV2LOGREL (*height
);
1319 if (externalLeading
)
1320 *externalLeading
= 0;
1323 wxCoord
wxWindowDC::GetCharWidth() const
1325 wxCHECK_MSG( Ok(), 0, "invalid dc" );
1326 wxCHECK_MSG( m_font
.Ok(), 0, "invalid font" );
1330 wxGetTextExtent (m_display
, m_font
, m_userScaleY
* m_logicalScaleY
,
1331 "x", &width
, NULL
, NULL
, NULL
);
1333 return XDEV2LOGREL(width
);
1336 wxCoord
wxWindowDC::GetCharHeight() const
1338 wxCHECK_MSG( Ok(), 0, "invalid dc" );
1339 wxCHECK_MSG( m_font
.Ok(), 0, "invalid font" );
1343 wxGetTextExtent (m_display
, m_font
, m_userScaleY
* m_logicalScaleY
,
1344 "x", NULL
, &height
, NULL
, NULL
);
1346 return XDEV2LOGREL(height
);
1349 void wxWindowDC::DoGetSize( int *width
, int *height
) const
1355 if( m_window
->GetBackingPixmap() )
1357 w
= m_window
->GetPixmapWidth();
1358 h
= m_window
->GetPixmapHeight();
1361 m_window
->GetSize( &w
, &h
);
1364 if( width
) *width
= w
;
1365 if( height
) *height
= h
;
1368 void wxWindowDC::Clear()
1370 wxCHECK_RET( Ok(), "invalid dc" );
1372 wxRect
rect( GetSize() );
1376 void wxWindowDC::Clear(const wxRect
& rect
)
1378 wxCHECK_RET( Ok(), "invalid dc" );
1380 int x
= rect
.x
; int y
= rect
.y
;
1381 int w
= rect
.width
; int h
= rect
.height
;
1383 wxBrush saveBrush
= m_brush
;
1384 SetBrush (m_backgroundBrush
);
1386 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
1389 if (m_window
&& m_window
->GetBackingPixmap())
1390 XFillRectangle ((Display
*) m_display
,
1391 (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
1394 m_brush
= saveBrush
;
1397 void wxWindowDC::SetFont( const wxFont
&font
)
1399 wxCHECK_RET( Ok(), "invalid dc" );
1408 #if !wxMOTIF_NEW_FONT_HANDLING
1409 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1411 Font fontId
= ((XFontStruct
*)pFontStruct
)->fid
;
1412 XSetFont ((Display
*) m_display
, (GC
) m_gc
, fontId
);
1414 if (m_window
&& m_window
->GetBackingPixmap())
1415 XSetFont ((Display
*) m_display
,(GC
) m_gcBacking
, fontId
);
1419 void wxWindowDC::SetForegroundPixelWithLogicalFunction(int pixel
)
1421 if (m_logicalFunction
== wxXOR
)
1424 XGetGCValues ((Display
*) m_display
, (GC
) m_gc
, GCBackground
, &values
);
1425 XSetForeground ((Display
*) m_display
, (GC
) m_gc
,
1426 pixel
^ values
.background
);
1427 if (m_window
&& m_window
->GetBackingPixmap())
1428 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
,
1429 pixel
^ values
.background
);
1433 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1434 if (m_window
&& m_window
->GetBackingPixmap())
1435 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1439 int wxWindowDC::CalculatePixel(wxColour
& colour
, wxColour
& curCol
,
1440 bool roundToWhite
) const
1442 const unsigned char wp
= (unsigned char)255;
1445 if(!m_colour
) // Mono display
1447 unsigned char red
= colour
.Red ();
1448 unsigned char blue
= colour
.Blue ();
1449 unsigned char green
= colour
.Green ();
1451 if((red
== wp
&& blue
== wp
&& green
== wp
) ||
1452 // not black and roundToWhite was specified
1453 ((red
!= 0 || blue
!= 0 || green
!= 0) && roundToWhite
))
1456 pixel
= (int)WhitePixel((Display
*) m_display
,
1457 DefaultScreen((Display
*) m_display
));
1458 curCol
.SetPixel(pixel
);
1459 colour
.SetPixel(pixel
);
1464 pixel
= (int)BlackPixel((Display
*) m_display
,
1465 DefaultScreen((Display
*) m_display
));
1466 curCol
.SetPixel(pixel
);
1467 colour
.SetPixel(pixel
);
1473 pixel
= colour
.AllocColour((Display
*) m_display
);
1474 curCol
.SetPixel(pixel
);
1480 void wxWindowDC::SetPen( const wxPen
&pen
)
1482 wxCHECK_RET( Ok(), "invalid dc" );
1488 wxBitmap oldStipple
= m_currentStipple
;
1489 int oldStyle
= m_currentStyle
;
1490 int oldFill
= m_currentFill
;
1491 int old_pen_width
= m_currentPenWidth
;
1492 int old_pen_join
= m_currentPenJoin
;
1493 int old_pen_cap
= m_currentPenCap
;
1494 int old_pen_nb_dash
= m_currentPenDashCount
;
1495 wxX11Dash
*old_pen_dash
= m_currentPenDash
;
1497 wxColour oldPenColour
= m_currentColour
;
1498 m_currentColour
= m_pen
.GetColour ();
1499 m_currentStyle
= m_pen
.GetStyle ();
1500 m_currentFill
= m_pen
.GetStyle (); // TODO?
1501 m_currentPenWidth
= m_pen
.GetWidth ();
1502 m_currentPenJoin
= m_pen
.GetJoin ();
1503 m_currentPenCap
= m_pen
.GetCap ();
1504 m_currentPenDashCount
= m_pen
.GetDashCount();
1505 m_currentPenDash
= (wxX11Dash
*)m_pen
.GetDash();
1507 if (m_currentStyle
== wxSTIPPLE
)
1508 m_currentStipple
= * m_pen
.GetStipple ();
1510 bool sameStyle
= (oldStyle
== m_currentStyle
&&
1511 oldFill
== m_currentFill
&&
1512 old_pen_join
== m_currentPenJoin
&&
1513 old_pen_cap
== m_currentPenCap
&&
1514 old_pen_nb_dash
== m_currentPenDashCount
&&
1515 old_pen_dash
== m_currentPenDash
&&
1516 old_pen_width
== m_currentPenWidth
);
1518 bool sameColour
= (oldPenColour
.Ok () &&
1519 (oldPenColour
.Red () == m_currentColour
.Red ()) &&
1520 (oldPenColour
.Blue () == m_currentColour
.Blue ()) &&
1521 (oldPenColour
.Green () == m_currentColour
.Green ()) &&
1522 (oldPenColour
.GetPixel() == m_currentColour
.GetPixel()));
1524 if (!sameStyle
|| !GET_OPTIMIZATION
)
1526 int scaled_width
= (int) XLOG2DEVREL (m_pen
.GetWidth ());
1527 if (scaled_width
< 0)
1533 static const wxX11Dash dotted
[] = {2, 5};
1534 static const wxX11Dash short_dashed
[] = {4, 4};
1535 static const wxX11Dash long_dashed
[] = {4, 8};
1536 static const wxX11Dash dotted_dashed
[] = {6, 6, 2, 6};
1538 // We express dash pattern in pen width unit, so we are
1539 // independent of zoom factor and so on...
1541 const wxX11Dash
*req_dash
;
1543 switch (m_pen
.GetStyle ())
1546 req_nb_dash
= m_currentPenDashCount
;
1547 req_dash
= m_currentPenDash
;
1548 style
= LineOnOffDash
;
1553 style
= LineOnOffDash
;
1557 req_dash
= short_dashed
;
1558 style
= LineOnOffDash
;
1562 req_dash
= long_dashed
;
1563 style
= LineOnOffDash
;
1567 req_dash
= dotted_dashed
;
1568 style
= LineOnOffDash
;
1575 req_dash
= (wxX11Dash
*)NULL
;
1579 if (req_dash
&& req_nb_dash
)
1581 wxX11Dash
*real_req_dash
= new wxX11Dash
[req_nb_dash
];
1584 int factor
= scaled_width
== 0 ? 1 : scaled_width
;
1585 for (int i
= 0; i
< req_nb_dash
; i
++)
1586 real_req_dash
[i
] = req_dash
[i
] * factor
;
1587 XSetDashes ((Display
*) m_display
, (GC
) m_gc
, 0, real_req_dash
, req_nb_dash
);
1589 if (m_window
&& m_window
->GetBackingPixmap())
1590 XSetDashes ((Display
*) m_display
,(GC
) m_gcBacking
, 0, real_req_dash
, req_nb_dash
);
1591 delete[]real_req_dash
;
1595 // No Memory. We use non-scaled dash pattern...
1596 XSetDashes ((Display
*) m_display
, (GC
) m_gc
, 0, req_dash
, req_nb_dash
);
1598 if (m_window
&& m_window
->GetBackingPixmap())
1599 XSetDashes ((Display
*) m_display
,(GC
) m_gcBacking
, 0, req_dash
, req_nb_dash
);
1603 switch (m_pen
.GetCap ())
1605 case wxCAP_PROJECTING
:
1606 cap
= CapProjecting
;
1613 cap
= (scaled_width
<= 1) ? CapNotLast
: CapRound
;
1617 switch (m_pen
.GetJoin ())
1631 XSetLineAttributes ((Display
*) m_display
, (GC
) m_gc
, scaled_width
, style
, cap
, join
);
1633 if (m_window
&& m_window
->GetBackingPixmap())
1634 XSetLineAttributes ((Display
*) m_display
,(GC
) m_gcBacking
, scaled_width
, style
, cap
, join
);
1637 if (IS_HATCH(m_currentFill
) && ((m_currentFill
!= oldFill
) || !GET_OPTIMIZATION
))
1641 oldStipple
= wxNullBitmap
; // For later reset!!
1643 switch (m_currentFill
)
1645 case wxBDIAGONAL_HATCH
:
1646 if (bdiag
== (Pixmap
) 0)
1647 bdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1648 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1649 bdiag_bits
, bdiag_width
, bdiag_height
);
1652 case wxFDIAGONAL_HATCH
:
1653 if (fdiag
== (Pixmap
) 0)
1654 fdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1655 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1656 fdiag_bits
, fdiag_width
, fdiag_height
);
1660 if (cross
== (Pixmap
) 0)
1661 cross
= XCreateBitmapFromData ((Display
*) m_display
,
1662 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1663 cross_bits
, cross_width
, cross_height
);
1666 case wxHORIZONTAL_HATCH
:
1667 if (horiz
== (Pixmap
) 0)
1668 horiz
= XCreateBitmapFromData ((Display
*) m_display
,
1669 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1670 horiz_bits
, horiz_width
, horiz_height
);
1673 case wxVERTICAL_HATCH
:
1674 if (verti
== (Pixmap
) 0)
1675 verti
= XCreateBitmapFromData ((Display
*) m_display
,
1676 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1677 verti_bits
, verti_width
, verti_height
);
1680 case wxCROSSDIAG_HATCH
:
1682 if (cdiag
== (Pixmap
) 0)
1683 cdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1684 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1685 cdiag_bits
, cdiag_width
, cdiag_height
);
1689 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, myStipple
);
1691 if (m_window
&& m_window
->GetBackingPixmap())
1692 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, myStipple
);
1694 else if (m_currentStipple
.Ok()
1695 && ((m_currentStipple
!= oldStipple
) || !GET_OPTIMIZATION
))
1697 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) m_currentStipple
.GetDrawable());
1699 if (m_window
&& m_window
->GetBackingPixmap())
1700 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, (Pixmap
) m_currentStipple
.GetDrawable());
1703 if ((m_currentFill
!= oldFill
) || !GET_OPTIMIZATION
)
1707 if (m_currentFill
== wxSTIPPLE
)
1708 fill_style
= FillStippled
;
1709 else if (IS_HATCH (m_currentFill
))
1710 fill_style
= FillStippled
;
1712 fill_style
= FillSolid
;
1713 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, fill_style
);
1714 if (m_window
&& m_window
->GetBackingPixmap())
1715 XSetFillStyle ((Display
*) m_display
,(GC
) m_gcBacking
, fill_style
);
1718 // must test m_logicalFunction, because it involves background!
1719 if (!sameColour
|| !GET_OPTIMIZATION
1720 || ((m_logicalFunction
== wxXOR
) || (m_autoSetting
& 0x2)))
1723 if (m_pen
.GetStyle () == wxTRANSPARENT
)
1724 pixel
= m_backgroundPixel
;
1727 pixel
= CalculatePixel(m_pen
.GetColour(), m_currentColour
, false);
1730 // Finally, set the GC to the required colour
1732 SetForegroundPixelWithLogicalFunction(pixel
);
1735 m_pen
.GetColour().SetPixel(oldPenColour
.GetPixel());
1740 void wxWindowDC::SetBrush( const wxBrush
&brush
)
1742 wxCHECK_RET( Ok(), "invalid dc" );
1746 if (!m_brush
.Ok() || m_brush
.GetStyle () == wxTRANSPARENT
)
1749 int oldFill
= m_currentFill
;
1750 wxBitmap oldStipple
= m_currentStipple
;
1752 m_autoSetting
|= 0x1;
1754 m_currentFill
= m_brush
.GetStyle ();
1755 if (m_currentFill
== wxSTIPPLE
)
1756 m_currentStipple
= * m_brush
.GetStipple ();
1758 wxColour
oldBrushColour(m_currentColour
);
1759 m_currentColour
= m_brush
.GetColour ();
1761 bool sameColour
= (oldBrushColour
.Ok () &&
1762 (oldBrushColour
.Red () == m_currentColour
.Red ()) &&
1763 (oldBrushColour
.Blue () == m_currentColour
.Blue ()) &&
1764 (oldBrushColour
.Green () == m_currentColour
.Green ()) &&
1765 (oldBrushColour
.GetPixel() == m_currentColour
.GetPixel()));
1767 int stippleDepth
= -1;
1769 if ((oldFill
!= m_brush
.GetStyle ()) || !GET_OPTIMIZATION
)
1771 switch (brush
.GetStyle ())
1776 stippleDepth
= m_currentStipple
.GetDepth();
1778 case wxBDIAGONAL_HATCH
:
1779 case wxCROSSDIAG_HATCH
:
1780 case wxFDIAGONAL_HATCH
:
1782 case wxHORIZONTAL_HATCH
:
1783 case wxVERTICAL_HATCH
:
1785 if (stippleDepth
== -1) stippleDepth
= 1;
1787 // Chris Breeze 23/07/97: use background mode to
1788 // determine whether fill style should be solid or
1790 int style
= stippleDepth
== 1 ?
1791 (m_backgroundMode
== wxSOLID
?
1792 FillOpaqueStippled
: FillStippled
) :
1794 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, style
);
1795 if (m_window
&& m_window
->GetBackingPixmap())
1796 XSetFillStyle ((Display
*) m_display
,(GC
) m_gcBacking
, style
);
1801 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, FillSolid
);
1802 if (m_window
&& m_window
->GetBackingPixmap())
1803 XSetFillStyle ((Display
*) m_display
,(GC
) m_gcBacking
,
1808 if (IS_HATCH(m_currentFill
) && ((m_currentFill
!= oldFill
) || !GET_OPTIMIZATION
))
1812 switch (m_currentFill
)
1814 case wxBDIAGONAL_HATCH
:
1815 if (bdiag
== (Pixmap
) 0)
1816 bdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1817 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1818 bdiag_bits
, bdiag_width
, bdiag_height
);
1821 case wxFDIAGONAL_HATCH
:
1822 if (fdiag
== (Pixmap
) 0)
1823 fdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1824 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1825 fdiag_bits
, fdiag_width
, fdiag_height
);
1829 if (cross
== (Pixmap
) 0)
1830 cross
= XCreateBitmapFromData ((Display
*) m_display
,
1831 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1832 cross_bits
, cross_width
, cross_height
);
1835 case wxHORIZONTAL_HATCH
:
1836 if (horiz
== (Pixmap
) 0)
1837 horiz
= XCreateBitmapFromData ((Display
*) m_display
,
1838 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1839 horiz_bits
, horiz_width
, horiz_height
);
1842 case wxVERTICAL_HATCH
:
1843 if (verti
== (Pixmap
) 0)
1844 verti
= XCreateBitmapFromData ((Display
*) m_display
,
1845 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1846 verti_bits
, verti_width
, verti_height
);
1849 case wxCROSSDIAG_HATCH
:
1851 if (cdiag
== (Pixmap
) 0)
1852 cdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1853 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1854 cdiag_bits
, cdiag_width
, cdiag_height
);
1858 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, myStipple
);
1860 if (m_window
&& m_window
->GetBackingPixmap())
1861 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, myStipple
);
1863 // X can forget the stipple value when resizing a window (apparently)
1864 // so always set the stipple.
1865 else if (m_currentFill
!= wxSOLID
&& m_currentFill
!= wxTRANSPARENT
&&
1866 m_currentStipple
.Ok()) // && m_currentStipple != oldStipple)
1868 if (m_currentStipple
.GetDepth() == 1)
1870 XSetStipple ((Display
*) m_display
, (GC
) m_gc
,
1871 (Pixmap
) m_currentStipple
.GetDrawable());
1872 if (m_window
&& m_window
->GetBackingPixmap())
1873 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
,
1874 (Pixmap
) m_currentStipple
.GetDrawable());
1878 XSetTile ((Display
*) m_display
, (GC
) m_gc
,
1879 (Pixmap
) m_currentStipple
.GetDrawable());
1880 if (m_window
&& m_window
->GetBackingPixmap())
1881 XSetTile ((Display
*) m_display
,(GC
) m_gcBacking
,
1882 (Pixmap
) m_currentStipple
.GetDrawable());
1886 // must test m_logicalFunction, because it involves background!
1887 if (!sameColour
|| !GET_OPTIMIZATION
|| m_logicalFunction
== wxXOR
)
1889 int pixel
= CalculatePixel(m_brush
.GetColour(), m_currentColour
, true);
1892 SetForegroundPixelWithLogicalFunction(pixel
);
1895 m_brush
.GetColour().SetPixel(oldBrushColour
.GetPixel());
1898 void wxWindowDC::SetBackground( const wxBrush
&brush
)
1900 wxCHECK_RET( Ok(), "invalid dc" );
1902 m_backgroundBrush
= brush
;
1904 if (!m_backgroundBrush
.Ok())
1907 m_backgroundPixel
= m_backgroundBrush
.GetColour().AllocColour(m_display
);
1909 // Necessary for ::DrawIcon, which use fg/bg pixel or the GC.
1910 // And Blit,... (Any fct that use XCopyPlane, in fact.)
1911 XSetBackground ((Display
*) m_display
, (GC
) m_gc
, m_backgroundPixel
);
1912 if (m_window
&& m_window
->GetBackingPixmap())
1913 XSetBackground ((Display
*) m_display
,(GC
) m_gcBacking
,
1917 void wxWindowDC::SetLogicalFunction( int function
)
1919 wxCHECK_RET( Ok(), "invalid dc" );
1924 if (m_logicalFunction
== function
)
1930 x_function
= GXclear
;
1936 x_function
= GXinvert
;
1939 x_function
= GXorReverse
;
1942 x_function
= GXandReverse
;
1951 x_function
= GXandInverted
;
1954 x_function
= GXnoop
;
1960 x_function
= GXequiv
;
1963 x_function
= GXcopyInverted
;
1966 x_function
= GXorInverted
;
1969 x_function
= GXnand
;
1976 x_function
= GXcopy
;
1980 XSetFunction((Display
*) m_display
, (GC
) m_gc
, x_function
);
1981 if (m_window
&& m_window
->GetBackingPixmap())
1982 XSetFunction((Display
*) m_display
, (GC
) m_gcBacking
, x_function
);
1984 if ((m_logicalFunction
== wxXOR
) != (function
== wxXOR
))
1985 /* MATTHEW: [9] Need to redo pen simply */
1986 m_autoSetting
|= 0x2;
1988 m_logicalFunction
= function
;
1992 void wxWindowDC::SetTextForeground( const wxColour
&col
)
1994 wxCHECK_RET( Ok(), "invalid dc" );
1996 m_textForegroundColour
= col
;
1999 void wxWindowDC::SetTextBackground( const wxColour
&col
)
2001 wxCHECK_RET( Ok(), "invalid dc" );
2003 m_textBackgroundColour
= col
;
2006 void wxWindowDC::SetBackgroundMode( int mode
)
2008 m_backgroundMode
= mode
;
2011 void wxWindowDC::SetPalette( const wxPalette
& palette
)
2016 /* Use GetXColormap */
2017 XSetWindowColormap ((Display
*) m_display
, (Window
) m_window
->GetXWindow(),
2018 (Colormap
) palette
.GetXColormap());
2020 /* Use wxGetMainColormap */
2021 XSetWindowColormap ((Display
*) m_display
, (Window
) m_window
->GetXWindow(),
2022 (Colormap
) wxTheApp
->GetMainColormap(m_display
));
2026 static void wxCopyRegion( WXRegion src
, WXRegion
& dst
)
2029 dst
= XCreateRegion();
2030 XUnionRegion( (Region
)src
, (Region
)src
, (Region
)dst
);
2033 // Helper function; userRegion is the region set by calling SetClippingRegion
2034 void wxWindowDC::SetDCClipping( WXRegion userRegion
)
2036 bool hasUpdateRegion
= m_window
&& m_window
->GetUpdateRegion().Ok();
2037 // this means that we should start the clip region from scratch,
2038 // or from the update region, if any
2042 XDestroyRegion( (Region
)m_clipRegion
);
2043 m_clipRegion
= (WXRegion
)NULL
;
2045 if( hasUpdateRegion
)
2046 wxCopyRegion( m_window
->GetUpdateRegion().GetX11Region(),
2049 // intersect the user region, if any, with the
2050 // exisiting clip region
2051 else // if( userRegion )
2054 wxCopyRegion( userRegion
, m_clipRegion
);
2056 XIntersectRegion( (Region
)m_clipRegion
,
2057 (Region
)userRegion
, (Region
)m_clipRegion
);
2061 XSetRegion( (Display
*)m_display
, (GC
)m_gc
, (Region
)m_clipRegion
);
2063 XSetClipMask( (Display
*)m_display
, (GC
)m_gc
, None
);
2066 void wxWindowDC::DoSetClippingRegion( wxCoord x
, wxCoord y
,
2067 wxCoord width
, wxCoord height
)
2069 wxDC::DoSetClippingRegion( x
, y
, width
, height
);
2071 wxRegion
temp(x
, y
, width
, height
);
2073 SetDCClipping(temp
.GetX11Region());
2075 // Needs to work differently for Pixmap: without this,
2076 // there's a nasty (Display*) m_display bug. 8/12/94
2077 if (m_window
&& m_window
->GetBackingPixmap())
2079 XRectangle rects
[1];
2080 rects
[0].x
= XLOG2DEV_2(x
);
2081 rects
[0].y
= YLOG2DEV_2(y
);
2082 rects
[0].width
= XLOG2DEVREL(width
);
2083 rects
[0].height
= YLOG2DEVREL(height
);
2084 XSetClipRectangles((Display
*) m_display
, (GC
) m_gcBacking
,
2085 0, 0, rects
, 1, Unsorted
);
2089 void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion
& region
)
2091 wxRect box
= region
.GetBox();
2093 wxDC::DoSetClippingRegion( box
.x
, box
.y
, box
.width
, box
.height
);
2095 SetDCClipping(region
.GetX11Region());
2097 // Needs to work differently for Pixmap: without this,
2098 // there's a nasty (Display*) m_display bug. 8/12/94
2099 if (m_window
&& m_window
->GetBackingPixmap())
2101 XRectangle rects
[1];
2102 rects
[0].x
= XLOG2DEV_2(box
.x
);
2103 rects
[0].y
= YLOG2DEV_2(box
.y
);
2104 rects
[0].width
= XLOG2DEVREL(box
.width
);
2105 rects
[0].height
= YLOG2DEVREL(box
.height
);
2106 XSetClipRectangles((Display
*) m_display
, (GC
) m_gcBacking
,
2107 0, 0, rects
, 1, Unsorted
);
2112 void wxWindowDC::DestroyClippingRegion()
2114 wxDC::DestroyClippingRegion();
2116 SetDCClipping(NULL
);
2118 if (m_window
&& m_window
->GetBackingPixmap())
2119 XSetClipMask ((Display
*) m_display
, (GC
) m_gcBacking
, None
);
2122 // Resolution in pixels per logical inch
2123 wxSize
wxWindowDC::GetPPI() const
2126 return wxSize(100, 100);
2129 int wxWindowDC::GetDepth() const
2138 // ----------------------------------------------------------------------------
2140 // ----------------------------------------------------------------------------
2142 wxPaintDC::wxPaintDC(wxWindow
* win
) : wxWindowDC(win
)
2144 // Set the clipping region.to the update region
2145 SetDCClipping((WXRegion
)NULL
);
2148 wxPaintDC::~wxPaintDC()
2151 m_window
->ClearUpdateRegion();
2152 SetDCClipping((WXRegion
)NULL
);
2155 // ----------------------------------------------------------------------------
2156 // private functions
2157 // ----------------------------------------------------------------------------
2160 Used when copying between drawables on different (Display*) m_displays. Not
2161 very fast, but better than giving up.
2164 static void XCopyRemote(Display
*src_display
, Display
*dest_display
,
2165 Drawable src
, Drawable dest
,
2168 unsigned int w
, unsigned int h
,
2169 int destx
, int desty
,
2170 bool more
, XImage
**cache
)
2172 XImage
*image
, *destimage
;
2173 Colormap destcm
, srccm
;
2174 static const int CACHE_SIZE
= 256;
2177 unsigned long cachesrc
[CACHE_SIZE
], cachedest
[CACHE_SIZE
];
2178 int k
, cache_pos
, all_cache
;
2180 if (!cache
|| !*cache
)
2181 image
= XGetImage(src_display
, src
, srcx
, srcy
, w
, h
, AllPlanes
, ZPixmap
);
2185 destimage
= XGetImage(dest_display
, dest
, destx
, desty
, w
, h
, AllPlanes
, ZPixmap
);
2187 srccm
= (Colormap
) wxTheApp
->GetMainColormap((WXDisplay
*) src_display
);
2188 destcm
= (Colormap
) wxTheApp
->GetMainColormap((WXDisplay
*) dest_display
);
2193 for (i
= 0; i
< w
; i
++)
2194 for (j
= 0; j
< h
; j
++) {
2195 unsigned long pixel
;
2198 pixel
= XGetPixel(image
, i
, j
);
2199 for (k
= cache_pos
; k
--; )
2200 if (cachesrc
[k
] == pixel
) {
2201 pixel
= cachedest
[k
];
2205 for (k
= CACHE_SIZE
; k
-- > cache_pos
; )
2206 if (cachesrc
[k
] == pixel
) {
2207 pixel
= cachedest
[k
];
2211 cachesrc
[cache_pos
] = xcol
.pixel
= pixel
;
2212 XQueryColor(src_display
, srccm
, &xcol
);
2213 if (!XAllocColor(dest_display
, destcm
, &xcol
))
2215 cachedest
[cache_pos
] = pixel
= xcol
.pixel
;
2217 if (++cache_pos
>= CACHE_SIZE
) {
2223 XPutPixel(destimage
, i
, j
, pixel
);
2226 XPutImage(dest_display
, dest
, destgc
, destimage
, 0, 0, destx
, desty
, w
, h
);
2227 XDestroyImage(destimage
);
2232 XDestroyImage(image
);
2237 /* Helper function for 16-bit fonts */
2238 static int str16len(const char *s
)
2242 while (s
[0] && s
[1]) {