Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Converting a Quartz method from iOS to OSX

I have this quartz class that works fine on iOS and draws an orange pizza slice style graph over a gray circle and I am trying to convert it to cocoa.

+ (UIImage *)circleWithDiameter:(CGFloat) diameter
                          color:(UIColor *)color
                       progress:(CGFloat)progress {


  CGFloat radius = diameter/2.0f;

  CGFloat scale = [[UIScreen mainScreen] scale];  // we need to size the graphics context according to the device scale

  CGRect rect = CGRectMake(0.0f, 0.0f, diameter, diameter);
  UIGraphicsBeginImageContextWithOptions(rect.size, NO, scale);
  CGContextRef context = UIGraphicsGetCurrentContext();


  // create a gray circle background
  CGContextSetLineWidth(context, 0); // set the line width

  CGContextSetFillColorWithColor(context, color.CGColor);

  CGContextBeginPath(context);
  CGContextAddEllipseInRect(context, rect);
  CGContextDrawPath(context, kCGPathFill); // Or kCGPathFill


  // Draw the slice  
  CGFloat angle = progress * 2.0f * M_PI; 

  CGPoint center = CGPointMake(radius, radius);

  CGContextBeginPath(context);
  CGContextMoveToPoint(context, center.x, center.y);

  CGPoint p1 = CGPointMake(center.x + radius * cosf(angle),
                           center.y + radius * sinf(angle));
  CGContextAddLineToPoint(context, p1.x, p1.y);
  CGContextMoveToPoint(context, center.x, center.y);
  CGContextAddArc(context, center.x, center.y, radius, 0.0f, angle, 0);
  CGContextClosePath(context);

  UIColor *orange = [UIColor orangeColor];
  CGContextSetFillColorWithColor(context, orange.CGColor);
  CGContextDrawPath(context, kCGPathFill);

  UIImage *result = UIGraphicsGetImageFromCurrentImageContext();

  CGContextRelease(context);

  return result;

}

This is the class I have converted to cocoa.

+ (NSImage *)circuloWithDiameter:(CGFloat)diameter
                          color:(NSColor *)color
                       progress:(CGFloat)progress {

  CGFloat radius = diameter/2.0f;

  CGContextRef context = [[NSGraphicsContext currentContext] graphicsPort];


  // draw the gray circle background
  CGContextSetLineWidth(context, 0); // set the line width

  CGContextSetFillColorWithColor(context, color.CGColor);

  CGContextBeginPath(context);
  CGContextAddEllipseInRect(context, rect);
  CGContextDrawPath(context, kCGPathFill); // Or kCGPathFill


  // draw the orange slice  
  CGFloat angle = progress * 2.0f * M_PI; 

  CGPoint center = CGPointMake(radius, radius);

  CGContextBeginPath(context);
  CGContextMoveToPoint(context, center.x, center.y);

  CGPoint p1 = CGPointMake(center.x + radius * cosf(angle),
                           center.y + radius * sinf(angle));
  CGContextAddLineToPoint(context, p1.x, p1.y);
  CGContextMoveToPoint(context, center.x, center.y);
  CGContextAddArc(context, center.x, center.y, radius, 0.0f, angle, 0);
  CGContextClosePath(context);

  NSColor *orange = [NSColor orangeColor];
  CGContextSetFillColorWithColor(context, orange.CGColor);
  CGContextDrawPath(context, kCGPathFill);


  CGImageRef imageRef = CGBitmapContextCreateImage(context);
  NSImage* result = [[NSImage alloc] initWithCGImage:imageRef size:NSMakeSize(diameter, diameter)];
  CFRelease(imageRef);


  CGContextRelease(context);

  return result;

}

Apparently the conversion goes fine and Xcode is not whining about anything but when the cocoa version runs, it crashes on the line

  CGImageRef imageRef = CGBitmapContextCreateImage(context);

with the message

<Error>: CGBitmapContextCreateImage: invalid context 0x600000160180. This is a serious error. This application, or a library it uses, is using an invalid context  and is thereby contributing to an overall degradation of system stability and reliability. This notice is a courtesy: please fix this problem. It will become a fatal error in an upcoming update.

what is wrong? any clues?

like image 927
Duck Avatar asked Dec 19 '22 08:12

Duck


1 Answers

The process is a little different in AppKit.

First you create an NSImage instance with the desired size. Then you use -[NSImage lockFocus] to initialize the drawing context. This replaces UIKit's UIGraphicsBeginImageContextWithOptions function.

From this point, your drawing code is the same as UIKit, using [[NSGraphicsContext currentContext] graphicsPort] to get the current CGContextRef.

When you finish drawing, use -[NSImage unlockFocus] to dispose of the current CGContextRef. You can then return the NSImage instance you created at the start of the function.

like image 107
Darren Avatar answered Jan 05 '23 05:01

Darren