API 0.9.5
AppKit/CoreAnimation/CALayer.j
Go to the documentation of this file.
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 }
 All Classes Files Functions Variables Defines