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 // ---------------------------------------------------------------------------
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/fontmap.h"
37 #include "wx/mgl/private.h"
46 //-----------------------------------------------------------------------------
48 //-----------------------------------------------------------------------------
51 #define M_PI 3.14159265358979323846
54 const double mm2inches
= 0.0393700787402;
55 const double inches2mm
= 25.4;
56 const double mm2twips
= 56.6929133859;
57 const double twips2mm
= 0.0176388888889;
58 const double mm2pt
= 2.83464566929;
59 const double pt2mm
= 0.352777777778;
60 const double RAD2DEG
= 180.0 / M_PI
;
63 //-----------------------------------------------------------------------------
65 //-----------------------------------------------------------------------------
67 const ushort STIPPLE_wxDOT
= 0x5555/* - - - - - - - -*/;
68 const ushort STIPPLE_wxLONG_DASH
= 0xF0F0/* ---- ----*/;
69 const ushort STIPPLE_wxSHORT_DASH
= 0xCCCC/*-- -- -- -- */;
70 const ushort STIPPLE_wxDOT_DASH
= 0x3939/* --- - --- -*/;
71 const ushort STIPPLE_wxSOLID
= 0xFFFF/*----------------*/;
73 #define PATTERN_ROW(b7,b6,b5,b4,b3,b2,b1,b0) \
74 ((b7 << 7) | (b6 << 6) | (b5 << 5) | (b4 << 4) | \
75 (b3 << 3) | (b2 << 2) | (b1 << 1) | b0)
77 static pattern_t PATTERN_wxFDIAGONAL_HATCH
= {{
78 PATTERN_ROW(1,0,0,0,0,0,0,0),
79 PATTERN_ROW(0,1,0,0,0,0,0,0),
80 PATTERN_ROW(0,0,1,0,0,0,0,0),
81 PATTERN_ROW(0,0,0,1,0,0,0,0),
82 PATTERN_ROW(0,0,0,0,1,0,0,0),
83 PATTERN_ROW(0,0,0,0,0,1,0,0),
84 PATTERN_ROW(0,0,0,0,0,0,1,0),
85 PATTERN_ROW(0,0,0,0,0,0,0,1),
88 static pattern_t PATTERN_wxCROSSDIAG_HATCH
= {{
89 PATTERN_ROW(1,0,0,0,0,0,0,1),
90 PATTERN_ROW(0,1,0,0,0,0,1,0),
91 PATTERN_ROW(0,0,1,0,0,1,0,0),
92 PATTERN_ROW(0,0,0,1,1,0,0,0),
93 PATTERN_ROW(0,0,0,1,1,0,0,0),
94 PATTERN_ROW(0,0,1,0,0,1,0,0),
95 PATTERN_ROW(0,1,0,0,0,0,1,0),
96 PATTERN_ROW(1,0,0,0,0,0,0,1),
99 static pattern_t PATTERN_wxBDIAGONAL_HATCH
= {{
100 PATTERN_ROW(0,0,0,0,0,0,0,1),
101 PATTERN_ROW(0,0,0,0,0,0,1,0),
102 PATTERN_ROW(0,0,0,0,0,1,0,0),
103 PATTERN_ROW(0,0,0,0,1,0,0,0),
104 PATTERN_ROW(0,0,0,1,0,0,0,0),
105 PATTERN_ROW(0,0,1,0,0,0,0,0),
106 PATTERN_ROW(0,1,0,0,0,0,0,0),
107 PATTERN_ROW(1,0,0,0,0,0,0,0),
110 static pattern_t PATTERN_wxCROSS_HATCH
= {{
111 PATTERN_ROW(0,0,0,1,0,0,0,0),
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(1,1,1,1,1,1,1,1),
115 PATTERN_ROW(0,0,0,1,0,0,0,0),
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),
121 static pattern_t PATTERN_wxHORIZONTAL_HATCH
= {{
122 PATTERN_ROW(0,0,0,0,0,0,0,0),
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(1,1,1,1,1,1,1,1),
126 PATTERN_ROW(0,0,0,0,0,0,0,0),
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),
132 static pattern_t PATTERN_wxVERTICAL_HATCH
= {{
133 PATTERN_ROW(0,0,0,1,0,0,0,0),
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),
145 //-----------------------------------------------------------------------------
147 //-----------------------------------------------------------------------------
149 IMPLEMENT_ABSTRACT_CLASS(wxDC
, wxDCBase
)
151 // Default constructor
157 m_ok
= FALSE
; // must call SetMGLDevCtx() before using it
159 m_mm_to_pix_x
= (double)wxGetDisplaySize().GetWidth() /
160 (double)wxGetDisplaySizeMM().GetWidth();
161 m_mm_to_pix_y
= (double)wxGetDisplaySize().GetHeight() /
162 (double)wxGetDisplaySizeMM().GetHeight();
164 m_pen
= *wxBLACK_PEN
;
165 m_font
= *wxNORMAL_FONT
;
166 m_brush
= *wxWHITE_BRUSH
;
167 m_penOfsX
= m_penOfsY
= 0;
169 m_penSelected
= m_brushSelected
= FALSE
;
170 m_downloadedPatterns
[0] = m_downloadedPatterns
[1] = FALSE
;
182 void wxDC::SetMGLDC(MGLDevCtx
*mgldc
, bool OwnsMGLDC
)
184 if ( m_OwnsMGLDC
&& m_MGLDC
)
187 m_OwnsMGLDC
= OwnsMGLDC
;
190 if ( !m_globalClippingRegion
.IsNull() )
191 SetClippingRegion(m_globalClippingRegion
);
196 void wxDC::InitializeMGLDC()
198 if ( GetDepth() > 8 )
200 wxCurrentDCSwitcher
switcher(m_MGLDC
); // will go away with MGL6
201 m_MGLDC
->setFontBlendMode(MGL_AA_RGBBLEND
);
206 // ---------------------------------------------------------------------------
208 // ---------------------------------------------------------------------------
211 #define DO_SET_CLIPPING_BOX(rg) \
213 wxRect rect = rg.GetBox(); \
214 m_clipX1 = (wxCoord) XDEV2LOG(rect.GetLeft()); \
215 m_clipY1 = (wxCoord) YDEV2LOG(rect.GetTop()); \
216 m_clipX2 = (wxCoord) XDEV2LOG(rect.GetRight()); \
217 m_clipY2 = (wxCoord) YDEV2LOG(rect.GetBottom()); \
220 void wxDC::DoSetClippingRegion(wxCoord cx
, wxCoord cy
, wxCoord cw
, wxCoord ch
)
222 wxCHECK_RET( Ok(), wxT("invalid dc") );
224 wxRect
rect(XLOG2DEV(cx
), YLOG2DEV(cy
), XLOG2DEVREL(cw
), YLOG2DEVREL(ch
));
226 if ( !m_currentClippingRegion
.IsNull() )
227 m_currentClippingRegion
.Intersect(rect
);
229 m_currentClippingRegion
.Union(rect
);
231 m_MGLDC
->setClipRegion(m_currentClippingRegion
.GetMGLRegion());
234 DO_SET_CLIPPING_BOX(m_currentClippingRegion
)
237 void wxDC::DoSetClippingRegionAsRegion(const wxRegion
& region
)
239 wxCHECK_RET( Ok(), wxT("invalid dc") );
241 if ( region
.IsEmpty() )
243 DestroyClippingRegion();
249 // check if the DC is scaled or moved, and if yes, then
250 // convert rg to device coordinates:
251 if ( m_deviceOriginX
!= 0 || m_deviceOriginY
!= 0 ||
252 m_logicalOriginX
!= 0 || m_logicalOriginY
!= 0 ||
253 XLOG2DEVREL(500) != 500 || YLOG2DEVREL(500) != 500 )
255 region_t
*mrg
= rg
.GetMGLRegion().rgnPointer();
258 for (s
= mrg
->spans
; s
; s
= s
->next
)
260 s
->y
= YLOG2DEV(s
->y
);
261 for (p
= s
->seg
; p
; p
= p
->next
)
262 p
->x
= XLOG2DEV(p
->x
);
266 if ( !m_currentClippingRegion
.IsNull() )
267 m_currentClippingRegion
.Intersect(rg
);
269 m_currentClippingRegion
.Union(rg
);
271 m_MGLDC
->setClipRegion(m_currentClippingRegion
.GetMGLRegion());
274 DO_SET_CLIPPING_BOX(m_currentClippingRegion
)
277 void wxDC::DestroyClippingRegion()
279 wxCHECK_RET( Ok(), wxT("invalid dc") );
281 if ( !m_globalClippingRegion
.IsNull() )
283 m_MGLDC
->setClipRegion(m_globalClippingRegion
.GetMGLRegion());
284 m_currentClippingRegion
= m_globalClippingRegion
;
289 m_MGLDC
->setClipRect(MGLRect(0, 0, m_MGLDC
->sizex()+1, m_MGLDC
->sizey()+1));
291 m_currentClippingRegion
.Clear();
295 // ---------------------------------------------------------------------------
296 // query capabilities
297 // ---------------------------------------------------------------------------
299 bool wxDC::CanDrawBitmap() const
304 bool wxDC::CanGetTextExtent() const
309 int wxDC::GetDepth() const
311 return m_MGLDC
->getBitsPerPixel();
314 // ---------------------------------------------------------------------------
316 // ---------------------------------------------------------------------------
320 wxCHECK_RET( Ok(), wxT("invalid dc") );
322 m_MGLDC
->makeCurrent(); // will go away with MGL6.0
323 if ( m_backgroundBrush
.GetStyle() != wxTRANSPARENT
)
326 wxBrush oldb
= m_brush
;
327 SetBrush(m_backgroundBrush
);
330 m_MGLDC
->fillRect(0, 0, w
, h
);
335 void wxDC::DoFloodFill(wxCoord x
, wxCoord y
, const wxColour
& col
, int style
)
337 if (GetBrush().GetStyle() == wxTRANSPARENT
)
339 wxLogDebug(wxT("In FloodFill, Current Brush is transparent, no filling done"));
344 this->GetSize(&width
, &height
);
345 //it would be nice to fail if we don't get a sensible size...
346 if (width
< 1 || height
< 1)
348 wxLogError(wxT("In FloodFill, dc.GetSize routine failed, method not supported by this DC"));
352 //this is much faster than doing the individual pixels
354 wxBitmap
bitmap(width
, height
);
355 memdc
.SelectObject(bitmap
);
356 memdc
.Blit(0, 0, width
, height
, (wxDC
*) this, 0, 0);
357 memdc
.SelectObject(wxNullBitmap
);
359 wxImage
image(bitmap
);
360 image
.DoFloodFill (x
,y
, GetBrush(), col
, style
, GetLogicalFunction());
361 bitmap
= wxBitmap(image
);
362 memdc
.SelectObject(bitmap
);
363 this->Blit(0, 0, width
, height
, &memdc
, 0, 0);
364 memdc
.SelectObject(wxNullBitmap
);
367 bool wxDC::DoGetPixel(wxCoord x
, wxCoord y
, wxColour
*col
) const
369 wxCHECK_MSG( col
, FALSE
, _T("NULL colour parameter in wxDC::GetPixel"));
372 m_MGLDC
->unpackColorFast(m_MGLDC
->getPixel(XLOG2DEV(x
), YLOG2DEV(y
)),
378 void wxDC::DoCrossHair(wxCoord x
, wxCoord y
)
380 wxCHECK_RET( Ok(), wxT("invalid dc") );
382 if ( m_pen
.GetStyle() != wxTRANSPARENT
)
387 m_MGLDC
->makeCurrent(); // will go away with MGL6.0
388 if ( !m_penSelected
)
390 wxCoord xx
= XLOG2DEV(x
);
391 wxCoord yy
= YLOG2DEV(y
);
392 m_MGLDC
->line(m_penOfsX
, yy
+ m_penOfsY
, w
-1 + m_penOfsX
, yy
+ m_penOfsY
);
393 m_MGLDC
->line(xx
+ m_penOfsX
, m_penOfsY
, x
+ m_penOfsX
, h
-1 + m_penOfsY
);
394 CalcBoundingBox(0, 0);
395 CalcBoundingBox(w
, h
);
399 void wxDC::DoDrawLine(wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
)
401 wxCHECK_RET( Ok(), wxT("invalid dc") );
403 if ( m_pen
.GetStyle() != wxTRANSPARENT
)
405 m_MGLDC
->makeCurrent(); // will go away with MGL6.0
406 if ( !m_penSelected
)
408 m_MGLDC
->lineExt(XLOG2DEV(x1
) + m_penOfsX
, YLOG2DEV(y1
) + m_penOfsY
,
409 XLOG2DEV(x2
) + m_penOfsX
, YLOG2DEV(y2
) + m_penOfsY
,FALSE
);
410 CalcBoundingBox(x1
, y1
);
411 CalcBoundingBox(x2
, y2
);
415 // Draws an arc of a circle, centred on (xc, yc), with starting point (x1, y1)
416 // and ending at (x2, y2)
417 void wxDC::DoDrawArc(wxCoord x1
, wxCoord y1
,
418 wxCoord x2
, wxCoord y2
,
419 wxCoord xc
, wxCoord yc
)
421 wxCHECK_RET( Ok(), wxT("invalid dc") );
423 wxCoord xx1
= XLOG2DEV(x1
);
424 wxCoord yy1
= YLOG2DEV(y1
);
425 wxCoord xx2
= XLOG2DEV(x2
);
426 wxCoord yy2
= YLOG2DEV(y2
);
427 wxCoord xxc
= XLOG2DEV(xc
);
428 wxCoord yyc
= YLOG2DEV(yc
);
429 double dx
= xx1
- xxc
;
430 double dy
= yy1
- yyc
;
431 double radius
= sqrt((double)(dx
*dx
+dy
*dy
));
432 wxCoord r
= (wxCoord
)radius
;
433 double radius1
, radius2
;
436 if (xx1
== xx2
&& yy1
== yy2
)
441 else if (radius
== 0.0)
443 radius1
= radius2
= 0.0;
447 radius1
= (xx1
- xxc
== 0) ?
448 (yy1
- yyc
< 0) ? 90.0 : -90.0 :
449 -atan2(double(yy1
-yyc
), double(xx1
-xxc
)) * RAD2DEG
;
450 radius2
= (xx2
- xxc
== 0) ?
451 (yy2
- yyc
< 0) ? 90.0 : -90.0 :
452 -atan2(double(yy2
-yyc
), double(xx2
-xxc
)) * RAD2DEG
;
454 wxCoord alpha1
= wxCoord(radius1
);
455 wxCoord alpha2
= alpha1
+ wxCoord(radius2
- radius1
);
456 while (alpha2
<= 0) alpha2
+= 360;
457 while (alpha1
> 360) alpha1
-= 360;
459 m_MGLDC
->makeCurrent(); // will go away with MGL6.0
460 if ( m_brush
.GetStyle() != wxTRANSPARENT
)
462 if ( !m_brushSelected
)
464 m_MGLDC
->fillEllipseArc(xxc
, yyc
, r
, r
, alpha1
, alpha2
);
467 if ( m_pen
.GetStyle() != wxTRANSPARENT
)
469 if ( !m_penSelected
)
471 m_MGLDC
->ellipseArc(xxc
+ m_penOfsX
, yyc
+ m_penOfsY
, r
, r
, alpha1
, alpha2
);
474 CalcBoundingBox(xc
- r
, yc
- r
);
475 CalcBoundingBox(xc
+ r
, yc
+ r
);
478 void wxDC::DoDrawPoint(wxCoord x
, wxCoord y
)
480 wxCHECK_RET( Ok(), wxT("invalid dc") );
482 if ( m_pen
.GetStyle() != wxTRANSPARENT
)
484 m_MGLDC
->makeCurrent(); // will go away with MGL6.0
485 if ( !m_penSelected
)
487 m_MGLDC
->pixel(XLOG2DEV(x
), YLOG2DEV(y
));
488 CalcBoundingBox(x
, y
);
492 void wxDC::DoDrawPolygon(int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
,int fillStyle
)
494 wxCHECK_RET( Ok(), wxT("invalid dc") );
496 wxCoord xxoffset
= XLOG2DEVREL(xoffset
),
497 yyoffset
= YLOG2DEVREL(yoffset
);
498 MGLPoint
*cpoints
= new MGLPoint
[n
+1];
499 for (int i
= 0; i
< n
; i
++)
501 CalcBoundingBox(points
[i
].x
+ xoffset
, points
[i
].y
+ yoffset
);
502 cpoints
[i
].x
= (int)(XLOG2DEV(points
[i
].x
));
503 cpoints
[i
].y
= (int)(YLOG2DEV(points
[i
].y
));
505 cpoints
[n
] = cpoints
[0];
507 m_MGLDC
->makeCurrent(); // will go away with MGL6.0
508 if ( m_brush
.GetStyle() != wxTRANSPARENT
)
510 if ( !m_brushSelected
)
512 m_MGLDC
->fillPolygon(n
, cpoints
, xxoffset
, yyoffset
);
515 if ( m_pen
.GetStyle() != wxTRANSPARENT
)
517 if ( !m_penSelected
)
519 if (m_penOfsX
!= 0 || m_penOfsY
!= 0)
521 for (int i
= 0; i
<= n
; i
++)
523 cpoints
[i
].x
+= m_penOfsX
;
524 cpoints
[i
].y
+= m_penOfsY
;
527 m_MGLDC
->polyLine(n
+1, cpoints
);
533 void wxDC::DoDrawLines(int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
)
535 wxCHECK_RET( Ok(), wxT("invalid dc") );
537 if ( m_pen
.GetStyle() != wxTRANSPARENT
)
539 MGLPoint
*cpoints
= new MGLPoint
[n
];
540 m_MGLDC
->makeCurrent(); // will go away with MGL6.0
541 if ( !m_penSelected
)
543 for (int i
= 0; i
< n
; i
++)
545 CalcBoundingBox(points
[i
].x
+ xoffset
, points
[i
].y
+ yoffset
);
546 cpoints
[i
].x
= (int)(XLOG2DEV(points
[i
].x
+ xoffset
) /*+ m_penOfsX*/);
547 cpoints
[i
].y
= (int)(YLOG2DEV(points
[i
].y
+ yoffset
) /*+ m_penOfsY*/);
549 m_MGLDC
->polyLine(n
, cpoints
);
554 void wxDC::DoDrawRectangle(wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
556 wxCHECK_RET( Ok(), wxT("invalid dc") );
558 wxCoord xx
= XLOG2DEV(x
);
559 wxCoord yy
= YLOG2DEV(y
);
560 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
561 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
563 if ( ww
== 0 || hh
== 0 ) return;
576 m_MGLDC
->makeCurrent(); // will go away with MGL6.0
577 if ( m_brush
.GetStyle() != wxTRANSPARENT
)
579 if ( !m_brushSelected
)
581 m_MGLDC
->fillRect(xx
, yy
, xx
+ ww
, yy
+ hh
);
584 if ( m_pen
.GetStyle() != wxTRANSPARENT
)
586 if ( !m_penSelected
)
589 m_MGLDC
->rect(xx
+ m_penOfsX
, yy
+ m_penOfsY
,
590 xx
+ ww
+ m_penOfsX
, yy
+ hh
+ m_penOfsY
);
593 CalcBoundingBox(x
, y
);
594 CalcBoundingBox(x
+ width
, y
+ height
);
597 void wxDC::DoDrawRoundedRectangle(wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double radius
)
599 wxCHECK_RET( Ok(), wxT("invalid dc") );
602 radius
= -radius
* ((width
< height
) ? width
: height
);
604 wxCoord xx
= XLOG2DEV(x
);
605 wxCoord yy
= YLOG2DEV(y
);
606 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
607 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
608 wxCoord rr
= XLOG2DEVREL((wxCoord
)radius
);
610 // CMB: handle -ve width and/or height
622 // CMB: if radius is zero use DrawRectangle() instead to avoid
623 // X drawing errors with small radii
626 DrawRectangle(x
, y
, width
, height
);
630 // CMB: draw nothing if transformed w or h is 0
631 if ( ww
== 0 || hh
== 0 ) return;
633 // CMB: ensure dd is not larger than rectangle otherwise we
634 // get an hour glass shape
636 if ( dd
> ww
) dd
= ww
;
637 if ( dd
> hh
) dd
= hh
;
640 m_MGLDC
->makeCurrent(); // will go away with MGL6.0
641 if ( m_brush
.GetStyle() != wxTRANSPARENT
)
643 if (!m_brushSelected
)
645 m_MGLDC
->fillRect(xx
+rr
, yy
, xx
+ww
-rr
, yy
+hh
);
646 m_MGLDC
->fillRect(xx
, yy
+rr
, xx
+ww
, yy
+hh
-rr
);
647 m_MGLDC
->fillEllipseArc(xx
+rr
, yy
+rr
, rr
, rr
, 90, 180);
648 m_MGLDC
->fillEllipseArc(xx
+ww
-rr
, yy
+rr
, rr
, rr
, 0, 90);
649 m_MGLDC
->fillEllipseArc(xx
+rr
, yy
+hh
-rr
, rr
, rr
, 180, 270);
650 m_MGLDC
->fillEllipseArc(xx
+ww
-rr
, yy
+hh
-rr
, rr
, rr
, 270, 0);
653 if ( m_pen
.GetStyle() != wxTRANSPARENT
)
655 if ( !m_penSelected
)
659 m_MGLDC
->line(xx
+rr
+1, yy
, xx
+ww
-rr
, yy
);
660 m_MGLDC
->ellipseArc(xx
+ww
-rr
, yy
+rr
, rr
, rr
, 0, 90);
661 m_MGLDC
->line(xx
+ww
, yy
+rr
+1, xx
+ww
, yy
+hh
-rr
);
662 m_MGLDC
->ellipseArc(xx
+ww
-rr
, yy
+hh
-rr
, rr
, rr
, 270, 0);
663 m_MGLDC
->line(xx
+ww
-rr
, yy
+hh
, xx
+rr
+1, yy
+hh
);
664 m_MGLDC
->ellipseArc(xx
+rr
, yy
+hh
-rr
, rr
, rr
, 180, 270);
665 m_MGLDC
->line(xx
, yy
+hh
-rr
, xx
, yy
+rr
+1);
666 m_MGLDC
->ellipseArc(xx
+rr
, yy
+rr
, rr
, rr
, 90, 180);
669 CalcBoundingBox(x
, y
);
670 CalcBoundingBox(x
+ width
, y
+ height
);
673 void wxDC::DoDrawEllipse(wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
675 wxCHECK_RET( Ok(), wxT("invalid dc") );
677 wxCoord x2
= (x
+width
);
678 wxCoord y2
= (y
+height
);
680 m_MGLDC
->makeCurrent(); // will go away with MGL6.0
681 if ( m_brush
.GetStyle() != wxTRANSPARENT
)
683 if ( !m_brushSelected
)
685 MGLRect
rect(XLOG2DEV(x
), YLOG2DEV(y
), XLOG2DEV(x2
), YLOG2DEV(y2
));
686 m_MGLDC
->fillEllipse(rect
);
689 if ( m_pen
.GetStyle() != wxTRANSPARENT
)
691 if ( !m_penSelected
)
693 MGLRect
rect(XLOG2DEV(x
) + m_penOfsX
, YLOG2DEV(y
) + m_penOfsY
,
694 XLOG2DEV(x2
) + m_penOfsX
, YLOG2DEV(y2
) + m_penOfsY
);
695 m_MGLDC
->ellipse(rect
);
698 CalcBoundingBox(x
, y
);
699 CalcBoundingBox(x2
, y2
);
702 void wxDC::DoDrawEllipticArc(wxCoord x
,wxCoord y
,wxCoord w
,wxCoord h
,double sa
,double ea
)
704 wxCHECK_RET( Ok(), wxT("invalid dc") );
709 m_MGLDC
->makeCurrent(); // will go away with MGL6.0
710 if ( m_brush
.GetStyle() != wxTRANSPARENT
)
712 if (!m_brushSelected
) SelectBrush();
713 MGLRect
rect(XLOG2DEV(x
), YLOG2DEV(y
), XLOG2DEV(x2
), YLOG2DEV(y2
));
714 m_MGLDC
->fillEllipseArc(rect
, (int)sa
, (int)ea
);
717 if ( m_pen
.GetStyle() != wxTRANSPARENT
)
719 if ( !m_penSelected
)
721 MGLRect
rect(XLOG2DEV(x
) + m_penOfsX
, YLOG2DEV(y
) + m_penOfsY
,
722 XLOG2DEV(x2
) + m_penOfsX
, YLOG2DEV(y2
) + m_penOfsY
);
723 m_MGLDC
->ellipseArc(rect
, (int)sa
, (int)ea
);
726 CalcBoundingBox(x
, y
);
727 CalcBoundingBox(x2
, y2
);
730 void wxDC::DoDrawText(const wxString
& text
, wxCoord x
, wxCoord y
)
732 m_MGLDC
->makeCurrent(); // will go away with MGL6.0
733 DrawAnyText(text
, x
, y
);
735 // update the bounding box
737 CalcBoundingBox(x
, y
);
738 GetTextExtent(text
, &w
, &h
);
739 CalcBoundingBox(x
+ w
, y
+ h
);
742 bool wxDC::SelectMGLFont()
744 if ( m_mglFont
== NULL
)
746 float scale
= m_scaleY
;
747 bool antialiased
= (GetDepth() > 8);
749 m_mglFont
= m_font
.GetMGLfont_t(scale
, antialiased
);
750 wxCHECK_MSG( m_mglFont
, FALSE
, wxT("invalid font") );
752 m_MGLDC
->useFont(m_mglFont
);
753 wxLogTrace("mgl_font", "useFont(%p)", m_mglFont
);
756 wxNativeEncodingInfo nativeEnc
;
757 wxFontEncoding encoding
= m_font
.GetEncoding();
758 if ( !wxGetNativeFontEncoding(encoding
, &nativeEnc
) ||
759 !wxTestFontEncoding(nativeEnc
) )
762 if ( !wxFontMapper::Get()->GetAltForEncoding(encoding
, &nativeEnc
) )
765 nativeEnc
.mglEncoding
= MGL_ENCODING_ASCII
;
768 m_MGLDC
->setTextEncoding(nativeEnc
.mglEncoding
);
774 void wxDC::DrawAnyText(const wxString
& text
, wxCoord x
, wxCoord y
)
776 wxCHECK_RET( Ok(), wxT("invalid dc") );
781 wxCoord xx
= XLOG2DEV(x
);
782 wxCoord yy
= YLOG2DEV(y
);
784 m_MGLDC
->setLineStyle(MGL_LINE_STIPPLE
);
785 m_MGLDC
->setLineStipple(0xFFFF);
786 m_MGLDC
->setPenSize(1, 1);
787 m_MGLDC
->setPenStyle(MGL_BITMAP_SOLID
);
790 const wchar_t *c_text
= text
.c_str();
792 const char *c_text
= text
.c_str();
796 // FIXME_MGL - this is a temporary hack in absence of proper
797 // implementation of solid text background in MGL. Once
798 // the bug in MGL is fixed, this code should be nuked
799 // immediately. Note that the code is not 100% correct;
800 // it only works with wxCOPY logical function
801 if ( m_backgroundMode
== wxSOLID
)
803 int w
= m_MGLDC
->textWidth(c_text
);
804 int h
= m_MGLDC
->textHeight();
805 m_MGLDC
->setColor(m_MGLDC
->packColorFast(m_textBackgroundColour
.Red(),
806 m_textBackgroundColour
.Green(), m_textBackgroundColour
.Blue()));
807 m_MGLDC
->fillRect(xx
, yy
, xx
+w
, yy
+h
);
811 m_MGLDC
->setColor(m_MGLDC
->packColorFast(m_textForegroundColour
.Red(),
812 m_textForegroundColour
.Green(), m_textForegroundColour
.Blue()));
813 m_MGLDC
->setBackColor(m_MGLDC
->packColorFast(m_textBackgroundColour
.Red(),
814 m_textBackgroundColour
.Green(), m_textBackgroundColour
.Blue()));
816 m_MGLDC
->drawStr(xx
, yy
, c_text
);
819 if ( m_font
.GetUnderlined() )
821 int x1
= xx
, y1
= yy
;
823 int w
= m_MGLDC
->textWidth(c_text
);
824 m_MGLDC
->underScoreLocation(x1
, y1
, c_text
);
825 switch (m_MGLDC
->getTextDirection())
827 case MGL_RIGHT_DIR
: x2
= x1
+ w
, y2
= y1
; break;
828 case MGL_LEFT_DIR
: x2
= x1
- w
, y2
= y1
; break;
829 case MGL_UP_DIR
: x2
= x1
, y2
= y1
- w
; break;
830 case MGL_DOWN_DIR
: x2
= x1
, y2
= y1
+ w
; break;
832 m_MGLDC
->line(x1
, y1
, x2
, y2
);
835 m_penSelected
= m_brushSelected
= FALSE
;
838 void wxDC::DoDrawRotatedText(const wxString
& text
,
839 wxCoord x
, wxCoord y
,
842 m_MGLDC
->makeCurrent(); // will go away with MGL6.0
846 DoDrawText(text
, x
, y
);
849 else if ( angle
== 90.0 )
850 m_MGLDC
->setTextDirection(MGL_UP_DIR
);
851 else if ( angle
== 180.0 )
852 m_MGLDC
->setTextDirection(MGL_LEFT_DIR
);
853 else if ( angle
== 270.0 )
854 m_MGLDC
->setTextDirection(MGL_DOWN_DIR
);
857 // FIXME_MGL -- implement once MGL supports it
858 wxFAIL_MSG(wxT("wxMGL only supports rotated text with angle 0,90,180 or 270"));
862 DrawAnyText(text
, x
, y
);
865 m_MGLDC
->setTextDirection(MGL_RIGHT_DIR
);
868 // ---------------------------------------------------------------------------
870 // ---------------------------------------------------------------------------
872 void wxDC::SelectMGLStipplePen(int style
)
878 case wxDOT
: stipple
= STIPPLE_wxDOT
; break;
879 case wxLONG_DASH
: stipple
= STIPPLE_wxLONG_DASH
; break;
880 case wxSHORT_DASH
: stipple
= STIPPLE_wxSHORT_DASH
; break;
881 case wxDOT_DASH
: stipple
= STIPPLE_wxDOT_DASH
; break;
882 default: stipple
= STIPPLE_wxSOLID
; break;
885 m_MGLDC
->setLineStyle(MGL_LINE_STIPPLE
);
886 m_MGLDC
->setLineStipple(stipple
);
887 m_MGLDC
->setPenSize(1, 1);
888 m_MGLDC
->setPenStyle(MGL_BITMAP_SOLID
);
889 m_penOfsY
= m_penOfsX
= 0;
892 // Accepted valus of SelectMGLFatPen's 2nd argument
894 wxMGL_SELECT_FROM_PEN
,
895 wxMGL_SELECT_FROM_BRUSH
898 void wxDC::SelectMGLFatPen(int style
, int flag
)
900 MGL_penStyleType penstyle
;
901 const pattern_t
*pattern
= NULL
;
902 pixpattern24_t
*pixPattern
= NULL
;
906 // Since MGL pens may be created from wxBrush or wxPen and we often
907 // switch between pens and brushes, we take advantage of MGL's ability
908 // to have multiple (pix)pattern_t's loaded. We always download pen
909 // to 0th slot and brush to 1st slot.
910 if ( flag
== wxMGL_SELECT_FROM_PEN
)
915 // compute pen's width:
916 if ( m_pen
.GetWidth() <= 1 )
919 m_penOfsX
= m_penOfsY
= 0;
923 wx
= (int)(0.5 + fabs((double) XLOG2DEVREL(m_pen
.GetWidth())));
924 wy
= (int)(0.5 + fabs((double) YLOG2DEVREL(m_pen
.GetWidth())));
930 penstyle
= MGL_BITMAP_TRANSPARENT
;
933 case wxBDIAGONAL_HATCH
: pattern
= &PATTERN_wxBDIAGONAL_HATCH
;
934 penstyle
= MGL_BITMAP_TRANSPARENT
;
936 case wxCROSSDIAG_HATCH
: pattern
= &PATTERN_wxCROSSDIAG_HATCH
;
937 penstyle
= MGL_BITMAP_TRANSPARENT
;
939 case wxFDIAGONAL_HATCH
: pattern
= &PATTERN_wxFDIAGONAL_HATCH
;
940 penstyle
= MGL_BITMAP_TRANSPARENT
;
942 case wxCROSS_HATCH
: pattern
= &PATTERN_wxCROSS_HATCH
;
943 penstyle
= MGL_BITMAP_TRANSPARENT
;
945 case wxHORIZONTAL_HATCH
: pattern
= &PATTERN_wxHORIZONTAL_HATCH
;
946 penstyle
= MGL_BITMAP_TRANSPARENT
;
948 case wxVERTICAL_HATCH
: pattern
= &PATTERN_wxVERTICAL_HATCH
;
949 penstyle
= MGL_BITMAP_TRANSPARENT
;
953 if ( flag
== wxMGL_SELECT_FROM_PEN
)
954 pixPattern
= (pixpattern24_t
*) m_pen
.GetPixPattern();
956 pixPattern
= (pixpattern24_t
*) m_brush
.GetPixPattern();
957 penstyle
= MGL_PIXMAP
;
960 case wxSTIPPLE_MASK_OPAQUE
:
961 pattern
= (pattern_t
*) m_brush
.GetMaskPattern();
962 penstyle
= MGL_BITMAP_OPAQUE
;
967 penstyle
= MGL_BITMAP_SOLID
; break;
970 // ...and finally, pass the pen to MGL:
974 if ( !m_downloadedPatterns
[slot
] )
976 m_MGLDC
->setPenBitmapPattern(slot
, pattern
);
977 m_downloadedPatterns
[slot
] = TRUE
;
979 m_MGLDC
->usePenBitmapPattern(slot
);
984 if ( !m_downloadedPatterns
[slot
] )
992 for (y
= 0; y
< 8; y
++)
993 for (x
= 0; x
< 8; x
++)
994 pix
.b8
.p
[x
][y
] = m_MGLDC
->packColorFast(
995 pixPattern
->p
[x
][y
][0],
996 pixPattern
->p
[x
][y
][1],
997 pixPattern
->p
[x
][y
][2]);
1001 for (y
= 0; y
< 8; y
++)
1002 for (x
= 0; x
< 8; x
++)
1003 pix
.b16
.p
[x
][y
] = m_MGLDC
->packColorFast(
1004 pixPattern
->p
[x
][y
][0],
1005 pixPattern
->p
[x
][y
][1],
1006 pixPattern
->p
[x
][y
][2]);
1009 for (y
= 0; y
< 8; y
++)
1010 for (x
= 0; x
< 8; x
++)
1011 for (c
= 0; c
< 3; c
++)
1012 pix
.b24
.p
[x
][y
][c
] = pixPattern
->p
[x
][y
][c
];
1015 for (y
= 0; y
< 8; y
++)
1016 for (x
= 0; x
< 8; x
++)
1017 pix
.b32
.p
[x
][y
] = m_MGLDC
->packColorFast(
1018 pixPattern
->p
[x
][y
][0],
1019 pixPattern
->p
[x
][y
][1],
1020 pixPattern
->p
[x
][y
][2]);
1023 wxFAIL_MSG(_T("invalid DC depth"));
1026 m_MGLDC
->setPenPixmapPattern(slot
, &pix
);
1027 m_downloadedPatterns
[slot
] = TRUE
;
1029 m_MGLDC
->usePenPixmapPattern(slot
);
1032 m_MGLDC
->setLineStyle(MGL_LINE_PENSTYLE
);
1033 m_MGLDC
->setPenStyle(penstyle
);
1034 m_MGLDC
->setPenSize(wy
, wx
);
1037 void wxDC::SelectPen()
1039 wxCHECK_RET( Ok(), wxT("invalid dc") );
1041 wxColour
& clr
= m_pen
.GetColour();
1042 m_MGLDC
->makeCurrent(); // will go away with MGL6.0
1043 m_MGLDC
->setColorRGB(clr
.Red(), clr
.Green(), clr
.Blue());
1045 switch (m_pen
.GetStyle())
1054 SelectMGLStipplePen(m_pen
.GetStyle());
1057 case wxBDIAGONAL_HATCH
:
1058 case wxCROSSDIAG_HATCH
:
1059 case wxFDIAGONAL_HATCH
:
1061 case wxHORIZONTAL_HATCH
:
1062 case wxVERTICAL_HATCH
:
1063 SelectMGLFatPen(m_pen
.GetStyle(), wxMGL_SELECT_FROM_PEN
);
1067 SelectMGLFatPen(m_pen
.GetStyle(), wxMGL_SELECT_FROM_PEN
);
1073 if ( m_pen
.GetWidth() <= 1 )
1074 SelectMGLStipplePen(wxSOLID
);
1076 SelectMGLFatPen(wxSOLID
, wxMGL_SELECT_FROM_PEN
);
1079 m_penSelected
= TRUE
;
1080 m_brushSelected
= FALSE
;
1083 void wxDC::SelectBrush()
1085 wxCHECK_RET( Ok(), wxT("invalid dc") );
1088 m_MGLDC
->makeCurrent(); // will go away with MGL6.0
1090 if ( m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
)
1092 fg
= m_textForegroundColour
;
1093 bg
= m_textBackgroundColour
;
1097 fg
= m_brush
.GetColour();
1098 bg
= m_backgroundBrush
.GetColour();
1101 m_MGLDC
->setColorRGB(fg
.Red(), fg
.Green(), fg
.Blue());
1102 m_MGLDC
->setBackColor(m_MGLDC
->packColorFast(bg
.Red(), bg
.Green(), bg
.Blue()));
1103 m_penSelected
= FALSE
;
1104 m_brushSelected
= TRUE
;
1106 SelectMGLFatPen(m_brush
.GetStyle(), wxMGL_SELECT_FROM_BRUSH
);
1109 void wxDC::SetPen(const wxPen
& pen
)
1111 if ( !pen
.Ok() ) return;
1112 if ( m_pen
== pen
) return;
1114 m_penSelected
= FALSE
;
1115 m_downloadedPatterns
[0] = FALSE
;
1118 void wxDC::SetBrush(const wxBrush
& brush
)
1120 if ( !brush
.Ok() ) return;
1121 if ( m_brush
== brush
) return;
1123 m_brushSelected
= FALSE
;
1124 m_downloadedPatterns
[1] = FALSE
;
1127 void wxDC::SetPalette(const wxPalette
& palette
)
1129 wxCHECK_RET( Ok(), wxT("invalid dc") );
1131 if ( palette
== wxNullPalette
)
1133 if ( m_oldPalette
.Ok() )
1134 SetPalette(m_oldPalette
);
1138 if ( !palette
.Ok() ) return;
1139 if ( m_palette
== palette
) return;
1140 m_oldPalette
= m_palette
;
1141 m_palette
= palette
;
1143 int cnt
= m_palette
.GetColoursCount();
1144 palette_t
*pal
= m_palette
.GetMGLpalette_t();
1145 m_MGLDC
->setPalette(pal
, cnt
, 0);
1146 m_MGLDC
->realizePalette(cnt
, 0, TRUE
);
1149 void wxDC::SetFont(const wxFont
& font
)
1158 void wxDC::SetBackground(const wxBrush
& brush
)
1160 wxCHECK_RET( Ok(), wxT("invalid dc") );
1162 if (!m_backgroundBrush
.Ok()) return;
1164 m_backgroundBrush
= brush
;
1165 wxColour
&clr
= m_backgroundBrush
.GetColour();
1166 m_MGLDC
->makeCurrent(); // will go away with MGL6.0
1167 m_MGLDC
->setBackColor(
1168 m_MGLDC
->packColorFast(clr
.Red(), clr
.Green(), clr
.Blue()));
1171 void wxDC::SetBackgroundMode(int mode
)
1173 m_backgroundMode
= mode
;
1174 if ( mode
== wxSOLID
)
1175 m_MGLDC
->setBackMode(MGL_OPAQUE_BACKGROUND
);
1177 m_MGLDC
->setBackMode(MGL_TRANSPARENT_BACKGROUND
);
1180 void wxDC::SetLogicalFunction(int function
)
1182 wxCHECK_RET( Ok(), wxT("invalid dc") );
1184 m_logicalFunction
= function
;
1186 m_MGLDC
->makeCurrent(); // will go away with MGL6.0
1187 m_MGLDC
->setWriteMode(LogicalFunctionToMGLRop(m_logicalFunction
));
1190 int wxDC::LogicalFunctionToMGLRop(int logFunc
) const
1192 MGL_writeModeType rop
;
1196 case wxCLEAR
: rop
= MGL_R2_BLACK
; break;
1197 case wxXOR
: rop
= MGL_R2_XORSRC
; break;
1198 case wxINVERT
: rop
= MGL_R2_NOT
; break;
1199 case wxOR_REVERSE
: rop
= MGL_R2_MERGESRCNOT
; break;
1200 case wxAND_REVERSE
: rop
= MGL_R2_MASKSRCNOT
; break;
1201 case wxCOPY
: rop
= MGL_R2_COPYSRC
; break;
1202 case wxAND
: rop
= MGL_R2_MASKSRC
; break;
1203 case wxAND_INVERT
: rop
= MGL_R2_MASKNOTSRC
; break;
1204 case wxNO_OP
: rop
= MGL_R2_NOP
; break;
1205 case wxNOR
: rop
= MGL_R2_NOTMERGESRC
; break;
1206 case wxEQUIV
: rop
= MGL_R2_NOTXORSRC
; break;
1207 case wxSRC_INVERT
: rop
= MGL_R2_NOTCOPYSRC
; break;
1208 case wxOR_INVERT
: rop
= MGL_R2_MERGENOTSRC
; break;
1209 case wxNAND
: rop
= MGL_R2_NOTMASKSRC
; break;
1210 case wxOR
: rop
= MGL_R2_MERGESRC
; break;
1211 case wxSET
: rop
= MGL_R2_WHITE
; break;
1213 wxFAIL_MSG( wxT("unsupported logical function") );
1214 return MGL_REPLACE_MODE
;
1219 bool wxDC::StartDoc(const wxString
& message
)
1221 // We might be previewing, so return TRUE to let it continue.
1229 void wxDC::StartPage()
1233 void wxDC::EndPage()
1237 // ---------------------------------------------------------------------------
1239 // ---------------------------------------------------------------------------
1241 wxCoord
wxDC::GetCharHeight() const
1243 wxCurrentDCSwitcher
switcher(m_MGLDC
);
1244 if ( !wxConstCast(this, wxDC
)->SelectMGLFont() ) return -1;
1245 return YDEV2LOGREL(m_mglFont
->fontHeight
);
1248 wxCoord
wxDC::GetCharWidth() const
1250 wxCurrentDCSwitcher
switcher(m_MGLDC
);
1251 if ( !wxConstCast(this, wxDC
)->SelectMGLFont() ) return -1;
1252 // VS: wxT() is intentional, charWidth() has both char and wchar_t version
1253 // VS: YDEV is corrent, it should *not* be XDEV, because font's are only
1254 // scaled according to m_scaleY
1255 return YDEV2LOGREL(m_mglFont
->fontWidth
);
1258 void wxDC::DoGetTextExtent(const wxString
& string
, wxCoord
*x
, wxCoord
*y
,
1259 wxCoord
*descent
, wxCoord
*externalLeading
,
1260 wxFont
*theFont
) const
1264 if ( theFont
!= NULL
)
1267 wxConstCast(this, wxDC
)->SetFont(*theFont
);
1270 wxCurrentDCSwitcher
switcher(m_MGLDC
);
1271 if ( !wxConstCast(this, wxDC
)->SelectMGLFont() ) return;
1274 // VS: YDEV is corrent, it should *not* be XDEV, because font's are
1275 // only scaled according to m_scaleY
1276 *x
= YDEV2LOGREL(m_MGLDC
->textWidth(string
.c_str()));
1278 *y
= YDEV2LOGREL(m_MGLDC
->textHeight());
1280 *descent
= YDEV2LOGREL(m_mglFont
->descent
);
1281 if ( externalLeading
)
1282 *externalLeading
= YDEV2LOGREL(m_mglFont
->leading
);
1284 if ( theFont
!= NULL
)
1285 wxConstCast(this, wxDC
)->SetFont(oldFont
);
1290 // ---------------------------------------------------------------------------
1292 // ---------------------------------------------------------------------------
1294 void wxDC::ComputeScaleAndOrigin()
1296 double newX
= m_logicalScaleX
* m_userScaleX
;
1297 double newY
= m_logicalScaleY
* m_userScaleY
;
1299 // make sure font will be reloaded before drawing:
1300 if ( newY
!= m_scaleY
)
1302 // make sure m_penOfs{X,Y} will be reevaluated before drawing:
1303 if ( newY
!= m_scaleY
|| newX
!= m_scaleX
)
1304 m_penSelected
= FALSE
;
1306 m_scaleX
= newX
, m_scaleY
= newY
;
1309 void wxDC::SetMapMode(int mode
)
1314 SetLogicalScale(twips2mm
*m_mm_to_pix_x
, twips2mm
*m_mm_to_pix_y
);
1317 SetLogicalScale(pt2mm
*m_mm_to_pix_x
, pt2mm
*m_mm_to_pix_y
);
1320 SetLogicalScale(m_mm_to_pix_x
, m_mm_to_pix_y
);
1323 SetLogicalScale(m_mm_to_pix_x
/10.0, m_mm_to_pix_y
/10.0);
1327 SetLogicalScale(1.0, 1.0);
1330 m_mappingMode
= mode
;
1333 void wxDC::SetUserScale( double x
, double y
)
1335 // allow negative ? -> no
1338 ComputeScaleAndOrigin();
1341 void wxDC::SetLogicalScale( double x
, double y
)
1344 m_logicalScaleX
= x
;
1345 m_logicalScaleY
= y
;
1346 ComputeScaleAndOrigin();
1349 void wxDC::SetLogicalOrigin( wxCoord x
, wxCoord y
)
1351 m_logicalOriginX
= x
* m_signX
; // is this still correct ?
1352 m_logicalOriginY
= y
* m_signY
;
1353 ComputeScaleAndOrigin();
1356 void wxDC::SetDeviceOrigin( wxCoord x
, wxCoord y
)
1358 // only wxPostScripDC has m_signX = -1, we override SetDeviceOrigin there
1359 m_deviceOriginX
= x
;
1360 m_deviceOriginY
= y
;
1361 ComputeScaleAndOrigin();
1364 void wxDC::SetAxisOrientation( bool xLeftRight
, bool yBottomUp
)
1366 // only wxPostScripDC has m_signX = -1, we override SetAxisOrientation there
1367 m_signX
= (xLeftRight
? 1 : -1);
1368 m_signY
= (yBottomUp
? -1 : 1);
1369 ComputeScaleAndOrigin();
1372 // ---------------------------------------------------------------------------
1373 // coordinates transformations
1374 // ---------------------------------------------------------------------------
1376 wxCoord
wxDCBase::DeviceToLogicalX(wxCoord x
) const
1378 return ((wxDC
*)this)->XDEV2LOG(x
);
1381 wxCoord
wxDCBase::DeviceToLogicalY(wxCoord y
) const
1383 return ((wxDC
*)this)->YDEV2LOG(y
);
1386 wxCoord
wxDCBase::DeviceToLogicalXRel(wxCoord x
) const
1388 return ((wxDC
*)this)->XDEV2LOGREL(x
);
1391 wxCoord
wxDCBase::DeviceToLogicalYRel(wxCoord y
) const
1393 return ((wxDC
*)this)->YDEV2LOGREL(y
);
1396 wxCoord
wxDCBase::LogicalToDeviceX(wxCoord x
) const
1398 return ((wxDC
*)this)->XLOG2DEV(x
);
1401 wxCoord
wxDCBase::LogicalToDeviceY(wxCoord y
) const
1403 return ((wxDC
*)this)->YLOG2DEV(y
);
1406 wxCoord
wxDCBase::LogicalToDeviceXRel(wxCoord x
) const
1408 return ((wxDC
*)this)->XLOG2DEVREL(x
);
1411 wxCoord
wxDCBase::LogicalToDeviceYRel(wxCoord y
) const
1413 return ((wxDC
*)this)->YLOG2DEVREL(y
);
1417 void wxDC::DoGetSize(int *w
, int *h
) const
1419 if (w
) *w
= m_MGLDC
->sizex()+1;
1420 if (h
) *h
= m_MGLDC
->sizey()+1;
1423 void wxDC::DoGetSizeMM(int *width
, int *height
) const
1428 if ( width
) *width
= int(double(w
) / (m_userScaleX
*m_mm_to_pix_x
));
1429 if ( height
) *height
= int(double(h
) / (m_userScaleY
*m_mm_to_pix_y
));
1432 wxSize
wxDC::GetPPI() const
1434 return wxSize(int(double(m_mm_to_pix_x
) * inches2mm
),
1435 int(double(m_mm_to_pix_y
) * inches2mm
));
1439 // ---------------------------------------------------------------------------
1441 // ---------------------------------------------------------------------------
1443 bool wxDC::DoBlit(wxCoord xdest
, wxCoord ydest
,
1444 wxCoord width
, wxCoord height
,
1445 wxDC
*source
, wxCoord xsrc
, wxCoord ysrc
,
1446 int rop
, bool useMask
,
1447 wxCoord xsrcMask
, wxCoord ysrcMask
)
1449 wxCHECK_MSG( Ok(), FALSE
, wxT("invalid dc") );
1450 wxCHECK_MSG( source
, FALSE
, wxT("invalid source dc") );
1452 // transform the source DC coords to the device ones
1453 xsrc
= source
->LogicalToDeviceX(xsrc
);
1454 ysrc
= source
->LogicalToDeviceY(ysrc
);
1456 /* FIXME_MGL: use the mask origin when drawing transparently */
1457 if (xsrcMask
== -1 && ysrcMask
== -1)
1459 xsrcMask
= xsrc
; ysrcMask
= ysrc
;
1463 xsrcMask
= source
->LogicalToDeviceX(xsrcMask
);
1464 ysrcMask
= source
->LogicalToDeviceY(ysrcMask
);
1467 CalcBoundingBox(xdest
, ydest
);
1468 CalcBoundingBox(xdest
+ width
, ydest
+ height
);
1470 /* scale/translate size and position */
1471 wxCoord xx
= XLOG2DEV(xdest
);
1472 wxCoord yy
= YLOG2DEV(ydest
);
1473 wxCoord ww
= XLOG2DEVREL(width
);
1474 wxCoord hh
= YLOG2DEVREL(height
);
1476 if ( source
->m_isMemDC
)
1478 wxMemoryDC
*memDC
= (wxMemoryDC
*) source
;
1479 DoDrawSubBitmap(memDC
->GetSelectedObject(), xsrc
, ysrc
, ww
, hh
,
1480 xdest
, ydest
, rop
, useMask
);
1484 m_MGLDC
->makeCurrent(); // will go away with MGL6.0
1485 m_MGLDC
->bitBlt(*source
->GetMGLDC(),
1486 xsrc
, ysrc
, xsrc
+ ww
, ysrc
+ hh
,
1487 xx
, yy
, LogicalFunctionToMGLRop(rop
));
1493 void wxDC::DoDrawBitmap(const wxBitmap
&bmp
, wxCoord x
, wxCoord y
, bool useMask
)
1495 wxCHECK_RET( Ok(), wxT("invalid dc") );
1496 wxCHECK_RET( bmp
.Ok(), wxT("invalid bitmap") );
1498 wxCoord w
= bmp
.GetWidth();
1499 wxCoord h
= bmp
.GetHeight();
1501 DoDrawSubBitmap(bmp
, 0, 0, w
, h
, x
, y
, m_logicalFunction
, useMask
);
1504 void wxDC::DoDrawIcon(const wxIcon
& icon
, wxCoord x
, wxCoord y
)
1506 // VZ: egcs 1.0.3 refuses to compile this without cast, no idea why
1507 DoDrawBitmap((const wxBitmap
&)icon
, x
, y
, (bool)TRUE
);
1511 static inline void DoBitBlt(const wxBitmap
& src
, MGLDevCtx
*dst
,
1512 int sx
, int sy
, int sw
, int sh
,
1513 int dx
, int dy
, int dw
, int dh
,
1514 int rop
, bool useStretching
, bool putSection
)
1516 bitmap_t
*bmp
= src
.GetMGLbitmap_t();
1520 dst
->putBitmap(dx
, dy
, bmp
, rop
);
1522 dst
->putBitmapSection(sx
, sy
, sx
+ sw
, sy
+ sh
, dx
, dy
, bmp
, rop
);
1527 dst
->stretchBitmap(dx
, dy
, dx
+ dw
, dy
+ dh
, bmp
, rop
);
1529 dst
->stretchBitmapSection(sx
, sy
, sx
+ sw
, sy
+ sh
,
1530 dx
, dy
, dx
+ dw
, dy
+ dh
, bmp
, rop
);
1534 void wxDC::DoDrawSubBitmap(const wxBitmap
&bmp
,
1535 wxCoord x
, wxCoord y
, wxCoord w
, wxCoord h
,
1536 wxCoord destx
, wxCoord desty
, int rop
, bool useMask
)
1538 wxCHECK_RET( Ok(), wxT("invalid dc") );
1539 wxCHECK_RET( bmp
.Ok(), wxT("invalid bitmap") );
1541 CalcBoundingBox(x
, y
);
1542 CalcBoundingBox(x
+ w
, y
+ h
);
1544 wxCoord dx
= XLOG2DEV(destx
);
1545 wxCoord dy
= YLOG2DEV(desty
);
1546 wxCoord dw
= XLOG2DEVREL(w
);
1547 wxCoord dh
= YLOG2DEVREL(h
);
1549 m_MGLDC
->makeCurrent(); // will go away with MGL6.0
1551 bool useStretching
= ((w
!= dw
) || (h
!= dh
));
1552 bool putSection
= (w
!= bmp
.GetWidth() || h
!= bmp
.GetHeight());
1553 MGL_writeModeType mglRop
= (MGL_writeModeType
)LogicalFunctionToMGLRop(rop
);
1555 if ( bmp
.GetDepth() == 1 )
1557 // Mono bitmaps are handled in special way -- all 1s are drawn in
1558 // foreground colours, all 0s in background colour.
1560 ((wxBitmap
&)bmp
).SetMonoPalette(m_textForegroundColour
, m_textBackgroundColour
);
1563 if ( useMask
&& bmp
.GetMask() )
1565 // Since MGL does not support masks directly (in MGL, mask is handled
1566 // in same way as in wxImage, i.e. there is one "key" color), we
1567 // simulate masked bitblt in 6 steps (same as in MSW):
1569 // 1. Create a temporary bitmap and copy the destination area into it.
1570 // 2. Copy the source area into the temporary bitmap using the
1571 // specified logical function.
1572 // 3. Set the masked area in the temporary bitmap to BLACK by ANDing
1573 // the mask bitmap with the temp bitmap with the foreground colour
1574 // set to WHITE and the bg colour set to BLACK.
1575 // 4. Set the unmasked area in the destination area to BLACK by
1576 // ANDing the mask bitmap with the destination area with the
1577 // foreground colour set to BLACK and the background colour set
1579 // 5. OR the temporary bitmap with the destination area.
1580 // 6. Delete the temporary bitmap.
1582 // This sequence of operations ensures that the source's transparent
1583 // area need not be black, and logical functions are supported.
1585 wxBitmap
*mask
= bmp
.GetMask()->GetBitmap();
1589 if ( GetDepth() <= 8 )
1591 temp
= new MGLMemoryDC(dw
, dh
, GetDepth(), NULL
);
1593 tempdc
.SetMGLDC(temp
, FALSE
);
1594 tempdc
.SetPalette(m_palette
);
1599 m_MGLDC
->getPixelFormat(pf
);
1600 temp
= new MGLMemoryDC(dw
, dh
, GetDepth(), &pf
);
1603 wxCHECK_RET( temp
->isValid(), wxT("cannot create temporary dc") );
1605 temp
->bitBlt(*m_MGLDC
, dx
, dy
, dx
+ dw
, dy
+ dh
, 0, 0, MGL_REPLACE_MODE
);
1607 DoBitBlt(bmp
, temp
, x
, y
, w
, h
, 0, 0, dw
, dh
, mglRop
,
1608 useStretching
, putSection
);
1610 mask
->SetMonoPalette(wxColour(0,0,0), wxColour(255,255,255));
1611 DoBitBlt(*mask
, temp
, x
, y
, w
, h
, 0, 0, dw
, dh
, MGL_R2_MASKSRC
,
1612 useStretching
, putSection
);
1613 DoBitBlt(*mask
, m_MGLDC
, x
, y
, w
, h
, dx
, dy
, dw
, dh
, MGL_R2_MASKNOTSRC
,
1614 useStretching
, putSection
);
1616 m_MGLDC
->bitBlt(*temp
, 0, 0, dw
, dh
, dx
, dy
, MGL_OR_MODE
);
1623 DoBitBlt(bmp
, m_MGLDC
, x
, y
, w
, h
, dx
, dy
, dw
, dh
, mglRop
,
1624 useStretching
, putSection
);