26 #define DOM(aLayer) aLayer._DOMElement 47 to have a transform applied to it.
51 call
this in place of its \c -drawInContext:.
52 @param layer the layer to draw for
53 @param ctx the context to draw on
55 @delegate -(
void)displayLayer:(
CALayer)layer;
57 by implementing this method. 59 @implementation CALayer : CPObject 61 // Modifying the Layer Geometry 69 CGAffineTransform _affineTransform; 70 CGAffineTransform _sublayerTransform; 71 CGAffineTransform _sublayerTransformForSublayers; 73 CGRect _backingStoreFrame; 74 CGRect _standardBackingStoreFrame; 76 BOOL _hasSublayerTransform; 77 BOOL _hasCustomBackingStoreFrame; 84 CPColor _backgroundColor; 86 // Managing Layer Hierarchy 89 CPMutableArray _sublayers; 91 // Updating Layer Display 93 unsigned _runLoopUpdateMask; 94 BOOL _needsDisplayOnBoundsChange; 96 // Modifying the Delegate 100 BOOL _delegateRespondsToDisplayLayerSelector; 101 BOOL _delegateRespondsToDrawLayerInContextSelector; 103 // DOM Implementation 105 DOMElement _DOMElement; 106 DOMElement _DOMContentsElement; 111 CGAffineTransform _transformToLayer; 112 CGAffineTransform _transformFromLayer; 120 return [[[self class] alloc] init]; 132 _frame = CGRectMakeZero(); 134 _backingStoreFrame = CGRectMakeZero(); 135 _standardBackingStoreFrame = CGRectMakeZero(); 137 _bounds = CGRectMakeZero(); 138 _position = CGPointMakeZero(); 140 _anchorPoint = CGPointMake(0.5, 0.5); 141 _affineTransform = CGAffineTransformMakeIdentity(); 142 _sublayerTransform = CGAffineTransformMakeIdentity(); 144 _transformToLayer = CGAffineTransformMakeIdentity(); // FIXME? does it matter? 145 _transformFromLayer = CGAffineTransformMakeIdentity(); 154 _DOMElement = document.createElement("div"); 156 _DOMElement.style.overflow = "visible"; 157 _DOMElement.style.position = "absolute"; 158 _DOMElement.style.visibility = "visible"; 159 _DOMElement.style.top = "0px"; 160 _DOMElement.style.left = "0px"; 161 _DOMElement.style.zIndex = 0; 162 _DOMElement.style.width = "0px"; 163 _DOMElement.style.height = "0px"; 170 // Modifying the Layer Geometry 175 - (void)setBounds:(CGRect)aBounds 177 if (CGRectEqualToRect(_bounds, aBounds)) 180 var oldOrigin = _bounds.origin; 182 _bounds = CGRectMakeCopy(aBounds); 184 if (_hasSublayerTransform) 185 _CALayerUpdateSublayerTransformForSublayers(self); 187 // _hasSublayerTransform == true will handle this for us. 188 /*else if (!CGPointEqualToPoint(_bounds.origin, oldOrigin)) 190 var index = _sublayers.length; 192 // FIXME: This should climb the layer tree down. 194 _CALayerRecalculateGeometry(_sublayers[index], CALayerGeometryPositionMask); 197 _CALayerRecalculateGeometry(self, CALayerGeometryBoundsMask); 212 - (void)setPosition:(CGPoint)aPosition 214 if (CGPointEqualToPoint(_position, aPosition)) 217 _position = CGPointMakeCopy(aPosition); 219 _CALayerRecalculateGeometry(self, CALayerGeometryPositionMask); 234 - (void)setZPosition:(int)aZPosition 236 if (_zPosition == aZPosition) 239 _zPosition = aZPosition; 241 [self registerRunLoopUpdateWithMask:CALayerZPositionUpdateMask]; 248 - (void)setAnchorPoint:(CGPoint)anAnchorPoint 250 anAnchorPoint = CGPointMakeCopy(anAnchorPoint); 251 anAnchorPoint.x = MIN(1.0, MAX(0.0, anAnchorPoint.x)); 252 anAnchorPoint.y = MIN(1.0, MAX(0.0, anAnchorPoint.y)); 254 if (CGPointEqualToPoint(_anchorPoint, anAnchorPoint)) 257 _anchorPoint = anAnchorPoint; 259 if (_hasSublayerTransform) 260 _CALayerUpdateSublayerTransformForSublayers(self); 263 _position = CGPointMake(CGRectGetWidth(_bounds) * _anchorPoint.x, CGRectGetHeight(_bounds) * _anchorPoint.y); 265 _CALayerRecalculateGeometry(self, CALayerGeometryAnchorPointMask); 271 - (CGPoint)anchorPoint 280 - (void)setAffineTransform:(CGAffineTransform)anAffineTransform 282 if (CGAffineTransformEqualToTransform(_affineTransform, anAffineTransform)) 285 _affineTransform = CGAffineTransformMakeCopy(anAffineTransform); 287 _CALayerRecalculateGeometry(self, CALayerGeometryAffineTransformMask); 293 - (CGAffineTransform)affineTransform 295 return _affineTransform; 302 - (void)setSublayerTransform:(CGAffineTransform)anAffineTransform 304 if (CGAffineTransformEqualToTransform(_sublayerTransform, anAffineTransform)) 307 var hadSublayerTransform = _hasSublayerTransform; 309 _sublayerTransform = CGAffineTransformMakeCopy(anAffineTransform); 310 _hasSublayerTransform = !CGAffineTransformIsIdentity(_sublayerTransform); 312 if (_hasSublayerTransform) 314 _CALayerUpdateSublayerTransformForSublayers(self); 316 var index = _sublayers.length; 318 // FIXME: This should climb the layer tree down. 320 _CALayerRecalculateGeometry(_sublayers[index], CALayerGeometryParentSublayerTransformMask); 327 - (CGAffineTransform)sublayerTransform 329 return _sublayerTransform; 336 - (CGAffineTransform)transformToLayer 338 return _transformToLayer; 346 - (void)setFrame:(CGRect)aFrame 348 // FIXME: implement this 361 _frame = [self convertRect:_bounds toLayer:_superlayer]; 374 - (CGRect)backingStoreFrame 376 return _backingStoreFrame; 383 - (void)setBackingStoreFrame:(CGRect)aFrame 385 _hasCustomBackingStoreFrame = (aFrame != nil); 388 aFrame = CGRectMakeCopy(_standardBackingStoreFrame); 393 aFrame = [_superlayer convertRect:aFrame toLayer:nil]; 395 var bounds = [_superlayer bounds], 396 frame = [_superlayer convertRect:bounds toLayer:nil]; 398 aFrame.origin.x -= CGRectGetMinX(frame); 399 aFrame.origin.y -= CGRectGetMinY(frame); 402 aFrame = CGRectMakeCopy(aFrame); 405 if (!CGPointEqualToPoint(_backingStoreFrame.origin, aFrame.origin)) 406 [self registerRunLoopUpdateWithMask:CALayerFrameOriginUpdateMask]; 408 if (!CGSizeEqualToSize(_backingStoreFrame.size, aFrame.size)) 409 [self registerRunLoopUpdateWithMask:CALayerFrameSizeUpdateMask]; 411 _backingStoreFrame = aFrame; 414 // Providing Layer Content 428 - (void)setContents:(CGImage)contents 430 if (_contents == contents) 433 _contents = contents; 439 Composites this layer onto the super layer, and draws its contents as well. 444 if (USE_BUFFER && !_contents || !_context) 447 CGContextClearRect(_context, CGRectMake(0.0, 0.0, CGRectGetWidth(_backingStoreFrame), CGRectGetHeight(_backingStoreFrame))); 454 var superlayerTransform = _CALayerGetTransform(_superlayer, nil), 455 superlayerOrigin = CGPointApplyAffineTransform(_superlayer._bounds.origin, superlayerTransform); 457 transform = CGAffineTransformConcat(_transformFromLayer, superlayerTransform); 459 transform.tx -= superlayerOrigin.x; 460 transform.ty -= superlayerOrigin.y; 464 // Copy so we don't affect the original.
465 transform = CGAffineTransformCreateCopy(_transformFromLayer);
467 transform.tx -= CGRectGetMinX(_backingStoreFrame);
468 transform.ty -= CGRectGetMinY(_backingStoreFrame);
477 _context.drawImage(_contents.buffer, CGRectGetMinX(_bounds), CGRectGetMinY(_bounds));
480 [
self drawInContext:_context];
495 _DOMContentsElement = _context.DOMElement;
497 _DOMContentsElement.style.zIndex = -100;
499 _DOMContentsElement.style.overflow =
"hidden";
500 _DOMContentsElement.style.position =
"absolute";
501 _DOMContentsElement.style.visibility =
"visible";
503 _DOMContentsElement.width = ROUND(CGRectGetWidth(_backingStoreFrame));
504 _DOMContentsElement.height = ROUND(CGRectGetHeight(_backingStoreFrame));
506 _DOMContentsElement.style.top =
"0px";
507 _DOMContentsElement.style.left =
"0px";
508 _DOMContentsElement.style.width = ROUND(CGRectGetWidth(_backingStoreFrame)) +
"px";
509 _DOMContentsElement.style.height = ROUND(CGRectGetHeight(_backingStoreFrame)) +
"px";
511 _DOMElement.appendChild(_DOMContentsElement);
516 if (_delegateRespondsToDisplayLayerSelector)
517 return [_delegate displayLayer:self];
519 if (CGRectGetWidth(_backingStoreFrame) == 0.0 || CGRectGetHeight(_backingStoreFrame) == 0.0)
523 _contents = CABackingStoreCreate();
527 [
self drawInContext:CABackingStoreGetContext(_contents)];
538 - (void)drawInContext:(CGContext)aContext
540 if (_backgroundColor)
546 if (_delegateRespondsToDrawLayerInContextSelector)
547 [_delegate drawLayer:self inContext:aContext];
565 - (void)setOpacity:(
float)anOpacity
567 if (_opacity == anOpacity)
570 _opacity = anOpacity;
572 _DOMElement.style.opacity = anOpacity;
573 _DOMElement.style.filter =
"alpha(opacity=" + anOpacity * 100 +
")";
580 - (void)setHidden:(BOOL)isHidden
583 _DOMElement.style.display =
isHidden ?
"none" :
"block";
606 - (void)setMasksToBounds:(BOOL)masksToBounds
608 if (_masksToBounds == masksToBounds)
611 _masksToBounds = masksToBounds;
612 _DOMElement.style.overflow = _masksToBounds ?
"hidden" :
"visible";
621 _backgroundColor = aColor;
623 [
self setNeedsDisplay];
631 return _backgroundColor;
651 #define ADJUST_CONTENTS_ZINDEX(aLayer)\ 652 if (_DOMContentsElement && aLayer._zPosition > _DOMContentsElement.style.zIndex)\ 653 _DOMContentsElement.style.zIndex -= 100.0;\ 660 [
self insertSublayer:aLayer atIndex:_sublayers.length];
669 [_owningView setLayer:nil];
674 _superlayer._DOMElement.removeChild(_DOMElement);
675 [_superlayer._sublayers removeObject:self];
685 - (void)insertSublayer:(
CALayer)aLayer atIndex:(CPUInteger)anIndex
694 var index = [_sublayers indexOfObjectIdenticalTo:aLayer];
696 if (index == anIndex)
699 [_sublayers removeObjectAtIndex:index];
705 [aLayer removeFromSuperlayer];
709 [_sublayers insertObject:aLayer atIndex:anIndex];
712 if (anIndex >= _sublayers.length - 1)
713 _DOMElement.appendChild(
DOM(aLayer));
715 _DOMElement.insertBefore(
DOM(aLayer), _sublayers[anIndex + 1]._DOMElement);
718 aLayer._superlayer =
self;
721 _CALayerRecalculateGeometry(aLayer, 0xFFFFFFF);
732 var index = aSublayer ? [_sublayers indexOfObjectIdenticalTo:aSublayer] : 0;
734 [
self insertSublayer:aLayer atIndex:index == CPNotFound ? _sublayers.length : index];
745 var index = aSublayer ? [_sublayers indexOfObjectIdenticalTo:aSublayer] : _sublayers.length;
750 [_sublayers insertObject:aLayer atIndex:index == CPNotFound ? _sublayers.length : index + 1];
760 if (aSublayer == aLayer)
763 if (aSublayer._superlayer !=
self)
765 CPLog.warn(
"Attempt to replace a sublayer (%s) which is not in the sublayers of the receiver (%s).", [aSublayer
description], [
self description]);
771 [_sublayers replaceObjectAtIndex:[_sublayers indexOfObjectIdenticalTo:aSublayer] withObject:aLayer];
772 _DOMElement.replaceChild(
DOM(aSublayer),
DOM(aLayer));
785 mask =
layer._runLoopUpdateMask;
788 _CALayerUpdateDOM(
layer, mask);
795 layer._runLoopUpdateMask = 0;
805 - (void)registerRunLoopUpdateWithMask:(
unsigned)anUpdateMask
815 _runLoopUpdateMask |= anUpdateMask;
824 [
self registerRunLoopUpdateWithMask:CALayerCompositeUpdateMask];
832 [
self registerRunLoopUpdateWithMask:CALayerDisplayUpdateMask];
839 - (void)setNeedsDisplayOnBoundsChange:(BOOL)needsDisplayOnBoundsChange
849 return _needsDisplayOnBoundsChange;
856 - (void)setNeedsDisplayInRect:(CGRect)aRect
869 - (CGPoint)convertPoint:(CGPoint)aPoint fromLayer:(
CALayer)aLayer
880 - (CGPoint)convertPoint:(CGPoint)aPoint toLayer:(
CALayer)aLayer
891 - (CGRect)convertRect:(CGRect)aRect fromLayer:(
CALayer)aLayer
893 return CGRectApplyAffineTransform(aRect, _CALayerGetTransform(aLayer,
self));
902 - (CGRect)convertRect:(CGRect)aRect toLayer:(
CALayer)aLayer
904 return CGRectApplyAffineTransform(aRect, _CALayerGetTransform(
self, aLayer));
912 - (BOOL)containsPoint:(CGPoint)aPoint
914 return CGRectContainsPoint(_bounds, aPoint);
929 if (!CGRectContainsPoint(_bounds, point))
933 index = _sublayers.length;
937 if (
layer = [_sublayers[index] hitTest:point])
948 - (void)setDelegate:(
id)aDelegate
950 if (_delegate == aDelegate)
953 _delegate = aDelegate;
955 _delegateRespondsToDisplayLayerSelector = [_delegate respondsToSelector:@selector(displayLayer:)];
956 _delegateRespondsToDrawLayerInContextSelector = [_delegate respondsToSelector:@selector(drawLayer:inContext:)];
958 if (_delegateRespondsToDisplayLayerSelector || _delegateRespondsToDrawLayerInContextSelector)
959 [
self setNeedsDisplay];
971 - (void)_setOwningView:(
CPView)anOwningView
973 _owningView = anOwningView;
977 _owningView = anOwningView;
979 _bounds.size = CGSizeMakeCopy([_owningView
bounds].size);
980 _position = CGPointMake(CGRectGetWidth(_bounds) * _anchorPoint.x, CGRectGetHeight(_bounds) * _anchorPoint.y);
987 - (void)_owningViewBoundsChanged
989 _bounds.size = CGSizeMakeCopy([_owningView
bounds].size);
990 _position = CGPointMake(CGRectGetWidth(_bounds) * _anchorPoint.x, CGRectGetHeight(_bounds) * _anchorPoint.y);
1000 var mask = _runLoopUpdateMask;
1003 _CALayerUpdateDOM(
self, mask);
1011 _runLoopUpdateMask = 0;
1013 window.loop =
false;
1018 function _CALayerUpdateSublayerTransformForSublayers(aLayer)
1020 var
bounds = aLayer._bounds,
1031 function _CALayerUpdateDOM(aLayer, aMask)
1034 var DOMElementStyle = aLayer._DOMElement.style;
1037 DOMElementStyle.zIndex = aLayer._zPosition;
1039 var
frame = aLayer._backingStoreFrame;
1043 DOMElementStyle.top = ROUND(CGRectGetMinY(
frame)) + "px";
1044 DOMElementStyle.left = ROUND(CGRectGetMinX(
frame)) + "px";
1049 var
width = MAX(0.0, ROUND(CGRectGetWidth(
frame))),
1050 height = MAX(0.0, ROUND(CGRectGetHeight(
frame))),
1051 DOMContentsElement = aLayer._DOMContentsElement;
1053 DOMElementStyle.width =
width + "px";
1054 DOMElementStyle.height = height + "px";
1056 if (DOMContentsElement)
1058 DOMContentsElement.width =
width;
1059 DOMContentsElement.height = height;
1060 DOMContentsElement.style.width =
width + "px";
1061 DOMContentsElement.style.height = height + "px";
1067 function _CALayerRecalculateGeometry(aLayer, aGeometryChange)
1069 var
bounds = aLayer._bounds,
1072 height = CGRectGetHeight(
bounds),
1076 backingStoreFrameSize = CGSizeMakeCopy(aLayer._backingStoreFrame),
1077 hasCustomBackingStoreFrame = aLayer._hasCustomBackingStoreFrame;
1091 aLayer._transformToLayer = CGAffineTransformInvert(aLayer._transformFromLayer);
1096 aLayer._frame = nil;
1097 aLayer._standardBackingStoreFrame = [aLayer convertRect:bounds toLayer:nil];
1101 var
bounds = [superlayer bounds],
1102 frame = [superlayer convertRect:bounds toLayer:nil];
1104 aLayer._standardBackingStoreFrame.origin.x -= CGRectGetMinX(
frame);
1105 aLayer._standardBackingStoreFrame.origin.y -= CGRectGetMinY(
frame);
1113 var origin = aLayer._standardBackingStoreFrame.origin,
1114 size = aLayer._standardBackingStoreFrame.size;
1116 origin.x = FLOOR(origin.x);
1117 origin.y = FLOOR(origin.y);
1118 size.width = CEIL(size.width) + 1.0;
1119 size.height = CEIL(size.height) + 1.0;
1125 if (!hasCustomBackingStoreFrame)
1131 if (ROUND(CGRectGetMinX(
backingStoreFrame)) != ROUND(CGRectGetMinX(aLayer._backingStoreFrame)) ||
1132 ROUND(CGRectGetMinY(
backingStoreFrame)) != ROUND(CGRectGetMinY(aLayer._backingStoreFrame)))
1133 [aLayer registerRunLoopUpdateWithMask:CALayerFrameOriginUpdateMask];
1136 if ((CGRectGetWidth(
backingStoreFrame) != ROUND(CGRectGetWidth(aLayer._backingStoreFrame)) ||
1137 CGRectGetHeight(
backingStoreFrame) != ROUND(CGRectGetHeight(aLayer._backingStoreFrame))))
1138 [aLayer registerRunLoopUpdateWithMask:CALayerFrameSizeUpdateMask];
1144 [aLayer setNeedsDisplay];
1150 [aLayer setNeedsComposite];
1156 for (; index < count; ++index)
1157 _CALayerRecalculateGeometry(
sublayers[index], aGeometryChange);
1160 function _CALayerGetTransform(fromLayer, toLayer)
1166 var
layer = fromLayer;
1172 var transformFromLayer =
layer._transformFromLayer;
1181 if (
layer == toLayer)
1194 var index = layers.length;
void removeFromSuperlayer()
Used to implement exception handling (creating & raising).
A CALayer is similar to a CPView
void runLoopUpdateLayers()
The main run loop for the application.
#define ADJUST_CONTENTS_ZINDEX(aLayer)
var CALayerCompositeUpdateMask
void performSelector:target:argument:order:modes:(SEL aSelector, [target] id aTarget, [argument] id anArgument, [order] int anOrder, [modes] CPArray modes)
function CGContextRestoreGState(aContext)
void raise:reason:(CPString aName, [reason] CPString aReason)
var CALayerGeometryBoundsMask
CPRunLoop currentRunLoop()
var CALayerFrameSizeUpdateMask
var CALayerGeometryAffineTransformMask
var CALayerRegisteredRunLoopUpdates
CGAffineTransform transformToLayer()
var CALayerZPositionUpdateMask
If the delegate implements this method
function CGContextSetFillColor(aContext, aColor)
CPColor backgroundColor()
var CALayerDisplayUpdateMask
var CALayerGeometryAnchorPointMask
function CGContextSaveGState(aContext)
var CALayerGeometryPositionMask
CGAffineTransform affineTransform()
var CALayerGeometryParentSublayerTransformMask
function CGContextFillRect(aContext, aRect)
function CGContextConcatCTM(aContext, aTransform)
BOOL needsDisplayOnBoundsChange()
function CGBitmapGraphicsContextCreate()
var CALayerFrameOriginUpdateMask
FrameUpdater prototype description
CGRect backingStoreFrame()