1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxClientDC class
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
13 About pens, brushes, and the autoSetting flag:
15 Under X, pens and brushes control some of the same X drawing parameters.
16 Therefore, it is impossible to independently maintain the current pen and the
17 current brush. Also, some settings depend on the current logical function. The
18 m_currentFill, etc. instance variables remember state across the brush and
21 Since pens are used more than brushes, the autoSetting flag is used to
22 indicate that a brush was recently used, and SetPen must be called to
23 reinstall the current pen's parameters. If autoSetting includes 0x2, then the
24 pens color may need to be set based on XOR.
26 There is, unfortunately, some confusion between setting the current pen/brush
27 and actually installing the brush/pen parameters. Both functionalies are
28 perform by SetPen and SetBrush. C'est la vie.
31 // ============================================================================
33 // ============================================================================
35 // ----------------------------------------------------------------------------
37 // ----------------------------------------------------------------------------
40 #pragma implementation "dcclient.h"
43 #include "wx/dcclient.h"
44 #include "wx/dcmemory.h"
45 #include "wx/window.h"
53 #pragma message disable nosimpint
57 #pragma message enable nosimpint
60 #include "wx/motif/private.h"
63 #include <float.h> // for M_PI
73 static Pixmap bdiag
, cdiag
, fdiag
, cross
, horiz
, verti
;
75 // ----------------------------------------------------------------------------
77 // ----------------------------------------------------------------------------
79 // Fudge factor (VZ: what??)
82 // ----------------------------------------------------------------------------
84 // ----------------------------------------------------------------------------
86 IMPLEMENT_DYNAMIC_CLASS(wxClientDC
, wxWindowDC
)
87 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC
, wxWindowDC
)
88 IMPLEMENT_DYNAMIC_CLASS(wxWindowDC
, wxDC
)
90 // ----------------------------------------------------------------------------
92 // ----------------------------------------------------------------------------
94 static void XCopyRemote(Display
*src_display
, Display
*dest_display
,
95 Drawable src
, Drawable dest
,
98 unsigned int w
, unsigned int h
,
100 bool more
, XImage
**cache
);
102 // ============================================================================
104 // ============================================================================
107 * compare two doubles and return the larger rounded
110 static int roundmax(double a
, double b
)
112 return (int)((a
> b
? a
: b
) + 0.5);
116 * compare two doubles and return the smaller rounded
119 static int roundmin(double a
, double b
)
121 return (int)((a
< b
? a
: b
) - 0.5);
125 // ----------------------------------------------------------------------------
127 // ----------------------------------------------------------------------------
129 wxWindowDC::wxWindowDC()
132 m_gcBacking
= (WXGC
) 0;
134 m_backgroundPixel
= -1;
135 m_currentPenWidth
= 1;
136 m_currentPenJoin
= -1;
137 m_currentPenDashCount
= -1;
138 m_currentPenDash
= (wxMOTIFDash
*) NULL
;
141 // m_currentBkMode = wxTRANSPARENT;
142 m_colour
= wxColourDisplay();
143 m_display
= (WXDisplay
*) NULL
;
144 m_currentRegion
= (WXRegion
) 0;
145 m_userRegion
= (WXRegion
) 0;
146 m_pixmap
= (WXPixmap
) 0;
148 m_oldFont
= (WXFont
) 0;
151 wxWindowDC::wxWindowDC( wxWindow
*window
)
153 wxASSERT_MSG( (window
!= (wxWindow
*) NULL
), "You must pass a valid wxWindow to wxWindowDC/wxClientDC/wxPaintDC constructor." );
156 m_font
= window
->GetFont();
158 m_gcBacking
= (WXGC
) 0;
159 m_backgroundPixel
= -1;
160 m_currentPenWidth
= 1;
161 m_currentPenJoin
= -1;
162 m_currentPenDashCount
= -1;
163 m_currentPenDash
= (wxMOTIFDash
*) NULL
;
166 // m_currentBkMode = wxTRANSPARENT;
167 m_colour
= wxColourDisplay();
168 m_currentRegion
= (WXRegion
) 0;
169 m_userRegion
= (WXRegion
) 0;
173 m_display
= window
->GetXDisplay();
174 m_pixmap
= window
->GetXWindow();
175 Display
* display
= (Display
*) m_display
;
177 XSetWindowColormap (display
, (Pixmap
) m_pixmap
, (Colormap
) wxTheApp
->GetMainColormap(m_display
));
180 gcvalues
.foreground
= BlackPixel (display
, DefaultScreen (display
));
181 gcvalues
.background
= WhitePixel (display
, DefaultScreen (display
));
182 gcvalues
.graphics_exposures
= False
;
183 gcvalues
.subwindow_mode
= IncludeInferiors
;
184 gcvalues
.line_width
= 1;
185 m_gc
= (WXGC
) XCreateGC (display
, RootWindow (display
, DefaultScreen (display
)),
186 GCForeground
| GCBackground
| GCGraphicsExposures
| GCLineWidth
| GCSubwindowMode
,
189 if (m_window
->GetBackingPixmap())
191 m_gcBacking
= (WXGC
) XCreateGC (display
, RootWindow (display
,
192 DefaultScreen (display
)),
193 GCForeground
| GCBackground
| GCGraphicsExposures
| GCLineWidth
| GCSubwindowMode
,
197 m_backgroundPixel
= (int) gcvalues
.background
;
199 // Get the current Font so we can set it back later
201 XGetGCValues((Display
*) m_display
, (GC
) m_gc
, GCFont
, &valReturn
);
202 m_oldFont
= (WXFont
) valReturn
.font
;
204 SetBackground(wxBrush(m_window
->GetBackgroundColour(), wxSOLID
));
207 wxWindowDC::~wxWindowDC()
209 if (m_gc
&& (m_oldFont
!= (WXFont
) 0) && ((long) m_oldFont
!= -1))
211 XSetFont ((Display
*) m_display
, (GC
) m_gc
, (Font
) m_oldFont
);
213 if (m_window
&& m_window
->GetBackingPixmap())
214 XSetFont ((Display
*) m_display
,(GC
) m_gcBacking
, (Font
) m_oldFont
);
218 XFreeGC ((Display
*) m_display
, (GC
) m_gc
);
222 XFreeGC ((Display
*) m_display
, (GC
) m_gcBacking
);
223 m_gcBacking
= (WXGC
) 0;
226 XDestroyRegion ((Region
) m_currentRegion
);
227 m_currentRegion
= (WXRegion
) 0;
230 XDestroyRegion ((Region
) m_userRegion
);
231 m_userRegion
= (WXRegion
) 0;
234 void wxWindowDC::DoFloodFill( wxCoord x1
, wxCoord y1
,
235 const wxColour
& col
, int style
)
237 if (GetBrush().GetStyle() == wxTRANSPARENT
)
239 wxLogDebug(wxT("In FloodFill, current brush is transparent, no filling done"));
244 this->GetSize(&width
, &height
);
245 //it would be nice to fail if we don't get a sensible size...
246 if (width
< 1 || height
< 1)
248 wxLogError(wxT("In FloodFill, dc.GetSize routine failed, method not supported by this DC"));
252 //this is much faster than doing the individual pixels
254 wxBitmap
bitmap(width
, height
);
255 memdc
.SelectObject(bitmap
);
256 memdc
.Blit(0, 0, width
, height
, (wxDC
*) this, 0, 0);
257 memdc
.SelectObject(wxNullBitmap
);
259 wxImage
image(bitmap
);
260 image
.DoFloodFill (x
,y
, GetBrush(), col
, style
, GetLogicalFunction());
261 bitmap
= wxBitmap(image
);
262 memdc
.SelectObject(bitmap
);
263 this->Blit(0, 0, width
, height
, &memdc
, 0, 0);
264 memdc
.SelectObject(wxNullBitmap
);
267 bool wxWindowDC::DoGetPixel( wxCoord x1
, wxCoord y1
, wxColour
*col
) const
269 // Generic (and therefore rather inefficient) method.
270 // Could be improved.
272 wxBitmap
bitmap(1, 1);
273 memdc
.SelectObject(bitmap
);
274 memdc
.Blit(0, 0, 1, 1, (wxDC
*) this, x1
, y1
);
275 memdc
.SelectObject(wxNullBitmap
);
276 wxImage
image(bitmap
);
277 col
->Set(image
.GetRed(0, 0), image
.GetGreen(0, 0), image
.GetBlue(0, 0));
281 void wxWindowDC::DoDrawLine( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
)
283 wxCHECK_RET( Ok(), "invalid dc" );
285 int x1d
, y1d
, x2d
, y2d
;
287 // FreeGetPixelCache();
297 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, x1d
, y1d
, x2d
, y2d
);
299 if (m_window
&& m_window
->GetBackingPixmap())
300 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
301 XLOG2DEV_2(x1
), YLOG2DEV_2(y1
),
302 XLOG2DEV_2(x2
), YLOG2DEV_2(y2
));
304 CalcBoundingBox(x1
, y1
);
305 CalcBoundingBox(x2
, y2
);
308 void wxWindowDC::DoCrossHair( wxCoord x
, wxCoord y
)
310 wxCHECK_RET( Ok(), "invalid dc" );
315 int xx
= XLOG2DEV (x
);
316 int yy
= YLOG2DEV (y
);
318 wxDisplaySize (&ww
, &hh
);
319 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, 0, yy
,
321 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xx
, 0,
324 if (m_window
&& m_window
->GetBackingPixmap())
328 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
331 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
337 void wxWindowDC::DoDrawArc( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
, wxCoord xc
, wxCoord yc
)
339 wxCHECK_RET( Ok(), "invalid dc" );
341 // FreeGetPixelCache();
343 int xx1
= XLOG2DEV (x1
);
344 int yy1
= YLOG2DEV (y1
);
345 int xx2
= XLOG2DEV (x2
);
346 int yy2
= YLOG2DEV (y2
);
347 int xxc
= XLOG2DEV (xc
);
348 int yyc
= YLOG2DEV (yc
);
349 int xxc_2
= XLOG2DEV_2 (xc
);
350 int yyc_2
= YLOG2DEV_2 (yc
);
352 wxCoord dx
= xx1
- xxc
;
353 wxCoord dy
= yy1
- yyc
;
354 double radius
= sqrt ((double)(dx
* dx
+ dy
* dy
));
355 wxCoord r
= (wxCoord
) radius
;
357 double radius1
, radius2
;
359 if (xx1
== xx2
&& yy1
== yy2
)
364 else if (radius
== 0.0)
365 radius1
= radius2
= 0.0;
374 radius1
= -atan2 ((double) (yy1
- yyc
), (double) (xx1
- xxc
)) * 360.0 / (2 * M_PI
);
382 radius2
= -atan2 ((double) (yy2
- yyc
), (double) (xx2
- xxc
)) * 360.0 / (2 * M_PI
);
386 int alpha1
= (int) radius1
;
387 int alpha2
= (int) (radius2
- radius1
);
390 while (alpha2
> 360 * 64)
393 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
396 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) (GC
) m_gc
,
397 xxc
- r
, yyc
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
399 if (m_window
&& m_window
->GetBackingPixmap())
400 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
401 xxc_2
- r
, yyc_2
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
405 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
409 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
410 xxc
- r
, yyc
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
412 if (m_window
&& m_window
->GetBackingPixmap())
413 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
414 xxc_2
- r
, yyc_2
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
416 CalcBoundingBox (x1
, y1
);
417 CalcBoundingBox (x2
, y2
);
420 void wxWindowDC::DoDrawEllipticArc( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double sa
, double ea
)
422 wxCHECK_RET( Ok(), "invalid dc" );
428 wd
= XLOG2DEVREL(width
);
429 hd
= YLOG2DEVREL(height
);
431 if (sa
>=360 || sa
<=-360) sa
=sa
-int(sa
/360)*360;
432 if (ea
>=360 || ea
<=-360) ea
=ea
-int(ea
/360)*360;
433 int start
= int(sa
*64);
434 int end
= int(ea
*64);
435 if (start
<0) start
+=360*64;
436 if (end
<0) end
+=360*64;
437 if (end
>start
) end
-=start
;
438 else end
+=360*64-start
;
440 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
442 m_autoSetting
= TRUE
; // must be reset
445 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, start
, end
);
447 if (m_window
&& m_window
->GetBackingPixmap())
448 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
449 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),wd
,hd
,start
,end
);
452 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
456 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, start
,end
);
457 if (m_window
&& m_window
->GetBackingPixmap())
458 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
459 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),wd
,hd
,start
,end
);
461 CalcBoundingBox (x
, y
);
462 CalcBoundingBox (x
+ width
, y
+ height
);
465 void wxWindowDC::DoDrawPoint( wxCoord x
, wxCoord y
)
467 wxCHECK_RET( Ok(), "invalid dc" );
469 // FreeGetPixelCache();
471 if (m_pen
.Ok() && m_autoSetting
)
474 XDrawPoint ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
));
475 if (m_window
&& m_window
->GetBackingPixmap())
476 XDrawPoint ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, XLOG2DEV_2 (x
), YLOG2DEV_2 (y
));
478 CalcBoundingBox (x
, y
);
481 void wxWindowDC::DoDrawLines( int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
)
483 wxCHECK_RET( Ok(), "invalid dc" );
485 // FreeGetPixelCache();
487 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
492 XPoint
*xpoints
= new XPoint
[n
];
495 for (i
= 0; i
< n
; i
++)
497 xpoints
[i
].x
= XLOG2DEV (points
[i
].x
+ xoffset
);
498 xpoints
[i
].y
= YLOG2DEV (points
[i
].y
+ yoffset
);
500 XDrawLines ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xpoints
, n
, 0);
502 if (m_window
&& m_window
->GetBackingPixmap())
504 for (i
= 0; i
< n
; i
++)
506 xpoints
[i
].x
= XLOG2DEV_2 (points
[i
].x
+ xoffset
);
507 xpoints
[i
].y
= YLOG2DEV_2 (points
[i
].y
+ yoffset
);
509 XDrawLines ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, xpoints
, n
, 0);
515 void wxWindowDC::DoDrawPolygon( int n
, wxPoint points
[],
516 wxCoord xoffset
, wxCoord yoffset
, int fillStyle
)
518 wxCHECK_RET( Ok(), "invalid dc" );
520 // FreeGetPixelCache();
522 XPoint
*xpoints1
= new XPoint
[n
+ 1];
523 XPoint
*xpoints2
= new XPoint
[n
+ 1];
525 for (i
= 0; i
< n
; i
++)
527 xpoints1
[i
].x
= XLOG2DEV (points
[i
].x
+ xoffset
);
528 xpoints1
[i
].y
= YLOG2DEV (points
[i
].y
+ yoffset
);
529 xpoints2
[i
].x
= XLOG2DEV_2 (points
[i
].x
+ xoffset
);
530 xpoints2
[i
].y
= YLOG2DEV_2 (points
[i
].y
+ yoffset
);
531 CalcBoundingBox (points
[i
].x
+ xoffset
, points
[i
].y
+ yoffset
);
534 // Close figure for XDrawLines (not needed for XFillPolygon)
535 xpoints1
[i
].x
= xpoints1
[0].x
;
536 xpoints1
[i
].y
= xpoints1
[0].y
;
537 xpoints2
[i
].x
= xpoints2
[0].x
;
538 xpoints2
[i
].y
= xpoints2
[0].y
;
540 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
543 XSetFillRule ((Display
*) m_display
, (GC
) m_gc
, fillStyle
== wxODDEVEN_RULE
? EvenOddRule
: WindingRule
);
544 XFillPolygon ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xpoints1
, n
, Complex
, 0);
545 XSetFillRule ((Display
*) m_display
, (GC
) m_gc
, EvenOddRule
); // default mode
546 if (m_window
&& m_window
->GetBackingPixmap())
548 XSetFillRule ((Display
*) m_display
,(GC
) m_gcBacking
,
549 fillStyle
== wxODDEVEN_RULE
? EvenOddRule
: WindingRule
);
550 XFillPolygon ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, xpoints2
, n
, Complex
, 0);
551 XSetFillRule ((Display
*) m_display
,(GC
) m_gcBacking
, EvenOddRule
); // default mode
555 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
559 XDrawLines ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xpoints1
, n
+ 1, 0);
561 if (m_window
&& m_window
->GetBackingPixmap())
562 XDrawLines ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, xpoints2
, n
+ 1, 0);
569 void wxWindowDC::DoDrawRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
571 wxCHECK_RET( Ok(), "invalid dc" );
573 // FreeGetPixelCache();
575 int xd
, yd
, wfd
, hfd
, wd
, hd
;
579 wfd
= XLOG2DEVREL(width
);
581 hfd
= YLOG2DEVREL(height
);
584 if (wfd
== 0 || hfd
== 0) return;
585 if (wd
< 0) { wd
= - wd
; xd
= xd
- wd
; }
586 if (hd
< 0) { hd
= - hd
; yd
= yd
- hd
; }
588 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
591 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wfd
, hfd
);
593 if (m_window
&& m_window
->GetBackingPixmap())
594 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
595 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
599 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
603 XDrawRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
);
605 if (m_window
&& m_window
->GetBackingPixmap())
606 XDrawRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
607 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
610 CalcBoundingBox (x
, y
);
611 CalcBoundingBox (x
+ width
, y
+ height
);
614 void wxWindowDC::DoDrawRoundedRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double radius
)
616 wxCHECK_RET( Ok(), "invalid dc" );
618 // FreeGetPixelCache();
620 // If radius is negative, it's a proportion of the smaller dimension.
622 if (radius
< 0.0) radius
= - radius
* ((width
< height
) ? width
: height
);
624 int xd
= XLOG2DEV (x
);
625 int yd
= YLOG2DEV (y
);
626 int rd
= XLOG2DEVREL ((long) radius
);
627 int wd
= XLOG2DEVREL (width
) - WX_GC_CF
;
628 int hd
= YLOG2DEVREL (height
) - WX_GC_CF
;
633 // If radius is zero use DrawRectangle() instead to avoid
634 // X drawing errors with small radii
637 DrawRectangle( x
, y
, width
, height
);
641 // Draw nothing if transformed w or h is 0
642 if (wd
== 0 || hd
== 0) return;
644 // CMB: adjust size if outline is drawn otherwise the result is
645 // 1 pixel too wide and high
646 if (m_pen
.GetStyle() != wxTRANSPARENT
)
652 // CMB: ensure dd is not larger than rectangle otherwise we
653 // get an hour glass shape
654 if (rw_d
> wd
) rw_d
= wd
;
655 if (rw_d
> hd
) rw_d
= hd
;
658 // For backing pixmap
659 int xd2
= XLOG2DEV_2 (x
);
660 int yd2
= YLOG2DEV_2 (y
);
661 int rd2
= XLOG2DEVREL ((long) radius
);
662 int wd2
= XLOG2DEVREL (width
) ;
663 int hd2
= YLOG2DEVREL (height
) ;
668 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
672 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ rd
, yd
,
674 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ rd
,
677 // Arcs start from 3 o'clock, positive angles anticlockwise
679 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
,
680 rw_d
, rh_d
, 90 * 64, 90 * 64);
682 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
, yd
,
683 // rw_d, rh_d, 0, 90 * 64);
684 rw_d
, rh_d
, 0, 91 * 64);
686 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
,
688 // rw_d, rh_d, 270 * 64, 90 * 64);
689 rw_d
, rh_d
, 269 * 64, 92 * 64);
691 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ hd
- rh_d
,
692 rw_d
, rh_d
, 180 * 64, 90 * 64);
694 if (m_window
&& m_window
->GetBackingPixmap())
696 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
697 xd2
+ rd2
, yd2
, wd2
- rw_d2
, hd2
);
698 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
699 xd2
, yd2
+ rd2
, wd2
, hd2
- rh_d2
);
701 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
702 xd2
, yd2
, rw_d2
, rh_d2
, 90 * 64, 90 * 64);
703 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
704 xd2
+ wd2
- rw_d2
, yd2
,
705 // rw_d2, rh_d2, 0, 90 * 64);
706 rw_d2
, rh_d2
, 0, 91 * 64);
707 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
710 // rw_d2, rh_d2, 270 * 64, 90 * 64);
711 rw_d2
, rh_d2
, 269 * 64, 92 * 64);
712 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
713 xd2
, yd2
+ hd2
- rh_d2
,
714 rw_d2
, rh_d2
, 180 * 64, 90 * 64);
718 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
721 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ rd
, yd
,
722 xd
+ wd
- rd
+ 1, yd
);
723 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ rd
, yd
+ hd
,
724 xd
+ wd
- rd
, yd
+ hd
);
726 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ rd
,
728 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
, yd
+ rd
,
729 xd
+ wd
, yd
+ hd
- rd
+ 1);
730 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
,
731 rw_d
, rh_d
, 90 * 64, 90 * 64);
732 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
, yd
,
733 // rw_d, rh_d, 0, 90 * 64);
734 rw_d
, rh_d
, 0, 91 * 64);
735 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
,
737 rw_d
, rh_d
, 269 * 64, 92 * 64);
738 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ hd
- rh_d
,
739 rw_d
, rh_d
, 180 * 64, 90 * 64);
741 if (m_window
&& m_window
->GetBackingPixmap())
743 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
745 xd2
+ wd2
- rd2
+ 1, yd2
);
746 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
747 xd2
+ rd2
, yd2
+ hd2
,
748 xd2
+ wd2
- rd2
, yd2
+ hd2
);
750 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
752 xd2
, yd2
+ hd2
- rd2
);
753 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
754 xd2
+ wd2
, yd2
+ rd2
,
755 xd2
+ wd2
, yd2
+ hd2
- rd2
+ 1);
756 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
758 rw_d2
, rh_d2
, 90 * 64, 90 * 64);
759 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
760 xd2
+ wd2
- rw_d2
, yd2
,
761 // rw_d2, rh_d2, 0, 90 * 64);
762 rw_d2
, rh_d2
, 0, 91 * 64);
763 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
766 rw_d2
, rh_d2
, 269 * 64, 92 * 64);
767 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
768 xd2
, yd2
+ hd2
- rh_d2
,
769 rw_d2
, rh_d2
, 180 * 64, 90 * 64);
772 CalcBoundingBox (x
, y
);
773 CalcBoundingBox (x
+ width
, y
+ height
);
778 void wxWindowDC::DoDrawEllipse( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
780 wxCHECK_RET( Ok(), "invalid dc" );
782 // Check for negative width and height
795 // FreeGetPixelCache();
797 static const int angle
= 23040;
803 wd
= XLOG2DEVREL(width
) ;
804 hd
= YLOG2DEVREL(height
) ;
806 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
809 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, 0, angle
);
810 if (m_window
&& m_window
->GetBackingPixmap())
811 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
812 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
813 XLOG2DEVREL (width
) - WX_GC_CF
,
814 YLOG2DEVREL (height
) - WX_GC_CF
, 0, angle
);
817 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
821 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, 0, angle
);
822 if (m_window
&& m_window
->GetBackingPixmap())
823 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
824 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
825 XLOG2DEVREL (width
) - WX_GC_CF
,
826 YLOG2DEVREL (height
) - WX_GC_CF
, 0, angle
);
828 CalcBoundingBox (x
, y
);
829 CalcBoundingBox (x
+ width
, y
+ height
);
833 bool wxWindowDC::CanDrawBitmap() const
835 wxCHECK_MSG( Ok(), FALSE
, "invalid dc" );
841 void wxWindowDC::DoDrawIcon( const wxIcon
&icon
, wxCoord x
, wxCoord y
)
843 // FreeGetPixelCache();
845 // Be sure that foreground pixels (1) of
846 // the Icon will be painted with pen colour. [m_pen.SetColour()]
847 // Background pixels (0) will be painted with
848 // last selected background color. [::SetBackground]
849 if (m_pen
.Ok() && m_autoSetting
)
853 Pixmap iconPixmap
= (Pixmap
) icon
.GetPixmap();
854 width
= icon
.GetWidth();
855 height
= icon
.GetHeight();
856 if (icon
.GetDisplay() == m_display
)
858 if (icon
.GetDepth() <= 1)
860 XCopyPlane ((Display
*) m_display
, iconPixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
862 (int) XLOG2DEV (x
), (int) YLOG2DEV (y
), 1);
866 XCopyArea ((Display
*) m_display
, iconPixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
868 (int) XLOG2DEV (x
), (int) YLOG2DEV (y
));
872 if (m_window
&& m_window
->GetBackingPixmap())
874 if (icon
.GetDepth() <= 1)
876 XCopyPlane ((Display
*) m_display
, iconPixmap
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
877 0, 0, width
, height
, (int) XLOG2DEV_2 (x
), (int) YLOG2DEV_2 (y
), 1);
881 XCopyArea ((Display
*) m_display
, iconPixmap
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
883 (int) XLOG2DEV_2 (x
), (int) YLOG2DEV_2 (y
));
886 } else { /* Remote copy (different (Display*) m_displays) */
887 XImage
*cache
= NULL
;
888 if (m_window
&& m_window
->GetBackingPixmap())
889 XCopyRemote((Display
*) icon
.GetDisplay(), (Display
*) m_display
, iconPixmap
, (Pixmap
) m_window
->GetBackingPixmap(),
890 (GC
) m_gcBacking
, 0, 0, width
, height
,
891 (int) XLOG2DEV_2 (x
), (int) YLOG2DEV_2 (y
), TRUE
, &cache
);
892 XCopyRemote((Display
*) icon
.GetDisplay(), (Display
*) m_display
, iconPixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
894 (int) XLOG2DEV (x
), (int) YLOG2DEV (y
), FALSE
, &cache
);
896 CalcBoundingBox (x
, y
);
900 // TODO: use scaled Blit e.g. as per John Price's implementation in Contrib/Utilities
901 bool wxWindowDC::DoBlit( wxCoord xdest
, wxCoord ydest
, wxCoord width
, wxCoord height
,
902 wxDC
*source
, wxCoord xsrc
, wxCoord ysrc
, int rop
, bool useMask
,
903 wxCoord xsrcMask
, wxCoord ysrcMask
)
905 wxCHECK_MSG( Ok(), FALSE
, "invalid dc" );
907 wxWindowDC
* sourceDC
= wxDynamicCast(source
, wxWindowDC
);
909 wxASSERT_MSG( sourceDC
, "Blit source DC must be wxWindowDC or derived class." );
911 // FreeGetPixelCache();
913 // Be sure that foreground pixels (1) of the Icon will be painted with pen
914 // colour. [m_pen.SetColour()] Background pixels (0) will be painted with
915 // last selected background color. [::SetBackground]
916 if (m_pen
.Ok() && m_autoSetting
)
919 // Do bitmap scaling if necessary
921 wxBitmap
*scaledBitmap
= (wxBitmap
*) NULL
;
922 Pixmap sourcePixmap
= (Pixmap
) NULL
;
923 double scaleX
, scaleY
;
924 GetUserScale(& scaleX
, & scaleY
);
926 /* TODO: use the mask origin when drawing transparently */
927 if (xsrcMask
== -1 && ysrcMask
== -1)
929 xsrcMask
= xsrc
; ysrcMask
= ysrc
;
932 // Sorry, can't scale masks just yet
933 if (!useMask
&& (scaleX
!= 1.0 || scaleY
!= 1.0) && sourceDC
->IsKindOf(CLASSINFO(wxMemoryDC
)))
935 wxMemoryDC
* memDC
= (wxMemoryDC
*) sourceDC
;
936 wxBitmap
& bitmap
= memDC
->GetBitmap();
938 wxASSERT_MSG( (bitmap
.Ok()), "Bad source bitmap in wxWindowDC::Blit");
940 wxImage
image(bitmap
);
943 sourcePixmap
= (Pixmap
) bitmap
.GetPixmap();
947 int scaledW
= (int) (bitmap
.GetWidth() * scaleX
);
948 int scaledH
= (int) (bitmap
.GetHeight() * scaleY
);
950 image
= image
.Scale(scaledW
, scaledH
);
951 scaledBitmap
= new wxBitmap(image
.ConvertToBitmap());
952 sourcePixmap
= (Pixmap
) scaledBitmap
->GetPixmap();
956 sourcePixmap
= (Pixmap
) sourceDC
->m_pixmap
;
958 if (m_pixmap
&& sourcePixmap
)
961 int orig
= m_logicalFunction
;
963 SetLogicalFunction (rop
);
965 if (m_display
!= sourceDC
->m_display
)
967 XImage
*cache
= NULL
;
969 if (m_window
&& m_window
->GetBackingPixmap())
970 XCopyRemote((Display
*) sourceDC
->m_display
, (Display
*) m_display
,
971 (Pixmap
) sourcePixmap
, (Pixmap
) m_window
->GetBackingPixmap(),
973 source
->LogicalToDeviceX (xsrc
),
974 source
->LogicalToDeviceY (ysrc
),
975 source
->LogicalToDeviceXRel(width
),
976 source
->LogicalToDeviceYRel(height
),
977 XLOG2DEV_2 (xdest
), YLOG2DEV_2 (ydest
),
980 if ( useMask
&& source
->IsKindOf(CLASSINFO(wxMemoryDC
)) )
982 wxMemoryDC
*memDC
= (wxMemoryDC
*)source
;
983 wxBitmap
& sel
= memDC
->GetBitmap();
984 if ( sel
.Ok() && sel
.GetMask() && sel
.GetMask()->GetPixmap() )
986 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) sel
.GetMask()->GetPixmap());
987 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, XLOG2DEV (xdest
), YLOG2DEV (ydest
));
991 XCopyRemote((Display
*) sourceDC
->m_display
, (Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
992 source
->LogicalToDeviceX (xsrc
),
993 source
->LogicalToDeviceY (ysrc
),
994 source
->LogicalToDeviceXRel(width
),
995 source
->LogicalToDeviceYRel(height
),
996 XLOG2DEV (xdest
), YLOG2DEV (ydest
),
1001 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
1002 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, 0, 0);
1007 if (m_window
&& m_window
->GetBackingPixmap())
1009 // +++ MARKUS (mho@comnets.rwth-aachen): error on blitting bitmaps with depth 1
1010 if (source
->IsKindOf(CLASSINFO(wxMemoryDC
)) && ((wxMemoryDC
*) source
)->GetBitmap().GetDepth() == 1)
1012 XCopyPlane ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
1013 source
->LogicalToDeviceX (xsrc
),
1014 source
->LogicalToDeviceY (ysrc
),
1015 source
->LogicalToDeviceXRel(width
),
1016 source
->LogicalToDeviceYRel(height
),
1017 XLOG2DEV_2 (xdest
), YLOG2DEV_2 (ydest
), 1);
1021 XCopyArea ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
1022 source
->LogicalToDeviceX (xsrc
),
1023 source
->LogicalToDeviceY (ysrc
),
1024 source
->LogicalToDeviceXRel(width
),
1025 source
->LogicalToDeviceYRel(height
),
1026 XLOG2DEV_2 (xdest
), YLOG2DEV_2 (ydest
));
1029 if ( useMask
&& source
->IsKindOf(CLASSINFO(wxMemoryDC
)) )
1031 wxMemoryDC
*memDC
= (wxMemoryDC
*)source
;
1032 wxBitmap
& sel
= memDC
->GetBitmap();
1033 if ( sel
.Ok() && sel
.GetMask() && sel
.GetMask()->GetPixmap() )
1035 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) sel
.GetMask()->GetPixmap());
1036 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, XLOG2DEV (xdest
), YLOG2DEV (ydest
));
1040 // Check if we're copying from a mono bitmap
1041 if (source
->IsKindOf(CLASSINFO(wxMemoryDC
)) &&
1042 ((wxMemoryDC
*)source
)->GetBitmap().Ok() && (((wxMemoryDC
*)source
)->GetBitmap().GetDepth () == 1))
1044 XCopyPlane ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
1045 source
->LogicalToDeviceX (xsrc
),
1046 source
->LogicalToDeviceY (ysrc
),
1047 source
->LogicalToDeviceXRel(width
),
1048 source
->LogicalToDeviceYRel(height
),
1049 XLOG2DEV (xdest
), YLOG2DEV (ydest
), 1);
1053 XCopyArea ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
1054 source
->LogicalToDeviceX (xsrc
),
1055 source
->LogicalToDeviceY (ysrc
),
1056 source
->LogicalToDeviceXRel(width
),
1057 source
->LogicalToDeviceYRel(height
),
1058 XLOG2DEV (xdest
), YLOG2DEV (ydest
));
1063 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
1064 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, 0, 0);
1067 } /* Remote/local (Display*) m_display */
1068 CalcBoundingBox (xdest
, ydest
);
1069 CalcBoundingBox (xdest
+ width
, ydest
+ height
);
1071 SetLogicalFunction(orig
);
1073 if (scaledBitmap
) delete scaledBitmap
;
1077 if (scaledBitmap
) delete scaledBitmap
;
1082 void wxWindowDC::DoDrawText( const wxString
&text
, wxCoord x
, wxCoord y
)
1084 wxCHECK_RET( Ok(), "invalid dc" );
1086 // Since X draws from the baseline of the text, must add the text height
1092 slen
= strlen(text
);
1096 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1097 int direction
, descent
;
1098 XCharStruct overall_return
;
1101 (void)XTextExtents16((XFontStruct
*) pFontStruct
, (XChar2b
*)(const char*) text
, slen
, &direction
,
1102 &ascent
, &descent
, &overall_return
);
1105 (void)XTextExtents((XFontStruct
*) pFontStruct
, (char*) (const char*) text
, slen
, &direction
,
1106 &ascent
, &descent
, &overall_return
);
1108 cx
= overall_return
.width
;
1109 cy
= ascent
+ descent
;
1112 // First draw a rectangle representing the text background, if a text
1113 // background is specified
1114 if (m_textBackgroundColour
.Ok () && (m_backgroundMode
!= wxTRANSPARENT
))
1116 wxColour oldPenColour
= m_currentColour
;
1117 m_currentColour
= m_textBackgroundColour
;
1118 bool sameColour
= (oldPenColour
.Ok () && m_textBackgroundColour
.Ok () &&
1119 (oldPenColour
.Red () == m_textBackgroundColour
.Red ()) &&
1120 (oldPenColour
.Blue () == m_textBackgroundColour
.Blue ()) &&
1121 (oldPenColour
.Green () == m_textBackgroundColour
.Green ()));
1123 // This separation of the big && test required for gcc2.7/HP UX 9.02
1124 // or pixel value can be corrupted!
1125 sameColour
= (sameColour
&&
1126 (oldPenColour
.GetPixel() == m_textBackgroundColour
.GetPixel()));
1128 if (!sameColour
|| !GetOptimization())
1130 int pixel
= m_textBackgroundColour
.AllocColour(m_display
);
1131 m_currentColour
= m_textBackgroundColour
;
1133 // Set the GC to the required colour
1136 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1137 if (m_window
&& m_window
->GetBackingPixmap())
1138 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1142 m_textBackgroundColour
= oldPenColour
;
1144 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
), cx
, cy
);
1145 if (m_window
&& m_window
->GetBackingPixmap())
1146 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
1147 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
), cx
, cy
);
1150 // Now set the text foreground and draw the text
1151 if (m_textForegroundColour
.Ok ())
1153 wxColour oldPenColour
= m_currentColour
;
1154 m_currentColour
= m_textForegroundColour
;
1155 bool sameColour
= (oldPenColour
.Ok () && m_currentColour
.Ok () &&
1156 (oldPenColour
.Red () == m_currentColour
.Red ()) &&
1157 (oldPenColour
.Blue () == m_currentColour
.Blue ()) &&
1158 (oldPenColour
.Green () == m_currentColour
.Green ()) &&
1159 (oldPenColour
.GetPixel() == m_currentColour
.GetPixel()));
1161 if (!sameColour
|| !GetOptimization())
1164 if (!m_colour
) // Mono display
1166 // Unless foreground is really white, draw it in black
1167 unsigned char red
= m_textForegroundColour
.Red ();
1168 unsigned char blue
= m_textForegroundColour
.Blue ();
1169 unsigned char green
= m_textForegroundColour
.Green ();
1170 if (red
== (unsigned char) 255 && blue
== (unsigned char) 255
1171 && green
== (unsigned char) 255)
1173 m_currentColour
= *wxWHITE
;
1174 pixel
= (int) WhitePixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1175 m_currentColour
.SetPixel(pixel
);
1176 m_textForegroundColour
.SetPixel(pixel
);
1180 m_currentColour
= *wxBLACK
;
1181 pixel
= (int) BlackPixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1182 m_currentColour
.SetPixel(pixel
);
1183 m_textForegroundColour
.SetPixel(pixel
);
1188 pixel
= m_textForegroundColour
.AllocColour((Display
*) m_display
);
1189 m_currentColour
.SetPixel(pixel
);
1192 // Set the GC to the required colour
1195 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1196 if (m_window
&& m_window
->GetBackingPixmap())
1197 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1201 m_textForegroundColour
= oldPenColour
;
1204 // We need to add the ascent, not the whole height, since X draws at the
1205 // point above the descender.
1208 XDrawString16((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
) + ascent
,
1209 (XChar2b
*)(char*) (const char*) text
, slen
);
1212 XDrawString((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
) + ascent
, text
, slen
);
1214 if (m_window
&& m_window
->GetBackingPixmap()) {
1217 XDrawString16((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
1218 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
) + ascent
,
1219 (XChar2b
*)(char*) (const char*) text
, slen
);
1222 XDrawString((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
1223 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
) + ascent
, (char*) (const char*) text
, slen
);
1227 GetTextExtent (text
, &w
, &h
);
1228 CalcBoundingBox (x
+ w
, y
+ h
);
1229 CalcBoundingBox (x
, y
);
1232 void wxWindowDC::DoDrawRotatedText( const wxString
&text
, wxCoord x
, wxCoord y
, double angle
)
1236 DrawText(text
, x
, y
);
1240 wxCHECK_RET( Ok(), "invalid dc" );
1242 // Since X draws from the baseline of the text, must add the text height
1248 slen
= strlen(text
);
1252 // Calculate text extent.
1253 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1254 int direction
, descent
;
1255 XCharStruct overall_return
;
1258 (void)XTextExtents16((XFontStruct
*) pFontStruct
, (XChar2b
*)(const char*) text
, slen
, &direction
,
1259 &ascent
, &descent
, &overall_return
);
1262 (void)XTextExtents((XFontStruct
*) pFontStruct
, (char*) (const char*) text
, slen
, &direction
,
1263 &ascent
, &descent
, &overall_return
);
1265 cx
= overall_return
.width
;
1266 cy
= ascent
+ descent
;
1269 wxBitmap
src(cx
, cy
);
1271 dc
.SelectObject(src
);
1272 dc
.SetFont(GetFont());
1273 dc
.SetBackground(*wxWHITE_BRUSH
);
1274 dc
.SetBrush(*wxBLACK_BRUSH
);
1276 dc
.DrawText(text
, 0, 0);
1277 dc
.SetFont(wxNullFont
);
1279 // Calculate the size of the rotated bounding box.
1280 double dx
= cos(angle
/ 180.0 * M_PI
);
1281 double dy
= sin(angle
/ 180.0 * M_PI
);
1282 double x4
= -cy
* dy
;
1283 double y4
= cy
* dx
;
1284 double x3
= cx
* dx
;
1285 double y3
= cx
* dy
;
1286 double x2
= x3
+ x4
;
1287 double y2
= y3
+ y4
;
1291 // Create image from the source bitmap after writing the text into it.
1294 int minx
= roundmin(0, roundmin(x4
, roundmin(x2
, x3
)));
1295 int miny
= roundmin(0, roundmin(y4
, roundmin(y2
, y3
)));
1296 int maxx
= roundmax(0, roundmax(x4
, roundmax(x2
, x3
)));
1297 int maxy
= roundmax(0, roundmax(y4
, roundmax(y2
, y3
)));
1299 // This rotates counterclockwise around the top left corner.
1300 for (int rx
= minx
; rx
< maxx
; rx
++)
1302 for (int ry
= miny
; ry
< maxy
; ry
++)
1304 // transform dest coords to source coords
1305 int sx
= (int) (rx
* dx
+ ry
* dy
+ 0.5);
1306 int sy
= (int) (ry
* dx
- rx
* dy
+ 0.5);
1307 if (sx
>= 0 && sx
< cx
&& sy
>= 0 && sy
< cy
)
1309 // draw black pixels, ignore white ones (i.e. transparent b/g)
1310 if (image
.GetRed(sx
, sy
) == 0)
1312 DrawPoint((wxCoord
) (x1
+ maxx
- rx
), (wxCoord
) (cy
+ y1
- ry
));
1317 //DrawPoint(x1 + maxx - rx, cy + y1 + maxy - ry);
1324 // First draw a rectangle representing the text background, if a text
1325 // background is specified
1326 if (m_textBackgroundColour
.Ok () && (m_backgroundMode
!= wxTRANSPARENT
))
1328 wxColour oldPenColour
= m_currentColour
;
1329 m_currentColour
= m_textBackgroundColour
;
1330 bool sameColour
= (oldPenColour
.Ok () && m_textBackgroundColour
.Ok () &&
1331 (oldPenColour
.Red () == m_textBackgroundColour
.Red ()) &&
1332 (oldPenColour
.Blue () == m_textBackgroundColour
.Blue ()) &&
1333 (oldPenColour
.Green () == m_textBackgroundColour
.Green ()));
1335 // This separation of the big && test required for gcc2.7/HP UX 9.02
1336 // or pixel value can be corrupted!
1337 sameColour
= (sameColour
&&
1338 (oldPenColour
.GetPixel() == m_textBackgroundColour
.GetPixel()));
1340 if (!sameColour
|| !GetOptimization())
1342 int pixel
= m_textBackgroundColour
.AllocColour(m_display
);
1343 m_currentColour
= m_textBackgroundColour
;
1345 // Set the GC to the required colour
1348 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1349 if (m_window
&& m_window
->GetBackingPixmap())
1350 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1354 m_textBackgroundColour
= oldPenColour
;
1356 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
), cx
, cy
);
1357 if (m_window
&& m_window
->GetBackingPixmap())
1358 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
1359 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
), cx
, cy
);
1364 // XXX use pixmap size
1365 GetTextExtent (text
, &w
, &h
);
1366 CalcBoundingBox (x
+ w
, y
+ h
);
1367 CalcBoundingBox (x
, y
);
1370 bool wxWindowDC::CanGetTextExtent() const
1375 void wxWindowDC::DoGetTextExtent( const wxString
&string
, wxCoord
*width
, wxCoord
*height
,
1376 wxCoord
*descent
, wxCoord
*externalLeading
,
1377 wxFont
*font
) const
1379 wxCHECK_RET( Ok(), "invalid dc" );
1381 wxFont
* theFont
= font
;
1383 theFont
= (wxFont
*)&m_font
; // const_cast
1387 // TODO: this should be an error log function
1388 wxFAIL_MSG("set a valid font before calling GetTextExtent!");
1390 if (width
) *width
= -1;
1391 if (height
) *height
= -1;
1395 WXFontStructPtr pFontStruct
= theFont
->GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1397 int direction
, ascent
, descent2
;
1398 XCharStruct overall
;
1403 slen
= str16len(string
);
1406 slen
= strlen(string
);
1410 XTextExtents16((XFontStruct
*) pFontStruct
, (XChar2b
*) (char*) (const char*) string
, slen
, &direction
,
1411 &ascent
, &descent2
, &overall
);
1414 XTextExtents((XFontStruct
*) pFontStruct
, (char*) (const char*) string
, slen
, &direction
,
1415 &ascent
, &descent2
, &overall
);
1417 if (width
) *width
= XDEV2LOGREL (overall
.width
);
1418 if (height
) *height
= YDEV2LOGREL (ascent
+ descent2
);
1420 *descent
= descent2
;
1421 if (externalLeading
)
1422 *externalLeading
= 0;
1425 wxCoord
wxWindowDC::GetCharWidth() const
1427 wxCHECK_MSG( Ok(), 0, "invalid dc" );
1428 wxCHECK_MSG( m_font
.Ok(), 0, "invalid font" );
1430 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
* m_logicalScaleY
, m_display
);
1432 int direction
, ascent
, descent
;
1433 XCharStruct overall
;
1434 XTextExtents ((XFontStruct
*) pFontStruct
, "x", 1, &direction
, &ascent
,
1435 &descent
, &overall
);
1436 return XDEV2LOGREL(overall
.width
);
1439 wxCoord
wxWindowDC::GetCharHeight() const
1441 wxCHECK_MSG( Ok(), 0, "invalid dc" );
1442 wxCHECK_MSG( m_font
.Ok(), 0, "invalid font" );
1444 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1446 int direction
, ascent
, descent
;
1447 XCharStruct overall
;
1448 XTextExtents ((XFontStruct
*) pFontStruct
, "x", 1, &direction
, &ascent
,
1449 &descent
, &overall
);
1450 // return XDEV2LOGREL(overall.ascent + overall.descent);
1451 return XDEV2LOGREL(ascent
+ descent
);
1454 void wxWindowDC::Clear()
1456 wxCHECK_RET( Ok(), "invalid dc" );
1461 m_window
->GetSize(&w
, &h
);
1463 if (m_window
&& m_window
->GetBackingPixmap())
1465 w
= m_window
->GetPixmapWidth();
1466 h
= m_window
->GetPixmapHeight();
1471 if (this->IsKindOf(CLASSINFO(wxMemoryDC
)))
1473 wxMemoryDC
* memDC
= (wxMemoryDC
*) this;
1474 w
= memDC
->GetBitmap().GetWidth();
1475 h
= memDC
->GetBitmap().GetHeight();
1481 wxBrush saveBrush
= m_brush
;
1482 SetBrush (m_backgroundBrush
);
1484 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, 0, 0, w
, h
);
1486 if (m_window
&& m_window
->GetBackingPixmap())
1487 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, 0, 0, w
, h
);
1489 m_brush
= saveBrush
;
1492 void wxWindowDC::Clear(const wxRect
& rect
)
1494 wxCHECK_RET( Ok(), "invalid dc" );
1496 int x
= rect
.x
; int y
= rect
.y
;
1497 int w
= rect
.width
; int h
= rect
.height
;
1499 wxBrush saveBrush
= m_brush
;
1500 SetBrush (m_backgroundBrush
);
1502 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, x
, y
, w
, h
);
1504 if (m_window
&& m_window
->GetBackingPixmap())
1505 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, x
, y
, w
, h
);
1507 m_brush
= saveBrush
;
1510 void wxWindowDC::SetFont( const wxFont
&font
)
1512 wxCHECK_RET( Ok(), "invalid dc" );
1518 if ((m_oldFont
!= (WXFont
) 0) && ((wxCoord
) m_oldFont
!= -1))
1520 XSetFont ((Display
*) m_display
, (GC
) m_gc
, (Font
) m_oldFont
);
1522 if (m_window
&& m_window
->GetBackingPixmap())
1523 XSetFont ((Display
*) m_display
,(GC
) m_gcBacking
, (Font
) m_oldFont
);
1528 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1530 Font fontId
= ((XFontStruct
*)pFontStruct
)->fid
;
1531 XSetFont ((Display
*) m_display
, (GC
) m_gc
, fontId
);
1533 if (m_window
&& m_window
->GetBackingPixmap())
1534 XSetFont ((Display
*) m_display
,(GC
) m_gcBacking
, fontId
);
1537 void wxWindowDC::SetPen( const wxPen
&pen
)
1539 wxCHECK_RET( Ok(), "invalid dc" );
1545 wxBitmap oldStipple
= m_currentStipple
;
1546 int oldStyle
= m_currentStyle
;
1547 int oldFill
= m_currentFill
;
1548 int old_pen_width
= m_currentPenWidth
;
1549 int old_pen_join
= m_currentPenJoin
;
1550 int old_pen_cap
= m_currentPenCap
;
1551 int old_pen_nb_dash
= m_currentPenDashCount
;
1552 wxMOTIFDash
*old_pen_dash
= m_currentPenDash
;
1554 wxColour oldPenColour
= m_currentColour
;
1555 m_currentColour
= m_pen
.GetColour ();
1556 m_currentStyle
= m_pen
.GetStyle ();
1557 m_currentFill
= m_pen
.GetStyle (); // TODO?
1558 m_currentPenWidth
= m_pen
.GetWidth ();
1559 m_currentPenJoin
= m_pen
.GetJoin ();
1560 m_currentPenCap
= m_pen
.GetCap ();
1561 m_currentPenDashCount
= m_pen
.GetDashCount();
1562 m_currentPenDash
= (wxMOTIFDash
*)m_pen
.GetDash();
1564 if (m_currentStyle
== wxSTIPPLE
)
1565 m_currentStipple
= * m_pen
.GetStipple ();
1567 bool sameStyle
= (oldStyle
== m_currentStyle
&&
1568 oldFill
== m_currentFill
&&
1569 old_pen_join
== m_currentPenJoin
&&
1570 old_pen_cap
== m_currentPenCap
&&
1571 old_pen_nb_dash
== m_currentPenDashCount
&&
1572 old_pen_dash
== m_currentPenDash
&&
1573 old_pen_width
== m_currentPenWidth
);
1575 bool sameColour
= (oldPenColour
.Ok () &&
1576 (oldPenColour
.Red () == m_currentColour
.Red ()) &&
1577 (oldPenColour
.Blue () == m_currentColour
.Blue ()) &&
1578 (oldPenColour
.Green () == m_currentColour
.Green ()) &&
1579 (oldPenColour
.GetPixel() == m_currentColour
.GetPixel()));
1581 if (!sameStyle
|| !GetOptimization())
1583 int scaled_width
= (int) XLOG2DEVREL (m_pen
.GetWidth ());
1584 if (scaled_width
< 0)
1590 static const wxMOTIFDash dotted
[] = {2, 5};
1591 static const wxMOTIFDash short_dashed
[] = {4, 4};
1592 static const wxMOTIFDash long_dashed
[] = {4, 8};
1593 static const wxMOTIFDash dotted_dashed
[] = {6, 6, 2, 6};
1595 // We express dash pattern in pen width unit, so we are
1596 // independent of zoom factor and so on...
1598 const wxMOTIFDash
*req_dash
;
1600 switch (m_pen
.GetStyle ())
1603 req_nb_dash
= m_currentPenDashCount
;
1604 req_dash
= m_currentPenDash
;
1605 style
= LineOnOffDash
;
1610 style
= LineOnOffDash
;
1614 req_dash
= short_dashed
;
1615 style
= LineOnOffDash
;
1619 req_dash
= long_dashed
;
1620 style
= LineOnOffDash
;
1624 req_dash
= dotted_dashed
;
1625 style
= LineOnOffDash
;
1632 req_dash
= (wxMOTIFDash
*)NULL
;
1636 if (req_dash
&& req_nb_dash
)
1638 wxMOTIFDash
*real_req_dash
= new wxMOTIFDash
[req_nb_dash
];
1641 int factor
= scaled_width
== 0 ? 1 : scaled_width
;
1642 for (int i
= 0; i
< req_nb_dash
; i
++)
1643 real_req_dash
[i
] = req_dash
[i
] * factor
;
1644 XSetDashes ((Display
*) m_display
, (GC
) m_gc
, 0, real_req_dash
, req_nb_dash
);
1646 if (m_window
&& m_window
->GetBackingPixmap())
1647 XSetDashes ((Display
*) m_display
,(GC
) m_gcBacking
, 0, real_req_dash
, req_nb_dash
);
1648 delete[]real_req_dash
;
1652 // No Memory. We use non-scaled dash pattern...
1653 XSetDashes ((Display
*) m_display
, (GC
) m_gc
, 0, req_dash
, req_nb_dash
);
1655 if (m_window
&& m_window
->GetBackingPixmap())
1656 XSetDashes ((Display
*) m_display
,(GC
) m_gcBacking
, 0, req_dash
, req_nb_dash
);
1660 switch (m_pen
.GetCap ())
1662 case wxCAP_PROJECTING
:
1663 cap
= CapProjecting
;
1670 cap
= (scaled_width
<= 1) ? CapNotLast
: CapRound
;
1674 switch (m_pen
.GetJoin ())
1688 XSetLineAttributes ((Display
*) m_display
, (GC
) m_gc
, scaled_width
, style
, cap
, join
);
1690 if (m_window
&& m_window
->GetBackingPixmap())
1691 XSetLineAttributes ((Display
*) m_display
,(GC
) m_gcBacking
, scaled_width
, style
, cap
, join
);
1694 if (IS_HATCH(m_currentFill
) && ((m_currentFill
!= oldFill
) || !GetOptimization()))
1698 oldStipple
= wxNullBitmap
; // For later reset!!
1700 switch (m_currentFill
)
1702 case wxBDIAGONAL_HATCH
:
1703 if (bdiag
== (Pixmap
) 0)
1704 bdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1705 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1706 bdiag_bits
, bdiag_width
, bdiag_height
);
1709 case wxFDIAGONAL_HATCH
:
1710 if (fdiag
== (Pixmap
) 0)
1711 fdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1712 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1713 fdiag_bits
, fdiag_width
, fdiag_height
);
1717 if (cross
== (Pixmap
) 0)
1718 cross
= XCreateBitmapFromData ((Display
*) m_display
,
1719 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1720 cross_bits
, cross_width
, cross_height
);
1723 case wxHORIZONTAL_HATCH
:
1724 if (horiz
== (Pixmap
) 0)
1725 horiz
= XCreateBitmapFromData ((Display
*) m_display
,
1726 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1727 horiz_bits
, horiz_width
, horiz_height
);
1730 case wxVERTICAL_HATCH
:
1731 if (verti
== (Pixmap
) 0)
1732 verti
= XCreateBitmapFromData ((Display
*) m_display
,
1733 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1734 verti_bits
, verti_width
, verti_height
);
1737 case wxCROSSDIAG_HATCH
:
1739 if (cdiag
== (Pixmap
) 0)
1740 cdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1741 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1742 cdiag_bits
, cdiag_width
, cdiag_height
);
1746 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, myStipple
);
1748 if (m_window
&& m_window
->GetBackingPixmap())
1749 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, myStipple
);
1751 else if (m_currentStipple
.Ok()
1752 && ((m_currentStipple
!= oldStipple
) || !GetOptimization()))
1754 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) m_currentStipple
.GetPixmap());
1756 if (m_window
&& m_window
->GetBackingPixmap())
1757 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, (Pixmap
) m_currentStipple
.GetPixmap());
1760 if ((m_currentFill
!= oldFill
) || !GetOptimization())
1764 if (m_currentFill
== wxSTIPPLE
)
1765 fill_style
= FillStippled
;
1766 else if (IS_HATCH (m_currentFill
))
1767 fill_style
= FillStippled
;
1769 fill_style
= FillSolid
;
1770 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, fill_style
);
1771 if (m_window
&& m_window
->GetBackingPixmap())
1772 XSetFillStyle ((Display
*) m_display
,(GC
) m_gcBacking
, fill_style
);
1775 // must test m_logicalFunction, because it involves background!
1776 if (!sameColour
|| !GetOptimization()
1777 || ((m_logicalFunction
== wxXOR
) || (m_autoSetting
& 0x2)))
1780 if (m_pen
.GetStyle () == wxTRANSPARENT
)
1781 pixel
= m_backgroundPixel
;
1784 unsigned char red
= m_pen
.GetColour ().Red ();
1785 unsigned char blue
= m_pen
.GetColour ().Blue ();
1786 unsigned char green
= m_pen
.GetColour ().Green ();
1787 if (red
== (unsigned char) 255 && blue
== (unsigned char) 255
1788 && green
== (unsigned char) 255)
1790 pixel
= (int) WhitePixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1791 m_currentColour
= *wxWHITE
;
1792 m_pen
.GetColour().SetPixel(pixel
);
1793 m_currentColour
.SetPixel(pixel
);
1797 pixel
= (int) BlackPixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1798 m_currentColour
= *wxBLACK
;
1799 m_pen
.GetColour().SetPixel(pixel
);
1804 pixel
= m_pen
.GetColour ().AllocColour(m_display
);
1805 m_currentColour
.SetPixel(pixel
);
1808 // Finally, set the GC to the required colour
1811 if (m_logicalFunction
== wxXOR
)
1814 XGetGCValues ((Display
*) m_display
, (GC
) m_gc
, GCBackground
, &values
);
1815 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
^ values
.background
);
1816 if (m_window
&& m_window
->GetBackingPixmap())
1817 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
^ values
.background
);
1821 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1822 if (m_window
&& m_window
->GetBackingPixmap())
1823 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1828 m_pen
.GetColour().SetPixel(oldPenColour
.GetPixel());
1833 void wxWindowDC::SetBrush( const wxBrush
&brush
)
1835 wxCHECK_RET( Ok(), "invalid dc" );
1839 if (!m_brush
.Ok() || m_brush
.GetStyle () == wxTRANSPARENT
)
1842 int oldFill
= m_currentFill
;
1843 wxBitmap oldStipple
= m_currentStipple
;
1845 m_autoSetting
|= 0x1;
1847 m_currentFill
= m_brush
.GetStyle ();
1848 if (m_currentFill
== wxSTIPPLE
)
1849 m_currentStipple
= * m_brush
.GetStipple ();
1851 wxColour
oldBrushColour(m_currentColour
);
1852 m_currentColour
= m_brush
.GetColour ();
1854 bool sameColour
= (oldBrushColour
.Ok () &&
1855 (oldBrushColour
.Red () == m_currentColour
.Red ()) &&
1856 (oldBrushColour
.Blue () == m_currentColour
.Blue ()) &&
1857 (oldBrushColour
.Green () == m_currentColour
.Green ()) &&
1858 (oldBrushColour
.GetPixel() == m_currentColour
.GetPixel()));
1860 if ((oldFill
!= m_brush
.GetStyle ()) || !GetOptimization())
1862 switch (brush
.GetStyle ())
1866 case wxBDIAGONAL_HATCH
:
1867 case wxCROSSDIAG_HATCH
:
1868 case wxFDIAGONAL_HATCH
:
1870 case wxHORIZONTAL_HATCH
:
1871 case wxVERTICAL_HATCH
:
1874 // Chris Breeze 23/07/97: use background mode to determine whether
1875 // fill style should be solid or transparent
1876 int style
= (m_backgroundMode
== wxSOLID
? FillOpaqueStippled
: FillStippled
);
1877 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, style
);
1878 if (m_window
&& m_window
->GetBackingPixmap())
1879 XSetFillStyle ((Display
*) m_display
,(GC
) m_gcBacking
, style
);
1884 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, FillSolid
);
1885 if (m_window
&& m_window
->GetBackingPixmap())
1886 XSetFillStyle ((Display
*) m_display
,(GC
) m_gcBacking
, FillSolid
);
1890 if (IS_HATCH(m_currentFill
) && ((m_currentFill
!= oldFill
) || !GetOptimization()))
1894 switch (m_currentFill
)
1896 case wxBDIAGONAL_HATCH
:
1897 if (bdiag
== (Pixmap
) 0)
1898 bdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1899 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1900 bdiag_bits
, bdiag_width
, bdiag_height
);
1903 case wxFDIAGONAL_HATCH
:
1904 if (fdiag
== (Pixmap
) 0)
1905 fdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1906 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1907 fdiag_bits
, fdiag_width
, fdiag_height
);
1911 if (cross
== (Pixmap
) 0)
1912 cross
= XCreateBitmapFromData ((Display
*) m_display
,
1913 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1914 cross_bits
, cross_width
, cross_height
);
1917 case wxHORIZONTAL_HATCH
:
1918 if (horiz
== (Pixmap
) 0)
1919 horiz
= XCreateBitmapFromData ((Display
*) m_display
,
1920 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1921 horiz_bits
, horiz_width
, horiz_height
);
1924 case wxVERTICAL_HATCH
:
1925 if (verti
== (Pixmap
) 0)
1926 verti
= XCreateBitmapFromData ((Display
*) m_display
,
1927 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1928 verti_bits
, verti_width
, verti_height
);
1931 case wxCROSSDIAG_HATCH
:
1933 if (cdiag
== (Pixmap
) 0)
1934 cdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1935 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1936 cdiag_bits
, cdiag_width
, cdiag_height
);
1940 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, myStipple
);
1942 if (m_window
&& m_window
->GetBackingPixmap())
1943 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, myStipple
);
1945 // X can forget the stipple value when resizing a window (apparently)
1946 // so always set the stipple.
1947 else if (m_currentStipple
.Ok()) // && m_currentStipple != oldStipple)
1949 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) m_currentStipple
.GetPixmap());
1950 if (m_window
&& m_window
->GetBackingPixmap())
1951 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, (Pixmap
) m_currentStipple
.GetPixmap());
1954 // must test m_logicalFunction, because it involves background!
1955 if (!sameColour
|| !GetOptimization() || m_logicalFunction
== wxXOR
)
1960 // Policy - on a monochrome screen, all brushes are white,
1961 // except when they're REALLY black!!!
1962 unsigned char red
= m_brush
.GetColour ().Red ();
1963 unsigned char blue
= m_brush
.GetColour ().Blue ();
1964 unsigned char green
= m_brush
.GetColour ().Green ();
1966 if (red
== (unsigned char) 0 && blue
== (unsigned char) 0
1967 && green
== (unsigned char) 0)
1969 pixel
= (int) BlackPixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1970 m_currentColour
= *wxBLACK
;
1971 m_brush
.GetColour().SetPixel(pixel
);
1972 m_currentColour
.SetPixel(pixel
);
1976 pixel
= (int) WhitePixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1977 m_currentColour
= *wxWHITE
;
1978 m_brush
.GetColour().SetPixel(pixel
);
1979 m_currentColour
.SetPixel(pixel
);
1982 // N.B. comment out the above line and uncomment the following lines
1983 // if you want non-white colours to be black on a monochrome display.
1985 if (red == (unsigned char )255 && blue == (unsigned char)255
1986 && green == (unsigned char)255)
1987 pixel = (int)WhitePixel((Display*) m_display, DefaultScreen((Display*) m_display));
1989 pixel = (int)BlackPixel((Display*) m_display, DefaultScreen((Display*) m_display));
1992 else if (m_brush
.GetStyle () != wxTRANSPARENT
)
1994 pixel
= m_brush
.GetColour().AllocColour(m_display
);
1995 m_currentColour
.SetPixel(pixel
);
1999 // Finally, set the GC to the required colour
2000 if (m_logicalFunction
== wxXOR
)
2003 XGetGCValues ((Display
*) m_display
, (GC
) m_gc
, GCBackground
, &values
);
2004 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
^ values
.background
);
2005 if (m_window
&& m_window
->GetBackingPixmap())
2006 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
^ values
.background
);
2010 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
2011 if (m_window
&& m_window
->GetBackingPixmap())
2012 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
2017 m_brush
.GetColour().SetPixel(oldBrushColour
.GetPixel());
2020 void wxWindowDC::SetBackground( const wxBrush
&brush
)
2022 wxCHECK_RET( Ok(), "invalid dc" );
2024 m_backgroundBrush
= brush
;
2026 if (!m_backgroundBrush
.Ok())
2029 int pixel
= m_backgroundBrush
.GetColour().AllocColour(m_display
);
2031 // New behaviour, 10/2/99: setting the background brush of a DC
2032 // doesn't affect the window background colour.
2034 // XSetWindowBackground doesn't work for non-Window pixmaps
2035 if (!this->IsKindOf(CLASSINFO(wxMemoryDC)))
2036 XSetWindowBackground ((Display*) m_display, (Pixmap) m_pixmap, pixel);
2039 // Necessary for ::DrawIcon, which use fg/bg pixel or the GC.
2040 // And Blit,... (Any fct that use XCopyPlane, in fact.)
2041 XSetBackground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
2042 if (m_window
&& m_window
->GetBackingPixmap())
2043 XSetBackground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
2046 void wxWindowDC::SetLogicalFunction( int function
)
2048 wxCHECK_RET( Ok(), "invalid dc" );
2053 if (m_logicalFunction
== function
)
2059 x_function
= GXclear
;
2065 x_function
= GXinvert
;
2068 x_function
= GXorReverse
;
2071 x_function
= GXandReverse
;
2080 x_function
= GXandInverted
;
2083 x_function
= GXnoop
;
2089 x_function
= GXequiv
;
2092 x_function
= GXcopyInverted
;
2095 x_function
= GXorInverted
;
2098 x_function
= GXnand
;
2105 x_function
= GXcopy
;
2109 XSetFunction((Display
*) m_display
, (GC
) m_gc
, x_function
);
2110 if (m_window
&& m_window
->GetBackingPixmap())
2111 XSetFunction((Display
*) m_display
, (GC
) m_gcBacking
, x_function
);
2113 if ((m_logicalFunction
== wxXOR
) != (function
== wxXOR
))
2114 /* MATTHEW: [9] Need to redo pen simply */
2115 m_autoSetting
|= 0x2;
2117 m_logicalFunction
= function
;
2121 void wxWindowDC::SetTextForeground( const wxColour
&col
)
2123 wxCHECK_RET( Ok(), "invalid dc" );
2125 if (m_textForegroundColour
== col
)
2128 m_textForegroundColour
= col
;
2132 void wxWindowDC::SetTextBackground( const wxColour
&col
)
2134 wxCHECK_RET( Ok(), "invalid dc" );
2136 if (m_textBackgroundColour
== col
)
2139 m_textBackgroundColour
= col
;
2140 if (!m_textBackgroundColour
.Ok())
2144 void wxWindowDC::SetBackgroundMode( int mode
)
2146 m_backgroundMode
= mode
;
2149 void wxWindowDC::SetPalette( const wxPalette
& palette
)
2154 /* Use GetXColormap */
2155 XSetWindowColormap ((Display
*) m_display
, (Window
) m_window
->GetXWindow(),
2156 (Colormap
) palette
.GetXColormap());
2158 /* Use wxGetMainColormap */
2159 XSetWindowColormap ((Display
*) m_display
, (Window
) m_window
->GetXWindow(),
2160 (Colormap
) wxTheApp
->GetMainColormap(m_display
));
2165 void wxWindowDC::SetDCClipping()
2167 // m_userRegion is the region set by calling SetClippingRegion
2169 if (m_currentRegion
)
2170 XDestroyRegion ((Region
) m_currentRegion
);
2172 // We need to take into account
2173 // clipping imposed on a window by a repaint.
2174 // We'll combine it with the user region. But for now,
2175 // just use the currently-defined user clipping region.
2176 if (m_userRegion
|| (m_window
&& m_window
->GetUpdateRegion().Ok()) )
2177 m_currentRegion
= (WXRegion
) XCreateRegion ();
2179 m_currentRegion
= (WXRegion
) NULL
;
2181 if ((m_window
&& m_window
->GetUpdateRegion().Ok()) && m_userRegion
)
2182 XIntersectRegion ((Region
) m_window
->GetUpdateRegion().GetXRegion(), (Region
) m_userRegion
, (Region
) m_currentRegion
);
2183 else if (m_userRegion
)
2184 XIntersectRegion ((Region
) m_userRegion
, (Region
) m_userRegion
, (Region
) m_currentRegion
);
2185 else if (m_window
&& m_window
->GetUpdateRegion().Ok())
2186 XIntersectRegion ((Region
) m_window
->GetUpdateRegion().GetXRegion(), (Region
) m_window
->GetUpdateRegion().GetXRegion(),
2187 (Region
) m_currentRegion
);
2189 if (m_currentRegion
)
2191 XSetRegion ((Display
*) m_display
, (GC
) m_gc
, (Region
) m_currentRegion
);
2195 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
2200 void wxWindowDC::DoSetClippingRegion( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
2202 wxDC::DoSetClippingRegion( x
, y
, width
, height
);
2205 XDestroyRegion ((Region
) m_userRegion
);
2206 m_userRegion
= (WXRegion
) XCreateRegion ();
2210 r
.width
= XLOG2DEVREL(width
);
2211 r
.height
= YLOG2DEVREL(height
);
2212 XUnionRectWithRegion (&r
, (Region
) m_userRegion
, (Region
) m_userRegion
);
2216 // Needs to work differently for Pixmap: without this,
2217 // there's a nasty (Display*) m_display bug. 8/12/94
2218 if (m_window
&& m_window
->GetBackingPixmap())
2220 XRectangle rects
[1];
2221 rects
[0].x
= XLOG2DEV_2(x
);
2222 rects
[0].y
= YLOG2DEV_2(y
);
2223 rects
[0].width
= XLOG2DEVREL(width
);
2224 rects
[0].height
= YLOG2DEVREL(height
);
2225 XSetClipRectangles((Display
*) m_display
, (GC
) m_gcBacking
, 0, 0, rects
, 1, Unsorted
);
2229 void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion
& region
)
2231 wxRect box
= region
.GetBox();
2233 wxDC::DoSetClippingRegion( box
.x
, box
.y
, box
.width
, box
.height
);
2236 XDestroyRegion ((Region
) m_userRegion
);
2237 m_userRegion
= (WXRegion
) XCreateRegion ();
2239 XUnionRegion((Region
) m_userRegion
, (Region
) region
.GetXRegion(), (Region
) m_userRegion
);
2243 // Needs to work differently for Pixmap: without this,
2244 // there's a nasty (Display*) m_display bug. 8/12/94
2245 if (m_window
&& m_window
->GetBackingPixmap())
2247 XRectangle rects
[1];
2248 rects
[0].x
= XLOG2DEV_2(box
.x
);
2249 rects
[0].y
= YLOG2DEV_2(box
.y
);
2250 rects
[0].width
= XLOG2DEVREL(box
.width
);
2251 rects
[0].height
= YLOG2DEVREL(box
.height
);
2252 XSetClipRectangles((Display
*) m_display
, (GC
) m_gcBacking
, 0, 0, rects
, 1, Unsorted
);
2257 void wxWindowDC::DestroyClippingRegion()
2259 wxDC::DestroyClippingRegion();
2262 XDestroyRegion ((Region
) m_userRegion
);
2263 m_userRegion
= NULL
;
2268 gc_val
.clip_mask
= None
;
2269 if (m_window
&& m_window
->GetBackingPixmap())
2270 XChangeGC((Display
*) m_display
, (GC
) m_gcBacking
, GCClipMask
, &gc_val
);
2273 // Resolution in pixels per logical inch
2274 wxSize
wxWindowDC::GetPPI() const
2276 return wxSize(100, 100);
2279 int wxWindowDC::GetDepth() const
2288 // ----------------------------------------------------------------------------
2290 // ----------------------------------------------------------------------------
2292 wxPaintDC::wxPaintDC(wxWindow
* win
) : wxWindowDC(win
)
2294 wxRegion
* region
= NULL
;
2296 // Combine all the update rects into a region
2297 const wxRectList
& updateRects(win
->GetUpdateRects());
2298 if ( updateRects
.GetCount() != 0 )
2300 for ( wxRectList::Node
*node
= updateRects
.GetFirst();
2302 node
= node
->GetNext() )
2304 wxRect
* rect
= node
->GetData();
2307 region
= new wxRegion(*rect
);
2309 // TODO: is this correct? In SetDCClipping above,
2310 // XIntersectRegion is used to combine paint and user
2311 // regions. XIntersectRegion appears to work in that case...
2312 region
->Union(*rect
);
2318 win
->GetClientSize(&cw
, &ch
);
2319 region
= new wxRegion(wxRect(0, 0, cw
, ch
));
2322 win
->SetUpdateRegion(*region
);
2324 wxRegion
& theRegion(win
->GetUpdateRegion());
2325 theRegion
.SetRects(updateRects
); // We also store in terms of rects, for iteration to work.
2327 // Set the clipping region. Any user-defined region will be combined with this
2328 // one in SetDCClipping.
2329 XSetRegion ((Display
*) m_display
, (GC
) m_gc
, (Region
) region
->GetXRegion());
2334 wxPaintDC::~wxPaintDC()
2336 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
2338 m_window
->ClearUpdateRegion();
2341 // ----------------------------------------------------------------------------
2342 // private functions
2343 // ----------------------------------------------------------------------------
2346 Used when copying between drawables on different (Display*) m_displays. Not
2347 very fast, but better than giving up.
2350 static void XCopyRemote(Display
*src_display
, Display
*dest_display
,
2351 Drawable src
, Drawable dest
,
2354 unsigned int w
, unsigned int h
,
2355 int destx
, int desty
,
2356 bool more
, XImage
**cache
)
2358 XImage
*image
, *destimage
;
2359 Colormap destcm
, srccm
;
2360 static const int CACHE_SIZE
= 256;
2363 unsigned long cachesrc
[CACHE_SIZE
], cachedest
[CACHE_SIZE
];
2364 int k
, cache_pos
, all_cache
;
2366 if (!cache
|| !*cache
)
2367 image
= XGetImage(src_display
, src
, srcx
, srcy
, w
, h
, AllPlanes
, ZPixmap
);
2371 destimage
= XGetImage(dest_display
, dest
, destx
, desty
, w
, h
, AllPlanes
, ZPixmap
);
2373 srccm
= (Colormap
) wxTheApp
->GetMainColormap((WXDisplay
*) src_display
);
2374 destcm
= (Colormap
) wxTheApp
->GetMainColormap((WXDisplay
*) dest_display
);
2379 for (i
= 0; i
< w
; i
++)
2380 for (j
= 0; j
< h
; j
++) {
2381 unsigned long pixel
;
2384 pixel
= XGetPixel(image
, i
, j
);
2385 for (k
= cache_pos
; k
--; )
2386 if (cachesrc
[k
] == pixel
) {
2387 pixel
= cachedest
[k
];
2391 for (k
= CACHE_SIZE
; k
-- > cache_pos
; )
2392 if (cachesrc
[k
] == pixel
) {
2393 pixel
= cachedest
[k
];
2397 cachesrc
[cache_pos
] = xcol
.pixel
= pixel
;
2398 XQueryColor(src_display
, srccm
, &xcol
);
2399 if (!XAllocColor(dest_display
, destcm
, &xcol
))
2401 cachedest
[cache_pos
] = pixel
= xcol
.pixel
;
2403 if (++cache_pos
>= CACHE_SIZE
) {
2409 XPutPixel(destimage
, i
, j
, pixel
);
2412 XPutImage(dest_display
, dest
, destgc
, destimage
, 0, 0, destx
, desty
, w
, h
);
2413 XDestroyImage(destimage
);
2418 XDestroyImage(image
);
2423 /* Helper function for 16-bit fonts */
2424 static int str16len(const char *s
)
2428 while (s
[0] && s
[1]) {