Bump
In order to clarifiy things more, I'm pasting some code in here. This is how i capture finger movement:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
self.lastTouch = [[event touchesForView:self] anyObject];
[self renderTouch:self.lastTouch];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
self.lastTouch = [[event touchesForView:self] anyObject];
[self renderTouch:self.lastTouch];
}
- (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
self.lastTouch = nil;
if ( m_updateRect.size.width > 0 )
{
[self setNeedsDisplay];
}
}
The method renderTouch: renders the fingerpainting into a mask:
- (void) renderTouch:(UITouch *)touch
{
// ... render in mask here into m_maskContext
// this works !!
// m_updateRect = CGRectUnion( m_updateRect, [self updateRectFromTouch:touch] );
// this does not work ?!
if ( m_updateRect.size.width == 0 )
{
m_updateRect = [self updateRectFromTouch:touch];
}
else
{
m_updateRect = CGRectUnion( m_updateRect, [self updateRectFromTouch:touch] );
}
}
While the drawing is in progress, a timer periodically calls this method:
- (void) refreshScreen
{
if ( m_updateRect.size.width > 0 )
{
[self setNeedsDisplayInRect:m_updateRect];
m_updateRect = CGRectZero;
}
}
Which only calls setNeedsDisplayInRect: if there are any updates. In drawRect: finally, I check if I'm drawing only a portion of the screen or the whole thing:
- (void)drawRect:(CGRect)rect
{
// Drawing code
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetBlendMode ( context, kCGBlendModeNormal );
// Turn coordinate system around
CGContextTranslateCTM( context, 0.0, rect.size.height );
CGContextScaleCTM( context, 1.0, -1.0 );
BOOL drawFullScreen = rectIsEqualTo( rect, self.frame );
// Take masked image and render it
self.maskImage = CGBitmapContextCreateImage( m_maskContext );
// Use that to mask the ice image
CGImageRef maskedImage = CGImageCreateWithMask( self.image, self.maskImage );
if ( drawFullScreen )
{
// Draw the masked image into the context
CGContextDrawImage( context, self.frame, maskedImage );
}
else
{
// copy the portion from image to current context
CGImageRef partialImage = CGImageCreateWithImageInRect( maskedImage, rect );
CGContextDrawImage( context, rect, partialImage );
CGImageRelease( partialImage );
}
CGImageRelease( maskedImage );
}
Now, the thing that stuns me rigid is this: in the method renderTouch: there are two ways of updating the rectangle in need of updating. This method works:
m_updateRect = CGRectUnion( m_updateRect, [self updateRectFromTouch:touch] );
However, this is not correct. Since m_updateRect starts out as (0,0,0,0), this always begins at (0,0). What should happen is, that only the areas are coalesced for updated, that the user touched, like so:
if ( m_updateRect.size.width == 0 )
{
m_updateRect = [self updateRectFromTouch:touch];
}
else
{
m_updateRect = CGRectUnion( m_updateRect, [self updateRectFromTouch:touch] );
}
But all this does, is draw little white rectangles! Does anyone have an idea what the heck is going on?