drawing over a view shades the view? - ios

I am creating a custom view to display month and date, and basically this is what it looks like:
However, I also want to add a small triangle point down just beneath the blue month label on top. So I added the following code in drawRect
- (void)drawRect:(CGRect)rect
{
[super drawRect:rect];
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextBeginPath(context);
CGContextMoveToPoint(context, 30 - 5.0, 20);
CGContextAddLineToPoint(context, 30 + 5.0, 20);
CGContextAddLineToPoint(context, 30, 20 + 4.0);
CGContextAddLineToPoint(context, 30 - 5.0, 20);
CGContextSetRGBFillColor(context, 0, 118/255.0, 166/255.0, 1.0);
CGContextFillPath(context);
}
This is basically drawing over the white date label to add the small triangle to my custom view, and it does work. But it has an unexpected side effect of shading the date label itself. The effect is as following:
Also if you zoom in the image you can see that the round corners are also filled in by a black color. It looks like some layer properties are messed up maybe? What exactly is happening?
Thank you very much!

Related

CGContextClip Antialiasing issue

I am drawing a shape in a UIView drawRect function that involves clipping a path, and then adding coloured blocks behind so that the colors have the shape of the clipped path. However, for some reason the lines of the path are not coming out smoothly; its if the antialiasing isn't working properly.
CGContextSetStrokeColorWithColor(context, [UIColor clearColor].CGColor);
CGContextSetLineWidth(context, 1.0);
CGContextSetShouldAntialias(context, true);
CGContextSetAllowsAntialiasing(context, true);
CGContextBeginPath (context);
CGContextMoveToPoint(context, xStart, yStart);
for (int i=0; i<points.count; i++) {
CGContextAddLineToPoint(context, xPoint, yPoint);
}
}
CGContextAddLineToPoint(context, xStart, yStart );
CGContextClip(context);
CGRect colorRect = CGRectMake(0, 0 , rectWidth, rectHeight);
CGContextSetFillColorWithColor(context, blockColor.CGColor);
CGContextFillRect(context, colorRect);
CGContextRestoreGState(context);
The result should have smooth lines, but it comes out jagged with visible pixels as in this image:
Any idea what the problem is and how to fix it?
Thanks in advance
Okey. So, there is no problem in your code. The problem is that antialiasing works a little different. You drawing a vertical slopes expecting that edge of resulting histogram will be smoothed. But actually antialiasing doesn't smooth the resulting figure. It works with path elements (curves, lines) one by one. So, for example if you draw a circle, its edges will be smoothed.
There is a simple solution of your problem: just create a curve, enveloping the histogram. Add it to your context. It will look more smooth.
Sorry for bad english.

Line isn't drawing at the top corner

I'm attempting to draw two lines -- I understand that 0 is suppose to start at the corner, but for me it seems off. I know it isn't the code that's wrong and I've tried doing negative numbers for the x-coordinate, but the line disappears.
Those who wanted the size of my frames:
2014-03-29 21:12:28.294 touchScreenClockTest[5178:70b] height = 568.000000
2014-03-29 21:12:28.295 touchScreenClockTest[5178:70b] width = 320.000000
What I want it to look like:
What it looks like:
// Draw the top line
CGContextRef drawTopLine = UIGraphicsGetCurrentContext();
CGContextSetStrokeColorWithColor(drawTopLine, [UIColor whiteColor].CGColor);
// Draw them with a 2.0 stroke width so they are a bit more visible.
CGContextSetLineWidth(drawTopLine, 1.5);
CGContextMoveToPoint(drawTopLine, 0,5); //start at this point
CGContextAddLineToPoint(drawTopLine, 300, 5); //draw to this point
// and now draw the Path!
CGContextStrokePath(drawTopLine);
// Draw the bottom line
CGContextRef drawBotLine = UIGraphicsGetCurrentContext();
CGContextSetStrokeColorWithColor(drawBotLine, [UIColor whiteColor].CGColor);
// Draw them with a 2.0 stroke width so they are a bit more visible.
CGContextSetLineWidth(drawBotLine, 1.5);
CGContextMoveToPoint(drawBotLine, 0, 30); //start at this point
CGContextAddLineToPoint(drawBotLine, 300, 30); //draw to this point
// and now draw the Path!
CGContextStrokePath(drawBotLine);
Also one more question. I wanted to know how to put the navigation button on my own. I have the image of the navigation, but I didn't know what I would need to call to place the image UIView? (since I don't have a storyboard)

Clipping a custom UIView to a triangle

First off, here's an image of my current situation.
To accomplish this I am using a subclassed UIView with the following method:
-(void)drawRect:(CGRect)rect
{
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextBeginPath(ctx);
CGContextMoveToPoint (ctx, CGRectGetMinX(rect), CGRectGetMinY(rect)); // top left
CGContextAddLineToPoint(ctx, CGRectGetMaxX(rect), CGRectGetMidY(rect)); // mid right
CGContextAddLineToPoint(ctx, CGRectGetMinX(rect), CGRectGetMaxY(rect)); // bottom left
CGContextClosePath(ctx);
CGContextSetRGBFillColor(ctx, 0, 1, 0, 1);
CGContextFillPath(ctx);
}
My ultimate goal is to clip the colored regions so that only the neon green remains. (I'll flip the colors later). I want it to look like a pie chart. I'm guessing there's a way to clip the colored corners out but I have no clue. CGContextClip(ctx) doesn't work.
I am using the Pixate framework as well. If anyone knows a way to accomplish a triangle shape with Pixate that would be even better.
The easiest way to clip a UIView to a path is to create a CAShapeLayer, add a path to the layer, and add the shape layer as a mask of your view's layer.
Or with a CGPathRef, essentially the same thing but at core foundation level
eg..
{
// before existing drawing code..
CGMutablePathRef clipTriangle = CGPathCreateMutable();
CGPathMoveToPoint (clipTriangle, nil, startX, startY);
CGPathAddLineToPoint(clipTriangle, nil, secondPointX, secondPointY);
CGPathAddLineToPoint(clipTriangle, nil, thirdPointX, thirdPointY);
CGPathCloseSubpath(clipTriangle);
CGContextSaveGstate(ctx);
CGContextAddPath(ctx, clipTriangle); /// this is the essential line I left out, we drew the triangle and forgot to use it, clipping to nothing instead, sorry mate
CGContextClip(ctx);
//draw stuff that you wanted clipped here...
CGContextRestoreGstate(ctx);
CGPathRelease(clippingTriangle); //CFstuff still needs manual memory management regardless of ARC
}

CGContextDrawRadialGradient For Non-Circular Glow

I'm able to use CGContextDrawRadialGradient to make a sphere that does an alpha fade to UIColor.clearColor and it works.
However, I'm trying to do this type of thing:
While placing some strategic spheres around makes for an interesting effect (similar to LED backlights in strategic places), I would love to get a true glow. How can I draw a glow around a rounded rectangle in drawRect?
You can create a glow effect around any path using CGContextSetShadowWithColor, but you don't get precise control over the appearance. In particular, the default shadow is fairly light:
And the only way I know of to make it darker is to draw it again over itself:
Not optimal, but it approximates what you want pretty well.
Those images were generated by the following drawRect:
- (void)drawRect:(CGRect)rect
{
CGContextRef context = UIGraphicsGetCurrentContext();
CGMutablePathRef path = CGPathCreateMutable();
int padding = 20;
CGPathMoveToPoint(path, NULL, padding, padding);
CGPathAddLineToPoint(path, NULL, rect.size.width - padding, rect.size.height / 2);
CGPathAddLineToPoint(path, NULL, padding, rect.size.height - padding);
CGContextSetShadowWithColor(context, CGSizeZero, 20, UIColor.redColor.CGColor);
CGContextSetFillColorWithColor(context, UIColor.blueColor.CGColor);
CGContextAddPath(context, path);
CGContextFillPath(context);
// CGContextAddPath(context, path);
// CGContextFillPath(context);
CGPathRelease(path);
}
One thing to bear in mind is that rendering fuzzy shadows is fairly expensive, which may or may not be a problem depending on how often your views are redrawn. If the shadows don't need to animate, consider rendering them to a UIImage once and just displaying the result in a UIImageView.

why CGContextSaveGState is not required even after several modification to the current context?

I am really strugggling with Quartz2D for more then 10 days please help me understand few concepts I will be really grateful, please look at this code and screenshot url.
This code draw image with border and write text to it and the image become whole new image with border and text.
//part 1
CGSize cgs = CGSizeMake(250.0, 400.0);
UIGraphicsBeginImageContext(cgs);
CGRect rectangle = CGRectMake(0,0,cgs.width,cgs.height);
CGRect imageRect = CGRectInset(rectangle, 5.4, 5.4);
imageRect.size.height -= 100;
UIImage *myImage = [UIImage imageNamed:#"BMW.jpg"];
[myImage drawInRect:imageRect];
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetLineWidth(context, 10.0);
CGContextSetRGBStrokeColor(context, 0.0, 0.0, 1.0, 1.0);
CGContextStrokeRect(context, rectangle);
//
//part 2
1. CGRect contextRect = rectangle;
2. CGContextTranslateCTM(context, 0, contextRect.size.height);
3. CGContextScaleCTM(context, 1, -1);
4. float w, h;
5. w = contextRect.size.width;
6. h = contextRect.size.height;
7. CGContextSelectFont (context, "Helvetica-Bold", 25,
kCGEncodingMacRoman);
8. CGContextSetCharacterSpacing (context, 5);
9. CGContextSetRGBFillColor(context, 0.0, 1.0, 1.0, 1.0);
10. CGContextSetRGBStrokeColor(context, 1.0, 0.0, 0.0, 1.0);
11. CGContextShowTextAtPoint(context, 45, 50, "Quartz 2D", 9);
//
//part 3
UIImage *testImg = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[testImg drawAtPoint:CGPointMake(35, 10)];
//
http://i40.tinypic.com/140aptv.png
part 1 and part 3 of the code is very clear to me
problem is regarding part 2
on line 2 and 3 coordinates are transformed so the text do not display
upside down, but uiimage already take care of this internally, why it
didn't transformed to upside down? why it is still displaying in
correct position after transform is applied for text using same
context? I am asking this because when uiimage coordinates are already
modified then this coordinate transform will not make uiimage again
upside down?
on line 9 and 10 fillcolor and strokecolor methods are called and
fillcolor changes the text color, but strokecolor not doing any thing
to text why? And why without CGContextSaveGState it modified the
color of text not the border color?
regarding these both points I mentioned above the common confusion is
why its working perfectly why this code didn't need
CGContextSaveGState and CGContextRestoreGState. How it is possible
that context is modified and it didn't effect the perviously drawing
item like blue border in this case and coordinates transformation for
text.
Please correct me if I am lacking in any way to make you understand my points.
Thanks in advance,
Regards.
Quartz 2D uses the "painter's model." That means, you draw one thing, and it's done. Then you draw another thing, and it goes on top of what you drew before. Then you draw another thing and that goes on top, etc. If I pick up a stamp, dip it in paint and press it to paper, then turn it over and do it again to another part of the paper, the first stamped image doesn't flip over just because I flipped the stamp.
Every time you see "stroke" or "draw," you're modifying the final image. Later changes to the context don't effect that.

Resources