draw a stroke around the shape, core graphic - objective-c

I am drawing a shape like following :
- (void)drawRect:(CGRect)rect
{
// Draw a cross rectagle
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context);
CGContextMoveToPoint(context, 190, 0);
CGContextAddLineToPoint(context, 220, 0);
CGContextAddLineToPoint(context, 310, 90);
CGContextAddLineToPoint(context, 310, 120);
CGContextSetFillColorWithColor(context, [UIColor lightGrayColor].CGColor);
CGContextFillPath(context);
CGContextRestoreGState(context);
}
I am getting a light-dark cross flag below
Now I would like to draw a stroke around the cross flag I have just drawn
What should I do to achieve this. Please advice me on this issue.
Thanks.

Surely CGContextDrawPath(context, kCGPathFillStroke); is what you're after
You can adjust the pattern and color using:
CGContextSetStrokePattern
CGContextSetStrokeColor
https://developer.apple.com/library/ios/#documentation/graphicsimaging/reference/CGContext/Reference/reference.html
So, in your case, assuming you want a plain black stroke, you'd have:
- (void)drawRect:(CGRect)rect
{
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context);
CGContextSetLineWidth(context, 2.0);
CGContextSetStrokeColorWithColor(context, [UIColor blackColor].CGColor);
CGContextSetFillColorWithColor(context, [UIColor lightGrayColor].CGColor);
CGContextMoveToPoint(context, 190, 0);
CGContextAddLineToPoint(context, 220, 0);
CGContextAddLineToPoint(context, 310, 90);
CGContextAddLineToPoint(context, 310, 120);
CGContextClosePath(context);
CGContextDrawPath(context, kCGPathFillStroke);
CGContextFillPath(context);
CGContextRestoreGState(context);
}
Produces:

- (void)drawRect:(CGRect)rect
{
// Draw a cross rectagle
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context);
//New
CGContextSetLineWidth(context, 2.0);
CGContextMoveToPoint(context, 190, 0);
CGContextAddLineToPoint(context, 220, 0);
CGContextAddLineToPoint(context, 310, 90);
CGContextAddLineToPoint(context, 310, 120);
//New
CGContextSetStrokeColorWithColor(context, [UIColor blackColor].CGColor);
CGContextSetFillColorWithColor(context, [UIColor lightGrayColor].CGColor);
CGContextFillPath(context);
//New
CGContextStrokePath(context);
CGContextRestoreGState(context);
}
#WDUK :after spending hours to figure it out, I know why your above answer is not working.
The reason is when you do CGContextFillPath first, the path is eventually cleared and then you can no long do CGContextStrokePath on it again.
Therefore in order to do CGContextFillPath and CGContextStrokePath, we have to do
CGContextDrawPath(context, kCGPathFillStroke);
After trying it , I am getting the following

Related

drawing a Line in a couple of frames with Quartz 2d [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
I am an Objective C Programmer. I am developing a universal App.
In this App i want to use Quartz to draw a square, but not completely in one frame, rather frame for frame. In the Code below there is a possibility. But its not so good, because i want to draw rectangles, circles and other stuff. So, is there a better way to draw such things.
-(void)drawRect:(CGRect)rect {
[self drawARect];
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetLineWidth(context, 20.0);
CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
CGFloat components[] = {0.0, 0.0, 1.0, 1.0};
CGColorRef color = CGColorCreate(colorspace, components);
CGContextSetStrokeColorWithColor(context, color);
if (!firstLineReady) {
CGContextMoveToPoint(context, 200, 200);
CGContextAddLineToPoint(context, x, y);
}
if (firstLineReady && !secondLineReady) {
CGContextMoveToPoint(context, 200, 200);
CGContextAddLineToPoint(context, 600, 200);
CGContextMoveToPoint(context, 600, 200);
CGContextAddLineToPoint(context, x, y);
}
if (secondLineReady && !thirdLineReady) {
CGContextMoveToPoint(context, 200, 200);
CGContextAddLineToPoint(context, 600, 200);
CGContextMoveToPoint(context, 600, 200);
CGContextAddLineToPoint(context, 600, 600);
CGContextMoveToPoint(context, 600, 600);
CGContextAddLineToPoint(context, x, y);
}
if (thirdLineReady && ! fourthLineReady) {
CGContextMoveToPoint(context, 200, 200);
CGContextAddLineToPoint(context, 600, 200);
CGContextMoveToPoint(context, 600, 200);
CGContextAddLineToPoint(context, 600, 600);
CGContextMoveToPoint(context, 600, 600);
CGContextAddLineToPoint(context, 200, 600);
CGContextMoveToPoint(context, 200, 600);
CGContextAddLineToPoint(context, x, y);
}
if (fourthLineReady) {
CGContextMoveToPoint(context, 200, 200);
CGContextAddLineToPoint(context, 600, 200);
CGContextMoveToPoint(context, 600, 200);
CGContextAddLineToPoint(context, 600, 600);
CGContextMoveToPoint(context, 600, 600);
CGContextAddLineToPoint(context, 200, 600);
CGContextMoveToPoint(context, 200, 600);
CGContextAddLineToPoint(context, 200, 200);
[timer invalidate];
}
CGContextStrokePath(context);
CGColorSpaceRelease(colorspace);
CGColorRelease(color);
}
- (void) drawARect{
if (!firstLineReady) {
x+=speed; y+=0;
if (x>=600) {
x=600;
firstLineReady = YES;
}
}
if (firstLineReady && !secondLineReady ) {
x+=0; y+=speed;
if (y>=600) {
y=600;
secondLineReady = YES;
}
}
if (firstLineReady && secondLineReady && !thirdLineReady ) {
x-=speed; y+=0;
if (x<=200) {
x=200;
thirdLineReady = YES;
}
}
if (firstLineReady && secondLineReady && thirdLineReady ) {
x+=0; y-=speed;
if (y<=200) {
y=200;
fourthLineReady = YES;
}
}
}
Is it possible to give the CGContextAddLineToPoint a custom Pattern like a pencil or a biro?
Oval
CGRect aRect= CGRectMake(80, 80, 160, 100);
CGContextSetRGBStrokeColor(context, 0.6, 0.9, 0, 1.0);
CGContextSetLineWidth(context, 3.0);
CGContextAddEllipseInRect(context, aRect); //椭圆
CGContextDrawPath(context, kCGPathStroke);
Diamond
CGContextSetLineWidth(context, 2.0);
CGContextSetStrokeColorWithColor(context, [UIColor blueColor].CGColor);
CGContextMoveToPoint(context, 100, 100);
CGContextAddLineToPoint(context, 150, 150);
CGContextAddLineToPoint(context, 100, 200);
CGContextAddLineToPoint(context, 50, 150);
CGContextAddLineToPoint(context, 100, 100);
CGContextStrokePath(context);
Rectangle
CGContextSetLineWidth(context, 2.0);
CGContextSetStrokeColorWithColor(context, [UIColor blueColor].CGColor);
CGRect rectangle = CGRectMake(60,170,200,80);
CGContextAddRect(context, rectangle);
CGContextStrokePath(context);
or you can get the opensource code from github

UITableView with static cell - different separation color per section?

I have UITableView with static cells in 4 sections done in Storyboard. However, I want to change the separator color for one section ([UIColor clearColor]). How can I do that??? Is it actually possible?
I can set the separatorColor to clearColor for the entire table, but not only for one specific section.
Screenshot of table view section:
AFAIK there is no method for this. But you can put a background image to the cell which has a separator at the bottom and set separatorstyle to UITableViewCellSeparatorStyleNone. So you have your own separator in every cell.
Maybe you can achieve your goal by setting the header text for the section to an empty string.
One approach would to create your own UIView subclass and do your own custom drawing in drawRect:. You would take this view and add it as the backgroundView of your table view cell. Something like this:
- (void)drawRect:(CGRect)rect
{
[super drawRect:rect];
// Drawing code
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetLineWidth(context, 1.0);
// Draw black line
CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
CGFloat components[] = {0.0, 0.0, 0.0, 0.3};
CGColorRef blackColor = CGColorCreate(colorspace, components);
CGContextSetStrokeColorWithColor(context, blackColor);
CGContextMoveToPoint(context, 0, rect.size.height - 1.5);
CGContextAddLineToPoint(context, rect.size.width, rect.size.height - 1.5);
CGContextStrokePath(context);
CGColorRelease(blackColor);
// Draw white bottom line
CGFloat whiteComponents[] = {1.0, 1.0, 1.0, 0.75f};
CGColorRef whiteColor = CGColorCreate(colorspace, whiteComponents);
CGContextSetStrokeColorWithColor(context, whiteColor);
CGContextMoveToPoint(context, 0, rect.size.height - 0.5);
CGContextAddLineToPoint(context, rect.size.width, rect.size.height - 0.5);
CGContextStrokePath(context);
CGColorRelease(whiteColor);
// Draw top white line
CGFloat whiteTransparentComponents[] = {1.0, 1.0, 1.0, 0.45};
CGColorRef whiteTransparentColor = CGColorCreate(colorspace, whiteTransparentComponents);
CGContextSetStrokeColorWithColor(context, whiteTransparentColor);
CGContextMoveToPoint(context, 0, 0.5);
CGContextAddLineToPoint(context, rect.size.width, 0.5);
CGContextStrokePath(context);
CGColorRelease(whiteTransparentColor);
CGColorSpaceRelease(colorspace);
}

objective-c CG filling path not working

I have following problem:
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetLineCap(context,kCGLineCapRound);
CGContextSetLineJoin(context, kCGLineJoinRound);
CGContextSetRGBFillColor(context, 1, 0, 0, 1);
for (drawnCurve *line in completeLines) {
CGContextBeginPath(context);
for(int i=0;i<[line.points count]-1;i++)
{
drawnPoint*point=[line.points objectAtIndex:i];
drawnPoint*point2=[line.points objectAtIndex:i+1];
// CGContextSetLineWidth(context, point.r);
[point.color set];
CGContextMoveToPoint(context, point.x,point.y);
CGContextAddLineToPoint(context, point2.x, point2.y);
// CGContextAddCurveToPoint(context, (point.x+point2.x)/2, point2.y, (point.x+point2.x)/2, point2.y, point2.x, point2.y);
//CGContextEOFillPath(context);
}
CGContextClosePath(context);
CGContextFillPath(context);
}
But it's just disappearing and not showing any kind of filled curves.. What is the problem?
A call to CGContextMoveToPoint begins a new subpath. You should call it once before your nested for loop, and then use only CGContextAddLineToPoint to preserve line connectivity:
drawnPoint*pointZero=[line.points objectAtIndex:0];
CGContextMoveToPoint(context, pointZero.x,pointZero.y);
for(int i=1;i<[line.points count];i++)
{
drawnPoint*point=[line.points objectAtIndex:i];
CGContextAddLineToPoint(context, point.x, point.y);
}
CGContextClosePath(context);
CGContextFillPath(context);

CGContextStrokePath triggers EXC_BAD_ACCESS in iOS > 5 [duplicate]

This question already has answers here:
Assigning an existing CGColor to a CGColor property works in iOS Simulator, not iOS device. Why?
(3 answers)
Closed 9 years ago.
I have a custom UIButton class that adds a gradient and a gloss effect to the UIButton
the code works perfectly in iOS 4 and on iOS5 simulator but when i run it on iOS 5 devices it gives me the exception EXC_BAD_ACCESS , the exception is triggered by the line :
CGContextStrokePath(context);
any help is really appreciated ,
here's my code
- (void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
CGFloat actualBrightness = _brightness;
if (self.selected) {
actualBrightness -= 0.10;
}
CGColorRef blackColor = [UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:1.0].CGColor;
CGColorRef highlightStart = [UIColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:0.7].CGColor;
CGColorRef highlightStop = [UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.0].CGColor;
CGColorRef outerTop = [UIColor colorWithHue:_hue saturation:_saturation brightness:1.0*actualBrightness alpha:1.0].CGColor;
CGColorRef outerBottom = [UIColor colorWithHue:_hue saturation:_saturation brightness:0.80*actualBrightness alpha:1.0].CGColor;
CGFloat outerMargin = 7.5f;
CGRect outerRect = CGRectInset(self.bounds, outerMargin, outerMargin);
CGMutablePathRef outerPath = createRoundedRectForRect(outerRect, 6.0);
// Draw gradient for outer path
CGContextSaveGState(context);
CGContextAddPath(context, outerPath);
CGContextClip(context);
drawLinearGradient(context, outerRect, outerTop, outerBottom);
CGContextRestoreGState(context);
if (!self.selected) {
CGRect highlightRect = CGRectInset(outerRect, 1.0f, 1.0f);
CGMutablePathRef highlightPath = createRoundedRectForRect(highlightRect, 6.0);
CGContextSaveGState(context);
CGContextAddPath(context, outerPath);
CGContextAddPath(context, highlightPath);
CGContextEOClip(context);
drawLinearGradient(context, CGRectMake(outerRect.origin.x, outerRect.origin.y, outerRect.size.width, outerRect.size.height/3), highlightStart, highlightStop);
CGContextRestoreGState(context);
drawCurvedGloss(context, outerRect, 180);
CFRelease(highlightPath);
}
else {
//reverse non-curved gradient when pressed
CGContextSaveGState(context);
CGContextAddPath(context, outerPath);
CGContextClip(context);
drawLinearGloss(context, outerRect, TRUE);
CGContextRestoreGState(context);
}
if (!_toggled) {
//bottom highlight
CGRect highlightRect2 = CGRectInset(self.bounds, 6.5f, 6.5f);
CGMutablePathRef highlightPath2 = createRoundedRectForRect(highlightRect2, 6.0);
CGContextSaveGState(context);
CGContextSetLineWidth(context, 0.5);
CGContextAddPath(context, highlightPath2);
CGContextAddPath(context, outerPath);
CGContextEOClip(context);
drawLinearGradient(context, CGRectMake(self.bounds.origin.x, self.bounds.size.height-self.bounds.size.height/3, self.bounds.size.width, self.bounds.size.height/3), highlightStop, highlightStart);
CGContextRestoreGState(context);
CFRelease(highlightPath2);
}
else {
//toggle marker
CGRect toggleRect= CGRectInset(self.bounds, 5.0f, 5.0f);
CGMutablePathRef togglePath= createRoundedRectForRect(toggleRect, 8.0);
CGContextSaveGState(context);
CGContextSetLineWidth(context, 3.5);
CGContextSetStrokeColorWithColor(context, [UIColor whiteColor].CGColor);
CGContextAddPath(context, togglePath);
CGContextStrokePath(context);
CGContextRestoreGState(context);
CFRelease(togglePath);
}
// Stroke outer path
CGContextSaveGState(context);
CGContextSetLineWidth(context, 0.5);
CGContextSetStrokeColorWithColor(context, blackColor);
CGContextAddPath(context, outerPath);
CGContextStrokePath(context);
CGContextRestoreGState(context);
CFRelease(outerPath);
}
what I really wanna now is that is it really related to iOS 5 or am i doing something else wrong ?
The crash happens because the UIColors are already deallocated when you access the CGColorRefs.
An easy way to avoid this is to use
UIColor* blackColor = [UIColor blackColor];
CGContextSetStrokeColorWithColor(context, [blackColor CGColor]);
instead of
CGColorRef* blackColor = [[UIColor blackColor] CGColor];
CGContextSetStrokeColorWithColor(context, blackColor);
so ARC doesn't get the chance to deallocate the UIColor objects early.

Objective C - remove drawing

I've been using the code below to draw on an UIView
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetStrokeColorWithColor(context, [UIColor blueColor].CGColor);
CGContextSetRGBFillColor(context, 0.0, 0.0, 1.0, 1.0);
CGContextSetAlpha(context, 0.5);
CGContextSetLineWidth(context, 10.0);
CGContextMoveToPoint(context, point.x, point.y);
CGContextAddLineToPoint(context, point.x, point.y);
CGContextStrokePath(context);
So that part works.
Now how do I clear my drawing? Most of the example just shows the drawing. Having a hardtime finding keyword to google.
Thanks,
Tee
Have you tried CGContextClearRect?
[self setNeedsDisplay];
it sends the message drawRect: to the view.