CGPath : appliquer une CGAffineTransform
Bon juste pour info, j'ai fait la fonction CGPathApplyTransform, que j'ai en fait appelée CGPathCreateTransformedMutableCopy pour que le nom soit plus clair (et fasse penser à faire le CGPathRelease dessus) :
Cependant, cela reste lourd car recrée un CGPath (attention le CGPath créé a un retainCount de 1 et de plus ne touche pas au CGPath passé en argument... donc il faudra penser à faire un CGPathRelease non seulement sur le CGPath qu'on a passé en argument, mais aussi sur le CGMutablePathRef retourné par la fonction CGPathCreateTransformedMutableCopy, comme indiqué dans les commentaires).
Il est donc souvent bien plus préférable d'appliquer la transformation lors du dessin, et d'appliquer la transformation inverse (surtout si ce n'est qu'une translation) sur le CGPoint quand c'est un test type containsPoint qu'on veut faire.
<br />typedef struct {<br /> CGMutablePathRef newPath;<br /> CGAffineTransform* transform;<br />} CGPathInfoData;<br /><br />void PathElementTransform(void* info, const CGPathElement* element)<br />{<br /> CGPathInfoData* infoData = (CGPathInfoData*)info;<br /> switch(element->type)<br /> {<br /> case kCGPathElementMoveToPoint:<br /> CGPathMoveToPoint(infoData->newPath, infoData->transform, element->points[0].x, element->points[0].y);<br /> break;<br /> case kCGPathElementAddLineToPoint:<br /> CGPathAddLineToPoint(infoData->newPath, infoData->transform, element->points[0].x, element->points[0].y);<br /> break;<br /> case kCGPathElementAddQuadCurveToPoint:<br /> CGPathAddQuadCurveToPoint(infoData->newPath, infoData->transform, element->points[0].x, element->points[0].y, element->points[1].x, element->points[1].y);<br /> break;<br /> case kCGPathElementAddCurveToPoint:<br /> CGPathAddCurveToPoint(infoData->newPath, infoData->transform, element->points[0].x, element->points[0].y, element->points[1].x, element->points[1].y, element->points[2].x, element->points[2].y);<br /> break;<br /> case kCGPathElementCloseSubpath:<br /> CGPathCloseSubpath(infoData->newPath);<br /> break;<br /> }<br />}<br /><br />/** @brief Create a MutableCopy of path, after applying the transform matrix.<br /> *<br /> * path is untouched, to you still have the responsability to call CGPathRelease on it<br /> * the returned path has a retainCount of 1 so you also have the responsability to call CGPathRelease on it when done.<br /> *<br /> * Call example :<br /> *Â CGPathRef p = ...<br /> *Â CGMutablePathRef mp = CGPathCreateTransformedMutableCopy(p, CGAffineTransformMakeRotation(M_PI_4));<br /> *Â CGPathRelease(p);<br /> *Â ...<br /> *Â // p is not valid anymore, and typically you do sthg with mp here<br /> *Â ...<br /> *Â CGPathRelease(mp);<br /> */<br />CGMutablePathRef CGPathCreateTransformedMutableCopy(const CGPathRef path, CGAffineTransform m)<br />{<br /> CGPathInfoData infoData;<br /> infoData.newPath = CGPathCreateMutable();<br /> infoData.transform = &m;<br /> <br /> CGPathApply(path, &infoData, PathElementTransform);<br /> <br /> return infoData.newPath;<br />}<br />
A priori de ce que j'ai testé, elle fonctionne comme il faut, donc bon après à creuser plus profondément avant de dire qu'elle est bug-free mais bon. Ca peut toujours servir.Cependant, cela reste lourd car recrée un CGPath (attention le CGPath créé a un retainCount de 1 et de plus ne touche pas au CGPath passé en argument... donc il faudra penser à faire un CGPathRelease non seulement sur le CGPath qu'on a passé en argument, mais aussi sur le CGMutablePathRef retourné par la fonction CGPathCreateTransformedMutableCopy, comme indiqué dans les commentaires).
Il est donc souvent bien plus préférable d'appliquer la transformation lors du dessin, et d'appliquer la transformation inverse (surtout si ce n'est qu'une translation) sur le CGPoint quand c'est un test type containsPoint qu'on veut faire.
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
Enfin il est p'tet pas géré pile pareil qu'en Cocoa, mais il n'empêche qu'il existe les méthodes CGPathRetain et CGPathRelease... et que quand on crée un CGPath via CGPathCreateMutable ou CGPathCopy ou CGPathMutableCopy, il faut faire un CGPathRelease pour balancer... comme avec retain/release en Cocoa
En fait tout est basé sur CFRetain/CFRelease sous le capot.
Donc oui, CoreFoundation utilise la mécanique des retainCount aussi et les CGPath aussi par voie de faitÂ
Pour l'autorelease j'avais trouvé
#define CGAutorelease(x) (__typeof(x))[NSMakeCollectable(x) autorelease]
mais il y a peut-être mieux ...
PS : Je ne suis pas sûr que cette discussion ait sa place ici... on commence à dériver là ... on pourrait pas splitter les sujets ?
Makes a newly allocated Core Foundation object eligible for collection.
NS_INLINE id NSMakeCollectable(CFTypeRef cf) {
return cf ? (id)CFMakeCollectable(cf) : nil;
}
Discussion
This function is a wrapper for CFMakeCollectable, but its return type is id"avoiding the need for casting when using Cocoa objects.
This function may be useful when returning Core Foundation objects in code that must support both garbage-collected and non-garbage-collected environments, as illustrated in the following example.
- (CFDateRef)foo {
CFDateRef aCFDate;
// ...
return [NSMakeCollectable(aCFDate) autorelease];
}
Et puis c'est pas aussi simple/propre que ça j'ai l'impression, en tout cas moi ça m'embrouille un peu j'aurais peur de faire des leaks selon si on est dans un environnement avec ou sans GC...
Le dernier est surement non toll-free bridged si on en croit la doc
Maintenant, j'ai pris ce procédé sur les exemples Core-Animation de Theo-Cacao, et je n'ai pas d'autres références. (les autres sites qui l'utilisent sont celui que j'ai fait sur Core Animation, et quelques autres qui semblent s'en inspirer, alors ... )