1///////////////////////////////////////////////////////////////////////////// 2// Name: src/x11/dcclient.cpp 3// Purpose: wxClientDC class 4// Author: Julian Smart, Robert Roebling 5// Modified by: 6// Created: 01/02/97 7// RCS-ID: $Id: dcclient.cpp 44576 2007-02-27 14:06:58Z VZ $ 8// Copyright: (c) Julian Smart, Robert Roebling 9// Licence: wxWindows licence 10///////////////////////////////////////////////////////////////////////////// 11 12// for compilers that support precompilation, includes "wx.h". 13#include "wx/wxprec.h" 14 15#include "wx/dcclient.h" 16 17#ifndef WX_PRECOMP 18 #include "wx/app.h" 19 #include "wx/window.h" 20 #include "wx/dcmemory.h" 21 #include "wx/math.h" 22 #include "wx/image.h" 23 #include "wx/module.h" 24#endif 25 26#include "wx/fontutil.h" 27 28#include "wx/x11/private.h" 29 30#if wxUSE_UNICODE 31#include "glib.h" 32#include "pango/pangox.h" 33#ifdef HAVE_PANGO_XFT 34 #include "pango/pangoxft.h" 35#endif 36 37#include "pango_x.cpp" 38#endif 39 40//----------------------------------------------------------------------------- 41// local defines 42//----------------------------------------------------------------------------- 43 44#define USE_PAINT_REGION 1 45 46//----------------------------------------------------------------------------- 47// local data 48//----------------------------------------------------------------------------- 49 50#include "bdiag.xbm" 51#include "fdiag.xbm" 52#include "cdiag.xbm" 53#include "horiz.xbm" 54#include "verti.xbm" 55#include "cross.xbm" 56#define num_hatches 6 57 58#define IS_15_PIX_HATCH(s) ((s)==wxCROSSDIAG_HATCH || (s)==wxHORIZONTAL_HATCH || (s)==wxVERTICAL_HATCH) 59#define IS_16_PIX_HATCH(s) ((s)!=wxCROSSDIAG_HATCH && (s)!=wxHORIZONTAL_HATCH && (s)!=wxVERTICAL_HATCH) 60 61static Pixmap hatches[num_hatches]; 62static Pixmap *hatch_bitmap = (Pixmap *) NULL; 63 64//----------------------------------------------------------------------------- 65// constants 66//----------------------------------------------------------------------------- 67 68const double RAD2DEG = 180.0 / M_PI; 69 70// ---------------------------------------------------------------------------- 71// private functions 72// ---------------------------------------------------------------------------- 73 74static inline double dmax(double a, double b) { return a > b ? a : b; } 75static inline double dmin(double a, double b) { return a < b ? a : b; } 76 77static inline double DegToRad(double deg) { return (deg * M_PI) / 180.0; } 78 79//----------------------------------------------------------------------------- 80// Implement Pool of Graphic contexts. Creating them takes too much time. 81//----------------------------------------------------------------------------- 82 83#define GC_POOL_SIZE 200 84 85enum wxPoolGCType 86{ 87 wxGC_ERROR = 0, 88 wxTEXT_MONO, 89 wxBG_MONO, 90 wxPEN_MONO, 91 wxBRUSH_MONO, 92 wxTEXT_COLOUR, 93 wxBG_COLOUR, 94 wxPEN_COLOUR, 95 wxBRUSH_COLOUR, 96 wxTEXT_SCREEN, 97 wxBG_SCREEN, 98 wxPEN_SCREEN, 99 wxBRUSH_SCREEN 100}; 101 102struct wxGC 103{ 104 GC m_gc; 105 wxPoolGCType m_type; 106 bool m_used; 107}; 108 109static wxGC wxGCPool[GC_POOL_SIZE]; 110 111static void wxInitGCPool() 112{ 113 memset( wxGCPool, 0, GC_POOL_SIZE*sizeof(wxGC) ); 114} 115 116static void wxCleanUpGCPool() 117{ 118 for (int i = 0; i < GC_POOL_SIZE; i++) 119 { 120 if (wxGCPool[i].m_gc) 121 XFreeGC( wxGlobalDisplay(), wxGCPool[i].m_gc ); 122 } 123} 124 125static GC wxGetPoolGC( Window window, wxPoolGCType type ) 126{ 127 for (int i = 0; i < GC_POOL_SIZE; i++) 128 { 129 if (!wxGCPool[i].m_gc) 130 { 131 wxGCPool[i].m_gc = XCreateGC( wxGlobalDisplay(), window, 0, NULL ); 132 XSetGraphicsExposures( wxGlobalDisplay(), wxGCPool[i].m_gc, FALSE ); 133 wxGCPool[i].m_type = type; 134 wxGCPool[i].m_used = false; 135 } 136 if ((!wxGCPool[i].m_used) && (wxGCPool[i].m_type == type)) 137 { 138 wxGCPool[i].m_used = true; 139 return wxGCPool[i].m_gc; 140 } 141 } 142 143 wxFAIL_MSG( wxT("No GC available") ); 144 145 return (GC) NULL; 146} 147 148static void wxFreePoolGC( GC gc ) 149{ 150 for (int i = 0; i < GC_POOL_SIZE; i++) 151 { 152 if (wxGCPool[i].m_gc == gc) 153 { 154 wxGCPool[i].m_used = false; 155 return; 156 } 157 } 158 159 wxFAIL_MSG( wxT("Wrong GC") ); 160} 161 162// ---------------------------------------------------------------------------- 163// wxWindowDC 164// ---------------------------------------------------------------------------- 165 166IMPLEMENT_DYNAMIC_CLASS(wxWindowDC, wxDC) 167 168void wxWindowDC::Init() 169{ 170 m_display = (WXDisplay *) NULL; 171 m_penGC = (WXGC *) NULL; 172 m_brushGC = (WXGC *) NULL; 173 m_textGC = (WXGC *) NULL; 174 m_bgGC = (WXGC *) NULL; 175 m_cmap = (WXColormap *) NULL; 176 m_isMemDC = false; 177 m_isScreenDC = false; 178 m_owner = (wxWindow *)NULL; 179 180#if wxUSE_UNICODE 181 m_context = wxTheApp->GetPangoContext(); 182 m_fontdesc = (PangoFontDescription *)NULL; 183#endif 184} 185 186wxWindowDC::wxWindowDC( wxWindow *window ) 187{ 188 wxASSERT_MSG( window, wxT("DC needs a window") ); 189 190 Init(); 191 192 m_font = window->GetFont(); 193 194 m_window = (WXWindow*) window->GetMainWindow(); 195 196 // not realized ? 197 if (!m_window) 198 { 199 // don't report problems 200 m_ok = true; 201 202 return; 203 } 204 205 m_display = (WXDisplay *) wxGlobalDisplay(); 206 207#if wxUSE_UNICODE 208 m_fontdesc = window->GetFont().GetNativeFontInfo()->description; 209#endif 210 211 int screen = DefaultScreen( (Display*) m_display ); 212 m_cmap = (WXColormap) DefaultColormap( (Display*) m_display, screen ); 213 214 SetUpDC(); 215 216 /* this must be done after SetUpDC, bacause SetUpDC calls the 217 repective SetBrush, SetPen, SetBackground etc functions 218 to set up the DC. SetBackground call m_owner->SetBackground 219 and this might not be desired as the standard dc background 220 is white whereas a window might assume gray to be the 221 standard (as e.g. wxStatusBar) */ 222 223 m_owner = window; 224} 225 226wxWindowDC::~wxWindowDC() 227{ 228 Destroy(); 229} 230 231void wxWindowDC::SetUpDC() 232{ 233 m_ok = true; 234 235 wxASSERT_MSG( !m_penGC, wxT("GCs already created") ); 236 237 if (m_isScreenDC) 238 { 239 m_penGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxPEN_SCREEN ); 240 m_brushGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxBRUSH_SCREEN ); 241 m_textGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxTEXT_SCREEN ); 242 m_bgGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxBG_SCREEN ); 243 } 244 else 245 if (m_isMemDC && (((wxMemoryDC*)this)->m_selected.GetDepth() == 1)) 246 { 247 m_penGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxPEN_MONO ); 248 m_brushGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxBRUSH_MONO ); 249 m_textGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxTEXT_MONO ); 250 m_bgGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxBG_MONO ); 251 } 252 else 253 { 254 m_penGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxPEN_COLOUR ); 255 m_brushGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxBRUSH_COLOUR ); 256 m_textGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxTEXT_COLOUR ); 257 m_bgGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxBG_COLOUR ); 258 } 259 260 /* background colour */ 261 m_backgroundBrush = *wxWHITE_BRUSH; 262 m_backgroundBrush.GetColour().CalcPixel( m_cmap ); 263 unsigned long bg_col = m_backgroundBrush.GetColour().GetPixel(); 264 265 m_textForegroundColour = *wxBLACK; 266 m_textBackgroundColour = *wxWHITE; 267 268 /* m_textGC */ 269 m_textForegroundColour.CalcPixel( m_cmap ); 270 XSetForeground( (Display*) m_display, (GC) m_textGC, m_textForegroundColour.GetPixel() ); 271 272 m_textBackgroundColour.CalcPixel( m_cmap ); 273 XSetBackground( (Display*) m_display, (GC) m_textGC, m_textBackgroundColour.GetPixel() ); 274 275 XSetFillStyle( (Display*) m_display, (GC) m_textGC, FillSolid ); 276 277#if wxUSE_NANOX 278 // By default, draw transparently 279 GrSetGCUseBackground((GC) m_textGC, FALSE); 280#endif 281 282 /* m_penGC */ 283 m_pen.GetColour().CalcPixel( m_cmap ); 284 XSetForeground( (Display*) m_display, (GC) m_penGC, m_pen.GetColour().GetPixel() ); 285 XSetBackground( (Display*) m_display, (GC) m_penGC, bg_col ); 286 287 XSetLineAttributes( (Display*) m_display, (GC) m_penGC, 0, LineSolid, CapNotLast, JoinRound ); 288 289 /* m_brushGC */ 290 m_brush.GetColour().CalcPixel( m_cmap ); 291 XSetForeground( (Display*) m_display, (GC) m_brushGC, m_brush.GetColour().GetPixel() ); 292 XSetBackground( (Display*) m_display, (GC) m_brushGC, bg_col ); 293 294 XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillSolid ); 295 296 /* m_bgGC */ 297 XSetForeground( (Display*) m_display, (GC) m_bgGC, bg_col ); 298 XSetBackground( (Display*) m_display, (GC) m_bgGC, bg_col ); 299 300 XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillSolid ); 301 302 /* ROPs */ 303 XSetFunction( (Display*) m_display, (GC) m_textGC, GXcopy ); 304 XSetFunction( (Display*) m_display, (GC) m_brushGC, GXcopy ); 305 XSetFunction( (Display*) m_display, (GC)m_penGC, GXcopy ); 306 307 /* clipping */ 308 XSetClipMask( (Display*) m_display, (GC) m_penGC, None ); 309 XSetClipMask( (Display*) m_display, (GC) m_brushGC, None ); 310 XSetClipMask( (Display*) m_display, (GC) m_textGC, None ); 311 XSetClipMask( (Display*) m_display, (GC) m_bgGC, None ); 312 313 if (!hatch_bitmap) 314 { 315 int xscreen = DefaultScreen( (Display*) m_display ); 316 Window xroot = RootWindow( (Display*) m_display, xscreen ); 317 318 hatch_bitmap = hatches; 319 hatch_bitmap[0] = XCreateBitmapFromData( (Display*) m_display, xroot, bdiag_bits, bdiag_width, bdiag_height ); 320 hatch_bitmap[1] = XCreateBitmapFromData( (Display*) m_display, xroot, cdiag_bits, cdiag_width, cdiag_height ); 321 hatch_bitmap[2] = XCreateBitmapFromData( (Display*) m_display, xroot, fdiag_bits, fdiag_width, fdiag_height ); 322 hatch_bitmap[3] = XCreateBitmapFromData( (Display*) m_display, xroot, cross_bits, cross_width, cross_height ); 323 hatch_bitmap[4] = XCreateBitmapFromData( (Display*) m_display, xroot, horiz_bits, horiz_width, horiz_height ); 324 hatch_bitmap[5] = XCreateBitmapFromData( (Display*) m_display, xroot, verti_bits, verti_width, verti_height ); 325 } 326} 327 328void wxWindowDC::DoGetSize( int* width, int* height ) const 329{ 330 wxCHECK_RET( m_owner, _T("GetSize() doesn't work without window") ); 331 332 m_owner->GetSize(width, height); 333} 334 335extern bool wxDoFloodFill(wxDC *dc, wxCoord x, wxCoord y, 336 const wxColour & col, int style); 337 338bool wxWindowDC::DoFloodFill(wxCoord x, wxCoord y, 339 const wxColour& col, int style) 340{ 341 return wxDoFloodFill(this, x, y, col, style); 342} 343 344bool wxWindowDC::DoGetPixel( wxCoord x1, wxCoord y1, wxColour *col ) const 345{ 346 // Generic (and therefore rather inefficient) method. 347 // Could be improved. 348 wxMemoryDC memdc; 349 wxBitmap bitmap(1, 1); 350 memdc.SelectObject(bitmap); 351 memdc.Blit(0, 0, 1, 1, (wxDC*) this, x1, y1); 352 memdc.SelectObject(wxNullBitmap); 353 wxImage image(bitmap.ConvertToImage()); 354 col->Set(image.GetRed(0, 0), image.GetGreen(0, 0), image.GetBlue(0, 0)); 355 return true; 356} 357 358void wxWindowDC::DoDrawLine( wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2 ) 359{ 360 wxCHECK_RET( Ok(), wxT("invalid window dc") ); 361 362 if (m_pen.GetStyle() != wxTRANSPARENT) 363 { 364 if (m_window) 365 { 366 // This hack is for the iPaq: XDrawLine draws 367 // nothing, whereas XDrawLines works... 368 wxPoint points[2]; 369 points[0].x = x1; 370 points[0].y = y1; 371 points[1].x = x2; 372 points[1].y = y2; 373 DrawLines( 2, points, 0, 0 ); 374 375 // XDrawLine( (Display*) m_display, (Window) m_window, 376 // (GC) m_penGC, XLOG2DEV(x1), YLOG2DEV(y1), XLOG2DEV(x2), YLOG2DEV(y2) ); 377 } 378 379 CalcBoundingBox(x1, y1); 380 CalcBoundingBox(x2, y2); 381 } 382} 383 384void wxWindowDC::DoCrossHair( wxCoord x, wxCoord y ) 385{ 386 wxCHECK_RET( Ok(), wxT("invalid window dc") ); 387 388 if (m_pen.GetStyle() != wxTRANSPARENT) 389 { 390 int w = 0; 391 int h = 0; 392 GetSize( &w, &h ); 393 wxCoord xx = XLOG2DEV(x); 394 wxCoord yy = YLOG2DEV(y); 395 if (m_window) 396 { 397 XDrawLine( (Display*) m_display, (Window) m_window, 398 (GC) m_penGC, 0, yy, XLOG2DEVREL(w), yy ); 399 XDrawLine( (Display*) m_display, (Window) m_window, 400 (GC) m_penGC, xx, 0, xx, YLOG2DEVREL(h) ); 401 } 402 } 403} 404 405void wxWindowDC::DoDrawArc( wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2, wxCoord xc, wxCoord yc ) 406{ 407 wxCHECK_RET( Ok(), wxT("invalid window dc") ); 408 409 wxCoord xx1 = XLOG2DEV(x1); 410 wxCoord yy1 = YLOG2DEV(y1); 411 wxCoord xx2 = XLOG2DEV(x2); 412 wxCoord yy2 = YLOG2DEV(y2); 413 wxCoord xxc = XLOG2DEV(xc); 414 wxCoord yyc = YLOG2DEV(yc); 415 double dx = xx1 - xxc; 416 double dy = yy1 - yyc; 417 double radius = sqrt((double)(dx*dx+dy*dy)); 418 wxCoord r = (wxCoord)radius; 419 double radius1, radius2; 420 421 if (xx1 == xx2 && yy1 == yy2) 422 { 423 radius1 = 0.0; 424 radius2 = 360.0; 425 } 426 else 427 if (radius == 0.0) 428 { 429 radius1 = radius2 = 0.0; 430 } 431 else 432 { 433 radius1 = (xx1 - xxc == 0) ? 434 (yy1 - yyc < 0) ? 90.0 : -90.0 : 435 -atan2(double(yy1-yyc), double(xx1-xxc)) * RAD2DEG; 436 radius2 = (xx2 - xxc == 0) ? 437 (yy2 - yyc < 0) ? 90.0 : -90.0 : 438 -atan2(double(yy2-yyc), double(xx2-xxc)) * RAD2DEG; 439 } 440 wxCoord alpha1 = wxCoord(radius1 * 64.0); 441 wxCoord alpha2 = wxCoord((radius2 - radius1) * 64.0); 442 while (alpha2 <= 0) alpha2 += 360*64; 443 while (alpha1 > 360*64) alpha1 -= 360*64; 444 445 if (m_window) 446 { 447 if (m_brush.GetStyle() != wxTRANSPARENT) 448 { 449 if ((m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE) && (m_brush.GetStipple()->GetMask())) 450 { 451 XSetTSOrigin( (Display*) m_display, (GC) m_textGC, 452 m_deviceOriginX % m_brush.GetStipple()->GetWidth(), 453 m_deviceOriginY % m_brush.GetStipple()->GetHeight() ); 454 455 XFillArc( (Display*) m_display, (Window) m_window, 456 (GC) m_brushGC, xxc-r, yyc-r, 2*r,2*r, alpha1, alpha2 ); 457 458 XSetTSOrigin( (Display*) m_display, (GC) m_textGC, 0, 0 ); 459 } else 460 if (IS_15_PIX_HATCH(m_brush.GetStyle())) 461 { 462 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 463 m_deviceOriginX % 15, m_deviceOriginY % 15 ); 464 465 XFillArc( (Display*) m_display, (Window) m_window, 466 (GC) m_brushGC, xxc-r, yyc-r, 2*r,2*r, alpha1, alpha2 ); 467 468 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 ); 469 } else 470 if (IS_16_PIX_HATCH(m_brush.GetStyle())) 471 { 472 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 473 m_deviceOriginX % 16, m_deviceOriginY % 16 ); 474 475 XFillArc( (Display*) m_display, (Window) m_window, 476 (GC) m_brushGC, xxc-r, yyc-r, 2*r,2*r, alpha1, alpha2 ); 477 478 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 ); 479 } else 480 if (m_brush.GetStyle() == wxSTIPPLE) 481 { 482 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 483 m_deviceOriginX % m_brush.GetStipple()->GetWidth(), 484 m_deviceOriginY % m_brush.GetStipple()->GetHeight() ); 485 486 XFillArc( (Display*) m_display, (Window) m_window, 487 (GC) m_brushGC, xxc-r, yyc-r, 2*r,2*r, alpha1, alpha2 ); 488 489 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 ); 490 } 491 else 492 { 493 XFillArc( (Display*) m_display, (Window) m_window, 494 (GC) m_brushGC, xxc-r, yyc-r, 2*r,2*r, alpha1, alpha2 ); 495 } 496 } 497 498 if (m_pen.GetStyle() != wxTRANSPARENT) 499 { 500 XDrawArc( (Display*) m_display, (Window) m_window, 501 (GC) m_penGC, xxc-r, yyc-r, 2*r,2*r, alpha1, alpha2 ); 502 503 XDrawLine( (Display*) m_display, (Window) m_window, 504 (GC) m_penGC, xx1, yy1, xxc, yyc ); 505 506 XDrawLine( (Display*) m_display, (Window) m_window, 507 (GC) m_penGC, xxc, yyc, xx2, yy2 ); 508 } 509 } 510 511 CalcBoundingBox (x1, y1); 512 CalcBoundingBox (x2, y2); 513} 514 515void wxWindowDC::DoDrawEllipticArc( wxCoord x, wxCoord y, wxCoord width, wxCoord height, double sa, double ea ) 516{ 517 wxCHECK_RET( Ok(), wxT("invalid window dc") ); 518 519 wxCoord xx = XLOG2DEV(x); 520 wxCoord yy = YLOG2DEV(y); 521 wxCoord ww = m_signX * XLOG2DEVREL(width); 522 wxCoord hh = m_signY * YLOG2DEVREL(height); 523 524 // CMB: handle -ve width and/or height 525 if (ww < 0) { ww = -ww; xx = xx - ww; } 526 if (hh < 0) { hh = -hh; yy = yy - hh; } 527 528 if (m_window) 529 { 530 wxCoord start = wxCoord(sa * 64.0); 531 wxCoord end = wxCoord((ea-sa) * 64.0); 532 533 if (m_brush.GetStyle() != wxTRANSPARENT) 534 { 535 if ((m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE) && (m_brush.GetStipple()->GetMask())) 536 { 537 XSetTSOrigin( (Display*) m_display, (GC) m_textGC, 538 m_deviceOriginX % m_brush.GetStipple()->GetWidth(), 539 m_deviceOriginY % m_brush.GetStipple()->GetHeight() ); 540 541 XFillArc( (Display*) m_display, (Window) m_window, 542 (GC) m_textGC, xx, yy, ww, hh, start, end ); 543 544 XSetTSOrigin( (Display*) m_display, (GC) m_textGC, 0, 0 ); 545 } else 546 if (IS_15_PIX_HATCH(m_brush.GetStyle())) 547 { 548 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 549 m_deviceOriginX % 15, m_deviceOriginY % 15 ); 550 551 XFillArc( (Display*) m_display, (Window) m_window, 552 (GC) m_brushGC, xx, yy, ww, hh, start, end ); 553 554 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 ); 555 } else 556 if (IS_16_PIX_HATCH(m_brush.GetStyle())) 557 { 558 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 559 m_deviceOriginX % 16, m_deviceOriginY % 16 ); 560 561 XFillArc( (Display*) m_display, (Window) m_window, 562 (GC) m_brushGC, xx, yy, ww, hh, start, end ); 563 564 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 ); 565 } else 566 if (m_brush.GetStyle() == wxSTIPPLE) 567 { 568 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 569 m_deviceOriginX % m_brush.GetStipple()->GetWidth(), 570 m_deviceOriginY % m_brush.GetStipple()->GetHeight() ); 571 572 XFillArc( (Display*) m_display, (Window) m_window, 573 (GC) m_brushGC, xx, yy, ww, hh, start, end ); 574 575 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 ); 576 } 577 else 578 { 579 XFillArc( (Display*) m_display, (Window) m_window, 580 (GC) m_brushGC, xx, yy, ww, hh, start, end ); 581 } 582 } 583 584 if (m_pen.GetStyle() != wxTRANSPARENT) 585 { 586 XDrawArc( (Display*) m_display, (Window) m_window, 587 (GC) m_penGC, xx, yy, ww, hh, start, end ); 588 } 589 } 590 591 CalcBoundingBox (x, y); 592 CalcBoundingBox (x + width, y + height); 593} 594 595void wxWindowDC::DoDrawPoint( wxCoord x, wxCoord y ) 596{ 597 wxCHECK_RET( Ok(), wxT("invalid window dc") ); 598 599 if ((m_pen.GetStyle() != wxTRANSPARENT) && m_window) 600 XDrawPoint( (Display*) m_display, (Window) m_window, 601 (GC) m_penGC, XLOG2DEV(x), YLOG2DEV(y) ); 602 603 CalcBoundingBox (x, y); 604} 605 606void wxWindowDC::DoDrawLines( int n, wxPoint points[], wxCoord xoffset, wxCoord yoffset ) 607{ 608 wxCHECK_RET( Ok(), wxT("invalid window dc") ); 609 610 if (m_pen.GetStyle() == wxTRANSPARENT) return; 611 if (n <= 0) return; 612 613 XPoint *xpoints = new XPoint[n]; 614 for (int i = 0; i < n; i++) 615 { 616 xpoints[i].x = XLOG2DEV (points[i].x + xoffset); 617 xpoints[i].y = YLOG2DEV (points[i].y + yoffset); 618 619 CalcBoundingBox( points[i].x + xoffset, points[i].y + yoffset ); 620 } 621 XDrawLines( (Display*) m_display, (Window) m_window, (GC) m_penGC, xpoints, n, 0 ); 622 623 delete[] xpoints; 624} 625 626void wxWindowDC::DoDrawPolygon( int n, wxPoint points[], 627 wxCoord xoffset, wxCoord yoffset, int fillStyle ) 628{ 629 wxCHECK_RET( Ok(), wxT("invalid window dc") ); 630 631 if (n <= 0) return; 632 633 XPoint *xpoints = new XPoint[n + 1]; 634 int i; 635 for (i = 0; i < n; i++) 636 { 637 xpoints[i].x = XLOG2DEV (points[i].x + xoffset); 638 xpoints[i].y = YLOG2DEV (points[i].y + yoffset); 639 640 CalcBoundingBox (points[i].x + xoffset, points[i].y + yoffset); 641 } 642 643 if (m_window) 644 { 645 if (m_brush.GetStyle() != wxTRANSPARENT) 646 { 647 648 if ((m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE) && (m_brush.GetStipple()->GetMask())) 649 { 650 XSetTSOrigin( (Display*) m_display, (GC) m_textGC, 651 m_deviceOriginX % m_brush.GetStipple()->GetWidth(), 652 m_deviceOriginY % m_brush.GetStipple()->GetHeight() ); 653 654 XFillPolygon( (Display*) m_display, (Window) m_window, 655 (GC) m_textGC, xpoints, n, Complex, 0); 656 657 XSetTSOrigin( (Display*) m_display, (GC) m_textGC, 0, 0 ); 658 } else 659 if (IS_15_PIX_HATCH(m_brush.GetStyle())) 660 { 661 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 662 m_deviceOriginX % 15, m_deviceOriginY % 15 ); 663 664 XFillPolygon( (Display*) m_display, (Window) m_window, 665 (GC) m_brushGC, xpoints, n, Complex, 0); 666 667 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 ); 668 } else 669 if (IS_16_PIX_HATCH(m_brush.GetStyle())) 670 { 671 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 672 m_deviceOriginX % 16, m_deviceOriginY % 16 ); 673 674 XFillPolygon( (Display*) m_display, (Window) m_window, 675 (GC) m_brushGC, xpoints, n, Complex, 0); 676 677 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 ); 678 } else 679 if (m_brush.GetStyle() == wxSTIPPLE) 680 { 681 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 682 m_deviceOriginX % m_brush.GetStipple()->GetWidth(), 683 m_deviceOriginY % m_brush.GetStipple()->GetHeight() ); 684 685 XFillPolygon( (Display*) m_display, (Window) m_window, 686 (GC) m_brushGC, xpoints, n, Complex, 0); 687 688 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 ); 689 } 690 else 691 { 692 XFillPolygon( (Display*) m_display, (Window) m_window, 693 (GC) m_brushGC, xpoints, n, Complex, 0); 694 } 695 } 696 697 if (m_pen.GetStyle () != wxTRANSPARENT) 698 { 699 // Close figure for XDrawLines 700 xpoints[i].x = xpoints[0].x; 701 xpoints[i].y = xpoints[0].y; 702 703 XDrawLines( (Display*) m_display, (Window) m_window, (GC) m_penGC, xpoints, n + 1, 0); 704 } 705 } 706 707 delete[] xpoints; 708} 709 710void wxWindowDC::DoDrawRectangle( wxCoord x, wxCoord y, wxCoord width, wxCoord height ) 711{ 712 wxCHECK_RET( Ok(), wxT("invalid window dc") ); 713 714 wxCoord xx = XLOG2DEV(x); 715 wxCoord yy = YLOG2DEV(y); 716 wxCoord ww = m_signX * XLOG2DEVREL(width); 717 wxCoord hh = m_signY * YLOG2DEVREL(height); 718 719 // CMB: draw nothing if transformed w or h is 0 720 if (ww == 0 || hh == 0) return; 721 722 // CMB: handle -ve width and/or height 723 if (ww < 0) { ww = -ww; xx = xx - ww; } 724 if (hh < 0) { hh = -hh; yy = yy - hh; } 725 726 if (m_window) 727 { 728 if (m_brush.GetStyle() != wxTRANSPARENT) 729 { 730 if ((m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE) && (m_brush.GetStipple()->GetMask())) 731 { 732 XSetTSOrigin( (Display*) m_display, (GC) m_textGC, 733 m_deviceOriginX % m_brush.GetStipple()->GetWidth(), 734 m_deviceOriginY % m_brush.GetStipple()->GetHeight() ); 735 736 XFillRectangle( (Display*) m_display, (Window) m_window, 737 (GC) m_textGC, xx, yy, ww, hh ); 738 739 XSetTSOrigin( (Display*) m_display, (GC) m_textGC, 0, 0 ); 740 } else 741 if (IS_15_PIX_HATCH(m_brush.GetStyle())) 742 { 743 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 744 m_deviceOriginX % 15, m_deviceOriginY % 15 ); 745 746 XFillRectangle( (Display*) m_display, (Window) m_window, 747 (GC) m_brushGC, xx, yy, ww, hh ); 748 749 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 ); 750 } else 751 if (IS_16_PIX_HATCH(m_brush.GetStyle())) 752 { 753 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 754 m_deviceOriginX % 16, m_deviceOriginY % 16 ); 755 756 XFillRectangle( (Display*) m_display, (Window) m_window, 757 (GC) m_brushGC, xx, yy, ww, hh ); 758 759 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 ); 760 } else 761 if (m_brush.GetStyle() == wxSTIPPLE) 762 { 763 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 764 m_deviceOriginX % m_brush.GetStipple()->GetWidth(), 765 m_deviceOriginY % m_brush.GetStipple()->GetHeight() ); 766 767 XFillRectangle( (Display*) m_display, (Window) m_window, 768 (GC) m_brushGC, xx, yy, ww, hh ); 769 770 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 ); 771 } 772 else 773 { 774 XFillRectangle( (Display*) m_display, (Window) m_window, 775 (GC) m_brushGC, xx, yy, ww, hh ); 776 } 777 } 778 779 if (m_pen.GetStyle () != wxTRANSPARENT) 780 { 781 XDrawRectangle( (Display*) m_display, (Window) m_window, 782 (GC) m_penGC, xx, yy, ww-1, hh-1 ); 783 } 784 } 785 786 CalcBoundingBox( x, y ); 787 CalcBoundingBox( x + width, y + height ); 788} 789 790void wxWindowDC::DoDrawRoundedRectangle( wxCoord x, wxCoord y, wxCoord width, wxCoord height, double radius ) 791{ 792 wxCHECK_RET( Ok(), wxT("invalid window dc") ); 793 794 if (radius < 0.0) radius = - radius * ((width < height) ? width : height); 795 796 wxCoord xx = XLOG2DEV(x); 797 wxCoord yy = YLOG2DEV(y); 798 wxCoord ww = m_signX * XLOG2DEVREL(width); 799 wxCoord hh = m_signY * YLOG2DEVREL(height); 800 wxCoord rr = XLOG2DEVREL((wxCoord)radius); 801 802 // CMB: handle -ve width and/or height 803 if (ww < 0) { ww = -ww; xx = xx - ww; } 804 if (hh < 0) { hh = -hh; yy = yy - hh; } 805 806 // CMB: if radius is zero use DrawRectangle() instead to avoid 807 // X drawing errors with small radii 808 if (rr == 0) 809 { 810 XDrawRectangle( (Display*) m_display, (Window) m_window, 811 (GC) m_penGC, x, y, width, height); 812 return; 813 } 814 815 // CMB: draw nothing if transformed w or h is 0 816 if (ww == 0 || hh == 0) return; 817 818 // CMB: adjust size if outline is drawn otherwise the result is 819 // 1 pixel too wide and high 820 if (m_pen.GetStyle() != wxTRANSPARENT) 821 { 822 ww--; 823 hh--; 824 } 825 826 if (m_window) 827 { 828 // CMB: ensure dd is not larger than rectangle otherwise we 829 // get an hour glass shape 830 wxCoord dd = 2 * rr; 831 if (dd > ww) dd = ww; 832 if (dd > hh) dd = hh; 833 rr = dd / 2; 834 835 if (m_brush.GetStyle() != wxTRANSPARENT) 836 { 837 if ((m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE) && (m_brush.GetStipple()->GetMask())) 838 { 839 XSetTSOrigin( (Display*) m_display, (GC) m_textGC, 840 m_deviceOriginX % m_brush.GetStipple()->GetWidth(), 841 m_deviceOriginY % m_brush.GetStipple()->GetHeight() ); 842 XFillRectangle( (Display*) m_display, (Window) m_window, (GC) m_textGC, xx+rr, yy, ww-dd+1, hh ); 843 XFillRectangle( (Display*) m_display, (Window) m_window, (GC) m_textGC, xx, yy+rr, ww, hh-dd+1 ); 844 XFillArc( (Display*) m_display, (Window) m_window, (GC) m_textGC, xx, yy, dd, dd, 90*64, 90*64 ); 845 XFillArc( (Display*) m_display, (Window) m_window, (GC) m_textGC, xx+ww-dd, yy, dd, dd, 0, 90*64 ); 846 XFillArc( (Display*) m_display, (Window) m_window, (GC) m_textGC, xx+ww-dd, yy+hh-dd, dd, dd, 270*64, 90*64 ); 847 XFillArc( (Display*) m_display, (Window) m_window, (GC) m_textGC, xx, yy+hh-dd, dd, dd, 180*64, 90*64 ); 848 XSetTSOrigin( (Display*) m_display, (GC) m_textGC, 0, 0); 849 } else 850 if (IS_15_PIX_HATCH(m_brush.GetStyle())) 851 { 852 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, m_deviceOriginX % 15, m_deviceOriginY % 15 ); 853 XFillRectangle( (Display*) m_display, (Window) m_window, (GC) m_brushGC, xx+rr, yy, ww-dd+1, hh ); 854 XFillRectangle( (Display*) m_display, (Window) m_window, (GC) m_brushGC, xx, yy+rr, ww, hh-dd+1 ); 855 XFillArc( (Display*) m_display, (Window) m_window, (GC) m_brushGC, xx, yy, dd, dd, 90*64, 90*64 ); 856 XFillArc( (Display*) m_display, (Window) m_window, (GC) m_brushGC, xx+ww-dd, yy, dd, dd, 0, 90*64 ); 857 XFillArc( (Display*) m_display, (Window) m_window, (GC) m_brushGC, xx+ww-dd, yy+hh-dd, dd, dd, 270*64, 90*64 ); 858 XFillArc( (Display*) m_display, (Window) m_window, (GC) m_brushGC, xx, yy+hh-dd, dd, dd, 180*64, 90*64 ); 859 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0); 860 } else 861 if (IS_16_PIX_HATCH(m_brush.GetStyle())) 862 { 863 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, m_deviceOriginX % 16, m_deviceOriginY % 16 ); 864 XFillRectangle( (Display*) m_display, (Window) m_window, (GC) m_brushGC, xx+rr, yy, ww-dd+1, hh ); 865 XFillRectangle( (Display*) m_display, (Window) m_window, (GC) m_brushGC, xx, yy+rr, ww, hh-dd+1 ); 866 XFillArc( (Display*) m_display, (Window) m_window, (GC) m_brushGC, xx, yy, dd, dd, 90*64, 90*64 ); 867 XFillArc( (Display*) m_display, (Window) m_window, (GC) m_brushGC, xx+ww-dd, yy, dd, dd, 0, 90*64 ); 868 XFillArc( (Display*) m_display, (Window) m_window, (GC) m_brushGC, xx+ww-dd, yy+hh-dd, dd, dd, 270*64, 90*64 ); 869 XFillArc( (Display*) m_display, (Window) m_window, (GC) m_brushGC, xx, yy+hh-dd, dd, dd, 180*64, 90*64 ); 870 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0); 871 } else 872 if (m_brush.GetStyle() == wxSTIPPLE) 873 { 874 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 875 m_deviceOriginX % m_brush.GetStipple()->GetWidth(), 876 m_deviceOriginY % m_brush.GetStipple()->GetHeight() ); 877 XFillRectangle( (Display*) m_display, (Window) m_window, (GC) m_brushGC, xx+rr, yy, ww-dd+1, hh ); 878 XFillRectangle( (Display*) m_display, (Window) m_window, (GC) m_brushGC, xx, yy+rr, ww, hh-dd+1 ); 879 XFillArc( (Display*) m_display, (Window) m_window, (GC) m_brushGC, xx, yy, dd, dd, 90*64, 90*64 ); 880 XFillArc( (Display*) m_display, (Window) m_window, (GC) m_brushGC, xx+ww-dd, yy, dd, dd, 0, 90*64 ); 881 XFillArc( (Display*) m_display, (Window) m_window, (GC) m_brushGC, xx+ww-dd, yy+hh-dd, dd, dd, 270*64, 90*64 ); 882 XFillArc( (Display*) m_display, (Window) m_window, (GC) m_brushGC, xx, yy+hh-dd, dd, dd, 180*64, 90*64 ); 883 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0); 884 } 885 else 886 { 887 XFillRectangle( (Display*) m_display, (Window) m_window, (GC) m_brushGC, xx+rr, yy, ww-dd+1, hh ); 888 XFillRectangle( (Display*) m_display, (Window) m_window, (GC) m_brushGC, xx, yy+rr, ww, hh-dd+1 ); 889 XFillArc( (Display*) m_display, (Window) m_window, (GC) m_brushGC, xx, yy, dd, dd, 90*64, 90*64 ); 890 XFillArc( (Display*) m_display, (Window) m_window, (GC) m_brushGC, xx+ww-dd, yy, dd, dd, 0, 90*64 ); 891 XFillArc( (Display*) m_display, (Window) m_window, (GC) m_brushGC, xx+ww-dd, yy+hh-dd, dd, dd, 270*64, 90*64 ); 892 XFillArc( (Display*) m_display, (Window) m_window, (GC) m_brushGC, xx, yy+hh-dd, dd, dd, 180*64, 90*64 ); 893 } 894 } 895 if (m_pen.GetStyle() != wxTRANSPARENT) 896 { 897 XDrawLine( (Display*) m_display, (Window) m_window, (GC) m_penGC, xx+rr+1, yy, xx+ww-rr, yy ); 898 XDrawLine( (Display*) m_display, (Window) m_window, (GC) m_penGC, xx+rr+1, yy+hh, xx+ww-rr, yy+hh ); 899 XDrawLine( (Display*) m_display, (Window) m_window, (GC) m_penGC, xx, yy+rr+1, xx, yy+hh-rr ); 900 XDrawLine( (Display*) m_display, (Window) m_window, (GC) m_penGC, xx+ww, yy+rr+1, xx+ww, yy+hh-rr ); 901 XDrawArc( (Display*) m_display, (Window) m_window, (GC) m_penGC, xx, yy, dd, dd, 90*64, 90*64 ); 902 XDrawArc( (Display*) m_display, (Window) m_window, (GC) m_penGC, xx+ww-dd, yy, dd, dd, 0, 90*64 ); 903 XDrawArc( (Display*) m_display, (Window) m_window, (GC) m_penGC, xx+ww-dd, yy+hh-dd, dd, dd, 270*64, 90*64 ); 904 XDrawArc( (Display*) m_display, (Window) m_window, (GC) m_penGC, xx, yy+hh-dd, dd, dd, 180*64, 90*64 ); 905 } 906 } 907 908 // this ignores the radius 909 CalcBoundingBox( x, y ); 910 CalcBoundingBox( x + width, y + height ); 911} 912 913void wxWindowDC::DoDrawEllipse( wxCoord x, wxCoord y, wxCoord width, wxCoord height ) 914{ 915 wxCHECK_RET( Ok(), wxT("invalid window dc") ); 916 917 wxCoord xx = XLOG2DEV(x); 918 wxCoord yy = YLOG2DEV(y); 919 wxCoord ww = m_signX * XLOG2DEVREL(width); 920 wxCoord hh = m_signY * YLOG2DEVREL(height); 921 922 // CMB: handle -ve width and/or height 923 if (ww < 0) { ww = -ww; xx = xx - ww; } 924 if (hh < 0) { hh = -hh; yy = yy - hh; } 925 926 if (m_window) 927 { 928 if (m_brush.GetStyle() != wxTRANSPARENT) 929 { 930 if ((m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE) && (m_brush.GetStipple()->GetMask())) 931 { 932 XSetTSOrigin( (Display*) m_display, (GC) m_textGC, 933 m_deviceOriginX % m_brush.GetStipple()->GetWidth(), 934 m_deviceOriginY % m_brush.GetStipple()->GetHeight() ); 935 936 XFillArc( (Display*) m_display, (Window) m_window, 937 (GC) m_textGC, xx, yy, ww, hh, 0, 360*64 ); 938 939 XSetTSOrigin( (Display*) m_display, (GC) m_textGC, 0, 0 ); 940 } else 941 if (IS_15_PIX_HATCH(m_brush.GetStyle())) 942 { 943 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 944 m_deviceOriginX % 15, m_deviceOriginY % 15 ); 945 946 XFillArc( (Display*) m_display, (Window) m_window, 947 (GC) m_brushGC, xx, yy, ww, hh, 0, 360*64 ); 948 949 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 ); 950 } else 951 if (IS_16_PIX_HATCH(m_brush.GetStyle())) 952 { 953 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 954 m_deviceOriginX % 16, m_deviceOriginY % 16 ); 955 956 XFillArc( (Display*) m_display, (Window) m_window, 957 (GC) m_brushGC, xx, yy, ww, hh, 0, 360*64 ); 958 959 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 ); 960 } else 961 if (m_brush.GetStyle() == wxSTIPPLE) 962 { 963 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 964 m_deviceOriginX % m_brush.GetStipple()->GetWidth(), 965 m_deviceOriginY % m_brush.GetStipple()->GetHeight() ); 966 967 XFillArc( (Display*) m_display, (Window) m_window, 968 (GC) m_brushGC, xx, yy, ww, hh, 0, 360*64 ); 969 970 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 ); 971 } 972 else 973 { 974 XFillArc( (Display*) m_display, (Window) m_window, 975 (GC) m_brushGC, xx, yy, ww, hh, 0, 360*64 ); 976 } 977 } 978 979 if (m_pen.GetStyle () != wxTRANSPARENT) 980 { 981 XDrawArc( (Display*) m_display, (Window) m_window, 982 (GC) m_penGC, xx, yy, ww, hh, 0, 360*64 ); 983 } 984 } 985 986 CalcBoundingBox( x, y ); 987 CalcBoundingBox( x + width, y + height ); 988} 989 990void wxWindowDC::DoDrawIcon( const wxIcon &icon, wxCoord x, wxCoord y) 991{ 992 DoDrawBitmap(icon, x, y, true); 993} 994 995#if wxUSE_NANOX 996void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap, 997 wxCoord x, wxCoord y, 998 bool useMask ) 999{ 1000 wxCHECK_RET( Ok(), wxT("invalid window dc") ); 1001 1002 wxCHECK_RET( bitmap.Ok(), wxT("invalid bitmap") ); 1003 1004 bool is_mono = (bitmap.GetBitmap() != NULL); 1005 1006 /* scale/translate size and position */ 1007 int xx = XLOG2DEV(x); 1008 int yy = YLOG2DEV(y); 1009 1010 int w = bitmap.GetWidth(); 1011 int h = bitmap.GetHeight(); 1012 1013 CalcBoundingBox( x, y ); 1014 CalcBoundingBox( x + w, y + h ); 1015 1016 if (!m_window) return; 1017 1018 int ww = XLOG2DEVREL(w); 1019 int hh = YLOG2DEVREL(h); 1020 1021 /* compare to current clipping region */ 1022 if (!m_currentClippingRegion.IsNull()) 1023 { 1024 wxRegion tmp( xx,yy,ww,hh ); 1025 tmp.Intersect( m_currentClippingRegion ); 1026 if (tmp.IsEmpty()) 1027 return; 1028 } 1029 1030 /* scale bitmap if required */ 1031 wxBitmap use_bitmap; 1032 if ((w != ww) || (h != hh)) 1033 { 1034 wxImage image( bitmap.ConvertToImage() ); 1035 image.Rescale( ww, hh ); 1036#if 0 1037 if (is_mono) 1038 use_bitmap = image.ConvertToMonoBitmap(255,255,255); 1039 else 1040#endif 1041 use_bitmap = image; 1042 } 1043 else 1044 { 1045 use_bitmap = bitmap; 1046 } 1047 1048 /* apply mask if any */ 1049 WXPixmap mask = NULL; 1050 if (use_bitmap.GetMask()) 1051 mask = use_bitmap.GetMask()->GetBitmap(); 1052 1053 if (useMask && mask) 1054 { 1055 Pixmap pixmap = (Pixmap) use_bitmap.GetPixmap() ; 1056 Pixmap maskPixmap = (Pixmap) use_bitmap.GetMask()->GetBitmap() ; 1057 Pixmap bufPixmap = GrNewPixmap(w, h, 0); 1058 GC gc = GrNewGC(); 1059 GrSetGCUseBackground(gc, FALSE); 1060 GrSetGCMode(gc, GR_MODE_COPY); 1061 1062 // This code assumes that background and foreground 1063 // colours are used in ROPs, like in MSW. 1064 // Not sure if this is true. 1065 1066 // Copy destination to buffer. 1067 // In DoBlit, we need this step because Blit has 1068 // a ROP argument. Here, we don't need it. 1069 // In DoBlit, we may be able to eliminate this step 1070 // if we check if the rop = copy 1071#if 0 1072 GrCopyArea(bufPixmap, gc, 0, 0, w, h, (Window) m_window, 1073 0, 0, GR_MODE_COPY); 1074#endif 1075 1076 // Copy src to buffer using selected raster op (none selected 1077 // in DrawBitmap, so just use Gxcopy) 1078 GrCopyArea(bufPixmap, gc, 0, 0, w, h, pixmap, 1079 0, 0, GR_MODE_COPY); 1080 1081 // Set masked area in buffer to BLACK (pixel value 0) 1082 GrSetGCBackground(gc, WHITE); 1083 GrSetGCForeground(gc, BLACK); 1084 GrCopyArea(bufPixmap, gc, 0, 0, w, h, maskPixmap, 1085 0, 0, GR_MODE_AND); 1086 1087 // set unmasked area in dest to BLACK 1088 GrSetGCBackground(gc, BLACK); 1089 GrSetGCForeground(gc, WHITE); 1090 GrCopyArea((Window) m_window, gc, xx, yy, w, h, maskPixmap, 1091 0, 0, GR_MODE_AND); 1092 1093 // OR buffer to dest 1094 GrCopyArea((Window) m_window, gc, xx, yy, w, h, bufPixmap, 1095 0, 0, GR_MODE_OR); 1096 1097 GrDestroyGC(gc); 1098 GrDestroyWindow(bufPixmap); 1099 } 1100 else 1101 XCopyArea( (Display*) m_display, (Pixmap) use_bitmap.GetPixmap(), (Window) m_window, 1102 (GC) m_penGC, 0, 0, w, h, xx, yy ); 1103 1104 /* remove mask again if any */ 1105 if (useMask && mask) 1106 { 1107 if (!m_currentClippingRegion.IsNull()) 1108 XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() ); 1109 } 1110} 1111 1112#else 1113 1114// Normal X11 1115void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap, 1116 wxCoord x, wxCoord y, 1117 bool useMask ) 1118{ 1119 wxCHECK_RET( Ok(), wxT("invalid window dc") ); 1120 1121 wxCHECK_RET( bitmap.Ok(), wxT("invalid bitmap") ); 1122 1123 bool is_mono = (bitmap.GetBitmap() != NULL); 1124 1125 // scale/translate size and position 1126 int xx = XLOG2DEV(x); 1127 int yy = YLOG2DEV(y); 1128 1129 int w = bitmap.GetWidth(); 1130 int h = bitmap.GetHeight(); 1131 1132 CalcBoundingBox( x, y ); 1133 CalcBoundingBox( x + w, y + h ); 1134 1135 if (!m_window) return; 1136 1137 int ww = XLOG2DEVREL(w); 1138 int hh = YLOG2DEVREL(h); 1139 1140 // compare to current clipping region 1141 if (!m_currentClippingRegion.IsNull()) 1142 { 1143 wxRegion tmp( xx,yy,ww,hh ); 1144 tmp.Intersect( m_currentClippingRegion ); 1145 if (tmp.IsEmpty()) 1146 return; 1147 } 1148 1149 // scale bitmap if required 1150 wxBitmap use_bitmap; 1151 if ((w != ww) || (h != hh)) 1152 { 1153 wxImage image( bitmap.ConvertToImage() ); 1154 image.Rescale( ww, hh ); 1155#if 0 1156 if (is_mono) 1157 use_bitmap = image.ConvertToMonoBitmap(255,255,255); 1158 else 1159#endif 1160 use_bitmap = image; 1161 } 1162 else 1163 { 1164 use_bitmap = bitmap; 1165 } 1166 1167 // apply mask if any 1168 WXPixmap mask = NULL; 1169 if (use_bitmap.GetMask()) mask = use_bitmap.GetMask()->GetBitmap(); 1170 1171 bool setClipMask = false; 1172 1173 if (!m_currentClippingRegion.IsNull() || (useMask && mask)) 1174 { 1175 // XSetClipMask() call is necessary (because of clip region and/or transparent mask) 1176 setClipMask = true; 1177 Pixmap new_pixmap = 0; 1178 1179 if (!m_currentClippingRegion.IsNull()) 1180 { 1181 // clipping necessary => create new_pixmap 1182 Display *xdisplay = (Display*) m_display; 1183 int xscreen = DefaultScreen( xdisplay ); 1184 Window xroot = RootWindow( xdisplay, xscreen ); 1185 1186 new_pixmap = XCreatePixmap( xdisplay, xroot, ww, hh, 1 ); 1187 GC gc = XCreateGC( xdisplay, new_pixmap, 0, NULL ); 1188 1189 XSetForeground( xdisplay, gc, BlackPixel(xdisplay,xscreen) ); 1190 1191 XSetFillStyle( xdisplay, gc, FillSolid ); 1192 XFillRectangle( xdisplay, new_pixmap, gc, 0, 0, ww, hh ); 1193 1194 XSetForeground( xdisplay, gc, WhitePixel(xdisplay,xscreen) ); 1195 1196 if (useMask && mask) 1197 { 1198 // transparent mask => call XSetStipple 1199 XSetFillStyle( xdisplay, gc, FillStippled ); 1200 XSetTSOrigin( xdisplay, gc, 0, 0); 1201 XSetStipple( xdisplay, gc, (Pixmap) mask); 1202 } 1203 1204 wxCoord clip_x, clip_y, clip_w, clip_h; 1205 m_currentClippingRegion.GetBox(clip_x, clip_y, clip_w, clip_h); 1206 XFillRectangle( xdisplay, new_pixmap, gc, clip_x-xx, clip_y-yy, clip_w, clip_h ); 1207 1208 XFreeGC( xdisplay, gc ); 1209 } 1210 1211 if (is_mono) 1212 { 1213 if (new_pixmap) 1214 XSetClipMask( (Display*) m_display, (GC) m_textGC, new_pixmap ); 1215 else 1216 XSetClipMask( (Display*) m_display, (GC) m_textGC, (Pixmap) mask ); 1217 XSetClipOrigin( (Display*) m_display, (GC) m_textGC, xx, yy ); 1218 } 1219 else 1220 { 1221 if (new_pixmap) 1222 XSetClipMask( (Display*) m_display, (GC) m_penGC, new_pixmap ); 1223 else 1224 XSetClipMask( (Display*) m_display, (GC) m_penGC, (Pixmap) mask ); 1225 XSetClipOrigin( (Display*) m_display, (GC) m_penGC, xx, yy ); 1226 } 1227 1228 if (new_pixmap) 1229 XFreePixmap( (Display*) m_display, new_pixmap ); 1230 } 1231 1232 // Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For 1233 // drawing a mono-bitmap (XBitmap) we use the current text GC 1234 if (is_mono) 1235 XCopyPlane( (Display*) m_display, (Pixmap) use_bitmap.GetBitmap(), (Window) m_window, 1236 (GC) m_textGC, 0, 0, ww, hh, xx, yy, 1 ); 1237 else 1238 XCopyArea( (Display*) m_display, (Pixmap) use_bitmap.GetPixmap(), (Window) m_window, 1239 (GC) m_penGC, 0, 0, ww, hh, xx, yy ); 1240 1241 // remove mask again if any 1242 if (setClipMask) 1243 { 1244 if (is_mono) 1245 { 1246 XSetClipMask( (Display*) m_display, (GC) m_textGC, None ); 1247 XSetClipOrigin( (Display*) m_display, (GC) m_textGC, 0, 0 ); 1248 if (!m_currentClippingRegion.IsNull()) 1249 XSetRegion( (Display*) m_display, (GC) m_textGC, (Region) m_currentClippingRegion.GetX11Region() ); 1250 } 1251 else 1252 { 1253 XSetClipMask( (Display*) m_display, (GC) m_penGC, None ); 1254 XSetClipOrigin( (Display*) m_display, (GC) m_penGC, 0, 0 ); 1255 if (!m_currentClippingRegion.IsNull()) 1256 XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() ); 1257 } 1258 } 1259} 1260#endif 1261 // wxUSE_NANOX/!wxUSE_NANOX 1262 1263bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height, 1264 wxDC *source, wxCoord xsrc, wxCoord ysrc, int logical_func, bool useMask, 1265 wxCoord xsrcMask, wxCoord ysrcMask ) 1266{ 1267 /* this is the nth try to get this utterly useless function to 1268 work. it now completely ignores the scaling or translation 1269 of the source dc, but scales correctly on the target dc and 1270 knows about possible mask information in a memory dc. */ 1271 1272 wxCHECK_MSG( Ok(), false, wxT("invalid window dc") ); 1273 1274 wxCHECK_MSG( source, false, wxT("invalid source dc") ); 1275 1276 if (!m_window) return false; 1277 1278 // transform the source DC coords to the device ones 1279 xsrc = source->XLOG2DEV(xsrc); 1280 ysrc = source->YLOG2DEV(ysrc); 1281 1282 wxClientDC *srcDC = (wxClientDC*)source; 1283 wxMemoryDC *memDC = (wxMemoryDC*)source; 1284 1285 bool use_bitmap_method = false; 1286 bool is_mono = false; 1287 1288 // TODO: use the mask origin when drawing transparently 1289 if (xsrcMask == -1 && ysrcMask == -1) 1290 { 1291 xsrcMask = xsrc; 1292 ysrcMask = ysrc; 1293 } 1294 1295 if (srcDC->m_isMemDC) 1296 { 1297 if (!memDC->m_selected.Ok()) return false; 1298 1299 /* we use the "XCopyArea" way to copy a memory dc into 1300 y different window if the memory dc BOTH 1301 a) doesn't have any mask or its mask isn't used 1302 b) it is clipped 1303 c) is not 1-bit */ 1304 1305 if (useMask && (memDC->m_selected.GetMask())) 1306 { 1307 /* we HAVE TO use the direct way for memory dcs 1308 that have mask since the XCopyArea doesn't know 1309 about masks */ 1310 use_bitmap_method = true; 1311 } 1312 else if (memDC->m_selected.GetDepth() == 1) 1313 { 1314 /* we HAVE TO use the direct way for memory dcs 1315 that are bitmaps because XCopyArea doesn't cope 1316 with different bit depths */ 1317 is_mono = true; 1318 use_bitmap_method = true; 1319 } 1320 else if ((xsrc == 0) && (ysrc == 0) && 1321 (width == memDC->m_selected.GetWidth()) && 1322 (height == memDC->m_selected.GetHeight())) 1323 { 1324 /* we SHOULD use the direct way if all of the bitmap 1325 in the memory dc is copied in which case XCopyArea 1326 wouldn't be able able to boost performace by reducing 1327 the area to be scaled */ 1328 use_bitmap_method = true; 1329 } 1330 else 1331 { 1332 use_bitmap_method = false; 1333 } 1334 } 1335 1336 CalcBoundingBox( xdest, ydest ); 1337 CalcBoundingBox( xdest + width, ydest + height ); 1338 1339 // scale/translate size and position 1340 wxCoord xx = XLOG2DEV(xdest); 1341 wxCoord yy = YLOG2DEV(ydest); 1342 1343 wxCoord ww = XLOG2DEVREL(width); 1344 wxCoord hh = YLOG2DEVREL(height); 1345 1346 // compare to current clipping region 1347 if (!m_currentClippingRegion.IsNull()) 1348 { 1349 wxRegion tmp( xx,yy,ww,hh ); 1350 tmp.Intersect( m_currentClippingRegion ); 1351 if (tmp.IsEmpty()) 1352 return true; 1353 } 1354 1355 int old_logical_func = m_logicalFunction; 1356 SetLogicalFunction( logical_func ); 1357 1358 if (use_bitmap_method) 1359 { 1360 // scale/translate bitmap size 1361 wxCoord bm_width = memDC->m_selected.GetWidth(); 1362 wxCoord bm_height = memDC->m_selected.GetHeight(); 1363 1364 wxCoord bm_ww = XLOG2DEVREL( bm_width ); 1365 wxCoord bm_hh = YLOG2DEVREL( bm_height ); 1366 1367 // scale bitmap if required 1368 wxBitmap use_bitmap; 1369 1370 if ((bm_width != bm_ww) || (bm_height != bm_hh)) 1371 { 1372 wxImage image( memDC->m_selected.ConvertToImage() ); 1373 image = image.Scale( bm_ww, bm_hh ); 1374 1375#if 0 1376 if (is_mono) 1377 use_bitmap = image.ConvertToMonoBitmap(255,255,255); 1378 else 1379#endif 1380 use_bitmap = image; 1381 } 1382 else 1383 { 1384 use_bitmap = memDC->m_selected; 1385 } 1386 1387 // apply mask if any 1388 WXPixmap mask = NULL; 1389 if (use_bitmap.GetMask()) mask = use_bitmap.GetMask()->GetBitmap(); 1390 1391 if (useMask && mask) 1392 { 1393 WXPixmap new_mask = NULL; 1394#if 0 1395 if (!m_currentClippingRegion.IsNull()) 1396 { 1397 GdkColor col; 1398 new_mask = gdk_pixmap_new( wxGetRootWindow()->window, bm_ww, bm_hh, 1 ); 1399 GdkGC *gc = gdk_gc_new( new_mask ); 1400 col.pixel = 0; 1401 gdk_gc_set_foreground( gc, &col ); 1402 gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, bm_ww, bm_hh ); 1403 col.pixel = 0; 1404 gdk_gc_set_background( gc, &col ); 1405 col.pixel = 1; 1406 gdk_gc_set_foreground( gc, &col ); 1407 gdk_gc_set_clip_region( gc, m_currentClippingRegion.GetRegion() ); 1408 gdk_gc_set_clip_origin( gc, -xx, -yy ); 1409 gdk_gc_set_fill( gc, GDK_OPAQUE_STIPPLED ); 1410 gdk_gc_set_stipple( gc, mask ); 1411 gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, bm_ww, bm_hh ); 1412 gdk_gc_unref( gc ); 1413 } 1414#endif 1415 if (is_mono) 1416 { 1417 if (new_mask) 1418 XSetClipMask( (Display*) m_display, (GC) m_textGC, (Pixmap) new_mask ); 1419 else 1420 XSetClipMask( (Display*) m_display, (GC) m_textGC, (Pixmap) mask ); 1421 XSetClipOrigin( (Display*) m_display, (GC) m_textGC, xx, yy ); 1422 } 1423 else 1424 { 1425 if (new_mask) 1426 XSetClipMask( (Display*) m_display, (GC) m_penGC, (Pixmap) new_mask ); 1427 else 1428 XSetClipMask( (Display*) m_display, (GC) m_penGC, (Pixmap) mask ); 1429 XSetClipOrigin( (Display*) m_display, (GC) m_penGC, xx, yy ); 1430 } 1431 1432 if (new_mask) 1433 XFreePixmap( (Display*) m_display, (Pixmap) new_mask ); 1434 } 1435 1436 // Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For 1437 // drawing a mono-bitmap (XBitmap) we use the current text GC 1438 1439 if (is_mono) 1440 XCopyPlane( (Display*) m_display, (Pixmap) use_bitmap.GetBitmap(), (Window) m_window, 1441 (GC) m_textGC, xsrc, ysrc, width, height, xx, yy, 1 ); 1442 else 1443 XCopyArea( (Display*) m_display, (Pixmap) use_bitmap.GetPixmap(), (Window) m_window, 1444 (GC) m_penGC, xsrc, ysrc, width, height, xx, yy ); 1445 1446 // remove mask again if any 1447 if (useMask && mask) 1448 { 1449 if (is_mono) 1450 { 1451 XSetClipMask( (Display*) m_display, (GC) m_textGC, None ); 1452 XSetClipOrigin( (Display*) m_display, (GC) m_textGC, 0, 0 ); 1453 if (!m_currentClippingRegion.IsNull()) 1454 XSetRegion( (Display*) m_display, (GC) m_textGC, (Region) m_currentClippingRegion.GetX11Region() ); 1455 } 1456 else 1457 { 1458 XSetClipMask( (Display*) m_display, (GC) m_penGC, None ); 1459 XSetClipOrigin( (Display*) m_display, (GC) m_penGC, 0, 0 ); 1460 if (!m_currentClippingRegion.IsNull()) 1461 XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() ); 1462 } 1463 } 1464 } 1465 else // use_bitmap_method 1466 { 1467 if ((width != ww) || (height != hh)) 1468 { 1469 /* Draw source window into a bitmap as we cannot scale 1470 a window in contrast to a bitmap. this would actually 1471 work with memory dcs as well, but we'd lose the mask 1472 information and waste one step in this process since 1473 a memory already has a bitmap. all this is slightly 1474 inefficient as we could take an XImage directly from 1475 an X window, but we'd then also have to care that 1476 the window is not outside the screen (in which case 1477 we'd get a BadMatch or what not). 1478 Is a double XGetImage and combined XGetPixel and 1479 XPutPixel really faster? I'm not sure. look at wxXt 1480 for a different implementation of the same problem. */ 1481 1482 wxBitmap bitmap( width, height ); 1483 1484 // copy including child window contents 1485 XSetSubwindowMode( (Display*) m_display, (GC) m_penGC, IncludeInferiors ); 1486 XCopyArea( (Display*) m_display, (Window) srcDC->GetWindow(), (Window) bitmap.GetPixmap(), 1487 (GC) m_penGC, xsrc, ysrc, width, height, 0, 0 ); 1488 XSetSubwindowMode( (Display*) m_display, (GC) m_penGC, ClipByChildren ); 1489 1490 // scale image 1491 wxImage image( bitmap.ConvertToImage() ); 1492 image = image.Scale( ww, hh ); 1493 1494 // convert to bitmap 1495 bitmap = image; 1496 1497 // draw scaled bitmap 1498 XCopyArea( (Display*) m_display, (Window) bitmap.GetPixmap(), (Window) m_window, 1499 (GC) m_penGC, 0, 0, width, height, xx, yy ); 1500 } 1501 else 1502 { 1503 // No scaling and not a memory dc with a mask either 1504 1505 // copy including child window contents 1506 XSetSubwindowMode( (Display*) m_display, (GC) m_penGC, IncludeInferiors ); 1507 XCopyArea( (Display*) m_display, (Window) srcDC->GetWindow(), (Window) m_window, 1508 (GC) m_penGC, xsrc, ysrc, width, height, xx, yy ); 1509 XSetSubwindowMode( (Display*) m_display, (GC) m_penGC, ClipByChildren ); 1510 } 1511 } 1512 1513 SetLogicalFunction( old_logical_func ); 1514 1515 return true; 1516} 1517 1518void wxWindowDC::DoDrawText( const wxString &text, wxCoord x, wxCoord y ) 1519{ 1520 wxCHECK_RET( Ok(), wxT("invalid window dc") ); 1521 1522 if (!m_window) return; 1523 1524 x = XLOG2DEV(x); 1525 y = YLOG2DEV(y); 1526 1527#if wxUSE_UNICODE 1528 PangoLayout *layout = pango_layout_new(m_context); 1529 pango_layout_set_font_description(layout, m_fontdesc); 1530 1531 const wxCharBuffer data = wxConvUTF8.cWC2MB( text ); 1532 pango_layout_set_text(layout, (const char*) data, strlen( (const char*) data )); 1533 1534 // Measure layout. 1535 int w,h; 1536 pango_layout_get_pixel_size(layout, &w, &h); 1537 wxCoord width = w; 1538 wxCoord height = h; 1539 1540 // Draw layout. 1541 x11_draw_layout( (Drawable) m_window, (GC) m_textGC, x, y, layout, m_textForegroundColour ); 1542 1543 g_object_unref( G_OBJECT( layout ) ); 1544 1545 CalcBoundingBox (x + width, y + height); 1546 CalcBoundingBox (x, y); 1547#else 1548 XFontStruct *xfont = (XFontStruct*) m_font.GetFontStruct( m_scaleY, m_display ); 1549 1550 wxCHECK_RET( xfont, wxT("invalid font") ); 1551 1552 // First draw a rectangle representing the text background, if a text 1553 // background is specified 1554 if (m_textBackgroundColour.Ok () && (m_backgroundMode != wxTRANSPARENT)) 1555 { 1556 // Since X draws from the baseline of the text, must add the text height 1557 int cx = 0; 1558 int cy = 0; 1559 int ascent = 0; 1560 int slen; 1561 int direction, descent; 1562 1563 slen = strlen(text); 1564 XCharStruct overall_return; 1565 1566 (void)XTextExtents(xfont, (char*) text.c_str(), slen, &direction, 1567 &ascent, &descent, &overall_return); 1568 1569 cx = overall_return.width; 1570 cy = ascent + descent; 1571 m_textBackgroundColour.CalcPixel(m_cmap); 1572 m_textForegroundColour.CalcPixel(m_cmap); 1573 XSetForeground ((Display*) m_display, (GC) m_textGC, m_textBackgroundColour.GetPixel()); 1574 XFillRectangle( (Display*) m_display, (Window) m_window, 1575 (GC) m_textGC, x, y, cx, cy ); 1576 XSetForeground ((Display*) m_display, (GC) m_textGC, m_textForegroundColour.GetPixel()); 1577 1578 } 1579 1580 XSetFont( (Display*) m_display, (GC) m_textGC, xfont->fid ); 1581#if !wxUSE_NANOX 1582 // This may be a test for whether the font is 16-bit, but it also 1583 // seems to fail for valid 8-bit fonts too. 1584 if (1) // (xfont->min_byte1 == 0) && (xfont->max_byte1 == 0)) 1585#endif 1586 { 1587 XDrawString( (Display*) m_display, (Window) m_window, 1588 (GC) m_textGC, x, y + XFontStructGetAscent(xfont), text.c_str(), text.length() ); 1589 } 1590 1591#if 0 1592 if (m_font.GetUnderlined()) 1593 { 1594 wxCoord ul_y = y + XFontStructGetAscent(font); 1595 if (font->descent > 0) ul_y++; 1596 gdk_draw_line( m_window, m_textGC, x, ul_y, x + width, ul_y); 1597 } 1598 1599 width = wxCoord(width / m_scaleX); 1600 height = wxCoord(height / m_scaleY); 1601 1602 CalcBoundingBox (x + width, y + height); 1603 CalcBoundingBox (x, y); 1604#endif 1605#endif 1606} 1607 1608void wxWindowDC::DoDrawRotatedText( const wxString &text, wxCoord x, wxCoord y, double angle ) 1609{ 1610 // later 1611} 1612 1613void wxWindowDC::DoGetTextExtent( const wxString &string, wxCoord *width, wxCoord *height, 1614 wxCoord *descent, wxCoord *externalLeading, 1615 wxFont *font ) const 1616{ 1617 wxCHECK_RET( Ok(), wxT("invalid dc") ); 1618 1619 if (string.empty()) 1620 { 1621 if (width) (*width) = 0; 1622 if (height) (*height) = 0; 1623 return; 1624 } 1625 1626#if wxUSE_UNICODE 1627 PangoLayout *layout = pango_layout_new( m_context ); 1628 1629 if (font) 1630 pango_layout_set_font_description( layout, font->GetNativeFontInfo()->description ); 1631 else 1632 pango_layout_set_font_description(layout, m_fontdesc); 1633 1634 const wxCharBuffer data = wxConvUTF8.cWC2MB( string ); 1635 pango_layout_set_text(layout, (const char*) data, strlen( (const char*) data )); 1636 1637 // Measure text. 1638 int w,h; 1639 pango_layout_get_pixel_size(layout, &w, &h); 1640 1641 if (width) (*width) = (wxCoord) w; 1642 if (height) (*height) = (wxCoord) h; 1643 if (descent) 1644 { 1645 // Do something about metrics here. TODO. 1646 (*descent) = 0; 1647 } 1648 if (externalLeading) (*externalLeading) = 0; // ?? 1649 1650 g_object_unref( G_OBJECT( layout ) ); 1651#else 1652 wxFont fontToUse = m_font; 1653 if (font) fontToUse = *font; 1654 1655 wxCHECK_RET( fontToUse.Ok(), wxT("invalid font") ); 1656 1657 XFontStruct *xfont = (XFontStruct*) fontToUse.GetFontStruct( m_scaleY, m_display ); 1658 1659 wxCHECK_RET( xfont, wxT("invalid font") ); 1660 1661 int direction, ascent, descent2; 1662 XCharStruct overall; 1663 1664 XTextExtents( xfont, (char*) string.c_str(), string.length(), &direction, 1665 &ascent, &descent2, &overall); 1666 1667 if (width) 1668 *width = (wxCoord)( overall.width / m_scaleX ); 1669 if (height) 1670 *height = (wxCoord)((ascent + descent2) / m_scaleY ); 1671 if (descent) 1672 *descent = (wxCoord)(descent2 / m_scaleY ); 1673 if (externalLeading) 1674 *externalLeading = 0; // ?? 1675#endif 1676} 1677 1678wxCoord wxWindowDC::GetCharWidth() const 1679{ 1680 wxCHECK_MSG( Ok(), 0, wxT("invalid dc") ); 1681 1682#if wxUSE_UNICODE 1683 PangoLayout *layout = pango_layout_new( m_context ); 1684 1685 if (m_fontdesc) 1686 pango_layout_set_font_description(layout, m_fontdesc); 1687 else 1688 pango_layout_set_font_description(layout, this->GetFont().GetNativeFontInfo()->description); 1689 1690 pango_layout_set_text(layout, "H", 1 ); 1691 int w,h; 1692 pango_layout_get_pixel_size(layout, &w, &h); 1693 g_object_unref( G_OBJECT( layout ) ); 1694 1695 return w; 1696#else 1697 wxCHECK_MSG( m_font.Ok(), 0, wxT("invalid font") ); 1698 1699 XFontStruct *xfont = (XFontStruct*) m_font.GetFontStruct( m_scaleY, m_display ); 1700 1701 wxCHECK_MSG( xfont, 0, wxT("invalid font") ); 1702 1703 int direction, ascent, descent; 1704 XCharStruct overall; 1705 1706 XTextExtents( xfont, "H", 1, &direction, &ascent, &descent, &overall ); 1707 1708 return (wxCoord)(overall.width / m_scaleX); 1709#endif 1710} 1711 1712wxCoord wxWindowDC::GetCharHeight() const 1713{ 1714 wxCHECK_MSG( Ok(), 0, wxT("invalid dc") ); 1715 1716#if wxUSE_UNICODE 1717 PangoLayout *layout = pango_layout_new( m_context ); 1718 1719 if (m_fontdesc) 1720 pango_layout_set_font_description(layout, m_fontdesc); 1721 else 1722 pango_layout_set_font_description(layout, this->GetFont().GetNativeFontInfo()->description); 1723 1724 pango_layout_set_text(layout, "H", 1 ); 1725 int w,h; 1726 pango_layout_get_pixel_size(layout, &w, &h); 1727 g_object_unref( G_OBJECT( layout ) ); 1728 1729 return h; 1730#else 1731 wxCHECK_MSG( m_font.Ok(), 0, wxT("invalid font") ); 1732 1733 XFontStruct *xfont = (XFontStruct*) m_font.GetFontStruct( m_scaleY, m_display ); 1734 1735 wxCHECK_MSG( xfont, 0, wxT("invalid font") ); 1736 1737 int direction, ascent, descent; 1738 XCharStruct overall; 1739 1740 XTextExtents( xfont, "H", 1, &direction, &ascent, &descent, &overall ); 1741 1742 return (wxCoord)((ascent+descent) / m_scaleY); 1743#endif 1744} 1745 1746void wxWindowDC::Clear() 1747{ 1748 wxCHECK_RET( Ok(), wxT("invalid window dc") ); 1749 1750 if (!m_window) return; 1751 1752 /* - we either are a memory dc or have a window as the 1753 owner. anything else shouldn't happen. 1754 - we don't use gdk_window_clear() as we don't set 1755 the window's background colour anymore. it is too 1756 much pain to keep the DC's and the window's back- 1757 ground colour in synch. */ 1758 1759 if (m_owner) 1760 { 1761 int width,height; 1762 m_owner->GetSize( &width, &height ); 1763 XFillRectangle( (Display*) m_display, (Window) m_window, (GC) m_bgGC, 0, 0, width, height ); 1764 return; 1765 } 1766 1767 if (m_isMemDC) 1768 { 1769 int width,height; 1770 GetSize( &width, &height ); 1771 XFillRectangle( (Display*) m_display, (Window) m_window, (GC) m_bgGC, 0, 0, width, height ); 1772 return; 1773 } 1774} 1775 1776void wxWindowDC::SetFont( const wxFont &font ) 1777{ 1778 wxCHECK_RET( Ok(), wxT("invalid dc") ); 1779 1780 m_font = font; 1781 1782#if wxUSE_UNICODE 1783 m_fontdesc = font.GetNativeFontInfo()->description; 1784#endif 1785} 1786 1787void wxWindowDC::SetPen( const wxPen &pen ) 1788{ 1789 wxCHECK_RET( Ok(), wxT("invalid window dc") ); 1790 1791 if (m_pen == pen) return; 1792 1793 m_pen = pen; 1794 1795 if (!m_pen.Ok()) return; 1796 1797 if (!m_window) return; 1798 1799 int width = m_pen.GetWidth(); 1800 if (width <= 0) 1801 { 1802 // CMB: if width is non-zero scale it with the dc 1803 width = 1; 1804 } 1805 else 1806 { 1807 // X doesn't allow different width in x and y and so we take 1808 // the average 1809 double w = 0.5 + 1810 ( fabs((double) XLOG2DEVREL(width)) + 1811 fabs((double) YLOG2DEVREL(width)) ) / 2.0; 1812 width = (int)w; 1813 } 1814 1815 static const wxX11Dash dotted[] = {1, 1}; 1816 static const wxX11Dash short_dashed[] = {2, 2}; 1817 static const wxX11Dash long_dashed[] = {2, 4}; 1818 static const wxX11Dash dotted_dashed[] = {3, 3, 1, 3}; 1819 1820 // We express dash pattern in pen width unit, so we are 1821 // independent of zoom factor and so on... 1822 int req_nb_dash; 1823 const wxX11Dash *req_dash; 1824 1825 int lineStyle = LineSolid; 1826 switch (m_pen.GetStyle()) 1827 { 1828 case wxUSER_DASH: 1829 { 1830 lineStyle = LineOnOffDash; 1831 req_nb_dash = m_pen.GetDashCount(); 1832 req_dash = (wxX11Dash*)m_pen.GetDash(); 1833 break; 1834 } 1835 case wxDOT: 1836 { 1837 lineStyle = LineOnOffDash; 1838 req_nb_dash = 2; 1839 req_dash = dotted; 1840 break; 1841 } 1842 case wxLONG_DASH: 1843 { 1844 lineStyle = LineOnOffDash; 1845 req_nb_dash = 2; 1846 req_dash = long_dashed; 1847 break; 1848 } 1849 case wxSHORT_DASH: 1850 { 1851 lineStyle = LineOnOffDash; 1852 req_nb_dash = 2; 1853 req_dash = short_dashed; 1854 break; 1855 } 1856 case wxDOT_DASH: 1857 { 1858// lineStyle = LineDoubleDash; 1859 lineStyle = LineOnOffDash; 1860 req_nb_dash = 4; 1861 req_dash = dotted_dashed; 1862 break; 1863 } 1864 1865 case wxTRANSPARENT: 1866 case wxSTIPPLE_MASK_OPAQUE: 1867 case wxSTIPPLE: 1868 case wxSOLID: 1869 default: 1870 { 1871 lineStyle = LineSolid; 1872 req_dash = (wxX11Dash*)NULL; 1873 req_nb_dash = 0; 1874 break; 1875 } 1876 } 1877 1878 int capStyle = CapRound; 1879 switch (m_pen.GetCap()) 1880 { 1881 case wxCAP_PROJECTING: { capStyle = CapProjecting; break; } 1882 case wxCAP_BUTT: { capStyle = CapButt; break; } 1883 case wxCAP_ROUND: 1884 default: 1885 { 1886 if (width <= 1) 1887 { 1888 width = 0; 1889 capStyle = CapNotLast; 1890 } 1891 else 1892 { 1893 capStyle = CapRound; 1894 } 1895 break; 1896 } 1897 } 1898 1899 int joinStyle = JoinRound; 1900 switch (m_pen.GetJoin()) 1901 { 1902 case wxJOIN_BEVEL: { joinStyle = JoinBevel; break; } 1903 case wxJOIN_MITER: { joinStyle = JoinMiter; break; } 1904 case wxJOIN_ROUND: 1905 default: { joinStyle = JoinRound; break; } 1906 } 1907 1908 XSetLineAttributes( (Display*) m_display, (GC) m_penGC, width, lineStyle, capStyle, joinStyle ); 1909 1910 m_pen.GetColour().CalcPixel( m_cmap ); 1911 XSetForeground( (Display*) m_display, (GC) m_penGC, m_pen.GetColour().GetPixel() ); 1912} 1913 1914void wxWindowDC::SetBrush( const wxBrush &brush ) 1915{ 1916 wxCHECK_RET( Ok(), wxT("invalid window dc") ); 1917 1918 if (m_brush == brush) return; 1919 1920 m_brush = brush; 1921 1922 if (!m_brush.Ok()) return; 1923 1924 if (!m_window) return; 1925 1926 m_brush.GetColour().CalcPixel( m_cmap ); 1927 XSetForeground( (Display*) m_display, (GC) m_brushGC, m_brush.GetColour().GetPixel() ); 1928 1929 XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillSolid ); 1930 1931 if ((m_brush.GetStyle() == wxSTIPPLE) && (m_brush.GetStipple()->Ok())) 1932 { 1933 if (m_brush.GetStipple()->GetPixmap()) 1934 { 1935 XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillTiled ); 1936 XSetTile( (Display*) m_display, (GC) m_brushGC, (Pixmap) m_brush.GetStipple()->GetPixmap() ); 1937 } 1938 else 1939 { 1940 XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillStippled ); 1941 XSetStipple( (Display*) m_display, (GC) m_brushGC, (Pixmap) m_brush.GetStipple()->GetBitmap() ); 1942 } 1943 } 1944 1945 if ((m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE) && (m_brush.GetStipple()->GetMask())) 1946 { 1947 XSetFillStyle( (Display*) m_display, (GC) m_textGC, FillOpaqueStippled ); 1948 XSetStipple( (Display*) m_display, (GC) m_textGC, (Pixmap) m_brush.GetStipple()->GetMask()->GetBitmap() ); 1949 } 1950 1951 if (m_brush.IsHatch()) 1952 { 1953 XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillStippled ); 1954 int num = m_brush.GetStyle() - wxBDIAGONAL_HATCH; 1955 XSetStipple( (Display*) m_display, (GC) m_brushGC, hatches[num] ); 1956 } 1957} 1958 1959void wxWindowDC::SetBackground( const wxBrush &brush ) 1960{ 1961 /* CMB 21/7/98: Added SetBackground. Sets background brush 1962 * for Clear() and bg colour for shapes filled with cross-hatch brush */ 1963 1964 wxCHECK_RET( Ok(), wxT("invalid window dc") ); 1965 1966 if (m_backgroundBrush == brush) return; 1967 1968 m_backgroundBrush = brush; 1969 1970 if (!m_backgroundBrush.Ok()) return; 1971 1972 if (!m_window) return; 1973 1974 m_backgroundBrush.GetColour().CalcPixel( m_cmap ); 1975 XSetBackground( (Display*) m_display, (GC) m_brushGC, m_backgroundBrush.GetColour().GetPixel() ); 1976 XSetBackground( (Display*) m_display, (GC) m_penGC, m_backgroundBrush.GetColour().GetPixel() ); 1977 XSetBackground( (Display*) m_display, (GC) m_bgGC, m_backgroundBrush.GetColour().GetPixel() ); 1978 XSetForeground( (Display*) m_display, (GC) m_bgGC, m_backgroundBrush.GetColour().GetPixel() ); 1979 1980 XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillSolid ); 1981 1982 if ((m_backgroundBrush.GetStyle() == wxSTIPPLE) && (m_backgroundBrush.GetStipple()->Ok())) 1983 { 1984 if (m_backgroundBrush.GetStipple()->GetPixmap()) 1985 { 1986 XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillTiled ); 1987 XSetTile( (Display*) m_display, (GC) m_bgGC, (Pixmap) m_backgroundBrush.GetStipple()->GetPixmap() ); 1988 } 1989 else 1990 { 1991 XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillStippled ); 1992 XSetStipple( (Display*) m_display, (GC) m_bgGC, (Pixmap) m_backgroundBrush.GetStipple()->GetBitmap() ); 1993 } 1994 } 1995 1996 if (m_backgroundBrush.IsHatch()) 1997 { 1998 XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillStippled ); 1999 int num = m_backgroundBrush.GetStyle() - wxBDIAGONAL_HATCH; 2000 XSetStipple( (Display*) m_display, (GC) m_bgGC, hatches[num] ); 2001 } 2002} 2003 2004void wxWindowDC::SetLogicalFunction( int function ) 2005{ 2006 wxCHECK_RET( Ok(), wxT("invalid dc") ); 2007 2008 int x_function; 2009 2010 if (m_logicalFunction == function) 2011 return; 2012 2013 // VZ: shouldn't this be a CHECK? 2014 if (!m_window) 2015 return; 2016 2017 switch (function) 2018 { 2019 case wxCLEAR: 2020 x_function = GXclear; 2021 break; 2022 case wxXOR: 2023 x_function = GXxor; 2024 break; 2025 case wxINVERT: 2026 x_function = GXinvert; 2027 break; 2028 case wxOR_REVERSE: 2029 x_function = GXorReverse; 2030 break; 2031 case wxAND_REVERSE: 2032 x_function = GXandReverse; 2033 break; 2034 case wxAND: 2035 x_function = GXand; 2036 break; 2037 case wxOR: 2038 x_function = GXor; 2039 break; 2040 case wxAND_INVERT: 2041 x_function = GXandInverted; 2042 break; 2043 case wxNO_OP: 2044 x_function = GXnoop; 2045 break; 2046 case wxNOR: 2047 x_function = GXnor; 2048 break; 2049 case wxEQUIV: 2050 x_function = GXequiv; 2051 break; 2052 case wxSRC_INVERT: 2053 x_function = GXcopyInverted; 2054 break; 2055 case wxOR_INVERT: 2056 x_function = GXorInverted; 2057 break; 2058 case wxNAND: 2059 x_function = GXnand; 2060 break; 2061 case wxSET: 2062 x_function = GXset; 2063 break; 2064 case wxCOPY: 2065 default: 2066 x_function = GXcopy; 2067 break; 2068 } 2069 2070 XSetFunction( (Display*) m_display, (GC) m_penGC, x_function ); 2071 XSetFunction( (Display*) m_display, (GC) m_brushGC, x_function ); 2072 2073 // to stay compatible with wxMSW, we don't apply ROPs to the text 2074 // operations (i.e. DrawText/DrawRotatedText). 2075 // True, but mono-bitmaps use the m_textGC and they use ROPs as well. 2076 XSetFunction( (Display*) m_display, (GC) m_textGC, x_function ); 2077 2078 m_logicalFunction = function; 2079} 2080 2081void wxWindowDC::SetTextForeground( const wxColour &col ) 2082{ 2083 wxCHECK_RET( Ok(), wxT("invalid window dc") ); 2084 2085 // don't set m_textForegroundColour to an invalid colour as we'd crash 2086 // later then (we use m_textForegroundColour.GetColor() without checking 2087 // in a few places) 2088 if ( !col.Ok() || (m_textForegroundColour == col) ) 2089 return; 2090 2091 m_textForegroundColour = col; 2092 2093 if (m_window) 2094 { 2095 m_textForegroundColour.CalcPixel( m_cmap ); 2096 XSetForeground( (Display*) m_display, (GC) m_textGC, m_textForegroundColour.GetPixel() ); 2097 } 2098} 2099 2100void wxWindowDC::SetTextBackground( const wxColour &col ) 2101{ 2102 wxCHECK_RET( Ok(), wxT("invalid window dc") ); 2103 2104 // same as above 2105 if ( !col.Ok() || (m_textBackgroundColour == col) ) 2106 return; 2107 2108 m_textBackgroundColour = col; 2109 2110 if (m_window) 2111 { 2112 m_textBackgroundColour.CalcPixel( m_cmap ); 2113 XSetBackground( (Display*) m_display, (GC) m_textGC, m_textBackgroundColour.GetPixel() ); 2114 } 2115} 2116 2117void wxWindowDC::SetBackgroundMode( int mode ) 2118{ 2119 wxCHECK_RET( Ok(), wxT("invalid window dc") ); 2120 2121 m_backgroundMode = mode; 2122 2123#if wxUSE_NANOX 2124 GrSetGCUseBackground((GC) m_textGC, mode == wxTRANSPARENT ? FALSE : TRUE); 2125#endif 2126 2127 if (!m_window) return; 2128 2129 // CMB 21/7/98: fill style of cross-hatch brushes is affected by 2130 // transparent/solid background mode 2131 2132 if (m_brush.GetStyle() != wxSOLID && m_brush.GetStyle() != wxTRANSPARENT) 2133 { 2134 XSetFillStyle( (Display*) m_display, (GC) m_brushGC, 2135 (m_backgroundMode == wxTRANSPARENT) ? FillStippled : FillOpaqueStippled ); 2136 } 2137} 2138 2139void wxWindowDC::SetPalette( const wxPalette& palette ) 2140{ 2141#if 0 2142 if (m_window) 2143 { 2144 if (palette.Ok()) 2145 /* Use GetXColormap */ 2146 XSetWindowColormap ((Display*) m_display, (Window) m_window->GetXWindow(), 2147 (Colormap) palette.GetXColormap()); 2148 else 2149 /* Use wxGetMainColormap */ 2150 XSetWindowColormap ((Display*) m_display, (Window) m_window->GetXWindow(), 2151 (Colormap) wxTheApp->GetMainColormap(m_display)); 2152 } 2153#endif 2154} 2155 2156void wxWindowDC::DoSetClippingRegion( wxCoord x, wxCoord y, wxCoord width, wxCoord height ) 2157{ 2158 wxCHECK_RET( Ok(), wxT("invalid window dc") ); 2159 2160 if (!m_window) return; 2161 2162 if (width <= 0) 2163 width = 1; 2164 2165 if (height <= 0) 2166 height = 1; 2167 2168 wxRect rect; 2169 rect.x = XLOG2DEV(x); 2170 rect.y = YLOG2DEV(y); 2171 rect.width = XLOG2DEVREL(width); 2172 rect.height = YLOG2DEVREL(height); 2173 2174 if (!m_currentClippingRegion.IsNull()) 2175 m_currentClippingRegion.Intersect( rect ); 2176 else 2177 m_currentClippingRegion.Union( rect ); 2178 2179#if USE_PAINT_REGION 2180 if (!m_paintClippingRegion.IsNull()) 2181 m_currentClippingRegion.Intersect( m_paintClippingRegion ); 2182#endif 2183 2184 wxCoord xx, yy, ww, hh; 2185 m_currentClippingRegion.GetBox( xx, yy, ww, hh ); 2186 wxDC::DoSetClippingRegion( xx, yy, ww, hh ); 2187 2188 XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() ); 2189 XSetRegion( (Display*) m_display, (GC) m_brushGC, (Region) m_currentClippingRegion.GetX11Region() ); 2190 XSetRegion( (Display*) m_display, (GC) m_textGC, (Region) m_currentClippingRegion.GetX11Region() ); 2191 XSetRegion( (Display*) m_display, (GC) m_bgGC, (Region) m_currentClippingRegion.GetX11Region() ); 2192} 2193 2194void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion& region ) 2195{ 2196 wxCHECK_RET( Ok(), wxT("invalid window dc") ); 2197 2198 if (region.Empty()) 2199 { 2200 DestroyClippingRegion(); 2201 return; 2202 } 2203 2204 if (!m_window) return; 2205 2206 if (!m_currentClippingRegion.IsNull()) 2207 m_currentClippingRegion.Intersect( region ); 2208 else 2209 m_currentClippingRegion.Union( region ); 2210 2211#if USE_PAINT_REGION 2212 if (!m_paintClippingRegion.IsNull()) 2213 m_currentClippingRegion.Intersect( m_paintClippingRegion ); 2214#endif 2215 2216 wxCoord xx, yy, ww, hh; 2217 m_currentClippingRegion.GetBox( xx, yy, ww, hh ); 2218 wxDC::DoSetClippingRegion( xx, yy, ww, hh ); 2219 2220 XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() ); 2221 XSetRegion( (Display*) m_display, (GC) m_brushGC, (Region) m_currentClippingRegion.GetX11Region() ); 2222 XSetRegion( (Display*) m_display, (GC) m_textGC, (Region) m_currentClippingRegion.GetX11Region() ); 2223 XSetRegion( (Display*) m_display, (GC) m_bgGC, (Region) m_currentClippingRegion.GetX11Region() ); 2224} 2225 2226void wxWindowDC::DestroyClippingRegion() 2227{ 2228 wxCHECK_RET( Ok(), wxT("invalid window dc") ); 2229 2230 wxDC::DestroyClippingRegion(); 2231 2232 m_currentClippingRegion.Clear(); 2233 2234#if USE_PAINT_REGION 2235 if (!m_paintClippingRegion.IsEmpty()) 2236 m_currentClippingRegion.Union( m_paintClippingRegion ); 2237#endif 2238 2239 if (!m_window) return; 2240 2241 if (m_currentClippingRegion.IsEmpty()) 2242 { 2243 XSetClipMask( (Display*) m_display, (GC) m_penGC, None ); 2244 XSetClipMask( (Display*) m_display, (GC) m_brushGC, None ); 2245 XSetClipMask( (Display*) m_display, (GC) m_textGC, None ); 2246 XSetClipMask( (Display*) m_display, (GC) m_bgGC, None ); 2247 } 2248 else 2249 { 2250 XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() ); 2251 XSetRegion( (Display*) m_display, (GC) m_brushGC, (Region) m_currentClippingRegion.GetX11Region() ); 2252 XSetRegion( (Display*) m_display, (GC) m_textGC, (Region) m_currentClippingRegion.GetX11Region() ); 2253 XSetRegion( (Display*) m_display, (GC) m_bgGC, (Region) m_currentClippingRegion.GetX11Region() ); 2254 } 2255} 2256 2257void wxWindowDC::Destroy() 2258{ 2259 if (m_penGC) wxFreePoolGC( (GC) m_penGC ); 2260 m_penGC = NULL; 2261 if (m_brushGC) wxFreePoolGC( (GC) m_brushGC ); 2262 m_brushGC = NULL; 2263 if (m_textGC) wxFreePoolGC( (GC) m_textGC ); 2264 m_textGC = NULL; 2265 if (m_bgGC) wxFreePoolGC( (GC) m_bgGC ); 2266 m_bgGC = NULL; 2267} 2268 2269void wxWindowDC::ComputeScaleAndOrigin() 2270{ 2271 /* CMB: copy scale to see if it changes */ 2272 double origScaleX = m_scaleX; 2273 double origScaleY = m_scaleY; 2274 2275 wxDC::ComputeScaleAndOrigin(); 2276 2277 /* CMB: if scale has changed call SetPen to recalulate the line width */ 2278 if ((m_scaleX != origScaleX || m_scaleY != origScaleY) && 2279 (m_pen.Ok())) 2280 { 2281 /* this is a bit artificial, but we need to force wxDC to think 2282 the pen has changed */ 2283 wxPen pen = m_pen; 2284 m_pen = wxNullPen; 2285 SetPen( pen ); 2286 } 2287} 2288 2289wxSize wxWindowDC::GetPPI() const 2290{ 2291 return wxSize(100, 100); 2292} 2293 2294int wxWindowDC::GetDepth() const 2295{ 2296 wxFAIL_MSG(wxT("not implemented")); 2297 2298 return -1; 2299} 2300 2301//----------------------------------------------------------------------------- 2302// wxClientDC 2303//----------------------------------------------------------------------------- 2304 2305IMPLEMENT_DYNAMIC_CLASS(wxClientDC, wxWindowDC) 2306 2307wxClientDC::wxClientDC( wxWindow *window ) 2308 : wxWindowDC( window ) 2309{ 2310 wxCHECK_RET( window, _T("NULL window in wxClientDC::wxClientDC") ); 2311 2312 m_window = (WXWindow*) window->GetClientAreaWindow(); 2313 2314 // Adjust the client area when the wxWindow is not using 2 X11 windows. 2315 if (m_window == (WXWindow*) window->GetMainWindow()) 2316 { 2317 wxPoint ptOrigin = window->GetClientAreaOrigin(); 2318 SetDeviceOrigin(ptOrigin.x, ptOrigin.y); 2319 wxSize size = window->GetClientSize(); 2320 SetClippingRegion(wxPoint(0, 0), size); 2321 } 2322} 2323 2324void wxClientDC::DoGetSize(int *width, int *height) const 2325{ 2326 wxCHECK_RET( m_owner, _T("GetSize() doesn't work without window") ); 2327 2328 m_owner->GetClientSize( width, height ); 2329} 2330 2331// ---------------------------------------------------------------------------- 2332// wxPaintDC 2333// ---------------------------------------------------------------------------- 2334 2335IMPLEMENT_DYNAMIC_CLASS(wxPaintDC, wxClientDC) 2336 2337wxPaintDC::wxPaintDC(wxWindow* window) 2338 : wxClientDC(window) 2339{ 2340#if USE_PAINT_REGION 2341 if (!window->GetClipPaintRegion()) 2342 return; 2343 2344 m_paintClippingRegion = window->GetUpdateRegion(); 2345 Region region = (Region) m_paintClippingRegion.GetX11Region(); 2346 if (region) 2347 { 2348 m_currentClippingRegion.Union( m_paintClippingRegion ); 2349 2350 XSetRegion( (Display*) m_display, (GC) m_penGC, region ); 2351 XSetRegion( (Display*) m_display, (GC) m_brushGC, region ); 2352 XSetRegion( (Display*) m_display, (GC) m_textGC, region ); 2353 XSetRegion( (Display*) m_display, (GC) m_bgGC, region ); 2354 } 2355#endif // USE_PAINT_REGION 2356} 2357 2358// ---------------------------------------------------------------------------- 2359// wxDCModule 2360// ---------------------------------------------------------------------------- 2361 2362class wxDCModule : public wxModule 2363{ 2364public: 2365 // we must be cleaned up before wxDisplayModule which closes the global 2366 // display 2367 wxDCModule() 2368 { 2369 AddDependency(wxClassInfo::FindClass(_T("wxX11DisplayModule"))); 2370 } 2371 2372 bool OnInit() { wxInitGCPool(); return true; } 2373 void OnExit() { wxCleanUpGCPool(); } 2374 2375private: 2376 DECLARE_DYNAMIC_CLASS(wxDCModule) 2377}; 2378 2379IMPLEMENT_DYNAMIC_CLASS(wxDCModule, wxModule) 2380 2381