J'ai trouvé une solution, mais il m'échappe encore comment exactement cela fonctionne. Voici le code:
Cette méthode retourne le rectangle donné de la même manière, dans laquelle la transformation de coordonnées dans le contexte flips le système de coordonnées contexte:
- (CGRect) flippedRect:(CGRect)rect
{
CGRect flippedRect = rect;
flippedRect.origin.y = self.bounds.size.height - rect.origin.y - rect.size.height;
return CGRectIntersection(self.bounds, flippedRect);
}
Calcule le rectangle à être mis à jour à partir de la touche emplacement. Notez que le rectangle se renversé:
- (CGRect) updateRectFromTouch:(UITouch *)touch
{
CGPoint location = [touch locationInView:self];
int d = RubbingSize;
CGRect touchRect = [self flippedRect:CGRectMake(location.x - d, location.y - d, 2*d, 2*d)];
return CGRectIntersection(self.frame, touchRect);
}
En render toucher les « rectangles » basculées de mise à jour sont sous la contrainte:
- (void) renderTouch:(UITouch *)touch
{
//
// Code to render into the mask here
//
if (m_updateRect.size.width == 0)
{
m_updateRect = [self updateRectFromTouch:touch];
}
else
{
m_updateRect = CGRectUnion(m_updateRect, [self updateRectFromTouch:touch]);
}
}
La vue entière est actualisée avec environ 20Hz au cours du processus de Fingerpainting. La méthode suivante est appelée à chaque 1/20ème seconde et soumet le rectangle pour le rendu:
- (void) refreshScreen
{
if (m_updateRect.size.width > 0)
{
[self setNeedsDisplayInRect:[self flippedRect:m_updateRect]];
}
}
Voici une méthode d'aide à comparer aux rectangles:
BOOL rectIsEqualTo(CGRect a, CGRect b)
{
return a.origin.x == b.origin.x && a.origin.y == b.origin.y && a.size.width == b.size.width && a.size.height == b.size.height;
}
Dans la drawRect: méthode, le rectangle de mise à jour est utilisé pour dessiner uniquement la partie à mettre à jour.
- (void)drawRect:(CGRect)rect
{
BOOL drawFullScreen = rectIsEqualTo(rect, self.frame);
// Drawing code
CGContextRef context = UIGraphicsGetCurrentContext();
// Turn coordinate system around
CGContextTranslateCTM(context, 0.0, self.frame.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
if (drawFullScreen)
{
// draw the full thing
CGContextDrawImage(context, self.frame, self.image);
}
else
{
CGImageRef partialImage = CGImageCreateWithImageInRect(self.image, [self flippedRect:m_updateRect]);
CGContextDrawImage(context, m_updateRect, partialPhoto);
CGImageRelease(partialImage);
}
...
// Reset update box
m_updateRect = CGRectZero;
}
Si quelqu'un peut m'expliquer pourquoi le retournement fonctionne, j'apprécierais.