ed04972882919d1d54e753ff0faff02f12c7af40
[WebKit-https.git] / Source / WebCore / platform / graphics / ca / mac / PlatformCALayerMac.mm
1 /*
2  * Copyright (C) 2010 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 #include "config.h"
27
28 #if USE(ACCELERATED_COMPOSITING)
29
30 #import "PlatformCALayer.h"
31
32 #import "BlockExceptions.h"
33 #import "FloatConversion.h"
34 #import "GraphicsContext.h"
35 #import "GraphicsLayerCA.h"
36 #import "WebLayer.h"
37 #import "WebTiledLayer.h"
38 #import <objc/objc-auto.h>
39 #import <objc/objc-runtime.h>
40 #import <QuartzCore/QuartzCore.h>
41 #import <wtf/CurrentTime.h>
42 #import <wtf/UnusedParam.h>
43
44 #define HAVE_MODERN_QUARTZCORE (!defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD))
45
46 using namespace WebCore;
47
48 // This value must be the same as in PlatformCAAnimationMac.mm
49 static NSString * const WKNonZeroBeginTimeFlag = @"WKPlatformCAAnimationNonZeroBeginTimeFlag";
50
51 static double mediaTimeToCurrentTime(CFTimeInterval t)
52 {
53     return WTF::currentTime() + t - CACurrentMediaTime();
54 }
55
56 // Delegate for animationDidStart callback
57 @interface WebAnimationDelegate : NSObject {
58     PlatformCALayer* m_owner;
59 }
60
61 - (void)animationDidStart:(CAAnimation *)anim;
62 - (void)setOwner:(PlatformCALayer*)owner;
63
64 @end
65
66 @implementation WebAnimationDelegate
67
68 - (void)animationDidStart:(CAAnimation *)animation
69 {
70     // hasNonZeroBeginTime is stored in a key in the animation
71     bool hasNonZeroBeginTime = [[animation valueForKey:WKNonZeroBeginTimeFlag] boolValue];
72     CFTimeInterval startTime;
73     
74     if (hasNonZeroBeginTime) {
75         // We don't know what time CA used to commit the animation, so just use the current time
76         // (even though this will be slightly off).
77         startTime = mediaTimeToCurrentTime(CACurrentMediaTime());
78     } else
79         startTime = mediaTimeToCurrentTime([animation beginTime]);
80
81     if (m_owner)
82         m_owner->animationStarted(startTime);
83 }
84
85 - (void)setOwner:(PlatformCALayer*)owner
86 {
87     m_owner = owner;
88 }
89
90 @end
91
92 @interface CALayer(Private)
93 - (void)setContentsChanged;
94 #if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
95 - (void)setAcceleratesDrawing:(BOOL)flag;
96 - (BOOL)acceleratesDrawing;
97 #endif
98 @end
99
100 static NSString * const platformCALayerPointer = @"WKPlatformCALayer";
101
102 bool PlatformCALayer::isValueFunctionSupported()
103 {
104     static bool sHaveValueFunction = [CAPropertyAnimation instancesRespondToSelector:@selector(setValueFunction:)];
105     return sHaveValueFunction;
106 }
107
108 void PlatformCALayer::setOwner(PlatformCALayerClient* owner)
109 {
110     m_owner = owner;
111     
112     // Change the delegate's owner if needed
113     if (m_delegate)
114         [static_cast<WebAnimationDelegate*>(m_delegate.get()) setOwner:this];        
115 }
116
117 static NSDictionary* nullActionsDictionary()
118 {
119     NSNull* nullValue = [NSNull null];
120     NSDictionary* actions = [NSDictionary dictionaryWithObjectsAndKeys:
121                              nullValue, @"anchorPoint",
122                              nullValue, @"bounds",
123                              nullValue, @"contents",
124                              nullValue, @"contentsRect",
125                              nullValue, @"opacity",
126                              nullValue, @"position",
127                              nullValue, @"shadowColor",
128                              nullValue, @"sublayerTransform",
129                              nullValue, @"sublayers",
130                              nullValue, @"transform",
131                              nullValue, @"zPosition",
132                              nil];
133     return actions;
134 }
135
136 #if HAVE_MODERN_QUARTZCORE
137 static NSString* toCAFilterType(PlatformCALayer::FilterType type)
138 {
139     switch (type) {
140     case PlatformCALayer::Linear: return kCAFilterLinear;
141     case PlatformCALayer::Nearest: return kCAFilterNearest;
142     case PlatformCALayer::Trilinear: return kCAFilterTrilinear;
143     default: return 0;
144     }
145 }
146 #endif
147
148 PassRefPtr<PlatformCALayer> PlatformCALayer::create(LayerType layerType, PlatformCALayerClient* owner)
149 {
150     return adoptRef(new PlatformCALayer(layerType, 0, owner));
151 }
152
153 PassRefPtr<PlatformCALayer> PlatformCALayer::create(void* platformLayer, PlatformCALayerClient* owner)
154 {
155     return adoptRef(new PlatformCALayer(LayerTypeCustom, static_cast<PlatformLayer*>(platformLayer), owner));
156 }
157
158 PlatformCALayer::PlatformCALayer(LayerType layerType, PlatformLayer* layer, PlatformCALayerClient* owner)
159     : m_owner(owner)
160 {
161     BEGIN_BLOCK_OBJC_EXCEPTIONS
162     if (layer) {
163         m_layerType = LayerTypeCustom;
164         m_layer = layer;
165     } else {
166         m_layerType = layerType;
167     
168         Class layerClass = Nil;
169         switch(layerType) {
170             case LayerTypeLayer:
171             case LayerTypeRootLayer:
172                 layerClass = [CALayer class];
173                 break;
174             case LayerTypeWebLayer:
175                 layerClass = [WebLayer class];
176                 break;
177             case LayerTypeTransformLayer:
178                 layerClass = NSClassFromString(@"CATransformLayer");
179                 break;
180             case LayerTypeWebTiledLayer:
181                 layerClass = [WebTiledLayer class];
182                 break;
183             case LayerTypeCustom:
184                 break;
185         }
186
187         if (layerClass)
188             m_layer.adoptNS([[layerClass alloc] init]);
189     }
190     
191     // Save a pointer to 'this' in the CALayer
192     [m_layer.get() setValue:[NSValue valueWithPointer:this] forKey:platformCALayerPointer];
193     
194     // Clear all the implicit animations on the CALayer
195     [m_layer.get() setStyle:[NSDictionary dictionaryWithObject:nullActionsDictionary() forKey:@"actions"]];
196     
197     // If this is a TiledLayer, set some initial values
198     if (m_layerType == LayerTypeWebTiledLayer) {
199         WebTiledLayer* tiledLayer = static_cast<WebTiledLayer*>(m_layer.get());
200         [tiledLayer setTileSize:CGSizeMake(GraphicsLayerCA::kTiledLayerTileSize, GraphicsLayerCA::kTiledLayerTileSize)];
201         [tiledLayer setLevelsOfDetail:1];
202         [tiledLayer setLevelsOfDetailBias:0];
203         [tiledLayer setContentsGravity:@"bottomLeft"];
204     }
205     
206     END_BLOCK_OBJC_EXCEPTIONS
207 }
208
209 PlatformCALayer::~PlatformCALayer()
210 {
211     [m_layer.get() setValue:nil forKey:platformCALayerPointer];
212
213     // Clear the owner, which also clears it in the delegate to prevent attempts 
214     // to use the GraphicsLayerCA after it has been destroyed.
215     setOwner(0);
216     
217     // Remove the owner pointer from the delegate in case there is a pending animationStarted event.
218     [static_cast<WebAnimationDelegate*>(m_delegate.get()) setOwner:nil];        
219 }
220
221 PlatformCALayer* PlatformCALayer::platformCALayer(void* platformLayer)
222 {
223     if (!platformLayer)
224         return 0;
225         
226     // Pointer to PlatformCALayer is kept in a key of the CALayer
227     PlatformCALayer* platformCALayer = nil;
228     BEGIN_BLOCK_OBJC_EXCEPTIONS
229     platformCALayer = static_cast<PlatformCALayer*>([[static_cast<CALayer*>(platformLayer) valueForKey:platformCALayerPointer] pointerValue]);
230     END_BLOCK_OBJC_EXCEPTIONS
231     return platformCALayer;
232 }
233
234 PlatformLayer* PlatformCALayer::platformLayer() const
235 {
236     return m_layer.get();
237 }
238
239 void PlatformCALayer::setNeedsDisplay(const FloatRect* dirtyRect)
240 {
241     BEGIN_BLOCK_OBJC_EXCEPTIONS
242     if (dirtyRect)
243         [m_layer.get() setNeedsDisplayInRect:*dirtyRect];
244     else
245         [m_layer.get() setNeedsDisplay];
246     END_BLOCK_OBJC_EXCEPTIONS
247 }
248     
249 void PlatformCALayer::setContentsChanged()
250 {
251     BEGIN_BLOCK_OBJC_EXCEPTIONS
252     [m_layer.get() setContentsChanged];
253     END_BLOCK_OBJC_EXCEPTIONS
254 }
255
256 PlatformCALayer* PlatformCALayer::superlayer() const
257 {
258     return platformCALayer([m_layer.get() superlayer]);
259 }
260
261 void PlatformCALayer::removeFromSuperlayer()
262 {
263     BEGIN_BLOCK_OBJC_EXCEPTIONS
264     [m_layer.get() removeFromSuperlayer];
265     END_BLOCK_OBJC_EXCEPTIONS
266 }
267
268 void PlatformCALayer::setSublayers(const PlatformCALayerList& list)
269 {
270     // Short circuiting here not only avoids the allocation of sublayers, but avoids <rdar://problem/7390716> (see below)
271     if (list.size() == 0) {
272         removeAllSublayers();
273         return;
274     }
275     
276     BEGIN_BLOCK_OBJC_EXCEPTIONS
277     NSMutableArray* sublayers = [[NSMutableArray alloc] init];
278     for (size_t i = 0; i < list.size(); ++i)
279         [sublayers addObject:list[i]->m_layer.get()];
280         
281     [m_layer.get() setSublayers:sublayers];
282     [sublayers release];
283     END_BLOCK_OBJC_EXCEPTIONS
284 }
285
286 void PlatformCALayer::removeAllSublayers()
287 {
288     // Workaround for <rdar://problem/7390716>: -[CALayer setSublayers:] crashes if sublayers is an empty array, or nil, under GC.
289     BEGIN_BLOCK_OBJC_EXCEPTIONS
290     if (objc_collectingEnabled())
291         while ([[m_layer.get() sublayers] count])
292             [[[m_layer.get() sublayers] objectAtIndex:0] removeFromSuperlayer];
293     else
294         [m_layer.get() setSublayers:nil];
295     END_BLOCK_OBJC_EXCEPTIONS
296 }
297
298 void PlatformCALayer::appendSublayer(PlatformCALayer* layer)
299 {
300     BEGIN_BLOCK_OBJC_EXCEPTIONS
301     [m_layer.get() addSublayer:layer->m_layer.get()];
302     END_BLOCK_OBJC_EXCEPTIONS
303 }
304
305 void PlatformCALayer::insertSublayer(PlatformCALayer* layer, size_t index)
306 {
307     BEGIN_BLOCK_OBJC_EXCEPTIONS
308     [m_layer.get() insertSublayer:layer->m_layer.get() atIndex:index];
309     END_BLOCK_OBJC_EXCEPTIONS
310 }
311
312 void PlatformCALayer::replaceSublayer(PlatformCALayer* reference, PlatformCALayer* layer)
313 {
314     BEGIN_BLOCK_OBJC_EXCEPTIONS
315     [m_layer.get() replaceSublayer:reference->m_layer.get() with:layer->m_layer.get()];
316     END_BLOCK_OBJC_EXCEPTIONS
317 }
318
319 size_t PlatformCALayer::sublayerCount() const
320 {
321     return [[m_layer.get() sublayers] count];
322 }
323
324 void PlatformCALayer::adoptSublayers(PlatformCALayer* source)
325 {
326     // Workaround for <rdar://problem/7390716>: -[CALayer setSublayers:] crashes if sublayers is an empty array, or nil, under GC.
327     NSArray* sublayers = [source->m_layer.get() sublayers];
328     
329     if (objc_collectingEnabled() && ![sublayers count]) {
330         BEGIN_BLOCK_OBJC_EXCEPTIONS
331         while ([[m_layer.get() sublayers] count])
332             [[[m_layer.get() sublayers] objectAtIndex:0] removeFromSuperlayer];
333         END_BLOCK_OBJC_EXCEPTIONS
334         return;
335     }
336     
337     BEGIN_BLOCK_OBJC_EXCEPTIONS
338     [m_layer.get() setSublayers:sublayers];
339     END_BLOCK_OBJC_EXCEPTIONS
340 }
341
342 void PlatformCALayer::addAnimationForKey(const String& key, PlatformCAAnimation* animation)
343 {
344     // Add the delegate
345     if (!m_delegate) {
346         WebAnimationDelegate* webAnimationDelegate = [[WebAnimationDelegate alloc] init];
347         m_delegate.adoptNS(webAnimationDelegate);
348         [webAnimationDelegate setOwner:this];
349     }
350     
351     CAPropertyAnimation* propertyAnimation = static_cast<CAPropertyAnimation*>(animation->platformAnimation());
352
353     if (![propertyAnimation delegate])
354         [propertyAnimation setDelegate:static_cast<id>(m_delegate.get())];
355      
356     BEGIN_BLOCK_OBJC_EXCEPTIONS
357     [m_layer.get() addAnimation:animation->m_animation.get() forKey:key];
358     END_BLOCK_OBJC_EXCEPTIONS
359 }
360
361 void PlatformCALayer::removeAnimationForKey(const String& key)
362 {
363     BEGIN_BLOCK_OBJC_EXCEPTIONS
364     [m_layer.get() removeAnimationForKey:key];
365     END_BLOCK_OBJC_EXCEPTIONS
366 }
367
368 PassRefPtr<PlatformCAAnimation> PlatformCALayer::animationForKey(const String& key)
369 {
370     CAPropertyAnimation* propertyAnimation = static_cast<CAPropertyAnimation*>([m_layer.get() animationForKey:key]);
371     if (!propertyAnimation)
372         return 0;
373     return PlatformCAAnimation::create(propertyAnimation);
374 }
375
376 PlatformCALayer* PlatformCALayer::mask() const
377 {
378     return platformCALayer([m_layer.get() mask]);
379 }
380
381 void PlatformCALayer::setMask(PlatformCALayer* layer)
382 {
383     BEGIN_BLOCK_OBJC_EXCEPTIONS
384     [m_layer.get() setMask:layer ? layer->platformLayer() : 0];
385     END_BLOCK_OBJC_EXCEPTIONS
386 }
387
388 bool PlatformCALayer::isOpaque() const
389 {
390     return [m_layer.get() isOpaque];
391 }
392
393 void PlatformCALayer::setOpaque(bool value)
394 {
395     BEGIN_BLOCK_OBJC_EXCEPTIONS
396     [m_layer.get() setOpaque:value];
397     END_BLOCK_OBJC_EXCEPTIONS
398 }
399
400 FloatRect PlatformCALayer::bounds() const
401 {
402     return [m_layer.get() bounds];
403 }
404
405 void PlatformCALayer::setBounds(const FloatRect& value)
406 {
407     BEGIN_BLOCK_OBJC_EXCEPTIONS
408     [m_layer.get() setBounds:value];
409     END_BLOCK_OBJC_EXCEPTIONS
410 }
411
412 FloatPoint3D PlatformCALayer::position() const
413 {
414     CGPoint point = [m_layer.get() position];
415     return FloatPoint3D(point.x, point.y, [m_layer.get() zPosition]);
416 }
417
418 void PlatformCALayer::setPosition(const FloatPoint3D& value)
419 {
420     BEGIN_BLOCK_OBJC_EXCEPTIONS
421     [m_layer.get() setPosition:CGPointMake(value.x(), value.y())];
422     [m_layer.get() setZPosition:value.z()];
423     END_BLOCK_OBJC_EXCEPTIONS
424 }
425
426 FloatPoint3D PlatformCALayer::anchorPoint() const
427 {
428     CGPoint point = [m_layer.get() anchorPoint];
429     float z = 0;
430 #if HAVE_MODERN_QUARTZCORE
431     z = [m_layer.get() anchorPointZ];
432 #endif
433     return FloatPoint3D(point.x, point.y, z);
434 }
435
436 void PlatformCALayer::setAnchorPoint(const FloatPoint3D& value)
437 {
438     BEGIN_BLOCK_OBJC_EXCEPTIONS
439     [m_layer.get() setAnchorPoint:CGPointMake(value.x(), value.y())];
440 #if HAVE_MODERN_QUARTZCORE
441     [m_layer.get() setAnchorPointZ:value.z()];
442 #endif
443     END_BLOCK_OBJC_EXCEPTIONS
444 }
445
446 TransformationMatrix PlatformCALayer::transform() const
447 {
448     return [m_layer.get() transform];
449 }
450
451 void PlatformCALayer::setTransform(const TransformationMatrix& value)
452 {
453     BEGIN_BLOCK_OBJC_EXCEPTIONS
454     [m_layer.get() setTransform:value];
455     END_BLOCK_OBJC_EXCEPTIONS
456 }
457
458 TransformationMatrix PlatformCALayer::sublayerTransform() const
459 {
460     return [m_layer.get() sublayerTransform];
461 }
462
463 void PlatformCALayer::setSublayerTransform(const TransformationMatrix& value)
464 {
465     BEGIN_BLOCK_OBJC_EXCEPTIONS
466     [m_layer.get() setSublayerTransform:value];
467     END_BLOCK_OBJC_EXCEPTIONS
468 }
469
470 TransformationMatrix PlatformCALayer::contentsTransform() const
471 {
472 #if !HAVE_MODERN_QUARTZCORE
473     if (m_layerType != LayerTypeWebLayer)
474         return TransformationMatrix();
475         
476     return [static_cast<WebLayer*>(m_layer.get()) contentsTransform];
477 #else
478     return TransformationMatrix();
479 #endif
480 }
481
482 void PlatformCALayer::setContentsTransform(const TransformationMatrix& value)
483 {
484 #if !HAVE_MODERN_QUARTZCORE
485     if (m_layerType != LayerTypeWebLayer)
486         return;
487
488     BEGIN_BLOCK_OBJC_EXCEPTIONS
489     [m_layer.get() setContentsTransform:value];
490     END_BLOCK_OBJC_EXCEPTIONS
491 #else
492     UNUSED_PARAM(value);
493 #endif
494 }
495
496 bool PlatformCALayer::isHidden() const
497 {
498     return [m_layer.get() isHidden];
499 }
500
501 void PlatformCALayer::setHidden(bool value)
502 {
503     BEGIN_BLOCK_OBJC_EXCEPTIONS
504     [m_layer.get() setHidden:value];
505     END_BLOCK_OBJC_EXCEPTIONS
506 }
507
508 bool PlatformCALayer::isGeometryFlipped() const
509 {
510 #if HAVE_MODERN_QUARTZCORE
511     return [m_layer.get() isGeometryFlipped];
512 #else
513     return false;
514 #endif
515 }
516
517 void PlatformCALayer::setGeometryFlipped(bool value)
518 {
519 #if HAVE_MODERN_QUARTZCORE
520     BEGIN_BLOCK_OBJC_EXCEPTIONS
521     [m_layer.get() setGeometryFlipped:value];
522     END_BLOCK_OBJC_EXCEPTIONS
523 #else
524     UNUSED_PARAM(value);
525 #endif
526 }
527
528 bool PlatformCALayer::isDoubleSided() const
529 {
530     return [m_layer.get() isDoubleSided];
531 }
532
533 void PlatformCALayer::setDoubleSided(bool value)
534 {
535     BEGIN_BLOCK_OBJC_EXCEPTIONS
536     [m_layer.get() setDoubleSided:value];
537     END_BLOCK_OBJC_EXCEPTIONS
538 }
539
540 bool PlatformCALayer::masksToBounds() const
541 {
542     return [m_layer.get() masksToBounds];
543 }
544
545 void PlatformCALayer::setMasksToBounds(bool value)
546 {
547     BEGIN_BLOCK_OBJC_EXCEPTIONS
548     [m_layer.get() setMasksToBounds:value];
549     END_BLOCK_OBJC_EXCEPTIONS
550 }
551
552 bool PlatformCALayer::acceleratesDrawing() const
553 {
554 #if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
555     return [m_layer.get() acceleratesDrawing];
556 #else
557     return false;
558 #endif
559 }
560
561 void PlatformCALayer::setAcceleratesDrawing(bool acceleratesDrawing)
562 {
563 #if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
564     BEGIN_BLOCK_OBJC_EXCEPTIONS
565     [m_layer.get() setAcceleratesDrawing:acceleratesDrawing];
566     END_BLOCK_OBJC_EXCEPTIONS
567 #else
568     UNUSED_PARAM(acceleratesDrawing);
569 #endif
570 }
571
572 CFTypeRef PlatformCALayer::contents() const
573 {
574     return [m_layer.get() contents];
575 }
576
577 void PlatformCALayer::setContents(CFTypeRef value)
578 {
579     BEGIN_BLOCK_OBJC_EXCEPTIONS
580     [m_layer.get() setContents:static_cast<id>(const_cast<void*>(value))];
581     END_BLOCK_OBJC_EXCEPTIONS
582 }
583
584 FloatRect PlatformCALayer::contentsRect() const
585 {
586     return [m_layer.get() contentsRect];
587 }
588
589 void PlatformCALayer::setContentsRect(const FloatRect& value)
590 {
591     BEGIN_BLOCK_OBJC_EXCEPTIONS
592     [m_layer.get() setContentsRect:value];
593     END_BLOCK_OBJC_EXCEPTIONS
594 }
595
596 void PlatformCALayer::setMinificationFilter(FilterType value)
597 {
598 #if HAVE_MODERN_QUARTZCORE
599     BEGIN_BLOCK_OBJC_EXCEPTIONS
600     [m_layer.get() setMinificationFilter:toCAFilterType(value)];
601     END_BLOCK_OBJC_EXCEPTIONS
602 #else
603     UNUSED_PARAM(value);
604 #endif
605 }
606
607 void PlatformCALayer::setMagnificationFilter(FilterType value)
608 {
609 #if HAVE_MODERN_QUARTZCORE
610     BEGIN_BLOCK_OBJC_EXCEPTIONS
611     [m_layer.get() setMagnificationFilter:toCAFilterType(value)];
612     END_BLOCK_OBJC_EXCEPTIONS
613 #else
614     UNUSED_PARAM(value);
615 #endif
616 }
617
618 Color PlatformCALayer::backgroundColor() const
619 {
620     return [m_layer.get() backgroundColor];
621 }
622
623 void PlatformCALayer::setBackgroundColor(const Color& value)
624 {
625     CGFloat components[4];
626     value.getRGBA(components[0], components[1], components[2], components[3]);
627
628     RetainPtr<CGColorSpaceRef> colorSpace(AdoptCF, CGColorSpaceCreateDeviceRGB());
629     RetainPtr<CGColorRef> color(AdoptCF, CGColorCreate(colorSpace.get(), components));
630
631     BEGIN_BLOCK_OBJC_EXCEPTIONS
632     [m_layer.get() setBackgroundColor:color.get()];
633     END_BLOCK_OBJC_EXCEPTIONS
634 }
635
636 float PlatformCALayer::borderWidth() const
637 {
638     return [m_layer.get() borderWidth];
639 }
640
641 void PlatformCALayer::setBorderWidth(float value)
642 {
643     BEGIN_BLOCK_OBJC_EXCEPTIONS
644     [m_layer.get() setBorderWidth:value];
645     END_BLOCK_OBJC_EXCEPTIONS
646 }
647
648 Color PlatformCALayer::borderColor() const
649 {
650     return [m_layer.get() borderColor];
651 }
652
653 void PlatformCALayer::setBorderColor(const Color& value)
654 {
655     CGFloat components[4];
656     value.getRGBA(components[0], components[1], components[2], components[3]);
657
658     RetainPtr<CGColorSpaceRef> colorSpace(AdoptCF, CGColorSpaceCreateDeviceRGB());
659     RetainPtr<CGColorRef> color(AdoptCF, CGColorCreate(colorSpace.get(), components));
660
661     BEGIN_BLOCK_OBJC_EXCEPTIONS
662     [m_layer.get() setBorderColor:color.get()];
663     END_BLOCK_OBJC_EXCEPTIONS
664 }
665
666 float PlatformCALayer::opacity() const
667 {
668     return [m_layer.get() opacity];
669 }
670
671 void PlatformCALayer::setOpacity(float value)
672 {
673     BEGIN_BLOCK_OBJC_EXCEPTIONS
674     [m_layer.get() setOpacity:value];
675     END_BLOCK_OBJC_EXCEPTIONS
676 }
677
678 String PlatformCALayer::name() const
679 {
680     return [m_layer.get() name];
681 }
682
683 void PlatformCALayer::setName(const String& value)
684 {
685     BEGIN_BLOCK_OBJC_EXCEPTIONS
686     [m_layer.get() setName:value];
687     END_BLOCK_OBJC_EXCEPTIONS
688 }
689
690 FloatRect PlatformCALayer::frame() const
691 {
692     return [m_layer.get() frame];
693 }
694
695 void PlatformCALayer::setFrame(const FloatRect& value)
696 {
697     BEGIN_BLOCK_OBJC_EXCEPTIONS
698     [m_layer.get() setFrame:value];
699     END_BLOCK_OBJC_EXCEPTIONS
700 }
701
702 float PlatformCALayer::speed() const
703 {
704     return [m_layer.get() speed];
705 }
706
707 void PlatformCALayer::setSpeed(float value)
708 {
709     BEGIN_BLOCK_OBJC_EXCEPTIONS
710     [m_layer.get() setSpeed:value];
711     END_BLOCK_OBJC_EXCEPTIONS
712 }
713
714 CFTimeInterval PlatformCALayer::timeOffset() const
715 {
716     return [m_layer.get() timeOffset];
717 }
718
719 void PlatformCALayer::setTimeOffset(CFTimeInterval value)
720 {
721     BEGIN_BLOCK_OBJC_EXCEPTIONS
722     [m_layer.get() setTimeOffset:value];
723     END_BLOCK_OBJC_EXCEPTIONS
724 }
725
726 float PlatformCALayer::contentsScale() const
727 {
728 #if !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
729     return [m_layer.get() contentsScale];
730 #else
731     return 1;
732 #endif
733 }
734
735 void PlatformCALayer::setContentsScale(float value)
736 {
737 #if !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
738     BEGIN_BLOCK_OBJC_EXCEPTIONS
739     [m_layer.get() setContentsScale:value];
740     END_BLOCK_OBJC_EXCEPTIONS
741 #endif
742 }
743
744 #endif // USE(ACCELERATED_COMPOSITING)