API  0.9.10
CALayer.j
Go to the documentation of this file.
1 /*
2  * CALayer.j
3  * AppKit
4  *
5  * Created by Francisco Tolmasky.
6  * Copyright 2008, 280 North, Inc.
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22 
23 
24 
25 
26 #define DOM(aLayer) aLayer._DOMElement
27 
33 
34 var USE_BUFFER = NO;
35 
42 
44 
45 
46  A CALayer is similar to a CPView, but with the ability
47  to have a transform applied to it.
48 
49  @delegate -(void)drawLayer:(CALayer)layer inContext:(CGContextRef)ctx;
50  If the delegate implements this method, the CALayer will
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
54 
55  @delegate -(void)displayLayer:(CALayer)layer;
56  The delegate can override the layer's \c -display method
57  by implementing this method.
58 */
59 @implementation CALayer : CPObject
60 {
61  // Modifying the Layer Geometry
62 
63  CGRect _frame;
64  CGRect _bounds;
65  CGPoint _position;
66  unsigned _zPosition;
67  CGPoint _anchorPoint;
68 
69  CGAffineTransform _affineTransform;
70  CGAffineTransform _sublayerTransform;
71  CGAffineTransform _sublayerTransformForSublayers;
72 
73  CGRect _backingStoreFrame;
74  CGRect _standardBackingStoreFrame;
75 
76  BOOL _hasSublayerTransform;
77  BOOL _hasCustomBackingStoreFrame;
78 
79  // Style Attributes
80 
81  float _opacity;
82  BOOL _isHidden;
83  BOOL _masksToBounds;
84  CPColor _backgroundColor;
85 
86  // Managing Layer Hierarchy
87 
88  CALayer _superlayer;
89  CPMutableArray _sublayers;
90 
91  // Updating Layer Display
92 
93  unsigned _runLoopUpdateMask;
94  BOOL _needsDisplayOnBoundsChange;
95 
96  // Modifying the Delegate
97 
98  id _delegate;
99 
100  BOOL _delegateRespondsToDisplayLayerSelector;
101  BOOL _delegateRespondsToDrawLayerInContextSelector;
102 
103  // DOM Implementation
104 
105  DOMElement _DOMElement;
106  DOMElement _DOMContentsElement;
107  id _contents;
108  CGContext _context;
109  CPView _owningView;
110 
111  CGAffineTransform _transformToLayer;
112  CGAffineTransform _transformFromLayer;
113 }
114 
118 + (CALayer)layer
119 {
120  return [[[self class] alloc] init];
121 }
122 
126 - (id)init
127 {
128  self = [super init];
129 
130  if (self)
131  {
132  _frame = CGRectMakeZero();
133 
134  _backingStoreFrame = CGRectMakeZero();
135  _standardBackingStoreFrame = CGRectMakeZero();
136 
137  _bounds = CGRectMakeZero();
138  _position = CGPointMakeZero();
139  _zPosition = 0.0;
140  _anchorPoint = CGPointMake(0.5, 0.5);
141  _affineTransform = CGAffineTransformMakeIdentity();
142  _sublayerTransform = CGAffineTransformMakeIdentity();
143 
144  _transformToLayer = CGAffineTransformMakeIdentity(); // FIXME? does it matter?
145  _transformFromLayer = CGAffineTransformMakeIdentity();
146 
147  _opacity = 1.0;
148  _isHidden = NO;
149  _masksToBounds = NO;
150 
151  _sublayers = [];
152 
153 #if PLATFORM(DOM)
154  _DOMElement = document.createElement("div");
155 
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";
164 #endif
165  }
166 
167  return self;
168 }
169 
170 // Modifying the Layer Geometry
175 - (void)setBounds:(CGRect)aBounds
176 {
177  if (CGRectEqualToRect(_bounds, aBounds))
178  return;
179 
180  var oldOrigin = _bounds.origin;
181 
182  _bounds = CGRectMakeCopy(aBounds);
183 
184  if (_hasSublayerTransform)
185  _CALayerUpdateSublayerTransformForSublayers(self);
186 
187  // _hasSublayerTransform == true will handle this for us.
188  /*else if (!CGPointEqualToPoint(_bounds.origin, oldOrigin))
189  {
190  var index = _sublayers.length;
191 
192  // FIXME: This should climb the layer tree down.
193  while (index--)
194  _CALayerRecalculateGeometry(_sublayers[index], CALayerGeometryPositionMask);
195  }*/
196 
197  _CALayerRecalculateGeometry(self, CALayerGeometryBoundsMask);
198 }
199 
203 - (CGRect)bounds
204 {
205  return _bounds;
206 }
207 
212 - (void)setPosition:(CGPoint)aPosition
213 {
214  if (CGPointEqualToPoint(_position, aPosition))
215  return;
216 
217  _position = CGPointMakeCopy(aPosition);
218 
219  _CALayerRecalculateGeometry(self, CALayerGeometryPositionMask);
220 }
221 
225 - (CGPoint)position
226 {
227  return _position;
228 }
229 
234 - (void)setZPosition:(int)aZPosition
235 {
236  if (_zPosition == aZPosition)
237  return;
238 
239  _zPosition = aZPosition;
240 
241  [self registerRunLoopUpdateWithMask:CALayerZPositionUpdateMask];
242 }
243 
248 - (void)setAnchorPoint:(CGPoint)anAnchorPoint
249 {
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));
253 
254  if (CGPointEqualToPoint(_anchorPoint, anAnchorPoint))
255  return;
256 
257  _anchorPoint = anAnchorPoint;
258 
259  if (_hasSublayerTransform)
260  _CALayerUpdateSublayerTransformForSublayers(self);
261 
262  if (_owningView)
263  _position = CGPointMake(CGRectGetWidth(_bounds) * _anchorPoint.x, CGRectGetHeight(_bounds) * _anchorPoint.y);
264 
265  _CALayerRecalculateGeometry(self, CALayerGeometryAnchorPointMask);
266 }
267 
271 - (CGPoint)anchorPoint
272 {
273  return _anchorPoint;
274 }
275 
280 - (void)setAffineTransform:(CGAffineTransform)anAffineTransform
281 {
282  if (CGAffineTransformEqualToTransform(_affineTransform, anAffineTransform))
283  return;
284 
285  _affineTransform = CGAffineTransformMakeCopy(anAffineTransform);
286 
287  _CALayerRecalculateGeometry(self, CALayerGeometryAffineTransformMask);
288 }
289 
293 - (CGAffineTransform)affineTransform
294 {
295  return _affineTransform;
296 }
297 
302 - (void)setSublayerTransform:(CGAffineTransform)anAffineTransform
303 {
304  if (CGAffineTransformEqualToTransform(_sublayerTransform, anAffineTransform))
305  return;
306 
307  var hadSublayerTransform = _hasSublayerTransform;
308 
309  _sublayerTransform = CGAffineTransformMakeCopy(anAffineTransform);
310  _hasSublayerTransform = !CGAffineTransformIsIdentity(_sublayerTransform);
311 
312  if (_hasSublayerTransform)
313  {
314  _CALayerUpdateSublayerTransformForSublayers(self);
315 
316  var index = _sublayers.length;
317 
318  // FIXME: This should climb the layer tree down.
319  while (index--)
320  _CALayerRecalculateGeometry(_sublayers[index], CALayerGeometryParentSublayerTransformMask);
321  }
322 }
323 
327 - (CGAffineTransform)sublayerTransform
328 {
329  return _sublayerTransform;
330 }
331 
332 /*
333  Private
334  @ignore
335 */
336 - (CGAffineTransform)transformToLayer
337 {
338  return _transformToLayer;
339 }
340 
346 - (void)setFrame:(CGRect)aFrame
347 {
348  // FIXME: implement this
349 }
350 
358 - (CGRect)frame
359 {
360  if (!_frame)
361  _frame = [self convertRect:_bounds toLayer:_superlayer];
362 
363  return _frame;
364 }
365 
374 - (CGRect)backingStoreFrame
375 {
376  return _backingStoreFrame;
377 }
378 
383 - (void)setBackingStoreFrame:(CGRect)aFrame
384 {
385  _hasCustomBackingStoreFrame = (aFrame != nil);
386 
387  if (aFrame == nil)
388  aFrame = CGRectMakeCopy(_standardBackingStoreFrame);
389  else
390  {
391  if (_superlayer)
392  {
393  aFrame = [_superlayer convertRect:aFrame toLayer:nil];
394 
395  var bounds = [_superlayer bounds],
396  frame = [_superlayer convertRect:bounds toLayer:nil];
397 
398  aFrame.origin.x -= CGRectGetMinX(frame);
399  aFrame.origin.y -= CGRectGetMinY(frame);
400  }
401  else
402  aFrame = CGRectMakeCopy(aFrame);
403  }
404 
405  if (!CGPointEqualToPoint(_backingStoreFrame.origin, aFrame.origin))
406  [self registerRunLoopUpdateWithMask:CALayerFrameOriginUpdateMask];
407 
408  if (!CGSizeEqualToSize(_backingStoreFrame.size, aFrame.size))
409  [self registerRunLoopUpdateWithMask:CALayerFrameSizeUpdateMask];
410 
411  _backingStoreFrame = aFrame;
412 }
413 
414 // Providing Layer Content
419 - (CGImage)contents
420 {
421  return _contents;
422 }
423 
428 - (void)setContents:(CGImage)contents
429 {
430  if (_contents == contents)
431  return;
432 
433  _contents = contents;
434 
435  [self composite];
436 }
437 
438 /*
439  Composites this layer onto the super layer, and draws its contents as well.
440  @ignore
441 */
442 - (void)composite
443 {
444  if (USE_BUFFER && !_contents || !_context)
445  return;
446 
447  CGContextClearRect(_context, CGRectMake(0.0, 0.0, CGRectGetWidth(_backingStoreFrame), CGRectGetHeight(_backingStoreFrame)));
448 
449  // Recomposite
450  var transform;
451 
452  if (_superlayer)
453  {
454  var superlayerTransform = _CALayerGetTransform(_superlayer, nil),
455  superlayerOrigin = CGPointApplyAffineTransform(_superlayer._bounds.origin, superlayerTransform);
456 
457  transform = CGAffineTransformConcat(_transformFromLayer, superlayerTransform);
458 
459  transform.tx -= superlayerOrigin.x;
460  transform.ty -= superlayerOrigin.y;
461  }
462 
463  else
464  // Copy so we don't affect the original.
465  transform = CGAffineTransformCreateCopy(_transformFromLayer);
466 
467  transform.tx -= CGRectGetMinX(_backingStoreFrame);
468  transform.ty -= CGRectGetMinY(_backingStoreFrame);
469 
470  CGContextSaveGState(_context);
471 
472  CGContextConcatCTM(_context, transform);//_transformFromView);
473 
474  if (USE_BUFFER)
475  {
476 // CGContextDrawImage(_context, _bounds, _contents.context);
477  _context.drawImage(_contents.buffer, CGRectGetMinX(_bounds), CGRectGetMinY(_bounds));//, CGRectGetWidth(_standardBackingStoreFrame), CGRectGetHeight(_standardBackingStoreFrame));
478  }
479  else
480  [self drawInContext:_context];
481 
482  CGContextRestoreGState(_context);
483 }
484 
488 - (void)display
489 {
490 #if PLATFORM(DOM)
491  if (!_context)
492  {
493  _context = CGBitmapGraphicsContextCreate();
494 
495  _DOMContentsElement = _context.DOMElement;
496 
497  _DOMContentsElement.style.zIndex = -100;
498 
499  _DOMContentsElement.style.overflow = "hidden";
500  _DOMContentsElement.style.position = "absolute";
501  _DOMContentsElement.style.visibility = "visible";
502 
503  _DOMContentsElement.width = ROUND(CGRectGetWidth(_backingStoreFrame));
504  _DOMContentsElement.height = ROUND(CGRectGetHeight(_backingStoreFrame));
505 
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";
510 
511  _DOMElement.appendChild(_DOMContentsElement);
512  }
513 
514  if (USE_BUFFER)
515  {
516  if (_delegateRespondsToDisplayLayerSelector)
517  return [_delegate displayInLayer:self];
518 
519  if (CGRectGetWidth(_backingStoreFrame) == 0.0 || CGRectGetHeight(_backingStoreFrame) == 0.0)
520  return;
521 
522  if (!_contents)
523  _contents = CABackingStoreCreate();
524 
525  CABackingStoreSetSize(_contents, _bounds.size);
526 
527  [self drawInContext:CABackingStoreGetContext(_contents)];
528  }
529 #endif
530 
531  [self composite];
532 }
533 
538 - (void)drawInContext:(CGContext)aContext
539 {
540  if (_backgroundColor)
541  {
542  CGContextSetFillColor(aContext, _backgroundColor);
543  CGContextFillRect(aContext, _bounds);
544  }
545 
546  if (_delegateRespondsToDrawLayerInContextSelector)
547  [_delegate drawLayer:self inContext:aContext];
548 }
549 
550 
551 // Style Attributes
556 - (float)opacity
557 {
558  return _opacity;
559 }
560 
565 - (void)setOpacity:(float)anOpacity
566 {
567  if (_opacity == anOpacity)
568  return;
569 
570  _opacity = anOpacity;
571 
572  _DOMElement.style.opacity = anOpacity;
573  _DOMElement.style.filter = "alpha(opacity=" + anOpacity * 100 + ")";
574 }
575 
580 - (void)setHidden:(BOOL)isHidden
581 {
582  _isHidden = isHidden;
583  _DOMElement.style.display = isHidden ? "none" : "block";
584 }
585 
589 - (BOOL)hidden
590 {
591  return _isHidden;
592 }
593 
597 - (BOOL)isHidden
598 {
599  return _isHidden;
600 }
601 
606 - (void)setMasksToBounds:(BOOL)masksToBounds
607 {
608  if (_masksToBounds == masksToBounds)
609  return;
610 
611  _masksToBounds = masksToBounds;
612  _DOMElement.style.overflow = _masksToBounds ? "hidden" : "visible";
613 }
614 
619 - (void)setBackgroundColor:(CPColor)aColor
620 {
621  _backgroundColor = aColor;
622 
623  [self setNeedsDisplay];
624 }
625 
630 {
631  return _backgroundColor;
632 }
633 
634 // Managing Layer Hierarchy
638 - (CPArray)sublayers
639 {
640  return _sublayers;
641 }
642 
647 {
648  return _superlayer;
649 }
650 
651 #define ADJUST_CONTENTS_ZINDEX(aLayer)\
652 if (_DOMContentsElement && aLayer._zPosition > _DOMContentsElement.style.zIndex)\
653  _DOMContentsElement.style.zIndex -= 100.0;\
654 
655 
658 - (void)addSublayer:(CALayer)aLayer
659 {
660  [self insertSublayer:aLayer atIndex:_sublayers.length];
661 }
662 
667 {
668  if (_owningView)
669  [_owningView setLayer:nil];
670 
671  if (!_superlayer)
672  return;
673 
674  _superlayer._DOMElement.removeChild(_DOMElement);
675  [_superlayer._sublayers removeObject:self];
676 
677  _superlayer = nil;
678 }
679 
685 - (void)insertSublayer:(CALayer)aLayer atIndex:(CPUInteger)anIndex
686 {
687  if (!aLayer)
688  return;
689 
690  var superlayer = [aLayer superlayer];
691 
692  if (superlayer == self)
693  {
694  var index = [_sublayers indexOfObjectIdenticalTo:aLayer];
695 
696  if (index == anIndex)
697  return;
698 
699  [_sublayers removeObjectAtIndex:index];
700 
701  if (index < anIndex)
702  --anIndex;
703  }
704  else if (superlayer != nil)
705  [aLayer removeFromSuperlayer];
706 
707  ADJUST_CONTENTS_ZINDEX(aLayer);
708 
709  [_sublayers insertObject:aLayer atIndex:anIndex];
710 
711 #if PLATFORM(DOM)
712  if (anIndex >= _sublayers.length - 1)
713  _DOMElement.appendChild(DOM(aLayer));
714  else
715  _DOMElement.insertBefore(DOM(aLayer), _sublayers[anIndex + 1]._DOMElement);
716 #endif
717 
718  aLayer._superlayer = self;
719 
720  if (self != superlayer)
721  _CALayerRecalculateGeometry(aLayer, 0xFFFFFFF);
722 }
723 
730 - (void)insertSublayer:(CALayer)aLayer below:(CALayer)aSublayer
731 {
732  var index = aSublayer ? [_sublayers indexOfObjectIdenticalTo:aSublayer] : 0;
733 
734  [self insertSublayer:aLayer atIndex:index == CPNotFound ? _sublayers.length : index];
735 }
736 
743 - (void)insertSublayer:(CALayer)aLayer above:(CALayer)aSublayer
744 {
745  var index = aSublayer ? [_sublayers indexOfObjectIdenticalTo:aSublayer] : _sublayers.length;
746 
747  if (index == CPNotFound)
748  [CPException raise:"CALayerNotFoundException" reason:"aSublayer is not a sublayer of this layer"];
749 
750  [_sublayers insertObject:aLayer atIndex:index == CPNotFound ? _sublayers.length : index + 1];
751 }
752 
758 - (void)replaceSublayer:(CALayer)aSublayer with:(CALayer)aLayer
759 {
760  if (aSublayer == aLayer)
761  return;
762 
763  if (aSublayer._superlayer != self)
764  {
765  CPLog.warn("Attempt to replace a sublayer (%s) which is not in the sublayers of the receiver (%s).", [aSublayer description], [self description]);
766  return;
767  }
768 
769  ADJUST_CONTENTS_ZINDEX(aLayer);
770 
771  [_sublayers replaceObjectAtIndex:[_sublayers indexOfObjectIdenticalTo:aSublayer] withObject:aLayer];
772  _DOMElement.replaceChild(DOM(aSublayer), DOM(aLayer));
773 }
774 
775 // Updating Layer Display
776 /*
777  Updates the layers on screen.
778  @ignore
779 */
781 {
783  {
784  var layer = CALayerRegisteredRunLoopUpdates[UID],
785  mask = layer._runLoopUpdateMask;
786 
787  if (mask & CALayerDOMUpdateMask)
788  _CALayerUpdateDOM(layer, mask);
789 
790  if (mask & CALayerDisplayUpdateMask)
791  [layer display];
792  else if (mask & CALayerFrameSizeUpdateMask || mask & CALayerCompositeUpdateMask)
793  [layer composite];
794 
795  layer._runLoopUpdateMask = 0;
796  }
797 
798  window.loop = false;
800 }
801 
802 /*
803  @ignore
804 */
805 - (void)registerRunLoopUpdateWithMask:(unsigned)anUpdateMask
806 {
808  {
810 
811  [[CPRunLoop currentRunLoop] performSelector:@selector(runLoopUpdateLayers)
812  target:CALayer argument:nil order:0 modes:[CPDefaultRunLoopMode]];
813  }
814 
815  _runLoopUpdateMask |= anUpdateMask;
816  CALayerRegisteredRunLoopUpdates[[self UID]] = self;
817 }
818 
819 /*
820  @ignore
821 */
823 {
824  [self registerRunLoopUpdateWithMask:CALayerCompositeUpdateMask];
825 }
826 
831 {
832  [self registerRunLoopUpdateWithMask:CALayerDisplayUpdateMask];
833 }
834 
839 - (void)setNeedsDisplayOnBoundsChange:(BOOL)needsDisplayOnBoundsChange
840 {
841  _needsDisplayOnBoundsChange = needsDisplayOnBoundsChange;
842 }
843 
848 {
849  return _needsDisplayOnBoundsChange;
850 }
851 
856 - (void)setNeedsDisplayInRect:(CGRect)aRect
857 {
858 // _dirtyRect = aRect;
859  [self display];
860 }
861 
862 // Mapping Between Coordinate and Time Spaces
869 - (CGPoint)convertPoint:(CGPoint)aPoint fromLayer:(CALayer)aLayer
870 {
871  return CGPointApplyAffineTransform(aPoint, _CALayerGetTransform(aLayer, self));
872 }
873 
880 - (CGPoint)convertPoint:(CGPoint)aPoint toLayer:(CALayer)aLayer
881 {
882  return CGPointApplyAffineTransform(aPoint, _CALayerGetTransform(self, aLayer));
883 }
884 
891 - (CGRect)convertRect:(CGRect)aRect fromLayer:(CALayer)aLayer
892 {
893  return CGRectApplyAffineTransform(aRect, _CALayerGetTransform(aLayer, self));
894 }
895 
902 - (CGRect)convertRect:(CGRect)aRect toLayer:(CALayer)aLayer
903 {
904  return CGRectApplyAffineTransform(aRect, _CALayerGetTransform(self, aLayer));
905 }
906 
907 // Hit Testing
912 - (BOOL)containsPoint:(CGPoint)aPoint
913 {
914  return CGRectContainsPoint(_bounds, aPoint);
915 }
916 
922 - (CALayer)hitTest:(CGPoint)aPoint
923 {
924  if (_isHidden)
925  return nil;
926 
927  var point = CGPointApplyAffineTransform(aPoint, _transformToLayer);
928 
929  if (!CGRectContainsPoint(_bounds, point))
930  return nil;
931 
932  var layer = nil,
933  index = _sublayers.length;
934 
935  // FIXME: this should take into account zPosition.
936  while (index--)
937  if (layer = [_sublayers[index] hitTest:point])
938  return layer;
939 
940  return self;
941 }
942 
943 // Modifying the Delegate
948 - (void)setDelegate:(id)aDelegate
949 {
950  if (_delegate == aDelegate)
951  return;
952 
953  _delegate = aDelegate;
954 
955  _delegateRespondsToDisplayLayerSelector = [_delegate respondsToSelector:@selector(displayLayer:)];
956  _delegateRespondsToDrawLayerInContextSelector = [_delegate respondsToSelector:@selector(drawLayer:inContext:)];
957 
958  if (_delegateRespondsToDisplayLayerSelector || _delegateRespondsToDrawLayerInContextSelector)
959  [self setNeedsDisplay];
960 }
961 
965 - (id)delegate
966 {
967  return _delegate;
968 }
969 
970 /* @ignore */
971 - (void)_setOwningView:(CPView)anOwningView
972 {
973  _owningView = anOwningView;
974 
975  if (_owningView)
976  {
977  _owningView = anOwningView;
978 
979  _bounds.size = CGSizeMakeCopy([_owningView bounds].size);
980  _position = CGPointMake(CGRectGetWidth(_bounds) * _anchorPoint.x, CGRectGetHeight(_bounds) * _anchorPoint.y);
981  }
982 
983  _CALayerRecalculateGeometry(self, CALayerGeometryPositionMask | CALayerGeometryBoundsMask);
984 }
985 
986 /* @ignore */
987 - (void)_owningViewBoundsChanged
988 {
989  _bounds.size = CGSizeMakeCopy([_owningView bounds].size);
990  _position = CGPointMake(CGRectGetWidth(_bounds) * _anchorPoint.x, CGRectGetHeight(_bounds) * _anchorPoint.y);
991 
992  _CALayerRecalculateGeometry(self, CALayerGeometryPositionMask | CALayerGeometryBoundsMask);
993 }
994 
995 /* @ignore */
996 - (void)_update
997 {
998  window.loop = true;
999 
1000  var mask = _runLoopUpdateMask;
1001 
1002  if (mask & CALayerDOMUpdateMask)
1003  _CALayerUpdateDOM(self, mask);
1004 
1005  if (mask & CALayerDisplayUpdateMask)
1006  [self display];
1007 
1008  else if (mask & CALayerFrameSizeUpdateMask || mask & CALayerCompositeUpdateMask)
1009  [self composite];
1010 
1011  _runLoopUpdateMask = 0;
1012 
1013  window.loop = false;
1014 }
1015 
1016 @end
1017 
1018 function _CALayerUpdateSublayerTransformForSublayers(aLayer)
1019 {
1020  var bounds = aLayer._bounds,
1021  anchorPoint = aLayer._anchorPoint,
1022  translateX = CGRectGetWidth(bounds) * anchorPoint.x,
1023  translateY = CGRectGetHeight(bounds) * anchorPoint.y;
1024 
1025  aLayer._sublayerTransformForSublayers = CGAffineTransformConcat(
1026  CGAffineTransformMakeTranslation(-translateX, -translateY),
1027  CGAffineTransformConcat(aLayer._sublayerTransform,
1028  CGAffineTransformMakeTranslation(translateX, translateY)));
1029 }
1030 
1031 function _CALayerUpdateDOM(aLayer, aMask)
1032 {
1033 #if PLATFORM(DOM)
1034  var DOMElementStyle = aLayer._DOMElement.style;
1035 
1036  if (aMask & CALayerZPositionUpdateMask)
1037  DOMElementStyle.zIndex = aLayer._zPosition;
1038 
1039  var frame = aLayer._backingStoreFrame;
1040 
1041  if (aMask & CALayerFrameOriginUpdateMask)
1042  {
1043  DOMElementStyle.top = ROUND(CGRectGetMinY(frame)) + "px";
1044  DOMElementStyle.left = ROUND(CGRectGetMinX(frame)) + "px";
1045  }
1046 
1047  if (aMask & CALayerFrameSizeUpdateMask)
1048  {
1049  var width = MAX(0.0, ROUND(CGRectGetWidth(frame))),
1050  height = MAX(0.0, ROUND(CGRectGetHeight(frame))),
1051  DOMContentsElement = aLayer._DOMContentsElement;
1052 
1053  DOMElementStyle.width = width + "px";
1054  DOMElementStyle.height = height + "px";
1055 
1056  if (DOMContentsElement)
1057  {
1058  DOMContentsElement.width = width;
1059  DOMContentsElement.height = height;
1060  DOMContentsElement.style.width = width + "px";
1061  DOMContentsElement.style.height = height + "px";
1062  }
1063  }
1064 #endif
1065 }
1066 
1067 function _CALayerRecalculateGeometry(aLayer, aGeometryChange)
1068 {
1069  var bounds = aLayer._bounds,
1070  superlayer = aLayer._superlayer,
1071  width = CGRectGetWidth(bounds),
1072  height = CGRectGetHeight(bounds),
1073  position = aLayer._position,
1074  anchorPoint = aLayer._anchorPoint,
1075  affineTransform = aLayer._affineTransform,
1076  backingStoreFrameSize = CGSizeMakeCopy(aLayer._backingStoreFrame),
1077  hasCustomBackingStoreFrame = aLayer._hasCustomBackingStoreFrame;
1078 
1079  // Go to anchor, transform, go back to bounds.
1080  aLayer._transformFromLayer = CGAffineTransformConcat(
1081  CGAffineTransformMakeTranslation(-width * anchorPoint.x - CGRectGetMinX(aLayer._bounds), -height * anchorPoint.y - CGRectGetMinY(aLayer._bounds)),
1084 
1085  if (superlayer && superlayer._hasSublayerTransform)
1086  {
1087  // aLayer._transformFromLayer = CGAffineTransformConcat(aLayer._transformFromLayer, superlayer._sublayerTransformForSublayers);
1088  CGAffineTransformConcatTo(aLayer._transformFromLayer, superlayer._sublayerTransformForSublayers, aLayer._transformFromLayer);
1089  }
1090 
1091  aLayer._transformToLayer = CGAffineTransformInvert(aLayer._transformFromLayer);
1092 
1093  //aLayer._transformFromLayer.tx = ROUND(aLayer._transformFromLayer.tx);
1094  //aLayer._transformFromLayer.ty = ROUND(aLayer._transformFromLayer.ty);
1095 
1096  aLayer._frame = nil;
1097  aLayer._standardBackingStoreFrame = [aLayer convertRect:bounds toLayer:nil];
1098 
1099  if (superlayer)
1100  {
1101  var bounds = [superlayer bounds],
1102  frame = [superlayer convertRect:bounds toLayer:nil];
1103 
1104  aLayer._standardBackingStoreFrame.origin.x -= CGRectGetMinX(frame);
1105  aLayer._standardBackingStoreFrame.origin.y -= CGRectGetMinY(frame);
1106  }
1107 
1108  // We used to use CGRectIntegral here, but what we actually want, is the largest integral
1109  // rect that would ever contain this box, since for any width/height, there are 2 (4)
1110  // possible integral rects for it depending on it's position. It's OK that this is sometimes
1111  // bigger than the "optimal" bounding integral rect since that doesn't change drawing.
1112 
1113  var origin = aLayer._standardBackingStoreFrame.origin,
1114  size = aLayer._standardBackingStoreFrame.size;
1115 
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;
1120 
1121  // FIXME: This avoids the central issue that a position change is sometimes a display and sometimes
1122  // a div move, and sometimes both.
1123 
1124  // Only use this frame if we don't currently have a custom backing store frame.
1125  if (!hasCustomBackingStoreFrame)
1126  {
1127  var backingStoreFrame = CGRectMakeCopy(aLayer._standardBackingStoreFrame);
1128 
1129  // These values get rounded in the DOM, so don't both updating them if they're
1130  // not going to be different after rounding.
1131  if (ROUND(CGRectGetMinX(backingStoreFrame)) != ROUND(CGRectGetMinX(aLayer._backingStoreFrame)) ||
1132  ROUND(CGRectGetMinY(backingStoreFrame)) != ROUND(CGRectGetMinY(aLayer._backingStoreFrame)))
1133  [aLayer registerRunLoopUpdateWithMask:CALayerFrameOriginUpdateMask];
1134 
1135  // Any change in size due to a geometry change is purely due to rounding error.
1136  if ((CGRectGetWidth(backingStoreFrame) != ROUND(CGRectGetWidth(aLayer._backingStoreFrame)) ||
1137  CGRectGetHeight(backingStoreFrame) != ROUND(CGRectGetHeight(aLayer._backingStoreFrame))))
1138  [aLayer registerRunLoopUpdateWithMask:CALayerFrameSizeUpdateMask];
1139 
1140  aLayer._backingStoreFrame = backingStoreFrame;
1141  }
1142 
1143  if (aGeometryChange & CALayerGeometryBoundsMask && aLayer._needsDisplayOnBoundsChange)
1144  [aLayer setNeedsDisplay];
1145  // We need to recompose if we have a custom backing store frame, OR
1146  // If the change is not solely composed of position and anchor points changes.
1147  // Anchor point and position changes simply move the object, requiring
1148  // no re-rendering.
1149  else if (hasCustomBackingStoreFrame || (aGeometryChange & ~(CALayerGeometryPositionMask | CALayerGeometryAnchorPointMask)))
1150  [aLayer setNeedsComposite];
1151 
1152  var sublayers = aLayer._sublayers,
1153  index = 0,
1154  count = sublayers.length;
1155 
1156  for (; index < count; ++index)
1157  _CALayerRecalculateGeometry(sublayers[index], aGeometryChange);
1158 }
1159 
1160 function _CALayerGetTransform(fromLayer, toLayer)
1161 {
1162  var transform = CGAffineTransformMakeIdentity();
1163 
1164  if (fromLayer)
1165  {
1166  var layer = fromLayer;
1167 
1168  // If we have a fromLayer, "climb up" the layer tree until
1169  // we hit the root node or we hit the toLayer.
1170  while (layer && layer != toLayer)
1171  {
1172  var transformFromLayer = layer._transformFromLayer;
1173 
1174  //transform = CGAffineTransformConcat(transform, layer._transformFromLayer);
1175  CGAffineTransformConcatTo(transform, transformFromLayer, transform);
1176 
1177  layer = layer._superlayer;
1178  }
1179 
1180  // If we hit toLayer, then we're done.
1181  if (layer == toLayer)
1182  return transform;
1183  }
1184 
1185  var layers = [],
1186  layer = toLayer;
1187 
1188  while (layer)
1189  {
1190  layers.push(layer);
1191  layer = layer._superlayer;
1192  }
1193 
1194  var index = layers.length;
1195 
1196  while (index--)
1197  {
1198  var transformToLayer = layers[index]._transformToLayer;
1199 
1200  CGAffineTransformConcatTo(transform, transformToLayer, transform);
1201  }
1202 
1203  return transform;
1204 }
void removeFromSuperlayer()
Definition: CALayer.j:666
Used to implement exception handling (creating & raising).
Definition: CPException.h:2
void setNeedsComposite()
Definition: CALayer.j:822
BOOL isHidden()
Definition: CALayer.j:597
A CALayer is similar to a CPView
Definition: CALayer.j:46
var USE_BUFFER
Definition: CALayer.j:34
function CGAffineTransformMakeIdentity()
var CALayerDOMUpdateMask
Definition: CALayer.j:41
CGPoint position()
Definition: CALayer.j:225
void runLoopUpdateLayers()
Definition: CALayer.j:780
The main run loop for the application.
Definition: CPRunLoop.h:2
#define ADJUST_CONTENTS_ZINDEX(aLayer)
Definition: CALayer.j:651
var CALayerCompositeUpdateMask
Definition: CALayer.j:40
void performSelector:target:argument:order:modes:(SEL aSelector, [target] id aTarget, [argument] id anArgument, [order] int anOrder, [modes] CPArray modes)
Definition: CPRunLoop.j:253
CABackingStoreSetSize
CPArray sublayers()
Definition: CALayer.j:638
function CGContextRestoreGState(aContext)
Definition: CGContext.j:156
id delegate()
Definition: CALayer.j:965
int width
void raise:reason:(CPString aName, [reason] CPString aReason)
Definition: CPException.j:66
var CALayerGeometryBoundsMask
Definition: CALayer.j:28
Definition: CALayer.h:2
CGPoint anchorPoint()
Definition: CALayer.j:271
CALayer superlayer()
Definition: CALayer.j:646
CPRunLoop currentRunLoop()
Definition: CPRunLoop.j:232
void setNeedsDisplay()
Definition: CALayer.j:830
CGRect bounds()
Definition: CALayer.j:203
void display()
Definition: CALayer.j:488
CALayer layer()
Definition: CALayer.j:118
var CALayerFrameSizeUpdateMask
Definition: CALayer.j:37
var CALayerGeometryAffineTransformMask
Definition: CALayer.j:31
var CALayerRegisteredRunLoopUpdates
Definition: CALayer.j:43
float opacity()
Definition: CALayer.j:556
#define DOM(aLayer)
Definition: CALayer.j:26
CGAffineTransform transformToLayer()
Definition: CALayer.j:336
var CALayerZPositionUpdateMask
Definition: CALayer.j:38
If the delegate implements this method
Definition: CALayer.j:50
function CGContextSetFillColor(aContext, aColor)
Definition: CGContext.j:663
function CGAffineTransformMakeTranslation(tx, ty)
function CGRectApplyAffineTransform(aRect, anAffineTransform)
function CGAffineTransformInvert(aTransform)
CPColor backgroundColor()
Definition: CALayer.j:629
function CGAffineTransformConcatTo(lhs, rhs, to)
var CALayerDisplayUpdateMask
Definition: CALayer.j:39
var CALayerGeometryAnchorPointMask
Definition: CALayer.j:30
CPNotFound
Definition: CPObjJRuntime.j:62
function CGContextSaveGState(aContext)
Definition: CGContext.j:146
CGRect frame()
Definition: CALayer.j:358
var CALayerGeometryPositionMask
Definition: CALayer.j:29
CGAffineTransform affineTransform()
Definition: CALayer.j:293
var CALayerGeometryParentSublayerTransformMask
Definition: CALayer.j:32
function CGContextFillRect(aContext, aRect)
Definition: CGContext.j:358
function CGContextConcatCTM(aContext, aTransform)
Definition: CGContext.j:420
function CGPointApplyAffineTransform(aPoint, aTransform)
BOOL needsDisplayOnBoundsChange()
Definition: CALayer.j:847
function CGBitmapGraphicsContextCreate()
Definition: CGContext.j:136
CGAffineTransformCreateCopy
function CGAffineTransformConcat(lhs, rhs)
BOOL hidden()
Definition: CALayer.j:589
Definition: CPView.j:136
var CALayerFrameOriginUpdateMask
Definition: CALayer.j:36
FrameUpdater prototype description
CGRect backingStoreFrame()
Definition: CALayer.j:374