/////////////////////////////////////////////////////////////////////////////
-// Name: src/osx/carbon/dccg.cpp
+// Name: src/osx/carbon/graphics.cpp
// Purpose: wxDC class
// Author: Stefan Csomor
// Modified by:
// constants
//-----------------------------------------------------------------------------
-#if !defined( __DARWIN__ ) || defined(__MWERKS__)
#ifndef M_PI
const double M_PI = 3.14159265358979;
#endif
-#endif
static const double RAD2DEG = 180.0 / M_PI;
CGColorRef wxMacCreateCGColor( const wxColour& col )
{
- CGColorRef retval = 0;
-#ifdef __WXMAC__
- retval = col.CreateCGColor();
-#else
-// TODO add conversion NSColor - CGColorRef (obj-c)
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
- if ( CGColorCreateGenericRGB )
- retval = CGColorCreateGenericRGB( col.Red() / 255.0 , col.Green() / 255.0, col.Blue() / 255.0, col.Alpha() / 255.0 );
- else
-#endif
- {
- CGFloat components[4] = { col.Red() / 255.0, col.Green() / 255.0, col.Blue() / 255.0, col.Alpha() / 255.0 } ;
- retval = CGColorCreate( wxMacGetGenericRGBColorSpace() , components ) ;
- }
+ CGColorRef retval = col.CreateCGColor();
-#endif
+ wxASSERT(retval != NULL);
return retval;
}
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 && wxOSX_USE_CORE_TEXT
+#if wxOSX_USE_CORE_TEXT
CTFontRef wxMacCreateCTFont( const wxFont& font )
{
public :
ImagePattern( const wxBitmap* bmp , const CGAffineTransform& transform )
{
- wxASSERT( bmp && bmp->Ok() );
+ wxASSERT( bmp && bmp->IsOk() );
#ifdef __WXMAC__
Init( (CGImageRef) bmp->CreateCGImage() , transform );
#endif
case wxPENSTYLE_STIPPLE:
{
wxBitmap* bmp = pen.GetStipple();
- if ( bmp && bmp->Ok() )
+ if ( bmp && bmp->IsOk() )
{
m_colorSpace.reset( CGColorSpaceCreatePattern( NULL ) );
m_pattern.reset( (CGPatternRef) *( new ImagePattern( bmp , CGAffineTransformMakeScale( 1,-1 ) ) ) );
{
// now brush is a bitmap
wxBitmap* bmp = brush.GetStipple();
- if ( bmp && bmp->Ok() )
+ if ( bmp && bmp->IsOk() )
{
m_isPattern = true;
m_patternColorComponents = new CGFloat[1] ;
#endif
}
-class wxMacCoreGraphicsBitmapData : public wxGraphicsObjectRefData
+class wxMacCoreGraphicsBitmapData : public wxGraphicsBitmapData
{
public:
wxMacCoreGraphicsBitmapData( wxGraphicsRenderer* renderer, CGImageRef bitmap, bool monochrome );
~wxMacCoreGraphicsBitmapData();
virtual CGImageRef GetBitmap() { return m_bitmap; }
+ virtual void* GetNativeBitmap() const { return m_bitmap; }
bool IsMonochrome() { return m_monochrome; }
+
+#if wxUSE_IMAGE
+ wxImage ConvertToImage() const
+ {
+ return wxBitmap(m_bitmap).ConvertToImage();
+ }
+#endif // wxUSE_IMAGE
+
private :
CGImageRef m_bitmap;
bool m_monochrome;
};
-wxMacCoreGraphicsBitmapData::wxMacCoreGraphicsBitmapData( wxGraphicsRenderer* renderer, CGImageRef bitmap, bool monochrome ) : wxGraphicsObjectRefData( renderer ),
+wxMacCoreGraphicsBitmapData::wxMacCoreGraphicsBitmapData( wxGraphicsRenderer* renderer, CGImageRef bitmap, bool monochrome ) : wxGraphicsBitmapData( renderer ),
m_bitmap(bitmap), m_monochrome(monochrome)
{
}
CGImageRelease( m_bitmap );
}
+
//
// Graphics Matrix
//
virtual void Transform( const wxGraphicsMatrixData* matrix );
// gets the bounding box enclosing all points (possibly including control points)
- virtual void GetBox(wxDouble *x, wxDouble *y, wxDouble *w, wxDouble *y) const;
+ virtual void GetBox(wxDouble *x, wxDouble *y, wxDouble *w, wxDouble *h) const;
virtual bool Contains( wxDouble x, wxDouble y, wxPolygonFillMode fillStyle = wxODDEVEN_RULE) const;
private :
wxMacCoreGraphicsContext( wxGraphicsRenderer* renderer);
- wxMacCoreGraphicsContext();
-
~wxMacCoreGraphicsContext();
void Init();
- // returns the size of the graphics context in device coordinates
- virtual void GetSize( wxDouble* width, wxDouble* height);
-
virtual void StartPage( wxDouble width, wxDouble height );
virtual void EndPage();
virtual bool SetAntialiasMode(wxAntialiasMode antialias);
+ virtual bool SetInterpolationQuality(wxInterpolationQuality interpolation);
+
virtual bool SetCompositionMode(wxCompositionMode op);
virtual void BeginLayer(wxDouble opacity);
virtual bool ShouldOffset() const
{
+ if ( !m_enableOffset )
+ return false;
+
int penwidth = 0 ;
if ( !m_pen.IsNull() )
{
virtual void DrawBitmap( const wxGraphicsBitmap &bmp, wxDouble x, wxDouble y, wxDouble w, wxDouble h );
virtual void DrawIcon( const wxIcon &icon, wxDouble x, wxDouble y, wxDouble w, wxDouble h );
+
+ // fast convenience methods
+
+
+ virtual void DrawRectangle( wxDouble x, wxDouble y, wxDouble w, wxDouble h );
void SetNativeContext( CGContextRef cg );
- DECLARE_DYNAMIC_CLASS_NO_COPY(wxMacCoreGraphicsContext)
+ wxDECLARE_NO_COPY_CLASS(wxMacCoreGraphicsContext);
private:
bool EnsureIsValid();
+ void CheckInvariants() const;
virtual void DoDrawText( const wxString &str, wxDouble x, wxDouble y );
virtual void DoDrawRotatedText( const wxString &str, wxDouble x, wxDouble y, wxDouble angle );
#endif
bool m_contextSynthesized;
CGAffineTransform m_windowTransform;
- wxDouble m_width;
- wxDouble m_height;
bool m_invisible;
#if wxOSX_USE_COCOA_OR_CARBON
// wxMacCoreGraphicsContext implementation
//-----------------------------------------------------------------------------
-IMPLEMENT_DYNAMIC_CLASS(wxMacCoreGraphicsContext, wxGraphicsContext)
-
class wxQuartzOffsetHelper
{
public :
m_view = NULL;
#endif
m_invisible = false;
+ m_antialias = wxANTIALIAS_DEFAULT;
+ m_interpolation = wxINTERPOLATION_DEFAULT;
}
wxMacCoreGraphicsContext::wxMacCoreGraphicsContext( wxGraphicsRenderer* renderer, CGContextRef cgcontext, wxDouble width, wxDouble height ) : wxGraphicsContext(renderer)
{
Init();
m_windowRef = window;
+ m_enableOffset = true;
}
#endif
{
Init();
+ m_enableOffset = true;
wxSize sz = window->GetSize();
m_width = sz.x;
m_height = sz.y;
Init();
}
-wxMacCoreGraphicsContext::wxMacCoreGraphicsContext() : wxGraphicsContext(NULL)
-{
- Init();
- wxLogDebug(wxT("Illegal Constructor called"));
-}
-
wxMacCoreGraphicsContext::~wxMacCoreGraphicsContext()
{
SetNativeContext(NULL);
}
-void wxMacCoreGraphicsContext::GetSize( wxDouble* width, wxDouble* height)
+
+void wxMacCoreGraphicsContext::CheckInvariants() const
{
- *width = m_width;
- *height = m_height;
+ // check invariants here for debugging ...
}
+
void wxMacCoreGraphicsContext::StartPage( wxDouble width, wxDouble height )
{
CGRect r;
bool wxMacCoreGraphicsContext::EnsureIsValid()
{
+ CheckInvariants();
+
if ( !m_cgContext )
{
if (m_invisible)
if ( m_cgContext )
{
CGContextSaveGState( m_cgContext );
- CGContextConcatCTM( m_cgContext, m_windowTransform );
- CGContextSetTextMatrix( m_cgContext, CGAffineTransformIdentity );
- m_contextSynthesized = true;
#if wxOSX_USE_COCOA_OR_CARBON
if ( m_clipRgn.get() )
{
- // the clip region is in device coordinates, so we convert this again to user coordinates
wxCFRef<HIMutableShapeRef> hishape( HIShapeCreateMutableCopy( m_clipRgn ) );
- CGPoint transformedOrigin = CGPointApplyAffineTransform( CGPointZero,m_windowTransform);
- HIShapeOffset( hishape, -transformedOrigin.x, -transformedOrigin.y );
// if the shape is empty, HIShapeReplacePathInCGContext doesn't work
if ( HIShapeIsEmpty(hishape))
{
}
}
#endif
+ CGContextConcatCTM( m_cgContext, m_windowTransform );
+ CGContextSetTextMatrix( m_cgContext, CGAffineTransformIdentity );
+ m_contextSynthesized = true;
CGContextSaveGState( m_cgContext );
#if 0 // turn on for debugging of clientdc
#endif
}
}
+ CheckInvariants();
+
return m_cgContext != NULL;
}
return false;
}
CGContextSetShouldAntialias(m_cgContext, antialiasMode);
+ CheckInvariants();
+ return true;
+}
+
+bool wxMacCoreGraphicsContext::SetInterpolationQuality(wxInterpolationQuality interpolation)
+{
+ if (!EnsureIsValid())
+ return true;
+
+ if (m_interpolation == interpolation)
+ return true;
+
+ m_interpolation = interpolation;
+ CGInterpolationQuality quality;
+
+ switch (interpolation)
+ {
+ case wxINTERPOLATION_DEFAULT:
+ quality = kCGInterpolationDefault;
+ break;
+ case wxINTERPOLATION_NONE:
+ quality = kCGInterpolationNone;
+ break;
+ case wxINTERPOLATION_FAST:
+ quality = kCGInterpolationLow;
+ break;
+ case wxINTERPOLATION_GOOD:
+#if wxOSX_USE_COCOA_OR_CARBON
+ quality = UMAGetSystemVersion() < 0x1060 ? kCGInterpolationHigh : (CGInterpolationQuality) 4 /*kCGInterpolationMedium only on 10.6*/;
+#else
+ quality = kCGInterpolationMedium;
+#endif
+ break;
+ case wxINTERPOLATION_BEST:
+ quality = kCGInterpolationHigh;
+ break;
+ default:
+ return false;
+ }
+ CGContextSetInterpolationQuality(m_cgContext, quality);
+ CheckInvariants();
return true;
}
if (m_composition == wxCOMPOSITION_DEST)
return true;
-#if wxOSX_USE_COCOA_OR_CARBON
- if ( UMAGetSystemVersion() < 0x1060 )
+ // TODO REMOVE if we don't need it because of bugs in 10.5
+#if 0
{
CGCompositeOperation cop = kCGCompositeOperationSourceOver;
CGBlendMode mode = kCGBlendModeNormal;
case wxCOMPOSITION_XOR:
cop = kCGCompositeOperationXOR;
break;
-#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5
case wxCOMPOSITION_ADD:
mode = kCGBlendModePlusLighter ;
break;
-#endif
default:
return false;
}
CGContextSetBlendMode(m_cgContext, mode);
}
#endif
-#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5
- else
{
CGBlendMode mode = kCGBlendModeNormal;
switch( op )
mode = kCGBlendModeDestinationAtop;
break;
case wxCOMPOSITION_XOR:
- mode = kCGBlendModeXOR;
+ mode = kCGBlendModeExclusion; // Not kCGBlendModeXOR!
break;
case wxCOMPOSITION_ADD:
}
CGContextSetBlendMode(m_cgContext, mode);
}
-#endif
+
+ CheckInvariants();
return true;
}
void wxMacCoreGraphicsContext::BeginLayer(wxDouble opacity)
{
+ CheckInvariants();
CGContextSaveGState(m_cgContext);
CGContextSetAlpha(m_cgContext, (CGFloat) opacity);
CGContextBeginTransparencyLayer(m_cgContext, 0);
+ CheckInvariants();
}
void wxMacCoreGraphicsContext::EndLayer()
{
+ CheckInvariants();
CGContextEndTransparencyLayer(m_cgContext);
CGContextRestoreGState(m_cgContext);
+ CheckInvariants();
}
void wxMacCoreGraphicsContext::Clip( const wxRegion ®ion )
{
+ CheckInvariants();
#if wxOSX_USE_COCOA_OR_CARBON
if( m_cgContext )
{
// allow usage as measuring context
// wxASSERT_MSG( m_cgContext != NULL, "Needs a valid context for clipping" );
#endif
+ CheckInvariants();
}
// clips drawings to the rect
void wxMacCoreGraphicsContext::Clip( wxDouble x, wxDouble y, wxDouble w, wxDouble h )
{
+ CheckInvariants();
CGRect r = CGRectMake( (CGFloat) x , (CGFloat) y , (CGFloat) w , (CGFloat) h );
if ( m_cgContext )
{
// the clipping itself must be stored as device coordinates, otherwise
// we cannot apply it back correctly
r.origin= CGPointApplyAffineTransform( r.origin, m_windowTransform );
+ r.size= CGSizeApplyAffineTransform(r.size, m_windowTransform);
m_clipRgn.reset(HIShapeCreateWithRect(&r));
#else
// allow usage as measuring context
// wxFAIL_MSG( "Needs a valid context for clipping" );
#endif
}
+ CheckInvariants();
}
// resets the clipping to original extent
// wxFAIL_MSG( "Needs a valid context for clipping" );
#endif
}
+ CheckInvariants();
}
void wxMacCoreGraphicsContext::StrokePath( const wxGraphicsPath &path )
((wxMacCoreGraphicsPenData*)m_pen.GetRefData())->Apply(this);
CGContextAddPath( m_cgContext , (CGPathRef) path.GetNativePath() );
CGContextStrokePath( m_cgContext );
+
+ CheckInvariants();
}
void wxMacCoreGraphicsContext::DrawPath( const wxGraphicsPath &path , wxPolygonFillMode fillStyle )
CGContextAddPath( m_cgContext , (CGPathRef) path.GetNativePath() );
CGContextDrawPath( m_cgContext , mode );
+
+ CheckInvariants();
}
void wxMacCoreGraphicsContext::FillPath( const wxGraphicsPath &path , wxPolygonFillMode fillStyle )
else
CGContextFillPath( m_cgContext );
}
+
+ CheckInvariants();
}
void wxMacCoreGraphicsContext::SetNativeContext( CGContextRef cg )
if ( m_cgContext )
{
+ CheckInvariants();
CGContextRestoreGState( m_cgContext );
CGContextRestoreGState( m_cgContext );
if ( m_contextSynthesized )
return;
#ifdef __WXMAC__
- wxMacCoreGraphicsBitmapData* refdata =static_cast<wxMacCoreGraphicsBitmapData*>(bmp.GetRefData());
+ wxMacCoreGraphicsBitmapData* refdata = static_cast<wxMacCoreGraphicsBitmapData*>(bmp.GetRefData());
CGImageRef image = refdata->GetBitmap();
CGRect r = CGRectMake( (CGFloat) x , (CGFloat) y , (CGFloat) w , (CGFloat) h );
if ( refdata->IsMonochrome() == 1 )
{
- // is is a mask, the '1' in the mask tell where to draw the current brush
+ // is a mask, the '1' in the mask tell where to draw the current brush
if ( !m_brush.IsNull() )
{
if ( ((wxMacCoreGraphicsBrushData*)m_brush.GetRefData())->IsShading() )
wxMacDrawCGImage( m_cgContext , &r , image );
}
#endif
+
+ CheckInvariants();
}
void wxMacCoreGraphicsContext::DrawIcon( const wxIcon &icon, wxDouble x, wxDouble y, wxDouble w, wxDouble h )
if (m_composition == wxCOMPOSITION_DEST)
return;
- CGRect r = CGRectMake( (CGFloat) 0.0 , (CGFloat) 0.0 , (CGFloat) w , (CGFloat) h );
CGContextSaveGState( m_cgContext );
CGContextTranslateCTM( m_cgContext,(CGFloat) x ,(CGFloat) (y + h) );
CGContextScaleCTM( m_cgContext, 1, -1 );
#if wxOSX_USE_COCOA_OR_CARBON
+ CGRect r = CGRectMake( (CGFloat) 0.0 , (CGFloat) 0.0 , (CGFloat) w , (CGFloat) h );
PlotIconRefInContext( m_cgContext , &r , kAlignNone , kTransformNone ,
NULL , kPlotIconRefNormalFlags , icon.GetHICON() );
#endif
CGContextRestoreGState( m_cgContext );
+
+ CheckInvariants();
}
void wxMacCoreGraphicsContext::PushState()
return;
#if wxOSX_USE_CORE_TEXT
- if ( UMAGetSystemVersion() >= 0x1050 )
{
wxMacCoreGraphicsFontData* fref = (wxMacCoreGraphicsFontData*)m_font.GetRefData();
wxCFStringRef text(str, wxLocale::GetSystemEncoding() );
CTFontRef font = fref->OSXGetCTFont();
CGColorRef col = wxMacCreateCGColor( fref->GetColour() );
+#if 0
+ // right now there's no way to get continuous underlines, only words, so we emulate it
CTUnderlineStyle ustyle = fref->GetUnderlined() ? kCTUnderlineStyleSingle : kCTUnderlineStyleNone ;
wxCFRef<CFNumberRef> underlined( CFNumberCreate(NULL, kCFNumberSInt32Type, &ustyle) );
CFStringRef keys[] = { kCTFontAttributeName , kCTForegroundColorAttributeName, kCTUnderlineStyleAttributeName };
CFTypeRef values[] = { font, col, underlined };
+#else
+ CFStringRef keys[] = { kCTFontAttributeName , kCTForegroundColorAttributeName };
+ CFTypeRef values[] = { font, col };
+#endif
wxCFRef<CFDictionaryRef> attributes( CFDictionaryCreate(kCFAllocatorDefault, (const void**) &keys, (const void**) &values,
WXSIZEOF( keys ), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks) );
wxCFRef<CFAttributedStringRef> attrtext( CFAttributedStringCreate(kCFAllocatorDefault, text, attributes) );
y += CTFontGetAscent(font);
CGContextSaveGState(m_cgContext);
+ CGAffineTransform textMatrix = CGContextGetTextMatrix(m_cgContext);
+
CGContextTranslateCTM(m_cgContext, (CGFloat) x, (CGFloat) y);
CGContextScaleCTM(m_cgContext, 1, -1);
- CGContextSetTextPosition(m_cgContext, 0, 0);
+ CGContextSetTextMatrix(m_cgContext, CGAffineTransformIdentity);
+
CTLineDraw( line, m_cgContext );
+
+ if ( fref->GetUnderlined() ) {
+ //AKT: draw horizontal line 1 pixel thick and with 1 pixel gap under baseline
+ CGFloat width = CTLineGetTypographicBounds(line, NULL, NULL, NULL);
+
+ CGPoint points[] = { {0.0, -2.0}, {width, -2.0} };
+
+ CGContextSetStrokeColorWithColor(m_cgContext, col);
+ CGContextSetShouldAntialias(m_cgContext, false);
+ CGContextSetLineWidth(m_cgContext, 1.0);
+ CGContextStrokeLineSegments(m_cgContext, points, 2);
+ }
+
CGContextRestoreGState(m_cgContext);
- CFRelease( col );
+ CGContextSetTextMatrix(m_cgContext, textMatrix);
+ CGColorRelease( col );
+ CheckInvariants();
return;
}
#endif
CGContextRestoreGState(m_cgContext);
CFRelease( col );
#endif
+
+ CheckInvariants();
}
void wxMacCoreGraphicsContext::DoDrawRotatedText(const wxString &str,
return;
#if wxOSX_USE_CORE_TEXT
- if ( UMAGetSystemVersion() >= 0x1050 )
{
// default implementation takes care of rotation and calls non rotated DrawText afterwards
wxGraphicsContext::DoDrawRotatedText( str, x, y, angle );
wxASSERT_MSG( status == noErr , wxT("couldn't measure the rotated text") );
Rect rect;
- x += (int)(sin(angle) * FixedToInt(ascent));
- y += (int)(cos(angle) * FixedToInt(ascent));
+ x += (int)(sin(angle) * FixedToFloat(ascent));
+ y += (int)(cos(angle) * FixedToFloat(ascent));
status = ::ATSUMeasureTextImage( atsuLayout, kATSUFromTextBeginning, kATSUToTextEnd,
IntToFixed(x) , IntToFixed(y) , &rect );
CGContextRestoreGState(m_cgContext);
::ATSUDisposeTextLayout(atsuLayout);
+ CheckInvariants();
return;
}
// default implementation takes care of rotation and calls non rotated DrawText afterwards
wxGraphicsContext::DoDrawRotatedText( str, x, y, angle );
#endif
+
+ CheckInvariants();
}
void wxMacCoreGraphicsContext::GetTextExtent( const wxString &str, wxDouble *width, wxDouble *height,
return;
#if wxOSX_USE_CORE_TEXT
- if ( UMAGetSystemVersion() >= 0x1050 )
{
wxMacCoreGraphicsFontData* fref = (wxMacCoreGraphicsFontData*)m_font.GetRefData();
CTFontRef font = fref->OSXGetCTFont();
wxCFRef<CFAttributedStringRef> attrtext( CFAttributedStringCreate(kCFAllocatorDefault, text, attributes) );
wxCFRef<CTLineRef> line( CTLineCreateWithAttributedString(attrtext) );
- // round the returned extent: this is probably more correct anyhow but
- // we also need to do it to be consistent with GetPartialTextExtents()
- // below and avoid strange situation when the last partial extent
- // returned by it could have been greater than the full extent returned
- // by us
- CGFloat a, d, l;
- int w = CTLineGetTypographicBounds(line, &a, &d, &l) + 0.5;
+ CGFloat a, d, l, w;
+ w = CTLineGetTypographicBounds(line, &a, &d, &l);
if ( height )
*height = a+d+l;
&textBefore , &textAfter, &textAscent , &textDescent );
if ( height )
- *height = FixedToInt(textAscent + textDescent);
+ *height = FixedToFloat(textAscent + textDescent);
if ( descent )
- *descent = FixedToInt(textDescent);
+ *descent = FixedToFloat(textDescent);
if ( externalLeading )
*externalLeading = 0;
if ( width )
- *width = FixedToInt(textAfter - textBefore);
+ *width = FixedToFloat(textAfter - textBefore);
::ATSUDisposeTextLayout(atsuLayout);
*height = sz.height;
/*
if ( descent )
- *descent = FixedToInt(textDescent);
+ *descent = FixedToFloat(textDescent);
if ( externalLeading )
*externalLeading = 0;
*/
if ( width )
*width = sz.width;
#endif
+
+ CheckInvariants();
}
void wxMacCoreGraphicsContext::GetPartialTextExtents(const wxString& text, wxArrayDouble& widths) const
if (result != noErr || actualNumberOfBounds != 1 )
return;
- widths[pos] = FixedToInt( glyphBounds.upperRight.x - glyphBounds.upperLeft.x );
+ widths[pos] = FixedToFloat( glyphBounds.upperRight.x - glyphBounds.upperLeft.x );
//unsigned char uch = s[i];
}
#else
{
for ( int pos = 1; pos < (int)glyphCount ; pos ++ )
{
- widths[pos-1] = FixedToInt( layoutRecords[pos].realPos );
+ widths[pos-1] = FixedToFloat( layoutRecords[pos].realPos );
}
}
#if wxOSX_USE_IPHONE
// TODO core graphics text implementation here
#endif
+
+ CheckInvariants();
}
void * wxMacCoreGraphicsContext::GetNativeContext()
return m_cgContext;
}
+
+void wxMacCoreGraphicsContext::DrawRectangle( wxDouble x, wxDouble y, wxDouble w, wxDouble h )
+{
+ if (!EnsureIsValid())
+ return;
+
+ if (m_composition == wxCOMPOSITION_DEST)
+ return;
+
+ // when using shading, we have to go back to drawing paths
+ if ( !m_brush.IsNull() && ((wxMacCoreGraphicsBrushData*)m_brush.GetRefData())->IsShading() )
+ {
+ wxGraphicsContext::DrawRectangle( x,y,w,h );
+ return;
+ }
+
+ CGRect rect = CGRectMake( (CGFloat) x , (CGFloat) y , (CGFloat) w , (CGFloat) h );
+ if ( !m_brush.IsNull() )
+ {
+ ((wxMacCoreGraphicsBrushData*)m_brush.GetRefData())->Apply(this);
+ CGContextFillRect(m_cgContext, rect);
+ }
+
+ wxQuartzOffsetHelper helper( m_cgContext , ShouldOffset() );
+ if ( !m_pen.IsNull() )
+ {
+ ((wxMacCoreGraphicsPenData*)m_pen.GetRefData())->Apply(this);
+ CGContextStrokeRect(m_cgContext, rect);
+ }
+}
+
// concatenates this transform with the current transform of this context
void wxMacCoreGraphicsContext::ConcatTransform( const wxGraphicsMatrix& matrix )
{
// sets the transform of this context
void wxMacCoreGraphicsContext::SetTransform( const wxGraphicsMatrix& matrix )
{
+ CheckInvariants();
if ( m_cgContext )
{
CGAffineTransform transform = CGContextGetCTM( m_cgContext );
{
m_windowTransform = *(CGAffineTransform*) matrix.GetNativeMatrix();
}
+ CheckInvariants();
}
// gets the matrix of this context
return m;
}
+
+#if wxUSE_IMAGE
+
+// ----------------------------------------------------------------------------
+// wxMacCoreGraphicsImageContext
+// ----------------------------------------------------------------------------
+
+// This is a GC that can be used to draw on wxImage. In this implementation we
+// simply draw on a wxBitmap using wxMemoryDC and then convert it to wxImage in
+// the end so it's not especially interesting and exists mainly for
+// compatibility with the other platforms.
+class wxMacCoreGraphicsImageContext : public wxMacCoreGraphicsContext
+{
+public:
+ wxMacCoreGraphicsImageContext(wxGraphicsRenderer* renderer,
+ wxImage& image) :
+ wxMacCoreGraphicsContext(renderer),
+ m_image(image),
+ m_bitmap(image),
+ m_memDC(m_bitmap)
+ {
+ SetNativeContext
+ (
+ (CGContextRef)(m_memDC.GetGraphicsContext()->GetNativeContext())
+ );
+ m_width = image.GetWidth();
+ m_height = image.GetHeight();
+ }
+
+ virtual ~wxMacCoreGraphicsImageContext()
+ {
+ m_memDC.SelectObject(wxNullBitmap);
+ m_image = m_bitmap.ConvertToImage();
+ }
+
+private:
+ wxImage& m_image;
+ wxBitmap m_bitmap;
+ wxMemoryDC m_memDC;
+};
+
+#endif // wxUSE_IMAGE
+
//
// Renderer
//
virtual wxGraphicsContext * CreateContext( wxWindow* window );
+#if wxUSE_IMAGE
+ virtual wxGraphicsContext * CreateContextFromImage(wxImage& image);
+#endif // wxUSE_IMAGE
+
virtual wxGraphicsContext * CreateMeasuringContext();
// Path
// sets the font
virtual wxGraphicsFont CreateFont( const wxFont &font , const wxColour &col = *wxBLACK ) ;
+ virtual wxGraphicsFont CreateFont(double sizeInPixels,
+ const wxString& facename,
+ int flags = wxFONTFLAG_DEFAULT,
+ const wxColour& col = *wxBLACK);
// create a native bitmap representation
virtual wxGraphicsBitmap CreateBitmap( const wxBitmap &bitmap ) ;
+#if wxUSE_IMAGE
+ virtual wxGraphicsBitmap CreateBitmapFromImage(const wxImage& image);
+ virtual wxImage CreateImageFromBitmap(const wxGraphicsBitmap& bmp);
+#endif // wxUSE_IMAGE
+
// create a graphics bitmap from a native bitmap
virtual wxGraphicsBitmap CreateBitmapFromNativeBitmap( void* bitmap );
if (win_impl->GetWindow())
cgctx = (CGContextRef)(win_impl->GetWindow()->MacGetCGContextRef());
- if (cgctx != 0)
- return new wxMacCoreGraphicsContext( this, cgctx, (wxDouble) w, (wxDouble) h );
+ // having a cgctx being NULL is fine (will be created on demand)
+ // this is the case for all wxWindowDCs except wxPaintDC
+ wxMacCoreGraphicsContext *context =
+ new wxMacCoreGraphicsContext( this, cgctx, (wxDouble) w, (wxDouble) h );
+ context->EnableOffset(true);
+ return context;
}
return NULL;
}
{
int w, h;
mem_impl->GetSize( &w, &h );
- return new wxMacCoreGraphicsContext( this,
+ wxMacCoreGraphicsContext* context = new wxMacCoreGraphicsContext( this,
(CGContextRef)(mem_impl->GetGraphicsContext()->GetNativeContext()), (wxDouble) w, (wxDouble) h );
+ context->EnableOffset(true);
+ return context;
}
#endif
return NULL;
wxGraphicsContext * wxMacCoreGraphicsRenderer::CreateContextFromNativeWindow( void * window )
{
#if wxOSX_USE_CARBON
- return new wxMacCoreGraphicsContext(this,(WindowRef)window);
+ wxMacCoreGraphicsContext* context = new wxMacCoreGraphicsContext(this,(WindowRef)window);
+ context->EnableOffset(true);
+ return context;
#else
wxUnusedVar(window);
return NULL;
return new wxMacCoreGraphicsContext(this);
}
+#if wxUSE_IMAGE
+
+wxGraphicsContext*
+wxMacCoreGraphicsRenderer::CreateContextFromImage(wxImage& image)
+{
+ return new wxMacCoreGraphicsImageContext(this, image);
+}
+
+#endif // wxUSE_IMAGE
+
// Path
wxGraphicsPath wxMacCoreGraphicsRenderer::CreatePath()
wxGraphicsPen wxMacCoreGraphicsRenderer::CreatePen(const wxPen& pen)
{
- if ( !pen.Ok() || pen.GetStyle() == wxTRANSPARENT )
+ if ( !pen.IsOk() || pen.GetStyle() == wxTRANSPARENT )
return wxNullGraphicsPen;
else
{
wxGraphicsBrush wxMacCoreGraphicsRenderer::CreateBrush(const wxBrush& brush )
{
- if ( !brush.Ok() || brush.GetStyle() == wxTRANSPARENT )
+ if ( !brush.IsOk() || brush.GetStyle() == wxTRANSPARENT )
return wxNullGraphicsBrush;
else
{
wxGraphicsBitmap wxMacCoreGraphicsRenderer::CreateBitmap( const wxBitmap& bmp )
{
- if ( bmp.Ok() )
+ if ( bmp.IsOk() )
{
wxGraphicsBitmap p;
p.SetRefData(new wxMacCoreGraphicsBitmapData( this , bmp.CreateCGImage(), bmp.GetDepth() == 1 ) );
return wxNullGraphicsBitmap;
}
+#if wxUSE_IMAGE
+
+wxGraphicsBitmap
+wxMacCoreGraphicsRenderer::CreateBitmapFromImage(const wxImage& image)
+{
+ // We don't have any direct way to convert wxImage to CGImage so pass by
+ // wxBitmap. This makes this function pretty useless in this implementation
+ // but it allows to have the same API as with Cairo backend where we can
+ // convert wxImage to a Cairo surface directly, bypassing wxBitmap.
+ return CreateBitmap(wxBitmap(image));
+}
+
+wxImage wxMacCoreGraphicsRenderer::CreateImageFromBitmap(const wxGraphicsBitmap& bmp)
+{
+ wxMacCoreGraphicsBitmapData* const
+ data = static_cast<wxMacCoreGraphicsBitmapData*>(bmp.GetRefData());
+
+ return data ? data->ConvertToImage() : wxNullImage;
+}
+
+#endif // wxUSE_IMAGE
+
wxGraphicsBitmap wxMacCoreGraphicsRenderer::CreateBitmapFromNativeBitmap( void* bitmap )
{
if ( bitmap != NULL )
return p;
}
-// sets the font
wxGraphicsFont wxMacCoreGraphicsRenderer::CreateFont( const wxFont &font , const wxColour &col )
{
- if ( font.Ok() )
+ if ( font.IsOk() )
{
wxGraphicsFont p;
p.SetRefData(new wxMacCoreGraphicsFontData( this , font, col ));
return wxNullGraphicsFont;
}
+wxGraphicsFont
+wxMacCoreGraphicsRenderer::CreateFont(double sizeInPixels,
+ const wxString& facename,
+ int flags,
+ const wxColour& col)
+{
+ // This implementation is not ideal as we don't support fractional font
+ // sizes right now, but it's the simplest one.
+ //
+ // Notice that under Mac we always use 72 DPI so the font size in pixels is
+ // the same as the font size in points and we can pass it directly to wxFont
+ // ctor.
+ wxFont font(wxRound(sizeInPixels),
+ wxFONTFAMILY_DEFAULT,
+ flags & wxFONTFLAG_ITALIC ? wxFONTSTYLE_ITALIC
+ : wxFONTSTYLE_NORMAL,
+ flags & wxFONTFLAG_BOLD ? wxFONTWEIGHT_BOLD
+ : wxFONTWEIGHT_NORMAL,
+ (flags & wxFONTFLAG_UNDERLINED) != 0,
+ facename);
+
+ wxGraphicsFont f;
+ f.SetRefData(new wxMacCoreGraphicsFontData(this, font, col));
+ return f;
+}
+
//
// CoreGraphics Helper Methods
//