SVGGElement.m 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. #import "SVGGElement.h"
  2. #import "CALayerWithChildHitTest.h"
  3. #import "SVGHelperUtilities.h"
  4. @implementation SVGGElement
  5. @synthesize transform; // each SVGElement subclass that conforms to protocol "SVGTransformable" has to re-synthesize this to work around bugs in Apple's Objective-C 2.0 design that don't allow @properties to be extended by categories / protocols
  6. - (CALayer *) newLayer
  7. {
  8. CALayer* _layer = [CALayerWithChildHitTest layer];
  9. [SVGHelperUtilities configureCALayer:_layer usingElement:self];
  10. return _layer;
  11. }
  12. - (void)layoutLayer:(CALayer *)layer {
  13. // null rect union any other rect will return the other rect
  14. CGRect mainRect = CGRectNull;
  15. /** make mainrect the UNION of all sublayer's frames (i.e. their individual "bounds" inside THIS layer's space) */
  16. for ( CALayer *currentLayer in [layer sublayers] )
  17. {
  18. CGRect subLayerFrame = currentLayer.frame;
  19. mainRect = CGRectUnion(mainRect, subLayerFrame);
  20. }
  21. NSAssert(!CGRectIsNull(mainRect), @"A G element has been generated with non-existent size and no contents. Apple cannot cope with this. As a workaround, we are resetting your layer to empty, but this may have unwanted side-effects (hard to test)" );
  22. if (CGRectIsNull(mainRect))
  23. {
  24. return;
  25. }
  26. else
  27. {
  28. /** use mainrect (union of all sub-layer bounds) this layer's FRAME
  29. i.e. top-left-corner of this layer will be "the top left corner of the convex-hull rect of all sublayers"
  30. AND: bottom-right-corner of this layer will be "the bottom-right corner of the convex-hull rect of all sublayers"
  31. */
  32. layer.frame = mainRect;
  33. /**
  34. If this group layer has a mask then since we've adjusted this layer's frame we need to offset the mask's frame by the opposite amount.
  35. */
  36. if (layer.mask)
  37. layer.mask.frame = CGRectOffset(layer.mask.frame, -mainRect.origin.x, -mainRect.origin.y);
  38. /** Changing THIS layer's frame now means all DIRECT sublayers are offset by too much (because when we change the offset
  39. of the parent frame (this.frame), Apple *does not* shift the sublayers around to keep them in same place.
  40. NB: there are bugs in some Apple code in Interface Builder where it attempts to do exactly that (incorrectly, as the API
  41. is specifically designed NOT to do this), and ... Fails. But in code, thankfully, Apple *almost* never does this (there are a few method
  42. calls where it appears someone at Apple forgot how their API works, and tried to do the offsetting automatically. "Paved
  43. with good intentions...".
  44. */
  45. for (CALayer *currentLayer in [layer sublayers]) {
  46. CGRect frame = currentLayer.frame;
  47. frame.origin.x -= mainRect.origin.x;
  48. frame.origin.y -= mainRect.origin.y;
  49. currentLayer.frame = frame;
  50. }
  51. }
  52. }
  53. @end