1 /////////////////////////////////////////////////////////////////////////////
8 // Copyright: (c) AUTHOR
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation "dc.h"
18 #include "wx/mac/uma.h"
19 #include "wx/dcmemory.h"
20 #include "wx/region.h"
29 #include "wx/mac/private.h"
30 #include "ATSUnicode.h"
31 #include "TextCommon.h"
32 #include "TextEncodingConverter.h"
34 #if !USE_SHARED_LIBRARY
35 IMPLEMENT_ABSTRACT_CLASS(wxDC
, wxObject
)
38 //-----------------------------------------------------------------------------
40 //-----------------------------------------------------------------------------
42 #define mm2inches 0.0393700787402
43 #define inches2mm 25.4
44 #define mm2twips 56.6929133859
45 #define twips2mm 0.0176388888889
46 #define mm2pt 2.83464566929
47 #define pt2mm 0.352777777778
49 const double M_PI
= 3.14159265358979 ;
51 const double RAD2DEG
= 180.0 / M_PI
;
52 const short kEmulatedMode
= -1 ;
53 const short kUnsupportedMode
= -2 ;
55 wxMacPortSetter::wxMacPortSetter( const wxDC
* dc
) :
56 m_ph( (GrafPtr
) dc
->m_macPort
)
58 wxASSERT( dc
->Ok() ) ;
60 dc
->MacSetupPort(&m_ph
) ;
63 wxMacPortSetter::~wxMacPortSetter()
65 m_dc
->MacCleanupPort(&m_ph
) ;
68 //-----------------------------------------------------------------------------
70 //-----------------------------------------------------------------------------
72 static inline double dmin(double a
, double b
) { return a
< b
? a
: b
; }
73 static inline double dmax(double a
, double b
) { return a
> b
? a
: b
; }
74 static inline double DegToRad(double deg
) { return (deg
* M_PI
) / 180.0; }
76 //-----------------------------------------------------------------------------
78 //-----------------------------------------------------------------------------
80 // this function emulates all wx colour manipulations, used to verify the implementation
81 // by setting the mode in the blitting functions to kEmulatedMode
83 void wxMacCalculateColour( int logical_func
, const RGBColor
&srcColor
, RGBColor
&dstColor
) ;
84 void wxMacCalculateColour( int logical_func
, const RGBColor
&srcColor
, RGBColor
&dstColor
)
86 switch ( logical_func
)
88 case wxAND
: // src AND dst
89 dstColor
.red
= dstColor
.red
& srcColor
.red
;
90 dstColor
.green
= dstColor
.green
& srcColor
.green
;
91 dstColor
.blue
= dstColor
.blue
& srcColor
.blue
;
93 case wxAND_INVERT
: // (NOT src) AND dst
94 dstColor
.red
= dstColor
.red
& ~srcColor
.red
;
95 dstColor
.green
= dstColor
.green
& ~srcColor
.green
;
96 dstColor
.blue
= dstColor
.blue
& ~srcColor
.blue
;
98 case wxAND_REVERSE
:// src AND (NOT dst)
99 dstColor
.red
= ~dstColor
.red
& srcColor
.red
;
100 dstColor
.green
= ~dstColor
.green
& srcColor
.green
;
101 dstColor
.blue
= ~dstColor
.blue
& srcColor
.blue
;
109 dstColor
.red
= srcColor
.red
;
110 dstColor
.green
= srcColor
.green
;
111 dstColor
.blue
= srcColor
.blue
;
113 case wxEQUIV
: // (NOT src) XOR dst
114 dstColor
.red
= dstColor
.red
^ ~srcColor
.red
;
115 dstColor
.green
= dstColor
.green
^ ~srcColor
.green
;
116 dstColor
.blue
= dstColor
.blue
^ ~srcColor
.blue
;
118 case wxINVERT
: // NOT dst
119 dstColor
.red
= ~dstColor
.red
;
120 dstColor
.green
= ~dstColor
.green
;
121 dstColor
.blue
= ~dstColor
.blue
;
123 case wxNAND
: // (NOT src) OR (NOT dst)
124 dstColor
.red
= ~dstColor
.red
| ~srcColor
.red
;
125 dstColor
.green
= ~dstColor
.green
| ~srcColor
.green
;
126 dstColor
.blue
= ~dstColor
.blue
| ~srcColor
.blue
;
128 case wxNOR
: // (NOT src) AND (NOT dst)
129 dstColor
.red
= ~dstColor
.red
& ~srcColor
.red
;
130 dstColor
.green
= ~dstColor
.green
& ~srcColor
.green
;
131 dstColor
.blue
= ~dstColor
.blue
& ~srcColor
.blue
;
135 case wxOR
: // src OR dst
136 dstColor
.red
= dstColor
.red
| srcColor
.red
;
137 dstColor
.green
= dstColor
.green
| srcColor
.green
;
138 dstColor
.blue
= dstColor
.blue
| srcColor
.blue
;
140 case wxOR_INVERT
: // (NOT src) OR dst
141 dstColor
.red
= dstColor
.red
| ~srcColor
.red
;
142 dstColor
.green
= dstColor
.green
| ~srcColor
.green
;
143 dstColor
.blue
= dstColor
.blue
| ~srcColor
.blue
;
145 case wxOR_REVERSE
: // src OR (NOT dst)
146 dstColor
.red
= ~dstColor
.red
| srcColor
.red
;
147 dstColor
.green
= ~dstColor
.green
| srcColor
.green
;
148 dstColor
.blue
= ~dstColor
.blue
| srcColor
.blue
;
151 dstColor
.red
= 0xFFFF ;
152 dstColor
.green
= 0xFFFF ;
153 dstColor
.blue
= 0xFFFF ;
155 case wxSRC_INVERT
: // (NOT src)
156 dstColor
.red
= ~srcColor
.red
;
157 dstColor
.green
= ~srcColor
.green
;
158 dstColor
.blue
= ~srcColor
.blue
;
160 case wxXOR
: // src XOR dst
161 dstColor
.red
= dstColor
.red
^ srcColor
.red
;
162 dstColor
.green
= dstColor
.green
^ srcColor
.green
;
163 dstColor
.blue
= dstColor
.blue
^ srcColor
.blue
;
174 m_mm_to_pix_x
= mm2pt
;
175 m_mm_to_pix_y
= mm2pt
;
177 m_internalDeviceOriginX
= 0;
178 m_internalDeviceOriginY
= 0;
179 m_externalDeviceOriginX
= 0;
180 m_externalDeviceOriginY
= 0;
182 m_logicalScaleX
= 1.0;
183 m_logicalScaleY
= 1.0;
189 m_needComputeScaleX
= FALSE
;
190 m_needComputeScaleY
= FALSE
;
196 m_macFontInstalled
= false ;
197 m_macBrushInstalled
= false ;
198 m_macPenInstalled
= false ;
200 m_macLocalOrigin
.x
= m_macLocalOrigin
.y
= 0 ;
201 m_macBoundaryClipRgn
= NewRgn() ;
202 m_macCurrentClipRgn
= NewRgn() ;
204 SetRectRgn( (RgnHandle
) m_macBoundaryClipRgn
, -32000 , -32000 , 32000 , 32000 ) ;
205 SetRectRgn( (RgnHandle
) m_macCurrentClipRgn
, -32000 , -32000 , 32000 , 32000 ) ;
207 m_pen
= *wxBLACK_PEN
;
208 m_font
= *wxNORMAL_FONT
;
209 m_brush
= *wxWHITE_BRUSH
;
210 m_macCurrentPortStateHelper
= NULL
;
211 m_macATSUIStyle
= NULL
;
212 m_macAliasWasEnabled
= false;
213 m_macForegroundPixMap
= NULL
;
214 m_macBackgroundPixMap
= NULL
;
219 DisposeRgn( (RgnHandle
) m_macBoundaryClipRgn
) ;
220 DisposeRgn( (RgnHandle
) m_macCurrentClipRgn
) ;
222 void wxDC::MacSetupPort(wxMacPortStateHelper
* help
) const
224 wxASSERT( m_macCurrentPortStateHelper
== NULL
) ;
225 m_macCurrentPortStateHelper
= help
;
226 SetClip( (RgnHandle
) m_macCurrentClipRgn
);
228 m_macFontInstalled
= false ;
229 m_macBrushInstalled
= false ;
230 m_macPenInstalled
= false ;
233 void wxDC::MacCleanupPort(wxMacPortStateHelper
* help
) const
235 wxASSERT( m_macCurrentPortStateHelper
== help
) ;
236 m_macCurrentPortStateHelper
= NULL
;
237 if( m_macATSUIStyle
)
239 ::ATSUDisposeStyle((ATSUStyle
)m_macATSUIStyle
);
240 m_macATSUIStyle
= NULL
;
242 if ( m_macAliasWasEnabled
)
244 SetAntiAliasedTextEnabled(m_macFormerAliasState
, m_macFormerAliasSize
);
245 m_macAliasWasEnabled
= false ;
247 if ( m_macForegroundPixMap
)
250 ::PenPat(GetQDGlobalsBlack(&blackColor
));
251 DisposePixPat( (PixPatHandle
) m_macForegroundPixMap
) ;
252 m_macForegroundPixMap
= NULL
;
254 if ( m_macBackgroundPixMap
)
257 ::BackPat(GetQDGlobalsWhite(&whiteColor
));
258 DisposePixPat( (PixPatHandle
) m_macBackgroundPixMap
) ;
259 m_macBackgroundPixMap
= NULL
;
263 void wxDC::DoDrawBitmap( const wxBitmap
&bmp
, wxCoord x
, wxCoord y
, bool useMask
)
265 wxCHECK_RET( Ok(), wxT("invalid window dc") );
267 wxCHECK_RET( bmp
.Ok(), wxT("invalid bitmap") );
269 wxMacPortSetter
helper(this) ;
271 wxCoord xx
= XLOG2DEVMAC(x
);
272 wxCoord yy
= YLOG2DEVMAC(y
);
273 wxCoord w
= bmp
.GetWidth();
274 wxCoord h
= bmp
.GetHeight();
275 wxCoord ww
= XLOG2DEVREL(w
);
276 wxCoord hh
= YLOG2DEVREL(h
);
278 // Set up drawing mode
279 short mode
= (m_logicalFunction
== wxCOPY
? srcCopy
:
280 //m_logicalFunction == wxCLEAR ? WHITENESS :
281 //m_logicalFunction == wxSET ? BLACKNESS :
282 m_logicalFunction
== wxINVERT
? hilite
:
283 //m_logicalFunction == wxAND ? MERGECOPY :
284 m_logicalFunction
== wxOR
? srcOr
:
285 m_logicalFunction
== wxSRC_INVERT
? notSrcCopy
:
286 m_logicalFunction
== wxXOR
? srcXor
:
287 m_logicalFunction
== wxOR_REVERSE
? notSrcOr
:
288 //m_logicalFunction == wxAND_REVERSE ? SRCERASE :
289 //m_logicalFunction == wxSRC_OR ? srcOr :
290 //m_logicalFunction == wxSRC_AND ? SRCAND :
293 if ( bmp
.GetBitmapType() == kMacBitmapTypePict
) {
294 Rect bitmaprect
= { 0 , 0 , hh
, ww
};
295 ::OffsetRect( &bitmaprect
, xx
, yy
) ;
296 ::DrawPicture( (PicHandle
) bmp
.GetPict(), &bitmaprect
) ;
298 else if ( bmp
.GetBitmapType() == kMacBitmapTypeGrafWorld
)
300 GWorldPtr bmapworld
= MAC_WXHBITMAP( bmp
.GetHBITMAP() );
301 PixMapHandle bmappixels
;
303 // Set foreground and background colours (for bitmaps depth = 1)
304 if(bmp
.GetDepth() == 1)
306 RGBColor fore
= MAC_WXCOLORREF(m_textForegroundColour
.GetPixel());
307 RGBColor back
= MAC_WXCOLORREF(m_textBackgroundColour
.GetPixel());
313 RGBColor white
= { 0xFFFF, 0xFFFF,0xFFFF} ;
314 RGBColor black
= { 0,0,0} ;
315 RGBForeColor( &black
) ;
316 RGBBackColor( &white
) ;
319 bmappixels
= GetGWorldPixMap( bmapworld
) ;
321 wxCHECK_RET(LockPixels(bmappixels
),
322 wxT("DoDrawBitmap: Unable to lock pixels"));
324 Rect source
= { 0, 0, h
, w
};
325 Rect dest
= { yy
, xx
, yy
+ hh
, xx
+ ww
};
327 if ( useMask
&& bmp
.GetMask() )
329 if( LockPixels(GetGWorldPixMap(MAC_WXHBITMAP(bmp
.GetMask()->GetMaskBitmap()))))
333 GetPortBitMapForCopyBits(bmapworld
),
334 GetPortBitMapForCopyBits(MAC_WXHBITMAP(bmp
.GetMask()->GetMaskBitmap())),
335 GetPortBitMapForCopyBits( MAC_WXHBITMAP(m_macPort
) ),
336 &source
, &source
, &dest
, mode
, NULL
338 UnlockPixels(GetGWorldPixMap(MAC_WXHBITMAP(bmp
.GetMask()->GetMaskBitmap())));
342 CopyBits( GetPortBitMapForCopyBits( bmapworld
),
343 GetPortBitMapForCopyBits( MAC_WXHBITMAP(m_macPort
) ),
344 &source
, &dest
, mode
, NULL
) ;
346 UnlockPixels( bmappixels
) ;
348 else if ( bmp
.GetBitmapType() == kMacBitmapTypeIcon
)
350 Rect bitmaprect
= { 0 , 0 , bmp
.GetHeight(), bmp
.GetWidth() } ;
351 OffsetRect( &bitmaprect
, xx
, yy
) ;
352 PlotCIconHandle( &bitmaprect
, atNone
, ttNone
, MAC_WXHICON(bmp
.GetHICON()) ) ;
354 m_macPenInstalled
= false ;
355 m_macBrushInstalled
= false ;
356 m_macFontInstalled
= false ;
360 void wxDC::DoDrawIcon( const wxIcon
&icon
, wxCoord x
, wxCoord y
)
362 wxCHECK_RET(Ok(), wxT("Invalid dc wxDC::DoDrawIcon"));
364 wxCHECK_RET(icon
.Ok(), wxT("Invalid icon wxDC::DoDrawIcon"));
366 DoDrawBitmap( icon
, x
, y
, icon
.GetMask() != NULL
) ;
368 void wxDC::DoSetClippingRegion( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
370 wxCHECK_RET(Ok(), wxT("wxDC::DoSetClippingRegion Invalid DC"));
371 wxCoord xx
, yy
, ww
, hh
;
375 ww
= XLOG2DEVREL(width
);
376 hh
= YLOG2DEVREL(height
);
378 SetRectRgn( (RgnHandle
) m_macCurrentClipRgn
, xx
, yy
, xx
+ ww
, yy
+ hh
) ;
379 SectRgn( (RgnHandle
) m_macCurrentClipRgn
, (RgnHandle
) m_macBoundaryClipRgn
, (RgnHandle
) m_macCurrentClipRgn
) ;
383 m_clipX1
= wxMax( m_clipX1
, xx
);
384 m_clipY1
= wxMax( m_clipY1
, yy
);
385 m_clipX2
= wxMin( m_clipX2
, (xx
+ ww
));
386 m_clipY2
= wxMin( m_clipY2
, (yy
+ hh
));
398 void wxDC::DoSetClippingRegionAsRegion( const wxRegion
®ion
)
400 wxCHECK_RET( Ok(), wxT("invalid window dc") ) ;
402 wxMacPortSetter
helper(this) ;
405 DestroyClippingRegion();
410 region
.GetBox( x
, y
, w
, h
);
411 wxCoord xx
, yy
, ww
, hh
;
418 // if we have a scaling that we cannot map onto native regions
419 // we must use the box
421 if ( ww
!= w
|| hh
!= h
)
423 wxDC::DoSetClippingRegion( x
, y
, w
, h
);
427 CopyRgn( (RgnHandle
) region
.GetWXHRGN() , (RgnHandle
) m_macCurrentClipRgn
) ;
428 if ( xx
!= x
|| yy
!= y
)
430 OffsetRgn( (RgnHandle
) m_macCurrentClipRgn
, xx
- x
, yy
- y
) ;
432 SectRgn( (RgnHandle
) m_macCurrentClipRgn
, (RgnHandle
) m_macBoundaryClipRgn
, (RgnHandle
) m_macCurrentClipRgn
) ;
435 m_clipX1
= wxMax( m_clipX1
, xx
);
436 m_clipY1
= wxMax( m_clipY1
, yy
);
437 m_clipX2
= wxMin( m_clipX2
, (xx
+ ww
));
438 m_clipY2
= wxMin( m_clipY2
, (yy
+ hh
));
452 void wxDC::DestroyClippingRegion()
454 wxMacPortSetter
helper(this) ;
455 CopyRgn( (RgnHandle
) m_macBoundaryClipRgn
, (RgnHandle
) m_macCurrentClipRgn
) ;
458 void wxDC::DoGetSize( int* width
, int* height
) const
460 *width
= m_maxX
-m_minX
;
461 *height
= m_maxY
-m_minY
;
463 void wxDC::DoGetSizeMM( int* width
, int* height
) const
468 *width
= long( double(w
) / (m_scaleX
*m_mm_to_pix_x
) );
469 *height
= long( double(h
) / (m_scaleY
*m_mm_to_pix_y
) );
471 void wxDC::SetTextForeground( const wxColour
&col
)
473 wxCHECK_RET(Ok(), wxT("Invalid DC"));
474 m_textForegroundColour
= col
;
475 m_macFontInstalled
= false ;
477 void wxDC::SetTextBackground( const wxColour
&col
)
479 wxCHECK_RET(Ok(), wxT("Invalid DC"));
480 m_textBackgroundColour
= col
;
481 m_macFontInstalled
= false ;
483 void wxDC::SetMapMode( int mode
)
488 SetLogicalScale( twips2mm
*m_mm_to_pix_x
, twips2mm
*m_mm_to_pix_y
);
491 SetLogicalScale( pt2mm
*m_mm_to_pix_x
, pt2mm
*m_mm_to_pix_y
);
494 SetLogicalScale( m_mm_to_pix_x
, m_mm_to_pix_y
);
497 SetLogicalScale( m_mm_to_pix_x
/10.0, m_mm_to_pix_y
/10.0 );
501 SetLogicalScale( 1.0, 1.0 );
504 if (mode
!= wxMM_TEXT
)
506 m_needComputeScaleX
= TRUE
;
507 m_needComputeScaleY
= TRUE
;
510 void wxDC::SetUserScale( double x
, double y
)
512 // allow negative ? -> no
515 ComputeScaleAndOrigin();
517 void wxDC::SetLogicalScale( double x
, double y
)
522 ComputeScaleAndOrigin();
524 void wxDC::SetLogicalOrigin( wxCoord x
, wxCoord y
)
526 m_logicalOriginX
= x
* m_signX
; // is this still correct ?
527 m_logicalOriginY
= y
* m_signY
;
528 ComputeScaleAndOrigin();
530 void wxDC::SetDeviceOrigin( wxCoord x
, wxCoord y
)
532 m_externalDeviceOriginX
= x
;
533 m_externalDeviceOriginY
= y
;
534 ComputeScaleAndOrigin();
538 void wxDC::SetInternalDeviceOrigin( long x
, long y
)
540 m_internalDeviceOriginX
= x
;
541 m_internalDeviceOriginY
= y
;
542 ComputeScaleAndOrigin();
544 void wxDC::GetInternalDeviceOrigin( long *x
, long *y
)
546 if (x
) *x
= m_internalDeviceOriginX
;
547 if (y
) *y
= m_internalDeviceOriginY
;
550 void wxDC::SetAxisOrientation( bool xLeftRight
, bool yBottomUp
)
552 m_signX
= (xLeftRight
? 1 : -1);
553 m_signY
= (yBottomUp
? -1 : 1);
554 ComputeScaleAndOrigin();
557 wxSize
wxDC::GetPPI() const
559 return wxSize(72, 72);
562 int wxDC::GetDepth() const
564 if ( IsPortColor( (CGrafPtr
) m_macPort
) )
566 return ( (**GetPortPixMap( (CGrafPtr
) m_macPort
)).pixelSize
) ;
571 void wxDC::ComputeScaleAndOrigin()
573 // CMB: copy scale to see if it changes
574 double origScaleX
= m_scaleX
;
575 double origScaleY
= m_scaleY
;
577 m_scaleX
= m_logicalScaleX
* m_userScaleX
;
578 m_scaleY
= m_logicalScaleY
* m_userScaleY
;
580 m_deviceOriginX
= m_internalDeviceOriginX
+ m_externalDeviceOriginX
;
581 m_deviceOriginY
= m_internalDeviceOriginY
+ m_externalDeviceOriginY
;
583 // CMB: if scale has changed call SetPen to recalulate the line width
584 if (m_scaleX
!= origScaleX
|| m_scaleY
!= origScaleY
)
586 // this is a bit artificial, but we need to force wxDC to think
587 // the pen has changed
588 wxPen
* pen
= & GetPen();
594 void wxDC::SetPalette( const wxPalette
& palette
)
598 void wxDC::SetBackgroundMode( int mode
)
600 m_backgroundMode
= mode
;
603 void wxDC::SetFont( const wxFont
&font
)
606 m_macFontInstalled
= false ;
609 void wxDC::SetPen( const wxPen
&pen
)
616 m_macPenInstalled
= false ;
619 void wxDC::SetBrush( const wxBrush
&brush
)
621 if (m_brush
== brush
)
625 m_macBrushInstalled
= false ;
628 void wxDC::SetBackground( const wxBrush
&brush
)
630 if (m_backgroundBrush
== brush
)
633 m_backgroundBrush
= brush
;
635 if (!m_backgroundBrush
.Ok())
637 m_macBrushInstalled
= false ;
640 void wxDC::SetLogicalFunction( int function
)
642 if (m_logicalFunction
== function
)
645 m_logicalFunction
= function
;
646 m_macFontInstalled
= false ;
647 m_macBrushInstalled
= false ;
648 m_macPenInstalled
= false ;
651 void wxDC::DoFloodFill( wxCoord x
, wxCoord y
, const wxColour
& col
,
656 bool wxDC::DoGetPixel( wxCoord x
, wxCoord y
, wxColour
*col
) const
658 wxCHECK_MSG( Ok(), false, wxT("wxDC::DoGetPixel Invalid DC") );
659 wxMacPortSetter
helper(this) ;
663 GetCPixel( XLOG2DEVMAC(x
), YLOG2DEVMAC(y
), &colour
);
665 // Convert from Mac colour to wx
666 col
->Set( colour
.red
>> 8,
673 void wxDC::DoDrawLine( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
)
675 wxCHECK_RET(Ok(), wxT("Invalid DC"));
677 wxMacPortSetter
helper(this) ;
679 if (m_pen
.GetStyle() != wxTRANSPARENT
)
682 wxCoord offset
= ( (m_pen
.GetWidth() == 0 ? 1 :
683 m_pen
.GetWidth() ) * (wxCoord
)m_scaleX
- 1) / 2;
685 wxCoord xx1
= XLOG2DEVMAC(x1
) - offset
;
686 wxCoord yy1
= YLOG2DEVMAC(y1
) - offset
;
687 wxCoord xx2
= XLOG2DEVMAC(x2
) - offset
;
688 wxCoord yy2
= YLOG2DEVMAC(y2
) - offset
;
690 if ((m_pen
.GetCap() == wxCAP_ROUND
) &&
691 (m_pen
.GetWidth() <= 1))
693 // Implement LAST_NOT for MAC at least for
694 // orthogonal lines. RR.
716 void wxDC::DoCrossHair( wxCoord x
, wxCoord y
)
718 wxCHECK_RET( Ok(), wxT("wxDC::DoCrossHair Invalid window dc") );
720 if (m_pen
.GetStyle() != wxTRANSPARENT
)
725 wxCoord xx
= XLOG2DEVMAC(x
);
726 wxCoord yy
= YLOG2DEVMAC(y
);
729 ::MoveTo( XLOG2DEVMAC(0), yy
);
730 ::LineTo( XLOG2DEVMAC(w
), yy
);
731 ::MoveTo( xx
, YLOG2DEVMAC(0) );
732 ::LineTo( xx
, YLOG2DEVMAC(h
) );
734 CalcBoundingBox(x
, y
);
735 CalcBoundingBox(x
+w
, y
+h
);
741 * To draw arcs properly the angles need to be converted from the WX style:
742 * Angles start on the +ve X axis and go anti-clockwise (As you would draw on
743 * a normal axis on paper).
746 * Angles start on the +ve y axis and go clockwise.
747 * To achive this I work out which quadrant the angle lies in then map this to
748 * the equivalent quadrant on the Mac. (Sin and Cos values reveal which
749 * quadrant you are in).
751 static double wxConvertWXangleToMACangle(double angle
)
755 sin_a
= sin(angle
/ RAD2DEG
);
756 cos_a
= cos(angle
/ RAD2DEG
);
758 if( (sin_a
>= 0.0) && (cos_a
>= 0.0) ) {
759 angle
= acos(sin_a
) * RAD2DEG
;
761 else if( (sin_a
>= 0.0) && (cos_a
<= 0.0) ) {
763 angle
= acos(sin_a
) * RAD2DEG
+ 180;
765 else if( (sin_a
<= 0.0) && (cos_a
>= 0.0) ) {
766 angle
= acos(sin_a
) * RAD2DEG
+ 180;
768 else if( (sin_a
< 0.0) && (cos_a
< 0.0) ) {
770 angle
= acos(sin_a
) * RAD2DEG
+ 180;
775 void wxDC::DoDrawArc( wxCoord x1
, wxCoord y1
,
776 wxCoord x2
, wxCoord y2
,
777 wxCoord xc
, wxCoord yc
)
779 wxCHECK_RET(Ok(), wxT("wxDC::DoDrawArc Invalid DC"));
781 wxCoord xx1
= XLOG2DEVMAC(x1
);
782 wxCoord yy1
= YLOG2DEVMAC(y1
);
783 wxCoord xx2
= XLOG2DEVMAC(x2
);
784 wxCoord yy2
= YLOG2DEVMAC(y2
);
785 wxCoord xxc
= XLOG2DEVMAC(xc
);
786 wxCoord yyc
= YLOG2DEVMAC(yc
);
787 double dx
= xx1
- xxc
;
788 double dy
= yy1
- yyc
;
789 double radius
= sqrt((double)(dx
*dx
+dy
*dy
));
790 wxCoord rad
= (wxCoord
)radius
;
791 double radius1
, radius2
;
793 if (xx1
== xx2
&& yy1
== yy2
)
798 else if (radius
== 0.0)
800 radius1
= radius2
= 0.0;
804 radius1
= (xx1
- xxc
== 0) ?
805 (yy1
- yyc
< 0) ? 90.0 : -90.0 :
806 -atan2(double(yy1
-yyc
), double(xx1
-xxc
)) * RAD2DEG
;
807 radius2
= (xx2
- xxc
== 0) ?
808 (yy2
- yyc
< 0) ? 90.0 : -90.0 :
809 -atan2(double(yy2
-yyc
), double(xx2
-xxc
)) * RAD2DEG
;
811 wxCoord alpha2
= wxCoord(radius2
- radius1
);
812 wxCoord alpha1
= wxCoord(wxConvertWXangleToMACangle(radius1
));
813 if( (xx1
> xx2
) || (yy1
> yy2
) ) {
817 Rect r
= { yyc
- rad
, xxc
- rad
, yyc
+ rad
, xxc
+ rad
};
819 if(m_brush
.GetStyle() != wxTRANSPARENT
) {
821 PaintArc(&r
, alpha1
, alpha2
);
823 if(m_pen
.GetStyle() != wxTRANSPARENT
) {
825 FrameArc(&r
, alpha1
, alpha2
);
829 void wxDC::DoDrawEllipticArc( wxCoord x
, wxCoord y
, wxCoord w
, wxCoord h
,
830 double sa
, double ea
)
832 wxCHECK_RET(Ok(), wxT("wxDC::DoDrawEllepticArc Invalid DC"));
835 double angle
= sa
- ea
; // Order important Mac in opposite direction to wx
837 wxCoord xx
= XLOG2DEVMAC(x
);
838 wxCoord yy
= YLOG2DEVMAC(y
);
839 wxCoord ww
= m_signX
* XLOG2DEVREL(w
);
840 wxCoord hh
= m_signY
* YLOG2DEVREL(h
);
842 // handle -ve width and/or height
843 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
844 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
846 sa
= wxConvertWXangleToMACangle(sa
);
853 if(m_brush
.GetStyle() != wxTRANSPARENT
) {
855 PaintArc(&r
, (short)sa
, (short)angle
);
857 if(m_pen
.GetStyle() != wxTRANSPARENT
) {
859 FrameArc(&r
, (short)sa
, (short)angle
);
863 void wxDC::DoDrawPoint( wxCoord x
, wxCoord y
)
865 wxCHECK_RET(Ok(), wxT("Invalid DC"));
867 wxMacPortSetter
helper(this) ;
869 if (m_pen
.GetStyle() != wxTRANSPARENT
)
872 wxCoord xx1
= XLOG2DEVMAC(x
);
873 wxCoord yy1
= YLOG2DEVMAC(y
);
876 ::LineTo(xx1
+1, yy1
+1);
880 void wxDC::DoDrawLines(int n
, wxPoint points
[],
881 wxCoord xoffset
, wxCoord yoffset
)
883 wxCHECK_RET(Ok(), wxT("Invalid DC"));
884 wxMacPortSetter
helper(this) ;
886 if (m_pen
.GetStyle() == wxTRANSPARENT
)
891 wxCoord offset
= ( (m_pen
.GetWidth() == 0 ? 1 :
892 m_pen
.GetWidth() ) * (wxCoord
)m_scaleX
- 1) / 2 ;
894 wxCoord x1
, x2
, y1
, y2
;
895 x1
= XLOG2DEVMAC(points
[0].x
+ xoffset
);
896 y1
= YLOG2DEVMAC(points
[0].y
+ yoffset
);
897 ::MoveTo(x1
- offset
, y1
- offset
);
899 for (int i
= 0; i
< n
-1; i
++)
901 x2
= XLOG2DEVMAC(points
[i
+1].x
+ xoffset
);
902 y2
= YLOG2DEVMAC(points
[i
+1].y
+ yoffset
);
903 ::LineTo( x2
- offset
, y2
- offset
);
907 void wxDC::DoDrawPolygon(int n
, wxPoint points
[],
908 wxCoord xoffset
, wxCoord yoffset
,
911 wxCHECK_RET(Ok(), wxT("Invalid DC"));
912 wxMacPortSetter
helper(this) ;
914 wxCoord x1
, x2
, y1
, y2
;
916 if ( m_brush
.GetStyle() == wxTRANSPARENT
&& m_pen
.GetStyle() == wxTRANSPARENT
)
919 PolyHandle polygon
= OpenPoly();
921 x1
= XLOG2DEVMAC(points
[0].x
+ xoffset
);
922 y1
= YLOG2DEVMAC(points
[0].y
+ yoffset
);
925 for (int i
= 1; i
< n
; i
++)
927 x2
= XLOG2DEVMAC(points
[i
].x
+ xoffset
);
928 y2
= YLOG2DEVMAC(points
[i
].y
+ yoffset
);
932 // close the polyline if necessary
933 if ( x1
!= x2
|| y1
!= y2
)
940 if (m_brush
.GetStyle() != wxTRANSPARENT
)
944 ::PaintPoly( polygon
);
948 if (m_pen
.GetStyle() != wxTRANSPARENT
)
952 ::FramePoly( polygon
) ;
958 void wxDC::DoDrawRectangle(wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
960 wxCHECK_RET(Ok(), wxT("Invalid DC"));
961 wxMacPortSetter
helper(this) ;
963 wxCoord xx
= XLOG2DEVMAC(x
);
964 wxCoord yy
= YLOG2DEVMAC(y
);
965 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
966 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
968 // CMB: draw nothing if transformed w or h is 0
969 if (ww
== 0 || hh
== 0)
972 // CMB: handle -ve width and/or height
985 Rect rect
= { yy
, xx
, yy
+ hh
, xx
+ ww
} ;
987 if (m_brush
.GetStyle() != wxTRANSPARENT
)
990 ::PaintRect( &rect
) ;
993 if (m_pen
.GetStyle() != wxTRANSPARENT
)
996 ::FrameRect( &rect
) ;
1000 void wxDC::DoDrawRoundedRectangle(wxCoord x
, wxCoord y
,
1001 wxCoord width
, wxCoord height
,
1004 wxCHECK_RET(Ok(), wxT("Invalid DC"));
1005 wxMacPortSetter
helper(this) ;
1008 radius
= - radius
* ((width
< height
) ? width
: height
);
1010 wxCoord xx
= XLOG2DEVMAC(x
);
1011 wxCoord yy
= YLOG2DEVMAC(y
);
1012 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
1013 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
1015 // CMB: draw nothing if transformed w or h is 0
1016 if (ww
== 0 || hh
== 0)
1019 // CMB: handle -ve width and/or height
1032 Rect rect
= { yy
, xx
, yy
+ hh
, xx
+ ww
} ;
1034 if (m_brush
.GetStyle() != wxTRANSPARENT
)
1037 ::PaintRoundRect( &rect
, int(radius
* 2) , int(radius
* 2) ) ;
1040 if (m_pen
.GetStyle() != wxTRANSPARENT
)
1043 ::FrameRoundRect( &rect
, int(radius
* 2) , int(radius
* 2) ) ;
1047 void wxDC::DoDrawEllipse(wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
1049 wxCHECK_RET(Ok(), wxT("Invalid DC"));
1050 wxMacPortSetter
helper(this) ;
1052 wxCoord xx
= XLOG2DEVMAC(x
);
1053 wxCoord yy
= YLOG2DEVMAC(y
);
1054 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
1055 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
1057 // CMB: draw nothing if transformed w or h is 0
1058 if (ww
== 0 || hh
== 0)
1061 // CMB: handle -ve width and/or height
1074 Rect rect
= { yy
, xx
, yy
+ hh
, xx
+ ww
} ;
1076 if (m_brush
.GetStyle() != wxTRANSPARENT
)
1079 ::PaintOval( &rect
) ;
1082 if (m_pen
.GetStyle() != wxTRANSPARENT
)
1085 ::FrameOval( &rect
) ;
1091 bool wxDC::CanDrawBitmap(void) const
1097 bool wxDC::DoBlit(wxCoord xdest
, wxCoord ydest
, wxCoord width
, wxCoord height
,
1098 wxDC
*source
, wxCoord xsrc
, wxCoord ysrc
, int logical_func
, bool useMask
,
1099 wxCoord xsrcMask
, wxCoord ysrcMask
)
1101 wxCHECK_MSG(Ok(), false, wxT("wxDC::DoBlit Illegal dc"));
1102 wxCHECK_MSG(source
->Ok(), false, wxT("wxDC::DoBlit Illegal source DC"));
1104 if ( logical_func
== wxNO_OP
)
1107 if (xsrcMask
== -1 && ysrcMask
== -1)
1109 xsrcMask
= xsrc
; ysrcMask
= ysrc
;
1112 // correct the parameter in case this dc does not have a mask at all
1114 if ( useMask
&& !source
->m_macMask
)
1117 Rect srcrect
, dstrect
;
1118 srcrect
.top
= source
->YLOG2DEVMAC(ysrc
) ;
1119 srcrect
.left
= source
->XLOG2DEVMAC(xsrc
) ;
1120 srcrect
.right
= source
->XLOG2DEVMAC(xsrc
+ width
) ;
1121 srcrect
.bottom
= source
->YLOG2DEVMAC(ysrc
+ height
) ;
1122 dstrect
.top
= YLOG2DEVMAC(ydest
) ;
1123 dstrect
.left
= XLOG2DEVMAC(xdest
) ;
1124 dstrect
.bottom
= YLOG2DEVMAC(ydest
+ height
) ;
1125 dstrect
.right
= XLOG2DEVMAC(xdest
+ width
) ;
1127 short mode
= kUnsupportedMode
;
1128 bool invertDestinationFirst
= false ;
1129 switch ( logical_func
)
1131 case wxAND
: // src AND dst
1132 mode
= srcOr
; // ok
1134 case wxAND_INVERT
: // (NOT src) AND dst
1135 mode
= notSrcOr
; // ok
1137 case wxAND_REVERSE
:// src AND (NOT dst)
1138 invertDestinationFirst
= true ;
1142 mode
= kEmulatedMode
;
1145 mode
= srcCopy
; // ok
1147 case wxEQUIV
: // (NOT src) XOR dst
1148 mode
= srcXor
; // ok
1150 case wxINVERT
: // NOT dst
1151 mode
= kEmulatedMode
; //or hilite ;
1153 case wxNAND
: // (NOT src) OR (NOT dst)
1154 invertDestinationFirst
= true ;
1157 case wxNOR
: // (NOT src) AND (NOT dst)
1158 invertDestinationFirst
= true ;
1161 case wxNO_OP
: // dst
1162 mode
= kEmulatedMode
; // this has already been handled upon entry
1164 case wxOR
: // src OR dst
1167 case wxOR_INVERT
: // (NOT src) OR dst
1170 case wxOR_REVERSE
: // src OR (NOT dst)
1171 invertDestinationFirst
= true ;
1175 mode
= kEmulatedMode
;
1177 case wxSRC_INVERT
: // (NOT src)
1178 mode
= notSrcCopy
; // ok
1180 case wxXOR
: // src XOR dst
1181 mode
= notSrcXor
; // ok
1189 if ( mode
== kUnsupportedMode
)
1191 wxFAIL_MSG("unsupported blitting mode" )
1195 CGrafPtr sourcePort
= (CGrafPtr
) source
->m_macPort
;
1196 PixMapHandle bmappixels
= GetGWorldPixMap( sourcePort
) ;
1197 if ( LockPixels(bmappixels
) )
1199 wxMacPortSetter
helper(this) ;
1200 RGBColor tempColor
;
1202 if ( source
->GetDepth() == 1 )
1204 RGBForeColor( &MAC_WXCOLORREF(m_textForegroundColour
.GetPixel()) ) ;
1205 RGBBackColor( &MAC_WXCOLORREF(m_textBackgroundColour
.GetPixel()) ) ;
1209 // the modes need this, otherwise we'll end up having really nice colors...
1210 RGBColor white
= { 0xFFFF, 0xFFFF,0xFFFF} ;
1211 RGBColor black
= { 0,0,0} ;
1212 RGBForeColor( &black
) ;
1213 RGBBackColor( &white
) ;
1216 if ( useMask
&& source
->m_macMask
)
1218 if ( mode
== srcCopy
)
1220 if ( LockPixels( GetGWorldPixMap( MAC_WXHBITMAP(source
->m_macMask
) ) ) )
1222 CopyMask( GetPortBitMapForCopyBits( sourcePort
) ,
1223 GetPortBitMapForCopyBits( MAC_WXHBITMAP(source
->m_macMask
) ) ,
1224 GetPortBitMapForCopyBits( MAC_WXHBITMAP(m_macPort
) ) ,
1225 &srcrect
, &srcrect
, &dstrect
) ;
1226 UnlockPixels( GetGWorldPixMap( MAC_WXHBITMAP(source
->m_macMask
) ) ) ;
1231 RgnHandle clipRgn
= NewRgn() ;
1232 LockPixels( GetGWorldPixMap( MAC_WXHBITMAP(source
->m_macMask
) ) ) ;
1233 BitMapToRegion( clipRgn
, (BitMap
*) *GetGWorldPixMap( MAC_WXHBITMAP(source
->m_macMask
) ) ) ;
1234 UnlockPixels( GetGWorldPixMap( MAC_WXHBITMAP(source
->m_macMask
) ) ) ;
1235 OffsetRgn( clipRgn
, -srcrect
.left
+ dstrect
.left
, -srcrect
.top
+ dstrect
.top
) ;
1236 if ( mode
== kEmulatedMode
)
1239 ::PenPat(GetQDGlobalsBlack(&pat
));
1240 if ( logical_func
== wxSET
)
1242 RGBColor col
= { 0xFFFF, 0xFFFF, 0xFFFF } ;
1243 ::RGBForeColor( &col
) ;
1244 ::PaintRgn( clipRgn
) ;
1246 else if ( logical_func
== wxCLEAR
)
1248 RGBColor col
= { 0x0000, 0x0000, 0x0000 } ;
1249 ::RGBForeColor( &col
) ;
1250 ::PaintRgn( clipRgn
) ;
1252 else if ( logical_func
== wxINVERT
)
1254 MacInvertRgn( clipRgn
) ;
1258 for ( int y
= 0 ; y
< srcrect
.right
- srcrect
.left
; ++y
)
1260 for ( int x
= 0 ; x
< srcrect
.bottom
- srcrect
.top
; ++x
)
1262 Point dstPoint
= { dstrect
.top
+ y
, dstrect
.left
+ x
} ;
1263 Point srcPoint
= { srcrect
.top
+ y
, srcrect
.left
+ x
} ;
1264 if ( PtInRgn( dstPoint
, clipRgn
) )
1269 SetPort( (GrafPtr
) sourcePort
) ;
1270 GetCPixel( srcPoint
.h
, srcPoint
.v
, &srcColor
) ;
1271 SetPort( (GrafPtr
) m_macPort
) ;
1272 GetCPixel( dstPoint
.h
, dstPoint
.v
, &dstColor
) ;
1274 wxMacCalculateColour( logical_func
, srcColor
, dstColor
) ;
1275 SetCPixel( dstPoint
.h
, dstPoint
.v
, &dstColor
) ;
1283 if ( invertDestinationFirst
)
1285 MacInvertRgn( clipRgn
) ;
1287 CopyBits( GetPortBitMapForCopyBits( sourcePort
) ,
1288 GetPortBitMapForCopyBits( MAC_WXHBITMAP(m_macPort
) ) ,
1289 &srcrect
, &dstrect
, mode
, clipRgn
) ;
1291 DisposeRgn( clipRgn
) ;
1296 RgnHandle clipRgn
= NewRgn() ;
1297 SetRectRgn( clipRgn
, dstrect
.left
, dstrect
.top
, dstrect
.right
, dstrect
.bottom
) ;
1298 if ( mode
== kEmulatedMode
)
1301 ::PenPat(GetQDGlobalsBlack(&pat
));
1302 if ( logical_func
== wxSET
)
1304 RGBColor col
= { 0xFFFF, 0xFFFF, 0xFFFF } ;
1305 ::RGBForeColor( &col
) ;
1306 ::PaintRgn( clipRgn
) ;
1308 else if ( logical_func
== wxCLEAR
)
1310 RGBColor col
= { 0x0000, 0x0000, 0x0000 } ;
1311 ::RGBForeColor( &col
) ;
1312 ::PaintRgn( clipRgn
) ;
1314 else if ( logical_func
== wxINVERT
)
1316 MacInvertRgn( clipRgn
) ;
1320 for ( int y
= 0 ; y
< srcrect
.right
- srcrect
.left
; ++y
)
1322 for ( int x
= 0 ; x
< srcrect
.bottom
- srcrect
.top
; ++x
)
1324 Point dstPoint
= { dstrect
.top
+ y
, dstrect
.left
+ x
} ;
1325 Point srcPoint
= { srcrect
.top
+ y
, srcrect
.left
+ x
} ;
1331 SetPort( (GrafPtr
) sourcePort
) ;
1332 GetCPixel( srcPoint
.h
, srcPoint
.v
, &srcColor
) ;
1333 SetPort( (GrafPtr
) m_macPort
) ;
1334 GetCPixel( dstPoint
.h
, dstPoint
.v
, &dstColor
) ;
1336 wxMacCalculateColour( logical_func
, srcColor
, dstColor
) ;
1337 SetCPixel( dstPoint
.h
, dstPoint
.v
, &dstColor
) ;
1346 if ( invertDestinationFirst
)
1348 MacInvertRgn( clipRgn
) ;
1350 CopyBits( GetPortBitMapForCopyBits( sourcePort
) ,
1351 GetPortBitMapForCopyBits( MAC_WXHBITMAP(m_macPort
) ) ,
1352 &srcrect
, &dstrect
, mode
, NULL
) ;
1354 DisposeRgn( clipRgn
) ;
1356 UnlockPixels( bmappixels
) ;
1359 m_macPenInstalled
= false ;
1360 m_macBrushInstalled
= false ;
1361 m_macFontInstalled
= false ;
1366 inline Fixed
IntToFixed( int inInt
)
1368 return (((SInt32
) inInt
) << 16);
1372 void wxDC::DoDrawRotatedText(const wxString
& str
, wxCoord x
, wxCoord y
,
1375 wxCHECK_RET( Ok(), wxT("wxDC::DoDrawRotatedText Invalid window dc") );
1379 DrawText(str
, x
, y
);
1383 wxMacPortSetter
helper(this) ;
1387 if ( wxApp::s_macDefaultEncodingIsPC
)
1389 text
= wxMacMakeMacStringFromPC( str
) ;
1396 wxFontRefData
* font
= (wxFontRefData
*) m_font
.GetRefData() ;
1399 m_macFormerAliasState
= IsAntiAliasedTextEnabled(&m_macFormerAliasSize
);
1400 SetAntiAliasedTextEnabled(true, m_scaleY
* font
->m_macFontSize
);
1401 m_macAliasWasEnabled
= true ;
1404 OSStatus status
= noErr
;
1407 status
= TECCreateConverter(&ec
, kTextEncodingMacRoman
, kTextEncodingUnicodeDefault
);
1408 wxASSERT_MSG( status
== noErr
, "couldn't start converter" ) ;
1410 ByteCount byteOutLen
;
1411 ByteCount byteInLen
= text
.Length() ;
1412 ByteCount byteBufferLen
= byteInLen
*2 ;
1413 char* buf
= new char[byteBufferLen
] ;
1415 status
= TECConvertText(ec
, (ConstTextPtr
)text
.c_str() , byteInLen
, &byteInLen
,
1416 (TextPtr
)buf
, byteBufferLen
, &byteOutLen
);
1418 wxASSERT_MSG( status
== noErr
, "couldn't convert text" ) ;
1419 status
= TECDisposeConverter(ec
);
1420 wxASSERT_MSG( status
== noErr
, "couldn't dispose converter" ) ;
1422 ATSUTextLayout atsuLayout
;
1423 UniCharCount chars
= byteOutLen
/ 2 ;
1424 status
= ::ATSUCreateTextLayoutWithTextPtr( (UniCharArrayPtr
) buf
, 0 , byteOutLen
/ 2 , byteOutLen
/ 2 , 1 ,
1425 &chars
, (ATSUStyle
*) &m_macATSUIStyle
, &atsuLayout
) ;
1426 wxASSERT_MSG( status
== noErr
, "couldn't create the layout of the rotated text" );
1428 Fixed atsuAngle
= IntToFixed( angle
) ;
1429 ByteCount angleSize
= sizeof(Fixed
) ;
1430 ATSUAttributeTag rotationTag
= kATSULineRotationTag
;
1431 ATSUAttributeValuePtr angleValue
= &atsuAngle
;
1432 status
= ::ATSUSetLayoutControls(atsuLayout
, 1 , &rotationTag
, &angleSize
, &angleValue
) ;
1434 status
= ::ATSUDrawText( atsuLayout
, kATSUFromTextBeginning
, kATSUToTextEnd
,
1435 IntToFixed(XLOG2DEVMAC(x
) ) , IntToFixed(YLOG2DEVMAC(y
) ) );
1436 wxASSERT_MSG( status
== noErr
, "couldn't draw the rotated text" );
1438 status
= ::ATSUMeasureTextImage( atsuLayout
, kATSUFromTextBeginning
, kATSUToTextEnd
,
1439 IntToFixed(XLOG2DEVMAC(x
) ) , IntToFixed(YLOG2DEVMAC(y
) ) , &rect
);
1440 wxASSERT_MSG( status
== noErr
, "couldn't measure the rotated text" );
1442 OffsetRect( &rect
, -m_macLocalOrigin
.x
, -m_macLocalOrigin
.y
) ;
1443 CalcBoundingBox(XDEV2LOG(rect
.left
), YDEV2LOG(rect
.top
) );
1444 CalcBoundingBox(XDEV2LOG(rect
.right
), YDEV2LOG(rect
.bottom
) );
1445 ::ATSUDisposeTextLayout(atsuLayout
);
1449 void wxDC::DoDrawText(const wxString
& strtext
, wxCoord x
, wxCoord y
)
1451 wxCHECK_RET(Ok(), wxT("wxDC::DoDrawText Invalid DC"));
1452 wxMacPortSetter
helper(this) ;
1454 long xx
= XLOG2DEVMAC(x
);
1455 long yy
= YLOG2DEVMAC(y
);
1460 m_macFormerAliasState
= IsAntiAliasedTextEnabled(&m_macFormerAliasSize
);
1461 SetAntiAliasedTextEnabled(true, 8);
1462 m_macAliasWasEnabled
= true ;
1466 ::GetFontInfo( &fi
) ;
1469 ::MoveTo( xx
, yy
);
1470 if ( m_backgroundMode
== wxTRANSPARENT
)
1472 ::TextMode( srcOr
) ;
1476 ::TextMode( srcCopy
) ;
1479 const char *text
= NULL
;
1483 if ( wxApp::s_macDefaultEncodingIsPC
)
1485 macText
= wxMacMakeMacStringFromPC( strtext
) ;
1487 length
= macText
.Length() ;
1492 length
= strtext
.Length() ;
1501 if( text
[i
] == 13 || text
[i
] == 10)
1503 ::DrawText( text
, laststop
, i
- laststop
) ;
1505 ::MoveTo( xx
, yy
+ line
*(fi
.descent
+ fi
.ascent
+ fi
.leading
) );
1511 ::DrawText( text
, laststop
, i
- laststop
) ;
1512 ::TextMode( srcOr
) ;
1515 bool wxDC::CanGetTextExtent() const
1517 wxCHECK_MSG(Ok(), false, wxT("Invalid DC"));
1522 void wxDC::DoGetTextExtent( const wxString
&string
, wxCoord
*width
, wxCoord
*height
,
1523 wxCoord
*descent
, wxCoord
*externalLeading
,
1524 wxFont
*theFont
) const
1526 wxCHECK_RET(Ok(), wxT("Invalid DC"));
1527 wxMacPortSetter
helper(this) ;
1529 wxFont formerFont
= m_font
;
1533 wxFontRefData
* font
= (wxFontRefData
*) m_font
.GetRefData() ;
1537 ::TextFont( font
->m_macFontNum
) ;
1538 ::TextSize( YLOG2DEVREL( font
->m_macFontSize
) ) ;
1539 ::TextFace( font
->m_macFontStyle
) ;
1548 ::GetFontInfo( &fi
) ;
1551 *height
= YDEV2LOGREL( fi
.descent
+ fi
.ascent
) ;
1553 *descent
=YDEV2LOGREL( fi
.descent
);
1554 if ( externalLeading
)
1555 *externalLeading
= YDEV2LOGREL( fi
.leading
) ;
1557 const char *text
= NULL
;
1560 if ( wxApp::s_macDefaultEncodingIsPC
)
1562 macText
= wxMacMakeMacStringFromPC( string
) ;
1564 length
= macText
.Length() ;
1569 length
= string
.Length() ;
1581 if( text
[i
] == 13 || text
[i
] == 10)
1584 *height
+= YDEV2LOGREL( fi
.descent
+ fi
.ascent
+ fi
.leading
) ;
1585 curwidth
= ::TextWidth( text
, laststop
, i
- laststop
) ;
1586 if ( curwidth
> *width
)
1587 *width
= XDEV2LOGREL( curwidth
) ;
1593 curwidth
= ::TextWidth( text
, laststop
, i
- laststop
) ;
1594 if ( curwidth
> *width
)
1595 *width
= XDEV2LOGREL( curwidth
) ;
1600 m_macFontInstalled
= false ;
1604 wxCoord
wxDC::GetCharWidth(void) const
1606 wxCHECK_MSG(Ok(), 1, wxT("Invalid DC"));
1608 wxMacPortSetter
helper(this) ;
1612 int width
= ::TextWidth( "n" , 0 , 1 ) ;
1614 return YDEV2LOGREL(width
) ;
1617 wxCoord
wxDC::GetCharHeight(void) const
1619 wxCHECK_MSG(Ok(), 1, wxT("Invalid DC"));
1621 wxMacPortSetter
helper(this) ;
1626 ::GetFontInfo( &fi
) ;
1628 return YDEV2LOGREL( fi
.descent
+ fi
.ascent
);
1631 void wxDC::Clear(void)
1633 wxCHECK_RET(Ok(), wxT("Invalid DC"));
1634 wxMacPortSetter
helper(this) ;
1635 Rect rect
= { -32000 , -32000 , 32000 , 32000 } ;
1637 if (m_backgroundBrush
.GetStyle() != wxTRANSPARENT
)
1640 //MacInstallBrush() ;
1641 MacSetupBackgroundForCurrentPort( m_backgroundBrush
) ;
1642 ::EraseRect( &rect
) ;
1646 void wxDC::MacInstallFont() const
1648 wxCHECK_RET(Ok(), wxT("Invalid DC"));
1649 // if ( m_macFontInstalled )
1651 Pattern blackColor
;
1653 wxFontRefData
* font
= (wxFontRefData
*) m_font
.GetRefData() ;
1657 ::TextFont( font
->m_macFontNum
) ;
1658 ::TextSize( short(m_scaleY
* font
->m_macFontSize
) ) ;
1659 ::TextFace( font
->m_macFontStyle
) ;
1661 m_macFontInstalled
= true ;
1662 m_macBrushInstalled
= false ;
1663 m_macPenInstalled
= false ;
1665 RGBColor forecolor
= MAC_WXCOLORREF( m_textForegroundColour
.GetPixel());
1666 RGBColor backcolor
= MAC_WXCOLORREF( m_textBackgroundColour
.GetPixel());
1667 ::RGBForeColor( &forecolor
);
1668 ::RGBBackColor( &backcolor
);
1674 GetFNum( "\pGeneva" , &fontnum
) ;
1675 ::TextFont( fontnum
) ;
1676 ::TextSize( short(m_scaleY
* 10) ) ;
1679 // todo reset after spacing changes - or store the current spacing somewhere
1681 m_macFontInstalled
= true ;
1682 m_macBrushInstalled
= false ;
1683 m_macPenInstalled
= false ;
1685 RGBColor forecolor
= MAC_WXCOLORREF( m_textForegroundColour
.GetPixel());
1686 RGBColor backcolor
= MAC_WXCOLORREF( m_textBackgroundColour
.GetPixel());
1687 ::RGBForeColor( &forecolor
);
1688 ::RGBBackColor( &backcolor
);
1691 short mode
= patCopy
;
1695 switch( m_logicalFunction
)
1700 case wxINVERT
: // NOT dst
1701 ::PenPat(GetQDGlobalsBlack(&blackColor
));
1704 case wxXOR
: // src XOR dst
1707 case wxOR_REVERSE
: // src OR (NOT dst)
1710 case wxSRC_INVERT
: // (NOT src)
1717 case wxAND_REVERSE
:// src AND (NOT dst)
1718 case wxAND
: // src AND dst
1719 case wxAND_INVERT
: // (NOT src) AND dst
1720 case wxNO_OP
: // dst
1721 case wxNOR
: // (NOT src) AND (NOT dst)
1722 case wxEQUIV
: // (NOT src) XOR dst
1723 case wxOR_INVERT
: // (NOT src) OR dst
1724 case wxNAND
: // (NOT src) OR (NOT dst)
1725 case wxOR
: // src OR dst
1727 // case wxSRC_OR: // source _bitmap_ OR destination
1728 // case wxSRC_AND: // source _bitmap_ AND destination
1733 OSStatus status
= noErr
;
1735 Fixed atsuSize
= IntToFixed(m_scaleY
* font
->m_macFontSize
) ;
1737 Style qdStyle
= font
->m_macFontStyle
;
1738 ATSUFontID atsuFont
= font
->m_macATSUFontID
;
1740 status
= ::ATSUCreateStyle(&(ATSUStyle
)m_macATSUIStyle
) ;
1741 wxASSERT_MSG( status
== noErr
, "couldn't create ATSU style" ) ;
1743 ATSUAttributeTag atsuTags
[] =
1749 kATSUQDBoldfaceTag
,
1751 kATSUQDUnderlineTag
,
1752 kATSUQDCondensedTag
,
1753 kATSUQDExtendedTag
,
1757 ByteCount atsuSizes
[sizeof(atsuTags
)/sizeof(ATSUAttributeTag
)] =
1759 sizeof( ATSUFontID
) ,
1761 sizeof( RGBColor
) ,
1769 Boolean kTrue
= true ;
1770 Boolean kFalse
= false ;
1772 ATSUAttributeValuePtr atsuValues
[sizeof(atsuTags
)/sizeof(ATSUAttributeTag
)] =
1776 &MAC_WXCOLORREF( m_textForegroundColour
.GetPixel() ) ,
1778 (qdStyle
& bold
) ? &kTrue
: &kFalse
,
1779 (qdStyle
& italic
) ? &kTrue
: &kFalse
,
1780 (qdStyle
& underline
) ? &kTrue
: &kFalse
,
1781 (qdStyle
& condense
) ? &kTrue
: &kFalse
,
1782 (qdStyle
& extend
) ? &kTrue
: &kFalse
,
1785 status
= ::ATSUSetAttributes((ATSUStyle
)m_macATSUIStyle
, sizeof(atsuTags
)/sizeof(ATSUAttributeTag
),
1786 atsuTags
, atsuSizes
, atsuValues
);
1787 wxASSERT_MSG( status
== noErr
, "couldn't set create ATSU style" ) ;
1791 Pattern gHatchPatterns
[] =
1793 { 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF } ,
1794 { 0x01 , 0x02 , 0x04 , 0x08 , 0x10 , 0x20 , 0x40 , 0x80 } ,
1795 { 0x80 , 0x40 , 0x20 , 0x10 , 0x08 , 0x04 , 0x02 , 0x01 } ,
1796 { 0x10 , 0x10 , 0x10 , 0xFF , 0x10 , 0x10 , 0x10 , 0x10 } ,
1797 { 0x00 , 0x00 , 0x00 , 0xFF , 0x00 , 0x00 , 0x00 , 0x00 } ,
1798 { 0x10 , 0x10 , 0x10 , 0x10 , 0x10 , 0x10 , 0x10 , 0x10 } ,
1799 { 0x81 , 0x42 , 0x24 , 0x18 , 0x18 , 0x24 , 0x42 , 0x81 } ,
1802 static void wxMacGetHatchPattern(int hatchStyle
, Pattern
*pattern
)
1808 case wxBDIAGONAL_HATCH
:
1811 case wxFDIAGONAL_HATCH
:
1817 case wxHORIZONTAL_HATCH
:
1820 case wxVERTICAL_HATCH
:
1823 case wxCROSSDIAG_HATCH
:
1827 theIndex
= 1; // solid pattern
1830 *pattern
= gHatchPatterns
[theIndex
-1] ;
1833 void wxDC::MacInstallPen() const
1835 wxCHECK_RET(Ok(), wxT("Invalid DC"));
1839 // if ( m_macPenInstalled )
1842 RGBColor forecolor
= MAC_WXCOLORREF( m_pen
.GetColour().GetPixel());
1843 RGBColor backcolor
= MAC_WXCOLORREF( m_backgroundBrush
.GetColour().GetPixel());
1844 ::RGBForeColor( &forecolor
);
1845 ::RGBBackColor( &backcolor
);
1848 int penWidth
= m_pen
.GetWidth() * (int) m_scaleX
;
1850 // null means only one pixel, at whatever resolution
1851 if ( penWidth
== 0 )
1853 ::PenSize(penWidth
, penWidth
);
1855 int penStyle
= m_pen
.GetStyle();
1857 if (penStyle
== wxSOLID
)
1859 ::PenPat(GetQDGlobalsBlack(&blackColor
));
1861 else if (IS_HATCH(penStyle
))
1864 wxMacGetHatchPattern(penStyle
, &pat
);
1869 Pattern pat
= *GetQDGlobalsBlack(&blackColor
) ;
1873 for ( int i
= 0 ; i
< 8 ; ++i
)
1879 for ( int i
= 0 ; i
< 8 ; ++i
)
1885 for ( int i
= 0 ; i
< 8 ; ++i
)
1891 for ( int i
= 0 ; i
< 8 ; ++i
)
1899 int number
= m_pen
.GetDashes(&dash
) ;
1900 // right now we don't allocate larger pixmaps
1901 for ( int i
= 0 ; i
< 8 ; ++i
)
1903 pat
.pat
[i
] = dash
[0] ;
1911 short mode
= patCopy
;
1915 switch( m_logicalFunction
)
1917 case wxCOPY
: // only foreground color, leave background (thus not patCopy)
1920 case wxINVERT
: // NOT dst
1921 // ::PenPat(GetQDGlobalsBlack(&blackColor));
1924 case wxXOR
: // src XOR dst
1927 case wxOR_REVERSE
: // src OR (NOT dst)
1930 case wxSRC_INVERT
: // (NOT src)
1937 case wxAND_REVERSE
:// src AND (NOT dst)
1938 case wxAND
: // src AND dst
1939 case wxAND_INVERT
: // (NOT src) AND dst
1940 case wxNO_OP
: // dst
1941 case wxNOR
: // (NOT src) AND (NOT dst)
1942 case wxEQUIV
: // (NOT src) XOR dst
1943 case wxOR_INVERT
: // (NOT src) OR dst
1944 case wxNAND
: // (NOT src) OR (NOT dst)
1945 case wxOR
: // src OR dst
1947 // case wxSRC_OR: // source _bitmap_ OR destination
1948 // case wxSRC_AND: // source _bitmap_ AND destination
1952 m_macPenInstalled
= true ;
1953 m_macBrushInstalled
= false ;
1954 m_macFontInstalled
= false ;
1957 void wxDC::MacSetupBackgroundForCurrentPort(const wxBrush
& background
)
1959 Pattern whiteColor
;
1960 switch( background
.MacGetBrushKind() )
1962 case kwxMacBrushTheme
:
1964 ::SetThemeBackground( background
.GetMacTheme() , wxDisplayDepth() , true ) ;
1967 case kwxMacBrushThemeBackground
:
1970 ThemeBackgroundKind bg
= background
.GetMacThemeBackground( &extent
) ;
1971 ::ApplyThemeBackground( bg
, &extent
,kThemeStateActive
, wxDisplayDepth() , true ) ;
1974 case kwxMacBrushColour
:
1976 ::RGBBackColor( &MAC_WXCOLORREF( background
.GetColour().GetPixel()) );
1977 int brushStyle
= background
.GetStyle();
1978 if (brushStyle
== wxSOLID
)
1979 ::BackPat(GetQDGlobalsWhite(&whiteColor
));
1980 else if (IS_HATCH(brushStyle
))
1983 wxMacGetHatchPattern(brushStyle
, &pat
);
1988 ::BackPat(GetQDGlobalsWhite(&whiteColor
));
1995 void wxDC::MacInstallBrush() const
1997 wxCHECK_RET(Ok(), wxT("Invalid DC"));
1999 Pattern blackColor
;
2000 // if ( m_macBrushInstalled )
2005 bool backgroundTransparent
= (GetBackgroundMode() == wxTRANSPARENT
) ;
2007 ::RGBForeColor( &MAC_WXCOLORREF( m_brush
.GetColour().GetPixel()) );
2008 ::RGBBackColor( &MAC_WXCOLORREF( m_backgroundBrush
.GetColour().GetPixel()) );
2010 int brushStyle
= m_brush
.GetStyle();
2011 if (brushStyle
== wxSOLID
)
2013 ::PenPat(GetQDGlobalsBlack(&blackColor
));
2015 else if (IS_HATCH(brushStyle
))
2018 wxMacGetHatchPattern(brushStyle
, &pat
);
2021 else if ( m_brush
.GetStyle() == wxSTIPPLE
|| m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
)
2023 // we force this in order to be compliant with wxMSW
2024 backgroundTransparent
= false ;
2025 // for these the text fore (and back for MASK_OPAQUE) colors are used
2026 wxBitmap
* bitmap
= m_brush
.GetStipple() ;
2027 int width
= bitmap
->GetWidth() ;
2028 int height
= bitmap
->GetHeight() ;
2029 GWorldPtr gw
= NULL
;
2031 if ( m_brush
.GetStyle() == wxSTIPPLE
)
2032 gw
= MAC_WXHBITMAP(bitmap
->GetHBITMAP()) ;
2034 gw
= MAC_WXHBITMAP(bitmap
->GetMask()->GetMaskBitmap()) ;
2036 PixMapHandle gwpixmaphandle
= GetGWorldPixMap( gw
) ;
2037 LockPixels( gwpixmaphandle
) ;
2039 bool isMonochrome
= !IsPortColor( gw
) ;
2041 if ( !isMonochrome
)
2043 if ( (**gwpixmaphandle
).pixelSize
== 1 )
2044 isMonochrome
= true ;
2047 if ( isMonochrome
&& width
== 8 && height
== 8 )
2049 ::RGBForeColor( &MAC_WXCOLORREF( m_textForegroundColour
.GetPixel()) );
2050 ::RGBForeColor( &MAC_WXCOLORREF( m_textBackgroundColour
.GetPixel()) );
2051 BitMap
* gwbitmap
= (BitMap
*) *gwpixmaphandle
; // since the color depth is 1 it is a BitMap
2052 UInt8
*gwbits
= (UInt8
*) gwbitmap
->baseAddr
;
2053 int alignment
= gwbitmap
->rowBytes
& 0x7FFF ;
2055 for ( int i
= 0 ; i
< 8 ; ++i
)
2057 pat
.pat
[i
] = gwbits
[i
*alignment
+0] ;
2059 UnlockPixels( GetGWorldPixMap( gw
) ) ;
2064 // this will be the code to handle power of 2 patterns, we will have to arrive at a nice
2065 // caching scheme before putting this into production
2068 PixPatHandle pixpat
= NewPixPat() ;
2070 CopyPixMap(gwpixmaphandle
, (**pixpat
).patMap
);
2071 imageSize
= GetPixRowBytes((**pixpat
).patMap
) *
2072 ((**(**pixpat
).patMap
).bounds
.bottom
-
2073 (**(**pixpat
).patMap
).bounds
.top
);
2075 PtrToHand( (**gwpixmaphandle
).baseAddr
, &image
, imageSize
);
2076 (**pixpat
).patData
= image
;
2079 CTabHandle ctable
= ((**((**pixpat
).patMap
)).pmTable
) ;
2080 ColorSpecPtr ctspec
= (ColorSpecPtr
) &(**ctable
).ctTable
;
2081 if ( ctspec
[0].rgb
.red
== 0x0000 )
2083 ctspec
[1].rgb
= MAC_WXCOLORREF( m_textBackgroundColour
.GetPixel()) ;
2084 ctspec
[0].rgb
= MAC_WXCOLORREF( m_textForegroundColour
.GetPixel()) ;
2088 ctspec
[0].rgb
= MAC_WXCOLORREF( m_textBackgroundColour
.GetPixel()) ;
2089 ctspec
[1].rgb
= MAC_WXCOLORREF( m_textForegroundColour
.GetPixel()) ;
2091 ::CTabChanged( ctable
) ;
2093 ::PenPixPat(pixpat
);
2094 m_macForegroundPixMap
= pixpat
;
2096 UnlockPixels( gwpixmaphandle
) ;
2100 ::PenPat(GetQDGlobalsBlack(&blackColor
));
2103 short mode
= patCopy
;
2104 switch( m_logicalFunction
)
2107 if ( backgroundTransparent
)
2112 case wxINVERT
: // NOT dst
2113 if ( !backgroundTransparent
)
2115 ::PenPat(GetQDGlobalsBlack(&blackColor
));
2119 case wxXOR
: // src XOR dst
2122 case wxOR_REVERSE
: // src OR (NOT dst)
2125 case wxSRC_INVERT
: // (NOT src)
2132 case wxAND_REVERSE
:// src AND (NOT dst)
2133 case wxAND
: // src AND dst
2134 case wxAND_INVERT
: // (NOT src) AND dst
2135 case wxNO_OP
: // dst
2136 case wxNOR
: // (NOT src) AND (NOT dst)
2137 case wxEQUIV
: // (NOT src) XOR dst
2138 case wxOR_INVERT
: // (NOT src) OR dst
2139 case wxNAND
: // (NOT src) OR (NOT dst)
2140 case wxOR
: // src OR dst
2142 // case wxSRC_OR: // source _bitmap_ OR destination
2143 // case wxSRC_AND: // source _bitmap_ AND destination
2147 m_macBrushInstalled
= true ;
2148 m_macPenInstalled
= false ;
2149 m_macFontInstalled
= false ;
2152 // ---------------------------------------------------------------------------
2153 // coordinates transformations
2154 // ---------------------------------------------------------------------------
2157 wxCoord
wxDCBase::DeviceToLogicalX(wxCoord x
) const
2159 return ((wxDC
*)this)->XDEV2LOG(x
);
2162 wxCoord
wxDCBase::DeviceToLogicalY(wxCoord y
) const
2164 return ((wxDC
*)this)->YDEV2LOG(y
);
2167 wxCoord
wxDCBase::DeviceToLogicalXRel(wxCoord x
) const
2169 return ((wxDC
*)this)->XDEV2LOGREL(x
);
2172 wxCoord
wxDCBase::DeviceToLogicalYRel(wxCoord y
) const
2174 return ((wxDC
*)this)->YDEV2LOGREL(y
);
2177 wxCoord
wxDCBase::LogicalToDeviceX(wxCoord x
) const
2179 return ((wxDC
*)this)->XLOG2DEV(x
);
2182 wxCoord
wxDCBase::LogicalToDeviceY(wxCoord y
) const
2184 return ((wxDC
*)this)->YLOG2DEV(y
);
2187 wxCoord
wxDCBase::LogicalToDeviceXRel(wxCoord x
) const
2189 return ((wxDC
*)this)->XLOG2DEVREL(x
);
2192 wxCoord
wxDCBase::LogicalToDeviceYRel(wxCoord y
) const
2194 return ((wxDC
*)this)->YLOG2DEVREL(y
);