Home | History | Annotate | Download | only in mac
      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 
     56 using namespace std;
     57 
     58 #define HAVE_MODERN_QUARTZCORE (!defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD))
     59 
     60 namespace 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.
     65 static 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.
     70 static 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.
     74 static 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).
     78 static CFTimeInterval currentTimeToMediaTime(double t)
     79 {
     80     return CACurrentMediaTime() + t - WTF::currentTime();
     81 }
     82 
     83 static 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 
    127 namespace WebCore {
    128 
    129 static 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 
    149 static 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
    204 static 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 
    238 static 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 
    254 static 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
    271 static TransformationMatrix flipTransform()
    272 {
    273     TransformationMatrix flipper;
    274     flipper.flipY();
    275     return flipper;
    276 }
    277 #endif
    278 
    279 static 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 
    291 static void setLayerBorderColor(PlatformLayer* layer, const Color& color)
    292 {
    293     CGColorRef borderColor = createCGColor(color);
    294     [layer setBorderColor:borderColor];
    295     CGColorRelease(borderColor);
    296 }
    297 
    298 static void clearBorderColor(PlatformLayer* layer)
    299 {
    300     [layer setBorderColor:nil];
    301 }
    302 
    303 static void setLayerBackgroundColor(PlatformLayer* layer, const Color& color)
    304 {
    305     CGColorRef bgColor = createCGColor(color);
    306     [layer setBackgroundColor:bgColor];
    307     CGColorRelease(bgColor);
    308 }
    309 
    310 static void clearLayerBackgroundColor(PlatformLayer* layer)
    311 {
    312     [layer setBackgroundColor:0];
    313 }
    314 
    315 static 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 
    327 static bool caValueFunctionSupported()
    328 {
    329     static bool sHaveValueFunction = [CAPropertyAnimation instancesRespondToSelector:@selector(setValueFunction:)];
    330     return sHaveValueFunction;
    331 }
    332 
    333 static bool forceSoftwareAnimation()
    334 {
    335     static bool forceSoftwareAnimation = [[NSUserDefaults standardUserDefaults] boolForKey:@"WebCoreForceSoftwareAnimation"];
    336     return forceSoftwareAnimation;
    337 }
    338 
    339 GraphicsLayer::CompositingCoordinatesOrientation GraphicsLayer::compositingCoordinatesOrientation()
    340 {
    341     return CompositingCoordinatesBottomUp;
    342 }
    343 
    344 static 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 
    363 PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerClient* client)
    364 {
    365     return new GraphicsLayerCA(client);
    366 }
    367 
    368 GraphicsLayerCA::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 
    394 GraphicsLayerCA::~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 
    422 void 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 
    429 NativeLayer GraphicsLayerCA::nativeLayer() const
    430 {
    431     return m_layer.get();
    432 }
    433 
    434 bool GraphicsLayerCA::setChildren(const Vector<GraphicsLayer*>& children)
    435 {
    436     bool childrenChanged = GraphicsLayer::setChildren(children);
    437     if (childrenChanged)
    438         noteSublayersChanged();
    439 
    440     return childrenChanged;
    441 }
    442 
    443 void GraphicsLayerCA::addChild(GraphicsLayer* childLayer)
    444 {
    445     GraphicsLayer::addChild(childLayer);
    446     noteSublayersChanged();
    447 }
    448 
    449 void GraphicsLayerCA::addChildAtIndex(GraphicsLayer* childLayer, int index)
    450 {
    451     GraphicsLayer::addChildAtIndex(childLayer, index);
    452     noteSublayersChanged();
    453 }
    454 
    455 void GraphicsLayerCA::addChildBelow(GraphicsLayer* childLayer, GraphicsLayer* sibling)
    456 {
    457     GraphicsLayer::addChildBelow(childLayer, sibling);
    458     noteSublayersChanged();
    459 }
    460 
    461 void GraphicsLayerCA::addChildAbove(GraphicsLayer* childLayer, GraphicsLayer* sibling)
    462 {
    463     GraphicsLayer::addChildAbove(childLayer, sibling);
    464     noteSublayersChanged();
    465 }
    466 
    467 bool GraphicsLayerCA::replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild)
    468 {
    469     if (GraphicsLayer::replaceChild(oldChild, newChild)) {
    470         noteSublayersChanged();
    471         return true;
    472     }
    473     return false;
    474 }
    475 
    476 void GraphicsLayerCA::removeFromParent()
    477 {
    478     if (m_parent)
    479         static_cast<GraphicsLayerCA*>(m_parent)->noteSublayersChanged();
    480     GraphicsLayer::removeFromParent();
    481 }
    482 
    483 void 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 
    497 void GraphicsLayerCA::setReplicatedLayer(GraphicsLayer* layer)
    498 {
    499     if (layer == m_replicatedLayer)
    500         return;
    501 
    502     GraphicsLayer::setReplicatedLayer(layer);
    503     noteLayerPropertyChanged(ReplicatedLayerChanged);
    504 }
    505 
    506 void GraphicsLayerCA::setReplicatedByLayer(GraphicsLayer* layer)
    507 {
    508     if (layer == m_replicaLayer)
    509         return;
    510 
    511     GraphicsLayer::setReplicatedByLayer(layer);
    512     noteSublayersChanged();
    513     noteLayerPropertyChanged(ReplicatedLayerChanged);
    514 }
    515 
    516 void GraphicsLayerCA::setPosition(const FloatPoint& point)
    517 {
    518     if (point == m_position)
    519         return;
    520 
    521     GraphicsLayer::setPosition(point);
    522     noteLayerPropertyChanged(PositionChanged);
    523 }
    524 
    525 void GraphicsLayerCA::setAnchorPoint(const FloatPoint3D& point)
    526 {
    527     if (point == m_anchorPoint)
    528         return;
    529 
    530     GraphicsLayer::setAnchorPoint(point);
    531     noteLayerPropertyChanged(AnchorPointChanged);
    532 }
    533 
    534 void GraphicsLayerCA::setSize(const FloatSize& size)
    535 {
    536     if (size == m_size)
    537         return;
    538 
    539     GraphicsLayer::setSize(size);
    540     noteLayerPropertyChanged(SizeChanged);
    541 }
    542 
    543 void GraphicsLayerCA::setTransform(const TransformationMatrix& t)
    544 {
    545     if (t == m_transform)
    546         return;
    547 
    548     GraphicsLayer::setTransform(t);
    549     noteLayerPropertyChanged(TransformChanged);
    550 }
    551 
    552 void GraphicsLayerCA::setChildrenTransform(const TransformationMatrix& t)
    553 {
    554     if (t == m_childrenTransform)
    555         return;
    556 
    557     GraphicsLayer::setChildrenTransform(t);
    558     noteLayerPropertyChanged(ChildrenTransformChanged);
    559 }
    560 
    561 void 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 
    585 void 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 
    596 void GraphicsLayerCA::setPreserves3D(bool preserves3D)
    597 {
    598     if (preserves3D == m_preserves3D)
    599         return;
    600 
    601     GraphicsLayer::setPreserves3D(preserves3D);
    602     noteLayerPropertyChanged(Preserves3DChanged);
    603 }
    604 
    605 void GraphicsLayerCA::setMasksToBounds(bool masksToBounds)
    606 {
    607     if (masksToBounds == m_masksToBounds)
    608         return;
    609 
    610     GraphicsLayer::setMasksToBounds(masksToBounds);
    611     noteLayerPropertyChanged(MasksToBoundsChanged);
    612 }
    613 
    614 void GraphicsLayerCA::setDrawsContent(bool drawsContent)
    615 {
    616     if (drawsContent == m_drawsContent)
    617         return;
    618 
    619     GraphicsLayer::setDrawsContent(drawsContent);
    620     noteLayerPropertyChanged(DrawsContentChanged);
    621 }
    622 
    623 void 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 
    634 void GraphicsLayerCA::clearBackgroundColor()
    635 {
    636     if (!m_backgroundColorSet)
    637         return;
    638 
    639     GraphicsLayer::clearBackgroundColor();
    640     m_contentsLayerHasBackgroundColor = false;
    641     noteLayerPropertyChanged(BackgroundColorChanged);
    642 }
    643 
    644 void GraphicsLayerCA::setContentsOpaque(bool opaque)
    645 {
    646     if (m_contentsOpaque == opaque)
    647         return;
    648 
    649     GraphicsLayer::setContentsOpaque(opaque);
    650     noteLayerPropertyChanged(ContentsOpaqueChanged);
    651 }
    652 
    653 void GraphicsLayerCA::setBackfaceVisibility(bool visible)
    654 {
    655     if (m_backfaceVisibility == visible)
    656         return;
    657 
    658     GraphicsLayer::setBackfaceVisibility(visible);
    659     noteLayerPropertyChanged(BackfaceVisibilityChanged);
    660 }
    661 
    662 void 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 
    673 void 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 
    681 void 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 
    701 void GraphicsLayerCA::setContentsRect(const IntRect& rect)
    702 {
    703     if (rect == m_contentsRect)
    704         return;
    705 
    706     GraphicsLayer::setContentsRect(rect);
    707     noteLayerPropertyChanged(ContentsRectChanged);
    708 }
    709 
    710 bool 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 
    734 void 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 
    743 void 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 
    752 void 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 
    769 void 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 
    795 void 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 
    807 void 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 
    829 void 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 
    858 void GraphicsLayerCA::syncCompositingState()
    859 {
    860     recursiveCommitChanges();
    861 }
    862 
    863 void 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 
    886 void 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 
    965 void 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 
    979 void 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 
    994 void 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 
   1041 void 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 
   1064 void 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 
   1108 void 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 
   1129 void 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 
   1149 void 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 
   1164 void 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 
   1179 void 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 
   1192 void 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 
   1205 void GraphicsLayerCA::updateStructuralLayer()
   1206 {
   1207     ensureStructuralLayer(structuralLayerPurpose());
   1208 }
   1209 
   1210 void 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 
   1294 GraphicsLayerCA::StructuralLayerPurpose GraphicsLayerCA::structuralLayerPurpose() const
   1295 {
   1296     if (preserves3D())
   1297         return StructuralLayerForPreserves3D;
   1298 
   1299     if (isReplicated())
   1300         return StructuralLayerForReplicaFlattening;
   1301 
   1302     return NoStructuralLayer;
   1303 }
   1304 
   1305 void 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 
   1319 void 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 
   1331 void 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 
   1366 void 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)
   1376 void 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 
   1387 void 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 
   1412 void 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 
   1429 void 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 
   1447 void 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.
   1463 GraphicsLayerCA::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 
   1483 CALayer *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 
   1501 void 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 
   1572 void 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>
   1597 static 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 
   1611 bool 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 
   1637 static 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 
   1653 void 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)
   1702 void 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 
   1737 void 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 
   1748 bool 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 
   1781 bool 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 
   1836 CABasicAnimation* 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 
   1843 CAKeyframeAnimation* 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 
   1850 void 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 
   1872 CAMediaTimingFunction* 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 
   1883 bool 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 
   1912 bool 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 
   1947 bool 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 
   1992 bool 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 
   2036 void 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 
   2053 void 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 
   2069 CALayer* GraphicsLayerCA::hostLayerForSublayers() const
   2070 {
   2071     return m_structuralLayer.get() ? m_structuralLayer.get() : m_layer.get();
   2072 }
   2073 
   2074 CALayer* GraphicsLayerCA::layerForSuperlayer() const
   2075 {
   2076     return m_structuralLayer ? m_structuralLayer.get() : m_layer.get();
   2077 }
   2078 
   2079 CALayer* GraphicsLayerCA::animatedLayer(AnimatedPropertyID property) const
   2080 {
   2081     return (property == AnimatedPropertyBackgroundColor) ? m_contentsLayer.get() : primaryLayer();
   2082 }
   2083 
   2084 GraphicsLayerCA::LayerMap* GraphicsLayerCA::animatedLayerClones(AnimatedPropertyID property) const
   2085 {
   2086     return (property == AnimatedPropertyBackgroundColor) ? m_contentsLayerClones.get() : primaryLayerClones();
   2087 }
   2088 
   2089 PlatformLayer* GraphicsLayerCA::platformLayer() const
   2090 {
   2091     return primaryLayer();
   2092 }
   2093 
   2094 void 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 
   2106 void 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 
   2121 bool 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 
   2130 void 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 
   2200 GraphicsLayer::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 
   2212 void 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 
   2225 void 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 
   2247 CALayer *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 
   2272 void 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 
   2291 void GraphicsLayerCA::removeCloneLayers()
   2292 {
   2293     m_layerClones = 0;
   2294     m_structuralLayerClones = 0;
   2295     m_contentsLayerClones = 0;
   2296 }
   2297 
   2298 FloatPoint 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 
   2309 void 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 
   2321 CALayer *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 
   2413 CALayer *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 
   2452 void 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 
   2475 void 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 
   2498 void GraphicsLayerCA::noteSublayersChanged()
   2499 {
   2500     noteLayerPropertyChanged(ChildrenChanged);
   2501     propagateLayerChangeToReplicas();
   2502 }
   2503 
   2504 void 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)
   2513 void 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