![]() |
API 0.9.5
|
00001 /* 00002 * CALayer.j 00003 * AppKit 00004 * 00005 * Created by Francisco Tolmasky. 00006 * Copyright 2008, 280 North, Inc. 00007 * 00008 * This library is free software; you can redistribute it and/or 00009 * modify it under the terms of the GNU Lesser General Public 00010 * License as published by the Free Software Foundation; either 00011 * version 2.1 of the License, or (at your option) any later version. 00012 * 00013 * This library is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00016 * Lesser General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU Lesser General Public 00019 * License along with this library; if not, write to the Free Software 00020 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00021 */ 00022 00023 00024 00025 00026 00027 #define DOM(aLayer) aLayer._DOMElement 00028 00029 var CALayerGeometryBoundsMask = 1, 00030 CALayerGeometryPositionMask = 2, 00031 CALayerGeometryAnchorPointMask = 4, 00032 CALayerGeometryAffineTransformMask = 8, 00033 CALayerGeometryParentSublayerTransformMask = 16; 00034 var USE_BUFFER = NO; 00035 00036 var CALayerFrameOriginUpdateMask = 1, 00037 CALayerFrameSizeUpdateMask = 2, 00038 CALayerZPositionUpdateMask = 4, 00039 CALayerDisplayUpdateMask = 8, 00040 CALayerCompositeUpdateMask = 16, 00041 CALayerDOMUpdateMask = CALayerZPositionUpdateMask | CALayerFrameOriginUpdateMask | CALayerFrameSizeUpdateMask; 00042 00043 var CALayerRegisteredRunLoopUpdates = nil; 00044 00060 @implementation CALayer : CPObject 00061 { 00062 // Modifying the Layer Geometry 00063 00064 CGRect _frame; 00065 CGRect _bounds; 00066 CGPoint _position; 00067 unsigned _zPosition; 00068 CGPoint _anchorPoint; 00069 00070 CGAffineTransform _affineTransform; 00071 CGAffineTransform _sublayerTransform; 00072 CGAffineTransform _sublayerTransformForSublayers; 00073 00074 CGRect _backingStoreFrame; 00075 CGRect _standardBackingStoreFrame; 00076 00077 BOOL _hasSublayerTransform; 00078 BOOL _hasCustomBackingStoreFrame; 00079 00080 // Style Attributes 00081 00082 float _opacity; 00083 BOOL _isHidden; 00084 CPColor _backgroundColor; 00085 00086 // Managing Layer Hierarchy 00087 00088 CALayer _superlayer; 00089 CPMutableArray _sublayers; 00090 00091 // Updating Layer Display 00092 00093 unsigned _runLoopUpdateMask; 00094 BOOL _needsDisplayOnBoundsChange; 00095 00096 // Modifying the Delegate 00097 00098 id _delegate; 00099 00100 BOOL _delegateRespondsToDisplayLayerSelector; 00101 BOOL _delegateRespondsToDrawLayerInContextSelector; 00102 00103 // DOM Implementation 00104 00105 DOMElement _DOMElement; 00106 DOMElement _DOMContentsElement; 00107 id _contents; 00108 CGContext _context; 00109 CPView _owningView; 00110 00111 CGAffineTransform _transformToLayer; 00112 CGAffineTransform _transformFromLayer; 00113 } 00114 00118 + (CALayer)layer 00119 { 00120 return [[[self class] alloc] init]; 00121 } 00122 00126 - (id)init 00127 { 00128 self = [super init]; 00129 00130 if (self) 00131 { 00132 _frame = CGRectMakeZero(); 00133 00134 _backingStoreFrame = CGRectMakeZero(); 00135 _standardBackingStoreFrame = CGRectMakeZero(); 00136 00137 _bounds = CGRectMakeZero(); 00138 _position = CGPointMakeZero(); 00139 _zPosition = 0.0; 00140 _anchorPoint = CGPointMake(0.5, 0.5); 00141 _affineTransform = CGAffineTransformMakeIdentity(); 00142 _sublayerTransform = CGAffineTransformMakeIdentity(); 00143 00144 _transformToLayer = CGAffineTransformMakeIdentity(); // FIXME? does it matter? 00145 _transformFromLayer = CGAffineTransformMakeIdentity(); 00146 00147 _opacity = 1.0; 00148 _isHidden = NO; 00149 _masksToBounds = NO; 00150 00151 _sublayers = []; 00152 00153 _DOMElement = document.createElement("div"); 00154 00155 _DOMElement.style.overflow = "visible"; 00156 _DOMElement.style.position = "absolute"; 00157 _DOMElement.style.visibility = "visible"; 00158 _DOMElement.style.top = "0px"; 00159 _DOMElement.style.left = "0px"; 00160 _DOMElement.style.zIndex = 0; 00161 _DOMElement.style.width = "0px"; 00162 _DOMElement.style.height = "0px"; 00163 } 00164 00165 return self; 00166 } 00167 00168 // Modifying the Layer Geometry 00173 - (void)setBounds:(CGRect)aBounds 00174 { 00175 if (CGRectEqualToRect(_bounds, aBounds)) 00176 return; 00177 00178 var oldOrigin = _bounds.origin; 00179 00180 _bounds = _CGRectMakeCopy(aBounds); 00181 00182 if (_hasSublayerTransform) 00183 _CALayerUpdateSublayerTransformForSublayers(self); 00184 00185 // _hasSublayerTransform == true will handle this for us. 00186 /*else if (!CGPointEqualToPoint(_bounds.origin, oldOrigin)) 00187 { 00188 var index = _sublayers.length; 00189 00190 // FIXME: This should climb the layer tree down. 00191 while (index--) 00192 _CALayerRecalculateGeometry(_sublayers[index], CALayerGeometryPositionMask); 00193 }*/ 00194 00195 _CALayerRecalculateGeometry(self, CALayerGeometryBoundsMask); 00196 } 00197 00201 - (CGRect)bounds 00202 { 00203 return _bounds; 00204 } 00205 00210 - (void)setPosition:(CGPoint)aPosition 00211 { 00212 if (CGPointEqualToPoint(_position, aPosition)) 00213 return; 00214 00215 _position = _CGPointMakeCopy(aPosition); 00216 00217 _CALayerRecalculateGeometry(self, CALayerGeometryPositionMask); 00218 } 00219 00223 - (CGPoint)position 00224 { 00225 return _position; 00226 } 00227 00232 - (void)setZPosition:(int)aZPosition 00233 { 00234 if (_zPosition == aZPosition) 00235 return; 00236 00237 _zPosition = aZPosition; 00238 00239 [self registerRunLoopUpdateWithMask:CALayerZPositionUpdateMask]; 00240 } 00241 00246 - (void)setAnchorPoint:(CGPoint)anAnchorPoint 00247 { 00248 anAnchorPoint = _CGPointMakeCopy(anAnchorPoint); 00249 anAnchorPoint.x = MIN(1.0, MAX(0.0, anAnchorPoint.x)); 00250 anAnchorPoint.y = MIN(1.0, MAX(0.0, anAnchorPoint.y)); 00251 00252 if (CGPointEqualToPoint(_anchorPoint, anAnchorPoint)) 00253 return; 00254 00255 _anchorPoint = anAnchorPoint; 00256 00257 if (_hasSublayerTransform) 00258 _CALayerUpdateSublayerTransformForSublayers(self); 00259 00260 if (_owningView) 00261 _position = CGPointMake(_CGRectGetWidth(_bounds) * _anchorPoint.x, _CGRectGetHeight(_bounds) * _anchorPoint.y); 00262 00263 _CALayerRecalculateGeometry(self, CALayerGeometryAnchorPointMask); 00264 } 00265 00269 - (CGPoint)anchorPoint 00270 { 00271 return _anchorPoint; 00272 } 00273 00278 - (void)setAffineTransform:(CGAffineTransform)anAffineTransform 00279 { 00280 if (CGAffineTransformEqualToTransform(_affineTransform, anAffineTransform)) 00281 return; 00282 00283 _affineTransform = _CGAffineTransformMakeCopy(anAffineTransform); 00284 00285 _CALayerRecalculateGeometry(self, CALayerGeometryAffineTransformMask); 00286 } 00287 00291 - (CGAffineTransform)affineTransform 00292 { 00293 return _affineTransform; 00294 } 00295 00300 - (void)setSublayerTransform:(CGAffineTransform)anAffineTransform 00301 { 00302 if (CGAffineTransformEqualToTransform(_sublayerTransform, anAffineTransform)) 00303 return; 00304 00305 var hadSublayerTransform = _hasSublayerTransform; 00306 00307 _sublayerTransform = _CGAffineTransformMakeCopy(anAffineTransform); 00308 _hasSublayerTransform = !_CGAffineTransformIsIdentity(_sublayerTransform); 00309 00310 if (_hasSublayerTransform) 00311 { 00312 _CALayerUpdateSublayerTransformForSublayers(self); 00313 00314 var index = _sublayers.length; 00315 00316 // FIXME: This should climb the layer tree down. 00317 while (index--) 00318 _CALayerRecalculateGeometry(_sublayers[index], CALayerGeometryParentSublayerTransformMask); 00319 } 00320 } 00321 00325 - (CGAffineTransform)sublayerTransform 00326 { 00327 return _sublayerTransform; 00328 } 00329 00330 /* 00331 Private 00332 @ignore 00333 */ 00334 - (CGAffineTransform)transformToLayer 00335 { 00336 return _transformToLayer; 00337 } 00338 00344 - (void)setFrame:(CGRect)aFrame 00345 { 00346 alert("FIXME IMPLEMENT"); 00347 } 00348 00356 - (CGRect)frame 00357 { 00358 if (!_frame) 00359 _frame = [self convertRect:_bounds toLayer:_superlayer]; 00360 00361 return _frame; 00362 } 00363 00372 - (CGRect)backingStoreFrame 00373 { 00374 return _backingStoreFrame; 00375 } 00376 00381 - (void)setBackingStoreFrame:(CGRect)aFrame 00382 { 00383 _hasCustomBackingStoreFrame = (aFrame != nil); 00384 00385 if (aFrame == nil) 00386 aFrame = CGRectMakeCopy(_standardBackingStoreFrame); 00387 else 00388 { 00389 if (_superlayer) 00390 { 00391 aFrame = [_superlayer convertRect:aFrame toLayer:nil]; 00392 00393 var bounds = [_superlayer bounds], 00394 frame = [_superlayer convertRect:bounds toLayer:nil]; 00395 00396 aFrame.origin.x -= _CGRectGetMinX(frame); 00397 aFrame.origin.y -= _CGRectGetMinY(frame); 00398 } 00399 else 00400 aFrame = CGRectMakeCopy(aFrame); 00401 } 00402 00403 if (!CGPointEqualToPoint(_backingStoreFrame.origin, aFrame.origin)) 00404 [self registerRunLoopUpdateWithMask:CALayerFrameOriginUpdateMask]; 00405 00406 if (!CGSizeEqualToSize(_backingStoreFrame.size, aFrame.size)) 00407 [self registerRunLoopUpdateWithMask:CALayerFrameSizeUpdateMask]; 00408 00409 _backingStoreFrame = aFrame; 00410 } 00411 00412 // Providing Layer Content 00417 - (CGImage)contents 00418 { 00419 return _contents; 00420 } 00421 00426 - (void)setContents:(CGImage)contents 00427 { 00428 if (_contents == contents) 00429 return; 00430 00431 _contents = contents; 00432 00433 [self composite]; 00434 } 00435 00436 /* 00437 Composites this layer onto the super layer, and draws its contents as well. 00438 @ignore 00439 */ 00440 - (void)composite 00441 { 00442 if (USE_BUFFER && !_contents || !_context) 00443 return; 00444 00445 CGContextClearRect(_context, _CGRectMake(0.0, 0.0, _CGRectGetWidth(_backingStoreFrame), _CGRectGetHeight(_backingStoreFrame))); 00446 00447 // Recomposite 00448 var transform; 00449 00450 if (_superlayer) 00451 { 00452 var superlayerTransform = _CALayerGetTransform(_superlayer, nil), 00453 superlayerOrigin = CGPointApplyAffineTransform(_superlayer._bounds.origin, superlayerTransform); 00454 00455 transform = CGAffineTransformConcat(_transformFromLayer, superlayerTransform); 00456 00457 transform.tx -= superlayerOrigin.x; 00458 transform.ty -= superlayerOrigin.y; 00459 } 00460 00461 else 00462 // Copy so we don't affect the original. 00463 transform = CGAffineTransformCreateCopy(_transformFromLayer); 00464 00465 transform.tx -= _CGRectGetMinX(_backingStoreFrame); 00466 transform.ty -= _CGRectGetMinY(_backingStoreFrame); 00467 00468 CGContextSaveGState(_context); 00469 00470 CGContextConcatCTM(_context, transform);//_transformFromView); 00471 if (USE_BUFFER) 00472 { 00473 // CGContextDrawImage(_context, _bounds, _contents.context); 00474 _context.drawImage(_contents.buffer, _CGRectGetMinX(_bounds), _CGRectGetMinY(_bounds));//, _CGRectGetWidth(_standardBackingStoreFrame), _CGRectGetHeight(_standardBackingStoreFrame)); 00475 } 00476 else 00477 [self drawInContext:_context]; 00478 CGContextRestoreGState(_context); 00479 } 00480 00484 - (void)display 00485 { 00486 if (!_context) 00487 { 00488 _context = CGBitmapGraphicsContextCreate(); 00489 00490 _DOMContentsElement = _context.DOMElement; 00491 00492 _DOMContentsElement.style.zIndex = -100; 00493 00494 _DOMContentsElement.style.overflow = "hidden"; 00495 _DOMContentsElement.style.position = "absolute"; 00496 _DOMContentsElement.style.visibility = "visible"; 00497 00498 _DOMContentsElement.width = ROUND(_CGRectGetWidth(_backingStoreFrame)); 00499 _DOMContentsElement.height = ROUND(_CGRectGetHeight(_backingStoreFrame)); 00500 00501 _DOMContentsElement.style.top = "0px"; 00502 _DOMContentsElement.style.left = "0px"; 00503 _DOMContentsElement.style.width = ROUND(_CGRectGetWidth(_backingStoreFrame)) + "px"; 00504 _DOMContentsElement.style.height = ROUND(_CGRectGetHeight(_backingStoreFrame)) + "px"; 00505 00506 _DOMElement.appendChild(_DOMContentsElement); 00507 } 00508 00509 if (USE_BUFFER) 00510 { 00511 if (_delegateRespondsToDisplayLayerSelector) 00512 return [_delegate displayInLayer:self]; 00513 00514 if (_CGRectGetWidth(_backingStoreFrame) == 0.0 || _CGRectGetHeight(_backingStoreFrame) == 0.0) 00515 return; 00516 00517 if (!_contents) 00518 _contents = CABackingStoreCreate(); 00519 00520 CABackingStoreSetSize(_contents, _bounds.size); 00521 00522 [self drawInContext:CABackingStoreGetContext(_contents)]; 00523 } 00524 00525 [self composite]; 00526 } 00527 00532 - (void)drawInContext:(CGContext)aContext 00533 { //if (!window.loop || window.nodisplay) CPLog.error("htiasd"); 00534 if (_backgroundColor) 00535 { 00536 CGContextSetFillColor(aContext, _backgroundColor); 00537 CGContextFillRect(aContext, _bounds); 00538 } 00539 00540 if (_delegateRespondsToDrawLayerInContextSelector) 00541 [_delegate drawLayer:self inContext:aContext]; 00542 } 00543 00544 00545 // Style Attributes 00550 - (float)opacity 00551 { 00552 return _opacity; 00553 } 00554 00559 - (void)setOpacity:(float)anOpacity 00560 { 00561 if (_opacity == anOpacity) 00562 return; 00563 00564 _opacity = anOpacity; 00565 00566 _DOMElement.style.opacity = anOpacity; 00567 _DOMElement.style.filter = "alpha(opacity=" + anOpacity * 100 + ")"; 00568 } 00569 00574 - (void)setHidden:(BOOL)isHidden 00575 { 00576 _isHidden = isHidden; 00577 _DOMElement.style.display = isHidden ? "none" : "block"; 00578 } 00579 00583 - (BOOL)hidden 00584 { 00585 return _isHidden; 00586 } 00587 00591 - (BOOL)isHidden 00592 { 00593 return _isHidden; 00594 } 00595 00600 - (void)setMasksToBounds:(BOOL)masksToBounds 00601 { 00602 if (_masksToBounds == masksToBounds) 00603 return; 00604 00605 _masksToBounds = masksToBounds; 00606 _DOMElement.style.overflow = _masksToBounds ? "hidden" : "visible"; 00607 } 00608 00613 - (void)setBackgroundColor:(CPColor)aColor 00614 { 00615 _backgroundColor = aColor; 00616 00617 [self setNeedsDisplay]; 00618 } 00619 00623 - (CPColor)backgroundColor 00624 { 00625 return _backgroundColor; 00626 } 00627 00628 // Managing Layer Hierarchy 00632 - (CPArray)sublayers 00633 { 00634 return _sublayers; 00635 } 00636 00640 - (CALayer)superlayer 00641 { 00642 return _superlayer; 00643 } 00644 00645 #define ADJUST_CONTENTS_ZINDEX(aLayer)\ 00646 if (_DOMContentsElement && aLayer._zPosition > _DOMContentsElement.style.zIndex)\ 00647 _DOMContentsElement.style.zIndex -= 100.0;\ 00648 00649 00652 - (void)addSublayer:(CALayer)aLayer 00653 { 00654 [self insertSublayer:aLayer atIndex:_sublayers.length]; 00655 return; 00656 ADJUST_CONTENTS_ZINDEX(aLayer); 00657 00658 [_sublayers addObject:aLayer]; 00659 _DOMElement.appendChild(DOM(aLayer)); 00660 } 00661 00665 - (void)removeFromSuperlayer 00666 { 00667 if (_owningView) 00668 [_owningView setLayer:nil]; 00669 00670 if (!_superlayer) 00671 return; 00672 00673 _superlayer._DOMElement.removeChild(_DOMElement); 00674 [_superlayer._sublayers removeObject:self]; 00675 00676 _superlayer = nil; 00677 } 00678 00684 - (void)insertSublayer:(CALayer)aLayer atIndex:(unsigned)anIndex 00685 { 00686 if (!aLayer) 00687 return; 00688 00689 var superlayer = [aLayer superlayer]; 00690 00691 if (superlayer == self) 00692 { 00693 var index = [_sublayers indexOfObjectIdenticalTo:aLayer]; 00694 00695 if (index == anIndex) 00696 return; 00697 00698 [_sublayers removeObjectAtIndex:index]; 00699 00700 if (index < anIndex) 00701 --anIndex; 00702 } 00703 else if (superlayer != nil) 00704 [aLayer removeFromSuperlayer]; 00705 00706 ADJUST_CONTENTS_ZINDEX(aLayer); 00707 00708 [_sublayers insertObject:aLayer atIndex:anIndex]; 00709 00710 if (anIndex >= _sublayers.length - 1) 00711 _DOMElement.appendChild(DOM(aLayer)); 00712 else 00713 _DOMElement.insertBefore(DOM(aLayer), _sublayers[anIndex + 1]._DOMElement); 00714 00715 aLayer._superlayer = self; 00716 00717 if (self != superlayer) 00718 _CALayerRecalculateGeometry(aLayer, 0xFFFFFFF); 00719 } 00720 00727 - (void)insertSublayer:(CALayer)aLayer below:(CALayer)aSublayer 00728 { 00729 var index = aSublayer ? [_sublayers indexOfObjectIdenticalTo:aSublayer] : 0; 00730 00731 [self insertSublayer:aLayer atIndex:index == CPNotFound ? _sublayers.length : index]; 00732 } 00733 00740 - (void)insertSublayer:(CALayer)aLayer above:(CALayer)aSublayer 00741 { 00742 var index = aSublayer ? [_sublayers indexOfObjectIdenticalTo:aSublayer] : _sublayers.length; 00743 if (index == CPNotFound) 00744 [CPException raise:"CALayerNotFoundException" reason:"aSublayer is not a sublayer of this layer"]; 00745 00746 [_sublayers insertObject:aLayer atIndex:index == CPNotFound ? _sublayers.length : index + 1]; 00747 } 00748 00754 - (void)replaceSublayer:(CALayer)aSublayer with:(CALayer)aLayer 00755 { 00756 if (aSublayer == aLayer) 00757 return; 00758 00759 // FIXME: EXCEPTION 00760 if (aSublayer._superlayer != self) 00761 { 00762 alert("EXCEPTION"); 00763 return; 00764 } 00765 00766 ADJUST_CONTENTS_ZINDEX(aLayer); 00767 00768 [_sublayers replaceObjectAtIndex:[_sublayers indexOfObjectIdenticalTo:aSublayer] withObject:aLayer]; 00769 _DOMElement.replaceChild(DOM(aSublayer), DOM(aLayer)); 00770 } 00771 00772 // Updating Layer Display 00773 /* 00774 Updates the layers on screen. 00775 @ignore 00776 */ 00777 + (void)runLoopUpdateLayers 00778 { 00779 for (UID in CALayerRegisteredRunLoopUpdates) 00780 { 00781 var layer = CALayerRegisteredRunLoopUpdates[UID], 00782 mask = layer._runLoopUpdateMask; 00783 00784 if (mask & CALayerDOMUpdateMask) 00785 _CALayerUpdateDOM(layer, mask); 00786 00787 if (mask & CALayerDisplayUpdateMask) 00788 [layer display]; 00789 00790 else if (mask & CALayerFrameSizeUpdateMask || mask & CALayerCompositeUpdateMask) 00791 [layer composite]; 00792 00793 layer._runLoopUpdateMask = 0; 00794 } 00795 window.loop = false; 00796 CALayerRegisteredRunLoopUpdates = nil; 00797 } 00798 00799 /* 00800 @ignore 00801 */ 00802 - (void)registerRunLoopUpdateWithMask:(unsigned)anUpdateMask 00803 { 00804 if (CALayerRegisteredRunLoopUpdates == nil) 00805 { 00806 CALayerRegisteredRunLoopUpdates = {}; 00807 00808 [[CPRunLoop currentRunLoop] performSelector:@selector(runLoopUpdateLayers) 00809 target:CALayer argument:nil order:0 modes:[CPDefaultRunLoopMode]]; 00810 } 00811 00812 _runLoopUpdateMask |= anUpdateMask; 00813 CALayerRegisteredRunLoopUpdates[[self UID]] = self; 00814 } 00815 00816 /* 00817 @ignore 00818 */ 00819 - (void)setNeedsComposite 00820 { 00821 [self registerRunLoopUpdateWithMask:CALayerCompositeUpdateMask]; 00822 } 00823 00827 - (void)setNeedsDisplay 00828 { 00829 [self registerRunLoopUpdateWithMask:CALayerDisplayUpdateMask]; 00830 } 00831 00836 - (void)setNeedsDisplayOnBoundsChange:(BOOL)needsDisplayOnBoundsChange 00837 { 00838 _needsDisplayOnBoundsChange = needsDisplayOnBoundsChange; 00839 } 00840 00844 - (BOOL)needsDisplayOnBoundsChange 00845 { 00846 return _needsDisplayOnBoundsChange; 00847 } 00848 00853 - (void)setNeedsDisplayInRect:(CGRect)aRect 00854 { 00855 _dirtyRect = aRect; 00856 [self display]; 00857 } 00858 00859 // Mapping Between Coordinate and Time Spaces 00866 - (CGPoint)convertPoint:(CGPoint)aPoint fromLayer:(CALayer)aLayer 00867 { 00868 return CGPointApplyAffineTransform(aPoint, _CALayerGetTransform(aLayer, self)); 00869 } 00870 00877 - (CGPoint)convertPoint:(CGPoint)aPoint toLayer:(CALayer)aLayer 00878 { 00879 return CGPointApplyAffineTransform(aPoint, _CALayerGetTransform(self, aLayer)); 00880 } 00881 00888 - (CGRect)convertRect:(CGRect)aRect fromLayer:(CALayer)aLayer 00889 { 00890 return CGRectApplyAffineTransform(aRect, _CALayerGetTransform(aLayer, self)); 00891 } 00892 00899 - (CGRect)convertRect:(CGRect)aRect toLayer:(CALayer)aLayer 00900 { 00901 return CGRectApplyAffineTransform(aRect, _CALayerGetTransform(self, aLayer)); 00902 } 00903 00904 // Hit Testing 00909 - (BOOL)containsPoint:(CGPoint)aPoint 00910 { 00911 return _CGRectContainsPoint(_bounds, aPoint); 00912 } 00913 00919 - (CALayer)hitTest:(CGPoint)aPoint 00920 { 00921 if (_isHidden) 00922 return nil; 00923 00924 var point = CGPointApplyAffineTransform(aPoint, _transformToLayer); 00925 //alert(point.x + " " + point.y); 00926 00927 if (!_CGRectContainsPoint(_bounds, point)) 00928 return nil; 00929 00930 var layer = nil, 00931 index = _sublayers.length; 00932 00933 // FIXME: this should take into account zPosition. 00934 while (index--) 00935 if (layer = [_sublayers[index] hitTest:point]) 00936 return layer; 00937 00938 return self; 00939 } 00940 00941 // Modifying the Delegate 00946 - (void)setDelegate:(id)aDelegate 00947 { 00948 if (_delegate == aDelegate) 00949 return; 00950 00951 _delegate = aDelegate; 00952 00953 _delegateRespondsToDisplayLayerSelector = [_delegate respondsToSelector:@selector(displayLayer:)]; 00954 _delegateRespondsToDrawLayerInContextSelector = [_delegate respondsToSelector:@selector(drawLayer:inContext:)]; 00955 00956 if (_delegateRespondsToDisplayLayerSelector || _delegateRespondsToDrawLayerInContextSelector) 00957 [self setNeedsDisplay]; 00958 } 00959 00963 - (id)delegate 00964 { 00965 return _delegate; 00966 } 00967 00968 /* @ignore */ 00969 - (void)_setOwningView:(CPView)anOwningView 00970 { 00971 _owningView = anOwningView; 00972 00973 if (_owningView) 00974 { 00975 _owningView = anOwningView; 00976 00977 _bounds.size = CGSizeMakeCopy([_owningView bounds].size); 00978 _position = CGPointMake(_CGRectGetWidth(_bounds) * _anchorPoint.x, _CGRectGetHeight(_bounds) * _anchorPoint.y); 00979 } 00980 00981 _CALayerRecalculateGeometry(self, CALayerGeometryPositionMask | CALayerGeometryBoundsMask); 00982 } 00983 00984 /* @ignore */ 00985 - (void)_owningViewBoundsChanged 00986 { 00987 _bounds.size = CGSizeMakeCopy([_owningView bounds].size); 00988 _position = CGPointMake(_CGRectGetWidth(_bounds) * _anchorPoint.x, _CGRectGetHeight(_bounds) * _anchorPoint.y); 00989 00990 _CALayerRecalculateGeometry(self, CALayerGeometryPositionMask | CALayerGeometryBoundsMask); 00991 } 00992 00993 /* @ignore */ 00994 - (void)_update 00995 { 00996 window.loop = true; 00997 00998 var mask = _runLoopUpdateMask; 00999 01000 if (mask & CALayerDOMUpdateMask) 01001 _CALayerUpdateDOM(self, mask); 01002 01003 if (mask & CALayerDisplayUpdateMask) 01004 [self display]; 01005 01006 else if (mask & CALayerFrameSizeUpdateMask || mask & CALayerCompositeUpdateMask) 01007 [self composite]; 01008 01009 _runLoopUpdateMask = 0; 01010 01011 window.loop = false; 01012 } 01013 01014 @end 01015 01016 function _CALayerUpdateSublayerTransformForSublayers(aLayer) 01017 { 01018 var bounds = aLayer._bounds, 01019 anchorPoint = aLayer._anchorPoint, 01020 translateX = _CGRectGetWidth(bounds) * anchorPoint.x, 01021 translateY = _CGRectGetHeight(bounds) * anchorPoint.y; 01022 01023 aLayer._sublayerTransformForSublayers = CGAffineTransformConcat( 01024 CGAffineTransformMakeTranslation(-translateX, -translateY), 01025 CGAffineTransformConcat(aLayer._sublayerTransform, 01026 CGAffineTransformMakeTranslation(translateX, translateY))); 01027 } 01028 01029 function _CALayerUpdateDOM(aLayer, aMask) 01030 { 01031 var DOMElementStyle = aLayer._DOMElement.style; 01032 01033 if (aMask & CALayerZPositionUpdateMask) 01034 DOMElementStyle.zIndex = aLayer._zPosition; 01035 01036 var frame = aLayer._backingStoreFrame; 01037 01038 if (aMask & CALayerFrameOriginUpdateMask) 01039 { 01040 DOMElementStyle.top = ROUND(_CGRectGetMinY(frame)) + "px"; 01041 DOMElementStyle.left = ROUND(_CGRectGetMinX(frame)) + "px"; 01042 } 01043 01044 if (aMask & CALayerFrameSizeUpdateMask) 01045 { 01046 var width = MAX(0.0, ROUND(_CGRectGetWidth(frame))), 01047 height = MAX(0.0, ROUND(_CGRectGetHeight(frame))), 01048 DOMContentsElement = aLayer._DOMContentsElement; 01049 01050 DOMElementStyle.width = width + "px"; 01051 DOMElementStyle.height = height + "px"; 01052 01053 if (DOMContentsElement) 01054 { 01055 DOMContentsElement.width = width; 01056 DOMContentsElement.height = height; 01057 DOMContentsElement.style.width = width + "px"; 01058 DOMContentsElement.style.height = height + "px"; 01059 } 01060 } 01061 } 01062 01063 function _CALayerRecalculateGeometry(aLayer, aGeometryChange) 01064 { 01065 var bounds = aLayer._bounds, 01066 superlayer = aLayer._superlayer, 01067 width = _CGRectGetWidth(bounds), 01068 height = _CGRectGetHeight(bounds), 01069 position = aLayer._position, 01070 anchorPoint = aLayer._anchorPoint, 01071 affineTransform = aLayer._affineTransform, 01072 backingStoreFrameSize = _CGSizeMakeCopy(aLayer._backingStoreFrame), 01073 hasCustomBackingStoreFrame = aLayer._hasCustomBackingStoreFrame; 01074 01075 // Go to anchor, transform, go back to bounds. 01076 aLayer._transformFromLayer = CGAffineTransformConcat( 01077 CGAffineTransformMakeTranslation(-width * anchorPoint.x - _CGRectGetMinX(aLayer._bounds), -height * anchorPoint.y - _CGRectGetMinY(aLayer._bounds)), 01078 CGAffineTransformConcat(affineTransform, 01079 CGAffineTransformMakeTranslation(position.x, position.y))); 01080 01081 if (superlayer && superlayer._hasSublayerTransform) 01082 { 01083 // aLayer._transformFromLayer = CGAffineTransformConcat(aLayer._transformFromLayer, superlayer._sublayerTransformForSublayers); 01084 _CGAffineTransformConcatTo(aLayer._transformFromLayer, superlayer._sublayerTransformForSublayers, aLayer._transformFromLayer); 01085 } 01086 01087 aLayer._transformToLayer = CGAffineTransformInvert(aLayer._transformFromLayer); 01088 01089 //aLayer._transformFromLayer.tx = ROUND(aLayer._transformFromLayer.tx); 01090 //aLayer._transformFromLayer.ty = ROUND(aLayer._transformFromLayer.ty); 01091 01092 aLayer._frame = nil; 01093 aLayer._standardBackingStoreFrame = [aLayer convertRect:bounds toLayer:nil]; 01094 01095 if (superlayer) 01096 { 01097 var bounds = [superlayer bounds], 01098 frame = [superlayer convertRect:bounds toLayer:nil]; 01099 01100 aLayer._standardBackingStoreFrame.origin.x -= _CGRectGetMinX(frame); 01101 aLayer._standardBackingStoreFrame.origin.y -= _CGRectGetMinY(frame); 01102 } 01103 01104 // We used to use CGRectIntegral here, but what we actually want, is the largest integral 01105 // rect that would ever contain this box, since for any width/height, there are 2 (4) 01106 // possible integral rects for it depending on it's position. It's OK that this is sometimes 01107 // bigger than the "optimal" bounding integral rect since that doesn't change drawing. 01108 01109 var origin = aLayer._standardBackingStoreFrame.origin, 01110 size = aLayer._standardBackingStoreFrame.size; 01111 01112 origin.x = FLOOR(origin.x); 01113 origin.y = FLOOR(origin.y); 01114 size.width = CEIL(size.width) + 1.0; 01115 size.height = CEIL(size.height) + 1.0; 01116 01117 // FIXME: This avoids the central issue that a position change is sometimes a display and sometimes 01118 // a div move, and sometimes both. 01119 01120 // Only use this frame if we don't currently have a custom backing store frame. 01121 if (!hasCustomBackingStoreFrame) 01122 { 01123 var backingStoreFrame = CGRectMakeCopy(aLayer._standardBackingStoreFrame); 01124 01125 // These values get rounded in the DOM, so don't both updating them if they're 01126 // not going to be different after rounding. 01127 if (ROUND(_CGRectGetMinX(backingStoreFrame)) != ROUND(_CGRectGetMinX(aLayer._backingStoreFrame)) || 01128 ROUND(_CGRectGetMinY(backingStoreFrame)) != ROUND(_CGRectGetMinY(aLayer._backingStoreFrame))) 01129 [aLayer registerRunLoopUpdateWithMask:CALayerFrameOriginUpdateMask]; 01130 01131 // Any change in size due to a geometry change is purely due to rounding error. 01132 if ((_CGRectGetWidth(backingStoreFrame) != ROUND(_CGRectGetWidth(aLayer._backingStoreFrame)) || 01133 _CGRectGetHeight(backingStoreFrame) != ROUND(_CGRectGetHeight(aLayer._backingStoreFrame)))) 01134 [aLayer registerRunLoopUpdateWithMask:CALayerFrameSizeUpdateMask]; 01135 01136 aLayer._backingStoreFrame = backingStoreFrame; 01137 } 01138 01139 if (aGeometryChange & CALayerGeometryBoundsMask && aLayer._needsDisplayOnBoundsChange) 01140 [aLayer setNeedsDisplay]; 01141 // We need to recompose if we have a custom backing store frame, OR 01142 // If the change is not solely composed of position and anchor points changes. 01143 // Anchor point and position changes simply move the object, requiring 01144 // no re-rendering. 01145 else if (hasCustomBackingStoreFrame || (aGeometryChange & ~(CALayerGeometryPositionMask | CALayerGeometryAnchorPointMask))) 01146 [aLayer setNeedsComposite]; 01147 01148 var sublayers = aLayer._sublayers, 01149 index = 0, 01150 count = sublayers.length; 01151 01152 for (; index < count; ++index) 01153 _CALayerRecalculateGeometry(sublayers[index], aGeometryChange); 01154 } 01155 01156 function _CALayerGetTransform(fromLayer, toLayer) 01157 { 01158 var transform = CGAffineTransformMakeIdentity(); 01159 01160 if (fromLayer) 01161 { 01162 var layer = fromLayer; 01163 01164 // If we have a fromLayer, "climb up" the layer tree until 01165 // we hit the root node or we hit the toLayer. 01166 while (layer && layer != toLayer) 01167 { 01168 var transformFromLayer = layer._transformFromLayer; 01169 01170 //transform = CGAffineTransformConcat(transform, layer._transformFromLayer); 01171 _CGAffineTransformConcatTo(transform, transformFromLayer, transform); 01172 01173 layer = layer._superlayer; 01174 } 01175 01176 // If we hit toLayer, then we're done. 01177 if (layer == toLayer) 01178 return transform; 01179 } 01180 01181 var layers = [], 01182 layer = toLayer; 01183 01184 while (layer) 01185 { 01186 layers.push(layer); 01187 layer = layer._superlayer; 01188 } 01189 01190 var index = layers.length; 01191 01192 while (index--) 01193 { 01194 var transformToLayer = layers[index]._transformToLayer; 01195 01196 _CGAffineTransformConcatTo(transform, transformToLayer, transform); 01197 } 01198 01199 return transform; 01200 }