Skip to content

Commit

Permalink
[OSX] Reintroduce Cocoa System.Drawing support
Browse files Browse the repository at this point in the history
The old Cocoa backend for System.Drawing appears to still work.  You must
pass in a NSView.Handle while in the DrawRect method, or with lockFocus
called to prepare the NSGraphicsContext.
  • Loading branch information
Geoff Norton committed Oct 30, 2010
1 parent 32832e3 commit 44dc98d
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 15 deletions.
2 changes: 1 addition & 1 deletion mcs/class/System.Drawing/System.Drawing.dll.sources
Expand Up @@ -8,7 +8,7 @@ System.Drawing/BufferedGraphics.cs
System.Drawing/BufferedGraphicsManager.cs
System.Drawing/BufferedGraphicsContext.cs
System.Drawing/CharacterRange.cs
System.Drawing/carbonFunctions.cs
System.Drawing/macFunctions.cs
System.Drawing/ColorConverter.cs
System.Drawing/Color.cs
System.Drawing/ColorTranslator.cs
Expand Down
29 changes: 21 additions & 8 deletions mcs/class/System.Drawing/System.Drawing/Graphics.cs
Expand Up @@ -49,7 +49,7 @@ public sealed class Graphics : MarshalByRefObject, IDisposable
#endif
{
internal IntPtr nativeObject = IntPtr.Zero;
internal CarbonContext context;
internal IMacContext maccontext;
private bool disposed = false;
private static float defDpiX = 0;
private static float defDpiY = 0;
Expand Down Expand Up @@ -190,6 +190,8 @@ public void CopyFromScreen (int sourceX, int sourceY, int destinationX, int dest
CopyFromScreenX11 (sourceX, sourceY, destinationX, destinationY, blockRegionSize, copyPixelOperation);
} else if (GDIPlus.UseCarbonDrawable) {
CopyFromScreenMac (sourceX, sourceY, destinationX, destinationY, blockRegionSize, copyPixelOperation);
} else if (GDIPlus.UseCocoaDrawable) {
CopyFromScreenMac (sourceX, sourceY, destinationX, destinationY, blockRegionSize, copyPixelOperation);
} else {
CopyFromScreenWin32 (sourceX, sourceY, destinationX, destinationY, blockRegionSize, copyPixelOperation);
}
Expand Down Expand Up @@ -293,11 +295,11 @@ public void Dispose ()
{
Status status;
if (! disposed) {
if (GDIPlus.UseCarbonDrawable && context.ctx != IntPtr.Zero) {
if (GDIPlus.UseCarbonDrawable || GDIPlus.UseCocoaDrawable) {
Flush ();
Carbon.CGContextSynchronize (context.ctx);
Carbon.ReleaseContext (context.port, context.ctx);
maccontext.Release ();
}

status = GDIPlus.GdipDeleteGraphics (nativeObject);
nativeObject = IntPtr.Zero;
GDIPlus.CheckStatus (status);
Expand Down Expand Up @@ -1681,8 +1683,9 @@ public void Flush (FlushIntention intention)

Status status = GDIPlus.GdipFlush (nativeObject, intention);
GDIPlus.CheckStatus (status);
if (GDIPlus.UseCarbonDrawable && context.ctx != IntPtr.Zero)
Carbon.CGContextSynchronize (context.ctx);

if (maccontext != null)
maccontext.Synchronize ();
}

[EditorBrowsable (EditorBrowsableState.Advanced)]
Expand Down Expand Up @@ -1714,12 +1717,22 @@ public static Graphics FromHwnd (IntPtr hwnd)
{
IntPtr graphics;

if (GDIPlus.UseCocoaDrawable) {
CocoaContext context = MacSupport.GetCGContextForNSView (hwnd);
GDIPlus.GdipCreateFromContext_macosx (context.ctx, context.width, context.height, out graphics);

Graphics g = new Graphics (graphics);
g.maccontext = context;

return g;
}

if (GDIPlus.UseCarbonDrawable) {
CarbonContext context = Carbon.GetCGContextForView (hwnd);
CarbonContext context = MacSupport.GetCGContextForView (hwnd);
GDIPlus.GdipCreateFromContext_macosx (context.ctx, context.width, context.height, out graphics);

Graphics g = new Graphics (graphics);
g.context = context;
g.maccontext = context;

return g;
}
Expand Down
5 changes: 3 additions & 2 deletions mcs/class/System.Drawing/System.Drawing/gdipFunctions.cs
Expand Up @@ -61,6 +61,7 @@ internal class GDIPlus {
public static IntPtr Display = IntPtr.Zero;
public static bool UseX11Drawable = false;
public static bool UseCarbonDrawable = false;
public static bool UseCocoaDrawable = false;

#region gdiplus.dll functions

Expand Down Expand Up @@ -138,12 +139,12 @@ static GDIPlus ()

static public bool RunningOnWindows ()
{
return !UseX11Drawable && !UseCarbonDrawable;
return !UseX11Drawable && !UseCarbonDrawable && !UseCocoaDrawable;
}

static public bool RunningOnUnix ()
{
return UseX11Drawable || UseCarbonDrawable;
return UseX11Drawable || UseCarbonDrawable || UseCocoaDrawable;
}

// Copies a Ptr to an array of Points and releases the memory
Expand Down
Expand Up @@ -36,9 +36,9 @@ namespace System.Drawing {

[SuppressUnmanagedCodeSecurity]
#if NET_2_0
internal static class Carbon {
internal static class MacSupport {
#else
internal sealed class Carbon {
internal sealed class MacSupport {
#endif
internal static Hashtable contextReference = new Hashtable ();
internal static object lockobj = new object ();
Expand All @@ -52,7 +52,7 @@ internal sealed class Carbon {
internal static int debug_threshold = 1;
#endif

static Carbon () {
static MacSupport () {
foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies ()) {
if (String.Equals (asm.GetName ().Name, "System.Windows.Forms")) {
Type driver_type = asm.GetType ("System.Windows.Forms.XplatUICarbon");
Expand All @@ -63,6 +63,16 @@ internal sealed class Carbon {
}
}

internal static CocoaContext GetCGContextForNSView (IntPtr handle) {
IntPtr graphicsContext = objc_msgSend (objc_getClass ("NSGraphicsContext"), sel_registerName ("currentContext"));
IntPtr ctx = objc_msgSend (graphicsContext, sel_registerName ("graphicsPort"));
Rect bounds = new Rect ();

objc_msgSend_stret (ref bounds, handle, sel_registerName ("bounds"));

return new CocoaContext (ctx, (int) bounds.size.width, (int) bounds.size.height);
}

internal static CarbonContext GetCGContextForView (IntPtr handle) {
IntPtr context = IntPtr.Zero;
IntPtr port = IntPtr.Zero;
Expand Down Expand Up @@ -289,7 +299,7 @@ internal struct QDRect
public short right;
}

internal struct CarbonContext
internal struct CarbonContext : IMacContext
{
public IntPtr port;
public IntPtr ctx;
Expand All @@ -303,5 +313,44 @@ public CarbonContext (IntPtr port, IntPtr ctx, int width, int height)
this.width = width;
this.height = height;
}

public void Synchronize ()
{
MacSupport.CGContextSynchronize (ctx);
}

public void Release ()
{
MacSupport.ReleaseContext (port, ctx);
}
}

internal struct CocoaContext : IMacContext
{
public IntPtr ctx;
public int width;
public int height;

public CocoaContext (IntPtr ctx, int width, int height)
{
this.ctx = ctx;
this.width = width;
this.height = height;
}

public void Synchronize ()
{
MacSupport.CGContextSynchronize (ctx);
}

public void Release ()
{
}
}

internal interface IMacContext
{
void Synchronize ();
void Release ();
}
}

0 comments on commit 44dc98d

Please sign in to comment.