1///////////////////////////////////////////////////////////////////////////// 2// Name: src/os2/dc.cpp 3// Purpose: wxDC class 4// Author: David Webster 5// Modified by: 6// Created: 10/14/99 7// RCS-ID: $Id: dc.cpp 51287 2008-01-19 14:10:36Z SN $ 8// Copyright: (c) David Webster 9// Licence: wxWindows licence 10///////////////////////////////////////////////////////////////////////////// 11 12// For compilers that support precompilation, includes "wx.h". 13#include "wx/wxprec.h" 14 15#ifndef WX_PRECOMP 16 #include "wx/window.h" 17 #include "wx/dc.h" 18 #include "wx/utils.h" 19 #include "wx/dialog.h" 20 #include "wx/app.h" 21 #include "wx/bitmap.h" 22 #include "wx/dcmemory.h" 23 #include "wx/log.h" 24 #include "wx/icon.h" 25 #include "wx/msgdlg.h" 26 #include "wx/dcprint.h" 27 #include "wx/statusbr.h" 28 #include "wx/module.h" 29#endif 30 31#include <string.h> 32 33#include "wx/os2/private.h" 34 35IMPLEMENT_ABSTRACT_CLASS(wxDC, wxObject) 36 37// 38// wxWidgets uses the Microsoft convention that the origin is the UPPER left. 39// Native OS/2 however in the GPI and PM define the origin as the LOWER left. 40// In order to map OS/2 GPI/PM y coordinates to wxWidgets coordinates we must 41// perform the following transformation: 42// 43// Parent object height: POBJHEIGHT 44// Desried origin: WXORIGINY 45// Object to place's height: OBJHEIGHT 46// 47// To get the OS2 position from the wxWidgets one: 48// 49// OS2Y = POBJHEIGHT - (WXORIGINY + OBJHEIGHT) 50// 51// For OS/2 wxDC's we will always determine m_vRclPaint as the size of the 52// OS/2 Presentation Space associated with the device context. y is the 53// desired application's y coordinate of the origin in wxWidgets space. 54// objy is the height of the object we are going to draw. 55// 56#define OS2Y(y, objy) ((m_vRclPaint.yTop - m_vRclPaint.yBottom) - (y + objy)) 57 58// --------------------------------------------------------------------------- 59// constants 60// --------------------------------------------------------------------------- 61 62static const int VIEWPORT_EXTENT = 1000; 63 64static const int MM_POINTS = 9; 65static const int MM_METRIC = 10; 66 67// --------------------------------------------------------------------------- 68// private functions 69// --------------------------------------------------------------------------- 70 71// convert degrees to radians 72static inline double DegToRad(double deg) { return (deg * M_PI) / 180.0; } 73 74int SetTextColor( 75 HPS hPS 76, int nForegroundColour 77) 78{ 79 CHARBUNDLE vCbnd; 80 81 vCbnd.lColor = nForegroundColour; 82 ::GpiSetAttrs( hPS // presentation-space handle 83 ,PRIM_CHAR // Char primitive. 84 ,CBB_COLOR // sets color. 85 ,0 // 86 ,&vCbnd // buffer for attributes. 87 ); 88 return 0; 89} 90 91int QueryTextBkColor( 92 HPS hPS 93) 94{ 95 CHARBUNDLE vCbnd; 96 97 ::GpiQueryAttrs( hPS // presentation-space handle 98 ,PRIM_CHAR // Char primitive. 99 ,CBB_BACK_COLOR // Background color. 100 ,&vCbnd // buffer for attributes. 101 ); 102 return vCbnd.lBackColor; 103} 104 105 106int SetTextBkColor( 107 HPS hPS 108, int nBackgroundColour 109) 110{ 111 CHARBUNDLE vCbnd; 112 int rc; 113 114 rc = QueryTextBkColor(hPS); 115 116 vCbnd.lBackColor = nBackgroundColour; 117 ::GpiSetAttrs(hPS, // presentation-space handle 118 PRIM_CHAR, // Char primitive. 119 CBB_BACK_COLOR, // sets color. 120 0, 121 &vCbnd // buffer for attributes. 122 ); 123 return rc; 124} 125 126int SetBkMode( 127 HPS hPS 128, int nBackgroundMode 129) 130{ 131 if(nBackgroundMode == wxTRANSPARENT) 132 ::GpiSetBackMix( hPS 133 ,BM_LEAVEALONE 134 ); 135 else 136 // the background of the primitive takes over whatever is underneath. 137 ::GpiSetBackMix( hPS 138 ,BM_OVERPAINT 139 ); 140 return 0; 141} 142 143// =========================================================================== 144// implementation 145// =========================================================================== 146 147#if wxUSE_DC_CACHEING 148 149/* 150 * This implementation is a bit ugly and uses the old-fashioned wxList class, so I will 151 * improve it in due course, either using arrays, or simply storing pointers to one 152 * entry for the bitmap, and two for the DCs. -- JACS 153 */ 154 155// --------------------------------------------------------------------------- 156// wxDCCacheEntry 157// --------------------------------------------------------------------------- 158 159wxList wxDC::m_svBitmapCache; 160wxList wxDC::m_svDCCache; 161 162wxDCCacheEntry::wxDCCacheEntry( 163 WXHBITMAP hBitmap 164, int nWidth 165, int nHeight 166, int nDepth 167) 168{ 169 m_hBitmap = hBitmap; 170 m_hPS = NULLHANDLE; 171 m_nWidth = nWidth; 172 m_nHeight = nHeight; 173 m_nDepth = nDepth; 174} // end of wxDCCacheEntry::wxDCCacheEntry 175 176wxDCCacheEntry::wxDCCacheEntry( 177 HPS hPS 178, int nDepth 179) 180{ 181 m_hBitmap = NULLHANDLE; 182 m_hPS = hPS; 183 m_nWidth = 0; 184 m_nHeight = 0; 185 m_nDepth = nDepth; 186} // end of wxDCCacheEntry::wxDCCacheEntry 187 188wxDCCacheEntry::~wxDCCacheEntry() 189{ 190 if (m_hBitmap) 191 ::GpiDeleteBitmap(m_hBitmap); 192 if (m_hPS) 193 ::GpiDestroyPS(m_hPS); 194} // end of wxDCCacheEntry::~wxDCCacheEntry 195 196wxDCCacheEntry* wxDC::FindBitmapInCache( 197 HPS hPS 198, int nWidth 199, int nHeight 200) 201{ 202 int nDepth = 24; // we'll fix this later ::GetDeviceCaps((HDC) dc, PLANES) * ::GetDeviceCaps((HDC) dc, BITSPIXEL); 203 wxNode* pNode = m_svBitmapCache.First(); 204 BITMAPINFOHEADER2 vBmpHdr; 205 206 while(pNode) 207 { 208 wxDCCacheEntry* pEntry = (wxDCCacheEntry*)pNode->Data(); 209 210 if (pEntry->m_nDepth == nDepth) 211 { 212 memset(&vBmpHdr, 0, sizeof(BITMAPINFOHEADER2)); 213 214 if (pEntry->m_nWidth < nWidth || pEntry->m_nHeight < nHeight) 215 { 216 ::GpiDeleteBitmap((HBITMAP)pEntry->m_hBitmap); 217 vBmpHdr.cbFix = sizeof(BITMAPINFOHEADER2); 218 vBmpHdr.cx = nWidth; 219 vBmpHdr.cy = nHeight; 220 vBmpHdr.cPlanes = 1; 221 vBmpHdr.cBitCount = (USHORT)nDepth; 222 223 pEntry->m_hBitmap = (WXHBITMAP) ::GpiCreateBitmap( hPS 224 ,&vBmpHdr 225 ,0L, NULL, NULL 226 ); 227 if (!pEntry->m_hBitmap) 228 { 229 wxLogLastError(wxT("CreateCompatibleBitmap")); 230 } 231 pEntry->m_nWidth = nWidth; 232 pEntry->m_nHeight = nHeight; 233 return pEntry; 234 } 235 return pEntry; 236 } 237 pNode = pNode->Next(); 238 } 239 memset(&vBmpHdr, 0, sizeof(BITMAPINFOHEADER2)); 240 vBmpHdr.cbFix = sizeof(BITMAPINFOHEADER2); 241 vBmpHdr.cx = nWidth; 242 vBmpHdr.cy = nHeight; 243 vBmpHdr.cPlanes = 1; 244 vBmpHdr.cBitCount = (USHORT)nDepth; 245 246 WXHBITMAP hBitmap = (WXHBITMAP) ::GpiCreateBitmap( hPS 247 ,&vBmpHdr 248 ,0L, NULL, NULL 249 ); 250 if (!hBitmap) 251 { 252 wxLogLastError(wxT("CreateCompatibleBitmap")); 253 } 254 wxDCCacheEntry* pEntry = new wxDCCacheEntry( hBitmap 255 ,nWidth 256 ,nHeight 257 ,nDepth 258 ); 259 AddToBitmapCache(pEntry); 260 return pEntry; 261} // end of FindBitmapInCache 262 263wxDCCacheEntry* wxDC::FindDCInCache( 264 wxDCCacheEntry* pNotThis 265, HPS hPS 266) 267{ 268 int nDepth = 24; // we'll fix this up later ::GetDeviceCaps((HDC) dc, PLANES) * ::GetDeviceCaps((HDC) dc, BITSPIXEL); 269 wxNode* pNode = m_svDCCache.First(); 270 271 while(pNode) 272 { 273 wxDCCacheEntry* pEntry = (wxDCCacheEntry*)pNode->Data(); 274 275 // 276 // Don't return the same one as we already have 277 // 278 if (!pNotThis || (pNotThis != pEntry)) 279 { 280 if (pEntry->m_nDepth == nDepth) 281 { 282 return pEntry; 283 } 284 } 285 pNode = pNode->Next(); 286 } 287 wxDCCacheEntry* pEntry = new wxDCCacheEntry( hPS 288 ,nDepth 289 ); 290 AddToDCCache(pEntry); 291 return pEntry; 292} // end of wxDC::FindDCInCache 293 294void wxDC::AddToBitmapCache( 295 wxDCCacheEntry* pEntry 296) 297{ 298 m_svBitmapCache.Append(pEntry); 299} // end of wxDC::AddToBitmapCache 300 301void wxDC::AddToDCCache( 302 wxDCCacheEntry* pEntry 303) 304{ 305 m_svDCCache.Append(pEntry); 306} // end of wxDC::AddToDCCache 307 308void wxDC::ClearCache() 309{ 310 m_svBitmapCache.DeleteContents(true); 311 m_svBitmapCache.Clear(); 312 m_svBitmapCache.DeleteContents(false); 313 m_svDCCache.DeleteContents(true); 314 m_svDCCache.Clear(); 315 m_svDCCache.DeleteContents(false); 316} // end of wxDC::ClearCache 317 318// Clean up cache at app exit 319class wxDCModule : public wxModule 320{ 321public: 322 virtual bool OnInit() { return true; } 323 virtual void OnExit() { wxDC::ClearCache(); } 324 325private: 326 DECLARE_DYNAMIC_CLASS(wxDCModule) 327}; // end of CLASS wxDCModule 328 329IMPLEMENT_DYNAMIC_CLASS(wxDCModule, wxModule) 330 331#endif // ndef for wxUSE_DC_CACHEING 332 333// --------------------------------------------------------------------------- 334// wxDC 335// --------------------------------------------------------------------------- 336 337wxDC::wxDC(void) 338{ 339 m_pCanvas = NULL; 340 341 m_hOldBitmap = 0; 342 m_hOldPen = 0; 343 m_hOldBrush = 0; 344 m_hOldFont = 0; 345 m_hOldPalette = 0; 346 347 m_bOwnsDC = false; 348 m_hDC = 0; 349 m_hOldPS = NULL; 350 m_hPS = NULL; 351 m_bIsPaintTime = false; // True at Paint Time 352 353 m_pen.SetColour(*wxBLACK); 354 m_brush.SetColour(*wxWHITE); 355 356} // end of wxDC::wxDC 357 358wxDC::~wxDC(void) 359{ 360 if ( m_hDC != 0 ) 361 { 362 SelectOldObjects(m_hDC); 363 364 // if we own the HDC, we delete it, otherwise we just release it 365 366 if (m_bOwnsDC) 367 { 368 if(m_hPS) 369 { 370 ::GpiAssociate(m_hPS, NULLHANDLE); 371 ::GpiDestroyPS(m_hPS); 372 } 373 m_hPS = NULLHANDLE; 374 ::DevCloseDC((HDC)m_hDC); 375 } 376 else 377 { 378 // 379 // Just Dissacociate, not destroy if we don't own the DC 380 // 381 if(m_hPS) 382 { 383 ::GpiAssociate(m_hPS, NULLHANDLE); 384 } 385 } 386 } 387} // end of wxDC::~wxDC 388 389// This will select current objects out of the DC, 390// which is what you have to do before deleting the 391// DC. 392void wxDC::SelectOldObjects( 393 WXHDC hPS 394) 395{ 396 if (hPS) 397 { 398 if (m_hOldBitmap) 399 { 400 ::GpiSetBitmap(hPS, (HBITMAP) m_hOldBitmap); 401 if (m_vSelectedBitmap.Ok()) 402 { 403 m_vSelectedBitmap.SetSelectedInto(NULL); 404 } 405 } 406 m_hOldBitmap = 0; 407 // 408 // OS/2 has no other native GDI objects to set in a PS/DC like windows 409 // 410 m_hOldPen = 0; 411 m_hOldBrush = 0; 412 m_hOldFont = 0; 413 m_hOldPalette = 0; 414 } 415 416 m_brush = wxNullBrush; 417 m_pen = wxNullPen; 418 m_palette = wxNullPalette; 419 m_font = wxNullFont; 420 m_backgroundBrush = wxNullBrush; 421 m_vSelectedBitmap = wxNullBitmap; 422} // end of wxDC::SelectOldObjects 423 424// --------------------------------------------------------------------------- 425// clipping 426// --------------------------------------------------------------------------- 427 428#define DO_SET_CLIPPING_BOX() \ 429{ \ 430 RECTL rect; \ 431 \ 432 ::GpiQueryClipBox(m_hPS, &rect); \ 433 \ 434 m_clipX1 = (wxCoord) XDEV2LOG(rect.xLeft); \ 435 m_clipY1 = (wxCoord) YDEV2LOG(rect.yTop); \ 436 m_clipX2 = (wxCoord) XDEV2LOG(rect.xRight); \ 437 m_clipY2 = (wxCoord) YDEV2LOG(rect.yBottom); \ 438} 439 440void wxDC::DoSetClippingRegion( 441 wxCoord vX 442, wxCoord vY 443, wxCoord vWidth 444, wxCoord vHeight 445) 446{ 447 RECTL vRect; 448 449 vY = OS2Y(vY,vHeight); 450 m_clipping = true; 451 vRect.xLeft = vX; 452 vRect.yTop = vY + vHeight; 453 vRect.xRight = vX + vWidth; 454 vRect.yBottom = vY; 455 ::GpiIntersectClipRectangle(m_hPS, &vRect); 456 DO_SET_CLIPPING_BOX() 457} // end of wxDC::DoSetClippingRegion 458 459void wxDC::DoSetClippingRegionAsRegion( 460 const wxRegion& rRegion 461) 462{ 463 wxCHECK_RET(rRegion.GetHRGN(), wxT("invalid clipping region")); 464 HRGN hRgnOld; 465 466 m_clipping = true; 467 ::GpiSetClipRegion( m_hPS 468 ,(HRGN)rRegion.GetHRGN() 469 ,&hRgnOld 470 ); 471 DO_SET_CLIPPING_BOX() 472} // end of wxDC::DoSetClippingRegionAsRegion 473 474void wxDC::DestroyClippingRegion(void) 475{ 476 if (m_clipping && m_hPS) 477 { 478 HRGN hRgnOld; 479 RECTL vRect; 480 481 // TODO: this should restore the previous clipped region 482 // so that OnPaint processing works correctly, and 483 // the update doesn't get destroyed after the first 484 // DestroyClippingRegion 485 vRect.xLeft = XLOG2DEV(0); 486 vRect.yTop = YLOG2DEV(32000); 487 vRect.xRight = XLOG2DEV(32000); 488 vRect.yBottom = YLOG2DEV(0); 489 490 HRGN hRgn = ::GpiCreateRegion(m_hPS, 1, &vRect); 491 492 ::GpiSetClipRegion(m_hPS, hRgn, &hRgnOld); 493 } 494 ResetClipping(); 495} // end of wxDC::DestroyClippingRegion 496 497// --------------------------------------------------------------------------- 498// query capabilities 499// --------------------------------------------------------------------------- 500 501bool wxDC::CanDrawBitmap() const 502{ 503 return true; 504} 505 506bool wxDC::CanGetTextExtent() const 507{ 508 LONG lTechnology = 0L; 509 510 ::DevQueryCaps(GetHDC(), CAPS_TECHNOLOGY, 1L, &lTechnology); 511 return (lTechnology == CAPS_TECH_RASTER_DISPLAY) || (lTechnology == CAPS_TECH_RASTER_PRINTER); 512} // end of wxDC::CanGetTextExtent 513 514int wxDC::GetDepth() const 515{ 516 LONG lCapsColorBitcount; 517 int nBitsPerPixel = 0; 518 519 if(::DevQueryCaps( GetHDC() 520 ,CAPS_COLOR_BITCOUNT 521 ,1L 522 ,&lCapsColorBitcount 523 )) 524 { 525 nBitsPerPixel = (int)lCapsColorBitcount; 526 } 527 return nBitsPerPixel; 528} // end of wxDC::GetDepth 529 530// --------------------------------------------------------------------------- 531// drawing 532// --------------------------------------------------------------------------- 533 534void wxDC::Clear() 535{ 536 // 537 // If this is a canvas DC then just fill with the background color 538 // Otherwise purge the whole thing 539 // 540 if (m_pCanvas) 541 { 542 RECTL vRect; 543 544 ::GpiQueryClipBox(m_hPS, &vRect); 545 ::WinFillRect(m_hPS, &vRect, ::GpiQueryBackColor(m_hPS)); 546 } 547 else 548 ::GpiErase(m_hPS); 549} // end of wxDC::Clear 550 551bool wxDC::DoFloodFill( 552 wxCoord vX 553, wxCoord vY 554, const wxColour& rCol 555, int nStyle 556) 557{ 558 POINTL vPtlPos; 559 LONG lColor; 560 LONG lOptions; 561 LONG lHits; 562 bool bSuccess = false; 563 564 vPtlPos.x = vX; // Loads x-coordinate 565 vPtlPos.y = OS2Y(vY,0); // Loads y-coordinate 566 ::GpiMove(m_hPS, &vPtlPos); // Sets current position 567 lColor = rCol.GetPixel(); 568 lOptions = FF_BOUNDARY; 569 if(wxFLOOD_SURFACE == nStyle) 570 lOptions = FF_SURFACE; 571 572 if ((lHits = ::GpiFloodFill(m_hPS, lOptions, lColor)) != GPI_ERROR) 573 bSuccess = true; 574 575 return bSuccess; 576} // end of wxDC::DoFloodFill 577 578bool wxDC::DoGetPixel( 579 wxCoord vX 580, wxCoord vY 581, wxColour* pCol 582) const 583{ 584 POINTL vPoint; 585 LONG lColor; 586 587 vPoint.x = vX; 588 vPoint.y = OS2Y(vY,0); 589 lColor = ::GpiQueryPel(m_hPS, &vPoint); 590 591 // 592 // return the color of the pixel 593 // 594 if(pCol) 595 pCol->Set( GetRValue(lColor) 596 ,GetGValue(lColor) 597 ,GetBValue(lColor) 598 ); 599 return true; 600} // end of wxDC::DoGetPixel 601 602void wxDC::DoCrossHair( 603 wxCoord vX 604, wxCoord vY 605) 606{ 607 vY = OS2Y(vY,0); 608 609 wxCoord vX1 = vX - VIEWPORT_EXTENT; 610 wxCoord vY1 = vY - VIEWPORT_EXTENT; 611 wxCoord vX2 = vX + VIEWPORT_EXTENT; 612 wxCoord vY2 = vY + VIEWPORT_EXTENT; 613 POINTL vPoint[4]; 614 615 vPoint[0].x = vX1; 616 vPoint[0].y = vY; 617 618 vPoint[1].x = vX2; 619 vPoint[1].y = vY; 620 621 ::GpiMove(m_hPS, &vPoint[0]); 622 ::GpiLine(m_hPS, &vPoint[1]); 623 624 vPoint[2].x = vX; 625 vPoint[2].y = vY1; 626 627 vPoint[3].x = vX; 628 vPoint[3].y = vY2; 629 630 ::GpiMove(m_hPS, &vPoint[2]); 631 ::GpiLine(m_hPS, &vPoint[3]); 632 CalcBoundingBox(vX1, vY1); 633 CalcBoundingBox(vX2, vY2); 634} // end of wxDC::DoCrossHair 635 636void wxDC::DoDrawLine( 637 wxCoord vX1 638, wxCoord vY1 639, wxCoord vX2 640, wxCoord vY2 641) 642{ 643 POINTL vPoint[2]; 644 COLORREF vColor = 0x00ffffff; 645 646 // 647 // Might be a memory DC with no Paint rect. 648 // 649 if (!(m_vRclPaint.yTop == 0 && 650 m_vRclPaint.yBottom == 0 && 651 m_vRclPaint.xRight == 0 && 652 m_vRclPaint.xLeft == 0)) 653 { 654 vY1 = OS2Y(vY1,0); 655 vY2 = OS2Y(vY2,0); 656 } 657 else 658 { 659 if (m_vSelectedBitmap.Ok()) 660 { 661 m_vRclPaint.yTop = m_vSelectedBitmap.GetHeight(); 662 m_vRclPaint.xRight = m_vSelectedBitmap.GetWidth(); 663 vY1 = OS2Y(vY1,0); 664 vY2 = OS2Y(vY2,0); 665 } 666 } 667 vPoint[0].x = vX1; 668 vPoint[0].y = vY1; 669 vPoint[1].x = vX2; 670 vPoint[1].y = vY2; 671 if (m_pen.Ok()) 672 { 673 vColor = m_pen.GetColour().GetPixel(); 674 } 675 ::GpiSetColor(m_hPS, vColor); 676 ::GpiMove(m_hPS, &vPoint[0]); 677 ::GpiLine(m_hPS, &vPoint[1]); 678 CalcBoundingBox(vX1, vY1); 679 CalcBoundingBox(vX2, vY2); 680} // end of wxDC::DoDrawLine 681 682////////////////////////////////////////////////////////////////////////////// 683// Draws an arc of a circle, centred on (xc, yc), with starting point (x1, y1) 684// and ending at (x2, y2). The current pen is used for the outline and the 685// current brush for filling the shape. The arc is drawn in an anticlockwise 686// direction from the start point to the end point. 687////////////////////////////////////////////////////////////////////////////// 688void wxDC::DoDrawArc( 689 wxCoord vX1 690, wxCoord vY1 691, wxCoord vX2 692, wxCoord vY2 693, wxCoord vXc 694, wxCoord vYc 695) 696{ 697 POINTL vPtlPos; 698 POINTL vPtlArc[2]; // Structure for current position 699 double dRadius; 700 double dAngl1; 701 double dAngl2; 702 double dAnglmid; 703 wxCoord vXm; 704 wxCoord vYm; 705 ARCPARAMS vArcp; // Structure for arc parameters 706 707 if((vX1 == vXc && vY1 == vXc) || (vX2 == vXc && vY2 == vXc)) 708 return; // Draw point ?? 709 dRadius = 0.5 * ( hypot( (double)(vY1 - vYc) 710 ,(double)(vX1 - vXc) 711 ) + 712 hypot( (double)(vY2 - vYc) 713 ,(double)(vX2 - vXc) 714 ) 715 ); 716 717 dAngl1 = atan2( (double)(vY1 - vYc) 718 ,(double)(vX1 - vXc) 719 ); 720 dAngl2 = atan2( (double)(vY2 - vYc) 721 ,(double)(vX2 - vXc) 722 ); 723 if(dAngl2 < dAngl1) 724 dAngl2 += M_PI * 2; 725 726 // 727 // GpiPointArc can't draw full arc 728 // 729 if(dAngl2 == dAngl1 || (vX1 == vX2 && vY1 == vY2) ) 730 { 731 // 732 // Medium point 733 // 734 dAnglmid = (dAngl1 + dAngl2)/2. + M_PI; 735 vXm = (wxCoord)(vXc + dRadius * cos(dAnglmid)); 736 vYm = (wxCoord)(vYc + dRadius * sin(dAnglmid)); 737 DoDrawArc( vX1, vY1 738 ,vXm, vYm 739 ,vXc, vYc 740 ); 741 DoDrawArc( vXm, vYm 742 ,vX2, vY2 743 ,vXc, vYc 744 ); 745 return; 746 } 747 748 // 749 // Medium point 750 // 751 dAnglmid = (dAngl1 + dAngl2)/2.; 752 vXm = (wxCoord)(vXc + dRadius * cos(dAnglmid)); 753 vYm = (wxCoord)(vYc + dRadius * sin(dAnglmid)); 754 755 // 756 // Ellipse main axis (r,q), (p,s) with center at (0,0) */ 757 // 758 vArcp.lR = 0; 759 vArcp.lQ = 1; 760 vArcp.lP = 1; 761 vArcp.lS = 0; 762 ::GpiSetArcParams(m_hPS, &vArcp); // Sets parameters to default 763 764 vPtlPos.x = vX1; // Loads x-coordinate 765 vPtlPos.y = vY1; // Loads y-coordinate 766 ::GpiMove(m_hPS, &vPtlPos); // Sets current position 767 vPtlArc[0].x = vXm; 768 vPtlArc[0].y = vYm; 769 vPtlArc[1].x = vX2; 770 vPtlArc[1].y = vY2; 771 ::GpiPointArc(m_hPS, vPtlArc); // Draws the arc 772 CalcBoundingBox( (wxCoord)(vXc - dRadius) 773 ,(wxCoord)(vYc - dRadius) 774 ); 775 CalcBoundingBox( (wxCoord)(vXc + dRadius) 776 ,(wxCoord)(vYc + dRadius) 777 ); 778} // end of wxDC::DoDrawArc 779 780void wxDC::DoDrawCheckMark( 781 wxCoord vX1 782, wxCoord vY1 783, wxCoord vWidth 784, wxCoord vHeight 785) 786{ 787 POINTL vPoint[2]; 788 789 vY1 = OS2Y(vY1,vHeight); 790 791 vPoint[0].x = vX1; 792 vPoint[0].y = vY1; 793 vPoint[1].x = vX1 + vWidth; 794 vPoint[1].y = vY1 + vHeight; 795 796 ::GpiMove(m_hPS, &vPoint[0]); 797 ::GpiBox( m_hPS // handle to a presentation space 798 ,DRO_OUTLINE // draw the box outline ? or ? 799 ,&vPoint[1] // address of the corner 800 ,0L // horizontal corner radius 801 ,0L // vertical corner radius 802 ); 803 if(vWidth > 4 && vHeight > 4) 804 { 805 int nTmp; 806 807 vPoint[0].x += 2; vPoint[0].y += 2; 808 vPoint[1].x -= 2; vPoint[1].y -= 2; 809 ::GpiMove(m_hPS, &vPoint[0]); 810 ::GpiLine(m_hPS, &vPoint[1]); 811 nTmp = vPoint[0].x; 812 vPoint[0].x = vPoint[1].x; 813 vPoint[1].x = nTmp; 814 ::GpiMove(m_hPS, &vPoint[0]); 815 ::GpiLine(m_hPS, &vPoint[1]); 816 } 817 CalcBoundingBox( vX1 818 ,vY1 819 ); 820 821 wxCoord vX2 = vX1 + vWidth; 822 wxCoord vY2 = vY1 + vHeight; 823 824 CalcBoundingBox( vX2 825 ,vY2 826 ); 827} // end of wxDC::DoDrawCheckMark 828 829void wxDC::DoDrawPoint( 830 wxCoord vX 831, wxCoord vY 832) 833{ 834 POINTL vPoint; 835 COLORREF vColor = 0x00ffffff; 836 837 if (m_pen.Ok()) 838 { 839 vColor = m_pen.GetColour().GetPixel(); 840 } 841 ::GpiSetColor(m_hPS, vColor); 842 vPoint.x = vX; 843 vPoint.y = OS2Y(vY,0); 844 ::GpiSetPel(m_hPS, &vPoint); 845 CalcBoundingBox( vX 846 ,vY 847 ); 848} // end of wxDC::DoDrawPoint 849 850void wxDC::DoDrawPolygon( int n, 851 wxPoint vPoints[], 852 wxCoord vXoffset, 853 wxCoord vYoffset, 854 int nFillStyle ) 855{ 856 ULONG ulCount = 1; // Number of polygons. 857 POLYGON vPlgn; // polygon. 858 ULONG flOptions = 0L; // Drawing options. 859 860 ////////////////////////////////////////////////////////////////////////////// 861 // This contains fields of option bits... to draw boundary lines as well as 862 // the area interior. 863 // 864 // Drawing boundary lines: 865 // POLYGON_NOBOUNDARY Does not draw boundary lines. 866 // POLYGON_BOUNDARY Draws boundary lines (the default). 867 // 868 // Construction of the area interior: 869 // POLYGON_ALTERNATE Constructs interior in alternate mode 870 // (the default). 871 // POLYGON_WINDING Constructs interior in winding mode. 872 ////////////////////////////////////////////////////////////////////////////// 873 874 ULONG flModel = POLYGON_INCL; // Drawing model. 875 876 ////////////////////////////////////////////////////////////////////////////// 877 // Drawing model. 878 // POLYGON_INCL Fill is inclusive of bottom right (the default). 879 // POLYGON_EXCL Fill is exclusive of bottom right. 880 // This is provided to aid migration from other graphics models. 881 ////////////////////////////////////////////////////////////////////////////// 882 883 LONG lHits = 0L; // Correlation/error indicator. 884 int i; 885 int nIsTRANSPARENT = 0; 886 LONG lBorderColor = 0L; 887 LONG lColor = 0L; 888 889 lBorderColor = m_pen.GetColour().GetPixel(); 890 lColor = m_brush.GetColour().GetPixel(); 891 if(m_brush.GetStyle() == wxTRANSPARENT) 892 nIsTRANSPARENT = 1; 893 894 vPlgn.ulPoints = n; 895 vPlgn.aPointl = (POINTL*) calloc( n + 1 896 ,sizeof(POINTL) 897 ); // well, new will call malloc 898 899 for(i = 0; i < n; i++) 900 { 901 vPlgn.aPointl[i].x = vPoints[i].x+vXoffset; 902 vPlgn.aPointl[i].y = OS2Y(vPoints[i].y+vYoffset,0); 903 } 904 flOptions = POLYGON_BOUNDARY; 905 if(nFillStyle == wxWINDING_RULE) 906 flOptions |= POLYGON_WINDING; 907 else 908 flOptions |= POLYGON_ALTERNATE; 909 910 ::GpiSetColor(m_hPS, lBorderColor); 911 ::GpiMove(m_hPS, &vPlgn.aPointl[0]); 912 lHits = ::GpiPolygons(m_hPS, ulCount, &vPlgn, flOptions, flModel); 913 free(vPlgn.aPointl); 914} // end of wxDC::DoDrawPolygon 915 916void wxDC::DoDrawLines( 917 int n 918, wxPoint vPoints[] 919, wxCoord vXoffset 920, wxCoord vYoffset 921) 922{ 923 POINTL vPoint; 924 925 if (vXoffset != 0L || vXoffset != 0L) 926 { 927 int i; 928 929 vPoint.x = vPoints[0].x + vXoffset; 930 vPoint.y = OS2Y(vPoints[0].y + vYoffset,0); 931 ::GpiMove(m_hPS, &vPoint); 932 933 LONG lBorderColor = m_pen.GetColour().GetPixel(); 934 935 ::GpiSetColor(m_hPS, lBorderColor); 936 for(i = 1; i < n; i++) 937 { 938 vPoint.x = vPoints[i].x + vXoffset; 939 vPoint.y = OS2Y(vPoints[i].y + vYoffset,0); 940 ::GpiLine(m_hPS, &vPoint); 941 } 942 } 943 else 944 { 945 int i; 946 947 CalcBoundingBox( vPoints[0].x 948 ,vPoints[0].y 949 ); 950 vPoint.x = vPoints[0].x; 951 vPoint.y = OS2Y(vPoints[0].y,0); 952 ::GpiMove(m_hPS, &vPoint); 953 954 for (i = 0; i < n; i++) 955 { 956 CalcBoundingBox( vPoints[i].x 957 ,vPoints[i].y 958 ); 959 vPoint.x = vPoints[i].x; 960 vPoint.y = OS2Y(vPoints[i].y,0); 961 ::GpiLine(m_hPS, &vPoint); 962 } 963 } 964} // end of wxDC::DoDrawLines 965 966void wxDC::DoDrawRectangle( 967 wxCoord vX 968, wxCoord vY 969, wxCoord vWidth 970, wxCoord vHeight 971) 972{ 973 POINTL vPoint[2]; 974 LONG lControl; 975 LONG lColor; 976 LONG lBorderColor; 977 int nIsTRANSPARENT = 0; 978 979 // 980 // Might be a memory DC with no Paint rect. 981 // 982 if (!(m_vRclPaint.yTop == 0 && 983 m_vRclPaint.yBottom == 0 && 984 m_vRclPaint.xRight == 0 && 985 m_vRclPaint.xLeft == 0)) 986 vY = OS2Y(vY,vHeight); 987 else 988 { 989 if (m_vSelectedBitmap.Ok()) 990 { 991 m_vRclPaint.yTop = m_vSelectedBitmap.GetHeight(); 992 m_vRclPaint.xRight = m_vSelectedBitmap.GetWidth(); 993 vY = OS2Y(vY,vHeight); 994 } 995 } 996 997 wxCoord vX2 = vX + vWidth; 998 wxCoord vY2 = vY + vHeight; 999 1000 vPoint[0].x = vX; 1001 vPoint[0].y = vY; 1002 vPoint[1].x = vX + vWidth - 1; 1003 vPoint[1].y = vY + vHeight - 1; 1004 ::GpiMove(m_hPS, &vPoint[0]); 1005 lColor = m_brush.GetColour().GetPixel(); 1006 lBorderColor = m_pen.GetColour().GetPixel(); 1007 if (m_brush.GetStyle() == wxTRANSPARENT) 1008 nIsTRANSPARENT = 1; 1009 if(lColor == lBorderColor || nIsTRANSPARENT) 1010 { 1011 lControl = DRO_OUTLINEFILL; //DRO_FILL; 1012 if(m_brush.GetStyle() == wxTRANSPARENT) 1013 lControl = DRO_OUTLINE; 1014 1015 ::GpiSetColor(m_hPS, lBorderColor); 1016 ::GpiBox( m_hPS // handle to a presentation space 1017 ,lControl // draw the box outline ? or ? 1018 ,&vPoint[1] // address of the corner 1019 ,0L // horizontal corner radius 1020 ,0L // vertical corner radius 1021 ); 1022 } 1023 else 1024 { 1025 lControl = DRO_OUTLINE; 1026 ::GpiSetColor( m_hPS 1027 ,lBorderColor 1028 ); 1029 ::GpiBox( m_hPS 1030 ,lControl 1031 ,&vPoint[1] 1032 ,0L 1033 ,0L 1034 ); 1035 lControl = DRO_FILL; 1036 ::GpiSetColor( m_hPS 1037 ,lColor 1038 ); 1039 vPoint[0].x = vX + 1; 1040 vPoint[0].y = vY + 1; 1041 vPoint[1].x = vX + vWidth - 2; 1042 vPoint[1].y = vY + vHeight - 2; 1043 ::GpiMove(m_hPS, &vPoint[0]); 1044 ::GpiBox( m_hPS 1045 ,lControl 1046 ,&vPoint[1] 1047 ,0L 1048 ,0L 1049 ); 1050 } 1051 CalcBoundingBox(vX, vY); 1052 CalcBoundingBox(vX2, vY2); 1053} // end of wxDC::DoDrawRectangle 1054 1055void wxDC::DoDrawRoundedRectangle( 1056 wxCoord vX 1057, wxCoord vY 1058, wxCoord vWidth 1059, wxCoord vHeight 1060, double dRadius 1061) 1062{ 1063 POINTL vPoint[2]; 1064 LONG lControl; 1065 LONG lColor; 1066 LONG lBorderColor; 1067 int nIsTRANSPARENT = 0; 1068 1069 // 1070 // Might be a memory DC with no Paint rect. 1071 // 1072 if (!(m_vRclPaint.yTop == 0 && 1073 m_vRclPaint.yBottom == 0 && 1074 m_vRclPaint.xRight == 0 && 1075 m_vRclPaint.xLeft == 0)) 1076 vY = OS2Y(vY,vHeight); 1077 else 1078 { 1079 if (m_vSelectedBitmap.Ok()) 1080 { 1081 m_vRclPaint.yTop = m_vSelectedBitmap.GetHeight(); 1082 m_vRclPaint.xRight = m_vSelectedBitmap.GetWidth(); 1083 vY = OS2Y(vY,vHeight); 1084 } 1085 } 1086 1087 wxCoord vX2 = (vX + vWidth); 1088 wxCoord vY2 = (vY + vHeight); 1089 1090 vPoint[0].x = vX; 1091 vPoint[0].y = vY; 1092 vPoint[1].x = vX + vWidth - 1; 1093 vPoint[1].y = vY + vHeight - 1; 1094 ::GpiMove(m_hPS, &vPoint[0]); 1095 1096 lColor = m_brush.GetColour().GetPixel(); 1097 lBorderColor = m_pen.GetColour().GetPixel(); 1098 lControl = DRO_OUTLINEFILL; //DRO_FILL; 1099 if (m_brush.GetStyle() == wxTRANSPARENT) 1100 nIsTRANSPARENT = 1; 1101 if(lColor == lBorderColor || nIsTRANSPARENT) 1102 { 1103 lControl = DRO_OUTLINEFILL; //DRO_FILL; 1104 if(m_brush.GetStyle() == wxTRANSPARENT) 1105 lControl = DRO_OUTLINE; 1106 1107 ::GpiSetColor(m_hPS, lColor); 1108 ::GpiBox( m_hPS // handle to a presentation space 1109 ,lControl // draw the box outline ? or ? 1110 ,&vPoint[1] // address of the corner 1111 ,(LONG)dRadius // horizontal corner radius 1112 ,(LONG)dRadius // vertical corner radius 1113 ); 1114 } 1115 else 1116 { 1117 lControl = DRO_OUTLINE; 1118 ::GpiSetColor( m_hPS 1119 ,lBorderColor 1120 ); 1121 ::GpiBox( m_hPS 1122 ,lControl 1123 ,&vPoint[1] 1124 ,(LONG)dRadius 1125 ,(LONG)dRadius 1126 ); 1127 lControl = DRO_FILL; 1128 ::GpiSetColor( m_hPS 1129 ,lColor 1130 ); 1131 vPoint[0].x = vX + 1; 1132 vPoint[0].y = vY + 1; 1133 vPoint[1].x = vX + vWidth - 2; 1134 vPoint[1].y = vY + vHeight - 2; 1135 ::GpiMove(m_hPS, &vPoint[0]); 1136 ::GpiBox( m_hPS 1137 ,lControl 1138 ,&vPoint[1] 1139 ,(LONG)dRadius 1140 ,(LONG)dRadius 1141 ); 1142 } 1143 1144 CalcBoundingBox(vX, vY); 1145 CalcBoundingBox(vX2, vY2); 1146} // end of wxDC::DoDrawRoundedRectangle 1147 1148// Draw Ellipse within box (x,y) - (x+width, y+height) 1149void wxDC::DoDrawEllipse( 1150 wxCoord vX 1151, wxCoord vY 1152, wxCoord vWidth 1153, wxCoord vHeight 1154) 1155{ 1156 POINTL vPtlPos; // Structure for current position 1157 FIXED vFxMult; // Multiplier for ellipse 1158 ARCPARAMS vArcp; // Structure for arc parameters 1159 1160 vY = OS2Y(vY,vHeight); 1161 1162 vArcp.lR = 0; 1163 vArcp.lQ = vHeight/2; 1164 vArcp.lP = vWidth/2; 1165 vArcp.lS = 0; 1166 ::GpiSetArcParams( m_hPS 1167 ,&vArcp 1168 ); // Sets parameters to default 1169 vPtlPos.x = vX + vWidth/2; // Loads x-coordinate 1170 vPtlPos.y = vY + vHeight/2; // Loads y-coordinate 1171 ::GpiMove( m_hPS 1172 ,&vPtlPos 1173 ); // Sets current position 1174 vFxMult = MAKEFIXED(1, 0); /* Sets multiplier */ 1175 1176 // 1177 // DRO_FILL, DRO_OTLINEFILL - where to get 1178 // 1179 ::GpiFullArc( m_hPS 1180 ,DRO_OUTLINE 1181 ,vFxMult 1182 ); // Draws full arc with center at current position 1183 1184 wxCoord vX2 = (vX + vWidth); 1185 wxCoord vY2 = (vY + vHeight); 1186 1187 CalcBoundingBox(vX, vY); 1188 CalcBoundingBox(vX2, vY2); 1189} // end of wxDC::DoDrawEllipse 1190 1191void wxDC::DoDrawEllipticArc( 1192 wxCoord vX 1193, wxCoord vY 1194, wxCoord vWidth 1195, wxCoord vHeight 1196, double dSa 1197, double dEa 1198) 1199{ 1200 POINTL vPtlPos; // Structure for current position 1201 FIXED vFxMult; // Multiplier for ellipse 1202 ARCPARAMS vArcp; // Structure for arc parameters 1203 FIXED vFSa; 1204 FIXED vFSweepa; // Start angle, sweep angle 1205 double dIntPart; 1206 double dFractPart; 1207 1208 vY = OS2Y(vY,vHeight); 1209 1210 dFractPart = modf(dSa,&dIntPart); 1211 vFSa = MAKEFIXED((int)dIntPart, (int)(dFractPart * 0xffff) ); 1212 dFractPart = modf(dEa - dSa, &dIntPart); 1213 vFSweepa = MAKEFIXED((int)dIntPart, (int)(dFractPart * 0xffff) ); 1214 1215 // 1216 // Ellipse main axis (r,q), (p,s) with center at (0,0) 1217 // 1218 vArcp.lR = 0; 1219 vArcp.lQ = vHeight/2; 1220 vArcp.lP = vWidth/2; 1221 vArcp.lS = 0; 1222 ::GpiSetArcParams(m_hPS, &vArcp); // Sets parameters to default 1223 vPtlPos.x = (wxCoord)(vX + vWidth/2 * (1. + cos(DegToRad(dSa)))); // Loads x-coordinate 1224 vPtlPos.y = (wxCoord)(vY + vHeight/2 * (1. + sin(DegToRad(dSa)))); // Loads y-coordinate 1225 ::GpiMove(m_hPS, &vPtlPos); // Sets current position 1226 1227 // 1228 // May be not to the center ? 1229 // 1230 vPtlPos.x = vX + vWidth/2 ; // Loads x-coordinate 1231 vPtlPos.y = vY + vHeight/2; // Loads y-coordinate 1232 vFxMult = MAKEFIXED(1, 0); // Sets multiplier 1233 1234 // 1235 // DRO_FILL, DRO_OTLINEFILL - where to get 1236 // 1237 ::GpiPartialArc( m_hPS 1238 ,&vPtlPos 1239 ,vFxMult 1240 ,vFSa 1241 ,vFSweepa 1242 ); 1243 wxCoord vX2 = (vX + vWidth); 1244 wxCoord vY2 = (vY + vHeight); 1245 1246 CalcBoundingBox(vX, vY); 1247 CalcBoundingBox(vX2, vY2); 1248} // end of wxDC::DoDrawEllipticArc 1249 1250void wxDC::DoDrawIcon( 1251 const wxIcon& rIcon 1252, wxCoord vX 1253, wxCoord vY 1254) 1255{ 1256 // 1257 // Need to copy back into a bitmap. ::WinDrawPointer uses device coords 1258 // and I don't feel like figuring those out for scrollable windows so 1259 // just convert to a bitmap then let the DoDrawBitmap routine display it 1260 // 1261 if (rIcon.IsXpm()) 1262 { 1263 DoDrawBitmap(rIcon.GetXpmSrc(), vX, vY, true); 1264 } 1265 else 1266 { 1267 wxBitmap vBitmap(rIcon); 1268 1269 DoDrawBitmap(vBitmap, vX, vY, false); 1270 } 1271 CalcBoundingBox(vX, vY); 1272 CalcBoundingBox(vX + rIcon.GetWidth(), vY + rIcon.GetHeight()); 1273} // end of wxDC::DoDrawIcon 1274 1275void wxDC::DoDrawBitmap( 1276 const wxBitmap& rBmp 1277, wxCoord vX 1278, wxCoord vY 1279, bool bUseMask 1280) 1281{ 1282#if wxUSE_PRINTING_ARCHITECTURE 1283 if (!IsKindOf(CLASSINFO(wxPrinterDC))) 1284#endif 1285 { 1286 HBITMAP hBitmap = (HBITMAP)rBmp.GetHBITMAP(); 1287 HBITMAP hBitmapOld = NULLHANDLE; 1288 POINTL vPoint[4]; 1289 1290 vY = OS2Y(vY,rBmp.GetHeight()); 1291 1292 vPoint[0].x = vX; 1293 vPoint[0].y = vY + rBmp.GetHeight(); 1294 vPoint[1].x = vX + rBmp.GetWidth(); 1295 vPoint[1].y = vY; 1296 vPoint[2].x = 0; 1297 vPoint[2].y = 0; 1298 vPoint[3].x = rBmp.GetWidth(); 1299 vPoint[3].y = rBmp.GetHeight(); 1300 if (bUseMask) 1301 { 1302 wxMask* pMask = rBmp.GetMask(); 1303 1304 if (pMask) 1305 { 1306 // 1307 // Need to imitate ::MaskBlt in windows. 1308 // 1) Extract the bits from from the bitmap. 1309 // 2) Extract the bits from the mask 1310 // 3) Using the mask bits do the following: 1311 // A) If the mask byte is 00 leave the bitmap byte alone 1312 // B) If the mask byte is FF copy the screen color into 1313 // bitmap byte 1314 // 4) Create a new bitmap and set its bits to the above result 1315 // 5) Blit this to the screen PS 1316 // 1317 HBITMAP hMask = (HBITMAP)pMask->GetMaskBitmap(); 1318 HBITMAP hOldMask = NULLHANDLE; 1319 HBITMAP hOldBitmap = NULLHANDLE; 1320 HBITMAP hNewBitmap = NULLHANDLE; 1321 unsigned char* pucBits; // buffer that will contain the bitmap data 1322 unsigned char* pucBitsMask; // buffer that will contain the mask data 1323 unsigned char* pucData; // pointer to use to traverse bitmap data 1324 unsigned char* pucDataMask; // pointer to use to traverse mask data 1325 LONG lHits; 1326 ERRORID vError; 1327 wxString sError; 1328 1329 // 1330 // The usual Memory context creation stuff 1331 // 1332 DEVOPENSTRUC vDop = {0L, "DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L}; 1333 SIZEL vSize = {0, 0}; 1334 HDC hDC = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDop, NULLHANDLE); 1335 HPS hPS = ::GpiCreatePS(vHabmain, hDC, &vSize, PU_PELS | GPIA_ASSOC); 1336 1337 // 1338 // The usual bitmap header stuff 1339 // 1340 BITMAPINFOHEADER2 vHeader; 1341 BITMAPINFO2 vInfo; 1342 1343 memset(&vHeader, '\0', 16); 1344 vHeader.cbFix = 16; 1345 1346 memset(&vInfo, '\0', 16); 1347 vInfo.cbFix = 16; 1348 vInfo.cx = (ULONG)rBmp.GetWidth(); 1349 vInfo.cy = (ULONG)rBmp.GetHeight(); 1350 vInfo.cPlanes = 1; 1351 vInfo.cBitCount = 24; // Set to desired count going in 1352 1353 // 1354 // Create the buffers for data....all wxBitmaps are 24 bit internally 1355 // 1356 int nBytesPerLine = rBmp.GetWidth() * 3; 1357 int nSizeDWORD = sizeof(DWORD); 1358 int nLineBoundary = nBytesPerLine % nSizeDWORD; 1359 int nPadding = 0; 1360 int i; 1361 int j; 1362 LONG lScans = 0L; 1363 LONG lColor = 0L; 1364 1365 // 1366 // Need to get a background color for mask blitting 1367 // 1368 if (IsKindOf(CLASSINFO(wxWindowDC))) 1369 { 1370 wxWindowDC* pWindowDC = wxDynamicCast(this, wxWindowDC); 1371 1372 lColor = pWindowDC->m_pCanvas->GetBackgroundColour().GetPixel(); 1373 } 1374 else if (GetBrush().Ok()) 1375 lColor = GetBrush().GetColour().GetPixel(); 1376 else 1377 lColor = m_textBackgroundColour.GetPixel(); 1378 1379 // 1380 // Bitmap must be in a double-word aligned address so we may 1381 // have some padding to worry about 1382 // 1383 if (nLineBoundary > 0) 1384 { 1385 nPadding = nSizeDWORD - nLineBoundary; 1386 nBytesPerLine += nPadding; 1387 } 1388 pucBits = (unsigned char *)malloc(nBytesPerLine * rBmp.GetHeight()); 1389 pucBitsMask = (unsigned char *)malloc(nBytesPerLine * rBmp.GetHeight()); 1390 memset(pucBits, '\0', (nBytesPerLine * rBmp.GetHeight())); 1391 memset(pucBitsMask, '\0', (nBytesPerLine * rBmp.GetHeight())); 1392 1393 // 1394 // Extract the bitmap and mask data 1395 // 1396 if ((hOldBitmap = ::GpiSetBitmap(hPS, hBitmap)) == HBM_ERROR) 1397 { 1398 vError = ::WinGetLastError(vHabmain); 1399 sError = wxPMErrorToStr(vError); 1400 } 1401 ::GpiQueryBitmapInfoHeader(hBitmap, &vHeader); 1402 vInfo.cBitCount = 24; 1403 if ((lScans = ::GpiQueryBitmapBits( hPS 1404 ,0L 1405 ,(LONG)rBmp.GetHeight() 1406 ,(PBYTE)pucBits 1407 ,&vInfo 1408 )) == GPI_ALTERROR) 1409 { 1410 vError = ::WinGetLastError(vHabmain); 1411 sError = wxPMErrorToStr(vError); 1412 } 1413 if ((hOldMask = ::GpiSetBitmap(hPS, hMask)) == HBM_ERROR) 1414 { 1415 vError = ::WinGetLastError(vHabmain); 1416 sError = wxPMErrorToStr(vError); 1417 } 1418 ::GpiQueryBitmapInfoHeader(hMask, &vHeader); 1419 vInfo.cBitCount = 24; 1420 if ((lScans = ::GpiQueryBitmapBits( hPS 1421 ,0L 1422 ,(LONG)rBmp.GetHeight() 1423 ,(PBYTE)pucBitsMask 1424 ,&vInfo 1425 )) == GPI_ALTERROR) 1426 { 1427 vError = ::WinGetLastError(vHabmain); 1428 sError = wxPMErrorToStr(vError); 1429 } 1430 if (( hMask = ::GpiSetBitmap(hPS, hOldMask)) == HBM_ERROR) 1431 { 1432 vError = ::WinGetLastError(vHabmain); 1433 sError = wxPMErrorToStr(vError); 1434 } 1435 1436 // 1437 // Now set the bytes(bits) according to the mask values 1438 // 3 bytes per pel...must handle one at a time 1439 // 1440 pucData = pucBits; 1441 pucDataMask = pucBitsMask; 1442 1443 // 1444 // 16 bit kludge really only kinda works. The mask gets applied 1445 // where needed but the original bitmap bits are dorked sometimes 1446 // 1447 bool bpp16 = (wxDisplayDepth() == 16); 1448 1449 for (i = 0; i < rBmp.GetHeight(); i++) 1450 { 1451 for (j = 0; j < rBmp.GetWidth(); j++) 1452 { 1453 // Byte 1 1454 if (bpp16 && *pucDataMask == 0xF8) // 16 bit display gobblygook 1455 pucData++; 1456 else if (*pucDataMask == 0xFF) // leave bitmap byte alone 1457 pucData++; 1458 else 1459 { 1460 *pucData = ((unsigned char)(lColor >> 16)); 1461 pucData++; 1462 } 1463 // Byte 2 1464 if (bpp16 && *(pucDataMask + 1) == 0xFC) // 16 bit display gobblygook 1465 pucData++; 1466 else if (*(pucDataMask + 1) == 0xFF) // leave bitmap byte alone 1467 pucData++; 1468 else 1469 { 1470 *pucData = ((unsigned char)(lColor >> 8)); 1471 pucData++; 1472 } 1473 1474 // Byte 3 1475 if (bpp16 && *(pucDataMask + 2) == 0xF8) // 16 bit display gobblygook 1476 pucData++; 1477 else if (*(pucDataMask + 2) == 0xFF) // leave bitmap byte alone 1478 pucData++; 1479 else 1480 { 1481 *pucData = ((unsigned char)lColor); 1482 pucData++; 1483 } 1484 pucDataMask += 3; 1485 } 1486 for (j = 0; j < nPadding; j++) 1487 { 1488 pucData++; 1489 pucDataMask++; 1490 } 1491 } 1492 // 1493 // Create a new bitmap 1494 // 1495 vHeader.cx = (ULONG)rBmp.GetWidth(); 1496 vHeader.cy = (ULONG)rBmp.GetHeight(); 1497 vHeader.cPlanes = 1L; 1498 vHeader.cBitCount = 24; 1499 if ((hNewBitmap = ::GpiCreateBitmap( hPS 1500 ,&vHeader 1501 ,CBM_INIT 1502 ,(PBYTE)pucBits 1503 ,&vInfo 1504 )) == GPI_ERROR) 1505 { 1506 vError = ::WinGetLastError(vHabmain); 1507 sError = wxPMErrorToStr(vError); 1508 } 1509 1510 // 1511 // Now blit it to the screen PS 1512 // 1513 if ((lHits = ::GpiWCBitBlt( (HPS)GetHPS() 1514 ,hNewBitmap 1515 ,4 1516 ,vPoint 1517 ,ROP_SRCCOPY 1518 ,BBO_IGNORE 1519 )) == GPI_ERROR) 1520 { 1521 vError = ::WinGetLastError(vHabmain); 1522 sError = wxPMErrorToStr(vError); 1523 } 1524 1525 // 1526 // Clean up 1527 // 1528 free(pucBits); 1529 free(pucBitsMask); 1530 ::GpiSetBitmap(hPS, NULLHANDLE); 1531 ::GpiDeleteBitmap(hNewBitmap); 1532 ::GpiDestroyPS(hPS); 1533 ::DevCloseDC(hDC); 1534 } 1535 } 1536 else 1537 { 1538 ULONG lOldForeGround = ::GpiQueryColor((HPS)GetHPS()); 1539 ULONG lOldBackGround = ::GpiQueryBackColor((HPS)GetHPS()); 1540 1541 if (m_textForegroundColour.Ok()) 1542 { 1543 ::GpiSetColor( (HPS)GetHPS() 1544 ,m_textForegroundColour.GetPixel() 1545 ); 1546 } 1547 if (m_textBackgroundColour.Ok()) 1548 { 1549 ::GpiSetBackColor( (HPS)GetHPS() 1550 ,m_textBackgroundColour.GetPixel() 1551 ); 1552 } 1553 // 1554 // Need to alter bits in a mono bitmap to match the new 1555 // background-foreground if it is different. 1556 // 1557 if (rBmp.IsMono() && 1558 ((m_textForegroundColour.GetPixel() != lOldForeGround) || 1559 (m_textBackgroundColour.GetPixel() != lOldBackGround))) 1560 { 1561 DEVOPENSTRUC vDop = {0L, "DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L}; 1562 SIZEL vSize = {0, 0}; 1563 HDC hDC = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDop, NULLHANDLE); 1564 HPS hPS = ::GpiCreatePS(vHabmain, hDC, &vSize, PU_PELS | GPIA_ASSOC); 1565 1566 int nBytesPerLine = rBmp.GetWidth() * 3; 1567 int i, j; 1568 LONG lForeGround = m_textForegroundColour.GetPixel(); 1569 LONG lBackGround = m_textBackgroundColour.GetPixel(); 1570 LONG lScans; 1571 HBITMAP hOldBitmap = NULLHANDLE; 1572 BITMAPINFO2 vInfo; 1573 ERRORID vError; 1574 wxString sError; 1575 1576 1577 memset(&vInfo, '\0', 16); 1578 vInfo.cbFix = 16; 1579 vInfo.cx = (ULONG)rBmp.GetWidth(); 1580 vInfo.cy = (ULONG)rBmp.GetHeight(); 1581 vInfo.cPlanes = 1; 1582 vInfo.cBitCount = 24; 1583 1584 unsigned char* pucBits; // buffer that will contain the bitmap data 1585 unsigned char* pucData; // pointer to use to traverse bitmap data 1586 1587 pucBits = new unsigned char[nBytesPerLine * rBmp.GetHeight()]; 1588 memset(pucBits, '\0', (nBytesPerLine * rBmp.GetHeight())); 1589 1590 if ((hOldBitmap = ::GpiSetBitmap(hPS, hBitmap)) == HBM_ERROR) 1591 { 1592 vError = ::WinGetLastError(vHabmain); 1593 sError = wxPMErrorToStr(vError); 1594 return; 1595 } 1596 if ((lScans = ::GpiQueryBitmapBits( hPS 1597 ,0L 1598 ,(LONG)rBmp.GetHeight() 1599 ,(PBYTE)pucBits 1600 ,&vInfo 1601 )) == GPI_ALTERROR) 1602 { 1603 vError = ::WinGetLastError(vHabmain); 1604 sError = wxPMErrorToStr(vError); 1605 return; 1606 } 1607 unsigned char cOldRedFore = (unsigned char)(lOldForeGround >> 16); 1608 unsigned char cOldGreenFore = (unsigned char)(lOldForeGround >> 8); 1609 unsigned char cOldBlueFore = (unsigned char)lOldForeGround; 1610 1611 unsigned char cRedFore = (unsigned char)(lForeGround >> 16); 1612 unsigned char cGreenFore = (unsigned char)(lForeGround >> 8); 1613 unsigned char cBlueFore = (unsigned char)lForeGround; 1614 1615 unsigned char cRedBack = (unsigned char)(lBackGround >> 16); 1616 unsigned char cGreenBack = (unsigned char)(lBackGround >> 8); 1617 unsigned char cBlueBack = (unsigned char)lBackGround; 1618 1619 pucData = pucBits; 1620 for (i = 0; i < rBmp.GetHeight(); i++) 1621 { 1622 for (j = 0; j < rBmp.GetWidth(); j++) 1623 { 1624 unsigned char cBmpRed = *pucData; 1625 unsigned char cBmpGreen = *(pucData + 1); 1626 unsigned char cBmpBlue = *(pucData + 2); 1627 1628 if ((cBmpRed == cOldRedFore) && 1629 (cBmpGreen == cOldGreenFore) && 1630 (cBmpBlue == cOldBlueFore)) 1631 { 1632 *pucData = cBlueFore; 1633 pucData++; 1634 *pucData = cGreenFore; 1635 pucData++; 1636 *pucData = cRedFore; 1637 pucData++; 1638 } 1639 else 1640 { 1641 *pucData = cBlueBack; 1642 pucData++; 1643 *pucData = cGreenBack; 1644 pucData++; 1645 *pucData = cRedBack; 1646 pucData++; 1647 } 1648 } 1649 } 1650 if ((lScans = ::GpiSetBitmapBits( hPS 1651 ,0L 1652 ,(LONG)rBmp.GetHeight() 1653 ,(PBYTE)pucBits 1654 ,&vInfo 1655 )) == GPI_ALTERROR) 1656 { 1657 vError = ::WinGetLastError(vHabmain); 1658 sError = wxPMErrorToStr(vError); 1659 return; 1660 } 1661 delete [] pucBits; 1662 ::GpiSetBitmap(hPS, NULLHANDLE); 1663 ::GpiDestroyPS(hPS); 1664 ::DevCloseDC(hDC); 1665 } 1666 ::GpiWCBitBlt( (HPS)GetHPS() 1667 ,hBitmap 1668 ,4 1669 ,vPoint 1670 ,ROP_SRCCOPY 1671 ,BBO_IGNORE 1672 ); 1673 ::GpiSetBitmap((HPS)GetHPS(), hBitmapOld); 1674 ::GpiSetColor((HPS)GetHPS(), lOldForeGround); 1675 ::GpiSetBackColor((HPS)GetHPS(), lOldBackGround); 1676 } 1677 } 1678} // end of wxDC::DoDrawBitmap 1679 1680void wxDC::DoDrawText( 1681 const wxString& rsText 1682, wxCoord vX 1683, wxCoord vY 1684) 1685{ 1686 wxCoord vWidth; 1687 wxCoord vHeight; 1688 1689 DrawAnyText( rsText 1690 ,vX 1691 ,vY 1692 ); 1693 1694 CalcBoundingBox(vX, vY); 1695 GetTextExtent(rsText, &vWidth, &vHeight); 1696 CalcBoundingBox((vX + vWidth), (vY + vHeight)); 1697} // end of wxDC::DoDrawText 1698 1699void wxDC::DrawAnyText( const wxString& rsText, 1700 wxCoord vX, 1701 wxCoord vY ) 1702{ 1703 int nOldBackground = 0; 1704 POINTL vPtlStart; 1705 LONG lHits; 1706 wxCoord vTextX = 0; 1707 wxCoord vTextY = 0; 1708 1709 // 1710 // prepare for drawing the text 1711 // 1712 1713 // 1714 // Set text color attributes 1715 // 1716 if (m_textForegroundColour.Ok()) 1717 { 1718 SetTextColor( m_hPS 1719 ,(int)m_textForegroundColour.GetPixel() 1720 ); 1721 } 1722 1723 if (m_textBackgroundColour.Ok()) 1724 { 1725 nOldBackground = SetTextBkColor( m_hPS 1726 ,(int)m_textBackgroundColour.GetPixel() 1727 ); 1728 } 1729 SetBkMode( m_hPS 1730 ,m_backgroundMode 1731 ); 1732 GetTextExtent( rsText 1733 ,&vTextX 1734 ,&vTextY 1735 ); 1736 vPtlStart.x = vX; 1737 if (!(m_vRclPaint.yTop == 0 && 1738 m_vRclPaint.yBottom == 0 && 1739 m_vRclPaint.xRight == 0 && 1740 m_vRclPaint.xLeft == 0)) 1741 { 1742 vPtlStart.y = OS2Y(vY,vTextY); 1743 } 1744 else 1745 { 1746 if (m_vSelectedBitmap.Ok()) 1747 { 1748 m_vRclPaint.yTop = m_vSelectedBitmap.GetHeight(); 1749 m_vRclPaint.xRight = m_vSelectedBitmap.GetWidth(); 1750 vPtlStart.y = OS2Y(vY,vTextY); 1751 } 1752 else 1753 vPtlStart.y = vY; 1754 } 1755 1756 PCH pzStr = (PCH)rsText.c_str(); 1757 1758 ::GpiMove(m_hPS, &vPtlStart); 1759 lHits = ::GpiCharString( m_hPS 1760 ,rsText.length() 1761 ,pzStr 1762 ); 1763 if (lHits != GPI_OK) 1764 { 1765 wxLogLastError(wxT("TextOut")); 1766 } 1767 1768 // 1769 // Restore the old parameters (text foreground colour may be left because 1770 // it never is set to anything else, but background should remain 1771 // transparent even if we just drew an opaque string) 1772 // 1773 if (m_textBackgroundColour.Ok()) 1774 SetTextBkColor( m_hPS 1775 ,nOldBackground 1776 ); 1777 SetBkMode( m_hPS 1778 ,wxTRANSPARENT 1779 ); 1780} 1781 1782void wxDC::DoDrawRotatedText( 1783 const wxString& rsText 1784, wxCoord vX 1785, wxCoord vY 1786, double dAngle 1787) 1788{ 1789 if (dAngle == 0.0) 1790 { 1791 DoDrawText( rsText 1792 ,vX 1793 ,vY 1794 ); 1795 } 1796 1797 // TODO: 1798 /* 1799 if ( angle == 0.0 ) 1800 { 1801 DoDrawText(text, x, y); 1802 } 1803 else 1804 { 1805 LOGFONT lf; 1806 wxFillLogFont(&lf, &m_font); 1807 1808 // GDI wants the angle in tenth of degree 1809 long angle10 = (long)(angle * 10); 1810 lf.lfEscapement = angle10; 1811 lf. lfOrientation = angle10; 1812 1813 HFONT hfont = ::CreateFontIndirect(&lf); 1814 if ( !hfont ) 1815 { 1816 wxLogLastError("CreateFont"); 1817 } 1818 else 1819 { 1820 HFONT hfontOld = ::SelectObject(GetHdc(), hfont); 1821 1822 DrawAnyText(text, x, y); 1823 1824 (void)::SelectObject(GetHdc(), hfontOld); 1825 } 1826 1827 // call the bounding box by adding all four vertices of the rectangle 1828 // containing the text to it (simpler and probably not slower than 1829 // determining which of them is really topmost/leftmost/...) 1830 wxCoord w, h; 1831 GetTextExtent(text, &w, &h); 1832 1833 double rad = DegToRad(angle); 1834 1835 // "upper left" and "upper right" 1836 CalcBoundingBox(x, y); 1837 CalcBoundingBox(x + w*cos(rad), y - h*sin(rad)); 1838 CalcBoundingBox(x + h*sin(rad), y + h*cos(rad)); 1839 1840 // "bottom left" and "bottom right" 1841 x += (wxCoord)(h*sin(rad)); 1842 y += (wxCoord)(h*cos(rad)); 1843 CalcBoundingBox(x, y); 1844 CalcBoundingBox(x + h*sin(rad), y + h*cos(rad)); 1845 } 1846*/ 1847} 1848 1849// --------------------------------------------------------------------------- 1850// set GDI objects 1851// --------------------------------------------------------------------------- 1852 1853void wxDC::DoSelectPalette( bool WXUNUSED(bRealize) ) 1854{ 1855 // 1856 // Set the old object temporarily, in case the assignment deletes an object 1857 // that's not yet selected out. 1858 // 1859 if (m_hOldPalette) 1860 { 1861 m_hOldPalette = 0; 1862 } 1863 1864 if (m_palette.Ok()) 1865 { 1866 HPALETTE hOldPal; 1867 1868 hOldPal = ::GpiSelectPalette((HDC) m_hPS, (HPALETTE) m_palette.GetHPALETTE()); 1869 if (!m_hOldPalette) 1870 m_hOldPalette = (WXHPALETTE)hOldPal; 1871 } 1872} // end of wxDC::DoSelectPalette 1873 1874void wxDC::InitializePalette() 1875{ 1876 if (wxDisplayDepth() <= 8 ) 1877 { 1878 // 1879 // Look for any window or parent that has a custom palette. If any has 1880 // one then we need to use it in drawing operations 1881 // 1882 wxWindow* pWin = m_pCanvas->GetAncestorWithCustomPalette(); 1883 1884 m_hasCustomPalette = pWin && pWin->HasCustomPalette(); 1885 if (m_hasCustomPalette) 1886 { 1887 m_palette = pWin->GetPalette(); 1888 1889 // 1890 // turn on PM translation for this palette 1891 // 1892 DoSelectPalette(); 1893 } 1894 } 1895} // end of wxDC::InitializePalette 1896 1897void wxDC::SetPalette( 1898 const wxPalette& rPalette 1899) 1900{ 1901 if (m_hOldFont) 1902 { 1903 m_hOldFont = 0; 1904 } 1905 m_palette = rPalette; 1906 if (!rPalette.Ok()) 1907 { 1908 if (m_hOldFont) 1909 { 1910 m_hOldFont = 0; 1911 } 1912 } 1913 HPALETTE hOldPal = ::GpiSelectPalette((HDC) m_hPS, (HPALETTE) m_palette.GetHPALETTE()); 1914 if (!m_hOldPalette) 1915 m_hOldPalette = (WXHPALETTE)hOldPal; 1916} // end of wxDC::SetPalette 1917 1918void wxDC::SetFont( 1919 const wxFont& rFont 1920) 1921{ 1922 // 1923 // Set the old object temporarily, in case the assignment deletes an object 1924 // that's not yet selected out. 1925 // 1926 if (m_hOldFont) 1927 { 1928 m_hOldFont = 0; 1929 } 1930 m_font = rFont; 1931 if (!rFont.Ok()) 1932 { 1933 m_hOldFont = 0; 1934 } 1935 1936 m_font.SetPS(m_hPS); // this will realize the font 1937 1938 if (m_font.Ok()) 1939 { 1940 HFONT hFont = m_font.GetResourceHandle(); 1941 if (hFont == (HFONT) NULL) 1942 { 1943 wxLogDebug(wxT("::SelectObject failed in wxDC::SetFont.")); 1944 } 1945 if (!m_hOldFont) 1946 m_hOldFont = (WXHFONT) hFont; 1947 } 1948} // end of wxDC::SetFont 1949 1950void wxDC::SetPen( 1951 const wxPen& rPen 1952) 1953{ 1954 wxCHECK_RET( Ok(), wxT("invalid window dc") ); 1955 1956 if (m_pen == rPen) 1957 return; 1958 m_pen = rPen; 1959 if (!m_pen.Ok()) 1960 return; 1961 1962 if (m_hOldPen) 1963 m_hOldPen = 0L; 1964 m_pen = rPen; 1965 1966 if (!m_pen.Ok()) 1967 { 1968 if (m_hOldPen) 1969 { 1970 m_pen.SetPS((HPS)m_hOldPen); 1971 } 1972 m_hOldPen = 0L; 1973 } 1974 1975 if (m_pen.Ok()) 1976 { 1977 if (m_pen.GetResourceHandle()) 1978 { 1979 m_pen.SetPS(m_hPS); 1980 if (!m_hOldPen) 1981 m_hOldPen = m_pen.GetPS(); 1982 } 1983 ::GpiSetColor(m_hPS, m_pen.GetColour().GetPixel()); 1984 } 1985} 1986 1987void wxDC::SetBrush( 1988 const wxBrush& rBrush 1989) 1990{ 1991 wxCHECK_RET( Ok(), wxT("invalid window dc") ); 1992 1993 if (m_hOldBrush) 1994 m_hOldBrush = 0L; 1995 m_brush = rBrush; 1996 if (!m_brush.Ok()) 1997 if (m_brush == rBrush) 1998 return; 1999 if (!m_brush.Ok()) 2000 if (m_hOldBrush) 2001 m_hOldBrush = 0L; 2002 2003 if (!m_brush.Ok()) 2004 { 2005 if (m_hOldBrush) 2006 { 2007 m_brush.SetPS((HPS)m_hOldBrush); 2008 } 2009 m_hOldBrush = 0L; 2010 } 2011 2012 if (m_brush.Ok()) 2013 { 2014 if (m_brush.GetResourceHandle()) 2015 { 2016 m_brush.SetPS(m_hPS); 2017 if (!m_hOldBrush) 2018 m_hOldBrush = (WXHWND)m_brush.GetPS(); 2019 } 2020 } 2021} // end of wxDC::SetBrush 2022 2023void wxDC::SetBackground(const wxBrush& rBrush) 2024{ 2025 m_backgroundBrush = rBrush; 2026 2027 if (m_backgroundBrush.Ok()) 2028 { 2029 (void)::GpiSetBackColor((HPS)m_hPS, m_backgroundBrush.GetColour().GetPixel()); 2030 } 2031} // end of wxDC::SetBackground 2032 2033void wxDC::SetBackgroundMode(int nMode) 2034{ 2035 m_backgroundMode = nMode; 2036} // end of wxDC::SetBackgroundMode 2037 2038void wxDC::SetLogicalFunction(int nFunction) 2039{ 2040 m_logicalFunction = nFunction; 2041 SetRop((WXHDC)m_hDC); 2042} // wxDC::SetLogicalFunction 2043 2044void wxDC::SetRop(WXHDC hDC) 2045{ 2046 if (!hDC || m_logicalFunction < 0) 2047 return; 2048 2049 LONG lCRop; 2050 switch (m_logicalFunction) 2051 { 2052 case wxXOR: 2053 lCRop = FM_XOR; 2054 break; 2055 2056 case wxINVERT: 2057 lCRop = FM_INVERT; 2058 break; 2059 2060 case wxOR_REVERSE: 2061 lCRop = FM_MERGESRCNOT; 2062 break; 2063 2064 case wxAND_REVERSE: 2065 lCRop = FM_NOTMASKSRC; 2066 break; 2067 2068 case wxCLEAR: 2069 lCRop = FM_ONE; 2070 break; 2071 2072 case wxSET: 2073 lCRop = FM_ZERO; 2074 break; 2075 2076 case wxSRC_INVERT: 2077 lCRop = FM_MERGENOTSRC; 2078 break; 2079 2080 case wxOR_INVERT: 2081 lCRop = FM_MERGESRCNOT; 2082 break; 2083 2084 case wxAND: 2085 lCRop = FM_AND; 2086 break; 2087 2088 case wxOR: 2089 lCRop = FM_OR; 2090 break; 2091 2092 case wxAND_INVERT: 2093 lCRop = FM_SUBTRACT; 2094 break; 2095 2096 case wxEQUIV: 2097 case wxNAND: 2098 case wxCOPY: 2099 default: 2100 lCRop = FM_OVERPAINT; 2101 break; 2102 } 2103 ::GpiSetMix((HPS)hDC, lCRop); 2104} // end of wxDC::SetRop 2105 2106bool wxDC::StartDoc( const wxString& WXUNUSED(rsMessage) ) 2107{ 2108 // We might be previewing, so return true to let it continue. 2109 return true; 2110} // end of wxDC::StartDoc 2111 2112void wxDC::EndDoc() 2113{ 2114} // end of wxDC::EndDoc 2115 2116void wxDC::StartPage() 2117{ 2118} // end of wxDC::StartPage 2119 2120void wxDC::EndPage() 2121{ 2122} // end of wxDC::EndPage 2123 2124// --------------------------------------------------------------------------- 2125// text metrics 2126// --------------------------------------------------------------------------- 2127 2128wxCoord wxDC::GetCharHeight() const 2129{ 2130 FONTMETRICS vFM; // metrics structure 2131 2132 ::GpiQueryFontMetrics( m_hPS 2133 ,sizeof(FONTMETRICS) 2134 ,&vFM 2135 ); 2136 return YDEV2LOGREL(vFM.lXHeight); 2137} 2138 2139wxCoord wxDC::GetCharWidth() const 2140{ 2141 FONTMETRICS vFM; // metrics structure 2142 2143 ::GpiQueryFontMetrics( m_hPS 2144 ,sizeof(FONTMETRICS) 2145 ,&vFM 2146 ); 2147 return XDEV2LOGREL(vFM.lAveCharWidth); 2148} 2149 2150void wxDC::DoGetTextExtent( 2151 const wxString& rsString 2152, wxCoord* pvX 2153, wxCoord* pvY 2154, wxCoord* pvDescent 2155, wxCoord* pvExternalLeading 2156, wxFont* pTheFont 2157) const 2158{ 2159 POINTL avPoint[TXTBOX_COUNT]; 2160 POINTL vPtMin; 2161 POINTL vPtMax; 2162 int i; 2163 int l; 2164 FONTMETRICS vFM; // metrics structure 2165 BOOL bRc; 2166 ERRORID vErrorCode; // last error id code 2167 wxFont* pFontToUse = (wxFont*)pTheFont; 2168 2169 wxChar zMsg[128]; // DEBUG 2170 wxString sError; 2171 2172 if (!pFontToUse) 2173 pFontToUse = (wxFont*)&m_font; 2174 l = rsString.length(); 2175 2176 // 2177 // In world coordinates. 2178 // 2179 bRc = ::GpiQueryTextBox( m_hPS 2180 ,l 2181 ,(PCH)rsString.c_str() 2182 ,TXTBOX_COUNT // return maximum information 2183 ,avPoint // array of coordinates points 2184 ); 2185 if(!bRc) 2186 { 2187 vErrorCode = ::WinGetLastError(wxGetInstance()); 2188 sError = wxPMErrorToStr(vErrorCode); 2189 // DEBUG 2190 wxSprintf(zMsg, _T("GpiQueryTextBox for %s: failed with Error: %lx - %s"), rsString.c_str(), vErrorCode, sError.c_str()); 2191 (void)wxMessageBox( _T("wxWidgets Menu sample") 2192 ,zMsg 2193 ,wxICON_INFORMATION 2194 ); 2195 } 2196 2197 vPtMin.x = avPoint[0].x; 2198 vPtMax.x = avPoint[0].x; 2199 vPtMin.y = avPoint[0].y; 2200 vPtMax.y = avPoint[0].y; 2201 for (i = 1; i < 4; i++) 2202 { 2203 if(vPtMin.x > avPoint[i].x) vPtMin.x = avPoint[i].x; 2204 if(vPtMin.y > avPoint[i].y) vPtMin.y = avPoint[i].y; 2205 if(vPtMax.x < avPoint[i].x) vPtMax.x = avPoint[i].x; 2206 if(vPtMax.y < avPoint[i].y) vPtMax.y = avPoint[i].y; 2207 } 2208 ::GpiQueryFontMetrics( m_hPS 2209 ,sizeof(FONTMETRICS) 2210 ,&vFM 2211 ); 2212 2213 if (pvX) 2214 *pvX = (wxCoord)(vPtMax.x - vPtMin.x + 1); 2215 if (pvY) 2216 *pvY = (wxCoord)(vPtMax.y - vPtMin.y + 1); 2217 if (pvDescent) 2218 *pvDescent = vFM.lMaxDescender; 2219 if (pvExternalLeading) 2220 *pvExternalLeading = vFM.lExternalLeading; 2221} 2222 2223void wxDC::SetMapMode( 2224 int nMode 2225) 2226{ 2227 int nPixelWidth = 0; 2228 int nPixelHeight = 0; 2229 int nMmWidth = 1; 2230 int nMmHeight = 1; 2231 LONG lArray[CAPS_VERTICAL_RESOLUTION+1]; 2232 2233 m_mappingMode = nMode; 2234 2235 if(::DevQueryCaps( m_hDC 2236 ,CAPS_FAMILY // id of first item 2237 ,CAPS_VERTICAL_RESOLUTION+1 // number of items wanted 2238 ,lArray 2239 )) 2240 { 2241 LONG lHorzRes; 2242 LONG lVertRes; 2243 2244 nPixelWidth = lArray[CAPS_WIDTH]; 2245 nPixelHeight = lArray[CAPS_HEIGHT]; 2246 lHorzRes = lArray[CAPS_HORIZONTAL_RESOLUTION]; // returns pel/meter 2247 lVertRes = lArray[CAPS_VERTICAL_RESOLUTION]; // returns pel/meter 2248 nMmWidth = (lHorzRes/1000) * nPixelWidth; 2249 nMmHeight = (lVertRes/1000) * nPixelHeight; 2250 } 2251 if ((nPixelWidth == 0) || (nPixelHeight == 0) || (nMmWidth == 0) || (nMmHeight == 0)) 2252 { 2253 return; 2254 } 2255 2256 double dMm2pixelsX = nPixelWidth/(double)nMmWidth; 2257 double dMm2pixelsY = nPixelHeight/(double)nMmHeight; 2258 2259 switch (nMode) 2260 { 2261 case wxMM_TWIPS: 2262 m_logicalScaleX = (twips2mm * dMm2pixelsX); 2263 m_logicalScaleY = (twips2mm * dMm2pixelsY); 2264 break; 2265 2266 case wxMM_POINTS: 2267 m_logicalScaleX = (pt2mm * dMm2pixelsX); 2268 m_logicalScaleY = (pt2mm * dMm2pixelsY); 2269 break; 2270 2271 case wxMM_METRIC: 2272 m_logicalScaleX = dMm2pixelsX; 2273 m_logicalScaleY = dMm2pixelsY; 2274 break; 2275 2276 case wxMM_LOMETRIC: 2277 m_logicalScaleX = (dMm2pixelsX/10.0); 2278 m_logicalScaleY = (dMm2pixelsY/10.0); 2279 break; 2280 2281 case wxMM_TEXT: 2282 default: 2283 m_logicalScaleX = 1.0; 2284 m_logicalScaleY = 1.0; 2285 break; 2286 } 2287 2288 SIZEL vSize; 2289 ULONG ulOptions; 2290 2291 ulOptions = ::GpiQueryPS(m_hPS, &vSize); 2292 if (!ulOptions & PU_ARBITRARY) 2293 { 2294 ulOptions = PU_ARBITRARY | GPIF_DEFAULT; 2295 ::GpiSetPS(m_hPS, &vSize, ulOptions); 2296 } 2297}; // end of wxDC::SetMapMode 2298 2299void wxDC::SetUserScale( double dX, 2300 double dY ) 2301{ 2302 m_userScaleX = dX; 2303 m_userScaleY = dY; 2304 2305 SetMapMode(m_mappingMode); 2306} // end of wxDC::SetUserScale 2307 2308void wxDC::SetAxisOrientation( bool bXLeftRight, 2309 bool bYBottomUp ) 2310{ 2311 m_signX = bXLeftRight ? 1 : -1; 2312 m_signY = bYBottomUp ? -1 : 1; 2313 2314 SetMapMode(m_mappingMode); 2315} // end of wxDC::SetAxisOrientation 2316 2317void wxDC::SetSystemScale( 2318 double dX 2319, double dY 2320) 2321{ 2322 m_scaleX = dX; 2323 m_scaleY = dY; 2324 2325 SetMapMode(m_mappingMode); 2326} // end of wxDC::SetSystemScale 2327 2328void wxDC::SetLogicalOrigin( 2329 wxCoord vX 2330, wxCoord vY 2331) 2332{ 2333 RECTL vRect; 2334 2335 ::GpiQueryPageViewport( m_hPS 2336 ,&vRect 2337 ); 2338 vRect.xRight -= vX; 2339 vRect.yTop += vY; 2340 vRect.xLeft = vX; 2341 vRect.yBottom = vY; 2342 ::GpiSetPageViewport( m_hPS 2343 ,&vRect 2344 ); 2345}; // end of wxDC::SetLogicalOrigin 2346 2347void wxDC::SetDeviceOrigin( 2348 wxCoord vX 2349, wxCoord vY 2350) 2351{ 2352 RECTL vRect; 2353 2354 m_deviceOriginX = vX; 2355 m_deviceOriginY = vY; 2356 ::GpiQueryPageViewport( m_hPS 2357 ,&vRect 2358 ); 2359 vRect.xLeft += vX; 2360 vRect.xRight += vX; 2361 vRect.yBottom -= vY; 2362 vRect.yTop -= vY; 2363 ::GpiSetPageViewport( m_hPS 2364 ,&vRect 2365 ); 2366}; // end of wxDC::SetDeviceOrigin 2367 2368// --------------------------------------------------------------------------- 2369// coordinates transformations 2370// --------------------------------------------------------------------------- 2371 2372wxCoord wxDCBase::DeviceToLogicalX(wxCoord x) const 2373{ 2374 return (wxCoord) (((x) - m_deviceOriginX)/(m_logicalScaleX*m_userScaleX*m_signX*m_scaleX) - m_logicalOriginX); 2375} 2376 2377wxCoord wxDCBase::DeviceToLogicalXRel(wxCoord x) const 2378{ 2379 // axis orientation is not taken into account for conversion of a distance 2380 return (wxCoord) ((x)/(m_logicalScaleX*m_userScaleX*m_scaleX)); 2381} 2382 2383wxCoord wxDCBase::DeviceToLogicalY(wxCoord y) const 2384{ 2385 return (wxCoord) (((y) - m_deviceOriginY)/(m_logicalScaleY*m_userScaleY*m_signY*m_scaleY) - m_logicalOriginY); 2386} 2387 2388wxCoord wxDCBase::DeviceToLogicalYRel(wxCoord y) const 2389{ 2390 // axis orientation is not taken into account for conversion of a distance 2391 return (wxCoord) ((y)/(m_logicalScaleY*m_userScaleY*m_scaleY)); 2392} 2393 2394wxCoord wxDCBase::LogicalToDeviceX(wxCoord x) const 2395{ 2396 return (wxCoord) ((x - m_logicalOriginX)*m_logicalScaleX*m_userScaleX*m_signX*m_scaleX + m_deviceOriginX); 2397} 2398 2399wxCoord wxDCBase::LogicalToDeviceXRel(wxCoord x) const 2400{ 2401 // axis orientation is not taken into account for conversion of a distance 2402 return (wxCoord) (x*m_logicalScaleX*m_userScaleX*m_scaleX); 2403} 2404 2405wxCoord wxDCBase::LogicalToDeviceY(wxCoord y) const 2406{ 2407 return (wxCoord) ((y - m_logicalOriginY)*m_logicalScaleY*m_userScaleY*m_signY*m_scaleY + m_deviceOriginY); 2408} 2409 2410wxCoord wxDCBase::LogicalToDeviceYRel(wxCoord y) const 2411{ 2412 // axis orientation is not taken into account for conversion of a distance 2413 return (wxCoord) (y*m_logicalScaleY*m_userScaleY*m_scaleY); 2414} 2415 2416// --------------------------------------------------------------------------- 2417// bit blit 2418// --------------------------------------------------------------------------- 2419 2420bool wxDC::DoBlit( wxCoord vXdest, 2421 wxCoord vYdest, 2422 wxCoord vWidth, 2423 wxCoord vHeight, 2424 wxDC* pSource, 2425 wxCoord vXsrc, 2426 wxCoord vYsrc, 2427 int nRop, 2428 bool bUseMask, 2429 wxCoord WXUNUSED(vXsrcMask), 2430 wxCoord WXUNUSED(vYsrcMask) ) 2431{ 2432 wxMask* pMask = NULL; 2433 CHARBUNDLE vCbnd; 2434 COLORREF vOldTextColor; 2435 COLORREF vOldBackground = ::GpiQueryBackColor(m_hPS); 2436 2437 if (bUseMask) 2438 { 2439 const wxBitmap& rBmp = pSource->m_vSelectedBitmap; 2440 2441 pMask = rBmp.GetMask(); 2442 if (!(rBmp.Ok() && pMask && pMask->GetMaskBitmap())) 2443 { 2444 bUseMask = false; 2445 } 2446 } 2447 2448 ::GpiQueryAttrs( m_hPS 2449 ,PRIM_CHAR 2450 ,CBB_COLOR 2451 ,&vCbnd 2452 ); 2453 vOldTextColor = (COLORREF)vCbnd.lColor; 2454 2455 if (m_textForegroundColour.Ok()) 2456 { 2457 vCbnd.lColor = (LONG)m_textForegroundColour.GetPixel(); 2458 ::GpiSetAttrs( m_hPS // presentation-space handle 2459 ,PRIM_CHAR // Char primitive. 2460 ,CBB_COLOR // sets color. 2461 ,0 2462 ,&vCbnd // buffer for attributes. 2463 ); 2464 } 2465 if (m_textBackgroundColour.Ok()) 2466 { 2467 ::GpiSetBackColor(m_hPS, (LONG)m_textBackgroundColour.GetPixel()); 2468 } 2469 2470 LONG lRop = ROP_SRCCOPY; 2471 2472 switch (nRop) 2473 { 2474 case wxXOR: lRop = ROP_SRCINVERT; break; 2475 case wxINVERT: lRop = ROP_DSTINVERT; break; 2476 case wxOR_REVERSE: lRop = 0x00DD0228; break; 2477 case wxAND_REVERSE: lRop = ROP_SRCERASE; break; 2478 case wxCLEAR: lRop = ROP_ZERO; break; 2479 case wxSET: lRop = ROP_ONE; break; 2480 case wxOR_INVERT: lRop = ROP_MERGEPAINT; break; 2481 case wxAND: lRop = ROP_SRCAND; break; 2482 case wxOR: lRop = ROP_SRCPAINT; break; 2483 case wxEQUIV: lRop = 0x00990066; break; 2484 case wxNAND: lRop = 0x007700E6; break; 2485 case wxAND_INVERT: lRop = 0x00220326; break; 2486 case wxCOPY: lRop = ROP_SRCCOPY; break; 2487 case wxNO_OP: lRop = ROP_NOTSRCERASE; break; 2488 case wxSRC_INVERT: lRop = ROP_SRCINVERT; break; 2489 case wxNOR: lRop = ROP_NOTSRCCOPY; break; 2490 default: 2491 wxFAIL_MSG( wxT("unsupported logical function") ); 2492 return false; 2493 } 2494 2495 bool bSuccess; 2496 2497 if (bUseMask) 2498 { 2499 // 2500 // Blit bitmap with mask 2501 // 2502 2503 // 2504 // Create a temp buffer bitmap and DCs/PSs to access it and the mask 2505 // 2506 HDC hDCMask; 2507 HDC hDCBuffer; 2508 HPS hPSMask; 2509 HPS hPSBuffer; 2510 DEVOPENSTRUC vDOP = {0L, "DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L}; 2511 BITMAPINFOHEADER2 vBmpHdr; 2512 HBITMAP hBufBitmap; 2513 SIZEL vSize = {0, 0}; 2514 LONG rc; 2515 2516 memset(&vBmpHdr, 0, sizeof(BITMAPINFOHEADER2)); 2517 vBmpHdr.cbFix = sizeof(BITMAPINFOHEADER2); 2518 vBmpHdr.cx = vWidth; 2519 vBmpHdr.cy = vHeight; 2520 vBmpHdr.cPlanes = 1; 2521 vBmpHdr.cBitCount = 24; 2522 2523#if wxUSE_DC_CACHEING 2524 { 2525 // 2526 // create a temp buffer bitmap and DCs to access it and the mask 2527 // 2528 wxDCCacheEntry* pDCCacheEntry1 = FindDCInCache( NULL 2529 ,pSource->GetHPS() 2530 ); 2531 wxDCCacheEntry* pDCCacheEntry2 = FindDCInCache( pDCCacheEntry1 2532 ,GetHPS() 2533 ); 2534 wxDCCacheEntry* pBitmapCacheEntry = FindBitmapInCache( GetHPS() 2535 ,vWidth 2536 ,vHeight 2537 ); 2538 2539 hPSMask = pDCCacheEntry1->m_hPS; 2540 hDCBuffer = (HDC)pDCCacheEntry2->m_hPS; 2541 hBufBitmap = (HBITMAP)pBitmapCacheEntry->m_hBitmap; 2542 wxUnusedVar(hDCMask); 2543 } 2544#else 2545 { 2546 hDCMask = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDOP, NULLHANDLE); 2547 hDCBuffer = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDOP, NULLHANDLE); 2548 hPSMask = ::GpiCreatePS(vHabmain, hDCMask, &vSize, PU_PELS | GPIT_MICRO | GPIA_ASSOC); 2549 hPSBuffer = ::GpiCreatePS(vHabmain, hDCBuffer, &vSize, PU_PELS | GPIT_MICRO | GPIA_ASSOC); 2550 hBufBitmap = ::GpiCreateBitmap(GetHPS(), &vBmpHdr, 0L, NULL, NULL); 2551 } 2552#endif 2553 2554 POINTL aPoint1[4] = { {0, 0} 2555 ,{vWidth, vHeight} 2556 ,{vXdest, vYdest} 2557 ,{vXdest + vWidth, vYdest + vHeight} 2558 }; 2559 POINTL aPoint2[4] = { {0, 0} 2560 ,{vWidth, vHeight} 2561 ,{vXsrc, vYsrc} 2562 ,{vXsrc + vWidth, vYsrc + vHeight} 2563 }; 2564 POINTL aPoint3[4] = { {vXdest, vYdest} 2565 ,{vXdest + vWidth, vYdest + vHeight} 2566 ,{vXsrc, vYsrc} 2567 ,{vXsrc + vWidth, vYsrc + vHeight} 2568 }; 2569 POINTL aPoint4[4] = { {vXdest, vYdest} 2570 ,{vXdest + vWidth, vYdest + vHeight} 2571 ,{0, 0} 2572 ,{vWidth, vHeight} 2573 }; 2574 ::GpiSetBitmap(hPSMask, (HBITMAP) pMask->GetMaskBitmap()); 2575 ::GpiSetBitmap(hPSBuffer, (HBITMAP) hBufBitmap); 2576 2577 // 2578 // Copy dest to buffer 2579 // 2580 rc = ::GpiBitBlt( hPSBuffer 2581 ,GetHPS() 2582 ,4L 2583 ,aPoint1 2584 ,ROP_SRCCOPY 2585 ,BBO_IGNORE 2586 ); 2587 if (rc == GPI_ERROR) 2588 { 2589 wxLogLastError(wxT("BitBlt")); 2590 } 2591 2592 // 2593 // Copy src to buffer using selected raster op 2594 // 2595 rc = ::GpiBitBlt( hPSBuffer 2596 ,GetHPS() 2597 ,4L 2598 ,aPoint2 2599 ,lRop 2600 ,BBO_IGNORE 2601 ); 2602 if (rc == GPI_ERROR) 2603 { 2604 wxLogLastError(wxT("BitBlt")); 2605 } 2606 2607 // 2608 // Set masked area in buffer to BLACK (pixel value 0) 2609 // 2610 COLORREF vPrevBkCol = ::GpiQueryBackColor(GetHPS()); 2611 COLORREF vPrevCol = ::GpiQueryColor(GetHPS()); 2612 2613 ::GpiSetBackColor(GetHPS(), OS2RGB(255, 255, 255)); 2614 ::GpiSetColor(GetHPS(), OS2RGB(0, 0, 0)); 2615 2616 rc = ::GpiBitBlt( hPSBuffer 2617 ,hPSMask 2618 ,4L 2619 ,aPoint2 2620 ,ROP_SRCAND 2621 ,BBO_IGNORE 2622 ); 2623 if (rc == GPI_ERROR) 2624 { 2625 wxLogLastError(wxT("BitBlt")); 2626 } 2627 2628 // 2629 // Set unmasked area in dest to BLACK 2630 // 2631 ::GpiSetBackColor(GetHPS(), OS2RGB(0, 0, 0)); 2632 ::GpiSetColor(GetHPS(), OS2RGB(255, 255, 255)); 2633 rc = ::GpiBitBlt( GetHPS() 2634 ,hPSMask 2635 ,4L 2636 ,aPoint3 2637 ,ROP_SRCAND 2638 ,BBO_IGNORE 2639 ); 2640 if (rc == GPI_ERROR) 2641 { 2642 wxLogLastError(wxT("BitBlt")); 2643 } 2644 2645 // 2646 // Restore colours to original values 2647 // 2648 ::GpiSetBackColor(GetHPS(), vPrevBkCol); 2649 ::GpiSetColor(GetHPS(), vPrevCol); 2650 2651 // 2652 // OR buffer to dest 2653 // 2654 rc = ::GpiBitBlt( GetHPS() 2655 ,hPSMask 2656 ,4L 2657 ,aPoint4 2658 ,ROP_SRCPAINT 2659 ,BBO_IGNORE 2660 ); 2661 if (rc == GPI_ERROR) 2662 { 2663 bSuccess = false; 2664 wxLogLastError(wxT("BitBlt")); 2665 } 2666 2667 // 2668 // Tidy up temporary DCs and bitmap 2669 // 2670 ::GpiSetBitmap(hPSMask, NULLHANDLE); 2671 ::GpiSetBitmap(hPSBuffer, NULLHANDLE); 2672#if !wxUSE_DC_CACHEING 2673 ::GpiDestroyPS(hPSMask); 2674 ::GpiDestroyPS(hPSBuffer); 2675 ::DevCloseDC(hDCMask); 2676 ::DevCloseDC(hDCBuffer); 2677 ::GpiDeleteBitmap(hBufBitmap); 2678#endif 2679 bSuccess = true; 2680 } 2681 else // no mask, just BitBlt() it 2682 { 2683 POINTL aPoint[4] = { {vXdest, vYdest} 2684 ,{vXdest + vWidth, vYdest + vHeight} 2685 ,{vXsrc, vYsrc} 2686 ,{vXsrc + vWidth, vYsrc + vHeight} 2687 }; 2688 2689 bSuccess = (::GpiBitBlt( m_hPS 2690 ,pSource->GetHPS() 2691 ,4L 2692 ,aPoint 2693 ,lRop 2694 ,BBO_IGNORE 2695 ) != GPI_ERROR); 2696 if (!bSuccess ) 2697 { 2698 wxLogLastError(wxT("BitBlt")); 2699 } 2700 } 2701 vCbnd.lColor = (LONG)vOldTextColor; 2702 ::GpiSetAttrs( m_hPS // presentation-space handle 2703 ,PRIM_CHAR // Char primitive. 2704 ,CBB_COLOR // sets color. 2705 ,0 2706 ,&vCbnd // buffer for attributes. 2707 ); 2708 ::GpiSetBackColor(m_hPS, (LONG)vOldBackground); 2709 return bSuccess; 2710} 2711 2712void wxDC::DoGetSize( int* pnWidth, 2713 int* pnHeight ) const 2714{ 2715 LONG lArray[CAPS_HEIGHT+1]; 2716 2717 if(::DevQueryCaps( m_hDC 2718 ,CAPS_FAMILY 2719 ,CAPS_HEIGHT+1 2720 ,lArray 2721 )) 2722 { 2723 if (pnWidth) 2724 *pnWidth = lArray[CAPS_WIDTH]; 2725 if (pnHeight) 2726 *pnHeight = lArray[CAPS_HEIGHT]; 2727 } 2728}; // end of wxDC::DoGetSize( 2729 2730void wxDC::DoGetSizeMM( int* pnWidth, 2731 int* pnHeight ) const 2732{ 2733 LONG lArray[CAPS_VERTICAL_RESOLUTION+1]; 2734 2735 if(::DevQueryCaps( m_hDC 2736 ,CAPS_FAMILY 2737 ,CAPS_VERTICAL_RESOLUTION+1 2738 ,lArray 2739 )) 2740 { 2741 if(pnWidth) 2742 { 2743 int nWidth = lArray[CAPS_WIDTH]; 2744 int nHorzRes = lArray[CAPS_HORIZONTAL_RESOLUTION]; // returns pel/meter 2745 // use fp to avoid returning 0 if nHorzRes < 1000 2746 *pnWidth = (int)((nHorzRes/1000.0) * nWidth); 2747 } 2748 2749 if(pnHeight) 2750 { 2751 int nHeight = lArray[CAPS_HEIGHT]; 2752 int nVertRes = lArray[CAPS_VERTICAL_RESOLUTION]; // returns pel/meter 2753 // use fp to avoid returning 0 if nVertRes < 1000 2754 *pnHeight = (int)((nVertRes/1000.0) * nHeight); 2755 } 2756 } 2757}; // end of wxDC::DoGetSizeMM 2758 2759wxSize wxDC::GetPPI() const 2760{ 2761 LONG lArray[CAPS_VERTICAL_RESOLUTION+1]; 2762 int nWidth = 0; 2763 int nHeight = 0; 2764 2765 if(::DevQueryCaps( m_hDC 2766 ,CAPS_FAMILY 2767 ,CAPS_VERTICAL_RESOLUTION+1 2768 ,lArray 2769 )) 2770 { 2771 int nPelWidth; 2772 int nPelHeight; 2773 int nHorzRes; 2774 int nVertRes; 2775 2776 nPelWidth = lArray[CAPS_WIDTH]; 2777 nPelHeight = lArray[CAPS_HEIGHT]; 2778 nHorzRes = lArray[CAPS_HORIZONTAL_RESOLUTION]; // returns pel/meter 2779 nVertRes = lArray[CAPS_VERTICAL_RESOLUTION]; // returns pel/meter 2780 nWidth = (int)((nHorzRes/39.3) * nPelWidth); 2781 nHeight = (int)((nVertRes/39.3) * nPelHeight); 2782 } 2783 wxSize ppisize(nWidth, nHeight); 2784 return ppisize; 2785} // end of wxDC::GetPPI 2786 2787void wxDC::SetLogicalScale( double dX, double dY ) 2788{ 2789 m_logicalScaleX = dX; 2790 m_logicalScaleY = dY; 2791}; // end of wxDC::SetLogicalScale 2792