1/* 2 * Copyright (C) 2009 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26#import "config.h" 27 28#if USE(ACCELERATED_COMPOSITING) 29 30#import "GraphicsLayerCA.h" 31 32#import "Animation.h" 33#import "BlockExceptions.h" 34#if ENABLE(3D_CANVAS) 35#import "Canvas3DLayer.h" 36#endif 37#import "CString.h" 38#import "FloatConversion.h" 39#import "FloatRect.h" 40#import "Image.h" 41#import "PlatformString.h" 42#import <QuartzCore/QuartzCore.h> 43#import "RotateTransformOperation.h" 44#import "ScaleTransformOperation.h" 45#import "StringBuilder.h" 46#import "SystemTime.h" 47#import "TranslateTransformOperation.h" 48#import "WebLayer.h" 49#import "WebTiledLayer.h" 50#import <limits.h> 51#import <objc/objc-auto.h> 52#import <wtf/CurrentTime.h> 53#import <wtf/UnusedParam.h> 54#import <wtf/RetainPtr.h> 55 56using namespace std; 57 58#define HAVE_MODERN_QUARTZCORE (!defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)) 59 60namespace WebCore { 61 62// The threshold width or height above which a tiled layer will be used. This should be 63// large enough to avoid tiled layers for most GraphicsLayers, but less than the OpenGL 64// texture size limit on all supported hardware. 65static const int cMaxPixelDimension = 2000; 66 67// The width and height of a single tile in a tiled layer. Should be large enough to 68// avoid lots of small tiles (and therefore lots of drawing callbacks), but small enough 69// to keep the overall tile cost low. 70static const int cTiledLayerTileSize = 512; 71 72// If we send a duration of 0 to CA, then it will use the default duration 73// of 250ms. So send a very small value instead. 74static const float cAnimationAlmostZeroDuration = 1e-3f; 75 76// CACurrentMediaTime() is a time since boot. These methods convert between that and 77// WebCore time, which is system time (UTC). 78static CFTimeInterval currentTimeToMediaTime(double t) 79{ 80 return CACurrentMediaTime() + t - WTF::currentTime(); 81} 82 83static double mediaTimeToCurrentTime(CFTimeInterval t) 84{ 85 return WTF::currentTime() + t - CACurrentMediaTime(); 86} 87 88} // namespace WebCore 89 90@interface CALayer(Private) 91- (void)setContentsChanged; 92@end 93 94@interface WebAnimationDelegate : NSObject { 95 WebCore::GraphicsLayerCA* m_graphicsLayer; 96} 97 98- (void)animationDidStart:(CAAnimation *)anim; 99- (WebCore::GraphicsLayerCA*)graphicsLayer; 100- (void)setLayer:(WebCore::GraphicsLayerCA*)graphicsLayer; 101 102@end 103 104@implementation WebAnimationDelegate 105 106- (void)animationDidStart:(CAAnimation *)animation 107{ 108 if (!m_graphicsLayer) 109 return; 110 111 double startTime = WebCore::mediaTimeToCurrentTime([animation beginTime]); 112 m_graphicsLayer->client()->notifyAnimationStarted(m_graphicsLayer, startTime); 113} 114 115- (WebCore::GraphicsLayerCA*)graphicsLayer 116{ 117 return m_graphicsLayer; 118} 119 120- (void)setLayer:(WebCore::GraphicsLayerCA*)graphicsLayer 121{ 122 m_graphicsLayer = graphicsLayer; 123} 124 125@end 126 127namespace WebCore { 128 129static inline void copyTransform(CATransform3D& toT3D, const TransformationMatrix& t) 130{ 131 toT3D.m11 = narrowPrecisionToFloat(t.m11()); 132 toT3D.m12 = narrowPrecisionToFloat(t.m12()); 133 toT3D.m13 = narrowPrecisionToFloat(t.m13()); 134 toT3D.m14 = narrowPrecisionToFloat(t.m14()); 135 toT3D.m21 = narrowPrecisionToFloat(t.m21()); 136 toT3D.m22 = narrowPrecisionToFloat(t.m22()); 137 toT3D.m23 = narrowPrecisionToFloat(t.m23()); 138 toT3D.m24 = narrowPrecisionToFloat(t.m24()); 139 toT3D.m31 = narrowPrecisionToFloat(t.m31()); 140 toT3D.m32 = narrowPrecisionToFloat(t.m32()); 141 toT3D.m33 = narrowPrecisionToFloat(t.m33()); 142 toT3D.m34 = narrowPrecisionToFloat(t.m34()); 143 toT3D.m41 = narrowPrecisionToFloat(t.m41()); 144 toT3D.m42 = narrowPrecisionToFloat(t.m42()); 145 toT3D.m43 = narrowPrecisionToFloat(t.m43()); 146 toT3D.m44 = narrowPrecisionToFloat(t.m44()); 147} 148 149static NSValue* getTransformFunctionValue(const TransformOperation* transformOp, TransformOperation::OperationType transformType, const IntSize& size) 150{ 151 switch (transformType) { 152 case TransformOperation::ROTATE: 153 case TransformOperation::ROTATE_X: 154 case TransformOperation::ROTATE_Y: 155 return [NSNumber numberWithDouble:transformOp ? deg2rad(static_cast<const RotateTransformOperation*>(transformOp)->angle()) : 0]; 156 case TransformOperation::SCALE_X: 157 return [NSNumber numberWithDouble:transformOp ? static_cast<const ScaleTransformOperation*>(transformOp)->x() : 1]; 158 case TransformOperation::SCALE_Y: 159 return [NSNumber numberWithDouble:transformOp ? static_cast<const ScaleTransformOperation*>(transformOp)->y() : 1]; 160 case TransformOperation::SCALE_Z: 161 return [NSNumber numberWithDouble:transformOp ? static_cast<const ScaleTransformOperation*>(transformOp)->z() : 1]; 162 case TransformOperation::TRANSLATE_X: 163 return [NSNumber numberWithDouble:transformOp ? static_cast<const TranslateTransformOperation*>(transformOp)->x(size) : 0]; 164 case TransformOperation::TRANSLATE_Y: 165 return [NSNumber numberWithDouble:transformOp ? static_cast<const TranslateTransformOperation*>(transformOp)->y(size) : 0]; 166 case TransformOperation::TRANSLATE_Z: 167 return [NSNumber numberWithDouble:transformOp ? static_cast<const TranslateTransformOperation*>(transformOp)->z(size) : 0]; 168 case TransformOperation::SCALE: 169 case TransformOperation::SCALE_3D: 170 return [NSArray arrayWithObjects: 171 [NSNumber numberWithDouble:transformOp ? static_cast<const ScaleTransformOperation*>(transformOp)->x() : 1], 172 [NSNumber numberWithDouble:transformOp ? static_cast<const ScaleTransformOperation*>(transformOp)->y() : 1], 173 [NSNumber numberWithDouble:transformOp ? static_cast<const ScaleTransformOperation*>(transformOp)->z() : 1], 174 nil]; 175 case TransformOperation::TRANSLATE: 176 case TransformOperation::TRANSLATE_3D: 177 return [NSArray arrayWithObjects: 178 [NSNumber numberWithDouble:transformOp ? static_cast<const TranslateTransformOperation*>(transformOp)->x(size) : 0], 179 [NSNumber numberWithDouble:transformOp ? static_cast<const TranslateTransformOperation*>(transformOp)->y(size) : 0], 180 [NSNumber numberWithDouble:transformOp ? static_cast<const TranslateTransformOperation*>(transformOp)->z(size) : 0], 181 nil]; 182 case TransformOperation::SKEW_X: 183 case TransformOperation::SKEW_Y: 184 case TransformOperation::SKEW: 185 case TransformOperation::MATRIX: 186 case TransformOperation::ROTATE_3D: 187 case TransformOperation::MATRIX_3D: 188 case TransformOperation::PERSPECTIVE: 189 case TransformOperation::IDENTITY: 190 case TransformOperation::NONE: { 191 TransformationMatrix transform; 192 if (transformOp) 193 transformOp->apply(transform, size); 194 CATransform3D caTransform; 195 copyTransform(caTransform, transform); 196 return [NSValue valueWithCATransform3D:caTransform]; 197 } 198 } 199 200 return 0; 201} 202 203#if HAVE_MODERN_QUARTZCORE 204static NSString* getValueFunctionNameForTransformOperation(TransformOperation::OperationType transformType) 205{ 206 // Use literal strings to avoid link-time dependency on those symbols. 207 switch (transformType) { 208 case TransformOperation::ROTATE_X: 209 return @"rotateX"; // kCAValueFunctionRotateX; 210 case TransformOperation::ROTATE_Y: 211 return @"rotateY"; // kCAValueFunctionRotateY; 212 case TransformOperation::ROTATE: 213 return @"rotateZ"; // kCAValueFunctionRotateZ; 214 case TransformOperation::SCALE_X: 215 return @"scaleX"; // kCAValueFunctionScaleX; 216 case TransformOperation::SCALE_Y: 217 return @"scaleY"; // kCAValueFunctionScaleY; 218 case TransformOperation::SCALE_Z: 219 return @"scaleZ"; // kCAValueFunctionScaleZ; 220 case TransformOperation::TRANSLATE_X: 221 return @"translateX"; // kCAValueFunctionTranslateX; 222 case TransformOperation::TRANSLATE_Y: 223 return @"translateY"; // kCAValueFunctionTranslateY; 224 case TransformOperation::TRANSLATE_Z: 225 return @"translateZ"; // kCAValueFunctionTranslateZ; 226 case TransformOperation::SCALE: 227 case TransformOperation::SCALE_3D: 228 return @"scale"; // kCAValueFunctionScale; 229 case TransformOperation::TRANSLATE: 230 case TransformOperation::TRANSLATE_3D: 231 return @"translate"; // kCAValueFunctionTranslate; 232 default: 233 return nil; 234 } 235} 236#endif 237 238static String propertyIdToString(AnimatedPropertyID property) 239{ 240 switch (property) { 241 case AnimatedPropertyWebkitTransform: 242 return "transform"; 243 case AnimatedPropertyOpacity: 244 return "opacity"; 245 case AnimatedPropertyBackgroundColor: 246 return "backgroundColor"; 247 case AnimatedPropertyInvalid: 248 ASSERT_NOT_REACHED(); 249 } 250 ASSERT_NOT_REACHED(); 251 return ""; 252} 253 254static String animationIdentifier(AnimatedPropertyID property, const String& keyframesName, int index) 255{ 256 StringBuilder builder; 257 258 builder.append(propertyIdToString(property)); 259 builder.append("_"); 260 261 if (!keyframesName.isEmpty()) { 262 builder.append(keyframesName); 263 builder.append("_"); 264 } 265 builder.append("_"); 266 builder.append(String::number(index)); 267 return builder.toString(); 268} 269 270#if !HAVE_MODERN_QUARTZCORE 271static TransformationMatrix flipTransform() 272{ 273 TransformationMatrix flipper; 274 flipper.flipY(); 275 return flipper; 276} 277#endif 278 279static CAMediaTimingFunction* getCAMediaTimingFunction(const TimingFunction& timingFunction) 280{ 281 switch (timingFunction.type()) { 282 case LinearTimingFunction: 283 return [CAMediaTimingFunction functionWithName:@"linear"]; 284 case CubicBezierTimingFunction: 285 return [CAMediaTimingFunction functionWithControlPoints:static_cast<float>(timingFunction.x1()) :static_cast<float>(timingFunction.y1()) 286 :static_cast<float>(timingFunction.x2()) :static_cast<float>(timingFunction.y2())]; 287 } 288 return 0; 289} 290 291static void setLayerBorderColor(PlatformLayer* layer, const Color& color) 292{ 293 CGColorRef borderColor = createCGColor(color); 294 [layer setBorderColor:borderColor]; 295 CGColorRelease(borderColor); 296} 297 298static void clearBorderColor(PlatformLayer* layer) 299{ 300 [layer setBorderColor:nil]; 301} 302 303static void setLayerBackgroundColor(PlatformLayer* layer, const Color& color) 304{ 305 CGColorRef bgColor = createCGColor(color); 306 [layer setBackgroundColor:bgColor]; 307 CGColorRelease(bgColor); 308} 309 310static void clearLayerBackgroundColor(PlatformLayer* layer) 311{ 312 [layer setBackgroundColor:0]; 313} 314 315static void safeSetSublayers(CALayer* layer, NSArray* sublayers) 316{ 317 // Workaround for <rdar://problem/7390716>: -[CALayer setSublayers:] crashes if sublayers is an empty array, or nil, under GC. 318 if (objc_collectingEnabled() && ![sublayers count]) { 319 while ([[layer sublayers] count]) 320 [[[layer sublayers] objectAtIndex:0] removeFromSuperlayer]; 321 return; 322 } 323 324 [layer setSublayers:sublayers]; 325} 326 327static bool caValueFunctionSupported() 328{ 329 static bool sHaveValueFunction = [CAPropertyAnimation instancesRespondToSelector:@selector(setValueFunction:)]; 330 return sHaveValueFunction; 331} 332 333static bool forceSoftwareAnimation() 334{ 335 static bool forceSoftwareAnimation = [[NSUserDefaults standardUserDefaults] boolForKey:@"WebCoreForceSoftwareAnimation"]; 336 return forceSoftwareAnimation; 337} 338 339GraphicsLayer::CompositingCoordinatesOrientation GraphicsLayer::compositingCoordinatesOrientation() 340{ 341 return CompositingCoordinatesBottomUp; 342} 343 344static NSDictionary* nullActionsDictionary() 345{ 346 NSNull* nullValue = [NSNull null]; 347 NSDictionary* actions = [NSDictionary dictionaryWithObjectsAndKeys: 348 nullValue, @"anchorPoint", 349 nullValue, @"bounds", 350 nullValue, @"contents", 351 nullValue, @"contentsRect", 352 nullValue, @"opacity", 353 nullValue, @"position", 354 nullValue, @"shadowColor", 355 nullValue, @"sublayerTransform", 356 nullValue, @"sublayers", 357 nullValue, @"transform", 358 nullValue, @"zPosition", 359 nil]; 360 return actions; 361} 362 363PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerClient* client) 364{ 365 return new GraphicsLayerCA(client); 366} 367 368GraphicsLayerCA::GraphicsLayerCA(GraphicsLayerClient* client) 369 : GraphicsLayer(client) 370 , m_contentsLayerPurpose(NoContentsLayer) 371 , m_contentsLayerHasBackgroundColor(false) 372 , m_uncommittedChanges(NoChange) 373#if ENABLE(3D_CANVAS) 374 , m_platformGraphicsContext3D(NullPlatformGraphicsContext3D) 375 , m_platformTexture(NullPlatform3DObject) 376#endif 377{ 378 BEGIN_BLOCK_OBJC_EXCEPTIONS 379 m_layer.adoptNS([[WebLayer alloc] init]); 380 [m_layer.get() setLayerOwner:this]; 381 382#if !HAVE_MODERN_QUARTZCORE 383 setContentsOrientation(defaultContentsOrientation()); 384#endif 385 386 updateDebugIndicators(); 387 388 m_animationDelegate.adoptNS([[WebAnimationDelegate alloc] init]); 389 [m_animationDelegate.get() setLayer:this]; 390 391 END_BLOCK_OBJC_EXCEPTIONS 392} 393 394GraphicsLayerCA::~GraphicsLayerCA() 395{ 396 // We release our references to the CALayers here, but do not actively unparent them, 397 // since that will cause a commit and break our batched commit model. The layers will 398 // get released when the rootmost modified GraphicsLayerCA rebuilds its child layers. 399 400 BEGIN_BLOCK_OBJC_EXCEPTIONS 401 402 // Clean up the WK layer. 403 if (m_layer) { 404 WebLayer* layer = m_layer.get(); 405 [layer setLayerOwner:nil]; 406 } 407 408 if (m_contentsLayer) { 409 if ([m_contentsLayer.get() respondsToSelector:@selector(setLayerOwner:)]) 410 [(id)m_contentsLayer.get() setLayerOwner:nil]; 411 } 412 413 // animationDidStart: can fire after this, so we need to clear out the layer on the delegate. 414 [m_animationDelegate.get() setLayer:0]; 415 416 // Release the clone layers inside the exception-handling block. 417 removeCloneLayers(); 418 419 END_BLOCK_OBJC_EXCEPTIONS 420} 421 422void GraphicsLayerCA::setName(const String& name) 423{ 424 String longName = String::format("CALayer(%p) GraphicsLayer(%p) ", m_layer.get(), this) + name; 425 GraphicsLayer::setName(longName); 426 noteLayerPropertyChanged(NameChanged); 427} 428 429NativeLayer GraphicsLayerCA::nativeLayer() const 430{ 431 return m_layer.get(); 432} 433 434bool GraphicsLayerCA::setChildren(const Vector<GraphicsLayer*>& children) 435{ 436 bool childrenChanged = GraphicsLayer::setChildren(children); 437 if (childrenChanged) 438 noteSublayersChanged(); 439 440 return childrenChanged; 441} 442 443void GraphicsLayerCA::addChild(GraphicsLayer* childLayer) 444{ 445 GraphicsLayer::addChild(childLayer); 446 noteSublayersChanged(); 447} 448 449void GraphicsLayerCA::addChildAtIndex(GraphicsLayer* childLayer, int index) 450{ 451 GraphicsLayer::addChildAtIndex(childLayer, index); 452 noteSublayersChanged(); 453} 454 455void GraphicsLayerCA::addChildBelow(GraphicsLayer* childLayer, GraphicsLayer* sibling) 456{ 457 GraphicsLayer::addChildBelow(childLayer, sibling); 458 noteSublayersChanged(); 459} 460 461void GraphicsLayerCA::addChildAbove(GraphicsLayer* childLayer, GraphicsLayer* sibling) 462{ 463 GraphicsLayer::addChildAbove(childLayer, sibling); 464 noteSublayersChanged(); 465} 466 467bool GraphicsLayerCA::replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild) 468{ 469 if (GraphicsLayer::replaceChild(oldChild, newChild)) { 470 noteSublayersChanged(); 471 return true; 472 } 473 return false; 474} 475 476void GraphicsLayerCA::removeFromParent() 477{ 478 if (m_parent) 479 static_cast<GraphicsLayerCA*>(m_parent)->noteSublayersChanged(); 480 GraphicsLayer::removeFromParent(); 481} 482 483void GraphicsLayerCA::setMaskLayer(GraphicsLayer* layer) 484{ 485 if (layer == m_maskLayer) 486 return; 487 488 GraphicsLayer::setMaskLayer(layer); 489 noteLayerPropertyChanged(MaskLayerChanged); 490 491 propagateLayerChangeToReplicas(); 492 493 if (m_replicatedLayer) 494 static_cast<GraphicsLayerCA*>(m_replicatedLayer)->propagateLayerChangeToReplicas(); 495} 496 497void GraphicsLayerCA::setReplicatedLayer(GraphicsLayer* layer) 498{ 499 if (layer == m_replicatedLayer) 500 return; 501 502 GraphicsLayer::setReplicatedLayer(layer); 503 noteLayerPropertyChanged(ReplicatedLayerChanged); 504} 505 506void GraphicsLayerCA::setReplicatedByLayer(GraphicsLayer* layer) 507{ 508 if (layer == m_replicaLayer) 509 return; 510 511 GraphicsLayer::setReplicatedByLayer(layer); 512 noteSublayersChanged(); 513 noteLayerPropertyChanged(ReplicatedLayerChanged); 514} 515 516void GraphicsLayerCA::setPosition(const FloatPoint& point) 517{ 518 if (point == m_position) 519 return; 520 521 GraphicsLayer::setPosition(point); 522 noteLayerPropertyChanged(PositionChanged); 523} 524 525void GraphicsLayerCA::setAnchorPoint(const FloatPoint3D& point) 526{ 527 if (point == m_anchorPoint) 528 return; 529 530 GraphicsLayer::setAnchorPoint(point); 531 noteLayerPropertyChanged(AnchorPointChanged); 532} 533 534void GraphicsLayerCA::setSize(const FloatSize& size) 535{ 536 if (size == m_size) 537 return; 538 539 GraphicsLayer::setSize(size); 540 noteLayerPropertyChanged(SizeChanged); 541} 542 543void GraphicsLayerCA::setTransform(const TransformationMatrix& t) 544{ 545 if (t == m_transform) 546 return; 547 548 GraphicsLayer::setTransform(t); 549 noteLayerPropertyChanged(TransformChanged); 550} 551 552void GraphicsLayerCA::setChildrenTransform(const TransformationMatrix& t) 553{ 554 if (t == m_childrenTransform) 555 return; 556 557 GraphicsLayer::setChildrenTransform(t); 558 noteLayerPropertyChanged(ChildrenTransformChanged); 559} 560 561void GraphicsLayerCA::moveOrCopyAllAnimationsForProperty(MoveOrCopy operation, AnimatedPropertyID property, const String& keyframesName, CALayer *fromLayer, CALayer *toLayer) 562{ 563 for (int index = 0; ; ++index) { 564 String animName = animationIdentifier(property, keyframesName, index); 565 566 CAAnimation* anim = [fromLayer animationForKey:animName]; 567 if (!anim) 568 break; 569 570 switch (operation) { 571 case Move: 572 [anim retain]; 573 [fromLayer removeAnimationForKey:animName]; 574 [toLayer addAnimation:anim forKey:animName]; 575 [anim release]; 576 break; 577 578 case Copy: 579 [toLayer addAnimation:anim forKey:animName]; 580 break; 581 } 582 } 583} 584 585void GraphicsLayerCA::moveOrCopyAnimationsForProperty(MoveOrCopy operation, AnimatedPropertyID property, CALayer *fromLayer, CALayer *toLayer) 586{ 587 // Move transitions for this property. 588 moveOrCopyAllAnimationsForProperty(operation, property, "", fromLayer, toLayer); 589 590 // Look for running animations affecting this property. 591 KeyframeAnimationsMap::const_iterator end = m_runningKeyframeAnimations.end(); 592 for (KeyframeAnimationsMap::const_iterator it = m_runningKeyframeAnimations.begin(); it != end; ++it) 593 moveOrCopyAllAnimationsForProperty(operation, property, it->first, fromLayer, toLayer); 594} 595 596void GraphicsLayerCA::setPreserves3D(bool preserves3D) 597{ 598 if (preserves3D == m_preserves3D) 599 return; 600 601 GraphicsLayer::setPreserves3D(preserves3D); 602 noteLayerPropertyChanged(Preserves3DChanged); 603} 604 605void GraphicsLayerCA::setMasksToBounds(bool masksToBounds) 606{ 607 if (masksToBounds == m_masksToBounds) 608 return; 609 610 GraphicsLayer::setMasksToBounds(masksToBounds); 611 noteLayerPropertyChanged(MasksToBoundsChanged); 612} 613 614void GraphicsLayerCA::setDrawsContent(bool drawsContent) 615{ 616 if (drawsContent == m_drawsContent) 617 return; 618 619 GraphicsLayer::setDrawsContent(drawsContent); 620 noteLayerPropertyChanged(DrawsContentChanged); 621} 622 623void GraphicsLayerCA::setBackgroundColor(const Color& color) 624{ 625 if (m_backgroundColorSet && m_backgroundColor == color) 626 return; 627 628 GraphicsLayer::setBackgroundColor(color); 629 630 m_contentsLayerHasBackgroundColor = true; 631 noteLayerPropertyChanged(BackgroundColorChanged); 632} 633 634void GraphicsLayerCA::clearBackgroundColor() 635{ 636 if (!m_backgroundColorSet) 637 return; 638 639 GraphicsLayer::clearBackgroundColor(); 640 m_contentsLayerHasBackgroundColor = false; 641 noteLayerPropertyChanged(BackgroundColorChanged); 642} 643 644void GraphicsLayerCA::setContentsOpaque(bool opaque) 645{ 646 if (m_contentsOpaque == opaque) 647 return; 648 649 GraphicsLayer::setContentsOpaque(opaque); 650 noteLayerPropertyChanged(ContentsOpaqueChanged); 651} 652 653void GraphicsLayerCA::setBackfaceVisibility(bool visible) 654{ 655 if (m_backfaceVisibility == visible) 656 return; 657 658 GraphicsLayer::setBackfaceVisibility(visible); 659 noteLayerPropertyChanged(BackfaceVisibilityChanged); 660} 661 662void GraphicsLayerCA::setOpacity(float opacity) 663{ 664 float clampedOpacity = max(0.0f, min(opacity, 1.0f)); 665 666 if (clampedOpacity == m_opacity) 667 return; 668 669 GraphicsLayer::setOpacity(clampedOpacity); 670 noteLayerPropertyChanged(OpacityChanged); 671} 672 673void GraphicsLayerCA::setNeedsDisplay() 674{ 675 FloatRect hugeRect(-numeric_limits<float>::max() / 2, -numeric_limits<float>::max() / 2, 676 numeric_limits<float>::max(), numeric_limits<float>::max()); 677 678 setNeedsDisplayInRect(hugeRect); 679} 680 681void GraphicsLayerCA::setNeedsDisplayInRect(const FloatRect& rect) 682{ 683 if (!drawsContent()) 684 return; 685 686 const size_t maxDirtyRects = 32; 687 688 for (size_t i = 0; i < m_dirtyRects.size(); ++i) { 689 if (m_dirtyRects[i].contains(rect)) 690 return; 691 } 692 693 if (m_dirtyRects.size() < maxDirtyRects) 694 m_dirtyRects.append(rect); 695 else 696 m_dirtyRects[0].unite(rect); 697 698 noteLayerPropertyChanged(DirtyRectsChanged); 699} 700 701void GraphicsLayerCA::setContentsRect(const IntRect& rect) 702{ 703 if (rect == m_contentsRect) 704 return; 705 706 GraphicsLayer::setContentsRect(rect); 707 noteLayerPropertyChanged(ContentsRectChanged); 708} 709 710bool GraphicsLayerCA::addAnimation(const KeyframeValueList& valueList, const IntSize& boxSize, const Animation* anim, const String& keyframesName, double timeOffset) 711{ 712 if (forceSoftwareAnimation() || !anim || anim->isEmptyOrZeroDuration() || valueList.size() < 2) 713 return false; 714 715#if !HAVE_MODERN_QUARTZCORE 716 // Older versions of QuartzCore do not handle opacity in transform layers properly, so we will 717 // always do software animation in that case. 718 if (valueList.property() == AnimatedPropertyOpacity) 719 return false; 720#endif 721 722 bool createdAnimations = false; 723 if (valueList.property() == AnimatedPropertyWebkitTransform) 724 createdAnimations = createTransformAnimationsFromKeyframes(valueList, anim, keyframesName, timeOffset, boxSize); 725 else 726 createdAnimations = createAnimationFromKeyframes(valueList, anim, keyframesName, timeOffset); 727 728 if (createdAnimations) 729 noteLayerPropertyChanged(AnimationChanged); 730 731 return createdAnimations; 732} 733 734void GraphicsLayerCA::removeAnimationsForProperty(AnimatedPropertyID property) 735{ 736 if (m_transitionPropertiesToRemove.find(property) != m_transitionPropertiesToRemove.end()) 737 return; 738 739 m_transitionPropertiesToRemove.add(property); 740 noteLayerPropertyChanged(AnimationChanged); 741} 742 743void GraphicsLayerCA::removeAnimationsForKeyframes(const String& animationName) 744{ 745 if (!animationIsRunning(animationName)) 746 return; 747 748 m_keyframeAnimationsToProcess.add(animationName, AnimationProcessingAction(Remove)); 749 noteLayerPropertyChanged(AnimationChanged); 750} 751 752void GraphicsLayerCA::pauseAnimation(const String& keyframesName, double timeOffset) 753{ 754 if (!animationIsRunning(keyframesName)) 755 return; 756 757 AnimationsToProcessMap::iterator it = m_keyframeAnimationsToProcess.find(keyframesName); 758 if (it != m_keyframeAnimationsToProcess.end()) { 759 AnimationProcessingAction& processingInfo = it->second; 760 // If an animation is scheduled to be removed, don't change the remove to a pause. 761 if (processingInfo.action != Remove) 762 processingInfo.action = Pause; 763 } else 764 m_keyframeAnimationsToProcess.add(keyframesName, AnimationProcessingAction(Pause, timeOffset)); 765 766 noteLayerPropertyChanged(AnimationChanged); 767} 768 769void GraphicsLayerCA::setContentsToImage(Image* image) 770{ 771 if (image) { 772 m_pendingContentsImage = image->nativeImageForCurrentFrame(); 773 CGColorSpaceRef colorSpace = CGImageGetColorSpace(m_pendingContentsImage.get()); 774 775 static CGColorSpaceRef deviceRGB = CGColorSpaceCreateDeviceRGB(); 776 if (colorSpace && CFEqual(colorSpace, deviceRGB)) { 777 // CoreGraphics renders images tagged with DeviceRGB using the color space of the main display. When we hand such 778 // images to CA we need to tag them similarly so CA rendering matches CG rendering. 779 static CGColorSpaceRef genericRGB = CGDisplayCopyColorSpace(kCGDirectMainDisplay); 780 m_pendingContentsImage.adoptCF(CGImageCreateCopyWithColorSpace(m_pendingContentsImage.get(), genericRGB)); 781 } 782 m_contentsLayerPurpose = ContentsLayerForImage; 783 if (!m_contentsLayer) 784 noteSublayersChanged(); 785 } else { 786 m_pendingContentsImage = 0; 787 m_contentsLayerPurpose = NoContentsLayer; 788 if (m_contentsLayer) 789 noteSublayersChanged(); 790 } 791 792 noteLayerPropertyChanged(ContentsImageChanged); 793} 794 795void GraphicsLayerCA::setContentsToMedia(PlatformLayer* mediaLayer) 796{ 797 if (mediaLayer == m_contentsLayer) 798 return; 799 800 m_contentsLayer = mediaLayer; 801 m_contentsLayerPurpose = mediaLayer ? ContentsLayerForMedia : NoContentsLayer; 802 803 noteSublayersChanged(); 804 noteLayerPropertyChanged(ContentsMediaLayerChanged); 805} 806 807void GraphicsLayerCA::setGeometryOrientation(CompositingCoordinatesOrientation orientation) 808{ 809 if (orientation == m_geometryOrientation) 810 return; 811 812 GraphicsLayer::setGeometryOrientation(orientation); 813 noteLayerPropertyChanged(GeometryOrientationChanged); 814 815#if !HAVE_MODERN_QUARTZCORE 816 // Geometry orientation is mapped onto children transform in older QuartzCores. 817 switch (m_geometryOrientation) { 818 case CompositingCoordinatesTopDown: 819 setChildrenTransform(TransformationMatrix()); 820 break; 821 822 case CompositingCoordinatesBottomUp: 823 setChildrenTransform(flipTransform()); 824 break; 825 } 826#endif 827} 828 829void GraphicsLayerCA::didDisplay(PlatformLayer* layer) 830{ 831 CALayer* sourceLayer; 832 LayerMap* layerCloneMap; 833 834 if (layer == m_layer) { 835 sourceLayer = m_layer.get(); 836 layerCloneMap = m_layerClones.get(); 837 } else if (layer == m_contentsLayer) { 838 sourceLayer = m_contentsLayer.get(); 839 layerCloneMap = m_contentsLayerClones.get(); 840 } else 841 return; 842 843 if (layerCloneMap) { 844 LayerMap::const_iterator end = layerCloneMap->end(); 845 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { 846 CALayer *currClone = it->second.get(); 847 if (!currClone) 848 continue; 849 850 if ([currClone contents] != [sourceLayer contents]) 851 [currClone setContents:[sourceLayer contents]]; 852 else 853 [currClone setContentsChanged]; 854 } 855 } 856} 857 858void GraphicsLayerCA::syncCompositingState() 859{ 860 recursiveCommitChanges(); 861} 862 863void GraphicsLayerCA::recursiveCommitChanges() 864{ 865 commitLayerChangesBeforeSublayers(); 866 867 if (m_maskLayer) 868 static_cast<GraphicsLayerCA*>(m_maskLayer)->commitLayerChangesBeforeSublayers(); 869 870 const Vector<GraphicsLayer*>& childLayers = children(); 871 size_t numChildren = childLayers.size(); 872 for (size_t i = 0; i < numChildren; ++i) { 873 GraphicsLayerCA* curChild = static_cast<GraphicsLayerCA*>(childLayers[i]); 874 curChild->recursiveCommitChanges(); 875 } 876 877 if (m_replicaLayer) 878 static_cast<GraphicsLayerCA*>(m_replicaLayer)->recursiveCommitChanges(); 879 880 if (m_maskLayer) 881 static_cast<GraphicsLayerCA*>(m_maskLayer)->commitLayerChangesAfterSublayers(); 882 883 commitLayerChangesAfterSublayers(); 884} 885 886void GraphicsLayerCA::commitLayerChangesBeforeSublayers() 887{ 888 if (!m_uncommittedChanges) 889 return; 890 891 BEGIN_BLOCK_OBJC_EXCEPTIONS 892 893 // Need to handle Preserves3DChanged first, because it affects which layers subsequent properties are applied to 894 if (m_uncommittedChanges & (Preserves3DChanged | ReplicatedLayerChanged)) 895 updateStructuralLayer(); 896 897 if (m_uncommittedChanges & NameChanged) 898 updateLayerNames(); 899 900 if (m_uncommittedChanges & ContentsImageChanged) // Needs to happen before ChildrenChanged 901 updateContentsImage(); 902 903 if (m_uncommittedChanges & ContentsMediaLayerChanged) // Needs to happen before ChildrenChanged 904 updateContentsMediaLayer(); 905 906#if ENABLE(3D_CANVAS) 907 if (m_uncommittedChanges & ContentsGraphicsContext3DChanged) // Needs to happen before ChildrenChanged 908 updateContentsGraphicsContext3D(); 909#endif 910 911 if (m_uncommittedChanges & BackgroundColorChanged) // Needs to happen before ChildrenChanged, and after updating image or video 912 updateLayerBackgroundColor(); 913 914 if (m_uncommittedChanges & ChildrenChanged) 915 updateSublayerList(); 916 917 if (m_uncommittedChanges & PositionChanged) 918 updateLayerPosition(); 919 920 if (m_uncommittedChanges & AnchorPointChanged) 921 updateAnchorPoint(); 922 923 if (m_uncommittedChanges & SizeChanged) 924 updateLayerSize(); 925 926 if (m_uncommittedChanges & TransformChanged) 927 updateTransform(); 928 929 if (m_uncommittedChanges & ChildrenTransformChanged) 930 updateChildrenTransform(); 931 932 if (m_uncommittedChanges & MasksToBoundsChanged) 933 updateMasksToBounds(); 934 935 if (m_uncommittedChanges & DrawsContentChanged) 936 updateLayerDrawsContent(); 937 938 if (m_uncommittedChanges & ContentsOpaqueChanged) 939 updateContentsOpaque(); 940 941 if (m_uncommittedChanges & BackfaceVisibilityChanged) 942 updateBackfaceVisibility(); 943 944 if (m_uncommittedChanges & OpacityChanged) 945 updateOpacityOnLayer(); 946 947 if (m_uncommittedChanges & AnimationChanged) 948 updateLayerAnimations(); 949 950 if (m_uncommittedChanges & DirtyRectsChanged) 951 repaintLayerDirtyRects(); 952 953 if (m_uncommittedChanges & ContentsRectChanged) 954 updateContentsRect(); 955 956 if (m_uncommittedChanges & GeometryOrientationChanged) 957 updateGeometryOrientation(); 958 959 if (m_uncommittedChanges & MaskLayerChanged) 960 updateMaskLayer(); 961 962 END_BLOCK_OBJC_EXCEPTIONS 963} 964 965void GraphicsLayerCA::commitLayerChangesAfterSublayers() 966{ 967 if (!m_uncommittedChanges) 968 return; 969 970 BEGIN_BLOCK_OBJC_EXCEPTIONS 971 972 if (m_uncommittedChanges & ReplicatedLayerChanged) 973 updateReplicatedLayers(); 974 975 m_uncommittedChanges = NoChange; 976 END_BLOCK_OBJC_EXCEPTIONS 977} 978 979void GraphicsLayerCA::updateLayerNames() 980{ 981 switch (structuralLayerPurpose()) { 982 case StructuralLayerForPreserves3D: 983 [m_structuralLayer.get() setName:("Transform layer " + name())]; 984 break; 985 case StructuralLayerForReplicaFlattening: 986 [m_structuralLayer.get() setName:("Replica flattening layer " + name())]; 987 break; 988 case NoStructuralLayer: 989 break; 990 } 991 [m_layer.get() setName:name()]; 992} 993 994void GraphicsLayerCA::updateSublayerList() 995{ 996 NSMutableArray* newSublayers = nil; 997 998 const Vector<GraphicsLayer*>& childLayers = children(); 999 1000 if (m_structuralLayer || m_contentsLayer || childLayers.size() > 0) { 1001 newSublayers = [[NSMutableArray alloc] init]; 1002 1003 if (m_structuralLayer) { 1004 // Add the replica layer first. 1005 if (m_replicaLayer) 1006 [newSublayers addObject:static_cast<GraphicsLayerCA*>(m_replicaLayer)->primaryLayer()]; 1007 // Add the primary layer. Even if we have negative z-order children, the primary layer always comes behind. 1008 [newSublayers addObject:m_layer.get()]; 1009 } else if (m_contentsLayer) { 1010 // FIXME: add the contents layer in the correct order with negative z-order children. 1011 // This does not cause visible rendering issues because currently contents layers are only used 1012 // for replaced elements that don't have children. 1013 [newSublayers addObject:m_contentsLayer.get()]; 1014 } 1015 1016 size_t numChildren = childLayers.size(); 1017 for (size_t i = 0; i < numChildren; ++i) { 1018 GraphicsLayerCA* curChild = static_cast<GraphicsLayerCA*>(childLayers[i]); 1019 CALayer *childLayer = curChild->layerForSuperlayer(); 1020 [newSublayers addObject:childLayer]; 1021 } 1022 1023 [newSublayers makeObjectsPerformSelector:@selector(removeFromSuperlayer)]; 1024 } 1025 1026 if (m_structuralLayer) { 1027 safeSetSublayers(m_structuralLayer.get(), newSublayers); 1028 1029 if (m_contentsLayer) { 1030 // If we have a transform layer, then the contents layer is parented in the 1031 // primary layer (which is itself a child of the transform layer). 1032 safeSetSublayers(m_layer.get(), nil); 1033 [m_layer.get() addSublayer:m_contentsLayer.get()]; 1034 } 1035 } else 1036 safeSetSublayers(m_layer.get(), newSublayers); 1037 1038 [newSublayers release]; 1039} 1040 1041void GraphicsLayerCA::updateLayerPosition() 1042{ 1043 // Position is offset on the layer by the layer anchor point. 1044 CGPoint posPoint = CGPointMake(m_position.x() + m_anchorPoint.x() * m_size.width(), 1045 m_position.y() + m_anchorPoint.y() * m_size.height()); 1046 1047 [primaryLayer() setPosition:posPoint]; 1048 1049 if (LayerMap* layerCloneMap = primaryLayerClones()) { 1050 LayerMap::const_iterator end = layerCloneMap->end(); 1051 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { 1052 CGPoint clonePosition = posPoint; 1053 if (m_replicaLayer && isReplicatedRootClone(it->first)) { 1054 // Maintain the special-case position for the root of a clone subtree, 1055 // which we set up in replicatedLayerRoot(). 1056 clonePosition = positionForCloneRootLayer(); 1057 } 1058 CALayer *currLayer = it->second.get(); 1059 [currLayer setPosition:clonePosition]; 1060 } 1061 } 1062} 1063 1064void GraphicsLayerCA::updateLayerSize() 1065{ 1066 CGRect rect = CGRectMake(0, 0, m_size.width(), m_size.height()); 1067 if (m_structuralLayer) { 1068 [m_structuralLayer.get() setBounds:rect]; 1069 1070 if (LayerMap* layerCloneMap = m_structuralLayerClones.get()) { 1071 LayerMap::const_iterator end = layerCloneMap->end(); 1072 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) 1073 [it->second.get() setBounds:rect]; 1074 } 1075 1076 // The anchor of the contents layer is always at 0.5, 0.5, so the position is center-relative. 1077 CGPoint centerPoint = CGPointMake(m_size.width() / 2.0f, m_size.height() / 2.0f); 1078 [m_layer.get() setPosition:centerPoint]; 1079 1080 if (LayerMap* layerCloneMap = m_layerClones.get()) { 1081 LayerMap::const_iterator end = layerCloneMap->end(); 1082 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) 1083 [it->second.get() setPosition:centerPoint]; 1084 } 1085 } 1086 1087 bool needTiledLayer = requiresTiledLayer(m_size); 1088 if (needTiledLayer != m_usingTiledLayer) 1089 swapFromOrToTiledLayer(needTiledLayer); 1090 1091 [m_layer.get() setBounds:rect]; 1092 if (LayerMap* layerCloneMap = m_layerClones.get()) { 1093 LayerMap::const_iterator end = layerCloneMap->end(); 1094 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) 1095 [it->second.get() setBounds:rect]; 1096 } 1097 1098 // Contents transform may depend on height. 1099 updateContentsTransform(); 1100 1101 // Note that we don't resize m_contentsLayer. It's up the caller to do that. 1102 1103 // if we've changed the bounds, we need to recalculate the position 1104 // of the layer, taking anchor point into account. 1105 updateLayerPosition(); 1106} 1107 1108void GraphicsLayerCA::updateAnchorPoint() 1109{ 1110 [primaryLayer() setAnchorPoint:FloatPoint(m_anchorPoint.x(), m_anchorPoint.y())]; 1111#if HAVE_MODERN_QUARTZCORE 1112 [primaryLayer() setAnchorPointZ:m_anchorPoint.z()]; 1113#endif 1114 1115 if (LayerMap* layerCloneMap = primaryLayerClones()) { 1116 LayerMap::const_iterator end = layerCloneMap->end(); 1117 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { 1118 CALayer *currLayer = it->second.get(); 1119 [currLayer setAnchorPoint:FloatPoint(m_anchorPoint.x(), m_anchorPoint.y())]; 1120#if HAVE_MODERN_QUARTZCORE 1121 [currLayer setAnchorPointZ:m_anchorPoint.z()]; 1122#endif 1123 } 1124 } 1125 1126 updateLayerPosition(); 1127} 1128 1129void GraphicsLayerCA::updateTransform() 1130{ 1131 CATransform3D transform; 1132 copyTransform(transform, m_transform); 1133 [primaryLayer() setTransform:transform]; 1134 1135 if (LayerMap* layerCloneMap = primaryLayerClones()) { 1136 LayerMap::const_iterator end = layerCloneMap->end(); 1137 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { 1138 CALayer *currLayer = it->second.get(); 1139 if (m_replicaLayer && isReplicatedRootClone(it->first)) { 1140 // Maintain the special-case transform for the root of a clone subtree, 1141 // which we set up in replicatedLayerRoot(). 1142 [currLayer setTransform:CATransform3DIdentity]; 1143 } else 1144 [currLayer setTransform:transform]; 1145 } 1146 } 1147} 1148 1149void GraphicsLayerCA::updateChildrenTransform() 1150{ 1151 CATransform3D transform; 1152 copyTransform(transform, m_childrenTransform); 1153 [primaryLayer() setSublayerTransform:transform]; 1154 1155 if (LayerMap* layerCloneMap = primaryLayerClones()) { 1156 LayerMap::const_iterator end = layerCloneMap->end(); 1157 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { 1158 CALayer *currLayer = it->second.get(); 1159 [currLayer setSublayerTransform:transform]; 1160 } 1161 } 1162} 1163 1164void GraphicsLayerCA::updateMasksToBounds() 1165{ 1166 [m_layer.get() setMasksToBounds:m_masksToBounds]; 1167 1168 if (LayerMap* layerCloneMap = m_layerClones.get()) { 1169 LayerMap::const_iterator end = layerCloneMap->end(); 1170 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { 1171 CALayer *currLayer = it->second.get(); 1172 [currLayer setMasksToBounds:m_masksToBounds]; 1173 } 1174 } 1175 1176 updateDebugIndicators(); 1177} 1178 1179void GraphicsLayerCA::updateContentsOpaque() 1180{ 1181 [m_layer.get() setOpaque:m_contentsOpaque]; 1182 1183 if (LayerMap* layerCloneMap = m_layerClones.get()) { 1184 LayerMap::const_iterator end = layerCloneMap->end(); 1185 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { 1186 CALayer *currLayer = it->second.get(); 1187 [currLayer setOpaque:m_contentsOpaque]; 1188 } 1189 } 1190} 1191 1192void GraphicsLayerCA::updateBackfaceVisibility() 1193{ 1194 [m_layer.get() setDoubleSided:m_backfaceVisibility]; 1195 1196 if (LayerMap* layerCloneMap = m_layerClones.get()) { 1197 LayerMap::const_iterator end = layerCloneMap->end(); 1198 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { 1199 CALayer *currLayer = it->second.get(); 1200 [currLayer setDoubleSided:m_backfaceVisibility]; 1201 } 1202 } 1203} 1204 1205void GraphicsLayerCA::updateStructuralLayer() 1206{ 1207 ensureStructuralLayer(structuralLayerPurpose()); 1208} 1209 1210void GraphicsLayerCA::ensureStructuralLayer(StructuralLayerPurpose purpose) 1211{ 1212 if (purpose == NoStructuralLayer) { 1213 if (m_structuralLayer) { 1214 // Replace the transformLayer in the parent with this layer. 1215 [m_layer.get() removeFromSuperlayer]; 1216 [[m_structuralLayer.get() superlayer] replaceSublayer:m_structuralLayer.get() with:m_layer.get()]; 1217 1218 moveOrCopyAnimationsForProperty(Move, AnimatedPropertyWebkitTransform, m_structuralLayer.get(), m_layer.get()); 1219 moveOrCopyAnimationsForProperty(Move, AnimatedPropertyOpacity, m_structuralLayer.get(), m_layer.get()); 1220 1221 // Release the structural layer. 1222 m_structuralLayer = 0; 1223 1224 // Update the properties of m_layer now that we no loner have a structural layer. 1225 updateLayerPosition(); 1226 updateLayerSize(); 1227 updateAnchorPoint(); 1228 updateTransform(); 1229 updateChildrenTransform(); 1230 1231 updateSublayerList(); 1232 updateOpacityOnLayer(); 1233 } 1234 return; 1235 } 1236 1237 bool structuralLayerChanged = false; 1238 1239 if (purpose == StructuralLayerForPreserves3D) { 1240 Class transformLayerClass = NSClassFromString(@"CATransformLayer"); 1241 if (!transformLayerClass) 1242 return; 1243 1244 if (m_structuralLayer && ![m_structuralLayer.get() isKindOfClass:transformLayerClass]) 1245 m_structuralLayer = 0; 1246 1247 if (!m_structuralLayer) { 1248 m_structuralLayer.adoptNS([[transformLayerClass alloc] init]); 1249 structuralLayerChanged = true; 1250 } 1251 } else { 1252 if (m_structuralLayer && ![m_structuralLayer.get() isMemberOfClass:[CALayer self]]) 1253 m_structuralLayer = 0; 1254 1255 if (!m_structuralLayer) { 1256 m_structuralLayer.adoptNS([[CALayer alloc] init]); 1257 structuralLayerChanged = true; 1258 } 1259 } 1260 1261 if (!structuralLayerChanged) 1262 return; 1263 1264 // Turn off default animations. 1265 [m_structuralLayer.get() setStyle:[NSDictionary dictionaryWithObject:nullActionsDictionary() forKey:@"actions"]]; 1266 1267 updateLayerNames(); 1268 1269 // Update the properties of the structural layer. 1270 updateLayerPosition(); 1271 updateLayerSize(); 1272 updateAnchorPoint(); 1273 updateTransform(); 1274 updateChildrenTransform(); 1275 1276 // Set properties of m_layer to their default values, since these are expressed on on the structural layer. 1277 CGPoint point = CGPointMake(m_size.width() / 2.0f, m_size.height() / 2.0f); 1278 [m_layer.get() setPosition:point]; 1279 [m_layer.get() setAnchorPoint:CGPointMake(0.5f, 0.5f)]; 1280 [m_layer.get() setTransform:CATransform3DIdentity]; 1281 [m_layer.get() setOpacity:1]; 1282 1283 // Move this layer to be a child of the transform layer. 1284 [[m_layer.get() superlayer] replaceSublayer:m_layer.get() with:m_structuralLayer.get()]; 1285 [m_structuralLayer.get() addSublayer:m_layer.get()]; 1286 1287 moveOrCopyAnimationsForProperty(Move, AnimatedPropertyWebkitTransform, m_layer.get(), m_structuralLayer.get()); 1288 moveOrCopyAnimationsForProperty(Move, AnimatedPropertyOpacity, m_layer.get(), m_structuralLayer.get()); 1289 1290 updateSublayerList(); 1291 updateOpacityOnLayer(); 1292} 1293 1294GraphicsLayerCA::StructuralLayerPurpose GraphicsLayerCA::structuralLayerPurpose() const 1295{ 1296 if (preserves3D()) 1297 return StructuralLayerForPreserves3D; 1298 1299 if (isReplicated()) 1300 return StructuralLayerForReplicaFlattening; 1301 1302 return NoStructuralLayer; 1303} 1304 1305void GraphicsLayerCA::updateLayerDrawsContent() 1306{ 1307 bool needTiledLayer = requiresTiledLayer(m_size); 1308 if (needTiledLayer != m_usingTiledLayer) 1309 swapFromOrToTiledLayer(needTiledLayer); 1310 1311 if (m_drawsContent) 1312 [m_layer.get() setNeedsDisplay]; 1313 else 1314 [m_layer.get() setContents:nil]; 1315 1316 updateDebugIndicators(); 1317} 1318 1319void GraphicsLayerCA::updateLayerBackgroundColor() 1320{ 1321 if (!m_contentsLayer) 1322 return; 1323 1324 // We never create the contents layer just for background color yet. 1325 if (m_backgroundColorSet) 1326 setLayerBackgroundColor(m_contentsLayer.get(), m_backgroundColor); 1327 else 1328 clearLayerBackgroundColor(m_contentsLayer.get()); 1329} 1330 1331void GraphicsLayerCA::updateContentsImage() 1332{ 1333 if (m_pendingContentsImage) { 1334 if (!m_contentsLayer.get()) { 1335 WebLayer* imageLayer = [WebLayer layer]; 1336#ifndef NDEBUG 1337 [imageLayer setName:@"Image Layer"]; 1338#endif 1339 setupContentsLayer(imageLayer); 1340 m_contentsLayer.adoptNS([imageLayer retain]); 1341 // m_contentsLayer will be parented by updateSublayerList 1342 } 1343 1344 // FIXME: maybe only do trilinear if the image is being scaled down, 1345 // but then what if the layer size changes? 1346#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) 1347 [m_contentsLayer.get() setMinificationFilter:kCAFilterTrilinear]; 1348#endif 1349 [m_contentsLayer.get() setContents:(id)m_pendingContentsImage.get()]; 1350 m_pendingContentsImage = 0; 1351 1352 if (m_contentsLayerClones) { 1353 LayerMap::const_iterator end = m_contentsLayerClones->end(); 1354 for (LayerMap::const_iterator it = m_contentsLayerClones->begin(); it != end; ++it) 1355 [it->second.get() setContents:[m_contentsLayer.get() contents]]; 1356 } 1357 1358 updateContentsRect(); 1359 } else { 1360 // No image. 1361 // m_contentsLayer will be removed via updateSublayerList. 1362 m_contentsLayer = 0; 1363 } 1364} 1365 1366void GraphicsLayerCA::updateContentsMediaLayer() 1367{ 1368 // Video layer was set as m_contentsLayer, and will get parented in updateSublayerList(). 1369 if (m_contentsLayer) { 1370 setupContentsLayer(m_contentsLayer.get()); 1371 updateContentsRect(); 1372 } 1373} 1374 1375#if ENABLE(3D_CANVAS) 1376void GraphicsLayerCA::updateContentsGraphicsContext3D() 1377{ 1378 // Canvas3D layer was set as m_contentsLayer, and will get parented in updateSublayerList(). 1379 if (m_contentsLayer) { 1380 setupContentsLayer(m_contentsLayer.get()); 1381 [m_contentsLayer.get() setNeedsDisplay]; 1382 updateContentsRect(); 1383 } 1384} 1385#endif 1386 1387void GraphicsLayerCA::updateContentsRect() 1388{ 1389 if (!m_contentsLayer) 1390 return; 1391 1392 CGPoint point = CGPointMake(m_contentsRect.x(), 1393 m_contentsRect.y()); 1394 CGRect rect = CGRectMake(0.0f, 1395 0.0f, 1396 m_contentsRect.width(), 1397 m_contentsRect.height()); 1398 1399 [m_contentsLayer.get() setPosition:point]; 1400 [m_contentsLayer.get() setBounds:rect]; 1401 1402 if (m_contentsLayerClones) { 1403 LayerMap::const_iterator end = m_contentsLayerClones->end(); 1404 for (LayerMap::const_iterator it = m_contentsLayerClones->begin(); it != end; ++it) { 1405 CALayer *currLayer = it->second.get(); 1406 [currLayer setPosition:point]; 1407 [currLayer setBounds:rect]; 1408 } 1409 } 1410} 1411 1412void GraphicsLayerCA::updateGeometryOrientation() 1413{ 1414#if HAVE_MODERN_QUARTZCORE 1415 switch (geometryOrientation()) { 1416 case CompositingCoordinatesTopDown: 1417 [m_layer.get() setGeometryFlipped:NO]; 1418 break; 1419 1420 case CompositingCoordinatesBottomUp: 1421 [m_layer.get() setGeometryFlipped:YES]; 1422 break; 1423 } 1424 // Geometry orientation is mapped onto children transform in older QuartzCores, 1425 // so is handled via setGeometryOrientation(). 1426#endif 1427} 1428 1429void GraphicsLayerCA::updateMaskLayer() 1430{ 1431 CALayer *maskCALayer = m_maskLayer ? m_maskLayer->platformLayer() : 0; 1432 [m_layer.get() setMask:maskCALayer]; 1433 1434 LayerMap* maskLayerCloneMap = m_maskLayer ? static_cast<GraphicsLayerCA*>(m_maskLayer)->primaryLayerClones() : 0; 1435 1436 if (LayerMap* layerCloneMap = m_layerClones.get()) { 1437 LayerMap::const_iterator end = layerCloneMap->end(); 1438 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { 1439 CALayer *currLayer = it->second.get(); 1440 1441 CALayer *maskClone = maskLayerCloneMap ? maskLayerCloneMap->get(it->first).get() : 0; 1442 [currLayer setMask:maskClone]; 1443 } 1444 } 1445} 1446 1447void GraphicsLayerCA::updateReplicatedLayers() 1448{ 1449 // Clone the descendants of the replicated layer, and parent under us. 1450 ReplicaState replicaState(ReplicaState::ReplicaBranch); 1451 1452 CALayer *replicaRoot = replicatedLayerRoot(replicaState); 1453 if (!replicaRoot) 1454 return; 1455 1456 if (m_structuralLayer) 1457 [m_structuralLayer.get() insertSublayer:replicaRoot atIndex:0]; 1458 else 1459 [m_layer.get() insertSublayer:replicaRoot atIndex:0]; 1460} 1461 1462// For now, this assumes that layers only ever have one replica, so replicaIndices contains only 0 and 1. 1463GraphicsLayerCA::CloneID GraphicsLayerCA::ReplicaState::cloneID() const 1464{ 1465 size_t depth = m_replicaBranches.size(); 1466 1467 const size_t bitsPerUChar = sizeof(UChar) * 8; 1468 size_t vectorSize = (depth + bitsPerUChar - 1) / bitsPerUChar; 1469 1470 Vector<UChar> result(vectorSize); 1471 result.fill(0); 1472 1473 // Create a string from the bit sequence which we can use to identify the clone. 1474 // Note that the string may contain embedded nulls, but that's OK. 1475 for (size_t i = 0; i < depth; ++i) { 1476 UChar& currChar = result[i / bitsPerUChar]; 1477 currChar = (currChar << 1) | m_replicaBranches[i]; 1478 } 1479 1480 return String::adopt(result); 1481} 1482 1483CALayer *GraphicsLayerCA::replicatedLayerRoot(ReplicaState& replicaState) 1484{ 1485 // Limit replica nesting, to avoid 2^N explosion of replica layers. 1486 if (!m_replicatedLayer || replicaState.replicaDepth() == ReplicaState::maxReplicaDepth) 1487 return nil; 1488 1489 GraphicsLayerCA* replicatedLayer = static_cast<GraphicsLayerCA*>(m_replicatedLayer); 1490 1491 CALayer *clonedLayerRoot = replicatedLayer->fetchCloneLayers(this, replicaState, RootCloneLevel); 1492 FloatPoint cloneRootPosition = replicatedLayer->positionForCloneRootLayer(); 1493 1494 // Replica root has no offset or transform 1495 [clonedLayerRoot setPosition:cloneRootPosition]; 1496 [clonedLayerRoot setTransform:CATransform3DIdentity]; 1497 1498 return clonedLayerRoot; 1499} 1500 1501void GraphicsLayerCA::updateLayerAnimations() 1502{ 1503 if (m_transitionPropertiesToRemove.size()) { 1504 HashSet<int>::const_iterator end = m_transitionPropertiesToRemove.end(); 1505 for (HashSet<AnimatedProperty>::const_iterator it = m_transitionPropertiesToRemove.begin(); it != end; ++it) { 1506 AnimatedPropertyID currProperty = static_cast<AnimatedPropertyID>(*it); 1507 // Remove all animations with this property in the key. 1508 for (int index = 0; ; ++index) { 1509 if (!removeAnimationFromLayer(currProperty, "", index)) 1510 break; 1511 } 1512 } 1513 1514 m_transitionPropertiesToRemove.clear(); 1515 } 1516 1517 if (m_keyframeAnimationsToProcess.size()) { 1518 AnimationsToProcessMap::const_iterator end = m_keyframeAnimationsToProcess.end(); 1519 for (AnimationsToProcessMap::const_iterator it = m_keyframeAnimationsToProcess.begin(); it != end; ++it) { 1520 const String& currKeyframeName = it->first; 1521 KeyframeAnimationsMap::iterator animationIt = m_runningKeyframeAnimations.find(currKeyframeName); 1522 if (animationIt == m_runningKeyframeAnimations.end()) 1523 continue; 1524 1525 const AnimationProcessingAction& processingInfo = it->second; 1526 const Vector<AnimationPair>& animations = animationIt->second; 1527 for (size_t i = 0; i < animations.size(); ++i) { 1528 const AnimationPair& currPair = animations[i]; 1529 switch (processingInfo.action) { 1530 case Remove: 1531 removeAnimationFromLayer(static_cast<AnimatedPropertyID>(currPair.first), currKeyframeName, currPair.second); 1532 break; 1533 case Pause: 1534 pauseAnimationOnLayer(static_cast<AnimatedPropertyID>(currPair.first), currKeyframeName, currPair.second, processingInfo.timeOffset); 1535 break; 1536 } 1537 } 1538 1539 if (processingInfo.action == Remove) 1540 m_runningKeyframeAnimations.remove(currKeyframeName); 1541 } 1542 1543 m_keyframeAnimationsToProcess.clear(); 1544 } 1545 1546 size_t numAnimations; 1547 if ((numAnimations = m_uncomittedAnimations.size())) { 1548 for (size_t i = 0; i < numAnimations; ++i) { 1549 const LayerAnimation& pendingAnimation = m_uncomittedAnimations[i]; 1550 setAnimationOnLayer(pendingAnimation.m_animation.get(), pendingAnimation.m_property, pendingAnimation.m_keyframesName, pendingAnimation.m_index, pendingAnimation.m_timeOffset); 1551 1552 if (!pendingAnimation.m_keyframesName.isEmpty()) { 1553 // If this is a keyframe anim, we have to remember the association of keyframes name to property/index pairs, 1554 // so we can remove the animations later if needed. 1555 // For transitions, we can just generate animation names with property and index. 1556 KeyframeAnimationsMap::iterator it = m_runningKeyframeAnimations.find(pendingAnimation.m_keyframesName); 1557 if (it == m_runningKeyframeAnimations.end()) { 1558 Vector<AnimationPair> firstPair; 1559 firstPair.append(AnimationPair(pendingAnimation.m_property, pendingAnimation.m_index)); 1560 m_runningKeyframeAnimations.add(pendingAnimation.m_keyframesName, firstPair); 1561 } else { 1562 Vector<AnimationPair>& animPairs = it->second; 1563 animPairs.append(AnimationPair(pendingAnimation.m_property, pendingAnimation.m_index)); 1564 } 1565 } 1566 } 1567 1568 m_uncomittedAnimations.clear(); 1569 } 1570} 1571 1572void GraphicsLayerCA::setAnimationOnLayer(CAPropertyAnimation* caAnim, AnimatedPropertyID property, const String& keyframesName, int index, double timeOffset) 1573{ 1574 PlatformLayer* layer = animatedLayer(property); 1575 1576 [caAnim setTimeOffset:timeOffset]; 1577 1578 String animationName = animationIdentifier(property, keyframesName, index); 1579 1580 [layer removeAnimationForKey:animationName]; 1581 [layer addAnimation:caAnim forKey:animationName]; 1582 1583 if (LayerMap* layerCloneMap = animatedLayerClones(property)) { 1584 LayerMap::const_iterator end = layerCloneMap->end(); 1585 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { 1586 // Skip immediate replicas, since they move with the original. 1587 if (m_replicaLayer && isReplicatedRootClone(it->first)) 1588 continue; 1589 CALayer *currLayer = it->second.get(); 1590 [currLayer removeAnimationForKey:animationName]; 1591 [currLayer addAnimation:caAnim forKey:animationName]; 1592 } 1593 } 1594} 1595 1596// Workaround for <rdar://problem/7311367> 1597static void bug7311367Workaround(CALayer* transformLayer, const TransformationMatrix& transform) 1598{ 1599 if (!transformLayer) 1600 return; 1601 1602 CATransform3D caTransform; 1603 copyTransform(caTransform, transform); 1604 caTransform.m41 += 1; 1605 [transformLayer setTransform:caTransform]; 1606 1607 caTransform.m41 -= 1; 1608 [transformLayer setTransform:caTransform]; 1609} 1610 1611bool GraphicsLayerCA::removeAnimationFromLayer(AnimatedPropertyID property, const String& keyframesName, int index) 1612{ 1613 PlatformLayer* layer = animatedLayer(property); 1614 1615 String animationName = animationIdentifier(property, keyframesName, index); 1616 1617 if (![layer animationForKey:animationName]) 1618 return false; 1619 1620 [layer removeAnimationForKey:animationName]; 1621 bug7311367Workaround(m_structuralLayer.get(), m_transform); 1622 1623 if (LayerMap* layerCloneMap = animatedLayerClones(property)) { 1624 LayerMap::const_iterator end = layerCloneMap->end(); 1625 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { 1626 // Skip immediate replicas, since they move with the original. 1627 if (m_replicaLayer && isReplicatedRootClone(it->first)) 1628 continue; 1629 1630 CALayer *currLayer = it->second.get(); 1631 [currLayer removeAnimationForKey:animationName]; 1632 } 1633 } 1634 return true; 1635} 1636 1637static void copyAnimationProperties(CAPropertyAnimation* from, CAPropertyAnimation* to) 1638{ 1639 [to setBeginTime:[from beginTime]]; 1640 [to setDuration:[from duration]]; 1641 [to setRepeatCount:[from repeatCount]]; 1642 [to setAutoreverses:[from autoreverses]]; 1643 [to setFillMode:[from fillMode]]; 1644 [to setRemovedOnCompletion:[from isRemovedOnCompletion]]; 1645 [to setAdditive:[from isAdditive]]; 1646 [to setTimingFunction:[from timingFunction]]; 1647 1648#if HAVE_MODERN_QUARTZCORE 1649 [to setValueFunction:[from valueFunction]]; 1650#endif 1651} 1652 1653void GraphicsLayerCA::pauseAnimationOnLayer(AnimatedPropertyID property, const String& keyframesName, int index, double timeOffset) 1654{ 1655 PlatformLayer* layer = animatedLayer(property); 1656 1657 String animationName = animationIdentifier(property, keyframesName, index); 1658 1659 CAAnimation* caAnim = [layer animationForKey:animationName]; 1660 if (!caAnim) 1661 return; 1662 1663 // Animations on the layer are immutable, so we have to clone and modify. 1664 CAPropertyAnimation* pausedAnim = nil; 1665 if ([caAnim isKindOfClass:[CAKeyframeAnimation class]]) { 1666 CAKeyframeAnimation* existingKeyframeAnim = static_cast<CAKeyframeAnimation*>(caAnim); 1667 CAKeyframeAnimation* newAnim = [CAKeyframeAnimation animationWithKeyPath:[existingKeyframeAnim keyPath]]; 1668 copyAnimationProperties(existingKeyframeAnim, newAnim); 1669 [newAnim setValues:[existingKeyframeAnim values]]; 1670 [newAnim setKeyTimes:[existingKeyframeAnim keyTimes]]; 1671 [newAnim setTimingFunctions:[existingKeyframeAnim timingFunctions]]; 1672 pausedAnim = newAnim; 1673 } else if ([caAnim isKindOfClass:[CABasicAnimation class]]) { 1674 CABasicAnimation* existingPropertyAnim = static_cast<CABasicAnimation*>(caAnim); 1675 CABasicAnimation* newAnim = [CABasicAnimation animationWithKeyPath:[existingPropertyAnim keyPath]]; 1676 copyAnimationProperties(existingPropertyAnim, newAnim); 1677 [newAnim setFromValue:[existingPropertyAnim fromValue]]; 1678 [newAnim setToValue:[existingPropertyAnim toValue]]; 1679 pausedAnim = newAnim; 1680 } 1681 1682 // pausedAnim has the beginTime of caAnim already. 1683 [pausedAnim setSpeed:0]; 1684 [pausedAnim setTimeOffset:timeOffset]; 1685 1686 [layer addAnimation:pausedAnim forKey:animationName]; // This will replace the running animation. 1687 1688 // Pause the animations on the clones too. 1689 if (LayerMap* layerCloneMap = animatedLayerClones(property)) { 1690 LayerMap::const_iterator end = layerCloneMap->end(); 1691 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { 1692 // Skip immediate replicas, since they move with the original. 1693 if (m_replicaLayer && isReplicatedRootClone(it->first)) 1694 continue; 1695 CALayer *currLayer = it->second.get(); 1696 [currLayer addAnimation:pausedAnim forKey:animationName]; 1697 } 1698 } 1699} 1700 1701#if ENABLE(3D_CANVAS) 1702void GraphicsLayerCA::setContentsToGraphicsContext3D(const GraphicsContext3D* graphicsContext3D) 1703{ 1704 PlatformGraphicsContext3D context = graphicsContext3D->platformGraphicsContext3D(); 1705 Platform3DObject texture = graphicsContext3D->platformTexture(); 1706 1707 if (context == m_platformGraphicsContext3D && texture == m_platformTexture) 1708 return; 1709 1710 m_platformGraphicsContext3D = context; 1711 m_platformTexture = texture; 1712 1713 noteSublayersChanged(); 1714 1715 BEGIN_BLOCK_OBJC_EXCEPTIONS 1716 1717 if (m_platformGraphicsContext3D != NullPlatformGraphicsContext3D && m_platformTexture != NullPlatform3DObject) { 1718 // create the inner 3d layer 1719 m_contentsLayer.adoptNS([[Canvas3DLayer alloc] initWithContext:static_cast<CGLContextObj>(m_platformGraphicsContext3D) texture:static_cast<GLuint>(m_platformTexture)]); 1720#ifndef NDEBUG 1721 [m_contentsLayer.get() setName:@"3D Layer"]; 1722#endif 1723 [m_contentsLayer.get() setLayerOwner:this]; 1724 } else { 1725 // remove the inner layer 1726 [m_contentsLayer.get() setLayerOwner:0]; 1727 m_contentsLayer = 0; 1728 } 1729 1730 END_BLOCK_OBJC_EXCEPTIONS 1731 1732 noteLayerPropertyChanged(ContentsGraphicsContext3DChanged); 1733 m_contentsLayerPurpose = m_contentsLayer ? ContentsLayerForGraphicsLayer3D : NoContentsLayer; 1734} 1735#endif 1736 1737void GraphicsLayerCA::repaintLayerDirtyRects() 1738{ 1739 if (!m_dirtyRects.size()) 1740 return; 1741 1742 for (size_t i = 0; i < m_dirtyRects.size(); ++i) 1743 [m_layer.get() setNeedsDisplayInRect:m_dirtyRects[i]]; 1744 1745 m_dirtyRects.clear(); 1746} 1747 1748bool GraphicsLayerCA::createAnimationFromKeyframes(const KeyframeValueList& valueList, const Animation* animation, const String& keyframesName, double timeOffset) 1749{ 1750 ASSERT(valueList.property() != AnimatedPropertyWebkitTransform); 1751 1752 BEGIN_BLOCK_OBJC_EXCEPTIONS; 1753 1754 bool isKeyframe = valueList.size() > 2; 1755 bool valuesOK; 1756 1757 bool additive = false; 1758 int animationIndex = 0; 1759 1760 CAPropertyAnimation* caAnimation; 1761 if (isKeyframe) { 1762 CAKeyframeAnimation* keyframeAnim = createKeyframeAnimation(animation, valueList.property(), additive); 1763 valuesOK = setAnimationKeyframes(valueList, animation, keyframeAnim); 1764 caAnimation = keyframeAnim; 1765 } else { 1766 CABasicAnimation* basicAnim = createBasicAnimation(animation, valueList.property(), additive); 1767 valuesOK = setAnimationEndpoints(valueList, animation, basicAnim); 1768 caAnimation = basicAnim; 1769 } 1770 1771 if (!valuesOK) 1772 return false; 1773 1774 m_uncomittedAnimations.append(LayerAnimation(caAnimation, keyframesName, valueList.property(), animationIndex, timeOffset)); 1775 1776 END_BLOCK_OBJC_EXCEPTIONS; 1777 1778 return true; 1779} 1780 1781bool GraphicsLayerCA::createTransformAnimationsFromKeyframes(const KeyframeValueList& valueList, const Animation* animation, const String& keyframesName, double timeOffset, const IntSize& boxSize) 1782{ 1783 ASSERT(valueList.property() == AnimatedPropertyWebkitTransform); 1784 1785 TransformOperationList functionList; 1786 bool listsMatch, hasBigRotation; 1787 fetchTransformOperationList(valueList, functionList, listsMatch, hasBigRotation); 1788 1789 // We need to fall back to software animation if we don't have setValueFunction:, and 1790 // we would need to animate each incoming transform function separately. This is the 1791 // case if we have a rotation >= 180 or we have more than one transform function. 1792 if ((hasBigRotation || functionList.size() > 1) && !caValueFunctionSupported()) 1793 return false; 1794 1795 bool validMatrices = true; 1796 1797 BEGIN_BLOCK_OBJC_EXCEPTIONS; 1798 1799 // If functionLists don't match we do a matrix animation, otherwise we do a component hardware animation. 1800 // Also, we can't do component animation unless we have valueFunction, so we need to do matrix animation 1801 // if that's not true as well. 1802 bool isMatrixAnimation = !listsMatch || !caValueFunctionSupported(); 1803 1804 size_t numAnimations = isMatrixAnimation ? 1 : functionList.size(); 1805 bool isKeyframe = valueList.size() > 2; 1806 1807 // Iterate through the transform functions, sending an animation for each one. 1808 for (size_t animationIndex = 0; animationIndex < numAnimations; ++animationIndex) { 1809 TransformOperation::OperationType transformOp = isMatrixAnimation ? TransformOperation::MATRIX_3D : functionList[animationIndex]; 1810 CAPropertyAnimation* caAnimation; 1811 1812 // CA applies animations in reverse order (<rdar://problem/7095638>) so we need the last one we add (per property) 1813 // to be non-additive. 1814 bool additive = animationIndex < (numAnimations - 1); 1815 if (isKeyframe) { 1816 CAKeyframeAnimation* keyframeAnim = createKeyframeAnimation(animation, valueList.property(), additive); 1817 validMatrices = setTransformAnimationKeyframes(valueList, animation, keyframeAnim, animationIndex, transformOp, isMatrixAnimation, boxSize); 1818 caAnimation = keyframeAnim; 1819 } else { 1820 CABasicAnimation* basicAnim = createBasicAnimation(animation, valueList.property(), additive); 1821 validMatrices = setTransformAnimationEndpoints(valueList, animation, basicAnim, animationIndex, transformOp, isMatrixAnimation, boxSize); 1822 caAnimation = basicAnim; 1823 } 1824 1825 if (!validMatrices) 1826 break; 1827 1828 m_uncomittedAnimations.append(LayerAnimation(caAnimation, keyframesName, valueList.property(), animationIndex, timeOffset)); 1829 } 1830 1831 END_BLOCK_OBJC_EXCEPTIONS; 1832 1833 return validMatrices; 1834} 1835 1836CABasicAnimation* GraphicsLayerCA::createBasicAnimation(const Animation* anim, AnimatedPropertyID property, bool additive) 1837{ 1838 CABasicAnimation* basicAnim = [CABasicAnimation animationWithKeyPath:propertyIdToString(property)]; 1839 setupAnimation(basicAnim, anim, additive); 1840 return basicAnim; 1841} 1842 1843CAKeyframeAnimation* GraphicsLayerCA::createKeyframeAnimation(const Animation* anim, AnimatedPropertyID property, bool additive) 1844{ 1845 CAKeyframeAnimation* keyframeAnim = [CAKeyframeAnimation animationWithKeyPath:propertyIdToString(property)]; 1846 setupAnimation(keyframeAnim, anim, additive); 1847 return keyframeAnim; 1848} 1849 1850void GraphicsLayerCA::setupAnimation(CAPropertyAnimation* propertyAnim, const Animation* anim, bool additive) 1851{ 1852 double duration = anim->duration(); 1853 if (duration <= 0) 1854 duration = cAnimationAlmostZeroDuration; 1855 1856 float repeatCount = anim->iterationCount(); 1857 if (repeatCount == Animation::IterationCountInfinite) 1858 repeatCount = FLT_MAX; 1859 else if (anim->direction() == Animation::AnimationDirectionAlternate) 1860 repeatCount /= 2; 1861 1862 [propertyAnim setDuration:duration]; 1863 [propertyAnim setRepeatCount:repeatCount]; 1864 [propertyAnim setAutoreverses:anim->direction()]; 1865 [propertyAnim setRemovedOnCompletion:NO]; 1866 [propertyAnim setAdditive:additive]; 1867 [propertyAnim setFillMode:@"extended"]; 1868 1869 [propertyAnim setDelegate:m_animationDelegate.get()]; 1870} 1871 1872CAMediaTimingFunction* GraphicsLayerCA::timingFunctionForAnimationValue(const AnimationValue* animValue, const Animation* anim) 1873{ 1874 const TimingFunction* tf = 0; 1875 if (animValue->timingFunction()) 1876 tf = animValue->timingFunction(); 1877 else if (anim->isTimingFunctionSet()) 1878 tf = &anim->timingFunction(); 1879 1880 return getCAMediaTimingFunction(tf ? *tf : TimingFunction()); 1881} 1882 1883bool GraphicsLayerCA::setAnimationEndpoints(const KeyframeValueList& valueList, const Animation* anim, CABasicAnimation* basicAnim) 1884{ 1885 id fromValue = nil; 1886 id toValue = nil; 1887 1888 switch (valueList.property()) { 1889 case AnimatedPropertyOpacity: { 1890 const FloatAnimationValue* startVal = static_cast<const FloatAnimationValue*>(valueList.at(0)); 1891 const FloatAnimationValue* endVal = static_cast<const FloatAnimationValue*>(valueList.at(1)); 1892 fromValue = [NSNumber numberWithFloat:startVal->value()]; 1893 toValue = [NSNumber numberWithFloat:endVal->value()]; 1894 break; 1895 } 1896 default: 1897 ASSERT_NOT_REACHED(); // we don't animate color yet 1898 break; 1899 } 1900 1901 // This codepath is used for 2-keyframe animations, so we still need to look in the start 1902 // for a timing function. 1903 CAMediaTimingFunction* timingFunction = timingFunctionForAnimationValue(valueList.at(0), anim); 1904 [basicAnim setTimingFunction:timingFunction]; 1905 1906 [basicAnim setFromValue:fromValue]; 1907 [basicAnim setToValue:toValue]; 1908 1909 return true; 1910} 1911 1912bool GraphicsLayerCA::setAnimationKeyframes(const KeyframeValueList& valueList, const Animation* anim, CAKeyframeAnimation* keyframeAnim) 1913{ 1914 RetainPtr<NSMutableArray> keyTimes(AdoptNS, [[NSMutableArray alloc] init]); 1915 RetainPtr<NSMutableArray> values(AdoptNS, [[NSMutableArray alloc] init]); 1916 RetainPtr<NSMutableArray> timingFunctions(AdoptNS, [[NSMutableArray alloc] init]); 1917 1918 for (unsigned i = 0; i < valueList.size(); ++i) { 1919 const AnimationValue* curValue = valueList.at(i); 1920 [keyTimes.get() addObject:[NSNumber numberWithFloat:curValue->keyTime()]]; 1921 1922 switch (valueList.property()) { 1923 case AnimatedPropertyOpacity: { 1924 const FloatAnimationValue* floatValue = static_cast<const FloatAnimationValue*>(curValue); 1925 [values.get() addObject:[NSNumber numberWithFloat:floatValue->value()]]; 1926 break; 1927 } 1928 default: 1929 ASSERT_NOT_REACHED(); // we don't animate color yet 1930 break; 1931 } 1932 1933 CAMediaTimingFunction* timingFunction = timingFunctionForAnimationValue(curValue, anim); 1934 [timingFunctions.get() addObject:timingFunction]; 1935 } 1936 1937 // We toss the last tfArray value because it has to one shorter than the others. 1938 [timingFunctions.get() removeLastObject]; 1939 1940 [keyframeAnim setKeyTimes:keyTimes.get()]; 1941 [keyframeAnim setValues:values.get()]; 1942 [keyframeAnim setTimingFunctions:timingFunctions.get()]; 1943 1944 return true; 1945} 1946 1947bool GraphicsLayerCA::setTransformAnimationEndpoints(const KeyframeValueList& valueList, const Animation* anim, CABasicAnimation* basicAnim, int functionIndex, TransformOperation::OperationType transformOp, bool isMatrixAnimation, const IntSize& boxSize) 1948{ 1949 id fromValue; 1950 id toValue; 1951 1952 ASSERT(valueList.size() == 2); 1953 const TransformAnimationValue* startValue = static_cast<const TransformAnimationValue*>(valueList.at(0)); 1954 const TransformAnimationValue* endValue = static_cast<const TransformAnimationValue*>(valueList.at(1)); 1955 1956 if (isMatrixAnimation) { 1957 TransformationMatrix fromTransform, toTransform; 1958 startValue->value()->apply(boxSize, fromTransform); 1959 endValue->value()->apply(boxSize, toTransform); 1960 1961 // If any matrix is singular, CA won't animate it correctly. So fall back to software animation 1962 if (!fromTransform.isInvertible() || !toTransform.isInvertible()) 1963 return false; 1964 1965 CATransform3D caTransform; 1966 copyTransform(caTransform, fromTransform); 1967 fromValue = [NSValue valueWithCATransform3D:caTransform]; 1968 1969 copyTransform(caTransform, toTransform); 1970 toValue = [NSValue valueWithCATransform3D:caTransform]; 1971 } else { 1972 fromValue = getTransformFunctionValue(startValue->value()->at(functionIndex), transformOp, boxSize); 1973 toValue = getTransformFunctionValue(endValue->value()->at(functionIndex), transformOp, boxSize); 1974 } 1975 1976 // This codepath is used for 2-keyframe animations, so we still need to look in the start 1977 // for a timing function. 1978 CAMediaTimingFunction* timingFunction = timingFunctionForAnimationValue(valueList.at(0), anim); 1979 [basicAnim setTimingFunction:timingFunction]; 1980 1981 [basicAnim setFromValue:fromValue]; 1982 [basicAnim setToValue:toValue]; 1983 1984#if HAVE_MODERN_QUARTZCORE 1985 if (NSString* valueFunctionName = getValueFunctionNameForTransformOperation(transformOp)) 1986 [basicAnim setValueFunction:[CAValueFunction functionWithName:valueFunctionName]]; 1987#endif 1988 1989 return true; 1990} 1991 1992bool GraphicsLayerCA::setTransformAnimationKeyframes(const KeyframeValueList& valueList, const Animation* animation, CAKeyframeAnimation* keyframeAnim, int functionIndex, TransformOperation::OperationType transformOpType, bool isMatrixAnimation, const IntSize& boxSize) 1993{ 1994 RetainPtr<NSMutableArray> keyTimes(AdoptNS, [[NSMutableArray alloc] init]); 1995 RetainPtr<NSMutableArray> values(AdoptNS, [[NSMutableArray alloc] init]); 1996 RetainPtr<NSMutableArray> timingFunctions(AdoptNS, [[NSMutableArray alloc] init]); 1997 1998 for (unsigned i = 0; i < valueList.size(); ++i) { 1999 const TransformAnimationValue* curValue = static_cast<const TransformAnimationValue*>(valueList.at(i)); 2000 [keyTimes.get() addObject:[NSNumber numberWithFloat:curValue->keyTime()]]; 2001 2002 if (isMatrixAnimation) { 2003 TransformationMatrix transform; 2004 curValue->value()->apply(boxSize, transform); 2005 2006 // If any matrix is singular, CA won't animate it correctly. So fall back to software animation 2007 if (!transform.isInvertible()) 2008 return false; 2009 2010 CATransform3D caTransform; 2011 copyTransform(caTransform, transform); 2012 [values.get() addObject:[NSValue valueWithCATransform3D:caTransform]]; 2013 } else { 2014 const TransformOperation* transformOp = curValue->value()->at(functionIndex); 2015 [values.get() addObject:getTransformFunctionValue(transformOp, transformOpType, boxSize)]; 2016 } 2017 2018 CAMediaTimingFunction* timingFunction = timingFunctionForAnimationValue(curValue, animation); 2019 [timingFunctions.get() addObject:timingFunction]; 2020 } 2021 2022 // We toss the last tfArray value because it has to one shorter than the others. 2023 [timingFunctions.get() removeLastObject]; 2024 2025 [keyframeAnim setKeyTimes:keyTimes.get()]; 2026 [keyframeAnim setValues:values.get()]; 2027 [keyframeAnim setTimingFunctions:timingFunctions.get()]; 2028 2029#if HAVE_MODERN_QUARTZCORE 2030 if (NSString* valueFunctionName = getValueFunctionNameForTransformOperation(transformOpType)) 2031 [keyframeAnim setValueFunction:[CAValueFunction functionWithName:valueFunctionName]]; 2032#endif 2033 return true; 2034} 2035 2036void GraphicsLayerCA::suspendAnimations(double time) 2037{ 2038 double t = currentTimeToMediaTime(time ? time : currentTime()); 2039 [primaryLayer() setSpeed:0]; 2040 [primaryLayer() setTimeOffset:t]; 2041 2042 // Suspend the animations on the clones too. 2043 if (LayerMap* layerCloneMap = primaryLayerClones()) { 2044 LayerMap::const_iterator end = layerCloneMap->end(); 2045 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { 2046 CALayer *currLayer = it->second.get(); 2047 [currLayer setSpeed:0 ]; 2048 [currLayer setTimeOffset:t]; 2049 } 2050 } 2051} 2052 2053void GraphicsLayerCA::resumeAnimations() 2054{ 2055 [primaryLayer() setSpeed:1]; 2056 [primaryLayer() setTimeOffset:0]; 2057 2058 // Resume the animations on the clones too. 2059 if (LayerMap* layerCloneMap = primaryLayerClones()) { 2060 LayerMap::const_iterator end = layerCloneMap->end(); 2061 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { 2062 CALayer *currLayer = it->second.get(); 2063 [currLayer setSpeed:1]; 2064 [currLayer setTimeOffset:0]; 2065 } 2066 } 2067} 2068 2069CALayer* GraphicsLayerCA::hostLayerForSublayers() const 2070{ 2071 return m_structuralLayer.get() ? m_structuralLayer.get() : m_layer.get(); 2072} 2073 2074CALayer* GraphicsLayerCA::layerForSuperlayer() const 2075{ 2076 return m_structuralLayer ? m_structuralLayer.get() : m_layer.get(); 2077} 2078 2079CALayer* GraphicsLayerCA::animatedLayer(AnimatedPropertyID property) const 2080{ 2081 return (property == AnimatedPropertyBackgroundColor) ? m_contentsLayer.get() : primaryLayer(); 2082} 2083 2084GraphicsLayerCA::LayerMap* GraphicsLayerCA::animatedLayerClones(AnimatedPropertyID property) const 2085{ 2086 return (property == AnimatedPropertyBackgroundColor) ? m_contentsLayerClones.get() : primaryLayerClones(); 2087} 2088 2089PlatformLayer* GraphicsLayerCA::platformLayer() const 2090{ 2091 return primaryLayer(); 2092} 2093 2094void GraphicsLayerCA::setDebugBackgroundColor(const Color& color) 2095{ 2096 BEGIN_BLOCK_OBJC_EXCEPTIONS 2097 2098 if (color.isValid()) 2099 setLayerBackgroundColor(m_layer.get(), color); 2100 else 2101 clearLayerBackgroundColor(m_layer.get()); 2102 2103 END_BLOCK_OBJC_EXCEPTIONS 2104} 2105 2106void GraphicsLayerCA::setDebugBorder(const Color& color, float borderWidth) 2107{ 2108 BEGIN_BLOCK_OBJC_EXCEPTIONS 2109 2110 if (color.isValid()) { 2111 setLayerBorderColor(m_layer.get(), color); 2112 [m_layer.get() setBorderWidth:borderWidth]; 2113 } else { 2114 clearBorderColor(m_layer.get()); 2115 [m_layer.get() setBorderWidth:0]; 2116 } 2117 2118 END_BLOCK_OBJC_EXCEPTIONS 2119} 2120 2121bool GraphicsLayerCA::requiresTiledLayer(const FloatSize& size) const 2122{ 2123 if (!m_drawsContent) 2124 return false; 2125 2126 // FIXME: catch zero-size height or width here (or earlier)? 2127 return size.width() > cMaxPixelDimension || size.height() > cMaxPixelDimension; 2128} 2129 2130void GraphicsLayerCA::swapFromOrToTiledLayer(bool useTiledLayer) 2131{ 2132 if (useTiledLayer == m_usingTiledLayer) 2133 return; 2134 2135 CGSize tileSize = CGSizeMake(cTiledLayerTileSize, cTiledLayerTileSize); 2136 2137 RetainPtr<CALayer> oldLayer = m_layer.get(); 2138 2139 Class layerClass = useTiledLayer ? [WebTiledLayer self] : [WebLayer self]; 2140 m_layer.adoptNS([[layerClass alloc] init]); 2141 2142 m_usingTiledLayer = useTiledLayer; 2143 2144 if (useTiledLayer) { 2145 WebTiledLayer* tiledLayer = (WebTiledLayer*)m_layer.get(); 2146 [tiledLayer setTileSize:tileSize]; 2147 [tiledLayer setLevelsOfDetail:1]; 2148 [tiledLayer setLevelsOfDetailBias:0]; 2149 2150 if (GraphicsLayer::compositingCoordinatesOrientation() == GraphicsLayer::CompositingCoordinatesBottomUp) 2151 [tiledLayer setContentsGravity:@"bottomLeft"]; 2152 else 2153 [tiledLayer setContentsGravity:@"topLeft"]; 2154 2155#if !HAVE_MODERN_QUARTZCORE 2156 // Tiled layer has issues with flipped coordinates. 2157 setContentsOrientation(CompositingCoordinatesTopDown); 2158#endif 2159 } else { 2160#if !HAVE_MODERN_QUARTZCORE 2161 setContentsOrientation(defaultContentsOrientation()); 2162#endif 2163 } 2164 2165 [m_layer.get() setLayerOwner:this]; 2166 safeSetSublayers(m_layer.get(), [oldLayer.get() sublayers]); 2167 2168 [[oldLayer.get() superlayer] replaceSublayer:oldLayer.get() with:m_layer.get()]; 2169 2170 updateContentsTransform(); 2171 2172 updateLayerPosition(); 2173 updateLayerSize(); 2174 updateAnchorPoint(); 2175 updateTransform(); 2176 updateChildrenTransform(); 2177 updateMasksToBounds(); 2178 updateContentsOpaque(); 2179 updateBackfaceVisibility(); 2180 updateLayerBackgroundColor(); 2181 2182 updateOpacityOnLayer(); 2183 2184#ifndef NDEBUG 2185 String name = String::format("CALayer(%p) GraphicsLayer(%p) ", m_layer.get(), this) + m_name; 2186 [m_layer.get() setName:name]; 2187#endif 2188 2189 // move over animations 2190 moveOrCopyAnimationsForProperty(Move, AnimatedPropertyWebkitTransform, oldLayer.get(), m_layer.get()); 2191 moveOrCopyAnimationsForProperty(Move, AnimatedPropertyOpacity, oldLayer.get(), m_layer.get()); 2192 moveOrCopyAnimationsForProperty(Move, AnimatedPropertyBackgroundColor, oldLayer.get(), m_layer.get()); 2193 2194 // need to tell new layer to draw itself 2195 setNeedsDisplay(); 2196 2197 updateDebugIndicators(); 2198} 2199 2200GraphicsLayer::CompositingCoordinatesOrientation GraphicsLayerCA::defaultContentsOrientation() const 2201{ 2202#if !HAVE_MODERN_QUARTZCORE 2203 // Older QuartzCore does not support -geometryFlipped, so we manually flip the root 2204 // layer geometry, and then flip the contents of each layer back so that the CTM for CG 2205 // is unflipped, allowing it to do the correct font auto-hinting. 2206 return CompositingCoordinatesBottomUp; 2207#else 2208 return CompositingCoordinatesTopDown; 2209#endif 2210} 2211 2212void GraphicsLayerCA::updateContentsTransform() 2213{ 2214#if !HAVE_MODERN_QUARTZCORE 2215 if (contentsOrientation() == CompositingCoordinatesBottomUp) { 2216 CGAffineTransform contentsTransform = CGAffineTransformMakeScale(1, -1); 2217 contentsTransform = CGAffineTransformTranslate(contentsTransform, 0, -[m_layer.get() bounds].size.height); 2218 [m_layer.get() setContentsTransform:contentsTransform]; 2219 } 2220#else 2221 ASSERT(contentsOrientation() == CompositingCoordinatesTopDown); 2222#endif 2223} 2224 2225void GraphicsLayerCA::setupContentsLayer(CALayer* contentsLayer) 2226{ 2227 // Turn off implicit animations on the inner layer. 2228 [contentsLayer setStyle:[NSDictionary dictionaryWithObject:nullActionsDictionary() forKey:@"actions"]]; 2229 2230 if (defaultContentsOrientation() == CompositingCoordinatesBottomUp) { 2231 CATransform3D flipper = { 2232 1.0f, 0.0f, 0.0f, 0.0f, 2233 0.0f, -1.0f, 0.0f, 0.0f, 2234 0.0f, 0.0f, 1.0f, 0.0f, 2235 0.0f, 0.0f, 0.0f, 1.0f}; 2236 [contentsLayer setTransform:flipper]; 2237 [contentsLayer setAnchorPoint:CGPointMake(0.0f, 1.0f)]; 2238 } else 2239 [contentsLayer setAnchorPoint:CGPointZero]; 2240 2241 if (showDebugBorders()) { 2242 setLayerBorderColor(contentsLayer, Color(0, 0, 128, 180)); 2243 [contentsLayer setBorderWidth:1.0f]; 2244 } 2245} 2246 2247CALayer *GraphicsLayerCA::findOrMakeClone(CloneID cloneID, CALayer *sourceLayer, LayerMap* clones, CloneLevel cloneLevel) 2248{ 2249 if (!sourceLayer) 2250 return 0; 2251 2252 CALayer *resultLayer; 2253 2254 // Add with a dummy value to get an iterator for the insertion position, and a boolean that tells 2255 // us whether there's an item there. This technique avoids two hash lookups. 2256 RetainPtr<CALayer> dummy; 2257 pair<LayerMap::iterator, bool> addResult = clones->add(cloneID, dummy); 2258 if (!addResult.second) { 2259 // Value was not added, so it exists already. 2260 resultLayer = addResult.first->second.get(); 2261 } else { 2262 resultLayer = cloneLayer(sourceLayer, cloneLevel); 2263#ifndef NDEBUG 2264 [resultLayer setName:[NSString stringWithFormat:@"Clone %d of layer %@", cloneID[0U], sourceLayer]]; 2265#endif 2266 addResult.first->second = resultLayer; 2267 } 2268 2269 return resultLayer; 2270} 2271 2272void GraphicsLayerCA::ensureCloneLayers(CloneID cloneID, CALayer *& primaryLayer, CALayer *& structuralLayer, CALayer *& contentsLayer, CloneLevel cloneLevel) 2273{ 2274 structuralLayer = nil; 2275 contentsLayer = nil; 2276 2277 if (!m_layerClones) 2278 m_layerClones = new LayerMap; 2279 2280 if (!m_structuralLayerClones && m_structuralLayer) 2281 m_structuralLayerClones = new LayerMap; 2282 2283 if (!m_contentsLayerClones && m_contentsLayer) 2284 m_contentsLayerClones = new LayerMap; 2285 2286 primaryLayer = findOrMakeClone(cloneID, m_layer.get(), m_layerClones.get(), cloneLevel); 2287 structuralLayer = findOrMakeClone(cloneID, m_structuralLayer.get(), m_structuralLayerClones.get(), cloneLevel); 2288 contentsLayer = findOrMakeClone(cloneID, m_contentsLayer.get(), m_contentsLayerClones.get(), cloneLevel); 2289} 2290 2291void GraphicsLayerCA::removeCloneLayers() 2292{ 2293 m_layerClones = 0; 2294 m_structuralLayerClones = 0; 2295 m_contentsLayerClones = 0; 2296} 2297 2298FloatPoint GraphicsLayerCA::positionForCloneRootLayer() const 2299{ 2300 // This can get called during a sync when we've just removed the m_replicaLayer. 2301 if (!m_replicaLayer) 2302 return FloatPoint(); 2303 2304 FloatPoint replicaPosition = m_replicaLayer->replicatedLayerPosition(); 2305 return FloatPoint(replicaPosition.x() + m_anchorPoint.x() * m_size.width(), 2306 replicaPosition.y() + m_anchorPoint.y() * m_size.height()); 2307} 2308 2309void GraphicsLayerCA::propagateLayerChangeToReplicas() 2310{ 2311 for (GraphicsLayer* currLayer = this; currLayer; currLayer = currLayer->parent()) { 2312 GraphicsLayerCA* currLayerCA = static_cast<GraphicsLayerCA*>(currLayer); 2313 if (!currLayerCA->hasCloneLayers()) 2314 break; 2315 2316 if (currLayerCA->replicaLayer()) 2317 static_cast<GraphicsLayerCA*>(currLayerCA->replicaLayer())->noteLayerPropertyChanged(ReplicatedLayerChanged); 2318 } 2319} 2320 2321CALayer *GraphicsLayerCA::fetchCloneLayers(GraphicsLayer* replicaRoot, ReplicaState& replicaState, CloneLevel cloneLevel) 2322{ 2323 CALayer *primaryLayer; 2324 CALayer *structuralLayer; 2325 CALayer *contentsLayer; 2326 ensureCloneLayers(replicaState.cloneID(), primaryLayer, structuralLayer, contentsLayer, cloneLevel); 2327 2328 if (m_maskLayer) { 2329 CALayer *maskClone = static_cast<GraphicsLayerCA*>(m_maskLayer)->fetchCloneLayers(replicaRoot, replicaState, IntermediateCloneLevel); 2330 [primaryLayer setMask:maskClone]; 2331 } 2332 2333 if (m_replicatedLayer) { 2334 // We are a replica being asked for clones of our layers. 2335 CALayer *replicaRoot = replicatedLayerRoot(replicaState); 2336 if (!replicaRoot) 2337 return nil; 2338 2339 if (structuralLayer) { 2340 [structuralLayer insertSublayer:replicaRoot atIndex:0]; 2341 return structuralLayer; 2342 } 2343 2344 [primaryLayer insertSublayer:replicaRoot atIndex:0]; 2345 return primaryLayer; 2346 } 2347 2348 const Vector<GraphicsLayer*>& childLayers = children(); 2349 NSMutableArray* clonalSublayers = nil; 2350 2351 CALayer *replicaLayer = nil; 2352 if (m_replicaLayer && m_replicaLayer != replicaRoot) { 2353 // We have nested replicas. Ask the replica layer for a clone of its contents. 2354 replicaState.setBranchType(ReplicaState::ReplicaBranch); 2355 replicaLayer = static_cast<GraphicsLayerCA*>(m_replicaLayer)->fetchCloneLayers(replicaRoot, replicaState, RootCloneLevel); 2356 replicaState.setBranchType(ReplicaState::ChildBranch); 2357 } 2358 2359 if (replicaLayer || structuralLayer || contentsLayer || childLayers.size() > 0) { 2360 clonalSublayers = [[NSMutableArray alloc] init]; 2361 2362 if (structuralLayer) { 2363 // Replicas render behind the actual layer content. 2364 if (replicaLayer) 2365 [clonalSublayers addObject:replicaLayer]; 2366 2367 // Add the primary layer next. Even if we have negative z-order children, the primary layer always comes behind. 2368 [clonalSublayers addObject:primaryLayer]; 2369 } else if (contentsLayer) { 2370 // FIXME: add the contents layer in the correct order with negative z-order children. 2371 // This does not cause visible rendering issues because currently contents layers are only used 2372 // for replaced elements that don't have children. 2373 [clonalSublayers addObject:contentsLayer]; 2374 } 2375 2376 replicaState.push(ReplicaState::ChildBranch); 2377 2378 size_t numChildren = childLayers.size(); 2379 for (size_t i = 0; i < numChildren; ++i) { 2380 GraphicsLayerCA* curChild = static_cast<GraphicsLayerCA*>(childLayers[i]); 2381 2382 CALayer *childLayer = curChild->fetchCloneLayers(replicaRoot, replicaState, IntermediateCloneLevel); 2383 if (childLayer) 2384 [clonalSublayers addObject:childLayer]; 2385 } 2386 2387 replicaState.pop(); 2388 2389 [clonalSublayers makeObjectsPerformSelector:@selector(removeFromSuperlayer)]; 2390 } 2391 2392 CALayer *result; 2393 if (structuralLayer) { 2394 [structuralLayer setSublayers:clonalSublayers]; 2395 2396 if (contentsLayer) { 2397 // If we have a transform layer, then the contents layer is parented in the 2398 // primary layer (which is itself a child of the transform layer). 2399 [primaryLayer setSublayers:nil]; 2400 [primaryLayer addSublayer:contentsLayer]; 2401 } 2402 2403 result = structuralLayer; 2404 } else { 2405 [primaryLayer setSublayers:clonalSublayers]; 2406 result = primaryLayer; 2407 } 2408 2409 [clonalSublayers release]; 2410 return result; 2411} 2412 2413CALayer *GraphicsLayerCA::cloneLayer(CALayer *layer, CloneLevel cloneLevel) 2414{ 2415 static Class transformLayerClass = NSClassFromString(@"CATransformLayer"); 2416 CALayer *newLayer = nil; 2417 if ([layer isKindOfClass:transformLayerClass]) 2418 newLayer = [transformLayerClass layer]; 2419 else 2420 newLayer = [CALayer layer]; 2421 2422 [newLayer setStyle:[NSDictionary dictionaryWithObject:nullActionsDictionary() forKey:@"actions"]]; 2423 2424 [newLayer setPosition:[layer position]]; 2425 [newLayer setBounds:[layer bounds]]; 2426 [newLayer setAnchorPoint:[layer anchorPoint]]; 2427#if HAVE_MODERN_QUARTZCORE 2428 [newLayer setAnchorPointZ:[layer anchorPointZ]]; 2429#endif 2430 [newLayer setTransform:[layer transform]]; 2431 [newLayer setSublayerTransform:[layer sublayerTransform]]; 2432 [newLayer setContents:[layer contents]]; 2433 [newLayer setMasksToBounds:[layer masksToBounds]]; 2434 [newLayer setDoubleSided:[layer isDoubleSided]]; 2435 [newLayer setOpaque:[layer isOpaque]]; 2436 [newLayer setBackgroundColor:[layer backgroundColor]]; 2437 2438 if (cloneLevel == IntermediateCloneLevel) { 2439 [newLayer setOpacity:[layer opacity]]; 2440 moveOrCopyAnimationsForProperty(Copy, AnimatedPropertyWebkitTransform, layer, newLayer); 2441 moveOrCopyAnimationsForProperty(Copy, AnimatedPropertyOpacity, layer, newLayer); 2442 } 2443 2444 if (showDebugBorders()) { 2445 setLayerBorderColor(newLayer, Color(255, 122, 251)); 2446 [newLayer setBorderWidth:2]; 2447 } 2448 2449 return newLayer; 2450} 2451 2452void GraphicsLayerCA::setOpacityInternal(float accumulatedOpacity) 2453{ 2454 LayerMap* layerCloneMap = 0; 2455 2456 if (preserves3D()) { 2457 [m_layer.get() setOpacity:accumulatedOpacity]; 2458 layerCloneMap = m_layerClones.get(); 2459 } else { 2460 [primaryLayer() setOpacity:accumulatedOpacity]; 2461 layerCloneMap = primaryLayerClones(); 2462 } 2463 2464 if (layerCloneMap) { 2465 LayerMap::const_iterator end = layerCloneMap->end(); 2466 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { 2467 if (m_replicaLayer && isReplicatedRootClone(it->first)) 2468 continue; 2469 CALayer *currLayer = it->second.get(); 2470 [currLayer setOpacity:m_opacity]; 2471 } 2472 } 2473} 2474 2475void GraphicsLayerCA::updateOpacityOnLayer() 2476{ 2477#if !HAVE_MODERN_QUARTZCORE 2478 // Distribute opacity either to our own layer or to our children. We pass in the 2479 // contribution from our parent(s). 2480 distributeOpacity(parent() ? parent()->accumulatedOpacity() : 1); 2481#else 2482 [primaryLayer() setOpacity:m_opacity]; 2483 2484 if (LayerMap* layerCloneMap = primaryLayerClones()) { 2485 LayerMap::const_iterator end = layerCloneMap->end(); 2486 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { 2487 if (m_replicaLayer && isReplicatedRootClone(it->first)) 2488 continue; 2489 2490 CALayer *currLayer = it->second.get(); 2491 [currLayer setOpacity:m_opacity]; 2492 } 2493 2494 } 2495#endif 2496} 2497 2498void GraphicsLayerCA::noteSublayersChanged() 2499{ 2500 noteLayerPropertyChanged(ChildrenChanged); 2501 propagateLayerChangeToReplicas(); 2502} 2503 2504void GraphicsLayerCA::noteLayerPropertyChanged(LayerChangeFlags flags) 2505{ 2506 if (!m_uncommittedChanges && m_client) 2507 m_client->notifySyncRequired(this); 2508 2509 m_uncommittedChanges |= flags; 2510} 2511 2512#if ENABLE(3D_CANVAS) 2513void GraphicsLayerCA::setGraphicsContext3DNeedsDisplay() 2514{ 2515 if (m_contentsLayerPurpose == ContentsLayerForGraphicsLayer3D) 2516 [m_contentsLayer.get() setNeedsDisplay]; 2517} 2518#endif 2519 2520} // namespace WebCore 2521 2522#endif // USE(ACCELERATED_COMPOSITING) 2523