CGContext giving unexpected line width - iphone

I'm trying to draw a L shape, the code works but the lines are not of the right width and is 5 pixels thick for vertical lines and some are 3 pixels thick despite me explicitly telling it to use 3 pixel as line width,what am I doing wrong? here's my code:
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextClearRect(ctx, rect);
CGContextAddPath(ctx, pathi);
CGContextSetStrokeColorWithColor(ctx, [UIColor redColor].CGColor);
CGContextSetLineWidth(ctx, 3.0);
CGContextSetLineCap(ctx, kCGLineCapRound);
CGContextSetShouldAntialias(ctx, NO);
CGContextStrokePath(ctx);
I have already calculated path "pathi" The path is working fine.

The lines are actually not thick, the half of the lines gets cutoff while drawing.
You should apply padding equal to the half of the width( inn your case, 3/2 => 1.5) because the drawing always start from the mid of the points provided.

Related

Improper borders in draw rect

I am trying to draw rounded corners on rectangle in drawRect method using bezier path, but somehow the rounded corner is being shown on inner side of rectangle, instead of both inner and outer sides. Code is given below. Also attached herewith is border that is currently being drawn (outer side of border is not rounded)
- (void)drawRect:(CGRect)rect
{
// Drawing code
CGContextRef context=UIGraphicsGetCurrentContext();
//Set gray color to whole context
[[UIColor lightGrayColor] set];
CGContextSetAlpha(context,0.7);
UIRectFill(rect);
// Configure the context colors and line
CGContextSetStrokeColorWithColor(context, [UIColor colorWithRed:131./255. green:148./255. blue:219./255. alpha:1.0].CGColor);
CGContextSetFillColorWithColor(context, [UIColor whiteColor].CGColor);
CGContextSetLineWidth(context, 10.0);
CGSize size=self.bounds.size;
CGFloat radius = 10.0;
CGSize guideSize=CGSizeMake(330, 130);
CGRect guideCoords= CGRectMake(size.width*.5-guideSize.width*.5, size.height*.5-guideSize.height*.5, guideSize.width , guideSize.height);
// Guide drawing
CGContextStrokeRect(context,guideCoords);
// Draw the Text
[kVinGuideMessage drawInRect:CGRectMake(guideCoords.origin.x+kSideMessageMargin, guideCoords.origin.y+guideSize.height+kMarginFromGuide, guideCoords.size.width-2*kSideMessageMargin,40) withFont:[UIFont systemFontOfSize:16.0] lineBreakMode:NSLineBreakByWordWrapping alignment:NSTextAlignmentLeft];
//Get instersection and clear color of inner overlay
CGRect holeRectIntersection = CGRectIntersection(rect,guideCoords);
//----------ADDING ROUNDED CORNERS HERE-----------//
CGPathRef clippath = [UIBezierPath bezierPathWithRoundedRect:guideCoords cornerRadius:radius].CGPath;
CGContextAddPath(context, clippath);
CGContextClip(context);
//------------------------------------------------//
[[UIColor clearColor] setFill];
UIRectFill(holeRectIntersection);
}
The outer corners are being drawn by the CGContextStrokeRect(context,guideCoords); I think. At that point you haven't set a clipping path and your line width is 10 points, so why would the outer corners be rounded? I think you'll have better luck if you set a clipping path (probably not exactly the same clipping path you've got at the bottom) before calling stroke rect on the guideCoords rectangle.

CGContextRestoreGState seems not to restore the previous state

So, I need to draw a series of dotted lines along an axis.
In the drawRect method I call another method to draw the axis..
In that method I save the GState draw the axis and then save the gstate again draw the dotted line when appropriate,then stroke the path restore the gstate add some thing to the axis fill the path..
The thing is now the whole thing is dotted ...
It seems the the code didn't discard the dotted line pattern when I restored the gstate ...
CGContextSaveGState(ctx);
CGContextSetFillColorWithColor(ctx, [[UIColor whiteColor] CGColor]);
.......
//draw a dased line
CGContextSaveGState(ctx);
CGContextSetLineWidth(ctx, 1.0);
CGContextSetStrokeColorWithColor(ctx, [UIColor whiteColor].CGColor);
CGFloat const kDashedLinesLength[] = {1.0f, 0.5f};
CGContextSetLineDash(ctx, 0.0, kDashedLinesLength, 2);
CGContextMoveToPoint(ctx, LEFT_EXCLUSION_LENGTH + AXIS_LINE_WIDTH, crtYval);
CGContextAddLineToPoint(ctx, LEFT_EXCLUSION_LENGTH + AXIS_LINE_WIDTH + self.xAxis.visibleLength , crtYval);
CGContextStrokePath(ctx);
CGContextRestoreGState(ctx);
...
CGContextFillPath(ctx);
CGContextRestoreGState(ctx);
How can I make sore that only the line I need gets doted ???
I'm not sure what's wrong with your code, but it's not a bug in the context restore which works fine. Likely you have another error in the code you replaced with .....
Could be that you have unbalanced save and restores which will cause all kinds of problems - I'd check that first.
I copied and pasted it with minimal changes into a small iOS test app custom view's drawRect method and ran it and I'm seeing what I expect.
here's the little test code that works as expected:
- (void)drawRect:(CGRect)rect
{
// Drawing code
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextSaveGState(ctx);
CGContextSetFillColorWithColor(ctx, [[UIColor blackColor] CGColor]);
CGContextSetStrokeColorWithColor(ctx, [UIColor blackColor].CGColor);
CGContextSetLineWidth(ctx, 2.0);
//draw a dased line
CGContextSaveGState(ctx);
CGContextSetStrokeColorWithColor(ctx, [UIColor blueColor].CGColor);
CGFloat const kDashedLinesLength[] = {1.0f, 2.0f};
CGContextSetLineDash(ctx, 0.0, kDashedLinesLength, 2);
CGContextMoveToPoint(ctx, 100, 100 );
CGContextAddLineToPoint(ctx, 100, 200);
CGContextStrokePath(ctx);
CGContextRestoreGState(ctx);
CGContextMoveToPoint(ctx, 200, 100 );
CGContextAddLineToPoint(ctx, 200, 200);
CGContextStrokePath(ctx);
CGContextFillPath(ctx);
CGContextRestoreGState(ctx);
}
And is the sample output:
You need to be careful to always exactly balance a Save with a Restore. I've had situations where I had one or the other too many in a totally different location of my app. Because iOS partially reuses contexts this can leave a graphics context in a weird state.
You should search your source code for all instances of a Save and a Restore and count if there are equal numbers of them.
I think I know your problem. Look at it this way: The line isn't drawn until you stroke the path. So whatever pattern is in effect when you call CGContextAddLineToPoint (for example) doesn't matter. When you call CGContextAddLineToPoint you're not drawing a line, you are simply building a path. I'm guessing that your subroutine for drawing the axes does not stroke them. The axes don't get drawn until you later call CGContextStrokePath, at which point the dashed pattern is in effect.

CGContextDrawPath Stroke disappears if Fill is added

trying to draw circle divided to dynamically provided number of sectors. In the end my circle should look like pie.
I've created class Circle which contains number of Pies inside. Circle has method - (void)draw which calles [pie draw]; in for (Pie *pie in self.pies) loop.
Implementation of pie looks like this:
- (void)draw {
CGContextRef context = UIGraphicsGetCurrentContext();
float startAngleRads = degreesToRadians(_startAngle);
float endAngleRads = degreesToRadians(_endAngle);
CGContextBeginPath(context);
CGContextSetLineWidth(context, 1.0f);
CGContextSetLineCap(context, kCGLineCapRound);
CGContextSetLineJoin(context, kCGLineJoinRound);
CGColorRef strokeColor = [_strokeColor CGColor];
CGContextSetStrokeColorWithColor(context, strokeColor);
CGColorRef fillColor = [_bgColor CGColor];
CGContextSetFillColorWithColor(context, fillColor);
CGContextMoveToPoint(context, _x, _y);
CGContextAddArc(context, _x, _y, _r, startAngleRads, endAngleRads, YES);
CGContextDrawPath(context, kCGPathStroke);
CGContextFlush(context);
}
This draws nice circle with sectors but without any filling of course. When I change last lines to CGContextDrawPath(context, kCGPathStrokeFill); my stroke lines disappears and only last line (last sector) stays at the screen, other parts of circle are filled with bgcolor and no stroke is visible anymore.
The question is: how can I draw completly separated "sectors" (every sector should look like triangle with Arc and Stroke and Fill). I need this because I want to toggle visibility of that sectors but at the moment I cant even figure out how to draw them correctly.
If this is important, all drawing happens on the layer with self.opaque = NO;.
Ok, found my error: had to set NO in CGContextAddArc call.

Draw lines and fills with a chalk texture in iPhone app

I have code in my iPhone app to draw a pie chart in a UIView. All is great but I need to be able to use a chalk-like texture to draw the outlines and then to fill in the different colours of the pie chart.
Here are extracts from the existing code for each area:
Drawing the circle around the pie chart:
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextSetRGBStrokeColor(ctx, 1.0, 1.0, 1.0, 1.0);
CGContextSetLineWidth(ctx, 8.0);
// Draw a thin line around the circle
CGContextAddArc(ctx, x, y, r, 0.0, 360.0*M_PI/180.0, 0);
CGContextClosePath(ctx);
CGContextDrawPath(ctx, kCGPathStroke);
... and drawing a segment of the pie:
CGContextSetRGBStrokeColor(ctx, 1.0, 1.0, 1.0, 1.0);
CGContextSetLineWidth(ctx, 8.0);
CGContextMoveToPoint(ctx, x, y);
CGContextAddArc(ctx, x, y, r, (startDeg-90)*M_PI/180.0, (endDeg-90)*M_PI/180.0, 0);
CGContextClosePath(ctx);
CGContextDrawPath(ctx, kCGPathStroke);
... then filling it with a colour fill:
CGContextSetRGBFillColor(ctx, color.red, color.green, color.blue, color.alpha );
CGContextMoveToPoint(ctx, x, y);
CGContextAddArc(ctx, x, y, r, (startDeg-90)*M_PI/180.0, (endDeg-90)*M_PI/180.0, 0);
CGContextClosePath(ctx);
CGContextFillPath(ctx);
Ignoring the fact that I haven't pasted in the variable declarations for many of the variables used, I hope the code is fairly self-explanatory.
Now: How could I change the code to use a texture for the actual drawing of the lines/arcs?
Similarly, how can I use a texture fill instead of a colour fill?
I'm trying to get this app finished off and this is my last stumbling block. Other questions on SO and elsewhere on the web just don't seem to answer the question in a way I can follow.
Any help will be gratefully received!
Robert
Know this is outdated but one can set fill or stroke patterns using this simple code snippet:
// Somewhere in initialization code.
UIColor *pattern = [UIColor colorWithPatternImage:[UIImage imageNamed:#"pattern.png"]];
CGColorRef fillColor = [pattern CGColor];
CGColorRef strokeColor = [pattern CGColor];
// Probably in |draw| method call.
CGContextSetStrokeColorWithColor(context, strokeColor);
CGContextSetFillColorWithColor(context, fillColor);
Hope it will help someone. There are also other great advanced possibilities - you can manipulate patterns in many ways: shift, scale, rotate, use colored or stencil patters and many many others, but this requires deep digging in api docs.

iPhone Quartz curve jaggy and has dark border

I've got a weird issue with quartz. The first time I run the piece of code below, the line will be drawn like the line to the right in the image. The second time (and every time after) these lines are executed, the line will look like the line to the left. Why does it look like that? It's all jaggy and seems to have a dark border. If you'd draw the curve with opacity, it would be rather bright the first time, and very dark the second.
CGContextSetRGBFillColor(context, 0.0,0.0,0.0,0.0);
CGContextClearRect(context, CGRectMake( 0, 0, 320, 480));
CGContextSetRGBFillColor(context, 0, 0, 0, 0);
CGContextSetBlendMode(context, kCGBlendModeNormal);
CGContextSetRGBStrokeColor(context, 1.0, 1.0, 1.0, 1.0);
CGContextSetLineWidth(context, 4.0);
CGContextMoveToPoint(context, p1.x, p1.y);
CGContextAddCurveToPoint(context, cp1.x, cp1.y, cp2.x, cp2.y, p2.x, p2.y);
CGContextDrawPath(context, kCGPathStroke);
(source: pici.se)
antialiasing OFF?
also, you might want to make sure the x and y values are rounded as the Quartz Framework doesn't handle well the half point.