1 ///////////////////////////////////////////////////////////////////////////// 
   4 // Author:      Vaclav Slavik 
   7 // Copyright:   (c) 2001-2002 SciTech Software, Inc. (www.scitechsoft.com) 
   8 // Licence:     wxWindows licence 
   9 ///////////////////////////////////////////////////////////////////////////// 
  11 // =========================================================================== 
  13 // =========================================================================== 
  15 // --------------------------------------------------------------------------- 
  17 // --------------------------------------------------------------------------- 
  19 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) 
  20     #pragma implementation "dc.h" 
  23 // For compilers that support precompilation, includes "wx.h". 
  24 #include "wx/wxprec.h" 
  32     #include "wx/dcmemory.h" 
  35 #include "wx/fontutil.h" 
  36 #include "wx/encinfo.h" 
  37 #include "wx/fontmap.h" 
  38 #include "wx/mgl/private.h" 
  47 //----------------------------------------------------------------------------- 
  49 //----------------------------------------------------------------------------- 
  52 #define M_PI 3.14159265358979323846 
  55 const double mm2inches      
= 0.0393700787402; 
  56 const double inches2mm      
= 25.4; 
  57 const double mm2twips       
= 56.6929133859; 
  58 const double twips2mm       
= 0.0176388888889; 
  59 const double mm2pt          
= 2.83464566929; 
  60 const double pt2mm          
= 0.352777777778; 
  61 const double RAD2DEG        
= 180.0 / M_PI
; 
  64 //----------------------------------------------------------------------------- 
  66 //----------------------------------------------------------------------------- 
  68 const ushort STIPPLE_wxDOT        
= 0x5555/* - - - - - - - -*/; 
  69 const ushort STIPPLE_wxLONG_DASH  
= 0xF0F0/*    ----    ----*/; 
  70 const ushort STIPPLE_wxSHORT_DASH 
= 0xCCCC/*--  --  --  --  */; 
  71 const ushort STIPPLE_wxDOT_DASH   
= 0x3939/*  ---  -  ---  -*/;         
  72 const ushort STIPPLE_wxSOLID      
= 0xFFFF/*----------------*/;         
  74 #define PATTERN_ROW(b7,b6,b5,b4,b3,b2,b1,b0) \ 
  75             ((b7 << 7) | (b6 << 6) | (b5 << 5) | (b4 << 4) | \ 
  76              (b3 << 3) | (b2 << 2) | (b1 << 1) | b0) 
  78 static pattern_t PATTERN_wxFDIAGONAL_HATCH 
= {{ 
  79        PATTERN_ROW(1,0,0,0,0,0,0,0), 
  80        PATTERN_ROW(0,1,0,0,0,0,0,0), 
  81        PATTERN_ROW(0,0,1,0,0,0,0,0), 
  82        PATTERN_ROW(0,0,0,1,0,0,0,0), 
  83        PATTERN_ROW(0,0,0,0,1,0,0,0), 
  84        PATTERN_ROW(0,0,0,0,0,1,0,0), 
  85        PATTERN_ROW(0,0,0,0,0,0,1,0), 
  86        PATTERN_ROW(0,0,0,0,0,0,0,1), 
  89 static pattern_t PATTERN_wxCROSSDIAG_HATCH 
= {{ 
  90        PATTERN_ROW(1,0,0,0,0,0,0,1), 
  91        PATTERN_ROW(0,1,0,0,0,0,1,0), 
  92        PATTERN_ROW(0,0,1,0,0,1,0,0), 
  93        PATTERN_ROW(0,0,0,1,1,0,0,0), 
  94        PATTERN_ROW(0,0,0,1,1,0,0,0), 
  95        PATTERN_ROW(0,0,1,0,0,1,0,0), 
  96        PATTERN_ROW(0,1,0,0,0,0,1,0), 
  97        PATTERN_ROW(1,0,0,0,0,0,0,1), 
 100 static pattern_t PATTERN_wxBDIAGONAL_HATCH 
= {{ 
 101        PATTERN_ROW(0,0,0,0,0,0,0,1), 
 102        PATTERN_ROW(0,0,0,0,0,0,1,0), 
 103        PATTERN_ROW(0,0,0,0,0,1,0,0), 
 104        PATTERN_ROW(0,0,0,0,1,0,0,0), 
 105        PATTERN_ROW(0,0,0,1,0,0,0,0), 
 106        PATTERN_ROW(0,0,1,0,0,0,0,0), 
 107        PATTERN_ROW(0,1,0,0,0,0,0,0), 
 108        PATTERN_ROW(1,0,0,0,0,0,0,0), 
 111 static pattern_t PATTERN_wxCROSS_HATCH 
= {{ 
 112        PATTERN_ROW(0,0,0,1,0,0,0,0), 
 113        PATTERN_ROW(0,0,0,1,0,0,0,0), 
 114        PATTERN_ROW(0,0,0,1,0,0,0,0), 
 115        PATTERN_ROW(1,1,1,1,1,1,1,1), 
 116        PATTERN_ROW(0,0,0,1,0,0,0,0), 
 117        PATTERN_ROW(0,0,0,1,0,0,0,0), 
 118        PATTERN_ROW(0,0,0,1,0,0,0,0), 
 119        PATTERN_ROW(0,0,0,1,0,0,0,0), 
 122 static pattern_t PATTERN_wxHORIZONTAL_HATCH 
= {{ 
 123        PATTERN_ROW(0,0,0,0,0,0,0,0), 
 124        PATTERN_ROW(0,0,0,0,0,0,0,0), 
 125        PATTERN_ROW(0,0,0,0,0,0,0,0), 
 126        PATTERN_ROW(1,1,1,1,1,1,1,1), 
 127        PATTERN_ROW(0,0,0,0,0,0,0,0), 
 128        PATTERN_ROW(0,0,0,0,0,0,0,0), 
 129        PATTERN_ROW(0,0,0,0,0,0,0,0), 
 130        PATTERN_ROW(0,0,0,0,0,0,0,0), 
 133 static pattern_t PATTERN_wxVERTICAL_HATCH 
= {{ 
 134        PATTERN_ROW(0,0,0,1,0,0,0,0), 
 135        PATTERN_ROW(0,0,0,1,0,0,0,0), 
 136        PATTERN_ROW(0,0,0,1,0,0,0,0), 
 137        PATTERN_ROW(0,0,0,1,0,0,0,0), 
 138        PATTERN_ROW(0,0,0,1,0,0,0,0), 
 139        PATTERN_ROW(0,0,0,1,0,0,0,0), 
 140        PATTERN_ROW(0,0,0,1,0,0,0,0), 
 141        PATTERN_ROW(0,0,0,1,0,0,0,0), 
 146 //----------------------------------------------------------------------------- 
 148 //----------------------------------------------------------------------------- 
 150 IMPLEMENT_ABSTRACT_CLASS(wxDC
, wxDCBase
) 
 152 // Default constructor 
 158     m_ok 
= FALSE
; // must call SetMGLDevCtx() before using it 
 160     m_mm_to_pix_x 
= (double)wxGetDisplaySize().GetWidth() / 
 161                     (double)wxGetDisplaySizeMM().GetWidth(); 
 162     m_mm_to_pix_y 
= (double)wxGetDisplaySize().GetHeight() / 
 163                     (double)wxGetDisplaySizeMM().GetHeight(); 
 165     m_pen 
= *wxBLACK_PEN
; 
 166     m_font 
= *wxNORMAL_FONT
; 
 167     m_brush 
= *wxWHITE_BRUSH
; 
 168     m_penOfsX 
= m_penOfsY 
= 0; 
 170     m_penSelected 
= m_brushSelected 
= FALSE
; 
 171     m_downloadedPatterns
[0] = m_downloadedPatterns
[1] = FALSE
; 
 183 void wxDC::SetMGLDC(MGLDevCtx 
*mgldc
, bool OwnsMGLDC
) 
 185     if ( m_OwnsMGLDC 
&& m_MGLDC 
) 
 188     m_OwnsMGLDC 
= OwnsMGLDC
; 
 191     if ( !m_globalClippingRegion
.IsNull() ) 
 192         SetClippingRegion(m_globalClippingRegion
); 
 197 void wxDC::InitializeMGLDC() 
 199     if ( GetDepth() > 8 ) 
 201         wxCurrentDCSwitcher 
switcher(m_MGLDC
); // will go away with MGL6 
 202         m_MGLDC
->setFontBlendMode(MGL_AA_RGBBLEND
); 
 207 // --------------------------------------------------------------------------- 
 209 // --------------------------------------------------------------------------- 
 212 #define DO_SET_CLIPPING_BOX(rg)                      \ 
 214     wxRect rect = rg.GetBox();                       \ 
 215     m_clipX1 = (wxCoord) XDEV2LOG(rect.GetLeft());   \ 
 216     m_clipY1 = (wxCoord) YDEV2LOG(rect.GetTop());    \ 
 217     m_clipX2 = (wxCoord) XDEV2LOG(rect.GetRight());  \ 
 218     m_clipY2 = (wxCoord) YDEV2LOG(rect.GetBottom()); \ 
 221 void wxDC::DoSetClippingRegion(wxCoord cx
, wxCoord cy
, wxCoord cw
, wxCoord ch
) 
 223     wxCHECK_RET( Ok(), wxT("invalid dc") ); 
 225     wxRect 
rect(XLOG2DEV(cx
), YLOG2DEV(cy
), XLOG2DEVREL(cw
), YLOG2DEVREL(ch
)); 
 227     if ( !m_currentClippingRegion
.IsNull() ) 
 228         m_currentClippingRegion
.Intersect(rect
); 
 230         m_currentClippingRegion
.Union(rect
); 
 232     m_MGLDC
->setClipRegion(m_currentClippingRegion
.GetMGLRegion()); 
 235     DO_SET_CLIPPING_BOX(m_currentClippingRegion
) 
 238 void wxDC::DoSetClippingRegionAsRegion(const wxRegion
& region
) 
 240     wxCHECK_RET( Ok(), wxT("invalid dc") ); 
 242     if ( region
.IsEmpty() ) 
 244         DestroyClippingRegion(); 
 250     // check if the DC is scaled or moved, and if yes, then 
 251     // convert rg to device coordinates: 
 252     if ( m_deviceOriginX 
!= 0 || m_deviceOriginY 
!= 0 || 
 253          m_logicalOriginX 
!= 0 || m_logicalOriginY 
!= 0 || 
 254          XLOG2DEVREL(500) != 500 || YLOG2DEVREL(500) != 500 ) 
 256         region_t 
*mrg 
= rg
.GetMGLRegion().rgnPointer(); 
 259             for (s 
= mrg
->spans
; s
; s 
= s
->next
)  
 261                     s
->y 
= YLOG2DEV(s
->y
); 
 262                     for (p 
= s
->seg
; p
; p 
= p
->next
) 
 263                             p
->x 
= XLOG2DEV(p
->x
); 
 267     if ( !m_currentClippingRegion
.IsNull() ) 
 268         m_currentClippingRegion
.Intersect(rg
); 
 270         m_currentClippingRegion
.Union(rg
); 
 272     m_MGLDC
->setClipRegion(m_currentClippingRegion
.GetMGLRegion()); 
 275     DO_SET_CLIPPING_BOX(m_currentClippingRegion
) 
 278 void wxDC::DestroyClippingRegion() 
 280     wxCHECK_RET( Ok(), wxT("invalid dc") ); 
 282     if ( !m_globalClippingRegion
.IsNull() ) 
 284         m_MGLDC
->setClipRegion(m_globalClippingRegion
.GetMGLRegion()); 
 285         m_currentClippingRegion 
= m_globalClippingRegion
; 
 290         m_MGLDC
->setClipRect(MGLRect(0, 0, m_MGLDC
->sizex()+1, m_MGLDC
->sizey()+1)); 
 292         m_currentClippingRegion
.Clear(); 
 296 // --------------------------------------------------------------------------- 
 297 // query capabilities 
 298 // --------------------------------------------------------------------------- 
 300 bool wxDC::CanDrawBitmap() const 
 305 bool wxDC::CanGetTextExtent() const 
 310 int wxDC::GetDepth() const 
 312     return m_MGLDC
->getBitsPerPixel(); 
 315 // --------------------------------------------------------------------------- 
 317 // --------------------------------------------------------------------------- 
 321     wxCHECK_RET( Ok(), wxT("invalid dc") ); 
 323     m_MGLDC
->makeCurrent(); // will go away with MGL6.0 
 324     if ( m_backgroundBrush
.GetStyle() != wxTRANSPARENT 
) 
 327         wxBrush oldb 
= m_brush
; 
 328         SetBrush(m_backgroundBrush
); 
 331         m_MGLDC
->fillRect(0, 0, w
, h
); 
 336 extern bool wxDoFloodFill(wxDC 
*dc
, wxCoord x
, wxCoord y
,  
 337                           const wxColour 
& col
, int style
); 
 339 bool wxDC::DoFloodFill(wxCoord x
, wxCoord y
, 
 340                        const wxColour
& col
, int style
) 
 342     return wxDoFloodFill(this, x
, y
, col
, style
); 
 345 bool wxDC::DoGetPixel(wxCoord x
, wxCoord y
, wxColour 
*col
) const 
 347     wxCHECK_MSG( col
, FALSE
, _T("NULL colour parameter in wxDC::GetPixel")); 
 350     m_MGLDC
->unpackColorFast(m_MGLDC
->getPixel(XLOG2DEV(x
), YLOG2DEV(y
)),  
 356 void wxDC::DoCrossHair(wxCoord x
, wxCoord y
) 
 358     wxCHECK_RET( Ok(), wxT("invalid dc") ); 
 360     if ( m_pen
.GetStyle() != wxTRANSPARENT 
) 
 365         m_MGLDC
->makeCurrent(); // will go away with MGL6.0 
 366         if ( !m_penSelected 
)  
 368         wxCoord xx 
= XLOG2DEV(x
); 
 369         wxCoord yy 
= YLOG2DEV(y
); 
 370         m_MGLDC
->line(m_penOfsX
, yy 
+ m_penOfsY
, w
-1 + m_penOfsX
, yy 
+ m_penOfsY
); 
 371         m_MGLDC
->line(xx 
+ m_penOfsX
, m_penOfsY
, x 
+ m_penOfsX
, h
-1 + m_penOfsY
); 
 372         CalcBoundingBox(0, 0); 
 373         CalcBoundingBox(w
, h
); 
 377 void wxDC::DoDrawLine(wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
) 
 379     wxCHECK_RET( Ok(), wxT("invalid dc") ); 
 381     if ( m_pen
.GetStyle() != wxTRANSPARENT 
) 
 383         m_MGLDC
->makeCurrent(); // will go away with MGL6.0 
 384         if ( !m_penSelected 
)  
 386         m_MGLDC
->lineExt(XLOG2DEV(x1
) + m_penOfsX
, YLOG2DEV(y1
) + m_penOfsY
,  
 387                       XLOG2DEV(x2
) + m_penOfsX
, YLOG2DEV(y2
) + m_penOfsY
,FALSE
); 
 388         CalcBoundingBox(x1
, y1
); 
 389         CalcBoundingBox(x2
, y2
); 
 393 // Draws an arc of a circle, centred on (xc, yc), with starting point (x1, y1) 
 394 // and ending at (x2, y2) 
 395 void wxDC::DoDrawArc(wxCoord x1
, wxCoord y1
, 
 396                      wxCoord x2
, wxCoord y2
, 
 397                      wxCoord xc
, wxCoord yc
) 
 399     wxCHECK_RET( Ok(), wxT("invalid dc") ); 
 401     wxCoord xx1 
= XLOG2DEV(x1
); 
 402     wxCoord yy1 
= YLOG2DEV(y1
); 
 403     wxCoord xx2 
= XLOG2DEV(x2
); 
 404     wxCoord yy2 
= YLOG2DEV(y2
); 
 405     wxCoord xxc 
= XLOG2DEV(xc
); 
 406     wxCoord yyc 
= YLOG2DEV(yc
); 
 407     double dx 
= xx1 
- xxc
; 
 408     double dy 
= yy1 
- yyc
; 
 409     double radius 
= sqrt((double)(dx
*dx
+dy
*dy
)); 
 410     wxCoord r 
= (wxCoord
)radius
; 
 411     double radius1
, radius2
; 
 414     if (xx1 
== xx2 
&& yy1 
== yy2
) 
 419     else if (radius 
== 0.0) 
 421         radius1 
= radius2 
= 0.0; 
 425         radius1 
= (xx1 
- xxc 
== 0) ? 
 426             (yy1 
- yyc 
< 0) ? 90.0 : -90.0 : 
 427             -atan2(double(yy1
-yyc
), double(xx1
-xxc
)) * RAD2DEG
; 
 428         radius2 
= (xx2 
- xxc 
== 0) ? 
 429             (yy2 
- yyc 
< 0) ? 90.0 : -90.0 : 
 430             -atan2(double(yy2
-yyc
), double(xx2
-xxc
)) * RAD2DEG
; 
 432     wxCoord alpha1 
= wxCoord(radius1
); 
 433     wxCoord alpha2 
= alpha1 
+ wxCoord(radius2 
- radius1
); 
 434     while (alpha2 
<= 0) alpha2 
+= 360; 
 435     while (alpha1 
> 360) alpha1 
-= 360; 
 437     m_MGLDC
->makeCurrent(); // will go away with MGL6.0 
 438     if ( m_brush
.GetStyle() != wxTRANSPARENT 
) 
 440         if ( !m_brushSelected 
)  
 442         m_MGLDC
->fillEllipseArc(xxc
, yyc
, r
, r
, alpha1
, alpha2
); 
 445     if ( m_pen
.GetStyle() != wxTRANSPARENT 
) 
 447         if ( !m_penSelected 
)  
 449         m_MGLDC
->ellipseArc(xxc 
+ m_penOfsX
, yyc 
+ m_penOfsY
, r
, r
, alpha1
, alpha2
); 
 452     CalcBoundingBox(xc 
- r
, yc 
- r
); 
 453     CalcBoundingBox(xc 
+ r
, yc 
+ r
); 
 456 void wxDC::DoDrawPoint(wxCoord x
, wxCoord y
) 
 458     wxCHECK_RET( Ok(), wxT("invalid dc") ); 
 460     if ( m_pen
.GetStyle() != wxTRANSPARENT 
) 
 462         m_MGLDC
->makeCurrent(); // will go away with MGL6.0 
 463         if ( !m_penSelected 
)  
 465         m_MGLDC
->pixel(XLOG2DEV(x
), YLOG2DEV(y
)); 
 466         CalcBoundingBox(x
, y
); 
 470 void wxDC::DoDrawPolygon(int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
,int fillStyle
) 
 472     wxCHECK_RET( Ok(), wxT("invalid dc") ); 
 474     wxCoord xxoffset 
= XLOG2DEVREL(xoffset
),  
 475             yyoffset 
= YLOG2DEVREL(yoffset
); 
 476     MGLPoint 
*cpoints 
= new MGLPoint
[n
+1];    
 477     for (int i 
= 0; i 
< n
; i
++) 
 479         CalcBoundingBox(points
[i
].x 
+ xoffset
, points
[i
].y 
+ yoffset
); 
 480         cpoints
[i
].x 
= (int)(XLOG2DEV(points
[i
].x
)); 
 481         cpoints
[i
].y 
= (int)(YLOG2DEV(points
[i
].y
)); 
 483     cpoints
[n
] = cpoints
[0]; 
 485     m_MGLDC
->makeCurrent(); // will go away with MGL6.0 
 486     if ( m_brush
.GetStyle() != wxTRANSPARENT 
) 
 488         if ( !m_brushSelected 
) 
 490         m_MGLDC
->fillPolygon(n
, cpoints
, xxoffset
, yyoffset
); 
 493     if ( m_pen
.GetStyle() != wxTRANSPARENT 
) 
 495         if ( !m_penSelected 
)  
 497         if (m_penOfsX 
!= 0 || m_penOfsY 
!= 0) 
 499             for (int i 
= 0; i 
<= n
; i
++) 
 501                 cpoints
[i
].x 
+= m_penOfsX
; 
 502                 cpoints
[i
].y 
+= m_penOfsY
; 
 505         m_MGLDC
->polyLine(n
+1, cpoints
); 
 511 void wxDC::DoDrawLines(int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
) 
 513     wxCHECK_RET( Ok(), wxT("invalid dc") ); 
 515     if ( m_pen
.GetStyle() != wxTRANSPARENT 
) 
 517         MGLPoint 
*cpoints 
= new MGLPoint
[n
]; 
 518         m_MGLDC
->makeCurrent(); // will go away with MGL6.0 
 519         if ( !m_penSelected 
)  
 521         for (int i 
= 0; i 
< n
; i
++) 
 523             CalcBoundingBox(points
[i
].x 
+ xoffset
, points
[i
].y 
+ yoffset
); 
 524             cpoints
[i
].x 
= (int)(XLOG2DEV(points
[i
].x 
+ xoffset
) /*+ m_penOfsX*/); 
 525             cpoints
[i
].y 
= (int)(YLOG2DEV(points
[i
].y 
+ yoffset
) /*+ m_penOfsY*/); 
 527         m_MGLDC
->polyLine(n
, cpoints
); 
 532 void wxDC::DoDrawRectangle(wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
) 
 534     wxCHECK_RET( Ok(), wxT("invalid dc") ); 
 536     wxCoord xx 
= XLOG2DEV(x
); 
 537     wxCoord yy 
= YLOG2DEV(y
); 
 538     wxCoord ww 
= m_signX 
* XLOG2DEVREL(width
); 
 539     wxCoord hh 
= m_signY 
* YLOG2DEVREL(height
); 
 541     if ( ww 
== 0 || hh 
== 0 ) return; 
 554     m_MGLDC
->makeCurrent(); // will go away with MGL6.0 
 555     if ( m_brush
.GetStyle() != wxTRANSPARENT 
) 
 557         if ( !m_brushSelected 
)  
 559         m_MGLDC
->fillRect(xx
, yy
, xx 
+ ww
, yy 
+ hh
); 
 562     if ( m_pen
.GetStyle() != wxTRANSPARENT 
) 
 564         if ( !m_penSelected 
)  
 567         m_MGLDC
->rect(xx 
+ m_penOfsX
, yy 
+ m_penOfsY
,  
 568                       xx 
+ ww 
+ m_penOfsX
, yy 
+ hh 
+ m_penOfsY
); 
 571     CalcBoundingBox(x
, y
); 
 572     CalcBoundingBox(x 
+ width
, y 
+ height
); 
 575 void wxDC::DoDrawRoundedRectangle(wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double radius
) 
 577     wxCHECK_RET( Ok(), wxT("invalid dc") ); 
 580         radius 
= -radius 
* ((width 
< height
) ? width 
: height
); 
 582     wxCoord xx 
= XLOG2DEV(x
); 
 583     wxCoord yy 
= YLOG2DEV(y
); 
 584     wxCoord ww 
= m_signX 
* XLOG2DEVREL(width
); 
 585     wxCoord hh 
= m_signY 
* YLOG2DEVREL(height
); 
 586     wxCoord rr 
= XLOG2DEVREL((wxCoord
)radius
); 
 588     // CMB: handle -ve width and/or height 
 600     // CMB: if radius is zero use DrawRectangle() instead to avoid 
 601     // X drawing errors with small radii 
 604         DrawRectangle(x
, y
, width
, height
); 
 608     // CMB: draw nothing if transformed w or h is 0 
 609     if ( ww 
== 0 || hh 
== 0 ) return; 
 611     // CMB: ensure dd is not larger than rectangle otherwise we 
 612     // get an hour glass shape 
 614     if ( dd 
> ww 
) dd 
= ww
; 
 615     if ( dd 
> hh 
) dd 
= hh
; 
 618     m_MGLDC
->makeCurrent(); // will go away with MGL6.0 
 619     if ( m_brush
.GetStyle() != wxTRANSPARENT 
) 
 621         if (!m_brushSelected
)  
 623         m_MGLDC
->fillRect(xx
+rr
, yy
, xx
+ww
-rr
, yy
+hh
); 
 624         m_MGLDC
->fillRect(xx
, yy
+rr
, xx
+ww
, yy
+hh
-rr
); 
 625         m_MGLDC
->fillEllipseArc(xx
+rr
, yy
+rr
, rr
, rr
, 90, 180); 
 626         m_MGLDC
->fillEllipseArc(xx
+ww
-rr
, yy
+rr
, rr
, rr
, 0, 90); 
 627         m_MGLDC
->fillEllipseArc(xx
+rr
, yy
+hh
-rr
, rr
, rr
, 180, 270); 
 628         m_MGLDC
->fillEllipseArc(xx
+ww
-rr
, yy
+hh
-rr
, rr
, rr
, 270, 0); 
 631     if ( m_pen
.GetStyle() != wxTRANSPARENT 
) 
 633         if ( !m_penSelected 
)  
 637         m_MGLDC
->line(xx
+rr
+1, yy
, xx
+ww
-rr
, yy
);        
 638         m_MGLDC
->ellipseArc(xx
+ww
-rr
, yy
+rr
, rr
, rr
, 0, 90); 
 639         m_MGLDC
->line(xx
+ww
, yy
+rr
+1, xx
+ww
, yy
+hh
-rr
); 
 640         m_MGLDC
->ellipseArc(xx
+ww
-rr
, yy
+hh
-rr
, rr
, rr
, 270, 0); 
 641         m_MGLDC
->line(xx
+ww
-rr
, yy
+hh
, xx
+rr
+1, yy
+hh
); 
 642         m_MGLDC
->ellipseArc(xx
+rr
, yy
+hh
-rr
, rr
, rr
, 180, 270);        
 643         m_MGLDC
->line(xx
, yy
+hh
-rr
, xx
, yy
+rr
+1); 
 644         m_MGLDC
->ellipseArc(xx
+rr
, yy
+rr
, rr
, rr
, 90, 180); 
 647     CalcBoundingBox(x
, y
); 
 648     CalcBoundingBox(x 
+ width
, y 
+ height
); 
 651 void wxDC::DoDrawEllipse(wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
) 
 653     wxCHECK_RET( Ok(), wxT("invalid dc") ); 
 655     wxCoord x2 
= (x
+width
); 
 656     wxCoord y2 
= (y
+height
); 
 658     m_MGLDC
->makeCurrent(); // will go away with MGL6.0 
 659     if ( m_brush
.GetStyle() != wxTRANSPARENT 
) 
 661         if ( !m_brushSelected 
) 
 663         MGLRect 
rect(XLOG2DEV(x
), YLOG2DEV(y
), XLOG2DEV(x2
), YLOG2DEV(y2
)); 
 664         m_MGLDC
->fillEllipse(rect
); 
 667     if ( m_pen
.GetStyle() != wxTRANSPARENT 
) 
 669         if ( !m_penSelected 
)  
 671         MGLRect 
rect(XLOG2DEV(x
) + m_penOfsX
, YLOG2DEV(y
) + m_penOfsY
,  
 672                      XLOG2DEV(x2
) + m_penOfsX
, YLOG2DEV(y2
) + m_penOfsY
); 
 673         m_MGLDC
->ellipse(rect
); 
 676     CalcBoundingBox(x
, y
); 
 677     CalcBoundingBox(x2
, y2
); 
 680 void wxDC::DoDrawEllipticArc(wxCoord x
,wxCoord y
,wxCoord w
,wxCoord h
,double sa
,double ea
) 
 682     wxCHECK_RET( Ok(), wxT("invalid dc") ); 
 687     m_MGLDC
->makeCurrent(); // will go away with MGL6.0 
 688     if ( m_brush
.GetStyle() != wxTRANSPARENT 
) 
 690         if (!m_brushSelected
) SelectBrush(); 
 691         MGLRect 
rect(XLOG2DEV(x
), YLOG2DEV(y
), XLOG2DEV(x2
), YLOG2DEV(y2
)); 
 692         m_MGLDC
->fillEllipseArc(rect
, (int)sa
, (int)ea
); 
 695     if ( m_pen
.GetStyle() != wxTRANSPARENT 
) 
 697         if ( !m_penSelected 
)  
 699         MGLRect 
rect(XLOG2DEV(x
) + m_penOfsX
, YLOG2DEV(y
) + m_penOfsY
,  
 700                      XLOG2DEV(x2
) + m_penOfsX
, YLOG2DEV(y2
) + m_penOfsY
); 
 701         m_MGLDC
->ellipseArc(rect
, (int)sa
, (int)ea
); 
 704     CalcBoundingBox(x
, y
); 
 705     CalcBoundingBox(x2
, y2
); 
 708 void wxDC::DoDrawText(const wxString
& text
, wxCoord x
, wxCoord y
) 
 710     m_MGLDC
->makeCurrent(); // will go away with MGL6.0 
 711     DrawAnyText(text
, x
, y
); 
 713     // update the bounding box 
 715     CalcBoundingBox(x
, y
); 
 716     GetTextExtent(text
, &w
, &h
); 
 717     CalcBoundingBox(x 
+ w
, y 
+ h
); 
 720 bool wxDC::SelectMGLFont() 
 722     if ( m_mglFont 
== NULL 
) 
 724         float scale 
= m_scaleY
; 
 725         bool antialiased 
= (GetDepth() > 8); 
 727         m_mglFont 
= m_font
.GetMGLfont_t(scale
, antialiased
); 
 728         wxCHECK_MSG( m_mglFont
, FALSE
, wxT("invalid font") ); 
 730         m_MGLDC
->useFont(m_mglFont
); 
 731         wxLogTrace("mgl_font", "useFont(%p)", m_mglFont
); 
 734         wxNativeEncodingInfo nativeEnc
; 
 735         wxFontEncoding encoding 
= m_font
.GetEncoding(); 
 736         if ( !wxGetNativeFontEncoding(encoding
, &nativeEnc
) || 
 737              !wxTestFontEncoding(nativeEnc
) ) 
 740             if ( !wxFontMapper::Get()->GetAltForEncoding(encoding
, &nativeEnc
) ) 
 743                 nativeEnc
.mglEncoding 
= MGL_ENCODING_ASCII
; 
 746         m_MGLDC
->setTextEncoding(nativeEnc
.mglEncoding
); 
 752 void wxDC::DrawAnyText(const wxString
& text
, wxCoord x
, wxCoord y
) 
 754     wxCHECK_RET( Ok(), wxT("invalid dc") ); 
 759     wxCoord xx 
= XLOG2DEV(x
); 
 760     wxCoord yy 
= YLOG2DEV(y
); 
 762     m_MGLDC
->setLineStyle(MGL_LINE_STIPPLE
); 
 763     m_MGLDC
->setLineStipple(0xFFFF); 
 764     m_MGLDC
->setPenSize(1, 1); 
 765     m_MGLDC
->setPenStyle(MGL_BITMAP_SOLID
); 
 768     const wchar_t *c_text 
= text
.c_str(); 
 770     const char *c_text 
= text
.c_str(); 
 774     // FIXME_MGL - this is a temporary hack in absence of proper  
 775     //             implementation of solid text background in MGL. Once  
 776     //             the bug in MGL is fixed, this code should be nuked 
 777     //             immediately. Note that the code is not 100% correct; 
 778     //             it only works with wxCOPY logical function 
 779     if ( m_backgroundMode 
== wxSOLID 
) 
 781         int w 
= m_MGLDC
->textWidth(c_text
); 
 782         int h 
= m_MGLDC
->textHeight(); 
 783         m_MGLDC
->setColor(m_MGLDC
->packColorFast(m_textBackgroundColour
.Red(), 
 784                 m_textBackgroundColour
.Green(), m_textBackgroundColour
.Blue())); 
 785         m_MGLDC
->fillRect(xx
, yy
, xx
+w
, yy
+h
); 
 789     m_MGLDC
->setColor(m_MGLDC
->packColorFast(m_textForegroundColour
.Red(), 
 790             m_textForegroundColour
.Green(), m_textForegroundColour
.Blue())); 
 791     m_MGLDC
->setBackColor(m_MGLDC
->packColorFast(m_textBackgroundColour
.Red(), 
 792             m_textBackgroundColour
.Green(), m_textBackgroundColour
.Blue())); 
 794     m_MGLDC
->drawStr(xx
, yy
, c_text
); 
 797     if ( m_font
.GetUnderlined() ) 
 799         int x1 
= xx
, y1 
= yy
; 
 801         int w 
= m_MGLDC
->textWidth(c_text
); 
 802         m_MGLDC
->underScoreLocation(x1
, y1
, c_text
); 
 803         switch (m_MGLDC
->getTextDirection()) 
 805             case MGL_RIGHT_DIR
: x2 
= x1 
+ w
, y2 
= y1
; break; 
 806             case MGL_LEFT_DIR
:  x2 
= x1 
- w
, y2 
= y1
; break; 
 807             case MGL_UP_DIR
:    x2 
= x1
, y2 
= y1 
- w
; break; 
 808             case MGL_DOWN_DIR
:  x2 
= x1
, y2 
= y1 
+ w
; break; 
 810         m_MGLDC
->line(x1
, y1
, x2
, y2
); 
 813     m_penSelected 
= m_brushSelected 
= FALSE
; 
 816 void wxDC::DoDrawRotatedText(const wxString
& text
, 
 817                              wxCoord x
, wxCoord y
, 
 820     m_MGLDC
->makeCurrent(); // will go away with MGL6.0 
 824         DoDrawText(text
, x
, y
); 
 827     else if ( angle 
== 90.0 ) 
 828         m_MGLDC
->setTextDirection(MGL_UP_DIR
); 
 829     else if ( angle 
== 180.0 ) 
 830         m_MGLDC
->setTextDirection(MGL_LEFT_DIR
); 
 831     else if ( angle 
== 270.0 ) 
 832         m_MGLDC
->setTextDirection(MGL_DOWN_DIR
); 
 835         // FIXME_MGL -- implement once MGL supports it 
 836         wxFAIL_MSG(wxT("wxMGL only supports rotated text with angle 0,90,180 or 270")); 
 840     DrawAnyText(text
, x
, y
); 
 843     m_MGLDC
->setTextDirection(MGL_RIGHT_DIR
); 
 846 // --------------------------------------------------------------------------- 
 848 // --------------------------------------------------------------------------- 
 850 void wxDC::SelectMGLStipplePen(int style
) 
 856         case wxDOT
:        stipple 
= STIPPLE_wxDOT
;        break; 
 857         case wxLONG_DASH
:  stipple 
= STIPPLE_wxLONG_DASH
;  break; 
 858         case wxSHORT_DASH
: stipple 
= STIPPLE_wxSHORT_DASH
; break; 
 859         case wxDOT_DASH
:   stipple 
= STIPPLE_wxDOT_DASH
;   break; 
 860         default:           stipple 
= STIPPLE_wxSOLID
;      break; 
 863     m_MGLDC
->setLineStyle(MGL_LINE_STIPPLE
); 
 864     m_MGLDC
->setLineStipple(stipple
); 
 865     m_MGLDC
->setPenSize(1, 1); 
 866     m_MGLDC
->setPenStyle(MGL_BITMAP_SOLID
); 
 867     m_penOfsY 
= m_penOfsX 
= 0; 
 870 // Accepted valus of SelectMGLFatPen's 2nd argument 
 872     wxMGL_SELECT_FROM_PEN
, 
 873     wxMGL_SELECT_FROM_BRUSH
 
 876 void wxDC::SelectMGLFatPen(int style
, int flag
) 
 878     MGL_penStyleType penstyle
; 
 879     const pattern_t 
*pattern 
= NULL
; 
 880     pixpattern24_t 
*pixPattern 
= NULL
; 
 884     // Since MGL pens may be created from wxBrush or wxPen and we often 
 885     // switch between pens and brushes, we take advantage of MGL's ability 
 886     // to have multiple (pix)pattern_t's loaded. We always download pen 
 887     // to 0th slot and brush to 1st slot. 
 888     if ( flag 
== wxMGL_SELECT_FROM_PEN 
)  
 893     // compute pen's width:     
 894     if ( m_pen
.GetWidth() <= 1 ) 
 897         m_penOfsX 
= m_penOfsY 
= 0; 
 901         wx 
= (int)(0.5 + fabs((double) XLOG2DEVREL(m_pen
.GetWidth()))); 
 902         wy 
= (int)(0.5 + fabs((double) YLOG2DEVREL(m_pen
.GetWidth()))); 
 908     penstyle 
= MGL_BITMAP_TRANSPARENT
; 
 911         case wxBDIAGONAL_HATCH
:  pattern 
= &PATTERN_wxBDIAGONAL_HATCH
;   
 912                                  penstyle 
= MGL_BITMAP_TRANSPARENT
;  
 914         case wxCROSSDIAG_HATCH
:  pattern 
= &PATTERN_wxCROSSDIAG_HATCH
;   
 915                                  penstyle 
= MGL_BITMAP_TRANSPARENT
;  
 917         case wxFDIAGONAL_HATCH
:  pattern 
= &PATTERN_wxFDIAGONAL_HATCH
; 
 918                                  penstyle 
= MGL_BITMAP_TRANSPARENT
;  
 920         case wxCROSS_HATCH
:      pattern 
= &PATTERN_wxCROSS_HATCH
; 
 921                                  penstyle 
= MGL_BITMAP_TRANSPARENT
;  
 923         case wxHORIZONTAL_HATCH
: pattern 
= &PATTERN_wxHORIZONTAL_HATCH
; 
 924                                  penstyle 
= MGL_BITMAP_TRANSPARENT
;  
 926         case wxVERTICAL_HATCH
:   pattern 
= &PATTERN_wxVERTICAL_HATCH
; 
 927                                  penstyle 
= MGL_BITMAP_TRANSPARENT
;  
 931             if ( flag 
== wxMGL_SELECT_FROM_PEN 
)  
 932                 pixPattern 
= (pixpattern24_t
*) m_pen
.GetPixPattern(); 
 934                 pixPattern 
= (pixpattern24_t
*) m_brush
.GetPixPattern(); 
 935             penstyle 
= MGL_PIXMAP
; 
 938         case wxSTIPPLE_MASK_OPAQUE
: 
 939             pattern 
= (pattern_t
*) m_brush
.GetMaskPattern(); 
 940             penstyle 
= MGL_BITMAP_OPAQUE
; 
 945             penstyle 
= MGL_BITMAP_SOLID
; break; 
 948     // ...and finally, pass the pen to MGL: 
 952         if ( !m_downloadedPatterns
[slot
] ) 
 954             m_MGLDC
->setPenBitmapPattern(slot
, pattern
); 
 955             m_downloadedPatterns
[slot
] = TRUE
; 
 957         m_MGLDC
->usePenBitmapPattern(slot
); 
 962         if ( !m_downloadedPatterns
[slot
] ) 
 970                     for (y 
= 0; y 
< 8; y
++) 
 971                         for (x 
= 0; x 
< 8; x
++) 
 972                             pix
.b8
.p
[x
][y
] = m_MGLDC
->packColorFast( 
 973                                                         pixPattern
->p
[x
][y
][0], 
 974                                                         pixPattern
->p
[x
][y
][1], 
 975                                                         pixPattern
->p
[x
][y
][2]); 
 979                     for (y 
= 0; y 
< 8; y
++) 
 980                         for (x 
= 0; x 
< 8; x
++) 
 981                             pix
.b16
.p
[x
][y
] = m_MGLDC
->packColorFast( 
 982                                                         pixPattern
->p
[x
][y
][0], 
 983                                                         pixPattern
->p
[x
][y
][1], 
 984                                                         pixPattern
->p
[x
][y
][2]); 
 987                     for (y 
= 0; y 
< 8; y
++) 
 988                         for (x 
= 0; x 
< 8; x
++) 
 989                             for (c 
= 0; c 
< 3; c
++) 
 990                                 pix
.b24
.p
[x
][y
][c
] = pixPattern
->p
[x
][y
][c
]; 
 993                     for (y 
= 0; y 
< 8; y
++) 
 994                         for (x 
= 0; x 
< 8; x
++) 
 995                             pix
.b32
.p
[x
][y
] = m_MGLDC
->packColorFast( 
 996                                                         pixPattern
->p
[x
][y
][0], 
 997                                                         pixPattern
->p
[x
][y
][1], 
 998                                                         pixPattern
->p
[x
][y
][2]); 
1001                     wxFAIL_MSG(_T("invalid DC depth")); 
1004             m_MGLDC
->setPenPixmapPattern(slot
, &pix
); 
1005             m_downloadedPatterns
[slot
] = TRUE
; 
1007         m_MGLDC
->usePenPixmapPattern(slot
); 
1010     m_MGLDC
->setLineStyle(MGL_LINE_PENSTYLE
); 
1011     m_MGLDC
->setPenStyle(penstyle
); 
1012     m_MGLDC
->setPenSize(wy
, wx
); 
1015 void wxDC::SelectPen() 
1017     wxCHECK_RET( Ok(), wxT("invalid dc") ); 
1019     wxColour
& clr 
= m_pen
.GetColour(); 
1020     m_MGLDC
->makeCurrent(); // will go away with MGL6.0 
1021     m_MGLDC
->setColorRGB(clr
.Red(), clr
.Green(), clr
.Blue()); 
1023     switch (m_pen
.GetStyle()) 
1032             SelectMGLStipplePen(m_pen
.GetStyle()); 
1035         case wxBDIAGONAL_HATCH
: 
1036         case wxCROSSDIAG_HATCH
: 
1037         case wxFDIAGONAL_HATCH
: 
1039         case wxHORIZONTAL_HATCH
: 
1040         case wxVERTICAL_HATCH
: 
1041             SelectMGLFatPen(m_pen
.GetStyle(), wxMGL_SELECT_FROM_PEN
); 
1045             SelectMGLFatPen(m_pen
.GetStyle(), wxMGL_SELECT_FROM_PEN
); 
1051             if ( m_pen
.GetWidth() <= 1 ) 
1052                 SelectMGLStipplePen(wxSOLID
); 
1054                 SelectMGLFatPen(wxSOLID
, wxMGL_SELECT_FROM_PEN
); 
1057     m_penSelected 
= TRUE
; 
1058     m_brushSelected 
= FALSE
; 
1061 void wxDC::SelectBrush() 
1063     wxCHECK_RET( Ok(), wxT("invalid dc") ); 
1066     m_MGLDC
->makeCurrent(); // will go away with MGL6.0 
1068     if ( m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE 
) 
1070         fg 
= m_textForegroundColour
; 
1071         bg 
= m_textBackgroundColour
; 
1075         fg 
= m_brush
.GetColour(); 
1076         bg 
= m_backgroundBrush
.GetColour(); 
1079     m_MGLDC
->setColorRGB(fg
.Red(), fg
.Green(), fg
.Blue()); 
1080     m_MGLDC
->setBackColor(m_MGLDC
->packColorFast(bg
.Red(), bg
.Green(), bg
.Blue())); 
1081     m_penSelected 
= FALSE
; 
1082     m_brushSelected 
= TRUE
; 
1084     SelectMGLFatPen(m_brush
.GetStyle(), wxMGL_SELECT_FROM_BRUSH
); 
1087 void wxDC::SetPen(const wxPen
& pen
) 
1089     if ( !pen
.Ok() ) return; 
1090     if ( m_pen 
== pen 
) return; 
1092     m_penSelected 
= FALSE
; 
1093     m_downloadedPatterns
[0] = FALSE
; 
1096 void wxDC::SetBrush(const wxBrush
& brush
) 
1098     if ( !brush
.Ok() ) return; 
1099     if ( m_brush 
== brush 
) return; 
1101     m_brushSelected 
= FALSE
; 
1102     m_downloadedPatterns
[1] = FALSE
; 
1105 void wxDC::SetPalette(const wxPalette
& palette
) 
1107     wxCHECK_RET( Ok(), wxT("invalid dc") ); 
1109     if ( palette 
== wxNullPalette 
) 
1111         if ( m_oldPalette
.Ok() ) 
1112             SetPalette(m_oldPalette
); 
1116     if ( !palette
.Ok() ) return; 
1117     if ( m_palette 
== palette 
) return; 
1118     m_oldPalette 
= m_palette
; 
1119     m_palette 
= palette
; 
1121     int cnt 
= m_palette
.GetColoursCount(); 
1122     palette_t 
*pal 
= m_palette
.GetMGLpalette_t();    
1123     m_MGLDC
->setPalette(pal
, cnt
, 0); 
1124     m_MGLDC
->realizePalette(cnt
, 0, TRUE
); 
1127 void wxDC::SetFont(const wxFont
& font
) 
1136 void wxDC::SetBackground(const wxBrush
& brush
) 
1138     wxCHECK_RET( Ok(), wxT("invalid dc") ); 
1140     if (!m_backgroundBrush
.Ok()) return; 
1142     m_backgroundBrush 
= brush
; 
1143     wxColour 
&clr 
= m_backgroundBrush
.GetColour(); 
1144     m_MGLDC
->makeCurrent(); // will go away with MGL6.0 
1145     m_MGLDC
->setBackColor( 
1146              m_MGLDC
->packColorFast(clr
.Red(), clr
.Green(), clr
.Blue())); 
1149 void wxDC::SetBackgroundMode(int mode
) 
1151     m_backgroundMode 
= mode
; 
1152     if ( mode 
== wxSOLID 
) 
1153         m_MGLDC
->setBackMode(MGL_OPAQUE_BACKGROUND
); 
1155         m_MGLDC
->setBackMode(MGL_TRANSPARENT_BACKGROUND
); 
1158 void wxDC::SetLogicalFunction(int function
) 
1160     wxCHECK_RET( Ok(), wxT("invalid dc") ); 
1162     m_logicalFunction 
= function
; 
1164     m_MGLDC
->makeCurrent(); // will go away with MGL6.0 
1165     m_MGLDC
->setWriteMode(LogicalFunctionToMGLRop(m_logicalFunction
)); 
1168 int wxDC::LogicalFunctionToMGLRop(int logFunc
) const 
1170     MGL_writeModeType rop
; 
1174         case wxCLEAR
:        rop 
= MGL_R2_BLACK
;         break; 
1175         case wxXOR
:          rop 
= MGL_R2_XORSRC
;        break; 
1176         case wxINVERT
:       rop 
= MGL_R2_NOT
;           break; 
1177         case wxOR_REVERSE
:   rop 
= MGL_R2_MERGESRCNOT
;   break; 
1178         case wxAND_REVERSE
:  rop 
= MGL_R2_MASKSRCNOT
;    break; 
1179         case wxCOPY
:         rop 
= MGL_R2_COPYSRC
;       break; 
1180         case wxAND
:          rop 
= MGL_R2_MASKSRC
;       break; 
1181         case wxAND_INVERT
:   rop 
= MGL_R2_MASKNOTSRC
;    break; 
1182         case wxNO_OP
:        rop 
= MGL_R2_NOP
;           break; 
1183         case wxNOR
:          rop 
= MGL_R2_NOTMERGESRC
;   break; 
1184         case wxEQUIV
:        rop 
= MGL_R2_NOTXORSRC
;     break; 
1185         case wxSRC_INVERT
:   rop 
= MGL_R2_NOTCOPYSRC
;    break; 
1186         case wxOR_INVERT
:    rop 
= MGL_R2_MERGENOTSRC
;   break; 
1187         case wxNAND
:         rop 
= MGL_R2_NOTMASKSRC
;    break; 
1188         case wxOR
:           rop 
= MGL_R2_MERGESRC
;      break; 
1189         case wxSET
:          rop 
= MGL_R2_WHITE
;         break; 
1191            wxFAIL_MSG( wxT("unsupported logical function") ); 
1192            return MGL_REPLACE_MODE
; 
1197 bool wxDC::StartDoc(const wxString
& message
) 
1199     // We might be previewing, so return TRUE to let it continue. 
1207 void wxDC::StartPage() 
1211 void wxDC::EndPage() 
1215 // --------------------------------------------------------------------------- 
1217 // --------------------------------------------------------------------------- 
1219 wxCoord 
wxDC::GetCharHeight() const 
1221     wxCurrentDCSwitcher 
switcher(m_MGLDC
); 
1222     if ( !wxConstCast(this, wxDC
)->SelectMGLFont() ) return -1; 
1223     return YDEV2LOGREL(m_mglFont
->fontHeight
); 
1226 wxCoord 
wxDC::GetCharWidth() const 
1228     wxCurrentDCSwitcher 
switcher(m_MGLDC
); 
1229     if ( !wxConstCast(this, wxDC
)->SelectMGLFont() ) return -1; 
1230     // VS: wxT() is intentional, charWidth() has both char and wchar_t version 
1231     // VS: YDEV is corrent, it should *not* be XDEV, because font's are only 
1232     //     scaled according to m_scaleY 
1233     return YDEV2LOGREL(m_mglFont
->fontWidth
); 
1236 void wxDC::DoGetTextExtent(const wxString
& string
, wxCoord 
*x
, wxCoord 
*y
, 
1237                            wxCoord 
*descent
, wxCoord 
*externalLeading
, 
1238                            wxFont 
*theFont
) const 
1242     if ( theFont 
!= NULL 
) 
1245         wxConstCast(this, wxDC
)->SetFont(*theFont
); 
1248     wxCurrentDCSwitcher 
switcher(m_MGLDC
); 
1249     if ( !wxConstCast(this, wxDC
)->SelectMGLFont() ) return; 
1252         // VS: YDEV is corrent, it should *not* be XDEV, because font's are  
1253         //     only scaled according to m_scaleY 
1254         *x 
= YDEV2LOGREL(m_MGLDC
->textWidth(string
.c_str())); 
1256         *y 
= YDEV2LOGREL(m_MGLDC
->textHeight()); 
1258         *descent 
= YDEV2LOGREL(m_mglFont
->descent
); 
1259     if ( externalLeading 
) 
1260         *externalLeading 
= YDEV2LOGREL(m_mglFont
->leading
); 
1262     if ( theFont 
!= NULL 
) 
1263         wxConstCast(this, wxDC
)->SetFont(oldFont
); 
1268 // --------------------------------------------------------------------------- 
1270 // --------------------------------------------------------------------------- 
1272 void wxDC::ComputeScaleAndOrigin() 
1274     double newX 
= m_logicalScaleX 
* m_userScaleX
; 
1275     double newY 
= m_logicalScaleY 
* m_userScaleY
; 
1277     // make sure font will be reloaded before drawing: 
1278     if ( newY 
!= m_scaleY 
) 
1280     // make sure m_penOfs{X,Y} will be reevaluated before drawing: 
1281     if ( newY 
!= m_scaleY 
|| newX 
!= m_scaleX 
) 
1282         m_penSelected 
= FALSE
; 
1284     m_scaleX 
= newX
, m_scaleY 
= newY
; 
1287 void wxDC::SetMapMode(int mode
) 
1292           SetLogicalScale(twips2mm
*m_mm_to_pix_x
, twips2mm
*m_mm_to_pix_y
); 
1295           SetLogicalScale(pt2mm
*m_mm_to_pix_x
, pt2mm
*m_mm_to_pix_y
); 
1298           SetLogicalScale(m_mm_to_pix_x
, m_mm_to_pix_y
); 
1301           SetLogicalScale(m_mm_to_pix_x
/10.0, m_mm_to_pix_y
/10.0); 
1305           SetLogicalScale(1.0, 1.0); 
1308     m_mappingMode 
= mode
; 
1311 void wxDC::SetUserScale( double x
, double y 
) 
1313     // allow negative ? -> no 
1316     ComputeScaleAndOrigin(); 
1319 void wxDC::SetLogicalScale( double x
, double y 
) 
1322     m_logicalScaleX 
= x
; 
1323     m_logicalScaleY 
= y
; 
1324     ComputeScaleAndOrigin(); 
1327 void wxDC::SetLogicalOrigin( wxCoord x
, wxCoord y 
) 
1329     m_logicalOriginX 
= x 
* m_signX
;   // is this still correct ? 
1330     m_logicalOriginY 
= y 
* m_signY
; 
1331     ComputeScaleAndOrigin(); 
1334 void wxDC::SetDeviceOrigin( wxCoord x
, wxCoord y 
) 
1336     // only wxPostScripDC has m_signX = -1, we override SetDeviceOrigin there 
1337     m_deviceOriginX 
= x
; 
1338     m_deviceOriginY 
= y
; 
1339     ComputeScaleAndOrigin(); 
1342 void wxDC::SetAxisOrientation( bool xLeftRight
, bool yBottomUp 
) 
1344     // only wxPostScripDC has m_signX = -1, we override SetAxisOrientation there 
1345     m_signX 
= (xLeftRight 
?  1 : -1); 
1346     m_signY 
= (yBottomUp  
? -1 :  1); 
1347     ComputeScaleAndOrigin(); 
1350 // --------------------------------------------------------------------------- 
1351 // coordinates transformations 
1352 // --------------------------------------------------------------------------- 
1354 wxCoord 
wxDCBase::DeviceToLogicalX(wxCoord x
) const 
1356     return ((wxDC 
*)this)->XDEV2LOG(x
); 
1359 wxCoord 
wxDCBase::DeviceToLogicalY(wxCoord y
) const 
1361     return ((wxDC 
*)this)->YDEV2LOG(y
); 
1364 wxCoord 
wxDCBase::DeviceToLogicalXRel(wxCoord x
) const 
1366     return ((wxDC 
*)this)->XDEV2LOGREL(x
); 
1369 wxCoord 
wxDCBase::DeviceToLogicalYRel(wxCoord y
) const 
1371     return ((wxDC 
*)this)->YDEV2LOGREL(y
); 
1374 wxCoord 
wxDCBase::LogicalToDeviceX(wxCoord x
) const 
1376     return ((wxDC 
*)this)->XLOG2DEV(x
); 
1379 wxCoord 
wxDCBase::LogicalToDeviceY(wxCoord y
) const 
1381     return ((wxDC 
*)this)->YLOG2DEV(y
); 
1384 wxCoord 
wxDCBase::LogicalToDeviceXRel(wxCoord x
) const 
1386     return ((wxDC 
*)this)->XLOG2DEVREL(x
); 
1389 wxCoord 
wxDCBase::LogicalToDeviceYRel(wxCoord y
) const 
1391     return ((wxDC 
*)this)->YLOG2DEVREL(y
); 
1395 void wxDC::DoGetSize(int *w
, int *h
) const 
1397     if (w
) *w 
= m_MGLDC
->sizex()+1; 
1398     if (h
) *h 
= m_MGLDC
->sizey()+1; 
1401 void wxDC::DoGetSizeMM(int *width
, int *height
) const 
1406     if ( width 
) *width 
= int(double(w
) / (m_userScaleX
*m_mm_to_pix_x
)); 
1407     if ( height 
) *height 
= int(double(h
) / (m_userScaleY
*m_mm_to_pix_y
)); 
1410 wxSize 
wxDC::GetPPI() const 
1412     return wxSize(int(double(m_mm_to_pix_x
) * inches2mm
),  
1413                   int(double(m_mm_to_pix_y
) * inches2mm
)); 
1417 // --------------------------------------------------------------------------- 
1419 // --------------------------------------------------------------------------- 
1421 bool wxDC::DoBlit(wxCoord xdest
, wxCoord ydest
, 
1422                   wxCoord width
, wxCoord height
, 
1423                   wxDC 
*source
, wxCoord xsrc
, wxCoord ysrc
, 
1424                   int rop
, bool useMask
, 
1425                   wxCoord xsrcMask
, wxCoord ysrcMask
) 
1427     wxCHECK_MSG( Ok(), FALSE
, wxT("invalid dc") ); 
1428     wxCHECK_MSG( source
, FALSE
, wxT("invalid source dc") ); 
1430     // transform the source DC coords to the device ones 
1431     xsrc 
= source
->LogicalToDeviceX(xsrc
); 
1432     ysrc 
= source
->LogicalToDeviceY(ysrc
); 
1434     /* FIXME_MGL: use the mask origin when drawing transparently */ 
1435     if (xsrcMask 
== -1 && ysrcMask 
== -1) 
1437         xsrcMask 
= xsrc
; ysrcMask 
= ysrc
; 
1441         xsrcMask 
= source
->LogicalToDeviceX(xsrcMask
); 
1442         ysrcMask 
= source
->LogicalToDeviceY(ysrcMask
); 
1445     CalcBoundingBox(xdest
, ydest
); 
1446     CalcBoundingBox(xdest 
+ width
, ydest 
+ height
); 
1448     /* scale/translate size and position */ 
1449     wxCoord xx 
= XLOG2DEV(xdest
); 
1450     wxCoord yy 
= YLOG2DEV(ydest
); 
1451     wxCoord ww 
= XLOG2DEVREL(width
); 
1452     wxCoord hh 
= YLOG2DEVREL(height
); 
1454     if ( source
->m_isMemDC 
) 
1456         wxMemoryDC 
*memDC 
= (wxMemoryDC
*) source
; 
1457         DoDrawSubBitmap(memDC
->GetSelectedObject(), xsrc
, ysrc
, ww
, hh
, 
1458                         xdest
, ydest
, rop
, useMask
); 
1462         m_MGLDC
->makeCurrent(); // will go away with MGL6.0 
1463         m_MGLDC
->bitBlt(*source
->GetMGLDC(),  
1464                         xsrc
, ysrc
, xsrc 
+ ww
, ysrc 
+ hh
, 
1465                         xx
, yy
, LogicalFunctionToMGLRop(rop
)); 
1471 void wxDC::DoDrawBitmap(const wxBitmap 
&bmp
, wxCoord x
, wxCoord y
, bool useMask
) 
1473     wxCHECK_RET( Ok(), wxT("invalid dc") ); 
1474     wxCHECK_RET( bmp
.Ok(), wxT("invalid bitmap") ); 
1476     wxCoord w 
= bmp
.GetWidth(); 
1477     wxCoord h 
= bmp
.GetHeight(); 
1479     DoDrawSubBitmap(bmp
, 0, 0, w
, h
, x
, y
, m_logicalFunction
, useMask
); 
1482 void wxDC::DoDrawIcon(const wxIcon
& icon
, wxCoord x
, wxCoord y
) 
1484     // VZ: egcs 1.0.3 refuses to compile this without cast, no idea why 
1485     DoDrawBitmap((const wxBitmap
&)icon
, x
, y
, (bool)TRUE
); 
1489 static inline void DoBitBlt(const wxBitmap
& src
, MGLDevCtx 
*dst
, 
1490                             int sx
, int sy
, int sw
, int sh
,  
1491                             int dx
, int dy
, int dw
, int dh
,  
1492                             int rop
, bool useStretching
, bool putSection
) 
1494     bitmap_t 
*bmp 
= src
.GetMGLbitmap_t(); 
1498             dst
->putBitmap(dx
, dy
, bmp
, rop
); 
1500             dst
->putBitmapSection(sx
, sy
, sx 
+ sw
, sy 
+ sh
, dx
, dy
, bmp
, rop
); 
1505             dst
->stretchBitmap(dx
, dy
, dx 
+ dw
, dy 
+ dh
, bmp
, rop
); 
1507             dst
->stretchBitmapSection(sx
, sy
, sx 
+ sw
, sy 
+ sh
,  
1508                                       dx
, dy
, dx 
+ dw
, dy 
+ dh
, bmp
, rop
); 
1512 void wxDC::DoDrawSubBitmap(const wxBitmap 
&bmp
,  
1513                            wxCoord x
, wxCoord y
, wxCoord w
, wxCoord h
, 
1514                            wxCoord destx
, wxCoord desty
, int rop
, bool useMask
) 
1516     wxCHECK_RET( Ok(), wxT("invalid dc") ); 
1517     wxCHECK_RET( bmp
.Ok(), wxT("invalid bitmap") ); 
1519     CalcBoundingBox(x
, y
); 
1520     CalcBoundingBox(x 
+ w
, y 
+ h
); 
1522     wxCoord dx 
= XLOG2DEV(destx
); 
1523     wxCoord dy 
= YLOG2DEV(desty
); 
1524     wxCoord dw 
= XLOG2DEVREL(w
); 
1525     wxCoord dh 
= YLOG2DEVREL(h
); 
1527     m_MGLDC
->makeCurrent(); // will go away with MGL6.0 
1529     bool useStretching 
= ((w 
!= dw
) || (h 
!= dh
)); 
1530     bool putSection 
= (w 
!= bmp
.GetWidth() || h 
!= bmp
.GetHeight()); 
1531     MGL_writeModeType mglRop 
= (MGL_writeModeType
)LogicalFunctionToMGLRop(rop
); 
1533     if ( bmp
.GetDepth() == 1 ) 
1535         // Mono bitmaps are handled in special way -- all 1s are drawn in 
1536         // foreground colours, all 0s in background colour. 
1538         ((wxBitmap
&)bmp
).SetMonoPalette(m_textForegroundColour
, m_textBackgroundColour
); 
1541     if ( useMask 
&& bmp
.GetMask() ) 
1543         // Since MGL does not support masks directly (in MGL, mask is handled 
1544         // in same way as in wxImage, i.e. there is one "key" color), we  
1545         // simulate masked bitblt in 6 steps (same as in MSW): 
1547         // 1. Create a temporary bitmap and copy the destination area into it.  
1548         // 2. Copy the source area into the temporary bitmap using the  
1549         //    specified logical function. 
1550         // 3. Set the masked area in the temporary bitmap to BLACK by ANDing  
1551         //    the mask bitmap with the temp bitmap with the foreground colour  
1552         //    set to WHITE and the bg colour set to BLACK. 
1553         // 4. Set the unmasked area in the destination area to BLACK by 
1554         //    ANDing the mask bitmap with the destination area with the  
1555         //    foreground colour set to BLACK and the background colour set 
1557         // 5. OR the temporary bitmap with the destination area.   
1558         // 6. Delete the temporary bitmap.  
1560         // This sequence of operations ensures that the source's transparent  
1561         // area need not be black, and logical functions are supported. 
1563         wxBitmap 
*mask 
= bmp
.GetMask()->GetBitmap(); 
1567         if ( GetDepth() <= 8 ) 
1569             temp 
= new MGLMemoryDC(dw
, dh
, GetDepth(), NULL
); 
1571             tempdc
.SetMGLDC(temp
, FALSE
); 
1572             tempdc
.SetPalette(m_palette
); 
1577             m_MGLDC
->getPixelFormat(pf
); 
1578             temp 
= new MGLMemoryDC(dw
, dh
, GetDepth(), &pf
); 
1581         wxCHECK_RET( temp
->isValid(), wxT("cannot create temporary dc") ); 
1583         temp
->bitBlt(*m_MGLDC
, dx
, dy
, dx 
+ dw
, dy 
+ dh
, 0, 0, MGL_REPLACE_MODE
); 
1585         DoBitBlt(bmp
, temp
, x
, y
, w
, h
, 0, 0, dw
, dh
, mglRop
,  
1586                  useStretching
, putSection
); 
1588         mask
->SetMonoPalette(wxColour(0,0,0), wxColour(255,255,255)); 
1589         DoBitBlt(*mask
, temp
, x
, y
, w
, h
, 0, 0, dw
, dh
, MGL_R2_MASKSRC
,  
1590                  useStretching
, putSection
); 
1591         DoBitBlt(*mask
, m_MGLDC
, x
, y
, w
, h
, dx
, dy
, dw
, dh
, MGL_R2_MASKNOTSRC
,  
1592                  useStretching
, putSection
); 
1594         m_MGLDC
->bitBlt(*temp
, 0, 0, dw
, dh
, dx
, dy
, MGL_OR_MODE
); 
1601         DoBitBlt(bmp
, m_MGLDC
, x
, y
, w
, h
, dx
, dy
, dw
, dh
, mglRop
,  
1602                  useStretching
, putSection
);