1///////////////////////////////////////////////////////////////////////////// 2// Name: src/motif/dcclient.cpp 3// Purpose: wxClientDC class 4// Author: Julian Smart 5// Modified by: 6// Created: 01/02/97 7// RCS-ID: $Id: dcclient.cpp 42787 2006-10-30 22:58:02Z VZ $ 8// Copyright: (c) Julian Smart 9// Licence: wxWindows licence 10///////////////////////////////////////////////////////////////////////////// 11 12/* 13 About pens, brushes, and the m_autoSetting flag: 14 15 Under X, pens and brushes control some of the same X drawing 16 parameters. Therefore, it is impossible to independently maintain 17 the current pen and the current brush. Also, some settings depend on 18 the current logical function. The m_currentFill, etc. instance 19 variables remember state across the brush and pen. 20 21 Since pens are used more than brushes, the m_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 m_autoSetting includes 0x2, then the 24 pens color may need to be set based on XOR. 25 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. 29*/ 30 31// ============================================================================ 32// declarations 33// ============================================================================ 34 35// ---------------------------------------------------------------------------- 36// headers 37// ---------------------------------------------------------------------------- 38 39// For compilers that support precompilation, includes "wx.h". 40#include "wx/wxprec.h" 41 42#include "wx/dcclient.h" 43 44#ifndef WX_PRECOMP 45 #include "wx/log.h" 46 #include "wx/app.h" 47 #include "wx/window.h" 48 #include "wx/dcmemory.h" 49 #include "wx/math.h" 50 #include "wx/image.h" 51#endif 52 53#ifdef __VMS__ 54#pragma message disable nosimpint 55#endif 56#include <Xm/Xm.h> 57#ifdef __VMS__ 58#pragma message enable nosimpint 59#endif 60 61#include "wx/motif/private.h" 62 63#ifdef __EMX__ 64 #include <float.h> // for M_PI 65#endif // __EMX__ 66 67#include "bdiag.xbm" 68#include "fdiag.xbm" 69#include "cdiag.xbm" 70#include "horiz.xbm" 71#include "verti.xbm" 72#include "cross.xbm" 73 74static Pixmap bdiag, cdiag, fdiag, cross, horiz, verti; 75 76// ---------------------------------------------------------------------------- 77// constants 78// ---------------------------------------------------------------------------- 79 80// Fudge factor (VZ: what??) 81#define WX_GC_CF 1 82 83// ---------------------------------------------------------------------------- 84// macros 85// ---------------------------------------------------------------------------- 86 87IMPLEMENT_DYNAMIC_CLASS(wxClientDC, wxWindowDC) 88IMPLEMENT_DYNAMIC_CLASS(wxPaintDC, wxWindowDC) 89IMPLEMENT_DYNAMIC_CLASS(wxWindowDC, wxDC) 90 91#ifndef IS_HATCH 92 // IS_HATCH exists for WXWIN_COMPATIBILITY_2_4 only 93 // but wxMotif needs it for its internals here 94 #define IS_HATCH(s) ((s)>=wxFIRST_HATCH && (s)<=wxLAST_HATCH) 95#endif 96 97// FIXME: left over after removal of wxDC::GetOptimization() 98#define GET_OPTIMIZATION false 99 100// ---------------------------------------------------------------------------- 101// prototypes 102// ---------------------------------------------------------------------------- 103 104static void XCopyRemote(Display *src_display, Display *dest_display, 105 Drawable src, Drawable dest, 106 GC destgc, 107 int srcx, int srcy, 108 unsigned int w, unsigned int h, 109 int destx, int desty, 110 bool more, XImage **cache); 111 112// ============================================================================ 113// implementation 114// ============================================================================ 115 116/* 117 * compare two doubles and return the larger rounded 118 * to the nearest int 119 */ 120static int roundmax(double a, double b) 121{ 122 return (int)((a > b ? a : b) + 0.5); 123} 124 125/* 126 * compare two doubles and return the smaller rounded 127 * to the nearest int 128 */ 129static int roundmin(double a, double b) 130{ 131 return (int)((a < b ? a : b) - 0.5); 132} 133 134 135// ---------------------------------------------------------------------------- 136// wxWindowDC 137// ---------------------------------------------------------------------------- 138 139void wxWindowDC::Init() 140{ 141 m_gc = (WXGC) 0; 142 m_gcBacking = (WXGC) 0; 143 m_window = NULL; 144 m_backgroundPixel = -1; 145 m_currentPenWidth = 1; 146 m_currentPenJoin = -1; 147 m_currentPenDashCount = -1; 148 m_currentPenDash = (wxX11Dash*) NULL; 149 m_currentStyle = -1; 150 m_currentFill = -1; 151 m_colour = wxColourDisplay(); 152 m_display = (WXDisplay*) NULL; 153 m_pixmap = (WXPixmap) 0; 154 m_autoSetting = 0; 155 m_ok = false; 156 m_clipRegion = (WXRegion) 0; 157} 158 159wxWindowDC::wxWindowDC() 160{ 161 Init(); 162} 163 164wxWindowDC::wxWindowDC( wxWindow *window ) 165{ 166 wxASSERT_MSG( (window != (wxWindow*) NULL), "You must pass a valid wxWindow to wxWindowDC/wxClientDC/wxPaintDC constructor." ); 167 168 Init(); 169 170 m_window = window; 171 m_font = window->GetFont(); 172 m_ok = true; 173 174 m_display = window->GetXDisplay(); 175 m_pixmap = window->GetXWindow(); 176 Display* display = (Display*) m_display; 177 178 XSetWindowColormap (display, (Pixmap) m_pixmap, (Colormap) wxTheApp->GetMainColormap(m_display)); 179 180 XGCValues gcvalues; 181 gcvalues.foreground = BlackPixel (display, DefaultScreen (display)); 182 gcvalues.background = WhitePixel (display, DefaultScreen (display)); 183 gcvalues.graphics_exposures = False; 184 gcvalues.subwindow_mode = IncludeInferiors; 185 gcvalues.line_width = 1; 186 m_gc = (WXGC) XCreateGC (display, RootWindow (display, DefaultScreen (display)), 187 GCForeground | GCBackground | GCGraphicsExposures | GCLineWidth | GCSubwindowMode, 188 &gcvalues); 189 190 if (m_window->GetBackingPixmap()) 191 { 192 m_gcBacking = (WXGC) XCreateGC (display, RootWindow (display, 193 DefaultScreen (display)), 194 GCForeground | GCBackground | GCGraphicsExposures | GCLineWidth | GCSubwindowMode, 195 &gcvalues); 196 } 197 198 m_backgroundPixel = gcvalues.background; 199 200 SetBackground(wxBrush(m_window->GetBackgroundColour(), wxSOLID)); 201} 202 203wxWindowDC::~wxWindowDC() 204{ 205 if (m_gc) 206 XFreeGC ((Display*) m_display, (GC) m_gc); 207 m_gc = (WXGC) 0; 208 209 if (m_gcBacking) 210 XFreeGC ((Display*) m_display, (GC) m_gcBacking); 211 m_gcBacking = (WXGC) 0; 212 213 if (m_clipRegion) 214 XDestroyRegion ((Region) m_clipRegion); 215 m_clipRegion = (WXRegion) 0; 216} 217 218extern bool wxDoFloodFill(wxDC *dc, wxCoord x, wxCoord y, 219 const wxColour & col, int style); 220 221bool wxWindowDC::DoFloodFill(wxCoord x, wxCoord y, 222 const wxColour& col, int style) 223{ 224 return wxDoFloodFill(this, x, y, col, style); 225} 226 227bool wxWindowDC::DoGetPixel( wxCoord x1, wxCoord y1, wxColour *col ) const 228{ 229 // Generic (and therefore rather inefficient) method. 230 // Could be improved. 231 wxMemoryDC memdc; 232 wxBitmap bitmap(1, 1); 233 memdc.SelectObject(bitmap); 234 memdc.Blit(0, 0, 1, 1, (wxDC*) this, x1, y1); 235 memdc.SelectObject(wxNullBitmap); 236 wxImage image = bitmap.ConvertToImage(); 237 col->Set(image.GetRed(0, 0), image.GetGreen(0, 0), image.GetBlue(0, 0)); 238 return true; 239} 240 241void wxWindowDC::DoDrawLine( wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2 ) 242{ 243 wxCHECK_RET( Ok(), "invalid dc" ); 244 245 int x1d, y1d, x2d, y2d; 246 247 x1d = XLOG2DEV(x1); 248 y1d = YLOG2DEV(y1); 249 x2d = XLOG2DEV(x2); 250 y2d = YLOG2DEV(y2); 251 252 if (m_autoSetting) 253 SetPen (m_pen); 254 255 XDrawLine ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, x1d, y1d, x2d, y2d); 256 257 if (m_window && m_window->GetBackingPixmap()) 258 XDrawLine ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(), (GC) m_gcBacking, 259 XLOG2DEV_2(x1), YLOG2DEV_2(y1), 260 XLOG2DEV_2(x2), YLOG2DEV_2(y2)); 261 262 CalcBoundingBox(x1, y1); 263 CalcBoundingBox(x2, y2); 264} 265 266void wxWindowDC::DoCrossHair( wxCoord x, wxCoord y ) 267{ 268 wxCHECK_RET( Ok(), "invalid dc" ); 269 270 if (m_autoSetting) 271 SetPen (m_pen); 272 273 int xx = XLOG2DEV (x); 274 int yy = YLOG2DEV (y); 275 int ww, hh; 276 wxDisplaySize (&ww, &hh); 277 XDrawLine ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, 0, yy, 278 ww, yy); 279 XDrawLine ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xx, 0, 280 xx, hh); 281 282 if (m_window && m_window->GetBackingPixmap()) 283 { 284 xx = XLOG2DEV_2 (x); 285 yy = YLOG2DEV_2 (y); 286 XDrawLine ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(), (GC) m_gcBacking, 287 0, yy, 288 ww, yy); 289 XDrawLine ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(), (GC) m_gcBacking, 290 xx, 0, 291 xx, hh); 292 } 293} 294 295void wxWindowDC::DoDrawArc( wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2, wxCoord xc, wxCoord yc ) 296{ 297 wxCHECK_RET( Ok(), "invalid dc" ); 298 299 int xx1 = XLOG2DEV (x1); 300 int yy1 = YLOG2DEV (y1); 301 int xx2 = XLOG2DEV (x2); 302 int yy2 = YLOG2DEV (y2); 303 int xxc = XLOG2DEV (xc); 304 int yyc = YLOG2DEV (yc); 305 int xxc_2 = XLOG2DEV_2 (xc); 306 int yyc_2 = YLOG2DEV_2 (yc); 307 308 wxCoord dx = xx1 - xxc; 309 wxCoord dy = yy1 - yyc; 310 double radius = sqrt ((double)(dx * dx + dy * dy)); 311 wxCoord r = (wxCoord) radius; 312 313 double radius1, radius2; 314 315 if (xx1 == xx2 && yy1 == yy2) 316 { 317 radius1 = 0.0; 318 radius2 = 360.0; 319 } 320 else if (radius == 0.0) 321 radius1 = radius2 = 0.0; 322 else 323 { 324 if (xx1 - xxc == 0) 325 if (yy1 - yyc < 0) 326 radius1 = 90.0; 327 else 328 radius1 = -90.0; 329 else 330 radius1 = -atan2 ((double) (yy1 - yyc), (double) (xx1 - xxc)) * 360.0 / (2 * M_PI); 331 332 if (xx2 - xxc == 0) 333 if (yy2 - yyc < 0) 334 radius2 = 90.0; 335 else 336 radius2 = -90.0; 337 else 338 radius2 = -atan2 ((double) (yy2 - yyc), (double) (xx2 - xxc)) * 360.0 / (2 * M_PI); 339 } 340 radius1 *= 64.0; 341 radius2 *= 64.0; 342 int alpha1 = (int) radius1; 343 int alpha2 = (int) (radius2 - radius1); 344 while (alpha2 <= 0) 345 alpha2 += 360 * 64; 346 while (alpha2 > 360 * 64) 347 alpha2 -= 360 * 64; 348 349 if (m_brush.Ok() && m_brush.GetStyle () != wxTRANSPARENT) 350 { 351 SetBrush (m_brush); 352 XFillArc ((Display*) m_display, (Pixmap) m_pixmap, (GC) (GC) m_gc, 353 xxc - r, yyc - r, 2 * r, 2 * r, alpha1, alpha2); 354 355 if (m_window && m_window->GetBackingPixmap()) 356 XFillArc ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(), (GC) m_gcBacking, 357 xxc_2 - r, yyc_2 - r, 2 * r, 2 * r, alpha1, alpha2); 358 359 } 360 361 if (m_pen.Ok() && m_pen.GetStyle () != wxTRANSPARENT) 362 { 363 if (m_autoSetting) 364 SetPen (m_pen); 365 XDrawArc ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, 366 xxc - r, yyc - r, 2 * r, 2 * r, alpha1, alpha2); 367 368 if (m_window && m_window->GetBackingPixmap()) 369 XDrawArc ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(), (GC) m_gcBacking, 370 xxc_2 - r, yyc_2 - r, 2 * r, 2 * r, alpha1, alpha2); 371 } 372 CalcBoundingBox (x1, y1); 373 CalcBoundingBox (x2, y2); 374} 375 376void wxWindowDC::DoDrawEllipticArc( wxCoord x, wxCoord y, wxCoord width, wxCoord height, double sa, double ea ) 377{ 378 wxCHECK_RET( Ok(), "invalid dc" ); 379 380 int xd, yd, wd, hd; 381 382 xd = XLOG2DEV(x); 383 yd = YLOG2DEV(y); 384 wd = XLOG2DEVREL(width); 385 hd = YLOG2DEVREL(height); 386 387 if (sa>=360 || sa<=-360) sa=sa-int(sa/360)*360; 388 if (ea>=360 || ea<=-360) ea=ea-int(ea/360)*360; 389 int start = int(sa*64); 390 int end = int(ea*64); 391 if (start<0) start+=360*64; 392 if (end <0) end +=360*64; 393 if (end>start) end-=start; 394 else end+=360*64-start; 395 396 if (m_brush.Ok() && m_brush.GetStyle () != wxTRANSPARENT) 397 { 398 m_autoSetting = true; // must be reset 399 400 SetBrush (m_brush); 401 XFillArc ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd, yd, wd, hd, start, end); 402 403 if (m_window && m_window->GetBackingPixmap()) 404 XFillArc ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(), (GC) m_gcBacking, 405 XLOG2DEV_2 (x), YLOG2DEV_2 (y),wd,hd,start,end); 406 } 407 408 if (m_pen.Ok() && m_pen.GetStyle () != wxTRANSPARENT) 409 { 410 if (m_autoSetting) 411 SetPen (m_pen); 412 XDrawArc ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd, yd, wd, hd, start,end); 413 if (m_window && m_window->GetBackingPixmap()) 414 XDrawArc ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(), (GC) m_gcBacking, 415 XLOG2DEV_2 (x), YLOG2DEV_2 (y),wd,hd,start,end); 416 } 417 CalcBoundingBox (x, y); 418 CalcBoundingBox (x + width, y + height); 419} 420 421void wxWindowDC::DoDrawPoint( wxCoord x, wxCoord y ) 422{ 423 wxCHECK_RET( Ok(), "invalid dc" ); 424 425 if (m_pen.Ok() && m_autoSetting) 426 SetPen (m_pen); 427 428 XDrawPoint ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, XLOG2DEV (x), YLOG2DEV (y)); 429 if (m_window && m_window->GetBackingPixmap()) 430 XDrawPoint ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, XLOG2DEV_2 (x), YLOG2DEV_2 (y)); 431 432 CalcBoundingBox (x, y); 433} 434 435void wxWindowDC::DoDrawLines( int n, wxPoint points[], wxCoord xoffset, wxCoord yoffset ) 436{ 437 wxCHECK_RET( Ok(), "invalid dc" ); 438 439 if (m_pen.Ok() && m_pen.GetStyle () != wxTRANSPARENT) 440 { 441 if (m_autoSetting) 442 SetPen (m_pen); 443 444 XPoint *xpoints = new XPoint[n]; 445 int i; 446 447 for (i = 0; i < n; i++) 448 { 449 xpoints[i].x = (short)XLOG2DEV (points[i].x + xoffset); 450 xpoints[i].y = (short)YLOG2DEV (points[i].y + yoffset); 451 } 452 XDrawLines ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xpoints, n, 0); 453 454 if (m_window && m_window->GetBackingPixmap()) 455 { 456 for (i = 0; i < n; i++) 457 { 458 xpoints[i].x = (short)XLOG2DEV_2 (points[i].x + xoffset); 459 xpoints[i].y = (short)YLOG2DEV_2 (points[i].y + yoffset); 460 } 461 XDrawLines ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, xpoints, n, 0); 462 } 463 delete[]xpoints; 464 } 465} 466 467void wxWindowDC::DoDrawPolygon( int n, wxPoint points[], 468 wxCoord xoffset, wxCoord yoffset, int fillStyle ) 469{ 470 wxCHECK_RET( Ok(), "invalid dc" ); 471 472 XPoint *xpoints1 = new XPoint[n + 1]; 473 XPoint *xpoints2 = new XPoint[n + 1]; 474 int i; 475 for (i = 0; i < n; i++) 476 { 477 xpoints1[i].x = (short)XLOG2DEV (points[i].x + xoffset); 478 xpoints1[i].y = (short)YLOG2DEV (points[i].y + yoffset); 479 xpoints2[i].x = (short)XLOG2DEV_2 (points[i].x + xoffset); 480 xpoints2[i].y = (short)YLOG2DEV_2 (points[i].y + yoffset); 481 CalcBoundingBox (points[i].x + xoffset, points[i].y + yoffset); 482 } 483 484 // Close figure for XDrawLines (not needed for XFillPolygon) 485 xpoints1[i].x = xpoints1[0].x; 486 xpoints1[i].y = xpoints1[0].y; 487 xpoints2[i].x = xpoints2[0].x; 488 xpoints2[i].y = xpoints2[0].y; 489 490 if (m_brush.Ok() && m_brush.GetStyle () != wxTRANSPARENT) 491 { 492 SetBrush (m_brush); 493 XSetFillRule ((Display*) m_display, (GC) m_gc, fillStyle == wxODDEVEN_RULE ? EvenOddRule : WindingRule); 494 XFillPolygon ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xpoints1, n, Complex, 0); 495 XSetFillRule ((Display*) m_display, (GC) m_gc, EvenOddRule); // default mode 496 if (m_window && m_window->GetBackingPixmap()) 497 { 498 XSetFillRule ((Display*) m_display,(GC) m_gcBacking, 499 fillStyle == wxODDEVEN_RULE ? EvenOddRule : WindingRule); 500 XFillPolygon ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, xpoints2, n, Complex, 0); 501 XSetFillRule ((Display*) m_display,(GC) m_gcBacking, EvenOddRule); // default mode 502 } 503 } 504 505 if (m_pen.Ok() && m_pen.GetStyle () != wxTRANSPARENT) 506 { 507 if (m_autoSetting) 508 SetPen (m_pen); 509 XDrawLines ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xpoints1, n + 1, 0); 510 511 if (m_window && m_window->GetBackingPixmap()) 512 XDrawLines ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, xpoints2, n + 1, 0); 513 } 514 515 delete[]xpoints1; 516 delete[]xpoints2; 517} 518 519void wxWindowDC::DoDrawRectangle( wxCoord x, wxCoord y, wxCoord width, wxCoord height ) 520{ 521 wxCHECK_RET( Ok(), "invalid dc" ); 522 523 int xd, yd, wfd, hfd, wd, hd; 524 525 xd = XLOG2DEV(x); 526 yd = YLOG2DEV(y); 527 wfd = XLOG2DEVREL(width); 528 wd = wfd - WX_GC_CF; 529 hfd = YLOG2DEVREL(height); 530 hd = hfd - WX_GC_CF; 531 532 if (wfd == 0 || hfd == 0) return; 533 if (wd < 0) { wd = - wd; xd = xd - wd; } 534 if (hd < 0) { hd = - hd; yd = yd - hd; } 535 536 if (m_brush.Ok() && m_brush.GetStyle () != wxTRANSPARENT) 537 { 538 SetBrush (m_brush); 539 XFillRectangle ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd, yd, wfd, hfd); 540 541 if (m_window && m_window->GetBackingPixmap()) 542 XFillRectangle ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, 543 XLOG2DEV_2 (x), YLOG2DEV_2 (y), 544 wfd, hfd); 545 } 546 547 if (m_pen.Ok() && m_pen.GetStyle () != wxTRANSPARENT) 548 { 549 if (m_autoSetting) 550 SetPen (m_pen); 551 XDrawRectangle ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd, yd, wd, hd); 552 553 if (m_window && m_window->GetBackingPixmap()) 554 XDrawRectangle ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, 555 XLOG2DEV_2 (x), YLOG2DEV_2 (y), 556 wd, hd); 557 } 558 CalcBoundingBox (x, y); 559 CalcBoundingBox (x + width, y + height); 560} 561 562void wxWindowDC::DoDrawRoundedRectangle( wxCoord x, wxCoord y, wxCoord width, wxCoord height, double radius ) 563{ 564 wxCHECK_RET( Ok(), "invalid dc" ); 565 566 // If radius is negative, it's a proportion of the smaller dimension. 567 568 if (radius < 0.0) radius = - radius * ((width < height) ? width : height); 569 570 int xd = XLOG2DEV (x); 571 int yd = YLOG2DEV (y); 572 int rd = XLOG2DEVREL ((long) radius); 573 int wd = XLOG2DEVREL (width) - WX_GC_CF; 574 int hd = YLOG2DEVREL (height) - WX_GC_CF; 575 576 int rw_d = rd * 2; 577 int rh_d = rw_d; 578 579 // If radius is zero use DrawRectangle() instead to avoid 580 // X drawing errors with small radii 581 if (rd == 0) 582 { 583 DrawRectangle( x, y, width, height ); 584 return; 585 } 586 587 // Draw nothing if transformed w or h is 0 588 if (wd == 0 || hd == 0) return; 589 590 // CMB: adjust size if outline is drawn otherwise the result is 591 // 1 pixel too wide and high 592 if (m_pen.GetStyle() != wxTRANSPARENT) 593 { 594 wd--; 595 hd--; 596 } 597 598 // CMB: ensure dd is not larger than rectangle otherwise we 599 // get an hour glass shape 600 if (rw_d > wd) rw_d = wd; 601 if (rw_d > hd) rw_d = hd; 602 rd = rw_d / 2; 603 604 // For backing pixmap 605 int xd2 = XLOG2DEV_2 (x); 606 int yd2 = YLOG2DEV_2 (y); 607 int rd2 = XLOG2DEVREL ((long) radius); 608 int wd2 = XLOG2DEVREL (width) ; 609 int hd2 = YLOG2DEVREL (height) ; 610 611 int rw_d2 = rd2 * 2; 612 int rh_d2 = rw_d2; 613 614 if (m_brush.Ok() && m_brush.GetStyle () != wxTRANSPARENT) 615 { 616 SetBrush (m_brush); 617 618 XFillRectangle ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd + rd, yd, 619 wd - rw_d, hd); 620 XFillRectangle ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd, yd + rd, 621 wd, hd - rh_d); 622 623 // Arcs start from 3 o'clock, positive angles anticlockwise 624 // Top-left 625 XFillArc ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd, yd, 626 rw_d, rh_d, 90 * 64, 90 * 64); 627 // Top-right 628 XFillArc ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd + wd - rw_d, yd, 629 // rw_d, rh_d, 0, 90 * 64); 630 rw_d, rh_d, 0, 91 * 64); 631 // Bottom-right 632 XFillArc ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd + wd - rw_d, 633 yd + hd - rh_d, 634 // rw_d, rh_d, 270 * 64, 90 * 64); 635 rw_d, rh_d, 269 * 64, 92 * 64); 636 // Bottom-left 637 XFillArc ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd, yd + hd - rh_d, 638 rw_d, rh_d, 180 * 64, 90 * 64); 639 640 if (m_window && m_window->GetBackingPixmap()) 641 { 642 XFillRectangle ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, 643 xd2 + rd2, yd2, wd2 - rw_d2, hd2); 644 XFillRectangle ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, 645 xd2, yd2 + rd2, wd2, hd2 - rh_d2); 646 647 XFillArc ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, 648 xd2, yd2, rw_d2, rh_d2, 90 * 64, 90 * 64); 649 XFillArc ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, 650 xd2 + wd2 - rw_d2, yd2, 651 // rw_d2, rh_d2, 0, 90 * 64); 652 rw_d2, rh_d2, 0, 91 * 64); 653 XFillArc ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, 654 xd2 + wd2 - rw_d2, 655 yd2 + hd2 - rh_d2, 656 // rw_d2, rh_d2, 270 * 64, 90 * 64); 657 rw_d2, rh_d2, 269 * 64, 92 * 64); 658 XFillArc ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, 659 xd2, yd2 + hd2 - rh_d2, 660 rw_d2, rh_d2, 180 * 64, 90 * 64); 661 } 662 } 663 664 if (m_pen.Ok() && m_pen.GetStyle () != wxTRANSPARENT) 665 { 666 SetPen (m_pen); 667 XDrawLine ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd + rd, yd, 668 xd + wd - rd + 1, yd); 669 XDrawLine ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd + rd, yd + hd, 670 xd + wd - rd, yd + hd); 671 672 XDrawLine ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd, yd + rd, 673 xd, yd + hd - rd); 674 XDrawLine ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd + wd, yd + rd, 675 xd + wd, yd + hd - rd + 1); 676 XDrawArc ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd, yd, 677 rw_d, rh_d, 90 * 64, 90 * 64); 678 XDrawArc ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd + wd - rw_d, yd, 679 // rw_d, rh_d, 0, 90 * 64); 680 rw_d, rh_d, 0, 91 * 64); 681 XDrawArc ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd + wd - rw_d, 682 yd + hd - rh_d, 683 rw_d, rh_d, 269 * 64, 92 * 64); 684 XDrawArc ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd, yd + hd - rh_d, 685 rw_d, rh_d, 180 * 64, 90 * 64); 686 687 if (m_window && m_window->GetBackingPixmap()) 688 { 689 XDrawLine ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, 690 xd2 + rd2, yd2, 691 xd2 + wd2 - rd2 + 1, yd2); 692 XDrawLine ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, 693 xd2 + rd2, yd2 + hd2, 694 xd2 + wd2 - rd2, yd2 + hd2); 695 696 XDrawLine ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, 697 xd2, yd2 + rd2, 698 xd2, yd2 + hd2 - rd2); 699 XDrawLine ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, 700 xd2 + wd2, yd2 + rd2, 701 xd2 + wd2, yd2 + hd2 - rd2 + 1); 702 XDrawArc ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, 703 xd2, yd2, 704 rw_d2, rh_d2, 90 * 64, 90 * 64); 705 XDrawArc ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, 706 xd2 + wd2 - rw_d2, yd2, 707 // rw_d2, rh_d2, 0, 90 * 64); 708 rw_d2, rh_d2, 0, 91 * 64); 709 XDrawArc ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, 710 xd2 + wd2 - rw_d2, 711 yd2 + hd2 - rh_d2, 712 rw_d2, rh_d2, 269 * 64, 92 * 64); 713 XDrawArc ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, 714 xd2, yd2 + hd2 - rh_d2, 715 rw_d2, rh_d2, 180 * 64, 90 * 64); 716 } 717 } 718 CalcBoundingBox (x, y); 719 CalcBoundingBox (x + width, y + height); 720} 721 722void wxWindowDC::DoDrawEllipse( wxCoord x, wxCoord y, wxCoord width, wxCoord height ) 723{ 724 wxCHECK_RET( Ok(), "invalid dc" ); 725 726 // Check for negative width and height 727 if (height < 0) 728 { 729 y = y + height; 730 height = - height ; 731 } 732 733 if (width < 0) 734 { 735 x = x + width; 736 width = - width ; 737 } 738 739 static const int angle = 23040; 740 741 int xd, yd, wd, hd; 742 743 xd = XLOG2DEV(x); 744 yd = YLOG2DEV(y); 745 wd = XLOG2DEVREL(width) ; 746 hd = YLOG2DEVREL(height) ; 747 748 if (m_brush.Ok() && m_brush.GetStyle () != wxTRANSPARENT) 749 { 750 SetBrush (m_brush); 751 XFillArc ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd, yd, wd, hd, 0, angle); 752 if (m_window && m_window->GetBackingPixmap()) 753 XFillArc ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, 754 XLOG2DEV_2 (x), YLOG2DEV_2 (y), 755 XLOG2DEVREL (width) - WX_GC_CF, 756 YLOG2DEVREL (height) - WX_GC_CF, 0, angle); 757 } 758 759 if (m_pen.Ok() && m_pen.GetStyle () != wxTRANSPARENT) 760 { 761 if (m_autoSetting) 762 SetPen (m_pen); 763 XDrawArc ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd, yd, wd, hd, 0, angle); 764 if (m_window && m_window->GetBackingPixmap()) 765 XDrawArc ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, 766 XLOG2DEV_2 (x), YLOG2DEV_2 (y), 767 XLOG2DEVREL (width) - WX_GC_CF, 768 YLOG2DEVREL (height) - WX_GC_CF, 0, angle); 769 } 770 CalcBoundingBox (x, y); 771 CalcBoundingBox (x + width, y + height); 772 773} 774 775bool wxWindowDC::CanDrawBitmap() const 776{ 777 wxCHECK_MSG( Ok(), false, "invalid dc" ); 778 779 return true; 780} 781 782// TODO: use scaled Blit e.g. as per John Price's implementation 783// in Contrib/Utilities 784bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, 785 wxCoord width, wxCoord height, 786 wxDC *source, wxCoord xsrc, wxCoord ysrc, 787 int rop, bool useMask, 788 wxCoord xsrcMask, wxCoord ysrcMask ) 789{ 790 wxCHECK_MSG( Ok(), false, "invalid dc" ); 791 792 wxWindowDC* sourceDC = wxDynamicCast(source, wxWindowDC); 793 794 wxASSERT_MSG( sourceDC, "Blit source DC must be wxWindowDC or derived class." ); 795 796 // Be sure that foreground pixels (1) of the Icon will be painted with 797 // foreground colour. [m_textForegroundColour] Background pixels (0) 798 // will be painted with backgound colour (m_textBackgroundColour) 799 // Using ::SetPen is horribly slow, so avoid doing it 800 WXPixel oldBackgroundPixel = -1; 801 WXPixel oldForegroundPixel = -1; 802 803 if (m_textBackgroundColour.Ok()) 804 { 805 oldBackgroundPixel = m_backgroundPixel; 806 WXPixel pixel = m_textBackgroundColour.AllocColour(m_display); 807 808 XSetBackground ((Display*) m_display, (GC) m_gc, pixel); 809 if (m_window && m_window->GetBackingPixmap()) 810 XSetBackground ((Display*) m_display,(GC) m_gcBacking, 811 pixel); 812 } 813 if (m_textForegroundColour.Ok()) 814 { 815 oldForegroundPixel = m_currentColour.GetPixel(); 816 817 if( m_textForegroundColour.GetPixel() <= -1 ) 818 CalculatePixel( m_textForegroundColour, 819 m_textForegroundColour, true); 820 821 WXPixel pixel = m_textForegroundColour.GetPixel(); 822 if (pixel > -1) 823 SetForegroundPixelWithLogicalFunction(pixel); 824 } 825 826 // Do bitmap scaling if necessary 827 828 wxBitmap *scaledBitmap = (wxBitmap*) NULL; 829 Pixmap sourcePixmap = (Pixmap) NULL; 830 double scaleX, scaleY; 831 GetUserScale(& scaleX, & scaleY); 832 bool retVal = false; 833 834 /* TODO: use the mask origin when drawing transparently */ 835 if (xsrcMask == -1 && ysrcMask == -1) 836 { 837 xsrcMask = xsrc; ysrcMask = ysrc; 838 } 839 840 // Sorry, can't scale masks just yet 841 if (!useMask && (scaleX != 1.0 || scaleY != 1.0) && sourceDC->IsKindOf(CLASSINFO(wxMemoryDC))) 842 { 843 wxMemoryDC* memDC = (wxMemoryDC*) sourceDC; 844 wxBitmap& bitmap = memDC->GetBitmap(); 845 846 wxASSERT_MSG( (bitmap.Ok()), "Bad source bitmap in wxWindowDC::Blit"); 847 848 wxImage image = bitmap.ConvertToImage(); 849 if (!image.Ok()) 850 { 851 sourcePixmap = (Pixmap) bitmap.GetDrawable(); 852 } 853 else 854 { 855 int scaledW = (int) (bitmap.GetWidth() * scaleX); 856 int scaledH = (int) (bitmap.GetHeight() * scaleY); 857 858 image = image.Scale(scaledW, scaledH); 859 scaledBitmap = new wxBitmap(image); 860 sourcePixmap = (Pixmap) scaledBitmap->GetDrawable(); 861 } 862 } 863 else 864 sourcePixmap = (Pixmap) sourceDC->m_pixmap; 865 866 if (m_pixmap && sourcePixmap) 867 { 868 /* MATTHEW: [9] */ 869 int orig = m_logicalFunction; 870 871 SetLogicalFunction (rop); 872 873 if (m_display != sourceDC->m_display) 874 { 875 XImage *cache = NULL; 876 877 if (m_window && m_window->GetBackingPixmap()) 878 XCopyRemote((Display*) sourceDC->m_display, (Display*) m_display, 879 (Pixmap) sourcePixmap, (Pixmap) m_window->GetBackingPixmap(), 880 (GC) m_gcBacking, 881 source->LogicalToDeviceX (xsrc), 882 source->LogicalToDeviceY (ysrc), 883 source->LogicalToDeviceXRel(width), 884 source->LogicalToDeviceYRel(height), 885 XLOG2DEV_2 (xdest), YLOG2DEV_2 (ydest), 886 True, &cache); 887 888 if ( useMask && source->IsKindOf(CLASSINFO(wxMemoryDC)) ) 889 { 890 wxMemoryDC *memDC = (wxMemoryDC *)source; 891 wxBitmap& sel = memDC->GetBitmap(); 892 if ( sel.Ok() && sel.GetMask() && sel.GetMask()->GetBitmap() ) 893 { 894 XSetClipMask ((Display*) m_display, (GC) m_gc, (Pixmap) sel.GetMask()->GetBitmap()); 895 XSetClipOrigin ((Display*) m_display, (GC) m_gc, XLOG2DEV (xdest), YLOG2DEV (ydest)); 896 } 897 } 898 899 XCopyRemote((Display*) sourceDC->m_display, (Display*) m_display, (Pixmap) sourcePixmap, (Pixmap) m_pixmap, (GC) m_gc, 900 source->LogicalToDeviceX (xsrc), 901 source->LogicalToDeviceY (ysrc), 902 source->LogicalToDeviceXRel(width), 903 source->LogicalToDeviceYRel(height), 904 XLOG2DEV (xdest), YLOG2DEV (ydest), 905 False, &cache); 906 907 if ( useMask ) 908 { 909 if ( m_clipRegion ) 910 XSetRegion ((Display*) m_display, (GC) m_gc, 911 (Region) m_clipRegion); 912 else 913 XSetClipMask ((Display*) m_display, (GC) m_gc, None); 914 915 XSetClipOrigin ((Display*) m_display, (GC) m_gc, 0, 0); 916 } 917 918 } else 919 { //XGCValues values; 920 //XGetGCValues((Display*)m_display, (GC)m_gc, GCForeground, &values); 921 922 if (m_window && m_window->GetBackingPixmap()) 923 { 924 // +++ MARKUS (mho@comnets.rwth-aachen): error on blitting bitmaps with depth 1 925 if (source->IsKindOf(CLASSINFO(wxMemoryDC)) && ((wxMemoryDC*) source)->GetBitmap().GetDepth() == 1) 926 { 927 XCopyPlane ((Display*) m_display, (Pixmap) sourcePixmap, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, 928 source->LogicalToDeviceX (xsrc), 929 source->LogicalToDeviceY (ysrc), 930 source->LogicalToDeviceXRel(width), 931 source->LogicalToDeviceYRel(height), 932 XLOG2DEV_2 (xdest), YLOG2DEV_2 (ydest), 1); 933 } 934 else 935 { 936 XCopyArea ((Display*) m_display, (Pixmap) sourcePixmap, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, 937 source->LogicalToDeviceX (xsrc), 938 source->LogicalToDeviceY (ysrc), 939 source->LogicalToDeviceXRel(width), 940 source->LogicalToDeviceYRel(height), 941 XLOG2DEV_2 (xdest), YLOG2DEV_2 (ydest)); 942 } 943 } 944 if ( useMask && source->IsKindOf(CLASSINFO(wxMemoryDC)) ) 945 { 946 wxMemoryDC *memDC = (wxMemoryDC *)source; 947 wxBitmap& sel = memDC->GetBitmap(); 948 if ( sel.Ok() && sel.GetMask() && sel.GetMask()->GetBitmap() ) 949 { 950 XSetClipMask ((Display*) m_display, (GC) m_gc, (Pixmap) sel.GetMask()->GetBitmap()); 951 XSetClipOrigin ((Display*) m_display, (GC) m_gc, XLOG2DEV (xdest), YLOG2DEV (ydest)); 952 } 953 } 954 955 // Check if we're copying from a mono bitmap 956 if (source->IsKindOf(CLASSINFO(wxMemoryDC)) && 957 ((wxMemoryDC*)source)->GetBitmap().Ok() && (((wxMemoryDC*)source)->GetBitmap().GetDepth () == 1)) 958 { 959 XCopyPlane ((Display*) m_display, (Pixmap) sourcePixmap, (Pixmap) m_pixmap, (GC) m_gc, 960 source->LogicalToDeviceX (xsrc), 961 source->LogicalToDeviceY (ysrc), 962 source->LogicalToDeviceXRel(width), 963 source->LogicalToDeviceYRel(height), 964 XLOG2DEV (xdest), YLOG2DEV (ydest), 1); 965 } 966 else 967 { 968 XCopyArea ((Display*) m_display, (Pixmap) sourcePixmap, (Pixmap) m_pixmap, (GC) m_gc, 969 source->LogicalToDeviceX (xsrc), 970 source->LogicalToDeviceY (ysrc), 971 source->LogicalToDeviceXRel(width), 972 source->LogicalToDeviceYRel(height), 973 XLOG2DEV (xdest), YLOG2DEV (ydest)); 974 975 } 976 if ( useMask ) 977 { 978 if ( m_clipRegion ) 979 XSetRegion ((Display*) m_display, (GC) m_gc, 980 (Region) m_clipRegion); 981 else 982 XSetClipMask ((Display*) m_display, (GC) m_gc, None); 983 984 XSetClipOrigin ((Display*) m_display, (GC) m_gc, 0, 0); 985 } 986 987 } /* Remote/local (Display*) m_display */ 988 CalcBoundingBox (xdest, ydest); 989 CalcBoundingBox (xdest + width, ydest + height); 990 991 SetLogicalFunction(orig); 992 993 retVal = true; 994 } 995 if (scaledBitmap) delete scaledBitmap; 996 997 if (oldBackgroundPixel > -1) 998 { 999 XSetBackground ((Display*) m_display, (GC) m_gc, oldBackgroundPixel); 1000 if (m_window && m_window->GetBackingPixmap()) 1001 XSetBackground ((Display*) m_display,(GC) m_gcBacking, 1002 oldBackgroundPixel); 1003 } 1004 if (oldForegroundPixel > -1) 1005 { 1006 XSetForeground ((Display*) m_display, (GC) m_gc, oldForegroundPixel); 1007 if (m_window && m_window->GetBackingPixmap()) 1008 XSetForeground ((Display*) m_display,(GC) m_gcBacking, 1009 oldForegroundPixel); 1010 } 1011 1012 return retVal; 1013} 1014 1015void wxWindowDC::DoDrawText( const wxString &text, wxCoord x, wxCoord y ) 1016{ 1017 wxCHECK_RET( Ok(), "invalid dc" ); 1018 1019 // Since X draws from the baseline of the text, must add the text height 1020 int cx = 0; 1021 int cy = 0; 1022 int ascent = 0; 1023 int slen = text.length(); 1024 1025 // Set FillStyle, otherwise X will use current stipple! 1026 XGCValues gcV, gcBackingV; 1027 1028 XGetGCValues ((Display*) m_display, (GC)m_gc, GCFillStyle, &gcV); 1029 XSetFillStyle ((Display*) m_display, (GC) m_gc, FillSolid); 1030 if (m_window && m_window->GetBackingPixmap()) 1031 { 1032 XGetGCValues ((Display*) m_display, (GC)m_gcBacking, GCFillStyle, 1033 &gcBackingV ); 1034 XSetFillStyle ((Display*) m_display, (GC) m_gcBacking, FillSolid); 1035 } 1036 1037 if (m_font.Ok()) 1038 wxGetTextExtent (m_display, m_font, m_userScaleY * m_logicalScaleY, 1039 text, &cx, &cy, &ascent, NULL); 1040 1041 // First draw a rectangle representing the text background, if a text 1042 // background is specified 1043 if (m_textBackgroundColour.Ok () && (m_backgroundMode != wxTRANSPARENT)) 1044 { 1045 wxColour oldPenColour = m_currentColour; 1046 m_currentColour = m_textBackgroundColour; 1047 bool sameColour = (oldPenColour.Ok () && m_textBackgroundColour.Ok () && 1048 (oldPenColour.Red () == m_textBackgroundColour.Red ()) && 1049 (oldPenColour.Blue () == m_textBackgroundColour.Blue ()) && 1050 (oldPenColour.Green () == m_textBackgroundColour.Green ())); 1051 1052 // This separation of the big && test required for gcc2.7/HP UX 9.02 1053 // or pixel value can be corrupted! 1054 sameColour = (sameColour && 1055 (oldPenColour.GetPixel() == m_textBackgroundColour.GetPixel())); 1056 1057 if (!sameColour || !GET_OPTIMIZATION) 1058 { 1059 WXPixel pixel = m_textBackgroundColour.AllocColour(m_display); 1060 m_currentColour = m_textBackgroundColour; 1061 1062 // Set the GC to the required colour 1063 if (pixel > -1) 1064 { 1065 XSetForeground ((Display*) m_display, (GC) m_gc, pixel); 1066 if (m_window && m_window->GetBackingPixmap()) 1067 XSetForeground ((Display*) m_display,(GC) m_gcBacking, pixel); 1068 } 1069 } 1070 else 1071 m_textBackgroundColour = oldPenColour ; 1072 1073 XFillRectangle ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, XLOG2DEV (x), YLOG2DEV (y), cx, cy); 1074 if (m_window && m_window->GetBackingPixmap()) 1075 XFillRectangle ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, 1076 XLOG2DEV_2 (x), YLOG2DEV_2 (y), cx, cy); 1077 } 1078 1079 // Now set the text foreground and draw the text 1080 if (m_textForegroundColour.Ok ()) 1081 { 1082 wxColour oldPenColour = m_currentColour; 1083 m_currentColour = m_textForegroundColour; 1084 bool sameColour = (oldPenColour.Ok () && m_currentColour.Ok () && 1085 (oldPenColour.Red () == m_currentColour.Red ()) && 1086 (oldPenColour.Blue () == m_currentColour.Blue ()) && 1087 (oldPenColour.Green () == m_currentColour.Green ()) && 1088 (oldPenColour.GetPixel() == m_currentColour.GetPixel())); 1089 1090 if (!sameColour || !GET_OPTIMIZATION) 1091 { 1092 WXPixel pixel = CalculatePixel(m_textForegroundColour, 1093 m_currentColour, false); 1094 1095 // Set the GC to the required colour 1096 if (pixel > -1) 1097 { 1098 XSetForeground ((Display*) m_display, (GC) m_gc, pixel); 1099 if (m_window && m_window->GetBackingPixmap()) 1100 XSetForeground ((Display*) m_display,(GC) m_gcBacking, pixel); 1101 } 1102 } 1103 else 1104 m_textForegroundColour = oldPenColour; 1105 } 1106 1107 // We need to add the ascent, not the whole height, since X draws at the 1108 // point above the descender. 1109#if 0 1110 if (use16) 1111 XDrawString16((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, XLOG2DEV (x), YLOG2DEV (y) + ascent, 1112 (XChar2b *)(char*) (const char*) text, slen); 1113 else 1114#endif // 0 1115#if wxMOTIF_NEW_FONT_HANDLING 1116 XFontSet fset = (XFontSet) m_font.GetFontSet (m_userScaleY * m_logicalScaleY, m_display); 1117 XmbDrawString((Display*) m_display, (Pixmap) m_pixmap, fset, (GC) m_gc, XLOG2DEV (x), YLOG2DEV (y) + ascent, text, slen); 1118#else 1119 XDrawString((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, XLOG2DEV (x), YLOG2DEV (y) + ascent, text, slen); 1120#endif 1121 1122 if (m_window && m_window->GetBackingPixmap()) { 1123#if 0 1124 if (use16) 1125 XDrawString16((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(), (GC) m_gcBacking, 1126 XLOG2DEV_2 (x), YLOG2DEV_2 (y) + ascent, 1127 (XChar2b *)(char*) (const char*) text, slen); 1128 else 1129#endif // 0 1130#if wxMOTIF_NEW_FONT_HANDLING 1131 XmbDrawString((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(), fset, (GC) m_gcBacking, 1132 XLOG2DEV_2 (x), YLOG2DEV_2 (y) + ascent, 1133 wxConstCast(text.c_str(), char), slen); 1134#else 1135 XDrawString((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(), (GC) m_gcBacking, 1136 XLOG2DEV_2 (x), YLOG2DEV_2 (y) + ascent, 1137 wxConstCast(text.c_str(), char), slen); 1138#endif 1139 } 1140 1141 // restore fill style 1142 XSetFillStyle ((Display*) m_display, (GC) m_gc, gcV.fill_style); 1143 if (m_window && m_window->GetBackingPixmap()) 1144 XSetFillStyle ((Display*) m_display, (GC) m_gcBacking, 1145 gcBackingV.fill_style); 1146 1147 wxCoord w, h; 1148 GetTextExtent (text, &w, &h); 1149 CalcBoundingBox (x + w, y + h); 1150 CalcBoundingBox (x, y); 1151} 1152 1153void wxWindowDC::DoDrawRotatedText( const wxString &text, wxCoord x, wxCoord y, 1154 double angle ) 1155{ 1156 if (angle == 0.0) 1157 { 1158 DrawText(text, x, y); 1159 return; 1160 } 1161 1162 wxCHECK_RET( Ok(), "invalid dc" ); 1163 1164 WXPixel oldBackgroundPixel = -1; 1165 WXPixel oldForegroundPixel = -1; 1166 WXPixel foregroundPixel = -1; 1167 WXPixel backgroundPixel = -1; 1168 1169 if (m_textBackgroundColour.Ok()) 1170 { 1171 oldBackgroundPixel = m_backgroundPixel; 1172 backgroundPixel = m_textBackgroundColour.AllocColour(m_display); 1173 } 1174 if (m_textForegroundColour.Ok()) 1175 { 1176 oldForegroundPixel = m_currentColour.GetPixel(); 1177 1178 if( m_textForegroundColour.GetPixel() <= -1 ) 1179 CalculatePixel( m_textForegroundColour, 1180 m_textForegroundColour, true); 1181 1182 foregroundPixel = m_textForegroundColour.GetPixel(); 1183 } 1184 1185 // Since X draws from the baseline of the text, must add the text height 1186 int cx = 0; 1187 int cy = 0; 1188 int ascent = 0; 1189 1190 if (m_font.Ok()) 1191 wxGetTextExtent (m_display, m_font, m_userScaleY * m_logicalScaleY, 1192 text, &cx, &cy, &ascent, NULL); 1193 1194 wxBitmap src(cx, cy); 1195 wxMemoryDC dc; 1196 dc.SelectObject(src); 1197 dc.SetFont(GetFont()); 1198 dc.SetBackground(*wxWHITE_BRUSH); 1199 dc.SetBrush(*wxBLACK_BRUSH); 1200 dc.Clear(); 1201 dc.DrawText(text, 0, 0); 1202 dc.SetFont(wxNullFont); 1203 1204 // Calculate the size of the rotated bounding box. 1205 double dx = cos(angle / 180.0 * M_PI); 1206 double dy = sin(angle / 180.0 * M_PI); 1207 double x4 = cy * dy; 1208 double y4 = cy * dx; 1209 double x3 = cx * dx; 1210 double y3 = -cx * dy; 1211 double x2 = x3 + x4; 1212 double y2 = y3 + y4; 1213 double x1 = x; 1214 double y1 = y; 1215 1216 // Create image from the source bitmap after writing the text into it. 1217 wxImage image = src.ConvertToImage(); 1218 1219 int minx = roundmin(0, roundmin(x4, roundmin(x2, x3))); 1220 int miny = roundmin(0, roundmin(y4, roundmin(y2, y3))); 1221 int maxx = roundmax(0, roundmax(x4, roundmax(x2, x3))); 1222 int maxy = roundmax(0, roundmax(y4, roundmax(y2, y3))); 1223 1224 bool lastFore = false, lastBack = false; 1225 1226 // This rotates counterclockwise around the top left corner. 1227 for (int rx = minx; rx < maxx; rx++) 1228 { 1229 for (int ry = miny; ry < maxy; ry++) 1230 { 1231 // transform dest coords to source coords 1232 int sx = (int) (rx * dx - ry * dy + 0.5); 1233 int sy = - (int) (-ry * dx - rx * dy + 0.5); 1234 if (sx >= 0 && sx < cx && sy >= 0 && sy < cy) 1235 { 1236 bool textPixel = image.GetRed(sx, sy) == 0; 1237 1238 if (!textPixel && m_backgroundMode != wxSOLID) 1239 continue; 1240 1241 wxCoord ox = (wxCoord) (x1 + rx), 1242 oy = (wxCoord) (y1 + ry); 1243 // draw black pixels, ignore white ones (i.e. transparent b/g) 1244 if (textPixel && !lastFore) 1245 { 1246 XSetForeground ((Display*) m_display, (GC) m_gc, 1247 foregroundPixel); 1248 lastFore = true; 1249 lastBack = false; 1250 } 1251 else if (!textPixel && !lastBack) 1252 { 1253 XSetForeground ((Display*) m_display, (GC) m_gc, 1254 backgroundPixel); 1255 lastFore = false; 1256 lastBack = true; 1257 } 1258 1259 XDrawPoint ((Display*) m_display, (Pixmap) m_pixmap, 1260 (GC) m_gc, XLOG2DEV (ox), YLOG2DEV (oy)); 1261 if (m_window && m_window->GetBackingPixmap()) 1262 XDrawPoint ((Display*) m_display, 1263 (Pixmap) m_window->GetBackingPixmap(), 1264 (GC) m_gcBacking, 1265 XLOG2DEV_2 (ox), YLOG2DEV_2 (oy)); 1266 } 1267 } 1268 } 1269 1270 if (oldBackgroundPixel > -1) 1271 { 1272 XSetBackground ((Display*) m_display, (GC) m_gc, oldBackgroundPixel); 1273 if (m_window && m_window->GetBackingPixmap()) 1274 XSetBackground ((Display*) m_display,(GC) m_gcBacking, 1275 oldBackgroundPixel); 1276 } 1277 if (oldForegroundPixel > -1) 1278 { 1279 XSetForeground ((Display*) m_display, (GC) m_gc, oldForegroundPixel); 1280 if (m_window && m_window->GetBackingPixmap()) 1281 XSetForeground ((Display*) m_display,(GC) m_gcBacking, 1282 oldForegroundPixel); 1283 } 1284 1285 CalcBoundingBox (minx, miny); 1286 CalcBoundingBox (maxx, maxy); 1287} 1288 1289bool wxWindowDC::CanGetTextExtent() const 1290{ 1291 return true; 1292} 1293 1294void wxWindowDC::DoGetTextExtent( const wxString &string, wxCoord *width, wxCoord *height, 1295 wxCoord *descent, wxCoord *externalLeading, 1296 wxFont *font ) const 1297{ 1298 wxCHECK_RET( Ok(), "invalid dc" ); 1299 1300 const wxFont* theFont = font ? font : &m_font; 1301 1302 if (!theFont->Ok()) 1303 { 1304 // TODO: this should be an error log function 1305 wxFAIL_MSG("set a valid font before calling GetTextExtent!"); 1306 1307 if (width) *width = -1; 1308 if (height) *height = -1; 1309 return; 1310 } 1311 1312 wxGetTextExtent(m_display, *theFont, m_userScaleY * m_logicalScaleY, 1313 string, width, height, NULL, descent); 1314 1315 if (width) *width = XDEV2LOGREL (*width); 1316 if (height) *height = YDEV2LOGREL (*height); 1317 if (externalLeading) 1318 *externalLeading = 0; 1319} 1320 1321wxCoord wxWindowDC::GetCharWidth() const 1322{ 1323 wxCHECK_MSG( Ok(), 0, "invalid dc" ); 1324 wxCHECK_MSG( m_font.Ok(), 0, "invalid font" ); 1325 1326 int width; 1327 1328 wxGetTextExtent (m_display, m_font, m_userScaleY * m_logicalScaleY, 1329 "x", &width, NULL, NULL, NULL); 1330 1331 return XDEV2LOGREL(width); 1332} 1333 1334wxCoord wxWindowDC::GetCharHeight() const 1335{ 1336 wxCHECK_MSG( Ok(), 0, "invalid dc" ); 1337 wxCHECK_MSG( m_font.Ok(), 0, "invalid font" ); 1338 1339 int height; 1340 1341 wxGetTextExtent (m_display, m_font, m_userScaleY * m_logicalScaleY, 1342 "x", NULL, &height, NULL, NULL); 1343 1344 return XDEV2LOGREL(height); 1345} 1346 1347void wxWindowDC::DoGetSize( int *width, int *height ) const 1348{ 1349 int w = 0, h = 0; 1350 1351 if( m_window ) 1352 { 1353 if( m_window->GetBackingPixmap() ) 1354 { 1355 w = m_window->GetPixmapWidth(); 1356 h = m_window->GetPixmapHeight(); 1357 } 1358 else 1359 m_window->GetSize( &w, &h ); 1360 } 1361 1362 if( width ) *width = w; 1363 if( height ) *height = h; 1364} 1365 1366void wxWindowDC::Clear() 1367{ 1368 wxCHECK_RET( Ok(), "invalid dc" ); 1369 1370 wxRect rect( GetSize() ); 1371 Clear( rect ); 1372} 1373 1374void wxWindowDC::Clear(const wxRect& rect) 1375{ 1376 wxCHECK_RET( Ok(), "invalid dc" ); 1377 1378 int x = rect.x; int y = rect.y; 1379 int w = rect.width; int h = rect.height; 1380 1381 wxBrush saveBrush = m_brush; 1382 SetBrush (m_backgroundBrush); 1383 1384 XFillRectangle ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, 1385 x, y, w, h); 1386 1387 if (m_window && m_window->GetBackingPixmap()) 1388 XFillRectangle ((Display*) m_display, 1389 (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, 1390 x, y, w, h); 1391 1392 m_brush = saveBrush; 1393} 1394 1395void wxWindowDC::SetFont( const wxFont &font ) 1396{ 1397 wxCHECK_RET( Ok(), "invalid dc" ); 1398 1399 m_font = font; 1400 1401 if (!m_font.Ok()) 1402 { 1403 return; 1404 } 1405 1406#if !wxMOTIF_NEW_FONT_HANDLING 1407 WXFontStructPtr pFontStruct = m_font.GetFontStruct(m_userScaleY*m_logicalScaleY, m_display); 1408 1409 Font fontId = ((XFontStruct*)pFontStruct)->fid; 1410 XSetFont ((Display*) m_display, (GC) m_gc, fontId); 1411 1412 if (m_window && m_window->GetBackingPixmap()) 1413 XSetFont ((Display*) m_display,(GC) m_gcBacking, fontId); 1414#endif 1415} 1416 1417void wxWindowDC::SetForegroundPixelWithLogicalFunction(WXPixel pixel) 1418{ 1419 if (m_logicalFunction == wxXOR) 1420 { 1421 XGCValues values; 1422 XGetGCValues ((Display*) m_display, (GC) m_gc, GCBackground, &values); 1423 XSetForeground ((Display*) m_display, (GC) m_gc, 1424 pixel ^ values.background); 1425 if (m_window && m_window->GetBackingPixmap()) 1426 XSetForeground ((Display*) m_display,(GC) m_gcBacking, 1427 pixel ^ values.background); 1428 } 1429 else 1430 { 1431 XSetForeground ((Display*) m_display, (GC) m_gc, pixel); 1432 if (m_window && m_window->GetBackingPixmap()) 1433 XSetForeground ((Display*) m_display,(GC) m_gcBacking, pixel); 1434 } 1435} 1436 1437WXPixel wxWindowDC::CalculatePixel(wxColour& colour, wxColour& curCol, 1438 bool roundToWhite) const 1439{ 1440 const unsigned char wp = (unsigned char)255; 1441 1442 WXPixel pixel = -1; 1443 if(!m_colour) // Mono display 1444 { 1445 unsigned char red = colour.Red (); 1446 unsigned char blue = colour.Blue (); 1447 unsigned char green = colour.Green (); 1448 // white 1449 if((red == wp && blue == wp && green == wp) || 1450 // not black and roundToWhite was specified 1451 ((red != 0 || blue != 0 || green != 0) && roundToWhite)) 1452 { 1453 curCol = *wxWHITE; 1454 pixel = WhitePixel((Display*) m_display, 1455 DefaultScreen((Display*) m_display)); 1456 curCol.SetPixel(pixel); 1457 colour.SetPixel(pixel); 1458 } 1459 else 1460 { 1461 curCol = *wxBLACK; 1462 pixel = BlackPixel((Display*) m_display, 1463 DefaultScreen((Display*) m_display)); 1464 curCol.SetPixel(pixel); 1465 colour.SetPixel(pixel); 1466 } 1467 } 1468 else 1469 { 1470 curCol = colour; 1471 pixel = colour.AllocColour((Display*) m_display); 1472 curCol.SetPixel(pixel); 1473 } 1474 1475 return pixel; 1476} 1477 1478void wxWindowDC::SetPen( const wxPen &pen ) 1479{ 1480 wxCHECK_RET( Ok(), "invalid dc" ); 1481 1482 m_pen = pen; 1483 if (!m_pen.Ok()) 1484 return; 1485 1486 wxBitmap oldStipple = m_currentStipple; 1487 int oldStyle = m_currentStyle; 1488 int oldFill = m_currentFill; 1489 int old_pen_width = m_currentPenWidth; 1490 int old_pen_join = m_currentPenJoin; 1491 int old_pen_cap = m_currentPenCap; 1492 int old_pen_nb_dash = m_currentPenDashCount; 1493 wxX11Dash *old_pen_dash = m_currentPenDash; 1494 1495 wxColour oldPenColour = m_currentColour; 1496 m_currentColour = m_pen.GetColour (); 1497 m_currentStyle = m_pen.GetStyle (); 1498 m_currentFill = m_pen.GetStyle (); // TODO? 1499 m_currentPenWidth = m_pen.GetWidth (); 1500 m_currentPenJoin = m_pen.GetJoin (); 1501 m_currentPenCap = m_pen.GetCap (); 1502 m_currentPenDashCount = m_pen.GetDashCount(); 1503 m_currentPenDash = (wxX11Dash*)m_pen.GetDash(); 1504 1505 if (m_currentStyle == wxSTIPPLE) 1506 m_currentStipple = * m_pen.GetStipple (); 1507 1508 bool sameStyle = (oldStyle == m_currentStyle && 1509 oldFill == m_currentFill && 1510 old_pen_join == m_currentPenJoin && 1511 old_pen_cap == m_currentPenCap && 1512 old_pen_nb_dash == m_currentPenDashCount && 1513 old_pen_dash == m_currentPenDash && 1514 old_pen_width == m_currentPenWidth); 1515 1516 bool sameColour = (oldPenColour.Ok () && 1517 (oldPenColour.Red () == m_currentColour.Red ()) && 1518 (oldPenColour.Blue () == m_currentColour.Blue ()) && 1519 (oldPenColour.Green () == m_currentColour.Green ()) && 1520 (oldPenColour.GetPixel() == m_currentColour.GetPixel())); 1521 1522 if (!sameStyle || !GET_OPTIMIZATION) 1523 { 1524 int scaled_width = (int) XLOG2DEVREL (m_pen.GetWidth ()); 1525 if (scaled_width < 0) 1526 scaled_width = 0; 1527 1528 int style; 1529 int join; 1530 int cap; 1531 static const wxX11Dash dotted[] = {2, 5}; 1532 static const wxX11Dash short_dashed[] = {4, 4}; 1533 static const wxX11Dash long_dashed[] = {4, 8}; 1534 static const wxX11Dash dotted_dashed[] = {6, 6, 2, 6}; 1535 1536 // We express dash pattern in pen width unit, so we are 1537 // independent of zoom factor and so on... 1538 int req_nb_dash; 1539 const wxX11Dash *req_dash; 1540 1541 switch (m_pen.GetStyle ()) 1542 { 1543 case wxUSER_DASH: 1544 req_nb_dash = m_currentPenDashCount; 1545 req_dash = m_currentPenDash; 1546 style = LineOnOffDash; 1547 break; 1548 case wxDOT: 1549 req_nb_dash = 2; 1550 req_dash = dotted; 1551 style = LineOnOffDash; 1552 break; 1553 case wxSHORT_DASH: 1554 req_nb_dash = 2; 1555 req_dash = short_dashed; 1556 style = LineOnOffDash; 1557 break; 1558 case wxLONG_DASH: 1559 req_nb_dash = 2; 1560 req_dash = long_dashed; 1561 style = LineOnOffDash; 1562 break; 1563 case wxDOT_DASH: 1564 req_nb_dash = 4; 1565 req_dash = dotted_dashed; 1566 style = LineOnOffDash; 1567 break; 1568 case wxSTIPPLE: 1569 case wxSOLID: 1570 case wxTRANSPARENT: 1571 default: 1572 style = LineSolid; 1573 req_dash = (wxX11Dash*)NULL; 1574 req_nb_dash = 0; 1575 } 1576 1577 if (req_dash && req_nb_dash) 1578 { 1579 wxX11Dash *real_req_dash = new wxX11Dash[req_nb_dash]; 1580 if (real_req_dash) 1581 { 1582 int factor = scaled_width == 0 ? 1 : scaled_width; 1583 for (int i = 0; i < req_nb_dash; i++) 1584 real_req_dash[i] = (wxX11Dash)(req_dash[i] * factor); 1585 XSetDashes ((Display*) m_display, (GC) m_gc, 0, real_req_dash, req_nb_dash); 1586 1587 if (m_window && m_window->GetBackingPixmap()) 1588 XSetDashes ((Display*) m_display,(GC) m_gcBacking, 0, real_req_dash, req_nb_dash); 1589 delete[]real_req_dash; 1590 } 1591 else 1592 { 1593 // No Memory. We use non-scaled dash pattern... 1594 XSetDashes ((Display*) m_display, (GC) m_gc, 0, req_dash, req_nb_dash); 1595 1596 if (m_window && m_window->GetBackingPixmap()) 1597 XSetDashes ((Display*) m_display,(GC) m_gcBacking, 0, req_dash, req_nb_dash); 1598 } 1599 } 1600 1601 switch (m_pen.GetCap ()) 1602 { 1603 case wxCAP_PROJECTING: 1604 cap = CapProjecting; 1605 break; 1606 case wxCAP_BUTT: 1607 cap = CapButt; 1608 break; 1609 case wxCAP_ROUND: 1610 default: 1611 cap = (scaled_width <= 1) ? CapNotLast : CapRound; 1612 break; 1613 } 1614 1615 switch (m_pen.GetJoin ()) 1616 { 1617 case wxJOIN_BEVEL: 1618 join = JoinBevel; 1619 break; 1620 case wxJOIN_MITER: 1621 join = JoinMiter; 1622 break; 1623 case wxJOIN_ROUND: 1624 default: 1625 join = JoinRound; 1626 break; 1627 } 1628 1629 XSetLineAttributes ((Display*) m_display, (GC) m_gc, scaled_width, style, cap, join); 1630 1631 if (m_window && m_window->GetBackingPixmap()) 1632 XSetLineAttributes ((Display*) m_display,(GC) m_gcBacking, scaled_width, style, cap, join); 1633 } 1634 1635 if (IS_HATCH(m_currentFill) && ((m_currentFill != oldFill) || !GET_OPTIMIZATION)) 1636 { 1637 Pixmap myStipple; 1638 1639 oldStipple = wxNullBitmap; // For later reset!! 1640 1641 switch (m_currentFill) 1642 { 1643 case wxBDIAGONAL_HATCH: 1644 if (bdiag == (Pixmap) 0) 1645 bdiag = XCreateBitmapFromData ((Display*) m_display, 1646 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)), 1647 bdiag_bits, bdiag_width, bdiag_height); 1648 myStipple = bdiag; 1649 break; 1650 case wxFDIAGONAL_HATCH: 1651 if (fdiag == (Pixmap) 0) 1652 fdiag = XCreateBitmapFromData ((Display*) m_display, 1653 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)), 1654 fdiag_bits, fdiag_width, fdiag_height); 1655 myStipple = fdiag; 1656 break; 1657 case wxCROSS_HATCH: 1658 if (cross == (Pixmap) 0) 1659 cross = XCreateBitmapFromData ((Display*) m_display, 1660 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)), 1661 cross_bits, cross_width, cross_height); 1662 myStipple = cross; 1663 break; 1664 case wxHORIZONTAL_HATCH: 1665 if (horiz == (Pixmap) 0) 1666 horiz = XCreateBitmapFromData ((Display*) m_display, 1667 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)), 1668 horiz_bits, horiz_width, horiz_height); 1669 myStipple = horiz; 1670 break; 1671 case wxVERTICAL_HATCH: 1672 if (verti == (Pixmap) 0) 1673 verti = XCreateBitmapFromData ((Display*) m_display, 1674 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)), 1675 verti_bits, verti_width, verti_height); 1676 myStipple = verti; 1677 break; 1678 case wxCROSSDIAG_HATCH: 1679 default: 1680 if (cdiag == (Pixmap) 0) 1681 cdiag = XCreateBitmapFromData ((Display*) m_display, 1682 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)), 1683 cdiag_bits, cdiag_width, cdiag_height); 1684 myStipple = cdiag; 1685 break; 1686 } 1687 XSetStipple ((Display*) m_display, (GC) m_gc, myStipple); 1688 1689 if (m_window && m_window->GetBackingPixmap()) 1690 XSetStipple ((Display*) m_display,(GC) m_gcBacking, myStipple); 1691 } 1692 else if (m_currentStipple.Ok() 1693 && ((!m_currentStipple.IsSameAs(oldStipple)) || !GET_OPTIMIZATION)) 1694 { 1695 XSetStipple ((Display*) m_display, (GC) m_gc, (Pixmap) m_currentStipple.GetDrawable()); 1696 1697 if (m_window && m_window->GetBackingPixmap()) 1698 XSetStipple ((Display*) m_display,(GC) m_gcBacking, (Pixmap) m_currentStipple.GetDrawable()); 1699 } 1700 1701 if ((m_currentFill != oldFill) || !GET_OPTIMIZATION) 1702 { 1703 int fill_style; 1704 1705 if (m_currentFill == wxSTIPPLE) 1706 fill_style = FillStippled; 1707 else if (IS_HATCH (m_currentFill)) 1708 fill_style = FillStippled; 1709 else 1710 fill_style = FillSolid; 1711 XSetFillStyle ((Display*) m_display, (GC) m_gc, fill_style); 1712 if (m_window && m_window->GetBackingPixmap()) 1713 XSetFillStyle ((Display*) m_display,(GC) m_gcBacking, fill_style); 1714 } 1715 1716 // must test m_logicalFunction, because it involves background! 1717 if (!sameColour || !GET_OPTIMIZATION 1718 || ((m_logicalFunction == wxXOR) || (m_autoSetting & 0x2))) 1719 { 1720 WXPixel pixel = -1; 1721 if (m_pen.GetStyle () == wxTRANSPARENT) 1722 pixel = m_backgroundPixel; 1723 else 1724 { 1725 pixel = CalculatePixel(m_pen.GetColour(), m_currentColour, false); 1726 } 1727 1728 // Finally, set the GC to the required colour 1729 if (pixel > -1) 1730 SetForegroundPixelWithLogicalFunction(pixel); 1731 } 1732 else 1733 m_pen.GetColour().SetPixel(oldPenColour.GetPixel()); 1734 1735 m_autoSetting = 0; 1736} 1737 1738void wxWindowDC::SetBrush( const wxBrush &brush ) 1739{ 1740 wxCHECK_RET( Ok(), "invalid dc" ); 1741 1742 m_brush = brush; 1743 1744 if (!m_brush.Ok() || m_brush.GetStyle () == wxTRANSPARENT) 1745 return; 1746 1747 int oldFill = m_currentFill; 1748 wxBitmap oldStipple = m_currentStipple; 1749 1750 m_autoSetting |= 0x1; 1751 1752 m_currentFill = m_brush.GetStyle (); 1753 if (m_currentFill == wxSTIPPLE) 1754 m_currentStipple = * m_brush.GetStipple (); 1755 1756 wxColour oldBrushColour(m_currentColour); 1757 m_currentColour = m_brush.GetColour (); 1758 1759 bool sameColour = (oldBrushColour.Ok () && 1760 (oldBrushColour.Red () == m_currentColour.Red ()) && 1761 (oldBrushColour.Blue () == m_currentColour.Blue ()) && 1762 (oldBrushColour.Green () == m_currentColour.Green ()) && 1763 (oldBrushColour.GetPixel() == m_currentColour.GetPixel())); 1764 1765 int stippleDepth = -1; 1766 1767 if ((oldFill != m_brush.GetStyle ()) || !GET_OPTIMIZATION) 1768 { 1769 switch (brush.GetStyle ()) 1770 { 1771 case wxTRANSPARENT: 1772 break; 1773 case wxSTIPPLE: 1774 stippleDepth = m_currentStipple.GetDepth(); 1775 // fall through! 1776 case wxBDIAGONAL_HATCH: 1777 case wxCROSSDIAG_HATCH: 1778 case wxFDIAGONAL_HATCH: 1779 case wxCROSS_HATCH: 1780 case wxHORIZONTAL_HATCH: 1781 case wxVERTICAL_HATCH: 1782 { 1783 if (stippleDepth == -1) stippleDepth = 1; 1784 1785 // Chris Breeze 23/07/97: use background mode to 1786 // determine whether fill style should be solid or 1787 // transparent 1788 int style = stippleDepth == 1 ? 1789 (m_backgroundMode == wxSOLID ? 1790 FillOpaqueStippled : FillStippled) : 1791 FillTiled; 1792 XSetFillStyle ((Display*) m_display, (GC) m_gc, style); 1793 if (m_window && m_window->GetBackingPixmap()) 1794 XSetFillStyle ((Display*) m_display,(GC) m_gcBacking, style); 1795 } 1796 break; 1797 case wxSOLID: 1798 default: 1799 XSetFillStyle ((Display*) m_display, (GC) m_gc, FillSolid); 1800 if (m_window && m_window->GetBackingPixmap()) 1801 XSetFillStyle ((Display*) m_display,(GC) m_gcBacking, 1802 FillSolid); 1803 } 1804 } 1805 1806 if (IS_HATCH(m_currentFill) && ((m_currentFill != oldFill) || !GET_OPTIMIZATION)) 1807 { 1808 Pixmap myStipple; 1809 1810 switch (m_currentFill) 1811 { 1812 case wxBDIAGONAL_HATCH: 1813 if (bdiag == (Pixmap) 0) 1814 bdiag = XCreateBitmapFromData ((Display*) m_display, 1815 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)), 1816 bdiag_bits, bdiag_width, bdiag_height); 1817 myStipple = bdiag; 1818 break; 1819 case wxFDIAGONAL_HATCH: 1820 if (fdiag == (Pixmap) 0) 1821 fdiag = XCreateBitmapFromData ((Display*) m_display, 1822 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)), 1823 fdiag_bits, fdiag_width, fdiag_height); 1824 myStipple = fdiag; 1825 break; 1826 case wxCROSS_HATCH: 1827 if (cross == (Pixmap) 0) 1828 cross = XCreateBitmapFromData ((Display*) m_display, 1829 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)), 1830 cross_bits, cross_width, cross_height); 1831 myStipple = cross; 1832 break; 1833 case wxHORIZONTAL_HATCH: 1834 if (horiz == (Pixmap) 0) 1835 horiz = XCreateBitmapFromData ((Display*) m_display, 1836 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)), 1837 horiz_bits, horiz_width, horiz_height); 1838 myStipple = horiz; 1839 break; 1840 case wxVERTICAL_HATCH: 1841 if (verti == (Pixmap) 0) 1842 verti = XCreateBitmapFromData ((Display*) m_display, 1843 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)), 1844 verti_bits, verti_width, verti_height); 1845 myStipple = verti; 1846 break; 1847 case wxCROSSDIAG_HATCH: 1848 default: 1849 if (cdiag == (Pixmap) 0) 1850 cdiag = XCreateBitmapFromData ((Display*) m_display, 1851 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)), 1852 cdiag_bits, cdiag_width, cdiag_height); 1853 myStipple = cdiag; 1854 break; 1855 } 1856 XSetStipple ((Display*) m_display, (GC) m_gc, myStipple); 1857 1858 if (m_window && m_window->GetBackingPixmap()) 1859 XSetStipple ((Display*) m_display,(GC) m_gcBacking, myStipple); 1860 } 1861 // X can forget the stipple value when resizing a window (apparently) 1862 // so always set the stipple. 1863 else if (m_currentFill != wxSOLID && m_currentFill != wxTRANSPARENT && 1864 m_currentStipple.Ok()) // && m_currentStipple != oldStipple) 1865 { 1866 if (m_currentStipple.GetDepth() == 1) 1867 { 1868 XSetStipple ((Display*) m_display, (GC) m_gc, 1869 (Pixmap) m_currentStipple.GetDrawable()); 1870 if (m_window && m_window->GetBackingPixmap()) 1871 XSetStipple ((Display*) m_display,(GC) m_gcBacking, 1872 (Pixmap) m_currentStipple.GetDrawable()); 1873 } 1874 else 1875 { 1876 XSetTile ((Display*) m_display, (GC) m_gc, 1877 (Pixmap) m_currentStipple.GetDrawable()); 1878 if (m_window && m_window->GetBackingPixmap()) 1879 XSetTile ((Display*) m_display,(GC) m_gcBacking, 1880 (Pixmap) m_currentStipple.GetDrawable()); 1881 } 1882 } 1883 1884 // must test m_logicalFunction, because it involves background! 1885 if (!sameColour || !GET_OPTIMIZATION || m_logicalFunction == wxXOR) 1886 { 1887 WXPixel pixel = CalculatePixel(m_brush.GetColour(), m_currentColour, true); 1888 1889 if (pixel > -1) 1890 SetForegroundPixelWithLogicalFunction(pixel); 1891 } 1892 else 1893 m_brush.GetColour().SetPixel(oldBrushColour.GetPixel()); 1894} 1895 1896void wxWindowDC::SetBackground( const wxBrush &brush ) 1897{ 1898 wxCHECK_RET( Ok(), "invalid dc" ); 1899 1900 m_backgroundBrush = brush; 1901 1902 if (!m_backgroundBrush.Ok()) 1903 return; 1904 1905 m_backgroundPixel = m_backgroundBrush.GetColour().AllocColour(m_display); 1906 1907 // Necessary for ::DrawIcon, which use fg/bg pixel or the GC. 1908 // And Blit,... (Any fct that use XCopyPlane, in fact.) 1909 XSetBackground ((Display*) m_display, (GC) m_gc, m_backgroundPixel); 1910 if (m_window && m_window->GetBackingPixmap()) 1911 XSetBackground ((Display*) m_display,(GC) m_gcBacking, 1912 m_backgroundPixel); 1913} 1914 1915void wxWindowDC::SetLogicalFunction( int function ) 1916{ 1917 wxCHECK_RET( Ok(), "invalid dc" ); 1918 1919 int x_function; 1920 1921 /* MATTHEW: [9] */ 1922 if (m_logicalFunction == function) 1923 return; 1924 1925 switch (function) 1926 { 1927 case wxCLEAR: 1928 x_function = GXclear; 1929 break; 1930 case wxXOR: 1931 x_function = GXxor; 1932 break; 1933 case wxINVERT: 1934 x_function = GXinvert; 1935 break; 1936 case wxOR_REVERSE: 1937 x_function = GXorReverse; 1938 break; 1939 case wxAND_REVERSE: 1940 x_function = GXandReverse; 1941 break; 1942 case wxAND: 1943 x_function = GXand; 1944 break; 1945 case wxOR: 1946 x_function = GXor; 1947 break; 1948 case wxAND_INVERT: 1949 x_function = GXandInverted; 1950 break; 1951 case wxNO_OP: 1952 x_function = GXnoop; 1953 break; 1954 case wxNOR: 1955 x_function = GXnor; 1956 break; 1957 case wxEQUIV: 1958 x_function = GXequiv; 1959 break; 1960 case wxSRC_INVERT: 1961 x_function = GXcopyInverted; 1962 break; 1963 case wxOR_INVERT: 1964 x_function = GXorInverted; 1965 break; 1966 case wxNAND: 1967 x_function = GXnand; 1968 break; 1969 case wxSET: 1970 x_function = GXset; 1971 break; 1972 case wxCOPY: 1973 default: 1974 x_function = GXcopy; 1975 break; 1976 } 1977 1978 XSetFunction((Display*) m_display, (GC) m_gc, x_function); 1979 if (m_window && m_window->GetBackingPixmap()) 1980 XSetFunction((Display*) m_display, (GC) m_gcBacking, x_function); 1981 1982 if ((m_logicalFunction == wxXOR) != (function == wxXOR)) 1983 /* MATTHEW: [9] Need to redo pen simply */ 1984 m_autoSetting |= 0x2; 1985 1986 m_logicalFunction = function; 1987 1988} 1989 1990void wxWindowDC::SetTextForeground( const wxColour &col ) 1991{ 1992 wxCHECK_RET( Ok(), "invalid dc" ); 1993 1994 m_textForegroundColour = col; 1995} 1996 1997void wxWindowDC::SetTextBackground( const wxColour &col ) 1998{ 1999 wxCHECK_RET( Ok(), "invalid dc" ); 2000 2001 m_textBackgroundColour = col; 2002} 2003 2004void wxWindowDC::SetBackgroundMode( int mode ) 2005{ 2006 m_backgroundMode = mode; 2007} 2008 2009void wxWindowDC::SetPalette( const wxPalette& palette ) 2010{ 2011 if (m_window) 2012 { 2013 if (palette.Ok()) 2014 /* Use GetXColormap */ 2015 XSetWindowColormap ((Display*) m_display, (Window) m_window->GetXWindow(), 2016 (Colormap) palette.GetXColormap()); 2017 else 2018 /* Use wxGetMainColormap */ 2019 XSetWindowColormap ((Display*) m_display, (Window) m_window->GetXWindow(), 2020 (Colormap) wxTheApp->GetMainColormap(m_display)); 2021 } 2022} 2023 2024static void wxCopyRegion( WXRegion src, WXRegion& dst ) 2025{ 2026 if( !dst ) 2027 dst = XCreateRegion(); 2028 XUnionRegion( (Region)src, (Region)src, (Region)dst ); 2029} 2030 2031// Helper function; userRegion is the region set by calling SetClippingRegion 2032void wxWindowDC::SetDCClipping( WXRegion userRegion ) 2033{ 2034 bool hasUpdateRegion = m_window && m_window->GetUpdateRegion().Ok(); 2035 // this means that we should start the clip region from scratch, 2036 // or from the update region, if any 2037 if( !userRegion ) 2038 { 2039 if( m_clipRegion ) 2040 XDestroyRegion( (Region)m_clipRegion ); 2041 m_clipRegion = (WXRegion)NULL; 2042 2043 if( hasUpdateRegion ) 2044 wxCopyRegion( m_window->GetUpdateRegion().GetX11Region(), 2045 m_clipRegion ); 2046 } 2047 // intersect the user region, if any, with the 2048 // exisiting clip region 2049 else // if( userRegion ) 2050 { 2051 if( !m_clipRegion ) 2052 wxCopyRegion( userRegion, m_clipRegion ); 2053 else 2054 XIntersectRegion( (Region)m_clipRegion, 2055 (Region)userRegion, (Region)m_clipRegion ); 2056 } 2057 2058 if( m_clipRegion ) 2059 XSetRegion( (Display*)m_display, (GC)m_gc, (Region)m_clipRegion ); 2060 else 2061 XSetClipMask( (Display*)m_display, (GC)m_gc, None ); 2062} 2063 2064void wxWindowDC::DoSetClippingRegion( wxCoord x, wxCoord y, 2065 wxCoord width, wxCoord height ) 2066{ 2067 wxDC::DoSetClippingRegion( x, y, width, height ); 2068 2069 wxRegion temp(XLOG2DEV(x), YLOG2DEV(y), 2070 XLOG2DEVREL(width), YLOG2DEVREL(height)); 2071 2072 SetDCClipping(temp.GetX11Region()); 2073 2074 // Needs to work differently for Pixmap: without this, 2075 // there's a nasty (Display*) m_display bug. 8/12/94 2076 if (m_window && m_window->GetBackingPixmap()) 2077 { 2078 XRectangle rects[1]; 2079 rects[0].x = (short)XLOG2DEV_2(x); 2080 rects[0].y = (short)YLOG2DEV_2(y); 2081 rects[0].width = (unsigned short)XLOG2DEVREL(width); 2082 rects[0].height = (unsigned short)YLOG2DEVREL(height); 2083 XSetClipRectangles((Display*) m_display, (GC) m_gcBacking, 2084 0, 0, rects, 1, Unsorted); 2085 } 2086} 2087 2088void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion& region ) 2089{ 2090 SetDCClipping(region.GetX11Region()); 2091 2092 // Needs to work differently for Pixmap: without this, 2093 // there's a nasty (Display*) m_display bug. 8/12/94 2094 if (m_window && m_window->GetBackingPixmap()) 2095 { 2096 wxRect box = region.GetBox(); 2097 2098 XRectangle rects[1]; 2099 rects[0].x = (short)XLOG2DEV_2(box.x); 2100 rects[0].y = (short)YLOG2DEV_2(box.y); 2101 rects[0].width = (unsigned short)XLOG2DEVREL(box.width); 2102 rects[0].height = (unsigned short)YLOG2DEVREL(box.height); 2103 XSetClipRectangles((Display*) m_display, (GC) m_gcBacking, 2104 0, 0, rects, 1, Unsorted); 2105 } 2106} 2107 2108 2109void wxWindowDC::DestroyClippingRegion() 2110{ 2111 wxDC::DestroyClippingRegion(); 2112 2113 SetDCClipping(NULL); 2114 2115 if (m_window && m_window->GetBackingPixmap()) 2116 XSetClipMask ((Display*) m_display, (GC) m_gcBacking, None); 2117} 2118 2119// Resolution in pixels per logical inch 2120wxSize wxWindowDC::GetPPI() const 2121{ 2122 // TODO 2123 return wxSize(100, 100); 2124} 2125 2126int wxWindowDC::GetDepth() const 2127{ 2128 // TODO 2129 return 24; 2130} 2131 2132 2133 2134 2135// ---------------------------------------------------------------------------- 2136// wxPaintDC 2137// ---------------------------------------------------------------------------- 2138 2139wxPaintDC::wxPaintDC(wxWindow* win) : wxWindowDC(win) 2140{ 2141 // Set the clipping region.to the update region 2142 SetDCClipping((WXRegion)NULL); 2143} 2144 2145wxPaintDC::~wxPaintDC() 2146{ 2147 if (m_window) 2148 m_window->ClearUpdateRegion(); 2149 SetDCClipping((WXRegion)NULL); 2150} 2151 2152// ---------------------------------------------------------------------------- 2153// private functions 2154// ---------------------------------------------------------------------------- 2155 2156/* 2157 Used when copying between drawables on different (Display*) m_displays. Not 2158 very fast, but better than giving up. 2159*/ 2160 2161static void XCopyRemote(Display *src_display, Display *dest_display, 2162 Drawable src, Drawable dest, 2163 GC destgc, 2164 int srcx, int srcy, 2165 unsigned int w, unsigned int h, 2166 int destx, int desty, 2167 bool more, XImage **cache) 2168{ 2169 XImage *image, *destimage; 2170 Colormap destcm, srccm; 2171 static const int CACHE_SIZE = 256; 2172 2173 unsigned int i, j; 2174 Pixel cachesrc[CACHE_SIZE], cachedest[CACHE_SIZE]; 2175 int k, cache_pos, all_cache; 2176 2177 if (!cache || !*cache) 2178 image = XGetImage(src_display, src, srcx, srcy, w, h, AllPlanes, ZPixmap); 2179 else 2180 image = *cache; 2181 2182 destimage = XGetImage(dest_display, dest, destx, desty, w, h, AllPlanes, ZPixmap); 2183 2184 srccm = (Colormap) wxTheApp->GetMainColormap((WXDisplay*) src_display); 2185 destcm = (Colormap) wxTheApp->GetMainColormap((WXDisplay*) dest_display); 2186 2187 cache_pos = 0; 2188 all_cache = False; 2189 2190 for (i = 0; i < w; i++) 2191 for (j = 0; j < h; j++) { 2192 Pixel pixel; 2193 XColor xcol; 2194 2195 pixel = XGetPixel(image, i, j); 2196 for (k = cache_pos; k--; ) 2197 if (cachesrc[k] == pixel) { 2198 pixel = cachedest[k]; 2199 goto install; 2200 } 2201 if (all_cache) 2202 for (k = CACHE_SIZE; k-- > cache_pos; ) 2203 if (cachesrc[k] == pixel) { 2204 pixel = cachedest[k]; 2205 goto install; 2206 } 2207 2208 cachesrc[cache_pos] = xcol.pixel = pixel; 2209 XQueryColor(src_display, srccm, &xcol); 2210 if (!XAllocColor(dest_display, destcm, &xcol)) 2211 xcol.pixel = 0; 2212 cachedest[cache_pos] = pixel = xcol.pixel; 2213 2214 if (++cache_pos >= CACHE_SIZE) { 2215 cache_pos = 0; 2216 all_cache = true; 2217 } 2218 2219install: 2220 XPutPixel(destimage, i, j, pixel); 2221 } 2222 2223 XPutImage(dest_display, dest, destgc, destimage, 0, 0, destx, desty, w, h); 2224 XDestroyImage(destimage); 2225 2226 if (more) 2227 *cache = image; 2228 else 2229 XDestroyImage(image); 2230} 2231 2232#if 0 2233 2234/* Helper function for 16-bit fonts */ 2235static int str16len(const char *s) 2236{ 2237 int count = 0; 2238 2239 while (s[0] && s[1]) { 2240 count++; 2241 s += 2; 2242 } 2243 2244 return count; 2245} 2246 2247#endif // 0 2248