I am working on a drawing project, where I have an eraser option. The code given below is for when I start my app and draw some lines and the proceed to use the eraser. It works fine and I get the eraser effect. Now the second scenario is where I draw some 10 lines and then click on the "undo button" and undo the whole thing, then I redo the whole thing, and now when I click on the "eraser button" and try to erase some part, but instead, it will clear the whole drawing. This is what I am trying to figure out, but i'm not understanding where I am going wrong so friends, please help me out.

Below is my code.

- (void)drawRect:(CGRect)rect
{


      case DRAW:
    {
        [m_curImage drawAtPoint:CGPointMake(0, 0)];

        CGPoint mid1 = midPoint(m_previousPoint1, m_previousPoint2); 
        CGPoint mid2 = midPoint(m_currentPoint, m_previousPoint1);
        CGContextRef context = UIGraphicsGetCurrentContext(); 



        [self.layer renderInContext:context];
        CGContextMoveToPoint(context, mid1.x, mid1.y);
        CGContextAddQuadCurveToPoint(context, m_previousPoint1.x, m_previousPoint1.y, mid2.x, mid2.y); 
        CGContextSetLineCap(context, kCGLineCapRound);
        CGContextSetLineWidth(context, self.lineWidth);
        CGContextSetStrokeColorWithColor(context, self.lineColor.CGColor);
        CGContextSetAlpha(context, self.lineAlpha);
        CGContextSetAllowsAntialiasing(context, YES);
        CGContextStrokePath(context); 
       //            [super drawRect:rect];           
    }
         break;



        case ERASE:
        {
            [m_curImage drawAtPoint:CGPointMake(0, 0)];
            CGContextRef context = UIGraphicsGetCurrentContext();     
            CGContextClearRect(context, rect);                
            CGContextSetBlendMode(context, kCGBlendModeClear);
            [super drawRect:rect];
            break;                

  }      


        case UNDO:
        {
            [m_curImage drawInRect:self.bounds];
             break;

        }

        case REDO:
        {
            [m_curImage drawInRect:self.bounds];  
             break;           
        }


        default:
            break;
    }    
}

These are functions that run when I click on undo/redo.

-(void)redrawLine
{
    UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, 0.0f);
    [self.layer renderInContext:UIGraphicsGetCurrentContext()];
    NSDictionary *lineInfo = [m_lineArray lastObject];
    m_curImage = (UIImage*)[lineInfo valueForKey:@"IMAGE"];
    UIGraphicsEndImageContext();
    [self setNeedsDisplayInRect:self.bounds];   
}


-(void)undoButtonClicked
{
    if([m_lineArray count] > 0)
    {
        NSMutableArray *line = [m_lineArray lastObject];
        [m_bufferArray addObject:line];
        [m_lineArray removeLastObject];
        [self redrawLine];
    }
    m_drawStep = UNDO;

}

-(void)redoButtonClicked
{
    if([m_bufferArray count] > 0)
    {
        NSMutableArray *line = [m_bufferArray lastObject];
        [m_lineArray addObject:line];
        [m_bufferArray removeLastObject];        
        [self redrawLine];
    }
     m_drawStep = REDO;

}

Please tell me whether I am doing it right.

Regards,

Ranjit


Solution 1:

I have solved this issue, the problem and below is the code which works perfectly

case :ERASE
{
 CGPoint mid1 = midPoint(m_previousPoint1, m_previousPoint2); 
            CGPoint mid2 = midPoint(m_currentPoint, m_previousPoint1);

            [m_curImage drawAtPoint:CGPointMake(0, 0)];
            CGContextRef context = UIGraphicsGetCurrentContext(); 

            [self.layer renderInContext:context];
            CGContextMoveToPoint(context, mid1.x, mid1.y);
            CGContextAddQuadCurveToPoint(context, m_previousPoint1.x, m_previousPoint1.y, mid2.x, mid2.y); 
            CGContextSetLineCap(context, kCGLineCapRound);


            CGContextSetBlendMode(context, kCGBlendModeClear);
            CGContextSetLineJoin(context, kCGLineJoinRound);
            CGContextSetLineWidth(context, self.lineWidth);
            CGContextSetStrokeColorWithColor(context, self.lineColor.CGColor);
            CGContextSetShouldAntialias(context, YES);  
            CGContextSetAllowsAntialiasing(context, YES); 
            CGContextSetFlatness(context, 0.1f);

            CGContextSetAlpha(context, self.lineAlpha);
            CGContextStrokePath(context); 
}

Regards Ranjit.

This solved my issue, if anyone has the same issue, please implement this.

Solution 2:

Here what is happening is when you erase the whole rect will get clear na?? so instead of using that erase method draw line in same color that of screen so that it will look like window is clearing and its easy too jus try out this.

For example if your drawing screen is black then draw line for touchesmoved on screen in black color so that it will look like clearing.

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
  lastPoint = [touch locationInView:imagevw];
  }

  -(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
   UITouch *touch = [touches anyObject];
   CGPoint currentPoint = [touch locationInView:imagevw];
   UIGraphicsBeginImageContext(self.imagevw.frame.size);

  [self.imagevw.image drawInRect:CGRectMake(0, 0, self.imagevw.frame.size.width,        self.imagevw.frame.size.height)];
    CGContextSetLineWidth(UIGraphicsGetCurrentContext(), width);
    CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), 0.0, 0.0, 0.0, 1.0); // black color
    CGContextBeginPath(UIGraphicsGetCurrentContext());
    CGContextMoveToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y);
    CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), currentPoint.x, currentPoint.y);
    CGContextStrokePath(UIGraphicsGetCurrentContext());
     imagevw.image = UIGraphicsGetImageFromCurrentImageContext();
     UIGraphicsEndImageContext();

This is code to draw line in black color on black view... just try out...it may help you..