What is the difference between CGContextAddLineToPoint and addLineToPoint function in UIBezierPath? - ios

I have rendered some basic shapes using quartz-2d. I came across two methods to draw a line. First is to get a context using UIGraphicsGetCurrentContext() and then draw the line using CGContextAddLineToPoint.
And other way is to define a UIBezierPath object and draw using its function addLineToPoint
[bezierPath addLineToPoint:CGPointMake(10, 10)];
And then I have to add bezierPath to the context using CGContextAddPath.
So I wanted to know the difference between these two approaches as both are used to draw only a line. Is there a performance issue between these two? Also which method is better under what circumstances.

The UIBezierPath is an object from the UIKit, and allow you to use a set of function mixing particular curve with control point but also with a normal line.
Being an object from the UIKit you are not able to use CGContextAddLineToPoint, but anyway at the end you need to add the path in the context with CGContextAddPath.
With CGContexAddLineToPoint instead you draw directly on the context.
So my suggest is to use this last way if you have not particular reasons (like amazing curve with different control point). Otherwise, use UIBezierPath.

The CGContextAdd.. functions are lower-level C Quartz2D API that bridge between CGContext and CGPathRef instances. You use a CGContext when you want to draw something, while CGPathRef is the structure that manages geometric shapes.
On the other hand, UIBezierPath is an Objective-C UIKit class that wraps around CGPath, and provides also some bridge to CGContext functions, for example with setFill, setStroke, fill or stroke methods.
Is totally safe to mix the two approaches, but it's sure that CGContext gives you more tools. Performance and memory are better with direct CGContext calls, but performance difference are absolutely negligible in 99% of the cases.

Related

UIBezierPath fill vs CAShapeLayer

I'm trying to draw a simple shape as part of the interface of a game, and most tutorials use a UIBezierPath to define the path of a CAShapeLayer. However, I noticed that UIBezierPath already has an existing fill function.
This is probably a stupid question, but what is the difference between using that and using a separate CAShapeLayer to draw the path? Also, which one is better?
The "CA" in CAShapeLayer stands for CoreAnimation.
If you wish to animate, move, manipulate, or well, anything else to a UIBezierPath, you need to use a CALayer (or it's subclass CAShapeLayer).
UIBezierPaths are the correct thing to use if what you want is to simply "draw" - and it's usually done in draw(rect:). You can also "redraw" if you will.
But if you want persistence (and control) over a shape, turn that UIBezierPath into a CAShapeLayer.

If I want to manipulate the control points in a path by touching the path, would it be better to use uibezierpath or core graphics?

I want to draw a path and then change it's shape by touching the control points of the path, would it be better to use uibezierpath or core graphics for this purpose and why? I want to get access to the path after im done with modifying it's shape. Thank you.
You're going to want to keep the control points in your own data structure, because neither UIBezierPath nor CGPath provides a convenient way to get at or modify the existing control points of the path.
That said, it's generally easier to use the UIKit drawing API if it covers your needs, so you'll want to convert your data structure to a UIBezierPath to draw it each time the user makes a change.

Can a CAShapeLayer be passed to CGContextDrawLayerAtPoint?

I've got a CAShapeLayer and was trying to draw it by passing it to CGContextDrawLayerAtPoint but get an error about passing a retainable parameter of CAShapeLayer *__strong to a function expecting a CGLayerRef.
I've done some browsing but can't figure out how to convert it/bridge the CAShapeLayer to the CGLayerRef.
If its not possible to convert, then can a CAShapeLayer be created using CGLayerCreateWithContext?
What I'm doing is creating a drawing with a UIBezierPath, then creating a CAShapeLayer and setting its path to the UIBezierPath then I want to display it. I could use addSublayer to display the shape layer however I'm going to display the same shape at multiple different points so rather than add multiple sublayers I was planning on using CGContextDrawLayerAtPoint to display it at different points.
Short answer: no.
Long answer: CAShapeLayer is a Core Animation layer (CALayer). You put it into your interface and it draws itself.
I know it's confusing, the way they use the word "layer", but CGContextDrawLayerAtPoint has nothing to do with that (it's using the word "layer" in a totally different way, referring to a CGLayer, which is completely different and is used utterly differently). You've gone down the wrong rabbit hole here.
I could use addSublayer: to display the shape layer
Not could. Must. That is what you do with a CAShapeLayer.
The alternative you are looking for would be to pull the CGPath out of the CAShapeLayer and assign that path and stroke it, multiple times in multiple places, in a CGContext. But there is really no need to do that. iOS drawing is all about layers; don't be afraid of having multiple sublayers.

drawing shadow using core graphic and using CALayer

As far as I know we can use core graphic such as CGContextSetShadowWithColor to draw a shadow. However, we can also use CALayer to show the shadow as well.
Question :
what are the differences between 2 of them. Are there any rules to determine when we use core graphic to draw a or when we use CALayer to do the job
I would have to say that using CoreAnimation is always preferred over CoreGraphics, since it's more high level, and abstracts the low-level details of drawing the shadow. (It may also allow apple to optimize the shadow drawing without hurting your code syntax).
However, there are times where you are overriding drawRect: anyways, and you have very specific use for the shadow, not the whole view's layer. You might wanna use CoreGraphics shadows here.
One last note, CoreAnimation gradients are much faster when rendering, take my word for it. I used it on UITableViewCell, and the scroll performance significantly increased, as opposed to using CoreGraphics Gradients. That comes at a price, though. It's a bit worse-looking.

Quartz2D drawing without using drawRect:(CGRect)rect method

In Quartz2D, can I draw any shapes without using drawRect:(CGRect)rect method?
Yes. If you want to draw to a bitmap (as one example) and produce a CGImage, you could certainly create a CGBitmapContext, then use CoreGraphics as usual using that as your context.
If you want to draw to the display, do your work from within drawRect:, using the supplied graphics context.

Resources