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