Using Core Graphics for drawing - iphone

I am building an iOS app for drawing first time. Now i am able to draw lines and curves using core graphics but unable UNDO the drawing. I am saving all the points when drawing and try trying to reuse them for UNDO and REDO, but with no success. Can anyone help to know what i am doing wrong?
Any help is highly appreciated.
Here is my code
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[tempPathArray removeAllObjects];
UITouch *touch = [touches anyObject];
previousPoint1 = [touch previousLocationInView:self];
previousPoint2 = [touch previousLocationInView:self];
currentPoint = [touch locationInView:self];
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
previousPoint2 = previousPoint1;
previousPoint1 = [touch previousLocationInView:self];
currentPoint = [touch locationInView:self];
// calculate mid point
CGPoint mid1 = midPoint(previousPoint1, previousPoint2);
CGPoint mid2 = midPoint(currentPoint, previousPoint1);
CGMutablePathRef path = CGPathCreateMutable();
CGPathMoveToPoint(path, NULL, mid1.x, mid1.y);
CGPathAddQuadCurveToPoint(path, NULL, previousPoint1.x, previousPoint1.y, mid2.x, mid2.y);
CGRect bounds = CGPathGetBoundingBox(path);
CGPathRelease(path);
drawBox = bounds;
//Pad our values so the bounding box respects our line width
drawBox.origin.x -= self.lineWidth * 2;
drawBox.origin.y -= self.lineWidth * 2;
drawBox.size.width += self.lineWidth * 4;
drawBox.size.height += self.lineWidth * 4;
UIGraphicsBeginImageContext(drawBox.size);
[self.layer renderInContext:UIGraphicsGetCurrentContext()];
curImage = UIGraphicsGetImageFromCurrentImageContext();
[curImage retain];
UIGraphicsEndImageContext();
[tempPathArray addObject:[NSValue valueWithCGRect:drawBox]];
[self setNeedsDisplayInRect:drawBox];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
[pathArray addObject:tempPathArray];
NSLog(#"path array count %d", [pathArray count]);
}
- (void)drawRect:(CGRect)rect
{
NSLog(#"draw rect");
[curImage drawAtPoint:CGPointMake(0, 0)];
CGPoint mid1 = midPoint(previousPoint1, previousPoint2);
CGPoint mid2 = midPoint(currentPoint, previousPoint1);
context = UIGraphicsGetCurrentContext();
[self.layer renderInContext:context];
CGContextMoveToPoint(context, mid1.x, mid1.y);
// Use QuadCurve is the key
CGContextAddQuadCurveToPoint(context, previousPoint1.x, previousPoint1.y, mid2.x, mid2.y);
CGContextSetLineCap(context, kCGLineCapRound);
CGContextSetLineWidth(context, self.lineWidth);
CGContextSetStrokeColorWithColor(context, self.lineColor.CGColor);
CGContextStrokePath(context);
[super drawRect:rect];
}
-(void)undoButtonClicked
{
KidsPhotoBookAppDelegate *appDelegate = (KidsPhotoBookAppDelegate*)[[UIApplication sharedApplication]delegate];
if([pathArray count]>0){
[bufferArray addObject:[pathArray lastObject]];
[pathArray removeLastObject];
for (NSMutableArray *tempArray in pathArray) {
for (int i = 0; i < [tempArray count]; i++) {
CGRect draw = [[tempArray objectAtIndex:i] CGRectValue];
[self setNeedsDisplayInRect:draw];
}
}
}
}

Try this:
Draw a line.
Draw another line back over the first line.
Undo.
I suspect you'll see it mostly work—the part of the second line that overlapped the first line will disappear, and only the part that didn't will remain.
The problem is that you're setting needs display on the portions of the drawing that you still have, but not the portion that you just vacated. This is exactly the inverse of what you should be doing: The portions you still have don't need to be redrawn, because they haven't changed, whereas the portion you vacated does need to be redrawn because it has changed.
So, set needs display in the area of the path you're removing, just before you remove it. You shouldn't need to set needs display of anything else.

Related

Clear context graphics

I am trying to clear graphics context. It clears perfectly using these 2 ways.
1. clearContextBeforeDrawing
2. CGContextClearRect(context, rect);
CGContextSetFillColorWithColor(context, [UIColor whiteColor].CGColor);
CGContextFillRect(context, rect);
CGContextFlush(context);
But when I draw lines again. The previous lines are mixed up with the new lines with dots appearing. Can anyone please help ?
This is how I am clearing lines
-(IBAction)eraseButton:(id)sender
{
self.viewmainHandwriting.isErase = TRUE;
[self.viewmainHandwriting setBackgroundColor:[UIColor clearColor]];
[self.viewmainHandwriting setNeedsDisplay]; //It calls my drawRect Function
}
- (void)drawRect:(CGRect)rect
{
CGContextRef context = UIGraphicsGetCurrentContext();
if (!self.isErase)
{
CGContextAddPath(context, path);
CGContextSetLineCap(context, kCGLineCapRound);
CGContextSetLineWidth(context, self.lineWidth);
CGContextSetStrokeColorWithColor(context, self.lineColor.CGColor);
CGContextStrokePath(context);
self.empty = NO;
}
else
{
CGContextClearRect(context, self.bounds);
path
self.isErase = FALSE;
}
}
The is how I am drawing lines
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
previousPoint1 = [touch previousLocationInView:self];
previousPoint2 = [touch previousLocationInView:self];
currentPoint = [touch locationInView:self];
[self touchesMoved:touches withEvent:event];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint point = [touch locationInView:self];
/* check if the point is farther than min dist from previous */
CGFloat dx = point.x - currentPoint.x;
CGFloat dy = point.y - currentPoint.y;
if ((dx * dx + dy * dy) < kPointMinDistanceSquared) {
return;
}
previousPoint2 = previousPoint1;
previousPoint1 = [touch previousLocationInView:self];
currentPoint = [touch locationInView:self];
CGPoint mid1 = midPoint(previousPoint1, previousPoint2);
CGPoint mid2 = midPoint(currentPoint, previousPoint1);
CGMutablePathRef subpath = CGPathCreateMutable();
CGPathMoveToPoint(subpath, NULL, mid1.x, mid1.y);
CGPathAddQuadCurveToPoint(subpath, NULL, previousPoint1.x, previousPoint1.y, mid2.x, mid2.y);
CGRect bounds = CGPathGetBoundingBox(subpath);
CGPathAddPath(path, NULL, subpath);
CGPathRelease(subpath);
CGRect drawBox = bounds;
drawBox.origin.x -= self.lineWidth * 2.0;
drawBox.origin.y -= self.lineWidth * 2.0;
drawBox.size.width += self.lineWidth * 4.0;
drawBox.size.height += self.lineWidth * 4.0;
[self setNeedsDisplayInRect:drawBox];
}
It looks like you don't clear path in the method that clears the whole view (eraseButton ?).
So the path would still contain the whole old drawing. Only those parts would show on which you call setNeedsDisplayInRect: (from within touchesMoved:). You can reveal the old drawing by drawing over it again.
You should clear path (probably an ivar) by just creating a new one in eraseButton:
CGPathRelease(path);
path = CGPathCreateMutable();

ios paint application overwriting paint strokes

I'm creating a paint application but if stroke one line one color and if stroke another line crossing the previous stroke the first stroke change color to the second color
Here is the code I'm using to paint:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
previousPoint1 = [touch previousLocationInView:self];
previousPoint2 = [touch previousLocationInView:self];
currentPoint = [touch locationInView:self];
[self touchesMoved:touches withEvent:event];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint point = [touch locationInView:self];
/* check if the point is farther than min dist from previous */
CGFloat dx = point.x - currentPoint.x;
CGFloat dy = point.y - currentPoint.y;
if ((dx * dx + dy * dy) < kPointMinDistanceSquared) {
return;
}
previousPoint2 = previousPoint1;
previousPoint1 = [touch previousLocationInView:self];
currentPoint = [touch locationInView:self];
CGPoint mid1 = midPoint(previousPoint1, previousPoint2);
CGPoint mid2 = midPoint(currentPoint, previousPoint1);
CGMutablePathRef subpath = CGPathCreateMutable();
CGPathMoveToPoint(subpath, NULL, mid1.x, mid1.y);
CGPathAddQuadCurveToPoint(subpath, NULL, previousPoint1.x, previousPoint1.y, mid2.x, mid2.y);
CGRect bounds = CGPathGetBoundingBox(subpath);
CGPathAddPath(path, NULL, subpath);
CGPathRelease(subpath);
CGRect drawBox = bounds;
drawBox.origin.x -= self.lineWidth * 2.0;
drawBox.origin.y -= self.lineWidth * 2.0;
drawBox.size.width += self.lineWidth * 4.0;
drawBox.size.height += self.lineWidth * 4.0;
[self setNeedsDisplayInRect:drawBox];
}
- (void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextAddPath(context, path);
CGContextSetLineCap(context, kCGLineCapRound);
CGContextSetLineWidth(context, self.lineWidth);
CGContextSetStrokeColorWithColor(context, self.lineColor.CGColor);
CGContextStrokePath(context);
self.empty = NO;
}
Any of you knows what I'm doing wrong or how can I keep each stroke independent one from each other ?
I'll really appreciate your help.
I think what you need to do is to start a new path when you change color. Don't just keep adding new subpaths with the new color to the same path that had the old color.
You will need to store for each path the color it should be rendered and then loop over your paths in the drawRect method.

Objective C: How do I draw lines with alpha in quad curve

I'm having trouble in points when i'm using a quad curve point.. I want to set the opacity to my lines but i also see points here it is..
here are my codes..
CGPoint midPoint(CGPoint p1,CGPoint p2)
{
return CGPointMake ((p1.x + p2.x) * 0.5,(p1.y + p2.y) * 0.5);
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event//upon touches
{
UITouch *touch = [touches anyObject];
previousPoint1 = [touch locationInView:self.view];
previousPoint2 = [touch locationInView:self.view];
currentTouch = [touch locationInView:self.view];
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event//upon moving
{
UITouch *touch = [touches anyObject];
previousPoint2 = previousPoint1;
previousPoint1 = currentTouch;
currentTouch = [touch locationInView:self.view];
CGPoint mid1 = midPoint(previousPoint2, previousPoint1);
CGPoint mid2 = midPoint(currentTouch, previousPoint1);
UIGraphicsBeginImageContext(CGSizeMake(1024, 768));
[imgDraw.image drawInRect:CGRectMake(0, 0, 1024, 768)];
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetLineCap(context,kCGLineCapRound);
CGContextSetLineWidth(context, slider.value);
CGContextSetBlendMode(context, blendMode);
CGContextSetRGBStrokeColor(context,red, green, blue, 0.5);
CGContextBeginPath(context);
CGContextMoveToPoint(context, mid1.x, mid1.y);
CGContextAddQuadCurveToPoint(context, previousPoint1.x, previousPoint1.y, mid2.x, mid2.y);
CGContextStrokePath(context);
imgDraw.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsGetCurrentContext();
endingPoint=currentTouch;
}
any answer will be appreciated.
What you need to do is keep the list of all points the user has entered so far, and always redraw all of them as part of the same path.
You'll need an array to store the points in. Something like
CGPoint points[kMaxNumPoints];
instead of previousPoint1/2, etc. Then in touchesMoved:, you'll iterate over the points in a loop. Something like this:
CGContextBeginPath (context);
CGContextMoveToPoint (context, points [ 0 ].x, point [ 0 ].y);
for (int i = 1; i < currNumPoints; i++)
{
// I wasn't sure from your example if you wanted the mid point here instead of the
// previous point. But you get the idea.
CGContextAddQuadCurveToPoint (context, points [ i - 1 ].x, points [ i - 1 ].y, point [ i ].x, point [ i ].y);
}
CGContextStrokePath (context);

How to create embossed or shadow effects using Core Graphics (for finger paint)

I have issue to implement "Emboss/Shadow effects" in my drawing. Finger paint functionality is currently working fine with my custom UIView and below is my drawRect method code:
Edit code with all methods :
- (void)drawRect:(CGRect)rect
{
CGPoint mid1 = midPoint(previousPoint1, previousPoint2);
CGPoint mid2 = midPoint(currentPoint, previousPoint1);
CGContextRef context = UIGraphicsGetCurrentContext();
[self.layer renderInContext:context];
CGContextMoveToPoint(context, mid1.x, mid1.y);
CGContextAddQuadCurveToPoint(context, previousPoint1.x, previousPoint1.y, mid2.x, mid2.y);
CGContextSetLineCap(context, kCGLineCapRound);
CGContextSetLineWidth(context, self.lineWidth);
CGContextSetStrokeColorWithColor(context, self.lineColor.CGColor);
CGContextSaveGState(context);
// for shadow effects
CGContextSetShadowWithColor(context, CGSizeMake(0, 2),3, self.lineColor.CGColor);
CGContextStrokePath(context);
[super drawRect:rect];
}
CGPoint midPoint(CGPoint p1, CGPoint p2)
{
return CGPointMake((p1.x + p2.x) * 0.5, (p1.y + p2.y) * 0.5);
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
previousPoint1 = [touch previousLocationInView:self];
previousPoint2 = [touch previousLocationInView:self];
currentPoint = [touch locationInView:self];
[self touchesMoved:touches withEvent:event];
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
previousPoint2 = previousPoint1;
previousPoint1 = [touch previousLocationInView:self];
currentPoint = [touch locationInView:self];
// calculate mid point
CGPoint mid1 = midPoint(previousPoint1, previousPoint2);
CGPoint mid2 = midPoint(currentPoint, previousPoint1);
CGMutablePathRef path = CGPathCreateMutable();
CGPathMoveToPoint(path, NULL, mid1.x, mid1.y);
CGPathAddQuadCurveToPoint(path, NULL, previousPoint1.x, previousPoint1.y, mid2.x, mid2.y);
CGRect bounds = CGPathGetBoundingBox(path);
CGPathRelease(path);
CGRect drawBox = bounds;
//Pad our values so the bounding box respects our line width
drawBox.origin.x -= self.lineWidth * 2;
drawBox.origin.y -= self.lineWidth * 2;
drawBox.size.width += self.lineWidth * 4;
drawBox.size.height += self.lineWidth * 4;
UIGraphicsBeginImageContext(drawBox.size);
[self.layer renderInContext:UIGraphicsGetCurrentContext()];
curImage = UIGraphicsGetImageFromCurrentImageContext();
[curImage retain];
UIGraphicsEndImageContext();
[self setNeedsDisplayInRect:drawBox];
}
when i have implemented this i am getting paint effects with dot dot dot ...
See below image (which does not have any shadow or embossed effects). If you have any idea of how to add these effects, please give me some suggestion. How can i resolve this?
It appears that you're creating hundreds, maybe even thousands of separate paths, one on each drawRect. You do flatten these out using [self.layer renderInContext] but I don't think that's a good way to go about it. Instead, I think what you want to do is create one UIBezierPath to track the finger, append paths to that and draw the UIBezierPath to the screen. If you create two layers (or views) you can set the top one (transparent) to "draw" on. When the user lifts their finger, you then render the entire UIBezierPath to the second layer (along with previously drawn data) and create a new UIBezierPath to draw the next finger-tracking. This way you're only updating one layer (the top one) when you're tracking someone's finger. This will help prevent the device from slowing down drawing too many paths.
Although, I will say, your current method does produce a cool looking "3D" effect.
I'm not sure about embossing, but if what you want is to apply a drop shadow to a drawing that is updated progressively, then a nice approach would be to use CALayers (link to a tutorial). Basically, your progressive drawing would update a transparent image (without attempting to draw any shadows in this image) and this image would be configured to be displayed with a drop shadow through its CALayer.
Shadow is created on borders and you are drawing small segments of lines and this creates this effect. You need to create a path and then stroke it once. This code might help you :)
for (int i=0; i<[currentPath count]; i++)
{
CGPoint mid1 = [[self midPoint:[currentPath objectAtIndex:i+1] :[currentPath objectAtIndex:i]] CGPointValue];
CGPoint mid2 = [[self midPoint:[currentPath objectAtIndex:i+2] :[currentPath objectAtIndex:i+1]] CGPointValue];
CGContextMoveToPoint(context, mid1.x, mid1.y);
CGContextAddQuadCurveToPoint(context, [[currentPath objectAtIndex:i+1] CGPointValue].x, [[currentPath objectAtIndex:i+1] CGPointValue].y, mid2.x, mid2.y);
CGContextSetShadow(context, CGSizeMake(-2, -2), 3);
CGContextSetLineCap(context, kCGLineCapRound);
CGContextSetStrokeColorWithColor(context,[color CGColor]);
CGContextSetLineWidth(context, linewidth);
i+=2;
}
CGContextStrokePath(context);
Try this way.. This solved might solve your issue.. First create ur path and after it is fully created, stroke it. This happens since at every small line you stroke and hence shadow created make a dot on its bounds, so you get this effect.

issue in drawing line using core graphics : bubbles are shown

Using core graphics , I am trying to draw a line, in that when I try to add shadow is creates lin and bubbles inside the line, see the image, I am not able to solve the issue. please find my code below
-(void)drawRect:(CGRect)rect
{
[curImage drawAtPoint:CGPointMake(0, 0)];
CGPoint mid1 = midPoint(previousPoint1, previousPoint2);
CGPoint mid2 = midPoint(currentPoint, previousPoint1);
CGContextRef context = UIGraphicsGetCurrentContext();
[self.layer renderInContext:context];
CGContextMoveToPoint(context, mid1.x, mid1.y);
CGContextAddQuadCurveToPoint(context, previousPoint1.x, previousPoint1.y, mid2.x, mid2.y);
CGContextSetLineCap(context, kCGLineCapRound);
CGContextSetLineWidth(context, self.lineWidth);
CGContextSetStrokeColorWithColor(context, self.lineColor.CGColor);
CGContextSetShadow(context, CGSizeMake(-16.00, -5.0f), 5.0f);
CGContextStrokePath(context);
[super drawRect:rect];
[curImage release];
}
Below is the touchesMoved method.
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
previousPoint2 = previousPoint1;
previousPoint1 = [touch previousLocationInView:self];
currentPoint = [touch locationInView:self];
// calculate mid point
CGPoint mid1 = midPoint(previousPoint1, previousPoint2);
CGPoint mid2 = midPoint(currentPoint, previousPoint1);
CGMutablePathRef path = CGPathCreateMutable();
CGPathMoveToPoint(path, NULL, mid1.x, mid1.y);
CGPathAddQuadCurveToPoint(path, NULL, previousPoint1.x, previousPoint1.y, mid2.x, mid2.y);
CGRect bounds = CGPathGetBoundingBox(path);
CGPathRelease(path);
CGRect drawBox = bounds;
//Pad our values so the bounding box respects our line width
drawBox.origin.x -= self.lineWidth * 2;
drawBox.origin.y -= self.lineWidth * 2;
drawBox.size.width += self.lineWidth * 4;
drawBox.size.height += self.lineWidth * 4;
UIGraphicsBeginImageContext(drawBox.size);
[self.layer renderInContext:UIGraphicsGetCurrentContext()];
curImage = UIGraphicsGetImageFromCurrentImageContext();
[curImage retain];
UIGraphicsEndImageContext();
[self setNeedsDisplayInRect:drawBox];
}
CGPoint midPoint(CGPoint p1, CGPoint p2)
{
return CGPointMake((p1.x + p2.x) * 0.5, (p1.y + p2.y) * 0.5);
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
previousPoint1 = [touch previousLocationInView:self];
previousPoint2 = [touch previousLocationInView:self];
currentPoint = [touch locationInView:self];
[self touchesMoved:touches withEvent:event];
}
Here the issue arrives when I try to add the line
CGContextSetShadow(context, CGSizeMake(-16.00, -5.0f), 5.0f);
Please help me out from the issue, thanks in advance. please see editing question with methods .
It would appear you are drawing a series of segments as quad curves. The bubbles would be where the previous segment and the current segment overlap. Since your segment line is a solid red, you don't notice the overlap, but it shows up in the shadows as darker regions.
Try setting your stroke color to have and alpha of 0.5 (or some such translucency). I think (know) you will see the overlapping segments will also show a similar effect as the the shadow.
To solve it, you will want to draw the segment as a continuous path for each line. I'm guessing you are using touchesBegan:withEvent: / touchesMoved:withEvent / touchesEnded:withEvent: to obtain the points of the lines?
In that case, when touchesBegan:withEvent: is called, start your new path. During touchesMoved:withEvent render the new path over the current image. Commit the path to a UIImage in touchesEnded:withEvent:. At this point you may discard the path until touchesBegan:withEvent: is called again with the next stroke.
Update
In your code snippets you end up rendering the whole view three times every run loop. That's a lot of drawing overhead. I quickly put together some code that demonstrates what I am talking about above. It is not tested code, but it should be mostly right:
Update 2
I had a bit of time to write and test some code that will do what you are seeking based on my latest two comments. This code is from the view controller instead of the view itself, but with a little modification, you can move in the view if you like. As such, I added an UIImageView as a subview to the generic UIView to hold and display the image (and maintained a reference to in the view controller), and made the view controller the first responder in order to receive the touch events. Lots of hard coded values that you can clean up when integrating into your own project:
static
UIImage *CreateImage( CGRect rect, NSArray *paths )
{
UIGraphicsBeginImageContextWithOptions(rect.size, NO, 1.0);
CGContextRef context = UIGraphicsGetCurrentContext();
CGFloat colorComponents[4] = {0.0,0.0,0.0,0.0};
CGContextSetFillColor(context, colorComponents);
CGContextFillRect(context, rect);
for ( id obj in paths ) {
CGPathRef path = (CGPathRef)obj;
CGContextAddPath(context, path);
}
CGContextSetStrokeColorWithColor(context, [[UIColor redColor] CGColor]);
CGContextSetLineCap(context, kCGLineCapRound);
CGContextSetLineWidth(context, 5.0);
CGContextSetShadow(context, (CGSize){-8.0,40}, 5.0);
CGContextBeginTransparencyLayer(context, NULL);
CGContextDrawPath(context, kCGPathStroke);
CGContextEndTransparencyLayer(context);
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
static
CGPoint MidPoint( CGPoint pt1, CGPoint pt2 )
{
return (CGPoint){(pt1.x+pt2.x)/2.0,(pt1.y+pt2.y)/2.0};
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[super touchesBegan:touches withEvent:event];
CGPoint location = [[touches anyObject] locationInView:self.view];
myPath = CGPathCreateMutable();
CGPathMoveToPoint(myPath, NULL, location.x, location.y);
[self.paths addObject:(id)myPath];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
[super touchesMoved:touches withEvent:event];
UITouch *touch = [touches anyObject];
CGPoint previousLocation = [touch previousLocationInView:self.view];
CGPoint location = [touch locationInView:self.view];
CGPoint midPoint = MidPoint(previousLocation, location);
CGPathAddQuadCurveToPoint(myPath, NULL, midPoint.x, midPoint.y, location.x, location.y);
self.imageView.image = CreateImage(self.view.bounds, self.paths);
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
[super touchesEnded:touches withEvent:event];
UITouch *touch = [touches anyObject];
CGPoint previousLocation = [touch previousLocationInView:self.view];
CGPoint location = [touch locationInView:self.view];
CGPoint midPoint = MidPoint(previousLocation, location);
CGPathAddQuadCurveToPoint(myPath, NULL, midPoint.x, midPoint.y, location.x, location.y);
self.imageView.image = CreateImage(self.view.bounds, self.paths);
CGPathRelease(myPath);
myPath = nil;
}
the problem is you have multiple lines which lie above each other. So the shadows of both overlap and you get a darker color.
For something that easy like your line drawings you can simply copy the whole drawing code and redraw with a different color and a view pixel offset (instead of the shadow). E.g. you save the curves into an array and draw them separately later.
EDIT:
ok #gschandler describes the problem great too.
But you may also like to have a look at the Transparency Layer documentation. Group the elements together and apply a shadow for the group.
Another way round to this is to create an array of points on touch move events, and then draw them..
Create an array of points :
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[pointArray release]; pointArray = nil;
pointArray=[[NSMutableArray alloc] init];
UITouch *touch = [touches anyObject];
[bufferArray removeAllObjects];
previousPoint1 = [touch previousLocationInView:self];
previousPoint2 = [touch previousLocationInView:self];
currentPoint = [touch locationInView:self];
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
previousPoint2 = previousPoint1;
previousPoint1 = [touch previousLocationInView:self];
currentPoint = [touch locationInView:self];
[pointArray addObject: [NSValue valueWithCGPoint:previousPoint2]];
[pointArray addObject:[NSValue valueWithCGPoint:previousPoint1]];
[pointArray addObject:[NSValue valueWithCGPoint:currentPoint]];
[self setNeedsDisplay];
}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
}
-(void)drawRect:(CGRect)rect
{
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetLineCap(context, kCGLineCapRound);
CGContextSetLineWidth(context, self.lineWidth);
CGContextSetStrokeColorWithColor(context, self.lineColor.CGColor);
CGContextSetShadow(context, CGSizeMake(-16.00, -5.0f), 5.0f);
for(int i = 1 ; i < [pointArray count]-1;i++)
{
CGPoint mid1 = midPoint([pointArray objectAtIndex:i+1], [pointArray objectAtIndex:i]);
CGPoint mid2 = midPoint([pointArray objectAtIndex:i+2], [pointArray objectAtIndex:i+1]);
CGContextMoveToPoint(context, mid1.x, mid1.y);
CGContextAddQuadCurveToPoint(context, previousPoint1.x, previousPoint1.y, mid2.x, mid2.y);
i+=2;
}
CGContextStrokePath(context);
}
You can manage multiple lines with multiple dimensional array :)